{"version":3,"file":"toolCallNormalization.mjs","sources":["../../../src/utils/toolCallNormalization.ts"],"sourcesContent":["/**\n * Tool-call name normalization for malformed LLM tool_use outputs.\n *\n * LLMs — especially smaller / faster models — frequently emit tool_use\n * blocks with names that don't exactly match the registered tool name:\n *\n *   - Wrong delimiter: `outlook/operations` vs `outlook_operations`\n *   - Function-prefix style: `functions.outlook_operations`\n *   - Case drift: `Outlook_Operations`\n *   - Counter suffix: `outlook_operations_1`\n *   - Missing name, only id: `{name: \"\", id: \"tool_outlook_operations_42\"}`\n *\n * Before this normalization layer, any of the above caused the LangGraph\n * ToolNode to throw \"Tool X not found\" and the whole turn to fail. With\n * normalization, we resolve to the correct registered name case-insensitively\n * and transparently fix the tool_call in place.\n *\n * Resolution order:\n *   1. Exact match\n *   2. Normalized delimiter + exact\n *   3. Case-insensitive match\n *   4. Structured candidates (strip prefixes, take suffix segments)\n *   5. Infer from tool_call id (strip trailing digits, function/tool prefix)\n *\n * Any unresolvable tool_call is left as-is — the downstream ToolNode will\n * fail with its usual error and the auto-recovery path kicks in.\n */\n\nfunction lowercaseOrEmpty(value: string): string {\n  return typeof value === 'string' ? value.toLowerCase() : '';\n}\n\n/** Collapse common delimiters (space, dot, slash, dash) to `_` and fold case. */\nfunction normalizeDelimiters(name: string): string {\n  return name\n    .trim()\n    .replace(/[\\s./-]+/g, '_')\n    .replace(/_{2,}/g, '_')\n    .replace(/^_+|_+$/g, '');\n}\n\nfunction resolveCaseInsensitive(\n  rawName: string,\n  allowed: Set<string>\n): string | null {\n  if (allowed.size === 0) return null;\n  const folded = lowercaseOrEmpty(rawName);\n  let match: string | null = null;\n  for (const name of allowed) {\n    if (lowercaseOrEmpty(name) !== folded) continue;\n    // Ambiguous → fail closed\n    if (match && match !== name) return null;\n    match = name;\n  }\n  return match;\n}\n\nfunction resolveExact(rawName: string, allowed: Set<string>): string | null {\n  if (allowed.size === 0) return null;\n  if (allowed.has(rawName)) return rawName;\n  const normalized = normalizeDelimiters(rawName);\n  if (allowed.has(normalized)) return normalized;\n  return (\n    resolveCaseInsensitive(rawName, allowed) ??\n    resolveCaseInsensitive(normalized, allowed)\n  );\n}\n\nfunction buildStructuredCandidates(rawName: string): string[] {\n  const trimmed = rawName.trim();\n  if (!trimmed) return [];\n  const seen = new Set<string>();\n  const out: string[] = [];\n  const add = (value: string): void => {\n    const c = value.trim();\n    if (!c || seen.has(c)) return;\n    seen.add(c);\n    out.push(c);\n  };\n  add(trimmed);\n  add(normalizeDelimiters(trimmed));\n  // Also try dot-normalized, then split\n  const dotForm = trimmed.replace(/\\//g, '.');\n  add(dotForm);\n  add(normalizeDelimiters(dotForm));\n  const segments = dotForm\n    .split('.')\n    .map((s) => s.trim())\n    .filter(Boolean);\n  if (segments.length > 1) {\n    for (let i = 1; i < segments.length; i++) {\n      const suffix = segments.slice(i).join('.');\n      add(suffix);\n      add(normalizeDelimiters(suffix));\n    }\n  }\n  return out;\n}\n\nfunction resolveStructured(\n  rawName: string,\n  allowed: Set<string>\n): string | null {\n  if (allowed.size === 0) return null;\n  const candidates = buildStructuredCandidates(rawName);\n  for (const c of candidates) {\n    if (allowed.has(c)) return c;\n  }\n  for (const c of candidates) {\n    const ci = resolveCaseInsensitive(c, allowed);\n    if (ci) return ci;\n  }\n  return null;\n}\n\nfunction inferFromToolCallId(\n  rawId: string | undefined,\n  allowed: Set<string>\n): string | null {\n  if (!rawId || allowed.size === 0) return null;\n  const id = rawId.trim();\n  if (!id) return null;\n\n  const tokens = new Set<string>();\n  const addTokens = (value: string): void => {\n    const t = value.trim();\n    if (!t) return;\n    tokens.add(t);\n    tokens.add(t.replace(/[:._/-]\\d+$/, ''));\n    tokens.add(t.replace(/\\d+$/, ''));\n    const dotForm = t.replace(/\\//g, '.');\n    tokens.add(dotForm);\n    tokens.add(dotForm.replace(/[:._-]\\d+$/, ''));\n    tokens.add(dotForm.replace(/\\d+$/, ''));\n    for (const prefix of [/^functions?[._-]?/i, /^tools?[._-]?/i]) {\n      const stripped = dotForm.replace(prefix, '');\n      if (stripped !== dotForm) {\n        tokens.add(stripped);\n        tokens.add(stripped.replace(/[:._-]\\d+$/, ''));\n        tokens.add(stripped.replace(/\\d+$/, ''));\n      }\n    }\n  };\n\n  const preColon = id.split(':')[0] ?? id;\n  addTokens(id);\n  addTokens(preColon);\n\n  let singleMatch: string | null = null;\n  for (const token of tokens) {\n    const matched = resolveStructured(token, allowed);\n    if (!matched) continue;\n    // Ambiguous → fail closed\n    if (singleMatch && singleMatch !== matched) return null;\n    singleMatch = matched;\n  }\n  if (singleMatch) return singleMatch;\n\n  // Substring fallback: ids frequently look like `call_<toolname>_<n>` or\n  // `toolu_01...<toolname>...`. Scan for any allowed name embedded in the\n  // delimiter-normalized id (case-insensitive) and fail closed if more than\n  // one distinct allowed name matches.\n  const haystack = lowercaseOrEmpty(normalizeDelimiters(id));\n  let substrMatch: string | null = null;\n  for (const allowedName of allowed) {\n    const needle = lowercaseOrEmpty(allowedName);\n    if (!needle) continue;\n    if (!haystack.includes(needle)) continue;\n    if (substrMatch && substrMatch !== allowedName) return null;\n    substrMatch = allowedName;\n  }\n  return substrMatch;\n}\n\n/**\n * Produce the best allowed tool name for a raw LLM tool_use name.\n * Returns the original name unchanged if no resolution is possible —\n * the downstream executor will then fail with its normal error path.\n */\nexport function normalizeToolCallName(\n  rawName: string,\n  allowedToolNames: Set<string>,\n  rawToolCallId?: string\n): string {\n  const trimmed = rawName.trim() ?? '';\n  if (!trimmed) {\n    return (\n      inferFromToolCallId(rawToolCallId, allowedToolNames) ?? rawName ?? ''\n    );\n  }\n  if (allowedToolNames.size === 0) return trimmed;\n\n  const exact = resolveExact(trimmed, allowedToolNames);\n  if (exact) return exact;\n\n  const structured = resolveStructured(trimmed, allowedToolNames);\n  if (structured) return structured;\n\n  // Last-resort: try the raw id (if supplied). Substring matching lives\n  // inside inferFromToolCallId — only safe to invoke when the caller\n  // passed a real provider id, not when the raw name was used above.\n  const inferred = inferFromToolCallId(rawToolCallId, allowedToolNames);\n  if (inferred) return inferred;\n\n  return trimmed;\n}\n\n/**\n * In-place normalization of all tool_calls on an AIMessage-like object.\n *\n * Applies `normalizeToolCallName` to each tool_call's `name` field using the\n * provided allowed-tool set (derived from the agent's toolMap keys). Also\n * rewrites the `name` field inside any content blocks of type `tool_use` so\n * that downstream providers see the corrected name.\n *\n * Returns `true` if any name was rewritten.\n */\nexport function normalizeMessageToolCalls(\n  message: unknown,\n  allowedToolNames: Set<string>\n): boolean {\n  if (!message || typeof message !== 'object') return false;\n  let changed = false;\n\n  // LangChain AIMessage.tool_calls (normalized form)\n  const msg = message as {\n    tool_calls?: Array<{ name?: string; id?: string }>;\n    content?: unknown;\n  };\n  if (Array.isArray(msg.tool_calls)) {\n    for (const tc of msg.tool_calls) {\n      if (!tc || typeof tc !== 'object') continue;\n      const rawName = typeof tc.name === 'string' ? tc.name : '';\n      const rawId = typeof tc.id === 'string' ? tc.id : undefined;\n      const normalized = normalizeToolCallName(\n        rawName,\n        allowedToolNames,\n        rawId\n      );\n      if (normalized && normalized !== rawName) {\n        tc.name = normalized;\n        changed = true;\n      }\n    }\n  }\n\n  // Anthropic-style content blocks with type: 'tool_use'\n  if (Array.isArray(msg.content)) {\n    for (const block of msg.content as Array<{\n      type?: unknown;\n      name?: unknown;\n      id?: unknown;\n    }>) {\n      if (!block || typeof block !== 'object') continue;\n      if (block.type !== 'tool_use') continue;\n      const rawName = typeof block.name === 'string' ? block.name : '';\n      const rawId = typeof block.id === 'string' ? block.id : undefined;\n      const normalized = normalizeToolCallName(\n        rawName,\n        allowedToolNames,\n        rawId\n      );\n      if (normalized && normalized !== rawName) {\n        block.name = normalized;\n        changed = true;\n      }\n    }\n  }\n\n  return changed;\n}\n"],"names":[],"mappings":"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"}