(transcriptPath: string)
| 13 | * from recall and reference markers in assistant messages. |
| 14 | */ |
| 15 | export async function parseTranscriptForVotes(transcriptPath: string): Promise<TranscriptVoteData> { |
| 16 | const recalledSet = new Set<string>(); |
| 17 | const referencedSet = new Set<string>(); |
| 18 | |
| 19 | try { |
| 20 | const stat = await fs.promises.stat(transcriptPath); |
| 21 | if (stat.size === 0) return { recalledDocIds: [], referencedDocIds: [] }; |
| 22 | } catch { |
| 23 | return { recalledDocIds: [], referencedDocIds: [] }; |
| 24 | } |
| 25 | |
| 26 | const rl = readline.createInterface({ |
| 27 | input: fs.createReadStream(transcriptPath, { encoding: 'utf-8' }), |
| 28 | crlfDelay: Infinity, |
| 29 | }); |
| 30 | |
| 31 | for await (const line of rl) { |
| 32 | const trimmed = line.trim(); |
| 33 | if (!trimmed) continue; |
| 34 | |
| 35 | // Host transcript schemas vary. Keep a raw-line fallback for recalled |
| 36 | // markers that may live outside message.content (for example a plain |
| 37 | // content string or top-level toolUseResult.stdout). Parsed scans below |
| 38 | // additionally handle multiline recall regions after JSON decoding. |
| 39 | extractRecalledDocIdsFromComment(trimmed, recalledSet); |
| 40 | |
| 41 | let entry: Record<string, unknown>; |
| 42 | try { |
| 43 | entry = JSON.parse(trimmed) as Record<string, unknown>; |
| 44 | } catch { |
| 45 | continue; |
| 46 | } |
| 47 | |
| 48 | const message = entry['message'] as Record<string, unknown> | undefined; |
| 49 | if (!message || !Array.isArray(message['content'])) continue; |
| 50 | |
| 51 | for (const block of message['content'] as Array<Record<string, unknown>>) { |
| 52 | // Subagent and Bash recall output lands in a tool_result. Scan its decoded |
| 53 | // content recursively because some hosts represent it as nested blocks. |
| 54 | if (block['type'] === 'tool_result') { |
| 55 | extractRecalledDocIdsFromValue(block['content'], recalledSet); |
| 56 | } |
| 57 | |
| 58 | if (entry['type'] !== 'assistant' || block['type'] !== 'text') continue; |
| 59 | const text = block['text']; |
| 60 | if (typeof text !== 'string') continue; |
| 61 | |
| 62 | extractRecalledDocIds(text, recalledSet); |
| 63 | extractReferencedDocIds(text, referencedSet); |
| 64 | } |
| 65 | } |
| 66 | |
| 67 | return { |
| 68 | recalledDocIds: [...recalledSet], |
| 69 | referencedDocIds: [...referencedSet], |
| 70 | }; |
| 71 | } |
| 72 |
no test coverage detected