stageflow 0.40.0 → 0.42.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 (326) hide show
  1. package/README.md +3 -1
  2. package/dist/agents/authorChat.d.ts +4 -0
  3. package/dist/agents/authorChat.js +113 -12
  4. package/dist/agents/authorSessionStore.d.ts +35 -0
  5. package/dist/agents/authorSessionStore.js +152 -0
  6. package/dist/agents/chatTurn.d.ts +2 -0
  7. package/dist/agents/chatTurn.js +17 -1
  8. package/dist/agents/errors.d.ts +1 -1
  9. package/dist/agents/errors.js +1 -0
  10. package/dist/agents/evalGate.d.ts +61 -0
  11. package/dist/agents/evalGate.js +103 -0
  12. package/dist/agents/evalSession.d.ts +26 -0
  13. package/dist/agents/evalSession.js +29 -0
  14. package/dist/agents/hostContext.d.ts +3 -0
  15. package/dist/agents/hostContext.js +4 -1
  16. package/dist/agents/runtime/piRuntime.d.ts +1 -1
  17. package/dist/agents/runtime/piRuntime.js +4 -4
  18. package/dist/agents/runtime/types.d.ts +3 -1
  19. package/dist/agents/service.d.ts +27 -2
  20. package/dist/agents/service.js +88 -13
  21. package/dist/agents/sessions.d.ts +8 -0
  22. package/dist/agents/sessions.js +50 -10
  23. package/dist/agents/store.d.ts +14 -3
  24. package/dist/agents/store.js +45 -7
  25. package/dist/agents/toolRisk.d.ts +21 -0
  26. package/dist/agents/toolRisk.js +50 -0
  27. package/dist/cli/doctorCommand.js +26 -0
  28. package/dist/cli/evalCommand.d.ts +20 -0
  29. package/dist/cli/evalCommand.js +720 -0
  30. package/dist/cli/exportAllCommand.js +1 -1
  31. package/dist/cli/hostClient.d.ts +60 -0
  32. package/dist/cli/hostClient.js +71 -0
  33. package/dist/cli/validateOutput.d.ts +2 -2
  34. package/dist/cli/validateOutput.js +2 -2
  35. package/dist/cli.js +10 -0
  36. package/dist/config/atomicWrite.d.ts +15 -0
  37. package/dist/config/atomicWrite.js +43 -0
  38. package/dist/config/browseCatalog.d.ts +2 -0
  39. package/dist/config/browseCatalog.js +4 -2
  40. package/dist/config/csv.d.ts +9 -0
  41. package/dist/config/csv.js +81 -0
  42. package/dist/config/datasetAgentCheck.d.ts +18 -0
  43. package/dist/config/datasetAgentCheck.js +109 -0
  44. package/dist/config/datasetCandidates.d.ts +22 -0
  45. package/dist/config/datasetCandidates.js +86 -0
  46. package/dist/config/datasetFromSessions.d.ts +34 -0
  47. package/dist/config/datasetFromSessions.js +105 -0
  48. package/dist/config/datasetHash.d.ts +1 -0
  49. package/dist/config/datasetHash.js +4 -0
  50. package/dist/config/datasetImport.d.ts +21 -0
  51. package/dist/config/datasetImport.js +120 -0
  52. package/dist/config/datasetStageCheck.d.ts +9 -0
  53. package/dist/config/datasetStageCheck.js +17 -0
  54. package/dist/config/datasetTypes.d.ts +27 -0
  55. package/dist/config/datasetTypes.js +1 -0
  56. package/dist/config/ensureCatalogScanRoot.d.ts +2 -1
  57. package/dist/config/ensureCatalogScanRoot.js +2 -6
  58. package/dist/config/evalCatalog.d.ts +22 -0
  59. package/dist/config/evalCatalog.js +67 -0
  60. package/dist/config/evalWriteRoots.d.ts +17 -0
  61. package/dist/config/evalWriteRoots.js +109 -0
  62. package/dist/config/hostConfig.js +1 -0
  63. package/dist/config/installEvalSample.d.ts +34 -0
  64. package/dist/config/installEvalSample.js +182 -0
  65. package/dist/config/loadDataset.d.ts +16 -0
  66. package/dist/config/loadDataset.js +318 -0
  67. package/dist/config/loadEval.d.ts +32 -0
  68. package/dist/config/loadEval.js +1085 -0
  69. package/dist/config/loadOutcome.d.ts +5 -0
  70. package/dist/config/loadStageflowManifest.js +64 -0
  71. package/dist/config/resolveAgentTarget.d.ts +32 -0
  72. package/dist/config/resolveAgentTarget.js +118 -0
  73. package/dist/config/resolveEvalTarget.d.ts +21 -0
  74. package/dist/config/resolveEvalTarget.js +89 -0
  75. package/dist/config/scanCatalogPaths.d.ts +1 -1
  76. package/dist/config/scanCatalogPaths.js +17 -5
  77. package/dist/config/validateCatalog.d.ts +1 -1
  78. package/dist/config/validateCatalog.js +9 -1
  79. package/dist/config/validateEval.d.ts +36 -0
  80. package/dist/config/validateEval.js +405 -0
  81. package/dist/config/writeDataset.d.ts +54 -0
  82. package/dist/config/writeDataset.js +186 -0
  83. package/dist/config/writeEval.d.ts +25 -0
  84. package/dist/config/writeEval.js +398 -0
  85. package/dist/diagnostics/checks.js +1 -1
  86. package/dist/evals/agentDiff.d.ts +13 -0
  87. package/dist/evals/agentDiff.js +11 -0
  88. package/dist/evals/canonical.d.ts +3 -0
  89. package/dist/evals/canonical.js +24 -0
  90. package/dist/evals/caseTask.d.ts +3 -0
  91. package/dist/evals/caseTask.js +9 -0
  92. package/dist/evals/compare.d.ts +94 -0
  93. package/dist/evals/compare.js +201 -0
  94. package/dist/evals/constants.d.ts +60 -0
  95. package/dist/evals/constants.js +95 -0
  96. package/dist/evals/engine/FakeEngine.d.ts +33 -0
  97. package/dist/evals/engine/FakeEngine.js +176 -0
  98. package/dist/evals/engine/index.d.ts +9 -0
  99. package/dist/evals/engine/index.js +19 -0
  100. package/dist/evals/engine/promptfoo/PromptfooEngine.d.ts +52 -0
  101. package/dist/evals/engine/promptfoo/PromptfooEngine.js +311 -0
  102. package/dist/evals/engine/promptfoo/errors.d.ts +5 -0
  103. package/dist/evals/engine/promptfoo/errors.js +8 -0
  104. package/dist/evals/engine/promptfoo/generate.d.ts +30 -0
  105. package/dist/evals/engine/promptfoo/generate.js +342 -0
  106. package/dist/evals/engine/promptfoo/guard.d.ts +10 -0
  107. package/dist/evals/engine/promptfoo/guard.js +116 -0
  108. package/dist/evals/engine/promptfoo/install.d.ts +17 -0
  109. package/dist/evals/engine/promptfoo/install.js +73 -0
  110. package/dist/evals/engine/promptfoo/judgeProviders.d.ts +2 -0
  111. package/dist/evals/engine/promptfoo/judgeProviders.js +9 -0
  112. package/dist/evals/engine/promptfoo/judgeServices.d.ts +6 -0
  113. package/dist/evals/engine/promptfoo/judgeServices.js +41 -0
  114. package/dist/evals/engine/promptfoo/locate.d.ts +21 -0
  115. package/dist/evals/engine/promptfoo/locate.js +68 -0
  116. package/dist/evals/engine/promptfoo/nodeVersion.d.ts +7 -0
  117. package/dist/evals/engine/promptfoo/nodeVersion.js +14 -0
  118. package/dist/evals/engine/promptfoo/normalize.d.ts +66 -0
  119. package/dist/evals/engine/promptfoo/normalize.js +261 -0
  120. package/dist/evals/engine/promptfoo/pinned.d.ts +5 -0
  121. package/dist/evals/engine/promptfoo/pinned.js +5 -0
  122. package/dist/evals/engine/promptfoo/rubricPrompt.d.ts +14 -0
  123. package/dist/evals/engine/promptfoo/rubricPrompt.js +103 -0
  124. package/dist/evals/engine/promptfoo/runTokens.d.ts +18 -0
  125. package/dist/evals/engine/promptfoo/runTokens.js +31 -0
  126. package/dist/evals/engine/promptfoo/status.d.ts +13 -0
  127. package/dist/evals/engine/promptfoo/status.js +16 -0
  128. package/dist/evals/estimate.d.ts +56 -0
  129. package/dist/evals/estimate.js +66 -0
  130. package/dist/evals/graders/codeGrader.d.ts +6 -0
  131. package/dist/evals/graders/codeGrader.js +85 -0
  132. package/dist/evals/graders/conversationCheckGrader.d.ts +6 -0
  133. package/dist/evals/graders/conversationCheckGrader.js +62 -0
  134. package/dist/evals/graders/fieldGrader.d.ts +11 -0
  135. package/dist/evals/graders/fieldGrader.js +117 -0
  136. package/dist/evals/graders/goal.d.ts +3 -0
  137. package/dist/evals/graders/goal.js +14 -0
  138. package/dist/evals/graders/index.d.ts +18 -0
  139. package/dist/evals/graders/index.js +34 -0
  140. package/dist/evals/graders/notApplicable.d.ts +5 -0
  141. package/dist/evals/graders/notApplicable.js +9 -0
  142. package/dist/evals/graders/path.d.ts +26 -0
  143. package/dist/evals/graders/path.js +75 -0
  144. package/dist/evals/graders/referenceGrader.d.ts +5 -0
  145. package/dist/evals/graders/referenceGrader.js +59 -0
  146. package/dist/evals/graders/schemaGrader.d.ts +5 -0
  147. package/dist/evals/graders/schemaGrader.js +29 -0
  148. package/dist/evals/graders/subject.d.ts +6 -0
  149. package/dist/evals/graders/subject.js +33 -0
  150. package/dist/evals/graders/toolCallsGrader.d.ts +6 -0
  151. package/dist/evals/graders/toolCallsGrader.js +100 -0
  152. package/dist/evals/graders/transcript.d.ts +12 -0
  153. package/dist/evals/graders/transcript.js +57 -0
  154. package/dist/evals/graders/types.d.ts +20 -0
  155. package/dist/evals/graders/types.js +1 -0
  156. package/dist/evals/judgeProviders.d.ts +16 -0
  157. package/dist/evals/judgeProviders.js +27 -0
  158. package/dist/evals/lineDiff.d.ts +5 -0
  159. package/dist/evals/lineDiff.js +34 -0
  160. package/dist/evals/listStatus.d.ts +31 -0
  161. package/dist/evals/listStatus.js +48 -0
  162. package/dist/evals/manager.d.ts +174 -0
  163. package/dist/evals/manager.js +787 -0
  164. package/dist/evals/plan.d.ts +58 -0
  165. package/dist/evals/plan.js +602 -0
  166. package/dist/evals/providerKeys.d.ts +1 -0
  167. package/dist/evals/providerKeys.js +21 -0
  168. package/dist/evals/read/agentTargets.d.ts +37 -0
  169. package/dist/evals/read/agentTargets.js +101 -0
  170. package/dist/evals/read/api.d.ts +196 -0
  171. package/dist/evals/read/api.js +358 -0
  172. package/dist/evals/read/compare.d.ts +4 -0
  173. package/dist/evals/read/compare.js +39 -0
  174. package/dist/evals/read/datasets.d.ts +105 -0
  175. package/dist/evals/read/datasets.js +318 -0
  176. package/dist/evals/read/list.d.ts +66 -0
  177. package/dist/evals/read/list.js +173 -0
  178. package/dist/evals/read/results.d.ts +46 -0
  179. package/dist/evals/read/results.js +107 -0
  180. package/dist/evals/read/runs.d.ts +149 -0
  181. package/dist/evals/read/runs.js +289 -0
  182. package/dist/evals/read/suggestions.d.ts +43 -0
  183. package/dist/evals/read/suggestions.js +73 -0
  184. package/dist/evals/runner/FakeAgentBackend.d.ts +40 -0
  185. package/dist/evals/runner/FakeAgentBackend.js +82 -0
  186. package/dist/evals/runner/agentCaseRunner.d.ts +24 -0
  187. package/dist/evals/runner/agentCaseRunner.js +388 -0
  188. package/dist/evals/runner/caseRunner.d.ts +7 -0
  189. package/dist/evals/runner/caseRunner.js +17 -0
  190. package/dist/evals/runner/conversationSubject.d.ts +18 -0
  191. package/dist/evals/runner/conversationSubject.js +123 -0
  192. package/dist/evals/runner/simulatorModel.d.ts +51 -0
  193. package/dist/evals/runner/simulatorModel.js +58 -0
  194. package/dist/evals/runner/simulatorPrompt.d.ts +29 -0
  195. package/dist/evals/runner/simulatorPrompt.js +59 -0
  196. package/dist/evals/runner/stageCaseRunner.d.ts +30 -0
  197. package/dist/evals/runner/stageCaseRunner.js +279 -0
  198. package/dist/evals/runner/userDriver.d.ts +71 -0
  199. package/dist/evals/runner/userDriver.js +104 -0
  200. package/dist/evals/scoring.d.ts +34 -0
  201. package/dist/evals/scoring.js +67 -0
  202. package/dist/evals/snapshot.d.ts +183 -0
  203. package/dist/evals/snapshot.js +65 -0
  204. package/dist/evals/stageDiff.d.ts +8 -0
  205. package/dist/evals/stageDiff.js +48 -0
  206. package/dist/evals/stats.d.ts +95 -0
  207. package/dist/evals/stats.js +220 -0
  208. package/dist/evals/statsAdapter.d.ts +4 -0
  209. package/dist/evals/statsAdapter.js +30 -0
  210. package/dist/evals/statsTypes.d.ts +51 -0
  211. package/dist/evals/statsTypes.js +18 -0
  212. package/dist/evals/storeError.d.ts +5 -0
  213. package/dist/evals/storeError.js +8 -0
  214. package/dist/evals/storeTypes.d.ts +207 -0
  215. package/dist/evals/storeTypes.js +1 -0
  216. package/dist/evals/tTable.d.ts +3 -0
  217. package/dist/evals/tTable.js +15 -0
  218. package/dist/evals/triage/constants.d.ts +26 -0
  219. package/dist/evals/triage/constants.js +33 -0
  220. package/dist/evals/triage/credentials.d.ts +13 -0
  221. package/dist/evals/triage/credentials.js +20 -0
  222. package/dist/evals/triage/jevClassifier.d.ts +14 -0
  223. package/dist/evals/triage/jevClassifier.js +124 -0
  224. package/dist/evals/triage/judgeClassifier.d.ts +10 -0
  225. package/dist/evals/triage/judgeClassifier.js +76 -0
  226. package/dist/evals/triage/prompts.d.ts +16 -0
  227. package/dist/evals/triage/prompts.js +64 -0
  228. package/dist/evals/triage/service.d.ts +79 -0
  229. package/dist/evals/triage/service.js +217 -0
  230. package/dist/evals/triage/stateBuilder.d.ts +19 -0
  231. package/dist/evals/triage/stateBuilder.js +125 -0
  232. package/dist/evals/triage/types.d.ts +60 -0
  233. package/dist/evals/triage/types.js +8 -0
  234. package/dist/evals/types.d.ts +347 -0
  235. package/dist/evals/types.js +1 -0
  236. package/dist/mcp/deps.d.ts +7 -0
  237. package/dist/mcp/evalTools.d.ts +3 -0
  238. package/dist/mcp/evalTools.js +280 -0
  239. package/dist/mcp/server.js +1 -0
  240. package/dist/mcp/tools.js +2 -0
  241. package/dist/models/response.d.ts +7 -2
  242. package/dist/models/response.js +6 -1
  243. package/dist/operatorAgent/agentAuthorContext.d.ts +1 -1
  244. package/dist/operatorAgent/agentAuthorContext.js +1 -1
  245. package/dist/operatorAgent/piModel.js +17 -4
  246. package/dist/operatorAgent/profiles/agentAuthor.d.ts +3 -1
  247. package/dist/operatorAgent/profiles/agentAuthor.js +145 -20
  248. package/dist/operatorAgent/profiles/agentAuthorPlaybook.d.ts +1 -1
  249. package/dist/operatorAgent/profiles/agentAuthorPlaybook.js +48 -15
  250. package/dist/operatorAgent/profiles/authorReadable.d.ts +2 -0
  251. package/dist/operatorAgent/profiles/authorReadable.js +26 -0
  252. package/dist/package-meta.d.ts +1 -1
  253. package/dist/package-meta.js +1 -1
  254. package/dist/runstore/port.d.ts +43 -0
  255. package/dist/runstore/sqlite/SqliteRunStore.d.ts +28 -0
  256. package/dist/runstore/sqlite/SqliteRunStore.js +99 -5
  257. package/dist/runstore/sqlite/evalStore.d.ts +20 -0
  258. package/dist/runstore/sqlite/evalStore.js +541 -0
  259. package/dist/runstore/sqlite/migrations/015-evals.d.ts +12 -0
  260. package/dist/runstore/sqlite/migrations/015-evals.js +157 -0
  261. package/dist/runstore/sqlite/migrations/016-eval-subject-ref.d.ts +12 -0
  262. package/dist/runstore/sqlite/migrations/016-eval-subject-ref.js +20 -0
  263. package/dist/runstore/sqlite/migrations/017-eval-result-suggestions.d.ts +11 -0
  264. package/dist/runstore/sqlite/migrations/017-eval-result-suggestions.js +36 -0
  265. package/dist/runstore/sqlite/migrations/index.js +6 -0
  266. package/dist/runstore/sqlite/suggestionStore.d.ts +14 -0
  267. package/dist/runstore/sqlite/suggestionStore.js +132 -0
  268. package/dist/runtime/pipelineRunner.d.ts +2 -1
  269. package/dist/runtime/pipelineRunner.js +2 -0
  270. package/dist/runtime/runManager.d.ts +2 -1
  271. package/dist/runtime/runManager.js +8 -6
  272. package/dist/runtime/runRetentionSweep.js +2 -2
  273. package/dist/server/agentAuthorRoutes.js +50 -1
  274. package/dist/server/bootstrap.d.ts +8 -0
  275. package/dist/server/bootstrap.js +56 -0
  276. package/dist/server/controlToken.js +3 -0
  277. package/dist/server/evalInternalRoutes.d.ts +14 -0
  278. package/dist/server/evalInternalRoutes.js +87 -0
  279. package/dist/server/evalRouteContext.d.ts +46 -0
  280. package/dist/server/evalRouteContext.js +43 -0
  281. package/dist/server/evalRoutes.d.ts +5 -0
  282. package/dist/server/evalRoutes.js +1427 -0
  283. package/dist/server/evalTriageRoutes.d.ts +2 -0
  284. package/dist/server/evalTriageRoutes.js +95 -0
  285. package/dist/server/http.d.ts +5 -0
  286. package/dist/server/http.js +32 -2
  287. package/dist/server/mcpHost.js +3 -0
  288. package/dist/toolkit/meta.d.ts +1 -1
  289. package/dist/toolkit/meta.js +15 -0
  290. package/dist/toolkit/profiles.js +1 -1
  291. package/dist/types/stageflowManifest.d.ts +6 -0
  292. package/dist/ui/assets/AssistantRuntimeProvider-qIX1xNoH.js +9 -0
  293. package/dist/ui/assets/{MarkdownText-D7tYaIFO.js → MarkdownText-BTrOqu5J.js} +1 -1
  294. package/dist/ui/assets/chat-Df_wCpak.js +5 -0
  295. package/dist/ui/assets/chat-P7KQznHm.css +2 -0
  296. package/dist/ui/assets/{main-BFo79krC.css → main-CHlmTNJe.css} +1 -1
  297. package/dist/ui/assets/main-CvVfxmMd.js +271 -0
  298. package/dist/ui/chat.html +3 -3
  299. package/dist/ui/index.html +3 -3
  300. package/examples/README.md +2 -0
  301. package/examples/document-policy-review/README.md +35 -0
  302. package/examples/document-policy-review/agents/compliance.agent.yaml +42 -0
  303. package/examples/document-policy-review/documents/acme-vendor-sow.md +15 -0
  304. package/examples/document-policy-review/documents/support-runbook.md +13 -0
  305. package/examples/document-policy-review/policies/acceptable-use.md +13 -0
  306. package/examples/document-policy-review/policies/data-handling.md +17 -0
  307. package/examples/document-policy-review/policies/vendor-security.md +17 -0
  308. package/examples/evals/README.md +123 -0
  309. package/examples/evals/critique-sample.dataset.jsonl +8 -0
  310. package/examples/evals/critique-sample.eval.yaml +34 -0
  311. package/examples/evals/critique-sample.task.yaml +4 -0
  312. package/examples/evals/eval-sample.pipeline.yaml +35 -0
  313. package/examples/evals/support-sample.agent.yaml +20 -0
  314. package/examples/evals/support-sample.dataset.jsonl +6 -0
  315. package/examples/evals/support-sample.eval.yaml +38 -0
  316. package/examples/stageflow.yaml +6 -0
  317. package/package.json +1 -1
  318. package/skills/stageflow/SKILL.md +5 -2
  319. package/skills/stageflow/references/control-surface.md +4 -2
  320. package/skills/stageflow/references/evals.md +68 -0
  321. package/skills/stageflow-author/SKILL.md +4 -0
  322. package/skills/stageflow-run/SKILL.md +4 -0
  323. package/dist/ui/assets/AssistantRuntimeProvider-CsiPFhCT.js +0 -9
  324. package/dist/ui/assets/chat-BbLukq9W.js +0 -5
  325. package/dist/ui/assets/chat-zIZU_bP1.css +0 -2
  326. package/dist/ui/assets/main-CijYMeM0.js +0 -259
