stageflow 0.40.0 → 0.44.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 (519) hide show
  1. package/README.md +15 -4
  2. package/dist/agent/activity.d.ts +18 -0
  3. package/dist/agent/claudeAdapter.js +7 -0
  4. package/dist/agent/claudeTools.d.ts +27 -18
  5. package/dist/agent/claudeTools.js +54 -15
  6. package/dist/agent/compactionEvents.d.ts +34 -0
  7. package/dist/agent/compactionEvents.js +37 -0
  8. package/dist/agent/openRouterRouting.d.ts +7 -0
  9. package/dist/agent/openRouterRouting.js +23 -0
  10. package/dist/agent/piAdapter.d.ts +6 -0
  11. package/dist/agent/piAdapter.js +128 -27
  12. package/dist/agent/piSettings.d.ts +7 -0
  13. package/dist/agent/piSettings.js +9 -0
  14. package/dist/agent/sandboxPiTools.d.ts +3 -1
  15. package/dist/agent/sandboxPiTools.js +8 -2
  16. package/dist/agent/stageTurnDriver.d.ts +11 -2
  17. package/dist/agent/stageTurnDriver.js +45 -4
  18. package/dist/agent/toolOutputBudget.d.ts +15 -1
  19. package/dist/agent/toolOutputBudget.js +18 -0
  20. package/dist/agent/toolOutputBudgetExtension.d.ts +2 -0
  21. package/dist/agent/toolOutputBudgetExtension.js +40 -3
  22. package/dist/agents/authorChat.d.ts +5 -0
  23. package/dist/agents/authorChat.js +120 -12
  24. package/dist/agents/authorSessionStore.d.ts +38 -0
  25. package/dist/agents/authorSessionStore.js +167 -0
  26. package/dist/agents/chatTurn.d.ts +2 -0
  27. package/dist/agents/chatTurn.js +17 -1
  28. package/dist/agents/errors.d.ts +1 -1
  29. package/dist/agents/errors.js +1 -0
  30. package/dist/agents/evalGate.d.ts +61 -0
  31. package/dist/agents/evalGate.js +103 -0
  32. package/dist/agents/evalSession.d.ts +26 -0
  33. package/dist/agents/evalSession.js +29 -0
  34. package/dist/agents/hostContext.d.ts +4 -1
  35. package/dist/agents/hostContext.js +4 -1
  36. package/dist/agents/runtime/piRuntime.d.ts +6 -2
  37. package/dist/agents/runtime/piRuntime.js +50 -16
  38. package/dist/agents/runtime/types.d.ts +3 -1
  39. package/dist/agents/service.d.ts +27 -2
  40. package/dist/agents/service.js +91 -15
  41. package/dist/agents/sessions.d.ts +8 -0
  42. package/dist/agents/sessions.js +53 -11
  43. package/dist/agents/store.d.ts +14 -3
  44. package/dist/agents/store.js +45 -7
  45. package/dist/agents/toolRisk.d.ts +21 -0
  46. package/dist/agents/toolRisk.js +50 -0
  47. package/dist/cli/doctorCommand.js +26 -0
  48. package/dist/cli/evalCommand.d.ts +20 -0
  49. package/dist/cli/evalCommand.js +720 -0
  50. package/dist/cli/exportAllCommand.js +1 -1
  51. package/dist/cli/hostClient.d.ts +60 -0
  52. package/dist/cli/hostClient.js +71 -0
  53. package/dist/cli/validateOutput.d.ts +2 -2
  54. package/dist/cli/validateOutput.js +2 -2
  55. package/dist/cli.js +10 -0
  56. package/dist/compaction/directives.d.ts +18 -0
  57. package/dist/compaction/directives.js +119 -0
  58. package/dist/compaction/extension.d.ts +20 -0
  59. package/dist/compaction/extension.js +78 -0
  60. package/dist/compaction/mask.d.ts +18 -0
  61. package/dist/compaction/mask.js +155 -0
  62. package/dist/compaction/pin.d.ts +21 -0
  63. package/dist/compaction/pin.js +270 -0
  64. package/dist/compaction/scrub.d.ts +7 -0
  65. package/dist/compaction/scrub.js +26 -0
  66. package/dist/compaction/sessionWiring.d.ts +22 -0
  67. package/dist/compaction/sessionWiring.js +26 -0
  68. package/dist/compaction/summarize.d.ts +79 -0
  69. package/dist/compaction/summarize.js +171 -0
  70. package/dist/compaction/toolPolicy.d.ts +3 -0
  71. package/dist/compaction/toolPolicy.js +33 -0
  72. package/dist/compaction/types.d.ts +45 -0
  73. package/dist/compaction/types.js +7 -0
  74. package/dist/compaction/workingState.d.ts +56 -0
  75. package/dist/compaction/workingState.js +198 -0
  76. package/dist/config/atomicWrite.d.ts +15 -0
  77. package/dist/config/atomicWrite.js +43 -0
  78. package/dist/config/browseCatalog.d.ts +2 -0
  79. package/dist/config/browseCatalog.js +4 -2
  80. package/dist/config/createPipeline.js +2 -0
  81. package/dist/config/createTrigger.js +7 -1
  82. package/dist/config/csv.d.ts +9 -0
  83. package/dist/config/csv.js +81 -0
  84. package/dist/config/datasetAgentCheck.d.ts +18 -0
  85. package/dist/config/datasetAgentCheck.js +109 -0
  86. package/dist/config/datasetCandidates.d.ts +22 -0
  87. package/dist/config/datasetCandidates.js +86 -0
  88. package/dist/config/datasetFromSessions.d.ts +34 -0
  89. package/dist/config/datasetFromSessions.js +105 -0
  90. package/dist/config/datasetHash.d.ts +1 -0
  91. package/dist/config/datasetHash.js +4 -0
  92. package/dist/config/datasetImport.d.ts +21 -0
  93. package/dist/config/datasetImport.js +120 -0
  94. package/dist/config/datasetStageCheck.d.ts +9 -0
  95. package/dist/config/datasetStageCheck.js +17 -0
  96. package/dist/config/datasetTypes.d.ts +27 -0
  97. package/dist/config/datasetTypes.js +1 -0
  98. package/dist/config/ensureCatalogScanRoot.d.ts +4 -1
  99. package/dist/config/ensureCatalogScanRoot.js +8 -6
  100. package/dist/config/evalCatalog.d.ts +22 -0
  101. package/dist/config/evalCatalog.js +95 -0
  102. package/dist/config/evalWriteRoots.d.ts +17 -0
  103. package/dist/config/evalWriteRoots.js +109 -0
  104. package/dist/config/githubTriggerAction.d.ts +8 -0
  105. package/dist/config/githubTriggerAction.js +29 -0
  106. package/dist/config/hostConfig.js +3 -0
  107. package/dist/config/installEvalSample.d.ts +34 -0
  108. package/dist/config/installEvalSample.js +182 -0
  109. package/dist/config/loadDataset.d.ts +16 -0
  110. package/dist/config/loadDataset.js +318 -0
  111. package/dist/config/loadEval.d.ts +32 -0
  112. package/dist/config/loadEval.js +1103 -0
  113. package/dist/config/loadOutcome.d.ts +5 -0
  114. package/dist/config/loadStageflowManifest.js +64 -0
  115. package/dist/config/pipelineNeeds.d.ts +2 -0
  116. package/dist/config/pipelineNeeds.js +16 -3
  117. package/dist/config/pipelineRoute.js +5 -4
  118. package/dist/config/resolveAgentTarget.d.ts +32 -0
  119. package/dist/config/resolveAgentTarget.js +118 -0
  120. package/dist/config/resolveEvalTarget.d.ts +21 -0
  121. package/dist/config/resolveEvalTarget.js +89 -0
  122. package/dist/config/scanCatalogPaths.d.ts +1 -1
  123. package/dist/config/scanCatalogPaths.js +17 -5
  124. package/dist/config/validateCatalog.d.ts +2 -2
  125. package/dist/config/validateCatalog.js +21 -1
  126. package/dist/config/validateEval.d.ts +36 -0
  127. package/dist/config/validateEval.js +446 -0
  128. package/dist/config/writeDataset.d.ts +54 -0
  129. package/dist/config/writeDataset.js +186 -0
  130. package/dist/config/writeEval.d.ts +25 -0
  131. package/dist/config/writeEval.js +398 -0
  132. package/dist/diagnostics/checks.js +1 -1
  133. package/dist/envelope/assertEmittedArtifacts.d.ts +12 -0
  134. package/dist/envelope/assertEmittedArtifacts.js +43 -0
  135. package/dist/envelope/preEmitChecks.d.ts +3 -0
  136. package/dist/evals/agentDiff.d.ts +13 -0
  137. package/dist/evals/agentDiff.js +11 -0
  138. package/dist/evals/canonical.d.ts +3 -0
  139. package/dist/evals/canonical.js +24 -0
  140. package/dist/evals/caseTask.d.ts +3 -0
  141. package/dist/evals/caseTask.js +9 -0
  142. package/dist/evals/compare.d.ts +94 -0
  143. package/dist/evals/compare.js +201 -0
  144. package/dist/evals/constants.d.ts +62 -0
  145. package/dist/evals/constants.js +97 -0
  146. package/dist/evals/engine/FakeEngine.d.ts +33 -0
  147. package/dist/evals/engine/FakeEngine.js +177 -0
  148. package/dist/evals/engine/index.d.ts +9 -0
  149. package/dist/evals/engine/index.js +19 -0
  150. package/dist/evals/engine/promptfoo/PromptfooEngine.d.ts +52 -0
  151. package/dist/evals/engine/promptfoo/PromptfooEngine.js +312 -0
  152. package/dist/evals/engine/promptfoo/errors.d.ts +5 -0
  153. package/dist/evals/engine/promptfoo/errors.js +8 -0
  154. package/dist/evals/engine/promptfoo/generate.d.ts +30 -0
  155. package/dist/evals/engine/promptfoo/generate.js +345 -0
  156. package/dist/evals/engine/promptfoo/guard.d.ts +10 -0
  157. package/dist/evals/engine/promptfoo/guard.js +116 -0
  158. package/dist/evals/engine/promptfoo/install.d.ts +17 -0
  159. package/dist/evals/engine/promptfoo/install.js +73 -0
  160. package/dist/evals/engine/promptfoo/judgeProviders.d.ts +2 -0
  161. package/dist/evals/engine/promptfoo/judgeProviders.js +9 -0
  162. package/dist/evals/engine/promptfoo/judgeServices.d.ts +6 -0
  163. package/dist/evals/engine/promptfoo/judgeServices.js +41 -0
  164. package/dist/evals/engine/promptfoo/locate.d.ts +21 -0
  165. package/dist/evals/engine/promptfoo/locate.js +68 -0
  166. package/dist/evals/engine/promptfoo/nodeVersion.d.ts +7 -0
  167. package/dist/evals/engine/promptfoo/nodeVersion.js +14 -0
  168. package/dist/evals/engine/promptfoo/normalize.d.ts +66 -0
  169. package/dist/evals/engine/promptfoo/normalize.js +261 -0
  170. package/dist/evals/engine/promptfoo/pinned.d.ts +5 -0
  171. package/dist/evals/engine/promptfoo/pinned.js +5 -0
  172. package/dist/evals/engine/promptfoo/rubricPrompt.d.ts +14 -0
  173. package/dist/evals/engine/promptfoo/rubricPrompt.js +105 -0
  174. package/dist/evals/engine/promptfoo/runTokens.d.ts +18 -0
  175. package/dist/evals/engine/promptfoo/runTokens.js +31 -0
  176. package/dist/evals/engine/promptfoo/status.d.ts +13 -0
  177. package/dist/evals/engine/promptfoo/status.js +16 -0
  178. package/dist/evals/estimate.d.ts +56 -0
  179. package/dist/evals/estimate.js +66 -0
  180. package/dist/evals/graders/codeGrader.d.ts +6 -0
  181. package/dist/evals/graders/codeGrader.js +85 -0
  182. package/dist/evals/graders/conversationCheckGrader.d.ts +6 -0
  183. package/dist/evals/graders/conversationCheckGrader.js +62 -0
  184. package/dist/evals/graders/fieldGrader.d.ts +11 -0
  185. package/dist/evals/graders/fieldGrader.js +117 -0
  186. package/dist/evals/graders/goal.d.ts +3 -0
  187. package/dist/evals/graders/goal.js +14 -0
  188. package/dist/evals/graders/index.d.ts +18 -0
  189. package/dist/evals/graders/index.js +34 -0
  190. package/dist/evals/graders/notApplicable.d.ts +5 -0
  191. package/dist/evals/graders/notApplicable.js +9 -0
  192. package/dist/evals/graders/path.d.ts +26 -0
  193. package/dist/evals/graders/path.js +75 -0
  194. package/dist/evals/graders/referenceGrader.d.ts +5 -0
  195. package/dist/evals/graders/referenceGrader.js +59 -0
  196. package/dist/evals/graders/schemaGrader.d.ts +5 -0
  197. package/dist/evals/graders/schemaGrader.js +29 -0
  198. package/dist/evals/graders/subject.d.ts +6 -0
  199. package/dist/evals/graders/subject.js +33 -0
  200. package/dist/evals/graders/toolCallsGrader.d.ts +6 -0
  201. package/dist/evals/graders/toolCallsGrader.js +100 -0
  202. package/dist/evals/graders/transcript.d.ts +12 -0
  203. package/dist/evals/graders/transcript.js +57 -0
  204. package/dist/evals/graders/types.d.ts +20 -0
  205. package/dist/evals/graders/types.js +1 -0
  206. package/dist/evals/judgeProviders.d.ts +16 -0
  207. package/dist/evals/judgeProviders.js +27 -0
  208. package/dist/evals/lineDiff.d.ts +5 -0
  209. package/dist/evals/lineDiff.js +34 -0
  210. package/dist/evals/listStatus.d.ts +31 -0
  211. package/dist/evals/listStatus.js +48 -0
  212. package/dist/evals/manager.d.ts +187 -0
  213. package/dist/evals/manager.js +795 -0
  214. package/dist/evals/plan.d.ts +65 -0
  215. package/dist/evals/plan.js +621 -0
  216. package/dist/evals/planInternalAgent.d.ts +19 -0
  217. package/dist/evals/planInternalAgent.js +205 -0
  218. package/dist/evals/providerKeys.d.ts +1 -0
  219. package/dist/evals/providerKeys.js +21 -0
  220. package/dist/evals/read/agentTargets.d.ts +37 -0
  221. package/dist/evals/read/agentTargets.js +101 -0
  222. package/dist/evals/read/api.d.ts +208 -0
  223. package/dist/evals/read/api.js +363 -0
  224. package/dist/evals/read/compare.d.ts +4 -0
  225. package/dist/evals/read/compare.js +39 -0
  226. package/dist/evals/read/datasets.d.ts +105 -0
  227. package/dist/evals/read/datasets.js +318 -0
  228. package/dist/evals/read/list.d.ts +66 -0
  229. package/dist/evals/read/list.js +182 -0
  230. package/dist/evals/read/results.d.ts +46 -0
  231. package/dist/evals/read/results.js +107 -0
  232. package/dist/evals/read/runs.d.ts +154 -0
  233. package/dist/evals/read/runs.js +295 -0
  234. package/dist/evals/read/suggestions.d.ts +43 -0
  235. package/dist/evals/read/suggestions.js +73 -0
  236. package/dist/evals/runner/FakeAgentBackend.d.ts +40 -0
  237. package/dist/evals/runner/FakeAgentBackend.js +82 -0
  238. package/dist/evals/runner/agentCaseRunner.d.ts +24 -0
  239. package/dist/evals/runner/agentCaseRunner.js +388 -0
  240. package/dist/evals/runner/caseRunner.d.ts +8 -0
  241. package/dist/evals/runner/caseRunner.js +28 -0
  242. package/dist/evals/runner/conversationSubject.d.ts +18 -0
  243. package/dist/evals/runner/conversationSubject.js +123 -0
  244. package/dist/evals/runner/internalAgentCaseRunner.d.ts +6 -0
  245. package/dist/evals/runner/internalAgentCaseRunner.js +250 -0
  246. package/dist/evals/runner/simulatorModel.d.ts +51 -0
  247. package/dist/evals/runner/simulatorModel.js +58 -0
  248. package/dist/evals/runner/simulatorPrompt.d.ts +29 -0
  249. package/dist/evals/runner/simulatorPrompt.js +59 -0
  250. package/dist/evals/runner/stageCaseRunner.d.ts +30 -0
  251. package/dist/evals/runner/stageCaseRunner.js +279 -0
  252. package/dist/evals/runner/userDriver.d.ts +71 -0
  253. package/dist/evals/runner/userDriver.js +104 -0
  254. package/dist/evals/scoring.d.ts +34 -0
  255. package/dist/evals/scoring.js +67 -0
  256. package/dist/evals/snapshot.d.ts +191 -0
  257. package/dist/evals/snapshot.js +70 -0
  258. package/dist/evals/stageDiff.d.ts +8 -0
  259. package/dist/evals/stageDiff.js +48 -0
  260. package/dist/evals/stats.d.ts +95 -0
  261. package/dist/evals/stats.js +220 -0
  262. package/dist/evals/statsAdapter.d.ts +4 -0
  263. package/dist/evals/statsAdapter.js +30 -0
  264. package/dist/evals/statsTypes.d.ts +51 -0
  265. package/dist/evals/statsTypes.js +18 -0
  266. package/dist/evals/storeError.d.ts +5 -0
  267. package/dist/evals/storeError.js +8 -0
  268. package/dist/evals/storeTypes.d.ts +207 -0
  269. package/dist/evals/storeTypes.js +1 -0
  270. package/dist/evals/tTable.d.ts +3 -0
  271. package/dist/evals/tTable.js +15 -0
  272. package/dist/evals/triage/constants.d.ts +26 -0
  273. package/dist/evals/triage/constants.js +33 -0
  274. package/dist/evals/triage/credentials.d.ts +13 -0
  275. package/dist/evals/triage/credentials.js +20 -0
  276. package/dist/evals/triage/jevClassifier.d.ts +14 -0
  277. package/dist/evals/triage/jevClassifier.js +124 -0
  278. package/dist/evals/triage/judgeClassifier.d.ts +10 -0
  279. package/dist/evals/triage/judgeClassifier.js +76 -0
  280. package/dist/evals/triage/prompts.d.ts +16 -0
  281. package/dist/evals/triage/prompts.js +64 -0
  282. package/dist/evals/triage/service.d.ts +79 -0
  283. package/dist/evals/triage/service.js +217 -0
  284. package/dist/evals/triage/stateBuilder.d.ts +19 -0
  285. package/dist/evals/triage/stateBuilder.js +125 -0
  286. package/dist/evals/triage/types.d.ts +60 -0
  287. package/dist/evals/triage/types.js +8 -0
  288. package/dist/evals/types.d.ts +357 -0
  289. package/dist/evals/types.js +4 -0
  290. package/dist/guide/cardContract.d.ts +133 -0
  291. package/dist/guide/cardContract.js +156 -0
  292. package/dist/guide/chat.d.ts +45 -0
  293. package/dist/guide/chat.js +378 -0
  294. package/dist/guide/knowledge/index.d.ts +14 -0
  295. package/dist/guide/knowledge/index.js +109 -0
  296. package/dist/guide/knowledge/topics/agents.d.ts +2 -0
  297. package/dist/guide/knowledge/topics/agents.js +58 -0
  298. package/dist/guide/knowledge/topics/bestPractices.d.ts +2 -0
  299. package/dist/guide/knowledge/topics/bestPractices.js +67 -0
  300. package/dist/guide/knowledge/topics/connections.d.ts +2 -0
  301. package/dist/guide/knowledge/topics/connections.js +66 -0
  302. package/dist/guide/knowledge/topics/consoleMap.d.ts +2 -0
  303. package/dist/guide/knowledge/topics/consoleMap.js +55 -0
  304. package/dist/guide/knowledge/topics/evals.d.ts +2 -0
  305. package/dist/guide/knowledge/topics/evals.js +72 -0
  306. package/dist/guide/knowledge/topics/limitations.d.ts +2 -0
  307. package/dist/guide/knowledge/topics/limitations.js +84 -0
  308. package/dist/guide/knowledge/topics/mcpSkillsBrowser.d.ts +2 -0
  309. package/dist/guide/knowledge/topics/mcpSkillsBrowser.js +57 -0
  310. package/dist/guide/knowledge/topics/memories.d.ts +2 -0
  311. package/dist/guide/knowledge/topics/memories.js +63 -0
  312. package/dist/guide/knowledge/topics/modelsAndProviders.d.ts +2 -0
  313. package/dist/guide/knowledge/topics/modelsAndProviders.js +56 -0
  314. package/dist/guide/knowledge/topics/overview.d.ts +2 -0
  315. package/dist/guide/knowledge/topics/overview.js +56 -0
  316. package/dist/guide/knowledge/topics/pipelines.d.ts +2 -0
  317. package/dist/guide/knowledge/topics/pipelines.js +93 -0
  318. package/dist/guide/knowledge/topics/stages.d.ts +2 -0
  319. package/dist/guide/knowledge/topics/stages.js +54 -0
  320. package/dist/guide/knowledge/topics/tasks.d.ts +2 -0
  321. package/dist/guide/knowledge/topics/tasks.js +52 -0
  322. package/dist/guide/knowledge/topics/triggers.d.ts +2 -0
  323. package/dist/guide/knowledge/topics/triggers.js +68 -0
  324. package/dist/guide/knowledge/topics/troubleshooting.d.ts +2 -0
  325. package/dist/guide/knowledge/topics/troubleshooting.js +85 -0
  326. package/dist/guide/knowledgeTools.d.ts +2 -0
  327. package/dist/guide/knowledgeTools.js +56 -0
  328. package/dist/guide/showUi.d.ts +6 -0
  329. package/dist/guide/showUi.js +546 -0
  330. package/dist/guide/threadStore.d.ts +48 -0
  331. package/dist/guide/threadStore.js +189 -0
  332. package/dist/guide/writeRoot.d.ts +11 -0
  333. package/dist/guide/writeRoot.js +70 -0
  334. package/dist/hosted/translate.js +2 -0
  335. package/dist/mcp/agentTools.js +12 -0
  336. package/dist/mcp/catalogTools.js +18 -20
  337. package/dist/mcp/catalogWriteTools.d.ts +8 -0
  338. package/dist/mcp/catalogWriteTools.js +225 -0
  339. package/dist/mcp/connectionTools.d.ts +3 -0
  340. package/dist/mcp/connectionTools.js +85 -0
  341. package/dist/mcp/controlTools.js +34 -1
  342. package/dist/mcp/deps.d.ts +16 -0
  343. package/dist/mcp/evalTools.d.ts +3 -0
  344. package/dist/mcp/evalTools.js +943 -0
  345. package/dist/mcp/memoryHostTools.d.ts +3 -0
  346. package/dist/mcp/memoryHostTools.js +72 -0
  347. package/dist/mcp/pipelineAuthorTools.js +14 -1
  348. package/dist/mcp/server.js +6 -0
  349. package/dist/mcp/tools.js +8 -0
  350. package/dist/mcp/triggerTools.js +77 -31
  351. package/dist/models/response.d.ts +7 -2
  352. package/dist/models/response.js +6 -1
  353. package/dist/operatorAgent/agentAuthorContext.d.ts +1 -1
  354. package/dist/operatorAgent/agentAuthorContext.js +1 -1
  355. package/dist/operatorAgent/evalGate.d.ts +22 -0
  356. package/dist/operatorAgent/evalGate.js +77 -0
  357. package/dist/operatorAgent/fakeHost.js +10 -2
  358. package/dist/operatorAgent/host.js +18 -2
  359. package/dist/operatorAgent/index.d.ts +1 -0
  360. package/dist/operatorAgent/index.js +1 -0
  361. package/dist/operatorAgent/internalAgents.d.ts +11 -0
  362. package/dist/operatorAgent/internalAgents.js +13 -0
  363. package/dist/operatorAgent/piModel.d.ts +5 -1
  364. package/dist/operatorAgent/piModel.js +32 -14
  365. package/dist/operatorAgent/profiles/agentAuthor.d.ts +3 -1
  366. package/dist/operatorAgent/profiles/agentAuthor.js +201 -32
  367. package/dist/operatorAgent/profiles/agentAuthorPlaybook.d.ts +1 -1
  368. package/dist/operatorAgent/profiles/agentAuthorPlaybook.js +48 -15
  369. package/dist/operatorAgent/profiles/authorReadable.d.ts +2 -0
  370. package/dist/operatorAgent/profiles/authorReadable.js +26 -0
  371. package/dist/operatorAgent/profiles/guideConfirm.d.ts +21 -0
  372. package/dist/operatorAgent/profiles/guideConfirm.js +100 -0
  373. package/dist/operatorAgent/profiles/guideTools.d.ts +7 -0
  374. package/dist/operatorAgent/profiles/guideTools.js +123 -0
  375. package/dist/operatorAgent/profiles/stageflowGuide.d.ts +7 -0
  376. package/dist/operatorAgent/profiles/stageflowGuide.js +132 -0
  377. package/dist/operatorAgent/profiles/workshopAuthor.js +23 -0
  378. package/dist/operatorAgent/profiles/workshopAuthorPlaybook.d.ts +1 -1
  379. package/dist/operatorAgent/profiles/workshopAuthorPlaybook.js +9 -1
  380. package/dist/operatorAgent/profiles/workshopAuthorTools.d.ts +2 -0
  381. package/dist/operatorAgent/profiles/workshopAuthorTools.js +197 -9
  382. package/dist/operatorAgent/types.d.ts +23 -0
  383. package/dist/package-meta.d.ts +1 -1
  384. package/dist/package-meta.js +1 -1
  385. package/dist/runstore/port.d.ts +43 -0
  386. package/dist/runstore/retention.d.ts +2 -1
  387. package/dist/runstore/retention.js +3 -7
  388. package/dist/runstore/runStatusClock.d.ts +17 -0
  389. package/dist/runstore/runStatusClock.js +19 -0
  390. package/dist/runstore/sqlite/SqliteRunStore.d.ts +29 -0
  391. package/dist/runstore/sqlite/SqliteRunStore.js +144 -50
  392. package/dist/runstore/sqlite/evalStore.d.ts +20 -0
  393. package/dist/runstore/sqlite/evalStore.js +541 -0
  394. package/dist/runstore/sqlite/migrations/015-evals.d.ts +12 -0
  395. package/dist/runstore/sqlite/migrations/015-evals.js +157 -0
  396. package/dist/runstore/sqlite/migrations/016-eval-subject-ref.d.ts +12 -0
  397. package/dist/runstore/sqlite/migrations/016-eval-subject-ref.js +20 -0
  398. package/dist/runstore/sqlite/migrations/017-eval-result-suggestions.d.ts +11 -0
  399. package/dist/runstore/sqlite/migrations/017-eval-result-suggestions.js +36 -0
  400. package/dist/runstore/sqlite/migrations/index.js +6 -0
  401. package/dist/runstore/sqlite/suggestionStore.d.ts +14 -0
  402. package/dist/runstore/sqlite/suggestionStore.js +132 -0
  403. package/dist/runstore/workspaceLayout.js +6 -1
  404. package/dist/runtime/artifactDiskInspect.d.ts +14 -0
  405. package/dist/runtime/artifactDiskInspect.js +52 -0
  406. package/dist/runtime/artifactPath.d.ts +24 -0
  407. package/dist/runtime/artifactPath.js +84 -0
  408. package/dist/runtime/completionCheckRunner.js +15 -43
  409. package/dist/runtime/githubPollSource.d.ts +22 -4
  410. package/dist/runtime/githubPollSource.js +93 -8
  411. package/dist/runtime/pipelineRunner.d.ts +2 -1
  412. package/dist/runtime/pipelineRunner.js +2 -0
  413. package/dist/runtime/priorArtifactGrants.d.ts +8 -0
  414. package/dist/runtime/priorArtifactGrants.js +105 -0
  415. package/dist/runtime/runActionEligibility.d.ts +46 -0
  416. package/dist/runtime/runActionEligibility.js +123 -0
  417. package/dist/runtime/runManager.d.ts +6 -2
  418. package/dist/runtime/runManager.js +60 -16
  419. package/dist/runtime/runRetentionSweep.js +2 -2
  420. package/dist/runtime/runRetryCoordinator.d.ts +2 -14
  421. package/dist/runtime/runRetryCoordinator.js +3 -67
  422. package/dist/runtime/sandboxContainer.d.ts +7 -0
  423. package/dist/runtime/sandboxContainer.js +48 -6
  424. package/dist/runtime/sandboxDesk.d.ts +2 -1
  425. package/dist/runtime/sandboxDesk.js +11 -12
  426. package/dist/runtime/stageEnvironment.js +1 -0
  427. package/dist/runtime/stageRoots.d.ts +12 -0
  428. package/dist/runtime/stageSandbox.d.ts +2 -1
  429. package/dist/runtime/stageSandbox.js +18 -2
  430. package/dist/runtime/stageWorker.js +20 -0
  431. package/dist/server/agentAuthorRoutes.js +59 -1
  432. package/dist/server/bootstrap.d.ts +13 -0
  433. package/dist/server/bootstrap.js +69 -0
  434. package/dist/server/controlToken.js +3 -0
  435. package/dist/server/evalInternalRoutes.d.ts +14 -0
  436. package/dist/server/evalInternalRoutes.js +87 -0
  437. package/dist/server/evalRouteContext.d.ts +46 -0
  438. package/dist/server/evalRouteContext.js +43 -0
  439. package/dist/server/evalRoutes.d.ts +5 -0
  440. package/dist/server/evalRoutes.js +1456 -0
  441. package/dist/server/evalTriageRoutes.d.ts +2 -0
  442. package/dist/server/evalTriageRoutes.js +95 -0
  443. package/dist/server/guideRoutes.d.ts +5 -0
  444. package/dist/server/guideRoutes.js +166 -0
  445. package/dist/server/http.d.ts +15 -0
  446. package/dist/server/http.js +67 -3
  447. package/dist/server/internalAgentRoutes.d.ts +6 -0
  448. package/dist/server/internalAgentRoutes.js +12 -0
  449. package/dist/server/mcpHost.js +5 -0
  450. package/dist/toolkit/meta.d.ts +1 -1
  451. package/dist/toolkit/meta.js +53 -0
  452. package/dist/toolkit/profiles.d.ts +5 -0
  453. package/dist/toolkit/profiles.js +13 -1
  454. package/dist/tools/askOperator.js +2 -1
  455. package/dist/tools/emitStageEnvelope.d.ts +17 -16
  456. package/dist/tools/emitStageEnvelope.js +46 -32
  457. package/dist/tools/stageToolNames.d.ts +4 -0
  458. package/dist/tools/stageToolNames.js +4 -0
  459. package/dist/tools/workingState.d.ts +40 -0
  460. package/dist/tools/workingState.js +108 -0
  461. package/dist/tools/writeStageArtifact.d.ts +0 -9
  462. package/dist/tools/writeStageArtifact.js +2 -1
  463. package/dist/types/stageflowManifest.d.ts +6 -0
  464. package/dist/ui/assets/{MarkdownText-D7tYaIFO.js → MarkdownText-S5C_vemc.js} +2 -2
  465. package/dist/ui/assets/adapters-C0l4ruiR.js +17 -0
  466. package/dist/ui/assets/chat-CjnsmvqR.js +2 -0
  467. package/dist/ui/assets/chat-DFDd4UjS.css +2 -0
  468. package/dist/ui/assets/{main-BFo79krC.css → main-Del1GeLf.css} +1 -1
  469. package/dist/ui/assets/main-_yXVqcW9.js +277 -0
  470. package/dist/ui/chat.html +3 -4
  471. package/dist/ui/index.html +3 -4
  472. package/dist/workshop/chatTurn.js +1 -1
  473. package/dist/workshop/workshopPin.d.ts +3 -3
  474. package/dist/workshop/workshopPin.js +16 -15
  475. package/examples/README.md +2 -0
  476. package/examples/compaction-stress/README.md +30 -0
  477. package/examples/compaction-stress/check-run.mjs +53 -0
  478. package/examples/compaction-stress/collect-evidence.yaml +60 -0
  479. package/examples/compaction-stress/compaction-stress.pipeline.yaml +141 -0
  480. package/examples/compaction-stress/compaction-stress.task.yaml +15 -0
  481. package/examples/compaction-stress/generate-evidence.mjs +110 -0
  482. package/examples/compaction-stress/root-cause.yaml +26 -0
  483. package/examples/compaction-stress/stageflow.yaml +9 -0
  484. package/examples/compaction-stress/write-postmortem.yaml +40 -0
  485. package/examples/document-policy-review/README.md +35 -0
  486. package/examples/document-policy-review/agents/compliance.agent.yaml +42 -0
  487. package/examples/document-policy-review/documents/acme-vendor-sow.md +15 -0
  488. package/examples/document-policy-review/documents/support-runbook.md +13 -0
  489. package/examples/document-policy-review/policies/acceptable-use.md +13 -0
  490. package/examples/document-policy-review/policies/data-handling.md +17 -0
  491. package/examples/document-policy-review/policies/vendor-security.md +17 -0
  492. package/examples/evals/README.md +141 -0
  493. package/examples/evals/critique-sample.dataset.jsonl +8 -0
  494. package/examples/evals/critique-sample.eval.yaml +34 -0
  495. package/examples/evals/critique-sample.task.yaml +4 -0
  496. package/examples/evals/eval-sample.pipeline.yaml +35 -0
  497. package/examples/evals/guide-behavior.dataset.jsonl +15 -0
  498. package/examples/evals/guide-behavior.eval.yaml +35 -0
  499. package/examples/evals/guide-depth.dataset.jsonl +35 -0
  500. package/examples/evals/guide-depth.eval.yaml +169 -0
  501. package/examples/evals/support-sample.agent.yaml +20 -0
  502. package/examples/evals/support-sample.dataset.jsonl +6 -0
  503. package/examples/evals/support-sample.eval.yaml +38 -0
  504. package/examples/memory/evals/guide-behavior.dataset.jsonl +15 -0
  505. package/examples/memory/evals/guide-behavior.eval.yaml +35 -0
  506. package/examples/memory/evals/guide-depth.dataset.jsonl +35 -0
  507. package/examples/memory/evals/guide-depth.eval.yaml +169 -0
  508. package/examples/stageflow.yaml +6 -0
  509. package/package.json +1 -1
  510. package/skills/stageflow/SKILL.md +5 -2
  511. package/skills/stageflow/references/control-surface.md +4 -2
  512. package/skills/stageflow/references/evals.md +68 -0
  513. package/skills/stageflow-author/SKILL.md +4 -0
  514. package/skills/stageflow-run/SKILL.md +4 -0
  515. package/dist/ui/assets/AssistantRuntimeProvider-CsiPFhCT.js +0 -9
  516. package/dist/ui/assets/ReadonlyStore-BfXqHykm.js +0 -6
  517. package/dist/ui/assets/chat-BbLukq9W.js +0 -5
  518. package/dist/ui/assets/chat-zIZU_bP1.css +0 -2
  519. package/dist/ui/assets/main-CijYMeM0.js +0 -259
