{"version":3,"file":"pii.cjs","names":["z","createMiddleware","HumanMessage","AIMessage","ToolMessage"],"sources":["../../../src/agents/middleware/pii.ts"],"sourcesContent":["import { z } from \"zod/v3\";\nimport { sha256 } from \"@langchain/core/utils/hash\";\nimport { AIMessage, HumanMessage, ToolMessage } from \"@langchain/core/messages\";\nimport type { InferInteropZodInput } from \"@langchain/core/utils/types\";\n\nimport { createMiddleware } from \"../middleware.js\";\n\n/**\n * Represents a detected PII match in content\n */\nexport interface PIIMatch {\n  /**\n   * The matched text\n   */\n  text: string;\n  /**\n   * The start index of the match\n   */\n  start: number;\n  /**\n   * The end index of the match\n   */\n  end: number;\n}\n\n/**\n * Error thrown when PII is detected and strategy is 'block'\n */\nexport class PIIDetectionError extends Error {\n  constructor(\n    public readonly piiType: string,\n    public readonly matches: PIIMatch[]\n  ) {\n    super(`PII detected: ${piiType} found ${matches.length} occurrence(s)`);\n    this.name = \"PIIDetectionError\";\n  }\n}\n\n/**\n * Strategy for handling detected PII\n */\nexport type PIIStrategy = \"block\" | \"redact\" | \"mask\" | \"hash\";\n\n/**\n * Built-in PII types\n */\nexport type BuiltInPIIType =\n  | \"email\"\n  | \"credit_card\"\n  | \"ip\"\n  | \"mac_address\"\n  | \"url\";\n\n/**\n * Custom detector function that takes content and returns matches\n */\nexport type PIIDetector = (content: string) => PIIMatch[];\nexport type Detector = PIIDetector | RegExp | string;\n\n/**\n * Configuration for a redaction rule\n */\nexport interface RedactionRuleConfig {\n  /**\n   * Type of PII to detect (built-in or custom name)\n   */\n  piiType: BuiltInPIIType | string;\n  /**\n   * Strategy for handling detected PII\n   */\n  strategy: PIIStrategy;\n  /**\n   * Custom detector function or regex pattern string\n   */\n  detector?: Detector;\n}\n\n/**\n * Resolved redaction rule with a concrete detector function\n */\nexport interface ResolvedRedactionRule {\n  piiType: string;\n  strategy: PIIStrategy;\n  detector: PIIDetector;\n}\n\n/**\n * Email detection regex pattern\n */\nconst EMAIL_PATTERN = /\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}\\b/g;\n\n/**\n * Credit card detection regex pattern (basic, will be validated with Luhn)\n */\nconst CREDIT_CARD_PATTERN = /\\b(?:\\d{4}[-\\s]?){3}\\d{4}\\b/g;\n\n/**\n * IP address detection regex pattern\n */\nconst IP_PATTERN =\n  /\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b/g;\n\n/**\n * MAC address detection regex pattern\n */\nconst MAC_ADDRESS_PATTERN = /\\b(?:[0-9A-Fa-f]{2}[:-]){5}(?:[0-9A-Fa-f]{2})\\b/g;\n\n/**\n * URL detection regex pattern\n */\nconst URL_PATTERN = /(?:https?:\\/\\/|www\\.)[^\\s<>\"{}|\\\\^`[\\]]+/gi;\n\n/**\n * Luhn algorithm for credit card validation\n */\nfunction luhnCheck(cardNumber: string): boolean {\n  const digits = cardNumber.replace(/\\D/g, \"\");\n  let sum = 0;\n  let isEven = false;\n\n  for (let i = digits.length - 1; i >= 0; i--) {\n    let digit = parseInt(digits[i], 10);\n\n    if (isEven) {\n      digit *= 2;\n      if (digit > 9) {\n        digit -= 9;\n      }\n    }\n\n    sum += digit;\n    isEven = !isEven;\n  }\n\n  return sum % 10 === 0;\n}\n\n/**\n * Convert regex match to PIIMatch\n */\nfunction regexMatchToPIIMatch(match: RegExpMatchArray): PIIMatch {\n  return {\n    text: match[0],\n    start: match.index ?? 0,\n    end: (match.index ?? 0) + match[0].length,\n  };\n}\n\n/**\n * Detect email addresses in content\n */\nexport function detectEmail(content: string): PIIMatch[] {\n  const matches: PIIMatch[] = [];\n  const regex = new RegExp(EMAIL_PATTERN);\n  let match: RegExpMatchArray | null;\n\n  while ((match = regex.exec(content)) !== null) {\n    matches.push(regexMatchToPIIMatch(match));\n  }\n\n  return matches;\n}\n\n/**\n * Detect credit card numbers in content (validated with Luhn algorithm)\n */\nexport function detectCreditCard(content: string): PIIMatch[] {\n  const matches: PIIMatch[] = [];\n  const regex = new RegExp(CREDIT_CARD_PATTERN);\n  let match: RegExpMatchArray | null;\n\n  while ((match = regex.exec(content)) !== null) {\n    const cardNumber = match[0].replace(/\\D/g, \"\");\n    // Credit cards are typically 13-19 digits\n    if (\n      cardNumber.length >= 13 &&\n      cardNumber.length <= 19 &&\n      luhnCheck(cardNumber)\n    ) {\n      matches.push(regexMatchToPIIMatch(match));\n    }\n  }\n\n  return matches;\n}\n\n/**\n * Detect IP addresses in content (validated)\n */\nexport function detectIP(content: string): PIIMatch[] {\n  const matches: PIIMatch[] = [];\n  const regex = new RegExp(IP_PATTERN);\n  let match: RegExpMatchArray | null;\n\n  while ((match = regex.exec(content)) !== null) {\n    const ip = match[0];\n    // Additional validation: each octet should be 0-255\n    const parts = ip.split(\".\");\n    if (\n      parts.length === 4 &&\n      parts.every((part) => {\n        const num = parseInt(part, 10);\n        return num >= 0 && num <= 255;\n      })\n    ) {\n      matches.push(regexMatchToPIIMatch(match));\n    }\n  }\n\n  return matches;\n}\n\n/**\n * Detect MAC addresses in content\n */\nexport function detectMacAddress(content: string): PIIMatch[] {\n  const matches: PIIMatch[] = [];\n  const regex = new RegExp(MAC_ADDRESS_PATTERN);\n  let match: RegExpMatchArray | null;\n\n  while ((match = regex.exec(content)) !== null) {\n    matches.push(regexMatchToPIIMatch(match));\n  }\n\n  return matches;\n}\n\n/**\n * Detect URLs in content\n */\nexport function detectUrl(content: string): PIIMatch[] {\n  const matches: PIIMatch[] = [];\n  const regex = new RegExp(URL_PATTERN);\n  let match: RegExpMatchArray | null;\n\n  while ((match = regex.exec(content)) !== null) {\n    matches.push(regexMatchToPIIMatch(match));\n  }\n\n  return matches;\n}\n\n/**\n * Built-in detector map\n */\nconst BUILT_IN_DETECTORS: Record<BuiltInPIIType, PIIDetector> = {\n  email: detectEmail,\n  credit_card: detectCreditCard,\n  ip: detectIP,\n  mac_address: detectMacAddress,\n  url: detectUrl,\n};\n\n/**\n * Resolve a redaction rule to a concrete detector function\n */\nexport function resolveRedactionRule(\n  config: RedactionRuleConfig\n): ResolvedRedactionRule {\n  let detector: PIIDetector;\n\n  if (config.detector) {\n    if (typeof config.detector === \"string\") {\n      // Regex pattern string\n      const regex = new RegExp(config.detector, \"g\");\n      detector = (content: string) => {\n        const matches: PIIMatch[] = [];\n        let match: RegExpMatchArray | null;\n        const regexCopy = new RegExp(regex);\n\n        while ((match = regexCopy.exec(content)) !== null) {\n          matches.push(regexMatchToPIIMatch(match));\n        }\n\n        return matches;\n      };\n      // oxlint-disable-next-line no-instanceof/no-instanceof\n    } else if (config.detector instanceof RegExp) {\n      detector = (content: string) => {\n        // oxlint-disable-next-line no-instanceof/no-instanceof\n        if (!(config.detector instanceof RegExp)) {\n          throw new Error(\"Detector is required\");\n        }\n        const matches: PIIMatch[] = [];\n        let match: RegExpMatchArray | null;\n        while ((match = config.detector.exec(content)) !== null) {\n          matches.push(regexMatchToPIIMatch(match));\n        }\n\n        return matches;\n      };\n    } else {\n      detector = config.detector;\n    }\n  } else {\n    // Use built-in detector\n    const builtInType = config.piiType as BuiltInPIIType;\n    if (!BUILT_IN_DETECTORS[builtInType]) {\n      throw new Error(\n        `Unknown PII type: ${config.piiType}. Must be one of: ${Object.keys(\n          BUILT_IN_DETECTORS\n        ).join(\", \")}, or provide a custom detector.`\n      );\n    }\n    detector = BUILT_IN_DETECTORS[builtInType];\n  }\n\n  return {\n    piiType: config.piiType,\n    strategy: config.strategy,\n    detector,\n  };\n}\n\n/**\n * Apply redact strategy: replace with [REDACTED_TYPE]\n */\nfunction applyRedactStrategy(\n  content: string,\n  matches: PIIMatch[],\n  piiType: string\n): string {\n  let result = content;\n  // Process matches in reverse order to preserve indices\n  for (let i = matches.length - 1; i >= 0; i--) {\n    const match = matches[i];\n    const replacement = `[REDACTED_${piiType.toUpperCase()}]`;\n    result =\n      result.slice(0, match.start) + replacement + result.slice(match.end);\n  }\n  return result;\n}\n\n/**\n * Apply mask strategy: partially mask PII (show last few characters)\n */\nfunction applyMaskStrategy(\n  content: string,\n  matches: PIIMatch[],\n  piiType: string\n): string {\n  let result = content;\n  // Process matches in reverse order to preserve indices\n  for (let i = matches.length - 1; i >= 0; i--) {\n    const match = matches[i];\n    const text = match.text;\n    let masked: string;\n\n    if (piiType === \"credit_card\") {\n      // Show last 4 digits: ****-****-****-1234\n      const digits = text.replace(/\\D/g, \"\");\n      const last4 = digits.slice(-4);\n      masked = `****-****-****-${last4}`;\n    } else if (piiType === \"email\") {\n      // Show first char and domain: j***@example.com\n      const [local, domain] = text.split(\"@\");\n      if (local && domain) {\n        masked = `${local[0]}***@${domain}`;\n      } else {\n        masked = \"***\";\n      }\n    } else {\n      // Default: show last 4 characters\n      const visibleChars = Math.min(4, text.length);\n      masked = `${\"*\".repeat(\n        Math.max(0, text.length - visibleChars)\n      )}${text.slice(-visibleChars)}`;\n    }\n\n    result = result.slice(0, match.start) + masked + result.slice(match.end);\n  }\n  return result;\n}\n\n/**\n * Apply hash strategy: replace with deterministic hash\n */\nfunction applyHashStrategy(\n  content: string,\n  matches: PIIMatch[],\n  piiType: string\n): string {\n  let result = content;\n  // Process matches in reverse order to preserve indices\n  for (let i = matches.length - 1; i >= 0; i--) {\n    const match = matches[i];\n    const hash = sha256(match.text).slice(0, 8);\n    const replacement = `<${piiType}_hash:${hash}>`;\n    result =\n      result.slice(0, match.start) + replacement + result.slice(match.end);\n  }\n  return result;\n}\n\n/**\n * Apply strategy to content based on matches\n */\nexport function applyStrategy(\n  content: string,\n  matches: PIIMatch[],\n  strategy: PIIStrategy,\n  piiType: string\n): string {\n  if (matches.length === 0) {\n    return content;\n  }\n\n  switch (strategy) {\n    case \"block\":\n      throw new PIIDetectionError(piiType, matches);\n    case \"redact\":\n      return applyRedactStrategy(content, matches, piiType);\n    case \"mask\":\n      return applyMaskStrategy(content, matches, piiType);\n    case \"hash\":\n      return applyHashStrategy(content, matches, piiType);\n    default:\n      throw new Error(`Unknown strategy: ${strategy}`);\n  }\n}\n\n/**\n * Configuration schema for PII middleware\n */\nconst contextSchema = z.object({\n  /**\n   * Whether to check user messages before model call\n   */\n  applyToInput: z.boolean().optional(),\n  /**\n   * Whether to check AI messages after model call\n   */\n  applyToOutput: z.boolean().optional(),\n  /**\n   * Whether to check tool result messages after tool execution\n   */\n  applyToToolResults: z.boolean().optional(),\n});\n\nexport type PIIMiddlewareConfig = InferInteropZodInput<typeof contextSchema>;\n\n/**\n * Process content for PII detection and apply strategy\n */\nfunction processContent(\n  content: string,\n  rule: ResolvedRedactionRule\n): { content: string; matches: PIIMatch[] } {\n  const matches = rule.detector(content);\n  if (matches.length === 0) {\n    return { content, matches: [] };\n  }\n\n  const sanitized = applyStrategy(\n    content,\n    matches,\n    rule.strategy,\n    rule.piiType\n  );\n  return { content: sanitized, matches };\n}\n\n/**\n * Creates a middleware that detects and handles personally identifiable information (PII)\n * in conversations.\n *\n * This middleware detects common PII types and applies configurable strategies to handle them.\n * It can detect emails, credit cards, IP addresses, MAC addresses, and URLs in both user input\n * and agent output.\n *\n * Built-in PII types:\n * - `email`: Email addresses\n * - `credit_card`: Credit card numbers (validated with Luhn algorithm)\n * - `ip`: IP addresses (validated)\n * - `mac_address`: MAC addresses\n * - `url`: URLs (both `http`/`https` and bare URLs)\n *\n * Strategies:\n * - `block`: Raise an exception when PII is detected\n * - `redact`: Replace PII with `[REDACTED_TYPE]` placeholders\n * - `mask`: Partially mask PII (e.g., `****-****-****-1234` for credit card)\n * - `hash`: Replace PII with deterministic hash (e.g., `<email_hash:a1b2c3d4>`)\n *\n * Strategy Selection Guide:\n * | Strategy | Preserves Identity? | Best For                                |\n * | -------- | ------------------- | --------------------------------------- |\n * | `block`  | N/A                 | Avoid PII completely                    |\n * | `redact` | No                  | General compliance, log sanitization    |\n * | `mask`   | No                  | Human readability, customer service UIs |\n * | `hash`   | Yes (pseudonymous)  | Analytics, debugging                    |\n *\n * @param piiType - Type of PII to detect. Can be a built-in type (`email`, `credit_card`, `ip`, `mac_address`, `url`) or a custom type name.\n * @param options - Configuration options\n * @param options.strategy - How to handle detected PII. Defaults to `\"redact\"`.\n * @param options.detector - Custom detector function or regex pattern string. If not provided, uses built-in detector for the `piiType`.\n * @param options.applyToInput - Whether to check user messages before model call. Defaults to `true`.\n * @param options.applyToOutput - Whether to check AI messages after model call. Defaults to `false`.\n * @param options.applyToToolResults - Whether to check tool result messages after tool execution. Defaults to `false`.\n *\n * @returns Middleware instance for use with `createAgent`\n *\n * @throws {PIIDetectionError} When PII is detected and strategy is `'block'`\n * @throws {Error} If `piiType` is not built-in and no detector is provided\n *\n * @example Basic usage\n * ```typescript\n * import { piiMiddleware } from \"langchain\";\n * import { createAgent } from \"langchain\";\n *\n * // Redact all emails in user input\n * const agent = createAgent({\n *   model: \"openai:gpt-4\",\n *   middleware: [\n *     piiMiddleware(\"email\", { strategy: \"redact\" }),\n *   ],\n * });\n * ```\n *\n * @example Different strategies for different PII types\n * ```typescript\n * const agent = createAgent({\n *   model: \"openai:gpt-4o\",\n *   middleware: [\n *     piiMiddleware(\"credit_card\", { strategy: \"mask\" }),\n *     piiMiddleware(\"url\", { strategy: \"redact\" }),\n *     piiMiddleware(\"ip\", { strategy: \"hash\" }),\n *   ],\n * });\n * ```\n *\n * @example Custom PII type with regex\n * ```typescript\n * const agent = createAgent({\n *   model: \"openai:gpt-4\",\n *   middleware: [\n *     piiMiddleware(\"api_key\", {\n *       detector: \"sk-[a-zA-Z0-9]{32}\",\n *       strategy: \"block\",\n *     }),\n *   ],\n * });\n * ```\n *\n * @public\n */\nexport function piiMiddleware(\n  piiType: BuiltInPIIType | string,\n  options: {\n    strategy?: PIIStrategy;\n    detector?: Detector;\n    applyToInput?: boolean;\n    applyToOutput?: boolean;\n    applyToToolResults?: boolean;\n  } = {}\n) {\n  const { strategy = \"redact\", detector } = options;\n  const resolvedRule = resolveRedactionRule({\n    piiType,\n    strategy,\n    detector,\n  });\n\n  const middlewareName = `PIIMiddleware[${resolvedRule.piiType}]`;\n\n  return createMiddleware({\n    name: middlewareName,\n    contextSchema,\n    beforeModel: async (state, runtime) => {\n      const applyToInput =\n        runtime.context.applyToInput ?? options.applyToInput ?? true;\n      const applyToToolResults =\n        runtime.context.applyToToolResults ??\n        options.applyToToolResults ??\n        false;\n\n      if (!applyToInput && !applyToToolResults) {\n        return;\n      }\n\n      const messages = state.messages;\n      if (!messages || messages.length === 0) {\n        return;\n      }\n\n      const newMessages = [...messages];\n      let anyModified = false;\n\n      // Check user input if enabled\n      if (applyToInput) {\n        // Get last user message\n        let lastUserIdx: number | null = null;\n        for (let i = messages.length - 1; i >= 0; i--) {\n          if (HumanMessage.isInstance(messages[i])) {\n            lastUserIdx = i;\n            break;\n          }\n        }\n\n        if (lastUserIdx !== null) {\n          const lastUserMsg = messages[lastUserIdx];\n          if (lastUserMsg && lastUserMsg.content) {\n            const content = String(lastUserMsg.content);\n            const { content: newContent, matches } = processContent(\n              content,\n              resolvedRule\n            );\n\n            if (matches.length > 0) {\n              newMessages[lastUserIdx] = new HumanMessage({\n                content: newContent,\n                id: lastUserMsg.id,\n                name: lastUserMsg.name,\n              });\n              anyModified = true;\n            }\n          }\n        }\n      }\n\n      // Check tool results if enabled\n      if (applyToToolResults) {\n        // Find the last AIMessage, then process all ToolMessage objects after it\n        let lastAiIdx: number | null = null;\n        for (let i = messages.length - 1; i >= 0; i--) {\n          if (AIMessage.isInstance(messages[i])) {\n            lastAiIdx = i;\n            break;\n          }\n        }\n\n        if (lastAiIdx !== null) {\n          // Get all tool messages after the last AI message\n          for (let i = lastAiIdx + 1; i < messages.length; i++) {\n            const msg = messages[i];\n            if (ToolMessage.isInstance(msg)) {\n              if (!msg.content) {\n                continue;\n              }\n\n              const content = String(msg.content);\n              const { content: newContent, matches } = processContent(\n                content,\n                resolvedRule\n              );\n\n              if (matches.length > 0) {\n                newMessages[i] = new ToolMessage({\n                  content: newContent,\n                  id: msg.id,\n                  name: msg.name,\n                  tool_call_id: msg.tool_call_id,\n                });\n                anyModified = true;\n              }\n            }\n          }\n        }\n      }\n\n      if (anyModified) {\n        return { messages: newMessages };\n      }\n\n      return;\n    },\n    afterModel: async (state, runtime) => {\n      const applyToOutput =\n        runtime.context.applyToOutput ?? options.applyToOutput ?? false;\n\n      if (!applyToOutput) {\n        return;\n      }\n\n      const messages = state.messages;\n      if (!messages || messages.length === 0) {\n        return;\n      }\n\n      // Get last AI message\n      let lastAiIdx: number | null = null;\n      let lastAiMsg: AIMessage | null = null;\n      for (let i = messages.length - 1; i >= 0; i--) {\n        const msg = messages[i];\n        if (AIMessage.isInstance(msg)) {\n          lastAiMsg = msg;\n          lastAiIdx = i;\n          break;\n        }\n      }\n\n      if (lastAiIdx === null || !lastAiMsg || !lastAiMsg.content) {\n        return;\n      }\n\n      // Detect PII in message content\n      const content = String(lastAiMsg.content);\n      const { content: newContent, matches } = processContent(\n        content,\n        resolvedRule\n      );\n\n      if (matches.length === 0) {\n        return;\n      }\n\n      // Create updated message\n      const updatedMessage = new AIMessage({\n        content: newContent,\n        id: lastAiMsg.id,\n        name: lastAiMsg.name,\n        tool_calls: lastAiMsg.tool_calls,\n      });\n\n      // Return updated messages\n      const newMessages = [...messages];\n      newMessages[lastAiIdx] = updatedMessage;\n      return { messages: newMessages };\n    },\n  });\n}\n"],"mappings":"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"}