fix(auto-reply): wire get-reply-run.ts queue-mode gates to session-run-registry — interrupt now actually interrupts#2470
Merged
alexey-pelykh merged 1 commit intomainfrom Apr 22, 2026
Conversation
…n-registry — interrupt now actually interrupts (#2342) `src/auto-reply/reply/get-reply-run.ts` (hot path for every inbound auto-reply) had hardcoded `const isActive = false; const isStreaming = false;` at the queue-mode gate. This collapsed every user-configured queue mode to the "no run active" branch, breaking `interrupt` / `steer` / `steer-backlog` / `collect` semantics. A user who set `queue.mode: interrupt` in their config got silently downgraded — the interrupt mode never actually interrupted a running CLI subprocess. ## Fix - Wire `isActive` to `isSessionRunActive(queueKey)` from `src/agents/session-run-registry.js` (the registry populated by `ChannelBridge` at register/unregister sites). - Wire `interrupt` queue mode to `killSessionRun(queueKey)` — when `isActive` is true and mode is `interrupt`, dispatch `abortController.abort()` or `SIGTERM` to the running subprocess before starting the new run. - Delete the dead `sessionLaneKey` / `laneSize` / `clearCommandLane` block at lines 402-408 — the issue noted (and grep confirmed) `command-queue.ts` lanes are `main`/`cron`/`subagent`/`nested`; there is no session-keyed lane that this code populates. - Drop `isStreaming` entirely. CLI runtimes don't expose a "streaming" state distinct from "active" — the distinction was Pi-embedded-era. Binary: active = streaming. Removed the param from `RunPreparedReplyParams` / `runReplyAgent`'s contract and deleted the dead `shouldSteer && isStreaming` branch at `agent-runner.ts:193-200` (inside that branch `const steered = false` made the inner block unreachable anyway). - Drop unused `shouldSteer` from `runReplyAgent` contract and the local declaration in `get-reply-run.ts` (only consumer was the deleted dead branch). ## Changes - `src/auto-reply/reply/get-reply-run.ts`: - Import `isSessionRunActive`, `killSessionRun` from `../../agents/session-run-registry.js`. - Drop unused `clearCommandLane`, `getQueueSize` imports. - Replace hardcoded `isActive = false` with registry call. - Replace hardcoded interrupt-mode no-op with `killSessionRun(queueKey)`. - Delete `shouldSteer` local + `isStreaming` pass-through. - `src/auto-reply/reply/agent-runner.ts`: remove `isStreaming`, `shouldSteer` from `runReplyAgent` params; delete the `shouldSteer && isStreaming` dead branch (9 lines). - Test fixtures (`agent-runner.media-paths.test.ts`, `agent-runner.misc.runreplyagent.test.ts`, `agent-runner.runreplyagent.e2e.test.ts`): remove stale `isStreaming: false` and `shouldSteer: false` properties that no longer exist on the contract. ## Verification - `pnpm check` (format + tsgo + lint + project-specific lints) → exit 0 - `pnpm test` (full parallel suite) → **800 files / 7010 passed / 3 skipped** — no regression - Rescan: `git grep "isEmbeddedPiRunActive\|isEmbeddedPiRunStreaming\|resolveEmbeddedSessionLane"` in `src/` returns zero hits. - Rescan: `git grep "isStreaming"` in `src/auto-reply/` returns zero hits (test fixtures cleaned). Closes #2342 Refs: #2089, #2088 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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
src/auto-reply/reply/get-reply-run.ts(hot path for every inbound auto-reply) had hardcodedconst isActive = false; const isStreaming = false;at the queue-mode gate — collapsing every user-configured queue mode to the "no run active" branch. A user who setqueue.mode: interruptgot silently downgraded: interrupt mode never actually interrupted the running CLI subprocess.Same family as #2460 / #2461 / #2462 — completes the
session-run-registrywiring sweep from ChannelBridge audit #2089.Fix
isActivetoisSessionRunActive(queueKey)fromsession-run-registry.ts(registry is populated byChannelBridgeat register/unregister sites).interruptqueue mode tokillSessionRun(queueKey)— dispatchesabortController.abort()orSIGTERMwhen a new interrupt-mode message arrives while a run is active.sessionLaneKey/laneSize/clearCommandLaneblock —command-queue.tslanes aremain/cron/subagent/nested, not session-keyed (issue explicitly flagged this as dead regardless of Pi-embedded stubs).isStreamingentirely. CLI runtimes are binary: active = streaming. The distinction was Pi-embedded-era. Removed fromRunPreparedReplyParams/runReplyAgentcontract and deleted theshouldSteer && isStreamingdead branch atagent-runner.ts:193-200(inside:const steered = falsemade the block unreachable anyway).shouldSteerfromrunReplyAgentcontract (only consumer was the deleted dead branch).Changes
src/auto-reply/reply/get-reply-run.tsisSessionRunActive+killSessionRunimport; -clearCommandLane/getQueueSizeimports; replaced hardcodedisActive/isStreamingwith registry call; interrupt-mode gate callskillSessionRun; removed dead lane block andshouldSteerlocalsrc/auto-reply/reply/agent-runner.tsisStreamingandshouldSteerfrom params; deleted deadshouldSteer && isStreamingbranch (9 lines)isStreaming: falseandshouldSteer: falsefixtures (contract-removed fields)5 files / +6 / -53.
Why CLI runtimes are binary (no
isStreaming)AgentRuntime.execute(src/middleware/types.ts:7) returnsAsyncIterable<AgentEvent>. The subprocess is either iterating events (active + streaming) or not (inactive). There's no "request in flight, not yet streaming" state the way Pi-embedded had. Collapsing toisActivealone is accurate.Verification
pnpm check(format + tsgo + lint +lint:tmp:no-random-messaging+lint:no-remoteclaw-ai) → exit 0pnpm test(full parallel suite) → 800 files / 7010 passed / 3 skipped — no regressiongit grep "isEmbeddedPiRunActive\|isEmbeddedPiRunStreaming\|resolveEmbeddedSessionLane" src/→ zero hitsgit grep "isStreaming" src/auto-reply/→ zero hitsTest plan
pnpm checkexit 0pnpm testfull suite green (7010 passed)Context
b27cecc795(Remove pi-embedded.ts stub barrel and clean up no-op call sites #76/feat: remove pi-embedded.ts stub barrel and clean up call sites (#76) #77) +9ef18943dc(sync: upstream to v2026.3.7 (893 commits) #2298 v2026.3.7 sync)src/agents/session-run-registry.tsCloses #2342
Refs: #2089, #2088
🤖 Generated with Claude Code