niceeval 0.9.1 → 0.10.2
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 +10 -0
- package/dist/report/components/attempt-detail/AttemptConversation.js +74 -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 +97 -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 +297 -0
- package/dist/report/components/attempt-detail/faces.d.ts +14 -0
- package/dist/report/components/attempt-detail/faces.js +239 -0
- package/dist/report/components/attempt-detail/index.d.ts +38 -0
- package/dist/report/components/attempt-detail/index.js +547 -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 +4 -5
- package/dist/report/{react → components/entity-lists}/ExperimentList.js +12 -11
- 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 +175 -0
- package/dist/report/components/entity-lists/index.d.ts +49 -0
- package/dist/report/components/entity-lists/index.js +169 -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 +27 -60
- 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} +13 -7
- package/dist/report/{format.js → model/format.js} +79 -9
- 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} +154 -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 +151 -24
- package/dist/sandbox/docker.d.ts +6 -0
- package/dist/sandbox/e2b.d.ts +0 -1
- 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 +6 -6
- 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 +17 -13
- 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 +36 -33
- 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 +195 -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 +102 -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 +60 -57
- package/docs-site/zh/tutorials/write-experiment.mdx +353 -0
- package/docs-site/zh/{how-to → tutorials}/write-send.mdx +40 -40
- package/package.json +10 -7
- 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 +75 -59
- 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/o11y/prices.json +176 -99
- package/src/report/{react → assets}/colors.ts +22 -0
- package/src/report/{react → assets}/enhance.js +1 -33
- package/src/report/assets/styles.css +1785 -0
- 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 +158 -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 +224 -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 +758 -0
- package/src/report/components/attempt-detail/compute.ts +336 -0
- package/src/report/components/attempt-detail/faces.ts +260 -0
- package/src/report/components/attempt-detail/index.tsx +600 -0
- package/src/report/components/attempt-detail/validate.test.ts +252 -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 +33 -27
- package/src/report/components/entity-lists/compute.ts +196 -0
- package/src/report/components/entity-lists/faces.ts +208 -0
- package/src/report/components/entity-lists/index.tsx +238 -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 +42 -70
- 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 +66 -26
- 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 +128 -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} +89 -10
- 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} +159 -22
- package/src/report/react/index.tsx +54 -26
- package/src/report/{dual-render.test.tsx → runtime/dual-render.test.tsx} +601 -53
- 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 +160 -24
- package/src/sandbox/docker.ts +7 -0
- package/src/sandbox/e2b-reconcile.test.ts +125 -0
- package/src/sandbox/e2b.ts +47 -12
- 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 +143 -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/react/styles.css +0 -945
- 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
|
@@ -5,26 +5,13 @@
|
|
|
5
5
|
// `extends` 在另一份报告上叠外壳——页归 base、外壳逐字段覆盖,合并在调用时折叠完成,
|
|
6
6
|
// 宿主装载看到的永远是已折叠的普通产物。
|
|
7
7
|
//
|
|
8
|
-
// renderReportToText
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
|
|
12
|
-
import type {
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
renderNodeToText,
|
|
16
|
-
resolveReportTree,
|
|
17
|
-
validateReportTree,
|
|
18
|
-
ResolveMemo,
|
|
19
|
-
type ReportNode,
|
|
20
|
-
type TextRenderOptions,
|
|
21
|
-
} from "./tree.ts";
|
|
22
|
-
import {
|
|
23
|
-
localizedTextEquals,
|
|
24
|
-
resolveLocalizedText,
|
|
25
|
-
type LocalizedText,
|
|
26
|
-
type ReportLocale,
|
|
27
|
-
} from "./locale.ts";
|
|
8
|
+
// text/web 两个宿主的渲染入口(renderReportToText / renderReportToStaticHtml)在 ../runtime/
|
|
9
|
+
// (text.ts / web.ts);这里只有 ReportDefinition 的类型体系、装载规范化与元数据折叠
|
|
10
|
+
// (buildReportMeta / resolveReportTitle),不做任何渲染。
|
|
11
|
+
|
|
12
|
+
import type { Scope } from "../../results/types.ts";
|
|
13
|
+
import type { ReportNode } from "./tree.ts";
|
|
14
|
+
import { localizedTextEquals, type LocalizedText } from "../model/locale.ts";
|
|
28
15
|
|
|
29
16
|
// ───────────────────────── 公开形状 ─────────────────────────
|
|
30
17
|
|
|
@@ -73,7 +60,7 @@ export interface ReportShell {
|
|
|
73
60
|
|
|
74
61
|
export type NonEmptyArray<T> = readonly [T, ...T[]];
|
|
75
62
|
|
|
76
|
-
export interface
|
|
63
|
+
export interface ReportPageBase {
|
|
77
64
|
/** 页面身份:`--page <id>` 的取值、web 路由 `#/page/<id>` 与导航锚。小写字母、数字与连字符。 */
|
|
78
65
|
id: string;
|
|
79
66
|
/** 导航中的页名。 */
|
|
@@ -82,6 +69,18 @@ export interface ReportPage {
|
|
|
82
69
|
content: ReportNode;
|
|
83
70
|
}
|
|
84
71
|
|
|
72
|
+
/**
|
|
73
|
+
* 页按输入分两种形态,仍是同一个类型族,走同一条 resolve → validate → render 管线
|
|
74
|
+
* (docs/feature/reports/architecture.md「Attempt 详情是一张参数化 page」):
|
|
75
|
+
* - `input` 省略或为 `"scope"`:消费宿主选择的 Scope;省略时规范化为 `navigation: true`。
|
|
76
|
+
* - `input: "attempt"`:以 locator 为参数,消费一份 AttemptEvidence;没有 locator 时不能打开,
|
|
77
|
+
* 必须显式 `navigation: false`,不进导航。
|
|
78
|
+
* 一份报告至多声明一张 attempt-input page。
|
|
79
|
+
*/
|
|
80
|
+
export type ReportPage =
|
|
81
|
+
| (ReportPageBase & { input?: "scope"; navigation?: boolean })
|
|
82
|
+
| (ReportPageBase & { input: "attempt"; navigation: false });
|
|
83
|
+
|
|
85
84
|
/** content / pages / extends 三选一由类型表达,不把非法状态留到运行期。 */
|
|
86
85
|
export type ReportDef = ReportShell &
|
|
87
86
|
(
|
|
@@ -92,7 +91,7 @@ export type ReportDef = ReportShell &
|
|
|
92
91
|
extends?: never;
|
|
93
92
|
}
|
|
94
93
|
| {
|
|
95
|
-
/**
|
|
94
|
+
/** 非空页列表;`navigation !== false` 的项按数组顺序显示。 */
|
|
96
95
|
pages: NonEmptyArray<ReportPage>;
|
|
97
96
|
content?: never;
|
|
98
97
|
extends?: never;
|
|
@@ -128,17 +127,27 @@ export interface ReportDefinition {
|
|
|
128
127
|
readonly pages: NonEmptyArray<ReportPage>;
|
|
129
128
|
}
|
|
130
129
|
|
|
131
|
-
/**
|
|
130
|
+
/** 规范化后页列表在 ctx.report 上的元数据形态(id / 导航页名 / 输入声明 / 导航资格)。 */
|
|
131
|
+
export interface ReportMetaPage {
|
|
132
|
+
id: string;
|
|
133
|
+
title: LocalizedText;
|
|
134
|
+
input: "scope" | "attempt";
|
|
135
|
+
navigation: boolean;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* 规范化后的报告声明,经组合组件 ctx.report 只读可见(scripts / styles 是注入资产,不进)。
|
|
140
|
+
* 不携带"当前是哪一页"——那由 ctx.page(PageContext)表达,两者不是同一份状态
|
|
141
|
+
* (docs/feature/reports/library/shell.md「行为约束」)。
|
|
142
|
+
*/
|
|
132
143
|
export interface ReportMeta {
|
|
133
144
|
/** 走完回退链(声明 title → 唯一快照 name → 内置文案「Eval 运行结果 / Eval Results」)后的标题。 */
|
|
134
145
|
title: LocalizedText;
|
|
135
146
|
/** 页头外链;声明省略时为空数组。 */
|
|
136
147
|
links: readonly ReportLink[];
|
|
137
148
|
footer?: LocalizedText;
|
|
138
|
-
/**
|
|
139
|
-
pages: NonEmptyArray<
|
|
140
|
-
/** 当前渲染中的页 id。 */
|
|
141
|
-
pageId: string;
|
|
149
|
+
/** 规范化后的页列表,恒非空。 */
|
|
150
|
+
pages: NonEmptyArray<ReportMetaPage>;
|
|
142
151
|
}
|
|
143
152
|
|
|
144
153
|
/** 单页缩写展开出的唯一页 id 与内置页名。 */
|
|
@@ -332,6 +341,53 @@ function assertHeadTags(tags: unknown): HeadTag[] {
|
|
|
332
341
|
return tags as HeadTag[];
|
|
333
342
|
}
|
|
334
343
|
|
|
344
|
+
/**
|
|
345
|
+
* page 的 input / navigation 规范化(shell.md「page 显式声明输入」):省略或 "scope" 时补
|
|
346
|
+
* `input: "scope"`,`navigation` 缺省为 true;"attempt" 必须显式 `navigation: false`——
|
|
347
|
+
* 没有 locator 时不可打开,不能悄悄挤进导航,省略或传 true 都在装载期报错。
|
|
348
|
+
*/
|
|
349
|
+
function normalizePageInputAndNavigation(page: Record<string, unknown>): ReportPage {
|
|
350
|
+
const input = page.input;
|
|
351
|
+
if (input === undefined || input === "scope") {
|
|
352
|
+
return {
|
|
353
|
+
id: page.id as string,
|
|
354
|
+
title: page.title as LocalizedText,
|
|
355
|
+
content: page.content as ReportNode,
|
|
356
|
+
input: "scope",
|
|
357
|
+
navigation: page.navigation !== false,
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
if (input === "attempt") {
|
|
361
|
+
if (page.navigation !== false) {
|
|
362
|
+
throw new Error(
|
|
363
|
+
`Report page "${page.id}" declares input: "attempt" but not navigation: false — an attempt-input page has no content without a locator, so it must not appear in navigation. Add navigation: false.`,
|
|
364
|
+
);
|
|
365
|
+
}
|
|
366
|
+
return {
|
|
367
|
+
id: page.id as string,
|
|
368
|
+
title: page.title as LocalizedText,
|
|
369
|
+
content: page.content as ReportNode,
|
|
370
|
+
input: "attempt",
|
|
371
|
+
navigation: false,
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
throw new Error(
|
|
375
|
+
`Report page "${page.id}" input ${JSON.stringify(input)} is not valid — input is omitted, "scope", or "attempt".`,
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/** 一份报告至多一张 attempt-input page,避免 show @<locator> 与 locator 链接出现多个目标。 */
|
|
380
|
+
function assertAtMostOneAttemptPage(pages: readonly ReportPage[]): void {
|
|
381
|
+
const attemptPages = pages.filter((p) => p.input === "attempt");
|
|
382
|
+
if (attemptPages.length > 1) {
|
|
383
|
+
throw new Error(
|
|
384
|
+
`A report can declare at most one input: "attempt" page — got ${attemptPages.length} (${attemptPages
|
|
385
|
+
.map((p) => `"${p.id}"`)
|
|
386
|
+
.join(", ")}). Keep one and remove the others, or fold their content into a single attempt-input page.`,
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
335
391
|
export function defineReport(content: ReportNode): ReportDefinition;
|
|
336
392
|
export function defineReport(def: ReportDef): ReportDefinition;
|
|
337
393
|
export function defineReport(input: ReportNode | ReportDef): ReportDefinition {
|
|
@@ -379,7 +435,9 @@ export function defineReport(input: ReportNode | ReportDef): ReportDefinition {
|
|
|
379
435
|
pages = base.pages;
|
|
380
436
|
} else if (hasContent) {
|
|
381
437
|
assertNotDefinition(def.content, 'defineReport "content"');
|
|
382
|
-
pages = [
|
|
438
|
+
pages = [
|
|
439
|
+
{ id: DEFAULT_PAGE_ID, title: DEFAULT_PAGE_TITLE, input: "scope", navigation: true, content: def.content as ReportNode },
|
|
440
|
+
];
|
|
383
441
|
} else {
|
|
384
442
|
const raw = def.pages as unknown;
|
|
385
443
|
if (!Array.isArray(raw) || raw.length === 0) {
|
|
@@ -388,6 +446,7 @@ export function defineReport(input: ReportNode | ReportDef): ReportDefinition {
|
|
|
388
446
|
);
|
|
389
447
|
}
|
|
390
448
|
const seen = new Set<string>();
|
|
449
|
+
const normalized: ReportPage[] = [];
|
|
391
450
|
for (const page of raw as Array<Record<string, unknown>>) {
|
|
392
451
|
if (typeof page?.id !== "string" || !PAGE_ID_PATTERN.test(page.id)) {
|
|
393
452
|
throw new Error(
|
|
@@ -402,9 +461,11 @@ export function defineReport(input: ReportNode | ReportDef): ReportDefinition {
|
|
|
402
461
|
seen.add(page.id);
|
|
403
462
|
assertLocalizedText(page.title, `Report page "${page.id}" title`);
|
|
404
463
|
assertNotDefinition(page.content, `Report page "${page.id}" content`);
|
|
464
|
+
normalized.push(normalizePageInputAndNavigation(page));
|
|
405
465
|
}
|
|
406
|
-
pages =
|
|
466
|
+
pages = normalized;
|
|
407
467
|
}
|
|
468
|
+
assertAtMostOneAttemptPage(pages);
|
|
408
469
|
|
|
409
470
|
if (def.title !== undefined) assertLocalizedText(def.title, "defineReport title");
|
|
410
471
|
if (def.footer !== undefined) assertLocalizedText(def.footer, "defineReport footer");
|
|
@@ -482,145 +543,17 @@ export function resolveReportTitle(definition: ReportDefinition, scope: Scope):
|
|
|
482
543
|
return names.every((name) => localizedTextEquals(name, first)) ? first : FALLBACK_REPORT_TITLE;
|
|
483
544
|
}
|
|
484
545
|
|
|
485
|
-
/** 规范化声明 → 组合组件可见的 ReportMeta(scripts / styles
|
|
486
|
-
export function buildReportMeta(definition: ReportDefinition, scope: Scope
|
|
546
|
+
/** 规范化声明 → 组合组件可见的 ReportMeta(scripts / styles 是注入资产,不进;不携带当前页)。 */
|
|
547
|
+
export function buildReportMeta(definition: ReportDefinition, scope: Scope): ReportMeta {
|
|
487
548
|
return {
|
|
488
549
|
title: resolveReportTitle(definition, scope),
|
|
489
550
|
links: definition.links,
|
|
490
551
|
...(definition.footer !== undefined ? { footer: definition.footer } : {}),
|
|
491
|
-
pages: definition.pages.map((page) => ({
|
|
492
|
-
id:
|
|
493
|
-
title:
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
// ───────────────────────── 页选择与 text 宿主入口 ─────────────────────────
|
|
500
|
-
|
|
501
|
-
/** `--page` 未命中:宿主据此按用法错误退出并列出可用页 id。 */
|
|
502
|
-
export class ReportPageNotFoundError extends Error {
|
|
503
|
-
readonly pageId: string;
|
|
504
|
-
readonly available: string[];
|
|
505
|
-
constructor(pageId: string, available: string[]) {
|
|
506
|
-
super(`page "${pageId}" not found. Available pages: ${available.join(", ")}`);
|
|
507
|
-
this.pageId = pageId;
|
|
508
|
-
this.available = available;
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
export function pickReportPage(definition: ReportDefinition, pageId?: string): ReportPage {
|
|
513
|
-
if (pageId === undefined) return definition.pages[0];
|
|
514
|
-
const page = definition.pages.find((p) => p.id === pageId);
|
|
515
|
-
if (!page) {
|
|
516
|
-
throw new ReportPageNotFoundError(
|
|
517
|
-
pageId,
|
|
518
|
-
definition.pages.map((p) => p.id),
|
|
519
|
-
);
|
|
520
|
-
}
|
|
521
|
-
return page;
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
/** 宿主注入的渲染上下文:官方口径挑好的 Scope 与结果根完整读取面。 */
|
|
525
|
-
export interface ReportHostContext {
|
|
526
|
-
scope: Scope;
|
|
527
|
-
/** 组合组件 ctx.results 的来源;历史视图从这里自行挑 Snapshot[]。 */
|
|
528
|
-
results: Results;
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
export interface RenderReportTextOptions extends TextRenderOptions {
|
|
532
|
-
/** 渲染哪一页;缺省第一页。未命中抛 ReportPageNotFoundError。 */
|
|
533
|
-
pageId?: string;
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
/**
|
|
537
|
-
* text 宿主的装载语义:选页 → resolve(组合展开 + spec 取数,唯一的 await 边界)→ 树校验 →
|
|
538
|
-
* 遍历渲染 text 面。不需要 react-dom。宿主不在报告树外另设警告通道——挑选警告的呈现件是
|
|
539
|
-
* `ScopeWarnings` 组件,内建报告每页都放它,自定义报告放不放是作者义务
|
|
540
|
-
* (docs/feature/reports/architecture.md「Scope 是计算入口」)。
|
|
541
|
-
*/
|
|
542
|
-
export async function renderReportToText(
|
|
543
|
-
definition: ReportDefinition,
|
|
544
|
-
ctx: ReportHostContext,
|
|
545
|
-
options?: RenderReportTextOptions,
|
|
546
|
-
): Promise<string> {
|
|
547
|
-
const page = pickReportPage(definition, options?.pageId);
|
|
548
|
-
const meta = buildReportMeta(definition, ctx.scope, page.id);
|
|
549
|
-
const resolved = await resolveReportTree(page.content, {
|
|
550
|
-
scope: ctx.scope,
|
|
551
|
-
results: ctx.results,
|
|
552
|
-
report: meta,
|
|
553
|
-
memo: new ResolveMemo(),
|
|
554
|
-
});
|
|
555
|
-
validateReportTree(resolved);
|
|
556
|
-
return renderNodeToText(resolved, createTextContext(options));
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
/** 页索引标题行(show 多页索引 / view 导航共用的解析结果):按 locale 解析的标题字符串。 */
|
|
560
|
-
export function reportTitleText(definition: ReportDefinition, scope: Scope, locale: ReportLocale): string {
|
|
561
|
-
return resolveLocalizedText(resolveReportTitle(definition, scope), locale);
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
// ───────────────────────── 逐页(树)渲染入口:宿主联系面 ─────────────────────────
|
|
565
|
-
|
|
566
|
-
/** 宿主索引命令的完整上下文(docs/feature/reports/show/reports.md「索引命令携带完整上下文」)。 */
|
|
567
|
-
export interface HostCommandContext {
|
|
568
|
-
patterns: string[];
|
|
569
|
-
results?: string;
|
|
570
|
-
experiment?: string;
|
|
571
|
-
report?: string;
|
|
572
|
-
page?: string;
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
function quoteArg(value: string): string {
|
|
576
|
-
return /^[A-Za-z0-9._/@-]+$/.test(value) ? value : `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
/** 按上下文拼组索引的可复制命令:`niceeval show <patterns> --exp <id> [--results/--report/--page]`。 */
|
|
580
|
-
function experimentCommandFor(ctx: HostCommandContext): (experimentIdPrefix: string) => string {
|
|
581
|
-
return (prefix) => {
|
|
582
|
-
const parts = ["niceeval show", ...ctx.patterns.map(quoteArg), `--exp ${quoteArg(prefix)}`];
|
|
583
|
-
if (ctx.results !== undefined) parts.push(`--results ${quoteArg(ctx.results)}`);
|
|
584
|
-
if (ctx.report !== undefined) parts.push(`--report ${quoteArg(ctx.report)}`);
|
|
585
|
-
if (ctx.page !== undefined) parts.push(`--page ${quoteArg(ctx.page)}`);
|
|
586
|
-
return parts.join(" ");
|
|
552
|
+
pages: definition.pages.map((page) => ({
|
|
553
|
+
id: page.id,
|
|
554
|
+
title: page.title,
|
|
555
|
+
input: page.input ?? "scope",
|
|
556
|
+
navigation: page.navigation ?? true,
|
|
557
|
+
})) as unknown as NonEmptyArray<ReportMetaPage>,
|
|
587
558
|
};
|
|
588
559
|
}
|
|
589
|
-
|
|
590
|
-
/** 逐页渲染的宿主上下文:官方口径的 Scope、结果根读取面与规范化声明(ctx.report)。 */
|
|
591
|
-
export interface ReportTreeHostContext {
|
|
592
|
-
scope: Scope;
|
|
593
|
-
results: Results;
|
|
594
|
-
report: ReportMeta;
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
export interface RenderTreeTextOptions extends TextRenderOptions {
|
|
598
|
-
/** 组索引命令的完整上下文;给了就按它拼命令,experimentCommand 显式注入时以后者为准。 */
|
|
599
|
-
commandContext?: HostCommandContext;
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
/**
|
|
603
|
-
* 渲染一页报告树的 text 面(宿主逐页调用;页选择归宿主):
|
|
604
|
-
* resolve(组合展开 + spec 取数)→ validate → render。宿主不在报告树外另设警告通道,
|
|
605
|
-
* 挑选警告由页内的 `ScopeWarnings` 组件呈现(内建报告每页都放它)。
|
|
606
|
-
*/
|
|
607
|
-
export async function renderReportTreeToText(
|
|
608
|
-
tree: ReportNode,
|
|
609
|
-
ctx: ReportTreeHostContext,
|
|
610
|
-
options?: RenderTreeTextOptions,
|
|
611
|
-
): Promise<string> {
|
|
612
|
-
const resolved = await resolveReportTree(tree, {
|
|
613
|
-
scope: ctx.scope,
|
|
614
|
-
results: ctx.results,
|
|
615
|
-
report: ctx.report,
|
|
616
|
-
memo: new ResolveMemo(),
|
|
617
|
-
});
|
|
618
|
-
validateReportTree(resolved);
|
|
619
|
-
const textCtx = createTextContext({
|
|
620
|
-
...options,
|
|
621
|
-
...(options?.experimentCommand === undefined && options?.commandContext !== undefined
|
|
622
|
-
? { experimentCommand: experimentCommandFor(options.commandContext) }
|
|
623
|
-
: {}),
|
|
624
|
-
});
|
|
625
|
-
return renderNodeToText(resolved, textCtx);
|
|
626
|
-
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { describe, expect, it } from "vitest";
|
|
7
7
|
|
|
8
|
-
import type { Scope } from "
|
|
8
|
+
import type { Scope } from "../../results/index.ts";
|
|
9
9
|
import { buildReportMeta, defineReport } from "./report.ts";
|
|
10
10
|
|
|
11
11
|
const emptyScope = { snapshots: [] } as unknown as Scope;
|
|
@@ -97,6 +97,6 @@ describe("defineReport head 通道(装载校验)", () => {
|
|
|
97
97
|
];
|
|
98
98
|
const definition = defineReport({ content: null, head });
|
|
99
99
|
expect(definition.head).toEqual(head);
|
|
100
|
-
expect(buildReportMeta(definition, emptyScope
|
|
100
|
+
expect(buildReportMeta(definition, emptyScope)).not.toHaveProperty("head");
|
|
101
101
|
});
|
|
102
102
|
});
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
// 列宽按显示宽度算(CJK 记 2 列);null 渲染 —,不补 0;超宽先折最宽的左对齐列,
|
|
7
7
|
// 压到下限仍放不下就从右侧丢列并如实报数(「截断报剩余」是既有契约,不在这里破例)。
|
|
8
8
|
|
|
9
|
-
import type { TableProps, TableRow } from "
|
|
10
|
-
import type { TextContext } from "
|
|
11
|
-
import { countText, localeText, resolveLocalizedText } from "../locale.ts";
|
|
12
|
-
import { charDisplayWidth, renderAlignedRows, stringWidth, wrapDisplay, type ColumnAlign } from "
|
|
9
|
+
import type { TableProps, TableRow } from "./primitives.tsx";
|
|
10
|
+
import type { TextContext } from "./tree.ts";
|
|
11
|
+
import { countText, localeText, resolveLocalizedText } from "../model/locale.ts";
|
|
12
|
+
import { charDisplayWidth, renderAlignedRows, stringWidth, wrapDisplay, type ColumnAlign } from "../model/text-layout.ts";
|
|
13
13
|
|
|
14
14
|
const MISSING_MARK = "—";
|
|
15
15
|
/** 列间距,与 renderAlignedRows 的 join(" ") 一致。 */
|
|
@@ -10,12 +10,37 @@
|
|
|
10
10
|
// 只在 resolve 阶段被懒加载,永远不进渲染路径。
|
|
11
11
|
|
|
12
12
|
import type { ReactNode } from "react";
|
|
13
|
-
import type { AttemptLocator } from "
|
|
14
|
-
import type {
|
|
15
|
-
import {
|
|
16
|
-
import type
|
|
13
|
+
import type { AttemptLocator } from "../../results/locator.ts";
|
|
14
|
+
import type { AttemptEvidence } from "../../results/attempt-evidence.ts";
|
|
15
|
+
import type { Results, Scope } from "../../results/types.ts";
|
|
16
|
+
import { DEFAULT_REPORT_LOCALE, type ReportLocale } from "../model/locale.ts";
|
|
17
|
+
import type { ReportInput } from "../model/types.ts";
|
|
17
18
|
import type { ReportMeta } from "./report.ts";
|
|
18
19
|
|
|
20
|
+
// ───────────────────────── 当前页判别(PageContext) ─────────────────────────
|
|
21
|
+
|
|
22
|
+
/** scope-input page 的当前页上下文:消费宿主选择的 Scope,没有 locator/evidence。 */
|
|
23
|
+
export interface ScopePageContext {
|
|
24
|
+
id: string;
|
|
25
|
+
input: "scope";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** attempt-input page 的当前页上下文:按 locator 消费一份 AttemptEvidence。 */
|
|
29
|
+
export interface AttemptPageContext {
|
|
30
|
+
id: string;
|
|
31
|
+
input: "attempt";
|
|
32
|
+
locator: AttemptLocator;
|
|
33
|
+
evidence: AttemptEvidence;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 当前渲染中的页判别联合(docs/feature/reports/library/shell.md「行为约束」、
|
|
38
|
+
* library/attempt-detail.md「page 输入与 spec / data 形态」)。经 ComposeContext.page 与
|
|
39
|
+
* ResolveContext.page 双双可见:组合组件靠它读当前页 id 与输入分支;attempt 叶子组件靠它
|
|
40
|
+
* 取省略 input 时的缺省 evidence。
|
|
41
|
+
*/
|
|
42
|
+
export type PageContext = ScopePageContext | AttemptPageContext;
|
|
43
|
+
|
|
19
44
|
// ───────────────────────── 节点形状 ─────────────────────────
|
|
20
45
|
|
|
21
46
|
/** 标准 jsx-runtime 元素形状;text 宿主只认 type / props,不管 $$typeof。 */
|
|
@@ -67,8 +92,12 @@ export interface TextContext {
|
|
|
67
92
|
locale: ReportLocale;
|
|
68
93
|
/** 容器组件渲染 children 用,宽度显式传递。 */
|
|
69
94
|
render(node: ReportNode, width?: number): string;
|
|
70
|
-
/**
|
|
71
|
-
|
|
95
|
+
/**
|
|
96
|
+
* 下钻命令,通 attempt-input page:`niceeval show @<locator>`。当前报告没有声明
|
|
97
|
+
* attempt-input page 时不存在——宿主不生成假命令,locator 只是文本(architecture.md
|
|
98
|
+
* 「Attempt 详情是一张参数化 page」)。
|
|
99
|
+
*/
|
|
100
|
+
attemptCommand?(locator: AttemptLocator): string;
|
|
72
101
|
/**
|
|
73
102
|
* 组索引一类「按实验收窄」命令的生成;宿主注入以携带完整上下文(--results / --report /
|
|
74
103
|
* --page 与位置参数),默认 `niceeval show --exp <id>`。非契约字段,官方组件内部用。
|
|
@@ -77,8 +106,12 @@ export interface TextContext {
|
|
|
77
106
|
}
|
|
78
107
|
|
|
79
108
|
export interface WebContext {
|
|
80
|
-
/**
|
|
81
|
-
|
|
109
|
+
/**
|
|
110
|
+
* attempt-input page 深链,同 view 的 attempt 路由(`#/attempt/@<locator>`,单段、不透明)。
|
|
111
|
+
* 当前报告没有声明 attempt-input page 时不存在——宿主不生成空 href 或假链接,locator 只是
|
|
112
|
+
* 文本(architecture.md「Attempt 详情是一张参数化 page」)。
|
|
113
|
+
*/
|
|
114
|
+
attemptHref?(locator: AttemptLocator): string;
|
|
82
115
|
/** chrome 文案的 locale;官方组件渲染面经上下文读取,宿主外默认 "en"。 */
|
|
83
116
|
locale: ReportLocale;
|
|
84
117
|
}
|
|
@@ -86,6 +119,8 @@ export interface WebContext {
|
|
|
86
119
|
/** 双面组件解析面的上下文:宿主注入的数据来源;props 显式给出 input 时以 props 为准。 */
|
|
87
120
|
export interface ResolveContext {
|
|
88
121
|
input: ReportInput;
|
|
122
|
+
/** 当前页判别;attempt 叶子组件省略 input 时从这里的 attempt 分支取缺省 evidence。 */
|
|
123
|
+
page: PageContext;
|
|
89
124
|
}
|
|
90
125
|
|
|
91
126
|
/** 组合组件的上下文:宿主 Scope、结果根完整读取面与规范化后的报告声明。 */
|
|
@@ -96,6 +131,8 @@ export interface ComposeContext {
|
|
|
96
131
|
results: Results;
|
|
97
132
|
/** 规范化后的报告声明,只读(docs/feature/reports/library/layout.md「自定义组件」)。 */
|
|
98
133
|
report: ReportMeta;
|
|
134
|
+
/** 当前页判别:scope 分支只有 id;attempt 分支带 locator + evidence。 */
|
|
135
|
+
page: PageContext;
|
|
99
136
|
}
|
|
100
137
|
|
|
101
138
|
export interface ComponentFaces<P, R = P> {
|
|
@@ -125,9 +162,9 @@ export type ReportComponent<P> = ((props: P) => ReactNode) & {
|
|
|
125
162
|
};
|
|
126
163
|
|
|
127
164
|
// web 面的环境上下文:web 宿主渲染前设好;宿主之外(组件直接嵌进用户 React 应用)
|
|
128
|
-
//
|
|
165
|
+
// 用默认值——没有 attemptHref,组件显式传 prop 才产生外部链接(architecture.md
|
|
166
|
+
// 「Attempt 详情是一张参数化 page」:没有 target 时 locator 只是文本,不生成假 href)。
|
|
129
167
|
const DEFAULT_WEB_CONTEXT: WebContext = {
|
|
130
|
-
attemptHref: (locator) => `#/attempt/${locator}`,
|
|
131
168
|
locale: DEFAULT_REPORT_LOCALE,
|
|
132
169
|
};
|
|
133
170
|
let activeWebContext: WebContext | null = null;
|
|
@@ -143,11 +180,6 @@ export function runWithWebContext<T>(ctx: WebContext, fn: () => T): T {
|
|
|
143
180
|
}
|
|
144
181
|
}
|
|
145
182
|
|
|
146
|
-
/** 官方组件的装配用:宿主上下文激活时才把 ctx.attemptHref 当默认下钻。 */
|
|
147
|
-
export function isHostWebContextActive(): boolean {
|
|
148
|
-
return activeWebContext !== null;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
183
|
/** 函数形态:组合组件,只装配已有组件,可以异步;ctx 携带 scope / results / report。 */
|
|
152
184
|
export function defineComponent<P>(
|
|
153
185
|
compose: (props: P, context: ComposeContext) => ReportNode | Promise<ReportNode>,
|
|
@@ -269,11 +301,13 @@ export class ResolveMemo {
|
|
|
269
301
|
}
|
|
270
302
|
}
|
|
271
303
|
|
|
272
|
-
/** resolveReportTree 的环境:宿主注入的 Scope / 读取面 /
|
|
304
|
+
/** resolveReportTree 的环境:宿主注入的 Scope / 读取面 / 规范化声明 / 当前页判别。 */
|
|
273
305
|
export interface ResolveEnv {
|
|
274
306
|
scope: Scope;
|
|
275
307
|
results: Results;
|
|
276
308
|
report: ReportMeta;
|
|
309
|
+
/** 当前渲染的页:scope 分支只有 id;attempt 分支带 locator + evidence。 */
|
|
310
|
+
page: PageContext;
|
|
277
311
|
/** 一次页渲染一份;跨页共享缓存时由宿主显式传同一实例。 */
|
|
278
312
|
memo?: ResolveMemo;
|
|
279
313
|
}
|
|
@@ -323,7 +357,7 @@ function bareTextError(value: string | number, path: string[]): Error {
|
|
|
323
357
|
*/
|
|
324
358
|
export async function resolveReportTree(node: ReportNode, env: ResolveEnv): Promise<ReportNode> {
|
|
325
359
|
const memo = env.memo ?? new ResolveMemo();
|
|
326
|
-
const composeCtx: ComposeContext = { scope: env.scope, results: env.results, report: env.report };
|
|
360
|
+
const composeCtx: ComposeContext = { scope: env.scope, results: env.results, report: env.report, page: env.page };
|
|
327
361
|
return resolveNode(node, { memo, composeCtx }, []);
|
|
328
362
|
}
|
|
329
363
|
|
|
@@ -367,6 +401,7 @@ async function resolveNode(node: ReportNode | string | number, state: ResolveSta
|
|
|
367
401
|
const input = ((props as { input?: unknown }).input as ReportInput | undefined) ?? state.composeCtx.scope;
|
|
368
402
|
const ctx: InternalResolveContext = {
|
|
369
403
|
input,
|
|
404
|
+
page: state.composeCtx.page,
|
|
370
405
|
memoFetch: <T,>(dataFn: unknown, dataInput: unknown, options: unknown, compute: () => Promise<T>) =>
|
|
371
406
|
state.memo.fetch(dataFn, dataInput, options, compute) as Promise<T>,
|
|
372
407
|
};
|
|
@@ -528,9 +563,10 @@ function shellQuote(value: string): string {
|
|
|
528
563
|
export function createTextContext(options?: TextRenderOptions): TextContext {
|
|
529
564
|
const width = Math.max(20, options?.width ?? 80);
|
|
530
565
|
const locale = options?.locale ?? DEFAULT_REPORT_LOCALE;
|
|
531
|
-
//
|
|
532
|
-
//
|
|
533
|
-
|
|
566
|
+
// 没有默认值:当前报告没有声明 attempt-input page 时不存在下钻命令——宿主(report.ts /
|
|
567
|
+
// web.ts 的渲染入口)据规范化 definition 是否有 attempt page 决定要不要注入生成器,
|
|
568
|
+
// 这里只透传调用方给的值(architecture.md「Attempt 详情是一张参数化 page」)。
|
|
569
|
+
const attemptCommand = options?.attemptCommand;
|
|
534
570
|
const experimentCommand =
|
|
535
571
|
options?.experimentCommand ?? ((prefix: string) => `niceeval show --exp ${shellQuote(prefix)}`);
|
|
536
572
|
const make = (w: number): TextContext => ({
|