MCPcopy
hub / github.com/claude-code-best/claude-code / createCanUseTool

Method createCanUseTool

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

Source from the content-addressed store, hash-verified

557 }
558
559 createCanUseTool(
560 onPermissionPrompt?: (details: RequiresActionDetails) => void,
561 ): CanUseToolFn {
562 return async (
563 tool: Tool,
564 input: { [key: string]: unknown },
565 toolUseContext: ToolUseContext,
566 assistantMessage: AssistantMessage,
567 toolUseID: string,
568 forceDecision?: PermissionDecision,
569 ): Promise<PermissionDecision> => {
570 const mainPermissionResult =
571 forceDecision ??
572 (await hasPermissionsToUseTool(
573 tool,
574 input,
575 toolUseContext,
576 assistantMessage,
577 toolUseID,
578 ))
579 // If the tool is allowed or denied, return the result
580 if (
581 mainPermissionResult.behavior === 'allow' ||
582 mainPermissionResult.behavior === 'deny'
583 ) {
584 return mainPermissionResult
585 }
586
587 // Run PermissionRequest hooks in parallel with the SDK permission
588 // prompt. In the terminal CLI, hooks race against the interactive
589 // prompt so that e.g. a hook with --delay 20 doesn't block the UI.
590 // We need the same behavior here: the SDK host (VS Code, etc.) shows
591 // its permission dialog immediately while hooks run in the background.
592 // Whichever resolves first wins; the loser is cancelled/ignored.
593
594 // AbortController used to cancel the SDK request if a hook decides first
595 const hookAbortController = new AbortController()
596 const parentSignal = toolUseContext.abortController.signal
597 // Forward parent abort to our local controller
598 const onParentAbort = () => hookAbortController.abort()
599 parentSignal.addEventListener('abort', onParentAbort, { once: true })
600
601 try {
602 // Start the hook evaluation (runs in background)
603 const hookPromise = executePermissionRequestHooksForSDK(
604 tool.name,
605 toolUseID,
606 input,
607 toolUseContext,
608 mainPermissionResult.suggestions,
609 ).then(decision => ({ source: 'hook' as const, decision }))
610
611 // Start the SDK permission prompt immediately (don't wait for hooks)
612 const requestId = randomUUID()
613 onPermissionPrompt?.(
614 buildRequiresActionDetails(tool, input, toolUseID, requestId),
615 )
616 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.65

Tested by

no test coverage detected