fix: Resolve pre-flight task failures synchronously#1080
Open
jirispilka wants to merge 1 commit into
Open
Conversation
A task-augmented tool call that fails pre-flight (missing payment signature, standby rejection) created a task, then executeToolAndUpdateTask re-checked the known outcome and stored it asynchronously — a zombie working phase for a result decided before execution. The task branch now stores the failure as the terminal result right after createTask and returns a CreateTaskResult already completed, with a single completed status notification. The dead pre-flight re-checks and their two carrier params are removed from executeToolAndUpdateTask. Returning the failure without any task (the fix #684 originally proposed) is not possible: SDK 1.29.0 validates task-augmented responses against CreateTaskResultSchema, so a bare result would surface as McpError(InvalidParams) instead of the x402 payload. Throwing McpError instead was rejected — it would move the payment payload out of structuredContent and break payment clients. Closes #684 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LUZNJQKNCn7ntZCbYsFer5
9a67f8e to
f28785e
Compare
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.
What we're solving
A task-augmented
tools/callthat fails pre-flight (missing payment signature →paymentRequiredResult, standby rejection →standbyRejection) created a task, scheduledexecuteToolAndUpdateTaskviasetImmediate, and had it re-check the same values just to store the already-known error asynchronously. The client saw a fakeworkingphase, and the task path carried dead re-check code that #1063's dispatch extraction would have to drag along. Closes #684 (step 2 of #658). Stacked on #1073 (base:claude/deduplicate-sync-task-paths-duv3zq).How
In the handler's task branch, right after
createTask: if a pre-flight value is set (standby priority first, matching the sync path), store it as the terminalcompletedresult, emit a singlecompletedstatus notification (noworkingtransition), and return{ task: { ...task, status: 'completed' } }. Telemetry rides the handler's existingfinally, firing once with the same properties as the non-task path. The dead re-check block and its two carrier params are deleted fromexecuteToolAndUpdateTask; the runtime 402/permission-approval handling there is untouched (pinned by the #1061 suite, which passes with zero assertion edits).New tests: payment pre-flight (Skyfire-like provider fixture) and standby (mocked conflict check) both resolve synchronously; stored result deep-equals the non-task response including x402
structuredContent; standby-over-payment priority; exactly onecompleted/ zeroworkingnotifications; toolcallnever invoked; telemetry shape per class; expiry edge (task evicted between create and store) still putscompletedon the wire.Alternatives considered
CreateTaskResultSchema; a bare result surfaces asMcpError(InvalidParams)instead of the x402 payload.McpErrorpre-flight — moves the payment payload out ofstructuredContent; breaks payment clients.apify-mcp-server-internalcontract suiteWire-visible change: task-augmented pre-flight failures now return a
CreateTaskResultthat is alreadycompleted— previously the task transitioned throughworkingand completed asynchronously. Notification timing changes accordingly (singlecompleted, noworking).RedisTaskStoreneeds no new transition (working→ terminal viastoreTaskResultis the existing completion path), but the contract suite may want a matching test.Run evidence
type-check,lint,test:unit(980 passed / 2 skipped, deterministic across repeated runs),format,check:agentsall green.expected 'working' to be 'completed'when reverted.workingonto the wire — fixed); final reviewers code-review and thermonuclear both PASS (0 findings); mcpc live-probe smoke PASS (async task lifecycle, pre-dispatch gate, error shapes intact).pnpm run test:integration— the standby task-mode test (tests/integration/suite.ts:3129) is expected green and doubles as the SDK-client check for already-completed tasks.🤖 Generated with Claude Code
https://claude.ai/code/session_01LUZNJQKNCn7ntZCbYsFer5
Generated by Claude Code