Skip to content

feat: implement SDK canUseTool interrupt handling#71

Open
BingqingLyu wants to merge 3 commits into
mainfrom
pr-2771-fix-sdk-interrupt
Open

feat: implement SDK canUseTool interrupt handling#71
BingqingLyu wants to merge 3 commits into
mainfrom
pr-2771-fix-sdk-interrupt

Conversation

@BingqingLyu

@BingqingLyu BingqingLyu commented Apr 27, 2026

Copy link
Copy Markdown
Owner

TLDR

Implements interrupt handling for SDK canUseTool responses. When the SDK denies a tool call with interrupt: true, the request is terminated immediately and all pending tools are cascade-cancelled with an INTERRUPTED error type.

Screenshots / Video Demo

N/A — no user-facing change. This is a backend feature for SDK integrations.

Dive Deeper

This PR adds support for the SDK canUseTool interrupt mechanism:

  • New error type: Added ToolErrorType.INTERRUPTED to distinguish interrupted tool calls from regular permission denials (EXECUTION_DENIED).

  • Core scheduler changes (coreToolScheduler.ts):

    • When a tool is denied via canUseTool with cancelMessage, the status is now set to 'error' with INTERRUPTED or EXECUTION_DENIED type instead of 'cancelled'.
    • Added cancelPendingTools() method that cascade-cancels all pending tools (awaiting_approval or scheduled) when an interrupt is triggered. These tools are marked with INTERRUPTED error type.
  • CLI changes:

    • permissionController.ts: Extracts interrupt flag from SDK response and passes it to onConfirm.
    • BaseJsonOutputAdapter.ts: Treats INTERRUPTED errors as permission denials for tracking purposes.
    • nonInteractiveCli.ts: Detects INTERRUPTED responses after tool execution and breaks the loop with an appropriate error message.
  • Interface change: Added optional interrupt?: boolean field to ToolConfirmationPayload to support passing the interrupt flag from SDK responses.

Reviewer Test Plan

  1. SDK Integration Test: Create a custom SDK that implements canUseTool and returns { cancelMessage: 'reason', interrupt: true } when denying a tool.
  2. Verify Interrupt Behavior:
    • Start a multi-turn conversation with multiple pending tool calls
    • Have the SDK deny one tool with interrupt: true
    • Confirm the request terminates immediately and all pending tools are cancelled
  3. Verify Non-Interrupt Denial: Ensure that denials without interrupt: true still work normally (tools can be re-allowed in subsequent turns).
  4. JSON Output Test: Run with --output json and verify INTERRUPTED errors are tracked as permission denials.

Testing Matrix

🍏 🪟 🐧
npm run
npx
Docker
Podman - -
Seatbelt - -

Linked issues / bugs

Mingholy and others added 3 commits April 13, 2026 14:12
Add support for handling interrupt flag from SDK canUseTool callback:

- Add ToolErrorType.INTERRUPTED enum for tracking user-initiated interruptions
- Update ToolConfirmationPayload to include optional interrupt field
- Parse and pass interrupt flag from can_use_tool response in permissionController
- Handle interrupt in coreToolScheduler with proper error type and cascade cancellation
- Update nonInteractiveCli to detect INTERRUPTED errors and break the loop
- Track INTERRUPTED and EXECUTION_DENIED errors in permission_denials
- Fix: add tool responses to history before interrupt to preserve request/response pairs

This enables SDK users to interrupt the conversation flow by returning
{ behavior: 'deny', interrupt: true } from canUseTool callback.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
- Add INTERRUPTED error type for tool denial with interrupt flag
- Update permission controller to parse and pass interrupt field from SDK
- Implement cascade cancellation of pending tools on interrupt
- Add permission_denials field to ResultOptions type
- Add integration tests for canUseTool deny and interrupt behavior
- Fix lint errors in tool-control.test.ts

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
… messages

- Add [PermissionDenied] prefix to permission denial messages for proper distinction
- Propagate original denial message to cascade-cancelled tools in interrupt scenarios
- Clean up test files by removing unnecessary debug options
@BingqingLyu BingqingLyu added conflicting-group-1 conflicting-group-1 Conflicting PR group 1 — review as a batch conflicting-pr Shares at least one cross-PR dependency with other PRs and removed conflicting-group-1 labels May 7, 2026
@BingqingLyu

BingqingLyu commented May 7, 2026

Copy link
Copy Markdown
Owner Author

Conflict Group 1

This PR shares modified functions with 9 other PR(s): #112, #113, #114, #117, #14, #17, #6, #75, #88.

These PRs should be reviewed as a batch — merging one may affect the others.

Function File Also modified by
createStreamingInputWithControlPoint permission-control.test.ts #112, #113, #114, #117, #88
runNonInteractive nonInteractiveCli.ts #114, #14, #17, #6, #75
graph LR
    PR71["PR #71"]
    FcreateStreamingInputWithControlPoint_8943["createStreamingInputWithControlPoint<br>permission-control.test.ts"]
    PR71 -->|modifies| FcreateStreamingInputWithControlPoint_8943
    PR112["PR #112"]
    PR112 -->|modifies| FcreateStreamingInputWithControlPoint_8943
    PR113["PR #113"]
    PR113 -->|modifies| FcreateStreamingInputWithControlPoint_8943
    PR114["PR #114"]
    PR114 -->|modifies| FcreateStreamingInputWithControlPoint_8943
    PR117["PR #117"]
    PR117 -->|modifies| FcreateStreamingInputWithControlPoint_8943
    PR88["PR #88"]
    PR88 -->|modifies| FcreateStreamingInputWithControlPoint_8943
    FrunNonInteractive_8467["runNonInteractive<br>nonInteractiveCli.ts"]
    PR71 -->|modifies| FrunNonInteractive_8467
    PR114 -->|modifies| FrunNonInteractive_8467
    PR14["PR #14"]
    PR14 -->|modifies| FrunNonInteractive_8467
    PR17["PR #17"]
    PR17 -->|modifies| FrunNonInteractive_8467
    PR6["PR #6"]
    PR6 -->|modifies| FrunNonInteractive_8467
    PR75["PR #75"]
    PR75 -->|modifies| FrunNonInteractive_8467
Loading

Posted by codegraph-ai conflict detection.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

conflicting-group-1 Conflicting PR group 1 — review as a batch conflicting-pr Shares at least one cross-PR dependency with other PRs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants