@theoremjs/agents 0.0.0-stage → 0.3.1
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/LICENSE +21 -0
- package/README.md +545 -2
- package/esm/_dnt.polyfills.d.ts +66 -0
- package/esm/_dnt.polyfills.js +51 -0
- package/esm/mod.d.ts +79 -0
- package/esm/mod.js +49 -0
- package/esm/package.json +3 -0
- package/esm/src/cli/bin.d.ts +7 -0
- package/esm/src/cli/bin.js +9 -0
- package/esm/src/cli/commands/bench.d.ts +6 -0
- package/esm/src/cli/commands/bench.js +480 -0
- 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 +37 -0
- package/esm/src/cli/commands/eval.js +190 -0
- package/esm/src/cli/commands/fuzz-canary.d.ts +15 -0
- package/esm/src/cli/commands/fuzz-canary.js +241 -0
- package/esm/src/cli/commands/fuzz-guardrails.d.ts +2 -0
- package/esm/src/cli/commands/fuzz-guardrails.js +5 -0
- package/esm/src/cli/commands/profile.d.ts +2 -0
- package/esm/src/cli/commands/profile.js +80 -0
- package/esm/src/cli/commands/run.d.ts +13 -0
- package/esm/src/cli/commands/run.js +45 -0
- package/esm/src/cli/commands/test.d.ts +26 -0
- package/esm/src/cli/commands/test.js +143 -0
- package/esm/src/cli/event-log.d.ts +15 -0
- package/esm/src/cli/event-log.js +136 -0
- package/esm/src/cli/index.d.ts +10 -0
- package/esm/src/cli/index.js +267 -0
- package/esm/src/cli/matrix/fixtures.d.ts +10 -0
- package/esm/src/cli/matrix/fixtures.js +67 -0
- package/esm/src/cli/matrix/synthesizer.d.ts +18 -0
- package/esm/src/cli/matrix/synthesizer.js +103 -0
- package/esm/src/evals/attachments.d.ts +5 -0
- package/esm/src/evals/attachments.js +55 -0
- package/esm/src/evals/breakdown.d.ts +30 -0
- package/esm/src/evals/breakdown.js +69 -0
- package/esm/src/evals/graders/answer.d.ts +16 -0
- package/esm/src/evals/graders/answer.js +134 -0
- package/esm/src/evals/graders/code.d.ts +40 -0
- package/esm/src/evals/graders/code.js +184 -0
- package/esm/src/evals/graders/judge.d.ts +24 -0
- package/esm/src/evals/graders/judge.js +367 -0
- package/esm/src/evals/graders/latency.d.ts +6 -0
- package/esm/src/evals/graders/latency.js +82 -0
- package/esm/src/evals/graders/live.d.ts +14 -0
- package/esm/src/evals/graders/live.js +42 -0
- package/esm/src/evals/graders/media.d.ts +18 -0
- package/esm/src/evals/graders/media.js +91 -0
- package/esm/src/evals/graders/shared.d.ts +11 -0
- package/esm/src/evals/graders/shared.js +62 -0
- package/esm/src/evals/graders/transcript.d.ts +19 -0
- package/esm/src/evals/graders/transcript.js +202 -0
- package/esm/src/evals/mod.d.ts +34 -0
- package/esm/src/evals/mod.js +22 -0
- package/esm/src/evals/record.d.ts +41 -0
- package/esm/src/evals/record.js +107 -0
- package/esm/src/evals/rubrics/catalog.d.ts +148 -0
- package/esm/src/evals/rubrics/catalog.js +846 -0
- package/esm/src/evals/rubrics/mod.d.ts +24 -0
- package/esm/src/evals/rubrics/mod.js +55 -0
- package/esm/src/evals/rubrics/mustache.d.ts +23 -0
- package/esm/src/evals/rubrics/mustache.js +154 -0
- package/esm/src/evals/rubrics/types.d.ts +54 -0
- package/esm/src/evals/rubrics/types.js +74 -0
- package/esm/src/evals/run.d.ts +75 -0
- package/esm/src/evals/run.js +418 -0
- package/esm/src/evals/suite.d.ts +28 -0
- package/esm/src/evals/suite.js +97 -0
- package/esm/src/evals/summary.d.ts +35 -0
- package/esm/src/evals/summary.js +31 -0
- package/esm/src/evals/trial.d.ts +14 -0
- package/esm/src/evals/trial.js +135 -0
- package/esm/src/evals/types.d.ts +169 -0
- package/esm/src/evals/types.js +113 -0
- package/esm/src/evals/verdict.d.ts +23 -0
- package/esm/src/evals/verdict.js +48 -0
- 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 +22 -0
- package/esm/src/guardrails/canary-gate.js +40 -0
- package/esm/src/guardrails/canary.d.ts +146 -0
- package/esm/src/guardrails/canary.js +974 -0
- package/esm/src/guardrails/compile-egress.d.ts +12 -0
- package/esm/src/guardrails/compile-egress.js +12 -0
- package/esm/src/guardrails/corpus/canary-egress-attacks.d.ts +24 -0
- package/esm/src/guardrails/corpus/canary-egress-attacks.js +305 -0
- package/esm/src/guardrails/corpus/fuzz-inbound.d.ts +5 -0
- package/esm/src/guardrails/corpus/fuzz-inbound.js +199 -0
- package/esm/src/guardrails/corpus/inbound-payloads.d.ts +5 -0
- package/esm/src/guardrails/corpus/inbound-payloads.js +120 -0
- package/esm/src/guardrails/corpus/live-attacks.d.ts +15 -0
- package/esm/src/guardrails/corpus/live-attacks.js +229 -0
- package/esm/src/guardrails/corpus/mod.d.ts +7 -0
- package/esm/src/guardrails/corpus/mod.js +4 -0
- package/esm/src/guardrails/corpus/secrets.d.ts +12 -0
- package/esm/src/guardrails/corpus/secrets.js +16 -0
- package/esm/src/guardrails/corpus/strings.d.ts +23 -0
- package/esm/src/guardrails/corpus/strings.js +29 -0
- package/esm/src/guardrails/corpus/types.d.ts +36 -0
- package/esm/src/guardrails/corpus/types.js +1 -0
- 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 +12 -0
- package/esm/src/guardrails/egress-automata.js +25582 -0
- package/esm/src/guardrails/egress-compiler.d.ts +55 -0
- package/esm/src/guardrails/egress-compiler.js +431 -0
- package/esm/src/guardrails/egress-patterns.d.ts +26 -0
- package/esm/src/guardrails/egress-patterns.js +36 -0
- package/esm/src/guardrails/egress-stream.d.ts +123 -0
- package/esm/src/guardrails/egress-stream.js +774 -0
- package/esm/src/guardrails/egress-urls.d.ts +86 -0
- package/esm/src/guardrails/egress-urls.js +909 -0
- package/esm/src/guardrails/egress.d.ts +46 -0
- package/esm/src/guardrails/egress.js +124 -0
- package/esm/src/guardrails/error.d.ts +31 -0
- package/esm/src/guardrails/error.js +96 -0
- package/esm/src/guardrails/event-schemas.d.ts +100 -0
- package/esm/src/guardrails/event-schemas.js +48 -0
- package/esm/src/guardrails/events.d.ts +13 -0
- package/esm/src/guardrails/events.js +45 -0
- package/esm/src/guardrails/hints.d.ts +14 -0
- package/esm/src/guardrails/hints.js +57 -0
- package/esm/src/guardrails/hits.d.ts +14 -0
- package/esm/src/guardrails/hits.js +30 -0
- 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 +20 -0
- package/esm/src/guardrails/injection-patterns.js +126 -0
- 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 +30 -0
- package/esm/src/guardrails/injection.js +460 -0
- package/esm/src/guardrails/labels.d.ts +40 -0
- package/esm/src/guardrails/labels.js +874 -0
- package/esm/src/guardrails/live-outbound-gate.d.ts +55 -0
- package/esm/src/guardrails/live-outbound-gate.js +298 -0
- package/esm/src/guardrails/mod.d.ts +54 -0
- package/esm/src/guardrails/mod.js +34 -0
- package/esm/src/guardrails/network.d.ts +46 -0
- package/esm/src/guardrails/network.js +330 -0
- package/esm/src/guardrails/normalize.d.ts +20 -0
- package/esm/src/guardrails/normalize.js +165 -0
- package/esm/src/guardrails/policy.d.ts +4 -0
- package/esm/src/guardrails/policy.js +21 -0
- package/esm/src/guardrails/progressive-yield.d.ts +110 -0
- package/esm/src/guardrails/progressive-yield.js +281 -0
- package/esm/src/guardrails/prompt-echo.d.ts +40 -0
- package/esm/src/guardrails/prompt-echo.js +306 -0
- package/esm/src/guardrails/quota.d.ts +21 -0
- package/esm/src/guardrails/quota.js +80 -0
- package/esm/src/guardrails/rules.d.ts +47 -0
- package/esm/src/guardrails/rules.js +47 -0
- package/esm/src/guardrails/sanitize.d.ts +40 -0
- package/esm/src/guardrails/sanitize.js +160 -0
- 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 +22 -0
- package/esm/src/guardrails/sensitive.js +234 -0
- package/esm/src/guardrails/serialize.d.ts +15 -0
- package/esm/src/guardrails/serialize.js +37 -0
- package/esm/src/guardrails/testing.d.ts +11 -0
- package/esm/src/guardrails/testing.js +10 -0
- package/esm/src/guardrails/theorem-error.d.ts +21 -0
- package/esm/src/guardrails/theorem-error.js +54 -0
- package/esm/src/guardrails/thought-guard.d.ts +76 -0
- package/esm/src/guardrails/thought-guard.js +664 -0
- package/esm/src/guardrails/tool-directives.d.ts +38 -0
- package/esm/src/guardrails/tool-directives.js +195 -0
- 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 +92 -0
- package/esm/src/guardrails/tool-result.js +272 -0
- package/esm/src/guardrails/types.d.ts +250 -0
- package/esm/src/guardrails/types.js +58 -0
- package/esm/src/host/client-turn.d.ts +36 -0
- package/esm/src/host/client-turn.js +80 -0
- package/esm/src/host/mint-trace.d.ts +29 -0
- package/esm/src/host/mint-trace.js +60 -0
- package/esm/src/host/mod.d.ts +13 -0
- package/esm/src/host/mod.js +11 -0
- package/esm/src/host/readStreamingJsonStringField.d.ts +2 -0
- package/esm/src/host/readStreamingJsonStringField.js +27 -0
- package/esm/src/host/reply.d.ts +13 -0
- package/esm/src/host/reply.js +41 -0
- package/esm/src/interface/blocks.d.ts +11 -0
- package/esm/src/interface/blocks.js +283 -0
- package/esm/src/interface/composer-actions.d.ts +24 -0
- package/esm/src/interface/composer-actions.js +33 -0
- package/esm/src/interface/draft.d.ts +20 -0
- package/esm/src/interface/draft.js +39 -0
- package/esm/src/interface/from-profile.d.ts +24 -0
- package/esm/src/interface/from-profile.js +179 -0
- package/esm/src/interface/history.d.ts +46 -0
- package/esm/src/interface/history.js +278 -0
- package/esm/src/interface/inputs.d.ts +11 -0
- package/esm/src/interface/inputs.js +67 -0
- package/esm/src/interface/mod.d.ts +33 -0
- package/esm/src/interface/mod.js +22 -0
- package/esm/src/interface/models.d.ts +26 -0
- package/esm/src/interface/models.js +50 -0
- package/esm/src/interface/pending.d.ts +57 -0
- package/esm/src/interface/pending.js +152 -0
- package/esm/src/interface/profile-interface.d.ts +4 -0
- package/esm/src/interface/profile-interface.js +237 -0
- package/esm/src/interface/session.d.ts +71 -0
- package/esm/src/interface/session.js +128 -0
- 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 +32 -0
- package/esm/src/interface/tool-calls.js +127 -0
- package/esm/src/interface/tool-invoke.d.ts +6 -0
- package/esm/src/interface/tool-invoke.js +22 -0
- package/esm/src/interface/tool-media.d.ts +11 -0
- package/esm/src/interface/tool-media.js +113 -0
- package/esm/src/interface/types.d.ts +278 -0
- package/esm/src/interface/types.js +5 -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/credential-source.d.ts +23 -0
- package/esm/src/kernel/auth/credential-source.js +11 -0
- package/esm/src/kernel/auth/crypto.d.ts +56 -0
- package/esm/src/kernel/auth/crypto.js +163 -0
- package/esm/src/kernel/auth/mod.d.ts +5 -0
- package/esm/src/kernel/auth/mod.js +5 -0
- package/esm/src/kernel/auth/oauth.d.ts +18 -0
- package/esm/src/kernel/auth/oauth.js +439 -0
- package/esm/src/kernel/auth/scope-refusal.d.ts +9 -0
- package/esm/src/kernel/auth/scope-refusal.js +8 -0
- package/esm/src/kernel/auth/typed-secret.d.ts +13 -0
- package/esm/src/kernel/auth/typed-secret.js +23 -0
- package/esm/src/kernel/auth/types.d.ts +152 -0
- package/esm/src/kernel/auth/types.js +1 -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 +72 -0
- package/esm/src/kernel/default-scope.js +121 -0
- 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 +71 -0
- package/esm/src/kernel/engine/compaction.js +203 -0
- package/esm/src/kernel/engine/decision.d.ts +43 -0
- package/esm/src/kernel/engine/decision.js +439 -0
- package/esm/src/kernel/engine/embedding.d.ts +8 -0
- package/esm/src/kernel/engine/embedding.js +118 -0
- package/esm/src/kernel/engine/hash.d.ts +6 -0
- package/esm/src/kernel/engine/hash.js +22 -0
- package/esm/src/kernel/engine/live-inbound.d.ts +19 -0
- package/esm/src/kernel/engine/live-inbound.js +44 -0
- package/esm/src/kernel/engine/live-ingress.d.ts +15 -0
- package/esm/src/kernel/engine/live-ingress.js +42 -0
- package/esm/src/kernel/engine/record.d.ts +3 -0
- package/esm/src/kernel/engine/record.js +11 -0
- package/esm/src/kernel/engine/repair.d.ts +7 -0
- package/esm/src/kernel/engine/repair.js +36 -0
- package/esm/src/kernel/engine/runner/gates.d.ts +5 -0
- package/esm/src/kernel/engine/runner/gates.js +508 -0
- package/esm/src/kernel/engine/runner/mod.d.ts +29 -0
- package/esm/src/kernel/engine/runner/mod.js +625 -0
- 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 +35 -0
- package/esm/src/kernel/engine/runner/schema-validation.js +179 -0
- package/esm/src/kernel/engine/runner/stages.d.ts +28 -0
- package/esm/src/kernel/engine/runner/stages.js +41 -0
- package/esm/src/kernel/engine/runner/state.d.ts +97 -0
- package/esm/src/kernel/engine/runner/state.js +50 -0
- 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 +14 -0
- package/esm/src/kernel/engine/runner/steps.js +519 -0
- package/esm/src/kernel/engine/runner/stream.d.ts +71 -0
- package/esm/src/kernel/engine/runner/stream.js +376 -0
- package/esm/src/kernel/engine/runner/usage.d.ts +45 -0
- package/esm/src/kernel/engine/runner/usage.js +148 -0
- package/esm/src/kernel/engine/session/mod.d.ts +33 -0
- package/esm/src/kernel/engine/session/mod.js +1182 -0
- package/esm/src/kernel/engine/session/session-trace.d.ts +115 -0
- package/esm/src/kernel/engine/session/session-trace.js +500 -0
- package/esm/src/kernel/engine/token-estimate.d.ts +23 -0
- package/esm/src/kernel/engine/token-estimate.js +38 -0
- package/esm/src/kernel/engine/tool-trace.d.ts +58 -0
- package/esm/src/kernel/engine/tool-trace.js +132 -0
- package/esm/src/kernel/engine/tree.d.ts +2 -0
- package/esm/src/kernel/engine/tree.js +17 -0
- package/esm/src/kernel/engine/turn-trace.d.ts +119 -0
- package/esm/src/kernel/engine/turn-trace.js +855 -0
- package/esm/src/kernel/engine/usage.d.ts +36 -0
- package/esm/src/kernel/engine/usage.js +151 -0
- package/esm/src/kernel/interaction-parts.d.ts +13 -0
- package/esm/src/kernel/interaction-parts.js +40 -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 +74 -0
- package/esm/src/kernel/mod.js +45 -0
- package/esm/src/kernel/profile-graph.d.ts +145 -0
- package/esm/src/kernel/profile-graph.js +158 -0
- package/esm/src/kernel/profile-presence.d.ts +18 -0
- package/esm/src/kernel/profile-presence.js +158 -0
- package/esm/src/kernel/profile-scope.d.ts +40 -0
- package/esm/src/kernel/profile-scope.js +274 -0
- 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 +46 -0
- package/esm/src/kernel/registry/attachments.js +220 -0
- package/esm/src/kernel/registry/catalog.d.ts +25 -0
- package/esm/src/kernel/registry/catalog.js +85 -0
- 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 +12 -0
- package/esm/src/kernel/registry/ingress.js +179 -0
- package/esm/src/kernel/registry/kernel-registry.d.ts +15 -0
- package/esm/src/kernel/registry/kernel-registry.js +15 -0
- package/esm/src/kernel/registry/profile-outputs.d.ts +3 -0
- package/esm/src/kernel/registry/profile-outputs.js +10 -0
- package/esm/src/kernel/registry/profiles.d.ts +116 -0
- package/esm/src/kernel/registry/profiles.js +773 -0
- package/esm/src/kernel/registry/provider-request.d.ts +6 -0
- package/esm/src/kernel/registry/provider-request.js +34 -0
- package/esm/src/kernel/registry/resolve.d.ts +17 -0
- package/esm/src/kernel/registry/resolve.js +238 -0
- package/esm/src/kernel/registry/schemas.d.ts +12 -0
- package/esm/src/kernel/registry/schemas.js +27 -0
- 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/sole-model.d.ts +2 -0
- package/esm/src/kernel/registry/sole-model.js +4 -0
- package/esm/src/kernel/registry/system-prompt.d.ts +8 -0
- package/esm/src/kernel/registry/system-prompt.js +32 -0
- package/esm/src/kernel/registry/system-role.d.ts +3 -0
- package/esm/src/kernel/registry/system-role.js +9 -0
- package/esm/src/kernel/registry/vault.d.ts +14 -0
- package/esm/src/kernel/registry/vault.js +1 -0
- package/esm/src/kernel/schema.d.ts +226 -0
- package/esm/src/kernel/schema.js +895 -0
- package/esm/src/kernel/scope.d.ts +29 -0
- package/esm/src/kernel/scope.js +45 -0
- package/esm/src/kernel/stages.d.ts +176 -0
- package/esm/src/kernel/stages.js +431 -0
- package/esm/src/kernel/stop.d.ts +116 -0
- package/esm/src/kernel/stop.js +137 -0
- package/esm/src/kernel/system-parts.d.ts +26 -0
- package/esm/src/kernel/system-parts.js +98 -0
- package/esm/src/kernel/tools/activity-label.d.ts +22 -0
- package/esm/src/kernel/tools/activity-label.js +435 -0
- 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 +66 -0
- package/esm/src/kernel/tools/events.js +184 -0
- package/esm/src/kernel/tools/execute.d.ts +100 -0
- package/esm/src/kernel/tools/execute.js +1173 -0
- package/esm/src/kernel/tools/gate-answer.d.ts +60 -0
- package/esm/src/kernel/tools/gate-answer.js +65 -0
- 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 +17 -0
- package/esm/src/kernel/tools/harness.js +43 -0
- 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 +32 -0
- package/esm/src/kernel/tools/invoke.js +282 -0
- package/esm/src/kernel/tools/mcp-sessions.d.ts +23 -0
- package/esm/src/kernel/tools/mcp-sessions.js +69 -0
- package/esm/src/kernel/tools/mod.d.ts +10 -0
- package/esm/src/kernel/tools/mod.js +7 -0
- package/esm/src/kernel/tools/model-text.d.ts +16 -0
- package/esm/src/kernel/tools/model-text.js +31 -0
- 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 +15 -0
- package/esm/src/kernel/tools/permission.js +38 -0
- package/esm/src/kernel/tools/project.d.ts +11 -0
- package/esm/src/kernel/tools/project.js +55 -0
- package/esm/src/kernel/tools/registry.d.ts +27 -0
- package/esm/src/kernel/tools/registry.js +143 -0
- package/esm/src/kernel/tools/remote.d.ts +144 -0
- package/esm/src/kernel/tools/remote.js +1125 -0
- package/esm/src/kernel/tools/resolve.d.ts +31 -0
- package/esm/src/kernel/tools/resolve.js +267 -0
- 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 +10 -0
- package/esm/src/kernel/tools/schema.js +95 -0
- package/esm/src/kernel/tools/signed-in-fetch.d.ts +19 -0
- package/esm/src/kernel/tools/signed-in-fetch.js +45 -0
- package/esm/src/kernel/tools/stage-run.d.ts +116 -0
- package/esm/src/kernel/tools/stage-run.js +198 -0
- package/esm/src/kernel/tools/types.d.ts +497 -0
- package/esm/src/kernel/tools/types.js +1 -0
- 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 +776 -0
- package/esm/src/kernel/turn-events.js +543 -0
- package/esm/src/kernel/types.d.ts +1025 -0
- package/esm/src/kernel/types.js +1 -0
- package/esm/src/kernel/util/base64.d.ts +4 -0
- package/esm/src/kernel/util/base64.js +15 -0
- package/esm/src/kernel/util/exact-type.d.ts +31 -0
- package/esm/src/kernel/util/exact-type.js +1 -0
- package/esm/src/kernel/util/find-last.d.ts +3 -0
- package/esm/src/kernel/util/find-last.js +9 -0
- package/esm/src/kernel/util/mime.d.ts +2 -0
- package/esm/src/kernel/util/mime.js +4 -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 +2 -0
- package/esm/src/kernel/util/record.js +4 -0
- package/esm/src/observability/destinations.d.ts +14 -0
- package/esm/src/observability/destinations.js +43 -0
- package/esm/src/observability/jsonl.d.ts +18 -0
- package/esm/src/observability/jsonl.js +110 -0
- package/esm/src/observability/mod.d.ts +22 -0
- package/esm/src/observability/mod.js +16 -0
- package/esm/src/observability/openinference.d.ts +11 -0
- package/esm/src/observability/openinference.js +205 -0
- package/esm/src/observability/otlp.d.ts +71 -0
- package/esm/src/observability/otlp.js +98 -0
- package/esm/src/observability/phoenix.d.ts +30 -0
- package/esm/src/observability/phoenix.js +71 -0
- package/esm/src/observability/policy.d.ts +17 -0
- package/esm/src/observability/policy.js +73 -0
- package/esm/src/observability/resolve-policy.d.ts +8 -0
- package/esm/src/observability/resolve-policy.js +64 -0
- package/esm/src/observability/spans.d.ts +22 -0
- package/esm/src/observability/spans.js +72 -0
- package/esm/src/observability/trace-catalog.d.ts +128 -0
- package/esm/src/observability/trace-catalog.js +906 -0
- package/esm/src/observability/trace-record.d.ts +23 -0
- package/esm/src/observability/trace-record.js +228 -0
- package/esm/src/observability/trace-schema.d.ts +57 -0
- package/esm/src/observability/trace-schema.js +59 -0
- package/esm/src/observability/trace-sink.d.ts +14 -0
- package/esm/src/observability/trace-sink.js +3 -0
- package/esm/src/observability/trace-span.d.ts +98 -0
- package/esm/src/observability/trace-span.js +201 -0
- package/esm/src/observability/trace.d.ts +13 -0
- package/esm/src/observability/trace.js +37 -0
- package/esm/src/observability/types.d.ts +109 -0
- package/esm/src/observability/types.js +3 -0
- package/esm/src/presets/google/speech-voices.d.ts +9 -0
- package/esm/src/presets/google/speech-voices.js +38 -0
- package/esm/src/presets/google-limits.d.ts +13 -0
- package/esm/src/presets/google-limits.js +18 -0
- package/esm/src/presets/google.d.ts +119 -0
- package/esm/src/presets/google.js +197 -0
- package/esm/src/presets/local.d.ts +26 -0
- package/esm/src/presets/local.js +30 -0
- package/esm/src/presets/mod.d.ts +11 -0
- package/esm/src/presets/mod.js +9 -0
- package/esm/src/presets/openrouter.d.ts +26 -0
- package/esm/src/presets/openrouter.js +31 -0
- 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 +105 -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 +8 -0
- package/esm/src/providers/google/api-error.js +123 -0
- 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 +5 -0
- package/esm/src/providers/google/grounding.js +226 -0
- package/esm/src/providers/google/interactions/framing.d.ts +27 -0
- package/esm/src/providers/google/interactions/framing.js +304 -0
- package/esm/src/providers/google/interactions/steps.d.ts +12 -0
- package/esm/src/providers/google/interactions/steps.js +200 -0
- package/esm/src/providers/google/interactions/stream.d.ts +23 -0
- package/esm/src/providers/google/interactions/stream.js +230 -0
- package/esm/src/providers/google/live/framing.d.ts +61 -0
- package/esm/src/providers/google/live/framing.js +597 -0
- package/esm/src/providers/google/live/stream.d.ts +13 -0
- package/esm/src/providers/google/live/stream.js +57 -0
- package/esm/src/providers/google/thinking.d.ts +3 -0
- package/esm/src/providers/google/thinking.js +8 -0
- package/esm/src/providers/google/urls.d.ts +4 -0
- package/esm/src/providers/google/urls.js +4 -0
- package/esm/src/providers/google/usage.d.ts +7 -0
- package/esm/src/providers/google/usage.js +49 -0
- 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 +32 -0
- package/esm/src/providers/mod.js +23 -0
- 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 +15 -0
- package/esm/src/providers/openrouter/image.js +34 -0
- 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 +19 -0
- package/esm/src/providers/openrouter/openai/compat.js +162 -0
- package/esm/src/providers/openrouter/openai/image-payload.d.ts +9 -0
- package/esm/src/providers/openrouter/openai/image-payload.js +115 -0
- 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/openai/usage.d.ts +8 -0
- package/esm/src/providers/openrouter/openai/usage.js +56 -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.d.ts +14 -0
- package/esm/src/providers/shared/pcm.js +78 -0
- 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 +11 -0
- package/esm/src/providers/shared/response-identity.js +12 -0
- package/esm/src/providers/shared/retry.d.ts +17 -0
- package/esm/src/providers/shared/retry.js +90 -0
- package/esm/src/providers/shared/sse.d.ts +6 -0
- package/esm/src/providers/shared/sse.js +93 -0
- package/esm/src/providers/shared/structured-output.d.ts +4 -0
- package/esm/src/providers/shared/structured-output.js +11 -0
- package/esm/src/providers/shared/tool-args.d.ts +24 -0
- package/esm/src/providers/shared/tool-args.js +88 -0
- 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 +8 -0
- package/esm/src/providers/shared/upstream-tap.js +85 -0
- package/esm/src/providers/shared/upstream-tape.d.ts +6 -0
- package/esm/src/providers/shared/upstream-tape.js +88 -0
- 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 +51 -0
- package/esm/src/providers/types.js +2 -0
- 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 +46 -0
- package/esm/src/surface/formats.js +178 -0
- package/esm/src/surface/mod.d.ts +16 -0
- package/esm/src/surface/mod.js +12 -0
- package/esm/src/surface/runtime.d.ts +44 -0
- package/esm/src/surface/runtime.js +441 -0
- package/esm/src/surface/tools.d.ts +9 -0
- package/esm/src/surface/tools.js +62 -0
- package/esm/src/surface/types.d.ts +110 -0
- package/esm/src/surface/types.js +4 -0
- package/package.json +100 -4
|
@@ -0,0 +1,597 @@
|
|
|
1
|
+
import { TheoremError, toErrorEvent } from '../../../guardrails/error.js';
|
|
2
|
+
import { asRecord } from '../../../kernel/engine/record.js';
|
|
3
|
+
import { reportedTokens, usageCount } from '../../../kernel/engine/usage.js';
|
|
4
|
+
import { historyMessageParts, isMediaRefPart } from '../../../kernel/interaction-parts.js';
|
|
5
|
+
import { mediaKindForMime } from '../../../kernel/registry/catalog.js';
|
|
6
|
+
import { toolEvent } from '../../../kernel/tools/events.js';
|
|
7
|
+
import { isRecord } from '../../../kernel/util/record.js';
|
|
8
|
+
import { pcmMediaAsWav } from '../../shared/pcm.js';
|
|
9
|
+
import { historyToolArguments, historyToolIdentity, toolCallEvents, } from '../../shared/tool-args.js';
|
|
10
|
+
import { liveBuiltinTool } from '../builtins.js';
|
|
11
|
+
import { groundingFromLiveMetadata } from '../grounding.js';
|
|
12
|
+
import { assertGoogleThinkingLevel } from '../thinking.js';
|
|
13
|
+
import { GEMINI_LIVE_WS_URL } from '../urls.js';
|
|
14
|
+
import { byModality, modalityCounts } from '../usage.js';
|
|
15
|
+
export function buildGeminiLiveWebSocketUrl(apiKey) {
|
|
16
|
+
return `${GEMINI_LIVE_WS_URL}?key=${encodeURIComponent(apiKey)}`;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Non-blocking: the host runs each call via `LiveSession.executeTool` while the
|
|
20
|
+
* model keeps speaking, and a cancel reaches it as a `tool` event with `phase: 'cancel'`.
|
|
21
|
+
*/
|
|
22
|
+
const LIVE_FUNCTION_BEHAVIOR = 'NON_BLOCKING';
|
|
23
|
+
/** `parametersJsonSchema` takes the JSON Schema as it is; `parameters` takes only Google's OpenAPI subset. */
|
|
24
|
+
export function wireFunctionDeclaration(decl) {
|
|
25
|
+
return {
|
|
26
|
+
name: decl.name,
|
|
27
|
+
description: decl.description,
|
|
28
|
+
behavior: LIVE_FUNCTION_BEHAVIOR,
|
|
29
|
+
parametersJsonSchema: decl.parameters ?? { type: 'object', properties: {} },
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function wireLiveTools(req) {
|
|
33
|
+
const tools = [];
|
|
34
|
+
for (const builtin of req.builtins) {
|
|
35
|
+
tools.push(liveBuiltinTool(builtin));
|
|
36
|
+
}
|
|
37
|
+
const functionDeclarations = (req.wireTools ?? []).map(wireFunctionDeclaration);
|
|
38
|
+
if (functionDeclarations.length > 0) {
|
|
39
|
+
tools.push({ functionDeclarations });
|
|
40
|
+
}
|
|
41
|
+
return tools;
|
|
42
|
+
}
|
|
43
|
+
function buildLiveGenerationConfig(req) {
|
|
44
|
+
const generationConfig = {
|
|
45
|
+
responseModalities: ['AUDIO'],
|
|
46
|
+
temperature: req.temperature,
|
|
47
|
+
maxOutputTokens: req.maxOutputTokens,
|
|
48
|
+
};
|
|
49
|
+
if (req.live?.voice) {
|
|
50
|
+
generationConfig.speechConfig = {
|
|
51
|
+
voiceConfig: {
|
|
52
|
+
prebuiltVoiceConfig: {
|
|
53
|
+
voiceName: req.live.voice,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
assertGoogleThinkingLevel(req.thinking);
|
|
59
|
+
const thinkingConfig = {
|
|
60
|
+
...(req.thinking ? { thinkingLevel: req.thinking } : {}),
|
|
61
|
+
...(req.summaries ? { includeThoughts: req.summaries === 'auto' } : {}),
|
|
62
|
+
};
|
|
63
|
+
if (Object.keys(thinkingConfig).length > 0) {
|
|
64
|
+
generationConfig.thinkingConfig = thinkingConfig;
|
|
65
|
+
}
|
|
66
|
+
return generationConfig;
|
|
67
|
+
}
|
|
68
|
+
// why: Unset numbers are left to Gemini's defaults.
|
|
69
|
+
function buildContextWindowCompression(compression) {
|
|
70
|
+
const { triggerTokens } = compression;
|
|
71
|
+
const { targetTokens } = compression.slidingWindow;
|
|
72
|
+
return {
|
|
73
|
+
...(triggerTokens !== undefined ? { triggerTokens } : {}),
|
|
74
|
+
slidingWindow: targetTokens !== undefined ? { targetTokens } : {},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function buildLiveRealtimeInputConfig(vad) {
|
|
78
|
+
const automaticActivityDetection = {};
|
|
79
|
+
if (vad.startSensitivity !== undefined) {
|
|
80
|
+
automaticActivityDetection.startOfSpeechSensitivity = vad.startSensitivity;
|
|
81
|
+
}
|
|
82
|
+
if (vad.endSensitivity !== undefined) {
|
|
83
|
+
automaticActivityDetection.endOfSpeechSensitivity = vad.endSensitivity;
|
|
84
|
+
}
|
|
85
|
+
if (vad.prefixPaddingMs !== undefined) {
|
|
86
|
+
automaticActivityDetection.prefixPaddingMs = vad.prefixPaddingMs;
|
|
87
|
+
}
|
|
88
|
+
if (vad.silenceDurationMs !== undefined) {
|
|
89
|
+
automaticActivityDetection.silenceDurationMs = vad.silenceDurationMs;
|
|
90
|
+
}
|
|
91
|
+
const config = {};
|
|
92
|
+
if (vad.activityHandling !== undefined) {
|
|
93
|
+
config.activityHandling = vad.activityHandling;
|
|
94
|
+
}
|
|
95
|
+
if (Object.keys(automaticActivityDetection).length > 0) {
|
|
96
|
+
config.automaticActivityDetection = automaticActivityDetection;
|
|
97
|
+
}
|
|
98
|
+
return Object.keys(config).length > 0 ? config : undefined;
|
|
99
|
+
}
|
|
100
|
+
function buildLiveSessionResumption(req) {
|
|
101
|
+
if (req.sessionResumptionHandle) {
|
|
102
|
+
return { handle: req.sessionResumptionHandle };
|
|
103
|
+
}
|
|
104
|
+
if (req.live?.sessionResumption) {
|
|
105
|
+
return {};
|
|
106
|
+
}
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
function liveModelName(apiId) {
|
|
110
|
+
return apiId.startsWith('models/') ? apiId : `models/${apiId}`;
|
|
111
|
+
}
|
|
112
|
+
function applyLiveOptionalFeatures(live, setup) {
|
|
113
|
+
if (live?.transcription?.input) {
|
|
114
|
+
setup.inputAudioTranscription = {};
|
|
115
|
+
}
|
|
116
|
+
if (live?.transcription?.output) {
|
|
117
|
+
setup.outputAudioTranscription = {};
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
export function buildGeminiLiveSetupMessage(req) {
|
|
121
|
+
const live = req.live;
|
|
122
|
+
const realtimeInputConfig = live?.vad ? buildLiveRealtimeInputConfig(live.vad) : undefined;
|
|
123
|
+
const tools = wireLiveTools(req);
|
|
124
|
+
const sessionResumption = buildLiveSessionResumption(req);
|
|
125
|
+
// why: `initialHistoryInClientContent` makes Gemini wait for clientContent before
|
|
126
|
+
// realtime generation, so an empty session (e.g. Th30) would hang forever.
|
|
127
|
+
const seedInitialHistory = Boolean(req.history && req.history.length > 0);
|
|
128
|
+
const setup = {
|
|
129
|
+
model: liveModelName(req.apiId),
|
|
130
|
+
generationConfig: buildLiveGenerationConfig(req),
|
|
131
|
+
systemInstruction: {
|
|
132
|
+
parts: [{ text: req.system }],
|
|
133
|
+
},
|
|
134
|
+
...(tools.length > 0 ? { tools } : {}),
|
|
135
|
+
...(sessionResumption ? { sessionResumption } : {}),
|
|
136
|
+
...(live?.contextCompression
|
|
137
|
+
? { contextWindowCompression: buildContextWindowCompression(live.contextCompression) }
|
|
138
|
+
: {}),
|
|
139
|
+
...(seedInitialHistory ? { historyConfig: { initialHistoryInClientContent: true } } : {}),
|
|
140
|
+
...(realtimeInputConfig ? { realtimeInputConfig } : {}),
|
|
141
|
+
};
|
|
142
|
+
applyLiveOptionalFeatures(live, setup);
|
|
143
|
+
return { setup };
|
|
144
|
+
}
|
|
145
|
+
/** Live carries inline bytes only — provider file references are rejected until support is verified. */
|
|
146
|
+
function inlineMediaPart(part) {
|
|
147
|
+
if (isMediaRefPart(part)) {
|
|
148
|
+
throw new TheoremError('unsupported', 'media references are not supported on geminiLive');
|
|
149
|
+
}
|
|
150
|
+
return part;
|
|
151
|
+
}
|
|
152
|
+
function inlineData(part) {
|
|
153
|
+
const inline = inlineMediaPart(part);
|
|
154
|
+
return { mimeType: inline.mimeType, data: inline.data };
|
|
155
|
+
}
|
|
156
|
+
function contentPart(part) {
|
|
157
|
+
return part.type === 'text' ? { text: part.text } : { inlineData: inlineData(part) };
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* A `tool` message as one `functionResponse` part in a `user` turn (probed 23/09/2026).
|
|
161
|
+
* Text parts are the `result`; media rides nested in `functionResponse.parts`.
|
|
162
|
+
*/
|
|
163
|
+
function functionResponseTurn(msg) {
|
|
164
|
+
const parts = historyMessageParts(msg);
|
|
165
|
+
const result = parts
|
|
166
|
+
.map((part) => (part.type === 'text' ? part.text : ''))
|
|
167
|
+
.filter(Boolean)
|
|
168
|
+
.join('\n');
|
|
169
|
+
const media = parts.filter((part) => part.type !== 'text').map(contentPart);
|
|
170
|
+
return {
|
|
171
|
+
role: 'user',
|
|
172
|
+
parts: [
|
|
173
|
+
{
|
|
174
|
+
functionResponse: {
|
|
175
|
+
...historyToolIdentity({ id: msg.tool_call_id, name: msg.name }),
|
|
176
|
+
response: { result },
|
|
177
|
+
...(media.length > 0 ? { parts: media } : {}),
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
],
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
function historyTurnToGoogleTurn(msg) {
|
|
184
|
+
if (msg.role === 'tool') {
|
|
185
|
+
return functionResponseTurn(msg);
|
|
186
|
+
}
|
|
187
|
+
const role = msg.role === 'assistant' ? 'model' : 'user';
|
|
188
|
+
const parts = historyMessageParts(msg).map(contentPart);
|
|
189
|
+
for (const call of msg.role === 'assistant' ? (msg.tool_calls ?? []) : []) {
|
|
190
|
+
parts.push({
|
|
191
|
+
functionCall: {
|
|
192
|
+
id: call.id,
|
|
193
|
+
name: call.function.name,
|
|
194
|
+
args: historyToolArguments(call.function.arguments),
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
return { role, parts };
|
|
199
|
+
}
|
|
200
|
+
export function buildGeminiLiveClientContent(history) {
|
|
201
|
+
if (!history || history.length === 0) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
clientContent: {
|
|
206
|
+
turns: history.map(historyTurnToGoogleTurn),
|
|
207
|
+
turnComplete: true,
|
|
208
|
+
},
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
export function buildGeminiLiveContext(text) {
|
|
212
|
+
return {
|
|
213
|
+
clientContent: { turns: [{ role: 'user', parts: [{ text }] }], turnComplete: false },
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
export function buildGeminiLiveRealtimeInput(input) {
|
|
217
|
+
if (input.type === 'text') {
|
|
218
|
+
return {
|
|
219
|
+
realtimeInput: {
|
|
220
|
+
text: input.text,
|
|
221
|
+
},
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
const part = inlineMediaPart(input);
|
|
225
|
+
// why: The part's mime as given: the API reads the rate from it and rejects what it cannot take.
|
|
226
|
+
const media = { mimeType: part.mimeType, data: part.data };
|
|
227
|
+
return { realtimeInput: part.type === 'audio' ? { audio: media } : { video: media } };
|
|
228
|
+
}
|
|
229
|
+
function liveFunctionResponsePayload(output) {
|
|
230
|
+
const error = asRecord(output)?.error;
|
|
231
|
+
if (typeof error === 'string') {
|
|
232
|
+
return { error };
|
|
233
|
+
}
|
|
234
|
+
return { result: output };
|
|
235
|
+
}
|
|
236
|
+
export function buildGeminiLiveToolResponse(id, name, output, parts) {
|
|
237
|
+
return buildGeminiLiveToolResponses([{ id, name, output, parts }]);
|
|
238
|
+
}
|
|
239
|
+
export function buildGeminiLiveToolResponses(responses) {
|
|
240
|
+
return {
|
|
241
|
+
toolResponse: {
|
|
242
|
+
functionResponses: responses.map(({ id, name, output, parts }) => ({
|
|
243
|
+
id,
|
|
244
|
+
name,
|
|
245
|
+
response: liveFunctionResponsePayload(output),
|
|
246
|
+
...(parts?.length
|
|
247
|
+
? { parts: parts.filter((part) => part.type !== 'text').map(contentPart) }
|
|
248
|
+
: {}),
|
|
249
|
+
})),
|
|
250
|
+
},
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
function functionResponseMessage(response) {
|
|
254
|
+
return {
|
|
255
|
+
role: 'tool',
|
|
256
|
+
...(typeof response.id === 'string' ? { tool_call_id: response.id } : {}),
|
|
257
|
+
...(typeof response.name === 'string' ? { name: response.name } : {}),
|
|
258
|
+
content: JSON.stringify(response.response ?? null),
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
function records(value) {
|
|
262
|
+
if (!Array.isArray(value))
|
|
263
|
+
return [];
|
|
264
|
+
return value.flatMap((item) => {
|
|
265
|
+
const record = asRecord(item);
|
|
266
|
+
return record ? [record] : [];
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
function clientTurnMessages(turn) {
|
|
270
|
+
const parts = [];
|
|
271
|
+
const calls = [];
|
|
272
|
+
const responses = [];
|
|
273
|
+
for (const part of records(turn.parts)) {
|
|
274
|
+
const inline = asRecord(part.inlineData);
|
|
275
|
+
const call = asRecord(part.functionCall);
|
|
276
|
+
const response = asRecord(part.functionResponse);
|
|
277
|
+
if (typeof part.text === 'string') {
|
|
278
|
+
parts.push({ type: 'text', text: part.text });
|
|
279
|
+
}
|
|
280
|
+
else if (inline && typeof inline.mimeType === 'string' && typeof inline.data === 'string') {
|
|
281
|
+
const type = mediaKindForMime(inline.mimeType) ?? 'document';
|
|
282
|
+
parts.push({ type, mimeType: inline.mimeType, data: inline.data });
|
|
283
|
+
}
|
|
284
|
+
else if (call) {
|
|
285
|
+
calls.push({
|
|
286
|
+
id: typeof call.id === 'string' ? call.id : '',
|
|
287
|
+
type: 'function',
|
|
288
|
+
function: { name: String(call.name ?? ''), arguments: JSON.stringify(call.args ?? {}) },
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
else if (response) {
|
|
292
|
+
responses.push(functionResponseMessage(response));
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
const role = turn.role === 'model' ? 'assistant' : 'user';
|
|
296
|
+
const content = parts.length > 0 || calls.length > 0
|
|
297
|
+
? [{ role, parts, ...(calls.length > 0 ? { tool_calls: calls } : {}) }]
|
|
298
|
+
: [];
|
|
299
|
+
return [...content, ...responses];
|
|
300
|
+
}
|
|
301
|
+
/** What one outbound frame gives the model to read; setup and control frames give none. */
|
|
302
|
+
export function liveFrameInput(frame) {
|
|
303
|
+
const realtime = asRecord(frame.realtimeInput);
|
|
304
|
+
if (realtime) {
|
|
305
|
+
const audio = asRecord(realtime.audio);
|
|
306
|
+
const video = asRecord(realtime.video);
|
|
307
|
+
const media = audio ?? video;
|
|
308
|
+
if (media && typeof media.mimeType === 'string' && typeof media.data === 'string') {
|
|
309
|
+
const type = audio ? 'audio' : 'video';
|
|
310
|
+
return [{ role: 'user', parts: [{ type, mimeType: media.mimeType, data: media.data }] }];
|
|
311
|
+
}
|
|
312
|
+
return typeof realtime.text === 'string'
|
|
313
|
+
? [{ role: 'user', parts: [{ type: 'text', text: realtime.text }] }]
|
|
314
|
+
: [];
|
|
315
|
+
}
|
|
316
|
+
const client = asRecord(frame.clientContent);
|
|
317
|
+
if (client) {
|
|
318
|
+
return records(client.turns).flatMap(clientTurnMessages);
|
|
319
|
+
}
|
|
320
|
+
const toolResponse = asRecord(frame.toolResponse);
|
|
321
|
+
return toolResponse ? records(toolResponse.functionResponses).map(functionResponseMessage) : [];
|
|
322
|
+
}
|
|
323
|
+
export function parseGeminiLiveMessage(raw) {
|
|
324
|
+
if (isRecord(raw)) {
|
|
325
|
+
if (raw instanceof ArrayBuffer || raw instanceof Uint8Array) {
|
|
326
|
+
const text = new TextDecoder().decode(raw);
|
|
327
|
+
return parseGeminiLiveMessage(text);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
if (typeof raw !== 'string' || !raw.trim()) {
|
|
331
|
+
return { ok: false, reason: 'empty' };
|
|
332
|
+
}
|
|
333
|
+
try {
|
|
334
|
+
const parsed = JSON.parse(raw);
|
|
335
|
+
if (isRecord(parsed)) {
|
|
336
|
+
return { ok: true, value: parsed };
|
|
337
|
+
}
|
|
338
|
+
return { ok: false, reason: 'malformed' };
|
|
339
|
+
}
|
|
340
|
+
catch {
|
|
341
|
+
return { ok: false, reason: 'malformed' };
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Live sends one usage row per model response, at its `turnComplete`, covering that
|
|
346
|
+
* response alone; the prompt count grows because each response re-reads the session.
|
|
347
|
+
* Probe (gemini-3.1-flash-live-preview, 22/09/2026): `thoughtsTokenCount` sits outside
|
|
348
|
+
* `responseTokenCount` and `totalTokenCount`, so it is added to output.
|
|
349
|
+
* `toolUsePromptTokenCount` (not seen in that probe) is added to input, as on Interactions.
|
|
350
|
+
*/
|
|
351
|
+
export function extractLiveUsageTokens(metadata) {
|
|
352
|
+
const prompt = usageCount(metadata.promptTokenCount);
|
|
353
|
+
const response = usageCount(metadata.responseTokenCount);
|
|
354
|
+
const thoughts = usageCount(metadata.thoughtsTokenCount) ?? 0;
|
|
355
|
+
const toolUse = usageCount(metadata.toolUsePromptTokenCount) ?? 0;
|
|
356
|
+
return reportedTokens({
|
|
357
|
+
input: prompt ? prompt + toolUse : undefined,
|
|
358
|
+
output: response === undefined ? undefined : response + thoughts,
|
|
359
|
+
thinking: thoughts,
|
|
360
|
+
toolUse,
|
|
361
|
+
cached: usageCount(metadata.cachedContentTokenCount),
|
|
362
|
+
byModality: byModality(modalityCounts(metadata.promptTokensDetails, 'tokenCount'), modalityCounts(metadata.responseTokensDetails, 'tokenCount')),
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
function foldSessionUpdate(message, events) {
|
|
366
|
+
const sessionUpdate = asRecord(message.sessionResumptionUpdate);
|
|
367
|
+
if (!sessionUpdate)
|
|
368
|
+
return;
|
|
369
|
+
const handle = typeof sessionUpdate.newHandle === 'string' && sessionUpdate.newHandle.length > 0
|
|
370
|
+
? sessionUpdate.newHandle
|
|
371
|
+
: undefined;
|
|
372
|
+
const resumable = typeof sessionUpdate.resumable === 'boolean' ? sessionUpdate.resumable : undefined;
|
|
373
|
+
if (handle === undefined && resumable === undefined)
|
|
374
|
+
return;
|
|
375
|
+
events.push({
|
|
376
|
+
type: 'evidence',
|
|
377
|
+
...(handle !== undefined ? { sessionResumptionHandle: handle } : {}),
|
|
378
|
+
evidence: {
|
|
379
|
+
provider: 'google',
|
|
380
|
+
kind: 'session_resumption',
|
|
381
|
+
resumable: resumable ?? handle !== undefined,
|
|
382
|
+
raw: sessionUpdate,
|
|
383
|
+
},
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
export function newLiveFold() {
|
|
387
|
+
return { calls: new Map() };
|
|
388
|
+
}
|
|
389
|
+
function foldToolCalls(message, fold, events) {
|
|
390
|
+
const calls = asRecord(message.toolCall)?.functionCalls;
|
|
391
|
+
if (!Array.isArray(calls))
|
|
392
|
+
return;
|
|
393
|
+
// why: The calls of one `toolCall` message are the model's step: chosen together, before any result.
|
|
394
|
+
const stepId = crypto.randomUUID();
|
|
395
|
+
const stepCallCount = calls.length;
|
|
396
|
+
for (const value of calls) {
|
|
397
|
+
const call = asRecord(value) ?? {};
|
|
398
|
+
const id = typeof call.id === 'string' && call.id ? call.id : undefined;
|
|
399
|
+
const name = typeof call.name === 'string' ? call.name : '';
|
|
400
|
+
if (id && name)
|
|
401
|
+
fold.calls.set(id, name);
|
|
402
|
+
events.push(...toolCallEvents({ id, name, stepId, stepCallCount }, call.args));
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* `toolCallCancellation: { ids }` (probe 23/09/2026: gemini-3.1-flash-live and
|
|
407
|
+
* gemini-2.5-flash-native-audio on barge-in; gemini-3.8-live never sends it).
|
|
408
|
+
* It names only ids, so each cancel takes its name from the call this
|
|
409
|
+
* connection issued.
|
|
410
|
+
*/
|
|
411
|
+
function foldToolCancellations(message, fold, events) {
|
|
412
|
+
const ids = asRecord(message.toolCallCancellation)?.ids;
|
|
413
|
+
if (!Array.isArray(ids))
|
|
414
|
+
return;
|
|
415
|
+
for (const id of ids) {
|
|
416
|
+
const name = typeof id === 'string' ? fold.calls.get(id) : undefined;
|
|
417
|
+
if (typeof id !== 'string' || !name) {
|
|
418
|
+
// why: Every observed cancel names a call this connection issued; anything else is a wire change.
|
|
419
|
+
events.push(toErrorEvent(new TheoremError('bad_response', `Live cancelled a tool call it never issued: ${String(id)}`)));
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
fold.calls.delete(id);
|
|
423
|
+
events.push(toolEvent({ name, callId: id }, { phase: 'cancel' }));
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* `voiceActivity: { type: 'ACTIVITY_START' | 'ACTIVITY_END', audioOffset: '0.360s' }`
|
|
428
|
+
* (probe 23/09/2026: gemini-3.1-flash-live only), as `evidence` with the
|
|
429
|
+
* message as `raw`.
|
|
430
|
+
*/
|
|
431
|
+
function foldVoiceActivity(message, events) {
|
|
432
|
+
const voiceActivity = asRecord(message.voiceActivity);
|
|
433
|
+
if (!voiceActivity)
|
|
434
|
+
return;
|
|
435
|
+
events.push({
|
|
436
|
+
type: 'evidence',
|
|
437
|
+
evidence: { provider: 'google', kind: 'voice_activity', raw: voiceActivity },
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* `goAway.timeLeft` → milliseconds. It is a protobuf Duration, which JSON
|
|
442
|
+
* encodes as seconds with an `s` suffix (`"10s"`, `"1.5s"`).
|
|
443
|
+
*/
|
|
444
|
+
export function parseGoAwayTimeLeftMs(timeLeft) {
|
|
445
|
+
if (typeof timeLeft !== 'string')
|
|
446
|
+
return undefined;
|
|
447
|
+
const match = /^(\d+(?:\.\d+)?)s$/.exec(timeLeft);
|
|
448
|
+
return match?.[1] ? Math.round(Number(match[1]) * 1000) : undefined;
|
|
449
|
+
}
|
|
450
|
+
function foldGoAway(message, events) {
|
|
451
|
+
const goAway = asRecord(message.goAway);
|
|
452
|
+
if (!goAway)
|
|
453
|
+
return;
|
|
454
|
+
const timeLeftMs = parseGoAwayTimeLeftMs(goAway.timeLeft);
|
|
455
|
+
events.push({
|
|
456
|
+
type: 'session',
|
|
457
|
+
session: {
|
|
458
|
+
kind: 'closing_soon',
|
|
459
|
+
...(timeLeftMs !== undefined ? { timeLeftMs } : {}),
|
|
460
|
+
},
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Output audio arrives as `inlineData` with `mimeType: 'audio/pcm;rate=24000'`
|
|
465
|
+
* (probes 23/09/2026, every Live model); it becomes WAV at the stated rate.
|
|
466
|
+
* Thinking models mark reasoning text with `thought: true`.
|
|
467
|
+
*/
|
|
468
|
+
function foldModelPart(part, events) {
|
|
469
|
+
if (typeof part.text === 'string' && part.text) {
|
|
470
|
+
events.push({ type: part.thought === true ? 'thought' : 'text', text: part.text });
|
|
471
|
+
}
|
|
472
|
+
const inlineData = asRecord(part.inlineData);
|
|
473
|
+
const mimeType = inlineData?.mimeType;
|
|
474
|
+
const data = inlineData?.data;
|
|
475
|
+
if (typeof mimeType === 'string' && mimeType && typeof data === 'string' && data) {
|
|
476
|
+
events.push({ type: 'media', media: pcmMediaAsWav({ mimeType, data }) });
|
|
477
|
+
}
|
|
478
|
+
const codeExecutionResult = asRecord(part.codeExecutionResult);
|
|
479
|
+
if (codeExecutionResult) {
|
|
480
|
+
events.push(codeExecutionResultEvidence(codeExecutionResult));
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* `codeExecutionResult: { outcome, output }` (probe 23/09/2026:
|
|
485
|
+
* gemini-2.5-flash-native-audio reports each search / URL fetch this way, e.g.
|
|
486
|
+
* `OUTCOME_OK` / `Browsing the web.`). No `executableCode` part was seen on any
|
|
487
|
+
* Live model.
|
|
488
|
+
*/
|
|
489
|
+
function codeExecutionResultEvidence(result) {
|
|
490
|
+
return {
|
|
491
|
+
type: 'evidence',
|
|
492
|
+
evidence: {
|
|
493
|
+
provider: 'google',
|
|
494
|
+
kind: 'code_execution_result',
|
|
495
|
+
...(typeof result.output === 'string' ? { result: result.output } : {}),
|
|
496
|
+
...(typeof result.outcome === 'string' ? { isError: result.outcome !== 'OUTCOME_OK' } : {}),
|
|
497
|
+
raw: result,
|
|
498
|
+
},
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
function transcriptionText(value) {
|
|
502
|
+
const text = asRecord(value)?.text;
|
|
503
|
+
return typeof text === 'string' && text ? text : undefined;
|
|
504
|
+
}
|
|
505
|
+
function foldTranscription(value, kind, events, interim) {
|
|
506
|
+
const text = transcriptionText(value);
|
|
507
|
+
if (!text)
|
|
508
|
+
return;
|
|
509
|
+
events.push({
|
|
510
|
+
type: 'evidence',
|
|
511
|
+
text,
|
|
512
|
+
evidence: {
|
|
513
|
+
provider: 'google',
|
|
514
|
+
kind,
|
|
515
|
+
...(interim ? { interim: true } : {}),
|
|
516
|
+
},
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
function foldLiveGrounding(serverContent, events) {
|
|
520
|
+
events.push(...groundingFromLiveMetadata(serverContent.groundingMetadata));
|
|
521
|
+
const urlContext = asRecord(serverContent.urlContextMetadata);
|
|
522
|
+
if (urlContext) {
|
|
523
|
+
events.push({
|
|
524
|
+
type: 'evidence',
|
|
525
|
+
evidence: { provider: 'google', kind: 'url_context', raw: urlContext },
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* `serverContent.interactionStatus`, sent beside `turnComplete` by models that
|
|
531
|
+
* keep working after a turn (gemini-3.8-live-extended-thinking, probe
|
|
532
|
+
* 23/09/2026: `IN_PROGRESS` on each intermediate `turnComplete` of a tool
|
|
533
|
+
* flow, `IDLE` on the last).
|
|
534
|
+
*/
|
|
535
|
+
export function readLiveInteractionStatus(message) {
|
|
536
|
+
const raw = asRecord(message.serverContent)?.interactionStatus;
|
|
537
|
+
if (raw === 'IN_PROGRESS' || raw === 'IDLE')
|
|
538
|
+
return raw;
|
|
539
|
+
return undefined;
|
|
540
|
+
}
|
|
541
|
+
function foldInteractionStatus(message, events) {
|
|
542
|
+
const status = readLiveInteractionStatus(message);
|
|
543
|
+
if (!status)
|
|
544
|
+
return;
|
|
545
|
+
events.push({
|
|
546
|
+
type: 'session',
|
|
547
|
+
session: { kind: status === 'IDLE' ? 'idle' : 'working' },
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
function foldServerContent(message, events) {
|
|
551
|
+
const serverContent = asRecord(message.serverContent);
|
|
552
|
+
if (!serverContent)
|
|
553
|
+
return;
|
|
554
|
+
if (serverContent.interrupted === true) {
|
|
555
|
+
events.push({ type: 'done', interrupted: true, stop: { kind: 'interrupted' } });
|
|
556
|
+
}
|
|
557
|
+
if (serverContent.waitingForInput === true) {
|
|
558
|
+
events.push({ type: 'session', session: { kind: 'waiting_for_input' } });
|
|
559
|
+
}
|
|
560
|
+
if (serverContent.generationComplete === true) {
|
|
561
|
+
events.push({ type: 'done', stop: { kind: 'generation_complete' } });
|
|
562
|
+
}
|
|
563
|
+
foldTranscription(serverContent.inputTranscription, 'input_transcription', events);
|
|
564
|
+
foldTranscription(serverContent.interimInputTranscription, 'input_transcription', events, true);
|
|
565
|
+
foldTranscription(serverContent.outputTranscription, 'output_transcription', events);
|
|
566
|
+
const parts = asRecord(serverContent.modelTurn)?.parts;
|
|
567
|
+
for (const part of Array.isArray(parts) ? parts : []) {
|
|
568
|
+
const record = asRecord(part);
|
|
569
|
+
if (record)
|
|
570
|
+
foldModelPart(record, events);
|
|
571
|
+
}
|
|
572
|
+
foldLiveGrounding(serverContent, events);
|
|
573
|
+
if (serverContent.turnComplete === true) {
|
|
574
|
+
events.push({ type: 'session', session: { kind: 'turn_complete' } });
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
function foldUsageMetadata(message, events) {
|
|
578
|
+
const usageMetadata = asRecord(message.usageMetadata);
|
|
579
|
+
const tokens = usageMetadata ? extractLiveUsageTokens(usageMetadata) : undefined;
|
|
580
|
+
if (tokens) {
|
|
581
|
+
events.push({ type: 'tokens', tokens });
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
export function foldGeminiLiveServerMessage(message, fold) {
|
|
585
|
+
if (!message || typeof message !== 'object')
|
|
586
|
+
return [];
|
|
587
|
+
const events = [];
|
|
588
|
+
foldGoAway(message, events);
|
|
589
|
+
foldSessionUpdate(message, events);
|
|
590
|
+
foldToolCalls(message, fold, events);
|
|
591
|
+
foldToolCancellations(message, fold, events);
|
|
592
|
+
foldVoiceActivity(message, events);
|
|
593
|
+
foldServerContent(message, events);
|
|
594
|
+
foldInteractionStatus(message, events);
|
|
595
|
+
foldUsageMetadata(message, events);
|
|
596
|
+
return events;
|
|
597
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { TheoremError } from '../../../guardrails/error.js';
|
|
2
|
+
import type { ModelEvent } from '../../../kernel/types.js';
|
|
3
|
+
import type { LiveTurnPhase } from '../../types.js';
|
|
4
|
+
export declare function closeError(code: number, reason: string, during: 'setup' | 'session'): TheoremError;
|
|
5
|
+
export declare function goAwayIn(events: readonly ModelEvent[]): {
|
|
6
|
+
timeLeftMs?: number;
|
|
7
|
+
} | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* `interactionStatus`, when sent, is authoritative: `IN_PROGRESS` keeps the cycle
|
|
10
|
+
* open across `turnComplete` (background reasoning or async tools may still
|
|
11
|
+
* produce output). Without it, `turnComplete` is the boundary.
|
|
12
|
+
*/
|
|
13
|
+
export declare function turnPhaseFromMessage(message: Record<string, unknown>, events: ModelEvent[]): LiveTurnPhase;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { TheoremError } from '../../../guardrails/error.js';
|
|
2
|
+
import { asRecord } from '../../../kernel/engine/record.js';
|
|
3
|
+
import { findLast } from '../../../kernel/util/find-last.js';
|
|
4
|
+
import { readLiveInteractionStatus } from './framing.js';
|
|
5
|
+
/** RFC 6455 §7.4.1 close codes; any other code is `unavailable`. */
|
|
6
|
+
const CLOSE_KINDS = {
|
|
7
|
+
1006: 'network',
|
|
8
|
+
1007: 'unsupported',
|
|
9
|
+
1008: 'unsupported',
|
|
10
|
+
1011: 'unavailable',
|
|
11
|
+
1013: 'unavailable',
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Google refuses an over-quota Live key with code 1011 (`unavailable`) and a reason
|
|
15
|
+
* ("You exceeded your current quota, …"); the reason is the only quota signal.
|
|
16
|
+
*/
|
|
17
|
+
const QUOTA_CLOSE_RE = /\bquota\b/i;
|
|
18
|
+
/**
|
|
19
|
+
* A bad key closes setup with 1007 ("API key not valid. …"), which by code
|
|
20
|
+
* reads as `unsupported`; like quota, the reason is the only signal.
|
|
21
|
+
*/
|
|
22
|
+
const AUTH_CLOSE_RE = /\bAPI key (?:not valid|expired)\b/i;
|
|
23
|
+
/** The kind a close's reason names, if any. */
|
|
24
|
+
function closeReasonKind(reason) {
|
|
25
|
+
if (QUOTA_CLOSE_RE.test(reason))
|
|
26
|
+
return 'rate_limit';
|
|
27
|
+
if (AUTH_CLOSE_RE.test(reason))
|
|
28
|
+
return 'auth';
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
export function closeError(code, reason, during) {
|
|
32
|
+
return new TheoremError(closeReasonKind(reason) ?? CLOSE_KINDS[code] ?? 'unavailable', `Gemini Live WebSocket closed during ${during} (${code}: ${reason})`);
|
|
33
|
+
}
|
|
34
|
+
export function goAwayIn(events) {
|
|
35
|
+
const warning = findLast(events, (ev) => ev.type === 'session' && ev.session.kind === 'closing_soon');
|
|
36
|
+
return warning?.session.kind === 'closing_soon'
|
|
37
|
+
? { timeLeftMs: warning.session.timeLeftMs }
|
|
38
|
+
: undefined;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* `interactionStatus`, when sent, is authoritative: `IN_PROGRESS` keeps the cycle
|
|
42
|
+
* open across `turnComplete` (background reasoning or async tools may still
|
|
43
|
+
* produce output). Without it, `turnComplete` is the boundary.
|
|
44
|
+
*/
|
|
45
|
+
export function turnPhaseFromMessage(message, events) {
|
|
46
|
+
const interrupted = events.some((ev) => ev.type === 'done' && ev.interrupted === true);
|
|
47
|
+
if (interrupted)
|
|
48
|
+
return 'abort';
|
|
49
|
+
const status = readLiveInteractionStatus(message);
|
|
50
|
+
if (status === 'IDLE')
|
|
51
|
+
return 'complete';
|
|
52
|
+
if (status === 'IN_PROGRESS')
|
|
53
|
+
return 'streaming';
|
|
54
|
+
if (asRecord(message.serverContent)?.turnComplete === true)
|
|
55
|
+
return 'complete';
|
|
56
|
+
return 'streaming';
|
|
57
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { TheoremError } from '../../guardrails/error.js';
|
|
2
|
+
import { GOOGLE_THINKING_LEVELS } from '../../presets/google-limits.js';
|
|
3
|
+
/** Refuses a thinking level Gemini does not take, rather than sending it. */
|
|
4
|
+
export function assertGoogleThinkingLevel(level) {
|
|
5
|
+
if (level && !GOOGLE_THINKING_LEVELS.includes(level)) {
|
|
6
|
+
throw new TheoremError('unsupported', `Gemini does not take the '${level}' thinking level (${GOOGLE_THINKING_LEVELS.join(', ')})`);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** The models a key's project can call; paged with `pageToken`. */
|
|
2
|
+
declare const GEMINI_MODELS_URL = "https://generativelanguage.googleapis.com/v1beta/models";
|
|
3
|
+
declare const GEMINI_LIVE_WS_URL = "wss://generativelanguage.googleapis.com/ws/google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent";
|
|
4
|
+
export { GEMINI_LIVE_WS_URL, GEMINI_MODELS_URL };
|