MCPcopy Index your code
hub / github.com/codeaashu/claude-code / resolveHookPermissionDecision

Function resolveHookPermissionDecision

src/services/tools/toolHooks.ts:332–433  ·  view source on GitHub ↗
(
  hookPermissionResult: PermissionResult | undefined,
  tool: Tool,
  input: Record<string, unknown>,
  toolUseContext: ToolUseContext,
  canUseTool: CanUseToolFn,
  assistantMessage: AssistantMessage,
  toolUseID: string,
)

Source from the content-addressed store, hash-verified

330 * (REPL inner calls) so the permission semantics stay in lockstep.
331 */
332export async function resolveHookPermissionDecision(
333 hookPermissionResult: PermissionResult | undefined,
334 tool: Tool,
335 input: Record<string, unknown>,
336 toolUseContext: ToolUseContext,
337 canUseTool: CanUseToolFn,
338 assistantMessage: AssistantMessage,
339 toolUseID: string,
340): Promise<{
341 decision: PermissionDecision
342 input: Record<string, unknown>
343}> {
344 const requiresInteraction = tool.requiresUserInteraction?.()
345 const requireCanUseTool = toolUseContext.requireCanUseTool
346
347 if (hookPermissionResult?.behavior === 'allow') {
348 const hookInput = hookPermissionResult.updatedInput ?? input
349
350 // Hook provided updatedInput for an interactive tool — the hook IS the
351 // user interaction (e.g. headless wrapper that collected AskUserQuestion
352 // answers). Treat as non-interactive for the rule-check path.
353 const interactionSatisfied =
354 requiresInteraction && hookPermissionResult.updatedInput !== undefined
355
356 if ((requiresInteraction && !interactionSatisfied) || requireCanUseTool) {
357 logForDebugging(
358 `Hook approved tool use for ${tool.name}, but canUseTool is required`,
359 )
360 return {
361 decision: await canUseTool(
362 tool,
363 hookInput,
364 toolUseContext,
365 assistantMessage,
366 toolUseID,
367 ),
368 input: hookInput,
369 }
370 }
371
372 // Hook allow skips the interactive prompt, but deny/ask rules still apply.
373 const ruleCheck = await checkRuleBasedPermissions(
374 tool,
375 hookInput,
376 toolUseContext,
377 )
378 if (ruleCheck === null) {
379 logForDebugging(
380 interactionSatisfied
381 ? `Hook satisfied user interaction for ${tool.name} via updatedInput`
382 : `Hook approved tool use for ${tool.name}, bypassing permission prompt`,
383 )
384 return { decision: hookPermissionResult, input: hookInput }
385 }
386 if (ruleCheck.behavior === 'deny') {
387 logForDebugging(
388 `Hook approved tool use for ${tool.name}, but deny rule overrides: ${ruleCheck.message}`,
389 )

Callers 1

Calls 3

logForDebuggingFunction · 0.85
canUseToolFunction · 0.50

Tested by

no test coverage detected