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,168 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "defineAgent and defineSandboxAgent: adapter reference"
|
|
3
|
-
sidebarTitle: "defineAgent"
|
|
4
|
-
description: "Reference for defineAgent and defineSandboxAgent: AgentContext, AgentSession, the Sandbox interface, and shared sandbox helpers."
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
Every NiceEval agent is an adapter: code that knows how to drive a specific backend and translate its output into the standard event stream. The runner only calls `agent.send(input, ctx)`.
|
|
8
|
-
|
|
9
|
-

|
|
10
|
-
|
|
11
|
-
## `defineAgent`
|
|
12
|
-
|
|
13
|
-
Use this for direct agent integrations:
|
|
14
|
-
|
|
15
|
-
```ts
|
|
16
|
-
import { defineAgent } from "niceeval/adapter";
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
<ParamField body="name" type="string" required>
|
|
20
|
-
Unique agent name. Experiments reference the agent object, and reports group results by this name.
|
|
21
|
-
</ParamField>
|
|
22
|
-
|
|
23
|
-
<ParamField body="tracing" type="AgentTracing">
|
|
24
|
-
OTLP export configuration, used by CLI / child-process agents: declares how to hand the receiver endpoint to the process under test (`env` / `configure`). Long-running HTTP apps do not need this field — configure a fixed port with `telemetry: { port }` in `niceeval.config.ts` instead (see [OTel integration](/guides/connect-otel)). Spans only feed the `niceeval view` waterfall, never assertions.
|
|
25
|
-
</ParamField>
|
|
26
|
-
|
|
27
|
-
<ParamField body="spanMapper" type="(spans: TraceSpan[]) => TraceSpan[]">
|
|
28
|
-
Thin mapper from native spans to canonical GenAI semconv; it only affects semantic coloring in the waterfall. Omit it to fall back to the generic heuristic. For what maps to what in the waterfall and how to write your own (`tagSpan` / `heuristicTag`), see [OTel integration](/guides/connect-otel).
|
|
29
|
-
</ParamField>
|
|
30
|
-
|
|
31
|
-
<ParamField body="send" type="(input: TurnInput, ctx: AgentContext) => Promise<Turn>" required>
|
|
32
|
-
Core function that drives the agent. Must return a standard `Turn`.
|
|
33
|
-
</ParamField>
|
|
34
|
-
|
|
35
|
-
`Agent.kind` produced by `defineAgent` is always `"remote"` (an internal discriminant field you never declare). There are no capability bits on `t` that need declaring to unlock — filesystem assertions like `t.sandbox` exist only on agents constructed with `defineSandboxAgent` (`kind: "sandbox"`); everything else is judged by which events `send` actually returned and whether `ctx.session` was used. See the [capabilities reference](/reference/capabilities).
|
|
36
|
-
|
|
37
|
-
## `input` (`TurnInput`)
|
|
38
|
-
|
|
39
|
-
<ResponseField name="text" type="string">
|
|
40
|
-
Text passed by the current `t.send(...)`.
|
|
41
|
-
</ResponseField>
|
|
42
|
-
|
|
43
|
-
<ResponseField name="files" type="readonly InputFile[] | undefined">
|
|
44
|
-
Files attached to this turn (images, etc.). Adapters that do not support multimodal input can ignore it.
|
|
45
|
-
</ResponseField>
|
|
46
|
-
|
|
47
|
-
<ResponseField name="responses" type="readonly InputResponse[] | undefined">
|
|
48
|
-
Present only on answer turns (`t.respond` / `t.respondAll`): per-request structured answers, matched by `requestId`.
|
|
49
|
-
</ResponseField>
|
|
50
|
-
|
|
51
|
-
## `ctx` (`AgentContext`)
|
|
52
|
-
|
|
53
|
-
<ResponseField name="signal" type="AbortSignal">
|
|
54
|
-
For timeouts and cancellation; pass it through to every request you make.
|
|
55
|
-
</ResponseField>
|
|
56
|
-
|
|
57
|
-
<ResponseField name="model" type="string | undefined">
|
|
58
|
-
Model comparison for Tier 1: `experiment.model`, passed through; forward it if the app's interface accepts a model selection.
|
|
59
|
-
</ResponseField>
|
|
60
|
-
|
|
61
|
-
<ResponseField name="flags" type="Readonly<Record<string, unknown>>">
|
|
62
|
-
Feature A/B for Tier 3: `experiment.flags`, passed through; `{}` when not configured.
|
|
63
|
-
</ResponseField>
|
|
64
|
-
|
|
65
|
-
<ResponseField name="telemetry" type="Telemetry | undefined">
|
|
66
|
-
Present only when OTel integration is configured: this turn's W3C trace context (`headers`, a fresh `traceparent` per turn).
|
|
67
|
-
</ResponseField>
|
|
68
|
-
|
|
69
|
-
<ResponseField name="sandbox" type="Sandbox | undefined">
|
|
70
|
-
Only agents constructed with `defineSandboxAgent` receive this.
|
|
71
|
-
</ResponseField>
|
|
72
|
-
|
|
73
|
-
<ResponseField name="session" type="AgentSession">
|
|
74
|
-
State slot for the current conversation line. Every `send` on the same conversation line gets the same `ctx.session`; a new conversation line (the eval's first turn, or after `t.newSession()`) gets a fresh one:
|
|
75
|
-
|
|
76
|
-
- `id?: string` / `capture(id): void` — session continuation when the server keeps history: `id` is the session id recorded on this line (`undefined` on a new line), `capture` records the returned id (it only lands when none has been recorded yet).
|
|
77
|
-
- `history<TMsg>(): { get(): TMsg[]; commit(messages: TMsg[]): void }` — session continuation when the client carries the full history.
|
|
78
|
-
- `hold<T>(state: T): void` / `take<T>(): T | undefined` — storage for the HITL paused-turn scene; `take` clears on read (consume once).
|
|
79
|
-
- `state: Record<string, unknown>` — escape hatch, starts as `{}`, never written by the framework.
|
|
80
|
-
|
|
81
|
-
Full contract in the [Adapter concept](/concepts/adapter#context-agentcontext).
|
|
82
|
-
</ResponseField>
|
|
83
|
-
|
|
84
|
-
<ResponseField name="log" type="(msg: string) => void">
|
|
85
|
-
Writes a message to the run log, visible in `niceeval view`.
|
|
86
|
-
</ResponseField>
|
|
87
|
-
|
|
88
|
-
## Direct agent example
|
|
89
|
-
|
|
90
|
-
```ts
|
|
91
|
-
export default defineAgent({
|
|
92
|
-
name: "echo",
|
|
93
|
-
async send(input) {
|
|
94
|
-
return {
|
|
95
|
-
status: "completed",
|
|
96
|
-
events: [{ type: "message", role: "assistant", text: input.text }],
|
|
97
|
-
};
|
|
98
|
-
},
|
|
99
|
-
});
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## `defineSandboxAgent`
|
|
103
|
-
|
|
104
|
-
Use this for coding agent CLIs. The produced `Agent.kind` is always `"sandbox"` — filesystem assertions like `t.sandbox` and `t.sandbox.fileChanged()` unlock only on this kind of agent. `ctx.sandbox` is the handle to the current isolated environment:
|
|
105
|
-
|
|
106
|
-
<ResponseField name="runCommand(cmd, args?, opts?)" type="(cmd: string, args?: string[], opts?: CommandOptions) => Promise<CommandResult>">
|
|
107
|
-
Run a command.
|
|
108
|
-
</ResponseField>
|
|
109
|
-
|
|
110
|
-
<ResponseField name="runShell(script, opts?)" type="(script: string, opts?: CommandOptions) => Promise<CommandResult>">
|
|
111
|
-
Run a shell script.
|
|
112
|
-
</ResponseField>
|
|
113
|
-
|
|
114
|
-
<ResponseField name="readFile(path)" type="(path: string) => Promise<string>">
|
|
115
|
-
Read a file inside the sandbox.
|
|
116
|
-
</ResponseField>
|
|
117
|
-
|
|
118
|
-
<ResponseField name="fileExists(path)" type="(path: string) => Promise<boolean>">
|
|
119
|
-
Check whether a file exists inside the sandbox.
|
|
120
|
-
</ResponseField>
|
|
121
|
-
|
|
122
|
-
<ResponseField name="writeFiles(files, targetDir?)" type="(files: Record<string, string>, targetDir?: string) => Promise<void>">
|
|
123
|
-
Write file contents by path.
|
|
124
|
-
</ResponseField>
|
|
125
|
-
|
|
126
|
-
<ResponseField name="uploadFiles(files, targetDir?)" type="(files: SandboxFile[], targetDir?: string) => Promise<void>">
|
|
127
|
-
Upload local files into the sandbox.
|
|
128
|
-
</ResponseField>
|
|
129
|
-
|
|
130
|
-
<ResponseField name="uploadDirectory(localDir, targetDir?, opts?)" type="(localDir: string, targetDir?: string, opts?: { ignore?: string[] }) => Promise<void>">
|
|
131
|
-
Upload an entire local directory, typically used to write the eval's starting files.
|
|
132
|
-
</ResponseField>
|
|
133
|
-
|
|
134
|
-
<ResponseField name="sandboxId" type="string">
|
|
135
|
-
Id of the current sandbox instance.
|
|
136
|
-
</ResponseField>
|
|
137
|
-
|
|
138
|
-
<ResponseField name="stop()" type="() => Promise<void>">
|
|
139
|
-
Stop the sandbox.
|
|
140
|
-
</ResponseField>
|
|
141
|
-
|
|
142
|
-
```ts
|
|
143
|
-
import { defineSandboxAgent } from "niceeval/adapter";
|
|
144
|
-
|
|
145
|
-
export default defineSandboxAgent({
|
|
146
|
-
name: "my-cli-agent",
|
|
147
|
-
async send(input, ctx) {
|
|
148
|
-
await ctx.sandbox.runCommand("my-agent", ["run", input.text]);
|
|
149
|
-
return { status: "completed", events: [] };
|
|
150
|
-
},
|
|
151
|
-
});
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
## Registration
|
|
155
|
-
|
|
156
|
-
```ts
|
|
157
|
-
import { defineExperiment } from "niceeval";
|
|
158
|
-
import echo from "./agents/echo";
|
|
159
|
-
|
|
160
|
-
export default defineExperiment({
|
|
161
|
-
agent: echo,
|
|
162
|
-
runs: 1,
|
|
163
|
-
});
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
## `ctx` and `t`
|
|
167
|
-
|
|
168
|
-
`ctx` is the run context seen by the adapter side; `t` is the test context seen by the eval author. They use the same run data but have different responsibilities.
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "defineConfig: project defaults"
|
|
3
|
-
sidebarTitle: "defineConfig"
|
|
4
|
-
description: "defineConfig reference: judge, reporters, concurrency, timeout, and sandbox defaults."
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
Use `defineConfig` in `niceeval.config.ts` for project-wide defaults. Agent, model, flags, runs, and per-experiment budget belong in `experiments/` files via `defineExperiment`.
|
|
8
|
-
|
|
9
|
-
```ts
|
|
10
|
-
import { defineConfig } from "niceeval";
|
|
11
|
-
import { JUnit } from "niceeval/reporters";
|
|
12
|
-
|
|
13
|
-
export default defineConfig({
|
|
14
|
-
judge: { model: "gpt-5.4-mini" },
|
|
15
|
-
reporters: [JUnit(".niceeval/junit.xml")],
|
|
16
|
-
maxConcurrency: 4,
|
|
17
|
-
timeoutMs: 300_000,
|
|
18
|
-
});
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
<ParamField body="judge" type="{ model: string; baseUrl?: string; apiKeyEnv?: string }">
|
|
22
|
-
Default judge configuration for `t.judge.autoevals.*`. Individual evals can override this with `defineEval({ judge })`.
|
|
23
|
-
</ParamField>
|
|
24
|
-
|
|
25
|
-
<ParamField body="reporters" type="Reporter[]">
|
|
26
|
-
Additional reporters that observe the whole run, such as `Braintrust(...)` for uploading to an experiment platform. See [Reporters](../guides/reporters). For temporary JUnit output, use the CLI flag `--junit <path>`.
|
|
27
|
-
</ParamField>
|
|
28
|
-
|
|
29
|
-
<ParamField body="maxConcurrency" type="number">
|
|
30
|
-
Maximum concurrent attempts. Sandbox backends may choose a lower default when this is omitted.
|
|
31
|
-
</ParamField>
|
|
32
|
-
|
|
33
|
-
<ParamField body="timeoutMs" type="number">
|
|
34
|
-
Per-attempt timeout in milliseconds.
|
|
35
|
-
</ParamField>
|
|
36
|
-
|
|
37
|
-
<ParamField body="sandbox" type="SandboxSpec">
|
|
38
|
-
Default sandbox backend for sandbox agents, built with `dockerSandbox()` / `vercelSandbox()` / `e2bSandbox()` from `niceeval/sandbox` — bare strings like `"docker"` are no longer accepted here. Required for sandbox agents (directly on the experiment, or via this project-wide fallback: `exp.sandbox ?? config.sandbox`) — niceeval no longer auto-detects a backend from env vars, and there is no CLI flag for choosing one.
|
|
39
|
-
</ParamField>
|
|
40
|
-
|
|
41
|
-
niceeval keeps environment preparation in ordinary code. Prepare files inside `test(t)` with `t.sandbox.writeFiles`, `uploadFiles`, or `uploadDirectory`; put adapter setup in the Adapter.
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "defineEval: declare, configure, and run NiceEval evals"
|
|
3
|
-
sidebarTitle: "defineEval"
|
|
4
|
-
description: "Reference for defineEval options, the test context t, Turn return values, sandbox helpers, and dataset array exports."
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
`defineEval` is the main entry point for authoring evals. Each eval file normally calls it once and default-exports the result.
|
|
8
|
-
|
|
9
|
-
```ts
|
|
10
|
-
import { defineEval } from "niceeval";
|
|
11
|
-
|
|
12
|
-
export default defineEval({
|
|
13
|
-
description: "Brooklyn weather query",
|
|
14
|
-
async test(t) {
|
|
15
|
-
await t.send("What's the weather like in Brooklyn today?");
|
|
16
|
-
t.succeeded();
|
|
17
|
-
},
|
|
18
|
-
});
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
<Note>
|
|
22
|
-
Do not provide `id` or `name`. NiceEval derives the eval ID from the file path.
|
|
23
|
-
</Note>
|
|
24
|
-
|
|
25
|
-
## `defineEval` options
|
|
26
|
-
|
|
27
|
-
<ParamField body="description" type="string">
|
|
28
|
-
Human-readable description shown in console output and reports.
|
|
29
|
-
</ParamField>
|
|
30
|
-
|
|
31
|
-
<ParamField body="agent" type="string">
|
|
32
|
-
Agent name for this eval. Usually omitted so the experiment supplies the agent.
|
|
33
|
-
</ParamField>
|
|
34
|
-
|
|
35
|
-
<ParamField body="tags" type="string[]">
|
|
36
|
-
Tags for filtering or organizing evals.
|
|
37
|
-
</ParamField>
|
|
38
|
-
|
|
39
|
-
<ParamField body="judge" type="JudgeConfig">
|
|
40
|
-
Judge model override for this eval.
|
|
41
|
-
</ParamField>
|
|
42
|
-
|
|
43
|
-
<ParamField body="reporters" type="Reporter[]">
|
|
44
|
-
Eval-specific reporters. The instance only observes evals that reference it. If multiple evals share the same instance, their results land in the same destination. See [Reporters](../guides/reporters).
|
|
45
|
-
</ParamField>
|
|
46
|
-
|
|
47
|
-
<ParamField body="timeoutMs" type="number">
|
|
48
|
-
Timeout override.
|
|
49
|
-
</ParamField>
|
|
50
|
-
|
|
51
|
-
<ParamField body="metadata" type="Record<string, unknown>">
|
|
52
|
-
Extra metadata for reports or external tools.
|
|
53
|
-
</ParamField>
|
|
54
|
-
|
|
55
|
-
<ParamField body="test" type="(t: TestContext) => Promise<void>" required>
|
|
56
|
-
Eval body. Drive the agent and declare assertions here.
|
|
57
|
-
</ParamField>
|
|
58
|
-
|
|
59
|
-
## Test context: `t`
|
|
60
|
-
|
|
61
|
-
### Always available
|
|
62
|
-
|
|
63
|
-
<ParamField body="t.send(text)" type="(text: string, opts?) => Promise<Turn>">
|
|
64
|
-
Sends a message to the agent and returns the current turn.
|
|
65
|
-
</ParamField>
|
|
66
|
-
|
|
67
|
-
<ParamField body="t.sendFile(path, text?, opts?)" type="function">
|
|
68
|
-
Sends a file plus optional text.
|
|
69
|
-
</ParamField>
|
|
70
|
-
|
|
71
|
-
<ParamField body="t.check(value, assertion)" type="(value: unknown, assertion: Assertion) => void">
|
|
72
|
-
Records a value assertion. Failure does not immediately abort the test.
|
|
73
|
-
</ParamField>
|
|
74
|
-
|
|
75
|
-
<ParamField body="t.require(value, assertion)" type="(value: unknown, assertion: Assertion) => void">
|
|
76
|
-
Records a prerequisite assertion. Failure aborts the test immediately.
|
|
77
|
-
</ParamField>
|
|
78
|
-
|
|
79
|
-
<ParamField body="t.skip(reason)" type="(reason: string) => void">
|
|
80
|
-
Skips the eval.
|
|
81
|
-
</ParamField>
|
|
82
|
-
|
|
83
|
-
### Conversation
|
|
84
|
-
|
|
85
|
-
<ParamField body="t.reply" type="string">
|
|
86
|
-
Last assistant text message in the current session.
|
|
87
|
-
</ParamField>
|
|
88
|
-
|
|
89
|
-
<ParamField body="t.newSession()" type="() => TestContext">
|
|
90
|
-
Starts an independent session line.
|
|
91
|
-
</ParamField>
|
|
92
|
-
|
|
93
|
-
### Tool observability
|
|
94
|
-
|
|
95
|
-
<ParamField body="t.calledTool(name, opts?)" type="function">
|
|
96
|
-
Asserts that a tool was called.
|
|
97
|
-
</ParamField>
|
|
98
|
-
|
|
99
|
-
<ParamField body="t.notCalledTool(name, opts?)" type="function">
|
|
100
|
-
Asserts that a tool was not called. This is only trustworthy when the event stream is complete.
|
|
101
|
-
</ParamField>
|
|
102
|
-
|
|
103
|
-
<ParamField body="t.event(type, opts?)" type="function">
|
|
104
|
-
Low-level event stream assertion.
|
|
105
|
-
</ParamField>
|
|
106
|
-
|
|
107
|
-
### Workspace / sandbox
|
|
108
|
-
|
|
109
|
-
<ParamField body="t.sandbox.fileChanged(path)" type="function">
|
|
110
|
-
Asserts that a workspace file changed.
|
|
111
|
-
</ParamField>
|
|
112
|
-
|
|
113
|
-
<ParamField body="t.sandbox.runCommand(command, args?)" type="function">
|
|
114
|
-
Runs a verification command in the sandbox.
|
|
115
|
-
</ParamField>
|
|
116
|
-
|
|
117
|
-
## Judge assertions
|
|
118
|
-
|
|
119
|
-
```ts
|
|
120
|
-
t.judge.autoevals.factuality(expected, { on: t.reply }).atLeast(0.8);
|
|
121
|
-
t.judge.autoevals.closedQA(question, { on: t.reply }).atLeast(0.7);
|
|
122
|
-
t.judge.autoevals.closedQA(rubric, { on: t.reply }).atLeast(0.75);
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
## `Turn`
|
|
126
|
-
|
|
127
|
-
<ResponseField name="events" type="StreamEvent[]">
|
|
128
|
-
Standard event stream for this turn.
|
|
129
|
-
</ResponseField>
|
|
130
|
-
|
|
131
|
-
<ResponseField name="data" type="unknown | undefined">
|
|
132
|
-
Structured output, present only when declared by the send call.
|
|
133
|
-
</ResponseField>
|
|
134
|
-
|
|
135
|
-
<ResponseField name="status" type='"completed" | "failed" | "waiting"'>
|
|
136
|
-
Current turn status.
|
|
137
|
-
</ResponseField>
|
|
138
|
-
|
|
139
|
-
<ResponseField name="message" type="string">
|
|
140
|
-
Assistant text for this turn.
|
|
141
|
-
</ResponseField>
|
|
142
|
-
|
|
143
|
-
<ResponseField name="toolCalls" type="ToolCall[]">
|
|
144
|
-
Tool calls for this turn.
|
|
145
|
-
</ResponseField>
|
|
146
|
-
|
|
147
|
-
## Dataset export
|
|
148
|
-
|
|
149
|
-
```ts
|
|
150
|
-
export default rows.map((row) =>
|
|
151
|
-
defineEval({
|
|
152
|
-
description: row.task,
|
|
153
|
-
async test(t) {
|
|
154
|
-
await t.send(row.prompt);
|
|
155
|
-
},
|
|
156
|
-
}),
|
|
157
|
-
);
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
Array exports generate stable IDs such as `file/0000`, `file/0001`, and so on.
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Standard event stream reference"
|
|
3
|
-
sidebarTitle: "Events"
|
|
4
|
-
description: "The nine StreamEvent variants: what each one means, when adapters emit it, and which assertions consume it. Producing this stream is the adapter's core job."
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
An adapter `send` returns a `Turn`, and its `events: StreamEvent[]` is the **only data source for assertions**: `t.calledTool()`, `t.reply`, `toolOrder`, `noFailedActions`, and more all read from this stream. Once your adapter translates "what the agent did this turn" into this stream, the whole assertion surface becomes available.
|
|
8
|
-
|
|
9
|
-
## Turn: the return value of `send`
|
|
10
|
-
|
|
11
|
-
```ts
|
|
12
|
-
interface Turn {
|
|
13
|
-
events: StreamEvent[]; // events for this turn, in real order
|
|
14
|
-
data?: unknown; // structured output -> outputEquals / outputMatches
|
|
15
|
-
status: "completed" | "failed" | "waiting"; // waiting = paused for human input
|
|
16
|
-
usage?: { inputTokens: number; outputTokens: number }; // -> maxTokens / maxCost / cost reports
|
|
17
|
-
}
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
`data` means "the structured product of this turn". Only fill it when the application answer itself is structured, such as extraction, classification, or form filling. `outputEquals` / `outputMatches` read from it. If the app only returns text, leave it unset. Do not copy raw response bodies or message text into `data`, and do not serialize structured output back into `events`. Include `usage` only when you have it. Do not invent numbers.
|
|
21
|
-
|
|
22
|
-
## Event table
|
|
23
|
-
|
|
24
|
-
| Event | Meaning | Consumed by |
|
|
25
|
-
|---|---|---|
|
|
26
|
-
| `message` | the agent (or user) said something | `t.reply`, `messageIncludes`, judge inputs |
|
|
27
|
-
| `action.called` | a tool call started | `calledTool`, `toolOrder`, `maxToolCalls`, `notCalledTool` |
|
|
28
|
-
| `action.result` | the result of that call | `calledTool` status matching, `noFailedActions` |
|
|
29
|
-
| `subagent.called` | delegated to a subagent | `calledSubagent` |
|
|
30
|
-
| `subagent.completed` | the subagent returned | `calledSubagent` status, `noFailedActions` |
|
|
31
|
-
| `input.requested` | paused and waiting for human input | `t.parked()`, `t.requireInputRequest()` |
|
|
32
|
-
| `thinking` | reasoning text | `event("thinking")`, viewer display |
|
|
33
|
-
| `compaction` | context got compacted | `event("compaction")` |
|
|
34
|
-
| `error` | the turn hit an error | `event("error")`, viewer display |
|
|
35
|
-
|
|
36
|
-
Any event can also be checked with `event(type)`, `notEvent(type)`, `eventOrder(types)`, or `eventsSatisfy(label, predicate)`.
|
|
37
|
-
|
|
38
|
-
## Event details
|
|
39
|
-
|
|
40
|
-
### `message` - what was said
|
|
41
|
-
|
|
42
|
-
```ts
|
|
43
|
-
{ type: "message", role: "assistant" | "user", text: string }
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
Emit one `message` with `role: "assistant"` for each chunk of assistant text. **Tool results are not assistant messages.** Do not wrap tool output as `message`, or `t.reply` will read the wrong thing. User `message` events are usually recorded by NiceEval automatically.
|
|
47
|
-
|
|
48
|
-
### `action.called` / `action.result` - which tool was used, and what happened
|
|
49
|
-
|
|
50
|
-
```ts
|
|
51
|
-
{ type: "action.called", callId: string, name: string, input: JsonValue }
|
|
52
|
-
{ type: "action.result", callId: string, output?: JsonValue,
|
|
53
|
-
status: "completed" | "failed" | "rejected" }
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
- Pair each `action.called` with an `action.result` that has the same `callId`, so concurrent calls do not get mixed up. Use the explicit ID from your source when it exists.
|
|
57
|
-
- Fill `status` truthfully: actual tool execution failure is `"failed"`. Human denial is `"rejected"`.
|
|
58
|
-
- Keep `name` as the tool's original name.
|
|
59
|
-
|
|
60
|
-
### `subagent.called` / `subagent.completed` - which subagent was delegated to
|
|
61
|
-
|
|
62
|
-
```ts
|
|
63
|
-
{ type: "subagent.called", callId: string, name: string, remoteUrl?: string }
|
|
64
|
-
{ type: "subagent.completed", callId: string, output?: JsonValue,
|
|
65
|
-
status: "completed" | "failed" }
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
Emit this pair when the subject under test delegates work to a subagent and waits for it to return.
|
|
69
|
-
|
|
70
|
-
### `input.requested` - paused for human input
|
|
71
|
-
|
|
72
|
-
```ts
|
|
73
|
-
{ type: "input.requested", request: {
|
|
74
|
-
id?: string,
|
|
75
|
-
action?: string,
|
|
76
|
-
input?: JsonValue,
|
|
77
|
-
prompt?: string,
|
|
78
|
-
options?: { id: string, label?: string }[],
|
|
79
|
-
} }
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
When the agent pauses for a person, emit one event per pending question and return overall turn `status: "waiting"`. `t.requireInputRequest(filter)` matches this `request` structure field by field, so populate as many fields as you can. See the HITL part of [Connect Your Agent](/guides/connect-your-agent).
|
|
83
|
-
|
|
84
|
-
### `thinking` / `compaction` / `error`
|
|
85
|
-
|
|
86
|
-
```ts
|
|
87
|
-
{ type: "thinking", text: string }
|
|
88
|
-
{ type: "compaction", reason?: string }
|
|
89
|
-
{ type: "error", message: string }
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
Emit them when your source gives them to you. Do not fabricate them. `compaction` mostly appears in coding-agent CLIs when context is compressed automatically.
|
|
93
|
-
|
|
94
|
-
## Three mapping rules
|
|
95
|
-
|
|
96
|
-
1. **Order is fact.** Keep events in real execution order. `toolOrder` and `eventOrder` depend on that sequence.
|
|
97
|
-
2. **Match `callId`s.** Every `called` event should have the corresponding `result` with the same ID.
|
|
98
|
-
3. **Be honest about completeness.** If you declare `toolObservability: true`, all tool calls must be in the stream. If you omit some of them, negative assertions can silently pass. If your manual mapping cannot be complete, [do not claim that capability](/reference/capabilities).
|
|
99
|
-
|
|
100
|
-
## A complete mapping example
|
|
101
|
-
|
|
102
|
-
When the agent response contains step records, the mapping is usually a small loop:
|
|
103
|
-
|
|
104
|
-
```ts
|
|
105
|
-
import type { StreamEvent } from "niceeval";
|
|
106
|
-
|
|
107
|
-
function toStreamEvents(body: MyBotResponse): StreamEvent[] {
|
|
108
|
-
const events: StreamEvent[] = [];
|
|
109
|
-
for (const step of body.steps) {
|
|
110
|
-
if (step.type === "tool_call") {
|
|
111
|
-
events.push({ type: "action.called", callId: step.id, name: step.tool, input: step.args });
|
|
112
|
-
events.push({
|
|
113
|
-
type: "action.result",
|
|
114
|
-
callId: step.id,
|
|
115
|
-
output: step.result,
|
|
116
|
-
status: step.error ? "failed" : "completed",
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
if (step.type === "text") {
|
|
120
|
-
events.push({ type: "message", role: "assistant", text: step.text });
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
return events;
|
|
124
|
-
}
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
## Related reading
|
|
128
|
-
|
|
129
|
-
- [Connect Your Agent](/guides/connect-your-agent) - The from-scratch integration tutorial.
|
|
130
|
-
- [Capabilities](/reference/capabilities) - What it means to claim "the event stream is complete".
|
|
131
|
-
- [Authoring Evals](/guides/authoring) - The assertions that consume this stream.
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "niceeval/expect matchers and custom assertion reference"
|
|
3
|
-
sidebarTitle: "Assertion Matchers"
|
|
4
|
-
description: "Reference for niceeval/expect: includes, equals, matches, similarity, satisfies. Chain `.gate()` or `.atLeast(0.7)`, or build custom matchers with `makeAssertion`."
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
`niceeval/expect` provides a set of composable matchers for `t.check()` and `t.require()`. A matcher returns an `Assertion` with a default severity, either `gate` or `soft`.
|
|
8
|
-
|
|
9
|
-
```ts
|
|
10
|
-
import { includes, equals, matches, similarity, satisfies } from "niceeval/expect";
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## How matchers are used
|
|
14
|
-
|
|
15
|
-
```ts
|
|
16
|
-
t.check(t.reply, includes("confirmed"));
|
|
17
|
-
t.check(turn.data, equals({ intent: "refund" }));
|
|
18
|
-
t.require(turn.status, equals("completed"));
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
| Method | On failure | Best for |
|
|
22
|
-
|---|---|---|
|
|
23
|
-
| `t.check` | record result, keep executing | most assertions |
|
|
24
|
-
| `t.require` | throw immediately, abort the test | preconditions where continuing makes no sense |
|
|
25
|
-
|
|
26
|
-
## Matchers
|
|
27
|
-
|
|
28
|
-
### `includes`
|
|
29
|
-
|
|
30
|
-
```ts
|
|
31
|
-
includes(substring: string | RegExp): Assertion
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
Assert that a string contains the given substring, or matches a regex.
|
|
35
|
-
|
|
36
|
-
```ts
|
|
37
|
-
t.check(t.reply, includes("Paris"));
|
|
38
|
-
t.check(t.reply, includes(/order #\d+/i));
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
### `equals`
|
|
42
|
-
|
|
43
|
-
```ts
|
|
44
|
-
equals(expected: unknown): Assertion
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
Assert deep structural equality, useful for JSON, arrays, and objects.
|
|
48
|
-
|
|
49
|
-
```ts
|
|
50
|
-
t.check(turn.data, equals({ intent: "refund" }));
|
|
51
|
-
t.check(turn.data, equals(["a", "b", "c"]));
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
### `matches`
|
|
55
|
-
|
|
56
|
-
```ts
|
|
57
|
-
matches(pattern: RegExp): Assertion
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
Assert that a string matches a regex.
|
|
61
|
-
|
|
62
|
-
```ts
|
|
63
|
-
t.check(t.reply, matches(/#[A-Z0-9]{8}/));
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
### `similarity`
|
|
67
|
-
|
|
68
|
-
```ts
|
|
69
|
-
similarity(expected: string): Assertion
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
Use this for semantic or textual similarity checks, usually together with a threshold.
|
|
73
|
-
|
|
74
|
-
```ts
|
|
75
|
-
t.check(t.reply, similarity("The capital of France is Paris.").atLeast(0.8));
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
### `satisfies`
|
|
79
|
-
|
|
80
|
-
```ts
|
|
81
|
-
satisfies(predicate: (value: unknown) => boolean): Assertion
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
Check a value with a custom predicate.
|
|
85
|
-
|
|
86
|
-
```ts
|
|
87
|
-
t.check(turn.data, satisfies((value) => Array.isArray(value)));
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
## Gate and soft
|
|
91
|
-
|
|
92
|
-
```ts
|
|
93
|
-
t.check(t.reply, includes("required").gate());
|
|
94
|
-
t.check(t.reply, includes("nice to have").atLeast(0.7));
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
- `gate()`: failure makes the eval fail.
|
|
98
|
-
- `soft()`: contributes to scoring without necessarily failing the eval.
|
|
99
|
-
|
|
100
|
-
## Custom matchers
|
|
101
|
-
|
|
102
|
-
```ts
|
|
103
|
-
import { makeAssertion } from "niceeval/expect";
|
|
104
|
-
|
|
105
|
-
const validEmail = makeAssertion("valid email", (value) => {
|
|
106
|
-
return typeof value === "string" && value.includes("@") ? 1 : 0;
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
t.check(t.reply, validEmail());
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
Custom matchers should return a score between 0 and 1 and use a clear name.
|
package/docs-site/tracker.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
(function () {
|
|
2
|
-
var script = document.createElement("script");
|
|
3
|
-
script.src = "https://api.goshipfast.com/tracker.js";
|
|
4
|
-
script.async = true;
|
|
5
|
-
script.setAttribute("data-project", "cmr24oe2n006qlj10lr9t38n8");
|
|
6
|
-
script.setAttribute("data-endpoint", "https://api.goshipfast.com");
|
|
7
|
-
document.head.appendChild(script);
|
|
8
|
-
})();
|
package/src/report/react/data.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
// niceeval/report/react 的数据契约(组件 props 类型)。
|
|
2
|
-
//
|
|
3
|
-
// 契约的家在计算层(../types.ts,照 docs/reports.md「计算函数与数据契约」),这里 re-export,
|
|
4
|
-
// 「算」与「画」两侧共用同一份类型;本文件零运行时代码——组件不做任何聚合或数据操作。
|
|
5
|
-
|
|
6
|
-
export type {
|
|
7
|
-
AttemptRef,
|
|
8
|
-
MetricColumn,
|
|
9
|
-
MetricCell,
|
|
10
|
-
TableData,
|
|
11
|
-
MatrixData,
|
|
12
|
-
ScoreboardData,
|
|
13
|
-
ScatterData,
|
|
14
|
-
OverviewData,
|
|
15
|
-
DeltaData,
|
|
16
|
-
CaseListData,
|
|
17
|
-
} from "../types.ts";
|