niceeval 0.13.0 → 0.13.2-canary.35
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 +1 -0
- package/README.md +9 -10
- package/README.zh.md +9 -10
- package/dist/agents/ai-sdk.cjs.map +1 -1
- package/dist/agents/ai-sdk.d.cts +1 -1
- package/dist/agents/ai-sdk.d.mts +1 -1
- package/dist/agents/ai-sdk.d.ts +1 -1
- package/dist/agents/coding-cli-versions.cjs +10 -1
- package/dist/agents/coding-cli-versions.cjs.map +1 -1
- package/dist/agents/coding-cli-versions.d.cts +8 -3
- package/dist/agents/coding-cli-versions.d.mts +8 -3
- package/dist/agents/coding-cli-versions.d.ts +8 -3
- package/dist/agents/coding-cli-versions.js +18 -12
- package/dist/agents/deepseek-harness.cjs +103 -0
- package/dist/agents/deepseek-harness.cjs.map +1 -0
- package/dist/agents/deepseek-harness.d.cts +12 -0
- package/dist/agents/deepseek-harness.d.mts +12 -0
- package/dist/agents/deepseek-harness.d.ts +12 -0
- package/dist/agents/deepseek-harness.js +7 -0
- package/dist/agents/deepseek-harness.js.map +1 -0
- package/dist/agents/index.cjs +5 -1
- package/dist/agents/index.cjs.map +1 -1
- package/dist/agents/index.d.cts +4 -0
- package/dist/agents/index.d.mts +4 -0
- package/dist/agents/index.d.ts +4 -0
- package/dist/agents/index.js +54 -50
- package/dist/agents/index.mjs +54 -50
- package/dist/agents/omp.cjs +170 -0
- package/dist/agents/omp.cjs.map +1 -0
- package/dist/agents/omp.d.cts +14 -0
- package/dist/agents/omp.d.mts +14 -0
- package/dist/agents/omp.d.ts +14 -0
- package/dist/agents/omp.js +7 -0
- package/dist/agents/omp.js.map +1 -0
- package/dist/agents/types.cjs.map +1 -1
- package/dist/agents/types.d.cts +2 -2
- package/dist/agents/types.d.mts +2 -2
- package/dist/agents/types.d.ts +2 -2
- package/dist/analysis/api.cjs +9 -1
- package/dist/analysis/api.cjs.map +1 -1
- package/dist/analysis/api.d.cts +21 -0
- package/dist/analysis/api.d.mts +21 -0
- package/dist/analysis/api.d.ts +21 -0
- package/dist/analysis/api.js +8 -6
- package/dist/cli.cjs +10 -1
- package/dist/cli.cjs.map +1 -1
- package/dist/i18n/en.cjs +7 -2
- package/dist/i18n/en.cjs.map +1 -1
- package/dist/i18n/en.d.cts +7 -2
- package/dist/i18n/en.d.mts +7 -2
- package/dist/i18n/en.d.ts +7 -2
- package/dist/o11y/parsers/hermes.cjs +1 -1
- package/dist/o11y/parsers/hermes.cjs.map +1 -1
- package/dist/report/built-in/analysis-values.cjs +21 -5
- package/dist/report/built-in/analysis-values.cjs.map +1 -1
- package/dist/report/built-in/analysis-values.d.cts +11 -9
- package/dist/report/built-in/analysis-values.d.mts +11 -9
- package/dist/report/built-in/analysis-values.d.ts +11 -9
- package/dist/report/built-in/overview.cjs +1 -0
- package/dist/report/built-in/overview.cjs.map +1 -1
- package/dist/report/built-in/result-components.cjs +58 -12
- package/dist/report/built-in/result-components.cjs.map +1 -1
- package/dist/report/built-in/result-components.d.cts +15 -0
- package/dist/report/built-in/result-components.d.mts +15 -0
- package/dist/report/built-in/result-components.d.ts +15 -0
- package/dist/report/built-in/run-membership-overview.cjs +100 -4
- package/dist/report/built-in/run-membership-overview.cjs.map +1 -1
- package/dist/report/built-in/standard.cjs +1 -0
- package/dist/report/built-in/standard.cjs.map +1 -1
- package/dist/report/built-in/standard.d.cts +1 -0
- package/dist/report/built-in/standard.d.mts +1 -0
- package/dist/report/built-in/standard.d.ts +1 -0
- package/dist/report/components/entity-lists/compute.cjs +40 -3
- package/dist/report/components/entity-lists/compute.cjs.map +1 -1
- package/dist/report/components/entity-lists/compute.d.cts +8 -6
- package/dist/report/components/entity-lists/compute.d.mts +8 -6
- package/dist/report/components/entity-lists/compute.d.ts +8 -6
- package/dist/report/components/entity-lists/content.cjs +31 -6
- package/dist/report/components/entity-lists/content.cjs.map +1 -1
- package/dist/report/components/entity-lists/index.cjs +3 -2
- package/dist/report/components/entity-lists/index.cjs.map +1 -1
- package/dist/report/components/entity-lists/index.d.cts +1 -1
- package/dist/report/components/entity-lists/index.d.mts +1 -1
- package/dist/report/components/entity-lists/index.d.ts +1 -1
- package/dist/report/definition/cell.cjs +3 -0
- package/dist/report/definition/cell.cjs.map +1 -1
- package/dist/report/definition/cell.d.cts +2 -0
- package/dist/report/definition/cell.d.mts +2 -0
- package/dist/report/definition/cell.d.ts +2 -0
- package/dist/report/definition/primitives.cjs +9 -2
- package/dist/report/definition/primitives.cjs.map +1 -1
- package/dist/report/execution/machine.cjs +1 -1
- package/dist/report/execution/machine.cjs.map +1 -1
- package/dist/report/host/execute.cjs +14 -4
- package/dist/report/host/execute.cjs.map +1 -1
- package/dist/report/host/execute.d.cts +5 -0
- package/dist/report/host/execute.d.mts +5 -0
- package/dist/report/host/execute.d.ts +5 -0
- package/dist/report/host/from-record.cjs +6 -1
- package/dist/report/host/from-record.cjs.map +1 -1
- package/dist/report/host/from-record.d.cts +5 -0
- package/dist/report/host/from-record.d.mts +5 -0
- package/dist/report/host/from-record.d.ts +5 -0
- package/dist/report/runtime/resolved-page.cjs +16 -6
- package/dist/report/runtime/resolved-page.cjs.map +1 -1
- package/dist/report/runtime/resolved-page.d.cts +3 -0
- package/dist/report/runtime/resolved-page.d.mts +3 -0
- package/dist/report/runtime/resolved-page.d.ts +3 -0
- package/dist/report/runtime/text.cjs +1 -0
- package/dist/report/runtime/text.cjs.map +1 -1
- package/dist/report/runtime/text.d.cts +4 -0
- package/dist/report/runtime/text.d.mts +4 -0
- package/dist/report/runtime/text.d.ts +4 -0
- package/dist/runner/feedback/human.cjs +180 -16
- package/dist/runner/feedback/human.cjs.map +1 -1
- package/dist/runner/run.cjs +43 -0
- package/dist/runner/run.cjs.map +1 -1
- package/dist/sample/capability.cjs +93 -0
- package/dist/sample/capability.cjs.map +1 -1
- package/dist/sample/capability.d.cts +3 -1
- package/dist/sample/capability.d.mts +3 -1
- package/dist/sample/capability.d.ts +3 -1
- package/dist/sample/capability.js +8 -6
- package/dist/sandbox/docker-agent-image.cjs +5 -1
- package/dist/sandbox/docker-agent-image.cjs.map +1 -1
- package/dist/sandbox/docker-agent-image.d.cts +2 -0
- package/dist/sandbox/docker-agent-image.d.mts +2 -0
- package/dist/sandbox/docker-agent-image.d.ts +2 -0
- package/dist/sandbox/docker-agent-image.js +14 -10
- package/dist/sandbox/index.cjs +4 -2
- package/dist/sandbox/index.cjs.map +1 -1
- package/dist/sandbox/index.d.cts +1 -1
- package/dist/sandbox/index.d.mts +1 -1
- package/dist/sandbox/index.d.ts +1 -1
- package/dist/sandbox/index.js +120 -116
- package/dist/sandbox/index.mjs +120 -116
- package/docs-site/images/hitl-handshake-zh.svg +3 -3
- package/docs-site/zh/examples/integrations/ai-sdk-v7.mdx +3 -3
- package/docs-site/zh/examples/integrations/claude-sdk.mdx +3 -3
- package/docs-site/zh/examples/integrations/codex-sdk.mdx +5 -5
- package/docs-site/zh/examples/integrations/langgraph.mdx +3 -3
- package/docs-site/zh/examples/integrations/pi-sdk.mdx +5 -5
- package/docs-site/zh/explanation/adapter.mdx +5 -5
- package/docs-site/zh/explanation/assert.mdx +1 -1
- package/docs-site/zh/explanation/drive.mdx +3 -1
- package/docs-site/zh/explanation/evals.mdx +3 -1
- package/docs-site/zh/explanation/hitl.mdx +7 -7
- package/docs-site/zh/explanation/runner.mdx +2 -2
- package/docs-site/zh/index.mdx +2 -2
- package/docs-site/zh/reference/builtin-agents.mdx +4 -4
- package/docs-site/zh/reference/capabilities.mdx +1 -1
- package/docs-site/zh/reference/cli.mdx +14 -14
- package/docs-site/zh/reference/events.mdx +11 -11
- package/docs-site/zh/reference/official-adapters.mdx +1 -1
- package/docs-site/zh/reference/results-data.mdx +6 -0
- package/docs-site/zh/troubleshooting/debugging.mdx +2 -2
- package/docs-site/zh/tutorials/agent-feedback-loop.mdx +2 -2
- package/docs-site/zh/tutorials/ci-integration.mdx +1 -1
- package/docs-site/zh/tutorials/connect-your-agent.mdx +2 -2
- package/docs-site/zh/tutorials/custom-reports.mdx +4 -4
- package/docs-site/zh/tutorials/deploy-report-site.mdx +3 -3
- package/docs-site/zh/tutorials/docker-in-docker.mdx +3 -0
- package/docs-site/zh/tutorials/experiments.mdx +2 -2
- package/docs-site/zh/tutorials/handle-execution-failures.mdx +1 -1
- package/docs-site/zh/tutorials/install-custom-sandbox-agent.mdx +1 -1
- package/docs-site/zh/tutorials/nixos-managed-dind.mdx +160 -0
- package/docs-site/zh/tutorials/publish-report.mdx +4 -4
- package/docs-site/zh/tutorials/reporters.mdx +1 -1
- package/docs-site/zh/tutorials/rerun-and-cache.mdx +16 -0
- package/docs-site/zh/tutorials/viewing-results.mdx +28 -10
- package/docs-site/zh/tutorials/write-send.mdx +7 -6
- package/package.json +1 -1
|
@@ -14,7 +14,7 @@ HITL(human-in-the-loop,人工介入)指 agent 在执行中间停下来,
|
|
|
14
14
|
- **Codex**:审批模式(suggest / auto-edit 等)决定哪些动作要先经人确认,本质是同一扇门。
|
|
15
15
|
- **AI SDK 应用**:工具不带 `execute` 时,工具调用会浮到前端,由界面上的人确认后把结果交回(`addToolResult`),模型再继续——这是自研应用里最常见的审批门写法。
|
|
16
16
|
|
|
17
|
-
对被测对象来说,这条"停下来等人"的分支和别的行为一样需要回归:批准后该发生的事发生了吗?拒绝后真的没做吗?问错了人、停错了地方呢?但评估用例是自动跑的,里面没有人。[NiceEval](https://niceeval.com/) 的做法是把"人"
|
|
17
|
+
对被测对象来说,这条"停下来等人"的分支和别的行为一样需要回归:批准后该发生的事发生了吗?拒绝后真的没做吗?问错了人、停错了地方呢?但评估用例是自动跑的,里面没有人。[NiceEval](https://niceeval.com/) 的做法是把"人"折叠成三个可编排的动作:用 `t.check(turn.status, equals("waiting"))` 确认 agent 停下、用 `t.requireInputRequest()` 检查它在等什么、再用 `t.respond()` 替人回答。批准、拒绝、补充信息,从此都是能写进评估用例的路径。
|
|
18
18
|
|
|
19
19
|
## 停轮如何表达:waiting + input.requested
|
|
20
20
|
|
|
@@ -36,10 +36,10 @@ HITL(human-in-the-loop,人工介入)指 agent 在执行中间停下来,
|
|
|
36
36
|
## 评估侧:三个动作
|
|
37
37
|
|
|
38
38
|
```ts
|
|
39
|
-
import { toolMatch } from "niceeval/expect";
|
|
39
|
+
import { equals, toolMatch } from "niceeval/expect";
|
|
40
40
|
|
|
41
41
|
const draft = await t.send("给老板发一封周报邮件。");
|
|
42
|
-
draft.
|
|
42
|
+
t.check(draft.status, equals("waiting")); // ① 断言这一轮停下了
|
|
43
43
|
|
|
44
44
|
const req = t.requireInputRequest({ action: "send_email" }); // ② 取出待答请求
|
|
45
45
|
|
|
@@ -47,7 +47,7 @@ await t.respond({ request: req, optionId: "approve" }); // ③ 替人回答,发
|
|
|
47
47
|
t.calledTool(toolMatch("send_email", { status: "completed" }));
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
-
- `t.
|
|
50
|
+
- `t.check(draft.status, equals("waiting"))` 断言这一轮确实以 waiting 停下。反过来 `draft.succeeded()` 在 waiting 轮上会失败——停轮是显式状态,不会被当成"跑完了"。
|
|
51
51
|
- `t.requireInputRequest(filter)` 从待处理请求里精确取一个(按 `id` / `prompt` / `action` / `optionIds` 等字段匹配),匹配到 0 个或超过 1 个都会抛,多个请求并停时靠它消歧。
|
|
52
52
|
- `t.respond(...)` 回答并发出下一轮。同类请求要给同一个答案时(比如逐个批准一批改动),`t.respondAll(optionId)` 一次处理完。
|
|
53
53
|
|
|
@@ -57,13 +57,13 @@ t.calledTool(toolMatch("send_email", { status: "completed" }));
|
|
|
57
57
|
|
|
58
58
|
HITL 对 Adapter 的全部要求就三件事——前两件发生在停下的那一轮,第三件发生在回答到达的下一轮:
|
|
59
59
|
|
|
60
|
-
1. **停轮时如实返回 `status: "waiting"`**,不要把挂起报成 `"completed"`,否则 `
|
|
60
|
+
1. **停轮时如实返回 `status: "waiting"`**,不要把挂起报成 `"completed"`,否则 `t.check(turn.status, equals("waiting"))` 会失败、`succeeded()` 可能假通过。
|
|
61
61
|
2. **每个待回答的问题吐一条 `input.requested`**,`id` 稳定、字段尽量填全——评估侧的检查和对位全靠它们。
|
|
62
62
|
3. **下一次 `send` 先交裁决、再续跑**:从 `input.responses` 按 `requestId` 把裁决交回应用(不要按顺序猜),然后接着上一轮挂起的地方继续,而不是重发请求。
|
|
63
63
|
|
|
64
64
|
"挂起的现场"(比如读了一半的 SSE 流)存在本会话线的 `ctx.session` 上。Adapter 用 `createSessionSlot<Pending>()` 声明私有 slot,停轮时 `ctx.session.set(slot, pending)`,回答轮 `ctx.session.take(slot)` 取回,取到即清除。怎么和流式驱动拼起来,见[写 send](/zh/tutorials/write-send#第五步:hitl) 第五步的完整骨架。
|
|
65
65
|
|
|
66
|
-
和 [NiceEval](https://niceeval.com/) 的其它能力一样,HITL 没有布尔声明:**做到了就是有**。send 返回过 `"waiting"` 并吐了 `input.requested`,`t.respond` 就能工作。没做到,eval
|
|
66
|
+
和 [NiceEval](https://niceeval.com/) 的其它能力一样,HITL 没有布尔声明:**做到了就是有**。send 返回过 `"waiting"` 并吐了 `input.requested`,`t.respond` 就能工作。没做到,eval 会在状态检查或 `requireInputRequest()` 上明确失败,而不是静默假通过。能力如何从构造中来,见 [Adapter](/zh/explanation/adapter#能力从哪来:构造证明,不是问卷)。
|
|
67
67
|
|
|
68
68
|
## 拒绝不是故障
|
|
69
69
|
|
|
@@ -81,7 +81,7 @@ HITL 对 Adapter 的全部要求就三件事——前两件发生在停下的那
|
|
|
81
81
|
|
|
82
82
|
## 相关阅读
|
|
83
83
|
|
|
84
|
-
- [Drive](/zh/explanation/drive#人工介入-hitl) —
|
|
84
|
+
- [Drive](/zh/explanation/drive#人工介入-hitl) — 评估侧的完整用法:状态检查、`t.requireInputRequest()`、`t.respond()` / `t.respondAll()`。
|
|
85
85
|
- [Adapter](/zh/explanation/adapter#不同回答的入参) — 回答到 Adapter 的结构化入参,四种典型形态。
|
|
86
86
|
- [写 send](/zh/tutorials/write-send) — Adapter 侧实操:typed session slot 与流式 + HITL 的完整骨架。
|
|
87
87
|
- [接入你的 Agent](/zh/tutorials/connect-your-agent) — 接入全景:最小接入、参数通道与增量地图。
|
|
@@ -66,8 +66,8 @@ Reporter 只接入当前 Invocation。它可以把当前进程已知的结果交
|
|
|
66
66
|
Runner 结束后,用明确 Run 选择查看结果:
|
|
67
67
|
|
|
68
68
|
```sh
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
pnpm exec niceeval show --run 01J9ZK3M6P4T7V9X2C5N8QW0RY
|
|
70
|
+
pnpm exec niceeval view --run 01J9ZK3M6P4T7V9X2C5N8QW0RY --no-open
|
|
71
71
|
```
|
|
72
72
|
|
|
73
73
|
不带 locator 或 `--run` 的 `show` 和 `view` 读取身份仍匹配当前项目的全部结果;locator 与 `--run` 读取指定历史事实。NiceEval 形成 `Sample`,再按选中 Page 或完整站点所需的 Measure 与领域视图取得闭合值。
|
package/docs-site/zh/index.mdx
CHANGED
|
@@ -107,8 +107,8 @@ export default defineExperiment({
|
|
|
107
107
|
|
|
108
108
|
```sh
|
|
109
109
|
npx niceeval exp local weather-tool
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
pnpm exec niceeval show # 终端读取结果,失败项可继续下钻
|
|
111
|
+
pnpm exec niceeval view # 网页交互浏览
|
|
112
112
|
```
|
|
113
113
|
|
|
114
114
|
如果被测对象是需要隔离工作区的 coding agent(Codex、Claude Code 插件/Skill),评估用例里改用 `t.sandbox.uploadDirectory()` 铺工作区。检查文件变化用 `t.sandbox.fileChanged()` 等归因断言。`t.sandbox.runCommand()` 跑测试。参考独立仓库 [coding-agent-skill](https://github.com/CorrectRoadH/coding-agent-skill)。
|
|
@@ -10,17 +10,17 @@ description: "NiceEval 内置的 claude-code、codex、bub 适配器分别做到
|
|
|
10
10
|
|
|
11
11
|
| 能力 | 对应的断言 / API |
|
|
12
12
|
|---|---|
|
|
13
|
-
| 收发消息(基础契约) | `t.send()`(可多次调用)、`t.reply`、`turn.
|
|
14
|
-
| 事件流完整性 | `calledTool` / `
|
|
13
|
+
| 收发消息(基础契约) | `t.send()`(可多次调用)、`t.reply`、`t.check(turn.data, equals(...))` / `matches(...)`、按状态判断的 `t.succeeded()` |
|
|
14
|
+
| 事件流完整性 | `calledTool` / `usedNoTools` / `maxToolCalls` / `noFailedActions` / `event` 等作用域断言;`toolOrder` / `eventOrder` 只在 Turn 或 Session 上接收 matcher。消息用 `t.check(turn.message, includes(...))` 或 `t.check(turn.message, pattern(...))`。**负断言(`notCalledTool` 等)有完整事件流才可信** |
|
|
15
15
|
| 会话续接 | 跨轮记忆断言、`t.newSession()` 会话隔离 |
|
|
16
|
-
| HITL(人工介入) | `t.
|
|
16
|
+
| HITL(人工介入) | `t.check(turn.status, equals("waiting"))`、`t.requireInputRequest()`、`t.respond()` / `t.respondAll()` |
|
|
17
17
|
| `tracing` | trace decoding、`niceeval view` 的调用瀑布图 |
|
|
18
18
|
|
|
19
19
|
## 三个内置 agent 分别做到哪
|
|
20
20
|
|
|
21
21
|
| Agent | 收发 | 事件流 | 会话续接 | HITL | tracing | 备注 |
|
|
22
22
|
|---|---|---|---|---|---|---|
|
|
23
|
-
| `claude-code` | ✅ | ✅ | ✅(`claude --resume <id>`) | ❌ | ✅(`http/protobuf` → OTLP,beta 开关) | 内置 parser 自动吐 `compaction`
|
|
23
|
+
| `claude-code` | ✅ | ✅ | ✅(`claude --resume <id>`) | ❌ | ✅(`http/protobuf` → OTLP,beta 开关) | 内置 parser 自动吐 `compaction` 原始事件,供报告和诊断读取;当前没有公开 `eventMatch` selector |
|
|
24
24
|
| `codex` | ✅ | ✅ | ✅(`codex exec resume <id>`) | ❌ | ✅(`http/json` → OTLP) | 内置 parser 自动吐 `compaction` 事件 |
|
|
25
25
|
| `bub` | ✅ | ✅ | ✅(`--session-id` + tape 续接) | ❌ | ✅(`http/protobuf` → OTLP) | 内置 parser 自动吐 `compaction` 事件 |
|
|
26
26
|
|
|
@@ -19,7 +19,7 @@ description: "Agent 的构造方式、运行时行为与必填的六通道 evide
|
|
|
19
19
|
| `tracing`(OTLP 接收 → `niceeval view` 瀑布图) | CLI 型 Agent 配置 `tracing`。长驻应用在 config 配置固定的 `telemetry` 端口 | Span 只进时间瀑布图,不能填补行为证据缺口 |
|
|
20
20
|
| 跨轮续接与 `t.newSession()` 隔离 | 用 `ctx.session.id` / `capture` 续接后端会话,或用 `ctx.session.get` / `set` 保存 Adapter 私有的强类型历史 | 会话接法决定实际行为,不从一个 evidence bit 推断 |
|
|
21
21
|
| HITL(`t.respond()`) | `send` 返回 `status: "waiting"` 和 `input.requested` | 下一轮回答按结构化 request ID 对位 |
|
|
22
|
-
| Compaction 可见 | 官方 parser 或完整的手写映射发出 `compaction` 事件 |
|
|
22
|
+
| Compaction 可见 | 官方 parser 或完整的手写映射发出 `compaction` 事件 | 原始事件进入报告与诊断;当前没有公开 `eventMatch` selector |
|
|
23
23
|
|
|
24
24
|
## 必填的六通道声明
|
|
25
25
|
|
|
@@ -24,10 +24,10 @@ description: "NiceEval CLI 参考:exp、debug、show、view、init、list 和
|
|
|
24
24
|
<Card title="npx niceeval clean" icon="trash">
|
|
25
25
|
删除明确 writer 留下的 Record 临时目录,不删除正式 Run 或 Attempt。
|
|
26
26
|
</Card>
|
|
27
|
-
<Card title="
|
|
27
|
+
<Card title="pnpm exec niceeval show [--run]" icon="terminal">
|
|
28
28
|
在终端执行报告。不带 locator 或 `--run` 的命令读取当前项目结果;精确 Attempt 定位符或 Run ID 用于审计历史。
|
|
29
29
|
</Card>
|
|
30
|
-
<Card title="
|
|
30
|
+
<Card title="pnpm exec niceeval view" icon="eye">
|
|
31
31
|
构建完整报告站并在浏览器中托管。它与 `show` 共享选择规则,但会枚举全部页面。
|
|
32
32
|
</Card>
|
|
33
33
|
</CardGroup>
|
|
@@ -205,7 +205,7 @@ npx niceeval exp compare-models weather-tool
|
|
|
205
205
|
|
|
206
206
|
运行命名 experiment,用矩阵比较 agents、models 或 flags。第二个参数开始是评估用例 ID 前缀过滤。
|
|
207
207
|
|
|
208
|
-
`show` 与 `view` 是顶层命令,应写成 `
|
|
208
|
+
`show` 与 `view` 是顶层命令,应写成 `pnpm exec niceeval show`、`pnpm exec niceeval view`。误写成 `pnpm exec niceeval exp show` / `exp view` 且没有同名 experiment 时,CLI 会在“不存在的实验”错误后提示正确命令。仓库确实存在同名 experiment 时仍按合法 id 执行。
|
|
209
209
|
|
|
210
210
|
## 两种输出:人读文本与 `--json`
|
|
211
211
|
|
|
@@ -227,10 +227,10 @@ npx niceeval exp compare --junit ./artifacts/niceeval-junit.xml
|
|
|
227
227
|
## `view`
|
|
228
228
|
|
|
229
229
|
```bash
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
230
|
+
pnpm exec niceeval view
|
|
231
|
+
pnpm exec niceeval view --run 01H...
|
|
232
|
+
pnpm exec niceeval view @01H...
|
|
233
|
+
pnpm exec niceeval view --host 192.168.0.199
|
|
234
234
|
```
|
|
235
235
|
|
|
236
236
|
打开本地结果查看器。它和 `show` 共用默认 Report 与选择规则。不带 locator 或 `--run` 的命令读取所有身份仍匹配当前项目的结果;精确 `@<AttemptLocator>` 显示该 Attempt 的默认概览;`--run` 读取指定历史 Run。NiceEval 随后形成固定 Sample、枚举全部 Page 与参数实例,并构建完整站点。
|
|
@@ -246,13 +246,13 @@ npx niceeval view --host 192.168.0.199
|
|
|
246
246
|
## `show`
|
|
247
247
|
|
|
248
248
|
```bash
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
249
|
+
pnpm exec niceeval show
|
|
250
|
+
pnpm exec niceeval show --run 01H...
|
|
251
|
+
pnpm exec niceeval show --run 01H... --run 01J...
|
|
252
|
+
pnpm exec niceeval show @01H...
|
|
253
|
+
pnpm exec niceeval show --run 01H... --page /
|
|
254
|
+
pnpm exec niceeval show --run 01H... --report ./reports/summary.tsx --page /overview
|
|
255
|
+
pnpm exec niceeval show --run 01H... --report ./reports/summary.tsx --json
|
|
256
256
|
```
|
|
257
257
|
|
|
258
258
|
`show` 是终端报告入口,适合人直接阅读,也适合 coding agent 在上下文窗口里逐级下钻。它不接受模糊的位置选择。省略 `--page` 时选择默认 Page;提供 `--page <route>` 时只执行这个精确 route。
|
|
@@ -200,14 +200,14 @@ token 用量或 OTel span 反推得到)。与顶层 `estimatedCostUSD`(价目表
|
|
|
200
200
|
| `message` | agent(或用户)说了一段话 | `turn.message`、`turn.event(eventMatch("message", ...))`、Judge 的材料 |
|
|
201
201
|
| `operation.started`(`kind: "tool"`) | 发起一次工具调用 | `turn.calledTool(...)`、`turn.toolOrder(...)`、`turn.event(...)` |
|
|
202
202
|
| `operation.finished`(`kind: "tool"`) | 该次工具调用的结果 | 带状态条件的 `ToolMatch` |
|
|
203
|
-
| `operation.started`(`kind: "subagent"`) | 委派一个子 agent |
|
|
204
|
-
| `operation.finished`(`kind: "subagent"`) | 子 agent 返回 | `
|
|
205
|
-
| `input.requested` | 停下来等人输入(HITL) | `t.
|
|
206
|
-
| `thinking` | 思考文本 | `
|
|
207
|
-
| `compaction` | 上下文被压缩 | `
|
|
208
|
-
| `error` | 本轮出错 | `
|
|
203
|
+
| `operation.started`(`kind: "subagent"`) | 委派一个子 agent | 原始事件与报告;当前没有子 agent 专用断言 |
|
|
204
|
+
| `operation.finished`(`kind: "subagent"`) | 子 agent 返回 | 原始事件与报告;失败会进入 `noFailedActions()` 的汇总事实 |
|
|
205
|
+
| `input.requested` | 停下来等人输入(HITL) | `t.check(turn.status, equals("waiting"))`、`t.requireInputRequest()` |
|
|
206
|
+
| `thinking` | 思考文本 | view 展示;当前没有 `eventMatch` selector |
|
|
207
|
+
| `compaction` | 上下文被压缩 | view 展示;当前没有 `eventMatch` selector |
|
|
208
|
+
| `error` | 本轮出错 | view 展示;当前没有 `eventMatch` selector |
|
|
209
209
|
|
|
210
|
-
事件断言共用三个入口:`event(match)`、`notEvent(match)` 与 `eventOrder(matches)`;它们都接收 `eventMatch(...)`,不另造 selector object 或匿名事件 predicate。
|
|
210
|
+
事件断言共用三个入口:`event(match)`、`notEvent(match)` 与 `eventOrder(matches)`;它们都接收 `eventMatch(...)`,不另造 selector object 或匿名事件 predicate。当前 `eventMatch` 只有 `message`、工具 `operation.started` 与工具 `operation.finished` 三种形状,不能把全部原始 `StreamEvent` 当成可断言 selector。
|
|
211
211
|
|
|
212
212
|
## 逐事件说明
|
|
213
213
|
|
|
@@ -267,7 +267,7 @@ events.push({
|
|
|
267
267
|
});
|
|
268
268
|
```
|
|
269
269
|
|
|
270
|
-
`commandProjection()` 保留 Adapter 已确认的 original tokens,并调用同一份 `normalizeLogicalCommand()` 生成 `logical-command/v1` 投影。`pnpm exec niceeval show`
|
|
270
|
+
`commandProjection()` 保留 Adapter 已确认的 original tokens,并调用同一份 `normalizeLogicalCommand()` 生成 `logical-command/v1` 投影。`pnpm exec niceeval show` 能由 `commandMatch("niceeval", { argsStart: ["show"] })` 精确匹配。
|
|
271
271
|
|
|
272
272
|
只有原生协议已经给出 argv,或协议 grammar 能无歧义地产生单一 invocation,才能把 original 标为 available。协议只给 shell source、内容已截断或脱敏时使用 `opaqueCommandProjection(reason)`;能确认不是 command 时使用 `notCommandProjection()`。无法确认 command / not-command 时降低 actions coverage,不能从 tool name、input 或 shell 文本猜测。
|
|
273
273
|
|
|
@@ -280,7 +280,7 @@ events.push({
|
|
|
280
280
|
output?: JsonValue, status: "completed" | "failed" }
|
|
281
281
|
```
|
|
282
282
|
|
|
283
|
-
被测系统把任务委派给子 agent(等它返回)时吐这一对,`operationId`
|
|
283
|
+
被测系统把任务委派给子 agent(等它返回)时吐这一对,`operationId` 配对规则同上。它们会保留在原始事件流与报告中,但当前公开 Assert-first API 没有 `calledSubagent`,`eventMatch(...)` 也不能选择子 agent operation;不要凭空换成另一个 selector。
|
|
284
284
|
|
|
285
285
|
### `input.requested` —— 停下等人(HITL)
|
|
286
286
|
|
|
@@ -304,11 +304,11 @@ agent 停轮等人时,每个待回答的问题吐一条,同时该 Turn 的 `
|
|
|
304
304
|
{ type: "error", message: string }
|
|
305
305
|
```
|
|
306
306
|
|
|
307
|
-
有就吐,没有不硬造。`compaction` 主要来自 coding agent CLI
|
|
307
|
+
有就吐,没有不硬造。`compaction` 主要来自 coding agent CLI(上下文满了自动压缩)。这几种原始事件保留给报告与诊断;当前公开 `eventMatch` 不能选择它们。
|
|
308
308
|
|
|
309
309
|
## 映射的三条纪律
|
|
310
310
|
|
|
311
|
-
1. **时序即事实**:事件按真实发生顺序排。`toolOrder` / `eventOrder` 用单调 cursor 匹配不同 occurrence
|
|
311
|
+
1. **时序即事实**:事件按真实发生顺序排。`toolOrder` / `eventOrder` 用单调 cursor 匹配不同 occurrence 的子序列,顺序错了断言就失真。`eventOrder` 只排公开 `eventMatch` 支持的事件。
|
|
312
312
|
2. **`operationId` 配对**:每个 started operation 都要有同 `kind`、同 id 的 finished operation。只有配对完成,框架才能把状态与 input 归到同一个逻辑工具 occurrence。
|
|
313
313
|
3. **完整性必须显式**:官方转换器按实际 adapter 能力声明 evidence coverage。负向断言在相关输入或 action coverage 不完整时是 `unavailable`,不会把“没观察到”冒充“没有发生”。手工映射同样要如实声明覆盖范围,见[能力位参考](/zh/reference/capabilities)。
|
|
314
314
|
|
|
@@ -16,7 +16,7 @@ description: "NiceEval 内置的 Sandbox 和非 Sandbox 适配器分别是什么
|
|
|
16
16
|
|
|
17
17
|
- **鉴权**:`ANTHROPIC_API_KEY`(工厂参数 `apiKey` 可覆盖),可选 `ANTHROPIC_BASE_URL`(工厂参数 `baseUrl`)。
|
|
18
18
|
- **装 MCP server**:`mcpServers` 配置项,`setup` 阶段写进 Sandbox 里用户级的 `~/.claude.json`(顶层 `mcpServers` 字段)。两种形态按字段区分:本地 stdio 进程写 `command`(可带 `args` / `env`)。远程 Streamable HTTP 端点写 `url`(可带 `headers`,逐字进请求头,常用于 `Authorization`),写成 `{ "type": "http", "url": …, "headers": … }` 条目。`url` 要 Sandbox 内可达:服务跑在你自己机器上时,先用 cloudflared / tailscale 这类隧道暴露成公网地址。
|
|
19
|
-
- **装 Skill**:`skills: SkillSpec[]`。本地 Skill(`{ kind: "local", path }`,从项目根读文件或目录)或 Repo Skill(`{ kind: "repo", source, ref, skills }`,可钉 commit/tag、可只启用多 Skill 仓库里的一部分)。装进 Sandbox 的 project 级 `.claude/skills/<name>/`,claude CLI
|
|
19
|
+
- **装 Skill**:`skills: SkillSpec[]`。本地 Skill(`{ kind: "local", path }`,从项目根读文件或目录)或 Repo Skill(`{ kind: "repo", source, ref, skills }`,可钉 commit/tag、可只启用多 Skill 仓库里的一部分)。装进 Sandbox 的 project 级 `.claude/skills/<name>/`,claude CLI 原生发现。adapter 会把原生 `Skill` 调用归一为 `skill.loaded` 原始事件,不重复记成工具调用;当前公开 Assert-first API 没有专用 Skill 断言,也不能把它伪装成 `calledTool("Skill", ...)`。
|
|
20
20
|
- **装原生 Plugin**:`plugins: ClaudeCodePluginSpec[]`,每一项声明 Marketplace 连接(`name` / `source` / 可选 `ref`)和其中的 Plugin 名。这个类型只属于 claude-code,传不进 codex。复用 Sandbox 的 Experiment 不用额外处理残留:每条 Attempt 开始前,同名 marketplace 注册与已装 Plugin 都会按声明的 `source` / `ref` 重新安装。
|
|
21
21
|
- **官方配置文件**:`settingsFile` 是运行 NiceEval 的机器上的本地项目路径,不是 Sandbox 内路径。它指向一份完整的 Claude Code `settings.json`。路径相对项目根,只允许普通相对路径或 `./` 前缀。`..`、绝对路径、`~` 和解析后逃出项目根的符号链接都会报错。
|
|
22
22
|
|
|
@@ -12,6 +12,8 @@ Sample 固定本次选择的 Run、logical Slot 与分母。每个位置保留 `
|
|
|
12
12
|
|
|
13
13
|
`--run` 保留指定 Run 的完整计划范围。`project-current` 只保留仍与当前项目身份匹配的范围。两种选择都不会因为某个度量缺少输入而缩小分母。
|
|
14
14
|
|
|
15
|
+
`project-current` 的成员单位是匹配的 Run slot occurrence,不是去重后的 `(experiment, eval, ordinal)`。同一位置出现在多个匹配 Run 中时,每个 occurrence 都进入 `MetricValue.total`。重复运行或逐条 `accept` 因此可能增加分母。
|
|
16
|
+
|
|
15
17
|
Sample 只能在 `load()`、Page 或组合组件执行期间传给 Report facade。回调结束后,页面只保留已经关闭的值,不能再次读取结果。
|
|
16
18
|
|
|
17
19
|
## 用 `aggregate()` 取得 rows
|
|
@@ -58,6 +60,10 @@ Attempt Evidence、Observability、File Changes、Sources 和 Sandbox history
|
|
|
58
60
|
|
|
59
61
|
`available`、`partial`、`empty`、`unsupported` 和 `failed` 都是不同状态。不要把 `null` 当成零,也不要用只剩下的可见行数替换总分母。
|
|
60
62
|
|
|
63
|
+
例如 `formatMetricValue()` 输出的 `2 / 4 slot · partial` 表示四个已选 occurrence 中只有两个提供该 Measure 的输入。这组计数只描述覆盖率;它不是 earned score、通过率或工作完成比例。Measure 自己的 `value` 才是读数。
|
|
64
|
+
|
|
65
|
+
默认 Overview 不把这组计数重复追加到每个指标单元格。它按题型显示通过率或 earned score,并在结果不完整时用独立的 `Result coverage` 区域显示可用结果数。终端把这个区域渲染成有标题的边框;底层 `MetricValue` 的字段保持不变。
|
|
66
|
+
|
|
61
67
|
## 相关页面
|
|
62
68
|
|
|
63
69
|
- [报告 API](/zh/reference/report-components):Page、组件、JSON 和全站构建边界。
|
|
@@ -7,8 +7,8 @@ description: "根据可见错误、Sample 状态和 rebuild 反馈,定位查
|
|
|
7
7
|
先用明确 Run 读取问题,不要从目录名或时间猜测目标。
|
|
8
8
|
|
|
9
9
|
```sh
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
pnpm exec niceeval show --run <run-id>
|
|
11
|
+
pnpm exec niceeval view --run <run-id> --no-open
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
这两条命令从同一范围形成 Sample,并执行同一份 Report。先确定选择是否正确,再检查页面中的度量和问题。
|
|
@@ -49,8 +49,8 @@ Agent 应把最后一条 receipt 当作本次调用的交接信息。它不是
|
|
|
49
49
|
运行结束后,先读取 Run 的 Report:
|
|
50
50
|
|
|
51
51
|
```sh
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
pnpm exec niceeval show --run 01J9ZK3M6P4T7V9X2C5N8QW0RY
|
|
53
|
+
pnpm exec niceeval view --run 01J9ZK3M6P4T7V9X2C5N8QW0RY --no-open
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
`show` 与 `view` 选择 Sample,再取得当前目标需要的闭合分析值。`show` 只执行一个 Page;`view` 构建完整站点。Agent 应区分以下状态:
|
|
@@ -50,7 +50,7 @@ with:
|
|
|
50
50
|
成功建立 Invocation 后,NDJSON 的最后一行包含 receipt。后续脚本可以读取它的 `runIds`,用明确 Run 选择查看或导出报告:
|
|
51
51
|
|
|
52
52
|
```sh
|
|
53
|
-
|
|
53
|
+
pnpm exec niceeval view --run 01J9ZK3M6P4T7V9X2C5N8QW0RY \
|
|
54
54
|
--out ./report-site \
|
|
55
55
|
--no-open
|
|
56
56
|
```
|
|
@@ -101,10 +101,10 @@ export default defineEval({
|
|
|
101
101
|
```bash
|
|
102
102
|
npx niceeval exp my-agent # 跑这个 experiment 下的全部 eval
|
|
103
103
|
npx niceeval exp my-agent refund # 只跑 ID 以 refund 开头的
|
|
104
|
-
|
|
104
|
+
pnpm exec niceeval view --experiment my-agent # 本地查看器里看结果
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
-
**验证运行结果**:终端会显示动态 dashboard,完成和排队数量在原位更新。失败、错误和 warning 会保留在输出中。运行结束后会打印摘要和 receipt;用其中的 Run ID 也可以执行 `
|
|
107
|
+
**验证运行结果**:终端会显示动态 dashboard,完成和排队数量在原位更新。失败、错误和 warning 会保留在输出中。运行结束后会打印摘要和 receipt;用其中的 Run ID 也可以执行 `pnpm exec niceeval view --run <runId>`,查看每条评估用例逐轮的输入、事件和评分明细。
|
|
108
108
|
|
|
109
109
|
没跑通时,按报错的位置分三类排查:
|
|
110
110
|
|
|
@@ -173,10 +173,10 @@ export default defineConfig({
|
|
|
173
173
|
## 运行、读取和发布
|
|
174
174
|
|
|
175
175
|
```sh
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
176
|
+
pnpm exec niceeval show --run <run-id> --report ./reports/quality.tsx
|
|
177
|
+
pnpm exec niceeval show --run <run-id> --report ./reports/quality.tsx --json
|
|
178
|
+
pnpm exec niceeval view --run <run-id> --report ./reports/quality.tsx --no-open
|
|
179
|
+
pnpm exec niceeval view --run <run-id> --report ./reports/quality.tsx --out ./quality-site
|
|
180
180
|
```
|
|
181
181
|
|
|
182
182
|
前三条命令从相同选择形成 Sample,但范围不同:`show` 和 `show --json` 只执行一个 Page,并只捕获该页的 projection closure;`view` 与 `view --out` 枚举全部 Page 后形成完整站点及 `_niceeval/data/projections.json`。该文件的 bytes 进入 revision identity。view 的成功 rebuild 原子替换当前站点;失败时保留上一份可用站点。`--out` 必须指向不存在的目录。
|
|
@@ -7,7 +7,7 @@ description: "将 view --out 生成的完整自包含报告目录部署到任意
|
|
|
7
7
|
先生成完整报告站,再部署输出目录。托管平台不读取源 Record,也不需要安装或运行 NiceEval。
|
|
8
8
|
|
|
9
9
|
```sh
|
|
10
|
-
|
|
10
|
+
pnpm exec niceeval view --experiment checkout \
|
|
11
11
|
--out ./report-site \
|
|
12
12
|
--no-open
|
|
13
13
|
```
|
|
@@ -15,7 +15,7 @@ npx niceeval view --experiment checkout \
|
|
|
15
15
|
要部署一次明确运行,请从 receipt 读取 Run ID:
|
|
16
16
|
|
|
17
17
|
```sh
|
|
18
|
-
|
|
18
|
+
pnpm exec niceeval view --run <run-id> --out ./report-site --no-open
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
## CI 流程
|
|
@@ -30,7 +30,7 @@ GitHub Actions 的构建任务示例:
|
|
|
30
30
|
|
|
31
31
|
```yaml
|
|
32
32
|
- name: 生成报告站
|
|
33
|
-
run:
|
|
33
|
+
run: pnpm exec niceeval view --experiment checkout --out ./report-site --no-open
|
|
34
34
|
|
|
35
35
|
- name: 上传静态站点目录
|
|
36
36
|
uses: actions/upload-pages-artifact@v3
|
|
@@ -180,6 +180,9 @@ export default defineExperiment({
|
|
|
180
180
|
共享宿主或不可信 Agent使用 managed模式。它在 inner daemon之外增加 profile attestation、单容器
|
|
181
181
|
资源限制、跨进程容量准入、独占外层网络和 watchdog恢复:
|
|
182
182
|
|
|
183
|
+
NixOS宿主先按照[在 NixOS上配置 Managed DinD](/zh/tutorials/nixos-managed-dind)部署并验证 profile,
|
|
184
|
+
再配置下面的 Experiment。
|
|
185
|
+
|
|
183
186
|
```ts title="experiments/dind-managed.ts"
|
|
184
187
|
import { defineExperiment } from "niceeval";
|
|
185
188
|
import { codexAgent } from "niceeval/adapter";
|
|
@@ -75,8 +75,8 @@ api-validation claude-code pass@3 = 1/3 (33%) mean 41s
|
|
|
75
75
|
除了 pass rate,还应该看平均耗时、token、成本和失败类型。
|
|
76
76
|
|
|
77
77
|
```bash
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
pnpm exec niceeval show --experiment models
|
|
79
|
+
pnpm exec niceeval view --experiment models
|
|
80
80
|
```
|
|
81
81
|
|
|
82
82
|
每个 experiment 用自己的 `evals` 选择评估用例。函数形式会遍历所有已发现的评估用例:
|
|
@@ -108,7 +108,7 @@ npx niceeval exp compare evals/coding
|
|
|
108
108
|
需要查看某个 Attempt 的原始错误和重试摘要时,使用终端给出的定位符:
|
|
109
109
|
|
|
110
110
|
```shell
|
|
111
|
-
|
|
111
|
+
pnpm exec niceeval show @<attempt-locator>
|
|
112
112
|
```
|
|
113
113
|
|
|
114
114
|
自定义 Adapter 如果有专用的受理前拒绝信号,可以提供 `classifySendFailure`。该字段的类型和边界见 [`defineSandboxAgent` 参考](/zh/reference/define-agent#definesandboxagent)。
|
|
@@ -87,7 +87,7 @@ Sandbox 不需要 Node.js 或 npm。`createNpmCliInstaller` 在宿主机上下
|
|
|
87
87
|
安装或复检失败时,Attempt 会在 `agent.ensure` 阶段变成 `errored`。终端会给出 Attempt 定位符。
|
|
88
88
|
|
|
89
89
|
```shell
|
|
90
|
-
|
|
90
|
+
pnpm exec niceeval show @<attempt-locator>
|
|
91
91
|
```
|
|
92
92
|
|
|
93
93
|
先检查错误里的包名、版本和目标平台。修正 `identity`、npm 包或安装步骤后,重新运行原命令。
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "在 NixOS 上配置 Managed DinD"
|
|
3
|
+
sidebarTitle: "NixOS Managed DinD"
|
|
4
|
+
description: "使用 NiceEval 的 NixOS module 部署 managed rootless Docker profile,并通过 doctor 验证宿主环境。"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Managed rootless DinD 适合在共享 NixOS 宿主上运行不可信 Agent。NiceEval 的 NixOS module 会创建专用
|
|
8
|
+
系统用户、rootless Docker daemon、容量受限的数据盘、资源 slice 和 watchdog。日常运行 NiceEval
|
|
9
|
+
不需要 `sudo`,但首次部署和更新系统配置需要管理员权限。
|
|
10
|
+
|
|
11
|
+
如果任务可以信任 Agent,或者只在一次性 VM 中运行,先阅读[让 Sandbox 使用 Docker](/zh/tutorials/docker-in-docker)
|
|
12
|
+
选择 Docker socket 或 raw privileged DinD。它们不需要本页的宿主 profile。
|
|
13
|
+
|
|
14
|
+
## 前置条件
|
|
15
|
+
|
|
16
|
+
开始前确认:
|
|
17
|
+
|
|
18
|
+
- NixOS 使用 flake 管理系统配置;
|
|
19
|
+
- 宿主使用 systemd 和 cgroup v2;
|
|
20
|
+
- 你知道日常运行 NiceEval 的 NixOS 用户名;
|
|
21
|
+
- 宿主有足够的 CPU、内存和磁盘留给评估容器。
|
|
22
|
+
|
|
23
|
+
下面假设系统配置仓库已经有 `flake.nix`,配置名是 `my-host`,日常用户名是 `alice`。请把它们替换成
|
|
24
|
+
自己的值。
|
|
25
|
+
|
|
26
|
+
## 引入 NiceEval module
|
|
27
|
+
|
|
28
|
+
在系统配置的 `flake.nix` 中加入 NiceEval input,并把 module 放进主机的 `modules`:
|
|
29
|
+
|
|
30
|
+
```nix title="flake.nix"
|
|
31
|
+
{
|
|
32
|
+
inputs = {
|
|
33
|
+
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
34
|
+
niceeval.url = "github:NiceEval/NiceEval";
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
outputs = { self, nixpkgs, niceeval, ... }: {
|
|
38
|
+
nixosConfigurations.my-host = nixpkgs.lib.nixosSystem {
|
|
39
|
+
system = "x86_64-linux";
|
|
40
|
+
modules = [
|
|
41
|
+
niceeval.nixosModules.default
|
|
42
|
+
./configuration.nix
|
|
43
|
+
];
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
第一次运行 Nix 命令后,Nix 会把 NiceEval 的具体 commit 写进你的 `flake.lock`。提交这份锁文件,避免
|
|
50
|
+
不同机器在未确认的时间使用不同 module 版本。
|
|
51
|
+
|
|
52
|
+
## 声明 profile
|
|
53
|
+
|
|
54
|
+
在 NixOS 配置中声明一个名为 `default` 的 profile:
|
|
55
|
+
|
|
56
|
+
```nix title="configuration.nix"
|
|
57
|
+
{ ... }:
|
|
58
|
+
{
|
|
59
|
+
services.niceeval.dockerProfiles.default = {
|
|
60
|
+
enable = true;
|
|
61
|
+
accessUsers = [ "alice" ];
|
|
62
|
+
|
|
63
|
+
capacity = {
|
|
64
|
+
cpus = 4;
|
|
65
|
+
memory = "8G";
|
|
66
|
+
pids = 4096;
|
|
67
|
+
maxContainers = 2;
|
|
68
|
+
maxBuilds = 1;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
aggregate = {
|
|
72
|
+
cpus = 6;
|
|
73
|
+
memory = "12G";
|
|
74
|
+
pids = 6144;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
storage = {
|
|
78
|
+
size = "30G";
|
|
79
|
+
backing = "loop-ext4";
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`capacity` 是 NiceEval 可以分配给评估任务的预算。`aggregate` 是 daemon、构建进程、watchdog 和评估
|
|
86
|
+
容器共同受到的硬限制,因此每一项都不能小于 `capacity`。两者之间的余量留给宿主侧开销。
|
|
87
|
+
|
|
88
|
+
`loop-ext4` 会在 `/var/lib/niceeval/docker-profiles/default.img` 创建稀疏镜像,并挂载为 Docker
|
|
89
|
+
data root。`size` 是这个 profile 的磁盘上限,不代表 rebuild 时立即占用同等物理空间。
|
|
90
|
+
|
|
91
|
+
## 应用系统配置
|
|
92
|
+
|
|
93
|
+
先检查配置能够求值,再切换系统:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
nix flake check
|
|
97
|
+
sudo nixos-rebuild switch --flake .#my-host
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
module 会把 `alice` 加入 profile 的 access group。rebuild 完成后退出当前登录会话并重新登录,让新组
|
|
101
|
+
成员身份生效。只在旧 shell 中重新运行命令不会刷新 supplementary groups。
|
|
102
|
+
|
|
103
|
+
重新登录后检查服务:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
systemctl status niceeval-docker-profile-default.service
|
|
107
|
+
systemctl status niceeval-docker-profile-watchdog-default.service
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
两个服务都应显示 `active (running)`。失败时读取对应 unit 的日志:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
journalctl -u niceeval-docker-profile-default.service -b
|
|
114
|
+
journalctl -u niceeval-docker-profile-watchdog-default.service -b
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## 验证 profile
|
|
118
|
+
|
|
119
|
+
进入已经安装 NiceEval 的评估项目,以日常用户运行:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
pnpm exec niceeval docker profile list
|
|
123
|
+
pnpm exec niceeval docker profile doctor default --smoke
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
`list` 应显示 `default`。`doctor --smoke` 会检查 descriptor、Unix socket、cgroup、容量和 watchdog,
|
|
127
|
+
然后启动一个受限的外层容器及一个内层 Alpine 容器。所有项目都通过后,宿主 profile 才可以用于正式
|
|
128
|
+
评估。
|
|
129
|
+
|
|
130
|
+
不要用 `sudo pnpm exec niceeval ...` 绕过权限错误。日常用户无法访问 profile 时,先确认用户名已经写入
|
|
131
|
+
`accessUsers`,再重新登录并重跑 doctor。
|
|
132
|
+
|
|
133
|
+
## 在 Experiment 中使用
|
|
134
|
+
|
|
135
|
+
宿主通过验收后,在 Experiment 的 Docker Sandbox 中引用同一个别名:
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
dockerAccess: {
|
|
139
|
+
mode: "dind",
|
|
140
|
+
isolation: "managed-rootless",
|
|
141
|
+
profile: "default",
|
|
142
|
+
},
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Experiment 还必须声明单容器 CPU、内存、PID、只读 rootfs 和 tmpfs。完整配置见
|
|
146
|
+
[让 Sandbox 使用 Docker](/zh/tutorials/docker-in-docker#managed-rootless-dind)。先用较小的
|
|
147
|
+
`maxConcurrency` 运行一次,再根据 profile 的 `capacity` 增加并发。
|
|
148
|
+
|
|
149
|
+
## 更新 module
|
|
150
|
+
|
|
151
|
+
需要更新 NiceEval module 时,在系统配置仓库更新对应 input,检查 diff 后重新构建:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
nix flake update niceeval
|
|
155
|
+
nix flake check
|
|
156
|
+
sudo nixos-rebuild switch --flake .#my-host
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
更新会改变宿主服务,不能只更新评估项目里的 npm 依赖。保留旧 generation,确认 doctor 和实际评估都
|
|
160
|
+
通过后再清理 NixOS generation。
|
|
@@ -7,7 +7,7 @@ description: "用 view --out 导出可离线打开、与源 Record 脱离且包
|
|
|
7
7
|
`niceeval view --out <目录>` 从已发布结果形成固定 Sample,再构建完整报告站。它不是把当前浏览器页面保存为文件:`pages` 中显式声明的所有普通 Page、参数 Page 实例、资源和下载都必须先关闭并通过校验;Host 不补建详情页。
|
|
8
8
|
|
|
9
9
|
```sh
|
|
10
|
-
|
|
10
|
+
pnpm exec niceeval view --experiment checkout \
|
|
11
11
|
--out ./report-site \
|
|
12
12
|
--no-open
|
|
13
13
|
```
|
|
@@ -15,7 +15,7 @@ npx niceeval view --experiment checkout \
|
|
|
15
15
|
需要固定到本次运行时,从 receipt 的 `runIds` 取得 Run ID:
|
|
16
16
|
|
|
17
17
|
```sh
|
|
18
|
-
|
|
18
|
+
pnpm exec niceeval view --run <run-id> \
|
|
19
19
|
--out ./report-site \
|
|
20
20
|
--no-open
|
|
21
21
|
```
|
|
@@ -47,14 +47,14 @@ Analysis 的 `partial`、`empty`、`unsupported` 与 `failed` 是可显示的数
|
|
|
47
47
|
|
|
48
48
|
```sh
|
|
49
49
|
# 成功时写入全新目录
|
|
50
|
-
|
|
50
|
+
pnpm exec niceeval view --run <run-id> --out ./report-site-2026-08-15
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
## 在 CI 中生成
|
|
54
54
|
|
|
55
55
|
```sh
|
|
56
56
|
npx niceeval exp ci --json
|
|
57
|
-
|
|
57
|
+
pnpm exec niceeval view --experiment ci --out ./report-site --no-open
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
若 CI 必须发布刚完成的那次运行,读取第一条命令最后一行 receipt 的 `runIds`,并使用 `view --run <run-id>`。不要让托管平台读取源 Record;它只应部署生成目录。
|
|
@@ -47,7 +47,7 @@ npx niceeval exp checkout --json
|
|
|
47
47
|
`--json` 输出当前进程的 NDJSON。最后一条 receipt 包含 `invocationId`、`runIds`、开始时间、结束时间和 completion。外部自动化可以保留 receipt,再根据 `runIds` 选择要查看的 Report。
|
|
48
48
|
|
|
49
49
|
```sh
|
|
50
|
-
|
|
50
|
+
pnpm exec niceeval show --run 01J9ZK3M6P4T7V9X2C5N8QW0RY
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
不要把 progress 或 diagnostic 行当作长期结果格式。它们服务当前 Invocation,完整业务事实属于停稳 Record。
|