-
Notifications
You must be signed in to change notification settings - Fork 309
Persisted token usage is always empty — breakdown rides on the prompt response (result.usage), not usage_update._meta.usage #406
Copy link
Copy link
Closed
Labels
P2Normal priority bug or improvement with limited blast radius.Normal priority bug or improvement with limited blast radius.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.ClawSweeper found a clear likely implementation shape for this issue.clawsweeper:queueable-fixClawSweeper marked this issue as an existing queue_fix_pr work candidate.ClawSweeper marked this issue as an existing queue_fix_pr work candidate.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.ClawSweeper found a high-confidence source-level issue reproduction.impact:data-lossThis issue is about lost, corrupted, or silently dropped user/session/config data.This issue is about lost, corrupted, or silently dropped user/session/config data.impact:session-stateThis issue is about session, memory, transcript, context, or agent state drift.This issue is about session, memory, transcript, context, or agent state drift.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.Very strong issue quality with high-confidence source-level or clear reproduction.no-staleExempts this issue from stale automation.Exempts this issue from stale automation.
Description
Metadata
Metadata
Assignees
Labels
P2Normal priority bug or improvement with limited blast radius.Normal priority bug or improvement with limited blast radius.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.ClawSweeper found a clear likely implementation shape for this issue.clawsweeper:queueable-fixClawSweeper marked this issue as an existing queue_fix_pr work candidate.ClawSweeper marked this issue as an existing queue_fix_pr work candidate.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.ClawSweeper found a high-confidence source-level issue reproduction.impact:data-lossThis issue is about lost, corrupted, or silently dropped user/session/config data.This issue is about lost, corrupted, or silently dropped user/session/config data.impact:session-stateThis issue is about session, memory, transcript, context, or agent state drift.This issue is about session, memory, transcript, context, or agent state drift.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.Very strong issue quality with high-confidence source-level or clear reproduction.no-staleExempts this issue from stale automation.Exempts this issue from stale automation.
Type
Fields
Priority
None yet
Summary
A session's persisted
cumulative_token_usage(in~/.acpx/sessions/<id>.json) — and thereforegetStatus().usage.cumulative— is always{}, even though the agent reports a full per-turn token breakdown every turn. This affects every ACP agent I checked: claude-agent-acp, codex-acp, and cursor-agent.cumulative_costis captured fine; only the token breakdown is lost.Root cause
The conversation reducer captures token usage only from
usage_update._meta.usage:src/session/conversation-model.ts→usageToTokenUsage()readsupdate._meta?.usage(falling back to top-levelinput_tokens/…).But none of the agents put the breakdown there. They emit
usage_updateas{ used, size }(claude addscoston the final one), and report the actual token breakdown on thesession/promptresponse underresult.usage:result.usage = { inputTokens, outputTokens, cachedReadTokens, cachedWriteTokens, totalTokens }result.usage = { inputTokens, outputTokens, cachedReadTokens, thoughtTokens, totalTokens }(plus_meta.quotadetail){ stopReason, usage: { inputTokens, outputTokens, cachedReadTokens, cachedWriteTokens, … } }The data is already available to the runtime —
src/cli/output/output.tsconsumes it for the printed usage line:…but
result.usageis never folded into the conversation'scumulative_token_usage/request_token_usage. So the persisted record (andgetStatus()) shows nothing, while the CLI's own usage line shows the real numbers.Reproduction
~/.acpx/sessions/<id>.json→cumulative_token_usageis{}(notecumulative_costis populated for claude).<id>.stream.ndjsonconfirms everyusage_updateis{ used, size }(no_meta.usage), while thesession/promptresponse carries the breakdown underresult.usage.Suggested fix
Fold the prompt response's
result.usageintocumulative_token_usage/request_token_usage(mappingcachedReadTokens→cache_read_input_tokens,cachedWriteTokens→cache_creation_input_tokens,thoughtTokens→thought_tokens) — the sameresult.usagethe output line already reads. The existingusage_update._meta.usagepath can stay for agents that populate it.