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.
Files changed (174) hide show
  1. package/docs-site/zh/concepts/adapter.mdx +6 -6
  2. package/docs-site/zh/concepts/experiment.mdx +7 -7
  3. package/docs-site/zh/concepts/overview.mdx +1 -1
  4. package/docs-site/zh/concepts/tier.mdx +6 -6
  5. package/docs-site/zh/guides/agent-feedback-loop.mdx +64 -21
  6. package/docs-site/zh/guides/connect-your-agent.mdx +7 -7
  7. package/docs-site/zh/guides/custom-reports.mdx +243 -0
  8. package/docs-site/zh/guides/experiments.mdx +3 -3
  9. package/docs-site/zh/guides/report-components.mdx +252 -0
  10. package/docs-site/zh/guides/reporters.mdx +1 -1
  11. package/docs-site/zh/guides/results-data.mdx +224 -0
  12. package/docs-site/zh/guides/runner.mdx +1 -1
  13. package/docs-site/zh/guides/sandbox-agent.mdx +2 -2
  14. package/docs-site/zh/guides/viewing-results.mdx +147 -77
  15. package/docs-site/zh/guides/write-experiment.mdx +9 -9
  16. package/docs-site/zh/guides/write-send.mdx +6 -6
  17. package/docs-site/zh/index.mdx +1 -1
  18. package/docs-site/zh/introduction.mdx +1 -1
  19. package/docs-site/zh/reference/cli.mdx +11 -3
  20. package/docs-site/zh/reference/define-agent.mdx +5 -5
  21. package/docs-site/zh/reference/define-config.mdx +1 -1
  22. package/docs-site/zh/reference/define-eval.mdx +3 -3
  23. package/package.json +3 -2
  24. package/src/agents/ai-sdk.test.ts +1 -1
  25. package/src/agents/ai-sdk.ts +2 -2
  26. package/src/agents/claude-code.ts +1 -1
  27. package/src/agents/codex.ts +2 -2
  28. package/src/agents/streaming.test.ts +1 -1
  29. package/src/agents/types.ts +4 -4
  30. package/src/agents/ui-message-stream.test.ts +1 -1
  31. package/src/cli.ts +120 -18
  32. package/src/context/context.test.ts +1 -1
  33. package/src/context/context.ts +3 -3
  34. package/src/context/session.ts +2 -2
  35. package/src/context/types.ts +2 -2
  36. package/src/i18n/en.ts +29 -7
  37. package/src/i18n/zh-CN.ts +24 -2
  38. package/src/report/aggregate.ts +79 -50
  39. package/src/report/components.tsx +190 -0
  40. package/src/report/compute.ts +149 -84
  41. package/src/report/default-report.tsx +222 -0
  42. package/src/report/dual-face.test.tsx +527 -0
  43. package/src/report/format.ts +29 -0
  44. package/src/report/index.ts +79 -24
  45. package/src/report/load.ts +67 -0
  46. package/src/report/metrics.ts +2 -1
  47. package/src/report/param.ts +18 -0
  48. package/src/report/primitives.tsx +117 -0
  49. package/src/report/react/CaseList.tsx +2 -2
  50. package/src/report/react/DeltaTable.tsx +2 -2
  51. package/src/report/react/MetricBars.tsx +109 -0
  52. package/src/report/react/MetricLine.tsx +200 -0
  53. package/src/report/react/MetricMatrix.tsx +1 -1
  54. package/src/report/react/MetricScatter.tsx +1 -1
  55. package/src/report/react/MetricTable.tsx +1 -1
  56. package/src/report/react/RunOverview.tsx +4 -4
  57. package/src/report/react/Scoreboard.tsx +3 -3
  58. package/src/report/react/cell.tsx +1 -1
  59. package/src/report/react/fixtures.ts +98 -36
  60. package/src/report/react/format.ts +3 -28
  61. package/src/report/react/index.tsx +41 -24
  62. package/src/report/react/render.test.tsx +8 -8
  63. package/src/report/react/styles.css +77 -0
  64. package/src/report/report.test.ts +248 -128
  65. package/src/report/report.ts +69 -0
  66. package/src/report/text/faces.ts +356 -0
  67. package/src/report/text/layout.ts +125 -0
  68. package/src/report/text/plot.ts +127 -0
  69. package/src/report/tree.ts +220 -0
  70. package/src/report/types.ts +75 -27
  71. package/src/report/web.ts +40 -0
  72. package/src/results/copy.ts +95 -41
  73. package/src/results/format.ts +12 -11
  74. package/src/results/index.ts +34 -17
  75. package/src/results/open.ts +201 -81
  76. package/src/results/results.test.ts +595 -191
  77. package/src/results/select.ts +107 -55
  78. package/src/results/types.ts +137 -45
  79. package/src/results/writer.ts +258 -0
  80. package/src/runner/attempt.ts +3 -3
  81. package/src/runner/fingerprint.ts +1 -1
  82. package/src/runner/reporters/artifacts.ts +38 -78
  83. package/src/runner/reporters/braintrust.test.ts +2 -2
  84. package/src/runner/reporters/braintrust.ts +3 -3
  85. package/src/runner/run.ts +1 -1
  86. package/src/runner/types.ts +18 -12
  87. package/src/show/compose.ts +215 -0
  88. package/src/show/index.ts +263 -0
  89. package/src/show/render.ts +456 -0
  90. package/src/show/show.test.ts +505 -0
  91. package/src/view/app/App.tsx +85 -24
  92. package/src/view/app/components/CostScoreChart.tsx +29 -10
  93. package/src/view/app/components/ExperimentTable.tsx +27 -9
  94. package/src/view/app/components/GroupSelector.tsx +1 -1
  95. package/src/view/app/i18n.ts +18 -3
  96. package/src/view/app/lib/attempt-route.test.ts +9 -9
  97. package/src/view/app/lib/attempt-route.ts +5 -5
  98. package/src/view/app/lib/outcome.ts +1 -3
  99. package/src/view/app/lib/rows.ts +95 -15
  100. package/src/view/app/main.tsx +18 -6
  101. package/src/view/app/pages/RunsPage.tsx +4 -7
  102. package/src/view/app/pages/TracesPage.tsx +3 -8
  103. package/src/view/app/types.ts +50 -6
  104. package/src/view/client-dist/app.css +1 -1
  105. package/src/view/client-dist/app.js +20 -20
  106. package/src/view/data.test.ts +254 -0
  107. package/src/view/data.ts +336 -0
  108. package/src/view/index.ts +64 -10
  109. package/src/view/server.ts +31 -9
  110. package/src/view/shared/types.ts +47 -41
  111. package/src/view/styles.css +5 -0
  112. package/src/view/template.html +1 -0
  113. package/src/view/view-report.test.ts +308 -0
  114. package/docs-site/.mintignore +0 -13
  115. package/docs-site/AGENTS.md +0 -46
  116. package/docs-site/concepts/adapter.mdx +0 -287
  117. package/docs-site/concepts/assert.mdx +0 -243
  118. package/docs-site/concepts/drive.mdx +0 -118
  119. package/docs-site/concepts/evals.mdx +0 -108
  120. package/docs-site/concepts/experiment.mdx +0 -37
  121. package/docs-site/concepts/hitl.mdx +0 -83
  122. package/docs-site/concepts/judge.mdx +0 -129
  123. package/docs-site/concepts/overview.mdx +0 -98
  124. package/docs-site/concepts/tier.mdx +0 -42
  125. package/docs-site/docs-ref/00-index.md +0 -23
  126. package/docs-site/docs-ref/01-page-types.md +0 -43
  127. package/docs-site/docs-ref/03-style-rules.md +0 -45
  128. package/docs-site/docs-ref/04-code-examples.md +0 -37
  129. package/docs-site/docs-ref/05-dx-failure-paths.md +0 -45
  130. package/docs-site/docs-ref/06-checklists.md +0 -53
  131. package/docs-site/docs.json +0 -256
  132. package/docs-site/example/ai-agent-application.mdx +0 -148
  133. package/docs-site/example/claude-code-codex-plugin.mdx +0 -162
  134. package/docs-site/example/claude-code-codex-skill.mdx +0 -147
  135. package/docs-site/example/showcase.mdx +0 -39
  136. package/docs-site/example/tier1-ai-sdk-v7.mdx +0 -136
  137. package/docs-site/example/tier1-claude-sdk.mdx +0 -119
  138. package/docs-site/example/tier1-codex-sdk.mdx +0 -111
  139. package/docs-site/example/tier1-langgraph.mdx +0 -119
  140. package/docs-site/example/tier1-pi-sdk.mdx +0 -119
  141. package/docs-site/favicon.svg +0 -5
  142. package/docs-site/github-diff.css +0 -135
  143. package/docs-site/github-diff.js +0 -11
  144. package/docs-site/guides/authoring.mdx +0 -129
  145. package/docs-site/guides/ci-integration.mdx +0 -97
  146. package/docs-site/guides/connect-otel.mdx +0 -209
  147. package/docs-site/guides/connect-your-agent.mdx +0 -221
  148. package/docs-site/guides/dataset-fanout.mdx +0 -98
  149. package/docs-site/guides/experiments.mdx +0 -71
  150. package/docs-site/guides/fixtures.mdx +0 -147
  151. package/docs-site/guides/reporters.mdx +0 -113
  152. package/docs-site/guides/runner.mdx +0 -79
  153. package/docs-site/guides/sandbox-agent.mdx +0 -138
  154. package/docs-site/guides/sandbox-backends.mdx +0 -64
  155. package/docs-site/guides/scoring-guide.mdx +0 -92
  156. package/docs-site/guides/viewing-results.mdx +0 -195
  157. package/docs-site/guides/write-experiment.mdx +0 -81
  158. package/docs-site/guides/write-send.mdx +0 -347
  159. package/docs-site/index.mdx +0 -181
  160. package/docs-site/introduction.mdx +0 -141
  161. package/docs-site/quickstart.mdx +0 -136
  162. package/docs-site/reference/builtin-agents.mdx +0 -161
  163. package/docs-site/reference/capabilities.mdx +0 -76
  164. package/docs-site/reference/cli.mdx +0 -120
  165. package/docs-site/reference/define-agent.mdx +0 -168
  166. package/docs-site/reference/define-config.mdx +0 -41
  167. package/docs-site/reference/define-eval.mdx +0 -160
  168. package/docs-site/reference/events.mdx +0 -131
  169. package/docs-site/reference/expect.mdx +0 -112
  170. package/docs-site/tracker.js +0 -8
  171. package/src/report/react/data.ts +0 -17
  172. package/src/view/aggregate.ts +0 -103
  173. package/src/view/loader.test.ts +0 -61
  174. 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.