* fix(web): send a cancellation notification when cancelling an ordinary tool call (#1458) The Tool detail panel's Cancel button was a silent no-op for ordinary (non-task) tool calls: App.onCancelToolCall found no captured taskId and did nothing, leaving the button looking actionable while the call ran on. Wire request cancellation through the MCP cancellation flow. callTool now tracks the in-flight call with an AbortController whose signal is threaded into the SDK request options; aborting it makes the SDK send a notifications/cancelled for that request and reject the pending call. cancelToolCall() performs the abort. callTool surfaces the cancellation as a ToolCallCancelledError (without recording a failed call), which App clears as a clean cancel plus a short confirmation toast. Task-augmented calls are unchanged: they have a server-side task and are still cancelled via cancelRequestorTask (#1457). Closes #1458 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(web): address review — distinguish disconnect from cancel; tidy callTool params Review follow-ups on #1463: - Disconnect no longer surfaces as "Tool call cancelled". The catch in callToolWithRetries now throws ToolCallCancelledError only when the abort reason matches the deliberate user-cancel reason (TOOL_CALL_CANCELLED_REASON); a disconnect aborts the same controller with a different reason and falls through to the normal error path, so no misleading toast. - Note the activeToolCallAbortController slot is shared (last-writer-wins) across all callTool callers. - Fold callToolWithRetries/attemptToolCall's long positional parameter list into a single ToolCallRequest object; move the URL-elicitation loop state into callToolWithRetries. Adds an integration test that a disconnect mid-call rejects as an ordinary error (not ToolCallCancelledError), using a slow send_progress call over HTTP. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
26 lines
1.1 KiB
TypeScript
26 lines
1.1 KiB
TypeScript
/**
|
|
* Thrown by `InspectorClient.callTool` when the in-flight ordinary (non-task)
|
|
* tool call is cancelled via `cancelToolCall()`. By the time this is thrown the
|
|
* SDK has already sent the `notifications/cancelled` to the server (the MCP
|
|
* cancellation flow) and rejected the underlying request; `callTool` converts
|
|
* that rejection into this error so the web layer can clear the executing state
|
|
* as a clean cancellation instead of surfacing a generic failure — and so the
|
|
* cancelled call is *not* recorded as a failed call in request history.
|
|
*
|
|
* Task-augmented calls have a server-side task and are cancelled via
|
|
* `cancelRequestorTask()` instead, so they never produce this error.
|
|
*/
|
|
export class ToolCallCancelledError extends Error {
|
|
/** The name of the tool whose call was cancelled, when known. */
|
|
readonly toolName?: string;
|
|
|
|
constructor(toolName?: string) {
|
|
super(
|
|
toolName
|
|
? `Tool call "${toolName}" was cancelled.`
|
|
: "Tool call was cancelled.",
|
|
);
|
|
this.name = "ToolCallCancelledError";
|
|
this.toolName = toolName;
|
|
}
|
|
}
|