niceeval 0.9.1 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (428) hide show
  1. package/INDEX.md +31 -33
  2. package/dist/agents/types.d.ts +20 -17
  3. package/dist/context/types.d.ts +21 -21
  4. package/dist/i18n/en.d.ts +10 -2
  5. package/dist/i18n/zh-CN.d.ts +14 -6
  6. package/dist/o11y/execution-tree.d.ts +103 -0
  7. package/dist/o11y/otlp/select.d.ts +22 -0
  8. package/dist/report/{react → assets}/colors.d.ts +8 -0
  9. package/dist/report/{react → assets}/colors.js +23 -0
  10. package/dist/report/built-in/index.d.ts +2 -2
  11. package/dist/report/built-in/index.js +2 -2
  12. package/dist/report/built-in/standard.d.ts +8 -1
  13. package/dist/report/built-in/standard.js +17 -7
  14. package/dist/report/components/attempt-detail/AttemptAssertions.d.ts +6 -0
  15. package/dist/report/components/attempt-detail/AttemptAssertions.js +17 -0
  16. package/dist/report/components/attempt-detail/AttemptConversation.d.ts +6 -0
  17. package/dist/report/components/attempt-detail/AttemptConversation.js +34 -0
  18. package/dist/report/components/attempt-detail/AttemptDiagnostics.d.ts +6 -0
  19. package/dist/report/components/attempt-detail/AttemptDiagnostics.js +7 -0
  20. package/dist/report/components/attempt-detail/AttemptDiff.d.ts +6 -0
  21. package/dist/report/components/attempt-detail/AttemptDiff.js +11 -0
  22. package/dist/report/components/attempt-detail/AttemptError.d.ts +6 -0
  23. package/dist/report/components/attempt-detail/AttemptError.js +16 -0
  24. package/dist/report/components/attempt-detail/AttemptFixPrompt.d.ts +6 -0
  25. package/dist/report/components/attempt-detail/AttemptFixPrompt.js +7 -0
  26. package/dist/report/components/attempt-detail/AttemptSource.d.ts +6 -0
  27. package/dist/report/components/attempt-detail/AttemptSource.js +27 -0
  28. package/dist/report/components/attempt-detail/AttemptSummary.d.ts +8 -0
  29. package/dist/report/components/attempt-detail/AttemptSummary.js +20 -0
  30. package/dist/report/components/attempt-detail/AttemptTimeline.d.ts +6 -0
  31. package/dist/report/components/attempt-detail/AttemptTimeline.js +28 -0
  32. package/dist/report/components/attempt-detail/AttemptTrace.d.ts +6 -0
  33. package/dist/report/components/attempt-detail/AttemptTrace.js +29 -0
  34. package/dist/report/components/attempt-detail/AttemptUsage.d.ts +6 -0
  35. package/dist/report/components/attempt-detail/AttemptUsage.js +20 -0
  36. package/dist/report/components/attempt-detail/compute.d.ts +24 -0
  37. package/dist/report/components/attempt-detail/compute.js +254 -0
  38. package/dist/report/components/attempt-detail/faces.d.ts +14 -0
  39. package/dist/report/components/attempt-detail/faces.js +235 -0
  40. package/dist/report/components/attempt-detail/index.d.ts +38 -0
  41. package/dist/report/components/attempt-detail/index.js +527 -0
  42. package/dist/report/{react → components}/cell.d.ts +5 -3
  43. package/dist/report/{react → components}/cell.js +3 -3
  44. package/dist/report/{react → components/entity-lists}/AttemptList.d.ts +8 -4
  45. package/dist/report/{react → components/entity-lists}/AttemptList.js +16 -10
  46. package/dist/report/{react → components/entity-lists}/EvalList.d.ts +3 -3
  47. package/dist/report/{react → components/entity-lists}/EvalList.js +0 -0
  48. package/dist/report/{react → components/entity-lists}/ExperimentList.d.ts +3 -3
  49. package/dist/report/{react → components/entity-lists}/ExperimentList.js +10 -10
  50. package/dist/report/components/entity-lists/compute.d.ts +23 -0
  51. package/dist/report/components/entity-lists/compute.js +171 -0
  52. package/dist/report/components/entity-lists/faces.d.ts +5 -0
  53. package/dist/report/components/entity-lists/faces.js +174 -0
  54. package/dist/report/components/entity-lists/index.d.ts +51 -0
  55. package/dist/report/components/entity-lists/index.js +165 -0
  56. package/dist/report/{react → components}/fixtures.d.ts +2 -2
  57. package/dist/report/{react → components}/fixtures.js +1 -1
  58. package/dist/report/{react → components/metric-views}/DeltaTable.d.ts +2 -2
  59. package/dist/report/{react → components/metric-views}/DeltaTable.js +4 -4
  60. package/dist/report/{react → components/metric-views}/MetricBars.d.ts +3 -3
  61. package/dist/report/{react → components/metric-views}/MetricBars.js +3 -3
  62. package/dist/report/{react → components/metric-views}/MetricLine.d.ts +2 -2
  63. package/dist/report/{react → components/metric-views}/MetricLine.js +8 -5
  64. package/dist/report/{react → components/metric-views}/MetricMatrix.d.ts +3 -3
  65. package/dist/report/{react → components/metric-views}/MetricMatrix.js +4 -4
  66. package/dist/report/components/metric-views/MetricScatter.d.ts +11 -0
  67. package/dist/report/{react → components/metric-views}/MetricScatter.js +26 -23
  68. package/dist/report/{react → components/metric-views}/MetricTable.d.ts +3 -3
  69. package/dist/report/{react → components/metric-views}/MetricTable.js +4 -4
  70. package/dist/report/{react → components/metric-views}/Scoreboard.d.ts +2 -2
  71. package/dist/report/{react → components/metric-views}/Scoreboard.js +3 -3
  72. package/dist/report/components/metric-views/compute.d.ts +89 -0
  73. package/dist/report/{compute.js → components/metric-views/compute.js} +32 -415
  74. package/dist/report/components/metric-views/faces.d.ts +13 -0
  75. package/dist/report/components/metric-views/faces.js +381 -0
  76. package/dist/report/components/metric-views/index.d.ts +50 -0
  77. package/dist/report/components/metric-views/index.js +273 -0
  78. package/dist/report/{text → components/metric-views}/plot.js +1 -1
  79. package/dist/report/components/shared-compute.d.ts +22 -0
  80. package/dist/report/components/shared-compute.js +47 -0
  81. package/dist/report/components/shared-faces.d.ts +9 -0
  82. package/dist/report/components/shared-faces.js +26 -0
  83. package/dist/report/components/shared.d.ts +68 -0
  84. package/dist/report/components/shared.js +125 -0
  85. package/dist/report/{react → components/site-components}/CopyFixPrompt.d.ts +2 -2
  86. package/dist/report/{react → components/site-components}/CopyFixPrompt.js +2 -2
  87. package/dist/report/{react → components/site-components}/HeroCard.d.ts +2 -2
  88. package/dist/report/{react → components/site-components}/HeroCard.js +2 -2
  89. package/dist/report/{react → components/site-components}/ScopeWarnings.d.ts +2 -2
  90. package/dist/report/{react → components/site-components}/ScopeWarnings.js +3 -3
  91. package/dist/report/{react → components/site-components}/TraceWaterfall.d.ts +3 -3
  92. package/dist/report/{react → components/site-components}/TraceWaterfall.js +5 -5
  93. package/dist/report/components/site-components/compute.d.ts +28 -0
  94. package/dist/report/components/site-components/compute.js +132 -0
  95. package/dist/report/components/site-components/faces.d.ts +21 -0
  96. package/dist/report/components/site-components/faces.js +75 -0
  97. package/dist/report/components/site-components/index.d.ts +74 -0
  98. package/dist/report/components/site-components/index.js +220 -0
  99. package/dist/report/{scope-warnings.d.ts → components/site-components/scope-warnings.d.ts} +2 -2
  100. package/dist/report/{scope-warnings.js → components/site-components/scope-warnings.js} +2 -2
  101. package/dist/report/{react → components/summaries}/ScopeSummary.d.ts +2 -2
  102. package/dist/report/{react → components/summaries}/ScopeSummary.js +17 -8
  103. package/dist/report/components/summaries/compute.d.ts +7 -0
  104. package/dist/report/components/summaries/compute.js +51 -0
  105. package/dist/report/components/summaries/faces.d.ts +7 -0
  106. package/dist/report/components/summaries/faces.js +38 -0
  107. package/dist/report/components/summaries/index.d.ts +27 -0
  108. package/dist/report/components/summaries/index.js +78 -0
  109. package/dist/report/definition/grid-layout.d.ts +50 -0
  110. package/dist/report/definition/grid-layout.js +89 -0
  111. package/dist/report/{primitives.d.ts → definition/primitives.d.ts} +34 -4
  112. package/dist/report/{primitives.js → definition/primitives.js} +101 -10
  113. package/dist/report/{report.d.ts → definition/report.d.ts} +36 -65
  114. package/dist/report/{report.js → definition/report.js} +58 -90
  115. package/dist/report/{text/table.d.ts → definition/table-text.d.ts} +2 -2
  116. package/dist/report/{text/table.js → definition/table-text.js} +2 -2
  117. package/dist/report/{tree.d.ts → definition/tree.d.ts} +43 -11
  118. package/dist/report/{tree.js → definition/tree.js} +9 -11
  119. package/dist/report/index.d.ts +33 -18
  120. package/dist/report/index.js +23 -14
  121. package/dist/report/{aggregate.d.ts → model/aggregate.d.ts} +12 -4
  122. package/dist/report/{aggregate.js → model/aggregate.js} +28 -8
  123. package/dist/report/{flag.d.ts → model/flag.d.ts} +14 -1
  124. package/dist/report/{flag.js → model/flag.js} +35 -0
  125. package/dist/report/{format.d.ts → model/format.d.ts} +11 -5
  126. package/dist/report/{format.js → model/format.js} +48 -4
  127. package/dist/report/{locale.d.ts → model/locale.d.ts} +17 -17
  128. package/dist/report/{locale.js → model/locale.js} +31 -33
  129. package/dist/report/{metrics.d.ts → model/metrics.d.ts} +2 -2
  130. package/dist/report/{metrics.js → model/metrics.js} +2 -2
  131. package/dist/report/{types.d.ts → model/types.d.ts} +140 -20
  132. package/dist/report/react/index.d.ts +32 -21
  133. package/dist/report/react/index.js +33 -21
  134. package/dist/report/{load.d.ts → runtime/load.d.ts} +1 -1
  135. package/dist/report/{load.js → runtime/load.js} +1 -1
  136. package/dist/report/runtime/text.d.ts +67 -0
  137. package/dist/report/runtime/text.js +114 -0
  138. package/dist/report/runtime/web.d.ts +35 -0
  139. package/dist/report/runtime/web.js +70 -0
  140. package/dist/results/annotated-source.d.ts +87 -0
  141. package/dist/results/attempt-evidence.d.ts +74 -0
  142. package/dist/results/attempt-source.d.ts +15 -0
  143. package/dist/results/select.d.ts +11 -1
  144. package/dist/results/select.js +27 -5
  145. package/dist/runner/eval-selection.d.ts +26 -0
  146. package/dist/runner/feedback/sink.d.ts +26 -1
  147. package/dist/runner/types.d.ts +149 -23
  148. package/dist/sandbox/docker.d.ts +6 -0
  149. package/dist/sandbox/types.d.ts +23 -21
  150. package/dist/scoring/display.d.ts +7 -2
  151. package/dist/scoring/display.js +42 -4
  152. package/dist/scoring/types.d.ts +3 -3
  153. package/dist/shared/aggregate.d.ts +14 -0
  154. package/dist/shared/aggregate.js +31 -0
  155. package/dist/shared/types.d.ts +6 -1
  156. package/docs-site/images/logo-dark.svg +7 -0
  157. package/docs-site/images/logo.svg +6 -5
  158. package/docs-site/zh/README.md +8 -7
  159. package/docs-site/zh/examples/ai-agent-application.mdx +5 -5
  160. package/docs-site/zh/examples/coding-agent-extensions.mdx +4 -4
  161. package/docs-site/zh/examples/index.mdx +3 -3
  162. package/docs-site/zh/examples/integrations/ai-sdk-v7.mdx +1 -1
  163. package/docs-site/zh/examples/integrations/claude-sdk.mdx +3 -3
  164. package/docs-site/zh/examples/integrations/codex-sdk.mdx +3 -3
  165. package/docs-site/zh/examples/integrations/langgraph.mdx +3 -3
  166. package/docs-site/zh/examples/integrations/pi-sdk.mdx +2 -2
  167. package/docs-site/zh/explanation/adapter.mdx +19 -19
  168. package/docs-site/zh/explanation/assert.mdx +9 -9
  169. package/docs-site/zh/explanation/drive.mdx +4 -4
  170. package/docs-site/zh/explanation/evals.mdx +8 -8
  171. package/docs-site/zh/explanation/experiment.mdx +8 -8
  172. package/docs-site/zh/explanation/hitl.mdx +13 -13
  173. package/docs-site/zh/explanation/judge.mdx +3 -3
  174. package/docs-site/zh/explanation/overview.mdx +7 -7
  175. package/docs-site/zh/explanation/runner.mdx +11 -11
  176. package/docs-site/zh/explanation/tier.mdx +6 -6
  177. package/docs-site/zh/index.mdx +14 -14
  178. package/docs-site/zh/introduction.mdx +13 -16
  179. package/docs-site/zh/reference/builtin-agents.mdx +61 -28
  180. package/docs-site/zh/reference/capabilities.mdx +7 -27
  181. package/docs-site/zh/reference/cli.mdx +35 -32
  182. package/docs-site/zh/reference/define-agent.mdx +32 -31
  183. package/docs-site/zh/reference/define-config.mdx +6 -6
  184. package/docs-site/zh/reference/define-eval.mdx +33 -20
  185. package/docs-site/zh/reference/events.mdx +4 -4
  186. package/docs-site/zh/reference/expect.mdx +3 -3
  187. package/docs-site/zh/reference/official-adapters.mdx +17 -17
  188. package/docs-site/zh/reference/report-components.mdx +193 -121
  189. package/docs-site/zh/reference/results-data.mdx +13 -13
  190. package/docs-site/zh/troubleshooting/debug-sandbox.mdx +11 -11
  191. package/docs-site/zh/troubleshooting/debugging.mdx +40 -16
  192. package/docs-site/zh/{how-to → tutorials}/agent-feedback-loop.mdx +38 -38
  193. package/docs-site/zh/tutorials/agent-onboarding.mdx +100 -0
  194. package/docs-site/zh/tutorials/authoring.mdx +211 -0
  195. package/docs-site/zh/{how-to → tutorials}/ci-integration.mdx +8 -8
  196. package/docs-site/zh/{how-to → tutorials}/connect-otel.mdx +22 -22
  197. package/docs-site/zh/{how-to → tutorials}/connect-your-agent.mdx +58 -63
  198. package/docs-site/zh/tutorials/custom-reports.mdx +453 -0
  199. package/docs-site/zh/{how-to → tutorials}/dataset-fanout.mdx +4 -4
  200. package/docs-site/zh/tutorials/experiments.mdx +103 -0
  201. package/docs-site/zh/{how-to → tutorials}/fixtures.mdx +9 -9
  202. package/docs-site/zh/{how-to → tutorials}/publish-report.mdx +6 -6
  203. package/docs-site/zh/tutorials/quickstart.mdx +18 -18
  204. package/docs-site/zh/{how-to → tutorials}/reporters.mdx +6 -6
  205. package/docs-site/zh/{how-to → tutorials}/sandbox-agent.mdx +6 -6
  206. package/docs-site/zh/{how-to → tutorials}/sandbox-providers.mdx +41 -19
  207. package/docs-site/zh/{how-to → tutorials}/scoring-guide.mdx +4 -4
  208. package/docs-site/zh/{how-to → tutorials}/viewing-results.mdx +49 -49
  209. package/docs-site/zh/tutorials/write-experiment.mdx +355 -0
  210. package/docs-site/zh/{how-to → tutorials}/write-send.mdx +40 -40
  211. package/package.json +8 -4
  212. package/src/agents/bub.ts +21 -8
  213. package/src/agents/claude-code.ts +23 -10
  214. package/src/agents/codex.test.ts +22 -7
  215. package/src/agents/codex.ts +22 -9
  216. package/src/agents/index.ts +2 -2
  217. package/src/agents/openai-compat.ts +1 -1
  218. package/src/agents/post-setup.ts +45 -22
  219. package/src/agents/streaming.ts +1 -1
  220. package/src/agents/types.ts +20 -17
  221. package/src/agents/ui-message-stream.test.ts +10 -0
  222. package/src/agents/ui-message-stream.ts +12 -1
  223. package/src/cli.ts +71 -57
  224. package/src/context/types.ts +21 -21
  225. package/src/define.ts +13 -0
  226. package/src/i18n/en.ts +27 -12
  227. package/src/i18n/zh-CN.ts +27 -12
  228. package/src/index.ts +2 -0
  229. package/src/report/{react → assets}/colors.ts +22 -0
  230. package/src/report/{react → assets}/enhance.js +1 -33
  231. package/src/report/{react → assets}/styles.css +124 -106
  232. package/src/report/built-in/index.tsx +2 -2
  233. package/src/report/built-in/standard.tsx +18 -6
  234. package/src/report/components/attempt-detail/AttemptAssertions.tsx +67 -0
  235. package/src/report/components/attempt-detail/AttemptConversation.tsx +110 -0
  236. package/src/report/components/attempt-detail/AttemptDiagnostics.tsx +38 -0
  237. package/src/report/components/attempt-detail/AttemptDiff.tsx +35 -0
  238. package/src/report/components/attempt-detail/AttemptError.tsx +31 -0
  239. package/src/report/components/attempt-detail/AttemptFixPrompt.tsx +26 -0
  240. package/src/report/components/attempt-detail/AttemptSource.tsx +80 -0
  241. package/src/report/components/attempt-detail/AttemptSummary.tsx +74 -0
  242. package/src/report/components/attempt-detail/AttemptTimeline.tsx +108 -0
  243. package/src/report/components/attempt-detail/AttemptTrace.tsx +63 -0
  244. package/src/report/components/attempt-detail/AttemptUsage.tsx +29 -0
  245. package/src/report/components/attempt-detail/attempt-components.test.tsx +680 -0
  246. package/src/report/components/attempt-detail/compute.ts +287 -0
  247. package/src/report/components/attempt-detail/faces.ts +257 -0
  248. package/src/report/components/attempt-detail/index.tsx +583 -0
  249. package/src/report/components/attempt-detail/validate.test.ts +235 -0
  250. package/src/report/{react → components}/cell.tsx +6 -3
  251. package/src/report/{report.test.ts → components/compute.test.ts} +316 -46
  252. package/src/report/{react → components/entity-lists}/AttemptList.tsx +24 -16
  253. package/src/report/{react → components/entity-lists}/EvalList.tsx +0 -0
  254. package/src/report/{react → components/entity-lists}/ExperimentList.tsx +23 -20
  255. package/src/report/components/entity-lists/compute.ts +196 -0
  256. package/src/report/components/entity-lists/faces.ts +207 -0
  257. package/src/report/components/entity-lists/index.tsx +241 -0
  258. package/src/report/components/entity-lists/validate.test.ts +114 -0
  259. package/src/report/{react → components}/fixtures.ts +2 -2
  260. package/src/report/{react → components/metric-views}/DeltaTable.tsx +5 -5
  261. package/src/report/{react → components/metric-views}/MetricBars.tsx +5 -5
  262. package/src/report/{react → components/metric-views}/MetricLine.tsx +9 -6
  263. package/src/report/{react → components/metric-views}/MetricMatrix.tsx +6 -6
  264. package/src/report/{react → components/metric-views}/MetricScatter.tsx +41 -33
  265. package/src/report/{react → components/metric-views}/MetricTable.tsx +6 -6
  266. package/src/report/{react → components/metric-views}/Scoreboard.tsx +4 -4
  267. package/src/report/{compute.ts → components/metric-views/compute.ts} +51 -477
  268. package/src/report/components/metric-views/faces.ts +423 -0
  269. package/src/report/components/metric-views/index.tsx +352 -0
  270. package/src/report/{text → components/metric-views}/plot.ts +1 -1
  271. package/src/report/components/metric-views/validate.test.ts +211 -0
  272. package/src/report/{react → components}/render.test.tsx +47 -17
  273. package/src/report/components/shared-compute.ts +59 -0
  274. package/src/report/components/shared-faces.ts +30 -0
  275. package/src/report/components/shared.ts +192 -0
  276. package/src/report/{react → components/site-components}/CopyFixPrompt.tsx +3 -3
  277. package/src/report/{react → components/site-components}/HeroCard.tsx +3 -3
  278. package/src/report/{react → components/site-components}/ScopeWarnings.tsx +4 -4
  279. package/src/report/{react → components/site-components}/TraceWaterfall.tsx +13 -10
  280. package/src/report/components/site-components/compute.ts +144 -0
  281. package/src/report/components/site-components/faces.ts +80 -0
  282. package/src/report/components/site-components/index.tsx +265 -0
  283. package/src/report/{scope-warnings.ts → components/site-components/scope-warnings.ts} +3 -3
  284. package/src/report/{site-components.test.tsx → components/site-components/site-components.test.tsx} +23 -21
  285. package/src/report/components/site-components/validate.test.ts +89 -0
  286. package/src/report/{react → components/summaries}/ScopeSummary.tsx +26 -11
  287. package/src/report/components/summaries/compute.ts +56 -0
  288. package/src/report/components/summaries/faces.ts +48 -0
  289. package/src/report/components/summaries/index.tsx +127 -0
  290. package/src/report/components/summaries/validate.test.ts +49 -0
  291. package/src/report/definition/grid-layout.test.ts +124 -0
  292. package/src/report/definition/grid-layout.ts +146 -0
  293. package/src/report/{primitives.tsx → definition/primitives.tsx} +168 -18
  294. package/src/report/{report.ts → definition/report.ts} +98 -165
  295. package/src/report/{shell-head.test.ts → definition/shell-head.test.ts} +2 -2
  296. package/src/report/{text/table.ts → definition/table-text.ts} +4 -4
  297. package/src/report/{tree.ts → definition/tree.ts} +56 -20
  298. package/src/report/index.ts +126 -66
  299. package/src/report/{aggregate.ts → model/aggregate.ts} +31 -9
  300. package/src/report/{flag.ts → model/flag.ts} +39 -1
  301. package/src/report/{format.ts → model/format.ts} +59 -5
  302. package/src/report/{locale.ts → model/locale.ts} +34 -36
  303. package/src/report/{metrics.ts → model/metrics.ts} +3 -3
  304. package/src/report/{types.ts → model/types.ts} +143 -22
  305. package/src/report/react/index.tsx +52 -26
  306. package/src/report/{dual-render.test.tsx → runtime/dual-render.test.tsx} +564 -49
  307. package/src/report/runtime/host.test.ts +44 -0
  308. package/src/report/runtime/host.ts +138 -0
  309. package/src/report/{load.ts → runtime/load.ts} +1 -1
  310. package/src/report/runtime/text.ts +192 -0
  311. package/src/report/runtime/web.ts +106 -0
  312. package/src/results/attempt-evidence.ts +5 -1
  313. package/src/results/host-equivalence.test.ts +53 -2
  314. package/src/results/select.ts +29 -5
  315. package/src/runner/attempt.test.ts +48 -1
  316. package/src/runner/attempt.ts +62 -42
  317. package/src/runner/cleanup-timeout.test.ts +16 -0
  318. package/src/runner/cleanup-timeout.ts +23 -0
  319. package/src/runner/discover.ts +1 -2
  320. package/src/runner/eval-selection.test.ts +187 -0
  321. package/src/runner/eval-selection.ts +109 -0
  322. package/src/runner/experiment-cleanup-registry.test.ts +89 -0
  323. package/src/runner/experiment-cleanup-registry.ts +39 -0
  324. package/src/runner/experiment-labels.test.ts +71 -0
  325. package/src/runner/feedback/agent.test.ts +33 -1
  326. package/src/runner/feedback/agent.ts +12 -16
  327. package/src/runner/feedback/ci.test.ts +35 -1
  328. package/src/runner/feedback/ci.ts +16 -18
  329. package/src/runner/feedback/coordinator.ts +28 -0
  330. package/src/runner/feedback/human.test.ts +108 -1
  331. package/src/runner/feedback/human.ts +71 -21
  332. package/src/runner/feedback/reducer.test.ts +64 -0
  333. package/src/runner/feedback/reducer.ts +26 -0
  334. package/src/runner/feedback/sink.ts +40 -1
  335. package/src/runner/fingerprint.ts +2 -1
  336. package/src/runner/report.test.ts +14 -0
  337. package/src/runner/report.ts +3 -1
  338. package/src/runner/run.test.ts +390 -12
  339. package/src/runner/run.ts +259 -26
  340. package/src/runner/sandbox-selection.test.ts +13 -3
  341. package/src/runner/sandbox-selection.ts +4 -2
  342. package/src/runner/types.ts +158 -23
  343. package/src/sandbox/docker.ts +7 -0
  344. package/src/sandbox/e2b.ts +12 -13
  345. package/src/sandbox/types.ts +23 -21
  346. package/src/scoring/display.test.ts +28 -2
  347. package/src/scoring/display.ts +38 -5
  348. package/src/scoring/types.ts +3 -3
  349. package/src/shared/aggregate.test.ts +52 -0
  350. package/src/shared/aggregate.ts +29 -0
  351. package/src/shared/types.ts +6 -1
  352. package/src/show/command.test.ts +34 -0
  353. package/src/show/command.ts +16 -0
  354. package/src/show/compose.ts +1 -1
  355. package/src/show/index.ts +56 -20
  356. package/src/show/render.ts +15 -239
  357. package/src/show/show.test.ts +127 -34
  358. package/src/view/app/App.test.tsx +1 -1
  359. package/src/view/app/App.tsx +119 -47
  360. package/src/view/app/i18n.ts +7 -147
  361. package/src/view/app/lib/attempt-dialog.test.ts +65 -0
  362. package/src/view/app/lib/attempt-dialog.ts +69 -0
  363. package/src/view/app/main.tsx +0 -1
  364. package/src/view/app/types.ts +3 -86
  365. package/src/view/artifact-serving.test.ts +22 -38
  366. package/src/view/client-dist/app.css +1 -1
  367. package/src/view/client-dist/app.js +15 -22
  368. package/src/view/data.test.ts +48 -36
  369. package/src/view/data.ts +105 -83
  370. package/src/view/index.ts +1 -1
  371. package/src/view/server.ts +32 -2
  372. package/src/view/shared/types.ts +6 -31
  373. package/src/view/site-parity.test.ts +24 -1
  374. package/src/view/site.ts +144 -17
  375. package/src/view/styles.css +0 -805
  376. package/src/view/view-report.test.ts +141 -22
  377. package/dist/report/components.d.ts +0 -179
  378. package/dist/report/components.js +0 -544
  379. package/dist/report/compute.d.ts +0 -139
  380. package/dist/report/react/ExperimentComparison.d.ts +0 -10
  381. package/dist/report/react/ExperimentComparison.js +0 -12
  382. package/dist/report/react/MetricScatter.d.ts +0 -9
  383. package/dist/report/react/format.d.ts +0 -3
  384. package/dist/report/react/format.js +0 -7
  385. package/dist/report/text/faces.d.ts +0 -45
  386. package/dist/report/text/faces.js +0 -671
  387. package/dist/report/web.d.ts +0 -32
  388. package/dist/report/web.js +0 -48
  389. package/docs-site/zh/how-to/authoring.mdx +0 -162
  390. package/docs-site/zh/how-to/custom-reports.mdx +0 -414
  391. package/docs-site/zh/how-to/experiments.mdx +0 -86
  392. package/docs-site/zh/how-to/write-experiment.mdx +0 -164
  393. package/src/report/components.tsx +0 -925
  394. package/src/report/react/ExperimentComparison.tsx +0 -73
  395. package/src/report/react/format.ts +0 -9
  396. package/src/report/text/faces.ts +0 -767
  397. package/src/report/web.ts +0 -77
  398. package/src/show/report-host.test.ts +0 -205
  399. package/src/show/report-host.ts +0 -389
  400. package/src/view/app/components/AttemptModal.tsx +0 -496
  401. package/src/view/app/components/CodeView.test.tsx +0 -142
  402. package/src/view/app/components/CodeView.tsx +0 -310
  403. package/src/view/app/components/CopyControls.tsx +0 -106
  404. package/src/view/app/components/Trace.tsx +0 -100
  405. package/src/view/app/components/Transcript.tsx +0 -157
  406. package/src/view/app/components/ui/badge.tsx +0 -21
  407. package/src/view/app/lib/artifact-url.ts +0 -17
  408. package/src/view/app/lib/attempt-route.test.ts +0 -80
  409. package/src/view/app/lib/attempt-route.ts +0 -52
  410. package/src/view/app/lib/format.ts +0 -70
  411. package/src/view/app/lib/guards.test.ts +0 -108
  412. package/src/view/app/lib/guards.ts +0 -71
  413. package/src/view/app/lib/rows.ts +0 -22
  414. package/src/view/app/lib/transcript-data.tsx +0 -151
  415. package/src/view/app/lib/verdict.ts +0 -23
  416. package/src/view/app/shared.ts +0 -8
  417. /package/dist/report/{react → components/metric-views}/chart-math.d.ts +0 -0
  418. /package/dist/report/{react → components/metric-views}/chart-math.js +0 -0
  419. /package/dist/report/{text → components/metric-views}/plot.d.ts +0 -0
  420. /package/dist/report/{react → components/site-components}/PoweredBy.d.ts +0 -0
  421. /package/dist/report/{react → components/site-components}/PoweredBy.js +0 -0
  422. /package/dist/report/{text/layout.d.ts → model/text-layout.d.ts} +0 -0
  423. /package/dist/report/{text/layout.js → model/text-layout.js} +0 -0
  424. /package/dist/report/{types.js → model/types.js} +0 -0
  425. /package/src/report/{react → components/metric-views}/chart-math.test.ts +0 -0
  426. /package/src/report/{react → components/metric-views}/chart-math.ts +0 -0
  427. /package/src/report/{react → components/site-components}/PoweredBy.tsx +0 -0
  428. /package/src/report/{text/layout.ts → model/text-layout.ts} +0 -0
