niceeval 0.9.1 → 0.10.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/INDEX.md +31 -33
- package/dist/agents/types.d.ts +20 -17
- package/dist/context/types.d.ts +21 -21
- package/dist/i18n/en.d.ts +10 -2
- package/dist/i18n/zh-CN.d.ts +14 -6
- package/dist/o11y/execution-tree.d.ts +103 -0
- package/dist/o11y/otlp/select.d.ts +22 -0
- package/dist/report/{react → assets}/colors.d.ts +8 -0
- package/dist/report/{react → assets}/colors.js +23 -0
- package/dist/report/built-in/index.d.ts +2 -2
- package/dist/report/built-in/index.js +2 -2
- package/dist/report/built-in/standard.d.ts +8 -1
- package/dist/report/built-in/standard.js +17 -7
- package/dist/report/components/attempt-detail/AttemptAssertions.d.ts +6 -0
- package/dist/report/components/attempt-detail/AttemptAssertions.js +17 -0
- package/dist/report/components/attempt-detail/AttemptConversation.d.ts +6 -0
- package/dist/report/components/attempt-detail/AttemptConversation.js +34 -0
- package/dist/report/components/attempt-detail/AttemptDiagnostics.d.ts +6 -0
- package/dist/report/components/attempt-detail/AttemptDiagnostics.js +7 -0
- package/dist/report/components/attempt-detail/AttemptDiff.d.ts +6 -0
- package/dist/report/components/attempt-detail/AttemptDiff.js +11 -0
- package/dist/report/components/attempt-detail/AttemptError.d.ts +6 -0
- package/dist/report/components/attempt-detail/AttemptError.js +16 -0
- package/dist/report/components/attempt-detail/AttemptFixPrompt.d.ts +6 -0
- package/dist/report/components/attempt-detail/AttemptFixPrompt.js +7 -0
- package/dist/report/components/attempt-detail/AttemptSource.d.ts +6 -0
- package/dist/report/components/attempt-detail/AttemptSource.js +27 -0
- package/dist/report/components/attempt-detail/AttemptSummary.d.ts +8 -0
- package/dist/report/components/attempt-detail/AttemptSummary.js +20 -0
- package/dist/report/components/attempt-detail/AttemptTimeline.d.ts +6 -0
- package/dist/report/components/attempt-detail/AttemptTimeline.js +28 -0
- package/dist/report/components/attempt-detail/AttemptTrace.d.ts +6 -0
- package/dist/report/components/attempt-detail/AttemptTrace.js +29 -0
- package/dist/report/components/attempt-detail/AttemptUsage.d.ts +6 -0
- package/dist/report/components/attempt-detail/AttemptUsage.js +20 -0
- package/dist/report/components/attempt-detail/compute.d.ts +24 -0
- package/dist/report/components/attempt-detail/compute.js +254 -0
- package/dist/report/components/attempt-detail/faces.d.ts +14 -0
- package/dist/report/components/attempt-detail/faces.js +235 -0
- package/dist/report/components/attempt-detail/index.d.ts +38 -0
- package/dist/report/components/attempt-detail/index.js +527 -0
- package/dist/report/{react → components}/cell.d.ts +5 -3
- package/dist/report/{react → components}/cell.js +3 -3
- package/dist/report/{react → components/entity-lists}/AttemptList.d.ts +8 -4
- package/dist/report/{react → components/entity-lists}/AttemptList.js +16 -10
- package/dist/report/{react → components/entity-lists}/EvalList.d.ts +3 -3
- package/dist/report/{react → components/entity-lists}/EvalList.js +0 -0
- package/dist/report/{react → components/entity-lists}/ExperimentList.d.ts +3 -3
- package/dist/report/{react → components/entity-lists}/ExperimentList.js +10 -10
- package/dist/report/components/entity-lists/compute.d.ts +23 -0
- package/dist/report/components/entity-lists/compute.js +171 -0
- package/dist/report/components/entity-lists/faces.d.ts +5 -0
- package/dist/report/components/entity-lists/faces.js +174 -0
- package/dist/report/components/entity-lists/index.d.ts +51 -0
- package/dist/report/components/entity-lists/index.js +165 -0
- package/dist/report/{react → components}/fixtures.d.ts +2 -2
- package/dist/report/{react → components}/fixtures.js +1 -1
- package/dist/report/{react → components/metric-views}/DeltaTable.d.ts +2 -2
- package/dist/report/{react → components/metric-views}/DeltaTable.js +4 -4
- package/dist/report/{react → components/metric-views}/MetricBars.d.ts +3 -3
- package/dist/report/{react → components/metric-views}/MetricBars.js +3 -3
- package/dist/report/{react → components/metric-views}/MetricLine.d.ts +2 -2
- package/dist/report/{react → components/metric-views}/MetricLine.js +8 -5
- package/dist/report/{react → components/metric-views}/MetricMatrix.d.ts +3 -3
- package/dist/report/{react → components/metric-views}/MetricMatrix.js +4 -4
- package/dist/report/components/metric-views/MetricScatter.d.ts +11 -0
- package/dist/report/{react → components/metric-views}/MetricScatter.js +26 -23
- package/dist/report/{react → components/metric-views}/MetricTable.d.ts +3 -3
- package/dist/report/{react → components/metric-views}/MetricTable.js +4 -4
- package/dist/report/{react → components/metric-views}/Scoreboard.d.ts +2 -2
- package/dist/report/{react → components/metric-views}/Scoreboard.js +3 -3
- package/dist/report/components/metric-views/compute.d.ts +89 -0
- package/dist/report/{compute.js → components/metric-views/compute.js} +32 -415
- package/dist/report/components/metric-views/faces.d.ts +13 -0
- package/dist/report/components/metric-views/faces.js +381 -0
- package/dist/report/components/metric-views/index.d.ts +50 -0
- package/dist/report/components/metric-views/index.js +273 -0
- package/dist/report/{text → components/metric-views}/plot.js +1 -1
- package/dist/report/components/shared-compute.d.ts +22 -0
- package/dist/report/components/shared-compute.js +47 -0
- package/dist/report/components/shared-faces.d.ts +9 -0
- package/dist/report/components/shared-faces.js +26 -0
- package/dist/report/components/shared.d.ts +68 -0
- package/dist/report/components/shared.js +125 -0
- package/dist/report/{react → components/site-components}/CopyFixPrompt.d.ts +2 -2
- package/dist/report/{react → components/site-components}/CopyFixPrompt.js +2 -2
- package/dist/report/{react → components/site-components}/HeroCard.d.ts +2 -2
- package/dist/report/{react → components/site-components}/HeroCard.js +2 -2
- package/dist/report/{react → components/site-components}/ScopeWarnings.d.ts +2 -2
- package/dist/report/{react → components/site-components}/ScopeWarnings.js +3 -3
- package/dist/report/{react → components/site-components}/TraceWaterfall.d.ts +3 -3
- package/dist/report/{react → components/site-components}/TraceWaterfall.js +5 -5
- package/dist/report/components/site-components/compute.d.ts +28 -0
- package/dist/report/components/site-components/compute.js +132 -0
- package/dist/report/components/site-components/faces.d.ts +21 -0
- package/dist/report/components/site-components/faces.js +75 -0
- package/dist/report/components/site-components/index.d.ts +74 -0
- package/dist/report/components/site-components/index.js +220 -0
- package/dist/report/{scope-warnings.d.ts → components/site-components/scope-warnings.d.ts} +2 -2
- package/dist/report/{scope-warnings.js → components/site-components/scope-warnings.js} +2 -2
- package/dist/report/{react → components/summaries}/ScopeSummary.d.ts +2 -2
- package/dist/report/{react → components/summaries}/ScopeSummary.js +17 -8
- package/dist/report/components/summaries/compute.d.ts +7 -0
- package/dist/report/components/summaries/compute.js +51 -0
- package/dist/report/components/summaries/faces.d.ts +7 -0
- package/dist/report/components/summaries/faces.js +38 -0
- package/dist/report/components/summaries/index.d.ts +27 -0
- package/dist/report/components/summaries/index.js +78 -0
- package/dist/report/definition/grid-layout.d.ts +50 -0
- package/dist/report/definition/grid-layout.js +89 -0
- package/dist/report/{primitives.d.ts → definition/primitives.d.ts} +34 -4
- package/dist/report/{primitives.js → definition/primitives.js} +101 -10
- package/dist/report/{report.d.ts → definition/report.d.ts} +36 -65
- package/dist/report/{report.js → definition/report.js} +58 -90
- package/dist/report/{text/table.d.ts → definition/table-text.d.ts} +2 -2
- package/dist/report/{text/table.js → definition/table-text.js} +2 -2
- package/dist/report/{tree.d.ts → definition/tree.d.ts} +43 -11
- package/dist/report/{tree.js → definition/tree.js} +9 -11
- package/dist/report/index.d.ts +33 -18
- package/dist/report/index.js +23 -14
- package/dist/report/{aggregate.d.ts → model/aggregate.d.ts} +12 -4
- package/dist/report/{aggregate.js → model/aggregate.js} +28 -8
- package/dist/report/{flag.d.ts → model/flag.d.ts} +14 -1
- package/dist/report/{flag.js → model/flag.js} +35 -0
- package/dist/report/{format.d.ts → model/format.d.ts} +11 -5
- package/dist/report/{format.js → model/format.js} +48 -4
- package/dist/report/{locale.d.ts → model/locale.d.ts} +17 -17
- package/dist/report/{locale.js → model/locale.js} +31 -33
- package/dist/report/{metrics.d.ts → model/metrics.d.ts} +2 -2
- package/dist/report/{metrics.js → model/metrics.js} +2 -2
- package/dist/report/{types.d.ts → model/types.d.ts} +140 -20
- package/dist/report/react/index.d.ts +32 -21
- package/dist/report/react/index.js +33 -21
- package/dist/report/{load.d.ts → runtime/load.d.ts} +1 -1
- package/dist/report/{load.js → runtime/load.js} +1 -1
- package/dist/report/runtime/text.d.ts +67 -0
- package/dist/report/runtime/text.js +114 -0
- package/dist/report/runtime/web.d.ts +35 -0
- package/dist/report/runtime/web.js +70 -0
- package/dist/results/annotated-source.d.ts +87 -0
- package/dist/results/attempt-evidence.d.ts +74 -0
- package/dist/results/attempt-source.d.ts +15 -0
- package/dist/results/select.d.ts +11 -1
- package/dist/results/select.js +27 -5
- package/dist/runner/eval-selection.d.ts +26 -0
- package/dist/runner/feedback/sink.d.ts +26 -1
- package/dist/runner/types.d.ts +149 -23
- package/dist/sandbox/docker.d.ts +6 -0
- package/dist/sandbox/types.d.ts +23 -21
- package/dist/scoring/display.d.ts +7 -2
- package/dist/scoring/display.js +42 -4
- package/dist/scoring/types.d.ts +3 -3
- package/dist/shared/aggregate.d.ts +14 -0
- package/dist/shared/aggregate.js +31 -0
- package/dist/shared/types.d.ts +6 -1
- package/docs-site/images/logo-dark.svg +7 -0
- package/docs-site/images/logo.svg +6 -5
- package/docs-site/zh/README.md +8 -7
- package/docs-site/zh/examples/ai-agent-application.mdx +5 -5
- package/docs-site/zh/examples/coding-agent-extensions.mdx +4 -4
- package/docs-site/zh/examples/index.mdx +3 -3
- package/docs-site/zh/examples/integrations/ai-sdk-v7.mdx +1 -1
- package/docs-site/zh/examples/integrations/claude-sdk.mdx +3 -3
- package/docs-site/zh/examples/integrations/codex-sdk.mdx +3 -3
- package/docs-site/zh/examples/integrations/langgraph.mdx +3 -3
- package/docs-site/zh/examples/integrations/pi-sdk.mdx +2 -2
- package/docs-site/zh/explanation/adapter.mdx +19 -19
- package/docs-site/zh/explanation/assert.mdx +9 -9
- package/docs-site/zh/explanation/drive.mdx +4 -4
- package/docs-site/zh/explanation/evals.mdx +8 -8
- package/docs-site/zh/explanation/experiment.mdx +8 -8
- package/docs-site/zh/explanation/hitl.mdx +13 -13
- package/docs-site/zh/explanation/judge.mdx +3 -3
- package/docs-site/zh/explanation/overview.mdx +7 -7
- package/docs-site/zh/explanation/runner.mdx +11 -11
- package/docs-site/zh/explanation/tier.mdx +6 -6
- package/docs-site/zh/index.mdx +14 -14
- package/docs-site/zh/introduction.mdx +13 -16
- package/docs-site/zh/reference/builtin-agents.mdx +61 -28
- package/docs-site/zh/reference/capabilities.mdx +7 -27
- package/docs-site/zh/reference/cli.mdx +35 -32
- package/docs-site/zh/reference/define-agent.mdx +32 -31
- package/docs-site/zh/reference/define-config.mdx +6 -6
- package/docs-site/zh/reference/define-eval.mdx +33 -20
- package/docs-site/zh/reference/events.mdx +4 -4
- package/docs-site/zh/reference/expect.mdx +3 -3
- package/docs-site/zh/reference/official-adapters.mdx +17 -17
- package/docs-site/zh/reference/report-components.mdx +193 -121
- package/docs-site/zh/reference/results-data.mdx +13 -13
- package/docs-site/zh/troubleshooting/debug-sandbox.mdx +11 -11
- package/docs-site/zh/troubleshooting/debugging.mdx +40 -16
- package/docs-site/zh/{how-to → tutorials}/agent-feedback-loop.mdx +38 -38
- package/docs-site/zh/tutorials/agent-onboarding.mdx +100 -0
- package/docs-site/zh/tutorials/authoring.mdx +211 -0
- package/docs-site/zh/{how-to → tutorials}/ci-integration.mdx +8 -8
- package/docs-site/zh/{how-to → tutorials}/connect-otel.mdx +22 -22
- package/docs-site/zh/{how-to → tutorials}/connect-your-agent.mdx +58 -63
- package/docs-site/zh/tutorials/custom-reports.mdx +453 -0
- package/docs-site/zh/{how-to → tutorials}/dataset-fanout.mdx +4 -4
- package/docs-site/zh/tutorials/experiments.mdx +103 -0
- package/docs-site/zh/{how-to → tutorials}/fixtures.mdx +9 -9
- package/docs-site/zh/{how-to → tutorials}/publish-report.mdx +6 -6
- package/docs-site/zh/tutorials/quickstart.mdx +18 -18
- package/docs-site/zh/{how-to → tutorials}/reporters.mdx +6 -6
- package/docs-site/zh/{how-to → tutorials}/sandbox-agent.mdx +6 -6
- package/docs-site/zh/{how-to → tutorials}/sandbox-providers.mdx +41 -19
- package/docs-site/zh/{how-to → tutorials}/scoring-guide.mdx +4 -4
- package/docs-site/zh/{how-to → tutorials}/viewing-results.mdx +49 -49
- package/docs-site/zh/tutorials/write-experiment.mdx +355 -0
- package/docs-site/zh/{how-to → tutorials}/write-send.mdx +40 -40
- package/package.json +8 -4
- package/src/agents/bub.ts +21 -8
- package/src/agents/claude-code.ts +23 -10
- package/src/agents/codex.test.ts +22 -7
- package/src/agents/codex.ts +22 -9
- package/src/agents/index.ts +2 -2
- package/src/agents/openai-compat.ts +1 -1
- package/src/agents/post-setup.ts +45 -22
- package/src/agents/streaming.ts +1 -1
- package/src/agents/types.ts +20 -17
- package/src/agents/ui-message-stream.test.ts +10 -0
- package/src/agents/ui-message-stream.ts +12 -1
- package/src/cli.ts +71 -57
- package/src/context/types.ts +21 -21
- package/src/define.ts +13 -0
- package/src/i18n/en.ts +27 -12
- package/src/i18n/zh-CN.ts +27 -12
- package/src/index.ts +2 -0
- package/src/report/{react → assets}/colors.ts +22 -0
- package/src/report/{react → assets}/enhance.js +1 -33
- package/src/report/{react → assets}/styles.css +124 -106
- package/src/report/built-in/index.tsx +2 -2
- package/src/report/built-in/standard.tsx +18 -6
- package/src/report/components/attempt-detail/AttemptAssertions.tsx +67 -0
- package/src/report/components/attempt-detail/AttemptConversation.tsx +110 -0
- package/src/report/components/attempt-detail/AttemptDiagnostics.tsx +38 -0
- package/src/report/components/attempt-detail/AttemptDiff.tsx +35 -0
- package/src/report/components/attempt-detail/AttemptError.tsx +31 -0
- package/src/report/components/attempt-detail/AttemptFixPrompt.tsx +26 -0
- package/src/report/components/attempt-detail/AttemptSource.tsx +80 -0
- package/src/report/components/attempt-detail/AttemptSummary.tsx +74 -0
- package/src/report/components/attempt-detail/AttemptTimeline.tsx +108 -0
- package/src/report/components/attempt-detail/AttemptTrace.tsx +63 -0
- package/src/report/components/attempt-detail/AttemptUsage.tsx +29 -0
- package/src/report/components/attempt-detail/attempt-components.test.tsx +680 -0
- package/src/report/components/attempt-detail/compute.ts +287 -0
- package/src/report/components/attempt-detail/faces.ts +257 -0
- package/src/report/components/attempt-detail/index.tsx +583 -0
- package/src/report/components/attempt-detail/validate.test.ts +235 -0
- package/src/report/{react → components}/cell.tsx +6 -3
- package/src/report/{report.test.ts → components/compute.test.ts} +316 -46
- package/src/report/{react → components/entity-lists}/AttemptList.tsx +24 -16
- package/src/report/{react → components/entity-lists}/EvalList.tsx +0 -0
- package/src/report/{react → components/entity-lists}/ExperimentList.tsx +23 -20
- package/src/report/components/entity-lists/compute.ts +196 -0
- package/src/report/components/entity-lists/faces.ts +207 -0
- package/src/report/components/entity-lists/index.tsx +241 -0
- package/src/report/components/entity-lists/validate.test.ts +114 -0
- package/src/report/{react → components}/fixtures.ts +2 -2
- package/src/report/{react → components/metric-views}/DeltaTable.tsx +5 -5
- package/src/report/{react → components/metric-views}/MetricBars.tsx +5 -5
- package/src/report/{react → components/metric-views}/MetricLine.tsx +9 -6
- package/src/report/{react → components/metric-views}/MetricMatrix.tsx +6 -6
- package/src/report/{react → components/metric-views}/MetricScatter.tsx +41 -33
- package/src/report/{react → components/metric-views}/MetricTable.tsx +6 -6
- package/src/report/{react → components/metric-views}/Scoreboard.tsx +4 -4
- package/src/report/{compute.ts → components/metric-views/compute.ts} +51 -477
- package/src/report/components/metric-views/faces.ts +423 -0
- package/src/report/components/metric-views/index.tsx +352 -0
- package/src/report/{text → components/metric-views}/plot.ts +1 -1
- package/src/report/components/metric-views/validate.test.ts +211 -0
- package/src/report/{react → components}/render.test.tsx +47 -17
- package/src/report/components/shared-compute.ts +59 -0
- package/src/report/components/shared-faces.ts +30 -0
- package/src/report/components/shared.ts +192 -0
- package/src/report/{react → components/site-components}/CopyFixPrompt.tsx +3 -3
- package/src/report/{react → components/site-components}/HeroCard.tsx +3 -3
- package/src/report/{react → components/site-components}/ScopeWarnings.tsx +4 -4
- package/src/report/{react → components/site-components}/TraceWaterfall.tsx +13 -10
- package/src/report/components/site-components/compute.ts +144 -0
- package/src/report/components/site-components/faces.ts +80 -0
- package/src/report/components/site-components/index.tsx +265 -0
- package/src/report/{scope-warnings.ts → components/site-components/scope-warnings.ts} +3 -3
- package/src/report/{site-components.test.tsx → components/site-components/site-components.test.tsx} +23 -21
- package/src/report/components/site-components/validate.test.ts +89 -0
- package/src/report/{react → components/summaries}/ScopeSummary.tsx +26 -11
- package/src/report/components/summaries/compute.ts +56 -0
- package/src/report/components/summaries/faces.ts +48 -0
- package/src/report/components/summaries/index.tsx +127 -0
- package/src/report/components/summaries/validate.test.ts +49 -0
- package/src/report/definition/grid-layout.test.ts +124 -0
- package/src/report/definition/grid-layout.ts +146 -0
- package/src/report/{primitives.tsx → definition/primitives.tsx} +168 -18
- package/src/report/{report.ts → definition/report.ts} +98 -165
- package/src/report/{shell-head.test.ts → definition/shell-head.test.ts} +2 -2
- package/src/report/{text/table.ts → definition/table-text.ts} +4 -4
- package/src/report/{tree.ts → definition/tree.ts} +56 -20
- package/src/report/index.ts +126 -66
- package/src/report/{aggregate.ts → model/aggregate.ts} +31 -9
- package/src/report/{flag.ts → model/flag.ts} +39 -1
- package/src/report/{format.ts → model/format.ts} +59 -5
- package/src/report/{locale.ts → model/locale.ts} +34 -36
- package/src/report/{metrics.ts → model/metrics.ts} +3 -3
- package/src/report/{types.ts → model/types.ts} +143 -22
- package/src/report/react/index.tsx +52 -26
- package/src/report/{dual-render.test.tsx → runtime/dual-render.test.tsx} +564 -49
- package/src/report/runtime/host.test.ts +44 -0
- package/src/report/runtime/host.ts +138 -0
- package/src/report/{load.ts → runtime/load.ts} +1 -1
- package/src/report/runtime/text.ts +192 -0
- package/src/report/runtime/web.ts +106 -0
- package/src/results/attempt-evidence.ts +5 -1
- package/src/results/host-equivalence.test.ts +53 -2
- package/src/results/select.ts +29 -5
- package/src/runner/attempt.test.ts +48 -1
- package/src/runner/attempt.ts +62 -42
- package/src/runner/cleanup-timeout.test.ts +16 -0
- package/src/runner/cleanup-timeout.ts +23 -0
- package/src/runner/discover.ts +1 -2
- package/src/runner/eval-selection.test.ts +187 -0
- package/src/runner/eval-selection.ts +109 -0
- package/src/runner/experiment-cleanup-registry.test.ts +89 -0
- package/src/runner/experiment-cleanup-registry.ts +39 -0
- package/src/runner/experiment-labels.test.ts +71 -0
- package/src/runner/feedback/agent.test.ts +33 -1
- package/src/runner/feedback/agent.ts +12 -16
- package/src/runner/feedback/ci.test.ts +35 -1
- package/src/runner/feedback/ci.ts +16 -18
- package/src/runner/feedback/coordinator.ts +28 -0
- package/src/runner/feedback/human.test.ts +108 -1
- package/src/runner/feedback/human.ts +71 -21
- package/src/runner/feedback/reducer.test.ts +64 -0
- package/src/runner/feedback/reducer.ts +26 -0
- package/src/runner/feedback/sink.ts +40 -1
- package/src/runner/fingerprint.ts +2 -1
- package/src/runner/report.test.ts +14 -0
- package/src/runner/report.ts +3 -1
- package/src/runner/run.test.ts +390 -12
- package/src/runner/run.ts +259 -26
- package/src/runner/sandbox-selection.test.ts +13 -3
- package/src/runner/sandbox-selection.ts +4 -2
- package/src/runner/types.ts +158 -23
- package/src/sandbox/docker.ts +7 -0
- package/src/sandbox/e2b.ts +12 -13
- package/src/sandbox/types.ts +23 -21
- package/src/scoring/display.test.ts +28 -2
- package/src/scoring/display.ts +38 -5
- package/src/scoring/types.ts +3 -3
- package/src/shared/aggregate.test.ts +52 -0
- package/src/shared/aggregate.ts +29 -0
- package/src/shared/types.ts +6 -1
- package/src/show/command.test.ts +34 -0
- package/src/show/command.ts +16 -0
- package/src/show/compose.ts +1 -1
- package/src/show/index.ts +56 -20
- package/src/show/render.ts +15 -239
- package/src/show/show.test.ts +127 -34
- package/src/view/app/App.test.tsx +1 -1
- package/src/view/app/App.tsx +119 -47
- package/src/view/app/i18n.ts +7 -147
- package/src/view/app/lib/attempt-dialog.test.ts +65 -0
- package/src/view/app/lib/attempt-dialog.ts +69 -0
- package/src/view/app/main.tsx +0 -1
- package/src/view/app/types.ts +3 -86
- package/src/view/artifact-serving.test.ts +22 -38
- package/src/view/client-dist/app.css +1 -1
- package/src/view/client-dist/app.js +15 -22
- package/src/view/data.test.ts +48 -36
- package/src/view/data.ts +105 -83
- package/src/view/index.ts +1 -1
- package/src/view/server.ts +32 -2
- package/src/view/shared/types.ts +6 -31
- package/src/view/site-parity.test.ts +24 -1
- package/src/view/site.ts +144 -17
- package/src/view/styles.css +0 -805
- package/src/view/view-report.test.ts +141 -22
- package/dist/report/components.d.ts +0 -179
- package/dist/report/components.js +0 -544
- package/dist/report/compute.d.ts +0 -139
- package/dist/report/react/ExperimentComparison.d.ts +0 -10
- package/dist/report/react/ExperimentComparison.js +0 -12
- package/dist/report/react/MetricScatter.d.ts +0 -9
- package/dist/report/react/format.d.ts +0 -3
- package/dist/report/react/format.js +0 -7
- package/dist/report/text/faces.d.ts +0 -45
- package/dist/report/text/faces.js +0 -671
- package/dist/report/web.d.ts +0 -32
- package/dist/report/web.js +0 -48
- package/docs-site/zh/how-to/authoring.mdx +0 -162
- package/docs-site/zh/how-to/custom-reports.mdx +0 -414
- package/docs-site/zh/how-to/experiments.mdx +0 -86
- package/docs-site/zh/how-to/write-experiment.mdx +0 -164
- package/src/report/components.tsx +0 -925
- package/src/report/react/ExperimentComparison.tsx +0 -73
- package/src/report/react/format.ts +0 -9
- package/src/report/text/faces.ts +0 -767
- package/src/report/web.ts +0 -77
- package/src/show/report-host.test.ts +0 -205
- package/src/show/report-host.ts +0 -389
- package/src/view/app/components/AttemptModal.tsx +0 -496
- package/src/view/app/components/CodeView.test.tsx +0 -142
- package/src/view/app/components/CodeView.tsx +0 -310
- package/src/view/app/components/CopyControls.tsx +0 -106
- package/src/view/app/components/Trace.tsx +0 -100
- package/src/view/app/components/Transcript.tsx +0 -157
- package/src/view/app/components/ui/badge.tsx +0 -21
- package/src/view/app/lib/artifact-url.ts +0 -17
- package/src/view/app/lib/attempt-route.test.ts +0 -80
- package/src/view/app/lib/attempt-route.ts +0 -52
- package/src/view/app/lib/format.ts +0 -70
- package/src/view/app/lib/guards.test.ts +0 -108
- package/src/view/app/lib/guards.ts +0 -71
- package/src/view/app/lib/rows.ts +0 -22
- package/src/view/app/lib/transcript-data.tsx +0 -151
- package/src/view/app/lib/verdict.ts +0 -23
- package/src/view/app/shared.ts +0 -8
- /package/dist/report/{react → components/metric-views}/chart-math.d.ts +0 -0
- /package/dist/report/{react → components/metric-views}/chart-math.js +0 -0
- /package/dist/report/{text → components/metric-views}/plot.d.ts +0 -0
- /package/dist/report/{react → components/site-components}/PoweredBy.d.ts +0 -0
- /package/dist/report/{react → components/site-components}/PoweredBy.js +0 -0
- /package/dist/report/{text/layout.d.ts → model/text-layout.d.ts} +0 -0
- /package/dist/report/{text/layout.js → model/text-layout.js} +0 -0
- /package/dist/report/{types.js → model/types.js} +0 -0
- /package/src/report/{react → components/metric-views}/chart-math.test.ts +0 -0
- /package/src/report/{react → components/metric-views}/chart-math.ts +0 -0
- /package/src/report/{react → components/site-components}/PoweredBy.tsx +0 -0
- /package/src/report/{text/layout.ts → model/text-layout.ts} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// 计算函数(*Data):ReportInput → 一份组件数据。跑在 Node 侧,产物是算好的、可序列化的
|
|
2
|
-
// 普通 JSON(终值 + 渲染提示,不含公式);渲染面(web/text)
|
|
3
|
-
//
|
|
4
|
-
//
|
|
2
|
+
// 普通 JSON(终值 + 渲染提示,不含公式);渲染面(web/text)只做展示。指标图形族
|
|
3
|
+
// (MetricTable / MetricMatrix / MetricBars / Scoreboard / MetricScatter / MetricLine /
|
|
4
|
+
// DeltaTable)的 *Data 与配套 Options 都住在这里(docs/feature/reports/library/metric-views.md)。
|
|
5
5
|
//
|
|
6
6
|
// 共同约定(docs/feature/reports/architecture.md「指标聚合不变量」):
|
|
7
7
|
// - 第一参收 ReportInput = Scope | readonly Snapshot[];warnings 不进组件数据(宿主统一显示);
|
|
@@ -10,14 +10,11 @@
|
|
|
10
10
|
// - 显式传入的列表(questions / pairs / metrics)保留声明顺序,从数据发现的维度 domain
|
|
11
11
|
// 按稳定 key 字典序;
|
|
12
12
|
// - core 中立:只认 Metric / Dimension 接口,不出现具体 agent 名的分支。
|
|
13
|
-
import { comparabilityConfigOf, deepEqualJson } from "
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import { formatMetricValue, formatPlainNumber, localizedDisplay } from "./format.js";
|
|
19
|
-
import { compactAssertionSummary, primaryAssertionSummary, summaryText } from "../scoring/display.js";
|
|
20
|
-
import { defineMetric } from "./metrics.js";
|
|
13
|
+
import { comparabilityConfigOf, deepEqualJson } from "../../../results/select.js";
|
|
14
|
+
import { assertUniqueMetricNames, axisValueOf, collectItems, computeCell, dimensionKey, dimensionName, evalGroupOf, evalIdOf, experimentIdOf, filterItems, fullEvalKey, groupItems, locatorOf, refDisplayKey, resolveInput, seriesKey, seriesName, toColumn, } from "../../model/aggregate.js";
|
|
15
|
+
import { examScore } from "../../model/metrics.js";
|
|
16
|
+
import { formatMetricValue, formatPlainNumber, localizedDisplay } from "../../model/format.js";
|
|
17
|
+
import { selectedEvalsOnly } from "../shared-compute.js";
|
|
21
18
|
export async function metricTableData(input, options) {
|
|
22
19
|
assertUniqueMetricNames(options.columns, "metricTableData columns");
|
|
23
20
|
if (options.sort !== undefined) {
|
|
@@ -91,266 +88,6 @@ export async function metricMatrixData(input, options) {
|
|
|
91
88
|
cells,
|
|
92
89
|
};
|
|
93
90
|
}
|
|
94
|
-
// ───────────────────────── 实体列表(experimentListData / evalListData / attemptListData)─────────────────────────
|
|
95
|
-
/**
|
|
96
|
-
* 一次 attempt 的单行结果摘要(Scoring display 契约):failed 取主失败断言摘要(不含
|
|
97
|
-
* "+N more",N 单独进 moreFailures),errored 取结构化 error 的一层摘要
|
|
98
|
-
* (phase · code · message),passed / skipped 为 null。
|
|
99
|
-
*/
|
|
100
|
-
function failureSummaryOf(result) {
|
|
101
|
-
if (result.verdict === "errored" && result.error !== undefined) {
|
|
102
|
-
const parts = [result.error.phase, result.error.code, result.error.message].filter((part) => typeof part === "string" && part.length > 0);
|
|
103
|
-
return { summary: summaryText(parts.join(" · ")), more: 0 };
|
|
104
|
-
}
|
|
105
|
-
if (result.verdict === "failed" || result.verdict === "errored") {
|
|
106
|
-
const primary = primaryAssertionSummary(result.assertions, result.verdict);
|
|
107
|
-
if (primary !== undefined) {
|
|
108
|
-
return {
|
|
109
|
-
summary: compactAssertionSummary({ ...primary, additionalFailures: 0 }),
|
|
110
|
-
more: primary.additionalFailures,
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
if (result.verdict === "errored" && result.skipReason !== undefined) {
|
|
114
|
-
return { summary: summaryText(result.skipReason), more: 0 };
|
|
115
|
-
}
|
|
116
|
-
return { summary: null, more: 0 };
|
|
117
|
-
}
|
|
118
|
-
return { summary: null, more: 0 };
|
|
119
|
-
}
|
|
120
|
-
/** AttemptList / ExperimentList / EvalList 共用的叶子构造:一个 Item → 一个 AttemptListItem。 */
|
|
121
|
-
async function attemptListItemOf(item) {
|
|
122
|
-
const result = item.attempt.result;
|
|
123
|
-
const { summary, more } = failureSummaryOf(result);
|
|
124
|
-
return {
|
|
125
|
-
experimentId: experimentIdOf(item),
|
|
126
|
-
evalId: evalIdOf(item),
|
|
127
|
-
attempt: result.attempt,
|
|
128
|
-
agent: result.agent,
|
|
129
|
-
verdict: result.verdict,
|
|
130
|
-
failureSummary: summary,
|
|
131
|
-
moreFailures: more,
|
|
132
|
-
examScore: await computeCell(examScore, [item]),
|
|
133
|
-
durationMs: result.durationMs,
|
|
134
|
-
costUSD: attemptCostUSD(result),
|
|
135
|
-
locator: locatorOf(item),
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
/** `attemptListData(input)`:每个 Attempt 一项,顺序取自 Scope 展平顺序(不重排)。 */
|
|
139
|
-
export async function attemptListData(input) {
|
|
140
|
-
const { snapshots } = resolveInput(input);
|
|
141
|
-
const items = collectItems(snapshots);
|
|
142
|
-
return Promise.all(items.map((item) => attemptListItemOf(item)));
|
|
143
|
-
}
|
|
144
|
-
/** `evalListData(input)`:每个 `experimentId + evalId` 一项,按 evalId 再按 experimentId 升序。 */
|
|
145
|
-
export async function evalListData(input) {
|
|
146
|
-
const { snapshots } = resolveInput(input);
|
|
147
|
-
const items = collectItems(snapshots);
|
|
148
|
-
const groups = new Map();
|
|
149
|
-
for (const item of items) {
|
|
150
|
-
const key = fullEvalKey(item);
|
|
151
|
-
const list = groups.get(key);
|
|
152
|
-
if (list)
|
|
153
|
-
list.push(item);
|
|
154
|
-
else
|
|
155
|
-
groups.set(key, [item]);
|
|
156
|
-
}
|
|
157
|
-
const out = [];
|
|
158
|
-
for (const group of groups.values()) {
|
|
159
|
-
const sorted = [...group].sort((a, b) => a.attempt.result.attempt - b.attempt.result.attempt);
|
|
160
|
-
const verdict = foldEvalVerdict(sorted.map((item) => item.attempt.result));
|
|
161
|
-
const attempts = await Promise.all(sorted.map((item) => attemptListItemOf(item)));
|
|
162
|
-
out.push({
|
|
163
|
-
experimentId: experimentIdOf(sorted[0]),
|
|
164
|
-
evalId: evalIdOf(sorted[0]),
|
|
165
|
-
verdict,
|
|
166
|
-
examScore: await computeCell(examScore, sorted),
|
|
167
|
-
durationMs: await computeCell(durationMs, sorted),
|
|
168
|
-
costUSD: await computeCell(costUSD, sorted),
|
|
169
|
-
attempts,
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
out.sort((a, b) => a.evalId.localeCompare(b.evalId) || a.experimentId.localeCompare(b.experimentId));
|
|
173
|
-
return out;
|
|
174
|
-
}
|
|
175
|
-
/**
|
|
176
|
-
* `experimentListData(input)`:每个 experiment 一项,展开到每道 Eval;初始按端到端成功率
|
|
177
|
-
* 从高到低(缺数据沉底,同分按 id)。一行只有一套 agent / model / flags 是输入约束:
|
|
178
|
-
* 宿主注入的 current() Scope 保证每个 experiment 只由可比性配置一致的快照拼成;作者自选
|
|
179
|
-
* Snapshot[] 时若同一 experiment 混入不一致的可比性配置,按完整用户反馈失败并指引——
|
|
180
|
-
* 看跨配置演化用 snapshot 维度或 MetricLine,不把两套配置拼成一行冒充单一配置。
|
|
181
|
-
*/
|
|
182
|
-
export async function experimentListData(input) {
|
|
183
|
-
const { snapshots } = resolveInput(input);
|
|
184
|
-
// 可比性配置单义检查:同一 experiment 的输入快照必须共享一套可比性配置。
|
|
185
|
-
const configByExperiment = new Map();
|
|
186
|
-
for (const snapshot of snapshots) {
|
|
187
|
-
const config = comparabilityConfigOf(snapshot);
|
|
188
|
-
const existing = configByExperiment.get(snapshot.experimentId);
|
|
189
|
-
if (existing === undefined) {
|
|
190
|
-
configByExperiment.set(snapshot.experimentId, { snapshot, config });
|
|
191
|
-
}
|
|
192
|
-
else if (!deepEqualJson(existing.config, config)) {
|
|
193
|
-
throw new Error(`experimentListData got inconsistent comparability configs for experiment "${snapshot.experimentId}" ` +
|
|
194
|
-
`(snapshots ${existing.snapshot.startedAt} and ${snapshot.startedAt} differ in agent/model/reasoningEffort/flags/budget/timeoutMs/sandbox). ` +
|
|
195
|
-
"One row shows one configuration — it cannot honestly merge two. To chart evolution across configs, " +
|
|
196
|
-
'use the "snapshot" dimension or MetricLine; to show the current level, pass results.current() which selects a single config per experiment.');
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
const items = collectItems(snapshots);
|
|
200
|
-
const groups = groupItems(items, "experiment");
|
|
201
|
-
const out = [];
|
|
202
|
-
for (const [experimentId, group] of groups) {
|
|
203
|
-
const stats = summarizeItems(group);
|
|
204
|
-
const newest = [...group].sort((a, b) => b.snapshot.startedAt.localeCompare(a.snapshot.startedAt))[0];
|
|
205
|
-
const evalGroups = groupItems(group, "eval");
|
|
206
|
-
const evalRows = [];
|
|
207
|
-
for (const [evalId, evalItems] of evalGroups) {
|
|
208
|
-
const sorted = [...evalItems].sort((a, b) => a.attempt.result.attempt - b.attempt.result.attempt);
|
|
209
|
-
const verdict = foldEvalVerdict(sorted.map((item) => item.attempt.result));
|
|
210
|
-
const attempts = await Promise.all(sorted.map((item) => attemptListItemOf(item)));
|
|
211
|
-
evalRows.push({
|
|
212
|
-
evalId,
|
|
213
|
-
verdict,
|
|
214
|
-
durationMs: await computeCell(durationMs, sorted),
|
|
215
|
-
costUSD: await computeCell(costUSD, sorted),
|
|
216
|
-
attempts,
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
const experiment = newest.snapshot.experiment ?? newest.attempt.result.experiment;
|
|
220
|
-
const model = newest.attempt.result.model ?? newest.snapshot.model;
|
|
221
|
-
out.push({
|
|
222
|
-
experimentId,
|
|
223
|
-
agent: newest.snapshot.agent || newest.attempt.result.agent,
|
|
224
|
-
...(model !== undefined ? { model } : {}),
|
|
225
|
-
...(experiment?.flags ? { flags: experiment.flags } : {}),
|
|
226
|
-
evalVerdicts: stats.verdicts,
|
|
227
|
-
endToEndPassRate: await computeCell(endToEndPassRate, group),
|
|
228
|
-
costUSD: await computeCell(costUSD, group),
|
|
229
|
-
durationMs: await computeCell(durationMs, group),
|
|
230
|
-
tokens: await computeCell(tokens, group),
|
|
231
|
-
evals: stats.evals,
|
|
232
|
-
attempts: stats.attempts,
|
|
233
|
-
lastRunAt: stats.lastRunAt,
|
|
234
|
-
evalRows,
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
// 初始态按端到端成功率(endToEndPassRate)从高到低,缺数据沉底;同分按 experiment id 稳定排序。
|
|
238
|
-
out.sort((a, b) => {
|
|
239
|
-
const va = a.endToEndPassRate.value;
|
|
240
|
-
const vb = b.endToEndPassRate.value;
|
|
241
|
-
if (va === null && vb === null)
|
|
242
|
-
return a.experimentId.localeCompare(b.experimentId);
|
|
243
|
-
if (va === null)
|
|
244
|
-
return 1;
|
|
245
|
-
if (vb === null)
|
|
246
|
-
return -1;
|
|
247
|
-
return vb - va || a.experimentId.localeCompare(b.experimentId);
|
|
248
|
-
});
|
|
249
|
-
return out;
|
|
250
|
-
}
|
|
251
|
-
// ───────────────────────── scopeSummaryData ─────────────────────────
|
|
252
|
-
/** costUSD 的求和投影:两级都 sum(题内多轮求和 + 跨题求和 = 全量求和),display 走 $。 */
|
|
253
|
-
const totalCostMetric = defineMetric({
|
|
254
|
-
name: "total-cost",
|
|
255
|
-
label: costUSD.label,
|
|
256
|
-
unit: "$",
|
|
257
|
-
value: costUSD.value,
|
|
258
|
-
aggregate: { perEval: "sum", acrossEvals: "sum" },
|
|
259
|
-
});
|
|
260
|
-
function tallyOf() {
|
|
261
|
-
return { passed: 0, failed: 0, errored: 0, skipped: 0 };
|
|
262
|
-
}
|
|
263
|
-
/** 一批 Item 的组级统计(experimentListData / scopeSummaryData 共用)。 */
|
|
264
|
-
function summarizeItems(items) {
|
|
265
|
-
const experimentIds = new Set();
|
|
266
|
-
for (const item of items)
|
|
267
|
-
experimentIds.add(experimentIdOf(item));
|
|
268
|
-
const stats = evalLevelStats(items.map((item) => ({ verdict: item.attempt.result.verdict, key: fullEvalKey(item) })), (r) => r.key);
|
|
269
|
-
let lastRunAt;
|
|
270
|
-
for (const item of items) {
|
|
271
|
-
const startedAt = item.snapshot.startedAt;
|
|
272
|
-
if (lastRunAt === undefined || startedAt > lastRunAt)
|
|
273
|
-
lastRunAt = startedAt;
|
|
274
|
-
}
|
|
275
|
-
return {
|
|
276
|
-
experiments: experimentIds.size,
|
|
277
|
-
evals: stats.evals,
|
|
278
|
-
attempts: items.length,
|
|
279
|
-
verdicts: { passed: stats.passed, failed: stats.failed, errored: stats.errored, skipped: stats.skipped },
|
|
280
|
-
lastRunAt,
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
/**
|
|
284
|
-
* `scopeSummaryData(input)`:范围摘要——快照时间窗、experiment / eval / attempt 数、
|
|
285
|
-
* 两级判定计票、端到端成功率与总成本(docs/feature/reports/library/summaries.md)。
|
|
286
|
-
* data 恒携带两级计票;成功率来自官方两级指标引擎,不从任一计票重算。
|
|
287
|
-
*/
|
|
288
|
-
export async function scopeSummaryData(input) {
|
|
289
|
-
const { snapshots } = resolveInput(input);
|
|
290
|
-
const items = collectItems(snapshots);
|
|
291
|
-
let earliest = null;
|
|
292
|
-
let latest = null;
|
|
293
|
-
for (const snapshot of snapshots) {
|
|
294
|
-
if (earliest === null || snapshot.startedAt < earliest)
|
|
295
|
-
earliest = snapshot.startedAt;
|
|
296
|
-
if (latest === null || snapshot.startedAt > latest)
|
|
297
|
-
latest = snapshot.startedAt;
|
|
298
|
-
}
|
|
299
|
-
const stats = summarizeItems(items);
|
|
300
|
-
const attemptVerdicts = tallyOf();
|
|
301
|
-
for (const item of items)
|
|
302
|
-
attemptVerdicts[item.attempt.result.verdict] += 1;
|
|
303
|
-
return {
|
|
304
|
-
range: { earliestStartedAt: earliest, latestStartedAt: latest },
|
|
305
|
-
experiments: stats.experiments,
|
|
306
|
-
evals: stats.evals,
|
|
307
|
-
attempts: stats.attempts,
|
|
308
|
-
evalVerdicts: stats.verdicts,
|
|
309
|
-
attemptVerdicts,
|
|
310
|
-
endToEndPassRate: await computeCell(endToEndPassRate, items),
|
|
311
|
-
totalCostUSD: await computeCell(totalCostMetric, items),
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
// ───────────────────────── experimentComparisonData ─────────────────────────
|
|
315
|
-
/** 完整父路径是组键;没有父路径的 experiment 不能互相比,自己形成单例组。 */
|
|
316
|
-
export function experimentComparisonGroupKey(experimentId) {
|
|
317
|
-
return experimentGroupOf(experimentId) ?? experimentId;
|
|
318
|
-
}
|
|
319
|
-
/** 每组散点的唯一口径:默认 definition 与公开计算共用,不各写一份。 */
|
|
320
|
-
const COMPARISON_SCATTER_OPTIONS = {
|
|
321
|
-
points: "experiment",
|
|
322
|
-
series: "agent",
|
|
323
|
-
x: costUSD,
|
|
324
|
-
y: endToEndPassRate,
|
|
325
|
-
};
|
|
326
|
-
/**
|
|
327
|
-
* `experimentComparisonData(input)`:先把 input 按可比组分区(experiment id 的完整父路径),
|
|
328
|
-
* 再为每组分别计算 ScopeSummary、成本 × 端到端成功率散点和 ExperimentList——分区发生在任何
|
|
329
|
-
* 指标计算之前,组外 attempt 不可能污染该组的坐标尺度、series、成功率、成本、排序或缺数据计数。
|
|
330
|
-
*/
|
|
331
|
-
export async function experimentComparisonData(input) {
|
|
332
|
-
const { snapshots } = resolveInput(input);
|
|
333
|
-
const snapshotsByGroup = new Map();
|
|
334
|
-
for (const snapshot of snapshots) {
|
|
335
|
-
const key = experimentComparisonGroupKey(snapshot.experimentId);
|
|
336
|
-
const group = snapshotsByGroup.get(key);
|
|
337
|
-
if (group)
|
|
338
|
-
group.push(snapshot);
|
|
339
|
-
else
|
|
340
|
-
snapshotsByGroup.set(key, [snapshot]);
|
|
341
|
-
}
|
|
342
|
-
const groups = await Promise.all([...snapshotsByGroup.entries()]
|
|
343
|
-
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
344
|
-
.map(async ([key, groupSnapshots]) => {
|
|
345
|
-
const [summary, scatter, experiments] = await Promise.all([
|
|
346
|
-
scopeSummaryData(groupSnapshots),
|
|
347
|
-
metricScatterData(groupSnapshots, COMPARISON_SCATTER_OPTIONS),
|
|
348
|
-
experimentListData(groupSnapshots),
|
|
349
|
-
]);
|
|
350
|
-
return { key, summary, scatter, experiments };
|
|
351
|
-
}));
|
|
352
|
-
return { groups };
|
|
353
|
-
}
|
|
354
91
|
/**
|
|
355
92
|
* 固定题集分母:未跑题按 0 分计入 `notRun`,跑了但指标为 null 的题按 0 分计入 `unscorable`,
|
|
356
93
|
* 两个计数不合并——成绩单能回答「这 0 分是没去考还是考了判不了」。组件不从已观测 attempt
|
|
@@ -497,7 +234,7 @@ function subjectDisplay(earned, possible) {
|
|
|
497
234
|
return `${formatPlainNumber(earned)}/${formatPlainNumber(possible)} (${formatMetricValue(ratio, "%")})`;
|
|
498
235
|
}
|
|
499
236
|
export async function metricScatterData(input, options) {
|
|
500
|
-
const
|
|
237
|
+
const snapshots = selectedEvalsOnly(resolveInput(input).snapshots);
|
|
501
238
|
const items = filterItems(collectItems(snapshots), options.evals);
|
|
502
239
|
const groups = groupItems(items, options.points);
|
|
503
240
|
const rows = [];
|
|
@@ -505,14 +242,14 @@ export async function metricScatterData(input, options) {
|
|
|
505
242
|
rows.push({
|
|
506
243
|
key,
|
|
507
244
|
// 组内取第一条解析系列:点维度细于系列维度时(experiment ⊂ agent)天然一致
|
|
508
|
-
...(options.series ? { series:
|
|
245
|
+
...(options.series ? { series: seriesKey(options.series, group[0]) } : {}),
|
|
509
246
|
x: await computeCell(options.x, group),
|
|
510
247
|
y: await computeCell(options.y, group), // 任一轴 null 的点留在 rows 里:组件不画,但注脚要报的数就从这里数
|
|
511
248
|
});
|
|
512
249
|
}
|
|
513
250
|
return {
|
|
514
251
|
pointDimension: dimensionName(options.points),
|
|
515
|
-
...(options.series ? { seriesDimension:
|
|
252
|
+
...(options.series ? { seriesDimension: seriesName(options.series) } : {}),
|
|
516
253
|
x: toColumn(options.x),
|
|
517
254
|
y: toColumn(options.y),
|
|
518
255
|
rows,
|
|
@@ -544,7 +281,7 @@ export async function metricLineData(input, options) {
|
|
|
544
281
|
"not vary per attempt — a per-attempt quantity is material for the y metric, not an x axis. " +
|
|
545
282
|
"Fix of() to read experiment-level configuration (numericFlag()/numericRunConfig() do this by construction).");
|
|
546
283
|
}
|
|
547
|
-
const series = options.series ?
|
|
284
|
+
const series = options.series ? seriesKey(options.series, item) : undefined;
|
|
548
285
|
const bucketKey = `${series ?? ""}${x === null ? "null" : String(x)}`;
|
|
549
286
|
const bucket = buckets.get(bucketKey);
|
|
550
287
|
if (bucket)
|
|
@@ -579,7 +316,7 @@ export async function metricLineData(input, options) {
|
|
|
579
316
|
label: options.x.label ?? options.x.name,
|
|
580
317
|
...(options.x.unit !== undefined ? { unit: options.x.unit } : {}),
|
|
581
318
|
},
|
|
582
|
-
...(options.series ? { seriesDimension:
|
|
319
|
+
...(options.series ? { seriesDimension: seriesName(options.series) } : {}),
|
|
583
320
|
y: toColumn(options.y),
|
|
584
321
|
rows,
|
|
585
322
|
};
|
|
@@ -587,8 +324,10 @@ export async function metricLineData(input, options) {
|
|
|
587
324
|
// ───────────────────────── deltaTableData 与 pairsByFlag ─────────────────────────
|
|
588
325
|
/**
|
|
589
326
|
* 按 flag 派生 A/B 对(docs/feature/reports/library/metric-views.md「DeltaTable」):
|
|
590
|
-
* 配对域 =
|
|
591
|
-
*
|
|
327
|
+
* 配对域 = input Scope 内删除该 flag 后可比性配置深相等(不额外按 experiment id 的目录前缀分组
|
|
328
|
+
* ——architecture.md「Scope 是默认报告的比较边界」同一条契约);a 取 baseline(缺省 = 未声明该
|
|
329
|
+
* flag),b 侧该 flag 的每个其它取值各成一对;label 自动 `<完整 a experiment id> · <flag>=<显示键>`,
|
|
330
|
+
* 排序仍按 a 的末段、再按 flag 显示键(不受完整 id 的字符串差异影响)。
|
|
592
331
|
*/
|
|
593
332
|
export function pairsByFlag(name, options) {
|
|
594
333
|
if (typeof name !== "string" || name.length === 0) {
|
|
@@ -603,12 +342,12 @@ export function pairsByFlag(name, options) {
|
|
|
603
342
|
function isFlagPairs(pairs) {
|
|
604
343
|
return typeof pairs === "object" && pairs !== null && !Array.isArray(pairs) && pairs.kind === "flagPairs";
|
|
605
344
|
}
|
|
606
|
-
/** experiment id
|
|
345
|
+
/** experiment id 的末段(最后一个 `/` 之后;无 `/` 时是完整 id)。 */
|
|
607
346
|
function experimentTail(experimentId) {
|
|
608
347
|
const slash = experimentId.lastIndexOf("/");
|
|
609
348
|
return slash === -1 ? experimentId : experimentId.slice(slash + 1);
|
|
610
349
|
}
|
|
611
|
-
/**
|
|
350
|
+
/** 派生配对:input Scope 内删除该 flag 后可比性配置深相等。返回 pair 列表与配对域实验数。 */
|
|
612
351
|
function derivePairsByFlag(snapshots, spec) {
|
|
613
352
|
// 每个 experiment 取最新快照的配置(current() Scope 天然一实验一快照)。
|
|
614
353
|
const byExperiment = new Map();
|
|
@@ -624,8 +363,9 @@ function derivePairsByFlag(snapshots, spec) {
|
|
|
624
363
|
const flagValue = config.flags?.[spec.flag];
|
|
625
364
|
const reduced = { ...config, flags: { ...config.flags } };
|
|
626
365
|
delete reduced.flags[spec.flag];
|
|
627
|
-
|
|
628
|
-
|
|
366
|
+
// 配对域只是 input Scope + 删除该 flag 后的可比性配置深相等;不额外按 experiment id 的
|
|
367
|
+
// 目录前缀分组——组件不从路径猜比较边界(architecture.md「Scope 是默认报告的比较边界」)。
|
|
368
|
+
entries.push({ id, flagValue, bucket: JSON.stringify(sortedJson(reduced)) });
|
|
629
369
|
}
|
|
630
370
|
const baseline = spec.baseline; // undefined = 未声明该 flag 的实验作 a
|
|
631
371
|
const buckets = new Map();
|
|
@@ -636,29 +376,29 @@ function derivePairsByFlag(snapshots, spec) {
|
|
|
636
376
|
else
|
|
637
377
|
buckets.set(entry.bucket, [entry]);
|
|
638
378
|
}
|
|
639
|
-
const
|
|
379
|
+
const derived = [];
|
|
640
380
|
for (const bucket of buckets.values()) {
|
|
641
381
|
const aSide = bucket.filter((e) => deepEqualJson(e.flagValue, baseline));
|
|
642
382
|
const bSide = bucket.filter((e) => !deepEqualJson(e.flagValue, baseline));
|
|
643
383
|
for (const a of aSide) {
|
|
644
384
|
for (const b of bSide) {
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
});
|
|
385
|
+
const flagKey = refDisplayKey(b.flagValue)[0];
|
|
386
|
+
// label 用完整 a experiment id 自动命名,不截断成末段——目录前缀不同的两个实验
|
|
387
|
+
// 配成一对时,末段可能撞名,完整 id 才能唯一标识这一对来自哪个实验。
|
|
388
|
+
derived.push({ a: a.id, b: b.id, label: `${a.id} · ${spec.flag}=${flagKey}`, flagKey });
|
|
650
389
|
}
|
|
651
390
|
}
|
|
652
391
|
}
|
|
653
|
-
|
|
392
|
+
// 排序只看 a 的末段与 flag 显示键,不看完整 label 字符串——完整 a id 只服务显示,
|
|
393
|
+
// 不该让目录前缀的字符串差异打乱本该相邻的 a 末段分组。
|
|
394
|
+
derived.sort((p, q) => {
|
|
654
395
|
const ta = experimentTail(p.a);
|
|
655
396
|
const tb = experimentTail(q.a);
|
|
656
397
|
if (ta !== tb)
|
|
657
398
|
return ta < tb ? -1 : 1;
|
|
658
|
-
|
|
659
|
-
const lb = q.label;
|
|
660
|
-
return la < lb ? -1 : la > lb ? 1 : 0;
|
|
399
|
+
return p.flagKey < q.flagKey ? -1 : p.flagKey > q.flagKey ? 1 : 0;
|
|
661
400
|
});
|
|
401
|
+
const pairs = derived.map(({ a, b, label }) => ({ a, b, label }));
|
|
662
402
|
return { pairs, experiments: byExperiment.size };
|
|
663
403
|
}
|
|
664
404
|
/** 对象键递归排序(派生配对的 bucket 键用;undefined 字段剔除)。 */
|
|
@@ -774,126 +514,3 @@ function deltaOutcome(metric, delta) {
|
|
|
774
514
|
const better = metric.better ?? "higher";
|
|
775
515
|
return (delta > 0) === (better === "higher") ? "improved" : "regressed";
|
|
776
516
|
}
|
|
777
|
-
// ───────────────────────── 站点组件的计算函数(hero / warnings / fix prompt / trace)─────────────────────────
|
|
778
|
-
/**
|
|
779
|
-
* `heroData(input)`:站点标题区的运行 meta——`latestStartedAt` 取范围内最新快照的开始时间
|
|
780
|
-
* (空范围为 null,不编造当前时间),`snapshots` 计贡献当前水位的快照数
|
|
781
|
-
* (docs/feature/reports/library/site-components.md「HeroCard」)。
|
|
782
|
-
*/
|
|
783
|
-
export async function heroData(input) {
|
|
784
|
-
const { snapshots } = resolveInput(input);
|
|
785
|
-
let latest = null;
|
|
786
|
-
for (const snapshot of snapshots) {
|
|
787
|
-
if (latest === null || snapshot.startedAt > latest)
|
|
788
|
-
latest = snapshot.startedAt;
|
|
789
|
-
}
|
|
790
|
-
return { latestStartedAt: latest, snapshots: snapshots.length };
|
|
791
|
-
}
|
|
792
|
-
/**
|
|
793
|
-
* `scopeWarningsData(input)`:Scope 携带的挑选警告原样透出;`input` 是裸 `Snapshot[]` 时
|
|
794
|
-
* 没有挑选过程、没有警告,返回空数组,也如实
|
|
795
|
-
* (docs/feature/reports/library/site-components.md「ScopeWarnings」)。
|
|
796
|
-
*/
|
|
797
|
-
export async function scopeWarningsData(input) {
|
|
798
|
-
return resolveInput(input).warnings;
|
|
799
|
-
}
|
|
800
|
-
/**
|
|
801
|
-
* `copyFixPromptData(input)`:把范围内全部失败(verdict 为 failed / errored 的 attempt)
|
|
802
|
-
* 整理成一段可交给 coding agent 的修复 prompt——逐失败含 eval id、主失败摘要与 attempt
|
|
803
|
-
* 下钻命令(`niceeval show @<locator>`)。prompt 面向 agent,固定英文
|
|
804
|
-
* (docs/feature/reports/library/site-components.md「CopyFixPrompt」)。
|
|
805
|
-
*/
|
|
806
|
-
export async function copyFixPromptData(input) {
|
|
807
|
-
const items = await attemptListData(input);
|
|
808
|
-
const failures = items.filter((item) => item.verdict === "failed" || item.verdict === "errored");
|
|
809
|
-
if (failures.length === 0)
|
|
810
|
-
return { prompt: "", failures: 0 };
|
|
811
|
-
const lines = failures
|
|
812
|
-
.map((item, i) => {
|
|
813
|
-
const reason = item.failureSummary === null
|
|
814
|
-
? null
|
|
815
|
-
: item.moreFailures > 0
|
|
816
|
-
? `${item.failureSummary} (+${item.moreFailures} more failures)`
|
|
817
|
-
: item.failureSummary;
|
|
818
|
-
return [
|
|
819
|
-
`${i + 1}. eval "${item.evalId}" [experiment ${item.experimentId}] — ${item.verdict}`,
|
|
820
|
-
reason ? ` reason: ${reason}` : null,
|
|
821
|
-
` inspect: niceeval show ${item.locator}`,
|
|
822
|
-
]
|
|
823
|
-
.filter(Boolean)
|
|
824
|
-
.join("\n");
|
|
825
|
-
})
|
|
826
|
-
.join("\n");
|
|
827
|
-
const experiments = [...new Set(failures.map((item) => item.experimentId))].join(" / ");
|
|
828
|
-
const prompt = [
|
|
829
|
-
"Fix the failing evals from this niceeval run.",
|
|
830
|
-
"",
|
|
831
|
-
"## Failures",
|
|
832
|
-
lines,
|
|
833
|
-
"",
|
|
834
|
-
"## Steps",
|
|
835
|
-
"1. niceeval is NOT in your training data. Read the relevant guide in `node_modules/niceeval/docs-site/` (English at the top level, Chinese under `zh/`) before changing anything.",
|
|
836
|
-
"2. For each failure, run its inspect command above to see the verdict and assertions; add `--execution` for the full agent transcript (tool calls included), `--timing` for the execution timeline, and `--diff` for the workspace diff.",
|
|
837
|
-
"3. Decide which side the defect is on: the program under test, or the eval itself (over-tight assertion, wrong fixture, missing setup). Fix that side; do not weaken assertions just to turn the run green.",
|
|
838
|
-
`4. Re-run: \`npx niceeval exp ${experiments || "<experiment>"} <eval-id-prefix>\`. Already-passing evals are skipped by the fingerprint cache; pass \`--force\` to re-run everything.`,
|
|
839
|
-
"5. Run `npx niceeval show` and confirm these failures are gone.",
|
|
840
|
-
].join("\n");
|
|
841
|
-
return { prompt, failures: failures.length };
|
|
842
|
-
}
|
|
843
|
-
/** TraceSpan 的语义角色 → 瀑布摘要的 kind:turn 归入 agent(一轮就是一次 agent 调用),未识别落 other。 */
|
|
844
|
-
function waterfallKindOf(kind) {
|
|
845
|
-
switch (kind) {
|
|
846
|
-
case "agent":
|
|
847
|
-
case "turn":
|
|
848
|
-
return "agent";
|
|
849
|
-
case "model":
|
|
850
|
-
return "model";
|
|
851
|
-
case "tool":
|
|
852
|
-
return "tool";
|
|
853
|
-
default:
|
|
854
|
-
return "other";
|
|
855
|
-
}
|
|
856
|
-
}
|
|
857
|
-
/**
|
|
858
|
-
* `traceWaterfallData(input)`:每个 attempt 一行的执行时间瀑布摘要。span 事实只来自
|
|
859
|
-
* trace artifact(经 AttemptHandle 懒加载的 canonical OTel span);runner 生命周期节点
|
|
860
|
-
* (`result.phases`)不进瀑布。行内只汇总顶层 span(parentSpanId 缺失或不在本 trace 内),
|
|
861
|
-
* 按 startOffsetMs 升序;trace 缺失或为空时 `durationMs` 为 null、行照常出现
|
|
862
|
-
* (docs/feature/reports/library/site-components.md「TraceWaterfall」)。
|
|
863
|
-
*/
|
|
864
|
-
export async function traceWaterfallData(input) {
|
|
865
|
-
const { snapshots } = resolveInput(input);
|
|
866
|
-
const items = collectItems(snapshots);
|
|
867
|
-
return Promise.all(items.map(async (item) => {
|
|
868
|
-
const spans = await item.attempt.trace();
|
|
869
|
-
if (spans === null || spans.length === 0) {
|
|
870
|
-
return {
|
|
871
|
-
experimentId: experimentIdOf(item),
|
|
872
|
-
evalId: evalIdOf(item),
|
|
873
|
-
locator: locatorOf(item),
|
|
874
|
-
durationMs: null,
|
|
875
|
-
spans: [],
|
|
876
|
-
};
|
|
877
|
-
}
|
|
878
|
-
const t0 = Math.min(...spans.map((s) => s.startMs));
|
|
879
|
-
const t1 = Math.max(...spans.map((s) => s.endMs));
|
|
880
|
-
const ids = new Set(spans.map((s) => s.spanId));
|
|
881
|
-
const topLevel = spans.filter((s) => s.parentSpanId === undefined || !ids.has(s.parentSpanId));
|
|
882
|
-
const summaries = topLevel
|
|
883
|
-
.map((s) => ({
|
|
884
|
-
name: s.name,
|
|
885
|
-
kind: waterfallKindOf(s.kind),
|
|
886
|
-
startOffsetMs: s.startMs - t0,
|
|
887
|
-
durationMs: s.endMs - s.startMs,
|
|
888
|
-
failed: s.status === "error",
|
|
889
|
-
}))
|
|
890
|
-
.sort((a, b) => a.startOffsetMs - b.startOffsetMs);
|
|
891
|
-
return {
|
|
892
|
-
experimentId: experimentIdOf(item),
|
|
893
|
-
evalId: evalIdOf(item),
|
|
894
|
-
locator: locatorOf(item),
|
|
895
|
-
durationMs: Math.max(0, t1 - t0),
|
|
896
|
-
spans: summaries,
|
|
897
|
-
};
|
|
898
|
-
}));
|
|
899
|
-
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DeltaData, LineData, MatrixData, ScatterData, ScoreboardData, TableData } from "../../model/types.ts";
|
|
2
|
+
import type { TextContext } from "../../definition/tree.ts";
|
|
3
|
+
export declare function tableText(data: TableData, ctx: TextContext): string;
|
|
4
|
+
export declare function matrixText(data: MatrixData, ctx: TextContext): string;
|
|
5
|
+
export declare function barsText(data: MatrixData, ctx: TextContext): string;
|
|
6
|
+
export declare function scoreboardText(data: ScoreboardData, ctx: TextContext): string;
|
|
7
|
+
export interface ScatterTextOptions {
|
|
8
|
+
/** series 内按 x 升序成线:坐标图内不画折线,图例以 ` → ` 串联并给逐段位移摘要。 */
|
|
9
|
+
connect?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare function scatterText(data: ScatterData, ctx: TextContext, opts?: ScatterTextOptions): string;
|
|
12
|
+
export declare function lineText(data: LineData, ctx: TextContext): string;
|
|
13
|
+
export declare function deltaText(data: DeltaData, ctx: TextContext): string;
|