niceeval 0.6.1 → 0.6.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/dist/agents/types.d.ts +67 -5
- package/dist/context/types.d.ts +32 -12
- package/dist/i18n/en.d.ts +54 -0
- package/dist/i18n/zh-CN.d.ts +55 -1
- package/dist/o11y/types.d.ts +16 -2
- package/dist/report/aggregate.d.ts +5 -3
- package/dist/report/aggregate.js +32 -5
- package/dist/report/built-ins/experiment-comparison.d.ts +39 -1
- package/dist/report/built-ins/experiment-comparison.js +116 -10
- package/dist/report/built-ins/index.d.ts +1 -0
- package/dist/report/built-ins/index.js +1 -1
- package/dist/report/components.d.ts +8 -2
- package/dist/report/components.js +3 -3
- package/dist/report/compute.d.ts +11 -18
- package/dist/report/compute.js +54 -34
- package/dist/report/flag.d.ts +16 -1
- package/dist/report/flag.js +19 -1
- package/dist/report/format.d.ts +16 -8
- package/dist/report/format.js +27 -12
- package/dist/report/index.d.ts +4 -3
- package/dist/report/index.js +5 -4
- package/dist/report/locale.d.ts +11 -2
- package/dist/report/locale.js +23 -5
- package/dist/report/metrics.d.ts +13 -1
- package/dist/report/metrics.js +65 -14
- package/dist/report/primitives.d.ts +6 -0
- package/dist/report/react/AttemptList.d.ts +2 -2
- package/dist/report/react/AttemptList.js +5 -6
- package/dist/report/react/EvalList.d.ts +1 -1
- package/dist/report/react/EvalList.js +0 -0
- package/dist/report/react/ExperimentComparison.d.ts +8 -0
- package/dist/report/react/ExperimentComparison.js +11 -0
- package/dist/report/react/ExperimentList.d.ts +2 -1
- package/dist/report/react/ExperimentList.js +8 -10
- package/dist/report/react/MetricScatter.js +5 -11
- package/dist/report/react/chart-math.d.ts +23 -6
- package/dist/report/react/chart-math.js +71 -19
- package/dist/report/react/fixtures.d.ts +3 -3
- package/dist/report/react/fixtures.js +21 -14
- package/dist/report/report.d.ts +5 -1
- package/dist/report/report.js +6 -2
- package/dist/report/text/faces.d.ts +1 -1
- package/dist/report/text/faces.js +42 -41
- package/dist/report/text/table.js +36 -5
- package/dist/report/types.d.ts +39 -21
- package/dist/results/types.d.ts +11 -0
- package/dist/runner/feedback/sink.d.ts +110 -0
- package/dist/runner/types.d.ts +513 -22
- package/dist/sandbox/docker.d.ts +23 -2
- package/dist/sandbox/e2b.d.ts +15 -1
- package/dist/sandbox/errors.d.ts +30 -3
- package/dist/sandbox/io-retry.d.ts +17 -0
- package/dist/sandbox/registry.d.ts +2 -0
- package/dist/sandbox/resolve.d.ts +18 -5
- package/dist/sandbox/retry.d.ts +11 -1
- package/dist/sandbox/types.d.ts +39 -5
- package/dist/sandbox/vercel.d.ts +7 -1
- package/dist/scoring/coverage.d.ts +30 -0
- package/dist/scoring/display.d.ts +21 -0
- package/dist/scoring/display.js +120 -0
- package/dist/scoring/types.d.ts +103 -20
- package/dist/shared/aggregate.d.ts +1 -0
- package/dist/shared/aggregate.js +3 -3
- package/dist/shared/types.d.ts +28 -0
- package/dist/tty-line.d.ts +0 -4
- package/dist/util.d.ts +23 -0
- package/docs-site/zh/concepts/adapter.mdx +22 -4
- package/docs-site/zh/concepts/experiment.mdx +1 -1
- package/docs-site/zh/concepts/overview.mdx +6 -6
- package/docs-site/zh/guides/agent-feedback-loop.mdx +28 -26
- package/docs-site/zh/guides/authoring.mdx +33 -0
- package/docs-site/zh/guides/ci-integration.mdx +23 -12
- package/docs-site/zh/guides/connect-your-agent.mdx +29 -3
- package/docs-site/zh/guides/custom-reports.mdx +29 -34
- package/docs-site/zh/guides/dataset-fanout.mdx +25 -3
- package/docs-site/zh/guides/debug-sandbox.mdx +57 -0
- package/docs-site/zh/guides/debugging.mdx +210 -0
- package/docs-site/zh/guides/experiments.mdx +10 -3
- package/docs-site/zh/guides/official-adapters.mdx +26 -2
- package/docs-site/zh/guides/publish-report.mdx +30 -16
- package/docs-site/zh/guides/report-components.mdx +42 -30
- package/docs-site/zh/guides/reporters.mdx +2 -2
- package/docs-site/zh/guides/results-data.mdx +17 -9
- package/docs-site/zh/guides/runner.mdx +17 -7
- package/docs-site/zh/guides/sandbox-agent.mdx +56 -7
- package/docs-site/zh/guides/sandbox-providers.mdx +257 -9
- package/docs-site/zh/guides/scoring-guide.mdx +4 -4
- package/docs-site/zh/guides/viewing-results.mdx +79 -36
- package/docs-site/zh/guides/write-experiment.mdx +5 -3
- package/docs-site/zh/guides/write-send.mdx +17 -1
- package/docs-site/zh/index.mdx +1 -1
- package/docs-site/zh/reference/builtin-agents.mdx +27 -0
- package/docs-site/zh/reference/capabilities.mdx +2 -2
- package/docs-site/zh/reference/cli.mdx +33 -7
- package/docs-site/zh/reference/define-agent.mdx +57 -4
- package/docs-site/zh/reference/define-config.mdx +1 -1
- package/docs-site/zh/reference/define-eval.mdx +42 -9
- package/docs-site/zh/reference/expect.mdx +26 -1
- package/package.json +5 -1
- package/src/agents/ai-sdk-otel.test.ts +1 -0
- package/src/agents/ai-sdk.test.ts +3 -0
- package/src/agents/ai-sdk.ts +3 -0
- package/src/agents/bub-install-spec.test.ts +34 -0
- package/src/agents/bub-install-spec.ts +32 -0
- package/src/agents/bub.ts +31 -32
- package/src/agents/claude-code.test.ts +130 -9
- package/src/agents/claude-code.ts +76 -4
- package/src/agents/codex.test.ts +189 -40
- package/src/agents/codex.ts +155 -14
- package/src/agents/coding-cli-versions.test.ts +15 -0
- package/src/agents/coding-cli-versions.ts +3 -0
- package/src/agents/index.ts +11 -0
- package/src/agents/langgraph.test.ts +204 -0
- package/src/agents/langgraph.ts +495 -0
- package/src/agents/marketplace.ts +85 -0
- package/src/agents/native-config.test.ts +179 -0
- package/src/agents/native-config.ts +267 -0
- package/src/agents/openai-compat.test.ts +1 -0
- package/src/agents/openclaw.test.ts +31 -0
- package/src/agents/openclaw.ts +171 -0
- package/src/agents/plugin-config.test.ts +1 -0
- package/src/agents/sdk-streams.test.ts +79 -0
- package/src/agents/sdk-streams.ts +55 -10
- package/src/agents/skills.test.ts +1 -0
- package/src/agents/streaming.test.ts +3 -9
- package/src/agents/types.ts +68 -5
- package/src/agents/ui-message-stream.test.ts +3 -0
- package/src/cli.ts +411 -108
- package/src/context/context.test.ts +51 -12
- package/src/context/context.ts +161 -29
- package/src/context/session.test.ts +1 -0
- package/src/context/session.ts +114 -6
- package/src/context/types.ts +30 -12
- package/src/define.test.ts +13 -8
- package/src/define.ts +25 -4
- package/src/expect/index.ts +53 -23
- package/src/i18n/en.ts +64 -2
- package/src/i18n/zh-CN.ts +65 -3
- package/src/o11y/cost.test.ts +1 -0
- package/src/o11y/execution-tree.test.ts +1 -20
- package/src/o11y/otlp/mappers/claude-code.test.ts +1 -0
- package/src/o11y/otlp/parse.test.ts +1 -0
- package/src/o11y/otlp/turn-otel.test.ts +1 -0
- package/src/o11y/parsers/bub.test.ts +1 -0
- package/src/o11y/parsers/claude-code.test.ts +1 -34
- package/src/o11y/parsers/openclaw.test.ts +154 -0
- package/src/o11y/parsers/openclaw.ts +310 -0
- package/src/o11y/prices.json +746 -311
- package/src/o11y/tool-names.test.ts +1 -0
- package/src/o11y/types.ts +16 -2
- package/src/report/aggregate.ts +34 -5
- package/src/report/built-in-user-parity.test.tsx +110 -153
- package/src/report/built-ins/experiment-comparison.tsx +173 -13
- package/src/report/built-ins/index.ts +6 -1
- package/src/report/components.tsx +9 -3
- package/src/report/compute.ts +70 -40
- package/src/report/dual-render.test.tsx +194 -67
- package/src/report/flag.ts +30 -2
- package/src/report/format.ts +35 -11
- package/src/report/index.ts +22 -4
- package/src/report/locale.ts +25 -5
- package/src/report/metrics.ts +67 -14
- package/src/report/primitives.tsx +6 -0
- package/src/report/react/AttemptList.tsx +6 -31
- package/src/report/react/EvalList.tsx +0 -0
- package/src/report/react/ExperimentComparison.tsx +68 -0
- package/src/report/react/ExperimentList.tsx +15 -9
- package/src/report/react/MetricScatter.tsx +12 -14
- package/src/report/react/chart-math.test.ts +85 -0
- package/src/report/react/chart-math.ts +101 -22
- package/src/report/react/enhance.js +33 -1
- package/src/report/react/fixtures.ts +24 -17
- package/src/report/react/render.test.tsx +9 -64
- package/src/report/react/styles.css +73 -2
- package/src/report/report.test.ts +306 -98
- package/src/report/report.ts +6 -2
- package/src/report/text/faces.ts +47 -43
- package/src/report/text/table.ts +42 -5
- package/src/report/types.ts +41 -21
- package/src/results/annotated-source.test.ts +62 -9
- package/src/results/annotated-source.ts +64 -6
- package/src/results/attempt-evidence.test.ts +9 -7
- package/src/results/attempt-evidence.ts +15 -8
- package/src/results/attempt-source.ts +6 -3
- package/src/results/copy.ts +145 -55
- package/src/results/host-equivalence.test.ts +8 -6
- package/src/results/index.ts +2 -0
- package/src/results/locator.test.ts +1 -22
- package/src/results/open.ts +7 -1
- package/src/results/publish.ts +149 -0
- package/src/results/results.test.ts +85 -51
- package/src/results/truncate.ts +90 -0
- package/src/results/types.ts +7 -0
- package/src/results/writer.ts +31 -13
- package/src/runner/attempt.test.ts +138 -7
- package/src/runner/attempt.ts +603 -104
- package/src/runner/discover.test.ts +47 -0
- package/src/runner/discover.ts +36 -2
- package/src/runner/eval-source.test.ts +1 -27
- package/src/runner/feedback/agent.test.ts +504 -0
- package/src/runner/feedback/agent.ts +409 -0
- package/src/runner/feedback/ci.test.ts +562 -0
- package/src/runner/feedback/ci.ts +401 -0
- package/src/runner/feedback/coordinator.test.ts +317 -0
- package/src/runner/feedback/coordinator.ts +397 -0
- package/src/runner/feedback/failure.ts +40 -0
- package/src/runner/feedback/human.test.ts +616 -0
- package/src/runner/feedback/human.ts +535 -0
- package/src/runner/feedback/index.ts +66 -0
- package/src/runner/feedback/io.ts +78 -0
- package/src/runner/feedback/profile.test.ts +50 -0
- package/src/runner/feedback/profile.ts +58 -0
- package/src/runner/feedback/reducer.test.ts +395 -0
- package/src/runner/feedback/reducer.ts +260 -0
- package/src/runner/feedback/renderer.ts +82 -0
- package/src/runner/feedback/sink.ts +203 -0
- package/src/runner/feedback/testing.ts +106 -0
- package/src/runner/ledger.test.ts +230 -0
- package/src/runner/ledger.ts +329 -0
- package/src/runner/report.test.ts +128 -3
- package/src/runner/report.ts +33 -9
- package/src/runner/reporters/artifacts.ts +8 -2
- package/src/runner/reporters/braintrust.test.ts +8 -7
- package/src/runner/reporters/braintrust.ts +9 -2
- package/src/runner/reporters/index.ts +2 -2
- package/src/runner/reporters/json.test.ts +162 -0
- package/src/runner/reporters/json.ts +35 -8
- package/src/runner/reporters/shared.ts +1 -5
- package/src/runner/run.test.ts +760 -3
- package/src/runner/run.ts +242 -36
- package/src/runner/sandbox-prep.ts +3 -42
- package/src/runner/timing.ts +158 -0
- package/src/runner/types.ts +518 -22
- package/src/sandbox/checkpoint.test.ts +55 -0
- package/src/sandbox/checkpoint.ts +29 -8
- package/src/sandbox/cli-commands.ts +407 -0
- package/src/sandbox/docker.ts +115 -16
- package/src/sandbox/e2b-agent-template.test.ts +56 -0
- package/src/sandbox/e2b-agent-template.ts +94 -0
- package/src/sandbox/e2b.ts +74 -9
- package/src/sandbox/errors.ts +111 -4
- package/src/sandbox/index.ts +2 -0
- package/src/sandbox/io-retry.test.ts +58 -0
- package/src/sandbox/io-retry.ts +45 -0
- package/src/sandbox/keep-registry.test.ts +86 -0
- package/src/sandbox/keep-registry.ts +142 -0
- package/src/sandbox/keep.ts +178 -0
- package/src/sandbox/paths.test.ts +1 -0
- package/src/sandbox/paths.ts +19 -8
- package/src/sandbox/registry.ts +20 -3
- package/src/sandbox/resolve.ts +76 -11
- package/src/sandbox/retry.test.ts +70 -0
- package/src/sandbox/retry.ts +46 -4
- package/src/sandbox/types.ts +44 -6
- package/src/sandbox/vercel.ts +43 -20
- package/src/scoring/collector.ts +60 -17
- package/src/scoring/coverage.ts +95 -0
- package/src/scoring/diff.ts +81 -0
- package/src/scoring/display.test.ts +121 -0
- package/src/scoring/display.ts +133 -0
- package/src/scoring/evidence.test.ts +189 -0
- package/src/scoring/judge.test.ts +142 -0
- package/src/scoring/judge.ts +15 -18
- package/src/scoring/scoped.ts +217 -50
- package/src/scoring/types.ts +117 -20
- package/src/scoring/verdict.ts +16 -4
- package/src/shared/aggregate.ts +3 -2
- package/src/shared/types.ts +31 -0
- package/src/show/compose.ts +2 -2
- package/src/show/index.ts +21 -1
- package/src/show/render.ts +619 -104
- package/src/show/show.test.ts +235 -19
- package/src/tty-line.ts +8 -26
- package/src/util.test.ts +1 -0
- package/src/util.ts +41 -0
- package/src/view/app/components/AttemptModal.tsx +153 -2
- package/src/view/app/components/CodeView.tsx +32 -11
- package/src/view/app/components/CopyControls.tsx +2 -2
- package/src/view/app/i18n.ts +6 -0
- package/src/view/app/lib/attempt-route.test.ts +1 -0
- package/src/view/app/lib/verdict.ts +7 -9
- package/src/view/artifact-serving.test.ts +2 -1
- package/src/view/client-dist/app.css +1 -1
- package/src/view/client-dist/app.js +17 -17
- package/src/view/data.test.ts +1 -0
- package/src/view/data.ts +11 -1
- package/src/view/index.ts +11 -0
- package/src/view/server.ts +2 -0
- package/src/view/styles.css +3 -0
- package/src/view/view-report.test.ts +6 -5
- package/src/runner/reporters/console.ts +0 -70
- package/src/runner/reporters/live.test.ts +0 -56
- package/src/runner/reporters/live.ts +0 -247
- package/src/runner/reporters/quiet.test.ts +0 -66
- package/src/runner/reporters/quiet.ts +0 -49
- package/src/runner/reporters/table.ts +0 -277
package/src/i18n/en.ts
CHANGED
|
@@ -14,6 +14,8 @@ export const en = {
|
|
|
14
14
|
"bub.installFailed": "bub install failed after {{attempts}} attempts:\n{{tail}}",
|
|
15
15
|
"bub.setupNotRun": "bub adapter setup() has not run in this sandbox (missing home/workspace info). The runner must call setup before send.",
|
|
16
16
|
"checkpoint.emptyTar": "checkpoint: tar is empty (paths: {{paths}})",
|
|
17
|
+
"checkpoint.archiveFailed": "checkpoint archive failed (exit {{exitCode}}): {{detail}}",
|
|
18
|
+
"checkpoint.restoreFailed": "checkpoint restore failed (exit {{exitCode}}): {{detail}}",
|
|
17
19
|
"skill.localMissing": "Local skill path \"{{path}}\" does not exist (resolved to {{resolved}}). Paths are resolved from the project root you run niceeval in.",
|
|
18
20
|
"skill.localDirNoSkillFile": "Local skill directory \"{{path}}\" has no SKILL.md. A directory-shaped skill must contain SKILL.md at its root.",
|
|
19
21
|
"skill.localUnsupportedShape": "Local skill path \"{{path}}\" has an unsupported shape. Accepted: a directory containing SKILL.md, or a single .md file.",
|
|
@@ -23,7 +25,21 @@ export const en = {
|
|
|
23
25
|
"skill.repoUnknownSkill": "Repo skill {{source}} (ref: {{ref}}) has no skill named \"{{skill}}\". Available: {{available}}.",
|
|
24
26
|
"skill.copyFailed": "Could not install skill \"{{name}}\" into {{dest}}:\n{{tail}}",
|
|
25
27
|
"plugin.marketplaceFailed": "Could not connect {{agent}} marketplace \"{{name}}\" (source: {{source}}, ref: {{ref}}):\n{{tail}}",
|
|
28
|
+
"plugin.marketplaceVerifyFailed": "Could not read back the registered marketplace list after adding {{agent}} marketplace \"{{name}}\" ({{command}}):\n{{tail}}",
|
|
29
|
+
"plugin.marketplaceNameMismatch":
|
|
30
|
+
"{{agent}} marketplace name mismatch: the configured name \"{{expected}}\" (source: {{source}}) is not in the registered list after add; actually registered: {{actual}}. " +
|
|
31
|
+
"marketplace.name must equal the name declared in the target repo's manifest — use the real name.",
|
|
26
32
|
"plugin.installFailed": "Could not install {{agent}} plugin \"{{name}}\" (marketplace: {{marketplace}}):\n{{tail}}",
|
|
33
|
+
"nativeConfig.pathNotProjectRelative":
|
|
34
|
+
"{{agent}} {{field}} only accepts relative paths inside the project root, got \"{{path}}\". Absolute paths, `..` segments and `~` paths are rejected; copy configs from outside the project into it first.",
|
|
35
|
+
"nativeConfig.missing":
|
|
36
|
+
"{{agent}} {{field}} points to a missing file: \"{{path}}\" (resolved to {{resolved}}). Paths resolve from the project root you run niceeval in (the directory containing niceeval.config.ts), not from eval / experiment source files.",
|
|
37
|
+
"nativeConfig.escapesRoot": "{{agent}} {{field}} \"{{path}}\" resolves through a symlink to outside the project root ({{resolved}}). The config file must physically live inside the project root.",
|
|
38
|
+
"nativeConfig.notFile": "{{agent}} {{field}} \"{{path}}\" is not a regular file. Point it at a complete official config file.",
|
|
39
|
+
"nativeConfig.invalidSyntax": "{{agent}} {{field}} \"{{path}}\" is not valid {{format}}: {{detail}}",
|
|
40
|
+
"nativeConfig.reservedKeys":
|
|
41
|
+
"{{agent}} {{field}} \"{{path}}\" contains reserved keys: {{keys}}. These keys are owned by the experiment and the Adapter (model, auth, MCP and OTel are layered separately) — remove them from the file.",
|
|
42
|
+
"nativeConfig.uploadFailed": "Could not upload native config file \"{{path}}\" into the sandbox ({{dest}}):\n{{tail}}",
|
|
27
43
|
"cli.all": "(all)",
|
|
28
44
|
"cli.browserOpenFailed": "Could not open the browser automatically. Open manually: {{url}}\n",
|
|
29
45
|
"cli.clean.done": "Deleted .niceeval/ historical run artifacts.\n",
|
|
@@ -39,6 +55,7 @@ export const en = {
|
|
|
39
55
|
"cli.dry.row": " {{who}}{{experiment}}: {{evals}} ×{{runs}}\n",
|
|
40
56
|
"cli.error": "niceeval error: {{error}}\n",
|
|
41
57
|
"cli.flag.invalidNumber": "Flag --{{flag}} expects a number, got \"{{value}}\".\n",
|
|
58
|
+
"cli.flag.invalidOutput": "Flag --output expects one of auto|human|agent|ci, got \"{{value}}\".\n",
|
|
42
59
|
"runner.budgetUnenforceable":
|
|
43
60
|
"budget for {{budgetKey}}: several attempts completed without any cost data (agent reports no usage and the model is not in the price table) — the budget cannot be enforced for this agent; continuing without the guard.\n",
|
|
44
61
|
"judge.modelMissing":
|
|
@@ -62,6 +79,7 @@ export const en = {
|
|
|
62
79
|
" assertions mapped back to source lines\n" +
|
|
63
80
|
" --execution this attempt's execution event stream (messages/thinking/\n" +
|
|
64
81
|
" Skill loads/tool calls); OTel adds timing to the same node when present\n" +
|
|
82
|
+
" --timing unified timing tree for the attempt (phases + hooks/commands/turns + per-turn OTel)\n" +
|
|
65
83
|
" --diff[=file] sandbox workspace file-change summary; =file expands one file\n" +
|
|
66
84
|
" --history cross-run timeline (mutually exclusive with --report)\n" +
|
|
67
85
|
" --run <dir> pin a results dir --experiment <id> one experiment\n" +
|
|
@@ -73,11 +91,13 @@ export const en = {
|
|
|
73
91
|
" --experiment <id> one experiment\n" +
|
|
74
92
|
" --out <dir> exports a static site: index.html plus the viewer\n" +
|
|
75
93
|
" artifacts, ready for any static host\n" +
|
|
94
|
+
" niceeval sandbox list|enter|history|diff|stop inspect & destroy sandboxes kept by --keep-sandbox\n" +
|
|
76
95
|
" niceeval clean delete .niceeval/ artifacts\n" +
|
|
77
96
|
" niceeval init scaffold config + evals/\n\n" +
|
|
78
97
|
"Flags:\n" +
|
|
79
98
|
" --runs n --max-concurrency n --timeout ms --budget usd --tag t\n" +
|
|
80
|
-
" --early-exit / --no-early-exit --strict --force --dry
|
|
99
|
+
" --early-exit / --no-early-exit --strict --force --dry\n" +
|
|
100
|
+
" --output auto|human|agent|ci\n" +
|
|
81
101
|
" --junit path --json path --out dir --port n --open / --no-open -h, --help -v, --version\n\n" +
|
|
82
102
|
"Positional args only select which evals to run (id prefixes); which agent and\n" +
|
|
83
103
|
"how to run come from experiments/ + flags. Env overrides (flag > env > config):\n" +
|
|
@@ -95,8 +115,11 @@ export const en = {
|
|
|
95
115
|
"cli.eval.noMatch": "No eval matched: {{patterns}}.\n",
|
|
96
116
|
"cli.eval.noMatchHintExperiment": "Hint: \"{{pattern}}\" is an experiment{{kind}}; you probably meant: niceeval exp {{pattern}}\n",
|
|
97
117
|
"cli.eval.noMatchKnown": "Discovered {{count}} evals: {{evals}}\n",
|
|
98
|
-
"cli.exp.agentModelFlagUnsupported": "
|
|
118
|
+
"cli.exp.agentModelFlagUnsupported": "experiment runs do not support --agent / --model. Add or copy an experiment file and change its model instead.\n",
|
|
119
|
+
"cli.exp.viewerFlagUnsupported": "`{{flag}}` only applies to niceeval {{command}}, not niceeval exp.\n",
|
|
99
120
|
"cli.experiment.noMatch": "No experiment matched: {{arg}}. Discovered: {{experiments}}\n",
|
|
121
|
+
"cli.experiment.viewerCommandHint": "Did you mean: niceeval {{command}}{{args}}\n",
|
|
122
|
+
"cli.experiment.noEvalsSelected": "No evals selected: {{selection}} matched 0 evals. Available experiments: {{experiments}}.\n",
|
|
100
123
|
"cli.experimentGroup": " group",
|
|
101
124
|
"cli.fallbackCleanupTimeout": "\ngraceful cleanup timed out; force-cleaning sandboxes...\n",
|
|
102
125
|
"cli.forceCleanupExit": "\nForce-cleaning sandboxes and exiting...\n",
|
|
@@ -128,6 +151,7 @@ export const en = {
|
|
|
128
151
|
"define.evalIdRejected": "defineEval does not accept id; ids are derived from file paths.",
|
|
129
152
|
"define.evalTestRequired": "defineEval requires an async test(t) function.",
|
|
130
153
|
"define.experimentAgentRequired": "defineExperiment requires agent.",
|
|
154
|
+
"define.experimentFlagNotJson": "experiment.flags.{{key}} is not JSON-serializable (functions / undefined / cycles / bigint are not allowed); flags are persisted verbatim into result snapshots and must be plain JSON.",
|
|
131
155
|
"define.experimentIdRejected": "defineExperiment does not accept id; ids are derived from file paths.",
|
|
132
156
|
"define.sandboxAgentNameRequired": "defineSandboxAgent requires name.",
|
|
133
157
|
"define.sandboxCreateRequired": "defineSandbox requires a create() function.",
|
|
@@ -138,6 +162,41 @@ export const en = {
|
|
|
138
162
|
"docker.imagePullStart": "Pulling Docker image: {{image}}...",
|
|
139
163
|
"docker.readFileFailed": "Failed to read file {{path}}: {{stderr}}",
|
|
140
164
|
"docker.unsupportedRuntime": "Unsupported runtime: {{runtime}}",
|
|
165
|
+
"feedback.human.active": "ACTIVE",
|
|
166
|
+
"feedback.human.budgetExhausted": "budget exhausted for {{experimentId}} (spent {{spent}}, unstarted {{unstarted}})",
|
|
167
|
+
"feedback.human.compare": "Compare: niceeval view {{group}}",
|
|
168
|
+
"feedback.human.counts": "{{total}} total · {{reused}} reused · {{running}} running · {{queued}} queued · {{completed}} completed",
|
|
169
|
+
"feedback.human.diffHint": "Diff: niceeval show {{locator}} --diff",
|
|
170
|
+
"feedback.human.evalHint": "Eval: niceeval show {{locator}} --eval",
|
|
171
|
+
"feedback.human.failuresHeader": "FAILURES",
|
|
172
|
+
"feedback.human.heartbeat": "{{elapsed}} elapsed · {{counts}}",
|
|
173
|
+
"feedback.human.inspect": "Inspect: niceeval show {{locator}}",
|
|
174
|
+
"feedback.human.moreActive": "… {{count}} more active",
|
|
175
|
+
"feedback.human.plan": "Plan: {{total}} attempts · {{evals}} evals × {{configs}} configs · concurrency {{concurrency}}",
|
|
176
|
+
"feedback.human.resultFailed": "FAILED",
|
|
177
|
+
"feedback.human.resultIncomplete": "INCOMPLETE",
|
|
178
|
+
"feedback.human.resultInterrupted": "INTERRUPTED",
|
|
179
|
+
"feedback.human.resultPassed": "PASSED",
|
|
180
|
+
"feedback.human.resultsHeader": "Results:",
|
|
181
|
+
"feedback.human.resultsMore": "… {{count}} more",
|
|
182
|
+
"feedback.human.reuse": "Reuse: {{reused}} of {{total}} carried in from cache · {{toRun}} to run",
|
|
183
|
+
"feedback.human.summaryLine": "{{passed}} passed · {{failed}} failed · {{errored}} errored ({{reused}} reused)",
|
|
184
|
+
"feedback.human.summaryAllReusedLine": "{{passed}} passed · {{failed}} failed · {{errored}} errored (all {{reused}} reused)",
|
|
185
|
+
"feedback.human.suppressedFailures": "… {{count}} more failures suppressed",
|
|
186
|
+
"feedback.human.trace": "Trace: niceeval show {{locator}} --execution",
|
|
187
|
+
"feedback.phase.agentSetup": "agent setup",
|
|
188
|
+
"feedback.phase.evalRun": "running eval",
|
|
189
|
+
"feedback.phase.evalSetup": "eval setup",
|
|
190
|
+
"feedback.phase.sandboxCreate": "creating sandbox",
|
|
191
|
+
"feedback.phase.sandboxQueue": "queued for sandbox",
|
|
192
|
+
"feedback.phase.sandboxSetup": "sandbox setup",
|
|
193
|
+
"feedback.phase.scoring": "scoring",
|
|
194
|
+
"feedback.phase.teardown": "cleaning up",
|
|
195
|
+
"feedback.phase.telemetryCollect": "collecting trace",
|
|
196
|
+
"feedback.phase.telemetryConfigure": "configuring telemetry",
|
|
197
|
+
"feedback.phase.workspaceBaseline": "preparing workspace",
|
|
198
|
+
"feedback.phase.workspaceDiff": "capturing diff",
|
|
199
|
+
"feedback.rendererError": " · [feedback] renderer failed while handling {{context}} (ignored): {{message}}\n",
|
|
141
200
|
"hitl.answerNeedsOptionOrText": "The object form of t.respond needs either optionId or text (neither was given).",
|
|
142
201
|
"hitl.invalidOption": "Answer \"{{optionId}}\" is not an option of request {{requestId}} ({{options}}).",
|
|
143
202
|
"hitl.noOptions": "this request has no options",
|
|
@@ -189,6 +248,7 @@ export const en = {
|
|
|
189
248
|
"otel.portInUse": "OTLP receiver port {{port}} is already in use (another process is bound to it). Pick a free port in defineConfig({ telemetry: { port } }), or stop whatever is using {{port}} and retry.",
|
|
190
249
|
"otel.windowAttribution": "otel: spans missing our traceparent, attributing by time window (turns for this agent serialized; concurrency resumes once W3C propagation is confirmed)",
|
|
191
250
|
"runner.diffProgress": "captured diff: {{changed}} changed / {{deleted}} deleted",
|
|
251
|
+
"runner.failFast": "error {{code}} recurred consecutively on {{evalId}}; treating it as deterministic and skipping the remaining attempts for this config (fail-fast).",
|
|
192
252
|
"runner.driveAgent": "driving agent...",
|
|
193
253
|
"runner.evalSetup": "eval setup (installing dependencies)...",
|
|
194
254
|
"runner.interrupted": " · interrupted: sandbox containers cleaned up; printing partial results completed so far.\n",
|
|
@@ -219,6 +279,8 @@ export const en = {
|
|
|
219
279
|
"sandbox.dependencyMissing.e2b": "E2B sandbox requires 'e2b'. Install it with: pnpm add e2b",
|
|
220
280
|
"sandbox.dependencyMissing.vercel": "Vercel sandbox requires '@vercel/sandbox'. Install it with: pnpm add @vercel/sandbox",
|
|
221
281
|
"sandbox.forceCleanup": " · [sandbox] force-cleaning {{count}} sandboxes...\n",
|
|
282
|
+
"sandbox.provisionReconcileFailed": " · [sandbox] provision reconcile failed, aborting retry (a possibly-created instance could not be verified/killed): {{error}}\n",
|
|
283
|
+
"sandbox.provisionRetry": " · [sandbox] provisioning rate-limited, retrying in {{delayMs}}ms (attempt {{attempt}}/{{maxAttempts}})...\n",
|
|
222
284
|
"sandbox.stopFailed": " · [sandbox] failed to stop sandbox {{id}} (ignored; provider TTL should clean it up): {{message}}\n",
|
|
223
285
|
"sandbox.stopTimeout": "stop timed out ({{timeoutMs}}ms)",
|
|
224
286
|
"scoring.evalError": "evaluation error: {{error}}",
|
package/src/i18n/zh-CN.ts
CHANGED
|
@@ -12,6 +12,8 @@ export const zhCN = {
|
|
|
12
12
|
"bub.installFailed": "bub 安装失败(重试 {{attempts}} 次):\n{{tail}}",
|
|
13
13
|
"bub.setupNotRun": "bub adapter 的 setup() 尚未在该沙箱运行(缺 home/workspace 信息);运行器应先调 setup 再 send。",
|
|
14
14
|
"checkpoint.emptyTar": "checkpoint: tar 为空(paths: {{paths}})",
|
|
15
|
+
"checkpoint.archiveFailed": "checkpoint 归档失败(exit {{exitCode}}): {{detail}}",
|
|
16
|
+
"checkpoint.restoreFailed": "checkpoint 恢复失败(exit {{exitCode}}): {{detail}}",
|
|
15
17
|
"skill.localMissing": "本地 skill 路径不存在:\"{{path}}\"(解析到 {{resolved}})。path 相对跑 niceeval 的项目根解析。",
|
|
16
18
|
"skill.localDirNoSkillFile": "本地 skill 目录 \"{{path}}\" 里没有 SKILL.md。目录形态的 skill 必须在根下带一个 SKILL.md。",
|
|
17
19
|
"skill.localUnsupportedShape": "本地 skill 路径 \"{{path}}\" 形态不支持。只接受:含 SKILL.md 的目录,或单个 .md 文件。",
|
|
@@ -21,7 +23,21 @@ export const zhCN = {
|
|
|
21
23
|
"skill.repoUnknownSkill": "repo skill {{source}}(ref: {{ref}})里没有名为 \"{{skill}}\" 的 skill。可选:{{available}}。",
|
|
22
24
|
"skill.copyFailed": "skill \"{{name}}\" 装进 {{dest}} 失败:\n{{tail}}",
|
|
23
25
|
"plugin.marketplaceFailed": "{{agent}} marketplace \"{{name}}\" 连接失败(source: {{source}}, ref: {{ref}}):\n{{tail}}",
|
|
26
|
+
"plugin.marketplaceVerifyFailed": "{{agent}} marketplace \"{{name}}\" add 后回读注册列表失败({{command}}):\n{{tail}}",
|
|
27
|
+
"plugin.marketplaceNameMismatch":
|
|
28
|
+
"{{agent}} marketplace 名不匹配:配置的 name \"{{expected}}\"(source: {{source}})不在 add 后回读的注册列表里,本次实际注册为:{{actual}}。" +
|
|
29
|
+
"marketplace.name 必须等于目标仓库 manifest 声明的 name,改成真实名字再跑。",
|
|
24
30
|
"plugin.installFailed": "{{agent}} plugin \"{{name}}\"(marketplace: {{marketplace}})安装失败:\n{{tail}}",
|
|
31
|
+
"nativeConfig.pathNotProjectRelative":
|
|
32
|
+
"{{agent}} {{field}} 只接受项目根内的相对路径,收到 \"{{path}}\"。绝对路径、包含 `..` 的路径和 `~` 路径都不行;项目根外的配置先复制进项目再引用。",
|
|
33
|
+
"nativeConfig.missing":
|
|
34
|
+
"{{agent}} {{field}} 指向的文件不存在:\"{{path}}\"(解析到 {{resolved}})。路径相对运行 niceeval 的项目根(含 niceeval.config.ts 的目录)解析,不相对 eval / experiment 源码文件。",
|
|
35
|
+
"nativeConfig.escapesRoot": "{{agent}} {{field}} \"{{path}}\" 经符号链接解析到项目根之外({{resolved}})。配置文件必须真实位于项目根内。",
|
|
36
|
+
"nativeConfig.notFile": "{{agent}} {{field}} \"{{path}}\" 不是普通文件。指向一份完整的官方配置文件。",
|
|
37
|
+
"nativeConfig.invalidSyntax": "{{agent}} {{field}} \"{{path}}\" 不是合法的 {{format}}:{{detail}}",
|
|
38
|
+
"nativeConfig.reservedKeys":
|
|
39
|
+
"{{agent}} {{field}} \"{{path}}\" 含保留键:{{keys}}。这些键由 experiment 与 Adapter 拥有(model、鉴权、MCP、OTel 经独立配置层叠加),从文件里删掉再跑。",
|
|
40
|
+
"nativeConfig.uploadFailed": "原生配置文件 \"{{path}}\" 上传沙箱失败({{dest}}):\n{{tail}}",
|
|
25
41
|
"cli.all": "(全部)",
|
|
26
42
|
"cli.browserOpenFailed": "无法自动打开浏览器,请手动访问:{{url}}\n",
|
|
27
43
|
"cli.clean.done": "已删除 .niceeval/ 历史运行 artifact。\n",
|
|
@@ -37,6 +53,7 @@ export const zhCN = {
|
|
|
37
53
|
"cli.dry.row": " {{who}}{{experiment}}: {{evals}} ×{{runs}}\n",
|
|
38
54
|
"cli.error": "niceeval 出错:{{error}}\n",
|
|
39
55
|
"cli.flag.invalidNumber": "标志 --{{flag}} 需要数字,收到 \"{{value}}\"。\n",
|
|
56
|
+
"cli.flag.invalidOutput": "标志 --output 需要 auto|human|agent|ci 之一,收到 \"{{value}}\"。\n",
|
|
40
57
|
"runner.budgetUnenforceable":
|
|
41
58
|
"{{budgetKey}} 的 budget:连续多个 attempt 完成后都拿不到成本数据(agent 不上报用量且模型不在价格表)——该 agent 的 budget 无法执行,取消护栏继续跑。\n",
|
|
42
59
|
"judge.modelMissing":
|
|
@@ -58,7 +75,8 @@ export const zhCN = {
|
|
|
58
75
|
" --eval 该 attempt 运行时保存的 Eval 源码,断言标回源码行\n" +
|
|
59
76
|
" --execution 该 attempt 的执行事件流(消息/thinking/Skill/工具调用),\n" +
|
|
60
77
|
" 有 OTel 时同一节点补时间\n" +
|
|
61
|
-
" --
|
|
78
|
+
" --timing 整个 attempt 的统一时间树(阶段 + hook/命令/turn + 轮内 OTel)\n" +
|
|
79
|
+
" --diff[=文件] agent 归因的文件改动摘要;=文件 按窗口展开单个文件\n" +
|
|
62
80
|
" --history 跨 run 时间轴(与 --report 互斥)\n" +
|
|
63
81
|
" --run <目录> 钉死结果目录 --experiment <id> 只看该实验\n" +
|
|
64
82
|
" --report <文件> 自定义报告\n" +
|
|
@@ -67,11 +85,13 @@ export const zhCN = {
|
|
|
67
85
|
" 报告槽 + 证据室;--report <文件> 整槽换成自定义报告(与 show 同一文件)\n" +
|
|
68
86
|
" --run <目录> 钉死结果目录 --experiment <id> 只看该实验\n" +
|
|
69
87
|
" --out <目录> 静态导出:index.html 连同查看器 artifact,可直接静态托管\n" +
|
|
88
|
+
" niceeval sandbox list|enter|history|diff|stop 查看与销毁 --keep-sandbox 留下的现场\n" +
|
|
70
89
|
" niceeval clean 删除 .niceeval/ 历史 artifact\n" +
|
|
71
90
|
" niceeval init 脚手架 config + evals/\n\n" +
|
|
72
91
|
"标志:\n" +
|
|
73
92
|
" --runs n --max-concurrency n --timeout ms --budget usd --tag t\n" +
|
|
74
|
-
" --early-exit / --no-early-exit --strict --force --dry --
|
|
93
|
+
" --early-exit / --no-early-exit --strict --force --dry --keep-sandbox[=failed|all]\n" +
|
|
94
|
+
" --output auto|human|agent|ci\n" +
|
|
75
95
|
" --junit path --json path --out dir --port n --open / --no-open -h, --help -v, --version\n\n" +
|
|
76
96
|
"位置参数只选「跑哪些 eval」(id 前缀);对着哪个 agent、怎么跑来自 experiments/ 与\n" +
|
|
77
97
|
"标志。环境变量覆盖(标志 > 环境变量 > config):\n" +
|
|
@@ -90,8 +110,11 @@ export const zhCN = {
|
|
|
90
110
|
"cli.eval.noMatch": "没有匹配的 eval:{{patterns}}。\n",
|
|
91
111
|
"cli.eval.noMatchHintExperiment": "提示:\"{{pattern}}\" 是实验{{kind}},你大概想跑:niceeval exp {{pattern}}\n",
|
|
92
112
|
"cli.eval.noMatchKnown": "已发现 {{count}} 个 eval:{{evals}}\n",
|
|
93
|
-
"cli.exp.agentModelFlagUnsupported": "
|
|
113
|
+
"cli.exp.agentModelFlagUnsupported": "experiment 运行不支持 --agent / --model。请新增或复制一个 experiment 文件并修改 model。\n",
|
|
114
|
+
"cli.exp.viewerFlagUnsupported": "`{{flag}}` 只适用于 niceeval {{command}},不能用于 niceeval exp。\n",
|
|
94
115
|
"cli.experiment.noMatch": "没有匹配的实验:{{arg}}。已发现:{{experiments}}\n",
|
|
116
|
+
"cli.experiment.viewerCommandHint": "你可能想运行:niceeval {{command}}{{args}}\n",
|
|
117
|
+
"cli.experiment.noEvalsSelected": "未选择任何 eval:{{selection}} 匹配到 0 个 eval。可用实验:{{experiments}}。\n",
|
|
95
118
|
"cli.experimentGroup": "组",
|
|
96
119
|
"cli.fallbackCleanupTimeout": "\ngraceful 清理超时,强制清理沙箱…\n",
|
|
97
120
|
"cli.forceCleanupExit": "\n强制清理沙箱并退出…\n",
|
|
@@ -123,6 +146,7 @@ export const zhCN = {
|
|
|
123
146
|
"define.evalIdRejected": "defineEval 不接受 id —— id 由文件路径推导。",
|
|
124
147
|
"define.evalTestRequired": "defineEval 需要一个 async test(t) 函数。",
|
|
125
148
|
"define.experimentAgentRequired": "defineExperiment 需要 agent。",
|
|
149
|
+
"define.experimentFlagNotJson": "experiment.flags.{{key}} 不是可 JSON 序列化的值(函数 / undefined / 循环引用 / bigint 不允许);flags 会原样进入结果快照,必须是纯 JSON。",
|
|
126
150
|
"define.experimentIdRejected": "defineExperiment 不接受 id —— id 由文件路径推导。",
|
|
127
151
|
"define.sandboxAgentNameRequired": "defineSandboxAgent 需要 name。",
|
|
128
152
|
"define.sandboxCreateRequired": "defineSandbox 需要一个 create() 函数。",
|
|
@@ -133,6 +157,41 @@ export const zhCN = {
|
|
|
133
157
|
"docker.imagePullStart": "Pulling Docker image: {{image}}...",
|
|
134
158
|
"docker.readFileFailed": "Failed to read file {{path}}: {{stderr}}",
|
|
135
159
|
"docker.unsupportedRuntime": "Unsupported runtime: {{runtime}}",
|
|
160
|
+
"feedback.human.active": "ACTIVE",
|
|
161
|
+
"feedback.human.budgetExhausted": "{{experimentId}} 预算已耗尽(已花 {{spent}},未跑 {{unstarted}})",
|
|
162
|
+
"feedback.human.compare": "Compare: niceeval view {{group}}",
|
|
163
|
+
"feedback.human.counts": "共 {{total}} · 复用 {{reused}} · 运行中 {{running}} · 排队 {{queued}} · 已完成 {{completed}}",
|
|
164
|
+
"feedback.human.diffHint": "Diff: niceeval show {{locator}} --diff",
|
|
165
|
+
"feedback.human.evalHint": "Eval: niceeval show {{locator}} --eval",
|
|
166
|
+
"feedback.human.failuresHeader": "FAILURES",
|
|
167
|
+
"feedback.human.heartbeat": "已运行 {{elapsed}} · {{counts}}",
|
|
168
|
+
"feedback.human.inspect": "Inspect: niceeval show {{locator}}",
|
|
169
|
+
"feedback.human.moreActive": "… 还有 {{count}} 项运行中",
|
|
170
|
+
"feedback.human.plan": "计划:{{total}} 个 attempt · {{evals}} 个 eval × {{configs}} 个配置 · 并发 {{concurrency}}",
|
|
171
|
+
"feedback.human.resultFailed": "FAILED",
|
|
172
|
+
"feedback.human.resultIncomplete": "INCOMPLETE",
|
|
173
|
+
"feedback.human.resultInterrupted": "INTERRUPTED",
|
|
174
|
+
"feedback.human.resultPassed": "PASSED",
|
|
175
|
+
"feedback.human.resultsHeader": "Results:",
|
|
176
|
+
"feedback.human.resultsMore": "… 还有 {{count}} 个",
|
|
177
|
+
"feedback.human.reuse": "复用:{{total}} 中 {{reused}} 条来自缓存 · {{toRun}} 待跑",
|
|
178
|
+
"feedback.human.summaryLine": "{{passed}} 通过 · {{failed}} 失败 · {{errored}} 出错 (复用 {{reused}})",
|
|
179
|
+
"feedback.human.summaryAllReusedLine": "{{passed}} 通过 · {{failed}} 失败 · {{errored}} 出错 (全部 {{reused}} 条复用)",
|
|
180
|
+
"feedback.human.suppressedFailures": "… 还有 {{count}} 条失败被折叠",
|
|
181
|
+
"feedback.human.trace": "Trace: niceeval show {{locator}} --execution",
|
|
182
|
+
"feedback.phase.agentSetup": "agent 预置",
|
|
183
|
+
"feedback.phase.evalRun": "运行 eval",
|
|
184
|
+
"feedback.phase.evalSetup": "eval 预置",
|
|
185
|
+
"feedback.phase.sandboxCreate": "创建沙箱",
|
|
186
|
+
"feedback.phase.sandboxQueue": "排队等沙箱",
|
|
187
|
+
"feedback.phase.sandboxSetup": "沙箱预置",
|
|
188
|
+
"feedback.phase.scoring": "评分",
|
|
189
|
+
"feedback.phase.teardown": "清理中",
|
|
190
|
+
"feedback.phase.telemetryCollect": "收集 trace",
|
|
191
|
+
"feedback.phase.telemetryConfigure": "配置 telemetry",
|
|
192
|
+
"feedback.phase.workspaceBaseline": "准备工作区",
|
|
193
|
+
"feedback.phase.workspaceDiff": "采集 diff",
|
|
194
|
+
"feedback.rendererError": " · [feedback] renderer 处理 {{context}} 失败(已忽略):{{message}}\n",
|
|
136
195
|
"hitl.answerNeedsOptionOrText": "t.respond 的对象形式需要 optionId 或 text 二选一(两者都没给)。",
|
|
137
196
|
"hitl.invalidOption": "回答 \"{{optionId}}\" 不是请求 {{requestId}} 的可选项({{options}})。",
|
|
138
197
|
"hitl.noOptions": "该请求没有可选项",
|
|
@@ -184,6 +243,7 @@ export const zhCN = {
|
|
|
184
243
|
"otel.portInUse": "OTLP 接收端口 {{port}} 已被占用(另一个进程占着这个端口)。在 defineConfig({ telemetry: { port } }) 里换一个空闲端口,或者停掉占用 {{port}} 的进程后重试。",
|
|
185
244
|
"otel.windowAttribution": "otel:span 未带本轮 traceparent,按时间窗口归属(该 agent 的轮次已串行;应用支持 W3C 传播后自动并发)",
|
|
186
245
|
"runner.diffProgress": "采 diff:{{changed}} 改 / {{deleted}} 删",
|
|
246
|
+
"runner.failFast": "{{evalId}} 的错误 {{code}} 连续复现,判定为确定性错误;停止派发该配置剩余的 attempt(fail-fast)。",
|
|
187
247
|
"runner.driveAgent": "驱动 agent…",
|
|
188
248
|
"runner.evalSetup": "eval setup(装依赖)…",
|
|
189
249
|
"runner.interrupted": " · 已中断:沙箱容器已清理,输出本次已完成的部分结果。\n",
|
|
@@ -214,6 +274,8 @@ export const zhCN = {
|
|
|
214
274
|
"sandbox.dependencyMissing.e2b": "E2B sandbox requires 'e2b'. Install it with: pnpm add e2b",
|
|
215
275
|
"sandbox.dependencyMissing.vercel": "Vercel sandbox requires '@vercel/sandbox'. Install it with: pnpm add @vercel/sandbox",
|
|
216
276
|
"sandbox.forceCleanup": " · [sandbox] 强制清理 {{count}} 个沙箱…\n",
|
|
277
|
+
"sandbox.provisionReconcileFailed": " · [sandbox] 创建重试前对账失败,放弃重试(可能已创建的实例无法核实/销毁):{{error}}\n",
|
|
278
|
+
"sandbox.provisionRetry": " · [sandbox] 创建被限流,{{delayMs}}ms 后重试(第 {{attempt}}/{{maxAttempts}} 次)…\n",
|
|
217
279
|
"sandbox.stopFailed": " · [sandbox] 停沙箱 {{id}} 失败(已忽略,靠 provider 过期兜底):{{message}}\n",
|
|
218
280
|
"sandbox.stopTimeout": "stop 超时({{timeoutMs}}ms)",
|
|
219
281
|
"scoring.evalError": "评估出错: {{error}}",
|
package/src/o11y/cost.test.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// cases: docs/engineering/unit-tests/adapters/cases.md
|
|
1
2
|
// buildExecutionTree 的单测(定稿见 docs/observability.md「OTLP traces → 统一瀑布图」、
|
|
2
3
|
// docs/concepts.md「执行树」词条)。覆盖:无 OTel 时骨架完整、有 OTel 时按 callId 精确合并、
|
|
3
4
|
// 唯一关联不上时降级成 telemetry-only 节点(不猜)、同 callId 撞多条 span 时不強行择一、
|
|
@@ -147,18 +148,6 @@ describe("buildExecutionTree", () => {
|
|
|
147
148
|
expect(Object.keys(tree.nodes[0].span?.attributes ?? {})).toEqual(["call_id"]);
|
|
148
149
|
});
|
|
149
150
|
|
|
150
|
-
it("correlates a subagent node the same way as an action node", () => {
|
|
151
|
-
const events: StreamEvent[] = [
|
|
152
|
-
{ type: "subagent.called", callId: "s1", name: "Task" },
|
|
153
|
-
{ type: "subagent.completed", callId: "s1", output: "done", status: "completed" },
|
|
154
|
-
];
|
|
155
|
-
const agentSpan = span({ spanId: "sp1", attributes: { call_id: "s1" } });
|
|
156
|
-
|
|
157
|
-
const tree = buildExecutionTree(events, [agentSpan]);
|
|
158
|
-
|
|
159
|
-
expect(tree.nodes[0]).toMatchObject({ kind: "subagent", callId: "s1", span: agentSpan });
|
|
160
|
-
});
|
|
161
|
-
|
|
162
151
|
it("never guesses by name/text: a span whose call_id matches no node becomes a telemetry-only node, and the skeleton node's span stays absent", () => {
|
|
163
152
|
const events: StreamEvent[] = [
|
|
164
153
|
{ type: "action.called", callId: "c1", name: "Bash", input: {}, tool: "shell" },
|
|
@@ -252,14 +241,6 @@ describe("buildExecutionTree", () => {
|
|
|
252
241
|
expect(action.span?.status).toBe("error");
|
|
253
242
|
});
|
|
254
243
|
|
|
255
|
-
it("skill.loaded is a first-class node carrying the skill name (and optional callId), never a generic action", () => {
|
|
256
|
-
const events: StreamEvent[] = [{ type: "skill.loaded", skill: "pdf-processing", callId: "tool_1" }];
|
|
257
|
-
|
|
258
|
-
const tree = buildExecutionTree(events, []);
|
|
259
|
-
|
|
260
|
-
expect(tree.nodes).toEqual([{ id: "skill-0", kind: "skill.loaded", skill: "pdf-processing", callId: "tool_1" }]);
|
|
261
|
-
});
|
|
262
|
-
|
|
263
244
|
it("a skill.loaded node passes through immediately as its own node — it has no result event to pair with, so it never gets stuck 'pending' the way action/subagent nodes do while awaiting a result", () => {
|
|
264
245
|
const events: StreamEvent[] = [
|
|
265
246
|
{ type: "action.called", callId: "c1", name: "Bash", input: {}, tool: "shell" },
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// cases: docs/engineering/unit-tests/adapters/cases.md
|
|
1
2
|
// claude-code transcript 解析器单测。
|
|
2
3
|
//
|
|
3
4
|
// 重点覆盖 Skill 加载识别(定稿见 docs/observability.md「OTLP traces → 统一瀑布图」、
|
|
@@ -40,14 +41,6 @@ describe("parseClaudeCodeTranscript — Skill 加载", () => {
|
|
|
40
41
|
expect(events).toEqual([{ type: "skill.loaded", skill: "ms-office-suite:pdf", callId: "toolu_02" }]);
|
|
41
42
|
});
|
|
42
43
|
|
|
43
|
-
it("工具名大小写不定也能识别(防御性小写比较)", () => {
|
|
44
|
-
const raw = toolUseLine({ id: "toolu_03", name: "skill", input: { skill: "xlsx" } });
|
|
45
|
-
|
|
46
|
-
const { events } = parseClaudeCodeTranscript(raw);
|
|
47
|
-
|
|
48
|
-
expect(events).toEqual([{ type: "skill.loaded", skill: "xlsx", callId: "toolu_03" }]);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
44
|
it("Skill 加载的 tool_result 被吃掉,不补发孤儿 action.result", () => {
|
|
52
45
|
const raw = [
|
|
53
46
|
toolUseLine({ id: "toolu_01", name: "Skill", input: { skill: "pdf" } }),
|
|
@@ -75,20 +68,6 @@ describe("parseClaudeCodeTranscript — Skill 加载", () => {
|
|
|
75
68
|
]);
|
|
76
69
|
});
|
|
77
70
|
|
|
78
|
-
it("普通(非 Skill)工具调用完全不受影响:Bash 仍产出 action.called + action.result,顺序不变", () => {
|
|
79
|
-
const raw = [
|
|
80
|
-
toolUseLine({ id: "toolu_06", name: "Bash", input: { command: "ls" } }),
|
|
81
|
-
toolResultLine("toolu_06", "a.ts\nb.ts", false),
|
|
82
|
-
].join("\n");
|
|
83
|
-
|
|
84
|
-
const { events } = parseClaudeCodeTranscript(raw);
|
|
85
|
-
|
|
86
|
-
expect(events).toEqual([
|
|
87
|
-
{ type: "action.called", callId: "toolu_06", name: "Bash", input: { command: "ls" }, tool: "shell" },
|
|
88
|
-
{ type: "action.result", callId: "toolu_06", output: "a.ts\nb.ts", status: "completed" },
|
|
89
|
-
]);
|
|
90
|
-
});
|
|
91
|
-
|
|
92
71
|
it("Skill 加载与普通工具调用混合出现时,各自独立、顺序保持事件出现顺序", () => {
|
|
93
72
|
const raw = [
|
|
94
73
|
toolUseLine({ id: "t1", name: "Skill", input: { skill: "pdf" } }),
|
|
@@ -106,18 +85,6 @@ describe("parseClaudeCodeTranscript — Skill 加载", () => {
|
|
|
106
85
|
]);
|
|
107
86
|
});
|
|
108
87
|
|
|
109
|
-
it("Read/Write/Edit/WebFetch/WebSearch/Task 等既有别名归一不受 Skill 识别改动影响(回归锁)", () => {
|
|
110
|
-
const raw = [
|
|
111
|
-
toolUseLine({ id: "a", name: "Write", input: { file_path: "/x", content: "y" } }),
|
|
112
|
-
toolUseLine({ id: "b", name: "Task", input: { prompt: "go" } }),
|
|
113
|
-
toolUseLine({ id: "c", name: "WebSearch", input: { query: "q" } }),
|
|
114
|
-
].join("\n");
|
|
115
|
-
|
|
116
|
-
const { events } = parseClaudeCodeTranscript(raw);
|
|
117
|
-
const tools = events.filter((e) => e.type === "action.called").map((e) => (e as { tool?: string }).tool);
|
|
118
|
-
|
|
119
|
-
expect(tools).toEqual(["file_write", "agent_task", "web_search"]);
|
|
120
|
-
});
|
|
121
88
|
});
|
|
122
89
|
|
|
123
90
|
describe("parseClaudeCodeTranscript — 既有行为回归", () => {
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// cases: docs/engineering/unit-tests/adapters/cases.md
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
|
|
4
|
+
import { parseOpenClawTranscript, parseOpenClaw, parseOpenClawRunJson } from "./openclaw.ts";
|
|
5
|
+
|
|
6
|
+
function jsonl(lines: unknown[]): string {
|
|
7
|
+
return lines.map((l) => JSON.stringify(l)).join("\n");
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
describe("parseOpenClawTranscript", () => {
|
|
11
|
+
it("空 / 无内容 → 空事件流,parseSuccess true", () => {
|
|
12
|
+
expect(parseOpenClawTranscript(undefined)).toEqual({
|
|
13
|
+
events: [],
|
|
14
|
+
usage: { inputTokens: 0, outputTokens: 0 },
|
|
15
|
+
compactions: 0,
|
|
16
|
+
parseSuccess: true,
|
|
17
|
+
});
|
|
18
|
+
expect(parseOpenClawTranscript(" \n ").events).toEqual([]);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("assistant 的 text/thinking/toolCall parts + toolResult 按 call ID 配对,usage 逐消息累加", () => {
|
|
22
|
+
const raw = jsonl([
|
|
23
|
+
{ role: "user", content: "改一下配置" },
|
|
24
|
+
{
|
|
25
|
+
role: "assistant",
|
|
26
|
+
content: [
|
|
27
|
+
{ type: "thinking", thinking: "先看文件" },
|
|
28
|
+
{ type: "text", text: "我来改" },
|
|
29
|
+
{ type: "toolCall", id: "tc_1", name: "read", arguments: { path: "a.ts" } },
|
|
30
|
+
],
|
|
31
|
+
usage: { input: 100, output: 20, cacheRead: 5, cacheWrite: 3, cost: { total: 0.01 } },
|
|
32
|
+
},
|
|
33
|
+
{ role: "toolResult", toolCallId: "tc_1", content: [{ type: "text", text: "file body" }], isError: false },
|
|
34
|
+
{
|
|
35
|
+
role: "assistant",
|
|
36
|
+
content: [{ type: "text", text: "改好了" }],
|
|
37
|
+
usage: { input: 50, output: 10, cacheRead: 0, cacheWrite: 0, cost: { total: 0.002 } },
|
|
38
|
+
},
|
|
39
|
+
]);
|
|
40
|
+
|
|
41
|
+
const parsed = parseOpenClawTranscript(raw);
|
|
42
|
+
expect(parsed.events).toEqual([
|
|
43
|
+
{ type: "message", role: "user", text: "改一下配置" },
|
|
44
|
+
{ type: "thinking", text: "先看文件" },
|
|
45
|
+
{ type: "message", role: "assistant", text: "我来改" },
|
|
46
|
+
{ type: "action.called", callId: "tc_1", name: "read", input: { path: "a.ts" }, tool: "file_read" },
|
|
47
|
+
{ type: "action.result", callId: "tc_1", output: "file body", status: "completed" },
|
|
48
|
+
{ type: "message", role: "assistant", text: "改好了" },
|
|
49
|
+
]);
|
|
50
|
+
expect(parsed.usage).toEqual({
|
|
51
|
+
inputTokens: 150,
|
|
52
|
+
outputTokens: 30,
|
|
53
|
+
cacheReadTokens: 5,
|
|
54
|
+
cacheWriteTokens: 3,
|
|
55
|
+
requests: 2,
|
|
56
|
+
costUSD: 0.012,
|
|
57
|
+
});
|
|
58
|
+
expect(parsed.parseSuccess).toBe(true);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("{ type: 'message', message: {...} } 包装条目与 snake_case 变体也认", () => {
|
|
62
|
+
const raw = jsonl([
|
|
63
|
+
{
|
|
64
|
+
type: "message",
|
|
65
|
+
message: {
|
|
66
|
+
role: "assistant",
|
|
67
|
+
content: [{ type: "tool_call", tool_call_id: "c9", toolName: "exec", input: { cmd: "ls" } }],
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
{ type: "message", message: { role: "tool", tool_call_id: "c9", output: "a.txt", is_error: true } },
|
|
71
|
+
]);
|
|
72
|
+
expect(parseOpenClaw(raw)).toEqual([
|
|
73
|
+
{ type: "action.called", callId: "c9", name: "exec", input: { cmd: "ls" }, tool: "shell" },
|
|
74
|
+
{ type: "action.result", callId: "c9", output: "a.txt", status: "failed" },
|
|
75
|
+
]);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("compaction 条目计数,error 条目落 error 事件", () => {
|
|
79
|
+
const parsed = parseOpenClawTranscript(
|
|
80
|
+
jsonl([
|
|
81
|
+
{ type: "compaction", reason: "context-limit" },
|
|
82
|
+
{ type: "error", message: "boom" },
|
|
83
|
+
]),
|
|
84
|
+
);
|
|
85
|
+
expect(parsed.events).toEqual([
|
|
86
|
+
{ type: "compaction", reason: "context-limit" },
|
|
87
|
+
{ type: "error", message: "boom" },
|
|
88
|
+
]);
|
|
89
|
+
expect(parsed.compactions).toBe(1);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("坏 JSON 行不中断解析,标 parseSuccess: false 但保留其余行的事件", () => {
|
|
93
|
+
const raw = `{"role":"assistant","content":[{"type":"text","text":"hi"}]}\nnot-json\n`;
|
|
94
|
+
const parsed = parseOpenClawTranscript(raw);
|
|
95
|
+
expect(parsed.parseSuccess).toBe(false);
|
|
96
|
+
expect(parsed.events).toEqual([{ type: "message", role: "assistant", text: "hi" }]);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("字符串形态的 arguments 先按 JSON 解;解不开原样保留", () => {
|
|
100
|
+
const raw = jsonl([
|
|
101
|
+
{
|
|
102
|
+
role: "assistant",
|
|
103
|
+
content: [{ type: "toolCall", id: "c1", name: "write", arguments: '{"path":"b.ts"}' }],
|
|
104
|
+
},
|
|
105
|
+
]);
|
|
106
|
+
expect(parseOpenClaw(raw)).toEqual([
|
|
107
|
+
{ type: "action.called", callId: "c1", name: "write", input: { path: "b.ts" }, tool: "file_write" },
|
|
108
|
+
]);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
describe("parseOpenClawRunJson", () => {
|
|
113
|
+
it("整段 pretty-print JSON 封包:text / sessionId / usage / failed", () => {
|
|
114
|
+
const stdout = JSON.stringify(
|
|
115
|
+
{
|
|
116
|
+
sessionId: "sess-42",
|
|
117
|
+
result: { text: "done" },
|
|
118
|
+
usage: { input_tokens: 10, output_tokens: 3 },
|
|
119
|
+
status: "ok",
|
|
120
|
+
},
|
|
121
|
+
null,
|
|
122
|
+
2,
|
|
123
|
+
);
|
|
124
|
+
expect(parseOpenClawRunJson(stdout)).toEqual({
|
|
125
|
+
text: "done",
|
|
126
|
+
sessionId: "sess-42",
|
|
127
|
+
usage: { inputTokens: 10, outputTokens: 3 },
|
|
128
|
+
failed: false,
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("混日志行的 stdout:取最后一个完整 JSON 对象;payloads[].text 拼接", () => {
|
|
133
|
+
const stdout = [
|
|
134
|
+
"starting agent...",
|
|
135
|
+
JSON.stringify({ payloads: [{ text: "第一段" }, { text: "第二段" }], sessionKey: "k1" }),
|
|
136
|
+
].join("\n");
|
|
137
|
+
expect(parseOpenClawRunJson(stdout)).toEqual({
|
|
138
|
+
text: "第一段\n第二段",
|
|
139
|
+
sessionId: "k1",
|
|
140
|
+
failed: false,
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it("error 字段 / status=error / success=false → failed", () => {
|
|
145
|
+
expect(parseOpenClawRunJson(JSON.stringify({ error: "rate limited" })).failed).toBe(true);
|
|
146
|
+
expect(parseOpenClawRunJson(JSON.stringify({ status: "error" })).failed).toBe(true);
|
|
147
|
+
expect(parseOpenClawRunJson(JSON.stringify({ success: false })).failed).toBe(true);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it("解析不出 JSON → 空摘要,failed 交给调用方 exitCode", () => {
|
|
151
|
+
expect(parseOpenClawRunJson("plain text output")).toEqual({ failed: false });
|
|
152
|
+
expect(parseOpenClawRunJson(undefined)).toEqual({ failed: false });
|
|
153
|
+
});
|
|
154
|
+
});
|