@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
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { defineProtocol, modelOptions } from '../../kernel/protocols/mod.js';
|
|
3
|
+
function task(value, title, description) {
|
|
4
|
+
return z.literal(value).meta({ title, description });
|
|
5
|
+
}
|
|
6
|
+
const options = z.strictObject({
|
|
7
|
+
// why: Labels and descriptions are Google's own task-type table (ai.google.dev/gemini-api/docs/embeddings), so a studio can show them.
|
|
8
|
+
taskType: z
|
|
9
|
+
.union([
|
|
10
|
+
task('RETRIEVAL_QUERY', 'Retrieval query', 'Embeddings optimized for general search queries. Pair with Retrieval document for the documents searched.'),
|
|
11
|
+
task('RETRIEVAL_DOCUMENT', 'Retrieval document', 'Embeddings optimized for document search, such as indexing articles, books or web pages.'),
|
|
12
|
+
task('SEMANTIC_SIMILARITY', 'Semantic similarity', 'Embeddings optimized to assess text similarity, such as for recommendations or duplicate detection.'),
|
|
13
|
+
task('CLASSIFICATION', 'Classification', 'Embeddings optimized to classify texts according to preset labels, such as sentiment or spam.'),
|
|
14
|
+
task('CLUSTERING', 'Clustering', 'Embeddings optimized to cluster texts based on their similarities.'),
|
|
15
|
+
task('QUESTION_ANSWERING', 'Question answering', 'Embeddings for questions, optimized for finding documents that answer them. Pair with Retrieval document.'),
|
|
16
|
+
task('FACT_VERIFICATION', 'Fact verification', 'Embeddings for statements to verify, optimized for retrieving evidence that supports or refutes them. Pair with Retrieval document.'),
|
|
17
|
+
task('CODE_RETRIEVAL_QUERY', 'Code retrieval query', 'Embeddings optimized for finding code blocks from natural language queries. Pair with Retrieval document for the code.'),
|
|
18
|
+
])
|
|
19
|
+
.optional()
|
|
20
|
+
.describe("What the vectors will be used for, so Google tunes them to it. Only gemini-embedding-001 takes it; later models read the request's task from the text. Absent: no tuning."),
|
|
21
|
+
outputDimensionality: z
|
|
22
|
+
.union([z.literal(768), z.literal(1536), z.literal(3072)])
|
|
23
|
+
.optional()
|
|
24
|
+
.describe('How many numbers each vector holds. A shorter vector is cheaper to store and compare and a little less precise. Absent: the 3072 the model returns.'),
|
|
25
|
+
});
|
|
26
|
+
/** Models that take the task as `taskType`. Later ones (Gemini Embedding 2 on) refuse the field and read the task from the text. */
|
|
27
|
+
const TASK_FIELD_MODELS = /^(gemini-embedding-001|text-embedding-|embedding-)/;
|
|
28
|
+
// why: ai.google.dev/gemini-api/docs/embeddings gives 6 images and 1 PDF per input, and duration caps (not counts) for audio and video; a batch of 101 inputs is refused (checked 2026-10-19).
|
|
29
|
+
const MULTIMODAL = {
|
|
30
|
+
maxInputs: 100,
|
|
31
|
+
media: [
|
|
32
|
+
{ accept: ['image/png', 'image/jpeg'], maxPerInput: 6 },
|
|
33
|
+
{ accept: ['application/pdf'], maxPerInput: 1 },
|
|
34
|
+
{ accept: ['audio/mpeg', 'audio/mp3', 'audio/wav', 'audio/x-wav'] },
|
|
35
|
+
{ accept: ['video/mp4', 'video/quicktime'] },
|
|
36
|
+
],
|
|
37
|
+
};
|
|
38
|
+
const TEXT_ONLY = { maxInputs: 100, media: [] };
|
|
39
|
+
const TASK_TYPES = {
|
|
40
|
+
query: 'RETRIEVAL_QUERY',
|
|
41
|
+
document: 'RETRIEVAL_DOCUMENT',
|
|
42
|
+
};
|
|
43
|
+
// why: The formats Google gives for Gemini Embedding 2 search (ai.google.dev/gemini-api/docs/embeddings); it advises leaving input with media unprefixed.
|
|
44
|
+
function withTask(text, task) {
|
|
45
|
+
return task === 'query' ? `task: search result | query: ${text}` : `title: none | text: ${text}`;
|
|
46
|
+
}
|
|
47
|
+
function parts(input, task) {
|
|
48
|
+
const list = typeof input === 'string' ? [{ type: 'text', text: input }] : input.parts;
|
|
49
|
+
const textOnly = list.every((part) => part.type === 'text');
|
|
50
|
+
return list.map((part, at) => {
|
|
51
|
+
if (part.type === 'text')
|
|
52
|
+
return { text: task && textOnly && at === 0 ? withTask(part.text, task) : part.text };
|
|
53
|
+
if (part.type === 'media') {
|
|
54
|
+
return { inlineData: { mimeType: part.mimeType, data: part.data } };
|
|
55
|
+
}
|
|
56
|
+
return { fileData: { mimeType: part.mimeType, fileUri: part.uri } };
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function values(row) {
|
|
60
|
+
const embedding = row.embedding;
|
|
61
|
+
const values = embedding && typeof embedding === 'object'
|
|
62
|
+
? embedding.values
|
|
63
|
+
: undefined;
|
|
64
|
+
return Array.isArray(values)
|
|
65
|
+
? values.filter((value) => typeof value === 'number')
|
|
66
|
+
: [];
|
|
67
|
+
}
|
|
68
|
+
function requestBody(input, parsed, shape) {
|
|
69
|
+
const body = {
|
|
70
|
+
content: { parts: parts(input, shape.taskField ? undefined : shape.task) },
|
|
71
|
+
};
|
|
72
|
+
const taskType = shape.taskField && shape.task ? TASK_TYPES[shape.task] : parsed.taskType;
|
|
73
|
+
if (taskType)
|
|
74
|
+
body.taskType = taskType;
|
|
75
|
+
if (parsed.outputDimensionality)
|
|
76
|
+
body.outputDimensionality = parsed.outputDimensionality;
|
|
77
|
+
return body;
|
|
78
|
+
}
|
|
79
|
+
export const geminiEmbedding = defineProtocol({
|
|
80
|
+
id: 'geminiEmbedding',
|
|
81
|
+
name: 'Gemini Embeddings',
|
|
82
|
+
description: "Google's embedding API for text and supported media.",
|
|
83
|
+
endpoints: { embedding: '/models/{apiId}:embedContent' },
|
|
84
|
+
options,
|
|
85
|
+
embeddingLimits: (apiId) => (TASK_FIELD_MODELS.test(apiId) ? TEXT_ONLY : MULTIMODAL),
|
|
86
|
+
// why: Gemini Embedding 2 reads the task from the text and refuses the field; the request's `task` says it.
|
|
87
|
+
refusedOptions: (apiId) => (TASK_FIELD_MODELS.test(apiId) ? [] : ['taskType']),
|
|
88
|
+
create(context) {
|
|
89
|
+
return {
|
|
90
|
+
async embed(request) {
|
|
91
|
+
const parsed = modelOptions(geminiEmbedding, context.apiId, request.options);
|
|
92
|
+
const taskField = TASK_FIELD_MODELS.test(context.apiId);
|
|
93
|
+
const shape = { taskField, ...(request.task ? { task: request.task } : {}) };
|
|
94
|
+
const inputs = Array.isArray(request.input) ? request.input : [request.input];
|
|
95
|
+
const body = inputs.length === 1
|
|
96
|
+
? requestBody(inputs[0], parsed, shape)
|
|
97
|
+
: {
|
|
98
|
+
requests: inputs.map((input) => ({
|
|
99
|
+
model: `models/${context.apiId}`,
|
|
100
|
+
...requestBody(input, parsed, shape),
|
|
101
|
+
})),
|
|
102
|
+
};
|
|
103
|
+
const path = inputs.length === 1
|
|
104
|
+
? `/models/${encodeURIComponent(context.apiId)}:embedContent`
|
|
105
|
+
: `/models/${encodeURIComponent(context.apiId)}:batchEmbedContents`;
|
|
106
|
+
let row;
|
|
107
|
+
for await (const current of context.send(body, { stream: false, path }))
|
|
108
|
+
row = current;
|
|
109
|
+
const raw = Array.isArray(row?.embeddings)
|
|
110
|
+
? row.embeddings
|
|
111
|
+
: row?.embedding
|
|
112
|
+
? [row.embedding]
|
|
113
|
+
: [];
|
|
114
|
+
return {
|
|
115
|
+
model: context.apiId,
|
|
116
|
+
embeddings: raw.map((item, index) => ({
|
|
117
|
+
index,
|
|
118
|
+
values: item && typeof item === 'object' ? values({ embedding: item }) : [],
|
|
119
|
+
dimensions: item && typeof item === 'object' ? values({ embedding: item }).length : 0,
|
|
120
|
+
})),
|
|
121
|
+
};
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
},
|
|
125
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type Protocol } from '../../kernel/protocols/mod.js';
|
|
2
|
+
/** What a `geminiInteractions` binding sets in `options`. */
|
|
3
|
+
export interface GeminiInteractionsOptions {
|
|
4
|
+
store?: boolean;
|
|
5
|
+
persistViaInteractionId?: boolean;
|
|
6
|
+
}
|
|
7
|
+
/** Gemini's Interactions API: text, images, and speech, all at `/interactions`. */
|
|
8
|
+
export declare const geminiInteractions: Protocol<GeminiInteractionsOptions>;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { asRecord } from '../../kernel/engine/record.js';
|
|
3
|
+
import { jsonObjectSchema } from '../../kernel/json.js';
|
|
4
|
+
import { defineProtocol, } from '../../kernel/protocols/mod.js';
|
|
5
|
+
import { readGeminiApiError, statedOrStatusError } from '../google/api-error.js';
|
|
6
|
+
import { googleBuiltins } from '../google/builtins.js';
|
|
7
|
+
import { thoughtSignature, toInteractionsBody, } from '../google/interactions/framing.js';
|
|
8
|
+
import { finalizeStructured, foldBody, foldPayload, missingMediaError, newStreamFold, openStepEvents, } from '../google/interactions/stream.js';
|
|
9
|
+
import { asProtocolEvent } from '../shared/protocol-events.js';
|
|
10
|
+
const state = z.strictObject({ interactionId: z.string().min(1) });
|
|
11
|
+
const options = z
|
|
12
|
+
.strictObject({
|
|
13
|
+
store: z
|
|
14
|
+
.boolean()
|
|
15
|
+
.optional()
|
|
16
|
+
.describe('Whether Google keeps the interaction. Off, nothing is stored server-side.'), // labels-exempt: builder field description, read by the studio and docs
|
|
17
|
+
persistViaInteractionId: z.boolean().optional().describe('Continue from the stored interaction instead of sending the conversation again. Needs store.'),
|
|
18
|
+
})
|
|
19
|
+
.refine((value) => !value.persistViaInteractionId || value.store !== false, 'persistViaInteractionId needs store');
|
|
20
|
+
function wireRequest(context, request) {
|
|
21
|
+
const history = request.history ?? [];
|
|
22
|
+
const previous = context.options.persistViaInteractionId
|
|
23
|
+
? request.state?.interactionId
|
|
24
|
+
: undefined;
|
|
25
|
+
const builtins = googleBuiltins(request.builtins);
|
|
26
|
+
const wire = {
|
|
27
|
+
...request,
|
|
28
|
+
apiId: context.apiId,
|
|
29
|
+
history,
|
|
30
|
+
builtins,
|
|
31
|
+
state: undefined,
|
|
32
|
+
tapUpstream: undefined,
|
|
33
|
+
store: context.options.store,
|
|
34
|
+
previousInteractionId: previous,
|
|
35
|
+
continuation: previous
|
|
36
|
+
? [
|
|
37
|
+
...history.slice(request.stateHistoryLength ?? 0),
|
|
38
|
+
...request.input.map((part) => ({ role: 'user', parts: [part] })),
|
|
39
|
+
]
|
|
40
|
+
: undefined,
|
|
41
|
+
};
|
|
42
|
+
const body = jsonObjectSchema.parse(JSON.parse(JSON.stringify(toInteractionsBody(wire))));
|
|
43
|
+
return { wire, body, wroteTools: builtins.map((builtin) => builtin.id) };
|
|
44
|
+
}
|
|
45
|
+
/** The shared reader's events as protocol events; the `done` waits for the end, with the state to keep. */
|
|
46
|
+
function asProtocolEvents(events, reply, persist) {
|
|
47
|
+
return events.flatMap((event) => {
|
|
48
|
+
if (event.type !== 'done') {
|
|
49
|
+
const converted = asProtocolEvent(event);
|
|
50
|
+
return converted ? [converted] : [];
|
|
51
|
+
}
|
|
52
|
+
const { interactionId, ...done } = event;
|
|
53
|
+
reply.done = {
|
|
54
|
+
...done,
|
|
55
|
+
...(persist && interactionId ? { state: { interactionId } } : {}),
|
|
56
|
+
};
|
|
57
|
+
return [];
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/** Gemini's Interactions API: text, images, and speech, all at `/interactions`. */
|
|
61
|
+
export const geminiInteractions = defineProtocol({
|
|
62
|
+
id: 'geminiInteractions',
|
|
63
|
+
name: 'Gemini Interactions',
|
|
64
|
+
description: "Google's Interactions API for Gemini: text, images and speech at one endpoint.", // labels-exempt: builder field description, read by the studio and docs
|
|
65
|
+
endpoints: { text: '/interactions', image: '/interactions', speech: '/interactions' },
|
|
66
|
+
options,
|
|
67
|
+
continuation: { version: 1, schema: state, keyOptions: ['store', 'persistViaInteractionId'] },
|
|
68
|
+
reasoning: thoughtSignature,
|
|
69
|
+
error(failure) {
|
|
70
|
+
const record = asRecord(failure.body);
|
|
71
|
+
return statedOrStatusError(record ? readGeminiApiError(record) : null, failure.status, `Gemini HTTP ${failure.status}`);
|
|
72
|
+
},
|
|
73
|
+
create(context) {
|
|
74
|
+
return {
|
|
75
|
+
async *complete(request) {
|
|
76
|
+
const { wire, body, wroteTools } = wireRequest(context, request);
|
|
77
|
+
const stream = request.stream !== false;
|
|
78
|
+
const persist = Boolean(context.options.persistViaInteractionId);
|
|
79
|
+
const reply = { fold: newStreamFold() };
|
|
80
|
+
const init = { stream, wroteTools, ...(stream ? { path: '/interactions?alt=sse' } : {}) };
|
|
81
|
+
for await (const row of context.send(body, init)) {
|
|
82
|
+
// why: an error row before any output is thrown, so the kernel can fall back to the other key.
|
|
83
|
+
const failed = readGeminiApiError(row);
|
|
84
|
+
if (failed)
|
|
85
|
+
throw failed;
|
|
86
|
+
const events = stream ? foldPayload(row, reply.fold) : foldBody(row, reply.fold);
|
|
87
|
+
yield* asProtocolEvents(events, reply, persist);
|
|
88
|
+
if (events.some((event) => event.type === 'error')) {
|
|
89
|
+
yield* asProtocolEvents(openStepEvents(reply.fold), reply, persist);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
yield* asProtocolEvents(openStepEvents(reply.fold), reply, persist);
|
|
94
|
+
yield* asProtocolEvents([...finalizeStructured(wire, reply.fold)], reply, persist);
|
|
95
|
+
const missing = missingMediaError(wire, reply.fold);
|
|
96
|
+
if (missing)
|
|
97
|
+
yield* asProtocolEvents([missing], reply, persist);
|
|
98
|
+
yield reply.done ?? { type: 'done', stop: { kind: 'stream_incomplete' } };
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
},
|
|
102
|
+
});
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { TheoremError } from '../../guardrails/error.js';
|
|
3
|
+
import { jsonObjectSchema } from '../../kernel/json.js';
|
|
4
|
+
import { defineProtocol, } from '../../kernel/protocols/mod.js';
|
|
5
|
+
import { readGeminiApiError } from '../google/api-error.js';
|
|
6
|
+
import { googleBuiltins } from '../google/builtins.js';
|
|
7
|
+
import { buildGeminiLiveClientContent, buildGeminiLiveContext, buildGeminiLiveRealtimeInput, buildGeminiLiveSetupMessage, buildGeminiLiveToolResponse, foldGeminiLiveServerMessage, liveFrameInput, newLiveFold, } from '../google/live/framing.js';
|
|
8
|
+
import { closeError, goAwayIn, turnPhaseFromMessage } from '../google/live/stream.js';
|
|
9
|
+
import { asProtocolEvent } from '../shared/protocol-events.js';
|
|
10
|
+
const state = z.strictObject({ liveHandle: z.string().min(1) });
|
|
11
|
+
const NORMAL_CLOSE = 1000;
|
|
12
|
+
/** What a frame that is not the model's says: a close, a socket error, or bytes that are not JSON. */
|
|
13
|
+
function socketTrouble(frame, during) {
|
|
14
|
+
if (frame.eventType === 'ws_error')
|
|
15
|
+
return new TheoremError('network', `Gemini Live WebSocket error during ${during}`); // labels-exempt: developer diagnostic
|
|
16
|
+
if (frame.eventType === 'ws_unparsed')
|
|
17
|
+
return new TheoremError('bad_response', 'malformed Gemini Live message'); // labels-exempt: developer diagnostic
|
|
18
|
+
return readGeminiApiError(frame) ?? undefined;
|
|
19
|
+
}
|
|
20
|
+
/** Waits for `setupComplete`; a refusal here comes before any event, so the kernel can try the other key. */
|
|
21
|
+
async function setupComplete(frames, context) {
|
|
22
|
+
let timer;
|
|
23
|
+
const late = new Promise((_, reject) => {
|
|
24
|
+
timer = setTimeout(() => reject(new TheoremError('timeout', `Gemini Live setup timed out after ${context.limits.connectTimeoutMs}ms`)), context.limits.connectTimeoutMs);
|
|
25
|
+
});
|
|
26
|
+
try {
|
|
27
|
+
for (;;) {
|
|
28
|
+
const next = await Promise.race([frames.next(), late]);
|
|
29
|
+
if (next.done)
|
|
30
|
+
throw closeError(1006, '', 'setup');
|
|
31
|
+
const frame = next.value;
|
|
32
|
+
if (frame.eventType === 'ws_close')
|
|
33
|
+
throw closeError(Number(frame.code), String(frame.reason ?? ''), 'setup');
|
|
34
|
+
const trouble = socketTrouble(frame, 'setup');
|
|
35
|
+
if (trouble)
|
|
36
|
+
throw trouble;
|
|
37
|
+
if (frame.setupComplete)
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
clearTimeout(timer);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function wireRequest(context, request) {
|
|
46
|
+
const handle = request.state?.liveHandle;
|
|
47
|
+
const history = request.history ?? [];
|
|
48
|
+
const builtins = googleBuiltins(request.builtins);
|
|
49
|
+
const wire = {
|
|
50
|
+
...request,
|
|
51
|
+
apiId: context.apiId,
|
|
52
|
+
builtins,
|
|
53
|
+
state: undefined,
|
|
54
|
+
tapUpstream: undefined,
|
|
55
|
+
sessionResumptionHandle: handle,
|
|
56
|
+
// why: a resumed session already holds what came before its handle.
|
|
57
|
+
history: handle ? history.slice(request.stateHistoryLength ?? 0) : history,
|
|
58
|
+
live: {
|
|
59
|
+
...request.live,
|
|
60
|
+
transcription: { ...request.live?.transcription, input: true, output: true },
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
const setup = jsonObjectSchema.parse(JSON.parse(JSON.stringify(buildGeminiLiveSetupMessage(wire))));
|
|
64
|
+
return { wire, setup, wroteTools: builtins.map((builtin) => builtin.id) };
|
|
65
|
+
}
|
|
66
|
+
/** One server message's events, then the stop its turn phase calls for. */
|
|
67
|
+
function* batch(events, phase, handle) {
|
|
68
|
+
// why: usage first, so a turn's tokens are counted before its stop.
|
|
69
|
+
const ordered = [
|
|
70
|
+
...events.filter((event) => event.type === 'tokens'),
|
|
71
|
+
...events.filter((event) => event.type !== 'tokens'),
|
|
72
|
+
];
|
|
73
|
+
for (const event of ordered) {
|
|
74
|
+
const converted = asProtocolEvent(event);
|
|
75
|
+
if (converted)
|
|
76
|
+
yield converted;
|
|
77
|
+
}
|
|
78
|
+
if (phase === 'abort')
|
|
79
|
+
return;
|
|
80
|
+
const saved = handle ? { state: { liveHandle: handle } } : {};
|
|
81
|
+
if (events.some((event) => event.type === 'tool' && event.tool.phase === undefined))
|
|
82
|
+
yield { type: 'done', stop: { kind: 'tool' }, ...saved };
|
|
83
|
+
if (phase === 'complete')
|
|
84
|
+
yield { type: 'done', stop: { kind: 'completed' }, ...saved };
|
|
85
|
+
}
|
|
86
|
+
function session(socket, frames, context, resumedFrom) {
|
|
87
|
+
const send = (frame) => sendFrame(socket, frame);
|
|
88
|
+
const fold = newLiveFold();
|
|
89
|
+
let handle = resumedFrom;
|
|
90
|
+
let goAway;
|
|
91
|
+
let closed;
|
|
92
|
+
return {
|
|
93
|
+
closeInfo: () => closed,
|
|
94
|
+
async *events() {
|
|
95
|
+
for (;;) {
|
|
96
|
+
const next = await frames.next();
|
|
97
|
+
if (next.done)
|
|
98
|
+
return;
|
|
99
|
+
const frame = next.value;
|
|
100
|
+
if (frame.eventType === 'ws_close') {
|
|
101
|
+
context.signal?.throwIfAborted();
|
|
102
|
+
const code = Number(frame.code);
|
|
103
|
+
const reason = String(frame.reason ?? '');
|
|
104
|
+
closed = {
|
|
105
|
+
code,
|
|
106
|
+
reason,
|
|
107
|
+
...(code === NORMAL_CLOSE ? {} : { error: closeError(code, reason, 'session') }),
|
|
108
|
+
...(goAway
|
|
109
|
+
? {
|
|
110
|
+
warning: {
|
|
111
|
+
...(goAway.timeLeftMs === undefined ? {} : { timeLeftMs: goAway.timeLeftMs }),
|
|
112
|
+
closedAfterMs: Math.round(performance.now() - goAway.atMs),
|
|
113
|
+
},
|
|
114
|
+
}
|
|
115
|
+
: {}),
|
|
116
|
+
};
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const trouble = socketTrouble(frame, 'session');
|
|
120
|
+
if (trouble)
|
|
121
|
+
throw trouble;
|
|
122
|
+
if (frame.setupComplete)
|
|
123
|
+
continue;
|
|
124
|
+
const events = foldGeminiLiveServerMessage(frame, fold);
|
|
125
|
+
const warning = goAwayIn(events);
|
|
126
|
+
if (warning)
|
|
127
|
+
goAway = { ...warning, atMs: performance.now() };
|
|
128
|
+
for (const event of events)
|
|
129
|
+
if (event.type === 'evidence' && event.sessionResumptionHandle)
|
|
130
|
+
handle = event.sessionResumptionHandle;
|
|
131
|
+
yield* batch(events, turnPhaseFromMessage(frame, events), handle);
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
sendText: (text) => settled(() => send(buildGeminiLiveRealtimeInput({ type: 'text', text }))),
|
|
135
|
+
sendAudio: (media) => settled(() => send(buildGeminiLiveRealtimeInput({ type: 'audio', ...media }))),
|
|
136
|
+
sendVideo: (media) => settled(() => send(buildGeminiLiveRealtimeInput({ type: 'video', ...media }))),
|
|
137
|
+
sendContext: (value) => settled(() => send(buildGeminiLiveContext(typeof value.server === 'string' ? value.server : JSON.stringify(value)))),
|
|
138
|
+
sendToolResult: (result) => settled(() => send(buildGeminiLiveToolResponse(result.callId, result.name, result.text, result.parts))),
|
|
139
|
+
close: (reason) => settled(() => socket.close(NORMAL_CLOSE, reason ?? 'session-closed')),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/** Gemini Live: a spoken session over one WebSocket. */
|
|
143
|
+
export const geminiLive = defineProtocol({
|
|
144
|
+
id: 'geminiLive',
|
|
145
|
+
name: 'Gemini Live',
|
|
146
|
+
description: "Google's Live API for Gemini: a spoken session over one WebSocket.", // labels-exempt: builder field description, read by the studio and docs
|
|
147
|
+
endpoints: { live: '/google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent' },
|
|
148
|
+
options: z.strictObject({}),
|
|
149
|
+
continuation: { version: 1, schema: state },
|
|
150
|
+
create(context) {
|
|
151
|
+
return {
|
|
152
|
+
async openSession(request) {
|
|
153
|
+
const { wire, setup, wroteTools } = wireRequest(context, request);
|
|
154
|
+
const socket = await context.connect(setup, { wroteTools });
|
|
155
|
+
const frames = socket.frames()[Symbol.asyncIterator]();
|
|
156
|
+
const abort = () => socket.close(NORMAL_CLOSE, 'aborted');
|
|
157
|
+
context.signal?.addEventListener('abort', abort, { once: true });
|
|
158
|
+
try {
|
|
159
|
+
context.signal?.throwIfAborted();
|
|
160
|
+
await setupComplete(frames, context);
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
context.signal?.removeEventListener('abort', abort);
|
|
164
|
+
socket.close(NORMAL_CLOSE, 'setup-failed');
|
|
165
|
+
throw error;
|
|
166
|
+
}
|
|
167
|
+
const history = wire.history?.length
|
|
168
|
+
? buildGeminiLiveClientContent(wire.history)
|
|
169
|
+
: undefined;
|
|
170
|
+
if (history)
|
|
171
|
+
sendFrame(socket, history);
|
|
172
|
+
for (const part of wire.input)
|
|
173
|
+
sendFrame(socket, buildGeminiLiveRealtimeInput(part));
|
|
174
|
+
return session(socket, frames, context, wire.sessionResumptionHandle);
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
/** A send that throws becomes a rejected promise, as the session's callers expect. */
|
|
180
|
+
function settled(act) {
|
|
181
|
+
try {
|
|
182
|
+
act();
|
|
183
|
+
return Promise.resolve();
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
return Promise.reject(error);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
function sendFrame(socket, frame) {
|
|
190
|
+
socket.send(frame, liveFrameInput(frame));
|
|
191
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/* probed 2026-10-15: https://ai.google.dev/gemini-api/docs/pricing, paid tier, US dollars per
|
|
2
|
+
* million tokens. The Gemini API reports no cost. gemini-3.8-flash rises to $1.50 input and $7.50
|
|
3
|
+
* output on 2027-01-01. Cached input is one rate here, so gemini-3.1-flash-lite's cached audio
|
|
4
|
+
* ($0.05) is billed at its cached text rate. Gemma, gemini-3.7-flash and gemini-3.5-flash list no paid price;
|
|
5
|
+
* gemini-2.5-flash-image's output is all image, $30 per million tokens.
|
|
6
|
+
*/
|
|
7
|
+
const live = {
|
|
8
|
+
input: 0.75,
|
|
9
|
+
output: 4.5,
|
|
10
|
+
byModality: { input: { audio: 3, image: 1, video: 1 }, output: { audio: 12 } },
|
|
11
|
+
};
|
|
12
|
+
/** What the Gemini API charges per model. */
|
|
13
|
+
export const geminiPrices = {
|
|
14
|
+
checked: '2026-10-15',
|
|
15
|
+
models: {
|
|
16
|
+
'gemini-3.8-flash': { input: 0.75, output: 3.75, cachedInput: 0.075 },
|
|
17
|
+
'gemini-3.6-flash': { input: 0.75, output: 3.75, cachedInput: 0.075 },
|
|
18
|
+
'gemini-3.8-live': live,
|
|
19
|
+
'gemini-3.8-live-extended-thinking': live,
|
|
20
|
+
'gemini-3.1-flash-live-preview': live,
|
|
21
|
+
'gemini-3.5-flash-lite': { input: 0.3, output: 2.5, cachedInput: 0.03 },
|
|
22
|
+
'gemini-3.1-flash-lite': {
|
|
23
|
+
input: 0.25,
|
|
24
|
+
output: 1.5,
|
|
25
|
+
cachedInput: 0.025,
|
|
26
|
+
byModality: { input: { audio: 0.5 } },
|
|
27
|
+
},
|
|
28
|
+
'gemini-3.1-pro-preview': {
|
|
29
|
+
input: 2,
|
|
30
|
+
output: 12,
|
|
31
|
+
cachedInput: 0.2,
|
|
32
|
+
longContext: { above: 200_000, input: 4, output: 18, cachedInput: 0.4 },
|
|
33
|
+
},
|
|
34
|
+
'gemini-3.1-flash-lite-image': {
|
|
35
|
+
input: 0.25,
|
|
36
|
+
output: 1.5,
|
|
37
|
+
byModality: { output: { image: 30 } },
|
|
38
|
+
},
|
|
39
|
+
'gemini-3.8-flash-tts': { input: 0.5, output: 9 },
|
|
40
|
+
'gemini-3.8-flash-lite-tts': { input: 0.5, output: 6 },
|
|
41
|
+
'gemini-3.1-flash-tts-preview': { input: 1, output: 20 },
|
|
42
|
+
'gemini-3-flash-preview': {
|
|
43
|
+
input: 0.5,
|
|
44
|
+
output: 3,
|
|
45
|
+
cachedInput: 0.05,
|
|
46
|
+
byModality: { input: { audio: 1 } },
|
|
47
|
+
},
|
|
48
|
+
'gemini-2.5-flash': {
|
|
49
|
+
input: 0.3,
|
|
50
|
+
output: 2.5,
|
|
51
|
+
cachedInput: 0.03,
|
|
52
|
+
byModality: { input: { audio: 1 } },
|
|
53
|
+
},
|
|
54
|
+
'gemini-2.5-flash-lite': {
|
|
55
|
+
input: 0.1,
|
|
56
|
+
output: 0.4,
|
|
57
|
+
cachedInput: 0.01,
|
|
58
|
+
byModality: { input: { audio: 0.3 } },
|
|
59
|
+
},
|
|
60
|
+
'gemini-2.5-flash-preview-tts': { input: 0.5, output: 10 },
|
|
61
|
+
'gemini-2.5-flash-image': { input: 0.3, output: 30 },
|
|
62
|
+
},
|
|
63
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type Provider } from '../../kernel/protocols/provider.js';
|
|
2
|
+
/** What registering `geminiProvider` takes as `connection`. */
|
|
3
|
+
export interface GeminiConnection {
|
|
4
|
+
host?: string;
|
|
5
|
+
}
|
|
6
|
+
/** Gemini: Google's models with an API key. Text, images, and speech, and Live voice. */
|
|
7
|
+
export declare const geminiProvider: Provider<GeminiConnection, string>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { labelText } from '../../guardrails/labels.js';
|
|
3
|
+
import { defineProvider, endpointUrlSchema, header, query, } from '../../kernel/protocols/provider.js';
|
|
4
|
+
import { geminiEmbedding } from './embedding-protocol.js';
|
|
5
|
+
import { geminiInteractions } from './interactions-protocol.js';
|
|
6
|
+
import { geminiLive } from './live-protocol.js';
|
|
7
|
+
import { geminiPrices } from './prices.js';
|
|
8
|
+
/** Gemini: Google's models with an API key. Text, images, and speech, and Live voice. */
|
|
9
|
+
export const geminiProvider = defineProvider({
|
|
10
|
+
id: 'gemini',
|
|
11
|
+
name: 'Gemini',
|
|
12
|
+
description: "Google's models with an API key, from Google AI Studio.", // labels-exempt: builder field description, read by the studio and docs
|
|
13
|
+
traceName: 'gcp.gemini',
|
|
14
|
+
connection: z
|
|
15
|
+
.strictObject({
|
|
16
|
+
host: endpointUrlSchema
|
|
17
|
+
.refine((value) => {
|
|
18
|
+
const url = new URL(value);
|
|
19
|
+
return url.pathname === '/' && !url.search && !url.hash;
|
|
20
|
+
}, labelText('protocol.endpoint_host'))
|
|
21
|
+
.optional()
|
|
22
|
+
.describe('The API host, by default https://generativelanguage.googleapis.com. Live connects to the same host over wss.'),
|
|
23
|
+
})
|
|
24
|
+
.default({}),
|
|
25
|
+
key: z.string().trim().min(1),
|
|
26
|
+
authorize: header('x-goog-api-key'),
|
|
27
|
+
prices: geminiPrices,
|
|
28
|
+
serves(at) {
|
|
29
|
+
const host = new URL(at.host ?? 'https://generativelanguage.googleapis.com');
|
|
30
|
+
const origin = host.origin;
|
|
31
|
+
const liveOrigin = `${host.protocol === 'http:' ? 'ws:' : 'wss:'}//${host.host}`;
|
|
32
|
+
return [
|
|
33
|
+
{ protocol: geminiInteractions, baseUrl: `${origin}/v1beta` },
|
|
34
|
+
{ protocol: geminiEmbedding, baseUrl: `${origin}/v1beta` },
|
|
35
|
+
// probed 2026-09-23: Live's WebSocket takes the key only in the URL's query.
|
|
36
|
+
{ protocol: geminiLive, baseUrl: `${liveOrigin}/ws`, authorize: query('key') },
|
|
37
|
+
];
|
|
38
|
+
},
|
|
39
|
+
});
|
|
@@ -6,3 +6,5 @@ import { TheoremError } from '../../guardrails/error.js';
|
|
|
6
6
|
export declare function readGeminiApiError(record: Record<string, unknown>): TheoremError | null;
|
|
7
7
|
/** The kind is the HTTP status's, unless the body names a refused key. */
|
|
8
8
|
export declare function readNonOkError(response: Response): Promise<TheoremError>;
|
|
9
|
+
/** A non-OK reply's error: the body's own when it names a refused key, else the status's with the body's message. */
|
|
10
|
+
export declare function statedOrStatusError(stated: TheoremError | null, status: number, fallback: string): TheoremError;
|
|
@@ -72,13 +72,15 @@ const BLOCKED_CODES = new Set([
|
|
|
72
72
|
* codes (`malformed_function_call`, `no_image`, …) and any code Google adds later
|
|
73
73
|
* are `bad_response`.
|
|
74
74
|
*/
|
|
75
|
-
function
|
|
75
|
+
function namedCodeError(code, message) {
|
|
76
76
|
if (code === 'cancelled')
|
|
77
|
-
return 'cancelled';
|
|
77
|
+
return new TheoremError('cancelled', message);
|
|
78
78
|
if (BLOCKED_CODES.has(code))
|
|
79
|
-
return 'safety';
|
|
79
|
+
return new TheoremError('safety', message);
|
|
80
80
|
const status = NAMED_CODE_STATUS[code];
|
|
81
|
-
return status === undefined
|
|
81
|
+
return status === undefined
|
|
82
|
+
? new TheoremError('bad_response', message)
|
|
83
|
+
: new TheoremError(kindOfHttpStatus(status), message);
|
|
82
84
|
}
|
|
83
85
|
/**
|
|
84
86
|
* Interactions (SSE `error` rows, non-OK bodies) and Live (error frames) both send
|
|
@@ -90,28 +92,34 @@ export function readGeminiApiError(record) {
|
|
|
90
92
|
return null;
|
|
91
93
|
}
|
|
92
94
|
const { code, message, status, details } = error;
|
|
93
|
-
const
|
|
94
|
-
? '
|
|
95
|
-
: typeof
|
|
96
|
-
?
|
|
97
|
-
:
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if (typeof
|
|
101
|
-
return new TheoremError(
|
|
95
|
+
const text = typeof message !== 'string' || message.length === 0
|
|
96
|
+
? 'Gemini returned an error.'
|
|
97
|
+
: typeof status === 'string'
|
|
98
|
+
? `${status}: ${message}`
|
|
99
|
+
: message;
|
|
100
|
+
if (refusesKey(details))
|
|
101
|
+
return new TheoremError('auth', text);
|
|
102
|
+
if (typeof code === 'number' && code >= HTTP_STATUS_MIN && code <= HTTP_STATUS_MAX) {
|
|
103
|
+
return new TheoremError(kindOfHttpStatus(code), text);
|
|
102
104
|
}
|
|
103
|
-
return
|
|
105
|
+
return typeof code === 'string'
|
|
106
|
+
? namedCodeError(code, text)
|
|
107
|
+
: new TheoremError('bad_response', text);
|
|
104
108
|
}
|
|
105
109
|
/** The kind is the HTTP status's, unless the body names a refused key. */
|
|
106
110
|
export async function readNonOkError(response) {
|
|
107
|
-
const kind = kindOfHttpStatus(response.status);
|
|
108
111
|
const text = await response.text().catch(() => '');
|
|
109
112
|
if (!text.trim()) {
|
|
110
|
-
return new TheoremError(
|
|
113
|
+
return new TheoremError(kindOfHttpStatus(response.status), `HTTP ${response.status}`);
|
|
111
114
|
}
|
|
112
115
|
const parsed = parseRecord(text);
|
|
113
|
-
|
|
114
|
-
|
|
116
|
+
return statedOrStatusError(parsed ? readGeminiApiError(parsed) : null, response.status, `Gemini HTTP ${response.status}: ${text}`);
|
|
117
|
+
}
|
|
118
|
+
/** A non-OK reply's error: the body's own when it names a refused key, else the status's with the body's message. */
|
|
119
|
+
export function statedOrStatusError(stated, status, fallback) {
|
|
120
|
+
if (stated?.kind === 'auth')
|
|
121
|
+
return stated;
|
|
122
|
+
return new TheoremError(kindOfHttpStatus(status), stated?.message ?? fallback);
|
|
115
123
|
}
|
|
116
124
|
function parseRecord(text) {
|
|
117
125
|
try {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The tools Gemini runs itself, and how each is sent on Interactions and on Live, with what it
|
|
3
|
+
* takes from a request's `builtInArgs`.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
import type { ProviderBuiltin } from '../../kernel/types.js';
|
|
8
|
+
/** The request's builtins that are Google's own tools; the wire takes no others. */
|
|
9
|
+
declare function googleBuiltins<B extends ProviderBuiltin>(builtins: readonly B[]): B[];
|
|
10
|
+
/** One builtin as an Interactions `tools` entry. */
|
|
11
|
+
declare function interactionsBuiltinTool(builtin: ProviderBuiltin): Record<string, unknown>;
|
|
12
|
+
/** One builtin as a Live setup `tools` entry. Live takes no args for any of them. */
|
|
13
|
+
declare function liveBuiltinTool(builtin: ProviderBuiltin): Record<string, unknown>;
|
|
14
|
+
export { googleBuiltins, interactionsBuiltinTool, liveBuiltinTool };
|