You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
ACP: PromptResponse.usage reports only the final LLM request of the turn (neither session-cumulative nor per-turn totals) #46092
Over ACP, PromptResponse.usage reports the token usage of the final LLM request of the turn — not session-cumulative totals (what the ACP schema documents) and not a per-turn sum either. Multi-step (tool-calling) turns and multi-message turns systematically under-report: all but the last request's tokens are invisible on this surface.
Where (v1.18.18)
Two levels of "last wins":
Within one assistant message: every step-finishreplaces the message's tokens (ctx.assistantMessage.tokens = usage.tokens) while cost accumulates (cost += usage.cost) — packages/opencode/src/session/processor.ts:444-445. A multi-step message therefore carries only its final LLM request's tokens.
Across the turn: each outer loop iteration creates a new assistant message (packages/opencode/src/session/prompt.ts:1186-1200), and session/prompt returns lastAssistant(sessionID) (prompt.ts:1338-1340); the ACP layer builds usage: buildUsage(info) from that single message (packages/opencode/src/acp/service.ts:823-838, packages/opencode/src/acp/usage.ts:90-103).
Net: PromptResponse.usage = tokens of the turn's final LLM request.
Why it matters
The ACP SDK schema documents Usage fields as session-cumulative ("Total input tokens across all turns", "Sum of all token types across session"). There is an open discussion about clarifying the session-usage RFD to per-turn instead (agentclientprotocol/claude-agent-acp#390) — but last-request semantics matches neither reading, so clients cannot recover turn or session totals from this surface no matter which aggregation they apply.
Note the asymmetry within opencode's own reporting: usage_update.cost is session-cumulative (acp/usage.ts:111-115 sums info.cost over all assistant messages), while the token counters on PromptResponse.usage are last-request — the two halves of the usage report cover different windows.
Concrete downstream impact: intentd (intent-hq/intent) ingests PromptResponse.usage with the schema's cumulative-REPLACE semantics, so opencode sessions are undercounted in its token accounting — tracked in intent-hq/intent#3801.
Suggested fix
Report session-cumulative token totals in PromptResponse.usage (e.g. sum the disjoint token buckets across all assistant messages of the session, mirroring what totalSessionCost already does for cost). If the RFD lands on per-turn semantics instead, summing the steps of the turn's messages would satisfy that reading — either is strictly better than last-request.
Happy to provide the full audit trail (line-cited) if useful.
Activity
github-actions commentedon Aug 29, 2026
This issue might be a duplicate of existing issues. Please check:
usage.ts/prompt.tsprocessor.tsassignment-vs-accumulation bug (tokens = usage.tokensinstead of accumulating) that is the underlying causeYou may want to coordinate with those issues or add detail there rather than tracking separately.