MCPcopy Create free account
hub / github.com/Noumena-Network/code / createCanUseTool

Method createCanUseTool

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

Source from the content-addressed store, hash-verified

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

Callers 1

getCanUseToolFnFunction · 0.80

Calls 10

sendRequestMethod · 0.95
randomUUIDFunction · 0.90
hasPermissionsToUseToolFunction · 0.85
onPermissionPromptFunction · 0.85
serializeDecisionReasonFunction · 0.85

Tested by

no test coverage detected