1
0

parse-run.mjs 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. #!/usr/bin/env node
  2. // Parse a Claude Code stream-json run log: tool-call sequence + token usage.
  3. import { readFileSync } from 'fs';
  4. const file = process.argv[2];
  5. const lines = readFileSync(file, 'utf8').split('\n').filter(Boolean);
  6. const toolCalls = [];
  7. let result = null;
  8. let initTools = null;
  9. for (const line of lines) {
  10. let ev;
  11. try { ev = JSON.parse(line); } catch { continue; }
  12. if (ev.type === 'system' && ev.subtype === 'init') {
  13. initTools = (ev.tools || []).filter(t => /codegraph/.test(t));
  14. }
  15. if (ev.type === 'assistant' && ev.message?.content) {
  16. for (const block of ev.message.content) {
  17. if (block.type === 'tool_use') {
  18. let detail = '';
  19. if (block.name === 'Task') detail = ` [subagent_type=${block.input?.subagent_type ?? '?'}] ${(block.input?.description ?? '').slice(0,40)}`;
  20. else if (/codegraph/.test(block.name)) detail = ` ${JSON.stringify(block.input?.query ?? block.input?.task ?? block.input?.symbol ?? '').slice(0,60)}`;
  21. else if (block.name === 'Bash') detail = ` ${(block.input?.command ?? '').slice(0,50)}`;
  22. else if (block.name === 'Read') detail = ` ${(block.input?.file_path ?? '').split('/').slice(-1)[0]}`;
  23. toolCalls.push(`${block.name}${detail}`);
  24. }
  25. }
  26. }
  27. if (ev.type === 'result') result = ev;
  28. }
  29. console.log(`\n=== ${file.split('/').pop()} ===`);
  30. console.log(`codegraph tools exposed: ${initTools ? initTools.length : '?'}`);
  31. console.log(`\nTool calls (${toolCalls.length}):`);
  32. const counts = {};
  33. for (const tc of toolCalls) { const n = tc.split(' ')[0]; counts[n] = (counts[n]||0)+1; }
  34. console.log(' by type:', JSON.stringify(counts));
  35. toolCalls.forEach((tc, i) => console.log(` ${i+1}. ${tc}`));
  36. if (result) {
  37. const u = result.usage || {};
  38. const totalIn = (u.input_tokens||0) + (u.cache_read_input_tokens||0) + (u.cache_creation_input_tokens||0);
  39. console.log(`\nResult: ${result.subtype} | duration ${(result.duration_ms/1000).toFixed(0)}s | turns ${result.num_turns}`);
  40. console.log(` tokens: in=${totalIn} out=${u.output_tokens||0} | cost $${(result.total_cost_usd||0).toFixed(3)}`);
  41. }