feat(chat): re-enable the stop button via chatAbort (#550)#563
Open
clemenshelm wants to merge 2 commits into
Open
feat(chat): re-enable the stop button via chatAbort (#550)#563clemenshelm wants to merge 2 commits into
clemenshelm wants to merge 2 commits into
Conversation
added 2 commits
June 19, 2026 13:22
The composer's stop button was cosmetic since PR #136 rolled it back — OpenClaw's chat.abort was a no-op on agent-RPC runs (openclaw#42172, fixed upstream and shipped in our pinned OC 2026.6.5). - Add an {type:"abort"} WS frame to BrowserMessage; ClientRouter routes it to chatAbort(sessionKey, runId) using the active-run registry for a precise runId, then emits the chat.run_aborted audit event (reserved by #441, first emitted here) with outcome reflecting the RPC result. - Wire onCancel into the assistant-ui external-store runtime: send the abort frame and optimistically end the turn client-side. - Unit tests for the server routing/audit contract and the client onCancel dispatch + optimistic stop. Integration E2E drives a real stop against OpenClaw and guards the session-lane-release regression (a second message on the same session must still get a reply).
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.
Closes #550. Part of the OpenClaw-integration audit (#556).
Why
The chat composer's stop button has been cosmetic since PR #136 rolled it back. The original implementation (PR #23) looked like it worked client-side, but OpenClaw's
chat.abortwas a no-op onagent-RPC runs — it returned{ aborted: false }and never released the session lane, so every subsequent message on that session came back as an emptydone. Root-caused as openclaw/openclaw#42172.That upstream bug is fixed (closed 2026-04-26, commit
fd68994c5aregisters theAbortControllerfor agent-RPC runs) and shipped in our pinned OpenClaw 2026.6.5. So the button can come back — but only with empirical proof against a real gateway, because last time the client-side flow lied about the server having stopped.What changed
client-router.ts): a new{type:"abort"}WS frame is routed tochatAbort(sessionKey, runId)— runId resolved precisely from the active-run registry (never aborts a newer run that already replaced this one), falling back to a sessionKey-only abort. It emitschat.run_aborted(reserved by feat(chat): server-side run registry + watchdog for stuck runs (#310 Tier 2a) #441's watchdog work, emitted here for the first time) withoutcomereflecting the RPC result, so an operator always sees that a user asked to stop. The abort frame goes through the same agent-access check as chat/history.use-ws-runtime.ts):onCancelwired into the assistant-ui external-store runtime — sends the abort frame and optimistically ends the turn so the composer re-enables immediately. The existingComposerPrimitive.Cancelbutton now does something; no markup change needed.chat.run_abortedflipped from reserved to emitted inaudit-trail.mdx.The stream pipe's existing post-abort handling (the synthetic terminal
doneopenclaw-node emits) cleans up the run — no new teardown code.Test plan
client-router-abort.test.ts(6): routing tochatAbortwith the registry runId, thechat.run_abortedaudit (actor=user, success), sessionKey-only abort when no run is registered, per-chatchatIdtargeting (Chats: per-agent session overview + per-task session model (fixes silent history loss from cross-channel /new) #508),outcome: failureon RPC throw (still audits), and access-denied (no abort, no audit).use-ws-runtime.test.ts(+3): the abort frame is sent (withchatIdwhen scoped), andisRunningflips optimistically.19-chat-stop-button.spec.tsagainst real OpenClaw 2026.6.5: send a genuinely incremental reply, stop it mid-stream, and assert (1) the full reply never lands, (2) achat.run_abortedaudit row appears, and (3) the same session is immediately reusable — a second message gets a real reply. That third assertion is the openclaw#42172 regression guard; it would go red if the upstream fix ever regressed. Verified green locally against the production-image integration stack (run withDB_PASSWORDset, as CI does).tsc --noEmitclean,eslint0 errors, full web unit suite (6203 passed),test:db(115 passed).Notes
chat.run_aborteddetail:{ agent:{id,name}, sessionKey, runId|null, reason:"user_request" }— no PII; sessionKey embeds the user UUID, not an email.onCancelmust be() => Promise<void>per assistant-ui) was caught by the production-image build's stricter typecheck and fixed — folded into the feature commit.