niceeval 0.4.6 → 0.5.0

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 +63 -20
  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 +10 -2
  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 +104 -14
  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,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
- ![Full round trip of one t.send: the eval calls t.send, the runner assembles TurnInput and ctx, the adapter returns a Turn with standard events.](/images/agent-turn-roundtrip-en.svg)
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.
@@ -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
- })();
@@ -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";