MCPcopy Create free account
hub / github.com/WJX20/claude-code / createCanUseTool

Method createCanUseTool

src/cli/structuredIO.ts:539–665  ·  view source on GitHub ↗
(
    onPermissionPrompt?: (details: RequiresActionDetails) => void,
  )

Source from the content-addressed store, hash-verified

537 }
538
539 createCanUseTool(
540 onPermissionPrompt?: (details: RequiresActionDetails) => void,
541 ): CanUseToolFn {
542 return async (
543 tool: Tool,
544 input: { [key: string]: unknown },
545 toolUseContext: ToolUseContext,
546 assistantMessage: AssistantMessage,
547 toolUseID: string,
548 forceDecision?: PermissionDecision,
549 ): Promise<PermissionDecision> => {
550 const mainPermissionResult =
551 forceDecision ??
552 (await hasPermissionsToUseTool(
553 tool,
554 input,
555 toolUseContext,
556 assistantMessage,
557 toolUseID,
558 ))
559 // If the tool is allowed or denied, return the result
560 if (
561 mainPermissionResult.behavior === 'allow' ||
562 mainPermissionResult.behavior === 'deny'
563 ) {
564 return mainPermissionResult
565 }
566
567 // Run PermissionRequest hooks in parallel with the SDK permission
568 // prompt. In the terminal CLI, hooks race against the interactive
569 // prompt so that e.g. a hook with --delay 20 doesn't block the UI.
570 // We need the same behavior here: the SDK host (VS Code, etc.) shows
571 // its permission dialog immediately while hooks run in the background.
572 // Whichever resolves first wins; the loser is cancelled/ignored.
573
574 // AbortController used to cancel the SDK request if a hook decides first
575 const hookAbortController = new AbortController()
576 const parentSignal = toolUseContext.abortController.signal
577 // Forward parent abort to our local controller
578 const onParentAbort = () => hookAbortController.abort()
579 parentSignal.addEventListener('abort', onParentAbort, { once: true })
580
581 try {
582 // Start the hook evaluation (runs in background)
583 const hookPromise = executePermissionRequestHooksForSDK(
584 tool.name,
585 toolUseID,
586 input,
587 toolUseContext,
588 mainPermissionResult.suggestions,
589 ).then(decision => ({ source: 'hook' as const, decision }))
590
591 // Start the SDK permission prompt immediately (don't wait for hooks)
592 const requestId = randomUUID()
593 onPermissionPrompt?.(
594 buildRequiresActionDetails(tool, input, toolUseID, requestId),
595 )
596 const sdkPromise = this.sendRequest<PermissionToolOutput>(

Callers 1

getCanUseToolFnFunction · 0.80

Calls 10

sendRequestMethod · 0.95
hasPermissionsToUseToolFunction · 0.85
onPermissionPromptFunction · 0.85
serializeDecisionReasonFunction · 0.85
abortMethod · 0.80

Tested by

no test coverage detected