niceeval 0.5.3 → 0.6.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 +55 -0
- package/dist/agents/types.d.ts +317 -0
- package/dist/context/types.d.ts +335 -0
- package/dist/i18n/core.d.ts +11 -0
- package/dist/i18n/en.d.ts +181 -0
- package/dist/i18n/index.d.ts +5 -0
- package/dist/i18n/zh-CN.d.ts +183 -0
- package/dist/o11y/execution-tree.d.ts +103 -0
- package/dist/o11y/otlp/parse.d.ts +3 -0
- package/dist/o11y/otlp/receiver.d.ts +21 -0
- package/dist/o11y/otlp/select.d.ts +22 -0
- package/dist/o11y/otlp/turn-otel.d.ts +43 -0
- package/dist/o11y/types.d.ts +190 -0
- package/dist/report/aggregate.d.ts +57 -0
- package/dist/report/aggregate.js +212 -0
- package/dist/report/built-ins/cost-pass-rate-comparison.d.ts +1 -0
- package/dist/report/built-ins/cost-pass-rate-comparison.js +17 -0
- package/dist/report/built-ins/index.d.ts +1 -0
- package/dist/report/built-ins/index.js +2 -0
- package/dist/report/components.d.ts +178 -0
- package/dist/report/components.js +132 -0
- package/dist/report/compute.d.ts +106 -0
- package/dist/report/compute.js +618 -0
- package/dist/report/flag.d.ts +6 -0
- package/dist/report/flag.js +8 -0
- package/dist/report/format.d.ts +32 -0
- package/dist/report/format.js +126 -0
- package/dist/report/index.d.ts +19 -0
- package/dist/report/index.js +30 -0
- package/dist/report/load.d.ts +12 -0
- package/dist/report/load.js +56 -0
- package/dist/report/locale.d.ts +83 -0
- package/dist/report/locale.js +160 -0
- package/dist/report/metrics.d.ts +21 -0
- package/dist/report/metrics.js +115 -0
- package/dist/report/primitives.d.ts +64 -0
- package/dist/report/primitives.js +113 -0
- package/dist/report/react/AttemptList.d.ts +23 -0
- package/dist/report/react/AttemptList.js +20 -0
- package/dist/report/react/DeltaTable.d.ts +8 -0
- package/dist/report/react/DeltaTable.js +24 -0
- package/dist/report/react/EvalList.d.ts +10 -0
- package/dist/report/react/EvalList.js +0 -0
- package/dist/report/react/ExperimentList.d.ts +10 -0
- package/dist/report/react/ExperimentList.js +15 -0
- package/dist/report/react/GroupSummary.d.ts +8 -0
- package/dist/report/react/GroupSummary.js +8 -0
- package/dist/report/react/MetricBars.d.ts +10 -0
- package/dist/report/react/MetricBars.js +48 -0
- package/dist/report/react/MetricLine.d.ts +9 -0
- package/dist/report/react/MetricLine.js +68 -0
- package/dist/report/react/MetricMatrix.d.ts +10 -0
- package/dist/report/react/MetricMatrix.js +23 -0
- package/dist/report/react/MetricScatter.d.ts +9 -0
- package/dist/report/react/MetricScatter.js +100 -0
- package/dist/report/react/MetricTable.d.ts +11 -0
- package/dist/report/react/MetricTable.js +26 -0
- package/dist/report/react/RunOverview.d.ts +8 -0
- package/dist/report/react/RunOverview.js +12 -0
- package/dist/report/react/Scoreboard.d.ts +8 -0
- package/dist/report/react/Scoreboard.js +26 -0
- package/dist/report/react/cell.d.ts +9 -0
- package/dist/report/react/cell.js +9 -0
- package/dist/report/react/chart-math.d.ts +14 -0
- package/dist/report/react/chart-math.js +68 -0
- package/dist/report/react/colors.d.ts +14 -0
- package/dist/report/react/colors.js +45 -0
- package/dist/report/react/fixtures.d.ts +19 -0
- package/dist/report/react/fixtures.js +393 -0
- package/dist/report/react/format.d.ts +3 -0
- package/dist/report/react/format.js +7 -0
- package/dist/report/react/index.d.ts +6 -0
- package/dist/report/react/index.js +14 -0
- package/dist/report/report.d.ts +24 -0
- package/dist/report/report.js +49 -0
- package/dist/report/text/faces.d.ts +29 -0
- package/dist/report/text/faces.js +503 -0
- package/dist/report/text/layout.d.ts +75 -0
- package/dist/report/text/layout.js +173 -0
- package/dist/report/text/plot.d.ts +37 -0
- package/dist/report/text/plot.js +81 -0
- package/dist/report/text/table.d.ts +8 -0
- package/dist/report/text/table.js +86 -0
- package/dist/report/tree.d.ts +99 -0
- package/dist/report/tree.js +228 -0
- package/dist/report/types.d.ts +420 -0
- package/dist/report/types.js +4 -0
- package/dist/report/web.d.ts +15 -0
- package/dist/report/web.js +37 -0
- package/dist/results/annotated-source.d.ts +61 -0
- package/dist/results/attempt-evidence.d.ts +69 -0
- package/dist/results/attempt-source.d.ts +15 -0
- package/dist/results/locator.d.ts +75 -0
- package/dist/results/locator.js +0 -0
- package/dist/results/select.d.ts +45 -0
- package/dist/results/select.js +230 -0
- package/dist/results/source-hash.d.ts +9 -0
- package/dist/results/types.d.ts +204 -0
- package/dist/runner/eval-source.d.ts +22 -0
- package/dist/runner/fingerprint.d.ts +23 -0
- package/dist/runner/types.d.ts +332 -0
- package/dist/sandbox/docker-stream.d.ts +24 -0
- package/dist/sandbox/docker.d.ts +84 -0
- package/dist/sandbox/e2b.d.ts +31 -0
- package/dist/sandbox/errors.d.ts +4 -0
- package/dist/sandbox/local-files.d.ts +6 -0
- package/dist/sandbox/paths.d.ts +4 -0
- package/dist/sandbox/registry.d.ts +13 -0
- package/dist/sandbox/resolve.d.ts +40 -0
- package/dist/sandbox/retry.d.ts +10 -0
- package/dist/sandbox/shell.d.ts +11 -0
- package/dist/sandbox/source-files.d.ts +13 -0
- package/dist/sandbox/types.d.ts +203 -0
- package/dist/sandbox/vercel.d.ts +37 -0
- package/dist/scoring/types.d.ts +70 -0
- package/dist/shared/aggregate.d.ts +29 -0
- package/dist/shared/aggregate.js +55 -0
- package/dist/shared/types.d.ts +27 -0
- package/dist/shared/verdict.d.ts +27 -0
- package/dist/shared/verdict.js +34 -0
- package/dist/tty-line.d.ts +6 -0
- package/dist/types.d.ts +7 -0
- package/dist/util.d.ts +22 -0
- package/docs-site/zh/concepts/adapter.mdx +9 -4
- package/docs-site/zh/concepts/assert.mdx +8 -8
- package/docs-site/zh/concepts/evals.mdx +5 -5
- package/docs-site/zh/concepts/experiment.mdx +3 -1
- package/docs-site/zh/concepts/judge.mdx +9 -9
- package/docs-site/zh/concepts/overview.mdx +2 -2
- package/docs-site/zh/concepts/tier.mdx +6 -6
- package/docs-site/zh/example/claude-code-codex-plugin.mdx +9 -5
- package/docs-site/zh/example/claude-code-codex-skill.mdx +12 -7
- package/docs-site/zh/guides/agent-feedback-loop.mdx +235 -78
- package/docs-site/zh/guides/connect-otel.mdx +3 -3
- package/docs-site/zh/guides/connect-your-agent.mdx +2 -2
- package/docs-site/zh/guides/custom-reports.mdx +196 -36
- package/docs-site/zh/guides/experiments.mdx +7 -0
- package/docs-site/zh/guides/fixtures.mdx +1 -1
- package/docs-site/zh/guides/official-adapters.mdx +31 -9
- package/docs-site/zh/guides/publish-report.mdx +4 -4
- package/docs-site/zh/guides/report-components.mdx +194 -55
- package/docs-site/zh/guides/reporters.mdx +2 -2
- package/docs-site/zh/guides/results-data.mdx +35 -34
- package/docs-site/zh/guides/runner.mdx +2 -2
- package/docs-site/zh/guides/sandbox-agent.mdx +10 -5
- package/docs-site/zh/guides/sandbox-providers.mdx +102 -0
- package/docs-site/zh/guides/viewing-results.mdx +199 -79
- package/docs-site/zh/guides/write-experiment.mdx +23 -1
- package/docs-site/zh/guides/write-send.mdx +2 -2
- package/docs-site/zh/index.mdx +4 -3
- package/docs-site/zh/introduction.mdx +2 -1
- package/docs-site/zh/quickstart.mdx +5 -3
- package/docs-site/zh/reference/builtin-agents.mdx +38 -13
- package/docs-site/zh/reference/capabilities.mdx +1 -1
- package/docs-site/zh/reference/cli.mdx +36 -13
- package/docs-site/zh/reference/define-agent.mdx +24 -12
- package/docs-site/zh/reference/define-config.mdx +1 -1
- package/docs-site/zh/reference/define-eval.mdx +3 -3
- package/docs-site/zh/reference/events.mdx +7 -1
- package/docs-site/zh/reference/expect.mdx +3 -3
- package/package.json +10 -6
- package/src/agents/bub.ts +134 -43
- package/src/agents/claude-code.test.ts +152 -0
- package/src/agents/claude-code.ts +127 -13
- package/src/agents/codex.test.ts +192 -0
- package/src/agents/codex.ts +151 -12
- package/src/agents/index.ts +11 -3
- package/src/agents/manifest.ts +41 -0
- package/src/agents/plugin-config.test.ts +94 -0
- package/src/agents/shared.ts +33 -2
- package/src/agents/skills.test.ts +214 -0
- package/src/agents/skills.ts +304 -0
- package/src/agents/streaming.ts +5 -5
- package/src/agents/types.ts +62 -2
- package/src/cli.ts +74 -47
- package/src/context/context.test.ts +20 -2
- package/src/context/context.ts +3 -0
- package/src/context/control-flow.ts +1 -1
- package/src/context/session.test.ts +92 -1
- package/src/context/session.ts +26 -1
- package/src/context/types.ts +4 -4
- package/src/define.test.ts +82 -0
- package/src/define.ts +72 -11
- package/src/expect/index.ts +5 -5
- package/src/i18n/en.ts +36 -15
- package/src/i18n/zh-CN.ts +39 -21
- package/src/index.ts +1 -1
- package/src/o11y/execution-tree.test.ts +452 -0
- package/src/o11y/execution-tree.ts +367 -0
- package/src/o11y/otlp/receiver.ts +1 -1
- package/src/o11y/otlp/select.ts +7 -3
- package/src/o11y/parsers/claude-code.test.ts +175 -0
- package/src/o11y/parsers/claude-code.ts +32 -0
- package/src/o11y/types.ts +6 -1
- package/src/report/aggregate.ts +26 -20
- package/src/report/built-in-user-parity.test.tsx +643 -0
- package/src/report/built-ins/cost-pass-rate-comparison.tsx +23 -0
- package/src/report/built-ins/index.ts +2 -0
- package/src/report/components.tsx +223 -50
- package/src/report/compute.ts +358 -53
- package/src/report/dual-render.test.tsx +1125 -0
- package/src/report/flag.ts +1 -1
- package/src/report/format.ts +50 -2
- package/src/report/index.ts +48 -14
- package/src/report/load.ts +1 -1
- package/src/report/locale.ts +206 -0
- package/src/report/metrics.ts +39 -15
- package/src/report/primitives.tsx +100 -2
- package/src/report/react/AttemptList.tsx +115 -0
- package/src/report/react/DeltaTable.tsx +9 -6
- package/src/report/react/EvalList.tsx +0 -0
- package/src/report/react/ExperimentList.tsx +108 -0
- package/src/report/react/GroupSummary.tsx +66 -0
- package/src/report/react/MetricBars.tsx +24 -13
- package/src/report/react/MetricLine.tsx +21 -21
- package/src/report/react/MetricMatrix.tsx +8 -4
- package/src/report/react/MetricScatter.tsx +136 -96
- package/src/report/react/MetricTable.tsx +115 -15
- package/src/report/react/RunOverview.tsx +48 -26
- package/src/report/react/Scoreboard.tsx +15 -7
- package/src/report/react/cell.tsx +18 -9
- package/src/{view/app/lib/chart.ts → report/react/chart-math.ts} +2 -6
- package/src/report/react/colors.ts +24 -15
- package/src/report/react/enhance.js +129 -0
- package/src/report/react/fixtures.ts +163 -34
- package/src/report/react/format.ts +1 -1
- package/src/report/react/index.tsx +22 -6
- package/src/report/react/render.test.tsx +164 -31
- package/src/report/react/styles.css +405 -213
- package/src/report/report.test.ts +403 -94
- package/src/report/report.ts +29 -11
- package/src/report/text/faces.ts +303 -95
- package/src/report/text/layout.ts +76 -11
- package/src/report/text/table.ts +98 -0
- package/src/report/tree.ts +103 -20
- package/src/report/types.ts +196 -25
- package/src/report/web.ts +46 -19
- package/src/results/annotated-source.test.ts +146 -0
- package/src/results/annotated-source.ts +128 -0
- package/src/results/attempt-evidence.test.ts +158 -0
- package/src/results/attempt-evidence.ts +158 -0
- package/src/results/attempt-source.ts +48 -0
- package/src/results/copy.ts +154 -139
- package/src/results/format.ts +54 -47
- package/src/results/host-equivalence.test.ts +527 -0
- package/src/results/index.ts +56 -14
- package/src/results/locator.test.ts +198 -0
- package/src/results/locator.ts +0 -0
- package/src/results/open.ts +392 -175
- package/src/results/results.test.ts +943 -494
- package/src/results/select.ts +129 -23
- package/src/results/skipped-notice.ts +0 -0
- package/src/results/source-hash.ts +28 -0
- package/src/results/types.ts +98 -62
- package/src/results/writer.ts +304 -176
- package/src/runner/attempt.test.ts +170 -0
- package/src/runner/attempt.ts +97 -15
- package/src/runner/discover.test.ts +65 -0
- package/src/runner/discover.ts +6 -2
- package/src/runner/eval-source.test.ts +121 -0
- package/src/runner/eval-source.ts +45 -0
- package/src/runner/fingerprint.ts +54 -1
- package/src/runner/remote-sandbox.ts +1 -1
- package/src/runner/report.test.ts +6 -8
- package/src/runner/report.ts +5 -4
- package/src/runner/reporters/artifacts.ts +27 -41
- package/src/runner/reporters/braintrust.test.ts +3 -3
- package/src/runner/reporters/braintrust.ts +1 -1
- package/src/runner/reporters/console.ts +6 -6
- package/src/runner/reporters/json.ts +4 -4
- package/src/runner/reporters/live.test.ts +56 -0
- package/src/runner/reporters/live.ts +36 -10
- package/src/runner/reporters/quiet.test.ts +66 -0
- package/src/runner/reporters/quiet.ts +49 -0
- package/src/runner/reporters/shared.ts +5 -5
- package/src/runner/reporters/table.ts +17 -17
- package/src/runner/run.ts +61 -102
- package/src/runner/types.ts +43 -32
- package/src/sandbox/checkpoint.ts +1 -1
- package/src/sandbox/docker.ts +15 -2
- package/src/sandbox/e2b.ts +11 -5
- package/src/sandbox/errors.ts +13 -0
- package/src/sandbox/index.ts +3 -3
- package/src/sandbox/local-files.ts +1 -1
- package/src/sandbox/registry.ts +6 -5
- package/src/sandbox/resolve.ts +38 -23
- package/src/sandbox/retry.test.ts +68 -0
- package/src/sandbox/retry.ts +44 -0
- package/src/sandbox/types.ts +69 -28
- package/src/sandbox/vercel.ts +17 -3
- package/src/scoring/collector.ts +3 -3
- package/src/scoring/judge.ts +2 -2
- package/src/scoring/scoped.ts +13 -1
- package/src/scoring/types.ts +7 -7
- package/src/scoring/verdict.ts +4 -4
- package/src/shared/aggregate.ts +23 -3
- package/src/shared/types.ts +2 -2
- package/src/shared/{outcome.ts → verdict.ts} +15 -15
- package/src/show/compose.ts +12 -132
- package/src/show/index.ts +125 -94
- package/src/show/render.ts +660 -160
- package/src/show/show.test.ts +472 -253
- package/src/source-loc.ts +1 -1
- package/src/tty-line.ts +32 -0
- package/src/types.ts +2 -2
- package/src/util.test.ts +21 -1
- package/src/util.ts +5 -1
- package/src/view/app/App.tsx +33 -198
- package/src/view/app/components/AttemptModal.tsx +6 -6
- package/src/view/app/components/CodeView.tsx +2 -2
- package/src/view/app/components/CopyControls.tsx +32 -36
- package/src/view/app/components/SkippedRunsBanner.tsx +140 -0
- package/src/view/app/components/ui/badge.tsx +1 -1
- package/src/view/app/components/ui/dialog.tsx +2 -2
- package/src/view/app/i18n.ts +40 -31
- package/src/view/app/lib/artifact-url.ts +1 -1
- package/src/view/app/lib/attempt-route.test.ts +37 -47
- package/src/view/app/lib/attempt-route.ts +26 -26
- package/src/view/app/lib/rows.ts +9 -112
- package/src/view/app/lib/verdict.ts +25 -0
- package/src/view/app/main.tsx +9 -12
- package/src/view/app/pages/RunsPage.tsx +4 -4
- package/src/view/app/pages/TracesPage.tsx +3 -3
- package/src/view/app/shared.ts +0 -1
- package/src/view/app/types.ts +6 -51
- package/src/view/artifact-serving.test.ts +136 -0
- package/src/view/client-dist/app.css +1 -1
- package/src/view/client-dist/app.js +21 -21
- package/src/view/data.test.ts +214 -143
- package/src/view/data.ts +166 -120
- package/src/view/index.ts +23 -11
- package/src/view/server.ts +52 -17
- package/src/view/shared/types.ts +22 -31
- package/src/view/styles.css +117 -327
- package/src/view/view-report.test.ts +146 -98
- package/docs-site/zh/guides/sandbox-backends.mdx +0 -75
- package/src/report/default-report.tsx +0 -222
- package/src/report/dual-face.test.tsx +0 -527
- package/src/report/react/CaseList.tsx +0 -70
- package/src/view/app/components/CostScoreChart.tsx +0 -147
- package/src/view/app/components/ExperimentTable.tsx +0 -284
- package/src/view/app/components/GroupSelector.tsx +0 -61
- package/src/view/app/components/primitives.tsx +0 -43
- package/src/view/app/lib/outcome.ts +0 -82
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Sandbox provider:Docker、Vercel 与第三方"
|
|
3
|
+
sidebarTitle: "沙箱 provider"
|
|
4
|
+
description: "NiceEval 在 Docker 或 Vercel sandbox 中运行 coding agents。了解如何选择 provider、配置权限,并通过 warm pools 改善性能。"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Sandbox backend 是创建和管理隔离运行环境的基础设施。[NiceEval](https://niceeval.com/) 把它们包装成同一个 `Sandbox` 接口,所以 adapter 不需要知道当前用的是本地 Docker、Vercel micro-VM 还是第三方云服务。
|
|
8
|
+
|
|
9
|
+
## `Sandbox` 接口
|
|
10
|
+
|
|
11
|
+
Adapter 常用操作包括:
|
|
12
|
+
|
|
13
|
+
| 方法 | 用途 |
|
|
14
|
+
|---|---|
|
|
15
|
+
| `runCommand(cmd, args)` | 运行命令 |
|
|
16
|
+
| `runShell(script)` | 运行 shell 脚本 |
|
|
17
|
+
| `readFile(path)` | 读取文件 |
|
|
18
|
+
| `writeFiles(files)` | 写入一组文件 |
|
|
19
|
+
| `uploadFiles(files)` | 上传 workspace 或测试文件 |
|
|
20
|
+
| `workdir` | provider 真实工作目录;省略的 `cwd` / `targetDir` 都解析到这里 |
|
|
21
|
+
| `runCommand(..., { cwd })` | 单条命令临时切换工作目录;相对路径按 `workdir` 解析 |
|
|
22
|
+
| `stop()` | 销毁环境 |
|
|
23
|
+
|
|
24
|
+
## 选择 provider
|
|
25
|
+
|
|
26
|
+
选择 provider 只能写在代码里——没有对应的 CLI flag,[NiceEval](https://niceeval.com/) 也不会自动探测 provider。在 experiment 里设置 `sandbox` 字段(或者在 `niceeval.config.ts` 里设置作为项目级兜底),三选一:
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
// experiments/local.ts
|
|
30
|
+
import { defineExperiment } from "niceeval";
|
|
31
|
+
import { dockerSandbox } from "niceeval/sandbox";
|
|
32
|
+
|
|
33
|
+
export default defineExperiment({
|
|
34
|
+
agent: myCodingAgent,
|
|
35
|
+
model: "claude-sonnet-4-6",
|
|
36
|
+
sandbox: dockerSandbox(), // 或 vercelSandbox() / e2bSandbox()
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
如果 experiment 和 `niceeval.config.ts` 都没有设置 `sandbox`,[NiceEval](https://niceeval.com/) 在创建 sandbox 时会直接报错,而不会猜一个 provider。
|
|
41
|
+
|
|
42
|
+
三个内置 provider 的 SDK 不随 NiceEval 一起安装——用哪个就装哪个,避免把用不到的依赖(以及它们的原生构建脚本)带进你的项目:
|
|
43
|
+
|
|
44
|
+
| provider | 安装命令 |
|
|
45
|
+
|---|---|
|
|
46
|
+
| `dockerSandbox()` | `pnpm add dockerode @types/dockerode` |
|
|
47
|
+
| `vercelSandbox()` | `pnpm add @vercel/sandbox` |
|
|
48
|
+
| `e2bSandbox()` | `pnpm add e2b` |
|
|
49
|
+
|
|
50
|
+
漏装时不会静默失败:NiceEval 在创建 sandbox 的那一刻报错并直接给出上面的安装命令,例如 `Docker sandbox requires 'dockerode'. Install it with: pnpm add dockerode @types/dockerode`。
|
|
51
|
+
|
|
52
|
+
## 环境钩子
|
|
53
|
+
|
|
54
|
+
`dockerSandbox()` / `vercelSandbox()` / `e2bSandbox()` 返回的 spec 上有两个链式方法:`.setup(fn)` 和 `.teardown(fn)`。它们解决一类具体问题:**有些东西你本想直接做进 Docker 镜像或 E2B 模板,但它要按实验变化**——比如某个实验要装一个额外的二进制、预热一次模型、写一份 hook 文件,或者在多次 attempt 之间载入和回存状态。静态镜像做不到"每个实验装不同的东西",这两个钩子就是运行时补上的那一层。
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
export default defineExperiment({
|
|
58
|
+
agent: codexAgent({ mcpServers: [mempalMcp] }),
|
|
59
|
+
sandbox: e2bSandbox({ template: "fasteval-agents" })
|
|
60
|
+
.setup(mempalSetup("codex")) // 装二进制、预热、写 hook、载入状态
|
|
61
|
+
.teardown(mempalTeardown("codex")), // 回存状态
|
|
62
|
+
maxConcurrency: 1, // 载入和回存之间不能并发,声明串行
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
规则一览:
|
|
67
|
+
|
|
68
|
+
- **签名**:钩子函数和 Adapter 的 `setup` / `teardown` 一样是 `(sandbox, ctx)`;`setup` 可以返回一个清理函数。
|
|
69
|
+
- **不可变**:每次 `.setup()` / `.teardown()` 都返回一个新 spec,原对象不变,可以继续链。
|
|
70
|
+
- **多个钩子**:多个 `.setup()` 按追加顺序执行;多个 `.teardown()` 按追加的逆序执行。
|
|
71
|
+
- **执行时机**:`setup` 钩子在 sandbox 创建后、git 基线之前最先跑——它写下的文件会进基线,不会被算进 agent 产出的 diff;`teardown` 钩子在 Adapter 的 `teardown` 之后、sandbox 销毁之前最后跑——把状态回存到外部正好用这个时机。
|
|
72
|
+
- **失败语义**:`setup` 钩子抛错,这次 attempt 记为 `errored`(环境问题,不是 agent 做错题);`teardown` 钩子报错只记日志,不改变已产出的结果。
|
|
73
|
+
- **不带 sandbox 的 Agent**:`defineAgent` 构造的 Agent 没有 sandbox,`sandbox` 字段对它不生效,钩子自然不会跑。
|
|
74
|
+
|
|
75
|
+
钩子里可以用 `ctx.experimentId`(路径推导的实验 id)当状态隔离的键,比如不同实验各自维护一份跨 attempt 的缓存。跨 attempt 状态的载入和回存是你自己在钩子里写的普通代码——[NiceEval](https://niceeval.com/) 不提供状态存储;要保证同一实验的 attempt 不并发读写同一份状态,在 experiment 上声明 `maxConcurrency: 1`。
|
|
76
|
+
|
|
77
|
+
和另外两处 setup 的分工:Adapter 的 `setup` 管"怎么连被测 agent"(装 CLI、写鉴权配置);eval 里 `test(t)` 开头的代码管"这道题需要哪些起始文件";sandbox 的 `.setup()` 管"这次实验的环境里要多装什么"。三层各写各的,互相不知道对方的内容。MCP server、Skill、model 这些被测 agent 的配置仍然只从 Adapter 工厂参数进——环境钩子不做 Adapter 的事。
|
|
78
|
+
|
|
79
|
+
## Docker
|
|
80
|
+
|
|
81
|
+
Docker 适合本地开发和标准 CI。优点是简单、可控、无云端依赖;缺点是机器资源有限,冷启动和安装依赖可能较慢。
|
|
82
|
+
|
|
83
|
+
## Vercel Sandbox
|
|
84
|
+
|
|
85
|
+
Vercel Sandbox 适合需要云端隔离、更多资源或更稳定环境的任务。需要相应 token 或 OIDC 配置。
|
|
86
|
+
|
|
87
|
+
## 第三方 provider
|
|
88
|
+
|
|
89
|
+
只要实现 `Sandbox` 接口,就可以接入其他 sandbox provider。adapter 仍然只依赖接口,不依赖 provider 私有 API。
|
|
90
|
+
|
|
91
|
+
## 权限和 root
|
|
92
|
+
|
|
93
|
+
不同 provider 对 root 权限、网络、文件系统和进程生命周期的约束不同。编写 fixture 时尽量避免依赖宿主机环境,把依赖写进 `package.json` 或 fixture setup。
|
|
94
|
+
|
|
95
|
+
## 性能建议
|
|
96
|
+
|
|
97
|
+
- 减少 fixture 依赖体积。
|
|
98
|
+
- 使用缓存或预热机制。
|
|
99
|
+
- 控制 `sandboxConcurrency`,避免本地 Docker 资源耗尽。
|
|
100
|
+
- 把慢测试拆成必要的 gate 和可选的 soft 检查。
|
|
101
|
+
|
|
102
|
+
Warm pools 和复用属于 runner / scheduler 层面的能力,详见 [Runner](/zh/guides/runner)。
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "查看 NiceEval 结果并调试 agent 行为"
|
|
3
3
|
sidebarTitle: "查看结果"
|
|
4
|
-
description: "每次运行写入 .niceeval/
|
|
4
|
+
description: "每次运行写入 .niceeval/ 的结构化 artifact 有两扇门:niceeval show 在终端用 @<locator> 精确定位一次 Attempt,逐级下钻 Eval 源码、执行记录与 diff;niceeval view 在网页看同一份证据。"
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
每次运行后,[NiceEval](https://niceeval.com/)
|
|
7
|
+
每次运行后,[NiceEval](https://niceeval.com/) 都会把结构化结果写入该实验的**结果快照**目录 `.niceeval/<experiment>/<快照>/`。看结果有两扇门,读的是同一批 artifact:`niceeval show` 是终端读法,人和 coding agent 都能用;`niceeval view` 是网页读法,适合人浏览证据。两扇门共用判定公式与选结果规则:对每个 experiment 的每道 eval,取时间上最新的那份判定,同一个 experiment 跨多次运行拼出来。默认首页针对媒介不同:`show` 先给可下钻的 Attempt 表,`view` 先给图表分析;传入同一个 `--report` 文件时则共用报告组件与数据口径。
|
|
8
8
|
|
|
9
9
|
## 控制台输出
|
|
10
10
|
|
|
@@ -22,21 +22,23 @@ Failing:
|
|
|
22
22
|
→ niceeval show api-validation
|
|
23
23
|
|
|
24
24
|
Results: 2 passed, 1 failed, 0 errored, 0 skipped
|
|
25
|
-
Structured results: .niceeval/2026-07-09T10-00-00-000Z/
|
|
25
|
+
Structured results: .niceeval/compare_web-agent/2026-07-09T10-00-00-000Z-x1f2/
|
|
26
|
+
(snapshot.json + 每 attempt 的 result.json / events.json / trace.json / diff.json)
|
|
26
27
|
```
|
|
27
28
|
|
|
28
|
-
运行中每个 eval
|
|
29
|
+
运行中每个 eval 一条流式行,失败断言内联展开;运行结束的收尾块把失败集中重放一遍,每条自带下钻命令,末尾是本次实验的快照目录。这段输出怎么进「跑→读→修→再跑」的循环,见 [Agent 反馈闭环](/zh/guides/agent-feedback-loop)。
|
|
29
30
|
|
|
30
|
-
## `.niceeval/<
|
|
31
|
+
## `.niceeval/<experiment>/<快照>/`
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
落盘单位是**结果快照**(一个 experiment 的一次运行):实验目录在外层,快照目录(时间戳 + 随机后缀,独占创建)在实验目录下。典型结构:
|
|
33
34
|
|
|
34
35
|
```text
|
|
35
36
|
.niceeval/
|
|
36
|
-
└─
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
└─
|
|
37
|
+
└─ compare_web-agent/ # 实验目录:experimentId 清洗后的名字
|
|
38
|
+
└─ 2026-07-09T10-00-00-000Z-x1f2/ # 快照目录:时间戳 + 随机后缀
|
|
39
|
+
├─ snapshot.json # 快照元数据(开始时写,收尾补 completedAt)
|
|
40
|
+
└─ weather-tool/a0/ # 单个 eval attempt 的目录
|
|
41
|
+
├─ result.json # 判决、断言、用量 —— attempt 完成时一次写成
|
|
40
42
|
├─ events.json
|
|
41
43
|
├─ sources.json
|
|
42
44
|
├─ trace.json
|
|
@@ -46,50 +48,42 @@ Structured results: .niceeval/2026-07-09T10-00-00-000Z/summary.json
|
|
|
46
48
|
|
|
47
49
|
## `niceeval show`:终端下钻
|
|
48
50
|
|
|
49
|
-
`niceeval show`
|
|
51
|
+
`niceeval show` 的位置参数有两种形态:eval id 前缀选「看哪些 eval」,`@<locator>` 精确指名「看哪一次 Attempt」。flag 选「看哪个切面」:
|
|
50
52
|
|
|
51
53
|
```bash
|
|
52
|
-
niceeval show # 榜单:每个
|
|
53
|
-
niceeval show weather # 前缀过滤:weather/* 下每个 eval
|
|
54
|
-
niceeval show weather/brooklyn # 单个 eval:各 experiment 的 attempt
|
|
55
|
-
niceeval show
|
|
56
|
-
niceeval show
|
|
57
|
-
niceeval show
|
|
54
|
+
niceeval show # 榜单:每个 Attempt 的判定、eval、locator、短原因、耗时与成本
|
|
55
|
+
niceeval show weather # 前缀过滤:weather/* 下每个 eval 的判定
|
|
56
|
+
niceeval show weather/brooklyn # 单个 eval:各 experiment 的 attempt 行(含 @<locator>)、默认 attempt 的断言明细
|
|
57
|
+
niceeval show @1k2m9qrs # 精确到一次 Attempt:紧凑全景(断言/执行/diff 摘要 + 可用证据一览)
|
|
58
|
+
niceeval show @1k2m9qrs --eval # 该 Attempt 运行时保存的 Eval 源码,断言标回源码行
|
|
59
|
+
niceeval show @1k2m9qrs --execution # 该 Attempt 的消息、thinking、Skill 加载、工具调用,有 OTel 时补时间
|
|
60
|
+
niceeval show @1c3h6twx --diff # sandbox 里的文件改动
|
|
58
61
|
niceeval show weather/brooklyn --history # 跨 run 时间轴:抖动与回归拐点
|
|
59
62
|
```
|
|
60
63
|
|
|
61
|
-
|
|
64
|
+
`@<locator>` 是一次 Attempt 的持久、不透明身份,形如 `@1k2m9qrs`:由 `{experimentId, 快照时刻, evalId, attempt 序号}` 这个身份元组确定性派生,同一份落盘结果反复解析恒得到同一个值。它出现在 `niceeval show` 的紧凑索引里,直接复制粘贴就能定位到那一次运行。裸 `show` 的 locator 列只打印 `@<id>`,不追加判定或证据能力缩写;打开 Attempt 首页后,`available` 会列出实际可用的证据命令。
|
|
62
65
|
|
|
63
|
-
|
|
66
|
+
同一个实验多次跑会留下多份结果,不带 `@<locator>` 的默认视图只回答一个问题——「现在整体怎样」:每个 experiment × eval 取时间上最新的那份判定,同一个 experiment 跨多次运行拼出来。按前缀只重跑了部分 eval 时,其余 eval 的判定从更早的运行补齐,报告永远是全局最新,不会因为一次局部重跑变残缺。合成是有标注的:每份判定都带上它产生的时间,能看出报告是从哪几次运行拼出来的。合成结果可能混着不同版本的被测代码——所以收工判定以 `--force` 全量重跑为准,迭代途中的 `show` 负责快、收尾的全量跑负责真。
|
|
67
|
+
|
|
68
|
+
单个 eval 视图里,多 experiment、多 Attempt 时的断言明细块默认挑最新一次失败的 Attempt 展开;没有失败就挑最新一次。这只是一个默认展开的启发式,不是精确选择——需要精确看某一次 Attempt,复制那一行的 `@<locator>` 直接 `show` 它即可。`--experiment` 把 Selection 收窄到一个实验,`--run <目录>` 钉死看某一次历史 run,`--history` 看跨 run 趋势。不带 `--report` 时 `show` 渲染专用 Attempt 索引;`--report <文件>` 换成你自己的报告,同一个文件也能喂给 `view`。位置前缀、`--run`、`--experiment` 对 `--report` 同样生效;`--history` 与 `--report` 互斥。
|
|
64
69
|
|
|
65
70
|
`niceeval view` 的每个视图都有 CLI 对应物:
|
|
66
71
|
|
|
67
72
|
| `niceeval view` 里的视图 | 终端对应 |
|
|
68
73
|
| --- | --- |
|
|
69
|
-
|
|
|
70
|
-
| attempt
|
|
71
|
-
|
|
|
72
|
-
|
|
|
73
|
-
|
|
|
74
|
+
| 当前结果的同构 Attempt 表 | `niceeval show` |
|
|
75
|
+
| 该 eval 各 experiment 的判定行 + 默认 attempt 的断言明细 | `niceeval show <eval id>` |
|
|
76
|
+
| 单次 Attempt 的紧凑全景(断言、执行、diff 摘要与证据可用性) | `niceeval show @<locator>` |
|
|
77
|
+
| Eval 源码标注(断言标回源码行) | `niceeval show @<locator> --eval` |
|
|
78
|
+
| AI 对话、thinking、Skill 加载与工具调用(有 OTel 时补时间) | `niceeval show @<locator> --execution` |
|
|
79
|
+
| 文件改动 | `niceeval show @<locator> --diff` |
|
|
74
80
|
| 历史 run 列表 | `niceeval show <eval id> --history`;钉死某一次用 `--run <目录>` |
|
|
75
|
-
| 质量 × 成本散点图 | `niceeval show` 榜单的 pass / cost 列已含同一份数据;要图形化口径,用 `MetricScatter` 积木写[自定义报告](/zh/guides/custom-reports) |
|
|
76
|
-
|
|
77
|
-
### 榜单
|
|
78
|
-
|
|
79
|
-
```text
|
|
80
|
-
$ niceeval show
|
|
81
|
-
Current verdicts · 2 experiments · composed from 3 runs · latest 2026-07-09T10-00-00-000Z
|
|
82
81
|
|
|
83
|
-
|
|
84
|
-
compare/bub-gpt-5.4 13/15 87% $0.42 4m 12s
|
|
85
|
-
compare/codex-gpt-5.4 12/15 80% $0.51 5m 03s
|
|
82
|
+
### 默认 Attempt 索引
|
|
86
83
|
|
|
87
|
-
|
|
88
|
-
✗ weather/brooklyn compare/codex-gpt-5.4 gate calledTool("get_weather") 41s ago
|
|
89
|
-
✗ fixtures/button compare/bub-gpt-5.4 gate fileChanged("src/components/Button.tsx") 2h ago
|
|
90
|
-
```
|
|
84
|
+
不带 flag 的 `niceeval show` 先按 experiment 打印摘要,再用同构表列出每个 Attempt。列固定为 `STATUS / EVAL / ATTEMPT / RESULT / DURATION / COST`:四态判定同时给图标与完整单词,locator 只保留 `@<id>`,失败原因优先显示期望值/实际值或命令退出码。完整断言和 evidence 留在 `niceeval show @<locator>`。
|
|
91
85
|
|
|
92
|
-
|
|
86
|
+
只有一个 experiment 时直接显示它的表,不出现“至少两个实验才能比较”的无关空态。有两个及以上 experiment 时,前面增加紧凑比较表;成本 × 通过率散点留给 `niceeval view`。快照未完成、过旧或覆盖不全的 warning 位于索引前;自定义报告摆了 `RunOverview` 时,同一条 warning 也只显示一次。
|
|
93
87
|
|
|
94
88
|
### 单个 eval
|
|
95
89
|
|
|
@@ -97,56 +91,175 @@ Failing:
|
|
|
97
91
|
$ niceeval show weather/brooklyn
|
|
98
92
|
weather/brooklyn — 布鲁克林天气查询
|
|
99
93
|
|
|
100
|
-
compare/bub-gpt-5.4 ✓ passed 1 attempt
|
|
101
|
-
compare/codex-gpt-5.4 ✗ failed 3 attempts
|
|
94
|
+
compare/bub-gpt-5.4 ✓ passed 1 attempt 38.0s $0.03 (2h ago) @1xqur9kx[E,X,⏱]
|
|
95
|
+
compare/codex-gpt-5.4 ✗ failed 3 attempts 41.2s $0.12 (40s ago) @1k2m9qrs[E,X,⏱] gate calledTool("get_weather")
|
|
102
96
|
|
|
103
|
-
attempt 3 · compare/codex-gpt-5.4 · failed ·
|
|
97
|
+
attempt 3 · compare/codex-gpt-5.4 · failed · 41.2s · 12.3k tokens · $0.04
|
|
104
98
|
✗ gate calledTool("get_weather") — tool was never called
|
|
105
99
|
✓ gate succeeded()
|
|
106
100
|
✗ soft judge("回答基于实时数据") — 0.2/1: reply invents a temperature without any tool call
|
|
107
101
|
|
|
108
|
-
artifacts: .niceeval/2026-07-09T10-00-00-000Z/
|
|
109
|
-
|
|
102
|
+
artifacts: .niceeval/compare_codex-gpt-5.4/2026-07-09T10-00-00-000Z-x1f2/weather/brooklyn/a2/
|
|
103
|
+
attempt locator: @1k2m9qrs
|
|
104
|
+
next: niceeval show @1k2m9qrs [--eval|--execution|--diff]
|
|
110
105
|
```
|
|
111
106
|
|
|
112
|
-
|
|
107
|
+
每个 experiment 一行的紧凑索引末尾就带着代表 attempt 的 `@<locator>`(`compare/bub-gpt-5.4` 只有一次 attempt 就代表它自己,`compare/codex-gpt-5.4` 代表的是默认展开的那一次失败);展开的明细块结尾再重复一次精确的 `attempt locator:`,两处给的是同一个值。想看别的 attempt(比如 `compare/codex-gpt-5.4` 更早失败的那次),去 `--history` 或 artifact 目录里找到它的 locator,`niceeval show @<locator>` 直接跳过去,不需要先回到这张列表。
|
|
113
108
|
|
|
114
|
-
|
|
109
|
+
### `@<locator>`:一次 Attempt 的全景
|
|
110
|
+
|
|
111
|
+
不带证据 flag 的 `niceeval show @<locator>` 是失败诊断首页:除断言计票外,失败项直接列 group、matcher、expected、received、原因和源码位置;随后给 Eval 源码是否可用、Agent 事件计数、OTel 计时可用性与工作区 diff 摘要。通常这一页已经能回答“为什么失败”,需要解释 Agent 为什么产生该结果时再打开证据切面:
|
|
115
112
|
|
|
116
113
|
```text
|
|
117
|
-
$ niceeval show
|
|
118
|
-
|
|
114
|
+
$ niceeval show @1k2m9qrs
|
|
115
|
+
@1k2m9qrs · weather/brooklyn · compare/codex-gpt-5.4 · failed
|
|
116
|
+
snapshot 2026-07-09T10:00:00.000Z · attempt 3 · 41.2s · 12.3k tokens · $0.04
|
|
117
|
+
|
|
118
|
+
assertions: 1 passed · 1 gate failed · 1 soft below target
|
|
119
|
+
eval source: evals/weather/brooklyn.eval.ts · sha256:a3fa4555…
|
|
120
|
+
|
|
121
|
+
failures:
|
|
122
|
+
gate · Issue 15193: selected proposal matches the one maintainers accepted
|
|
123
|
+
assertion: equals(4)
|
|
124
|
+
expected: 4
|
|
125
|
+
received: 1
|
|
126
|
+
source: evals/memory/swelancer-manager-proposals.eval.ts:40:11
|
|
127
|
+
|
|
128
|
+
execution: 2 events · 0 skill loads · 0 tool calls · 1 AI messages
|
|
129
|
+
timing: OTel spans recorded for this attempt — see --execution for per-step timing.
|
|
130
|
+
|
|
131
|
+
changes: diff unavailable · no workspace diff was recorded for this attempt
|
|
132
|
+
|
|
133
|
+
evidence: eval source [E] · execution [X] · OTel timing [⏱]
|
|
134
|
+
artifacts: .niceeval/compare_codex-gpt-5.4/2026-07-09T10-00-00-000Z-x1f2/weather/brooklyn/a2/
|
|
135
|
+
next: niceeval show @1k2m9qrs [--eval|--execution|--diff]
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
这份全景只给摘要,不复现某个切面的完整内容——完整源码、完整事件流或完整文件列表分别要对应的证据 flag 才给。`changes` 一行永远说明 diff 不可用的具体原因:这里是「这次 Attempt 从未收集过 diff」(`weather/brooklyn` 不是 sandbox eval,压根不会有工作区改动可收集);如果是 sandbox eval 但 agent 确实没碰任何文件,会是另一句「没有产生工作区文件改动」;两种「不可用」原因不同,不共用一句含糊的提示。
|
|
139
|
+
|
|
140
|
+
### `--eval`、`--execution`、`--diff`:三个证据切面
|
|
119
141
|
|
|
120
|
-
|
|
121
|
-
[assistant] 布鲁克林今天大约 24°C,晴。
|
|
142
|
+
三个证据 flag 既可以加在 `@<locator>` 后面(精确到一次 Attempt),也可以加在能唯一收窄到一个 eval 的前缀后面(挑同一套默认启发式选中的 attempt——最新一次失败,没有失败就挑最新一次,与单 eval 详情块展开的是同一次);前缀撞到不止一个 eval 时会报错,报错正文直接给出每个候选 eval 的 `@<locator>`,照抄一个继续即可。可以同时传多个证据 flag,一次输出全部要看的切面。
|
|
122
143
|
|
|
123
|
-
|
|
144
|
+
`--eval` 是运行时保存的 Eval 源码,按行标注每条断言、gate 失败与 soft 分数直接排在对应源码行下面,源码里没能对应到具体行的断言(没有位置信息,或位置指向另一个文件)单独成一段,永不丢弃:
|
|
145
|
+
|
|
146
|
+
```text
|
|
147
|
+
$ niceeval show @1k2m9qrs --eval
|
|
148
|
+
@1k2m9qrs · weather/brooklyn · compare/codex-gpt-5.4 · failed
|
|
149
|
+
|
|
150
|
+
eval source: evals/weather/brooklyn.eval.ts · sha256:a3fa4555…
|
|
151
|
+
|
|
152
|
+
1 export default defineEval({
|
|
153
|
+
2 id: "weather/brooklyn",
|
|
154
|
+
3 async test(t) {
|
|
155
|
+
4 const turn = await t.send("布鲁克林今天天气怎么样?");
|
|
156
|
+
5✗ turn.calledTool("get_weather");
|
|
157
|
+
gate · tool was never called
|
|
158
|
+
6✓ turn.succeeded();
|
|
159
|
+
7✗ t.check(turn.message, judge("回答基于实时数据"));
|
|
160
|
+
soft · 0.2/1 · reply invents a temperature without any tool call
|
|
161
|
+
8 },
|
|
162
|
+
9 });
|
|
163
|
+
|
|
164
|
+
assertions: 1 passed · 1 gate failed · 1 soft below target
|
|
165
|
+
|
|
166
|
+
full eval source: .niceeval/compare_codex-gpt-5.4/2026-07-09T10-00-00-000Z-x1f2/weather/brooklyn/a2/sources.json
|
|
124
167
|
```
|
|
125
168
|
|
|
126
|
-
|
|
169
|
+
它展示的是**这次 Attempt 运行当时保存的源码**,不是当前工作区里同名文件的最新内容——eval 改过之后再看旧 Attempt,看到的仍是它跑的那一版。没有捕获到源码时如实说明「eval source unavailable for this attempt」,不伪造一份空文档。
|
|
170
|
+
|
|
171
|
+
`--execution` 把标准事件流(消息、thinking、Skill 加载、工具调用/结果、subagent、错误)排成一棵执行树;这次 Attempt 接入过 OTel 时,同一节点能关联到的 span 会补上相对时间与耗时。无法关联到 Agent 事件的 SDK / runtime span 不逐行混入执行记录,只在结尾报告省略数量并指向完整 `trace.json`。没接入 OTel 时骨架、顺序和内容不变,只去掉时间列并标 `timing unavailable`:
|
|
127
172
|
|
|
128
173
|
```text
|
|
129
|
-
$ niceeval show
|
|
130
|
-
|
|
131
|
-
├─ inference ▕█████░░░░░░░░░░░░░░░▏ 10.1s
|
|
132
|
-
├─ inference ▕░░░░░█████████░░░░░░▏ 18.3s
|
|
133
|
-
└─ inference ▕░░░░░░░░░░░░░░██████▏ 12.4s
|
|
174
|
+
$ niceeval show @1k2m9qrs --execution
|
|
175
|
+
@1k2m9qrs · weather/brooklyn · compare/codex-gpt-5.4 · failed
|
|
134
176
|
|
|
135
|
-
|
|
177
|
+
USER 0.0s · 100ms
|
|
178
|
+
布鲁克林今天天气怎么样?
|
|
179
|
+
|
|
180
|
+
ASSISTANT 0.2s · 41.0s
|
|
181
|
+
布鲁克林今天大约 24°C,晴。
|
|
182
|
+
|
|
183
|
+
total 41.2s · 0 skill loads · 0 tool calls · 1 AI message
|
|
184
|
+
full events: .niceeval/compare_codex-gpt-5.4/2026-07-09T10-00-00-000Z-x1f2/weather/brooklyn/a2/events.json
|
|
185
|
+
full OTel trace: .niceeval/compare_codex-gpt-5.4/2026-07-09T10-00-00-000Z-x1f2/weather/brooklyn/a2/trace.json
|
|
136
186
|
```
|
|
137
187
|
|
|
138
|
-
|
|
188
|
+
这次 Attempt 只有两条消息、没有任何工具调用节点——这正是上面 `calledTool("get_weather")` 这条 gate 断言失败的原因,`--execution` 在这里直接印证了 `--eval` 那份断言标注。有 Skill 加载和工具调用时,`--execution` 把它们按发生顺序一起排进同一棵树,工具调用拆成「调用」与「结果」两行读:
|
|
139
189
|
|
|
140
190
|
```text
|
|
141
|
-
$ niceeval show
|
|
142
|
-
|
|
143
|
-
|
|
191
|
+
$ niceeval show @1c3h6twx --execution
|
|
192
|
+
@1c3h6twx · fixtures/button · compare/bub-gpt-5.4 · errored
|
|
193
|
+
|
|
194
|
+
USER 0.0s · 100ms
|
|
195
|
+
给 Button 组件加一个 loading 态
|
|
196
|
+
|
|
197
|
+
ASSISTANT 0.2s · 100ms
|
|
198
|
+
我先看看现有 Button 组件的实现。
|
|
199
|
+
|
|
200
|
+
SKILL · component-scaffold 0.3s · 400ms
|
|
201
|
+
loaded
|
|
202
|
+
|
|
203
|
+
TOOL · write_file 0.8s · 1.8s
|
|
204
|
+
input
|
|
205
|
+
{"path":"src/components/Button.tsx"}
|
|
206
|
+
result · completed
|
|
207
|
+
{"bytesWritten":1820}
|
|
144
208
|
|
|
145
|
-
|
|
146
|
-
|
|
209
|
+
ASSISTANT 2.8s · 1.2s
|
|
210
|
+
已经加上 loading 态并补了对应样式。
|
|
211
|
+
|
|
212
|
+
total 4.0s · 1 skill load · 1 tool call · 2 AI messages
|
|
213
|
+
full events: fixtures/button/a1/events.json
|
|
214
|
+
full OTel trace: fixtures/button/a1/trace.json
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
没有 OTel 接入时,同一棵树去掉时间列,节点内容原样保留:
|
|
218
|
+
|
|
219
|
+
```text
|
|
220
|
+
$ niceeval show @1nx4dpqr --execution
|
|
221
|
+
@1nx4dpqr · weather/brooklyn · compare/codex-gpt-5.4 · failed
|
|
222
|
+
|
|
223
|
+
USER
|
|
224
|
+
布鲁克林今天天气怎么样?
|
|
225
|
+
|
|
226
|
+
ASSISTANT
|
|
227
|
+
布鲁克林今天大约 24°C,晴。
|
|
228
|
+
|
|
229
|
+
timing unavailable · OTel trace was not collected
|
|
230
|
+
full events: .niceeval/compare_codex-gpt-5.4/2026-07-09T10-00-00-000Z-x1f2/weather/brooklyn/a2/events.json
|
|
147
231
|
```
|
|
148
232
|
|
|
149
|
-
|
|
233
|
+
`--diff` 默认给文件级摘要(落盘的 diff 只有改动后的全文,没有基线可比对增删行数,所以每个改动过的文件都标 `M`、后面跟它现在的行数,不区分新建与修改);看单个文件的完整内容用 `--diff=<文件路径>`——路径必须用 `=` 连写,位置参数永远留给 eval id 前缀 / `@<locator>`:
|
|
234
|
+
|
|
235
|
+
```text
|
|
236
|
+
$ niceeval show @1c3h6twx --diff
|
|
237
|
+
@1c3h6twx · fixtures/button · compare/bub-gpt-5.4 · errored
|
|
238
|
+
|
|
239
|
+
M src/components/Button.css 18 lines
|
|
240
|
+
M src/components/Button.tsx 42 lines
|
|
241
|
+
|
|
242
|
+
(2 files · full diff: fixtures/button/a1/diff.json)
|
|
243
|
+
$ niceeval show @1c3h6twx --diff=src/components/Button.tsx
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
三个切面对长内容都会截断,但截断永远如实标注剩余数量和原始 artifact 路径——输出对上下文窗口友好,事实源一字不少地留在盘上。
|
|
247
|
+
|
|
248
|
+
### 给 coding agent 的最短阅读路径
|
|
249
|
+
|
|
250
|
+
把下面这条闭环交给 coding agent 即可。每一步只在上一层不足以定位问题时继续,避免一开始就把完整 artifact 塞进上下文:
|
|
251
|
+
|
|
252
|
+
```text
|
|
253
|
+
1. 运行 niceeval show,找到失败或出错的 eval,从紧凑索引里摘一个 @<locator>。
|
|
254
|
+
2. 运行 niceeval show <eval-id>,读取该题各 experiment 的判定、默认 attempt 的断言明细,
|
|
255
|
+
以及每行末尾的 @<locator>。
|
|
256
|
+
3. 运行 niceeval show @<locator>,看紧凑全景确认这次 Attempt 实际捕获到了哪些证据。
|
|
257
|
+
4. 按问题选择 --eval、--execution 或 --diff;可以同时传多个证据 flag。
|
|
258
|
+
5. 输出被截断时,读取末尾标出的 sources.json、events.json、trace.json 或 diff.json 原始路径。
|
|
259
|
+
6. 修复后重跑该 eval,再用 niceeval show <eval-id> 验证新的 @<locator>;收工前用 --force 全量重跑确认整体结果。
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
`--eval` 回答“这道题实际检查了什么、哪条断言为什么过或没过”,`--execution` 回答“agent 做了什么、调用了什么、时间花在哪里”,`--diff` 回答“沙箱里的文件实际改成了什么”。先按问题选证据,不需要每次把三份都读完。
|
|
150
263
|
|
|
151
264
|
### 历史与抖动:`--history`
|
|
152
265
|
|
|
@@ -163,7 +276,7 @@ compare/codex-gpt-5.4 · 5 runs · passed 2/5
|
|
|
163
276
|
2026-07-07T16-40 ✗ failed 3 attempts $0.05 gate calledTool("get_weather")
|
|
164
277
|
```
|
|
165
278
|
|
|
166
|
-
✓✗ 交替说明这个 eval 在抖,该修的是稳定性(被测程序或断言),反复重跑碰运气只会烧钱;连续绿转红的拐点就是回归引入的位置,用 `--run <目录>`
|
|
279
|
+
✓✗ 交替说明这个 eval 在抖,该修的是稳定性(被测程序或断言),反复重跑碰运气只会烧钱;连续绿转红的拐点就是回归引入的位置,用 `--run <目录>` 钉住拐点前后两次细看。时间轴只列真实执行——缓存携带的旧结果是判定的复印件,不占行,否则趋势会被复印件灌满假数据。不带 eval id 的 `niceeval show --history` 给每个 experiment 的 per-run 通过率序列,同一份趋势的榜单视角。
|
|
167
280
|
|
|
168
281
|
两次 run 的精确对比(这次修复具体翻转了哪些 eval)不做成 flag:用 `DeltaTable` 积木写一份报告递给 `--report`,几行就是一份自定义对比报告,终端和网页两扇门都认——内置命令只管固定摆法,自定义口径见[自定义报告](/zh/guides/custom-reports)。
|
|
169
282
|
|
|
@@ -173,13 +286,15 @@ compare/codex-gpt-5.4 · 5 runs · passed 2/5
|
|
|
173
286
|
npx niceeval view
|
|
174
287
|
```
|
|
175
288
|
|
|
176
|
-
|
|
289
|
+
这会打开本地结果查看器。它的首页报告和 `niceeval show` 选结果的规则一模一样:对每个 experiment 的每道 eval,取时间上最新的那份判定,同一个 experiment 跨多次运行拼出来;收窄范围(eval ID 前缀、`--experiment`)时按同一条规则收窄。你可以浏览 eval、查看 agent 的对话与工具调用、读 diff、检查断言结果。数据不会上传到外部服务。
|
|
177
290
|
|
|
178
291
|
<Tip>
|
|
179
292
|
失败后立刻运行 `npx niceeval view`,可以直接打开刚刚那次运行的 artifacts。
|
|
180
293
|
</Tip>
|
|
181
294
|
|
|
182
|
-
view
|
|
295
|
+
`view` 的首页是一份报告:不传 `--report` 时是成本 × 通过率散点图与逐实验表,适合人在网页比较;传了 `--report` 就换成你自己的报告(与 `show --report` 吃同一个文件),见[自定义报告](/zh/guides/custom-reports)。裸 `show` 则使用更适合终端 agent 循环的 Attempt 索引。证据部分(Attempt 弹窗、transcript、trace 瀑布、run 列表)始终保留。
|
|
296
|
+
|
|
297
|
+
网页版多几样浏览操作:点表头就地排序、在榜单的过滤框里筛行、点开一个 experiment 行看它每道题的判定与原因、悬停散点看数值——这些只影响眼前的视图,不改判定口径,刷新即恢复。报告上方有 **Copy fix prompt** 按钮,把全部失败打包成可直接粘给 coding agent 的修复 prompt(attempt 弹窗里有单条版)。报告文案有中英两份,随界面语言切换。
|
|
183
298
|
|
|
184
299
|
## 导出与静态托管
|
|
185
300
|
|
|
@@ -191,24 +306,28 @@ view 的结构是「报告槽 + 证据室」:报告槽默认装官方榜单,
|
|
|
191
306
|
npx niceeval view --out site
|
|
192
307
|
```
|
|
193
308
|
|
|
194
|
-
NiceEval 写入 `<dir>/index.html
|
|
309
|
+
NiceEval 写入 `<dir>/index.html`,并把查看器要读取的 artifact(`sources.json`、`events.json`、`trace.json`)复制到 `<dir>/artifact/` 下。把整个目录交给任何静态托管(Vercel、GitHub Pages 或 `python3 -m http.server`),代码视图、transcript 和 trace 瀑布图都和本地 `niceeval view` 一致;表格排序、过滤和图表悬停也照常可用——所需脚本已内联进页面,浏览器禁用 JS 时页面仍完整可读,只是少这些浏览操作。
|
|
195
310
|
|
|
196
|
-
`--out` 只接受目录。没有单文件导出:代码视图、transcript 和 trace
|
|
311
|
+
`--out` 只接受目录。没有单文件导出:代码视图、transcript 和 trace 依赖 artifact 文件,单个 HTML 装不下完整证据。要把结果发给别人,托管整站发链接即可。
|
|
197
312
|
|
|
198
|
-
零可读结果时 `view` 直接报错、非零退出——本地服务起不来,`--out`
|
|
313
|
+
零可读结果时 `view` 直接报错、非零退出——本地服务起不来,`--out` 不导出空页面。错误逐条列出被跳过的快照目录与原因;落盘 schemaVersion 与当前版本不兼容时,还给出能直接查看旧落盘的 `npx niceeval@<版本> view` 命令。
|
|
199
314
|
|
|
200
315
|
两点限制:
|
|
201
316
|
|
|
202
317
|
- `diff.json` 和 `o11y.json` 不会被复制。查看器不读取它们,且 diff 可能达到上百 MB。
|
|
203
|
-
- 用 `file://` 直接打开 `index.html` 时浏览器不允许 fetch
|
|
318
|
+
- 用 `file://` 直接打开 `index.html` 时浏览器不允许 fetch artifact,代码视图会提示源码不可用。本地预览用 http 服务打开。
|
|
204
319
|
|
|
205
320
|
最简单的流程是在跑过 eval 的机器上导出,把产物目录直接部署,不需要额外步骤。要让站点随 push 自动更新,把 `.niceeval/` 提交进仓库、CI 上一行 `view --out` 导出——workflow 与平台接线见[通过 CI 发布报告](/zh/guides/publish-report)。
|
|
206
321
|
|
|
207
322
|
## Artifact 说明
|
|
208
323
|
|
|
209
|
-
### `
|
|
324
|
+
### `snapshot.json`
|
|
325
|
+
|
|
326
|
+
快照级元数据:实验身份(experimentId)、agent、model、开始与收尾时间、格式版本。不含任何逐 attempt 数据——通过数、失败数这类聚合不落盘,由读取面逐条推导。
|
|
327
|
+
|
|
328
|
+
### `result.json`
|
|
210
329
|
|
|
211
|
-
|
|
330
|
+
单个 attempt 的权威记录:判定、断言、耗时、用量、成本。attempt 完成时一次写成,之后不再改写。
|
|
212
331
|
|
|
213
332
|
### `events.json`
|
|
214
333
|
|
|
@@ -230,7 +349,7 @@ OTLP trace 或标准化后的 span 数据。
|
|
|
230
349
|
|
|
231
350
|
工具调用、命令、usage 和成本等观测摘要。
|
|
232
351
|
|
|
233
|
-
##
|
|
352
|
+
## Verdict 含义
|
|
234
353
|
|
|
235
354
|
<Tabs>
|
|
236
355
|
<Tab title="passed">所有 gate 通过。</Tab>
|
|
@@ -239,11 +358,12 @@ OTLP trace 或标准化后的 span 数据。
|
|
|
239
358
|
<Tab title="skipped">eval 被主动跳过。</Tab>
|
|
240
359
|
</Tabs>
|
|
241
360
|
|
|
242
|
-
Soft 断言的分数记录在 `assertions[].score` 里;非 `--strict` 模式下,它们不会产生额外的
|
|
361
|
+
Soft 断言的分数记录在 `assertions[].score` 里;非 `--strict` 模式下,它们不会产生额外的 verdict。
|
|
243
362
|
|
|
244
363
|
## 调试建议
|
|
245
364
|
|
|
246
|
-
-
|
|
247
|
-
- 想知道
|
|
248
|
-
-
|
|
365
|
+
- 榜单里失败/错误的题每条自带下钻命令:`niceeval show <eval id>` 先看断言明细,行尾的 `@<locator>` 可以直接精确下钻到某一次 Attempt。
|
|
366
|
+
- 想知道 eval 实际检查了什么、断言为什么过或没过,看 `--eval`(标回源码行的断言标注)。
|
|
367
|
+
- 想知道 agent 做了什么、调用了什么、时间花在哪里,看 `--execution`(或 view 的证据面板)。
|
|
368
|
+
- coding-agent 失败时看 `--diff` 和 `--execution` 里的工具调用;两者结合能看出「改错了文件」还是「压根没调用该调用的工具」。
|
|
249
369
|
- 判断缺陷在被测程序还是 eval 本身、修完怎么重跑,流程见 [Agent 反馈闭环](/zh/guides/agent-feedback-loop)。
|
|
@@ -82,6 +82,14 @@ npx niceeval exp prompt-variants
|
|
|
82
82
|
|
|
83
83
|
这样报告会按同一组展示,差异也能在 Git 里 review。
|
|
84
84
|
|
|
85
|
+
只想验证组里某一个配置时,把位置参数写成该配置的完整 id(`组/文件名`,不带扩展名),精确匹配到单个文件:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
npx niceeval exp prompt-variants/concise
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
用于逐配置排查——确认某一格改动是否达标,不用先跑完整组,也不用把其它配置文件挪出目录。
|
|
92
|
+
|
|
85
93
|
## 常用字段
|
|
86
94
|
|
|
87
95
|
| 字段 | 用途 |
|
|
@@ -96,6 +104,20 @@ npx niceeval exp prompt-variants
|
|
|
96
104
|
| `timeoutMs` | 单个 attempt 的超时 |
|
|
97
105
|
| `budget` | 这一格配置的预算上限 |
|
|
98
106
|
| `maxConcurrency` | 这一格配置的并发上限 |
|
|
99
|
-
| `sandbox` | sandbox agent 使用的后端,如 `dockerSandbox()` / `e2bSandbox()` |
|
|
107
|
+
| `sandbox` | sandbox agent 使用的后端,如 `dockerSandbox()` / `e2bSandbox()`;spec 上可以链 `.setup()` / `.teardown()` 挂按实验变化的环境钩子 |
|
|
108
|
+
|
|
109
|
+
Experiment 本身是纯配置数据,没有 `setup` / `teardown` 这类字段。要在跑 agent 前按实验准备环境(装二进制、预热、跨 attempt 载入和回存状态),挂在 `sandbox` 字段的 spec 上:
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
export default defineExperiment({
|
|
113
|
+
agent: codexAgent({ mcpServers: [mempalMcp] }),
|
|
114
|
+
sandbox: e2bSandbox({ template: "fasteval-agents" })
|
|
115
|
+
.setup(mempalSetup("codex")) // 装二进制、预热、写 hook、载入状态
|
|
116
|
+
.teardown(mempalTeardown("codex")), // 回存状态
|
|
117
|
+
maxConcurrency: 1, // 载入和回存之间不能并发,声明串行
|
|
118
|
+
});
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
钩子的执行时机、多钩子顺序和失败语义见 [Sandbox 后端 · 环境钩子](/zh/guides/sandbox-providers#环境钩子)。
|
|
100
122
|
|
|
101
123
|
跨配置比较的设计建议见[实验矩阵](/zh/guides/experiments)。adapter 如何消费 `ctx.model` 和 `ctx.flags` 见[Adapter](/zh/concepts/adapter)。
|
|
@@ -301,7 +301,7 @@ OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318/v1/traces node server.js
|
|
|
301
301
|
|
|
302
302
|
`ctx.telemetry` 只在配置了 OTel 接入时出现,没配时 spread 一个 `undefined` 也安全,这行可以常驻。不带这个头 span 也能收到,但归属退化成时间窗口、该 agent 的轮次会降为串行——带上它是并发下归属准确的来源。
|
|
303
303
|
|
|
304
|
-
**这一步解锁**:`niceeval view` 里的调用瀑布图——应用内部每次模型调用、每次工具执行的耗时与 token
|
|
304
|
+
**这一步解锁**:`niceeval view` 里的调用瀑布图——应用内部每次模型调用、每次工具执行的耗时与 token,按轮铺成时间线。断言不变:判定依据在前几步的事件映射里已经齐了,span 只进瀑布图、不喂断言。接收器怎么起、span 怎么归属到轮,见 [OTel 接入](/zh/guides/connect-otel)。
|
|
305
305
|
|
|
306
306
|
## 第七步:透传 experiment 的 flags(A/B 对比)
|
|
307
307
|
|
|
@@ -346,7 +346,7 @@ export default defineExperiment({
|
|
|
346
346
|
|
|
347
347
|
## 相关阅读
|
|
348
348
|
|
|
349
|
-
- [Adapter](/zh/concepts/adapter) — 契约本身:`send`
|
|
349
|
+
- [Adapter](/zh/concepts/adapter) — 契约本身:`send` 传入什么返回什么、三个接入等级、能力从哪来。
|
|
350
350
|
- [接入你的 Agent](/zh/guides/connect-your-agent) — 接入全景:最小接入、参数通道与增量地图。
|
|
351
351
|
- [HITL](/zh/concepts/hitl) — 停轮等人的完整概念:握手时序与两侧义务。
|
|
352
352
|
- [Drive](/zh/concepts/drive) — eval 侧视角:`t.send()`、`t.newSession()` 与 HITL 怎么用。
|
package/docs-site/zh/index.mdx
CHANGED
|
@@ -89,7 +89,7 @@ eval 运行完成后,[NiceEval](https://niceeval.com/) 会生成易读报告
|
|
|
89
89
|
| [Eval](/zh/concepts/evals) | 一个测试用例:写在 `evals/*.eval.ts` 里,描述测什么。 |
|
|
90
90
|
| [Experiment](/zh/concepts/experiment) | 可签入的运行配置:决定连哪个 Adapter、什么 model、什么 flags。 |
|
|
91
91
|
| [Adapter](/zh/concepts/adapter) | 连接被测系统的适配层:实现一个 `send`,把返回翻译成标准事件流。 |
|
|
92
|
-
| [Sandbox](/zh/guides/sandbox-
|
|
92
|
+
| [Sandbox](/zh/guides/sandbox-providers) | 需要隔离工作区的 coding agent 才用得到;直连 Web Agent 不需要。 |
|
|
93
93
|
| [Tier](/zh/concepts/tier) | 接入 Adapter 的三档投入:Tier 1 只接 send,Tier 2 加 OTel 换调用瀑布图,Tier 3 侵入改造做 feature A/B。 |
|
|
94
94
|
|
|
95
95
|
完整术语表见[架构概览](/zh/concepts/overview)。
|
|
@@ -134,10 +134,11 @@ export default defineExperiment({
|
|
|
134
134
|
|
|
135
135
|
```sh
|
|
136
136
|
npx niceeval exp local weather-tool
|
|
137
|
-
npx niceeval
|
|
137
|
+
npx niceeval show # 终端读取结果,失败项可继续下钻
|
|
138
|
+
npx niceeval view # 网页交互浏览
|
|
138
139
|
```
|
|
139
140
|
|
|
140
|
-
如果被测对象是需要隔离工作区的 coding agent(Codex、Claude Code 插件/Skill),evals 里改用 `t.sandbox.uploadDirectory()` 铺工作区、`t.sandbox.fileChanged()` / `t.sandbox.file()` 检查改了什么文件、`t.sandbox.runCommand()`
|
|
141
|
+
如果被测对象是需要隔离工作区的 coding agent(Codex、Claude Code 插件/Skill),evals 里改用 `t.sandbox.uploadDirectory()` 铺工作区、`t.sandbox.fileChanged()` / `t.sandbox.file()` 检查改了什么文件、`t.sandbox.runCommand()` 跑测试——参考独立仓库 [coding-agent-skill](https://github.com/CorrectRoadH/coding-agent-skill)。
|
|
141
142
|
|
|
142
143
|
## 快速开始
|
|
143
144
|
|
|
@@ -42,7 +42,8 @@ export default defineEval({
|
|
|
42
42
|
|
|
43
43
|
```sh
|
|
44
44
|
pnpm exec niceeval exp local eval-tool-call # 用 local experiment 只跑 eval-tool-call
|
|
45
|
-
pnpm exec niceeval
|
|
45
|
+
pnpm exec niceeval show # 终端读取结果,适合人和 AI
|
|
46
|
+
pnpm exec niceeval view # 在网页中浏览同一批 artifacts
|
|
46
47
|
```
|
|
47
48
|
|
|
48
49
|
## 为什么有了 DeepEval、LangFuse、BrainTrust 还需要 NiceEval
|