@silmaril-security/sdk 0.4.1 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  All notable changes to the Silmaril Firewall TypeScript SDK are documented here.
4
4
 
5
+ ## 0.4.2 - 2026-06-02
6
+
7
+ - Add typed firewall outcome constants, ordered outcome lists, descriptions,
8
+ type guards, and response normalizers.
9
+ - Type `BlockResult.primaryOutcome`, `outcomeScores`, `detectorScores`, and
10
+ `detectorCounts` around the canonical outcome taxonomy.
11
+ - Document simple outcome routing examples for direct `classify()` results.
12
+
5
13
  ## 0.4.1 - 2026-05-24
6
14
 
7
15
  - Recover the `0.4.x` npm release by moving to `0.4.1`. The `v0.4.0` Git tag
package/README.md CHANGED
@@ -37,7 +37,7 @@ npm install @silmaril-security/sdk
37
37
  For reproducible installs, pin a tagged release:
38
38
 
39
39
  ```sh
40
- npm install @silmaril-security/sdk@0.4.1
40
+ npm install @silmaril-security/sdk@0.4.2
41
41
  ```
42
42
 
43
43
  Requires Node 18 or later.
@@ -117,6 +117,52 @@ internally applied threshold. Direct calls do not throw on malicious verdicts.
117
117
  The Vercel AI SDK and LangChain.js adapters use `result.threshold` and throw
118
118
  `FirewallBlockedException` when enforcement is enabled.
119
119
 
120
+ ## Handle Outcomes
121
+
122
+ Direct calls expose typed outcome labels so applications can choose different
123
+ responses for different firewall decisions:
124
+
125
+ ```ts
126
+ import { Firewall, HookLabel, Outcome } from "@silmaril-security/sdk";
127
+
128
+ const result = await fw.classify(userInput, {
129
+ hook: HookLabel.USER_INPUT,
130
+ });
131
+
132
+ if (result.score < result.threshold) {
133
+ continueNormally();
134
+ } else {
135
+ switch (result.primaryOutcome) {
136
+ case Outcome.SecretExposure:
137
+ redactAndSuppress(result);
138
+ break;
139
+ case Outcome.InformationDisclosure:
140
+ requireReview(result);
141
+ break;
142
+ case Outcome.ControlAbuse:
143
+ denyAndAskForConfirmation(result);
144
+ break;
145
+ case Outcome.SystemCompromise:
146
+ blockAndEscalate(result);
147
+ break;
148
+ case Outcome.ServiceDisruption:
149
+ blockDisruptiveAction(result);
150
+ break;
151
+ default:
152
+ blockByDefault(result);
153
+ }
154
+ }
155
+ ```
156
+
157
+ Outcome taxonomy:
158
+
159
+ - `benign`: no harmful firewall outcome detected.
160
+ - `information_disclosure`: private data, documents, internal context, logs, traces, customer data, SQL rows, topology, or similar non-secret sensitive information.
161
+ - `secret_exposure`: credentials, tokens, API keys, cookies, passwords, signing keys, OAuth secrets, session material, or webhook secrets.
162
+ - `control_abuse`: misuse of authorized tools or user privileges to send, change, approve, delete, operate, or bypass policy/RBAC without a stronger outcome.
163
+ - `system_compromise`: privilege escalation, account takeover, hostile integration/plugin takeover, persistence, lateral movement, attacker webhook registration, or code/plugin execution.
164
+ - `service_disruption`: downtime, lockout, degradation, alert suppression, destructive loops, resource exhaustion, cost spikes, or hidden outage evidence.
165
+
120
166
  ## Options
121
167
 
