niceeval 0.8.1 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/INDEX.md +77 -45
  2. package/dist/agents/types.d.ts +28 -6
  3. package/dist/i18n/en.d.ts +2 -0
  4. package/dist/i18n/zh-CN.d.ts +3 -1
  5. package/dist/report/built-in/index.d.ts +3 -2
  6. package/dist/report/built-in/index.js +7 -8
  7. package/dist/report/built-in/standard.d.ts +1 -0
  8. package/dist/report/built-in/standard.js +30 -0
  9. package/dist/report/components.d.ts +69 -2
  10. package/dist/report/components.js +152 -3
  11. package/dist/report/compute.d.ts +28 -1
  12. package/dist/report/compute.js +123 -0
  13. package/dist/report/index.d.ts +4 -4
  14. package/dist/report/index.js +3 -2
  15. package/dist/report/locale.d.ts +39 -1
  16. package/dist/report/locale.js +69 -0
  17. package/dist/report/react/AttemptList.d.ts +3 -1
  18. package/dist/report/react/AttemptList.js +3 -3
  19. package/dist/report/react/CopyFixPrompt.d.ts +12 -0
  20. package/dist/report/react/CopyFixPrompt.js +12 -0
  21. package/dist/report/react/HeroCard.d.ts +13 -0
  22. package/dist/report/react/HeroCard.js +35 -0
  23. package/dist/report/react/PoweredBy.d.ts +5 -0
  24. package/dist/report/react/PoweredBy.js +7 -0
  25. package/dist/report/react/ScopeWarnings.d.ts +12 -0
  26. package/dist/report/react/ScopeWarnings.js +18 -0
  27. package/dist/report/react/TraceWaterfall.d.ts +14 -0
  28. package/dist/report/react/TraceWaterfall.js +22 -0
  29. package/dist/report/react/index.d.ts +6 -1
  30. package/dist/report/react/index.js +6 -0
  31. package/dist/report/report.d.ts +22 -6
  32. package/dist/report/report.js +68 -55
  33. package/dist/report/scope-warnings.d.ts +28 -0
  34. package/dist/report/scope-warnings.js +101 -0
  35. package/dist/report/text/faces.d.ts +19 -1
  36. package/dist/report/text/faces.js +61 -0
  37. package/dist/report/tree.d.ts +1 -1
  38. package/dist/report/tree.js +7 -2
  39. package/dist/report/types.d.ts +45 -0
  40. package/dist/report/web.d.ts +5 -4
  41. package/dist/report/web.js +7 -22
  42. package/dist/results/select.d.ts +17 -4
  43. package/dist/results/select.js +76 -11
  44. package/dist/results/types.d.ts +26 -0
  45. package/dist/runner/fingerprint.d.ts +3 -3
  46. package/dist/runner/sandbox-selection.d.ts +12 -0
  47. package/dist/runner/types.d.ts +18 -6
  48. package/dist/sandbox/types.d.ts +12 -0
  49. package/dist/shared/aggregate.d.ts +1 -1
  50. package/dist/shared/aggregate.js +1 -1
  51. package/docs-site/zh/explanation/evals.mdx +2 -1
  52. package/docs-site/zh/explanation/experiment.mdx +2 -0
  53. package/docs-site/zh/how-to/custom-reports.mdx +23 -7
  54. package/docs-site/zh/how-to/experiments.mdx +2 -2
  55. package/docs-site/zh/how-to/publish-report.mdx +11 -4
  56. package/docs-site/zh/how-to/viewing-results.mdx +17 -8
  57. package/docs-site/zh/how-to/write-experiment.mdx +40 -1
  58. package/docs-site/zh/reference/builtin-agents.mdx +40 -3
  59. package/docs-site/zh/reference/cli.mdx +3 -3
  60. package/docs-site/zh/reference/define-eval.mdx +8 -0
  61. package/docs-site/zh/reference/official-adapters.mdx +10 -5
  62. package/docs-site/zh/troubleshooting/debugging.mdx +3 -3
  63. package/package.json +2 -1
  64. package/src/agents/bub.ts +13 -1
  65. package/src/agents/claude-code.test.ts +43 -1
  66. package/src/agents/claude-code.ts +32 -14
  67. package/src/agents/codex.test.ts +168 -1
  68. package/src/agents/codex.ts +51 -15
  69. package/src/agents/mcp.ts +31 -0
  70. package/src/agents/post-setup.ts +33 -0
  71. package/src/agents/types.ts +28 -7
  72. package/src/cli.ts +15 -14
  73. package/src/define.ts +3 -0
  74. package/src/i18n/en.ts +8 -5
  75. package/src/i18n/zh-CN.ts +8 -4
  76. package/src/index.ts +1 -0
  77. package/src/report/built-in/index.tsx +8 -7
  78. package/src/report/built-in/standard.tsx +59 -0
  79. package/src/report/components.tsx +218 -2
  80. package/src/report/compute.ts +138 -1
  81. package/src/report/dual-render.test.tsx +141 -14
  82. package/src/report/index.ts +20 -0
  83. package/src/report/locale.ts +83 -1
  84. package/src/report/react/AttemptList.tsx +13 -1
  85. package/src/report/react/CopyFixPrompt.tsx +37 -0
  86. package/src/report/react/HeroCard.tsx +59 -0
  87. package/src/report/react/PoweredBy.tsx +20 -0
  88. package/src/report/react/ScopeWarnings.tsx +74 -0
  89. package/src/report/react/TraceWaterfall.tsx +78 -0
  90. package/src/report/react/enhance.js +14 -0
  91. package/src/report/react/index.tsx +11 -0
  92. package/src/report/react/styles.css +193 -7
  93. package/src/report/report.ts +99 -64
  94. package/src/report/scope-warnings.ts +155 -0
  95. package/src/report/site-components.test.tsx +526 -0
  96. package/src/report/text/faces.ts +66 -0
  97. package/src/report/tree.ts +10 -3
  98. package/src/report/types.ts +51 -0
  99. package/src/report/web.ts +7 -40
  100. package/src/results/host-equivalence.test.ts +6 -2
  101. package/src/results/open.ts +5 -4
  102. package/src/results/results.test.ts +78 -1
  103. package/src/results/select.ts +80 -12
  104. package/src/results/types.ts +27 -0
  105. package/src/runner/attempt.ts +10 -9
  106. package/src/runner/discover.test.ts +9 -1
  107. package/src/runner/discover.ts +3 -3
  108. package/src/runner/fingerprint.ts +9 -4
  109. package/src/runner/ledger.test.ts +30 -1
  110. package/src/runner/ledger.ts +26 -4
  111. package/src/runner/run.ts +5 -1
  112. package/src/runner/sandbox-selection.test.ts +131 -0
  113. package/src/runner/sandbox-selection.ts +110 -0
  114. package/src/runner/types.ts +19 -2
  115. package/src/sandbox/types.ts +6 -0
  116. package/src/shared/aggregate.ts +1 -1
  117. package/src/show/index.ts +19 -12
  118. package/src/show/render.ts +12 -12
  119. package/src/show/report-host.test.ts +34 -17
  120. package/src/show/report-host.ts +6 -5
  121. package/src/show/show.test.ts +141 -4
  122. package/src/view/app/App.test.tsx +79 -17
  123. package/src/view/app/App.tsx +25 -74
  124. package/src/view/app/components/CopyControls.tsx +4 -42
  125. package/src/view/app/i18n.ts +5 -227
  126. package/src/view/app/lib/rows.ts +3 -21
  127. package/src/view/app/shared.ts +1 -3
  128. package/src/view/app/types.ts +2 -2
  129. package/src/view/client-dist/app.css +1 -1
  130. package/src/view/client-dist/app.js +20 -20
  131. package/src/view/data.ts +21 -10
  132. package/src/view/index.ts +2 -12
  133. package/src/view/server.ts +4 -4
  134. package/src/view/shared/types.ts +11 -6
  135. package/src/view/styles.css +9 -252
  136. package/src/view/view-report.test.ts +99 -33
  137. package/src/view/app/components/LazyArtifact.tsx +0 -51
  138. package/src/view/app/components/SkippedRunsBanner.tsx +0 -140
  139. package/src/view/app/pages/AttemptsPage.tsx +0 -80
  140. package/src/view/app/pages/TracesPage.tsx +0 -35
