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
@@ -14,6 +14,12 @@ import { assertStoreFilesystemSupported } from "../runstore/storeFilesystem.js";
14
14
  import { assertStoreQuickCheck, isSqliteCorruptError, maybeCheckpointResidualWal, rethrowAsStoreIntegrityFailed, } from "../runstore/sqlite/applyStorePragmas.js";
15
15
  import { consoleStageBrowserSupport } from "../browser/stageBrowserEnv.js";
16
16
  import { RunManager } from "../runtime/runManager.js";
17
+ import { EvalRunManager } from "../evals/manager.js";
18
+ import { createStageCaseRunner } from "../evals/runner/stageCaseRunner.js";
19
+ import { getEngine } from "../evals/engine/index.js";
20
+ import { RunTokenRegistry } from "../evals/engine/promptfoo/runTokens.js";
21
+ import { EVAL_DEFAULT_ENGINE } from "../evals/manager.js";
22
+ import { PACKAGE_VERSION } from "../package-meta.js";
17
23
  import { PI_CODING_AGENT_DIR_ENV } from "../runtime/stageRoots.js";
18
24
  import { ScheduleSource, triggerTickIntervalMsFromEnv, } from "../runtime/scheduleSource.js";
19
25
  import { GithubPollSource, githubPollIntervalMsFromEnv, } from "../runtime/githubPollSource.js";
@@ -32,6 +38,9 @@ import { applyPendingRestoreAtBoot, } from "../runstore/restore.js";
32
38
  import { assertTmpdirUsable } from "../runstore/assertTmpdir.js";
33
39
  import { logger as rootLogger } from "../logging/logger.js";
34
40
  import { getModelCatalog } from "../models/catalog.js";
41
+ import { createAgentCaseRunner } from "../evals/runner/agentCaseRunner.js";
42
+ import { createEvalCaseRunner } from "../evals/runner/caseRunner.js";
43
+ import { defaultLoadJudgePrices } from "../evals/engine/promptfoo/judgeServices.js";
35
44
  import { createAgentHostContext } from "../agents/hostContext.js";
36
45
  export const DEFAULT_GC_INTERVAL_MS = 60 * 60 * 1000;
37
46
  /** Parse `STAGEFLOW_GC_INTERVAL_MS`; default 1h; `0` disables. */
@@ -257,6 +266,47 @@ export async function bootstrapStageflowHost(options) {
257
266
  await manager.autoResumeInterruptedStages();
258
267
  await manager.resumeStalledSchedules();
259
268
  await manager.reenqueuePersistedQueuedRuns();
269
+ const evalLog = rootLogger.child({ component: "evals" });
270
+ const evalStageRunner = createStageCaseRunner({ manager, store });
271
+ const evalAgentRunner = createAgentCaseRunner({
272
+ host: () => agentHost,
273
+ loadPrices: defaultLoadJudgePrices,
274
+ });
275
+ const evalRunner = createEvalCaseRunner({ stage: evalStageRunner, agent: evalAgentRunner });
276
+ const evalTokens = new RunTokenRegistry();
277
+ let evalCallbackBase = "";
278
+ const evalRunManager = new EvalRunManager({
279
+ store,
280
+ stageRunner: evalRunner,
281
+ agents: () => agentHost?.service,
282
+ engines: (name, engineOptions) => getEngine(name, name === EVAL_DEFAULT_ENGINE
283
+ ? {
284
+ tokens: evalTokens,
285
+ callbackUrl: () => `${evalCallbackBase}/api/evals/internal/run-case`,
286
+ home: ctx.globalHome,
287
+ ...engineOptions,
288
+ }
289
+ : engineOptions),
290
+ stageflowVersion: PACKAGE_VERSION,
291
+ workDirRoot: path.join(ctx.globalHome, "eval-runs"),
292
+ logger: {
293
+ info: (event, msg) => evalLog.info(event, msg),
294
+ warn: (event, msg) => evalLog.warn(event, msg),
295
+ error: (event, msg) => evalLog.error(event, msg),
296
+ },
297
+ });
298
+ const recoveredEvalRuns = await evalRunManager.recoverOnBoot().catch((err) => {
299
+ evalLog.warn("eval.recover_failed", err instanceof Error ? err.message : String(err));
300
+ return [];
301
+ });
302
+ const evalServices = {
303
+ tokens: evalTokens,
304
+ runner: evalRunner,
305
+ isRunning: (evalRunId) => evalRunManager.isExecuting(evalRunId),
306
+ };
307
+ const setEvalCallbackBase = (baseUrl) => {
308
+ evalCallbackBase = baseUrl.replace(/\/+$/, "");
309
+ };
260
310
  await warnDurableRootDiskIfNeeded(ctx.globalHome, { env });
261
311
  const gcInterval = startPeriodicRunGc(manager, gcIntervalMsFromEnv(env));
262
312
  const stopGcInterval = () => {
@@ -355,6 +405,8 @@ export async function bootstrapStageflowHost(options) {
355
405
  },
356
406
  })