122
168
  ```ts
@@ -1,5 +1,5 @@
1
1
  import { BaseCallbackHandler } from '@langchain/core/callbacks/base';
2
- import { f as Firewall, L as LangChainAdapterOptions } from '../firewall-CEV5hItA.cjs';
2
+ import { f as Firewall, L as LangChainAdapterOptions } from '../firewall-DfZCCDU6.cjs';
3
3
 
4
4
  declare function createLangChainHandler(firewall: Firewall, options?: LangChainAdapterOptions): Promise<BaseCallbackHandler>;
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { BaseCallbackHandler } from '@langchain/core/callbacks/base';
2
- import { f as Firewall, L as LangChainAdapterOptions } from '../firewall-CEV5hItA.js';
2
+ import { f as Firewall, L as LangChainAdapterOptions } from '../firewall-DfZCCDU6.js';
3
3
 
4
4
  declare function createLangChainHandler(firewall: Firewall, options?: LangChainAdapterOptions): Promise<BaseCallbackHandler>;
5
5
 
@@ -1 +1 @@
1
- export { h as FirewallMiddleware, l as createMiddleware } from '../firewall-CEV5hItA.cjs';
1
+ export { h as FirewallMiddleware, z as createMiddleware } from '../firewall-DfZCCDU6.cjs';
@@ -1 +1 @@
1
- export { h as FirewallMiddleware, l as createMiddleware } from '../firewall-CEV5hItA.js';
1
+ export { h as FirewallMiddleware, z as createMiddleware } from '../firewall-DfZCCDU6.js';
@@ -26,15 +26,47 @@ declare function resolveHooks(hooks: Iterable<FirewallHook | string> | undefined
26
26
  declare function prependHook(text: string, hook: HookLabel | string | undefined | null): string;
27
27
  declare function prependToolName(text: string, toolName: string | undefined | null): string;
28
28
 
29
+ declare const Outcome: {
30
+ readonly Benign: "benign";
31
+ readonly InformationDisclosure: "information_disclosure";
32
+ readonly SecretExposure: "secret_exposure";
33
+ readonly ControlAbuse: "control_abuse";
34
+ readonly SystemCompromise: "system_compromise";
35
+ readonly ServiceDisruption: "service_disruption";
36
+ };
37
+ declare const unknownOutcomeBrand: unique symbol;
38
+ type KnownPrimaryOutcome = (typeof Outcome)[keyof typeof Outcome];
39
+ type KnownHarmfulOutcome = Exclude<KnownPrimaryOutcome, typeof Outcome.Benign>;
40
+ type UnknownOutcome = string & {
41
+ readonly [unknownOutcomeBrand]: "UnknownOutcome";
42
+ };
43
+ type PrimaryOutcome = KnownPrimaryOutcome | UnknownOutcome;
44
+ type HarmfulOutcome = KnownHarmfulOutcome | UnknownOutcome;
45
+ declare const PRIMARY_OUTCOMES: readonly ["benign", "information_disclosure", "secret_exposure", "control_abuse", "system_compromise", "service_disruption"];
46
+ declare const HARMFUL_OUTCOMES: readonly ["information_disclosure", "secret_exposure", "control_abuse", "system_compromise", "service_disruption"];
47
+ declare const OUTCOME_DESCRIPTIONS: {
48
+ readonly benign: "No harmful firewall outcome detected.";
49
+ readonly information_disclosure: "Exposes private data, documents, internal context, logs, traces, customer data, SQL rows, topology, or similar non-secret sensitive information.";
50
+ readonly secret_exposure: "Exposes credentials, tokens, API keys, cookies, passwords, signing keys, OAuth secrets, session material, or webhook secrets.";
51
+ readonly control_abuse: "Misuses authorized tools or user privileges to send, change, approve, delete, operate, or bypass policy/RBAC without a stronger outcome.";
52
+ readonly system_compromise: "Enables privilege escalation, account takeover, hostile integration or plugin takeover, persistence, lateral movement, attacker webhook registration, or code/plugin execution.";
53
+ readonly service_disruption: "Causes downtime, lockout, degradation, alert suppression, destructive loops, resource exhaustion, cost spikes, or hidden outage evidence.";
54
+ };
55
+ declare function isPrimaryOutcome(value: unknown): value is KnownPrimaryOutcome;
56
+ declare function isHarmfulOutcome(value: unknown): value is KnownHarmfulOutcome;
57
+ declare function normalizePrimaryOutcome(value: unknown, fieldName?: string): PrimaryOutcome;
58
+ declare function normalizeHarmfulOutcome(value: unknown, fieldName?: string): HarmfulOutcome;
59
+ declare function normalizeHarmfulOutcomeMap(values: unknown, fieldName: string): Readonly<Partial<Record<HarmfulOutcome, number>>> | undefined;
60
+
29
61
  type Prediction = "BENIGN" | "MALICIOUS";
30
62
  interface BlockResult {
31
63
  readonly prediction: Prediction;
32
64
  readonly score: number;
33
65
  readonly threshold: number;
34
- readonly primaryOutcome?: string;
35
- readonly outcomeScores?: Readonly<Record<string, number>>;
36
- readonly detectorScores?: Readonly<Record<string, number>>;
37
- readonly detectorCounts?: Readonly<Record<string, number>>;
66
+ readonly primaryOutcome?: PrimaryOutcome;
67
+ readonly outcomeScores?: Readonly<Partial<Record<HarmfulOutcome, number>>>;
68
+ readonly detectorScores?: Readonly<Partial<Record<HarmfulOutcome, number>>>;
69
+ readonly detectorCounts?: Readonly<Partial<Record<HarmfulOutcome, number>>>;
38
70
  }
39
71
  interface FirewallOptions {
40
72
  apiKey: string;
@@ -162,4 +194,4 @@ declare class Firewall {
162
194
  private classifySingleChunk;
163
195
  }
164
196
 
165
- export { ALL_HOOKS as A, type BlockResult as B, type ClassificationMetadata as C, DEFAULT_CHUNK_CONCURRENCY as D, FIREWALL_HOOK_TO_LABEL as F, HookLabel as H, INPUT_HOOKS as I, type LangChainAdapterOptions as L, type MiddlewareOptions as M, OUTPUT_HOOKS as O, type Prediction as P, type ClassifyBatchOptions as a, type ClassifyEvent as b, type ClassifyOptions as c, DEFAULT_HOOKS as d, DEFAULT_TIMEOUT_MS as e, Firewall as f, FirewallHook as g, type FirewallMiddleware as h, type FirewallOptions as i, type LangChainFirewallHandler as j, prependToolName as k, createMiddleware as l, prependHook as p, resolveHooks as r };
197
+ export { ALL_HOOKS as A, type BlockResult as B, type ClassificationMetadata as C, DEFAULT_CHUNK_CONCURRENCY as D, FIREWALL_HOOK_TO_LABEL as F, HookLabel as H, INPUT_HOOKS as I, type KnownHarmfulOutcome as K, type LangChainAdapterOptions as L, type MiddlewareOptions as M, OUTCOME_DESCRIPTIONS as O, PRIMARY_OUTCOMES as P, type UnknownOutcome as U, type ClassifyBatchOptions as a, type ClassifyEvent as b, type ClassifyOptions as c, DEFAULT_HOOKS as d, DEFAULT_TIMEOUT_MS as e, Firewall as f, FirewallHook as g, type FirewallMiddleware as h, type FirewallOptions as i, HARMFUL_OUTCOMES as j, type HarmfulOutcome as k, type KnownPrimaryOutcome as l, type LangChainFirewallHandler as m, OUTPUT_HOOKS as n, Outcome as o, type Prediction as p, type PrimaryOutcome as q, isHarmfulOutcome as r, isPrimaryOutcome as s, normalizeHarmfulOutcome as t, normalizeHarmfulOutcomeMap as u, normalizePrimaryOutcome as v, prependHook as w, prependToolName as x, resolveHooks as y, createMiddleware as z };
@@ -26,15 +26,47 @@ declare function resolveHooks(hooks: Iterable<FirewallHook | string> | undefined
26
26
  declare function prependHook(text: string, hook: HookLabel | string | undefined | null): string;
27
27
  declare function prependToolName(text: string, toolName: string | undefined | null): string;
28
28
 
29
+ declare const Outcome: {
30
+ readonly Benign: "benign";
31
+ readonly InformationDisclosure: "information_disclosure";
32
+ readonly SecretExposure: "secret_exposure";
33
+ readonly ControlAbuse: "control_abuse";
34
+ readonly SystemCompromise: "system_compromise";
35
+ readonly ServiceDisruption: "service_disruption";
36
+ };
37
+ declare const unknownOutcomeBrand: unique symbol;
38
+ type KnownPrimaryOutcome = (typeof Outcome)[keyof typeof Outcome];
39
+ type KnownHarmfulOutcome = Exclude<KnownPrimaryOutcome, typeof Outcome.Benign>;
40
+ type UnknownOutcome = string & {
41
+ readonly [unknownOutcomeBrand]: "UnknownOutcome";
42
+ };
43
+ type PrimaryOutcome = KnownPrimaryOutcome | UnknownOutcome;
44
+ type HarmfulOutcome = KnownHarmfulOutcome | UnknownOutcome;
45
+ declare const PRIMARY_OUTCOMES: readonly ["benign", "information_disclosure", "secret_exposure", "control_abuse", "system_compromise", "service_disruption"];
46
+ declare const HARMFUL_OUTCOMES: readonly ["information_disclosure", "secret_exposure", "control_abuse", "system_compromise", "service_disruption"];
47
+ declare const OUTCOME_DESCRIPTIONS: {
48
+ readonly benign: "No harmful firewall outcome detected.";
49
+ readonly information_disclosure: "Exposes private data, documents, internal context, logs, traces, customer data, SQL rows, topology, or similar non-secret sensitive information.";
50
+ readonly secret_exposure: "Exposes credentials, tokens, API keys, cookies, passwords, signing keys, OAuth secrets, session material, or webhook secrets.";
51
+ readonly control_abuse: "Misuses authorized tools or user privileges to send, change, approve, delete, operate, or bypass policy/RBAC without a stronger outcome.";
52
+ readonly system_compromise: "Enables privilege escalation, account takeover, hostile integration or plugin takeover, persistence, lateral movement, attacker webhook registration, or code/plugin execution.";
53
+ readonly service_disruption: "Causes downtime, lockout, degradation, alert suppression, destructive loops, resource exhaustion, cost spikes, or hidden outage evidence.";
54
+ };
55
+ declare function isPrimaryOutcome(value: unknown): value is KnownPrimaryOutcome;
56
+ declare function isHarmfulOutcome(value: unknown): value is KnownHarmfulOutcome;
57
+ declare function normalizePrimaryOutcome(value: unknown, fieldName?: string): PrimaryOutcome;
58
+ declare function normalizeHarmfulOutcome(value: unknown, fieldName?: string): HarmfulOutcome;
59
+ declare function normalizeHarmfulOutcomeMap(values: unknown, fieldName: string): Readonly<Partial<Record<HarmfulOutcome, number>>> | undefined;
60
+
29
61
  type Prediction = "BENIGN" | "MALICIOUS";
30
62
  interface BlockResult {
31
63
  readonly prediction: Prediction;
32
64
  readonly score: number;
33
65
  readonly threshold: number;
34
- readonly primaryOutcome?: string;
35
- readonly outcomeScores?: Readonly<Record<string, number>>;
36
- readonly detectorScores?: Readonly<Record<string, number>>;
37
- readonly detectorCounts?: Readonly<Record<string, number>>;
66
+ readonly primaryOutcome?: PrimaryOutcome;
67
+ readonly outcomeScores?: Readonly<Partial<Record<HarmfulOutcome, number>>>;
68
+ readonly detectorScores?: Readonly<Partial<Record<HarmfulOutcome, number>>>;
69
+ readonly detectorCounts?: Readonly<Partial<Record<HarmfulOutcome, number>>>;
38
70
  }
39
71
  interface FirewallOptions {
40
72
  apiKey: string;
@@ -162,4 +194,4 @@ declare class Firewall {
162
194
  private classifySingleChunk;
163
195
  }
164
196
 
165
- export { ALL_HOOKS as A, type BlockResult as B, type ClassificationMetadata as C, DEFAULT_CHUNK_CONCURRENCY as D, FIREWALL_HOOK_TO_LABEL as F, HookLabel as H, INPUT_HOOKS as I, type LangChainAdapterOptions as L, type MiddlewareOptions as M, OUTPUT_HOOKS as O, type Prediction as P, type ClassifyBatchOptions as a, type ClassifyEvent as b, type ClassifyOptions as c, DEFAULT_HOOKS as d, DEFAULT_TIMEOUT_MS as e, Firewall as f, FirewallHook as g, type FirewallMiddleware as h, type FirewallOptions as i, type LangChainFirewallHandler as j, prependToolName as k, createMiddleware as l, prependHook as p, resolveHooks as r };
197
+ export { ALL_HOOKS as A, type BlockResult as B, type ClassificationMetadata as C, DEFAULT_CHUNK_CONCURRENCY as D, FIREWALL_HOOK_TO_LABEL as F, HookLabel as H, INPUT_HOOKS as I, type KnownHarmfulOutcome as K, type LangChainAdapterOptions as L, type MiddlewareOptions as M, OUTCOME_DESCRIPTIONS as O, PRIMARY_OUTCOMES as P, type UnknownOutcome as U, type ClassifyBatchOptions as a, type ClassifyEvent as b, type ClassifyOptions as c, DEFAULT_HOOKS as d, DEFAULT_TIMEOUT_MS as e, Firewall as f, FirewallHook as g, type FirewallMiddleware as h, type FirewallOptions as i, HARMFUL_OUTCOMES as j, type HarmfulOutcome as k, type KnownPrimaryOutcome as l, type LangChainFirewallHandler as m, OUTPUT_HOOKS as n, Outcome as o, type Prediction as p, type PrimaryOutcome as q, isHarmfulOutcome as r, isPrimaryOutcome as s, normalizeHarmfulOutcome as t, normalizeHarmfulOutcomeMap as u, normalizePrimaryOutcome as v, prependHook as w, prependToolName as x, resolveHooks as y, createMiddleware as z };
package/dist/index.cjs CHANGED
@@ -437,14 +437,23 @@ __export(src_exports, {
437
437
  Firewall: () => Firewall,
438
438
  FirewallBlockedException: () => FirewallBlockedException,
439
439
  FirewallHook: () => FirewallHook,
440
+ HARMFUL_OUTCOMES: () => HARMFUL_OUTCOMES,
440
441
  HookLabel: () => HookLabel,
441
442
  INPUT_HOOKS: () => INPUT_HOOKS,
442
443
  MAX_INPUT_CHARS: () => MAX_INPUT_CHARS,
443
444
  MAX_INPUT_TOKENS: () => MAX_INPUT_TOKENS,
445
+ OUTCOME_DESCRIPTIONS: () => OUTCOME_DESCRIPTIONS,
444
446
  OUTPUT_HOOKS: () => OUTPUT_HOOKS,
447
+ Outcome: () => Outcome,
448
+ PRIMARY_OUTCOMES: () => PRIMARY_OUTCOMES,
445
449
  PromptBlockedException: () => PromptBlockedException,
446
450
  SilmarilApiError: () => SilmarilApiError,
447
451
  chunkText: () => chunkText,
452
+ isHarmfulOutcome: () => isHarmfulOutcome,
453
+ isPrimaryOutcome: () => isPrimaryOutcome,
454
+ normalizeHarmfulOutcome: () => normalizeHarmfulOutcome,
455
+ normalizeHarmfulOutcomeMap: () => normalizeHarmfulOutcomeMap,
456
+ normalizePrimaryOutcome: () => normalizePrimaryOutcome,
448
457
  prependHook: () => prependHook,
449
458
  prependToolName: () => prependToolName,
450
459
  resolveHooks: () => resolveHooks,
@@ -744,7 +753,79 @@ function chunkText(text) {
744
753
 
745
754
  // src/firewall.ts
746
755
  init_exceptions();
747
- var SDK_VERSION = "0.4.1";
756
+
757
+ // src/outcomes.ts
758
+ var Outcome = {
759
+ Benign: "benign",
760
+ InformationDisclosure: "information_disclosure",
761
+ SecretExposure: "secret_exposure",
762
+ ControlAbuse: "control_abuse",
763
+ SystemCompromise: "system_compromise",
764
+ ServiceDisruption: "service_disruption"
765
+ };
766
+ var PRIMARY_OUTCOMES = [
767
+ Outcome.Benign,
768
+ Outcome.InformationDisclosure,
769
+ Outcome.SecretExposure,
770
+ Outcome.ControlAbuse,
771
+ Outcome.SystemCompromise,
772
+ Outcome.ServiceDisruption
773
+ ];
774
+ var HARMFUL_OUTCOMES = [
775
+ Outcome.InformationDisclosure,
776
+ Outcome.SecretExposure,
777
+ Outcome.ControlAbuse,
778
+ Outcome.SystemCompromise,
779
+ Outcome.ServiceDisruption
780
+ ];
781
+ var OUTCOME_DESCRIPTIONS = {
782
+ [Outcome.Benign]: "No harmful firewall outcome detected.",
783
+ [Outcome.InformationDisclosure]: "Exposes private data, documents, internal context, logs, traces, customer data, SQL rows, topology, or similar non-secret sensitive information.",
784
+ [Outcome.SecretExposure]: "Exposes credentials, tokens, API keys, cookies, passwords, signing keys, OAuth secrets, session material, or webhook secrets.",
785
+ [Outcome.ControlAbuse]: "Misuses authorized tools or user privileges to send, change, approve, delete, operate, or bypass policy/RBAC without a stronger outcome.",
786
+ [Outcome.SystemCompromise]: "Enables privilege escalation, account takeover, hostile integration or plugin takeover, persistence, lateral movement, attacker webhook registration, or code/plugin execution.",
787
+ [Outcome.ServiceDisruption]: "Causes downtime, lockout, degradation, alert suppression, destructive loops, resource exhaustion, cost spikes, or hidden outage evidence."
788
+ };
789
+ var PRIMARY_OUTCOME_SET = new Set(PRIMARY_OUTCOMES);
790
+ var HARMFUL_OUTCOME_SET = new Set(HARMFUL_OUTCOMES);
791
+ function isPrimaryOutcome(value) {
792
+ return typeof value === "string" && PRIMARY_OUTCOME_SET.has(value);
793
+ }
794
+ function isHarmfulOutcome(value) {
795
+ return typeof value === "string" && HARMFUL_OUTCOME_SET.has(value);
796
+ }
797
+ function normalizePrimaryOutcome(value, fieldName = "primary_outcome") {
798
+ if (typeof value !== "string") {
799
+ throw new Error(`Firewall: invalid ${fieldName} ${JSON.stringify(value)}`);
800
+ }
801
+ return isPrimaryOutcome(value) ? value : value;
802
+ }
803
+ function normalizeHarmfulOutcome(value, fieldName = "outcome") {
804
+ if (typeof value !== "string" || value === Outcome.Benign) {
805
+ throw new Error(`Firewall: invalid ${fieldName} ${JSON.stringify(value)}`);
806
+ }
807
+ return isHarmfulOutcome(value) ? value : value;
808
+ }
809
+ function normalizeHarmfulOutcomeMap(values, fieldName) {
810
+ if (values === void 0 || values === null) {
811
+ return void 0;
812
+ }
813
+ if (typeof values !== "object" || Array.isArray(values)) {
814
+ throw new Error(`Firewall: invalid ${fieldName} ${JSON.stringify(values)}`);
815
+ }
816
+ const out = {};
817
+ for (const [key, value] of Object.entries(values)) {
818
+ const normalizedKey = normalizeHarmfulOutcome(key, `${fieldName} key`);
819
+ if (typeof value !== "number") {
820
+ throw new Error(`Firewall: invalid ${fieldName} value for ${JSON.stringify(key)}`);
821
+ }
822
+ out[normalizedKey] = value;
823
+ }
824
+ return Object.freeze(out);
825
+ }
826
+
827
+ // src/firewall.ts
828
+ var SDK_VERSION = "0.4.2";
748
829
  var DEFAULT_TIMEOUT_MS = 1e4;
749
830
  var DEFAULT_CHUNK_CONCURRENCY = 8;
750
831
  var DEFAULT_MAX_RETRIES = 5;
@@ -757,22 +838,25 @@ function blockResultFromResponse(data) {
757
838
  threshold: Number(data.threshold)
758
839
  };
759
840
  if (data.primary_outcome !== void 0) {
760
- result.primaryOutcome = data.primary_outcome;
841
+ result.primaryOutcome = normalizePrimaryOutcome(data.primary_outcome);
761
842
  }
762
843
  if (data.outcome_scores !== void 0) {
763
- result.outcomeScores = Object.freeze(
764
- Object.fromEntries(Object.entries(data.outcome_scores).map(([k, v]) => [k, Number(v)]))
765
- );
844
+ const outcomeScores = normalizeHarmfulOutcomeMap(data.outcome_scores, "outcome_scores");
845
+ if (outcomeScores !== void 0) {
846
+ result.outcomeScores = outcomeScores;
847
+ }
766
848
  }
767
849
  if (data.detector_scores !== void 0) {
768
- result.detectorScores = Object.freeze(
769
- Object.fromEntries(Object.entries(data.detector_scores).map(([k, v]) => [k, Number(v)]))
770
- );
850
+ const detectorScores = normalizeHarmfulOutcomeMap(data.detector_scores, "detector_scores");
851
+ if (detectorScores !== void 0) {
852
+ result.detectorScores = detectorScores;
853
+ }
771
854
  }
772
855
  if (data.detector_counts !== void 0) {
773
- result.detectorCounts = Object.freeze(
774
- Object.fromEntries(Object.entries(data.detector_counts).map(([k, v]) => [k, Number(v)]))
775
- );
856
+ const detectorCounts = normalizeHarmfulOutcomeMap(data.detector_counts, "detector_counts");
857
+ if (detectorCounts !== void 0) {
858
+ result.detectorCounts = detectorCounts;
859
+ }
776
860
  }
777
861
  return Object.freeze(result);
778
862
  }
@@ -1017,14 +1101,23 @@ init_hooks();
1017
1101
  Firewall,
1018
1102
  FirewallBlockedException,
1019
1103
  FirewallHook,
1104
+ HARMFUL_OUTCOMES,
1020
1105
  HookLabel,
1021
1106
  INPUT_HOOKS,
1022
1107
  MAX_INPUT_CHARS,
1023
1108
  MAX_INPUT_TOKENS,
1109
+ OUTCOME_DESCRIPTIONS,
1024
1110
  OUTPUT_HOOKS,
1111
+ Outcome,
1112
+ PRIMARY_OUTCOMES,
1025
1113
  PromptBlockedException,
1026
1114
  SilmarilApiError,
1027
1115
  chunkText,
1116
+ isHarmfulOutcome,
1117
+ isPrimaryOutcome,
1118
+ normalizeHarmfulOutcome,
1119
+ normalizeHarmfulOutcomeMap,
1120
+ normalizePrimaryOutcome,
1028
1121
  prependHook,
1029
1122
  prependToolName,
1030
1123
  resolveHooks,