Skip to content

fix(dashboard): parse CodeBuddy index.json for token usage - #107

Merged
jeff-r2026 merged 1 commit into
Tencent:mainfrom
jeff-r2026:fix/codebuddy-token-usage
Jul 2, 2026
Merged

fix(dashboard): parse CodeBuddy index.json for token usage#107
jeff-r2026 merged 1 commit into
Tencent:mainfrom
jeff-r2026:fix/codebuddy-token-usage

Conversation

@jeff-r2026

Copy link
Copy Markdown
Collaborator

Problem

Token/prompt usage statistics never populated for CodeBuddy sessions (always 0), while Claude sessions worked.

Root cause: token stats have a single source — scanTranscriptStop() scanning the transcript_path at Stop time. That scanner is hard-bound to the Claude Code JSONL schema (line-by-line JSON.parse of {type:"assistant", message.usage.*_tokens}). CodeBuddy's Stop hook does fire and does pass a transcript_path, but it points to a single pretty-printed index.json document (CodeBuddy's own format), so every line fails JSON.parse and tokens stay 0.

CodeBuddy's index.json actually contains authoritative usage:

{
  "messages": [{ "role": "user" | "assistant" | "tool" }],
  "requests": [{ "usage": { "inputTokens", "outputTokens", "totalTokens" } }]
}

Fix

Add scanCodebuddyIndex():

  • tokens: sum requests[].usage.{inputTokens,outputTokens} (same per-turn accumulation model as the Claude scan; input + output matches CodeBuddy's own totalTokens). CodeBuddy exposes no cache-read/creation split at the request level, so those map to 0.
  • prompts: count messages[] with role === "user".

Dispatched from scanTranscriptStop() when the transcript basename is index.json, with a safe fallback to the existing Claude JSONL scanner (returns null on any parse failure). No change to the Claude path.

Verification

Tested end-to-end against a real local CodeBuddy transcript:

  • scanTranscriptStop(index.json){input: 215609, output: 2967}, prompts: 2 (total 218576 matches the file's totalTokens)
  • Full parseHookEvent(Stop payload, "codebuddy") path attaches tokens + prompts
  • Compiled artifact via the real hook CLI command dashboard-report --stdin --tool codebuddy writes the tokens into events.jsonl

Added a regression test; vitest (dashboard-collector + conversation-token-metrics, 83 tests) and tsc --noEmit pass.

CodeBuddy persists its transcript as a single index.json document (a JSON object with requests[].usage + messages[]), not the Claude Code JSONL schema scanTranscriptStop expects. Every line failed JSON.parse, so token/prompt stats stayed 0 for CodeBuddy sessions.

Add scanCodebuddyIndex(): sum requests[].usage.{inputTokens,outputTokens} and count user messages as prompts, dispatched when the transcript basename is index.json, with a safe fallback to the Claude JSONL scanner. Verified against a real local CodeBuddy transcript end-to-end.
@jeff-r2026
jeff-r2026 merged commit f5b05d1 into Tencent:main Jul 2, 2026
7 checks passed
jeff-r2026 added a commit that referenced this pull request Jul 2, 2026
…flushed (#108)

CodeBuddy writes requests[].usage into index.json shortly AFTER firing the Stop hook, so the first scan sees messages (prompts captured) but zero usage — single-turn/last-turn sessions permanently recorded 0 tokens. Add a bounded retry (up to ~1.75s, within the 60s hook timeout) that re-reads until usage appears, then returns the cumulative snapshot. Follow-up to #107.
@hsuchifeng hsuchifeng mentioned this pull request Jul 3, 2026
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant