Fix MCP elicitation detection and multi-resume hang - #126
Merged
Conversation
- Relax supportsManagedElicitation to only require form capability (not form AND url). Most MCP clients (including Claude Code) only advertise form support — they were incorrectly falling back to the pause/resume two-tool pattern. - When a UrlElicitation is triggered but the client lacks url support, fall back to a form elicitation with the URL in the message. - Fix resume hanging when an execution triggers multiple elicitations. The pause signal is now re-armable so resume races completion against a new pause, matching the executeWithPause pattern. Previously resume just awaited the completion promise which would never resolve if the execution paused again. - Update resume return type from ExecuteResult | null to ExecutionResult | null so callers can handle re-pauses.
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
executor-marketing | 8d3adab | Commit Preview URL Branch Preview URL |
Apr 09 2026, 02:35 AM |
Replace raw Promise.race, mutable callbacks, and unsafe casts with idiomatic Effect primitives: - Deferred<PausedExecution> as the pause signal (swappable via Ref) - Deferred<ElicitationResponse> as the resume response channel - Fiber for the sandbox execution (stays alive across pause/resume) - Effect.race (non-interrupting) to await completion or next pause
RhysSullivan
added a commit
that referenced
this pull request
May 31, 2026
* Fix MCP elicitation detection and multi-elicitation resume hang - Relax supportsManagedElicitation to only require form capability (not form AND url). Most MCP clients (including Claude Code) only advertise form support — they were incorrectly falling back to the pause/resume two-tool pattern. - When a UrlElicitation is triggered but the client lacks url support, fall back to a form elicitation with the URL in the message. - Fix resume hanging when an execution triggers multiple elicitations. The pause signal is now re-armable so resume races completion against a new pause, matching the executeWithPause pattern. Previously resume just awaited the completion promise which would never resolve if the execution paused again. - Update resume return type from ExecuteResult | null to ExecutionResult | null so callers can handle re-pauses. * Refactor pause/resume engine to use Effect Deferred/Fiber/Ref Replace raw Promise.race, mutable callbacks, and unsafe casts with idiomatic Effect primitives: - Deferred<PausedExecution> as the pause signal (swappable via Ref) - Deferred<ElicitationResponse> as the resume response channel - Fiber for the sandbox execution (stays alive across pause/resume) - Effect.race (non-interrupting) to await completion or next pause * Fix type error: orDie on Fiber.join to eliminate unknown error channel
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
supportsManagedElicitationto only requireformcapability — clients like Claude Code that advertise{ form: {} }now use inline elicitation instead of the pause/resume two-tool pathurlsupportresume()hanging when an execution triggers multiple elicitations (e.g. a loop calling multiple tools that each require approval) — the pause signal is now re-armable soresumeraces completion against a new pauseresumereturn type fromExecuteResult | nulltoExecutionResult | nullso callers can handle re-pausesTest plan