@codebam/jev-guardrails 0.1.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/LICENSE +21 -0
- package/README.md +180 -0
- package/dist/batteries.d.ts +12 -0
- package/dist/batteries.d.ts.map +1 -0
- package/dist/batteries.js +170 -0
- package/dist/batteries.js.map +1 -0
- package/dist/cache.d.ts +26 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +46 -0
- package/dist/cache.js.map +1 -0
- package/dist/client.d.ts +65 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +197 -0
- package/dist/client.js.map +1 -0
- package/dist/guardrails.d.ts +58 -0
- package/dist/guardrails.d.ts.map +1 -0
- package/dist/guardrails.js +386 -0
- package/dist/guardrails.js.map +1 -0
- package/dist/heuristics.d.ts +33 -0
- package/dist/heuristics.d.ts.map +1 -0
- package/dist/heuristics.js +370 -0
- package/dist/heuristics.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/openrouter.d.ts +65 -0
- package/dist/openrouter.d.ts.map +1 -0
- package/dist/openrouter.js +205 -0
- package/dist/openrouter.js.map +1 -0
- package/dist/policies.d.ts +48 -0
- package/dist/policies.d.ts.map +1 -0
- package/dist/policies.js +167 -0
- package/dist/policies.js.map +1 -0
- package/dist/redact.d.ts +18 -0
- package/dist/redact.d.ts.map +1 -0
- package/dist/redact.js +124 -0
- package/dist/redact.js.map +1 -0
- package/dist/render.d.ts +26 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +90 -0
- package/dist/render.js.map +1 -0
- package/dist/types.d.ts +329 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/util.d.ts +42 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +102 -0
- package/dist/util.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/** Default endpoint. */
|
|
2
|
+
export const OPENROUTER_DECISIONS_ENDPOINT = 'https://openrouter.ai/api/alpha/decisions';
|
|
3
|
+
/** Default OpenRouter model alias for the latest Jev. */
|
|
4
|
+
export const OPENROUTER_DEFAULT_MODEL = '~typesafe/jev-latest';
|
|
5
|
+
/** Friendly model names mapped to OpenRouter slugs. */
|
|
6
|
+
const OPENROUTER_MODEL_ALIASES = {
|
|
7
|
+
'jev-latest': OPENROUTER_DEFAULT_MODEL,
|
|
8
|
+
'typesafe/jev-latest': OPENROUTER_DEFAULT_MODEL,
|
|
9
|
+
'~typesafe/jev-latest': OPENROUTER_DEFAULT_MODEL,
|
|
10
|
+
'jev-1.13': 'typesafe/jev-1.13',
|
|
11
|
+
'typesafe/jev-1.13': 'typesafe/jev-1.13',
|
|
12
|
+
};
|
|
13
|
+
/** Error raised for a non-2xx OpenRouter response after retries. */
|
|
14
|
+
export class OpenRouterError extends Error {
|
|
15
|
+
status;
|
|
16
|
+
body;
|
|
17
|
+
constructor(status, message, body = '') {
|
|
18
|
+
super(message);
|
|
19
|
+
this.name = 'OpenRouterError';
|
|
20
|
+
this.status = status;
|
|
21
|
+
this.body = body;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const DEFAULT_RETRY = {
|
|
25
|
+
maxRetries: 2,
|
|
26
|
+
backoffInitialMs: 500,
|
|
27
|
+
backoffMaxMs: 5000,
|
|
28
|
+
backoffJitter: 0.25,
|
|
29
|
+
httpStatuses: new Set([408, 409, 425, 429, 500, 502, 503, 504, 529]),
|
|
30
|
+
respectRetryAfter: true,
|
|
31
|
+
maxRetryAfterMs: 60000,
|
|
32
|
+
apiConnectionError: true,
|
|
33
|
+
apiTimeoutError: true,
|
|
34
|
+
};
|
|
35
|
+
/** Resolve a friendly Jev name to an OpenRouter model slug. */
|
|
36
|
+
export function normalizeOpenRouterModel(model) {
|
|
37
|
+
const trimmed = model?.trim() ?? '';
|
|
38
|
+
if (trimmed.length === 0)
|
|
39
|
+
return OPENROUTER_DEFAULT_MODEL;
|
|
40
|
+
const alias = OPENROUTER_MODEL_ALIASES[trimmed.toLowerCase()];
|
|
41
|
+
if (alias !== undefined)
|
|
42
|
+
return alias;
|
|
43
|
+
if (trimmed.includes('/'))
|
|
44
|
+
return trimmed;
|
|
45
|
+
return `typesafe/${trimmed}`;
|
|
46
|
+
}
|
|
47
|
+
/** Resolve a caller base URL to the exact Decisions endpoint. */
|
|
48
|
+
export function resolveOpenRouterEndpoint(baseURL) {
|
|
49
|
+
const trimmed = baseURL?.trim().replace(/\/+$/, '') ?? '';
|
|
50
|
+
if (trimmed.length === 0)
|
|
51
|
+
return OPENROUTER_DECISIONS_ENDPOINT;
|
|
52
|
+
if (trimmed.endsWith('/decisions'))
|
|
53
|
+
return trimmed;
|
|
54
|
+
if (trimmed.endsWith('/api/alpha'))
|
|
55
|
+
return `${trimmed}/decisions`;
|
|
56
|
+
if (!/\/api\//.test(trimmed))
|
|
57
|
+
return `${trimmed}/api/alpha/decisions`;
|
|
58
|
+
return trimmed;
|
|
59
|
+
}
|
|
60
|
+
/** OpenRouter Decisions transport implementing the library's `JevTransport`. */
|
|
61
|
+
export class OpenRouterDecisionsTransport {
|
|
62
|
+
endpoint;
|
|
63
|
+
model;
|
|
64
|
+
apiKey;
|
|
65
|
+
fetchImpl;
|
|
66
|
+
retry;
|
|
67
|
+
sessionId;
|
|
68
|
+
headers;
|
|
69
|
+
constructor(options) {
|
|
70
|
+
if (options.apiKey.trim().length === 0) {
|
|
71
|
+
throw new OpenRouterError(401, 'OpenRouter API key is missing');
|
|
72
|
+
}
|
|
73
|
+
this.endpoint = resolveOpenRouterEndpoint(options.baseURL);
|
|
74
|
+
this.model = options.model?.trim() ?? OPENROUTER_DEFAULT_MODEL;
|
|
75
|
+
this.apiKey = options.apiKey;
|
|
76
|
+
this.fetchImpl = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
77
|
+
this.retry = { ...DEFAULT_RETRY, ...options.retry, httpStatuses: options.retry?.httpStatuses ?? DEFAULT_RETRY.httpStatuses };
|
|
78
|
+
this.sessionId = options.sessionId;
|
|
79
|
+
this.headers = {
|
|
80
|
+
...(options.referer !== undefined ? { 'HTTP-Referer': options.referer } : {}),
|
|
81
|
+
...(options.title !== undefined ? { 'X-Title': options.title } : {}),
|
|
82
|
+
...(options.headers ?? {}),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/** Submit one Decisions request and return the normalized response. */
|
|
86
|
+
async systemOne(request, options = {}) {
|
|
87
|
+
const model = normalizeOpenRouterModel(request.model ?? this.model);
|
|
88
|
+
const body = {
|
|
89
|
+
model,
|
|
90
|
+
state: request.state,
|
|
91
|
+
questions: request.questions,
|
|
92
|
+
};
|
|
93
|
+
if (this.sessionId !== undefined)
|
|
94
|
+
body.session_id = this.sessionId;
|
|
95
|
+
let attempt = 0;
|
|
96
|
+
for (;;) {
|
|
97
|
+
const response = await this.fetchOnce(body, options);
|
|
98
|
+
if (response.ok) {
|
|
99
|
+
return (await response.json());
|
|
100
|
+
}
|
|
101
|
+
const text = await response.text().catch(() => '');
|
|
102
|
+
if (attempt < this.retry.maxRetries && this.retry.httpStatuses.has(response.status)) {
|
|
103
|
+
await sleep(this.retryDelay(attempt, response.headers));
|
|
104
|
+
attempt += 1;
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
throw new OpenRouterError(response.status, describeError(response.status, text), text);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
async fetchOnce(body, options) {
|
|
111
|
+
try {
|
|
112
|
+
return await this.fetchImpl(this.endpoint, {
|
|
113
|
+
method: 'POST',
|
|
114
|
+
headers: {
|
|
115
|
+
authorization: `Bearer ${this.apiKey}`,
|
|
116
|
+
'content-type': 'application/json',
|
|
117
|
+
accept: 'application/json',
|
|
118
|
+
...this.headers,
|
|
119
|
+
...(options.headers ?? {}),
|
|
120
|
+
},
|
|
121
|
+
body: JSON.stringify(body),
|
|
122
|
+
...(options.signal !== undefined ? { signal: options.signal } : {}),
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
if (options.signal?.aborted || (error instanceof Error && error.name === 'AbortError'))
|
|
127
|
+
throw error;
|
|
128
|
+
const retry = this.retry;
|
|
129
|
+
if (retry.apiConnectionError) {
|
|
130
|
+
// One bounded connection-retry loop; the abort check above keeps
|
|
131
|
+
// cancellation immediate.
|
|
132
|
+
let attempt = 0;
|
|
133
|
+
while (attempt < retry.maxRetries) {
|
|
134
|
+
await sleep(this.retryDelay(attempt));
|
|
135
|
+
attempt += 1;
|
|
136
|
+
try {
|
|
137
|
+
return await this.fetchImpl(this.endpoint, {
|
|
138
|
+
method: 'POST',
|
|
139
|
+
headers: {
|
|
140
|
+
authorization: `Bearer ${this.apiKey}`,
|
|
141
|
+
'content-type': 'application/json',
|
|
142
|
+
accept: 'application/json',
|
|
143
|
+
...this.headers,
|
|
144
|
+
...(options.headers ?? {}),
|
|
145
|
+
},
|
|
146
|
+
body: JSON.stringify(body),
|
|
147
|
+
...(options.signal !== undefined ? { signal: options.signal } : {}),
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
catch (retryError) {
|
|
151
|
+
if (options.signal?.aborted || (retryError instanceof Error && retryError.name === 'AbortError'))
|
|
152
|
+
throw retryError;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
retryDelay(attempt, headers) {
|
|
160
|
+
if (headers !== undefined && this.retry.respectRetryAfter) {
|
|
161
|
+
const retryAfterMs = parseRetryAfter(headers.get('retry-after'), headers.get('retry-after-ms'));
|
|
162
|
+
if (retryAfterMs !== undefined)
|
|
163
|
+
return Math.min(retryAfterMs, this.retry.maxRetryAfterMs);
|
|
164
|
+
}
|
|
165
|
+
const base = Math.min(this.retry.backoffInitialMs * 2 ** attempt, this.retry.backoffMaxMs);
|
|
166
|
+
const jitter = base * this.retry.backoffJitter * Math.random();
|
|
167
|
+
return Math.max(0, Math.round(base - jitter));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/** Build an OpenRouter Decisions transport. */
|
|
171
|
+
export function createOpenRouterTransport(options) {
|
|
172
|
+
return new OpenRouterDecisionsTransport(options);
|
|
173
|
+
}
|
|
174
|
+
function parseRetryAfter(secondsHeader, msHeader) {
|
|
175
|
+
if (msHeader !== null) {
|
|
176
|
+
const ms = Number(msHeader);
|
|
177
|
+
if (Number.isFinite(ms) && ms >= 0)
|
|
178
|
+
return ms;
|
|
179
|
+
}
|
|
180
|
+
if (secondsHeader !== null) {
|
|
181
|
+
const seconds = Number(secondsHeader);
|
|
182
|
+
if (Number.isFinite(seconds) && seconds >= 0)
|
|
183
|
+
return seconds * 1000;
|
|
184
|
+
const date = Date.parse(secondsHeader);
|
|
185
|
+
if (!Number.isNaN(date))
|
|
186
|
+
return Math.max(0, date - Date.now());
|
|
187
|
+
}
|
|
188
|
+
return undefined;
|
|
189
|
+
}
|
|
190
|
+
function describeError(status, text) {
|
|
191
|
+
try {
|
|
192
|
+
const parsed = JSON.parse(text);
|
|
193
|
+
const message = parsed.error?.message ?? parsed.message;
|
|
194
|
+
if (typeof message === 'string')
|
|
195
|
+
return `OpenRouter Decisions request failed (${status}): ${message}`;
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
// Not JSON; fall through to the raw text.
|
|
199
|
+
}
|
|
200
|
+
return `OpenRouter Decisions request failed (${status})${text.length > 0 ? `: ${text.slice(0, 300)}` : ''}`;
|
|
201
|
+
}
|
|
202
|
+
function sleep(ms) {
|
|
203
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=openrouter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openrouter.js","sourceRoot":"","sources":["../src/openrouter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Probabilities to product actions.
|
|
3
|
+
*
|
|
4
|
+
* TypeSafe answers the questions; this module owns the decision. The same
|
|
5
|
+
* answers under a different policy are a different product, so every policy
|
|
6
|
+
* field is explicit and overridable.
|
|
7
|
+
*
|
|
8
|
+
* @module @codebam/jev-guardrails/policies
|
|
9
|
+
*/
|
|
10
|
+
import type { Battery, GuardAction, GuardPolicyInput, GuardSide, ResolvedGuardPolicy } from './types.js';
|
|
11
|
+
/** Highest precedence first. `support` routes to a crisis path, not a refusal. */
|
|
12
|
+
export declare const DEFAULT_PRECEDENCE: readonly GuardAction[];
|
|
13
|
+
/** Default action map for the text-input battery. */
|
|
14
|
+
export declare const INPUT_ACTIONS: Record<string, GuardAction | null>;
|
|
15
|
+
/** Default action map for the model-output battery. */
|
|
16
|
+
export declare const OUTPUT_ACTIONS: Record<string, GuardAction | null>;
|
|
17
|
+
/** Default action map for untrusted text that entered the model context. */
|
|
18
|
+
export declare const OBSERVATION_ACTIONS: Record<string, GuardAction | null>;
|
|
19
|
+
/** Default action map for a proposed agent action. */
|
|
20
|
+
export declare const ACTION_ACTIONS: Record<string, GuardAction | null>;
|
|
21
|
+
/** Default action map per side. */
|
|
22
|
+
export declare const DEFAULT_ACTIONS: Record<GuardSide, Record<string, GuardAction | null>>;
|
|
23
|
+
/** Merge a caller policy over a battery's defaults. */
|
|
24
|
+
export declare function resolvePolicy(side: GuardSide, overrides: GuardPolicyInput | undefined, battery: Battery): ResolvedGuardPolicy;
|
|
25
|
+
/** One triggered reason and its candidate action. */
|
|
26
|
+
export interface TriggeredHazard {
|
|
27
|
+
name: string;
|
|
28
|
+
probability: number;
|
|
29
|
+
action: GuardAction;
|
|
30
|
+
reason: string;
|
|
31
|
+
}
|
|
32
|
+
/** The complete route recommendation from one set of hazard probabilities. */
|
|
33
|
+
export interface RouteResult {
|
|
34
|
+
action: GuardAction;
|
|
35
|
+
reasons: string[];
|
|
36
|
+
triggered: TriggeredHazard[];
|
|
37
|
+
/** True when a severity score upgraded at least one review to a block. */
|
|
38
|
+
severityEscalated: boolean;
|
|
39
|
+
}
|
|
40
|
+
/** The pure routing function: hazards + severity + policy -> one action. */
|
|
41
|
+
export declare function routePolicy(input: {
|
|
42
|
+
hazards: Record<string, number>;
|
|
43
|
+
severity?: number;
|
|
44
|
+
policy: ResolvedGuardPolicy;
|
|
45
|
+
}): RouteResult;
|
|
46
|
+
/** A concise, model-readable summary of the top hazards in a decision. */
|
|
47
|
+
export declare function summarizeHazards(hazards: Record<string, number>, labels?: Record<string, string>): string;
|
|
48
|
+
//# sourceMappingURL=policies.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policies.d.ts","sourceRoot":"","sources":["../src/policies.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EACV,OAAO,EACP,WAAW,EACX,gBAAgB,EAChB,SAAS,EACT,mBAAmB,EACpB,MAAM,YAAY,CAAA;AAGnB,kFAAkF;AAClF,eAAO,MAAM,kBAAkB,EAAE,SAAS,WAAW,EAA4C,CAAA;AAEjG,qDAAqD;AACrD,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAK5D,CAAA;AAED,uDAAuD;AACvD,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAK7D,CAAA;AAED,4EAA4E;AAC5E,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAOlE,CAAA;AAED,sDAAsD;AACtD,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAQ7D,CAAA;AAED,mCAAmC;AACnC,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC,CAKjF,CAAA;AAED,uDAAuD;AACvD,wBAAgB,aAAa,CAC3B,IAAI,EAAE,SAAS,EACf,SAAS,EAAE,gBAAgB,GAAG,SAAS,EACvC,OAAO,EAAE,OAAO,GACf,mBAAmB,CA8BrB;AAgBD,qDAAqD;AACrD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,WAAW,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,8EAA8E;AAC9E,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,WAAW,CAAA;IACnB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,SAAS,EAAE,eAAe,EAAE,CAAA;IAC5B,0EAA0E;IAC1E,iBAAiB,EAAE,OAAO,CAAA;CAC3B;AAED,4EAA4E;AAC5E,wBAAgB,WAAW,CAAC,KAAK,EAAE;IACjC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,mBAAmB,CAAA;CAC5B,GAAG,WAAW,CAiEd;AAOD,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAClC,MAAM,CASR"}
|
package/dist/policies.js
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { formatP } from './util.js';
|
|
2
|
+
/** Highest precedence first. `support` routes to a crisis path, not a refusal. */
|
|
3
|
+
export const DEFAULT_PRECEDENCE = ['support', 'block', 'review', 'allow'];
|
|
4
|
+
/** Default action map for the text-input battery. */
|
|
5
|
+
export const INPUT_ACTIONS = {
|
|
6
|
+
jailbreak: 'block',
|
|
7
|
+
harmful_request: 'block',
|
|
8
|
+
medical_advice: 'review',
|
|
9
|
+
self_harm: 'support',
|
|
10
|
+
};
|
|
11
|
+
/** Default action map for the model-output battery. */
|
|
12
|
+
export const OUTPUT_ACTIONS = {
|
|
13
|
+
broke_policy: 'block',
|
|
14
|
+
harmful_request: 'block',
|
|
15
|
+
medical_advice: 'review',
|
|
16
|
+
self_harm: 'support',
|
|
17
|
+
};
|
|
18
|
+
/** Default action map for untrusted text that entered the model context. */
|
|
19
|
+
export const OBSERVATION_ACTIONS = {
|
|
20
|
+
injection: 'block',
|
|
21
|
+
destructive: 'block',
|
|
22
|
+
exfiltration: 'block',
|
|
23
|
+
secrets: 'review',
|
|
24
|
+
hidden: 'review',
|
|
25
|
+
urgency: 'review',
|
|
26
|
+
};
|
|
27
|
+
/** Default action map for a proposed agent action. */
|
|
28
|
+
export const ACTION_ACTIONS = {
|
|
29
|
+
destructive: 'block',
|
|
30
|
+
exfiltration: 'block',
|
|
31
|
+
remote_code: 'block',
|
|
32
|
+
weakens_security: 'block',
|
|
33
|
+
credential_access: 'review',
|
|
34
|
+
outside_scope: 'review',
|
|
35
|
+
consequential: 'review',
|
|
36
|
+
};
|
|
37
|
+
/** Default action map per side. */
|
|
38
|
+
export const DEFAULT_ACTIONS = {
|
|
39
|
+
input: INPUT_ACTIONS,
|
|
40
|
+
output: OUTPUT_ACTIONS,
|
|
41
|
+
observation: OBSERVATION_ACTIONS,
|
|
42
|
+
action: ACTION_ACTIONS,
|
|
43
|
+
};
|
|
44
|
+
/** Merge a caller policy over a battery's defaults. */
|
|
45
|
+
export function resolvePolicy(side, overrides, battery) {
|
|
46
|
+
const baseActions = battery.defaultActions ?? DEFAULT_ACTIONS[side];
|
|
47
|
+
const actions = { ...baseActions };
|
|
48
|
+
if (overrides?.actions) {
|
|
49
|
+
for (const [name, action] of Object.entries(overrides.actions))
|
|
50
|
+
actions[name] = action;
|
|
51
|
+
}
|
|
52
|
+
const precedence = overrides?.precedence ?? DEFAULT_PRECEDENCE;
|
|
53
|
+
if (precedence.length === 0)
|
|
54
|
+
throw new Error('jev-guardrails: policy precedence must not be empty');
|
|
55
|
+
const reviewThreshold = requireProbability(overrides?.reviewThreshold ?? 0.35, 'reviewThreshold');
|
|
56
|
+
const actionThreshold = requireProbability(overrides?.actionThreshold ?? 0.7, 'actionThreshold');
|
|
57
|
+
if (reviewThreshold > actionThreshold) {
|
|
58
|
+
throw new Error('jev-guardrails: reviewThreshold must be less than or equal to actionThreshold');
|
|
59
|
+
}
|
|
60
|
+
const severityReview = requireNonNegative(overrides?.severityReview ?? 1.25, 'severityReview');
|
|
61
|
+
const severityBlock = requireNonNegative(overrides?.severityBlock ?? 2.0, 'severityBlock');
|
|
62
|
+
if (severityReview > severityBlock) {
|
|
63
|
+
throw new Error('jev-guardrails: severityReview must be less than or equal to severityBlock');
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
reviewThreshold,
|
|
67
|
+
actionThreshold,
|
|
68
|
+
severityReview,
|
|
69
|
+
severityBlock,
|
|
70
|
+
actions,
|
|
71
|
+
fallback: overrides?.fallback ?? 'review',
|
|
72
|
+
precedence,
|
|
73
|
+
failMode: overrides?.failMode ?? 'open',
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function requireProbability(value, name) {
|
|
77
|
+
if (!Number.isFinite(value) || value < 0 || value > 1) {
|
|
78
|
+
throw new Error(`jev-guardrails: ${name} must be a probability between 0 and 1`);
|
|
79
|
+
}
|
|
80
|
+
return value;
|
|
81
|
+
}
|
|
82
|
+
function requireNonNegative(value, name) {
|
|
83
|
+
if (!Number.isFinite(value) || value < 0) {
|
|
84
|
+
throw new Error(`jev-guardrails: ${name} must be a non-negative number`);
|
|
85
|
+
}
|
|
86
|
+
return value;
|
|
87
|
+
}
|
|
88
|
+
/** The pure routing function: hazards + severity + policy -> one action. */
|
|
89
|
+
export function routePolicy(input) {
|
|
90
|
+
const { hazards, severity, policy } = input;
|
|
91
|
+
const candidates = [];
|
|
92
|
+
for (const [name, rawProbability] of Object.entries(hazards)) {
|
|
93
|
+
const probability = Number.isFinite(rawProbability) ? rawProbability : 0;
|
|
94
|
+
const configured = policy.actions[name];
|
|
95
|
+
if (configured === null)
|
|
96
|
+
continue;
|
|
97
|
+
if (probability >= policy.actionThreshold) {
|
|
98
|
+
const action = configured ?? policy.fallback;
|
|
99
|
+
candidates.push({
|
|
100
|
+
name,
|
|
101
|
+
probability,
|
|
102
|
+
action,
|
|
103
|
+
reason: `${name} ${formatP(probability)} at or above action threshold -> ${action}`,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
else if (probability >= policy.reviewThreshold) {
|
|
107
|
+
candidates.push({
|
|
108
|
+
name,
|
|
109
|
+
probability,
|
|
110
|
+
action: 'review',
|
|
111
|
+
reason: `${name} ${formatP(probability)} at or above review threshold -> review`,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
let severityEscalated = false;
|
|
116
|
+
if (severity !== undefined && Number.isFinite(severity)) {
|
|
117
|
+
if (severity >= policy.severityBlock) {
|
|
118
|
+
for (const candidate of candidates) {
|
|
119
|
+
if (candidate.action === 'review') {
|
|
120
|
+
candidate.action = 'block';
|
|
121
|
+
candidate.reason = `${candidate.reason}; severity ${severity.toFixed(2)} escalated review to block`;
|
|
122
|
+
severityEscalated = true;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const alreadyBlocking = candidates.some((candidate) => candidate.action === 'block');
|
|
126
|
+
if (!alreadyBlocking) {
|
|
127
|
+
candidates.push({
|
|
128
|
+
name: 'severity',
|
|
129
|
+
probability: 1,
|
|
130
|
+
action: 'block',
|
|
131
|
+
reason: `severity ${severity.toFixed(2)} at or above block threshold -> block`,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else if (severity >= policy.severityReview) {
|
|
136
|
+
candidates.push({
|
|
137
|
+
name: 'severity',
|
|
138
|
+
probability: 1,
|
|
139
|
+
action: 'review',
|
|
140
|
+
reason: `severity ${severity.toFixed(2)} at or above review threshold -> review`,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const action = policy.precedence.find((candidateAction) => candidates.some((candidate) => candidate.action === candidateAction)) ?? 'allow';
|
|
145
|
+
const reasons = candidates
|
|
146
|
+
.filter((candidate) => candidate.action === action || action === 'allow')
|
|
147
|
+
.map((candidate) => candidate.reason)
|
|
148
|
+
.sort((a, b) => actionRank(b, policy) - actionRank(a, policy));
|
|
149
|
+
return { action, reasons, triggered: candidates, severityEscalated };
|
|
150
|
+
}
|
|
151
|
+
function actionRank(reason, policy) {
|
|
152
|
+
const index = policy.precedence.findIndex((action) => reason.includes(`-> ${action}`));
|
|
153
|
+
return index === -1 ? 0 : policy.precedence.length - index;
|
|
154
|
+
}
|
|
155
|
+
/** A concise, model-readable summary of the top hazards in a decision. */
|
|
156
|
+
export function summarizeHazards(hazards, labels = {}) {
|
|
157
|
+
const entries = Object.entries(hazards)
|
|
158
|
+
.filter(([, probability]) => Number.isFinite(probability))
|
|
159
|
+
.sort((a, b) => b[1] - a[1])
|
|
160
|
+
.slice(0, 2);
|
|
161
|
+
if (entries.length === 0)
|
|
162
|
+
return 'no hazard above threshold';
|
|
163
|
+
return entries
|
|
164
|
+
.map(([name, probability]) => `${labels[name] ?? name} ${formatP(probability)}`)
|
|
165
|
+
.join('; ');
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=policies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policies.js","sourceRoot":"","sources":["../src/policies.ts"],"names":[],"mappings":"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"}
|
package/dist/redact.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret redaction for state sent to Jev.
|
|
3
|
+
*
|
|
4
|
+
* Guardrail checks are most useful on realistic input, but prompts and tool
|
|
5
|
+
* arguments often carry credentials. The built-in rules preserve the *shape*
|
|
6
|
+
* that makes a credential dangerous (so the `secrets` and `exfiltration`
|
|
7
|
+
* questions still fire) while replacing the value itself.
|
|
8
|
+
*
|
|
9
|
+
* @module @codebam/jev-guardrails/redact
|
|
10
|
+
*/
|
|
11
|
+
import type { RedactionPattern, RedactorOptions } from './types.js';
|
|
12
|
+
/** Built-in best-effort secret patterns. These are signals, not a scanner. */
|
|
13
|
+
export declare const DEFAULT_SECRET_PATTERNS: RedactionPattern[];
|
|
14
|
+
/** Redact known secret shapes from one string. */
|
|
15
|
+
export declare function redactString(text: string, options?: RedactorOptions): string;
|
|
16
|
+
/** Recursively redact every string in a JSON-like value, preserving its shape. */
|
|
17
|
+
export declare function redactState<T>(state: T, options?: RedactorOptions): T;
|
|
18
|
+
//# sourceMappingURL=redact.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../src/redact.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAGnE,8EAA8E;AAC9E,eAAO,MAAM,uBAAuB,EAAE,gBAAgB,EAwErD,CAAA;AASD,kDAAkD;AAClD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,MAAM,CAiBhF;AAKD,kFAAkF;AAClF,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,GAAE,eAAoB,GAAG,CAAC,CAEzE"}
|
package/dist/redact.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { isRecord } from './util.js';
|
|
2
|
+
/** Built-in best-effort secret patterns. These are signals, not a scanner. */
|
|
3
|
+
export const DEFAULT_SECRET_PATTERNS = [
|
|
4
|
+
{
|
|
5
|
+
name: 'private-key',
|
|
6
|
+
pattern: /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z0-9 ]*PRIVATE KEY-----/g,
|
|
7
|
+
replacement: '[REDACTED:private-key]',
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
name: 'aws-access-key',
|
|
11
|
+
pattern: /\b(?:AKIA|ASIA|AROA|AIPA|ANPA|ANVA|APKA)[0-9A-Z]{16}\b/g,
|
|
12
|
+
replacement: '[REDACTED:aws-access-key]',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
name: 'github-token',
|
|
16
|
+
pattern: /\bgh[pousr]_[A-Za-z0-9]{20,}\b/g,
|
|
17
|
+
replacement: '[REDACTED:github-token]',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'github-pat',
|
|
21
|
+
pattern: /\bgithub_pat_[A-Za-z0-9_]{20,}\b/g,
|
|
22
|
+
replacement: '[REDACTED:github-pat]',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: 'slack-token',
|
|
26
|
+
pattern: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/g,
|
|
27
|
+
replacement: '[REDACTED:slack-token]',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: 'openai-key',
|
|
31
|
+
pattern: /\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\b/g,
|
|
32
|
+
replacement: '[REDACTED:api-key]',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: 'anthropic-key',
|
|
36
|
+
pattern: /\bsk-ant-[A-Za-z0-9_-]{20,}\b/g,
|
|
37
|
+
replacement: '[REDACTED:api-key]',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: 'google-api-key',
|
|
41
|
+
pattern: /\bAIza[0-9A-Za-z_-]{20,}\b/g,
|
|
42
|
+
replacement: '[REDACTED:api-key]',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: 'stripe-key',
|
|
46
|
+
pattern: /\b(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{16,}\b/g,
|
|
47
|
+
replacement: '[REDACTED:stripe-key]',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: 'jwt',
|
|
51
|
+
pattern: /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g,
|
|
52
|
+
replacement: '[REDACTED:jwt]',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: 'bearer-token',
|
|
56
|
+
pattern: /\b(Bearer\s+)([A-Za-z0-9._~+/=-]{16,})\b/gi,
|
|
57
|
+
replacement: (_match, _scheme) => `Bearer [REDACTED:bearer-token]`,
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: 'basic-auth',
|
|
61
|
+
pattern: /\b(Basic\s+)([A-Za-z0-9+/=]{12,})\b/gi,
|
|
62
|
+
replacement: (_match, _scheme) => `Basic [REDACTED:basic-auth]`,
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: 'url-password',
|
|
66
|
+
pattern: /(\b[a-z][a-z0-9+.-]*:\/\/[^\s/:@]+:)([^\s/@]+)(@)/gi,
|
|
67
|
+
replacement: (_match, prefix, _password, suffix) => `${prefix}[REDACTED:url-password]${suffix}`,
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: 'assigned-secret',
|
|
71
|
+
pattern: /([A-Za-z0-9_.-]*(?:api[_-]?key|apikey|client[_-]?secret|secret|token|password|passwd|pwd|private[_-]?key))(\s*[:=]\s*)(["']?)([^\s"',;]{8,})(\3)/gi,
|
|
72
|
+
replacement: (_match, key, separator, quote, _value) => `${key}${separator}${quote}[REDACTED:assigned-secret]${quote}`,
|
|
73
|
+
},
|
|
74
|
+
];
|
|
75
|
+
function replacementFor(pattern) {
|
|
76
|
+
if (typeof pattern.replacement === 'function') {
|
|
77
|
+
return pattern.replacement;
|
|
78
|
+
}
|
|
79
|
+
return pattern.replacement ?? `[REDACTED:${pattern.name}]`;
|
|
80
|
+
}
|
|
81
|
+
/** Redact known secret shapes from one string. */
|
|
82
|
+
export function redactString(text, options = {}) {
|
|
83
|
+
const patterns = [
|
|
84
|
+
...(options.secrets === false ? [] : DEFAULT_SECRET_PATTERNS),
|
|
85
|
+
...(options.extraPatterns ?? []),
|
|
86
|
+
];
|
|
87
|
+
let output = text;
|
|
88
|
+
for (const rule of patterns) {
|
|
89
|
+
try {
|
|
90
|
+
const replacement = replacementFor(rule);
|
|
91
|
+
output = typeof replacement === 'string'
|
|
92
|
+
? output.replace(rule.pattern, replacement)
|
|
93
|
+
: output.replace(rule.pattern, replacement);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// A misbehaving custom pattern must never break a safety check.
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return output;
|
|
100
|
+
}
|
|
101
|
+
/** Object keys whose values are secrets even without a recognizable value shape. */
|
|
102
|
+
const SENSITIVE_KEYS = /(?:^|[_-])(?:password|passwd|pwd|secret|token|api_?key|apikey|authorization|auth|cookie|private_?key|client_?secret|access_?key|session_?id)(?:$|[_-])/i;
|
|
103
|
+
/** Recursively redact every string in a JSON-like value, preserving its shape. */
|
|
104
|
+
export function redactState(state, options = {}) {
|
|
105
|
+
return redactValue(state, options);
|
|
106
|
+
}
|
|
107
|
+
function redactValue(value, options, key = '') {
|
|
108
|
+
if (typeof value === 'string') {
|
|
109
|
+
if (SENSITIVE_KEYS.test(key) && value.trim().length > 0 && !value.includes('[REDACTED:')) {
|
|
110
|
+
return '[REDACTED:assigned-secret]';
|
|
111
|
+
}
|
|
112
|
+
return redactString(value, options);
|
|
113
|
+
}
|
|
114
|
+
if (Array.isArray(value))
|
|
115
|
+
return value.map((entry) => redactValue(entry, options, key));
|
|
116
|
+
if (isRecord(value)) {
|
|
117
|
+
const out = {};
|
|
118
|
+
for (const [entryKey, entry] of Object.entries(value))
|
|
119
|
+
out[entryKey] = redactValue(entry, options, entryKey);
|
|
120
|
+
return out;
|
|
121
|
+
}
|
|
122
|
+
return value;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=redact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact.js","sourceRoot":"","sources":["../src/redact.ts"],"names":[],"mappings":"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"}
|
package/dist/render.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Human-readable and model-readable explanations for verdicts.
|
|
3
|
+
*
|
|
4
|
+
* Guardrail messages are themselves instructions to a model, so they are
|
|
5
|
+
* written to be short, specific, and non-negotiable: state the finding, name
|
|
6
|
+
* the consequence, and close the obvious workaround.
|
|
7
|
+
*
|
|
8
|
+
* @module @codebam/jev-guardrails/render
|
|
9
|
+
*/
|
|
10
|
+
import type { GuardVerdict } from './types.js';
|
|
11
|
+
/** Fallback labels for every built-in hazard. */
|
|
12
|
+
export declare const DEFAULT_HAZARD_LABELS: Record<string, string>;
|
|
13
|
+
/** A verdict with or without its final `reason` field. */
|
|
14
|
+
type VerdictView = Omit<GuardVerdict, 'reason'> & {
|
|
15
|
+
reason?: string;
|
|
16
|
+
};
|
|
17
|
+
/** One-line audit summary for logs and callbacks. */
|
|
18
|
+
export declare function describeVerdict(verdict: VerdictView, labels?: Record<string, string>): string;
|
|
19
|
+
/** Reason shown to the model when a tool call or prompt is denied. */
|
|
20
|
+
export declare function modelFacingReason(verdict: VerdictView, labels?: Record<string, string>): string;
|
|
21
|
+
/** Plugin-visible context attached to a conversation when input is flagged but allowed. */
|
|
22
|
+
export declare function guardrailNotice(verdict: VerdictView, labels?: Record<string, string>): string;
|
|
23
|
+
/** Steering message used when a model response is blocked or flagged. */
|
|
24
|
+
export declare function correctionNotice(verdict: VerdictView, labels?: Record<string, string>): string;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAa,YAAY,EAAE,MAAM,YAAY,CAAA;AAGzD,iDAAiD;AACjD,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAkBxD,CAAA;AAED,0DAA0D;AAC1D,KAAK,WAAW,GAAG,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AA0BrE,qDAAqD;AACrD,wBAAgB,eAAe,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAe7F;AAED,sEAAsE;AACtE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAe/F;AAED,2FAA2F;AAC3F,wBAAgB,eAAe,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAI7F;AAED,yEAAyE;AACzE,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAI9F"}
|