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
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "实验与生命周期"
|
|
3
|
+
sidebarTitle: "实验"
|
|
4
|
+
description: "如何写好实验。选择 Agent、传递 model 和 flags,设置 runs、预算、并发与 Sandbox,并用 setup / teardown 起停实验级共享服务。"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Experiment 是可签入的运行配置:同一批评估用例对着哪个 adapter、哪个模型、开哪些 flags、跑几次、预算多少,都写在 `experiments/` 里。CLI 的位置参数只负责筛评估用例,不负责临时改 agent 或运行配置。
|
|
8
|
+
|
|
9
|
+
## 最小实验
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
// experiments/local.ts
|
|
13
|
+
import { defineExperiment } from "niceeval";
|
|
14
|
+
import { webAgent } from "../agents/web-agent.ts";
|
|
15
|
+
|
|
16
|
+
export default defineExperiment({
|
|
17
|
+
agent: webAgent({ baseUrl: "http://127.0.0.1:5188" }),
|
|
18
|
+
});
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`agent` 放的是已经配置好的 agent 实例。被测系统的 URL、鉴权、协议细节通常传给 adapter 工厂;运行器不会单独保存一个 `agentConfig` 字段。
|
|
22
|
+
|
|
23
|
+
## 评估不同的 System Prompt 对于 Agent 的影响
|
|
24
|
+
使用 flag 机制,配置不同的 Flag,设置两个实验,对比不同 Prompt 的区别。
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
// experiments/concise.ts
|
|
28
|
+
import { defineExperiment } from "niceeval";
|
|
29
|
+
import { webAgent } from "../agents/web-agent.ts";
|
|
30
|
+
|
|
31
|
+
export default defineExperiment({
|
|
32
|
+
description: "测试 V1 System Prompt",
|
|
33
|
+
agent: webAgent({
|
|
34
|
+
baseUrl: "https://staging.example.com",
|
|
35
|
+
}),
|
|
36
|
+
model: "gpt-5.4",
|
|
37
|
+
flags: {
|
|
38
|
+
promptVariant: "v1",
|
|
39
|
+
},
|
|
40
|
+
runs: 1,
|
|
41
|
+
earlyExit: true,
|
|
42
|
+
budget: 5,
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
// experiments/concise.ts
|
|
48
|
+
import { defineExperiment } from "niceeval";
|
|
49
|
+
import { webAgent } from "../agents/web-agent.ts";
|
|
50
|
+
|
|
51
|
+
export default defineExperiment({
|
|
52
|
+
description: "测试 V1 System Prompt",
|
|
53
|
+
agent: webAgent({
|
|
54
|
+
baseUrl: "https://staging.example.com",
|
|
55
|
+
}),
|
|
56
|
+
model: "gpt-5.4",
|
|
57
|
+
flags: {
|
|
58
|
+
promptVariant: "v1",
|
|
59
|
+
},
|
|
60
|
+
runs: 1,
|
|
61
|
+
earlyExit: true,
|
|
62
|
+
budget: 5,
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
`model` 会作为 `ctx.model` 传给 Adapter;如果你的 Agent 支持模型选择,自己构建请求
|
|
68
|
+
|
|
69
|
+
`flags` 会作为 `ctx.flags` 传给 Adapter,也会作为 `t.flags` 出现在评估用例里。
|
|
70
|
+
|
|
71
|
+
语义就是产品 A/B 测试里的 feature flag,应该编写 Adapter 把 Flag 发给你的 Agent,Agent 根据 Flag 切换不同的 System Prompt 或者行为。
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
// agents/web-agent.ts
|
|
75
|
+
async send(input, ctx) {
|
|
76
|
+
await fetch(`${baseUrl}/api/turn`, {
|
|
77
|
+
method: "POST",
|
|
78
|
+
headers: { "content-type": "application/json" },
|
|
79
|
+
body: JSON.stringify({
|
|
80
|
+
message: input.text,
|
|
81
|
+
model: ctx.model,
|
|
82
|
+
flags: ctx.flags,
|
|
83
|
+
}),
|
|
84
|
+
signal: ctx.signal,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## 编写一组实验
|
|
90
|
+
|
|
91
|
+
一个实验文件是一格配置。要比较多个模型、agent 或 flag 取值,就写多个文件;目录只负责 id:
|
|
92
|
+
|
|
93
|
+
```text
|
|
94
|
+
experiments/
|
|
95
|
+
prompts/baseline.ts
|
|
96
|
+
prompts/concise.ts
|
|
97
|
+
retrieval/with-retrieval.ts
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
npx niceeval exp prompts
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
报告直接比较当前 Scope 中的这些 experiments,不需要额外分组字段。
|
|
105
|
+
|
|
106
|
+
只想验证某一个配置时,把位置参数写成该配置的完整 id:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
npx niceeval exp prompts/concise
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
用于逐配置排查——确认某一格改动是否达标,不用先跑完整组,也不用把其它配置文件挪出目录。
|
|
113
|
+
|
|
114
|
+
## 常用字段
|
|
115
|
+
|
|
116
|
+
| 字段 | 用途 |
|
|
117
|
+
|---|---|
|
|
118
|
+
| `agent` | 选择并配置 adapter;必填 |
|
|
119
|
+
| `model` | 单个模型名,经 `ctx.model` 透传 |
|
|
120
|
+
| `reasoningEffort` | 单个推理努力程度(如 `"high"`),经 `ctx.reasoningEffort` / `t.reasoningEffort` 透传,归属与 `model` 一致 |
|
|
121
|
+
| `flags` | 实验条件(A/B 里的 feature flag),任意 JSON 对象,经 `ctx.flags` / `t.flags` 透传 |
|
|
122
|
+
| `runs` | 每个评估用例 × 配置最多跑几次 |
|
|
123
|
+
| `earlyExit` | 多次运行里通过一次就提前停止 |
|
|
124
|
+
| `evals` | `"*"`、id 前缀数组,或遍历只读 eval 描述并返回 boolean 的函数 |
|
|
125
|
+
| `timeoutMs` | 单个 attempt 的超时 |
|
|
126
|
+
| `budget` | 这一格配置的预算上限 |
|
|
127
|
+
| `maxConcurrency` | 这一格配置的并发上限 |
|
|
128
|
+
| `sandbox` | sandbox agent 使用的固定 spec;spec 可带 `environments` 表按评估用例的环境 profile 换预制产物,也可以链 `.setup()` / `.teardown()` 挂环境 Hook |
|
|
129
|
+
| `setup` | 实验级 Hook:整个实验只跑一次、在你自己的机器上执行,启动全部 Attempt 共享的服务(见下) |
|
|
130
|
+
| `teardown` | 与 `setup` 成对的实验级 Hook:全部 Attempt 收尾后执行一次,当且仅当 `setup` 的时点已经走到(见下) |
|
|
131
|
+
|
|
132
|
+
## 启动 Experiment 共享服务
|
|
133
|
+
|
|
134
|
+
有些资源是「一个实验一份、所有 Attempt 共用」的:一条到内网记忆服务的隧道、一个实验专用的 mock server、一个 license 租约。这类资源写进一对实验级 Hook `setup` / `teardown`:整场至多各跑一次。`setup` 在这个实验第一个要派发的 Attempt 前执行;`teardown` 在全部 Attempt 收尾后执行(运行被中断也执行),当且仅当 `setup` 的时点已经走到才触发——`setup` 抛错同样要走到 `teardown`,收尾代码要对可能未赋值的变量做防御。上一次的结果全部被复用、这个实验一个 Attempt 都不需要真正运行时,`setup` 和 `teardown` 都不会执行:
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
// setup 拿到的地址、密钥放模块变量:teardown 和同文件里的 agent(每个 Attempt 都会执行、晚于 setup)直接读它。
|
|
138
|
+
let tunnel: { url: string; apiKey: string; stop(): Promise<void> };
|
|
139
|
+
|
|
140
|
+
export default defineExperiment({
|
|
141
|
+
agent: nowledgeAgent(() => ({ url: tunnel.url, apiKey: tunnel.apiKey })),
|
|
142
|
+
evals: ["memory/"],
|
|
143
|
+
async setup(ctx) {
|
|
144
|
+
ctx.progress({ message: "starting nowledge tunnel" });
|
|
145
|
+
tunnel = await nowledgeTunnel({ signal: ctx.signal });
|
|
146
|
+
},
|
|
147
|
+
async teardown(ctx) {
|
|
148
|
+
ctx.progress({ message: "stopping nowledge tunnel" });
|
|
149
|
+
await tunnel?.stop(); // setup 抛错也会走到这里:对可能未赋值的变量做防御
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
`setup` 在跑的时候,终端的 `ACTIVE` 区会显示一行 `experiment setup · <实验 id>`,`ctx.progress(...)` 的消息就更新在这一行末尾;等它的 Attempt 计入排队数,这不是卡住。在 CI 或 agent 输出里,`setup` / `teardown` 的开始和结束各追加一行。
|
|
155
|
+
|
|
156
|
+
`setup` 抛错时,这个实验的每条 Attempt 都记为 `errored`(错误码 `experiment-setup-failed`)、逐条进报告;同一批的其它实验照常跑——环境起不来不该伪装成绿,也不该连坐别人。
|
|
157
|
+
|
|
158
|
+
`teardown` 里资源释放是必达底线:用 `try/finally` 包住,不管前面的观测代码是否出错都要执行。观测类动作(health probe、指标上报)只是 best-effort——给它自己的短超时、失败不要拦住释放,并在 `ctx.signal.aborted` 时直接跳过;中断路径上,一次可能挂起的观测不该挡在「拆隧道、退租约」前面:
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
async teardown(ctx) {
|
|
162
|
+
try {
|
|
163
|
+
if (!ctx.signal.aborted) {
|
|
164
|
+
await tunnel?.probe({ timeoutMs: 10_000 }).catch(() => {});
|
|
165
|
+
}
|
|
166
|
+
} finally {
|
|
167
|
+
await tunnel?.stop(); // 释放是必达底线,无论观测成败都要执行
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
`setup` / `teardown` 只管「在你机器上、一个实验一份」的服务。要在跑 agent 前按实验在**Sandbox 里**准备环境(装二进制、预热、跨 attempt 载入和回存状态),挂在 `sandbox` 字段的 spec 上:
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
export default defineExperiment({
|
|
176
|
+
agent: codexAgent({ mcpServers: [mempalMcp] }),
|
|
177
|
+
sandbox: e2bSandbox({ template: "fasteval-agents" })
|
|
178
|
+
.setup(mempalSetup("codex")) // 预检、写动态配置、预热、载入状态
|
|
179
|
+
.teardown(mempalTeardown("codex")), // 回存状态
|
|
180
|
+
maxConcurrency: 1, // 载入和回存之间不能并发,声明串行
|
|
181
|
+
});
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
固定的 Agent CLI、系统包和大模型缓存应先做进 image/template/snapshot;`.setup()` 不应在每个 Attempt 重建同一套环境。从官方 Docker 镜像、E2B 模板或 Vercel runtime 派生预制环境的步骤见 [Sandbox Provider · 从官方基线继续构建以提速](/zh/tutorials/sandbox-providers#从官方基线继续构建以提速)。
|
|
185
|
+
|
|
186
|
+
Hook 的执行时机、多 Hook 顺序和失败语义见 [Sandbox provider · 生命周期](/zh/tutorials/sandbox-providers#生命周期)。
|
|
187
|
+
|
|
188
|
+
### 与 Sandbox Hook 协作
|
|
189
|
+
|
|
190
|
+
实验级 Hook 起宿主机侧服务,Sandbox Hook 每个 Sandbox 把坐标写进去、收尾时回存状态——两层在同一个文件里靠模块变量衔接,时序由 runner 保证:实验级 `setup` 早于本实验任何 Sandbox Hook,Sandbox Hook 读到的变量一定已经赋好值:
|
|
191
|
+
|
|
192
|
+
```ts
|
|
193
|
+
// experiments/compare/claude--nowledge.ts
|
|
194
|
+
import { defineExperiment } from "niceeval";
|
|
195
|
+
import { e2bSandbox } from "niceeval/sandbox";
|
|
196
|
+
import { nowledgeAgent, nowledgeTunnel } from "../../agents/nowledge.ts";
|
|
197
|
+
import { loadMemoryState, saveMemoryState } from "../shared/memory-state.ts";
|
|
198
|
+
|
|
199
|
+
let tunnel: { url: string; apiKey: string; stop(): Promise<void> };
|
|
200
|
+
|
|
201
|
+
export default defineExperiment({
|
|
202
|
+
agent: nowledgeAgent(() => ({ url: tunnel.url, apiKey: tunnel.apiKey })),
|
|
203
|
+
evals: ["memory/"],
|
|
204
|
+
maxConcurrency: 1, // [载入…回存] 是临界区,声明式串行
|
|
205
|
+
sandbox: e2bSandbox({ template: "niceeval-agents" })
|
|
206
|
+
.setup(async (sandbox, ctx) => {
|
|
207
|
+
// 每沙箱一次,晚于实验级 setup:把宿主机侧坐标写进沙箱
|
|
208
|
+
await sandbox.writeFiles({
|
|
209
|
+
".nowledge/config.json": JSON.stringify({ url: tunnel.url, apiKey: tunnel.apiKey }),
|
|
210
|
+
});
|
|
211
|
+
await loadMemoryState(sandbox, ctx.experimentId);
|
|
212
|
+
})
|
|
213
|
+
.teardown(async (sandbox, ctx) => {
|
|
214
|
+
await saveMemoryState(sandbox, ctx.experimentId); // 每沙箱回存跨 attempt 状态
|
|
215
|
+
}),
|
|
216
|
+
async setup(ctx) {
|
|
217
|
+
tunnel = await nowledgeTunnel({ signal: ctx.signal }); // 整场一次,宿主机侧
|
|
218
|
+
},
|
|
219
|
+
async teardown() {
|
|
220
|
+
await tunnel?.stop(); // 全部 Attempt 收尾后拆
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
一份实验文件从上往下读就是完整的运行说明:整场一次的宿主机资源在实验级 Hook 对里;每 Sandbox 的写入与回存在 `sandbox` 链式 Hook 里,读实验级产物;agent 怎么连自己、评估用例的任务夹具各在 agent 定义与 `EvalDef` 里,不进实验文件。
|
|
226
|
+
|
|
227
|
+
### 多个实验共享同一套生命周期代码
|
|
228
|
+
|
|
229
|
+
对比组里常常是几个实验对着同一类基础设施——同一个记忆产品,claude 与 codex 各一格对照,起停机制完全一样。把起停写成一个**工厂函数**,返回共享同一闭包的整套件:实验级 Hook 对、给 agent / MCP 工厂读坐标的 getter、把坐标写进 Sandbox 的 sandbox Hook。每个实验文件各自调用一次工厂,同一套代码、各自的实例与坐标:
|
|
230
|
+
|
|
231
|
+
```ts
|
|
232
|
+
// experiments/shared/nowledge.ts —— 启停一份代码;实例、坐标每实验一份
|
|
233
|
+
import type { ExperimentHookContext } from "niceeval";
|
|
234
|
+
import type { SandboxHook } from "niceeval/sandbox";
|
|
235
|
+
|
|
236
|
+
export function nowledgeLifecycle() {
|
|
237
|
+
let instance: string | undefined;
|
|
238
|
+
let env: { url: string; apiKey: string } | undefined;
|
|
239
|
+
|
|
240
|
+
return {
|
|
241
|
+
/** agent / MCP 工厂经它读连接信息:闭包值,setup 之后才存在 */
|
|
242
|
+
endpoint: () => env!,
|
|
243
|
+
|
|
244
|
+
async setup(ctx: ExperimentHookContext) {
|
|
245
|
+
instance = `exp-${ctx.experimentId.replace(/[^A-Za-z0-9]+/g, "-")}`;
|
|
246
|
+
ctx.progress({ message: `[nowledge] activating ${instance}` });
|
|
247
|
+
await memctl("up", instance); // 容器 + 隧道,全新记忆库
|
|
248
|
+
env = await readInstanceEnv(instance);
|
|
249
|
+
},
|
|
250
|
+
|
|
251
|
+
async teardown(ctx: ExperimentHookContext) {
|
|
252
|
+
if (!instance) return; // setup 没走到起实例就抛了:无事可扫
|
|
253
|
+
await memctl("down", instance); // 释放是必达底线
|
|
254
|
+
},
|
|
255
|
+
|
|
256
|
+
/** 每沙箱一次:把闭包坐标写进沙箱 */
|
|
257
|
+
sandboxSetup(): SandboxHook {
|
|
258
|
+
return async (sandbox) => {
|
|
259
|
+
await sandbox.writeFiles({
|
|
260
|
+
".nowledge/env": `NMEM_URL=${env!.url}\nNMEM_API_KEY=${env!.apiKey}\n`,
|
|
261
|
+
});
|
|
262
|
+
};
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
实验文件里换 agent 只换 agent 那几行,生命周期四行接完:
|
|
269
|
+
|
|
270
|
+
```ts
|
|
271
|
+
// experiments/compare/codex-gpt-5.4--nowledge.ts
|
|
272
|
+
const nowledge = nowledgeLifecycle();
|
|
273
|
+
export default defineExperiment({
|
|
274
|
+
agent: codexAgent(nowledgeCodexConfig(nowledge.endpoint)),
|
|
275
|
+
sandbox: e2bSandbox({ template: CODEX_TEMPLATE }).setup(nowledge.sandboxSetup()),
|
|
276
|
+
setup: nowledge.setup,
|
|
277
|
+
teardown: nowledge.teardown,
|
|
278
|
+
maxConcurrency: 1, // 中心化记忆库,attempt 串行累积
|
|
279
|
+
});
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
两条纪律保证多个实验并发跑同一套代码不互相踩踏:
|
|
283
|
+
|
|
284
|
+
- **工厂在 import 期只创建闭包,不做 I/O、不读配置**——实验文件在 `niceeval exp` 的发现阶段就会被 import,import 抛错会连累同批无关实验;所有硬失败留给 `setup`。
|
|
285
|
+
- **运行时坐标活在工厂闭包里,不放模块级单例**——同批并行的两个实验各持一份,互不覆写;坐标在 `setup` 之后才存在。
|
|
286
|
+
|
|
287
|
+
服务起多份太贵、必须让同批实验共享一份实例时,用「首进启动、末出关停」的引用计数代替按实验各建一份:
|
|
288
|
+
|
|
289
|
+
```ts
|
|
290
|
+
// experiments/shared/nowledge-shared.ts
|
|
291
|
+
let refs = 0;
|
|
292
|
+
let starting: Promise<void> | undefined;
|
|
293
|
+
let service: { url: string; stop(): Promise<void> } | undefined;
|
|
294
|
+
|
|
295
|
+
export const sharedNowledge = {
|
|
296
|
+
async setup() {
|
|
297
|
+
refs += 1;
|
|
298
|
+
starting ??= startNowledge().then((s) => { service = s; });
|
|
299
|
+
await starting; // 并发实验等同一个启动;启动失败各自抛错
|
|
300
|
+
},
|
|
301
|
+
async teardown() {
|
|
302
|
+
refs -= 1;
|
|
303
|
+
if (refs === 0) {
|
|
304
|
+
await service?.stop(); // 启动失败时 service 未赋值,防御式跳过
|
|
305
|
+
service = undefined;
|
|
306
|
+
starting = undefined;
|
|
307
|
+
}
|
|
308
|
+
},
|
|
309
|
+
};
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
计数能保持平衡,靠的是成对触发规则本身:`teardown` 当且仅当同层 `setup` 时点走到过才执行、`setup` 抛错也照样配对触发 `teardown`,`refs` 不会泄漏。
|
|
313
|
+
|
|
314
|
+
边界在生命周期:同批共享的服务活不过这次 run。要**跨 run** 存在的服务(先起好、连续跑多次 `niceeval exp`)仍归外部编排(`docker compose` 之类)起停,URL 经环境变量传入。
|
|
315
|
+
|
|
316
|
+
## 让不同评估用例使用不同预制环境
|
|
317
|
+
|
|
318
|
+
一批真实任务可能需要不同版本的运行时和依赖。评估用例用 `environment` 声明一个与 provider 无关的 profile ID;sandbox spec 的 `environments` 表再把它映射到具体模板或快照:
|
|
319
|
+
|
|
320
|
+
```ts
|
|
321
|
+
// evals/astropy-2021.eval.ts
|
|
322
|
+
export default defineEval({
|
|
323
|
+
environment: "python-3.9-astropy-4.2",
|
|
324
|
+
async test(t) {
|
|
325
|
+
// 驱动任务并验证结果
|
|
326
|
+
},
|
|
327
|
+
});
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
```ts
|
|
331
|
+
// experiments/shared.ts —— 一个 provider 一张表,所有实验共用
|
|
332
|
+
import { e2bSandbox } from "niceeval/sandbox";
|
|
333
|
+
|
|
334
|
+
export const e2b = e2bSandbox({
|
|
335
|
+
template: "codex-default", // 未声明 environment 的 eval 用它
|
|
336
|
+
environments: {
|
|
337
|
+
"python-3.9-astropy-4.2": { template: "codex-python39" },
|
|
338
|
+
},
|
|
339
|
+
});
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
```ts
|
|
343
|
+
// experiments/e2b.ts —— 实验保持一行 diff,覆盖全部 eval
|
|
344
|
+
import { defineExperiment } from "niceeval";
|
|
345
|
+
import { e2b } from "./shared";
|
|
346
|
+
|
|
347
|
+
export default defineExperiment({
|
|
348
|
+
agent: codexAgent(),
|
|
349
|
+
sandbox: e2b,
|
|
350
|
+
});
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
`environment` 是非空的稳定字符串,不是包版本约束。`environments` 表的值就是该 provider 预制产物字段的覆盖(Docker 的 `image`、E2B 的 `template`、Vercel 的 `snapshotId`)。NiceEval 在启动任何 Sandbox 前对所有选中的评估用例完成查表;某条评估用例声明的 profile 缺表项会在启动时一次性报出全部缺项。remote Agent 不创建 Sandbox,不参与查表。因为映射是随 spec 复用的数据,同一个实验能覆盖全部评估用例——分数和对比表不会因为环境不同被拆成多个实验。
|
|
354
|
+
|
|
355
|
+
跨配置比较的设计建议见[实验矩阵](/zh/tutorials/experiments)。Adapter 对 `ctx.model` 和 `ctx.flags` 的用法见 [Adapter](/zh/explanation/adapter)。
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
3
|
-
sidebarTitle: "
|
|
4
|
-
description: "
|
|
2
|
+
title: "编写 Send"
|
|
3
|
+
sidebarTitle: "编写 Send"
|
|
4
|
+
description: "分七步编写 Adapter 的 send 函数:发送消息、续接会话、记录用量、映射工具事件、处理人工介入(HITL)、接入 OTel trace,并透传 Experiment flags。"
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
[Adapter](/zh/explanation/adapter)
|
|
7
|
+
[Adapter](/zh/explanation/adapter) 定义了 `send` 的契约:接收 `TurnInput` 和 `AgentContext`,返回 `Turn`。本教程从发送一条消息开始,逐步加入完整接入所需的能力。每一步只增加少量代码,已有部分以 `// ……省略` 标出;步骤末尾列出新增数据支持的断言。完成任一步后,都可以把对应断言写进评估用例,重跑 `npx niceeval exp`,再在 `niceeval view` 中检查多轮轨迹、用量、工具事件或待回答请求。
|
|
8
8
|
|
|
9
9
|
三个贯穿全文的原则:
|
|
10
10
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
11
|
+
- **连接用户前端正在使用的接口。** Adapter 调用相同端点并接收相同格式,不为评估用例新建接口,也不 import 应用内部代码直接调用函数。具体原因见[接入你的 Agent](/zh/tutorials/connect-your-agent)。
|
|
12
|
+
- **只手写 transport。** URL、鉴权和请求体取决于应用。`niceeval/adapter` 提供从原始返回到标准事件流的转换器;`ctx.session` 提供会话续接与 HITL 暂停恢复所需的状态 API。
|
|
13
13
|
- **运行反馈走 `ctx`,不直接写终端。** 长步骤用 `ctx.progress(...)`;需要在运行后回顾的退化或异常上下文用 `ctx.diagnostic(...)`;无法继续时抛错。不要从 Adapter 调用 `console.log/error` 或写 `process.stdout/stderr`。
|
|
14
14
|
|
|
15
|
-

|
|
16
16
|
|
|
17
|
-
##
|
|
17
|
+
## 确认应用接口形状
|
|
18
18
|
|
|
19
|
-
[NiceEval](https://niceeval.com/)
|
|
19
|
+
[NiceEval](https://niceeval.com/) 不定义新的应用协议。现有应用通常使用下列协议或其变体,内置转换器按这些响应形状提供:
|
|
20
20
|
|
|
21
|
-
| 协议 |
|
|
21
|
+
| 协议 | 定义方 | 说明 | 参考 |
|
|
22
22
|
|---|---|---|---|
|
|
23
23
|
| **Chat Completions** | OpenAI;业界事实标准,几乎所有模型服务商都提供兼容端点 | 无状态一问一答:客户端每轮发完整 `messages` 列表,一个 JSON 回来 | [API 参考](https://platform.openai.com/docs/api-reference/chat) |
|
|
24
24
|
| **Responses / Open Responses** | OpenAI(Responses API);Open Responses 是基于它的开放规范,OpenAI 发起、Hugging Face 等社区共建,用于多提供商互操作 | 有状态、面向 agent:请求带 `previous_response_id` 由服务端续接历史,`output` 数组承诺记录全过程 | [API 参考](https://platform.openai.com/docs/api-reference/responses) · [Open Responses 规范](https://www.openresponses.org/specification) |
|
|
25
25
|
| **AI SDK(Vercel)** | Vercel;TypeScript 生态的事实标准 | 不是线上协议而是 SDK:`generateText` 返回完整结果,`useChat` 走它定义的 UI Message Stream 流协议 | [generateText 参考](https://ai-sdk.dev/docs/reference/ai-sdk-core/generate-text) · [UI Message Stream 协议](https://ai-sdk.dev/docs/ai-sdk-ui/stream-protocol) |
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
以下步骤使用 Chat Completions 形接口。Responses 形接口和流式接口的替换实现分别在第二步和第四步给出。
|
|
28
28
|
|
|
29
29
|
## 第一步:发一条消息,拿到回复
|
|
30
30
|
|
|
@@ -72,15 +72,15 @@ if (!res.requestId) {
|
|
|
72
72
|
|
|
73
73
|
`progress` 不落盘;diagnostic 会随 Attempt 保存并可通过 locator 回顾。HTTP 连接失败或响应无法解析时直接抛错,runner 会记录错误发生在 `agent.run`,并把 Attempt 标为 `errored`。
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
**这一步支持**:`t.reply`、`t.messageIncludes()`、Judge 的全部对话材料,以及 Experiment 侧的**模型对比**。`ctx.model` 来自 Experiment 的 `model`;运行器原样传递,Adapter 只负责转发。接入等级见 [Tier](/zh/explanation/tier)。
|
|
76
76
|
|
|
77
77
|
它有两个明显的局限:每轮都是一场全新对话(第二次 `t.send` 接不上第一次),工具调用完全看不见。后面两步各解决一个。
|
|
78
78
|
|
|
79
79
|
## 第二步:接上之前的消息
|
|
80
80
|
|
|
81
|
-
运行器在会话上只承诺一件事:**同一条会话线的每次 `send` 拿到同一个 `ctx.session
|
|
81
|
+
运行器在会话上只承诺一件事:**同一条会话线的每次 `send` 拿到同一个 `ctx.session`,新会话线(评估用例的第一轮,或 `t.newSession()` 之后)拿到一个全新的。**
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
会话续接方式取决于应用接口形状。`ctx.session` 为两种常见模式分别提供一对存取器:
|
|
84
84
|
|
|
85
85
|
- **客户端带全量历史**(服务端无状态,每轮发完整消息列表:Chat Completions 形是典型)→ `ctx.session.history<TMsg>()`
|
|
86
86
|
- **服务端记历史**(接口收一个会话 id:Responses 形的 `previous_response_id`、各 SDK 的原生 session / thread)→ `ctx.session.id` + `ctx.session.capture(id)`
|
|
@@ -129,7 +129,7 @@ export default defineAgent({
|
|
|
129
129
|
|
|
130
130
|
`capture` 只在还没记过 id 时落地,后端重复回传(甚至因 fork 变了)也不会覆盖正在续接的线。
|
|
131
131
|
|
|
132
|
-
|
|
132
|
+
**这一步支持**:多轮对话,以及 `t.newSession()` 的会话隔离。
|
|
133
133
|
|
|
134
134
|
## 第三步:记录消费
|
|
135
135
|
|
|
@@ -149,7 +149,7 @@ export default defineAgent({
|
|
|
149
149
|
|
|
150
150
|
`Usage` 的完整字段还有可选的 `cacheReadTokens` / `cacheWriteTokens`、请求次数 `requests`,以及 `costUSD`——网关回了实测成本就填它,优先于价格表估算。接口不回用量就整个不填 `usage`,其它断言不受影响。这段照抄也是过渡:下一步的官方转换器会连 `usage` 一起填好。
|
|
151
151
|
|
|
152
|
-
|
|
152
|
+
**这一步支持**:`t.maxTokens()` / `t.maxCost()` 评分器(`maxCost` 用 `costUSD` 或配置里的价格表估算),以及报告和 `niceeval view` 里的用量。
|
|
153
153
|
|
|
154
154
|
## 第四步:把工具解析成事件
|
|
155
155
|
|
|
@@ -196,19 +196,19 @@ type StreamEvent =
|
|
|
196
196
|
|
|
197
197
|
接口不是这个形状,就换对应的件:
|
|
198
198
|
|
|
199
|
-
|
|
|
199
|
+
| 接口响应形状 | 内置实现 | 需要编写的代码 |
|
|
200
200
|
|---|---|---|
|
|
201
|
-
| Chat Completions 形返回 | `fromChatCompletion(res)` |
|
|
202
|
-
| Responses 形返回 | `fromResponses(res)` |
|
|
203
|
-
| AI SDK `generateText` 的完整结果 | `fromAiSdk(result)` |
|
|
204
|
-
| 流式:SDK 原生事件透传(一帧一个完整单元) | `fromClaudeSdkMessages()` / `fromPiAgentEvents()` / `fromCodexThreadEvents()` |
|
|
205
|
-
| 流式:AI SDK 的 UI Message Stream(`useChat` 协议) | `uiMessageStreamAgent()` |
|
|
201
|
+
| Chat Completions 形返回 | `fromChatCompletion(res)` | 无需手写映射 |
|
|
202
|
+
| Responses 形返回 | `fromResponses(res)` | 无需手写映射 |
|
|
203
|
+
| AI SDK `generateText` 的完整结果 | `fromAiSdk(result)` | 无需手写映射 |
|
|
204
|
+
| 流式:SDK 原生事件透传(一帧一个完整单元) | `fromClaudeSdkMessages()` / `fromPiAgentEvents()` / `fromCodexThreadEvents()` | 无需手写映射 |
|
|
205
|
+
| 流式:AI SDK 的 UI Message Stream(`useChat` 协议) | `uiMessageStreamAgent()` | 无需手写 `send` 或事件映射 |
|
|
206
206
|
| 流式:逐 token / 逐参数增量 | 协议方官方 reducer;没有才用 `deltaStream({ toOps })` | 一张"帧类型 → 操作"映射表 |
|
|
207
207
|
| 只有最终答案 | 手写几条 events | 一条 `message` 起步(第一步就是这个档) |
|
|
208
208
|
|
|
209
|
-
|
|
209
|
+
内置转换器按响应形状工作,不假设具体应用协议。只有增量流且协议方没有现成 reducer 时才需要编写映射;映射只声明每一帧对应的操作,拼接、配对和落盘时机由 `deltaStream` 处理。
|
|
210
210
|
|
|
211
|
-
|
|
211
|
+
归一完成后,你吐哪种事件,评估用例作者就能写哪族断言:
|
|
212
212
|
|
|
213
213
|
| 你吐的事件 | 解锁的断言 |
|
|
214
214
|
|---|---|
|
|
@@ -217,16 +217,16 @@ type StreamEvent =
|
|
|
217
217
|
| `input.requested`(配合 status `"waiting"`) | `t.parked()`、`t.requireInputRequest()`、`t.respond()`(第五步) |
|
|
218
218
|
| `thinking` / `compaction` / `error` | 对应断言与 o11y 计数 |
|
|
219
219
|
|
|
220
|
-
|
|
220
|
+
Chat Completions 响应**不保证包含完整过程记录**。应用可能在服务端完成工具循环,只返回最终答案。因此,`fromChatCompletion` 的返回不带完整性证明:`calledTool` 等正断言可用,`notCalledTool` 等负断言会提示证据不完整。Responses 协议要求 `output` 数组记录完整过程,`fromResponses` 的返回带完整性证明,负断言可信。两者的可信度差异来自接口契约。
|
|
221
221
|
|
|
222
|
-
|
|
222
|
+
**这一步支持**:`t.calledTool()`、`t.toolOrder()`、`t.maxToolCalls()`、`t.noFailedActions()` 等工具断言。
|
|
223
223
|
|
|
224
224
|
## 第五步:HITL
|
|
225
225
|
|
|
226
226
|
应用中途停下来等人(工具审批、等补充信息)时,`send` 两侧各有义务:
|
|
227
227
|
|
|
228
228
|
- **停轮**:返回 `status: "waiting"`,并且每个待回答的问题吐一条带稳定 `id` 的 `input.requested` 事件——`t.parked()`、`t.requireInputRequest()` 读它,回答靠这个 `id` 对位。
|
|
229
|
-
-
|
|
229
|
+
- **回答轮**:评估用例里的 `t.respond(...)` 到 Adapter 是**又一次普通的 `send`**(还是同一条会话线、同一份状态),人的裁决以结构化形式随 `input.responses` 到达,每条带 `requestId`、`optionId` 或 `text`(形态见[不同回答的入参](/zh/explanation/adapter#不同回答的入参))。Adapter 先把裁决交回应用,再接着取结果。被人拒绝的调用,`action.result` 的 `status` 置 `"rejected"` 而不是 `"failed"`——拒绝是人的决定、不是工具故障,`noFailedActions()` 不误伤。
|
|
230
230
|
|
|
231
231
|
"停轮时读了一半的现场"(比如一条读到一半的 SSE 流)也存在 `ctx.session` 上:停轮时 `ctx.session.hold(现场)`,回答轮开头 `ctx.session.take()` 取回——取到即清除,一次消费。
|
|
232
232
|
|
|
@@ -286,13 +286,13 @@ export default defineAgent({
|
|
|
286
286
|
|
|
287
287
|
不需要 HITL 的接口,删掉停轮现场相关的三处(`Pending`、`hold`、开头的 `take` 分支)即可,其余不变。停轮 / 回答 / 续跑的完整心智模型见 [HITL](/zh/explanation/hitl)。
|
|
288
288
|
|
|
289
|
-
|
|
289
|
+
**这一步支持**:`t.parked()`、`t.requireInputRequest()`、`t.respond()` / `t.respondAll()`,以及 `calledTool(..., { status: "rejected" })` 的精确断言。
|
|
290
290
|
|
|
291
291
|
## 第六步:接上 OTel trace
|
|
292
292
|
|
|
293
293
|
应用已经埋了点(标准 OTel HTTP 服务端埋点即可)的话,接入分两半——一半是启动期配置,一半在 `send` 里。分清它们就是分清「不变的」和「每轮变的」。
|
|
294
294
|
|
|
295
|
-
**端点是启动期配置,不从 send 传。** [NiceEval](https://niceeval.com/) 的 OTLP 接收地址每次运行都一样,所以它不走 `ctx`:在 `niceeval.config.ts` 里把接收端口钉住,应用启动时把自己的 OTel exporter 指向这个固定 URL
|
|
295
|
+
**端点是启动期配置,不从 send 传。** [NiceEval](https://niceeval.com/) 的 OTLP 接收地址每次运行都一样,所以它不走 `ctx`:在 `niceeval.config.ts` 里把接收端口钉住,应用启动时把自己的 OTel exporter 指向这个固定 URL,之后跑多少次评估用例都不用再改:
|
|
296
296
|
|
|
297
297
|
```ts
|
|
298
298
|
// niceeval.config.ts
|
|
@@ -307,7 +307,7 @@ export default defineConfig({
|
|
|
307
307
|
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318/v1/traces node server.js
|
|
308
308
|
```
|
|
309
309
|
|
|
310
|
-
**send 里传的是本轮的 trace context,不是端点。** `ctx.telemetry.headers` 是运行器每轮新生成的 W3C `traceparent` 头——把它 spread 进请求,应用这一轮产生的 span 就精确挂到本轮的 trace
|
|
310
|
+
**send 里传的是本轮的 trace context,不是端点。** `ctx.telemetry.headers` 是运行器每轮新生成的 W3C `traceparent` 头——把它 spread 进请求,应用这一轮产生的 span 就精确挂到本轮的 trace 下,并发跑多条评估用例时归属不混。回到主线的 chat-app,`send` 里只多一行:
|
|
311
311
|
|
|
312
312
|
```ts
|
|
313
313
|
const res = await fetch(`${BASE_URL}/v1/chat/completions`, {
|
|
@@ -318,7 +318,7 @@ OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318/v1/traces node server.js
|
|
|
318
318
|
|
|
319
319
|
`ctx.telemetry` 只在配置了 OTel 接入时出现,没配时 spread 一个 `undefined` 也安全,这行可以常驻。不带这个头 span 也能收到,但归属退化成时间窗口、该 agent 的轮次会降为串行——带上它是并发下归属准确的来源。
|
|
320
320
|
|
|
321
|
-
|
|
321
|
+
**这一步支持**:`niceeval view` 中按轮显示调用瀑布图,包括模型调用、工具执行、耗时与 token。断言仍读取前几步产生的事件;span 只用于瀑布图。接收器配置和 span 归属规则见 [OTel 接入](/zh/tutorials/connect-otel)。
|
|
322
322
|
|
|
323
323
|
## 第七步:透传 experiment 的 flags(A/B 对比)
|
|
324
324
|
|
|
@@ -345,26 +345,26 @@ export default defineExperiment({
|
|
|
345
345
|
});
|
|
346
346
|
```
|
|
347
347
|
|
|
348
|
-
两个 experiment 文件各声明一份 `flags`,`npx niceeval exp`
|
|
348
|
+
两个 experiment 文件各声明一份 `flags`,`npx niceeval exp` 分别跑同一批评估用例,就是一组 A/B 对比。这是三档接入里的 Tier 3(要求应用配合暴露开关),投入与回报见 [Tier](/zh/explanation/tier);`flags` 与 `model`、`runs` 等其余 experiment 字段见[写实验](/zh/tutorials/write-experiment)。
|
|
349
349
|
|
|
350
|
-
|
|
350
|
+
**这一步支持**:同一批评估用例跨变体的成绩对比。
|
|
351
351
|
|
|
352
352
|
## 对照:五个 t API 到 send 的形态
|
|
353
353
|
|
|
354
|
-
|
|
354
|
+
七步写完,回头看评估用例侧的五个驱动 API——它们到 `send` 只是同一个函数收到不同字段,没有第二个要实现的方法:
|
|
355
355
|
|
|
356
|
-
|
|
|
356
|
+
| 评估用例 API | Adapter 调用 | `send` 输入 |
|
|
357
357
|
|---|---|---|
|
|
358
358
|
| `t.send(text)` | 一次 `send` | `input.text`;`ctx.session` 是这条会话线的自有状态 |
|
|
359
359
|
| `t.sendFile(path, text?)` | 一次 `send` | 同上,外加 `input.files`(base64 的 `InputFile[]`);按应用接口的方式放进请求体,不支持多模态就忽略 |
|
|
360
|
-
| `t.newSession()` | 不直接触发 `send` | 开第二条会话线;该线随后第一次 `send`
|
|
360
|
+
| `t.newSession()` | 不直接触发 `send` | 开第二条会话线;该线随后第一次 `send` 拿到一份**全空的**状态——和整个评估用例的第一次 `send` 形态完全相同 |
|
|
361
361
|
| `t.respond(...answers)` | 一次**普通的** `send` | `input.text` = 回答文本;`input.responses` 逐请求一条 `{ requestId, optionId }`(自由文本回答则是 `{ requestId, text }`);还是同一条线、同一份状态 |
|
|
362
|
-
| `t.respondAll(optionId)` | 一次**普通的** `send` | 同上,每条待处理请求各一条回答;`optionId`
|
|
362
|
+
| `t.respondAll(optionId)` | 一次**普通的** `send` | 同上,每条待处理请求各一条回答;`optionId` 已在评估用例侧对每条请求校验过存在,写错直接抛,不会静默传给应用 |
|
|
363
363
|
|
|
364
364
|
## 相关阅读
|
|
365
365
|
|
|
366
|
-
- [Adapter](/zh/explanation/adapter) —
|
|
367
|
-
- [接入你的 Agent](/zh/
|
|
366
|
+
- [Adapter](/zh/explanation/adapter) — `send` 的输入、输出、三个接入等级和能力来源。
|
|
367
|
+
- [接入你的 Agent](/zh/tutorials/connect-your-agent) — 最小接入、参数传递与可选能力。
|
|
368
368
|
- [HITL](/zh/explanation/hitl) — 停轮等人的完整概念:握手时序与两侧义务。
|
|
369
|
-
- [Drive](/zh/explanation/drive) —
|
|
369
|
+
- [Drive](/zh/explanation/drive) — 评估用例侧的 `t.send()`、`t.newSession()` 与 HITL 用法。
|
|
370
370
|
- [Assert](/zh/explanation/assert) — 标准事件流驱动的完整断言词汇。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "niceeval",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Agent-native eval tool — eval agents, services, functions, and coding-agent fixtures",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -64,8 +64,8 @@
|
|
|
64
64
|
"types": "./dist/report/built-in/index.d.ts",
|
|
65
65
|
"import": "./dist/report/built-in/index.js"
|
|
66
66
|
},
|
|
67
|
-
"./report/react/styles.css": "./src/report/
|
|
68
|
-
"./report/react/enhance.js": "./src/report/
|
|
67
|
+
"./report/react/styles.css": "./src/report/assets/styles.css",
|
|
68
|
+
"./report/react/enhance.js": "./src/report/assets/enhance.js"
|
|
69
69
|
},
|
|
70
70
|
"files": [
|
|
71
71
|
"INDEX.md",
|
|
@@ -76,8 +76,11 @@
|
|
|
76
76
|
"docs-site/images"
|
|
77
77
|
],
|
|
78
78
|
"dependencies": {
|
|
79
|
+
"@vercel/analytics": "^2.0.1",
|
|
80
|
+
"@vercel/speed-insights": "^2.0.0",
|
|
79
81
|
"autoevals": "0.0.132",
|
|
80
82
|
"effect": "^3.21.4",
|
|
83
|
+
"mermaid": "^11.16.0",
|
|
81
84
|
"tar-stream": "^3.1.7",
|
|
82
85
|
"tsx": "^4.19.2"
|
|
83
86
|
},
|
|
@@ -166,6 +169,7 @@
|
|
|
166
169
|
"test": "vitest run",
|
|
167
170
|
"test:watch": "vitest",
|
|
168
171
|
"niceeval": "node bin/niceeval.js",
|
|
172
|
+
"e2e": "tsx e2e/scripts/run.ts",
|
|
169
173
|
"gen:diff-code": "tsx scripts/gen-diff-code.ts",
|
|
170
174
|
"docs:reference": "tsx scripts/generate-reference.ts",
|
|
171
175
|
"tiers:sync": "node scripts/sync-tiers.mjs sync",
|
|
@@ -174,7 +178,7 @@
|
|
|
174
178
|
"build:report": "tsc -p tsconfig.report-build.json && node scripts/prune-report-dist.mjs",
|
|
175
179
|
"build:index": "tsx scripts/generate-reference.ts --bundled-index",
|
|
176
180
|
"site:dev": "cd site && node scripts/dev.mjs",
|
|
177
|
-
"site:build": "cd site && next build",
|
|
181
|
+
"site:build": "cd site && next build && cd .. && tsx scripts/submit-indexnow.ts",
|
|
178
182
|
"docs:dev": "node scripts/docs-dev.mjs",
|
|
179
183
|
"docs:validate": "cd docs-site && npx --yes mint@latest validate",
|
|
180
184
|
"docs:links": "cd docs-site && npx --yes mint@latest broken-links --check-anchors --check-redirects"
|