niceeval 0.1.1 → 0.1.2
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/README.md +8 -8
- package/README.zh.md +13 -13
- package/docs/README.md +119 -0
- package/docs/adapters/README.md +60 -0
- package/docs/adapters/authoring.md +179 -0
- package/docs/adapters/coding-agent-skills-plugins.md +324 -0
- package/docs/adapters/collection.md +128 -0
- package/docs/adapters/contract.md +263 -0
- package/docs/adapters/reference/agent-eval.md +215 -0
- package/docs/adapters/reference/agent-loop-apis.md +69 -0
- package/docs/adapters/reference/claude-code-otel-telemetry.md +100 -0
- package/docs/adapters/reference/eve-protocol.md +127 -0
- package/docs/adapters/reference/otel-genai.md +107 -0
- package/docs/adapters/reference/otel-instrumentation.md +65 -0
- package/docs/adapters/targets.md +99 -0
- package/docs/architecture.md +140 -0
- package/docs/assertions.md +388 -0
- package/docs/capabilities-by-construction.md +48 -0
- package/docs/cli.md +171 -0
- package/docs/concepts.md +106 -0
- package/docs/e2e-ci.md +295 -0
- package/docs/eval-authoring.md +319 -0
- package/docs/experiments.md +154 -0
- package/docs/getting-started.md +224 -0
- package/docs/multi-agent.md +145 -0
- package/docs/observability.md +333 -0
- package/docs/origin-integration.md +195 -0
- package/docs/references.md +35 -0
- package/docs/results-format.md +228 -0
- package/docs/runner.md +104 -0
- package/docs/sandbox.md +276 -0
- package/docs/scoring.md +119 -0
- package/docs/source-map.md +106 -0
- package/docs/tier-sync.md +177 -0
- package/docs/view.md +157 -0
- package/docs/vision.md +88 -0
- package/package.json +35 -5
- package/src/agents/ai-sdk-otel.ts +0 -0
- package/src/agents/ai-sdk.test.ts +377 -0
- package/src/agents/ai-sdk.ts +577 -0
- package/src/agents/bub.ts +30 -37
- package/src/agents/claude-code.ts +7 -4
- package/src/agents/codex.ts +15 -10
- package/src/agents/index.ts +43 -1
- package/src/agents/sdk-streams.test.ts +145 -0
- package/src/agents/sdk-streams.ts +457 -0
- package/src/agents/shared.ts +77 -39
- package/src/agents/streaming.test.ts +152 -0
- package/src/agents/streaming.ts +195 -0
- package/src/agents/types.ts +218 -0
- package/src/agents/ui-message-stream.test.ts +249 -0
- package/src/agents/ui-message-stream.ts +372 -0
- package/src/cli.ts +124 -77
- package/src/context/context.test.ts +203 -7
- package/src/context/context.ts +158 -49
- package/src/context/session.test.ts +96 -0
- package/src/context/session.ts +119 -9
- package/src/context/types.ts +205 -0
- package/src/define.ts +4 -14
- package/src/expect/index.ts +8 -71
- package/src/i18n/core.ts +28 -0
- package/src/i18n/en.ts +47 -5
- package/src/i18n/index.ts +5 -17
- package/src/i18n/zh-CN.ts +47 -5
- package/src/index.ts +12 -0
- package/src/loaders/index.ts +8 -39
- package/src/o11y/otlp/canonical.ts +7 -6
- package/src/o11y/otlp/mappers/codex.ts +10 -8
- package/src/o11y/otlp/mappers/index.ts +9 -21
- package/src/o11y/otlp/receiver.ts +25 -7
- package/src/o11y/otlp/sandbox-receiver.ts +57 -21
- package/src/o11y/otlp/turn-otel.test.ts +110 -0
- package/src/o11y/otlp/turn-otel.ts +125 -0
- package/src/o11y/parsers/bub.ts +13 -11
- package/src/o11y/parsers/claude-code.ts +27 -51
- package/src/o11y/parsers/codex.ts +29 -46
- package/src/o11y/parsers/index.ts +5 -14
- package/src/o11y/tool-names.test.ts +61 -0
- package/src/o11y/tool-names.ts +74 -0
- package/src/o11y/types.ts +135 -0
- package/src/runner/attempt.ts +456 -0
- package/src/runner/fingerprint.ts +59 -0
- package/src/runner/remote-sandbox.ts +53 -0
- package/src/runner/report.ts +53 -0
- package/src/runner/reporters/artifacts.ts +25 -4
- package/src/runner/reporters/console.ts +2 -8
- package/src/runner/reporters/live.ts +2 -8
- package/src/runner/reporters/shared.ts +15 -0
- package/src/runner/reporters/table.ts +10 -62
- package/src/runner/run.ts +114 -619
- package/src/runner/types.ts +237 -0
- package/src/sandbox/checkpoint.ts +15 -13
- package/src/sandbox/docker-stream.ts +87 -0
- package/src/sandbox/docker.ts +42 -120
- package/src/sandbox/e2b.ts +24 -75
- package/src/sandbox/local-files.ts +33 -0
- package/src/sandbox/paths.test.ts +85 -0
- package/src/sandbox/paths.ts +45 -0
- package/src/sandbox/resolve.ts +10 -34
- package/src/sandbox/shell.ts +17 -0
- package/src/sandbox/source-files.ts +42 -2
- package/src/sandbox/types.ts +158 -0
- package/src/sandbox/vercel.ts +55 -71
- package/src/scoring/collector.ts +3 -2
- package/src/scoring/judge.ts +72 -146
- package/src/scoring/match.ts +79 -0
- package/src/scoring/types.ts +76 -0
- package/src/shared/aggregate.ts +48 -0
- package/src/shared/format.ts +20 -0
- package/src/shared/outcome.ts +48 -0
- package/src/shared/types.ts +37 -0
- package/src/types.ts +20 -911
- package/src/view/aggregate.ts +103 -0
- package/src/view/app/App.tsx +26 -5
- package/src/view/app/components/AttemptModal.tsx +12 -3
- package/src/view/app/components/CodeView.tsx +9 -5
- package/src/view/app/components/CopyControls.tsx +4 -4
- package/src/view/app/components/ExperimentTable.tsx +5 -5
- package/src/view/app/i18n.ts +31 -7
- package/src/view/app/lib/format.ts +17 -20
- package/src/view/app/lib/outcome.ts +4 -16
- package/src/view/app/main.tsx +3 -5
- package/src/view/app/pages/RunsPage.tsx +2 -2
- package/src/view/app/pages/TracesPage.tsx +2 -2
- package/src/view/app/shared.ts +2 -1
- package/src/view/app/types.ts +6 -43
- package/src/view/client-dist/app.css +1 -1
- package/src/view/client-dist/app.js +18 -18
- package/src/view/index.ts +24 -401
- package/src/view/loader.ts +234 -0
- package/src/view/server.ts +136 -0
- package/src/view/shared/types.ts +64 -0
- package/src/view/styles.css +60 -9
|
@@ -3,13 +3,7 @@
|
|
|
3
3
|
import type { EvalResult, Reporter, RunSummary } from "../../types.ts";
|
|
4
4
|
import { t } from "../../i18n/index.ts";
|
|
5
5
|
import { formatDuration, formatTokens, renderRunReport } from "./table.ts";
|
|
6
|
-
|
|
7
|
-
const SYMBOL: Record<string, string> = {
|
|
8
|
-
passed: "✓",
|
|
9
|
-
failed: "✗",
|
|
10
|
-
errored: "!",
|
|
11
|
-
skipped: "○",
|
|
12
|
-
};
|
|
6
|
+
import { outcomeSymbol } from "./shared.ts";
|
|
13
7
|
|
|
14
8
|
export function Console(): Reporter {
|
|
15
9
|
return {
|
|
@@ -24,7 +18,7 @@ export function Console(): Reporter {
|
|
|
24
18
|
process.stdout.write(t("report.runStart", { count: n, extra }));
|
|
25
19
|
},
|
|
26
20
|
onEvalComplete(result: EvalResult) {
|
|
27
|
-
const sym =
|
|
21
|
+
const sym = outcomeSymbol(result.outcome);
|
|
28
22
|
const tok = (result.usage?.inputTokens ?? 0) + (result.usage?.outputTokens ?? 0);
|
|
29
23
|
// requests > 0 但 tokens = 0 → agent 跑了但不上报用量(如 bub);显示 — 而非误导性的 0
|
|
30
24
|
const tokStr = tok > 0 ? `${formatTokens(tok)} tok` : (result.usage?.requests ?? 0) > 0 ? `— tok` : `0 tok`;
|
|
@@ -5,16 +5,10 @@
|
|
|
5
5
|
import type { Reporter, RunShape, RunSummary } from "../../types.ts";
|
|
6
6
|
import { t } from "../../i18n/index.ts";
|
|
7
7
|
import { renderRunReport } from "./table.ts";
|
|
8
|
+
import { outcomeSymbol } from "./shared.ts";
|
|
8
9
|
|
|
9
10
|
const SPINNER = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
10
11
|
|
|
11
|
-
const OUTCOME_SYM: Record<string, string> = {
|
|
12
|
-
passed: "✓",
|
|
13
|
-
failed: "✗",
|
|
14
|
-
errored: "!",
|
|
15
|
-
skipped: "○",
|
|
16
|
-
};
|
|
17
|
-
|
|
18
12
|
// 进度日志里的基础设施噪声:OTLP 端口、remote-agent 启动提示、trace span 计数。
|
|
19
13
|
// 这些在行尾显示毫无意义,直接丢弃。
|
|
20
14
|
const NOISE_PATTERNS = [
|
|
@@ -76,7 +70,7 @@ export function Live(rows: LiveRow[], totalAttempts: number): LiveReporter {
|
|
|
76
70
|
function renderRow(state: RowState, frame: number): string {
|
|
77
71
|
const done = state.completed >= state.total;
|
|
78
72
|
const sym = done
|
|
79
|
-
? (
|
|
73
|
+
? outcomeSymbol(state.dominantOutcome ?? "")
|
|
80
74
|
: SPINNER[frame % SPINNER.length];
|
|
81
75
|
|
|
82
76
|
const evalCol = state.evalId.slice(0, 24).padEnd(24);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// reporter 共用的展示常量。符号表只此一份 —— console/live/table 各抄一份时,
|
|
2
|
+
// 改一个符号要同步三处且不报错。
|
|
3
|
+
|
|
4
|
+
import type { ResultOutcome } from "../../types.ts";
|
|
5
|
+
|
|
6
|
+
export const OUTCOME_SYM: Record<ResultOutcome, string> = {
|
|
7
|
+
passed: "✓",
|
|
8
|
+
failed: "✗",
|
|
9
|
+
errored: "!",
|
|
10
|
+
skipped: "○",
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export function outcomeSymbol(outcome: string): string {
|
|
14
|
+
return OUTCOME_SYM[outcome as ResultOutcome] ?? "?";
|
|
15
|
+
}
|
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
import type { EvalResult, RunSummary, Usage } from "../../types.ts";
|
|
2
2
|
import { t } from "../../i18n/index.ts";
|
|
3
|
+
import { outcomeSymbol } from "./shared.ts";
|
|
4
|
+
import { foldEvalOutcome, evalLevelStats as sharedEvalLevelStats } from "../../shared/outcome.ts";
|
|
5
|
+
// 展示口径(耗时/成本/百分比)与聚合小工具(标签/求和/排序)与 view 共用一份实现;
|
|
6
|
+
// console.ts 经这里 re-export formatDuration。
|
|
7
|
+
import { formatCost, formatDuration, formatPercent } from "../../shared/format.ts";
|
|
8
|
+
import { OUTCOME_ORDER, avg, displayExperimentName, fallbackExperimentLabel, sumMaybe, totalTokens } from "../../shared/aggregate.ts";
|
|
3
9
|
|
|
4
|
-
|
|
5
|
-
failed: 0,
|
|
6
|
-
errored: 1,
|
|
7
|
-
skipped: 2,
|
|
8
|
-
passed: 3,
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
const OUTCOME_SYM: Record<string, string> = {
|
|
12
|
-
passed: "✓",
|
|
13
|
-
failed: "✗",
|
|
14
|
-
errored: "!",
|
|
15
|
-
skipped: "○",
|
|
16
|
-
};
|
|
10
|
+
export { formatCost, formatDuration } from "../../shared/format.ts";
|
|
17
11
|
|
|
18
12
|
interface ExperimentRow {
|
|
19
13
|
key: string;
|
|
@@ -119,20 +113,8 @@ export function formatTokens(n: number): string {
|
|
|
119
113
|
return String(n);
|
|
120
114
|
}
|
|
121
115
|
|
|
122
|
-
export function formatDuration(ms: number): string {
|
|
123
|
-
if (!Number.isFinite(ms) || ms <= 0) return "0ms";
|
|
124
|
-
if (ms >= 60_000) return `${(ms / 60_000).toFixed(1)}m`;
|
|
125
|
-
if (ms >= 1000) return `${(ms / 1000).toFixed(2)}s`;
|
|
126
|
-
return `${Math.round(ms)}ms`;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export function formatCost(n: number | undefined): string {
|
|
130
|
-
if (n === undefined || n <= 0) return "$0";
|
|
131
|
-
return `$${n.toFixed(n < 1 ? 3 : 2)}`;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
116
|
export function formatOutcome(outcome: string): string {
|
|
135
|
-
const sym =
|
|
117
|
+
const sym = outcomeSymbol(outcome);
|
|
136
118
|
switch (outcome) {
|
|
137
119
|
case "passed": return `${sym} ${t("report.passed")}`;
|
|
138
120
|
case "failed": return `${sym} ${t("report.failed")}`;
|
|
@@ -198,21 +180,9 @@ function aggregateEvalRows(results: EvalResult[]): EvalRow[] {
|
|
|
198
180
|
.sort((a, b) => OUTCOME_ORDER[a.outcome] - OUTCOME_ORDER[b.outcome] || a.id.localeCompare(b.id));
|
|
199
181
|
}
|
|
200
182
|
|
|
183
|
+
// 折叠 / 计票口径与 view 同一份实现(src/shared/outcome.ts),CLI 表格和网页榜单永不打架。
|
|
201
184
|
function evalLevelStats(results: EvalResult[]) {
|
|
202
|
-
|
|
203
|
-
for (const r of results) byEval.set(r.id, [...(byEval.get(r.id) ?? []), r]);
|
|
204
|
-
const counts = { passed: 0, failed: 0, errored: 0, skipped: 0 };
|
|
205
|
-
for (const group of byEval.values()) counts[foldEvalOutcome(group)] += 1;
|
|
206
|
-
const ran = counts.passed + counts.failed + counts.errored;
|
|
207
|
-
return { evals: byEval.size, ...counts, passRate: ran ? counts.passed / ran : 0 };
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
function foldEvalOutcome(results: EvalResult[]): EvalResult["outcome"] {
|
|
211
|
-
const outcomes = results.map((r) => r.outcome);
|
|
212
|
-
if (outcomes.some((o) => o === "passed")) return "passed";
|
|
213
|
-
if (outcomes.some((o) => o === "failed")) return "failed";
|
|
214
|
-
if (outcomes.some((o) => o === "errored")) return "errored";
|
|
215
|
-
return "skipped";
|
|
185
|
+
return sharedEvalLevelStats(results, (r) => r.id);
|
|
216
186
|
}
|
|
217
187
|
|
|
218
188
|
function reasonFor(result: EvalResult): string {
|
|
@@ -238,33 +208,11 @@ function formatResult(row: ExperimentRow): string {
|
|
|
238
208
|
return `${row.passed}/${row.evals} ${t("report.passed")} · ${failures} ${t("report.failed")}${suffix}`;
|
|
239
209
|
}
|
|
240
210
|
|
|
241
|
-
function displayExperimentName(id: string | undefined): string | undefined {
|
|
242
|
-
if (!id) return undefined;
|
|
243
|
-
return id.split("/").filter(Boolean).at(-1) ?? id;
|
|
244
|
-
}
|
|
245
211
|
|
|
246
|
-
function fallbackExperimentLabel(result: EvalResult): string {
|
|
247
|
-
if (result.experiment?.id) return displayExperimentName(result.experiment.id) ?? result.experiment.id;
|
|
248
|
-
if (result.model) return `${result.agent}/${result.model}`;
|
|
249
|
-
return result.agent || "ad hoc run";
|
|
250
|
-
}
|
|
251
212
|
|
|
252
|
-
function totalTokens(items: Array<Usage | undefined>): number {
|
|
253
|
-
return items.reduce((n, u) => n + (u?.inputTokens ?? 0) + (u?.outputTokens ?? 0), 0);
|
|
254
|
-
}
|
|
255
213
|
|
|
256
|
-
function sumMaybe(items: Array<number | undefined>): number | undefined {
|
|
257
|
-
const known = items.filter((n): n is number => n !== undefined);
|
|
258
|
-
return known.length ? known.reduce((sum, n) => sum + n, 0) : undefined;
|
|
259
|
-
}
|
|
260
214
|
|
|
261
|
-
function avg(items: number[]): number {
|
|
262
|
-
return items.length ? items.reduce((sum, n) => sum + n, 0) / items.length : 0;
|
|
263
|
-
}
|
|
264
215
|
|
|
265
|
-
function formatPercent(v: number): string {
|
|
266
|
-
return `${Math.round(v * 100)}%`;
|
|
267
|
-
}
|
|
268
216
|
|
|
269
217
|
function renderTable(headers: string[], rows: string[][], opts: { maxWidth?: number; flexibleColumn?: number } = {}): string {
|
|
270
218
|
const rawRows = [headers, ...rows];
|