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

Function normalizeToolInput

src/utils/api.ts:566–681  ·  view source on GitHub ↗
(
  tool: T,
  input: z.infer<T['inputSchema']>,
  agentId?: AgentId,
)

Source from the content-addressed store, hash-verified

564
565// TODO: Generalize this to all tools
566export function normalizeToolInput<T extends Tool>(
567 tool: T,
568 input: z.infer<T['inputSchema']>,
569 agentId?: AgentId,
570): z.infer<T['inputSchema']> {
571 switch (tool.name) {
572 case EXIT_PLAN_MODE_V2_TOOL_NAME: {
573 // Always inject plan content and file path for ExitPlanModeV2 so hooks/SDK get the plan.
574 // The V2 tool reads plan from file instead of input, but hooks/SDK
575 const plan = getPlan(agentId)
576 const planFilePath = getPlanFilePath(agentId)
577 // Persist file snapshot for CCR sessions so the plan survives pod recycling
578 void persistFileSnapshotIfRemote()
579 return plan !== null ? { ...input, plan, planFilePath } : input
580 }
581 case BashTool.name: {
582 // Validated upstream, won't throw
583 const parsed = BashTool.inputSchema.parse(input)
584 const { command, timeout, description } = parsed
585 const cwd = getCwd()
586 let normalizedCommand = command.replace(`cd ${cwd} && `, '')
587 if (getPlatform() === 'windows') {
588 normalizedCommand = normalizedCommand.replace(
589 `cd ${windowsPathToPosixPath(cwd)} && `,
590 '',
591 )
592 }
593
594 // Replace \\; with \; (commonly needed for find -exec commands)
595 normalizedCommand = normalizedCommand.replace(/\\\\;/g, '\\;')
596
597 // Logging for commands that are only echoing a string. This is to help us understand how often Claude talks via bash
598 if (/^echo\s+["']?[^|&;><]*["']?$/i.test(normalizedCommand.trim())) {
599 logEvent('tengu_bash_tool_simple_echo', {})
600 }
601
602 // Check for run_in_background (may not exist in schema if CLAUDE_CODE_DISABLE_BACKGROUND_TASKS is set)
603 const run_in_background =
604 'run_in_background' in parsed ? parsed.run_in_background : undefined
605
606 // SAFETY: Cast is safe because input was validated by .parse() above.
607 // TypeScript can't narrow the generic T based on switch(tool.name), so it
608 // doesn't know the return type matches T['inputSchema']. This is a fundamental
609 // TS limitation with generics, not bypassable without major refactoring.
610 return {
611 command: normalizedCommand,
612 description,
613 ...(timeout !== undefined && { timeout }),
614 ...(description !== undefined && { description }),
615 ...(run_in_background !== undefined && { run_in_background }),
616 ...('dangerouslyDisableSandbox' in parsed &&
617 parsed.dangerouslyDisableSandbox !== undefined && {
618 dangerouslyDisableSandbox: parsed.dangerouslyDisableSandbox,
619 }),
620 } as z.infer<T['inputSchema']>
621 }
622 case FileEditTool.name: {
623 // Validated upstream, won't throw

Callers 1

normalizeContentFromAPIFunction · 0.85

Calls 9

getPlanFunction · 0.85
getPlanFilePathFunction · 0.85
getCwdFunction · 0.85
getPlatformFunction · 0.85
logEventFunction · 0.85
normalizeFileEditInputFunction · 0.85
stripTrailingWhitespaceFunction · 0.85
parseMethod · 0.45

Tested by

no test coverage detected