MCPcopy Create free account
hub / github.com/claude-code-best/claude-code / canUseTool

Function canUseTool

src/cli/print.ts:4374–4483  ·  view source on GitHub ↗
(
    tool,
    input,
    toolUseContext,
    assistantMessage,
    toolUseId,
    forceDecision,
  )

Source from the content-addressed store, hash-verified

4372 permissionPromptTool: PermissionPromptTool,
4373): CanUseToolFn {
4374 const canUseTool: CanUseToolFn = async (
4375 tool,
4376 input,
4377 toolUseContext,
4378 assistantMessage,
4379 toolUseId,
4380 forceDecision,
4381 ) => {
4382 const mainPermissionResult =
4383 forceDecision ??
4384 (await hasPermissionsToUseTool(
4385 tool,
4386 input,
4387 toolUseContext,
4388 assistantMessage,
4389 toolUseId,
4390 ))
4391
4392 // If the tool is allowed or denied, return the result
4393 if (
4394 mainPermissionResult.behavior === 'allow' ||
4395 mainPermissionResult.behavior === 'deny'
4396 ) {
4397 return mainPermissionResult
4398 }
4399
4400 // Race the permission prompt tool against the abort signal.
4401 //
4402 // Why we need this: The permission prompt tool may block indefinitely waiting
4403 // for user input (e.g., via stdin or a UI dialog). If the user triggers an
4404 // interrupt (Ctrl+C), we need to detect it even while the tool is blocked.
4405 // Without this race, the abort check would only run AFTER the tool completes,
4406 // which may never happen if the tool is waiting for input that will never come.
4407 //
4408 // The second check (combinedSignal.aborted) handles a race condition where
4409 // abort fires after Promise.race resolves but before we reach this check.
4410 const { signal: combinedSignal, cleanup: cleanupAbortListener } =
4411 createCombinedAbortSignal(toolUseContext.abortController.signal)
4412
4413 // Check if already aborted before starting the race
4414 if (combinedSignal.aborted) {
4415 cleanupAbortListener()
4416 return {
4417 behavior: 'deny',
4418 message: 'Permission prompt was aborted.',
4419 decisionReason: {
4420 type: 'permissionPromptTool' as const,
4421 permissionPromptToolName: tool.name,
4422 toolResult: undefined,
4423 },
4424 }
4425 }
4426
4427 const abortPromise = new Promise<'aborted'>(resolve => {
4428 combinedSignal.addEventListener('abort', () => resolve('aborted'), {
4429 once: true,
4430 })
4431 })

Callers 1

wrappedCanUseToolMethod · 0.50

Calls 7

hasPermissionsToUseToolFunction · 0.85
safeParseJSONFunction · 0.85
callMethod · 0.80
resolveFunction · 0.50

Tested by

no test coverage detected