fix(chat): stop active runs and cancel tool invocations#269
Merged
su-fen merged 10 commits intoJul 26, 2026
Merged
Conversation
…ed call An abort while a call waited on the per-server serialization lock threw before the lock's release() ran, leaving the chained tail promise unresolved: every later call to that MCP server hung forever and only an app restart recovered. Move the abortable wait into the same release/cleanup scope as the call body — early release is safe because the tail still chains behind the previous holder, so serialization for subsequent callers is preserved. Adds a regression test that deadlocks (2s timeout) without the fix.
finalizeConversationRun raced the history-persist barrier against the gateway stream close and the terminal runtime snapshot inside a single Promise.allSettled, so "done"/"cancelled" could reach the gateway before the conversation was persisted — reverting the 26f2561 invariant that protects WebUI clients from hydrating truncated conversations. Serialize via finalizeChatRunInOrder: await the persist barrier first, then run the two flushes together. The synchronous UI release and the 2s settle cap are unchanged, and the force-stop escape hatch still skips the barrier on purpose (it exists for runs whose persistence is hung).
… path - createToolRunId gains a uuid suffix: provider tool-call ids are not globally unique (local models reuse call_1 across conversations), and registering a duplicate run id cancels the previous registration's token, so two sessions could cancel each other's MCP/SSH runs. - Drop the duplicated shell_cancel command; runtime_cancel is the single registry cancel entry point and shellTools reuses the shared requestRuntimeCancel helper (its bespoke retry loop also bailed on the first IPC error — now bounded retries continue past transient failures). - Replace the 25ms wait_for_cancel polling loop with an event-driven ShellCancelFlag (AtomicBool + tokio Notify): blocking code still polls is_cancelled, async watchers await cancelled() without timers. - sftp_transfer abort cleanup goes through invokeWithAbort onLateResult instead of a dangling per-signal listener: an abort during the start call now cancels the transfer as soon as its id surfaces. - CI runs the shell_runner cancellation tests (previously never executed by the targeted Tauri test filters).
…ancels - stopSending no longer falls back to "any running conversation": when the visible sending state and the running set were briefly out of sync, Stop could silently kill an unrelated background run. - A gateway:chat-cancel that finds nothing to stop (no in-flight bridge request, no handler, no controller, not running) now consumes its own persistent stop intent — a leftover flag used to swallow the conversation's next send().
The settled-round CSS struck through and dimmed incomplete todo items in every settled reply — including normally completed ones that legitimately leave todos open. Keep the animation freeze for all settled rounds, but gate the strike-through/dim on the reply actually being aborted. Mirrored in GUI and WebUI.
# Conflicts: # .github/workflows/ci.yml
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.
Summary
Validation
pnpm --dir crates/agent-gui buildpnpm --dir crates/agent-gateway/web buildcargo check --manifest-path crates/agent-gui/src-tauri/Cargo.toml --testsgit diff --check upstream/main..HEADNotes
The full frontend test commands exceeded the local runner's fixed 30-second execution window; the focused cancellation suites above completed successfully with no failures.