@silmaril-security/sdk 0.5.0 → 0.5.1

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  All notable changes to the Silmaril Firewall TypeScript SDK are documented here.
4
4
 
5
+ ## 0.5.1 - 2026-07-29
6
+
7
+ - Add typed support for `code_generation`, `story_script_generation`,
8
+ `game_generation`, `website_generation`, `clickup_terms_violation`, and
9
+ `traditional_ai_abuse`.
10
+ - Extend ordered outcome collections, descriptions, guards, normalization
11
+ fixtures, exports, and documentation without changing the `/classify` wire
12
+ shape.
13
+
5
14
  ## 0.5.0 - 2026-07-15
6
15
 
7
16
  - Send every `classify()` input as one complete event without client chunking.
package/README.md CHANGED
@@ -37,7 +37,7 @@ npm install @silmaril-security/sdk
37
37
  For reproducible installs, pin a tagged release:
38
38
 
39
39
  ```sh
40
- npm install @silmaril-security/sdk@0.5.0
40
+ npm install @silmaril-security/sdk@0.5.1
41
41
  ```
42
42
 
43
43
  Requires Node 18 or later.
@@ -148,6 +148,14 @@ if (result.prediction === "BENIGN") {
148
148
  case Outcome.ServiceDisruption:
149
149
  blockDisruptiveAction(result);
150
150
  break;
151
+ case Outcome.CodeGeneration:
152
+ case Outcome.StoryScriptGeneration:
153
+ case Outcome.GameGeneration:
154
+ case Outcome.WebsiteGeneration:
155
+ case Outcome.ClickUpTermsViolation:
156
+ case Outcome.TraditionalAiAbuse:
157
+ applyTenantPolicy(result);
158
+ break;
151
159
  default:
152
160
  blockByDefault(result);
153
161
  }
@@ -162,6 +170,12 @@ Outcome taxonomy:
162
170
  - `control_abuse`: misuse of authorized tools or user privileges to send, change, approve, delete, operate, or bypass policy/RBAC without a stronger outcome.
163
171
  - `system_compromise`: privilege escalation, account takeover, hostile integration/plugin takeover, persistence, lateral movement, attacker webhook registration, or code/plugin execution.
164
172
  - `service_disruption`: downtime, lockout, degradation, alert suppression, destructive loops, resource exhaustion, cost spikes, or hidden outage evidence.
173
+ - `code_generation`: generation or material modification of executable code, scripts, workflows, or configuration.
174
+ - `story_script_generation`: generation of narrative prose, dialogue, scripts, or story artifacts.
175
+ - `game_generation`: generation of a game, quest, level, mechanic, or playable experience.
176
+ - `website_generation`: generation of a website, landing page, storefront, or web experience.
177
+ - `clickup_terms_violation`: content or actions that violate the configured ClickUp tenant policy.
178
+ - `traditional_ai_abuse`: unsafe AI assistance outside the concrete security outcome classes.
165
179
 
166
180
  ## Options
167
181
 
@@ -1,5 +1,5 @@
1
1
  import { BaseCallbackHandler } from '@langchain/core/callbacks/base';
2
- import { e as Firewall, L as LangChainAdapterOptions } from '../firewall-DNC9vSbq.cjs';
2
+ import { e as Firewall, L as LangChainAdapterOptions } from '../firewall-D2doJsD5.cjs';
3
3
 
4
4
  declare function createLangChainHandler(firewall: Firewall, options?: LangChainAdapterOptions): Promise<BaseCallbackHandler>;
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { BaseCallbackHandler } from '@langchain/core/callbacks/base';
2
- import { e as Firewall, L as LangChainAdapterOptions } from '../firewall-DNC9vSbq.js';
2
+ import { e as Firewall, L as LangChainAdapterOptions } from '../firewall-D2doJsD5.js';
3
3
 
4
4
  declare function createLangChainHandler(firewall: Firewall, options?: LangChainAdapterOptions): Promise<BaseCallbackHandler>;
5
5
 
@@ -1 +1 @@
1
- export { g as FirewallMiddleware, y as createMiddleware } from '../firewall-DNC9vSbq.cjs';
1
+ export { g as FirewallMiddleware, y as createMiddleware } from '../firewall-D2doJsD5.cjs';
@@ -1 +1 @@
1
- export { g as FirewallMiddleware, y as createMiddleware } from '../firewall-DNC9vSbq.js';
1
+ export { g as FirewallMiddleware, y as createMiddleware } from '../firewall-D2doJsD5.js';
@@ -33,6 +33,12 @@ declare const Outcome: {
33
33
  readonly ControlAbuse: "control_abuse";
34
34
  readonly SystemCompromise: "system_compromise";
35
35
  readonly ServiceDisruption: "service_disruption";
36
+ readonly CodeGeneration: "code_generation";
37
+ readonly StoryScriptGeneration: "story_script_generation";
38
+ readonly GameGeneration: "game_generation";
39
+ readonly WebsiteGeneration: "website_generation";
40
+ readonly ClickUpTermsViolation: "clickup_terms_violation";
41
+ readonly TraditionalAiAbuse: "traditional_ai_abuse";
36
42
  };
37
43
  declare const unknownOutcomeBrand: unique symbol;
38
44
  type KnownPrimaryOutcome = (typeof Outcome)[keyof typeof Outcome];
@@ -42,8 +48,8 @@ type UnknownOutcome = string & {
42
48
  };
43
49
  type PrimaryOutcome = KnownPrimaryOutcome | UnknownOutcome;
44
50
  type HarmfulOutcome = KnownHarmfulOutcome | UnknownOutcome;
