@directive-run/ai 1.19.0 → 1.19.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/anthropic.d.cts +1 -1
  2. package/dist/anthropic.d.ts +1 -1
  3. package/dist/chunk-2C3R77ZW.cjs +16 -0
  4. package/dist/chunk-2C3R77ZW.cjs.map +1 -0
  5. package/dist/chunk-4TZDDT63.cjs +4 -0
  6. package/dist/chunk-4TZDDT63.cjs.map +1 -0
  7. package/dist/chunk-ARYO7BLK.js +16 -0
  8. package/dist/chunk-ARYO7BLK.js.map +1 -0
  9. package/dist/chunk-MAWPOW4D.js +4 -0
  10. package/dist/chunk-MAWPOW4D.js.map +1 -0
  11. package/dist/{debug-timeline-Dn1lC_gK.d.cts → debug-timeline-DpnRMnLU.d.cts} +1 -1
  12. package/dist/{debug-timeline-BGcPa0JO.d.ts → debug-timeline-L13P-U2I.d.ts} +1 -1
  13. package/dist/devtools.d.cts +5 -5
  14. package/dist/devtools.d.ts +5 -5
  15. package/dist/evals.d.cts +2 -2
  16. package/dist/evals.d.ts +2 -2
  17. package/dist/gemini.d.cts +1 -1
  18. package/dist/gemini.d.ts +1 -1
  19. package/dist/guardrails.cjs +1 -1
  20. package/dist/guardrails.cjs.map +1 -1
  21. package/dist/guardrails.d.cts +645 -21
  22. package/dist/guardrails.d.ts +645 -21
  23. package/dist/guardrails.js +1 -1
  24. package/dist/guardrails.js.map +1 -1
  25. package/dist/{health-monitor-Cq5sDvid.d.cts → health-monitor-C6xoXrQz.d.cts} +1 -1
  26. package/dist/{health-monitor-DtwmIJkb.d.ts → health-monitor-qL9RNMH3.d.ts} +1 -1
  27. package/dist/index.cjs +11 -11
  28. package/dist/index.d.cts +10 -10
  29. package/dist/index.d.ts +10 -10
  30. package/dist/index.js +11 -11
  31. package/dist/index.js.map +1 -1
  32. package/dist/multi-agent.d.cts +6 -6
  33. package/dist/multi-agent.d.ts +6 -6
  34. package/dist/ollama.d.cts +1 -1
  35. package/dist/ollama.d.ts +1 -1
  36. package/dist/openai.d.cts +2 -2
  37. package/dist/openai.d.ts +2 -2
  38. package/dist/{orchestrator-types-s0766dDB.d.cts → orchestrator-types-C-sgbBQX.d.cts} +20 -3
  39. package/dist/{orchestrator-types-C5D5JZUj.d.ts → orchestrator-types-CX1PqpKR.d.ts} +20 -3
  40. package/dist/predicate.d.cts +1 -1
  41. package/dist/predicate.d.ts +1 -1
  42. package/dist/{semantic-cache-Ba0-jEwb.d.cts → semantic-cache-DM7ev7NQ.d.cts} +1 -1
  43. package/dist/{semantic-cache-Ba0-jEwb.d.ts → semantic-cache-DM7ev7NQ.d.ts} +1 -1
  44. package/dist/testing.cjs +1 -1
  45. package/dist/testing.d.cts +4 -4
  46. package/dist/testing.d.ts +4 -4
  47. package/dist/testing.js +1 -1
  48. package/dist/{types-CUp1N0uU.d.cts → types-DJ09LjZX.d.cts} +1 -1
  49. package/dist/{types-CUp1N0uU.d.ts → types-DJ09LjZX.d.ts} +1 -1
  50. package/package.json +2 -2
  51. package/dist/ann-index-27QV9tPC.d.ts +0 -616
  52. package/dist/ann-index-HoZFIUA-.d.cts +0 -616
  53. package/dist/chunk-2PG26JZU.cjs +0 -16
  54. package/dist/chunk-2PG26JZU.cjs.map +0 -1
  55. package/dist/chunk-BFSRYCOS.js +0 -4
  56. package/dist/chunk-BFSRYCOS.js.map +0 -1
  57. package/dist/chunk-CAA6Q4YY.cjs +0 -4
  58. package/dist/chunk-CAA6Q4YY.cjs.map +0 -1
  59. package/dist/chunk-MIHH5GPT.js +0 -16
  60. package/dist/chunk-MIHH5GPT.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/builtin-guardrails.ts","../src/guardrails/pii-enhanced.ts","../src/guardrails/prompt-injection.ts","../src/guardrails/semantic-cache.ts","../src/guardrails/ann-index.ts"],"names":["createPIIGuardrail","options","patterns","redact","redactReplacement","data","text","hasPII","pattern","createModerationGuardrail","checkFn","message","flagged","createRateLimitGuardrail","maxTokensPerMinute","maxRequestsPerMinute","maxEntries","tokenTimestamps","requestTimestamps","windowMs","findCutoffIndex","arr","cutoffTime","low","high","mid","guardrail","_data","context","now","tokenCutoff","requestCutoff","tokenUsage","AGENT_KEY","recentTokens","recentRequests","createToolGuardrail","allowlist","denylist","caseSensitive","normalizedAllowlist","t","normalizedDenylist","toolName","createOutputSchemaGuardrail","validate","errorPrefix","result","createOutputTypeGuardrail","type","requiredFields","minLength","maxLength","minStringLength","maxStringLength","output","field","createLengthGuardrail","maxCharacters","maxTokens","estimateTokens","safeStringify","tokens","createContentFilterGuardrail","blockedPatterns","compiledPatterns","p","escaped","PII_PATTERNS","match","digits","sum","isEven","i","char","digit","octets","a","b","detectAddresses","results","streetTypes","addressPattern","NAME_PREFIXES","detectNames","prefixPattern","nameRegex","name","prefix","MAX_PII_INPUT_LENGTH","matchPattern","regex","group","value","start","end","regexDetector","types","typeSet","SENSITIVE_CATEGORY_TYPES","hasValidSpan","item","textLength","buildRedactionReplacement","style","fnv1aHash","redactPII","items","byPriority","aSpan","bSpan","kept","k","sorted","replacement","str","hash","DEFAULT_PII_TYPES","createEnhancedPIIGuardrail","detector","redactionStyle","minConfidence","onDetected","minItemsToBlock","detectorTimeout","detectorInstance","allowSet","v","detectWithTimeout","piiTypes","timer","detectPromise","timeoutPromise","_","reject","filtered","typeCounts","count","createOutputPIIGuardrail","inputGuardrail","detectPII","timeout","detectAndRedactPII","DEFAULT_INJECTION_PATTERNS","STRICT_INJECTION_PATTERNS","MAX_INJECTION_INPUT_LENGTH","detectPromptInjection","matches","severity","category","severityScores","totalScore","m","riskScore","sanitizeInjection","sanitized","allPatterns","hasGlobal","hasIgnoreCase","hasMultiline","flags","combinedRegex","createPromptInjectionGuardrail","additionalPatterns","replacePatterns","strictMode","blockThreshold","sanitize","onBlocked","ignoreCategories","ignoredSet","topPatterns","order","markUntrustedContent","content","source","createUntrustedContentGuardrail","baseGuardrail","untrustedMarkerRegex","fullResult","strictResult","cosineSimilarity","dotProduct","normA","normB","ai","bi","findSimilar","queryEmbedding","entries","threshold","agentName","bestMatch","entry","similarity","createInMemoryStorage","storage","getNamespace","namespace","ns","id","updates","createSemanticCache","config","embedder","similarityThreshold","maxCacheSize","ttlMs","onHit","onMiss","onError","perAgent","stats","totalSimilaritySum","updateStats","times","e","evictExpiredAndExcess","remainingEntries","toRemove","query","error","response","metadata","predicate","removed","allEntries","createSemanticCacheGuardrail","cache","createTestEmbedder","dimensions","embedding","charCode","norm","val","createBatchedEmbedder","batchSize","embedBatch","maxWaitMs","pendingBatch","batchTimer","isDestroyed","flushBatch","batch","texts","embeddings","err","resolve","createBruteForceIndex","vectors","expectedDimension","validateDimension","cosineDistance","buildVPTree","random","vpIdx","vp","rest","distances","medianIdx","mu","leftItems","d","rightItems","searchVPTree","node","maxDist","dist","createVPTreeIndex","vpConfig","root","needsRebuild","itemArray"],"mappings":"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","file":"chunk-BFSRYCOS.js","sourcesContent":["/**\n * Built-in guardrails for AI adapter — PII, moderation, rate limiting, tool allowlists, schema validation.\n */\n\nimport type {\n AgentState,\n GuardrailFn,\n InputGuardrailData,\n OutputGuardrailData,\n SchemaValidator,\n ToolCallGuardrailData,\n} from \"./types.js\";\nimport { AGENT_KEY } from \"./types.js\";\n\nimport { safeStringify } from \"@directive-run/core/internals\";\n\n// ============================================================================\n// PII Guardrail\n// ============================================================================\n\n/**\n * Create a PII detection guardrail that scans input text for personally identifiable\n * information. Blocks input when PII is detected, or optionally redacts matches and\n * passes the sanitized text through.\n *\n * @param options - Configuration for PII detection: `patterns` sets the RegExp list (defaults to SSN, credit card, email), `redact` replaces matches instead of blocking, `redactReplacement` sets the replacement string (defaults to `\"[REDACTED]\"`).\n * @returns An input guardrail that blocks or redacts PII in user input.\n *\n * @example\n * ```typescript\n * const piiGuardrail = createPIIGuardrail({\n * patterns: [\n * /\\b\\d{3}-\\d{2}-\\d{4}\\b/, // SSN\n * /\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}\\b/i, // Email\n * ],\n * redact: true,\n * });\n * ```\n *\n * @public\n */\nexport function createPIIGuardrail(options: {\n patterns?: RegExp[];\n redact?: boolean;\n redactReplacement?: string;\n}): GuardrailFn<InputGuardrailData> {\n const {\n patterns = [\n /\\b\\d{3}-\\d{2}-\\d{4}\\b/g, // SSN\n /\\b\\d{16}\\b/g, // Credit card\n /\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}\\b/gi, // Email\n ],\n redact = false,\n redactReplacement = \"[REDACTED]\",\n } = options;\n\n return (data) => {\n let text = data.input;\n let hasPII = false;\n\n for (const pattern of patterns) {\n pattern.lastIndex = 0;\n if (pattern.test(text)) {\n hasPII = true;\n if (redact) {\n pattern.lastIndex = 0;\n text = text.replace(pattern, redactReplacement);\n }\n }\n }\n\n if (hasPII && !redact) {\n return { passed: false, reason: \"Input contains PII\" };\n }\n\n return { passed: true, transformed: redact && hasPII ? text : undefined };\n };\n}\n\n// ============================================================================\n// Moderation Guardrail\n// ============================================================================\n\n/**\n * Create a content moderation guardrail that delegates to a user-supplied check function.\n * Works on both input and output data — the guardrail extracts the text content\n * automatically and passes it to {@link options.checkFn}.\n *\n * @param options - Configuration for content moderation: `checkFn` returns `true` when content should be flagged (supports async), `message` sets the rejection reason (defaults to `\"Content flagged by moderation\"`).\n * @returns A guardrail that blocks content flagged by the check function.\n *\n * @example\n * ```typescript\n * const moderationGuardrail = createModerationGuardrail({\n * checkFn: async (text) => {\n * const result = await openai.moderations.create({ input: text });\n * return result.results[0].flagged;\n * },\n * });\n * ```\n *\n * @public\n */\nexport function createModerationGuardrail(options: {\n checkFn: (text: string) => boolean | Promise<boolean>;\n message?: string;\n}): GuardrailFn<InputGuardrailData | OutputGuardrailData> {\n const { checkFn, message = \"Content flagged by moderation\" } = options;\n\n return async (data) => {\n const text =\n \"output\" in data\n ? typeof data.output === \"string\"\n ? data.output\n : JSON.stringify(data.output)\n : data.input;\n\n const flagged = await checkFn(text);\n\n return { passed: !flagged, reason: flagged ? message : undefined };\n };\n}\n\n// ============================================================================\n// Rate Limit Guardrail\n// ============================================================================\n\n/** Rate limiter with reset capability for testing */\nexport interface RateLimitGuardrail extends GuardrailFn<InputGuardrailData> {\n reset(): void;\n}\n\n/**\n * Create a rate limit guardrail that tracks token and request counts over a sliding\n * one-minute window. Returns a {@link RateLimitGuardrail} — a guardrail function with\n * an additional `reset()` method for testing.\n *\n * @param options - Configuration for rate limiting: `maxTokensPerMinute` caps tokens in the sliding window (defaults to `100000`), `maxRequestsPerMinute` caps requests (defaults to `60`).\n * @returns A rate limit guardrail with an attached `reset()` method.\n *\n * @example\n * ```typescript\n * const rateLimiter = createRateLimitGuardrail({\n * maxTokensPerMinute: 50000,\n * maxRequestsPerMinute: 30,\n * });\n * ```\n *\n * @public\n */\nexport function createRateLimitGuardrail(options: {\n maxTokensPerMinute?: number;\n maxRequestsPerMinute?: number;\n}): RateLimitGuardrail {\n const { maxTokensPerMinute = 100000, maxRequestsPerMinute = 60 } = options;\n\n const maxEntries = Math.max(maxRequestsPerMinute, 1000);\n let tokenTimestamps: number[] = [];\n let requestTimestamps: number[] = [];\n const windowMs = 60000;\n\n function findCutoffIndex(arr: number[], cutoffTime: number): number {\n let low = 0;\n let high = arr.length;\n while (low < high) {\n const mid = (low + high) >>> 1;\n if ((arr[mid] ?? 0) < cutoffTime) {\n low = mid + 1;\n } else {\n high = mid;\n }\n }\n return low;\n }\n\n const guardrail: RateLimitGuardrail = (_data, context) => {\n const now = Date.now();\n const cutoffTime = now - windowMs;\n\n const tokenCutoff = findCutoffIndex(tokenTimestamps, cutoffTime);\n if (tokenCutoff > 0) {\n tokenTimestamps = tokenTimestamps.slice(tokenCutoff);\n }\n\n const requestCutoff = findCutoffIndex(requestTimestamps, cutoffTime);\n if (requestCutoff > 0) {\n requestTimestamps = requestTimestamps.slice(requestCutoff);\n }\n\n const factsObj = context.facts as Record<string, unknown>;\n const agentState = factsObj[AGENT_KEY] as AgentState | undefined;\n const tokenUsage = agentState?.tokenUsage ?? 0;\n const recentTokens = tokenTimestamps.length;\n const recentRequests = requestTimestamps.length;\n\n if (recentTokens + tokenUsage > maxTokensPerMinute) {\n return { passed: false, reason: \"Token rate limit exceeded\" };\n }\n\n if (recentRequests >= maxRequestsPerMinute) {\n return { passed: false, reason: \"Request rate limit exceeded\" };\n }\n\n if (requestTimestamps.length < maxEntries) {\n requestTimestamps.push(now);\n }\n if (tokenTimestamps.length < maxEntries) {\n tokenTimestamps.push(now);\n }\n\n return { passed: true };\n };\n\n guardrail.reset = () => {\n tokenTimestamps = [];\n requestTimestamps = [];\n };\n\n return guardrail;\n}\n\n// ============================================================================\n// Tool Guardrail\n// ============================================================================\n\n/**\n * Create a tool-call guardrail that restricts which tools an agent may invoke.\n * Supports allowlist mode, denylist mode, or both — when both are provided, a tool\n * must appear in the allowlist and not appear in the denylist.\n *\n * @param options - Configuration for tool filtering: `allowlist` sets permitted tool names, `denylist` sets blocked tool names, `caseSensitive` controls case matching (defaults to `false`).\n * @returns A tool-call guardrail that enforces the allowlist/denylist rules.\n *\n * @example\n * ```typescript\n * const toolGuardrail = createToolGuardrail({\n * allowlist: [\"search\", \"calculate\"],\n * denylist: [\"delete_account\"],\n * });\n * ```\n *\n * @public\n */\nexport function createToolGuardrail(options: {\n allowlist?: string[];\n denylist?: string[];\n /** @default false */\n caseSensitive?: boolean;\n}): GuardrailFn<ToolCallGuardrailData> {\n const { allowlist, denylist, caseSensitive = false } = options;\n\n const normalizedAllowlist = allowlist?.map((t) =>\n caseSensitive ? t : t.toLowerCase(),\n );\n const normalizedDenylist = denylist?.map((t) =>\n caseSensitive ? t : t.toLowerCase(),\n );\n\n return (data) => {\n const toolName = caseSensitive\n ? data.toolCall.name\n : data.toolCall.name.toLowerCase();\n\n if (normalizedAllowlist && !normalizedAllowlist.includes(toolName)) {\n return {\n passed: false,\n reason: `Tool \"${data.toolCall.name}\" not in allowlist`,\n };\n }\n\n if (normalizedDenylist?.includes(toolName)) {\n return {\n passed: false,\n reason: `Tool \"${data.toolCall.name}\" is blocked`,\n };\n }\n\n return { passed: true };\n };\n}\n\n// ============================================================================\n// Output Schema Guardrail\n// ============================================================================\n\n/**\n * Create an output guardrail that validates agent output against a schema using\n * a user-supplied {@link SchemaValidator}. Compatible with any validation library\n * (Zod, Valibot, ArkType, etc.) via the adapter pattern.\n *\n * @param options - Configuration for schema validation: `validate` checks the output against the expected schema, `errorPrefix` is prepended to error messages (defaults to `\"Output schema validation failed\"`).\n * @returns An output guardrail that rejects output failing schema validation.\n *\n * @example\n * ```typescript\n * import { z } from \"zod\";\n *\n * const schemaGuardrail = createOutputSchemaGuardrail({\n * validate: (value) => {\n * const result = z.object({ answer: z.string() }).safeParse(value);\n * return { valid: result.success, errors: result.error?.issues.map(i => i.message) };\n * },\n * });\n * ```\n *\n * @public\n */\nexport function createOutputSchemaGuardrail<T = unknown>(options: {\n validate: SchemaValidator<T>;\n errorPrefix?: string;\n}): GuardrailFn<OutputGuardrailData> {\n const { validate, errorPrefix = \"Output schema validation failed\" } = options;\n\n return (data) => {\n const result = validate(data.output);\n\n if (typeof result === \"boolean\") {\n return {\n passed: result,\n reason: result ? undefined : errorPrefix,\n };\n }\n\n if (result.valid) {\n return { passed: true };\n }\n\n const errorMessage = result.errors?.length\n ? `${errorPrefix}: ${result.errors.join(\"; \")}`\n : errorPrefix;\n\n return { passed: false, reason: errorMessage };\n };\n}\n\n// ============================================================================\n// Output Type Guardrail\n// ============================================================================\n\n/**\n * Create an output guardrail that performs lightweight runtime type checks without\n * requiring a schema library. Supports `\"string\"`, `\"number\"`, `\"boolean\"`, `\"object\"`,\n * and `\"array\"` with optional size and field constraints.\n *\n * @param options - Configuration for type checking: `type` sets the expected JS type, `requiredFields` lists object keys that must exist, `minLength`/`maxLength` constrain array size, `minStringLength`/`maxStringLength` constrain string length.\n * @returns An output guardrail that rejects output not matching the expected type or constraints.\n *\n * @example\n * ```typescript\n * const typeGuardrail = createOutputTypeGuardrail({\n * type: \"object\",\n * requiredFields: [\"id\", \"name\"],\n * });\n * ```\n *\n * @public\n */\nexport function createOutputTypeGuardrail(options: {\n type: \"string\" | \"number\" | \"boolean\" | \"object\" | \"array\";\n requiredFields?: string[];\n minLength?: number;\n maxLength?: number;\n minStringLength?: number;\n maxStringLength?: number;\n}): GuardrailFn<OutputGuardrailData> {\n const {\n type,\n requiredFields = [],\n minLength,\n maxLength,\n minStringLength,\n maxStringLength,\n } = options;\n\n return (data) => {\n const output = data.output;\n\n switch (type) {\n case \"string\":\n if (typeof output !== \"string\") {\n return {\n passed: false,\n reason: `Expected string, got ${typeof output}`,\n };\n }\n if (minStringLength !== undefined && output.length < minStringLength) {\n return {\n passed: false,\n reason: `String too short: ${output.length} < ${minStringLength}`,\n };\n }\n if (maxStringLength !== undefined && output.length > maxStringLength) {\n return {\n passed: false,\n reason: `String too long: ${output.length} > ${maxStringLength}`,\n };\n }\n return { passed: true };\n\n case \"number\":\n if (typeof output !== \"number\" || Number.isNaN(output)) {\n return {\n passed: false,\n reason: `Expected number, got ${typeof output}`,\n };\n }\n return { passed: true };\n\n case \"boolean\":\n if (typeof output !== \"boolean\") {\n return {\n passed: false,\n reason: `Expected boolean, got ${typeof output}`,\n };\n }\n return { passed: true };\n\n case \"object\":\n if (\n typeof output !== \"object\" ||\n output === null ||\n Array.isArray(output)\n ) {\n return {\n passed: false,\n reason: `Expected object, got ${Array.isArray(output) ? \"array\" : typeof output}`,\n };\n }\n for (const field of requiredFields) {\n if (!(field in output)) {\n return {\n passed: false,\n reason: `Missing required field: ${field}`,\n };\n }\n }\n return { passed: true };\n\n case \"array\":\n if (!Array.isArray(output)) {\n return {\n passed: false,\n reason: `Expected array, got ${typeof output}`,\n };\n }\n if (minLength !== undefined && output.length < minLength) {\n return {\n passed: false,\n reason: `Array too short: ${output.length} < ${minLength}`,\n };\n }\n if (maxLength !== undefined && output.length > maxLength) {\n return {\n passed: false,\n reason: `Array too long: ${output.length} > ${maxLength}`,\n };\n }\n return { passed: true };\n\n default:\n return { passed: false, reason: `Unknown type: ${type}` };\n }\n };\n}\n\n// ============================================================================\n// Length Guardrail\n// ============================================================================\n\n/**\n * Create an output guardrail that enforces maximum length constraints on agent output,\n * measured in characters or estimated tokens.\n *\n * @param options - Configuration for length limits: `maxCharacters` caps character count, `maxTokens` caps estimated token count, `estimateTokens` provides a custom token estimator (defaults to `Math.ceil(text.length / 4)`).\n * @returns An output guardrail that rejects output exceeding the configured length limits.\n *\n * @example\n * ```typescript\n * const lengthGuardrail = createLengthGuardrail({\n * maxCharacters: 5000,\n * maxTokens: 1200,\n * });\n * ```\n *\n * @public\n */\nexport function createLengthGuardrail(options: {\n /** Maximum characters in output */\n maxCharacters?: number;\n /** Maximum estimated tokens in output */\n maxTokens?: number;\n /** Custom token estimator (default: chars / 4) */\n estimateTokens?: (text: string) => number;\n}): GuardrailFn<OutputGuardrailData> {\n const {\n maxCharacters,\n maxTokens,\n estimateTokens = (text: string) => Math.ceil(text.length / 4),\n } = options;\n\n return (data) => {\n const text = safeStringify(data.output);\n\n if (maxCharacters !== undefined && text.length > maxCharacters) {\n return {\n passed: false,\n reason: `Output too long: ${text.length} characters (max: ${maxCharacters})`,\n };\n }\n\n if (maxTokens !== undefined) {\n const tokens = estimateTokens(text);\n if (tokens > maxTokens) {\n return {\n passed: false,\n reason: `Output too long: ~${tokens} tokens (max: ${maxTokens})`,\n };\n }\n }\n\n return { passed: true };\n };\n}\n\n// ============================================================================\n// Content Filter Guardrail\n// ============================================================================\n\n/**\n * Create an output guardrail that blocks content matching any of the provided patterns.\n * String patterns are escaped and compiled to RegExp; RegExp patterns are used as-is.\n *\n * @remarks\n * A warning is logged when `blockedPatterns` is empty, since an empty list means no\n * content will ever be filtered.\n *\n * @param options - Configuration for content filtering: `blockedPatterns` lists strings or RegExps to match against output, `caseSensitive` controls case matching for string patterns (defaults to `false`).\n * @returns An output guardrail that rejects output containing any blocked pattern.\n *\n * @example\n * ```typescript\n * const contentFilter = createContentFilterGuardrail({\n * blockedPatterns: [\n * /\\bpassword\\b/i,\n * /\\bsecret\\b/i,\n * 'internal-only',\n * ],\n * });\n * ```\n *\n * @public\n */\nexport function createContentFilterGuardrail(options: {\n /** Patterns to block — strings or RegExp */\n blockedPatterns: Array<string | RegExp>;\n /** Case-sensitive matching for string patterns (default: false) */\n caseSensitive?: boolean;\n}): GuardrailFn<OutputGuardrailData> {\n const { blockedPatterns, caseSensitive = false } = options;\n\n if (blockedPatterns.length === 0) {\n console.warn(\n \"[Directive] createContentFilterGuardrail: blockedPatterns is empty — no content will be filtered\",\n );\n }\n\n const compiledPatterns = blockedPatterns.map((p) => {\n if (p instanceof RegExp) return p;\n const escaped = p.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n return new RegExp(escaped, caseSensitive ? \"g\" : \"gi\");\n });\n\n return (data) => {\n const text = safeStringify(data.output);\n\n for (const pattern of compiledPatterns) {\n pattern.lastIndex = 0; // Reset required for global flags across iterations\n if (pattern.test(text)) {\n return {\n passed: false,\n reason: `Output contains blocked content matching: ${pattern.source}`,\n };\n }\n }\n\n return { passed: true };\n };\n}\n","/**\n * Enhanced PII Detection Guardrail\n *\n * Provides comprehensive PII detection beyond basic regex patterns:\n * - Multiple PII types (SSN, credit cards, emails, phones, addresses, names)\n * - Pluggable detection backends (regex, custom, or external services)\n * - Context-aware detection (reduces false positives)\n * - Redaction with reversible or irreversible options\n *\n * @example\n * ```typescript\n * import { createEnhancedPIIGuardrail } from '@directive-run/ai';\n *\n * const guardrail = createEnhancedPIIGuardrail({\n * types: ['ssn', 'credit_card', 'email'],\n * redact: true,\n * detector: 'regex', // or 'custom' with custom detector\n * });\n * ```\n */\n\nimport type {\n GuardrailFn,\n GuardrailResult,\n InputGuardrailData,\n OutputGuardrailData,\n} from \"../types.js\";\n\n// ============================================================================\n// PII Types\n// ============================================================================\n\n/** Supported PII types */\nexport type PIIType =\n | \"ssn\" // Social Security Number\n | \"credit_card\" // Credit/debit card numbers\n | \"email\" // Email addresses\n | \"phone\" // Phone numbers (various formats)\n | \"address\" // Physical addresses\n | \"name\" // Personal names (requires context)\n | \"date_of_birth\" // Birth dates\n | \"passport\" // Passport numbers\n | \"driver_license\" // Driver's license numbers\n | \"ip_address\" // IP addresses\n | \"bank_account\" // Bank account numbers\n | \"medical_id\" // Medical record numbers\n | \"national_id\"; // Non-US national IDs\n\n/** Detected PII instance */\nexport interface DetectedPII {\n type: PIIType;\n value: string;\n position: { start: number; end: number };\n confidence: number; // 0-1\n context?: string; // Surrounding text for debugging\n}\n\n/** PII detection result */\nexport interface PIIDetectionResult {\n detected: boolean;\n items: DetectedPII[];\n typeCounts: Partial<Record<PIIType, number>>;\n /** Text with PII redacted (if requested) */\n redactedText?: string;\n}\n\n// ============================================================================\n// Regex Patterns\n// ============================================================================\n\n/** PII pattern with validation */\ninterface PIIPattern {\n type: PIIType;\n pattern: RegExp;\n /**\n * Capture group holding the PII value itself. Defaults to 1.\n * Keyword-anchored patterns set this to 2 — group 1 is the keyword\n * (\"account\", \"passport\", …) and group 2 is the actual identifier.\n * `value` is read from this group; the redacted span still covers the\n * whole match (keyword included) so the category is not re-disclosed.\n */\n valueGroup?: number;\n /** Additional validation function (reduces false positives) */\n validate?: (match: string, context: string) => boolean;\n /** Confidence score (0-1) */\n confidence: number;\n}\n\n/** Comprehensive PII patterns */\nconst PII_PATTERNS: PIIPattern[] = [\n // SSN - US Social Security Number\n {\n type: \"ssn\",\n pattern: /\\b(\\d{3}[-\\s]?\\d{2}[-\\s]?\\d{4})\\b/g,\n validate: (match) => {\n // Remove separators and validate format\n const digits = match.replace(/[-\\s]/g, \"\");\n // SSN cannot start with 000, 666, or 9xx\n if (\n digits.startsWith(\"000\") ||\n digits.startsWith(\"666\") ||\n digits.startsWith(\"9\")\n ) {\n return false;\n }\n // Middle 2 digits cannot be 00\n if (digits.slice(3, 5) === \"00\") {\n return false;\n }\n // Last 4 digits cannot be 0000\n if (digits.slice(5) === \"0000\") {\n return false;\n }\n return true;\n },\n confidence: 0.95,\n },\n\n // Credit Card Numbers (Luhn validated)\n {\n type: \"credit_card\",\n // One capture group wraps both branches so the value group is always 1\n // (default valueGroup): the 4-4-4-4 separated grouping, or an unseparated\n // \\d{13,19} run matching the Luhn validator's 13-19 range (previously\n // \\d{15,16} left 13/14/17/18/19-digit PANs undetected).\n pattern: /\\b((?:\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4})|\\d{13,19})\\b/g,\n validate: (match) => {\n const digits = match.replace(/[-\\s]/g, \"\");\n if (digits.length < 13 || digits.length > 19) return false;\n // Luhn algorithm\n let sum = 0;\n let isEven = false;\n for (let i = digits.length - 1; i >= 0; i--) {\n const char = digits[i];\n if (!char) continue;\n let digit = Number.parseInt(char, 10);\n if (isEven) {\n digit *= 2;\n if (digit > 9) digit -= 9;\n }\n sum += digit;\n isEven = !isEven;\n }\n return sum % 10 === 0;\n },\n confidence: 0.95,\n },\n\n // Email addresses\n {\n type: \"email\",\n pattern: /\\b([A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,})\\b/gi,\n confidence: 0.9,\n },\n\n // Phone numbers (US/NANP only — not international)\n {\n type: \"phone\",\n // Matches US/NANP formats only: (555) 555-5555, 555-555-5555,\n // +1 555 555 5555. Does NOT support non-NANP international numbers.\n pattern: /\\b(\\+?1?[-.\\s]?\\(?[0-9]{3}\\)?[-.\\s]?[0-9]{3}[-.\\s]?[0-9]{4})\\b/g,\n validate: (match) => {\n const digits = match.replace(/\\D/g, \"\");\n // US numbers should be 10 or 11 digits\n return digits.length >= 10 && digits.length <= 11;\n },\n confidence: 0.8,\n },\n\n // Date of birth patterns\n {\n type: \"date_of_birth\",\n // Various formats: MM/DD/YYYY, YYYY-MM-DD, DD-MM-YYYY\n pattern:\n /\\b(born|dob|birth.?date|date.?of.?birth)[:.\\s]+(\\d{1,4}[-/]\\d{1,2}[-/]\\d{1,4})\\b/gi,\n valueGroup: 2,\n confidence: 0.85,\n },\n\n // IP addresses (IPv4 only — IPv6 deferred)\n {\n type: \"ip_address\",\n pattern: /\\b(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})\\b/g,\n validate: (match) => {\n const parts = match.split(\".\");\n const octets = parts.map((p) => Number.parseInt(p, 10));\n // Each octet must be a valid 0-255 number\n if (octets.some((n) => Number.isNaN(n) || n < 0 || n > 255)) {\n return false;\n }\n const [a, b] = octets as [number, number, number, number];\n // Skip non-PII infrastructure noise: RFC1918 private ranges,\n // loopback, link-local, and the unspecified/broadcast addresses.\n if (a === 10) return false; // 10.0.0.0/8 private\n if (a === 172 && b >= 16 && b <= 31) return false; // 172.16.0.0/12 private\n if (a === 192 && b === 168) return false; // 192.168.0.0/16 private\n if (a === 127) return false; // 127.0.0.0/8 loopback\n if (a === 169 && b === 254) return false; // 169.254.0.0/16 link-local\n if (match === \"0.0.0.0\" || match === \"255.255.255.255\") return false;\n\n return true;\n },\n confidence: 0.9,\n },\n\n // Bank account numbers (generic)\n {\n type: \"bank_account\",\n // Account number followed by routing or preceded by \"account\"\n pattern: /\\b(account|acct)[\\s#:]+(\\d{8,17})\\b/gi,\n valueGroup: 2,\n confidence: 0.7,\n },\n\n // Passport numbers (various countries)\n {\n type: \"passport\",\n // US passports: 9 digits, UK: 9 digits, etc.\n pattern: /\\b(passport)[\\s#:]+([A-Z0-9]{6,9})\\b/gi,\n valueGroup: 2,\n confidence: 0.75,\n },\n\n // Driver's license (US - state specific patterns would be better)\n {\n type: \"driver_license\",\n pattern: /\\b(driver'?s?\\s*licen[cs]e|dl)[\\s#:]+([A-Z0-9]{5,15})\\b/gi,\n valueGroup: 2,\n confidence: 0.7,\n },\n\n // Medical record numbers\n {\n type: \"medical_id\",\n pattern: /\\b(mrn|medical.?record|patient.?id)[\\s#:]+([A-Z0-9-]{6,15})\\b/gi,\n valueGroup: 2,\n confidence: 0.7,\n },\n\n // National IDs (non-US) — keyword-anchored, alphanumeric ID 6-20 chars\n {\n type: \"national_id\",\n pattern:\n /\\b(national.?id|nin|identity.?number|identity.?card|id.?number)[\\s#:]+([A-Z0-9-]{6,20})\\b/gi,\n valueGroup: 2,\n confidence: 0.85,\n },\n];\n\n// ============================================================================\n// Address Detection\n// ============================================================================\n\n/** Detect US physical addresses */\nfunction detectAddresses(text: string): DetectedPII[] {\n const results: DetectedPII[] = [];\n\n // Simplified US address pattern to avoid ReDoS\n // Matches: \"123 Main Street, City, CA 12345\" or similar\n // Uses possessive-like matching and limits word count to prevent catastrophic backtracking\n const streetTypes =\n \"street|st|avenue|ave|road|rd|drive|dr|lane|ln|court|ct|way|boulevard|blvd|circle|cir|place|pl\";\n const addressPattern = new RegExp(\n `\\\\b(\\\\d{1,5}\\\\s+(?:\\\\w+\\\\s+){1,4}(?:${streetTypes})\\\\b[^\\\\n]{0,50}\\\\b[A-Z]{2}\\\\s+\\\\d{5}(?:-\\\\d{4})?)\\\\b`,\n \"gi\",\n );\n\n let match: RegExpExecArray | null;\n while ((match = addressPattern.exec(text)) !== null) {\n results.push({\n type: \"address\",\n value: match[0],\n position: { start: match.index, end: match.index + match[0].length },\n confidence: 0.7, // Lower confidence due to simpler pattern\n });\n }\n\n return results;\n}\n\n// ============================================================================\n// Name Detection (Context-Aware)\n// ============================================================================\n\n/** Common prefixes that indicate names */\nconst NAME_PREFIXES = [\n \"mr\",\n \"mrs\",\n \"ms\",\n \"miss\",\n \"dr\",\n \"prof\",\n \"sir\",\n \"madam\",\n \"name is\",\n \"called\",\n \"known as\",\n \"signed by\",\n \"from\",\n \"dear\",\n \"hi\",\n \"hello\",\n \"contact\",\n \"recipient\",\n];\n\n/** Detect personal names (requires context) */\nfunction detectNames(text: string): DetectedPII[] {\n const results: DetectedPII[] = [];\n\n // Simplified name pattern to avoid ReDoS\n // Matches: \"Mr. John Smith\" or \"name is Jane Doe\"\n // Uses non-capturing groups and limits repetition\n const prefixPattern = NAME_PREFIXES.join(\"|\");\n const nameRegex = new RegExp(\n `\\\\b(${prefixPattern})[.,:]?\\\\s+([A-Z][a-z]{1,20}(?:\\\\s[A-Z][a-z]{1,20}){0,2})\\\\b`,\n \"gi\",\n );\n\n let match: RegExpExecArray | null;\n\n while ((match = nameRegex.exec(text)) !== null) {\n const name = match[2];\n const prefix = match[1];\n // Skip if name is undefined\n if (!name) continue;\n // Ignore single-word names that might be common words\n if (\n name.split(/\\s+/).length >= 2 ||\n (prefix && NAME_PREFIXES.some((p) => prefix.toLowerCase().includes(p)))\n ) {\n results.push({\n type: \"name\",\n value: name,\n position: { start: match.index, end: match.index + match[0].length },\n confidence: 0.6,\n context: match[0],\n });\n }\n }\n\n return results;\n}\n\n// ============================================================================\n// Detection Backend Types\n// ============================================================================\n\n/** Maximum input length for PII detection (100KB) */\nconst MAX_PII_INPUT_LENGTH = 100_000;\n\n/** Custom PII detector interface */\nexport interface PIIDetector {\n detect(text: string, types: PIIType[]): Promise<DetectedPII[]>;\n name: string;\n}\n\n/**\n * Run a single PII pattern over `text` and collect every (validated) match.\n * `position` spans the FULL match: for keyword-anchored patterns the keyword\n * is redacted along with the identifier, so the redacted output never\n * re-discloses the PII category (e.g. \"MRN: ABC123\" → \"[REDACTED]\"). `value`\n * reports just the identifier (the value group) for masking/hashing/allowlist.\n */\nfunction matchPattern(pattern: PIIPattern, text: string): DetectedPII[] {\n const results: DetectedPII[] = [];\n const regex = new RegExp(pattern.pattern.source, pattern.pattern.flags);\n const group = pattern.valueGroup ?? 1;\n let match: RegExpExecArray | null;\n\n // biome-ignore lint/suspicious/noAssignInExpressions: standard regex.exec loop\n while ((match = regex.exec(text)) !== null) {\n const value = match[group] ?? match[0];\n const start = match.index;\n const end = match.index + match[0].length;\n const context = text.slice(Math.max(0, start - 20), end + 20);\n\n if (pattern.validate && !pattern.validate(value, context)) {\n continue;\n }\n\n results.push({\n type: pattern.type,\n value,\n position: { start, end },\n confidence: pattern.confidence,\n context,\n });\n }\n\n return results;\n}\n\n/** Built-in regex detector */\nexport const regexDetector: PIIDetector = {\n name: \"regex\",\n async detect(text: string, types: PIIType[]): Promise<DetectedPII[]> {\n // Security: Prevent DoS via extremely large inputs\n if (text.length > MAX_PII_INPUT_LENGTH) {\n throw new Error(\n `[Directive] Input exceeds maximum length of ${MAX_PII_INPUT_LENGTH} characters for PII detection. Truncate input or process in chunks.`,\n );\n }\n\n const results: DetectedPII[] = [];\n const typeSet = new Set(types);\n\n // Pattern-based detection\n for (const pattern of PII_PATTERNS) {\n if (typeSet.has(pattern.type)) {\n results.push(...matchPattern(pattern, text));\n }\n }\n\n // Address detection (separate logic)\n if (typeSet.has(\"address\")) {\n results.push(...detectAddresses(text));\n }\n\n // Name detection (context-aware)\n if (typeSet.has(\"name\")) {\n results.push(...detectNames(text));\n }\n\n return results;\n },\n};\n\n// ============================================================================\n// Redaction Functions\n// ============================================================================\n\n/** Redaction style */\nexport type RedactionStyle =\n /** Replace with [REDACTED] */\n | \"placeholder\"\n /** Replace with type-specific placeholder like [EMAIL] */\n | \"typed\"\n /**\n * Replace with a fixed-width `****` mask plus the last 4 characters\n * (e.g. `****6789`). Does not preserve or reveal the original length.\n */\n | \"masked\"\n /**\n * Replace with a deterministic FNV-1a hash.\n *\n * **WARNING — this is PSEUDONYMIZATION, not anonymization.** FNV-1a is a\n * fast, non-cryptographic 32-bit hash. For low-entropy structured PII (SSNs,\n * card numbers, phone numbers) the output is trivially RE-IDENTIFIABLE via\n * brute force or a precomputed rainbow table. It MUST NOT be relied on for\n * GDPR / HIPAA de-identification. Use it only for referential integrity\n * (correlating the same value across audit logs).\n */\n | \"hashed\";\n\n/**\n * PII types whose *category name* is itself sensitive. For these, `typed`\n * redaction emits a generic `[REDACTED]` instead of the type name so the\n * redacted text does not reveal that the user has, e.g., an SSN, a credit\n * card, a medical record, a passport, or a bank account on file. Only the\n * mundane contact/network types (email, phone, name, address, ip_address)\n * keep their `[TYPE]` label.\n */\nconst SENSITIVE_CATEGORY_TYPES: ReadonlySet<PIIType> = new Set<PIIType>([\n \"ssn\",\n \"credit_card\",\n \"date_of_birth\",\n \"medical_id\",\n \"national_id\",\n \"passport\",\n \"driver_license\",\n \"bank_account\",\n]);\n\n/** Whether a detected item's span is a valid, in-bounds slice of `text`. */\nfunction hasValidSpan(item: DetectedPII, textLength: number): boolean {\n const { start, end } = item.position;\n\n return (\n Number.isInteger(start) &&\n Number.isInteger(end) &&\n start >= 0 &&\n start < end &&\n end <= textLength\n );\n}\n\n/** Build the replacement string for one detected item under a given style. */\nfunction buildRedactionReplacement(\n item: DetectedPII,\n style: RedactionStyle,\n): string {\n switch (style) {\n case \"placeholder\":\n return \"[REDACTED]\";\n case \"typed\":\n // For sensitive-category types, emit a generic [REDACTED] — the\n // category name itself would otherwise reveal the presence of, e.g.,\n // medical, passport, or national-ID data.\n return SENSITIVE_CATEGORY_TYPES.has(item.type)\n ? \"[REDACTED]\"\n : `[${item.type.toUpperCase()}]`;\n case \"masked\": {\n // A full-length `*` run would reveal the exact digit count of\n // structured PII. Use a fixed-width `****` mask. Only a credit-card\n // PAN may show a last-4 tail (PCI-permitted for display); the tail\n // is digit-normalized so separators never leak. Every other type —\n // SSN especially, whose last 4 are an auth token — is fully masked.\n if (item.type !== \"credit_card\") {\n return \"****\";\n }\n\n const digits = item.value.replace(/\\D/g, \"\");\n\n return `****${digits.length > 4 ? digits.slice(-4) : \"\"}`;\n }\n case \"hashed\":\n // FNV-1a hash for referential integrity (not for security). Same\n // input always produces same hash, useful for audit trails.\n return `[HASH:${fnv1aHash(item.value)}]`;\n }\n}\n\n/** Redact detected PII from text */\nexport function redactPII(\n text: string,\n items: DetectedPII[],\n style: RedactionStyle = \"typed\",\n): string {\n // Items may come from an untrusted custom PIIDetector. Drop any with a\n // malformed span before splicing — a negative, fractional, out-of-range,\n // or inverted range would corrupt offsets and could re-expose raw PII.\n const safeItems = items.filter((item) => hasValidSpan(item, text.length));\n\n // The same span can be matched by multiple patterns (e.g. a 16-digit\n // number flagged as both credit_card and phone). Splicing overlapping\n // or nested ranges shifts offsets and can leave raw PII in the output.\n // Dedupe order-independently: sort by confidence (then longer span,\n // then earlier start) so the strongest match claims its range first,\n // and keep a later item only if it overlaps nothing already kept. This\n // handles chains of three or more overlapping spans.\n const byPriority = [...safeItems].sort((a, b) => {\n if (b.confidence !== a.confidence) {\n return b.confidence - a.confidence;\n }\n\n const aSpan = a.position.end - a.position.start;\n const bSpan = b.position.end - b.position.start;\n if (bSpan !== aSpan) {\n return bSpan - aSpan;\n }\n\n return a.position.start - b.position.start;\n });\n\n const kept: DetectedPII[] = [];\n for (const item of byPriority) {\n const overlaps = kept.some(\n (k) =>\n item.position.start < k.position.end &&\n k.position.start < item.position.end,\n );\n\n if (!overlaps) {\n kept.push(item);\n }\n }\n\n // Redact the surviving non-overlapping set descending by start so earlier\n // splices do not shift the offsets of later ones.\n const sorted = kept.sort((a, b) => b.position.start - a.position.start);\n\n let result = text;\n for (const item of sorted) {\n const replacement = buildRedactionReplacement(item, style);\n\n result =\n result.slice(0, item.position.start) +\n replacement +\n result.slice(item.position.end);\n }\n\n return result;\n}\n\n/**\n * FNV-1a hash function for referential integrity.\n *\n * **WARNING — PSEUDONYMIZATION, NOT ANONYMIZATION.** This is NOT a\n * cryptographic hash. FNV-1a 32-bit is fast and unkeyed, so for low-entropy\n * structured PII (SSNs, card numbers, phone numbers) the hash is trivially\n * RE-IDENTIFIABLE by brute force or a precomputed rainbow table. The output\n * MUST NOT be treated as de-identified data under GDPR or HIPAA.\n *\n * It is designed only for:\n * - Consistent redaction references (same PII → same hash)\n * - Audit trail correlation (track redacted values across logs)\n *\n * For security-sensitive hashing, use a keyed cryptographic hash via the\n * Web Crypto API externally.\n *\n * @see https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function\n */\nfunction fnv1aHash(str: string): string {\n // FNV-1a 32-bit parameters\n const FNV_PRIME = 0x01000193;\n const FNV_OFFSET = 0x811c9dc5;\n\n let hash = FNV_OFFSET;\n for (let i = 0; i < str.length; i++) {\n hash ^= str.charCodeAt(i);\n hash = Math.imul(hash, FNV_PRIME);\n }\n\n // Convert to unsigned 32-bit and return as hex\n return (hash >>> 0).toString(16).padStart(8, \"0\");\n}\n\n// ============================================================================\n// Guardrail Factory\n// ============================================================================\n\n/** Options for enhanced PII guardrail */\nexport interface EnhancedPIIGuardrailOptions {\n /** PII types to detect (default: all) */\n types?: PIIType[];\n /** Detection backend (default: 'regex') */\n detector?: \"regex\" | PIIDetector;\n /** Redact instead of blocking */\n redact?: boolean;\n /** Redaction style (default: 'typed') */\n redactionStyle?: RedactionStyle;\n /** Minimum confidence to flag (0-1, default: 0.7) */\n minConfidence?: number;\n /** Callback when PII is detected */\n onDetected?: (items: DetectedPII[]) => void;\n /** Allow specific values (whitelist) */\n allowlist?: string[];\n /** Block only if count exceeds threshold */\n minItemsToBlock?: number;\n /** Timeout for custom detector in milliseconds (default: 5000) */\n detectorTimeout?: number;\n}\n\n/** Default PII types to detect */\nconst DEFAULT_PII_TYPES: PIIType[] = [\n \"ssn\",\n \"credit_card\",\n \"email\",\n \"phone\",\n \"date_of_birth\",\n \"bank_account\",\n];\n\n/**\n * Create an enhanced PII detection guardrail.\n *\n * @example\n * ```typescript\n * // Basic usage\n * const guardrail = createEnhancedPIIGuardrail();\n *\n * // Redact instead of blocking\n * const redactGuardrail = createEnhancedPIIGuardrail({\n * redact: true,\n * redactionStyle: 'masked',\n * });\n *\n * // Custom detection with external service\n * const customGuardrail = createEnhancedPIIGuardrail({\n * detector: myPresidioDetector,\n * types: ['ssn', 'credit_card', 'medical_id'],\n * });\n * ```\n */\nexport function createEnhancedPIIGuardrail(\n options: EnhancedPIIGuardrailOptions = {},\n): GuardrailFn<InputGuardrailData> {\n const {\n types = DEFAULT_PII_TYPES,\n detector = \"regex\",\n redact = false,\n redactionStyle = \"typed\",\n minConfidence = 0.7,\n onDetected,\n allowlist = [],\n minItemsToBlock = 1,\n detectorTimeout = 5000,\n } = options;\n\n const detectorInstance = detector === \"regex\" ? regexDetector : detector;\n // Normalize allowlist: lowercase and trim for consistent comparison\n const allowSet = new Set(allowlist.map((v) => v.toLowerCase().trim()));\n\n // Wrap detector with timeout to prevent DoS via slow external services\n async function detectWithTimeout(\n text: string,\n piiTypes: PIIType[],\n ): Promise<DetectedPII[]> {\n // Built-in regex detector doesn't need timeout (it's synchronous)\n if (detectorInstance === regexDetector) {\n return detectorInstance.detect(text, piiTypes);\n }\n\n // Custom detectors get a timeout. Whichever promise loses the race\n // still settles afterwards — attach a no-op .catch() to each so the\n // loser's rejection (timeout firing after detector wins, or detector\n // throwing after timeout wins) never surfaces as an unhandledRejection.\n let timer: ReturnType<typeof setTimeout>;\n const detectPromise = detectorInstance.detect(text, piiTypes);\n const timeoutPromise = new Promise<never>((_, reject) => {\n timer = setTimeout(\n () =>\n reject(\n new Error(\n `[Directive] PII detector '${detectorInstance.name}' timed out after ${detectorTimeout}ms`,\n ),\n ),\n detectorTimeout,\n );\n });\n detectPromise.catch(() => {});\n timeoutPromise.catch(() => {});\n try {\n return await Promise.race([detectPromise, timeoutPromise]);\n } finally {\n clearTimeout(timer!);\n }\n }\n\n return async (data): Promise<GuardrailResult> => {\n const items = await detectWithTimeout(data.input, types);\n\n // Filter by confidence and allowlist (normalize value for comparison)\n const filtered = items.filter((item) => {\n if (item.confidence < minConfidence) return false;\n // Normalize detected value for allowlist comparison\n if (allowSet.has(item.value.toLowerCase().trim())) return false;\n return true;\n });\n\n if (filtered.length > 0) {\n onDetected?.(filtered);\n }\n\n if (filtered.length >= minItemsToBlock) {\n if (redact) {\n const redactedText = redactPII(data.input, filtered, redactionStyle);\n return {\n passed: true,\n transformed: redactedText,\n };\n }\n\n const typeCounts: Record<string, number> = {};\n for (const item of filtered) {\n typeCounts[item.type] = (typeCounts[item.type] || 0) + 1;\n }\n\n const summary = Object.entries(typeCounts)\n .map(([type, count]) => `${type}: ${count}`)\n .join(\", \");\n\n return {\n passed: false,\n reason: `PII detected (${summary})`,\n };\n }\n\n return { passed: true };\n };\n}\n\n/**\n * Create an output PII guardrail (for checking agent responses).\n *\n * @example\n * ```typescript\n * const outputGuardrail = createOutputPIIGuardrail({\n * types: ['ssn', 'credit_card'],\n * redact: true,\n * });\n * ```\n */\nexport function createOutputPIIGuardrail(\n options: EnhancedPIIGuardrailOptions = {},\n): GuardrailFn<OutputGuardrailData> {\n const inputGuardrail = createEnhancedPIIGuardrail(options);\n\n return async (data, context): Promise<GuardrailResult> => {\n const text =\n typeof data.output === \"string\"\n ? data.output\n : JSON.stringify(data.output);\n\n return inputGuardrail({ input: text, agentName: data.agentName }, context);\n };\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Detect PII in text without using as a guardrail.\n * Useful for analysis and logging.\n *\n * @example\n * ```typescript\n * const result = await detectPII('My SSN is 123-45-6789');\n * console.log(result.items); // [{ type: 'ssn', value: '123-45-6789', ... }]\n *\n * // With custom detector and timeout\n * const result = await detectPII(text, {\n * detector: myPresidioDetector,\n * timeout: 10000, // 10 seconds\n * });\n * ```\n */\nexport async function detectPII(\n text: string,\n options: {\n types?: PIIType[];\n detector?: \"regex\" | PIIDetector;\n minConfidence?: number;\n /** Timeout for custom detectors in milliseconds (default: 5000) */\n timeout?: number;\n } = {},\n): Promise<PIIDetectionResult> {\n const {\n types = DEFAULT_PII_TYPES,\n detector = \"regex\",\n minConfidence = 0.7,\n timeout = 5000,\n } = options;\n\n const detectorInstance = detector === \"regex\" ? regexDetector : detector;\n\n // Apply timeout for custom detectors to prevent DoS\n let items: DetectedPII[];\n if (detectorInstance === regexDetector) {\n // Built-in regex detector is synchronous, no timeout needed\n items = await detectorInstance.detect(text, types);\n } else {\n // Custom detectors get a timeout. Attach a no-op .catch() to each\n // racer so the losing promise's rejection (timeout after detector\n // wins, or detector throwing after timeout wins) never surfaces as\n // an unhandledRejection.\n let timer: ReturnType<typeof setTimeout>;\n const detectPromise = detectorInstance.detect(text, types);\n const timeoutPromise = new Promise<never>((_, reject) => {\n timer = setTimeout(\n () =>\n reject(\n new Error(\n `[Directive] PII detector '${detectorInstance.name}' timed out after ${timeout}ms`,\n ),\n ),\n timeout,\n );\n });\n detectPromise.catch(() => {});\n timeoutPromise.catch(() => {});\n try {\n items = await Promise.race([detectPromise, timeoutPromise]);\n } finally {\n clearTimeout(timer!);\n }\n }\n\n const filtered = items.filter((item) => item.confidence >= minConfidence);\n\n const typeCounts: Partial<Record<PIIType, number>> = {};\n for (const item of filtered) {\n typeCounts[item.type] = (typeCounts[item.type] || 0) + 1;\n }\n\n return {\n detected: filtered.length > 0,\n items: filtered,\n typeCounts,\n };\n}\n\n/**\n * Detect PII in text and return a result whose `redactedText` is populated.\n *\n * This composes {@link detectPII} and {@link redactPII} so callers do not have\n * to manually wire the two together (and do not have to mutate the detection\n * result). When no PII is detected, `redactedText` is left `undefined` — it is\n * deliberately NOT defaulted to the raw input.\n *\n * @example\n * ```typescript\n * const result = await detectAndRedactPII('My SSN is 123-45-6789', {\n * types: ['ssn'],\n * style: 'typed',\n * });\n * console.log(result.detected); // true\n * // ssn is a sensitive-category type, so `typed` emits a generic [REDACTED]\n * console.log(result.redactedText); // 'My SSN is [REDACTED]'\n *\n * const clean = await detectAndRedactPII('nothing here', { types: ['ssn'] });\n * console.log(clean.detected); // false\n * console.log(clean.redactedText); // undefined\n * ```\n */\nexport async function detectAndRedactPII(\n text: string,\n options: {\n types?: PIIType[];\n detector?: \"regex\" | PIIDetector;\n minConfidence?: number;\n /** Timeout for custom detectors in milliseconds (default: 5000) */\n timeout?: number;\n /** Redaction style applied when PII is detected (default: 'typed') */\n style?: RedactionStyle;\n } = {},\n): Promise<PIIDetectionResult> {\n const result = await detectPII(text, options);\n\n if (!result.detected) {\n return { ...result };\n }\n\n return {\n ...result,\n redactedText: redactPII(text, result.items, options.style ?? \"typed\"),\n };\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport {\n detectPII as detect,\n redactPII as redact,\n createEnhancedPIIGuardrail as create,\n createOutputPIIGuardrail as createOutput,\n};\n","/**\n * Prompt Injection Detection Guardrail\n *\n * Detects and blocks prompt injection attacks including:\n * - Direct injection attempts (\"ignore previous instructions\")\n * - Jailbreak patterns (\"DAN mode\", \"pretend you can\")\n * - Indirect injection via external content\n * - Encoding-based evasion attempts\n *\n * @example\n * ```typescript\n * import { createPromptInjectionGuardrail } from '@directive-run/ai';\n *\n * const guardrail = createPromptInjectionGuardrail({\n * strictMode: true,\n * onBlocked: (input, patterns) => logSecurityEvent(input, patterns),\n * });\n * ```\n */\n\nimport type {\n GuardrailFn,\n GuardrailResult,\n InputGuardrailData,\n} from \"../types.js\";\n\n// ============================================================================\n// Pattern Categories\n// ============================================================================\n\n/** Pattern with metadata for better debugging */\nexport interface InjectionPattern {\n pattern: RegExp;\n name: string;\n severity: \"low\" | \"medium\" | \"high\" | \"critical\";\n category: InjectionCategory;\n}\n\n/** Categories of injection attacks */\nexport type InjectionCategory =\n | \"instruction_override\" // \"ignore previous instructions\"\n | \"jailbreak\" // \"DAN mode\", \"pretend you can\"\n | \"role_manipulation\" // \"you are now\", \"act as\"\n | \"encoding_evasion\" // base64, rot13, unicode tricks\n | \"delimiter_injection\" // XML/JSON injection, markdown escape\n | \"context_manipulation\" // \"system:\", \"assistant:\", fake messages\n | \"indirect_injection\"; // URL loading, file inclusion\n\n// ============================================================================\n// Built-in Patterns\n// ============================================================================\n\n/** Default injection patterns - well-tested and low false-positive rate */\nexport const DEFAULT_INJECTION_PATTERNS: InjectionPattern[] = [\n // Instruction override patterns\n {\n pattern:\n /ignore\\s+(all\\s+)?(previous|prior|above|earlier)\\s+(instructions?|prompts?|rules?|guidelines?)/i,\n name: \"ignore-previous\",\n severity: \"critical\",\n category: \"instruction_override\",\n },\n {\n pattern:\n /disregard\\s+(all\\s+)?(previous|prior|above|earlier)\\s+(instructions?|prompts?)/i,\n name: \"disregard-previous\",\n severity: \"critical\",\n category: \"instruction_override\",\n },\n {\n pattern:\n /forget\\s+(all\\s+)?(previous|prior|above|earlier)\\s+(instructions?|prompts?)/i,\n name: \"forget-previous\",\n severity: \"critical\",\n category: \"instruction_override\",\n },\n {\n pattern: /override\\s+(the\\s+)?(system|base)\\s+(prompt|instructions?)/i,\n name: \"override-system\",\n severity: \"critical\",\n category: \"instruction_override\",\n },\n\n // Jailbreak patterns\n {\n pattern: /\\bDAN\\s+(mode|jailbreak)\\b/i,\n name: \"dan-mode\",\n severity: \"critical\",\n category: \"jailbreak\",\n },\n {\n pattern: /\\bjailbreak(ed)?\\s*(mode)?\\b/i,\n name: \"jailbreak-keyword\",\n severity: \"high\",\n category: \"jailbreak\",\n },\n {\n pattern: /developer\\s+mode\\s+(enabled|activated|on)/i,\n name: \"developer-mode\",\n severity: \"critical\",\n category: \"jailbreak\",\n },\n {\n pattern:\n /pretend\\s+(you\\s+)?(are|can|have)\\s+(no\\s+)?(restrictions?|limits?|boundaries?|ethics)/i,\n name: \"pretend-no-restrictions\",\n severity: \"high\",\n category: \"jailbreak\",\n },\n {\n pattern:\n /you\\s+(now\\s+)?have\\s+no\\s+(ethical\\s+)?(restrictions?|guidelines?|boundaries?)/i,\n name: \"no-restrictions\",\n severity: \"high\",\n category: \"jailbreak\",\n },\n\n // Role manipulation\n {\n pattern: /you\\s+are\\s+now\\s+(a|an)\\s+\\w+\\s+(that|who)\\s+(can|will|must)/i,\n name: \"role-assignment\",\n severity: \"medium\",\n category: \"role_manipulation\",\n },\n {\n pattern: /from\\s+now\\s+on,?\\s+(you\\s+)?(will|must|should)\\s+(only\\s+)?/i,\n name: \"from-now-on\",\n severity: \"medium\",\n category: \"role_manipulation\",\n },\n\n // Context manipulation (fake message markers)\n {\n pattern: /^(system|assistant|user):\\s*/im,\n name: \"fake-role-marker\",\n severity: \"high\",\n category: \"context_manipulation\",\n },\n {\n pattern: /<\\|?(system|endofprompt|im_start|im_end)\\|?>/i,\n name: \"special-token-injection\",\n severity: \"critical\",\n category: \"context_manipulation\",\n },\n\n // Delimiter injection\n {\n pattern: /```(system|assistant|instructions?)\\n/i,\n name: \"markdown-code-injection\",\n severity: \"medium\",\n category: \"delimiter_injection\",\n },\n {\n pattern: /<system>|<\\/system>|<instructions?>|<\\/instructions?>/i,\n name: \"xml-tag-injection\",\n severity: \"high\",\n category: \"delimiter_injection\",\n },\n\n // Indirect injection indicators\n {\n pattern: /fetch\\s+(content\\s+)?(from|at)\\s+(the\\s+)?url/i,\n name: \"url-fetch-instruction\",\n severity: \"medium\",\n category: \"indirect_injection\",\n },\n {\n pattern: /execute\\s+(the\\s+)?(code|script|command)\\s+(from|in|at)/i,\n name: \"execute-from-source\",\n severity: \"high\",\n category: \"indirect_injection\",\n },\n];\n\n/** Strict patterns - more aggressive, may have higher false positives */\nexport const STRICT_INJECTION_PATTERNS: InjectionPattern[] = [\n ...DEFAULT_INJECTION_PATTERNS,\n\n // Additional strict patterns\n {\n pattern: /act\\s+as\\s+(if\\s+)?(you\\s+)?(were|are|can)/i,\n name: \"act-as\",\n severity: \"low\",\n category: \"role_manipulation\",\n },\n {\n pattern: /new\\s+instructions?:/i,\n name: \"new-instructions\",\n severity: \"medium\",\n category: \"instruction_override\",\n },\n {\n pattern: /\\[system\\]|\\[admin\\]|\\[developer\\]/i,\n name: \"bracket-role-marker\",\n severity: \"medium\",\n category: \"context_manipulation\",\n },\n {\n pattern: /base64|rot13|decode\\s+(this|the)/i,\n name: \"encoding-reference\",\n severity: \"low\",\n category: \"encoding_evasion\",\n },\n {\n pattern: /\\u200b|\\u200c|\\u200d|\\u2060|\\ufeff/,\n name: \"zero-width-chars\",\n severity: \"medium\",\n category: \"encoding_evasion\",\n },\n];\n\n// ============================================================================\n// Detection Result Types\n// ============================================================================\n\n/** Detailed detection result */\nexport interface InjectionDetectionResult {\n detected: boolean;\n patterns: Array<{\n name: string;\n category: InjectionCategory;\n severity: InjectionPattern[\"severity\"];\n match: string;\n position: number;\n }>;\n riskScore: number; // 0-100\n sanitizedInput?: string;\n}\n\n// ============================================================================\n// Core Detection Function\n// ============================================================================\n\n/** Maximum input length for injection detection (100KB) */\nconst MAX_INJECTION_INPUT_LENGTH = 100_000;\n\n/**\n * Detect prompt injection patterns in text.\n * Returns detailed results about what was detected.\n *\n * @throws Error if input exceeds MAX_INJECTION_INPUT_LENGTH (100KB)\n */\nexport function detectPromptInjection(\n text: string,\n patterns: InjectionPattern[] = DEFAULT_INJECTION_PATTERNS,\n): InjectionDetectionResult {\n // Security: Prevent DoS via extremely large inputs\n if (text.length > MAX_INJECTION_INPUT_LENGTH) {\n throw new Error(\n `[Directive] Input exceeds maximum length of ${MAX_INJECTION_INPUT_LENGTH} characters for injection detection. Truncate input or process in chunks.`,\n );\n }\n\n const matches: InjectionDetectionResult[\"patterns\"] = [];\n\n for (const { pattern, name, severity, category } of patterns) {\n // Reset regex state\n const regex = new RegExp(pattern.source, pattern.flags);\n const match = regex.exec(text);\n\n if (match) {\n matches.push({\n name,\n category,\n severity,\n match: match[0],\n position: match.index,\n });\n }\n }\n\n // Calculate risk score based on severity and number of matches\n const severityScores = {\n low: 10,\n medium: 25,\n high: 50,\n critical: 100,\n };\n\n const totalScore = matches.reduce(\n (sum, m) => sum + severityScores[m.severity],\n 0,\n );\n const riskScore = Math.min(100, totalScore);\n\n return {\n detected: matches.length > 0,\n patterns: matches,\n riskScore,\n };\n}\n\n/**\n * Sanitize text by removing detected injection patterns.\n * Warning: This is a best-effort sanitization, not a security guarantee.\n *\n * Uses a single-pass approach to prevent infinite loops where a replacement\n * could create a new pattern match.\n */\nexport function sanitizeInjection(\n text: string,\n patterns: InjectionPattern[] = DEFAULT_INJECTION_PATTERNS,\n): string {\n // Remove zero-width characters first (always safe)\n let sanitized = text.replace(/\\u200b|\\u200c|\\u200d|\\u2060|\\ufeff/g, \"\");\n\n // Build a combined regex for single-pass replacement to prevent\n // infinite loops where \"[REDACTED]\" could match another pattern\n const allPatterns = patterns.map((p) => `(${p.pattern.source})`);\n if (allPatterns.length === 0) return sanitized;\n\n // Combine all patterns with alternation, using the most permissive flags\n const hasGlobal = patterns.some((p) => p.pattern.flags.includes(\"g\"));\n const hasIgnoreCase = patterns.some((p) => p.pattern.flags.includes(\"i\"));\n const hasMultiline = patterns.some((p) => p.pattern.flags.includes(\"m\"));\n\n const flags = `${hasGlobal ? \"g\" : \"\"}${hasIgnoreCase ? \"i\" : \"\"}${hasMultiline ? \"m\" : \"\"}`;\n const combinedRegex = new RegExp(allPatterns.join(\"|\"), flags || \"gi\");\n\n // Single-pass replacement prevents cascade issues\n sanitized = sanitized.replace(combinedRegex, \"[REDACTED]\");\n\n return sanitized;\n}\n\n// ============================================================================\n// Guardrail Factory\n// ============================================================================\n\n/** Options for prompt injection guardrail */\nexport interface PromptInjectionGuardrailOptions {\n /** Additional patterns to check (added to defaults) */\n additionalPatterns?: InjectionPattern[];\n /** Replace default patterns entirely */\n replacePatterns?: InjectionPattern[];\n /** Use strict mode with more aggressive detection */\n strictMode?: boolean;\n /** Minimum risk score to block (0-100, default: 50) */\n blockThreshold?: number;\n /** Attempt to sanitize instead of blocking */\n sanitize?: boolean;\n /** Callback when injection is detected */\n onBlocked?: (input: string, result: InjectionDetectionResult) => void;\n /** Categories to ignore (e.g., allow 'role_manipulation' for roleplay apps) */\n ignoreCategories?: InjectionCategory[];\n}\n\n/**\n * Create a prompt injection detection guardrail.\n *\n * @example\n * ```typescript\n * // Basic usage\n * const guardrail = createPromptInjectionGuardrail();\n *\n * // Strict mode for high-security applications\n * const strictGuardrail = createPromptInjectionGuardrail({\n * strictMode: true,\n * blockThreshold: 25,\n * });\n *\n * // Allow role manipulation for roleplay apps\n * const roleplayGuardrail = createPromptInjectionGuardrail({\n * ignoreCategories: ['role_manipulation'],\n * });\n * ```\n */\nexport function createPromptInjectionGuardrail(\n options: PromptInjectionGuardrailOptions = {},\n): GuardrailFn<InputGuardrailData> {\n const {\n additionalPatterns = [],\n replacePatterns,\n strictMode = false,\n blockThreshold = 50,\n sanitize = false,\n onBlocked,\n ignoreCategories = [],\n } = options;\n\n // Build pattern list\n let patterns: InjectionPattern[];\n if (replacePatterns) {\n patterns = replacePatterns;\n } else {\n patterns = strictMode\n ? [...STRICT_INJECTION_PATTERNS]\n : [...DEFAULT_INJECTION_PATTERNS];\n }\n patterns = [...patterns, ...additionalPatterns];\n\n // Filter out ignored categories\n if (ignoreCategories.length > 0) {\n const ignoredSet = new Set(ignoreCategories);\n patterns = patterns.filter((p) => !ignoredSet.has(p.category));\n }\n\n return (data): GuardrailResult => {\n const result = detectPromptInjection(data.input, patterns);\n\n if (result.detected && result.riskScore >= blockThreshold) {\n onBlocked?.(data.input, result);\n\n if (sanitize) {\n const sanitized = sanitizeInjection(data.input, patterns);\n return {\n passed: true,\n transformed: sanitized,\n };\n }\n\n const topPatterns = result.patterns\n .sort((a, b) => {\n const order = { critical: 0, high: 1, medium: 2, low: 3 };\n return order[a.severity] - order[b.severity];\n })\n .slice(0, 3)\n .map((p) => p.name)\n .join(\", \");\n\n return {\n passed: false,\n reason: `Prompt injection detected (risk: ${result.riskScore}%, patterns: ${topPatterns})`,\n };\n }\n\n return { passed: true };\n };\n}\n\n// ============================================================================\n// Indirect Injection Defense\n// ============================================================================\n\n/**\n * Mark content as potentially untrusted (from external sources).\n * This wraps the content with markers that injection detection will scrutinize more closely.\n *\n * @example\n * ```typescript\n * const userUpload = await readFile(path);\n * const markedContent = markUntrustedContent(userUpload, 'user-upload');\n * const prompt = `Summarize this document: ${markedContent}`;\n * ```\n */\nexport function markUntrustedContent(content: string, source: string): string {\n // Use a delimiter that's unlikely to appear in normal content\n // and that injection patterns will trigger on\n return `[UNTRUSTED_CONTENT source=\"${source}\"]\\n${content}\\n[/UNTRUSTED_CONTENT]`;\n}\n\n/**\n * Create a guardrail that applies stricter checks to marked untrusted content.\n *\n * @example\n * ```typescript\n * const guardrail = createUntrustedContentGuardrail({\n * baseGuardrail: createPromptInjectionGuardrail({ strictMode: true }),\n * });\n * ```\n */\nexport function createUntrustedContentGuardrail(options: {\n /** Guardrail to apply to untrusted sections */\n baseGuardrail?: GuardrailFn<InputGuardrailData>;\n /** Block if untrusted content contains these patterns */\n additionalPatterns?: InjectionPattern[];\n}): GuardrailFn<InputGuardrailData> {\n const {\n baseGuardrail = createPromptInjectionGuardrail({\n strictMode: true,\n blockThreshold: 25,\n }),\n additionalPatterns = [],\n } = options;\n\n const untrustedMarkerRegex =\n /\\[UNTRUSTED_CONTENT source=\"([^\"]+)\"\\]([\\s\\S]*?)\\[\\/UNTRUSTED_CONTENT\\]/g;\n\n return async (data, context): Promise<GuardrailResult> => {\n // First, check the entire input\n const fullResult = await baseGuardrail(data, context);\n if (!fullResult.passed) {\n return fullResult;\n }\n\n // Then, apply additional scrutiny to untrusted sections\n const matches = data.input.matchAll(untrustedMarkerRegex);\n for (const match of matches) {\n const [, source, content] = match;\n\n // Skip if content is undefined\n if (!content) continue;\n\n // Check with stricter patterns\n const strictResult = detectPromptInjection(content, [\n ...STRICT_INJECTION_PATTERNS,\n ...additionalPatterns,\n ]);\n\n if (strictResult.detected && strictResult.riskScore >= 25) {\n return {\n passed: false,\n reason: `Untrusted content from \"${source}\" contains potential injection (risk: ${strictResult.riskScore}%)`,\n };\n }\n }\n\n return { passed: true };\n };\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport {\n detectPromptInjection as detect,\n sanitizeInjection as sanitize,\n createPromptInjectionGuardrail as create,\n};\n","/**\n * Semantic Caching Guardrail\n *\n * Caches agent responses based on semantic similarity to reduce redundant LLM calls.\n * Uses vector embeddings to find semantically similar previous queries.\n *\n * @example\n * ```typescript\n * import { createSemanticCacheGuardrail } from '@directive-run/ai';\n *\n * const cacheGuardrail = createSemanticCacheGuardrail({\n * embedder: async (text) => {\n * // Use your embedding model (OpenAI, local model, etc.)\n * return await getEmbedding(text);\n * },\n * similarityThreshold: 0.95,\n * maxCacheSize: 1000,\n * ttlMs: 3600000, // 1 hour\n * });\n *\n * const orchestrator = createAgentOrchestrator({\n * guardrails: {\n * input: [cacheGuardrail],\n * },\n * runner: run,\n * });\n * ```\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** Vector embedding (array of numbers) */\nexport type Embedding = number[];\n\n/** Function to generate embeddings for text */\nexport type EmbedderFn = (text: string) => Promise<Embedding>;\n\n/** Cached response entry */\nexport interface CacheEntry {\n id: string;\n query: string;\n queryEmbedding: Embedding;\n response: string;\n metadata: Record<string, unknown>;\n createdAt: number;\n accessedAt: number;\n accessCount: number;\n agentName?: string;\n}\n\n/** Cache lookup result */\nexport interface CacheLookupResult {\n hit: boolean;\n entry?: CacheEntry;\n similarity?: number;\n latencyMs: number;\n}\n\n/** Semantic cache configuration */\nexport interface SemanticCacheConfig {\n /** Function to generate embeddings */\n embedder: EmbedderFn;\n /** Similarity threshold (0.0 to 1.0) for cache hits */\n similarityThreshold?: number;\n /** Maximum number of entries to cache */\n maxCacheSize?: number;\n /** Time-to-live in milliseconds for cache entries */\n ttlMs?: number;\n /** Cache namespace for multi-tenant scenarios */\n namespace?: string;\n /** Custom storage backend (defaults to in-memory) */\n storage?: SemanticCacheStorage;\n /** Callback when cache hit occurs */\n onHit?: (entry: CacheEntry, similarity: number) => void;\n /** Callback when cache miss occurs */\n onMiss?: (query: string) => void;\n /** Callback when cache lookup encounters an error */\n onError?: (error: Error) => void;\n /** Whether to include agent name in cache key */\n perAgent?: boolean;\n}\n\n/** Storage interface for cache backends */\nexport interface SemanticCacheStorage {\n /** Get all entries for a namespace */\n getEntries(namespace: string): Promise<CacheEntry[]>;\n /** Add an entry to the cache */\n addEntry(namespace: string, entry: CacheEntry): Promise<void>;\n /** Update an entry (e.g., access count) */\n updateEntry(\n namespace: string,\n id: string,\n updates: Partial<CacheEntry>,\n ): Promise<void>;\n /** Remove an entry */\n removeEntry(namespace: string, id: string): Promise<void>;\n /** Clear all entries in a namespace */\n clear(namespace: string): Promise<void>;\n}\n\n/** Semantic cache instance */\nexport interface SemanticCache {\n /** Look up a query in the cache */\n lookup(query: string, agentName?: string): Promise<CacheLookupResult>;\n /** Store a response in the cache */\n store(\n query: string,\n response: string,\n agentName?: string,\n metadata?: Record<string, unknown>,\n ): Promise<void>;\n /** Invalidate cache entries matching a predicate */\n invalidate(predicate: (entry: CacheEntry) => boolean): Promise<number>;\n /** Clear all cache entries */\n clear(): Promise<void>;\n /** Get cache statistics */\n getStats(): CacheStats;\n /** Export cache entries (for persistence) */\n export(): Promise<CacheEntry[]>;\n /** Import cache entries (from persistence) */\n import(entries: CacheEntry[]): Promise<void>;\n}\n\n/** Cache statistics */\nexport interface CacheStats {\n totalEntries: number;\n totalHits: number;\n totalMisses: number;\n hitRate: number;\n avgSimilarityOnHit: number;\n oldestEntry: number | null;\n newestEntry: number | null;\n}\n\n// ============================================================================\n// Vector Math Utilities\n// ============================================================================\n\n/**\n * Calculate cosine similarity between two vectors.\n */\nexport function cosineSimilarity(a: Embedding, b: Embedding): number {\n if (a.length !== b.length) {\n throw new Error(`Vector dimensions must match: ${a.length} vs ${b.length}`);\n }\n\n let dotProduct = 0;\n let normA = 0;\n let normB = 0;\n\n for (let i = 0; i < a.length; i++) {\n const ai = a[i]!; // Safe: i is within bounds\n const bi = b[i]!; // Safe: dimensions match and i is within bounds\n dotProduct += ai * bi;\n normA += ai * ai;\n normB += bi * bi;\n }\n\n normA = Math.sqrt(normA);\n normB = Math.sqrt(normB);\n\n if (normA === 0 || normB === 0) {\n return 0;\n }\n\n return dotProduct / (normA * normB);\n}\n\n/**\n * Find the most similar entries to a query embedding.\n */\nfunction findSimilar(\n queryEmbedding: Embedding,\n entries: CacheEntry[],\n threshold: number,\n agentName?: string,\n): { entry: CacheEntry; similarity: number } | null {\n let bestMatch: { entry: CacheEntry; similarity: number } | null = null;\n\n for (const entry of entries) {\n // Filter by agent if specified\n if (agentName && entry.agentName && entry.agentName !== agentName) {\n continue;\n }\n\n const similarity = cosineSimilarity(queryEmbedding, entry.queryEmbedding);\n\n if (similarity >= threshold) {\n if (!bestMatch || similarity > bestMatch.similarity) {\n bestMatch = { entry, similarity };\n }\n }\n }\n\n return bestMatch;\n}\n\n// ============================================================================\n// In-Memory Storage\n// ============================================================================\n\n/**\n * Create an in-memory cache storage backend.\n */\nexport function createInMemoryStorage(): SemanticCacheStorage {\n const storage = new Map<string, Map<string, CacheEntry>>();\n\n function getNamespace(namespace: string): Map<string, CacheEntry> {\n let ns = storage.get(namespace);\n if (!ns) {\n ns = new Map();\n storage.set(namespace, ns);\n }\n return ns;\n }\n\n return {\n async getEntries(namespace: string): Promise<CacheEntry[]> {\n return Array.from(getNamespace(namespace).values());\n },\n\n async addEntry(namespace: string, entry: CacheEntry): Promise<void> {\n getNamespace(namespace).set(entry.id, entry);\n },\n\n async updateEntry(\n namespace: string,\n id: string,\n updates: Partial<CacheEntry>,\n ): Promise<void> {\n const ns = getNamespace(namespace);\n const entry = ns.get(id);\n if (entry) {\n ns.set(id, { ...entry, ...updates });\n }\n },\n\n async removeEntry(namespace: string, id: string): Promise<void> {\n getNamespace(namespace).delete(id);\n },\n\n async clear(namespace: string): Promise<void> {\n storage.delete(namespace);\n },\n };\n}\n\n// ============================================================================\n// Semantic Cache Factory\n// ============================================================================\n\n/**\n * Create a semantic cache instance.\n *\n * @example\n * ```typescript\n * const cache = createSemanticCache({\n * embedder: async (text) => {\n * const response = await openai.embeddings.create({\n * model: 'text-embedding-3-small',\n * input: text,\n * });\n * return response.data[0].embedding;\n * },\n * similarityThreshold: 0.92,\n * maxCacheSize: 500,\n * ttlMs: 3600000, // 1 hour\n * });\n *\n * // Check cache before calling agent\n * const result = await cache.lookup(userQuery);\n * if (result.hit) {\n * return result.entry!.response;\n * }\n *\n * // Call agent and cache response\n * const response = await runAgent(userQuery);\n * await cache.store(userQuery, response);\n * ```\n */\nexport function createSemanticCache(\n config: SemanticCacheConfig,\n): SemanticCache {\n const {\n embedder,\n similarityThreshold = 0.9,\n maxCacheSize = 1000,\n ttlMs = 3600000, // 1 hour default\n namespace = \"default\",\n storage = createInMemoryStorage(),\n onHit,\n onMiss,\n onError,\n perAgent = false,\n } = config;\n\n // Statistics\n let stats: CacheStats = {\n totalEntries: 0,\n totalHits: 0,\n totalMisses: 0,\n hitRate: 0,\n avgSimilarityOnHit: 0,\n oldestEntry: null,\n newestEntry: null,\n };\n\n let totalSimilaritySum = 0;\n\n function updateStats(entries: CacheEntry[]): void {\n stats.totalEntries = entries.length;\n stats.hitRate =\n stats.totalHits + stats.totalMisses > 0\n ? stats.totalHits / (stats.totalHits + stats.totalMisses)\n : 0;\n stats.avgSimilarityOnHit =\n stats.totalHits > 0 ? totalSimilaritySum / stats.totalHits : 0;\n\n if (entries.length > 0) {\n const times = entries.map((e) => e.createdAt);\n stats.oldestEntry = Math.min(...times);\n stats.newestEntry = Math.max(...times);\n } else {\n stats.oldestEntry = null;\n stats.newestEntry = null;\n }\n }\n\n async function evictExpiredAndExcess(): Promise<void> {\n const entries = await storage.getEntries(namespace);\n const now = Date.now();\n\n // Remove expired entries\n for (const entry of entries) {\n if (now - entry.createdAt > ttlMs) {\n await storage.removeEntry(namespace, entry.id);\n }\n }\n\n // Get fresh list after expiration\n const remainingEntries = await storage.getEntries(namespace);\n\n // Remove oldest entries if over max size (LRU based on accessedAt)\n if (remainingEntries.length > maxCacheSize) {\n const sorted = remainingEntries.sort(\n (a, b) => a.accessedAt - b.accessedAt,\n );\n const toRemove = sorted.slice(0, remainingEntries.length - maxCacheSize);\n for (const entry of toRemove) {\n await storage.removeEntry(namespace, entry.id);\n }\n }\n }\n\n return {\n async lookup(\n query: string,\n agentName?: string,\n ): Promise<CacheLookupResult> {\n const start = Date.now();\n\n try {\n // Generate embedding for query\n const queryEmbedding = await embedder(query);\n\n // Get all entries\n const entries = await storage.getEntries(namespace);\n\n // Find similar entry\n const match = findSimilar(\n queryEmbedding,\n entries,\n similarityThreshold,\n perAgent ? agentName : undefined,\n );\n\n if (match) {\n // Update access stats\n await storage.updateEntry(namespace, match.entry.id, {\n accessedAt: Date.now(),\n accessCount: match.entry.accessCount + 1,\n });\n\n stats.totalHits++;\n totalSimilaritySum += match.similarity;\n updateStats(entries);\n\n onHit?.(match.entry, match.similarity);\n\n return {\n hit: true,\n entry: match.entry,\n similarity: match.similarity,\n latencyMs: Date.now() - start,\n };\n }\n\n stats.totalMisses++;\n updateStats(entries);\n\n onMiss?.(query);\n\n return {\n hit: false,\n latencyMs: Date.now() - start,\n };\n } catch (error) {\n // On error, treat as cache miss\n stats.totalMisses++;\n onError?.(error instanceof Error ? error : new Error(String(error)));\n return {\n hit: false,\n latencyMs: Date.now() - start,\n };\n }\n },\n\n async store(\n query: string,\n response: string,\n agentName?: string,\n metadata: Record<string, unknown> = {},\n ): Promise<void> {\n // Generate embedding\n const queryEmbedding = await embedder(query);\n\n const entry: CacheEntry = {\n id:\n globalThis.crypto?.randomUUID?.() ??\n `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`,\n query,\n queryEmbedding,\n response,\n metadata,\n createdAt: Date.now(),\n accessedAt: Date.now(),\n accessCount: 0,\n agentName: perAgent ? agentName : undefined,\n };\n\n await storage.addEntry(namespace, entry);\n\n // Evict if necessary\n await evictExpiredAndExcess();\n\n const entries = await storage.getEntries(namespace);\n updateStats(entries);\n },\n\n async invalidate(\n predicate: (entry: CacheEntry) => boolean,\n ): Promise<number> {\n const entries = await storage.getEntries(namespace);\n let removed = 0;\n\n for (const entry of entries) {\n if (predicate(entry)) {\n await storage.removeEntry(namespace, entry.id);\n removed++;\n }\n }\n\n const remainingEntries = await storage.getEntries(namespace);\n updateStats(remainingEntries);\n\n return removed;\n },\n\n async clear(): Promise<void> {\n await storage.clear(namespace);\n stats = {\n totalEntries: 0,\n totalHits: 0,\n totalMisses: 0,\n hitRate: 0,\n avgSimilarityOnHit: 0,\n oldestEntry: null,\n newestEntry: null,\n };\n totalSimilaritySum = 0;\n },\n\n getStats(): CacheStats {\n return { ...stats };\n },\n\n async export(): Promise<CacheEntry[]> {\n return storage.getEntries(namespace);\n },\n\n async import(entries: CacheEntry[]): Promise<void> {\n for (const entry of entries) {\n await storage.addEntry(namespace, entry);\n }\n await evictExpiredAndExcess();\n const allEntries = await storage.getEntries(namespace);\n updateStats(allEntries);\n },\n };\n}\n\n// ============================================================================\n// Guardrail Integration\n// ============================================================================\n\n/** Input guardrail data for semantic cache */\nexport interface SemanticCacheGuardrailData {\n input: string;\n agentName?: string;\n}\n\n/**\n * Result of semantic cache guardrail.\n *\n * **Important semantics:**\n * - `passed: false` + `cacheHit: true` = Short-circuit with cached response (not an error!)\n * - `passed: true` + `cacheHit: false` = No cache hit, proceed with agent call\n *\n * The `passed: false` follows guardrail convention where \"not passing\" stops the flow,\n * but in this case stopping is desirable (returning cached data is good).\n */\nexport interface SemanticCacheGuardrailResult {\n /**\n * Whether to proceed with the agent call.\n * `false` means short-circuit with cached response (this is good, not an error).\n * `true` means no cache hit, proceed with agent.\n */\n passed: boolean;\n /** Indicates whether this was a cache hit */\n cacheHit: boolean;\n /** Reason for the result */\n reason?: string;\n /** The cached response (only present on cache hit) */\n cachedResponse?: string;\n /** Similarity score (0-1) of the cache hit */\n similarity?: number;\n}\n\n/**\n * Create a semantic caching input guardrail.\n *\n * **How it works:**\n * - On cache HIT: Returns `{ passed: false, cacheHit: true, cachedResponse: \"...\" }`\n * The orchestrator should detect `cacheHit: true` and return the cached response.\n * - On cache MISS: Returns `{ passed: true, cacheHit: false }`\n * Proceed with normal agent execution.\n *\n * **Important:** `passed: false` with `cacheHit: true` is SUCCESS, not failure.\n * The guardrail \"short-circuits\" the flow to return cached data efficiently.\n *\n * @example\n * ```typescript\n * const cacheGuardrail = createSemanticCacheGuardrail({\n * cache: mySemanticCache,\n * });\n *\n * const orchestrator = createAgentOrchestrator({\n * guardrails: {\n * input: [\n * {\n * name: 'semantic-cache',\n * fn: cacheGuardrail,\n * },\n * ],\n * },\n * runner: run,\n * });\n *\n * // In your orchestrator wrapper, check for cache hits:\n * const guardrailResult = await cacheGuardrail({ input: userQuery });\n * if (guardrailResult.cacheHit) {\n * return guardrailResult.cachedResponse; // Fast path!\n * }\n * // Otherwise proceed with agent call...\n * ```\n */\nexport function createSemanticCacheGuardrail(config: {\n cache: SemanticCache;\n}): (\n data: SemanticCacheGuardrailData,\n) => Promise<SemanticCacheGuardrailResult> {\n const { cache } = config;\n\n return async (\n data: SemanticCacheGuardrailData,\n ): Promise<SemanticCacheGuardrailResult> => {\n const result = await cache.lookup(data.input, data.agentName);\n\n if (result.hit && result.entry) {\n return {\n passed: false, // Short-circuit: don't proceed to agent\n cacheHit: true,\n reason: `Cache hit (similarity: ${(result.similarity! * 100).toFixed(1)}%)`,\n cachedResponse: result.entry.response,\n similarity: result.similarity,\n };\n }\n\n return {\n passed: true, // No cache hit, proceed with agent call\n cacheHit: false,\n };\n };\n}\n\n// ============================================================================\n// Embedding Utilities\n// ============================================================================\n\n/**\n * Create a simple hash-based \"embedder\" for testing.\n * NOT suitable for production - use a real embedding model.\n */\nexport function createTestEmbedder(dimensions = 128): EmbedderFn {\n return async (text: string): Promise<Embedding> => {\n const embedding = new Array(dimensions).fill(0);\n\n // Simple hash-based embedding for testing\n for (let i = 0; i < text.length; i++) {\n const charCode = text.charCodeAt(i);\n embedding[i % dimensions] += charCode / 256;\n }\n\n // Normalize\n const norm = Math.sqrt(embedding.reduce((sum, val) => sum + val * val, 0));\n if (norm > 0) {\n for (let i = 0; i < dimensions; i++) {\n embedding[i] /= norm;\n }\n }\n\n return embedding;\n };\n}\n\n/** Batched embedder instance with destroy capability */\nexport interface BatchedEmbedder {\n /** Embed a single text (batched internally) */\n embed: EmbedderFn;\n /** Flush any pending batch immediately */\n flush(): Promise<void>;\n /** Destroy the embedder, clearing timers and rejecting pending requests */\n destroy(): void;\n}\n\n/**\n * Create a batched embedder that groups multiple texts into single API calls.\n *\n * **BREAKING CHANGE:** Previously returned `EmbedderFn` directly. Now returns\n * a `BatchedEmbedder` object with `embed`, `flush`, and `destroy` methods.\n *\n * To migrate: `const embed = createBatchedEmbedder(...)` becomes\n * `const { embed } = createBatchedEmbedder(...)`.\n *\n * @example\n * ```typescript\n * const batchedEmbedder = createBatchedEmbedder({\n * batchSize: 20,\n * embedBatch: async (texts) => {\n * const response = await openai.embeddings.create({\n * model: 'text-embedding-3-small',\n * input: texts,\n * });\n * return response.data.map(d => d.embedding);\n * },\n * maxWaitMs: 50,\n * });\n *\n * // Use the embedder\n * const embedding = await batchedEmbedder.embed(\"Hello world\");\n *\n * // Clean up when done\n * batchedEmbedder.destroy();\n * ```\n */\nexport function createBatchedEmbedder(config: {\n batchSize?: number;\n embedBatch: (texts: string[]) => Promise<Embedding[]>;\n maxWaitMs?: number;\n}): BatchedEmbedder {\n const { batchSize = 20, embedBatch, maxWaitMs = 50 } = config;\n\n if (batchSize < 1 || !Number.isFinite(batchSize)) {\n throw new Error(\n `[Directive SemanticCache] batchSize must be >= 1, got ${batchSize}`,\n );\n }\n\n let pendingBatch: Array<{\n text: string;\n resolve: (embedding: Embedding) => void;\n reject: (error: Error) => void;\n }> = [];\n let batchTimer: ReturnType<typeof setTimeout> | null = null;\n let isDestroyed = false;\n\n async function flushBatch(): Promise<void> {\n if (pendingBatch.length === 0) return;\n\n const batch = pendingBatch;\n pendingBatch = [];\n\n if (batchTimer) {\n clearTimeout(batchTimer);\n batchTimer = null;\n }\n\n try {\n const texts = batch.map((item) => item.text);\n const embeddings = await embedBatch(texts);\n\n if (embeddings.length !== batch.length) {\n throw new Error(\n `[Directive SemanticCache] embedBatch returned ${embeddings.length} embeddings for ${batch.length} texts. The embedBatch function must return exactly one embedding per input text.`,\n );\n }\n\n for (let i = 0; i < batch.length; i++) {\n batch[i]!.resolve(embeddings[i]!);\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n for (const item of batch) {\n item.reject(err);\n }\n }\n }\n\n return {\n async embed(text: string): Promise<Embedding> {\n if (isDestroyed) {\n throw new Error(\"BatchedEmbedder has been destroyed\");\n }\n\n return new Promise((resolve, reject) => {\n pendingBatch.push({ text, resolve, reject });\n\n if (pendingBatch.length >= batchSize) {\n flushBatch();\n } else if (!batchTimer) {\n batchTimer = setTimeout(flushBatch, maxWaitMs);\n }\n });\n },\n\n async flush(): Promise<void> {\n await flushBatch();\n },\n\n destroy(): void {\n isDestroyed = true;\n\n // Clear timer\n if (batchTimer) {\n clearTimeout(batchTimer);\n batchTimer = null;\n }\n\n // Reject pending requests\n const batch = pendingBatch;\n pendingBatch = [];\n const err = new Error(\"BatchedEmbedder destroyed\");\n for (const item of batch) {\n item.reject(err);\n }\n },\n };\n}\n","/**\n * Approximate Nearest Neighbor (ANN) Index for Semantic Cache\n *\n * Provides pluggable vector search backends for efficient similarity lookups.\n * Includes a brute-force exact search and a VP-tree (Vantage Point Tree) for\n * fast approximate nearest neighbor queries.\n *\n * @example\n * ```typescript\n * import { createSemanticCache } from '@directive-run/ai';\n * import { createVPTreeIndex } from '@directive-run/ai';\n *\n * const index = createVPTreeIndex();\n *\n * const cache = createSemanticCache({\n * embedder: myEmbedder,\n * annIndex: index,\n * });\n * ```\n */\n\nimport type { Embedding } from \"./semantic-cache.js\";\nimport { cosineSimilarity } from \"./semantic-cache.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** Search result from an ANN index */\nexport interface ANNSearchResult {\n /** ID of the matched item */\n id: number;\n /** Similarity score (0-1, higher is more similar) */\n similarity: number;\n}\n\n/** ANN Index interface - pluggable vector search backend */\nexport interface ANNIndex {\n /** Add a vector to the index */\n add(id: number, embedding: Embedding): void;\n /** Remove a vector from the index */\n remove(id: number): void;\n /** Search for the k nearest neighbors */\n search(query: Embedding, k: number, threshold?: number): ANNSearchResult[];\n /** Rebuild the index (call after batch additions) */\n rebuild(): void;\n /** Get the number of indexed vectors */\n size(): number;\n /** Clear the index */\n clear(): void;\n /** Check if the index needs to be rebuilt (e.g., after additions/removals) */\n needsRebuild(): boolean;\n}\n\n// ============================================================================\n// Brute Force Index (Exact Search)\n// ============================================================================\n\n/**\n * Create a brute-force exact search index.\n *\n * O(n) search, O(1) add/remove. Best for small collections (< 10,000 vectors).\n *\n * @example\n * ```typescript\n * const index = createBruteForceIndex();\n * index.add(0, [0.1, 0.2, 0.3]);\n * index.add(1, [0.4, 0.5, 0.6]);\n *\n * const results = index.search([0.1, 0.2, 0.3], 1);\n * // [{ id: 0, similarity: 1.0 }]\n * ```\n */\nexport function createBruteForceIndex(): ANNIndex {\n const vectors = new Map<number, Embedding>();\n let expectedDimension: number | null = null;\n\n function validateDimension(embedding: Embedding): void {\n if (expectedDimension === null) {\n expectedDimension = embedding.length;\n } else if (embedding.length !== expectedDimension) {\n throw new Error(\n `[Directive ANNIndex] Dimension mismatch: expected ${expectedDimension}, got ${embedding.length}`,\n );\n }\n }\n\n return {\n add(id: number, embedding: Embedding): void {\n validateDimension(embedding);\n vectors.set(id, embedding);\n },\n\n remove(id: number): void {\n vectors.delete(id);\n },\n\n search(query: Embedding, k: number, threshold = 0): ANNSearchResult[] {\n if (expectedDimension !== null && query.length !== expectedDimension) {\n throw new Error(\n `[Directive ANNIndex] Query dimension mismatch: expected ${expectedDimension}, got ${query.length}`,\n );\n }\n const results: ANNSearchResult[] = [];\n\n for (const [id, embedding] of vectors) {\n const similarity = cosineSimilarity(query, embedding);\n if (similarity >= threshold) {\n results.push({ id, similarity });\n }\n }\n\n // Sort by similarity descending, take top k\n results.sort((a, b) => b.similarity - a.similarity);\n return results.slice(0, k);\n },\n\n rebuild(): void {\n // No-op for brute force\n },\n\n size(): number {\n return vectors.size;\n },\n\n clear(): void {\n vectors.clear();\n expectedDimension = null;\n },\n\n needsRebuild(): boolean {\n return false; // Brute force doesn't need rebuilding\n },\n };\n}\n\n// ============================================================================\n// VP-Tree Index (Approximate Search)\n// ============================================================================\n\ninterface VPNode {\n id: number;\n embedding: Embedding;\n mu: number; // Median distance\n left: VPNode | null;\n right: VPNode | null;\n}\n\nfunction cosineDistance(a: Embedding, b: Embedding): number {\n return 1 - cosineSimilarity(a, b);\n}\n\n/** VP-Tree index configuration */\nexport interface VPTreeIndexConfig {\n /** Optional random number generator for deterministic builds. Returns a number in [0, 1). */\n random?: () => number;\n}\n\nfunction buildVPTree(\n items: Array<{ id: number; embedding: Embedding }>,\n random: () => number,\n): VPNode | null {\n if (items.length === 0) return null;\n\n // Pick a random vantage point\n const vpIdx = Math.floor(random() * items.length);\n const vp = items[vpIdx]!;\n const rest = items.filter((_, i) => i !== vpIdx);\n\n if (rest.length === 0) {\n return {\n id: vp.id,\n embedding: vp.embedding,\n mu: 0,\n left: null,\n right: null,\n };\n }\n\n // Calculate distances from vantage point\n const distances = rest.map((item) => ({\n item,\n distance: cosineDistance(vp.embedding, item.embedding),\n }));\n\n // Find median distance\n distances.sort((a, b) => a.distance - b.distance);\n const medianIdx = Math.floor(distances.length / 2);\n const mu = distances[medianIdx]!.distance;\n\n const leftItems = distances.slice(0, medianIdx).map((d) => d.item);\n const rightItems = distances.slice(medianIdx).map((d) => d.item);\n\n return {\n id: vp.id,\n embedding: vp.embedding,\n mu,\n left: buildVPTree(leftItems, random),\n right: buildVPTree(rightItems, random),\n };\n}\n\nfunction searchVPTree(\n node: VPNode | null,\n query: Embedding,\n k: number,\n threshold: number,\n results: ANNSearchResult[],\n maxDist: { value: number },\n): void {\n if (!node) return;\n\n const dist = cosineDistance(query, node.embedding);\n const similarity = 1 - dist;\n\n if (similarity >= threshold) {\n results.push({ id: node.id, similarity });\n results.sort((a, b) => b.similarity - a.similarity);\n\n if (results.length > k) {\n results.pop();\n }\n\n if (results.length === k) {\n maxDist.value = 1 - results[results.length - 1]!.similarity;\n }\n }\n\n // Determine which subtrees to search\n if (dist < node.mu) {\n // Query is inside the ball: search left (inside) first\n searchVPTree(node.left, query, k, threshold, results, maxDist);\n // Only search right if the distance boundary overlaps\n if (dist + maxDist.value >= node.mu) {\n searchVPTree(node.right, query, k, threshold, results, maxDist);\n }\n } else {\n // Query is outside the ball: search right (outside) first\n searchVPTree(node.right, query, k, threshold, results, maxDist);\n // Only search left if the distance boundary overlaps\n if (dist - maxDist.value <= node.mu) {\n searchVPTree(node.left, query, k, threshold, results, maxDist);\n }\n }\n}\n\n/**\n * Create a VP-Tree (Vantage Point Tree) index for efficient approximate nearest neighbor search.\n *\n * O(log n) search on average, requires rebuild after batch additions.\n * Best for medium collections (1,000 - 100,000 vectors).\n *\n * @example\n * ```typescript\n * const index = createVPTreeIndex();\n *\n * // Add vectors\n * for (let i = 0; i < embeddings.length; i++) {\n * index.add(i, embeddings[i]);\n * }\n *\n * // Build the tree\n * index.rebuild();\n *\n * // Search\n * const results = index.search(queryEmbedding, 5, 0.9);\n * ```\n */\nexport function createVPTreeIndex(vpConfig: VPTreeIndexConfig = {}): ANNIndex {\n const { random = Math.random } = vpConfig;\n const items = new Map<number, Embedding>();\n let root: VPNode | null = null;\n let needsRebuild = false;\n let expectedDimension: number | null = null;\n\n function validateDimension(embedding: Embedding): void {\n if (expectedDimension === null) {\n expectedDimension = embedding.length;\n } else if (embedding.length !== expectedDimension) {\n throw new Error(\n `[Directive ANNIndex] Dimension mismatch: expected ${expectedDimension}, got ${embedding.length}`,\n );\n }\n }\n\n return {\n add(id: number, embedding: Embedding): void {\n validateDimension(embedding);\n items.set(id, embedding);\n needsRebuild = true;\n },\n\n remove(id: number): void {\n items.delete(id);\n needsRebuild = true;\n },\n\n search(query: Embedding, k: number, threshold = 0): ANNSearchResult[] {\n if (expectedDimension !== null && query.length !== expectedDimension) {\n throw new Error(\n `[Directive ANNIndex] Query dimension mismatch: expected ${expectedDimension}, got ${query.length}`,\n );\n }\n if (needsRebuild || !root) {\n // Fall back to brute force if tree is stale\n const results: ANNSearchResult[] = [];\n for (const [id, embedding] of items) {\n const similarity = cosineSimilarity(query, embedding);\n if (similarity >= threshold) {\n results.push({ id, similarity });\n }\n }\n results.sort((a, b) => b.similarity - a.similarity);\n return results.slice(0, k);\n }\n\n const results: ANNSearchResult[] = [];\n const maxDist = { value: Number.POSITIVE_INFINITY };\n searchVPTree(root, query, k, threshold, results, maxDist);\n return results;\n },\n\n rebuild(): void {\n const itemArray = Array.from(items.entries()).map(([id, embedding]) => ({\n id,\n embedding,\n }));\n root = buildVPTree(itemArray, random);\n needsRebuild = false;\n },\n\n size(): number {\n return items.size;\n },\n\n clear(): void {\n items.clear();\n root = null;\n needsRebuild = false;\n expectedDimension = null;\n },\n\n needsRebuild(): boolean {\n return needsRebuild;\n },\n };\n}\n"]}