@@ -0,0 +1,398 @@
1
+ import { access, readFile } from "node:fs/promises";
2
+ import { isDeepStrictEqual } from "node:util";
3
+ import path from "node:path";
4
+ import { Document, isMap, isNode, isScalar, isSeq, parseDocument, Scalar, } from "yaml";
5
+ import { assertBaseHash, contentHash, EvalsWriteError, FileChangedError, writeFileAtomic, } from "./atomicWrite.js";
6
+ import { ensureCatalogScanRoot } from "./ensureCatalogScanRoot.js";
7
+ import { assertInsideProject, explicitRoots, findEvalFile, manifestForWrite, resolveWriteDir, } from "./evalWriteRoots.js";
8
+ import { EVAL_AGENT_DEFAULT_CONCURRENCY, EVAL_AGENT_DEFAULT_MAX_COST_USD, EVAL_CONVERSATION_DEFAULTS, EVAL_DEFAULT_CONCURRENCY, EVAL_DEFAULT_MAX_COST_USD, EVAL_DEFAULT_PASS_THRESHOLD, EVAL_DEFAULT_REPEATS, parseEvalOutcome, } from "./loadEval.js";
9
+ import { evalFindingsFromIssues } from "./validateEval.js";
10
+ const TOP_ORDER = [
11
+ "version",
12
+ "id",
13
+ "name",
14
+ "description",
15
+ "type",
16
+ "target",
17
+ "dataset",
18
+ "task",
19
+ "defaults",
20
+ "conversation",
21
+ "graders",
22
+ "budget",
23
+ ];
24
+ const TARGET_ORDER = ["kind", "pipeline", "stage", "file", "agent"];
25
+ const CONVERSATION_ORDER = [
26
+ "mode",
27
+ "max_turns",
28
+ "turn_timeout_ms",
29
+ "tools",
30
+ "approvals",
31
+ "read_only_tools",
32
+ "allow_real_tools",
33
+ ];
34
+ const TASK_ORDER = ["goal", "context", "constraints"];
35
+ const DEFAULTS_ORDER = ["repeats", "judge", "user_model", "pass_threshold", "max_cost_usd", "concurrency", "model"];
36
+ const BUDGET_ORDER = ["latency_ms", "cost_usd"];
37
+ const GRADER_COMMON_ORDER = ["id", "type", "description", "weight", "must_pass"];
38
+ const GRADER_TYPE_ORDER = {
39
+ schema: [],
40
+ field: ["checks"],
41
+ reference: ["mode", "path", "expected", "pass_at"],
42
+ rubric: ["rubric", "scale", "pass_at", "judge", "examples"],
43
+ code: ["code"],
44
+ tool_calls: ["must_call", "must_not_call", "must_ask_first", "max_calls", "args"],
45
+ conversation_check: ["max_turns", "max_agent_questions_per_turn", "final_reply"],
46
+ goal_reached: ["judge", "guidance"],
47
+ };
48
+ const CHECK_ORDER = ["path", "op", "value"];
49
+ const TOOL_ARG_ORDER = ["tool", "path", "op", "value"];
50
+ const FINAL_REPLY_ORDER = ["op", "value"];
51
+ const FLOW_LISTS = new Set(["checks", "args", "final_reply"]);
52
+ function isPlain(value) {
53
+ return typeof value === "object" && value !== null && !Array.isArray(value);
54
+ }
55
+ function ordered(value, order) {
56
+ const out = {};
57
+ for (const key of order) {
58
+ if (value[key] !== undefined)
59
+ out[key] = value[key];
60
+ }
61
+ for (const key of Object.keys(value)) {
62
+ if (!(key in out) && value[key] !== undefined)
63
+ out[key] = value[key];
64
+ }
65
+ return out;
66
+ }
67
+ function graderOrder(grader) {
68
+ const typeKeys = typeof grader.type === "string" ? (GRADER_TYPE_ORDER[grader.type] ?? []) : [];
69
+ return [...GRADER_COMMON_ORDER, ...typeKeys];
70
+ }
71
+ function orderedGrader(grader) {
72
+ const out = ordered(grader, graderOrder(grader));
73
+ if (Array.isArray(out.checks)) {
74
+ out.checks = out.checks.map((c) => (isPlain(c) ? ordered(c, CHECK_ORDER) : c));
75
+ }
76
+ if (Array.isArray(out.args)) {
77
+ out.args = out.args.map((c) => (isPlain(c) ? ordered(c, TOOL_ARG_ORDER) : c));
78
+ }
79
+ if (Array.isArray(out.final_reply)) {
80
+ out.final_reply = out.final_reply.map((c) => (isPlain(c) ? ordered(c, FINAL_REPLY_ORDER) : c));
81
+ }
82
+ if (Array.isArray(out.examples)) {
83
+ out.examples = out.examples.map((e) => isPlain(e) ? ordered(e, ["verdict", "score", "output", "reason"]) : e);
84
+ }
85
+ return out;
86
+ }
87
+ function orderedDefinition(definition) {
88
+ if (!isPlain(definition))
89
+ return definition;
90
+ const out = ordered(definition, TOP_ORDER);
91
+ const subs = [
92
+ ["target", TARGET_ORDER],
93
+ ["task", TASK_ORDER],
94
+ ["defaults", DEFAULTS_ORDER],
95
+ ["conversation", CONVERSATION_ORDER],
96
+ ["budget", BUDGET_ORDER],
97
+ ];
98
+ for (const [key, order] of subs) {
99
+ if (isPlain(out[key]))
100
+ out[key] = ordered(out[key], order);
101
+ }
102
+ if (Array.isArray(out.graders)) {
103
+ out.graders = out.graders.map((g) => (isPlain(g) ? orderedGrader(g) : g));
104
+ }
105
+ return out;
106
+ }
107
+ function styleNode(node, keys) {
108
+ if (isMap(node)) {
109
+ for (const pair of node.items) {
110
+ const key = isScalar(pair.key) ? String(pair.key.value) : String(pair.key);
111
+ styleNode(pair.value, [...keys, key]);
112
+ }
113
+ }
114
+ else if (isSeq(node)) {
115
+ for (const item of node.items) {
116
+ if (FLOW_LISTS.has(keys[keys.length - 1] ?? "") && isMap(item))
117
+ item.flow = true;
118
+ styleNode(item, [...keys, "[]"]);
119
+ }
120
+ }
121
+ else if (isScalar(node) && typeof node.value === "string") {
122
+ if (keys[keys.length - 1] === "output" && keys[keys.length - 3] === "examples") {
123
+ node.type = Scalar.QUOTE_DOUBLE;
124
+ }
125
+ else if (node.value.includes("\n")) {
126
+ node.type = Scalar.BLOCK_LITERAL;
127
+ }
128
+ }
129
+ }
130
+ const STRINGIFY = { indent: 2, lineWidth: 0 };
131
+ function toText(doc) {
132
+ const text = doc.toString(STRINGIFY);
133
+ return text.endsWith("\n") ? text : `${text}\n`;
134
+ }
135
+ export function renderEvalYaml(definition) {
136
+ const doc = new Document(orderedDefinition(definition));
137
+ styleNode(doc.contents, []);
138
+ return toText(doc);
139
+ }
140
+ function fillCreateDefaults(definition) {
141
+ if (definition.target?.kind === "agent") {
142
+ const conversation = { ...definition.conversation };
143
+ const d = EVAL_CONVERSATION_DEFAULTS;
144
+ const explicit = {
145
+ mode: d.mode,
146
+ max_turns: d.maxTurns,
147
+ turn_timeout_ms: d.turnTimeoutMs,
148
+ tools: d.tools,
149
+ approvals: d.approvals,
150
+ };
151
+ for (const [key, value] of Object.entries(explicit))
152
+ conversation[key] ??= value;
153
+ if (Array.isArray(conversation.read_only_tools) && conversation.read_only_tools.length === 0) {
154
+ delete conversation.read_only_tools;
155
+ }
156
+ if (conversation.allow_real_tools === false)
157
+ delete conversation.allow_real_tools;
158
+ return {
159
+ ...definition,
160
+ defaults: {
161
+ repeats: EVAL_DEFAULT_REPEATS,
162
+ pass_threshold: EVAL_DEFAULT_PASS_THRESHOLD,
163
+ max_cost_usd: EVAL_AGENT_DEFAULT_MAX_COST_USD,
164
+ concurrency: EVAL_AGENT_DEFAULT_CONCURRENCY,
165
+ ...definition.defaults,
166
+ },
167
+ conversation: conversation,
168
+ };
169
+ }
170
+ return {
171
+ ...definition,
172
+ defaults: {
173
+ repeats: EVAL_DEFAULT_REPEATS,
174
+ pass_threshold: EVAL_DEFAULT_PASS_THRESHOLD,
175
+ max_cost_usd: EVAL_DEFAULT_MAX_COST_USD,
176
+ ...definition.defaults,
177
+ },
178
+ };
179
+ }
180
+ export function renderEvalCreateYaml(definition) {
181
+ return renderEvalYaml(fillCreateDefaults(definition));
182
+ }
183
+ function isOmittableDefault(keys, value, parent, agent) {
184
+ const key = keys[keys.length - 1];
185
+ if (keys.length === 1)
186
+ return key === "type" && value === "capability";
187
+ if (keys.length === 2 && keys[0] === "defaults") {
188
+ return ((key === "repeats" && value === EVAL_DEFAULT_REPEATS) ||
189
+ (key === "pass_threshold" && value === EVAL_DEFAULT_PASS_THRESHOLD) ||
190
+ (key === "max_cost_usd" && value === (agent ? EVAL_AGENT_DEFAULT_MAX_COST_USD : EVAL_DEFAULT_MAX_COST_USD)) ||
191
+ (key === "concurrency" && value === (agent ? EVAL_AGENT_DEFAULT_CONCURRENCY : EVAL_DEFAULT_CONCURRENCY)));
192
+ }
193
+ if (keys.length === 3 && keys[0] === "graders") {
194
+ if (key === "weight")
195
+ return value === 1;
196
+ if (key === "must_pass")
197
+ return value === false;
198
+ if (key === "scale")
199
+ return value === "pass_fail";
200
+ if (key === "path")
201
+ return parent.type === "reference" && value === (agent ? "final_reply" : "payload");
202
+ if (key === "pass_at") {
203
+ if (parent.type === "reference")
204
+ return value === 1;
205
+ if (parent.type === "rubric")
206
+ return parent.scale === "1_to_5" && value === 4;
207
+ }
208
+ }
209
+ return false;
210
+ }
211
+ function create(doc, value, keys) {
212
+ const node = doc.createNode(value);
213
+ styleNode(node, keys);
214
+ return node;
215
+ }
216
+ function carryComments(from, to) {
217
+ if (!isNode(from) || !isNode(to))
218
+ return;
219
+ if (from.comment !== undefined)
220
+ to.comment = from.comment;
221
+ if (from.commentBefore !== undefined)
222
+ to.commentBefore = from.commentBefore;
223
+ if (from.spaceBefore)
224
+ to.spaceBefore = true;
225
+ }
226
+ function replace(doc, old, value, keys) {
227
+ const node = create(doc, value, keys);
228
+ carryComments(old, node);
229
+ return node;
230
+ }
231
+ function pairKey(pair) {
232
+ return isScalar(pair.key) ? String(pair.key.value) : String(pair.key);
233
+ }
234
+ function syncValue(doc, node, value, keys, agent) {
235
+ if (isPlain(value)) {
236
+ if (!isMap(node))
237
+ return replace(doc, node, value, keys);
238
+ syncMap(doc, node, value, keys, agent);
239
+ return node;
240
+ }
241
+ if (Array.isArray(value)) {
242
+ if (!isSeq(node))
243
+ return replace(doc, node, value, keys);
244
+ syncSeq(doc, node, value, keys, agent);
245
+ return node;
246
+ }
247
+ if (isScalar(node) && (value === null || typeof value !== "object")) {
248
+ if (node.value !== value) {
249
+ node.value = value;
250
+ if (typeof value === "string" && value.includes("\n")) {
251
+ if (node.type !== Scalar.BLOCK_FOLDED)
252
+ node.type = Scalar.BLOCK_LITERAL;
253
+ }
254
+ else if (node.type === Scalar.BLOCK_LITERAL || node.type === Scalar.BLOCK_FOLDED) {
255
+ node.type = undefined;
256
+ }
257
+ }
258
+ return node;
259
+ }
260
+ return replace(doc, node, value, keys);
261
+ }
262
+ function syncMap(doc, map, value, keys, agent) {
263
+ const desired = Object.keys(value).filter((k) => value[k] !== undefined);
264
+ map.items = map.items.filter((pair) => desired.includes(pairKey(pair)));
265
+ let lastIndex = -1;
266
+ for (const key of desired) {
267
+ const childKeys = [...keys, key];
268
+ const index = map.items.findIndex((pair) => pairKey(pair) === key);
269
+ if (index >= 0) {
270
+ const pair = map.items[index];
271
+ pair.value = syncValue(doc, pair.value, value[key], childKeys, agent);
272
+ lastIndex = index;
273
+ continue;
274
+ }
275
+ if (isOmittableDefault(childKeys, value[key], value, agent))
276
+ continue;
277
+ const pair = doc.createPair(key, create(doc, value[key], childKeys));
278
+ map.items.splice(lastIndex + 1, 0, pair);
279
+ lastIndex += 1;
280
+ }
281
+ }
282
+ function itemId(node) {
283
+ if (!isMap(node))
284
+ return undefined;
285
+ const id = node.get("id");
286
+ return typeof id === "string" ? id : undefined;
287
+ }
288
+ function syncSeq(doc, seq, value, keys, agent) {
289
+ const byId = keys[keys.length - 1] === "graders";
290
+ const childKeys = [...keys, "[]"];
291
+ const used = new Set();
292
+ const next = value.map((item, index) => {
293
+ let existing;
294
+ if (byId) {
295
+ const id = isPlain(item) && typeof item.id === "string" ? item.id : undefined;
296
+ existing = seq.items.find((n) => !used.has(n) && id !== undefined && itemId(n) === id);
297
+ }
298
+ else {
299
+ existing = seq.items[index];
300
+ }
301
+ if (existing === undefined)
302
+ return create(doc, item, childKeys);
303
+ used.add(existing);
304
+ return syncValue(doc, existing, item, childKeys, agent);
305
+ });
306
+ seq.items = next;
307
+ }
308
+ export function previewEvalUpdate(currentText, definition) {
309
+ const doc = parseDocument(currentText);
310
+ if (doc.errors.length > 0 || !isMap(doc.contents))
311
+ return renderEvalYaml(definition);
312
+ const target = orderedDefinition(definition);
313
+ if (!isPlain(target))
314
+ return renderEvalYaml(definition);
315
+ if (isDeepStrictEqual(doc.toJS(), JSON.parse(JSON.stringify(target))))
316
+ return currentText;
317
+ const targetKind = isPlain(target.target) ? target.target.kind : undefined;
318
+ syncMap(doc, doc.contents, target, [], targetKind === "agent");
319
+ return toText(doc);
320
+ }
321
+ function relOf(projectRoot, abs) {
322
+ return path.relative(projectRoot, abs).split(path.sep).join("/");
323
+ }
324
+ function validateEvalText(text, absPath, projectRoot) {
325
+ const outcome = parseEvalOutcome(text, absPath, projectRoot);
326
+ const relPath = relOf(projectRoot, absPath);
327
+ if (!outcome.ok) {
328
+ const findings = evalFindingsFromIssues(relPath, outcome.issues);
329
+ throw new EvalsWriteError("EVAL_INVALID", findings.find((f) => f.severity === "error")?.message ?? "Eval definition is invalid", findings);
330
+ }
331
+ return evalFindingsFromIssues(relPath, outcome.issues ?? []);
332
+ }
333
+ async function exists(abs) {
334
+ try {
335
+ await access(abs);
336
+ return true;
337
+ }
338
+ catch {
339
+ return false;
340
+ }
341
+ }
342
+ export async function createEvalFile(input) {
343
+ const { projectRoot, definition } = input;
344
+ const manifest = await manifestForWrite(projectRoot);
345
+ const dir = await resolveWriteDir(projectRoot, manifest, "evals", input.directory);
346
+ const rawId = definition.id;
347
+ const fileName = `${typeof rawId === "string" ? rawId : "new"}.eval.yaml`;
348
+ const absPath = path.join(dir.absDir, fileName);
349
+ assertInsideProject(projectRoot, absPath, "eval path");
350
+ if (typeof rawId === "string") {
351
+ if ((await findEvalFile(projectRoot, rawId, manifest)) !== undefined || (await exists(absPath))) {
352
+ throw new EvalsWriteError("EVAL_EXISTS", `Eval "${rawId}" already exists`);
353
+ }
354
+ }
355
+ const text = renderEvalYaml(fillCreateDefaults(definition));
356
+ const findings = validateEvalText(text, absPath, projectRoot);
357
+ await writeFileAtomic(absPath, text);
358
+ const named = explicitRoots(manifest, "evals");
359
+ if (named !== undefined)
360
+ await ensureCatalogScanRoot(projectRoot, dir.relDir, ["evals"]);
361
+ return {
362
+ id: rawId,
363
+ path: absPath,
364
+ relPath: relOf(projectRoot, absPath),
365
+ text,
366
+ fileHash: contentHash(text),
367
+ findings,
368
+ };
369
+ }
370
+ export async function updateEvalFile(input) {
371
+ const { projectRoot, id, baseHash } = input;
372
+ if ((input.definition === undefined) === (input.yaml === undefined)) {
373
+ throw new EvalsWriteError("EVAL_INVALID", "Provide exactly one of definition or yaml");
374
+ }
375
+ const ref = await findEvalFile(projectRoot, id);
376
+ if (ref === undefined)
377
+ throw new EvalsWriteError("EVAL_NOT_FOUND", `Eval "${id}" not found`);
378
+ const current = await readFile(ref.absPath);
379
+ const currentHash = contentHash(current);
380
+ if (currentHash !== baseHash)
381
+ throw new FileChangedError(currentHash);
382
+ const text = input.yaml !== undefined
383
+ ? input.yaml.endsWith("\n")
384
+ ? input.yaml
385
+ : `${input.yaml}\n`
386
+ : previewEvalUpdate(current.toString("utf8"), input.definition);
387
+ const findings = validateEvalText(text, ref.absPath, projectRoot);
388
+ await assertBaseHash(ref.absPath, baseHash);
389
+ await writeFileAtomic(ref.absPath, text);
390
+ return {
391
+ id,
392
+ path: ref.absPath,
393
+ relPath: ref.relPath,
394
+ text,
395
+ fileHash: contentHash(text),
396
+ findings,
397
+ };
398
+ }
@@ -49,7 +49,7 @@ function checkHomeWritable(home) {
49
49
  }
