niceeval 0.8.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/INDEX.md +77 -45
- package/dist/agents/types.d.ts +28 -6
- package/dist/i18n/en.d.ts +2 -0
- package/dist/i18n/zh-CN.d.ts +2 -0
- package/dist/report/built-in/index.d.ts +3 -2
- package/dist/report/built-in/index.js +7 -8
- package/dist/report/built-in/standard.d.ts +1 -0
- package/dist/report/built-in/standard.js +30 -0
- package/dist/report/components.d.ts +69 -2
- package/dist/report/components.js +152 -3
- package/dist/report/compute.d.ts +28 -1
- package/dist/report/compute.js +123 -0
- package/dist/report/index.d.ts +4 -4
- package/dist/report/index.js +3 -2
- package/dist/report/locale.d.ts +39 -1
- package/dist/report/locale.js +69 -0
- package/dist/report/react/AttemptList.d.ts +3 -1
- package/dist/report/react/AttemptList.js +3 -3
- package/dist/report/react/CopyFixPrompt.d.ts +12 -0
- package/dist/report/react/CopyFixPrompt.js +12 -0
- package/dist/report/react/HeroCard.d.ts +13 -0
- package/dist/report/react/HeroCard.js +35 -0
- package/dist/report/react/PoweredBy.d.ts +5 -0
- package/dist/report/react/PoweredBy.js +7 -0
- package/dist/report/react/ScopeWarnings.d.ts +12 -0
- package/dist/report/react/ScopeWarnings.js +18 -0
- package/dist/report/react/TraceWaterfall.d.ts +14 -0
- package/dist/report/react/TraceWaterfall.js +22 -0
- package/dist/report/react/index.d.ts +6 -1
- package/dist/report/react/index.js +6 -0
- package/dist/report/report.d.ts +22 -6
- package/dist/report/report.js +66 -53
- package/dist/report/scope-warnings.d.ts +28 -0
- package/dist/report/scope-warnings.js +101 -0
- package/dist/report/text/faces.d.ts +19 -1
- package/dist/report/text/faces.js +61 -0
- package/dist/report/tree.js +6 -1
- package/dist/report/types.d.ts +45 -0
- package/dist/report/web.d.ts +5 -4
- package/dist/report/web.js +7 -22
- package/dist/results/select.d.ts +15 -2
- package/dist/results/select.js +75 -10
- package/dist/results/types.d.ts +26 -0
- package/dist/runner/fingerprint.d.ts +3 -3
- package/dist/runner/sandbox-selection.d.ts +12 -0
- package/dist/runner/types.d.ts +18 -6
- package/dist/sandbox/types.d.ts +12 -0
- package/docs-site/zh/explanation/evals.mdx +2 -1
- package/docs-site/zh/explanation/experiment.mdx +2 -0
- package/docs-site/zh/how-to/custom-reports.mdx +22 -6
- package/docs-site/zh/how-to/publish-report.mdx +5 -4
- package/docs-site/zh/how-to/viewing-results.mdx +3 -3
- package/docs-site/zh/how-to/write-experiment.mdx +40 -1
- package/docs-site/zh/reference/builtin-agents.mdx +40 -3
- package/docs-site/zh/reference/cli.mdx +1 -1
- package/docs-site/zh/reference/define-eval.mdx +8 -0
- package/docs-site/zh/reference/official-adapters.mdx +10 -5
- package/package.json +2 -1
- package/src/agents/bub.ts +13 -1
- package/src/agents/claude-code.test.ts +43 -1
- package/src/agents/claude-code.ts +32 -14
- package/src/agents/codex.test.ts +168 -1
- package/src/agents/codex.ts +51 -15
- package/src/agents/mcp.ts +31 -0
- package/src/agents/post-setup.ts +33 -0
- package/src/agents/types.ts +28 -7
- package/src/cli.ts +8 -6
- package/src/define.ts +3 -0
- package/src/i18n/en.ts +5 -2
- package/src/i18n/zh-CN.ts +5 -1
- package/src/index.ts +1 -0
- package/src/report/built-in/index.tsx +8 -7
- package/src/report/built-in/standard.tsx +59 -0
- package/src/report/components.tsx +218 -2
- package/src/report/compute.ts +138 -1
- package/src/report/dual-render.test.tsx +139 -12
- package/src/report/index.ts +20 -0
- package/src/report/locale.ts +83 -1
- package/src/report/react/AttemptList.tsx +13 -1
- package/src/report/react/CopyFixPrompt.tsx +37 -0
- package/src/report/react/HeroCard.tsx +59 -0
- package/src/report/react/PoweredBy.tsx +20 -0
- package/src/report/react/ScopeWarnings.tsx +74 -0
- package/src/report/react/TraceWaterfall.tsx +78 -0
- package/src/report/react/enhance.js +14 -0
- package/src/report/react/index.tsx +11 -0
- package/src/report/react/styles.css +187 -7
- package/src/report/report.ts +97 -62
- package/src/report/scope-warnings.ts +155 -0
- package/src/report/site-components.test.tsx +526 -0
- package/src/report/text/faces.ts +66 -0
- package/src/report/tree.ts +8 -1
- package/src/report/types.ts +51 -0
- package/src/report/web.ts +7 -40
- package/src/results/host-equivalence.test.ts +5 -1
- package/src/results/open.ts +5 -4
- package/src/results/results.test.ts +78 -1
- package/src/results/select.ts +78 -10
- package/src/results/types.ts +27 -0
- package/src/runner/attempt.ts +10 -9
- package/src/runner/discover.test.ts +9 -1
- package/src/runner/discover.ts +3 -3
- package/src/runner/fingerprint.ts +9 -4
- package/src/runner/ledger.test.ts +30 -1
- package/src/runner/ledger.ts +26 -4
- package/src/runner/run.ts +5 -1
- package/src/runner/sandbox-selection.test.ts +131 -0
- package/src/runner/sandbox-selection.ts +110 -0
- package/src/runner/types.ts +19 -2
- package/src/sandbox/types.ts +6 -0
- package/src/show/index.ts +17 -10
- package/src/show/render.ts +11 -11
- package/src/show/report-host.test.ts +32 -15
- package/src/show/report-host.ts +5 -4
- package/src/show/show.test.ts +140 -3
- package/src/view/app/App.test.tsx +78 -17
- package/src/view/app/App.tsx +17 -78
- package/src/view/app/components/CopyControls.tsx +4 -42
- package/src/view/app/i18n.ts +5 -227
- package/src/view/app/lib/rows.ts +3 -21
- package/src/view/app/shared.ts +1 -3
- package/src/view/app/types.ts +2 -2
- package/src/view/client-dist/app.css +1 -1
- package/src/view/client-dist/app.js +20 -20
- package/src/view/data.ts +2 -2
- package/src/view/shared/types.ts +11 -6
- package/src/view/styles.css +6 -266
- package/src/view/view-report.test.ts +59 -22
- package/src/view/app/components/LazyArtifact.tsx +0 -51
- package/src/view/app/components/SkippedRunsBanner.tsx +0 -140
- package/src/view/app/pages/AttemptsPage.tsx +0 -80
- package/src/view/app/pages/TracesPage.tsx +0 -35
package/INDEX.md
CHANGED
|
@@ -2,51 +2,83 @@
|
|
|
2
2
|
|
|
3
3
|
这是 coding agent 读取 NiceEval 文档的稳定入口,随 npm 包发布,不属于公开文档站。不要根据训练数据、官网或 GitHub `main` 分支猜测 API。
|
|
4
4
|
|
|
5
|
-
以下路径都相对于包根 `node_modules/niceeval/`。文档位于 `docs-site/zh/`,与当前安装的 NiceEval
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
5
|
+
以下路径都相对于包根 `node_modules/niceeval/`。文档位于 `docs-site/zh/`,与当前安装的 NiceEval 版本一起发布。下面的树列出全部随包页面,每行是「路径 — 标题:一句话自述」。分区含义:
|
|
6
|
+
|
|
7
|
+
- `tutorials/` 第一次跑通;`explanation/` 概念、边界与原理;`how-to/` 按任务的操作步骤;`reference/` API、CLI 与数据形状的精确事实;`troubleshooting/` 按症状排查失败;`examples/` 真实项目的接入案例。
|
|
8
|
+
|
|
9
|
+
按当前任务从树里挑 1–3 页读取(通常是一页 how-to 或 explanation 搭一页 reference);页面再引用其它概念或参考时,继续读取包内文件。
|
|
10
|
+
|
|
11
|
+
<!-- GENERATED:BEGIN bundled-docs-tree -->
|
|
12
|
+
|
|
13
|
+
<!-- 本文件是构建产物(pnpm run build:index),勿手改:树区文案改对应页面的 frontmatter title/description,导语改 INDEX.template.md(生成逻辑见 scripts/generate-reference.ts) -->
|
|
14
|
+
|
|
15
|
+
## `docs-site/zh/tutorials/`
|
|
16
|
+
|
|
17
|
+
- `docs-site/zh/tutorials/quickstart.mdx` — 为你的 Agent 项目设置评估:安装 NiceEval,写三个文件,10 分钟内对你自己的应用跑通第一条 eval。
|
|
18
|
+
|
|
19
|
+
## `docs-site/zh/explanation/`
|
|
20
|
+
|
|
21
|
+
- `docs-site/zh/explanation/adapter.mdx` — Adapter:把 Agent 接入 NiceEval:Adapter 是你写的适配器。本文讲清楚 send 函数传入什么返回什么、被测系统配置怎么传、三个接入等级,以及 t 上的能力从哪来。
|
|
22
|
+
- `docs-site/zh/explanation/assert.mdx` — NiceEval 断言:值、作用域事实、测试与成本:NiceEval 的断言词汇——值断言、作用域断言、test-as-scoring 和效率断言——以及 gate / soft 严重度和判定 verdict 的规则。
|
|
23
|
+
- `docs-site/zh/explanation/drive.mdx` — NiceEval 里怎么驱动 agent:send、session 与 HITL:t.send() 和它返回的 Turn、t.sendFile()、多轮对话、t.newSession(),以及 respond() 处理的人工介入(HITL)。
|
|
24
|
+
- `docs-site/zh/explanation/evals.mdx` — NiceEval 中的 eval:生命周期、verdict 与文件:eval 是一个测试用例:描述和 test 函数,agent-neutral。了解 eval 如何被发现、调度、评分和报告。
|
|
25
|
+
- `docs-site/zh/explanation/experiment.mdx` — 实验(Experiment):评谁、怎么跑:Experiment 是可签入的运行配置:同一批 eval 对着哪个 agent、哪个模型、开哪些 flags、跑几次。eval 与 experiment 分开的原因——晚绑定,让同一份 eval 换着对象跑。
|
|
26
|
+
- `docs-site/zh/explanation/hitl.mdx` — 人工介入(HITL):停轮、回答、继续:什么是 Human-in-the-loop,Claude Code / Codex / AI SDK 应用里它长什么样;NiceEval 如何把它变成可评的路径——waiting 停轮、input.requested 说明在等什么、t.respond 替人回答后同一轮继续。
|
|
27
|
+
- `docs-site/zh/explanation/judge.mdx` — NiceEval 里的 LLM-as-judge: 给开放式输出打分:t.judge / session.judge / turn.judge 如何用独立裁判模型评估事实性、闭合式质量和摘要忠实度,以及模型解析优先级和严重度。
|
|
28
|
+
- `docs-site/zh/explanation/overview.mdx` — NiceEval 架构:evals、agents 与 sandboxes:理解 NiceEval、Adapter 和 Sandbox Provider 如何配合,用统一 API 评估任意 AI Agent。
|
|
29
|
+
- `docs-site/zh/explanation/runner.mdx` — NiceEval runner 如何调度和执行 eval:NiceEval runner 发现 eval,用有界并发调度,缓存结果,重试脆弱基础设施,并执行预算保护。
|
|
30
|
+
- `docs-site/zh/explanation/tier.mdx` — 接入等级(Tier):三级投入,三组能力:按「Adapter 接到哪里、额外拿到什么观测数据」接入分三级:Tier 1 只接 send,Tier 2 加 OTel,Tier 3 侵入改造暴露 experiment flags。每档买到什么、什么时候升级。
|
|
31
|
+
|
|
32
|
+
## `docs-site/zh/how-to/`
|
|
33
|
+
|
|
34
|
+
- `docs-site/zh/how-to/agent-feedback-loop.mdx` — 让 AI 写 Eval 并自主优化:让 coding agent 读取随包文档,用 bash 运行实验、下钻结果、定位失败并持续迭代,最后用全量重跑确认收敛。
|
|
35
|
+
- `docs-site/zh/how-to/authoring.mdx` — 编写 eval: 单轮、多轮和数据集模式:学习如何用 defineEval 编写 NiceEval eval,包括单轮断言、多轮对话、数据驱动测试和 sandbox workspace。
|
|
36
|
+
- `docs-site/zh/how-to/ci-integration.mdx` — 在 GitHub Actions 和 CI 中运行 NiceEval:把 NiceEval 接入 GitHub Actions 或任意 CI。eval 失败时非零退出,输出 JUnit XML,并通过缓存加速重复运行。
|
|
37
|
+
- `docs-site/zh/how-to/connect-otel.mdx` — OTel 接入:把应用已经在发的 OTel span 也发给 NiceEval 一份,niceeval view 里就有每轮的调用瀑布图。断言不从这里来——接好 send 那一刻断言就齐了。
|
|
38
|
+
- `docs-site/zh/how-to/connect-your-agent.mdx` — 接入你的 Agent:接入的全景:写一个 adapter、配一个 experiment、跑通第一条 eval;配置和参数怎么在 experiment 里声明、在 Adapter 里消费。事件流、多轮、HITL、tracing 是增量,各有专章。
|
|
39
|
+
- `docs-site/zh/how-to/custom-reports.mdx` — 用报告积木搭自己的口径:一份报告就是一个报告文件:官方宿主打开结果、注入数据,双面组件让同一份自定义报告同时用于 niceeval show 与 niceeval view。
|
|
40
|
+
- `docs-site/zh/how-to/dataset-fanout.mdx` — 数据驱动测试(dataset fan-out):用多份数据运行同一套 eval:从 .eval.ts 文件导出数组或 keyed record,将一套 eval 逻辑展开为多个 case。用 loadYaml 或 loadJson 读取外部数据集,并获得稳定 ID。
|
|
41
|
+
- `docs-site/zh/how-to/experiments.mdx` — 实验矩阵:用运行矩阵比较 agents 和 models:使用 NiceEval experiments 让同一批 eval 横跨多个 agents、models 和 flags,比较 pass rate、成本和延迟。
|
|
42
|
+
- `docs-site/zh/how-to/fixtures.mdx` — 沙箱 Fixture:用任务评估 coding agents:用 .eval.ts 给 coding agent 准备隔离 workspace、发送真实任务,并用 sandbox 文件、命令、diff 和 judge 验证结果。
|
|
43
|
+
- `docs-site/zh/how-to/publish-report.mdx` — 通过 CI 发布报告:把经过 copySnapshots 大小预检的结果目录提交进仓库,CI 用一行 view --results 导出报告站;超大文件在 commit 前就会得到可执行错误。
|
|
44
|
+
- `docs-site/zh/how-to/reporters.mdx` — 把结果上报到 Braintrust 与其它目的地:用内置 reporters 把 eval 结果送到 Braintrust 实验、JUnit XML 或自定义目的地。
|
|
45
|
+
- `docs-site/zh/how-to/sandbox-agent.mdx` — 沙箱 Agent:评估 Claude Code、Codex 和 bub:使用 NiceEval 内置 agents 或自定义 adapter,在 Docker 或云端 sandbox 中运行 coding-agent CLI。
|
|
46
|
+
- `docs-site/zh/how-to/sandbox-providers.mdx` — Sandbox provider:Docker、Vercel 与第三方:NiceEval 在 Docker 或 Vercel sandbox 中运行 coding agents。了解如何选择 provider、配置权限,并通过 warm pools 改善性能。
|
|
47
|
+
- `docs-site/zh/how-to/scoring-guide.mdx` — 评分指南: 断言、judge 和成本限制:用 NiceEval 的五种评分机制评估任意 eval:值断言、作用域断言、LLM-as-judge、test-as-scoring 和效率检查。
|
|
48
|
+
- `docs-site/zh/how-to/viewing-results.mdx` — 查看 NiceEval 结果并调试 agent 行为:每次运行写入 .niceeval/ 的结构化 artifact 有两扇门:niceeval show 在终端用 @<locator> 精确定位一次 Attempt,逐级下钻 Eval 源码、执行记录与 diff;niceeval view 在网页看同一份证据。
|
|
49
|
+
- `docs-site/zh/how-to/write-experiment.mdx` — 写实验:用 defineExperiment 固定运行配置:学习如何在 experiments/ 里用 defineExperiment 选择 agent、传 model 和 flags、设置 runs、预算、并发与 sandbox。
|
|
50
|
+
- `docs-site/zh/how-to/write-send.mdx` — 如何写好 Send:手写 Adapter 的 send 函数,一条主线七步走:发消息拿回复、接上之前的消息、记录消费、把工具解析成事件、人工介入(HITL)、接上 OTel trace、透传 experiment 的 flags。每一步只在上一步的代码上多几行,每一步解锁一组断言。
|
|
51
|
+
|
|
52
|
+
## `docs-site/zh/reference/`
|
|
53
|
+
|
|
54
|
+
- `docs-site/zh/reference/builtin-agents.mdx` — 内置 Agent 能力参考:NiceEval 内置的 claude-code、codex、bub 适配器分别做到了哪些能力,对应哪些断言,以及已知限制。
|
|
55
|
+
- `docs-site/zh/reference/capabilities.mdx` — 能力位参考:NiceEval 怎么知道你的 adapter 做到了什么:没有声明式能力位,全部由构造和实际行为证明。
|
|
56
|
+
- `docs-site/zh/reference/cli.mdx` — NiceEval CLI:命令、flags 和退出码参考:NiceEval CLI 参考:exp、show、view、init、list 和 clean 命令,以及结果下钻、experiment、eval 过滤、并发、预算和 CI 输出。
|
|
57
|
+
- `docs-site/zh/reference/define-agent.mdx` — defineAgent 和 defineSandboxAgent:adapter 参考:defineAgent 和 defineSandboxAgent 参考:AgentContext、AgentSession、Sandbox 接口和共享 sandbox helpers。
|
|
58
|
+
- `docs-site/zh/reference/define-config.mdx` — defineConfig:项目默认配置:defineConfig 参考:judge、reporters、并发、超时和 sandbox 默认值。
|
|
59
|
+
- `docs-site/zh/reference/define-eval.mdx` — defineEval:声明、配置并运行 NiceEval eval:defineEval 参考:选项、test context t、Turn 返回值、sandbox helper,以及数组和 keyed record 数据集导出。
|
|
60
|
+
- `docs-site/zh/reference/events.mdx` — 标准事件流参考:StreamEvent 的十种事件:每种的字段、什么时候吐、哪些断言消费它。adapter 的核心工作就是产出这条流。
|
|
61
|
+
- `docs-site/zh/reference/expect.mdx` — niceeval/expect matchers 与自定义断言参考:niceeval/expect 参考:includes、equals、matches、similarity、satisfies。可链式调用 .gate() 或 .atLeast(0.7),也可以用 makeAssertion 构建自定义 matcher。
|
|
62
|
+
- `docs-site/zh/reference/official-adapters.mdx` — 官方适配器一览:NiceEval 内置的 Sandbox 和非 Sandbox 适配器分别是什么、怎么鉴权,Sandbox 型里怎么装 MCP server、Skill、插件,怎么使用 Agent 官方配置文件。
|
|
63
|
+
- `docs-site/zh/reference/report-components.mdx` — 报告组件一览:报告文件里能摆的全部官方双面组件:每个组件回答什么问题、怎么调用、网页面长什么样、终端字符输出长什么样。
|
|
64
|
+
- `docs-site/zh/reference/results-data.mdx` — 用 niceeval/results 直接读写结果数据:报告积木脚下的数据层:openResults 把 .niceeval/ 的落盘 artifact parse 成「实验 → 结果快照 → eval → attempt」的类型化层次,createResultsWriter 把别家结果写成 NiceEval 格式,copySnapshots 负责发布瘦身。
|
|
65
|
+
|
|
66
|
+
## `docs-site/zh/troubleshooting/`
|
|
67
|
+
|
|
68
|
+
- `docs-site/zh/troubleshooting/debug-sandbox.mdx` — 保留沙箱现场排查问题:用 --keep-sandbox 把失败 Attempt 的沙箱保留成可随时唤醒的现场,用 niceeval sandbox enter 进去手动排查,用 sandbox list / stop 查看和清理。
|
|
69
|
+
- `docs-site/zh/troubleshooting/debugging.mdx` — 排查失败与复盘历史运行:一份按场景组织的排查手册:断言失败怎么定位、环境错误怎么进沙箱、agent 改了什么怎么看、旧的运行怎么翻出来复盘——每一步都有命令顺序和输出示例。
|
|
70
|
+
|
|
71
|
+
## `docs-site/zh/examples/`
|
|
72
|
+
|
|
73
|
+
- `docs-site/zh/examples/ai-agent-application.mdx` — 自写 Adapter 评估 AI Agent 应用:一个可运行的 AI SDK v6 Web Agent 评测项目,覆盖自写 Adapter、工具调用、图片理解、多轮会话、模型对比和双路可观测。
|
|
74
|
+
- `docs-site/zh/examples/coding-agent-extensions.mdx` — 评估 Coding Agent 扩展:用真实 Workspace、基线实验和自定义报告,评估 Skill、提示词与 Plugin Benchmark 是否改善 Coding Agent 的任务结果。
|
|
75
|
+
- `docs-site/zh/examples/integrations/ai-sdk-v7.mdx` — AI SDK v7 如何非侵入式接入 NiceEval:一个 AI SDK v7 聊天应用,对着它的 HTTP 接口无侵入接入 NiceEval 前后的完整代码 diff:应用侧一行没改。
|
|
76
|
+
- `docs-site/zh/examples/integrations/claude-sdk.mdx` — Claude Agent SDK 如何非侵入式接入 NiceEval:一个 Claude Agent SDK 助手后端,接入 NiceEval 前后的完整代码 diff:应用侧一行没改,全部新增在 eval 侧。
|
|
77
|
+
- `docs-site/zh/examples/integrations/codex-sdk.mdx` — Codex SDK 如何非侵入式接入 NiceEval:一个 Codex SDK(目录里的编码 agent)后端,接入 NiceEval 前后的完整代码 diff:应用侧一行没改。
|
|
78
|
+
- `docs-site/zh/examples/integrations/langgraph.mdx` — LangGraph 如何非侵入式接入 NiceEval:一个纯 Python LangGraph + LangSmith OTel 导出的应用,接入 NiceEval 前后的完整代码 diff。
|
|
79
|
+
- `docs-site/zh/examples/integrations/pi-sdk.mdx` — pi-agent-core 如何非侵入式接入 NiceEval:一个 pi-agent-core(@earendil-works)助手后端,接入 NiceEval 前后的完整代码 diff:应用侧只加了一个 devDependency。
|
|
80
|
+
|
|
81
|
+
<!-- GENERATED:END bundled-docs-tree -->
|
|
50
82
|
|
|
51
83
|
## 版本规则
|
|
52
84
|
|
package/dist/agents/types.d.ts
CHANGED
|
@@ -2,20 +2,39 @@ import type { Cleanup, DiagnosticInput, ProgressUpdate } from "../shared/types.t
|
|
|
2
2
|
import type { StreamEvent, TraceSpan, Usage } from "../o11y/types.ts";
|
|
3
3
|
import type { Sandbox } from "../sandbox/types.ts";
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* 见 docs/feature/adapters/architecture/coding-agent-extensions.md「类型边界」。
|
|
5
|
+
* 本地 stdio 形态的 MCP server:沙箱内起子进程,按 stdio 说 MCP 协议。
|
|
6
|
+
* 与 {@link McpHttpServer} 按形状判别(有 `command` 的是 stdio,有 `url` 的是 HTTP)。
|
|
8
7
|
*/
|
|
9
|
-
export interface
|
|
8
|
+
export interface McpStdioServer {
|
|
10
9
|
/** 服务器唯一名(config key)。 */
|
|
11
10
|
name: string;
|
|
12
11
|
/** 启动命令(如 "npx"、"node"、"uvx")。 */
|
|
13
12
|
command: string;
|
|
14
13
|
/** 传给命令的参数。 */
|
|
15
14
|
args?: string[];
|
|
16
|
-
/**
|
|
15
|
+
/** 注入服务器进程的环境变量(可能含 secret,不进 manifest)。 */
|
|
17
16
|
env?: Record<string, string>;
|
|
18
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* 远程 Streamable HTTP 形态的 MCP server:沙箱直接连一个 HTTP 端点。
|
|
20
|
+
* `url` 必须沙箱内可达——宿主机上的服务先经隧道(cloudflared / tailscale 等)暴露。
|
|
21
|
+
*/
|
|
22
|
+
export interface McpHttpServer {
|
|
23
|
+
/** 服务器唯一名(config key)。 */
|
|
24
|
+
name: string;
|
|
25
|
+
/** Streamable HTTP 端点(如 https://mem.example.com/mcp/)。 */
|
|
26
|
+
url: string;
|
|
27
|
+
/** 逐字写进每个请求的 HTTP 头(常用于 Authorization;可能含 secret,不进 manifest)。 */
|
|
28
|
+
headers?: Record<string, string>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* MCP server 描述符 —— 支持 MCP 的 adapter(Claude Code / Codex)共用的工具服务单元,
|
|
32
|
+
* 不是 native plugin 的一种。stdio 与 Streamable HTTP 两种形态按形状判别,不设 kind 标签
|
|
33
|
+
* (两种形态各有唯一必填判别字段);同时给出 `command` 与 `url` 属配置错误,setup 报错点名。
|
|
34
|
+
* 在 agent factory config 里声明,setup 阶段写进各自的配置文件。
|
|
35
|
+
* 见 docs/feature/adapters/architecture/coding-agent-extensions.md「类型边界」。
|
|
36
|
+
*/
|
|
37
|
+
export type McpServer = McpStdioServer | McpHttpServer;
|
|
19
38
|
/**
|
|
20
39
|
* Skill 的来源描述 —— Claude Code / Codex / Bub 共用的**数据类型**:只统一「从哪里取得
|
|
21
40
|
* 哪份 Skill」,安装位置、发现机制、要不要额外写 project instruction 由各 Adapter 决定。
|
|
@@ -69,11 +88,14 @@ export interface AgentSetupManifest {
|
|
|
69
88
|
/** 安装后 CLI 报告的版本;取不到时省略。 */
|
|
70
89
|
resolvedVersion?: string;
|
|
71
90
|
}>;
|
|
72
|
-
/** 挂上的 MCP server(不含 env
|
|
91
|
+
/** 挂上的 MCP server(只记非 secret 字段:stdio 不含 env,HTTP 不含 headers)。 */
|
|
73
92
|
mcpServers?: Array<{
|
|
74
93
|
name: string;
|
|
75
94
|
command: string;
|
|
76
95
|
args?: string[];
|
|
96
|
+
} | {
|
|
97
|
+
name: string;
|
|
98
|
+
url: string;
|
|
77
99
|
}>;
|
|
78
100
|
/**
|
|
79
101
|
* 官方原生配置文件(Claude Code `settings.json` / Codex `config.toml`):只记 Agent 名、
|
package/dist/i18n/en.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export declare const en: {
|
|
|
22
22
|
"skill.repoAmbiguous": string;
|
|
23
23
|
"skill.repoUnknownSkill": string;
|
|
24
24
|
"skill.copyFailed": string;
|
|
25
|
+
"mcp.ambiguousTransport": string;
|
|
25
26
|
"plugin.marketplaceFailed": string;
|
|
26
27
|
"plugin.marketplaceVerifyFailed": string;
|
|
27
28
|
"plugin.marketplaceNameMismatch": string;
|
|
@@ -91,6 +92,7 @@ export declare const en: {
|
|
|
91
92
|
"context.turnFailedDefault": string;
|
|
92
93
|
"define.agentNameRequired": string;
|
|
93
94
|
"define.evalIdRejected": string;
|
|
95
|
+
"define.evalEnvironmentEmpty": string;
|
|
94
96
|
"define.evalTestRequired": string;
|
|
95
97
|
"define.experimentAgentRequired": string;
|
|
96
98
|
"define.experimentFlagNotJson": string;
|
package/dist/i18n/zh-CN.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export declare const zhCN: {
|
|
|
22
22
|
readonly "skill.repoAmbiguous": "repo skill {{source}} 里有多个 skill,必须用 `skills: [...]` 明确选择要启用哪些。可选:{{available}}。";
|
|
23
23
|
readonly "skill.repoUnknownSkill": "repo skill {{source}}(ref: {{ref}})里没有名为 \"{{skill}}\" 的 skill。可选:{{available}}。";
|
|
24
24
|
readonly "skill.copyFailed": "skill \"{{name}}\" 装进 {{dest}} 失败:\n{{tail}}";
|
|
25
|
+
readonly "mcp.ambiguousTransport": "MCP server \"{{name}}\" 同时给出了 command 和 url——二选一:本地 stdio 进程写 command,远程 Streamable HTTP 端点写 url。";
|
|
25
26
|
readonly "plugin.marketplaceFailed": "{{agent}} marketplace \"{{name}}\" 连接失败(source: {{source}}, ref: {{ref}}):\n{{tail}}";
|
|
26
27
|
readonly "plugin.marketplaceVerifyFailed": "{{agent}} marketplace \"{{name}}\" add 后回读注册列表失败({{command}}):\n{{tail}}";
|
|
27
28
|
readonly "plugin.marketplaceNameMismatch": string;
|
|
@@ -91,6 +92,7 @@ export declare const zhCN: {
|
|
|
91
92
|
readonly "context.turnFailedDefault": "本轮 send 返回 failed(turn status = failed)";
|
|
92
93
|
readonly "define.agentNameRequired": "defineAgent 需要 name。";
|
|
93
94
|
readonly "define.evalIdRejected": "defineEval 不接受 id —— id 由文件路径推导。";
|
|
95
|
+
readonly "define.evalEnvironmentEmpty": "defineEval 的 environment 如有提供,必须是非空的 profile id。";
|
|
94
96
|
readonly "define.evalTestRequired": "defineEval 需要一个 async test(t) 函数。";
|
|
95
97
|
readonly "define.experimentAgentRequired": "defineExperiment 需要 agent。";
|
|
96
98
|
readonly "define.experimentFlagNotJson": "experiment.flags.{{key}} 不是可 JSON 序列化的值(函数 / undefined / 循环引用 / bigint 不允许);flags 会原样进入结果快照,必须是纯 JSON。";
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
1
|
+
import { standard } from "./standard.tsx";
|
|
2
|
+
export { standard };
|
|
3
|
+
export default standard;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
//
|
|
3
|
-
// (docs/feature/reports/library/built-in.md)
|
|
4
|
-
//
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export default defineReport(_jsx(ExperimentComparison, {}));
|
|
1
|
+
// niceeval/report/built-in —— 内建视图的家:每个内建视图是一份普通 defineReport 成品,
|
|
2
|
+
// 有自己的名字、一个源文件,按名字具名导出;默认导出恒等于 standard——裸宿主装载的那份
|
|
3
|
+
// (docs/feature/reports/library/built-in.md)。新增内建视图 = 新文件 + 新具名导出,
|
|
4
|
+
// 不需要注册表,也不改变装载管线。
|
|
5
|
+
import { standard } from "./standard.js";
|
|
6
|
+
export { standard };
|
|
7
|
+
export default standard;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const standard: import("../report.ts").ReportDefinition;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// standard —— 内建视图之一:报告 / Attempts / 追踪三页的通用结果站,没有任何私有钩子
|
|
3
|
+
// (docs/feature/reports/library/built-in.md)。裸 `niceeval show` 与 `niceeval view`
|
|
4
|
+
// 装载的就是它:一份普通 defineReport,与用户的 --report 文件同层、走同一条
|
|
5
|
+
// 装载 → resolve → validate → render 管线。「builtin」不是装载逻辑里的类别,
|
|
6
|
+
// 只是宿主默认拿哪个值的事实;用户报告经 defineReport({ extends: standard, … }) 整站复用。
|
|
7
|
+
//
|
|
8
|
+
// 三页站点:report(Hero + 警告 + 批量修复 prompt + 实验对比)、attempts(带过滤的
|
|
9
|
+
// attempt 全列表)、traces(执行瀑布)。裸宿主导航上能看到的一切内容都在这份定义里;
|
|
10
|
+
// 宿主保留的只有机器(docs/feature/reports/architecture.md「宿主保留的只有机器」)。
|
|
11
|
+
import { AttemptList, Col, CopyFixPrompt, ExperimentComparison, Hero, ScopeWarnings, TraceWaterfall, defineReport, } from "../index.js";
|
|
12
|
+
export const standard = defineReport({
|
|
13
|
+
pages: [
|
|
14
|
+
{
|
|
15
|
+
id: "report",
|
|
16
|
+
title: { en: "Report", "zh-CN": "报告" },
|
|
17
|
+
content: (_jsxs(Col, { children: [_jsx(Hero, {}), _jsx(ScopeWarnings, {}), _jsx(CopyFixPrompt, {}), _jsx(ExperimentComparison, {})] })),
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: "attempts",
|
|
21
|
+
title: "Attempts",
|
|
22
|
+
content: (_jsxs(Col, { children: [_jsx(Hero, {}), _jsx(ScopeWarnings, {}), _jsx(AttemptList, { filter: true })] })),
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: "traces",
|
|
26
|
+
title: { en: "Traces", "zh-CN": "追踪" },
|
|
27
|
+
content: (_jsxs(Col, { children: [_jsx(Hero, {}), _jsx(ScopeWarnings, {}), _jsx(TraceWaterfall, {})] })),
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ReportComponent } from "./tree.ts";
|
|
2
|
-
import type { ReportLocale } from "./locale.ts";
|
|
2
|
+
import type { LocalizedText, ReportLocale } from "./locale.ts";
|
|
3
3
|
import type { AttemptLocator } from "../results/locator.ts";
|
|
4
|
-
import type { AttemptListItem, DeltaData, EvalListItem, ExperimentComparisonData, ExperimentListItem, LineData, MatrixData, ReportInput, ScatterData, ScopeSummaryData, ScoreboardData, TableData } from "./types.ts";
|
|
4
|
+
import type { AttemptListItem, CopyFixPromptData, DeltaData, EvalListItem, ExperimentComparisonData, ExperimentListItem, HeroData, LineData, MatrixData, ReportInput, ScatterData, ScopeSummaryData, ScopeWarning, ScoreboardData, TableData, TraceWaterfallRow } from "./types.ts";
|
|
5
5
|
import { type DeltaTableOptions, type MetricLineOptions, type MetricMatrixOptions, type MetricScatterOptions, type MetricTableOptions, type ScoreboardOptions } from "./compute.ts";
|
|
6
6
|
type Never<T> = {
|
|
7
7
|
[K in keyof T]?: never;
|
|
@@ -55,6 +55,8 @@ export declare const EvalList: ReportComponent<EvalListProps>;
|
|
|
55
55
|
export type AttemptListProps = DataProps<readonly AttemptListItem[], Record<never, never>, EntityListChrome & {
|
|
56
56
|
/** 过滤 / 截断前的总数;省略时等于 data 长度。 */
|
|
57
57
|
total?: number;
|
|
58
|
+
/** web 面加过滤输入框(按 experiment、eval、agent、verdict 或摘要文本收窄行);渐进增强,不改变数据与 text 面。 */
|
|
59
|
+
filter?: boolean;
|
|
58
60
|
}>;
|
|
59
61
|
/** Attempt 列表:实体列表的叶子层,每项一次 attempt 的判定、单行摘要与 locator。 */
|
|
60
62
|
export declare const AttemptList: ReportComponent<AttemptListProps>;
|
|
@@ -74,6 +76,71 @@ export interface FailureListProps {
|
|
|
74
76
|
* 截断到 limit(默认 20),total 报告截断前总数。
|
|
75
77
|
*/
|
|
76
78
|
export declare const FailureList: ReportComponent<FailureListProps>;
|
|
79
|
+
/** `Hero` 的 props:标题缺省取 `ctx.report.title`(回退链后的站点标题)。 */
|
|
80
|
+
export interface HeroProps {
|
|
81
|
+
/** 覆盖标题;省略时取 ctx.report.title(回退链后的站点标题)。 */
|
|
82
|
+
title?: LocalizedText;
|
|
83
|
+
className?: string;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* `HeroCard`:Hero 的渲染件,双面组件,只收 data 形态——标题输入是站点声明与 Scope 的
|
|
87
|
+
* 合成物,没有单独的 spec 等价形。web 面渲染 hero 标题(h1)、按渲染 locale 格式化的运行
|
|
88
|
+
* meta(latestStartedAt 为 null 时内置「暂无运行」文案)与品牌行(等同 PoweredBy,恒含、
|
|
89
|
+
* 无拆除 prop);text 面输出标题行与 meta 行,不含品牌行
|
|
90
|
+
* (docs/feature/reports/library/site-components.md「HeroCard」)。
|
|
91
|
+
*/
|
|
92
|
+
export declare const HeroCard: ReportComponent<HeroCardProps>;
|
|
93
|
+
/** `HeroCard` 的 props:标题 + `heroData()` 的产物,只有 data 形态。 */
|
|
94
|
+
export interface HeroCardProps {
|
|
95
|
+
title: LocalizedText;
|
|
96
|
+
data: HeroData;
|
|
97
|
+
className?: string;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* `Hero`:页首的站点标题区——标题、最后运行时间、快照合成来源,恒含品牌行。官方组合组件,
|
|
101
|
+
* 与手写 `<HeroCard title={title ?? ctx.report.title} data={await heroData(ctx.scope)} />`
|
|
102
|
+
* 严格等价、没有私有能力;读 `ctx.report` 意味着输出跟随站点,要站点无关的标题区直接用
|
|
103
|
+
* `HeroCard` 显式传值(docs/feature/reports/library/site-components.md「Hero」)。
|
|
104
|
+
*/
|
|
105
|
+
export declare const Hero: ReportComponent<HeroProps>;
|
|
106
|
+
/**
|
|
107
|
+
* `PoweredBy`:唯一的品牌件,无 props 双面组件。web 面渲染指向 niceeval 官网的一行品牌色
|
|
108
|
+
* 小字(`utm_source=report&utm_medium=powered-by`,`rel` 仅 `noopener` 以保留 Referer);
|
|
109
|
+
* text 面零输出。没有任何配置——品牌契约是「提供一个组件,不给开关」:不想要品牌就不用
|
|
110
|
+
* 这些组件、自己写替代组件(docs/feature/reports/library/site-components.md「PoweredBy」)。
|
|
111
|
+
*/
|
|
112
|
+
export declare const PoweredBy: ReportComponent<Record<never, never>>;
|
|
113
|
+
/** `ScopeWarnings` 的 props:spec 形态取宿主 Scope 的 warnings,data 形态收 `ScopeWarning[]`。 */
|
|
114
|
+
export type ScopeWarningsProps = DataProps<readonly ScopeWarning[], Record<never, never>, ChromeProps>;
|
|
115
|
+
/**
|
|
116
|
+
* `ScopeWarnings`:选择警告区,警告的唯一呈现组件。把 Scope 携带的 `ScopeWarning[]`
|
|
117
|
+
* 按「下一步动作」聚合渲染(带 experimentId 的按实验聚合、非实验作用域按 kind 聚合;
|
|
118
|
+
* integrity 组在前);web 面组头带去重后的可复制命令、明细收原生 `<details>`(总条数 ≤ 3
|
|
119
|
+
* 默认展开),text 面同构但不折叠。空警告集与裸 `Snapshot[]` 输入两面零输出
|
|
120
|
+
* (docs/feature/reports/library/site-components.md「ScopeWarnings」)。
|
|
121
|
+
*/
|
|
122
|
+
export declare const ScopeWarnings: ReportComponent<ScopeWarningsProps>;
|
|
123
|
+
/** `CopyFixPrompt` 的 props:spec 形态无选项,data 形态收 `copyFixPromptData()` 的产物。 */
|
|
124
|
+
export type CopyFixPromptProps = DataProps<CopyFixPromptData, Record<never, never>, ChromeProps>;
|
|
125
|
+
/**
|
|
126
|
+
* `CopyFixPrompt`:把当前范围的全部失败整理成一段可交给 coding agent 的修复 prompt。
|
|
127
|
+
* prompt 在 resolve 阶段算好、烘进静态 HTML,无 JS 时在折叠块里完整可读,「复制」是增强层
|
|
128
|
+
* 行为;`failures` 为 0 时两面零输出;text 面恒零输出——终端里的等价能力是 `show` 的
|
|
129
|
+
* attempt 下钻命令本身(docs/feature/reports/library/site-components.md「CopyFixPrompt」)。
|
|
130
|
+
*/
|
|
131
|
+
export declare const CopyFixPrompt: ReportComponent<CopyFixPromptProps>;
|
|
132
|
+
/** `TraceWaterfall` 的 props:spec 形态无选项,data 形态收 `traceWaterfallData()` 的产物。 */
|
|
133
|
+
export type TraceWaterfallProps = DataProps<readonly TraceWaterfallRow[], Record<never, never>, ChromeProps & {
|
|
134
|
+
attemptHref?: (locator: AttemptLocator) => string;
|
|
135
|
+
}>;
|
|
136
|
+
/**
|
|
137
|
+
* `TraceWaterfall`:每个 attempt 一行的执行时间瀑布,用 canonical OTel 字段显示被测 agent
|
|
138
|
+
* 的原始 span(agent / model / tool)。web 面静态渲染顶层 span 分解条(失败 span 带失败
|
|
139
|
+
* 标记),行链接 attempt 详情;text 面每 attempt 一行(locator、总耗时、span 计数与失败
|
|
140
|
+
* 标记)+ 可复制的 `--timing` 下钻命令。trace 缺失的行照常出现并如实显示缺失;runner
|
|
141
|
+
* 生命周期节点不进瀑布(docs/feature/reports/library/site-components.md「TraceWaterfall」)。
|
|
142
|
+
*/
|
|
143
|
+
export declare const TraceWaterfall: ReportComponent<TraceWaterfallProps>;
|
|
77
144
|
export type MetricTableProps = DataProps<TableData, MetricTableOptions, ChromeProps & {
|
|
78
145
|
/** web 面在表格前渲染过滤输入框(enhance.js 接管);无 JS 时表格内容依旧完整。 */
|
|
79
146
|
filter?: boolean;
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { defineComponent, isHostWebContextActive, memoFetchOf, } from "./tree.js";
|
|
3
|
-
import { attemptListData, deltaTableData, evalListData, experimentComparisonData, experimentListData, metricLineData, metricMatrixData, metricScatterData, metricTableData, scopeSummaryData, scoreboardData, } from "./compute.js";
|
|
3
|
+
import { attemptListData, copyFixPromptData, deltaTableData, evalListData, experimentComparisonData, experimentListData, heroData, metricLineData, metricMatrixData, metricScatterData, metricTableData, scopeSummaryData, scopeWarningsData, scoreboardData, traceWaterfallData, } from "./compute.js";
|
|
4
4
|
import { collectItems, locatorOf, resolveInput } from "./aggregate.js";
|
|
5
|
-
import { attemptListText, deltaText, evalListText, experimentComparisonText, experimentListText, barsText, lineText, matrixText, scatterText, scoreboardText, scopeSummaryText, tableText, } from "./text/faces.js";
|
|
5
|
+
import { attemptListText, deltaText, evalListText, experimentComparisonText, experimentListText, barsText, heroCardText, lineText, matrixText, scatterText, scopeWarningsText, scoreboardText, scopeSummaryText, tableText, traceWaterfallText, } from "./text/faces.js";
|
|
6
6
|
import { ScopeSummary as ScopeSummaryWeb } from "./react/ScopeSummary.js";
|
|
7
7
|
import { ExperimentComparisonView } from "./react/ExperimentComparison.js";
|
|
8
8
|
import { ExperimentList as ExperimentListWeb } from "./react/ExperimentList.js";
|
|
9
9
|
import { EvalList as EvalListWeb } from "./react/EvalList.js";
|
|
10
10
|
import { AttemptList as AttemptListWeb } from "./react/AttemptList.js";
|
|
11
|
+
import { HeroCard as HeroCardWeb } from "./react/HeroCard.js";
|
|
12
|
+
import { PoweredBy as PoweredByWeb } from "./react/PoweredBy.js";
|
|
13
|
+
import { ScopeWarnings as ScopeWarningsWeb } from "./react/ScopeWarnings.js";
|
|
14
|
+
import { CopyFixPrompt as CopyFixPromptWeb } from "./react/CopyFixPrompt.js";
|
|
15
|
+
import { TraceWaterfall as TraceWaterfallWeb } from "./react/TraceWaterfall.js";
|
|
11
16
|
import { MetricTable as MetricTableWeb } from "./react/MetricTable.js";
|
|
12
17
|
import { MetricMatrix as MetricMatrixWeb } from "./react/MetricMatrix.js";
|
|
13
18
|
import { MetricBars as MetricBarsWeb } from "./react/MetricBars.js";
|
|
@@ -183,6 +188,56 @@ const validateAttemptListData = (data) => {
|
|
|
183
188
|
}
|
|
184
189
|
return null;
|
|
185
190
|
};
|
|
191
|
+
const validateHeroData = (data) => {
|
|
192
|
+
if (!isObject(data))
|
|
193
|
+
return "expected an object";
|
|
194
|
+
if (!("latestStartedAt" in data) || (data.latestStartedAt !== null && typeof data.latestStartedAt !== "string")) {
|
|
195
|
+
return 'missing "latestStartedAt" (string | null)';
|
|
196
|
+
}
|
|
197
|
+
if (typeof data.snapshots !== "number")
|
|
198
|
+
return 'missing "snapshots" (number)';
|
|
199
|
+
return null;
|
|
200
|
+
};
|
|
201
|
+
const validateScopeWarningsData = (data) => {
|
|
202
|
+
if (!Array.isArray(data))
|
|
203
|
+
return "expected an array of ScopeWarning";
|
|
204
|
+
for (const item of data) {
|
|
205
|
+
if (!isObject(item) || typeof item.kind !== "string" || typeof item.message !== "string") {
|
|
206
|
+
return "each warning needs { kind, message, … }";
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return null;
|
|
210
|
+
};
|
|
211
|
+
const validateCopyFixPromptData = (data) => {
|
|
212
|
+
if (!isObject(data))
|
|
213
|
+
return "expected an object";
|
|
214
|
+
if (typeof data.prompt !== "string")
|
|
215
|
+
return 'missing "prompt" (string)';
|
|
216
|
+
if (typeof data.failures !== "number")
|
|
217
|
+
return 'missing "failures" (number)';
|
|
218
|
+
return null;
|
|
219
|
+
};
|
|
220
|
+
const validateTraceWaterfallData = (data) => {
|
|
221
|
+
if (!Array.isArray(data))
|
|
222
|
+
return "expected an array of TraceWaterfallRow";
|
|
223
|
+
for (const row of data) {
|
|
224
|
+
if (!isObject(row) ||
|
|
225
|
+
typeof row.experimentId !== "string" ||
|
|
226
|
+
typeof row.evalId !== "string" ||
|
|
227
|
+
typeof row.locator !== "string" ||
|
|
228
|
+
!("durationMs" in row) ||
|
|
229
|
+
(row.durationMs !== null && typeof row.durationMs !== "number") ||
|
|
230
|
+
!Array.isArray(row.spans)) {
|
|
231
|
+
return "each row needs { experimentId, evalId, locator, durationMs: number | null, spans }";
|
|
232
|
+
}
|
|
233
|
+
for (const span of row.spans) {
|
|
234
|
+
if (!isObject(span) || typeof span.name !== "string" || typeof span.startOffsetMs !== "number") {
|
|
235
|
+
return "each span needs { name, kind, startOffsetMs, durationMs, failed }";
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return null;
|
|
240
|
+
};
|
|
186
241
|
function makeDataComponent(def) {
|
|
187
242
|
const assertData = (data) => {
|
|
188
243
|
const problem = def.validate(data);
|
|
@@ -286,7 +341,7 @@ export const AttemptList = makeDataComponent({
|
|
|
286
341
|
dataFn: (input) => attemptListData(input),
|
|
287
342
|
specKeys: [],
|
|
288
343
|
validate: validateAttemptListData,
|
|
289
|
-
web: (props, ctx) => (_jsx(AttemptListWeb, { data: props.data, total: props.total, locale: props.locale ?? ctx.locale, attemptHref: hrefOf(props, ctx) ?? ctx.attemptHref, className: props.className })),
|
|
344
|
+
web: (props, ctx) => (_jsx(AttemptListWeb, { data: props.data, total: props.total, filter: props.filter, locale: props.locale ?? ctx.locale, attemptHref: hrefOf(props, ctx) ?? ctx.attemptHref, className: props.className })),
|
|
290
345
|
text: (props, ctx) => attemptListText(props.data, props.total, ctx),
|
|
291
346
|
});
|
|
292
347
|
/**
|
|
@@ -316,6 +371,100 @@ export const FailureList = defineComponent(async (props, ctx) => {
|
|
|
316
371
|
return (_jsx(AttemptList, { data: failures.slice(0, limit), total: failures.length, attemptHref: props.attemptHref, locale: props.locale, className: props.className }));
|
|
317
372
|
});
|
|
318
373
|
FailureList.displayName = "FailureList";
|
|
374
|
+
/** HeroCard 的 data 校验入口(它不经 makeDataComponent,数据形态是唯一形态)。 */
|
|
375
|
+
const assertHeroData = (data) => {
|
|
376
|
+
const problem = validateHeroData(data);
|
|
377
|
+
if (problem !== null)
|
|
378
|
+
throw dataShapeError("HeroCard", "heroData", "HeroData", problem);
|
|
379
|
+
return data;
|
|
380
|
+
};
|
|
381
|
+
/**
|
|
382
|
+
* `HeroCard`:Hero 的渲染件,双面组件,只收 data 形态——标题输入是站点声明与 Scope 的
|
|
383
|
+
* 合成物,没有单独的 spec 等价形。web 面渲染 hero 标题(h1)、按渲染 locale 格式化的运行
|
|
384
|
+
* meta(latestStartedAt 为 null 时内置「暂无运行」文案)与品牌行(等同 PoweredBy,恒含、
|
|
385
|
+
* 无拆除 prop);text 面输出标题行与 meta 行,不含品牌行
|
|
386
|
+
* (docs/feature/reports/library/site-components.md「HeroCard」)。
|
|
387
|
+
*/
|
|
388
|
+
export const HeroCard = defineComponent({
|
|
389
|
+
web: (props, ctx) => {
|
|
390
|
+
assertHeroData(props.data);
|
|
391
|
+
return _jsx(HeroCardWeb, { title: props.title, data: props.data, className: props.className, locale: ctx.locale });
|
|
392
|
+
},
|
|
393
|
+
text: (props, ctx) => {
|
|
394
|
+
assertHeroData(props.data);
|
|
395
|
+
return heroCardText(props.title, props.data, ctx);
|
|
396
|
+
},
|
|
397
|
+
});
|
|
398
|
+
HeroCard.displayName = "HeroCard";
|
|
399
|
+
/**
|
|
400
|
+
* `Hero`:页首的站点标题区——标题、最后运行时间、快照合成来源,恒含品牌行。官方组合组件,
|
|
401
|
+
* 与手写 `<HeroCard title={title ?? ctx.report.title} data={await heroData(ctx.scope)} />`
|
|
402
|
+
* 严格等价、没有私有能力;读 `ctx.report` 意味着输出跟随站点,要站点无关的标题区直接用
|
|
403
|
+
* `HeroCard` 显式传值(docs/feature/reports/library/site-components.md「Hero」)。
|
|
404
|
+
*/
|
|
405
|
+
export const Hero = defineComponent(async ({ title, className }, ctx) => (_jsx(HeroCard, { title: title ?? ctx.report.title, data: await heroData(ctx.scope), className: className })));
|
|
406
|
+
Hero.displayName = "Hero";
|
|
407
|
+
/**
|
|
408
|
+
* `PoweredBy`:唯一的品牌件,无 props 双面组件。web 面渲染指向 niceeval 官网的一行品牌色
|
|
409
|
+
* 小字(`utm_source=report&utm_medium=powered-by`,`rel` 仅 `noopener` 以保留 Referer);
|
|
410
|
+
* text 面零输出。没有任何配置——品牌契约是「提供一个组件,不给开关」:不想要品牌就不用
|
|
411
|
+
* 这些组件、自己写替代组件(docs/feature/reports/library/site-components.md「PoweredBy」)。
|
|
412
|
+
*/
|
|
413
|
+
export const PoweredBy = defineComponent({
|
|
414
|
+
web: () => _jsx(PoweredByWeb, {}),
|
|
415
|
+
text: () => "",
|
|
416
|
+
});
|
|
417
|
+
PoweredBy.displayName = "PoweredBy";
|
|
418
|
+
/**
|
|
419
|
+
* `ScopeWarnings`:选择警告区,警告的唯一呈现组件。把 Scope 携带的 `ScopeWarning[]`
|
|
420
|
+
* 按「下一步动作」聚合渲染(带 experimentId 的按实验聚合、非实验作用域按 kind 聚合;
|
|
421
|
+
* integrity 组在前);web 面组头带去重后的可复制命令、明细收原生 `<details>`(总条数 ≤ 3
|
|
422
|
+
* 默认展开),text 面同构但不折叠。空警告集与裸 `Snapshot[]` 输入两面零输出
|
|
423
|
+
* (docs/feature/reports/library/site-components.md「ScopeWarnings」)。
|
|
424
|
+
*/
|
|
425
|
+
export const ScopeWarnings = makeDataComponent({
|
|
426
|
+
name: "ScopeWarnings",
|
|
427
|
+
dataFnName: "scopeWarningsData",
|
|
428
|
+
shapeName: "ScopeWarning[]",
|
|
429
|
+
dataFn: (input) => scopeWarningsData(input),
|
|
430
|
+
specKeys: [],
|
|
431
|
+
validate: validateScopeWarningsData,
|
|
432
|
+
web: (props, ctx) => props.data.length === 0 ? null : (_jsx(ScopeWarningsWeb, { data: props.data, locale: props.locale ?? ctx.locale, className: props.className })),
|
|
433
|
+
text: (props, ctx) => scopeWarningsText(props.data, ctx),
|
|
434
|
+
});
|
|
435
|
+
/**
|
|
436
|
+
* `CopyFixPrompt`:把当前范围的全部失败整理成一段可交给 coding agent 的修复 prompt。
|
|
437
|
+
* prompt 在 resolve 阶段算好、烘进静态 HTML,无 JS 时在折叠块里完整可读,「复制」是增强层
|
|
438
|
+
* 行为;`failures` 为 0 时两面零输出;text 面恒零输出——终端里的等价能力是 `show` 的
|
|
439
|
+
* attempt 下钻命令本身(docs/feature/reports/library/site-components.md「CopyFixPrompt」)。
|
|
440
|
+
*/
|
|
441
|
+
export const CopyFixPrompt = makeDataComponent({
|
|
442
|
+
name: "CopyFixPrompt",
|
|
443
|
+
dataFnName: "copyFixPromptData",
|
|
444
|
+
shapeName: "CopyFixPromptData",
|
|
445
|
+
dataFn: (input) => copyFixPromptData(input),
|
|
446
|
+
specKeys: [],
|
|
447
|
+
validate: validateCopyFixPromptData,
|
|
448
|
+
web: (props, ctx) => props.data.failures === 0 ? null : (_jsx(CopyFixPromptWeb, { data: props.data, locale: props.locale ?? ctx.locale, className: props.className })),
|
|
449
|
+
text: () => "",
|
|
450
|
+
});
|
|
451
|
+
/**
|
|
452
|
+
* `TraceWaterfall`:每个 attempt 一行的执行时间瀑布,用 canonical OTel 字段显示被测 agent
|
|
453
|
+
* 的原始 span(agent / model / tool)。web 面静态渲染顶层 span 分解条(失败 span 带失败
|
|
454
|
+
* 标记),行链接 attempt 详情;text 面每 attempt 一行(locator、总耗时、span 计数与失败
|
|
455
|
+
* 标记)+ 可复制的 `--timing` 下钻命令。trace 缺失的行照常出现并如实显示缺失;runner
|
|
456
|
+
* 生命周期节点不进瀑布(docs/feature/reports/library/site-components.md「TraceWaterfall」)。
|
|
457
|
+
*/
|
|
458
|
+
export const TraceWaterfall = makeDataComponent({
|
|
459
|
+
name: "TraceWaterfall",
|
|
460
|
+
dataFnName: "traceWaterfallData",
|
|
461
|
+
shapeName: "TraceWaterfallRow[]",
|
|
462
|
+
dataFn: (input) => traceWaterfallData(input),
|
|
463
|
+
specKeys: [],
|
|
464
|
+
validate: validateTraceWaterfallData,
|
|
465
|
+
web: (props, ctx) => (_jsx(TraceWaterfallWeb, { data: props.data, attemptHref: hrefOf(props, ctx) ?? ctx.attemptHref, locale: props.locale ?? ctx.locale, className: props.className })),
|
|
466
|
+
text: (props, ctx) => traceWaterfallText(props.data, ctx),
|
|
467
|
+
});
|
|
319
468
|
/** 榜单:一行一个维度值、一列一个指标,回答「谁整体更好」。 */
|
|
320
469
|
export const MetricTable = makeDataComponent({
|
|
321
470
|
name: "MetricTable",
|
package/dist/report/compute.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AttemptListItem, DeltaData, DeltaPair, DimensionInput, EvalListItem, ExperimentComparisonData, ExperimentListItem, FlagPairs, LineData, MatrixData, Metric, NumericAxis, ReportInput, ScatterData, ScopeSummaryData, ScoreboardData, TableData } from "./types.ts";
|
|
1
|
+
import type { AttemptListItem, CopyFixPromptData, DeltaData, DeltaPair, DimensionInput, EvalListItem, ExperimentComparisonData, ExperimentListItem, FlagPairs, HeroData, LineData, MatrixData, Metric, NumericAxis, ReportInput, ScatterData, ScopeSummaryData, ScopeWarning, ScoreboardData, TableData, TraceWaterfallRow } from "./types.ts";
|
|
2
2
|
import type { JsonValue } from "../types.ts";
|
|
3
3
|
export interface MetricTableOptions {
|
|
4
4
|
/** 行维度(内置 / 自定义 / flag() / runConfig())。 */
|
|
@@ -110,3 +110,30 @@ export interface DeltaTableOptions {
|
|
|
110
110
|
evals?: string | readonly string[];
|
|
111
111
|
}
|
|
112
112
|
export declare function deltaTableData(input: ReportInput, options: DeltaTableOptions): Promise<DeltaData>;
|
|
113
|
+
/**
|
|
114
|
+
* `heroData(input)`:站点标题区的运行 meta——`latestStartedAt` 取范围内最新快照的开始时间
|
|
115
|
+
* (空范围为 null,不编造当前时间),`snapshots` 计贡献当前水位的快照数
|
|
116
|
+
* (docs/feature/reports/library/site-components.md「HeroCard」)。
|
|
117
|
+
*/
|
|
118
|
+
export declare function heroData(input: ReportInput): Promise<HeroData>;
|
|
119
|
+
/**
|
|
120
|
+
* `scopeWarningsData(input)`:Scope 携带的挑选警告原样透出;`input` 是裸 `Snapshot[]` 时
|
|
121
|
+
* 没有挑选过程、没有警告,返回空数组,也如实
|
|
122
|
+
* (docs/feature/reports/library/site-components.md「ScopeWarnings」)。
|
|
123
|
+
*/
|
|
124
|
+
export declare function scopeWarningsData(input: ReportInput): Promise<readonly ScopeWarning[]>;
|
|
125
|
+
/**
|
|
126
|
+
* `copyFixPromptData(input)`:把范围内全部失败(verdict 为 failed / errored 的 attempt)
|
|
127
|
+
* 整理成一段可交给 coding agent 的修复 prompt——逐失败含 eval id、主失败摘要与 attempt
|
|
128
|
+
* 下钻命令(`niceeval show @<locator>`)。prompt 面向 agent,固定英文
|
|
129
|
+
* (docs/feature/reports/library/site-components.md「CopyFixPrompt」)。
|
|
130
|
+
*/
|
|
131
|
+
export declare function copyFixPromptData(input: ReportInput): Promise<CopyFixPromptData>;
|
|
132
|
+
/**
|
|
133
|
+
* `traceWaterfallData(input)`:每个 attempt 一行的执行时间瀑布摘要。span 事实只来自
|
|
134
|
+
* trace artifact(经 AttemptHandle 懒加载的 canonical OTel span);runner 生命周期节点
|
|
135
|
+
* (`result.phases`)不进瀑布。行内只汇总顶层 span(parentSpanId 缺失或不在本 trace 内),
|
|
136
|
+
* 按 startOffsetMs 升序;trace 缺失或为空时 `durationMs` 为 null、行照常出现
|
|
137
|
+
* (docs/feature/reports/library/site-components.md「TraceWaterfall」)。
|
|
138
|
+
*/
|
|
139
|
+
export declare function traceWaterfallData(input: ReportInput): Promise<readonly TraceWaterfallRow[]>;
|