Skip to content

fix(acp): drop mid-stream usage emit; OpenCode only sends usage_update at end-of-turn#760

Merged
tiann merged 1 commit into
tiann:mainfrom
swear01:fix/acp-drop-mid-stream-usage-emit
Jun 1, 2026
Merged

fix(acp): drop mid-stream usage emit; OpenCode only sends usage_update at end-of-turn#760
tiann merged 1 commit into
tiann:mainfrom
swear01:fix/acp-drop-mid-stream-usage-emit

Conversation

@swear01
Copy link
Copy Markdown
Contributor

@swear01 swear01 commented May 31, 2026

Summary

Why

PR #756 assumed OpenCode would emit ACP usage_update notifications throughout a streaming turn so the web status bar could tick live. Real-session debug logs against OpenCode 1.15.11 show otherwise:

```
[15:23:38.714] usage_update raw={used:14388, size:65536}
[15:23:38.715] session/prompt response ← 1ms later
[15:23:39.086] finalize promptUsage={inputTokens:52, …}
```

OpenCode emits exactly one usage_update per turn, within ~1ms of the session/prompt response. So the mid-turn emit:

  • never fires during streaming (the data isn't there to relay),
  • only fires once at end-of-turn, where the original finalize emit already produces a richer record,
  • persists a junk inputTokens: 0 / outputTokens: 0 token_count message that gets overwritten ~370ms later by the real one — churn in session history for zero observable gain.

Removing it puts us back to the simpler state machine and leaves only the genuinely useful finalize fallback. A real live counter requires OpenCode (or any other ACP agent) to start emitting usage_update during streaming; filed upstream at anomalyco/opencode.

Refs #750

Test plan

  • `vitest run src/agent/backends/acp/AcpSdkBackend.test.ts` (15 passed; dropped one mid-turn-emit test, adjusted finalize-fallback test to expect a single emit)

🤖 Generated with Claude Code

…e at end-of-turn

PR tiann#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 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
None.

Summary
Review mode: initial
No issues found in the modified ACP usage handling. Residual risk: targeted test execution could not be verified in this runner because bun is unavailable.

Testing
Not run (automation): bun test cli/src/agent/backends/acp/AcpSdkBackend.test.ts failed with bun: command not found.

HAPI Bot

@tiann tiann merged commit 02d4e93 into tiann:main Jun 1, 2026
2 checks passed
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.

2 participants