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,16 +1,18 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Protocol } from '../kernel/schema.js';
|
|
2
|
+
import type { ResolvedGeneration, TurnEvent, TurnRequest } from '../kernel/types.js';
|
|
2
3
|
import type { TraceRecord } from './trace-record.js';
|
|
3
4
|
declare function attachResolved(record: TraceRecord, args: {
|
|
4
5
|
safe: TurnRequest;
|
|
5
6
|
model?: string;
|
|
6
|
-
|
|
7
|
+
keySlot?: string;
|
|
7
8
|
generation?: ResolvedGeneration;
|
|
8
9
|
}): void;
|
|
9
10
|
declare function attachTape(record: TraceRecord, args: {
|
|
10
|
-
|
|
11
|
+
upstream?: unknown;
|
|
11
12
|
canary?: string;
|
|
12
13
|
system?: string;
|
|
13
14
|
generation?: ResolvedGeneration;
|
|
15
|
+
protocol?: Protocol;
|
|
14
16
|
}): Promise<void>;
|
|
15
|
-
declare function attachUsage(record: TraceRecord,
|
|
17
|
+
declare function attachUsage(record: TraceRecord, upstream: unknown, done: Record<string, unknown> | undefined, events?: TurnEvent[]): void;
|
|
16
18
|
export { attachResolved, attachTape, attachUsage };
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { providerCompleteRequest } from '../kernel/registry/provider-request.js';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { httpStatus } from './trace-usage.js';
|
|
2
|
+
import { tapeUpstream } from '../providers/shared/upstream-tape.js';
|
|
3
|
+
import { httpStatus, openAiFinishReason, tokensFromEvents } from './trace-usage.js';
|
|
5
4
|
function attachResolved(record, args) {
|
|
6
|
-
const { safe, model,
|
|
5
|
+
const { safe, model, keySlot, generation } = args;
|
|
7
6
|
if (safe.projectId) {
|
|
8
7
|
record.projectId = safe.projectId;
|
|
9
8
|
}
|
|
@@ -13,9 +12,6 @@ function attachResolved(record, args) {
|
|
|
13
12
|
if (safe.thinking !== undefined) {
|
|
14
13
|
record.thinking = safe.thinking;
|
|
15
14
|
}
|
|
16
|
-
if (safe.tools) {
|
|
17
|
-
record.tools = safe.tools;
|
|
18
|
-
}
|
|
19
15
|
if (safe.metadata) {
|
|
20
16
|
record.metadata = safe.metadata;
|
|
21
17
|
}
|
|
@@ -25,43 +21,61 @@ function attachResolved(record, args) {
|
|
|
25
21
|
apiId: generation?.apiId ?? model,
|
|
26
22
|
};
|
|
27
23
|
}
|
|
28
|
-
if (
|
|
29
|
-
record.
|
|
24
|
+
if (keySlot) {
|
|
25
|
+
record.keySlot = keySlot;
|
|
30
26
|
}
|
|
31
27
|
if (generation) {
|
|
32
|
-
|
|
28
|
+
const traceGeneration = {
|
|
33
29
|
thinking: generation.thinking,
|
|
34
30
|
summaries: generation.summaries,
|
|
35
31
|
temperature: generation.temperature,
|
|
36
32
|
maxOutputTokens: generation.maxOutputTokens,
|
|
37
33
|
builtins: generation.builtins,
|
|
38
|
-
|
|
34
|
+
visibleTools: generation.tools.visible,
|
|
39
35
|
structured: generation.structured,
|
|
40
36
|
image: generation.image,
|
|
41
37
|
};
|
|
38
|
+
record.generation = traceGeneration;
|
|
42
39
|
}
|
|
43
40
|
}
|
|
44
41
|
async function attachTape(record, args) {
|
|
45
|
-
const {
|
|
46
|
-
if (
|
|
47
|
-
record.
|
|
42
|
+
const { upstream, canary, system, generation, protocol } = args;
|
|
43
|
+
if (upstream !== undefined) {
|
|
44
|
+
record.upstreamLog = await tapeUpstream(upstream, canary ?? '');
|
|
48
45
|
}
|
|
49
|
-
if (generation && system !== undefined) {
|
|
50
|
-
|
|
46
|
+
if (generation && system !== undefined && protocol === 'geminiInteractions') {
|
|
47
|
+
const { toInteractionsBody } = await import('../providers/google/interactions/framing.js');
|
|
48
|
+
record.wire = await tapeUpstream(toInteractionsBody(providerCompleteRequest(generation, system)), canary ?? '');
|
|
51
49
|
}
|
|
52
50
|
}
|
|
53
|
-
function
|
|
51
|
+
function attachUsageTokens(record, done, events) {
|
|
54
52
|
if (done?.usage !== undefined) {
|
|
55
53
|
record.usage = done.usage;
|
|
54
|
+
return;
|
|
56
55
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
serviceTier: done?.service_tier ?? done?.serviceTier,
|
|
64
|
-
};
|
|
56
|
+
if (!events) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const tokens = tokensFromEvents(events);
|
|
60
|
+
if (tokens) {
|
|
61
|
+
record.usage = tokens;
|
|
65
62
|
}
|
|
66
63
|
}
|
|
64
|
+
function attachUpstreamSummary(record, upstream, done) {
|
|
65
|
+
const upStatus = httpStatus(upstream);
|
|
66
|
+
const finishReason = openAiFinishReason(upstream);
|
|
67
|
+
if (upStatus === undefined && !done && finishReason === undefined) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
record.upstream = {
|
|
71
|
+
status: upStatus,
|
|
72
|
+
id: done?.id,
|
|
73
|
+
finish: done?.status ?? finishReason,
|
|
74
|
+
serviceTier: done?.service_tier ?? done?.serviceTier,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function attachUsage(record, upstream, done, events) {
|
|
78
|
+
attachUsageTokens(record, done, events);
|
|
79
|
+
attachUpstreamSummary(record, upstream, done);
|
|
80
|
+
}
|
|
67
81
|
export { attachResolved, attachTape, attachUsage };
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module
|
|
8
8
|
*/
|
|
9
|
+
import type { Protocol } from '../kernel/schema.js';
|
|
9
10
|
import type { ResolvedGeneration, TurnEvent, TurnRequest } from '../kernel/types.js';
|
|
10
11
|
/** Hash-only image reference stored in trace records. */
|
|
11
12
|
export interface TraceImage {
|
|
@@ -47,20 +48,19 @@ interface TraceRecord {
|
|
|
47
48
|
projectId?: string;
|
|
48
49
|
select?: string;
|
|
49
50
|
thinking?: boolean;
|
|
50
|
-
tools?: TurnRequest['tools'];
|
|
51
51
|
metadata?: Record<string, unknown>;
|
|
52
52
|
model?: {
|
|
53
53
|
id: string;
|
|
54
54
|
apiId: string;
|
|
55
55
|
};
|
|
56
|
-
|
|
56
|
+
keySlot?: string;
|
|
57
57
|
generation?: {
|
|
58
58
|
thinking: string;
|
|
59
|
-
summaries
|
|
60
|
-
temperature
|
|
61
|
-
maxOutputTokens
|
|
59
|
+
summaries?: string;
|
|
60
|
+
temperature?: number;
|
|
61
|
+
maxOutputTokens?: number;
|
|
62
62
|
builtins: string[];
|
|
63
|
-
|
|
63
|
+
visibleTools: string[];
|
|
64
64
|
structured: string | null;
|
|
65
65
|
image: unknown;
|
|
66
66
|
};
|
|
@@ -75,7 +75,8 @@ interface TraceRecord {
|
|
|
75
75
|
};
|
|
76
76
|
wire?: unknown;
|
|
77
77
|
events: TraceEvent[];
|
|
78
|
-
|
|
78
|
+
/** Raw upstream tap rows (HTTP, SSE, provider events). */
|
|
79
|
+
upstreamLog?: unknown;
|
|
79
80
|
usage?: unknown;
|
|
80
81
|
upstream?: {
|
|
81
82
|
status?: unknown;
|
|
@@ -102,12 +103,13 @@ declare function buildRecord(args: {
|
|
|
102
103
|
events: TurnEvent[];
|
|
103
104
|
started: number;
|
|
104
105
|
model?: string;
|
|
105
|
-
|
|
106
|
+
keySlot?: string;
|
|
106
107
|
thrown?: unknown;
|
|
107
|
-
|
|
108
|
+
upstreamLog?: unknown;
|
|
108
109
|
canary?: string;
|
|
109
110
|
system?: string;
|
|
110
111
|
generation?: ResolvedGeneration;
|
|
112
|
+
protocol?: Protocol;
|
|
111
113
|
sanitizedReq?: TurnRequest;
|
|
112
114
|
}): Promise<TraceRecord>;
|
|
113
115
|
export type { TraceRecord };
|
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module
|
|
8
8
|
*/
|
|
9
|
+
import { OMIT_CANARY } from '../guardrails/canary.js';
|
|
9
10
|
import { isAbortError, publicError } from '../guardrails/error.js';
|
|
10
|
-
import { redactSensitiveOnly, sanitizeText,
|
|
11
|
-
import { OMIT_CANARY } from '../kernel/engine/boundary.js';
|
|
11
|
+
import { redactSensitiveOnly, sanitizeText, sanitizeTurnRequestForTrace, } from '../guardrails/sanitize.js';
|
|
12
12
|
import { sha256 } from '../kernel/engine/hash.js';
|
|
13
13
|
import { attachResolved, attachTape, attachUsage } from './trace-attach.js';
|
|
14
|
-
import { completedInteraction } from './trace-usage.js';
|
|
14
|
+
import { completedInteraction, stopKindFromEvents } from './trace-usage.js';
|
|
15
15
|
const TRACE_VERSION = 2;
|
|
16
16
|
const TITLE_MAX = 80;
|
|
17
17
|
function hashBlobs(blobs) {
|
|
@@ -38,13 +38,22 @@ async function snapshotEvent(event) {
|
|
|
38
38
|
row.structured = event.structured;
|
|
39
39
|
}
|
|
40
40
|
if (event.tool) {
|
|
41
|
-
const { name, arguments: args,
|
|
41
|
+
const { name, arguments: args, output, phase, failure } = event.tool;
|
|
42
42
|
row.tool = { name, arguments: args };
|
|
43
|
-
if (
|
|
43
|
+
if (output !== undefined && phase === 'complete') {
|
|
44
|
+
const data = typeof output === 'object' && output !== null
|
|
45
|
+
? output
|
|
46
|
+
: { value: output };
|
|
44
47
|
row.tool.result = {
|
|
45
|
-
status:
|
|
46
|
-
...(
|
|
47
|
-
|
|
48
|
+
status: 'ok',
|
|
49
|
+
...(typeof data.finding === 'string' ? { finding: data.finding } : {}),
|
|
50
|
+
data,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
else if (phase === 'error' && failure) {
|
|
54
|
+
row.tool.result = {
|
|
55
|
+
status: 'error',
|
|
56
|
+
finding: failure.message,
|
|
48
57
|
};
|
|
49
58
|
}
|
|
50
59
|
}
|
|
@@ -63,12 +72,7 @@ async function snapshotEvent(event) {
|
|
|
63
72
|
return row;
|
|
64
73
|
}
|
|
65
74
|
function requestForTrace(req) {
|
|
66
|
-
|
|
67
|
-
return sanitizeTurnRequest(req);
|
|
68
|
-
}
|
|
69
|
-
catch {
|
|
70
|
-
return { profile: req.profile, input: {} };
|
|
71
|
-
}
|
|
75
|
+
return sanitizeTurnRequestForTrace(req);
|
|
72
76
|
}
|
|
73
77
|
function internalError(err) {
|
|
74
78
|
if (typeof err === 'string') {
|
|
@@ -102,22 +106,28 @@ function attachFailure(record, thrown, lastErr, canary) {
|
|
|
102
106
|
}
|
|
103
107
|
}
|
|
104
108
|
async function buildRecord(args) {
|
|
105
|
-
const { req, events, started, model,
|
|
106
|
-
const
|
|
109
|
+
const { req, events, started, model, keySlot, thrown, upstreamLog, canary, system, generation } = args;
|
|
110
|
+
const protocol = args.protocol;
|
|
111
|
+
const traced = args.sanitizedReq ? { request: args.sanitizedReq } : requestForTrace(req);
|
|
112
|
+
const safe = traced.request;
|
|
107
113
|
const input = safe.input ?? {};
|
|
108
114
|
const snapped = await Promise.all(events.map((event) => snapshotEvent(event)));
|
|
109
115
|
const lastErr = [...snapped].reverse().find((row) => row.type === 'error');
|
|
110
|
-
const done = completedInteraction(gemini);
|
|
111
|
-
const status = done?.status;
|
|
112
116
|
const aborted = isAbortError(thrown);
|
|
113
|
-
const
|
|
117
|
+
const stopKind = stopKindFromEvents(events);
|
|
118
|
+
const done = completedInteraction(upstreamLog);
|
|
119
|
+
const interactionStatus = done?.status;
|
|
120
|
+
const cancelled = aborted ||
|
|
121
|
+
stopKind === 'cancelled' ||
|
|
122
|
+
(protocol === 'geminiInteractions' && interactionStatus === 'cancelled');
|
|
123
|
+
const ok = !(thrown || lastErr) && !cancelled;
|
|
114
124
|
const record = {
|
|
115
125
|
v: TRACE_VERSION,
|
|
116
126
|
id: crypto.randomUUID(),
|
|
117
127
|
ts: started,
|
|
118
128
|
ms: Date.now() - started,
|
|
119
129
|
streamed: true,
|
|
120
|
-
cancelled
|
|
130
|
+
cancelled,
|
|
121
131
|
previousInteractionId: safe.previousInteractionId ?? null,
|
|
122
132
|
store: safe.store ?? null,
|
|
123
133
|
profile: safe.profile,
|
|
@@ -135,10 +145,13 @@ async function buildRecord(args) {
|
|
|
135
145
|
if (title) {
|
|
136
146
|
record.title = title;
|
|
137
147
|
}
|
|
138
|
-
await attachTape(record, {
|
|
139
|
-
attachUsage(record,
|
|
140
|
-
attachResolved(record, { safe, model,
|
|
148
|
+
await attachTape(record, { upstream: upstreamLog, canary, system, generation, protocol });
|
|
149
|
+
attachUsage(record, upstreamLog, done, events);
|
|
150
|
+
attachResolved(record, { safe, model, keySlot, generation });
|
|
141
151
|
attachFailure(record, thrown, lastErr, canary);
|
|
152
|
+
if (traced.sanitizeError && !record.errorInternal) {
|
|
153
|
+
record.errorInternal = sanitizeText(`request sanitize for trace failed: ${traced.sanitizeError}`);
|
|
154
|
+
}
|
|
142
155
|
return record;
|
|
143
156
|
}
|
|
144
157
|
export { buildRecord };
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
declare function
|
|
3
|
-
|
|
1
|
+
import type { TurnEvent, TurnTokens } from '../kernel/types.js';
|
|
2
|
+
declare function completedInteraction(upstream: unknown): Record<string, unknown> | undefined;
|
|
3
|
+
/** Extract the terminal stop kind from the TurnEvent stream (protocol-agnostic). */
|
|
4
|
+
declare function stopKindFromEvents(events: TurnEvent[]): string | undefined;
|
|
5
|
+
/** Extract the last tokens snapshot from the TurnEvent stream. */
|
|
6
|
+
declare function tokensFromEvents(events: TurnEvent[]): TurnTokens | undefined;
|
|
7
|
+
/** Extract finish_reason from OpenAI-compat upstream tap rows. */
|
|
8
|
+
declare function openAiFinishReason(upstream: unknown): string | undefined;
|
|
9
|
+
declare function httpStatus(upstream: unknown): unknown;
|
|
10
|
+
export { completedInteraction, httpStatus, openAiFinishReason, stopKindFromEvents, tokensFromEvents, };
|
|
@@ -2,31 +2,84 @@ import { asRecord } from '../kernel/engine/record.js';
|
|
|
2
2
|
function eventName(row) {
|
|
3
3
|
return String(row.event_type ?? row.eventType ?? '');
|
|
4
4
|
}
|
|
5
|
-
function
|
|
6
|
-
if (!Array.isArray(
|
|
7
|
-
return
|
|
5
|
+
function upstreamRows(upstream) {
|
|
6
|
+
if (!Array.isArray(upstream)) {
|
|
7
|
+
return [];
|
|
8
8
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
return upstream
|
|
10
|
+
.map((item) => asRecord(item))
|
|
11
|
+
.filter((row) => row != null);
|
|
12
|
+
}
|
|
13
|
+
function lastUpstreamRow(upstream, pred) {
|
|
14
|
+
const rows = upstreamRows(upstream);
|
|
15
|
+
for (let i = rows.length - 1; i >= 0; i -= 1) {
|
|
16
|
+
if (pred(rows[i])) {
|
|
17
|
+
return rows[i];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
function firstUpstreamRow(upstream, pred) {
|
|
23
|
+
for (const row of upstreamRows(upstream)) {
|
|
24
|
+
if (pred(row)) {
|
|
25
|
+
return row;
|
|
16
26
|
}
|
|
17
27
|
}
|
|
18
28
|
return undefined;
|
|
19
29
|
}
|
|
20
|
-
function
|
|
21
|
-
|
|
30
|
+
function completedInteraction(upstream) {
|
|
31
|
+
const row = lastUpstreamRow(upstream, (r) => {
|
|
32
|
+
const name = eventName(r);
|
|
33
|
+
return name === 'interaction.completed' || name === 'interaction.complete';
|
|
34
|
+
});
|
|
35
|
+
return row ? (asRecord(row.interaction) ?? row) : undefined;
|
|
36
|
+
}
|
|
37
|
+
/** Extract the terminal stop kind from the TurnEvent stream (protocol-agnostic). */
|
|
38
|
+
function stopKindFromEvents(events) {
|
|
39
|
+
for (let i = events.length - 1; i >= 0; i -= 1) {
|
|
40
|
+
const ev = events[i];
|
|
41
|
+
if (ev?.type === 'done' && ev.stop) {
|
|
42
|
+
return ev.stop.kind;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
/** Extract the last tokens snapshot from the TurnEvent stream. */
|
|
48
|
+
function tokensFromEvents(events) {
|
|
49
|
+
for (let i = events.length - 1; i >= 0; i -= 1) {
|
|
50
|
+
const ev = events[i];
|
|
51
|
+
if (ev?.type === 'tokens' && ev.tokens) {
|
|
52
|
+
return ev.tokens;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
/** Extract finish_reason from OpenAI-compat upstream tap rows. */
|
|
58
|
+
function openAiFinishReason(upstream) {
|
|
59
|
+
const row = lastUpstreamRow(upstream, (r) => {
|
|
60
|
+
const choices = r.choices;
|
|
61
|
+
if (!Array.isArray(choices)) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
return choices.some((choice) => asRecord(choice)?.finish_reason != null);
|
|
65
|
+
});
|
|
66
|
+
if (!row) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
const choices = row.choices;
|
|
70
|
+
if (!Array.isArray(choices)) {
|
|
22
71
|
return undefined;
|
|
23
72
|
}
|
|
24
|
-
for (const
|
|
25
|
-
const
|
|
26
|
-
if (
|
|
27
|
-
return
|
|
73
|
+
for (const choice of choices) {
|
|
74
|
+
const c = asRecord(choice);
|
|
75
|
+
if (c?.finish_reason != null) {
|
|
76
|
+
return String(c.finish_reason);
|
|
28
77
|
}
|
|
29
78
|
}
|
|
30
79
|
return undefined;
|
|
31
80
|
}
|
|
32
|
-
|
|
81
|
+
function httpStatus(upstream) {
|
|
82
|
+
const row = firstUpstreamRow(upstream, (r) => eventName(r) === 'http_response');
|
|
83
|
+
return row?.status;
|
|
84
|
+
}
|
|
85
|
+
export { completedInteraction, httpStatus, openAiFinishReason, stopKindFromEvents, tokensFromEvents, };
|
|
@@ -2,8 +2,16 @@ import type { TraceRecord } from './trace-record.js';
|
|
|
2
2
|
/** Minimal async destination for completed turn trace records. */
|
|
3
3
|
interface TraceSink {
|
|
4
4
|
write: (record: TraceRecord) => Promise<void>;
|
|
5
|
+
/**
|
|
6
|
+
* Optional host hook when `writeTrace` catches record-build or write failures.
|
|
7
|
+
* Must not throw; tracing never fails the turn.
|
|
8
|
+
*/
|
|
9
|
+
onError?: (err: unknown) => void;
|
|
5
10
|
}
|
|
6
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* Write a trace record without allowing trace failures to fail the turn.
|
|
13
|
+
* Build/write errors are forwarded to `sink.onError` when provided.
|
|
14
|
+
*/
|
|
7
15
|
declare function writeTrace(sink: TraceSink, record: Promise<TraceRecord>): Promise<void>;
|
|
8
16
|
/** Trace sink that drops records. */
|
|
9
17
|
declare function noopSink(): TraceSink;
|
|
@@ -19,13 +19,21 @@ const MIB = KIB * KIB;
|
|
|
19
19
|
const ROTATE_MIB = 32;
|
|
20
20
|
const ROTATE_BYTES = ROTATE_MIB * MIB;
|
|
21
21
|
const FILE_DAY = /^turns-(\d{4}-\d{2}-\d{2})(?:-\d+)?\.jsonl$/;
|
|
22
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* Write a trace record without allowing trace failures to fail the turn.
|
|
24
|
+
* Build/write errors are forwarded to `sink.onError` when provided.
|
|
25
|
+
*/
|
|
23
26
|
async function writeTrace(sink, record) {
|
|
24
27
|
try {
|
|
25
28
|
await sink.write(await record);
|
|
26
29
|
}
|
|
27
|
-
catch {
|
|
28
|
-
|
|
30
|
+
catch (err) {
|
|
31
|
+
try {
|
|
32
|
+
sink.onError?.(err);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// Host onError must not fail the turn.
|
|
36
|
+
}
|
|
29
37
|
}
|
|
30
38
|
}
|
|
31
39
|
/** Trace sink that drops records. */
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Gemini TTS voice names for `speech.voice`.
|
|
3
|
+
*
|
|
4
|
+
* Standalone preset vocabulary — no kernel registry imports so docs UIs can
|
|
5
|
+
* import this file without pulling provider wiring.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
/** Common Gemini TTS voice names. */
|
|
10
|
+
export declare const GOOGLE_SPEECH_VOICES: readonly ["Zephyr", "Puck", "Charon", "Kore", "Fenrir", "Leda", "Orus", "Aoede", "Callirrhoe", "Autonoe", "Enceladus", "Iapetus", "Umbriel", "Algieba", "Despina", "Erinome", "Algenib", "Rasalgethi", "Laomedeia", "Achernar", "Alnilam", "Schedar", "Gacrux", "Pulcherrima", "Achird", "Zubenelgenubi", "Vindemiatrix", "Sadachbia", "Sadaltager", "Sulafat"];
|
|
11
|
+
export type GoogleSpeechVoice = (typeof GOOGLE_SPEECH_VOICES)[number];
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Gemini TTS voice names for `speech.voice`.
|
|
3
|
+
*
|
|
4
|
+
* Standalone preset vocabulary — no kernel registry imports so docs UIs can
|
|
5
|
+
* import this file without pulling provider wiring.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
/** Common Gemini TTS voice names. */
|
|
10
|
+
export const GOOGLE_SPEECH_VOICES = [
|
|
11
|
+
'Zephyr',
|
|
12
|
+
'Puck',
|
|
13
|
+
'Charon',
|
|
14
|
+
'Kore',
|
|
15
|
+
'Fenrir',
|
|
16
|
+
'Leda',
|
|
17
|
+
'Orus',
|
|
18
|
+
'Aoede',
|
|
19
|
+
'Callirrhoe',
|
|
20
|
+
'Autonoe',
|
|
21
|
+
'Enceladus',
|
|
22
|
+
'Iapetus',
|
|
23
|
+
'Umbriel',
|
|
24
|
+
'Algieba',
|
|
25
|
+
'Despina',
|
|
26
|
+
'Erinome',
|
|
27
|
+
'Algenib',
|
|
28
|
+
'Rasalgethi',
|
|
29
|
+
'Laomedeia',
|
|
30
|
+
'Achernar',
|
|
31
|
+
'Alnilam',
|
|
32
|
+
'Schedar',
|
|
33
|
+
'Gacrux',
|
|
34
|
+
'Pulcherrima',
|
|
35
|
+
'Achird',
|
|
36
|
+
'Zubenelgenubi',
|
|
37
|
+
'Vindemiatrix',
|
|
38
|
+
'Sadachbia',
|
|
39
|
+
'Sadaltager',
|
|
40
|
+
'Sulafat',
|
|
41
|
+
];
|
|
@@ -1,50 +1,62 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Google / Gemini convenience preset.
|
|
3
3
|
*
|
|
4
|
-
* Kernel stays open (`string` pins). This pack owns Google vocabularies as
|
|
5
|
-
* real unions so host profiles stay typed when they opt into the preset.
|
|
6
|
-
*
|
|
7
|
-
* Call `registerGooglePreset()` at host startup for tools; use the exported
|
|
8
|
-
* types/constants when authoring image/speech-adjacent profile fields.
|
|
9
|
-
*
|
|
10
4
|
* @module
|
|
11
5
|
*/
|
|
12
6
|
import "../../_dnt.polyfills.js";
|
|
13
|
-
import type { ProfileImageSpec,
|
|
14
|
-
|
|
15
|
-
declare const GOOGLE_BUILTIN_TOOLS: Record<string, ToolCatalogEntry>;
|
|
7
|
+
import type { ProfileImageSpec, ProfileLiveSpec, ProfileSpeechSpec } from '../kernel/types.js';
|
|
8
|
+
import { GOOGLE_SPEECH_VOICES, type GoogleSpeechVoice } from './google/speech-voices.js';
|
|
16
9
|
/** Common Gemini image input MIME allowlist. */
|
|
17
10
|
declare const GOOGLE_IMAGE_INPUT_MIMES: readonly ["image/png", "image/jpeg", "image/webp", "image/heic", "image/heif"];
|
|
18
11
|
/** Common voice/audio input MIME allowlist for Gemini multimodal. */
|
|
19
12
|
declare const GOOGLE_VOICE_INPUT_MIMES: readonly ["audio/webm", "audio/wav", "audio/mpeg", "audio/mp4"];
|
|
20
|
-
/** Common Gemini TTS voice names for `outputs.speech.voice`. */
|
|
21
|
-
declare const GOOGLE_SPEECH_VOICES: readonly ["Zephyr", "Puck", "Charon", "Kore", "Fenrir", "Leda", "Orus", "Aoede", "Callirrhoe", "Autonoe", "Enceladus", "Iapetus", "Umbriel", "Algieba", "Despina", "Erinome", "Algenib", "Rasalgethi", "Laomedeia", "Achernar", "Alnilam", "Schedar", "Gacrux", "Pulcherrima", "Achird", "Zubenelgenubi", "Vindemiatrix", "Sadachbia", "Sadaltager", "Sulafat"];
|
|
22
|
-
type GoogleSpeechVoice = (typeof GOOGLE_SPEECH_VOICES)[number];
|
|
23
|
-
/**
|
|
24
|
-
* `outputs.speech` pins narrowed to Google TTS vocabulary.
|
|
25
|
-
* Assignable to kernel `ProfileSpeechSpec`.
|
|
26
|
-
*/
|
|
27
13
|
type GoogleSpeechPins = Omit<ProfileSpeechSpec, 'voice'> & {
|
|
28
14
|
voice?: GoogleSpeechVoice;
|
|
29
15
|
};
|
|
30
|
-
|
|
16
|
+
type GoogleLivePins = Omit<ProfileLiveSpec, 'voice'> & {
|
|
17
|
+
voice?: GoogleSpeechVoice;
|
|
18
|
+
};
|
|
31
19
|
declare const GOOGLE_IMAGE_ASPECT_RATIOS: readonly ["1:1", "3:2", "2:3", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9"];
|
|
32
|
-
/** Image sizes commonly accepted by Gemini Flash Lite image. */
|
|
33
20
|
declare const GOOGLE_IMAGE_SIZES: readonly ["1K"];
|
|
34
21
|
type GoogleImageInputMime = (typeof GOOGLE_IMAGE_INPUT_MIMES)[number];
|
|
35
22
|
type GoogleVoiceInputMime = (typeof GOOGLE_VOICE_INPUT_MIMES)[number];
|
|
36
23
|
type GoogleImageAspectRatio = (typeof GOOGLE_IMAGE_ASPECT_RATIOS)[number];
|
|
37
24
|
type GoogleImageSize = (typeof GOOGLE_IMAGE_SIZES)[number];
|
|
38
|
-
/**
|
|
39
|
-
* `outputs.image` pins narrowed to Google image vocabulary.
|
|
40
|
-
* Assignable to kernel `ProfileImageSpec`.
|
|
41
|
-
*/
|
|
42
25
|
type GoogleImagePins = Omit<ProfileImageSpec, 'aspectRatio' | 'size' | 'mimeType'> & {
|
|
43
26
|
aspectRatio?: GoogleImageAspectRatio;
|
|
44
27
|
size?: GoogleImageSize;
|
|
45
28
|
mimeType?: GoogleImageInputMime | 'image/jpeg';
|
|
46
29
|
};
|
|
47
|
-
|
|
30
|
+
declare const GOOGLE_BUILTIN_TOOLS: ({
|
|
31
|
+
type: "builtin";
|
|
32
|
+
name: string;
|
|
33
|
+
description: string;
|
|
34
|
+
category: string;
|
|
35
|
+
access: "read-only";
|
|
36
|
+
paths: string[];
|
|
37
|
+
loadTier: "T0";
|
|
38
|
+
permission: "auto";
|
|
39
|
+
forcePaidKey: boolean;
|
|
40
|
+
wire: {
|
|
41
|
+
interactions: string;
|
|
42
|
+
openRouter: string;
|
|
43
|
+
};
|
|
44
|
+
} | {
|
|
45
|
+
type: "builtin";
|
|
46
|
+
name: string;
|
|
47
|
+
description: string;
|
|
48
|
+
category: string;
|
|
49
|
+
access: "read-only";
|
|
50
|
+
paths: string[];
|
|
51
|
+
loadTier: "T0";
|
|
52
|
+
permission: "auto";
|
|
53
|
+
wire: {
|
|
54
|
+
interactions: string;
|
|
55
|
+
openRouter?: undefined;
|
|
56
|
+
};
|
|
57
|
+
forcePaidKey?: undefined;
|
|
58
|
+
})[];
|
|
59
|
+
/** Register Google provider builtins into the process-local tool registry. */
|
|
48
60
|
declare function registerGooglePreset(): void;
|
|
49
|
-
export type { GoogleImageAspectRatio, GoogleImageInputMime, GoogleImagePins, GoogleImageSize, GoogleSpeechPins, GoogleSpeechVoice, GoogleVoiceInputMime, };
|
|
61
|
+
export type { GoogleImageAspectRatio, GoogleImageInputMime, GoogleImagePins, GoogleImageSize, GoogleLivePins, GoogleSpeechPins, GoogleSpeechVoice, GoogleVoiceInputMime, };
|
|
50
62
|
export { GOOGLE_BUILTIN_TOOLS, GOOGLE_IMAGE_ASPECT_RATIOS, GOOGLE_IMAGE_INPUT_MIMES, GOOGLE_IMAGE_SIZES, GOOGLE_SPEECH_VOICES, GOOGLE_VOICE_INPUT_MIMES, registerGooglePreset, };
|