@@ -1,8 +1,7 @@
1
1
  import React, { useState } from "react";
2
2
  import { Check, Copy } from "lucide-react";
3
3
  import type { T } from "../shared.ts";
4
- import type { ViewResult, ViewSnapshot } from "../types.ts";
5
- import { snapshotLabel } from "../lib/rows.ts";
4
+ import type { ViewResult } from "../types.ts";
6
5
  import { reasonFor } from "../lib/verdict.ts";
7
6
 
8
7
  /** 修复 prompt 的一条失败条目;路径均相对 view 输入根(默认 `.niceeval/`)。 */
@@ -63,46 +62,9 @@ export function buildFixPrompt(entries: FixPromptEntry[]): string {
63
62
  ].join("\n");
64
63
  }
65
64
 
66
- /**
67
- * 报告槽同款口径的失败清单:每个 experiment 最新一次快照(latest 标记;快照明细已在
68
- * server 侧跨快照去重)里的 failed / errored attempt,从 viewData.snapshots 现算——
69
- * 默认报告与 --report 两种填充下按钮都在,不依赖任何统计产物。
70
- */
71
- export function fixPromptEntries(snapshots: ViewSnapshot[]): FixPromptEntry[] {
72
- return snapshots
73
- .filter((s) => s.latest)
74
- .flatMap((snapshot) =>
75
- snapshot.results
76
- .filter((r: ViewResult) => r.verdict === "failed" || r.verdict === "errored")
77
- .map((r: ViewResult) => toFixPromptEntry(r, snapshotLabel(snapshot))),
78
- );
79
- }
80
-
81
- export function CopyFixPrompt({ snapshots, t }: { snapshots: ViewSnapshot[]; t: T }) {
82
- const [copied, setCopied] = useState(false);
83
-
84
- const entries = fixPromptEntries(snapshots);
85
-
86
- if (!entries.length) return null;
87
-
88
- const copy = async (event: React.MouseEvent<HTMLButtonElement>) => {
89
- event.stopPropagation();
90
- try {
91
- await copyText(buildFixPrompt(entries));
92
- setCopied(true);
93
- setTimeout(() => setCopied(false), 1500);
94
- } catch {
95
- setCopied(false);
96
- }
97
- };
98
-
99
- return (
100
- <button className={`copy-all-errors${copied ? " is-copied" : ""}`} onClick={copy} title={t("action.copyPrompt")}>
101
- {copied ? <Check aria-hidden="true" /> : <Copy aria-hidden="true" />}
102
- <span>{copied ? t("action.copied") : `${t("action.copyPrompt")} (${entries.length})`}</span>
103
- </button>
104
- );
105
- }
65
+ // 批量修复 prompt 不再由壳渲染:它是内建报告首页里的 CopyFixPrompt 组件
66
+ // (niceeval/report 的站点组件,prompt resolve 期烘进静态 HTML)。这里只留
67
+ // attempt 弹窗的单条版。
106
68
 
