fix(acp): complete turns against agents that notify before session/new resolves - #121
Open
Yevanchen wants to merge 2 commits into
Open
Conversation
The OpenClaw Gateway ACP bridge (openclaw acp 2026.7.1-2) writes session/update notifications for a newly created session before it writes the session/new response. The client request handler asserted the update against the not-yet-registered native session id, threw "ACP driver backend session is not initialized.", and the update inbox failure closed the whole transport - every fresh-session turn against an OpenClaw gateway failed deterministically during ACP session setup. Hold updates that arrive while no native session id is registered in a bounded queue, and apply them right after session setup registers the id. Pre-registration updates for a different session are dropped with a warning instead of killing the transport. Regression: real-process stub agent reproducing the captured OpenClaw frame order (updates first, then the session/new response), asserting the prompt completes and the deferred updates are applied.
Stdio "close" is not a reliable exit signal for the ACP agent process: the transport keeps the child's stdout locked behind web-stream readers, so "close" can stay pending after the process is gone, and a descendant holding inherited pipes delays it indefinitely. stopAcpAgentProcess then reported "ACP agent process did not exit after force kill." for a child that was already dead, failing otherwise-successful turns. Register both "exit" and "close", short-circuit on recorded exit metadata, and re-check it after a timed-out wait. Port of f3ccdb2 from the main line onto the production lineage.
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.
Problem
Production issue YEF-1119: on an OpenClaw Computer, a Web Console message stalls forever in "Working on this computer…" — no first token, no reply, no visible failure. Authorization, catalog, and model binding were all verified healthy.
Root cause
The OpenClaw Gateway ACP bridge (
openclaw acp2026.7.1-2) writessession/updatenotifications for the newly created session before it writes thesession/newresponse. Captured wire order (loopback gateway, verbatim):session/new(id 1)session/update(session_info_update, new session id)session/update(available_commands_update)session/newresultAcpClientRequestHandler.#applyUpdateasserted the update against the native session id, which only registers after thesession/newresponse resolves, so it threwACP driver backend session is not initialized.; the update-inbox failure closed the connection and every fresh-session OpenClaw turn failed deterministically during ACP session setup — before any prompt could complete.A second defect compounds it during teardown:
waitForChildProcessExitwaited on stdioclose, but the transport keeps the child's stdout locked behind web-stream readers, soclosecan stay pending after the SIGKILLed process is gone. Stop then threwACP agent process did not exit after force kill.for an already-dead child.Fix
acp-client-request-handler.ts: while no native session id is registered, hold incomingsession/updatenotifications in a bounded queue instead of failing the transport.acp-driver-backend.tsapplies them right after session setup registers the id; pre-registration updates for a foreign session are dropped with a warning.acp-agent-process.ts: observe processexitindependently of stdioclose(port of f3ccdb2 from the main line onto this production lineage), and re-check exit metadata after a timed-out wait.Tests
tests/acp-early-session-update.test.ts: real-process stub agent reproducing the captured OpenClaw frame order; asserts the prompt completes, the deferred updates are applied, and a foreign-session early update is dropped without failing the turn. Red on the parent commit, green here.tests/acp-agent-process.test.ts: descendant-holds-stdio case updated to the exit-observation contract (stop resolves promptly; group SIGKILL still reaps the descendant).Verification
bun teston Linux (oven/bun:1.3.14-debian): 1086 pass / 0 fail.bun run tc,bun run lint,git diff --check: clean.openclaw gateway+openclaw acp+ a loopback mock model through mosoo-computer'smosoo-driver-turnbuilt at this commit: prompt completes in ~5s withstopReason=end_turn(regression wired into the mosoo-computer image build; companion PR).Production consumer: mosoo-computer bumps
MOSOO_AGENT_DRIVER_COMMITto this branch head (companion PR references YEF-1119).