@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,103 @@
|
|
|
1
|
+
import { profileInputs } from '../../kernel/registry/catalog.js';
|
|
2
|
+
import { FIXTURE_PNG_BASE64, FIXTURE_WAV_BASE64, getFixtureForMime } from './fixtures.js';
|
|
3
|
+
export function synthesizeLiteCombo(profile) {
|
|
4
|
+
const model = profile.allowModelSelect && profile.models.fast ? 'fast' : undefined;
|
|
5
|
+
return {
|
|
6
|
+
profile: profile.id,
|
|
7
|
+
model,
|
|
8
|
+
input: {
|
|
9
|
+
text: `Ping test for profile ${profile.id}. Respond concisely with confirmation.`,
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function resolveStressModel(profile) {
|
|
14
|
+
if (!profile.allowModelSelect) {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
if (profile.models.smart) {
|
|
18
|
+
return 'smart';
|
|
19
|
+
}
|
|
20
|
+
const ids = Object.keys(profile.models);
|
|
21
|
+
return ids.length > 1 ? ids[ids.length - 1] : undefined;
|
|
22
|
+
}
|
|
23
|
+
function resolveStressAttachments(profile) {
|
|
24
|
+
const inputs = profileInputs(profile);
|
|
25
|
+
if (!inputs) {
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
const attachments = [];
|
|
29
|
+
const accept = inputs.attachments?.accept;
|
|
30
|
+
if (accept && accept.length > 0) {
|
|
31
|
+
const preferredMimes = ['image/png', 'application/pdf', 'text/plain'];
|
|
32
|
+
const chosenMime = preferredMimes.find((m) => accept.includes(m)) ?? accept[0];
|
|
33
|
+
const fixture = getFixtureForMime(chosenMime);
|
|
34
|
+
if (fixture) {
|
|
35
|
+
attachments.push(fixture);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
attachments.push({ mimeType: 'image/png', data: FIXTURE_PNG_BASE64 });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return attachments;
|
|
42
|
+
}
|
|
43
|
+
function resolveStressVoice(profile) {
|
|
44
|
+
const inputs = profileInputs(profile);
|
|
45
|
+
if (!inputs) {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
const voice = [];
|
|
49
|
+
if (inputs.voice?.accept && inputs.voice.accept.length > 0) {
|
|
50
|
+
voice.push({ mimeType: 'audio/wav', data: FIXTURE_WAV_BASE64 });
|
|
51
|
+
}
|
|
52
|
+
return voice;
|
|
53
|
+
}
|
|
54
|
+
export function synthesizeStressCombo(profile) {
|
|
55
|
+
const model = resolveStressModel(profile);
|
|
56
|
+
const attachments = resolveStressAttachments(profile);
|
|
57
|
+
const voice = resolveStressVoice(profile);
|
|
58
|
+
const promptText = `Execute comprehensive test turn for profile ${profile.id}. Validate all instructions and produce required outputs.`;
|
|
59
|
+
return {
|
|
60
|
+
profile: profile.id,
|
|
61
|
+
model,
|
|
62
|
+
input: {
|
|
63
|
+
text: promptText,
|
|
64
|
+
attachments: attachments.length > 0 ? attachments : undefined,
|
|
65
|
+
voice: voice.length > 0 ? voice : undefined,
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export function synthesizeMatrixCombos(profile) {
|
|
70
|
+
return [
|
|
71
|
+
{
|
|
72
|
+
name: 'Lite (connectivity)',
|
|
73
|
+
req: synthesizeLiteCombo(profile),
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: 'Stress (all modalities + primary tools)',
|
|
77
|
+
req: synthesizeStressCombo(profile),
|
|
78
|
+
},
|
|
79
|
+
];
|
|
80
|
+
}
|
|
81
|
+
function assertGroundingFlagsOnModel(profile, options) {
|
|
82
|
+
const modelId = options.mode && profile.models[options.mode] ? options.mode : profile.defaultModel;
|
|
83
|
+
const builtins = new Set(profile.models[modelId]?.builtInTools ?? []);
|
|
84
|
+
if (options.search === true && !builtins.has('googleSearch')) {
|
|
85
|
+
throw new Error(`--search requires googleSearch on models.${modelId}.builtInTools`);
|
|
86
|
+
}
|
|
87
|
+
if (options.map === true && !builtins.has('googleMaps')) {
|
|
88
|
+
throw new Error(`--map requires googleMaps on models.${modelId}.builtInTools`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
export function buildCustomTurnRequest(profile, options) {
|
|
92
|
+
if (options.lite) {
|
|
93
|
+
return synthesizeLiteCombo(profile);
|
|
94
|
+
}
|
|
95
|
+
const base = synthesizeStressCombo(profile);
|
|
96
|
+
if (options.mode) {
|
|
97
|
+
base.model = options.mode;
|
|
98
|
+
}
|
|
99
|
+
if (options.search !== undefined || options.map !== undefined) {
|
|
100
|
+
assertGroundingFlagsOnModel(profile, options);
|
|
101
|
+
}
|
|
102
|
+
return base;
|
|
103
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { EvalAttachment, EvalCase } from './types.js';
|
|
2
|
+
/** An attachment's content as base64, read from the file when the attachment is a path. */
|
|
3
|
+
declare function attachmentData(attachment: EvalAttachment): Promise<string>;
|
|
4
|
+
declare function pinCaseFiles(cases: EvalCase[], casesPath: string): Promise<EvalCase[]>;
|
|
5
|
+
export { attachmentData, pinCaseFiles };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// why: A file attachment is read when its trial runs, not when the suite loads, so thousands of photos are never held at once.
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { readFile } from 'node:fs/promises';
|
|
4
|
+
import { dirname, resolve } from 'node:path';
|
|
5
|
+
import { TheoremError } from '../guardrails/error.js';
|
|
6
|
+
import { bytesToBase64 } from '../kernel/util/base64.js';
|
|
7
|
+
async function hashedFile(path) {
|
|
8
|
+
let bytes;
|
|
9
|
+
try {
|
|
10
|
+
bytes = await readFile(path);
|
|
11
|
+
}
|
|
12
|
+
catch (error) {
|
|
13
|
+
throw new TheoremError('config', `attachment ${path} cannot be read: ${error instanceof Error ? error.message : String(error)}`);
|
|
14
|
+
}
|
|
15
|
+
return { bytes, sha256: createHash('sha256').update(bytes).digest('hex') };
|
|
16
|
+
}
|
|
17
|
+
async function fileBytes(attachment) {
|
|
18
|
+
const { bytes, sha256 } = await hashedFile(attachment.path);
|
|
19
|
+
if (sha256 !== attachment.sha256) {
|
|
20
|
+
throw new TheoremError('config', `attachment ${attachment.path} hashes to ${sha256}, not the ${attachment.sha256} its case pins`);
|
|
21
|
+
}
|
|
22
|
+
return bytes;
|
|
23
|
+
}
|
|
24
|
+
/** An attachment's content as base64, read from the file when the attachment is a path. */
|
|
25
|
+
async function attachmentData(attachment) {
|
|
26
|
+
return 'data' in attachment ? attachment.data : bytesToBase64(await fileBytes(attachment));
|
|
27
|
+
}
|
|
28
|
+
async function pinCaseFiles(cases, casesPath) {
|
|
29
|
+
const pinned = [];
|
|
30
|
+
for (const evalCase of cases) {
|
|
31
|
+
const { input } = evalCase;
|
|
32
|
+
if (!('attachments' in input) || input.attachments === undefined) {
|
|
33
|
+
pinned.push(evalCase);
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const attachments = [];
|
|
37
|
+
for (const attachment of input.attachments) {
|
|
38
|
+
if ('data' in attachment) {
|
|
39
|
+
attachments.push(attachment);
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const path = resolve(dirname(casesPath), attachment.path);
|
|
43
|
+
try {
|
|
44
|
+
await fileBytes({ ...attachment, path });
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
throw new TheoremError('config', `case ${evalCase.id}: ${error instanceof Error ? error.message : String(error)}`);
|
|
48
|
+
}
|
|
49
|
+
attachments.push({ ...attachment, path });
|
|
50
|
+
}
|
|
51
|
+
pinned.push({ ...evalCase, input: { ...input, attachments } });
|
|
52
|
+
}
|
|
53
|
+
return pinned;
|
|
54
|
+
}
|
|
55
|
+
export { attachmentData, pinCaseFiles };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { SuiteRun } from './run.js';
|
|
2
|
+
/** Nearest-rank percentiles, so each is a value some trial had. */
|
|
3
|
+
interface Spread {
|
|
4
|
+
median: number;
|
|
5
|
+
p90: number;
|
|
6
|
+
}
|
|
7
|
+
/** The results of one group of cases: all cases, or the cases with one tag. It counts cases and trials by outcome and, where they apply, the answers by grade, the stop kinds, and the spread of duration, model calls, and tool calls. */
|
|
8
|
+
interface GroupSummary {
|
|
9
|
+
group: string;
|
|
10
|
+
cases: number;
|
|
11
|
+
casesPassed: number;
|
|
12
|
+
casesUndecided: number;
|
|
13
|
+
trials: number;
|
|
14
|
+
trialsPassed: number;
|
|
15
|
+
trialsErrored: number;
|
|
16
|
+
answers?: {
|
|
17
|
+
accepted: number;
|
|
18
|
+
partial: number;
|
|
19
|
+
wrong: number;
|
|
20
|
+
none: number;
|
|
21
|
+
};
|
|
22
|
+
stops: Record<string, number>;
|
|
23
|
+
durationMs?: Spread;
|
|
24
|
+
modelCalls?: Spread;
|
|
25
|
+
toolCalls?: Spread;
|
|
26
|
+
}
|
|
27
|
+
/** Summarizes a run as one group for all cases and one for each tag its cases carry. */
|
|
28
|
+
declare function groupSummaries(run: Pick<SuiteRun, 'trials' | 'verdicts'>): GroupSummary[];
|
|
29
|
+
export type { GroupSummary, Spread };
|
|
30
|
+
export { groupSummaries };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
const MEDIAN = 0.5;
|
|
2
|
+
const P90 = 0.9;
|
|
3
|
+
function rank(sorted, quantile) {
|
|
4
|
+
return sorted[Math.max(0, Math.ceil(quantile * sorted.length) - 1)] ?? 0;
|
|
5
|
+
}
|
|
6
|
+
function spread(values) {
|
|
7
|
+
if (values.length === 0)
|
|
8
|
+
return undefined;
|
|
9
|
+
const sorted = values.toSorted((a, b) => a - b);
|
|
10
|
+
return { median: rank(sorted, MEDIAN), p90: rank(sorted, P90) };
|
|
11
|
+
}
|
|
12
|
+
function answerLabel(report) {
|
|
13
|
+
return report.results.find((result) => result.name === 'answer')?.score?.label;
|
|
14
|
+
}
|
|
15
|
+
function groupOf(group, verdicts, trials, gradesAnswers) {
|
|
16
|
+
const turns = trials.flatMap((report) => report.turn ?? []);
|
|
17
|
+
const of = (key) => spread(turns.map((turn) => turn[key]));
|
|
18
|
+
const labels = trials.map(answerLabel);
|
|
19
|
+
const count = (label) => labels.filter((each) => each === label).length;
|
|
20
|
+
const stops = {};
|
|
21
|
+
for (const turn of turns) {
|
|
22
|
+
const stop = turn.stop ?? 'unrecorded';
|
|
23
|
+
stops[stop] = (stops[stop] ?? 0) + 1;
|
|
24
|
+
}
|
|
25
|
+
const durationMs = of('durationMs');
|
|
26
|
+
const modelCalls = of('modelCalls');
|
|
27
|
+
const toolCalls = of('toolCalls');
|
|
28
|
+
return {
|
|
29
|
+
group,
|
|
30
|
+
cases: verdicts.length,
|
|
31
|
+
casesPassed: verdicts.filter((verdict) => verdict.passed).length,
|
|
32
|
+
casesUndecided: verdicts.filter((verdict) => !verdict.decided).length,
|
|
33
|
+
trials: trials.length,
|
|
34
|
+
trialsPassed: trials.filter((report) => report.outcome === 'passed').length,
|
|
35
|
+
trialsErrored: trials.filter((report) => report.outcome === 'errored').length,
|
|
36
|
+
...(gradesAnswers
|
|
37
|
+
? {
|
|
38
|
+
answers: {
|
|
39
|
+
accepted: count('accepted'),
|
|
40
|
+
partial: count('partial'),
|
|
41
|
+
wrong: count('wrong'),
|
|
42
|
+
none: count(undefined),
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
: {}),
|
|
46
|
+
stops,
|
|
47
|
+
...(durationMs ? { durationMs } : {}),
|
|
48
|
+
...(modelCalls ? { modelCalls } : {}),
|
|
49
|
+
...(toolCalls ? { toolCalls } : {}),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/** Summarizes a run as one group for all cases and one for each tag its cases carry. */
|
|
53
|
+
function groupSummaries(run) {
|
|
54
|
+
const gradesAnswers = run.trials.some((report) => report.results.some((result) => result.name === 'answer'));
|
|
55
|
+
const tags = [...new Set(run.trials.flatMap((report) => report.case?.tags ?? []))].sort();
|
|
56
|
+
const tagged = (tag) => run.trials.filter((report) => report.case?.tags?.includes(tag) === true);
|
|
57
|
+
const verdictsOf = (trials) => {
|
|
58
|
+
const ids = new Set(trials.map((report) => report.case?.id));
|
|
59
|
+
return run.verdicts.filter((verdict) => ids.has(verdict.case));
|
|
60
|
+
};
|
|
61
|
+
return [
|
|
62
|
+
groupOf('all', run.verdicts, run.trials, gradesAnswers),
|
|
63
|
+
...tags.map((tag) => {
|
|
64
|
+
const trials = tagged(tag);
|
|
65
|
+
return groupOf(tag, verdictsOf(trials), trials, gradesAnswers);
|
|
66
|
+
}),
|
|
67
|
+
];
|
|
68
|
+
}
|
|
69
|
+
export { groupSummaries };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { EvalGrader } from '../types.js';
|
|
2
|
+
/** Where `answer` reads the agent's answer: a key of the reply's JSON, or an argument of a tool call. */
|
|
3
|
+
type AnswerSource = {
|
|
4
|
+
json: string;
|
|
5
|
+
} | {
|
|
6
|
+
tool: string;
|
|
7
|
+
arg: string;
|
|
8
|
+
};
|
|
9
|
+
/** How an answer was graded: `accepted` passes, `partial` and `wrong` fail. */
|
|
10
|
+
type AnswerLabel = 'accepted' | 'partial' | 'wrong';
|
|
11
|
+
/** A code grader that checks the agent's answer against the case's `expect.answer` lists of accepted, partial, and rejected names, normalizing both sides; with `from` it compares the named JSON key or tool argument exactly, otherwise it looks for the names in the reply text. A provider error before an answer errors the trial instead. */
|
|
12
|
+
declare function answer(options?: {
|
|
13
|
+
from?: AnswerSource;
|
|
14
|
+
}): EvalGrader;
|
|
15
|
+
export type { AnswerLabel, AnswerSource };
|
|
16
|
+
export { answer };
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { isRecord } from '../../kernel/util/record.js';
|
|
2
|
+
import { codeGrader, deliveredJson, deliveredText, listOf } from './shared.js';
|
|
3
|
+
import { toolSteps } from './transcript.js';
|
|
4
|
+
function normalized(text) {
|
|
5
|
+
return text
|
|
6
|
+
.normalize('NFKD')
|
|
7
|
+
.replace(/\p{M}/gu, '')
|
|
8
|
+
.toLowerCase()
|
|
9
|
+
.replace(/[^\p{L}\p{N}]+/gu, ' ')
|
|
10
|
+
.trim();
|
|
11
|
+
}
|
|
12
|
+
/** A name said only inside a longer one of them is not said: `Calathea` in `Calathea orbifolia` is the species. */
|
|
13
|
+
function namedIn(text, names) {
|
|
14
|
+
const words = normalized(text).split(' ');
|
|
15
|
+
const spans = names.flatMap((name) => {
|
|
16
|
+
const key = normalized(name);
|
|
17
|
+
if (!key)
|
|
18
|
+
return [];
|
|
19
|
+
const parts = key.split(' ');
|
|
20
|
+
return words.flatMap((_, start) => parts.every((part, i) => words[start + i] === part)
|
|
21
|
+
? [{ name, start, end: start + parts.length }]
|
|
22
|
+
: []);
|
|
23
|
+
});
|
|
24
|
+
const said = new Set(spans
|
|
25
|
+
.filter((span) => !spans.some((other) => other.start <= span.start &&
|
|
26
|
+
other.end >= span.end &&
|
|
27
|
+
other.end - other.start > span.end - span.start))
|
|
28
|
+
.map((span) => span.name));
|
|
29
|
+
return (among) => among.find((name) => said.has(name));
|
|
30
|
+
}
|
|
31
|
+
function at(value, path) {
|
|
32
|
+
let current = value;
|
|
33
|
+
for (const key of path.split('.')) {
|
|
34
|
+
if (!isRecord(current))
|
|
35
|
+
return undefined;
|
|
36
|
+
current = current[key];
|
|
37
|
+
}
|
|
38
|
+
return current;
|
|
39
|
+
}
|
|
40
|
+
function parsedArguments(text) {
|
|
41
|
+
try {
|
|
42
|
+
return JSON.parse(text);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function readAnswer(trial, source) {
|
|
49
|
+
if ('json' in source) {
|
|
50
|
+
const where = `JSON key ${source.json}`;
|
|
51
|
+
const value = at(deliveredJson(trial), source.json);
|
|
52
|
+
return typeof value === 'string' ? { value, where } : { missing: `no string at ${where}` };
|
|
53
|
+
}
|
|
54
|
+
const where = `${source.tool} argument ${source.arg}`;
|
|
55
|
+
const call = toolSteps(trial)
|
|
56
|
+
.filter((step) => step.name === source.tool)
|
|
57
|
+
.at(-1);
|
|
58
|
+
if (!call)
|
|
59
|
+
return { missing: `${source.tool} was not called` };
|
|
60
|
+
const value = at(parsedArguments(call.arguments), source.arg);
|
|
61
|
+
return typeof value === 'string' ? { value, where } : { missing: `no string at ${where}` };
|
|
62
|
+
}
|
|
63
|
+
function result(label, explanation) {
|
|
64
|
+
const passed = label === 'accepted';
|
|
65
|
+
return {
|
|
66
|
+
name: 'answer',
|
|
67
|
+
source: 'code',
|
|
68
|
+
score: { value: passed ? 1 : 0, label },
|
|
69
|
+
explanation,
|
|
70
|
+
passed,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/** A turn the provider failed before it answered: the agent never had its say, so the trial errors instead of counting as wrong. */
|
|
74
|
+
function unanswered(trial, why) {
|
|
75
|
+
if (trial.root.attributes['theorem.stop.kind'] !== 'provider_error')
|
|
76
|
+
return undefined;
|
|
77
|
+
const kind = trial.root.status.message ? ` (${trial.root.status.message})` : '';
|
|
78
|
+
return {
|
|
79
|
+
name: 'answer',
|
|
80
|
+
source: 'code',
|
|
81
|
+
errorType: 'provider_error',
|
|
82
|
+
explanation: `${why}; the turn stopped provider_error${kind} before it answered`,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/** A code grader that checks the agent's answer against the case's `expect.answer` lists of accepted, partial, and rejected names, normalizing both sides; with `from` it compares the named JSON key or tool argument exactly, otherwise it looks for the names in the reply text. A provider error before an answer errors the trial instead. */
|
|
86
|
+
function answer(options = {}) {
|
|
87
|
+
const { from } = options;
|
|
88
|
+
const identity = `answer:${from ? JSON.stringify(from) : 'reply'}`;
|
|
89
|
+
return codeGrader('answer', identity, true, (trial) => {
|
|
90
|
+
const expected = trial.case?.expect?.answer;
|
|
91
|
+
if (!expected)
|
|
92
|
+
return result('wrong', 'case has no expect.answer');
|
|
93
|
+
const accepted = expected.accepted;
|
|
94
|
+
const partial = expected.partial ?? [];
|
|
95
|
+
const rejected = expected.rejected ?? [];
|
|
96
|
+
if (from) {
|
|
97
|
+
const read = readAnswer(trial, from);
|
|
98
|
+
if ('missing' in read) {
|
|
99
|
+
return (unanswered(trial, read.missing) ??
|
|
100
|
+
result('wrong', `${read.missing}; accepted ${listOf(accepted)}`));
|
|
101
|
+
}
|
|
102
|
+
const said = normalized(read.value);
|
|
103
|
+
const quoted = JSON.stringify(read.value);
|
|
104
|
+
if (accepted.some((name) => normalized(name) === said)) {
|
|
105
|
+
return result('accepted', `answered ${quoted} (${read.where})`);
|
|
106
|
+
}
|
|
107
|
+
if (rejected.some((name) => normalized(name) === said)) {
|
|
108
|
+
return result('wrong', `answered ${quoted} (${read.where}), which the case rejects; accepted ${listOf(accepted)}`);
|
|
109
|
+
}
|
|
110
|
+
if (partial.some((name) => normalized(name) === said)) {
|
|
111
|
+
return result('partial', `answered ${quoted} (${read.where}); accepted ${listOf(accepted)}`);
|
|
112
|
+
}
|
|
113
|
+
return result('wrong', `answered ${quoted} (${read.where}); accepted ${listOf(accepted)}`);
|
|
114
|
+
}
|
|
115
|
+
const found = namedIn(deliveredText(trial, undefined), [...accepted, ...partial, ...rejected]);
|
|
116
|
+
const hit = found(accepted);
|
|
117
|
+
const miss = found(rejected);
|
|
118
|
+
if (hit && miss) {
|
|
119
|
+
return result('partial', `reply names ${JSON.stringify(hit)} and ${JSON.stringify(miss)}, which the case rejects`);
|
|
120
|
+
}
|
|
121
|
+
if (hit)
|
|
122
|
+
return result('accepted', `reply names ${JSON.stringify(hit)}`);
|
|
123
|
+
if (miss) {
|
|
124
|
+
return result('wrong', `reply names ${JSON.stringify(miss)}, which the case rejects; accepted ${listOf(accepted)}`);
|
|
125
|
+
}
|
|
126
|
+
const near = found(partial);
|
|
127
|
+
if (near) {
|
|
128
|
+
return result('partial', `reply names ${JSON.stringify(near)}; accepted ${listOf(accepted)}`);
|
|
129
|
+
}
|
|
130
|
+
return (unanswered(trial, 'the reply names no answer') ??
|
|
131
|
+
result('wrong', `reply names none of ${listOf(accepted)}`));
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
export { answer };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { EvalGrader, EvalResult, Trial } from '../types.js';
|
|
2
|
+
/** Graders over the text the turn delivered to the user. */
|
|
3
|
+
interface DeliveredGraders {
|
|
4
|
+
includes: (text: string) => EvalGrader;
|
|
5
|
+
regex: (pattern: string, flags?: string) => EvalGrader;
|
|
6
|
+
equals: (text: string) => EvalGrader;
|
|
7
|
+
jsonSchema: (schema: Record<string, unknown>) => EvalGrader;
|
|
8
|
+
json: () => EvalGrader;
|
|
9
|
+
}
|
|
10
|
+
/** Graders over the text the turn delivered to the user. */
|
|
11
|
+
declare const delivered: DeliveredGraders;
|
|
12
|
+
/** `in_order` lets other tools interleave; `subset` means none unexpected, though some expected may be missing. */
|
|
13
|
+
type TrajectoryMode = 'exact' | 'in_order' | 'any_order' | 'subset';
|
|
14
|
+
/** Grades the tools a turn called against the expected ones, by order or by set. */
|
|
15
|
+
declare function toolTrajectory(options: {
|
|
16
|
+
expect?: string[];
|
|
17
|
+
mode: TrajectoryMode;
|
|
18
|
+
}): EvalGrader;
|
|
19
|
+
/** Grades that the turn stopped with one of the given kinds. */
|
|
20
|
+
declare function stopKind(kind: string | string[]): EvalGrader;
|
|
21
|
+
/** A guardrail did (`fired: true`) or did not (`fired: false`) act on any span; `allow` does not count as acting. */
|
|
22
|
+
declare function guardrail(options: {
|
|
23
|
+
fired: boolean;
|
|
24
|
+
action?: 'redact' | 'flag' | 'block';
|
|
25
|
+
}): EvalGrader;
|
|
26
|
+
/** Limits a trial must stay under: cost, tokens, steps, and time. */
|
|
27
|
+
interface BudgetOptions {
|
|
28
|
+
maxCostUsd?: number;
|
|
29
|
+
maxTokens?: number;
|
|
30
|
+
maxSteps?: number;
|
|
31
|
+
maxDurationMs?: number;
|
|
32
|
+
/** The slowest model call's time to first chunk. */
|
|
33
|
+
maxTimeToFirstChunkMs?: number;
|
|
34
|
+
}
|
|
35
|
+
/** The trial stayed within every ceiling given; a ceiling with no reading in the trace fails, since it cannot be shown. */
|
|
36
|
+
declare function budget(options: BudgetOptions): EvalGrader;
|
|
37
|
+
/** A grader that passes when `check` accepts the trial. */
|
|
38
|
+
declare function outcome(name: string, check: (trial: Trial) => boolean | EvalResult | Promise<boolean | EvalResult>): EvalGrader;
|
|
39
|
+
export type { BudgetOptions, DeliveredGraders, TrajectoryMode };
|
|
40
|
+
export { budget, delivered, guardrail, outcome, stopKind, toolTrajectory };
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { collectValidationFailures } from '../../kernel/engine/runner/schema-validation.js';
|
|
2
|
+
import { isRecord } from '../../kernel/util/record.js';
|
|
3
|
+
import { codeGrader, deliveredJson, deliveredText, listOf, modelCalls, passFail, spanDurationMs, } from './shared.js';
|
|
4
|
+
const MS_PER_S = 1000;
|
|
5
|
+
function stringAttribute(span, key) {
|
|
6
|
+
const value = span.attributes[key];
|
|
7
|
+
return typeof value === 'string' ? value : undefined;
|
|
8
|
+
}
|
|
9
|
+
function numberAttribute(span, key) {
|
|
10
|
+
const value = span.attributes[key];
|
|
11
|
+
return typeof value === 'number' ? value : undefined;
|
|
12
|
+
}
|
|
13
|
+
function sameJson(left, right) {
|
|
14
|
+
return JSON.stringify(left) === JSON.stringify(right);
|
|
15
|
+
}
|
|
16
|
+
function quote(text) {
|
|
17
|
+
return JSON.stringify(text);
|
|
18
|
+
}
|
|
19
|
+
/** Graders over the text the turn delivered to the user. */
|
|
20
|
+
const delivered = {
|
|
21
|
+
includes(text) {
|
|
22
|
+
return codeGrader('delivered_includes', `delivered.includes:${text}`, false, (trial) => {
|
|
23
|
+
const actual = deliveredText(trial, undefined);
|
|
24
|
+
const passed = actual.includes(text);
|
|
25
|
+
return passFail('delivered_includes', passed, passed ? `delivered text includes ${quote(text)}` : `delivered text lacks ${quote(text)}`);
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
regex(pattern, flags = '') {
|
|
29
|
+
const re = new RegExp(pattern, flags);
|
|
30
|
+
return codeGrader('delivered_regex', `delivered.regex:/${pattern}/${flags}`, false, (trial) => {
|
|
31
|
+
const passed = re.test(deliveredText(trial, undefined));
|
|
32
|
+
return passFail('delivered_regex', passed, passed
|
|
33
|
+
? `delivered text matches /${pattern}/${flags}`
|
|
34
|
+
: `delivered text does not match /${pattern}/${flags}`);
|
|
35
|
+
});
|
|
36
|
+
},
|
|
37
|
+
equals(text) {
|
|
38
|
+
return codeGrader('delivered_equals', `delivered.equals:${text}`, false, (trial) => {
|
|
39
|
+
const actual = deliveredText(trial, undefined);
|
|
40
|
+
const passed = actual === text;
|
|
41
|
+
return passFail('delivered_equals', passed, passed ? 'delivered text is exactly as expected' : `delivered text was ${quote(actual)}`);
|
|
42
|
+
});
|
|
43
|
+
},
|
|
44
|
+
jsonSchema(schema) {
|
|
45
|
+
return codeGrader('delivered_json_schema', `delivered.jsonSchema:${JSON.stringify(schema)}`, false, async (trial) => {
|
|
46
|
+
const value = deliveredJson(trial);
|
|
47
|
+
if (value === undefined) {
|
|
48
|
+
return passFail('delivered_json_schema', false, 'delivered output is not JSON');
|
|
49
|
+
}
|
|
50
|
+
const failures = await collectValidationFailures(schema, value, undefined);
|
|
51
|
+
const passed = failures.length === 0;
|
|
52
|
+
return passFail('delivered_json_schema', passed, passed ? 'delivered JSON fits the schema' : failures.map((f) => f.error).join('; '));
|
|
53
|
+
});
|
|
54
|
+
},
|
|
55
|
+
json() {
|
|
56
|
+
return codeGrader('delivered_json', 'delivered.json', true, (trial) => {
|
|
57
|
+
const expected = trial.case?.expect?.json;
|
|
58
|
+
if (!expected) {
|
|
59
|
+
return passFail('delivered_json', false, 'case has no expect.json');
|
|
60
|
+
}
|
|
61
|
+
const actual = deliveredJson(trial);
|
|
62
|
+
if (!isRecord(actual)) {
|
|
63
|
+
return passFail('delivered_json', false, 'delivered output is not a JSON object');
|
|
64
|
+
}
|
|
65
|
+
const wrong = Object.entries(expected).filter(([key, want]) => !sameJson(actual[key], want));
|
|
66
|
+
const passed = wrong.length === 0;
|
|
67
|
+
return passFail('delivered_json', passed, passed
|
|
68
|
+
? 'delivered JSON carries every expected field'
|
|
69
|
+
: `fields differ: ${wrong.map(([key, want]) => `${key} expected ${JSON.stringify(want)} got ${JSON.stringify(actual[key])}`).join('; ')}`);
|
|
70
|
+
});
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
function inOrder(expected, actual) {
|
|
74
|
+
let at = 0;
|
|
75
|
+
for (const name of actual) {
|
|
76
|
+
if (name === expected[at])
|
|
77
|
+
at += 1;
|
|
78
|
+
}
|
|
79
|
+
return at === expected.length;
|
|
80
|
+
}
|
|
81
|
+
function anyOrder(expected, actual) {
|
|
82
|
+
return sameJson([...expected].sort(), [...actual].sort());
|
|
83
|
+
}
|
|
84
|
+
function trajectoryMatches(mode, expected, actual) {
|
|
85
|
+
switch (mode) {
|
|
86
|
+
case 'exact':
|
|
87
|
+
return sameJson(expected, actual);
|
|
88
|
+
case 'in_order':
|
|
89
|
+
return inOrder(expected, actual);
|
|
90
|
+
case 'any_order':
|
|
91
|
+
return anyOrder(expected, actual);
|
|
92
|
+
case 'subset':
|
|
93
|
+
return actual.every((name) => expected.includes(name));
|
|
94
|
+
default:
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/** Grades the tools a turn called against the expected ones, by order or by set. */
|
|
99
|
+
function toolTrajectory(options) {
|
|
100
|
+
const identity = `toolTrajectory:${options.mode}:${options.expect ? JSON.stringify(options.expect) : 'case'}`;
|
|
101
|
+
return codeGrader('tool_trajectory', identity, options.expect === undefined, (trial) => {
|
|
102
|
+
const expected = options.expect ?? trial.case?.expect?.tools;
|
|
103
|
+
if (!expected) {
|
|
104
|
+
return passFail('tool_trajectory', false, 'case has no expect.tools');
|
|
105
|
+
}
|
|
106
|
+
const actual = trial
|
|
107
|
+
.spans('execute_tool')
|
|
108
|
+
.flatMap((span) => stringAttribute(span, 'gen_ai.tool.name') ?? []);
|
|
109
|
+
const passed = trajectoryMatches(options.mode, expected, actual);
|
|
110
|
+
return passFail('tool_trajectory', passed, `called ${listOf(actual)}; expected ${listOf(expected)} (${options.mode})`);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
/** Grades that the turn stopped with one of the given kinds. */
|
|
114
|
+
function stopKind(kind) {
|
|
115
|
+
const kinds = Array.isArray(kind) ? kind : [kind];
|
|
116
|
+
return codeGrader('stop_kind', `stopKind:${kinds.join('|')}`, false, (trial) => {
|
|
117
|
+
const actual = stringAttribute(trial.root, 'theorem.stop.kind');
|
|
118
|
+
const passed = actual !== undefined && kinds.includes(actual);
|
|
119
|
+
return passFail('stop_kind', passed, `stopped ${actual ?? 'without a stop'}; expected ${listOf(kinds)}`);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
/** A guardrail did (`fired: true`) or did not (`fired: false`) act on any span; `allow` does not count as acting. */
|
|
123
|
+
function guardrail(options) {
|
|
124
|
+
const identity = `guardrail:${options.fired}:${options.action ?? 'any'}`;
|
|
125
|
+
return codeGrader('guardrail', identity, false, (trial) => {
|
|
126
|
+
const actions = trial.records
|
|
127
|
+
.flatMap((record) => record.spans)
|
|
128
|
+
.flatMap((span) => span.events)
|
|
129
|
+
.filter((event) => event.name === 'theorem.guardrail')
|
|
130
|
+
.flatMap((event) => typeof event.attributes.action === 'string' ? [event.attributes.action] : [])
|
|
131
|
+
.filter((action) => (options.action ? action === options.action : action !== 'allow'));
|
|
132
|
+
const fired = actions.length > 0;
|
|
133
|
+
const passed = fired === options.fired;
|
|
134
|
+
return passFail('guardrail', passed, fired ? `guardrail acted: ${listOf(actions)}` : 'no guardrail acted');
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
const BUDGET_KEYS = [
|
|
138
|
+
'maxCostUsd',
|
|
139
|
+
'maxTokens',
|
|
140
|
+
'maxSteps',
|
|
141
|
+
'maxDurationMs',
|
|
142
|
+
'maxTimeToFirstChunkMs',
|
|
143
|
+
];
|
|
144
|
+
function budgetReadings(trial) {
|
|
145
|
+
const usage = trial.usage();
|
|
146
|
+
const firstChunks = modelCalls(trial).flatMap((span) => numberAttribute(span, 'gen_ai.response.time_to_first_chunk') ?? []);
|
|
147
|
+
return {
|
|
148
|
+
maxCostUsd: usage.costUsd,
|
|
149
|
+
maxTokens: usage.tokens.total,
|
|
150
|
+
maxSteps: numberAttribute(trial.root, 'theorem.steps'),
|
|
151
|
+
maxDurationMs: spanDurationMs(trial.top),
|
|
152
|
+
maxTimeToFirstChunkMs: firstChunks.length > 0 ? Math.max(...firstChunks) * MS_PER_S : undefined,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/** The trial stayed within every ceiling given; a ceiling with no reading in the trace fails, since it cannot be shown. */
|
|
156
|
+
function budget(options) {
|
|
157
|
+
return codeGrader('budget', `budget:${JSON.stringify(options)}`, false, (trial) => {
|
|
158
|
+
const readings = budgetReadings(trial);
|
|
159
|
+
const over = [];
|
|
160
|
+
for (const key of BUDGET_KEYS) {
|
|
161
|
+
const limit = options[key];
|
|
162
|
+
if (limit === undefined)
|
|
163
|
+
continue;
|
|
164
|
+
const reading = readings[key];
|
|
165
|
+
if (reading === undefined)
|
|
166
|
+
over.push(`${key}: not recorded`);
|
|
167
|
+
else if (reading > limit)
|
|
168
|
+
over.push(`${key}: ${reading} over ${limit}`);
|
|
169
|
+
}
|
|
170
|
+
const passed = over.length === 0;
|
|
171
|
+
return passFail('budget', passed, passed ? 'within budget' : over.join('; '));
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
/** A grader that passes when `check` accepts the trial. */
|
|
175
|
+
function outcome(name, check) {
|
|
176
|
+
return codeGrader(name, `outcome:${name}`, false, async (trial) => {
|
|
177
|
+
const verdict = await check(trial);
|
|
178
|
+
if (typeof verdict === 'boolean') {
|
|
179
|
+
return passFail(name, verdict, verdict ? 'outcome check passed' : 'outcome check failed');
|
|
180
|
+
}
|
|
181
|
+
return verdict;
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
export { budget, delivered, guardrail, outcome, stopKind, toolTrajectory };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type EvalRubric } from '../rubrics/types.js';
|
|
2
|
+
import type { EvalGrader, Trial } from '../types.js';
|
|
3
|
+
/** The id of the structured schema a text judge answers with, registered when this module loads. */
|
|
4
|
+
declare const EVAL_JUDGMENT = "evalJudgment";
|
|
5
|
+
/** A judge's answer: one of the rubric's labels, or `unknown`, and why. */
|
|
6
|
+
interface Judgment {
|
|
7
|
+
label: string;
|
|
8
|
+
explanation: string;
|
|
9
|
+
}
|
|
10
|
+
/** Options for `judge`: the rubric and, optionally, a name, the labels that pass, a judge profile, the rubric's variables, the cost of a wrong pass and an escalation profile. */
|
|
11
|
+
interface JudgeOptions {
|
|
12
|
+
rubric: EvalRubric;
|
|
13
|
+
name?: string;
|
|
14
|
+
pass?: readonly string[];
|
|
15
|
+
profile?: string;
|
|
16
|
+
variables?: (trial: Trial) => Record<string, string>;
|
|
17
|
+
/** Decision judges only: how many times worse a wrong pass is than a wrong fail; default 1. */
|
|
18
|
+
wrongPassCost?: number;
|
|
19
|
+
escalate?: string;
|
|
20
|
+
}
|
|
21
|
+
/** A grader in which a model judges the trial against a rubric: a text profile answers directly, a decision profile answers the rubric's question, and an `escalate` text profile takes trials with media a decision judge cannot see. A turn that failed or delivered nothing is not judged; a misconfiguration throws. */
|
|
22
|
+
declare function judge(options: JudgeOptions): EvalGrader;
|
|
23
|
+
export type { JudgeOptions, Judgment };
|
|
24
|
+
export { EVAL_JUDGMENT, judge };
|