Skip to content

fix(opencode): surface ACP context usage live to web status bar#756

Merged
tiann merged 1 commit into
tiann:mainfrom
swear01:fix/opencode-acp-usage-status-bar
May 31, 2026
Merged

fix(opencode): surface ACP context usage live to web status bar#756
tiann merged 1 commit into
tiann:mainfrom
swear01:fix/opencode-acp-usage-status-bar

Conversation

@swear01
Copy link
Copy Markdown
Contributor

@swear01 swear01 commented May 31, 2026

Summary

  • Emit a context-only `usage` AgentMessage from `AcpSdkBackend.captureUsageUpdate` whenever cached ACP context values change, so the OpenCode web status bar's `ctx N/M (X%)` segment updates during a turn instead of staying blank until prompt finalization.
  • In the prompt finalizer, fall back to a context-only usage emit when `promptUsage` is null but a cached `latestUsageUpdate` exists — so slash-handled turns and errored turns still refresh the bar.

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:

  • Mid-turn streaming never updated the bar (Claude, by contrast, attaches usage to every assistant chunk).
  • Turns with no final `usage` (slash commands, errors) left the bar frozen at the previous value.

`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

  • `vitest run src/agent/backends/acp/AcpSdkBackend.test.ts` (16 passed, including 2 new tests for mid-turn emit and finalize fallback)
  • `vitest run src/opencode src/agent` (186 passed)
  • Manually verify a fresh OpenCode session shows `ctx …` once the first chunk arrives, the percentage ticks up during streaming, and the bar refreshes after `/help` or other slash-handled turns

🤖 Generated with Claude Code

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>
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@tiann tiann merged commit 994a820 into tiann:main May 31, 2026
2 checks passed
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>
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.

bug(web): OpenCode session status bar shows no context usage during a turn (and not at all on a fresh session)

2 participants