@@ -1,10 +1,10 @@
1
1
  ---
2
2
  title: "用 niceeval/results 直接读写结果数据"
3
3
  sidebarTitle: "结果数据 API"
4
- description: "报告积木脚下的数据层:openResults 把 .niceeval/ 的落盘 artifact parse 成「实验 → 结果快照 → eval → attempt」的类型化层次,createResultsWriter 把别家结果写成 NiceEval 格式,copySnapshots 负责发布瘦身。"
4
+ description: "报告积木脚下的数据层:openResults 把 .niceeval/ 的落盘 artifact parse 成「实验 → 结果快照 → 评估 → attempt」的类型化层次,createResultsWriter 把别家结果写成 NiceEval 格式,copySnapshots 负责发布瘦身。"
5
5
  ---
6
6
 
7
- [自定义报告](/zh/how-to/custom-reports)的积木——指标、计算函数、双面组件——脚下还有一层:`niceeval/results`,落盘 artifact 的 parser。官方两扇门和全部报告积木读的都是这一层,没有私有数据通道;报告表达不了的口径,下到这层直接拿数据算。
7
+ [自定义报告](/zh/tutorials/custom-reports)的积木——指标、计算函数、双面组件——脚下还有一层:`niceeval/results`,落盘 artifact 的 parser。官方两扇门和全部报告积木读的都是这一层,没有私有数据通道;报告表达不了的口径,下到这层直接拿数据算。
8
8
 
