Skip to content

fix(acp): absorb non-steering redirect without synthetic turn_complete - #813

Open
Frank-zhu0404 wants to merge 4 commits into
xintaofei:mainfrom
Frank-zhu0404:fix/issue-590-acp-redirect-steering
Open

Frank-zhu0404 wants to merge 4 commits into
xintaofei:mainfrom
Frank-zhu0404:fix/issue-590-acp-redirect-steering

Conversation

@Frank-zhu0404

Copy link
Copy Markdown
Contributor

Summary

When an ACP agent advertises steering=false, mid-turn "redirect" notices were treated as synthetic turn completions. That fabricated empty ~1ms turn_complete events, wedged the conversation into cancelled / pending_review, and swallowed the user's send.

This branch absorbs those busy/redirect notices without completing the turn, follows live agent output through the absorb window, and (r3) races a queued notice against a fast end_turn so a notice already in flight cannot settle as end_turn while still unread.

Changes

  • Skip synthetic mid-turn redirect completion when the agent has no steering.
  • Keep the turn open through absorb / quiet follow for live chunks.
  • On non-steering fast end_turn after output: biased select prefers read_update; arm a short notice race before finishing so a queued Hermes notice is applied first.

Test plan

  • vitest run src/lib/busy-prompt.test.ts (9 passed)
  • Filtered cargo test --features test-utils --lib absorb / busy-prompt / abandon / classify tests (prior FIX + review gate)
  • CI frontend + rust matrix on this PR

Closes #590

A session/prompt that lands on a turn the agent is already running comes
back as an instant end_turn. Hermes answers that with "Redirected the
active turn with your correction." or "Queued for the next turn.", and
codeg treated the ack as a finished turn. The conversation then flipped
to pending_review or cancelled, and the real reply never streamed.

When native steering is not available, that ack settles as busy (the
prompt was lost, so the client requeues it) or deferred (the agent kept
it). Neither stop reason moves the row. Codeg keeps reading the live
turn and closes it only once real output goes quiet. Agents that
advertise steering are unchanged.

Closes xintaofei#590
A busy-absorb notice stays conclusive after the live turn has already
streamed, so the prompt response enters the follow instead of settling
end_turn. The quiet timer pauses while a permission, question, or plan
approval is outstanding and re-arms when that queue is empty. A
notice-only quiet settle writes pending_review so the row cannot stay
in_progress after codeg stops reading.

busy and deferred no longer notify, post Turn Complete, or fail an
automation or work-task run. Cancel during the follow drops the prompt
future without polling it again. A busy requeue resends the submitted
draft and its mode.
A non-steering fast end_turn could be selected while the Hermes
notice was still queued after a live chunk. The turn settled as
end_turn and the rest of the reply was dropped.

Bias the turn select so a queued session update is applied before
that response, and arm the notice race even when the chunk was
already noted. Hold the permission-queue lock from the quiet-settle
check through TurnComplete.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant