{"version":3,"file":"pii.cjs","names":["piiType: string","matches: PIIMatch[]","cardNumber: string","match: RegExpMatchArray","content: string","match: RegExpMatchArray | null","BUILT_IN_DETECTORS: Record<BuiltInPIIType, PIIDetector>","config: RedactionRuleConfig","detector: PIIDetector","masked: string","strategy: PIIStrategy","z","rule: ResolvedRedactionRule","piiType: BuiltInPIIType | string","options: {\n    strategy?: PIIStrategy;\n    detector?: Detector;\n    applyToInput?: boolean;\n    applyToOutput?: boolean;\n    applyToToolResults?: boolean;\n  }","createMiddleware","lastUserIdx: number | null","HumanMessage","lastAiIdx: number | null","AIMessage","ToolMessage","lastAiMsg: AIMessage | null"],"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      // eslint-disable-next-line no-instanceof/no-instanceof\n    } else if (config.detector instanceof RegExp) {\n      detector = (content: string) => {\n        // eslint-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): ReturnType<typeof createMiddleware> {\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        if (AIMessage.isInstance(messages[i])) {\n          lastAiMsg = messages[i];\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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"}