9
9
  什么时候下到这层:
10
10
 
@@ -16,7 +16,7 @@ description: "报告积木脚下的数据层:openResults 把 .niceeval/ 的落
16
16
 
17
17
  ## 读:`openResults`
18
18
 
19
- 输入是 `.niceeval/` 目录(或 `copySnapshots` 产出的结果根目录,同一种布局),输出是四层数据:**实验 → 结果快照(单次跑的实验)→ eval → attempt**。你从此不碰路径、不判断文件存在性、不解析 JSON:
19
+ 输入是 `.niceeval/` 目录(或 `copySnapshots` 产出的结果根目录,同一种布局),输出是四层数据:**实验 → 结果快照(单次跑的实验)→ 评估 → attempt**。你从此不碰路径、不判断文件存在性、不解析 JSON:
20
20
 
21
21
  ```typescript
22
22
  import { openResults } from "niceeval/results";
@@ -51,7 +51,7 @@ snap.producer; // { name: "niceeval", version: "0.4.6" } ——
51
51
  snap.schemaVersion; // 结果格式版本
52
52
  ```
53
53
 
54
- **第三层,eval**——这次实验里的每道题,attempt(重试历史)挂在题下面:
54
+ **第三层,评估**——这次实验里的每道题,attempt(重试历史)挂在题下面:
55
55
 
56
56
  ```typescript
57
57
  for (const ev of snap.evals) {
@@ -134,7 +134,7 @@ for (const s of results.skipped) {
134
134
 
135
135
  ## 选快照:`results.latest()`
136
136
 
137
- 多数场景先回答「现在什么水位」,选择器替你挑「每个实验最新一次」——这也是默认报告的口径。返回的是一个 **Selection**,快照和警告绑在一起走:
137
+ 多数场景先回答「每个实验现在的最新结果是什么」,选择器替你挑「每个实验最新一次」——这也是默认报告的口径。返回的是一个 **Scope**,快照和警告绑在一起走:
138
138
 
139
139
  ```typescript
