fix: auto-reply in pipe mode instead of aborting on incoming messages#5
Open
cad0p wants to merge 2 commits into
Open
fix: auto-reply in pipe mode instead of aborting on incoming messages#5cad0p wants to merge 2 commits into
cad0p wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR prevents background (pipe-mode) subagents from aborting their current turn when intercom messages arrive while they’re busy, avoiding lost messages and broker disconnect cascades. Instead, in non-interactive mode it sends a best-effort auto-reply for new incoming messages (non-threaded) and ignores threaded replies.
Changes:
- Detect non-interactive mode (
ctx.hasUI === false) when an incoming message arrives while the agent is not idle. - In pipe mode, avoid the interrupt/detach path and
ctx.abort(); optionally send an auto-reply for messages withoutreplyTo. - Preserve existing interactive-mode behavior (detach/interrupt + queue/flush logic).
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
When a background (pipe mode) subagent receives an intercom message while busy, the interrupt path calls ctx.abort() which kills the agent's turn. Pipe mode then exits in its finally block, and session_shutdown clears the pending message queue before the flush can fire. The message is lost and the sender gets 'Cancelled'. Instead, detect non-interactive mode (ctx.hasUI === false) and send an automatic reply explaining the agent can't respond. This way: - The sender's `ask` gets a meaningful response instead of hanging - The subagent continues its task uninterrupted - No disconnection cascade from the broker
4b83a18 to
9802313
Compare
pi requires the `pi-package` keyword in package.json to identify packages whose extensions should be loaded. Without it, `pi list` discovers the package but never loads the extension, so the `intercom` tool is unavailable. Also adds explicit `pi.extensions` declaration pointing to `index.ts`.
Author
|
@nicobailon is this still happening? let me know and I can close if fixed in other way |
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
When a background (pipe mode) subagent receives an intercom message while busy streaming, the interrupt path in
handleIncomingMessagecallsctx.abort(), which kills the agent's current turn. Pipe mode then exits in itsfinallyblock, andsession_shutdownclears the pending message queue before the scheduledflushInterruptedMessagescan fire. The message is lost, the subagent disconnects from the broker, and the sender'saskgetsFailed: Cancelled.Root cause chain
handleIncomingMessage→ctx.abort()(interrupt path)finallyblock firessession_shutdownruns synchronously: clearspendingInterruptedMessages, disconnects clientsetTimeout(flushInterruptedMessages, 0)fires too late — queue empty, client gonewaitForReplynever resolves →CancelledInteractive mode survives because it has a persistent event loop — after abort, it starts a new turn to process the message.
Fix
Detect non-interactive mode (
ctx.hasUI === false) before the interrupt path. When a pipe-mode agent is busy:replyTo(i.e.,askquestions or plainsend): auto-reply explaining the agent can't respondreplyTo(replies to previous asks): silently skipThis way:
askgets a meaningful response instead of hangingTesting
pi -p --no-sessionwith a multi-step taskintercom listshowed it)intercom asktargeting the subagentFailed: Cancelledand killed the subagent's intercom connection