50
50
  async function checkStoreOpenable(store) {
51
51
  try {
52
- await store.listRuns();
52
+ await store.listRuns({ origin: "any" });
53
53
  return true;
54
54
  }
55
55
  catch {
@@ -0,0 +1,13 @@
1
+ import { type DiffLine } from "./lineDiff.js";
2
+ export interface AgentDiff {
3
+ changed_keys: string[];
4
+ instructions_diff: DiffLine[] | null;
5
+ revision: {
6
+ a: number | null;
7
+ b: number | null;
8
+ };
9
+ }
10
+ export declare function agentDiff(defA: Record<string, unknown>, defB: Record<string, unknown>, revision: {
11
+ a: number | null;
12
+ b: number | null;
13
+ }): AgentDiff;
@@ -0,0 +1,11 @@
1
+ import { lineDiff } from "./lineDiff.js";
2
+ import { stageDiff } from "./stageDiff.js";
3
+ export function agentDiff(defA, defB, revision) {
4
+ const changed = stageDiff(defA, defB).changed_keys;
5
+ const text = (v) => (typeof v === "string" ? v : v === undefined || v === null ? "" : JSON.stringify(v));
6
+ return {
7
+ changed_keys: changed,
8
+ instructions_diff: changed.includes("instructions") ? lineDiff(text(defA.instructions), text(defB.instructions)) : null,
9
+ revision,
10
+ };
11
+ }
@@ -0,0 +1,3 @@
1
+ export declare function canonicalJson(value: unknown): string;
2
+ export declare function sha256Hex(input: string | Uint8Array): string;
3
+ export declare function hash6(fullHash: string): string;
@@ -0,0 +1,24 @@
1
+ import { createHash } from "node:crypto";
2
+ function sortValue(value) {
3
+ if (Array.isArray(value))
4
+ return value.map(sortValue);
5
+ if (value !== null && typeof value === "object") {
6
+ const out = {};
7
+ for (const key of Object.keys(value).sort()) {
8
+ const v = value[key];
9
+ if (v !== undefined)
10
+ out[key] = sortValue(v);
11
+ }
12
+ return out;
13
+ }
14
+ return value;
15
+ }
16
+ export function canonicalJson(value) {
17
+ return JSON.stringify(sortValue(value));
18
+ }
19
+ export function sha256Hex(input) {
20
+ return createHash("sha256").update(input).digest("hex");
21
+ }
22
+ export function hash6(fullHash) {
23
+ return fullHash.slice(0, 6);
24
+ }
@@ -0,0 +1,3 @@
1
+ import type { TaskFile } from "../types/task.js";
2
+ import type { EvalPlan, PlanCase } from "./types.js";
3
+ export declare function caseToTask(plan: Pick<EvalPlan, "task">, testCase: Pick<PlanCase, "id" | "goal" | "input">, evalRunId: string, repeatIndex: number): TaskFile;
@@ -0,0 +1,9 @@
1
+ export function caseToTask(plan, testCase, evalRunId, repeatIndex) {
2
+ return {
3
+ id: `eval-${evalRunId}-${testCase.id}-${repeatIndex}`,
4
+ goal: testCase.goal ?? plan.task.goal ?? `Evaluate case ${testCase.id}`,
5
+ ...(plan.task.context !== undefined ? { context: plan.task.context } : {}),
6
+ ...(plan.task.constraints !== undefined ? { constraints: plan.task.constraints } : {}),
7
+ input: testCase.input,
8
+ };
9
+ }
@@ -0,0 +1,94 @@
1
+ import { type Interval, type Stats } from "./stats.js";
2
+ import { type AgentDiff } from "./agentDiff.js";
3
+ import { type StageDiff } from "./stageDiff.js";
4
+ import { type GradeRecord, type GraderRef, type ResultRecord } from "./statsTypes.js";
5
+ export interface CompareRunInput {
6
+ evalId: string;
7
+ runNumber: number;
8
+ datasetHash: string;
9
+ stageVersionHash: string;
10
+ stageDefinition: Record<string, unknown> | null;
11
+ targetKind?: "stage" | "agent";
12
+ agentId?: string | null;
13
+ agentRevision?: number | null;
14
+ agentDefinition?: Record<string, unknown> | null;
15
+ configComponents: Record<string, unknown>;
16
+ results: ResultRecord[];
17
+ grades: GradeRecord[];
18
+ graders: GraderRef[];
19
+ repeats: number;
20
+ passThreshold: number;
21
+ }
22
+ export type Verdict = "improved" | "regressed" | "no_clear_difference" | "insufficient_data";
23
+ export type CaseChange = "improved" | "regressed" | "same";
24
+ export interface CaseDetail {
25
+ case_id: string;
26
+ change: CaseChange;
27
+ p_a: number;
28
+ p_b: number;
29
+ d: number;
30
+ passes_a: boolean[];
31
+ passes_b: boolean[];
32
+ mean_score_a: number | null;
33
+ mean_score_b: number | null;
34
+ graders_changed: string[];
35
+ }
36
+ export interface GraderComparison {
37
+ grader_id: string;
38
+ status: "compared" | "changed" | "added" | "removed";
39
+ pass_rate_a: number | null;
40
+ pass_rate_b: number | null;
41
+ delta: number | null;
42
+ }
43
+ export interface ComponentDiff {
44
+ key: string;
45
+ status: "same" | "changed";
46
+ a: unknown;
47
+ b: unknown;
48
+ }
49
+ export type CompareWarningCode = "dataset_differs" | "graders_differ" | "engine_differs" | "few_shared_cases";
50
+ export interface CompareWarning {
51
+ code: CompareWarningCode;
52
+ shared_cases?: number;
53
+ cases_a?: number;
54
+ cases_b?: number;
55
+ }
56
+ export interface NumberDelta {
57
+ a: number | null;
58
+ b: number | null;
59
+ delta: number | null;
60
+ percent_change: number | null;
61
+ }
62
+ export interface CompareResult {
63
+ shared_cases: number;
64
+ cases_a: number;
65
+ cases_b: number;
66
+ mean_difference: number | null;
67
+ ci: Interval | null;
68
+ verdict: Verdict;
69
+ cases: CaseDetail[];
70
+ graders: GraderComparison[];
71
+ deltas: {
72
+ cost_per_result: NumberDelta;
73
+ latency_p50: NumberDelta;
74
+ latency_p95: NumberDelta;
75
+ flaky_cases: NumberDelta;
76
+ mean_score: NumberDelta;
77
+ mean_turns?: NumberDelta;
78
+ mean_tool_calls?: NumberDelta;
79
+ };
80
+ stage_diff: StageDiff | null;
81
+ agent_diff?: AgentDiff | null;
82
+ components: ComponentDiff[];
83
+ same_config: boolean;
84
+ warnings: CompareWarning[];
85
+ sd_d: number | null;
86
+ cases_needed_5pts: number | null;
87
+ stats_a: Stats;
88
+ stats_b: Stats;
89
+ }
90
+ export declare class CompareMismatchError extends Error {
91
+ readonly code = "EVAL_COMPARE_MISMATCH";
92
+ constructor(a: string, b: string, what?: string);
93
+ }
94
+ export declare function compareRuns(a: CompareRunInput, b: CompareRunInput): CompareResult;