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
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turn tool visibility and wire snapshot resolution.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { TheorumError } from '../../guardrails/error.js';
|
|
7
|
+
import { getTool } from './registry.js';
|
|
8
|
+
export function pathMatches(catalogPaths, turnPath) {
|
|
9
|
+
if (!catalogPaths || catalogPaths.includes('*')) {
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
if (!turnPath) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
return catalogPaths.includes(turnPath);
|
|
16
|
+
}
|
|
17
|
+
export function applyBuiltinMutualExclusions(requested) {
|
|
18
|
+
return requested.filter((id) => {
|
|
19
|
+
const tool = getTool(id);
|
|
20
|
+
if (tool?.type !== 'builtin') {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
const conflicts = tool.conflictsWith ?? [];
|
|
24
|
+
return !conflicts.some((other) => requested.includes(other));
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
export function resolveAllowedCustomToolIds(profile, req) {
|
|
28
|
+
if (profile.type === 'speech') {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
return profile.tools.allow.filter((id) => {
|
|
32
|
+
const tool = getTool(id);
|
|
33
|
+
if (!tool || tool.type === 'builtin') {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
// Host profiles execute every allowed tool — path gating does not apply.
|
|
37
|
+
return profile.type === 'host' || pathMatches(tool.paths, req.path);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/** Provider builtins listed on the selected model — on for the turn (path-filtered). */
|
|
41
|
+
export function resolveModelBuiltinIds(profile, req, modelId) {
|
|
42
|
+
const spec = profile.models[modelId];
|
|
43
|
+
if (!spec) {
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
return (spec.builtInTools ?? []).filter((id) => {
|
|
47
|
+
const tool = getTool(id);
|
|
48
|
+
if (tool?.type !== 'builtin') {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
return pathMatches(tool.paths, req.path);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
export function wireForTool(name) {
|
|
55
|
+
const tool = getTool(name);
|
|
56
|
+
if (!tool || tool.type === 'builtin') {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
type: 'function',
|
|
61
|
+
name: tool.name,
|
|
62
|
+
description: tool.description,
|
|
63
|
+
parameters: tool.inputSchema,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export function buildWire(visible) {
|
|
67
|
+
const out = [];
|
|
68
|
+
for (const id of visible) {
|
|
69
|
+
const wire = wireForTool(id);
|
|
70
|
+
if (wire) {
|
|
71
|
+
out.push(wire);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return out;
|
|
75
|
+
}
|
|
76
|
+
export function promoteTool(state, id) {
|
|
77
|
+
if (state.visible.includes(id)) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
state.visible.push(id);
|
|
81
|
+
const wire = wireForTool(id);
|
|
82
|
+
if (wire && !state.wire.some((w) => w.name === id)) {
|
|
83
|
+
state.wire.push(wire);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
export function promoteBuiltin(state, id) {
|
|
87
|
+
if (state.builtins.includes(id)) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const tool = getTool(id);
|
|
91
|
+
if (tool?.type !== 'builtin') {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const conflicts = tool.conflictsWith ?? [];
|
|
95
|
+
state.builtins = state.builtins.filter((existing) => {
|
|
96
|
+
if (conflicts.includes(existing)) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
const existingTool = getTool(existing);
|
|
100
|
+
return !(existingTool?.type === 'builtin' && existingTool.conflictsWith?.includes(id));
|
|
101
|
+
});
|
|
102
|
+
state.builtins.push(id);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Custom tools wired at turn start. Text/image: T0 only (T1/T2 pending).
|
|
106
|
+
* Live: every gated tool — declarations are fixed at session setup, so every
|
|
107
|
+
* allowed tool is effectively T0. Host: every gated tool — no tiers at all.
|
|
108
|
+
*/
|
|
109
|
+
export function initialVisible(profile, gated) {
|
|
110
|
+
if (profile.type === 'live' || profile.type === 'host') {
|
|
111
|
+
return [...gated];
|
|
112
|
+
}
|
|
113
|
+
return gated.filter((id) => getTool(id)?.loadTier === 'T0');
|
|
114
|
+
}
|
|
115
|
+
/** Builtins on at turn start — every gated builtin on live, T0 elsewhere (mutual exclusions applied). */
|
|
116
|
+
export function initialBuiltins(profile, gated) {
|
|
117
|
+
return applyBuiltinMutualExclusions(gated.filter((id) => {
|
|
118
|
+
const tool = getTool(id);
|
|
119
|
+
return tool?.type === 'builtin' && (profile.type === 'live' || tool.loadTier === 'T0');
|
|
120
|
+
}));
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Build the initial tool snapshot for a turn.
|
|
124
|
+
* Text/image: T0 wired, T1/T2 pending. Live: the whole allow list and every
|
|
125
|
+
* model builtin. Host: the whole allow list, no builtins, no path gating.
|
|
126
|
+
*/
|
|
127
|
+
export function resolveTurnTools(profile, req, modelId) {
|
|
128
|
+
const customAllowed = resolveAllowedCustomToolIds(profile, req);
|
|
129
|
+
const modelBuiltins = profile.type === 'host' || modelId === undefined
|
|
130
|
+
? []
|
|
131
|
+
: resolveModelBuiltinIds(profile, req, modelId);
|
|
132
|
+
const gated = [...customAllowed, ...modelBuiltins];
|
|
133
|
+
const builtins = initialBuiltins(profile, gated);
|
|
134
|
+
const visible = initialVisible(profile, gated);
|
|
135
|
+
const executable = visible.filter((id) => getTool(id)?.type !== 'builtin');
|
|
136
|
+
return {
|
|
137
|
+
builtins,
|
|
138
|
+
gated,
|
|
139
|
+
visible,
|
|
140
|
+
executable,
|
|
141
|
+
path: req.path,
|
|
142
|
+
sessionPermissions: req.sessionPermissions,
|
|
143
|
+
wire: buildWire(visible),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/** Resolve T0 snapshot and expand T1 selections from `profile.tools.t1Policy`. */
|
|
147
|
+
export async function prepareTurnToolSnapshot(profile, req, modelId) {
|
|
148
|
+
const snapshot = resolveTurnTools(profile, req, modelId);
|
|
149
|
+
await expandT1Policy(snapshot, profile, req);
|
|
150
|
+
return snapshot;
|
|
151
|
+
}
|
|
152
|
+
/** Deep-clone a turn snapshot so host-side concurrent invokes do not share mutable state. */
|
|
153
|
+
export function cloneTurnToolSnapshot(state) {
|
|
154
|
+
return {
|
|
155
|
+
builtins: [...state.builtins],
|
|
156
|
+
gated: [...state.gated],
|
|
157
|
+
visible: [...state.visible],
|
|
158
|
+
executable: [...state.executable],
|
|
159
|
+
path: state.path,
|
|
160
|
+
sessionPermissions: state.sessionPermissions ? [...state.sessionPermissions] : undefined,
|
|
161
|
+
wire: state.wire.map((w) => ({ ...w, parameters: structuredClone(w.parameters) })),
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
/** Wire T1 tools selected by `profile.tools.t1Policy`. */
|
|
165
|
+
export async function expandT1Policy(state, profile, req) {
|
|
166
|
+
if (profile.type === 'speech' || profile.type === 'live' || profile.type === 'host') {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
const t1Policy = profile.tools.t1Policy;
|
|
170
|
+
if (!t1Policy) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
let selected;
|
|
174
|
+
try {
|
|
175
|
+
selected = await t1Policy({
|
|
176
|
+
profile,
|
|
177
|
+
input: req.input,
|
|
178
|
+
path: req.path,
|
|
179
|
+
sessionPermissions: req.sessionPermissions,
|
|
180
|
+
gated: state.gated,
|
|
181
|
+
host: req.host,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
catch (err) {
|
|
185
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
186
|
+
throw new TheorumError(`Profile '${profile.id}' tools.t1Policy rejected: ${msg}`, {
|
|
187
|
+
cause: err,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
if (!Array.isArray(selected)) {
|
|
191
|
+
throw new TheorumError(`Profile '${profile.id}' tools.t1Policy must return ToolId[]`); // lexicon-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
192
|
+
}
|
|
193
|
+
for (const id of selected) {
|
|
194
|
+
if (!state.gated.includes(id)) {
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
const tool = getTool(id);
|
|
198
|
+
// T0 tools are already visible; t1Policy may promote T1/T2 gated tools at turn start.
|
|
199
|
+
if (!tool || tool.loadTier === 'T0') {
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
if (tool.type === 'builtin') {
|
|
203
|
+
promoteBuiltin(state, id);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
promoteTool(state, id);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
state.executable = state.visible.filter((id) => getTool(id)?.type !== 'builtin');
|
|
210
|
+
}
|
|
211
|
+
const LOADED_ID_BLOCKLIST = new Set(['__proto__', 'constructor', 'prototype']);
|
|
212
|
+
/** Promote T2 tools into the visible set after tools.t2Loader returns { loaded }. */
|
|
213
|
+
export function promoteLoadedTools(state, loaded, profile) {
|
|
214
|
+
if (profile.type === 'live' || profile.type === 'host') {
|
|
215
|
+
// Every allowed tool is already visible — there is nothing to promote.
|
|
216
|
+
return { promoted: [] };
|
|
217
|
+
}
|
|
218
|
+
const toPromote = [];
|
|
219
|
+
for (const id of loaded) {
|
|
220
|
+
if (typeof id !== 'string' || LOADED_ID_BLOCKLIST.has(id)) {
|
|
221
|
+
return {
|
|
222
|
+
promoted: [],
|
|
223
|
+
failure: {
|
|
224
|
+
code: 'invalid_output',
|
|
225
|
+
message: 'tools.t2Loader loaded ids must be plain strings', // lexicon-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
const failure = promotionFailure(id, profile);
|
|
230
|
+
if (failure) {
|
|
231
|
+
return { promoted: [], failure };
|
|
232
|
+
}
|
|
233
|
+
const tool = getTool(id);
|
|
234
|
+
if (!tool) {
|
|
235
|
+
return {
|
|
236
|
+
promoted: [],
|
|
237
|
+
failure: {
|
|
238
|
+
code: 'invalid_output',
|
|
239
|
+
message: `Tool '${id}' is not registered`, // lexicon-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
240
|
+
},
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
if (!pathMatches(tool.paths, state.path) || !state.gated.includes(id)) {
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
toPromote.push(id);
|
|
247
|
+
}
|
|
248
|
+
const promoted = [];
|
|
249
|
+
for (const id of toPromote) {
|
|
250
|
+
promoteTool(state, id);
|
|
251
|
+
promoted.push(id);
|
|
252
|
+
}
|
|
253
|
+
state.executable = state.visible.filter((tid) => getTool(tid)?.type !== 'builtin');
|
|
254
|
+
return { promoted };
|
|
255
|
+
}
|
|
256
|
+
export function promotionFailure(id, profile) {
|
|
257
|
+
if (profile.type === 'speech' || !profile.tools.allow.includes(id)) {
|
|
258
|
+
return {
|
|
259
|
+
code: 'invalid_output',
|
|
260
|
+
message: `tools.t2Loader attempted to promote tool '${id}' outside profile allow`, // lexicon-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
const tool = getTool(id);
|
|
264
|
+
if (!tool) {
|
|
265
|
+
return {
|
|
266
|
+
code: 'invalid_output',
|
|
267
|
+
message: `tools.t2Loader attempted to promote unknown tool '${id}'`, // lexicon-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
if (tool.type === 'builtin') {
|
|
271
|
+
return {
|
|
272
|
+
code: 'invalid_output',
|
|
273
|
+
message: `tools.t2Loader attempted to promote builtin '${id}' — only custom tools may be promoted`, // lexicon-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
if (tool.loadTier !== 'T2') {
|
|
277
|
+
return {
|
|
278
|
+
code: 'invalid_output',
|
|
279
|
+
message: `tools.t2Loader attempted to promote tool '${id}' with loadTier '${tool.loadTier}' — only T2 tools may be promoted`, // lexicon-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
return undefined;
|
|
283
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool JSON Schema validation and Zod → wire schema conversion.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { type ZodType } from 'zod';
|
|
7
|
+
export type JsonSchema = Record<string, unknown>;
|
|
8
|
+
/** Validate a tool parameter schema for provider compatibility. */
|
|
9
|
+
declare function validateToolInputSchema(schema: JsonSchema, mode?: 'gemini' | 'structural'): void;
|
|
10
|
+
/** Validate a tool result schema at registration. */
|
|
11
|
+
declare function validateToolOutputSchema(schema: JsonSchema, mode?: 'gemini' | 'structural'): void;
|
|
12
|
+
declare function jsonSchemaFromZod(schema: ZodType, io?: 'input' | 'output'): JsonSchema;
|
|
13
|
+
export { jsonSchemaFromZod, validateToolInputSchema, validateToolOutputSchema };
|
|
14
|
+
/** Strip prototype-pollution keys from provider/host tool args or host-mutated values before validation. */
|
|
15
|
+
export declare function plainToolInput(input: unknown): unknown;
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool JSON Schema validation and Zod → wire schema conversion.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { TheorumError } from '../../guardrails/error.js';
|
|
8
|
+
const GEMINI_SUPPORTED_SCHEMA_KEYS = [
|
|
9
|
+
'type',
|
|
10
|
+
'format',
|
|
11
|
+
'title',
|
|
12
|
+
'description',
|
|
13
|
+
'nullable',
|
|
14
|
+
'enum',
|
|
15
|
+
'default',
|
|
16
|
+
'example',
|
|
17
|
+
'items',
|
|
18
|
+
'minItems',
|
|
19
|
+
'maxItems',
|
|
20
|
+
'properties',
|
|
21
|
+
'required',
|
|
22
|
+
'propertyOrdering',
|
|
23
|
+
'minProperties',
|
|
24
|
+
'maxProperties',
|
|
25
|
+
'minimum',
|
|
26
|
+
'maximum',
|
|
27
|
+
'pattern',
|
|
28
|
+
'minLength',
|
|
29
|
+
'maxLength',
|
|
30
|
+
'anyOf',
|
|
31
|
+
'oneOf',
|
|
32
|
+
];
|
|
33
|
+
function validateGeminiKeys(schema, path, errors) {
|
|
34
|
+
for (const key of Object.keys(schema)) {
|
|
35
|
+
if (!GEMINI_SUPPORTED_SCHEMA_KEYS.includes(key)) {
|
|
36
|
+
errors.push(`${path}: unsupported Gemini schema key '${key}'`); // lexicon-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function validateSchemaShape(schema, path, mode, errors) {
|
|
41
|
+
if (!schema || typeof schema !== 'object' || Array.isArray(schema)) {
|
|
42
|
+
errors.push(`${path}: schema must be an object`); // lexicon-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
const hasType = typeof schema.type === 'string' || Array.isArray(schema.type);
|
|
46
|
+
const hasCombinator = schema.anyOf !== undefined || schema.oneOf !== undefined;
|
|
47
|
+
if (!hasType && !hasCombinator) {
|
|
48
|
+
if (mode === 'structural' && path !== '$') {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
errors.push(`${path}: missing type or combinator`); // lexicon-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
52
|
+
}
|
|
53
|
+
if (mode === 'gemini') {
|
|
54
|
+
validateGeminiKeys(schema, path, errors);
|
|
55
|
+
}
|
|
56
|
+
if (schema.type === 'array' && schema.items === undefined) {
|
|
57
|
+
errors.push(`${path}: array schema must define items`); // lexicon-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
58
|
+
}
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
function walkSchemaProperties(props, required, path, mode, errors) {
|
|
62
|
+
const reqList = Array.isArray(required) ? required : [];
|
|
63
|
+
for (const req of reqList) {
|
|
64
|
+
if (typeof req === 'string' && !(req in props)) {
|
|
65
|
+
errors.push(`${path}: required key '${req}' missing from properties`); // lexicon-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
for (const [key, child] of Object.entries(props)) {
|
|
69
|
+
if (child && typeof child === 'object') {
|
|
70
|
+
walkSchema(child, `${path}.properties.${key}`, mode, errors);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function walkSchema(schema, path, mode, errors) {
|
|
75
|
+
if (!validateSchemaShape(schema, path, mode, errors))
|
|
76
|
+
return;
|
|
77
|
+
const props = schema.properties;
|
|
78
|
+
if (props && typeof props === 'object' && !Array.isArray(props)) {
|
|
79
|
+
walkSchemaProperties(props, schema.required, path, mode, errors);
|
|
80
|
+
}
|
|
81
|
+
if (schema.items && typeof schema.items === 'object' && !Array.isArray(schema.items)) {
|
|
82
|
+
walkSchema(schema.items, `${path}.items`, mode, errors);
|
|
83
|
+
}
|
|
84
|
+
for (const combinator of ['anyOf', 'oneOf']) {
|
|
85
|
+
const branch = schema[combinator];
|
|
86
|
+
if (Array.isArray(branch)) {
|
|
87
|
+
branch.forEach((entry, index) => {
|
|
88
|
+
if (entry && typeof entry === 'object') {
|
|
89
|
+
walkSchema(entry, `${path}.${combinator}[${index}]`, mode, errors);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/** Validate a tool wire schema for provider compatibility. */
|
|
96
|
+
function validateToolWireSchema(schema, mode = 'gemini', label = 'input') {
|
|
97
|
+
const errors = [];
|
|
98
|
+
walkSchema(schema, '$', mode, errors);
|
|
99
|
+
if (errors.length > 0) {
|
|
100
|
+
throw new TheorumError(`Invalid tool ${label} schema: ${errors.join('; ')}`); // lexicon-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/** Validate a tool parameter schema for provider compatibility. */
|
|
104
|
+
function validateToolInputSchema(schema, mode = 'gemini') {
|
|
105
|
+
validateToolWireSchema(schema, mode, 'input');
|
|
106
|
+
}
|
|
107
|
+
/** Validate a tool result schema at registration. */
|
|
108
|
+
function validateToolOutputSchema(schema, mode = 'structural') {
|
|
109
|
+
validateToolWireSchema(schema, mode, 'output');
|
|
110
|
+
}
|
|
111
|
+
function stripProperties(value) {
|
|
112
|
+
const props = {};
|
|
113
|
+
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
114
|
+
for (const [propKey, propValue] of Object.entries(value)) {
|
|
115
|
+
if (propValue && typeof propValue === 'object') {
|
|
116
|
+
props[propKey] = stripUnsupportedGeminiKeys(propValue);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return props;
|
|
121
|
+
}
|
|
122
|
+
function stripBranches(branches) {
|
|
123
|
+
return branches.map((entry) => entry && typeof entry === 'object' ? stripUnsupportedGeminiKeys(entry) : entry);
|
|
124
|
+
}
|
|
125
|
+
/** Derive provider wire JSON Schema from a Zod type. */
|
|
126
|
+
function stripUnsupportedGeminiKeys(schema) {
|
|
127
|
+
const out = {};
|
|
128
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
129
|
+
if (!GEMINI_SUPPORTED_SCHEMA_KEYS.includes(key)) {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
if (key === 'properties') {
|
|
133
|
+
out.properties = stripProperties(value);
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (key === 'items' && value && typeof value === 'object' && !Array.isArray(value)) {
|
|
137
|
+
out.items = stripUnsupportedGeminiKeys(value);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
if ((key === 'anyOf' || key === 'oneOf') && Array.isArray(value)) {
|
|
141
|
+
out[key] = stripBranches(value);
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
out[key] = value;
|
|
145
|
+
}
|
|
146
|
+
return out;
|
|
147
|
+
}
|
|
148
|
+
function jsonSchemaFromZod(schema, io = 'output') {
|
|
149
|
+
const json = z.toJSONSchema(schema, {
|
|
150
|
+
target: 'openApi3',
|
|
151
|
+
io,
|
|
152
|
+
});
|
|
153
|
+
delete json.$schema;
|
|
154
|
+
if (!json.type) {
|
|
155
|
+
json.type = 'object';
|
|
156
|
+
}
|
|
157
|
+
return stripUnsupportedGeminiKeys(json);
|
|
158
|
+
}
|
|
159
|
+
export { jsonSchemaFromZod, validateToolInputSchema, validateToolOutputSchema };
|
|
160
|
+
/** Strip prototype-pollution keys from provider/host tool args or host-mutated values before validation. */
|
|
161
|
+
export function plainToolInput(input) {
|
|
162
|
+
if (input === null || typeof input !== 'object') {
|
|
163
|
+
return input;
|
|
164
|
+
}
|
|
165
|
+
if (Array.isArray(input)) {
|
|
166
|
+
return input.map(plainToolInput);
|
|
167
|
+
}
|
|
168
|
+
const out = {};
|
|
169
|
+
for (const key of Object.keys(input)) {
|
|
170
|
+
if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
out[key] = plainToolInput(input[key]);
|
|
174
|
+
}
|
|
175
|
+
return out;
|
|
176
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool execute wiring around the stage spine: `pre_tool` outcomes (deny, gate,
|
|
3
|
+
* mutate, abort) and `post_tool` inject hand-off.
|
|
4
|
+
*
|
|
5
|
+
* Contract: `docs/contracts/stages.md` (tool execute pipeline).
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import type { z } from 'zod';
|
|
10
|
+
import { type StageHandler, type StageResult } from '../stages.js';
|
|
11
|
+
import type { Profile, TurnEvent, TurnHistoryMessage } from '../types.js';
|
|
12
|
+
import type { ToolCallBase } from './events.js';
|
|
13
|
+
import type { ModelToolResult, ToolContext, ToolFailure, ToolGate } from './types.js';
|
|
14
|
+
/** Stage wiring passed into `executeRegisteredTool`. */
|
|
15
|
+
export interface ToolStageSupport {
|
|
16
|
+
/** Ordered host handlers: request `onStage`, then turn/session ambient. */
|
|
17
|
+
handlers: StageHandler[];
|
|
18
|
+
/** Profile whose guardrails sanitize injects and whose inject gate applies. */
|
|
19
|
+
profile: Profile;
|
|
20
|
+
step: number;
|
|
21
|
+
history: () => readonly TurnHistoryMessage[];
|
|
22
|
+
injectAllowed: boolean;
|
|
23
|
+
injectWouldExceedMaxSteps?: boolean;
|
|
24
|
+
/** Apply sanitized inject messages immediately instead of handing them back. */
|
|
25
|
+
applyInject?: (messages: TurnHistoryMessage[]) => void;
|
|
26
|
+
host?: unknown;
|
|
27
|
+
signal?: AbortSignal;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Everything before a tool body runs, after schema + permission: tool `preTool`,
|
|
31
|
+
* host `pre_tool`, and the mutate re-parse. Each execute path maps the terminal
|
|
32
|
+
* shapes onto its own settlement; the pipeline itself lives here once.
|
|
33
|
+
*/
|
|
34
|
+
export type PreBodyOutcome = {
|
|
35
|
+
ok: true;
|
|
36
|
+
input: unknown;
|
|
37
|
+
} | {
|
|
38
|
+
ok: false;
|
|
39
|
+
kind: 'aborted';
|
|
40
|
+
aborted: true | {
|
|
41
|
+
reason?: string;
|
|
42
|
+
};
|
|
43
|
+
} | {
|
|
44
|
+
ok: false;
|
|
45
|
+
kind: 'gated';
|
|
46
|
+
gate: ToolGate;
|
|
47
|
+
} | {
|
|
48
|
+
ok: false;
|
|
49
|
+
kind: 'failed';
|
|
50
|
+
failure: ToolFailure;
|
|
51
|
+
};
|
|
52
|
+
export type PostToolStageOutcome = {
|
|
53
|
+
abort?: boolean | {
|
|
54
|
+
reason?: string;
|
|
55
|
+
};
|
|
56
|
+
/** Sanitized inject messages for the caller to apply after recording the tool result. */
|
|
57
|
+
inject?: TurnHistoryMessage[];
|
|
58
|
+
/** Host refused the result: the model gets this failure instead. */
|
|
59
|
+
deny?: {
|
|
60
|
+
code: string;
|
|
61
|
+
message: string;
|
|
62
|
+
};
|
|
63
|
+
/** Host replaced the raw output; the caller re-validates and re-projects it. */
|
|
64
|
+
mutate?: {
|
|
65
|
+
output: unknown;
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Tool-local `preTool` (skipped when resume.granted) → host `pre_tool` →
|
|
70
|
+
* mutate re-parse. Emits the gate wire for a host confirm.
|
|
71
|
+
*/
|
|
72
|
+
export declare function runPreToolPipeline(args: {
|
|
73
|
+
tool: {
|
|
74
|
+
name: string;
|
|
75
|
+
input: {
|
|
76
|
+
safeParse: (value: unknown) => z.ZodSafeParseResult<unknown>;
|
|
77
|
+
};
|
|
78
|
+
preTool?: (input: never, ctx: ToolContext) => StageResult | undefined | Promise<StageResult | undefined>;
|
|
79
|
+
};
|
|
80
|
+
input: unknown;
|
|
81
|
+
ctx: ToolContext;
|
|
82
|
+
base: ToolCallBase;
|
|
83
|
+
stages?: ToolStageSupport;
|
|
84
|
+
}): AsyncGenerator<TurnEvent, PreBodyOutcome>;
|
|
85
|
+
/** Emit `post_tool`, run host handlers, hand back inject/abort. */
|
|
86
|
+
export declare function runPostToolStages(args: {
|
|
87
|
+
stages: ToolStageSupport;
|
|
88
|
+
toolName: string;
|
|
89
|
+
callId: string;
|
|
90
|
+
input?: unknown;
|
|
91
|
+
callNotStarted?: boolean;
|
|
92
|
+
outputRaw?: unknown;
|
|
93
|
+
outputModel?: ModelToolResult;
|
|
94
|
+
failure?: ToolFailure;
|
|
95
|
+
awaiting?: boolean;
|
|
96
|
+
/** False when there is no completed output for `mutate` to replace. */
|
|
97
|
+
mutable: boolean;
|
|
98
|
+
}): AsyncGenerator<TurnEvent, PostToolStageOutcome>;
|
|
99
|
+
/** Emit observe `pre_tool` (callNotStarted) then the tool `gate` wire. */
|
|
100
|
+
export declare function emitGateSettlement(args: {
|
|
101
|
+
base: ToolCallBase;
|
|
102
|
+
gate: ToolGate;
|
|
103
|
+
callId: string;
|
|
104
|
+
toolName: string;
|
|
105
|
+
}): AsyncGenerator<TurnEvent, void>;
|