niceeval 0.5.4 → 0.6.1

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