niceeval 0.19.0 → 0.19.1-canary.102
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 -1
- package/dist/assertions/record/codec.cjs +19 -13
- package/dist/assertions/record/codec.cjs.map +1 -1
- package/dist/assertions/record/codec.d.cts +2 -0
- package/dist/assertions/record/codec.d.mts +2 -0
- package/dist/assertions/record/codec.d.ts +2 -0
- package/dist/assertions/record/codec.js +16 -14
- package/dist/inspection/assertion-projection.cjs +4 -1
- package/dist/inspection/assertion-projection.cjs.map +1 -1
- package/dist/inspection/cli/contribution.cjs +18 -14
- package/dist/inspection/cli/contribution.cjs.map +1 -1
- package/dist/inspection/cli/contribution.d.cts +7 -0
- package/dist/inspection/cli/contribution.d.mts +7 -0
- package/dist/inspection/cli/contribution.d.ts +7 -0
- package/dist/inspection/overview.cjs +28 -14
- package/dist/inspection/overview.cjs.map +1 -1
- package/dist/inspection/overview.d.cts +151 -18
- package/dist/inspection/overview.d.mts +151 -18
- package/dist/inspection/overview.d.ts +151 -18
- package/dist/inspection/overview.js +4 -2
- package/dist/inspection/project-result.d.cts +148 -148
- package/dist/inspection/project-result.d.mts +148 -148
- package/dist/inspection/project-result.d.ts +148 -148
- package/dist/inspection/protocol-values.cjs +1 -1
- package/dist/inspection/protocol-values.cjs.map +1 -1
- package/dist/inspection/protocol-values.d.cts +1 -1
- package/dist/inspection/protocol-values.d.mts +1 -1
- package/dist/inspection/protocol-values.d.ts +1 -1
- package/dist/inspection/protocol.d.cts +611 -479
- package/dist/inspection/protocol.d.mts +611 -479
- package/dist/inspection/protocol.d.ts +611 -479
- package/dist/inspection/public.cjs +3 -1
- package/dist/inspection/public.cjs.map +1 -1
- package/dist/inspection/public.d.cts +1 -0
- package/dist/inspection/public.d.mts +1 -0
- package/dist/inspection/public.d.ts +1 -0
- package/dist/inspection/public.js +18 -16
- package/dist/inspection/public.mjs +54 -52
- package/dist/inspection/results.cjs +11 -15
- package/dist/inspection/results.cjs.map +1 -1
- package/dist/inspection/results.d.cts +769 -324
- package/dist/inspection/results.d.mts +769 -324
- package/dist/inspection/results.d.ts +769 -324
- package/dist/inspection/results.js +4 -0
- package/dist/inspection/select.cjs +12 -72
- package/dist/inspection/select.cjs.map +1 -1
- package/dist/inspection/verdict.cjs +61 -0
- package/dist/inspection/verdict.cjs.map +1 -0
- package/dist/inspection/verdict.d.cts +3 -0
- package/dist/inspection/verdict.d.mts +3 -0
- package/dist/inspection/verdict.d.ts +3 -0
- package/dist/inspection/verdict.js +6 -0
- package/dist/inspection/verdict.js.map +1 -0
- package/dist/runner/discover.cjs +5 -4
- package/dist/runner/discover.cjs.map +1 -1
- package/dist/sandbox/index.cjs +4 -2
- package/dist/sandbox/index.cjs.map +1 -1
- package/dist/sandbox/index.d.cts +2 -0
- package/dist/sandbox/index.d.mts +2 -0
- package/dist/sandbox/index.d.ts +2 -0
- package/dist/sandbox/index.js +34 -32
- package/dist/sandbox/index.mjs +34 -32
- package/dist/sandbox/opensandbox/managed-process.cjs +224 -0
- package/dist/sandbox/opensandbox/managed-process.cjs.map +1 -0
- package/dist/sandbox/opensandbox/managed-process.d.cts +9 -0
- package/dist/sandbox/opensandbox/managed-process.d.mts +9 -0
- package/dist/sandbox/opensandbox/managed-process.d.ts +9 -0
- package/dist/sandbox/opensandbox/managed-process.js +6 -0
- package/dist/sandbox/opensandbox/managed-process.js.map +1 -0
- package/dist/sandbox/opensandbox/materialize.cjs +25 -0
- package/dist/sandbox/opensandbox/materialize.cjs.map +1 -0
- package/dist/sandbox/opensandbox/materialize.d.cts +4 -0
- package/dist/sandbox/opensandbox/materialize.d.mts +4 -0
- package/dist/sandbox/opensandbox/materialize.d.ts +4 -0
- package/dist/sandbox/opensandbox/materialize.js +6 -0
- package/dist/sandbox/opensandbox/materialize.js.map +1 -0
- package/dist/sandbox/opensandbox/process-bridge.cjs +89 -0
- package/dist/sandbox/opensandbox/process-bridge.cjs.map +1 -0
- package/dist/sandbox/opensandbox/process-bridge.d.cts +2 -0
- package/dist/sandbox/opensandbox/process-bridge.d.mts +2 -0
- package/dist/sandbox/opensandbox/process-bridge.d.ts +2 -0
- package/dist/sandbox/opensandbox/process-bridge.js +6 -0
- package/dist/sandbox/opensandbox/process-bridge.js.map +1 -0
- package/dist/sandbox/opensandbox/sandbox.cjs +253 -0
- package/dist/sandbox/opensandbox/sandbox.cjs.map +1 -0
- package/dist/sandbox/opensandbox/sandbox.d.cts +51 -0
- package/dist/sandbox/opensandbox/sandbox.d.mts +51 -0
- package/dist/sandbox/opensandbox/sandbox.d.ts +51 -0
- package/dist/sandbox/opensandbox/sandbox.js +6 -0
- package/dist/sandbox/opensandbox/sandbox.js.map +1 -0
- package/dist/sandbox/opensandbox.cjs +88 -0
- package/dist/sandbox/opensandbox.cjs.map +1 -0
- package/dist/sandbox/opensandbox.d.cts +17 -0
- package/dist/sandbox/opensandbox.d.mts +17 -0
- package/dist/sandbox/opensandbox.d.ts +17 -0
- package/dist/sandbox/opensandbox.js +6 -0
- package/dist/sandbox/opensandbox.js.map +1 -0
- package/dist/sandbox/runtime.cjs +1 -0
- package/dist/sandbox/runtime.cjs.map +1 -1
- package/dist/sandbox/runtime.d.cts +2 -0
- package/dist/sandbox/runtime.d.mts +2 -0
- package/dist/sandbox/runtime.d.ts +2 -0
- package/dist/sandbox/runtime.js +2 -0
- package/dist/sandbox/types.cjs.map +1 -1
- package/dist/sandbox/types.d.cts +1 -1
- package/dist/sandbox/types.d.mts +1 -1
- package/dist/sandbox/types.d.ts +1 -1
- package/dist/show/model.cjs +6 -5
- package/dist/show/model.cjs.map +1 -1
- package/dist/show/model.d.cts +1 -1
- package/dist/show/model.d.mts +1 -1
- package/dist/show/model.d.ts +1 -1
- package/dist/show/render.cjs +2 -2
- package/dist/show/render.cjs.map +1 -1
- package/dist/view/app-dist/.vite/manifest.json +2 -2
- package/dist/view/app-dist/assets/{index-CxrOUvHC.js → index-f9ZKc4km.js} +16 -16
- package/dist/view/app-dist/assets/{quality-cost-scatter-B6Aiss7x.js → quality-cost-scatter-C6lsrigr.js} +1 -1
- package/dist/view/app-dist/index.html +1 -1
- package/dist/view/function-runtime.mjs +126 -118
- package/dist/view/http-protocol.d.cts +1 -1
- package/dist/view/http-protocol.d.mts +1 -1
- package/dist/view/http-protocol.d.ts +1 -1
- package/dist/view/inspection-host.d.cts +625 -493
- package/dist/view/inspection-host.d.mts +625 -493
- package/dist/view/inspection-host.d.ts +625 -493
- package/docs-site/zh/explanation/evals.mdx +4 -0
- package/docs-site/zh/reference/cli.mdx +45 -4
- package/docs-site/zh/tutorials/compare-runs.mdx +1 -1
- package/docs-site/zh/tutorials/niceeval-taste.mdx +34 -1
- package/docs-site/zh/tutorials/sandbox-providers.mdx +35 -4
- package/docs-site/zh/tutorials/upgrade-0-19.mdx +1 -1
- package/docs-site/zh/tutorials/viewing-results.mdx +36 -3
- package/package.json +6 -1
|
@@ -52,6 +52,10 @@ npx niceeval exp local weather/brooklyn
|
|
|
52
52
|
|
|
53
53
|
ID 跟着目录结构走,稳定又好读。过滤按字符串前缀匹配:`terminal-swe-bench` 也会命中 `terminal-swe-bench-astropy-1`,不要求后一个字符是 `/`。
|
|
54
54
|
|
|
55
|
+
也可以用 `evals/weather/brooklyn/eval.ts` 声明同一个 ID。含 `eval.ts` 的目录是一道题的 case 目录,发现器在这里停止扫描子目录。子目录中的 `eval.ts`、`.eval.ts` 和 `.eval.tsx` 都作为资产保留,不会被导入为其它评估用例,因此可以直接放入完整的起始仓库。
|
|
56
|
+
|
|
57
|
+
普通 `.eval.ts` 文件旁边的子目录仍会被扫描。共享资产放在没有 `eval.ts` 入口的目录中,各道题使用兄弟 case 目录或兄弟 `.eval.ts` 文件。
|
|
58
|
+
|
|
55
59
|
## 生命周期
|
|
56
60
|
|
|
57
61
|
<Steps>
|
|
@@ -16,11 +16,11 @@ description: "用 query、show 和 view 读取运行记录。"
|
|
|
16
16
|
|
|
17
17
|
```sh
|
|
18
18
|
niceeval query discover
|
|
19
|
-
niceeval query explain [--record <file>] --request <file|->
|
|
20
|
-
niceeval query run [--record <file>] --request <file|->
|
|
19
|
+
niceeval query explain [--record <file>] (--request <file|-> | --request-json <document>)
|
|
20
|
+
niceeval query run [--record <file>] (--request <file|-> | --request-json <document>)
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
`query` 使用带版本号的 JSON 请求协议 `niceeval.query/
|
|
23
|
+
`query` 使用带版本号的 JSON 请求协议 `niceeval.query/v3`,每一种固定的读取问题叫一个 operation。成功的结果和协议里定义的失败,都会向 stdout 写出恰好一个 JSON 文档。参数无效时返回 failure 文档,退出码为 `2`。进程出错到无法生成文档时,错误只写到 stderr。
|
|
24
24
|
|
|
25
25
|
- `discover` 列出当前版本支持的 operation ID。它不读运行记录,所以不接受 `--record`,也不返回请求的字段结构。
|
|
26
26
|
- `explain` 校验完整请求,说明它会运行哪个 operation,以及接下来可以发哪些请求。
|
|
@@ -30,6 +30,46 @@ niceeval query run [--record <file>] --request <file|->
|
|
|
30
30
|
|
|
31
31
|
结果分页时会带一个续读 token。这个 token 记住了 operation、请求内容、读取的记录文件和这次读取的可见边界。任何一项变了,`query` 都不会接着读,而是返回 restart correction,表示调用方要从 `discover` 或重新发请求开始。
|
|
32
32
|
|
|
33
|
+
### 常用 operation 的请求与结果字段
|
|
34
|
+
|
|
35
|
+
下面只列读取运行结果时常用的字段。请求顶层必须包含 `protocol: "niceeval.query/v3"` 和 `operation`,表中的参数放在 `operation` 内,与 `kind` 并列。成功响应的顶层 `outcome` 为 `"success"`。
|
|
36
|
+
|
|
37
|
+
| `operation.kind` | 必填参数 | 关键结果字段(从响应顶层开始) |
|
|
38
|
+
| --- | --- | --- |
|
|
39
|
+
| `run.list` | 无 | `runs[]` 中的 `runId`、`experimentId`、`state`、`startedAt`、`invocationId`、`coverage` |
|
|
40
|
+
| `run.get` | `runId`:Run ID | `run.plannedAttempts[]` 中的 `evalId`、`outcome`、`verdict`、`publication.action`、`publication.attemptLocator` |
|
|
41
|
+
| `experiment.get` | `experimentId`:实验 ID | `experiment.cells[]` 中的 `evalId`,以及 `members[]` 中的 `verdict`、`publication.attemptLocator`、`publication.action` |
|
|
42
|
+
| `attempt.get` | `locator`:包含 `@` 的 Attempt 定位符 | `attempt.verdict`、`attempt.core.evalId`、`attempt.originRun.experimentId` |
|
|
43
|
+
|
|
44
|
+
`run.get` 读取指定 Run 的计划与发布结果,`experiment.get` 读取每条评估用例当前采用的结果。局部重跑后,实验当前结果可以包含不同 Run 的 Attempt。发布结果的 `action` 为 `executed`、`carried` 或 `accepted`,分别表示本次执行、沿用已有结果或显式采用结果。
|
|
45
|
+
|
|
46
|
+
`run.plannedAttempts[]` 与 `experiment.cells[].members[]` 使用相同成员字段。`verdict`、`score`、`costUSD`、`durationMs` 和 `tokens` 与 `publication` 同级;未发布时,判定为 `null`,指标为 unavailable。
|
|
47
|
+
|
|
48
|
+
`publication` 只描述发布绑定。先检查 `publication.state` 是否为 `published`,再从 `publication.attemptLocator` 读取 Attempt 定位符。
|
|
49
|
+
|
|
50
|
+
用 `--request -` 从标准输入传入完整请求:
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
pnpm --silent exec niceeval query run --request - <<'JSON'
|
|
54
|
+
{
|
|
55
|
+
"protocol": "niceeval.query/v3",
|
|
56
|
+
"operation": { "kind": "run.list" }
|
|
57
|
+
}
|
|
58
|
+
JSON
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
不能写标准输入的调用方可以把完整请求作为一个 argv 值传入:
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
niceeval query run --request-json '{"protocol":"niceeval.query/v3","operation":{"kind":"run.list"}}'
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
两种传输使用同一套校验,不接受 operation 简写或部分字段。缺少传输选项,或同时传入两种选项,均为用法错误。
|
|
68
|
+
|
|
69
|
+
响应的 `runs[]` 会列出 Run ID。读取其中一个 Run 时,把请求的 `operation` 换为 `{ "kind": "run.get", "runId": "<run-id>" }`。请求必须通过 `--request <file|->` 或 `--request-json <document>` 传入,恰好选择一种。
|
|
70
|
+
|
|
71
|
+
选择的 Run、实验或 Attempt 不存在时,响应顶层为 `outcome: "failure"`,`failure.code` 为 `"inspection-selection-missing"`,退出码为 `2`。这表示选择对象缺失,不是评估判定为 `failed`;先用 `run.list` 核对 ID,并确认读取的是对应项目的运行记录。
|
|
72
|
+
|
|
33
73
|
## `niceeval show`
|
|
34
74
|
|
|
35
75
|
```sh
|
|
@@ -140,7 +180,8 @@ niceeval view [--run <run-id>...] [--no-open] [--port <port>] [--json]
|
|
|
140
180
|
| `--dry` | `niceeval accept` | boolean | 完成整 Run 采用预检,但不发布新 Run。 |
|
|
141
181
|
| `--all` | `niceeval invocation` | boolean | 包含已经完成的 Invocation 状态条目。 |
|
|
142
182
|
| `--json` | `niceeval invocation` | boolean | 写出该命令的机器文档或事件流。 |
|
|
143
|
-
| `--request` | `niceeval query` | string | 从文件或标准输入读取一个 niceeval.query/
|
|
183
|
+
| `--request` | `niceeval query` | string | 从文件或标准输入读取一个 niceeval.query/v3 request。 |
|
|
184
|
+
| `--request-json` | `niceeval query` | string | 从一个 argv 值读取完整的 niceeval.query/v3 request。 |
|
|
144
185
|
| `--record` | `niceeval query`、`niceeval show` | string | 读取一个外部 canonical SQLite Record。 |
|
|
145
186
|
| `--help` | `niceeval query` | boolean | 打印该命令的帮助。 |
|
|
146
187
|
| `--json` | `niceeval show` | boolean | 写出该命令的机器文档或事件流。 |
|
|
@@ -124,7 +124,40 @@ export default defineScoreEval({
|
|
|
124
124
|
|
|
125
125
|
给 Judge 的材料要够回答问题。传入 `toolMatch` 时只会选中工具调用;问题还涉及用户要求和回复时,就要传包含它们的完整历史。
|
|
126
126
|
|
|
127
|
-
|
|
127
|
+
评质量时不要先筛掉失败的调用、拒绝或澄清,它们本身就是表现的一部分。
|
|
128
|
+
|
|
129
|
+
完整历史有采集上限,所有 Adapter 都受此限制:单项消息、工具输入或工具输出的文本最多保留 16,384 字节。超限时,`show --execution` 的 Conversation 显示 `partial`,限制原因包含 `text-truncated`。Adapter 声明事件、消息或工具调用不完整时,完整历史也会是 `partial`。
|
|
130
|
+
|
|
131
|
+
这时 `closeQA(问题)` 的材料会显示 `partial / provider-limited`,检查为 `unavailable / source-unavailable`;这里的 `provider-limited` 不一定来自 Adapter。该检查若参与计分,计分制 Attempt 会是 `errored`。用 `query` 读取断言详情可查看原因,步骤见[查看结果](/zh/tutorials/viewing-results#看一条断言具体为什么得这个分)。
|
|
132
|
+
|
|
133
|
+
问题只需要任务、命令输入与回复时,可以把这些事实显式交给 `t.judge`。下面的例子需要项目已配置 Judge;它检查命令调用与完成说明是否符合任务,不评价文件正文是否正确:
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
import { defineScoreEval } from "niceeval";
|
|
137
|
+
import { defineJudge } from "niceeval/expect";
|
|
138
|
+
|
|
139
|
+
const judge = defineJudge({
|
|
140
|
+
name: "command-and-reply",
|
|
141
|
+
rubric: "命令输入符合任务,调用状态为 completed,回复准确说明完成了什么。",
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
export default defineScoreEval({
|
|
145
|
+
description: "检查命令与完成说明",
|
|
146
|
+
async test(t) {
|
|
147
|
+
const task = "运行 pwd,并说明当前目录。";
|
|
148
|
+
const turn = await t.send(task);
|
|
149
|
+
await t.judge({
|
|
150
|
+
task,
|
|
151
|
+
commands: turn.toolCalls.map(({ name, input, status }) => ({
|
|
152
|
+
name, input, status,
|
|
153
|
+
})),
|
|
154
|
+
reply: turn.reply,
|
|
155
|
+
}, judge).score(1);
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
显式材料也有大小上限。材料不足或超限时保留不可判定;不要省略判据需要的工具输出,也不要用这段投影掩盖 Adapter 未采集到的调用。
|
|
128
161
|
|
|
129
162
|
多轮任务里,先想清楚每项要求属于哪一轮、哪个 Session。要检查工具调用顺序,用 `inOrder`,见 [Match 参考](/zh/reference/expect)。注意,先后发生不等于后一个调用用到了前一个的结果;要证明数据依赖,还要检查输入和输出。
|
|
130
163
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "选择并配置 Sandbox
|
|
2
|
+
title: "选择并配置 Sandbox Provider"
|
|
3
3
|
sidebarTitle: "Sandbox"
|
|
4
4
|
description: "给 Coding Agent 选一个隔离运行环境:本地 Docker、Vercel 或 E2B。按顺序准备环境,并用预制镜像和缓存让每次评估更快开始。"
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
Coding Agent 要在一个能随意改文件、跑命令的环境里工作,而且不能碰到你的机器。这个隔离环境就是 Sandbox,由 Provider 负责创建和销毁。
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
本地调试可以用 Docker;需要云端环境时可以用 Vercel 或 E2B;已有 OpenSandbox 服务时可以直接连接服务 API。
|
|
10
10
|
|
|
11
11
|
不管用哪种 Provider,评估用例和 Adapter 看到的都是同一个 `Sandbox` 接口。换 Provider 只改 Experiment 里的一行,评估用例不用动。
|
|
12
12
|
|
|
@@ -19,6 +19,7 @@ NiceEval 提供三种官方 Provider:本地 Docker、Vercel 和 E2B。本地
|
|
|
19
19
|
| Docker | 本地开发和标准 CI。简单、可控,不依赖云端 | 本机 Docker。机器资源有限,冷启动和装依赖可能较慢 |
|
|
20
20
|
| Vercel Sandbox | 需要云端隔离、更多资源或更稳定的环境 | Vercel token 或 OIDC 配置 |
|
|
21
21
|
| E2B | 需要大量并行,或者想直接用现成的 Agent template | E2B 账号和 `e2b auth login` |
|
|
22
|
+
| OpenSandbox | 通过已有服务管理远端容器 | OpenSandbox 服务入口、API key 和镜像 |
|
|
22
23
|
|
|
23
24
|
在 Experiment 的 `sandbox` 字段里选一个:
|
|
24
25
|
|
|
@@ -36,16 +37,44 @@ export default defineExperiment({
|
|
|
36
37
|
|
|
37
38
|
评估用例和 Experiment 都没有选择 Sandbox 时,运行会在创建任何 Sandbox 之前报错,NiceEval 不会替你猜一个 Provider。
|
|
38
39
|
|
|
39
|
-
|
|
40
|
+
Provider 的 SDK 不随 NiceEval 一起安装。用哪个就装哪个,用不到的依赖(以及它们的原生构建脚本)不会进入你的项目:
|
|
40
41
|
|
|
41
42
|
| Provider | 安装命令 |
|
|
42
43
|
|---|---|
|
|
43
44
|
| `dockerSandbox({ source: { type: "image", image: "node:24-slim" } })` | `pnpm add dockerode @types/dockerode` |
|
|
44
45
|
| `vercelSandbox({ snapshotId })` | `pnpm add @vercel/sandbox` |
|
|
45
46
|
| `e2bSandbox({ template })` | `pnpm add e2b` |
|
|
47
|
+
| `openSandbox({ image, targetPlatform, lifetimeMs })` | `pnpm add @alibaba-group/opensandbox` |
|
|
46
48
|
|
|
47
49
|
漏装时,创建 Sandbox 的那一刻会报错并给出安装命令,例如 `Docker sandbox requires 'dockerode'. Install it with: pnpm add dockerode @types/dockerode`。照着装好再运行即可。
|
|
48
50
|
|
|
51
|
+
### 连接 OpenSandbox
|
|
52
|
+
|
|
53
|
+
服务与 execd 使用配套的 `release-1.1.1`,SDK 使用 `1.1.1`。旧 `execd:v1.1.0` 不支持此 Provider 所需的原生 argv。
|
|
54
|
+
|
|
55
|
+
在运行 NiceEval 的机器上配置 `OPEN_SANDBOX_DOMAIN` 和 `OPEN_SANDBOX_API_KEY`。地址是完整的 HTTPS URL;本机开发可使用 HTTP。凭据只用于宿主连接,不写入 Sandbox。
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import { openSandbox } from "niceeval/sandbox";
|
|
59
|
+
|
|
60
|
+
const sandbox = openSandbox({
|
|
61
|
+
image: "node:24-bookworm",
|
|
62
|
+
targetPlatform: { _tag: "Linux", os: "linux", arch: "x64", libc: "gnu" },
|
|
63
|
+
lifetimeMs: 60 * 60_000,
|
|
64
|
+
resources: { cpu: "1", memory: "2Gi" },
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
目标平台填写远端镜像的平台,正式实验将镜像固定到 digest。`lifetimeMs` 必须覆盖 Attempt 剩余时限并预留 30 秒收尾;正常完成会立即销毁实例。可用 `user` 选择执行身份,用 `pathPrepend` 添加可执行文件目录。
|
|
69
|
+
|
|
70
|
+
Docker、Kubernetes 等 runtime 由 OpenSandbox 服务端选择,NiceEval 无需填写。服务入口只允许可信宿主访问,或在所有 HTTP 和 WebSocket 路径前置鉴权。OpenSandbox 的 Docker proxy 路由不受控制 API key 保护,不能直接暴露到公网。
|
|
71
|
+
|
|
72
|
+
镜像必须以 root 启动 execd,并提供 Bash 和 Git;用 `user` 让 Agent 以非 root 身份执行。交互 Coding Agent 还需要 Node.js 24。
|
|
73
|
+
|
|
74
|
+
命令取消或超时会销毁整个实例。此 Provider 不支持保留现场、跨 Attempt 复用或准备缓存;运行中的 Sandbox 也不会自动获得 Docker daemon。
|
|
75
|
+
|
|
76
|
+
接入服务时,需要验证销毁成功响应代表实例及其进程已停止。仅受理异步删除的服务不能满足这项要求;填写 runtime 名称无法替代验证。
|
|
77
|
+
|
|
49
78
|
### Docker Compose:`workspaceService` 指定主 Sandbox
|
|
50
79
|
|
|
51
80
|
一道题需要不止一个容器时(比如应用容器加一个数据库),用 `dockerComposeSandbox` 声明整份 Compose 环境:
|
|
@@ -152,7 +181,7 @@ Experiment、评估组、评估用例和 Sandbox Agent 的准备步骤排进同
|
|
|
152
181
|
| 本地单容器 Docker,所有改动都在外层容器的可写文件系统里 | `all` | 从头开始最长的一段没变的步骤直接沿用 |
|
|
153
182
|
| Docker profile 配置了独立、预先分配好、固定大小的存储位和种子数据 | `dockerData` | 只沿用从头开始、连续声明了 `dockerData` 的那一段 |
|
|
154
183
|
| 共享 loop 或 project-quota 的 Docker profile | 无 | 显示 `Unsupported`,步骤真实执行 |
|
|
155
|
-
| Docker Compose、E2B、Vercel 或自定义 Provider | 无 | 显示 `Unsupported`,步骤真实执行 |
|
|
184
|
+
| Docker Compose、E2B、Vercel、OpenSandbox 或自定义 Provider | 无 | 显示 `Unsupported`,步骤真实执行 |
|
|
156
185
|
|
|
157
186
|
沿用只能从第一步开始连续往下。遇到第一个无法保存的步骤,比如默认 `all` 但 Provider 不支持、写了 `opaque` 的回调,或者 Provider 不支持的范围,这一步和它后面的所有步骤都会真实执行。后面的步骤即使声明了 `dockerData`,也不能跳过,因为它依赖的前面状态没有被保存。
|
|
158
187
|
|
|
@@ -264,6 +293,8 @@ e2bSandbox({ template: "my-evals" })
|
|
|
264
293
|
|
|
265
294
|
## 瞬时错误重试
|
|
266
295
|
|
|
296
|
+
OpenSandbox 创建请求不自动重试,因为连接中断时,服务可能已经分配了实例。以下创建重试适用于 Docker、Vercel 和 E2B。
|
|
297
|
+
|
|
267
298
|
内置 Provider 创建 Sandbox 时,遇到限流、`fetch failed`、连接重置、5xx、临时网络不可达这类临时失败,会自动按指数退避重试。模板不存在、凭据缺失这类配置错误第一次就报错。重试用完后,这个 Attempt 记为 `errored`。`defineSandbox` 自定义 Provider 的 `create` 是你自己的函数,NiceEval 不替它重试。
|
|
268
299
|
|
|
269
300
|
`readText`、`readBytes`、`downloadFile`、`uploadFile`、文件写入和目录上传,遇到 429、5xx、`fetch failed`、连接重置等临时传输错误时,会自动重试有限次。文件不存在、权限错误、取消和 Sandbox 已终止不重试。
|
|
@@ -72,7 +72,7 @@ t.check(t.usage.cacheRead.rate(), atLeast(ratio(0.6)));
|
|
|
72
72
|
## Planned attempt
|
|
73
73
|
|
|
74
74
|
Run 的计划执行位置现在称为 Planned attempt;已发布的执行事实仍称为 Attempt。
|
|
75
|
-
`query` 使用 `niceeval.query/
|
|
75
|
+
`query` 使用 `niceeval.query/v3`,`/inspection` decoder 不再接受 v1。
|
|
76
76
|
将 `slotId`、`expectedSlots` 和 `originSlotId` 分别替换为 `plannedAttemptId`、`plannedAttempts` 和 `originPlannedAttemptId`。
|
|
77
77
|
Run 和当前结果的 `slots` 集合改为 `plannedAttempts`。Show 完整度统计显示 Planned / Recorded / Missing attempts。
|
|
78
78
|
已有 Record 无需重写;持久字段在查询投影边界转换。
|
|
@@ -154,7 +154,7 @@ pnpm exec niceeval view --run <run-id>
|
|
|
154
154
|
```sh
|
|
155
155
|
pnpm --silent exec niceeval query run --request - <<'JSON'
|
|
156
156
|
{
|
|
157
|
-
"protocol": "niceeval.query/
|
|
157
|
+
"protocol": "niceeval.query/v3",
|
|
158
158
|
"operation": { "kind": "attempt.get", "locator": "@1K1P0VJAPVJ12" }
|
|
159
159
|
}
|
|
160
160
|
JSON
|
|
@@ -165,7 +165,7 @@ JSON
|
|
|
165
165
|
```sh
|
|
166
166
|
pnpm --silent exec niceeval query run --request - <<'JSON'
|
|
167
167
|
{
|
|
168
|
-
"protocol": "niceeval.query/
|
|
168
|
+
"protocol": "niceeval.query/v3",
|
|
169
169
|
"operation": {
|
|
170
170
|
"kind": "attempt.assertion.detail",
|
|
171
171
|
"locator": "@1K1P0VJAPVJ12",
|
|
@@ -187,6 +187,39 @@ pnpm --silent exec niceeval query discover
|
|
|
187
187
|
|
|
188
188
|
`discover` 列出当前版本支持的全部请求类型,例如列出 Run、读取 Run 摘要、读取 Attempt 详情、trace、diff,以及比较两个 Run。按[CLI 参考](/zh/reference/cli)写好请求后,先用 `query explain --request <file>` 检查,再用 `query run --request <file>` 执行。
|
|
189
189
|
|
|
190
|
-
|
|
190
|
+
### 本次运行的结果
|
|
191
|
+
|
|
192
|
+
下面的脚本需要 `jq`,在评估项目根目录执行。把 `my-agent` 换成你的实验 ID。`exp --json` 输出多行 JSON,最后一行的 `receipt.createdRunIds` 列出本次创建的 Run。先保存输出,再读取每个 Run:
|
|
193
|
+
|
|
194
|
+
```sh
|
|
195
|
+
pnpm --silent exec niceeval exp my-agent --json > exp.ndjson
|
|
196
|
+
|
|
197
|
+
tail -n 1 exp.ndjson | jq -r '.receipt.createdRunIds[]' |
|
|
198
|
+
while IFS= read -r run_id; do
|
|
199
|
+
jq -n --arg runId "$run_id" '{
|
|
200
|
+
protocol: "niceeval.query/v3",
|
|
201
|
+
operation: { kind: "run.get", runId: $runId }
|
|
202
|
+
}' | pnpm --silent exec niceeval query run --request -
|
|
203
|
+
done
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
每个响应的 `run.plannedAttempts[]` 给出这次 Run 中各条评估用例的判定与 Attempt 定位符。评估未通过时,`exp` 也可能写出 receipt 并返回非零退出码;CI 要先保留退出码并读取结果,再决定任务是否失败。没有 receipt 时,先检查命令错误,不要把空列表当成全部通过。
|
|
207
|
+
|
|
208
|
+
### 每条评估当前的结果
|
|
209
|
+
|
|
210
|
+
需要包含局部重跑后采用的结果时,用实验 ID 读取当前结果:
|
|
211
|
+
|
|
212
|
+
```sh
|
|
213
|
+
pnpm --silent exec niceeval query run --request - <<'JSON'
|
|
214
|
+
{
|
|
215
|
+
"protocol": "niceeval.query/v3",
|
|
216
|
+
"operation": { "kind": "experiment.get", "experimentId": "my-agent" }
|
|
217
|
+
}
|
|
218
|
+
JSON
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
响应的 `experiment.cells[]` 按评估用例列出结果;各次 Attempt 的判定在 `members[].verdict`,定位符在 `members[].publication.attemptLocator`。例如只重跑一条评估用例时,这里会把它的新结果与其它评估用例已采用的结果放在一起。
|
|
222
|
+
|
|
223
|
+
请求参数和字段位置见 [CLI 的常用 operation 表](/zh/reference/cli#常用-operation-的请求与结果字段)。在 pnpm 项目里加 `--silent`,避免 pnpm 自己的输出混进 JSON。
|
|
191
224
|
|
|
192
225
|
比较两次运行见[比较两次运行](/zh/tutorials/compare-runs)。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "niceeval",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.1-canary.102",
|
|
4
4
|
"description": "Agent-native eval tool — eval agents, services, functions, and coding-agent fixtures",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -223,6 +223,7 @@
|
|
|
223
223
|
"yaml": "^2.9.1"
|
|
224
224
|
},
|
|
225
225
|
"devDependencies": {
|
|
226
|
+
"@alibaba-group/opensandbox": "1.1.1",
|
|
226
227
|
"@ai-sdk/otel": "^1.0.114",
|
|
227
228
|
"@effect/platform-node": "4.0.0-rc.112",
|
|
228
229
|
"@effect/platform-node-shared": "4.0.0-rc.112",
|
|
@@ -266,6 +267,7 @@
|
|
|
266
267
|
"ws": "8.21.3"
|
|
267
268
|
},
|
|
268
269
|
"peerDependencies": {
|
|
270
|
+
"@alibaba-group/opensandbox": "^1.1.1",
|
|
269
271
|
"@ai-sdk/otel": ">=1.0.0",
|
|
270
272
|
"@opentelemetry/exporter-trace-otlp-http": ">=0.200.0",
|
|
271
273
|
"@opentelemetry/sdk-trace-node": ">=2.0.0",
|
|
@@ -276,6 +278,9 @@
|
|
|
276
278
|
"e2b": ">=2.0.0"
|
|
277
279
|
},
|
|
278
280
|
"peerDependenciesMeta": {
|
|
281
|
+
"@alibaba-group/opensandbox": {
|
|
282
|
+
"optional": true
|
|
283
|
+
},
|
|
279
284
|
"@ai-sdk/otel": {
|
|
280
285
|
"optional": true
|
|
281
286
|
},
|