niceeval 0.9.0 → 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 +15 -7
- 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} +44 -12
- package/dist/report/{tree.js → definition/tree.js} +10 -12
- 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 +12 -2
- 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 +15 -1
- package/dist/shared/aggregate.js +32 -1
- 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 +43 -19
- 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 +11 -5
- 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 +59 -50
- 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 +77 -64
- package/src/context/types.ts +21 -21
- package/src/define.ts +13 -0
- package/src/i18n/en.ts +30 -15
- package/src/i18n/zh-CN.ts +30 -15
- 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 +136 -112
- 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} +58 -22
- 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 +54 -3
- package/src/results/select.ts +30 -6
- 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 +30 -1
- 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 +58 -22
- package/src/show/render.ts +16 -240
- package/src/show/show.test.ts +128 -35
- package/src/view/app/App.test.tsx +8 -7
- package/src/view/app/App.tsx +135 -51
- 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 +122 -89
- package/src/view/index.ts +3 -13
- package/src/view/server.ts +36 -6
- 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 +18 -806
- package/src/view/view-report.test.ts +182 -34
- 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
|
@@ -35,7 +35,7 @@ async function seedSnapshot(root: string, experimentId: string, evalId: string):
|
|
|
35
35
|
{ type: "message", role: "user", text: "hi", loc: { file: "evals/a.eval.ts", line: 3 } },
|
|
36
36
|
{ type: "message", role: "assistant", text: "hello there" },
|
|
37
37
|
],
|
|
38
|
-
trace: [{ name: "turn", kind: "turn"
|
|
38
|
+
trace: [{ traceId: "t1", spanId: "s1", name: "turn", kind: "turn", startMs: 0, endMs: 100 }],
|
|
39
39
|
diff: [{ window: "s1/t1", changes: { "a.txt": { status: "added", after: "1" } } }] as never,
|
|
40
40
|
},
|
|
41
41
|
);
|
|
@@ -114,4 +114,27 @@ describe("站点管线奇偶:server 与 --out 是同一份产物", () => {
|
|
|
114
114
|
const direct = await (await fetch(new URL(`/${eventsPath}`, server.url))).text();
|
|
115
115
|
expect(await res.text()).toBe(direct);
|
|
116
116
|
});
|
|
117
|
+
|
|
118
|
+
it("本地宿主的 attempt 详情路由越过 --exp 收窄,对完整结果根解析(cases.md 第 198/220 行,与 show @<locator> 同一套「各自结果根语义寻址」)", async () => {
|
|
119
|
+
const root = await makeDir("niceeval-parity-unnarrowed-");
|
|
120
|
+
await seedSnapshot(root, "exp-a", "q1");
|
|
121
|
+
await seedSnapshot(root, "exp-b", "q2");
|
|
122
|
+
server = await startViewServer({ input: root, scan: { experiment: "exp-a" } });
|
|
123
|
+
|
|
124
|
+
const full = await planSite(root); // 不收窄,拿到两个实验各自的 attempt 路径
|
|
125
|
+
const attemptPaths = [...full.files.keys()].filter((p) => p.startsWith("attempt/"));
|
|
126
|
+
expect(attemptPaths).toHaveLength(2);
|
|
127
|
+
|
|
128
|
+
// 收窄后的 plan 只剩 exp-a 的那份(row 205 已覆盖导出侧的同一断言;这里确认 plan 本身也收窄)。
|
|
129
|
+
const narrowed = await planSite(root, { experiment: "exp-a" });
|
|
130
|
+
const narrowedPaths = new Set(narrowed.files.keys());
|
|
131
|
+
const outsideScopePath = attemptPaths.find((p) => !narrowedPaths.has(p))!;
|
|
132
|
+
expect(outsideScopePath).toBeTruthy();
|
|
133
|
+
|
|
134
|
+
// 但本地 server 仍能直接打开它:路由越过收窄,对完整结果根解析。
|
|
135
|
+
const res = await fetch(new URL(`/${outsideScopePath}`, server.url));
|
|
136
|
+
expect(res.status).toBe(200);
|
|
137
|
+
const body = await res.text();
|
|
138
|
+
expect(body).toContain("q2"); // exp-b 的证据内容真的解析出来了,不是空白/占位
|
|
139
|
+
});
|
|
117
140
|
});
|
package/src/view/site.ts
CHANGED
|
@@ -8,14 +8,22 @@ import { existsSync } from "node:fs";
|
|
|
8
8
|
import { createHash } from "node:crypto";
|
|
9
9
|
import { dirname, join, resolve } from "node:path";
|
|
10
10
|
import { loadViewScan, type ResolvedHeadTag, type ViewScan, type ViewScanOptions } from "./data.ts";
|
|
11
|
-
import { localizeText } from "../
|
|
11
|
+
import { localizeText } from "../report/runtime/host.ts";
|
|
12
|
+
import type { AttemptHandle } from "../results/index.ts";
|
|
13
|
+
import type { AttemptLocator } from "../results/locator.ts";
|
|
12
14
|
|
|
13
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* 站点产物清单里的一个文件:现算内容(content)、指向结果根内的原文件(file),或延迟到
|
|
17
|
+
* 真正被请求 / 导出时才求值的产出器(lazy)。lazy 专为 `attempt/<locator>.html` 准备——
|
|
18
|
+
* 每个可达 locator 一份,数量可能很大,不能像 index.html 那样在建清单时就全部渲染
|
|
19
|
+
* (architecture.md「管线以 page 实例为单位执行」:本地 server 按请求求值并缓存进当前
|
|
20
|
+
* plan,`writeSite` 在写任何文件前对全部产出器求值一次)。
|
|
21
|
+
*/
|
|
14
22
|
export interface SiteFile {
|
|
15
23
|
/** 站点相对路径(posix),如 `index.html`、`artifact/<base>/events.json`。 */
|
|
16
24
|
path: string;
|
|
17
25
|
contentType: string;
|
|
18
|
-
source: { kind: "content"; body: string } | { kind: "file"; abs: string };
|
|
26
|
+
source: { kind: "content"; body: string } | { kind: "file"; abs: string } | { kind: "lazy"; produce: () => Promise<string> };
|
|
19
27
|
}
|
|
20
28
|
|
|
21
29
|
export interface SitePlan {
|
|
@@ -63,15 +71,51 @@ export async function planSite(input?: string, opts: ViewScanOptions = {}): Prom
|
|
|
63
71
|
files.set(path, { path, contentType: JSON_TYPE, source: { kind: "content", body: JSON.stringify(sources ?? []) } });
|
|
64
72
|
}
|
|
65
73
|
}
|
|
74
|
+
|
|
75
|
+
// attempt/<locator>.html:报告声明了 attempt-input page 时才出现,收窄后有效根内每个可达
|
|
76
|
+
// locator 各一份(view.md「静态导出」)。头资产的相对路径要从 attempt/ 子目录回退一层,
|
|
77
|
+
// 因此单独物化一份 `../` 前缀版本(与 index.html 的根相对版本共用同一份 files 内容寻址,
|
|
78
|
+
// 同一份资产只按内容哈希写一次)。每份文档的 IO/resolve 延迟到真正被请求或导出时才发生——
|
|
79
|
+
// 可达 locator 数量可能很大,不能像 index.html 一样在建清单时就全部渲染
|
|
80
|
+
// (architecture.md「管线以 page 实例为单位执行」)。
|
|
81
|
+
if (scan.attemptPages) {
|
|
82
|
+
const { locators, render } = scan.attemptPages;
|
|
83
|
+
const nestedHeadHtml = await materializeHeadAssets(scan.shellAssets.head, files, "../");
|
|
84
|
+
for (const [locator, handle] of locators) {
|
|
85
|
+
const path = `attempt/${locator}.html`;
|
|
86
|
+
files.set(path, {
|
|
87
|
+
path,
|
|
88
|
+
contentType: HTML_TYPE,
|
|
89
|
+
source: { kind: "lazy", produce: () => renderAttemptDocument(scan, locator, handle, render, nestedHeadHtml) },
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
66
94
|
return { files, scan };
|
|
67
95
|
}
|
|
68
96
|
|
|
69
|
-
/**
|
|
97
|
+
/**
|
|
98
|
+
* 把站点产物清单写盘(`--out`)。输入本身已是导出布局(对上次导出的目录重新生成)时原文件不自拷。
|
|
99
|
+
* 先对全部 lazy 产出器求值(任一份 attempt page resolve 失败就在这一步整体抛出,不写入任何
|
|
100
|
+
* 文件——architecture.md「写 writeSite 的整体失败语义」:静态导出不留半套目录),求值期间
|
|
101
|
+
* 头资产可能按内容哈希追加注册进 plan.files(见 planSite 的 `../` 前缀变体),因此写盘前
|
|
102
|
+
* 重新遍历一次清单,不用求值前的快照。
|
|
103
|
+
*/
|
|
70
104
|
export async function writeSite(plan: SitePlan, outDir: string): Promise<void> {
|
|
105
|
+
const lazyBodies = new Map<string, string>();
|
|
106
|
+
await Promise.all(
|
|
107
|
+
[...plan.files.values()]
|
|
108
|
+
.filter((file): file is SiteFile & { source: { kind: "lazy"; produce: () => Promise<string> } } => file.source.kind === "lazy")
|
|
109
|
+
.map(async (file) => {
|
|
110
|
+
lazyBodies.set(file.path, await file.source.produce());
|
|
111
|
+
}),
|
|
112
|
+
);
|
|
71
113
|
for (const file of plan.files.values()) {
|
|
72
114
|
const dest = join(outDir, file.path);
|
|
73
115
|
await mkdir(dirname(dest), { recursive: true });
|
|
74
|
-
if (file.source.kind === "
|
|
116
|
+
if (file.source.kind === "lazy") {
|
|
117
|
+
await writeFile(dest, lazyBodies.get(file.path)!, "utf-8");
|
|
118
|
+
} else if (file.source.kind === "content") {
|
|
75
119
|
await writeFile(dest, file.source.body, "utf-8");
|
|
76
120
|
} else if (resolve(file.source.abs) !== resolve(dest)) {
|
|
77
121
|
await copyFile(file.source.abs, dest);
|
|
@@ -79,9 +123,14 @@ export async function writeSite(plan: SitePlan, outDir: string): Promise<void> {
|
|
|
79
123
|
}
|
|
80
124
|
}
|
|
81
125
|
|
|
82
|
-
/**
|
|
126
|
+
/**
|
|
127
|
+
* 取清单中一个文件的字节(server 响应体与写盘内容同源;file 类缺失时返回 undefined,由宿主 404)。
|
|
128
|
+
* lazy 类每次调用都重新求值(不在这里缓存)——server.ts 按「同一路径同一 plan 生命周期内
|
|
129
|
+
* 不重复计算」的语义自行把求值结果写回 plan.files,这里保持纯函数,不持有 plan 状态。
|
|
130
|
+
*/
|
|
83
131
|
export async function readSiteFile(file: SiteFile): Promise<string | Buffer | undefined> {
|
|
84
132
|
if (file.source.kind === "content") return file.source.body;
|
|
133
|
+
if (file.source.kind === "lazy") return file.source.produce();
|
|
85
134
|
try {
|
|
86
135
|
// 原字节读取:assets/ 里的 head 资产可以是二进制(favicon、字体),不能按 utf-8 解码。
|
|
87
136
|
return await readFile(file.source.abs);
|
|
@@ -121,11 +170,14 @@ function renderHeadTagHtml(tag: ResolvedHeadTag, attrs: Record<string, string |
|
|
|
121
170
|
}
|
|
122
171
|
|
|
123
172
|
/**
|
|
124
|
-
* head 标签落成 HTML,本地 src/href 资产进站点清单:`assets/<sha256><ext
|
|
125
|
-
* source 指向原文件(写盘 copyFile、server
|
|
126
|
-
*
|
|
173
|
+
* head 标签落成 HTML,本地 src/href 资产进站点清单:`assets/<sha256><ext>`(与调用方无关,
|
|
174
|
+
* 同内容同扩展名跨全部文档去重),source 指向原文件(写盘 copyFile、server 原字节下发都
|
|
175
|
+
* 二进制安全)。标签属性回填的路径按 `prefix` 相对当前文档:index.html 在站点根,
|
|
176
|
+
* `prefix` 为空;`attempt/<locator>.html` 低一级,`prefix` 是 `"../"`(view.md「静态导出」
|
|
177
|
+
* 「所有 HTML 都按自身相对位置生成 assets/ / artifact/ 引用」)。外链(http(s)://)原样透传,
|
|
178
|
+
* 不进 assets/,prefix 对它们不生效。
|
|
127
179
|
*/
|
|
128
|
-
async function materializeHeadAssets(head: ResolvedHeadTag[], files: Map<string, SiteFile
|
|
180
|
+
async function materializeHeadAssets(head: ResolvedHeadTag[], files: Map<string, SiteFile>, prefix = ""): Promise<string> {
|
|
129
181
|
const rendered: string[] = [];
|
|
130
182
|
for (const tag of head) {
|
|
131
183
|
const attrs = { ...tag.attrs };
|
|
@@ -138,7 +190,7 @@ async function materializeHeadAssets(head: ResolvedHeadTag[], files: Map<string,
|
|
|
138
190
|
contentType: ASSET_CONTENT_TYPES[tag.localAsset.ext.toLowerCase()] ?? "application/octet-stream",
|
|
139
191
|
source: { kind: "file", abs: tag.localAsset.abs },
|
|
140
192
|
});
|
|
141
|
-
attrs[tag.localAsset.attr] = path
|
|
193
|
+
attrs[tag.localAsset.attr] = `${prefix}${path}`;
|
|
142
194
|
}
|
|
143
195
|
rendered.push(renderHeadTagHtml(tag, attrs));
|
|
144
196
|
}
|
|
@@ -168,8 +220,8 @@ export async function renderHtml(scan: ViewScan, headHtml = ""): Promise<string>
|
|
|
168
220
|
const styles = await readViewAsset("client-dist/app.css");
|
|
169
221
|
const app = await readViewAsset("client-dist/app.js");
|
|
170
222
|
const [reportStyles, reportEnhance] = await Promise.all([
|
|
171
|
-
readFile(new URL("../report/
|
|
172
|
-
readFile(new URL("../report/
|
|
223
|
+
readFile(new URL("../report/assets/styles.css", import.meta.url), "utf-8"),
|
|
224
|
+
readFile(new URL("../report/assets/enhance.js", import.meta.url), "utf-8"),
|
|
173
225
|
]);
|
|
174
226
|
|
|
175
227
|
const shellStyles = scan.shellAssets.styles.map((css) => `\n<style>\n${css}\n</style>`).join("");
|
|
@@ -187,10 +239,7 @@ export async function renderHtml(scan: ViewScan, headHtml = ""): Promise<string>
|
|
|
187
239
|
const title = localizeText(scan.viewData.report?.title, "en") ?? "Eval Results";
|
|
188
240
|
|
|
189
241
|
return template
|
|
190
|
-
.replace(
|
|
191
|
-
/<title>[^<]*<\/title>/,
|
|
192
|
-
() => `<title>${title.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")}</title>`,
|
|
193
|
-
)
|
|
242
|
+
.replace(/<title>[^<]*<\/title>/, () => `<title>${escapeText(title)}</title>`)
|
|
194
243
|
.replace(
|
|
195
244
|
TEMPLATE_PLACEHOLDERS.styles,
|
|
196
245
|
() =>
|
|
@@ -204,6 +253,84 @@ export async function renderHtml(scan: ViewScan, headHtml = ""): Promise<string>
|
|
|
204
253
|
.replace("</body>", () => `${shellScripts}</body>`);
|
|
205
254
|
}
|
|
206
255
|
|
|
256
|
+
function escapeText(value: string): string {
|
|
257
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* localStorage 里存的界面语言优先,否则按 navigator 语言猜(与 app/i18n.ts 的 detectLocale()
|
|
262
|
+
* 同一套判定规则,故意在这里用一份独立的极小 vanilla 版本——standalone 文档不拉入
|
|
263
|
+
* react/react-dom,不需要为了一次语言判定背上整个 SPA 打包产物)。
|
|
264
|
+
*/
|
|
265
|
+
const ATTEMPT_LOCALE_SWAP_SCRIPT = `(function(){try{var s=localStorage.getItem("niceeval:view:locale");var l=s==="zh-CN"||s==="en"?s:((navigator.languages||[navigator.language]).some(function(v){return /^zh/i.test(String(v||"").trim())})?"zh-CN":"en");if(l==="zh-CN"){var en=document.querySelector('[data-nre-locale="en"]');var zh=document.querySelector('[data-nre-locale="zh-CN"]');if(en)en.hidden=true;if(zh){zh.hidden=false;}document.documentElement.lang="zh-CN";}}catch(e){}})();`;
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* 一个 locator 的独立 attempt 文档:与 index.html 是「文档」而非「App」——en 内容直接可见
|
|
269
|
+
* (无 JavaScript 时浏览器正常渲染这个 div),zh-CN 变体带 `hidden` 属性(同样不需要 JS 就能
|
|
270
|
+
* 被浏览器正确隐藏,只是不显示,不是不存在),一段极小内联脚本按检测到的界面语言在两者间切换
|
|
271
|
+
* (docs/feature/reports/view.md「静态导出」:基线链接直接指向这份文档,保证无 JavaScript 也能
|
|
272
|
+
* 读完整详情)。不复用 renderHtml/template.html 的 SPA 外壳——那条路径的 #root 要等 React
|
|
273
|
+
* 挂载才有内容,不满足这里「无 JS 仍完整可读」的要求。增强脚本(index.html 里的渐进增强,
|
|
274
|
+
* 拦截 locator 链接后 fetch 这份文档、按同一 `[data-nre-locale]` 选择器取出对应语言的内容
|
|
275
|
+
* 塞进 dialog)与这里的选择器保持同一套约定,不维护第二份提取逻辑。
|
|
276
|
+
*/
|
|
277
|
+
async function renderAttemptDocument(
|
|
278
|
+
scan: ViewScan,
|
|
279
|
+
locator: AttemptLocator,
|
|
280
|
+
handle: AttemptHandle,
|
|
281
|
+
render: (locator: AttemptLocator, handle: AttemptHandle) => Promise<{ en: string; "zh-CN": string }>,
|
|
282
|
+
headHtml: string,
|
|
283
|
+
): Promise<string> {
|
|
284
|
+
const content = await render(locator, handle);
|
|
285
|
+
const [reportStyles, reportEnhance] = await Promise.all([
|
|
286
|
+
readFile(new URL("../report/assets/styles.css", import.meta.url), "utf-8"),
|
|
287
|
+
readFile(new URL("../report/assets/enhance.js", import.meta.url), "utf-8"),
|
|
288
|
+
]);
|
|
289
|
+
const shellStyles = scan.shellAssets.styles.map((css) => `\n<style>\n${css}\n</style>`).join("");
|
|
290
|
+
const shellScripts = scan.shellAssets.scripts.map((js) => `<script>\n${js}\n</script>\n`).join("");
|
|
291
|
+
const title = `${handle.evalId} · ${handle.experimentId}`;
|
|
292
|
+
|
|
293
|
+
return [
|
|
294
|
+
"<!doctype html>",
|
|
295
|
+
'<html lang="en">',
|
|
296
|
+
"<head>",
|
|
297
|
+
'<meta charset="utf-8">',
|
|
298
|
+
'<meta name="viewport" content="width=device-width, initial-scale=1">',
|
|
299
|
+
`<title>${escapeText(title)}</title>`,
|
|
300
|
+
`<style>\n${reportStyles}\n</style>`,
|
|
301
|
+
`<script>\n${reportEnhance}\n</script>`,
|
|
302
|
+
shellStyles,
|
|
303
|
+
headHtml ? `\n${headHtml}` : "",
|
|
304
|
+
"</head>",
|
|
305
|
+
"<body>",
|
|
306
|
+
`<div data-nre-locale="en">${content.en}</div>`,
|
|
307
|
+
`<div data-nre-locale="zh-CN" hidden>${content["zh-CN"]}</div>`,
|
|
308
|
+
`<script>${ATTEMPT_LOCALE_SWAP_SCRIPT}</script>`,
|
|
309
|
+
shellScripts,
|
|
310
|
+
"</body>",
|
|
311
|
+
"</html>",
|
|
312
|
+
].join("\n");
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* 独立渲染一个 locator 的 attempt 文档,不依赖已建好的站点清单——供本地 server 的「越过收窄」
|
|
317
|
+
* 回退路由使用(docs/engineering/unit-tests/reports/cases.md 第 198/220 行:本地宿主的 attempt
|
|
318
|
+
* 详情路由对完整结果根解析,不受 `--exp`/eval 前缀收窄限制,与 `show @<locator>` 同一套「各自
|
|
319
|
+
* 结果根语义寻址」)。头资产的物化路径由内容哈希确定性算出,这里用一个用后即弃的 Map 重新
|
|
320
|
+
* 算一遍就够——真正的文件已经由主 plan(`planSite` 对 index.html 的物化)写过一次,不需要
|
|
321
|
+
* 在这里重新登记。调用方(server.ts)负责先确认 `scan.attemptPages` 存在且这个 locator
|
|
322
|
+
* 在里面能查到对应的 handle。
|
|
323
|
+
*/
|
|
324
|
+
export async function renderStandaloneAttemptDocument(
|
|
325
|
+
scan: ViewScan,
|
|
326
|
+
locator: AttemptLocator,
|
|
327
|
+
handle: AttemptHandle,
|
|
328
|
+
): Promise<string> {
|
|
329
|
+
const throwaway = new Map<string, SiteFile>();
|
|
330
|
+
const headHtml = await materializeHeadAssets(scan.shellAssets.head, throwaway, "../");
|
|
331
|
+
return renderAttemptDocument(scan, locator, handle, scan.attemptPages!.render, headHtml);
|
|
332
|
+
}
|
|
333
|
+
|
|
207
334
|
async function readViewAsset(name: string): Promise<string> {
|
|
208
335
|
return readFile(new URL(name, import.meta.url), "utf-8");
|
|
209
336
|
}
|