@@ -0,0 +1,795 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { rm } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { stringify as stringifyYaml } from "yaml";
5
+ import { loadEvalOutcome } from "../config/loadEval.js";
6
+ import { EVAL_RUN_ID_PREFIX, } from "./constants.js";
7
+ import { getEngine } from "./engine/index.js";
8
+ import { buildEvalPlan } from "./plan.js";
9
+ import { scoreResult } from "./scoring.js";
10
+ import { computeStats } from "./stats.js";
11
+ import { toGradeRecords, toResultRecord } from "./statsAdapter.js";
12
+ import { isConversationTarget } from "./types.js";
13
+ export const EVAL_HOST_STOPPED_REASON = "Host stopped while the run was in progress";
14
+ export const EVAL_DEFAULT_ENGINE = "promptfoo";
15
+ export const EVAL_ORPHAN_SESSION_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
16
+ export class EvalRunError extends Error {
17
+ code;
18
+ findings;
19
+ constructor(code, message, findings) {
20
+ super(message);
21
+ this.code = code;
22
+ this.findings = findings;
23
+ this.name = "EvalRunError";
24
+ }
25
+ }
26
+ const key = (caseId, repeatIndex) => `${caseId}:${repeatIndex}`;
27
+ function isRecord(value) {
28
+ return typeof value === "object" && value !== null && !Array.isArray(value);
29
+ }
30
+ function safeMessage(err) {
31
+ const raw = err instanceof Error ? err.message : typeof err === "string" ? err : "";
32
+ const first = raw.split("\n")[0]?.trim() ?? "";
33
+ return first === "" ? "Eval engine failed" : first.slice(0, 300);
34
+ }
35
+ const RESULT_STATUS_BY_CODE = {
36
+ EVAL_STAGE_FAILED: "stage_failed",
37
+ EVAL_STAGE_TIMEOUT: "stage_failed",
38
+ EVAL_STAGE_NEEDS_INPUT: "needs_input",
39
+ EVAL_BUDGET_EXCEEDED: "skipped_budget",
40
+ EVAL_CANCELLED: "cancelled",
41
+ EVAL_ENGINE_ERROR: "error",
42
+ EVAL_AGENT_FAILED: "stage_failed",
43
+ EVAL_AGENT_EMPTY_REPLY: "error",
44
+ EVAL_AGENT_TIMEOUT: "stage_failed",
45
+ EVAL_SIMULATOR_ERROR: "error",
46
+ };
47
+ function conversationFields(output) {
48
+ const { transcript: _transport, ...stored } = output;
49
+ return {
50
+ output: stored,
51
+ turns: output.turns,
52
+ toolCallCount: output.tool_calls.length,
53
+ };
54
+ }
55
+ const EXECUTED = ["completed", "stage_failed", "needs_input", "error"];
56
+ function scoringGraders(plan) {
57
+ return plan.graders.map((g) => ({
58
+ id: g.id,
59
+ type: g.type,
60
+ weight: g.weight,
61
+ mustPass: g.mustPass,
62
+ ...(g.type === "rubric" ? { scale: g.scale } : {}),
63
+ ...(g.type === "rubric" || g.type === "reference" ? { passAt: g.passAt } : {}),
64
+ }));
65
+ }
66
+ function detailsOf(details) {
67
+ if (details === undefined || details === null)
68
+ return null;
69
+ return isRecord(details) ? details : { value: details };
70
+ }
71
+ function gradeInput(g) {
72
+ return {
73
+ graderId: g.graderId,
74
+ graderType: g.graderType,
75
+ status: g.status,
76
+ passed: g.passed ?? null,
77
+ score: g.score ?? null,
78
+ rawValue: g.rawValue ?? null,
79
+ reason: g.reason ?? null,
80
+ details: detailsOf(g.details),
81
+ errorCode: g.errorCode ?? null,
82
+ judgeModel: g.judgeModel ?? null,
83
+ judgeCostUsd: g.judgeCostUsd ?? null,
84
+ judgeTokensIn: g.judgeTokensIn ?? null,
85
+ judgeTokensOut: g.judgeTokensOut ?? null,
86
+ };
87
+ }
88
+ export class EvalRunManager {
89
+ deps;
90
+ store;
91
+ runner;
92
+ engines;
93
+ engineName;
94
+ now;
95
+ live;
96
+ reserved = false;
97
+ trying = false;
98
+ tryingRunId = null;
99
+ constructor(deps) {
100
+ this.deps = deps;
101
+ this.store = deps.store;
102
+ this.runner = deps.stageRunner;
103
+ this.engines = deps.engines ?? getEngine;
104
+ this.engineName = deps.engineName ?? EVAL_DEFAULT_ENGINE;
105
+ this.now = deps.now ?? (() => new Date());
106
+ }
107
+ activeRunId() {
108
+ return this.live?.evalRunId ?? null;
109
+ }
110
+ isExecuting(evalRunId) {
111
+ return this.live?.evalRunId === evalRunId || this.tryingRunId === evalRunId;
112
+ }
113
+ getLive(evalRunId) {
114
+ const live = this.live;
115
+ if (live === undefined || live.evalRunId !== evalRunId)
116
+ return null;
117
+ return { evalRunId, phases: [...live.phases.values()] };
118
+ }
119
+ claim() {
120
+ if (this.live !== undefined || this.reserved || this.trying) {
121
+ throw new EvalRunError("EVAL_RUN_ACTIVE", this.trying ? "A case is being tried; wait for it to finish" : "An eval run is already active");
122
+ }
123
+ this.reserved = true;
124
+ }
125
+ async start(input) {
126
+ this.claim();
127
+ let handedOff = false;
128
+ try {
129
+ const engine = this.engines(this.engineName);
130
+ const engineInfo = {
131
+ name: engine.name,
132
+ version: await engine.version(),
133
+ nodeVersion: process.versions.node,
134
+ };
135
+ const base = {
136
+ projectRoot: input.projectRoot,
137
+ evalPath: input.evalPath,
138
+ ...(input.overrides !== undefined ? { overrides: input.overrides } : {}),
139
+ evalRunId: "er_pending",
140
+ engine: engineInfo,
141
+ failedCaseIdsOf: (id) => this.failedCaseIds(input.projectRoot, input.evalPath, id),
142
+ ...(this.deps.isKnownModel ? { isKnownModel: this.deps.isKnownModel } : {}),
143
+ ...this.agentsInput(),
144
+ };
145
+ const first = await buildEvalPlan(base);
146
+ if (!first.ok)
147
+ throw new EvalRunError("EVAL_INVALID", "Eval is invalid", first.findings);
148
+ const ordinals = await this.store.recordGraderVersions(input.projectRoot, first.plan.evalId, first.plan.graders.map((g) => ({ graderId: g.id, graderHash: g.hash })));
149
+ const built = await buildEvalPlan({ ...base, graderOrdinals: ordinals });
150
+ if (!built.ok)
151
+ throw new EvalRunError("EVAL_INVALID", "Eval is invalid", built.findings);
152
+ const { plan: draft, snapshot, fingerprint, components } = built;
153
+ try {
154
+ engine.validatePlan?.(draft);
155
+ }
156
+ catch (err) {
157
+ throw new EvalRunError("EVAL_INVALID", err instanceof Error ? err.message : String(err));
158
+ }
159
+ this.requireRealToolsConsent(draft, input.overrides);
160
+ const stageTarget = snapshot.target.kind === "stage" ? snapshot.target : null;
161
+ const agentTarget = snapshot.target.kind === "agent" ? snapshot.target : null;
162
+ const row = await this.store.createEvalRun({
163
+ projectRoot: input.projectRoot,
164
+ evalId: draft.evalId,
165
+ evalPath: snapshot.eval.path,
166
+ evalHash: snapshot.eval.hash,
167
+ targetKind: agentTarget !== null ? "agent" : "stage",
168
+ targetRef: agentTarget !== null
169
+ ? { agent_id: agentTarget.agent_id, revision: agentTarget.revision }
170
+ : {
171
+ ...(stageTarget?.pipeline_path != null ? { pipeline_path: stageTarget.pipeline_path } : {}),
172
+ ...(stageTarget?.stage_id != null ? { stage_id: stageTarget.stage_id } : {}),
173
+ ...(stageTarget?.file != null ? { file: stageTarget.file } : {}),
174
+ },
175
+ targetVersionHash: draft.targetVersionHash,
176
+ datasetPath: snapshot.dataset.path,
177
+ datasetHash: snapshot.dataset.hash,
178
+ config: snapshot,
179
+ configFingerprint: fingerprint,
180
+ configComponents: components,
181
+ status: "queued",
182
+ repeats: draft.repeats,
183
+ passThreshold: draft.passThreshold,
184
+ maxCostUsd: draft.maxCostUsd,
185
+ casesTotal: draft.cases.length,
186
+ resultsTotal: draft.cases.length * draft.repeats,
187
+ engineName: engineInfo.name,
188
+ engineVersion: engineInfo.version,
189
+ stageflowVersion: this.deps.stageflowVersion,
190
+ startedVia: input.startedVia,
191
+ ...(input.label !== undefined ? { label: input.label } : {}),
192
+ ...(input.callerId !== undefined ? { callerId: input.callerId } : {}),
193
+ });
194
+ const plan = { ...draft, evalRunId: row.evalRunId };
195
+ await this.store.insertEvalCases(row.evalRunId, plan.cases.map((c) => {
196
+ const { position, ...rest } = c;
197
+ return { caseId: c.id, position, case: rest };
198
+ }));
199
+ const live = {
200
+ evalRunId: row.evalRunId,
201
+ plan,
202
+ abort: new AbortController(),
203
+ phases: new Map(),
204
+ emitted: new Set(),
205
+ writes: Promise.resolve(),
206
+ cancelRequested: false,
207
+ skippedBudget: false,
208
+ resultsDone: 0,
209
+ finished: undefined,
210
+ };
211
+ this.live = live;
212
+ this.reserved = false;
213
+ handedOff = true;
214
+ live.finished = this.execute(live, engine);
215
+ live.finished.catch(() => undefined);
216
+ return { evalRunId: row.evalRunId, runNumber: row.runNumber };
217
+ }
218
+ finally {
219
+ if (!handedOff)
220
+ this.reserved = false;
221
+ }
222
+ }
223
+ async failedCaseIds(projectRoot, evalPath, evalRunId) {
224
+ const run = await this.store.getEvalRun(evalRunId);
225
+ if (run === null || run.projectRoot !== projectRoot)
226
+ return undefined;
227
+ const evalRel = path.relative(projectRoot, path.resolve(projectRoot, evalPath)).split(path.sep).join("/");
228
+ if (run.evalPath !== evalRel)
229
+ return undefined;
230
+ const results = await this.store.listEvalResults(evalRunId);
231
+ const failed = results.filter((r) => EXECUTED.includes(r.status) && !r.passed);
232
+ return [...new Set(failed.map((r) => r.caseId))];
233
+ }
234
+ makeIo(plan, onResult, onPhase) {
235
+ const { logger } = this.deps;
236
+ return {
237
+ runCase: (req) => this.runner.runCase(plan, req),
238
+ onResult,
239
+ reportJudgeCost: (usd) => {
240
+ if (Number.isFinite(usd) && usd > 0)
241
+ this.runner.addSpend(plan.evalRunId, usd);
242
+ },
243
+ onPhase,
244
+ log: (level, message) => {
245
+ if (level === "info")
246
+ logger?.info?.("eval.engine", message);
247
+ else
248
+ logger?.[level]("eval.engine", message);
249
+ },
250
+ };
251
+ }
252
+ async runHook(name, hook) {
253
+ try {
254
+ await hook();
255
+ }
256
+ catch (err) {
257
+ this.deps.logger?.warn("eval.hook_failed", `${name}: ${safeMessage(err)}`);
258
+ }
259
+ }
260
+ async execute(live, engine) {
261
+ const { plan, evalRunId } = live;
262
+ try {
263
+ await this.store.updateEvalRunProgress(evalRunId, {
264
+ status: "running",
265
+ startedAt: this.now().toISOString(),
266
+ });
267
+ const io = this.makeIo(plan, (result) => this.enqueuePersist(live, result), (caseId, repeatIndex, phase) => {
268
+ const k = key(caseId, repeatIndex);
269
+ if (phase === "done")
270
+ live.phases.delete(k);
271
+ else
272
+ live.phases.set(k, { caseId, repeatIndex, phase });
273
+ });
274
+ const { onRunStarted } = this.deps;
275
+ if (onRunStarted) {
276
+ await this.runHook("onRunStarted", () => onRunStarted(evalRunId, {
277
+ plan,
278
+ engineName: engine.name,
279
+ runCase: io.runCase,
280
+ signal: live.abort.signal,
281
+ }));
282
+ }
283
+ let crashed = false;
284
+ let crash;
285
+ try {
286
+ await engine.run(plan, io, live.abort.signal);
287
+ }
288
+ catch (err) {
289
+ crashed = true;
290
+ crash = err;
291
+ this.deps.logger?.error("eval.engine_failed", safeMessage(err));
292
+ }
293
+ await live.writes;
294
+ return await this.finish(live, crashed, crash);
295
+ }
296
+ catch (err) {
297
+ this.deps.logger?.error("eval.finish_failed", safeMessage(err));
298
+ await live.writes.catch(() => undefined);
299
+ return await this.finishFailed(live, safeMessage(err));
300
+ }
301
+ finally {
302
+ live.phases.clear();
303
+ await this.cleanupWorkDir(evalRunId);
304
+ const { onRunFinished } = this.deps;
305
+ if (onRunFinished)
306
+ await this.runHook("onRunFinished", () => onRunFinished(evalRunId));
307
+ if (this.live === live)
308
+ this.live = undefined;
309
+ }
310
+ }
311
+ enqueuePersist(live, result) {
312
+ const k = key(result.caseId, result.repeatIndex);
313
+ if (live.emitted.has(k))
314
+ return;
315
+ live.emitted.add(k);
316
+ live.phases.delete(k);
317
+ const input = this.resultInput(live.plan, result);
318
+ if (input.status === "skipped_budget")
319
+ live.skippedBudget = true;
320
+ const stopReason = this.runner.stopReason?.(live.evalRunId);
321
+ if (stopReason !== undefined && live.providerStop === undefined && !live.cancelRequested) {
322
+ live.providerStop = stopReason;
323
+ live.abort.abort();
324
+ void this.runner.cancelAll(live.evalRunId).catch(() => undefined);
325
+ }
326
+ live.writes = live.writes.then(async () => {
327
+ if (live.persistError !== undefined)
328
+ return;
329
+ try {
330
+ await this.store.upsertEvalResult(input);
331
+ live.resultsDone += 1;
332
+ await this.store.updateEvalRunProgress(live.evalRunId, {
333
+ resultsDone: live.resultsDone,
334
+ costUsd: this.runner.spend(live.evalRunId),
335
+ });
336
+ }
337
+ catch (err) {
338
+ live.persistError = err;
339
+ live.abort.abort();
340
+ this.deps.logger?.error("eval.persist_failed", safeMessage(err));
341
+ }
342
+ });
343
+ }
344
+ resultInput(plan, nr) {
345
+ const finishedAt = this.now();
346
+ const { run } = nr;
347
+ const base = { evalRunId: plan.evalRunId, caseId: nr.caseId, repeatIndex: nr.repeatIndex };
348
+ const timing = (latencyMs) => ({
349
+ startedAt: latencyMs !== undefined ? new Date(finishedAt.getTime() - latencyMs).toISOString() : null,
350
+ finishedAt: finishedAt.toISOString(),
351
+ });
352
+ if (!run.ok) {
353
+ const status = RESULT_STATUS_BY_CODE[run.code] ?? "error";
354
+ const scored = scoreResult({
355
+ graders: [],
356
+ grades: [],
357
+ passThreshold: plan.passThreshold,
358
+ status,
359
+ latencyMs: run.latencyMs ?? null,
360
+ costUsd: run.costUsd ?? null,
361
+ budget: plan.budget,
362
+ });
363
+ return {
364
+ ...base,
365
+ status,
366
+ errorCode: run.code,
367
+ errorMessage: run.message,
368
+ stageRunId: run.stageRunId ?? null,
369
+ ...(run.subjectRef !== undefined || run.stageRunId !== undefined
370
+ ? { subjectRef: run.subjectRef ?? run.stageRunId ?? null }
371
+ : {}),
372
+ ...(run.output !== undefined ? conversationFields(run.output) : {}),
373
+ latencyMs: run.latencyMs ?? null,
374
+ costUsd: run.costUsd ?? null,
375
+ score: null,
376
+ passed: false,
377
+ hasGraderErrors: false,
378
+ budgetWarnings: scored.budgetWarnings,
379
+ ...timing(run.latencyMs),
380
+ };
381
+ }
382
+ const scored = scoreResult({
383
+ graders: scoringGraders(plan),
384
+ grades: nr.grades.map((g) => ({
385
+ graderId: g.graderId,
386
+ status: g.status,
387
+ passed: g.passed ?? null,
388
+ score: g.score ?? null,
389
+ rawValue: g.rawValue ?? null,
390
+ })),
391
+ passThreshold: plan.passThreshold,
392
+ status: "completed",
393
+ latencyMs: run.latencyMs,
394
+ costUsd: run.costUsd,
395
+ budget: plan.budget,
396
+ });
397
+ const { output } = run;
398
+ return {
399
+ ...base,
400
+ status: "completed",
401
+ stageRunId: run.stageRunId ?? null,
402
+ subjectRef: run.subjectRef ?? run.stageRunId ?? null,
403
+ ...(output.kind === "conversation"
404
+ ? conversationFields(output)
405
+ : {
406
+ output: {
407
+ status: output.status,
408
+ summary: output.summary,
409
+ ...(output.payload !== undefined ? { payload: output.payload } : {}),
410
+ artifacts: output.artifacts,
411
+ },
412
+ }),
413
+ latencyMs: run.latencyMs,
414
+ costUsd: run.costUsd,
415
+ tokensIn: run.tokensIn,
416
+ tokensOut: run.tokensOut,
417
+ score: scored.score,
418
+ passed: scored.passed,
419
+ hasGraderErrors: scored.hasGraderErrors,
420
+ budgetWarnings: scored.budgetWarnings,
421
+ ...timing(run.latencyMs),
422
+ grades: nr.grades.map(gradeInput),
423
+ };
424
+ }
425
+ statsFor(plan, results) {
426
+ return computeStats({
427
+ ...(plan.target?.kind === "agent" ? { targetKind: "agent" } : {}),
428
+ results: results.map(toResultRecord),
429
+ grades: results.flatMap(toGradeRecords),
430
+ graders: plan.graders.map((g) => ({ id: g.id, type: g.type, hash: g.hash })),
431
+ repeats: plan.repeats,
432
+ passThreshold: plan.passThreshold,
433
+ });
434
+ }
435
+ summaryOf(stats) {
436
+ return {
437
+ pass_rate: stats.pass_rate,
438
+ pass_rate_ci: stats.pass_rate_ci,
439
+ results_executed: stats.results_executed,
440
+ results_passed: stats.results_passed,
441
+ errored: stats.errored,
442
+ reliability: stats.reliability,
443
+ mean_score: stats.mean_score,
444
+ cost_total: stats.cost_total,
445
+ latency_p50: stats.latency_p50,
446
+ flaky_count: stats.flaky_cases.length,
447
+ ...(stats.mean_turns !== undefined ? { mean_turns: stats.mean_turns } : {}),
448
+ ...(stats.mean_tool_calls !== undefined ? { mean_tool_calls: stats.mean_tool_calls } : {}),
449
+ };
450
+ }
451
+ async fillRemainder(live, kind, message) {
452
+ const { plan } = live;
453
+ const finishedAt = this.now().toISOString();
454
+ const detail = kind === "cancelled"
455
+ ? { errorCode: "EVAL_CANCELLED", errorMessage: message ?? "Eval run was cancelled" }
456
+ : kind === "skipped_budget"
457
+ ? { errorCode: "EVAL_BUDGET_EXCEEDED", errorMessage: `Eval spend reached the $${plan.maxCostUsd} limit` }
458
+ : { errorCode: "EVAL_ENGINE_ERROR", errorMessage: "Engine finished without a result for this case" };
459
+ for (const c of plan.cases) {
460
+ for (let repeatIndex = 0; repeatIndex < plan.repeats; repeatIndex++) {
461
+ const k = key(c.id, repeatIndex);
462
+ if (live.emitted.has(k))
463
+ continue;
464
+ live.emitted.add(k);
465
+ await this.store.upsertEvalResult({
466
+ evalRunId: plan.evalRunId,
467
+ caseId: c.id,
468
+ repeatIndex,
469
+ status: kind,
470
+ ...detail,
471
+ score: null,
472
+ passed: false,
473
+ finishedAt,
474
+ });
475
+ live.resultsDone += 1;
476
+ }
477
+ }
478
+ }
479
+ async finish(live, crashed, crash) {
480
+ const { plan, evalRunId } = live;
481
+ const total = plan.cases.length * plan.repeats;
482
+ let status = "completed";
483
+ let reason = null;
484
+ if (live.persistError !== undefined) {
485
+ status = "failed";
486
+ reason = "Could not save eval results";
487
+ }
488
+ else if (crashed) {
489
+ status = "failed";
490
+ reason = safeMessage(crash);
491
+ }
492
+ else if (live.providerStop !== undefined && !live.cancelRequested) {
493
+ status = "failed";
494
+ reason = live.providerStop;
495
+ await this.fillRemainder(live, "cancelled", live.providerStop);
496
+ }
497
+ else if (live.cancelRequested) {
498
+ status = "cancelled";
499
+ reason = "Cancelled";
500
+ await this.fillRemainder(live, "cancelled");
501
+ }
502
+ else if (live.skippedBudget || (live.emitted.size < total && this.runner.spend(evalRunId) >= plan.maxCostUsd)) {
503
+ status = "budget_stopped";
504
+ reason = `Reached the $${plan.maxCostUsd} cost limit`;
505
+ await this.fillRemainder(live, "skipped_budget");
506
+ }
507
+ else if (live.emitted.size < total) {
508
+ await this.fillRemainder(live, "error");
509
+ }
510
+ const results = await this.store.listEvalResults(evalRunId);
511
+ const stats = this.statsFor(plan, results);
512
+ const passed = status === "completed" && stats.pass_rate !== null && stats.pass_rate + 1e-9 >= plan.passThreshold;
513
+ await this.store.updateEvalRunProgress(evalRunId, { resultsDone: live.resultsDone, costUsd: stats.cost_total });
514
+ await this.store.finishEvalRun(evalRunId, {
515
+ status,
516
+ statusReason: reason,
517
+ passed,
518
+ summary: this.summaryOf(stats),
519
+ finishedAt: this.now().toISOString(),
520
+ });
521
+ return (await this.store.getEvalRun(evalRunId));
522
+ }
523
+ async finishFailed(live, reason) {
524
+ const results = await this.store.listEvalResults(live.evalRunId);
525
+ await this.store.finishEvalRun(live.evalRunId, {
526
+ status: "failed",
527
+ statusReason: reason,
528
+ passed: false,
529
+ summary: this.summaryOf(this.statsFor(live.plan, results)),
530
+ finishedAt: this.now().toISOString(),
531
+ });
532
+ return (await this.store.getEvalRun(live.evalRunId));
533
+ }
534
+ async cleanupWorkDir(evalRunId) {
535
+ if (process.env.STAGEFLOW_EVALS_KEEP_WORKDIR === "1")
536
+ return;
537
+ try {
538
+ await rm(path.join(this.deps.workDirRoot, evalRunId), { recursive: true, force: true });
539
+ }
540
+ catch (err) {
541
+ this.deps.logger?.warn("eval.workdir_cleanup_failed", safeMessage(err));
542
+ }
543
+ }
544
+ async cancel(evalRunId) {
545
+ const live = this.live;
546
+ if (live === undefined || live.evalRunId !== evalRunId) {
547
+ if ((await this.store.getEvalRun(evalRunId)) === null) {
548
+ throw new EvalRunError("EVAL_RUN_NOT_FOUND", `Eval run not found: ${evalRunId}`);
549
+ }
550
+ return false;
551
+ }
552
+ if (live.cancelRequested)
553
+ return true;
554
+ live.cancelRequested = true;
555
+ live.abort.abort();
556
+ await this.runner.cancelAll(evalRunId);
557
+ return true;
558
+ }
559
+ async awaitFinished(evalRunId, timeoutMs) {
560
+ const live = this.live;
561
+ if (live !== undefined && live.evalRunId === evalRunId) {
562
+ let timer;
563
+ const timeout = new Promise((resolve) => {
564
+ timer = setTimeout(() => resolve("timeout"), Math.max(0, timeoutMs));
565
+ });
566
+ try {
567
+ const winner = await Promise.race([live.finished, timeout]);
568
+ if (winner !== "timeout")
569
+ return { finished: true, run: winner };
570
+ }
571
+ finally {
572
+ if (timer !== undefined)
573
+ clearTimeout(timer);
574
+ }
575
+ }
576
+ const run = await this.store.getEvalRun(evalRunId);
577
+ if (run === null)
578
+ throw new EvalRunError("EVAL_RUN_NOT_FOUND", `Eval run not found: ${evalRunId}`);
579
+ return { finished: run.status !== "queued" && run.status !== "running", run };
580
+ }
581
+ requireRealToolsConsent(plan, overrides) {
582
+ if (plan.target.kind === "internal_agent" && plan.conversation?.tools === "real") {
583
+ throw new EvalRunError("EVAL_REAL_TOOLS_NOT_CONFIRMED", "Internal agents cannot run an eval with real tools.");
584
+ }
585
+ if (plan.target.kind === "agent" && plan.conversation?.tools === "real" && overrides?.allow_real_tools !== true) {
586
+ throw new EvalRunError("EVAL_REAL_TOOLS_NOT_CONFIRMED", "This eval uses real tools, which can change files and call services from this machine. Confirm with allow_real_tools to run it.");
587
+ }
588
+ }
589
+ /**
590
+ * Validation and the real-tools consent for an agent eval, without claiming the run slot, so a transport can answer
591
+ * them before it checks the engine. Does nothing for stage evals and unreadable files.
592
+ */
593
+ async preflightAgentStart(input) {
594
+ const outcome = await loadEvalOutcome(path.resolve(input.projectRoot, input.evalPath), input.projectRoot);
595
+ if (!outcome.ok || !isConversationTarget(outcome.value.file.target.kind))
596
+ return;
597
+ const built = await buildEvalPlan({
598
+ projectRoot: input.projectRoot,
599
+ evalPath: input.evalPath,
600
+ ...(input.overrides !== undefined ? { overrides: input.overrides } : {}),
601
+ evalRunId: "er_preflight",
602
+ engine: { name: this.engineName, version: "preflight", nodeVersion: process.versions.node },
603
+ failedCaseIdsOf: (id) => this.failedCaseIds(input.projectRoot, input.evalPath, id),
604
+ ...(this.deps.isKnownModel ? { isKnownModel: this.deps.isKnownModel } : {}),
605
+ ...this.agentsInput(),
606
+ });
607
+ if (!built.ok)
608
+ throw new EvalRunError("EVAL_INVALID", "Eval is invalid", built.findings);
609
+ this.requireRealToolsConsent(built.plan, input.overrides);
610
+ }
611
+ visibleInternalAgents() {
612
+ return this.deps.internalAgents?.() ?? [];
613
+ }
614
+ agentsInput() {
615
+ const agents = this.deps.agents?.();
616
+ const internalAgents = this.deps.internalAgents?.() ?? [];
617
+ return { ...(agents ? { agents } : {}), internalAgents };
618
+ }
619
+ /** Delete the agent sessions of recovered runs and eval sessions older than 7 days that no result references. */
620
+ async sweepAgentSessions(recoveredRunIds) {
621
+ const agents = this.deps.agents?.();
622
+ if (!agents)
623
+ return 0;
624
+ try {
625
+ return await agents.sweepEvalSessions({
626
+ runIds: recoveredRunIds,
627
+ olderThanMs: EVAL_ORPHAN_SESSION_MAX_AGE_MS,
628
+ isReferenced: async (sessionId) => (await this.store.listEvalRuns({ subjectRef: sessionId, limit: 1 })).items.length > 0,
629
+ });
630
+ }
631
+ catch (err) {
632
+ this.deps.logger?.warn("eval.session_sweep_failed", safeMessage(err));
633
+ return 0;
634
+ }
635
+ }
636
+ async recoverOnBoot() {
637
+ const recovered = [];
638
+ for (const status of ["queued", "running"]) {
639
+ let cursor;
640
+ do {
641
+ const page = await this.store.listEvalRuns({
642
+ status,
643
+ limit: 200,
644
+ ...(cursor !== undefined ? { cursor } : {}),
645
+ });
646
+ for (const run of page.items) {
647
+ let summary = {};
648
+ try {
649
+ const results = await this.store.listEvalResults(run.evalRunId);
650
+ summary = this.summaryOf(this.statsFor({ graders: [], repeats: run.repeats, passThreshold: run.passThreshold, target: { kind: run.targetKind } }, results));
651
+ }
652
+ catch (err) {
653
+ this.deps.logger?.warn("eval.recover_summary_failed", safeMessage(err));
654
+ }
655
+ await this.store.finishEvalRun(run.evalRunId, {
656
+ status: "failed",
657
+ statusReason: EVAL_HOST_STOPPED_REASON,
658
+ passed: false,
659
+ summary,
660
+ finishedAt: this.now().toISOString(),
661
+ });
662
+ recovered.push(run.evalRunId);
663
+ }
664
+ cursor = page.nextCursor ?? undefined;
665
+ } while (cursor !== undefined);
666
+ }
667
+ return recovered;
668
+ }
669
+ async dropTrySession(tried) {
670
+ if (!tried)
671
+ return;
672
+ try {
673
+ await this.deps.agents?.()?.deleteEvalSessions(tried.projectRoot, [tried.subjectRef]);
674
+ }
675
+ catch (err) {
676
+ this.deps.logger?.warn("eval.try_session_cleanup_failed", safeMessage(err));
677
+ }
678
+ }
679
+ async tryOne(input) {
680
+ this.claim();
681
+ this.reserved = false;
682
+ this.trying = true;
683
+ const evalRunId = `${EVAL_RUN_ID_PREFIX}${randomBytes(6).toString("hex")}`;
684
+ this.tryingRunId = evalRunId;
685
+ const abort = new AbortController();
686
+ let hooked = false;
687
+ let tried;
688
+ try {
689
+ const engine = this.engines(this.engineName);
690
+ const engineInfo = { name: engine.name, version: await engine.version(), nodeVersion: process.versions.node };
691
+ const evalText = input.definition === undefined
692
+ ? undefined
693
+ : typeof input.definition === "string"
694
+ ? input.definition
695
+ : stringifyYaml(input.definition);
696
+ const built = await buildEvalPlan({
697
+ projectRoot: input.projectRoot,
698
+ evalPath: input.evalPath,
699
+ ...(evalText !== undefined ? { evalText } : {}),
700
+ ...(input.datasetCases !== undefined ? { datasetCases: input.datasetCases } : {}),
701
+ overrides: {
702
+ repeats: 1,
703
+ ...(input.caseId !== undefined ? { case_ids: [input.caseId] } : {}),
704
+ ...(input.allowRealTools === true ? { allow_real_tools: true } : {}),
705
+ },
706
+ evalRunId,
707
+ engine: engineInfo,
708
+ ...(this.deps.isKnownModel ? { isKnownModel: this.deps.isKnownModel } : {}),
709
+ ...this.agentsInput(),
710
+ });
711
+ if (!built.ok)
712
+ throw new EvalRunError("EVAL_INVALID", "Eval is invalid", built.findings);
713
+ this.requireRealToolsConsent(built.plan, { allow_real_tools: input.allowRealTools === true });
714
+ let plan = built.plan;
715
+ if (input.case !== undefined) {
716
+ const c = input.case;
717
+ const planCase = {
718
+ id: c.id ?? "try",
719
+ position: 0,
720
+ input: c.input,
721
+ tags: c.tags ?? [],
722
+ ...(c.expected !== undefined ? { expected: c.expected } : {}),
723
+ ...(c.title !== undefined ? { title: c.title } : {}),
724
+ ...(c.goal !== undefined ? { goal: c.goal } : {}),
725
+ ...(c.metadata !== undefined ? { metadata: c.metadata } : {}),
726
+ };
727
+ plan = { ...plan, cases: [planCase] };
728
+ }
729
+ else if (input.caseId === undefined || plan.cases.length !== 1) {
730
+ throw new EvalRunError("EVAL_INVALID", "Try one case needs a case id or an inline case");
731
+ }
732
+ plan = { ...plan, repeats: 1 };
733
+ let captured;
734
+ const io = this.makeIo(plan, (r) => {
735
+ captured ??= r;
736
+ }, () => undefined);
737
+ const { onRunStarted } = this.deps;
738
+ if (onRunStarted) {
739
+ hooked = true;
740
+ await this.runHook("onRunStarted", () => onRunStarted(evalRunId, { plan, engineName: engine.name, runCase: io.runCase, signal: abort.signal }));
741
+ }
742
+ await engine.run(plan, io, abort.signal);
743
+ if (captured === undefined) {
744
+ throw new EvalRunError("EVAL_ENGINE_ERROR", "Engine finished without a result for this case");
745
+ }
746
+ const row = this.resultInput(plan, captured);
747
+ if (plan.target.kind === "agent" && row.subjectRef)
748
+ tried = { projectRoot: input.projectRoot, subjectRef: row.subjectRef };
749
+ const grades = (row.grades ?? []).map((g) => ({
750
+ graderId: g.graderId,
751
+ graderType: g.graderType,
752
+ status: g.status,
753
+ passed: g.passed ?? null,
754
+ score: g.score ?? null,
755
+ rawValue: g.rawValue ?? null,
756
+ reason: g.reason ?? null,
757
+ errorCode: g.errorCode ?? null,
758
+ details: g.details ?? null,
759
+ judgeCostUsd: g.judgeCostUsd ?? null,
760
+ }));
761
+ return {
762
+ result: {
763
+ caseId: row.caseId,
764
+ status: row.status,
765
+ errorCode: row.errorCode ?? null,
766
+ errorMessage: row.errorMessage ?? null,
767
+ stageRunId: row.stageRunId ?? null,
768
+ subjectRef: row.subjectRef ?? null,
769
+ output: row.output ?? null,
770
+ latencyMs: row.latencyMs ?? null,
771
+ costUsd: row.costUsd ?? null,
772
+ tokensIn: row.tokensIn ?? null,
773
+ tokensOut: row.tokensOut ?? null,
774
+ score: row.score ?? null,
775
+ passed: row.passed ?? false,
776
+ hasGraderErrors: row.hasGraderErrors ?? false,
777
+ budgetWarnings: row.budgetWarnings ?? [],
778
+ grades,
779
+ },
780
+ grades,
781
+ stageRunId: row.stageRunId ?? null,
782
+ costUsd: this.runner.spend(evalRunId),
783
+ };
784
+ }
785
+ finally {
786
+ await this.dropTrySession(tried);
787
+ this.trying = false;
788
+ this.tryingRunId = null;
789
+ const { onRunFinished } = this.deps;
790
+ if (hooked && onRunFinished)
791
+ await this.runHook("onRunFinished", () => onRunFinished(evalRunId));
792
+ await this.cleanupWorkDir(evalRunId);
793
+ }
794
+ }
795
+ }