140
140
  const latest = results.latest({
@@ -158,9 +158,9 @@ latest.warnings[0];
158
158
  // }
159
159
  ```
160
160
 
161
- 字段供程序判断——CI 里「覆盖缩水就 fail」直接判 `covered < total`,不解析文本;`message` 是渲染好的英文句子,要展示就原样打。渲染与否在你,缺口永远被算出来。警告不止这一种:快照落后于 Selection 中最新的落盘进 `stale-snapshot`、选中的快照没收尾(进程中断)进 `unfinished-snapshot`,每种都带 `kind`、可判断的结构化字段和渲染好的 `message`。
161
+ 字段供程序判断——CI 里「覆盖缩水就 fail」直接判 `covered < total`,不解析文本;`message` 是渲染好的英文句子,要展示就原样打。渲染与否在你,缺口永远被算出来。警告不止这一种:快照落后于 Scope 中最新的落盘进 `stale-snapshot`、选中的快照没收尾(进程中断)进 `unfinished-snapshot`,每种都带 `kind`、可判断的结构化字段和渲染好的 `message`。
162
162
 
163
- Selection 是[报告积木](/zh/how-to/custom-reports)和下文 `copySnapshots` 的通用输入:收 `Selection` 时 warnings 随行(`RunOverview` 之类的组件会如实展示),手工挑的 `Snapshot[]` 数组照收。微调官方口径不用降级成裸数组:`latest.filter((s) => s.experimentId !== "compare/broken")` 返回新 Selection——快照被删减,warnings 修剪到幸存的实验,provenance 不丢。`filter` 只做删减;「换成该实验上一个完整快照」这类**替换式**重挑不是它的事,回到 `exp.snapshots` 自己拿——手工挑的数组没有挑选过程,自然没有 warnings 可带,也如实。
163
+ Scope 是[报告积木](/zh/tutorials/custom-reports)和下文 `copySnapshots` 的通用输入:收 `Scope` 时 warnings 随行(`ScopeWarnings` 组件会如实展示),手工挑的 `Snapshot[]` 数组照收。微调官方口径不用降级成裸数组:`latest.filter((s) => s.experimentId !== "compare/broken")` 返回新 Scope——快照被删减,warnings 修剪到幸存的实验,provenance 不丢。`filter` 只做删减;「换成该实验上一个完整快照」这类**替换式**重挑不是它的事,回到 `exp.snapshots` 自己拿——手工挑的数组没有挑选过程,自然没有 warnings 可带,也如实。
164
164
 
165
165
  ## 一个真实脚本:分布不是折叠
166
166
 
@@ -184,9 +184,9 @@ for (const exp of results.experiments) {
184
184
  }
185
185
  ```
186
186
 
187
- 即使在这条最深的路径上也不碰磁盘布局:路径拼接、存在性、版本过滤、快照切分全被库消化。要把这份分布摆进报告页,用 [`defineComponent`](/zh/how-to/custom-reports) 包一个双面组件即可。
187
+ 即使在这条最深的路径上也不碰磁盘布局:路径拼接、存在性、版本过滤、快照切分全被库消化。要把这份分布摆进报告页,用 [`defineComponent`](/zh/tutorials/custom-reports) 包一个双面组件即可。
188
188
 
189
- 一条跨快照累计时的义务:NiceEval 默认把上一轮已有确定判定(passed / failed)、且 eval 代码和配置没变的结果携带合入新快照(`--force` 全部重跑),同一个 attempt 因此可能存在于多份落盘。携带条目不是空壳:它带着原快照的 `startedAt`(身份锚)与 `artifactBase`(指向原快照 attempt 目录的相对路径),懒加载按候选顺序回退——先本快照的 attempt 目录,再 `artifactBase` 指向的原快照目录(原快照被清理后如实返回 `null`);`ref` 指向条目所在的落盘,即携带入的那份新快照。身份键 `(experimentId, evalId, attempt, startedAt)` 的四个字段都在数据上——前两个是 attempt 的直达字段,序号与 `startedAt` 在 `attempt.result` 上。reader 忠实反映这份重复;跨快照聚合前用 `dedupeAttempts` 按身份键去重,重复保留最新快照里的那份——报告积木的计算函数内置这条,自己写脚本时记得过一遍:
189
+ 一条跨快照累计时的义务:NiceEval 默认把上一轮已有确定判定(passed / failed)、且评估用例代码和配置没变的结果携带合入新快照(`--force` 全部重跑),同一个 attempt 因此可能存在于多份落盘。携带条目不是空壳:它带着原快照的 `startedAt`(身份锚)与 `artifactBase`(指向原快照 attempt 目录的相对路径),懒加载按候选顺序回退——先本快照的 attempt 目录,再 `artifactBase` 指向的原快照目录(原快照被清理后如实返回 `null`);`ref` 指向条目所在的落盘,即携带入的那份新快照。身份键 `(experimentId, evalId, attempt, startedAt)` 的四个字段都在数据上——前两个是 attempt 的直达字段,序号与 `startedAt` 在 `attempt.result` 上。reader 忠实反映这份重复;跨快照聚合前用 `dedupeAttempts` 按身份键去重,重复保留最新快照里的那份——报告积木的计算函数内置这条,自己写脚本时记得过一遍:
190
190
 
191
191
  ```typescript
192
192
  import { dedupeAttempts } from "niceeval/results";
@@ -223,7 +223,7 @@ for (const r of convertedResults) {
223
223
  await writer.finish(); // 给每个快照补 completedAt,没有任何收尾聚合
224
224
  ```
225
225
 
226
- `writer.snapshot()` 就是读取面「实验 → 快照」层次的镜像:转多个 experiment 就开多个快照目录,experimentId / agent / model / startedAt 这些快照级元数据在这里声明一次,不用塞进每条 attempt;可选的 `knownEvalIds`(该实验已知的 eval 并集)也在这里声明——它是残缺检测的分母,转换只覆盖部分题目时如实交代全集,下游的覆盖警告就能算出来(`copySnapshots` 发布时会自动补记这个字段,见下文)。转完的目录就是标准结果目录:`niceeval show` / `niceeval view` 直接能看,报告积木直接能算,不用抄格式文档;`producer` 会原样出现在读取面的 `snap.producer` 上。**每个文件恰好写入一次**是写入面的核心承诺:`snapshot.json` 开跑即写、收尾只补 `completedAt`;`result.json` 与 artifact 随 attempt 完成落盘。进程中断只丢未完成的 attempt,已完成的判定与 artifact 已经在盘上——真正「有 attempt 落盘却没有 `snapshot.json`」的极端情况才归 `skipped("incomplete")`,未收尾但元数据齐全的快照能正常读,只带一条警告。
226
+ `writer.snapshot()` 就是读取面「实验 → 快照」层次的镜像:转多个 experiment 就开多个快照目录,experimentId / agent / model / startedAt 这些快照级元数据在这里声明一次,不用塞进每条 attempt;可选的 `knownEvalIds`(该实验已知的评估用例并集)也在这里声明——它是残缺检测的分母,转换只覆盖部分题目时如实交代全集,下游的覆盖警告就能算出来(`copySnapshots` 发布时会自动补记这个字段,见下文)。转完的目录就是标准结果目录:`niceeval show` / `niceeval view` 直接能看,报告积木直接能算,不用抄格式文档;`producer` 会原样出现在读取面的 `snap.producer` 上。**每个文件恰好写入一次**是写入面的核心承诺:`snapshot.json` 开跑即写、收尾只补 `completedAt`;`result.json` 与 artifact 随 attempt 完成落盘。进程中断只丢未完成的 attempt,已完成的判定与 artifact 已经在盘上——真正「有 attempt 落盘却没有 `snapshot.json`」的极端情况才归 `skipped("incomplete")`,未收尾但元数据齐全的快照能正常读,只带一条警告。
227
227
 
228
228
  ## 发布:`copySnapshots`
229
229
 
@@ -240,18 +240,18 @@ await copySnapshots(results.latest(), "site-data/run", {
240
240
  // 读 o11y 的指标就把它带上,不然渲染成「—」
241
241
  ```
242
242
 
243
- 第一个参数收 `Selection` 或手工挑的 `Snapshot[]`——和报告积木同一个输入约定。`artifacts` 的合法值是 `"events" | "trace" | "o11y" | "agentSetup" | "diff" | "sources"`;缺省带除 `diff` 外的五类。目标目录已存在且非空时报错,不静默覆盖——发布脚本要幂等就自己先清目标目录。
243
+ 第一个参数收 `Scope` 或手工挑的 `Snapshot[]`——和报告积木同一个输入约定。`artifacts` 的合法值是 `"events" | "trace" | "o11y" | "agentSetup" | "diff" | "sources"`;缺省带除 `diff` 外的五类。目标目录已存在且非空时报错,不静默覆盖——发布脚本要幂等就自己先清目标目录。
244
244
 
245
245
  复制开始前,NiceEval 会规划全部目标文件并检查序列化后的大小。任一文件超过固定的 50 MiB,整次复制在创建目标目录前失败,错误会列出路径、实际大小和处理建议。你可以从 `artifacts` 排除那类证据;如果是旧版本留下的超大 events / trace,用当前版本重跑后再发布。这个检查既覆盖没有逐值截断的源码 / diff,也覆盖单值都正常但累计过大的 JSON,避免直到 `git push` 才撞上 Git host 的单文件限制。
246
246
 
247
- 大小预检只决定整次复制成功或失败,不会从一个超大文件中间删内容。复制忠实于源:artifact 按原字节复制,不重新序列化、不改写。唯一随行补记的是挑选时的**覆盖事实**:`partial-coverage` 警告的分母是实验的历史并集,而发布目录没有历史——所以每个复制出的快照带上 `knownEvalIds`(复制时刻该实验已知的 eval 并集),reader 端把它并进 `exp.evalIds` 的计算(取本地历史与快照携带值的并集)。发布目录上重新 `openResults().latest()`,残缺警告被同一套机制重新算出来,不靠发布者转述。复制出的目录就是标准结果目录,`niceeval view --results <目录>` 直接能看;要让报告站随 push 自动更新,workflow 见[通过 CI 发布报告](/zh/how-to/publish-report)。
247
+ 大小预检只决定整次复制成功或失败,不会从一个超大文件中间删内容。复制忠实于源:artifact 按原字节复制,不重新序列化、不改写。唯一随行补记的是挑选时的**覆盖事实**:`partial-coverage` 警告的分母是实验的历史并集,而发布目录没有历史——所以每个复制出的快照带上 `knownEvalIds`(复制时刻该实验已知的评估用例并集),reader 端把它并进 `exp.evalIds` 的计算(取本地历史与快照携带值的并集)。发布目录上重新 `openResults().latest()`,残缺警告被同一套机制重新算出来,不靠发布者转述。复制出的目录就是标准结果目录,`niceeval view --results <目录>` 直接能看;要让报告站随 push 自动更新,workflow 见[通过 CI 发布报告](/zh/tutorials/publish-report)。
248
248
 
249
249
  ## 分层速览
250
250
 
251
251
  | 层 | 入口 | 回答 |
252
252
  | --- | --- | --- |
253
253
  | 官方两扇门 | `niceeval show` / `niceeval view` | 零代码看官方摆法 |
254
- | 报告积木 | [自定义报告](/zh/how-to/custom-reports)、[报告组件](/zh/reference/report-components) | 自己的口径与摆法 |
254
+ | 报告积木 | [自定义报告](/zh/tutorials/custom-reports)、[报告组件](/zh/reference/report-components) | 自己的口径与摆法 |
255
255
  | 结果数据 API(本页) | `niceeval/results` | 折叠表达不了的算法、接自己的系统、读写格式本身 |
256
256
 
257
257
  每层都建立在下一层之上,同一份落盘 artifact 是唯一事实来源——上层的派生物删了随时可重算。
@@ -1,14 +1,14 @@
1
1
  ---
2
- title: "保留沙箱现场排查问题"
3
- sidebarTitle: "保留沙箱现场"
4
- description: "用 --keep-sandbox 把失败 Attempt 的沙箱保留成可随时唤醒的现场,用 niceeval sandbox enter 进去手动排查,用 sandbox list / stop 查看和清理。"
2
+ title: "保留 Sandbox 现场排查问题"
3
+ sidebarTitle: "保留 Sandbox 现场"
4
+ description: "用 --keep-sandbox 把失败 Attempt Sandbox 保留成可随时唤醒的现场,用 niceeval sandbox enter 进去手动排查,用 sandbox list / stop 查看和清理。"
5
5
  ---
6
6
 
7
- 沙箱默认在每个 Attempt 结束后销毁,排查依据是落盘的 artifact:`niceeval show` 能看到判定、断言、diff 和事件流。大多数问题到这里就够了——完整的排查路线见 [Debug 手册](/zh/troubleshooting/debugging)。
7
+ Sandbox 默认在每个 Attempt 结束后销毁,排查依据是落盘的 artifact:`niceeval show` 能看到判定、断言、diff 和事件流。大多数问题到这里就够了——完整的排查路线见 [Debug 手册](/zh/troubleshooting/debugging)。
8
8
 
9
9
  但有些问题只能进活的环境里看:
10
10
 
11
- - **环境起不来**——setup 阶段装依赖失败、agent CLI 启动不了。这时 agent 还没开始跑,事件流是空的,最快的办法是进沙箱手动重跑一遍安装命令。
11
+ - **环境起不来**——setup 阶段装依赖失败、agent CLI 启动不了。这时 agent 还没开始跑,事件流是空的,最快的办法是进 Sandbox 手动重跑一遍安装命令。
12
12
  - **改动落在 `git diff` 之外**——全局装了什么包、`$HOME` 下写了什么配置、`PATH` 实际是什么,artifact 里没有。
13
13
  - **重跑太慢**——冷启动加安装要几分钟,想逐条验证猜测时,留着现场比每次重跑快得多。
14
14
 
@@ -19,9 +19,9 @@ npx niceeval exp local onboarding/tool-first --keep-sandbox # 等价 --ke
19
19
  npx niceeval exp local onboarding/tool-first --keep-sandbox=all # 通过的也保留
20
20
  ```
21
21
 
22
- `--keep-sandbox` 是 `niceeval exp` 的运行参数,两档:`failed`(缺省值)保留判定为 `failed` 或 `errored` 的 Attempt(包括超时打断的);`all` 连通过的也保留——调 setup 钩子、核对通过环境的真实状态时用它,不用故意弄挂一条 eval。不带这个参数时全部销毁。
22
+ `--keep-sandbox` 是 `niceeval exp` 的运行参数,两档:`failed`(缺省值)保留判定为 `failed` 或 `errored` 的 Attempt(包括超时打断的);`all` 连通过的也保留——调 setup Hook、核对通过环境的真实状态时用它,不用故意弄挂一条评估用例。不带这个参数时全部销毁。
23
23
 
24
- 运行结束后,摘要里会列出保留了哪些沙箱、怎么进去:
24
+ 运行结束后,摘要里会列出保留了哪些 Sandbox、怎么进去:
25
25
 
26
26
  ```text
27
27
  Kept sandboxes (1)
@@ -30,11 +30,11 @@ Kept sandboxes (1)
30
30
  Stop them with: niceeval sandbox stop --all
31
31
  ```
32
32
 
33
- 每行给三样东西:Attempt 定位符(用 `niceeval show @1x7f3q9k` 看落盘证据)、沙箱实例 id、进入现场的命令。保留下来的沙箱不会一直跑着烧资源——Docker 容器停在磁盘上,E2B 微 VM 暂停计费,Vercel 保存文件系统。`niceeval sandbox enter` 会先唤醒再进入,在 workdir 打开 shell;退出 shell 后现场自动回到休眠(想让它保持运行,加 `--leave-running`)。进去之后就是这次 Attempt 跑完时的环境,可以手动执行命令、翻文件、复现失败。
33
+ 每行给三样东西:Attempt 定位符(用 `niceeval show @1x7f3q9k` 看落盘证据)、Sandbox 实例 id、进入现场的命令。保留下来的 Sandbox 不会一直跑着烧资源——Docker 容器停在磁盘上,E2B 微 VM 暂停计费,Vercel 保存文件系统。`niceeval sandbox enter` 会先唤醒再进入,在 workdir 打开 shell;退出 shell 后现场自动回到休眠(想让它保持运行,加 `--leave-running`)。进去之后就是这次 Attempt 跑完时的环境,可以手动执行命令、翻文件、复现失败。
34
34
 
35
35
  ## 查看和清理
36
36
 
37
- 保留下来的沙箱逐条记录在 `.niceeval/sandboxes/` 里,用 `niceeval sandbox` 管理:
37
+ 保留下来的 Sandbox 逐条记录在 `.niceeval/sandboxes/` 里,用 `niceeval sandbox` 管理:
38
38
 
39
39
  ```bash
40
40
  niceeval sandbox list # 列出保留的沙箱和现场状态
@@ -43,7 +43,7 @@ niceeval sandbox stop a3f9c2d1 # 销毁指定沙箱(id 可以只写唯一
43
43
  niceeval sandbox stop --all # 全部销毁
44
44
  ```
45
45
 
46
- `stop` 是幂等的:沙箱已经不在了(手动删过、云端过期)不算错误,只会把记录移掉并说明。如果 provider 销毁失败,命令会保留记录并返回错误,方便稍后重试,不会把仍活着的资源从列表里藏掉。忘了清也有提醒——下次运行开始时,如果还有上次保留的沙箱,会打一行提示。
46
+ `stop` 是幂等的:Sandbox 已经不在了(手动删过、云端过期)不算错误,只会把记录移掉并说明。如果 provider 销毁失败,命令会保留记录并返回错误,方便稍后重试,不会把仍活着的资源从列表里藏掉。忘了清也有提醒——下次运行开始时,如果还有上次保留的 Sandbox,会打一行提示。
47
47
 
48
48
  ## 各 Provider 的差别
49
49
 
@@ -54,4 +54,4 @@ niceeval sandbox stop --all # 全部销毁
54
54
 
55
55
  ## 边界
56
56
 
57
- 保留的沙箱只用来排查,不能续跑或重新评分;判定、断言、diff 这些结论仍以 artifact 为准。查看 artifact 的方法见[查看结果](/zh/how-to/viewing-results)。
57
+ 保留的 Sandbox 只用来排查,不能续跑或重新评分;判定、断言、diff 这些结论仍以 artifact 为准。查看 artifact 的方法见[查看结果](/zh/tutorials/viewing-results)。
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: "排查失败与复盘历史运行"
3
3
  sidebarTitle: "Debug 手册"
4
- description: "一份按场景组织的排查手册:断言失败怎么定位、环境错误怎么进沙箱、agent 改了什么怎么看、旧的运行怎么翻出来复盘——每一步都有命令顺序和输出示例。"
4
+ description: "一份按场景组织的排查手册:断言失败怎么定位、环境错误怎么进 Sandbox、agent 改了什么怎么看、旧的运行怎么翻出来复盘——每一步都有命令顺序和输出示例。"
5
5
  ---
6
6
 
7
7
  跑完一次 `niceeval exp`,失败的 Attempt 都带一个 `@` 开头的定位符(如 `@1qrdcfq8`)。它出现在运行摘要、CI 日志和报告里,定位符本身不会过期——只要 `.niceeval/` 里对应的结果快照还在,今天的定位符下周还能用同一条命令打开同一次 Attempt。所有排查都从它开始。
@@ -34,7 +34,7 @@ timing: sandbox.queue 0.2s · sandbox.create 5.6s · sandbox.setup 3.5s · agent
34
34
  changes: 2 files changed by agent · M manager_decisions.json · A notes/decision-log.md
35
35
 
36
36
  available:
37
- niceeval show @1qrdcfq8 --eval
37
+ niceeval show @1qrdcfq8 --source
38
38
  niceeval show @1qrdcfq8 --execution
39
39
  niceeval show @1qrdcfq8 --timing
40
40
  niceeval show @1qrdcfq8 --diff
@@ -46,10 +46,10 @@ available:
46
46
 
47
47
  排查顺序是「哪条断言挂了 → agent 当时做了什么 → 它到底改了什么」。
48
48
 
49
- **1. 把断言放回源码。** `--eval` 显示运行时保存的那份 eval 源码(不是你工作区里可能已经改过的版本),失败的断言直接标在对应行上;`t.send(...)` 的调用行标出它产生的那一轮——轮标签(`s1/t1`,与 `--execution` / `--timing` 用同一套)、这轮成没成、花了多久:
49
+ **1. 把断言放回源码。** `--source` 显示运行时保存的那份评估用例源码(不是你工作区里可能已经改过的版本),失败的断言直接标在对应行上;`t.send(...)` 的调用行标出它产生的那一轮——轮标签(`s1/t1`,与 `--execution` / `--timing` 用同一套)、这轮成没成、花了多久:
50
50
 
51
51
  ```text
52
- $ niceeval show @1qrdcfq8 --eval
52
+ $ niceeval show @1qrdcfq8 --source
53
53
  21✓ await t.send("Review the proposals and record your decision…");
54
54
  s1/t1 · completed · 22.4s
55
55
  38 for (const [issue, label] of Object.entries(expected)) {
@@ -80,6 +80,20 @@ TURN s1/t1 · completed · 22.4s · 12.4k tok · $0.02
80
80
 
81
81
  对话按轮分段,每轮头行给出编号(`s1/t1`)、状态、耗时和用量——这个编号和 `--diff`、`--timing` 里的轮次标签是同一套,能互相对照。
82
82
 
83
+ 不想通读全文时,接 `grep` 定向查。列出这次 Attempt 用过哪些工具、各多少次:
84
+
85
+ ```text
86
+ $ niceeval show @1qrdcfq8 --execution | grep "TOOL ·" | sort | uniq -c
87
+ 5 TOOL · command_execution
88
+ 2 TOOL · file_change
89
+ ```
90
+
91
+ 想确认它有没有跑过某条命令、有没有提到某个文件,直接搜关键词:
92
+
93
+ ```bash
94
+ niceeval show @1qrdcfq8 --execution | grep proposals
95
+ ```
96
+
83
97
  **3. 看它到底改了什么。** `--diff` 只显示 **agent 自己改动的文件**——你上传的起始文件、跑完后写入的验证材料不会混在里面,所以列表里的每一行都真的是 agent 干的:
84
98
 
85
99
  ```text
@@ -104,7 +118,7 @@ M manager_decisions.json · changed in s1/t1, s1/t2
104
118
 
105
119
  到这里通常能下结论:是任务描述有歧义、agent 理解错了,还是断言本身写得太死。
106
120
 
107
- **要看文件本身,而不只是改动?** 落盘的证据刻意不保存整个工作区——`--diff` 只有 agent 改过的文件,agent 该写没写的文件、你上传的起始材料、setup 装出来的东西都不在里面。想看它们的实际内容,进活现场:重跑这一条 eval 加 `--keep-sandbox`(`failed` 的 Attempt 同样会保留,不只是环境错误),用下面场景二的方式进沙箱,workdir 里就是这次跑完时的完整文件树。
121
+ **要看文件本身,而不只是改动?** 落盘的证据刻意不保存整个工作区——`--diff` 只有 agent 改过的文件,agent 该写没写的文件、你上传的起始材料、setup 装出来的东西都不在里面。想看它们的实际内容,进活现场:重跑这一条评估用例加 `--keep-sandbox`(`failed` 的 Attempt 同样会保留,不只是环境错误),用下面场景二的方式进 Sandbox,workdir 里就是这次跑完时的完整文件树。
108
122
 
109
123
  ## 场景二:环境错误(errored)——agent 根本没跑起来
110
124
 
@@ -126,9 +140,9 @@ timing: sandbox.queue 1.2s · sandbox.create 2m 6s ✗ failed here
126
140
 
127
141
  `phase` 直接告诉你死在哪一步,而且决定了下一步走哪条路:
128
142
 
129
- **`sandbox.create` 失败——沙箱根本没创建出来,没有现场可留。** 这类错误(配额、限流、凭据、镜像 / 模板不存在)在你自己的机器和账号侧排查:核对 API key 和配额、降低 `--max-concurrency`、确认镜像 / 模板名。示例里的 rate-limit 就属于这类,重跑加 `--keep-sandbox` 只会原地再死一次。
143
+ **`sandbox.create` 失败——Sandbox 根本没创建出来,没有现场可留。** 这类错误(配额、限流、凭据、镜像 / 模板不存在)在你自己的机器和账号侧排查:核对 API key 和配额、降低 `--max-concurrency`、确认镜像 / 模板名。示例里的 rate-limit 就属于这类,重跑加 `--keep-sandbox` 只会原地再死一次。
130
144
 
131
- **`sandbox.setup` / `agent.setup` / `eval.run` 失败——沙箱活过,值得留现场。** 装依赖失败、agent CLI 起不来、跑到一半超时,这类问题事件流往往是空的,落盘证据帮不上忙,最快的办法是留住现场进去手动重跑一遍出错的命令:
145
+ **`sandbox.setup` / `agent.setup` / `eval.run` 失败——Sandbox 活过,值得留现场。** 装依赖失败、agent CLI 起不来、跑到一半超时,这类问题事件流往往是空的,落盘证据帮不上忙,最快的办法是留住现场进去手动重跑一遍出错的命令:
132
146
 
133
147
  ```bash
134
148
  # 只重跑这一条 eval,失败时保留沙箱
@@ -142,11 +156,11 @@ Kept sandboxes (1)
142
156
  Stop them with: niceeval sandbox stop --all
143
157
  ```
144
158
 
145
- `niceeval sandbox enter a3f9c2d1` 会唤醒现场并在 workdir 打开 shell——手动执行安装命令看真实报错、翻 `$HOME` 下的配置、检查 `PATH`,这些都在 artifact 之外,只有活现场能回答;退出 shell 后现场自动回到休眠,不白烧资源。保留策略、各 provider 的差别见[保留沙箱现场](/zh/troubleshooting/debug-sandbox)。
159
+ `niceeval sandbox enter a3f9c2d1` 会唤醒现场并在 workdir 打开 shell——手动执行安装命令看真实报错、翻 `$HOME` 下的配置、检查 `PATH`,这些都在 artifact 之外,只有活现场能回答;退出 shell 后现场自动回到休眠,不白烧资源。保留策略、各 provider 的差别见[保留 Sandbox 现场](/zh/troubleshooting/debug-sandbox)。
146
160
 
147
- ## 查看和清理留下的沙箱
161
+ ## 查看和清理留下的 Sandbox
148
162
 
149
- 保留下来的沙箱不会一直烧资源:Docker 容器停驻在磁盘上,E2B 微 VM 暂停计费,进入时自动唤醒。用 `niceeval sandbox` 管理:
163
+ 保留下来的 Sandbox 不会一直烧资源:Docker 容器停驻在磁盘上,E2B 微 VM 暂停计费,进入时自动唤醒。用 `niceeval sandbox` 管理:
150
164
 
151
165
  ```text
152
166
  $ niceeval sandbox list
@@ -168,9 +182,9 @@ niceeval sandbox stop --all
168
182
 
169
183
  每次运行都会在 `.niceeval/<实验>/<时间戳>/` 下留一份完整的结果快照,判定、断言、事件流、diff 都在里面,**不会被下一次运行覆盖**。复盘有三个入口:
170
184
 
171
- **用旧定位符直接打开。** 从上周的终端记录、CI 日志或报告里复制 `@` 定位符,`niceeval show @<定位符>` 照常工作,上面的 `--eval` / `--execution` / `--diff` 全部可用——包括那份运行时的 eval 源码,哪怕你后来把 eval 改了。
185
+ **用旧定位符直接打开。** 从上周的终端记录、CI 日志或报告里复制 `@` 定位符,`niceeval show @<定位符>` 照常工作,上面的 `--source` / `--execution` / `--diff` 全部可用——包括那份运行时的评估用例源码,哪怕你后来把评估用例改了。
172
186
 
173
- **按实验回看当前水位。** 不记得定位符时,从实验入手:
187
+ **按实验回看现在的判定。** 不记得定位符时,从实验入手:
174
188
 
175
189
  ```bash
176
190
  niceeval show --exp compare/bub # 这个实验每道题现在的判定
@@ -179,6 +193,15 @@ niceeval show memory/swelancer --exp compare/bub # 收窄到某道题
179
193
 
180
194
  列表里每道题、每次 Attempt 都带定位符,接着往深处钻就回到上面的场景一 / 场景二。
181
195
 
196
+ **同一个检查刷一批 Attempt。** 从实验列表里复制定位符,套一层循环。比如核对这几次 Attempt 里谁调用过 `file_change`:
197
+
198
+ ```bash
199
+ for loc in @1qrdcfq8 @1x7f3q8a @18c1m2qx; do
200
+ echo "== $loc"
201
+ niceeval show $loc --execution | grep "TOOL · file_change"
202
+ done
203
+ ```
204
+
182
205
  **在浏览器里翻。** 复盘一批失败、对比多次 Attempt 时,网页比终端顺手:
183
206
 
184
207
  ```bash
@@ -200,13 +223,14 @@ niceeval view --results site-data/run
200
223
 
201
224
  | 症状 | 命令顺序 |
202
225
  |---|---|
203
- | 断言挂了,不知道为什么 | `show @loc` → `show @loc --eval` |
226
+ | 断言挂了,不知道为什么 | `show @loc` → `show @loc --source` |
204
227
  | 想知道 agent 当时做了什么 | `show @loc --execution` |
228
+ | 想确认有没有调用过某个工具 / 搜对话关键词 | `show @loc --execution \| grep "TOOL ·" \| sort \| uniq -c` / `\| grep <关键词>` |
205
229
  | 想确认 agent 改了哪些文件 | `show @loc --diff` → `--diff=<path>` |
206
230
  | 哪一步慢 / 超时死在哪 | `show @loc`(看 `timing:` 行)→ `show @loc --timing` |
207
- | 沙箱创建就失败(配额 / 凭据 / 镜像) | `show @loc` 看 error 的 code 与 cause → 查账号配额、核对凭据、降 `--max-concurrency`(没有现场可留) |
208
- | 装依赖失败、CLI 起不来、跑一半超时 | 重跑该 eval 加 `--keep-sandbox` → `niceeval sandbox enter <id>` |
231
+ | Sandbox 创建就失败(配额 / 凭据 / 镜像) | `show @loc` 看 error 的 code 与 cause → 查账号配额、核对凭据、降 `--max-concurrency`(没有现场可留) |
232
+ | 装依赖失败、CLI 起不来、跑一半超时 | 重跑该评估用例加 `--keep-sandbox` → `niceeval sandbox enter <id>` |
209
233
  | 想看文件实际内容(agent 没改的、起始材料、`$HOME`) | 重跑加 `--keep-sandbox`(failed 也留)→ `sandbox enter` 进 workdir 看 |
210
- | 留了哪些沙箱、清理 | `sandbox list` → `sandbox stop <id>` / `--all` |
234
+ | 留了哪些 Sandbox、清理 | `sandbox list` → `sandbox stop <id>` / `--all` |
211
235
  | 复盘上周那次失败 | 翻出旧定位符 → `show @loc`;不记得就 `show --exp <实验>` |
212
236
  | 一批失败一起看 | `niceeval view` → Attempt 详情 → Copy fix prompt |
@@ -1,14 +1,14 @@
1
1
  ---
2
- title: " AI Eval 并自主优化"
3
- sidebarTitle: "AI 反馈闭环"
4
- description: "让 coding agent 读取随包文档,用 bash 运行实验、下钻结果、定位失败并持续迭代,最后用全量重跑确认收敛。"
2
+ title: " Coding Agent 编写评估用例并迭代程序"
3
+ sidebarTitle: "Coding Agent 反馈闭环"
4
+ description: "让 Coding Agent 读取随包文档,用 Bash 运行实验、查看结果、定位失败并持续迭代,最后通过全量重跑确认结果。"
5
5
  ---
6
6
 
7
- Coding agent 可以独立完成两类工作:根据需求编写 NiceEval 配置与 Eval,以及根据运行结果持续改进被测程序。整个过程只需要仓库文件和 bash,不依赖浏览器,也不需要额外安装 Skill。
7
+ Coding Agent 可以根据需求编写 NiceEval 配置与评估用例,也可以根据运行结果持续改进被测程序。整个过程只需要仓库文件和 Bash,不依赖浏览器或额外的 Skill。
8
8
 
9
- ## 先让 AI 读安装版本的文档
9
+ ## 读取安装版本的文档
10
10
 
11
- NiceEval 把中文文档发布在 npm 包的 `docs-site/zh/` 目录,并在包根提供只给 AI 使用的 `INDEX.md`。AI 应该先读取 `node_modules/niceeval/INDEX.md`,再由索引进入当前任务需要的页面,而不是依赖训练数据或网上另一个版本的示例。这样 API、CLI 和安装版本始终一致;文档重组时也只需要更新随包索引。
11
+ NiceEval 把中文文档发布在 npm 包的 `docs-site/zh/` 目录,并在包根提供供 Coding Agent 使用的 `INDEX.md`。Coding Agent 应先读取 `node_modules/niceeval/INDEX.md`,再从索引进入当前任务需要的页面,不依赖训练数据或其它版本的在线示例。这样可以保证 API、CLI 与安装版本一致。
12
12
 
13
13
  `npx niceeval init` 会初始化配置,并把一段托管指引写进项目的 `AGENTS.md`。如果项目只有 `CLAUDE.md`,则写入 `CLAUDE.md`;两份文件都不存在时,新建 `AGENTS.md`。升级 NiceEval 后再运行一次 `init`,即可刷新托管区块。
14
14
 
@@ -25,15 +25,15 @@ AI 通常按任务选择这些入口:
25
25
  | 任务 | 随包文档 |
26
26
  | --- | --- |
27
27
  | 初始化项目 | `docs-site/zh/tutorials/quickstart.mdx` |
28
- | 编写 Eval | `docs-site/zh/explanation/evals.mdx` |
29
- | 定义实验 | `docs-site/zh/how-to/write-experiment.mdx` |
28
+ | 编写评估用例 | `docs-site/zh/explanation/evals.mdx` |
29
+ | 定义实验 | `docs-site/zh/tutorials/write-experiment.mdx` |
30
30
  | 连接被测 Agent | `docs-site/zh/explanation/adapter.mdx` |
31
- | 配置 Sandbox | `docs-site/zh/how-to/sandbox-agent.mdx` |
32
- | 解释运行结果 | `docs-site/zh/how-to/viewing-results.mdx` |
31
+ | 配置 Sandbox | `docs-site/zh/tutorials/sandbox-agent.mdx` |
32
+ | 解释运行结果 | `docs-site/zh/tutorials/viewing-results.mdx` |
33
33
 
34
34
  ## 用 bash 完成一次反馈闭环
35
35
 
36
- 闭环的目标不是“把命令跑绿”,而是形成并验证一个假设:失败来自被测程序、Eval,还是运行环境。推荐按下面的顺序迭代。
36
+ 闭环的目标不是”把命令跑绿”,而是形成并验证一个假设:失败来自被测程序、评估用例,还是运行环境。推荐按下面的顺序迭代。
37
37
 
38
38
  <Steps>
39
39
  <Step title="运行实验">
@@ -41,7 +41,7 @@ AI 通常按任务选择这些入口:
41
41
  npx niceeval exp local --output agent
42
42
  ```
43
43
 
44
- 先读取退出码:`0` 表示所有 Eval 通过;`1` 表示至少一个 Eval 失败或出错;`2` 表示 NiceEval 自身未能完成运行。退出码决定是否继续,控制台文本用于定位原因。
44
+ 先读取退出码:`0` 表示所有评估用例通过;`1` 表示至少一个评估用例失败或出错;`2` 表示 NiceEval 自身未能完成运行。退出码决定是否继续,控制台文本用于定位原因。
45
45
  </Step>
46
46
  <Step title="读取失败">
47
47
  ```bash
@@ -49,7 +49,7 @@ AI 通常按任务选择这些入口:
49
49
  npx niceeval show @1k2m9qtr
50
50
  ```
51
51
 
52
- 第一条命令显示当前各实验的通过率、成本、耗时,以及每个 Eval 的紧凑 Attempt locator——locator 本身就是证据入口,不在列表里编码证据可用性。第二条命令直接打开选中的 Attempt,页面末尾的 `available:` 只列出这个 Attempt 实际可用的证据命令。
52
+ 第一条命令显示当前各实验的通过率、成本、耗时,以及每个评估用例的紧凑 Attempt locator——locator 本身就是证据入口,不在列表里编码证据可用性。第二条命令直接打开选中的 Attempt,页面末尾的 `available:` 只列出这个 Attempt 实际可用的证据命令。
53
53
  </Step>
54
54
  <Step title="按问题读取证据">
55
55
  ```bash
@@ -59,7 +59,7 @@ AI 通常按任务选择这些入口:
59
59
 
60
60
  `--execution` 合并 AI 输出与 trace:标准事件流提供消息、thinking、tool call/result 和 Skill load;OTel 在能够关联时给同一节点补开始时间、耗时、父子关系和错误状态。没有 OTel 时步骤仍完整,只不显示时间。
61
61
 
62
- 不带证据 flag 时,`show @<id>` 是失败诊断首页。它先列出失败断言的 group、matcher、expected、received、原因和源码位置,再给执行、生命周期阶段耗时与文件变化摘要。AI 应该先读这一页;只有需要回答“为什么产生这个值”时,才继续打开对应证据。
62
+ 不带证据 flag 时,`show @<id>` 是失败诊断首页。它先列出失败断言的 group、matcher、expected、received、原因和源码位置,再给执行、生命周期阶段耗时与文件变化摘要。Coding Agent 应先读取这一页;需要追查值的来源时,再打开对应证据。
63
63
 
64
64
  ```text
65
65
  $ niceeval show @1k2m9qtr
@@ -96,7 +96,7 @@ AI 通常按任务选择这些入口:
96
96
 
97
97
  full eval source: …/weather/brooklyn/a2/sources.json
98
98
  available:
99
- niceeval show @1k2m9qtr --eval
99
+ niceeval show @1k2m9qtr --source
100
100
  niceeval show @1k2m9qtr --execution
101
101
  niceeval show @1k2m9qtr --timing
102
102
  ```
@@ -153,7 +153,7 @@ AI 通常按任务选择这些入口:
153
153
  full events: …/weather/brooklyn/a2/events.json
154
154
  ```
155
155
 
156
- diff 是被测 Agent 在 Sandbox 工作区造成的文件变化,不是 Eval 源码的新旧差异。只有 sandbox eval 才会收集到 diff——非 sandbox eval agent 确实没碰任何文件时,attempt 页的 `available:` 列表会省略 `--diff`。默认先给文件级摘要,避免把大段补丁塞进 Agent 上下文;`--diff=<文件>` 再展开单个文件,原始 artifact 路径始终保留:
156
+ diff 是被测 Agent 在 Sandbox 工作区造成的文件变化,不是评估用例源码的新旧差异。只有 Sandbox 评估用例才会收集到 diff——非 Sandbox 评估用例或 agent 确实没碰任何文件时,attempt 页的 `available:` 列表会省略 `--diff`。默认先给文件级摘要,避免把大段补丁塞进 Agent 上下文;`--diff=<文件>` 再展开单个文件,原始 artifact 路径始终保留:
157
157
 
158
158
  ```text
159
159
  $ niceeval show @1c3h6tbn --diff
@@ -169,13 +169,13 @@ AI 通常按任务选择这些入口:
169
169
 
170
170
  用这组输出检查信息是否足够:
171
171
 
172
- | 要回答的问题 | 入口 | 输出必须包含 |
172
+ | 诊断目标 | 入口 | 输出必须包含 |
173
173
  | --- | --- | --- |
174
- | 快速判断一次 Attempt 发生了什么 | `niceeval show @<id>` | Eval 断言、执行步骤、生命周期阶段耗时摘要、diff 摘要及各块可用性 |
175
- | Eval 实际检查了什么,哪条 gate / soft 为什么通过或失败 | `niceeval show @<id> --eval` | 运行时 Eval 源码、源码哈希、断言所在行、严重度、分数与原因 |
176
- | AI 做了什么、调用了什么 | `niceeval show @<id> --execution` | 消息、thinking、Skill load、工具调用与结果;有 OTel 时在同一节点附时间、父子关系和错误状态 |
177
- | 整个 Attempt 的时间花在哪里 | `niceeval show @<id> --timing` | lifecycle → hook/turn → shell → OTel 的统一时间树;出错的 Attempt 标出已知的最深失败节点 |
178
- | Sandbox 工作区文件变成什么 | `niceeval show @<id> --diff` | 文件摘要、增删行数、具体补丁和原始 diff 路径;无文件工作区时明确 unavailable |
174
+ | 查看一次 Attempt 摘要 | `niceeval show @<id>` | 评估用例断言、执行步骤、生命周期阶段耗时摘要、diff 摘要及各块可用性 |
175
+ | 检查评估用例断言及其通过或失败原因 | `niceeval show @<id> --source` | 运行时评估用例源码、源码哈希、断言所在行、严重度、分数与原因 |
176
+ | 检查 Coding Agent 的消息与调用 | `niceeval show @<id> --execution` | 消息、thinking、Skill load、工具调用与结果;有 OTel 时在同一节点附时间、父子关系和错误状态 |
177
+ | 检查 Attempt 各阶段耗时 | `niceeval show @<id> --timing` | lifecycle → hook/turn → shell → OTel 的统一时间树;出错的 Attempt 标出已知的最深失败节点 |
178
+ | 检查 Sandbox 工作区改动 | `niceeval show @<id> --diff` | 文件摘要、增删行数、具体补丁和原始 diff 路径;无文件工作区时明确 unavailable |
179
179
  </Step>
180
180
  <Step title="提出假设并修改">
181
181
  根据证据只修改最可能出错的一侧:
@@ -184,9 +184,9 @@ AI 通常按任务选择这些入口:
184
184
  | --- | --- |
185
185
  | 回复或工具调用不符合需求 | 被测程序、Prompt、工具定义 |
186
186
  | `diff` 与任务要求不符 | 被测 Agent 的实现策略或运行环境 |
187
- | 正确行为被 gate 拒绝 | Eval 断言、fixture、setup |
187
+ | 正确行为被 gate 拒绝 | 评估用例断言、fixture、setup |
188
188
  | timeout、鉴权或 Sandbox 错误 | 实验配置、Adapter、Sandbox |
189
- | 同一 Eval 时好时坏 | `--history`、`runs` 和稳定性问题 |
189
+ | 同一评估用例时好时坏 | `--history`、`runs` 和稳定性问题 |
190
190
 
191
191
  不要为了变绿而放宽一个本来正确的断言。先写清楚“哪条证据支持什么判断”,再修改代码。
192
192
  </Step>
@@ -196,7 +196,7 @@ AI 通常按任务选择这些入口:
196
196
  npx niceeval show weather/brooklyn
197
197
  ```
198
198
 
199
- 位置参数按 Eval ID 前缀缩小实验范围。调试同一个失败时加 `--force`,确保刚才的修改真的触发一次新运行。然后用 `show` 验证判定、断言和证据是否按预期变化。
199
+ 位置参数按评估用例 ID 前缀缩小实验范围。调试同一个失败时加 `--force`,确保刚才的修改真的触发一次新运行。然后用 `show` 验证判定、断言和证据是否按预期变化。
200
200
  </Step>
201
201
  <Step title="全量确认没有回归">
202
202
  ```bash
@@ -208,7 +208,7 @@ AI 通常按任务选择这些入口:
208
208
  </Step>
209
209
  </Steps>
210
210
 
211
- ## AI 应该从输出里读什么
211
+ ## 从输出读取诊断信号
212
212
 
213
213
  `--output agent` 运行中只向 stderr 追加低频 checkpoint(存活信号,不是结果数据源),结束时向 stdout 打印一个有界 handoff block——这才是 AI 应该解析的部分:
214
214
 
@@ -225,7 +225,7 @@ next:
225
225
  niceeval show @1k2m9qtr --execution
226
226
  ```
227
227
 
228
- AI 应先从 `failures` 选中 Attempt locator,再按证据位执行 `next` 给出的 `niceeval show @<id>` 或对应证据 flag,不要解析运行期间 stderr 上低频追加的 checkpoint 行——那些只用于判断进程是否存活。失败条数超过上限(默认 5 条)时,handoff 只展开前几条并给出总数,完整清单读结果快照。需要机器读取时,结果快照是事实来源:
228
+ Coding Agent 应先从 `failures` 选中 Attempt locator,再按证据位执行 `next` 给出的 `niceeval show @<id>` 或对应证据 flag。不要解析运行期间 stderr 上低频追加的 checkpoint 行;这些行只用于判断进程是否存活。失败条数超过上限(默认 5 条)时,handoff 只展开前几条并给出总数,完整清单从结果快照读取。机器读取以结果快照为事实来源:
229
229
 
230
230
  ```text
231
231
  .niceeval/<experiment>/<快照>/
@@ -242,11 +242,11 @@ AI 应先从 `failures` 选中 Attempt locator,再按证据位执行 `next`
242
242
  - `events.json` 是对话与工具调用事件,`trace.json` 是调用链,`diff.json` 是 Sandbox 文件变化。
243
243
  - 某类证据不存在时,对应文件不会生成。先以 `show` 的提示为准,不要假设每个目录都有全部文件。
244
244
 
245
- `show` 的默认结果可能合成自多次运行:每个 experiment × eval 选择最新判定,因此局部重跑后仍能看到其它 Eval 的旧结果。它适合回答“现在已知的水位是什么”;一次 `--force` 全量运行才适合回答“同一版代码是否整体通过”。
245
+ `show` 的默认结果可能合成自多次运行:每个 Experiment × 评估用例选择最新判定,因此局部重跑后仍能看到其它评估用例的旧结果。该视图用于查看每条评估用例的最新已知判定;同一版代码的整体结果必须通过一次 `--force` 全量运行确认。
246
246
 
247
- ## 什么时候会复用结果
247
+ ## 结果复用条件
248
248
 
249
- 不传 `--force` 时,NiceEval 会比较当前指纹与最近结果。指纹由 Eval 源码和运行配置组成,包括实验 ID、Agent、model、flags、Sandbox、timeout 与 strict 等设置。
249
+ 不传 `--force` 时,NiceEval 会比较当前指纹与最近结果。指纹由评估用例源码和运行配置组成,包括实验 ID、Agent、model、flags、Sandbox、timeout 与 strict 等设置。
250
250
 
251
251
  | 最近结果与当前输入 | 本次行为 |
252
252
  | --- | --- |
@@ -258,26 +258,26 @@ AI 应先从 `failures` 选中 Attempt locator,再按证据位执行 `next`
258
258
  被测程序的源码不在指纹里。修改实现后,即使行为已经变化,旧的 `passed` 或 `failed` 仍可能被复用。因此可以这样选择:
259
259
 
260
260
  - 只想重看已有结果:运行 `niceeval show`,不产生新费用。
261
- - 修改了 Eval 或实验配置:直接重跑;指纹变化会触发对应任务。
262
- - 修改了被测程序:对受影响的 Eval 使用 `--force`。
263
- - 准备结束本轮工作:对整个实验使用 `--force`,排除其它 Eval 的回归。
261
+ - 修改了评估用例或实验配置:直接重跑;指纹变化会触发对应任务。
262
+ - 修改了被测程序:对受影响的评估用例使用 `--force`。
263
+ - 准备结束本轮工作:对整个实验使用 `--force`,排除其它评估用例的回归。
264
264
 
265
- ## 让 AI 自己收敛
265
+ ## 设置自主迭代协议
266
266
 
267
- 可以把下面的协议放进任务描述。它既适合优化被测实现,也适合调试 Eval:
267
+ 可以把下面的协议放进任务描述。它既适合优化被测实现,也适合调试评估用例:
268
268
 
269
269
  ```text
270
270
  读取 node_modules/niceeval/INDEX.md,再按索引读取与任务有关的文档。
271
271
  运行 npx niceeval exp local --output agent,并根据退出码和失败 locator 决定下一步。
272
272
  对每个失败的 Eval,从报告选择一个 Attempt locator;再运行 niceeval show @<id>
273
- 并按问题选择 --eval、--execution、--timing 或 --diff;--timing 从 lifecycle 展开 setup/teardown
273
+ 并按问题选择 --source、--execution、--timing 或 --diff;--timing 从 lifecycle 展开 setup/teardown
274
274
  hook、shell 命令、每轮 send 与可关联的 OTel model/tool,回答整个 Attempt 的时间花在哪里。
275
275
  写出失败原因的假设,并判断应该修改被测程序、
276
276
  Eval,还是实验环境。修改后用 --force 重跑对应 Eval,比较新的判定和证据。
277
- 同一问题连续三轮没有新证据或改善时停止并汇报,不要靠放宽断言碰绿。
277
+ 同一问题连续三轮没有新证据或改善时停止并汇报,不要为得到通过结果而放宽正确的断言。
278
278
  全部局部失败清零后,用 npx niceeval exp local --output agent --force 全量验证;退出码 0 才完成。
279
279
  ```
280
280
 
281
281
  真实 Agent 的运行可能产生费用。实验阶段可以加 `--budget <美元>` 限制本轮累计成本;预算只能限制单次命令,不能替代上面的停止条件。
282
282
 
283
- 人与 AI 随时可以接手同一轮工作。AI 用 `niceeval show` 读取的结果,也能由人运行 `npx niceeval view` 在网页中查看。两者读取同一批 artifact;完整的输出格式、历史选择和网页操作见[查看结果](/zh/how-to/viewing-results)。
283
+ 人与 AI 随时可以接手同一轮工作。AI 用 `niceeval show` 读取的结果,也能由人运行 `npx niceeval view` 在网页中查看。两者读取同一批 artifact;完整的输出格式、历史选择和网页操作见[查看结果](/zh/tutorials/viewing-results)。
@@ -0,0 +1,100 @@
1
+ ---
2
+ title: "Coding Agent 从零接入项目"
3
+ sidebarTitle: "Coding Agent 从零接入"
4
+ description: "给 Coding Agent 的完整接入流程:探索项目、与用户确认路径、配置 Judge、写出 Adapter / Experiment / 评估用例并跑通第一个实验。"
5
+ ---
6
+
7
+ 这一页是 Coding Agent 把 NiceEval 接入一个项目的执行步骤。前提:`niceeval` 依赖已经装进项目、`niceeval init` 已经运行,你是从随包 `INDEX.md` 进入本页的。用用户的语言与用户交流;所有 API、字段和 CLI 行为以随包文档为准,不要凭训练记忆现编。
8
+
9
+ ## 第 1 步:探索项目,再和用户确认
10
+
11
+ 这一步决定后面整条路径。**先自己读代码探明,把探到的结论列给用户核对,探不到的再提问**——不要一上来就抛一串问题,也不要没探就假设。要探明的信息:
12
+
13
+ 1. **这是个什么 Agent**:读 README、`package.json` 依赖、路由和 agent loop 代码,判断它是用什么写的(AI SDK、LangGraph、OpenAI Agents SDK、Claude Agent SDK、自研 loop……),核心用例是什么(客服?SQL?编码任务?)。
14
+ 2. **前端和 Agent 怎么通信**:HTTP 还是 gRPC / WebSocket?协议是标准的还是自己实现的——AI SDK UI Message Stream、OpenAI Responses / Chat Completions 这类标准协议,还是 SDK 原生事件流透传,还是用户自定义的 JSON/SSE 帧?这直接决定 Adapter 是用内置的(零映射)还是手写 `send`(要自己写事件映射)。
15
+ 3. **后端有没有接 OTel**:搜有没有 OTel SDK 初始化、AI SDK telemetry、LangSmith / OpenLLMetry / OpenInference 这类埋点。已经有的话 Tier 2 几乎零成本。
16
+ 4. **用户自己有没有做 A/B Test / feature flag**:应用里已有变体开关的话,Experiment 的 `flags` 可以直接透传给它(Tier 3 的现成入口)。
17
+ 5. **Judge 用什么**:语义评分(`t.judge.autoevals.*`)要一个**与被测 Agent 分离的 Judge 模型**,走 OpenAI 兼容的 `/chat/completions` 协议——OpenAI 官方、DeepSeek、任何兼容该协议的网关都行。问用户手上有哪个服务的 key、想用什么 Judge 模型(没有内置默认模型,必须显式指定)。用户暂时没有 key 也不阻塞:Judge 断言会静默跳过,先用精确断言跑通。
18
+ 6. **是不是 Agent 本体要进 Sandbox**:被测对象是 coding agent CLI、或给 coding agent 写的 Skill/Plugin/Hook/MCP server(要在隔离 workspace 里改文件/跑命令)的话,必须走 Sandbox,不能像 HTTP 服务那样直接 `send`。默认建议 `dockerSandbox()`,但**要先跟用户确认**——本机/CI 有没有 Docker、要不要 Vercel Sandbox 或其它远程 Provider;用户没有异议就默认走 Docker。Provider 只能写在代码里(Experiment 或 `niceeval.config.ts` 的 `sandbox` 字段),没有 CLI flag,也不会自动探测——见[选择 Sandbox Provider](/zh/tutorials/sandbox-providers)。
19
+
20
+ 探完之后,向用户**介绍接入等级**并给出推荐(详见[接入等级](/zh/explanation/tier)):
21
+
22
+ - **Tier 1(只接 send)**:应用一行不改,全套断言(文本、Judge、多轮、工具、HITL)都在这一档。
23
+ - **Tier 2(send + OTel)**:应用把 OTel span 也发 NiceEval 一份,换 `niceeval view` 的调用瀑布图;已有埋点(第 3 点探到的)就零改动。
24
+ - **Tier 3(侵入改造 + flags)**:把应用内部变体暴露成 `flags` 做 feature A/B;已有 A/B 开关(第 4 点探到的)就是现成入口。
25
+
26
+ **默认推荐先 Tier 1 跑通,再升 Tier 2**——尤其当第 3 点探到应用已有 OTel 时,明确告诉用户「升 Tier 2 只是把 span 多发一份,成本接近零」。Tier 3 只在用户明确要做变体对比时提。
27
+
28
+ 按探明的形态挑对应文档,不要在没读的情况下直接开始写 Adapter:
29
+
30
+ | 被测对象 | 去读 |
31
+ |---|---|
32
+ | 用 Vercel AI SDK(`useChat` 后端)写的应用 | [内置 Agent 参考](/zh/reference/builtin-agents):内置 `uiMessageStreamAgent` 无侵入接入,不用手写事件映射 |
33
+ | coding agent CLI(claude-code / codex / bub 等改文件的任务) | [在 Sandbox 中评测 Agent](/zh/tutorials/sandbox-agent):要配 `sandbox`,默认 `dockerSandbox()`,先跟用户确认 Provider |
34
+ | 给 Claude Code / Codex 写的 Skill、Plugin、Hook 或 MCP server | [评测 Coding Agent 扩展](/zh/examples/coding-agent-extensions):同样跑在 Sandbox 里,Provider 确认方式同上 |
35
+ | 其它自研 agent loop、LangGraph、OpenAI Agents SDK、已部署 Agent | [接入自己的 Agent](/zh/tutorials/connect-your-agent) 起步,手写 `send` 的完整教程在[编写 send](/zh/tutorials/write-send) |
36
+ | 纯函数、没有独立服务的场景 | 先读[接入自己的 Agent](/zh/tutorials/connect-your-agent) 里「为什么不直调」那段,跟用户确认这确实是他们要的边缘用法,再继续 |
37
+
38
+ ## 第 2 步:配置 Judge
39
+
40
+ 把第 1 步问到的 Judge 服务配上。Judge 走 **OpenAI 兼容的 `/chat/completions`** 协议,在 `niceeval.config.ts` 里配:
41
+
42
+ ```ts
43
+ import { defineConfig } from "niceeval";
44
+
45
+ export default defineConfig({
46
+ judge: {
47
+ model: "gpt-5.4-mini", // 必填:没有内置默认模型
48
+ // 用非 OpenAI 官方的兼容服务(DeepSeek、网关等)时再加这两项:
49
+ // baseUrl: "https://api.deepseek.com/v1",
50
+ // apiKeyEnv: "DEEPSEEK_API_KEY", // key 从这个环境变量读;不配默认读 OPENAI_API_KEY
51
+ },
52
+ });
53
+ ```
54
+
55
+ 两个要提醒用户的点:
56
+
57
+ - **key 解析不到时 Judge 断言会静默跳过**(不报错、不记分)——评估用例全绿不代表 Judge 真的跑了。所以配完先跑一条带 `t.judge` 的评估用例,在 `niceeval view` 里确认有 Judge 分数。
58
+ - Judge 模型要**与被测 Agent 分离**,避免同一个模型给自己打分。模型解析优先级(单次调用 → 评估用例级 → 全局配置)和三种评分形状见 [Judge](/zh/explanation/judge),`judge` 字段全集见 [defineConfig 参考](/zh/reference/define-config)。
59
+
60
+ ## 第 3 步:写三件套
61
+
62
+ 按第 1 步选中的方向读完对应文档后,依次写:
63
+
64
+ 1. **Adapter**(`agents/*.ts` 或用户项目里约定的目录)——只填 `defineAgent` 的 `send`,配置走工厂参数,不写死、不读 `process.env`。契约见 [Adapter](/zh/explanation/adapter),API 签名见 [defineAgent 参考](/zh/reference/define-agent),事件映射见[事件参考](/zh/reference/events)。
65
+ 2. **Experiment**(`experiments/*.ts`)——引用上面的 Adapter,声明 `model`、`flags`、`runs` 等。模型对比写两个实验文件,各自钉一个 `model`;`evals: (eval) => boolean` 决定各自运行哪些评估用例。路径只负责 id 和批量运行,报告读取每份快照的 `selectedEvalIds`。
66
+ 3. **评估用例**(`evals/*.eval.ts`)——**先探明这个应用是干嘛的,再写一条贴着它真实功能的评估用例**:读它的 README、路由、工具定义或系统提示,找出它的核心用例(客服机器人就问一条真实的客服问题、SQL agent 就给一个真实的查询任务),拿这个用例做第一条评估用例的输入和断言,不要写「你好」这种和应用无关的占位输入。形式上仍从最小写起:一句输入,`t.succeeded()` + 一个针对预期回答的内容断言,跑通再加断言密度。写法见[编写评估用例](/zh/tutorials/authoring),断言与评分见[评分指南](/zh/tutorials/scoring-guide),签名见 [defineEval 参考](/zh/reference/define-eval)。
67
+
68
+ 参数怎么从 Experiment 流到 Adapter、静态配置和每轮动态值怎么分(工厂参数 vs `ctx`),见[接入自己的 Agent](/zh/tutorials/connect-your-agent)。
69
+
70
+ 架构上有两条硬规则,写 Adapter 时不要违反:
71
+
72
+ - **不做进程内直调**。就算 agent runtime 和评估用例在同一个代码库里,Adapter 也要走 HTTP(或对应传输层),不要把 `fetch` 换成直接 `import` 被测函数——原因见[接入自己的 Agent](/zh/tutorials/connect-your-agent) 里「为什么不直调」。
73
+ - **评估用例侧不代管被测进程**。不 spawn 应用、不另开端口;应用由用户自己按平时的方式启动(`pnpm dev` 之类),Adapter 连不上时报「先起应用」这类明确的错误,不要自己起服务。
74
+
75
+ ## 第 4 步:跑通并验证
76
+
77
+ ```sh
78
+ <包管理器> exec niceeval exp models # 按路径运行两个模型配置
79
+ <包管理器> exec niceeval view # 查看器里看对比结果
80
+ ```
81
+
82
+ 按 [Coding Agent 反馈闭环](/zh/tutorials/agent-feedback-loop)用 `niceeval show`、`--transcript`、`--trace` 和 `--diff` 完成运行、观察、修改和重跑;查看器用法见[查看结果](/zh/tutorials/viewing-results)。没跑通分三类定位:`fetch` 直接抛错 → 应用没起来或 URL 不对;`t.succeeded()` 不过 → 应用回了非成功状态;只有内容断言不过 → 接入已经通了,调断言或调应用。
83
+
84
+ ## 第 5 步:收尾,告诉用户做了什么
85
+
86
+ 跑通之后先总结,再谈下一步。总结要说清:接了什么被测对象、生成了哪几个文件(Adapter / Experiment / 评估用例各在哪)、`niceeval exp compare-models` 和 `niceeval view` 怎么跑、第一次运行的结果是什么样。不要在没被要求的情况下顺手重构用户已有代码,也不要在这几个文件之外新增抽象。
87
+
88
+ ## 第 6 步:问用户要不要往深了接
89
+
90
+ 总结完之后,把还能往深接的选项列给用户——每一项都说清**能做什么、大概改多少代码、买到什么好处**,让用户自己选,不要自作主张多做:
91
+
92
+ | 能做什么 | 改动量 | 好处 | 文档 |
93
+ |---|---|---|---|
94
+ | 工具调用断言(`t.calledTool()` 等) | 只改 Adapter:把应用响应映射成标准事件流,约 10–30 行映射代码 | 评估用例能断言「Agent 有没有调对工具、参数对不对」,不再只看最终回复 | [编写 send](/zh/tutorials/write-send)、[事件参考](/zh/reference/events) |
95
+ | 多轮对话、会话隔离 | 只改 Adapter:接上 `ctx.session`(`history()` 或 `id` + `capture()`),几行到十几行 | 评估用例能写多轮场景、`t.newSession()` 验证会话间不串味 | [驱动多轮交互](/zh/explanation/drive)、[编写 send](/zh/tutorials/write-send) |
96
+ | 人工审批流(HITL) | 只改 Adapter:停轮返回 `waiting` + `input.requested`,回答轮续跑,约 10–20 行 | 评估用例能覆盖「批准/拒绝之后 Agent 行为对不对」这类审批场景 | [HITL](/zh/explanation/hitl) |
97
+ | 调用瀑布图(升 Tier 2) | 应用已有 OTel 埋点(第 1 步探过):只是把 span 多发一份给 NiceEval,几行配置;没埋点:补一段通用 OTel 初始化 | `niceeval view` 里看到应用内部每次模型调用、工具执行的耗时和 token 时间线;不影响任何断言 | [配置 OTel](/zh/tutorials/connect-otel) |
98
+ | feature A/B 对比(升 Tier 3) | 改应用:把变体暴露成 `flags` 可切换的配置,改动量取决于应用;已有 A/B 开关(第 1 步探过)就是现成入口 | Experiment 层面直接对比「改 prompt / 换工具集 / 开关 feature 谁更好」 | [组织 Experiment](/zh/tutorials/experiments)、[接入等级](/zh/explanation/tier) |
99
+
100
+ 共同点也要讲给用户:这些全是给 Adapter 或应用加增量,**已写的评估用例一行不用改**。三档投入分别买到什么、什么时候值得升级,见[接入等级](/zh/explanation/tier)。第 1 步探到应用已有 OTel 埋点的话,瀑布图那条要主动推荐——成本接近零。