theorum 0.1.14 → 1.0.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/README.md +178 -89
- package/esm/mod.d.ts +21 -11
- package/esm/mod.js +15 -8
- package/esm/src/cli/commands/bench.js +6 -3
- package/esm/src/cli/commands/fuzz-canary.d.ts +13 -0
- package/esm/src/cli/commands/fuzz-canary.js +195 -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/profile.js +25 -14
- package/esm/src/cli/commands/run.d.ts +3 -0
- package/esm/src/cli/commands/run.js +22 -30
- package/esm/src/cli/commands/test.d.ts +10 -1
- package/esm/src/cli/commands/test.js +31 -31
- 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 +45 -11
- package/esm/src/cli/matrix/synthesizer.d.ts +7 -9
- package/esm/src/cli/matrix/synthesizer.js +32 -106
- package/esm/src/guardrails/canary-gate.d.ts +20 -0
- package/esm/src/guardrails/canary-gate.js +31 -0
- package/esm/src/guardrails/canary.d.ts +26 -0
- package/esm/src/guardrails/canary.js +139 -0
- package/esm/src/guardrails/corpus/canary-egress-attacks.d.ts +16 -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 +216 -0
- package/esm/src/guardrails/corpus/inbound-payloads.d.ts +10 -0
- package/esm/src/guardrails/corpus/inbound-payloads.js +124 -0
- package/esm/src/guardrails/corpus/live-attacks.d.ts +20 -0
- package/esm/src/guardrails/corpus/live-attacks.js +232 -0
- package/esm/src/guardrails/corpus/mod.d.ts +13 -0
- package/esm/src/guardrails/corpus/mod.js +11 -0
- package/esm/src/guardrails/corpus/secrets.d.ts +16 -0
- package/esm/src/guardrails/corpus/secrets.js +16 -0
- package/esm/src/guardrails/corpus/strings.d.ts +27 -0
- package/esm/src/guardrails/corpus/strings.js +33 -0
- package/esm/src/guardrails/corpus/types.d.ts +37 -0
- package/esm/src/guardrails/corpus/types.js +6 -0
- package/esm/src/guardrails/egress.d.ts +9 -0
- package/esm/src/guardrails/egress.js +36 -0
- package/esm/src/guardrails/error.js +6 -4
- package/esm/src/guardrails/injection.js +28 -5
- package/esm/src/guardrails/live-outbound-gate.d.ts +39 -0
- package/esm/src/guardrails/live-outbound-gate.js +180 -0
- package/esm/src/guardrails/mod.d.ts +13 -4
- package/esm/src/guardrails/mod.js +10 -4
- package/esm/src/guardrails/quota.js +1 -1
- package/esm/src/guardrails/sanitize.d.ts +11 -15
- package/esm/src/guardrails/sanitize.js +40 -49
- package/esm/src/guardrails/sensitive.js +2 -1
- package/esm/src/guardrails/testing.d.ts +10 -0
- package/esm/src/guardrails/testing.js +9 -0
- package/esm/src/host/client-turn.d.ts +19 -0
- package/esm/src/host/client-turn.js +32 -0
- package/esm/src/host/mod.d.ts +5 -3
- package/esm/src/host/mod.js +4 -3
- package/esm/src/interface/blocks.d.ts +20 -0
- package/esm/src/interface/blocks.js +180 -0
- package/esm/src/interface/from-profile.d.ts +14 -0
- package/esm/src/interface/from-profile.js +104 -0
- package/esm/src/interface/inputs.d.ts +8 -0
- package/esm/src/interface/inputs.js +127 -0
- package/esm/src/interface/mod.d.ts +10 -0
- package/esm/src/interface/mod.js +9 -0
- package/esm/src/interface/types.d.ts +153 -0
- package/esm/src/interface/types.js +13 -0
- package/esm/src/kernel/engine/delta.d.ts +24 -2
- package/esm/src/kernel/engine/delta.js +519 -29
- package/esm/src/kernel/engine/live-inbound.d.ts +9 -0
- package/esm/src/kernel/engine/live-inbound.js +17 -0
- package/esm/src/kernel/engine/repair.js +1 -1
- package/esm/src/kernel/engine/runner/gates.d.ts +1 -1
- package/esm/src/kernel/engine/runner/gates.js +7 -7
- package/esm/src/kernel/engine/runner/mod.js +13 -13
- package/esm/src/kernel/engine/runner/state.d.ts +7 -0
- package/esm/src/kernel/engine/runner/steps.d.ts +1 -1
- package/esm/src/kernel/engine/runner/steps.js +171 -37
- package/esm/src/kernel/engine/runner/stream.d.ts +1 -2
- package/esm/src/kernel/engine/runner/stream.js +66 -29
- package/esm/src/kernel/engine/session/mod.d.ts +23 -0
- package/esm/src/kernel/engine/session/mod.js +205 -0
- package/esm/src/kernel/mod.d.ts +9 -10
- package/esm/src/kernel/mod.js +6 -8
- package/esm/src/kernel/registry/attachments.d.ts +4 -2
- package/esm/src/kernel/registry/attachments.js +6 -3
- package/esm/src/kernel/registry/catalog.d.ts +3 -16
- package/esm/src/kernel/registry/catalog.js +5 -81
- package/esm/src/kernel/registry/ingress.d.ts +9 -4
- package/esm/src/kernel/registry/ingress.js +73 -63
- package/esm/src/kernel/registry/profiles.d.ts +35 -12
- package/esm/src/kernel/registry/profiles.js +159 -66
- package/esm/src/kernel/registry/provider-request.js +11 -7
- package/esm/src/kernel/registry/resolve.d.ts +5 -6
- package/esm/src/kernel/registry/resolve.js +100 -70
- package/esm/src/kernel/registry/vault.d.ts +12 -7
- package/esm/src/kernel/registry/vault.js +30 -8
- package/esm/src/kernel/schema.d.ts +145 -0
- package/esm/src/kernel/schema.js +462 -0
- package/esm/src/kernel/stop.d.ts +15 -10
- package/esm/src/kernel/stop.js +5 -5
- package/esm/src/kernel/tools/execute.d.ts +45 -0
- package/esm/src/kernel/tools/execute.js +363 -0
- package/esm/src/kernel/tools/harness.d.ts +8 -0
- package/esm/src/kernel/tools/harness.js +44 -0
- package/esm/src/kernel/tools/invoke.d.ts +10 -0
- package/esm/src/kernel/tools/invoke.js +83 -0
- package/esm/src/kernel/tools/mod.d.ts +11 -0
- package/esm/src/kernel/tools/mod.js +10 -0
- package/esm/src/kernel/tools/project.d.ts +12 -0
- package/esm/src/kernel/tools/project.js +34 -0
- package/esm/src/kernel/tools/registry.d.ts +23 -0
- package/esm/src/kernel/tools/registry.js +71 -0
- package/esm/src/kernel/tools/resolve.d.ts +29 -0
- package/esm/src/kernel/tools/resolve.js +262 -0
- package/esm/src/kernel/tools/schema.d.ts +13 -0
- package/esm/src/kernel/tools/schema.js +159 -0
- package/esm/src/kernel/tools/types.d.ts +216 -0
- package/esm/src/kernel/tools/types.js +9 -0
- package/esm/src/kernel/types.d.ts +338 -193
- package/esm/src/observability/trace-attach.d.ts +6 -4
- package/esm/src/observability/trace-attach.js +39 -25
- package/esm/src/observability/trace-record.d.ts +11 -9
- package/esm/src/observability/trace-record.js +36 -23
- 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 +9 -1
- package/esm/src/observability/trace.js +11 -3
- 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 +14 -14
- package/esm/src/providers/create-provider.js +55 -23
- package/esm/src/providers/google/interactions/framing.d.ts +15 -0
- package/esm/src/providers/google/interactions/framing.js +208 -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 +46 -0
- package/esm/src/providers/google/live/framing.js +515 -0
- package/esm/src/providers/google/live/openapi-schema.d.ts +6 -0
- package/esm/src/providers/google/live/openapi-schema.js +45 -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 +36 -0
- package/esm/src/providers/google/live/stream.js +201 -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/chat.d.ts +87 -0
- package/esm/src/providers/{openrouter.js → openrouter/chat.js} +70 -229
- package/esm/src/providers/openrouter/image.d.ts +34 -0
- package/esm/src/providers/openrouter/image.js +286 -0
- package/esm/src/providers/openrouter/openai/chat-payload.d.ts +24 -0
- package/esm/src/providers/openrouter/openai/chat-payload.js +60 -0
- package/esm/src/providers/openrouter/openai/compat.d.ts +47 -0
- package/esm/src/providers/openrouter/openai/compat.js +194 -0
- package/esm/src/providers/openrouter/openai/image-payload.d.ts +18 -0
- package/esm/src/providers/openrouter/openai/image-payload.js +84 -0
- package/esm/src/providers/openrouter/openai/sdk-messages.d.ts +22 -0
- package/esm/src/providers/openrouter/openai/sdk-messages.js +95 -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 -201
- 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 -176
- 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,198 +0,0 @@
|
|
|
1
|
-
import { toErrorEvent } from '../../../guardrails/error.js';
|
|
2
|
-
import { sanitizeDynamicTools, sanitizeText } from '../../../guardrails/sanitize.js';
|
|
3
|
-
import { CATALOG } from '../../registry/catalog.js';
|
|
4
|
-
import { executeTool } from '../../registry/tools.js';
|
|
5
|
-
function formatToolFinding(res) {
|
|
6
|
-
let raw;
|
|
7
|
-
if (res.finding) {
|
|
8
|
-
raw = res.finding;
|
|
9
|
-
}
|
|
10
|
-
else if (res.data) {
|
|
11
|
-
raw = JSON.stringify(res.data);
|
|
12
|
-
}
|
|
13
|
-
else {
|
|
14
|
-
return 'ok';
|
|
15
|
-
}
|
|
16
|
-
return sanitizeText(raw);
|
|
17
|
-
}
|
|
18
|
-
function* invokeFromUi(profile, req) {
|
|
19
|
-
const invoke = req.toolInvoke;
|
|
20
|
-
if (!invoke) {
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
try {
|
|
24
|
-
const result = executeTool(profile, invoke.name, invoke.arguments);
|
|
25
|
-
yield {
|
|
26
|
-
type: 'tool',
|
|
27
|
-
tool: { name: invoke.name, arguments: invoke.arguments, result },
|
|
28
|
-
};
|
|
29
|
-
if (result.status === 'error') {
|
|
30
|
-
yield toErrorEvent(formatToolFinding(result));
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
yield { type: 'done' };
|
|
34
|
-
}
|
|
35
|
-
catch (err) {
|
|
36
|
-
yield toErrorEvent(err);
|
|
37
|
-
yield { type: 'done' };
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
function executeCustomModelTool(profile, name, args) {
|
|
41
|
-
try {
|
|
42
|
-
const result = executeTool(profile, name, args);
|
|
43
|
-
const events = [
|
|
44
|
-
{
|
|
45
|
-
type: 'tool',
|
|
46
|
-
tool: { name, arguments: args, result },
|
|
47
|
-
},
|
|
48
|
-
];
|
|
49
|
-
if (result.status === 'error') {
|
|
50
|
-
events.push(toErrorEvent(formatToolFinding(result)));
|
|
51
|
-
}
|
|
52
|
-
return events;
|
|
53
|
-
}
|
|
54
|
-
catch (err) {
|
|
55
|
-
return [toErrorEvent(err)];
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
function dispatchModelTool(profile, event, gated) {
|
|
59
|
-
const { tool } = event;
|
|
60
|
-
if (!tool) {
|
|
61
|
-
return [];
|
|
62
|
-
}
|
|
63
|
-
const name = tool.name;
|
|
64
|
-
if (CATALOG.tools[name]?.kind === 'builtin') {
|
|
65
|
-
return [event];
|
|
66
|
-
}
|
|
67
|
-
if (!gated.includes(name)) {
|
|
68
|
-
return [toErrorEvent(`Tool '${name}' is not gated on this turn`)];
|
|
69
|
-
}
|
|
70
|
-
const args = tool.arguments ?? {};
|
|
71
|
-
return executeCustomModelTool(profile, name, args);
|
|
72
|
-
}
|
|
73
|
-
function findDynamicDeclaration(tools, name) {
|
|
74
|
-
return tools?.find((t) => t.name === name);
|
|
75
|
-
}
|
|
76
|
-
async function checkDynamicAuthorization(decl, args, profile, sessionPermissions) {
|
|
77
|
-
if (!decl.canExecute) {
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
try {
|
|
81
|
-
const decision = await decl.canExecute({
|
|
82
|
-
args,
|
|
83
|
-
profile,
|
|
84
|
-
sessionPermissions,
|
|
85
|
-
});
|
|
86
|
-
if (typeof decision === 'boolean' && !decision) {
|
|
87
|
-
return {
|
|
88
|
-
status: 'error',
|
|
89
|
-
finding: `Tool '${decl.name}' execution not authorized.`,
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
if (typeof decision === 'object' && decision !== null) {
|
|
93
|
-
return decision;
|
|
94
|
-
}
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
catch (err) {
|
|
98
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
99
|
-
return {
|
|
100
|
-
status: 'error',
|
|
101
|
-
finding: `Authorization error for '${decl.name}': ${msg}`,
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
function checkDynamicPermissionTier(decl, args, sessionPermissions) {
|
|
106
|
-
if (decl.permissionTier === 'session_consent' || decl.permissionTier === 'always_confirm') {
|
|
107
|
-
const isGranted = sessionPermissions?.includes(decl.name) || sessionPermissions?.includes('*');
|
|
108
|
-
if (!isGranted) {
|
|
109
|
-
return {
|
|
110
|
-
status: 'pause',
|
|
111
|
-
finding: `Tool '${decl.name}' requires ${decl.permissionTier} authorization.`,
|
|
112
|
-
data: { tool: decl.name, permissionTier: decl.permissionTier, args },
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
return null;
|
|
117
|
-
}
|
|
118
|
-
async function runDynamicHandler(decl, args) {
|
|
119
|
-
if (!decl.handler) {
|
|
120
|
-
return {
|
|
121
|
-
status: 'ok',
|
|
122
|
-
finding: `${decl.name} accepted (no handler)`,
|
|
123
|
-
data: args,
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
try {
|
|
127
|
-
return await decl.handler(args);
|
|
128
|
-
}
|
|
129
|
-
catch (err) {
|
|
130
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
131
|
-
return { status: 'error', finding: msg };
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
async function executeDynamicTool(decl, args, profile, sessionPermissions) {
|
|
135
|
-
const authEnvelope = await checkDynamicAuthorization(decl, args, profile, sessionPermissions);
|
|
136
|
-
if (authEnvelope) {
|
|
137
|
-
return authEnvelope;
|
|
138
|
-
}
|
|
139
|
-
const permissionEnvelope = checkDynamicPermissionTier(decl, args, sessionPermissions);
|
|
140
|
-
if (permissionEnvelope) {
|
|
141
|
-
return permissionEnvelope;
|
|
142
|
-
}
|
|
143
|
-
return runDynamicHandler(decl, args);
|
|
144
|
-
}
|
|
145
|
-
function mergeDynamicTools(current, loaded) {
|
|
146
|
-
const merged = [...(current ?? [])];
|
|
147
|
-
for (const tool of loaded) {
|
|
148
|
-
const existing = merged.findIndex((item) => item.name === tool.name);
|
|
149
|
-
if (existing >= 0) {
|
|
150
|
-
merged[existing] = tool;
|
|
151
|
-
}
|
|
152
|
-
else {
|
|
153
|
-
merged.push(tool);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
return merged;
|
|
157
|
-
}
|
|
158
|
-
async function executeDynamicToolLoader(args) {
|
|
159
|
-
const { decl, toolArgs, profile, generation } = args;
|
|
160
|
-
const loader = generation.dynamicToolLoader;
|
|
161
|
-
if (!loader) {
|
|
162
|
-
return {
|
|
163
|
-
status: 'error',
|
|
164
|
-
finding: `Tool '${decl.name}' is marked as a loader but no loader is configured.`,
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
const rawLoaded = await loader({
|
|
168
|
-
name: decl.name,
|
|
169
|
-
args: toolArgs,
|
|
170
|
-
profile,
|
|
171
|
-
currentTools: generation.dynamicTools ?? [],
|
|
172
|
-
sessionPermissions: generation.sessionPermissions,
|
|
173
|
-
});
|
|
174
|
-
const loaded = sanitizeDynamicTools(rawLoaded) ?? [];
|
|
175
|
-
generation.dynamicTools = mergeDynamicTools(generation.dynamicTools, loaded);
|
|
176
|
-
return {
|
|
177
|
-
status: 'ok',
|
|
178
|
-
finding: `Loaded ${String(loaded.length)} dynamic tool schema(s).`,
|
|
179
|
-
data: { loadedTools: loaded.map((tool) => tool.name) },
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
function isActionableDynamicDeclaration(decl) {
|
|
183
|
-
return Boolean(decl?.handler || decl?.canExecute || decl?.permissionTier || decl?.loadsDynamicTools);
|
|
184
|
-
}
|
|
185
|
-
async function executeDynamicDeclaration(args) {
|
|
186
|
-
const { decl, toolArgs, profile, generation } = args;
|
|
187
|
-
const res = await executeDynamicTool(decl, toolArgs, profile, generation.sessionPermissions);
|
|
188
|
-
if (res.status === 'ok' && decl.loadsDynamicTools) {
|
|
189
|
-
return await executeDynamicToolLoader({
|
|
190
|
-
decl,
|
|
191
|
-
toolArgs,
|
|
192
|
-
profile,
|
|
193
|
-
generation,
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
return res;
|
|
197
|
-
}
|
|
198
|
-
export { dispatchModelTool, executeDynamicDeclaration, findDynamicDeclaration, formatToolFinding, invokeFromUi, isActionableDynamicDeclaration, };
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generic built-in custom tool executor.
|
|
3
|
-
*
|
|
4
|
-
* Static custom tools are intentionally minimal. Application-specific tools
|
|
5
|
-
* should be supplied as dynamic declarations with host-owned handlers.
|
|
6
|
-
*
|
|
7
|
-
* @module
|
|
8
|
-
*/
|
|
9
|
-
import type { CustomToolId, Profile, ToolEnvelope } from '../types.js';
|
|
10
|
-
/** Execute a static tool after enforcing the profile allowlist. */
|
|
11
|
-
declare function executeTool(profile: Profile, name: CustomToolId, args: Record<string, unknown>): ToolEnvelope;
|
|
12
|
-
export { executeTool };
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generic built-in custom tool executor.
|
|
3
|
-
*
|
|
4
|
-
* Static custom tools are intentionally minimal. Application-specific tools
|
|
5
|
-
* should be supplied as dynamic declarations with host-owned handlers.
|
|
6
|
-
*
|
|
7
|
-
* @module
|
|
8
|
-
*/
|
|
9
|
-
import { getTool } from './catalog.js';
|
|
10
|
-
import { assertToolAllowed } from './resolve.js';
|
|
11
|
-
function executeAskUser(args) {
|
|
12
|
-
const { kind, prompt } = args;
|
|
13
|
-
if (kind !== 'confirm' && kind !== 'choice' && kind !== 'text') {
|
|
14
|
-
return { status: 'error', finding: 'askUser.kind must be confirm, choice, or text' };
|
|
15
|
-
}
|
|
16
|
-
if (typeof prompt !== 'string' || !prompt.trim()) {
|
|
17
|
-
return { status: 'error', finding: 'askUser.prompt is required' };
|
|
18
|
-
}
|
|
19
|
-
return {
|
|
20
|
-
status: 'pause',
|
|
21
|
-
finding: prompt,
|
|
22
|
-
data: { ...args, schema: getTool('askUser')?.schema },
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
/** Execute a static tool after enforcing the profile allowlist. */
|
|
26
|
-
function executeTool(profile, name, args) {
|
|
27
|
-
assertToolAllowed(profile, name);
|
|
28
|
-
if (name === 'askUser') {
|
|
29
|
-
return executeAskUser(args);
|
|
30
|
-
}
|
|
31
|
-
return {
|
|
32
|
-
status: 'error',
|
|
33
|
-
finding: `Tool '${name}' has no kernel executor; pass a dynamic tool handler instead.`,
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
export { executeTool };
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function exposeForTests(bucket: string, api: Record<string, unknown>): void;
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Side-channel for repo unit/mutation tests. Not part of the public package API
|
|
3
|
-
* (not listed in package exports). Enabled only when THEORUM_TEST_INTERNALS=1.
|
|
4
|
-
*
|
|
5
|
-
* @module
|
|
6
|
-
*/
|
|
7
|
-
import * as dntShim from "../../_dnt.shims.js";
|
|
8
|
-
export function exposeForTests(bucket, api) {
|
|
9
|
-
let enabled = false;
|
|
10
|
-
try {
|
|
11
|
-
enabled = typeof dntShim.Deno !== 'undefined' && dntShim.Deno.env.get('THEORUM_TEST_INTERNALS') === '1';
|
|
12
|
-
}
|
|
13
|
-
catch {
|
|
14
|
-
// Missing --allow-env, or non-Deno runtime: never expose.
|
|
15
|
-
}
|
|
16
|
-
if (!enabled)
|
|
17
|
-
return;
|
|
18
|
-
const g = dntShim.dntGlobalThis;
|
|
19
|
-
let root = g.__theorumTestInternals;
|
|
20
|
-
if (!root) {
|
|
21
|
-
root = {};
|
|
22
|
-
g.__theorumTestInternals = root;
|
|
23
|
-
}
|
|
24
|
-
root[bucket] = api;
|
|
25
|
-
}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { ProviderCompleteRequest } from '../kernel/types.js';
|
|
2
|
-
declare function camelToSnake(key: string): string;
|
|
3
|
-
/** Interactions REST body for one complete() call (Google snake_case keys). */
|
|
4
|
-
declare function toInteractionsBody(req: ProviderCompleteRequest): Record<string, unknown>;
|
|
5
|
-
export { camelToSnake, toInteractionsBody };
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
import { TheorumError } from '../guardrails/error.js';
|
|
2
|
-
import { getTool } from '../kernel/registry/catalog.js';
|
|
3
|
-
import { getStructured } from '../kernel/registry/schemas.js';
|
|
4
|
-
import { exposeForTests } from './expose-for-tests.js';
|
|
5
|
-
function camelToSnake(key) {
|
|
6
|
-
return key.replaceAll(/[A-Z]/g, (ch) => `_${ch.toLowerCase()}`);
|
|
7
|
-
}
|
|
8
|
-
function toGoogleValue(value) {
|
|
9
|
-
if (Array.isArray(value)) {
|
|
10
|
-
return value.map(toGoogleValue);
|
|
11
|
-
}
|
|
12
|
-
if (value && typeof value === 'object') {
|
|
13
|
-
const out = {};
|
|
14
|
-
for (const [key, nested] of Object.entries(value)) {
|
|
15
|
-
// JSON Schema property names must stay as authored (e.g. correctAnswer in
|
|
16
|
-
// both properties and required). Snake-casing breaks Gemini validation.
|
|
17
|
-
if (key === 'schema') {
|
|
18
|
-
out[camelToSnake(key)] = nested;
|
|
19
|
-
continue;
|
|
20
|
-
}
|
|
21
|
-
out[camelToSnake(key)] = toGoogleValue(nested);
|
|
22
|
-
}
|
|
23
|
-
return out;
|
|
24
|
-
}
|
|
25
|
-
return value;
|
|
26
|
-
}
|
|
27
|
-
function wirePart(part) {
|
|
28
|
-
if (part.type === 'text') {
|
|
29
|
-
return { type: 'text', text: part.text };
|
|
30
|
-
}
|
|
31
|
-
return { type: part.type, mimeType: part.mimeType, data: part.data };
|
|
32
|
-
}
|
|
33
|
-
const USER_INPUT = 'user_input';
|
|
34
|
-
function userInputStep(parts) {
|
|
35
|
-
return { type: USER_INPUT, content: parts.map(wirePart) };
|
|
36
|
-
}
|
|
37
|
-
function historyStep(msg) {
|
|
38
|
-
const isAssistant = msg.role === 'assistant';
|
|
39
|
-
// Google Interactions input steps: assistant history is `model_output` (not `model_turn`).
|
|
40
|
-
const type = isAssistant ? 'model_output' : 'user_input';
|
|
41
|
-
if (msg.parts && msg.parts.length > 0) {
|
|
42
|
-
return { type, content: msg.parts.map(wirePart) };
|
|
43
|
-
}
|
|
44
|
-
return { type, content: [{ type: 'text', text: msg.content ?? '' }] };
|
|
45
|
-
}
|
|
46
|
-
function systemHoldsUserInput(system, parts) {
|
|
47
|
-
for (const part of parts) {
|
|
48
|
-
if (part.type === 'text' && part.text && system.includes(part.text)) {
|
|
49
|
-
return true;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
function jsonResponseFormat(schema) {
|
|
55
|
-
return [{ type: 'text', mimeType: 'application/json', schema }];
|
|
56
|
-
}
|
|
57
|
-
function attachResponseFormat(req, camel) {
|
|
58
|
-
if (req.speech) {
|
|
59
|
-
if (req.image) {
|
|
60
|
-
throw new TheorumError('cannot mix speech and image response formats');
|
|
61
|
-
}
|
|
62
|
-
if (req.structured) {
|
|
63
|
-
throw new TheorumError('cannot mix speech and structured response formats');
|
|
64
|
-
}
|
|
65
|
-
camel.responseFormat = { type: 'audio' };
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
if (req.image) {
|
|
69
|
-
camel.responseFormat = {
|
|
70
|
-
type: 'image',
|
|
71
|
-
mimeType: req.image.mimeType,
|
|
72
|
-
aspectRatio: req.image.aspectRatio,
|
|
73
|
-
imageSize: req.image.size,
|
|
74
|
-
};
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
if (!req.structured) {
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
const spec = getStructured(req.structured);
|
|
81
|
-
if (spec.enforced !== 'responseFormat' || !spec.jsonSchema) {
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
camel.responseFormat = jsonResponseFormat(spec.jsonSchema);
|
|
85
|
-
}
|
|
86
|
-
function attachSpeechConfig(req, generationConfig) {
|
|
87
|
-
if (!req.speech) {
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
if (req.speech.voice) {
|
|
91
|
-
generationConfig.speechConfig = [{ voice: req.speech.voice }];
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
function inputStepsFromRequest(req) {
|
|
95
|
-
const inputSteps = [];
|
|
96
|
-
for (const h of req.history ?? []) {
|
|
97
|
-
inputSteps.push(historyStep(h));
|
|
98
|
-
}
|
|
99
|
-
if (req.input.length > 0 || inputSteps.length === 0) {
|
|
100
|
-
inputSteps.push(userInputStep(req.input));
|
|
101
|
-
}
|
|
102
|
-
return inputSteps;
|
|
103
|
-
}
|
|
104
|
-
function applyOptionalRequestFields(req, camel) {
|
|
105
|
-
if (req.store !== undefined) {
|
|
106
|
-
camel.store = req.store;
|
|
107
|
-
}
|
|
108
|
-
if (req.previousInteractionId) {
|
|
109
|
-
camel.previousInteractionId = req.previousInteractionId;
|
|
110
|
-
}
|
|
111
|
-
if (req.system) {
|
|
112
|
-
camel.systemInstruction = req.system;
|
|
113
|
-
}
|
|
114
|
-
if (req.builtins.length > 0) {
|
|
115
|
-
camel.tools = req.builtins.map((id) => {
|
|
116
|
-
const type = getTool(id)?.interactionsType;
|
|
117
|
-
if (!type) {
|
|
118
|
-
throw new TheorumError(`Builtin '${id}' has no Interactions wire type`);
|
|
119
|
-
}
|
|
120
|
-
return { type };
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
function baseInteractionsBody(req) {
|
|
125
|
-
const generationConfig = {
|
|
126
|
-
temperature: req.temperature,
|
|
127
|
-
maxOutputTokens: req.maxOutputTokens,
|
|
128
|
-
};
|
|
129
|
-
if (req.speech) {
|
|
130
|
-
// TTS models reject chat thinking knobs; voice lives under speech_config.
|
|
131
|
-
attachSpeechConfig(req, generationConfig);
|
|
132
|
-
}
|
|
133
|
-
else {
|
|
134
|
-
generationConfig.thinkingLevel = req.thinking;
|
|
135
|
-
generationConfig.thinkingSummaries = req.summaries;
|
|
136
|
-
}
|
|
137
|
-
return {
|
|
138
|
-
model: req.apiId,
|
|
139
|
-
stream: true,
|
|
140
|
-
input: inputStepsFromRequest(req),
|
|
141
|
-
generationConfig,
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
/** Interactions REST body for one complete() call (Google snake_case keys). */
|
|
145
|
-
function toInteractionsBody(req) {
|
|
146
|
-
if (systemHoldsUserInput(req.system, req.input)) {
|
|
147
|
-
throw new TheorumError('user input cannot be placed in the system block');
|
|
148
|
-
}
|
|
149
|
-
const camel = baseInteractionsBody(req);
|
|
150
|
-
applyOptionalRequestFields(req, camel);
|
|
151
|
-
attachResponseFormat(req, camel);
|
|
152
|
-
return toGoogleValue(camel);
|
|
153
|
-
}
|
|
154
|
-
export { camelToSnake, toInteractionsBody };
|
|
155
|
-
exposeForTests('interactions', {
|
|
156
|
-
camelToSnake,
|
|
157
|
-
toGoogleValue,
|
|
158
|
-
wirePart,
|
|
159
|
-
userInputStep,
|
|
160
|
-
historyStep,
|
|
161
|
-
systemHoldsUserInput,
|
|
162
|
-
jsonResponseFormat,
|
|
163
|
-
attachResponseFormat,
|
|
164
|
-
attachSpeechConfig,
|
|
165
|
-
inputStepsFromRequest,
|
|
166
|
-
applyOptionalRequestFields,
|
|
167
|
-
baseInteractionsBody,
|
|
168
|
-
toInteractionsBody,
|
|
169
|
-
});
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Gemini key vault selection, quota overflow, and fetch retries.
|
|
3
|
-
*
|
|
4
|
-
* Host applications supply vault credentials through `GeminiTransport`.
|
|
5
|
-
* THEORUM does not read environment variables for these keys.
|
|
6
|
-
*
|
|
7
|
-
* @module
|
|
8
|
-
*/
|
|
9
|
-
import type { GeminiBucket } from '../kernel/types.js';
|
|
10
|
-
type GeminiVault = Record<GeminiBucket, string | undefined>;
|
|
11
|
-
interface GeminiTransport {
|
|
12
|
-
vault: GeminiVault;
|
|
13
|
-
wait?: (ms: number) => Promise<void>;
|
|
14
|
-
fetch?: typeof fetch;
|
|
15
|
-
}
|
|
16
|
-
declare function withGeminiKey<T>(bucket: GeminiBucket, run: (apiKey: string) => Promise<T>, transport: GeminiTransport): Promise<T>;
|
|
17
|
-
declare function fetchGemini(url: string, init: RequestInit, bucket: GeminiBucket, transport: GeminiTransport): Promise<Response>;
|
|
18
|
-
export type { GeminiTransport, GeminiVault };
|
|
19
|
-
export { fetchGemini, withGeminiKey };
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Local provider adapter for OpenAI-compatible endpoints (Ollama, llama.cpp,
|
|
3
|
-
* vLLM, LM Studio, etc.).
|
|
4
|
-
*
|
|
5
|
-
* Streams SSE from `/v1/chat/completions`, accumulates tool calls, and yields
|
|
6
|
-
* normalized `TurnEvent` objects. No external SDK dependency — raw fetch + SSE.
|
|
7
|
-
*
|
|
8
|
-
* Hosts pass `baseUrl` explicitly. THEORUM does not read `OLLAMA_HOST` or other
|
|
9
|
-
* environment variables (see src/providers/CONTRACT.md).
|
|
10
|
-
*
|
|
11
|
-
* @module
|
|
12
|
-
*/
|
|
13
|
-
import type { ModelProvider } from '../kernel/types.js';
|
|
14
|
-
/** Default OpenAI-compat base when the host omits `baseUrl` (Ollama's default port). */
|
|
15
|
-
export declare const DEFAULT_LOCAL_BASE_URL = "http://127.0.0.1:11434";
|
|
16
|
-
/** Host-supplied config for the local provider. */
|
|
17
|
-
export interface LocalProviderConfig {
|
|
18
|
-
/**
|
|
19
|
-
* Base URL of the OpenAI-compat server (no trailing slash).
|
|
20
|
-
* Defaults to `http://127.0.0.1:11434`. Hosts that honor `OLLAMA_HOST` should
|
|
21
|
-
* resolve it themselves and pass the result here.
|
|
22
|
-
*/
|
|
23
|
-
baseUrl?: string;
|
|
24
|
-
/** Custom fetch implementation for testing or proxying. */
|
|
25
|
-
fetch?: typeof globalThis.fetch;
|
|
26
|
-
}
|
|
27
|
-
/** Create a `ModelProvider` for a local OpenAI-compatible server (Ollama, llama.cpp, vLLM, LM Studio). */
|
|
28
|
-
declare function createLocalProvider(config?: LocalProviderConfig): ModelProvider;
|
|
29
|
-
export { createLocalProvider };
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OpenRouter provider adapter and payload helpers.
|
|
3
|
-
*
|
|
4
|
-
* Prefer `createProvider(profile, { openRouter })` from `theorum` / `theorum/providers`
|
|
5
|
-
* for turn execution. This entrypoint is for hosts that build OpenRouter payloads
|
|
6
|
-
* outside the runner.
|
|
7
|
-
*
|
|
8
|
-
* @module
|
|
9
|
-
*/
|
|
10
|
-
import "../../_dnt.polyfills.js";
|
|
11
|
-
export { createOpenRouterProvider } from './openrouter.js';
|
|
12
|
-
export type { OpenRouterConfig } from './openrouter-payload.js';
|
|
13
|
-
export { resolveOpenRouterModel, toOpenRouterPayload, } from './openrouter-payload.js';
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OpenRouter provider adapter and payload helpers.
|
|
3
|
-
*
|
|
4
|
-
* Prefer `createProvider(profile, { openRouter })` from `theorum` / `theorum/providers`
|
|
5
|
-
* for turn execution. This entrypoint is for hosts that build OpenRouter payloads
|
|
6
|
-
* outside the runner.
|
|
7
|
-
*
|
|
8
|
-
* @module
|
|
9
|
-
*/
|
|
10
|
-
import "../../_dnt.polyfills.js";
|
|
11
|
-
export { createOpenRouterProvider } from './openrouter.js';
|
|
12
|
-
export { resolveOpenRouterModel, toOpenRouterPayload, } from './openrouter-payload.js';
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OpenRouter payload builder.
|
|
3
|
-
*
|
|
4
|
-
* Converts THEORUM provider requests into OpenAI-compatible chat completion
|
|
5
|
-
* payloads for OpenRouter and compatible gateways.
|
|
6
|
-
*
|
|
7
|
-
* @module
|
|
8
|
-
*/
|
|
9
|
-
import type { ModelId, ProviderCompleteRequest } from '../kernel/types.js';
|
|
10
|
-
/** Configuration supplied by the host app when creating OpenRouter providers. */
|
|
11
|
-
interface OpenRouterConfig {
|
|
12
|
-
apiKey?: string;
|
|
13
|
-
baseUrl?: string;
|
|
14
|
-
siteUrl?: string;
|
|
15
|
-
siteName?: string;
|
|
16
|
-
fetch?: typeof fetch;
|
|
17
|
-
modelMap?: Record<string, string>;
|
|
18
|
-
}
|
|
19
|
-
/** Host-owned wire ids used when resolving an OpenRouter model string. */
|
|
20
|
-
interface OpenRouterWireIds {
|
|
21
|
-
apiId?: string;
|
|
22
|
-
openRouterId?: string;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Resolve a THEORUM model id to an OpenRouter model string.
|
|
26
|
-
* Prefer `openRouterId` / `apiId` from the profile model spec on the request.
|
|
27
|
-
*/
|
|
28
|
-
declare function resolveOpenRouterModel(modelId: ModelId | string, customMap?: Record<string, string>, wire?: OpenRouterWireIds): string;
|
|
29
|
-
/** Convert a provider-neutral request into an OpenRouter chat completion payload. */
|
|
30
|
-
declare function toOpenRouterPayload(req: ProviderCompleteRequest, config: OpenRouterConfig): Record<string, unknown>;
|
|
31
|
-
interface ResolvedPlugins {
|
|
32
|
-
plugins: Array<{
|
|
33
|
-
id: string;
|
|
34
|
-
}>;
|
|
35
|
-
webSearch: boolean;
|
|
36
|
-
}
|
|
37
|
-
declare function resolveOpenRouterPlugins(builtins: readonly string[]): ResolvedPlugins;
|
|
38
|
-
export type { OpenRouterConfig, OpenRouterWireIds, ResolvedPlugins };
|
|
39
|
-
export { resolveOpenRouterModel, resolveOpenRouterPlugins, toOpenRouterPayload };
|