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,182 @@
1
+ import { existsSync } from "node:fs";
2
+ import { access, readFile } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { isMap, parse as parseYaml, parseDocument } from "yaml";
6
+ import { isAgentError } from "../agents/errors.js";
7
+ import { EvalsWriteError, writeFileAtomic } from "./atomicWrite.js";
8
+ import { ensureCatalogScanRoot } from "./ensureCatalogScanRoot.js";
9
+ import { explicitRoots, findEvalFile, manifestForWrite, resolveWriteDir, } from "./evalWriteRoots.js";
10
+ import { peekDefaultModel } from "../models/catalog.js";
11
+ import { loadStageflowManifestOutcome } from "./loadStageflowManifest.js";
12
+ import { resolveSeededExamplesPath } from "./seededCatalog.js";
13
+ export const EVAL_SAMPLE_FILES = {
14
+ pipeline: "eval-sample.pipeline.yaml",
15
+ eval: "critique-sample.eval.yaml",
16
+ dataset: "critique-sample.dataset.jsonl",
17
+ };
18
+ export const EVAL_SAMPLE_ID = "critique-sample";
19
+ export const AGENT_EVAL_SAMPLE_FILES = {
20
+ agent: "support-sample.agent.yaml",
21
+ eval: "support-sample.eval.yaml",
22
+ dataset: "support-sample.dataset.jsonl",
23
+ };
24
+ export const AGENT_EVAL_SAMPLE_ID = "support-sample";
25
+ export const AGENT_EVAL_SAMPLE_AGENT_ID = "support_sample";
26
+ async function exists(abs) {
27
+ try {
28
+ await access(abs);
29
+ return true;
30
+ }
31
+ catch {
32
+ return false;
33
+ }
34
+ }
35
+ function relativeRef(fromDir, toFile) {
36
+ const rel = path.relative(fromDir, toFile).split(path.sep).join("/");
37
+ return rel.startsWith(".") ? rel : `./${rel}`;
38
+ }
39
+ function rewriteEvalPaths(text, pipelineRef, datasetRef) {
40
+ const doc = parseDocument(text);
41
+ if (!isMap(doc.contents))
42
+ throw new EvalsWriteError("SAMPLE_SOURCE_MISSING", "Sample eval file is not a mapping");
43
+ if (pipelineRef !== undefined)
44
+ doc.setIn(["target", "pipeline"], pipelineRef);
45
+ doc.set("dataset", datasetRef);
46
+ const out = doc.toString({ lineWidth: 0 });
47
+ return out.endsWith("\n") ? out : `${out}\n`;
48
+ }
49
+ export function resolveEvalSampleDir(fromUrl = import.meta.url, marker = EVAL_SAMPLE_FILES.eval) {
50
+ const examples = resolveSeededExamplesPath(fromUrl);
51
+ const here = path.dirname(fileURLToPath(fromUrl));
52
+ const candidates = [
53
+ ...(examples === undefined ? [] : [path.join(examples, "evals")]),
54
+ path.resolve(here, "../../examples/evals"),
55
+ path.resolve(here, "../../../examples/evals"),
56
+ path.resolve(process.cwd(), "examples/evals"),
57
+ ];
58
+ return candidates.find((dir) => existsSync(path.join(dir, marker)));
59
+ }
60
+ export async function installEvalSample(input) {
61
+ if (input.kind === "agent")
62
+ return installAgentEvalSample(input);
63
+ const { projectRoot } = input;
64
+ const sourceDir = input.sourceDir ?? resolveEvalSampleDir();
65
+ if (sourceDir === undefined) {
66
+ throw new EvalsWriteError("SAMPLE_SOURCE_MISSING", "The packaged sample files were not found");
67
+ }
68
+ const sources = {
69
+ pipeline: path.join(sourceDir, EVAL_SAMPLE_FILES.pipeline),
70
+ eval: path.join(sourceDir, EVAL_SAMPLE_FILES.eval),
71
+ dataset: path.join(sourceDir, EVAL_SAMPLE_FILES.dataset),
72
+ };
73
+ const texts = { pipeline: "", eval: "", dataset: "" };
74
+ for (const key of Object.keys(sources)) {
75
+ try {
76
+ texts[key] = await readFile(sources[key], "utf8");
77
+ }
78
+ catch {
79
+ throw new EvalsWriteError("SAMPLE_SOURCE_MISSING", `Sample file ${EVAL_SAMPLE_FILES[key]} not found in ${sourceDir}`);
80
+ }
81
+ }
82
+ const manifest = await manifestForWrite(projectRoot);
83
+ const dirs = {
84
+ pipeline: await resolveWriteDir(projectRoot, manifest, "pipelines"),
85
+ eval: await resolveWriteDir(projectRoot, manifest, "evals"),
86
+ dataset: await resolveWriteDir(projectRoot, manifest, "datasets"),
87
+ };
88
+ const targets = {
89
+ pipeline: path.join(dirs.pipeline.absDir, EVAL_SAMPLE_FILES.pipeline),
90
+ eval: path.join(dirs.eval.absDir, EVAL_SAMPLE_FILES.eval),
91
+ dataset: path.join(dirs.dataset.absDir, EVAL_SAMPLE_FILES.dataset),
92
+ };
93
+ const taken = (await findEvalFile(projectRoot, EVAL_SAMPLE_ID, manifest)) !== undefined ||
94
+ (await exists(targets.pipeline)) ||
95
+ (await exists(targets.eval)) ||
96
+ (await exists(targets.dataset));
97
+ if (taken)
98
+ throw new EvalsWriteError("SAMPLE_EXISTS", "The sample eval is already installed");
99
+ const evalText = rewriteEvalPaths(texts.eval, relativeRef(dirs.eval.absDir, targets.pipeline), relativeRef(dirs.eval.absDir, targets.dataset));
100
+ const projectManifest = await loadStageflowManifestOutcome(projectRoot);
101
+ const hasDefaultModel = projectManifest.ok && projectManifest.value.manifest.model !== undefined;
102
+ const pipelineText = hasDefaultModel
103
+ ? texts.pipeline
104
+ : texts.pipeline.replace(/^id: .*\n/m, (line) => `${line}model: ${peekDefaultModel()}\n`);
105
+ await writeFileAtomic(targets.pipeline, pipelineText);
106
+ await writeFileAtomic(targets.dataset, texts.dataset);
107
+ await writeFileAtomic(targets.eval, evalText);
108
+ const scanKeys = {
109
+ pipeline: { kind: "pipelines", key: "pipelines" },
110
+ eval: { kind: "evals", key: "evals" },
111
+ dataset: { kind: "datasets", key: "datasets" },
112
+ };
113
+ for (const name of Object.keys(dirs)) {
114
+ const { kind, key } = scanKeys[name];
115
+ if (explicitRoots(manifest, kind) !== undefined) {
116
+ await ensureCatalogScanRoot(projectRoot, dirs[name].relDir, [key]);
117
+ }
118
+ }
119
+ return { evalId: EVAL_SAMPLE_ID };
120
+ }
121
+ async function agentExists(agents, projectRoot) {
122
+ try {
123
+ await agents.get(projectRoot, AGENT_EVAL_SAMPLE_AGENT_ID);
124
+ return true;
125
+ }
126
+ catch (err) {
127
+ if (isAgentError(err) && err.code === "agent.not_found")
128
+ return false;
129
+ throw err;
130
+ }
131
+ }
132
+ async function installAgentEvalSample(input) {
133
+ const { projectRoot, agents } = input;
134
+ const sourceDir = input.sourceDir ?? resolveEvalSampleDir(undefined, AGENT_EVAL_SAMPLE_FILES.eval);
135
+ if (sourceDir === undefined) {
136
+ throw new EvalsWriteError("SAMPLE_SOURCE_MISSING", "The packaged sample files were not found");
137
+ }
138
+ if (agents === undefined) {
139
+ throw new EvalsWriteError("SAMPLE_AGENTS_UNAVAILABLE", "Agents are not available on this Host");
140
+ }
141
+ const texts = { agent: "", eval: "", dataset: "" };
142
+ for (const key of Object.keys(AGENT_EVAL_SAMPLE_FILES)) {
143
+ try {
144
+ texts[key] = await readFile(path.join(sourceDir, AGENT_EVAL_SAMPLE_FILES[key]), "utf8");
145
+ }
146
+ catch {
147
+ throw new EvalsWriteError("SAMPLE_SOURCE_MISSING", `Sample file ${AGENT_EVAL_SAMPLE_FILES[key]} not found in ${sourceDir}`);
148
+ }
149
+ }
150
+ const projectManifest = await loadStageflowManifestOutcome(projectRoot);
151
+ if (!projectManifest.ok || projectManifest.value.manifest.model === undefined) {
152
+ throw new EvalsWriteError("SAMPLE_NO_DEFAULT_MODEL", "The agent sample needs a default model. Set model in stageflow.yaml, then install the sample again.");
153
+ }
154
+ const manifest = await manifestForWrite(projectRoot);
155
+ const dirs = {
156
+ eval: await resolveWriteDir(projectRoot, manifest, "evals"),
157
+ dataset: await resolveWriteDir(projectRoot, manifest, "datasets"),
158
+ };
159
+ const targets = {
160
+ eval: path.join(dirs.eval.absDir, AGENT_EVAL_SAMPLE_FILES.eval),
161
+ dataset: path.join(dirs.dataset.absDir, AGENT_EVAL_SAMPLE_FILES.dataset),
162
+ };
163
+ const taken = (await findEvalFile(projectRoot, AGENT_EVAL_SAMPLE_ID, manifest)) !== undefined ||
164
+ (await exists(targets.eval)) ||
165
+ (await exists(targets.dataset)) ||
166
+ (await agentExists(agents, projectRoot));
167
+ if (taken)
168
+ throw new EvalsWriteError("SAMPLE_EXISTS", "The sample eval is already installed");
169
+ const agentDefinition = parseYaml(texts.agent);
170
+ const evalText = rewriteEvalPaths(texts.eval, undefined, relativeRef(dirs.eval.absDir, targets.dataset));
171
+ await agents.create(projectRoot, { ...agentDefinition, web_chat: { enabled: false } }, { source: "api" });
172
+ await agents.setEnabled(projectRoot, AGENT_EVAL_SAMPLE_AGENT_ID, true, { source: "api" });
173
+ await writeFileAtomic(targets.dataset, texts.dataset);
174
+ await writeFileAtomic(targets.eval, evalText);
175
+ const scanKeys = { eval: "evals", dataset: "datasets" };
176
+ for (const name of Object.keys(dirs)) {
177
+ if (explicitRoots(manifest, scanKeys[name]) !== undefined) {
178
+ await ensureCatalogScanRoot(projectRoot, dirs[name].relDir, [scanKeys[name]]);
179
+ }
180
+ }
181
+ return { evalId: AGENT_EVAL_SAMPLE_ID };
182
+ }
@@ -0,0 +1,16 @@
1
+ import type { DatasetFormat, DatasetLimits, DatasetLoadResult, ParseDatasetResult } from "./datasetTypes.js";
2
+ export declare const DATASET_LIMITS: DatasetLimits;
3
+ export declare const DATASET_MIN_CASES = 5;
4
+ export type ParseDatasetOptions = {
5
+ limits?: Partial<DatasetLimits>;
6
+ path?: string;
7
+ };
8
+ export declare function datasetFormatFromPath(filePath: string): DatasetFormat | undefined;
9
+ export declare function parseDatasetText(text: string, format: DatasetFormat, options?: ParseDatasetOptions & {
10
+ csvDelimiter?: string;
11
+ }): ParseDatasetResult;
12
+ export declare function parseDatasetCases(rawCases: readonly unknown[], options?: ParseDatasetOptions): ParseDatasetResult;
13
+ export declare function loadDatasetFile(absPath: string, options?: ParseDatasetOptions & {
14
+ root?: string;
15
+ csvDelimiter?: string;
16
+ }): Promise<DatasetLoadResult>;
@@ -0,0 +1,318 @@
1
+ import { readFile, stat } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { CsvParseError, parseCsv } from "./csv.js";
4
+ import { datasetContentHash } from "./datasetHash.js";
5
+ export const DATASET_LIMITS = {
6
+ maxCases: 5000,
7
+ maxCaseBytes: 1024 * 1024,
8
+ maxFileBytes: 50 * 1024 * 1024,
9
+ };
10
+ export const DATASET_MIN_CASES = 5;
11
+ const ID_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
12
+ const TAG_RE = /^[a-z0-9][a-z0-9-]{0,31}$/;
13
+ const MAX_TAGS = 10;
14
+ const MAX_TITLE = 120;
15
+ const CASE_KEYS = new Set(["id", "input", "title", "expected", "tags", "goal", "metadata"]);
16
+ function isPlainObject(value) {
17
+ return value !== null && typeof value === "object" && !Array.isArray(value);
18
+ }
19
+ export function datasetFormatFromPath(filePath) {
20
+ const ext = path.extname(filePath).toLowerCase();
21
+ if (ext === ".jsonl")
22
+ return "jsonl";
23
+ if (ext === ".json")
24
+ return "json";
25
+ if (ext === ".csv")
26
+ return "csv";
27
+ return undefined;
28
+ }
29
+ function finding(severity, code, filePath, message, pos) {
30
+ const out = {
31
+ severity,
32
+ code,
33
+ path: filePath,
34
+ message: pos ? `${pos.label}: ${message}` : message,
35
+ category: "dataset",
36
+ };
37
+ if (pos && pos.line > 0)
38
+ out.line = pos.line;
39
+ return out;
40
+ }
41
+ function parseJsonl(text, filePath, findings) {
42
+ const entries = [];
43
+ const lines = text.charCodeAt(0) === 0xfeff ? text.slice(1).split(/\r?\n/) : text.split(/\r?\n/);
44
+ lines.forEach((raw, idx) => {
45
+ if (raw.trim() === "")
46
+ return;
47
+ const pos = { line: idx + 1, label: `line ${idx + 1}` };
48
+ try {
49
+ entries.push({ value: JSON.parse(raw), pos });
50
+ }
51
+ catch (err) {
52
+ const detail = err instanceof Error ? err.message : String(err);
53
+ findings.push(finding("error", "dataset.load_error", filePath, `invalid JSON (${detail})`, pos));
54
+ }
55
+ });
56
+ return entries;
57
+ }
58
+ function parseJson(text, filePath, findings) {
59
+ let doc;
60
+ try {
61
+ doc = JSON.parse(text.charCodeAt(0) === 0xfeff ? text.slice(1) : text);
62
+ }
63
+ catch (err) {
64
+ const detail = err instanceof Error ? err.message : String(err);
65
+ findings.push(finding("error", "dataset.load_error", filePath, `invalid JSON (${detail})`));
66
+ return [];
67
+ }
68
+ let list;
69
+ if (Array.isArray(doc))
70
+ list = doc;
71
+ else if (isPlainObject(doc) && Array.isArray(doc.cases))
72
+ list = doc.cases;
73
+ if (!Array.isArray(list)) {
74
+ findings.push(finding("error", "dataset.invalid_shape", filePath, 'JSON dataset must be an array of cases or an object { "cases": [...] }'));
75
+ return [];
76
+ }
77
+ return list.map((value, idx) => ({
78
+ value,
79
+ pos: { line: 0, label: `case ${idx + 1}` },
80
+ }));
81
+ }
82
+ const STRING_COLUMNS = new Set(["id", "title", "goal"]);
83
+ const JSON_BASES = new Set(["id", "title", "goal", "tags", "input", "expected", "metadata"]);
84
+ function classifyHeader(header) {
85
+ const json = header.endsWith(":json");
86
+ const name = json ? header.slice(0, -":json".length) : header;
87
+ if (json && JSON_BASES.has(name))
88
+ return { base: name, json };
89
+ if (!json && (STRING_COLUMNS.has(name) || name === "tags" || name === "expected")) {
90
+ return { base: name, json };
91
+ }
92
+ for (const prefix of ["input.", "expected."]) {
93
+ if (name.startsWith(prefix) && name.length > prefix.length) {
94
+ return { base: prefix.slice(0, -1), key: name.slice(prefix.length), json };
95
+ }
96
+ }
97
+ return undefined;
98
+ }
99
+ function parseCsvEntries(text, filePath, findings, delimiter) {
100
+ let records;
101
+ try {
102
+ records = parseCsv(text, { delimiter });
103
+ }
104
+ catch (err) {
105
+ if (err instanceof CsvParseError) {
106
+ findings.push(finding("error", "dataset.load_error", filePath, err.message, {
107
+ line: err.record,
108
+ label: `row ${err.record}`,
109
+ }));
110
+ return [];
111
+ }
112
+ throw err;
113
+ }
114
+ const headerIdx = records.findIndex((r) => !(r.length === 1 && r[0] === ""));
115
+ if (headerIdx === -1)
116
+ return [];
117
+ const headers = records[headerIdx].map((h) => h.trim());
118
+ const targets = headers.map((h, col) => {
119
+ const target = classifyHeader(h);
120
+ if (!target) {
121
+ findings.push(finding("error", "dataset.csv_unknown_column", filePath, `unknown CSV column "${h}" (column ${col + 1}); use id, title, goal, tags, input.<name>, expected.<name> or a :json suffix`, { line: headerIdx + 1, label: `row ${headerIdx + 1}` }));
122
+ }
123
+ return target;
124
+ });
125
+ const entries = [];
126
+ for (let r = headerIdx + 1; r < records.length; r += 1) {
127
+ const cells = records[r];
128
+ if (cells.length === 1 && cells[0] === "")
129
+ continue;
130
+ const pos = { line: r + 1, label: `row ${r + 1}` };
131
+ const obj = {};
132
+ let broken = false;
133
+ targets.forEach((target, col) => {
134
+ const cell = cells[col];
135
+ if (!target || cell === undefined || cell === "")
136
+ return;
137
+ let value = cell;
138
+ if (target.json) {
139
+ try {
140
+ value = JSON.parse(cell);
141
+ }
142
+ catch {
143
+ findings.push(finding("error", "dataset.load_error", filePath, `column "${headers[col]}" holds invalid JSON`, pos));
144
+ broken = true;
145
+ return;
146
+ }
147
+ }
148
+ else if (target.base === "tags") {
149
+ value = cell
150
+ .split(";")
151
+ .map((t) => t.trim())
152
+ .filter((t) => t !== "");
153
+ }
154
+ if (target.key !== undefined) {
155
+ const parent = (obj[target.base] ??= {});
156
+ parent[target.key] = value;
157
+ }
158
+ else {
159
+ obj[target.base] = value;
160
+ }
161
+ });
162
+ if (!broken)
163
+ entries.push({ value: obj, pos });
164
+ }
165
+ return entries;
166
+ }
167
+ function validateEntries(entries, filePath, limits, findings) {
168
+ const cases = [];
169
+ const seen = new Set();
170
+ let list = entries;
171
+ if (entries.length > limits.maxCases) {
172
+ findings.push(finding("error", "dataset.too_many_cases", filePath, `dataset has ${entries.length} cases; the limit is ${limits.maxCases}`));
173
+ list = entries.slice(0, limits.maxCases);
174
+ }
175
+ for (const { value, pos } of list) {
176
+ const report = (code, message) => {
177
+ findings.push(finding("error", code, filePath, message, pos));
178
+ };
179
+ if (!isPlainObject(value)) {
180
+ report("dataset.not_object", "case must be a JSON object");
181
+ continue;
182
+ }
183
+ let ok = true;
184
+ const fail = (code, message) => {
185
+ report(code, message);
186
+ ok = false;
187
+ };
188
+ for (const key of Object.keys(value)) {
189
+ if (!CASE_KEYS.has(key))
190
+ fail("dataset.unknown_key", `unknown case key "${key}"`);
191
+ }
192
+ const id = value.id;
193
+ if (id === undefined) {
194
+ fail("dataset.case_missing_id", "case has no id (hand-authored datasets must carry ids)");
195
+ }
196
+ else if (typeof id !== "string" || !ID_RE.test(id)) {
197
+ fail("dataset.case_invalid_id", `id ${JSON.stringify(id)} must match ${ID_RE.source}`);
198
+ }
199
+ else if (seen.has(id)) {
200
+ fail("dataset.duplicate_id", `duplicate id "${id}"`);
201
+ }
202
+ else {
203
+ seen.add(id);
204
+ }
205
+ if (value.input === undefined) {
206
+ fail("dataset.case_missing_input", "case has no input");
207
+ }
208
+ else if (!isPlainObject(value.input)) {
209
+ fail("dataset.invalid_field", "input must be an object");
210
+ }
211
+ if (value.title !== undefined && (typeof value.title !== "string" || value.title.length > MAX_TITLE)) {
212
+ fail("dataset.invalid_field", `title must be a string of at most ${MAX_TITLE} characters`);
213
+ }
214
+ if (value.goal !== undefined && typeof value.goal !== "string") {
215
+ fail("dataset.invalid_field", "goal must be a string");
216
+ }
217
+ if (value.metadata !== undefined && !isPlainObject(value.metadata)) {
218
+ fail("dataset.invalid_field", "metadata must be an object");
219
+ }
220
+ if (value.tags !== undefined) {
221
+ const tags = value.tags;
222
+ if (!Array.isArray(tags) || tags.length > MAX_TAGS) {
223
+ fail("dataset.invalid_field", `tags must be an array of at most ${MAX_TAGS} strings`);
224
+ }
225
+ else {
226
+ for (const tag of tags) {
227
+ if (typeof tag !== "string" || !TAG_RE.test(tag)) {
228
+ fail("dataset.invalid_field", `tag ${JSON.stringify(tag)} must match ${TAG_RE.source}`);
229
+ }
230
+ }
231
+ }
232
+ }
233
+ if (ok && Buffer.byteLength(JSON.stringify(value), "utf8") > limits.maxCaseBytes) {
234
+ fail("dataset.case_too_large", `case "${String(id)}" is larger than ${limits.maxCaseBytes} bytes`);
235
+ }
236
+ if (ok)
237
+ cases.push(value);
238
+ }
239
+ return cases;
240
+ }
241
+ export function parseDatasetText(text, format, options = {}) {
242
+ const limits = { ...DATASET_LIMITS, ...options.limits };
243
+ const filePath = options.path ?? "";
244
+ const findings = [];
245
+ if (Buffer.byteLength(text, "utf8") > limits.maxFileBytes) {
246
+ findings.push(finding("error", "dataset.file_too_large", filePath, `dataset file is larger than ${limits.maxFileBytes} bytes`));
247
+ return { cases: [], findings, contentHash: datasetContentHash([]) };
248
+ }
249
+ let entries;
250
+ if (format === "jsonl")
251
+ entries = parseJsonl(text, filePath, findings);
252
+ else if (format === "json")
253
+ entries = parseJson(text, filePath, findings);
254
+ else
255
+ entries = parseCsvEntries(text, filePath, findings, options.csvDelimiter);
256
+ return finishParse(entries, filePath, limits, findings);
257
+ }
258
+ function finishParse(entries, filePath, limits, findings) {
259
+ const cases = validateEntries(entries, filePath, limits, findings);
260
+ if (entries.length === 0 && !findings.some((f) => f.severity === "error")) {
261
+ findings.push(finding("error", "dataset.empty", filePath, "dataset has no cases"));
262
+ }
263
+ else if (entries.length > 0 &&
264
+ cases.length < DATASET_MIN_CASES &&
265
+ !findings.some((f) => f.severity === "error")) {
266
+ findings.push(finding("warning", "dataset.few_cases", filePath, `dataset has ${cases.length} cases; fewer than ${DATASET_MIN_CASES} gives wide error bars`));
267
+ }
268
+ return { cases, findings, contentHash: datasetContentHash(cases) };
269
+ }
270
+ export function parseDatasetCases(rawCases, options = {}) {
271
+ const limits = { ...DATASET_LIMITS, ...options.limits };
272
+ const entries = rawCases.map((value, idx) => ({
273
+ value,
274
+ pos: { line: 0, label: `case ${idx + 1}` },
275
+ }));
276
+ return finishParse(entries, options.path ?? "", limits, []);
277
+ }
278
+ export async function loadDatasetFile(absPath, options = {}) {
279
+ const limits = { ...DATASET_LIMITS, ...options.limits };
280
+ const relPath = (options.root ? path.relative(options.root, absPath) : path.basename(absPath))
281
+ .split(path.sep)
282
+ .join("/");
283
+ const base = {
284
+ path: absPath,
285
+ relPath,
286
+ format: datasetFormatFromPath(absPath),
287
+ cases: [],
288
+ contentHash: datasetContentHash([]),
289
+ fileBytes: 0,
290
+ };
291
+ const fail = (code, message, fileBytes = 0) => ({
292
+ ...base,
293
+ fileBytes,
294
+ findings: [finding("error", code, relPath, message)],
295
+ });
296
+ if (base.format === undefined) {
297
+ return fail("dataset.load_error", `unknown dataset format "${path.extname(absPath)}"; use .jsonl, .json or .csv`);
298
+ }
299
+ let size;
300
+ try {
301
+ size = (await stat(absPath)).size;
302
+ }
303
+ catch (err) {
304
+ return fail("dataset.load_error", `cannot read dataset: ${err.message}`);
305
+ }
306
+ if (size > limits.maxFileBytes) {
307
+ return fail("dataset.file_too_large", `dataset file is larger than ${limits.maxFileBytes} bytes`, size);
308
+ }
309
+ let text;
310
+ try {
311
+ text = await readFile(absPath, "utf8");
312
+ }
313
+ catch (err) {
314
+ return fail("dataset.load_error", `cannot read dataset: ${err.message}`, size);
315
+ }
316
+ const parsed = parseDatasetText(text, base.format, { ...options, path: relPath });
317
+ return { ...base, ...parsed, fileBytes: size };
318
+ }
@@ -0,0 +1,32 @@
1
+ import type { EvalConversation, EvalFile, ResolvedConversation, ResolvedGrader } from "../evals/types.js";
2
+ import { type LoadOutcome } from "./loadOutcome.js";
3
+ type UnhashedGrader = ResolvedGrader extends infer G ? (G extends unknown ? Omit<G, "hash"> : never) : never;
4
+ export type LoadedEval = {
5
+ path: string;
6
+ relPath: string;
7
+ id: string;
8
+ fileHash: string;
9
+ file: EvalFile;
10
+ graders: ResolvedGrader[];
11
+ };
12
+ export declare const EVAL_DEFAULT_REPEATS = 3;
13
+ export declare const EVAL_DEFAULT_PASS_THRESHOLD = 0.8;
14
+ export declare const EVAL_DEFAULT_MAX_COST_USD = 2;
15
+ export declare const EVAL_DEFAULT_CONCURRENCY = 4;
16
+ export declare const EVAL_AGENT_DEFAULT_CONCURRENCY = 2;
17
+ export declare const EVAL_AGENT_DEFAULT_MAX_COST_USD = 1;
18
+ export declare const EVAL_CONVERSATION_DEFAULTS: ResolvedConversation;
19
+ export declare function resolveConversation(conversation: EvalConversation | undefined): ResolvedConversation;
20
+ export declare function evalFileStem(filePath: string): string;
21
+ export type EvalPaths = {
22
+ pipelinePath?: string;
23
+ stageFile?: string;
24
+ datasetPath: string;
25
+ };
26
+ /** Paths in an eval file resolve against the eval file's directory (P6). */
27
+ export declare function resolveEvalPaths(file: EvalFile, evalAbsPath: string): EvalPaths;
28
+ export declare function graderHash(grader: UnhashedGrader): string;
29
+ export declare function graderHashShort(grader: Pick<ResolvedGrader, "hash">): string;
30
+ export declare function parseEvalOutcome(yamlText: string, filePath: string, projectRoot: string): LoadOutcome<LoadedEval>;
31
+ export declare function loadEvalOutcome(absPath: string, projectRoot: string): Promise<LoadOutcome<LoadedEval>>;
32
+ export {};