107
69
  /** attempt 弹窗里的单条版:只打包当前 attempt 的失败,供逐条转交 agent。 */
108
70
  export function CopyAttemptPrompt({ result, t }: { result: ViewResult; t: T }) {
@@ -1,78 +1,22 @@
1
1
  // view 前端 i18n:内核(插值/归一)在 src/i18n/core.ts;这里只注入
2
2
  // localStorage + navigator 的 locale 来源与 en 默认值。字典与 CLI 侧分开维护。
3
+ // 词条只覆盖宿主机器(导航标签、attempt 详情弹窗):页面内容(hero、警告、列表、瀑布)
4
+ // 是报告组件,文案在 niceeval/report 的组件词典里(src/report/locale.ts)。
3
5
 
4
6
  import { interpolate, normalizeLocale, type Locale, type Vars } from "../../i18n/core.ts";
5
7
 
6
8
  export type MessageKey =
7
- | "app.title"
8
9
  | "nav.label"
9
- | "nav.report"
10
- | "nav.experiments"
11
- | "nav.attempts"
12
- | "nav.traces"
13
10
  | "hero.title"
14
- | "hero.lastRun"
15
- | "hero.noRuns"
16
- | "metric.passRate"
17
- | "metric.evalResults"
18
- | "metric.duration"
19
- | "metric.cost"
20
- | "section.experiments"
21
- | "section.attempts"
22
- | "section.traces"
23
- | "search.experiments"
24
- | "search.attempts"
25
- | "empty.summary"
26
- | "empty.attempts"
27
- | "empty.attemptsFilter"
28
- | "empty.traces"
29
- | "table.experiment"
30
- | "table.model"
31
- | "table.agent"
32
- | "table.avgDuration"
33
- | "table.successRate"
34
- | "table.tokens"
35
- | "table.estCost"
36
- | "table.verdicts"
37
- | "table.evalId"
38
- | "table.verdict"
39
- | "table.ranAt"
40
- | "detail.evalResult"
41
- | "detail.evalResults"
42
- | "detail.attempts"
43
- | "detail.evals"
44
- | "detail.runs"
45
- | "detail.runsUnit"
46
- | "detail.passed"
47
- | "detail.failed"
48
- | "detail.errored"
49
- | "detail.totalTime"
50
- | "detail.totalCost"
51
- | "detail.ran"
52
- | "detail.evaluationAttempts"
53
- | "detail.status"
54
- | "detail.eval"
55
- | "detail.reason"
56
- | "detail.time"
57
- | "detail.run"
58
- | "detail.rawSample"
59
- | "detail.rawNote"
60
- | "config.experiment"
61
- | "config.flagsNone"
62
- | "config.default"
63
- | "config.none"
64
- | "config.notApplicable"
65
11
  | "status.pass"
66
12
  | "status.fail"
67
13
  | "status.error"
68
14
  | "status.skipped"
69
15
  | "action.close"
70
- | "action.copyReason"
71
16
  | "action.copyPrompt"
72
17
  | "action.copied"
73
18
  | "trace.loading"
74
19
  | "trace.loadFailed"
75
- | "trace.transcript"
76
20
  | "trace.timing"
77
21
  | "trace.noSpans"
78
22
  | "trace.total"
@@ -111,100 +55,25 @@ export type MessageKey =
111
55
  | "assert.unavailable"
112
56
  | "assert.optional"
113
57
  | "assert.soft"
114
- | "assert.evidence"
115
- | "verdict.passed"
116
- | "verdict.failed"
117
- | "verdict.errored"
118
- | "verdict.skipped"
119
- | "banner.skippedTitle"
120
- | "banner.skipped.incompatible"
121
- | "banner.skipped.incompatibleForeign"
122
- | "banner.skipped.malformed"
123
- | "banner.skipped.incomplete"
124
- | "banner.expandRest"
125
- | "banner.collapse"
126
- | "banner.copyCommand"
127
- | "banner.warningsTitle"
128
- | "hero.composedFrom"
129
- | "chart.costVsScore"
130
- | "chart.axisCost"
131
- | "chart.axisScore";
58
+ | "assert.evidence";
132
59
 
133
60
  type Dictionary = Record<MessageKey, string>;
134
61
 
135
62
  const dictionaries: Record<Locale, Dictionary> = {
136
63
  en: {
137
- "app.title": "niceeval experiment view",
138
64
  "nav.label": "Report",
139
- "nav.report": "Report",
140
- "nav.experiments": "Experiments",
141
- "nav.attempts": "Attempts",
142
- "nav.traces": "Traces",
143
65
  // 标题回退链终点的内置文案(shell.md:「Eval 运行结果 / Eval Results」);
144
66
  // 正常路径 server 侧已走完回退链,这里只兜旧数据 / 缺声明。
145
67
  "hero.title": "Eval Results",
146
- "hero.lastRun": "Last run:",
147
- "hero.noRuns": "No runs yet",
148
- "metric.passRate": "Pass Rate",
149
- "metric.evalResults": "Eval Results",
150
- "metric.duration": "Duration",
151
- "metric.cost": "Estimated Cost",
152
- "section.experiments": "Experiments",
153
- "section.attempts": "Attempts",
154
- "section.traces": "Traces",
155
- "search.experiments": "Filter experiment, agent, model, or eval...",
156
- "search.attempts": "Filter eval ID or experiment...",
157
- "empty.summary": "No snapshots found. Run niceeval or pass niceeval view path/to/snapshot.json.",
158
- "empty.attempts": "No attempts found.",
159
- "empty.attemptsFilter": "No results match the filter.",
160
- "empty.traces": "No traces available. Traces are collected during eval runs when artifacts are saved.",
161
- "table.experiment": "Experiment",
162
- "table.model": "Model",
163
- "table.agent": "Agent",
164
- "table.avgDuration": "Avg Duration",
165
- "table.successRate": "Success Rate",
166
- "table.tokens": "Tokens",
167
- "table.estCost": "Est. Cost",
168
- "table.verdicts": "Verdicts",
169
- "table.evalId": "Eval ID",
170
- "table.verdict": "Verdict",
171
- "table.ranAt": "Ran At",
172
- "detail.evalResult": "eval",
173
- "detail.evalResults": "evals",
174
- "detail.attempts": "Attempts",
175
- "detail.evals": "Evals",
176
- "detail.runs": "Runs",
177
- "detail.runsUnit": "runs",
178
- "detail.passed": "Passed",
179
- "detail.failed": "Failed",
180
- "detail.errored": "Errored",
181
- "detail.totalTime": "Total Time",
182
- "detail.totalCost": "Total Cost",
183
- "detail.ran": "Ran",
184
- "detail.evaluationAttempts": "Evals",
185
- "detail.status": "Status",
186
- "detail.eval": "Eval",
187
- "detail.reason": "Reason",
188
- "detail.time": "Time",
189
- "detail.run": "Run",
190
- "detail.rawSample": "Raw sample result",
191
- "detail.rawNote": "debug JSON, defaults to first error/failure when available",
192
- "config.experiment": "experiment",
193
- "config.flagsNone": "none",
194
- "config.default": "default",
195
- "config.none": "none",
196
- "config.notApplicable": "n/a",
197
68
  "status.pass": "pass",
198
69
  "status.fail": "fail",
199
70
  "status.error": "error",
200
71
  "status.skipped": "skipped",
201
72
  "action.close": "Close",
202
- "action.copyReason": "Copy reason",
203
73
  "action.copyPrompt": "Copy fix prompt",
204
74
  "action.copied": "Copied",
205
75
  "trace.loading": "loading...",
206
76
  "trace.loadFailed": "load failed (static report has no server - use niceeval view):",
207
- "trace.transcript": "transcript",
208
77
  "trace.timing": "timing trace",
209
78
  "trace.noSpans": "no spans",
210
79
  "trace.total": "total",
@@ -244,94 +113,19 @@ const dictionaries: Record<Locale, Dictionary> = {
244
113
  "assert.optional": "optional",
245
114
  "assert.soft": "soft",
246
115
  "assert.evidence": "What was checked",
247
- "verdict.passed": "passed",
248
- "verdict.failed": "failed",
249
- "verdict.errored": "errors",
250
- "verdict.skipped": "skipped",
251
- "banner.skippedTitle": "{{count}} run(s) could not be loaded and are not shown here",
252
- "banner.skipped.incompatible": "written by niceeval {{producer}} (schemaVersion {{schemaVersion}}) — current version can't read it, expand for the view command",
253
- "banner.skipped.incompatibleForeign": "written by {{name}} {{version}} (schemaVersion {{schemaVersion}}) — this viewer cannot read them; open with the tool that produced them",
254
- "banner.skipped.malformed": "unreadable report ({{detail}}) — may be corrupted; re-run the eval or delete the run directory",
255
- "banner.skipped.incomplete": "snapshot.json was never written (a narrow crash window) — completed attempt artifacts remain on disk for manual inspection; delete the directory if you no longer need them",
256
- "banner.expandRest": "Show {{count}} more",
257
- "banner.collapse": "Collapse",
258
- "banner.copyCommand": "Copy view command",
259
- "banner.warningsTitle": "Heads-up about the current leaderboard selection:",
260
- "hero.composedFrom": "Composed from {{count}} run(s)",
261
- "chart.costVsScore": "Cost vs. Score",
262
- "chart.axisCost": "Avg cost per eval",
263
- "chart.axisScore": "Pass rate",
264
116
  },
265
117
  "zh-CN": {
266
- "app.title": "niceeval 实验查看器",
267
118
  "nav.label": "报告",
268
- "nav.report": "报告",
269
- "nav.experiments": "实验",
270
- "nav.attempts": "Attempts",
271
- "nav.traces": "追踪",
272
119
  "hero.title": "Eval 运行结果",
273
- "hero.lastRun": "最近运行:",
274
- "hero.noRuns": "还没有运行",
275
- "metric.passRate": "通过率",
276
- "metric.evalResults": "Eval 结果",
277
- "metric.duration": "耗时",
278
- "metric.cost": "预估成本",
279
- "section.experiments": "实验",
280
- "section.attempts": "Attempts",
281
- "section.traces": "追踪",
282
- "search.experiments": "筛选实验、agent、model 或 eval...",
283
- "search.attempts": "筛选 eval ID 或实验...",
284
- "empty.summary": "没有找到快照。请先运行 niceeval,或传入 niceeval view path/to/snapshot.json。",
285
- "empty.attempts": "还没有 attempt。",
286
- "empty.attemptsFilter": "没有匹配筛选条件的结果。",
287
- "empty.traces": "没有可用追踪。保存 artifact 的 eval run 会收集 traces。",
288
- "table.experiment": "实验",
289
- "table.model": "模型",
290
- "table.agent": "Agent",
291
- "table.avgDuration": "平均耗时",
292
- "table.successRate": "成功率",
293
- "table.tokens": "Tokens",
294
- "table.estCost": "预估成本",
295
- "table.verdicts": "结果",
296
- "table.evalId": "Eval ID",
297
- "table.verdict": "状态",
298
- "table.ranAt": "运行时间",
299
- "detail.evalResult": "个 eval",
300
- "detail.evalResults": "个 eval",
301
- "detail.attempts": "尝试",
302
- "detail.evals": "Eval 数",
303
- "detail.runs": "总轮次",
304
- "detail.runsUnit": "轮",
305
- "detail.passed": "通过",
306
- "detail.failed": "失败",
307
- "detail.errored": "错误",
308
- "detail.totalTime": "总耗时",
309
- "detail.totalCost": "总成本",
310
- "detail.ran": "运行",
311
- "detail.evaluationAttempts": "各 Eval",
312
- "detail.status": "状态",
313
- "detail.eval": "Eval",
314
- "detail.reason": "原因",
315
- "detail.time": "耗时",
316
- "detail.run": "轮次",
317
- "detail.rawSample": "原始样例结果",
318
- "detail.rawNote": "调试 JSON,默认选择第一条错误/失败",
319
- "config.experiment": "实验",
320
- "config.flagsNone": "无",
321
- "config.default": "默认",
322
- "config.none": "无",
323
- "config.notApplicable": "不适用",
324
120
  "status.pass": "通过",
325
121
  "status.fail": "失败",
326
122
  "status.error": "错误",
327
123
  "status.skipped": "跳过",
328
124
  "action.close": "关闭",
329
- "action.copyReason": "复制原因",
330
125
  "action.copyPrompt": "复制修复 Prompt",
331
126
  "action.copied": "已复制",
332
127
  "trace.loading": "加载中...",
333
128
  "trace.loadFailed": "加载失败(静态报告没有服务端 - 请用 niceeval view):",
334
- "trace.transcript": "会话",
335
129
  "trace.timing": "耗时追踪",
336
130
  "trace.noSpans": "没有 span",
337
131
  "trace.total": "总计",
@@ -371,23 +165,6 @@ const dictionaries: Record<Locale, Dictionary> = {
371
165
  "assert.optional": "可缺席",
372
166
  "assert.soft": "soft",
373
167
  "assert.evidence": "实际被检查的内容",
374
- "verdict.passed": "通过",
375
- "verdict.failed": "失败",
376
- "verdict.errored": "错误",
377
- "verdict.skipped": "跳过",
378
- "banner.skippedTitle": "{{count}} 个 run 读取失败,此处不展示",
379
- "banner.skipped.incompatible": "由 niceeval {{producer}} 写入(schemaVersion {{schemaVersion}})—— 当前版本读不了,展开查看命令",
380
- "banner.skipped.incompatibleForeign": "由 {{name}} {{version}} 写入(schemaVersion {{schemaVersion}})—— 当前查看器读不了;请用写出它的工具查看",
381
- "banner.skipped.malformed": "报告读不了({{detail}})—— 可能已损坏;重跑该 eval 或删除对应 run 目录",
382
- "banner.skipped.incomplete": "快照目录已创建但从未写出 snapshot.json(极窄的崩溃窗口)—— 已完成的 attempt artifact 仍在盘上供手工排查;不需要就删除对应目录",
383
- "banner.expandRest": "展开其余 {{count}} 个",
384
- "banner.collapse": "收起",
385
- "banner.copyCommand": "复制查看命令",
386
- "banner.warningsTitle": "当前榜单挑选的提醒:",
387
- "hero.composedFrom": "合成自 {{count}} 个 run",
388
- "chart.costVsScore": "成本 × 通过率",
389
- "chart.axisCost": "平均每个 eval 成本",
390
- "chart.axisScore": "通过率",
391
168
  },
392
169
  };
393
170
 
@@ -408,9 +185,10 @@ export function persistLocale(locale: Locale): void {
408
185
  }
409
186
  }
410
187
 
188
+ // 浏览器 <title> 是宿主文档单例,唯一归属是 App 的 shellTitle effect(外壳标题回退链);
189
+ // 这里只切文档语言,不碰标题。
411
190
  export function setDocumentLocale(locale: Locale): void {
412
191
  document.documentElement.lang = locale;
413
- document.title = dictionaries[locale]["app.title"];
414
192
  }
415
193
 
416
194
  export function makeTranslator(locale: Locale): (key: MessageKey, vars?: Vars) => string {
@@ -1,26 +1,8 @@
1
- // viewData 快照明细 → 证据室页面模型的纯拼接,零聚合口径:Runs / Traces 的平铺列表
2
- // 来自全部快照(server 侧已跨快照去重);统计口径整体住在报告槽的静态 HTML 里,
3
- // 前端不再拼榜单行。修复 prompt 的失败清单(CopyControls 的 fixPromptEntries)
4
- // 也从这份快照明细现算。
1
+ // viewData 快照明细 → attempt 深链解析的纯拼接,零聚合口径:统计与列表整体住在报告页的
2
+ // 静态 HTML 里(报告组件的官方计算函数),前端不拼任何榜单行。Attempts / Traces 是内建报告
3
+ // 的普通页(AttemptList / TraceWaterfall 组件),不再由前端平铺快照明细。
5
4
 
6
- import type { RowRun } from "../shared.ts";
7
5
  import type { ViewResult, ViewSnapshot } from "../types.ts";
8
- import { displayExperimentName } from "../../../shared/aggregate.ts";
9
-
10
- /** 快照的展示标签:experiment id 的末段。 */
11
- export function snapshotLabel(snapshot: ViewSnapshot): string {
12
- return displayExperimentName(snapshot.experimentId) ?? snapshot.experimentId;
13
- }
14
-
15
- /** Runs / Traces 的平铺列表:全部快照(含历史)的 attempt,带所属实验的展示标注。 */
16
- export function flattenAttempts(snapshots: ViewSnapshot[]): RowRun[] {
17
- return snapshots.flatMap((snapshot) => {
18
- const label = snapshotLabel(snapshot);
19
- return snapshot.results.map(
20
- (r): RowRun => ({ ...r, rowLabel: label, rowAgent: snapshot.agent, rowModel: r.model ?? snapshot.model }),
21
- );
22
- });
23
- }
24
6
 
25
7
  /** 旧版 ?modal= 深链的只读回退:在全部快照里按 (eval id, experimentId, attempt) 定位。 */
26
8
  export function resultFromUrl(snapshots: ViewSnapshot[]): ViewResult | null {
@@ -1,10 +1,8 @@
1
1
  import type { Vars } from "../../i18n/core.ts";
2
2
  import type { MessageKey } from "./i18n.ts";
3
- import type { CodeSource, TranscriptEvent, ViewJson, ViewResult } from "./types.ts";
3
+ import type { CodeSource, TranscriptEvent, ViewJson } from "./types.ts";
4
4
 
5
5
  export type T = (key: MessageKey, vars?: Vars) => string;
6
6
  export type ArtifactLoadState =
7
7
  | { sources: CodeSource[] | null; events: TranscriptEvent[] | null; status: "loading" | "ready" | "none" };
8
- export type RowRun = ViewResult & { rowLabel: string; rowAgent: string; rowModel?: string };
9
- export type LazyArtifactType = "trace" | "transcript";
10
8
  export type ToolBlockCall = { tool?: string; name: string; input: ViewJson };
@@ -23,8 +23,8 @@ export type {
23
23
  ViewSnapshot,
24
24
  } from "../shared/types.ts";
25
25
 
26
- /** 导航 tab:报告页(`page:<id>`,路由 `#/page/<id>`)在前,内置证据页 Attempts / Traces 恒在其后。 */
27
- export type Tab = `page:${string}` | "attempts" | "traces";
26
+ /** 导航 tab:只有报告定义声明的页(`page:<id>`,路由 `#/page/<id>`),按声明序;宿主不追加任何项。 */
27
+ export type Tab = `page:${string}`;
28
28
 
29
29
  /** 前端拿到的单条 attempt 结果就是瘦身后的 EvalResult(locator / artifactBase 由 loader 注入)。 */
30
30
  export type ViewResult = ViewEvalResult;