@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,439 @@
|
|
|
1
|
+
import { TheoremError, throwIfAborted } from '../../guardrails/error.js';
|
|
2
|
+
import { labelText } from '../../guardrails/labels.js';
|
|
3
|
+
import { traceJson } from '../../observability/trace-span.js';
|
|
4
|
+
import { guardedCall } from '../provider-runtime.js';
|
|
5
|
+
import { soleModelId } from '../registry/sole-model.js';
|
|
6
|
+
import { isRecord } from '../util/record.js';
|
|
7
|
+
import { tracedCall } from './call-trace.js';
|
|
8
|
+
/** Where the provider takes decision requests, as its preset states. */
|
|
9
|
+
const DECISION_ERROR_KINDS = {
|
|
10
|
+
invalid_request: 'request',
|
|
11
|
+
authentication: 'auth',
|
|
12
|
+
permission: 'auth',
|
|
13
|
+
rate_limited: 'rate_limit',
|
|
14
|
+
unavailable: 'unavailable',
|
|
15
|
+
network: 'network',
|
|
16
|
+
timeout: 'timeout',
|
|
17
|
+
cancelled: 'cancelled',
|
|
18
|
+
malformed_response: 'bad_response',
|
|
19
|
+
disclosure_blocked: 'blocked',
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* A normalized native-decision failure; response bodies are deliberately omitted. What the
|
|
23
|
+
* provider path threw is its `cause`, and a failure the framework named reads as that failure.
|
|
24
|
+
*/
|
|
25
|
+
export class DecisionError extends TheoremError {
|
|
26
|
+
code;
|
|
27
|
+
status;
|
|
28
|
+
constructor(code, message, status, options) {
|
|
29
|
+
super(DECISION_ERROR_KINDS[code], message, options);
|
|
30
|
+
this.code = code;
|
|
31
|
+
this.status = status;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function requireDecisionProfile(registry, id) {
|
|
35
|
+
const profile = registry.profiles.get(id);
|
|
36
|
+
if (profile.type !== 'decision') {
|
|
37
|
+
throw new TheoremError('request',
|
|
38
|
+
// labels-exempt: developer contract error
|
|
39
|
+
`runDecision requires profile.type 'decision' (got '${profile.type}' for ${profile.id})`);
|
|
40
|
+
}
|
|
41
|
+
return profile;
|
|
42
|
+
}
|
|
43
|
+
/** The profile's one model; registration guarantees exactly one. */
|
|
44
|
+
function decisionModel(profile) {
|
|
45
|
+
const modelId = soleModelId(profile.models);
|
|
46
|
+
const binding = modelId ? profile.models[modelId] : undefined;
|
|
47
|
+
if (!modelId || !binding) {
|
|
48
|
+
throw new TheoremError('config', `Profile ${profile.id}: type 'decision' must declare exactly one model`);
|
|
49
|
+
}
|
|
50
|
+
return [modelId, binding];
|
|
51
|
+
}
|
|
52
|
+
function finite(value, path, min = 0, max = 1) {
|
|
53
|
+
if (typeof value !== 'number' || !Number.isFinite(value) || value < min || value > max) {
|
|
54
|
+
throw new DecisionError('malformed_response', `${path} is outside its valid range`); // labels-exempt: upstream contract error
|
|
55
|
+
}
|
|
56
|
+
return value;
|
|
57
|
+
}
|
|
58
|
+
function distribution(value, labels, path) {
|
|
59
|
+
if (!isRecord(value) ||
|
|
60
|
+
Object.keys(value).length !== labels.length ||
|
|
61
|
+
labels.some((key) => !Object.hasOwn(value, key))) {
|
|
62
|
+
throw new DecisionError('malformed_response', `${path} does not match declared labels`); // labels-exempt: upstream contract error
|
|
63
|
+
}
|
|
64
|
+
const out = Object.create(null);
|
|
65
|
+
for (const label of labels)
|
|
66
|
+
out[label] = finite(value[label], `${path}.${label}`);
|
|
67
|
+
const total = Object.values(out).reduce((sum, item) => sum + item, 0);
|
|
68
|
+
if (Math.abs(total - 1) > 0.001) {
|
|
69
|
+
throw new DecisionError('malformed_response', `${path} must sum to one`); // labels-exempt: upstream contract error
|
|
70
|
+
}
|
|
71
|
+
return out;
|
|
72
|
+
}
|
|
73
|
+
/** A box's four edges, each a fraction of the image, with the low edge before the high one. */
|
|
74
|
+
function box(value, path) {
|
|
75
|
+
if (!isRecord(value))
|
|
76
|
+
throw new DecisionError('malformed_response', `${path} is invalid`); // labels-exempt: upstream contract error
|
|
77
|
+
const edges = {
|
|
78
|
+
top: finite(value.top, `${path}.top`),
|
|
79
|
+
bottom: finite(value.bottom, `${path}.bottom`),
|
|
80
|
+
left: finite(value.left, `${path}.left`),
|
|
81
|
+
right: finite(value.right, `${path}.right`),
|
|
82
|
+
};
|
|
83
|
+
if (edges.left >= edges.right || edges.top >= edges.bottom)
|
|
84
|
+
throw new DecisionError('malformed_response', `${path} has an edge out of order`); // labels-exempt: upstream contract error
|
|
85
|
+
return edges;
|
|
86
|
+
}
|
|
87
|
+
/** A score's legend: text for every declared level. */
|
|
88
|
+
function legend(value, labels, path) {
|
|
89
|
+
if (!isRecord(value) ||
|
|
90
|
+
Object.keys(value).length !== labels.length ||
|
|
91
|
+
labels.some((label) => !Object.hasOwn(value, label)) ||
|
|
92
|
+
Object.values(value).some((text) => typeof text !== 'string' || !text.trim())) {
|
|
93
|
+
throw new DecisionError('malformed_response', `${path} is invalid`); // labels-exempt: upstream contract error
|
|
94
|
+
}
|
|
95
|
+
return value;
|
|
96
|
+
}
|
|
97
|
+
function validateAnswers(raw, questions) {
|
|
98
|
+
if (!isRecord(raw) || Object.keys(raw).length !== Object.keys(questions).length) {
|
|
99
|
+
throw new DecisionError('malformed_response',
|
|
100
|
+
// labels-exempt: upstream contract error
|
|
101
|
+
'Decision provider returned an incomplete answer set');
|
|
102
|
+
}
|
|
103
|
+
const answers = Object.create(null);
|
|
104
|
+
for (const [id, question] of Object.entries(questions)) {
|
|
105
|
+
const answer = raw[id];
|
|
106
|
+
if (!isRecord(answer) || answer.type !== question.type) {
|
|
107
|
+
throw new DecisionError('malformed_response',
|
|
108
|
+
// labels-exempt: upstream contract error
|
|
109
|
+
`Decision provider returned an invalid answer for '${id}'`);
|
|
110
|
+
}
|
|
111
|
+
if (question.type === 'choice') {
|
|
112
|
+
const labels = Object.keys(question.criteria);
|
|
113
|
+
if (typeof answer.choice !== 'string' || !labels.includes(answer.choice)) {
|
|
114
|
+
throw new DecisionError('malformed_response',
|
|
115
|
+
// labels-exempt: upstream contract error
|
|
116
|
+
`Decision provider returned an undeclared choice for '${id}'`);
|
|
117
|
+
}
|
|
118
|
+
answers[id] = {
|
|
119
|
+
type: 'choice',
|
|
120
|
+
choice: answer.choice,
|
|
121
|
+
confidence: finite(answer.confidence, `${id}.confidence`),
|
|
122
|
+
probabilities: distribution(answer.probabilities, labels, `${id}.probabilities`),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
else if (question.type === 'noul') {
|
|
126
|
+
answers[id] = { type: 'noul', noul: finite(answer.noul, `${id}.noul`) };
|
|
127
|
+
}
|
|
128
|
+
else if (question.type === 'box') {
|
|
129
|
+
answers[id] = {
|
|
130
|
+
type: 'box',
|
|
131
|
+
box: box(answer.box, `${id}.box`),
|
|
132
|
+
confidence: finite(answer.confidence, `${id}.confidence`),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
const labels = question.criteria.map((_, index) => String(index));
|
|
137
|
+
answers[id] = {
|
|
138
|
+
type: 'score',
|
|
139
|
+
score: finite(answer.score, `${id}.score`, 0, Math.max(0, labels.length - 1)),
|
|
140
|
+
confidence: finite(answer.confidence, `${id}.confidence`),
|
|
141
|
+
legend: legend(answer.legend, labels, `${id}.legend`),
|
|
142
|
+
probabilities: distribution(answer.probabilities, labels, `${id}.probabilities`),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return answers;
|
|
147
|
+
}
|
|
148
|
+
function isJson(value) {
|
|
149
|
+
const ancestors = new Set();
|
|
150
|
+
const pending = [{ value }];
|
|
151
|
+
while (pending.length) {
|
|
152
|
+
const next = pending.pop();
|
|
153
|
+
if (!next)
|
|
154
|
+
break;
|
|
155
|
+
const item = next.value;
|
|
156
|
+
if (next.exit) {
|
|
157
|
+
ancestors.delete(item);
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
if (item === null || typeof item === 'string' || typeof item === 'boolean')
|
|
161
|
+
continue;
|
|
162
|
+
if (typeof item === 'number') {
|
|
163
|
+
if (!Number.isFinite(item))
|
|
164
|
+
return false;
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (typeof item !== 'object' || ancestors.has(item))
|
|
168
|
+
return false;
|
|
169
|
+
if (!Array.isArray(item) &&
|
|
170
|
+
Object.getPrototypeOf(item) !== Object.prototype &&
|
|
171
|
+
Object.getPrototypeOf(item) !== null)
|
|
172
|
+
return false;
|
|
173
|
+
if (Object.getOwnPropertySymbols(item).length)
|
|
174
|
+
return false;
|
|
175
|
+
ancestors.add(item);
|
|
176
|
+
pending.push({ value: item, exit: true });
|
|
177
|
+
const entries = Array.isArray(item) ? Array.from(item) : Object.values(item);
|
|
178
|
+
for (const entry of entries)
|
|
179
|
+
pending.push({ value: entry });
|
|
180
|
+
}
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
function validateQuestion(id, question) {
|
|
184
|
+
if (!isRecord(question) || !id.trim() || !isDecisionEntry(question.instructions)) {
|
|
185
|
+
throw new DecisionError('invalid_request',
|
|
186
|
+
// labels-exempt: developer contract error
|
|
187
|
+
`Decision question '${id}' must include instructions`);
|
|
188
|
+
}
|
|
189
|
+
if ((question.type === 'noul' || question.type === 'box') && question.criteria === undefined)
|
|
190
|
+
return;
|
|
191
|
+
if (typeof question.type !== 'string' ||
|
|
192
|
+
!['choice', 'noul', 'score'].includes(question.type) ||
|
|
193
|
+
(question.type === 'score' ? !Array.isArray(question.criteria) : !isRecord(question.criteria))) {
|
|
194
|
+
throw new DecisionError('invalid_request', `Decision question '${id}' has invalid criteria`); // labels-exempt: developer contract error
|
|
195
|
+
}
|
|
196
|
+
const criteria = Array.isArray(question.criteria)
|
|
197
|
+
? question.criteria
|
|
198
|
+
: Object.values(question.criteria);
|
|
199
|
+
if (!criteria.length || !criteria.every(isDecisionEntry)) {
|
|
200
|
+
throw new DecisionError('invalid_request',
|
|
201
|
+
// labels-exempt: developer contract error
|
|
202
|
+
`Decision ${question.type} '${id}' must declare criteria`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/** Check a decision before a host spends quota or dispatches it. Does not apply model-specific policy. */
|
|
206
|
+
export function validateDecisionRequest(request, profile) {
|
|
207
|
+
throwIfAborted(request.signal);
|
|
208
|
+
if (request.model !== undefined) {
|
|
209
|
+
throw new DecisionError('invalid_request',
|
|
210
|
+
// labels-exempt: developer contract error
|
|
211
|
+
'Decision requests do not select a model; the profile runs its one model');
|
|
212
|
+
}
|
|
213
|
+
if (request.state === null || !isJson(request.state)) {
|
|
214
|
+
throw new DecisionError('invalid_request', 'Decision state must be non-null JSON'); // labels-exempt: developer contract error
|
|
215
|
+
}
|
|
216
|
+
let serialized;
|
|
217
|
+
try {
|
|
218
|
+
serialized = JSON.stringify(request.state);
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
// labels-exempt: developer contract error
|
|
222
|
+
throw new DecisionError('invalid_request', 'Decision state cannot be serialized as JSON');
|
|
223
|
+
}
|
|
224
|
+
const bytes = new TextEncoder().encode(serialized).byteLength;
|
|
225
|
+
if (profile.inputs.maxStateBytes !== undefined && bytes > profile.inputs.maxStateBytes) {
|
|
226
|
+
throw new DecisionError('invalid_request',
|
|
227
|
+
// labels-exempt: developer contract error
|
|
228
|
+
`Decision state exceeds ${profile.inputs.maxStateBytes} bytes`);
|
|
229
|
+
}
|
|
230
|
+
if (!isRecord(request.questions) ||
|
|
231
|
+
!isJson(request.questions) ||
|
|
232
|
+
Object.keys(request.questions).length === 0) {
|
|
233
|
+
throw new DecisionError('invalid_request',
|
|
234
|
+
// labels-exempt: developer contract error
|
|
235
|
+
'Decision request must declare at least one question');
|
|
236
|
+
}
|
|
237
|
+
for (const [id, question] of Object.entries(request.questions))
|
|
238
|
+
validateQuestion(id, question);
|
|
239
|
+
if (request.assets !== undefined)
|
|
240
|
+
validateAssets(request.assets);
|
|
241
|
+
for (const [id, question] of Object.entries(request.questions))
|
|
242
|
+
validateBoxImage(id, question, request.state, request.assets);
|
|
243
|
+
}
|
|
244
|
+
function stateAt(state, path) {
|
|
245
|
+
let value = state;
|
|
246
|
+
for (const step of path.split('.')) {
|
|
247
|
+
if (!isRecord(value) && !Array.isArray(value))
|
|
248
|
+
return undefined;
|
|
249
|
+
value = Array.isArray(value) ? value[Number(step)] : value[step];
|
|
250
|
+
}
|
|
251
|
+
return value;
|
|
252
|
+
}
|
|
253
|
+
/** A box's image names an image the request holds, itself or through the state field it gives. */
|
|
254
|
+
function validateBoxImage(id, question, state, assets) {
|
|
255
|
+
if (!isRecord(question) || question.image === undefined)
|
|
256
|
+
return;
|
|
257
|
+
const image = question.image;
|
|
258
|
+
const reference = typeof image === 'string' && !assets?.[image] ? stateAt(state, image) : image;
|
|
259
|
+
if (question.type !== 'box' || typeof reference !== 'string' || assets?.[reference] === undefined)
|
|
260
|
+
throw new DecisionError('invalid_request',
|
|
261
|
+
// labels-exempt: developer contract error
|
|
262
|
+
`Decision question '${id}' has an image that is neither a held image nor a state field holding one`);
|
|
263
|
+
}
|
|
264
|
+
/** The question as a provider reads it: a box's image said in its instructions, not as a field. */
|
|
265
|
+
function providerQuestion(question, assets) {
|
|
266
|
+
if (question.type !== 'box' || question.image === undefined)
|
|
267
|
+
return question;
|
|
268
|
+
const { image, instructions } = question;
|
|
269
|
+
const hint = labelText('decision.box_image', {
|
|
270
|
+
image: assets?.[image] ? image : `\`${image}\``,
|
|
271
|
+
});
|
|
272
|
+
return {
|
|
273
|
+
type: 'box',
|
|
274
|
+
instructions: typeof instructions === 'string' ? `${instructions} ${hint}` : [instructions, hint],
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
const BASE64 = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
278
|
+
/** Only what any provider needs: a known image type and bare, padded base64. The provider holds its own limits. */
|
|
279
|
+
function validateAssets(assets) {
|
|
280
|
+
if (!isRecord(assets) || Object.keys(assets).length === 0)
|
|
281
|
+
throw new DecisionError('invalid_request', 'Decision assets must name at least one image'); // labels-exempt: developer contract error
|
|
282
|
+
for (const [reference, asset] of Object.entries(assets)) {
|
|
283
|
+
if (!reference.trim() ||
|
|
284
|
+
!isRecord(asset) ||
|
|
285
|
+
(asset.mimeType !== 'image/png' && asset.mimeType !== 'image/jpeg') ||
|
|
286
|
+
typeof asset.data !== 'string' ||
|
|
287
|
+
asset.data.length % 4 !== 0 ||
|
|
288
|
+
!BASE64.test(asset.data))
|
|
289
|
+
throw new DecisionError('invalid_request',
|
|
290
|
+
// labels-exempt: developer contract error
|
|
291
|
+
`Decision asset '${reference}' must be PNG or JPEG bytes as padded base64`);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
function isDecisionEntry(value) {
|
|
295
|
+
const pending = [value];
|
|
296
|
+
while (pending.length) {
|
|
297
|
+
const item = pending.pop();
|
|
298
|
+
if (typeof item === 'string') {
|
|
299
|
+
if (!item.trim())
|
|
300
|
+
return false;
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
if (!isRecord(item) && !Array.isArray(item))
|
|
304
|
+
return false;
|
|
305
|
+
const entries = Object.values(item);
|
|
306
|
+
if (!entries.length)
|
|
307
|
+
return false;
|
|
308
|
+
for (const entry of entries)
|
|
309
|
+
pending.push(entry);
|
|
310
|
+
}
|
|
311
|
+
return true;
|
|
312
|
+
}
|
|
313
|
+
async function enforceDisclosure(profile, model, provider, request) {
|
|
314
|
+
const verdict = await profile.guardrails?.disclosure?.enforce(request.state, {
|
|
315
|
+
destination: provider,
|
|
316
|
+
profileId: profile.id,
|
|
317
|
+
model,
|
|
318
|
+
questionIds: Object.keys(request.questions),
|
|
319
|
+
...(request.assets ? { assets: request.assets } : {}),
|
|
320
|
+
});
|
|
321
|
+
if (verdict?.action === 'block') {
|
|
322
|
+
throw new DecisionError('disclosure_blocked', 'Decision disclosure was blocked'); // labels-exempt: developer contract error
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
function decisionSpanAttributes(profile, modelId, binding, request) {
|
|
326
|
+
return {
|
|
327
|
+
'gen_ai.operation.name': 'decide',
|
|
328
|
+
'gen_ai.provider.name': binding.provider,
|
|
329
|
+
'gen_ai.agent.name': profile.id,
|
|
330
|
+
'gen_ai.request.model': binding.apiId,
|
|
331
|
+
'theorem.model.id': modelId,
|
|
332
|
+
'theorem.decision.contract': profile.decision.contract,
|
|
333
|
+
'theorem.decision.state': traceJson(request.state),
|
|
334
|
+
'theorem.decision.questions': traceJson(request.questions),
|
|
335
|
+
...(request.assets
|
|
336
|
+
? {
|
|
337
|
+
// invariant: Image bytes never reach a trace; it keeps each image's type and size.
|
|
338
|
+
'theorem.decision.assets': traceJson(Object.fromEntries(Object.entries(request.assets).map(([reference, { mimeType, data }]) => [
|
|
339
|
+
reference,
|
|
340
|
+
{ mimeType, bytes: data.length },
|
|
341
|
+
]))),
|
|
342
|
+
}
|
|
343
|
+
: {}),
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
function recordResult(root, result) {
|
|
347
|
+
root.set({
|
|
348
|
+
'gen_ai.response.model': result.model,
|
|
349
|
+
'theorem.decision.answers': traceJson(result.answers),
|
|
350
|
+
...(result.usage
|
|
351
|
+
? {
|
|
352
|
+
'gen_ai.usage.input_tokens': result.usage.inputTokens,
|
|
353
|
+
'gen_ai.usage.output_tokens': result.usage.outputTokens,
|
|
354
|
+
...(result.usage.costUsd === undefined
|
|
355
|
+
? {}
|
|
356
|
+
: { 'theorem.usage.cost_usd': result.usage.costUsd }),
|
|
357
|
+
}
|
|
358
|
+
: {}),
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
function decisionProviderError(error) {
|
|
362
|
+
if (error instanceof DecisionError)
|
|
363
|
+
return error;
|
|
364
|
+
const kind = error instanceof TheoremError
|
|
365
|
+
? error.kind
|
|
366
|
+
: error instanceof TypeError
|
|
367
|
+
? 'network'
|
|
368
|
+
: 'bad_response';
|
|
369
|
+
const codes = {
|
|
370
|
+
auth: 'authentication',
|
|
371
|
+
rate_limit: 'rate_limited',
|
|
372
|
+
network: 'network',
|
|
373
|
+
unavailable: 'unavailable',
|
|
374
|
+
timeout: 'timeout',
|
|
375
|
+
cancelled: 'cancelled',
|
|
376
|
+
request: 'invalid_request',
|
|
377
|
+
unsupported: 'invalid_request',
|
|
378
|
+
};
|
|
379
|
+
const code = kind === 'auth' && isRecord(error) && error.status === 403
|
|
380
|
+
? 'permission'
|
|
381
|
+
: (codes[kind] ?? 'malformed_response');
|
|
382
|
+
return new DecisionError(code,
|
|
383
|
+
// why: A framework failure's message holds no response body, and says what stopped the decision.
|
|
384
|
+
error instanceof TheoremError ? error.message : labelText('provider.decision_failed'), isRecord(error) && typeof error.status === 'number' ? error.status : undefined, { cause: error });
|
|
385
|
+
}
|
|
386
|
+
async function decide(registry, profile, [modelId, binding], request, options) {
|
|
387
|
+
throwIfAborted(request.signal);
|
|
388
|
+
const provider = registry.providers.require(binding.provider, binding.apiId);
|
|
389
|
+
await enforceDisclosure(profile, modelId, binding.provider, request);
|
|
390
|
+
throwIfAborted(request.signal);
|
|
391
|
+
try {
|
|
392
|
+
const call = guardedCall(provider, binding, 'decision', options, {
|
|
393
|
+
...(request.signal ? { signal: request.signal } : {}),
|
|
394
|
+
...(binding.timeoutMs ? { timeoutMs: binding.timeoutMs } : {}),
|
|
395
|
+
});
|
|
396
|
+
const result = await call.decide({
|
|
397
|
+
apiId: binding.apiId,
|
|
398
|
+
state: request.state,
|
|
399
|
+
questions: Object.fromEntries(Object.entries(request.questions).map(([id, question]) => [
|
|
400
|
+
id,
|
|
401
|
+
providerQuestion(question, request.assets),
|
|
402
|
+
])),
|
|
403
|
+
...(request.assets ? { assets: request.assets } : {}),
|
|
404
|
+
});
|
|
405
|
+
if (typeof result.model !== 'string' || !result.model.trim())
|
|
406
|
+
throw new DecisionError('malformed_response', labelText('provider.decision_model_missing'));
|
|
407
|
+
return { ...result, answers: validateAnswers(result.answers, request.questions) };
|
|
408
|
+
}
|
|
409
|
+
catch (error) {
|
|
410
|
+
if (request.signal?.aborted)
|
|
411
|
+
throw new DecisionError('cancelled', labelText('provider.decision_ended'));
|
|
412
|
+
throw decisionProviderError(error);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Exactly one decision request, traced however it ends. An ambiguous POST is never retried,
|
|
417
|
+
* and a trace write failure never changes the decision's outcome.
|
|
418
|
+
*/
|
|
419
|
+
export async function runDecisionInRegistry(registry, request, options) {
|
|
420
|
+
const profile = requireDecisionProfile(registry, request.profile);
|
|
421
|
+
validateDecisionRequest(request, profile);
|
|
422
|
+
const model = decisionModel(profile);
|
|
423
|
+
const [modelId, binding] = model;
|
|
424
|
+
return await tracedCall({
|
|
425
|
+
name: `decide ${binding.apiId}`,
|
|
426
|
+
attributes: decisionSpanAttributes(profile, modelId, binding, request),
|
|
427
|
+
traceparent: request.traceparent,
|
|
428
|
+
metadata: request.metadata,
|
|
429
|
+
writer: {
|
|
430
|
+
override: options.sink,
|
|
431
|
+
observability: profile.observability,
|
|
432
|
+
guardrails: profile.guardrails,
|
|
433
|
+
},
|
|
434
|
+
}, async (root) => {
|
|
435
|
+
const result = await decide(registry, profile, model, request, options);
|
|
436
|
+
recordResult(root, result);
|
|
437
|
+
return result;
|
|
438
|
+
});
|
|
439
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TraceSink } from '../../observability/trace-sink.js';
|
|
2
|
+
import type { ProviderHostOptions } from '../protocols/runtime.js';
|
|
3
|
+
import type { KernelRegistry } from '../registry/kernel-registry.js';
|
|
4
|
+
import type { EmbeddingRequest, EmbeddingResult } from '../types.js';
|
|
5
|
+
export interface RunEmbeddingOptions extends ProviderHostOptions {
|
|
6
|
+
sink?: TraceSink;
|
|
7
|
+
}
|
|
8
|
+
export declare function runEmbeddingInRegistry(registry: KernelRegistry, request: EmbeddingRequest, options?: RunEmbeddingOptions): Promise<EmbeddingResult>;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { refuseOverlong } from '../../guardrails/detect-at.js';
|
|
2
|
+
import { TheoremError, throwIfAborted } from '../../guardrails/error.js';
|
|
3
|
+
import { protocolOf } from '../protocols/binding.js';
|
|
4
|
+
import { guardedCall } from '../provider-runtime.js';
|
|
5
|
+
import { attachmentsRefused, base64Bytes } from '../registry/attachments.js';
|
|
6
|
+
import { embeddingMediaIssues, embeddingRules } from '../registry/embedding-rules.js';
|
|
7
|
+
import { tracedCall } from './call-trace.js';
|
|
8
|
+
function requireEmbeddingProfile(registry, id) {
|
|
9
|
+
const profile = registry.profiles.get(id);
|
|
10
|
+
if (profile.type !== 'embedding')
|
|
11
|
+
throw new TheoremError('request', `runEmbedding requires profile.type 'embedding' (got '${profile.type}' for ${id})`);
|
|
12
|
+
return profile;
|
|
13
|
+
}
|
|
14
|
+
function chooseModel(profile, requested) {
|
|
15
|
+
const modelId = requested ?? profile.defaultModel;
|
|
16
|
+
if (requested && !profile.allowModelSelect)
|
|
17
|
+
throw new TheoremError('request', `Profile ${profile.id} does not allow model selection`); // labels-exempt: developer contract error
|
|
18
|
+
const binding = profile.models[modelId];
|
|
19
|
+
if (!binding)
|
|
20
|
+
throw new TheoremError('request', `Unknown model '${modelId}' for ${profile.id}`); // labels-exempt: developer contract error
|
|
21
|
+
return [modelId, binding];
|
|
22
|
+
}
|
|
23
|
+
const TASKS = ['query', 'document'];
|
|
24
|
+
function checkTask(task) {
|
|
25
|
+
if (task !== undefined && !TASKS.includes(task))
|
|
26
|
+
throw new TheoremError('request', `Embedding task must be 'query' or 'document'`); // labels-exempt: developer contract error
|
|
27
|
+
}
|
|
28
|
+
function inputsOf(input) {
|
|
29
|
+
return Array.isArray(input) ? input : [input];
|
|
30
|
+
}
|
|
31
|
+
/** An input's parts; a bare string is one text part. */
|
|
32
|
+
function partsOf(input) {
|
|
33
|
+
if (typeof input === 'string')
|
|
34
|
+
return [{ type: 'text', text: input }];
|
|
35
|
+
return input && Array.isArray(input.parts) ? input.parts : [];
|
|
36
|
+
}
|
|
37
|
+
/** Text is checked per part; media per input, held to the profile and to what the model takes. */
|
|
38
|
+
function validateInputs(profile, modelId, inputs, model) {
|
|
39
|
+
const rules = embeddingRules(profile.inputs, model);
|
|
40
|
+
if (rules.maxInputs !== undefined && inputs.length > rules.maxInputs)
|
|
41
|
+
throw new TheoremError('request', `Model '${modelId}' of ${profile.id} takes at most ${rules.maxInputs} inputs per request`);
|
|
42
|
+
const media = [];
|
|
43
|
+
for (const input of inputs) {
|
|
44
|
+
const parts = partsOf(input);
|
|
45
|
+
if (parts.length === 0)
|
|
46
|
+
throw new TheoremError('request', `Profile ${profile.id} received an empty embedding input`); // labels-exempt: developer contract error
|
|
47
|
+
const files = [];
|
|
48
|
+
for (const part of parts) {
|
|
49
|
+
if (part.type === 'text') {
|
|
50
|
+
refuseOverlong(part.text, 'embedding input');
|
|
51
|
+
if (!rules.text)
|
|
52
|
+
throw new TheoremError('unsupported', `Profile ${profile.id} does not accept text embedding input`);
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
files.push(part.type === 'media'
|
|
56
|
+
? { mimeType: part.mimeType, sizeBytes: base64Bytes(part.data) }
|
|
57
|
+
: { mimeType: part.mimeType });
|
|
58
|
+
}
|
|
59
|
+
media.push(files);
|
|
60
|
+
}
|
|
61
|
+
const issues = embeddingMediaIssues(rules, media);
|
|
62
|
+
if (issues.length > 0)
|
|
63
|
+
throw attachmentsRefused(issues);
|
|
64
|
+
}
|
|
65
|
+
function validateResult(result, count) {
|
|
66
|
+
if (!result.model.trim() || result.embeddings.length !== count)
|
|
67
|
+
throw new TheoremError('bad_response', 'Embedding provider returned an invalid vector count'); // labels-exempt: upstream contract error
|
|
68
|
+
const embeddings = result.embeddings.map((vector, index) => {
|
|
69
|
+
if (vector.index !== index ||
|
|
70
|
+
vector.dimensions !== vector.values.length ||
|
|
71
|
+
vector.dimensions === 0)
|
|
72
|
+
throw new TheoremError('bad_response', 'Embedding provider returned invalid vector metadata'); // labels-exempt: upstream contract error
|
|
73
|
+
if (vector.values.some((value) => !Number.isFinite(value)))
|
|
74
|
+
throw new TheoremError('bad_response', 'Embedding provider returned a non-finite vector value');
|
|
75
|
+
return vector;
|
|
76
|
+
});
|
|
77
|
+
return { ...result, embeddings };
|
|
78
|
+
}
|
|
79
|
+
export async function runEmbeddingInRegistry(registry, request, options = {}) {
|
|
80
|
+
throwIfAborted(request.signal);
|
|
81
|
+
const profile = requireEmbeddingProfile(registry, request.profile);
|
|
82
|
+
const [modelId, binding] = chooseModel(profile, request.model);
|
|
83
|
+
const inputs = inputsOf(request.input);
|
|
84
|
+
checkTask(request.task);
|
|
85
|
+
const provider = registry.providers.require(binding.provider, binding.apiId);
|
|
86
|
+
validateInputs(profile, modelId, inputs, protocolOf(provider, binding).embeddingLimits?.(binding.apiId));
|
|
87
|
+
const call = guardedCall(provider, binding, 'embedding', options, {
|
|
88
|
+
...(request.signal ? { signal: request.signal } : {}),
|
|
89
|
+
});
|
|
90
|
+
return await tracedCall({
|
|
91
|
+
name: `embed ${binding.apiId}`,
|
|
92
|
+
attributes: {
|
|
93
|
+
'gen_ai.operation.name': 'embeddings',
|
|
94
|
+
'gen_ai.provider.name': binding.provider,
|
|
95
|
+
'gen_ai.agent.name': profile.id,
|
|
96
|
+
'gen_ai.request.model': binding.apiId,
|
|
97
|
+
'theorem.model.id': modelId,
|
|
98
|
+
'theorem.embedding.inputs': inputs.length,
|
|
99
|
+
...(request.task ? { 'theorem.embedding.task': request.task } : {}),
|
|
100
|
+
},
|
|
101
|
+
traceparent: request.traceparent,
|
|
102
|
+
metadata: request.metadata,
|
|
103
|
+
writer: {
|
|
104
|
+
override: options.sink,
|
|
105
|
+
observability: profile.observability,
|
|
106
|
+
guardrails: profile.guardrails,
|
|
107
|
+
},
|
|
108
|
+
}, async () => {
|
|
109
|
+
const result = await call.embed({
|
|
110
|
+
apiId: binding.apiId,
|
|
111
|
+
input: request.input,
|
|
112
|
+
...(request.task ? { task: request.task } : {}),
|
|
113
|
+
...(binding.options ? { options: binding.options } : {}),
|
|
114
|
+
...(request.signal ? { signal: request.signal } : {}),
|
|
115
|
+
});
|
|
116
|
+
return validateResult(result, inputs.length);
|
|
117
|
+
});
|
|
118
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function sha256(text: string): Promise<string>;
|
|
2
|
+
/** Hashes the decoded bytes, so the hash names the media whatever encoding carried it; `undefined` when not base64. */
|
|
3
|
+
export declare function sha256Base64(base64: string): Promise<{
|
|
4
|
+
hash: string;
|
|
5
|
+
bytes: number;
|
|
6
|
+
} | undefined>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { base64ToBytes } from '../util/base64.js';
|
|
2
|
+
const HEX_PAD = 2;
|
|
3
|
+
const HEX_RADIX = 16;
|
|
4
|
+
function hexSha256(bytes) {
|
|
5
|
+
return [...bytes].map((b) => b.toString(HEX_RADIX).padStart(HEX_PAD, '0')).join('');
|
|
6
|
+
}
|
|
7
|
+
export async function sha256(text) {
|
|
8
|
+
const buf = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(text));
|
|
9
|
+
return hexSha256(new Uint8Array(buf));
|
|
10
|
+
}
|
|
11
|
+
/** Hashes the decoded bytes, so the hash names the media whatever encoding carried it; `undefined` when not base64. */
|
|
12
|
+
export async function sha256Base64(base64) {
|
|
13
|
+
let raw;
|
|
14
|
+
try {
|
|
15
|
+
raw = base64ToBytes(base64);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
const buf = await crypto.subtle.digest('SHA-256', raw);
|
|
21
|
+
return { hash: hexSha256(new Uint8Array(buf)), bytes: raw.byteLength };
|
|
22
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { TurnEventOf } from '../turn-events.js';
|
|
2
|
+
import type { Profile, TurnContext } from '../types.js';
|
|
3
|
+
export interface LiveInboundPrepareResult {
|
|
4
|
+
/** The message to send, wrapped as user data. Absent when a match blocks: it does not reach the model. */
|
|
5
|
+
text?: string;
|
|
6
|
+
/** Present when a detector matched. */
|
|
7
|
+
guardrail?: TurnEventOf<'guardrail'>;
|
|
8
|
+
}
|
|
9
|
+
/** Reads text a live session receives from the user at the `live_user` boundary, wraps what crosses as user data, and returns the guardrail event when something matched. */
|
|
10
|
+
declare function prepareLiveInboundText(profile: Profile, text: string): LiveInboundPrepareResult;
|
|
11
|
+
export interface LiveContextPrepareResult {
|
|
12
|
+
/** Each package that crossed, in its sender's fence, the host's first. */
|
|
13
|
+
texts: string[];
|
|
14
|
+
/** One per package a detector matched in. */
|
|
15
|
+
guardrails: TurnEventOf<'guardrail'>[];
|
|
16
|
+
}
|
|
17
|
+
/** Reads each sender's context at the `context` boundary, as a turn does. A package a match blocks does not reach the model. */
|
|
18
|
+
declare function prepareLiveContext(profile: Profile, context: TurnContext): LiveContextPrepareResult;
|
|
19
|
+
export { prepareLiveContext, prepareLiveInboundText };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { wrapContext, wrapUserData } from '../../guardrails/canary.js';
|
|
2
|
+
import { boundaryReader, detectAt, detectEvent } from '../../guardrails/detect-at.js';
|
|
3
|
+
import { guardrailTurnEvent, projectGuardrailTurnEvent } from '../../guardrails/events.js';
|
|
4
|
+
import { resolveGuardrailPolicy } from '../../guardrails/policy.js';
|
|
5
|
+
import { sanitizeContext } from '../../guardrails/sanitize.js';
|
|
6
|
+
import { resolveObservabilityPolicy } from '../../observability/resolve-policy.js';
|
|
7
|
+
import { CONTEXT_SENDERS } from '../schema.js';
|
|
8
|
+
// why: Resolves through the shared policy so Live ingress and the turn engine cannot drift on what an unset switch means.
|
|
9
|
+
/** Reads text a live session receives from the user at the `live_user` boundary, wraps what crosses as user data, and returns the guardrail event when something matched. */
|
|
10
|
+
function prepareLiveInboundText(profile, text) {
|
|
11
|
+
const { detect } = resolveGuardrailPolicy(profile.guardrails);
|
|
12
|
+
const detected = detectAt(text, 'live_user', detect);
|
|
13
|
+
const event = detectEvent('live_user', detected);
|
|
14
|
+
const includeMatch = resolveObservabilityPolicy(profile.observability).include
|
|
15
|
+
.guardrailMatchPreview;
|
|
16
|
+
const guardrail = event
|
|
17
|
+
? projectGuardrailTurnEvent(guardrailTurnEvent(event), includeMatch)
|
|
18
|
+
: undefined;
|
|
19
|
+
return {
|
|
20
|
+
...(detected.text === undefined ? {} : { text: wrapUserData(detected.text) }),
|
|
21
|
+
...(guardrail ? { guardrail } : {}),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/** Reads each sender's context at the `context` boundary, as a turn does. A package a match blocks does not reach the model. */
|
|
25
|
+
function prepareLiveContext(profile, context) {
|
|
26
|
+
const { detect } = resolveGuardrailPolicy(profile.guardrails);
|
|
27
|
+
const includeMatch = resolveObservabilityPolicy(profile.observability).include
|
|
28
|
+
.guardrailMatchPreview;
|
|
29
|
+
const texts = [];
|
|
30
|
+
const guardrails = [];
|
|
31
|
+
for (const sender of [...CONTEXT_SENDERS].reverse()) {
|
|
32
|
+
if (context[sender] === undefined)
|
|
33
|
+
continue;
|
|
34
|
+
const read = sanitizeContext({ [sender]: context[sender] }, () => boundaryReader('context', detect));
|
|
35
|
+
for (const event of read.events) {
|
|
36
|
+
guardrails.push(projectGuardrailTurnEvent(guardrailTurnEvent(event), includeMatch));
|
|
37
|
+
}
|
|
38
|
+
const text = read.context?.[sender];
|
|
39
|
+
if (!read.blocked && typeof text === 'string')
|
|
40
|
+
texts.push(wrapContext(sender, text));
|
|
41
|
+
}
|
|
42
|
+
return { texts, guardrails };
|
|
43
|
+
}
|
|
44
|
+
export { prepareLiveContext, prepareLiveInboundText };
|