theorum 0.1.4 → 0.1.6
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/docs/AGENT_PROFILE_CONTRACT.md +2 -2
- package/esm/_dnt.polyfills.d.ts +110 -0
- package/esm/_dnt.polyfills.js +144 -0
- package/esm/_dnt.shims.d.ts +5 -0
- package/esm/_dnt.shims.js +61 -0
- package/{mod.ts → esm/mod.d.ts} +17 -57
- package/esm/mod.js +50 -0
- package/esm/package.json +3 -0
- package/esm/src/cli/commands/profile.d.ts +2 -0
- package/esm/src/cli/commands/profile.js +53 -0
- package/esm/src/cli/commands/run.d.ts +10 -0
- package/esm/src/cli/commands/run.js +55 -0
- package/esm/src/cli/commands/test.d.ts +15 -0
- package/esm/src/cli/commands/test.js +140 -0
- package/esm/src/cli/index.d.ts +4 -0
- package/esm/src/cli/index.js +148 -0
- package/esm/src/cli/matrix/fixtures.d.ts +13 -0
- package/esm/src/cli/matrix/fixtures.js +77 -0
- package/esm/src/cli/matrix/synthesizer.d.ts +29 -0
- package/esm/src/cli/matrix/synthesizer.js +187 -0
- package/esm/src/guardrails/error.d.ts +45 -0
- package/esm/src/guardrails/error.js +149 -0
- package/esm/src/guardrails/injection.d.ts +12 -0
- package/esm/src/guardrails/injection.js +220 -0
- package/esm/src/guardrails/mod.d.ts +16 -0
- package/esm/src/guardrails/mod.js +15 -0
- package/esm/src/guardrails/quota.d.ts +10 -0
- package/esm/src/guardrails/quota.js +64 -0
- package/esm/src/guardrails/sanitize.d.ts +22 -0
- package/esm/src/guardrails/sanitize.js +133 -0
- package/esm/src/guardrails/sensitive.d.ts +12 -0
- package/esm/src/guardrails/sensitive.js +88 -0
- package/esm/src/host/mint-trace.d.ts +27 -0
- package/esm/src/host/mint-trace.js +33 -0
- package/esm/src/host/mod.d.ts +13 -0
- package/{src/host/mod.ts → esm/src/host/mod.js} +3 -11
- package/esm/src/host/reply.d.ts +14 -0
- package/esm/src/host/reply.js +27 -0
- package/esm/src/kernel/engine/boundary.d.ts +10 -0
- package/esm/src/kernel/engine/boundary.js +55 -0
- package/esm/src/kernel/engine/delta.d.ts +8 -0
- package/esm/src/kernel/engine/delta.js +389 -0
- package/esm/src/kernel/engine/hash.d.ts +1 -0
- package/esm/src/kernel/engine/hash.js +9 -0
- package/esm/src/kernel/engine/record.d.ts +2 -0
- package/esm/src/kernel/engine/record.js +7 -0
- package/esm/src/kernel/engine/repair.d.ts +7 -0
- package/esm/src/kernel/engine/repair.js +38 -0
- package/esm/src/kernel/engine/runner/gates.d.ts +4 -0
- package/esm/src/kernel/engine/runner/gates.js +208 -0
- package/esm/src/kernel/engine/runner/mod.d.ts +14 -0
- package/esm/src/kernel/engine/runner/mod.js +103 -0
- package/esm/src/kernel/engine/runner/schema-validation.d.ts +22 -0
- package/esm/src/kernel/engine/runner/schema-validation.js +113 -0
- package/esm/src/kernel/engine/runner/state.d.ts +16 -0
- package/esm/src/kernel/engine/runner/state.js +8 -0
- package/esm/src/kernel/engine/runner/steps.d.ts +15 -0
- package/esm/src/kernel/engine/runner/steps.js +127 -0
- package/esm/src/kernel/engine/runner/stream.d.ts +11 -0
- package/esm/src/kernel/engine/runner/stream.js +70 -0
- package/esm/src/kernel/engine/runner/tokens.d.ts +3 -0
- package/esm/src/kernel/engine/runner/tokens.js +38 -0
- package/esm/src/kernel/engine/runner/tools.d.ts +13 -0
- package/esm/src/kernel/engine/runner/tools.js +192 -0
- package/{src/kernel/engine/runner.ts → esm/src/kernel/engine/runner.d.ts} +1 -2
- package/esm/src/kernel/engine/runner.js +6 -0
- package/esm/src/kernel/engine/tree.d.ts +2 -0
- package/esm/src/kernel/engine/tree.js +17 -0
- package/esm/src/kernel/mod.d.ts +18 -0
- package/esm/src/kernel/mod.js +16 -0
- package/esm/src/kernel/registry/attachments.d.ts +16 -0
- package/esm/src/kernel/registry/attachments.js +156 -0
- package/esm/src/kernel/registry/catalog.d.ts +31 -0
- package/esm/src/kernel/registry/catalog.js +135 -0
- package/esm/src/kernel/registry/ingress.d.ts +13 -0
- package/esm/src/kernel/registry/ingress.js +163 -0
- package/esm/src/kernel/registry/profiles.d.ts +34 -0
- package/esm/src/kernel/registry/profiles.js +120 -0
- package/esm/src/kernel/registry/provider-request.d.ts +4 -0
- package/esm/src/kernel/registry/provider-request.js +25 -0
- package/esm/src/kernel/registry/resolve.d.ts +19 -0
- package/esm/src/kernel/registry/resolve.js +217 -0
- package/esm/src/kernel/registry/schemas.d.ts +14 -0
- package/esm/src/kernel/registry/schemas.js +23 -0
- package/esm/src/kernel/registry/tools.d.ts +12 -0
- package/esm/src/kernel/registry/tools.js +36 -0
- package/{src/kernel/registry/vault.ts → esm/src/kernel/registry/vault.d.ts} +2 -17
- package/esm/src/kernel/registry/vault.js +18 -0
- package/esm/src/kernel/types.d.ts +528 -0
- package/esm/src/kernel/types.js +10 -0
- package/esm/src/observability/mod.d.ts +12 -0
- package/{src/observability/mod.ts → esm/src/observability/mod.js} +2 -11
- package/esm/src/observability/spans.d.ts +16 -0
- package/esm/src/observability/spans.js +56 -0
- package/esm/src/observability/trace-attach.d.ts +16 -0
- package/esm/src/observability/trace-attach.js +67 -0
- package/esm/src/observability/trace-record.d.ts +113 -0
- package/esm/src/observability/trace-record.js +143 -0
- package/esm/src/observability/trace-usage.d.ts +3 -0
- package/esm/src/observability/trace-usage.js +32 -0
- package/esm/src/observability/trace.d.ts +23 -0
- package/esm/src/observability/trace.js +121 -0
- package/esm/src/presets/google.d.ts +50 -0
- package/esm/src/presets/google.js +96 -0
- package/esm/src/presets/mod.d.ts +11 -0
- package/esm/src/presets/mod.js +10 -0
- package/esm/src/providers/create-provider.d.ts +29 -0
- package/esm/src/providers/create-provider.js +38 -0
- package/esm/src/providers/gemini-tape.d.ts +2 -0
- package/esm/src/providers/gemini-tape.js +46 -0
- package/esm/src/providers/google-tap.d.ts +3 -0
- package/esm/src/providers/google-tap.js +48 -0
- package/esm/src/providers/interactions.d.ts +5 -0
- package/esm/src/providers/interactions.js +153 -0
- package/esm/src/providers/keys.d.ts +19 -0
- package/esm/src/providers/keys.js +129 -0
- package/esm/src/providers/mod.d.ts +12 -0
- package/{src/providers/mod.ts → esm/src/providers/mod.js} +2 -4
- package/esm/src/providers/openrouter-mod.d.ts +13 -0
- package/{src/providers/openrouter-mod.ts → esm/src/providers/openrouter-mod.js} +3 -7
- package/esm/src/providers/openrouter-payload.d.ts +32 -0
- package/esm/src/providers/openrouter-payload.js +179 -0
- package/esm/src/providers/openrouter.d.ts +15 -0
- package/esm/src/providers/openrouter.js +589 -0
- package/esm/src/providers/pcm.d.ts +7 -0
- package/esm/src/providers/pcm.js +35 -0
- package/esm/src/providers/provider.d.ts +15 -0
- package/esm/src/providers/provider.js +160 -0
- package/esm/src/providers/speech.d.ts +23 -0
- package/esm/src/providers/speech.js +125 -0
- package/esm/src/providers/sse.d.ts +7 -0
- package/esm/src/providers/sse.js +53 -0
- package/package.json +45 -36
- package/deno.json +0 -57
- package/deno.lock +0 -469
- package/src/cli/commands/profile.ts +0 -57
- package/src/cli/commands/run.ts +0 -66
- package/src/cli/commands/test.ts +0 -195
- package/src/cli/index.ts +0 -161
- package/src/cli/matrix/fixtures.ts +0 -96
- package/src/cli/matrix/synthesizer.ts +0 -240
- package/src/guardrails/error.ts +0 -142
- package/src/guardrails/injection.ts +0 -254
- package/src/guardrails/mod.ts +0 -40
- package/src/guardrails/quota.ts +0 -87
- package/src/guardrails/sanitize.ts +0 -165
- package/src/guardrails/sensitive.ts +0 -96
- package/src/host/mint-trace.ts +0 -54
- package/src/host/reply.ts +0 -32
- package/src/kernel/engine/assert.ts +0 -29
- package/src/kernel/engine/boundary.ts +0 -75
- package/src/kernel/engine/delta.ts +0 -440
- package/src/kernel/engine/hash.ts +0 -11
- package/src/kernel/engine/record.ts +0 -8
- package/src/kernel/engine/repair.ts +0 -56
- package/src/kernel/engine/runner/gates.ts +0 -338
- package/src/kernel/engine/runner/mod.ts +0 -135
- package/src/kernel/engine/runner/state.ts +0 -31
- package/src/kernel/engine/runner/steps.ts +0 -183
- package/src/kernel/engine/runner/stream.ts +0 -83
- package/src/kernel/engine/runner/tokens.ts +0 -47
- package/src/kernel/engine/runner/tools.ts +0 -266
- package/src/kernel/engine/tree.ts +0 -18
- package/src/kernel/mod.ts +0 -39
- package/src/kernel/registry/attachments.ts +0 -195
- package/src/kernel/registry/catalog.ts +0 -181
- package/src/kernel/registry/ingress.ts +0 -223
- package/src/kernel/registry/profiles.ts +0 -165
- package/src/kernel/registry/provider-request.ts +0 -31
- package/src/kernel/registry/resolve.ts +0 -290
- package/src/kernel/registry/schemas.ts +0 -29
- package/src/kernel/registry/tools.ts +0 -45
- package/src/kernel/types.ts +0 -576
- package/src/observability/spans.ts +0 -70
- package/src/observability/trace-attach.ts +0 -96
- package/src/observability/trace-record.ts +0 -254
- package/src/observability/trace-usage.ts +0 -36
- package/src/observability/trace.ts +0 -143
- package/src/presets/google.ts +0 -147
- package/src/presets/mod.ts +0 -24
- package/src/providers/create-provider.ts +0 -64
- package/src/providers/gemini-tape.ts +0 -59
- package/src/providers/google-tap.ts +0 -57
- package/src/providers/interactions.ts +0 -182
- package/src/providers/keys.ts +0 -182
- package/src/providers/openrouter-payload.ts +0 -232
- package/src/providers/openrouter.ts +0 -758
- package/src/providers/pcm.ts +0 -37
- package/src/providers/provider.ts +0 -206
- package/src/providers/speech.ts +0 -180
- package/src/providers/sse.ts +0 -59
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { recordStepEvent } from './state.js';
|
|
2
|
+
import { yieldProviderEvents } from './stream.js';
|
|
3
|
+
import { executeDynamicDeclaration, findDynamicDeclaration, formatToolFinding, isActionableDynamicDeclaration, } from './tools.js';
|
|
4
|
+
function isStepLimitReached(step, maxSteps) {
|
|
5
|
+
if (maxSteps <= 0) {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
return step >= maxSteps;
|
|
9
|
+
}
|
|
10
|
+
async function* executeAutonomousStep(args, state, buffer = {
|
|
11
|
+
holdLate: false,
|
|
12
|
+
holdUserVisible: false,
|
|
13
|
+
}) {
|
|
14
|
+
const { profile, generation, system, provider, gemini } = args;
|
|
15
|
+
const genForStep = { ...generation, history: state.currentHistory };
|
|
16
|
+
const pendingTools = [];
|
|
17
|
+
let latestStructured;
|
|
18
|
+
for await (const event of yieldProviderEvents({
|
|
19
|
+
profile,
|
|
20
|
+
generation: genForStep,
|
|
21
|
+
system,
|
|
22
|
+
provider,
|
|
23
|
+
gemini,
|
|
24
|
+
})) {
|
|
25
|
+
if (event.type === 'structured') {
|
|
26
|
+
latestStructured = event.structured;
|
|
27
|
+
}
|
|
28
|
+
if (event.type === 'done') {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (event.type === 'tool' && event.tool) {
|
|
32
|
+
pendingTools.push(event);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
recordStepEvent(event, state);
|
|
36
|
+
const isUserVisible = event.type === 'thought' || event.type === 'text';
|
|
37
|
+
// Egress must not stream user-visible text before the gate runs.
|
|
38
|
+
// Validation-only may stream thought/text live and only hold structured.
|
|
39
|
+
const streamNow = !buffer.holdLate || event.type === 'tokens' || (isUserVisible && !buffer.holdUserVisible);
|
|
40
|
+
if (streamNow) {
|
|
41
|
+
yield event;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return { pendingTools, latestStructured };
|
|
45
|
+
}
|
|
46
|
+
function appendToolTurnToHistory(history, toolEv, res) {
|
|
47
|
+
const tool = toolEv.tool;
|
|
48
|
+
if (!tool) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const callId = tool.id ?? `call_${tool.name}_${String(Date.now())}`;
|
|
52
|
+
history.push({
|
|
53
|
+
role: 'assistant',
|
|
54
|
+
tool_calls: [
|
|
55
|
+
{
|
|
56
|
+
id: callId,
|
|
57
|
+
type: 'function',
|
|
58
|
+
function: {
|
|
59
|
+
name: tool.name,
|
|
60
|
+
arguments: JSON.stringify(tool.arguments ?? {}),
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
});
|
|
65
|
+
history.push({
|
|
66
|
+
role: 'tool',
|
|
67
|
+
tool_call_id: callId,
|
|
68
|
+
name: tool.name,
|
|
69
|
+
content: formatToolFinding(res),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
async function* handlePendingDynamicTools(pendingTools, generation, profile, state) {
|
|
73
|
+
let hasRunnableHandler = false;
|
|
74
|
+
for (const toolEv of pendingTools) {
|
|
75
|
+
const tool = toolEv.tool;
|
|
76
|
+
if (!tool) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const decl = findDynamicDeclaration(generation.dynamicTools, tool.name);
|
|
80
|
+
if (!isActionableDynamicDeclaration(decl)) {
|
|
81
|
+
state.allEmittedEvents.push(toolEv);
|
|
82
|
+
yield toolEv;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
hasRunnableHandler = true;
|
|
86
|
+
const finalResult = await executeDynamicDeclaration({
|
|
87
|
+
decl,
|
|
88
|
+
toolArgs: tool.arguments ?? {},
|
|
89
|
+
profile,
|
|
90
|
+
generation,
|
|
91
|
+
});
|
|
92
|
+
const enrichedEvent = {
|
|
93
|
+
type: 'tool',
|
|
94
|
+
tool: { ...tool, result: finalResult },
|
|
95
|
+
};
|
|
96
|
+
state.allEmittedEvents.push(enrichedEvent);
|
|
97
|
+
yield enrichedEvent;
|
|
98
|
+
appendToolTurnToHistory(state.currentHistory, toolEv, finalResult);
|
|
99
|
+
}
|
|
100
|
+
return hasRunnableHandler;
|
|
101
|
+
}
|
|
102
|
+
async function* executeAttempt(args) {
|
|
103
|
+
const { profile, generation, system, provider, gemini, state } = args;
|
|
104
|
+
let latestStructured;
|
|
105
|
+
let pendingTools = [];
|
|
106
|
+
let stepInAttempt = 0;
|
|
107
|
+
const holdUserVisible = Boolean(profile.guardrails.egress?.enforce);
|
|
108
|
+
const holdLate = Boolean(profile.outputs.validation) || holdUserVisible;
|
|
109
|
+
while (!isStepLimitReached(stepInAttempt, generation.maxSteps)) {
|
|
110
|
+
stepInAttempt++;
|
|
111
|
+
state.stepCount++;
|
|
112
|
+
const stepResult = yield* executeAutonomousStep({ profile, generation, system, provider, gemini }, state, { holdLate, holdUserVisible });
|
|
113
|
+
if (stepResult.latestStructured !== undefined) {
|
|
114
|
+
latestStructured = stepResult.latestStructured;
|
|
115
|
+
}
|
|
116
|
+
pendingTools = stepResult.pendingTools;
|
|
117
|
+
if (pendingTools.length === 0) {
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
const hasRunnableHandler = yield* handlePendingDynamicTools(pendingTools, generation, profile, state);
|
|
121
|
+
if (!hasRunnableHandler) {
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return { pendingTools, latestStructured };
|
|
126
|
+
}
|
|
127
|
+
export { executeAttempt };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ModelProvider, Profile, ResolvedGeneration, TurnEvent } from '../../types.js';
|
|
2
|
+
declare function systemFromProfile(profile: Profile, role: string): string;
|
|
3
|
+
declare function shouldSkipStreamEvent(event: TurnEvent, profile: Profile): boolean;
|
|
4
|
+
declare function yieldProviderEvents(args: {
|
|
5
|
+
profile: Profile;
|
|
6
|
+
generation: ResolvedGeneration;
|
|
7
|
+
system: string;
|
|
8
|
+
provider: ModelProvider;
|
|
9
|
+
gemini: Record<string, unknown>[];
|
|
10
|
+
}): AsyncGenerator<TurnEvent>;
|
|
11
|
+
export { shouldSkipStreamEvent, systemFromProfile, yieldProviderEvents };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { publicError, toErrorEvent } from '../../../guardrails/error.js';
|
|
2
|
+
import { providerCompleteRequest } from '../../registry/provider-request.js';
|
|
3
|
+
import { eventHasCanary, redactCanary } from '../boundary.js';
|
|
4
|
+
import { dispatchModelTool } from './tools.js';
|
|
5
|
+
function systemFromProfile(profile, role) {
|
|
6
|
+
const { identity } = profile;
|
|
7
|
+
const { systemByRole, system } = identity;
|
|
8
|
+
if (systemByRole) {
|
|
9
|
+
const byRole = systemByRole[role];
|
|
10
|
+
if (byRole) {
|
|
11
|
+
return byRole;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
if (system) {
|
|
15
|
+
return system;
|
|
16
|
+
}
|
|
17
|
+
return '';
|
|
18
|
+
}
|
|
19
|
+
function* interceptProviderTool(event, profile, generation) {
|
|
20
|
+
const tool = event.tool;
|
|
21
|
+
if (!tool) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const isDynamic = generation.dynamicTools?.some((d) => d.name === tool.name);
|
|
25
|
+
if (isDynamic) {
|
|
26
|
+
yield event;
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
for (const item of dispatchModelTool(profile, event, generation.custom)) {
|
|
30
|
+
yield item;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function shouldSkipStreamEvent(event, profile) {
|
|
35
|
+
return event.type === 'thought' && profile.outputs.streaming?.streamThoughts === false;
|
|
36
|
+
}
|
|
37
|
+
function* processNormalEvent(event, profile, generation) {
|
|
38
|
+
if (event.type === 'tool') {
|
|
39
|
+
yield* interceptProviderTool(event, profile, generation);
|
|
40
|
+
}
|
|
41
|
+
else if (event.type === 'error') {
|
|
42
|
+
const internal = event.errorInternal ?? event.error ?? '';
|
|
43
|
+
yield {
|
|
44
|
+
type: 'error',
|
|
45
|
+
error: publicError(event.error ?? internal),
|
|
46
|
+
...(internal ? { errorInternal: internal } : {}),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
yield event;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function* yieldProviderEvents(args) {
|
|
54
|
+
const { profile, generation, system, provider, gemini } = args;
|
|
55
|
+
const { canary } = generation;
|
|
56
|
+
for await (const event of provider.complete({
|
|
57
|
+
...providerCompleteRequest(generation, system),
|
|
58
|
+
tapGemini: (row) => {
|
|
59
|
+
gemini.push(row);
|
|
60
|
+
},
|
|
61
|
+
})) {
|
|
62
|
+
if (canary && eventHasCanary(event, canary)) {
|
|
63
|
+
yield redactCanary(event, canary);
|
|
64
|
+
yield toErrorEvent('canary leaked');
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
yield* processNormalEvent(event, profile, generation);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export { shouldSkipStreamEvent, systemFromProfile, yieldProviderEvents };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
function calculateInputChars(safe, system) {
|
|
2
|
+
const input = safe.input ?? {};
|
|
3
|
+
return ((input.text?.length ?? 0) +
|
|
4
|
+
(input.repair?.previousOutput?.length ?? 0) +
|
|
5
|
+
(system?.length ?? 800));
|
|
6
|
+
}
|
|
7
|
+
function calculateOutputChars(events) {
|
|
8
|
+
let outputChars = 0;
|
|
9
|
+
let thinkingChars = 0;
|
|
10
|
+
for (const e of events) {
|
|
11
|
+
if (e.type === 'text' && e.text)
|
|
12
|
+
outputChars += e.text.length;
|
|
13
|
+
if (e.type === 'structured' && e.structured) {
|
|
14
|
+
outputChars += JSON.stringify(e.structured).length;
|
|
15
|
+
}
|
|
16
|
+
if (e.type === 'thought' && e.text)
|
|
17
|
+
thinkingChars += e.text.length;
|
|
18
|
+
}
|
|
19
|
+
return { outputChars, thinkingChars };
|
|
20
|
+
}
|
|
21
|
+
function* calculateFallbackTokens(safe, system, events) {
|
|
22
|
+
const inputChars = calculateInputChars(safe, system);
|
|
23
|
+
const { outputChars, thinkingChars } = calculateOutputChars(events);
|
|
24
|
+
const inputTokens = Math.max(1, Math.round(inputChars / 4));
|
|
25
|
+
const outputTokens = Math.max(1, Math.round(outputChars / 4));
|
|
26
|
+
const thinkingTokens = thinkingChars ? Math.round(thinkingChars / 4) : 0;
|
|
27
|
+
yield {
|
|
28
|
+
type: 'tokens',
|
|
29
|
+
tokens: {
|
|
30
|
+
input: inputTokens,
|
|
31
|
+
output: outputTokens,
|
|
32
|
+
thinking: thinkingTokens,
|
|
33
|
+
toolUse: 0,
|
|
34
|
+
total: inputTokens + outputTokens + thinkingTokens,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export { calculateFallbackTokens };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CustomToolId, DynamicToolDeclaration, Profile, ResolvedGeneration, ToolEnvelope, TurnEvent, TurnRequest } from '../../types.js';
|
|
2
|
+
declare function formatToolFinding(res: ToolEnvelope): string;
|
|
3
|
+
declare function invokeFromUi(profile: Profile, req: TurnRequest): Generator<TurnEvent>;
|
|
4
|
+
declare function dispatchModelTool(profile: Profile, event: TurnEvent, gated: CustomToolId[]): TurnEvent[];
|
|
5
|
+
declare function findDynamicDeclaration(tools: DynamicToolDeclaration[] | undefined, name: string): DynamicToolDeclaration | undefined;
|
|
6
|
+
declare function isActionableDynamicDeclaration(decl: DynamicToolDeclaration | undefined): decl is DynamicToolDeclaration;
|
|
7
|
+
declare function executeDynamicDeclaration(args: {
|
|
8
|
+
decl: DynamicToolDeclaration;
|
|
9
|
+
toolArgs: Record<string, unknown>;
|
|
10
|
+
profile: Profile;
|
|
11
|
+
generation: ResolvedGeneration;
|
|
12
|
+
}): Promise<ToolEnvelope>;
|
|
13
|
+
export { dispatchModelTool, executeDynamicDeclaration, findDynamicDeclaration, formatToolFinding, invokeFromUi, isActionableDynamicDeclaration, };
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { toErrorEvent } from '../../../guardrails/error.js';
|
|
2
|
+
import { CATALOG } from '../../registry/catalog.js';
|
|
3
|
+
import { executeTool } from '../../registry/tools.js';
|
|
4
|
+
function formatToolFinding(res) {
|
|
5
|
+
if (res.finding) {
|
|
6
|
+
return res.finding;
|
|
7
|
+
}
|
|
8
|
+
if (res.data) {
|
|
9
|
+
return JSON.stringify(res.data);
|
|
10
|
+
}
|
|
11
|
+
return 'ok';
|
|
12
|
+
}
|
|
13
|
+
function* invokeFromUi(profile, req) {
|
|
14
|
+
const invoke = req.toolInvoke;
|
|
15
|
+
if (!invoke) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
const result = executeTool(profile, invoke.name, invoke.arguments);
|
|
20
|
+
yield {
|
|
21
|
+
type: 'tool',
|
|
22
|
+
tool: { name: invoke.name, arguments: invoke.arguments, result },
|
|
23
|
+
};
|
|
24
|
+
if (result.status === 'error') {
|
|
25
|
+
yield toErrorEvent(formatToolFinding(result));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
yield { type: 'done' };
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
yield toErrorEvent(err);
|
|
32
|
+
yield { type: 'done' };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function executeCustomModelTool(profile, name, args) {
|
|
36
|
+
try {
|
|
37
|
+
const result = executeTool(profile, name, args);
|
|
38
|
+
const events = [
|
|
39
|
+
{
|
|
40
|
+
type: 'tool',
|
|
41
|
+
tool: { name, arguments: args, result },
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
if (result.status === 'error') {
|
|
45
|
+
events.push(toErrorEvent(formatToolFinding(result)));
|
|
46
|
+
}
|
|
47
|
+
return events;
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
return [toErrorEvent(err)];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function dispatchModelTool(profile, event, gated) {
|
|
54
|
+
const { tool } = event;
|
|
55
|
+
if (!tool) {
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
const name = tool.name;
|
|
59
|
+
if (CATALOG.tools[name]?.kind === 'builtin') {
|
|
60
|
+
return [event];
|
|
61
|
+
}
|
|
62
|
+
if (!gated.includes(name)) {
|
|
63
|
+
return [toErrorEvent(`Tool '${name}' is not gated on this turn`)];
|
|
64
|
+
}
|
|
65
|
+
const args = tool.arguments ?? {};
|
|
66
|
+
return executeCustomModelTool(profile, name, args);
|
|
67
|
+
}
|
|
68
|
+
function findDynamicDeclaration(tools, name) {
|
|
69
|
+
return tools?.find((t) => t.name === name);
|
|
70
|
+
}
|
|
71
|
+
async function checkDynamicAuthorization(decl, args, profile, sessionPermissions) {
|
|
72
|
+
if (!decl.canExecute) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
const decision = await decl.canExecute({
|
|
77
|
+
args,
|
|
78
|
+
profile,
|
|
79
|
+
sessionPermissions,
|
|
80
|
+
});
|
|
81
|
+
if (typeof decision === 'boolean' && !decision) {
|
|
82
|
+
return {
|
|
83
|
+
status: 'error',
|
|
84
|
+
finding: `Tool '${decl.name}' execution not authorized.`,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
if (typeof decision === 'object' && decision !== null) {
|
|
88
|
+
return decision;
|
|
89
|
+
}
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
94
|
+
return {
|
|
95
|
+
status: 'error',
|
|
96
|
+
finding: `Authorization error for '${decl.name}': ${msg}`,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function checkDynamicPermissionTier(decl, args, sessionPermissions) {
|
|
101
|
+
if (decl.permissionTier === 'session_consent' || decl.permissionTier === 'always_confirm') {
|
|
102
|
+
const isGranted = sessionPermissions?.includes(decl.name) || sessionPermissions?.includes('*');
|
|
103
|
+
if (!isGranted) {
|
|
104
|
+
return {
|
|
105
|
+
status: 'pause',
|
|
106
|
+
finding: `Tool '${decl.name}' requires ${decl.permissionTier} authorization.`,
|
|
107
|
+
data: { tool: decl.name, permissionTier: decl.permissionTier, args },
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
async function runDynamicHandler(decl, args) {
|
|
114
|
+
if (!decl.handler) {
|
|
115
|
+
return {
|
|
116
|
+
status: 'ok',
|
|
117
|
+
finding: `${decl.name} accepted (no handler)`,
|
|
118
|
+
data: args,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
return await decl.handler(args);
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
126
|
+
return { status: 'error', finding: msg };
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
async function executeDynamicTool(decl, args, profile, sessionPermissions) {
|
|
130
|
+
const authEnvelope = await checkDynamicAuthorization(decl, args, profile, sessionPermissions);
|
|
131
|
+
if (authEnvelope) {
|
|
132
|
+
return authEnvelope;
|
|
133
|
+
}
|
|
134
|
+
const permissionEnvelope = checkDynamicPermissionTier(decl, args, sessionPermissions);
|
|
135
|
+
if (permissionEnvelope) {
|
|
136
|
+
return permissionEnvelope;
|
|
137
|
+
}
|
|
138
|
+
return runDynamicHandler(decl, args);
|
|
139
|
+
}
|
|
140
|
+
function mergeDynamicTools(current, loaded) {
|
|
141
|
+
const merged = [...(current ?? [])];
|
|
142
|
+
for (const tool of loaded) {
|
|
143
|
+
const existing = merged.findIndex((item) => item.name === tool.name);
|
|
144
|
+
if (existing >= 0) {
|
|
145
|
+
merged[existing] = tool;
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
merged.push(tool);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return merged;
|
|
152
|
+
}
|
|
153
|
+
async function executeDynamicToolLoader(args) {
|
|
154
|
+
const { decl, toolArgs, profile, generation } = args;
|
|
155
|
+
const loader = generation.dynamicToolLoader;
|
|
156
|
+
if (!loader) {
|
|
157
|
+
return {
|
|
158
|
+
status: 'error',
|
|
159
|
+
finding: `Tool '${decl.name}' is marked as a loader but no loader is configured.`,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
const loaded = await loader({
|
|
163
|
+
name: decl.name,
|
|
164
|
+
args: toolArgs,
|
|
165
|
+
profile,
|
|
166
|
+
currentTools: generation.dynamicTools ?? [],
|
|
167
|
+
sessionPermissions: generation.sessionPermissions,
|
|
168
|
+
});
|
|
169
|
+
generation.dynamicTools = mergeDynamicTools(generation.dynamicTools, loaded);
|
|
170
|
+
return {
|
|
171
|
+
status: 'ok',
|
|
172
|
+
finding: `Loaded ${String(loaded.length)} dynamic tool schema(s).`,
|
|
173
|
+
data: { loadedTools: loaded.map((tool) => tool.name) },
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
function isActionableDynamicDeclaration(decl) {
|
|
177
|
+
return Boolean(decl?.handler || decl?.canExecute || decl?.permissionTier || decl?.loadsDynamicTools);
|
|
178
|
+
}
|
|
179
|
+
async function executeDynamicDeclaration(args) {
|
|
180
|
+
const { decl, toolArgs, profile, generation } = args;
|
|
181
|
+
const res = await executeDynamicTool(decl, toolArgs, profile, generation.sessionPermissions);
|
|
182
|
+
if (res.status === 'ok' && decl.loadsDynamicTools) {
|
|
183
|
+
return await executeDynamicToolLoader({
|
|
184
|
+
decl,
|
|
185
|
+
toolArgs,
|
|
186
|
+
profile,
|
|
187
|
+
generation,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
return res;
|
|
191
|
+
}
|
|
192
|
+
export { dispatchModelTool, executeDynamicDeclaration, findDynamicDeclaration, formatToolFinding, invokeFromUi, isActionableDynamicDeclaration, };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
function mapStrings(value, map) {
|
|
2
|
+
if (typeof value === 'string') {
|
|
3
|
+
return map(value);
|
|
4
|
+
}
|
|
5
|
+
if (Array.isArray(value)) {
|
|
6
|
+
return value.map((item) => mapStrings(item, map));
|
|
7
|
+
}
|
|
8
|
+
if (value && typeof value === 'object') {
|
|
9
|
+
const out = {};
|
|
10
|
+
for (const [key, nested] of Object.entries(value)) {
|
|
11
|
+
out[key] = mapStrings(nested, map);
|
|
12
|
+
}
|
|
13
|
+
return out;
|
|
14
|
+
}
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
export { mapStrings };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Profile, turn, tool, provider, egress, and event contracts for THEORUM.
|
|
3
|
+
*
|
|
4
|
+
* This entrypoint is type-first. Host applications import from here when they
|
|
5
|
+
* want to declare profiles, tool schemas, provider adapters, turn requests, or
|
|
6
|
+
* trace-safe event handlers without importing provider implementations.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
import "../../_dnt.polyfills.js";
|
|
11
|
+
export { runTurn } from './engine/runner.js';
|
|
12
|
+
export { CATALOG, clampThinkingLevel, clampThinkingLevelForApiId, geminiKindForMime, getTool, listBuiltinIds, mimeAllowed, mimeEssence, modelEntryByApiId, registerTools, requireModelSpec, resetTools, } from './registry/catalog.js';
|
|
13
|
+
export type { ProfileDefinition } from './registry/profiles.js';
|
|
14
|
+
export { clearProfiles, defineProfile, getProfile, hasProfile, listProfiles, registerProfile, registerProfiles, } from './registry/profiles.js';
|
|
15
|
+
export { projectProfile, resolveTurn } from './registry/resolve.js';
|
|
16
|
+
export { getStructured, registerStructured } from './registry/schemas.js';
|
|
17
|
+
export { executeTool } from './registry/tools.js';
|
|
18
|
+
export type * from './types.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Profile, turn, tool, provider, egress, and event contracts for THEORUM.
|
|
3
|
+
*
|
|
4
|
+
* This entrypoint is type-first. Host applications import from here when they
|
|
5
|
+
* want to declare profiles, tool schemas, provider adapters, turn requests, or
|
|
6
|
+
* trace-safe event handlers without importing provider implementations.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
import "../../_dnt.polyfills.js";
|
|
11
|
+
export { runTurn } from './engine/runner.js';
|
|
12
|
+
export { CATALOG, clampThinkingLevel, clampThinkingLevelForApiId, geminiKindForMime, getTool, listBuiltinIds, mimeAllowed, mimeEssence, modelEntryByApiId, registerTools, requireModelSpec, resetTools, } from './registry/catalog.js';
|
|
13
|
+
export { clearProfiles, defineProfile, getProfile, hasProfile, listProfiles, registerProfile, registerProfiles, } from './registry/profiles.js';
|
|
14
|
+
export { projectProfile, resolveTurn } from './registry/resolve.js';
|
|
15
|
+
export { getStructured, registerStructured } from './registry/schemas.js';
|
|
16
|
+
export { executeTool } from './registry/tools.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { MediaLimits, Profile, TurnBlob } from '../types.js';
|
|
2
|
+
declare function tooManyFilesMessage(maxFiles: number): string;
|
|
3
|
+
declare function fileTooLargeMessage(maxBytes: number): string;
|
|
4
|
+
declare function turnTooLargeMessage(maxTurnBytes: number): string;
|
|
5
|
+
declare function requireMediaLimits(profile: Profile): MediaLimits;
|
|
6
|
+
declare function sanitizeCsvText(text: string): string;
|
|
7
|
+
declare function assertAttachmentLimits(blobs: TurnBlob[], limits: MediaLimits): void;
|
|
8
|
+
declare function sanitizeTurnBlobs(attachments: TurnBlob[] | undefined, voice: TurnBlob[] | undefined, limits: MediaLimits | undefined): {
|
|
9
|
+
attachments?: TurnBlob[];
|
|
10
|
+
voice?: TurnBlob[];
|
|
11
|
+
};
|
|
12
|
+
declare function sanitizeTurnBlobsForProfile(profileId: string, attachments: TurnBlob[] | undefined, voice: TurnBlob[] | undefined): {
|
|
13
|
+
attachments?: TurnBlob[];
|
|
14
|
+
voice?: TurnBlob[];
|
|
15
|
+
};
|
|
16
|
+
export { assertAttachmentLimits, fileTooLargeMessage, requireMediaLimits, sanitizeCsvText, sanitizeTurnBlobs, sanitizeTurnBlobsForProfile, tooManyFilesMessage, turnTooLargeMessage, };
|