niceeval 0.5.3 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (344) hide show
  1. package/INDEX.md +55 -0
  2. package/dist/agents/types.d.ts +317 -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/execution-tree.d.ts +103 -0
  9. package/dist/o11y/otlp/parse.d.ts +3 -0
  10. package/dist/o11y/otlp/receiver.d.ts +21 -0
  11. package/dist/o11y/otlp/select.d.ts +22 -0
  12. package/dist/o11y/otlp/turn-otel.d.ts +43 -0
  13. package/dist/o11y/types.d.ts +190 -0
  14. package/dist/report/aggregate.d.ts +57 -0
  15. package/dist/report/aggregate.js +212 -0
  16. package/dist/report/built-ins/cost-pass-rate-comparison.d.ts +1 -0
  17. package/dist/report/built-ins/cost-pass-rate-comparison.js +17 -0
  18. package/dist/report/built-ins/index.d.ts +1 -0
  19. package/dist/report/built-ins/index.js +2 -0
  20. package/dist/report/components.d.ts +178 -0
  21. package/dist/report/components.js +132 -0
  22. package/dist/report/compute.d.ts +106 -0
  23. package/dist/report/compute.js +618 -0
  24. package/dist/report/flag.d.ts +6 -0
  25. package/dist/report/flag.js +8 -0
  26. package/dist/report/format.d.ts +32 -0
  27. package/dist/report/format.js +126 -0
  28. package/dist/report/index.d.ts +19 -0
  29. package/dist/report/index.js +30 -0
  30. package/dist/report/load.d.ts +12 -0
  31. package/dist/report/load.js +56 -0
  32. package/dist/report/locale.d.ts +83 -0
  33. package/dist/report/locale.js +160 -0
  34. package/dist/report/metrics.d.ts +21 -0
  35. package/dist/report/metrics.js +115 -0
  36. package/dist/report/primitives.d.ts +64 -0
  37. package/dist/report/primitives.js +113 -0
  38. package/dist/report/react/AttemptList.d.ts +23 -0
  39. package/dist/report/react/AttemptList.js +20 -0
  40. package/dist/report/react/DeltaTable.d.ts +8 -0
  41. package/dist/report/react/DeltaTable.js +24 -0
  42. package/dist/report/react/EvalList.d.ts +10 -0
  43. package/dist/report/react/EvalList.js +0 -0
  44. package/dist/report/react/ExperimentList.d.ts +10 -0
  45. package/dist/report/react/ExperimentList.js +15 -0
  46. package/dist/report/react/GroupSummary.d.ts +8 -0
  47. package/dist/report/react/GroupSummary.js +8 -0
  48. package/dist/report/react/MetricBars.d.ts +10 -0
  49. package/dist/report/react/MetricBars.js +48 -0
  50. package/dist/report/react/MetricLine.d.ts +9 -0
  51. package/dist/report/react/MetricLine.js +68 -0
  52. package/dist/report/react/MetricMatrix.d.ts +10 -0
  53. package/dist/report/react/MetricMatrix.js +23 -0
  54. package/dist/report/react/MetricScatter.d.ts +9 -0
  55. package/dist/report/react/MetricScatter.js +100 -0
  56. package/dist/report/react/MetricTable.d.ts +11 -0
  57. package/dist/report/react/MetricTable.js +26 -0
  58. package/dist/report/react/RunOverview.d.ts +8 -0
  59. package/dist/report/react/RunOverview.js +12 -0
  60. package/dist/report/react/Scoreboard.d.ts +8 -0
  61. package/dist/report/react/Scoreboard.js +26 -0
  62. package/dist/report/react/cell.d.ts +9 -0
  63. package/dist/report/react/cell.js +9 -0
  64. package/dist/report/react/chart-math.d.ts +14 -0
  65. package/dist/report/react/chart-math.js +68 -0
  66. package/dist/report/react/colors.d.ts +14 -0
  67. package/dist/report/react/colors.js +45 -0
  68. package/dist/report/react/fixtures.d.ts +19 -0
  69. package/dist/report/react/fixtures.js +393 -0
  70. package/dist/report/react/format.d.ts +3 -0
  71. package/dist/report/react/format.js +7 -0
  72. package/dist/report/react/index.d.ts +6 -0
  73. package/dist/report/react/index.js +14 -0
  74. package/dist/report/report.d.ts +24 -0
  75. package/dist/report/report.js +49 -0
  76. package/dist/report/text/faces.d.ts +29 -0
  77. package/dist/report/text/faces.js +503 -0
  78. package/dist/report/text/layout.d.ts +75 -0
  79. package/dist/report/text/layout.js +173 -0
  80. package/dist/report/text/plot.d.ts +37 -0
  81. package/dist/report/text/plot.js +81 -0
  82. package/dist/report/text/table.d.ts +8 -0
  83. package/dist/report/text/table.js +86 -0
  84. package/dist/report/tree.d.ts +99 -0
  85. package/dist/report/tree.js +228 -0
  86. package/dist/report/types.d.ts +420 -0
  87. package/dist/report/types.js +4 -0
  88. package/dist/report/web.d.ts +15 -0
  89. package/dist/report/web.js +37 -0
  90. package/dist/results/annotated-source.d.ts +61 -0
  91. package/dist/results/attempt-evidence.d.ts +69 -0
  92. package/dist/results/attempt-source.d.ts +15 -0
  93. package/dist/results/locator.d.ts +75 -0
  94. package/dist/results/locator.js +0 -0
  95. package/dist/results/select.d.ts +45 -0
  96. package/dist/results/select.js +230 -0
  97. package/dist/results/source-hash.d.ts +9 -0
  98. package/dist/results/types.d.ts +204 -0
  99. package/dist/runner/eval-source.d.ts +22 -0
  100. package/dist/runner/fingerprint.d.ts +23 -0
  101. package/dist/runner/types.d.ts +332 -0
  102. package/dist/sandbox/docker-stream.d.ts +24 -0
  103. package/dist/sandbox/docker.d.ts +84 -0
  104. package/dist/sandbox/e2b.d.ts +31 -0
  105. package/dist/sandbox/errors.d.ts +4 -0
  106. package/dist/sandbox/local-files.d.ts +6 -0
  107. package/dist/sandbox/paths.d.ts +4 -0
  108. package/dist/sandbox/registry.d.ts +13 -0
  109. package/dist/sandbox/resolve.d.ts +40 -0
  110. package/dist/sandbox/retry.d.ts +10 -0
  111. package/dist/sandbox/shell.d.ts +11 -0
  112. package/dist/sandbox/source-files.d.ts +13 -0
  113. package/dist/sandbox/types.d.ts +203 -0
  114. package/dist/sandbox/vercel.d.ts +37 -0
  115. package/dist/scoring/types.d.ts +70 -0
  116. package/dist/shared/aggregate.d.ts +29 -0
  117. package/dist/shared/aggregate.js +55 -0
  118. package/dist/shared/types.d.ts +27 -0
  119. package/dist/shared/verdict.d.ts +27 -0
  120. package/dist/shared/verdict.js +34 -0
  121. package/dist/tty-line.d.ts +6 -0
  122. package/dist/types.d.ts +7 -0
  123. package/dist/util.d.ts +22 -0
  124. package/docs-site/zh/concepts/adapter.mdx +9 -4
  125. package/docs-site/zh/concepts/assert.mdx +8 -8
  126. package/docs-site/zh/concepts/evals.mdx +5 -5
  127. package/docs-site/zh/concepts/experiment.mdx +3 -1
  128. package/docs-site/zh/concepts/judge.mdx +9 -9
  129. package/docs-site/zh/concepts/overview.mdx +2 -2
  130. package/docs-site/zh/concepts/tier.mdx +6 -6
  131. package/docs-site/zh/example/claude-code-codex-plugin.mdx +9 -5
  132. package/docs-site/zh/example/claude-code-codex-skill.mdx +12 -7
  133. package/docs-site/zh/guides/agent-feedback-loop.mdx +235 -78
  134. package/docs-site/zh/guides/connect-otel.mdx +3 -3
  135. package/docs-site/zh/guides/connect-your-agent.mdx +2 -2
  136. package/docs-site/zh/guides/custom-reports.mdx +196 -36
  137. package/docs-site/zh/guides/experiments.mdx +7 -0
  138. package/docs-site/zh/guides/fixtures.mdx +1 -1
  139. package/docs-site/zh/guides/official-adapters.mdx +31 -9
  140. package/docs-site/zh/guides/publish-report.mdx +4 -4
  141. package/docs-site/zh/guides/report-components.mdx +194 -55
  142. package/docs-site/zh/guides/reporters.mdx +2 -2
  143. package/docs-site/zh/guides/results-data.mdx +35 -34
  144. package/docs-site/zh/guides/runner.mdx +2 -2
  145. package/docs-site/zh/guides/sandbox-agent.mdx +10 -5
  146. package/docs-site/zh/guides/sandbox-providers.mdx +102 -0
  147. package/docs-site/zh/guides/viewing-results.mdx +199 -79
  148. package/docs-site/zh/guides/write-experiment.mdx +23 -1
  149. package/docs-site/zh/guides/write-send.mdx +2 -2
  150. package/docs-site/zh/index.mdx +4 -3
  151. package/docs-site/zh/introduction.mdx +2 -1
  152. package/docs-site/zh/quickstart.mdx +5 -3
  153. package/docs-site/zh/reference/builtin-agents.mdx +38 -13
  154. package/docs-site/zh/reference/capabilities.mdx +1 -1
  155. package/docs-site/zh/reference/cli.mdx +36 -13
  156. package/docs-site/zh/reference/define-agent.mdx +24 -12
  157. package/docs-site/zh/reference/define-config.mdx +1 -1
  158. package/docs-site/zh/reference/define-eval.mdx +3 -3
  159. package/docs-site/zh/reference/events.mdx +7 -1
  160. package/docs-site/zh/reference/expect.mdx +3 -3
  161. package/package.json +10 -6
  162. package/src/agents/bub.ts +134 -43
  163. package/src/agents/claude-code.test.ts +152 -0
  164. package/src/agents/claude-code.ts +127 -13
  165. package/src/agents/codex.test.ts +192 -0
  166. package/src/agents/codex.ts +151 -12
  167. package/src/agents/index.ts +11 -3
  168. package/src/agents/manifest.ts +41 -0
  169. package/src/agents/plugin-config.test.ts +94 -0
  170. package/src/agents/shared.ts +33 -2
  171. package/src/agents/skills.test.ts +214 -0
  172. package/src/agents/skills.ts +304 -0
  173. package/src/agents/streaming.ts +5 -5
  174. package/src/agents/types.ts +62 -2
  175. package/src/cli.ts +74 -47
  176. package/src/context/context.test.ts +20 -2
  177. package/src/context/context.ts +3 -0
  178. package/src/context/control-flow.ts +1 -1
  179. package/src/context/session.test.ts +92 -1
  180. package/src/context/session.ts +26 -1
  181. package/src/context/types.ts +4 -4
  182. package/src/define.test.ts +82 -0
  183. package/src/define.ts +72 -11
  184. package/src/expect/index.ts +5 -5
  185. package/src/i18n/en.ts +36 -15
  186. package/src/i18n/zh-CN.ts +39 -21
  187. package/src/index.ts +1 -1
  188. package/src/o11y/execution-tree.test.ts +452 -0
  189. package/src/o11y/execution-tree.ts +367 -0
  190. package/src/o11y/otlp/receiver.ts +1 -1
  191. package/src/o11y/otlp/select.ts +7 -3
  192. package/src/o11y/parsers/claude-code.test.ts +175 -0
  193. package/src/o11y/parsers/claude-code.ts +32 -0
  194. package/src/o11y/types.ts +6 -1
  195. package/src/report/aggregate.ts +26 -20
  196. package/src/report/built-in-user-parity.test.tsx +643 -0
  197. package/src/report/built-ins/cost-pass-rate-comparison.tsx +23 -0
  198. package/src/report/built-ins/index.ts +2 -0
  199. package/src/report/components.tsx +223 -50
  200. package/src/report/compute.ts +358 -53
  201. package/src/report/dual-render.test.tsx +1125 -0
  202. package/src/report/flag.ts +1 -1
  203. package/src/report/format.ts +50 -2
  204. package/src/report/index.ts +48 -14
  205. package/src/report/load.ts +1 -1
  206. package/src/report/locale.ts +206 -0
  207. package/src/report/metrics.ts +39 -15
  208. package/src/report/primitives.tsx +100 -2
  209. package/src/report/react/AttemptList.tsx +115 -0
  210. package/src/report/react/DeltaTable.tsx +9 -6
  211. package/src/report/react/EvalList.tsx +0 -0
  212. package/src/report/react/ExperimentList.tsx +108 -0
  213. package/src/report/react/GroupSummary.tsx +66 -0
  214. package/src/report/react/MetricBars.tsx +24 -13
  215. package/src/report/react/MetricLine.tsx +21 -21
  216. package/src/report/react/MetricMatrix.tsx +8 -4
  217. package/src/report/react/MetricScatter.tsx +136 -96
  218. package/src/report/react/MetricTable.tsx +115 -15
  219. package/src/report/react/RunOverview.tsx +48 -26
  220. package/src/report/react/Scoreboard.tsx +15 -7
  221. package/src/report/react/cell.tsx +18 -9
  222. package/src/{view/app/lib/chart.ts → report/react/chart-math.ts} +2 -6
  223. package/src/report/react/colors.ts +24 -15
  224. package/src/report/react/enhance.js +129 -0
  225. package/src/report/react/fixtures.ts +163 -34
  226. package/src/report/react/format.ts +1 -1
  227. package/src/report/react/index.tsx +22 -6
  228. package/src/report/react/render.test.tsx +164 -31
  229. package/src/report/react/styles.css +405 -213
  230. package/src/report/report.test.ts +403 -94
  231. package/src/report/report.ts +29 -11
  232. package/src/report/text/faces.ts +303 -95
  233. package/src/report/text/layout.ts +76 -11
  234. package/src/report/text/table.ts +98 -0
  235. package/src/report/tree.ts +103 -20
  236. package/src/report/types.ts +196 -25
  237. package/src/report/web.ts +46 -19
  238. package/src/results/annotated-source.test.ts +146 -0
  239. package/src/results/annotated-source.ts +128 -0
  240. package/src/results/attempt-evidence.test.ts +158 -0
  241. package/src/results/attempt-evidence.ts +158 -0
  242. package/src/results/attempt-source.ts +48 -0
  243. package/src/results/copy.ts +154 -139
  244. package/src/results/format.ts +54 -47
  245. package/src/results/host-equivalence.test.ts +527 -0
  246. package/src/results/index.ts +56 -14
  247. package/src/results/locator.test.ts +198 -0
  248. package/src/results/locator.ts +0 -0
  249. package/src/results/open.ts +392 -175
  250. package/src/results/results.test.ts +943 -494
  251. package/src/results/select.ts +129 -23
  252. package/src/results/skipped-notice.ts +0 -0
  253. package/src/results/source-hash.ts +28 -0
  254. package/src/results/types.ts +98 -62
  255. package/src/results/writer.ts +304 -176
  256. package/src/runner/attempt.test.ts +170 -0
  257. package/src/runner/attempt.ts +97 -15
  258. package/src/runner/discover.test.ts +65 -0
  259. package/src/runner/discover.ts +6 -2
  260. package/src/runner/eval-source.test.ts +121 -0
  261. package/src/runner/eval-source.ts +45 -0
  262. package/src/runner/fingerprint.ts +54 -1
  263. package/src/runner/remote-sandbox.ts +1 -1
  264. package/src/runner/report.test.ts +6 -8
  265. package/src/runner/report.ts +5 -4
  266. package/src/runner/reporters/artifacts.ts +27 -41
  267. package/src/runner/reporters/braintrust.test.ts +3 -3
  268. package/src/runner/reporters/braintrust.ts +1 -1
  269. package/src/runner/reporters/console.ts +6 -6
  270. package/src/runner/reporters/json.ts +4 -4
  271. package/src/runner/reporters/live.test.ts +56 -0
  272. package/src/runner/reporters/live.ts +36 -10
  273. package/src/runner/reporters/quiet.test.ts +66 -0
  274. package/src/runner/reporters/quiet.ts +49 -0
  275. package/src/runner/reporters/shared.ts +5 -5
  276. package/src/runner/reporters/table.ts +17 -17
  277. package/src/runner/run.ts +61 -102
  278. package/src/runner/types.ts +43 -32
  279. package/src/sandbox/checkpoint.ts +1 -1
  280. package/src/sandbox/docker.ts +15 -2
  281. package/src/sandbox/e2b.ts +11 -5
  282. package/src/sandbox/errors.ts +13 -0
  283. package/src/sandbox/index.ts +3 -3
  284. package/src/sandbox/local-files.ts +1 -1
  285. package/src/sandbox/registry.ts +6 -5
  286. package/src/sandbox/resolve.ts +38 -23
  287. package/src/sandbox/retry.test.ts +68 -0
  288. package/src/sandbox/retry.ts +44 -0
  289. package/src/sandbox/types.ts +69 -28
  290. package/src/sandbox/vercel.ts +17 -3
  291. package/src/scoring/collector.ts +3 -3
  292. package/src/scoring/judge.ts +2 -2
  293. package/src/scoring/scoped.ts +13 -1
  294. package/src/scoring/types.ts +7 -7
  295. package/src/scoring/verdict.ts +4 -4
  296. package/src/shared/aggregate.ts +23 -3
  297. package/src/shared/types.ts +2 -2
  298. package/src/shared/{outcome.ts → verdict.ts} +15 -15
  299. package/src/show/compose.ts +12 -132
  300. package/src/show/index.ts +125 -94
  301. package/src/show/render.ts +660 -160
  302. package/src/show/show.test.ts +472 -253
  303. package/src/source-loc.ts +1 -1
  304. package/src/tty-line.ts +32 -0
  305. package/src/types.ts +2 -2
  306. package/src/util.test.ts +21 -1
  307. package/src/util.ts +5 -1
  308. package/src/view/app/App.tsx +33 -198
  309. package/src/view/app/components/AttemptModal.tsx +6 -6
  310. package/src/view/app/components/CodeView.tsx +2 -2
  311. package/src/view/app/components/CopyControls.tsx +32 -36
  312. package/src/view/app/components/SkippedRunsBanner.tsx +140 -0
  313. package/src/view/app/components/ui/badge.tsx +1 -1
  314. package/src/view/app/components/ui/dialog.tsx +2 -2
  315. package/src/view/app/i18n.ts +40 -31
  316. package/src/view/app/lib/artifact-url.ts +1 -1
  317. package/src/view/app/lib/attempt-route.test.ts +37 -47
  318. package/src/view/app/lib/attempt-route.ts +26 -26
  319. package/src/view/app/lib/rows.ts +9 -112
  320. package/src/view/app/lib/verdict.ts +25 -0
  321. package/src/view/app/main.tsx +9 -12
  322. package/src/view/app/pages/RunsPage.tsx +4 -4
  323. package/src/view/app/pages/TracesPage.tsx +3 -3
  324. package/src/view/app/shared.ts +0 -1
  325. package/src/view/app/types.ts +6 -51
  326. package/src/view/artifact-serving.test.ts +136 -0
  327. package/src/view/client-dist/app.css +1 -1
  328. package/src/view/client-dist/app.js +21 -21
  329. package/src/view/data.test.ts +214 -143
  330. package/src/view/data.ts +166 -120
  331. package/src/view/index.ts +23 -11
  332. package/src/view/server.ts +52 -17
  333. package/src/view/shared/types.ts +22 -31
  334. package/src/view/styles.css +117 -327
  335. package/src/view/view-report.test.ts +146 -98
  336. package/docs-site/zh/guides/sandbox-backends.mdx +0 -75
  337. package/src/report/default-report.tsx +0 -222
  338. package/src/report/dual-face.test.tsx +0 -527
  339. package/src/report/react/CaseList.tsx +0 -70
  340. package/src/view/app/components/CostScoreChart.tsx +0 -147
  341. package/src/view/app/components/ExperimentTable.tsx +0 -284
  342. package/src/view/app/components/GroupSelector.tsx +0 -61
  343. package/src/view/app/components/primitives.tsx +0 -43
  344. package/src/view/app/lib/outcome.ts +0 -82