357
407
  : undefined;
408
+ if (agentHost)
409
+ void evalRunManager.sweepAgentSessions(recoveredEvalRuns);
358
410
  const mcpStateless = resolveMcpStateless({
359
411
  mcpStateless: options.mcpStateless,
360
412
  });
@@ -366,6 +418,7 @@ export async function bootstrapStageflowHost(options) {
366
418
  runChangeBus,
367
419
  providerAuthContext: options.providerAuthContext,
368
420
  projectRoot: rootDir,
421
+ evalRunManager,
369
422
  ...(agentHost
370
423
  ? {
371
424
  agentService: agentHost.service,
@@ -389,6 +442,9 @@ export async function bootstrapStageflowHost(options) {
389
442
  isGitProject,
390
443
  store,
391
444
  manager,
445
+ evalRunManager,
446
+ evalServices,
447
+ setEvalCallbackBase,
392
448
  runChangeBus,
393
449
  mcpStateless,
394
450
  providerAuthContext: options.providerAuthContext,
@@ -1,6 +1,7 @@
1
1
  import { createHash, timingSafeEqual } from "node:crypto";
2
2
  import { readSecretFromEnvOrFile } from "../config/secretFromEnvOrFile.js";
3
3
  import { isLoopbackHostname } from "./allowedHosts.js";
4
+ import { isEvalInternalPath } from "./evalInternalRoutes.js";
4
5
  import { matchLiveViewRoute } from "./liveViewPath.js";
5
6
  const CONTROL_TOKEN_PREFIX = "STAGEFLOW_CONTROL_TOKEN_";
6
7
  const DEFAULT_CALLER_ID = "default";
@@ -200,6 +201,8 @@ export function requiredScopeFor(method, pathname) {
200
201
  return null;
201
202
  if (isLiveViewRoute(pathname))
202
203
  return null;
204
+ if (isEvalInternalPath(pathname))
205
+ return null;
203
206
  if (pathname === "/api/backup" || pathname.startsWith("/api/backup/")) {
204
207
  return "drive";
205
208
  }
@@ -0,0 +1,14 @@
1
+ import type { IncomingMessage, ServerResponse } from "node:http";
2
+ import type { RunTokenRegistry } from "../evals/engine/promptfoo/runTokens.js";
3
+ import type { StageCaseRunner } from "../evals/runner/stageCaseRunner.js";
4
+ export declare const EVAL_INTERNAL_RUN_CASE_PATH = "/api/evals/internal/run-case";
5
+ export type EvalInternalServices = {
6
+ tokens: Pick<RunTokenRegistry, "verify">;
7
+ runner: Pick<StageCaseRunner, "runCase">;
8
+ isRunning(evalRunId: string): boolean;
9
+ };
10
+ export type EvalServices = EvalInternalServices | (() => EvalInternalServices | undefined);
11
+ type Json = (res: ServerResponse, status: number, body: unknown) => void;
12
+ export declare function isEvalInternalPath(pathname: string): boolean;
13
+ export declare function handleEvalInternalRoutes(req: IncomingMessage, method: string, pathname: string, services: EvalServices | undefined, res: ServerResponse, json: Json): Promise<boolean>;
14
+ export {};
@@ -0,0 +1,87 @@
1
+ export const EVAL_INTERNAL_RUN_CASE_PATH = "/api/evals/internal/run-case";
2
+ const MAX_BODY_BYTES = 8192;
3
+ export function isEvalInternalPath(pathname) {
4
+ return pathname === EVAL_INTERNAL_RUN_CASE_PATH;
5
+ }
6
+ function resolveServices(services) {
7
+ return typeof services === "function" ? services() : services;
8
+ }
9
+ async function readBody(req) {
10
+ const chunks = [];
11
+ let size = 0;
12
+ for await (const chunk of req) {
13
+ const buffer = typeof chunk === "string" ? Buffer.from(chunk) : chunk;
14
+ size += buffer.length;
15
+ if (size > MAX_BODY_BYTES)
16
+ throw new Error("body too large");
17
+ chunks.push(buffer);
18
+ }
19
+ return JSON.parse(Buffer.concat(chunks).toString("utf8"));
20
+ }
21
+ function parseRequest(body) {
22
+ if (typeof body !== "object" || body === null)
23
+ return undefined;
24
+ const { eval_run_id: evalRunId, case_id: caseId, repeat_index: repeatIndex } = body;
25
+ if (typeof evalRunId !== "string" || evalRunId.length === 0)
26
+ return undefined;
27
+ if (typeof caseId !== "string" || caseId.length === 0)
28
+ return undefined;
29
+ if (typeof repeatIndex !== "number" || !Number.isInteger(repeatIndex) || repeatIndex < 0)
30
+ return undefined;
31
+ return { evalRunId, caseId, repeatIndex };
32
+ }
33
+ function bearerToken(req) {
34
+ const header = req.headers.authorization;
35
+ const match = typeof header === "string" ? /^Bearer ([^\s]+)$/i.exec(header) : null;
36
+ return match?.[1];
37
+ }
38
+ export async function handleEvalInternalRoutes(req, method, pathname, services, res, json) {
39
+ if (!isEvalInternalPath(pathname))
40
+ return false;
41
+ const deps = resolveServices(services);
42
+ if (deps === undefined || method !== "POST") {
43
+ json(res, 404, { error: "Not found" });
44
+ return true;
45
+ }
46
+ const entry = deps.tokens.verify(bearerToken(req));
47
+ if (entry === undefined) {
48
+ json(res, 401, { code: "unauthorized" });
49
+ return true;
50
+ }
51
+ let request;
52
+ try {
53
+ request = parseRequest(await readBody(req));
54
+ }
55
+ catch {
56
+ request = undefined;
57
+ }
58
+ if (request === undefined) {
59
+ json(res, 400, { code: "invalid_request" });
60
+ return true;
61
+ }
62
+ if (request.evalRunId !== entry.evalRunId) {
63
+ json(res, 401, { code: "unauthorized" });
64
+ return true;
65
+ }
66
+ if (!deps.isRunning(request.evalRunId)) {
67
+ json(res, 409, { code: "eval_run_not_running" });
68
+ return true;
69
+ }
70
+ try {
71
+ const { binding } = entry;
72
+ const result = binding.runCase
73
+ ? await binding.runCase(request)
74
+ : binding.plan
75
+ ? await deps.runner.runCase(binding.plan, request)
76
+ : undefined;
77
+ if (result === undefined) {
78
+ json(res, 500, { code: "EVAL_ENGINE_ERROR" });
79
+ return true;
80
+ }
81
+ json(res, 200, result);
82
+ }
83
+ catch {
84
+ json(res, 500, { code: "EVAL_ENGINE_ERROR" });
85
+ }
86
+ return true;
87
+ }
@@ -0,0 +1,46 @@
1
+ import type { IncomingMessage, ServerResponse } from "node:http";
2
+ import type { SessionsSource } from "../config/datasetFromSessions.js";
3
+ import type { EvalSampleAgents } from "../config/installEvalSample.js";
4
+ import type { EngineStatus } from "../evals/engine/promptfoo/status.js";
5
+ import type { TokenPrice } from "../evals/estimate.js";
6
+ import type { EvalAgentsPort, EvalRunManager } from "../evals/manager.js";
7
+ import { EvalApiError } from "../evals/read/api.js";
8
+ import type { EvalRunRow } from "../evals/storeTypes.js";
9
+ import type { TriageDeps } from "../evals/triage/service.js";
10
+ import type { Logger } from "../logging/logger.js";
11
+ import type { RunStore } from "../runstore/port.js";
12
+ import type { RunManager } from "../runtime/runManager.js";
13
+ export type EvalRoutesDeps = {
14
+ cwd: string;
15
+ store: RunStore;
16
+ manager: RunManager;
17
+ evalRunManager: EvalRunManager | undefined;
18
+ json: (res: ServerResponse, status: number, body: unknown) => void;
19
+ readJsonBody: (req: IncomingMessage) => Promise<unknown>;
20
+ auditLog: Logger;
21
+ engineStatus: () => EngineStatus;
22
+ isKnownModel?: (id: string) => Promise<boolean>;
23
+ sampleSourceDir?: string;
24
+ now?: () => Date;
25
+ /** Lazy view of the agent service; absent or undefined means agents are unavailable on this host. */
26
+ agents?: () => RouteAgents | undefined;
27
+ /** Model prices (USD per million tokens) for the agent cost estimate; unknown models are simply absent. */
28
+ loadPrices?: (modelIds: string[], projectRoot: string) => Promise<Map<string, TokenPrice>>;
29
+ /** Failure sorting: the Host's agent backend (judge classifier) and test seams (fetch, key lookup, base URL). */
30
+ triage?: Omit<TriageDeps, "store">;
31
+ };
32
+ export type Ctx = EvalRoutesDeps & {
33
+ req: IncomingMessage;
34
+ res: ServerResponse;
35
+ url: URL;
36
+ method: string;
37
+ pathname: string;
38
+ evalRunManager: EvalRunManager;
39
+ };
40
+ export type RouteAgents = EvalAgentsPort & SessionsSource & Partial<Pick<EvalSampleAgents, "create" | "setEnabled">>;
41
+ export declare function isRecord(value: unknown): value is Record<string, unknown>;
42
+ export declare function bad(message: string, code?: string): EvalApiError;
43
+ export declare function audit(c: Ctx, action: string, outcome: "ok" | "error", target?: string, code?: string): void;
44
+ export declare function readOptionalBody(c: Ctx): Promise<Record<string, unknown>>;
45
+ export declare function optStringArray(body: Record<string, unknown>, key: string): string[] | undefined;
46
+ export declare function runByIdOr404(c: Ctx, id: string): Promise<EvalRunRow>;
@@ -0,0 +1,43 @@
1
+ import { badRequest, runByIdOr404 as runByIdOr404Shared } from "../evals/read/api.js";
2
+ import { writeAudit } from "../logging/audit.js";
3
+ import { callerIdFromRequestAuth, getRequestAuth } from "./requestAuthContext.js";
4
+ export function isRecord(value) {
5
+ return typeof value === "object" && value !== null && !Array.isArray(value);
6
+ }
7
+ export function bad(message, code = "invalid_request") {
8
+ return badRequest(message, code);
9
+ }
10
+ function surface() {
11
+ return getRequestAuth()?.surface ?? "rest";
12
+ }
13
+ export function audit(c, action, outcome, target, code) {
14
+ writeAudit(c.auditLog, {
15
+ caller_id: callerIdFromRequestAuth(),
16
+ surface: surface(),
17
+ action,
18
+ outcome,
19
+ ...(target !== undefined ? { target_run_id: target } : {}),
20
+ ...(code !== undefined ? { error_code: code } : {}),
21
+ });
22
+ }
23
+ export async function readOptionalBody(c) {
24
+ try {
25
+ const body = await c.readJsonBody(c.req);
26
+ return isRecord(body) ? body : {};
27
+ }
28
+ catch {
29
+ return {};
30
+ }
31
+ }
32
+ export function optStringArray(body, key) {
33
+ const value = body[key];
34
+ if (value === undefined)
35
+ return undefined;
36
+ if (!Array.isArray(value) || value.some((v) => typeof v !== "string" || v === "")) {
37
+ throw bad(`"${key}" must be an array of non-empty strings`);
38
+ }
39
+ return value;
40
+ }
41
+ export async function runByIdOr404(c, id) {
42
+ return runByIdOr404Shared(c.store, id);
43
+ }
@@ -0,0 +1,5 @@
1
+ import type { IncomingMessage, ServerResponse } from "node:http";
2
+ import { type EvalRoutesDeps } from "./evalRouteContext.js";
3
+ export type { EvalRoutesDeps };
4
+ export declare function isEvalRoutePath(pathname: string): boolean;
5
+ export declare function handleEvalRoutes(req: IncomingMessage, res: ServerResponse, deps: EvalRoutesDeps): Promise<boolean>;