fix(opencode): surface ACP context usage live to web status bar#756
Merged
Conversation
ACP usage_update notifications were captured into latestUsageUpdate but only relayed to the web at end-of-prompt, and only when the prompt response itself carried a usage block. As a result the OpenCode status bar's `ctx N/M (X%)` segment stayed blank during streaming and after any turn that produced no model usage (slash-handled, errored, …). - Capture the active onUpdate in prompt() and emit a context-only usage AgentMessage from captureUsageUpdate whenever the cached values meaningfully change. inputTokens/outputTokens are sent as 0 mid-turn; the final prompt-usage emit overwrites with the real totals. - In the prompt finalizer, fall back to emitting a context-only usage when promptUsage is null but a cached latestUsageUpdate exists. Web reducer already picks the most recent token_count for latestUsage, and reducerTimeline skips token-count events so the mid-turn ticks don't appear as visible event rows. Fixes tiann#750 via [HAPI](https://hapi.run) Co-Authored-By: HAPI <noreply@hapi.run>
There was a problem hiding this comment.
Findings
No issues found.
Summary
Review mode: initial
No actionable issues found in the latest diff. Residual risk: targeted test execution was unavailable in this runner because Bun is not installed; manual OpenCode status-bar verification remains outside this automated pass.
Testing
Not run: bun test cli/src/agent/backends/acp/AcpSdkBackend.test.ts failed with bun: command not found.
HAPI Bot
1 task
tiann
pushed a commit
that referenced
this pull request
Jun 1, 2026
…e at end-of-turn (#760) PR #756 added a mid-turn emit in captureUsageUpdate to surface live context usage via the web status bar. Testing against OpenCode 1.15.11 on a real session shows OpenCode emits a single usage_update per turn, within ~1ms of session/prompt resolving — never during streaming. That makes the mid-turn path dead code for OpenCode (and for any other ACP agent that follows the same pattern). It also persists a useless inputTokens:0/outputTokens:0 token_count message that gets immediately overwritten by the finalize emit, churning the session history. Drop the mid-stream emit and the activeOnUpdate plumbing it required. Keep the finalize fallback for agents that don't return a usage block on session/prompt (slash-handled turns, errored turns). The persistent "live" counter requires the agent to emit usage_update during streaming; filed upstream against anomalyco/opencode. Refs #750 via [HAPI](https://hapi.run) Co-authored-by: HAPI <noreply@hapi.run>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Why
ACP `usage_update` notifications carry only context tokens (`used` / `size`), so the existing code parked them in `latestUsageUpdate` and only forwarded them inside the `finally` block of `prompt(...)`, gated on a non-null prompt-level `usage`. That meant:
`inputTokens` / `outputTokens` are sent as 0 on the mid-turn ticks; the final prompt-usage emit overwrites with the real totals. Web's `reducerTimeline` already skips `token-count` events so these mid-turn emits don't appear as visible event rows, and the reducer picks the most-recent token_count for `latestUsage`.
Fixes #750
Test plan
🤖 Generated with Claude Code