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
|
@@ -48,12 +48,173 @@ function eventsFromAudio(delta) {
|
|
|
48
48
|
}
|
|
49
49
|
return [];
|
|
50
50
|
}
|
|
51
|
+
function nonEmptyString(value) {
|
|
52
|
+
if (typeof value === 'string' && value.trim()) {
|
|
53
|
+
return value;
|
|
54
|
+
}
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
function isCodeExecutionType(type) {
|
|
58
|
+
return type === 'code_execution_call' || type === 'code_execution_result';
|
|
59
|
+
}
|
|
60
|
+
function isGoogleBuiltinStepType(type) {
|
|
61
|
+
return type.startsWith('google_') || type === 'url_context_call' || type === 'url_context_result';
|
|
62
|
+
}
|
|
63
|
+
function googleBuiltinEvidence(raw) {
|
|
64
|
+
const type = String(raw.type ?? '');
|
|
65
|
+
return {
|
|
66
|
+
type: 'evidence',
|
|
67
|
+
evidence: {
|
|
68
|
+
provider: 'google',
|
|
69
|
+
raw,
|
|
70
|
+
...(type ? { kind: type } : {}),
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function mergeSandboxString(prev, next) {
|
|
75
|
+
if (typeof next !== 'string') {
|
|
76
|
+
return typeof prev === 'string' ? prev : undefined;
|
|
77
|
+
}
|
|
78
|
+
if (typeof prev !== 'string' || !prev) {
|
|
79
|
+
return next;
|
|
80
|
+
}
|
|
81
|
+
if (next.startsWith(prev) || prev.endsWith(next)) {
|
|
82
|
+
return next.length >= prev.length ? next : prev;
|
|
83
|
+
}
|
|
84
|
+
return prev + next;
|
|
85
|
+
}
|
|
86
|
+
function argumentsField(record) {
|
|
87
|
+
if (!record) {
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
return record.arguments;
|
|
91
|
+
}
|
|
92
|
+
function mergedArgObject(prevArgs, incomingArgs) {
|
|
93
|
+
const language = incomingArgs?.language;
|
|
94
|
+
return {
|
|
95
|
+
...prevArgs,
|
|
96
|
+
...incomingArgs,
|
|
97
|
+
code: mergeSandboxString(prevArgs?.code, incomingArgs?.code),
|
|
98
|
+
language: language === undefined ? prevArgs?.language : language,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function mergeStringArguments(prev, next) {
|
|
102
|
+
if (typeof next === 'string') {
|
|
103
|
+
return mergeSandboxString(prev, next);
|
|
104
|
+
}
|
|
105
|
+
if (typeof prev === 'string') {
|
|
106
|
+
return mergeSandboxString(prev, next);
|
|
107
|
+
}
|
|
108
|
+
if (next !== undefined) {
|
|
109
|
+
return next;
|
|
110
|
+
}
|
|
111
|
+
return prev;
|
|
112
|
+
}
|
|
113
|
+
function mergeCodeExecutionArguments(existing, incoming) {
|
|
114
|
+
const prevArgs = asRecord(argumentsField(existing));
|
|
115
|
+
const incomingArgs = asRecord(incoming.arguments);
|
|
116
|
+
if (prevArgs) {
|
|
117
|
+
return mergedArgObject(prevArgs, incomingArgs);
|
|
118
|
+
}
|
|
119
|
+
if (incomingArgs) {
|
|
120
|
+
return mergedArgObject(prevArgs, incomingArgs);
|
|
121
|
+
}
|
|
122
|
+
return mergeStringArguments(argumentsField(existing), incoming.arguments);
|
|
123
|
+
}
|
|
124
|
+
/** Merge a later code-exec delta/step onto an earlier snapshot (partial code/stdout). */
|
|
125
|
+
function mergeCodeExecutionPayload(existing, incoming) {
|
|
126
|
+
const next = { ...existing, ...incoming };
|
|
127
|
+
const argumentsValue = mergeCodeExecutionArguments(existing, incoming);
|
|
128
|
+
if (argumentsValue !== undefined) {
|
|
129
|
+
next.arguments = argumentsValue;
|
|
130
|
+
}
|
|
131
|
+
const result = mergeSandboxString(existing?.result, incoming.result);
|
|
132
|
+
if (result !== undefined) {
|
|
133
|
+
next.result = result;
|
|
134
|
+
}
|
|
135
|
+
return next;
|
|
136
|
+
}
|
|
137
|
+
function codeFromArguments(args) {
|
|
138
|
+
if (typeof args === 'string') {
|
|
139
|
+
return { code: args };
|
|
140
|
+
}
|
|
141
|
+
const rec = asRecord(args);
|
|
142
|
+
if (!rec) {
|
|
143
|
+
return {};
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
...(typeof rec.code === 'string' ? { code: rec.code } : {}),
|
|
147
|
+
...(typeof rec.language === 'string' ? { language: rec.language } : {}),
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function sandboxReportedError(raw) {
|
|
151
|
+
if (raw.is_error === undefined && raw.isError === undefined) {
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
return raw.is_error === true || raw.isError === true;
|
|
155
|
+
}
|
|
156
|
+
function applyCodeExecutionFields(evidence, raw) {
|
|
157
|
+
const type = String(raw.type ?? '');
|
|
158
|
+
if (isCodeExecutionType(type)) {
|
|
159
|
+
evidence.kind = type;
|
|
160
|
+
}
|
|
161
|
+
const fromArgs = codeFromArguments(raw.arguments);
|
|
162
|
+
if (fromArgs.code) {
|
|
163
|
+
evidence.code = fromArgs.code;
|
|
164
|
+
}
|
|
165
|
+
if (fromArgs.language) {
|
|
166
|
+
evidence.language = fromArgs.language;
|
|
167
|
+
}
|
|
168
|
+
if (typeof raw.result === 'string') {
|
|
169
|
+
evidence.result = raw.result;
|
|
170
|
+
}
|
|
171
|
+
const isError = sandboxReportedError(raw);
|
|
172
|
+
if (isError !== undefined) {
|
|
173
|
+
evidence.isError = isError;
|
|
174
|
+
}
|
|
175
|
+
const id = nonEmptyString(raw.id);
|
|
176
|
+
if (id) {
|
|
177
|
+
evidence.id = id;
|
|
178
|
+
}
|
|
179
|
+
const callId = nonEmptyString(raw.call_id ?? raw.callId);
|
|
180
|
+
if (callId) {
|
|
181
|
+
evidence.callId = callId;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/** Normalize a Google `code_execution_*` step/delta into an `evidence` event. */
|
|
185
|
+
function codeExecutionEvidence(raw) {
|
|
186
|
+
const evidence = { provider: 'google', raw };
|
|
187
|
+
applyCodeExecutionFields(evidence, raw);
|
|
188
|
+
return { type: 'evidence', evidence };
|
|
189
|
+
}
|
|
190
|
+
/** Stable key so streamed deltas and batched `steps[]` do not double-emit. */
|
|
191
|
+
function codeExecutionStepKey(raw, index) {
|
|
192
|
+
const type = String(raw.type ?? 'code_execution');
|
|
193
|
+
const id = nonEmptyString(raw.id) ?? nonEmptyString(raw.call_id ?? raw.callId);
|
|
194
|
+
if (id) {
|
|
195
|
+
return `${type}:${id}`;
|
|
196
|
+
}
|
|
197
|
+
const fromArgs = codeFromArguments(raw.arguments);
|
|
198
|
+
if (fromArgs.code) {
|
|
199
|
+
return `${type}:code:${fromArgs.code}`;
|
|
200
|
+
}
|
|
201
|
+
if (typeof raw.result === 'string') {
|
|
202
|
+
return `${type}:result:${raw.result}`;
|
|
203
|
+
}
|
|
204
|
+
if (raw.result !== undefined) {
|
|
205
|
+
return `${type}:result:${JSON.stringify(raw.result)}`;
|
|
206
|
+
}
|
|
207
|
+
return `${type}:idx:${String(index ?? '')}`;
|
|
208
|
+
}
|
|
51
209
|
function eventsFromDelta(deltaValue) {
|
|
52
210
|
const delta = asRecord(deltaValue);
|
|
53
211
|
if (!delta) {
|
|
54
212
|
return [];
|
|
55
213
|
}
|
|
56
214
|
const deltaType = String(delta.type ?? '');
|
|
215
|
+
if (isCodeExecutionType(deltaType)) {
|
|
216
|
+
return [codeExecutionEvidence(delta)];
|
|
217
|
+
}
|
|
57
218
|
if (deltaType === 'thought_summary' || deltaType === 'thought') {
|
|
58
219
|
return eventIfText('thought', delta);
|
|
59
220
|
}
|
|
@@ -86,51 +247,166 @@ function mediaFromOutputItem(item) {
|
|
|
86
247
|
}
|
|
87
248
|
return mediaFromRecord(rec);
|
|
88
249
|
}
|
|
89
|
-
function
|
|
250
|
+
function mediaEventsFromOutputs(outputs) {
|
|
90
251
|
if (!Array.isArray(outputs)) {
|
|
91
|
-
return
|
|
252
|
+
return [];
|
|
92
253
|
}
|
|
254
|
+
const events = [];
|
|
93
255
|
for (const item of outputs) {
|
|
94
256
|
const media = mediaFromOutputItem(item);
|
|
95
257
|
if (media) {
|
|
96
|
-
|
|
258
|
+
events.push(media);
|
|
97
259
|
}
|
|
98
260
|
}
|
|
99
|
-
return
|
|
261
|
+
return events;
|
|
100
262
|
}
|
|
101
|
-
function
|
|
263
|
+
function mediaEventsFromComplete(event) {
|
|
102
264
|
const interaction = asRecord(event.interaction) ?? event;
|
|
265
|
+
const events = [];
|
|
103
266
|
const directImage = asRecord(interaction.output_image);
|
|
104
267
|
if (directImage) {
|
|
105
268
|
const media = mediaFromRecord(directImage);
|
|
106
269
|
if (media) {
|
|
107
|
-
|
|
270
|
+
events.push(media);
|
|
108
271
|
}
|
|
109
272
|
}
|
|
110
273
|
const directAudio = asRecord(interaction.output_audio);
|
|
111
274
|
if (directAudio) {
|
|
112
275
|
const media = mediaFromRecord(directAudio);
|
|
113
276
|
if (media) {
|
|
114
|
-
|
|
277
|
+
events.push(media);
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
const { data } = directAudio;
|
|
281
|
+
if (typeof data === 'string' && data) {
|
|
282
|
+
events.push({ type: 'media', media: { mimeType: 'audio/pcm', data } });
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
if (events.length === 0) {
|
|
287
|
+
events.push(...mediaEventsFromOutputs(interaction.outputs));
|
|
288
|
+
}
|
|
289
|
+
return events;
|
|
290
|
+
}
|
|
291
|
+
function eventsFromModelOutputContent(step, alreadyText) {
|
|
292
|
+
const events = [];
|
|
293
|
+
const content = step.content;
|
|
294
|
+
if (!Array.isArray(content)) {
|
|
295
|
+
return events;
|
|
296
|
+
}
|
|
297
|
+
for (const block of content) {
|
|
298
|
+
const rec = asRecord(block);
|
|
299
|
+
if (!rec) {
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
const type = String(rec.type ?? '');
|
|
303
|
+
if (type === 'text' && !alreadyText) {
|
|
304
|
+
events.push(...eventIfText('text', rec));
|
|
305
|
+
}
|
|
306
|
+
if (type === 'image' || type === 'media') {
|
|
307
|
+
events.push(...eventsFromImage(rec));
|
|
115
308
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
309
|
+
if (type === 'audio' || type === 'output_audio') {
|
|
310
|
+
events.push(...eventsFromAudio(rec));
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return events;
|
|
314
|
+
}
|
|
315
|
+
function eventsFromInteractionStep(step, sawText) {
|
|
316
|
+
const type = String(step.type ?? '');
|
|
317
|
+
if (isCodeExecutionType(type)) {
|
|
318
|
+
return { events: [codeExecutionEvidence(step)], sawText };
|
|
319
|
+
}
|
|
320
|
+
if (isGoogleBuiltinStepType(type)) {
|
|
321
|
+
return { events: [googleBuiltinEvidence(step)], sawText };
|
|
322
|
+
}
|
|
323
|
+
if (type !== 'model_output') {
|
|
324
|
+
return { events: [], sawText };
|
|
325
|
+
}
|
|
326
|
+
const fromOutput = eventsFromModelOutputContent(step, sawText);
|
|
327
|
+
return {
|
|
328
|
+
events: fromOutput,
|
|
329
|
+
sawText: sawText || fromOutput.some((item) => item.type === 'text'),
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Replay a completed Interactions `steps[]` array (non-SSE or stream tail).
|
|
334
|
+
* Emits typed code-execution evidence plus model_output text/media.
|
|
335
|
+
*/
|
|
336
|
+
function eventsFromInteractionSteps(steps, alreadyText) {
|
|
337
|
+
const events = [];
|
|
338
|
+
let sawText = alreadyText;
|
|
339
|
+
for (const stepValue of steps) {
|
|
340
|
+
const step = asRecord(stepValue);
|
|
341
|
+
if (!step) {
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
const next = eventsFromInteractionStep(step, sawText);
|
|
345
|
+
events.push(...next.events);
|
|
346
|
+
sawText = next.sawText;
|
|
347
|
+
}
|
|
348
|
+
return events;
|
|
349
|
+
}
|
|
350
|
+
function cleanMapsTitle(title) {
|
|
351
|
+
const suffix = 'google maps';
|
|
352
|
+
const trimmed = title.trimEnd();
|
|
353
|
+
if (trimmed.length < suffix.length) {
|
|
354
|
+
return title.trim();
|
|
355
|
+
}
|
|
356
|
+
if (trimmed.slice(-suffix.length).toLowerCase() !== suffix) {
|
|
357
|
+
return title.trim();
|
|
358
|
+
}
|
|
359
|
+
let end = trimmed.length - suffix.length;
|
|
360
|
+
while (end > 0 && /\s/.test(trimmed[end - 1])) {
|
|
361
|
+
end--;
|
|
362
|
+
}
|
|
363
|
+
if (end > 0 && trimmed[end - 1] === '-') {
|
|
364
|
+
end--;
|
|
365
|
+
while (end > 0 && /\s/.test(trimmed[end - 1])) {
|
|
366
|
+
end--;
|
|
120
367
|
}
|
|
121
368
|
}
|
|
122
|
-
return
|
|
369
|
+
return trimmed.slice(0, end).trimEnd();
|
|
370
|
+
}
|
|
371
|
+
function isPrimaryMapsPlace(name, uri) {
|
|
372
|
+
if (/^Review of\b/i.test(name)) {
|
|
373
|
+
return false;
|
|
374
|
+
}
|
|
375
|
+
if (/\/maps\/reviews\//i.test(uri)) {
|
|
376
|
+
return false;
|
|
377
|
+
}
|
|
378
|
+
return true;
|
|
379
|
+
}
|
|
380
|
+
function placeIdFromRecord(record) {
|
|
381
|
+
return nonEmptyString(record.placeId ?? record.place_id);
|
|
123
382
|
}
|
|
124
383
|
function sourceFromMaps(maps) {
|
|
125
|
-
const uri = maps.uri ?? maps.googleMapsUri ?? maps.google_maps_uri;
|
|
384
|
+
const uri = maps.uri ?? maps.googleMapsUri ?? maps.google_maps_uri ?? maps.url;
|
|
126
385
|
if (typeof uri !== 'string' || !uri) {
|
|
127
386
|
return undefined;
|
|
128
387
|
}
|
|
129
|
-
const
|
|
388
|
+
const rawTitle = maps.title ?? maps.name;
|
|
389
|
+
const title = typeof rawTitle === 'string' && rawTitle ? cleanMapsTitle(rawTitle) : uri;
|
|
390
|
+
const placeId = placeIdFromRecord(maps);
|
|
130
391
|
return {
|
|
131
392
|
type: 'maps',
|
|
132
393
|
uri,
|
|
133
|
-
title
|
|
394
|
+
title,
|
|
395
|
+
...(placeId ? { placeId } : {}),
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
/** Classic grounding chunk shape hosts already parse (`chunks[].maps`). */
|
|
399
|
+
function chunkFromMapsPlace(place) {
|
|
400
|
+
const source = sourceFromMaps(place);
|
|
401
|
+
if (!source || !isPrimaryMapsPlace(source.title, source.uri)) {
|
|
402
|
+
return undefined;
|
|
403
|
+
}
|
|
404
|
+
return {
|
|
405
|
+
maps: {
|
|
406
|
+
title: source.title,
|
|
407
|
+
uri: source.uri,
|
|
408
|
+
...(source.placeId ? { placeId: source.placeId } : {}),
|
|
409
|
+
},
|
|
134
410
|
};
|
|
135
411
|
}
|
|
136
412
|
function sourceFromWeb(web) {
|
|
@@ -149,9 +425,18 @@ function pushUniqueSource(sources, source) {
|
|
|
149
425
|
if (!source) {
|
|
150
426
|
return;
|
|
151
427
|
}
|
|
152
|
-
if (
|
|
153
|
-
|
|
428
|
+
if (sources.some((item) => {
|
|
429
|
+
if (item.type !== source.type) {
|
|
430
|
+
return false;
|
|
431
|
+
}
|
|
432
|
+
if (source.placeId && item.placeId && source.placeId === item.placeId) {
|
|
433
|
+
return true;
|
|
434
|
+
}
|
|
435
|
+
return item.uri === source.uri;
|
|
436
|
+
})) {
|
|
437
|
+
return;
|
|
154
438
|
}
|
|
439
|
+
sources.push(source);
|
|
155
440
|
}
|
|
156
441
|
function groundingChunks(metadata) {
|
|
157
442
|
const chunks = metadata.groundingChunks ?? metadata.grounding_chunks;
|
|
@@ -168,6 +453,180 @@ function searchHtml(metadata) {
|
|
|
168
453
|
}
|
|
169
454
|
return undefined;
|
|
170
455
|
}
|
|
456
|
+
function searchSuggestionsFromRecord(record) {
|
|
457
|
+
return nonEmptyString(record.search_suggestions ?? record.searchSuggestions);
|
|
458
|
+
}
|
|
459
|
+
function firstSearchSuggestions(items) {
|
|
460
|
+
if (!Array.isArray(items)) {
|
|
461
|
+
return undefined;
|
|
462
|
+
}
|
|
463
|
+
for (const item of items) {
|
|
464
|
+
const record = asRecord(item);
|
|
465
|
+
if (!record) {
|
|
466
|
+
continue;
|
|
467
|
+
}
|
|
468
|
+
const html = searchSuggestionsFromRecord(record);
|
|
469
|
+
if (html) {
|
|
470
|
+
return html;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
return undefined;
|
|
474
|
+
}
|
|
475
|
+
/** Interactions streams search chips as `search_suggestions` HTML, not classic entry points. */
|
|
476
|
+
function searchSuggestionsHtml(step) {
|
|
477
|
+
return (searchSuggestionsFromRecord(step) ??
|
|
478
|
+
firstSearchSuggestions(step.result) ??
|
|
479
|
+
firstSearchSuggestions(step.content));
|
|
480
|
+
}
|
|
481
|
+
function sourceFromAnnotation(ann) {
|
|
482
|
+
const record = asRecord(ann);
|
|
483
|
+
if (!record) {
|
|
484
|
+
return undefined;
|
|
485
|
+
}
|
|
486
|
+
const uri = nonEmptyString(record.url ?? record.uri);
|
|
487
|
+
if (!uri) {
|
|
488
|
+
return undefined;
|
|
489
|
+
}
|
|
490
|
+
const kind = String(record.type ?? '');
|
|
491
|
+
const rawTitle = nonEmptyString(record.title ?? record.name) ?? uri;
|
|
492
|
+
if (kind === 'place_citation') {
|
|
493
|
+
const title = cleanMapsTitle(rawTitle);
|
|
494
|
+
if (!isPrimaryMapsPlace(title, uri)) {
|
|
495
|
+
return undefined;
|
|
496
|
+
}
|
|
497
|
+
const placeId = placeIdFromRecord(record);
|
|
498
|
+
return {
|
|
499
|
+
type: 'maps',
|
|
500
|
+
uri,
|
|
501
|
+
title,
|
|
502
|
+
...(placeId ? { placeId } : {}),
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
if (kind === 'url_citation' || kind === 'citation' || !kind) {
|
|
506
|
+
return { type: 'web', uri, title: rawTitle };
|
|
507
|
+
}
|
|
508
|
+
return undefined;
|
|
509
|
+
}
|
|
510
|
+
function pushUniqueChunk(chunks, chunk) {
|
|
511
|
+
const maps = asRecord(asRecord(chunk)?.maps);
|
|
512
|
+
if (!maps) {
|
|
513
|
+
chunks.push(chunk);
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
const placeId = placeIdFromRecord(maps);
|
|
517
|
+
const uri = nonEmptyString(maps.uri ?? maps.url);
|
|
518
|
+
if (chunks.some((existing) => {
|
|
519
|
+
const existingMaps = asRecord(asRecord(existing)?.maps);
|
|
520
|
+
if (!existingMaps) {
|
|
521
|
+
return false;
|
|
522
|
+
}
|
|
523
|
+
const existingId = placeIdFromRecord(existingMaps);
|
|
524
|
+
if (placeId && existingId && placeId === existingId) {
|
|
525
|
+
return true;
|
|
526
|
+
}
|
|
527
|
+
return Boolean(uri && nonEmptyString(existingMaps.uri ?? existingMaps.url) === uri);
|
|
528
|
+
})) {
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
chunks.push(chunk);
|
|
532
|
+
}
|
|
533
|
+
/** Interactions `google_maps_result.result[].places[]` — not classic groundingChunks. */
|
|
534
|
+
function chunksAndSourcesFromMapsResult(result) {
|
|
535
|
+
const chunks = [];
|
|
536
|
+
const sources = [];
|
|
537
|
+
if (!Array.isArray(result)) {
|
|
538
|
+
return { chunks, sources };
|
|
539
|
+
}
|
|
540
|
+
for (const entry of result) {
|
|
541
|
+
const record = asRecord(entry);
|
|
542
|
+
if (!record) {
|
|
543
|
+
continue;
|
|
544
|
+
}
|
|
545
|
+
const places = record.places;
|
|
546
|
+
if (!Array.isArray(places)) {
|
|
547
|
+
continue;
|
|
548
|
+
}
|
|
549
|
+
for (const placeValue of places) {
|
|
550
|
+
const place = asRecord(placeValue);
|
|
551
|
+
if (!place) {
|
|
552
|
+
continue;
|
|
553
|
+
}
|
|
554
|
+
const chunk = chunkFromMapsPlace(place);
|
|
555
|
+
if (!chunk) {
|
|
556
|
+
continue;
|
|
557
|
+
}
|
|
558
|
+
pushUniqueChunk(chunks, chunk);
|
|
559
|
+
pushUniqueSource(sources, sourceFromMaps(place));
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
return { chunks, sources };
|
|
563
|
+
}
|
|
564
|
+
function appendAnnotationSources(into, annotations) {
|
|
565
|
+
for (const source of sourcesFromAnnotations(annotations)) {
|
|
566
|
+
pushUniqueSource(into, source);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
function sourcesFromAnnotations(annotations) {
|
|
570
|
+
if (!Array.isArray(annotations)) {
|
|
571
|
+
return [];
|
|
572
|
+
}
|
|
573
|
+
const sources = [];
|
|
574
|
+
for (const ann of annotations) {
|
|
575
|
+
pushUniqueSource(sources, sourceFromAnnotation(ann));
|
|
576
|
+
}
|
|
577
|
+
return sources;
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Wrap Interactions tool-result steps (google_search_result, maps, etc.) into grounding.
|
|
581
|
+
* Preserves the raw step on `metadata` so hosts can inspect everything Gemini returned.
|
|
582
|
+
*
|
|
583
|
+
* Maps places arrive as `google_maps_result.result[].places[]` and as
|
|
584
|
+
* `place_citation` annotations on model_output content — not classic
|
|
585
|
+
* `grounding_metadata.groundingChunks`. Emit both `sources` and `chunks`
|
|
586
|
+
* (`chunks[].maps`) so hosts share one parse shape.
|
|
587
|
+
*/
|
|
588
|
+
function groundingFromInteractionsTool(step) {
|
|
589
|
+
const sources = [];
|
|
590
|
+
const chunks = [];
|
|
591
|
+
appendAnnotationSources(sources, step.annotations);
|
|
592
|
+
if (Array.isArray(step.content)) {
|
|
593
|
+
for (const block of step.content) {
|
|
594
|
+
const record = asRecord(block);
|
|
595
|
+
if (record) {
|
|
596
|
+
appendAnnotationSources(sources, record.annotations);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
for (const source of sources) {
|
|
601
|
+
if (source.type !== 'maps') {
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
604
|
+
pushUniqueChunk(chunks, {
|
|
605
|
+
maps: {
|
|
606
|
+
title: source.title,
|
|
607
|
+
uri: source.uri,
|
|
608
|
+
...(source.placeId ? { placeId: source.placeId } : {}),
|
|
609
|
+
},
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
const fromMapsResult = chunksAndSourcesFromMapsResult(step.result);
|
|
613
|
+
for (const chunk of fromMapsResult.chunks) {
|
|
614
|
+
pushUniqueChunk(chunks, chunk);
|
|
615
|
+
}
|
|
616
|
+
for (const source of fromMapsResult.sources) {
|
|
617
|
+
pushUniqueSource(sources, source);
|
|
618
|
+
}
|
|
619
|
+
const html = searchSuggestionsHtml(step);
|
|
620
|
+
if (!html && sources.length === 0 && chunks.length === 0) {
|
|
621
|
+
return undefined;
|
|
622
|
+
}
|
|
623
|
+
return {
|
|
624
|
+
metadata: step,
|
|
625
|
+
...(chunks.length > 0 ? { chunks } : {}),
|
|
626
|
+
...(html ? { searchHtml: html } : {}),
|
|
627
|
+
sources,
|
|
628
|
+
};
|
|
629
|
+
}
|
|
171
630
|
function sourcesFromChunks(chunks) {
|
|
172
631
|
const sources = [];
|
|
173
632
|
for (const chunk of chunks) {
|
|
@@ -193,7 +652,10 @@ function mergeGrounding(a, b) {
|
|
|
193
652
|
if (!b) {
|
|
194
653
|
return a;
|
|
195
654
|
}
|
|
196
|
-
const chunks = [
|
|
655
|
+
const chunks = [];
|
|
656
|
+
for (const chunk of [...(a.chunks ?? []), ...(b.chunks ?? [])]) {
|
|
657
|
+
pushUniqueChunk(chunks, chunk);
|
|
658
|
+
}
|
|
197
659
|
const sources = [...a.sources];
|
|
198
660
|
for (const source of b.sources) {
|
|
199
661
|
pushUniqueSource(sources, source);
|
|
@@ -238,6 +700,8 @@ function groundingFromStep(stepValue) {
|
|
|
238
700
|
grounding = mergeGrounding(grounding, groundingFromMetadata(groundingMetadataFromRecord(asRecord(block) ?? {})));
|
|
239
701
|
}
|
|
240
702
|
}
|
|
703
|
+
// Interactions search/maps tool results: chips + citations live on the step/delta itself.
|
|
704
|
+
grounding = mergeGrounding(grounding, groundingFromInteractionsTool(step));
|
|
241
705
|
return grounding;
|
|
242
706
|
}
|
|
243
707
|
function groundingFromEvent(event) {
|
|
@@ -299,6 +763,13 @@ const TOOL_KEYS = [
|
|
|
299
763
|
'toolTokens',
|
|
300
764
|
'toolUse',
|
|
301
765
|
];
|
|
766
|
+
const INTERMEDIATE_KEYS = [
|
|
767
|
+
'total_intermediate_tokens',
|
|
768
|
+
'totalIntermediateTokens',
|
|
769
|
+
'intermediate_tokens',
|
|
770
|
+
'intermediateTokens',
|
|
771
|
+
'intermediate',
|
|
772
|
+
];
|
|
302
773
|
const TOTAL_KEYS = [
|
|
303
774
|
'total_tokens',
|
|
304
775
|
'totalTokens',
|
|
@@ -327,9 +798,17 @@ function extractUsageTokens(raw) {
|
|
|
327
798
|
const output = pickNumericField(r, OUTPUT_KEYS);
|
|
328
799
|
const thinking = pickNumericField(r, THINKING_KEYS);
|
|
329
800
|
const toolUse = pickNumericField(r, TOOL_KEYS);
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
|
|
801
|
+
const intermediate = pickNumericField(r, INTERMEDIATE_KEYS);
|
|
802
|
+
const total = pickNumericField(r, TOTAL_KEYS) || input + output + thinking + toolUse + intermediate;
|
|
803
|
+
if (input > 0 || output > 0 || thinking > 0 || toolUse > 0 || intermediate > 0 || total > 0) {
|
|
804
|
+
return {
|
|
805
|
+
input,
|
|
806
|
+
output,
|
|
807
|
+
thinking,
|
|
808
|
+
toolUse,
|
|
809
|
+
total,
|
|
810
|
+
...(intermediate > 0 ? { intermediate } : {}),
|
|
811
|
+
};
|
|
333
812
|
}
|
|
334
813
|
return undefined;
|
|
335
814
|
}
|
|
@@ -361,13 +840,23 @@ function extractTokenEvent(event, interaction) {
|
|
|
361
840
|
function eventsFromComplete(event, alreadyText) {
|
|
362
841
|
const interaction = asRecord(event.interaction) ?? event;
|
|
363
842
|
const events = [];
|
|
843
|
+
let sawText = alreadyText;
|
|
844
|
+
const steps = interaction.steps;
|
|
845
|
+
if (Array.isArray(steps)) {
|
|
846
|
+
const fromSteps = eventsFromInteractionSteps(steps, sawText);
|
|
847
|
+
events.push(...fromSteps);
|
|
848
|
+
if (fromSteps.some((item) => item.type === 'text')) {
|
|
849
|
+
sawText = true;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
364
852
|
const outputText = interaction.output_text;
|
|
365
|
-
if (!
|
|
853
|
+
if (!sawText && typeof outputText === 'string' && outputText) {
|
|
366
854
|
events.push({ type: 'text', text: outputText });
|
|
855
|
+
sawText = true;
|
|
856
|
+
}
|
|
857
|
+
if (!events.some((item) => item.type === 'media')) {
|
|
858
|
+
events.push(...mediaEventsFromComplete(event));
|
|
367
859
|
}
|
|
368
|
-
const media = mediaFromComplete(event);
|
|
369
|
-
if (media)
|
|
370
|
-
events.push(media);
|
|
371
860
|
const tokenEvent = extractTokenEvent(event, interaction);
|
|
372
861
|
if (tokenEvent)
|
|
373
862
|
events.push(tokenEvent);
|
|
@@ -401,12 +890,13 @@ function doneFromInteractionStatus(interaction, event) {
|
|
|
401
890
|
...(typeof interaction.id === 'string' ? { interactionId: interaction.id } : {}),
|
|
402
891
|
};
|
|
403
892
|
}
|
|
404
|
-
|
|
893
|
+
/** Parse model text as structured JSON. Invalid JSON is a hard failure — never silent skip. */
|
|
894
|
+
function parseStructuredOutput(text) {
|
|
405
895
|
try {
|
|
406
|
-
return {
|
|
896
|
+
return { ok: true, structured: JSON.parse(text) };
|
|
407
897
|
}
|
|
408
898
|
catch {
|
|
409
|
-
return
|
|
899
|
+
return { ok: false, error: 'structured output was not valid JSON' };
|
|
410
900
|
}
|
|
411
901
|
}
|
|
412
|
-
export { eventsFromComplete, eventsFromDelta, extractTokenEvent, extractUsageTokens, groundingFromEvent,
|
|
902
|
+
export { codeExecutionEvidence, codeExecutionStepKey, eventsFromComplete, eventsFromDelta, eventsFromInteractionSteps, extractTokenEvent, extractUsageTokens, googleBuiltinEvidence, groundingFromEvent, isCodeExecutionType, isGoogleBuiltinStepType, mergeCodeExecutionPayload, parseStructuredOutput, };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live realtime inbound text — same sanitize + user_data fence as runTurn ingress.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import type { Profile } from '../types.js';
|
|
7
|
+
/** Sanitize profile-controlled inbound text and wrap with user_data fencing. */
|
|
8
|
+
declare function prepareLiveInboundText(profile: Profile, text: string): string;
|
|
9
|
+
export { prepareLiveInboundText };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live realtime inbound text — same sanitize + user_data fence as runTurn ingress.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { wrapUserData } from '../../guardrails/canary.js';
|
|
7
|
+
import { sanitizeText } from '../../guardrails/sanitize.js';
|
|
8
|
+
/** Sanitize profile-controlled inbound text and wrap with user_data fencing. */
|
|
9
|
+
function prepareLiveInboundText(profile, text) {
|
|
10
|
+
const guardrails = profile.guardrails;
|
|
11
|
+
const safe = sanitizeText(text, {
|
|
12
|
+
sanitizeInput: guardrails?.sanitizeInput === true,
|
|
13
|
+
redactSensitive: guardrails?.redactSensitive === true,
|
|
14
|
+
});
|
|
15
|
+
return wrapUserData(safe);
|
|
16
|
+
}
|
|
17
|
+
export { prepareLiveInboundText };
|
|
@@ -16,7 +16,7 @@ function formatHistoryBlock(messages) {
|
|
|
16
16
|
function synthesizeRepairPrompt(args) {
|
|
17
17
|
const { profile, repair, history } = args;
|
|
18
18
|
const guidance = repair.guidance ||
|
|
19
|
-
profile.outputs
|
|
19
|
+
profile.outputs?.validation?.repairGuidance ||
|
|
20
20
|
'Revise the previous output so it satisfies the validator rejection. Preserve the intended user-facing substance unless the guidance says otherwise.';
|
|
21
21
|
const historyBlock = formatHistoryBlock(scopeHistory(history));
|
|
22
22
|
let prompt = `## OUTPUT REPAIR REQUEST\n\n`;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { ModelProvider, Profile, ResolvedGeneration, TurnEvent, TurnRequest } from '../../types.js';
|
|
2
2
|
import type { StepExecutionState } from './state.js';
|
|
3
|
-
declare function runAttemptsWithValidation(safe: TurnRequest, profile: Profile, generation: ResolvedGeneration, system: string, provider: ModelProvider,
|
|
3
|
+
declare function runAttemptsWithValidation(safe: TurnRequest, profile: Profile, generation: ResolvedGeneration, system: string, provider: ModelProvider, upstream: Record<string, unknown>[], state: StepExecutionState): AsyncGenerator<TurnEvent>;
|
|
4
4
|
export { runAttemptsWithValidation };
|