From 44adb2631d9f517689de0d6e1395d805e65f7128 Mon Sep 17 00:00:00 2001 From: Jarrod Watts <35651410+jarrodwatts@users.noreply.github.com> Date: Tue, 3 Feb 2026 12:14:27 +1100 Subject: [PATCH] fix(transcript): support task todo updates (#106) --- dist/transcript.d.ts.map | 2 +- dist/transcript.js | 71 +++++++++++++++++++++++- dist/transcript.js.map | 2 +- src/transcript.ts | 78 ++++++++++++++++++++++++++- tests/core.test.js | 6 ++- tests/fixtures/transcript-basic.jsonl | 3 ++ 6 files changed, 156 insertions(+), 6 deletions(-) diff --git a/dist/transcript.d.ts.map b/dist/transcript.d.ts.map index a626ddc..daa06dc 100644 --- a/dist/transcript.d.ts.map +++ b/dist/transcript.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"transcript.d.ts","sourceRoot":"","sources":["../src/transcript.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAmC,MAAM,YAAY,CAAC;AAkBlF,wBAAsB,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAyCrF"} \ No newline at end of file +{"version":3,"file":"transcript.d.ts","sourceRoot":"","sources":["../src/transcript.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAmC,MAAM,YAAY,CAAC;AAkBlF,wBAAsB,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CA0CrF"} \ No newline at end of file diff --git a/dist/transcript.js b/dist/transcript.js index 82e67d6..1d85ecf 100644 --- a/dist/transcript.js +++ b/dist/transcript.js @@ -12,6 +12,7 @@ export async function parseTranscript(transcriptPath) { const toolMap = new Map(); const agentMap = new Map(); let latestTodos = []; + const taskIdToIndex = new Map(); try { const fileStream = fs.createReadStream(transcriptPath); const rl = readline.createInterface({ @@ -23,7 +24,7 @@ export async function parseTranscript(transcriptPath) { continue; try { const entry = JSON.parse(line); - processEntry(entry, toolMap, agentMap, latestTodos, result); + processEntry(entry, toolMap, agentMap, taskIdToIndex, latestTodos, result); } catch { // Skip malformed lines @@ -38,7 +39,7 @@ export async function parseTranscript(transcriptPath) { result.todos = latestTodos; return result; } -function processEntry(entry, toolMap, agentMap, latestTodos, result) { +function processEntry(entry, toolMap, agentMap, taskIdToIndex, latestTodos, result) { const timestamp = entry.timestamp ? new Date(entry.timestamp) : new Date(); if (!result.sessionStart && entry.timestamp) { result.sessionStart = timestamp; @@ -71,9 +72,41 @@ function processEntry(entry, toolMap, agentMap, latestTodos, result) { const input = block.input; if (input?.todos && Array.isArray(input.todos)) { latestTodos.length = 0; + taskIdToIndex.clear(); latestTodos.push(...input.todos); } } + else if (block.name === 'TaskCreate') { + const input = block.input; + const subject = typeof input?.subject === 'string' ? input.subject : ''; + const description = typeof input?.description === 'string' ? input.description : ''; + const content = subject || description || 'Untitled task'; + const status = normalizeTaskStatus(input?.status) ?? 'pending'; + latestTodos.push({ content, status }); + const rawTaskId = input?.taskId; + const taskId = typeof rawTaskId === 'string' || typeof rawTaskId === 'number' + ? String(rawTaskId) + : block.id; + if (taskId) { + taskIdToIndex.set(taskId, latestTodos.length - 1); + } + } + else if (block.name === 'TaskUpdate') { + const input = block.input; + const index = resolveTaskIndex(input?.taskId, taskIdToIndex, latestTodos); + if (index !== null) { + const status = normalizeTaskStatus(input?.status); + if (status) { + latestTodos[index].status = status; + } + const subject = typeof input?.subject === 'string' ? input.subject : ''; + const description = typeof input?.description === 'string' ? input.description : ''; + const content = subject || description; + if (content) { + latestTodos[index].content = content; + } + } + } else { toolMap.set(block.id, toolEntry); } @@ -110,4 +143,38 @@ function extractTarget(toolName, input) { } return undefined; } +function resolveTaskIndex(taskId, taskIdToIndex, latestTodos) { + if (typeof taskId === 'string' || typeof taskId === 'number') { + const key = String(taskId); + const mapped = taskIdToIndex.get(key); + if (typeof mapped === 'number') { + return mapped; + } + if (/^\d+$/.test(key)) { + const numericIndex = Number.parseInt(key, 10) - 1; + if (numericIndex >= 0 && numericIndex < latestTodos.length) { + return numericIndex; + } + } + } + return null; +} +function normalizeTaskStatus(status) { + if (typeof status !== 'string') + return null; + switch (status) { + case 'pending': + case 'not_started': + return 'pending'; + case 'in_progress': + case 'running': + return 'in_progress'; + case 'completed': + case 'complete': + case 'done': + return 'completed'; + default: + return null; + } +} //# sourceMappingURL=transcript.js.map \ No newline at end of file diff --git a/dist/transcript.js.map b/dist/transcript.js.map index fd12862..035ee25 100644 --- a/dist/transcript.js.map +++ b/dist/transcript.js.map @@ -1 +1 @@ -{"version":3,"file":"transcript.js","sourceRoot":"","sources":["../src/transcript.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"transcript.js","sourceRoot":"","sources":["../src/transcript.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/transcript.ts b/src/transcript.ts index 0947c6e..08a0af8 100644 --- a/src/transcript.ts +++ b/src/transcript.ts @@ -32,6 +32,7 @@ export async function parseTranscript(transcriptPath: string): Promise(); const agentMap = new Map(); let latestTodos: TodoItem[] = []; + const taskIdToIndex = new Map(); try { const fileStream = fs.createReadStream(transcriptPath); @@ -45,7 +46,7 @@ export async function parseTranscript(transcriptPath: string): Promise, agentMap: Map, + taskIdToIndex: Map, latestTodos: TodoItem[], result: TranscriptData ): void { @@ -102,8 +104,40 @@ function processEntry( const input = block.input as { todos?: TodoItem[] }; if (input?.todos && Array.isArray(input.todos)) { latestTodos.length = 0; + taskIdToIndex.clear(); latestTodos.push(...input.todos); } + } else if (block.name === 'TaskCreate') { + const input = block.input as Record; + const subject = typeof input?.subject === 'string' ? input.subject : ''; + const description = typeof input?.description === 'string' ? input.description : ''; + const content = subject || description || 'Untitled task'; + const status = normalizeTaskStatus(input?.status) ?? 'pending'; + latestTodos.push({ content, status }); + + const rawTaskId = input?.taskId; + const taskId = typeof rawTaskId === 'string' || typeof rawTaskId === 'number' + ? String(rawTaskId) + : block.id; + if (taskId) { + taskIdToIndex.set(taskId, latestTodos.length - 1); + } + } else if (block.name === 'TaskUpdate') { + const input = block.input as Record; + const index = resolveTaskIndex(input?.taskId, taskIdToIndex, latestTodos); + if (index !== null) { + const status = normalizeTaskStatus(input?.status); + if (status) { + latestTodos[index].status = status; + } + + const subject = typeof input?.subject === 'string' ? input.subject : ''; + const description = typeof input?.description === 'string' ? input.description : ''; + const content = subject || description; + if (content) { + latestTodos[index].content = content; + } + } } else { toolMap.set(block.id, toolEntry); } @@ -143,3 +177,45 @@ function extractTarget(toolName: string, input?: Record): strin } return undefined; } + +function resolveTaskIndex( + taskId: unknown, + taskIdToIndex: Map, + latestTodos: TodoItem[] +): number | null { + if (typeof taskId === 'string' || typeof taskId === 'number') { + const key = String(taskId); + const mapped = taskIdToIndex.get(key); + if (typeof mapped === 'number') { + return mapped; + } + + if (/^\d+$/.test(key)) { + const numericIndex = Number.parseInt(key, 10) - 1; + if (numericIndex >= 0 && numericIndex < latestTodos.length) { + return numericIndex; + } + } + } + + return null; +} + +function normalizeTaskStatus(status: unknown): TodoItem['status'] | null { + if (typeof status !== 'string') return null; + + switch (status) { + case 'pending': + case 'not_started': + return 'pending'; + case 'in_progress': + case 'running': + return 'in_progress'; + case 'completed': + case 'complete': + case 'done': + return 'completed'; + default: + return null; + } +} diff --git a/tests/core.test.js b/tests/core.test.js index e6294b3..79cd60f 100644 --- a/tests/core.test.js +++ b/tests/core.test.js @@ -169,8 +169,12 @@ test('parseTranscript aggregates tools, agents, and todos', async () => { assert.equal(result.tools[0].target, '/tmp/example.txt'); assert.equal(result.agents.length, 1); assert.equal(result.agents[0].status, 'completed'); - assert.equal(result.todos.length, 2); + assert.equal(result.todos.length, 4); + assert.equal(result.todos[0].status, 'completed'); assert.equal(result.todos[1].status, 'in_progress'); + assert.equal(result.todos[2].content, 'Third task'); + assert.equal(result.todos[2].status, 'completed'); + assert.equal(result.todos[3].status, 'in_progress'); assert.equal(result.sessionStart?.toISOString(), '2024-01-01T00:00:00.000Z'); }); diff --git a/tests/fixtures/transcript-basic.jsonl b/tests/fixtures/transcript-basic.jsonl index f1bd2d7..1a73ac8 100644 --- a/tests/fixtures/transcript-basic.jsonl +++ b/tests/fixtures/transcript-basic.jsonl @@ -3,3 +3,6 @@ {"timestamp":"2024-01-01T00:00:02.000Z","message":{"content":[{"type":"tool_use","id":"agent-1","name":"Task","input":{"subagent_type":"explore","model":"haiku"}}]}} {"timestamp":"2024-01-01T00:00:03.000Z","message":{"content":[{"type":"tool_result","tool_use_id":"agent-1","is_error":false}]}} {"timestamp":"2024-01-01T00:00:04.000Z","message":{"content":[{"type":"tool_use","id":"todo-1","name":"TodoWrite","input":{"todos":[{"content":"First task","status":"completed"},{"content":"Second task","status":"in_progress"}]}}]}} +{"timestamp":"2024-01-01T00:00:05.000Z","message":{"content":[{"type":"tool_use","id":"task-1","name":"TaskCreate","input":{"taskId":"alpha","subject":"Third task"}}]}} +{"timestamp":"2024-01-01T00:00:06.000Z","message":{"content":[{"type":"tool_use","id":"task-2","name":"TaskCreate","input":{"subject":"Fourth task","status":"in_progress"}}]}} +{"timestamp":"2024-01-01T00:00:07.000Z","message":{"content":[{"type":"tool_use","id":"task-3","name":"TaskUpdate","input":{"taskId":"alpha","status":"completed"}}]}}