theorum 0.1.15 → 1.1.3
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/README.md +241 -98
- package/esm/mod.d.ts +57 -28
- package/esm/mod.js +43 -23
- package/esm/src/cli/commands/bench.js +18 -18
- package/esm/src/cli/commands/fuzz-canary.d.ts +13 -0
- package/esm/src/cli/commands/fuzz-canary.js +191 -0
- package/esm/src/cli/commands/fuzz-guardrails.d.ts +3 -5
- package/esm/src/cli/commands/fuzz-guardrails.js +4 -581
- package/esm/src/cli/commands/guardrails-eval.d.ts +14 -0
- package/esm/src/cli/commands/guardrails-eval.js +15 -0
- package/esm/src/cli/commands/profile.js +35 -15
- package/esm/src/cli/commands/run.d.ts +3 -0
- package/esm/src/cli/commands/run.js +23 -32
- package/esm/src/cli/commands/test.d.ts +10 -1
- package/esm/src/cli/commands/test.js +34 -34
- package/esm/src/cli/event-log.d.ts +19 -0
- package/esm/src/cli/event-log.js +147 -0
- package/esm/src/cli/index.js +57 -11
- package/esm/src/cli/matrix/synthesizer.d.ts +10 -12
- package/esm/src/cli/matrix/synthesizer.js +45 -118
- package/esm/src/guardrails/canary-gate.d.ts +21 -0
- package/esm/src/guardrails/canary-gate.js +32 -0
- package/esm/src/guardrails/canary.d.ts +34 -0
- package/esm/src/guardrails/canary.js +150 -0
- package/esm/src/guardrails/corpus/canary-egress-attacks.d.ts +17 -0
- package/esm/src/guardrails/corpus/canary-egress-attacks.js +151 -0
- package/esm/src/guardrails/corpus/fuzz-inbound.d.ts +11 -0
- package/esm/src/guardrails/corpus/fuzz-inbound.js +213 -0
- package/esm/src/guardrails/corpus/inbound-payloads.d.ts +10 -0
- package/esm/src/guardrails/corpus/inbound-payloads.js +125 -0
- package/esm/src/guardrails/corpus/live-attacks.d.ts +20 -0
- package/esm/src/guardrails/corpus/live-attacks.js +231 -0
- package/esm/src/guardrails/corpus/mod.d.ts +14 -0
- package/esm/src/guardrails/corpus/mod.js +11 -0
- package/esm/src/guardrails/corpus/secrets.d.ts +17 -0
- package/esm/src/guardrails/corpus/secrets.js +17 -0
- package/esm/src/guardrails/corpus/strings.d.ts +28 -0
- package/esm/src/guardrails/corpus/strings.js +34 -0
- package/esm/src/guardrails/corpus/types.d.ts +38 -0
- package/esm/src/guardrails/corpus/types.js +6 -0
- package/esm/src/guardrails/egress.d.ts +32 -0
- package/esm/src/guardrails/egress.js +87 -0
- package/esm/src/guardrails/error.d.ts +14 -23
- package/esm/src/guardrails/error.js +87 -76
- package/esm/src/guardrails/eval/corpus.d.ts +108 -0
- package/esm/src/guardrails/eval/corpus.js +978 -0
- package/esm/src/guardrails/eval/mod.d.ts +51 -0
- package/esm/src/guardrails/eval/mod.js +133 -0
- package/esm/src/guardrails/eval/score.d.ts +66 -0
- package/esm/src/guardrails/eval/score.js +114 -0
- package/esm/src/guardrails/events.d.ts +25 -0
- package/esm/src/guardrails/events.js +56 -0
- package/esm/src/guardrails/hits.d.ts +24 -0
- package/esm/src/guardrails/hits.js +45 -0
- package/esm/src/guardrails/injection.js +28 -5
- package/esm/src/guardrails/lexicon.d.ts +39 -0
- package/esm/src/guardrails/lexicon.js +200 -0
- package/esm/src/guardrails/live-outbound-gate.d.ts +41 -0
- package/esm/src/guardrails/live-outbound-gate.js +222 -0
- package/esm/src/guardrails/mod.d.ts +30 -6
- package/esm/src/guardrails/mod.js +20 -5
- package/esm/src/guardrails/network.d.ts +19 -0
- package/esm/src/guardrails/network.js +234 -0
- package/esm/src/guardrails/policy.d.ts +35 -0
- package/esm/src/guardrails/policy.js +50 -0
- package/esm/src/guardrails/progressive-yield.d.ts +51 -0
- package/esm/src/guardrails/progressive-yield.js +98 -0
- package/esm/src/guardrails/quota.d.ts +17 -3
- package/esm/src/guardrails/quota.js +18 -4
- package/esm/src/guardrails/sanitize.d.ts +45 -19
- package/esm/src/guardrails/sanitize.js +177 -94
- package/esm/src/guardrails/sensitive.js +2 -1
- package/esm/src/guardrails/serialize.d.ts +35 -0
- package/esm/src/guardrails/serialize.js +58 -0
- package/esm/src/guardrails/testing.d.ts +17 -0
- package/esm/src/guardrails/testing.js +13 -0
- package/esm/src/guardrails/theorum-error.d.ts +12 -0
- package/esm/src/guardrails/theorum-error.js +15 -0
- package/esm/src/guardrails/tool-directives.d.ts +48 -0
- package/esm/src/guardrails/tool-directives.js +124 -0
- package/esm/src/guardrails/tool-result.d.ts +93 -0
- package/esm/src/guardrails/tool-result.js +276 -0
- package/esm/src/guardrails/types.d.ts +291 -0
- package/esm/src/guardrails/types.js +72 -0
- package/esm/src/host/client-turn.d.ts +19 -0
- package/esm/src/host/client-turn.js +36 -0
- package/esm/src/host/mint-trace.d.ts +1 -1
- package/esm/src/host/mod.d.ts +5 -3
- package/esm/src/host/mod.js +4 -3
- package/esm/src/kernel/auth/crypto.d.ts +42 -0
- package/esm/src/kernel/auth/crypto.js +106 -0
- package/esm/src/kernel/auth/mod.d.ts +11 -0
- package/esm/src/kernel/auth/mod.js +11 -0
- package/esm/src/kernel/auth/oauth.d.ts +47 -0
- package/esm/src/kernel/auth/oauth.js +278 -0
- package/esm/src/kernel/auth/types.d.ts +133 -0
- package/esm/src/kernel/auth/types.js +13 -0
- package/esm/src/kernel/engine/delta.d.ts +24 -2
- package/esm/src/kernel/engine/delta.js +478 -39
- package/esm/src/kernel/engine/live-inbound.d.ts +21 -0
- package/esm/src/kernel/engine/live-inbound.js +31 -0
- package/esm/src/kernel/engine/live-ingress.d.ts +19 -0
- package/esm/src/kernel/engine/live-ingress.js +47 -0
- package/esm/src/kernel/engine/repair.js +13 -12
- package/esm/src/kernel/engine/runner/gates.d.ts +1 -1
- package/esm/src/kernel/engine/runner/gates.js +130 -43
- package/esm/src/kernel/engine/runner/mod.d.ts +6 -4
- package/esm/src/kernel/engine/runner/mod.js +192 -53
- package/esm/src/kernel/engine/runner/schema-validation.js +3 -3
- package/esm/src/kernel/engine/runner/stages.d.ts +39 -0
- package/esm/src/kernel/engine/runner/stages.js +89 -0
- package/esm/src/kernel/engine/runner/state.d.ts +31 -0
- package/esm/src/kernel/engine/runner/steps.d.ts +1 -1
- package/esm/src/kernel/engine/runner/steps.js +244 -43
- package/esm/src/kernel/engine/runner/stream.d.ts +9 -3
- package/esm/src/kernel/engine/runner/stream.js +140 -44
- package/esm/src/kernel/engine/session/mod.d.ts +25 -0
- package/esm/src/kernel/engine/session/mod.js +557 -0
- package/esm/src/kernel/interaction-parts.d.ts +14 -0
- package/esm/src/kernel/interaction-parts.js +23 -0
- package/esm/src/kernel/mod.d.ts +21 -10
- package/esm/src/kernel/mod.js +11 -8
- package/esm/src/kernel/profile-graph.d.ts +159 -0
- package/esm/src/kernel/profile-graph.js +156 -0
- package/esm/src/kernel/registry/attachments.d.ts +12 -10
- package/esm/src/kernel/registry/attachments.js +33 -27
- package/esm/src/kernel/registry/catalog.d.ts +25 -24
- package/esm/src/kernel/registry/catalog.js +60 -101
- package/esm/src/kernel/registry/ingress.d.ts +9 -4
- package/esm/src/kernel/registry/ingress.js +97 -75
- package/esm/src/kernel/registry/profile-outputs.d.ts +4 -0
- package/esm/src/kernel/registry/profile-outputs.js +8 -0
- package/esm/src/kernel/registry/profiles.d.ts +55 -12
- package/esm/src/kernel/registry/profiles.js +413 -73
- package/esm/src/kernel/registry/provider-request.js +13 -7
- package/esm/src/kernel/registry/resolve.d.ts +8 -8
- package/esm/src/kernel/registry/resolve.js +169 -154
- package/esm/src/kernel/registry/schemas.js +1 -1
- package/esm/src/kernel/registry/sole-model.d.ts +8 -0
- package/esm/src/kernel/registry/sole-model.js +10 -0
- package/esm/src/kernel/registry/system-prompt.d.ts +10 -0
- package/esm/src/kernel/registry/system-prompt.js +40 -0
- package/esm/src/kernel/registry/system-role.d.ts +8 -0
- package/esm/src/kernel/registry/system-role.js +14 -0
- package/esm/src/kernel/registry/vault.d.ts +12 -7
- package/esm/src/kernel/registry/vault.js +32 -10
- package/esm/src/kernel/schema.d.ts +231 -0
- package/esm/src/kernel/schema.js +607 -0
- package/esm/src/kernel/stages.d.ts +175 -0
- package/esm/src/kernel/stages.js +476 -0
- package/esm/src/kernel/stop.d.ts +78 -19
- package/esm/src/kernel/stop.js +51 -16
- package/esm/src/kernel/tools/events.d.ts +41 -0
- package/esm/src/kernel/tools/events.js +71 -0
- package/esm/src/kernel/tools/execute.d.ts +84 -0
- package/esm/src/kernel/tools/execute.js +614 -0
- package/esm/src/kernel/tools/harness.d.ts +8 -0
- package/esm/src/kernel/tools/harness.js +46 -0
- package/esm/src/kernel/tools/invoke.d.ts +10 -0
- package/esm/src/kernel/tools/invoke.js +101 -0
- package/esm/src/kernel/tools/mod.d.ts +13 -0
- package/esm/src/kernel/tools/mod.js +11 -0
- package/esm/src/kernel/tools/permission.d.ts +15 -0
- package/esm/src/kernel/tools/permission.js +47 -0
- package/esm/src/kernel/tools/project.d.ts +12 -0
- package/esm/src/kernel/tools/project.js +36 -0
- package/esm/src/kernel/tools/registry.d.ts +23 -0
- package/esm/src/kernel/tools/registry.js +81 -0
- package/esm/src/kernel/tools/remote.d.ts +94 -0
- package/esm/src/kernel/tools/remote.js +577 -0
- package/esm/src/kernel/tools/resolve.d.ts +39 -0
- package/esm/src/kernel/tools/resolve.js +283 -0
- package/esm/src/kernel/tools/schema.d.ts +15 -0
- package/esm/src/kernel/tools/schema.js +176 -0
- package/esm/src/kernel/tools/stage-run.d.ts +105 -0
- package/esm/src/kernel/tools/stage-run.js +155 -0
- package/esm/src/kernel/tools/types.d.ts +394 -0
- package/esm/src/kernel/tools/types.js +9 -0
- package/esm/src/kernel/types.d.ts +540 -256
- package/esm/src/kernel/util/find-last.d.ts +2 -0
- package/esm/src/kernel/util/find-last.js +10 -0
- package/esm/src/observability/destinations.d.ts +31 -0
- package/esm/src/observability/destinations.js +67 -0
- package/esm/src/observability/mod.d.ts +10 -3
- package/esm/src/observability/mod.js +6 -2
- package/esm/src/observability/policy.d.ts +27 -0
- package/esm/src/observability/policy.js +80 -0
- package/esm/src/observability/resolve-policy.d.ts +16 -0
- package/esm/src/observability/resolve-policy.js +64 -0
- package/esm/src/observability/trace-attach.d.ts +8 -4
- package/esm/src/observability/trace-attach.js +50 -29
- package/esm/src/observability/trace-record.d.ts +23 -13
- package/esm/src/observability/trace-record.js +96 -39
- package/esm/src/observability/trace-sink.d.ts +19 -0
- package/esm/src/observability/trace-sink.js +10 -0
- package/esm/src/observability/trace-usage.d.ts +10 -3
- package/esm/src/observability/trace-usage.js +70 -17
- package/esm/src/observability/trace.d.ts +18 -7
- package/esm/src/observability/trace.js +34 -17
- package/esm/src/observability/types.d.ts +113 -0
- package/esm/src/observability/types.js +11 -0
- package/esm/src/presets/google/speech-voices.d.ts +11 -0
- package/esm/src/presets/google/speech-voices.js +41 -0
- package/esm/src/presets/google.d.ts +36 -24
- package/esm/src/presets/google.js +50 -63
- package/esm/src/presets/mod.d.ts +2 -2
- package/esm/src/presets/mod.js +1 -1
- package/esm/src/providers/create-provider.d.ts +20 -17
- package/esm/src/providers/create-provider.js +72 -26
- package/esm/src/providers/google/interactions/framing.d.ts +23 -0
- package/esm/src/providers/google/interactions/framing.js +269 -0
- package/esm/src/providers/google/interactions/mod.d.ts +7 -0
- package/esm/src/providers/google/interactions/mod.js +7 -0
- package/esm/src/providers/google/interactions/stream.d.ts +83 -0
- package/esm/src/providers/google/interactions/stream.js +588 -0
- package/esm/src/providers/google/keys.d.ts +26 -0
- package/esm/src/providers/{keys.js → google/keys.js} +19 -31
- package/esm/src/providers/google/live/framing.d.ts +49 -0
- package/esm/src/providers/google/live/framing.js +552 -0
- package/esm/src/providers/google/live/openapi-schema.d.ts +6 -0
- package/esm/src/providers/google/live/openapi-schema.js +46 -0
- package/esm/src/providers/google/live/session.d.ts +25 -0
- package/esm/src/providers/google/live/session.js +134 -0
- package/esm/src/providers/google/live/stream.d.ts +45 -0
- package/esm/src/providers/google/live/stream.js +214 -0
- package/esm/src/providers/google/urls.d.ts +6 -0
- package/esm/src/providers/google/urls.js +6 -0
- package/esm/src/providers/local/local.d.ts +30 -0
- package/esm/src/providers/{local.js → local/local.js} +66 -126
- package/esm/src/providers/local/mod.d.ts +9 -0
- package/esm/src/providers/local/mod.js +9 -0
- package/esm/src/providers/mod.d.ts +6 -3
- package/esm/src/providers/mod.js +3 -1
- package/esm/src/providers/openrouter/cache-control.d.ts +24 -0
- package/esm/src/providers/openrouter/cache-control.js +23 -0
- package/esm/src/providers/openrouter/chat.d.ts +107 -0
- package/esm/src/providers/{openrouter.js → openrouter/chat.js} +117 -231
- package/esm/src/providers/openrouter/image.d.ts +34 -0
- package/esm/src/providers/openrouter/image.js +275 -0
- package/esm/src/providers/openrouter/openai/chat-payload.d.ts +24 -0
- package/esm/src/providers/openrouter/openai/chat-payload.js +82 -0
- package/esm/src/providers/openrouter/openai/compat.d.ts +53 -0
- package/esm/src/providers/openrouter/openai/compat.js +213 -0
- package/esm/src/providers/openrouter/openai/image-payload.d.ts +18 -0
- package/esm/src/providers/openrouter/openai/image-payload.js +90 -0
- package/esm/src/providers/openrouter/openai/sdk-messages.d.ts +22 -0
- package/esm/src/providers/openrouter/openai/sdk-messages.js +122 -0
- package/esm/src/providers/openrouter/resolve-api-key.d.ts +9 -0
- package/esm/src/providers/openrouter/resolve-api-key.js +24 -0
- package/esm/src/providers/openrouter/speech.d.ts +23 -0
- package/esm/src/providers/{speech.js → openrouter/speech.js} +32 -55
- package/esm/src/providers/probe.d.ts +1 -0
- package/esm/src/providers/probe.js +22 -0
- package/esm/src/providers/shared/pcm.d.ts +12 -0
- package/esm/src/providers/{pcm.js → shared/pcm.js} +16 -3
- package/esm/src/providers/shared/sse.d.ts +18 -0
- package/esm/src/providers/shared/sse.js +87 -0
- package/esm/src/providers/shared/tool-args.d.ts +17 -0
- package/esm/src/providers/shared/tool-args.js +45 -0
- package/esm/src/providers/shared/upstream-tap.d.ts +5 -0
- package/esm/src/providers/{google-tap.js → shared/upstream-tap.js} +4 -7
- package/esm/src/providers/shared/upstream-tape.d.ts +6 -0
- package/esm/src/providers/{gemini-tape.js → shared/upstream-tape.js} +12 -22
- package/esm/src/providers/types.d.ts +27 -0
- package/esm/src/providers/types.js +1 -0
- package/package.json +11 -7
- package/docs/cli.md +0 -97
- package/docs/guardrails.md +0 -178
- package/docs/host.md +0 -97
- package/docs/kernel.md +0 -404
- package/docs/observability.md +0 -105
- package/docs/openrouter.md +0 -125
- package/docs/presets-google.md +0 -91
- package/docs/presets.md +0 -88
- package/docs/providers.md +0 -202
- package/docs/streaming.md +0 -96
- package/esm/src/kernel/engine/boundary.d.ts +0 -10
- package/esm/src/kernel/engine/boundary.js +0 -55
- package/esm/src/kernel/engine/runner/tools.d.ts +0 -13
- package/esm/src/kernel/engine/runner/tools.js +0 -198
- package/esm/src/kernel/registry/tools.d.ts +0 -12
- package/esm/src/kernel/registry/tools.js +0 -36
- package/esm/src/providers/expose-for-tests.d.ts +0 -1
- package/esm/src/providers/expose-for-tests.js +0 -25
- package/esm/src/providers/gemini-tape.d.ts +0 -2
- package/esm/src/providers/google-tap.d.ts +0 -3
- package/esm/src/providers/interactions.d.ts +0 -5
- package/esm/src/providers/interactions.js +0 -169
- package/esm/src/providers/keys.d.ts +0 -19
- package/esm/src/providers/local.d.ts +0 -29
- package/esm/src/providers/openrouter-mod.d.ts +0 -13
- package/esm/src/providers/openrouter-mod.js +0 -12
- package/esm/src/providers/openrouter-payload.d.ts +0 -39
- package/esm/src/providers/openrouter-payload.js +0 -195
- package/esm/src/providers/openrouter.d.ts +0 -15
- package/esm/src/providers/pcm.d.ts +0 -7
- package/esm/src/providers/provider.d.ts +0 -15
- package/esm/src/providers/provider.js +0 -202
- package/esm/src/providers/speech.d.ts +0 -23
- package/esm/src/providers/sse.d.ts +0 -7
- package/esm/src/providers/sse.js +0 -55
- package/esm/src/streaming/mod.d.ts +0 -9
- package/esm/src/streaming/mod.js +0 -8
- /package/esm/src/{streaming → host}/readStreamingJsonStringField.d.ts +0 -0
- /package/esm/src/{streaming → host}/readStreamingJsonStringField.js +0 -0
|
@@ -1,60 +1,60 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Request sanitization utilities for THEORUM.
|
|
3
3
|
*
|
|
4
|
-
* Sanitization removes inbound prompt-injection spans and sensitive-data spans
|
|
5
|
-
* according to the active profile guardrail flags. The host remains responsible
|
|
6
|
-
* for domain policy.
|
|
7
|
-
*
|
|
8
4
|
* @module
|
|
9
5
|
*/
|
|
10
|
-
import { mapStrings } from '../kernel/engine/tree.js';
|
|
11
6
|
import { sanitizeTurnBlobsForProfile } from '../kernel/registry/attachments.js';
|
|
12
7
|
import { getProfile } from '../kernel/registry/profiles.js';
|
|
13
8
|
import { applySpans } from '../observability/spans.js';
|
|
9
|
+
import { guardrailFromHits } from './events.js';
|
|
10
|
+
import { hitFromSpan } from './hits.js';
|
|
14
11
|
import { injectionSpans } from './injection.js';
|
|
12
|
+
import { detectionForTrust, resolveGuardrailPolicy } from './policy.js';
|
|
15
13
|
import { sensitiveSpans } from './sensitive.js';
|
|
16
|
-
/**
|
|
17
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Detect and redact injection / sensitive spans. Returns hits for observability
|
|
16
|
+
* (rule + offsets + optional `match` preview for debugging).
|
|
17
|
+
*/
|
|
18
|
+
function detectText(text, options) {
|
|
18
19
|
const sanitizeInput = options?.sanitizeInput ?? true;
|
|
19
20
|
const redactSensitive = options?.redactSensitive ?? true;
|
|
20
21
|
if (!sanitizeInput && !redactSensitive) {
|
|
21
|
-
return text;
|
|
22
|
+
return { text, hits: [] };
|
|
22
23
|
}
|
|
23
24
|
const spans = [
|
|
24
25
|
...(sanitizeInput ? injectionSpans(text) : []),
|
|
25
26
|
...(redactSensitive ? sensitiveSpans(text) : []),
|
|
26
27
|
];
|
|
27
|
-
|
|
28
|
+
const hits = spans.map((span) => hitFromSpan(text, span, span.kind === 'injection' ? 'sanitize.injection' : 'sanitize.sensitive', 'high'));
|
|
29
|
+
return { text: applySpans(text, spans), hits };
|
|
28
30
|
}
|
|
29
|
-
/**
|
|
30
|
-
|
|
31
|
+
/** Sanitize one text value using prompt-injection and sensitive-data detectors. */
|
|
32
|
+
function sanitizeText(text, options) {
|
|
33
|
+
return detectText(text, options).text;
|
|
34
|
+
}
|
|
35
|
+
/** Redact only sensitive data (credentials, PII) — skip injection patterns. */
|
|
31
36
|
function redactSensitiveOnly(text) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
37
|
+
return detectText(text, { sanitizeInput: false, redactSensitive: true }).text;
|
|
38
|
+
}
|
|
39
|
+
function appendHits(into, hits) {
|
|
40
|
+
for (const hit of hits) {
|
|
41
|
+
into.push(hit);
|
|
42
|
+
}
|
|
36
43
|
}
|
|
37
|
-
function sanitizeSlots(slots, options) {
|
|
44
|
+
function sanitizeSlots(slots, options, hits) {
|
|
38
45
|
if (!slots) {
|
|
39
46
|
return slots;
|
|
40
47
|
}
|
|
41
48
|
const out = {};
|
|
42
49
|
for (const [key, value] of Object.entries(slots)) {
|
|
43
|
-
|
|
50
|
+
const detected = detectText(value, options);
|
|
51
|
+
appendHits(hits, detected.hits);
|
|
52
|
+
out[key] = detected.text;
|
|
44
53
|
}
|
|
45
54
|
return out;
|
|
46
55
|
}
|
|
47
|
-
function sanitizeArgs(args, options) {
|
|
48
|
-
const next = mapStrings(args, (t) => sanitizeText(t, options));
|
|
49
|
-
if (next && typeof next === 'object' && !Array.isArray(next)) {
|
|
50
|
-
return next;
|
|
51
|
-
}
|
|
52
|
-
return args;
|
|
53
|
-
}
|
|
54
|
-
/** Maximum retained length for trace-safe host project ids. */
|
|
55
56
|
const PROJECT_ID_MAX = 128;
|
|
56
57
|
const PROJECT_ID_OK = /^[A-Za-z0-9._-]+$/;
|
|
57
|
-
/** Return a trace-safe project id or `undefined` when the input is unsafe. */
|
|
58
58
|
function sanitizeProjectId(id) {
|
|
59
59
|
if (!id) {
|
|
60
60
|
return undefined;
|
|
@@ -65,95 +65,178 @@ function sanitizeProjectId(id) {
|
|
|
65
65
|
}
|
|
66
66
|
return trimmed;
|
|
67
67
|
}
|
|
68
|
-
function sanitizeRepair(repair, options) {
|
|
68
|
+
function sanitizeRepair(repair, options, hits) {
|
|
69
69
|
if (!repair) {
|
|
70
70
|
return repair;
|
|
71
71
|
}
|
|
72
|
+
const previous = detectText(repair.previousOutput, options);
|
|
73
|
+
const rejection = detectText(repair.rejection, options);
|
|
74
|
+
appendHits(hits, previous.hits);
|
|
75
|
+
appendHits(hits, rejection.hits);
|
|
76
|
+
let guidance = repair.guidance;
|
|
77
|
+
if (guidance) {
|
|
78
|
+
const detected = detectText(guidance, options);
|
|
79
|
+
appendHits(hits, detected.hits);
|
|
80
|
+
guidance = detected.text;
|
|
81
|
+
}
|
|
72
82
|
return {
|
|
73
|
-
previousOutput:
|
|
74
|
-
rejection:
|
|
75
|
-
guidance
|
|
83
|
+
previousOutput: previous.text,
|
|
84
|
+
rejection: rejection.text,
|
|
85
|
+
...(guidance ? { guidance } : {}),
|
|
76
86
|
};
|
|
77
87
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Sanitize the text of each history message; tool calls, ids, and metadata pass
|
|
90
|
+
* through untouched.
|
|
91
|
+
*
|
|
92
|
+
* Exported because every path that injects messages into a turn needs it — turn
|
|
93
|
+
* history, and host steer injects mid-turn. A second copy would drift.
|
|
94
|
+
*/
|
|
95
|
+
function sanitizeHistory(history, options, hits = []) {
|
|
96
|
+
return history.map((m) => {
|
|
97
|
+
let content = m.content;
|
|
98
|
+
if (content !== undefined) {
|
|
99
|
+
const detected = detectText(content, options);
|
|
100
|
+
appendHits(hits, detected.hits);
|
|
101
|
+
content = detected.text;
|
|
102
|
+
}
|
|
103
|
+
let parts = m.parts;
|
|
104
|
+
if (parts) {
|
|
105
|
+
parts = parts.map((p) => {
|
|
106
|
+
if (p.type !== 'text') {
|
|
107
|
+
return p;
|
|
108
|
+
}
|
|
109
|
+
const detected = detectText(p.text, options);
|
|
110
|
+
appendHits(hits, detected.hits);
|
|
111
|
+
return { ...p, text: detected.text };
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
role: m.role,
|
|
116
|
+
...(content !== undefined ? { content } : {}),
|
|
117
|
+
...(parts ? { parts } : {}),
|
|
118
|
+
...(m.tool_calls ? { tool_calls: m.tool_calls } : {}),
|
|
119
|
+
...(m.tool_call_id ? { tool_call_id: m.tool_call_id } : {}),
|
|
120
|
+
...(m.name ? { name: m.name } : {}),
|
|
121
|
+
...(m.metadata ? { metadata: m.metadata } : {}),
|
|
122
|
+
};
|
|
123
|
+
});
|
|
95
124
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
125
|
+
/**
|
|
126
|
+
* Detection switches for one profile at one trust level.
|
|
127
|
+
*
|
|
128
|
+
* Falls back to full detection when the profile is not registered yet, so an
|
|
129
|
+
* unknown id never silently disables guardrails.
|
|
130
|
+
*/
|
|
131
|
+
function detectionForProfile(profileId, trust) {
|
|
132
|
+
let spec;
|
|
133
|
+
try {
|
|
134
|
+
spec = getProfile(profileId)?.guardrails;
|
|
100
135
|
}
|
|
101
|
-
|
|
102
|
-
|
|
136
|
+
catch {
|
|
137
|
+
// If profile not registered yet, default to full guardrails.
|
|
103
138
|
}
|
|
104
|
-
return
|
|
139
|
+
return detectionForTrust(resolveGuardrailPolicy(spec), trust);
|
|
105
140
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
if (
|
|
109
|
-
|
|
141
|
+
function pushStageEvent(events, stage, trust, hits) {
|
|
142
|
+
const event = guardrailFromHits(stage, trust, hits, 'redact');
|
|
143
|
+
if (event) {
|
|
144
|
+
events.push(event);
|
|
110
145
|
}
|
|
111
|
-
return tools.map((decl) => sanitizeDynamicTool(decl, options));
|
|
112
146
|
}
|
|
113
|
-
/**
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
147
|
+
/**
|
|
148
|
+
* Sanitize user-controlled text fields; leave attachments/voice untouched.
|
|
149
|
+
*
|
|
150
|
+
* Returns `{ type: 'guardrail' }` events for stages that redacted something.
|
|
151
|
+
* Clean surfaces emit nothing.
|
|
152
|
+
*
|
|
153
|
+
* `req.system` is host-assembled per turn — it interpolates retrieval and user
|
|
154
|
+
* data, so it is treated as `assembled`, not trusted. `identity.system` never
|
|
155
|
+
* reaches this path and stays verbatim.
|
|
156
|
+
*/
|
|
157
|
+
function sanitizeTurnRequestText(req, profileId) {
|
|
158
|
+
const untrusted = detectionForProfile(profileId, 'untrusted');
|
|
159
|
+
const assembled = detectionForProfile(profileId, 'assembled');
|
|
126
160
|
const input = req.input ?? {};
|
|
127
|
-
const
|
|
161
|
+
const events = [];
|
|
162
|
+
const inputHits = [];
|
|
163
|
+
const historyHits = [];
|
|
164
|
+
const systemHits = [];
|
|
128
165
|
const { text: rawText } = input;
|
|
129
|
-
let invoke = toolInvoke;
|
|
130
|
-
if (toolInvoke) {
|
|
131
|
-
invoke = { ...toolInvoke, arguments: sanitizeArgs(toolInvoke.arguments, options) };
|
|
132
|
-
}
|
|
133
166
|
let text = rawText;
|
|
134
167
|
if (rawText !== undefined) {
|
|
135
|
-
|
|
168
|
+
const detected = detectText(rawText, untrusted);
|
|
169
|
+
appendHits(inputHits, detected.hits);
|
|
170
|
+
text = detected.text;
|
|
136
171
|
}
|
|
137
172
|
let system = req.system;
|
|
138
173
|
if (system !== undefined) {
|
|
139
|
-
|
|
140
|
-
|
|
174
|
+
const detected = detectText(system, assembled);
|
|
175
|
+
appendHits(systemHits, detected.hits);
|
|
176
|
+
system = detected.text;
|
|
177
|
+
}
|
|
178
|
+
const slots = sanitizeSlots(input.slots, untrusted, inputHits);
|
|
179
|
+
const repair = sanitizeRepair(input.repair, untrusted, inputHits);
|
|
180
|
+
const history = input.history
|
|
181
|
+
? sanitizeHistory(input.history, untrusted, historyHits)
|
|
182
|
+
: undefined;
|
|
183
|
+
pushStageEvent(events, 'input', 'untrusted', inputHits);
|
|
184
|
+
pushStageEvent(events, 'history', 'untrusted', historyHits);
|
|
185
|
+
pushStageEvent(events, 'system', 'assembled', systemHits);
|
|
186
|
+
return {
|
|
187
|
+
request: {
|
|
188
|
+
...req,
|
|
189
|
+
system,
|
|
190
|
+
projectId: sanitizeProjectId(req.projectId),
|
|
191
|
+
input: {
|
|
192
|
+
...input,
|
|
193
|
+
text,
|
|
194
|
+
slots,
|
|
195
|
+
repair,
|
|
196
|
+
history,
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
events,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
/** Sanitize all user-controlled text and blobs in a turn request. */
|
|
203
|
+
function sanitizeTurnRequest(req) {
|
|
204
|
+
return sanitizeTurnRequestWithEvents(req).request;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Sanitize a turn request and return guardrail events for any redactionsactions spans.
|
|
208
|
+
* Attachments/voice are validated but do not emit content-span events.
|
|
209
|
+
*/
|
|
210
|
+
function sanitizeTurnRequestWithEvents(req) {
|
|
211
|
+
const { request: textSafe, events } = sanitizeTurnRequestText(req, req.profile);
|
|
212
|
+
const input = textSafe.input ?? {};
|
|
141
213
|
const { attachments, voice } = sanitizeTurnBlobsForProfile(req.profile, input.attachments, input.voice);
|
|
142
214
|
return {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
slots: sanitizeSlots(input.slots, options),
|
|
151
|
-
attachments,
|
|
152
|
-
voice,
|
|
153
|
-
repair: sanitizeRepair(input.repair, options),
|
|
154
|
-
history: sanitizeHistory(input.history, options),
|
|
215
|
+
request: {
|
|
216
|
+
...textSafe,
|
|
217
|
+
input: {
|
|
218
|
+
...input,
|
|
219
|
+
attachments,
|
|
220
|
+
voice,
|
|
221
|
+
},
|
|
155
222
|
},
|
|
156
|
-
|
|
223
|
+
events,
|
|
157
224
|
};
|
|
158
225
|
}
|
|
159
|
-
|
|
226
|
+
/**
|
|
227
|
+
* Trace-safe request sanitize. Prefers full `sanitizeTurnRequest`; if blob/policy
|
|
228
|
+
* checks throw, still redacts text and keeps attachments for hashing — never invents empty input.
|
|
229
|
+
*/
|
|
230
|
+
function sanitizeTurnRequestForTrace(req) {
|
|
231
|
+
try {
|
|
232
|
+
return { request: sanitizeTurnRequest(req) };
|
|
233
|
+
}
|
|
234
|
+
catch (err) {
|
|
235
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
236
|
+
return {
|
|
237
|
+
request: sanitizeTurnRequestText(req, req.profile).request,
|
|
238
|
+
sanitizeError: message,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
export { detectionForProfile, detectText, PROJECT_ID_MAX, redactSensitiveOnly, sanitizeHistory, sanitizeProjectId, sanitizeText, sanitizeTurnRequest, sanitizeTurnRequestForTrace, sanitizeTurnRequestWithEvents, };
|
|
@@ -23,7 +23,8 @@ const GITHUB_PAT = /\bgithub_pat_[A-Za-z0-9_]{20,}\b/g;
|
|
|
23
23
|
const GITHUB_TOKEN = /\bghp_[A-Za-z0-9]{36}\b/g;
|
|
24
24
|
const SLACK_TOKEN = /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/g;
|
|
25
25
|
const BEARER = /\bBearer\s+[A-Za-z0-9._~+/-]+=*/gi;
|
|
26
|
-
|
|
26
|
+
/** Bounded payload so PEM redaction cannot ReDoS on repeated BEGIN markers. */
|
|
27
|
+
const PEM_KEY = /-----BEGIN (?:RSA )?PRIVATE KEY-----[\s\S]{0,16384}?-----END (?:RSA )?PRIVATE KEY-----/g;
|
|
27
28
|
const CARD_CANDIDATE = /\b(?:\d[\s.-]*?){13,19}\b/g;
|
|
28
29
|
const KEY_PATTERNS = [
|
|
29
30
|
SSN,
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serialization for guardrail scanning.
|
|
3
|
+
*
|
|
4
|
+
* Detectors work on strings, so non-text event payloads (structured output, tool
|
|
5
|
+
* arguments, grounding metadata) must be flattened before they can be inspected.
|
|
6
|
+
* A guardrail must never be the thing that throws, so this never propagates a
|
|
7
|
+
* serializer error: cycles and bigints are represented rather than fatal, and a
|
|
8
|
+
* payload that still cannot be rendered is reported so the caller can fail closed.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
/** Marker substituted for a repeated reference so a cycle terminates. */
|
|
13
|
+
declare const CIRCULAR = "[circular]";
|
|
14
|
+
export interface ScanText {
|
|
15
|
+
text: string;
|
|
16
|
+
/** True when the payload could not be rendered and was not inspected. */
|
|
17
|
+
unscannable: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Flatten an arbitrary payload to text for detector scanning.
|
|
21
|
+
*
|
|
22
|
+
* Cycles collapse to `[circular]` and bigints render as digits, so the common
|
|
23
|
+
* unserializable shapes still get inspected instead of aborting the turn. Only a
|
|
24
|
+
* payload that defeats that (a throwing `toJSON`, for instance) comes back
|
|
25
|
+
* `unscannable`.
|
|
26
|
+
*/
|
|
27
|
+
declare function textForScan(value: unknown): ScanText;
|
|
28
|
+
/**
|
|
29
|
+
* Scan-ready text, discarding the unscannable signal.
|
|
30
|
+
*
|
|
31
|
+
* For callers whose only question is "does this contain X" and for whom an
|
|
32
|
+
* unrenderable payload is the same as no match.
|
|
33
|
+
*/
|
|
34
|
+
declare function scanTextOf(value: unknown): string;
|
|
35
|
+
export { CIRCULAR, scanTextOf, textForScan };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serialization for guardrail scanning.
|
|
3
|
+
*
|
|
4
|
+
* Detectors work on strings, so non-text event payloads (structured output, tool
|
|
5
|
+
* arguments, grounding metadata) must be flattened before they can be inspected.
|
|
6
|
+
* A guardrail must never be the thing that throws, so this never propagates a
|
|
7
|
+
* serializer error: cycles and bigints are represented rather than fatal, and a
|
|
8
|
+
* payload that still cannot be rendered is reported so the caller can fail closed.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
/** Marker substituted for a repeated reference so a cycle terminates. */
|
|
13
|
+
const CIRCULAR = '[circular]';
|
|
14
|
+
/**
|
|
15
|
+
* Flatten an arbitrary payload to text for detector scanning.
|
|
16
|
+
*
|
|
17
|
+
* Cycles collapse to `[circular]` and bigints render as digits, so the common
|
|
18
|
+
* unserializable shapes still get inspected instead of aborting the turn. Only a
|
|
19
|
+
* payload that defeats that (a throwing `toJSON`, for instance) comes back
|
|
20
|
+
* `unscannable`.
|
|
21
|
+
*/
|
|
22
|
+
function textForScan(value) {
|
|
23
|
+
if (value === undefined) {
|
|
24
|
+
return { text: '', unscannable: false };
|
|
25
|
+
}
|
|
26
|
+
if (typeof value === 'string') {
|
|
27
|
+
return { text: value, unscannable: false };
|
|
28
|
+
}
|
|
29
|
+
const seen = new WeakSet();
|
|
30
|
+
try {
|
|
31
|
+
const json = JSON.stringify(value, (_key, val) => {
|
|
32
|
+
if (typeof val === 'bigint') {
|
|
33
|
+
return val.toString();
|
|
34
|
+
}
|
|
35
|
+
if (typeof val === 'object' && val !== null) {
|
|
36
|
+
if (seen.has(val)) {
|
|
37
|
+
return CIRCULAR;
|
|
38
|
+
}
|
|
39
|
+
seen.add(val);
|
|
40
|
+
}
|
|
41
|
+
return val;
|
|
42
|
+
});
|
|
43
|
+
return { text: json ?? '', unscannable: false };
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return { text: '', unscannable: true };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Scan-ready text, discarding the unscannable signal.
|
|
51
|
+
*
|
|
52
|
+
* For callers whose only question is "does this contain X" and for whom an
|
|
53
|
+
* unrenderable payload is the same as no match.
|
|
54
|
+
*/
|
|
55
|
+
function scanTextOf(value) {
|
|
56
|
+
return textForScan(value).text;
|
|
57
|
+
}
|
|
58
|
+
export { CIRCULAR, scanTextOf, textForScan };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guardrails testing surface — adversarial corpus, fuzz runners, live attack builders.
|
|
3
|
+
*
|
|
4
|
+
* Import via `theorum/guardrails/testing` (not published on the production guardrails entry).
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
/** lexicon-exempt-file: adversarial harness helpers — not runtime user or model copy (P2) */
|
|
9
|
+
import "../../_dnt.polyfills.js";
|
|
10
|
+
export type { CanaryEgressAttack, CanaryEgressCatalogEntry, InboundFuzzPayload, InboundFuzzResult, LiveAttack, } from './corpus/mod.js';
|
|
11
|
+
export { buildCanaryEgressAttacks, buildLiveAttacks, canaryEgressCatalog, FIXED_CANARY, filterLiveAttacks, inboundFuzzPayloads, inboundPayloadByName, runInboundGuardrailFuzz, summarizeAttackBank, } from './corpus/mod.js';
|
|
12
|
+
export type { CorpusSample, CorpusSource } from './eval/corpus.js';
|
|
13
|
+
export { createCorpusCache, parseLabelledCsv, recordsFromYaml, SOURCES } from './eval/corpus.js';
|
|
14
|
+
export type { EvalOptions, EvalReport } from './eval/mod.js';
|
|
15
|
+
export { DETECTORS, formatReport, runGuardrailEval } from './eval/mod.js';
|
|
16
|
+
export type { DetectorScore, EvalDetector } from './eval/score.js';
|
|
17
|
+
export { formatScores, scoreAll, scoreDetector } from './eval/score.js';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guardrails testing surface — adversarial corpus, fuzz runners, live attack builders.
|
|
3
|
+
*
|
|
4
|
+
* Import via `theorum/guardrails/testing` (not published on the production guardrails entry).
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
/** lexicon-exempt-file: adversarial harness helpers — not runtime user or model copy (P2) */
|
|
9
|
+
import "../../_dnt.polyfills.js";
|
|
10
|
+
export { buildCanaryEgressAttacks, buildLiveAttacks, canaryEgressCatalog, FIXED_CANARY, filterLiveAttacks, inboundFuzzPayloads, inboundPayloadByName, runInboundGuardrailFuzz, summarizeAttackBank, } from './corpus/mod.js';
|
|
11
|
+
export { createCorpusCache, parseLabelledCsv, recordsFromYaml, SOURCES } from './eval/corpus.js';
|
|
12
|
+
export { DETECTORS, formatReport, runGuardrailEval } from './eval/mod.js';
|
|
13
|
+
export { formatScores, scoreAll, scoreDetector } from './eval/score.js';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract-failure error class for THEORUM.
|
|
3
|
+
*
|
|
4
|
+
* Lives in its own module so `lexicon.ts` can throw it without importing
|
|
5
|
+
* `error.ts` (which resolves public copy through the lexicon).
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
/** Error class used for expected THEORUM contract failures. */
|
|
10
|
+
export declare class TheorumError extends Error {
|
|
11
|
+
constructor(message?: string, options?: ErrorOptions);
|
|
12
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract-failure error class for THEORUM.
|
|
3
|
+
*
|
|
4
|
+
* Lives in its own module so `lexicon.ts` can throw it without importing
|
|
5
|
+
* `error.ts` (which resolves public copy through the lexicon).
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
/** Error class used for expected THEORUM contract failures. */
|
|
10
|
+
export class TheorumError extends Error {
|
|
11
|
+
constructor(message = '', options) {
|
|
12
|
+
super(message, options);
|
|
13
|
+
this.name = 'TheorumError';
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Directive detection for tool ingress.
|
|
3
|
+
*
|
|
4
|
+
* Tool results carry a different threat than user text. The jailbreak phrasings in
|
|
5
|
+
* `injection.ts` name the thing they attack — "ignore previous instructions",
|
|
6
|
+
* "reveal your system prompt" — and real indirect injection rarely does. It reads
|
|
7
|
+
* like a status update or a helpful next step, and pattern-matching for the word
|
|
8
|
+
* "instructions" misses all of it.
|
|
9
|
+
*
|
|
10
|
+
* What is anomalous in *data* is content that behaves like an instruction: naming
|
|
11
|
+
* a tool the agent can call, issuing an imperative at the agent, or claiming an
|
|
12
|
+
* authority the content does not have.
|
|
13
|
+
*
|
|
14
|
+
* A signal only counts when it co-occurs with a concrete external destination —
|
|
15
|
+
* an address or URL. Directive language alone is far too common in legitimate
|
|
16
|
+
* output to act on. These signals raise the turn's taint rather than rewriting the text. A page
|
|
17
|
+
* documenting an email API legitimately says "call send_email"; redacting that
|
|
18
|
+
* would corrupt content the model needs. Being wrong here should cost a refused
|
|
19
|
+
* write — recoverable and visible — not silently damaged input.
|
|
20
|
+
*
|
|
21
|
+
* @module
|
|
22
|
+
*/
|
|
23
|
+
import type { AdvisoryLevel, GuardrailHit } from './types.js';
|
|
24
|
+
/** Rule ids emitted by tool-ingress directive detection. */
|
|
25
|
+
export declare const DIRECTIVE_RULES: {
|
|
26
|
+
readonly toolName: "tool_result.names-callable-tool";
|
|
27
|
+
readonly imperative: "tool_result.imperative";
|
|
28
|
+
readonly authority: "tool_result.authority-claim";
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Detect instruction-shaped content in a tool result.
|
|
32
|
+
*
|
|
33
|
+
* `callableTools` is the set the model can actually invoke this turn. A result
|
|
34
|
+
* naming one is the highest-precision signal available — ordinary data has no
|
|
35
|
+
* reason to name the agent's tools, and no generic content filter can check it
|
|
36
|
+
* because it requires the turn's registry.
|
|
37
|
+
*/
|
|
38
|
+
declare function directiveHits(text: string, callableTools?: readonly string[]): GuardrailHit[];
|
|
39
|
+
/** True when a result looked like it was trying to steer the agent. */
|
|
40
|
+
declare function looksDirective(hits: GuardrailHit[]): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Strength of the signals, read off the hits rather than invented.
|
|
43
|
+
*
|
|
44
|
+
* Naming a tool the model can call is the sharpest signal available, so it alone
|
|
45
|
+
* reaches `high`; so does agreement between two different signal kinds.
|
|
46
|
+
*/
|
|
47
|
+
declare function advisoryLevel(hits: GuardrailHit[]): AdvisoryLevel;
|
|
48
|
+
export { advisoryLevel, directiveHits, looksDirective };
|