@theoremjs/agents 0.3.0 → 0.3.2
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 +277 -995
- package/esm/mod.d.ts +34 -20
- package/esm/mod.js +19 -12
- package/esm/src/cli/commands/bench.js +36 -14
- package/esm/src/cli/commands/detect-compile.d.ts +17 -0
- package/esm/src/cli/commands/detect-compile.js +22 -0
- package/esm/src/cli/commands/eval.d.ts +3 -3
- package/esm/src/cli/commands/fuzz-canary.js +55 -16
- package/esm/src/cli/commands/profile.js +4 -4
- package/esm/src/cli/commands/run.d.ts +2 -2
- package/esm/src/cli/commands/run.js +1 -1
- package/esm/src/cli/commands/test.d.ts +4 -3
- package/esm/src/cli/commands/test.js +2 -2
- package/esm/src/cli/index.js +9 -9
- package/esm/src/cli/matrix/fixtures.js +25 -30
- package/esm/src/evals/attachments.d.ts +1 -0
- package/esm/src/evals/attachments.js +4 -2
- package/esm/src/evals/breakdown.d.ts +2 -0
- package/esm/src/evals/breakdown.js +1 -0
- package/esm/src/evals/graders/answer.d.ts +3 -0
- package/esm/src/evals/graders/answer.js +1 -0
- package/esm/src/evals/graders/code.d.ts +7 -31
- package/esm/src/evals/graders/code.js +4 -25
- package/esm/src/evals/graders/judge.d.ts +4 -0
- package/esm/src/evals/graders/judge.js +7 -5
- package/esm/src/evals/graders/latency.d.ts +1 -0
- package/esm/src/evals/graders/latency.js +3 -2
- package/esm/src/evals/graders/live.d.ts +3 -0
- package/esm/src/evals/graders/live.js +2 -0
- package/esm/src/evals/graders/media.js +1 -2
- package/esm/src/evals/graders/shared.js +1 -1
- package/esm/src/evals/graders/transcript.d.ts +2 -0
- package/esm/src/evals/graders/transcript.js +5 -3
- package/esm/src/evals/mod.d.ts +1 -9
- package/esm/src/evals/mod.js +1 -9
- package/esm/src/evals/record.d.ts +6 -0
- package/esm/src/evals/record.js +4 -2
- package/esm/src/evals/rubrics/mod.d.ts +1 -1
- package/esm/src/evals/rubrics/mod.js +1 -1
- package/esm/src/evals/rubrics/mustache.js +1 -1
- package/esm/src/evals/rubrics/types.js +1 -1
- package/esm/src/evals/run.d.ts +9 -52
- package/esm/src/evals/run.js +12 -46
- package/esm/src/evals/suite.d.ts +12 -3
- package/esm/src/evals/suite.js +9 -4
- package/esm/src/evals/summary.d.ts +3 -0
- package/esm/src/evals/summary.js +1 -0
- package/esm/src/evals/trial.d.ts +3 -16
- package/esm/src/evals/trial.js +7 -30
- package/esm/src/evals/types.d.ts +30 -121
- package/esm/src/evals/types.js +3 -16
- package/esm/src/evals/verdict.d.ts +5 -0
- package/esm/src/evals/verdict.js +4 -1
- package/esm/src/guardrails/boundaries.d.ts +41 -0
- package/esm/src/guardrails/boundaries.js +103 -0
- package/esm/src/guardrails/canary-gate.d.ts +1 -0
- package/esm/src/guardrails/canary.d.ts +49 -15
- package/esm/src/guardrails/canary.js +103 -30
- package/esm/src/guardrails/compile-egress.d.ts +6 -5
- package/esm/src/guardrails/compile-egress.js +6 -5
- package/esm/src/guardrails/corpus/canary-egress-attacks.d.ts +3 -1
- package/esm/src/guardrails/corpus/canary-egress-attacks.js +4 -2
- package/esm/src/guardrails/corpus/fuzz-inbound.js +14 -17
- package/esm/src/guardrails/corpus/inbound-payloads.d.ts +2 -0
- package/esm/src/guardrails/corpus/inbound-payloads.js +4 -2
- package/esm/src/guardrails/corpus/live-attacks.d.ts +2 -0
- package/esm/src/guardrails/corpus/live-attacks.js +6 -1
- package/esm/src/guardrails/corpus/mod.d.ts +1 -1
- package/esm/src/guardrails/corpus/secrets.d.ts +3 -3
- package/esm/src/guardrails/corpus/secrets.js +2 -2
- package/esm/src/guardrails/corpus/strings.d.ts +1 -1
- package/esm/src/guardrails/corpus/strings.js +1 -1
- package/esm/src/guardrails/corpus/types.d.ts +5 -1
- package/esm/src/guardrails/credential-rules.d.ts +36 -0
- package/esm/src/guardrails/credential-rules.js +3001 -0
- package/esm/src/guardrails/credential-scan.d.ts +45 -0
- package/esm/src/guardrails/credential-scan.js +172 -0
- package/esm/src/guardrails/destinations.d.ts +45 -0
- package/esm/src/guardrails/destinations.js +234 -0
- package/esm/src/guardrails/detect-at.d.ts +107 -0
- package/esm/src/guardrails/detect-at.js +434 -0
- package/esm/src/guardrails/detect-reply.d.ts +61 -0
- package/esm/src/guardrails/detect-reply.js +95 -0
- package/esm/src/guardrails/detect-stream.d.ts +33 -0
- package/esm/src/guardrails/detect-stream.js +77 -0
- package/esm/src/guardrails/detectors.d.ts +216 -0
- package/esm/src/guardrails/detectors.js +503 -0
- package/esm/src/guardrails/egress-automata.d.ts +4 -6
- package/esm/src/guardrails/egress-automata.js +24095 -4572
- package/esm/src/guardrails/egress-compiler.d.ts +38 -16
- package/esm/src/guardrails/egress-compiler.js +254 -60
- package/esm/src/guardrails/egress-patterns.d.ts +4 -2
- package/esm/src/guardrails/egress-patterns.js +6 -2
- package/esm/src/guardrails/egress-stream.d.ts +54 -36
- package/esm/src/guardrails/egress-stream.js +253 -124
- package/esm/src/guardrails/egress-urls.d.ts +6 -3
- package/esm/src/guardrails/egress-urls.js +14 -22
- package/esm/src/guardrails/egress.d.ts +26 -86
- package/esm/src/guardrails/egress.js +59 -309
- package/esm/src/guardrails/error.d.ts +13 -8
- package/esm/src/guardrails/error.js +25 -18
- package/esm/src/guardrails/event-schemas.d.ts +46 -3
- package/esm/src/guardrails/event-schemas.js +12 -5
- package/esm/src/guardrails/events.d.ts +5 -1
- package/esm/src/guardrails/events.js +4 -1
- package/esm/src/guardrails/hints.d.ts +14 -0
- package/esm/src/guardrails/hints.js +57 -0
- package/esm/src/guardrails/hits.d.ts +7 -1
- package/esm/src/guardrails/hits.js +12 -1
- package/esm/src/guardrails/host-patterns.d.ts +85 -0
- package/esm/src/guardrails/host-patterns.js +173 -0
- package/esm/src/guardrails/injection-patterns.d.ts +6 -1
- package/esm/src/guardrails/injection-patterns.js +33 -1
- package/esm/src/guardrails/injection-reversed.d.ts +9 -0
- package/esm/src/guardrails/injection-reversed.js +49 -0
- package/esm/src/guardrails/injection.d.ts +17 -1
- package/esm/src/guardrails/injection.js +259 -36
- package/esm/src/guardrails/labels.d.ts +40 -0
- package/esm/src/guardrails/labels.js +881 -0
- package/esm/src/guardrails/live-outbound-gate.d.ts +9 -8
- package/esm/src/guardrails/live-outbound-gate.js +100 -107
- package/esm/src/guardrails/mod.d.ts +30 -22
- package/esm/src/guardrails/mod.js +19 -14
- package/esm/src/guardrails/network.d.ts +4 -0
- package/esm/src/guardrails/network.js +21 -19
- package/esm/src/guardrails/normalize.d.ts +15 -1
- package/esm/src/guardrails/normalize.js +34 -1
- package/esm/src/guardrails/policy.d.ts +2 -17
- package/esm/src/guardrails/policy.js +12 -41
- package/esm/src/guardrails/progressive-yield.d.ts +65 -24
- package/esm/src/guardrails/progressive-yield.js +191 -147
- package/esm/src/guardrails/prompt-echo.d.ts +4 -2
- package/esm/src/guardrails/prompt-echo.js +87 -6
- package/esm/src/guardrails/quota.d.ts +4 -1
- package/esm/src/guardrails/quota.js +7 -2
- package/esm/src/guardrails/rules.d.ts +20 -29
- package/esm/src/guardrails/rules.js +23 -30
- package/esm/src/guardrails/sanitize.d.ts +32 -15
- package/esm/src/guardrails/sanitize.js +100 -124
- package/esm/src/guardrails/sensitive-groups.d.ts +21 -0
- package/esm/src/guardrails/sensitive-groups.js +12 -0
- package/esm/src/guardrails/sensitive.d.ts +16 -23
- package/esm/src/guardrails/sensitive.js +168 -47
- package/esm/src/guardrails/serialize.d.ts +1 -0
- package/esm/src/guardrails/testing.d.ts +4 -2
- package/esm/src/guardrails/testing.js +4 -2
- package/esm/src/guardrails/theorem-error.d.ts +5 -2
- package/esm/src/guardrails/theorem-error.js +6 -3
- package/esm/src/guardrails/thought-guard.d.ts +34 -13
- package/esm/src/guardrails/thought-guard.js +264 -64
- package/esm/src/guardrails/tool-directives.d.ts +29 -10
- package/esm/src/guardrails/tool-directives.js +133 -47
- package/esm/src/guardrails/tool-leak.d.ts +26 -0
- package/esm/src/guardrails/tool-leak.js +45 -0
- package/esm/src/guardrails/tool-result.d.ts +45 -14
- package/esm/src/guardrails/tool-result.js +94 -70
- package/esm/src/guardrails/types.d.ts +79 -71
- package/esm/src/guardrails/types.js +11 -7
- package/esm/src/host/client-turn.d.ts +29 -2
- package/esm/src/host/client-turn.js +46 -4
- package/esm/src/host/mint-trace.d.ts +1 -0
- package/esm/src/host/mint-trace.js +3 -2
- package/esm/src/host/mod.d.ts +2 -2
- package/esm/src/host/mod.js +1 -1
- package/esm/src/host/readStreamingJsonStringField.js +2 -43
- package/esm/src/host/reply.d.ts +6 -0
- package/esm/src/host/reply.js +8 -1
- package/esm/src/interface/blocks.d.ts +3 -0
- package/esm/src/interface/blocks.js +84 -14
- package/esm/src/interface/composer-actions.d.ts +4 -0
- package/esm/src/interface/composer-actions.js +5 -3
- package/esm/src/interface/draft.d.ts +6 -0
- package/esm/src/interface/draft.js +22 -11
- package/esm/src/interface/from-profile.d.ts +13 -1
- package/esm/src/interface/from-profile.js +66 -31
- package/esm/src/interface/history.d.ts +9 -3
- package/esm/src/interface/history.js +33 -24
- package/esm/src/interface/inputs.d.ts +1 -0
- package/esm/src/interface/inputs.js +3 -0
- package/esm/src/interface/mod.d.ts +4 -2
- package/esm/src/interface/mod.js +3 -2
- package/esm/src/interface/models.d.ts +7 -0
- package/esm/src/interface/models.js +5 -0
- package/esm/src/interface/pending.d.ts +9 -0
- package/esm/src/interface/pending.js +9 -3
- package/esm/src/interface/profile-interface.js +54 -40
- package/esm/src/interface/session.d.ts +12 -5
- package/esm/src/interface/session.js +17 -10
- package/esm/src/interface/stop.d.ts +13 -0
- package/esm/src/interface/stop.js +28 -0
- package/esm/src/interface/tool-calls.d.ts +14 -2
- package/esm/src/interface/tool-calls.js +64 -10
- package/esm/src/interface/tool-invoke.d.ts +2 -0
- package/esm/src/interface/tool-invoke.js +3 -1
- package/esm/src/interface/tool-media.d.ts +2 -0
- package/esm/src/interface/tool-media.js +2 -1
- package/esm/src/interface/types.d.ts +105 -40
- package/esm/src/interface/types.js +1 -0
- package/esm/src/kernel/api-catalog.d.ts +85 -0
- package/esm/src/kernel/api-catalog.js +229 -0
- package/esm/src/kernel/auth/crypto.d.ts +7 -2
- package/esm/src/kernel/auth/crypto.js +12 -10
- package/esm/src/kernel/auth/oauth.d.ts +2 -1
- package/esm/src/kernel/auth/oauth.js +23 -22
- package/esm/src/kernel/auth/typed-secret.js +2 -2
- package/esm/src/kernel/auth/types.d.ts +13 -0
- package/esm/src/kernel/checkpoint.d.ts +43 -0
- package/esm/src/kernel/checkpoint.js +58 -0
- package/esm/src/kernel/default-scope.d.ts +43 -5
- package/esm/src/kernel/default-scope.js +54 -5
- package/esm/src/kernel/engine/call-trace.d.ts +19 -0
- package/esm/src/kernel/engine/call-trace.js +29 -0
- package/esm/src/kernel/engine/compaction.d.ts +6 -5
- package/esm/src/kernel/engine/compaction.js +12 -11
- package/esm/src/kernel/engine/decision.d.ts +10 -8
- package/esm/src/kernel/engine/decision.js +174 -146
- package/esm/src/kernel/engine/embedding.d.ts +8 -0
- package/esm/src/kernel/engine/embedding.js +118 -0
- package/esm/src/kernel/engine/live-inbound.d.ts +14 -4
- package/esm/src/kernel/engine/live-inbound.js +36 -11
- package/esm/src/kernel/engine/live-ingress.d.ts +6 -0
- package/esm/src/kernel/engine/live-ingress.js +6 -1
- package/esm/src/kernel/engine/repair.js +12 -12
- package/esm/src/kernel/engine/runner/gates.d.ts +2 -2
- package/esm/src/kernel/engine/runner/gates.js +287 -101
- package/esm/src/kernel/engine/runner/mod.d.ts +19 -5
- package/esm/src/kernel/engine/runner/mod.js +107 -56
- package/esm/src/kernel/engine/runner/nested.d.ts +32 -0
- package/esm/src/kernel/engine/runner/nested.js +134 -0
- package/esm/src/kernel/engine/runner/schema-validation.d.ts +24 -3
- package/esm/src/kernel/engine/runner/schema-validation.js +78 -4
- package/esm/src/kernel/engine/runner/stages.d.ts +1 -1
- package/esm/src/kernel/engine/runner/stages.js +1 -8
- package/esm/src/kernel/engine/runner/state.d.ts +33 -12
- package/esm/src/kernel/engine/runner/state.js +11 -1
- package/esm/src/kernel/engine/runner/step-order.d.ts +27 -0
- package/esm/src/kernel/engine/runner/step-order.js +165 -0
- package/esm/src/kernel/engine/runner/steps.d.ts +2 -2
- package/esm/src/kernel/engine/runner/steps.js +329 -169
- package/esm/src/kernel/engine/runner/stream.d.ts +42 -11
- package/esm/src/kernel/engine/runner/stream.js +197 -46
- package/esm/src/kernel/engine/runner/usage.d.ts +5 -5
- package/esm/src/kernel/engine/runner/usage.js +12 -14
- package/esm/src/kernel/engine/session/mod.d.ts +8 -6
- package/esm/src/kernel/engine/session/mod.js +360 -129
- package/esm/src/kernel/engine/session/session-trace.d.ts +10 -10
- package/esm/src/kernel/engine/session/session-trace.js +41 -30
- package/esm/src/kernel/engine/token-estimate.d.ts +10 -64
- package/esm/src/kernel/engine/token-estimate.js +14 -194
- package/esm/src/kernel/engine/tool-trace.d.ts +3 -3
- package/esm/src/kernel/engine/tool-trace.js +2 -1
- package/esm/src/kernel/engine/turn-trace.d.ts +8 -7
- package/esm/src/kernel/engine/turn-trace.js +28 -36
- package/esm/src/kernel/engine/usage.d.ts +6 -0
- package/esm/src/kernel/engine/usage.js +17 -0
- package/esm/src/kernel/interaction-parts.d.ts +3 -0
- package/esm/src/kernel/interaction-parts.js +18 -0
- package/esm/src/kernel/json.d.ts +10 -0
- package/esm/src/kernel/json.js +3 -0
- package/esm/src/kernel/mod.d.ts +38 -11
- package/esm/src/kernel/mod.js +22 -7
- package/esm/src/kernel/profile-graph.d.ts +11 -6
- package/esm/src/kernel/profile-graph.js +14 -7
- package/esm/src/kernel/profile-presence.d.ts +10 -1
- package/esm/src/kernel/profile-presence.js +90 -75
- package/esm/src/kernel/profile-scope.d.ts +7 -3
- package/esm/src/kernel/profile-scope.js +67 -55
- package/esm/src/kernel/protocols/binding.d.ts +65 -0
- package/esm/src/kernel/protocols/binding.js +125 -0
- package/esm/src/kernel/protocols/limits.d.ts +15 -0
- package/esm/src/kernel/protocols/limits.js +28 -0
- package/esm/src/kernel/protocols/mod.d.ts +5 -0
- package/esm/src/kernel/protocols/mod.js +5 -0
- package/esm/src/kernel/protocols/prices.d.ts +36 -0
- package/esm/src/kernel/protocols/prices.js +37 -0
- package/esm/src/kernel/protocols/protocol.d.ts +253 -0
- package/esm/src/kernel/protocols/protocol.js +253 -0
- package/esm/src/kernel/protocols/provider.d.ts +108 -0
- package/esm/src/kernel/protocols/provider.js +143 -0
- package/esm/src/kernel/protocols/runtime.d.ts +55 -0
- package/esm/src/kernel/protocols/runtime.js +534 -0
- package/esm/src/kernel/provider-budget.d.ts +32 -0
- package/esm/src/kernel/provider-budget.js +262 -0
- package/esm/src/kernel/provider-dispatch.d.ts +13 -0
- package/esm/src/kernel/provider-dispatch.js +36 -0
- package/esm/src/kernel/provider-live.d.ts +7 -0
- package/esm/src/kernel/provider-live.js +189 -0
- package/esm/src/kernel/provider-runtime.d.ts +57 -0
- package/esm/src/kernel/provider-runtime.js +524 -0
- package/esm/src/kernel/registry/attachments.d.ts +15 -4
- package/esm/src/kernel/registry/attachments.js +31 -22
- package/esm/src/kernel/registry/catalog.d.ts +6 -0
- package/esm/src/kernel/registry/catalog.js +9 -2
- package/esm/src/kernel/registry/embedding-rules.d.ts +28 -0
- package/esm/src/kernel/registry/embedding-rules.js +66 -0
- package/esm/src/kernel/registry/ingress.d.ts +6 -2
- package/esm/src/kernel/registry/ingress.js +55 -10
- package/esm/src/kernel/registry/kernel-registry.d.ts +3 -0
- package/esm/src/kernel/registry/kernel-registry.js +9 -2
- package/esm/src/kernel/registry/profile-outputs.js +4 -1
- package/esm/src/kernel/registry/profiles.d.ts +38 -14
- package/esm/src/kernel/registry/profiles.js +280 -205
- package/esm/src/kernel/registry/provider-request.d.ts +3 -3
- package/esm/src/kernel/registry/provider-request.js +5 -13
- package/esm/src/kernel/registry/resolve.d.ts +4 -1
- package/esm/src/kernel/registry/resolve.js +59 -58
- package/esm/src/kernel/registry/schemas.d.ts +3 -0
- package/esm/src/kernel/registry/schemas.js +3 -1
- package/esm/src/kernel/registry/slot-fill.d.ts +7 -0
- package/esm/src/kernel/registry/slot-fill.js +22 -0
- package/esm/src/kernel/registry/system-prompt.js +7 -8
- package/esm/src/kernel/registry/vault.d.ts +14 -13
- package/esm/src/kernel/registry/vault.js +1 -14
- package/esm/src/kernel/schema.d.ts +100 -46
- package/esm/src/kernel/schema.js +499 -257
- package/esm/src/kernel/scope.d.ts +12 -5
- package/esm/src/kernel/scope.js +23 -3
- package/esm/src/kernel/stages.d.ts +38 -3
- package/esm/src/kernel/stages.js +82 -39
- package/esm/src/kernel/stop.d.ts +29 -6
- package/esm/src/kernel/stop.js +16 -4
- package/esm/src/kernel/system-parts.js +6 -6
- package/esm/src/kernel/tools/activity-label.d.ts +12 -6
- package/esm/src/kernel/tools/activity-label.js +258 -32
- package/esm/src/kernel/tools/agent.d.ts +66 -0
- package/esm/src/kernel/tools/agent.js +212 -0
- package/esm/src/kernel/tools/coordinate.d.ts +4 -0
- package/esm/src/kernel/tools/coordinate.js +165 -0
- package/esm/src/kernel/tools/events.d.ts +21 -6
- package/esm/src/kernel/tools/events.js +53 -18
- package/esm/src/kernel/tools/execute.d.ts +47 -11
- package/esm/src/kernel/tools/execute.js +508 -136
- package/esm/src/kernel/tools/gate-answer.d.ts +12 -2
- package/esm/src/kernel/tools/gate-answer.js +17 -6
- package/esm/src/kernel/tools/handler-events.d.ts +45 -0
- package/esm/src/kernel/tools/handler-events.js +106 -0
- package/esm/src/kernel/tools/harness.d.ts +1 -0
- package/esm/src/kernel/tools/harness.js +2 -1
- package/esm/src/kernel/tools/http-limit.d.ts +27 -0
- package/esm/src/kernel/tools/http-limit.js +85 -0
- package/esm/src/kernel/tools/invoke.d.ts +27 -5
- package/esm/src/kernel/tools/invoke.js +223 -70
- package/esm/src/kernel/tools/mcp-sessions.d.ts +4 -1
- package/esm/src/kernel/tools/mcp-sessions.js +13 -8
- package/esm/src/kernel/tools/mod.d.ts +4 -3
- package/esm/src/kernel/tools/mod.js +3 -2
- package/esm/src/kernel/tools/model-text.d.ts +10 -5
- package/esm/src/kernel/tools/model-text.js +18 -12
- package/esm/src/kernel/tools/operation.d.ts +76 -0
- package/esm/src/kernel/tools/operation.js +100 -0
- package/esm/src/kernel/tools/page-answer.d.ts +8 -0
- package/esm/src/kernel/tools/page-answer.js +19 -0
- package/esm/src/kernel/tools/permission.d.ts +11 -2
- package/esm/src/kernel/tools/permission.js +12 -12
- package/esm/src/kernel/tools/project.d.ts +4 -1
- package/esm/src/kernel/tools/project.js +32 -2
- package/esm/src/kernel/tools/registry.d.ts +9 -2
- package/esm/src/kernel/tools/registry.js +69 -10
- package/esm/src/kernel/tools/remote.d.ts +40 -6
- package/esm/src/kernel/tools/remote.js +219 -92
- package/esm/src/kernel/tools/resolve.d.ts +3 -0
- package/esm/src/kernel/tools/resolve.js +12 -4
- package/esm/src/kernel/tools/run.d.ts +28 -0
- package/esm/src/kernel/tools/run.js +86 -0
- package/esm/src/kernel/tools/schema.d.ts +3 -3
- package/esm/src/kernel/tools/schema.js +21 -100
- package/esm/src/kernel/tools/signed-in-fetch.d.ts +2 -1
- package/esm/src/kernel/tools/signed-in-fetch.js +3 -3
- package/esm/src/kernel/tools/stage-run.d.ts +27 -4
- package/esm/src/kernel/tools/stage-run.js +75 -17
- package/esm/src/kernel/tools/types.d.ts +235 -25
- package/esm/src/kernel/tools/unchecked-output.d.ts +14 -0
- package/esm/src/kernel/tools/unchecked-output.js +18 -0
- package/esm/src/kernel/turn-events.d.ts +208 -31
- package/esm/src/kernel/turn-events.js +127 -9
- package/esm/src/kernel/types.d.ts +302 -161
- package/esm/src/kernel/util/base64.d.ts +2 -0
- package/esm/src/kernel/util/base64.js +2 -0
- package/esm/src/kernel/util/partial-json.d.ts +23 -0
- package/esm/src/kernel/util/partial-json.js +128 -0
- package/esm/src/kernel/util/record.d.ts +1 -0
- package/esm/src/kernel/util/record.js +1 -0
- package/esm/src/observability/destinations.d.ts +5 -0
- package/esm/src/observability/destinations.js +7 -2
- package/esm/src/observability/jsonl.d.ts +2 -2
- package/esm/src/observability/jsonl.js +15 -22
- package/esm/src/observability/mod.d.ts +3 -3
- package/esm/src/observability/mod.js +2 -2
- package/esm/src/observability/openinference.d.ts +1 -1
- package/esm/src/observability/openinference.js +3 -3
- package/esm/src/observability/otlp.d.ts +3 -0
- package/esm/src/observability/otlp.js +3 -3
- package/esm/src/observability/phoenix.d.ts +1 -0
- package/esm/src/observability/policy.d.ts +3 -0
- package/esm/src/observability/policy.js +5 -1
- package/esm/src/observability/resolve-policy.js +11 -5
- package/esm/src/observability/spans.d.ts +8 -2
- package/esm/src/observability/spans.js +21 -5
- package/esm/src/observability/trace-catalog.d.ts +19 -2
- package/esm/src/observability/trace-catalog.js +130 -88
- package/esm/src/observability/trace-record.js +22 -17
- package/esm/src/observability/trace-schema.d.ts +3 -0
- package/esm/src/observability/trace-schema.js +1 -1
- package/esm/src/observability/trace-sink.d.ts +1 -0
- package/esm/src/observability/trace-sink.js +1 -1
- package/esm/src/observability/trace-span.d.ts +7 -1
- package/esm/src/observability/trace-span.js +3 -1
- package/esm/src/observability/trace.d.ts +2 -0
- package/esm/src/observability/trace.js +4 -2
- package/esm/src/observability/types.d.ts +35 -11
- package/esm/src/observability/types.js +1 -1
- package/esm/src/presets/google/speech-voices.d.ts +1 -0
- package/esm/src/presets/google-limits.d.ts +1 -0
- package/esm/src/presets/google.d.ts +27 -12
- package/esm/src/presets/google.js +34 -25
- package/esm/src/presets/local.d.ts +26 -0
- package/esm/src/presets/local.js +30 -0
- package/esm/src/presets/mod.d.ts +5 -4
- package/esm/src/presets/mod.js +4 -4
- package/esm/src/presets/openrouter.d.ts +14 -1
- package/esm/src/presets/openrouter.js +19 -1
- package/esm/src/providers/embedding-limits.d.ts +7 -0
- package/esm/src/providers/embedding-limits.js +12 -0
- package/esm/src/providers/gemini/embedding-protocol.d.ts +8 -0
- package/esm/src/providers/gemini/embedding-protocol.js +125 -0
- package/esm/src/providers/gemini/interactions-protocol.d.ts +8 -0
- package/esm/src/providers/gemini/interactions-protocol.js +102 -0
- package/esm/src/providers/gemini/live-protocol.d.ts +3 -0
- package/esm/src/providers/gemini/live-protocol.js +191 -0
- package/esm/src/providers/gemini/prices.d.ts +3 -0
- package/esm/src/providers/gemini/prices.js +63 -0
- package/esm/src/providers/gemini/provider.d.ts +7 -0
- package/esm/src/providers/gemini/provider.js +39 -0
- package/esm/src/providers/google/api-error.d.ts +2 -0
- package/esm/src/providers/google/api-error.js +26 -18
- package/esm/src/providers/google/builtins.d.ts +14 -0
- package/esm/src/providers/google/builtins.js +57 -0
- package/esm/src/providers/google/grounding.d.ts +4 -4
- package/esm/src/providers/google/interactions/framing.d.ts +20 -8
- package/esm/src/providers/google/interactions/framing.js +85 -44
- package/esm/src/providers/google/interactions/steps.d.ts +5 -5
- package/esm/src/providers/google/interactions/steps.js +4 -4
- package/esm/src/providers/google/interactions/stream.d.ts +10 -11
- package/esm/src/providers/google/interactions/stream.js +33 -100
- package/esm/src/providers/google/live/framing.d.ts +15 -5
- package/esm/src/providers/google/live/framing.js +25 -25
- package/esm/src/providers/google/live/stream.d.ts +6 -44
- package/esm/src/providers/google/live/stream.js +4 -210
- package/esm/src/providers/google/urls.d.ts +1 -3
- package/esm/src/providers/google/urls.js +1 -3
- package/esm/src/providers/google/usage.js +2 -2
- package/esm/src/providers/live.d.ts +6 -0
- package/esm/src/providers/live.js +6 -0
- package/esm/src/providers/local/embedding-protocol.d.ts +7 -0
- package/esm/src/providers/local/embedding-protocol.js +60 -0
- package/esm/src/providers/local/provider.d.ts +7 -0
- package/esm/src/providers/local/provider.js +28 -0
- package/esm/src/providers/mod.d.ts +28 -7
- package/esm/src/providers/mod.js +19 -3
- package/esm/src/providers/open-ai/protocol.d.ts +3 -0
- package/esm/src/providers/open-ai/protocol.js +189 -0
- package/esm/src/providers/openrouter/embedding-protocol.d.ts +6 -0
- package/esm/src/providers/openrouter/embedding-protocol.js +86 -0
- package/esm/src/providers/openrouter/image.d.ts +0 -9
- package/esm/src/providers/openrouter/image.js +0 -153
- package/esm/src/providers/openrouter/images-protocol.d.ts +3 -0
- package/esm/src/providers/openrouter/images-protocol.js +82 -0
- package/esm/src/providers/openrouter/openai/compat.d.ts +2 -2
- package/esm/src/providers/openrouter/openai/compat.js +6 -6
- package/esm/src/providers/openrouter/openai/image-payload.d.ts +2 -2
- package/esm/src/providers/openrouter/openai/reasoning-state.d.ts +2 -0
- package/esm/src/providers/openrouter/openai/reasoning-state.js +31 -0
- package/esm/src/providers/openrouter/protocol.d.ts +8 -0
- package/esm/src/providers/openrouter/protocol.js +171 -0
- package/esm/src/providers/openrouter/provider.d.ts +10 -0
- package/esm/src/providers/openrouter/provider.js +50 -0
- package/esm/src/providers/shared/carried-tool-files.d.ts +7 -0
- package/esm/src/providers/shared/carried-tool-files.js +43 -0
- package/esm/src/providers/shared/pcm.js +2 -2
- package/esm/src/providers/shared/protocol-events.d.ts +8 -0
- package/esm/src/providers/shared/protocol-events.js +20 -0
- package/esm/src/providers/shared/response-identity.d.ts +2 -2
- package/esm/src/providers/shared/retry.d.ts +18 -0
- package/esm/src/providers/shared/retry.js +89 -0
- package/esm/src/providers/shared/sse.d.ts +0 -4
- package/esm/src/providers/shared/sse.js +50 -36
- package/esm/src/providers/shared/tool-args.d.ts +6 -7
- package/esm/src/providers/shared/tool-args.js +10 -6
- package/esm/src/providers/shared/tool-draft.d.ts +16 -0
- package/esm/src/providers/shared/tool-draft.js +14 -0
- package/esm/src/providers/shared/upstream-tap.d.ts +2 -2
- package/esm/src/providers/shared/upstream-tape.js +1 -1
- package/esm/src/providers/system-one/protocol.d.ts +8 -0
- package/esm/src/providers/system-one/protocol.js +93 -0
- package/esm/src/providers/types.d.ts +48 -16
- package/esm/src/providers/types.js +2 -1
- package/esm/src/providers/typesafe/provider.d.ts +7 -0
- package/esm/src/providers/typesafe/provider.js +24 -0
- package/esm/src/surface/formats.d.ts +19 -1
- package/esm/src/surface/formats.js +68 -29
- package/esm/src/surface/mod.d.ts +4 -2
- package/esm/src/surface/mod.js +4 -2
- package/esm/src/surface/runtime.d.ts +4 -0
- package/esm/src/surface/runtime.js +2 -0
- package/esm/src/surface/tools.d.ts +2 -8
- package/esm/src/surface/tools.js +4 -22
- package/esm/src/surface/types.d.ts +6 -0
- package/package.json +5 -13
- package/esm/src/cli/commands/egress-compile.d.ts +0 -17
- package/esm/src/cli/commands/egress-compile.js +0 -25
- package/esm/src/guardrails/egress-policy.d.ts +0 -27
- package/esm/src/guardrails/egress-policy.js +0 -76
- package/esm/src/guardrails/egress-rules.d.ts +0 -54
- package/esm/src/guardrails/egress-rules.js +0 -49
- package/esm/src/guardrails/lexicon.d.ts +0 -30
- package/esm/src/guardrails/lexicon.js +0 -478
- package/esm/src/kernel/engine/media-probe/audio.d.ts +0 -7
- package/esm/src/kernel/engine/media-probe/audio.js +0 -342
- package/esm/src/kernel/engine/media-probe/bytes.d.ts +0 -6
- package/esm/src/kernel/engine/media-probe/bytes.js +0 -26
- package/esm/src/kernel/engine/media-probe/image.d.ts +0 -5
- package/esm/src/kernel/engine/media-probe/image.js +0 -171
- package/esm/src/kernel/engine/media-probe/iso-bmff.d.ts +0 -19
- package/esm/src/kernel/engine/media-probe/iso-bmff.js +0 -48
- package/esm/src/kernel/engine/media-probe/matroska.d.ts +0 -35
- package/esm/src/kernel/engine/media-probe/matroska.js +0 -226
- package/esm/src/kernel/engine/media-probe/mp4.d.ts +0 -22
- package/esm/src/kernel/engine/media-probe/mp4.js +0 -279
- package/esm/src/kernel/engine/media-probe/opus.d.ts +0 -4
- package/esm/src/kernel/engine/media-probe/opus.js +0 -23
- package/esm/src/kernel/engine/media-probe/pdf.d.ts +0 -5
- package/esm/src/kernel/engine/media-probe/pdf.js +0 -117
- package/esm/src/kernel/engine/media-probe/video.d.ts +0 -15
- package/esm/src/kernel/engine/media-probe/video.js +0 -49
- package/esm/src/presets/typesafe.d.ts +0 -2
- package/esm/src/presets/typesafe.js +0 -2
- package/esm/src/providers/create-provider.d.ts +0 -21
- package/esm/src/providers/create-provider.js +0 -90
- package/esm/src/providers/decision/usage.d.ts +0 -3
- package/esm/src/providers/decision/usage.js +0 -25
- package/esm/src/providers/google/interactions/mod.d.ts +0 -2
- package/esm/src/providers/google/interactions/mod.js +0 -2
- package/esm/src/providers/google/keys.d.ts +0 -20
- package/esm/src/providers/google/keys.js +0 -87
- package/esm/src/providers/google/live/mod.d.ts +0 -7
- package/esm/src/providers/google/live/mod.js +0 -7
- package/esm/src/providers/google/live/openapi-schema.d.ts +0 -1
- package/esm/src/providers/google/live/openapi-schema.js +0 -42
- package/esm/src/providers/google/live/session.d.ts +0 -14
- package/esm/src/providers/google/live/session.js +0 -150
- package/esm/src/providers/local/local.d.ts +0 -12
- package/esm/src/providers/local/local.js +0 -186
- package/esm/src/providers/local/mod.d.ts +0 -8
- package/esm/src/providers/local/mod.js +0 -8
- package/esm/src/providers/openrouter/cache-control.d.ts +0 -5
- package/esm/src/providers/openrouter/cache-control.js +0 -4
- package/esm/src/providers/openrouter/chat.d.ts +0 -64
- package/esm/src/providers/openrouter/chat.js +0 -490
- package/esm/src/providers/openrouter/openai/sdk-messages.d.ts +0 -10
- package/esm/src/providers/openrouter/openai/sdk-messages.js +0 -99
- package/esm/src/providers/openrouter/resolve-api-key.d.ts +0 -3
- package/esm/src/providers/openrouter/resolve-api-key.js +0 -8
- package/esm/src/providers/openrouter/speech.d.ts +0 -18
- package/esm/src/providers/openrouter/speech.js +0 -109
- package/esm/src/providers/probe.d.ts +0 -5
- package/esm/src/providers/probe.js +0 -15
- package/esm/src/providers/shared/builtin-wire.d.ts +0 -4
- package/esm/src/providers/shared/builtin-wire.js +0 -9
- package/esm/src/providers/shared/vault.d.ts +0 -13
- package/esm/src/providers/shared/vault.js +0 -41
|
@@ -1,29 +1,47 @@
|
|
|
1
|
-
import { canaryNote, userDataNote } from '../../../guardrails/canary.js';
|
|
1
|
+
import { canaryNote, contextNote, USER_CLOSE, USER_OPEN, userDataNote, } from '../../../guardrails/canary.js';
|
|
2
|
+
import { addGivenDestinations, addHistoryDestinations, addRequestDestinations, addResultDestinations, turnDestinations, } from '../../../guardrails/destinations.js';
|
|
2
3
|
import { addHistoryUrls, addRequestUrls, addSeenUrls, givenUrlSets, } from '../../../guardrails/egress-urls.js';
|
|
3
|
-
import { describeError, errorKind, TheoremError, throwIfAborted, toErrorEvent,
|
|
4
|
+
import { describeError, errorKind, TheoremError, throwIfAborted, toErrorEvent, withPublicLabels, } from '../../../guardrails/error.js';
|
|
4
5
|
import { projectGuardrailTurnEvent } from '../../../guardrails/events.js';
|
|
5
|
-
import {
|
|
6
|
+
import { labelText } from '../../../guardrails/labels.js';
|
|
6
7
|
import { abortLiveOutboundTurn, createLiveOutboundGateSession, finalizeLiveOutboundTurn, processLiveOutboundBatch, } from '../../../guardrails/live-outbound-gate.js';
|
|
7
|
-
import {
|
|
8
|
+
import { sanitizeTurnRequestWithEvents } from '../../../guardrails/sanitize.js';
|
|
9
|
+
import { recordTaint } from '../../../guardrails/tool-result.js';
|
|
8
10
|
import { resolveObservabilityPolicy } from '../../../observability/resolve-policy.js';
|
|
9
|
-
import {
|
|
10
|
-
import { openGoogleLiveSession } from '../../../providers/google/live/session.js';
|
|
11
|
+
import { liveToolReadBack } from '../../../providers/live.js';
|
|
11
12
|
import { memoryCredentialSource } from '../../auth/credential-source.js';
|
|
13
|
+
import { historyHash } from '../../checkpoint.js';
|
|
14
|
+
import { openRegisteredLiveSession } from '../../provider-live.js';
|
|
15
|
+
import { assertHistoryKept } from '../../provider-runtime.js';
|
|
16
|
+
import { assertTurnContext } from '../../registry/ingress.js';
|
|
12
17
|
import { providerCompleteRequest } from '../../registry/provider-request.js';
|
|
13
18
|
import { resolveTurnInRegistry } from '../../registry/resolve.js';
|
|
19
|
+
import { fillSlots } from '../../registry/slot-fill.js';
|
|
20
|
+
import { DEFAULT_RESUMED_AFTER_MS } from '../../schema.js';
|
|
14
21
|
import { injectedStageEvent, runStage, stageEventFields, } from '../../stages.js';
|
|
15
22
|
import { profileAllowsInject, stageAbortStop } from '../../stop.js';
|
|
16
23
|
import { bindSystem } from '../../system-parts.js';
|
|
17
|
-
import { failureEvent } from '../../tools/events.js';
|
|
18
|
-
import { executeRegisteredTool, lapsedGateFailure, } from '../../tools/execute.js';
|
|
24
|
+
import { failedActivity, failureEvent } from '../../tools/events.js';
|
|
25
|
+
import { executeRegisteredTool, lapsedGateFailure, shownToolArguments, } from '../../tools/execute.js';
|
|
19
26
|
import { answerGatedCall, gateExpired, resolveGateTtlMs, resumeForAnswer, } from '../../tools/gate-answer.js';
|
|
20
27
|
import { formatToolFailureForModel, formatToolResult } from '../../tools/model-text.js';
|
|
28
|
+
import { ownToolsOf } from '../../tools/project.js';
|
|
21
29
|
import { cloneTurnToolSnapshot } from '../../tools/resolve.js';
|
|
22
30
|
import { turnDoneOf } from '../../turn-events.js';
|
|
23
|
-
import { prepareLiveInboundText } from '../live-inbound.js';
|
|
31
|
+
import { prepareLiveContext, prepareLiveInboundText } from '../live-inbound.js';
|
|
24
32
|
import { assertLiveIngress } from '../live-ingress.js';
|
|
25
|
-
import {
|
|
33
|
+
import { sessionAgentCaller } from '../runner/mod.js';
|
|
26
34
|
import { startLiveTrace } from './session-trace.js';
|
|
35
|
+
function pageAnswerForLiveRequest(page, execution) {
|
|
36
|
+
return page ?? (execution ? undefined : { unanswered: true });
|
|
37
|
+
}
|
|
38
|
+
function isUnresolvedOperationError(error) {
|
|
39
|
+
if (!(error instanceof TheoremError) || !error.copy)
|
|
40
|
+
return false;
|
|
41
|
+
return 'key' in error.copy
|
|
42
|
+
? error.copy.key === 'tool.execution_uncertain'
|
|
43
|
+
: error.copy.some((copy) => copy.key === 'tool.execution_uncertain');
|
|
44
|
+
}
|
|
27
45
|
function isReleased(held) {
|
|
28
46
|
return typeof held.state === 'object' && held.state.released === true;
|
|
29
47
|
}
|
|
@@ -35,14 +53,14 @@ function isSettledPhase(tool) {
|
|
|
35
53
|
* event, not a failure. Every close fact rides along for the builder; the raw
|
|
36
54
|
* close text is `errorInternal`, which `forClient` strips.
|
|
37
55
|
*/
|
|
38
|
-
function sessionEndedEvent(closed, goAway,
|
|
56
|
+
function sessionEndedEvent(closed, goAway, labels) {
|
|
39
57
|
const internal = closed.error ? describeError(closed.error) : closed.reason;
|
|
40
58
|
return {
|
|
41
59
|
type: 'session',
|
|
42
60
|
session: {
|
|
43
61
|
kind: 'ended',
|
|
44
62
|
...(goAway.timeLeftMs !== undefined ? { timeLeftMs: goAway.timeLeftMs } : {}),
|
|
45
|
-
message:
|
|
63
|
+
message: labelText('live.session_ended', {}, labels),
|
|
46
64
|
ended: {
|
|
47
65
|
cause: 'go_away',
|
|
48
66
|
code: closed.code,
|
|
@@ -84,7 +102,7 @@ function sessionSnapshotWithinAllow(profile, snapshot) {
|
|
|
84
102
|
}
|
|
85
103
|
}
|
|
86
104
|
if (outside.size > 0) {
|
|
87
|
-
//
|
|
105
|
+
// labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
88
106
|
const detail = `session snapshot declares tools outside tools.allow: ${[...outside].join(', ')}`;
|
|
89
107
|
throw new TheoremError('config', `Profile ${profile.id}: ${detail}`);
|
|
90
108
|
}
|
|
@@ -93,20 +111,39 @@ function sessionSnapshotWithinAllow(profile, snapshot) {
|
|
|
93
111
|
function toTurnRequest(req) {
|
|
94
112
|
return {
|
|
95
113
|
profile: req.profile,
|
|
114
|
+
providerState: req.providerState,
|
|
96
115
|
system: req.system,
|
|
116
|
+
builtInArgs: req.builtInArgs,
|
|
97
117
|
path: req.path,
|
|
98
118
|
sessionPermissions: req.sessionPermissions,
|
|
99
|
-
sessionResumptionHandle: req.sessionResumptionHandle,
|
|
100
119
|
signal: req.signal,
|
|
101
120
|
metadata: req.metadata,
|
|
102
121
|
host: req.host,
|
|
103
122
|
input: {
|
|
104
123
|
text: '',
|
|
105
124
|
history: req.history,
|
|
106
|
-
|
|
125
|
+
slots: req.slots,
|
|
107
126
|
},
|
|
108
127
|
};
|
|
109
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* The prompt the session opens with: the greeting on a new call, the resume prompt when the
|
|
131
|
+
* caller was away long enough to notice. It is the profile's own copy, so no boundary reads it.
|
|
132
|
+
*/
|
|
133
|
+
function openingPrompt(profile, req, slots) {
|
|
134
|
+
const { greeting, resumed } = profile.live;
|
|
135
|
+
if (!req.providerState && !req.history?.length) {
|
|
136
|
+
return greeting ? fillSlots(profile, greeting, slots, 'live.greeting') : undefined;
|
|
137
|
+
}
|
|
138
|
+
if (!resumed || (req.awayMs ?? 0) < (resumed.afterMs ?? DEFAULT_RESUMED_AFTER_MS)) {
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
return fillSlots(profile, resumed.prompt, slots, 'live.resumed.prompt');
|
|
142
|
+
}
|
|
143
|
+
/** Refuses context the profile's `inputs.context` does not take. */
|
|
144
|
+
function assertSessionContext(profile, context) {
|
|
145
|
+
assertTurnContext(profile, { profile: profile.id, input: { context } });
|
|
146
|
+
}
|
|
110
147
|
function applyVoiceOverride(generation, voice) {
|
|
111
148
|
if (!voice || !generation.live) {
|
|
112
149
|
return generation;
|
|
@@ -128,33 +165,42 @@ function applyInitialInput(generation, input) {
|
|
|
128
165
|
async function applyOutbound(gate, events, turnPhase, onWithhold) {
|
|
129
166
|
if (turnPhase === 'abort') {
|
|
130
167
|
abortLiveOutboundTurn(gate);
|
|
131
|
-
// Keep tool calls + interrupted marker; drop buffered speech via abortLiveOutboundTurn.
|
|
132
168
|
return events.filter((ev) => ev.type === 'tool' ||
|
|
133
169
|
ev.type === 'session' ||
|
|
134
170
|
(ev.type === 'done' && ev.interrupted === true));
|
|
135
171
|
}
|
|
136
172
|
const batch = await processLiveOutboundBatch(gate, events);
|
|
137
|
-
const out = [];
|
|
138
173
|
if (batch.action === 'withhold') {
|
|
139
174
|
onWithhold();
|
|
140
|
-
return [
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
175
|
+
return [
|
|
176
|
+
...(batch.events ?? []).filter((event) => !isTurnComplete(event) && event.type !== 'provider_checkpoint'),
|
|
177
|
+
toErrorEvent(batch.error),
|
|
178
|
+
];
|
|
144
179
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
180
|
+
const out = batch.action === 'emit' ? batch.events : [];
|
|
181
|
+
if (turnPhase !== 'complete')
|
|
182
|
+
return out;
|
|
183
|
+
// why: The response is whole only once its verdict is in: `turn_complete` follows what the
|
|
184
|
+
// verdict released, and a withheld response ends on its error.
|
|
185
|
+
const said = out.filter((event) => !isTurnComplete(event));
|
|
186
|
+
const finalized = await finalizeLiveOutboundTurn(gate);
|
|
187
|
+
if (finalized.action === 'withhold') {
|
|
188
|
+
onWithhold();
|
|
189
|
+
return [
|
|
190
|
+
...said.filter((event) => event.type !== 'provider_checkpoint'),
|
|
191
|
+
...(finalized.events ?? []),
|
|
192
|
+
toErrorEvent(finalized.error),
|
|
193
|
+
];
|
|
156
194
|
}
|
|
157
|
-
return
|
|
195
|
+
return [
|
|
196
|
+
...said,
|
|
197
|
+
...(finalized.action === 'emit' ? finalized.events : []),
|
|
198
|
+
...out.filter(isTurnComplete),
|
|
199
|
+
{ type: 'done', stop: { kind: 'completed' } },
|
|
200
|
+
];
|
|
201
|
+
}
|
|
202
|
+
function isTurnComplete(event) {
|
|
203
|
+
return event.type === 'session' && event.session.kind === 'turn_complete';
|
|
158
204
|
}
|
|
159
205
|
/**
|
|
160
206
|
* The output a settled Live call sends upstream, or `undefined` when nothing
|
|
@@ -172,7 +218,7 @@ function liveReadBack(s) {
|
|
|
172
218
|
const output = liveToolOutput(s);
|
|
173
219
|
return output === undefined
|
|
174
220
|
? undefined
|
|
175
|
-
: { text:
|
|
221
|
+
: { text: liveToolReadBack(output), parts: s.modelResult?.parts };
|
|
176
222
|
}
|
|
177
223
|
/**
|
|
178
224
|
* A provider batch as the host receives it: a call's `done` becomes the
|
|
@@ -180,7 +226,7 @@ function liveReadBack(s) {
|
|
|
180
226
|
*/
|
|
181
227
|
function hostEventsOf(events, snapshot) {
|
|
182
228
|
return events.flatMap((ev) => {
|
|
183
|
-
if (ev.type === 'response')
|
|
229
|
+
if (ev.type === 'response' || ev.type === 'reasoning')
|
|
184
230
|
return [];
|
|
185
231
|
if (ev.type !== 'done')
|
|
186
232
|
return [ev];
|
|
@@ -203,20 +249,75 @@ function boundaryDoneEvents(doneBatch, turnPhase, interrupted) {
|
|
|
203
249
|
}
|
|
204
250
|
return [{ type: 'done', stop: { kind: 'completed' } }];
|
|
205
251
|
}
|
|
206
|
-
function
|
|
252
|
+
function recordLiveHistory(events, recordUserText, recordAssistantText) {
|
|
253
|
+
for (const event of events) {
|
|
254
|
+
if (event.type === 'text')
|
|
255
|
+
recordAssistantText(event.text);
|
|
256
|
+
if (event.type === 'evidence' &&
|
|
257
|
+
event.text &&
|
|
258
|
+
(event.evidence.kind === 'input_transcription' ||
|
|
259
|
+
event.evidence.kind === 'output_transcription') &&
|
|
260
|
+
!event.evidence.interim) {
|
|
261
|
+
if (event.evidence.kind === 'input_transcription')
|
|
262
|
+
recordUserText(event.text);
|
|
263
|
+
if (event.evidence.kind === 'output_transcription' &&
|
|
264
|
+
!events.some((item) => item.type === 'text'))
|
|
265
|
+
recordAssistantText(event.text);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
async function sealLiveCheckpoints(events, history, calls, keepsHistory) {
|
|
270
|
+
const sealed = [];
|
|
271
|
+
for (const event of events) {
|
|
272
|
+
if (!keepsHistory && event.type === 'provider_checkpoint')
|
|
273
|
+
continue;
|
|
274
|
+
if (!keepsHistory && event.type === 'done') {
|
|
275
|
+
const { providerState: _dropped, ...standsAlone } = event;
|
|
276
|
+
sealed.push(standsAlone);
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
if ((event.type === 'provider_checkpoint' || event.type === 'done') && event.providerState) {
|
|
280
|
+
const covered = [...history];
|
|
281
|
+
for (const [callId, held] of calls) {
|
|
282
|
+
if (covered.some((message) => message.tool_calls?.some((call) => call.id === callId)))
|
|
283
|
+
continue;
|
|
284
|
+
covered.push({
|
|
285
|
+
role: 'assistant',
|
|
286
|
+
tool_calls: [
|
|
287
|
+
{
|
|
288
|
+
id: callId,
|
|
289
|
+
type: 'function',
|
|
290
|
+
function: { name: held.name, arguments: JSON.stringify(held.arguments) },
|
|
291
|
+
},
|
|
292
|
+
],
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
sealed.push({
|
|
296
|
+
...event,
|
|
297
|
+
...(event.type === 'provider_checkpoint' ? { history: structuredClone(covered) } : {}),
|
|
298
|
+
providerState: {
|
|
299
|
+
...event.providerState,
|
|
300
|
+
coveredHistoryLength: covered.length,
|
|
301
|
+
coveredHistoryHash: await historyHash(covered),
|
|
302
|
+
},
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
else
|
|
306
|
+
sealed.push(event);
|
|
307
|
+
}
|
|
308
|
+
return sealed;
|
|
309
|
+
}
|
|
310
|
+
function* yieldLiveNonDoneEvents(gated, includeMatch) {
|
|
207
311
|
const doneBatch = gated.filter((ev) => ev.type === 'done');
|
|
208
312
|
for (const ev of gated) {
|
|
209
313
|
if (ev.type === 'done')
|
|
210
314
|
continue;
|
|
211
|
-
if (ev.type === 'text' && typeof ev.text === 'string') {
|
|
212
|
-
recordAssistantText(ev.text);
|
|
213
|
-
}
|
|
214
315
|
yield projectGuardrailTurnEvent(ev, includeMatch ?? false);
|
|
215
316
|
}
|
|
216
317
|
return doneBatch;
|
|
217
318
|
}
|
|
218
319
|
function buildLiveSession(args) {
|
|
219
|
-
const { profile, canary, connection, gate, givenUrls, signal, onStage, host: sessionHost, resolveHost, path, snapshot, trace, gateTtlMs, signInGate, } = args;
|
|
320
|
+
const { profile, canary, connection, gate, givenUrls, destinations, signal, onStage, host: sessionHost, resolveHost, path, snapshot, trace, gateTtlMs, signInGate, } = args;
|
|
220
321
|
/** Grows as the user approves `session_consent` tools. */
|
|
221
322
|
let sessionPermissions = args.sessionPermissions;
|
|
222
323
|
/** Where keys typed at sign-in gates go when a call brings no source of its own. */
|
|
@@ -225,12 +326,14 @@ function buildLiveSession(args) {
|
|
|
225
326
|
let closed = false;
|
|
226
327
|
let withholdClose = false;
|
|
227
328
|
const pendingHostEvents = [];
|
|
228
|
-
/** Wakes the host's stream when the session queues an event while
|
|
329
|
+
/** Wakes the host's stream when the session queues an event while the model is silent. */
|
|
229
330
|
let wakeHost;
|
|
230
331
|
const includeMatch = resolveObservabilityPolicy(profile.observability).include
|
|
231
332
|
.guardrailMatchPreview;
|
|
232
333
|
let cycle = 'idle';
|
|
233
334
|
let cycleStep = 0;
|
|
335
|
+
/** What this cycle's tool results read from outside the host; a cycle starts clean, as a turn does. */
|
|
336
|
+
let cycleTaint;
|
|
234
337
|
const history = args.historySeed?.length
|
|
235
338
|
? structuredClone(args.historySeed)
|
|
236
339
|
: [];
|
|
@@ -242,19 +345,19 @@ function buildLiveSession(args) {
|
|
|
242
345
|
return;
|
|
243
346
|
history.push({ role: 'user', content: trimmed });
|
|
244
347
|
addSeenUrls(givenUrls.request, trimmed);
|
|
348
|
+
addGivenDestinations(destinations, trimmed);
|
|
245
349
|
};
|
|
246
350
|
const recordAssistantText = (text) => {
|
|
247
|
-
|
|
248
|
-
if (!trimmed)
|
|
351
|
+
if (!text)
|
|
249
352
|
return;
|
|
250
353
|
const last = history.at(-1);
|
|
251
354
|
if (last?.role === 'assistant' && typeof last.content === 'string' && !last.tool_calls) {
|
|
252
|
-
last.content = `${last.content}${
|
|
355
|
+
last.content = `${last.content}${text}`;
|
|
253
356
|
return;
|
|
254
357
|
}
|
|
255
|
-
history.push({ role: 'assistant', content:
|
|
358
|
+
history.push({ role: 'assistant', content: text });
|
|
256
359
|
};
|
|
257
|
-
const recordToolSettle = (tool, readBack) => {
|
|
360
|
+
const recordToolSettle = (tool, readBack, parts) => {
|
|
258
361
|
history.push({
|
|
259
362
|
role: 'assistant',
|
|
260
363
|
tool_calls: [
|
|
@@ -272,6 +375,7 @@ function buildLiveSession(args) {
|
|
|
272
375
|
tool_call_id: tool.callId,
|
|
273
376
|
name: tool.name,
|
|
274
377
|
content: readBack,
|
|
378
|
+
...(parts?.length ? { parts } : {}),
|
|
275
379
|
});
|
|
276
380
|
addSeenUrls(givenUrls.tools, readBack);
|
|
277
381
|
};
|
|
@@ -281,6 +385,8 @@ function buildLiveSession(args) {
|
|
|
281
385
|
wakeHost = undefined;
|
|
282
386
|
wake?.();
|
|
283
387
|
};
|
|
388
|
+
for (const ev of args.requestEvents)
|
|
389
|
+
enqueuePending(ev);
|
|
284
390
|
const hostEventQueued = () => pendingHostEvents.length > 0
|
|
285
391
|
? Promise.resolve('queued')
|
|
286
392
|
: new Promise((resolve) => {
|
|
@@ -288,31 +394,40 @@ function buildLiveSession(args) {
|
|
|
288
394
|
});
|
|
289
395
|
const assertOpen = () => {
|
|
290
396
|
if (closed) {
|
|
291
|
-
throw new TheoremError('request', 'Live session is closed'); //
|
|
397
|
+
throw new TheoremError('request', 'Live session is closed'); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
292
398
|
}
|
|
293
399
|
};
|
|
294
|
-
const
|
|
400
|
+
const sendInput = (input) => {
|
|
295
401
|
assertOpen();
|
|
296
|
-
connection.
|
|
402
|
+
connection.sendInput(input);
|
|
297
403
|
};
|
|
298
|
-
const answerModel = (callId, held, readBack) => {
|
|
299
|
-
recordToolSettle({ name: held.name, callId, arguments: held.arguments }, readBack);
|
|
300
|
-
|
|
404
|
+
const answerModel = (callId, held, readBack, parts) => {
|
|
405
|
+
recordToolSettle({ name: held.name, callId, arguments: held.arguments }, readBack, parts);
|
|
406
|
+
assertOpen();
|
|
407
|
+
connection.sendToolResponse(callId, held.name, readBack, parts);
|
|
301
408
|
};
|
|
302
|
-
const settleHeld = (callId, held, readBack) => {
|
|
409
|
+
const settleHeld = (callId, held, readBack, parts) => {
|
|
303
410
|
clearTimeout(held.lapse);
|
|
304
411
|
calls.delete(callId);
|
|
305
|
-
answerModel(callId, held, readBack);
|
|
412
|
+
answerModel(callId, held, readBack, parts);
|
|
413
|
+
};
|
|
414
|
+
const settleHeldFailure = (callId, held, failure) => {
|
|
415
|
+
const readBack = formatToolResult(formatToolFailureForModel(failure));
|
|
416
|
+
enqueuePending(failureEvent({
|
|
417
|
+
name: held.name,
|
|
418
|
+
callId,
|
|
419
|
+
operationId: held.operationId,
|
|
420
|
+
activityFailed: failedActivity(held.name, profile.labels),
|
|
421
|
+
}, failure, readBack));
|
|
422
|
+
settleHeld(callId, held, readBack);
|
|
306
423
|
};
|
|
307
424
|
/** A released call nobody answered in time: the model reads that its sign-in expired. */
|
|
308
425
|
const lapseReleased = (callId, held) => {
|
|
309
426
|
if (closed || calls.get(callId) !== held || typeof held.state !== 'object')
|
|
310
427
|
return;
|
|
311
428
|
const { gate } = held.state;
|
|
312
|
-
const failure = lapsedGateFailure(held.name, gate.kind === 'auth' ? gate.authChallenge.service : undefined, profile.
|
|
313
|
-
|
|
314
|
-
enqueuePending(failureEvent({ name: held.name, callId }, failure, readBack));
|
|
315
|
-
settleHeld(callId, held, readBack);
|
|
429
|
+
const failure = lapsedGateFailure(held.name, gate.kind === 'auth' ? gate.authChallenge.service : undefined, profile.labels);
|
|
430
|
+
settleHeldFailure(callId, held, failure);
|
|
316
431
|
};
|
|
317
432
|
/** A closed session answers nothing more. */
|
|
318
433
|
const stopLapses = () => {
|
|
@@ -346,7 +461,12 @@ function buildLiveSession(args) {
|
|
|
346
461
|
continue;
|
|
347
462
|
const tool = ev.tool;
|
|
348
463
|
if (tool.phase === undefined) {
|
|
349
|
-
calls.set(tool.callId, {
|
|
464
|
+
calls.set(tool.callId, {
|
|
465
|
+
name: tool.name,
|
|
466
|
+
arguments: tool.arguments,
|
|
467
|
+
operationId: tool.operationId ?? crypto.randomUUID(),
|
|
468
|
+
state: 'open',
|
|
469
|
+
});
|
|
350
470
|
continue;
|
|
351
471
|
}
|
|
352
472
|
const held = calls.get(tool.callId);
|
|
@@ -355,7 +475,9 @@ function buildLiveSession(args) {
|
|
|
355
475
|
if (tool.phase === 'error' && tool.readBack !== undefined) {
|
|
356
476
|
settleHeld(tool.callId, held, tool.readBack);
|
|
357
477
|
}
|
|
358
|
-
else if (tool.phase === 'cancel' &&
|
|
478
|
+
else if (tool.phase === 'cancel' &&
|
|
479
|
+
held.state !== 'running' &&
|
|
480
|
+
held.state !== 'uncertain') {
|
|
359
481
|
calls.delete(tool.callId);
|
|
360
482
|
}
|
|
361
483
|
}
|
|
@@ -394,14 +516,36 @@ function buildLiveSession(args) {
|
|
|
394
516
|
inject: result.value.inject,
|
|
395
517
|
};
|
|
396
518
|
};
|
|
397
|
-
|
|
519
|
+
/** The text to send, or `undefined` when a match blocks it: the message does not reach the model. */
|
|
520
|
+
const readLiveText = (text) => {
|
|
398
521
|
const start = performance.now();
|
|
399
522
|
const prepared = prepareLiveInboundText(profile, text);
|
|
400
523
|
trace.inboundCheck(performance.now() - start, prepared.guardrail);
|
|
401
524
|
if (prepared.guardrail)
|
|
402
525
|
enqueuePending(prepared.guardrail);
|
|
403
|
-
|
|
404
|
-
|
|
526
|
+
return prepared.text;
|
|
527
|
+
};
|
|
528
|
+
/** Context is background: it joins no history and opens no cycle, and its addresses count as given. */
|
|
529
|
+
const landContext = (context) => {
|
|
530
|
+
assertSessionContext(profile, context);
|
|
531
|
+
const start = performance.now();
|
|
532
|
+
const prepared = prepareLiveContext(profile, context);
|
|
533
|
+
trace.inboundCheck(performance.now() - start, prepared.guardrails[0]);
|
|
534
|
+
for (const guardrail of prepared.guardrails)
|
|
535
|
+
enqueuePending(guardrail);
|
|
536
|
+
for (const text of prepared.texts) {
|
|
537
|
+
addSeenUrls(givenUrls.request, text);
|
|
538
|
+
addGivenDestinations(destinations, text);
|
|
539
|
+
assertOpen();
|
|
540
|
+
connection.sendContext(text);
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
const ingestPreparedLiveText = (text) => {
|
|
544
|
+
const safe = readLiveText(text);
|
|
545
|
+
if (safe === undefined)
|
|
546
|
+
return;
|
|
547
|
+
recordUserText(safe.slice(USER_OPEN.length + 1, -(USER_CLOSE.length + 1)));
|
|
548
|
+
sendInput({ type: 'text', text: safe });
|
|
405
549
|
};
|
|
406
550
|
/**
|
|
407
551
|
* Write each inject whole into the open cycle (no re-entry into pre_turn),
|
|
@@ -419,7 +563,7 @@ function buildLiveSession(args) {
|
|
|
419
563
|
{
|
|
420
564
|
code: 'inject_invalid_messages',
|
|
421
565
|
field: 'inject',
|
|
422
|
-
message: 'live ingress takes plain-text inject messages only; inject refused', //
|
|
566
|
+
message: 'live ingress takes plain-text inject messages only; inject refused', // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
423
567
|
},
|
|
424
568
|
],
|
|
425
569
|
});
|
|
@@ -438,7 +582,7 @@ function buildLiveSession(args) {
|
|
|
438
582
|
/** A stage's `abort` ends the open cycle: a cancelled `done`, then `post_turn`. */
|
|
439
583
|
const cancelCycle = async (abort) => {
|
|
440
584
|
const stop = stageAbortStop(abort);
|
|
441
|
-
// Idle first, so a boundary
|
|
585
|
+
// why: Idle first, so a boundary the provider sends meanwhile does not end the cycle again.
|
|
442
586
|
cycle = 'idle';
|
|
443
587
|
enqueuePending({ type: 'done', stop, interrupted: true });
|
|
444
588
|
await runCycleStage('post_turn', { stop });
|
|
@@ -448,6 +592,8 @@ function buildLiveSession(args) {
|
|
|
448
592
|
return { aborted: false };
|
|
449
593
|
cycle = 'open';
|
|
450
594
|
cycleStep += 1;
|
|
595
|
+
cycleTaint = undefined;
|
|
596
|
+
destinations.remote.clear();
|
|
451
597
|
const pre = await runCycleStage('pre_turn');
|
|
452
598
|
if (pre.abort) {
|
|
453
599
|
await cancelCycle(pre.abort);
|
|
@@ -480,7 +626,11 @@ function buildLiveSession(args) {
|
|
|
480
626
|
cycle = 'idle';
|
|
481
627
|
};
|
|
482
628
|
const withIngress = (fn) => {
|
|
483
|
-
const
|
|
629
|
+
const flush = async () => {
|
|
630
|
+
await fn();
|
|
631
|
+
await connection.flush?.();
|
|
632
|
+
};
|
|
633
|
+
const next = ingressChain.then(flush, flush);
|
|
484
634
|
ingressChain = next.then(() => undefined, () => undefined);
|
|
485
635
|
return next;
|
|
486
636
|
};
|
|
@@ -488,19 +638,26 @@ function buildLiveSession(args) {
|
|
|
488
638
|
* Run a held call through the registry, with stages. A gate holds it for its
|
|
489
639
|
* decision; any other settlement answers the model and lets it go.
|
|
490
640
|
*/
|
|
491
|
-
const
|
|
641
|
+
const runHeldCore = async (callId, held, input, resume, per) => {
|
|
492
642
|
const waiting = held.state;
|
|
493
643
|
const wasReleased = isReleased(held);
|
|
494
644
|
held.state = 'running';
|
|
495
645
|
const host = per.host ?? sessionHost;
|
|
496
646
|
const record = trace.toolRecord(callId);
|
|
647
|
+
let dispatched = false;
|
|
497
648
|
const exec = executeRegisteredTool({
|
|
649
|
+
onDispatch: () => {
|
|
650
|
+
dispatched = true;
|
|
651
|
+
},
|
|
498
652
|
tools: args.tools,
|
|
653
|
+
agents: args.agents,
|
|
654
|
+
execution: args.execution,
|
|
499
655
|
profile,
|
|
500
656
|
name: held.name,
|
|
501
657
|
input,
|
|
502
658
|
callId,
|
|
503
659
|
ctx: {
|
|
660
|
+
operationId: held.operationId,
|
|
504
661
|
sessionPermissions,
|
|
505
662
|
credentials: per.credentials ?? sessionCredentials,
|
|
506
663
|
resolveHost,
|
|
@@ -508,7 +665,10 @@ function buildLiveSession(args) {
|
|
|
508
665
|
signal,
|
|
509
666
|
resume,
|
|
510
667
|
host,
|
|
511
|
-
|
|
668
|
+
// why: A call opens no second line to the page, so a call the page did not answer is not held for it.
|
|
669
|
+
page: pageAnswerForLiveRequest(per.page, args.pageExecution),
|
|
670
|
+
pageExecution: args.pageExecution,
|
|
671
|
+
turn: { step: Math.max(1, cycleStep), taint: cycleTaint, destinations },
|
|
512
672
|
},
|
|
513
673
|
snapshot,
|
|
514
674
|
stages: {
|
|
@@ -520,6 +680,7 @@ function buildLiveSession(args) {
|
|
|
520
680
|
host,
|
|
521
681
|
signal,
|
|
522
682
|
},
|
|
683
|
+
scope: gate.context,
|
|
523
684
|
openSpan: record.open,
|
|
524
685
|
readBack: liveReadBack,
|
|
525
686
|
});
|
|
@@ -535,8 +696,14 @@ function buildLiveSession(args) {
|
|
|
535
696
|
}
|
|
536
697
|
}
|
|
537
698
|
catch (err) {
|
|
538
|
-
//
|
|
539
|
-
|
|
699
|
+
// invariant: A dispatched call with no outcome cannot regain approval authority.
|
|
700
|
+
const unresolved = dispatched || isUnresolvedOperationError(err);
|
|
701
|
+
held.state = unresolved ? 'uncertain' : waiting;
|
|
702
|
+
if (unresolved)
|
|
703
|
+
throw new TheoremError('unavailable', labelText('tool.execution_uncertain', {}, profile.labels), {
|
|
704
|
+
copy: { key: 'tool.execution_uncertain' },
|
|
705
|
+
cause: err,
|
|
706
|
+
});
|
|
540
707
|
throw err;
|
|
541
708
|
}
|
|
542
709
|
finally {
|
|
@@ -549,26 +716,24 @@ function buildLiveSession(args) {
|
|
|
549
716
|
return { gated: s.gated };
|
|
550
717
|
}
|
|
551
718
|
if (s.aborted) {
|
|
552
|
-
// A stage stopped the call. The model still reads an answer, or it
|
|
719
|
+
// why: A stage stopped the call. The model still reads an answer, or it
|
|
553
720
|
// waits for one; then the open cycle ends cancelled, as a turn does.
|
|
554
721
|
const failure = s.callNotStarted
|
|
555
722
|
? {
|
|
556
723
|
code: 'cancelled',
|
|
557
724
|
kind: 'cancelled',
|
|
558
|
-
message:
|
|
725
|
+
message: labelText('session.tool_aborted', { tool: held.name }, profile.labels),
|
|
559
726
|
}
|
|
560
727
|
: s.failure;
|
|
561
728
|
if (s.callNotStarted && failure) {
|
|
562
|
-
|
|
563
|
-
enqueuePending(failureEvent({ name: held.name, callId }, failure, readBack));
|
|
564
|
-
settleHeld(callId, held, readBack);
|
|
729
|
+
settleHeldFailure(callId, held, failure);
|
|
565
730
|
}
|
|
566
731
|
else {
|
|
567
732
|
const output = liveToolOutput(s);
|
|
568
733
|
if (output === undefined)
|
|
569
734
|
calls.delete(callId);
|
|
570
735
|
else
|
|
571
|
-
settleHeld(callId, held, output);
|
|
736
|
+
settleHeld(callId, held, output, s.modelResult?.parts);
|
|
572
737
|
}
|
|
573
738
|
const { aborted } = s;
|
|
574
739
|
await withIngress(async () => {
|
|
@@ -582,6 +747,10 @@ function buildLiveSession(args) {
|
|
|
582
747
|
awaiting: s.awaiting,
|
|
583
748
|
};
|
|
584
749
|
}
|
|
750
|
+
if (s.modelResult?.provenance) {
|
|
751
|
+
cycleTaint = recordTaint(cycleTaint, s.modelResult.provenance, s.modelResult.suspicious);
|
|
752
|
+
addResultDestinations(destinations, s.modelResult, s.modelResult.provenance);
|
|
753
|
+
}
|
|
585
754
|
const { pendingInject } = s;
|
|
586
755
|
if (pendingInject) {
|
|
587
756
|
await withIngress(async () => {
|
|
@@ -595,7 +764,7 @@ function buildLiveSession(args) {
|
|
|
595
764
|
if (output === undefined)
|
|
596
765
|
calls.delete(callId);
|
|
597
766
|
else
|
|
598
|
-
settleHeld(callId, held, output);
|
|
767
|
+
settleHeld(callId, held, output, s.modelResult?.parts);
|
|
599
768
|
return {
|
|
600
769
|
outputRaw: s.outputRaw,
|
|
601
770
|
outputModel: s.modelResult,
|
|
@@ -603,8 +772,13 @@ function buildLiveSession(args) {
|
|
|
603
772
|
awaiting: s.awaiting,
|
|
604
773
|
};
|
|
605
774
|
};
|
|
775
|
+
const runHeld = async (...input) => {
|
|
776
|
+
const result = await runHeldCore(...input);
|
|
777
|
+
await connection.flush?.();
|
|
778
|
+
return result;
|
|
779
|
+
};
|
|
606
780
|
const gateExpiredError = (callId) =>
|
|
607
|
-
//
|
|
781
|
+
// labels-exempt: developer contract / internal diagnostic — the user reads session.gate_expired
|
|
608
782
|
new TheoremError('request', `gate ${callId} expired`, {
|
|
609
783
|
copy: { key: 'session.gate_expired' },
|
|
610
784
|
});
|
|
@@ -614,11 +788,20 @@ function buildLiveSession(args) {
|
|
|
614
788
|
* `gateTtlMs` is settled (a held one as abandoned, a released one as lapsed;
|
|
615
789
|
* the model reads that), then refused.
|
|
616
790
|
*/
|
|
617
|
-
const takeHeld = async (callId) => {
|
|
791
|
+
const takeHeld = async (callId, operationId) => {
|
|
618
792
|
const held = calls.get(callId);
|
|
619
793
|
if (!held || held.state === 'running') {
|
|
620
|
-
throw new TheoremError('request', `call ${callId} is not waiting to run`); //
|
|
794
|
+
throw new TheoremError('request', `call ${callId} is not waiting to run`); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
795
|
+
}
|
|
796
|
+
if (operationId !== undefined && operationId !== held.operationId) {
|
|
797
|
+
throw new TheoremError('request', labelText('session.gate_expired', {}, profile.labels), {
|
|
798
|
+
copy: { key: 'session.gate_expired' },
|
|
799
|
+
});
|
|
621
800
|
}
|
|
801
|
+
if (held.state === 'uncertain')
|
|
802
|
+
throw new TheoremError('unavailable', labelText('tool.execution_uncertain', {}, profile.labels), {
|
|
803
|
+
copy: { key: 'tool.execution_uncertain' },
|
|
804
|
+
});
|
|
622
805
|
if (gateLapsed(held)) {
|
|
623
806
|
if (isReleased(held))
|
|
624
807
|
lapseReleased(callId, held);
|
|
@@ -628,28 +811,58 @@ function buildLiveSession(args) {
|
|
|
628
811
|
}
|
|
629
812
|
return held;
|
|
630
813
|
};
|
|
814
|
+
/** The model's call as the host is shown it: its arguments as the tool gets them. */
|
|
815
|
+
const asToolGetsIt = (event) => {
|
|
816
|
+
if (event.type !== 'tool' || event.tool.phase !== undefined)
|
|
817
|
+
return event;
|
|
818
|
+
const { name, arguments: input } = event.tool;
|
|
819
|
+
const shown = shownToolArguments({
|
|
820
|
+
tools: args.tools,
|
|
821
|
+
profile,
|
|
822
|
+
name,
|
|
823
|
+
input,
|
|
824
|
+
scope: gate.context,
|
|
825
|
+
});
|
|
826
|
+
return { ...event, tool: { ...event.tool, arguments: shown } };
|
|
827
|
+
};
|
|
631
828
|
const deliverBatch = async function* (item) {
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
829
|
+
const identities = new Map();
|
|
830
|
+
const events = item.events.map((event) => {
|
|
831
|
+
if (event.type !== 'tool')
|
|
832
|
+
return event;
|
|
833
|
+
const { tool } = event;
|
|
834
|
+
if (tool.phase === undefined) {
|
|
835
|
+
if (calls.has(tool.callId) || identities.has(tool.callId)) {
|
|
836
|
+
throw new TheoremError('bad_response', labelText('provider.duplicate_call', {}, profile.labels), { cause: { code: 'duplicate_pending_call' } });
|
|
837
|
+
}
|
|
838
|
+
identities.set(tool.callId, crypto.randomUUID());
|
|
839
|
+
}
|
|
840
|
+
const operationId = identities.get(tool.callId) ?? calls.get(tool.callId)?.operationId;
|
|
841
|
+
return { ...event, tool: { ...tool, operationId } };
|
|
842
|
+
});
|
|
843
|
+
holdCalls(events);
|
|
844
|
+
// why: Usage is held per response and emitted once, reported or estimated, by `settle`.
|
|
845
|
+
const hostEvents = hostEventsOf(events.filter((ev) => ev.type !== 'tokens'), snapshot).map(asToolGetsIt);
|
|
635
846
|
const gateStart = performance.now();
|
|
636
847
|
const gated = await applyOutbound(gate, hostEvents, item.turnPhase, () => {
|
|
637
848
|
withholdClose = true;
|
|
638
849
|
});
|
|
639
|
-
// An abort only drops what the gate held; there is no check to time.
|
|
850
|
+
// why: An abort only drops what the gate held; there is no check to time.
|
|
640
851
|
if (item.turnPhase !== 'abort')
|
|
641
852
|
trace.outboundTime(performance.now() - gateStart);
|
|
642
853
|
for (const ev of gated) {
|
|
643
854
|
if (ev.type === 'guardrail')
|
|
644
855
|
trace.outbound(ev);
|
|
645
856
|
}
|
|
646
|
-
|
|
857
|
+
recordLiveHistory(gated, recordUserText, recordAssistantText);
|
|
858
|
+
const sealed = await sealLiveCheckpoints(gated, history, calls, profile.providerContinuation?.history !== 'stateless');
|
|
859
|
+
const doneBatch = yield* yieldLiveNonDoneEvents(sealed, includeMatch);
|
|
647
860
|
const tokens = await trace.settle();
|
|
648
861
|
if (tokens)
|
|
649
862
|
yield tokens;
|
|
650
863
|
const interrupted = doneBatch.some((ev) => ev.type === 'done' && ev.interrupted);
|
|
651
864
|
const completeBoundary = item.turnPhase === 'complete' || item.turnPhase === 'abort' || doneBatch.length > 0;
|
|
652
|
-
// Boundary batches (`interactionStatus: IDLE`, or bare `turnComplete` when the
|
|
865
|
+
// why: Boundary batches (`interactionStatus: IDLE`, or bare `turnComplete` when the
|
|
653
866
|
// provider sends no status) often have no folded `done` — still end the cycle.
|
|
654
867
|
if (completeBoundary && cycle === 'open') {
|
|
655
868
|
const boundaryDone = boundaryDoneEvents(doneBatch, item.turnPhase, interrupted);
|
|
@@ -665,16 +878,16 @@ function buildLiveSession(args) {
|
|
|
665
878
|
}
|
|
666
879
|
};
|
|
667
880
|
const streamToHost = async function* () {
|
|
668
|
-
// Who closes the socket when the loop ends: the host, unless THEOREM stops it.
|
|
881
|
+
// why: Who closes the socket when the loop ends: the host, unless THEOREM stops it.
|
|
669
882
|
let closer = 'host';
|
|
670
883
|
let thrown;
|
|
671
884
|
const provider = connection.batches();
|
|
672
|
-
// The batch being awaited; it stays pending across wakes, so no frame is read twice.
|
|
885
|
+
// why: The batch being awaited; it stays pending across wakes, so no frame is read twice.
|
|
673
886
|
let nextBatch;
|
|
674
887
|
try {
|
|
675
888
|
while (true) {
|
|
676
889
|
nextBatch ??= provider.next();
|
|
677
|
-
// A tool the host ran, or a stage the session fired, reaches the host
|
|
890
|
+
// why: A tool the host ran, or a stage the session fired, reaches the host
|
|
678
891
|
// now: a model waiting on a call's result sends nothing meanwhile.
|
|
679
892
|
const woke = await Promise.race([nextBatch, hostEventQueued()]);
|
|
680
893
|
throwIfAborted(signal);
|
|
@@ -690,7 +903,7 @@ function buildLiveSession(args) {
|
|
|
690
903
|
yield* drainPendingHostEvents(pendingHostEvents);
|
|
691
904
|
if (item.type === 'closed') {
|
|
692
905
|
if (item.goAway)
|
|
693
|
-
yield sessionEndedEvent(item, item.goAway, profile.
|
|
906
|
+
yield sessionEndedEvent(item, item.goAway, profile.labels);
|
|
694
907
|
else if (item.error)
|
|
695
908
|
yield toErrorEvent(item.error);
|
|
696
909
|
break;
|
|
@@ -722,7 +935,7 @@ function buildLiveSession(args) {
|
|
|
722
935
|
closeSocket(1011, 'guardrail withheld', closer);
|
|
723
936
|
else
|
|
724
937
|
closeSocket(1000, 'session-closed', closer);
|
|
725
|
-
// The socket is closed, so a batch still awaited resolves and the provider can finish.
|
|
938
|
+
// why: The socket is closed, so a batch still awaited resolves and the provider can finish.
|
|
726
939
|
await provider.return(undefined);
|
|
727
940
|
await trace.close({ thrown });
|
|
728
941
|
}
|
|
@@ -732,7 +945,7 @@ function buildLiveSession(args) {
|
|
|
732
945
|
canary,
|
|
733
946
|
async *events() {
|
|
734
947
|
for await (const raw of streamToHost()) {
|
|
735
|
-
const event =
|
|
948
|
+
const event = withPublicLabels(raw, profile.labels);
|
|
736
949
|
trace.delivered(event);
|
|
737
950
|
yield event;
|
|
738
951
|
}
|
|
@@ -745,11 +958,7 @@ function buildLiveSession(args) {
|
|
|
745
958
|
const opened = await openCycleIfNeeded();
|
|
746
959
|
if (opened.aborted)
|
|
747
960
|
return;
|
|
748
|
-
|
|
749
|
-
type: 'audio',
|
|
750
|
-
mimeType: audio.mimeType,
|
|
751
|
-
data: audio.data,
|
|
752
|
-
}));
|
|
961
|
+
sendInput({ type: 'audio', mimeType: audio.mimeType, data: audio.data });
|
|
753
962
|
});
|
|
754
963
|
},
|
|
755
964
|
sendVideo(video) {
|
|
@@ -758,11 +967,7 @@ function buildLiveSession(args) {
|
|
|
758
967
|
const opened = await openCycleIfNeeded();
|
|
759
968
|
if (opened.aborted)
|
|
760
969
|
return;
|
|
761
|
-
|
|
762
|
-
type: 'video',
|
|
763
|
-
mimeType: video.mimeType,
|
|
764
|
-
data: video.data,
|
|
765
|
-
}));
|
|
970
|
+
sendInput({ type: 'video', mimeType: video.mimeType, data: video.data });
|
|
766
971
|
});
|
|
767
972
|
},
|
|
768
973
|
sendText(text) {
|
|
@@ -774,35 +979,30 @@ function buildLiveSession(args) {
|
|
|
774
979
|
ingestPreparedLiveText(text);
|
|
775
980
|
});
|
|
776
981
|
},
|
|
777
|
-
sendContext(
|
|
982
|
+
sendContext(context) {
|
|
778
983
|
return withIngress(() => {
|
|
779
|
-
|
|
780
|
-
const start = performance.now();
|
|
781
|
-
const prepared = prepareLiveInboundText(profile, text);
|
|
782
|
-
trace.inboundCheck(performance.now() - start, prepared.guardrail);
|
|
783
|
-
if (prepared.guardrail)
|
|
784
|
-
enqueuePending(prepared.guardrail);
|
|
785
|
-
sendJson(buildGeminiLiveContext(prepared.text));
|
|
984
|
+
landContext(context);
|
|
786
985
|
return Promise.resolve();
|
|
787
986
|
});
|
|
788
987
|
},
|
|
789
|
-
async executeTool({ callId, decision, input, secret, credentials, host, }) {
|
|
988
|
+
async executeTool({ callId, operationId, decision, input, secret, credentials, host, page, }) {
|
|
790
989
|
assertOpen();
|
|
791
|
-
const held = await takeHeld(callId);
|
|
990
|
+
const held = await takeHeld(callId, operationId);
|
|
792
991
|
const gate = typeof held.state === 'object' ? held.state.gate : undefined;
|
|
793
992
|
if (!gate) {
|
|
794
993
|
if (decision !== undefined || input !== undefined || secret !== undefined) {
|
|
795
|
-
throw new TheoremError('request', `call ${callId} is not waiting on a gate; it takes no decision, input or secret`);
|
|
994
|
+
throw new TheoremError('request', `call ${callId} is not waiting on a gate; it takes no decision, input, or secret`);
|
|
796
995
|
}
|
|
797
|
-
return await runHeld(callId, held, held.arguments, undefined, { credentials, host });
|
|
996
|
+
return await runHeld(callId, held, held.arguments, undefined, { credentials, host, page });
|
|
798
997
|
}
|
|
799
998
|
if (decision === undefined) {
|
|
800
999
|
throw new TheoremError('request', `call ${callId} is waiting on a gate; answer it with a decision`);
|
|
801
1000
|
}
|
|
802
1001
|
const answered = answerGatedCall({ callId, decision, input, secret }, {
|
|
803
1002
|
name: held.name,
|
|
804
|
-
arguments: held.arguments,
|
|
1003
|
+
arguments: gate.preparedArguments ?? held.arguments,
|
|
805
1004
|
permission: gate.permission,
|
|
1005
|
+
gateKind: gate.kind,
|
|
806
1006
|
...(gate.kind === 'auth' ? { auth: gate.authChallenge } : {}),
|
|
807
1007
|
}, sessionPermissions ?? []);
|
|
808
1008
|
if (answered.typed) {
|
|
@@ -812,13 +1012,14 @@ function buildLiveSession(args) {
|
|
|
812
1012
|
return await runHeld(callId, held, answered.input, answered.resume, {
|
|
813
1013
|
credentials,
|
|
814
1014
|
host,
|
|
1015
|
+
page,
|
|
815
1016
|
});
|
|
816
1017
|
},
|
|
817
1018
|
answerToolCall({ callId, events }) {
|
|
818
1019
|
assertOpen();
|
|
819
1020
|
const held = calls.get(callId);
|
|
820
1021
|
if (!held || (held.state !== 'open' && !isReleased(held))) {
|
|
821
|
-
throw new TheoremError('request', `call ${callId} is not waiting for an answer`); //
|
|
1022
|
+
throw new TheoremError('request', `call ${callId} is not waiting for an answer`); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
822
1023
|
}
|
|
823
1024
|
if (gateLapsed(held)) {
|
|
824
1025
|
lapseReleased(callId, held);
|
|
@@ -831,11 +1032,16 @@ function buildLiveSession(args) {
|
|
|
831
1032
|
if (ev.tool.phase === undefined || ev.tool.callId !== callId) {
|
|
832
1033
|
throw new TheoremError('request', `the run answering call ${callId} carries a call of its own (${ev.tool.callId})`);
|
|
833
1034
|
}
|
|
1035
|
+
if (ev.tool.operationId !== held.operationId || ev.tool.name !== held.name) {
|
|
1036
|
+
throw new TheoremError('request', labelText('session.gate_expired', {}, profile.labels), {
|
|
1037
|
+
copy: { key: 'session.gate_expired' },
|
|
1038
|
+
});
|
|
1039
|
+
}
|
|
834
1040
|
if (isSettledPhase(ev.tool))
|
|
835
1041
|
settled = ev.tool;
|
|
836
1042
|
}
|
|
837
1043
|
if (!settled) {
|
|
838
|
-
throw new TheoremError('request', `the run answering call ${callId} settled nothing`); //
|
|
1044
|
+
throw new TheoremError('request', `the run answering call ${callId} settled nothing`); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
839
1045
|
}
|
|
840
1046
|
const forward = () => {
|
|
841
1047
|
for (const ev of events) {
|
|
@@ -850,7 +1056,7 @@ function buildLiveSession(args) {
|
|
|
850
1056
|
}
|
|
851
1057
|
const { readBack } = settled;
|
|
852
1058
|
if (readBack === undefined) {
|
|
853
|
-
throw new TheoremError('request', `the run answering call ${callId} carries no readBack`); //
|
|
1059
|
+
throw new TheoremError('request', `the run answering call ${callId} carries no readBack`); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
854
1060
|
}
|
|
855
1061
|
forward();
|
|
856
1062
|
settleHeld(callId, held, readBack);
|
|
@@ -858,19 +1064,28 @@ function buildLiveSession(args) {
|
|
|
858
1064
|
? { outputRaw: settled.output, ...(settled.awaiting ? { awaiting: true } : {}) }
|
|
859
1065
|
: { failure: settled.failure };
|
|
860
1066
|
},
|
|
861
|
-
close(reason = 'session-closed') {
|
|
1067
|
+
async close(reason = 'session-closed') {
|
|
862
1068
|
if (!closed) {
|
|
863
1069
|
closed = true;
|
|
864
1070
|
stopLapses();
|
|
865
1071
|
closeSocket(1000, reason, 'host');
|
|
866
1072
|
}
|
|
867
|
-
// The session record is sealed here; frames the host reads after closing are not in it.
|
|
1073
|
+
// why: The session record is sealed here; frames the host reads after closing are not in it.
|
|
1074
|
+
await connection.flush?.();
|
|
868
1075
|
return trace.close({});
|
|
869
1076
|
},
|
|
870
1077
|
};
|
|
871
|
-
|
|
1078
|
+
const { initialContext, opening } = args;
|
|
1079
|
+
if (args.openInitialCycle || initialContext || opening) {
|
|
872
1080
|
void withIngress(async () => {
|
|
873
|
-
|
|
1081
|
+
if (initialContext)
|
|
1082
|
+
landContext(initialContext);
|
|
1083
|
+
if (!args.openInitialCycle && !opening)
|
|
1084
|
+
return;
|
|
1085
|
+
const opened = await openCycleIfNeeded();
|
|
1086
|
+
if (opening && !opened.aborted) {
|
|
1087
|
+
sendInput({ type: 'text', text: opening });
|
|
1088
|
+
}
|
|
874
1089
|
});
|
|
875
1090
|
}
|
|
876
1091
|
return session;
|
|
@@ -880,7 +1095,7 @@ function buildLiveSession(args) {
|
|
|
880
1095
|
* profile fails to open and is recorded under the standard observability policy.
|
|
881
1096
|
*/
|
|
882
1097
|
export async function runSessionInRegistry(registry, req, options, sinkOverride) {
|
|
883
|
-
const trace = startLiveTrace(req, registry.profiles.find(req.profile)
|
|
1098
|
+
const trace = startLiveTrace(req, registry.profiles.find(req.profile), sinkOverride);
|
|
884
1099
|
try {
|
|
885
1100
|
return await openTracedSession(registry, req, options, trace);
|
|
886
1101
|
}
|
|
@@ -892,10 +1107,14 @@ export async function runSessionInRegistry(registry, req, options, sinkOverride)
|
|
|
892
1107
|
async function openTracedSession(registry, req, options, trace) {
|
|
893
1108
|
const gateTtlMs = resolveGateTtlMs('runSession', options.gateTtlMs);
|
|
894
1109
|
const turnReq = toTurnRequest(req);
|
|
895
|
-
const safe =
|
|
1110
|
+
const { request: safe, events: requestEvents, refusal, } = sanitizeTurnRequestWithEvents(turnReq, registry.profiles.get(turnReq.profile));
|
|
1111
|
+
if (refusal)
|
|
1112
|
+
throw refusal;
|
|
896
1113
|
throwIfAborted(safe.signal);
|
|
897
1114
|
const { profile, generation: gen0 } = resolveTurnInRegistry(registry, safe);
|
|
898
1115
|
assertLiveProfile(profile);
|
|
1116
|
+
if (req.context)
|
|
1117
|
+
assertSessionContext(profile, req.context);
|
|
899
1118
|
if (req.snapshot) {
|
|
900
1119
|
gen0.tools = sessionSnapshotWithinAllow(profile, req.snapshot);
|
|
901
1120
|
}
|
|
@@ -904,8 +1123,9 @@ async function openTracedSession(registry, req, options, trace) {
|
|
|
904
1123
|
const hasInitialInput = Boolean(req.input && req.input.length > 0);
|
|
905
1124
|
generation = applyInitialInput(generation, req.input);
|
|
906
1125
|
const system = bindSystem(generation.resolvedSystem, [
|
|
907
|
-
canaryNote(generation.canary, profile.
|
|
908
|
-
userDataNote(profile.
|
|
1126
|
+
canaryNote(generation.canary, profile.labels),
|
|
1127
|
+
userDataNote(profile.labels),
|
|
1128
|
+
profile.inputs?.context ? contextNote(profile.labels) : '',
|
|
909
1129
|
]);
|
|
910
1130
|
const completeReq = {
|
|
911
1131
|
...providerCompleteRequest(registry.tools, generation, system.text),
|
|
@@ -917,23 +1137,30 @@ async function openTracedSession(registry, req, options, trace) {
|
|
|
917
1137
|
request: completeReq,
|
|
918
1138
|
generation,
|
|
919
1139
|
binding,
|
|
920
|
-
family: binding ? mediaTokenFamily(binding) : undefined,
|
|
921
1140
|
system: system.text,
|
|
922
1141
|
canary: generation.canary,
|
|
923
1142
|
});
|
|
924
1143
|
const givenUrls = givenUrlSets();
|
|
925
1144
|
addRequestUrls(givenUrls, completeReq);
|
|
926
1145
|
addHistoryUrls(givenUrls, req.history ?? []);
|
|
927
|
-
const
|
|
928
|
-
|
|
1146
|
+
const destinations = turnDestinations();
|
|
1147
|
+
addRequestDestinations(destinations, completeReq, givenUrls.own);
|
|
1148
|
+
addHistoryDestinations(destinations, req.history ?? [], givenUrls.own);
|
|
1149
|
+
const gate = await createLiveOutboundGateSession(profile, generation.canary || undefined, system.private, givenUrls, ownToolsOf(registry.tools, profile));
|
|
1150
|
+
assertHistoryKept(profile.providerContinuation, req.providerState, req.history);
|
|
1151
|
+
const definition = registry.providers.require(binding.provider, binding.apiId);
|
|
1152
|
+
const connection = await openRegisteredLiveSession(definition, { ...binding }, completeReq, options, req.providerState, profile.providerContinuation);
|
|
929
1153
|
trace.setup(connection.setup);
|
|
930
1154
|
return buildLiveSession({
|
|
1155
|
+
execution: options.execution,
|
|
1156
|
+
pageExecution: options.pageExecution,
|
|
931
1157
|
tools: registry.tools,
|
|
932
1158
|
profile,
|
|
933
1159
|
canary: generation.canary,
|
|
934
1160
|
connection,
|
|
935
1161
|
gate,
|
|
936
1162
|
givenUrls,
|
|
1163
|
+
destinations,
|
|
937
1164
|
signal: safe.signal,
|
|
938
1165
|
onStage: req.onStage,
|
|
939
1166
|
host: req.host,
|
|
@@ -944,7 +1171,11 @@ async function openTracedSession(registry, req, options, trace) {
|
|
|
944
1171
|
snapshot: gen0.tools,
|
|
945
1172
|
historySeed: req.history,
|
|
946
1173
|
openInitialCycle: hasInitialInput,
|
|
1174
|
+
requestEvents,
|
|
1175
|
+
initialContext: req.context,
|
|
1176
|
+
opening: hasInitialInput ? undefined : openingPrompt(profile, req, safe.input?.slots),
|
|
947
1177
|
trace,
|
|
1178
|
+
agents: sessionAgentCaller(registry, req, options, trace.agentCanaries),
|
|
948
1179
|
gateTtlMs,
|
|
949
1180
|
signInGate: options.signInGate ?? 'hold',
|
|
950
1181
|
});
|