theorum 0.1.15 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +241 -98
- package/esm/mod.d.ts +57 -28
- package/esm/mod.js +43 -23
- package/esm/src/cli/commands/bench.js +18 -18
- package/esm/src/cli/commands/fuzz-canary.d.ts +13 -0
- package/esm/src/cli/commands/fuzz-canary.js +191 -0
- package/esm/src/cli/commands/fuzz-guardrails.d.ts +3 -5
- package/esm/src/cli/commands/fuzz-guardrails.js +4 -581
- package/esm/src/cli/commands/guardrails-eval.d.ts +14 -0
- package/esm/src/cli/commands/guardrails-eval.js +15 -0
- package/esm/src/cli/commands/profile.js +35 -15
- package/esm/src/cli/commands/run.d.ts +3 -0
- package/esm/src/cli/commands/run.js +23 -32
- package/esm/src/cli/commands/test.d.ts +10 -1
- package/esm/src/cli/commands/test.js +34 -34
- package/esm/src/cli/event-log.d.ts +19 -0
- package/esm/src/cli/event-log.js +147 -0
- package/esm/src/cli/index.js +57 -11
- package/esm/src/cli/matrix/synthesizer.d.ts +10 -12
- package/esm/src/cli/matrix/synthesizer.js +45 -118
- package/esm/src/guardrails/canary-gate.d.ts +21 -0
- package/esm/src/guardrails/canary-gate.js +32 -0
- package/esm/src/guardrails/canary.d.ts +34 -0
- package/esm/src/guardrails/canary.js +150 -0
- package/esm/src/guardrails/corpus/canary-egress-attacks.d.ts +17 -0
- package/esm/src/guardrails/corpus/canary-egress-attacks.js +151 -0
- package/esm/src/guardrails/corpus/fuzz-inbound.d.ts +11 -0
- package/esm/src/guardrails/corpus/fuzz-inbound.js +213 -0
- package/esm/src/guardrails/corpus/inbound-payloads.d.ts +10 -0
- package/esm/src/guardrails/corpus/inbound-payloads.js +125 -0
- package/esm/src/guardrails/corpus/live-attacks.d.ts +20 -0
- package/esm/src/guardrails/corpus/live-attacks.js +231 -0
- package/esm/src/guardrails/corpus/mod.d.ts +14 -0
- package/esm/src/guardrails/corpus/mod.js +11 -0
- package/esm/src/guardrails/corpus/secrets.d.ts +17 -0
- package/esm/src/guardrails/corpus/secrets.js +17 -0
- package/esm/src/guardrails/corpus/strings.d.ts +28 -0
- package/esm/src/guardrails/corpus/strings.js +34 -0
- package/esm/src/guardrails/corpus/types.d.ts +38 -0
- package/esm/src/guardrails/corpus/types.js +6 -0
- package/esm/src/guardrails/egress.d.ts +32 -0
- package/esm/src/guardrails/egress.js +87 -0
- package/esm/src/guardrails/error.d.ts +14 -23
- package/esm/src/guardrails/error.js +87 -76
- package/esm/src/guardrails/eval/corpus.d.ts +108 -0
- package/esm/src/guardrails/eval/corpus.js +978 -0
- package/esm/src/guardrails/eval/mod.d.ts +51 -0
- package/esm/src/guardrails/eval/mod.js +133 -0
- package/esm/src/guardrails/eval/score.d.ts +66 -0
- package/esm/src/guardrails/eval/score.js +114 -0
- package/esm/src/guardrails/events.d.ts +25 -0
- package/esm/src/guardrails/events.js +56 -0
- package/esm/src/guardrails/hits.d.ts +24 -0
- package/esm/src/guardrails/hits.js +45 -0
- package/esm/src/guardrails/injection.js +28 -5
- package/esm/src/guardrails/lexicon.d.ts +39 -0
- package/esm/src/guardrails/lexicon.js +200 -0
- package/esm/src/guardrails/live-outbound-gate.d.ts +41 -0
- package/esm/src/guardrails/live-outbound-gate.js +222 -0
- package/esm/src/guardrails/mod.d.ts +30 -6
- package/esm/src/guardrails/mod.js +20 -5
- package/esm/src/guardrails/network.d.ts +19 -0
- package/esm/src/guardrails/network.js +234 -0
- package/esm/src/guardrails/policy.d.ts +35 -0
- package/esm/src/guardrails/policy.js +50 -0
- package/esm/src/guardrails/progressive-yield.d.ts +51 -0
- package/esm/src/guardrails/progressive-yield.js +98 -0
- package/esm/src/guardrails/quota.d.ts +17 -3
- package/esm/src/guardrails/quota.js +18 -4
- package/esm/src/guardrails/sanitize.d.ts +45 -19
- package/esm/src/guardrails/sanitize.js +177 -94
- package/esm/src/guardrails/sensitive.js +2 -1
- package/esm/src/guardrails/serialize.d.ts +35 -0
- package/esm/src/guardrails/serialize.js +58 -0
- package/esm/src/guardrails/testing.d.ts +17 -0
- package/esm/src/guardrails/testing.js +13 -0
- package/esm/src/guardrails/theorum-error.d.ts +12 -0
- package/esm/src/guardrails/theorum-error.js +15 -0
- package/esm/src/guardrails/tool-directives.d.ts +48 -0
- package/esm/src/guardrails/tool-directives.js +124 -0
- package/esm/src/guardrails/tool-result.d.ts +93 -0
- package/esm/src/guardrails/tool-result.js +276 -0
- package/esm/src/guardrails/types.d.ts +291 -0
- package/esm/src/guardrails/types.js +72 -0
- package/esm/src/host/client-turn.d.ts +19 -0
- package/esm/src/host/client-turn.js +36 -0
- package/esm/src/host/mint-trace.d.ts +1 -1
- package/esm/src/host/mod.d.ts +5 -3
- package/esm/src/host/mod.js +4 -3
- package/esm/src/kernel/auth/crypto.d.ts +42 -0
- package/esm/src/kernel/auth/crypto.js +106 -0
- package/esm/src/kernel/auth/mod.d.ts +11 -0
- package/esm/src/kernel/auth/mod.js +11 -0
- package/esm/src/kernel/auth/oauth.d.ts +47 -0
- package/esm/src/kernel/auth/oauth.js +278 -0
- package/esm/src/kernel/auth/types.d.ts +133 -0
- package/esm/src/kernel/auth/types.js +13 -0
- package/esm/src/kernel/engine/delta.d.ts +24 -2
- package/esm/src/kernel/engine/delta.js +478 -39
- package/esm/src/kernel/engine/live-inbound.d.ts +21 -0
- package/esm/src/kernel/engine/live-inbound.js +31 -0
- package/esm/src/kernel/engine/live-ingress.d.ts +19 -0
- package/esm/src/kernel/engine/live-ingress.js +47 -0
- package/esm/src/kernel/engine/repair.js +13 -12
- package/esm/src/kernel/engine/runner/gates.d.ts +1 -1
- package/esm/src/kernel/engine/runner/gates.js +130 -43
- package/esm/src/kernel/engine/runner/mod.d.ts +6 -4
- package/esm/src/kernel/engine/runner/mod.js +192 -53
- package/esm/src/kernel/engine/runner/schema-validation.js +3 -3
- package/esm/src/kernel/engine/runner/stages.d.ts +39 -0
- package/esm/src/kernel/engine/runner/stages.js +89 -0
- package/esm/src/kernel/engine/runner/state.d.ts +31 -0
- package/esm/src/kernel/engine/runner/steps.d.ts +1 -1
- package/esm/src/kernel/engine/runner/steps.js +244 -43
- package/esm/src/kernel/engine/runner/stream.d.ts +9 -3
- package/esm/src/kernel/engine/runner/stream.js +140 -44
- package/esm/src/kernel/engine/session/mod.d.ts +25 -0
- package/esm/src/kernel/engine/session/mod.js +557 -0
- package/esm/src/kernel/interaction-parts.d.ts +14 -0
- package/esm/src/kernel/interaction-parts.js +23 -0
- package/esm/src/kernel/mod.d.ts +21 -10
- package/esm/src/kernel/mod.js +11 -8
- package/esm/src/kernel/profile-graph.d.ts +159 -0
- package/esm/src/kernel/profile-graph.js +156 -0
- package/esm/src/kernel/registry/attachments.d.ts +12 -10
- package/esm/src/kernel/registry/attachments.js +33 -27
- package/esm/src/kernel/registry/catalog.d.ts +25 -24
- package/esm/src/kernel/registry/catalog.js +60 -101
- package/esm/src/kernel/registry/ingress.d.ts +9 -4
- package/esm/src/kernel/registry/ingress.js +97 -75
- package/esm/src/kernel/registry/profile-outputs.d.ts +4 -0
- package/esm/src/kernel/registry/profile-outputs.js +8 -0
- package/esm/src/kernel/registry/profiles.d.ts +55 -12
- package/esm/src/kernel/registry/profiles.js +413 -73
- package/esm/src/kernel/registry/provider-request.js +13 -7
- package/esm/src/kernel/registry/resolve.d.ts +8 -8
- package/esm/src/kernel/registry/resolve.js +169 -154
- package/esm/src/kernel/registry/schemas.js +1 -1
- package/esm/src/kernel/registry/sole-model.d.ts +8 -0
- package/esm/src/kernel/registry/sole-model.js +10 -0
- package/esm/src/kernel/registry/system-prompt.d.ts +10 -0
- package/esm/src/kernel/registry/system-prompt.js +40 -0
- package/esm/src/kernel/registry/system-role.d.ts +8 -0
- package/esm/src/kernel/registry/system-role.js +14 -0
- package/esm/src/kernel/registry/vault.d.ts +12 -7
- package/esm/src/kernel/registry/vault.js +32 -10
- package/esm/src/kernel/schema.d.ts +231 -0
- package/esm/src/kernel/schema.js +607 -0
- package/esm/src/kernel/stages.d.ts +175 -0
- package/esm/src/kernel/stages.js +476 -0
- package/esm/src/kernel/stop.d.ts +78 -19
- package/esm/src/kernel/stop.js +51 -16
- package/esm/src/kernel/tools/events.d.ts +41 -0
- package/esm/src/kernel/tools/events.js +71 -0
- package/esm/src/kernel/tools/execute.d.ts +84 -0
- package/esm/src/kernel/tools/execute.js +614 -0
- package/esm/src/kernel/tools/harness.d.ts +8 -0
- package/esm/src/kernel/tools/harness.js +46 -0
- package/esm/src/kernel/tools/invoke.d.ts +10 -0
- package/esm/src/kernel/tools/invoke.js +101 -0
- package/esm/src/kernel/tools/mod.d.ts +13 -0
- package/esm/src/kernel/tools/mod.js +11 -0
- package/esm/src/kernel/tools/permission.d.ts +15 -0
- package/esm/src/kernel/tools/permission.js +47 -0
- package/esm/src/kernel/tools/project.d.ts +12 -0
- package/esm/src/kernel/tools/project.js +36 -0
- package/esm/src/kernel/tools/registry.d.ts +23 -0
- package/esm/src/kernel/tools/registry.js +81 -0
- package/esm/src/kernel/tools/remote.d.ts +94 -0
- package/esm/src/kernel/tools/remote.js +577 -0
- package/esm/src/kernel/tools/resolve.d.ts +39 -0
- package/esm/src/kernel/tools/resolve.js +283 -0
- package/esm/src/kernel/tools/schema.d.ts +15 -0
- package/esm/src/kernel/tools/schema.js +176 -0
- package/esm/src/kernel/tools/stage-run.d.ts +105 -0
- package/esm/src/kernel/tools/stage-run.js +155 -0
- package/esm/src/kernel/tools/types.d.ts +394 -0
- package/esm/src/kernel/tools/types.js +9 -0
- package/esm/src/kernel/types.d.ts +540 -256
- package/esm/src/kernel/util/find-last.d.ts +2 -0
- package/esm/src/kernel/util/find-last.js +10 -0
- package/esm/src/observability/destinations.d.ts +31 -0
- package/esm/src/observability/destinations.js +67 -0
- package/esm/src/observability/mod.d.ts +10 -3
- package/esm/src/observability/mod.js +6 -2
- package/esm/src/observability/policy.d.ts +27 -0
- package/esm/src/observability/policy.js +80 -0
- package/esm/src/observability/resolve-policy.d.ts +16 -0
- package/esm/src/observability/resolve-policy.js +64 -0
- package/esm/src/observability/trace-attach.d.ts +8 -4
- package/esm/src/observability/trace-attach.js +50 -29
- package/esm/src/observability/trace-record.d.ts +23 -13
- package/esm/src/observability/trace-record.js +96 -39
- package/esm/src/observability/trace-sink.d.ts +19 -0
- package/esm/src/observability/trace-sink.js +10 -0
- package/esm/src/observability/trace-usage.d.ts +10 -3
- package/esm/src/observability/trace-usage.js +70 -17
- package/esm/src/observability/trace.d.ts +18 -7
- package/esm/src/observability/trace.js +34 -17
- package/esm/src/observability/types.d.ts +113 -0
- package/esm/src/observability/types.js +11 -0
- package/esm/src/presets/google/speech-voices.d.ts +11 -0
- package/esm/src/presets/google/speech-voices.js +41 -0
- package/esm/src/presets/google.d.ts +36 -24
- package/esm/src/presets/google.js +50 -63
- package/esm/src/presets/mod.d.ts +2 -2
- package/esm/src/presets/mod.js +1 -1
- package/esm/src/providers/create-provider.d.ts +20 -17
- package/esm/src/providers/create-provider.js +72 -26
- package/esm/src/providers/google/interactions/framing.d.ts +23 -0
- package/esm/src/providers/google/interactions/framing.js +269 -0
- package/esm/src/providers/google/interactions/mod.d.ts +7 -0
- package/esm/src/providers/google/interactions/mod.js +7 -0
- package/esm/src/providers/google/interactions/stream.d.ts +83 -0
- package/esm/src/providers/google/interactions/stream.js +588 -0
- package/esm/src/providers/google/keys.d.ts +26 -0
- package/esm/src/providers/{keys.js → google/keys.js} +19 -31
- package/esm/src/providers/google/live/framing.d.ts +49 -0
- package/esm/src/providers/google/live/framing.js +552 -0
- package/esm/src/providers/google/live/openapi-schema.d.ts +6 -0
- package/esm/src/providers/google/live/openapi-schema.js +46 -0
- package/esm/src/providers/google/live/session.d.ts +25 -0
- package/esm/src/providers/google/live/session.js +134 -0
- package/esm/src/providers/google/live/stream.d.ts +45 -0
- package/esm/src/providers/google/live/stream.js +214 -0
- package/esm/src/providers/google/urls.d.ts +6 -0
- package/esm/src/providers/google/urls.js +6 -0
- package/esm/src/providers/local/local.d.ts +30 -0
- package/esm/src/providers/{local.js → local/local.js} +66 -126
- package/esm/src/providers/local/mod.d.ts +9 -0
- package/esm/src/providers/local/mod.js +9 -0
- package/esm/src/providers/mod.d.ts +6 -3
- package/esm/src/providers/mod.js +3 -1
- package/esm/src/providers/openrouter/cache-control.d.ts +24 -0
- package/esm/src/providers/openrouter/cache-control.js +23 -0
- package/esm/src/providers/openrouter/chat.d.ts +107 -0
- package/esm/src/providers/{openrouter.js → openrouter/chat.js} +117 -231
- package/esm/src/providers/openrouter/image.d.ts +34 -0
- package/esm/src/providers/openrouter/image.js +275 -0
- package/esm/src/providers/openrouter/openai/chat-payload.d.ts +24 -0
- package/esm/src/providers/openrouter/openai/chat-payload.js +82 -0
- package/esm/src/providers/openrouter/openai/compat.d.ts +53 -0
- package/esm/src/providers/openrouter/openai/compat.js +213 -0
- package/esm/src/providers/openrouter/openai/image-payload.d.ts +18 -0
- package/esm/src/providers/openrouter/openai/image-payload.js +90 -0
- package/esm/src/providers/openrouter/openai/sdk-messages.d.ts +22 -0
- package/esm/src/providers/openrouter/openai/sdk-messages.js +122 -0
- package/esm/src/providers/openrouter/resolve-api-key.d.ts +9 -0
- package/esm/src/providers/openrouter/resolve-api-key.js +24 -0
- package/esm/src/providers/openrouter/speech.d.ts +23 -0
- package/esm/src/providers/{speech.js → openrouter/speech.js} +32 -55
- package/esm/src/providers/probe.d.ts +1 -0
- package/esm/src/providers/probe.js +22 -0
- package/esm/src/providers/shared/pcm.d.ts +12 -0
- package/esm/src/providers/{pcm.js → shared/pcm.js} +16 -3
- package/esm/src/providers/shared/sse.d.ts +18 -0
- package/esm/src/providers/shared/sse.js +87 -0
- package/esm/src/providers/shared/tool-args.d.ts +17 -0
- package/esm/src/providers/shared/tool-args.js +45 -0
- package/esm/src/providers/shared/upstream-tap.d.ts +5 -0
- package/esm/src/providers/{google-tap.js → shared/upstream-tap.js} +4 -7
- package/esm/src/providers/shared/upstream-tape.d.ts +6 -0
- package/esm/src/providers/{gemini-tape.js → shared/upstream-tape.js} +12 -22
- package/esm/src/providers/types.d.ts +27 -0
- package/esm/src/providers/types.js +1 -0
- package/package.json +11 -7
- package/docs/cli.md +0 -97
- package/docs/guardrails.md +0 -178
- package/docs/host.md +0 -97
- package/docs/kernel.md +0 -404
- package/docs/observability.md +0 -105
- package/docs/openrouter.md +0 -125
- package/docs/presets-google.md +0 -91
- package/docs/presets.md +0 -88
- package/docs/providers.md +0 -202
- package/docs/streaming.md +0 -96
- package/esm/src/kernel/engine/boundary.d.ts +0 -10
- package/esm/src/kernel/engine/boundary.js +0 -55
- package/esm/src/kernel/engine/runner/tools.d.ts +0 -13
- package/esm/src/kernel/engine/runner/tools.js +0 -198
- package/esm/src/kernel/registry/tools.d.ts +0 -12
- package/esm/src/kernel/registry/tools.js +0 -36
- package/esm/src/providers/expose-for-tests.d.ts +0 -1
- package/esm/src/providers/expose-for-tests.js +0 -25
- package/esm/src/providers/gemini-tape.d.ts +0 -2
- package/esm/src/providers/google-tap.d.ts +0 -3
- package/esm/src/providers/interactions.d.ts +0 -5
- package/esm/src/providers/interactions.js +0 -169
- package/esm/src/providers/keys.d.ts +0 -19
- package/esm/src/providers/local.d.ts +0 -29
- package/esm/src/providers/openrouter-mod.d.ts +0 -13
- package/esm/src/providers/openrouter-mod.js +0 -12
- package/esm/src/providers/openrouter-payload.d.ts +0 -39
- package/esm/src/providers/openrouter-payload.js +0 -195
- package/esm/src/providers/openrouter.d.ts +0 -15
- package/esm/src/providers/pcm.d.ts +0 -7
- package/esm/src/providers/provider.d.ts +0 -15
- package/esm/src/providers/provider.js +0 -202
- package/esm/src/providers/speech.d.ts +0 -23
- package/esm/src/providers/sse.d.ts +0 -7
- package/esm/src/providers/sse.js +0 -55
- package/esm/src/streaming/mod.d.ts +0 -9
- package/esm/src/streaming/mod.js +0 -8
- /package/esm/src/{streaming → host}/readStreamingJsonStringField.d.ts +0 -0
- /package/esm/src/{streaming → host}/readStreamingJsonStringField.js +0 -0
|
@@ -1,29 +1,57 @@
|
|
|
1
1
|
import { throwIfAborted } from '../../../guardrails/error.js';
|
|
2
|
+
import { resolveGuardrailPolicy } from '../../../guardrails/policy.js';
|
|
3
|
+
import { recordTaint } from '../../../guardrails/tool-result.js';
|
|
4
|
+
import { wireInteractionPart } from '../../interaction-parts.js';
|
|
5
|
+
import { profileTurnOutputs } from '../../registry/profile-outputs.js';
|
|
6
|
+
import { injectWouldExceedMaxSteps } from '../../stages.js';
|
|
7
|
+
import { profileAllowsInject } from '../../stop.js';
|
|
8
|
+
import { executeRegisteredTool, formatToolFailureForModel, formatToolResult, newCallId, } from '../../tools/execute.js';
|
|
9
|
+
import { applyStageInjects } from './stages.js';
|
|
2
10
|
import { recordStepEvent } from './state.js';
|
|
3
11
|
import { yieldProviderEvents } from './stream.js';
|
|
4
|
-
import { executeDynamicDeclaration, findDynamicDeclaration, formatToolFinding, isActionableDynamicDeclaration, } from './tools.js';
|
|
5
12
|
function isStepLimitReached(step, maxSteps) {
|
|
6
|
-
if (maxSteps <= 0) {
|
|
13
|
+
if (maxSteps === undefined || maxSteps <= 0) {
|
|
7
14
|
return false;
|
|
8
15
|
}
|
|
9
16
|
return step >= maxSteps;
|
|
10
17
|
}
|
|
18
|
+
function generationForProviderStep(generation, state) {
|
|
19
|
+
if (state.interactionsContinuation) {
|
|
20
|
+
const { previousInteractionId, input } = state.interactionsContinuation;
|
|
21
|
+
state.interactionsContinuation = undefined;
|
|
22
|
+
return {
|
|
23
|
+
...generation,
|
|
24
|
+
history: [],
|
|
25
|
+
input: [],
|
|
26
|
+
previousInteractionId,
|
|
27
|
+
interactionOnlyInput: input,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
return { ...generation, history: state.currentHistory };
|
|
31
|
+
}
|
|
32
|
+
function captureInteractionId(event, state) {
|
|
33
|
+
if (event.interactionId) {
|
|
34
|
+
state.lastInteractionId = event.interactionId;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
11
37
|
async function* executeAutonomousStep(args, state, buffer = {
|
|
12
38
|
holdLate: false,
|
|
13
|
-
holdUserVisible: false,
|
|
14
39
|
}) {
|
|
15
|
-
const {
|
|
16
|
-
const genForStep =
|
|
40
|
+
const { generation, system, provider, upstream, signal } = args;
|
|
41
|
+
const genForStep = generationForProviderStep(generation, state);
|
|
17
42
|
const pendingTools = [];
|
|
18
43
|
let latestStructured;
|
|
44
|
+
const control = { withholdVisible: false };
|
|
19
45
|
for await (const event of yieldProviderEvents({
|
|
20
|
-
profile,
|
|
46
|
+
profile: args.profile,
|
|
21
47
|
generation: genForStep,
|
|
22
48
|
system,
|
|
23
49
|
provider,
|
|
24
|
-
|
|
50
|
+
upstream,
|
|
25
51
|
signal,
|
|
52
|
+
control,
|
|
26
53
|
})) {
|
|
54
|
+
captureInteractionId(event, state);
|
|
27
55
|
if (event.type === 'structured') {
|
|
28
56
|
latestStructured = event.structured;
|
|
29
57
|
}
|
|
@@ -38,22 +66,41 @@ async function* executeAutonomousStep(args, state, buffer = {
|
|
|
38
66
|
continue;
|
|
39
67
|
}
|
|
40
68
|
recordStepEvent(event, state);
|
|
41
|
-
const isUserVisible = event.type === 'thought' || event.type === 'text';
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
69
|
+
const isUserVisible = event.type === 'thought' || event.type === 'text' || event.type === 'media';
|
|
70
|
+
if (control.withholdVisible && isUserVisible) {
|
|
71
|
+
// Progressive-yield blocked this attempt — keep events for egress/repair only.
|
|
72
|
+
// Record the decision so the attempt gate knows nothing reached the host.
|
|
73
|
+
state.withheldVisible = true;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
// Progressive-yield streams text/thought live under egress; holdLate only
|
|
77
|
+
// buffers non-visible events (e.g. structured) for validation.
|
|
78
|
+
const streamNow = !buffer.holdLate || event.type === 'tokens' || isUserVisible;
|
|
45
79
|
if (streamNow) {
|
|
46
80
|
yield event;
|
|
47
81
|
}
|
|
48
82
|
}
|
|
49
83
|
return { pendingTools, latestStructured };
|
|
50
84
|
}
|
|
51
|
-
function
|
|
85
|
+
function appendInteractionsToolResultToHistory(history, toolEv, result) {
|
|
52
86
|
const tool = toolEv.tool;
|
|
53
87
|
if (!tool) {
|
|
54
88
|
return;
|
|
55
89
|
}
|
|
56
|
-
|
|
90
|
+
history.push({
|
|
91
|
+
role: 'tool',
|
|
92
|
+
tool_call_id: tool.id ?? tool.callId ?? `call_${tool.name}`,
|
|
93
|
+
name: tool.name,
|
|
94
|
+
content: formatToolResult(result),
|
|
95
|
+
...(result.parts && result.parts.length > 0 ? { parts: result.parts } : {}),
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
function appendToolTurnToHistory(history, toolEv, result) {
|
|
99
|
+
const tool = toolEv.tool;
|
|
100
|
+
if (!tool) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const callId = tool.id ?? tool.callId ?? newCallId(tool.name);
|
|
57
104
|
history.push({
|
|
58
105
|
role: 'assistant',
|
|
59
106
|
tool_calls: [
|
|
@@ -71,51 +118,205 @@ function appendToolTurnToHistory(history, toolEv, res) {
|
|
|
71
118
|
role: 'tool',
|
|
72
119
|
tool_call_id: callId,
|
|
73
120
|
name: tool.name,
|
|
74
|
-
content:
|
|
121
|
+
content: formatToolResult(result),
|
|
122
|
+
...(result.parts && result.parts.length > 0 ? { parts: result.parts } : {}),
|
|
75
123
|
});
|
|
76
124
|
}
|
|
77
|
-
|
|
78
|
-
|
|
125
|
+
function queueInteractionsToolContinuation(state, toolEv, result, fallbackInteractionId) {
|
|
126
|
+
const tool = toolEv.tool;
|
|
127
|
+
if (!tool) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const previousInteractionId = state.lastInteractionId ?? fallbackInteractionId;
|
|
131
|
+
if (!previousInteractionId) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const step = {
|
|
135
|
+
type: 'function_result',
|
|
136
|
+
name: tool.name,
|
|
137
|
+
call_id: tool.id ?? tool.callId ?? `call_${tool.name}`,
|
|
138
|
+
result: result.parts && result.parts.length > 0
|
|
139
|
+
? result.parts.map(wireInteractionPart)
|
|
140
|
+
: [{ type: 'text', text: formatToolResult(result) }],
|
|
141
|
+
};
|
|
142
|
+
if (state.interactionsContinuation &&
|
|
143
|
+
state.interactionsContinuation.previousInteractionId === previousInteractionId) {
|
|
144
|
+
state.interactionsContinuation.input.push(step);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
state.interactionsContinuation = {
|
|
148
|
+
previousInteractionId,
|
|
149
|
+
input: [step],
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function recordToolModelResult(state, toolEv, modelResult, generation, useInteractionsContinuation) {
|
|
153
|
+
if (useInteractionsContinuation) {
|
|
154
|
+
queueInteractionsToolContinuation(state, toolEv, modelResult, generation.previousInteractionId);
|
|
155
|
+
if (!state.interactionsContinuation) {
|
|
156
|
+
appendInteractionsToolResultToHistory(state.currentHistory, toolEv, modelResult);
|
|
157
|
+
}
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
appendToolTurnToHistory(state.currentHistory, toolEv, modelResult);
|
|
161
|
+
}
|
|
162
|
+
function enrichToolEvent(tool, callId, patch) {
|
|
163
|
+
return {
|
|
164
|
+
type: 'tool',
|
|
165
|
+
tool: {
|
|
166
|
+
...tool,
|
|
167
|
+
...patch,
|
|
168
|
+
callId,
|
|
169
|
+
id: tool.id ?? callId,
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
async function* drainToolExecEvents(exec, tool, callId, state) {
|
|
174
|
+
let next = await exec.next();
|
|
175
|
+
let sawGate = false;
|
|
176
|
+
while (!next.done) {
|
|
177
|
+
const event = next.value;
|
|
178
|
+
if (event.type === 'tool') {
|
|
179
|
+
const enriched = enrichToolEvent(tool, callId, event.tool);
|
|
180
|
+
state.allEmittedEvents.push(enriched);
|
|
181
|
+
yield enriched;
|
|
182
|
+
if (event.tool?.phase === 'gate')
|
|
183
|
+
sawGate = true;
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
state.allEmittedEvents.push(event);
|
|
187
|
+
yield event;
|
|
188
|
+
}
|
|
189
|
+
next = await exec.next();
|
|
190
|
+
}
|
|
191
|
+
return { settlement: next.value, sawGate };
|
|
192
|
+
}
|
|
193
|
+
function recordProviderToolFailure(state, toolEv, tool, callId, failure, generation, useInteractionsContinuation, patch) {
|
|
194
|
+
const enriched = enrichToolEvent(tool, callId, {
|
|
195
|
+
phase: 'error',
|
|
196
|
+
failure,
|
|
197
|
+
...patch,
|
|
198
|
+
});
|
|
199
|
+
state.allEmittedEvents.push(enriched);
|
|
200
|
+
recordToolModelResult(state, toolEv, formatToolFailureForModel(failure), generation, useInteractionsContinuation);
|
|
201
|
+
return enriched;
|
|
202
|
+
}
|
|
203
|
+
function applyToolSettlement(settlement, state, toolEv, generation, useInteractionsContinuation) {
|
|
204
|
+
if (settlement.aborted) {
|
|
205
|
+
state.lastStop = {
|
|
206
|
+
kind: 'cancelled',
|
|
207
|
+
...(typeof settlement.aborted === 'object' && settlement.aborted.reason
|
|
208
|
+
? { native: settlement.aborted.reason }
|
|
209
|
+
: {}),
|
|
210
|
+
};
|
|
211
|
+
return 'stop_cancelled';
|
|
212
|
+
}
|
|
213
|
+
if (settlement.gated) {
|
|
214
|
+
state.toolSnapshot = generation.tools;
|
|
215
|
+
return 'gated';
|
|
216
|
+
}
|
|
217
|
+
if (settlement.modelResult?.provenance) {
|
|
218
|
+
state.taint = recordTaint(state.taint, settlement.modelResult.provenance, settlement.modelResult.suspicious);
|
|
219
|
+
}
|
|
220
|
+
if (!settlement.modelResult)
|
|
221
|
+
return 'continue';
|
|
222
|
+
recordToolModelResult(state, toolEv, settlement.modelResult, generation, useInteractionsContinuation);
|
|
223
|
+
if (settlement.pendingInject?.length) {
|
|
224
|
+
applyStageInjects(state, settlement.pendingInject);
|
|
225
|
+
}
|
|
226
|
+
return 'continue';
|
|
227
|
+
}
|
|
228
|
+
async function* handlePendingTools(pendingTools, generation, profile, state, safe) {
|
|
229
|
+
let executed = false;
|
|
230
|
+
let sawGate = false;
|
|
231
|
+
const useInteractionsContinuation = generation.transport === 'interactions';
|
|
79
232
|
for (const toolEv of pendingTools) {
|
|
233
|
+
if (sawGate)
|
|
234
|
+
break;
|
|
80
235
|
const tool = toolEv.tool;
|
|
81
|
-
if (!tool)
|
|
236
|
+
if (!tool)
|
|
237
|
+
continue;
|
|
238
|
+
executed = true;
|
|
239
|
+
const callId = tool.id ?? tool.callId ?? newCallId(tool.name || 'unknown');
|
|
240
|
+
if (tool.phase === 'cancel') {
|
|
241
|
+
const enriched = enrichToolEvent(tool, callId);
|
|
242
|
+
state.allEmittedEvents.push(enriched);
|
|
243
|
+
yield enriched;
|
|
82
244
|
continue;
|
|
83
245
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
state.allEmittedEvents.push(
|
|
87
|
-
yield
|
|
246
|
+
if (tool.phase === 'error' && tool.failure) {
|
|
247
|
+
const enriched = enrichToolEvent(tool, callId);
|
|
248
|
+
state.allEmittedEvents.push(enriched);
|
|
249
|
+
yield enriched;
|
|
250
|
+
recordToolModelResult(state, toolEv, formatToolFailureForModel(tool.failure), generation, useInteractionsContinuation);
|
|
88
251
|
continue;
|
|
89
252
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
253
|
+
if (!tool.name) {
|
|
254
|
+
yield recordProviderToolFailure(state, toolEv, tool, callId, {
|
|
255
|
+
code: 'malformed_arguments',
|
|
256
|
+
message: 'Provider tool call is missing a function name', // lexicon-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
257
|
+
}, generation, useInteractionsContinuation, { name: '' });
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
const stages = {
|
|
261
|
+
handlers: safe?.onStage ? [safe.onStage] : [],
|
|
94
262
|
profile,
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
263
|
+
step: state.stepCount,
|
|
264
|
+
history: () => state.currentHistory,
|
|
265
|
+
injectAllowed: profileAllowsInject(profile),
|
|
266
|
+
injectWouldExceedMaxSteps: injectWouldExceedMaxSteps(state.stepCount, generation.maxSteps),
|
|
267
|
+
host: generation.host,
|
|
268
|
+
signal: safe?.signal,
|
|
100
269
|
};
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
270
|
+
const drained = yield* drainToolExecEvents(executeRegisteredTool({
|
|
271
|
+
profile,
|
|
272
|
+
name: tool.name,
|
|
273
|
+
input: tool.arguments ?? {},
|
|
274
|
+
callId,
|
|
275
|
+
ctx: {
|
|
276
|
+
sessionPermissions: generation.sessionPermissions,
|
|
277
|
+
path: generation.tools.path,
|
|
278
|
+
turn: { step: state.stepCount, taint: state.taint },
|
|
279
|
+
credentials: safe?.credentials,
|
|
280
|
+
host: generation.host,
|
|
281
|
+
resume: undefined,
|
|
282
|
+
signal: safe?.signal,
|
|
283
|
+
},
|
|
284
|
+
snapshot: generation.tools,
|
|
285
|
+
stages,
|
|
286
|
+
}), tool, callId, state);
|
|
287
|
+
if (drained.sawGate)
|
|
288
|
+
sawGate = true;
|
|
289
|
+
const outcome = applyToolSettlement(drained.settlement, state, toolEv, generation, useInteractionsContinuation);
|
|
290
|
+
if (outcome === 'stop_cancelled')
|
|
291
|
+
return false;
|
|
292
|
+
if (outcome === 'gated' || sawGate) {
|
|
293
|
+
sawGate = true;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
if (sawGate) {
|
|
297
|
+
state.lastStop = { kind: 'gate' };
|
|
298
|
+
return false;
|
|
104
299
|
}
|
|
105
|
-
return
|
|
300
|
+
return executed;
|
|
106
301
|
}
|
|
107
302
|
async function* executeAttempt(args) {
|
|
108
|
-
const { profile, generation, system, provider,
|
|
303
|
+
const { profile, generation, system, provider, upstream, state } = args;
|
|
109
304
|
let latestStructured;
|
|
110
305
|
let pendingTools = [];
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
306
|
+
// Text/thought stream via progressive-yield under egress; validation and egress
|
|
307
|
+
// both hold non-visible events (structured) until the attempt gate, so a policy
|
|
308
|
+
// sees the structured payload before any of it reaches the host.
|
|
309
|
+
const holdLate = Boolean(profileTurnOutputs(profile)?.validation ||
|
|
310
|
+
resolveGuardrailPolicy(profile.guardrails).egress?.enforce);
|
|
311
|
+
// Ceiling is cumulative `state.stepCount` across before_end inject re-entries
|
|
312
|
+
// within this attempt. Validation/egress repair resets stepCount at the start
|
|
313
|
+
// of each attempt cycle (see gates.ts).
|
|
314
|
+
while (!isStepLimitReached(state.stepCount, generation.maxSteps ?? 0)) {
|
|
115
315
|
throwIfAborted(args.safe.signal);
|
|
116
|
-
stepInAttempt++;
|
|
117
316
|
state.stepCount++;
|
|
118
|
-
|
|
317
|
+
// Mid-loop inject lives on `post_tool` (after tools). Opening inject is `pre_turn`
|
|
318
|
+
// outside this loop.
|
|
319
|
+
const stepResult = yield* executeAutonomousStep({ profile, generation, system, provider, upstream, signal: args.safe.signal }, state, { holdLate });
|
|
119
320
|
if (stepResult.latestStructured !== undefined) {
|
|
120
321
|
latestStructured = stepResult.latestStructured;
|
|
121
322
|
}
|
|
@@ -123,8 +324,8 @@ async function* executeAttempt(args) {
|
|
|
123
324
|
if (pendingTools.length === 0) {
|
|
124
325
|
break;
|
|
125
326
|
}
|
|
126
|
-
const
|
|
127
|
-
if (!
|
|
327
|
+
const executed = yield* handlePendingTools(pendingTools, generation, profile, state, args.safe);
|
|
328
|
+
if (!executed) {
|
|
128
329
|
break;
|
|
129
330
|
}
|
|
130
331
|
}
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import type { ModelProvider, Profile, ResolvedGeneration, TurnEvent } from '../../types.js';
|
|
2
|
-
|
|
2
|
+
/** Mutable control flags shared with the step runner during one provider stream. */
|
|
3
|
+
interface OutboundStreamControl {
|
|
4
|
+
/** Stop releasing text/thought/media to the host; keep recording for egress. */
|
|
5
|
+
withholdVisible: boolean;
|
|
6
|
+
}
|
|
3
7
|
declare function shouldSkipStreamEvent(event: TurnEvent, profile: Profile): boolean;
|
|
4
8
|
declare function yieldProviderEvents(args: {
|
|
5
9
|
profile: Profile;
|
|
6
10
|
generation: ResolvedGeneration;
|
|
7
11
|
system: string;
|
|
8
12
|
provider: ModelProvider;
|
|
9
|
-
|
|
13
|
+
upstream: Record<string, unknown>[];
|
|
10
14
|
signal?: AbortSignal;
|
|
15
|
+
control?: OutboundStreamControl;
|
|
11
16
|
}): AsyncGenerator<TurnEvent>;
|
|
12
|
-
export {
|
|
17
|
+
export type { OutboundStreamControl };
|
|
18
|
+
export { shouldSkipStreamEvent, yieldProviderEvents };
|
|
@@ -1,44 +1,16 @@
|
|
|
1
|
+
import { eventHasCanary, isStreamedCanaryEvent, redactCanary } from '../../../guardrails/canary.js';
|
|
2
|
+
import { EGRESS_RULES } from '../../../guardrails/egress.js';
|
|
1
3
|
import { publicError, throwIfAborted, toErrorEvent } from '../../../guardrails/error.js';
|
|
4
|
+
import { guardrailFromHits } from '../../../guardrails/events.js';
|
|
5
|
+
import { resolveGuardrailPolicy } from '../../../guardrails/policy.js';
|
|
6
|
+
import { createOutboundProgressiveGate, } from '../../../guardrails/progressive-yield.js';
|
|
7
|
+
import { profileTurnOutputs } from '../../registry/profile-outputs.js';
|
|
2
8
|
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
9
|
function shouldSkipStreamEvent(event, profile) {
|
|
35
|
-
return event.type === 'thought' && profile
|
|
10
|
+
return (event.type === 'thought' && profileTurnOutputs(profile)?.streaming?.streamThoughts === false);
|
|
36
11
|
}
|
|
37
|
-
function* processNormalEvent(event
|
|
38
|
-
if (event.type === '
|
|
39
|
-
yield* interceptProviderTool(event, profile, generation);
|
|
40
|
-
}
|
|
41
|
-
else if (event.type === 'error') {
|
|
12
|
+
function* processNormalEvent(event) {
|
|
13
|
+
if (event.type === 'error') {
|
|
42
14
|
const internal = event.errorInternal ?? event.error ?? '';
|
|
43
15
|
yield {
|
|
44
16
|
type: 'error',
|
|
@@ -50,24 +22,148 @@ function* processNormalEvent(event, profile, generation) {
|
|
|
50
22
|
yield event;
|
|
51
23
|
}
|
|
52
24
|
}
|
|
25
|
+
function* yieldCanaryLeak(canary, event) {
|
|
26
|
+
const guardrail = guardrailFromHits('output_delta', 'untrusted', [{ rule: EGRESS_RULES.canary, severity: 'high', match: '[canary]' }], 'block');
|
|
27
|
+
if (guardrail) {
|
|
28
|
+
yield guardrail;
|
|
29
|
+
}
|
|
30
|
+
yield redactCanary(event, canary);
|
|
31
|
+
yield toErrorEvent('canary leaked');
|
|
32
|
+
}
|
|
33
|
+
function* yieldDeltaBlock(hits) {
|
|
34
|
+
const guardrail = guardrailFromHits('output_delta', 'untrusted', hits, 'block');
|
|
35
|
+
if (guardrail) {
|
|
36
|
+
yield guardrail;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function isHostVisible(event) {
|
|
40
|
+
return event.type === 'text' || event.type === 'thought' || event.type === 'media';
|
|
41
|
+
}
|
|
42
|
+
function canaryOnlyImmediateStop(policy) {
|
|
43
|
+
return !policy.egress?.enforce;
|
|
44
|
+
}
|
|
45
|
+
function hasCanaryHit(hits) {
|
|
46
|
+
return hits.some((hit) => hit.rule === EGRESS_RULES.canary);
|
|
47
|
+
}
|
|
53
48
|
async function* yieldProviderEvents(args) {
|
|
54
|
-
const { profile, generation, system, provider,
|
|
49
|
+
const { profile, generation, system, provider, upstream, signal, control } = args;
|
|
55
50
|
const { canary } = generation;
|
|
51
|
+
const policy = resolveGuardrailPolicy(profile.guardrails);
|
|
52
|
+
const context = {
|
|
53
|
+
stage: 'output_final',
|
|
54
|
+
trust: 'untrusted',
|
|
55
|
+
profileId: profile.id,
|
|
56
|
+
...(canary ? { canary } : {}),
|
|
57
|
+
};
|
|
58
|
+
const gate = createOutboundProgressiveGate(policy, context);
|
|
59
|
+
let lastStreamType;
|
|
60
|
+
let withholdVisible = false;
|
|
61
|
+
function armWithhold() {
|
|
62
|
+
withholdVisible = true;
|
|
63
|
+
if (control)
|
|
64
|
+
control.withholdVisible = true;
|
|
65
|
+
}
|
|
66
|
+
function withholding() {
|
|
67
|
+
return withholdVisible;
|
|
68
|
+
}
|
|
69
|
+
async function* drainBlockedDelta(hits) {
|
|
70
|
+
yield* yieldDeltaBlock(hits);
|
|
71
|
+
// Arm withhold before recording the unreleased tail so the step runner
|
|
72
|
+
// does not forward that text to the host.
|
|
73
|
+
armWithhold();
|
|
74
|
+
const tail = gate?.drainUnreleased();
|
|
75
|
+
if (tail)
|
|
76
|
+
yield { type: 'text', text: tail };
|
|
77
|
+
}
|
|
78
|
+
async function* flushGate() {
|
|
79
|
+
if (!gate || !lastStreamType) {
|
|
80
|
+
return 'pass';
|
|
81
|
+
}
|
|
82
|
+
const emitType = lastStreamType;
|
|
83
|
+
const result = await gate.flush();
|
|
84
|
+
lastStreamType = undefined;
|
|
85
|
+
if (result.blocked) {
|
|
86
|
+
if (hasCanaryHit(result.hits) && canary && canaryOnlyImmediateStop(policy)) {
|
|
87
|
+
yield* yieldCanaryLeak(canary, { type: emitType, text: gate.accumulated() });
|
|
88
|
+
return 'stop';
|
|
89
|
+
}
|
|
90
|
+
yield* drainBlockedDelta(result.hits);
|
|
91
|
+
return 'pass';
|
|
92
|
+
}
|
|
93
|
+
if (result.emit) {
|
|
94
|
+
yield* processNormalEvent({ type: emitType, text: result.emit });
|
|
95
|
+
}
|
|
96
|
+
return 'pass';
|
|
97
|
+
}
|
|
98
|
+
async function* gateStreamEvent(event) {
|
|
99
|
+
if (!gate) {
|
|
100
|
+
yield* processNormalEvent(event);
|
|
101
|
+
return 'continue';
|
|
102
|
+
}
|
|
103
|
+
if (withholding()) {
|
|
104
|
+
// Keep recording ungated fragments for egress context; host will not see them.
|
|
105
|
+
yield { type: event.type, text: event.text ?? '' };
|
|
106
|
+
return 'continue';
|
|
107
|
+
}
|
|
108
|
+
if (lastStreamType && lastStreamType !== event.type) {
|
|
109
|
+
const flushed = yield* flushGate();
|
|
110
|
+
if (flushed === 'stop') {
|
|
111
|
+
return 'stop';
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
lastStreamType = event.type;
|
|
115
|
+
const result = await gate.process(event.text ?? '');
|
|
116
|
+
if (result.blocked) {
|
|
117
|
+
if (hasCanaryHit(result.hits) && canary && canaryOnlyImmediateStop(policy)) {
|
|
118
|
+
yield* yieldCanaryLeak(canary, event);
|
|
119
|
+
return 'stop';
|
|
120
|
+
}
|
|
121
|
+
yield* drainBlockedDelta(result.hits);
|
|
122
|
+
return 'continue';
|
|
123
|
+
}
|
|
124
|
+
if (result.emit) {
|
|
125
|
+
yield* processNormalEvent({ ...event, text: result.emit });
|
|
126
|
+
}
|
|
127
|
+
return 'continue';
|
|
128
|
+
}
|
|
56
129
|
throwIfAborted(signal);
|
|
57
130
|
for await (const event of provider.complete({
|
|
58
131
|
...providerCompleteRequest(generation, system),
|
|
59
132
|
signal,
|
|
60
|
-
|
|
61
|
-
|
|
133
|
+
tapUpstream: (row) => {
|
|
134
|
+
upstream.push(row);
|
|
62
135
|
},
|
|
63
136
|
})) {
|
|
64
137
|
throwIfAborted(signal);
|
|
138
|
+
if (isStreamedCanaryEvent(event)) {
|
|
139
|
+
const status = yield* gateStreamEvent(event);
|
|
140
|
+
if (status === 'stop') {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
if (gate && lastStreamType) {
|
|
146
|
+
const flushed = yield* flushGate();
|
|
147
|
+
if (flushed === 'stop') {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
65
151
|
if (canary && eventHasCanary(event, canary)) {
|
|
66
|
-
yield
|
|
67
|
-
|
|
152
|
+
yield* yieldCanaryLeak(canary, event);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (withholding() && isHostVisible(event)) {
|
|
156
|
+
// Record for attempt egress / repair; step runner withholds from host.
|
|
157
|
+
yield event;
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
yield* processNormalEvent(event);
|
|
161
|
+
}
|
|
162
|
+
if (gate && lastStreamType) {
|
|
163
|
+
const flushed = yield* flushGate();
|
|
164
|
+
if (flushed === 'stop') {
|
|
68
165
|
return;
|
|
69
166
|
}
|
|
70
|
-
yield* processNormalEvent(event, profile, generation);
|
|
71
167
|
}
|
|
72
168
|
}
|
|
73
|
-
export { shouldSkipStreamEvent,
|
|
169
|
+
export { shouldSkipStreamEvent, yieldProviderEvents };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `runSession` — long-lived live profile execution.
|
|
3
|
+
*
|
|
4
|
+
* Shares resolve / tools / canary / system / outbound gate with `runTurn`.
|
|
5
|
+
* Does not use `ModelProvider.complete()` — live is a session, not one turn.
|
|
6
|
+
*
|
|
7
|
+
* Stages: `docs/contracts/stages.md` (cycle map + `executeTool`).
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
import type { GeminiTransport } from '../../../providers/google/keys.js';
|
|
12
|
+
import type { LiveSession, SessionRequest } from '../../types.js';
|
|
13
|
+
export type { LiveSession, SessionRequest };
|
|
14
|
+
export interface RunSessionOptions {
|
|
15
|
+
gemini: GeminiTransport;
|
|
16
|
+
/** Override socket open (Cloudflare fetch-upgrade, tests). Default: `new WebSocket(url)`. */
|
|
17
|
+
openWebSocket?: (url: string) => Promise<WebSocket>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Open a gated Gemini Live session for a `type: 'live'` profile.
|
|
21
|
+
*
|
|
22
|
+
* Hosts bridge browser sockets and tool dispatch; THEORUM owns Gemini WS,
|
|
23
|
+
* framing, inbound prep, outbound canary/egress gates, and live stages.
|
|
24
|
+
*/
|
|
25
|
+
export declare function runSession(req: SessionRequest, options: RunSessionOptions): Promise<LiveSession>;
|