source dump of claude code
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 112 lines 3.3 kB view raw
1import axios from 'axios' 2import { readFile, stat } from 'fs/promises' 3import type { Message } from '../../types/message.js' 4import { checkAndRefreshOAuthTokenIfNeeded } from '../../utils/auth.js' 5import { logForDebugging } from '../../utils/debug.js' 6import { errorMessage } from '../../utils/errors.js' 7import { getAuthHeaders, getUserAgent } from '../../utils/http.js' 8import { normalizeMessagesForAPI } from '../../utils/messages.js' 9import { 10 extractAgentIdsFromMessages, 11 getTranscriptPath, 12 loadSubagentTranscripts, 13 MAX_TRANSCRIPT_READ_BYTES, 14} from '../../utils/sessionStorage.js' 15import { jsonStringify } from '../../utils/slowOperations.js' 16import { redactSensitiveInfo } from '../Feedback.js' 17 18type TranscriptShareResult = { 19 success: boolean 20 transcriptId?: string 21} 22 23export type TranscriptShareTrigger = 24 | 'bad_feedback_survey' 25 | 'good_feedback_survey' 26 | 'frustration' 27 | 'memory_survey' 28 29export async function submitTranscriptShare( 30 messages: Message[], 31 trigger: TranscriptShareTrigger, 32 appearanceId: string, 33): Promise<TranscriptShareResult> { 34 try { 35 logForDebugging('Collecting transcript for sharing', { level: 'info' }) 36 37 const transcript = normalizeMessagesForAPI(messages) 38 39 // Collect subagent transcripts 40 const agentIds = extractAgentIdsFromMessages(messages) 41 const subagentTranscripts = await loadSubagentTranscripts(agentIds) 42 43 // Read raw JSONL transcript (with size guard to prevent OOM) 44 let rawTranscriptJsonl: string | undefined 45 try { 46 const transcriptPath = getTranscriptPath() 47 const { size } = await stat(transcriptPath) 48 if (size <= MAX_TRANSCRIPT_READ_BYTES) { 49 rawTranscriptJsonl = await readFile(transcriptPath, 'utf-8') 50 } else { 51 logForDebugging( 52 `Skipping raw transcript read: file too large (${size} bytes)`, 53 { level: 'warn' }, 54 ) 55 } 56 } catch { 57 // File may not exist 58 } 59 60 const data = { 61 trigger, 62 version: MACRO.VERSION, 63 platform: process.platform, 64 transcript, 65 subagentTranscripts: 66 Object.keys(subagentTranscripts).length > 0 67 ? subagentTranscripts 68 : undefined, 69 rawTranscriptJsonl, 70 } 71 72 const content = redactSensitiveInfo(jsonStringify(data)) 73 74 await checkAndRefreshOAuthTokenIfNeeded() 75 76 const authResult = getAuthHeaders() 77 if (authResult.error) { 78 return { success: false } 79 } 80 81 const headers: Record<string, string> = { 82 'Content-Type': 'application/json', 83 'User-Agent': getUserAgent(), 84 ...authResult.headers, 85 } 86 87 const response = await axios.post( 88 'https://api.anthropic.com/api/claude_code_shared_session_transcripts', 89 { content, appearance_id: appearanceId }, 90 { 91 headers, 92 timeout: 30000, 93 }, 94 ) 95 96 if (response.status === 200 || response.status === 201) { 97 const result = response.data 98 logForDebugging('Transcript shared successfully', { level: 'info' }) 99 return { 100 success: true, 101 transcriptId: result?.transcript_id, 102 } 103 } 104 105 return { success: false } 106 } catch (err) { 107 logForDebugging(errorMessage(err), { 108 level: 'error', 109 }) 110 return { success: false } 111 } 112}