@theoremjs/agents 0.0.0-stage → 0.3.0
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 +1264 -2
- package/esm/_dnt.polyfills.d.ts +66 -0
- package/esm/_dnt.polyfills.js +51 -0
- package/esm/mod.d.ts +65 -0
- package/esm/mod.js +42 -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 +458 -0
- package/esm/src/cli/commands/egress-compile.d.ts +17 -0
- package/esm/src/cli/commands/egress-compile.js +25 -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 +202 -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 +25 -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 +72 -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 +4 -0
- package/esm/src/evals/attachments.js +53 -0
- package/esm/src/evals/breakdown.d.ts +28 -0
- package/esm/src/evals/breakdown.js +68 -0
- package/esm/src/evals/graders/answer.d.ts +13 -0
- package/esm/src/evals/graders/answer.js +133 -0
- package/esm/src/evals/graders/code.d.ts +64 -0
- package/esm/src/evals/graders/code.js +205 -0
- package/esm/src/evals/graders/judge.d.ts +20 -0
- package/esm/src/evals/graders/judge.js +365 -0
- package/esm/src/evals/graders/latency.d.ts +5 -0
- package/esm/src/evals/graders/latency.js +81 -0
- package/esm/src/evals/graders/live.d.ts +11 -0
- package/esm/src/evals/graders/live.js +40 -0
- package/esm/src/evals/graders/media.d.ts +18 -0
- package/esm/src/evals/graders/media.js +92 -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 +17 -0
- package/esm/src/evals/graders/transcript.js +200 -0
- package/esm/src/evals/mod.d.ts +42 -0
- package/esm/src/evals/mod.js +30 -0
- package/esm/src/evals/record.d.ts +35 -0
- package/esm/src/evals/record.js +105 -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 +118 -0
- package/esm/src/evals/run.js +452 -0
- package/esm/src/evals/suite.d.ts +19 -0
- package/esm/src/evals/suite.js +92 -0
- package/esm/src/evals/summary.d.ts +32 -0
- package/esm/src/evals/summary.js +30 -0
- package/esm/src/evals/trial.d.ts +27 -0
- package/esm/src/evals/trial.js +158 -0
- package/esm/src/evals/types.d.ts +260 -0
- package/esm/src/evals/types.js +126 -0
- package/esm/src/evals/verdict.d.ts +18 -0
- package/esm/src/evals/verdict.js +45 -0
- package/esm/src/guardrails/canary-gate.d.ts +21 -0
- package/esm/src/guardrails/canary-gate.js +40 -0
- package/esm/src/guardrails/canary.d.ts +112 -0
- package/esm/src/guardrails/canary.js +901 -0
- package/esm/src/guardrails/compile-egress.d.ts +11 -0
- package/esm/src/guardrails/compile-egress.js +11 -0
- package/esm/src/guardrails/corpus/canary-egress-attacks.d.ts +22 -0
- package/esm/src/guardrails/corpus/canary-egress-attacks.js +303 -0
- package/esm/src/guardrails/corpus/fuzz-inbound.d.ts +5 -0
- package/esm/src/guardrails/corpus/fuzz-inbound.js +202 -0
- package/esm/src/guardrails/corpus/inbound-payloads.d.ts +3 -0
- package/esm/src/guardrails/corpus/inbound-payloads.js +118 -0
- package/esm/src/guardrails/corpus/live-attacks.d.ts +13 -0
- package/esm/src/guardrails/corpus/live-attacks.js +224 -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 +32 -0
- package/esm/src/guardrails/corpus/types.js +1 -0
- package/esm/src/guardrails/egress-automata.d.ts +14 -0
- package/esm/src/guardrails/egress-automata.js +6059 -0
- package/esm/src/guardrails/egress-compiler.d.ts +33 -0
- package/esm/src/guardrails/egress-compiler.js +237 -0
- package/esm/src/guardrails/egress-patterns.d.ts +24 -0
- package/esm/src/guardrails/egress-patterns.js +32 -0
- package/esm/src/guardrails/egress-policy.d.ts +27 -0
- package/esm/src/guardrails/egress-policy.js +76 -0
- package/esm/src/guardrails/egress-rules.d.ts +54 -0
- package/esm/src/guardrails/egress-rules.js +49 -0
- package/esm/src/guardrails/egress-stream.d.ts +105 -0
- package/esm/src/guardrails/egress-stream.js +645 -0
- package/esm/src/guardrails/egress-urls.d.ts +83 -0
- package/esm/src/guardrails/egress-urls.js +917 -0
- package/esm/src/guardrails/egress.d.ts +106 -0
- package/esm/src/guardrails/egress.js +374 -0
- package/esm/src/guardrails/error.d.ts +26 -0
- package/esm/src/guardrails/error.js +91 -0
- package/esm/src/guardrails/event-schemas.d.ts +57 -0
- package/esm/src/guardrails/event-schemas.js +41 -0
- package/esm/src/guardrails/events.d.ts +9 -0
- package/esm/src/guardrails/events.js +42 -0
- package/esm/src/guardrails/hits.d.ts +8 -0
- package/esm/src/guardrails/hits.js +19 -0
- package/esm/src/guardrails/injection-patterns.d.ts +15 -0
- package/esm/src/guardrails/injection-patterns.js +94 -0
- package/esm/src/guardrails/injection.d.ts +14 -0
- package/esm/src/guardrails/injection.js +237 -0
- package/esm/src/guardrails/lexicon.d.ts +30 -0
- package/esm/src/guardrails/lexicon.js +478 -0
- package/esm/src/guardrails/live-outbound-gate.d.ts +54 -0
- package/esm/src/guardrails/live-outbound-gate.js +305 -0
- package/esm/src/guardrails/mod.d.ts +46 -0
- package/esm/src/guardrails/mod.js +29 -0
- package/esm/src/guardrails/network.d.ts +42 -0
- package/esm/src/guardrails/network.js +328 -0
- package/esm/src/guardrails/normalize.d.ts +6 -0
- package/esm/src/guardrails/normalize.js +132 -0
- package/esm/src/guardrails/policy.d.ts +19 -0
- package/esm/src/guardrails/policy.js +50 -0
- package/esm/src/guardrails/progressive-yield.d.ts +69 -0
- package/esm/src/guardrails/progressive-yield.js +237 -0
- package/esm/src/guardrails/prompt-echo.d.ts +38 -0
- package/esm/src/guardrails/prompt-echo.js +225 -0
- package/esm/src/guardrails/quota.d.ts +20 -0
- package/esm/src/guardrails/quota.js +80 -0
- package/esm/src/guardrails/rules.d.ts +56 -0
- package/esm/src/guardrails/rules.js +54 -0
- package/esm/src/guardrails/sanitize.d.ts +23 -0
- package/esm/src/guardrails/sanitize.js +184 -0
- package/esm/src/guardrails/sensitive.d.ts +29 -0
- package/esm/src/guardrails/sensitive.js +113 -0
- package/esm/src/guardrails/serialize.d.ts +14 -0
- package/esm/src/guardrails/serialize.js +37 -0
- package/esm/src/guardrails/testing.d.ts +9 -0
- package/esm/src/guardrails/testing.js +8 -0
- package/esm/src/guardrails/theorem-error.d.ts +18 -0
- package/esm/src/guardrails/theorem-error.js +53 -0
- package/esm/src/guardrails/thought-guard.d.ts +55 -0
- package/esm/src/guardrails/thought-guard.js +464 -0
- package/esm/src/guardrails/tool-directives.d.ts +19 -0
- package/esm/src/guardrails/tool-directives.js +109 -0
- package/esm/src/guardrails/tool-result.d.ts +61 -0
- package/esm/src/guardrails/tool-result.js +248 -0
- package/esm/src/guardrails/types.d.ts +242 -0
- package/esm/src/guardrails/types.js +54 -0
- package/esm/src/host/client-turn.d.ts +9 -0
- package/esm/src/host/client-turn.js +38 -0
- package/esm/src/host/mint-trace.d.ts +28 -0
- package/esm/src/host/mint-trace.js +59 -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 +68 -0
- package/esm/src/host/reply.d.ts +7 -0
- package/esm/src/host/reply.js +35 -0
- package/esm/src/interface/blocks.d.ts +8 -0
- package/esm/src/interface/blocks.js +213 -0
- package/esm/src/interface/composer-actions.d.ts +20 -0
- package/esm/src/interface/composer-actions.js +31 -0
- package/esm/src/interface/draft.d.ts +14 -0
- package/esm/src/interface/draft.js +28 -0
- package/esm/src/interface/from-profile.d.ts +12 -0
- package/esm/src/interface/from-profile.js +144 -0
- package/esm/src/interface/history.d.ts +40 -0
- package/esm/src/interface/history.js +269 -0
- package/esm/src/interface/inputs.d.ts +10 -0
- package/esm/src/interface/inputs.js +64 -0
- package/esm/src/interface/mod.d.ts +31 -0
- package/esm/src/interface/mod.js +21 -0
- package/esm/src/interface/models.d.ts +19 -0
- package/esm/src/interface/models.js +45 -0
- package/esm/src/interface/pending.d.ts +48 -0
- package/esm/src/interface/pending.js +146 -0
- package/esm/src/interface/profile-interface.d.ts +4 -0
- package/esm/src/interface/profile-interface.js +223 -0
- package/esm/src/interface/session.d.ts +64 -0
- package/esm/src/interface/session.js +121 -0
- package/esm/src/interface/tool-calls.d.ts +20 -0
- package/esm/src/interface/tool-calls.js +73 -0
- package/esm/src/interface/tool-invoke.d.ts +4 -0
- package/esm/src/interface/tool-invoke.js +20 -0
- package/esm/src/interface/tool-media.d.ts +9 -0
- package/esm/src/interface/tool-media.js +112 -0
- package/esm/src/interface/types.d.ts +213 -0
- package/esm/src/interface/types.js +4 -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 +51 -0
- package/esm/src/kernel/auth/crypto.js +161 -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 +17 -0
- package/esm/src/kernel/auth/oauth.js +438 -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 +139 -0
- package/esm/src/kernel/auth/types.js +1 -0
- package/esm/src/kernel/default-scope.d.ts +34 -0
- package/esm/src/kernel/default-scope.js +72 -0
- package/esm/src/kernel/engine/compaction.d.ts +70 -0
- package/esm/src/kernel/engine/compaction.js +202 -0
- package/esm/src/kernel/engine/decision.d.ts +41 -0
- package/esm/src/kernel/engine/decision.js +412 -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 +9 -0
- package/esm/src/kernel/engine/live-inbound.js +19 -0
- package/esm/src/kernel/engine/live-ingress.d.ts +9 -0
- package/esm/src/kernel/engine/live-ingress.js +37 -0
- package/esm/src/kernel/engine/media-probe/audio.d.ts +7 -0
- package/esm/src/kernel/engine/media-probe/audio.js +342 -0
- package/esm/src/kernel/engine/media-probe/bytes.d.ts +6 -0
- package/esm/src/kernel/engine/media-probe/bytes.js +26 -0
- package/esm/src/kernel/engine/media-probe/image.d.ts +5 -0
- package/esm/src/kernel/engine/media-probe/image.js +171 -0
- package/esm/src/kernel/engine/media-probe/iso-bmff.d.ts +19 -0
- package/esm/src/kernel/engine/media-probe/iso-bmff.js +48 -0
- package/esm/src/kernel/engine/media-probe/matroska.d.ts +35 -0
- package/esm/src/kernel/engine/media-probe/matroska.js +226 -0
- package/esm/src/kernel/engine/media-probe/mp4.d.ts +22 -0
- package/esm/src/kernel/engine/media-probe/mp4.js +279 -0
- package/esm/src/kernel/engine/media-probe/opus.d.ts +4 -0
- package/esm/src/kernel/engine/media-probe/opus.js +23 -0
- package/esm/src/kernel/engine/media-probe/pdf.d.ts +5 -0
- package/esm/src/kernel/engine/media-probe/pdf.js +117 -0
- package/esm/src/kernel/engine/media-probe/video.d.ts +15 -0
- package/esm/src/kernel/engine/media-probe/video.js +49 -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 +322 -0
- package/esm/src/kernel/engine/runner/mod.d.ts +15 -0
- package/esm/src/kernel/engine/runner/mod.js +574 -0
- package/esm/src/kernel/engine/runner/schema-validation.d.ts +14 -0
- package/esm/src/kernel/engine/runner/schema-validation.js +105 -0
- package/esm/src/kernel/engine/runner/stages.d.ts +28 -0
- package/esm/src/kernel/engine/runner/stages.js +48 -0
- package/esm/src/kernel/engine/runner/state.d.ts +76 -0
- package/esm/src/kernel/engine/runner/state.js +40 -0
- package/esm/src/kernel/engine/runner/steps.d.ts +14 -0
- package/esm/src/kernel/engine/runner/steps.js +360 -0
- package/esm/src/kernel/engine/runner/stream.d.ts +40 -0
- package/esm/src/kernel/engine/runner/stream.js +225 -0
- package/esm/src/kernel/engine/runner/usage.d.ts +45 -0
- package/esm/src/kernel/engine/runner/usage.js +150 -0
- package/esm/src/kernel/engine/session/mod.d.ts +31 -0
- package/esm/src/kernel/engine/session/mod.js +951 -0
- package/esm/src/kernel/engine/session/session-trace.d.ts +115 -0
- package/esm/src/kernel/engine/session/session-trace.js +489 -0
- package/esm/src/kernel/engine/token-estimate.d.ts +77 -0
- package/esm/src/kernel/engine/token-estimate.js +218 -0
- package/esm/src/kernel/engine/tool-trace.d.ts +58 -0
- package/esm/src/kernel/engine/tool-trace.js +131 -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 +118 -0
- package/esm/src/kernel/engine/turn-trace.js +863 -0
- package/esm/src/kernel/engine/usage.d.ts +30 -0
- package/esm/src/kernel/engine/usage.js +134 -0
- package/esm/src/kernel/interaction-parts.d.ts +10 -0
- package/esm/src/kernel/interaction-parts.js +22 -0
- package/esm/src/kernel/mod.d.ts +47 -0
- package/esm/src/kernel/mod.js +30 -0
- package/esm/src/kernel/profile-graph.d.ts +140 -0
- package/esm/src/kernel/profile-graph.js +151 -0
- package/esm/src/kernel/profile-presence.d.ts +9 -0
- package/esm/src/kernel/profile-presence.js +143 -0
- package/esm/src/kernel/profile-scope.d.ts +36 -0
- package/esm/src/kernel/profile-scope.js +262 -0
- package/esm/src/kernel/registry/attachments.d.ts +35 -0
- package/esm/src/kernel/registry/attachments.js +211 -0
- package/esm/src/kernel/registry/catalog.d.ts +19 -0
- package/esm/src/kernel/registry/catalog.js +78 -0
- package/esm/src/kernel/registry/ingress.d.ts +8 -0
- package/esm/src/kernel/registry/ingress.js +134 -0
- package/esm/src/kernel/registry/kernel-registry.d.ts +12 -0
- package/esm/src/kernel/registry/kernel-registry.js +8 -0
- package/esm/src/kernel/registry/profile-outputs.d.ts +3 -0
- package/esm/src/kernel/registry/profile-outputs.js +7 -0
- package/esm/src/kernel/registry/profiles.d.ts +92 -0
- package/esm/src/kernel/registry/profiles.js +698 -0
- package/esm/src/kernel/registry/provider-request.d.ts +6 -0
- package/esm/src/kernel/registry/provider-request.js +42 -0
- package/esm/src/kernel/registry/resolve.d.ts +14 -0
- package/esm/src/kernel/registry/resolve.js +237 -0
- package/esm/src/kernel/registry/schemas.d.ts +9 -0
- package/esm/src/kernel/registry/schemas.js +25 -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 +33 -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 +13 -0
- package/esm/src/kernel/registry/vault.js +14 -0
- package/esm/src/kernel/schema.d.ts +172 -0
- package/esm/src/kernel/schema.js +653 -0
- package/esm/src/kernel/scope.d.ts +22 -0
- package/esm/src/kernel/scope.js +25 -0
- package/esm/src/kernel/stages.d.ts +141 -0
- package/esm/src/kernel/stages.js +388 -0
- package/esm/src/kernel/stop.d.ts +93 -0
- package/esm/src/kernel/stop.js +125 -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 +16 -0
- package/esm/src/kernel/tools/activity-label.js +209 -0
- package/esm/src/kernel/tools/events.d.ts +51 -0
- package/esm/src/kernel/tools/events.js +149 -0
- package/esm/src/kernel/tools/execute.d.ts +64 -0
- package/esm/src/kernel/tools/execute.js +801 -0
- package/esm/src/kernel/tools/gate-answer.d.ts +50 -0
- package/esm/src/kernel/tools/gate-answer.js +54 -0
- package/esm/src/kernel/tools/harness.d.ts +16 -0
- package/esm/src/kernel/tools/harness.js +42 -0
- package/esm/src/kernel/tools/invoke.d.ts +10 -0
- package/esm/src/kernel/tools/invoke.js +129 -0
- package/esm/src/kernel/tools/mcp-sessions.d.ts +20 -0
- package/esm/src/kernel/tools/mcp-sessions.js +64 -0
- package/esm/src/kernel/tools/mod.d.ts +9 -0
- package/esm/src/kernel/tools/mod.js +6 -0
- package/esm/src/kernel/tools/model-text.d.ts +11 -0
- package/esm/src/kernel/tools/model-text.js +25 -0
- package/esm/src/kernel/tools/permission.d.ts +6 -0
- package/esm/src/kernel/tools/permission.js +38 -0
- package/esm/src/kernel/tools/project.d.ts +8 -0
- package/esm/src/kernel/tools/project.js +25 -0
- package/esm/src/kernel/tools/registry.d.ts +20 -0
- package/esm/src/kernel/tools/registry.js +84 -0
- package/esm/src/kernel/tools/remote.d.ts +110 -0
- package/esm/src/kernel/tools/remote.js +998 -0
- package/esm/src/kernel/tools/resolve.d.ts +28 -0
- package/esm/src/kernel/tools/resolve.js +259 -0
- package/esm/src/kernel/tools/schema.d.ts +10 -0
- package/esm/src/kernel/tools/schema.js +174 -0
- package/esm/src/kernel/tools/signed-in-fetch.d.ts +18 -0
- package/esm/src/kernel/tools/signed-in-fetch.js +45 -0
- package/esm/src/kernel/tools/stage-run.d.ts +93 -0
- package/esm/src/kernel/tools/stage-run.js +140 -0
- package/esm/src/kernel/tools/types.d.ts +287 -0
- package/esm/src/kernel/tools/types.js +1 -0
- package/esm/src/kernel/turn-events.d.ts +599 -0
- package/esm/src/kernel/turn-events.js +425 -0
- package/esm/src/kernel/types.d.ts +884 -0
- package/esm/src/kernel/types.js +1 -0
- package/esm/src/kernel/util/base64.d.ts +2 -0
- package/esm/src/kernel/util/base64.js +13 -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/record.d.ts +1 -0
- package/esm/src/kernel/util/record.js +3 -0
- package/esm/src/observability/destinations.d.ts +9 -0
- package/esm/src/observability/destinations.js +38 -0
- package/esm/src/observability/jsonl.d.ts +18 -0
- package/esm/src/observability/jsonl.js +117 -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 +68 -0
- package/esm/src/observability/otlp.js +98 -0
- package/esm/src/observability/phoenix.d.ts +29 -0
- package/esm/src/observability/phoenix.js +71 -0
- package/esm/src/observability/policy.d.ts +14 -0
- package/esm/src/observability/policy.js +69 -0
- package/esm/src/observability/resolve-policy.d.ts +8 -0
- package/esm/src/observability/resolve-policy.js +58 -0
- package/esm/src/observability/spans.d.ts +16 -0
- package/esm/src/observability/spans.js +56 -0
- package/esm/src/observability/trace-catalog.d.ts +111 -0
- package/esm/src/observability/trace-catalog.js +865 -0
- package/esm/src/observability/trace-record.d.ts +23 -0
- package/esm/src/observability/trace-record.js +223 -0
- package/esm/src/observability/trace-schema.d.ts +54 -0
- package/esm/src/observability/trace-schema.js +59 -0
- package/esm/src/observability/trace-sink.d.ts +13 -0
- package/esm/src/observability/trace-sink.js +3 -0
- package/esm/src/observability/trace-span.d.ts +92 -0
- package/esm/src/observability/trace-span.js +199 -0
- package/esm/src/observability/trace.d.ts +11 -0
- package/esm/src/observability/trace.js +35 -0
- package/esm/src/observability/types.d.ts +85 -0
- package/esm/src/observability/types.js +3 -0
- package/esm/src/presets/google/speech-voices.d.ts +8 -0
- package/esm/src/presets/google/speech-voices.js +38 -0
- package/esm/src/presets/google-limits.d.ts +12 -0
- package/esm/src/presets/google-limits.js +18 -0
- package/esm/src/presets/google.d.ts +104 -0
- package/esm/src/presets/google.js +188 -0
- package/esm/src/presets/mod.d.ts +10 -0
- package/esm/src/presets/mod.js +9 -0
- package/esm/src/presets/openrouter.d.ts +13 -0
- package/esm/src/presets/openrouter.js +13 -0
- package/esm/src/presets/typesafe.d.ts +2 -0
- package/esm/src/presets/typesafe.js +2 -0
- package/esm/src/providers/create-provider.d.ts +21 -0
- package/esm/src/providers/create-provider.js +90 -0
- package/esm/src/providers/decision/usage.d.ts +3 -0
- package/esm/src/providers/decision/usage.js +25 -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/grounding.d.ts +5 -0
- package/esm/src/providers/google/grounding.js +226 -0
- package/esm/src/providers/google/interactions/framing.d.ts +15 -0
- package/esm/src/providers/google/interactions/framing.js +263 -0
- package/esm/src/providers/google/interactions/mod.d.ts +2 -0
- package/esm/src/providers/google/interactions/mod.js +2 -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 +24 -0
- package/esm/src/providers/google/interactions/stream.js +297 -0
- package/esm/src/providers/google/keys.d.ts +20 -0
- package/esm/src/providers/google/keys.js +87 -0
- package/esm/src/providers/google/live/framing.d.ts +51 -0
- package/esm/src/providers/google/live/framing.js +597 -0
- package/esm/src/providers/google/live/mod.d.ts +7 -0
- package/esm/src/providers/google/live/mod.js +7 -0
- package/esm/src/providers/google/live/openapi-schema.d.ts +1 -0
- package/esm/src/providers/google/live/openapi-schema.js +42 -0
- package/esm/src/providers/google/live/session.d.ts +14 -0
- package/esm/src/providers/google/live/session.js +150 -0
- package/esm/src/providers/google/live/stream.d.ts +51 -0
- package/esm/src/providers/google/live/stream.js +263 -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 +6 -0
- package/esm/src/providers/google/urls.js +6 -0
- package/esm/src/providers/google/usage.d.ts +7 -0
- package/esm/src/providers/google/usage.js +49 -0
- package/esm/src/providers/local/local.d.ts +12 -0
- package/esm/src/providers/local/local.js +186 -0
- package/esm/src/providers/local/mod.d.ts +8 -0
- package/esm/src/providers/local/mod.js +8 -0
- package/esm/src/providers/mod.d.ts +11 -0
- package/esm/src/providers/mod.js +7 -0
- package/esm/src/providers/openrouter/cache-control.d.ts +5 -0
- package/esm/src/providers/openrouter/cache-control.js +4 -0
- package/esm/src/providers/openrouter/chat.d.ts +64 -0
- package/esm/src/providers/openrouter/chat.js +490 -0
- package/esm/src/providers/openrouter/image.d.ts +24 -0
- package/esm/src/providers/openrouter/image.js +187 -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/sdk-messages.d.ts +10 -0
- package/esm/src/providers/openrouter/openai/sdk-messages.js +99 -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/resolve-api-key.d.ts +3 -0
- package/esm/src/providers/openrouter/resolve-api-key.js +8 -0
- package/esm/src/providers/openrouter/speech.d.ts +18 -0
- package/esm/src/providers/openrouter/speech.js +109 -0
- package/esm/src/providers/probe.d.ts +5 -0
- package/esm/src/providers/probe.js +15 -0
- package/esm/src/providers/shared/builtin-wire.d.ts +4 -0
- package/esm/src/providers/shared/builtin-wire.js +9 -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/response-identity.d.ts +11 -0
- package/esm/src/providers/shared/response-identity.js +12 -0
- package/esm/src/providers/shared/sse.d.ts +10 -0
- package/esm/src/providers/shared/sse.js +79 -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 +25 -0
- package/esm/src/providers/shared/tool-args.js +84 -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/shared/vault.d.ts +13 -0
- package/esm/src/providers/shared/vault.js +41 -0
- package/esm/src/providers/types.d.ts +19 -0
- package/esm/src/providers/types.js +1 -0
- package/esm/src/surface/formats.d.ts +28 -0
- package/esm/src/surface/formats.js +139 -0
- package/esm/src/surface/mod.d.ts +14 -0
- package/esm/src/surface/mod.js +10 -0
- package/esm/src/surface/runtime.d.ts +40 -0
- package/esm/src/surface/runtime.js +439 -0
- package/esm/src/surface/tools.d.ts +15 -0
- package/esm/src/surface/tools.js +80 -0
- package/esm/src/surface/types.d.ts +104 -0
- package/esm/src/surface/types.js +4 -0
- package/package.json +108 -4
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type EvalRubric } from '../rubrics/types.js';
|
|
2
|
+
import type { EvalGrader, Trial } from '../types.js';
|
|
3
|
+
declare const EVAL_JUDGMENT = "evalJudgment";
|
|
4
|
+
interface Judgment {
|
|
5
|
+
label: string;
|
|
6
|
+
explanation: string;
|
|
7
|
+
}
|
|
8
|
+
interface JudgeOptions {
|
|
9
|
+
rubric: EvalRubric;
|
|
10
|
+
name?: string;
|
|
11
|
+
pass?: readonly string[];
|
|
12
|
+
profile?: string;
|
|
13
|
+
variables?: (trial: Trial) => Record<string, string>;
|
|
14
|
+
/** Decision judges only: how many times worse a wrong pass is than a wrong fail; default 1. */
|
|
15
|
+
wrongPassCost?: number;
|
|
16
|
+
escalate?: string;
|
|
17
|
+
}
|
|
18
|
+
declare function judge(options: JudgeOptions): EvalGrader;
|
|
19
|
+
export type { JudgeOptions, Judgment };
|
|
20
|
+
export { EVAL_JUDGMENT, judge };
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import { errorKind, TheoremError } from '../../guardrails/error.js';
|
|
2
|
+
import { getProfile, registerStructured, runDecision, runTurn, } from '../../kernel/default-scope.js';
|
|
3
|
+
import { mimeAllowed, profileAccept } from '../../kernel/registry/catalog.js';
|
|
4
|
+
import { isRecord } from '../../kernel/util/record.js';
|
|
5
|
+
import { memorySink } from '../../observability/trace.js';
|
|
6
|
+
import { formatTraceparent } from '../../observability/trace-span.js';
|
|
7
|
+
import { fillRubric } from '../rubrics/types.js';
|
|
8
|
+
import { buildTrial } from '../trial.js';
|
|
9
|
+
import { resolveMedia, trialMedia } from './media.js';
|
|
10
|
+
import { deliveredJson, deliveredText } from './shared.js';
|
|
11
|
+
import { rubricView, TRIAL_VARIABLES } from './transcript.js';
|
|
12
|
+
const EVAL_JUDGMENT = 'evalJudgment';
|
|
13
|
+
const UNKNOWN = 'unknown';
|
|
14
|
+
const UNKNOWN_CRITERION = 'The record does not show enough to decide.';
|
|
15
|
+
const VERDICT = 'verdict';
|
|
16
|
+
const FAILED_STOPS = new Set([
|
|
17
|
+
'provider_error',
|
|
18
|
+
'cancelled',
|
|
19
|
+
'stream_incomplete',
|
|
20
|
+
'interrupted',
|
|
21
|
+
]);
|
|
22
|
+
function turnFailure(trial) {
|
|
23
|
+
const stop = trial.root.attributes['theorem.stop.kind'];
|
|
24
|
+
if (typeof stop === 'string' && FAILED_STOPS.has(stop))
|
|
25
|
+
return `the turn stopped with ${stop}`;
|
|
26
|
+
if (deliveredText(trial, undefined) === '' && deliveredJson(trial) === undefined) {
|
|
27
|
+
return `the turn delivered nothing${typeof stop === 'string' ? ` (stopped ${stop})` : ''}`;
|
|
28
|
+
}
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
const JUDGMENT_SCHEMA = {
|
|
32
|
+
jsonSchema: {
|
|
33
|
+
type: 'object',
|
|
34
|
+
properties: {
|
|
35
|
+
label: {
|
|
36
|
+
type: 'string',
|
|
37
|
+
description: `One of the labels the rubric names, exactly as written, or "${UNKNOWN}" when the record does not let you decide.`,
|
|
38
|
+
},
|
|
39
|
+
explanation: {
|
|
40
|
+
type: 'string',
|
|
41
|
+
description: 'Why, in a few sentences, citing what the record shows.',
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
required: ['label', 'explanation'],
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
// Importing this module registers the schema, so a host's judge profile can name it at registration.
|
|
48
|
+
registerStructured(EVAL_JUDGMENT, JUDGMENT_SCHEMA);
|
|
49
|
+
function configError(grader, message) {
|
|
50
|
+
return new TheoremError('config', `judge ${grader}: ${message}`); // lexicon-exempt: developer contract error
|
|
51
|
+
}
|
|
52
|
+
function judgeKind(grader, rubric, profileId) {
|
|
53
|
+
const profile = getProfile(profileId);
|
|
54
|
+
if (profile.type === 'decision') {
|
|
55
|
+
if (!rubric.question) {
|
|
56
|
+
throw configError(grader, `rubric ${rubric.name} has no question for decision profile ${profileId}`);
|
|
57
|
+
}
|
|
58
|
+
return 'decision';
|
|
59
|
+
}
|
|
60
|
+
if (profile.type !== 'text') {
|
|
61
|
+
throw configError(grader, `judge profile ${profileId} is neither a text nor a decision profile`);
|
|
62
|
+
}
|
|
63
|
+
if (profile.outputs?.structured !== EVAL_JUDGMENT) {
|
|
64
|
+
throw configError(grader, `judge profile ${profileId} must set outputs.structured to '${EVAL_JUDGMENT}'`);
|
|
65
|
+
}
|
|
66
|
+
if (rubric.template === undefined) {
|
|
67
|
+
throw configError(grader, `rubric ${rubric.name} has no prompt for text profile ${profileId}`);
|
|
68
|
+
}
|
|
69
|
+
return 'text';
|
|
70
|
+
}
|
|
71
|
+
function traceparentsOf(records) {
|
|
72
|
+
const spans = records[0]?.spans ?? [];
|
|
73
|
+
const ids = new Set(spans.map((span) => span.spanId));
|
|
74
|
+
const root = spans.find((span) => span.parentSpanId === undefined || !ids.has(span.parentSpanId));
|
|
75
|
+
return root ? [formatTraceparent(root.traceId, root.spanId)] : [];
|
|
76
|
+
}
|
|
77
|
+
function judgeStamp(trial, grader) {
|
|
78
|
+
return {
|
|
79
|
+
eval: {
|
|
80
|
+
suite: trial.suite,
|
|
81
|
+
...(trial.case ? { case: trial.case.id } : {}),
|
|
82
|
+
trial: trial.index,
|
|
83
|
+
judge: { grader },
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function judgeCall(trial, grader, context) {
|
|
88
|
+
return {
|
|
89
|
+
metadata: judgeStamp(trial, grader),
|
|
90
|
+
...(context.traceparent ? { traceparent: context.traceparent } : {}),
|
|
91
|
+
...(context.signal ? { signal: context.signal } : {}),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function parseJudgment(value) {
|
|
95
|
+
if (!isRecord(value))
|
|
96
|
+
return undefined;
|
|
97
|
+
const { label, explanation } = value;
|
|
98
|
+
if (typeof label !== 'string' || typeof explanation !== 'string')
|
|
99
|
+
return undefined;
|
|
100
|
+
return { label, explanation };
|
|
101
|
+
}
|
|
102
|
+
async function askText(args) {
|
|
103
|
+
const { context } = args;
|
|
104
|
+
if (!context.judgeProvider) {
|
|
105
|
+
throw configError(args.grader, `no provider for text judge profile ${args.profile}`);
|
|
106
|
+
}
|
|
107
|
+
const records = [];
|
|
108
|
+
let error;
|
|
109
|
+
const request = {
|
|
110
|
+
profile: args.profile,
|
|
111
|
+
input: {
|
|
112
|
+
text: args.prompt,
|
|
113
|
+
...(args.attachments.length > 0 ? { attachments: args.attachments } : {}),
|
|
114
|
+
},
|
|
115
|
+
...judgeCall(args.trial, args.grader, context),
|
|
116
|
+
};
|
|
117
|
+
try {
|
|
118
|
+
for await (const _event of runTurn(request, context.judgeProvider, memorySink(records))) {
|
|
119
|
+
// The judge's trace is its record; its events are not read.
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
catch (thrown) {
|
|
123
|
+
error = errorKind(thrown);
|
|
124
|
+
}
|
|
125
|
+
await context.traced(records);
|
|
126
|
+
if (records.length === 0)
|
|
127
|
+
return { traceparents: [], error: error ?? 'internal' };
|
|
128
|
+
const judged = buildTrial({ suite: args.trial.suite, index: 0, records });
|
|
129
|
+
const traceparents = [formatTraceparent(judged.root.traceId, judged.root.spanId)];
|
|
130
|
+
const failure = judged.root.attributes['error.type'];
|
|
131
|
+
if (error === undefined && typeof failure === 'string')
|
|
132
|
+
error = failure;
|
|
133
|
+
if (error !== undefined)
|
|
134
|
+
return { traceparents, error };
|
|
135
|
+
const judgment = parseJudgment(deliveredJson(judged));
|
|
136
|
+
return judgment ? { traceparents, judgment } : { traceparents, error: 'bad_response' };
|
|
137
|
+
}
|
|
138
|
+
function percent(value) {
|
|
139
|
+
return `${Math.round(value * 100)}%`;
|
|
140
|
+
}
|
|
141
|
+
function choiceJudgment(answer, rule) {
|
|
142
|
+
if (answer?.type !== 'choice')
|
|
143
|
+
return undefined;
|
|
144
|
+
const p = answer.probabilities;
|
|
145
|
+
const odds = Object.entries(p)
|
|
146
|
+
.sort((a, b) => b[1] - a[1])
|
|
147
|
+
.map(([label, value]) => `${label} ${percent(value)}`)
|
|
148
|
+
.join(', ');
|
|
149
|
+
const { pass } = rule;
|
|
150
|
+
if (!pass)
|
|
151
|
+
return { label: answer.choice, explanation: `Jev chose ${answer.choice} (${odds}).` };
|
|
152
|
+
const mass = (labels) => labels.reduce((sum, l) => sum + (p[l] ?? 0), 0);
|
|
153
|
+
const likeliest = (labels) => labels.reduce((best, l) => ((p[l] ?? 0) > (p[best] ?? 0) ? l : best));
|
|
154
|
+
const failing = rule.labels.filter((label) => !pass.includes(label));
|
|
155
|
+
const needs = `passing needs ${pass.join(' or ')} above ${percent(rule.line)}`;
|
|
156
|
+
if (mass(pass) > rule.line) {
|
|
157
|
+
return { label: likeliest(pass), explanation: `Jev: ${odds}; ${needs}.` };
|
|
158
|
+
}
|
|
159
|
+
if (failing.length > 0 && mass(failing) > 0.5) {
|
|
160
|
+
return { label: likeliest(failing), explanation: `Jev: ${odds}; ${needs}.` };
|
|
161
|
+
}
|
|
162
|
+
return { label: UNKNOWN, explanation: `Jev was unsure: ${odds}; ${needs}.` };
|
|
163
|
+
}
|
|
164
|
+
async function askDecision(args) {
|
|
165
|
+
const { context, rubric } = args;
|
|
166
|
+
if (!context.judgeDecision) {
|
|
167
|
+
throw configError(args.grader, `no key for decision judge profile ${args.profile}`);
|
|
168
|
+
}
|
|
169
|
+
if (!rubric.question) {
|
|
170
|
+
throw configError(args.grader, `rubric ${rubric.name} has no question`);
|
|
171
|
+
}
|
|
172
|
+
const question = {
|
|
173
|
+
type: 'choice',
|
|
174
|
+
instructions: rubric.question.instructions,
|
|
175
|
+
criteria: { ...rubric.question.criteria, [UNKNOWN]: UNKNOWN_CRITERION },
|
|
176
|
+
};
|
|
177
|
+
const records = [];
|
|
178
|
+
try {
|
|
179
|
+
const result = await runDecision({
|
|
180
|
+
profile: args.profile,
|
|
181
|
+
state: args.state,
|
|
182
|
+
questions: { [VERDICT]: question },
|
|
183
|
+
...judgeCall(args.trial, args.grader, context),
|
|
184
|
+
}, { ...context.judgeDecision, sink: memorySink(records) });
|
|
185
|
+
await context.traced(records);
|
|
186
|
+
const traceparents = traceparentsOf(records);
|
|
187
|
+
const judgment = choiceJudgment(result.answers[VERDICT], args.rule);
|
|
188
|
+
return judgment ? { traceparents, judgment } : { traceparents, error: 'bad_response' };
|
|
189
|
+
}
|
|
190
|
+
catch (thrown) {
|
|
191
|
+
await context.traced(records);
|
|
192
|
+
return { traceparents: traceparentsOf(records), error: errorKind(thrown) };
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
function escalated(decision, text) {
|
|
196
|
+
const traceparents = [...decision.traceparents, ...text.traceparents];
|
|
197
|
+
if (!text.judgment)
|
|
198
|
+
return { traceparents, error: text.error ?? 'internal' };
|
|
199
|
+
return {
|
|
200
|
+
traceparents,
|
|
201
|
+
judgment: {
|
|
202
|
+
label: text.judgment.label,
|
|
203
|
+
explanation: `${decision.judgment?.explanation ?? ''} The text judge decided: ${text.judgment.explanation}`,
|
|
204
|
+
},
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
function stateOf(rubric, view) {
|
|
208
|
+
const state = {};
|
|
209
|
+
for (const variable of rubric.variables) {
|
|
210
|
+
const value = view[variable];
|
|
211
|
+
if (value === undefined) {
|
|
212
|
+
throw new TheoremError('config', `rubric ${rubric.name}: no value for ${variable}`); // lexicon-exempt: developer contract error
|
|
213
|
+
}
|
|
214
|
+
state[variable] = value;
|
|
215
|
+
}
|
|
216
|
+
return state;
|
|
217
|
+
}
|
|
218
|
+
// Models echo the prompt's headings (`CORRECT -`), so a text judge's label is read case-insensitively.
|
|
219
|
+
function declaredLabel(label, allowed) {
|
|
220
|
+
const wanted = label.trim().toLowerCase();
|
|
221
|
+
return [...allowed].find((declared) => declared.toLowerCase() === wanted);
|
|
222
|
+
}
|
|
223
|
+
function resultOf(run, rubric, name, pass) {
|
|
224
|
+
const base = {
|
|
225
|
+
name,
|
|
226
|
+
source: 'model',
|
|
227
|
+
...(run.traceparents.length > 0 ? { judgeTraceparents: run.traceparents } : {}),
|
|
228
|
+
};
|
|
229
|
+
if (!run.judgment) {
|
|
230
|
+
return {
|
|
231
|
+
...base,
|
|
232
|
+
errorType: run.error ?? 'internal',
|
|
233
|
+
explanation: `the judge gave no judgment (${run.error ?? 'internal'})`,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
const allowed = new Set([...Object.keys(rubric.labels), UNKNOWN]);
|
|
237
|
+
const label = declaredLabel(run.judgment.label, allowed);
|
|
238
|
+
if (label === undefined) {
|
|
239
|
+
return {
|
|
240
|
+
...base,
|
|
241
|
+
errorType: 'bad_response',
|
|
242
|
+
explanation: `the judge answered ${JSON.stringify(run.judgment.label)}, not one of ${[...allowed].join(', ')}`,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
const value = rubric.labels[label];
|
|
246
|
+
return {
|
|
247
|
+
...base,
|
|
248
|
+
score: { ...(value === undefined ? {} : { value }), label },
|
|
249
|
+
explanation: run.judgment.explanation,
|
|
250
|
+
...(pass ? { passed: pass.includes(label) } : {}),
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
function judge(options) {
|
|
254
|
+
const { rubric } = options;
|
|
255
|
+
const name = options.name ?? rubric.name;
|
|
256
|
+
const pass = options.pass ?? rubric.pass;
|
|
257
|
+
const unknownPass = (pass ?? []).filter((label) => !(label in rubric.labels));
|
|
258
|
+
if (unknownPass.length > 0) {
|
|
259
|
+
throw configError(name, `pass names labels the rubric lacks: ${unknownPass.join(', ')}`);
|
|
260
|
+
}
|
|
261
|
+
const unfillable = rubric.variables.filter((variable) => !TRIAL_VARIABLES.includes(variable));
|
|
262
|
+
if (unfillable.length > 0 && !options.variables) {
|
|
263
|
+
throw configError(name, `the rubric needs ${unfillable.join(', ')}, which the trace cannot fill; pass variables`);
|
|
264
|
+
}
|
|
265
|
+
const wrongPassCost = options.wrongPassCost ?? 1;
|
|
266
|
+
if (!(Number.isFinite(wrongPassCost) && wrongPassCost > 0)) {
|
|
267
|
+
throw configError(name, `wrongPassCost must be a positive number, not ${wrongPassCost}`);
|
|
268
|
+
}
|
|
269
|
+
if (options.wrongPassCost !== undefined && !pass) {
|
|
270
|
+
throw configError(name, `wrongPassCost needs labels that pass, and rubric ${rubric.name} names none`);
|
|
271
|
+
}
|
|
272
|
+
const rule = {
|
|
273
|
+
pass,
|
|
274
|
+
labels: Object.keys(rubric.labels),
|
|
275
|
+
line: wrongPassCost / (1 + wrongPassCost),
|
|
276
|
+
};
|
|
277
|
+
const judgeProfile = (suiteJudge) => {
|
|
278
|
+
const profile = options.profile ?? suiteJudge;
|
|
279
|
+
if (!profile)
|
|
280
|
+
throw configError(name, 'names no judge profile, and neither does the suite');
|
|
281
|
+
const kind = judgeKind(name, rubric, profile);
|
|
282
|
+
const decisionOnly = [
|
|
283
|
+
...(options.wrongPassCost === undefined ? [] : ['wrongPassCost']),
|
|
284
|
+
...(options.escalate === undefined ? [] : ['escalate']),
|
|
285
|
+
];
|
|
286
|
+
if (kind === 'text' && decisionOnly.length > 0) {
|
|
287
|
+
throw configError(name, `${decisionOnly.join(' and ')} ${decisionOnly.length > 1 ? 'need' : 'needs'} a decision judge, and ${profile} is a text profile`);
|
|
288
|
+
}
|
|
289
|
+
if (options.escalate !== undefined && judgeKind(name, rubric, options.escalate) !== 'text') {
|
|
290
|
+
throw configError(name, `escalate names ${options.escalate}, which is not a text profile`);
|
|
291
|
+
}
|
|
292
|
+
return profile;
|
|
293
|
+
};
|
|
294
|
+
const identity = [
|
|
295
|
+
`judge:${name}`,
|
|
296
|
+
`labels=${Object.entries(rubric.labels)
|
|
297
|
+
.map(([label, value]) => `${label}:${value}`)
|
|
298
|
+
.join(',')}`,
|
|
299
|
+
`pass=${pass ? [...pass].join(',') : 'none'}`,
|
|
300
|
+
...(options.profile ? [`profile=${options.profile}`] : []),
|
|
301
|
+
...(options.wrongPassCost === undefined ? [] : [`wrongPassCost=${options.wrongPassCost}`]),
|
|
302
|
+
...(options.escalate ? [`escalate=${options.escalate}`] : []),
|
|
303
|
+
`template=${rubric.template ?? ''}`,
|
|
304
|
+
`question=${rubric.question ? JSON.stringify(rubric.question) : ''}`,
|
|
305
|
+
].join('\n');
|
|
306
|
+
const grade = async (trial, context) => {
|
|
307
|
+
const notJudged = (why) => ({
|
|
308
|
+
name,
|
|
309
|
+
source: 'model',
|
|
310
|
+
explanation: `${why}; not judged`,
|
|
311
|
+
});
|
|
312
|
+
const failure = turnFailure(trial);
|
|
313
|
+
if (failure)
|
|
314
|
+
return notJudged(failure);
|
|
315
|
+
const profile = judgeProfile(context.judge);
|
|
316
|
+
const view = rubricView(rubric, trial, options.variables?.(trial) ?? {});
|
|
317
|
+
const read = JSON.stringify(view);
|
|
318
|
+
const media = trialMedia(trial).filter((item) => read.includes(item.label));
|
|
319
|
+
const resolved = await resolveMedia(trial, media, context);
|
|
320
|
+
if ('missing' in resolved) {
|
|
321
|
+
return notJudged(`the judge could not be shown ${resolved.missing.join(', ')}`);
|
|
322
|
+
}
|
|
323
|
+
const { attachments } = resolved;
|
|
324
|
+
const text = (textProfile) => {
|
|
325
|
+
const refused = attachments.filter((item) => !mimeAllowed(profileAccept(getProfile(textProfile), 'attachments') ?? [], item.mimeType));
|
|
326
|
+
if (refused.length > 0) {
|
|
327
|
+
throw configError(name, `judge profile ${textProfile} must accept ${[...new Set(refused.map((item) => item.mimeType))].join(', ')} to see the media it judges`);
|
|
328
|
+
}
|
|
329
|
+
return askText({
|
|
330
|
+
trial,
|
|
331
|
+
prompt: fillRubric(rubric, view),
|
|
332
|
+
profile: textProfile,
|
|
333
|
+
grader: name,
|
|
334
|
+
context,
|
|
335
|
+
attachments,
|
|
336
|
+
});
|
|
337
|
+
};
|
|
338
|
+
if (judgeKind(name, rubric, profile) === 'text')
|
|
339
|
+
return resultOf(await text(profile), rubric, name, pass);
|
|
340
|
+
if (attachments.length > 0) {
|
|
341
|
+
if (!options.escalate) {
|
|
342
|
+
return notJudged(`decision judge ${profile} cannot see ${media.map((item) => item.label).join(', ')} and no escalate judge can`);
|
|
343
|
+
}
|
|
344
|
+
return resultOf(await text(options.escalate), rubric, name, pass);
|
|
345
|
+
}
|
|
346
|
+
const run = await askDecision({
|
|
347
|
+
trial,
|
|
348
|
+
rubric,
|
|
349
|
+
rule,
|
|
350
|
+
state: stateOf(rubric, view),
|
|
351
|
+
profile,
|
|
352
|
+
grader: name,
|
|
353
|
+
context,
|
|
354
|
+
});
|
|
355
|
+
if (!options.escalate || run.judgment?.label !== UNKNOWN)
|
|
356
|
+
return resultOf(run, rubric, name, pass);
|
|
357
|
+
return resultOf(escalated(run, await text(options.escalate)), rubric, name, pass);
|
|
358
|
+
};
|
|
359
|
+
const judgeProfiles = (suiteJudge) => [
|
|
360
|
+
judgeProfile(suiteJudge),
|
|
361
|
+
...(options.escalate === undefined ? [] : [options.escalate]),
|
|
362
|
+
];
|
|
363
|
+
return { name, identity, source: 'model', needsExpect: false, judgeProfiles, grade };
|
|
364
|
+
}
|
|
365
|
+
export { EVAL_JUDGMENT, judge };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { codeGrader, passFail } from './shared.js';
|
|
2
|
+
const MS_PER_S = 1000;
|
|
3
|
+
const NANOS_PER_MS = 1000000n;
|
|
4
|
+
const ACTIVITY_END = 'ACTIVITY_END';
|
|
5
|
+
function msBetween(fromUnixNano, toUnixNano) {
|
|
6
|
+
return Number((toUnixNano - fromUnixNano) / NANOS_PER_MS);
|
|
7
|
+
}
|
|
8
|
+
function numberAttribute(span, key) {
|
|
9
|
+
const value = span.attributes[key];
|
|
10
|
+
return typeof value === 'number' ? value : undefined;
|
|
11
|
+
}
|
|
12
|
+
// The successful (last) HTTP try's start plus its time to first chunk, or the call's own start when the call streamed over a socket (Live).
|
|
13
|
+
function firstChunkAt(trial, call) {
|
|
14
|
+
const seconds = numberAttribute(call, 'gen_ai.response.time_to_first_chunk');
|
|
15
|
+
if (seconds === undefined)
|
|
16
|
+
return undefined;
|
|
17
|
+
const tries = trial.children(call).filter((span) => 'http.request.method' in span.attributes);
|
|
18
|
+
const from = tries.at(-1) ?? call;
|
|
19
|
+
return BigInt(from.startTimeUnixNano) + BigInt(Math.round(seconds * MS_PER_S)) * NANOS_PER_MS;
|
|
20
|
+
}
|
|
21
|
+
// Speech that prompted an earlier reply never anchors a later one.
|
|
22
|
+
function speechEndedAt(root, afterUnixNano, beforeUnixNano) {
|
|
23
|
+
let latest;
|
|
24
|
+
for (const event of root.events) {
|
|
25
|
+
if (event.name !== 'theorem.session')
|
|
26
|
+
continue;
|
|
27
|
+
if (event.attributes.kind !== 'voice_activity' || event.attributes.activity !== ACTIVITY_END) {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
const at = BigInt(event.timeUnixNano);
|
|
31
|
+
if (afterUnixNano !== undefined && at <= afterUnixNano)
|
|
32
|
+
continue;
|
|
33
|
+
if (at <= beforeUnixNano && (latest === undefined || at > latest))
|
|
34
|
+
latest = at;
|
|
35
|
+
}
|
|
36
|
+
return latest;
|
|
37
|
+
}
|
|
38
|
+
function reading(span, from, chunk) {
|
|
39
|
+
if (chunk === undefined)
|
|
40
|
+
return { span, missing: 'first chunk not recorded' };
|
|
41
|
+
return { span, ms: msBetween(from, chunk) };
|
|
42
|
+
}
|
|
43
|
+
function latencyReadings(trial) {
|
|
44
|
+
const responses = trial.spans('generate_content');
|
|
45
|
+
if (responses.length > 0) {
|
|
46
|
+
return responses.map((response, index) => {
|
|
47
|
+
const chunk = firstChunkAt(trial, response);
|
|
48
|
+
const start = BigInt(response.startTimeUnixNano);
|
|
49
|
+
const previous = responses[index - 1];
|
|
50
|
+
const after = previous ? BigInt(previous.startTimeUnixNano) : undefined;
|
|
51
|
+
const from = chunk === undefined ? start : (speechEndedAt(trial.root, after, chunk) ?? start);
|
|
52
|
+
return reading(response, from, chunk);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
const [firstCall] = trial.spans('chat');
|
|
56
|
+
if (!firstCall)
|
|
57
|
+
return [];
|
|
58
|
+
return [
|
|
59
|
+
reading(trial.root, BigInt(trial.root.startTimeUnixNano), firstChunkAt(trial, firstCall)),
|
|
60
|
+
];
|
|
61
|
+
}
|
|
62
|
+
function turnLatency(options) {
|
|
63
|
+
return codeGrader('turn_latency', `turnLatency:${options.maxMs}`, false, (trial) => {
|
|
64
|
+
const readings = latencyReadings(trial);
|
|
65
|
+
if (readings.length === 0)
|
|
66
|
+
return passFail('turn_latency', false, 'no model call recorded');
|
|
67
|
+
const over = readings.flatMap((entry, index) => {
|
|
68
|
+
const name = readings.length === 1 ? 'reply' : `reply ${index + 1}`;
|
|
69
|
+
if (entry.ms === undefined)
|
|
70
|
+
return [`${name}: ${entry.missing}`];
|
|
71
|
+
return entry.ms > options.maxMs ? [`${name}: ${entry.ms} ms over ${options.maxMs}`] : [];
|
|
72
|
+
});
|
|
73
|
+
const measured = readings.flatMap((entry) => entry.ms ?? []);
|
|
74
|
+
const summary = measured.length === 1
|
|
75
|
+
? `reply began after ${measured[0]} ms`
|
|
76
|
+
: `${measured.length} replies began within ${Math.max(...measured)} ms`;
|
|
77
|
+
const passed = over.length === 0;
|
|
78
|
+
return passFail('turn_latency', passed, passed ? summary : over.join('; '));
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
export { turnLatency };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { EvalGrader } from '../types.js';
|
|
2
|
+
interface TranscriptionGraders {
|
|
3
|
+
includes: (text?: string) => EvalGrader;
|
|
4
|
+
regex: (pattern?: string, flags?: string) => EvalGrader;
|
|
5
|
+
}
|
|
6
|
+
declare const transcription: TranscriptionGraders;
|
|
7
|
+
declare function interruptions(options: {
|
|
8
|
+
max: number;
|
|
9
|
+
}): EvalGrader;
|
|
10
|
+
export type { TranscriptionGraders };
|
|
11
|
+
export { interruptions, transcription };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { codeGrader, deliveredText, passFail } from './shared.js';
|
|
2
|
+
const OUTPUT_TRANSCRIPTION = 'output_transcription';
|
|
3
|
+
const transcription = {
|
|
4
|
+
includes(text) {
|
|
5
|
+
const identity = `transcription.includes:${text ?? 'case'}`;
|
|
6
|
+
return codeGrader('transcription_includes', identity, text === undefined, (trial) => {
|
|
7
|
+
const want = text ?? trial.case?.expect?.transcription?.includes;
|
|
8
|
+
if (want === undefined) {
|
|
9
|
+
return passFail('transcription_includes', false, 'case has no expect.transcription.includes');
|
|
10
|
+
}
|
|
11
|
+
const passed = deliveredText(trial, OUTPUT_TRANSCRIPTION).includes(want);
|
|
12
|
+
return passFail('transcription_includes', passed, passed
|
|
13
|
+
? `transcript includes ${JSON.stringify(want)}`
|
|
14
|
+
: `transcript lacks ${JSON.stringify(want)}`);
|
|
15
|
+
});
|
|
16
|
+
},
|
|
17
|
+
regex(pattern, flags = '') {
|
|
18
|
+
const identity = `transcription.regex:${pattern === undefined ? 'case' : `/${pattern}/${flags}`}`;
|
|
19
|
+
return codeGrader('transcription_regex', identity, pattern === undefined, (trial) => {
|
|
20
|
+
const source = pattern ?? trial.case?.expect?.transcription?.regex;
|
|
21
|
+
if (source === undefined) {
|
|
22
|
+
return passFail('transcription_regex', false, 'case has no expect.transcription.regex');
|
|
23
|
+
}
|
|
24
|
+
const passed = new RegExp(source, flags).test(deliveredText(trial, OUTPUT_TRANSCRIPTION));
|
|
25
|
+
return passFail('transcription_regex', passed, passed
|
|
26
|
+
? `transcript matches /${source}/${flags}`
|
|
27
|
+
: `transcript does not match /${source}/${flags}`);
|
|
28
|
+
});
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
function interruptions(options) {
|
|
32
|
+
return codeGrader('interruptions', `interruptions:${options.max}`, false, (trial) => {
|
|
33
|
+
const count = trial
|
|
34
|
+
.spans('generate_content')
|
|
35
|
+
.filter((span) => span.attributes['theorem.stop.kind'] === 'interrupted').length;
|
|
36
|
+
const passed = count <= options.max;
|
|
37
|
+
return passFail('interruptions', passed, `${count} interruption(s); at most ${options.max} allowed`);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
export { interruptions, transcription };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { TurnBlob, TurnMediaRef } from '../../kernel/types.js';
|
|
2
|
+
import type { EvalGradeContext, Trial } from '../types.js';
|
|
3
|
+
interface TrialMedia {
|
|
4
|
+
label: string;
|
|
5
|
+
mimeType: string;
|
|
6
|
+
from: 'input' | 'output';
|
|
7
|
+
sha256?: string;
|
|
8
|
+
uri?: string;
|
|
9
|
+
}
|
|
10
|
+
declare function trialMedia(trial: Trial): TrialMedia[];
|
|
11
|
+
declare function mediaLabeler(trial: Trial): (part: Record<string, unknown>) => string;
|
|
12
|
+
declare function resolveMedia(trial: Trial, media: readonly TrialMedia[], context: EvalGradeContext): Promise<{
|
|
13
|
+
attachments: Array<TurnBlob | TurnMediaRef>;
|
|
14
|
+
} | {
|
|
15
|
+
missing: string[];
|
|
16
|
+
}>;
|
|
17
|
+
export type { TrialMedia };
|
|
18
|
+
export { mediaLabeler, resolveMedia, trialMedia };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { sha256Base64 } from '../../kernel/engine/hash.js';
|
|
2
|
+
import { isRecord } from '../../kernel/util/record.js';
|
|
3
|
+
import { attachmentData } from '../attachments.js';
|
|
4
|
+
import { modelCalls } from './shared.js';
|
|
5
|
+
function mediaKey(part) {
|
|
6
|
+
if (part.type === 'blob' && typeof part.content_sha256 === 'string')
|
|
7
|
+
return part.content_sha256;
|
|
8
|
+
if (part.type === 'uri' && typeof part.uri === 'string')
|
|
9
|
+
return part.uri;
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
function messageParts(messages) {
|
|
13
|
+
if (!Array.isArray(messages))
|
|
14
|
+
return [];
|
|
15
|
+
return messages.flatMap((message) => isRecord(message) && Array.isArray(message.parts) ? message.parts.filter(isRecord) : []);
|
|
16
|
+
}
|
|
17
|
+
function trialMedia(trial) {
|
|
18
|
+
const parts = [
|
|
19
|
+
...messageParts(trial.content(trial.root.attributes['gen_ai.input.messages'])).map((part) => ({
|
|
20
|
+
part,
|
|
21
|
+
from: 'input',
|
|
22
|
+
})),
|
|
23
|
+
...modelCalls(trial).flatMap((span) => messageParts(trial.content(span.attributes['gen_ai.output.messages'])).map((part) => ({
|
|
24
|
+
part,
|
|
25
|
+
from: 'output',
|
|
26
|
+
}))),
|
|
27
|
+
];
|
|
28
|
+
const media = new Map();
|
|
29
|
+
for (const { part, from } of parts) {
|
|
30
|
+
const key = mediaKey(part);
|
|
31
|
+
if (key === undefined || media.has(key))
|
|
32
|
+
continue;
|
|
33
|
+
const mimeType = typeof part.mime_type === 'string' ? part.mime_type : 'application/octet-stream';
|
|
34
|
+
const kind = typeof part.modality === 'string' ? part.modality : 'file';
|
|
35
|
+
media.set(key, {
|
|
36
|
+
label: `[${kind} ${media.size + 1}: ${mimeType}]`,
|
|
37
|
+
mimeType,
|
|
38
|
+
from,
|
|
39
|
+
...(part.type === 'blob' ? { sha256: key } : { uri: key }),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return [...media.values()];
|
|
43
|
+
}
|
|
44
|
+
function mediaLabeler(trial) {
|
|
45
|
+
const byKey = new Map(trialMedia(trial).map((media) => [media.sha256 ?? media.uri ?? '', media.label]));
|
|
46
|
+
return (part) => byKey.get(mediaKey(part) ?? '') ?? `[${String(part.type)}]`;
|
|
47
|
+
}
|
|
48
|
+
// A file's hash is the one its case pins.
|
|
49
|
+
async function caseAttachments(trial) {
|
|
50
|
+
const byHash = new Map();
|
|
51
|
+
const input = trial.case?.input;
|
|
52
|
+
const attachments = input && 'attachments' in input ? (input.attachments ?? []) : [];
|
|
53
|
+
for (const attachment of attachments) {
|
|
54
|
+
if (!('data' in attachment)) {
|
|
55
|
+
byHash.set(attachment.sha256, attachment);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const digest = await sha256Base64(attachment.data);
|
|
59
|
+
if (digest)
|
|
60
|
+
byHash.set(digest.hash, attachment);
|
|
61
|
+
}
|
|
62
|
+
return byHash;
|
|
63
|
+
}
|
|
64
|
+
// The host's bytes for a hash, only when they are the bytes the trace hashed.
|
|
65
|
+
async function fromHost(sha256, mimeType, context) {
|
|
66
|
+
const data = await context.media?.({ sha256, mimeType });
|
|
67
|
+
if (data === undefined)
|
|
68
|
+
return undefined;
|
|
69
|
+
return (await sha256Base64(data))?.hash === sha256 ? data : undefined;
|
|
70
|
+
}
|
|
71
|
+
async function resolveMedia(trial, media, context) {
|
|
72
|
+
const fromCase = await caseAttachments(trial);
|
|
73
|
+
const attachments = [];
|
|
74
|
+
const missing = [];
|
|
75
|
+
for (const item of media) {
|
|
76
|
+
if (item.uri !== undefined) {
|
|
77
|
+
attachments.push({ mimeType: item.mimeType, uri: item.uri });
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
const sha256 = item.sha256 ?? '';
|
|
81
|
+
const attachment = fromCase.get(sha256);
|
|
82
|
+
const data = attachment
|
|
83
|
+
? await attachmentData(attachment)
|
|
84
|
+
: await fromHost(sha256, item.mimeType, context);
|
|
85
|
+
if (data === undefined)
|
|
86
|
+
missing.push(item.label);
|
|
87
|
+
else
|
|
88
|
+
attachments.push({ mimeType: item.mimeType, data });
|
|
89
|
+
}
|
|
90
|
+
return missing.length > 0 ? { missing } : { attachments };
|
|
91
|
+
}
|
|
92
|
+
export { mediaLabeler, resolveMedia, trialMedia };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { TraceSpan } from '../../observability/trace-span.js';
|
|
2
|
+
import type { EvalGrader, EvalResult, Trial } from '../types.js';
|
|
3
|
+
declare function passFail(name: string, passed: boolean, explanation: string): EvalResult;
|
|
4
|
+
declare function codeGrader(name: string, identity: string, needsExpect: boolean, grade: (trial: Trial) => EvalResult | Promise<EvalResult>): EvalGrader;
|
|
5
|
+
declare function deliveredText(trial: Trial, source: string | undefined): string;
|
|
6
|
+
declare function deliveredJson(trial: Trial): unknown;
|
|
7
|
+
declare function startOf(span: TraceSpan): bigint;
|
|
8
|
+
declare function modelCalls(trial: Trial): TraceSpan[];
|
|
9
|
+
declare function spanDurationMs(span: TraceSpan): number;
|
|
10
|
+
declare function listOf(items: readonly string[]): string;
|
|
11
|
+
export { codeGrader, deliveredJson, deliveredText, listOf, modelCalls, passFail, spanDurationMs, startOf, };
|