niceeval 0.4.6 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs-site/zh/concepts/adapter.mdx +6 -6
- package/docs-site/zh/concepts/experiment.mdx +7 -7
- package/docs-site/zh/concepts/overview.mdx +1 -1
- package/docs-site/zh/concepts/tier.mdx +6 -6
- package/docs-site/zh/guides/agent-feedback-loop.mdx +64 -21
- package/docs-site/zh/guides/connect-your-agent.mdx +7 -7
- package/docs-site/zh/guides/custom-reports.mdx +243 -0
- package/docs-site/zh/guides/experiments.mdx +3 -3
- package/docs-site/zh/guides/report-components.mdx +252 -0
- package/docs-site/zh/guides/reporters.mdx +1 -1
- package/docs-site/zh/guides/results-data.mdx +224 -0
- package/docs-site/zh/guides/runner.mdx +1 -1
- package/docs-site/zh/guides/sandbox-agent.mdx +2 -2
- package/docs-site/zh/guides/viewing-results.mdx +147 -77
- package/docs-site/zh/guides/write-experiment.mdx +9 -9
- package/docs-site/zh/guides/write-send.mdx +6 -6
- package/docs-site/zh/index.mdx +1 -1
- package/docs-site/zh/introduction.mdx +1 -1
- package/docs-site/zh/reference/cli.mdx +11 -3
- package/docs-site/zh/reference/define-agent.mdx +5 -5
- package/docs-site/zh/reference/define-config.mdx +1 -1
- package/docs-site/zh/reference/define-eval.mdx +3 -3
- package/package.json +3 -2
- package/src/agents/ai-sdk.test.ts +1 -1
- package/src/agents/ai-sdk.ts +2 -2
- package/src/agents/claude-code.ts +1 -1
- package/src/agents/codex.ts +2 -2
- package/src/agents/streaming.test.ts +1 -1
- package/src/agents/types.ts +4 -4
- package/src/agents/ui-message-stream.test.ts +1 -1
- package/src/cli.ts +120 -18
- package/src/context/context.test.ts +1 -1
- package/src/context/context.ts +3 -3
- package/src/context/session.ts +2 -2
- package/src/context/types.ts +2 -2
- package/src/i18n/en.ts +29 -7
- package/src/i18n/zh-CN.ts +24 -2
- package/src/report/aggregate.ts +79 -50
- package/src/report/components.tsx +190 -0
- package/src/report/compute.ts +149 -84
- package/src/report/default-report.tsx +222 -0
- package/src/report/dual-face.test.tsx +527 -0
- package/src/report/format.ts +29 -0
- package/src/report/index.ts +79 -24
- package/src/report/load.ts +67 -0
- package/src/report/metrics.ts +2 -1
- package/src/report/param.ts +18 -0
- package/src/report/primitives.tsx +117 -0
- package/src/report/react/CaseList.tsx +2 -2
- package/src/report/react/DeltaTable.tsx +2 -2
- package/src/report/react/MetricBars.tsx +109 -0
- package/src/report/react/MetricLine.tsx +200 -0
- package/src/report/react/MetricMatrix.tsx +1 -1
- package/src/report/react/MetricScatter.tsx +1 -1
- package/src/report/react/MetricTable.tsx +1 -1
- package/src/report/react/RunOverview.tsx +4 -4
- package/src/report/react/Scoreboard.tsx +3 -3
- package/src/report/react/cell.tsx +1 -1
- package/src/report/react/fixtures.ts +98 -36
- package/src/report/react/format.ts +3 -28
- package/src/report/react/index.tsx +41 -24
- package/src/report/react/render.test.tsx +8 -8
- package/src/report/react/styles.css +77 -0
- package/src/report/report.test.ts +248 -128
- package/src/report/report.ts +69 -0
- package/src/report/text/faces.ts +356 -0
- package/src/report/text/layout.ts +125 -0
- package/src/report/text/plot.ts +127 -0
- package/src/report/tree.ts +220 -0
- package/src/report/types.ts +75 -27
- package/src/report/web.ts +40 -0
- package/src/results/copy.ts +95 -41
- package/src/results/format.ts +12 -11
- package/src/results/index.ts +34 -17
- package/src/results/open.ts +201 -81
- package/src/results/results.test.ts +595 -191
- package/src/results/select.ts +107 -55
- package/src/results/types.ts +137 -45
- package/src/results/writer.ts +258 -0
- package/src/runner/attempt.ts +3 -3
- package/src/runner/fingerprint.ts +1 -1
- package/src/runner/reporters/artifacts.ts +38 -78
- package/src/runner/reporters/braintrust.test.ts +2 -2
- package/src/runner/reporters/braintrust.ts +3 -3
- package/src/runner/run.ts +1 -1
- package/src/runner/types.ts +18 -12
- package/src/show/compose.ts +215 -0
- package/src/show/index.ts +263 -0
- package/src/show/render.ts +456 -0
- package/src/show/show.test.ts +505 -0
- package/src/view/app/App.tsx +85 -24
- package/src/view/app/components/CostScoreChart.tsx +29 -10
- package/src/view/app/components/ExperimentTable.tsx +27 -9
- package/src/view/app/components/GroupSelector.tsx +1 -1
- package/src/view/app/i18n.ts +18 -3
- package/src/view/app/lib/attempt-route.test.ts +9 -9
- package/src/view/app/lib/attempt-route.ts +5 -5
- package/src/view/app/lib/outcome.ts +1 -3
- package/src/view/app/lib/rows.ts +95 -15
- package/src/view/app/main.tsx +18 -6
- package/src/view/app/pages/RunsPage.tsx +4 -7
- package/src/view/app/pages/TracesPage.tsx +3 -8
- package/src/view/app/types.ts +50 -6
- package/src/view/client-dist/app.css +1 -1
- package/src/view/client-dist/app.js +20 -20
- package/src/view/data.test.ts +254 -0
- package/src/view/data.ts +336 -0
- package/src/view/index.ts +64 -10
- package/src/view/server.ts +31 -9
- package/src/view/shared/types.ts +47 -41
- package/src/view/styles.css +5 -0
- package/src/view/template.html +1 -0
- package/src/view/view-report.test.ts +308 -0
- package/docs-site/.mintignore +0 -13
- package/docs-site/AGENTS.md +0 -46
- package/docs-site/concepts/adapter.mdx +0 -287
- package/docs-site/concepts/assert.mdx +0 -243
- package/docs-site/concepts/drive.mdx +0 -118
- package/docs-site/concepts/evals.mdx +0 -108
- package/docs-site/concepts/experiment.mdx +0 -37
- package/docs-site/concepts/hitl.mdx +0 -83
- package/docs-site/concepts/judge.mdx +0 -129
- package/docs-site/concepts/overview.mdx +0 -98
- package/docs-site/concepts/tier.mdx +0 -42
- package/docs-site/docs-ref/00-index.md +0 -23
- package/docs-site/docs-ref/01-page-types.md +0 -43
- package/docs-site/docs-ref/03-style-rules.md +0 -45
- package/docs-site/docs-ref/04-code-examples.md +0 -37
- package/docs-site/docs-ref/05-dx-failure-paths.md +0 -45
- package/docs-site/docs-ref/06-checklists.md +0 -53
- package/docs-site/docs.json +0 -256
- package/docs-site/example/ai-agent-application.mdx +0 -148
- package/docs-site/example/claude-code-codex-plugin.mdx +0 -162
- package/docs-site/example/claude-code-codex-skill.mdx +0 -147
- package/docs-site/example/showcase.mdx +0 -39
- package/docs-site/example/tier1-ai-sdk-v7.mdx +0 -136
- package/docs-site/example/tier1-claude-sdk.mdx +0 -119
- package/docs-site/example/tier1-codex-sdk.mdx +0 -111
- package/docs-site/example/tier1-langgraph.mdx +0 -119
- package/docs-site/example/tier1-pi-sdk.mdx +0 -119
- package/docs-site/favicon.svg +0 -5
- package/docs-site/github-diff.css +0 -135
- package/docs-site/github-diff.js +0 -11
- package/docs-site/guides/authoring.mdx +0 -129
- package/docs-site/guides/ci-integration.mdx +0 -97
- package/docs-site/guides/connect-otel.mdx +0 -209
- package/docs-site/guides/connect-your-agent.mdx +0 -221
- package/docs-site/guides/dataset-fanout.mdx +0 -98
- package/docs-site/guides/experiments.mdx +0 -71
- package/docs-site/guides/fixtures.mdx +0 -147
- package/docs-site/guides/reporters.mdx +0 -113
- package/docs-site/guides/runner.mdx +0 -79
- package/docs-site/guides/sandbox-agent.mdx +0 -138
- package/docs-site/guides/sandbox-backends.mdx +0 -64
- package/docs-site/guides/scoring-guide.mdx +0 -92
- package/docs-site/guides/viewing-results.mdx +0 -195
- package/docs-site/guides/write-experiment.mdx +0 -81
- package/docs-site/guides/write-send.mdx +0 -347
- package/docs-site/index.mdx +0 -181
- package/docs-site/introduction.mdx +0 -141
- package/docs-site/quickstart.mdx +0 -136
- package/docs-site/reference/builtin-agents.mdx +0 -161
- package/docs-site/reference/capabilities.mdx +0 -76
- package/docs-site/reference/cli.mdx +0 -120
- package/docs-site/reference/define-agent.mdx +0 -168
- package/docs-site/reference/define-config.mdx +0 -41
- package/docs-site/reference/define-eval.mdx +0 -160
- package/docs-site/reference/events.mdx +0 -131
- package/docs-site/reference/expect.mdx +0 -112
- package/docs-site/tracker.js +0 -8
- package/src/report/react/data.ts +0 -17
- package/src/view/aggregate.ts +0 -103
- package/src/view/loader.test.ts +0 -61
- package/src/view/loader.ts +0 -257
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "How the NiceEval runner schedules and executes evals"
|
|
3
|
-
sidebarTitle: "Runner"
|
|
4
|
-
description: "The NiceEval runner discovers evals, schedules them with bounded concurrency, caches results, retries flaky infrastructure, and enforces budget guards."
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
The runner is the execution engine that turns eval files into an actual run. It handles discovery, filtering, scheduling, caching, attempts, reporters, and artifact output.
|
|
8
|
-
|
|
9
|
-
## Discovery
|
|
10
|
-
|
|
11
|
-
The runner reads from `evals/`:
|
|
12
|
-
|
|
13
|
-
- `*.eval.ts` files
|
|
14
|
-
- dataset files that export eval arrays
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
npx niceeval list
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
`list` only discovers and prints IDs. It does not execute evals.
|
|
21
|
-
|
|
22
|
-
## Filtering
|
|
23
|
-
|
|
24
|
-
In the `exp` command, positional arguments after the experiment name are eval ID prefixes:
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
npx niceeval exp local
|
|
28
|
-
npx niceeval exp local weather
|
|
29
|
-
npx niceeval exp local fixtures/button
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
Do not put the agent name into positional arguments. Agent, model, and flags belong in the experiment.
|
|
33
|
-
|
|
34
|
-
## Concurrency
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
npx niceeval exp local --max-concurrency 8
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
Remote HTTP agents can usually handle higher concurrency. Local Docker sandbox runs usually need lower concurrency to avoid CPU, memory, and disk contention.
|
|
41
|
-
|
|
42
|
-
## `runs` and `early-exit`
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
npx niceeval exp local fixtures/button --runs 5 --early-exit
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
`runs` is for pass-rate measurement. `early-exit` stops the remaining attempts for the same eval after one attempt passes.
|
|
49
|
-
|
|
50
|
-
## Cache
|
|
51
|
-
|
|
52
|
-
NiceEval can skip already-passing results based on a fingerprint of inputs, configuration, and relevant files. Cache is useful for iteration speed, but turn it off or clear it explicitly when you are debugging non-deterministic behavior.
|
|
53
|
-
|
|
54
|
-
## Timeout and budget
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
npx niceeval exp local --timeout-ms 300000 --budget 5
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
Timeout protects a single eval. Budget protects the cost of the entire run.
|
|
61
|
-
|
|
62
|
-
## Reporter
|
|
63
|
-
|
|
64
|
-
After each eval finishes, the runner hands the result to reporters:
|
|
65
|
-
|
|
66
|
-
- the console reporter provides live feedback
|
|
67
|
-
- JSON artifacts support later analysis
|
|
68
|
-
- the JUnit reporter fits CI
|
|
69
|
-
|
|
70
|
-
## Output directory
|
|
71
|
-
|
|
72
|
-
Each run writes to `.niceeval/<timestamp>/`, including `summary.json` and per-attempt artifacts such as `events.json`, `sources.json`, `trace.json`, `o11y.json`, and `diff.json`.
|
|
73
|
-
|
|
74
|
-
## Recommended debugging flow
|
|
75
|
-
|
|
76
|
-
1. Run `npx niceeval list` to confirm discovery.
|
|
77
|
-
2. Narrow to one eval with `npx niceeval exp <experiment> <id-prefix>`.
|
|
78
|
-
3. After a failure, run `npx niceeval view` to inspect transcript and diff.
|
|
79
|
-
4. Then widen back out to the full suite or experiment.
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Sandbox agents: evaluate Claude Code, Codex, and bub"
|
|
3
|
-
sidebarTitle: "Sandbox Agents"
|
|
4
|
-
description: "Use NiceEval built-in agents or a custom adapter to run coding-agent CLIs inside Docker or cloud sandboxes."
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
Sandbox agents start a coding-agent CLI inside an isolated environment, give it a workspace and a task, let it edit files and run commands, then collect transcript, diff, and test results.
|
|
8
|
-
|
|
9
|
-
## Built-in sandbox agents
|
|
10
|
-
|
|
11
|
-
<CardGroup cols={3}>
|
|
12
|
-
<Card title="claude-code" icon="code">
|
|
13
|
-
Runs the Anthropic Claude Code CLI. Requires `ANTHROPIC_API_KEY`.
|
|
14
|
-
</Card>
|
|
15
|
-
<Card title="codex" icon="terminal">
|
|
16
|
-
Runs the OpenAI Codex CLI. Requires `CODEX_API_KEY`.
|
|
17
|
-
</Card>
|
|
18
|
-
<Card title="bub" icon="robot">
|
|
19
|
-
Runs the bub coding agent. Authentication follows the bub CLI's own rules.
|
|
20
|
-
</Card>
|
|
21
|
-
</CardGroup>
|
|
22
|
-
|
|
23
|
-
## Run a built-in agent
|
|
24
|
-
|
|
25
|
-
Set `sandbox` in the experiment, or as a project-level fallback in `niceeval.config.ts`, to choose where NiceEval creates the isolated environment:
|
|
26
|
-
|
|
27
|
-
```ts
|
|
28
|
-
import { defineExperiment } from "niceeval";
|
|
29
|
-
import { claudeCodeAgent } from "niceeval/adapter";
|
|
30
|
-
import { dockerSandbox } from "niceeval/sandbox";
|
|
31
|
-
|
|
32
|
-
export default defineExperiment({
|
|
33
|
-
agent: claudeCodeAgent(),
|
|
34
|
-
model: "claude-sonnet-4-6",
|
|
35
|
-
sandbox: dockerSandbox(),
|
|
36
|
-
});
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
```sh
|
|
40
|
-
export ANTHROPIC_API_KEY=sk-ant-...
|
|
41
|
-
npx niceeval exp local fixtures/button
|
|
42
|
-
|
|
43
|
-
npx niceeval exp local fixtures/button --runs 10 --early-exit
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
<Note>
|
|
47
|
-
There is no CLI flag for choosing the backend. Backend selection lives entirely in code. If neither the experiment nor `niceeval.config.ts` sets `sandbox`, NiceEval fails when it tries to create the sandbox.
|
|
48
|
-
</Note>
|
|
49
|
-
|
|
50
|
-
The built-in agents exported from `niceeval/adapter` are factory functions. Put auth, proxy, MCP, or GitHub Skill setup in the factory arguments. Keep the model in the experiment's `model` field, and the sandbox backend in `sandbox`:
|
|
51
|
-
|
|
52
|
-
```ts
|
|
53
|
-
import { defineExperiment } from "niceeval";
|
|
54
|
-
import { claudeCodeAgent } from "niceeval/adapter";
|
|
55
|
-
import { dockerSandbox } from "niceeval/sandbox";
|
|
56
|
-
|
|
57
|
-
export default defineExperiment({
|
|
58
|
-
agent: claudeCodeAgent({
|
|
59
|
-
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
60
|
-
baseUrl: process.env.ANTHROPIC_BASE_URL,
|
|
61
|
-
maxTurns: 8,
|
|
62
|
-
mcpServers: [
|
|
63
|
-
{
|
|
64
|
-
name: "browser",
|
|
65
|
-
command: "npx",
|
|
66
|
-
args: ["-y", "@anthropic/mcp-browser"],
|
|
67
|
-
},
|
|
68
|
-
],
|
|
69
|
-
skills: ["Effect-TS/skills"],
|
|
70
|
-
}),
|
|
71
|
-
model: "claude-sonnet-4-6",
|
|
72
|
-
sandbox: dockerSandbox(),
|
|
73
|
-
});
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
## Agent environment variables
|
|
77
|
-
|
|
78
|
-
| Agent | Required variables |
|
|
79
|
-
|---|---|
|
|
80
|
-
| `claude-code` | `ANTHROPIC_API_KEY` |
|
|
81
|
-
| `codex` | `CODEX_API_KEY` |
|
|
82
|
-
| `bub` | whatever the bub CLI requires |
|
|
83
|
-
|
|
84
|
-
## Workflow
|
|
85
|
-
|
|
86
|
-
```text
|
|
87
|
-
createSandbox
|
|
88
|
-
-> git init && git commit
|
|
89
|
-
-> adapter.setup?
|
|
90
|
-
-> test(t): uploadDirectory(...)
|
|
91
|
-
-> adapter.send(input, ctx)
|
|
92
|
-
-> test(t): runCommand(...)
|
|
93
|
-
-> collectGeneratedFiles()
|
|
94
|
-
-> sandbox.stop()
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
The starting files and verification commands both live in `test(t)`. During agent execution, it can only see the files you already wrote into the sandbox.
|
|
98
|
-
|
|
99
|
-
## Custom sandbox agent
|
|
100
|
-
|
|
101
|
-
```ts
|
|
102
|
-
import { defineSandboxAgent } from "niceeval/adapter";
|
|
103
|
-
|
|
104
|
-
export default defineSandboxAgent({
|
|
105
|
-
name: "my-agent",
|
|
106
|
-
async send(input, ctx) {
|
|
107
|
-
await ctx.sandbox.runCommand("my-agent", ["run", input.text, "--json-out", "agent-events.json"]);
|
|
108
|
-
const transcript = await ctx.sandbox.readFile("agent-events.json");
|
|
109
|
-
return {
|
|
110
|
-
status: "completed",
|
|
111
|
-
events: parseTranscript(transcript),
|
|
112
|
-
};
|
|
113
|
-
},
|
|
114
|
-
});
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
## `ctx.model` and `ctx.flags`
|
|
118
|
-
|
|
119
|
-
The model and custom flags passed by the experiment appear in the adapter context. The adapter decides how to map them to CLI arguments or HTTP payloads.
|
|
120
|
-
|
|
121
|
-
## Use a custom agent in an experiment
|
|
122
|
-
|
|
123
|
-
```ts
|
|
124
|
-
import { defineExperiment } from "niceeval";
|
|
125
|
-
import { dockerSandbox } from "niceeval/sandbox";
|
|
126
|
-
import myAgent from "./agents/my-agent";
|
|
127
|
-
|
|
128
|
-
export default defineExperiment({
|
|
129
|
-
agent: myAgent,
|
|
130
|
-
model: "claude-sonnet-4-6",
|
|
131
|
-
sandbox: dockerSandbox(),
|
|
132
|
-
runs: 3,
|
|
133
|
-
});
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
<Warning>
|
|
137
|
-
Do not add agent-specific branches inside the runner. Put differing behavior in the adapter.
|
|
138
|
-
</Warning>
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Sandbox backends: Docker, Vercel, and third-party providers"
|
|
3
|
-
sidebarTitle: "Sandbox Backends"
|
|
4
|
-
description: "NiceEval runs coding agents inside Docker or Vercel sandboxes. Learn how to choose a backend, configure permissions, and improve performance with warm pools."
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
The sandbox backend is the infrastructure that creates and manages isolated runtime environments. NiceEval wraps all backends behind the same `Sandbox` interface, so adapters do not need to know whether the current backend is local Docker, a Vercel micro-VM, or a third-party provider.
|
|
8
|
-
|
|
9
|
-
## The `Sandbox` interface
|
|
10
|
-
|
|
11
|
-
Common adapter operations include:
|
|
12
|
-
|
|
13
|
-
| Method | Use |
|
|
14
|
-
|---|---|
|
|
15
|
-
| `runCommand(cmd, args)` | run a command |
|
|
16
|
-
| `runShell(script)` | run a shell script |
|
|
17
|
-
| `readFile(path)` | read a file |
|
|
18
|
-
| `writeFiles(files)` | write a batch of files |
|
|
19
|
-
| `uploadFiles(files)` | upload a workspace or test files |
|
|
20
|
-
| `workdir` | the backend's real working directory; omitted `cwd` / `targetDir` resolve here |
|
|
21
|
-
| `runCommand(..., { cwd })` | temporarily switch directory for one command; relative paths resolve from `workdir` |
|
|
22
|
-
| `stop()` | destroy the environment |
|
|
23
|
-
|
|
24
|
-
## Choose a backend
|
|
25
|
-
|
|
26
|
-
Backend selection only lives in code. There is no CLI flag, and NiceEval does not auto-detect a backend. Set the `sandbox` field in the experiment, or set it in `niceeval.config.ts` as a project-level fallback:
|
|
27
|
-
|
|
28
|
-
```ts
|
|
29
|
-
import { defineExperiment } from "niceeval";
|
|
30
|
-
import { dockerSandbox } from "niceeval/sandbox";
|
|
31
|
-
|
|
32
|
-
export default defineExperiment({
|
|
33
|
-
agent: myCodingAgent,
|
|
34
|
-
model: "claude-sonnet-4-6",
|
|
35
|
-
sandbox: dockerSandbox(), // or vercelSandbox() / e2bSandbox()
|
|
36
|
-
});
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
If neither the experiment nor `niceeval.config.ts` sets `sandbox`, NiceEval fails when it tries to create the environment instead of guessing one.
|
|
40
|
-
|
|
41
|
-
## Docker
|
|
42
|
-
|
|
43
|
-
Docker is good for local development and standard CI. It is simple, controllable, and has no cloud dependency. The tradeoff is limited machine resources, plus slower cold starts and dependency installs.
|
|
44
|
-
|
|
45
|
-
## Vercel Sandbox
|
|
46
|
-
|
|
47
|
-
Vercel Sandbox is good when you want cloud isolation, more resources, or a more stable environment. It requires the right token or OIDC setup.
|
|
48
|
-
|
|
49
|
-
## Third-party backends
|
|
50
|
-
|
|
51
|
-
Any provider that implements the `Sandbox` interface can be plugged in. Adapters still depend only on the interface, not on provider-specific APIs.
|
|
52
|
-
|
|
53
|
-
## Permissions and root
|
|
54
|
-
|
|
55
|
-
Different backends impose different constraints on root access, networking, the file system, and process lifecycle. When writing fixtures, keep host assumptions to a minimum. Put dependencies in `package.json` or fixture setup instead of depending on the machine outside the sandbox.
|
|
56
|
-
|
|
57
|
-
## Performance advice
|
|
58
|
-
|
|
59
|
-
- Keep fixture dependencies small.
|
|
60
|
-
- Use caching or warm-up mechanisms.
|
|
61
|
-
- Tune `sandboxConcurrency` so local Docker does not run out of resources.
|
|
62
|
-
- Split slow checks into required gates and optional soft checks.
|
|
63
|
-
|
|
64
|
-
Warm pools and reuse belong to the runner / scheduler layer. See [Runner](/guides/runner).
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Scoring guide: assertions, judge, and cost limits"
|
|
3
|
-
sidebarTitle: "Scoring Guide"
|
|
4
|
-
description: "Evaluate any NiceEval run with five scoring mechanisms: value assertions, scoped assertions, LLM-as-judge, test-as-scoring, and efficiency checks."
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
A good eval should decompose "did this succeed?" into signals you can explain. NiceEval lets you mix precise assertions, semantic judge checks, event-stream checks, and real tests.
|
|
8
|
-
|
|
9
|
-
## Choose the assertion type
|
|
10
|
-
|
|
11
|
-
| Goal | Recommended mechanism |
|
|
12
|
-
|---|---|
|
|
13
|
-
| Reply includes a fixed field | `includes` / `matches` |
|
|
14
|
-
| Structured JSON matches exactly | `equals` |
|
|
15
|
-
| A tool call happened | `t.calledTool` / `t.notCalledTool` |
|
|
16
|
-
| Output is semantically correct | `t.judge.*` |
|
|
17
|
-
| Code actually works | `t.check(await t.sandbox.runCommand("npm", ["test"]), commandSucceeded())` |
|
|
18
|
-
| Cost stays under control | `t.maxTokens` / `t.maxCost` |
|
|
19
|
-
|
|
20
|
-
## Value assertions
|
|
21
|
-
|
|
22
|
-
```ts
|
|
23
|
-
import { includes, equals, matches } from "niceeval/expect";
|
|
24
|
-
|
|
25
|
-
t.check(t.reply, includes("refund"));
|
|
26
|
-
t.check(turn.data, equals({ intent: "refund" }));
|
|
27
|
-
t.check(t.reply, matches(/order #\d+/));
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
Value assertions fit results that are precise, stable, and low ambiguity.
|
|
31
|
-
|
|
32
|
-
## Scoped assertions
|
|
33
|
-
|
|
34
|
-
```ts
|
|
35
|
-
t.succeeded();
|
|
36
|
-
t.calledTool("search");
|
|
37
|
-
t.usedNoTools();
|
|
38
|
-
t.sandbox.fileChanged("src/app.ts");
|
|
39
|
-
t.check(await t.sandbox.runCommand("npm", ["test"]), commandSucceeded());
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
These check facts about the run, usually from the standard event stream or sandbox artifacts.
|
|
43
|
-
|
|
44
|
-
## LLM-as-judge
|
|
45
|
-
|
|
46
|
-
```ts
|
|
47
|
-
t.judge.autoevals.factuality("Refunds are available within 30 days.", { on: t.reply }).atLeast(0.8);
|
|
48
|
-
t.judge.autoevals.closedQA("The answer is specific, polite, and does not invent policy.", { on: t.reply }).atLeast(0.75);
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
Judge checks are good for semantic quality. They are not a replacement for all deterministic assertions. Prefer exact checks when you can make them.
|
|
52
|
-
|
|
53
|
-
## Gate vs soft
|
|
54
|
-
|
|
55
|
-
```ts
|
|
56
|
-
t.check(t.reply, includes("refund").gate());
|
|
57
|
-
t.check(t.reply, includes("friendly tone").atLeast(0.7));
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
- `gate`: failure is a run failure
|
|
61
|
-
- `soft`: keep the score for comparison without turning it into a hard failure
|
|
62
|
-
|
|
63
|
-
## Use tests to score code tasks
|
|
64
|
-
|
|
65
|
-
Run project tests or short probe scripts inside `.eval.ts`:
|
|
66
|
-
|
|
67
|
-
```ts
|
|
68
|
-
import { commandSucceeded, includes } from "niceeval/expect";
|
|
69
|
-
|
|
70
|
-
const testResult = await t.sandbox.runCommand("npm", ["test"]);
|
|
71
|
-
t.check(testResult, commandSucceeded());
|
|
72
|
-
|
|
73
|
-
const src = await t.sandbox.readSourceFiles({ extensions: ["ts"] });
|
|
74
|
-
t.check(src.text(), includes(/z\.object\s*\(/));
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
## Cost and efficiency
|
|
78
|
-
|
|
79
|
-
```ts
|
|
80
|
-
t.maxTokens(25_000);
|
|
81
|
-
t.maxCost(0.1);
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
This is especially useful for coding agents and long-chain agents, where repeated retries or excessive tool use can hide quality problems.
|
|
85
|
-
|
|
86
|
-
## Practical advice
|
|
87
|
-
|
|
88
|
-
- Start with one or two gates to establish the minimum bar.
|
|
89
|
-
- Add soft scores to compare quality across variants.
|
|
90
|
-
- Use judge for complex semantics, but give it a clear rubric.
|
|
91
|
-
- For coding-agent results, prefer real tests when possible.
|
|
92
|
-
- Make failure messages explicit so reports are actionable.
|
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "View NiceEval results and debug agent behavior"
|
|
3
|
-
sidebarTitle: "Viewing Results"
|
|
4
|
-
description: "After every run, NiceEval writes structured artifacts into .niceeval/. Use npx niceeval view to inspect transcripts, diffs, event streams, and pass rates."
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
After every run, [NiceEval](https://niceeval.com/) writes structured results into `.niceeval/<timestamp>/`. The console gives immediate feedback. The viewer is for deeper failure analysis.
|
|
8
|
-
|
|
9
|
-
## Console output
|
|
10
|
-
|
|
11
|
-
```text
|
|
12
|
-
Discovered 3 evals
|
|
13
|
-
|
|
14
|
-
✓ classify (12ms)
|
|
15
|
-
✓ weather/brooklyn (456ms)
|
|
16
|
-
✗ api-validation (38s)
|
|
17
|
-
- gate: expected src/routes/users.ts to include .safeParse() [FAILED]
|
|
18
|
-
|
|
19
|
-
Results: 2 passed, 1 failed, 0 errored, 0 skipped
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
Each line includes the eval ID, outcome, and duration. Failures also show the assertion type and error message.
|
|
23
|
-
|
|
24
|
-
## `.niceeval/<timestamp>/`
|
|
25
|
-
|
|
26
|
-
Typical structure:
|
|
27
|
-
|
|
28
|
-
```text
|
|
29
|
-
.niceeval/
|
|
30
|
-
└─ 2025-01-15T14-23-00/
|
|
31
|
-
├─ summary.json
|
|
32
|
-
└─ artifacts/
|
|
33
|
-
└─ compare__web-agent__gpt-5.4__weather-tool__0/
|
|
34
|
-
├─ events.json
|
|
35
|
-
├─ sources.json
|
|
36
|
-
├─ trace.json
|
|
37
|
-
├─ o11y.json
|
|
38
|
-
└─ diff.json
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## `niceeval view`
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
npx niceeval view
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
This opens the local viewer and, by default, shows the most recent run. You can browse evals, inspect transcripts, read diffs, inspect the event stream, and review assertions. Nothing is uploaded to an external service.
|
|
48
|
-
|
|
49
|
-
<Tip>
|
|
50
|
-
Run `npx niceeval view` right after a failure to open the artifacts from the run you just made.
|
|
51
|
-
</Tip>
|
|
52
|
-
|
|
53
|
-
## Exporting and Static Hosting
|
|
54
|
-
|
|
55
|
-
There is one export mode for publishing results: `--out <dir>` exports the whole viewer site with everything the viewer can inspect. If you want a custom report shape, build one with the report primitives.
|
|
56
|
-
|
|
57
|
-
### Built-in Viewer Site: Static Hosting
|
|
58
|
-
|
|
59
|
-
```bash
|
|
60
|
-
npx niceeval view --out site
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
NiceEval writes `<dir>/index.html` and copies the artifacts the viewer reads (`sources.json`, `events.json`, `trace.json`) into `<dir>/artifact/`. Deploy the whole directory to any static host, such as Vercel, GitHub Pages, or `python3 -m http.server`; code views, transcripts, and trace waterfalls behave the same as local `niceeval view`.
|
|
64
|
-
|
|
65
|
-
`--out` only accepts a directory. There is no single-file export: code views, transcripts, and traces depend on artifact files, and a single HTML file cannot carry the full evidence. To share results, host the whole site and send the link.
|
|
66
|
-
|
|
67
|
-
Two limits:
|
|
68
|
-
|
|
69
|
-
- `diff.json` and `o11y.json` are not copied. The viewer does not read them, and diffs can reach hundreds of MB.
|
|
70
|
-
- Opening `index.html` directly with `file://` prevents the browser from fetching artifacts, so the code view will say source is unavailable. Use an HTTP server for local preview.
|
|
71
|
-
|
|
72
|
-
The simplest flow is to export on the machine that ran the eval and deploy the output directory directly. `.niceeval/` usually does not go into version control. If the build happens on another machine, such as CI or a hosting platform, use `copyRun` first to copy a slim snapshot into the repo, then export from that snapshot directory:
|
|
73
|
-
|
|
74
|
-
```typescript
|
|
75
|
-
// scripts/snapshot.ts -- run after evals finish, then commit the output.
|
|
76
|
-
import { openResults, latestPerExperiment, copyRun } from "niceeval/results";
|
|
77
|
-
|
|
78
|
-
const results = await openResults(".niceeval");
|
|
79
|
-
const { snapshots } = latestPerExperiment(results.snapshots);
|
|
80
|
-
await copyRun(snapshots, "site-data/run", {
|
|
81
|
-
artifacts: ["sources", "events", "trace"],
|
|
82
|
-
});
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
```bash
|
|
86
|
-
npx niceeval view --out site site-data/run # Build from the snapshot in CI.
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
`latestPerExperiment` chooses the latest snapshot per experiment, not the latest run overall. If one run only covered part of the experiment set, the other experiments still keep their previous results.
|
|
90
|
-
|
|
91
|
-
### Custom Report Page: Your Own View
|
|
92
|
-
|
|
93
|
-
The built-in viewer has a fixed leaderboard shape. For your own view, such as a scorecard, benchmark board, or quality x cost scatter plot, build it into your app with report primitives: `niceeval/results` reads results, `niceeval/report` computes data, and `niceeval/report/react` renders components.
|
|
94
|
-
|
|
95
|
-
There is a serializable boundary between compute and render. Compute functions such as `table()`, `scatter()`, and `overview()` read the file system and only run in Node, such as a build script, server, or CI. Components only accept computed JSON data, perform zero IO, and can render anywhere. That gives static publishing two shapes.
|
|
96
|
-
|
|
97
|
-
**Option 1: compute at build time and export a fully static page.** Build the page on a machine that can read the result data, such as Next.js RSC or any SSG. The output is ordinary static files:
|
|
98
|
-
|
|
99
|
-
```tsx
|
|
100
|
-
// app/evals/page.tsx
|
|
101
|
-
import { openResults, latestPerExperiment } from "niceeval/results";
|
|
102
|
-
import { table, passRate, costUSD } from "niceeval/report";
|
|
103
|
-
import { MetricTable } from "niceeval/report/react";
|
|
104
|
-
import "niceeval/report/react/styles.css";
|
|
105
|
-
|
|
106
|
-
export default async function EvalsPage() {
|
|
107
|
-
const results = await openResults(".niceeval");
|
|
108
|
-
const { snapshots } = latestPerExperiment(results.snapshots);
|
|
109
|
-
const data = await table(snapshots, {
|
|
110
|
-
rows: "agent",
|
|
111
|
-
columns: [passRate, costUSD],
|
|
112
|
-
sort: passRate,
|
|
113
|
-
});
|
|
114
|
-
return <MetricTable data={data} />;
|
|
115
|
-
}
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
**Option 2: write JSON in CI and render it from any frontend.** Compute where the results exist, then render wherever your page lives, such as a Vite SPA or an existing internal dashboard:
|
|
119
|
-
|
|
120
|
-
```typescript
|
|
121
|
-
// scripts/build-report-data.ts -- run in CI after evals finish.
|
|
122
|
-
import { writeFile } from "node:fs/promises";
|
|
123
|
-
import { openResults, latestPerExperiment } from "niceeval/results";
|
|
124
|
-
import { table, passRate, costUSD } from "niceeval/report";
|
|
125
|
-
|
|
126
|
-
const results = await openResults(".niceeval");
|
|
127
|
-
const { snapshots } = latestPerExperiment(results.snapshots);
|
|
128
|
-
await writeFile("public/report.json", JSON.stringify({
|
|
129
|
-
board: await table(snapshots, { rows: "agent", columns: [passRate, costUSD] }),
|
|
130
|
-
}));
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
```tsx
|
|
134
|
-
// Frontend: any React app.
|
|
135
|
-
import { MetricTable } from "niceeval/report/react";
|
|
136
|
-
|
|
137
|
-
const doc = await fetch("/report.json").then((r) => r.json());
|
|
138
|
-
|
|
139
|
-
<MetricTable data={doc.board} />;
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
The components are complete without hydration: sorting is precomputed on the data side, drill-downs are normal links, and expand/collapse uses `<details>`. Static exports do not need client-side JavaScript. Styles ship with the package (`niceeval/report/react/styles.css`); load your own CSS after it to override.
|
|
143
|
-
|
|
144
|
-
Your custom page owns the conclusion. You do not need to redraw every attempt transcript and trace yourself. Export the built-in viewer to a subpath, such as `npx niceeval view --out <site-dir>/evidence`, then generate deep links with the component `attemptHref`:
|
|
145
|
-
|
|
146
|
-
```tsx
|
|
147
|
-
<MetricTable
|
|
148
|
-
data={data}
|
|
149
|
-
attemptHref={(ref) => `/evidence/#/attempt/${encodeURIComponent(ref.run)}/${ref.result}`}
|
|
150
|
-
/>
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
## Artifact Reference
|
|
154
|
-
|
|
155
|
-
### `summary.json`
|
|
156
|
-
|
|
157
|
-
The full-run summary: run ID, pass / fail counts, duration, cost, and per-eval status.
|
|
158
|
-
|
|
159
|
-
### `events.json`
|
|
160
|
-
|
|
161
|
-
The standard event stream. It is the low-level fact source for tool calls, messages, commands, and errors.
|
|
162
|
-
|
|
163
|
-
### `diff.json`
|
|
164
|
-
|
|
165
|
-
The file diff produced by a sandbox eval.
|
|
166
|
-
|
|
167
|
-
### `sources.json`
|
|
168
|
-
|
|
169
|
-
Eval source locations and assertion locations, which let the viewer map failures back to code.
|
|
170
|
-
|
|
171
|
-
### `trace.json`
|
|
172
|
-
|
|
173
|
-
OTLP traces or normalized span data.
|
|
174
|
-
|
|
175
|
-
### `o11y.json`
|
|
176
|
-
|
|
177
|
-
Observation summaries such as tool calls, commands, usage, and cost.
|
|
178
|
-
|
|
179
|
-
## Outcome Meanings
|
|
180
|
-
|
|
181
|
-
<Tabs>
|
|
182
|
-
<Tab title="passed">All gates passed.</Tab>
|
|
183
|
-
<Tab title="failed">At least one gate failed, or a soft assertion missed its threshold under `--strict`.</Tab>
|
|
184
|
-
<Tab title="errored">The environment, timeout, adapter, or agent runtime failed.</Tab>
|
|
185
|
-
<Tab title="skipped">The eval was intentionally skipped.</Tab>
|
|
186
|
-
</Tabs>
|
|
187
|
-
|
|
188
|
-
Soft assertion scores are recorded in `assertions[].score`; outside `--strict`, they do not create another outcome.
|
|
189
|
-
|
|
190
|
-
## Debugging Advice
|
|
191
|
-
|
|
192
|
-
- Start with `summary.json` to find the failing assertion.
|
|
193
|
-
- Then inspect the transcript view to understand the agent's decisions.
|
|
194
|
-
- For coding-agent failures, inspect `diff.json` and command output.
|
|
195
|
-
- For tool-call problems, inspect `events.json`.
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Write experiments with defineExperiment"
|
|
3
|
-
sidebarTitle: "Write Experiments"
|
|
4
|
-
description: "Use experiments/ to select an agent, pass model and flags, and configure runs, budget, concurrency, and sandbox."
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
An experiment is a checked-in run configuration. It says which adapter, model, flags, run count, budget, and sandbox to use for the same set of evals. CLI positional arguments select eval ID prefixes; they do not temporarily change the agent or run configuration.
|
|
8
|
-
|
|
9
|
-
## Minimal experiment
|
|
10
|
-
|
|
11
|
-
```ts
|
|
12
|
-
// experiments/local.ts
|
|
13
|
-
import { defineExperiment } from "niceeval";
|
|
14
|
-
import { webAgent } from "../agents/web-agent.ts";
|
|
15
|
-
|
|
16
|
-
export default defineExperiment({
|
|
17
|
-
agent: webAgent({ baseUrl: "http://127.0.0.1:5188" }),
|
|
18
|
-
});
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
`agent` is an already configured agent instance. URL, auth, and protocol details normally go into the adapter factory.
|
|
22
|
-
|
|
23
|
-
## Pass model and flags
|
|
24
|
-
|
|
25
|
-
```ts
|
|
26
|
-
// experiments/concise.ts
|
|
27
|
-
import { defineExperiment } from "niceeval";
|
|
28
|
-
import { webAgent } from "../agents/web-agent.ts";
|
|
29
|
-
|
|
30
|
-
export default defineExperiment({
|
|
31
|
-
description: "concise prompt variant",
|
|
32
|
-
agent: webAgent({
|
|
33
|
-
baseUrl: "https://staging.example.com",
|
|
34
|
-
apiKey: process.env.STAGING_AGENT_API_KEY,
|
|
35
|
-
}),
|
|
36
|
-
model: "gpt-5.4",
|
|
37
|
-
flags: {
|
|
38
|
-
promptVariant: "concise",
|
|
39
|
-
webResearch: false,
|
|
40
|
-
},
|
|
41
|
-
runs: 3,
|
|
42
|
-
earlyExit: true,
|
|
43
|
-
budget: 5,
|
|
44
|
-
});
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
`model` reaches the adapter as `ctx.model`. `flags` reaches the adapter as `ctx.flags` and evals as `t.flags`. NiceEval passes both through without interpreting them.
|
|
48
|
-
|
|
49
|
-
## Organize a comparison
|
|
50
|
-
|
|
51
|
-
One experiment file is one configuration cell. To compare multiple models, agents, or flags, put several files under one experiment group:
|
|
52
|
-
|
|
53
|
-
```text
|
|
54
|
-
experiments/
|
|
55
|
-
prompt-variants/
|
|
56
|
-
baseline.ts
|
|
57
|
-
concise.ts
|
|
58
|
-
with-retrieval.ts
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
```bash
|
|
62
|
-
npx niceeval exp prompt-variants
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## Common fields
|
|
66
|
-
|
|
67
|
-
| Field | Purpose |
|
|
68
|
-
|---|---|
|
|
69
|
-
| `agent` | Select and configure the adapter |
|
|
70
|
-
| `model` | Single model name passed through `ctx.model` |
|
|
71
|
-
| `reasoningEffort` | Single reasoning effort level (e.g. `"high"`), passed through `ctx.reasoningEffort` and `t.reasoningEffort`, same ownership as `model` |
|
|
72
|
-
| `flags` | JSON object passed through `ctx.flags` and `t.flags` |
|
|
73
|
-
| `runs` | Maximum runs per eval and configuration |
|
|
74
|
-
| `earlyExit` | Stop repeated runs when one passes |
|
|
75
|
-
| `evals` | Restrict which evals this configuration runs |
|
|
76
|
-
| `timeoutMs` | Attempt timeout |
|
|
77
|
-
| `budget` | Budget limit for this configuration |
|
|
78
|
-
| `maxConcurrency` | Concurrency limit for this configuration |
|
|
79
|
-
| `sandbox` | Sandbox backend for sandbox agents, such as `dockerSandbox()` or `e2bSandbox()` |
|
|
80
|
-
|
|
81
|
-
See [Experiment Matrix](/guides/experiments) for comparison design.
|