89
return { behavior: 'deny', message: 'SDK aborted the tool request' };
90
}
92
session.respondToPermissionRequest(options.toolUseID, false);
93
session.respondToUserInputRequest(options.toolUseID, ChatInputResponseKind.Cancel);
94
};
96
>
try {
97
>
return await dispatchCanUseTool(deps, session, toolName, input, options);
98
>
} finally {
99
>
options.signal.removeEventListener('abort', abortHandler);
100
>
}
101
}
102
104
>
deps: IClaudeCanUseToolDeps,
105
>
session: ClaudeAgentSession,
106
>
toolName: string,
107
>
input: Record<string, unknown>,
108
>
options: IClaudeCanUseToolOptions,
109
>
): Promise<PermissionResult> {
110
>
// Interactive tools (`AskUserQuestion`, `ExitPlanMode`) are
111
>
// exempt from SDK `permissionMode` auto-approval, so they reach
112
>
// `canUseTool` even under `bypassPermissions`. Routing then
113
>
// splits by tool semantics rather than by the
114
>
// `INTERACTIVE_CLAUDE_TOOLS` flag itself: `ExitPlanMode` is a
115
>
// permission gate (Approve/Deny on whether to leave plan mode)
116
>
// so it uses the standard `pending_confirmation` channel with
117
>
// custom button labels; `AskUserQuestion` is structured user
118
>
// input (a question carousel) so it routes through
119
>
// `requestUserInput` / `ChatInputRequested`.
120
>
if (INTERACTIVE_CLAUDE_TOOLS.has(toolName)) {
121
return handleInteractiveTool(deps, session, toolName, input, options);
122
}