45
- declare const PRIMARY_OUTCOMES: readonly ["benign", "information_disclosure", "secret_exposure", "control_abuse", "system_compromise", "service_disruption"];
46
- declare const HARMFUL_OUTCOMES: readonly ["information_disclosure", "secret_exposure", "control_abuse", "system_compromise", "service_disruption"];
51
+ declare const PRIMARY_OUTCOMES: readonly ["benign", "information_disclosure", "secret_exposure", "control_abuse", "system_compromise", "service_disruption", "code_generation", "story_script_generation", "game_generation", "website_generation", "clickup_terms_violation", "traditional_ai_abuse"];
52
+ declare const HARMFUL_OUTCOMES: readonly ["information_disclosure", "secret_exposure", "control_abuse", "system_compromise", "service_disruption", "code_generation", "story_script_generation", "game_generation", "website_generation", "clickup_terms_violation", "traditional_ai_abuse"];
47
53
  declare const OUTCOME_DESCRIPTIONS: {
48
54
  readonly benign: "No harmful firewall outcome detected.";
49
55
  readonly information_disclosure: "Exposes private data, documents, internal context, logs, traces, customer data, SQL rows, topology, or similar non-secret sensitive information.";
@@ -51,6 +57,12 @@ declare const OUTCOME_DESCRIPTIONS: {
51
57
  readonly control_abuse: "Misuses authorized tools or user privileges to send, change, approve, delete, operate, or bypass policy/RBAC without a stronger outcome.";
52
58
  readonly system_compromise: "Enables privilege escalation, account takeover, hostile integration or plugin takeover, persistence, lateral movement, attacker webhook registration, or code/plugin execution.";
53
59
  readonly service_disruption: "Causes downtime, lockout, degradation, alert suppression, destructive loops, resource exhaustion, cost spikes, or hidden outage evidence.";
60
+ readonly code_generation: "Requests generation or material modification of executable code, scripts, workflows, or configuration.";
61
+ readonly story_script_generation: "Requests generation of narrative prose, dialogue, scripts, or story artifacts.";
62
+ readonly game_generation: "Requests generation of a game, quest, level, mechanic, or playable experience.";
63
+ readonly website_generation: "Requests generation of a website, landing page, storefront, or web experience.";
64
+ readonly clickup_terms_violation: "Requests content or actions that violate the configured ClickUp tenant policy.";
65
+ readonly traditional_ai_abuse: "Requests unsafe AI assistance outside the concrete security outcome classes.";
54
66
  };
55
67
  declare function isPrimaryOutcome(value: unknown): value is KnownPrimaryOutcome;
56
68
  declare function isHarmfulOutcome(value: unknown): value is KnownHarmfulOutcome;
@@ -33,6 +33,12 @@ declare const Outcome: {
33
33
  readonly ControlAbuse: "control_abuse";
34
34
  readonly SystemCompromise: "system_compromise";
35
35
  readonly ServiceDisruption: "service_disruption";
36
+ readonly CodeGeneration: "code_generation";
37
+ readonly StoryScriptGeneration: "story_script_generation";
38
+ readonly GameGeneration: "game_generation";
39
+ readonly WebsiteGeneration: "website_generation";
40
+ readonly ClickUpTermsViolation: "clickup_terms_violation";
41
+ readonly TraditionalAiAbuse: "traditional_ai_abuse";
36
42
  };
37
43
  declare const unknownOutcomeBrand: unique symbol;
38
44
  type KnownPrimaryOutcome = (typeof Outcome)[keyof typeof Outcome];
@@ -42,8 +48,8 @@ type UnknownOutcome = string & {
42
48
  };
43
49
  type PrimaryOutcome = KnownPrimaryOutcome | UnknownOutcome;
44
50
  type HarmfulOutcome = KnownHarmfulOutcome | UnknownOutcome;
45
- declare const PRIMARY_OUTCOMES: readonly ["benign", "information_disclosure", "secret_exposure", "control_abuse", "system_compromise", "service_disruption"];
46
- declare const HARMFUL_OUTCOMES: readonly ["information_disclosure", "secret_exposure", "control_abuse", "system_compromise", "service_disruption"];
51
+ declare const PRIMARY_OUTCOMES: readonly ["benign", "information_disclosure", "secret_exposure", "control_abuse", "system_compromise", "service_disruption", "code_generation", "story_script_generation", "game_generation", "website_generation", "clickup_terms_violation", "traditional_ai_abuse"];
52
+ declare const HARMFUL_OUTCOMES: readonly ["information_disclosure", "secret_exposure", "control_abuse", "system_compromise", "service_disruption", "code_generation", "story_script_generation", "game_generation", "website_generation", "clickup_terms_violation", "traditional_ai_abuse"];
47
53
  declare const OUTCOME_DESCRIPTIONS: {
48
54
  readonly benign: "No harmful firewall outcome detected.";
49
55
  readonly information_disclosure: "Exposes private data, documents, internal context, logs, traces, customer data, SQL rows, topology, or similar non-secret sensitive information.";
@@ -51,6 +57,12 @@ declare const OUTCOME_DESCRIPTIONS: {
51
57
  readonly control_abuse: "Misuses authorized tools or user privileges to send, change, approve, delete, operate, or bypass policy/RBAC without a stronger outcome.";
52
58
  readonly system_compromise: "Enables privilege escalation, account takeover, hostile integration or plugin takeover, persistence, lateral movement, attacker webhook registration, or code/plugin execution.";
53
59
  readonly service_disruption: "Causes downtime, lockout, degradation, alert suppression, destructive loops, resource exhaustion, cost spikes, or hidden outage evidence.";
60
+ readonly code_generation: "Requests generation or material modification of executable code, scripts, workflows, or configuration.";
61
+ readonly story_script_generation: "Requests generation of narrative prose, dialogue, scripts, or story artifacts.";
62
+ readonly game_generation: "Requests generation of a game, quest, level, mechanic, or playable experience.";
63
+ readonly website_generation: "Requests generation of a website, landing page, storefront, or web experience.";
64
+ readonly clickup_terms_violation: "Requests content or actions that violate the configured ClickUp tenant policy.";
65
+ readonly traditional_ai_abuse: "Requests unsafe AI assistance outside the concrete security outcome classes.";
54
66
  };
55
67
  declare function isPrimaryOutcome(value: unknown): value is KnownPrimaryOutcome;
56
68
  declare function isHarmfulOutcome(value: unknown): value is KnownHarmfulOutcome;
package/dist/index.cjs CHANGED
@@ -685,7 +685,13 @@ var Outcome = {
685
685
  SecretExposure: "secret_exposure",
686
686
  ControlAbuse: "control_abuse",
687
687
  SystemCompromise: "system_compromise",
688
- ServiceDisruption: "service_disruption"
688
+ ServiceDisruption: "service_disruption",
689
+ CodeGeneration: "code_generation",
690
+ StoryScriptGeneration: "story_script_generation",
691
+ GameGeneration: "game_generation",
692
+ WebsiteGeneration: "website_generation",
693
+ ClickUpTermsViolation: "clickup_terms_violation",
694
+ TraditionalAiAbuse: "traditional_ai_abuse"
689
695
  };
690
696
  var PRIMARY_OUTCOMES = [
691
697
  Outcome.Benign,
@@ -693,14 +699,26 @@ var PRIMARY_OUTCOMES = [
693
699
  Outcome.SecretExposure,
694
700
  Outcome.ControlAbuse,
695
701
  Outcome.SystemCompromise,
696
- Outcome.ServiceDisruption
702
+ Outcome.ServiceDisruption,
703
+ Outcome.CodeGeneration,
704
+ Outcome.StoryScriptGeneration,
705
+ Outcome.GameGeneration,
706
+ Outcome.WebsiteGeneration,
707
+ Outcome.ClickUpTermsViolation,
708
+ Outcome.TraditionalAiAbuse
697
709
  ];
698
710
  var HARMFUL_OUTCOMES = [
699
711
  Outcome.InformationDisclosure,
700
712
  Outcome.SecretExposure,
701
713
  Outcome.ControlAbuse,
702
714
  Outcome.SystemCompromise,
703
- Outcome.ServiceDisruption
715
+ Outcome.ServiceDisruption,
716
+ Outcome.CodeGeneration,
717
+ Outcome.StoryScriptGeneration,
718
+ Outcome.GameGeneration,
719
+ Outcome.WebsiteGeneration,
720
+ Outcome.ClickUpTermsViolation,
721
+ Outcome.TraditionalAiAbuse
704
722
  ];
705
723
  var OUTCOME_DESCRIPTIONS = {
706
724
  [Outcome.Benign]: "No harmful firewall outcome detected.",
@@ -708,7 +726,13 @@ var OUTCOME_DESCRIPTIONS = {
708
726
  [Outcome.SecretExposure]: "Exposes credentials, tokens, API keys, cookies, passwords, signing keys, OAuth secrets, session material, or webhook secrets.",
709
727
  [Outcome.ControlAbuse]: "Misuses authorized tools or user privileges to send, change, approve, delete, operate, or bypass policy/RBAC without a stronger outcome.",
710
728
  [Outcome.SystemCompromise]: "Enables privilege escalation, account takeover, hostile integration or plugin takeover, persistence, lateral movement, attacker webhook registration, or code/plugin execution.",
711
- [Outcome.ServiceDisruption]: "Causes downtime, lockout, degradation, alert suppression, destructive loops, resource exhaustion, cost spikes, or hidden outage evidence."
729
+ [Outcome.ServiceDisruption]: "Causes downtime, lockout, degradation, alert suppression, destructive loops, resource exhaustion, cost spikes, or hidden outage evidence.",
730
+ [Outcome.CodeGeneration]: "Requests generation or material modification of executable code, scripts, workflows, or configuration.",
731
+ [Outcome.StoryScriptGeneration]: "Requests generation of narrative prose, dialogue, scripts, or story artifacts.",
732
+ [Outcome.GameGeneration]: "Requests generation of a game, quest, level, mechanic, or playable experience.",
733
+ [Outcome.WebsiteGeneration]: "Requests generation of a website, landing page, storefront, or web experience.",
734
+ [Outcome.ClickUpTermsViolation]: "Requests content or actions that violate the configured ClickUp tenant policy.",
735
+ [Outcome.TraditionalAiAbuse]: "Requests unsafe AI assistance outside the concrete security outcome classes."
712
736
  };
713
737
  var PRIMARY_OUTCOME_SET = new Set(PRIMARY_OUTCOMES);
714
738
  var HARMFUL_OUTCOME_SET = new Set(HARMFUL_OUTCOMES);
@@ -775,7 +799,7 @@ function sanitizeText(text) {
775
799
  }
776
800
 
777
801
  // src/firewall.ts
778
- var SDK_VERSION = "0.5.0";
802
+ var SDK_VERSION = "0.5.1";
779
803
  var DEFAULT_TIMEOUT_MS = 1e4;
780
804
  var DEFAULT_MAX_RETRIES = 5;
781
805
  var MAX_BACKOFF_SECONDS = 30;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/exceptions.ts","../src/hooks.ts","../src/utils/extract.ts","../src/adapters/langchain.ts","../src/index.ts","../src/firewall.ts","../src/adapters/vercel.ts","../src/outcomes.ts","../src/sanitization.ts"],"sourcesContent":["// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nimport type { HookLabel } from \"./hooks.js\";\nimport type { BlockResult } from \"./types.js\";\n\nconst MAX_PROMPT_DISPLAY_LEN = 100;\n\nexport interface MalformedInputDetails {\n field?: string;\n inputIndex?: number;\n charOffset?: number;\n malformedToken?: string;\n codePoint?: string;\n reason?: string;\n}\n\nexport class FirewallBlockedException extends Error {\n readonly score: number;\n readonly threshold: number;\n readonly promptText: string;\n readonly runId: string | undefined;\n readonly hook: HookLabel | undefined;\n readonly toolName: string | undefined;\n readonly toolCallId: string | undefined;\n readonly result: BlockResult | undefined;\n\n constructor(params: {\n score: number;\n threshold: number;\n promptText: string;\n runId?: string;\n hook?: HookLabel;\n toolName?: string;\n toolCallId?: string;\n result?: BlockResult;\n }) {\n super(FirewallBlockedException.formatMessage(params));\n this.name = \"FirewallBlockedException\";\n this.score = params.score;\n this.threshold = params.threshold;\n this.promptText = params.promptText;\n this.runId = params.runId;\n this.hook = params.hook;\n this.toolName = params.toolName;\n this.toolCallId = params.toolCallId;\n this.result = params.result;\n Object.setPrototypeOf(this, FirewallBlockedException.prototype);\n }\n\n private static formatMessage(params: {\n score: number;\n threshold: number;\n promptText: string;\n }): string {\n const truncated =\n params.promptText.length > MAX_PROMPT_DISPLAY_LEN\n ? `${params.promptText.slice(0, MAX_PROMPT_DISPLAY_LEN)}...`\n : params.promptText;\n return (\n `Request blocked by Silmaril Firewall ` +\n `(score=${params.score.toFixed(4)}, threshold=${params.threshold.toFixed(4)}): ` +\n `'${truncated}'`\n );\n }\n}\n\n/** @deprecated Use FirewallBlockedException instead. */\nexport const PromptBlockedException = FirewallBlockedException;\n/** @deprecated Use FirewallBlockedException instead. */\nexport type PromptBlockedException = FirewallBlockedException;\n\nexport class SilmarilApiError extends Error {\n readonly status: number;\n readonly statusText: string;\n readonly body: string;\n readonly details: MalformedInputDetails | undefined;\n readonly error: string | undefined;\n readonly apiMessage: string | undefined;\n\n constructor(params: {\n status: number;\n statusText: string;\n body: string;\n details?: MalformedInputDetails;\n error?: string;\n apiMessage?: string;\n }) {\n const statusText = params.statusText ? ` ${params.statusText}` : \"\";\n super(`Silmaril API error ${params.status}${statusText}`);\n this.name = \"SilmarilApiError\";\n this.status = params.status;\n this.statusText = params.statusText;\n this.body = params.body;\n const parsed = parseErrorBody(params.body);\n this.details = params.details ?? parsed.details;\n this.error = params.error ?? parsed.error;\n this.apiMessage = params.apiMessage ?? parsed.apiMessage;\n Object.setPrototypeOf(this, SilmarilApiError.prototype);\n }\n}\n\nfunction parseErrorBody(body: string): {\n details: MalformedInputDetails | undefined;\n error: string | undefined;\n apiMessage: string | undefined;\n} {\n try {\n const parsed = JSON.parse(body) as unknown;\n if (!parsed || typeof parsed !== \"object\") {\n return { details: undefined, error: undefined, apiMessage: undefined };\n }\n const data = parsed as Record<string, unknown>;\n return {\n details:\n data.details && typeof data.details === \"object\"\n ? (data.details as MalformedInputDetails)\n : undefined,\n error: typeof data.error === \"string\" ? data.error : undefined,\n apiMessage: typeof data.message === \"string\" ? data.message : undefined,\n };\n } catch {\n return { details: undefined, error: undefined, apiMessage: undefined };\n }\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nexport const HookLabel = {\n USER_INPUT: \"user_input\",\n SYSTEM_PROMPT: \"system_prompt\",\n TOOL_CALL: \"tool_call\",\n TOOL_RESPONSE: \"tool_response\",\n LLM_OUTPUT: \"llm_output\",\n UNKNOWN: \"unknown\",\n} as const;\n\nexport type HookLabel = (typeof HookLabel)[keyof typeof HookLabel];\n\nexport const FirewallHook = {\n LLM_START: \"on_llm_start\",\n CHAT_MODEL_START: \"on_chat_model_start\",\n TOOL_START: \"on_tool_start\",\n RETRIEVER_START: \"on_retriever_start\",\n LLM_END: \"on_llm_end\",\n TOOL_END: \"on_tool_end\",\n RETRIEVER_END: \"on_retriever_end\",\n} as const;\n\nexport type FirewallHook = (typeof FirewallHook)[keyof typeof FirewallHook];\n\nexport const DEFAULT_HOOKS: ReadonlySet<FirewallHook> = new Set<FirewallHook>([\n FirewallHook.LLM_START,\n FirewallHook.CHAT_MODEL_START,\n]);\n\nexport const INPUT_HOOKS: ReadonlySet<FirewallHook> = new Set<FirewallHook>([\n FirewallHook.LLM_START,\n FirewallHook.CHAT_MODEL_START,\n FirewallHook.TOOL_START,\n FirewallHook.RETRIEVER_START,\n]);\n\nexport const OUTPUT_HOOKS: ReadonlySet<FirewallHook> = new Set<FirewallHook>([\n FirewallHook.LLM_END,\n FirewallHook.TOOL_END,\n FirewallHook.RETRIEVER_END,\n]);\n\nexport const ALL_HOOKS: ReadonlySet<FirewallHook> = new Set<FirewallHook>([\n ...INPUT_HOOKS,\n ...OUTPUT_HOOKS,\n]);\n\nexport const FIREWALL_HOOK_TO_LABEL: Readonly<Record<FirewallHook, HookLabel>> = {\n [FirewallHook.CHAT_MODEL_START]: HookLabel.USER_INPUT,\n [FirewallHook.LLM_START]: HookLabel.USER_INPUT,\n [FirewallHook.TOOL_START]: HookLabel.TOOL_CALL,\n [FirewallHook.TOOL_END]: HookLabel.TOOL_RESPONSE,\n [FirewallHook.RETRIEVER_START]: HookLabel.TOOL_CALL,\n [FirewallHook.RETRIEVER_END]: HookLabel.TOOL_RESPONSE,\n [FirewallHook.LLM_END]: HookLabel.LLM_OUTPUT,\n};\n\nconst FIREWALL_HOOK_VALUES: ReadonlySet<string> = new Set(Object.values(FirewallHook));\n\nexport function resolveHooks(\n hooks: Iterable<FirewallHook | string> | undefined,\n): ReadonlySet<FirewallHook> {\n if (hooks === undefined) {\n return DEFAULT_HOOKS;\n }\n const resolved = new Set<FirewallHook>();\n for (const h of hooks) {\n if (!FIREWALL_HOOK_VALUES.has(h)) {\n throw new Error(`Invalid FirewallHook value: ${String(h)}`);\n }\n resolved.add(h as FirewallHook);\n }\n return resolved;\n}\n\nexport function prependHook(text: string, hook: HookLabel | string | undefined | null): string {\n if (hook === undefined || hook === null) {\n return text;\n }\n if (hook === HookLabel.UNKNOWN) {\n return text;\n }\n return `[HOOK:${hook}] ${text}`;\n}\n\nexport function prependToolName(text: string, toolName: string | undefined | null): string {\n if (toolName === undefined || toolName === null) {\n return text;\n }\n return `[TOOL:${toolName}] ${text}`;\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nconst SKIP_ROLES: ReadonlySet<string> = new Set([\"ai\", \"assistant\"]);\nconst SYSTEM_ROLES: ReadonlySet<string> = new Set([\"system\"]);\nconst TOOL_ROLES: ReadonlySet<string> = new Set([\"tool\", \"function\"]);\n\ntype MessageContent = string | ReadonlyArray<string | { type?: string; text?: string }>;\n\ninterface DucktypedMessage {\n role?: string;\n type?: string;\n content?: MessageContent;\n}\n\ninterface DucktypedGeneration {\n text?: string;\n}\n\ninterface DucktypedLLMResult {\n generations?: ReadonlyArray<ReadonlyArray<DucktypedGeneration>>;\n}\n\ninterface DucktypedDocument {\n pageContent?: string;\n}\n\nfunction extractContentText(content: MessageContent | undefined): string {\n if (typeof content === \"string\") {\n return content;\n }\n if (Array.isArray(content)) {\n const parts: string[] = [];\n for (const block of content) {\n if (typeof block === \"string\") {\n parts.push(block);\n } else if (block && typeof block === \"object\" && block.type === \"text\") {\n parts.push(block.text ?? \"\");\n }\n }\n return parts.join(\" \");\n }\n return \"\";\n}\n\nfunction getRole(message: DucktypedMessage): string {\n if (message.role !== undefined) {\n return message.role.toLowerCase();\n }\n if (typeof message.type === \"string\") {\n return message.type.toLowerCase();\n }\n return \"\";\n}\n\nexport function extractTextFromMessages(\n messages: ReadonlyArray<DucktypedMessage>,\n options: { includeSystem?: boolean; includeTool?: boolean } = {},\n): string {\n const includeSystem = options.includeSystem ?? true;\n const includeTool = options.includeTool ?? true;\n const parts: string[] = [];\n for (const message of messages) {\n const role = getRole(message);\n if (SKIP_ROLES.has(role)) {\n continue;\n }\n if (!includeSystem && SYSTEM_ROLES.has(role)) {\n continue;\n }\n if (!includeTool && TOOL_ROLES.has(role)) {\n continue;\n }\n const text = extractContentText(message.content);\n const stripped = text.trim();\n if (stripped) {\n parts.push(stripped);\n }\n }\n return parts.join(\"\\n\");\n}\n\nexport function extractTextFromPrompts(prompts: readonly string[]): string {\n return prompts\n .map((p) => p.trim())\n .filter((p) => p.length > 0)\n .join(\"\\n\");\n}\n\nexport function extractTextFromToolInput(inputStr: string): string {\n return inputStr.trim();\n}\n\nexport function extractTextFromLLMResult(response: DucktypedLLMResult): string {\n const parts: string[] = [];\n for (const genList of response.generations ?? []) {\n for (const gen of genList) {\n const text = (gen.text ?? \"\").trim();\n if (text) {\n parts.push(text);\n }\n }\n }\n return parts.join(\"\\n\");\n}\n\nexport function extractTextFromDocuments(documents: ReadonlyArray<DucktypedDocument>): string {\n const parts: string[] = [];\n for (const doc of documents) {\n const text = (doc.pageContent ?? \"\").trim();\n if (text) {\n parts.push(text);\n }\n }\n return parts.join(\"\\n\");\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nimport type { BaseCallbackHandler } from \"@langchain/core/callbacks/base\";\n\nimport type { Firewall } from \"../firewall.js\";\nimport { FirewallBlockedException } from \"../exceptions.js\";\nimport {\n FIREWALL_HOOK_TO_LABEL,\n FirewallHook,\n HookLabel,\n resolveHooks,\n} from \"../hooks.js\";\nimport type { BlockResult, ClassifyEvent, LangChainAdapterOptions } from \"../types.js\";\nimport {\n extractTextFromDocuments,\n extractTextFromLLMResult,\n extractTextFromPrompts,\n extractTextFromToolInput,\n} from \"../utils/extract.js\";\n\nconst USER_ROLES: ReadonlySet<string> = new Set([\"human\", \"user\"]);\n\ninterface LangChainDucktypedMessage {\n role?: string;\n type?: string;\n content?: string | ReadonlyArray<string | { type?: string; text?: string }>;\n}\n\nfunction getMessageRole(message: LangChainDucktypedMessage): string {\n if (typeof message.role === \"string\") {\n return message.role.toLowerCase();\n }\n if (typeof message.type === \"string\") {\n return message.type.toLowerCase();\n }\n return \"\";\n}\n\nfunction extractMessageText(content: LangChainDucktypedMessage[\"content\"]): string {\n if (content === undefined) {\n return \"\";\n }\n if (typeof content === \"string\") {\n return content;\n }\n const parts: string[] = [];\n for (const block of content) {\n if (typeof block === \"string\") {\n parts.push(block);\n } else if (block && block.type === \"text\") {\n parts.push(block.text ?? \"\");\n }\n }\n return parts.join(\" \");\n}\n\nfunction findLastUserMessage(\n messages: ReadonlyArray<LangChainDucktypedMessage>,\n): LangChainDucktypedMessage | undefined {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]!;\n if (USER_ROLES.has(getMessageRole(msg))) {\n return msg;\n }\n }\n return undefined;\n}\n\nexport async function createLangChainHandler(\n firewall: Firewall,\n options: LangChainAdapterOptions = {},\n): Promise<BaseCallbackHandler> {\n const { BaseCallbackHandler } = await import(\"@langchain/core/callbacks/base\");\n\n const enabledHooks = resolveHooks(options.hooks);\n // includeSystem / includeTool are retained in LangChainAdapterOptions for\n // backwards compat but are inert under the per-message hook-routing algorithm:\n // handleChatModelStart only scans the last user-role message; system and tool\n // messages are either trusted or already classified by their own hooks.\n const failOpen = options.failOpen ?? true;\n const logger =\n options.logger ??\n ((message: string, error: unknown): void => {\n // eslint-disable-next-line no-console\n console.warn(`silmaril.firewall: ${message}`, error);\n });\n const shadowMode = options.shadowMode ?? firewall.shadowMode;\n const onClassify = options.onClassify;\n\n const fireOnClassify = (event: ClassifyEvent): void => {\n if (!onClassify) {\n return;\n }\n try {\n onClassify(event);\n } catch (err) {\n logger(\"onClassify callback threw\", err);\n }\n };\n\n const classify = async (\n text: string,\n hookLabel: HookLabel,\n runId: string,\n toolName?: string,\n ): Promise<void> => {\n let result: BlockResult;\n try {\n result = await firewall.classify(text, {\n hook: hookLabel,\n ...(toolName !== undefined ? { toolName } : {}),\n });\n } catch (err) {\n if (!failOpen) {\n throw err;\n }\n logger(\"classification failed, allowing prompt through\", err);\n return;\n }\n const threshold = result.threshold;\n const blocked = result.prediction === \"MALICIOUS\";\n const commonEventFields = {\n hook: hookLabel,\n ...(toolName !== undefined ? { toolName } : {}),\n runId,\n text,\n result,\n };\n fireOnClassify({\n ...commonEventFields,\n blocked,\n shadowMode,\n });\n if (!blocked || shadowMode) {\n return;\n }\n\n throw new FirewallBlockedException({\n score: result.score,\n threshold,\n promptText: text,\n runId,\n hook: hookLabel,\n ...(toolName !== undefined ? { toolName } : {}),\n result,\n });\n };\n\n class SilmarilFirewallHandler extends BaseCallbackHandler {\n override name = \"silmaril_firewall_handler\";\n override raiseError = true;\n override awaitHandlers = true;\n\n override async handleChatModelStart(\n _llm: unknown,\n messages: unknown,\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.CHAT_MODEL_START)) {\n return;\n }\n const batches = messages as ReadonlyArray<ReadonlyArray<LangChainDucktypedMessage>>;\n const flat: LangChainDucktypedMessage[] = [];\n for (const batch of batches) {\n for (const m of batch) {\n flat.push(m);\n }\n }\n const lastUser = findLastUserMessage(flat);\n if (!lastUser) {\n return;\n }\n const text = extractMessageText(lastUser.content).trim();\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.CHAT_MODEL_START], runId);\n }\n\n override async handleLLMStart(\n _llm: unknown,\n prompts: string[],\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.LLM_START)) {\n return;\n }\n const text = extractTextFromPrompts(prompts);\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.LLM_START], runId);\n }\n\n override async handleToolStart(\n tool: { name?: string } | undefined,\n inputStr: string,\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.TOOL_START)) {\n return;\n }\n const text = extractTextFromToolInput(inputStr);\n if (!text) {\n return;\n }\n const toolName = tool?.name;\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.TOOL_START], runId, toolName);\n }\n\n override async handleRetrieverStart(\n _retriever: unknown,\n query: string,\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.RETRIEVER_START)) {\n return;\n }\n const text = query.trim();\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.RETRIEVER_START], runId);\n }\n\n override async handleLLMEnd(output: unknown, runId: string): Promise<void> {\n if (!enabledHooks.has(FirewallHook.LLM_END)) {\n return;\n }\n const text = extractTextFromLLMResult(output as { generations?: ReadonlyArray<ReadonlyArray<{ text?: string }>> });\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.LLM_END], runId);\n }\n\n override async handleToolEnd(\n output: unknown,\n runId: string,\n _parentRunId?: string,\n _tags?: string[],\n _kwargs?: { name?: string },\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.TOOL_END)) {\n return;\n }\n const text = String(output).trim();\n if (!text) {\n return;\n }\n const toolName = _kwargs?.name;\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.TOOL_END], runId, toolName);\n }\n\n override async handleRetrieverEnd(\n documents: ReadonlyArray<{ pageContent?: string }>,\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.RETRIEVER_END)) {\n return;\n }\n const text = extractTextFromDocuments(documents);\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.RETRIEVER_END], runId);\n }\n }\n\n return new SilmarilFirewallHandler();\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nexport {\n Firewall,\n DEFAULT_TIMEOUT_MS,\n} from \"./firewall.js\";\n\nexport { FirewallBlockedException, PromptBlockedException, SilmarilApiError } from \"./exceptions.js\";\nexport type { MalformedInputDetails } from \"./exceptions.js\";\n\nexport type { FirewallMiddleware } from \"./adapters/vercel.js\";\n\nexport {\n HookLabel,\n FirewallHook,\n DEFAULT_HOOKS,\n INPUT_HOOKS,\n OUTPUT_HOOKS,\n ALL_HOOKS,\n FIREWALL_HOOK_TO_LABEL,\n resolveHooks,\n prependHook,\n prependToolName,\n} from \"./hooks.js\";\n\nexport {\n Outcome,\n PRIMARY_OUTCOMES,\n HARMFUL_OUTCOMES,\n OUTCOME_DESCRIPTIONS,\n isPrimaryOutcome,\n isHarmfulOutcome,\n normalizePrimaryOutcome,\n normalizeHarmfulOutcome,\n normalizeHarmfulOutcomeMap,\n} from \"./outcomes.js\";\n\nexport type {\n KnownPrimaryOutcome,\n KnownHarmfulOutcome,\n PrimaryOutcome,\n HarmfulOutcome,\n UnknownOutcome,\n} from \"./outcomes.js\";\n\nexport type {\n BlockResult,\n ClassifyEvent,\n Prediction,\n ClassificationMetadata,\n FirewallOptions,\n ClassifyOptions,\n ClassifyBatchOptions,\n LangChainAdapterOptions,\n LangChainFirewallHandler,\n MiddlewareOptions,\n} from \"./types.js\";\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nimport { randomUUID } from \"node:crypto\";\n\nimport { createMiddleware, type FirewallMiddleware } from \"./adapters/vercel.js\";\nimport { SilmarilApiError } from \"./exceptions.js\";\nimport { normalizeHarmfulOutcomeMap, normalizePrimaryOutcome } from \"./outcomes.js\";\nimport { sanitizeText } from \"./sanitization.js\";\nimport type {\n BlockResult,\n ClassifyBatchOptions,\n ClassifyOptions,\n ClassificationMetadata,\n FirewallOptions,\n LangChainAdapterOptions,\n LangChainFirewallHandler,\n MiddlewareOptions,\n Prediction,\n} from \"./types.js\";\n\nexport const SDK_VERSION = \"0.5.0\";\nexport const DEFAULT_TIMEOUT_MS = 10_000;\nconst DEFAULT_MAX_RETRIES = 5;\nconst MAX_BACKOFF_SECONDS = 30;\nconst MAX_ERROR_BODY_BYTES = 1 << 16;\n\ninterface SingleClassifyPayload {\n text: string;\n hook?: string;\n tool_name?: string;\n metadata?: ClassificationMetadata;\n}\n\ninterface BatchClassifyPayload {\n texts: readonly string[];\n hooks?: readonly string[];\n tool_names?: readonly (string | null)[];\n metadata?: readonly (ClassificationMetadata | null)[];\n}\n\ninterface SingleClassifyResponse {\n prediction: Prediction;\n score: number;\n threshold: number;\n primary_outcome?: unknown;\n outcome_scores?: unknown;\n detector_scores?: unknown;\n detector_counts?: unknown;\n}\n\ninterface BatchClassifyResponse {\n predictions: readonly SingleClassifyResponse[];\n}\n\nfunction blockResultFromResponse(data: SingleClassifyResponse): BlockResult {\n if (data.prediction !== \"BENIGN\" && data.prediction !== \"MALICIOUS\") {\n throw new Error(\"Firewall: response prediction must be BENIGN or MALICIOUS\");\n }\n const result: {\n prediction: Prediction;\n score: number;\n threshold: number;\n primaryOutcome?: NonNullable<BlockResult[\"primaryOutcome\"]>;\n outcomeScores?: NonNullable<BlockResult[\"outcomeScores\"]>;\n detectorScores?: NonNullable<BlockResult[\"detectorScores\"]>;\n detectorCounts?: NonNullable<BlockResult[\"detectorCounts\"]>;\n } = {\n prediction: data.prediction,\n score: Number(data.score),\n threshold: Number(data.threshold),\n };\n if (data.primary_outcome !== undefined) {\n result.primaryOutcome = normalizePrimaryOutcome(data.primary_outcome);\n }\n if (data.outcome_scores !== undefined) {\n const outcomeScores = normalizeHarmfulOutcomeMap(data.outcome_scores, \"outcome_scores\");\n if (outcomeScores !== undefined) {\n result.outcomeScores = outcomeScores;\n }\n }\n if (data.detector_scores !== undefined) {\n const detectorScores = normalizeHarmfulOutcomeMap(data.detector_scores, \"detector_scores\");\n if (detectorScores !== undefined) {\n result.detectorScores = detectorScores;\n }\n }\n if (data.detector_counts !== undefined) {\n const detectorCounts = normalizeHarmfulOutcomeMap(data.detector_counts, \"detector_counts\");\n if (detectorCounts !== undefined) {\n result.detectorCounts = detectorCounts;\n }\n }\n return Object.freeze(result);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction withSdkMetadata(\n metadata: ClassificationMetadata | undefined,\n info: {\n requestId: string;\n inputIndex?: number;\n },\n): ClassificationMetadata {\n const payload: Record<string, unknown> = { ...(metadata ?? {}) };\n const existing = payload.silmaril;\n if (existing !== undefined && !isRecord(existing)) {\n throw new Error(\"Firewall: metadata.silmaril must be an object when provided\");\n }\n payload.silmaril = {\n ...(isRecord(existing) ? existing : {}),\n sdk_language: \"typescript\",\n sdk_version: SDK_VERSION,\n request_id: info.requestId,\n ...(info.inputIndex === undefined ? {} : { input_index: info.inputIndex }),\n };\n return payload;\n}\n\nasync function readCappedErrorBody(response: Response): Promise<string> {\n if (!response.body) {\n return response.text().then((body) => body.slice(0, MAX_ERROR_BODY_BYTES)).catch(() => \"\");\n }\n\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let remaining = MAX_ERROR_BODY_BYTES;\n try {\n while (remaining > 0) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n if (!value) {\n continue;\n }\n const chunk = value.byteLength > remaining ? value.slice(0, remaining) : value;\n chunks.push(chunk);\n remaining -= chunk.byteLength;\n if (chunk.byteLength < value.byteLength) {\n break;\n }\n }\n } catch {\n return \"\";\n } finally {\n await reader.cancel().catch(() => undefined);\n }\n\n const total = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);\n const body = new Uint8Array(total);\n let offset = 0;\n for (const chunk of chunks) {\n body.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return new TextDecoder().decode(body);\n}\n\nexport class Firewall {\n readonly apiKey: string;\n readonly apiUrl: string;\n readonly timeoutMs: number;\n readonly shadowMode: boolean;\n\n private readonly headers: Readonly<Record<string, string>>;\n\n constructor(options: FirewallOptions) {\n if (!options.apiKey) {\n throw new Error(\"Firewall: apiKey is required\");\n }\n if (!options.apiUrl) {\n throw new Error(\"Firewall: apiUrl is required\");\n }\n this.apiKey = options.apiKey;\n this.apiUrl = options.apiUrl;\n this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n if (typeof this.timeoutMs !== \"number\" || !Number.isFinite(this.timeoutMs) || this.timeoutMs < 0) {\n throw new Error(`Firewall: timeoutMs must be a finite non-negative number, got ${this.timeoutMs}`);\n }\n this.shadowMode = options.shadowMode ?? false;\n this.headers = Object.freeze({\n \"x-api-key\": this.apiKey,\n \"content-type\": \"application/json\",\n });\n }\n\n async classify(text: string, options: ClassifyOptions = {}): Promise<BlockResult> {\n const requestId = options.requestId ?? randomUUID();\n return this.classifySingle(sanitizeText(text), options, { requestId });\n }\n\n async classifyBatch(\n texts: readonly string[],\n options: ClassifyBatchOptions = {},\n ): Promise<BlockResult[]> {\n if (texts.length === 0) {\n throw new Error(\"Firewall: texts must not be empty\");\n }\n if (options.hooks !== undefined && options.hooks.length !== texts.length) {\n throw new Error(\n `Firewall: hooks length ${options.hooks.length} does not match texts length ${texts.length}`,\n );\n }\n if (options.toolNames !== undefined && options.toolNames.length !== texts.length) {\n throw new Error(\n `Firewall: toolNames length ${options.toolNames.length} does not match texts length ${texts.length}`,\n );\n }\n if (options.metadata !== undefined && options.metadata.length !== texts.length) {\n throw new Error(\n `Firewall: metadata length ${options.metadata.length} does not match texts length ${texts.length}`,\n );\n }\n\n const requestId = options.requestId ?? randomUUID();\n const payload: BatchClassifyPayload = {\n texts: texts.map((text) => sanitizeText(text)),\n };\n if (options.hooks && options.hooks.length > 0) {\n payload.hooks = options.hooks.map((h) => String(h));\n }\n if (options.toolNames && options.toolNames.length > 0) {\n payload.tool_names = options.toolNames.map((t) => (t === undefined ? null : t));\n }\n payload.metadata = texts.map((_, index) =>\n withSdkMetadata(options.metadata?.[index], {\n requestId,\n inputIndex: index,\n }),\n );\n const data = await this.postWithRetry<BatchClassifyResponse>(payload);\n return data.predictions.map((p) => blockResultFromResponse(p));\n }\n\n asLangChainHandler<THandler = LangChainFirewallHandler>(\n options: LangChainAdapterOptions = {},\n ): Promise<THandler> {\n return import(\"./adapters/langchain.js\").then((m) =>\n m.createLangChainHandler(this, options) as Promise<THandler>,\n );\n }\n\n asMiddleware(options: MiddlewareOptions = {}): FirewallMiddleware {\n return createMiddleware(this, options);\n }\n\n private async postWithRetry<T>(\n payload: SingleClassifyPayload | BatchClassifyPayload,\n maxRetries: number = DEFAULT_MAX_RETRIES,\n ): Promise<T> {\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const response = await fetch(this.apiUrl, {\n method: \"POST\",\n headers: this.headers,\n body: JSON.stringify(payload),\n redirect: \"error\",\n signal: AbortSignal.timeout(this.timeoutMs),\n });\n if (response.status !== 429 || attempt === maxRetries) {\n if (!response.ok) {\n const body = await readCappedErrorBody(response);\n throw new SilmarilApiError({\n status: response.status,\n statusText: response.statusText,\n body,\n });\n }\n return (await response.json()) as T;\n }\n const waitSeconds = Math.min(2 ** attempt, MAX_BACKOFF_SECONDS);\n await new Promise<void>((resolve) => setTimeout(resolve, waitSeconds * 1000));\n }\n throw new Error(\"Firewall: exhausted retries (unreachable)\");\n }\n\n private async classifySingle(\n text: string,\n options: ClassifyOptions,\n metadataInfo: {\n requestId: string;\n },\n ): Promise<BlockResult> {\n const payload: SingleClassifyPayload = { text };\n if (options.hook !== undefined) {\n payload.hook = options.hook;\n }\n if (options.toolName !== undefined) {\n payload.tool_name = options.toolName;\n }\n payload.metadata = withSdkMetadata(options.metadata, metadataInfo);\n const data = await this.postWithRetry<SingleClassifyResponse>(payload);\n return blockResultFromResponse(data);\n }\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nimport type { Firewall } from \"../firewall.js\";\nimport { FirewallBlockedException } from \"../exceptions.js\";\nimport { HookLabel } from \"../hooks.js\";\nimport type { BlockResult, MiddlewareOptions } from \"../types.js\";\n\ninterface VercelContentPart {\n type?: string;\n text?: string;\n toolCallId?: string;\n toolName?: string;\n args?: unknown;\n output?: unknown;\n result?: unknown;\n}\n\ninterface VercelPromptMessage {\n role: string;\n content: string | ReadonlyArray<VercelContentPart | string>;\n}\n\ninterface VercelToolCall {\n toolCallType?: string;\n toolCallId?: string;\n toolName?: string;\n args?: unknown;\n input?: unknown;\n}\n\ninterface VercelGenerateResult {\n text?: string;\n toolCalls?: ReadonlyArray<VercelToolCall>;\n}\n\ninterface WrapGenerateArgs<TResult extends VercelGenerateResult & Record<string, unknown>> {\n params: { prompt?: ReadonlyArray<VercelPromptMessage> } & Record<string, unknown>;\n doGenerate: () => PromiseLike<TResult>;\n}\n\ninterface WrapStreamArgs<\n TResult extends { stream: ReadableStream<unknown> } & Record<string, unknown>,\n> {\n params: { prompt?: ReadonlyArray<VercelPromptMessage> } & Record<string, unknown>;\n doStream: () => PromiseLike<TResult>;\n}\n\ninterface StreamPart {\n type?: string;\n textDelta?: string;\n delta?: string;\n}\n\ninterface VercelStepContext {\n toolName: string | undefined;\n toolCallId: string | undefined;\n}\n\nfunction stringifyToolValue(value: unknown): string {\n if (value === null || value === undefined) {\n return \"\";\n }\n if (typeof value === \"string\") {\n return value;\n }\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction extractContentText(content: VercelPromptMessage[\"content\"]): string {\n if (typeof content === \"string\") {\n return content;\n }\n const parts: string[] = [];\n for (const block of content) {\n if (typeof block === \"string\") {\n parts.push(block);\n } else if (block && block.type === \"text\") {\n parts.push(block.text ?? \"\");\n }\n }\n return parts.join(\" \");\n}\n\nfunction iterateToolResultParts(\n message: VercelPromptMessage,\n): Array<{ text: string; toolName: string | undefined; toolCallId: string | undefined }> {\n if (typeof message.content === \"string\") {\n return [];\n }\n const out: Array<{ text: string; toolName: string | undefined; toolCallId: string | undefined }> = [];\n for (const part of message.content) {\n if (typeof part === \"string\") {\n continue;\n }\n if (part.type === \"tool-result\") {\n const text = stringifyToolResult(part.result !== undefined ? part.result : part.output);\n if (text.trim()) {\n out.push({ text, toolName: part.toolName, toolCallId: part.toolCallId });\n }\n }\n }\n return out;\n}\n\nfunction stringifyToolResult(value: unknown): string {\n if (!isRecord(value)) {\n return stringifyToolValue(value);\n }\n if ((value.type === \"text\" || value.type === \"error-text\") && typeof value.value === \"string\") {\n return value.value;\n }\n if ((value.type === \"json\" || value.type === \"error-json\") && value.value !== undefined) {\n return stringifyToolValue(value.value);\n }\n if (value.type === \"content\" && Array.isArray(value.value)) {\n return value.value\n .map((part) => (isRecord(part) && part.type === \"text\" && typeof part.text === \"string\" ? part.text : \"\"))\n .filter((text) => text.length > 0)\n .join(\" \");\n }\n return stringifyToolValue(value);\n}\n\nfunction findLastUserMessage(\n messages: ReadonlyArray<VercelPromptMessage>,\n): VercelPromptMessage | undefined {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]!;\n if (msg.role.toLowerCase() === \"user\") {\n return msg;\n }\n }\n return undefined;\n}\n\nexport interface FirewallMiddleware {\n readonly specificationVersion: \"v3\";\n readonly middlewareVersion: \"v2\";\n wrapGenerate: <TResult extends VercelGenerateResult & Record<string, unknown>>(\n args: WrapGenerateArgs<TResult>,\n ) => Promise<TResult>;\n wrapStream: <TResult extends { stream: ReadableStream<unknown> } & Record<string, unknown>>(\n args: WrapStreamArgs<TResult>,\n ) => Promise<TResult>;\n}\n\nexport function createMiddleware(\n firewall: Firewall,\n options: MiddlewareOptions = {},\n): FirewallMiddleware {\n const scanInput = options.scanInput ?? true;\n const scanOutput = options.scanOutput ?? false;\n const shadowMode = options.shadowMode ?? firewall.shadowMode;\n\n const classifyOrBlock = async (\n text: string,\n hook: HookLabel,\n context: VercelStepContext = { toolName: undefined, toolCallId: undefined },\n ): Promise<void> => {\n if (!text.trim()) {\n return;\n }\n const { toolName, toolCallId } = context;\n const result: BlockResult = await firewall.classify(\n text,\n toolName !== undefined ? { hook, toolName } : { hook },\n );\n const threshold = result.threshold;\n const blocked = result.prediction === \"MALICIOUS\";\n const commonEventFields = {\n hook,\n ...(toolName !== undefined ? { toolName } : {}),\n ...(toolCallId !== undefined ? { toolCallId } : {}),\n text,\n result,\n };\n options.onClassify?.({\n ...commonEventFields,\n blocked,\n shadowMode,\n });\n if (!blocked || shadowMode) {\n return;\n }\n\n const err = new FirewallBlockedException({\n score: result.score,\n threshold,\n promptText: text,\n hook,\n ...(toolName !== undefined ? { toolName } : {}),\n ...(toolCallId !== undefined ? { toolCallId } : {}),\n result,\n });\n options.onBlocked?.(err);\n throw err;\n };\n\n const scanPrompt = async (prompt: ReadonlyArray<VercelPromptMessage>): Promise<void> => {\n if (prompt.length === 0) {\n return;\n }\n const last = prompt[prompt.length - 1]!;\n const role = last.role.toLowerCase();\n\n // If the newest message is a tool result (typical mid-flow in a\n // tool-calling loop), classify each tool-result part individually with\n // tool_response + toolName. No manual wiring from the caller — the\n // toolName is read directly from the Vercel content part.\n if (role === \"tool\") {\n for (const { text, toolName, toolCallId } of iterateToolResultParts(last)) {\n await classifyOrBlock(text, HookLabel.TOOL_RESPONSE, { toolName, toolCallId });\n }\n return;\n }\n\n // Otherwise, fall back to scanning the most recent user message.\n // Covers: [user], [system, user], [user, assistant(text), user], etc.\n const lastUser = findLastUserMessage(prompt);\n if (!lastUser) {\n return;\n }\n const text = extractContentText(lastUser.content).trim();\n if (!text) {\n return;\n }\n await classifyOrBlock(text, HookLabel.USER_INPUT);\n };\n\n const scanGenerateResult = async (result: VercelGenerateResult): Promise<void> => {\n if (scanOutput && typeof result.text === \"string\" && result.text.length > 0) {\n await classifyOrBlock(result.text, HookLabel.LLM_OUTPUT);\n }\n if (options.scanToolCalls && Array.isArray(result.toolCalls)) {\n for (const call of result.toolCalls) {\n if (!call || typeof call !== \"object\") {\n continue;\n }\n const toolInput = call.args !== undefined ? call.args : call.input;\n const args =\n typeof toolInput === \"string\" ? toolInput : stringifyToolValue(toolInput);\n const toolName = typeof call.toolName === \"string\" ? call.toolName : undefined;\n const toolCallId = typeof call.toolCallId === \"string\" ? call.toolCallId : undefined;\n if (args.trim()) {\n await classifyOrBlock(args, HookLabel.TOOL_CALL, { toolName, toolCallId });\n }\n }\n }\n };\n\n return {\n specificationVersion: \"v3\",\n middlewareVersion: \"v2\",\n\n async wrapGenerate<TResult extends VercelGenerateResult & Record<string, unknown>>({\n params,\n doGenerate,\n }: WrapGenerateArgs<TResult>): Promise<TResult> {\n if (scanInput) {\n await scanPrompt(params.prompt ?? []);\n }\n const result = await doGenerate();\n await scanGenerateResult(result);\n return result;\n },\n\n async wrapStream<TResult extends { stream: ReadableStream<unknown> } & Record<string, unknown>>({\n params,\n doStream,\n }: WrapStreamArgs<TResult>): Promise<TResult> {\n if (scanInput) {\n await scanPrompt(params.prompt ?? []);\n }\n const { stream, ...rest } = await doStream();\n if (!scanOutput) {\n return { stream, ...rest } as unknown as TResult;\n }\n\n let buffered = \"\";\n const transformed = stream.pipeThrough(\n new TransformStream<unknown, unknown>({\n transform(chunk, controller): void {\n const part = chunk as StreamPart;\n if (part && part.type === \"text-delta\") {\n const delta = part.textDelta ?? part.delta ?? \"\";\n buffered += delta;\n }\n controller.enqueue(chunk);\n },\n async flush(controller): Promise<void> {\n if (!buffered.trim()) {\n return;\n }\n try {\n await classifyOrBlock(buffered, HookLabel.LLM_OUTPUT);\n } catch (err) {\n if (err instanceof FirewallBlockedException) {\n controller.enqueue({ type: \"error\", error: err });\n return;\n }\n throw err;\n }\n },\n }),\n );\n return { stream: transformed, ...rest } as unknown as TResult;\n },\n };\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nexport const Outcome = {\n Benign: \"benign\",\n InformationDisclosure: \"information_disclosure\",\n SecretExposure: \"secret_exposure\",\n ControlAbuse: \"control_abuse\",\n SystemCompromise: \"system_compromise\",\n ServiceDisruption: \"service_disruption\",\n} as const;\n\ndeclare const unknownOutcomeBrand: unique symbol;\n\nexport type KnownPrimaryOutcome = (typeof Outcome)[keyof typeof Outcome];\nexport type KnownHarmfulOutcome = Exclude<KnownPrimaryOutcome, typeof Outcome.Benign>;\nexport type UnknownOutcome = string & { readonly [unknownOutcomeBrand]: \"UnknownOutcome\" };\nexport type PrimaryOutcome = KnownPrimaryOutcome | UnknownOutcome;\nexport type HarmfulOutcome = KnownHarmfulOutcome | UnknownOutcome;\n\nexport const PRIMARY_OUTCOMES = [\n Outcome.Benign,\n Outcome.InformationDisclosure,\n Outcome.SecretExposure,\n Outcome.ControlAbuse,\n Outcome.SystemCompromise,\n Outcome.ServiceDisruption,\n] as const satisfies readonly PrimaryOutcome[];\n\nexport const HARMFUL_OUTCOMES = [\n Outcome.InformationDisclosure,\n Outcome.SecretExposure,\n Outcome.ControlAbuse,\n Outcome.SystemCompromise,\n Outcome.ServiceDisruption,\n] as const satisfies readonly KnownHarmfulOutcome[];\n\nexport const OUTCOME_DESCRIPTIONS = {\n [Outcome.Benign]: \"No harmful firewall outcome detected.\",\n [Outcome.InformationDisclosure]:\n \"Exposes private data, documents, internal context, logs, traces, customer data, SQL rows, topology, or similar non-secret sensitive information.\",\n [Outcome.SecretExposure]:\n \"Exposes credentials, tokens, API keys, cookies, passwords, signing keys, OAuth secrets, session material, or webhook secrets.\",\n [Outcome.ControlAbuse]:\n \"Misuses authorized tools or user privileges to send, change, approve, delete, operate, or bypass policy/RBAC without a stronger outcome.\",\n [Outcome.SystemCompromise]:\n \"Enables privilege escalation, account takeover, hostile integration or plugin takeover, persistence, lateral movement, attacker webhook registration, or code/plugin execution.\",\n [Outcome.ServiceDisruption]:\n \"Causes downtime, lockout, degradation, alert suppression, destructive loops, resource exhaustion, cost spikes, or hidden outage evidence.\",\n} as const satisfies Readonly<Record<KnownPrimaryOutcome, string>>;\n\nconst PRIMARY_OUTCOME_SET = new Set<string>(PRIMARY_OUTCOMES);\nconst HARMFUL_OUTCOME_SET = new Set<string>(HARMFUL_OUTCOMES);\n\nexport function isPrimaryOutcome(value: unknown): value is KnownPrimaryOutcome {\n return typeof value === \"string\" && PRIMARY_OUTCOME_SET.has(value);\n}\n\nexport function isHarmfulOutcome(value: unknown): value is KnownHarmfulOutcome {\n return typeof value === \"string\" && HARMFUL_OUTCOME_SET.has(value);\n}\n\nexport function normalizePrimaryOutcome(\n value: unknown,\n fieldName = \"primary_outcome\",\n): PrimaryOutcome {\n if (typeof value !== \"string\") {\n throw new Error(`Firewall: invalid ${fieldName} ${JSON.stringify(value)}`);\n }\n return isPrimaryOutcome(value) ? value : (value as UnknownOutcome);\n}\n\nexport function normalizeHarmfulOutcome(\n value: unknown,\n fieldName = \"outcome\",\n): HarmfulOutcome {\n if (typeof value !== \"string\" || value === Outcome.Benign) {\n throw new Error(`Firewall: invalid ${fieldName} ${JSON.stringify(value)}`);\n }\n return isHarmfulOutcome(value) ? value : (value as UnknownOutcome);\n}\n\nexport function normalizeHarmfulOutcomeMap(\n values: unknown,\n fieldName: string,\n): Readonly<Partial<Record<HarmfulOutcome, number>>> | undefined {\n if (values === undefined || values === null) {\n return undefined;\n }\n if (typeof values !== \"object\" || Array.isArray(values)) {\n throw new Error(`Firewall: invalid ${fieldName} ${JSON.stringify(values)}`);\n }\n const out: Partial<Record<HarmfulOutcome, number>> = {};\n for (const [key, value] of Object.entries(values)) {\n const normalizedKey = normalizeHarmfulOutcome(key, `${fieldName} key`);\n if (typeof value !== \"number\") {\n throw new Error(`Firewall: invalid ${fieldName} value for ${JSON.stringify(key)}`);\n }\n out[normalizedKey] = value;\n }\n return Object.freeze(out);\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nfunction isHighSurrogate(code: number): boolean {\n return code >= 0xd800 && code <= 0xdbff;\n}\n\nfunction isLowSurrogate(code: number): boolean {\n return code >= 0xdc00 && code <= 0xdfff;\n}\n\nexport function sanitizeText(text: string): string {\n let out = \"\";\n for (let i = 0; i < text.length; i++) {\n const code = text.charCodeAt(i);\n if (isHighSurrogate(code)) {\n if (i + 1 < text.length && isLowSurrogate(text.charCodeAt(i + 1))) {\n out += text[i]!;\n out += text[i + 1]!;\n i++;\n }\n continue;\n }\n if (!isLowSurrogate(code)) {\n out += text[i]!;\n }\n }\n return out;\n}\n"],"mappings":"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","names":["findLastUserMessage","text","isRecord","body"]}
1
+ {"version":3,"sources":["../src/exceptions.ts","../src/hooks.ts","../src/utils/extract.ts","../src/adapters/langchain.ts","../src/index.ts","../src/firewall.ts","../src/adapters/vercel.ts","../src/outcomes.ts","../src/sanitization.ts"],"sourcesContent":["// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nimport type { HookLabel } from \"./hooks.js\";\nimport type { BlockResult } from \"./types.js\";\n\nconst MAX_PROMPT_DISPLAY_LEN = 100;\n\nexport interface MalformedInputDetails {\n field?: string;\n inputIndex?: number;\n charOffset?: number;\n malformedToken?: string;\n codePoint?: string;\n reason?: string;\n}\n\nexport class FirewallBlockedException extends Error {\n readonly score: number;\n readonly threshold: number;\n readonly promptText: string;\n readonly runId: string | undefined;\n readonly hook: HookLabel | undefined;\n readonly toolName: string | undefined;\n readonly toolCallId: string | undefined;\n readonly result: BlockResult | undefined;\n\n constructor(params: {\n score: number;\n threshold: number;\n promptText: string;\n runId?: string;\n hook?: HookLabel;\n toolName?: string;\n toolCallId?: string;\n result?: BlockResult;\n }) {\n super(FirewallBlockedException.formatMessage(params));\n this.name = \"FirewallBlockedException\";\n this.score = params.score;\n this.threshold = params.threshold;\n this.promptText = params.promptText;\n this.runId = params.runId;\n this.hook = params.hook;\n this.toolName = params.toolName;\n this.toolCallId = params.toolCallId;\n this.result = params.result;\n Object.setPrototypeOf(this, FirewallBlockedException.prototype);\n }\n\n private static formatMessage(params: {\n score: number;\n threshold: number;\n promptText: string;\n }): string {\n const truncated =\n params.promptText.length > MAX_PROMPT_DISPLAY_LEN\n ? `${params.promptText.slice(0, MAX_PROMPT_DISPLAY_LEN)}...`\n : params.promptText;\n return (\n `Request blocked by Silmaril Firewall ` +\n `(score=${params.score.toFixed(4)}, threshold=${params.threshold.toFixed(4)}): ` +\n `'${truncated}'`\n );\n }\n}\n\n/** @deprecated Use FirewallBlockedException instead. */\nexport const PromptBlockedException = FirewallBlockedException;\n/** @deprecated Use FirewallBlockedException instead. */\nexport type PromptBlockedException = FirewallBlockedException;\n\nexport class SilmarilApiError extends Error {\n readonly status: number;\n readonly statusText: string;\n readonly body: string;\n readonly details: MalformedInputDetails | undefined;\n readonly error: string | undefined;\n readonly apiMessage: string | undefined;\n\n constructor(params: {\n status: number;\n statusText: string;\n body: string;\n details?: MalformedInputDetails;\n error?: string;\n apiMessage?: string;\n }) {\n const statusText = params.statusText ? ` ${params.statusText}` : \"\";\n super(`Silmaril API error ${params.status}${statusText}`);\n this.name = \"SilmarilApiError\";\n this.status = params.status;\n this.statusText = params.statusText;\n this.body = params.body;\n const parsed = parseErrorBody(params.body);\n this.details = params.details ?? parsed.details;\n this.error = params.error ?? parsed.error;\n this.apiMessage = params.apiMessage ?? parsed.apiMessage;\n Object.setPrototypeOf(this, SilmarilApiError.prototype);\n }\n}\n\nfunction parseErrorBody(body: string): {\n details: MalformedInputDetails | undefined;\n error: string | undefined;\n apiMessage: string | undefined;\n} {\n try {\n const parsed = JSON.parse(body) as unknown;\n if (!parsed || typeof parsed !== \"object\") {\n return { details: undefined, error: undefined, apiMessage: undefined };\n }\n const data = parsed as Record<string, unknown>;\n return {\n details:\n data.details && typeof data.details === \"object\"\n ? (data.details as MalformedInputDetails)\n : undefined,\n error: typeof data.error === \"string\" ? data.error : undefined,\n apiMessage: typeof data.message === \"string\" ? data.message : undefined,\n };\n } catch {\n return { details: undefined, error: undefined, apiMessage: undefined };\n }\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nexport const HookLabel = {\n USER_INPUT: \"user_input\",\n SYSTEM_PROMPT: \"system_prompt\",\n TOOL_CALL: \"tool_call\",\n TOOL_RESPONSE: \"tool_response\",\n LLM_OUTPUT: \"llm_output\",\n UNKNOWN: \"unknown\",\n} as const;\n\nexport type HookLabel = (typeof HookLabel)[keyof typeof HookLabel];\n\nexport const FirewallHook = {\n LLM_START: \"on_llm_start\",\n CHAT_MODEL_START: \"on_chat_model_start\",\n TOOL_START: \"on_tool_start\",\n RETRIEVER_START: \"on_retriever_start\",\n LLM_END: \"on_llm_end\",\n TOOL_END: \"on_tool_end\",\n RETRIEVER_END: \"on_retriever_end\",\n} as const;\n\nexport type FirewallHook = (typeof FirewallHook)[keyof typeof FirewallHook];\n\nexport const DEFAULT_HOOKS: ReadonlySet<FirewallHook> = new Set<FirewallHook>([\n FirewallHook.LLM_START,\n FirewallHook.CHAT_MODEL_START,\n]);\n\nexport const INPUT_HOOKS: ReadonlySet<FirewallHook> = new Set<FirewallHook>([\n FirewallHook.LLM_START,\n FirewallHook.CHAT_MODEL_START,\n FirewallHook.TOOL_START,\n FirewallHook.RETRIEVER_START,\n]);\n\nexport const OUTPUT_HOOKS: ReadonlySet<FirewallHook> = new Set<FirewallHook>([\n FirewallHook.LLM_END,\n FirewallHook.TOOL_END,\n FirewallHook.RETRIEVER_END,\n]);\n\nexport const ALL_HOOKS: ReadonlySet<FirewallHook> = new Set<FirewallHook>([\n ...INPUT_HOOKS,\n ...OUTPUT_HOOKS,\n]);\n\nexport const FIREWALL_HOOK_TO_LABEL: Readonly<Record<FirewallHook, HookLabel>> = {\n [FirewallHook.CHAT_MODEL_START]: HookLabel.USER_INPUT,\n [FirewallHook.LLM_START]: HookLabel.USER_INPUT,\n [FirewallHook.TOOL_START]: HookLabel.TOOL_CALL,\n [FirewallHook.TOOL_END]: HookLabel.TOOL_RESPONSE,\n [FirewallHook.RETRIEVER_START]: HookLabel.TOOL_CALL,\n [FirewallHook.RETRIEVER_END]: HookLabel.TOOL_RESPONSE,\n [FirewallHook.LLM_END]: HookLabel.LLM_OUTPUT,\n};\n\nconst FIREWALL_HOOK_VALUES: ReadonlySet<string> = new Set(Object.values(FirewallHook));\n\nexport function resolveHooks(\n hooks: Iterable<FirewallHook | string> | undefined,\n): ReadonlySet<FirewallHook> {\n if (hooks === undefined) {\n return DEFAULT_HOOKS;\n }\n const resolved = new Set<FirewallHook>();\n for (const h of hooks) {\n if (!FIREWALL_HOOK_VALUES.has(h)) {\n throw new Error(`Invalid FirewallHook value: ${String(h)}`);\n }\n resolved.add(h as FirewallHook);\n }\n return resolved;\n}\n\nexport function prependHook(text: string, hook: HookLabel | string | undefined | null): string {\n if (hook === undefined || hook === null) {\n return text;\n }\n if (hook === HookLabel.UNKNOWN) {\n return text;\n }\n return `[HOOK:${hook}] ${text}`;\n}\n\nexport function prependToolName(text: string, toolName: string | undefined | null): string {\n if (toolName === undefined || toolName === null) {\n return text;\n }\n return `[TOOL:${toolName}] ${text}`;\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nconst SKIP_ROLES: ReadonlySet<string> = new Set([\"ai\", \"assistant\"]);\nconst SYSTEM_ROLES: ReadonlySet<string> = new Set([\"system\"]);\nconst TOOL_ROLES: ReadonlySet<string> = new Set([\"tool\", \"function\"]);\n\ntype MessageContent = string | ReadonlyArray<string | { type?: string; text?: string }>;\n\ninterface DucktypedMessage {\n role?: string;\n type?: string;\n content?: MessageContent;\n}\n\ninterface DucktypedGeneration {\n text?: string;\n}\n\ninterface DucktypedLLMResult {\n generations?: ReadonlyArray<ReadonlyArray<DucktypedGeneration>>;\n}\n\ninterface DucktypedDocument {\n pageContent?: string;\n}\n\nfunction extractContentText(content: MessageContent | undefined): string {\n if (typeof content === \"string\") {\n return content;\n }\n if (Array.isArray(content)) {\n const parts: string[] = [];\n for (const block of content) {\n if (typeof block === \"string\") {\n parts.push(block);\n } else if (block && typeof block === \"object\" && block.type === \"text\") {\n parts.push(block.text ?? \"\");\n }\n }\n return parts.join(\" \");\n }\n return \"\";\n}\n\nfunction getRole(message: DucktypedMessage): string {\n if (message.role !== undefined) {\n return message.role.toLowerCase();\n }\n if (typeof message.type === \"string\") {\n return message.type.toLowerCase();\n }\n return \"\";\n}\n\nexport function extractTextFromMessages(\n messages: ReadonlyArray<DucktypedMessage>,\n options: { includeSystem?: boolean; includeTool?: boolean } = {},\n): string {\n const includeSystem = options.includeSystem ?? true;\n const includeTool = options.includeTool ?? true;\n const parts: string[] = [];\n for (const message of messages) {\n const role = getRole(message);\n if (SKIP_ROLES.has(role)) {\n continue;\n }\n if (!includeSystem && SYSTEM_ROLES.has(role)) {\n continue;\n }\n if (!includeTool && TOOL_ROLES.has(role)) {\n continue;\n }\n const text = extractContentText(message.content);\n const stripped = text.trim();\n if (stripped) {\n parts.push(stripped);\n }\n }\n return parts.join(\"\\n\");\n}\n\nexport function extractTextFromPrompts(prompts: readonly string[]): string {\n return prompts\n .map((p) => p.trim())\n .filter((p) => p.length > 0)\n .join(\"\\n\");\n}\n\nexport function extractTextFromToolInput(inputStr: string): string {\n return inputStr.trim();\n}\n\nexport function extractTextFromLLMResult(response: DucktypedLLMResult): string {\n const parts: string[] = [];\n for (const genList of response.generations ?? []) {\n for (const gen of genList) {\n const text = (gen.text ?? \"\").trim();\n if (text) {\n parts.push(text);\n }\n }\n }\n return parts.join(\"\\n\");\n}\n\nexport function extractTextFromDocuments(documents: ReadonlyArray<DucktypedDocument>): string {\n const parts: string[] = [];\n for (const doc of documents) {\n const text = (doc.pageContent ?? \"\").trim();\n if (text) {\n parts.push(text);\n }\n }\n return parts.join(\"\\n\");\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nimport type { BaseCallbackHandler } from \"@langchain/core/callbacks/base\";\n\nimport type { Firewall } from \"../firewall.js\";\nimport { FirewallBlockedException } from \"../exceptions.js\";\nimport {\n FIREWALL_HOOK_TO_LABEL,\n FirewallHook,\n HookLabel,\n resolveHooks,\n} from \"../hooks.js\";\nimport type { BlockResult, ClassifyEvent, LangChainAdapterOptions } from \"../types.js\";\nimport {\n extractTextFromDocuments,\n extractTextFromLLMResult,\n extractTextFromPrompts,\n extractTextFromToolInput,\n} from \"../utils/extract.js\";\n\nconst USER_ROLES: ReadonlySet<string> = new Set([\"human\", \"user\"]);\n\ninterface LangChainDucktypedMessage {\n role?: string;\n type?: string;\n content?: string | ReadonlyArray<string | { type?: string; text?: string }>;\n}\n\nfunction getMessageRole(message: LangChainDucktypedMessage): string {\n if (typeof message.role === \"string\") {\n return message.role.toLowerCase();\n }\n if (typeof message.type === \"string\") {\n return message.type.toLowerCase();\n }\n return \"\";\n}\n\nfunction extractMessageText(content: LangChainDucktypedMessage[\"content\"]): string {\n if (content === undefined) {\n return \"\";\n }\n if (typeof content === \"string\") {\n return content;\n }\n const parts: string[] = [];\n for (const block of content) {\n if (typeof block === \"string\") {\n parts.push(block);\n } else if (block && block.type === \"text\") {\n parts.push(block.text ?? \"\");\n }\n }\n return parts.join(\" \");\n}\n\nfunction findLastUserMessage(\n messages: ReadonlyArray<LangChainDucktypedMessage>,\n): LangChainDucktypedMessage | undefined {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]!;\n if (USER_ROLES.has(getMessageRole(msg))) {\n return msg;\n }\n }\n return undefined;\n}\n\nexport async function createLangChainHandler(\n firewall: Firewall,\n options: LangChainAdapterOptions = {},\n): Promise<BaseCallbackHandler> {\n const { BaseCallbackHandler } = await import(\"@langchain/core/callbacks/base\");\n\n const enabledHooks = resolveHooks(options.hooks);\n // includeSystem / includeTool are retained in LangChainAdapterOptions for\n // backwards compat but are inert under the per-message hook-routing algorithm:\n // handleChatModelStart only scans the last user-role message; system and tool\n // messages are either trusted or already classified by their own hooks.\n const failOpen = options.failOpen ?? true;\n const logger =\n options.logger ??\n ((message: string, error: unknown): void => {\n // eslint-disable-next-line no-console\n console.warn(`silmaril.firewall: ${message}`, error);\n });\n const shadowMode = options.shadowMode ?? firewall.shadowMode;\n const onClassify = options.onClassify;\n\n const fireOnClassify = (event: ClassifyEvent): void => {\n if (!onClassify) {\n return;\n }\n try {\n onClassify(event);\n } catch (err) {\n logger(\"onClassify callback threw\", err);\n }\n };\n\n const classify = async (\n text: string,\n hookLabel: HookLabel,\n runId: string,\n toolName?: string,\n ): Promise<void> => {\n let result: BlockResult;\n try {\n result = await firewall.classify(text, {\n hook: hookLabel,\n ...(toolName !== undefined ? { toolName } : {}),\n });\n } catch (err) {\n if (!failOpen) {\n throw err;\n }\n logger(\"classification failed, allowing prompt through\", err);\n return;\n }\n const threshold = result.threshold;\n const blocked = result.prediction === \"MALICIOUS\";\n const commonEventFields = {\n hook: hookLabel,\n ...(toolName !== undefined ? { toolName } : {}),\n runId,\n text,\n result,\n };\n fireOnClassify({\n ...commonEventFields,\n blocked,\n shadowMode,\n });\n if (!blocked || shadowMode) {\n return;\n }\n\n throw new FirewallBlockedException({\n score: result.score,\n threshold,\n promptText: text,\n runId,\n hook: hookLabel,\n ...(toolName !== undefined ? { toolName } : {}),\n result,\n });\n };\n\n class SilmarilFirewallHandler extends BaseCallbackHandler {\n override name = \"silmaril_firewall_handler\";\n override raiseError = true;\n override awaitHandlers = true;\n\n override async handleChatModelStart(\n _llm: unknown,\n messages: unknown,\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.CHAT_MODEL_START)) {\n return;\n }\n const batches = messages as ReadonlyArray<ReadonlyArray<LangChainDucktypedMessage>>;\n const flat: LangChainDucktypedMessage[] = [];\n for (const batch of batches) {\n for (const m of batch) {\n flat.push(m);\n }\n }\n const lastUser = findLastUserMessage(flat);\n if (!lastUser) {\n return;\n }\n const text = extractMessageText(lastUser.content).trim();\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.CHAT_MODEL_START], runId);\n }\n\n override async handleLLMStart(\n _llm: unknown,\n prompts: string[],\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.LLM_START)) {\n return;\n }\n const text = extractTextFromPrompts(prompts);\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.LLM_START], runId);\n }\n\n override async handleToolStart(\n tool: { name?: string } | undefined,\n inputStr: string,\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.TOOL_START)) {\n return;\n }\n const text = extractTextFromToolInput(inputStr);\n if (!text) {\n return;\n }\n const toolName = tool?.name;\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.TOOL_START], runId, toolName);\n }\n\n override async handleRetrieverStart(\n _retriever: unknown,\n query: string,\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.RETRIEVER_START)) {\n return;\n }\n const text = query.trim();\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.RETRIEVER_START], runId);\n }\n\n override async handleLLMEnd(output: unknown, runId: string): Promise<void> {\n if (!enabledHooks.has(FirewallHook.LLM_END)) {\n return;\n }\n const text = extractTextFromLLMResult(output as { generations?: ReadonlyArray<ReadonlyArray<{ text?: string }>> });\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.LLM_END], runId);\n }\n\n override async handleToolEnd(\n output: unknown,\n runId: string,\n _parentRunId?: string,\n _tags?: string[],\n _kwargs?: { name?: string },\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.TOOL_END)) {\n return;\n }\n const text = String(output).trim();\n if (!text) {\n return;\n }\n const toolName = _kwargs?.name;\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.TOOL_END], runId, toolName);\n }\n\n override async handleRetrieverEnd(\n documents: ReadonlyArray<{ pageContent?: string }>,\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.RETRIEVER_END)) {\n return;\n }\n const text = extractTextFromDocuments(documents);\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.RETRIEVER_END], runId);\n }\n }\n\n return new SilmarilFirewallHandler();\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nexport {\n Firewall,\n DEFAULT_TIMEOUT_MS,\n} from \"./firewall.js\";\n\nexport { FirewallBlockedException, PromptBlockedException, SilmarilApiError } from \"./exceptions.js\";\nexport type { MalformedInputDetails } from \"./exceptions.js\";\n\nexport type { FirewallMiddleware } from \"./adapters/vercel.js\";\n\nexport {\n HookLabel,\n FirewallHook,\n DEFAULT_HOOKS,\n INPUT_HOOKS,\n OUTPUT_HOOKS,\n ALL_HOOKS,\n FIREWALL_HOOK_TO_LABEL,\n resolveHooks,\n prependHook,\n prependToolName,\n} from \"./hooks.js\";\n\nexport {\n Outcome,\n PRIMARY_OUTCOMES,\n HARMFUL_OUTCOMES,\n OUTCOME_DESCRIPTIONS,\n isPrimaryOutcome,\n isHarmfulOutcome,\n normalizePrimaryOutcome,\n normalizeHarmfulOutcome,\n normalizeHarmfulOutcomeMap,\n} from \"./outcomes.js\";\n\nexport type {\n KnownPrimaryOutcome,\n KnownHarmfulOutcome,\n PrimaryOutcome,\n HarmfulOutcome,\n UnknownOutcome,\n} from \"./outcomes.js\";\n\nexport type {\n BlockResult,\n ClassifyEvent,\n Prediction,\n ClassificationMetadata,\n FirewallOptions,\n ClassifyOptions,\n ClassifyBatchOptions,\n LangChainAdapterOptions,\n LangChainFirewallHandler,\n MiddlewareOptions,\n} from \"./types.js\";\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nimport { randomUUID } from \"node:crypto\";\n\nimport { createMiddleware, type FirewallMiddleware } from \"./adapters/vercel.js\";\nimport { SilmarilApiError } from \"./exceptions.js\";\nimport { normalizeHarmfulOutcomeMap, normalizePrimaryOutcome } from \"./outcomes.js\";\nimport { sanitizeText } from \"./sanitization.js\";\nimport type {\n BlockResult,\n ClassifyBatchOptions,\n ClassifyOptions,\n ClassificationMetadata,\n FirewallOptions,\n LangChainAdapterOptions,\n LangChainFirewallHandler,\n MiddlewareOptions,\n Prediction,\n} from \"./types.js\";\n\nexport const SDK_VERSION = \"0.5.1\";\nexport const DEFAULT_TIMEOUT_MS = 10_000;\nconst DEFAULT_MAX_RETRIES = 5;\nconst MAX_BACKOFF_SECONDS = 30;\nconst MAX_ERROR_BODY_BYTES = 1 << 16;\n\ninterface SingleClassifyPayload {\n text: string;\n hook?: string;\n tool_name?: string;\n metadata?: ClassificationMetadata;\n}\n\ninterface BatchClassifyPayload {\n texts: readonly string[];\n hooks?: readonly string[];\n tool_names?: readonly (string | null)[];\n metadata?: readonly (ClassificationMetadata | null)[];\n}\n\ninterface SingleClassifyResponse {\n prediction: Prediction;\n score: number;\n threshold: number;\n primary_outcome?: unknown;\n outcome_scores?: unknown;\n detector_scores?: unknown;\n detector_counts?: unknown;\n}\n\ninterface BatchClassifyResponse {\n predictions: readonly SingleClassifyResponse[];\n}\n\nfunction blockResultFromResponse(data: SingleClassifyResponse): BlockResult {\n if (data.prediction !== \"BENIGN\" && data.prediction !== \"MALICIOUS\") {\n throw new Error(\"Firewall: response prediction must be BENIGN or MALICIOUS\");\n }\n const result: {\n prediction: Prediction;\n score: number;\n threshold: number;\n primaryOutcome?: NonNullable<BlockResult[\"primaryOutcome\"]>;\n outcomeScores?: NonNullable<BlockResult[\"outcomeScores\"]>;\n detectorScores?: NonNullable<BlockResult[\"detectorScores\"]>;\n detectorCounts?: NonNullable<BlockResult[\"detectorCounts\"]>;\n } = {\n prediction: data.prediction,\n score: Number(data.score),\n threshold: Number(data.threshold),\n };\n if (data.primary_outcome !== undefined) {\n result.primaryOutcome = normalizePrimaryOutcome(data.primary_outcome);\n }\n if (data.outcome_scores !== undefined) {\n const outcomeScores = normalizeHarmfulOutcomeMap(data.outcome_scores, \"outcome_scores\");\n if (outcomeScores !== undefined) {\n result.outcomeScores = outcomeScores;\n }\n }\n if (data.detector_scores !== undefined) {\n const detectorScores = normalizeHarmfulOutcomeMap(data.detector_scores, \"detector_scores\");\n if (detectorScores !== undefined) {\n result.detectorScores = detectorScores;\n }\n }\n if (data.detector_counts !== undefined) {\n const detectorCounts = normalizeHarmfulOutcomeMap(data.detector_counts, \"detector_counts\");\n if (detectorCounts !== undefined) {\n result.detectorCounts = detectorCounts;\n }\n }\n return Object.freeze(result);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction withSdkMetadata(\n metadata: ClassificationMetadata | undefined,\n info: {\n requestId: string;\n inputIndex?: number;\n },\n): ClassificationMetadata {\n const payload: Record<string, unknown> = { ...(metadata ?? {}) };\n const existing = payload.silmaril;\n if (existing !== undefined && !isRecord(existing)) {\n throw new Error(\"Firewall: metadata.silmaril must be an object when provided\");\n }\n payload.silmaril = {\n ...(isRecord(existing) ? existing : {}),\n sdk_language: \"typescript\",\n sdk_version: SDK_VERSION,\n request_id: info.requestId,\n ...(info.inputIndex === undefined ? {} : { input_index: info.inputIndex }),\n };\n return payload;\n}\n\nasync function readCappedErrorBody(response: Response): Promise<string> {\n if (!response.body) {\n return response.text().then((body) => body.slice(0, MAX_ERROR_BODY_BYTES)).catch(() => \"\");\n }\n\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let remaining = MAX_ERROR_BODY_BYTES;\n try {\n while (remaining > 0) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n if (!value) {\n continue;\n }\n const chunk = value.byteLength > remaining ? value.slice(0, remaining) : value;\n chunks.push(chunk);\n remaining -= chunk.byteLength;\n if (chunk.byteLength < value.byteLength) {\n break;\n }\n }\n } catch {\n return \"\";\n } finally {\n await reader.cancel().catch(() => undefined);\n }\n\n const total = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);\n const body = new Uint8Array(total);\n let offset = 0;\n for (const chunk of chunks) {\n body.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return new TextDecoder().decode(body);\n}\n\nexport class Firewall {\n readonly apiKey: string;\n readonly apiUrl: string;\n readonly timeoutMs: number;\n readonly shadowMode: boolean;\n\n private readonly headers: Readonly<Record<string, string>>;\n\n constructor(options: FirewallOptions) {\n if (!options.apiKey) {\n throw new Error(\"Firewall: apiKey is required\");\n }\n if (!options.apiUrl) {\n throw new Error(\"Firewall: apiUrl is required\");\n }\n this.apiKey = options.apiKey;\n this.apiUrl = options.apiUrl;\n this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n if (typeof this.timeoutMs !== \"number\" || !Number.isFinite(this.timeoutMs) || this.timeoutMs < 0) {\n throw new Error(`Firewall: timeoutMs must be a finite non-negative number, got ${this.timeoutMs}`);\n }\n this.shadowMode = options.shadowMode ?? false;\n this.headers = Object.freeze({\n \"x-api-key\": this.apiKey,\n \"content-type\": \"application/json\",\n });\n }\n\n async classify(text: string, options: ClassifyOptions = {}): Promise<BlockResult> {\n const requestId = options.requestId ?? randomUUID();\n return this.classifySingle(sanitizeText(text), options, { requestId });\n }\n\n async classifyBatch(\n texts: readonly string[],\n options: ClassifyBatchOptions = {},\n ): Promise<BlockResult[]> {\n if (texts.length === 0) {\n throw new Error(\"Firewall: texts must not be empty\");\n }\n if (options.hooks !== undefined && options.hooks.length !== texts.length) {\n throw new Error(\n `Firewall: hooks length ${options.hooks.length} does not match texts length ${texts.length}`,\n );\n }\n if (options.toolNames !== undefined && options.toolNames.length !== texts.length) {\n throw new Error(\n `Firewall: toolNames length ${options.toolNames.length} does not match texts length ${texts.length}`,\n );\n }\n if (options.metadata !== undefined && options.metadata.length !== texts.length) {\n throw new Error(\n `Firewall: metadata length ${options.metadata.length} does not match texts length ${texts.length}`,\n );\n }\n\n const requestId = options.requestId ?? randomUUID();\n const payload: BatchClassifyPayload = {\n texts: texts.map((text) => sanitizeText(text)),\n };\n if (options.hooks && options.hooks.length > 0) {\n payload.hooks = options.hooks.map((h) => String(h));\n }\n if (options.toolNames && options.toolNames.length > 0) {\n payload.tool_names = options.toolNames.map((t) => (t === undefined ? null : t));\n }\n payload.metadata = texts.map((_, index) =>\n withSdkMetadata(options.metadata?.[index], {\n requestId,\n inputIndex: index,\n }),\n );\n const data = await this.postWithRetry<BatchClassifyResponse>(payload);\n return data.predictions.map((p) => blockResultFromResponse(p));\n }\n\n asLangChainHandler<THandler = LangChainFirewallHandler>(\n options: LangChainAdapterOptions = {},\n ): Promise<THandler> {\n return import(\"./adapters/langchain.js\").then((m) =>\n m.createLangChainHandler(this, options) as Promise<THandler>,\n );\n }\n\n asMiddleware(options: MiddlewareOptions = {}): FirewallMiddleware {\n return createMiddleware(this, options);\n }\n\n private async postWithRetry<T>(\n payload: SingleClassifyPayload | BatchClassifyPayload,\n maxRetries: number = DEFAULT_MAX_RETRIES,\n ): Promise<T> {\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const response = await fetch(this.apiUrl, {\n method: \"POST\",\n headers: this.headers,\n body: JSON.stringify(payload),\n redirect: \"error\",\n signal: AbortSignal.timeout(this.timeoutMs),\n });\n if (response.status !== 429 || attempt === maxRetries) {\n if (!response.ok) {\n const body = await readCappedErrorBody(response);\n throw new SilmarilApiError({\n status: response.status,\n statusText: response.statusText,\n body,\n });\n }\n return (await response.json()) as T;\n }\n const waitSeconds = Math.min(2 ** attempt, MAX_BACKOFF_SECONDS);\n await new Promise<void>((resolve) => setTimeout(resolve, waitSeconds * 1000));\n }\n throw new Error(\"Firewall: exhausted retries (unreachable)\");\n }\n\n private async classifySingle(\n text: string,\n options: ClassifyOptions,\n metadataInfo: {\n requestId: string;\n },\n ): Promise<BlockResult> {\n const payload: SingleClassifyPayload = { text };\n if (options.hook !== undefined) {\n payload.hook = options.hook;\n }\n if (options.toolName !== undefined) {\n payload.tool_name = options.toolName;\n }\n payload.metadata = withSdkMetadata(options.metadata, metadataInfo);\n const data = await this.postWithRetry<SingleClassifyResponse>(payload);\n return blockResultFromResponse(data);\n }\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nimport type { Firewall } from \"../firewall.js\";\nimport { FirewallBlockedException } from \"../exceptions.js\";\nimport { HookLabel } from \"../hooks.js\";\nimport type { BlockResult, MiddlewareOptions } from \"../types.js\";\n\ninterface VercelContentPart {\n type?: string;\n text?: string;\n toolCallId?: string;\n toolName?: string;\n args?: unknown;\n output?: unknown;\n result?: unknown;\n}\n\ninterface VercelPromptMessage {\n role: string;\n content: string | ReadonlyArray<VercelContentPart | string>;\n}\n\ninterface VercelToolCall {\n toolCallType?: string;\n toolCallId?: string;\n toolName?: string;\n args?: unknown;\n input?: unknown;\n}\n\ninterface VercelGenerateResult {\n text?: string;\n toolCalls?: ReadonlyArray<VercelToolCall>;\n}\n\ninterface WrapGenerateArgs<TResult extends VercelGenerateResult & Record<string, unknown>> {\n params: { prompt?: ReadonlyArray<VercelPromptMessage> } & Record<string, unknown>;\n doGenerate: () => PromiseLike<TResult>;\n}\n\ninterface WrapStreamArgs<\n TResult extends { stream: ReadableStream<unknown> } & Record<string, unknown>,\n> {\n params: { prompt?: ReadonlyArray<VercelPromptMessage> } & Record<string, unknown>;\n doStream: () => PromiseLike<TResult>;\n}\n\ninterface StreamPart {\n type?: string;\n textDelta?: string;\n delta?: string;\n}\n\ninterface VercelStepContext {\n toolName: string | undefined;\n toolCallId: string | undefined;\n}\n\nfunction stringifyToolValue(value: unknown): string {\n if (value === null || value === undefined) {\n return \"\";\n }\n if (typeof value === \"string\") {\n return value;\n }\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction extractContentText(content: VercelPromptMessage[\"content\"]): string {\n if (typeof content === \"string\") {\n return content;\n }\n const parts: string[] = [];\n for (const block of content) {\n if (typeof block === \"string\") {\n parts.push(block);\n } else if (block && block.type === \"text\") {\n parts.push(block.text ?? \"\");\n }\n }\n return parts.join(\" \");\n}\n\nfunction iterateToolResultParts(\n message: VercelPromptMessage,\n): Array<{ text: string; toolName: string | undefined; toolCallId: string | undefined }> {\n if (typeof message.content === \"string\") {\n return [];\n }\n const out: Array<{ text: string; toolName: string | undefined; toolCallId: string | undefined }> = [];\n for (const part of message.content) {\n if (typeof part === \"string\") {\n continue;\n }\n if (part.type === \"tool-result\") {\n const text = stringifyToolResult(part.result !== undefined ? part.result : part.output);\n if (text.trim()) {\n out.push({ text, toolName: part.toolName, toolCallId: part.toolCallId });\n }\n }\n }\n return out;\n}\n\nfunction stringifyToolResult(value: unknown): string {\n if (!isRecord(value)) {\n return stringifyToolValue(value);\n }\n if ((value.type === \"text\" || value.type === \"error-text\") && typeof value.value === \"string\") {\n return value.value;\n }\n if ((value.type === \"json\" || value.type === \"error-json\") && value.value !== undefined) {\n return stringifyToolValue(value.value);\n }\n if (value.type === \"content\" && Array.isArray(value.value)) {\n return value.value\n .map((part) => (isRecord(part) && part.type === \"text\" && typeof part.text === \"string\" ? part.text : \"\"))\n .filter((text) => text.length > 0)\n .join(\" \");\n }\n return stringifyToolValue(value);\n}\n\nfunction findLastUserMessage(\n messages: ReadonlyArray<VercelPromptMessage>,\n): VercelPromptMessage | undefined {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]!;\n if (msg.role.toLowerCase() === \"user\") {\n return msg;\n }\n }\n return undefined;\n}\n\nexport interface FirewallMiddleware {\n readonly specificationVersion: \"v3\";\n readonly middlewareVersion: \"v2\";\n wrapGenerate: <TResult extends VercelGenerateResult & Record<string, unknown>>(\n args: WrapGenerateArgs<TResult>,\n ) => Promise<TResult>;\n wrapStream: <TResult extends { stream: ReadableStream<unknown> } & Record<string, unknown>>(\n args: WrapStreamArgs<TResult>,\n ) => Promise<TResult>;\n}\n\nexport function createMiddleware(\n firewall: Firewall,\n options: MiddlewareOptions = {},\n): FirewallMiddleware {\n const scanInput = options.scanInput ?? true;\n const scanOutput = options.scanOutput ?? false;\n const shadowMode = options.shadowMode ?? firewall.shadowMode;\n\n const classifyOrBlock = async (\n text: string,\n hook: HookLabel,\n context: VercelStepContext = { toolName: undefined, toolCallId: undefined },\n ): Promise<void> => {\n if (!text.trim()) {\n return;\n }\n const { toolName, toolCallId } = context;\n const result: BlockResult = await firewall.classify(\n text,\n toolName !== undefined ? { hook, toolName } : { hook },\n );\n const threshold = result.threshold;\n const blocked = result.prediction === \"MALICIOUS\";\n const commonEventFields = {\n hook,\n ...(toolName !== undefined ? { toolName } : {}),\n ...(toolCallId !== undefined ? { toolCallId } : {}),\n text,\n result,\n };\n options.onClassify?.({\n ...commonEventFields,\n blocked,\n shadowMode,\n });\n if (!blocked || shadowMode) {\n return;\n }\n\n const err = new FirewallBlockedException({\n score: result.score,\n threshold,\n promptText: text,\n hook,\n ...(toolName !== undefined ? { toolName } : {}),\n ...(toolCallId !== undefined ? { toolCallId } : {}),\n result,\n });\n options.onBlocked?.(err);\n throw err;\n };\n\n const scanPrompt = async (prompt: ReadonlyArray<VercelPromptMessage>): Promise<void> => {\n if (prompt.length === 0) {\n return;\n }\n const last = prompt[prompt.length - 1]!;\n const role = last.role.toLowerCase();\n\n // If the newest message is a tool result (typical mid-flow in a\n // tool-calling loop), classify each tool-result part individually with\n // tool_response + toolName. No manual wiring from the caller — the\n // toolName is read directly from the Vercel content part.\n if (role === \"tool\") {\n for (const { text, toolName, toolCallId } of iterateToolResultParts(last)) {\n await classifyOrBlock(text, HookLabel.TOOL_RESPONSE, { toolName, toolCallId });\n }\n return;\n }\n\n // Otherwise, fall back to scanning the most recent user message.\n // Covers: [user], [system, user], [user, assistant(text), user], etc.\n const lastUser = findLastUserMessage(prompt);\n if (!lastUser) {\n return;\n }\n const text = extractContentText(lastUser.content).trim();\n if (!text) {\n return;\n }\n await classifyOrBlock(text, HookLabel.USER_INPUT);\n };\n\n const scanGenerateResult = async (result: VercelGenerateResult): Promise<void> => {\n if (scanOutput && typeof result.text === \"string\" && result.text.length > 0) {\n await classifyOrBlock(result.text, HookLabel.LLM_OUTPUT);\n }\n if (options.scanToolCalls && Array.isArray(result.toolCalls)) {\n for (const call of result.toolCalls) {\n if (!call || typeof call !== \"object\") {\n continue;\n }\n const toolInput = call.args !== undefined ? call.args : call.input;\n const args =\n typeof toolInput === \"string\" ? toolInput : stringifyToolValue(toolInput);\n const toolName = typeof call.toolName === \"string\" ? call.toolName : undefined;\n const toolCallId = typeof call.toolCallId === \"string\" ? call.toolCallId : undefined;\n if (args.trim()) {\n await classifyOrBlock(args, HookLabel.TOOL_CALL, { toolName, toolCallId });\n }\n }\n }\n };\n\n return {\n specificationVersion: \"v3\",\n middlewareVersion: \"v2\",\n\n async wrapGenerate<TResult extends VercelGenerateResult & Record<string, unknown>>({\n params,\n doGenerate,\n }: WrapGenerateArgs<TResult>): Promise<TResult> {\n if (scanInput) {\n await scanPrompt(params.prompt ?? []);\n }\n const result = await doGenerate();\n await scanGenerateResult(result);\n return result;\n },\n\n async wrapStream<TResult extends { stream: ReadableStream<unknown> } & Record<string, unknown>>({\n params,\n doStream,\n }: WrapStreamArgs<TResult>): Promise<TResult> {\n if (scanInput) {\n await scanPrompt(params.prompt ?? []);\n }\n const { stream, ...rest } = await doStream();\n if (!scanOutput) {\n return { stream, ...rest } as unknown as TResult;\n }\n\n let buffered = \"\";\n const transformed = stream.pipeThrough(\n new TransformStream<unknown, unknown>({\n transform(chunk, controller): void {\n const part = chunk as StreamPart;\n if (part && part.type === \"text-delta\") {\n const delta = part.textDelta ?? part.delta ?? \"\";\n buffered += delta;\n }\n controller.enqueue(chunk);\n },\n async flush(controller): Promise<void> {\n if (!buffered.trim()) {\n return;\n }\n try {\n await classifyOrBlock(buffered, HookLabel.LLM_OUTPUT);\n } catch (err) {\n if (err instanceof FirewallBlockedException) {\n controller.enqueue({ type: \"error\", error: err });\n return;\n }\n throw err;\n }\n },\n }),\n );\n return { stream: transformed, ...rest } as unknown as TResult;\n },\n };\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nexport const Outcome = {\n Benign: \"benign\",\n InformationDisclosure: \"information_disclosure\",\n SecretExposure: \"secret_exposure\",\n ControlAbuse: \"control_abuse\",\n SystemCompromise: \"system_compromise\",\n ServiceDisruption: \"service_disruption\",\n CodeGeneration: \"code_generation\",\n StoryScriptGeneration: \"story_script_generation\",\n GameGeneration: \"game_generation\",\n WebsiteGeneration: \"website_generation\",\n ClickUpTermsViolation: \"clickup_terms_violation\",\n TraditionalAiAbuse: \"traditional_ai_abuse\",\n} as const;\n\ndeclare const unknownOutcomeBrand: unique symbol;\n\nexport type KnownPrimaryOutcome = (typeof Outcome)[keyof typeof Outcome];\nexport type KnownHarmfulOutcome = Exclude<KnownPrimaryOutcome, typeof Outcome.Benign>;\nexport type UnknownOutcome = string & { readonly [unknownOutcomeBrand]: \"UnknownOutcome\" };\nexport type PrimaryOutcome = KnownPrimaryOutcome | UnknownOutcome;\nexport type HarmfulOutcome = KnownHarmfulOutcome | UnknownOutcome;\n\nexport const PRIMARY_OUTCOMES = [\n Outcome.Benign,\n Outcome.InformationDisclosure,\n Outcome.SecretExposure,\n Outcome.ControlAbuse,\n Outcome.SystemCompromise,\n Outcome.ServiceDisruption,\n Outcome.CodeGeneration,\n Outcome.StoryScriptGeneration,\n Outcome.GameGeneration,\n Outcome.WebsiteGeneration,\n Outcome.ClickUpTermsViolation,\n Outcome.TraditionalAiAbuse,\n] as const satisfies readonly PrimaryOutcome[];\n\nexport const HARMFUL_OUTCOMES = [\n Outcome.InformationDisclosure,\n Outcome.SecretExposure,\n Outcome.ControlAbuse,\n Outcome.SystemCompromise,\n Outcome.ServiceDisruption,\n Outcome.CodeGeneration,\n Outcome.StoryScriptGeneration,\n Outcome.GameGeneration,\n Outcome.WebsiteGeneration,\n Outcome.ClickUpTermsViolation,\n Outcome.TraditionalAiAbuse,\n] as const satisfies readonly KnownHarmfulOutcome[];\n\nexport const OUTCOME_DESCRIPTIONS = {\n [Outcome.Benign]: \"No harmful firewall outcome detected.\",\n [Outcome.InformationDisclosure]:\n \"Exposes private data, documents, internal context, logs, traces, customer data, SQL rows, topology, or similar non-secret sensitive information.\",\n [Outcome.SecretExposure]:\n \"Exposes credentials, tokens, API keys, cookies, passwords, signing keys, OAuth secrets, session material, or webhook secrets.\",\n [Outcome.ControlAbuse]:\n \"Misuses authorized tools or user privileges to send, change, approve, delete, operate, or bypass policy/RBAC without a stronger outcome.\",\n [Outcome.SystemCompromise]:\n \"Enables privilege escalation, account takeover, hostile integration or plugin takeover, persistence, lateral movement, attacker webhook registration, or code/plugin execution.\",\n [Outcome.ServiceDisruption]:\n \"Causes downtime, lockout, degradation, alert suppression, destructive loops, resource exhaustion, cost spikes, or hidden outage evidence.\",\n [Outcome.CodeGeneration]:\n \"Requests generation or material modification of executable code, scripts, workflows, or configuration.\",\n [Outcome.StoryScriptGeneration]:\n \"Requests generation of narrative prose, dialogue, scripts, or story artifacts.\",\n [Outcome.GameGeneration]:\n \"Requests generation of a game, quest, level, mechanic, or playable experience.\",\n [Outcome.WebsiteGeneration]:\n \"Requests generation of a website, landing page, storefront, or web experience.\",\n [Outcome.ClickUpTermsViolation]:\n \"Requests content or actions that violate the configured ClickUp tenant policy.\",\n [Outcome.TraditionalAiAbuse]:\n \"Requests unsafe AI assistance outside the concrete security outcome classes.\",\n} as const satisfies Readonly<Record<KnownPrimaryOutcome, string>>;\n\nconst PRIMARY_OUTCOME_SET = new Set<string>(PRIMARY_OUTCOMES);\nconst HARMFUL_OUTCOME_SET = new Set<string>(HARMFUL_OUTCOMES);\n\nexport function isPrimaryOutcome(value: unknown): value is KnownPrimaryOutcome {\n return typeof value === \"string\" && PRIMARY_OUTCOME_SET.has(value);\n}\n\nexport function isHarmfulOutcome(value: unknown): value is KnownHarmfulOutcome {\n return typeof value === \"string\" && HARMFUL_OUTCOME_SET.has(value);\n}\n\nexport function normalizePrimaryOutcome(\n value: unknown,\n fieldName = \"primary_outcome\",\n): PrimaryOutcome {\n if (typeof value !== \"string\") {\n throw new Error(`Firewall: invalid ${fieldName} ${JSON.stringify(value)}`);\n }\n return isPrimaryOutcome(value) ? value : (value as UnknownOutcome);\n}\n\nexport function normalizeHarmfulOutcome(\n value: unknown,\n fieldName = \"outcome\",\n): HarmfulOutcome {\n if (typeof value !== \"string\" || value === Outcome.Benign) {\n throw new Error(`Firewall: invalid ${fieldName} ${JSON.stringify(value)}`);\n }\n return isHarmfulOutcome(value) ? value : (value as UnknownOutcome);\n}\n\nexport function normalizeHarmfulOutcomeMap(\n values: unknown,\n fieldName: string,\n): Readonly<Partial<Record<HarmfulOutcome, number>>> | undefined {\n if (values === undefined || values === null) {\n return undefined;\n }\n if (typeof values !== \"object\" || Array.isArray(values)) {\n throw new Error(`Firewall: invalid ${fieldName} ${JSON.stringify(values)}`);\n }\n const out: Partial<Record<HarmfulOutcome, number>> = {};\n for (const [key, value] of Object.entries(values)) {\n const normalizedKey = normalizeHarmfulOutcome(key, `${fieldName} key`);\n if (typeof value !== \"number\") {\n throw new Error(`Firewall: invalid ${fieldName} value for ${JSON.stringify(key)}`);\n }\n out[normalizedKey] = value;\n }\n return Object.freeze(out);\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nfunction isHighSurrogate(code: number): boolean {\n return code >= 0xd800 && code <= 0xdbff;\n}\n\nfunction isLowSurrogate(code: number): boolean {\n return code >= 0xdc00 && code <= 0xdfff;\n}\n\nexport function sanitizeText(text: string): string {\n let out = \"\";\n for (let i = 0; i < text.length; i++) {\n const code = text.charCodeAt(i);\n if (isHighSurrogate(code)) {\n if (i + 1 < text.length && isLowSurrogate(text.charCodeAt(i + 1))) {\n out += text[i]!;\n out += text[i + 1]!;\n i++;\n }\n continue;\n }\n if (!isLowSurrogate(code)) {\n out += text[i]!;\n }\n }\n return out;\n}\n"],"mappings":"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","names":["findLastUserMessage","text","isRecord","body"]}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { H as HookLabel, B as BlockResult } from './firewall-DNC9vSbq.cjs';
2
- export { A as ALL_HOOKS, C as ClassificationMetadata, a as ClassifyBatchOptions, b as ClassifyEvent, c as ClassifyOptions, D as DEFAULT_HOOKS, d as DEFAULT_TIMEOUT_MS, F as FIREWALL_HOOK_TO_LABEL, e as Firewall, f as FirewallHook, g as FirewallMiddleware, h as FirewallOptions, i as HARMFUL_OUTCOMES, j as HarmfulOutcome, I as INPUT_HOOKS, K as KnownHarmfulOutcome, k as KnownPrimaryOutcome, L as LangChainAdapterOptions, l as LangChainFirewallHandler, M as MiddlewareOptions, O as OUTCOME_DESCRIPTIONS, m as OUTPUT_HOOKS, n as Outcome, P as PRIMARY_OUTCOMES, o as Prediction, p as PrimaryOutcome, U as UnknownOutcome, q as isHarmfulOutcome, r as isPrimaryOutcome, s as normalizeHarmfulOutcome, t as normalizeHarmfulOutcomeMap, u as normalizePrimaryOutcome, v as prependHook, w as prependToolName, x as resolveHooks } from './firewall-DNC9vSbq.cjs';
1
+ import { H as HookLabel, B as BlockResult } from './firewall-D2doJsD5.cjs';
2
+ export { A as ALL_HOOKS, C as ClassificationMetadata, a as ClassifyBatchOptions, b as ClassifyEvent, c as ClassifyOptions, D as DEFAULT_HOOKS, d as DEFAULT_TIMEOUT_MS, F as FIREWALL_HOOK_TO_LABEL, e as Firewall, f as FirewallHook, g as FirewallMiddleware, h as FirewallOptions, i as HARMFUL_OUTCOMES, j as HarmfulOutcome, I as INPUT_HOOKS, K as KnownHarmfulOutcome, k as KnownPrimaryOutcome, L as LangChainAdapterOptions, l as LangChainFirewallHandler, M as MiddlewareOptions, O as OUTCOME_DESCRIPTIONS, m as OUTPUT_HOOKS, n as Outcome, P as PRIMARY_OUTCOMES, o as Prediction, p as PrimaryOutcome, U as UnknownOutcome, q as isHarmfulOutcome, r as isPrimaryOutcome, s as normalizeHarmfulOutcome, t as normalizeHarmfulOutcomeMap, u as normalizePrimaryOutcome, v as prependHook, w as prependToolName, x as resolveHooks } from './firewall-D2doJsD5.cjs';
3
3
 
4
4
  interface MalformedInputDetails {
5
5
  field?: string;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { H as HookLabel, B as BlockResult } from './firewall-DNC9vSbq.js';
2
- export { A as ALL_HOOKS, C as ClassificationMetadata, a as ClassifyBatchOptions, b as ClassifyEvent, c as ClassifyOptions, D as DEFAULT_HOOKS, d as DEFAULT_TIMEOUT_MS, F as FIREWALL_HOOK_TO_LABEL, e as Firewall, f as FirewallHook, g as FirewallMiddleware, h as FirewallOptions, i as HARMFUL_OUTCOMES, j as HarmfulOutcome, I as INPUT_HOOKS, K as KnownHarmfulOutcome, k as KnownPrimaryOutcome, L as LangChainAdapterOptions, l as LangChainFirewallHandler, M as MiddlewareOptions, O as OUTCOME_DESCRIPTIONS, m as OUTPUT_HOOKS, n as Outcome, P as PRIMARY_OUTCOMES, o as Prediction, p as PrimaryOutcome, U as UnknownOutcome, q as isHarmfulOutcome, r as isPrimaryOutcome, s as normalizeHarmfulOutcome, t as normalizeHarmfulOutcomeMap, u as normalizePrimaryOutcome, v as prependHook, w as prependToolName, x as resolveHooks } from './firewall-DNC9vSbq.js';
1
+ import { H as HookLabel, B as BlockResult } from './firewall-D2doJsD5.js';
2
+ export { A as ALL_HOOKS, C as ClassificationMetadata, a as ClassifyBatchOptions, b as ClassifyEvent, c as ClassifyOptions, D as DEFAULT_HOOKS, d as DEFAULT_TIMEOUT_MS, F as FIREWALL_HOOK_TO_LABEL, e as Firewall, f as FirewallHook, g as FirewallMiddleware, h as FirewallOptions, i as HARMFUL_OUTCOMES, j as HarmfulOutcome, I as INPUT_HOOKS, K as KnownHarmfulOutcome, k as KnownPrimaryOutcome, L as LangChainAdapterOptions, l as LangChainFirewallHandler, M as MiddlewareOptions, O as OUTCOME_DESCRIPTIONS, m as OUTPUT_HOOKS, n as Outcome, P as PRIMARY_OUTCOMES, o as Prediction, p as PrimaryOutcome, U as UnknownOutcome, q as isHarmfulOutcome, r as isPrimaryOutcome, s as normalizeHarmfulOutcome, t as normalizeHarmfulOutcomeMap, u as normalizePrimaryOutcome, v as prependHook, w as prependToolName, x as resolveHooks } from './firewall-D2doJsD5.js';
3
3
 
4
4
  interface MalformedInputDetails {
5
5
  field?: string;
package/dist/index.js CHANGED
@@ -633,7 +633,13 @@ var Outcome = {
633
633
  SecretExposure: "secret_exposure",
634
634
  ControlAbuse: "control_abuse",
635
635
  SystemCompromise: "system_compromise",
636
- ServiceDisruption: "service_disruption"
636
+ ServiceDisruption: "service_disruption",
637
+ CodeGeneration: "code_generation",
638
+ StoryScriptGeneration: "story_script_generation",
639
+ GameGeneration: "game_generation",
640
+ WebsiteGeneration: "website_generation",
641
+ ClickUpTermsViolation: "clickup_terms_violation",
642
+ TraditionalAiAbuse: "traditional_ai_abuse"
637
643
  };
638
644
  var PRIMARY_OUTCOMES = [
639
645
  Outcome.Benign,
@@ -641,14 +647,26 @@ var PRIMARY_OUTCOMES = [
641
647
  Outcome.SecretExposure,
642
648
  Outcome.ControlAbuse,
643
649
  Outcome.SystemCompromise,
644
- Outcome.ServiceDisruption
650
+ Outcome.ServiceDisruption,
651
+ Outcome.CodeGeneration,
652
+ Outcome.StoryScriptGeneration,
653
+ Outcome.GameGeneration,
654
+ Outcome.WebsiteGeneration,
655
+ Outcome.ClickUpTermsViolation,
656
+ Outcome.TraditionalAiAbuse
645
657
  ];
646
658
  var HARMFUL_OUTCOMES = [
647
659
  Outcome.InformationDisclosure,
648
660
  Outcome.SecretExposure,
649
661
  Outcome.ControlAbuse,
650
662
  Outcome.SystemCompromise,
651
- Outcome.ServiceDisruption
663
+ Outcome.ServiceDisruption,
664
+ Outcome.CodeGeneration,
665
+ Outcome.StoryScriptGeneration,
666
+ Outcome.GameGeneration,
667
+ Outcome.WebsiteGeneration,
668
+ Outcome.ClickUpTermsViolation,
669
+ Outcome.TraditionalAiAbuse
652
670
  ];
653
671
  var OUTCOME_DESCRIPTIONS = {
654
672
  [Outcome.Benign]: "No harmful firewall outcome detected.",
@@ -656,7 +674,13 @@ var OUTCOME_DESCRIPTIONS = {
656
674
  [Outcome.SecretExposure]: "Exposes credentials, tokens, API keys, cookies, passwords, signing keys, OAuth secrets, session material, or webhook secrets.",
657
675
  [Outcome.ControlAbuse]: "Misuses authorized tools or user privileges to send, change, approve, delete, operate, or bypass policy/RBAC without a stronger outcome.",
658
676
  [Outcome.SystemCompromise]: "Enables privilege escalation, account takeover, hostile integration or plugin takeover, persistence, lateral movement, attacker webhook registration, or code/plugin execution.",
659
- [Outcome.ServiceDisruption]: "Causes downtime, lockout, degradation, alert suppression, destructive loops, resource exhaustion, cost spikes, or hidden outage evidence."
677
+ [Outcome.ServiceDisruption]: "Causes downtime, lockout, degradation, alert suppression, destructive loops, resource exhaustion, cost spikes, or hidden outage evidence.",
678
+ [Outcome.CodeGeneration]: "Requests generation or material modification of executable code, scripts, workflows, or configuration.",
679
+ [Outcome.StoryScriptGeneration]: "Requests generation of narrative prose, dialogue, scripts, or story artifacts.",
680
+ [Outcome.GameGeneration]: "Requests generation of a game, quest, level, mechanic, or playable experience.",
681
+ [Outcome.WebsiteGeneration]: "Requests generation of a website, landing page, storefront, or web experience.",
682
+ [Outcome.ClickUpTermsViolation]: "Requests content or actions that violate the configured ClickUp tenant policy.",
683
+ [Outcome.TraditionalAiAbuse]: "Requests unsafe AI assistance outside the concrete security outcome classes."
660
684
  };
661
685
  var PRIMARY_OUTCOME_SET = new Set(PRIMARY_OUTCOMES);
662
686
  var HARMFUL_OUTCOME_SET = new Set(HARMFUL_OUTCOMES);
@@ -723,7 +747,7 @@ function sanitizeText(text) {
723
747
  }
724
748
 
725
749
  // src/firewall.ts
726
- var SDK_VERSION = "0.5.0";
750
+ var SDK_VERSION = "0.5.1";
727
751
  var DEFAULT_TIMEOUT_MS = 1e4;
728
752
  var DEFAULT_MAX_RETRIES = 5;
729
753
  var MAX_BACKOFF_SECONDS = 30;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/exceptions.ts","../src/hooks.ts","../src/utils/extract.ts","../src/adapters/langchain.ts","../src/firewall.ts","../src/adapters/vercel.ts","../src/outcomes.ts","../src/sanitization.ts","../src/index.ts"],"sourcesContent":["// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nimport type { HookLabel } from \"./hooks.js\";\nimport type { BlockResult } from \"./types.js\";\n\nconst MAX_PROMPT_DISPLAY_LEN = 100;\n\nexport interface MalformedInputDetails {\n field?: string;\n inputIndex?: number;\n charOffset?: number;\n malformedToken?: string;\n codePoint?: string;\n reason?: string;\n}\n\nexport class FirewallBlockedException extends Error {\n readonly score: number;\n readonly threshold: number;\n readonly promptText: string;\n readonly runId: string | undefined;\n readonly hook: HookLabel | undefined;\n readonly toolName: string | undefined;\n readonly toolCallId: string | undefined;\n readonly result: BlockResult | undefined;\n\n constructor(params: {\n score: number;\n threshold: number;\n promptText: string;\n runId?: string;\n hook?: HookLabel;\n toolName?: string;\n toolCallId?: string;\n result?: BlockResult;\n }) {\n super(FirewallBlockedException.formatMessage(params));\n this.name = \"FirewallBlockedException\";\n this.score = params.score;\n this.threshold = params.threshold;\n this.promptText = params.promptText;\n this.runId = params.runId;\n this.hook = params.hook;\n this.toolName = params.toolName;\n this.toolCallId = params.toolCallId;\n this.result = params.result;\n Object.setPrototypeOf(this, FirewallBlockedException.prototype);\n }\n\n private static formatMessage(params: {\n score: number;\n threshold: number;\n promptText: string;\n }): string {\n const truncated =\n params.promptText.length > MAX_PROMPT_DISPLAY_LEN\n ? `${params.promptText.slice(0, MAX_PROMPT_DISPLAY_LEN)}...`\n : params.promptText;\n return (\n `Request blocked by Silmaril Firewall ` +\n `(score=${params.score.toFixed(4)}, threshold=${params.threshold.toFixed(4)}): ` +\n `'${truncated}'`\n );\n }\n}\n\n/** @deprecated Use FirewallBlockedException instead. */\nexport const PromptBlockedException = FirewallBlockedException;\n/** @deprecated Use FirewallBlockedException instead. */\nexport type PromptBlockedException = FirewallBlockedException;\n\nexport class SilmarilApiError extends Error {\n readonly status: number;\n readonly statusText: string;\n readonly body: string;\n readonly details: MalformedInputDetails | undefined;\n readonly error: string | undefined;\n readonly apiMessage: string | undefined;\n\n constructor(params: {\n status: number;\n statusText: string;\n body: string;\n details?: MalformedInputDetails;\n error?: string;\n apiMessage?: string;\n }) {\n const statusText = params.statusText ? ` ${params.statusText}` : \"\";\n super(`Silmaril API error ${params.status}${statusText}`);\n this.name = \"SilmarilApiError\";\n this.status = params.status;\n this.statusText = params.statusText;\n this.body = params.body;\n const parsed = parseErrorBody(params.body);\n this.details = params.details ?? parsed.details;\n this.error = params.error ?? parsed.error;\n this.apiMessage = params.apiMessage ?? parsed.apiMessage;\n Object.setPrototypeOf(this, SilmarilApiError.prototype);\n }\n}\n\nfunction parseErrorBody(body: string): {\n details: MalformedInputDetails | undefined;\n error: string | undefined;\n apiMessage: string | undefined;\n} {\n try {\n const parsed = JSON.parse(body) as unknown;\n if (!parsed || typeof parsed !== \"object\") {\n return { details: undefined, error: undefined, apiMessage: undefined };\n }\n const data = parsed as Record<string, unknown>;\n return {\n details:\n data.details && typeof data.details === \"object\"\n ? (data.details as MalformedInputDetails)\n : undefined,\n error: typeof data.error === \"string\" ? data.error : undefined,\n apiMessage: typeof data.message === \"string\" ? data.message : undefined,\n };\n } catch {\n return { details: undefined, error: undefined, apiMessage: undefined };\n }\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nexport const HookLabel = {\n USER_INPUT: \"user_input\",\n SYSTEM_PROMPT: \"system_prompt\",\n TOOL_CALL: \"tool_call\",\n TOOL_RESPONSE: \"tool_response\",\n LLM_OUTPUT: \"llm_output\",\n UNKNOWN: \"unknown\",\n} as const;\n\nexport type HookLabel = (typeof HookLabel)[keyof typeof HookLabel];\n\nexport const FirewallHook = {\n LLM_START: \"on_llm_start\",\n CHAT_MODEL_START: \"on_chat_model_start\",\n TOOL_START: \"on_tool_start\",\n RETRIEVER_START: \"on_retriever_start\",\n LLM_END: \"on_llm_end\",\n TOOL_END: \"on_tool_end\",\n RETRIEVER_END: \"on_retriever_end\",\n} as const;\n\nexport type FirewallHook = (typeof FirewallHook)[keyof typeof FirewallHook];\n\nexport const DEFAULT_HOOKS: ReadonlySet<FirewallHook> = new Set<FirewallHook>([\n FirewallHook.LLM_START,\n FirewallHook.CHAT_MODEL_START,\n]);\n\nexport const INPUT_HOOKS: ReadonlySet<FirewallHook> = new Set<FirewallHook>([\n FirewallHook.LLM_START,\n FirewallHook.CHAT_MODEL_START,\n FirewallHook.TOOL_START,\n FirewallHook.RETRIEVER_START,\n]);\n\nexport const OUTPUT_HOOKS: ReadonlySet<FirewallHook> = new Set<FirewallHook>([\n FirewallHook.LLM_END,\n FirewallHook.TOOL_END,\n FirewallHook.RETRIEVER_END,\n]);\n\nexport const ALL_HOOKS: ReadonlySet<FirewallHook> = new Set<FirewallHook>([\n ...INPUT_HOOKS,\n ...OUTPUT_HOOKS,\n]);\n\nexport const FIREWALL_HOOK_TO_LABEL: Readonly<Record<FirewallHook, HookLabel>> = {\n [FirewallHook.CHAT_MODEL_START]: HookLabel.USER_INPUT,\n [FirewallHook.LLM_START]: HookLabel.USER_INPUT,\n [FirewallHook.TOOL_START]: HookLabel.TOOL_CALL,\n [FirewallHook.TOOL_END]: HookLabel.TOOL_RESPONSE,\n [FirewallHook.RETRIEVER_START]: HookLabel.TOOL_CALL,\n [FirewallHook.RETRIEVER_END]: HookLabel.TOOL_RESPONSE,\n [FirewallHook.LLM_END]: HookLabel.LLM_OUTPUT,\n};\n\nconst FIREWALL_HOOK_VALUES: ReadonlySet<string> = new Set(Object.values(FirewallHook));\n\nexport function resolveHooks(\n hooks: Iterable<FirewallHook | string> | undefined,\n): ReadonlySet<FirewallHook> {\n if (hooks === undefined) {\n return DEFAULT_HOOKS;\n }\n const resolved = new Set<FirewallHook>();\n for (const h of hooks) {\n if (!FIREWALL_HOOK_VALUES.has(h)) {\n throw new Error(`Invalid FirewallHook value: ${String(h)}`);\n }\n resolved.add(h as FirewallHook);\n }\n return resolved;\n}\n\nexport function prependHook(text: string, hook: HookLabel | string | undefined | null): string {\n if (hook === undefined || hook === null) {\n return text;\n }\n if (hook === HookLabel.UNKNOWN) {\n return text;\n }\n return `[HOOK:${hook}] ${text}`;\n}\n\nexport function prependToolName(text: string, toolName: string | undefined | null): string {\n if (toolName === undefined || toolName === null) {\n return text;\n }\n return `[TOOL:${toolName}] ${text}`;\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nconst SKIP_ROLES: ReadonlySet<string> = new Set([\"ai\", \"assistant\"]);\nconst SYSTEM_ROLES: ReadonlySet<string> = new Set([\"system\"]);\nconst TOOL_ROLES: ReadonlySet<string> = new Set([\"tool\", \"function\"]);\n\ntype MessageContent = string | ReadonlyArray<string | { type?: string; text?: string }>;\n\ninterface DucktypedMessage {\n role?: string;\n type?: string;\n content?: MessageContent;\n}\n\ninterface DucktypedGeneration {\n text?: string;\n}\n\ninterface DucktypedLLMResult {\n generations?: ReadonlyArray<ReadonlyArray<DucktypedGeneration>>;\n}\n\ninterface DucktypedDocument {\n pageContent?: string;\n}\n\nfunction extractContentText(content: MessageContent | undefined): string {\n if (typeof content === \"string\") {\n return content;\n }\n if (Array.isArray(content)) {\n const parts: string[] = [];\n for (const block of content) {\n if (typeof block === \"string\") {\n parts.push(block);\n } else if (block && typeof block === \"object\" && block.type === \"text\") {\n parts.push(block.text ?? \"\");\n }\n }\n return parts.join(\" \");\n }\n return \"\";\n}\n\nfunction getRole(message: DucktypedMessage): string {\n if (message.role !== undefined) {\n return message.role.toLowerCase();\n }\n if (typeof message.type === \"string\") {\n return message.type.toLowerCase();\n }\n return \"\";\n}\n\nexport function extractTextFromMessages(\n messages: ReadonlyArray<DucktypedMessage>,\n options: { includeSystem?: boolean; includeTool?: boolean } = {},\n): string {\n const includeSystem = options.includeSystem ?? true;\n const includeTool = options.includeTool ?? true;\n const parts: string[] = [];\n for (const message of messages) {\n const role = getRole(message);\n if (SKIP_ROLES.has(role)) {\n continue;\n }\n if (!includeSystem && SYSTEM_ROLES.has(role)) {\n continue;\n }\n if (!includeTool && TOOL_ROLES.has(role)) {\n continue;\n }\n const text = extractContentText(message.content);\n const stripped = text.trim();\n if (stripped) {\n parts.push(stripped);\n }\n }\n return parts.join(\"\\n\");\n}\n\nexport function extractTextFromPrompts(prompts: readonly string[]): string {\n return prompts\n .map((p) => p.trim())\n .filter((p) => p.length > 0)\n .join(\"\\n\");\n}\n\nexport function extractTextFromToolInput(inputStr: string): string {\n return inputStr.trim();\n}\n\nexport function extractTextFromLLMResult(response: DucktypedLLMResult): string {\n const parts: string[] = [];\n for (const genList of response.generations ?? []) {\n for (const gen of genList) {\n const text = (gen.text ?? \"\").trim();\n if (text) {\n parts.push(text);\n }\n }\n }\n return parts.join(\"\\n\");\n}\n\nexport function extractTextFromDocuments(documents: ReadonlyArray<DucktypedDocument>): string {\n const parts: string[] = [];\n for (const doc of documents) {\n const text = (doc.pageContent ?? \"\").trim();\n if (text) {\n parts.push(text);\n }\n }\n return parts.join(\"\\n\");\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nimport type { BaseCallbackHandler } from \"@langchain/core/callbacks/base\";\n\nimport type { Firewall } from \"../firewall.js\";\nimport { FirewallBlockedException } from \"../exceptions.js\";\nimport {\n FIREWALL_HOOK_TO_LABEL,\n FirewallHook,\n HookLabel,\n resolveHooks,\n} from \"../hooks.js\";\nimport type { BlockResult, ClassifyEvent, LangChainAdapterOptions } from \"../types.js\";\nimport {\n extractTextFromDocuments,\n extractTextFromLLMResult,\n extractTextFromPrompts,\n extractTextFromToolInput,\n} from \"../utils/extract.js\";\n\nconst USER_ROLES: ReadonlySet<string> = new Set([\"human\", \"user\"]);\n\ninterface LangChainDucktypedMessage {\n role?: string;\n type?: string;\n content?: string | ReadonlyArray<string | { type?: string; text?: string }>;\n}\n\nfunction getMessageRole(message: LangChainDucktypedMessage): string {\n if (typeof message.role === \"string\") {\n return message.role.toLowerCase();\n }\n if (typeof message.type === \"string\") {\n return message.type.toLowerCase();\n }\n return \"\";\n}\n\nfunction extractMessageText(content: LangChainDucktypedMessage[\"content\"]): string {\n if (content === undefined) {\n return \"\";\n }\n if (typeof content === \"string\") {\n return content;\n }\n const parts: string[] = [];\n for (const block of content) {\n if (typeof block === \"string\") {\n parts.push(block);\n } else if (block && block.type === \"text\") {\n parts.push(block.text ?? \"\");\n }\n }\n return parts.join(\" \");\n}\n\nfunction findLastUserMessage(\n messages: ReadonlyArray<LangChainDucktypedMessage>,\n): LangChainDucktypedMessage | undefined {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]!;\n if (USER_ROLES.has(getMessageRole(msg))) {\n return msg;\n }\n }\n return undefined;\n}\n\nexport async function createLangChainHandler(\n firewall: Firewall,\n options: LangChainAdapterOptions = {},\n): Promise<BaseCallbackHandler> {\n const { BaseCallbackHandler } = await import(\"@langchain/core/callbacks/base\");\n\n const enabledHooks = resolveHooks(options.hooks);\n // includeSystem / includeTool are retained in LangChainAdapterOptions for\n // backwards compat but are inert under the per-message hook-routing algorithm:\n // handleChatModelStart only scans the last user-role message; system and tool\n // messages are either trusted or already classified by their own hooks.\n const failOpen = options.failOpen ?? true;\n const logger =\n options.logger ??\n ((message: string, error: unknown): void => {\n // eslint-disable-next-line no-console\n console.warn(`silmaril.firewall: ${message}`, error);\n });\n const shadowMode = options.shadowMode ?? firewall.shadowMode;\n const onClassify = options.onClassify;\n\n const fireOnClassify = (event: ClassifyEvent): void => {\n if (!onClassify) {\n return;\n }\n try {\n onClassify(event);\n } catch (err) {\n logger(\"onClassify callback threw\", err);\n }\n };\n\n const classify = async (\n text: string,\n hookLabel: HookLabel,\n runId: string,\n toolName?: string,\n ): Promise<void> => {\n let result: BlockResult;\n try {\n result = await firewall.classify(text, {\n hook: hookLabel,\n ...(toolName !== undefined ? { toolName } : {}),\n });\n } catch (err) {\n if (!failOpen) {\n throw err;\n }\n logger(\"classification failed, allowing prompt through\", err);\n return;\n }\n const threshold = result.threshold;\n const blocked = result.prediction === \"MALICIOUS\";\n const commonEventFields = {\n hook: hookLabel,\n ...(toolName !== undefined ? { toolName } : {}),\n runId,\n text,\n result,\n };\n fireOnClassify({\n ...commonEventFields,\n blocked,\n shadowMode,\n });\n if (!blocked || shadowMode) {\n return;\n }\n\n throw new FirewallBlockedException({\n score: result.score,\n threshold,\n promptText: text,\n runId,\n hook: hookLabel,\n ...(toolName !== undefined ? { toolName } : {}),\n result,\n });\n };\n\n class SilmarilFirewallHandler extends BaseCallbackHandler {\n override name = \"silmaril_firewall_handler\";\n override raiseError = true;\n override awaitHandlers = true;\n\n override async handleChatModelStart(\n _llm: unknown,\n messages: unknown,\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.CHAT_MODEL_START)) {\n return;\n }\n const batches = messages as ReadonlyArray<ReadonlyArray<LangChainDucktypedMessage>>;\n const flat: LangChainDucktypedMessage[] = [];\n for (const batch of batches) {\n for (const m of batch) {\n flat.push(m);\n }\n }\n const lastUser = findLastUserMessage(flat);\n if (!lastUser) {\n return;\n }\n const text = extractMessageText(lastUser.content).trim();\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.CHAT_MODEL_START], runId);\n }\n\n override async handleLLMStart(\n _llm: unknown,\n prompts: string[],\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.LLM_START)) {\n return;\n }\n const text = extractTextFromPrompts(prompts);\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.LLM_START], runId);\n }\n\n override async handleToolStart(\n tool: { name?: string } | undefined,\n inputStr: string,\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.TOOL_START)) {\n return;\n }\n const text = extractTextFromToolInput(inputStr);\n if (!text) {\n return;\n }\n const toolName = tool?.name;\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.TOOL_START], runId, toolName);\n }\n\n override async handleRetrieverStart(\n _retriever: unknown,\n query: string,\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.RETRIEVER_START)) {\n return;\n }\n const text = query.trim();\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.RETRIEVER_START], runId);\n }\n\n override async handleLLMEnd(output: unknown, runId: string): Promise<void> {\n if (!enabledHooks.has(FirewallHook.LLM_END)) {\n return;\n }\n const text = extractTextFromLLMResult(output as { generations?: ReadonlyArray<ReadonlyArray<{ text?: string }>> });\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.LLM_END], runId);\n }\n\n override async handleToolEnd(\n output: unknown,\n runId: string,\n _parentRunId?: string,\n _tags?: string[],\n _kwargs?: { name?: string },\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.TOOL_END)) {\n return;\n }\n const text = String(output).trim();\n if (!text) {\n return;\n }\n const toolName = _kwargs?.name;\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.TOOL_END], runId, toolName);\n }\n\n override async handleRetrieverEnd(\n documents: ReadonlyArray<{ pageContent?: string }>,\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.RETRIEVER_END)) {\n return;\n }\n const text = extractTextFromDocuments(documents);\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.RETRIEVER_END], runId);\n }\n }\n\n return new SilmarilFirewallHandler();\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nimport { randomUUID } from \"node:crypto\";\n\nimport { createMiddleware, type FirewallMiddleware } from \"./adapters/vercel.js\";\nimport { SilmarilApiError } from \"./exceptions.js\";\nimport { normalizeHarmfulOutcomeMap, normalizePrimaryOutcome } from \"./outcomes.js\";\nimport { sanitizeText } from \"./sanitization.js\";\nimport type {\n BlockResult,\n ClassifyBatchOptions,\n ClassifyOptions,\n ClassificationMetadata,\n FirewallOptions,\n LangChainAdapterOptions,\n LangChainFirewallHandler,\n MiddlewareOptions,\n Prediction,\n} from \"./types.js\";\n\nexport const SDK_VERSION = \"0.5.0\";\nexport const DEFAULT_TIMEOUT_MS = 10_000;\nconst DEFAULT_MAX_RETRIES = 5;\nconst MAX_BACKOFF_SECONDS = 30;\nconst MAX_ERROR_BODY_BYTES = 1 << 16;\n\ninterface SingleClassifyPayload {\n text: string;\n hook?: string;\n tool_name?: string;\n metadata?: ClassificationMetadata;\n}\n\ninterface BatchClassifyPayload {\n texts: readonly string[];\n hooks?: readonly string[];\n tool_names?: readonly (string | null)[];\n metadata?: readonly (ClassificationMetadata | null)[];\n}\n\ninterface SingleClassifyResponse {\n prediction: Prediction;\n score: number;\n threshold: number;\n primary_outcome?: unknown;\n outcome_scores?: unknown;\n detector_scores?: unknown;\n detector_counts?: unknown;\n}\n\ninterface BatchClassifyResponse {\n predictions: readonly SingleClassifyResponse[];\n}\n\nfunction blockResultFromResponse(data: SingleClassifyResponse): BlockResult {\n if (data.prediction !== \"BENIGN\" && data.prediction !== \"MALICIOUS\") {\n throw new Error(\"Firewall: response prediction must be BENIGN or MALICIOUS\");\n }\n const result: {\n prediction: Prediction;\n score: number;\n threshold: number;\n primaryOutcome?: NonNullable<BlockResult[\"primaryOutcome\"]>;\n outcomeScores?: NonNullable<BlockResult[\"outcomeScores\"]>;\n detectorScores?: NonNullable<BlockResult[\"detectorScores\"]>;\n detectorCounts?: NonNullable<BlockResult[\"detectorCounts\"]>;\n } = {\n prediction: data.prediction,\n score: Number(data.score),\n threshold: Number(data.threshold),\n };\n if (data.primary_outcome !== undefined) {\n result.primaryOutcome = normalizePrimaryOutcome(data.primary_outcome);\n }\n if (data.outcome_scores !== undefined) {\n const outcomeScores = normalizeHarmfulOutcomeMap(data.outcome_scores, \"outcome_scores\");\n if (outcomeScores !== undefined) {\n result.outcomeScores = outcomeScores;\n }\n }\n if (data.detector_scores !== undefined) {\n const detectorScores = normalizeHarmfulOutcomeMap(data.detector_scores, \"detector_scores\");\n if (detectorScores !== undefined) {\n result.detectorScores = detectorScores;\n }\n }\n if (data.detector_counts !== undefined) {\n const detectorCounts = normalizeHarmfulOutcomeMap(data.detector_counts, \"detector_counts\");\n if (detectorCounts !== undefined) {\n result.detectorCounts = detectorCounts;\n }\n }\n return Object.freeze(result);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction withSdkMetadata(\n metadata: ClassificationMetadata | undefined,\n info: {\n requestId: string;\n inputIndex?: number;\n },\n): ClassificationMetadata {\n const payload: Record<string, unknown> = { ...(metadata ?? {}) };\n const existing = payload.silmaril;\n if (existing !== undefined && !isRecord(existing)) {\n throw new Error(\"Firewall: metadata.silmaril must be an object when provided\");\n }\n payload.silmaril = {\n ...(isRecord(existing) ? existing : {}),\n sdk_language: \"typescript\",\n sdk_version: SDK_VERSION,\n request_id: info.requestId,\n ...(info.inputIndex === undefined ? {} : { input_index: info.inputIndex }),\n };\n return payload;\n}\n\nasync function readCappedErrorBody(response: Response): Promise<string> {\n if (!response.body) {\n return response.text().then((body) => body.slice(0, MAX_ERROR_BODY_BYTES)).catch(() => \"\");\n }\n\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let remaining = MAX_ERROR_BODY_BYTES;\n try {\n while (remaining > 0) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n if (!value) {\n continue;\n }\n const chunk = value.byteLength > remaining ? value.slice(0, remaining) : value;\n chunks.push(chunk);\n remaining -= chunk.byteLength;\n if (chunk.byteLength < value.byteLength) {\n break;\n }\n }\n } catch {\n return \"\";\n } finally {\n await reader.cancel().catch(() => undefined);\n }\n\n const total = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);\n const body = new Uint8Array(total);\n let offset = 0;\n for (const chunk of chunks) {\n body.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return new TextDecoder().decode(body);\n}\n\nexport class Firewall {\n readonly apiKey: string;\n readonly apiUrl: string;\n readonly timeoutMs: number;\n readonly shadowMode: boolean;\n\n private readonly headers: Readonly<Record<string, string>>;\n\n constructor(options: FirewallOptions) {\n if (!options.apiKey) {\n throw new Error(\"Firewall: apiKey is required\");\n }\n if (!options.apiUrl) {\n throw new Error(\"Firewall: apiUrl is required\");\n }\n this.apiKey = options.apiKey;\n this.apiUrl = options.apiUrl;\n this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n if (typeof this.timeoutMs !== \"number\" || !Number.isFinite(this.timeoutMs) || this.timeoutMs < 0) {\n throw new Error(`Firewall: timeoutMs must be a finite non-negative number, got ${this.timeoutMs}`);\n }\n this.shadowMode = options.shadowMode ?? false;\n this.headers = Object.freeze({\n \"x-api-key\": this.apiKey,\n \"content-type\": \"application/json\",\n });\n }\n\n async classify(text: string, options: ClassifyOptions = {}): Promise<BlockResult> {\n const requestId = options.requestId ?? randomUUID();\n return this.classifySingle(sanitizeText(text), options, { requestId });\n }\n\n async classifyBatch(\n texts: readonly string[],\n options: ClassifyBatchOptions = {},\n ): Promise<BlockResult[]> {\n if (texts.length === 0) {\n throw new Error(\"Firewall: texts must not be empty\");\n }\n if (options.hooks !== undefined && options.hooks.length !== texts.length) {\n throw new Error(\n `Firewall: hooks length ${options.hooks.length} does not match texts length ${texts.length}`,\n );\n }\n if (options.toolNames !== undefined && options.toolNames.length !== texts.length) {\n throw new Error(\n `Firewall: toolNames length ${options.toolNames.length} does not match texts length ${texts.length}`,\n );\n }\n if (options.metadata !== undefined && options.metadata.length !== texts.length) {\n throw new Error(\n `Firewall: metadata length ${options.metadata.length} does not match texts length ${texts.length}`,\n );\n }\n\n const requestId = options.requestId ?? randomUUID();\n const payload: BatchClassifyPayload = {\n texts: texts.map((text) => sanitizeText(text)),\n };\n if (options.hooks && options.hooks.length > 0) {\n payload.hooks = options.hooks.map((h) => String(h));\n }\n if (options.toolNames && options.toolNames.length > 0) {\n payload.tool_names = options.toolNames.map((t) => (t === undefined ? null : t));\n }\n payload.metadata = texts.map((_, index) =>\n withSdkMetadata(options.metadata?.[index], {\n requestId,\n inputIndex: index,\n }),\n );\n const data = await this.postWithRetry<BatchClassifyResponse>(payload);\n return data.predictions.map((p) => blockResultFromResponse(p));\n }\n\n asLangChainHandler<THandler = LangChainFirewallHandler>(\n options: LangChainAdapterOptions = {},\n ): Promise<THandler> {\n return import(\"./adapters/langchain.js\").then((m) =>\n m.createLangChainHandler(this, options) as Promise<THandler>,\n );\n }\n\n asMiddleware(options: MiddlewareOptions = {}): FirewallMiddleware {\n return createMiddleware(this, options);\n }\n\n private async postWithRetry<T>(\n payload: SingleClassifyPayload | BatchClassifyPayload,\n maxRetries: number = DEFAULT_MAX_RETRIES,\n ): Promise<T> {\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const response = await fetch(this.apiUrl, {\n method: \"POST\",\n headers: this.headers,\n body: JSON.stringify(payload),\n redirect: \"error\",\n signal: AbortSignal.timeout(this.timeoutMs),\n });\n if (response.status !== 429 || attempt === maxRetries) {\n if (!response.ok) {\n const body = await readCappedErrorBody(response);\n throw new SilmarilApiError({\n status: response.status,\n statusText: response.statusText,\n body,\n });\n }\n return (await response.json()) as T;\n }\n const waitSeconds = Math.min(2 ** attempt, MAX_BACKOFF_SECONDS);\n await new Promise<void>((resolve) => setTimeout(resolve, waitSeconds * 1000));\n }\n throw new Error(\"Firewall: exhausted retries (unreachable)\");\n }\n\n private async classifySingle(\n text: string,\n options: ClassifyOptions,\n metadataInfo: {\n requestId: string;\n },\n ): Promise<BlockResult> {\n const payload: SingleClassifyPayload = { text };\n if (options.hook !== undefined) {\n payload.hook = options.hook;\n }\n if (options.toolName !== undefined) {\n payload.tool_name = options.toolName;\n }\n payload.metadata = withSdkMetadata(options.metadata, metadataInfo);\n const data = await this.postWithRetry<SingleClassifyResponse>(payload);\n return blockResultFromResponse(data);\n }\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nimport type { Firewall } from \"../firewall.js\";\nimport { FirewallBlockedException } from \"../exceptions.js\";\nimport { HookLabel } from \"../hooks.js\";\nimport type { BlockResult, MiddlewareOptions } from \"../types.js\";\n\ninterface VercelContentPart {\n type?: string;\n text?: string;\n toolCallId?: string;\n toolName?: string;\n args?: unknown;\n output?: unknown;\n result?: unknown;\n}\n\ninterface VercelPromptMessage {\n role: string;\n content: string | ReadonlyArray<VercelContentPart | string>;\n}\n\ninterface VercelToolCall {\n toolCallType?: string;\n toolCallId?: string;\n toolName?: string;\n args?: unknown;\n input?: unknown;\n}\n\ninterface VercelGenerateResult {\n text?: string;\n toolCalls?: ReadonlyArray<VercelToolCall>;\n}\n\ninterface WrapGenerateArgs<TResult extends VercelGenerateResult & Record<string, unknown>> {\n params: { prompt?: ReadonlyArray<VercelPromptMessage> } & Record<string, unknown>;\n doGenerate: () => PromiseLike<TResult>;\n}\n\ninterface WrapStreamArgs<\n TResult extends { stream: ReadableStream<unknown> } & Record<string, unknown>,\n> {\n params: { prompt?: ReadonlyArray<VercelPromptMessage> } & Record<string, unknown>;\n doStream: () => PromiseLike<TResult>;\n}\n\ninterface StreamPart {\n type?: string;\n textDelta?: string;\n delta?: string;\n}\n\ninterface VercelStepContext {\n toolName: string | undefined;\n toolCallId: string | undefined;\n}\n\nfunction stringifyToolValue(value: unknown): string {\n if (value === null || value === undefined) {\n return \"\";\n }\n if (typeof value === \"string\") {\n return value;\n }\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction extractContentText(content: VercelPromptMessage[\"content\"]): string {\n if (typeof content === \"string\") {\n return content;\n }\n const parts: string[] = [];\n for (const block of content) {\n if (typeof block === \"string\") {\n parts.push(block);\n } else if (block && block.type === \"text\") {\n parts.push(block.text ?? \"\");\n }\n }\n return parts.join(\" \");\n}\n\nfunction iterateToolResultParts(\n message: VercelPromptMessage,\n): Array<{ text: string; toolName: string | undefined; toolCallId: string | undefined }> {\n if (typeof message.content === \"string\") {\n return [];\n }\n const out: Array<{ text: string; toolName: string | undefined; toolCallId: string | undefined }> = [];\n for (const part of message.content) {\n if (typeof part === \"string\") {\n continue;\n }\n if (part.type === \"tool-result\") {\n const text = stringifyToolResult(part.result !== undefined ? part.result : part.output);\n if (text.trim()) {\n out.push({ text, toolName: part.toolName, toolCallId: part.toolCallId });\n }\n }\n }\n return out;\n}\n\nfunction stringifyToolResult(value: unknown): string {\n if (!isRecord(value)) {\n return stringifyToolValue(value);\n }\n if ((value.type === \"text\" || value.type === \"error-text\") && typeof value.value === \"string\") {\n return value.value;\n }\n if ((value.type === \"json\" || value.type === \"error-json\") && value.value !== undefined) {\n return stringifyToolValue(value.value);\n }\n if (value.type === \"content\" && Array.isArray(value.value)) {\n return value.value\n .map((part) => (isRecord(part) && part.type === \"text\" && typeof part.text === \"string\" ? part.text : \"\"))\n .filter((text) => text.length > 0)\n .join(\" \");\n }\n return stringifyToolValue(value);\n}\n\nfunction findLastUserMessage(\n messages: ReadonlyArray<VercelPromptMessage>,\n): VercelPromptMessage | undefined {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]!;\n if (msg.role.toLowerCase() === \"user\") {\n return msg;\n }\n }\n return undefined;\n}\n\nexport interface FirewallMiddleware {\n readonly specificationVersion: \"v3\";\n readonly middlewareVersion: \"v2\";\n wrapGenerate: <TResult extends VercelGenerateResult & Record<string, unknown>>(\n args: WrapGenerateArgs<TResult>,\n ) => Promise<TResult>;\n wrapStream: <TResult extends { stream: ReadableStream<unknown> } & Record<string, unknown>>(\n args: WrapStreamArgs<TResult>,\n ) => Promise<TResult>;\n}\n\nexport function createMiddleware(\n firewall: Firewall,\n options: MiddlewareOptions = {},\n): FirewallMiddleware {\n const scanInput = options.scanInput ?? true;\n const scanOutput = options.scanOutput ?? false;\n const shadowMode = options.shadowMode ?? firewall.shadowMode;\n\n const classifyOrBlock = async (\n text: string,\n hook: HookLabel,\n context: VercelStepContext = { toolName: undefined, toolCallId: undefined },\n ): Promise<void> => {\n if (!text.trim()) {\n return;\n }\n const { toolName, toolCallId } = context;\n const result: BlockResult = await firewall.classify(\n text,\n toolName !== undefined ? { hook, toolName } : { hook },\n );\n const threshold = result.threshold;\n const blocked = result.prediction === \"MALICIOUS\";\n const commonEventFields = {\n hook,\n ...(toolName !== undefined ? { toolName } : {}),\n ...(toolCallId !== undefined ? { toolCallId } : {}),\n text,\n result,\n };\n options.onClassify?.({\n ...commonEventFields,\n blocked,\n shadowMode,\n });\n if (!blocked || shadowMode) {\n return;\n }\n\n const err = new FirewallBlockedException({\n score: result.score,\n threshold,\n promptText: text,\n hook,\n ...(toolName !== undefined ? { toolName } : {}),\n ...(toolCallId !== undefined ? { toolCallId } : {}),\n result,\n });\n options.onBlocked?.(err);\n throw err;\n };\n\n const scanPrompt = async (prompt: ReadonlyArray<VercelPromptMessage>): Promise<void> => {\n if (prompt.length === 0) {\n return;\n }\n const last = prompt[prompt.length - 1]!;\n const role = last.role.toLowerCase();\n\n // If the newest message is a tool result (typical mid-flow in a\n // tool-calling loop), classify each tool-result part individually with\n // tool_response + toolName. No manual wiring from the caller — the\n // toolName is read directly from the Vercel content part.\n if (role === \"tool\") {\n for (const { text, toolName, toolCallId } of iterateToolResultParts(last)) {\n await classifyOrBlock(text, HookLabel.TOOL_RESPONSE, { toolName, toolCallId });\n }\n return;\n }\n\n // Otherwise, fall back to scanning the most recent user message.\n // Covers: [user], [system, user], [user, assistant(text), user], etc.\n const lastUser = findLastUserMessage(prompt);\n if (!lastUser) {\n return;\n }\n const text = extractContentText(lastUser.content).trim();\n if (!text) {\n return;\n }\n await classifyOrBlock(text, HookLabel.USER_INPUT);\n };\n\n const scanGenerateResult = async (result: VercelGenerateResult): Promise<void> => {\n if (scanOutput && typeof result.text === \"string\" && result.text.length > 0) {\n await classifyOrBlock(result.text, HookLabel.LLM_OUTPUT);\n }\n if (options.scanToolCalls && Array.isArray(result.toolCalls)) {\n for (const call of result.toolCalls) {\n if (!call || typeof call !== \"object\") {\n continue;\n }\n const toolInput = call.args !== undefined ? call.args : call.input;\n const args =\n typeof toolInput === \"string\" ? toolInput : stringifyToolValue(toolInput);\n const toolName = typeof call.toolName === \"string\" ? call.toolName : undefined;\n const toolCallId = typeof call.toolCallId === \"string\" ? call.toolCallId : undefined;\n if (args.trim()) {\n await classifyOrBlock(args, HookLabel.TOOL_CALL, { toolName, toolCallId });\n }\n }\n }\n };\n\n return {\n specificationVersion: \"v3\",\n middlewareVersion: \"v2\",\n\n async wrapGenerate<TResult extends VercelGenerateResult & Record<string, unknown>>({\n params,\n doGenerate,\n }: WrapGenerateArgs<TResult>): Promise<TResult> {\n if (scanInput) {\n await scanPrompt(params.prompt ?? []);\n }\n const result = await doGenerate();\n await scanGenerateResult(result);\n return result;\n },\n\n async wrapStream<TResult extends { stream: ReadableStream<unknown> } & Record<string, unknown>>({\n params,\n doStream,\n }: WrapStreamArgs<TResult>): Promise<TResult> {\n if (scanInput) {\n await scanPrompt(params.prompt ?? []);\n }\n const { stream, ...rest } = await doStream();\n if (!scanOutput) {\n return { stream, ...rest } as unknown as TResult;\n }\n\n let buffered = \"\";\n const transformed = stream.pipeThrough(\n new TransformStream<unknown, unknown>({\n transform(chunk, controller): void {\n const part = chunk as StreamPart;\n if (part && part.type === \"text-delta\") {\n const delta = part.textDelta ?? part.delta ?? \"\";\n buffered += delta;\n }\n controller.enqueue(chunk);\n },\n async flush(controller): Promise<void> {\n if (!buffered.trim()) {\n return;\n }\n try {\n await classifyOrBlock(buffered, HookLabel.LLM_OUTPUT);\n } catch (err) {\n if (err instanceof FirewallBlockedException) {\n controller.enqueue({ type: \"error\", error: err });\n return;\n }\n throw err;\n }\n },\n }),\n );\n return { stream: transformed, ...rest } as unknown as TResult;\n },\n };\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nexport const Outcome = {\n Benign: \"benign\",\n InformationDisclosure: \"information_disclosure\",\n SecretExposure: \"secret_exposure\",\n ControlAbuse: \"control_abuse\",\n SystemCompromise: \"system_compromise\",\n ServiceDisruption: \"service_disruption\",\n} as const;\n\ndeclare const unknownOutcomeBrand: unique symbol;\n\nexport type KnownPrimaryOutcome = (typeof Outcome)[keyof typeof Outcome];\nexport type KnownHarmfulOutcome = Exclude<KnownPrimaryOutcome, typeof Outcome.Benign>;\nexport type UnknownOutcome = string & { readonly [unknownOutcomeBrand]: \"UnknownOutcome\" };\nexport type PrimaryOutcome = KnownPrimaryOutcome | UnknownOutcome;\nexport type HarmfulOutcome = KnownHarmfulOutcome | UnknownOutcome;\n\nexport const PRIMARY_OUTCOMES = [\n Outcome.Benign,\n Outcome.InformationDisclosure,\n Outcome.SecretExposure,\n Outcome.ControlAbuse,\n Outcome.SystemCompromise,\n Outcome.ServiceDisruption,\n] as const satisfies readonly PrimaryOutcome[];\n\nexport const HARMFUL_OUTCOMES = [\n Outcome.InformationDisclosure,\n Outcome.SecretExposure,\n Outcome.ControlAbuse,\n Outcome.SystemCompromise,\n Outcome.ServiceDisruption,\n] as const satisfies readonly KnownHarmfulOutcome[];\n\nexport const OUTCOME_DESCRIPTIONS = {\n [Outcome.Benign]: \"No harmful firewall outcome detected.\",\n [Outcome.InformationDisclosure]:\n \"Exposes private data, documents, internal context, logs, traces, customer data, SQL rows, topology, or similar non-secret sensitive information.\",\n [Outcome.SecretExposure]:\n \"Exposes credentials, tokens, API keys, cookies, passwords, signing keys, OAuth secrets, session material, or webhook secrets.\",\n [Outcome.ControlAbuse]:\n \"Misuses authorized tools or user privileges to send, change, approve, delete, operate, or bypass policy/RBAC without a stronger outcome.\",\n [Outcome.SystemCompromise]:\n \"Enables privilege escalation, account takeover, hostile integration or plugin takeover, persistence, lateral movement, attacker webhook registration, or code/plugin execution.\",\n [Outcome.ServiceDisruption]:\n \"Causes downtime, lockout, degradation, alert suppression, destructive loops, resource exhaustion, cost spikes, or hidden outage evidence.\",\n} as const satisfies Readonly<Record<KnownPrimaryOutcome, string>>;\n\nconst PRIMARY_OUTCOME_SET = new Set<string>(PRIMARY_OUTCOMES);\nconst HARMFUL_OUTCOME_SET = new Set<string>(HARMFUL_OUTCOMES);\n\nexport function isPrimaryOutcome(value: unknown): value is KnownPrimaryOutcome {\n return typeof value === \"string\" && PRIMARY_OUTCOME_SET.has(value);\n}\n\nexport function isHarmfulOutcome(value: unknown): value is KnownHarmfulOutcome {\n return typeof value === \"string\" && HARMFUL_OUTCOME_SET.has(value);\n}\n\nexport function normalizePrimaryOutcome(\n value: unknown,\n fieldName = \"primary_outcome\",\n): PrimaryOutcome {\n if (typeof value !== \"string\") {\n throw new Error(`Firewall: invalid ${fieldName} ${JSON.stringify(value)}`);\n }\n return isPrimaryOutcome(value) ? value : (value as UnknownOutcome);\n}\n\nexport function normalizeHarmfulOutcome(\n value: unknown,\n fieldName = \"outcome\",\n): HarmfulOutcome {\n if (typeof value !== \"string\" || value === Outcome.Benign) {\n throw new Error(`Firewall: invalid ${fieldName} ${JSON.stringify(value)}`);\n }\n return isHarmfulOutcome(value) ? value : (value as UnknownOutcome);\n}\n\nexport function normalizeHarmfulOutcomeMap(\n values: unknown,\n fieldName: string,\n): Readonly<Partial<Record<HarmfulOutcome, number>>> | undefined {\n if (values === undefined || values === null) {\n return undefined;\n }\n if (typeof values !== \"object\" || Array.isArray(values)) {\n throw new Error(`Firewall: invalid ${fieldName} ${JSON.stringify(values)}`);\n }\n const out: Partial<Record<HarmfulOutcome, number>> = {};\n for (const [key, value] of Object.entries(values)) {\n const normalizedKey = normalizeHarmfulOutcome(key, `${fieldName} key`);\n if (typeof value !== \"number\") {\n throw new Error(`Firewall: invalid ${fieldName} value for ${JSON.stringify(key)}`);\n }\n out[normalizedKey] = value;\n }\n return Object.freeze(out);\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nfunction isHighSurrogate(code: number): boolean {\n return code >= 0xd800 && code <= 0xdbff;\n}\n\nfunction isLowSurrogate(code: number): boolean {\n return code >= 0xdc00 && code <= 0xdfff;\n}\n\nexport function sanitizeText(text: string): string {\n let out = \"\";\n for (let i = 0; i < text.length; i++) {\n const code = text.charCodeAt(i);\n if (isHighSurrogate(code)) {\n if (i + 1 < text.length && isLowSurrogate(text.charCodeAt(i + 1))) {\n out += text[i]!;\n out += text[i + 1]!;\n i++;\n }\n continue;\n }\n if (!isLowSurrogate(code)) {\n out += text[i]!;\n }\n }\n return out;\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nexport {\n Firewall,\n DEFAULT_TIMEOUT_MS,\n} from \"./firewall.js\";\n\nexport { FirewallBlockedException, PromptBlockedException, SilmarilApiError } from \"./exceptions.js\";\nexport type { MalformedInputDetails } from \"./exceptions.js\";\n\nexport type { FirewallMiddleware } from \"./adapters/vercel.js\";\n\nexport {\n HookLabel,\n FirewallHook,\n DEFAULT_HOOKS,\n INPUT_HOOKS,\n OUTPUT_HOOKS,\n ALL_HOOKS,\n FIREWALL_HOOK_TO_LABEL,\n resolveHooks,\n prependHook,\n prependToolName,\n} from \"./hooks.js\";\n\nexport {\n Outcome,\n PRIMARY_OUTCOMES,\n HARMFUL_OUTCOMES,\n OUTCOME_DESCRIPTIONS,\n isPrimaryOutcome,\n isHarmfulOutcome,\n normalizePrimaryOutcome,\n normalizeHarmfulOutcome,\n normalizeHarmfulOutcomeMap,\n} from \"./outcomes.js\";\n\nexport type {\n KnownPrimaryOutcome,\n KnownHarmfulOutcome,\n PrimaryOutcome,\n HarmfulOutcome,\n UnknownOutcome,\n} from \"./outcomes.js\";\n\nexport type {\n BlockResult,\n ClassifyEvent,\n Prediction,\n ClassificationMetadata,\n FirewallOptions,\n ClassifyOptions,\n ClassifyBatchOptions,\n LangChainAdapterOptions,\n LangChainFirewallHandler,\n MiddlewareOptions,\n} from \"./types.js\";\n"],"mappings":"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","names":["findLastUserMessage","text","isRecord","body"]}
1
+ {"version":3,"sources":["../src/exceptions.ts","../src/hooks.ts","../src/utils/extract.ts","../src/adapters/langchain.ts","../src/firewall.ts","../src/adapters/vercel.ts","../src/outcomes.ts","../src/sanitization.ts","../src/index.ts"],"sourcesContent":["// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nimport type { HookLabel } from \"./hooks.js\";\nimport type { BlockResult } from \"./types.js\";\n\nconst MAX_PROMPT_DISPLAY_LEN = 100;\n\nexport interface MalformedInputDetails {\n field?: string;\n inputIndex?: number;\n charOffset?: number;\n malformedToken?: string;\n codePoint?: string;\n reason?: string;\n}\n\nexport class FirewallBlockedException extends Error {\n readonly score: number;\n readonly threshold: number;\n readonly promptText: string;\n readonly runId: string | undefined;\n readonly hook: HookLabel | undefined;\n readonly toolName: string | undefined;\n readonly toolCallId: string | undefined;\n readonly result: BlockResult | undefined;\n\n constructor(params: {\n score: number;\n threshold: number;\n promptText: string;\n runId?: string;\n hook?: HookLabel;\n toolName?: string;\n toolCallId?: string;\n result?: BlockResult;\n }) {\n super(FirewallBlockedException.formatMessage(params));\n this.name = \"FirewallBlockedException\";\n this.score = params.score;\n this.threshold = params.threshold;\n this.promptText = params.promptText;\n this.runId = params.runId;\n this.hook = params.hook;\n this.toolName = params.toolName;\n this.toolCallId = params.toolCallId;\n this.result = params.result;\n Object.setPrototypeOf(this, FirewallBlockedException.prototype);\n }\n\n private static formatMessage(params: {\n score: number;\n threshold: number;\n promptText: string;\n }): string {\n const truncated =\n params.promptText.length > MAX_PROMPT_DISPLAY_LEN\n ? `${params.promptText.slice(0, MAX_PROMPT_DISPLAY_LEN)}...`\n : params.promptText;\n return (\n `Request blocked by Silmaril Firewall ` +\n `(score=${params.score.toFixed(4)}, threshold=${params.threshold.toFixed(4)}): ` +\n `'${truncated}'`\n );\n }\n}\n\n/** @deprecated Use FirewallBlockedException instead. */\nexport const PromptBlockedException = FirewallBlockedException;\n/** @deprecated Use FirewallBlockedException instead. */\nexport type PromptBlockedException = FirewallBlockedException;\n\nexport class SilmarilApiError extends Error {\n readonly status: number;\n readonly statusText: string;\n readonly body: string;\n readonly details: MalformedInputDetails | undefined;\n readonly error: string | undefined;\n readonly apiMessage: string | undefined;\n\n constructor(params: {\n status: number;\n statusText: string;\n body: string;\n details?: MalformedInputDetails;\n error?: string;\n apiMessage?: string;\n }) {\n const statusText = params.statusText ? ` ${params.statusText}` : \"\";\n super(`Silmaril API error ${params.status}${statusText}`);\n this.name = \"SilmarilApiError\";\n this.status = params.status;\n this.statusText = params.statusText;\n this.body = params.body;\n const parsed = parseErrorBody(params.body);\n this.details = params.details ?? parsed.details;\n this.error = params.error ?? parsed.error;\n this.apiMessage = params.apiMessage ?? parsed.apiMessage;\n Object.setPrototypeOf(this, SilmarilApiError.prototype);\n }\n}\n\nfunction parseErrorBody(body: string): {\n details: MalformedInputDetails | undefined;\n error: string | undefined;\n apiMessage: string | undefined;\n} {\n try {\n const parsed = JSON.parse(body) as unknown;\n if (!parsed || typeof parsed !== \"object\") {\n return { details: undefined, error: undefined, apiMessage: undefined };\n }\n const data = parsed as Record<string, unknown>;\n return {\n details:\n data.details && typeof data.details === \"object\"\n ? (data.details as MalformedInputDetails)\n : undefined,\n error: typeof data.error === \"string\" ? data.error : undefined,\n apiMessage: typeof data.message === \"string\" ? data.message : undefined,\n };\n } catch {\n return { details: undefined, error: undefined, apiMessage: undefined };\n }\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nexport const HookLabel = {\n USER_INPUT: \"user_input\",\n SYSTEM_PROMPT: \"system_prompt\",\n TOOL_CALL: \"tool_call\",\n TOOL_RESPONSE: \"tool_response\",\n LLM_OUTPUT: \"llm_output\",\n UNKNOWN: \"unknown\",\n} as const;\n\nexport type HookLabel = (typeof HookLabel)[keyof typeof HookLabel];\n\nexport const FirewallHook = {\n LLM_START: \"on_llm_start\",\n CHAT_MODEL_START: \"on_chat_model_start\",\n TOOL_START: \"on_tool_start\",\n RETRIEVER_START: \"on_retriever_start\",\n LLM_END: \"on_llm_end\",\n TOOL_END: \"on_tool_end\",\n RETRIEVER_END: \"on_retriever_end\",\n} as const;\n\nexport type FirewallHook = (typeof FirewallHook)[keyof typeof FirewallHook];\n\nexport const DEFAULT_HOOKS: ReadonlySet<FirewallHook> = new Set<FirewallHook>([\n FirewallHook.LLM_START,\n FirewallHook.CHAT_MODEL_START,\n]);\n\nexport const INPUT_HOOKS: ReadonlySet<FirewallHook> = new Set<FirewallHook>([\n FirewallHook.LLM_START,\n FirewallHook.CHAT_MODEL_START,\n FirewallHook.TOOL_START,\n FirewallHook.RETRIEVER_START,\n]);\n\nexport const OUTPUT_HOOKS: ReadonlySet<FirewallHook> = new Set<FirewallHook>([\n FirewallHook.LLM_END,\n FirewallHook.TOOL_END,\n FirewallHook.RETRIEVER_END,\n]);\n\nexport const ALL_HOOKS: ReadonlySet<FirewallHook> = new Set<FirewallHook>([\n ...INPUT_HOOKS,\n ...OUTPUT_HOOKS,\n]);\n\nexport const FIREWALL_HOOK_TO_LABEL: Readonly<Record<FirewallHook, HookLabel>> = {\n [FirewallHook.CHAT_MODEL_START]: HookLabel.USER_INPUT,\n [FirewallHook.LLM_START]: HookLabel.USER_INPUT,\n [FirewallHook.TOOL_START]: HookLabel.TOOL_CALL,\n [FirewallHook.TOOL_END]: HookLabel.TOOL_RESPONSE,\n [FirewallHook.RETRIEVER_START]: HookLabel.TOOL_CALL,\n [FirewallHook.RETRIEVER_END]: HookLabel.TOOL_RESPONSE,\n [FirewallHook.LLM_END]: HookLabel.LLM_OUTPUT,\n};\n\nconst FIREWALL_HOOK_VALUES: ReadonlySet<string> = new Set(Object.values(FirewallHook));\n\nexport function resolveHooks(\n hooks: Iterable<FirewallHook | string> | undefined,\n): ReadonlySet<FirewallHook> {\n if (hooks === undefined) {\n return DEFAULT_HOOKS;\n }\n const resolved = new Set<FirewallHook>();\n for (const h of hooks) {\n if (!FIREWALL_HOOK_VALUES.has(h)) {\n throw new Error(`Invalid FirewallHook value: ${String(h)}`);\n }\n resolved.add(h as FirewallHook);\n }\n return resolved;\n}\n\nexport function prependHook(text: string, hook: HookLabel | string | undefined | null): string {\n if (hook === undefined || hook === null) {\n return text;\n }\n if (hook === HookLabel.UNKNOWN) {\n return text;\n }\n return `[HOOK:${hook}] ${text}`;\n}\n\nexport function prependToolName(text: string, toolName: string | undefined | null): string {\n if (toolName === undefined || toolName === null) {\n return text;\n }\n return `[TOOL:${toolName}] ${text}`;\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nconst SKIP_ROLES: ReadonlySet<string> = new Set([\"ai\", \"assistant\"]);\nconst SYSTEM_ROLES: ReadonlySet<string> = new Set([\"system\"]);\nconst TOOL_ROLES: ReadonlySet<string> = new Set([\"tool\", \"function\"]);\n\ntype MessageContent = string | ReadonlyArray<string | { type?: string; text?: string }>;\n\ninterface DucktypedMessage {\n role?: string;\n type?: string;\n content?: MessageContent;\n}\n\ninterface DucktypedGeneration {\n text?: string;\n}\n\ninterface DucktypedLLMResult {\n generations?: ReadonlyArray<ReadonlyArray<DucktypedGeneration>>;\n}\n\ninterface DucktypedDocument {\n pageContent?: string;\n}\n\nfunction extractContentText(content: MessageContent | undefined): string {\n if (typeof content === \"string\") {\n return content;\n }\n if (Array.isArray(content)) {\n const parts: string[] = [];\n for (const block of content) {\n if (typeof block === \"string\") {\n parts.push(block);\n } else if (block && typeof block === \"object\" && block.type === \"text\") {\n parts.push(block.text ?? \"\");\n }\n }\n return parts.join(\" \");\n }\n return \"\";\n}\n\nfunction getRole(message: DucktypedMessage): string {\n if (message.role !== undefined) {\n return message.role.toLowerCase();\n }\n if (typeof message.type === \"string\") {\n return message.type.toLowerCase();\n }\n return \"\";\n}\n\nexport function extractTextFromMessages(\n messages: ReadonlyArray<DucktypedMessage>,\n options: { includeSystem?: boolean; includeTool?: boolean } = {},\n): string {\n const includeSystem = options.includeSystem ?? true;\n const includeTool = options.includeTool ?? true;\n const parts: string[] = [];\n for (const message of messages) {\n const role = getRole(message);\n if (SKIP_ROLES.has(role)) {\n continue;\n }\n if (!includeSystem && SYSTEM_ROLES.has(role)) {\n continue;\n }\n if (!includeTool && TOOL_ROLES.has(role)) {\n continue;\n }\n const text = extractContentText(message.content);\n const stripped = text.trim();\n if (stripped) {\n parts.push(stripped);\n }\n }\n return parts.join(\"\\n\");\n}\n\nexport function extractTextFromPrompts(prompts: readonly string[]): string {\n return prompts\n .map((p) => p.trim())\n .filter((p) => p.length > 0)\n .join(\"\\n\");\n}\n\nexport function extractTextFromToolInput(inputStr: string): string {\n return inputStr.trim();\n}\n\nexport function extractTextFromLLMResult(response: DucktypedLLMResult): string {\n const parts: string[] = [];\n for (const genList of response.generations ?? []) {\n for (const gen of genList) {\n const text = (gen.text ?? \"\").trim();\n if (text) {\n parts.push(text);\n }\n }\n }\n return parts.join(\"\\n\");\n}\n\nexport function extractTextFromDocuments(documents: ReadonlyArray<DucktypedDocument>): string {\n const parts: string[] = [];\n for (const doc of documents) {\n const text = (doc.pageContent ?? \"\").trim();\n if (text) {\n parts.push(text);\n }\n }\n return parts.join(\"\\n\");\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nimport type { BaseCallbackHandler } from \"@langchain/core/callbacks/base\";\n\nimport type { Firewall } from \"../firewall.js\";\nimport { FirewallBlockedException } from \"../exceptions.js\";\nimport {\n FIREWALL_HOOK_TO_LABEL,\n FirewallHook,\n HookLabel,\n resolveHooks,\n} from \"../hooks.js\";\nimport type { BlockResult, ClassifyEvent, LangChainAdapterOptions } from \"../types.js\";\nimport {\n extractTextFromDocuments,\n extractTextFromLLMResult,\n extractTextFromPrompts,\n extractTextFromToolInput,\n} from \"../utils/extract.js\";\n\nconst USER_ROLES: ReadonlySet<string> = new Set([\"human\", \"user\"]);\n\ninterface LangChainDucktypedMessage {\n role?: string;\n type?: string;\n content?: string | ReadonlyArray<string | { type?: string; text?: string }>;\n}\n\nfunction getMessageRole(message: LangChainDucktypedMessage): string {\n if (typeof message.role === \"string\") {\n return message.role.toLowerCase();\n }\n if (typeof message.type === \"string\") {\n return message.type.toLowerCase();\n }\n return \"\";\n}\n\nfunction extractMessageText(content: LangChainDucktypedMessage[\"content\"]): string {\n if (content === undefined) {\n return \"\";\n }\n if (typeof content === \"string\") {\n return content;\n }\n const parts: string[] = [];\n for (const block of content) {\n if (typeof block === \"string\") {\n parts.push(block);\n } else if (block && block.type === \"text\") {\n parts.push(block.text ?? \"\");\n }\n }\n return parts.join(\" \");\n}\n\nfunction findLastUserMessage(\n messages: ReadonlyArray<LangChainDucktypedMessage>,\n): LangChainDucktypedMessage | undefined {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]!;\n if (USER_ROLES.has(getMessageRole(msg))) {\n return msg;\n }\n }\n return undefined;\n}\n\nexport async function createLangChainHandler(\n firewall: Firewall,\n options: LangChainAdapterOptions = {},\n): Promise<BaseCallbackHandler> {\n const { BaseCallbackHandler } = await import(\"@langchain/core/callbacks/base\");\n\n const enabledHooks = resolveHooks(options.hooks);\n // includeSystem / includeTool are retained in LangChainAdapterOptions for\n // backwards compat but are inert under the per-message hook-routing algorithm:\n // handleChatModelStart only scans the last user-role message; system and tool\n // messages are either trusted or already classified by their own hooks.\n const failOpen = options.failOpen ?? true;\n const logger =\n options.logger ??\n ((message: string, error: unknown): void => {\n // eslint-disable-next-line no-console\n console.warn(`silmaril.firewall: ${message}`, error);\n });\n const shadowMode = options.shadowMode ?? firewall.shadowMode;\n const onClassify = options.onClassify;\n\n const fireOnClassify = (event: ClassifyEvent): void => {\n if (!onClassify) {\n return;\n }\n try {\n onClassify(event);\n } catch (err) {\n logger(\"onClassify callback threw\", err);\n }\n };\n\n const classify = async (\n text: string,\n hookLabel: HookLabel,\n runId: string,\n toolName?: string,\n ): Promise<void> => {\n let result: BlockResult;\n try {\n result = await firewall.classify(text, {\n hook: hookLabel,\n ...(toolName !== undefined ? { toolName } : {}),\n });\n } catch (err) {\n if (!failOpen) {\n throw err;\n }\n logger(\"classification failed, allowing prompt through\", err);\n return;\n }\n const threshold = result.threshold;\n const blocked = result.prediction === \"MALICIOUS\";\n const commonEventFields = {\n hook: hookLabel,\n ...(toolName !== undefined ? { toolName } : {}),\n runId,\n text,\n result,\n };\n fireOnClassify({\n ...commonEventFields,\n blocked,\n shadowMode,\n });\n if (!blocked || shadowMode) {\n return;\n }\n\n throw new FirewallBlockedException({\n score: result.score,\n threshold,\n promptText: text,\n runId,\n hook: hookLabel,\n ...(toolName !== undefined ? { toolName } : {}),\n result,\n });\n };\n\n class SilmarilFirewallHandler extends BaseCallbackHandler {\n override name = \"silmaril_firewall_handler\";\n override raiseError = true;\n override awaitHandlers = true;\n\n override async handleChatModelStart(\n _llm: unknown,\n messages: unknown,\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.CHAT_MODEL_START)) {\n return;\n }\n const batches = messages as ReadonlyArray<ReadonlyArray<LangChainDucktypedMessage>>;\n const flat: LangChainDucktypedMessage[] = [];\n for (const batch of batches) {\n for (const m of batch) {\n flat.push(m);\n }\n }\n const lastUser = findLastUserMessage(flat);\n if (!lastUser) {\n return;\n }\n const text = extractMessageText(lastUser.content).trim();\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.CHAT_MODEL_START], runId);\n }\n\n override async handleLLMStart(\n _llm: unknown,\n prompts: string[],\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.LLM_START)) {\n return;\n }\n const text = extractTextFromPrompts(prompts);\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.LLM_START], runId);\n }\n\n override async handleToolStart(\n tool: { name?: string } | undefined,\n inputStr: string,\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.TOOL_START)) {\n return;\n }\n const text = extractTextFromToolInput(inputStr);\n if (!text) {\n return;\n }\n const toolName = tool?.name;\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.TOOL_START], runId, toolName);\n }\n\n override async handleRetrieverStart(\n _retriever: unknown,\n query: string,\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.RETRIEVER_START)) {\n return;\n }\n const text = query.trim();\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.RETRIEVER_START], runId);\n }\n\n override async handleLLMEnd(output: unknown, runId: string): Promise<void> {\n if (!enabledHooks.has(FirewallHook.LLM_END)) {\n return;\n }\n const text = extractTextFromLLMResult(output as { generations?: ReadonlyArray<ReadonlyArray<{ text?: string }>> });\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.LLM_END], runId);\n }\n\n override async handleToolEnd(\n output: unknown,\n runId: string,\n _parentRunId?: string,\n _tags?: string[],\n _kwargs?: { name?: string },\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.TOOL_END)) {\n return;\n }\n const text = String(output).trim();\n if (!text) {\n return;\n }\n const toolName = _kwargs?.name;\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.TOOL_END], runId, toolName);\n }\n\n override async handleRetrieverEnd(\n documents: ReadonlyArray<{ pageContent?: string }>,\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.RETRIEVER_END)) {\n return;\n }\n const text = extractTextFromDocuments(documents);\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.RETRIEVER_END], runId);\n }\n }\n\n return new SilmarilFirewallHandler();\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nimport { randomUUID } from \"node:crypto\";\n\nimport { createMiddleware, type FirewallMiddleware } from \"./adapters/vercel.js\";\nimport { SilmarilApiError } from \"./exceptions.js\";\nimport { normalizeHarmfulOutcomeMap, normalizePrimaryOutcome } from \"./outcomes.js\";\nimport { sanitizeText } from \"./sanitization.js\";\nimport type {\n BlockResult,\n ClassifyBatchOptions,\n ClassifyOptions,\n ClassificationMetadata,\n FirewallOptions,\n LangChainAdapterOptions,\n LangChainFirewallHandler,\n MiddlewareOptions,\n Prediction,\n} from \"./types.js\";\n\nexport const SDK_VERSION = \"0.5.1\";\nexport const DEFAULT_TIMEOUT_MS = 10_000;\nconst DEFAULT_MAX_RETRIES = 5;\nconst MAX_BACKOFF_SECONDS = 30;\nconst MAX_ERROR_BODY_BYTES = 1 << 16;\n\ninterface SingleClassifyPayload {\n text: string;\n hook?: string;\n tool_name?: string;\n metadata?: ClassificationMetadata;\n}\n\ninterface BatchClassifyPayload {\n texts: readonly string[];\n hooks?: readonly string[];\n tool_names?: readonly (string | null)[];\n metadata?: readonly (ClassificationMetadata | null)[];\n}\n\ninterface SingleClassifyResponse {\n prediction: Prediction;\n score: number;\n threshold: number;\n primary_outcome?: unknown;\n outcome_scores?: unknown;\n detector_scores?: unknown;\n detector_counts?: unknown;\n}\n\ninterface BatchClassifyResponse {\n predictions: readonly SingleClassifyResponse[];\n}\n\nfunction blockResultFromResponse(data: SingleClassifyResponse): BlockResult {\n if (data.prediction !== \"BENIGN\" && data.prediction !== \"MALICIOUS\") {\n throw new Error(\"Firewall: response prediction must be BENIGN or MALICIOUS\");\n }\n const result: {\n prediction: Prediction;\n score: number;\n threshold: number;\n primaryOutcome?: NonNullable<BlockResult[\"primaryOutcome\"]>;\n outcomeScores?: NonNullable<BlockResult[\"outcomeScores\"]>;\n detectorScores?: NonNullable<BlockResult[\"detectorScores\"]>;\n detectorCounts?: NonNullable<BlockResult[\"detectorCounts\"]>;\n } = {\n prediction: data.prediction,\n score: Number(data.score),\n threshold: Number(data.threshold),\n };\n if (data.primary_outcome !== undefined) {\n result.primaryOutcome = normalizePrimaryOutcome(data.primary_outcome);\n }\n if (data.outcome_scores !== undefined) {\n const outcomeScores = normalizeHarmfulOutcomeMap(data.outcome_scores, \"outcome_scores\");\n if (outcomeScores !== undefined) {\n result.outcomeScores = outcomeScores;\n }\n }\n if (data.detector_scores !== undefined) {\n const detectorScores = normalizeHarmfulOutcomeMap(data.detector_scores, \"detector_scores\");\n if (detectorScores !== undefined) {\n result.detectorScores = detectorScores;\n }\n }\n if (data.detector_counts !== undefined) {\n const detectorCounts = normalizeHarmfulOutcomeMap(data.detector_counts, \"detector_counts\");\n if (detectorCounts !== undefined) {\n result.detectorCounts = detectorCounts;\n }\n }\n return Object.freeze(result);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction withSdkMetadata(\n metadata: ClassificationMetadata | undefined,\n info: {\n requestId: string;\n inputIndex?: number;\n },\n): ClassificationMetadata {\n const payload: Record<string, unknown> = { ...(metadata ?? {}) };\n const existing = payload.silmaril;\n if (existing !== undefined && !isRecord(existing)) {\n throw new Error(\"Firewall: metadata.silmaril must be an object when provided\");\n }\n payload.silmaril = {\n ...(isRecord(existing) ? existing : {}),\n sdk_language: \"typescript\",\n sdk_version: SDK_VERSION,\n request_id: info.requestId,\n ...(info.inputIndex === undefined ? {} : { input_index: info.inputIndex }),\n };\n return payload;\n}\n\nasync function readCappedErrorBody(response: Response): Promise<string> {\n if (!response.body) {\n return response.text().then((body) => body.slice(0, MAX_ERROR_BODY_BYTES)).catch(() => \"\");\n }\n\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let remaining = MAX_ERROR_BODY_BYTES;\n try {\n while (remaining > 0) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n if (!value) {\n continue;\n }\n const chunk = value.byteLength > remaining ? value.slice(0, remaining) : value;\n chunks.push(chunk);\n remaining -= chunk.byteLength;\n if (chunk.byteLength < value.byteLength) {\n break;\n }\n }\n } catch {\n return \"\";\n } finally {\n await reader.cancel().catch(() => undefined);\n }\n\n const total = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);\n const body = new Uint8Array(total);\n let offset = 0;\n for (const chunk of chunks) {\n body.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return new TextDecoder().decode(body);\n}\n\nexport class Firewall {\n readonly apiKey: string;\n readonly apiUrl: string;\n readonly timeoutMs: number;\n readonly shadowMode: boolean;\n\n private readonly headers: Readonly<Record<string, string>>;\n\n constructor(options: FirewallOptions) {\n if (!options.apiKey) {\n throw new Error(\"Firewall: apiKey is required\");\n }\n if (!options.apiUrl) {\n throw new Error(\"Firewall: apiUrl is required\");\n }\n this.apiKey = options.apiKey;\n this.apiUrl = options.apiUrl;\n this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n if (typeof this.timeoutMs !== \"number\" || !Number.isFinite(this.timeoutMs) || this.timeoutMs < 0) {\n throw new Error(`Firewall: timeoutMs must be a finite non-negative number, got ${this.timeoutMs}`);\n }\n this.shadowMode = options.shadowMode ?? false;\n this.headers = Object.freeze({\n \"x-api-key\": this.apiKey,\n \"content-type\": \"application/json\",\n });\n }\n\n async classify(text: string, options: ClassifyOptions = {}): Promise<BlockResult> {\n const requestId = options.requestId ?? randomUUID();\n return this.classifySingle(sanitizeText(text), options, { requestId });\n }\n\n async classifyBatch(\n texts: readonly string[],\n options: ClassifyBatchOptions = {},\n ): Promise<BlockResult[]> {\n if (texts.length === 0) {\n throw new Error(\"Firewall: texts must not be empty\");\n }\n if (options.hooks !== undefined && options.hooks.length !== texts.length) {\n throw new Error(\n `Firewall: hooks length ${options.hooks.length} does not match texts length ${texts.length}`,\n );\n }\n if (options.toolNames !== undefined && options.toolNames.length !== texts.length) {\n throw new Error(\n `Firewall: toolNames length ${options.toolNames.length} does not match texts length ${texts.length}`,\n );\n }\n if (options.metadata !== undefined && options.metadata.length !== texts.length) {\n throw new Error(\n `Firewall: metadata length ${options.metadata.length} does not match texts length ${texts.length}`,\n );\n }\n\n const requestId = options.requestId ?? randomUUID();\n const payload: BatchClassifyPayload = {\n texts: texts.map((text) => sanitizeText(text)),\n };\n if (options.hooks && options.hooks.length > 0) {\n payload.hooks = options.hooks.map((h) => String(h));\n }\n if (options.toolNames && options.toolNames.length > 0) {\n payload.tool_names = options.toolNames.map((t) => (t === undefined ? null : t));\n }\n payload.metadata = texts.map((_, index) =>\n withSdkMetadata(options.metadata?.[index], {\n requestId,\n inputIndex: index,\n }),\n );\n const data = await this.postWithRetry<BatchClassifyResponse>(payload);\n return data.predictions.map((p) => blockResultFromResponse(p));\n }\n\n asLangChainHandler<THandler = LangChainFirewallHandler>(\n options: LangChainAdapterOptions = {},\n ): Promise<THandler> {\n return import(\"./adapters/langchain.js\").then((m) =>\n m.createLangChainHandler(this, options) as Promise<THandler>,\n );\n }\n\n asMiddleware(options: MiddlewareOptions = {}): FirewallMiddleware {\n return createMiddleware(this, options);\n }\n\n private async postWithRetry<T>(\n payload: SingleClassifyPayload | BatchClassifyPayload,\n maxRetries: number = DEFAULT_MAX_RETRIES,\n ): Promise<T> {\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const response = await fetch(this.apiUrl, {\n method: \"POST\",\n headers: this.headers,\n body: JSON.stringify(payload),\n redirect: \"error\",\n signal: AbortSignal.timeout(this.timeoutMs),\n });\n if (response.status !== 429 || attempt === maxRetries) {\n if (!response.ok) {\n const body = await readCappedErrorBody(response);\n throw new SilmarilApiError({\n status: response.status,\n statusText: response.statusText,\n body,\n });\n }\n return (await response.json()) as T;\n }\n const waitSeconds = Math.min(2 ** attempt, MAX_BACKOFF_SECONDS);\n await new Promise<void>((resolve) => setTimeout(resolve, waitSeconds * 1000));\n }\n throw new Error(\"Firewall: exhausted retries (unreachable)\");\n }\n\n private async classifySingle(\n text: string,\n options: ClassifyOptions,\n metadataInfo: {\n requestId: string;\n },\n ): Promise<BlockResult> {\n const payload: SingleClassifyPayload = { text };\n if (options.hook !== undefined) {\n payload.hook = options.hook;\n }\n if (options.toolName !== undefined) {\n payload.tool_name = options.toolName;\n }\n payload.metadata = withSdkMetadata(options.metadata, metadataInfo);\n const data = await this.postWithRetry<SingleClassifyResponse>(payload);\n return blockResultFromResponse(data);\n }\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nimport type { Firewall } from \"../firewall.js\";\nimport { FirewallBlockedException } from \"../exceptions.js\";\nimport { HookLabel } from \"../hooks.js\";\nimport type { BlockResult, MiddlewareOptions } from \"../types.js\";\n\ninterface VercelContentPart {\n type?: string;\n text?: string;\n toolCallId?: string;\n toolName?: string;\n args?: unknown;\n output?: unknown;\n result?: unknown;\n}\n\ninterface VercelPromptMessage {\n role: string;\n content: string | ReadonlyArray<VercelContentPart | string>;\n}\n\ninterface VercelToolCall {\n toolCallType?: string;\n toolCallId?: string;\n toolName?: string;\n args?: unknown;\n input?: unknown;\n}\n\ninterface VercelGenerateResult {\n text?: string;\n toolCalls?: ReadonlyArray<VercelToolCall>;\n}\n\ninterface WrapGenerateArgs<TResult extends VercelGenerateResult & Record<string, unknown>> {\n params: { prompt?: ReadonlyArray<VercelPromptMessage> } & Record<string, unknown>;\n doGenerate: () => PromiseLike<TResult>;\n}\n\ninterface WrapStreamArgs<\n TResult extends { stream: ReadableStream<unknown> } & Record<string, unknown>,\n> {\n params: { prompt?: ReadonlyArray<VercelPromptMessage> } & Record<string, unknown>;\n doStream: () => PromiseLike<TResult>;\n}\n\ninterface StreamPart {\n type?: string;\n textDelta?: string;\n delta?: string;\n}\n\ninterface VercelStepContext {\n toolName: string | undefined;\n toolCallId: string | undefined;\n}\n\nfunction stringifyToolValue(value: unknown): string {\n if (value === null || value === undefined) {\n return \"\";\n }\n if (typeof value === \"string\") {\n return value;\n }\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction extractContentText(content: VercelPromptMessage[\"content\"]): string {\n if (typeof content === \"string\") {\n return content;\n }\n const parts: string[] = [];\n for (const block of content) {\n if (typeof block === \"string\") {\n parts.push(block);\n } else if (block && block.type === \"text\") {\n parts.push(block.text ?? \"\");\n }\n }\n return parts.join(\" \");\n}\n\nfunction iterateToolResultParts(\n message: VercelPromptMessage,\n): Array<{ text: string; toolName: string | undefined; toolCallId: string | undefined }> {\n if (typeof message.content === \"string\") {\n return [];\n }\n const out: Array<{ text: string; toolName: string | undefined; toolCallId: string | undefined }> = [];\n for (const part of message.content) {\n if (typeof part === \"string\") {\n continue;\n }\n if (part.type === \"tool-result\") {\n const text = stringifyToolResult(part.result !== undefined ? part.result : part.output);\n if (text.trim()) {\n out.push({ text, toolName: part.toolName, toolCallId: part.toolCallId });\n }\n }\n }\n return out;\n}\n\nfunction stringifyToolResult(value: unknown): string {\n if (!isRecord(value)) {\n return stringifyToolValue(value);\n }\n if ((value.type === \"text\" || value.type === \"error-text\") && typeof value.value === \"string\") {\n return value.value;\n }\n if ((value.type === \"json\" || value.type === \"error-json\") && value.value !== undefined) {\n return stringifyToolValue(value.value);\n }\n if (value.type === \"content\" && Array.isArray(value.value)) {\n return value.value\n .map((part) => (isRecord(part) && part.type === \"text\" && typeof part.text === \"string\" ? part.text : \"\"))\n .filter((text) => text.length > 0)\n .join(\" \");\n }\n return stringifyToolValue(value);\n}\n\nfunction findLastUserMessage(\n messages: ReadonlyArray<VercelPromptMessage>,\n): VercelPromptMessage | undefined {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]!;\n if (msg.role.toLowerCase() === \"user\") {\n return msg;\n }\n }\n return undefined;\n}\n\nexport interface FirewallMiddleware {\n readonly specificationVersion: \"v3\";\n readonly middlewareVersion: \"v2\";\n wrapGenerate: <TResult extends VercelGenerateResult & Record<string, unknown>>(\n args: WrapGenerateArgs<TResult>,\n ) => Promise<TResult>;\n wrapStream: <TResult extends { stream: ReadableStream<unknown> } & Record<string, unknown>>(\n args: WrapStreamArgs<TResult>,\n ) => Promise<TResult>;\n}\n\nexport function createMiddleware(\n firewall: Firewall,\n options: MiddlewareOptions = {},\n): FirewallMiddleware {\n const scanInput = options.scanInput ?? true;\n const scanOutput = options.scanOutput ?? false;\n const shadowMode = options.shadowMode ?? firewall.shadowMode;\n\n const classifyOrBlock = async (\n text: string,\n hook: HookLabel,\n context: VercelStepContext = { toolName: undefined, toolCallId: undefined },\n ): Promise<void> => {\n if (!text.trim()) {\n return;\n }\n const { toolName, toolCallId } = context;\n const result: BlockResult = await firewall.classify(\n text,\n toolName !== undefined ? { hook, toolName } : { hook },\n );\n const threshold = result.threshold;\n const blocked = result.prediction === \"MALICIOUS\";\n const commonEventFields = {\n hook,\n ...(toolName !== undefined ? { toolName } : {}),\n ...(toolCallId !== undefined ? { toolCallId } : {}),\n text,\n result,\n };\n options.onClassify?.({\n ...commonEventFields,\n blocked,\n shadowMode,\n });\n if (!blocked || shadowMode) {\n return;\n }\n\n const err = new FirewallBlockedException({\n score: result.score,\n threshold,\n promptText: text,\n hook,\n ...(toolName !== undefined ? { toolName } : {}),\n ...(toolCallId !== undefined ? { toolCallId } : {}),\n result,\n });\n options.onBlocked?.(err);\n throw err;\n };\n\n const scanPrompt = async (prompt: ReadonlyArray<VercelPromptMessage>): Promise<void> => {\n if (prompt.length === 0) {\n return;\n }\n const last = prompt[prompt.length - 1]!;\n const role = last.role.toLowerCase();\n\n // If the newest message is a tool result (typical mid-flow in a\n // tool-calling loop), classify each tool-result part individually with\n // tool_response + toolName. No manual wiring from the caller — the\n // toolName is read directly from the Vercel content part.\n if (role === \"tool\") {\n for (const { text, toolName, toolCallId } of iterateToolResultParts(last)) {\n await classifyOrBlock(text, HookLabel.TOOL_RESPONSE, { toolName, toolCallId });\n }\n return;\n }\n\n // Otherwise, fall back to scanning the most recent user message.\n // Covers: [user], [system, user], [user, assistant(text), user], etc.\n const lastUser = findLastUserMessage(prompt);\n if (!lastUser) {\n return;\n }\n const text = extractContentText(lastUser.content).trim();\n if (!text) {\n return;\n }\n await classifyOrBlock(text, HookLabel.USER_INPUT);\n };\n\n const scanGenerateResult = async (result: VercelGenerateResult): Promise<void> => {\n if (scanOutput && typeof result.text === \"string\" && result.text.length > 0) {\n await classifyOrBlock(result.text, HookLabel.LLM_OUTPUT);\n }\n if (options.scanToolCalls && Array.isArray(result.toolCalls)) {\n for (const call of result.toolCalls) {\n if (!call || typeof call !== \"object\") {\n continue;\n }\n const toolInput = call.args !== undefined ? call.args : call.input;\n const args =\n typeof toolInput === \"string\" ? toolInput : stringifyToolValue(toolInput);\n const toolName = typeof call.toolName === \"string\" ? call.toolName : undefined;\n const toolCallId = typeof call.toolCallId === \"string\" ? call.toolCallId : undefined;\n if (args.trim()) {\n await classifyOrBlock(args, HookLabel.TOOL_CALL, { toolName, toolCallId });\n }\n }\n }\n };\n\n return {\n specificationVersion: \"v3\",\n middlewareVersion: \"v2\",\n\n async wrapGenerate<TResult extends VercelGenerateResult & Record<string, unknown>>({\n params,\n doGenerate,\n }: WrapGenerateArgs<TResult>): Promise<TResult> {\n if (scanInput) {\n await scanPrompt(params.prompt ?? []);\n }\n const result = await doGenerate();\n await scanGenerateResult(result);\n return result;\n },\n\n async wrapStream<TResult extends { stream: ReadableStream<unknown> } & Record<string, unknown>>({\n params,\n doStream,\n }: WrapStreamArgs<TResult>): Promise<TResult> {\n if (scanInput) {\n await scanPrompt(params.prompt ?? []);\n }\n const { stream, ...rest } = await doStream();\n if (!scanOutput) {\n return { stream, ...rest } as unknown as TResult;\n }\n\n let buffered = \"\";\n const transformed = stream.pipeThrough(\n new TransformStream<unknown, unknown>({\n transform(chunk, controller): void {\n const part = chunk as StreamPart;\n if (part && part.type === \"text-delta\") {\n const delta = part.textDelta ?? part.delta ?? \"\";\n buffered += delta;\n }\n controller.enqueue(chunk);\n },\n async flush(controller): Promise<void> {\n if (!buffered.trim()) {\n return;\n }\n try {\n await classifyOrBlock(buffered, HookLabel.LLM_OUTPUT);\n } catch (err) {\n if (err instanceof FirewallBlockedException) {\n controller.enqueue({ type: \"error\", error: err });\n return;\n }\n throw err;\n }\n },\n }),\n );\n return { stream: transformed, ...rest } as unknown as TResult;\n },\n };\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nexport const Outcome = {\n Benign: \"benign\",\n InformationDisclosure: \"information_disclosure\",\n SecretExposure: \"secret_exposure\",\n ControlAbuse: \"control_abuse\",\n SystemCompromise: \"system_compromise\",\n ServiceDisruption: \"service_disruption\",\n CodeGeneration: \"code_generation\",\n StoryScriptGeneration: \"story_script_generation\",\n GameGeneration: \"game_generation\",\n WebsiteGeneration: \"website_generation\",\n ClickUpTermsViolation: \"clickup_terms_violation\",\n TraditionalAiAbuse: \"traditional_ai_abuse\",\n} as const;\n\ndeclare const unknownOutcomeBrand: unique symbol;\n\nexport type KnownPrimaryOutcome = (typeof Outcome)[keyof typeof Outcome];\nexport type KnownHarmfulOutcome = Exclude<KnownPrimaryOutcome, typeof Outcome.Benign>;\nexport type UnknownOutcome = string & { readonly [unknownOutcomeBrand]: \"UnknownOutcome\" };\nexport type PrimaryOutcome = KnownPrimaryOutcome | UnknownOutcome;\nexport type HarmfulOutcome = KnownHarmfulOutcome | UnknownOutcome;\n\nexport const PRIMARY_OUTCOMES = [\n Outcome.Benign,\n Outcome.InformationDisclosure,\n Outcome.SecretExposure,\n Outcome.ControlAbuse,\n Outcome.SystemCompromise,\n Outcome.ServiceDisruption,\n Outcome.CodeGeneration,\n Outcome.StoryScriptGeneration,\n Outcome.GameGeneration,\n Outcome.WebsiteGeneration,\n Outcome.ClickUpTermsViolation,\n Outcome.TraditionalAiAbuse,\n] as const satisfies readonly PrimaryOutcome[];\n\nexport const HARMFUL_OUTCOMES = [\n Outcome.InformationDisclosure,\n Outcome.SecretExposure,\n Outcome.ControlAbuse,\n Outcome.SystemCompromise,\n Outcome.ServiceDisruption,\n Outcome.CodeGeneration,\n Outcome.StoryScriptGeneration,\n Outcome.GameGeneration,\n Outcome.WebsiteGeneration,\n Outcome.ClickUpTermsViolation,\n Outcome.TraditionalAiAbuse,\n] as const satisfies readonly KnownHarmfulOutcome[];\n\nexport const OUTCOME_DESCRIPTIONS = {\n [Outcome.Benign]: \"No harmful firewall outcome detected.\",\n [Outcome.InformationDisclosure]:\n \"Exposes private data, documents, internal context, logs, traces, customer data, SQL rows, topology, or similar non-secret sensitive information.\",\n [Outcome.SecretExposure]:\n \"Exposes credentials, tokens, API keys, cookies, passwords, signing keys, OAuth secrets, session material, or webhook secrets.\",\n [Outcome.ControlAbuse]:\n \"Misuses authorized tools or user privileges to send, change, approve, delete, operate, or bypass policy/RBAC without a stronger outcome.\",\n [Outcome.SystemCompromise]:\n \"Enables privilege escalation, account takeover, hostile integration or plugin takeover, persistence, lateral movement, attacker webhook registration, or code/plugin execution.\",\n [Outcome.ServiceDisruption]:\n \"Causes downtime, lockout, degradation, alert suppression, destructive loops, resource exhaustion, cost spikes, or hidden outage evidence.\",\n [Outcome.CodeGeneration]:\n \"Requests generation or material modification of executable code, scripts, workflows, or configuration.\",\n [Outcome.StoryScriptGeneration]:\n \"Requests generation of narrative prose, dialogue, scripts, or story artifacts.\",\n [Outcome.GameGeneration]:\n \"Requests generation of a game, quest, level, mechanic, or playable experience.\",\n [Outcome.WebsiteGeneration]:\n \"Requests generation of a website, landing page, storefront, or web experience.\",\n [Outcome.ClickUpTermsViolation]:\n \"Requests content or actions that violate the configured ClickUp tenant policy.\",\n [Outcome.TraditionalAiAbuse]:\n \"Requests unsafe AI assistance outside the concrete security outcome classes.\",\n} as const satisfies Readonly<Record<KnownPrimaryOutcome, string>>;\n\nconst PRIMARY_OUTCOME_SET = new Set<string>(PRIMARY_OUTCOMES);\nconst HARMFUL_OUTCOME_SET = new Set<string>(HARMFUL_OUTCOMES);\n\nexport function isPrimaryOutcome(value: unknown): value is KnownPrimaryOutcome {\n return typeof value === \"string\" && PRIMARY_OUTCOME_SET.has(value);\n}\n\nexport function isHarmfulOutcome(value: unknown): value is KnownHarmfulOutcome {\n return typeof value === \"string\" && HARMFUL_OUTCOME_SET.has(value);\n}\n\nexport function normalizePrimaryOutcome(\n value: unknown,\n fieldName = \"primary_outcome\",\n): PrimaryOutcome {\n if (typeof value !== \"string\") {\n throw new Error(`Firewall: invalid ${fieldName} ${JSON.stringify(value)}`);\n }\n return isPrimaryOutcome(value) ? value : (value as UnknownOutcome);\n}\n\nexport function normalizeHarmfulOutcome(\n value: unknown,\n fieldName = \"outcome\",\n): HarmfulOutcome {\n if (typeof value !== \"string\" || value === Outcome.Benign) {\n throw new Error(`Firewall: invalid ${fieldName} ${JSON.stringify(value)}`);\n }\n return isHarmfulOutcome(value) ? value : (value as UnknownOutcome);\n}\n\nexport function normalizeHarmfulOutcomeMap(\n values: unknown,\n fieldName: string,\n): Readonly<Partial<Record<HarmfulOutcome, number>>> | undefined {\n if (values === undefined || values === null) {\n return undefined;\n }\n if (typeof values !== \"object\" || Array.isArray(values)) {\n throw new Error(`Firewall: invalid ${fieldName} ${JSON.stringify(values)}`);\n }\n const out: Partial<Record<HarmfulOutcome, number>> = {};\n for (const [key, value] of Object.entries(values)) {\n const normalizedKey = normalizeHarmfulOutcome(key, `${fieldName} key`);\n if (typeof value !== \"number\") {\n throw new Error(`Firewall: invalid ${fieldName} value for ${JSON.stringify(key)}`);\n }\n out[normalizedKey] = value;\n }\n return Object.freeze(out);\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nfunction isHighSurrogate(code: number): boolean {\n return code >= 0xd800 && code <= 0xdbff;\n}\n\nfunction isLowSurrogate(code: number): boolean {\n return code >= 0xdc00 && code <= 0xdfff;\n}\n\nexport function sanitizeText(text: string): string {\n let out = \"\";\n for (let i = 0; i < text.length; i++) {\n const code = text.charCodeAt(i);\n if (isHighSurrogate(code)) {\n if (i + 1 < text.length && isLowSurrogate(text.charCodeAt(i + 1))) {\n out += text[i]!;\n out += text[i + 1]!;\n i++;\n }\n continue;\n }\n if (!isLowSurrogate(code)) {\n out += text[i]!;\n }\n }\n return out;\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nexport {\n Firewall,\n DEFAULT_TIMEOUT_MS,\n} from \"./firewall.js\";\n\nexport { FirewallBlockedException, PromptBlockedException, SilmarilApiError } from \"./exceptions.js\";\nexport type { MalformedInputDetails } from \"./exceptions.js\";\n\nexport type { FirewallMiddleware } from \"./adapters/vercel.js\";\n\nexport {\n HookLabel,\n FirewallHook,\n DEFAULT_HOOKS,\n INPUT_HOOKS,\n OUTPUT_HOOKS,\n ALL_HOOKS,\n FIREWALL_HOOK_TO_LABEL,\n resolveHooks,\n prependHook,\n prependToolName,\n} from \"./hooks.js\";\n\nexport {\n Outcome,\n PRIMARY_OUTCOMES,\n HARMFUL_OUTCOMES,\n OUTCOME_DESCRIPTIONS,\n isPrimaryOutcome,\n isHarmfulOutcome,\n normalizePrimaryOutcome,\n normalizeHarmfulOutcome,\n normalizeHarmfulOutcomeMap,\n} from \"./outcomes.js\";\n\nexport type {\n KnownPrimaryOutcome,\n KnownHarmfulOutcome,\n PrimaryOutcome,\n HarmfulOutcome,\n UnknownOutcome,\n} from \"./outcomes.js\";\n\nexport type {\n BlockResult,\n ClassifyEvent,\n Prediction,\n ClassificationMetadata,\n FirewallOptions,\n ClassifyOptions,\n ClassifyBatchOptions,\n LangChainAdapterOptions,\n LangChainFirewallHandler,\n MiddlewareOptions,\n} from \"./types.js\";\n"],"mappings":"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","names":["findLastUserMessage","text","isRecord","body"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@silmaril-security/sdk",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "TypeScript SDK for Silmaril Firewall — prompt injection and jailbreak detection",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": "Silmaril Security Inc.",
@@ -109,6 +109,6 @@
109
109
  },
110
110
  "overrides": {
111
111
  "esbuild": "0.28.1",
112
- "js-yaml": "4.2.0"
112
+ "js-yaml": "4.3.0"
113
113
  }
114
114
  }