@@ -1,4 +0,0 @@
1
- 'use strict';var chunkK64WKZ22_cjs=require('./chunk-K64WKZ22.cjs'),internals=require('@directive-run/core/internals');function K(i){let{patterns:a=[/\b\d{3}-\d{2}-\d{4}\b/g,/\b\d{16}\b/g,/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi],redact:r=false,redactReplacement:t="[REDACTED]"}=i;return e=>{let n=e.input,s=false;for(let c of a)c.lastIndex=0,c.test(n)&&(s=true,r&&(c.lastIndex=0,n=n.replace(c,t)));return s&&!r?{passed:false,reason:"Input contains PII"}:{passed:true,transformed:r&&s?n:void 0}}}function ee(i){let{checkFn:a,message:r="Content flagged by moderation"}=i;return async t=>{let e="output"in t?typeof t.output=="string"?t.output:JSON.stringify(t.output):t.input,n=await a(e);return {passed:!n,reason:n?r:void 0}}}function te(i){let{maxTokensPerMinute:a=1e5,maxRequestsPerMinute:r=60}=i,t=Math.max(r,1e3),e=[],n=[],s=6e4;function c(d,u){let l=0,g=d.length;for(;l<g;){let p=l+g>>>1;(d[p]??0)<u?l=p+1:g=p;}return l}let o=(d,u)=>{let l=Date.now(),g=l-s,p=c(e,g);p>0&&(e=e.slice(p));let b=c(n,g);b>0&&(n=n.slice(b));let h=u.facts[chunkK64WKZ22_cjs.c]?.tokenUsage??0,y=e.length,I=n.length;return y+h>a?{passed:false,reason:"Token rate limit exceeded"}:I>=r?{passed:false,reason:"Request rate limit exceeded"}:(n.length<t&&n.push(l),e.length<t&&e.push(l),{passed:true})};return o.reset=()=>{e=[],n=[];},o}function ne(i){let{allowlist:a,denylist:r,caseSensitive:t=false}=i,e=a?.map(s=>t?s:s.toLowerCase()),n=r?.map(s=>t?s:s.toLowerCase());return s=>{let c=t?s.toolCall.name:s.toolCall.name.toLowerCase();return e&&!e.includes(c)?{passed:false,reason:`Tool "${s.toolCall.name}" not in allowlist`}:n?.includes(c)?{passed:false,reason:`Tool "${s.toolCall.name}" is blocked`}:{passed:true}}}function re(i){let{validate:a,errorPrefix:r="Output schema validation failed"}=i;return t=>{let e=a(t.output);return typeof e=="boolean"?{passed:e,reason:e?void 0:r}:e.valid?{passed:true}:{passed:false,reason:e.errors?.length?`${r}: ${e.errors.join("; ")}`:r}}}function ie(i){let{type:a,requiredFields:r=[],minLength:t,maxLength:e,minStringLength:n,maxStringLength:s}=i;return c=>{let o=c.output;switch(a){case "string":return typeof o!="string"?{passed:false,reason:`Expected string, got ${typeof o}`}:n!==void 0&&o.length<n?{passed:false,reason:`String too short: ${o.length} < ${n}`}:s!==void 0&&o.length>s?{passed:false,reason:`String too long: ${o.length} > ${s}`}:{passed:true};case "number":return typeof o!="number"||Number.isNaN(o)?{passed:false,reason:`Expected number, got ${typeof o}`}:{passed:true};case "boolean":return typeof o!="boolean"?{passed:false,reason:`Expected boolean, got ${typeof o}`}:{passed:true};case "object":if(typeof o!="object"||o===null||Array.isArray(o))return {passed:false,reason:`Expected object, got ${Array.isArray(o)?"array":typeof o}`};for(let d of r)if(!(d in o))return {passed:false,reason:`Missing required field: ${d}`};return {passed:true};case "array":return Array.isArray(o)?t!==void 0&&o.length<t?{passed:false,reason:`Array too short: ${o.length} < ${t}`}:e!==void 0&&o.length>e?{passed:false,reason:`Array too long: ${o.length} > ${e}`}:{passed:true}:{passed:false,reason:`Expected array, got ${typeof o}`};default:return {passed:false,reason:`Unknown type: ${a}`}}}}function ae(i){let{maxCharacters:a,maxTokens:r,estimateTokens:t=e=>Math.ceil(e.length/4)}=i;return e=>{let n=internals.safeStringify(e.output);if(a!==void 0&&n.length>a)return {passed:false,reason:`Output too long: ${n.length} characters (max: ${a})`};if(r!==void 0){let s=t(n);if(s>r)return {passed:false,reason:`Output too long: ~${s} tokens (max: ${r})`}}return {passed:true}}}function se(i){let{blockedPatterns:a,caseSensitive:r=false}=i;a.length===0&&console.warn("[Directive] createContentFilterGuardrail: blockedPatterns is empty \u2014 no content will be filtered");let t=a.map(e=>{if(e instanceof RegExp)return e;let n=e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(n,r?"g":"gi")});return e=>{let n=internals.safeStringify(e.output);for(let s of t)if(s.lastIndex=0,s.test(n))return {passed:false,reason:`Output contains blocked content matching: ${s.source}`};return {passed:true}}}var M=[{type:"ssn",pattern:/\b(\d{3}[-\s]?\d{2}[-\s]?\d{4})\b/g,validate:i=>{let a=i.replace(/[-\s]/g,"");return !(a.startsWith("000")||a.startsWith("666")||a.startsWith("9")||a.slice(3,5)==="00"||a.slice(5)==="0000")},confidence:.95},{type:"credit_card",pattern:/\b((?:\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4})|\d{13,19})\b/g,validate:i=>{let a=i.replace(/[-\s]/g,"");if(a.length<13||a.length>19)return false;let r=0,t=false;for(let e=a.length-1;e>=0;e--){let n=a[e];if(!n)continue;let s=Number.parseInt(n,10);t&&(s*=2,s>9&&(s-=9)),r+=s,t=!t;}return r%10===0},confidence:.95},{type:"email",pattern:/\b([A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,})\b/gi,confidence:.9},{type:"phone",pattern:/\b(\+?1?[-.\s]?\(?[0-9]{3}\)?[-.\s]?[0-9]{3}[-.\s]?[0-9]{4})\b/g,validate:i=>{let a=i.replace(/\D/g,"");return a.length>=10&&a.length<=11},confidence:.8},{type:"date_of_birth",pattern:/\b(born|dob|birth.?date|date.?of.?birth)[:.\s]+(\d{1,4}[-/]\d{1,2}[-/]\d{1,4})\b/gi,valueGroup:2,confidence:.85},{type:"ip_address",pattern:/\b(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\b/g,validate:i=>{let r=i.split(".").map(n=>Number.parseInt(n,10));if(r.some(n=>Number.isNaN(n)||n<0||n>255))return false;let[t,e]=r;return !(t===10||t===172&&e>=16&&e<=31||t===192&&e===168||t===127||t===169&&e===254||i==="0.0.0.0"||i==="255.255.255.255")},confidence:.9},{type:"bank_account",pattern:/\b(account|acct)[\s#:]+(\d{8,17})\b/gi,valueGroup:2,confidence:.7},{type:"passport",pattern:/\b(passport)[\s#:]+([A-Z0-9]{6,9})\b/gi,valueGroup:2,confidence:.75},{type:"driver_license",pattern:/\b(driver'?s?\s*licen[cs]e|dl)[\s#:]+([A-Z0-9]{5,15})\b/gi,valueGroup:2,confidence:.7},{type:"medical_id",pattern:/\b(mrn|medical.?record|patient.?id)[\s#:]+([A-Z0-9-]{6,15})\b/gi,valueGroup:2,confidence:.7},{type:"national_id",pattern:/\b(national.?id|nin|identity.?number|identity.?card|id.?number)[\s#:]+([A-Z0-9-]{6,20})\b/gi,valueGroup:2,confidence:.85}];function F(i){let a=[],r="street|st|avenue|ave|road|rd|drive|dr|lane|ln|court|ct|way|boulevard|blvd|circle|cir|place|pl",t=new RegExp(`\\b(\\d{1,5}\\s+(?:\\w+\\s+){1,4}(?:${r})\\b[^\\n]{0,50}\\b[A-Z]{2}\\s+\\d{5}(?:-\\d{4})?)\\b`,"gi"),e;for(;(e=t.exec(i))!==null;)a.push({type:"address",value:e[0],position:{start:e.index,end:e.index+e[0].length},confidence:.7});return a}var D=["mr","mrs","ms","miss","dr","prof","sir","madam","name is","called","known as","signed by","from","dear","hi","hello","contact","recipient"];function O(i){let a=[],r=D.join("|"),t=new RegExp(`\\b(${r})[.,:]?\\s+([A-Z][a-z]{1,20}(?:\\s[A-Z][a-z]{1,20}){0,2})\\b`,"gi"),e;for(;(e=t.exec(i))!==null;){let n=e[2],s=e[1];n&&(n.split(/\s+/).length>=2||s&&D.some(c=>s.toLowerCase().includes(c)))&&a.push({type:"name",value:n,position:{start:e.index,end:e.index+e[0].length},confidence:.6,context:e[0]});}return a}var N=1e5;function L(i,a){let r=[],t=new RegExp(i.pattern.source,i.pattern.flags),e=i.valueGroup??1,n;for(;(n=t.exec(a))!==null;){let s=n[e]??n[0],c=n.index,o=n.index+n[0].length,d=a.slice(Math.max(0,c-20),o+20);i.validate&&!i.validate(s,d)||r.push({type:i.type,value:s,position:{start:c,end:o},confidence:i.confidence,context:d});}return r}var P={name:"regex",async detect(i,a){if(i.length>N)throw new Error(`[Directive] Input exceeds maximum length of ${N} characters for PII detection. Truncate input or process in chunks.`);let r=[],t=new Set(a);for(let e of M)t.has(e.type)&&r.push(...L(e,i));return t.has("address")&&r.push(...F(i)),t.has("name")&&r.push(...O(i)),r}},z=new Set(["ssn","credit_card","date_of_birth","medical_id","national_id","passport","driver_license","bank_account"]);function H(i,a){let{start:r,end:t}=i.position;return Number.isInteger(r)&&Number.isInteger(t)&&r>=0&&r<t&&t<=a}function U(i,a){switch(a){case "placeholder":return "[REDACTED]";case "typed":return z.has(i.type)?"[REDACTED]":`[${i.type.toUpperCase()}]`;case "masked":{if(i.type!=="credit_card")return "****";let r=i.value.replace(/\D/g,"");return `****${r.length>4?r.slice(-4):""}`}case "hashed":return `[HASH:${V(i.value)}]`}}function _(i,a,r="typed"){let e=[...a.filter(o=>H(o,i.length))].sort((o,d)=>{if(d.confidence!==o.confidence)return d.confidence-o.confidence;let u=o.position.end-o.position.start,l=d.position.end-d.position.start;return l!==u?l-u:o.position.start-d.position.start}),n=[];for(let o of e)n.some(u=>o.position.start<u.position.end&&u.position.start<o.position.end)||n.push(o);let s=n.sort((o,d)=>d.position.start-o.position.start),c=i;for(let o of s){let d=U(o,r);c=c.slice(0,o.position.start)+d+c.slice(o.position.end);}return c}function V(i){let t=2166136261;for(let e=0;e<i.length;e++)t^=i.charCodeAt(e),t=Math.imul(t,16777619);return (t>>>0).toString(16).padStart(8,"0")}var G=["ssn","credit_card","email","phone","date_of_birth","bank_account"];function B(i={}){let{types:a=G,detector:r="regex",redact:t=false,redactionStyle:e="typed",minConfidence:n=.7,onDetected:s,allowlist:c=[],minItemsToBlock:o=1,detectorTimeout:d=5e3}=i,u=r==="regex"?P:r,l=new Set(c.map(p=>p.toLowerCase().trim()));async function g(p,b){if(u===P)return u.detect(p,b);let m,f=u.detect(p,b),h=new Promise((y,I)=>{m=setTimeout(()=>I(new Error(`[Directive] PII detector '${u.name}' timed out after ${d}ms`)),d);});f.catch(()=>{}),h.catch(()=>{});try{return await Promise.race([f,h])}finally{clearTimeout(m);}}return async p=>{let m=(await g(p.input,a)).filter(f=>!(f.confidence<n||l.has(f.value.toLowerCase().trim())));if(m.length>0&&s?.(m),m.length>=o){if(t)return {passed:true,transformed:_(p.input,m,e)};let f={};for(let y of m)f[y.type]=(f[y.type]||0)+1;return {passed:false,reason:`PII detected (${Object.entries(f).map(([y,I])=>`${y}: ${I}`).join(", ")})`}}return {passed:true}}}function ce(i={}){let a=B(i);return async(r,t)=>{let e=typeof r.output=="string"?r.output:JSON.stringify(r.output);return a({input:e,agentName:r.agentName},t)}}async function Z(i,a={}){let{types:r=G,detector:t="regex",minConfidence:e=.7,timeout:n=5e3}=a,s=t==="regex"?P:t,c;if(s===P)c=await s.detect(i,r);else {let u,l=s.detect(i,r),g=new Promise((p,b)=>{u=setTimeout(()=>b(new Error(`[Directive] PII detector '${s.name}' timed out after ${n}ms`)),n);});l.catch(()=>{}),g.catch(()=>{});try{c=await Promise.race([l,g]);}finally{clearTimeout(u);}}let o=c.filter(u=>u.confidence>=e),d={};for(let u of o)d[u.type]=(d[u.type]||0)+1;return {detected:o.length>0,items:o,typeCounts:d}}async function de(i,a={}){let r=await Z(i,a);return r.detected?{...r,redactedText:_(i,r.items,a.style??"typed")}:{...r}}var w=[{pattern:/ignore\s+(all\s+)?(previous|prior|above|earlier)\s+(instructions?|prompts?|rules?|guidelines?)/i,name:"ignore-previous",severity:"critical",category:"instruction_override"},{pattern:/disregard\s+(all\s+)?(previous|prior|above|earlier)\s+(instructions?|prompts?)/i,name:"disregard-previous",severity:"critical",category:"instruction_override"},{pattern:/forget\s+(all\s+)?(previous|prior|above|earlier)\s+(instructions?|prompts?)/i,name:"forget-previous",severity:"critical",category:"instruction_override"},{pattern:/override\s+(the\s+)?(system|base)\s+(prompt|instructions?)/i,name:"override-system",severity:"critical",category:"instruction_override"},{pattern:/\bDAN\s+(mode|jailbreak)\b/i,name:"dan-mode",severity:"critical",category:"jailbreak"},{pattern:/\bjailbreak(ed)?\s*(mode)?\b/i,name:"jailbreak-keyword",severity:"high",category:"jailbreak"},{pattern:/developer\s+mode\s+(enabled|activated|on)/i,name:"developer-mode",severity:"critical",category:"jailbreak"},{pattern:/pretend\s+(you\s+)?(are|can|have)\s+(no\s+)?(restrictions?|limits?|boundaries?|ethics)/i,name:"pretend-no-restrictions",severity:"high",category:"jailbreak"},{pattern:/you\s+(now\s+)?have\s+no\s+(ethical\s+)?(restrictions?|guidelines?|boundaries?)/i,name:"no-restrictions",severity:"high",category:"jailbreak"},{pattern:/you\s+are\s+now\s+(a|an)\s+\w+\s+(that|who)\s+(can|will|must)/i,name:"role-assignment",severity:"medium",category:"role_manipulation"},{pattern:/from\s+now\s+on,?\s+(you\s+)?(will|must|should)\s+(only\s+)?/i,name:"from-now-on",severity:"medium",category:"role_manipulation"},{pattern:/^(system|assistant|user):\s*/im,name:"fake-role-marker",severity:"high",category:"context_manipulation"},{pattern:/<\|?(system|endofprompt|im_start|im_end)\|?>/i,name:"special-token-injection",severity:"critical",category:"context_manipulation"},{pattern:/```(system|assistant|instructions?)\n/i,name:"markdown-code-injection",severity:"medium",category:"delimiter_injection"},{pattern:/<system>|<\/system>|<instructions?>|<\/instructions?>/i,name:"xml-tag-injection",severity:"high",category:"delimiter_injection"},{pattern:/fetch\s+(content\s+)?(from|at)\s+(the\s+)?url/i,name:"url-fetch-instruction",severity:"medium",category:"indirect_injection"},{pattern:/execute\s+(the\s+)?(code|script|command)\s+(from|in|at)/i,name:"execute-from-source",severity:"high",category:"indirect_injection"}],k=[...w,{pattern:/act\s+as\s+(if\s+)?(you\s+)?(were|are|can)/i,name:"act-as",severity:"low",category:"role_manipulation"},{pattern:/new\s+instructions?:/i,name:"new-instructions",severity:"medium",category:"instruction_override"},{pattern:/\[system\]|\[admin\]|\[developer\]/i,name:"bracket-role-marker",severity:"medium",category:"context_manipulation"},{pattern:/base64|rot13|decode\s+(this|the)/i,name:"encoding-reference",severity:"low",category:"encoding_evasion"},{pattern:/\u200b|\u200c|\u200d|\u2060|\ufeff/,name:"zero-width-chars",severity:"medium",category:"encoding_evasion"}],A=1e5;function $(i,a=w){if(i.length>A)throw new Error(`[Directive] Input exceeds maximum length of ${A} characters for injection detection. Truncate input or process in chunks.`);let r=[];for(let{pattern:s,name:c,severity:o,category:d}of a){let l=new RegExp(s.source,s.flags).exec(i);l&&r.push({name:c,category:d,severity:o,match:l[0],position:l.index});}let t={low:10,medium:25,high:50,critical:100},e=r.reduce((s,c)=>s+t[c.severity],0),n=Math.min(100,e);return {detected:r.length>0,patterns:r,riskScore:n}}function q(i,a=w){let r=i.replace(/\u200b|\u200c|\u200d|\u2060|\ufeff/g,""),t=a.map(d=>`(${d.pattern.source})`);if(t.length===0)return r;let e=a.some(d=>d.pattern.flags.includes("g")),n=a.some(d=>d.pattern.flags.includes("i")),s=a.some(d=>d.pattern.flags.includes("m")),c=`${e?"g":""}${n?"i":""}${s?"m":""}`,o=new RegExp(t.join("|"),c||"gi");return r=r.replace(o,"[REDACTED]"),r}function W(i={}){let{additionalPatterns:a=[],replacePatterns:r,strictMode:t=false,blockThreshold:e=50,sanitize:n=false,onBlocked:s,ignoreCategories:c=[]}=i,o;if(r?o=r:o=t?[...k]:[...w],o=[...o,...a],c.length>0){let d=new Set(c);o=o.filter(u=>!d.has(u.category));}return d=>{let u=$(d.input,o);if(u.detected&&u.riskScore>=e){if(s?.(d.input,u),n)return {passed:true,transformed:q(d.input,o)};let l=u.patterns.sort((g,p)=>{let b={critical:0,high:1,medium:2,low:3};return b[g.severity]-b[p.severity]}).slice(0,3).map(g=>g.name).join(", ");return {passed:false,reason:`Prompt injection detected (risk: ${u.riskScore}%, patterns: ${l})`}}return {passed:true}}}function ue(i,a){return `[UNTRUSTED_CONTENT source="${a}"]
2
- ${i}
3
- [/UNTRUSTED_CONTENT]`}function me(i){let{baseGuardrail:a=W({strictMode:true,blockThreshold:25}),additionalPatterns:r=[]}=i,t=/\[UNTRUSTED_CONTENT source="([^"]+)"\]([\s\S]*?)\[\/UNTRUSTED_CONTENT\]/g;return async(e,n)=>{let s=await a(e,n);if(!s.passed)return s;let c=e.input.matchAll(t);for(let o of c){let[,d,u]=o;if(!u)continue;let l=$(u,[...k,...r]);if(l.detected&&l.riskScore>=25)return {passed:false,reason:`Untrusted content from "${d}" contains potential injection (risk: ${l.riskScore}%)`}}return {passed:true}}}function v(i,a){if(i.length!==a.length)throw new Error(`Vector dimensions must match: ${i.length} vs ${a.length}`);let r=0,t=0,e=0;for(let n=0;n<i.length;n++){let s=i[n],c=a[n];r+=s*c,t+=s*s,e+=c*c;}return t=Math.sqrt(t),e=Math.sqrt(e),t===0||e===0?0:r/(t*e)}function J(i,a,r,t){let e=null;for(let n of a){if(t&&n.agentName&&n.agentName!==t)continue;let s=v(i,n.queryEmbedding);s>=r&&(!e||s>e.similarity)&&(e={entry:n,similarity:s});}return e}function Y(){let i=new Map;function a(r){let t=i.get(r);return t||(t=new Map,i.set(r,t)),t}return {async getEntries(r){return Array.from(a(r).values())},async addEntry(r,t){a(r).set(t.id,t);},async updateEntry(r,t,e){let n=a(r),s=n.get(t);s&&n.set(t,{...s,...e});},async removeEntry(r,t){a(r).delete(t);},async clear(r){i.delete(r);}}}function ge(i){let{embedder:a,similarityThreshold:r=.9,maxCacheSize:t=1e3,ttlMs:e=36e5,namespace:n="default",storage:s=Y(),onHit:c,onMiss:o,onError:d,perAgent:u=false}=i,l={totalEntries:0,totalHits:0,totalMisses:0,hitRate:0,avgSimilarityOnHit:0,oldestEntry:null,newestEntry:null},g=0;function p(m){if(l.totalEntries=m.length,l.hitRate=l.totalHits+l.totalMisses>0?l.totalHits/(l.totalHits+l.totalMisses):0,l.avgSimilarityOnHit=l.totalHits>0?g/l.totalHits:0,m.length>0){let f=m.map(h=>h.createdAt);l.oldestEntry=Math.min(...f),l.newestEntry=Math.max(...f);}else l.oldestEntry=null,l.newestEntry=null;}async function b(){let m=await s.getEntries(n),f=Date.now();for(let y of m)f-y.createdAt>e&&await s.removeEntry(n,y.id);let h=await s.getEntries(n);if(h.length>t){let I=h.sort((E,S)=>E.accessedAt-S.accessedAt).slice(0,h.length-t);for(let E of I)await s.removeEntry(n,E.id);}}return {async lookup(m,f){let h=Date.now();try{let y=await a(m),I=await s.getEntries(n),E=J(y,I,r,u?f:void 0);return E?(await s.updateEntry(n,E.entry.id,{accessedAt:Date.now(),accessCount:E.entry.accessCount+1}),l.totalHits++,g+=E.similarity,p(I),c?.(E.entry,E.similarity),{hit:!0,entry:E.entry,similarity:E.similarity,latencyMs:Date.now()-h}):(l.totalMisses++,p(I),o?.(m),{hit:!1,latencyMs:Date.now()-h})}catch(y){return l.totalMisses++,d?.(y instanceof Error?y:new Error(String(y))),{hit:false,latencyMs:Date.now()-h}}},async store(m,f,h,y={}){let I=await a(m),E={id:globalThis.crypto?.randomUUID?.()??`${Date.now()}-${Math.random().toString(36).slice(2,11)}`,query:m,queryEmbedding:I,response:f,metadata:y,createdAt:Date.now(),accessedAt:Date.now(),accessCount:0,agentName:u?h:void 0};await s.addEntry(n,E),await b();let S=await s.getEntries(n);p(S);},async invalidate(m){let f=await s.getEntries(n),h=0;for(let I of f)m(I)&&(await s.removeEntry(n,I.id),h++);let y=await s.getEntries(n);return p(y),h},async clear(){await s.clear(n),l={totalEntries:0,totalHits:0,totalMisses:0,hitRate:0,avgSimilarityOnHit:0,oldestEntry:null,newestEntry:null},g=0;},getStats(){return {...l}},async export(){return s.getEntries(n)},async import(m){for(let h of m)await s.addEntry(n,h);await b();let f=await s.getEntries(n);p(f);}}}function fe(i){let{cache:a}=i;return async r=>{let t=await a.lookup(r.input,r.agentName);return t.hit&&t.entry?{passed:false,cacheHit:true,reason:`Cache hit (similarity: ${(t.similarity*100).toFixed(1)}%)`,cachedResponse:t.entry.response,similarity:t.similarity}:{passed:true,cacheHit:false}}}function he(i=128){return async a=>{let r=new Array(i).fill(0);for(let e=0;e<a.length;e++){let n=a.charCodeAt(e);r[e%i]+=n/256;}let t=Math.sqrt(r.reduce((e,n)=>e+n*n,0));if(t>0)for(let e=0;e<i;e++)r[e]/=t;return r}}function ye(i){let{batchSize:a=20,embedBatch:r,maxWaitMs:t=50}=i;if(a<1||!Number.isFinite(a))throw new Error(`[Directive SemanticCache] batchSize must be >= 1, got ${a}`);let e=[],n=null,s=false;async function c(){if(e.length===0)return;let o=e;e=[],n&&(clearTimeout(n),n=null);try{let d=o.map(l=>l.text),u=await r(d);if(u.length!==o.length)throw new Error(`[Directive SemanticCache] embedBatch returned ${u.length} embeddings for ${o.length} texts. The embedBatch function must return exactly one embedding per input text.`);for(let l=0;l<o.length;l++)o[l].resolve(u[l]);}catch(d){let u=d instanceof Error?d:new Error(String(d));for(let l of o)l.reject(u);}}return {async embed(o){if(s)throw new Error("BatchedEmbedder has been destroyed");return new Promise((d,u)=>{e.push({text:o,resolve:d,reject:u}),e.length>=a?c():n||(n=setTimeout(c,t));})},async flush(){await c();},destroy(){s=true,n&&(clearTimeout(n),n=null);let o=e;e=[];let d=new Error("BatchedEmbedder destroyed");for(let u of o)u.reject(d);}}}function Ee(){let i=new Map,a=null;function r(t){if(a===null)a=t.length;else if(t.length!==a)throw new Error(`[Directive ANNIndex] Dimension mismatch: expected ${a}, got ${t.length}`)}return {add(t,e){r(e),i.set(t,e);},remove(t){i.delete(t);},search(t,e,n=0){if(a!==null&&t.length!==a)throw new Error(`[Directive ANNIndex] Query dimension mismatch: expected ${a}, got ${t.length}`);let s=[];for(let[c,o]of i){let d=v(t,o);d>=n&&s.push({id:c,similarity:d});}return s.sort((c,o)=>o.similarity-c.similarity),s.slice(0,e)},rebuild(){},size(){return i.size},clear(){i.clear(),a=null;},needsRebuild(){return false}}}function j(i,a){return 1-v(i,a)}function T(i,a){if(i.length===0)return null;let r=Math.floor(a()*i.length),t=i[r],e=i.filter((u,l)=>l!==r);if(e.length===0)return {id:t.id,embedding:t.embedding,mu:0,left:null,right:null};let n=e.map(u=>({item:u,distance:j(t.embedding,u.embedding)}));n.sort((u,l)=>u.distance-l.distance);let s=Math.floor(n.length/2),c=n[s].distance,o=n.slice(0,s).map(u=>u.item),d=n.slice(s).map(u=>u.item);return {id:t.id,embedding:t.embedding,mu:c,left:T(o,a),right:T(d,a)}}function x(i,a,r,t,e,n){if(!i)return;let s=j(a,i.embedding),c=1-s;c>=t&&(e.push({id:i.id,similarity:c}),e.sort((o,d)=>d.similarity-o.similarity),e.length>r&&e.pop(),e.length===r&&(n.value=1-e[e.length-1].similarity)),s<i.mu?(x(i.left,a,r,t,e,n),s+n.value>=i.mu&&x(i.right,a,r,t,e,n)):(x(i.right,a,r,t,e,n),s-n.value<=i.mu&&x(i.left,a,r,t,e,n));}function ve(i={}){let{random:a=Math.random}=i,r=new Map,t=null,e=false,n=null;function s(c){if(n===null)n=c.length;else if(c.length!==n)throw new Error(`[Directive ANNIndex] Dimension mismatch: expected ${n}, got ${c.length}`)}return {add(c,o){s(o),r.set(c,o),e=true;},remove(c){r.delete(c),e=true;},search(c,o,d=0){if(n!==null&&c.length!==n)throw new Error(`[Directive ANNIndex] Query dimension mismatch: expected ${n}, got ${c.length}`);if(e||!t){let g=[];for(let[p,b]of r){let m=v(c,b);m>=d&&g.push({id:p,similarity:m});}return g.sort((p,b)=>b.similarity-p.similarity),g.slice(0,o)}let u=[],l={value:Number.POSITIVE_INFINITY};return x(t,c,o,d,u,l),u},rebuild(){let c=Array.from(r.entries()).map(([o,d])=>({id:o,embedding:d}));t=T(c,a),e=false;},size(){return r.size},clear(){r.clear(),t=null,e=false,n=null;},needsRebuild(){return e}}}exports.A=Ee;exports.B=ve;exports.a=K;exports.b=ee;exports.c=te;exports.d=ne;exports.e=re;exports.f=ie;exports.g=ae;exports.h=se;exports.i=_;exports.j=B;exports.k=ce;exports.l=Z;exports.m=de;exports.n=w;exports.o=k;exports.p=$;exports.q=q;exports.r=W;exports.s=ue;exports.t=me;exports.u=v;exports.v=Y;exports.w=ge;exports.x=fe;exports.y=he;exports.z=ye;//# sourceMappingURL=chunk-CAA6Q4YY.cjs.map
4
- //# sourceMappingURL=chunk-CAA6Q4YY.cjs.map