@silmaril-security/sdk 0.4.2 → 0.5.0
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 +12 -0
- package/README.md +18 -27
- package/dist/adapters/langchain.cjs +1 -1
- package/dist/adapters/langchain.cjs.map +1 -1
- package/dist/adapters/langchain.d.cts +1 -1
- package/dist/adapters/langchain.d.ts +1 -1
- package/dist/adapters/langchain.js +1 -1
- package/dist/adapters/langchain.js.map +1 -1
- package/dist/adapters/vercel.cjs +1 -1
- package/dist/adapters/vercel.cjs.map +1 -1
- package/dist/adapters/vercel.d.cts +1 -1
- package/dist/adapters/vercel.d.ts +1 -1
- package/dist/adapters/vercel.js +1 -1
- package/dist/adapters/vercel.js.map +1 -1
- package/dist/{firewall-DfZCCDU6.d.cts → firewall-DNC9vSbq.d.cts} +2 -5
- package/dist/{firewall-DfZCCDU6.d.ts → firewall-DNC9vSbq.d.ts} +2 -5
- package/dist/index.cjs +45 -157
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -12
- package/dist/index.d.ts +3 -12
- package/dist/index.js +44 -147
- package/dist/index.js.map +1 -1
- package/package.json +7 -3
package/dist/index.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
-
var __esm = (fn, res) => function __init() {
|
|
4
|
-
|
|
3
|
+
var __esm = (fn, res, err) => function __init() {
|
|
4
|
+
if (err) throw err[0];
|
|
5
|
+
try {
|
|
6
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
7
|
+
} catch (e) {
|
|
8
|
+
throw err = [e], e;
|
|
9
|
+
}
|
|
5
10
|
};
|
|
6
11
|
var __export = (target, all) => {
|
|
7
12
|
for (var name in all)
|
|
@@ -273,7 +278,7 @@ async function createLangChainHandler(firewall, options = {}) {
|
|
|
273
278
|
return;
|
|
274
279
|
}
|
|
275
280
|
const threshold = result.threshold;
|
|
276
|
-
const blocked = result.
|
|
281
|
+
const blocked = result.prediction === "MALICIOUS";
|
|
277
282
|
const commonEventFields = {
|
|
278
283
|
hook: hookLabel,
|
|
279
284
|
...toolName !== void 0 ? { toolName } : {},
|
|
@@ -492,7 +497,7 @@ function createMiddleware(firewall, options = {}) {
|
|
|
492
497
|
toolName !== void 0 ? { hook, toolName } : { hook }
|
|
493
498
|
);
|
|
494
499
|
const threshold = result.threshold;
|
|
495
|
-
const blocked = result.
|
|
500
|
+
const blocked = result.prediction === "MALICIOUS";
|
|
496
501
|
const commonEventFields = {
|
|
497
502
|
hook,
|
|
498
503
|
...toolName !== void 0 ? { toolName } : {},
|
|
@@ -618,78 +623,6 @@ function createMiddleware(firewall, options = {}) {
|
|
|
618
623
|
};
|
|
619
624
|
}
|
|
620
625
|
|
|
621
|
-
// src/chunking.ts
|
|
622
|
-
var CHARS_PER_TOKEN = 4;
|
|
623
|
-
var MAX_INPUT_TOKENS = 81920;
|
|
624
|
-
var CHUNK_WINDOW = 400;
|
|
625
|
-
var CHUNK_OVERLAP = 64;
|
|
626
|
-
var MAX_INPUT_CHARS = MAX_INPUT_TOKENS * CHARS_PER_TOKEN;
|
|
627
|
-
var CHUNK_WINDOW_CHARS = CHUNK_WINDOW * CHARS_PER_TOKEN;
|
|
628
|
-
var CHUNK_OVERLAP_CHARS = CHUNK_OVERLAP * CHARS_PER_TOKEN;
|
|
629
|
-
var CHUNK_STRIDE_CHARS = CHUNK_WINDOW_CHARS - CHUNK_OVERLAP_CHARS;
|
|
630
|
-
function isHighSurrogate(code) {
|
|
631
|
-
return code >= 55296 && code <= 56319;
|
|
632
|
-
}
|
|
633
|
-
function isLowSurrogate(code) {
|
|
634
|
-
return code >= 56320 && code <= 57343;
|
|
635
|
-
}
|
|
636
|
-
function sanitizeText(text) {
|
|
637
|
-
let out = "";
|
|
638
|
-
for (let i = 0; i < text.length; i++) {
|
|
639
|
-
const code = text.charCodeAt(i);
|
|
640
|
-
if (isHighSurrogate(code)) {
|
|
641
|
-
if (i + 1 < text.length && isLowSurrogate(text.charCodeAt(i + 1))) {
|
|
642
|
-
out += text[i];
|
|
643
|
-
out += text[i + 1];
|
|
644
|
-
i++;
|
|
645
|
-
}
|
|
646
|
-
continue;
|
|
647
|
-
}
|
|
648
|
-
if (isLowSurrogate(code)) {
|
|
649
|
-
continue;
|
|
650
|
-
}
|
|
651
|
-
out += text[i];
|
|
652
|
-
}
|
|
653
|
-
return out;
|
|
654
|
-
}
|
|
655
|
-
function safeChunkStart(text, start) {
|
|
656
|
-
if (start > 0 && start < text.length && isLowSurrogate(text.charCodeAt(start)) && isHighSurrogate(text.charCodeAt(start - 1))) {
|
|
657
|
-
return start + 1;
|
|
658
|
-
}
|
|
659
|
-
return start;
|
|
660
|
-
}
|
|
661
|
-
function safeChunkEnd(text, end) {
|
|
662
|
-
if (end > 0 && end < text.length && isHighSurrogate(text.charCodeAt(end - 1)) && isLowSurrogate(text.charCodeAt(end))) {
|
|
663
|
-
return end - 1;
|
|
664
|
-
}
|
|
665
|
-
return end;
|
|
666
|
-
}
|
|
667
|
-
function chunkText(text) {
|
|
668
|
-
text = sanitizeText(text);
|
|
669
|
-
const n = text.length;
|
|
670
|
-
if (n > MAX_INPUT_CHARS) {
|
|
671
|
-
throw new Error(
|
|
672
|
-
`Input has ~${Math.floor(n / CHARS_PER_TOKEN)} tokens (${n} chars); max is ${MAX_INPUT_TOKENS} tokens (${MAX_INPUT_CHARS} chars)`
|
|
673
|
-
);
|
|
674
|
-
}
|
|
675
|
-
if (n <= CHUNK_WINDOW_CHARS) {
|
|
676
|
-
return [text];
|
|
677
|
-
}
|
|
678
|
-
const chunks = [];
|
|
679
|
-
for (let start = 0; start < n; start += CHUNK_STRIDE_CHARS) {
|
|
680
|
-
const safeStart = safeChunkStart(text, start);
|
|
681
|
-
if (safeStart >= n) {
|
|
682
|
-
break;
|
|
683
|
-
}
|
|
684
|
-
const end = safeChunkEnd(text, safeStart + CHUNK_WINDOW_CHARS);
|
|
685
|
-
chunks.push(text.slice(safeStart, end));
|
|
686
|
-
if (end >= n) {
|
|
687
|
-
break;
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
return chunks;
|
|
691
|
-
}
|
|
692
|
-
|
|
693
626
|
// src/firewall.ts
|
|
694
627
|
init_exceptions();
|
|
695
628
|
|
|
@@ -763,14 +696,42 @@ function normalizeHarmfulOutcomeMap(values, fieldName) {
|
|
|
763
696
|
return Object.freeze(out);
|
|
764
697
|
}
|
|
765
698
|
|
|
699
|
+
// src/sanitization.ts
|
|
700
|
+
function isHighSurrogate(code) {
|
|
701
|
+
return code >= 55296 && code <= 56319;
|
|
702
|
+
}
|
|
703
|
+
function isLowSurrogate(code) {
|
|
704
|
+
return code >= 56320 && code <= 57343;
|
|
705
|
+
}
|
|
706
|
+
function sanitizeText(text) {
|
|
707
|
+
let out = "";
|
|
708
|
+
for (let i = 0; i < text.length; i++) {
|
|
709
|
+
const code = text.charCodeAt(i);
|
|
710
|
+
if (isHighSurrogate(code)) {
|
|
711
|
+
if (i + 1 < text.length && isLowSurrogate(text.charCodeAt(i + 1))) {
|
|
712
|
+
out += text[i];
|
|
713
|
+
out += text[i + 1];
|
|
714
|
+
i++;
|
|
715
|
+
}
|
|
716
|
+
continue;
|
|
717
|
+
}
|
|
718
|
+
if (!isLowSurrogate(code)) {
|
|
719
|
+
out += text[i];
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
return out;
|
|
723
|
+
}
|
|
724
|
+
|
|
766
725
|
// src/firewall.ts
|
|
767
|
-
var SDK_VERSION = "0.
|
|
726
|
+
var SDK_VERSION = "0.5.0";
|
|
768
727
|
var DEFAULT_TIMEOUT_MS = 1e4;
|
|
769
|
-
var DEFAULT_CHUNK_CONCURRENCY = 8;
|
|
770
728
|
var DEFAULT_MAX_RETRIES = 5;
|
|
771
729
|
var MAX_BACKOFF_SECONDS = 30;
|
|
772
730
|
var MAX_ERROR_BODY_BYTES = 1 << 16;
|
|
773
731
|
function blockResultFromResponse(data) {
|
|
732
|
+
if (data.prediction !== "BENIGN" && data.prediction !== "MALICIOUS") {
|
|
733
|
+
throw new Error("Firewall: response prediction must be BENIGN or MALICIOUS");
|
|
734
|
+
}
|
|
774
735
|
const result = {
|
|
775
736
|
prediction: data.prediction,
|
|
776
737
|
score: Number(data.score),
|
|
@@ -813,9 +774,7 @@ function withSdkMetadata(metadata, info) {
|
|
|
813
774
|
sdk_language: "typescript",
|
|
814
775
|
sdk_version: SDK_VERSION,
|
|
815
776
|
request_id: info.requestId,
|
|
816
|
-
input_index: info.inputIndex
|
|
817
|
-
chunk_index: info.chunkIndex,
|
|
818
|
-
chunk_count: info.chunkCount
|
|
777
|
+
...info.inputIndex === void 0 ? {} : { input_index: info.inputIndex }
|
|
819
778
|
};
|
|
820
779
|
return payload;
|
|
821
780
|
}
|
|
@@ -856,36 +815,10 @@ async function readCappedErrorBody(response) {
|
|
|
856
815
|
}
|
|
857
816
|
return new TextDecoder().decode(body);
|
|
858
817
|
}
|
|
859
|
-
async function mapWithConcurrency(items, concurrency, task) {
|
|
860
|
-
const results = new Array(items.length);
|
|
861
|
-
let nextIndex = 0;
|
|
862
|
-
let firstError;
|
|
863
|
-
const workerCount = Math.min(concurrency, items.length);
|
|
864
|
-
async function worker() {
|
|
865
|
-
for (; ; ) {
|
|
866
|
-
const index = nextIndex;
|
|
867
|
-
nextIndex += 1;
|
|
868
|
-
if (index >= items.length) {
|
|
869
|
-
return;
|
|
870
|
-
}
|
|
871
|
-
try {
|
|
872
|
-
results[index] = await task(items[index], index);
|
|
873
|
-
} catch (err) {
|
|
874
|
-
firstError ??= err;
|
|
875
|
-
}
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
await Promise.all(Array.from({ length: workerCount }, () => worker()));
|
|
879
|
-
if (firstError !== void 0) {
|
|
880
|
-
throw firstError;
|
|
881
|
-
}
|
|
882
|
-
return results;
|
|
883
|
-
}
|
|
884
818
|
var Firewall = class {
|
|
885
819
|
apiKey;
|
|
886
820
|
apiUrl;
|
|
887
821
|
timeoutMs;
|
|
888
|
-
chunkConcurrency;
|
|
889
822
|
shadowMode;
|
|
890
823
|
headers;
|
|
891
824
|
constructor(options) {
|
|
@@ -901,12 +834,6 @@ var Firewall = class {
|
|
|
901
834
|
if (typeof this.timeoutMs !== "number" || !Number.isFinite(this.timeoutMs) || this.timeoutMs < 0) {
|
|
902
835
|
throw new Error(`Firewall: timeoutMs must be a finite non-negative number, got ${this.timeoutMs}`);
|
|
903
836
|
}
|
|
904
|
-
this.chunkConcurrency = options.chunkConcurrency ?? DEFAULT_CHUNK_CONCURRENCY;
|
|
905
|
-
if (!Number.isInteger(this.chunkConcurrency) || this.chunkConcurrency < 1) {
|
|
906
|
-
throw new Error(
|
|
907
|
-
`Firewall: chunkConcurrency must be an integer >= 1, got ${this.chunkConcurrency}`
|
|
908
|
-
);
|
|
909
|
-
}
|
|
910
837
|
this.shadowMode = options.shadowMode ?? false;
|
|
911
838
|
this.headers = Object.freeze({
|
|
912
839
|
"x-api-key": this.apiKey,
|
|
@@ -914,27 +841,8 @@ var Firewall = class {
|
|
|
914
841
|
});
|
|
915
842
|
}
|
|
916
843
|
async classify(text, options = {}) {
|
|
917
|
-
const chunks = chunkText(text);
|
|
918
844
|
const requestId = options.requestId ?? randomUUID();
|
|
919
|
-
|
|
920
|
-
return this.classifySingleChunk(chunks[0], options, {
|
|
921
|
-
requestId,
|
|
922
|
-
inputIndex: 0,
|
|
923
|
-
chunkIndex: 0,
|
|
924
|
-
chunkCount: 1
|
|
925
|
-
});
|
|
926
|
-
}
|
|
927
|
-
const results = await mapWithConcurrency(
|
|
928
|
-
chunks,
|
|
929
|
-
this.chunkConcurrency,
|
|
930
|
-
(chunk, index) => this.classifySingleChunk(chunk, options, {
|
|
931
|
-
requestId,
|
|
932
|
-
inputIndex: 0,
|
|
933
|
-
chunkIndex: index,
|
|
934
|
-
chunkCount: chunks.length
|
|
935
|
-
})
|
|
936
|
-
);
|
|
937
|
-
return results.reduce((best, r) => r.score > best.score ? r : best);
|
|
845
|
+
return this.classifySingle(sanitizeText(text), options, { requestId });
|
|
938
846
|
}
|
|
939
847
|
async classifyBatch(texts, options = {}) {
|
|
940
848
|
if (texts.length === 0) {
|
|
@@ -968,9 +876,7 @@ var Firewall = class {
|
|
|
968
876
|
payload.metadata = texts.map(
|
|
969
877
|
(_, index) => withSdkMetadata(options.metadata?.[index], {
|
|
970
878
|
requestId,
|
|
971
|
-
inputIndex: index
|
|
972
|
-
chunkIndex: 0,
|
|
973
|
-
chunkCount: 1
|
|
879
|
+
inputIndex: index
|
|
974
880
|
})
|
|
975
881
|
);
|
|
976
882
|
const data = await this.postWithRetry(payload);
|
|
@@ -1009,7 +915,7 @@ var Firewall = class {
|
|
|
1009
915
|
}
|
|
1010
916
|
throw new Error("Firewall: exhausted retries (unreachable)");
|
|
1011
917
|
}
|
|
1012
|
-
async
|
|
918
|
+
async classifySingle(text, options, metadataInfo) {
|
|
1013
919
|
const payload = { text };
|
|
1014
920
|
if (options.hook !== void 0) {
|
|
1015
921
|
payload.hook = options.hook;
|
|
@@ -1028,11 +934,6 @@ init_exceptions();
|
|
|
1028
934
|
init_hooks();
|
|
1029
935
|
export {
|
|
1030
936
|
ALL_HOOKS,
|
|
1031
|
-
CHUNK_OVERLAP,
|
|
1032
|
-
CHUNK_OVERLAP_CHARS,
|
|
1033
|
-
CHUNK_WINDOW,
|
|
1034
|
-
CHUNK_WINDOW_CHARS,
|
|
1035
|
-
DEFAULT_CHUNK_CONCURRENCY,
|
|
1036
937
|
DEFAULT_HOOKS,
|
|
1037
938
|
DEFAULT_TIMEOUT_MS,
|
|
1038
939
|
FIREWALL_HOOK_TO_LABEL,
|
|
@@ -1042,15 +943,12 @@ export {
|
|
|
1042
943
|
HARMFUL_OUTCOMES,
|
|
1043
944
|
HookLabel,
|
|
1044
945
|
INPUT_HOOKS,
|
|
1045
|
-
MAX_INPUT_CHARS,
|
|
1046
|
-
MAX_INPUT_TOKENS,
|
|
1047
946
|
OUTCOME_DESCRIPTIONS,
|
|
1048
947
|
OUTPUT_HOOKS,
|
|
1049
948
|
Outcome,
|
|
1050
949
|
PRIMARY_OUTCOMES,
|
|
1051
950
|
PromptBlockedException,
|
|
1052
951
|
SilmarilApiError,
|
|
1053
|
-
chunkText,
|
|
1054
952
|
isHarmfulOutcome,
|
|
1055
953
|
isPrimaryOutcome,
|
|
1056
954
|
normalizeHarmfulOutcome,
|
|
@@ -1058,7 +956,6 @@ export {
|
|
|
1058
956
|
normalizePrimaryOutcome,
|
|
1059
957
|
prependHook,
|
|
1060
958
|
prependToolName,
|
|
1061
|
-
resolveHooks
|
|
1062
|
-
sanitizeText
|
|
959
|
+
resolveHooks
|
|
1063
960
|
};
|
|
1064
961
|
//# sourceMappingURL=index.js.map
|
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/chunking.ts","../src/outcomes.ts","../src/index.ts"],"sourcesContent":["// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nimport type { HookLabel } from \"./hooks.js\";\nimport type { BlockResult } from \"./types.js\";\n\nconst MAX_PROMPT_DISPLAY_LEN = 100;\n\nexport interface MalformedInputDetails {\n field?: string;\n inputIndex?: number;\n charOffset?: number;\n malformedToken?: string;\n codePoint?: string;\n reason?: string;\n}\n\nexport class FirewallBlockedException extends Error {\n readonly score: number;\n readonly threshold: number;\n readonly promptText: string;\n readonly runId: string | undefined;\n readonly hook: HookLabel | undefined;\n readonly toolName: string | undefined;\n readonly toolCallId: string | undefined;\n readonly result: BlockResult | undefined;\n\n constructor(params: {\n score: number;\n threshold: number;\n promptText: string;\n runId?: string;\n hook?: HookLabel;\n toolName?: string;\n toolCallId?: string;\n result?: BlockResult;\n }) {\n super(FirewallBlockedException.formatMessage(params));\n this.name = \"FirewallBlockedException\";\n this.score = params.score;\n this.threshold = params.threshold;\n this.promptText = params.promptText;\n this.runId = params.runId;\n this.hook = params.hook;\n this.toolName = params.toolName;\n this.toolCallId = params.toolCallId;\n this.result = params.result;\n Object.setPrototypeOf(this, FirewallBlockedException.prototype);\n }\n\n private static formatMessage(params: {\n score: number;\n threshold: number;\n promptText: string;\n }): string {\n const truncated =\n params.promptText.length > MAX_PROMPT_DISPLAY_LEN\n ? `${params.promptText.slice(0, MAX_PROMPT_DISPLAY_LEN)}...`\n : params.promptText;\n return (\n `Request blocked by Silmaril Firewall ` +\n `(score=${params.score.toFixed(4)}, threshold=${params.threshold.toFixed(4)}): ` +\n `'${truncated}'`\n );\n }\n}\n\n/** @deprecated Use FirewallBlockedException instead. */\nexport const PromptBlockedException = FirewallBlockedException;\n/** @deprecated Use FirewallBlockedException instead. */\nexport type PromptBlockedException = FirewallBlockedException;\n\nexport class SilmarilApiError extends Error {\n readonly status: number;\n readonly statusText: string;\n readonly body: string;\n readonly details: MalformedInputDetails | undefined;\n readonly error: string | undefined;\n readonly apiMessage: string | undefined;\n\n constructor(params: {\n status: number;\n statusText: string;\n body: string;\n details?: MalformedInputDetails;\n error?: string;\n apiMessage?: string;\n }) {\n const statusText = params.statusText ? ` ${params.statusText}` : \"\";\n super(`Silmaril API error ${params.status}${statusText}`);\n this.name = \"SilmarilApiError\";\n this.status = params.status;\n this.statusText = params.statusText;\n this.body = params.body;\n const parsed = parseErrorBody(params.body);\n this.details = params.details ?? parsed.details;\n this.error = params.error ?? parsed.error;\n this.apiMessage = params.apiMessage ?? parsed.apiMessage;\n Object.setPrototypeOf(this, SilmarilApiError.prototype);\n }\n}\n\nfunction parseErrorBody(body: string): {\n details: MalformedInputDetails | undefined;\n error: string | undefined;\n apiMessage: string | undefined;\n} {\n try {\n const parsed = JSON.parse(body) as unknown;\n if (!parsed || typeof parsed !== \"object\") {\n return { details: undefined, error: undefined, apiMessage: undefined };\n }\n const data = parsed as Record<string, unknown>;\n return {\n details:\n data.details && typeof data.details === \"object\"\n ? (data.details as MalformedInputDetails)\n : undefined,\n error: typeof data.error === \"string\" ? data.error : undefined,\n apiMessage: typeof data.message === \"string\" ? data.message : undefined,\n };\n } catch {\n return { details: undefined, error: undefined, apiMessage: undefined };\n }\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nexport const HookLabel = {\n USER_INPUT: \"user_input\",\n SYSTEM_PROMPT: \"system_prompt\",\n TOOL_CALL: \"tool_call\",\n TOOL_RESPONSE: \"tool_response\",\n LLM_OUTPUT: \"llm_output\",\n UNKNOWN: \"unknown\",\n} as const;\n\nexport type HookLabel = (typeof HookLabel)[keyof typeof HookLabel];\n\nexport const FirewallHook = {\n LLM_START: \"on_llm_start\",\n CHAT_MODEL_START: \"on_chat_model_start\",\n TOOL_START: \"on_tool_start\",\n RETRIEVER_START: \"on_retriever_start\",\n LLM_END: \"on_llm_end\",\n TOOL_END: \"on_tool_end\",\n RETRIEVER_END: \"on_retriever_end\",\n} as const;\n\nexport type FirewallHook = (typeof FirewallHook)[keyof typeof FirewallHook];\n\nexport const DEFAULT_HOOKS: ReadonlySet<FirewallHook> = new Set<FirewallHook>([\n FirewallHook.LLM_START,\n FirewallHook.CHAT_MODEL_START,\n]);\n\nexport const INPUT_HOOKS: ReadonlySet<FirewallHook> = new Set<FirewallHook>([\n FirewallHook.LLM_START,\n FirewallHook.CHAT_MODEL_START,\n FirewallHook.TOOL_START,\n FirewallHook.RETRIEVER_START,\n]);\n\nexport const OUTPUT_HOOKS: ReadonlySet<FirewallHook> = new Set<FirewallHook>([\n FirewallHook.LLM_END,\n FirewallHook.TOOL_END,\n FirewallHook.RETRIEVER_END,\n]);\n\nexport const ALL_HOOKS: ReadonlySet<FirewallHook> = new Set<FirewallHook>([\n ...INPUT_HOOKS,\n ...OUTPUT_HOOKS,\n]);\n\nexport const FIREWALL_HOOK_TO_LABEL: Readonly<Record<FirewallHook, HookLabel>> = {\n [FirewallHook.CHAT_MODEL_START]: HookLabel.USER_INPUT,\n [FirewallHook.LLM_START]: HookLabel.USER_INPUT,\n [FirewallHook.TOOL_START]: HookLabel.TOOL_CALL,\n [FirewallHook.TOOL_END]: HookLabel.TOOL_RESPONSE,\n [FirewallHook.RETRIEVER_START]: HookLabel.TOOL_CALL,\n [FirewallHook.RETRIEVER_END]: HookLabel.TOOL_RESPONSE,\n [FirewallHook.LLM_END]: HookLabel.LLM_OUTPUT,\n};\n\nconst FIREWALL_HOOK_VALUES: ReadonlySet<string> = new Set(Object.values(FirewallHook));\n\nexport function resolveHooks(\n hooks: Iterable<FirewallHook | string> | undefined,\n): ReadonlySet<FirewallHook> {\n if (hooks === undefined) {\n return DEFAULT_HOOKS;\n }\n const resolved = new Set<FirewallHook>();\n for (const h of hooks) {\n if (!FIREWALL_HOOK_VALUES.has(h)) {\n throw new Error(`Invalid FirewallHook value: ${String(h)}`);\n }\n resolved.add(h as FirewallHook);\n }\n return resolved;\n}\n\nexport function prependHook(text: string, hook: HookLabel | string | undefined | null): string {\n if (hook === undefined || hook === null) {\n return text;\n }\n if (hook === HookLabel.UNKNOWN) {\n return text;\n }\n return `[HOOK:${hook}] ${text}`;\n}\n\nexport function prependToolName(text: string, toolName: string | undefined | null): string {\n if (toolName === undefined || toolName === null) {\n return text;\n }\n return `[TOOL:${toolName}] ${text}`;\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nconst SKIP_ROLES: ReadonlySet<string> = new Set([\"ai\", \"assistant\"]);\nconst SYSTEM_ROLES: ReadonlySet<string> = new Set([\"system\"]);\nconst TOOL_ROLES: ReadonlySet<string> = new Set([\"tool\", \"function\"]);\n\ntype MessageContent = string | ReadonlyArray<string | { type?: string; text?: string }>;\n\ninterface DucktypedMessage {\n role?: string;\n type?: string;\n content?: MessageContent;\n}\n\ninterface DucktypedGeneration {\n text?: string;\n}\n\ninterface DucktypedLLMResult {\n generations?: ReadonlyArray<ReadonlyArray<DucktypedGeneration>>;\n}\n\ninterface DucktypedDocument {\n pageContent?: string;\n}\n\nfunction extractContentText(content: MessageContent | undefined): string {\n if (typeof content === \"string\") {\n return content;\n }\n if (Array.isArray(content)) {\n const parts: string[] = [];\n for (const block of content) {\n if (typeof block === \"string\") {\n parts.push(block);\n } else if (block && typeof block === \"object\" && block.type === \"text\") {\n parts.push(block.text ?? \"\");\n }\n }\n return parts.join(\" \");\n }\n return \"\";\n}\n\nfunction getRole(message: DucktypedMessage): string {\n if (message.role !== undefined) {\n return message.role.toLowerCase();\n }\n if (typeof message.type === \"string\") {\n return message.type.toLowerCase();\n }\n return \"\";\n}\n\nexport function extractTextFromMessages(\n messages: ReadonlyArray<DucktypedMessage>,\n options: { includeSystem?: boolean; includeTool?: boolean } = {},\n): string {\n const includeSystem = options.includeSystem ?? true;\n const includeTool = options.includeTool ?? true;\n const parts: string[] = [];\n for (const message of messages) {\n const role = getRole(message);\n if (SKIP_ROLES.has(role)) {\n continue;\n }\n if (!includeSystem && SYSTEM_ROLES.has(role)) {\n continue;\n }\n if (!includeTool && TOOL_ROLES.has(role)) {\n continue;\n }\n const text = extractContentText(message.content);\n const stripped = text.trim();\n if (stripped) {\n parts.push(stripped);\n }\n }\n return parts.join(\"\\n\");\n}\n\nexport function extractTextFromPrompts(prompts: readonly string[]): string {\n return prompts\n .map((p) => p.trim())\n .filter((p) => p.length > 0)\n .join(\"\\n\");\n}\n\nexport function extractTextFromToolInput(inputStr: string): string {\n return inputStr.trim();\n}\n\nexport function extractTextFromLLMResult(response: DucktypedLLMResult): string {\n const parts: string[] = [];\n for (const genList of response.generations ?? []) {\n for (const gen of genList) {\n const text = (gen.text ?? \"\").trim();\n if (text) {\n parts.push(text);\n }\n }\n }\n return parts.join(\"\\n\");\n}\n\nexport function extractTextFromDocuments(documents: ReadonlyArray<DucktypedDocument>): string {\n const parts: string[] = [];\n for (const doc of documents) {\n const text = (doc.pageContent ?? \"\").trim();\n if (text) {\n parts.push(text);\n }\n }\n return parts.join(\"\\n\");\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nimport type { BaseCallbackHandler } from \"@langchain/core/callbacks/base\";\n\nimport type { Firewall } from \"../firewall.js\";\nimport { FirewallBlockedException } from \"../exceptions.js\";\nimport {\n FIREWALL_HOOK_TO_LABEL,\n FirewallHook,\n HookLabel,\n resolveHooks,\n} from \"../hooks.js\";\nimport type { BlockResult, ClassifyEvent, LangChainAdapterOptions } from \"../types.js\";\nimport {\n extractTextFromDocuments,\n extractTextFromLLMResult,\n extractTextFromPrompts,\n extractTextFromToolInput,\n} from \"../utils/extract.js\";\n\nconst USER_ROLES: ReadonlySet<string> = new Set([\"human\", \"user\"]);\n\ninterface LangChainDucktypedMessage {\n role?: string;\n type?: string;\n content?: string | ReadonlyArray<string | { type?: string; text?: string }>;\n}\n\nfunction getMessageRole(message: LangChainDucktypedMessage): string {\n if (typeof message.role === \"string\") {\n return message.role.toLowerCase();\n }\n if (typeof message.type === \"string\") {\n return message.type.toLowerCase();\n }\n return \"\";\n}\n\nfunction extractMessageText(content: LangChainDucktypedMessage[\"content\"]): string {\n if (content === undefined) {\n return \"\";\n }\n if (typeof content === \"string\") {\n return content;\n }\n const parts: string[] = [];\n for (const block of content) {\n if (typeof block === \"string\") {\n parts.push(block);\n } else if (block && block.type === \"text\") {\n parts.push(block.text ?? \"\");\n }\n }\n return parts.join(\" \");\n}\n\nfunction findLastUserMessage(\n messages: ReadonlyArray<LangChainDucktypedMessage>,\n): LangChainDucktypedMessage | undefined {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]!;\n if (USER_ROLES.has(getMessageRole(msg))) {\n return msg;\n }\n }\n return undefined;\n}\n\nexport async function createLangChainHandler(\n firewall: Firewall,\n options: LangChainAdapterOptions = {},\n): Promise<BaseCallbackHandler> {\n const { BaseCallbackHandler } = await import(\"@langchain/core/callbacks/base\");\n\n const enabledHooks = resolveHooks(options.hooks);\n // includeSystem / includeTool are retained in LangChainAdapterOptions for\n // backwards compat but are inert under the per-message hook-routing algorithm:\n // handleChatModelStart only scans the last user-role message; system and tool\n // messages are either trusted or already classified by their own hooks.\n const failOpen = options.failOpen ?? true;\n const logger =\n options.logger ??\n ((message: string, error: unknown): void => {\n // eslint-disable-next-line no-console\n console.warn(`silmaril.firewall: ${message}`, error);\n });\n const shadowMode = options.shadowMode ?? firewall.shadowMode;\n const onClassify = options.onClassify;\n\n const fireOnClassify = (event: ClassifyEvent): void => {\n if (!onClassify) {\n return;\n }\n try {\n onClassify(event);\n } catch (err) {\n logger(\"onClassify callback threw\", err);\n }\n };\n\n const classify = async (\n text: string,\n hookLabel: HookLabel,\n runId: string,\n toolName?: string,\n ): Promise<void> => {\n let result: BlockResult;\n try {\n result = await firewall.classify(text, {\n hook: hookLabel,\n ...(toolName !== undefined ? { toolName } : {}),\n });\n } catch (err) {\n if (!failOpen) {\n throw err;\n }\n logger(\"classification failed, allowing prompt through\", err);\n return;\n }\n const threshold = result.threshold;\n const blocked = result.score >= threshold;\n const commonEventFields = {\n hook: hookLabel,\n ...(toolName !== undefined ? { toolName } : {}),\n runId,\n text,\n result,\n };\n fireOnClassify({\n ...commonEventFields,\n blocked,\n shadowMode,\n });\n if (!blocked || shadowMode) {\n return;\n }\n\n throw new FirewallBlockedException({\n score: result.score,\n threshold,\n promptText: text,\n runId,\n hook: hookLabel,\n ...(toolName !== undefined ? { toolName } : {}),\n result,\n });\n };\n\n class SilmarilFirewallHandler extends BaseCallbackHandler {\n override name = \"silmaril_firewall_handler\";\n override raiseError = true;\n override awaitHandlers = true;\n\n override async handleChatModelStart(\n _llm: unknown,\n messages: unknown,\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.CHAT_MODEL_START)) {\n return;\n }\n const batches = messages as ReadonlyArray<ReadonlyArray<LangChainDucktypedMessage>>;\n const flat: LangChainDucktypedMessage[] = [];\n for (const batch of batches) {\n for (const m of batch) {\n flat.push(m);\n }\n }\n const lastUser = findLastUserMessage(flat);\n if (!lastUser) {\n return;\n }\n const text = extractMessageText(lastUser.content).trim();\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.CHAT_MODEL_START], runId);\n }\n\n override async handleLLMStart(\n _llm: unknown,\n prompts: string[],\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.LLM_START)) {\n return;\n }\n const text = extractTextFromPrompts(prompts);\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.LLM_START], runId);\n }\n\n override async handleToolStart(\n tool: { name?: string } | undefined,\n inputStr: string,\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.TOOL_START)) {\n return;\n }\n const text = extractTextFromToolInput(inputStr);\n if (!text) {\n return;\n }\n const toolName = tool?.name;\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.TOOL_START], runId, toolName);\n }\n\n override async handleRetrieverStart(\n _retriever: unknown,\n query: string,\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.RETRIEVER_START)) {\n return;\n }\n const text = query.trim();\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.RETRIEVER_START], runId);\n }\n\n override async handleLLMEnd(output: unknown, runId: string): Promise<void> {\n if (!enabledHooks.has(FirewallHook.LLM_END)) {\n return;\n }\n const text = extractTextFromLLMResult(output as { generations?: ReadonlyArray<ReadonlyArray<{ text?: string }>> });\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.LLM_END], runId);\n }\n\n override async handleToolEnd(\n output: unknown,\n runId: string,\n _parentRunId?: string,\n _tags?: string[],\n _kwargs?: { name?: string },\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.TOOL_END)) {\n return;\n }\n const text = String(output).trim();\n if (!text) {\n return;\n }\n const toolName = _kwargs?.name;\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.TOOL_END], runId, toolName);\n }\n\n override async handleRetrieverEnd(\n documents: ReadonlyArray<{ pageContent?: string }>,\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.RETRIEVER_END)) {\n return;\n }\n const text = extractTextFromDocuments(documents);\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.RETRIEVER_END], runId);\n }\n }\n\n return new SilmarilFirewallHandler();\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nimport { randomUUID } from \"node:crypto\";\n\nimport { createMiddleware, type FirewallMiddleware } from \"./adapters/vercel.js\";\nimport { chunkText, sanitizeText } from \"./chunking.js\";\nimport { SilmarilApiError } from \"./exceptions.js\";\nimport { normalizeHarmfulOutcomeMap, normalizePrimaryOutcome } from \"./outcomes.js\";\nimport type {\n BlockResult,\n ClassifyBatchOptions,\n ClassifyOptions,\n ClassificationMetadata,\n FirewallOptions,\n LangChainAdapterOptions,\n LangChainFirewallHandler,\n MiddlewareOptions,\n Prediction,\n} from \"./types.js\";\n\nexport const BASE_THRESHOLD = 0.5;\nexport const TARGET_SEQUENCE_FPR = 0.01;\nexport const MAX_ADAPTIVE_THRESHOLD = 0.9;\nexport const SDK_VERSION = \"0.4.2\";\nexport const DEFAULT_TIMEOUT_MS = 10_000;\nexport const DEFAULT_CHUNK_CONCURRENCY = 8;\nconst DEFAULT_MAX_RETRIES = 5;\nconst MAX_BACKOFF_SECONDS = 30;\nconst MAX_ERROR_BODY_BYTES = 1 << 16;\n\ninterface SingleClassifyPayload {\n text: string;\n hook?: string;\n tool_name?: string;\n metadata?: ClassificationMetadata;\n}\n\ninterface BatchClassifyPayload {\n texts: readonly string[];\n hooks?: readonly string[];\n tool_names?: readonly (string | null)[];\n metadata?: readonly (ClassificationMetadata | null)[];\n}\n\ninterface SingleClassifyResponse {\n prediction: Prediction;\n score: number;\n threshold: number;\n primary_outcome?: unknown;\n outcome_scores?: unknown;\n detector_scores?: unknown;\n detector_counts?: unknown;\n}\n\ninterface BatchClassifyResponse {\n predictions: readonly SingleClassifyResponse[];\n}\n\n/** @deprecated Thresholds are tenant-owned by the Firewall backend. */\nexport function adaptiveThreshold(scoringOpportunityCount: number): number {\n if (!Number.isInteger(scoringOpportunityCount) || scoringOpportunityCount < 1) {\n throw new Error(\n `Firewall: scoringOpportunityCount must be an integer >= 1, got ${scoringOpportunityCount}`,\n );\n }\n if (scoringOpportunityCount === 1) {\n return BASE_THRESHOLD;\n }\n const targetChunkFpr = 1 - Math.pow(1 - TARGET_SEQUENCE_FPR, 1 / scoringOpportunityCount);\n const oddsRatio = TARGET_SEQUENCE_FPR / targetChunkFpr;\n const rawThreshold = oddsRatio / (1 + oddsRatio);\n return Math.min(rawThreshold, MAX_ADAPTIVE_THRESHOLD);\n}\n\nfunction blockResultFromResponse(data: SingleClassifyResponse): BlockResult {\n const result: {\n prediction: Prediction;\n score: number;\n threshold: number;\n primaryOutcome?: NonNullable<BlockResult[\"primaryOutcome\"]>;\n outcomeScores?: NonNullable<BlockResult[\"outcomeScores\"]>;\n detectorScores?: NonNullable<BlockResult[\"detectorScores\"]>;\n detectorCounts?: NonNullable<BlockResult[\"detectorCounts\"]>;\n } = {\n prediction: data.prediction,\n score: Number(data.score),\n threshold: Number(data.threshold),\n };\n if (data.primary_outcome !== undefined) {\n result.primaryOutcome = normalizePrimaryOutcome(data.primary_outcome);\n }\n if (data.outcome_scores !== undefined) {\n const outcomeScores = normalizeHarmfulOutcomeMap(data.outcome_scores, \"outcome_scores\");\n if (outcomeScores !== undefined) {\n result.outcomeScores = outcomeScores;\n }\n }\n if (data.detector_scores !== undefined) {\n const detectorScores = normalizeHarmfulOutcomeMap(data.detector_scores, \"detector_scores\");\n if (detectorScores !== undefined) {\n result.detectorScores = detectorScores;\n }\n }\n if (data.detector_counts !== undefined) {\n const detectorCounts = normalizeHarmfulOutcomeMap(data.detector_counts, \"detector_counts\");\n if (detectorCounts !== undefined) {\n result.detectorCounts = detectorCounts;\n }\n }\n return Object.freeze(result);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction withSdkMetadata(\n metadata: ClassificationMetadata | undefined,\n info: {\n requestId: string;\n inputIndex: number;\n chunkIndex: number;\n chunkCount: number;\n },\n): ClassificationMetadata {\n const payload: Record<string, unknown> = { ...(metadata ?? {}) };\n const existing = payload.silmaril;\n if (existing !== undefined && !isRecord(existing)) {\n throw new Error(\"Firewall: metadata.silmaril must be an object when provided\");\n }\n payload.silmaril = {\n ...(isRecord(existing) ? existing : {}),\n sdk_language: \"typescript\",\n sdk_version: SDK_VERSION,\n request_id: info.requestId,\n input_index: info.inputIndex,\n chunk_index: info.chunkIndex,\n chunk_count: info.chunkCount,\n };\n return payload;\n}\n\nasync function readCappedErrorBody(response: Response): Promise<string> {\n if (!response.body) {\n return response.text().then((body) => body.slice(0, MAX_ERROR_BODY_BYTES)).catch(() => \"\");\n }\n\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let remaining = MAX_ERROR_BODY_BYTES;\n try {\n while (remaining > 0) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n if (!value) {\n continue;\n }\n const chunk = value.byteLength > remaining ? value.slice(0, remaining) : value;\n chunks.push(chunk);\n remaining -= chunk.byteLength;\n if (chunk.byteLength < value.byteLength) {\n break;\n }\n }\n } catch {\n return \"\";\n } finally {\n await reader.cancel().catch(() => undefined);\n }\n\n const total = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);\n const body = new Uint8Array(total);\n let offset = 0;\n for (const chunk of chunks) {\n body.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return new TextDecoder().decode(body);\n}\n\nasync function mapWithConcurrency<T, R>(\n items: readonly T[],\n concurrency: number,\n task: (item: T, index: number) => Promise<R>,\n): Promise<R[]> {\n const results = new Array<R>(items.length);\n let nextIndex = 0;\n let firstError: unknown;\n const workerCount = Math.min(concurrency, items.length);\n\n async function worker(): Promise<void> {\n for (;;) {\n const index = nextIndex;\n nextIndex += 1;\n if (index >= items.length) {\n return;\n }\n try {\n results[index] = await task(items[index]!, index);\n } catch (err) {\n firstError ??= err;\n }\n }\n }\n\n await Promise.all(Array.from({ length: workerCount }, () => worker()));\n if (firstError !== undefined) {\n throw firstError;\n }\n return results;\n}\n\nexport class Firewall {\n readonly apiKey: string;\n readonly apiUrl: string;\n readonly timeoutMs: number;\n readonly chunkConcurrency: number;\n readonly shadowMode: boolean;\n\n private readonly headers: Readonly<Record<string, string>>;\n\n constructor(options: FirewallOptions) {\n if (!options.apiKey) {\n throw new Error(\"Firewall: apiKey is required\");\n }\n if (!options.apiUrl) {\n throw new Error(\"Firewall: apiUrl is required\");\n }\n this.apiKey = options.apiKey;\n this.apiUrl = options.apiUrl;\n this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n if (typeof this.timeoutMs !== \"number\" || !Number.isFinite(this.timeoutMs) || this.timeoutMs < 0) {\n throw new Error(`Firewall: timeoutMs must be a finite non-negative number, got ${this.timeoutMs}`);\n }\n this.chunkConcurrency = options.chunkConcurrency ?? DEFAULT_CHUNK_CONCURRENCY;\n if (!Number.isInteger(this.chunkConcurrency) || this.chunkConcurrency < 1) {\n throw new Error(\n `Firewall: chunkConcurrency must be an integer >= 1, got ${this.chunkConcurrency}`,\n );\n }\n this.shadowMode = options.shadowMode ?? false;\n this.headers = Object.freeze({\n \"x-api-key\": this.apiKey,\n \"content-type\": \"application/json\",\n });\n }\n\n async classify(text: string, options: ClassifyOptions = {}): Promise<BlockResult> {\n const chunks = chunkText(text);\n const requestId = options.requestId ?? randomUUID();\n if (chunks.length === 1) {\n return this.classifySingleChunk(chunks[0]!, options, {\n requestId,\n inputIndex: 0,\n chunkIndex: 0,\n chunkCount: 1,\n });\n }\n const results = await mapWithConcurrency(chunks, this.chunkConcurrency, (chunk, index) =>\n this.classifySingleChunk(chunk, options, {\n requestId,\n inputIndex: 0,\n chunkIndex: index,\n chunkCount: chunks.length,\n }),\n );\n return results.reduce((best, r) => (r.score > best.score ? r : best));\n }\n\n async classifyBatch(\n texts: readonly string[],\n options: ClassifyBatchOptions = {},\n ): Promise<BlockResult[]> {\n if (texts.length === 0) {\n throw new Error(\"Firewall: texts must not be empty\");\n }\n if (options.hooks !== undefined && options.hooks.length !== texts.length) {\n throw new Error(\n `Firewall: hooks length ${options.hooks.length} does not match texts length ${texts.length}`,\n );\n }\n if (options.toolNames !== undefined && options.toolNames.length !== texts.length) {\n throw new Error(\n `Firewall: toolNames length ${options.toolNames.length} does not match texts length ${texts.length}`,\n );\n }\n if (options.metadata !== undefined && options.metadata.length !== texts.length) {\n throw new Error(\n `Firewall: metadata length ${options.metadata.length} does not match texts length ${texts.length}`,\n );\n }\n\n const requestId = options.requestId ?? randomUUID();\n const payload: BatchClassifyPayload = {\n texts: texts.map((text) => sanitizeText(text)),\n };\n if (options.hooks && options.hooks.length > 0) {\n payload.hooks = options.hooks.map((h) => String(h));\n }\n if (options.toolNames && options.toolNames.length > 0) {\n payload.tool_names = options.toolNames.map((t) => (t === undefined ? null : t));\n }\n payload.metadata = texts.map((_, index) =>\n withSdkMetadata(options.metadata?.[index], {\n requestId,\n inputIndex: index,\n chunkIndex: 0,\n chunkCount: 1,\n }),\n );\n const data = await this.postWithRetry<BatchClassifyResponse>(payload);\n return data.predictions.map((p) => blockResultFromResponse(p));\n }\n\n asLangChainHandler<THandler = LangChainFirewallHandler>(\n options: LangChainAdapterOptions = {},\n ): Promise<THandler> {\n return import(\"./adapters/langchain.js\").then((m) =>\n m.createLangChainHandler(this, options) as Promise<THandler>,\n );\n }\n\n asMiddleware(options: MiddlewareOptions = {}): FirewallMiddleware {\n return createMiddleware(this, options);\n }\n\n private async postWithRetry<T>(\n payload: SingleClassifyPayload | BatchClassifyPayload,\n maxRetries: number = DEFAULT_MAX_RETRIES,\n ): Promise<T> {\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const response = await fetch(this.apiUrl, {\n method: \"POST\",\n headers: this.headers,\n body: JSON.stringify(payload),\n redirect: \"error\",\n signal: AbortSignal.timeout(this.timeoutMs),\n });\n if (response.status !== 429 || attempt === maxRetries) {\n if (!response.ok) {\n const body = await readCappedErrorBody(response);\n throw new SilmarilApiError({\n status: response.status,\n statusText: response.statusText,\n body,\n });\n }\n return (await response.json()) as T;\n }\n const waitSeconds = Math.min(2 ** attempt, MAX_BACKOFF_SECONDS);\n await new Promise<void>((resolve) => setTimeout(resolve, waitSeconds * 1000));\n }\n throw new Error(\"Firewall: exhausted retries (unreachable)\");\n }\n\n private async classifySingleChunk(\n text: string,\n options: ClassifyOptions,\n metadataInfo: {\n requestId: string;\n inputIndex: number;\n chunkIndex: number;\n chunkCount: number;\n },\n ): Promise<BlockResult> {\n const payload: SingleClassifyPayload = { text };\n if (options.hook !== undefined) {\n payload.hook = options.hook;\n }\n if (options.toolName !== undefined) {\n payload.tool_name = options.toolName;\n }\n payload.metadata = withSdkMetadata(options.metadata, metadataInfo);\n const data = await this.postWithRetry<SingleClassifyResponse>(payload);\n return blockResultFromResponse(data);\n }\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nimport type { Firewall } from \"../firewall.js\";\nimport { FirewallBlockedException } from \"../exceptions.js\";\nimport { HookLabel } from \"../hooks.js\";\nimport type { BlockResult, MiddlewareOptions } from \"../types.js\";\n\ninterface VercelContentPart {\n type?: string;\n text?: string;\n toolCallId?: string;\n toolName?: string;\n args?: unknown;\n output?: unknown;\n result?: unknown;\n}\n\ninterface VercelPromptMessage {\n role: string;\n content: string | ReadonlyArray<VercelContentPart | string>;\n}\n\ninterface VercelToolCall {\n toolCallType?: string;\n toolCallId?: string;\n toolName?: string;\n args?: unknown;\n input?: unknown;\n}\n\ninterface VercelGenerateResult {\n text?: string;\n toolCalls?: ReadonlyArray<VercelToolCall>;\n}\n\ninterface WrapGenerateArgs<TResult extends VercelGenerateResult & Record<string, unknown>> {\n params: { prompt?: ReadonlyArray<VercelPromptMessage> } & Record<string, unknown>;\n doGenerate: () => PromiseLike<TResult>;\n}\n\ninterface WrapStreamArgs<\n TResult extends { stream: ReadableStream<unknown> } & Record<string, unknown>,\n> {\n params: { prompt?: ReadonlyArray<VercelPromptMessage> } & Record<string, unknown>;\n doStream: () => PromiseLike<TResult>;\n}\n\ninterface StreamPart {\n type?: string;\n textDelta?: string;\n delta?: string;\n}\n\ninterface VercelStepContext {\n toolName: string | undefined;\n toolCallId: string | undefined;\n}\n\nfunction stringifyToolValue(value: unknown): string {\n if (value === null || value === undefined) {\n return \"\";\n }\n if (typeof value === \"string\") {\n return value;\n }\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction extractContentText(content: VercelPromptMessage[\"content\"]): string {\n if (typeof content === \"string\") {\n return content;\n }\n const parts: string[] = [];\n for (const block of content) {\n if (typeof block === \"string\") {\n parts.push(block);\n } else if (block && block.type === \"text\") {\n parts.push(block.text ?? \"\");\n }\n }\n return parts.join(\" \");\n}\n\nfunction iterateToolResultParts(\n message: VercelPromptMessage,\n): Array<{ text: string; toolName: string | undefined; toolCallId: string | undefined }> {\n if (typeof message.content === \"string\") {\n return [];\n }\n const out: Array<{ text: string; toolName: string | undefined; toolCallId: string | undefined }> = [];\n for (const part of message.content) {\n if (typeof part === \"string\") {\n continue;\n }\n if (part.type === \"tool-result\") {\n const text = stringifyToolResult(part.result !== undefined ? part.result : part.output);\n if (text.trim()) {\n out.push({ text, toolName: part.toolName, toolCallId: part.toolCallId });\n }\n }\n }\n return out;\n}\n\nfunction stringifyToolResult(value: unknown): string {\n if (!isRecord(value)) {\n return stringifyToolValue(value);\n }\n if ((value.type === \"text\" || value.type === \"error-text\") && typeof value.value === \"string\") {\n return value.value;\n }\n if ((value.type === \"json\" || value.type === \"error-json\") && value.value !== undefined) {\n return stringifyToolValue(value.value);\n }\n if (value.type === \"content\" && Array.isArray(value.value)) {\n return value.value\n .map((part) => (isRecord(part) && part.type === \"text\" && typeof part.text === \"string\" ? part.text : \"\"))\n .filter((text) => text.length > 0)\n .join(\" \");\n }\n return stringifyToolValue(value);\n}\n\nfunction findLastUserMessage(\n messages: ReadonlyArray<VercelPromptMessage>,\n): VercelPromptMessage | undefined {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]!;\n if (msg.role.toLowerCase() === \"user\") {\n return msg;\n }\n }\n return undefined;\n}\n\nexport interface FirewallMiddleware {\n readonly specificationVersion: \"v3\";\n readonly middlewareVersion: \"v2\";\n wrapGenerate: <TResult extends VercelGenerateResult & Record<string, unknown>>(\n args: WrapGenerateArgs<TResult>,\n ) => Promise<TResult>;\n wrapStream: <TResult extends { stream: ReadableStream<unknown> } & Record<string, unknown>>(\n args: WrapStreamArgs<TResult>,\n ) => Promise<TResult>;\n}\n\nexport function createMiddleware(\n firewall: Firewall,\n options: MiddlewareOptions = {},\n): FirewallMiddleware {\n const scanInput = options.scanInput ?? true;\n const scanOutput = options.scanOutput ?? false;\n const shadowMode = options.shadowMode ?? firewall.shadowMode;\n\n const classifyOrBlock = async (\n text: string,\n hook: HookLabel,\n context: VercelStepContext = { toolName: undefined, toolCallId: undefined },\n ): Promise<void> => {\n if (!text.trim()) {\n return;\n }\n const { toolName, toolCallId } = context;\n const result: BlockResult = await firewall.classify(\n text,\n toolName !== undefined ? { hook, toolName } : { hook },\n );\n const threshold = result.threshold;\n const blocked = result.score >= threshold;\n const commonEventFields = {\n hook,\n ...(toolName !== undefined ? { toolName } : {}),\n ...(toolCallId !== undefined ? { toolCallId } : {}),\n text,\n result,\n };\n options.onClassify?.({\n ...commonEventFields,\n blocked,\n shadowMode,\n });\n if (!blocked || shadowMode) {\n return;\n }\n\n const err = new FirewallBlockedException({\n score: result.score,\n threshold,\n promptText: text,\n hook,\n ...(toolName !== undefined ? { toolName } : {}),\n ...(toolCallId !== undefined ? { toolCallId } : {}),\n result,\n });\n options.onBlocked?.(err);\n throw err;\n };\n\n const scanPrompt = async (prompt: ReadonlyArray<VercelPromptMessage>): Promise<void> => {\n if (prompt.length === 0) {\n return;\n }\n const last = prompt[prompt.length - 1]!;\n const role = last.role.toLowerCase();\n\n // If the newest message is a tool result (typical mid-flow in a\n // tool-calling loop), classify each tool-result part individually with\n // tool_response + toolName. No manual wiring from the caller — the\n // toolName is read directly from the Vercel content part.\n if (role === \"tool\") {\n for (const { text, toolName, toolCallId } of iterateToolResultParts(last)) {\n await classifyOrBlock(text, HookLabel.TOOL_RESPONSE, { toolName, toolCallId });\n }\n return;\n }\n\n // Otherwise, fall back to scanning the most recent user message.\n // Covers: [user], [system, user], [user, assistant(text), user], etc.\n const lastUser = findLastUserMessage(prompt);\n if (!lastUser) {\n return;\n }\n const text = extractContentText(lastUser.content).trim();\n if (!text) {\n return;\n }\n await classifyOrBlock(text, HookLabel.USER_INPUT);\n };\n\n const scanGenerateResult = async (result: VercelGenerateResult): Promise<void> => {\n if (scanOutput && typeof result.text === \"string\" && result.text.length > 0) {\n await classifyOrBlock(result.text, HookLabel.LLM_OUTPUT);\n }\n if (options.scanToolCalls && Array.isArray(result.toolCalls)) {\n for (const call of result.toolCalls) {\n if (!call || typeof call !== \"object\") {\n continue;\n }\n const toolInput = call.args !== undefined ? call.args : call.input;\n const args =\n typeof toolInput === \"string\" ? toolInput : stringifyToolValue(toolInput);\n const toolName = typeof call.toolName === \"string\" ? call.toolName : undefined;\n const toolCallId = typeof call.toolCallId === \"string\" ? call.toolCallId : undefined;\n if (args.trim()) {\n await classifyOrBlock(args, HookLabel.TOOL_CALL, { toolName, toolCallId });\n }\n }\n }\n };\n\n return {\n specificationVersion: \"v3\",\n middlewareVersion: \"v2\",\n\n async wrapGenerate<TResult extends VercelGenerateResult & Record<string, unknown>>({\n params,\n doGenerate,\n }: WrapGenerateArgs<TResult>): Promise<TResult> {\n if (scanInput) {\n await scanPrompt(params.prompt ?? []);\n }\n const result = await doGenerate();\n await scanGenerateResult(result);\n return result;\n },\n\n async wrapStream<TResult extends { stream: ReadableStream<unknown> } & Record<string, unknown>>({\n params,\n doStream,\n }: WrapStreamArgs<TResult>): Promise<TResult> {\n if (scanInput) {\n await scanPrompt(params.prompt ?? []);\n }\n const { stream, ...rest } = await doStream();\n if (!scanOutput) {\n return { stream, ...rest } as unknown as TResult;\n }\n\n let buffered = \"\";\n const transformed = stream.pipeThrough(\n new TransformStream<unknown, unknown>({\n transform(chunk, controller): void {\n const part = chunk as StreamPart;\n if (part && part.type === \"text-delta\") {\n const delta = part.textDelta ?? part.delta ?? \"\";\n buffered += delta;\n }\n controller.enqueue(chunk);\n },\n async flush(controller): Promise<void> {\n if (!buffered.trim()) {\n return;\n }\n try {\n await classifyOrBlock(buffered, HookLabel.LLM_OUTPUT);\n } catch (err) {\n if (err instanceof FirewallBlockedException) {\n controller.enqueue({ type: \"error\", error: err });\n return;\n }\n throw err;\n }\n },\n }),\n );\n return { stream: transformed, ...rest } as unknown as TResult;\n },\n };\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nconst CHARS_PER_TOKEN = 4;\n\nexport const MAX_INPUT_TOKENS = 81_920;\nexport const CHUNK_WINDOW = 400;\nexport const CHUNK_OVERLAP = 64;\n\nexport const MAX_INPUT_CHARS = MAX_INPUT_TOKENS * CHARS_PER_TOKEN;\nexport const CHUNK_WINDOW_CHARS = CHUNK_WINDOW * CHARS_PER_TOKEN;\nexport const CHUNK_OVERLAP_CHARS = CHUNK_OVERLAP * CHARS_PER_TOKEN;\nconst CHUNK_STRIDE_CHARS = CHUNK_WINDOW_CHARS - CHUNK_OVERLAP_CHARS;\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 continue;\n }\n out += text[i]!;\n }\n return out;\n}\n\nfunction safeChunkStart(text: string, start: number): number {\n if (\n start > 0 &&\n start < text.length &&\n isLowSurrogate(text.charCodeAt(start)) &&\n isHighSurrogate(text.charCodeAt(start - 1))\n ) {\n return start + 1;\n }\n return start;\n}\n\nfunction safeChunkEnd(text: string, end: number): number {\n if (\n end > 0 &&\n end < text.length &&\n isHighSurrogate(text.charCodeAt(end - 1)) &&\n isLowSurrogate(text.charCodeAt(end))\n ) {\n return end - 1;\n }\n return end;\n}\n\nexport function chunkText(text: string): string[] {\n text = sanitizeText(text);\n const n = text.length;\n if (n > MAX_INPUT_CHARS) {\n throw new Error(\n `Input has ~${Math.floor(n / CHARS_PER_TOKEN)} tokens (${n} chars); ` +\n `max is ${MAX_INPUT_TOKENS} tokens (${MAX_INPUT_CHARS} chars)`,\n );\n }\n if (n <= CHUNK_WINDOW_CHARS) {\n return [text];\n }\n const chunks: string[] = [];\n for (let start = 0; start < n; start += CHUNK_STRIDE_CHARS) {\n const safeStart = safeChunkStart(text, start);\n if (safeStart >= n) {\n break;\n }\n const end = safeChunkEnd(text, safeStart + CHUNK_WINDOW_CHARS);\n chunks.push(text.slice(safeStart, end));\n if (end >= n) {\n break;\n }\n }\n return chunks;\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nexport const Outcome = {\n Benign: \"benign\",\n InformationDisclosure: \"information_disclosure\",\n SecretExposure: \"secret_exposure\",\n ControlAbuse: \"control_abuse\",\n SystemCompromise: \"system_compromise\",\n ServiceDisruption: \"service_disruption\",\n} as const;\n\ndeclare const unknownOutcomeBrand: unique symbol;\n\nexport type KnownPrimaryOutcome = (typeof Outcome)[keyof typeof Outcome];\nexport type KnownHarmfulOutcome = Exclude<KnownPrimaryOutcome, typeof Outcome.Benign>;\nexport type UnknownOutcome = string & { readonly [unknownOutcomeBrand]: \"UnknownOutcome\" };\nexport type PrimaryOutcome = KnownPrimaryOutcome | UnknownOutcome;\nexport type HarmfulOutcome = KnownHarmfulOutcome | UnknownOutcome;\n\nexport const PRIMARY_OUTCOMES = [\n Outcome.Benign,\n Outcome.InformationDisclosure,\n Outcome.SecretExposure,\n Outcome.ControlAbuse,\n Outcome.SystemCompromise,\n Outcome.ServiceDisruption,\n] as const satisfies readonly PrimaryOutcome[];\n\nexport const HARMFUL_OUTCOMES = [\n Outcome.InformationDisclosure,\n Outcome.SecretExposure,\n Outcome.ControlAbuse,\n Outcome.SystemCompromise,\n Outcome.ServiceDisruption,\n] as const satisfies readonly KnownHarmfulOutcome[];\n\nexport const OUTCOME_DESCRIPTIONS = {\n [Outcome.Benign]: \"No harmful firewall outcome detected.\",\n [Outcome.InformationDisclosure]:\n \"Exposes private data, documents, internal context, logs, traces, customer data, SQL rows, topology, or similar non-secret sensitive information.\",\n [Outcome.SecretExposure]:\n \"Exposes credentials, tokens, API keys, cookies, passwords, signing keys, OAuth secrets, session material, or webhook secrets.\",\n [Outcome.ControlAbuse]:\n \"Misuses authorized tools or user privileges to send, change, approve, delete, operate, or bypass policy/RBAC without a stronger outcome.\",\n [Outcome.SystemCompromise]:\n \"Enables privilege escalation, account takeover, hostile integration or plugin takeover, persistence, lateral movement, attacker webhook registration, or code/plugin execution.\",\n [Outcome.ServiceDisruption]:\n \"Causes downtime, lockout, degradation, alert suppression, destructive loops, resource exhaustion, cost spikes, or hidden outage evidence.\",\n} as const satisfies Readonly<Record<KnownPrimaryOutcome, string>>;\n\nconst PRIMARY_OUTCOME_SET = new Set<string>(PRIMARY_OUTCOMES);\nconst HARMFUL_OUTCOME_SET = new Set<string>(HARMFUL_OUTCOMES);\n\nexport function isPrimaryOutcome(value: unknown): value is KnownPrimaryOutcome {\n return typeof value === \"string\" && PRIMARY_OUTCOME_SET.has(value);\n}\n\nexport function isHarmfulOutcome(value: unknown): value is KnownHarmfulOutcome {\n return typeof value === \"string\" && HARMFUL_OUTCOME_SET.has(value);\n}\n\nexport function normalizePrimaryOutcome(\n value: unknown,\n fieldName = \"primary_outcome\",\n): PrimaryOutcome {\n if (typeof value !== \"string\") {\n throw new Error(`Firewall: invalid ${fieldName} ${JSON.stringify(value)}`);\n }\n return isPrimaryOutcome(value) ? value : (value as UnknownOutcome);\n}\n\nexport function normalizeHarmfulOutcome(\n value: unknown,\n fieldName = \"outcome\",\n): HarmfulOutcome {\n if (typeof value !== \"string\" || value === Outcome.Benign) {\n throw new Error(`Firewall: invalid ${fieldName} ${JSON.stringify(value)}`);\n }\n return isHarmfulOutcome(value) ? value : (value as UnknownOutcome);\n}\n\nexport function normalizeHarmfulOutcomeMap(\n values: unknown,\n fieldName: string,\n): Readonly<Partial<Record<HarmfulOutcome, number>>> | undefined {\n if (values === undefined || values === null) {\n return undefined;\n }\n if (typeof values !== \"object\" || Array.isArray(values)) {\n throw new Error(`Firewall: invalid ${fieldName} ${JSON.stringify(values)}`);\n }\n const out: Partial<Record<HarmfulOutcome, number>> = {};\n for (const [key, value] of Object.entries(values)) {\n const normalizedKey = normalizeHarmfulOutcome(key, `${fieldName} key`);\n if (typeof value !== \"number\") {\n throw new Error(`Firewall: invalid ${fieldName} value for ${JSON.stringify(key)}`);\n }\n out[normalizedKey] = value;\n }\n return Object.freeze(out);\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nexport {\n Firewall,\n DEFAULT_CHUNK_CONCURRENCY,\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 chunkText,\n sanitizeText,\n MAX_INPUT_TOKENS,\n CHUNK_WINDOW,\n CHUNK_OVERLAP,\n MAX_INPUT_CHARS,\n CHUNK_WINDOW_CHARS,\n CHUNK_OVERLAP_CHARS,\n} from \"./chunking.js\";\n\nexport {\n HookLabel,\n FirewallHook,\n DEFAULT_HOOKS,\n INPUT_HOOKS,\n OUTPUT_HOOKS,\n ALL_HOOKS,\n FIREWALL_HOOK_TO_LABEL,\n resolveHooks,\n prependHook,\n prependToolName,\n} from \"./hooks.js\";\n\nexport {\n Outcome,\n PRIMARY_OUTCOMES,\n HARMFUL_OUTCOMES,\n OUTCOME_DESCRIPTIONS,\n isPrimaryOutcome,\n isHarmfulOutcome,\n normalizePrimaryOutcome,\n normalizeHarmfulOutcome,\n normalizeHarmfulOutcomeMap,\n} from \"./outcomes.js\";\n\nexport type {\n KnownPrimaryOutcome,\n KnownHarmfulOutcome,\n PrimaryOutcome,\n HarmfulOutcome,\n UnknownOutcome,\n} from \"./outcomes.js\";\n\nexport type {\n BlockResult,\n ClassifyEvent,\n Prediction,\n ClassificationMetadata,\n FirewallOptions,\n ClassifyOptions,\n ClassifyBatchOptions,\n LangChainAdapterOptions,\n LangChainFirewallHandler,\n MiddlewareOptions,\n} from \"./types.js\";\n"],"mappings":"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","names":["findLastUserMessage","text","isRecord","body"]}
|
|
1
|
+
{"version":3,"sources":["../src/exceptions.ts","../src/hooks.ts","../src/utils/extract.ts","../src/adapters/langchain.ts","../src/firewall.ts","../src/adapters/vercel.ts","../src/outcomes.ts","../src/sanitization.ts","../src/index.ts"],"sourcesContent":["// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nimport type { HookLabel } from \"./hooks.js\";\nimport type { BlockResult } from \"./types.js\";\n\nconst MAX_PROMPT_DISPLAY_LEN = 100;\n\nexport interface MalformedInputDetails {\n field?: string;\n inputIndex?: number;\n charOffset?: number;\n malformedToken?: string;\n codePoint?: string;\n reason?: string;\n}\n\nexport class FirewallBlockedException extends Error {\n readonly score: number;\n readonly threshold: number;\n readonly promptText: string;\n readonly runId: string | undefined;\n readonly hook: HookLabel | undefined;\n readonly toolName: string | undefined;\n readonly toolCallId: string | undefined;\n readonly result: BlockResult | undefined;\n\n constructor(params: {\n score: number;\n threshold: number;\n promptText: string;\n runId?: string;\n hook?: HookLabel;\n toolName?: string;\n toolCallId?: string;\n result?: BlockResult;\n }) {\n super(FirewallBlockedException.formatMessage(params));\n this.name = \"FirewallBlockedException\";\n this.score = params.score;\n this.threshold = params.threshold;\n this.promptText = params.promptText;\n this.runId = params.runId;\n this.hook = params.hook;\n this.toolName = params.toolName;\n this.toolCallId = params.toolCallId;\n this.result = params.result;\n Object.setPrototypeOf(this, FirewallBlockedException.prototype);\n }\n\n private static formatMessage(params: {\n score: number;\n threshold: number;\n promptText: string;\n }): string {\n const truncated =\n params.promptText.length > MAX_PROMPT_DISPLAY_LEN\n ? `${params.promptText.slice(0, MAX_PROMPT_DISPLAY_LEN)}...`\n : params.promptText;\n return (\n `Request blocked by Silmaril Firewall ` +\n `(score=${params.score.toFixed(4)}, threshold=${params.threshold.toFixed(4)}): ` +\n `'${truncated}'`\n );\n }\n}\n\n/** @deprecated Use FirewallBlockedException instead. */\nexport const PromptBlockedException = FirewallBlockedException;\n/** @deprecated Use FirewallBlockedException instead. */\nexport type PromptBlockedException = FirewallBlockedException;\n\nexport class SilmarilApiError extends Error {\n readonly status: number;\n readonly statusText: string;\n readonly body: string;\n readonly details: MalformedInputDetails | undefined;\n readonly error: string | undefined;\n readonly apiMessage: string | undefined;\n\n constructor(params: {\n status: number;\n statusText: string;\n body: string;\n details?: MalformedInputDetails;\n error?: string;\n apiMessage?: string;\n }) {\n const statusText = params.statusText ? ` ${params.statusText}` : \"\";\n super(`Silmaril API error ${params.status}${statusText}`);\n this.name = \"SilmarilApiError\";\n this.status = params.status;\n this.statusText = params.statusText;\n this.body = params.body;\n const parsed = parseErrorBody(params.body);\n this.details = params.details ?? parsed.details;\n this.error = params.error ?? parsed.error;\n this.apiMessage = params.apiMessage ?? parsed.apiMessage;\n Object.setPrototypeOf(this, SilmarilApiError.prototype);\n }\n}\n\nfunction parseErrorBody(body: string): {\n details: MalformedInputDetails | undefined;\n error: string | undefined;\n apiMessage: string | undefined;\n} {\n try {\n const parsed = JSON.parse(body) as unknown;\n if (!parsed || typeof parsed !== \"object\") {\n return { details: undefined, error: undefined, apiMessage: undefined };\n }\n const data = parsed as Record<string, unknown>;\n return {\n details:\n data.details && typeof data.details === \"object\"\n ? (data.details as MalformedInputDetails)\n : undefined,\n error: typeof data.error === \"string\" ? data.error : undefined,\n apiMessage: typeof data.message === \"string\" ? data.message : undefined,\n };\n } catch {\n return { details: undefined, error: undefined, apiMessage: undefined };\n }\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nexport const HookLabel = {\n USER_INPUT: \"user_input\",\n SYSTEM_PROMPT: \"system_prompt\",\n TOOL_CALL: \"tool_call\",\n TOOL_RESPONSE: \"tool_response\",\n LLM_OUTPUT: \"llm_output\",\n UNKNOWN: \"unknown\",\n} as const;\n\nexport type HookLabel = (typeof HookLabel)[keyof typeof HookLabel];\n\nexport const FirewallHook = {\n LLM_START: \"on_llm_start\",\n CHAT_MODEL_START: \"on_chat_model_start\",\n TOOL_START: \"on_tool_start\",\n RETRIEVER_START: \"on_retriever_start\",\n LLM_END: \"on_llm_end\",\n TOOL_END: \"on_tool_end\",\n RETRIEVER_END: \"on_retriever_end\",\n} as const;\n\nexport type FirewallHook = (typeof FirewallHook)[keyof typeof FirewallHook];\n\nexport const DEFAULT_HOOKS: ReadonlySet<FirewallHook> = new Set<FirewallHook>([\n FirewallHook.LLM_START,\n FirewallHook.CHAT_MODEL_START,\n]);\n\nexport const INPUT_HOOKS: ReadonlySet<FirewallHook> = new Set<FirewallHook>([\n FirewallHook.LLM_START,\n FirewallHook.CHAT_MODEL_START,\n FirewallHook.TOOL_START,\n FirewallHook.RETRIEVER_START,\n]);\n\nexport const OUTPUT_HOOKS: ReadonlySet<FirewallHook> = new Set<FirewallHook>([\n FirewallHook.LLM_END,\n FirewallHook.TOOL_END,\n FirewallHook.RETRIEVER_END,\n]);\n\nexport const ALL_HOOKS: ReadonlySet<FirewallHook> = new Set<FirewallHook>([\n ...INPUT_HOOKS,\n ...OUTPUT_HOOKS,\n]);\n\nexport const FIREWALL_HOOK_TO_LABEL: Readonly<Record<FirewallHook, HookLabel>> = {\n [FirewallHook.CHAT_MODEL_START]: HookLabel.USER_INPUT,\n [FirewallHook.LLM_START]: HookLabel.USER_INPUT,\n [FirewallHook.TOOL_START]: HookLabel.TOOL_CALL,\n [FirewallHook.TOOL_END]: HookLabel.TOOL_RESPONSE,\n [FirewallHook.RETRIEVER_START]: HookLabel.TOOL_CALL,\n [FirewallHook.RETRIEVER_END]: HookLabel.TOOL_RESPONSE,\n [FirewallHook.LLM_END]: HookLabel.LLM_OUTPUT,\n};\n\nconst FIREWALL_HOOK_VALUES: ReadonlySet<string> = new Set(Object.values(FirewallHook));\n\nexport function resolveHooks(\n hooks: Iterable<FirewallHook | string> | undefined,\n): ReadonlySet<FirewallHook> {\n if (hooks === undefined) {\n return DEFAULT_HOOKS;\n }\n const resolved = new Set<FirewallHook>();\n for (const h of hooks) {\n if (!FIREWALL_HOOK_VALUES.has(h)) {\n throw new Error(`Invalid FirewallHook value: ${String(h)}`);\n }\n resolved.add(h as FirewallHook);\n }\n return resolved;\n}\n\nexport function prependHook(text: string, hook: HookLabel | string | undefined | null): string {\n if (hook === undefined || hook === null) {\n return text;\n }\n if (hook === HookLabel.UNKNOWN) {\n return text;\n }\n return `[HOOK:${hook}] ${text}`;\n}\n\nexport function prependToolName(text: string, toolName: string | undefined | null): string {\n if (toolName === undefined || toolName === null) {\n return text;\n }\n return `[TOOL:${toolName}] ${text}`;\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nconst SKIP_ROLES: ReadonlySet<string> = new Set([\"ai\", \"assistant\"]);\nconst SYSTEM_ROLES: ReadonlySet<string> = new Set([\"system\"]);\nconst TOOL_ROLES: ReadonlySet<string> = new Set([\"tool\", \"function\"]);\n\ntype MessageContent = string | ReadonlyArray<string | { type?: string; text?: string }>;\n\ninterface DucktypedMessage {\n role?: string;\n type?: string;\n content?: MessageContent;\n}\n\ninterface DucktypedGeneration {\n text?: string;\n}\n\ninterface DucktypedLLMResult {\n generations?: ReadonlyArray<ReadonlyArray<DucktypedGeneration>>;\n}\n\ninterface DucktypedDocument {\n pageContent?: string;\n}\n\nfunction extractContentText(content: MessageContent | undefined): string {\n if (typeof content === \"string\") {\n return content;\n }\n if (Array.isArray(content)) {\n const parts: string[] = [];\n for (const block of content) {\n if (typeof block === \"string\") {\n parts.push(block);\n } else if (block && typeof block === \"object\" && block.type === \"text\") {\n parts.push(block.text ?? \"\");\n }\n }\n return parts.join(\" \");\n }\n return \"\";\n}\n\nfunction getRole(message: DucktypedMessage): string {\n if (message.role !== undefined) {\n return message.role.toLowerCase();\n }\n if (typeof message.type === \"string\") {\n return message.type.toLowerCase();\n }\n return \"\";\n}\n\nexport function extractTextFromMessages(\n messages: ReadonlyArray<DucktypedMessage>,\n options: { includeSystem?: boolean; includeTool?: boolean } = {},\n): string {\n const includeSystem = options.includeSystem ?? true;\n const includeTool = options.includeTool ?? true;\n const parts: string[] = [];\n for (const message of messages) {\n const role = getRole(message);\n if (SKIP_ROLES.has(role)) {\n continue;\n }\n if (!includeSystem && SYSTEM_ROLES.has(role)) {\n continue;\n }\n if (!includeTool && TOOL_ROLES.has(role)) {\n continue;\n }\n const text = extractContentText(message.content);\n const stripped = text.trim();\n if (stripped) {\n parts.push(stripped);\n }\n }\n return parts.join(\"\\n\");\n}\n\nexport function extractTextFromPrompts(prompts: readonly string[]): string {\n return prompts\n .map((p) => p.trim())\n .filter((p) => p.length > 0)\n .join(\"\\n\");\n}\n\nexport function extractTextFromToolInput(inputStr: string): string {\n return inputStr.trim();\n}\n\nexport function extractTextFromLLMResult(response: DucktypedLLMResult): string {\n const parts: string[] = [];\n for (const genList of response.generations ?? []) {\n for (const gen of genList) {\n const text = (gen.text ?? \"\").trim();\n if (text) {\n parts.push(text);\n }\n }\n }\n return parts.join(\"\\n\");\n}\n\nexport function extractTextFromDocuments(documents: ReadonlyArray<DucktypedDocument>): string {\n const parts: string[] = [];\n for (const doc of documents) {\n const text = (doc.pageContent ?? \"\").trim();\n if (text) {\n parts.push(text);\n }\n }\n return parts.join(\"\\n\");\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nimport type { BaseCallbackHandler } from \"@langchain/core/callbacks/base\";\n\nimport type { Firewall } from \"../firewall.js\";\nimport { FirewallBlockedException } from \"../exceptions.js\";\nimport {\n FIREWALL_HOOK_TO_LABEL,\n FirewallHook,\n HookLabel,\n resolveHooks,\n} from \"../hooks.js\";\nimport type { BlockResult, ClassifyEvent, LangChainAdapterOptions } from \"../types.js\";\nimport {\n extractTextFromDocuments,\n extractTextFromLLMResult,\n extractTextFromPrompts,\n extractTextFromToolInput,\n} from \"../utils/extract.js\";\n\nconst USER_ROLES: ReadonlySet<string> = new Set([\"human\", \"user\"]);\n\ninterface LangChainDucktypedMessage {\n role?: string;\n type?: string;\n content?: string | ReadonlyArray<string | { type?: string; text?: string }>;\n}\n\nfunction getMessageRole(message: LangChainDucktypedMessage): string {\n if (typeof message.role === \"string\") {\n return message.role.toLowerCase();\n }\n if (typeof message.type === \"string\") {\n return message.type.toLowerCase();\n }\n return \"\";\n}\n\nfunction extractMessageText(content: LangChainDucktypedMessage[\"content\"]): string {\n if (content === undefined) {\n return \"\";\n }\n if (typeof content === \"string\") {\n return content;\n }\n const parts: string[] = [];\n for (const block of content) {\n if (typeof block === \"string\") {\n parts.push(block);\n } else if (block && block.type === \"text\") {\n parts.push(block.text ?? \"\");\n }\n }\n return parts.join(\" \");\n}\n\nfunction findLastUserMessage(\n messages: ReadonlyArray<LangChainDucktypedMessage>,\n): LangChainDucktypedMessage | undefined {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]!;\n if (USER_ROLES.has(getMessageRole(msg))) {\n return msg;\n }\n }\n return undefined;\n}\n\nexport async function createLangChainHandler(\n firewall: Firewall,\n options: LangChainAdapterOptions = {},\n): Promise<BaseCallbackHandler> {\n const { BaseCallbackHandler } = await import(\"@langchain/core/callbacks/base\");\n\n const enabledHooks = resolveHooks(options.hooks);\n // includeSystem / includeTool are retained in LangChainAdapterOptions for\n // backwards compat but are inert under the per-message hook-routing algorithm:\n // handleChatModelStart only scans the last user-role message; system and tool\n // messages are either trusted or already classified by their own hooks.\n const failOpen = options.failOpen ?? true;\n const logger =\n options.logger ??\n ((message: string, error: unknown): void => {\n // eslint-disable-next-line no-console\n console.warn(`silmaril.firewall: ${message}`, error);\n });\n const shadowMode = options.shadowMode ?? firewall.shadowMode;\n const onClassify = options.onClassify;\n\n const fireOnClassify = (event: ClassifyEvent): void => {\n if (!onClassify) {\n return;\n }\n try {\n onClassify(event);\n } catch (err) {\n logger(\"onClassify callback threw\", err);\n }\n };\n\n const classify = async (\n text: string,\n hookLabel: HookLabel,\n runId: string,\n toolName?: string,\n ): Promise<void> => {\n let result: BlockResult;\n try {\n result = await firewall.classify(text, {\n hook: hookLabel,\n ...(toolName !== undefined ? { toolName } : {}),\n });\n } catch (err) {\n if (!failOpen) {\n throw err;\n }\n logger(\"classification failed, allowing prompt through\", err);\n return;\n }\n const threshold = result.threshold;\n const blocked = result.prediction === \"MALICIOUS\";\n const commonEventFields = {\n hook: hookLabel,\n ...(toolName !== undefined ? { toolName } : {}),\n runId,\n text,\n result,\n };\n fireOnClassify({\n ...commonEventFields,\n blocked,\n shadowMode,\n });\n if (!blocked || shadowMode) {\n return;\n }\n\n throw new FirewallBlockedException({\n score: result.score,\n threshold,\n promptText: text,\n runId,\n hook: hookLabel,\n ...(toolName !== undefined ? { toolName } : {}),\n result,\n });\n };\n\n class SilmarilFirewallHandler extends BaseCallbackHandler {\n override name = \"silmaril_firewall_handler\";\n override raiseError = true;\n override awaitHandlers = true;\n\n override async handleChatModelStart(\n _llm: unknown,\n messages: unknown,\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.CHAT_MODEL_START)) {\n return;\n }\n const batches = messages as ReadonlyArray<ReadonlyArray<LangChainDucktypedMessage>>;\n const flat: LangChainDucktypedMessage[] = [];\n for (const batch of batches) {\n for (const m of batch) {\n flat.push(m);\n }\n }\n const lastUser = findLastUserMessage(flat);\n if (!lastUser) {\n return;\n }\n const text = extractMessageText(lastUser.content).trim();\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.CHAT_MODEL_START], runId);\n }\n\n override async handleLLMStart(\n _llm: unknown,\n prompts: string[],\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.LLM_START)) {\n return;\n }\n const text = extractTextFromPrompts(prompts);\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.LLM_START], runId);\n }\n\n override async handleToolStart(\n tool: { name?: string } | undefined,\n inputStr: string,\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.TOOL_START)) {\n return;\n }\n const text = extractTextFromToolInput(inputStr);\n if (!text) {\n return;\n }\n const toolName = tool?.name;\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.TOOL_START], runId, toolName);\n }\n\n override async handleRetrieverStart(\n _retriever: unknown,\n query: string,\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.RETRIEVER_START)) {\n return;\n }\n const text = query.trim();\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.RETRIEVER_START], runId);\n }\n\n override async handleLLMEnd(output: unknown, runId: string): Promise<void> {\n if (!enabledHooks.has(FirewallHook.LLM_END)) {\n return;\n }\n const text = extractTextFromLLMResult(output as { generations?: ReadonlyArray<ReadonlyArray<{ text?: string }>> });\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.LLM_END], runId);\n }\n\n override async handleToolEnd(\n output: unknown,\n runId: string,\n _parentRunId?: string,\n _tags?: string[],\n _kwargs?: { name?: string },\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.TOOL_END)) {\n return;\n }\n const text = String(output).trim();\n if (!text) {\n return;\n }\n const toolName = _kwargs?.name;\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.TOOL_END], runId, toolName);\n }\n\n override async handleRetrieverEnd(\n documents: ReadonlyArray<{ pageContent?: string }>,\n runId: string,\n ): Promise<void> {\n if (!enabledHooks.has(FirewallHook.RETRIEVER_END)) {\n return;\n }\n const text = extractTextFromDocuments(documents);\n if (!text) {\n return;\n }\n await classify(text, FIREWALL_HOOK_TO_LABEL[FirewallHook.RETRIEVER_END], runId);\n }\n }\n\n return new SilmarilFirewallHandler();\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nimport { randomUUID } from \"node:crypto\";\n\nimport { createMiddleware, type FirewallMiddleware } from \"./adapters/vercel.js\";\nimport { SilmarilApiError } from \"./exceptions.js\";\nimport { normalizeHarmfulOutcomeMap, normalizePrimaryOutcome } from \"./outcomes.js\";\nimport { sanitizeText } from \"./sanitization.js\";\nimport type {\n BlockResult,\n ClassifyBatchOptions,\n ClassifyOptions,\n ClassificationMetadata,\n FirewallOptions,\n LangChainAdapterOptions,\n LangChainFirewallHandler,\n MiddlewareOptions,\n Prediction,\n} from \"./types.js\";\n\nexport const SDK_VERSION = \"0.5.0\";\nexport const DEFAULT_TIMEOUT_MS = 10_000;\nconst DEFAULT_MAX_RETRIES = 5;\nconst MAX_BACKOFF_SECONDS = 30;\nconst MAX_ERROR_BODY_BYTES = 1 << 16;\n\ninterface SingleClassifyPayload {\n text: string;\n hook?: string;\n tool_name?: string;\n metadata?: ClassificationMetadata;\n}\n\ninterface BatchClassifyPayload {\n texts: readonly string[];\n hooks?: readonly string[];\n tool_names?: readonly (string | null)[];\n metadata?: readonly (ClassificationMetadata | null)[];\n}\n\ninterface SingleClassifyResponse {\n prediction: Prediction;\n score: number;\n threshold: number;\n primary_outcome?: unknown;\n outcome_scores?: unknown;\n detector_scores?: unknown;\n detector_counts?: unknown;\n}\n\ninterface BatchClassifyResponse {\n predictions: readonly SingleClassifyResponse[];\n}\n\nfunction blockResultFromResponse(data: SingleClassifyResponse): BlockResult {\n if (data.prediction !== \"BENIGN\" && data.prediction !== \"MALICIOUS\") {\n throw new Error(\"Firewall: response prediction must be BENIGN or MALICIOUS\");\n }\n const result: {\n prediction: Prediction;\n score: number;\n threshold: number;\n primaryOutcome?: NonNullable<BlockResult[\"primaryOutcome\"]>;\n outcomeScores?: NonNullable<BlockResult[\"outcomeScores\"]>;\n detectorScores?: NonNullable<BlockResult[\"detectorScores\"]>;\n detectorCounts?: NonNullable<BlockResult[\"detectorCounts\"]>;\n } = {\n prediction: data.prediction,\n score: Number(data.score),\n threshold: Number(data.threshold),\n };\n if (data.primary_outcome !== undefined) {\n result.primaryOutcome = normalizePrimaryOutcome(data.primary_outcome);\n }\n if (data.outcome_scores !== undefined) {\n const outcomeScores = normalizeHarmfulOutcomeMap(data.outcome_scores, \"outcome_scores\");\n if (outcomeScores !== undefined) {\n result.outcomeScores = outcomeScores;\n }\n }\n if (data.detector_scores !== undefined) {\n const detectorScores = normalizeHarmfulOutcomeMap(data.detector_scores, \"detector_scores\");\n if (detectorScores !== undefined) {\n result.detectorScores = detectorScores;\n }\n }\n if (data.detector_counts !== undefined) {\n const detectorCounts = normalizeHarmfulOutcomeMap(data.detector_counts, \"detector_counts\");\n if (detectorCounts !== undefined) {\n result.detectorCounts = detectorCounts;\n }\n }\n return Object.freeze(result);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction withSdkMetadata(\n metadata: ClassificationMetadata | undefined,\n info: {\n requestId: string;\n inputIndex?: number;\n },\n): ClassificationMetadata {\n const payload: Record<string, unknown> = { ...(metadata ?? {}) };\n const existing = payload.silmaril;\n if (existing !== undefined && !isRecord(existing)) {\n throw new Error(\"Firewall: metadata.silmaril must be an object when provided\");\n }\n payload.silmaril = {\n ...(isRecord(existing) ? existing : {}),\n sdk_language: \"typescript\",\n sdk_version: SDK_VERSION,\n request_id: info.requestId,\n ...(info.inputIndex === undefined ? {} : { input_index: info.inputIndex }),\n };\n return payload;\n}\n\nasync function readCappedErrorBody(response: Response): Promise<string> {\n if (!response.body) {\n return response.text().then((body) => body.slice(0, MAX_ERROR_BODY_BYTES)).catch(() => \"\");\n }\n\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let remaining = MAX_ERROR_BODY_BYTES;\n try {\n while (remaining > 0) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n if (!value) {\n continue;\n }\n const chunk = value.byteLength > remaining ? value.slice(0, remaining) : value;\n chunks.push(chunk);\n remaining -= chunk.byteLength;\n if (chunk.byteLength < value.byteLength) {\n break;\n }\n }\n } catch {\n return \"\";\n } finally {\n await reader.cancel().catch(() => undefined);\n }\n\n const total = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);\n const body = new Uint8Array(total);\n let offset = 0;\n for (const chunk of chunks) {\n body.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return new TextDecoder().decode(body);\n}\n\nexport class Firewall {\n readonly apiKey: string;\n readonly apiUrl: string;\n readonly timeoutMs: number;\n readonly shadowMode: boolean;\n\n private readonly headers: Readonly<Record<string, string>>;\n\n constructor(options: FirewallOptions) {\n if (!options.apiKey) {\n throw new Error(\"Firewall: apiKey is required\");\n }\n if (!options.apiUrl) {\n throw new Error(\"Firewall: apiUrl is required\");\n }\n this.apiKey = options.apiKey;\n this.apiUrl = options.apiUrl;\n this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n if (typeof this.timeoutMs !== \"number\" || !Number.isFinite(this.timeoutMs) || this.timeoutMs < 0) {\n throw new Error(`Firewall: timeoutMs must be a finite non-negative number, got ${this.timeoutMs}`);\n }\n this.shadowMode = options.shadowMode ?? false;\n this.headers = Object.freeze({\n \"x-api-key\": this.apiKey,\n \"content-type\": \"application/json\",\n });\n }\n\n async classify(text: string, options: ClassifyOptions = {}): Promise<BlockResult> {\n const requestId = options.requestId ?? randomUUID();\n return this.classifySingle(sanitizeText(text), options, { requestId });\n }\n\n async classifyBatch(\n texts: readonly string[],\n options: ClassifyBatchOptions = {},\n ): Promise<BlockResult[]> {\n if (texts.length === 0) {\n throw new Error(\"Firewall: texts must not be empty\");\n }\n if (options.hooks !== undefined && options.hooks.length !== texts.length) {\n throw new Error(\n `Firewall: hooks length ${options.hooks.length} does not match texts length ${texts.length}`,\n );\n }\n if (options.toolNames !== undefined && options.toolNames.length !== texts.length) {\n throw new Error(\n `Firewall: toolNames length ${options.toolNames.length} does not match texts length ${texts.length}`,\n );\n }\n if (options.metadata !== undefined && options.metadata.length !== texts.length) {\n throw new Error(\n `Firewall: metadata length ${options.metadata.length} does not match texts length ${texts.length}`,\n );\n }\n\n const requestId = options.requestId ?? randomUUID();\n const payload: BatchClassifyPayload = {\n texts: texts.map((text) => sanitizeText(text)),\n };\n if (options.hooks && options.hooks.length > 0) {\n payload.hooks = options.hooks.map((h) => String(h));\n }\n if (options.toolNames && options.toolNames.length > 0) {\n payload.tool_names = options.toolNames.map((t) => (t === undefined ? null : t));\n }\n payload.metadata = texts.map((_, index) =>\n withSdkMetadata(options.metadata?.[index], {\n requestId,\n inputIndex: index,\n }),\n );\n const data = await this.postWithRetry<BatchClassifyResponse>(payload);\n return data.predictions.map((p) => blockResultFromResponse(p));\n }\n\n asLangChainHandler<THandler = LangChainFirewallHandler>(\n options: LangChainAdapterOptions = {},\n ): Promise<THandler> {\n return import(\"./adapters/langchain.js\").then((m) =>\n m.createLangChainHandler(this, options) as Promise<THandler>,\n );\n }\n\n asMiddleware(options: MiddlewareOptions = {}): FirewallMiddleware {\n return createMiddleware(this, options);\n }\n\n private async postWithRetry<T>(\n payload: SingleClassifyPayload | BatchClassifyPayload,\n maxRetries: number = DEFAULT_MAX_RETRIES,\n ): Promise<T> {\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const response = await fetch(this.apiUrl, {\n method: \"POST\",\n headers: this.headers,\n body: JSON.stringify(payload),\n redirect: \"error\",\n signal: AbortSignal.timeout(this.timeoutMs),\n });\n if (response.status !== 429 || attempt === maxRetries) {\n if (!response.ok) {\n const body = await readCappedErrorBody(response);\n throw new SilmarilApiError({\n status: response.status,\n statusText: response.statusText,\n body,\n });\n }\n return (await response.json()) as T;\n }\n const waitSeconds = Math.min(2 ** attempt, MAX_BACKOFF_SECONDS);\n await new Promise<void>((resolve) => setTimeout(resolve, waitSeconds * 1000));\n }\n throw new Error(\"Firewall: exhausted retries (unreachable)\");\n }\n\n private async classifySingle(\n text: string,\n options: ClassifyOptions,\n metadataInfo: {\n requestId: string;\n },\n ): Promise<BlockResult> {\n const payload: SingleClassifyPayload = { text };\n if (options.hook !== undefined) {\n payload.hook = options.hook;\n }\n if (options.toolName !== undefined) {\n payload.tool_name = options.toolName;\n }\n payload.metadata = withSdkMetadata(options.metadata, metadataInfo);\n const data = await this.postWithRetry<SingleClassifyResponse>(payload);\n return blockResultFromResponse(data);\n }\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nimport type { Firewall } from \"../firewall.js\";\nimport { FirewallBlockedException } from \"../exceptions.js\";\nimport { HookLabel } from \"../hooks.js\";\nimport type { BlockResult, MiddlewareOptions } from \"../types.js\";\n\ninterface VercelContentPart {\n type?: string;\n text?: string;\n toolCallId?: string;\n toolName?: string;\n args?: unknown;\n output?: unknown;\n result?: unknown;\n}\n\ninterface VercelPromptMessage {\n role: string;\n content: string | ReadonlyArray<VercelContentPart | string>;\n}\n\ninterface VercelToolCall {\n toolCallType?: string;\n toolCallId?: string;\n toolName?: string;\n args?: unknown;\n input?: unknown;\n}\n\ninterface VercelGenerateResult {\n text?: string;\n toolCalls?: ReadonlyArray<VercelToolCall>;\n}\n\ninterface WrapGenerateArgs<TResult extends VercelGenerateResult & Record<string, unknown>> {\n params: { prompt?: ReadonlyArray<VercelPromptMessage> } & Record<string, unknown>;\n doGenerate: () => PromiseLike<TResult>;\n}\n\ninterface WrapStreamArgs<\n TResult extends { stream: ReadableStream<unknown> } & Record<string, unknown>,\n> {\n params: { prompt?: ReadonlyArray<VercelPromptMessage> } & Record<string, unknown>;\n doStream: () => PromiseLike<TResult>;\n}\n\ninterface StreamPart {\n type?: string;\n textDelta?: string;\n delta?: string;\n}\n\ninterface VercelStepContext {\n toolName: string | undefined;\n toolCallId: string | undefined;\n}\n\nfunction stringifyToolValue(value: unknown): string {\n if (value === null || value === undefined) {\n return \"\";\n }\n if (typeof value === \"string\") {\n return value;\n }\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction extractContentText(content: VercelPromptMessage[\"content\"]): string {\n if (typeof content === \"string\") {\n return content;\n }\n const parts: string[] = [];\n for (const block of content) {\n if (typeof block === \"string\") {\n parts.push(block);\n } else if (block && block.type === \"text\") {\n parts.push(block.text ?? \"\");\n }\n }\n return parts.join(\" \");\n}\n\nfunction iterateToolResultParts(\n message: VercelPromptMessage,\n): Array<{ text: string; toolName: string | undefined; toolCallId: string | undefined }> {\n if (typeof message.content === \"string\") {\n return [];\n }\n const out: Array<{ text: string; toolName: string | undefined; toolCallId: string | undefined }> = [];\n for (const part of message.content) {\n if (typeof part === \"string\") {\n continue;\n }\n if (part.type === \"tool-result\") {\n const text = stringifyToolResult(part.result !== undefined ? part.result : part.output);\n if (text.trim()) {\n out.push({ text, toolName: part.toolName, toolCallId: part.toolCallId });\n }\n }\n }\n return out;\n}\n\nfunction stringifyToolResult(value: unknown): string {\n if (!isRecord(value)) {\n return stringifyToolValue(value);\n }\n if ((value.type === \"text\" || value.type === \"error-text\") && typeof value.value === \"string\") {\n return value.value;\n }\n if ((value.type === \"json\" || value.type === \"error-json\") && value.value !== undefined) {\n return stringifyToolValue(value.value);\n }\n if (value.type === \"content\" && Array.isArray(value.value)) {\n return value.value\n .map((part) => (isRecord(part) && part.type === \"text\" && typeof part.text === \"string\" ? part.text : \"\"))\n .filter((text) => text.length > 0)\n .join(\" \");\n }\n return stringifyToolValue(value);\n}\n\nfunction findLastUserMessage(\n messages: ReadonlyArray<VercelPromptMessage>,\n): VercelPromptMessage | undefined {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i]!;\n if (msg.role.toLowerCase() === \"user\") {\n return msg;\n }\n }\n return undefined;\n}\n\nexport interface FirewallMiddleware {\n readonly specificationVersion: \"v3\";\n readonly middlewareVersion: \"v2\";\n wrapGenerate: <TResult extends VercelGenerateResult & Record<string, unknown>>(\n args: WrapGenerateArgs<TResult>,\n ) => Promise<TResult>;\n wrapStream: <TResult extends { stream: ReadableStream<unknown> } & Record<string, unknown>>(\n args: WrapStreamArgs<TResult>,\n ) => Promise<TResult>;\n}\n\nexport function createMiddleware(\n firewall: Firewall,\n options: MiddlewareOptions = {},\n): FirewallMiddleware {\n const scanInput = options.scanInput ?? true;\n const scanOutput = options.scanOutput ?? false;\n const shadowMode = options.shadowMode ?? firewall.shadowMode;\n\n const classifyOrBlock = async (\n text: string,\n hook: HookLabel,\n context: VercelStepContext = { toolName: undefined, toolCallId: undefined },\n ): Promise<void> => {\n if (!text.trim()) {\n return;\n }\n const { toolName, toolCallId } = context;\n const result: BlockResult = await firewall.classify(\n text,\n toolName !== undefined ? { hook, toolName } : { hook },\n );\n const threshold = result.threshold;\n const blocked = result.prediction === \"MALICIOUS\";\n const commonEventFields = {\n hook,\n ...(toolName !== undefined ? { toolName } : {}),\n ...(toolCallId !== undefined ? { toolCallId } : {}),\n text,\n result,\n };\n options.onClassify?.({\n ...commonEventFields,\n blocked,\n shadowMode,\n });\n if (!blocked || shadowMode) {\n return;\n }\n\n const err = new FirewallBlockedException({\n score: result.score,\n threshold,\n promptText: text,\n hook,\n ...(toolName !== undefined ? { toolName } : {}),\n ...(toolCallId !== undefined ? { toolCallId } : {}),\n result,\n });\n options.onBlocked?.(err);\n throw err;\n };\n\n const scanPrompt = async (prompt: ReadonlyArray<VercelPromptMessage>): Promise<void> => {\n if (prompt.length === 0) {\n return;\n }\n const last = prompt[prompt.length - 1]!;\n const role = last.role.toLowerCase();\n\n // If the newest message is a tool result (typical mid-flow in a\n // tool-calling loop), classify each tool-result part individually with\n // tool_response + toolName. No manual wiring from the caller — the\n // toolName is read directly from the Vercel content part.\n if (role === \"tool\") {\n for (const { text, toolName, toolCallId } of iterateToolResultParts(last)) {\n await classifyOrBlock(text, HookLabel.TOOL_RESPONSE, { toolName, toolCallId });\n }\n return;\n }\n\n // Otherwise, fall back to scanning the most recent user message.\n // Covers: [user], [system, user], [user, assistant(text), user], etc.\n const lastUser = findLastUserMessage(prompt);\n if (!lastUser) {\n return;\n }\n const text = extractContentText(lastUser.content).trim();\n if (!text) {\n return;\n }\n await classifyOrBlock(text, HookLabel.USER_INPUT);\n };\n\n const scanGenerateResult = async (result: VercelGenerateResult): Promise<void> => {\n if (scanOutput && typeof result.text === \"string\" && result.text.length > 0) {\n await classifyOrBlock(result.text, HookLabel.LLM_OUTPUT);\n }\n if (options.scanToolCalls && Array.isArray(result.toolCalls)) {\n for (const call of result.toolCalls) {\n if (!call || typeof call !== \"object\") {\n continue;\n }\n const toolInput = call.args !== undefined ? call.args : call.input;\n const args =\n typeof toolInput === \"string\" ? toolInput : stringifyToolValue(toolInput);\n const toolName = typeof call.toolName === \"string\" ? call.toolName : undefined;\n const toolCallId = typeof call.toolCallId === \"string\" ? call.toolCallId : undefined;\n if (args.trim()) {\n await classifyOrBlock(args, HookLabel.TOOL_CALL, { toolName, toolCallId });\n }\n }\n }\n };\n\n return {\n specificationVersion: \"v3\",\n middlewareVersion: \"v2\",\n\n async wrapGenerate<TResult extends VercelGenerateResult & Record<string, unknown>>({\n params,\n doGenerate,\n }: WrapGenerateArgs<TResult>): Promise<TResult> {\n if (scanInput) {\n await scanPrompt(params.prompt ?? []);\n }\n const result = await doGenerate();\n await scanGenerateResult(result);\n return result;\n },\n\n async wrapStream<TResult extends { stream: ReadableStream<unknown> } & Record<string, unknown>>({\n params,\n doStream,\n }: WrapStreamArgs<TResult>): Promise<TResult> {\n if (scanInput) {\n await scanPrompt(params.prompt ?? []);\n }\n const { stream, ...rest } = await doStream();\n if (!scanOutput) {\n return { stream, ...rest } as unknown as TResult;\n }\n\n let buffered = \"\";\n const transformed = stream.pipeThrough(\n new TransformStream<unknown, unknown>({\n transform(chunk, controller): void {\n const part = chunk as StreamPart;\n if (part && part.type === \"text-delta\") {\n const delta = part.textDelta ?? part.delta ?? \"\";\n buffered += delta;\n }\n controller.enqueue(chunk);\n },\n async flush(controller): Promise<void> {\n if (!buffered.trim()) {\n return;\n }\n try {\n await classifyOrBlock(buffered, HookLabel.LLM_OUTPUT);\n } catch (err) {\n if (err instanceof FirewallBlockedException) {\n controller.enqueue({ type: \"error\", error: err });\n return;\n }\n throw err;\n }\n },\n }),\n );\n return { stream: transformed, ...rest } as unknown as TResult;\n },\n };\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nexport const Outcome = {\n Benign: \"benign\",\n InformationDisclosure: \"information_disclosure\",\n SecretExposure: \"secret_exposure\",\n ControlAbuse: \"control_abuse\",\n SystemCompromise: \"system_compromise\",\n ServiceDisruption: \"service_disruption\",\n} as const;\n\ndeclare const unknownOutcomeBrand: unique symbol;\n\nexport type KnownPrimaryOutcome = (typeof Outcome)[keyof typeof Outcome];\nexport type KnownHarmfulOutcome = Exclude<KnownPrimaryOutcome, typeof Outcome.Benign>;\nexport type UnknownOutcome = string & { readonly [unknownOutcomeBrand]: \"UnknownOutcome\" };\nexport type PrimaryOutcome = KnownPrimaryOutcome | UnknownOutcome;\nexport type HarmfulOutcome = KnownHarmfulOutcome | UnknownOutcome;\n\nexport const PRIMARY_OUTCOMES = [\n Outcome.Benign,\n Outcome.InformationDisclosure,\n Outcome.SecretExposure,\n Outcome.ControlAbuse,\n Outcome.SystemCompromise,\n Outcome.ServiceDisruption,\n] as const satisfies readonly PrimaryOutcome[];\n\nexport const HARMFUL_OUTCOMES = [\n Outcome.InformationDisclosure,\n Outcome.SecretExposure,\n Outcome.ControlAbuse,\n Outcome.SystemCompromise,\n Outcome.ServiceDisruption,\n] as const satisfies readonly KnownHarmfulOutcome[];\n\nexport const OUTCOME_DESCRIPTIONS = {\n [Outcome.Benign]: \"No harmful firewall outcome detected.\",\n [Outcome.InformationDisclosure]:\n \"Exposes private data, documents, internal context, logs, traces, customer data, SQL rows, topology, or similar non-secret sensitive information.\",\n [Outcome.SecretExposure]:\n \"Exposes credentials, tokens, API keys, cookies, passwords, signing keys, OAuth secrets, session material, or webhook secrets.\",\n [Outcome.ControlAbuse]:\n \"Misuses authorized tools or user privileges to send, change, approve, delete, operate, or bypass policy/RBAC without a stronger outcome.\",\n [Outcome.SystemCompromise]:\n \"Enables privilege escalation, account takeover, hostile integration or plugin takeover, persistence, lateral movement, attacker webhook registration, or code/plugin execution.\",\n [Outcome.ServiceDisruption]:\n \"Causes downtime, lockout, degradation, alert suppression, destructive loops, resource exhaustion, cost spikes, or hidden outage evidence.\",\n} as const satisfies Readonly<Record<KnownPrimaryOutcome, string>>;\n\nconst PRIMARY_OUTCOME_SET = new Set<string>(PRIMARY_OUTCOMES);\nconst HARMFUL_OUTCOME_SET = new Set<string>(HARMFUL_OUTCOMES);\n\nexport function isPrimaryOutcome(value: unknown): value is KnownPrimaryOutcome {\n return typeof value === \"string\" && PRIMARY_OUTCOME_SET.has(value);\n}\n\nexport function isHarmfulOutcome(value: unknown): value is KnownHarmfulOutcome {\n return typeof value === \"string\" && HARMFUL_OUTCOME_SET.has(value);\n}\n\nexport function normalizePrimaryOutcome(\n value: unknown,\n fieldName = \"primary_outcome\",\n): PrimaryOutcome {\n if (typeof value !== \"string\") {\n throw new Error(`Firewall: invalid ${fieldName} ${JSON.stringify(value)}`);\n }\n return isPrimaryOutcome(value) ? value : (value as UnknownOutcome);\n}\n\nexport function normalizeHarmfulOutcome(\n value: unknown,\n fieldName = \"outcome\",\n): HarmfulOutcome {\n if (typeof value !== \"string\" || value === Outcome.Benign) {\n throw new Error(`Firewall: invalid ${fieldName} ${JSON.stringify(value)}`);\n }\n return isHarmfulOutcome(value) ? value : (value as UnknownOutcome);\n}\n\nexport function normalizeHarmfulOutcomeMap(\n values: unknown,\n fieldName: string,\n): Readonly<Partial<Record<HarmfulOutcome, number>>> | undefined {\n if (values === undefined || values === null) {\n return undefined;\n }\n if (typeof values !== \"object\" || Array.isArray(values)) {\n throw new Error(`Firewall: invalid ${fieldName} ${JSON.stringify(values)}`);\n }\n const out: Partial<Record<HarmfulOutcome, number>> = {};\n for (const [key, value] of Object.entries(values)) {\n const normalizedKey = normalizeHarmfulOutcome(key, `${fieldName} key`);\n if (typeof value !== \"number\") {\n throw new Error(`Firewall: invalid ${fieldName} value for ${JSON.stringify(key)}`);\n }\n out[normalizedKey] = value;\n }\n return Object.freeze(out);\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nfunction isHighSurrogate(code: number): boolean {\n return code >= 0xd800 && code <= 0xdbff;\n}\n\nfunction isLowSurrogate(code: number): boolean {\n return code >= 0xdc00 && code <= 0xdfff;\n}\n\nexport function sanitizeText(text: string): string {\n let out = \"\";\n for (let i = 0; i < text.length; i++) {\n const code = text.charCodeAt(i);\n if (isHighSurrogate(code)) {\n if (i + 1 < text.length && isLowSurrogate(text.charCodeAt(i + 1))) {\n out += text[i]!;\n out += text[i + 1]!;\n i++;\n }\n continue;\n }\n if (!isLowSurrogate(code)) {\n out += text[i]!;\n }\n }\n return out;\n}\n","// Copyright (c) 2024-2025 Silmaril Security Inc. All rights reserved.\n// PROPRIETARY AND CONFIDENTIAL\n\nexport {\n Firewall,\n DEFAULT_TIMEOUT_MS,\n} from \"./firewall.js\";\n\nexport { FirewallBlockedException, PromptBlockedException, SilmarilApiError } from \"./exceptions.js\";\nexport type { MalformedInputDetails } from \"./exceptions.js\";\n\nexport type { FirewallMiddleware } from \"./adapters/vercel.js\";\n\nexport {\n HookLabel,\n FirewallHook,\n DEFAULT_HOOKS,\n INPUT_HOOKS,\n OUTPUT_HOOKS,\n ALL_HOOKS,\n FIREWALL_HOOK_TO_LABEL,\n resolveHooks,\n prependHook,\n prependToolName,\n} from \"./hooks.js\";\n\nexport {\n Outcome,\n PRIMARY_OUTCOMES,\n HARMFUL_OUTCOMES,\n OUTCOME_DESCRIPTIONS,\n isPrimaryOutcome,\n isHarmfulOutcome,\n normalizePrimaryOutcome,\n normalizeHarmfulOutcome,\n normalizeHarmfulOutcomeMap,\n} from \"./outcomes.js\";\n\nexport type {\n KnownPrimaryOutcome,\n KnownHarmfulOutcome,\n PrimaryOutcome,\n HarmfulOutcome,\n UnknownOutcome,\n} from \"./outcomes.js\";\n\nexport type {\n BlockResult,\n ClassifyEvent,\n Prediction,\n ClassificationMetadata,\n FirewallOptions,\n ClassifyOptions,\n ClassifyBatchOptions,\n LangChainAdapterOptions,\n LangChainFirewallHandler,\n MiddlewareOptions,\n} from \"./types.js\";\n"],"mappings":"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","names":["findLastUserMessage","text","isRecord","body"]}
|