@silmaril-security/sdk 0.7.0 → 0.7.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,14 +2,22 @@
2
2
 
3
3
  All notable changes to the Silmaril Firewall TypeScript SDK are documented here.
4
4
 
5
+ ## 0.7.1 - 2026-10-04
6
+
7
+ - Reject malformed batch responses and result counts that do not match the
8
+ serialized request, including retried requests whose caller inputs change.
9
+
5
10
  ## 0.7.0 - 2026-09-30
6
11
 
7
12
  - Add optional Deep Agents middleware and protected constructors for root, general-purpose,
8
13
  declarative, and explicitly protected compiled subagents. The compiled graph factory
9
14
  records middleware installation and constructors reject unverified graphs.
15
+ - Declare optional peer dependencies for Deep Agents:
16
+ `deepagents@^1.14.1`, `langchain@^1.5.10`, `@langchain/langgraph@^1.4.10`, and
17
+ existing `@langchain/core@>=0.3.0`.
10
18
  - Enforce input, tool-call, tool-result, and non-streamed model-output decisions in
11
- Block mode with safe continuation and a repeated-denial cap. Shadow and Warn report
12
- decisions without changing content.
19
+ Block mode with safe continuation and a repeated-denial cap (`maxBlockedAttempts`,
20
+ default `3`). Shadow and Warn report decisions without changing content.
13
21
  - Enable LangChain tool start/end callbacks by default and send the LangChain run ID
14
22
  as correlation metadata alongside a distinct classification request ID per event.
15
23
 
package/README.md CHANGED
@@ -18,13 +18,13 @@ This SDK provides the low-level TypeScript interface for that workflow:
18
18
  - Classify user input, tool calls, tool responses, model output, or system
19
19
  prompt content.
20
20
  - Preserve hook and tool-name context for more accurate decisions.
21
- - Enforce backend-owned adaptive thresholds and effective Shadow, Warn, or
21
+ - Honor backend threat and governance decisions and effective Shadow, Warn, or
22
22
  Block behavior in adapters.
23
23
  - Send each complete sanitized event in one request.
24
- - Preserve exact `metadata.conversationId` sequence identity and add one event ID.
24
+ - On individual `classify()` calls, preserve exact `metadata.conversationId` as sequence identity and add one event ID.
25
25
  - Retry API rate-limit responses.
26
- - Optionally attach the firewall to Vercel AI SDK middleware and LangChain.js
27
- callback flows.
26
+ - Optionally attach the firewall to Vercel AI SDK middleware, LangChain.js
27
+ callback flows, and Deep Agents middleware/constructors.
28
28
 
29
29
  ## Install
30
30
 
@@ -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.7.0
40
+ npm install @silmaril-security/sdk@0.7.1
41
41
  ```
42
42
 
43
43
  Requires Node 20 or later.
@@ -63,10 +63,10 @@ Optional LangChain.js support:
63
63
  npm install @langchain/core @langchain/openai
64
64
  ```
65
65
 
66
- Optional Deep Agents support:
66
+ Optional Deep Agents support (peer ranges shipped with `0.7.0`):
67
67
 
68
68
  ```sh
69
- npm install deepagents langchain @langchain/core @langchain/langgraph
69
+ npm install "deepagents@^1.14.1" "langchain@^1.5.10" "@langchain/core@>=0.3.0" "@langchain/langgraph@^1.4.10"
70
70
  ```
71
71
 
72
72
  ## Configuration
