Skip to content

Vouch agent-initiated ACP turns so async job delivery renders - #2123

Open
bradhallett wants to merge 1 commit into
get-bb:mainfrom
bradhallett:fix/acp-agent-initiated-turns
Open

Vouch agent-initiated ACP turns so async job delivery renders#2123
bradhallett wants to merge 1 commit into
get-bb:mainfrom
bradhallett:fix/acp-agent-initiated-turns

Conversation

@bradhallett

Copy link
Copy Markdown

What was wrong

ACP agents can emit session/update work output with no prompt in flight — an agent-initiated turn (OMP's async-job auto-delivery is the concrete case: a background job settles, the agent resumes and streams a follow-up unprompted). ACP brackets no turn for that, and the bridge forwarded the updates unbracketed, so the translator classified them unhandled/onlyIfNoTurn and they never reached the thread: the agent's output was silently dropped. Root cause and evidence in #2122 (DB event gap, wire probe, pre-fix permalinks).

What changed

plugins/provider-acp/src/bridge/bridge.ts — the bridge now vouches agent-initiated turns itself, the shape docs/provider-bridge-protocol.md turn lifecycle rule 3 sanctions (and the compaction path already uses):

  • Idle agent-work updates (agent_message_chunk, agent_thought_chunk, tool_call, tool_call_update, plan) open a vouched turn via the existing bridge turn-started command → turn.open.
  • A quiet window (SPONTANEOUS_TURN_IDLE_TIMEOUT_MS, 120 s, re-armed per chunk) settles the turn as end_turn; a still-open one settles before the next bb-initiated turn or compaction starts; thread/stop and session teardown cancel/clean it. A slow provider can split into multiple vouched turns; output is never lost.
  • Non-work updates (available_commands_update, usage_update, …) stay noise — no phantom turns. user_message_chunk stays classified as input-echo noise, so the replayed async result creates no phantom user row.

No wire/protocol changes; translator untouched (stays context-free). fake-acp-agent.mjs gains spontaneous-stream:N (post-prompt unsolicited user_message_chunk + N agent chunks) and spontaneous-noise behaviors plus a follow-up usage_update signal; __setSpontaneousTurnIdleTimeoutForTests shrinks the quiet window in tests.

How you verified

  • 3 new tests in src/bridge/bridge.test.ts (real bridge + real delta assembler, fake agent over stdio): vouched turn opens for unsolicited output and quiet-closes; a still-open vouched turn settles before the next user turn (3 started / 3 completed, stream intact, exactly one input.accepted); non-work idle updates open nothing.
  • Mutation check: removing agent_message_chunk from the work-kind map fails both positive tests (and not the noise test).
  • pnpm -C plugins/provider-acp test → 184 passed (14 files); tsc --noEmit clean; eslint + prettier clean on touched files.

Fixes #2122

AGENT GENERATED: by zai/glm-5.3

ACP agents can produce session updates with no prompt in flight (OMP
async-job auto-delivery). The bridge gated all work updates on an
active prompt, so the output was dropped and nothing reached the
thread. The bridge now opens a turn itself when idle agent-work
updates arrive, settles it on a quiet window, before the next
bb-initiated turn, or on stop; non-work updates stay noise.
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.

provider-acp silently drops agent-initiated turns (unprompted session updates, e.g. OMP async-job delivery)

1 participant