@theoremjs/agents 0.3.0 → 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/README.md +276 -995
- package/esm/mod.d.ts +33 -19
- package/esm/mod.js +18 -11
- 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 +23 -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 +874 -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 +29 -21
- package/esm/src/guardrails/mod.js +18 -13
- 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 +1 -0
- package/esm/src/guardrails/quota.js +1 -1
- 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 +4 -1
- package/esm/src/guardrails/theorem-error.js +3 -2
- 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 +7 -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 +173 -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 +328 -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 +128 -87
- 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 +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/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 +3 -209
- 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 +17 -0
- package/esm/src/providers/shared/retry.js +90 -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,189 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { kindOfHttpStatus, TheoremError } from '../../guardrails/error.js';
|
|
3
|
+
import { asRecord } from '../../kernel/engine/record.js';
|
|
4
|
+
import { defineProtocol, } from '../../kernel/protocols/mod.js';
|
|
5
|
+
import { turnStopFromOpenAiFinishReason } from '../../kernel/stop.js';
|
|
6
|
+
import { base64ToBytes, bytesToBase64 } from '../../kernel/util/base64.js';
|
|
7
|
+
import { mimeEssence } from '../../kernel/util/mime.js';
|
|
8
|
+
import { buildChatMessages, resolveResponseFormat, wireTools, } from '../openrouter/openai/compat.js';
|
|
9
|
+
import { openAiResponse, openAiUsageTokens } from '../openrouter/openai/usage.js';
|
|
10
|
+
import { pcmFormatFromMime, wrapPcmAsWav } from '../shared/pcm.js';
|
|
11
|
+
import { asProtocolEvent } from '../shared/protocol-events.js';
|
|
12
|
+
import { foldResponse } from '../shared/response-identity.js';
|
|
13
|
+
import { structuredEvent } from '../shared/structured-output.js';
|
|
14
|
+
import { toolCallEvents } from '../shared/tool-args.js';
|
|
15
|
+
import { toolDraftEvents } from '../shared/tool-draft.js';
|
|
16
|
+
/** Old-shape events from the shared helpers, as protocol events. */
|
|
17
|
+
function asProtocolEvents(events) {
|
|
18
|
+
return events.flatMap((event) => asProtocolEvent(event) ?? []);
|
|
19
|
+
}
|
|
20
|
+
function requestBody(context, request) {
|
|
21
|
+
const stream = request.stream !== false;
|
|
22
|
+
const tools = wireTools(request.wireTools);
|
|
23
|
+
const format = resolveResponseFormat(request.structured);
|
|
24
|
+
const body = {
|
|
25
|
+
model: context.apiId,
|
|
26
|
+
// why: replayed reasoning belongs to the protocol that wrote it, never to plain Chat Completions.
|
|
27
|
+
messages: buildChatMessages(request),
|
|
28
|
+
stream,
|
|
29
|
+
...(stream ? { stream_options: { include_usage: true } } : {}),
|
|
30
|
+
...(request.temperature === undefined ? {} : { temperature: request.temperature }),
|
|
31
|
+
...(request.maxOutputTokens === undefined ? {} : { max_tokens: request.maxOutputTokens }),
|
|
32
|
+
...(request.thinking ? { reasoning_effort: request.thinking } : {}),
|
|
33
|
+
...(format ? { response_format: format } : {}),
|
|
34
|
+
// probed 2026-10-09: an empty `tools` list counts as a parameter the model must support, so OpenRouter refuses models without tool calling.
|
|
35
|
+
...(tools ? { tools } : {}),
|
|
36
|
+
};
|
|
37
|
+
return JSON.parse(JSON.stringify(body));
|
|
38
|
+
}
|
|
39
|
+
/** An error row inside a 200 reply: thrown, so a quota refusal before any output can still fall back. */
|
|
40
|
+
function errorRow(row) {
|
|
41
|
+
const error = asRecord(row.error);
|
|
42
|
+
if (!error)
|
|
43
|
+
return;
|
|
44
|
+
const status = typeof error.code === 'number' ? error.code : 502;
|
|
45
|
+
const message = typeof error.message === 'string' ? error.message : JSON.stringify(error);
|
|
46
|
+
throw new TheoremError(kindOfHttpStatus(status), message);
|
|
47
|
+
}
|
|
48
|
+
function citations(part, reply) {
|
|
49
|
+
const sources = (Array.isArray(part.annotations) ? part.annotations : []).flatMap((item) => {
|
|
50
|
+
const cited = asRecord(asRecord(item)?.url_citation);
|
|
51
|
+
if (typeof cited?.url !== 'string' || reply.cited.has(cited.url))
|
|
52
|
+
return [];
|
|
53
|
+
reply.cited.add(cited.url);
|
|
54
|
+
const title = typeof cited.title === 'string' && cited.title ? cited.title : cited.url;
|
|
55
|
+
return [{ title, uri: cited.url, type: 'web' }];
|
|
56
|
+
});
|
|
57
|
+
return sources.length ? [{ type: 'citation', sources }] : [];
|
|
58
|
+
}
|
|
59
|
+
function mergeCalls(part, reply) {
|
|
60
|
+
for (const [position, value] of (Array.isArray(part.tool_calls)
|
|
61
|
+
? part.tool_calls
|
|
62
|
+
: []).entries()) {
|
|
63
|
+
const call = asRecord(value);
|
|
64
|
+
const fn = asRecord(call?.function);
|
|
65
|
+
const index = typeof call?.index === 'number' ? call.index : position;
|
|
66
|
+
const current = reply.calls.get(index) ?? { name: '', args: '' };
|
|
67
|
+
if (typeof call?.id === 'string' && call.id)
|
|
68
|
+
current.id = call.id;
|
|
69
|
+
if (typeof fn?.name === 'string')
|
|
70
|
+
current.name += fn.name;
|
|
71
|
+
if (typeof fn?.arguments === 'string')
|
|
72
|
+
current.args += fn.arguments;
|
|
73
|
+
reply.calls.set(index, current);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/** One choice's delta (streamed) or message (whole). */
|
|
77
|
+
function partEvents(part, reply, request) {
|
|
78
|
+
const events = [];
|
|
79
|
+
const thought = part.reasoning ?? part.reasoning_content;
|
|
80
|
+
if (typeof thought === 'string' && thought && request.summaries !== 'none')
|
|
81
|
+
events.push({ type: 'thought', text: thought });
|
|
82
|
+
if (typeof part.content === 'string' && part.content) {
|
|
83
|
+
reply.text += part.content;
|
|
84
|
+
events.push({ type: 'text', text: part.content });
|
|
85
|
+
}
|
|
86
|
+
events.push(...citations(part, reply));
|
|
87
|
+
mergeCalls(part, reply);
|
|
88
|
+
return events;
|
|
89
|
+
}
|
|
90
|
+
function rowEvents(row, reply, request, stream) {
|
|
91
|
+
errorRow(row);
|
|
92
|
+
const events = [];
|
|
93
|
+
const identity = foldResponse(reply.response, openAiResponse(row));
|
|
94
|
+
reply.response = identity.known;
|
|
95
|
+
if (identity.event)
|
|
96
|
+
events.push(identity.event);
|
|
97
|
+
const tokens = reply.tokens ? undefined : openAiUsageTokens(row.usage);
|
|
98
|
+
if (tokens) {
|
|
99
|
+
reply.tokens = true;
|
|
100
|
+
events.push({ type: 'tokens', tokens });
|
|
101
|
+
}
|
|
102
|
+
for (const item of Array.isArray(row.choices) ? row.choices : []) {
|
|
103
|
+
const choice = asRecord(item);
|
|
104
|
+
const part = asRecord(stream ? choice?.delta : choice?.message);
|
|
105
|
+
if (part)
|
|
106
|
+
events.push(...partEvents(part, reply, request));
|
|
107
|
+
if (typeof choice?.finish_reason === 'string')
|
|
108
|
+
reply.finish = choice.finish_reason;
|
|
109
|
+
// why: gateways add the upstream's own reason beside it; it tells a provider failure from a stop.
|
|
110
|
+
if (typeof choice?.native_finish_reason === 'string')
|
|
111
|
+
reply.native = choice.native_finish_reason;
|
|
112
|
+
}
|
|
113
|
+
// why: a whole reply carries each call complete; only a streamed one has a draft to show.
|
|
114
|
+
if (stream)
|
|
115
|
+
for (const call of reply.calls.values())
|
|
116
|
+
events.push(...asProtocolEvents(toolDraftEvents(call)));
|
|
117
|
+
return events;
|
|
118
|
+
}
|
|
119
|
+
/** The calls, the structured reply, and the stop, once the rows are done. */
|
|
120
|
+
function endEvents(reply, request) {
|
|
121
|
+
const events = [];
|
|
122
|
+
// why: some compatible servers end a tool-calling reply with `stop`, so the calls go out whatever the finish.
|
|
123
|
+
for (const [index, call] of reply.calls)
|
|
124
|
+
events.push(...asProtocolEvents(toolCallEvents({ ...call, id: call.id ?? `call_${index}` }, call.args)));
|
|
125
|
+
const stop = turnStopFromOpenAiFinishReason(reply.finish, reply.native);
|
|
126
|
+
if (request.structured && reply.text && stop.kind === 'completed') {
|
|
127
|
+
const structured = asProtocolEvents([structuredEvent(reply.text)]);
|
|
128
|
+
events.push(...structured);
|
|
129
|
+
if (structured[0]?.type === 'error')
|
|
130
|
+
return events;
|
|
131
|
+
}
|
|
132
|
+
events.push({ type: 'done', stop });
|
|
133
|
+
return events;
|
|
134
|
+
}
|
|
135
|
+
/** `/audio/speech`: the input's text read aloud, answered whole. Raw PCM with a stated rate becomes WAV. */
|
|
136
|
+
async function* speech(context, request) {
|
|
137
|
+
const text = request.input
|
|
138
|
+
.flatMap((part) => (part.type === 'text' ? [part.text] : []))
|
|
139
|
+
.join(' ')
|
|
140
|
+
.trim();
|
|
141
|
+
if (!text)
|
|
142
|
+
throw new TheoremError('request', 'empty text for speech');
|
|
143
|
+
const spec = request.speech;
|
|
144
|
+
const body = {
|
|
145
|
+
model: context.apiId,
|
|
146
|
+
input: text,
|
|
147
|
+
...(spec?.format ? { response_format: spec.format } : {}),
|
|
148
|
+
...(spec?.voice ? { voice: spec.voice } : {}),
|
|
149
|
+
...(spec?.speed === undefined ? {} : { speed: spec.speed }),
|
|
150
|
+
// why: `instructions` is the endpoint's own field for delivery, never read aloud (probe 07/10/2026: Gemini 3.8 slowed and sped by it).
|
|
151
|
+
...(spec?.style ? { instructions: spec.style } : {}),
|
|
152
|
+
};
|
|
153
|
+
for await (const row of context.send(body, { stream: false })) {
|
|
154
|
+
const type = typeof row.mime_type === 'string' ? row.mime_type : '';
|
|
155
|
+
const bytes = typeof row.data === 'string' ? base64ToBytes(row.data) : new Uint8Array();
|
|
156
|
+
if (!bytes.length)
|
|
157
|
+
throw new TheoremError('bad_response', 'no audio returned from speech');
|
|
158
|
+
const pcm = pcmFormatFromMime(type);
|
|
159
|
+
const media = pcm
|
|
160
|
+
? { mimeType: 'audio/wav', data: bytesToBase64(wrapPcmAsWav(bytes, pcm)) }
|
|
161
|
+
: { mimeType: mimeEssence(type) || 'application/octet-stream', data: row.data };
|
|
162
|
+
yield { type: 'media', media };
|
|
163
|
+
// why: the endpoint answers whole or not at all: a body with audio completed.
|
|
164
|
+
yield { type: 'done', stop: { kind: 'completed' } };
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/** OpenAI Chat Completions: the shape most compatible servers speak. */
|
|
168
|
+
export const openAi = defineProtocol({
|
|
169
|
+
id: 'openAi',
|
|
170
|
+
name: 'OpenAI Chat Completions',
|
|
171
|
+
description: 'The Chat Completions shape that OpenAI and most compatible servers speak.', // labels-exempt: builder field description, read by the studio and docs
|
|
172
|
+
endpoints: { text: '/chat/completions', speech: '/audio/speech' },
|
|
173
|
+
options: z.strictObject({}),
|
|
174
|
+
create(context) {
|
|
175
|
+
return {
|
|
176
|
+
async *complete(request) {
|
|
177
|
+
if (context.profileType === 'speech') {
|
|
178
|
+
yield* speech(context, request);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const stream = request.stream !== false;
|
|
182
|
+
const reply = { text: '', tokens: false, cited: new Set(), calls: new Map() };
|
|
183
|
+
for await (const row of context.send(requestBody(context, request), { stream }))
|
|
184
|
+
yield* rowEvents(row, reply, request, stream);
|
|
185
|
+
yield* endEvents(reply, request);
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
},
|
|
189
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type Protocol } from '../../kernel/protocols/mod.js';
|
|
2
|
+
/** What an `openRouterEmbedding` binding sets in `options`. */
|
|
3
|
+
export interface OpenRouterEmbeddingOptions {
|
|
4
|
+
encodingFormat?: 'float' | 'base64';
|
|
5
|
+
}
|
|
6
|
+
export declare const openRouterEmbedding: Protocol<OpenRouterEmbeddingOptions>;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { defineProtocol, } from '../../kernel/protocols/mod.js';
|
|
3
|
+
import { base64ToBytes } from '../../kernel/util/base64.js';
|
|
4
|
+
const options = z.strictObject({
|
|
5
|
+
encodingFormat: z
|
|
6
|
+
.enum(['float', 'base64'])
|
|
7
|
+
.optional()
|
|
8
|
+
.describe('How OpenRouter sends each vector back: as a list of numbers (`float`) or packed into a base64 string (`base64`, smaller on the wire). Theorem decodes both to the same numbers. Absent: `float`.'),
|
|
9
|
+
});
|
|
10
|
+
// why: OpenRouter's embeddings reference takes images only and caps neither inputs nor images per input; a text-only model refuses an image itself.
|
|
11
|
+
const LIMITS = { media: [{ accept: ['image/*'] }] };
|
|
12
|
+
/** A string stays a string; a multimodal input is one `{ content }` item, as OpenRouter documents. */
|
|
13
|
+
function inputValue(input) {
|
|
14
|
+
if (typeof input === 'string')
|
|
15
|
+
return input;
|
|
16
|
+
return {
|
|
17
|
+
content: input.parts.map((part) => {
|
|
18
|
+
if (part.type === 'text')
|
|
19
|
+
return { type: 'text', text: part.text };
|
|
20
|
+
const url = part.type === 'media' ? `data:${part.mimeType};base64,${part.data}` : part.uri;
|
|
21
|
+
return { type: 'image_url', image_url: { url } };
|
|
22
|
+
}),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function embeddingValues(value) {
|
|
26
|
+
if (Array.isArray(value)) {
|
|
27
|
+
if (!value.every((entry) => typeof entry === 'number' && Number.isFinite(entry))) {
|
|
28
|
+
throw new Error('OpenRouter returned an embedding with a non-finite value');
|
|
29
|
+
}
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
if (typeof value !== 'string') {
|
|
33
|
+
throw new Error('OpenRouter returned an embedding in an unsupported format');
|
|
34
|
+
}
|
|
35
|
+
const bytes = base64ToBytes(value);
|
|
36
|
+
if (bytes.byteLength % Float32Array.BYTES_PER_ELEMENT !== 0) {
|
|
37
|
+
throw new Error('OpenRouter returned an invalid base64 embedding length');
|
|
38
|
+
}
|
|
39
|
+
return Array.from(new Float32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / Float32Array.BYTES_PER_ELEMENT));
|
|
40
|
+
}
|
|
41
|
+
export const openRouterEmbedding = defineProtocol({
|
|
42
|
+
id: 'openRouterEmbedding',
|
|
43
|
+
name: 'OpenRouter Embeddings',
|
|
44
|
+
description: 'OpenRouter embedding models, including supported multimodal models.',
|
|
45
|
+
endpoints: { embedding: '/embeddings' },
|
|
46
|
+
options,
|
|
47
|
+
embeddingLimits: () => LIMITS,
|
|
48
|
+
create(context) {
|
|
49
|
+
return {
|
|
50
|
+
async embed(request) {
|
|
51
|
+
const parsed = options.parse(request.options ?? {});
|
|
52
|
+
const inputs = Array.isArray(request.input) ? request.input : [request.input];
|
|
53
|
+
const body = {
|
|
54
|
+
model: context.apiId,
|
|
55
|
+
input: inputs.length === 1 && typeof inputs[0] === 'string'
|
|
56
|
+
? inputs[0]
|
|
57
|
+
: inputs.map(inputValue),
|
|
58
|
+
};
|
|
59
|
+
if (parsed.encodingFormat)
|
|
60
|
+
body.encoding_format = parsed.encodingFormat;
|
|
61
|
+
let row;
|
|
62
|
+
for await (const current of context.send(body, { stream: false }))
|
|
63
|
+
row = current;
|
|
64
|
+
const data = Array.isArray(row?.data) ? row.data : [];
|
|
65
|
+
const usage = row?.usage && typeof row.usage === 'object'
|
|
66
|
+
? row.usage
|
|
67
|
+
: undefined;
|
|
68
|
+
return {
|
|
69
|
+
model: typeof row?.model === 'string' ? row.model : context.apiId,
|
|
70
|
+
embeddings: data.map((item, position) => {
|
|
71
|
+
const record = item && typeof item === 'object' ? item : {};
|
|
72
|
+
const values = embeddingValues(record.embedding);
|
|
73
|
+
return {
|
|
74
|
+
index: typeof record.index === 'number' ? record.index : position,
|
|
75
|
+
values,
|
|
76
|
+
dimensions: values.length,
|
|
77
|
+
};
|
|
78
|
+
}),
|
|
79
|
+
...(typeof usage?.prompt_tokens === 'number'
|
|
80
|
+
? { usage: { inputTokens: usage.prompt_tokens } }
|
|
81
|
+
: {}),
|
|
82
|
+
};
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
},
|
|
86
|
+
});
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import type { ModelProvider, ProviderCompleteRequest, ProviderEvent } from '../../kernel/types.js';
|
|
2
|
-
import type { OpenAiGatewayTransport } from '../types.js';
|
|
3
1
|
export declare const OPENROUTER_IMAGE_TOOL = "openrouter:image_generation";
|
|
4
|
-
export type ImageProviderConfig = OpenAiGatewayTransport;
|
|
5
|
-
export declare function buildImageHeaders(apiKey: string, config: ImageProviderConfig): Record<string, string>;
|
|
6
2
|
/** `/images` answers `data[]` of `b64_json` + `media_type` (probe 23/09/2026, bytedance-seed/seedream-4.5). */
|
|
7
3
|
export declare function imagesFromImagesBody(body: Record<string, unknown>): {
|
|
8
4
|
mimeType: string;
|
|
@@ -17,8 +13,3 @@ export declare function imagesFromChatMessage(message: Record<string, unknown>):
|
|
|
17
13
|
mimeType: string;
|
|
18
14
|
data: string;
|
|
19
15
|
}[];
|
|
20
|
-
export declare function buildInterleavedChatPayload(req: ProviderCompleteRequest): Record<string, unknown>;
|
|
21
|
-
export declare function yieldInterleavedChat(req: ProviderCompleteRequest, config: ImageProviderConfig, apiKey: string): AsyncGenerator<ProviderEvent>;
|
|
22
|
-
export declare function yieldImagesEndpoint(req: ProviderCompleteRequest, config: ImageProviderConfig, apiKey: string): AsyncGenerator<ProviderEvent>;
|
|
23
|
-
export declare function streamImage(req: ProviderCompleteRequest, config?: ImageProviderConfig): AsyncGenerator<ProviderEvent>;
|
|
24
|
-
export declare function createImageProvider(config?: ImageProviderConfig): ModelProvider;
|
|
@@ -1,35 +1,5 @@
|
|
|
1
|
-
import { TheoremError, toErrorEvent } from '../../guardrails/error.js';
|
|
2
1
|
import { asRecord, nonEmptyString } from '../../kernel/engine/record.js';
|
|
3
|
-
import { turnStopFromOpenAiFinishReason } from '../../kernel/stop.js';
|
|
4
|
-
import { networkFetch } from '../shared/upstream-tap.js';
|
|
5
|
-
import { bearerFetch } from '../shared/vault.js';
|
|
6
|
-
import { buildChatMessages, httpErrorEvent, openAiGatewayHeaders } from './openai/compat.js';
|
|
7
|
-
import { buildImagesPayload, extractPromptText, imageToolParameters, } from './openai/image-payload.js';
|
|
8
|
-
import { openAiUsageTokens } from './openai/usage.js';
|
|
9
|
-
import { resolveOpenAiGatewayApiKey } from './resolve-api-key.js';
|
|
10
|
-
const HTTP_OK = 200;
|
|
11
2
|
export const OPENROUTER_IMAGE_TOOL = 'openrouter:image_generation';
|
|
12
|
-
export function buildImageHeaders(apiKey, config) {
|
|
13
|
-
const headers = {
|
|
14
|
-
Authorization: `Bearer ${apiKey}`,
|
|
15
|
-
'Content-Type': 'application/json',
|
|
16
|
-
};
|
|
17
|
-
const gateway = openAiGatewayHeaders(config);
|
|
18
|
-
if (gateway) {
|
|
19
|
-
Object.assign(headers, gateway);
|
|
20
|
-
}
|
|
21
|
-
return headers;
|
|
22
|
-
}
|
|
23
|
-
function baseUrl(config) {
|
|
24
|
-
return config.baseUrl?.replace(/\/+$/, '') ?? 'https://openrouter.ai/api/v1';
|
|
25
|
-
}
|
|
26
|
-
function* yieldUsage(raw) {
|
|
27
|
-
const tokens = openAiUsageTokens(raw);
|
|
28
|
-
if (!tokens) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
yield { type: 'tokens', tokens };
|
|
32
|
-
}
|
|
33
3
|
/** `/images` answers `data[]` of `b64_json` + `media_type` (probe 23/09/2026, bytedance-seed/seedream-4.5). */
|
|
34
4
|
export function imagesFromImagesBody(body) {
|
|
35
5
|
const entries = Array.isArray(body.data) ? body.data : [];
|
|
@@ -62,126 +32,3 @@ export function imagesFromChatMessage(message) {
|
|
|
62
32
|
return media ? [media] : [];
|
|
63
33
|
});
|
|
64
34
|
}
|
|
65
|
-
async function postJson(req, config, apiKey, path, body) {
|
|
66
|
-
const fetchFn = bearerFetch(req, networkFetch(config.fetch ?? fetch), config.vault, apiKey);
|
|
67
|
-
return await fetchFn(`${baseUrl(config)}${path}`, {
|
|
68
|
-
method: 'POST',
|
|
69
|
-
headers: buildImageHeaders(apiKey, config),
|
|
70
|
-
body: JSON.stringify(body),
|
|
71
|
-
signal: req.signal,
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
async function readTapedJson(req, res) {
|
|
75
|
-
const body = (await res.json());
|
|
76
|
-
req.tapUpstream?.(body);
|
|
77
|
-
return body;
|
|
78
|
-
}
|
|
79
|
-
async function requestImages(req, config, apiKey) {
|
|
80
|
-
return await postJson(req, config, apiKey, '/images', buildImagesPayload(req));
|
|
81
|
-
}
|
|
82
|
-
export function buildInterleavedChatPayload(req) {
|
|
83
|
-
if (!req.image) {
|
|
84
|
-
throw new Error('buildInterleavedChatPayload requires req.image');
|
|
85
|
-
}
|
|
86
|
-
return {
|
|
87
|
-
model: req.apiId,
|
|
88
|
-
stream: false,
|
|
89
|
-
messages: buildChatMessages(req),
|
|
90
|
-
temperature: req.temperature,
|
|
91
|
-
max_tokens: req.maxOutputTokens,
|
|
92
|
-
...(req.thinking ? { reasoning: { effort: req.thinking } } : {}),
|
|
93
|
-
tools: [
|
|
94
|
-
{
|
|
95
|
-
type: OPENROUTER_IMAGE_TOOL,
|
|
96
|
-
parameters: imageToolParameters(req.image),
|
|
97
|
-
},
|
|
98
|
-
],
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
async function requestInterleavedChat(req, config, apiKey) {
|
|
102
|
-
return await postJson(req, config, apiKey, '/chat/completions', buildInterleavedChatPayload(req));
|
|
103
|
-
}
|
|
104
|
-
export async function* yieldInterleavedChat(req, config, apiKey) {
|
|
105
|
-
const res = await requestInterleavedChat(req, config, apiKey);
|
|
106
|
-
if (res.status !== HTTP_OK) {
|
|
107
|
-
yield await httpErrorEvent(res, 'Image chat');
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
const body = await readTapedJson(req, res);
|
|
111
|
-
const choices = body.choices;
|
|
112
|
-
if (!Array.isArray(choices) || choices.length === 0) {
|
|
113
|
-
yield toErrorEvent(new TheoremError('bad_response', 'no chat choices returned for image generation'));
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
const choice = asRecord(choices[0]);
|
|
117
|
-
const message = asRecord(choice?.message);
|
|
118
|
-
if (!message) {
|
|
119
|
-
yield toErrorEvent(new TheoremError('bad_response', 'no assistant message returned for image generation'));
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
const text = nonEmptyString(message.content);
|
|
123
|
-
if (text) {
|
|
124
|
-
yield { type: 'text', text };
|
|
125
|
-
}
|
|
126
|
-
const images = imagesFromChatMessage(message);
|
|
127
|
-
if (images.length === 0) {
|
|
128
|
-
yield toErrorEvent(new TheoremError('bad_response', 'no image returned from chat image generation'));
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
for (const media of images) {
|
|
132
|
-
yield { type: 'media', media };
|
|
133
|
-
}
|
|
134
|
-
yield* yieldUsage(body.usage);
|
|
135
|
-
yield {
|
|
136
|
-
type: 'done',
|
|
137
|
-
stop: turnStopFromOpenAiFinishReason(typeof choice?.finish_reason === 'string' ? choice.finish_reason : undefined, typeof choice?.native_finish_reason === 'string' ? choice.native_finish_reason : undefined),
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
export async function* yieldImagesEndpoint(req, config, apiKey) {
|
|
141
|
-
const res = await requestImages(req, config, apiKey);
|
|
142
|
-
if (res.status !== HTTP_OK) {
|
|
143
|
-
yield await httpErrorEvent(res, 'Image');
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
const body = await readTapedJson(req, res);
|
|
147
|
-
const images = imagesFromImagesBody(body);
|
|
148
|
-
if (images.length === 0) {
|
|
149
|
-
yield toErrorEvent(new TheoremError('bad_response', 'no image returned from image generation'));
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
for (const media of images) {
|
|
153
|
-
yield { type: 'media', media };
|
|
154
|
-
}
|
|
155
|
-
yield* yieldUsage(body.usage);
|
|
156
|
-
// The endpoint answers whole or not at all: a body with images completed.
|
|
157
|
-
yield { type: 'done', stop: { kind: 'completed' } };
|
|
158
|
-
}
|
|
159
|
-
export async function* streamImage(req, config = {}) {
|
|
160
|
-
let apiKey;
|
|
161
|
-
try {
|
|
162
|
-
apiKey = resolveOpenAiGatewayApiKey(config, req.keySlot);
|
|
163
|
-
}
|
|
164
|
-
catch (err) {
|
|
165
|
-
yield toErrorEvent(err);
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
if (!req.image) {
|
|
169
|
-
yield toErrorEvent(new TheoremError('request', 'missing image response format'));
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
const prompt = extractPromptText(req.input);
|
|
173
|
-
if (!prompt) {
|
|
174
|
-
yield toErrorEvent(new TheoremError('request', 'empty text for image generation'));
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
if (req.image.includeText) {
|
|
178
|
-
yield* yieldInterleavedChat(req, config, apiKey);
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
yield* yieldImagesEndpoint(req, config, apiKey);
|
|
182
|
-
}
|
|
183
|
-
export function createImageProvider(config = {}) {
|
|
184
|
-
return {
|
|
185
|
-
complete: (req) => streamImage(req, config),
|
|
186
|
-
};
|
|
187
|
-
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { TheoremError } from '../../guardrails/error.js';
|
|
3
|
+
import { asRecord, nonEmptyString } from '../../kernel/engine/record.js';
|
|
4
|
+
import { defineProtocol, } from '../../kernel/protocols/mod.js';
|
|
5
|
+
import { turnStopFromOpenAiFinishReason } from '../../kernel/stop.js';
|
|
6
|
+
import { imagesFromChatMessage, imagesFromImagesBody, OPENROUTER_IMAGE_TOOL } from './image.js';
|
|
7
|
+
import { buildChatMessages } from './openai/compat.js';
|
|
8
|
+
import { buildImagesPayload, extractPromptText, imageToolParameters, } from './openai/image-payload.js';
|
|
9
|
+
import { openAiUsageTokens } from './openai/usage.js';
|
|
10
|
+
function json(value) {
|
|
11
|
+
return JSON.parse(JSON.stringify(value));
|
|
12
|
+
}
|
|
13
|
+
function tokens(row) {
|
|
14
|
+
const counted = openAiUsageTokens(row.usage);
|
|
15
|
+
return counted ? [{ type: 'tokens', tokens: counted }] : [];
|
|
16
|
+
}
|
|
17
|
+
function noImage() {
|
|
18
|
+
return new TheoremError('bad_response', 'no image returned from image generation');
|
|
19
|
+
}
|
|
20
|
+
/** `/images`: the picture alone, answered whole. */
|
|
21
|
+
async function* images(context, request) {
|
|
22
|
+
const body = json(buildImagesPayload({ ...request, apiId: context.apiId }));
|
|
23
|
+
for await (const row of context.send(body, { stream: false })) {
|
|
24
|
+
const media = imagesFromImagesBody(row);
|
|
25
|
+
if (!media.length)
|
|
26
|
+
throw noImage();
|
|
27
|
+
for (const item of media)
|
|
28
|
+
yield { type: 'media', media: item };
|
|
29
|
+
yield* tokens(row);
|
|
30
|
+
// why: the endpoint answers whole or not at all: a body with images completed.
|
|
31
|
+
yield { type: 'done', stop: { kind: 'completed' } };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** Text with the picture: Chat Completions with OpenRouter's image tool, on the chat path. */
|
|
35
|
+
async function* withText(context, request, image) {
|
|
36
|
+
const body = json({
|
|
37
|
+
model: context.apiId,
|
|
38
|
+
stream: false,
|
|
39
|
+
provider: { require_parameters: true },
|
|
40
|
+
messages: buildChatMessages(request),
|
|
41
|
+
temperature: request.temperature,
|
|
42
|
+
max_tokens: request.maxOutputTokens,
|
|
43
|
+
...(request.thinking ? { reasoning: { effort: request.thinking } } : {}),
|
|
44
|
+
tools: [{ type: OPENROUTER_IMAGE_TOOL, parameters: imageToolParameters(image) }],
|
|
45
|
+
});
|
|
46
|
+
for await (const row of context.send(body, { stream: false, path: '/chat/completions' })) {
|
|
47
|
+
const choice = asRecord(Array.isArray(row.choices) ? row.choices[0] : undefined);
|
|
48
|
+
const message = asRecord(choice?.message);
|
|
49
|
+
const text = nonEmptyString(message?.content);
|
|
50
|
+
if (text)
|
|
51
|
+
yield { type: 'text', text };
|
|
52
|
+
const media = message ? imagesFromChatMessage(message) : [];
|
|
53
|
+
if (!media.length)
|
|
54
|
+
throw noImage();
|
|
55
|
+
for (const item of media)
|
|
56
|
+
yield { type: 'media', media: item };
|
|
57
|
+
yield* tokens(row);
|
|
58
|
+
const finish = typeof choice?.finish_reason === 'string' ? choice.finish_reason : undefined;
|
|
59
|
+
const native = typeof choice?.native_finish_reason === 'string' ? choice.native_finish_reason : undefined;
|
|
60
|
+
yield { type: 'done', stop: turnStopFromOpenAiFinishReason(finish, native) };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/** OpenRouter's image generation: `/images`, or the chat path with its image tool when text is wanted too. */
|
|
64
|
+
export const openRouterImages = defineProtocol({
|
|
65
|
+
id: 'openRouterImages',
|
|
66
|
+
name: 'OpenRouter Images',
|
|
67
|
+
description: "OpenRouter's image generation, with or without text beside the picture.", // labels-exempt: builder field description, read by the studio and docs
|
|
68
|
+
endpoints: { image: '/images' },
|
|
69
|
+
options: z.strictObject({}),
|
|
70
|
+
create(context) {
|
|
71
|
+
return {
|
|
72
|
+
complete(request) {
|
|
73
|
+
const image = request.image;
|
|
74
|
+
if (!image)
|
|
75
|
+
throw new TheoremError('request', 'missing image response format');
|
|
76
|
+
if (!extractPromptText(request.input))
|
|
77
|
+
throw new TheoremError('request', 'empty text for image generation');
|
|
78
|
+
return image.includeText ? withText(context, request, image) : images(context, request);
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
},
|
|
82
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ProducedError } from '../../../guardrails/error.js';
|
|
2
|
-
import type { InteractionPart,
|
|
2
|
+
import type { InteractionPart, ModelRequest, ResolvedStructured, WireFunctionTool } from '../../../kernel/types.js';
|
|
3
3
|
/** The detail is the body's `error.message` (or raw text), so the upstream reason reaches traces. */
|
|
4
4
|
declare function httpErrorEvent(res: Response, label: string): Promise<ProducedError>;
|
|
5
5
|
interface GatewayHeaderConfig {
|
|
@@ -9,7 +9,7 @@ interface GatewayHeaderConfig {
|
|
|
9
9
|
/** Text-only input collapses to one string; mixed input is a content-part array. */
|
|
10
10
|
export declare function wireMessageContent(parts: InteractionPart[]): unknown;
|
|
11
11
|
/** `includeSystem: false` when the caller passes system text separately (AI SDK `instructions`). */
|
|
12
|
-
declare function buildChatMessages(req:
|
|
12
|
+
declare function buildChatMessages(req: Pick<ModelRequest, 'system' | 'history' | 'input'>, options?: {
|
|
13
13
|
includeSystem?: boolean;
|
|
14
14
|
}): Record<string, unknown>[];
|
|
15
15
|
declare function wireTools(wireTools?: WireFunctionTool[]): Record<string, unknown>[] | undefined;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { kindOfHttpStatus, TheoremError, toErrorEvent, } from '../../../guardrails/error.js';
|
|
2
2
|
import { asRecord } from '../../../kernel/engine/record.js';
|
|
3
3
|
import { historyMessageParts, isMediaRefPart } from '../../../kernel/interaction-parts.js';
|
|
4
|
+
import { withCarriedToolFiles } from '../../shared/carried-tool-files.js';
|
|
4
5
|
import { historyToolIdentity } from '../../shared/tool-args.js';
|
|
5
6
|
/** The detail is the body's `error.message` (or raw text), so the upstream reason reaches traces. */
|
|
6
7
|
async function httpErrorEvent(res, label) {
|
|
@@ -12,7 +13,7 @@ async function httpErrorEvent(res, label) {
|
|
|
12
13
|
detail = message;
|
|
13
14
|
}
|
|
14
15
|
catch {
|
|
15
|
-
// Not JSON: the raw body is the detail.
|
|
16
|
+
// why: Not JSON: the raw body is the detail.
|
|
16
17
|
}
|
|
17
18
|
const head = `${label} HTTP ${String(res.status)}`;
|
|
18
19
|
return toErrorEvent(new TheoremError(kindOfHttpStatus(res.status), detail ? `${head}: ${detail}` : head));
|
|
@@ -63,7 +64,6 @@ export function wireMessageContent(parts) {
|
|
|
63
64
|
if (part.type === 'audio') {
|
|
64
65
|
return wireAudioPart(part);
|
|
65
66
|
}
|
|
66
|
-
// video and document ride as a `file` part.
|
|
67
67
|
return {
|
|
68
68
|
type: 'file',
|
|
69
69
|
file: {
|
|
@@ -99,6 +99,8 @@ function wireHistoryMessage(msg) {
|
|
|
99
99
|
}
|
|
100
100
|
return wired;
|
|
101
101
|
}
|
|
102
|
+
// why: A PDF inside a `role: 'tool'` message was accepted and never read, and was read from the user message after it; a photo inside one was read (live, 13/10/2026, google/gemini-3.5-flash-lite).
|
|
103
|
+
const TOOL_MESSAGE_PART_TYPES = new Set(['text', 'image']);
|
|
102
104
|
/** `includeSystem: false` when the caller passes system text separately (AI SDK `instructions`). */
|
|
103
105
|
function buildChatMessages(req, options) {
|
|
104
106
|
const includeSystem = options?.includeSystem !== false;
|
|
@@ -106,10 +108,8 @@ function buildChatMessages(req, options) {
|
|
|
106
108
|
if (includeSystem && req.system) {
|
|
107
109
|
messages.push({ role: 'system', content: req.system });
|
|
108
110
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
messages.push(wireHistoryMessage(h));
|
|
112
|
-
}
|
|
111
|
+
for (const h of withCarriedToolFiles(req.history ?? [], TOOL_MESSAGE_PART_TYPES)) {
|
|
112
|
+
messages.push(wireHistoryMessage(h));
|
|
113
113
|
}
|
|
114
114
|
if (req.input.length > 0) {
|
|
115
115
|
messages.push({
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { ImageResponseFormat, InteractionMediaPart, InteractionMediaRefPart, InteractionPart,
|
|
1
|
+
import type { ImageResponseFormat, InteractionMediaPart, InteractionMediaRefPart, InteractionPart, ModelRequest } from '../../../kernel/types.js';
|
|
2
2
|
export declare function extractPromptText(input: InteractionPart[]): string;
|
|
3
3
|
export declare function outputFormatFromMime(mimeType: string): string;
|
|
4
4
|
export declare function wireInputReference(part: InteractionMediaPart | InteractionMediaRefPart): Record<string, unknown>;
|
|
5
5
|
/** Non-image media is refused, not dropped: a dropped file would leave the user believing the model saw it. */
|
|
6
6
|
export declare function wireInputReferences(input: InteractionPart[]): Record<string, unknown>[];
|
|
7
7
|
export declare function attachImagePins(payload: Record<string, unknown>, image: ImageResponseFormat): void;
|
|
8
|
-
export declare function buildImagesPayload(req:
|
|
8
|
+
export declare function buildImagesPayload(req: ModelRequest): Record<string, unknown>;
|
|
9
9
|
export declare function imageToolParameters(image: ImageResponseFormat): Record<string, unknown>;
|