@@ -119,15 +119,21 @@ console.log(`tool output: ${toolResult.prediction} ${toolResult.score.toFixed(4)
119
119
  ```
120
120
 
121
121
  `classify()` and `classifyBatch()` return the server's prediction, score, and
122
- internally applied threshold. Direct calls do not throw on malicious verdicts.
123
- The Vercel AI SDK and LangChain.js adapters use `result.threshold` and throw
124
- `FirewallBlockedException` when enforcement is enabled.
122
+ diagnostic threshold. Direct calls do not throw on a `MALICIOUS` prediction or
123
+ a governance block. The Vercel AI SDK and LangChain.js adapters throw
124
+ `FirewallBlockedException` only when `prediction` is `MALICIOUS` or
125
+ `governance.action` is `block`, and the effective mode is `block`.
126
+ `result.threshold` is backend-returned diagnostic metadata carried on the
127
+ result and the exception. Disabled and observe policy paths can retain the
128
+ compatibility threshold. The adapters do not compare `score` to a local
129
+ threshold.
125
130
 
126
131
  ## Concurrency and Cancellation
127
132
 
128
133
  A `Firewall` instance holds no per-request state, so one client can serve any
129
- number of concurrent calls in a runtime. Responses are matched to their own
130
- promise regardless of completion order:
134
+ number of concurrent calls in a runtime. Concurrent calls are appropriate for
135
+ independent events or different conversations. Responses are matched to their
136
+ own promise regardless of completion order:
131
137
 
132
138
  ```ts
133
139
  const [userResult, toolResult] = await Promise.all([
@@ -136,6 +142,10 @@ const [userResult, toolResult] = await Promise.all([
136
142
  ]);
137
143
  ```
138
144
 
145
+ Events that belong to one conversation are not independent. Send them with
146
+ ordered individual `classify()` calls that share `metadata.conversationId`, and
147
+ wait for each call before sending the next event for that conversation.
148
+
139
149
  Pass a `signal` to cancel one call without touching its siblings:
140
150
 
141
151
  ```ts
@@ -242,17 +252,16 @@ to each attempt and is combined with any caller-supplied `signal`.
242
252
 
243
253
  ## Backend Thresholding
244
254
 
245
- Customers do not tune score thresholds in the SDK. Tenant Firewall config owns
246
- the adaptive threshold schedule. The default backend config is
247
- `base_threshold=0.5`, `target_sequence_fpr=0.01`, and
248
- `max_adaptive_threshold=0.9`, which keeps the current schedule: 1 scoring
249
- opportunity uses `0.5`, 2 use about `0.6661`, 5 use about `0.8328`, and 10 or
250
- more are capped at `0.9`.
255
+ Customers do not tune score thresholds in the SDK. The Firewall backend owns
256
+ the threat decision and threshold policy. The current Cascade backend resolves
257
+ decision thresholds from a tenant default or a hook-specific override; it does
258
+ not raise them as text length, token-window count, batch size, or conversation
259
+ length grows.
251
260
 
252
- The SDK does not send `threshold` in request payloads. The backend owns the
253
- applied threshold, which remains available on
254
- `BlockResult.threshold` and `FirewallBlockedException.threshold` as diagnostic
255
- metadata.
261
+ The SDK does not send `threshold` in request payloads. `BlockResult.threshold`
262
+ and `FirewallBlockedException.threshold` are backend-returned diagnostic
263
+ metadata. Disabled and observe policy paths can retain the compatibility
264
+ threshold.
256
265
 
257
266
  ## Modes
258
267
 
@@ -350,14 +359,21 @@ await fw.classify(text, {
350
359
  ```
351
360
 
352
361
  The SDK preserves caller metadata and adds a reserved `metadata.silmaril`
353
- namespace to every request. SDK-controlled fields are `sdk_language`,
354
- `sdk_version`, and `request_id`; batches additionally carry `input_index` for
355
- diagnostics and remain stateless. `governance` is also SDK-controlled whenever
356
- the typed governance option is supplied; it replaces any caller-provided
357
- `metadata.silmaril.governance` value. Exact `metadata.conversationId` is
358
- preserved as the backend sequence identity. No aliases are inspected. If
359
- callers provide `metadata.silmaril`, it must be an object and SDK-reserved keys
360
- are overwritten by the SDK.
362
+ namespace to every request, including each batch item. SDK-controlled fields
363
+ are `sdk_language`, `sdk_version`, and `request_id`; batches additionally
364
+ carry `input_index` for diagnostics. `governance` is also SDK-controlled
365
+ whenever the typed governance option is supplied; it replaces any
366
+ caller-provided `metadata.silmaril.governance` value. On individual
367
+ `classify()` calls, exact `metadata.conversationId` is preserved as the
368
+ backend sequence identity. Batch items also preserve per-item metadata,
369
+ including `metadata.conversationId`, but current Cascade treats each input
370
+ independently and neither reads nor updates conversation history. Giving items
371
+ the same `metadata.conversationId` does not connect them into a sequence. For
372
+ conversation-aware checks, send complete events through ordered individual
373
+ `classify()` calls with the same `metadata.conversationId`, and wait for each
374
+ call before sending the next event for that conversation. No aliases are
375
+ inspected. If callers provide `metadata.silmaril`, it must be an object and
376
+ SDK-reserved keys are overwritten by the SDK.
361
377
 
362
378
  The `governance` option on `classify()` and per-item `governance` array on
363
379
  `classifyBatch()` send typed agent/resource context. `BlockResult.governance`
@@ -370,16 +386,22 @@ responses without governance remain valid.
370
386
  - `SilmarilApiError`: thrown when the firewall API responds with a non-2xx or redirect status. Carries `status`, `statusText`, a 64 KiB-capped `body`, and any parsed malformed-input diagnostics. The default error message omits the body to keep logs clean.
371
387
  - `FirewallBlockedException`: thrown by the Vercel AI SDK and LangChain.js adapters when a malicious or governance-block decision has effective Block mode. The message distinguishes governance-policy denials from threat-score denials. Carries `score`, `threshold`, `promptText`, and optional `runId`, `hook`, `toolName`, `toolCallId`, and `result`.
372
388
 
373
- `PromptBlockedException` remains as a deprecated alias for one release.
389
+ `PromptBlockedException` remains as a deprecated alias of
390
+ `FirewallBlockedException`.
374
391
 
375
392
  All SDK exception types extend `Error` and work with `instanceof`.
376
393
 
377
394
  ## Complete events
378
395
 
379
396
  `classify()` sanitizes invalid Unicode surrogate fragments and sends the full
380
- logical event once. The backend owns token-window processing and sequence
381
- ordering. `classifyBatch()` continues to send independent stateless texts as one
382
- batch request.
397
+ logical event once. For conversation-aware checks, send those complete events
398
+ through ordered individual `classify()` calls with the same
399
+ `metadata.conversationId`, and wait for each call before sending the next
400
+ event for that conversation. The backend owns token-window processing and
401
+ sequence ordering for those individual calls. `classifyBatch()` sends
402
+ independent texts in one request: each item keeps its metadata, including
403
+ `metadata.conversationId`, but Cascade neither reads nor updates conversation
404
+ history for the batch.
383
405
 
384
406
  ## Batch Classification
385
407
 
@@ -403,9 +425,36 @@ console.log(`classified ${results.length} items`);
403
425
  ```
404
426
 
405
427
  Batch requests preserve result order and can carry per-item hooks, tool names,
406
- and metadata. Hook, tool-name, and metadata arrays must match the number of
407
- texts. Each batch carries SDK metadata per item so the backend can apply
408
- tenant-owned thresholding.
428
+ metadata, and governance. Hook, tool-name, metadata, and governance arrays must
429
+ match the number of texts. Each batch item preserves caller metadata, including
430
+ `metadata.conversationId`, and carries SDK metadata so the backend can apply
431
+ tenant-owned thresholding. Current Cascade treats each input independently and
432
+ neither reads nor updates conversation history. Giving items the same
433
+ `metadata.conversationId` does not connect them into a sequence.
434
+
435
+ For conversation-aware checks, send complete events through ordered individual
436
+ `classify()` calls with the same `metadata.conversationId`. Wait for each call
437
+ before sending the next event for that conversation:
438
+
439
+ ```ts
440
+ const conversationId = "customer-conversation-123";
441
+
442
+ const first = await fw.classify(firstEvent, {
443
+ hook: HookLabel.USER_INPUT,
444
+ metadata: { conversationId },
445
+ });
446
+
447
+ const second = await fw.classify(secondEvent, {
448
+ hook: HookLabel.TOOL_RESPONSE,
449
+ toolName: "read_file",
450
+ metadata: { conversationId },
451
+ });
452
+ ```
453
+
454
+ Batch responses must contain a `predictions` array with exactly one result per
455
+ sent input. A missing array or mismatched count raises an `Error` before
456
+ results are returned or blocking callbacks run. Retries use the original
457
+ payload snapshot, even if caller-owned inputs change while the request is in flight.
409
458
 
410
459
  ## Migration Notes
411
460
 
@@ -416,7 +465,7 @@ tenant/backend config, adds SDK reconstruction metadata, renames blocking
416
465
  exceptions to `FirewallBlockedException`, keeps optional LangChain.js types out
417
466
  of the root package declarations, adds typed CJS/ESM export conditions, supports
418
467
  Vercel AI SDK v5 and v6. The deprecated
419
- `PromptBlockedException` alias remains available for one release.
468
+ `PromptBlockedException` alias remains available.
420
469
 
421
470
  ## Vercel AI SDK Middleware
422
471
 
@@ -439,10 +488,13 @@ const { text } = await generateText({ model, prompt: "Hello" });
439
488
  console.log(text);
440
489
  ```
441
490
 
442
- Middleware scans input by default. Set `scanOutput: true` to classify model
443
- text, and `scanToolCalls: true` to classify tool-call arguments. Infrastructure
444
- errors and blocking decisions are fail-closed by default and bubble up to the
445
- caller.
491
+ Middleware scans input by default (`scanInput` defaults to true). It classifies
492
+ that message's tool-result parts as `tool_response` only when the newest prompt
493
+ message is a tool message. Otherwise it classifies the latest user message as
494
+ `user_input` and does not scan earlier tool results. Set `scanOutput: true` to
495
+ classify model text, and `scanToolCalls: true` to classify tool-call arguments
496
+ on generate results. Infrastructure errors and blocking decisions are
497
+ fail-closed by default and bubble up to the caller.
446
498
 
447
499
  When `scanOutput: true` is combined with streaming, output is classified in the
448
500
  stream's `flush` after all deltas have been emitted, so blocking is advisory:
@@ -473,11 +525,11 @@ await model.invoke("Hello");
473
525
 
474
526
  The LangChain handler is fail-open by default: infrastructure errors are logged
475
527
  and the LLM call proceeds. Set `failOpen: false` to make API errors bubble up.
476
- Blocking decisions still throw `FirewallBlockedException` unless shadow mode is
477
- enabled. `PromptBlockedException` continues to work as a deprecated alias for
478
- one release.
528
+ Blocking decisions throw `FirewallBlockedException` only when the effective mode
529
+ is Block; Shadow and Warn preserve the host flow.
530
+ `PromptBlockedException` continues to work as a deprecated alias.
479
531
  Model-start, tool-start, and tool-end hooks are enabled by default; retriever
480
- hooks remain opt-in. The LangChain run ID is sent as
532
+ and model-end (`LLM_END`) hooks remain opt-in. The LangChain run ID is sent as
481
533
  `metadata.langgraph.run_id`; every classification gets a distinct
482
534
  `metadata.silmaril.request_id`. Supply `conversationId` to the handler for
483
535
  sequence identity; it sends `metadata.conversationId`. Callback blocks throw
@@ -515,17 +567,19 @@ model, tools })` and pass its returned spec through
515
567
  `protectedCompiledSubagents`. That factory installs middleware before
516
568
  compilation. The parent constructor verifies the exact graph and Firewall
517
569
  client; it rejects arbitrary compiled runnables. Root custom middleware does
518
- not automatically reach every subagent.
570
+ not automatically reach every subagent. For custom agent construction, import
571
+ `createDeepAgentsMiddleware` from the same adapter subpath.
519
572
 
520
573
  The middleware checks input before model use, tool calls before execution,
521
574
  tool results before the next model call, and non-streamed model output before
522
575
  the graph consumes it. In Block mode, denied tool interactions become a fixed
523
576
  safe `ToolMessage` with the original call ID. The agent can choose an allowed
524
- alternative; repeated denials end with a fixed safe response. Denied model
525
- output is replaced. Shadow and Warn report decisions through `onClassify`
526
- without replacing content. Classification errors allow model and tool execution
527
- by default; set `silmaril: { failOpen: false }` to require a successful
528
- classification. Already emitted streaming text cannot be recalled.
577
+ alternative; after `maxBlockedAttempts` denials (default `3`), the middleware
578
+ returns a fixed safe final response. Denied model output is replaced. Shadow
579
+ and Warn report decisions through `onClassify` without replacing content.
580
+ Classification errors allow model and tool execution by default; set
581
+ `silmaril: { failOpen: false }` to require a successful classification. Already
582
+ emitted streaming text cannot be recalled.
529
583
 
530
584
  ## Retries
531
585
 
package/dist/index.cjs CHANGED
@@ -818,7 +818,7 @@ function sanitizeText(text) {
818
818
  }
819
819
 
820
820
  // src/firewall.ts
821
- var SDK_VERSION = "0.7.0";
821
+ var SDK_VERSION = "0.7.1";
822
822
  var DEFAULT_TIMEOUT_MS = 1e4;
823
823
  var DEFAULT_MAX_RETRIES = 5;
824
824
  var MAX_BACKOFF_SECONDS = 30;
@@ -1109,6 +1109,14 @@ var Firewall = class {
1109
1109
  })
1110
1110
  );
1111
1111
  const data = await this.postWithRetry(payload, options.signal);
1112
+ if (!Array.isArray(data.predictions)) {
1113
+ throw new Error("Firewall: response predictions must be an array");
1114
+ }
1115
+ if (data.predictions.length !== payload.texts.length) {
1116
+ throw new Error(
1117
+ `Firewall: response predictions length ${data.predictions.length} does not match submitted texts length ${payload.texts.length}`
1118
+ );
1119
+ }
1112
1120
  return data.predictions.map((p) => blockResultFromResponse(p, requestedMode));
1113
1121
  }
1114
1122
  asLangChainHandler(options = {}) {
@@ -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 result?: BlockResult;\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 if (\n params.result?.prediction !== \"MALICIOUS\" &&\n params.result?.governance?.action === \"block\"\n ) {\n return `Request blocked by Silmaril Firewall governance policy: '${truncated}'`;\n }\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 FirewallHook.TOOL_START,\n FirewallHook.TOOL_END,\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 remains inert for the user-only chat-model scan.\n // includeTool still controls the explicit tool start and end callbacks.\n const includeTool = options.includeTool ?? true;\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 requestedMode = options.mode ?? (\n options.shadowMode === undefined\n ? firewall.mode\n : options.shadowMode ? \"shadow\" : \"block\"\n );\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 metadata: {\n langgraph: { run_id: runId },\n ...(options.conversationId === undefined ? {} : { conversationId: options.conversationId }),\n },\n ...(requestedMode !== undefined ? { mode: requestedMode } : {}),\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\" || result.governance?.action === \"block\";\n const effectiveMode = requestedMode ?? result.mode ?? \"block\";\n const commonEventFields = {\n hook: hookLabel,\n ...(toolName !== undefined ? { toolName } : {}),\n runId,\n text,\n result,\n };\n fireOnClassify({\n ...commonEventFields,\n blocked,\n mode: effectiveMode,\n shadowMode: effectiveMode === \"shadow\",\n });\n if (!blocked || effectiveMode !== \"block\") {\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 (!includeTool || !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 (!includeTool || !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 FirewallMode,\n GovernanceAction,\n GovernanceResourceKind,\n GovernanceResource,\n GovernanceContext,\n GovernanceDecision,\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 FirewallMode,\n GovernanceContext,\n GovernanceDecision,\n LangChainAdapterOptions,\n LangChainFirewallHandler,\n MiddlewareOptions,\n Prediction,\n} from \"./types.js\";\n\nexport const SDK_VERSION = \"0.7.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/**\n * Largest delay a timer can represent. Both `setTimeout` and the\n * `AbortSignal.timeout` this client used before silently collapse a larger\n * delay to 1 ms, which would turn a long timeout into an immediate abort.\n */\nconst MAX_TIMEOUT_MS = 2_147_483_647;\n\ninterface SingleClassifyPayload {\n text: string;\n mode?: FirewallMode;\n hook?: string;\n tool_name?: string;\n metadata?: ClassificationMetadata;\n}\n\ninterface BatchClassifyPayload {\n texts: readonly string[];\n mode?: FirewallMode;\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 mode?: unknown;\n primary_outcome?: unknown;\n outcome_scores?: unknown;\n detector_scores?: unknown;\n detector_counts?: unknown;\n governance?: unknown;\n}\n\ninterface BatchClassifyResponse {\n predictions: readonly SingleClassifyResponse[];\n}\n\nfunction resolveMode(value: unknown, requestedMode?: FirewallMode): FirewallMode | undefined {\n let responseMode: FirewallMode | undefined;\n if (value === \"shadow\" || value === \"warn\" || value === \"block\") {\n responseMode = value;\n } else if (value !== undefined) {\n throw new Error(\"Firewall: response mode must be shadow, warn, or block\");\n }\n\n // A supplied mode is the per-request override contract. Prefer it during\n // rolling upgrades so a missing or stale response field cannot strengthen\n // enforcement beyond what the caller requested.\n return requestedMode ?? responseMode;\n}\n\nfunction legacyMode(shadowMode: boolean | undefined): FirewallMode | undefined {\n return shadowMode === undefined ? undefined : shadowMode ? \"shadow\" : \"block\";\n}\n\nfunction blockResultFromResponse(\n data: SingleClassifyResponse,\n requestedMode?: FirewallMode,\n): 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 mode?: FirewallMode;\n primaryOutcome?: NonNullable<BlockResult[\"primaryOutcome\"]>;\n outcomeScores?: NonNullable<BlockResult[\"outcomeScores\"]>;\n detectorScores?: NonNullable<BlockResult[\"detectorScores\"]>;\n detectorCounts?: NonNullable<BlockResult[\"detectorCounts\"]>;\n governance?: GovernanceDecision;\n } = {\n prediction: data.prediction,\n score: Number(data.score),\n threshold: Number(data.threshold),\n };\n const mode = resolveMode(data.mode, requestedMode);\n if (mode !== undefined) {\n result.mode = mode;\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 if (data.governance !== undefined) {\n result.governance = governanceDecisionFromResponse(data.governance);\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 governance?: GovernanceContext;\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 ...(info.governance === undefined\n ? {}\n : { governance: governanceContextToWire(info.governance) }),\n };\n return payload;\n}\n\nfunction governanceContextToWire(context: GovernanceContext): Record<string, unknown> {\n return {\n ...(context.agent === undefined ? {} : { agent: context.agent }),\n ...(context.resource === undefined\n ? {}\n : {\n resource: {\n kind: context.resource.kind,\n ...(context.resource.id === undefined ? {} : { id: context.resource.id }),\n ...(context.resource.parentId === undefined\n ? {}\n : { parent_id: context.resource.parentId }),\n },\n }),\n };\n}\n\nfunction governanceDecisionFromResponse(value: unknown): GovernanceDecision {\n if (!isRecord(value)) {\n throw new Error(\"Firewall: response governance must be an object\");\n }\n if (value.action !== \"allow\" && value.action !== \"block\") {\n throw new Error(\"Firewall: response governance action must be allow or block\");\n }\n if (typeof value.policy_version !== \"string\" || value.policy_version.length === 0) {\n throw new Error(\"Firewall: response governance policy_version must be a non-empty string\");\n }\n if (value.rule_id !== undefined && typeof value.rule_id !== \"string\") {\n throw new Error(\"Firewall: response governance rule_id must be a string when provided\");\n }\n return Object.freeze({\n action: value.action,\n ...(value.rule_id === undefined ? {} : { ruleId: value.rule_id }),\n policyVersion: value.policy_version,\n });\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\n/** Releases a response we will not read so a retry does not leak its socket. */\nasync function discardResponseBody(response: Response): Promise<void> {\n try {\n if (response.body) {\n if (!response.body.locked) {\n await response.body.cancel();\n }\n return;\n }\n await response.text();\n } catch {\n // The discarded body belongs to a response we already decided to retry.\n }\n}\n\nfunction isAbortLikeError(error: unknown): boolean {\n if (typeof error !== \"object\" || error === null) {\n return false;\n }\n const name = (error as { name?: unknown }).name;\n return name === \"AbortError\" || name === \"TimeoutError\";\n}\n\n/**\n * Reads a decoded body under an attempt signal. Native fetch can reject a body\n * read that the signal cancelled with a generic `AbortError`, which would drop\n * the caller's abort reason or the timeout reason. Only abort-caused failures\n * are rewritten; decode and transport errors are surfaced unchanged.\n */\nasync function readBodyUnderSignal<T>(read: () => Promise<T>, signal: AbortSignal): Promise<T> {\n try {\n return await read();\n } catch (error) {\n if (signal.aborted && isAbortLikeError(error)) {\n throw signal.reason;\n }\n throw error;\n }\n}\n\ninterface AttemptSignal {\n readonly signal: AbortSignal;\n dispose(): void;\n}\n\n/**\n * Combines the per-attempt timeout with an optional caller signal. The caller\n * signal is shared across sibling calls, so the listener and the timer are\n * released by `dispose()` once the attempt no longer needs them.\n */\nfunction createAttemptSignal(timeoutMs: number, callerSignal?: AbortSignal): AttemptSignal {\n const controller = new AbortController();\n const timer = setTimeout(() => {\n controller.abort(\n new DOMException(\"The operation was aborted due to timeout\", \"TimeoutError\"),\n );\n }, timeoutMs);\n const onCallerAbort = (): void => {\n controller.abort(callerSignal?.reason);\n };\n callerSignal?.addEventListener(\"abort\", onCallerAbort, { once: true });\n return {\n signal: controller.signal,\n dispose: () => {\n clearTimeout(timer);\n callerSignal?.removeEventListener(\"abort\", onCallerAbort);\n },\n };\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(signal.reason);\n return;\n }\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(signal?.reason);\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\n/**\n * Firewall client for the `/classify` API.\n *\n * Instance state is set once in the constructor and never mutated by a request,\n * so one client is safe to share across any number of concurrent `classify()`\n * and `classifyBatch()` promises within a single JavaScript runtime. Each\n * worker thread owns its own client: `Firewall` instances are not transferable\n * across `worker_threads` boundaries.\n */\nexport class Firewall {\n readonly apiKey: string;\n readonly apiUrl: string;\n readonly timeoutMs: number;\n readonly shadowMode: boolean;\n readonly mode: FirewallMode | undefined;\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 if (this.timeoutMs > MAX_TIMEOUT_MS) {\n throw new Error(\n `Firewall: timeoutMs must be at most ${MAX_TIMEOUT_MS} ms, got ${this.timeoutMs}`,\n );\n }\n this.mode = options.mode ?? legacyMode(options.shadowMode);\n this.shadowMode = this.mode === \"shadow\";\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 if (options.governance !== undefined && options.governance.length !== texts.length) {\n throw new Error(\n `Firewall: governance length ${options.governance.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 const requestedMode = options.mode ?? this.mode;\n if (requestedMode !== undefined) {\n payload.mode = requestedMode;\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 ...(options.governance?.[index] === undefined\n ? {}\n : { governance: options.governance[index] }),\n }),\n );\n const data = await this.postWithRetry<BatchClassifyResponse>(payload, options.signal);\n return data.predictions.map((p) => blockResultFromResponse(p, requestedMode));\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 callerSignal?: AbortSignal,\n maxRetries: number = DEFAULT_MAX_RETRIES,\n ): Promise<T> {\n // Cancellation outranks payload serialization, which can itself throw on\n // cyclic metadata or a throwing `toJSON`.\n callerSignal?.throwIfAborted();\n // Serialize before the first attempt so retries resend the same logical\n // event even if the caller mutates the objects it passed in.\n const body = JSON.stringify(payload);\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n callerSignal?.throwIfAborted();\n const attemptSignal = createAttemptSignal(this.timeoutMs, callerSignal);\n try {\n const response = await fetch(this.apiUrl, {\n method: \"POST\",\n headers: this.headers,\n body,\n redirect: \"error\",\n signal: attemptSignal.signal,\n });\n if (response.status !== 429 || attempt === maxRetries) {\n if (!response.ok) {\n const errorBody = await readCappedErrorBody(response);\n // The capped read swallows its own failures, so an abort during it\n // would otherwise be reported as a plain API error.\n attemptSignal.signal.throwIfAborted();\n throw new SilmarilApiError({\n status: response.status,\n statusText: response.statusText,\n body: errorBody,\n });\n }\n return await readBodyUnderSignal<T>(\n () => response.json() as Promise<T>,\n attemptSignal.signal,\n );\n }\n await discardResponseBody(response);\n } finally {\n attemptSignal.dispose();\n }\n await sleep(Math.min(2 ** attempt, MAX_BACKOFF_SECONDS) * 1000, callerSignal);\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 const requestedMode = options.mode ?? this.mode;\n if (requestedMode !== undefined) {\n payload.mode = requestedMode;\n }\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, {\n ...metadataInfo,\n ...(options.governance === undefined ? {} : { governance: options.governance }),\n });\n const data = await this.postWithRetry<SingleClassifyResponse>(payload, options.signal);\n return blockResultFromResponse(data, requestedMode);\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 requestedMode = options.mode ?? (\n options.shadowMode === undefined\n ? firewall.mode\n : options.shadowMode ? \"shadow\" : \"block\"\n );\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 {\n hook,\n ...(toolName !== undefined ? { toolName } : {}),\n ...(requestedMode !== undefined ? { mode: requestedMode } : {}),\n },\n );\n const threshold = result.threshold;\n const blocked = result.prediction === \"MALICIOUS\" || result.governance?.action === \"block\";\n const effectiveMode = requestedMode ?? result.mode ?? \"block\";\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 mode: effectiveMode,\n shadowMode: effectiveMode === \"shadow\",\n });\n if (!blocked || effectiveMode !== \"block\") {\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"]}
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 result?: BlockResult;\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 if (\n params.result?.prediction !== \"MALICIOUS\" &&\n params.result?.governance?.action === \"block\"\n ) {\n return `Request blocked by Silmaril Firewall governance policy: '${truncated}'`;\n }\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 FirewallHook.TOOL_START,\n FirewallHook.TOOL_END,\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 remains inert for the user-only chat-model scan.\n // includeTool still controls the explicit tool start and end callbacks.\n const includeTool = options.includeTool ?? true;\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 requestedMode = options.mode ?? (\n options.shadowMode === undefined\n ? firewall.mode\n : options.shadowMode ? \"shadow\" : \"block\"\n );\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 metadata: {\n langgraph: { run_id: runId },\n ...(options.conversationId === undefined ? {} : { conversationId: options.conversationId }),\n },\n ...(requestedMode !== undefined ? { mode: requestedMode } : {}),\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\" || result.governance?.action === \"block\";\n const effectiveMode = requestedMode ?? result.mode ?? \"block\";\n const commonEventFields = {\n hook: hookLabel,\n ...(toolName !== undefined ? { toolName } : {}),\n runId,\n text,\n result,\n };\n fireOnClassify({\n ...commonEventFields,\n blocked,\n mode: effectiveMode,\n shadowMode: effectiveMode === \"shadow\",\n });\n if (!blocked || effectiveMode !== \"block\") {\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 (!includeTool || !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 (!includeTool || !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 FirewallMode,\n GovernanceAction,\n GovernanceResourceKind,\n GovernanceResource,\n GovernanceContext,\n GovernanceDecision,\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 FirewallMode,\n GovernanceContext,\n GovernanceDecision,\n LangChainAdapterOptions,\n LangChainFirewallHandler,\n MiddlewareOptions,\n Prediction,\n} from \"./types.js\";\n\nexport const SDK_VERSION = \"0.7.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/**\n * Largest delay a timer can represent. Both `setTimeout` and the\n * `AbortSignal.timeout` this client used before silently collapse a larger\n * delay to 1 ms, which would turn a long timeout into an immediate abort.\n */\nconst MAX_TIMEOUT_MS = 2_147_483_647;\n\ninterface SingleClassifyPayload {\n text: string;\n mode?: FirewallMode;\n hook?: string;\n tool_name?: string;\n metadata?: ClassificationMetadata;\n}\n\ninterface BatchClassifyPayload {\n texts: readonly string[];\n mode?: FirewallMode;\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 mode?: unknown;\n primary_outcome?: unknown;\n outcome_scores?: unknown;\n detector_scores?: unknown;\n detector_counts?: unknown;\n governance?: unknown;\n}\n\ninterface BatchClassifyResponse {\n predictions: readonly SingleClassifyResponse[];\n}\n\nfunction resolveMode(value: unknown, requestedMode?: FirewallMode): FirewallMode | undefined {\n let responseMode: FirewallMode | undefined;\n if (value === \"shadow\" || value === \"warn\" || value === \"block\") {\n responseMode = value;\n } else if (value !== undefined) {\n throw new Error(\"Firewall: response mode must be shadow, warn, or block\");\n }\n\n // A supplied mode is the per-request override contract. Prefer it during\n // rolling upgrades so a missing or stale response field cannot strengthen\n // enforcement beyond what the caller requested.\n return requestedMode ?? responseMode;\n}\n\nfunction legacyMode(shadowMode: boolean | undefined): FirewallMode | undefined {\n return shadowMode === undefined ? undefined : shadowMode ? \"shadow\" : \"block\";\n}\n\nfunction blockResultFromResponse(\n data: SingleClassifyResponse,\n requestedMode?: FirewallMode,\n): 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 mode?: FirewallMode;\n primaryOutcome?: NonNullable<BlockResult[\"primaryOutcome\"]>;\n outcomeScores?: NonNullable<BlockResult[\"outcomeScores\"]>;\n detectorScores?: NonNullable<BlockResult[\"detectorScores\"]>;\n detectorCounts?: NonNullable<BlockResult[\"detectorCounts\"]>;\n governance?: GovernanceDecision;\n } = {\n prediction: data.prediction,\n score: Number(data.score),\n threshold: Number(data.threshold),\n };\n const mode = resolveMode(data.mode, requestedMode);\n if (mode !== undefined) {\n result.mode = mode;\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 if (data.governance !== undefined) {\n result.governance = governanceDecisionFromResponse(data.governance);\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 governance?: GovernanceContext;\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 ...(info.governance === undefined\n ? {}\n : { governance: governanceContextToWire(info.governance) }),\n };\n return payload;\n}\n\nfunction governanceContextToWire(context: GovernanceContext): Record<string, unknown> {\n return {\n ...(context.agent === undefined ? {} : { agent: context.agent }),\n ...(context.resource === undefined\n ? {}\n : {\n resource: {\n kind: context.resource.kind,\n ...(context.resource.id === undefined ? {} : { id: context.resource.id }),\n ...(context.resource.parentId === undefined\n ? {}\n : { parent_id: context.resource.parentId }),\n },\n }),\n };\n}\n\nfunction governanceDecisionFromResponse(value: unknown): GovernanceDecision {\n if (!isRecord(value)) {\n throw new Error(\"Firewall: response governance must be an object\");\n }\n if (value.action !== \"allow\" && value.action !== \"block\") {\n throw new Error(\"Firewall: response governance action must be allow or block\");\n }\n if (typeof value.policy_version !== \"string\" || value.policy_version.length === 0) {\n throw new Error(\"Firewall: response governance policy_version must be a non-empty string\");\n }\n if (value.rule_id !== undefined && typeof value.rule_id !== \"string\") {\n throw new Error(\"Firewall: response governance rule_id must be a string when provided\");\n }\n return Object.freeze({\n action: value.action,\n ...(value.rule_id === undefined ? {} : { ruleId: value.rule_id }),\n policyVersion: value.policy_version,\n });\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\n/** Releases a response we will not read so a retry does not leak its socket. */\nasync function discardResponseBody(response: Response): Promise<void> {\n try {\n if (response.body) {\n if (!response.body.locked) {\n await response.body.cancel();\n }\n return;\n }\n await response.text();\n } catch {\n // The discarded body belongs to a response we already decided to retry.\n }\n}\n\nfunction isAbortLikeError(error: unknown): boolean {\n if (typeof error !== \"object\" || error === null) {\n return false;\n }\n const name = (error as { name?: unknown }).name;\n return name === \"AbortError\" || name === \"TimeoutError\";\n}\n\n/**\n * Reads a decoded body under an attempt signal. Native fetch can reject a body\n * read that the signal cancelled with a generic `AbortError`, which would drop\n * the caller's abort reason or the timeout reason. Only abort-caused failures\n * are rewritten; decode and transport errors are surfaced unchanged.\n */\nasync function readBodyUnderSignal<T>(read: () => Promise<T>, signal: AbortSignal): Promise<T> {\n try {\n return await read();\n } catch (error) {\n if (signal.aborted && isAbortLikeError(error)) {\n throw signal.reason;\n }\n throw error;\n }\n}\n\ninterface AttemptSignal {\n readonly signal: AbortSignal;\n dispose(): void;\n}\n\n/**\n * Combines the per-attempt timeout with an optional caller signal. The caller\n * signal is shared across sibling calls, so the listener and the timer are\n * released by `dispose()` once the attempt no longer needs them.\n */\nfunction createAttemptSignal(timeoutMs: number, callerSignal?: AbortSignal): AttemptSignal {\n const controller = new AbortController();\n const timer = setTimeout(() => {\n controller.abort(\n new DOMException(\"The operation was aborted due to timeout\", \"TimeoutError\"),\n );\n }, timeoutMs);\n const onCallerAbort = (): void => {\n controller.abort(callerSignal?.reason);\n };\n callerSignal?.addEventListener(\"abort\", onCallerAbort, { once: true });\n return {\n signal: controller.signal,\n dispose: () => {\n clearTimeout(timer);\n callerSignal?.removeEventListener(\"abort\", onCallerAbort);\n },\n };\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(signal.reason);\n return;\n }\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(signal?.reason);\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\n/**\n * Firewall client for the `/classify` API.\n *\n * Instance state is set once in the constructor and never mutated by a request,\n * so one client is safe to share across any number of concurrent `classify()`\n * and `classifyBatch()` promises within a single JavaScript runtime. Each\n * worker thread owns its own client: `Firewall` instances are not transferable\n * across `worker_threads` boundaries.\n */\nexport class Firewall {\n readonly apiKey: string;\n readonly apiUrl: string;\n readonly timeoutMs: number;\n readonly shadowMode: boolean;\n readonly mode: FirewallMode | undefined;\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 if (this.timeoutMs > MAX_TIMEOUT_MS) {\n throw new Error(\n `Firewall: timeoutMs must be at most ${MAX_TIMEOUT_MS} ms, got ${this.timeoutMs}`,\n );\n }\n this.mode = options.mode ?? legacyMode(options.shadowMode);\n this.shadowMode = this.mode === \"shadow\";\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 if (options.governance !== undefined && options.governance.length !== texts.length) {\n throw new Error(\n `Firewall: governance length ${options.governance.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 const requestedMode = options.mode ?? this.mode;\n if (requestedMode !== undefined) {\n payload.mode = requestedMode;\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 ...(options.governance?.[index] === undefined\n ? {}\n : { governance: options.governance[index] }),\n }),\n );\n const data = await this.postWithRetry<BatchClassifyResponse>(payload, options.signal);\n if (!Array.isArray(data.predictions)) {\n throw new Error(\"Firewall: response predictions must be an array\");\n }\n if (data.predictions.length !== payload.texts.length) {\n throw new Error(\n `Firewall: response predictions length ${data.predictions.length} does not match submitted texts length ${payload.texts.length}`,\n );\n }\n return data.predictions.map((p) => blockResultFromResponse(p, requestedMode));\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 callerSignal?: AbortSignal,\n maxRetries: number = DEFAULT_MAX_RETRIES,\n ): Promise<T> {\n // Cancellation outranks payload serialization, which can itself throw on\n // cyclic metadata or a throwing `toJSON`.\n callerSignal?.throwIfAborted();\n // Serialize before the first attempt so retries resend the same logical\n // event even if the caller mutates the objects it passed in.\n const body = JSON.stringify(payload);\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n callerSignal?.throwIfAborted();\n const attemptSignal = createAttemptSignal(this.timeoutMs, callerSignal);\n try {\n const response = await fetch(this.apiUrl, {\n method: \"POST\",\n headers: this.headers,\n body,\n redirect: \"error\",\n signal: attemptSignal.signal,\n });\n if (response.status !== 429 || attempt === maxRetries) {\n if (!response.ok) {\n const errorBody = await readCappedErrorBody(response);\n // The capped read swallows its own failures, so an abort during it\n // would otherwise be reported as a plain API error.\n attemptSignal.signal.throwIfAborted();\n throw new SilmarilApiError({\n status: response.status,\n statusText: response.statusText,\n body: errorBody,\n });\n }\n return await readBodyUnderSignal<T>(\n () => response.json() as Promise<T>,\n attemptSignal.signal,\n );\n }\n await discardResponseBody(response);\n } finally {\n attemptSignal.dispose();\n }\n await sleep(Math.min(2 ** attempt, MAX_BACKOFF_SECONDS) * 1000, callerSignal);\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 const requestedMode = options.mode ?? this.mode;\n if (requestedMode !== undefined) {\n payload.mode = requestedMode;\n }\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, {\n ...metadataInfo,\n ...(options.governance === undefined ? {} : { governance: options.governance }),\n });\n const data = await this.postWithRetry<SingleClassifyResponse>(payload, options.signal);\n return blockResultFromResponse(data, requestedMode);\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 requestedMode = options.mode ?? (\n options.shadowMode === undefined\n ? firewall.mode\n : options.shadowMode ? \"shadow\" : \"block\"\n );\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 {\n hook,\n ...(toolName !== undefined ? { toolName } : {}),\n ...(requestedMode !== undefined ? { mode: requestedMode } : {}),\n },\n );\n const threshold = result.threshold;\n const blocked = result.prediction === \"MALICIOUS\" || result.governance?.action === \"block\";\n const effectiveMode = requestedMode ?? result.mode ?? \"block\";\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 mode: effectiveMode,\n shadowMode: effectiveMode === \"shadow\",\n });\n if (!blocked || effectiveMode !== \"block\") {\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.js CHANGED
@@ -766,7 +766,7 @@ function sanitizeText(text) {
766
766
  }
767
767
 
768
768
  // src/firewall.ts
769
- var SDK_VERSION = "0.7.0";
769
+ var SDK_VERSION = "0.7.1";
770
770
  var DEFAULT_TIMEOUT_MS = 1e4;
771
771
  var DEFAULT_MAX_RETRIES = 5;
772
772
  var MAX_BACKOFF_SECONDS = 30;
@@ -1057,6 +1057,14 @@ var Firewall = class {
1057
1057
  })
1058
1058
  );
