@theoremjs/agents 0.0.0-stage → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +545 -2
- package/esm/_dnt.polyfills.d.ts +66 -0
- package/esm/_dnt.polyfills.js +51 -0
- package/esm/mod.d.ts +79 -0
- package/esm/mod.js +49 -0
- package/esm/package.json +3 -0
- package/esm/src/cli/bin.d.ts +7 -0
- package/esm/src/cli/bin.js +9 -0
- package/esm/src/cli/commands/bench.d.ts +6 -0
- package/esm/src/cli/commands/bench.js +480 -0
- package/esm/src/cli/commands/detect-compile.d.ts +17 -0
- package/esm/src/cli/commands/detect-compile.js +22 -0
- package/esm/src/cli/commands/eval.d.ts +37 -0
- package/esm/src/cli/commands/eval.js +190 -0
- package/esm/src/cli/commands/fuzz-canary.d.ts +15 -0
- package/esm/src/cli/commands/fuzz-canary.js +241 -0
- package/esm/src/cli/commands/fuzz-guardrails.d.ts +2 -0
- package/esm/src/cli/commands/fuzz-guardrails.js +5 -0
- package/esm/src/cli/commands/profile.d.ts +2 -0
- package/esm/src/cli/commands/profile.js +80 -0
- package/esm/src/cli/commands/run.d.ts +13 -0
- package/esm/src/cli/commands/run.js +45 -0
- package/esm/src/cli/commands/test.d.ts +26 -0
- package/esm/src/cli/commands/test.js +143 -0
- package/esm/src/cli/event-log.d.ts +15 -0
- package/esm/src/cli/event-log.js +136 -0
- package/esm/src/cli/index.d.ts +10 -0
- package/esm/src/cli/index.js +267 -0
- package/esm/src/cli/matrix/fixtures.d.ts +10 -0
- package/esm/src/cli/matrix/fixtures.js +67 -0
- package/esm/src/cli/matrix/synthesizer.d.ts +18 -0
- package/esm/src/cli/matrix/synthesizer.js +103 -0
- package/esm/src/evals/attachments.d.ts +5 -0
- package/esm/src/evals/attachments.js +55 -0
- package/esm/src/evals/breakdown.d.ts +30 -0
- package/esm/src/evals/breakdown.js +69 -0
- package/esm/src/evals/graders/answer.d.ts +16 -0
- package/esm/src/evals/graders/answer.js +134 -0
- package/esm/src/evals/graders/code.d.ts +40 -0
- package/esm/src/evals/graders/code.js +184 -0
- package/esm/src/evals/graders/judge.d.ts +24 -0
- package/esm/src/evals/graders/judge.js +367 -0
- package/esm/src/evals/graders/latency.d.ts +6 -0
- package/esm/src/evals/graders/latency.js +82 -0
- package/esm/src/evals/graders/live.d.ts +14 -0
- package/esm/src/evals/graders/live.js +42 -0
- package/esm/src/evals/graders/media.d.ts +18 -0
- package/esm/src/evals/graders/media.js +91 -0
- package/esm/src/evals/graders/shared.d.ts +11 -0
- package/esm/src/evals/graders/shared.js +62 -0
- package/esm/src/evals/graders/transcript.d.ts +19 -0
- package/esm/src/evals/graders/transcript.js +202 -0
- package/esm/src/evals/mod.d.ts +34 -0
- package/esm/src/evals/mod.js +22 -0
- package/esm/src/evals/record.d.ts +41 -0
- package/esm/src/evals/record.js +107 -0
- package/esm/src/evals/rubrics/catalog.d.ts +148 -0
- package/esm/src/evals/rubrics/catalog.js +846 -0
- package/esm/src/evals/rubrics/mod.d.ts +24 -0
- package/esm/src/evals/rubrics/mod.js +55 -0
- package/esm/src/evals/rubrics/mustache.d.ts +23 -0
- package/esm/src/evals/rubrics/mustache.js +154 -0
- package/esm/src/evals/rubrics/types.d.ts +54 -0
- package/esm/src/evals/rubrics/types.js +74 -0
- package/esm/src/evals/run.d.ts +75 -0
- package/esm/src/evals/run.js +418 -0
- package/esm/src/evals/suite.d.ts +28 -0
- package/esm/src/evals/suite.js +97 -0
- package/esm/src/evals/summary.d.ts +35 -0
- package/esm/src/evals/summary.js +31 -0
- package/esm/src/evals/trial.d.ts +14 -0
- package/esm/src/evals/trial.js +135 -0
- package/esm/src/evals/types.d.ts +169 -0
- package/esm/src/evals/types.js +113 -0
- package/esm/src/evals/verdict.d.ts +23 -0
- package/esm/src/evals/verdict.js +48 -0
- package/esm/src/guardrails/boundaries.d.ts +41 -0
- package/esm/src/guardrails/boundaries.js +103 -0
- package/esm/src/guardrails/canary-gate.d.ts +22 -0
- package/esm/src/guardrails/canary-gate.js +40 -0
- package/esm/src/guardrails/canary.d.ts +146 -0
- package/esm/src/guardrails/canary.js +974 -0
- package/esm/src/guardrails/compile-egress.d.ts +12 -0
- package/esm/src/guardrails/compile-egress.js +12 -0
- package/esm/src/guardrails/corpus/canary-egress-attacks.d.ts +24 -0
- package/esm/src/guardrails/corpus/canary-egress-attacks.js +305 -0
- package/esm/src/guardrails/corpus/fuzz-inbound.d.ts +5 -0
- package/esm/src/guardrails/corpus/fuzz-inbound.js +199 -0
- package/esm/src/guardrails/corpus/inbound-payloads.d.ts +5 -0
- package/esm/src/guardrails/corpus/inbound-payloads.js +120 -0
- package/esm/src/guardrails/corpus/live-attacks.d.ts +15 -0
- package/esm/src/guardrails/corpus/live-attacks.js +229 -0
- package/esm/src/guardrails/corpus/mod.d.ts +7 -0
- package/esm/src/guardrails/corpus/mod.js +4 -0
- package/esm/src/guardrails/corpus/secrets.d.ts +12 -0
- package/esm/src/guardrails/corpus/secrets.js +16 -0
- package/esm/src/guardrails/corpus/strings.d.ts +23 -0
- package/esm/src/guardrails/corpus/strings.js +29 -0
- package/esm/src/guardrails/corpus/types.d.ts +36 -0
- package/esm/src/guardrails/corpus/types.js +1 -0
- package/esm/src/guardrails/credential-rules.d.ts +36 -0
- package/esm/src/guardrails/credential-rules.js +3001 -0
- package/esm/src/guardrails/credential-scan.d.ts +45 -0
- package/esm/src/guardrails/credential-scan.js +172 -0
- package/esm/src/guardrails/destinations.d.ts +45 -0
- package/esm/src/guardrails/destinations.js +234 -0
- package/esm/src/guardrails/detect-at.d.ts +107 -0
- package/esm/src/guardrails/detect-at.js +434 -0
- package/esm/src/guardrails/detect-reply.d.ts +61 -0
- package/esm/src/guardrails/detect-reply.js +95 -0
- package/esm/src/guardrails/detect-stream.d.ts +33 -0
- package/esm/src/guardrails/detect-stream.js +77 -0
- package/esm/src/guardrails/detectors.d.ts +216 -0
- package/esm/src/guardrails/detectors.js +503 -0
- package/esm/src/guardrails/egress-automata.d.ts +12 -0
- package/esm/src/guardrails/egress-automata.js +25582 -0
- package/esm/src/guardrails/egress-compiler.d.ts +55 -0
- package/esm/src/guardrails/egress-compiler.js +431 -0
- package/esm/src/guardrails/egress-patterns.d.ts +26 -0
- package/esm/src/guardrails/egress-patterns.js +36 -0
- package/esm/src/guardrails/egress-stream.d.ts +123 -0
- package/esm/src/guardrails/egress-stream.js +774 -0
- package/esm/src/guardrails/egress-urls.d.ts +86 -0
- package/esm/src/guardrails/egress-urls.js +909 -0
- package/esm/src/guardrails/egress.d.ts +46 -0
- package/esm/src/guardrails/egress.js +124 -0
- package/esm/src/guardrails/error.d.ts +31 -0
- package/esm/src/guardrails/error.js +96 -0
- package/esm/src/guardrails/event-schemas.d.ts +100 -0
- package/esm/src/guardrails/event-schemas.js +48 -0
- package/esm/src/guardrails/events.d.ts +13 -0
- package/esm/src/guardrails/events.js +45 -0
- package/esm/src/guardrails/hints.d.ts +14 -0
- package/esm/src/guardrails/hints.js +57 -0
- package/esm/src/guardrails/hits.d.ts +14 -0
- package/esm/src/guardrails/hits.js +30 -0
- package/esm/src/guardrails/host-patterns.d.ts +85 -0
- package/esm/src/guardrails/host-patterns.js +173 -0
- package/esm/src/guardrails/injection-patterns.d.ts +20 -0
- package/esm/src/guardrails/injection-patterns.js +126 -0
- package/esm/src/guardrails/injection-reversed.d.ts +9 -0
- package/esm/src/guardrails/injection-reversed.js +49 -0
- package/esm/src/guardrails/injection.d.ts +30 -0
- package/esm/src/guardrails/injection.js +460 -0
- package/esm/src/guardrails/labels.d.ts +40 -0
- package/esm/src/guardrails/labels.js +874 -0
- package/esm/src/guardrails/live-outbound-gate.d.ts +55 -0
- package/esm/src/guardrails/live-outbound-gate.js +298 -0
- package/esm/src/guardrails/mod.d.ts +54 -0
- package/esm/src/guardrails/mod.js +34 -0
- package/esm/src/guardrails/network.d.ts +46 -0
- package/esm/src/guardrails/network.js +330 -0
- package/esm/src/guardrails/normalize.d.ts +20 -0
- package/esm/src/guardrails/normalize.js +165 -0
- package/esm/src/guardrails/policy.d.ts +4 -0
- package/esm/src/guardrails/policy.js +21 -0
- package/esm/src/guardrails/progressive-yield.d.ts +110 -0
- package/esm/src/guardrails/progressive-yield.js +281 -0
- package/esm/src/guardrails/prompt-echo.d.ts +40 -0
- package/esm/src/guardrails/prompt-echo.js +306 -0
- package/esm/src/guardrails/quota.d.ts +21 -0
- package/esm/src/guardrails/quota.js +80 -0
- package/esm/src/guardrails/rules.d.ts +47 -0
- package/esm/src/guardrails/rules.js +47 -0
- package/esm/src/guardrails/sanitize.d.ts +40 -0
- package/esm/src/guardrails/sanitize.js +160 -0
- package/esm/src/guardrails/sensitive-groups.d.ts +21 -0
- package/esm/src/guardrails/sensitive-groups.js +12 -0
- package/esm/src/guardrails/sensitive.d.ts +22 -0
- package/esm/src/guardrails/sensitive.js +234 -0
- package/esm/src/guardrails/serialize.d.ts +15 -0
- package/esm/src/guardrails/serialize.js +37 -0
- package/esm/src/guardrails/testing.d.ts +11 -0
- package/esm/src/guardrails/testing.js +10 -0
- package/esm/src/guardrails/theorem-error.d.ts +21 -0
- package/esm/src/guardrails/theorem-error.js +54 -0
- package/esm/src/guardrails/thought-guard.d.ts +76 -0
- package/esm/src/guardrails/thought-guard.js +664 -0
- package/esm/src/guardrails/tool-directives.d.ts +38 -0
- package/esm/src/guardrails/tool-directives.js +195 -0
- package/esm/src/guardrails/tool-leak.d.ts +26 -0
- package/esm/src/guardrails/tool-leak.js +45 -0
- package/esm/src/guardrails/tool-result.d.ts +92 -0
- package/esm/src/guardrails/tool-result.js +272 -0
- package/esm/src/guardrails/types.d.ts +250 -0
- package/esm/src/guardrails/types.js +58 -0
- package/esm/src/host/client-turn.d.ts +36 -0
- package/esm/src/host/client-turn.js +80 -0
- package/esm/src/host/mint-trace.d.ts +29 -0
- package/esm/src/host/mint-trace.js +60 -0
- package/esm/src/host/mod.d.ts +13 -0
- package/esm/src/host/mod.js +11 -0
- package/esm/src/host/readStreamingJsonStringField.d.ts +2 -0
- package/esm/src/host/readStreamingJsonStringField.js +27 -0
- package/esm/src/host/reply.d.ts +13 -0
- package/esm/src/host/reply.js +41 -0
- package/esm/src/interface/blocks.d.ts +11 -0
- package/esm/src/interface/blocks.js +283 -0
- package/esm/src/interface/composer-actions.d.ts +24 -0
- package/esm/src/interface/composer-actions.js +33 -0
- package/esm/src/interface/draft.d.ts +20 -0
- package/esm/src/interface/draft.js +39 -0
- package/esm/src/interface/from-profile.d.ts +24 -0
- package/esm/src/interface/from-profile.js +179 -0
- package/esm/src/interface/history.d.ts +46 -0
- package/esm/src/interface/history.js +278 -0
- package/esm/src/interface/inputs.d.ts +11 -0
- package/esm/src/interface/inputs.js +67 -0
- package/esm/src/interface/mod.d.ts +33 -0
- package/esm/src/interface/mod.js +22 -0
- package/esm/src/interface/models.d.ts +26 -0
- package/esm/src/interface/models.js +50 -0
- package/esm/src/interface/pending.d.ts +57 -0
- package/esm/src/interface/pending.js +152 -0
- package/esm/src/interface/profile-interface.d.ts +4 -0
- package/esm/src/interface/profile-interface.js +237 -0
- package/esm/src/interface/session.d.ts +71 -0
- package/esm/src/interface/session.js +128 -0
- package/esm/src/interface/stop.d.ts +13 -0
- package/esm/src/interface/stop.js +28 -0
- package/esm/src/interface/tool-calls.d.ts +32 -0
- package/esm/src/interface/tool-calls.js +127 -0
- package/esm/src/interface/tool-invoke.d.ts +6 -0
- package/esm/src/interface/tool-invoke.js +22 -0
- package/esm/src/interface/tool-media.d.ts +11 -0
- package/esm/src/interface/tool-media.js +113 -0
- package/esm/src/interface/types.d.ts +278 -0
- package/esm/src/interface/types.js +5 -0
- package/esm/src/kernel/api-catalog.d.ts +85 -0
- package/esm/src/kernel/api-catalog.js +229 -0
- package/esm/src/kernel/auth/credential-source.d.ts +23 -0
- package/esm/src/kernel/auth/credential-source.js +11 -0
- package/esm/src/kernel/auth/crypto.d.ts +56 -0
- package/esm/src/kernel/auth/crypto.js +163 -0
- package/esm/src/kernel/auth/mod.d.ts +5 -0
- package/esm/src/kernel/auth/mod.js +5 -0
- package/esm/src/kernel/auth/oauth.d.ts +18 -0
- package/esm/src/kernel/auth/oauth.js +439 -0
- package/esm/src/kernel/auth/scope-refusal.d.ts +9 -0
- package/esm/src/kernel/auth/scope-refusal.js +8 -0
- package/esm/src/kernel/auth/typed-secret.d.ts +13 -0
- package/esm/src/kernel/auth/typed-secret.js +23 -0
- package/esm/src/kernel/auth/types.d.ts +152 -0
- package/esm/src/kernel/auth/types.js +1 -0
- package/esm/src/kernel/checkpoint.d.ts +43 -0
- package/esm/src/kernel/checkpoint.js +58 -0
- package/esm/src/kernel/default-scope.d.ts +72 -0
- package/esm/src/kernel/default-scope.js +121 -0
- package/esm/src/kernel/engine/call-trace.d.ts +19 -0
- package/esm/src/kernel/engine/call-trace.js +29 -0
- package/esm/src/kernel/engine/compaction.d.ts +71 -0
- package/esm/src/kernel/engine/compaction.js +203 -0
- package/esm/src/kernel/engine/decision.d.ts +43 -0
- package/esm/src/kernel/engine/decision.js +439 -0
- package/esm/src/kernel/engine/embedding.d.ts +8 -0
- package/esm/src/kernel/engine/embedding.js +118 -0
- package/esm/src/kernel/engine/hash.d.ts +6 -0
- package/esm/src/kernel/engine/hash.js +22 -0
- package/esm/src/kernel/engine/live-inbound.d.ts +19 -0
- package/esm/src/kernel/engine/live-inbound.js +44 -0
- package/esm/src/kernel/engine/live-ingress.d.ts +15 -0
- package/esm/src/kernel/engine/live-ingress.js +42 -0
- package/esm/src/kernel/engine/record.d.ts +3 -0
- package/esm/src/kernel/engine/record.js +11 -0
- package/esm/src/kernel/engine/repair.d.ts +7 -0
- package/esm/src/kernel/engine/repair.js +36 -0
- package/esm/src/kernel/engine/runner/gates.d.ts +5 -0
- package/esm/src/kernel/engine/runner/gates.js +508 -0
- package/esm/src/kernel/engine/runner/mod.d.ts +29 -0
- package/esm/src/kernel/engine/runner/mod.js +625 -0
- package/esm/src/kernel/engine/runner/nested.d.ts +32 -0
- package/esm/src/kernel/engine/runner/nested.js +134 -0
- package/esm/src/kernel/engine/runner/schema-validation.d.ts +35 -0
- package/esm/src/kernel/engine/runner/schema-validation.js +179 -0
- package/esm/src/kernel/engine/runner/stages.d.ts +28 -0
- package/esm/src/kernel/engine/runner/stages.js +41 -0
- package/esm/src/kernel/engine/runner/state.d.ts +97 -0
- package/esm/src/kernel/engine/runner/state.js +50 -0
- package/esm/src/kernel/engine/runner/step-order.d.ts +27 -0
- package/esm/src/kernel/engine/runner/step-order.js +165 -0
- package/esm/src/kernel/engine/runner/steps.d.ts +14 -0
- package/esm/src/kernel/engine/runner/steps.js +519 -0
- package/esm/src/kernel/engine/runner/stream.d.ts +71 -0
- package/esm/src/kernel/engine/runner/stream.js +376 -0
- package/esm/src/kernel/engine/runner/usage.d.ts +45 -0
- package/esm/src/kernel/engine/runner/usage.js +148 -0
- package/esm/src/kernel/engine/session/mod.d.ts +33 -0
- package/esm/src/kernel/engine/session/mod.js +1182 -0
- package/esm/src/kernel/engine/session/session-trace.d.ts +115 -0
- package/esm/src/kernel/engine/session/session-trace.js +500 -0
- package/esm/src/kernel/engine/token-estimate.d.ts +23 -0
- package/esm/src/kernel/engine/token-estimate.js +38 -0
- package/esm/src/kernel/engine/tool-trace.d.ts +58 -0
- package/esm/src/kernel/engine/tool-trace.js +132 -0
- package/esm/src/kernel/engine/tree.d.ts +2 -0
- package/esm/src/kernel/engine/tree.js +17 -0
- package/esm/src/kernel/engine/turn-trace.d.ts +119 -0
- package/esm/src/kernel/engine/turn-trace.js +855 -0
- package/esm/src/kernel/engine/usage.d.ts +36 -0
- package/esm/src/kernel/engine/usage.js +151 -0
- package/esm/src/kernel/interaction-parts.d.ts +13 -0
- package/esm/src/kernel/interaction-parts.js +40 -0
- package/esm/src/kernel/json.d.ts +10 -0
- package/esm/src/kernel/json.js +3 -0
- package/esm/src/kernel/mod.d.ts +74 -0
- package/esm/src/kernel/mod.js +45 -0
- package/esm/src/kernel/profile-graph.d.ts +145 -0
- package/esm/src/kernel/profile-graph.js +158 -0
- package/esm/src/kernel/profile-presence.d.ts +18 -0
- package/esm/src/kernel/profile-presence.js +158 -0
- package/esm/src/kernel/profile-scope.d.ts +40 -0
- package/esm/src/kernel/profile-scope.js +274 -0
- package/esm/src/kernel/protocols/binding.d.ts +65 -0
- package/esm/src/kernel/protocols/binding.js +125 -0
- package/esm/src/kernel/protocols/limits.d.ts +15 -0
- package/esm/src/kernel/protocols/limits.js +28 -0
- package/esm/src/kernel/protocols/mod.d.ts +5 -0
- package/esm/src/kernel/protocols/mod.js +5 -0
- package/esm/src/kernel/protocols/prices.d.ts +36 -0
- package/esm/src/kernel/protocols/prices.js +37 -0
- package/esm/src/kernel/protocols/protocol.d.ts +253 -0
- package/esm/src/kernel/protocols/protocol.js +253 -0
- package/esm/src/kernel/protocols/provider.d.ts +108 -0
- package/esm/src/kernel/protocols/provider.js +143 -0
- package/esm/src/kernel/protocols/runtime.d.ts +55 -0
- package/esm/src/kernel/protocols/runtime.js +534 -0
- package/esm/src/kernel/provider-budget.d.ts +32 -0
- package/esm/src/kernel/provider-budget.js +262 -0
- package/esm/src/kernel/provider-dispatch.d.ts +13 -0
- package/esm/src/kernel/provider-dispatch.js +36 -0
- package/esm/src/kernel/provider-live.d.ts +7 -0
- package/esm/src/kernel/provider-live.js +189 -0
- package/esm/src/kernel/provider-runtime.d.ts +57 -0
- package/esm/src/kernel/provider-runtime.js +524 -0
- package/esm/src/kernel/registry/attachments.d.ts +46 -0
- package/esm/src/kernel/registry/attachments.js +220 -0
- package/esm/src/kernel/registry/catalog.d.ts +25 -0
- package/esm/src/kernel/registry/catalog.js +85 -0
- package/esm/src/kernel/registry/embedding-rules.d.ts +28 -0
- package/esm/src/kernel/registry/embedding-rules.js +66 -0
- package/esm/src/kernel/registry/ingress.d.ts +12 -0
- package/esm/src/kernel/registry/ingress.js +179 -0
- package/esm/src/kernel/registry/kernel-registry.d.ts +15 -0
- package/esm/src/kernel/registry/kernel-registry.js +15 -0
- package/esm/src/kernel/registry/profile-outputs.d.ts +3 -0
- package/esm/src/kernel/registry/profile-outputs.js +10 -0
- package/esm/src/kernel/registry/profiles.d.ts +116 -0
- package/esm/src/kernel/registry/profiles.js +773 -0
- package/esm/src/kernel/registry/provider-request.d.ts +6 -0
- package/esm/src/kernel/registry/provider-request.js +34 -0
- package/esm/src/kernel/registry/resolve.d.ts +17 -0
- package/esm/src/kernel/registry/resolve.js +238 -0
- package/esm/src/kernel/registry/schemas.d.ts +12 -0
- package/esm/src/kernel/registry/schemas.js +27 -0
- package/esm/src/kernel/registry/slot-fill.d.ts +7 -0
- package/esm/src/kernel/registry/slot-fill.js +22 -0
- package/esm/src/kernel/registry/sole-model.d.ts +2 -0
- package/esm/src/kernel/registry/sole-model.js +4 -0
- package/esm/src/kernel/registry/system-prompt.d.ts +8 -0
- package/esm/src/kernel/registry/system-prompt.js +32 -0
- package/esm/src/kernel/registry/system-role.d.ts +3 -0
- package/esm/src/kernel/registry/system-role.js +9 -0
- package/esm/src/kernel/registry/vault.d.ts +14 -0
- package/esm/src/kernel/registry/vault.js +1 -0
- package/esm/src/kernel/schema.d.ts +226 -0
- package/esm/src/kernel/schema.js +895 -0
- package/esm/src/kernel/scope.d.ts +29 -0
- package/esm/src/kernel/scope.js +45 -0
- package/esm/src/kernel/stages.d.ts +176 -0
- package/esm/src/kernel/stages.js +431 -0
- package/esm/src/kernel/stop.d.ts +116 -0
- package/esm/src/kernel/stop.js +137 -0
- package/esm/src/kernel/system-parts.d.ts +26 -0
- package/esm/src/kernel/system-parts.js +98 -0
- package/esm/src/kernel/tools/activity-label.d.ts +22 -0
- package/esm/src/kernel/tools/activity-label.js +435 -0
- package/esm/src/kernel/tools/agent.d.ts +66 -0
- package/esm/src/kernel/tools/agent.js +212 -0
- package/esm/src/kernel/tools/coordinate.d.ts +4 -0
- package/esm/src/kernel/tools/coordinate.js +165 -0
- package/esm/src/kernel/tools/events.d.ts +66 -0
- package/esm/src/kernel/tools/events.js +184 -0
- package/esm/src/kernel/tools/execute.d.ts +100 -0
- package/esm/src/kernel/tools/execute.js +1173 -0
- package/esm/src/kernel/tools/gate-answer.d.ts +60 -0
- package/esm/src/kernel/tools/gate-answer.js +65 -0
- package/esm/src/kernel/tools/handler-events.d.ts +45 -0
- package/esm/src/kernel/tools/handler-events.js +106 -0
- package/esm/src/kernel/tools/harness.d.ts +17 -0
- package/esm/src/kernel/tools/harness.js +43 -0
- package/esm/src/kernel/tools/http-limit.d.ts +27 -0
- package/esm/src/kernel/tools/http-limit.js +85 -0
- package/esm/src/kernel/tools/invoke.d.ts +32 -0
- package/esm/src/kernel/tools/invoke.js +282 -0
- package/esm/src/kernel/tools/mcp-sessions.d.ts +23 -0
- package/esm/src/kernel/tools/mcp-sessions.js +69 -0
- package/esm/src/kernel/tools/mod.d.ts +10 -0
- package/esm/src/kernel/tools/mod.js +7 -0
- package/esm/src/kernel/tools/model-text.d.ts +16 -0
- package/esm/src/kernel/tools/model-text.js +31 -0
- package/esm/src/kernel/tools/operation.d.ts +76 -0
- package/esm/src/kernel/tools/operation.js +100 -0
- package/esm/src/kernel/tools/page-answer.d.ts +8 -0
- package/esm/src/kernel/tools/page-answer.js +19 -0
- package/esm/src/kernel/tools/permission.d.ts +15 -0
- package/esm/src/kernel/tools/permission.js +38 -0
- package/esm/src/kernel/tools/project.d.ts +11 -0
- package/esm/src/kernel/tools/project.js +55 -0
- package/esm/src/kernel/tools/registry.d.ts +27 -0
- package/esm/src/kernel/tools/registry.js +143 -0
- package/esm/src/kernel/tools/remote.d.ts +144 -0
- package/esm/src/kernel/tools/remote.js +1125 -0
- package/esm/src/kernel/tools/resolve.d.ts +31 -0
- package/esm/src/kernel/tools/resolve.js +267 -0
- package/esm/src/kernel/tools/run.d.ts +28 -0
- package/esm/src/kernel/tools/run.js +86 -0
- package/esm/src/kernel/tools/schema.d.ts +10 -0
- package/esm/src/kernel/tools/schema.js +95 -0
- package/esm/src/kernel/tools/signed-in-fetch.d.ts +19 -0
- package/esm/src/kernel/tools/signed-in-fetch.js +45 -0
- package/esm/src/kernel/tools/stage-run.d.ts +116 -0
- package/esm/src/kernel/tools/stage-run.js +198 -0
- package/esm/src/kernel/tools/types.d.ts +497 -0
- package/esm/src/kernel/tools/types.js +1 -0
- package/esm/src/kernel/tools/unchecked-output.d.ts +14 -0
- package/esm/src/kernel/tools/unchecked-output.js +18 -0
- package/esm/src/kernel/turn-events.d.ts +776 -0
- package/esm/src/kernel/turn-events.js +543 -0
- package/esm/src/kernel/types.d.ts +1025 -0
- package/esm/src/kernel/types.js +1 -0
- package/esm/src/kernel/util/base64.d.ts +4 -0
- package/esm/src/kernel/util/base64.js +15 -0
- package/esm/src/kernel/util/exact-type.d.ts +31 -0
- package/esm/src/kernel/util/exact-type.js +1 -0
- package/esm/src/kernel/util/find-last.d.ts +3 -0
- package/esm/src/kernel/util/find-last.js +9 -0
- package/esm/src/kernel/util/mime.d.ts +2 -0
- package/esm/src/kernel/util/mime.js +4 -0
- package/esm/src/kernel/util/partial-json.d.ts +23 -0
- package/esm/src/kernel/util/partial-json.js +128 -0
- package/esm/src/kernel/util/record.d.ts +2 -0
- package/esm/src/kernel/util/record.js +4 -0
- package/esm/src/observability/destinations.d.ts +14 -0
- package/esm/src/observability/destinations.js +43 -0
- package/esm/src/observability/jsonl.d.ts +18 -0
- package/esm/src/observability/jsonl.js +110 -0
- package/esm/src/observability/mod.d.ts +22 -0
- package/esm/src/observability/mod.js +16 -0
- package/esm/src/observability/openinference.d.ts +11 -0
- package/esm/src/observability/openinference.js +205 -0
- package/esm/src/observability/otlp.d.ts +71 -0
- package/esm/src/observability/otlp.js +98 -0
- package/esm/src/observability/phoenix.d.ts +30 -0
- package/esm/src/observability/phoenix.js +71 -0
- package/esm/src/observability/policy.d.ts +17 -0
- package/esm/src/observability/policy.js +73 -0
- package/esm/src/observability/resolve-policy.d.ts +8 -0
- package/esm/src/observability/resolve-policy.js +64 -0
- package/esm/src/observability/spans.d.ts +22 -0
- package/esm/src/observability/spans.js +72 -0
- package/esm/src/observability/trace-catalog.d.ts +128 -0
- package/esm/src/observability/trace-catalog.js +906 -0
- package/esm/src/observability/trace-record.d.ts +23 -0
- package/esm/src/observability/trace-record.js +228 -0
- package/esm/src/observability/trace-schema.d.ts +57 -0
- package/esm/src/observability/trace-schema.js +59 -0
- package/esm/src/observability/trace-sink.d.ts +14 -0
- package/esm/src/observability/trace-sink.js +3 -0
- package/esm/src/observability/trace-span.d.ts +98 -0
- package/esm/src/observability/trace-span.js +201 -0
- package/esm/src/observability/trace.d.ts +13 -0
- package/esm/src/observability/trace.js +37 -0
- package/esm/src/observability/types.d.ts +109 -0
- package/esm/src/observability/types.js +3 -0
- package/esm/src/presets/google/speech-voices.d.ts +9 -0
- package/esm/src/presets/google/speech-voices.js +38 -0
- package/esm/src/presets/google-limits.d.ts +13 -0
- package/esm/src/presets/google-limits.js +18 -0
- package/esm/src/presets/google.d.ts +119 -0
- package/esm/src/presets/google.js +197 -0
- package/esm/src/presets/local.d.ts +26 -0
- package/esm/src/presets/local.js +30 -0
- package/esm/src/presets/mod.d.ts +11 -0
- package/esm/src/presets/mod.js +9 -0
- package/esm/src/presets/openrouter.d.ts +26 -0
- package/esm/src/presets/openrouter.js +31 -0
- package/esm/src/providers/embedding-limits.d.ts +7 -0
- package/esm/src/providers/embedding-limits.js +12 -0
- package/esm/src/providers/gemini/embedding-protocol.d.ts +8 -0
- package/esm/src/providers/gemini/embedding-protocol.js +125 -0
- package/esm/src/providers/gemini/interactions-protocol.d.ts +8 -0
- package/esm/src/providers/gemini/interactions-protocol.js +105 -0
- package/esm/src/providers/gemini/live-protocol.d.ts +3 -0
- package/esm/src/providers/gemini/live-protocol.js +191 -0
- package/esm/src/providers/gemini/prices.d.ts +3 -0
- package/esm/src/providers/gemini/prices.js +63 -0
- package/esm/src/providers/gemini/provider.d.ts +7 -0
- package/esm/src/providers/gemini/provider.js +39 -0
- package/esm/src/providers/google/api-error.d.ts +8 -0
- package/esm/src/providers/google/api-error.js +123 -0
- package/esm/src/providers/google/builtins.d.ts +14 -0
- package/esm/src/providers/google/builtins.js +57 -0
- package/esm/src/providers/google/grounding.d.ts +5 -0
- package/esm/src/providers/google/grounding.js +226 -0
- package/esm/src/providers/google/interactions/framing.d.ts +27 -0
- package/esm/src/providers/google/interactions/framing.js +304 -0
- package/esm/src/providers/google/interactions/steps.d.ts +12 -0
- package/esm/src/providers/google/interactions/steps.js +200 -0
- package/esm/src/providers/google/interactions/stream.d.ts +23 -0
- package/esm/src/providers/google/interactions/stream.js +230 -0
- package/esm/src/providers/google/live/framing.d.ts +61 -0
- package/esm/src/providers/google/live/framing.js +597 -0
- package/esm/src/providers/google/live/stream.d.ts +13 -0
- package/esm/src/providers/google/live/stream.js +57 -0
- package/esm/src/providers/google/thinking.d.ts +3 -0
- package/esm/src/providers/google/thinking.js +8 -0
- package/esm/src/providers/google/urls.d.ts +4 -0
- package/esm/src/providers/google/urls.js +4 -0
- package/esm/src/providers/google/usage.d.ts +7 -0
- package/esm/src/providers/google/usage.js +49 -0
- package/esm/src/providers/live.d.ts +6 -0
- package/esm/src/providers/live.js +6 -0
- package/esm/src/providers/local/embedding-protocol.d.ts +7 -0
- package/esm/src/providers/local/embedding-protocol.js +60 -0
- package/esm/src/providers/local/provider.d.ts +7 -0
- package/esm/src/providers/local/provider.js +28 -0
- package/esm/src/providers/mod.d.ts +32 -0
- package/esm/src/providers/mod.js +23 -0
- package/esm/src/providers/open-ai/protocol.d.ts +3 -0
- package/esm/src/providers/open-ai/protocol.js +189 -0
- package/esm/src/providers/openrouter/embedding-protocol.d.ts +6 -0
- package/esm/src/providers/openrouter/embedding-protocol.js +86 -0
- package/esm/src/providers/openrouter/image.d.ts +15 -0
- package/esm/src/providers/openrouter/image.js +34 -0
- package/esm/src/providers/openrouter/images-protocol.d.ts +3 -0
- package/esm/src/providers/openrouter/images-protocol.js +82 -0
- package/esm/src/providers/openrouter/openai/compat.d.ts +19 -0
- package/esm/src/providers/openrouter/openai/compat.js +162 -0
- package/esm/src/providers/openrouter/openai/image-payload.d.ts +9 -0
- package/esm/src/providers/openrouter/openai/image-payload.js +115 -0
- package/esm/src/providers/openrouter/openai/reasoning-state.d.ts +2 -0
- package/esm/src/providers/openrouter/openai/reasoning-state.js +31 -0
- package/esm/src/providers/openrouter/openai/usage.d.ts +8 -0
- package/esm/src/providers/openrouter/openai/usage.js +56 -0
- package/esm/src/providers/openrouter/protocol.d.ts +8 -0
- package/esm/src/providers/openrouter/protocol.js +171 -0
- package/esm/src/providers/openrouter/provider.d.ts +10 -0
- package/esm/src/providers/openrouter/provider.js +50 -0
- package/esm/src/providers/shared/carried-tool-files.d.ts +7 -0
- package/esm/src/providers/shared/carried-tool-files.js +43 -0
- package/esm/src/providers/shared/pcm.d.ts +14 -0
- package/esm/src/providers/shared/pcm.js +78 -0
- package/esm/src/providers/shared/protocol-events.d.ts +8 -0
- package/esm/src/providers/shared/protocol-events.js +20 -0
- package/esm/src/providers/shared/response-identity.d.ts +11 -0
- package/esm/src/providers/shared/response-identity.js +12 -0
- package/esm/src/providers/shared/retry.d.ts +17 -0
- package/esm/src/providers/shared/retry.js +90 -0
- package/esm/src/providers/shared/sse.d.ts +6 -0
- package/esm/src/providers/shared/sse.js +93 -0
- package/esm/src/providers/shared/structured-output.d.ts +4 -0
- package/esm/src/providers/shared/structured-output.js +11 -0
- package/esm/src/providers/shared/tool-args.d.ts +24 -0
- package/esm/src/providers/shared/tool-args.js +88 -0
- package/esm/src/providers/shared/tool-draft.d.ts +16 -0
- package/esm/src/providers/shared/tool-draft.js +14 -0
- package/esm/src/providers/shared/upstream-tap.d.ts +8 -0
- package/esm/src/providers/shared/upstream-tap.js +85 -0
- package/esm/src/providers/shared/upstream-tape.d.ts +6 -0
- package/esm/src/providers/shared/upstream-tape.js +88 -0
- package/esm/src/providers/system-one/protocol.d.ts +8 -0
- package/esm/src/providers/system-one/protocol.js +93 -0
- package/esm/src/providers/types.d.ts +51 -0
- package/esm/src/providers/types.js +2 -0
- package/esm/src/providers/typesafe/provider.d.ts +7 -0
- package/esm/src/providers/typesafe/provider.js +24 -0
- package/esm/src/surface/formats.d.ts +46 -0
- package/esm/src/surface/formats.js +178 -0
- package/esm/src/surface/mod.d.ts +16 -0
- package/esm/src/surface/mod.js +12 -0
- package/esm/src/surface/runtime.d.ts +44 -0
- package/esm/src/surface/runtime.js +441 -0
- package/esm/src/surface/tools.d.ts +9 -0
- package/esm/src/surface/tools.js +62 -0
- package/esm/src/surface/types.d.ts +110 -0
- package/esm/src/surface/types.js +4 -0
- package/package.json +100 -4
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { TheoremError } from '../../guardrails/error.js';
|
|
2
|
+
import { labelText, } from '../../guardrails/labels.js';
|
|
3
|
+
import { base64ToBytes, bytesToBase64 } from '../util/base64.js';
|
|
4
|
+
import { mimeEssence } from '../util/mime.js';
|
|
5
|
+
import { mimeAllowed, profileAccept } from './catalog.js';
|
|
6
|
+
const B64_PAD = 2;
|
|
7
|
+
const B64_WORD = 4;
|
|
8
|
+
const B64_TRIPLET = 3;
|
|
9
|
+
const CSV_FORMULA = /(^|,)(\s*)("?)(?:([=@])|([+-])(?![0-9."]))/gm;
|
|
10
|
+
const B64_BODY = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
11
|
+
const TEXT_MIMES = new Set(['text/csv', 'text/plain', 'text/markdown']);
|
|
12
|
+
/** The media limits an inputs spec sets, or `undefined` unless it sets `maxFiles`, `maxBytes`, and `maxTurnBytes`. */
|
|
13
|
+
function resolveMediaLimits(inputs) {
|
|
14
|
+
const { maxFiles, maxBytes, maxTurnBytes, limitsByMime } = inputs;
|
|
15
|
+
if (maxFiles && maxBytes && maxTurnBytes) {
|
|
16
|
+
return { maxFiles, maxBytes, maxTurnBytes, limitsByMime };
|
|
17
|
+
}
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
/** A MIME-specific cap, then its category wildcard, then the global cap. */
|
|
21
|
+
function maxBytesForMime(mimeType, limits) {
|
|
22
|
+
if (limits.limitsByMime) {
|
|
23
|
+
const cleanMime = mimeEssence(mimeType);
|
|
24
|
+
if (limits.limitsByMime[cleanMime]) {
|
|
25
|
+
return limits.limitsByMime[cleanMime];
|
|
26
|
+
}
|
|
27
|
+
const [category] = cleanMime.split('/');
|
|
28
|
+
const wildCard = `${category}/*`;
|
|
29
|
+
if (limits.limitsByMime[wildCard]) {
|
|
30
|
+
return limits.limitsByMime[wildCard];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return limits.maxBytes;
|
|
34
|
+
}
|
|
35
|
+
function isTurnMediaRef(item) {
|
|
36
|
+
return 'uri' in item;
|
|
37
|
+
}
|
|
38
|
+
/** The profile's media limits; throws when it takes no media. */
|
|
39
|
+
function requireMediaLimits(profile) {
|
|
40
|
+
if (profile.type === 'speech') {
|
|
41
|
+
throw new TheoremError('request', `Profile ${profile.id} (speech) does not accept media input`); // labels-exempt: developer contract error
|
|
42
|
+
}
|
|
43
|
+
if (profile.type === 'live') {
|
|
44
|
+
throw new TheoremError('request', `Profile ${profile.id} (live) does not accept turn attachment input`);
|
|
45
|
+
}
|
|
46
|
+
if (profile.type === 'host' || profile.type === 'decision' || profile.type === 'embedding') {
|
|
47
|
+
throw new TheoremError('request', `Profile ${profile.id} (${profile.type}) does not accept turn input`);
|
|
48
|
+
}
|
|
49
|
+
const limits = resolveMediaLimits(profile.inputs ?? {});
|
|
50
|
+
if (!limits) {
|
|
51
|
+
throw new TheoremError('config', `Profile ${profile.id} must set maxFiles, maxBytes, and maxTurnBytes`);
|
|
52
|
+
}
|
|
53
|
+
return limits;
|
|
54
|
+
}
|
|
55
|
+
function b64DecodedLen(data) {
|
|
56
|
+
let pad = 0;
|
|
57
|
+
if (data.endsWith('==')) {
|
|
58
|
+
pad = B64_PAD;
|
|
59
|
+
}
|
|
60
|
+
else if (data.endsWith('=')) {
|
|
61
|
+
pad = 1;
|
|
62
|
+
}
|
|
63
|
+
return Math.floor((data.length * B64_TRIPLET) / B64_WORD) - pad;
|
|
64
|
+
}
|
|
65
|
+
function decodeText(bytes) {
|
|
66
|
+
try {
|
|
67
|
+
return new TextDecoder('utf-8', { fatal: true }).decode(bytes);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return new TextDecoder('latin1').decode(bytes);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/** CSV formula injection: formula-like cells get an apostrophe before they reach a model. */
|
|
74
|
+
function sanitizeCsvText(text) {
|
|
75
|
+
return text.replace(CSV_FORMULA, (_full, ...groups) => {
|
|
76
|
+
const [a, b, c, d, e] = groups;
|
|
77
|
+
return `${a}${b}${c}'${d ?? ''}${e ?? ''}`;
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
function sanitizeTextBytes(mime, bytes, reader) {
|
|
81
|
+
let text = decodeText(bytes);
|
|
82
|
+
if (mime === 'text/csv') {
|
|
83
|
+
text = sanitizeCsvText(text);
|
|
84
|
+
}
|
|
85
|
+
return new TextEncoder().encode(reader.read(text));
|
|
86
|
+
}
|
|
87
|
+
function named(issue, name) {
|
|
88
|
+
return name ? { ...issue, fileName: name } : issue;
|
|
89
|
+
}
|
|
90
|
+
function mimeIssues(accept, files, channel) {
|
|
91
|
+
return files
|
|
92
|
+
.filter((file) => !mimeAllowed(accept, file.mimeType))
|
|
93
|
+
.map((file) => named({ code: 'mime_not_allowed', params: { mimeType: file.mimeType, channel } }, file.name));
|
|
94
|
+
}
|
|
95
|
+
function limitIssues(files, limits) {
|
|
96
|
+
const issues = [];
|
|
97
|
+
if (files.length > limits.maxFiles) {
|
|
98
|
+
issues.push({ code: 'too_many_files', params: { maxFiles: limits.maxFiles } });
|
|
99
|
+
}
|
|
100
|
+
let total = 0;
|
|
101
|
+
for (const file of files) {
|
|
102
|
+
if (file.sizeBytes === undefined)
|
|
103
|
+
continue;
|
|
104
|
+
const maxAllowed = maxBytesForMime(file.mimeType, limits);
|
|
105
|
+
if (file.sizeBytes > maxAllowed) {
|
|
106
|
+
issues.push(named({ code: 'file_too_large', params: { maxBytes: maxAllowed } }, file.name));
|
|
107
|
+
}
|
|
108
|
+
total += file.sizeBytes;
|
|
109
|
+
}
|
|
110
|
+
if (total > limits.maxTurnBytes) {
|
|
111
|
+
issues.push({ code: 'turn_too_large', params: { maxTurnBytes: limits.maxTurnBytes } });
|
|
112
|
+
}
|
|
113
|
+
return issues;
|
|
114
|
+
}
|
|
115
|
+
/** The one attachment check: the kernel throws on it at ingress and the headless interface runs it before a send. */
|
|
116
|
+
function attachmentIssues(rules, files, clips) {
|
|
117
|
+
const issues = [];
|
|
118
|
+
if (files.length > 0 && !rules.attachments) {
|
|
119
|
+
issues.push({ code: 'attachments_not_accepted', params: { channel: 'attachment' } });
|
|
120
|
+
}
|
|
121
|
+
if (clips.length > 0 && !rules.voice) {
|
|
122
|
+
issues.push({ code: 'voice_not_accepted', params: { channel: 'voice' } });
|
|
123
|
+
}
|
|
124
|
+
if (issues.length > 0)
|
|
125
|
+
return issues;
|
|
126
|
+
if (files.length === 0 && clips.length === 0)
|
|
127
|
+
return issues;
|
|
128
|
+
if (rules.attachments)
|
|
129
|
+
issues.push(...mimeIssues(rules.attachments, files, 'attachment'));
|
|
130
|
+
if (rules.voice)
|
|
131
|
+
issues.push(...mimeIssues(rules.voice, clips, 'voice'));
|
|
132
|
+
if (!rules.limits)
|
|
133
|
+
return [...issues, { code: 'limits_unconfigured' }];
|
|
134
|
+
return [...issues, ...limitIssues([...files, ...clips], rules.limits)];
|
|
135
|
+
}
|
|
136
|
+
const ISSUE_KEYS = {
|
|
137
|
+
mime_not_allowed: 'attachments.mime_not_allowed',
|
|
138
|
+
too_many_files: 'attachments.too_many_files',
|
|
139
|
+
too_many_of_kind: 'attachments.too_many_of_kind',
|
|
140
|
+
file_too_large: 'attachments.file_too_large',
|
|
141
|
+
turn_too_large: 'attachments.turn_too_large',
|
|
142
|
+
attachments_not_accepted: 'attachments.not_accepted',
|
|
143
|
+
voice_not_accepted: 'attachments.not_accepted',
|
|
144
|
+
limits_unconfigured: 'attachments.limits_unconfigured',
|
|
145
|
+
};
|
|
146
|
+
/** The user-facing wording key and params for an attachment issue. */
|
|
147
|
+
function attachmentIssueCopy(issue) {
|
|
148
|
+
const params = {};
|
|
149
|
+
for (const [key, value] of Object.entries(issue.params ?? {})) {
|
|
150
|
+
if (value !== undefined)
|
|
151
|
+
params[key] = value;
|
|
152
|
+
}
|
|
153
|
+
if (issue.fileName !== undefined)
|
|
154
|
+
params.fileName = issue.fileName;
|
|
155
|
+
return { key: ISSUE_KEYS[issue.code], params };
|
|
156
|
+
}
|
|
157
|
+
/** The user-facing text for an attachment issue. */
|
|
158
|
+
function attachmentIssueText(issue, labels) {
|
|
159
|
+
const copy = attachmentIssueCopy(issue);
|
|
160
|
+
return labelText(copy.key, copy.params, labels);
|
|
161
|
+
}
|
|
162
|
+
/** The error for a turn whose attachments were refused. */
|
|
163
|
+
function attachmentsRefused(issues) {
|
|
164
|
+
return new TheoremError('input',
|
|
165
|
+
// labels-exempt: internal diagnostic; the user reads the copy lines
|
|
166
|
+
`attachments refused: ${issues.map((issue) => issue.code).join(', ')}`, { copy: issues.map(attachmentIssueCopy) });
|
|
167
|
+
}
|
|
168
|
+
/** The decoded size of inline base64 data; throws when it is not base64. */
|
|
169
|
+
function base64Bytes(data) {
|
|
170
|
+
if (!B64_BODY.test(data)) {
|
|
171
|
+
// labels-exempt: developer-facing wire-format diagnostic, not product copy
|
|
172
|
+
throw new TheoremError('request', 'attachment data must be base64');
|
|
173
|
+
}
|
|
174
|
+
return b64DecodedLen(data);
|
|
175
|
+
}
|
|
176
|
+
function factsOf(item) {
|
|
177
|
+
const facts = { mimeType: item.mimeType, name: item.name };
|
|
178
|
+
if (isTurnMediaRef(item))
|
|
179
|
+
return facts;
|
|
180
|
+
facts.sizeBytes = base64Bytes(item.data);
|
|
181
|
+
return facts;
|
|
182
|
+
}
|
|
183
|
+
/** Provider references are checked for MIME and count; byte limits apply to inline blobs only. */
|
|
184
|
+
function assertTurnAttachments(profile, attachments, voice) {
|
|
185
|
+
if (!hasTurnBlobs(attachments, voice))
|
|
186
|
+
return;
|
|
187
|
+
const limits = requireMediaLimits(profile);
|
|
188
|
+
const issues = attachmentIssues({
|
|
189
|
+
attachments: profileAccept(profile, 'attachments'),
|
|
190
|
+
voice: profileAccept(profile, 'voice'),
|
|
191
|
+
limits,
|
|
192
|
+
}, (attachments ?? []).map(factsOf), (voice ?? []).map(factsOf));
|
|
193
|
+
if (issues.length > 0)
|
|
194
|
+
throw attachmentsRefused(issues);
|
|
195
|
+
}
|
|
196
|
+
function sanitizeAttachment(blob, reader) {
|
|
197
|
+
if (isTurnMediaRef(blob)) {
|
|
198
|
+
return blob;
|
|
199
|
+
}
|
|
200
|
+
const { mimeType, data } = blob;
|
|
201
|
+
if (!TEXT_MIMES.has(mimeEssence(mimeType))) {
|
|
202
|
+
return blob;
|
|
203
|
+
}
|
|
204
|
+
const bytes = sanitizeTextBytes(mimeType, base64ToBytes(data), reader);
|
|
205
|
+
return { ...blob, data: bytesToBase64(bytes) };
|
|
206
|
+
}
|
|
207
|
+
function hasTurnBlobs(attachments, voice) {
|
|
208
|
+
return (attachments?.length ?? 0) > 0 || (voice?.length ?? 0) > 0;
|
|
209
|
+
}
|
|
210
|
+
/** Provider file references pass through unsanitized: the kernel has no bytes to scan. */
|
|
211
|
+
function sanitizeTurnBlobs(profile, attachments, voice, at) {
|
|
212
|
+
assertTurnAttachments(profile, attachments, voice);
|
|
213
|
+
return {
|
|
214
|
+
attachments: attachments?.length
|
|
215
|
+
? attachments.map((blob) => sanitizeAttachment(blob, at.attachment))
|
|
216
|
+
: attachments,
|
|
217
|
+
voice: voice?.length ? voice.map((blob) => sanitizeAttachment(blob, at.voice)) : voice,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
export { assertTurnAttachments, attachmentIssueCopy, attachmentIssues, attachmentIssueText, attachmentsRefused, base64Bytes, isTurnMediaRef, maxBytesForMime, requireMediaLimits, resolveMediaLimits, sanitizeCsvText, sanitizeTurnBlobs, };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { MediaInputKind, ModelBinding, ModelId, ModelProfile, Profile, ProfileInputsSpec, ThinkingLevel } from '../types.js';
|
|
2
|
+
import { mimeEssence } from '../util/mime.js';
|
|
3
|
+
/** Where a media input arrives: as an attachment or as voice. */
|
|
4
|
+
type MediaInputChannel = 'attachments' | 'voice';
|
|
5
|
+
/** Rules support a subtype wildcard such as `image/*`; parameter values are ignored. */
|
|
6
|
+
declare function mimeAllowed(accept: readonly string[], mime: string): boolean;
|
|
7
|
+
/** The kind of media a MIME type is, or `undefined` when it is not accepted. */
|
|
8
|
+
declare function mediaKindForMime(mime: string): MediaInputKind | undefined;
|
|
9
|
+
declare function profileInputs(profile: Profile): ProfileInputsSpec | undefined;
|
|
10
|
+
declare function profileAccept(profile: Profile, channel: MediaInputChannel): string[] | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* `undefined` when the profile accepts it nowhere or the kernel cannot classify it. Hosts route
|
|
13
|
+
* files with this instead of their own MIME table: the profile's `accept` lists are the whole declaration.
|
|
14
|
+
*/
|
|
15
|
+
declare function mediaChannelForMime(profile: Profile, mime: string): MediaInputChannel | undefined;
|
|
16
|
+
/** The profile's binding for the model id; throws when there is none. */
|
|
17
|
+
declare function requireModelBinding(profile: ModelProfile, modelId: ModelId): ModelBinding;
|
|
18
|
+
/** The level if the binding accepts it, else the binding's default effort level, else its first listed level. */
|
|
19
|
+
declare function clampThinkingLevel(binding: ModelBinding, level: ThinkingLevel): ThinkingLevel;
|
|
20
|
+
/** The binding whose provider model id is `apiId`, or `undefined`. */
|
|
21
|
+
declare function modelEntryByApiId(bindings: Record<string, ModelBinding>, apiId: string): ModelBinding | undefined;
|
|
22
|
+
/** The level if the binding for this provider model id accepts it, else that binding's default effort level, else its first listed level. */
|
|
23
|
+
declare function clampThinkingLevelForApiId(bindings: Record<string, ModelBinding>, apiId: string, level: ThinkingLevel): ThinkingLevel;
|
|
24
|
+
export type { MediaInputChannel };
|
|
25
|
+
export { clampThinkingLevel, clampThinkingLevelForApiId, mediaChannelForMime, mediaKindForMime, mimeAllowed, mimeEssence, modelEntryByApiId, profileAccept, profileInputs, requireModelBinding, };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { TheoremError } from '../../guardrails/error.js';
|
|
2
|
+
import { MEDIA_INPUT_KINDS } from '../schema.js';
|
|
3
|
+
import { mimeEssence } from '../util/mime.js';
|
|
4
|
+
/** Rules support a subtype wildcard such as `image/*`; parameter values are ignored. */
|
|
5
|
+
function mimeAllowed(accept, mime) {
|
|
6
|
+
const actual = mimeEssence(mime);
|
|
7
|
+
return accept.some((rule) => {
|
|
8
|
+
const allowed = mimeEssence(rule);
|
|
9
|
+
if (allowed.endsWith('/*')) {
|
|
10
|
+
return actual.startsWith(allowed.slice(0, -1));
|
|
11
|
+
}
|
|
12
|
+
return allowed === actual;
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
/** The kind of media a MIME type is, or `undefined` when it is not accepted. */
|
|
16
|
+
function mediaKindForMime(mime) {
|
|
17
|
+
return MEDIA_INPUT_KINDS[mimeEssence(mime)];
|
|
18
|
+
}
|
|
19
|
+
function profileInputs(profile) {
|
|
20
|
+
return profile.type === 'text' || profile.type === 'image' || profile.type === 'live'
|
|
21
|
+
? profile.inputs
|
|
22
|
+
: undefined;
|
|
23
|
+
}
|
|
24
|
+
function profileAccept(profile, channel) {
|
|
25
|
+
const inputs = profileInputs(profile);
|
|
26
|
+
return channel === 'voice' ? inputs?.voice?.accept : inputs?.attachments?.accept;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* `undefined` when the profile accepts it nowhere or the kernel cannot classify it. Hosts route
|
|
30
|
+
* files with this instead of their own MIME table: the profile's `accept` lists are the whole declaration.
|
|
31
|
+
*/
|
|
32
|
+
function mediaChannelForMime(profile, mime) {
|
|
33
|
+
if (!mediaKindForMime(mime)) {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
for (const channel of ['attachments', 'voice']) {
|
|
37
|
+
const accept = profileAccept(profile, channel);
|
|
38
|
+
if (accept && mimeAllowed(accept, mime)) {
|
|
39
|
+
return channel;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
/** The profile's binding for the model id; throws when there is none. */
|
|
45
|
+
function requireModelBinding(profile, modelId) {
|
|
46
|
+
const binding = profile.models[modelId];
|
|
47
|
+
if (!binding) {
|
|
48
|
+
throw new TheoremError('config', `Profile ${profile.id} has no model binding for '${modelId}'`); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
49
|
+
}
|
|
50
|
+
return binding;
|
|
51
|
+
}
|
|
52
|
+
function effortLevels(binding) {
|
|
53
|
+
if (!binding?.efforts) {
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
return Object.values(binding.efforts);
|
|
57
|
+
}
|
|
58
|
+
function clampLevels(binding, level) {
|
|
59
|
+
const legal = effortLevels(binding);
|
|
60
|
+
if (legal.length === 0) {
|
|
61
|
+
return level;
|
|
62
|
+
}
|
|
63
|
+
if (legal.includes(level)) {
|
|
64
|
+
return level;
|
|
65
|
+
}
|
|
66
|
+
const fallbackAlias = binding?.defaultEffort;
|
|
67
|
+
const fallback = fallbackAlias ? binding?.efforts?.[fallbackAlias] : undefined;
|
|
68
|
+
if (fallback && legal.includes(fallback)) {
|
|
69
|
+
return fallback;
|
|
70
|
+
}
|
|
71
|
+
return legal[0] ?? level;
|
|
72
|
+
}
|
|
73
|
+
/** The level if the binding accepts it, else the binding's default effort level, else its first listed level. */
|
|
74
|
+
function clampThinkingLevel(binding, level) {
|
|
75
|
+
return clampLevels(binding, level);
|
|
76
|
+
}
|
|
77
|
+
/** The binding whose provider model id is `apiId`, or `undefined`. */
|
|
78
|
+
function modelEntryByApiId(bindings, apiId) {
|
|
79
|
+
return Object.values(bindings).find((m) => m.apiId === apiId);
|
|
80
|
+
}
|
|
81
|
+
/** The level if the binding for this provider model id accepts it, else that binding's default effort level, else its first listed level. */
|
|
82
|
+
function clampThinkingLevelForApiId(bindings, apiId, level) {
|
|
83
|
+
return clampLevels(modelEntryByApiId(bindings, apiId), level);
|
|
84
|
+
}
|
|
85
|
+
export { clampThinkingLevel, clampThinkingLevelForApiId, mediaChannelForMime, mediaKindForMime, mimeAllowed, mimeEssence, modelEntryByApiId, profileAccept, profileInputs, requireModelBinding, };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { EmbeddingModelLimits } from '../protocols/protocol.js';
|
|
2
|
+
import type { AttachmentValidationIssue, MimeInputs } from '../types.js';
|
|
3
|
+
import { type AttachmentFacts } from './attachments.js';
|
|
4
|
+
/**
|
|
5
|
+
* What one embedding request may carry: the profile's inputs held to its model's limits. File
|
|
6
|
+
* counts are per input, sizes per file and across the request.
|
|
7
|
+
*/
|
|
8
|
+
export interface EmbeddingRules {
|
|
9
|
+
text: boolean;
|
|
10
|
+
attachments?: {
|
|
11
|
+
accept: string[];
|
|
12
|
+
};
|
|
13
|
+
maxFiles?: number;
|
|
14
|
+
maxBytes?: number;
|
|
15
|
+
maxTurnBytes?: number;
|
|
16
|
+
limitsByMime?: Record<string, number>;
|
|
17
|
+
/** Inputs one request may carry. */
|
|
18
|
+
maxInputs?: number;
|
|
19
|
+
/** The model's caps on one kind of media in one input. */
|
|
20
|
+
perInput?: {
|
|
21
|
+
accept: string[];
|
|
22
|
+
max: number;
|
|
23
|
+
}[];
|
|
24
|
+
}
|
|
25
|
+
/** The profile's inputs held to what its model takes; without the model's limits, the profile's alone. */
|
|
26
|
+
export declare function embeddingRules(inputs: MimeInputs, model?: EmbeddingModelLimits): EmbeddingRules;
|
|
27
|
+
/** The one embedding media check, input by input: the kernel throws on it and the client runs it before a send. */
|
|
28
|
+
export declare function embeddingMediaIssues(rules: EmbeddingRules, media: readonly (readonly AttachmentFacts[])[]): AttachmentValidationIssue[];
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { mimeEssence } from '../util/mime.js';
|
|
2
|
+
import { attachmentIssues, resolveMediaLimits } from './attachments.js';
|
|
3
|
+
import { mimeAllowed } from './catalog.js';
|
|
4
|
+
/** The types both lists take, each as narrow as the narrower list names it. */
|
|
5
|
+
function bothAccept(profile, model) {
|
|
6
|
+
return [
|
|
7
|
+
...new Set([
|
|
8
|
+
...model.filter((mime) => mimeAllowed(profile, mime)),
|
|
9
|
+
...profile.filter((mime) => mimeAllowed(model, mime)),
|
|
10
|
+
]),
|
|
11
|
+
];
|
|
12
|
+
}
|
|
13
|
+
/** The profile's inputs held to what its model takes; without the model's limits, the profile's alone. */
|
|
14
|
+
export function embeddingRules(inputs, model) {
|
|
15
|
+
const accept = inputs.attachments
|
|
16
|
+
? model
|
|
17
|
+
? bothAccept(inputs.attachments.accept, model.media.flatMap((kind) => kind.accept))
|
|
18
|
+
: [...inputs.attachments.accept]
|
|
19
|
+
: [];
|
|
20
|
+
const perInput = (model?.media ?? []).flatMap((kind) => kind.maxPerInput === undefined ? [] : [{ accept: [...kind.accept], max: kind.maxPerInput }]);
|
|
21
|
+
return {
|
|
22
|
+
text: inputs.text !== false,
|
|
23
|
+
...(accept.length > 0 ? { attachments: { accept } } : {}),
|
|
24
|
+
...(inputs.maxFiles === undefined ? {} : { maxFiles: inputs.maxFiles }),
|
|
25
|
+
...(inputs.maxBytes === undefined ? {} : { maxBytes: inputs.maxBytes }),
|
|
26
|
+
...(inputs.maxTurnBytes === undefined ? {} : { maxTurnBytes: inputs.maxTurnBytes }),
|
|
27
|
+
...(inputs.limitsByMime === undefined ? {} : { limitsByMime: { ...inputs.limitsByMime } }),
|
|
28
|
+
...(model?.maxInputs === undefined ? {} : { maxInputs: model.maxInputs }),
|
|
29
|
+
...(perInput.length > 0 ? { perInput } : {}),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/** How the user reads a kind of media: PDF, or its top-level type. */
|
|
33
|
+
function kindName(accept) {
|
|
34
|
+
const first = mimeEssence(accept[0] ?? '');
|
|
35
|
+
return first === 'application/pdf' ? 'PDF' : (first.split('/')[0] ?? first);
|
|
36
|
+
}
|
|
37
|
+
/** The one embedding media check, input by input: the kernel throws on it and the client runs it before a send. */
|
|
38
|
+
export function embeddingMediaIssues(rules, media) {
|
|
39
|
+
const limits = resolveMediaLimits(rules);
|
|
40
|
+
const issues = attachmentIssues({
|
|
41
|
+
attachments: rules.attachments?.accept,
|
|
42
|
+
...(limits ? { limits: { ...limits, maxFiles: Number.MAX_SAFE_INTEGER } } : {}),
|
|
43
|
+
}, media.flat(), []);
|
|
44
|
+
if (limits) {
|
|
45
|
+
for (const files of media) {
|
|
46
|
+
if (files.length > limits.maxFiles)
|
|
47
|
+
issues.push({ code: 'too_many_files', params: { maxFiles: limits.maxFiles } });
|
|
48
|
+
for (const kind of rules.perInput ?? []) {
|
|
49
|
+
const count = files.filter((file) => mimeAllowed(kind.accept, file.mimeType)).length;
|
|
50
|
+
if (count > kind.max)
|
|
51
|
+
issues.push({
|
|
52
|
+
code: 'too_many_of_kind',
|
|
53
|
+
params: { maxFiles: kind.max, kind: kindName(kind.accept) },
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const seen = new Set();
|
|
59
|
+
return issues.filter((issue) => {
|
|
60
|
+
const key = JSON.stringify(issue);
|
|
61
|
+
if (seen.has(key))
|
|
62
|
+
return false;
|
|
63
|
+
seen.add(key);
|
|
64
|
+
return true;
|
|
65
|
+
});
|
|
66
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ImageResponseFormat, InteractionPart, Profile, ProfileSpeechSpec, TurnRequest } from '../types.js';
|
|
2
|
+
/** Typed profiles already make mixed wire formats unrepresentable; this is a safety net. */
|
|
3
|
+
declare function assertOutputMode(profile: Profile, structuredId: string | null): void;
|
|
4
|
+
declare function assertSpeechRole(profile: Profile, req: TurnRequest): void;
|
|
5
|
+
/** The profile's speech settings with this turn's laid over them. */
|
|
6
|
+
declare function resolveSpeech(profile: Profile, req: TurnRequest): ProfileSpeechSpec | undefined;
|
|
7
|
+
declare function resolveImageFormat(profile: Profile): ImageResponseFormat | null;
|
|
8
|
+
declare function resolveInputParts(profile: Profile, req: TurnRequest): InteractionPart[];
|
|
9
|
+
declare function assertTurnSlots(profile: Profile, req: TurnRequest): void;
|
|
10
|
+
/** Refuses context from a sender the profile's `inputs.context` does not list, and a package over its `maxChars`. */
|
|
11
|
+
declare function assertTurnContext(profile: Profile, req: TurnRequest): void;
|
|
12
|
+
export { assertOutputMode, assertSpeechRole, assertTurnContext, assertTurnSlots, resolveImageFormat, resolveInputParts, resolveSpeech, };
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { wrapContext, wrapUserData } from '../../guardrails/canary.js';
|
|
2
|
+
import { TheoremError } from '../../guardrails/error.js';
|
|
3
|
+
import { labelText } from '../../guardrails/labels.js';
|
|
4
|
+
import { contextText } from '../../guardrails/sanitize.js';
|
|
5
|
+
import { synthesizeRepairPrompt } from '../engine/repair.js';
|
|
6
|
+
import { CONTEXT_SENDERS } from '../schema.js';
|
|
7
|
+
import { CONTINUE_INSTRUCTION_TYPES } from '../stop.js';
|
|
8
|
+
import { isTurnMediaRef } from './attachments.js';
|
|
9
|
+
import { mediaKindForMime, mimeEssence, profileInputs } from './catalog.js';
|
|
10
|
+
function activePrimaryOutputModes(profile, structuredId) {
|
|
11
|
+
const modes = [];
|
|
12
|
+
if (structuredId) {
|
|
13
|
+
modes.push('structured');
|
|
14
|
+
}
|
|
15
|
+
if (profile.type === 'image') {
|
|
16
|
+
modes.push('image');
|
|
17
|
+
}
|
|
18
|
+
if (profile.type === 'speech') {
|
|
19
|
+
modes.push('speech');
|
|
20
|
+
}
|
|
21
|
+
return modes;
|
|
22
|
+
}
|
|
23
|
+
/** Typed profiles already make mixed wire formats unrepresentable; this is a safety net. */
|
|
24
|
+
function assertOutputMode(profile, structuredId) {
|
|
25
|
+
const active = activePrimaryOutputModes(profile, structuredId);
|
|
26
|
+
if (active.length <= 1) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
throw new TheoremError('config', `Profile ${profile.id} declares multiple output wire formats (${active.join(', ')}). ` + // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
30
|
+
'Only one of a structured JSON schema (outputs.structured), image, or speech may be active.');
|
|
31
|
+
}
|
|
32
|
+
function assertSpeechRole(profile, req) {
|
|
33
|
+
if (profile.type !== 'speech') {
|
|
34
|
+
if (req.speech) {
|
|
35
|
+
throw new TheoremError('request', `Profile ${profile.id} (${profile.type}) takes no speech settings — only a speech profile speaks`);
|
|
36
|
+
}
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (req.system) {
|
|
40
|
+
throw new TheoremError('config', `Profile ${profile.id} (speech) takes no system prompt — the input text is the transcript`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** The profile's speech settings with this turn's laid over them. */
|
|
44
|
+
function resolveSpeech(profile, req) {
|
|
45
|
+
return profile.type === 'speech'
|
|
46
|
+
? { ...profile.speech, ...definedFields(req.speech) }
|
|
47
|
+
: undefined;
|
|
48
|
+
}
|
|
49
|
+
function definedFields(speech) {
|
|
50
|
+
return Object.fromEntries(Object.entries(speech ?? {}).filter(([, value]) => value !== undefined));
|
|
51
|
+
}
|
|
52
|
+
function resolveImageFormat(profile) {
|
|
53
|
+
if (profile.type !== 'image') {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
const pins = profile.image;
|
|
57
|
+
return {
|
|
58
|
+
type: 'image',
|
|
59
|
+
mimeType: pins.mimeType,
|
|
60
|
+
aspectRatio: pins.aspectRatio,
|
|
61
|
+
resolution: pins.resolution,
|
|
62
|
+
quality: pins.quality,
|
|
63
|
+
background: pins.background,
|
|
64
|
+
n: pins.n,
|
|
65
|
+
seed: pins.seed,
|
|
66
|
+
outputCompression: pins.outputCompression,
|
|
67
|
+
includeText: pins.includeText === true,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function assertMediaMime(mime) {
|
|
71
|
+
const kind = mediaKindForMime(mime);
|
|
72
|
+
if (!kind) {
|
|
73
|
+
throw new TheoremError('input', `MIME '${mime}' is not a supported media input type`); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
74
|
+
}
|
|
75
|
+
return kind;
|
|
76
|
+
}
|
|
77
|
+
/** Runs after `assertTurnAttachments`. A reference's uri passes untouched: the host owns the upload. */
|
|
78
|
+
function mediaParts(blobs) {
|
|
79
|
+
return blobs.map((blob) => {
|
|
80
|
+
const kind = assertMediaMime(blob.mimeType);
|
|
81
|
+
const essence = mimeEssence(blob.mimeType);
|
|
82
|
+
const mimeType = essence === 'image/jpg' ? 'image/jpeg' : essence;
|
|
83
|
+
if (isTurnMediaRef(blob)) {
|
|
84
|
+
return { type: kind, mimeType, uri: blob.uri };
|
|
85
|
+
}
|
|
86
|
+
return { type: kind, mimeType, data: blob.data };
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
function extractTextPart(profile, req) {
|
|
90
|
+
const { text, repair, history } = req.input ?? {};
|
|
91
|
+
if (profile.type === 'speech' && !text?.trim()) {
|
|
92
|
+
throw new TheoremError('request', `Profile ${profile.id} (speech) requires text input`); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
93
|
+
}
|
|
94
|
+
if (profileInputs(profile)?.text === false && text) {
|
|
95
|
+
throw new TheoremError('request', `Profile ${profile.id} does not accept text input`); // labels-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
|
|
96
|
+
}
|
|
97
|
+
// why: A repair is the kernel's, not the user's, so it applies even when the profile takes no user text.
|
|
98
|
+
const promptText = repair
|
|
99
|
+
? synthesizeRepairPrompt({ profile, repair, history })
|
|
100
|
+
: (continueText(profile, req) ?? text);
|
|
101
|
+
// why: A speech model reads its input aloud, fence and all; it follows no instruction, so none needs fencing.
|
|
102
|
+
if (profile.type === 'speech') {
|
|
103
|
+
return promptText ? { type: 'text', text: promptText } : null;
|
|
104
|
+
}
|
|
105
|
+
const blocks = [...contextBlocks(req), ...(promptText ? [wrapUserData(promptText)] : [])];
|
|
106
|
+
return blocks.length > 0 ? { type: 'text', text: blocks.join('\n\n') } : null;
|
|
107
|
+
}
|
|
108
|
+
/** Each sender's context in its own fence, the host's first: the model reads it before the user's message. */
|
|
109
|
+
function contextBlocks(req) {
|
|
110
|
+
const context = req.input?.context ?? {};
|
|
111
|
+
return [...CONTEXT_SENDERS]
|
|
112
|
+
.reverse()
|
|
113
|
+
.filter((sender) => context[sender] !== undefined)
|
|
114
|
+
.map((sender) => wrapContext(sender, contextText(context[sender])));
|
|
115
|
+
}
|
|
116
|
+
/** Image and speech get none: their continue re-sends the host's request unchanged. */
|
|
117
|
+
function continueText(profile, req) {
|
|
118
|
+
if (!req.continueFrom || !CONTINUE_INSTRUCTION_TYPES.includes(profile.type)) {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
if (req.input?.text) {
|
|
122
|
+
throw new TheoremError('request', `Profile ${profile.id}: a continueFrom turn takes no input.text — its user message is the continue instruction`);
|
|
123
|
+
}
|
|
124
|
+
return labelText('continue.instruction', {}, profile.labels);
|
|
125
|
+
}
|
|
126
|
+
function pinnedReferenceParts(profile) {
|
|
127
|
+
return profile.type === 'image' && profile.image.references
|
|
128
|
+
? mediaParts(profile.image.references)
|
|
129
|
+
: [];
|
|
130
|
+
}
|
|
131
|
+
/** `sanitizeTurnRequest` has already checked the blobs against the profile's limits and accept lists. */
|
|
132
|
+
function extractMediaParts(profile, req) {
|
|
133
|
+
const files = req.input?.attachments ?? [];
|
|
134
|
+
const clips = req.input?.voice ?? [];
|
|
135
|
+
return [...pinnedReferenceParts(profile), ...mediaParts(files), ...mediaParts(clips)];
|
|
136
|
+
}
|
|
137
|
+
function resolveInputParts(profile, req) {
|
|
138
|
+
const parts = [];
|
|
139
|
+
const textPart = extractTextPart(profile, req);
|
|
140
|
+
if (textPart) {
|
|
141
|
+
parts.push(textPart);
|
|
142
|
+
}
|
|
143
|
+
parts.push(...extractMediaParts(profile, req));
|
|
144
|
+
return parts;
|
|
145
|
+
}
|
|
146
|
+
function assertTurnSlots(profile, req) {
|
|
147
|
+
const slots = req.input?.slots;
|
|
148
|
+
if (!slots)
|
|
149
|
+
return;
|
|
150
|
+
const declared = profileInputs(profile)?.slots ?? {};
|
|
151
|
+
for (const [key, value] of Object.entries(slots)) {
|
|
152
|
+
const choices = Object.hasOwn(declared, key) ? declared[key] : undefined;
|
|
153
|
+
if (!choices) {
|
|
154
|
+
throw new TheoremError('request', `Profile ${profile.id} has no slot '${key}'`);
|
|
155
|
+
}
|
|
156
|
+
if (!choices.includes(value)) {
|
|
157
|
+
throw new TheoremError('request', `Profile ${profile.id}: slot '${key}' takes ${choices.join(', ')}, not '${value}'`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/** Refuses context from a sender the profile's `inputs.context` does not list, and a package over its `maxChars`. */
|
|
162
|
+
function assertTurnContext(profile, req) {
|
|
163
|
+
const context = req.input?.context;
|
|
164
|
+
if (!context)
|
|
165
|
+
return;
|
|
166
|
+
const spec = profileInputs(profile)?.context;
|
|
167
|
+
for (const [sender, value] of Object.entries(context)) {
|
|
168
|
+
if (value === undefined)
|
|
169
|
+
continue;
|
|
170
|
+
const allowed = CONTEXT_SENDERS.includes(sender);
|
|
171
|
+
if (!allowed || !spec?.from.some((from) => from === sender)) {
|
|
172
|
+
throw new TheoremError('request', `Profile ${profile.id} takes no context from '${sender}'`);
|
|
173
|
+
}
|
|
174
|
+
if (contextText(value).length > spec.maxChars) {
|
|
175
|
+
throw new TheoremError('request', `Profile ${profile.id}: context from '${sender}' is over inputs.context.maxChars (${String(spec.maxChars)})`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
export { assertOutputMode, assertSpeechRole, assertTurnContext, assertTurnSlots, resolveImageFormat, resolveInputParts, resolveSpeech, };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ProviderRegistry } from '../protocols/provider.js';
|
|
2
|
+
import { type ToolRegistry } from '../tools/registry.js';
|
|
3
|
+
import { type ProfileRegistry } from './profiles.js';
|
|
4
|
+
import { type SchemaRegistry } from './schemas.js';
|
|
5
|
+
/** Every run takes one explicitly; nothing reads a registry it was not handed. */
|
|
6
|
+
interface KernelRegistry {
|
|
7
|
+
readonly providers: ProviderRegistry;
|
|
8
|
+
readonly tools: ToolRegistry;
|
|
9
|
+
readonly profiles: ProfileRegistry;
|
|
10
|
+
readonly schemas: SchemaRegistry;
|
|
11
|
+
}
|
|
12
|
+
/** Creates an empty registry of tools, profiles, and schemas, wired so a tool that names a profile can find it. */
|
|
13
|
+
declare function createKernelRegistry(): KernelRegistry;
|
|
14
|
+
export type { KernelRegistry };
|
|
15
|
+
export { createKernelRegistry };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createProviderRegistry } from '../protocols/provider.js';
|
|
2
|
+
import { createToolRegistry } from '../tools/registry.js';
|
|
3
|
+
import { createProfileRegistry } from './profiles.js';
|
|
4
|
+
import { createSchemaRegistry } from './schemas.js';
|
|
5
|
+
/** Creates an empty registry of tools, profiles, and schemas, wired so a tool that names a profile can find it. */
|
|
6
|
+
function createKernelRegistry() {
|
|
7
|
+
// why: An agent tool names a profile, and a profile allows tools: each registry reads
|
|
8
|
+
// the other. Tools look profiles up only when one registers, after both exist.
|
|
9
|
+
const tools = createToolRegistry((id) => profiles.find(id));
|
|
10
|
+
const schemas = createSchemaRegistry();
|
|
11
|
+
const providers = createProviderRegistry();
|
|
12
|
+
const profiles = createProfileRegistry(tools, schemas, providers);
|
|
13
|
+
return { tools, profiles, schemas, providers };
|
|
14
|
+
}
|
|
15
|
+
export { createKernelRegistry };
|