@@ -0,0 +1,204 @@
1
+ import type { EvalResult, ExperimentRunInfo, LocalizedText } from "../types.ts";
2
+ import type { O11ySummary, StreamEvent, TraceSpan } from "../types.ts";
3
+ import type { AgentSetupManifest, DiffData, SourceArtifact } from "../types.ts";
4
+ import type { AttemptLocator } from "./locator.ts";
5
+ /** attempt 级 artifact 的种类;文件名见 format.ts 的 artifactFileOf,布局见 docs/feature/results/architecture.md。 */
6
+ export declare const ARTIFACT_KINDS: readonly ["events", "trace", "o11y", "agentSetup", "diff", "sources"];
7
+ export type ArtifactKind = (typeof ARTIFACT_KINDS)[number];
8
+ /** 写这份结果的工具:niceeval 自己,或经 niceeval/results 写入面转换的第三方 harness。 */
9
+ export interface Producer {
10
+ name: string;
11
+ version?: string;
12
+ commit?: string;
13
+ }
14
+ /**
15
+ * `snapshot.json` 的持久化契约:快照元数据 —— 身份、快照级字段与版本元数据,
16
+ * 不含任何逐 attempt 数据。快照开始时写入;收尾时补写 `completedAt`。
17
+ * 字段规则与版本判定见 docs/feature/results/architecture.md「snapshot.json」「版本与升级设计」。
18
+ */
19
+ export interface SnapshotMeta {
20
+ /** 恒为 "niceeval.results";和 schemaVersion、producer 一起构成持久化契约,永不移动或改名。 */
21
+ format: "niceeval.results";
22
+ /** 结果格式版本;与读取器不同即视为不兼容,提示用 producer.version 对应的 niceeval 查看。 */
23
+ schemaVersion: number;
24
+ producer: Producer;
25
+ /** 权威的实验身份;实验目录名是它的清洗投影。 */
26
+ experimentId: string;
27
+ /** 实验运行配置(flags / runs / earlyExit / sandbox / timeoutMs / budget),快照内全部 attempt 共享。 */
28
+ experiment?: ExperimentRunInfo;
29
+ agent: string;
30
+ model?: string;
31
+ startedAt: string;
32
+ /** 收尾时补写;缺失 = 快照未收尾(进程中断),已落盘的 attempt 照常可读。 */
33
+ completedAt?: string;
34
+ /** 写入时刻该实验已知的 eval 并集 —— 残缺检测的分母随数据走(copySnapshots 自动补记,writer 可声明)。 */
35
+ knownEvalIds?: string[];
36
+ /** 项目名(来自 config.name),透传给 `niceeval view` 顶部 hero 显示。 */
37
+ name?: LocalizedText;
38
+ }
39
+ /**
40
+ * 回到证据的引用:快照目录(根相对)+ 快照内 attempt 目录(快照相对)。
41
+ * 字段名(snapshot / attempt)是 view 深链 `#/attempt/<snapshot>/<attempt>` 的持久化路由契约,
42
+ * 不随句柄改名;`snapshot` 恒为两段(`<实验目录>/<快照目录>`),`attempt` 是 `<evalId 路径>/a<n>`,
43
+ * 路由按「前两段 = 快照」解析。Reports 的 MetricCell.refs 用的是同一个身份。
44
+ */
45
+ export interface AttemptRef {
46
+ /** 根相对快照目录:`<experiment-dir>/<快照目录>`。 */
47
+ snapshot: string;
48
+ /** 快照相对 attempt 目录:`<evalId 路径>/a<n>`。 */
49
+ attempt: string;
50
+ }
51
+ /**
52
+ * 单个 eval attempt:瘦身条目 + 重 artifact 的懒加载方法。
53
+ * 懒加载即存在性判断: artifact 缺失返回 null,不抛错;同一 handle 内读过一次即记忆化。
54
+ * artifact 定位按候选顺序回退:先本 attempt 目录,再 artifactBase 指向的原快照 attempt 目录
55
+ * (--resume 合入条目的 artifact 留在原快照里);原快照被清理后如实返回 null。
56
+ */
57
+ export interface AttemptHandle {
58
+ /** 属于哪道题 —— 直达字段,不绕 result。 */
59
+ evalId: string;
60
+ /** 属于哪个实验。 */
61
+ experimentId: string;
62
+ /** EvalResult 瘦身条目:判定、断言、用量、成本(快照级字段已拼合)。 */
63
+ result: EvalResult;
64
+ /** 证据引用,指条目所在的落盘(合入后的新快照); artifact 经候选回退仍可达。 */
65
+ ref: AttemptRef;
66
+ /** 所属快照(反向引用);去重「保留最新快照里的那份」靠它比较新旧。 */
67
+ snapshot: Snapshot;
68
+ /**
69
+ * 不透明的 Attempt 定位符(见 `locator.ts`);openResults() 产出的 handle 恒会填这个字段
70
+ * (result.json 里有就直接用,没有则按当前身份兜底算,见 open.ts 的回填逻辑)。可选只是为了
71
+ * 不强制手工构造的 AttemptHandle(测试里的内存 fake)也必须带上——真实读取路径永远有值。
72
+ */
73
+ locator?: AttemptLocator;
74
+ events(): Promise<StreamEvent[] | null>;
75
+ trace(): Promise<TraceSpan[] | null>;
76
+ o11y(): Promise<O11ySummary | null>;
77
+ /** 这次 attempt 的 agent setup 装了什么(Skill / native plugin / MCP / Python plugin);没装扩展的 agent 恒为 null。 */
78
+ agentSetup(): Promise<AgentSetupManifest | null>;
79
+ diff(): Promise<DiffData | null>;
80
+ sources(): Promise<SourceArtifact[] | null>;
81
+ }
82
+ /** 一道题在一个快照里的结果:id + 该题的全部 attempt(重试历史)。 */
83
+ export interface Eval {
84
+ id: string;
85
+ attempts: AttemptHandle[];
86
+ }
87
+ /** 快照 = 单次跑的实验,物理上就是一个快照目录,没有更低一层。 */
88
+ export interface Snapshot {
89
+ /** 权威身份(snapshot.json 字段;实验目录名只是它的清洗投影)。 */
90
+ experimentId: string;
91
+ startedAt: string;
92
+ /** 缺失 = 未收尾(进程中断);已落盘 attempt 照常在下面读到。 */
93
+ completedAt?: string;
94
+ /** 本快照自己的 agent。 */
95
+ agent: string;
96
+ model?: string;
97
+ /** 实验运行配置(flags / runs / budget …),快照内全部 attempt 共享。 */
98
+ experiment?: ExperimentRunInfo;
99
+ /** 谁写的这份结果(niceeval 或第三方 harness)。 */
100
+ producer: Producer;
101
+ /** 结果格式版本(能读进来的恒为当前版本;不兼容的在 skipped)。 */
102
+ schemaVersion: number;
103
+ /** 项目名(来自 config.name),透传给 `niceeval view` 顶部 hero 显示。 */
104
+ name?: LocalizedText;
105
+ /** 每道题一项:{ id, attempts };残缺检测 / 逐题遍历从这里走。 */
106
+ evals: Eval[];
107
+ /** 全部 attempt 平铺(= evals 逐题展开),不关心题目边界的聚合消费用。 */
108
+ attempts: AttemptHandle[];
109
+ /** 快照目录的绝对路径(物理落盘就是快照本身,没有更低一层)。 */
110
+ dir: string;
111
+ /** 写入时刻该实验已知的 eval 并集(可选);copySnapshots 自动补记,writer.snapshot() 也可声明。 */
112
+ knownEvalIds?: string[];
113
+ }
114
+ /** 一个实验的全部历史:同一 experiment id 的历次快照归在一起。 */
115
+ export interface Experiment {
116
+ id: string;
117
+ /** 历次快照,最新在前。 */
118
+ snapshots: Snapshot[];
119
+ /** 最新一次(= snapshots[0])。 */
120
+ latest: Snapshot;
121
+ /** 已知 eval 并集 = 本地历史 ∪ 各快照携带的 knownEvalIds —— 残缺检测的分母。 */
122
+ evalIds: string[];
123
+ }
124
+ /** 目录扫描里读不了、但必须让调用方知道的落盘;无关 JSON 不记(静默忽略)。 */
125
+ export interface SkippedDir {
126
+ /** 落盘目录的绝对路径。 */
127
+ dir: string;
128
+ /**
129
+ * incompatible-version:schemaVersion 与读取器不同(不解析、不迁移、不降级);
130
+ * malformed:snapshot.json(或历史版本的 summary.json)是坏数据;
131
+ * incomplete:有 attempt 落盘、没有 snapshot.json —— 快照目录建好但元数据没写完的极小窗口,
132
+ * 或人为删文件。snapshot.json 是收尾事实,reader 不读无 snapshot.json 的目录;
133
+ * 已完成的 attempt 留在盘上供手工排查。
134
+ */
135
+ reason: "incompatible-version" | "malformed" | "incomplete";
136
+ /** 那份结果声明的 schemaVersion(incomplete 没有 snapshot.json,自然缺失)。 */
137
+ schemaVersion?: number;
138
+ /** 完整的 producer(name + version):只有 name === "niceeval" 才能拼 npx 提示,第三方如实报名字。 */
139
+ producer?: Producer;
140
+ /** malformed:一句英文诊断。 */
141
+ detail?: string;
142
+ }
143
+ /** openResults 的返回:experiments 分层;skipped 不静默丢。 */
144
+ export interface Results {
145
+ /** 每个实验一项,挂着自己的全部历史(id 字典序)。 */
146
+ experiments: Experiment[];
147
+ skipped: SkippedDir[];
148
+ /**
149
+ * 每个实验取最新一次快照,返回 Selection(快照与挑选警告绑在一起走)。
150
+ * `experiments` 是 experiment id 前缀过滤(string | string[]),同 CLI 位置参数语义。
151
+ */
152
+ latest(opts?: {
153
+ experiments?: string | string[];
154
+ }): Selection;
155
+ }
156
+ /**
157
+ * Selection:选出的快照 + 挑选过程算出的警告。渲染与否在消费方,但缺口永远被算出来。
158
+ * 下游(Reports 计算函数、copySnapshots)收 `Selection | Snapshot[]`;
159
+ * 手工挑的裸数组没有挑选过程,自然没有 warnings 可带,也如实。
160
+ */
161
+ export interface Selection {
162
+ snapshots: Snapshot[];
163
+ warnings: SelectionWarning[];
164
+ /**
165
+ * 只删不换:返回新 Selection,快照删减,warnings 按规则修剪 ——
166
+ * experimentId 不在幸存快照中的丢弃,非实验作用域的保留。
167
+ * 「换成上一个完整快照」这类替换式重挑不给方法,回 exp.snapshots 自己挑。
168
+ */
169
+ filter(predicate: (snapshot: Snapshot) => boolean): Selection;
170
+ }
171
+ /**
172
+ * 挑选警告:每种带 kind、可判断的结构化字段和渲染好的英文 message;
173
+ * kind 是契约的一部分,全集与触发条件见 docs/feature/results/library.md「警告 kind 全集」。
174
+ */
175
+ export type SelectionWarning = {
176
+ /** 选中快照的覆盖 < 该实验已知 eval 并集(本地历史 ∪ knownEvalIds)。 */
177
+ kind: "partial-coverage";
178
+ experimentId: string;
179
+ covered: number;
180
+ total: number;
181
+ message: string;
182
+ } | {
183
+ /** 该实验选中的快照早于 Selection 中最新的落盘;无阈值,如实触发,要阈值消费方按字段自比。 */
184
+ kind: "stale-snapshot";
185
+ experimentId: string;
186
+ startedAt: string;
187
+ latestStartedAt: string;
188
+ message: string;
189
+ } | {
190
+ /** 选中快照缺 completedAt(进程中断,未收尾);已落盘 attempt 照常读出,警告提示集合可能不完整。 */
191
+ kind: "unfinished-snapshot";
192
+ experimentId: string;
193
+ startedAt: string;
194
+ /** 该快照目录的绝对路径。 */
195
+ dir: string;
196
+ message: string;
197
+ };
198
+ /** dedupeAttempts 的警告:身份键缺 startedAt,宁可不去重也不误删。 */
199
+ export interface DedupeWarning {
200
+ kind: "missing-startedAt";
201
+ experimentId: string;
202
+ evalId: string;
203
+ message: string;
204
+ }
@@ -0,0 +1,22 @@
1
+ export interface CapturedEvalSource {
2
+ /** 项目相对路径(正斜杠),与 SourceArtifact.path / SourceLoc.file 同一约定。 */
3
+ path: string;
4
+ /** 归一化后的源码文本(去 BOM、CRLF/CR 统一成 LF)。 */
5
+ content: string;
6
+ /** 归一化文本的 SHA-256 十六进制摘要;同一份内容(哪怕跨平台不同换行符)恒相同。 */
7
+ sha256: string;
8
+ }
9
+ /**
10
+ * 读一个 eval 定义文件、归一化文本、算哈希。`filePath` 是绝对路径(discoverEvals() 里
11
+ * `DiscoveredEval.sourcePath` 的形状);`opts.root` 决定 `path` 字段相对谁计算,省略时
12
+ * 用 `process.cwd()`(与 src/source-loc.ts 的 captureLoc()、runner/attempt.ts 的
13
+ * collectSources() 同一约定——项目相对路径永远相对进程 cwd,不是相对 discoverEvals() 的
14
+ * `root` 参数,两者通常相同但不保证,显式传参让调用方按需要覆盖,也让单测不依赖真实 cwd)。
15
+ *
16
+ * 读不到文件(已删除 / 权限问题)如实抛错——发现阶段的源码文件应当总是可读,
17
+ * 与 collectSources() 运行后"读不到就跳过"的降级语义不同:那时源码可能已经在沙箱里、
18
+ * 已被清理;这里读的是刚刚 import 成功的同一个文件,读不到是需要暴露的异常。
19
+ */
20
+ export declare function captureEvalSource(filePath: string, opts?: {
21
+ root?: string;
22
+ }): Promise<CapturedEvalSource>;
@@ -0,0 +1,23 @@
1
+ import type { DiscoveredEval, EvalResult } from "../types.ts";
2
+ import type { AgentRun } from "./types.ts";
3
+ export declare function cacheKey(run: AgentRun, evalId: string): string;
4
+ /**
5
+ * @param sourceCache 按 sourcePath 缓存文件内容:一个矩阵(实验 × eval)会对同一批源文件
6
+ * 反复算指纹,不带缓存会在任何 attempt 起跑前做 E×N 次重复文件读。
7
+ */
8
+ export declare function computeFingerprint(evalDef: DiscoveredEval, run: AgentRun, sourceCache?: Map<string, Promise<string>>): Promise<string>;
9
+ export interface CarryPlan {
10
+ /** `cacheKey(run, evalId)` → 本次规划出的指纹,供调用方按同一口径判断"这条要不要携入"。 */
11
+ plannedFingerprints: Map<string, string>;
12
+ /** 命中携入条件(passed/failed 终态 + 指纹匹配)的 `${experimentId}|${evalId}` 集合。 */
13
+ priorRunKeys: Set<string>;
14
+ /** priorRunKeys 对应的完整结果对象,供 run.ts 直接并入 summary、cli.ts 直接取 verdict 展示。 */
15
+ carriedResults: EvalResult[];
16
+ }
17
+ /**
18
+ * 算出这一批 (agentRun × eval) 的指纹,并据此从 priorResults 里筛出可以携入(跳过重跑)的结果。
19
+ * run.ts 与 cli.ts(live 表格构建)必须共用这同一份计算 —— 否则两边一旦对"哪些携入"的判断
20
+ * 不一致,live 表格就会显示"还在等名额",而 run.ts 其实已经把它筛掉、根本不会调度这个 attempt
21
+ * (见 memory 的 live-carry-row-shows-waiting-forever)。
22
+ */
23
+ export declare function planCarry(evals: DiscoveredEval[], agentRuns: AgentRun[], priorResults: EvalResult[] | undefined): Promise<CarryPlan>;
@@ -0,0 +1,332 @@
1
+ import type { Cleanup, LocalizedText, SourceArtifact } from "../shared/types.ts";
2
+ import type { O11ySummary, StreamEvent, TraceSpan, Usage } from "../o11y/types.ts";
3
+ import type { Agent, AgentSetupManifest } from "../agents/types.ts";
4
+ import type { Sandbox, SandboxOption } from "../sandbox/types.ts";
5
+ import type { AssertionResult, DiffData, JudgeConfig, Verdict } from "../scoring/types.ts";
6
+ import type { TestContext } from "../context/types.ts";
7
+ import type { CapturedEvalSource } from "./eval-source.ts";
8
+ export interface ExperimentRunInfo {
9
+ id?: string;
10
+ flags?: Record<string, unknown>;
11
+ runs?: number;
12
+ earlyExit?: boolean;
13
+ sandbox?: string;
14
+ timeoutMs?: number;
15
+ budget?: number;
16
+ }
17
+ export interface EvalResult {
18
+ id: string;
19
+ description?: string;
20
+ experimentId?: string;
21
+ experiment?: ExperimentRunInfo;
22
+ agent: string;
23
+ model?: string;
24
+ verdict: Verdict;
25
+ fingerprint?: string;
26
+ attempt: number;
27
+ /** 本 attempt 开始的墙钟时刻(ISO);view 按 eval 粒度展示「何时跑的」。 */
28
+ startedAt?: string;
29
+ /**
30
+ * 不透明的 Attempt 定位符(`@` 前缀短确定性编码,见 `src/results/locator.ts` 的 AttemptLocator),
31
+ * 由 {experimentId, 快照 startedAt, evalId, attempt} 身份元组派生。非携带条目由 writer 在落盘时
32
+ * 算出;携带条目(`--resume` 合入)原样复制上一轮的值,从不重算——原快照的 startedAt 已经不在
33
+ * 当前快照里,重算会算出不同的字符串,详见 writer.ts 对携带分支的说明。省略时读取面按当前
34
+ * 已知身份兜底算出(第三方 harness 未实现 locator 时的降级,不保证跨 --resume 稳定)。
35
+ */
36
+ locator?: string;
37
+ durationMs: number;
38
+ assertions: AssertionResult[];
39
+ usage?: Usage;
40
+ estimatedCostUSD?: number;
41
+ error?: string;
42
+ skipReason?: string;
43
+ events?: StreamEvent[];
44
+ /** test 引用到的 eval 源码(按 loc 收集),供 view 渲染 github-diff 式代码视图。 */
45
+ sources?: SourceArtifact[];
46
+ o11y?: O11ySummary;
47
+ /** agent 经 OpenTelemetry 导出的运行追踪(有 tracing 能力且收到 span 时)。 */
48
+ trace?: TraceSpan[];
49
+ /** 本 attempt 的 agent setup 实际装了什么(Skill / native plugin / MCP / Python plugin);不参与评分。 */
50
+ agentSetup?: AgentSetupManifest;
51
+ diff?: DiffData;
52
+ rawTranscript?: string;
53
+ /** 携带条目(--resume 合入)专用:artifact 目录(相对结果根目录),指向原快照里的落盘。 */
54
+ artifactBase?: string;
55
+ hasTrace?: boolean;
56
+ hasEvents?: boolean;
57
+ hasSources?: boolean;
58
+ }
59
+ /** `snapshot.json` 的格式标记;把 niceeval 报告和其它工具的同名文件区分开。 */
60
+ export declare const RESULTS_FORMAT = "niceeval.results";
61
+ /**
62
+ * 结果格式版本,只在破坏兼容读取时递增;读取器只认相同版本。见 docs/feature/results/architecture.md。
63
+ * `5`(见 memory 的 attempt-locator-and-source-dedup 条目)= result.json 新增 `locator` 字段;
64
+ * `sources.json` 从逐 attempt 内联全量内容改为「attempt 级引用 + 快照级 `sources/<sha256>.json`
65
+ * 去重仓库」,`AttemptHandle.sources()` 的公开返回形状不变(仍是 `SourceArtifact[] | null`)。
66
+ */
67
+ export declare const RESULTS_SCHEMA_VERSION = 5;
68
+ /** 一次运行的纯运行时内存聚合(reporter 契约用);落盘格式契约在 niceeval/results 的 SnapshotMeta / AttemptRecord,见 docs/feature/results/architecture.md。 */
69
+ export interface RunSummary {
70
+ /** 项目名(来自 config.name),透传给 `niceeval view` 顶部 hero 显示。 */
71
+ name?: LocalizedText;
72
+ agent: string;
73
+ model?: string;
74
+ startedAt: string;
75
+ completedAt: string;
76
+ passed: number;
77
+ /** 断言不通过的数量;不包含 errored。 */
78
+ failed: number;
79
+ skipped: number;
80
+ /** 环境、超时、adapter、agent runtime 等执行错误数量;与 failed 互斥。 */
81
+ errored: number;
82
+ durationMs: number;
83
+ usage?: Usage;
84
+ estimatedCostUSD?: number;
85
+ results: EvalResult[];
86
+ }
87
+ /** onRunStart 的运行规模:去重后 eval 数 × 配置(agent×model×flags)数 → 总运行(attempt)数。 */
88
+ export interface RunShape {
89
+ /** 去重后实际要跑的 eval 数(= evals.length)。 */
90
+ evals: number;
91
+ /** (agent, model, flags) 配置组合数;compare 多 agent 时 > 1。 */
92
+ configs: number;
93
+ /** 总 attempt 数(evals × configs × runs);逐行输出与汇总计数都按它。 */
94
+ totalRuns: number;
95
+ /** 本次运行实际生效的全局并发数(flag/env/config/sandbox 默认值解析后的结果);
96
+ * 实验级 maxConcurrency 只在该实验内部限流,不改这个全局值。 */
97
+ maxConcurrency: number;
98
+ }
99
+ export interface Reporter {
100
+ onEvent?(event: ReporterEvent): void | Promise<void>;
101
+ onRunStart?(evals: {
102
+ id: string;
103
+ }[], agent: Agent, shape?: RunShape): void | Promise<void>;
104
+ onEvalComplete?(result: EvalResult): void | Promise<void>;
105
+ onRunComplete?(summary: RunSummary): void | Promise<void>;
106
+ }
107
+ export type ReporterEvent = {
108
+ type: "run:start";
109
+ evals: {
110
+ id: string;
111
+ }[];
112
+ agent: Agent;
113
+ shape: RunShape;
114
+ } | {
115
+ type: "eval:start";
116
+ eval: {
117
+ id: string;
118
+ };
119
+ agent: Agent;
120
+ model?: string;
121
+ attempt: number;
122
+ experimentId?: string;
123
+ } | {
124
+ type: "eval:complete";
125
+ result: EvalResult;
126
+ } | {
127
+ type: "run:earlyExit";
128
+ evalId: string;
129
+ experimentId?: string;
130
+ } | {
131
+ type: "run:budgetExceeded";
132
+ budget: number;
133
+ spent: number;
134
+ } | {
135
+ type: "run:saved";
136
+ summary: RunSummary;
137
+ } | {
138
+ type: "run:summary";
139
+ summary: RunSummary;
140
+ };
141
+ export interface EvalDef {
142
+ /** 路径推导,定义里禁止手写。 */
143
+ id?: string;
144
+ /** 一句话描述,展示在 `niceeval list` 和 view 里;纯说明,不影响调度或打分。 */
145
+ description?: string;
146
+ /** 标签,供 CLI `--tag` 过滤和 view 分类;与 id 前缀过滤是两套独立的筛选维度。 */
147
+ tags?: string[];
148
+ /** 覆盖项目级 Config.judge,只对这一个 eval 生效(如换个更贵的评审模型)。 */
149
+ judge?: JudgeConfig;
150
+ /** 覆盖 / 追加项目级 Config.reporters,只对这一个 eval 生效。 */
151
+ reporters?: Reporter[];
152
+ /** 覆盖项目级 / CLI 的单次 attempt 超时(毫秒),只对这一个 eval 生效。 */
153
+ timeoutMs?: number;
154
+ /** 任意附加元数据,原样透传进 EvalResult,不参与调度或打分;供自定义 reporter 消费。 */
155
+ metadata?: Record<string, unknown>;
156
+ /**
157
+ * eval 级预置:拿到沙箱(已上传 workspace + git 基线 + 装好依赖前)。
158
+ * 默认命令以非 root 跑(agent 的自然环境);装系统依赖时给 `runCommand` 传 `{ root: true }`
159
+ * (如 `runCommand("apt-get", ["install", …], { root: true })`),跨 provider 语义一致。
160
+ */
161
+ setup?: (sandbox: Sandbox) => Promise<void | Cleanup> | void | Cleanup;
162
+ /** eval 主体:拿到 TestContext,驱动对话 / 沙箱操作并就地断言。 */
163
+ test(t: TestContext): Promise<void> | void;
164
+ }
165
+ /** 内部:发现后带上 id 的 eval。 */
166
+ export interface DiscoveredEval extends EvalDef {
167
+ id: string;
168
+ /** 定义文件所在目录(解析相对 workspace 用)。 */
169
+ baseDir: string;
170
+ /** 定义文件绝对路径,用于内容指纹缓存。 */
171
+ sourcePath: string;
172
+ /**
173
+ * discovery 时捕获的规范化源码(归一化文本 + 项目相对路径 + SHA-256),见 `eval-source.ts`。
174
+ * 同一文件里多个 eval(数组默认导出)共享同一份引用——哈希与内容天然相同,不重复读盘。
175
+ */
176
+ source: CapturedEvalSource;
177
+ }
178
+ export interface ExperimentDef {
179
+ /** 路径推导,定义里禁止手写(defineExperiment 会拒绝显式传入)。 */
180
+ id?: string;
181
+ /** 一句话描述,展示在 view / CLI 里;纯说明,不影响调度或打分。 */
182
+ description?: string;
183
+ /**
184
+ * 必填:这个实验跑哪个 agent(defineSandboxAgent / defineAgent 的产物)。运行配置的
185
+ * agent 归属完全由这里决定——EvalDef.agent 不参与(见其字段注释)。
186
+ */
187
+ agent: Agent;
188
+ /** 单个模型(agent 留空时实验决定);省略=用 agent 原生默认。跨模型对比写多个实验文件,别用数组。 */
189
+ model?: string;
190
+ /** 模型推理努力程度(如 "low"/"medium"/"high",取值由具体模型/adapter 决定);省略=用 agent 原生默认。经 ctx.reasoningEffort 透给 adapter 与 eval。 */
191
+ reasoningEffort?: string;
192
+ /** 实验条件(A/B 里的 feature flag),由实验文件声明;经 ctx.flags 透传给 adapter、t.flags 暴露给 eval。 */
193
+ flags?: Record<string, unknown>;
194
+ /** 同一 eval 重复跑几次(结果各计一条 attempt);省略/CLI `--runs` 覆盖时默认 1。 */
195
+ runs?: number;
196
+ /** 一次重复(runs > 1)里某次 attempt 失败后是否跳过剩余重复;省略默认 true(提前退出省钱)。 */
197
+ earlyExit?: boolean;
198
+ /** 这个实验覆盖哪些 eval:"*" 全部、字符串数组按 id 前缀、或自定义谓词;省略等价于 "*"。 */
199
+ evals?: "*" | string[] | ((id: string) => boolean);
200
+ /** 覆盖项目级 / CLI 的单次 attempt 超时(毫秒),只对这个实验生效。 */
201
+ timeoutMs?: number;
202
+ /** 覆盖项目级 Config.sandbox,只对这个实验生效。 */
203
+ sandbox?: SandboxOption;
204
+ /**
205
+ * 本实验的花费上限(USD)。调度器按「已花 + 在飞预估」的护栏口径逼近上限时限流,
206
+ * 累计花费到顶后跳过这个实验剩下未起飞的 attempt 并上报一次 `run:budgetExceeded`
207
+ * (已在飞的 attempt 仍会跑完)。
208
+ */
209
+ budget?: number;
210
+ /**
211
+ * 本实验自己的并发上限:调度器只对这个实验的 attempt 限流,同批其它实验不受影响,
212
+ * 仍按全局并发(CLI / env / config / 沙箱默认)跑。用于串行化有共享状态的实验
213
+ * (如跨 eval 累积记忆:`maxConcurrency: 1` 保证 attempt 按 eval 顺序一个个跑),
214
+ * 或给撞 provider 限额的实验单独降速。
215
+ */
216
+ maxConcurrency?: number;
217
+ }
218
+ export interface DiscoveredExperiment extends ExperimentDef {
219
+ id: string;
220
+ group: string;
221
+ }
222
+ export interface Config {
223
+ /**
224
+ * 项目名,显示在 `niceeval view` 顶部 hero(`<h1>`),省略则回退到通用标题。
225
+ * 可传字符串,或按 locale 提供多语言(如 `{ en: "...", "zh-CN": "..." }`),随 view 语言切换。
226
+ */
227
+ name?: LocalizedText;
228
+ /** 项目级默认沙箱 provider(docker / vercel / e2b / custom);experiment 可覆盖。 */
229
+ sandbox?: SandboxOption;
230
+ /** 上传进沙箱的工作区根目录,省略则用项目根;eval 的 sandbox 视图从这里起步。 */
231
+ workspace?: string;
232
+ /** 项目级默认 judge 配置(model / baseUrl / apiKeyEnv);EvalDef.judge 可按 eval 覆盖。 */
233
+ judge?: JudgeConfig;
234
+ /** 项目级默认 reporter 列表(如落盘 / 上传结果);EvalDef.reporters 会与它合并。 */
235
+ reporters?: Reporter[];
236
+ /** 项目级默认并发上限;CLI flag / env / experiment 的同名设置优先级更高。 */
237
+ maxConcurrency?: number;
238
+ /** 项目级默认单次 attempt 超时(毫秒);CLI flag / experiment / EvalDef 的同名设置优先级更高。 */
239
+ timeoutMs?: number;
240
+ /**
241
+ * OTLP 接收配置,niceeval 项目内唯一入口(不读 NICEEVAL_OTLP_* 环境变量)。
242
+ * `port` 钉住接收端口(固定端口模式:长驻服务把 OTEL_EXPORTER_OTLP_ENDPOINT 一次性指到
243
+ * http://localhost:<port>/v1/traces,跑多少次 eval 都不用改)。省略 = 每次运行动态分配
244
+ * 临时端口(经 ctx.telemetry 交给 adapter)。代价:固定端口下同机同时只能跑一个 niceeval 进程,
245
+ * 且该端口被别的进程占用时会报错——换一个空闲端口写回这里即可。
246
+ * `host` 是报给 adapter 的接收端 hostname(而非监听地址,监听地址恒为 0.0.0.0):默认
247
+ * "127.0.0.1";docker 沙箱型 tracing 需要 "host.docker.internal" 之类的场景,或配了隧道
248
+ * 的远程接入,在这里覆盖。
249
+ */
250
+ telemetry?: {
251
+ host?: string;
252
+ port?: number;
253
+ };
254
+ /**
255
+ * 内置价格表(`o11y/prices.json`)之上的用户覆盖 / 补充,按 model 查(见 Observability
256
+ * · 用量与成本)。key 支持精确 model 名或 `provider/*` 通配(自托管/网关折扣按 provider 批量覆盖);
257
+ * 精确 key 优先于通配。只在没有网关实测成本(`usage.costUSD`)时才会用到——实测优先于估算恒成立。
258
+ */
259
+ pricing?: Record<string, PriceOverride>;
260
+ }
261
+ /** 每百万 token 的美元单价;省略的桶退回 `inputPerMTok`(cache token 本质也是 input)。 */
262
+ export interface PriceOverride {
263
+ /** 普通输入 token 单价。 */
264
+ inputPerMTok: number;
265
+ /** 输出 token 单价。 */
266
+ outputPerMTok: number;
267
+ /** cache 命中(读)token 单价,省略则退回 inputPerMTok。 */
268
+ cacheReadPerMTok?: number;
269
+ /** cache 写入 token 单价,省略则退回 inputPerMTok。 */
270
+ cacheWritePerMTok?: number;
271
+ }
272
+ /**
273
+ * 进度行 / 日志里标识一个 run 配置的短名。有 experiment 时用其 basename(唯一,
274
+ * 能区分同 agent 同 model 的实验变体,如 xxx 与 xxx--agents-md;与汇总表口径一致);
275
+ * 无 experiment 时退回 agent/model。live display 以它作行聚合 key,两处必须同源。
276
+ */
277
+ export declare function runWho(run: {
278
+ agentName: string;
279
+ model?: string;
280
+ experimentId?: string;
281
+ }): string;
282
+ /** 一个 (agent, model, flags) 的运行配置 —— 由 CLI / 实验展开。 */
283
+ export interface AgentRun {
284
+ agent: Agent;
285
+ model?: string;
286
+ reasoningEffort?: string;
287
+ flags: Record<string, unknown>;
288
+ runs: number;
289
+ earlyExit: boolean;
290
+ sandbox?: SandboxOption;
291
+ timeoutMs?: number;
292
+ budget?: number;
293
+ evalFilter: (id: string) => boolean;
294
+ experimentId?: string;
295
+ strict?: boolean;
296
+ /** 本配置自己的并发上限(来自 ExperimentDef.maxConcurrency):调度器为它单建信号量,
297
+ * attempt 先过这道闸再占全局并发位;省略则只受全局并发约束。 */
298
+ maxConcurrency?: number;
299
+ }
300
+ export interface RunOptions {
301
+ config: Config;
302
+ evals: DiscoveredEval[];
303
+ agentRuns: AgentRun[];
304
+ reporters: Reporter[];
305
+ maxConcurrency: number;
306
+ signal?: AbortSignal;
307
+ /** TTY live display 的进度回调;设置后 attempt 的 log 消息路由到它而不是 stderr。 */
308
+ onProgress?: (evalId: string, who: string, msg: string) => void;
309
+ /** 上次运行的结果。verdict 为 passed/failed 的 (experimentId, evalId) 组合跳过重跑,结果直接合入本次汇总。 */
310
+ priorResults?: EvalResult[];
311
+ /**
312
+ * 预算好的携入计划(见 fingerprint.ts 的 planCarry)。cli.ts 为了让 live 表格提前知道
313
+ * 哪些行会被携入,必须在构建 liveRows 之前算一次;传进来后 runEvals 直接复用,不重算
314
+ * 一遍(否则两处各自算一次,不仅重复 I/O,还留下"两边判断可能不一致"的隐患)。
315
+ * 省略时 runEvals 自己算(测试直调等场景)。
316
+ */
317
+ carryPlan?: import("./fingerprint.ts").CarryPlan;
318
+ /**
319
+ * 非沙箱 tracing agent 的 run 级共享 OTLP 接收池(runEvals 创建并回收;
320
+ * 每个 agent 一个 receiver,attempt 之间共享 —— 被测应用是长驻进程,端点不能随 attempt 换)。
321
+ */
322
+ otelPool?: import("../o11y/otlp/turn-otel.ts").OtelReceiverPool;
323
+ }
324
+ /** 调度器内部的一次尝试:eval × run × 第几轮。 */
325
+ export interface Attempt {
326
+ evalDef: DiscoveredEval;
327
+ run: AgentRun;
328
+ attempt: number;
329
+ /** agent+model+evalId,用于首过即停。 */
330
+ key: string;
331
+ fingerprint: string;
332
+ }
@@ -0,0 +1,24 @@
1
+ import * as tar from "tar-stream";
2
+ /**
3
+ * Docker exec 复用流(8 字节头 + 载荷)的增量解析器。
4
+ * 头:[stream_type(1B), 0, 0, 0, size(4B 大端)];stream_type:1=stdout,2=stderr。
5
+ *
6
+ * 关键:一帧可能被 Node 的可读流切到【多个 data 事件】里(尤其大输出,如 cat 一个
7
+ * ~100KB 的文件),帧头 / 载荷都可能跨 chunk。所以必须跨 data 累积一个 leftover,
8
+ * 只消费「已到齐的完整帧」,残帧留到下个 data —— 否则会在 chunk 边界丢字节 / 串帧,
9
+ * 表现为 transcript 里随机损坏的行(曾导致 bub tape 的 tool_result/tool_call 被吞)。
10
+ */
11
+ export declare function createExecDemuxer(): {
12
+ push(chunk: Buffer): void;
13
+ stdout(): string;
14
+ stderr(): string;
15
+ };
16
+ /** Readable stream → Buffer。 */
17
+ export declare function readableToBuffer(stream: NodeJS.ReadableStream): Promise<Buffer>;
18
+ /** 从单文件 tar 包里提取第一个 entry 的内容。 */
19
+ export declare function extractFileFromTar(tarBuf: Buffer): Promise<Buffer>;
20
+ /** 把若干文件打成 tar 流(putArchive 用)。 */
21
+ export declare function packFilesToTar(entries: readonly {
22
+ name: string;
23
+ content: Buffer;
24
+ }[]): tar.Pack;