1059
1059
  const data = await this.postWithRetry(payload, options.signal);
1060
+ if (!Array.isArray(data.predictions)) {
1061
+ throw new Error("Firewall: response predictions must be an array");
1062
+ }
1063
+ if (data.predictions.length !== payload.texts.length) {
1064
+ throw new Error(
1065
+ `Firewall: response predictions length ${data.predictions.length} does not match submitted texts length ${payload.texts.length}`
1066
+ );
1067
+ }
1060
1068
  return data.predictions.map((p) => blockResultFromResponse(p, requestedMode));
1061
1069
  }
1062
1070
  asLangChainHandler(options = {}) {
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 result?: BlockResult;\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 if (\n params.result?.prediction !== \"MALICIOUS\" &&\n params.result?.governance?.action === \"block\"\n ) {\n return `Request blocked by Silmaril Firewall governance policy: '${truncated}'`;\n }\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 FirewallHook.TOOL_START,\n FirewallHook.TOOL_END,\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 remains inert for the user-only chat-model scan.\n // includeTool still controls the explicit tool start and end callbacks.\n const includeTool = options.includeTool ?? true;\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 requestedMode = options.mode ?? (\n options.shadowMode === undefined\n ? firewall.mode\n : options.shadowMode ? \"shadow\" : \"block\"\n );\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 metadata: {\n langgraph: { run_id: runId },\n ...(options.conversationId === undefined ? {} : { conversationId: options.conversationId }),\n },\n ...(requestedMode !== undefined ? { mode: requestedMode } : {}),\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\" || result.governance?.action === \"block\";\n const effectiveMode = requestedMode ?? result.mode ?? \"block\";\n const commonEventFields = {\n hook: hookLabel,\n ...(toolName !== undefined ? { toolName } : {}),\n runId,\n text,\n result,\n };\n fireOnClassify({\n ...commonEventFields,\n blocked,\n mode: effectiveMode,\n shadowMode: effectiveMode === \"shadow\",\n });\n if (!blocked || effectiveMode !== \"block\") {\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 (!includeTool || !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 (!includeTool || !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 FirewallMode,\n GovernanceContext,\n GovernanceDecision,\n LangChainAdapterOptions,\n LangChainFirewallHandler,\n MiddlewareOptions,\n Prediction,\n} from \"./types.js\";\n\nexport const SDK_VERSION = \"0.7.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/**\n * Largest delay a timer can represent. Both `setTimeout` and the\n * `AbortSignal.timeout` this client used before silently collapse a larger\n * delay to 1 ms, which would turn a long timeout into an immediate abort.\n */\nconst MAX_TIMEOUT_MS = 2_147_483_647;\n\ninterface SingleClassifyPayload {\n text: string;\n mode?: FirewallMode;\n hook?: string;\n tool_name?: string;\n metadata?: ClassificationMetadata;\n}\n\ninterface BatchClassifyPayload {\n texts: readonly string[];\n mode?: FirewallMode;\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 mode?: unknown;\n primary_outcome?: unknown;\n outcome_scores?: unknown;\n detector_scores?: unknown;\n detector_counts?: unknown;\n governance?: unknown;\n}\n\ninterface BatchClassifyResponse {\n predictions: readonly SingleClassifyResponse[];\n}\n\nfunction resolveMode(value: unknown, requestedMode?: FirewallMode): FirewallMode | undefined {\n let responseMode: FirewallMode | undefined;\n if (value === \"shadow\" || value === \"warn\" || value === \"block\") {\n responseMode = value;\n } else if (value !== undefined) {\n throw new Error(\"Firewall: response mode must be shadow, warn, or block\");\n }\n\n // A supplied mode is the per-request override contract. Prefer it during\n // rolling upgrades so a missing or stale response field cannot strengthen\n // enforcement beyond what the caller requested.\n return requestedMode ?? responseMode;\n}\n\nfunction legacyMode(shadowMode: boolean | undefined): FirewallMode | undefined {\n return shadowMode === undefined ? undefined : shadowMode ? \"shadow\" : \"block\";\n}\n\nfunction blockResultFromResponse(\n data: SingleClassifyResponse,\n requestedMode?: FirewallMode,\n): 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 mode?: FirewallMode;\n primaryOutcome?: NonNullable<BlockResult[\"primaryOutcome\"]>;\n outcomeScores?: NonNullable<BlockResult[\"outcomeScores\"]>;\n detectorScores?: NonNullable<BlockResult[\"detectorScores\"]>;\n detectorCounts?: NonNullable<BlockResult[\"detectorCounts\"]>;\n governance?: GovernanceDecision;\n } = {\n prediction: data.prediction,\n score: Number(data.score),\n threshold: Number(data.threshold),\n };\n const mode = resolveMode(data.mode, requestedMode);\n if (mode !== undefined) {\n result.mode = mode;\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 if (data.governance !== undefined) {\n result.governance = governanceDecisionFromResponse(data.governance);\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 governance?: GovernanceContext;\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 ...(info.governance === undefined\n ? {}\n : { governance: governanceContextToWire(info.governance) }),\n };\n return payload;\n}\n\nfunction governanceContextToWire(context: GovernanceContext): Record<string, unknown> {\n return {\n ...(context.agent === undefined ? {} : { agent: context.agent }),\n ...(context.resource === undefined\n ? {}\n : {\n resource: {\n kind: context.resource.kind,\n ...(context.resource.id === undefined ? {} : { id: context.resource.id }),\n ...(context.resource.parentId === undefined\n ? {}\n : { parent_id: context.resource.parentId }),\n },\n }),\n };\n}\n\nfunction governanceDecisionFromResponse(value: unknown): GovernanceDecision {\n if (!isRecord(value)) {\n throw new Error(\"Firewall: response governance must be an object\");\n }\n if (value.action !== \"allow\" && value.action !== \"block\") {\n throw new Error(\"Firewall: response governance action must be allow or block\");\n }\n if (typeof value.policy_version !== \"string\" || value.policy_version.length === 0) {\n throw new Error(\"Firewall: response governance policy_version must be a non-empty string\");\n }\n if (value.rule_id !== undefined && typeof value.rule_id !== \"string\") {\n throw new Error(\"Firewall: response governance rule_id must be a string when provided\");\n }\n return Object.freeze({\n action: value.action,\n ...(value.rule_id === undefined ? {} : { ruleId: value.rule_id }),\n policyVersion: value.policy_version,\n });\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\n/** Releases a response we will not read so a retry does not leak its socket. */\nasync function discardResponseBody(response: Response): Promise<void> {\n try {\n if (response.body) {\n if (!response.body.locked) {\n await response.body.cancel();\n }\n return;\n }\n await response.text();\n } catch {\n // The discarded body belongs to a response we already decided to retry.\n }\n}\n\nfunction isAbortLikeError(error: unknown): boolean {\n if (typeof error !== \"object\" || error === null) {\n return false;\n }\n const name = (error as { name?: unknown }).name;\n return name === \"AbortError\" || name === \"TimeoutError\";\n}\n\n/**\n * Reads a decoded body under an attempt signal. Native fetch can reject a body\n * read that the signal cancelled with a generic `AbortError`, which would drop\n * the caller's abort reason or the timeout reason. Only abort-caused failures\n * are rewritten; decode and transport errors are surfaced unchanged.\n */\nasync function readBodyUnderSignal<T>(read: () => Promise<T>, signal: AbortSignal): Promise<T> {\n try {\n return await read();\n } catch (error) {\n if (signal.aborted && isAbortLikeError(error)) {\n throw signal.reason;\n }\n throw error;\n }\n}\n\ninterface AttemptSignal {\n readonly signal: AbortSignal;\n dispose(): void;\n}\n\n/**\n * Combines the per-attempt timeout with an optional caller signal. The caller\n * signal is shared across sibling calls, so the listener and the timer are\n * released by `dispose()` once the attempt no longer needs them.\n */\nfunction createAttemptSignal(timeoutMs: number, callerSignal?: AbortSignal): AttemptSignal {\n const controller = new AbortController();\n const timer = setTimeout(() => {\n controller.abort(\n new DOMException(\"The operation was aborted due to timeout\", \"TimeoutError\"),\n );\n }, timeoutMs);\n const onCallerAbort = (): void => {\n controller.abort(callerSignal?.reason);\n };\n callerSignal?.addEventListener(\"abort\", onCallerAbort, { once: true });\n return {\n signal: controller.signal,\n dispose: () => {\n clearTimeout(timer);\n callerSignal?.removeEventListener(\"abort\", onCallerAbort);\n },\n };\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(signal.reason);\n return;\n }\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(signal?.reason);\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\n/**\n * Firewall client for the `/classify` API.\n *\n * Instance state is set once in the constructor and never mutated by a request,\n * so one client is safe to share across any number of concurrent `classify()`\n * and `classifyBatch()` promises within a single JavaScript runtime. Each\n * worker thread owns its own client: `Firewall` instances are not transferable\n * across `worker_threads` boundaries.\n */\nexport class Firewall {\n readonly apiKey: string;\n readonly apiUrl: string;\n readonly timeoutMs: number;\n readonly shadowMode: boolean;\n readonly mode: FirewallMode | undefined;\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 if (this.timeoutMs > MAX_TIMEOUT_MS) {\n throw new Error(\n `Firewall: timeoutMs must be at most ${MAX_TIMEOUT_MS} ms, got ${this.timeoutMs}`,\n );\n }\n this.mode = options.mode ?? legacyMode(options.shadowMode);\n this.shadowMode = this.mode === \"shadow\";\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 if (options.governance !== undefined && options.governance.length !== texts.length) {\n throw new Error(\n `Firewall: governance length ${options.governance.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 const requestedMode = options.mode ?? this.mode;\n if (requestedMode !== undefined) {\n payload.mode = requestedMode;\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 ...(options.governance?.[index] === undefined\n ? {}\n : { governance: options.governance[index] }),\n }),\n );\n const data = await this.postWithRetry<BatchClassifyResponse>(payload, options.signal);\n return data.predictions.map((p) => blockResultFromResponse(p, requestedMode));\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 callerSignal?: AbortSignal,\n maxRetries: number = DEFAULT_MAX_RETRIES,\n ): Promise<T> {\n // Cancellation outranks payload serialization, which can itself throw on\n // cyclic metadata or a throwing `toJSON`.\n callerSignal?.throwIfAborted();\n // Serialize before the first attempt so retries resend the same logical\n // event even if the caller mutates the objects it passed in.\n const body = JSON.stringify(payload);\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n callerSignal?.throwIfAborted();\n const attemptSignal = createAttemptSignal(this.timeoutMs, callerSignal);\n try {\n const response = await fetch(this.apiUrl, {\n method: \"POST\",\n headers: this.headers,\n body,\n redirect: \"error\",\n signal: attemptSignal.signal,\n });\n if (response.status !== 429 || attempt === maxRetries) {\n if (!response.ok) {\n const errorBody = await readCappedErrorBody(response);\n // The capped read swallows its own failures, so an abort during it\n // would otherwise be reported as a plain API error.\n attemptSignal.signal.throwIfAborted();\n throw new SilmarilApiError({\n status: response.status,\n statusText: response.statusText,\n body: errorBody,\n });\n }\n return await readBodyUnderSignal<T>(\n () => response.json() as Promise<T>,\n attemptSignal.signal,\n );\n }\n await discardResponseBody(response);\n } finally {\n attemptSignal.dispose();\n }\n await sleep(Math.min(2 ** attempt, MAX_BACKOFF_SECONDS) * 1000, callerSignal);\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 const requestedMode = options.mode ?? this.mode;\n if (requestedMode !== undefined) {\n payload.mode = requestedMode;\n }\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, {\n ...metadataInfo,\n ...(options.governance === undefined ? {} : { governance: options.governance }),\n });\n const data = await this.postWithRetry<SingleClassifyResponse>(payload, options.signal);\n return blockResultFromResponse(data, requestedMode);\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 requestedMode = options.mode ?? (\n options.shadowMode === undefined\n ? firewall.mode\n : options.shadowMode ? \"shadow\" : \"block\"\n );\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 {\n hook,\n ...(toolName !== undefined ? { toolName } : {}),\n ...(requestedMode !== undefined ? { mode: requestedMode } : {}),\n },\n );\n const threshold = result.threshold;\n const blocked = result.prediction === \"MALICIOUS\" || result.governance?.action === \"block\";\n const effectiveMode = requestedMode ?? result.mode ?? \"block\";\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 mode: effectiveMode,\n shadowMode: effectiveMode === \"shadow\",\n });\n if (!blocked || effectiveMode !== \"block\") {\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 FirewallMode,\n GovernanceAction,\n GovernanceResourceKind,\n GovernanceResource,\n GovernanceContext,\n GovernanceDecision,\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 result?: BlockResult;\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 if (\n params.result?.prediction !== \"MALICIOUS\" &&\n params.result?.governance?.action === \"block\"\n ) {\n return `Request blocked by Silmaril Firewall governance policy: '${truncated}'`;\n }\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 FirewallHook.TOOL_START,\n FirewallHook.TOOL_END,\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 remains inert for the user-only chat-model scan.\n // includeTool still controls the explicit tool start and end callbacks.\n const includeTool = options.includeTool ?? true;\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 requestedMode = options.mode ?? (\n options.shadowMode === undefined\n ? firewall.mode\n : options.shadowMode ? \"shadow\" : \"block\"\n );\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 metadata: {\n langgraph: { run_id: runId },\n ...(options.conversationId === undefined ? {} : { conversationId: options.conversationId }),\n },\n ...(requestedMode !== undefined ? { mode: requestedMode } : {}),\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\" || result.governance?.action === \"block\";\n const effectiveMode = requestedMode ?? result.mode ?? \"block\";\n const commonEventFields = {\n hook: hookLabel,\n ...(toolName !== undefined ? { toolName } : {}),\n runId,\n text,\n result,\n };\n fireOnClassify({\n ...commonEventFields,\n blocked,\n mode: effectiveMode,\n shadowMode: effectiveMode === \"shadow\",\n });\n if (!blocked || effectiveMode !== \"block\") {\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 (!includeTool || !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 (!includeTool || !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 FirewallMode,\n GovernanceContext,\n GovernanceDecision,\n LangChainAdapterOptions,\n LangChainFirewallHandler,\n MiddlewareOptions,\n Prediction,\n} from \"./types.js\";\n\nexport const SDK_VERSION = \"0.7.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/**\n * Largest delay a timer can represent. Both `setTimeout` and the\n * `AbortSignal.timeout` this client used before silently collapse a larger\n * delay to 1 ms, which would turn a long timeout into an immediate abort.\n */\nconst MAX_TIMEOUT_MS = 2_147_483_647;\n\ninterface SingleClassifyPayload {\n text: string;\n mode?: FirewallMode;\n hook?: string;\n tool_name?: string;\n metadata?: ClassificationMetadata;\n}\n\ninterface BatchClassifyPayload {\n texts: readonly string[];\n mode?: FirewallMode;\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 mode?: unknown;\n primary_outcome?: unknown;\n outcome_scores?: unknown;\n detector_scores?: unknown;\n detector_counts?: unknown;\n governance?: unknown;\n}\n\ninterface BatchClassifyResponse {\n predictions: readonly SingleClassifyResponse[];\n}\n\nfunction resolveMode(value: unknown, requestedMode?: FirewallMode): FirewallMode | undefined {\n let responseMode: FirewallMode | undefined;\n if (value === \"shadow\" || value === \"warn\" || value === \"block\") {\n responseMode = value;\n } else if (value !== undefined) {\n throw new Error(\"Firewall: response mode must be shadow, warn, or block\");\n }\n\n // A supplied mode is the per-request override contract. Prefer it during\n // rolling upgrades so a missing or stale response field cannot strengthen\n // enforcement beyond what the caller requested.\n return requestedMode ?? responseMode;\n}\n\nfunction legacyMode(shadowMode: boolean | undefined): FirewallMode | undefined {\n return shadowMode === undefined ? undefined : shadowMode ? \"shadow\" : \"block\";\n}\n\nfunction blockResultFromResponse(\n data: SingleClassifyResponse,\n requestedMode?: FirewallMode,\n): 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 mode?: FirewallMode;\n primaryOutcome?: NonNullable<BlockResult[\"primaryOutcome\"]>;\n outcomeScores?: NonNullable<BlockResult[\"outcomeScores\"]>;\n detectorScores?: NonNullable<BlockResult[\"detectorScores\"]>;\n detectorCounts?: NonNullable<BlockResult[\"detectorCounts\"]>;\n governance?: GovernanceDecision;\n } = {\n prediction: data.prediction,\n score: Number(data.score),\n threshold: Number(data.threshold),\n };\n const mode = resolveMode(data.mode, requestedMode);\n if (mode !== undefined) {\n result.mode = mode;\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 if (data.governance !== undefined) {\n result.governance = governanceDecisionFromResponse(data.governance);\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 governance?: GovernanceContext;\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 ...(info.governance === undefined\n ? {}\n : { governance: governanceContextToWire(info.governance) }),\n };\n return payload;\n}\n\nfunction governanceContextToWire(context: GovernanceContext): Record<string, unknown> {\n return {\n ...(context.agent === undefined ? {} : { agent: context.agent }),\n ...(context.resource === undefined\n ? {}\n : {\n resource: {\n kind: context.resource.kind,\n ...(context.resource.id === undefined ? {} : { id: context.resource.id }),\n ...(context.resource.parentId === undefined\n ? {}\n : { parent_id: context.resource.parentId }),\n },\n }),\n };\n}\n\nfunction governanceDecisionFromResponse(value: unknown): GovernanceDecision {\n if (!isRecord(value)) {\n throw new Error(\"Firewall: response governance must be an object\");\n }\n if (value.action !== \"allow\" && value.action !== \"block\") {\n throw new Error(\"Firewall: response governance action must be allow or block\");\n }\n if (typeof value.policy_version !== \"string\" || value.policy_version.length === 0) {\n throw new Error(\"Firewall: response governance policy_version must be a non-empty string\");\n }\n if (value.rule_id !== undefined && typeof value.rule_id !== \"string\") {\n throw new Error(\"Firewall: response governance rule_id must be a string when provided\");\n }\n return Object.freeze({\n action: value.action,\n ...(value.rule_id === undefined ? {} : { ruleId: value.rule_id }),\n policyVersion: value.policy_version,\n });\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\n/** Releases a response we will not read so a retry does not leak its socket. */\nasync function discardResponseBody(response: Response): Promise<void> {\n try {\n if (response.body) {\n if (!response.body.locked) {\n await response.body.cancel();\n }\n return;\n }\n await response.text();\n } catch {\n // The discarded body belongs to a response we already decided to retry.\n }\n}\n\nfunction isAbortLikeError(error: unknown): boolean {\n if (typeof error !== \"object\" || error === null) {\n return false;\n }\n const name = (error as { name?: unknown }).name;\n return name === \"AbortError\" || name === \"TimeoutError\";\n}\n\n/**\n * Reads a decoded body under an attempt signal. Native fetch can reject a body\n * read that the signal cancelled with a generic `AbortError`, which would drop\n * the caller's abort reason or the timeout reason. Only abort-caused failures\n * are rewritten; decode and transport errors are surfaced unchanged.\n */\nasync function readBodyUnderSignal<T>(read: () => Promise<T>, signal: AbortSignal): Promise<T> {\n try {\n return await read();\n } catch (error) {\n if (signal.aborted && isAbortLikeError(error)) {\n throw signal.reason;\n }\n throw error;\n }\n}\n\ninterface AttemptSignal {\n readonly signal: AbortSignal;\n dispose(): void;\n}\n\n/**\n * Combines the per-attempt timeout with an optional caller signal. The caller\n * signal is shared across sibling calls, so the listener and the timer are\n * released by `dispose()` once the attempt no longer needs them.\n */\nfunction createAttemptSignal(timeoutMs: number, callerSignal?: AbortSignal): AttemptSignal {\n const controller = new AbortController();\n const timer = setTimeout(() => {\n controller.abort(\n new DOMException(\"The operation was aborted due to timeout\", \"TimeoutError\"),\n );\n }, timeoutMs);\n const onCallerAbort = (): void => {\n controller.abort(callerSignal?.reason);\n };\n callerSignal?.addEventListener(\"abort\", onCallerAbort, { once: true });\n return {\n signal: controller.signal,\n dispose: () => {\n clearTimeout(timer);\n callerSignal?.removeEventListener(\"abort\", onCallerAbort);\n },\n };\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(signal.reason);\n return;\n }\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(signal?.reason);\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\n/**\n * Firewall client for the `/classify` API.\n *\n * Instance state is set once in the constructor and never mutated by a request,\n * so one client is safe to share across any number of concurrent `classify()`\n * and `classifyBatch()` promises within a single JavaScript runtime. Each\n * worker thread owns its own client: `Firewall` instances are not transferable\n * across `worker_threads` boundaries.\n */\nexport class Firewall {\n readonly apiKey: string;\n readonly apiUrl: string;\n readonly timeoutMs: number;\n readonly shadowMode: boolean;\n readonly mode: FirewallMode | undefined;\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 if (this.timeoutMs > MAX_TIMEOUT_MS) {\n throw new Error(\n `Firewall: timeoutMs must be at most ${MAX_TIMEOUT_MS} ms, got ${this.timeoutMs}`,\n );\n }\n this.mode = options.mode ?? legacyMode(options.shadowMode);\n this.shadowMode = this.mode === \"shadow\";\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 if (options.governance !== undefined && options.governance.length !== texts.length) {\n throw new Error(\n `Firewall: governance length ${options.governance.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 const requestedMode = options.mode ?? this.mode;\n if (requestedMode !== undefined) {\n payload.mode = requestedMode;\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 ...(options.governance?.[index] === undefined\n ? {}\n : { governance: options.governance[index] }),\n }),\n );\n const data = await this.postWithRetry<BatchClassifyResponse>(payload, options.signal);\n if (!Array.isArray(data.predictions)) {\n throw new Error(\"Firewall: response predictions must be an array\");\n }\n if (data.predictions.length !== payload.texts.length) {\n throw new Error(\n `Firewall: response predictions length ${data.predictions.length} does not match submitted texts length ${payload.texts.length}`,\n );\n }\n return data.predictions.map((p) => blockResultFromResponse(p, requestedMode));\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 callerSignal?: AbortSignal,\n maxRetries: number = DEFAULT_MAX_RETRIES,\n ): Promise<T> {\n // Cancellation outranks payload serialization, which can itself throw on\n // cyclic metadata or a throwing `toJSON`.\n callerSignal?.throwIfAborted();\n // Serialize before the first attempt so retries resend the same logical\n // event even if the caller mutates the objects it passed in.\n const body = JSON.stringify(payload);\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n callerSignal?.throwIfAborted();\n const attemptSignal = createAttemptSignal(this.timeoutMs, callerSignal);\n try {\n const response = await fetch(this.apiUrl, {\n method: \"POST\",\n headers: this.headers,\n body,\n redirect: \"error\",\n signal: attemptSignal.signal,\n });\n if (response.status !== 429 || attempt === maxRetries) {\n if (!response.ok) {\n const errorBody = await readCappedErrorBody(response);\n // The capped read swallows its own failures, so an abort during it\n // would otherwise be reported as a plain API error.\n attemptSignal.signal.throwIfAborted();\n throw new SilmarilApiError({\n status: response.status,\n statusText: response.statusText,\n body: errorBody,\n });\n }\n return await readBodyUnderSignal<T>(\n () => response.json() as Promise<T>,\n attemptSignal.signal,\n );\n }\n await discardResponseBody(response);\n } finally {\n attemptSignal.dispose();\n }\n await sleep(Math.min(2 ** attempt, MAX_BACKOFF_SECONDS) * 1000, callerSignal);\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 const requestedMode = options.mode ?? this.mode;\n if (requestedMode !== undefined) {\n payload.mode = requestedMode;\n }\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, {\n ...metadataInfo,\n ...(options.governance === undefined ? {} : { governance: options.governance }),\n });\n const data = await this.postWithRetry<SingleClassifyResponse>(payload, options.signal);\n return blockResultFromResponse(data, requestedMode);\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 requestedMode = options.mode ?? (\n options.shadowMode === undefined\n ? firewall.mode\n : options.shadowMode ? \"shadow\" : \"block\"\n );\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 {\n hook,\n ...(toolName !== undefined ? { toolName } : {}),\n ...(requestedMode !== undefined ? { mode: requestedMode } : {}),\n },\n );\n const threshold = result.threshold;\n const blocked = result.prediction === \"MALICIOUS\" || result.governance?.action === \"block\";\n const effectiveMode = requestedMode ?? result.mode ?? \"block\";\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 mode: effectiveMode,\n shadowMode: effectiveMode === \"shadow\",\n });\n if (!blocked || effectiveMode !== \"block\") {\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 FirewallMode,\n GovernanceAction,\n GovernanceResourceKind,\n GovernanceResource,\n GovernanceContext,\n GovernanceDecision,\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.7.0",
3
+ "version": "0.7.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.",