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,51 @@
1
+ export declare const RESULT_STATUSES: readonly ["completed", "stage_failed", "needs_input", "error", "skipped_budget", "cancelled"];
2
+ export type ResultStatus = (typeof RESULT_STATUSES)[number];
3
+ export declare const EXECUTED_RESULT_STATUSES: readonly ResultStatus[];
4
+ export type GradeStatus = "graded" | "error";
5
+ export type EvalType = "capability" | "regression";
6
+ export declare const EVAL_COMPARE_MISMATCH = "EVAL_COMPARE_MISMATCH";
7
+ export interface ResultRecord {
8
+ caseId: string;
9
+ repeatIndex: number;
10
+ status: ResultStatus;
11
+ latencyMs: number | null;
12
+ costUsd: number | null;
13
+ tokensIn: number | null;
14
+ tokensOut: number | null;
15
+ score: number | null;
16
+ passed: 0 | 1;
17
+ turns?: number | null;
18
+ toolCalls?: number | null;
19
+ }
20
+ export interface GradeRecord {
21
+ caseId: string;
22
+ repeatIndex: number;
23
+ graderId: string;
24
+ graderType: string;
25
+ status: GradeStatus;
26
+ passed: 0 | 1 | null;
27
+ score: number | null;
28
+ rawValue: number | null;
29
+ judgeCostUsd: number | null;
30
+ judgeTokensIn: number | null;
31
+ judgeTokensOut: number | null;
32
+ }
33
+ export interface GraderRef {
34
+ id: string;
35
+ type: string;
36
+ hash: string;
37
+ }
38
+ export interface PreviousRunGraderStat {
39
+ graderId: string;
40
+ hash: string;
41
+ passRate: number | null;
42
+ }
43
+ export interface PreviousRunLite {
44
+ graders: PreviousRunGraderStat[];
45
+ }
46
+ export interface RunBudget {
47
+ latencyMs?: number | null;
48
+ costUsd?: number | null;
49
+ }
50
+ export type BudgetWarning = "latency" | "cost";
51
+ export declare function resultKey(caseId: string, repeatIndex: number): string;
@@ -0,0 +1,18 @@
1
+ export const RESULT_STATUSES = [
2
+ "completed",
3
+ "stage_failed",
4
+ "needs_input",
5
+ "error",
6
+ "skipped_budget",
7
+ "cancelled",
8
+ ];
9
+ export const EXECUTED_RESULT_STATUSES = [
10
+ "completed",
11
+ "stage_failed",
12
+ "needs_input",
13
+ "error",
14
+ ];
15
+ export const EVAL_COMPARE_MISMATCH = "EVAL_COMPARE_MISMATCH";
16
+ export function resultKey(caseId, repeatIndex) {
17
+ return `${caseId}:${repeatIndex}`;
18
+ }
@@ -0,0 +1,5 @@
1
+ import type { EvalErrorCode } from "./constants.js";
2
+ export declare class EvalStoreError extends Error {
3
+ readonly code: EvalErrorCode;
4
+ constructor(code: EvalErrorCode, message: string);
5
+ }
@@ -0,0 +1,8 @@
1
+ export class EvalStoreError extends Error {
2
+ code;
3
+ constructor(code, message) {
4
+ super(message);
5
+ this.code = code;
6
+ this.name = "EvalStoreError";
7
+ }
8
+ }
@@ -0,0 +1,207 @@
1
+ import type { EvalBudgetWarning, EvalGradeStatus, EvalResultStatus, EvalReviewLabel, EvalRunStatus, EvalStartedVia, EvalTargetKind } from "./constants.js";
2
+ export type EvalTargetRef = {
3
+ pipeline_path?: string;
4
+ stage_id?: string;
5
+ file?: string;
6
+ agent_id?: string;
7
+ revision?: number | string;
8
+ };
9
+ export type EvalJson = Record<string, unknown>;
10
+ export type EvalRunRow = {
11
+ evalRunId: string;
12
+ projectRoot: string;
13
+ evalId: string;
14
+ runNumber: number;
15
+ evalPath: string;
16
+ evalHash: string;
17
+ targetKind: EvalTargetKind;
18
+ targetRef: EvalTargetRef;
19
+ targetVersionHash: string;
20
+ datasetPath: string;
21
+ datasetHash: string;
22
+ config: EvalJson;
23
+ configFingerprint: string;
24
+ configComponents: EvalJson;
25
+ status: EvalRunStatus;
26
+ statusReason: string | null;
27
+ passed: boolean | null;
28
+ repeats: number;
29
+ passThreshold: number;
30
+ maxCostUsd: number;
31
+ casesTotal: number;
32
+ resultsTotal: number;
33
+ resultsDone: number;
34
+ costUsd: number;
35
+ engineName: string;
36
+ engineVersion: string;
37
+ stageflowVersion: string;
38
+ label: string | null;
39
+ startedVia: EvalStartedVia;
40
+ callerId: string | null;
41
+ summary: EvalJson | null;
42
+ createdAt: string;
43
+ startedAt: string | null;
44
+ finishedAt: string | null;
45
+ };
46
+ export type CreateEvalRunInput = {
47
+ projectRoot: string;
48
+ evalId: string;
49
+ evalPath: string;
50
+ evalHash: string;
51
+ targetKind: EvalTargetKind;
52
+ targetRef: EvalTargetRef;
53
+ targetVersionHash: string;
54
+ datasetPath: string;
55
+ datasetHash: string;
56
+ config: EvalJson;
57
+ configFingerprint: string;
58
+ configComponents: EvalJson;
59
+ status?: EvalRunStatus;
60
+ repeats: number;
61
+ passThreshold: number;
62
+ maxCostUsd: number;
63
+ casesTotal: number;
64
+ resultsTotal: number;
65
+ engineName: string;
66
+ engineVersion: string;
67
+ stageflowVersion: string;
68
+ label?: string;
69
+ startedVia: EvalStartedVia;
70
+ callerId?: string;
71
+ };
72
+ export type EvalRunProgress = {
73
+ resultsDone?: number;
74
+ costUsd?: number;
75
+ status?: EvalRunStatus;
76
+ statusReason?: string | null;
77
+ startedAt?: string;
78
+ };
79
+ export type FinishEvalRunInput = {
80
+ status: Extract<EvalRunStatus, "completed" | "failed" | "cancelled" | "budget_stopped">;
81
+ statusReason?: string | null;
82
+ passed: boolean;
83
+ summary: EvalJson;
84
+ finishedAt: string;
85
+ };
86
+ export type ListEvalRunsQuery = {
87
+ projectRoot?: string;
88
+ evalId?: string;
89
+ status?: EvalRunStatus;
90
+ stageRunId?: string;
91
+ subjectRef?: string;
92
+ limit: number;
93
+ cursor?: string;
94
+ };
95
+ export type EvalRunPage = {
96
+ items: EvalRunRow[];
97
+ nextCursor: string | null;
98
+ };
99
+ export type EvalCaseRow = {
100
+ evalRunId: string;
101
+ caseId: string;
102
+ position: number;
103
+ case: EvalJson;
104
+ };
105
+ export type EvalCaseInput = Omit<EvalCaseRow, "evalRunId">;
106
+ export type EvalGradeRow = {
107
+ evalRunId: string;
108
+ caseId: string;
109
+ repeatIndex: number;
110
+ graderId: string;
111
+ graderType: string;
112
+ status: EvalGradeStatus;
113
+ passed: boolean | null;
114
+ score: number | null;
115
+ rawValue: number | null;
116
+ reason: string | null;
117
+ details: EvalJson | null;
118
+ errorCode: string | null;
119
+ judgeModel: string | null;
120
+ judgeCostUsd: number | null;
121
+ judgeTokensIn: number | null;
122
+ judgeTokensOut: number | null;
123
+ };
124
+ export type EvalGradeInput = {
125
+ graderId: string;
126
+ graderType: string;
127
+ status: EvalGradeStatus;
128
+ passed?: boolean | null;
129
+ score?: number | null;
130
+ rawValue?: number | null;
131
+ reason?: string | null;
132
+ details?: EvalJson | null;
133
+ errorCode?: string | null;
134
+ judgeModel?: string | null;
135
+ judgeCostUsd?: number | null;
136
+ judgeTokensIn?: number | null;
137
+ judgeTokensOut?: number | null;
138
+ };
139
+ export type EvalResultRow = {
140
+ evalRunId: string;
141
+ caseId: string;
142
+ repeatIndex: number;
143
+ status: EvalResultStatus;
144
+ errorCode: string | null;
145
+ errorMessage: string | null;
146
+ stageRunId: string | null;
147
+ subjectRef: string | null;
148
+ turns: number | null;
149
+ toolCallCount: number | null;
150
+ output: EvalJson | null;
151
+ latencyMs: number | null;
152
+ costUsd: number | null;
153
+ tokensIn: number | null;
154
+ tokensOut: number | null;
155
+ score: number | null;
156
+ passed: boolean;
157
+ hasGraderErrors: boolean;
158
+ budgetWarnings: EvalBudgetWarning[] | null;
159
+ startedAt: string | null;
160
+ finishedAt: string | null;
161
+ };
162
+ export type EvalResultWithGrades = EvalResultRow & {
163
+ grades: EvalGradeRow[];
164
+ };
165
+ export type EvalResultInput = {
166
+ evalRunId: string;
167
+ caseId: string;
168
+ repeatIndex: number;
169
+ status: EvalResultStatus;
170
+ errorCode?: string | null;
171
+ errorMessage?: string | null;
172
+ stageRunId?: string | null;
173
+ subjectRef?: string | null;
174
+ turns?: number | null;
175
+ toolCallCount?: number | null;
176
+ output?: EvalJson | null;
177
+ latencyMs?: number | null;
178
+ costUsd?: number | null;
179
+ tokensIn?: number | null;
180
+ tokensOut?: number | null;
181
+ score?: number | null;
182
+ passed?: boolean;
183
+ hasGraderErrors?: boolean;
184
+ budgetWarnings?: EvalBudgetWarning[] | null;
185
+ startedAt?: string | null;
186
+ finishedAt?: string | null;
187
+ grades?: EvalGradeInput[];
188
+ };
189
+ export type EvalReviewPatch = {
190
+ label?: EvalReviewLabel;
191
+ note?: string | null;
192
+ tags?: string[];
193
+ };
194
+ export type EvalReviewRow = {
195
+ evalRunId: string;
196
+ caseId: string;
197
+ repeatIndex: number;
198
+ label: EvalReviewLabel | null;
199
+ note: string | null;
200
+ tags: string[];
201
+ createdAt: string | null;
202
+ updatedAt: string | null;
203
+ };
204
+ export type EvalGraderVersionInput = {
205
+ graderId: string;
206
+ graderHash: string;
207
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ export declare const T_TABLE_MAX_DF: 30;
2
+ export declare const T_LARGE_DF_QUANTILE = 1.96;
3
+ export declare function tQuantile(df: number): number;
@@ -0,0 +1,15 @@
1
+ const T_95_TWO_SIDED = [
2
+ 12.706, 4.303, 3.182, 2.776, 2.571, 2.447, 2.365, 2.306, 2.262, 2.228,
3
+ 2.201, 2.179, 2.16, 2.145, 2.131, 2.12, 2.11, 2.101, 2.093, 2.086,
4
+ 2.08, 2.074, 2.069, 2.064, 2.06, 2.056, 2.052, 2.048, 2.045, 2.042,
5
+ ];
6
+ export const T_TABLE_MAX_DF = T_95_TWO_SIDED.length;
7
+ export const T_LARGE_DF_QUANTILE = 1.96;
8
+ export function tQuantile(df) {
9
+ if (!Number.isInteger(df) || df < 1) {
10
+ throw new RangeError(`degrees of freedom must be an integer >= 1, got ${df}`);
11
+ }
12
+ if (df > T_TABLE_MAX_DF)
13
+ return T_LARGE_DF_QUANTILE;
14
+ return T_95_TWO_SIDED[df - 1];
15
+ }
@@ -0,0 +1,26 @@
1
+ export declare const TRIAGE_BUCKETS: readonly ["agent_wrong", "grader_wrong", "case_wrong", "unclear"];
2
+ export type TriageBucket = (typeof TRIAGE_BUCKETS)[number];
3
+ export declare const TRIAGE_SOURCES: readonly ["jev", "judge"];
4
+ export type TriageSource = (typeof TRIAGE_SOURCES)[number];
5
+ export declare const SUGGESTION_STATUSES: readonly ["pending", "accepted", "dismissed"];
6
+ export type SuggestionStatus = (typeof SUGGESTION_STATUSES)[number];
7
+ export declare const FAILURE_TYPES_BY_KIND: {
8
+ readonly agent: readonly ["missing_tool_call", "unneeded_tool_call", "wrong_or_missing_fact", "policy_violation", "tone", "ungrounded_claim", "off_topic", "no_handoff", "other"];
9
+ readonly stage: readonly ["wrong_value", "missing_field", "schema_invalid", "policy_violation", "ungrounded_claim", "tone", "other"];
10
+ };
11
+ /** Pinned System One model id; the alias `jev-latest` moves and is never used. Recorded on every suggestion. */
12
+ export declare const JEV_MODEL_ID = "jev-1.13.0";
13
+ export declare const JEV_BASE_URL = "https://api.typesafe.ai";
14
+ export declare const JEV_PRICE_INPUT_PER_MILLION_USD = 0.042;
15
+ /** Below this bucket confidence (or for `unclear`) a suggestion is low confidence and excluded from bulk accept. */
16
+ export declare const LOW_CONFIDENCE_THRESHOLD = 0.7;
17
+ export declare const TRIAGE_STATE_MAX_CHARS = 24000;
18
+ export declare const TRIAGE_CONCURRENCY = 4;
19
+ export declare const TRIAGE_DEFAULT_LIMIT = 200;
20
+ export declare const TRIAGE_MAX_LIMIT = 1000;
21
+ export declare const JEV_MAX_RETRIES = 4;
22
+ export declare const JEV_BACKOFF_BASE_MS = 500;
23
+ export declare const BUCKET_TAG_PREFIX = "bucket:";
24
+ export declare const TYPESAFE_PROVIDER_ID = "typesafe";
25
+ /** Env names tried after the stored `typesafe` provider credential, in order; the first one set wins. */
26
+ export declare const TYPESAFE_KEY_ENV_NAMES: readonly ["STAGEFLOW_PROVIDER_TYPESAFE_API_KEY", "TYPESAFE_API_KEY", "JEV_API_KEY"];
@@ -0,0 +1,33 @@
1
+ export const TRIAGE_BUCKETS = ["agent_wrong", "grader_wrong", "case_wrong", "unclear"];
2
+ export const TRIAGE_SOURCES = ["jev", "judge"];
3
+ export const SUGGESTION_STATUSES = ["pending", "accepted", "dismissed"];
4
+ export const FAILURE_TYPES_BY_KIND = {
5
+ agent: [
6
+ "missing_tool_call",
7
+ "unneeded_tool_call",
8
+ "wrong_or_missing_fact",
9
+ "policy_violation",
10
+ "tone",
11
+ "ungrounded_claim",
12
+ "off_topic",
13
+ "no_handoff",
14
+ "other",
15
+ ],
16
+ stage: ["wrong_value", "missing_field", "schema_invalid", "policy_violation", "ungrounded_claim", "tone", "other"],
17
+ };
18
+ /** Pinned System One model id; the alias `jev-latest` moves and is never used. Recorded on every suggestion. */
19
+ export const JEV_MODEL_ID = "jev-1.13.0";
20
+ export const JEV_BASE_URL = "https://api.typesafe.ai";
21
+ export const JEV_PRICE_INPUT_PER_MILLION_USD = 0.042;
22
+ /** Below this bucket confidence (or for `unclear`) a suggestion is low confidence and excluded from bulk accept. */
23
+ export const LOW_CONFIDENCE_THRESHOLD = 0.7;
24
+ export const TRIAGE_STATE_MAX_CHARS = 24_000;
25
+ export const TRIAGE_CONCURRENCY = 4;
26
+ export const TRIAGE_DEFAULT_LIMIT = 200;
27
+ export const TRIAGE_MAX_LIMIT = 1_000;
28
+ export const JEV_MAX_RETRIES = 4;
29
+ export const JEV_BACKOFF_BASE_MS = 500;
30
+ export const BUCKET_TAG_PREFIX = "bucket:";
31
+ export const TYPESAFE_PROVIDER_ID = "typesafe";
32
+ /** Env names tried after the stored `typesafe` provider credential, in order; the first one set wins. */
33
+ export const TYPESAFE_KEY_ENV_NAMES = ["STAGEFLOW_PROVIDER_TYPESAFE_API_KEY", "TYPESAFE_API_KEY", "JEV_API_KEY"];
@@ -0,0 +1,13 @@
1
+ export declare const STORED_KEY_SOURCE = "stored:typesafe";
2
+ export type TypesafeKeyLookup = {
3
+ /** The key. Never log it, return it from an API or put it in an error. */
4
+ key: string | undefined;
5
+ /** Names (never values) of the sources that hold a key, in lookup order. */
6
+ sources: string[];
7
+ };
8
+ export type TypesafeKeyResolver = (projectRoot: string) => Promise<TypesafeKeyLookup> | TypesafeKeyLookup;
9
+ /**
10
+ * Lookup order: the stored `typesafe` provider credential (Settings, Providers, or boot from
11
+ * STAGEFLOW_PROVIDER_TYPESAFE_API_KEY), then the env names in TYPESAFE_KEY_ENV_NAMES. The first one set wins.
12
+ */
13
+ export declare function resolveTypesafeKey(projectRoot: string, env?: NodeJS.ProcessEnv): TypesafeKeyLookup;
@@ -0,0 +1,20 @@
1
+ import { resolveCredentialBinding } from "../../runtime/credentialBinding.js";
2
+ import { readAuthKey } from "../providerKeys.js";
3
+ import { TYPESAFE_KEY_ENV_NAMES, TYPESAFE_PROVIDER_ID } from "./constants.js";
4
+ export const STORED_KEY_SOURCE = `stored:${TYPESAFE_PROVIDER_ID}`;
5
+ /**
6
+ * Lookup order: the stored `typesafe` provider credential (Settings, Providers, or boot from
7
+ * STAGEFLOW_PROVIDER_TYPESAFE_API_KEY), then the env names in TYPESAFE_KEY_ENV_NAMES. The first one set wins.
8
+ */
9
+ export function resolveTypesafeKey(projectRoot, env = process.env) {
10
+ const found = [];
11
+ const stored = readAuthKey(resolveCredentialBinding(projectRoot).authPath, TYPESAFE_PROVIDER_ID);
12
+ if (stored !== undefined)
13
+ found.push({ source: STORED_KEY_SOURCE, key: stored });
14
+ for (const name of TYPESAFE_KEY_ENV_NAMES) {
15
+ const value = env[name]?.trim();
16
+ if (value !== undefined && value.length > 0)
17
+ found.push({ source: name, key: value });
18
+ }
19
+ return { key: found[0]?.key, sources: found.map((entry) => entry.source) };
20
+ }
@@ -0,0 +1,14 @@
1
+ import { type TriageBucket } from "./constants.js";
2
+ import { type FailureClassifier } from "./types.js";
3
+ export type JevClassifierOptions = {
4
+ apiKey: string;
5
+ fetch?: typeof fetch;
6
+ baseUrl?: string;
7
+ model?: string;
8
+ maxRetries?: number;
9
+ backoffBaseMs?: number;
10
+ sleep?: (ms: number) => Promise<void>;
11
+ };
12
+ export declare function normalizeBucketProbabilities(raw: unknown, choice: TriageBucket, confidence: number): Record<TriageBucket, number>;
13
+ /** System One (TypeSafe Jev) backend. The key goes in one header and is never logged, returned or put in an error. */
14
+ export declare function createJevClassifier(options: JevClassifierOptions): FailureClassifier;
@@ -0,0 +1,124 @@
1
+ import { JEV_BACKOFF_BASE_MS, JEV_BASE_URL, JEV_MAX_RETRIES, JEV_MODEL_ID, JEV_PRICE_INPUT_PER_MILLION_USD, TRIAGE_BUCKETS, } from "./constants.js";
2
+ import { BUCKET_QUESTION, bucketCriteriaMap, FAILURE_TYPE_QUESTION, failureTypeCriteriaMap, failureTypesFor, falseAlarmQuestion, } from "./prompts.js";
3
+ import { ClassifierError } from "./types.js";
4
+ const defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
5
+ function num(value) {
6
+ return typeof value === "number" && Number.isFinite(value) ? value : undefined;
7
+ }
8
+ function clamp01(value) {
9
+ return Math.min(1, Math.max(0, value));
10
+ }
11
+ export function normalizeBucketProbabilities(raw, choice, confidence) {
12
+ const out = { agent_wrong: 0, grader_wrong: 0, case_wrong: 0, unclear: 0 };
13
+ const rec = typeof raw === "object" && raw !== null ? raw : {};
14
+ let any = false;
15
+ for (const bucket of TRIAGE_BUCKETS) {
16
+ const p = num(rec[bucket]);
17
+ if (p !== undefined) {
18
+ out[bucket] = clamp01(p);
19
+ any = true;
20
+ }
21
+ }
22
+ if (!any) {
23
+ const rest = (1 - confidence) / (TRIAGE_BUCKETS.length - 1);
24
+ for (const bucket of TRIAGE_BUCKETS)
25
+ out[bucket] = bucket === choice ? confidence : rest;
26
+ }
27
+ return out;
28
+ }
29
+ /** System One (TypeSafe Jev) backend. The key goes in one header and is never logged, returned or put in an error. */
30
+ export function createJevClassifier(options) {
31
+ const model = options.model ?? JEV_MODEL_ID;
32
+ const doFetch = options.fetch ?? fetch;
33
+ const url = `${(options.baseUrl ?? JEV_BASE_URL).replace(/\/+$/, "")}/v1/systemone`;
34
+ const maxRetries = options.maxRetries ?? JEV_MAX_RETRIES;
35
+ const backoff = options.backoffBaseMs ?? JEV_BACKOFF_BASE_MS;
36
+ const sleep = options.sleep ?? defaultSleep;
37
+ const { apiKey } = options;
38
+ async function post(body, signal) {
39
+ for (let attempt = 0;; attempt++) {
40
+ let res;
41
+ try {
42
+ res = await doFetch(url, {
43
+ method: "POST",
44
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` },
45
+ body: JSON.stringify(body),
46
+ ...(signal !== undefined ? { signal } : {}),
47
+ });
48
+ }
49
+ catch {
50
+ if (signal?.aborted)
51
+ throw new ClassifierError("CLASSIFIER_FAILED", "Classifier request was cancelled");
52
+ throw new ClassifierError("CLASSIFIER_FAILED", "Could not reach the classifier");
53
+ }
54
+ if (res.status === 429) {
55
+ if (attempt >= maxRetries)
56
+ throw new ClassifierError("CLASSIFIER_RATE_LIMITED", "Classifier rate limit; try again shortly");
57
+ const retryAfter = Number(res.headers.get("retry-after"));
58
+ const wait = Number.isFinite(retryAfter) && retryAfter > 0 ? retryAfter * 1000 : backoff * 2 ** attempt;
59
+ await res.body?.cancel().catch(() => undefined);
60
+ await sleep(wait);
61
+ continue;
62
+ }
63
+ if (res.status === 422 || res.status === 400) {
64
+ await res.body?.cancel().catch(() => undefined);
65
+ throw new ClassifierError("CLASSIFIER_REJECTED", `Classifier rejected the request (HTTP ${res.status})`);
66
+ }
67
+ if (!res.ok) {
68
+ await res.body?.cancel().catch(() => undefined);
69
+ throw new ClassifierError("CLASSIFIER_FAILED", `Classifier request failed (HTTP ${res.status})`);
70
+ }
71
+ try {
72
+ return (await res.json());
73
+ }
74
+ catch {
75
+ throw new ClassifierError("CLASSIFIER_BAD_REPLY", "Classifier reply was not JSON");
76
+ }
77
+ }
78
+ }
79
+ return {
80
+ source: "jev",
81
+ model,
82
+ async classify(input) {
83
+ const types = failureTypesFor(input.targetKind);
84
+ const questions = {
85
+ bucket: { type: "choice", instructions: BUCKET_QUESTION, criteria: bucketCriteriaMap() },
86
+ failure_type: {
87
+ type: "choice",
88
+ instructions: FAILURE_TYPE_QUESTION,
89
+ criteria: failureTypeCriteriaMap(input.targetKind),
90
+ },
91
+ };
92
+ input.graderQuestions.forEach((q, index) => {
93
+ questions[`false_alarm_${index}`] = { type: "noul", instructions: falseAlarmQuestion(q.graderId) };
94
+ });
95
+ const reply = await post({ model, state: input.state, questions }, input.signal);
96
+ const answers = reply.answers ?? {};
97
+ const bucketAnswer = answers.bucket;
98
+ const choice = bucketAnswer?.choice;
99
+ if (typeof choice !== "string" || !TRIAGE_BUCKETS.includes(choice)) {
100
+ throw new ClassifierError("CLASSIFIER_BAD_REPLY", "Classifier gave no valid bucket");
101
+ }
102
+ const bucket = choice;
103
+ const probsRaw = bucketAnswer?.probabilities;
104
+ const fromProbs = num(probsRaw?.[bucket]);
105
+ const confidence = clamp01(num(bucketAnswer?.confidence) ?? fromProbs ?? 0);
106
+ const failureChoice = answers.failure_type?.choice;
107
+ const failureType = typeof failureChoice === "string" && types.includes(failureChoice) ? failureChoice : null;
108
+ const graderFalseAlarms = input.graderQuestions.flatMap((q, index) => {
109
+ const p = num(answers[`false_alarm_${index}`]?.noul);
110
+ return p === undefined ? [] : [{ graderId: q.graderId, probability: clamp01(p) }];
111
+ });
112
+ const tokens = num(reply.usage?.input_tokens) ?? 0;
113
+ return {
114
+ bucket,
115
+ confidence,
116
+ bucketProbabilities: normalizeBucketProbabilities(probsRaw, bucket, confidence),
117
+ failureType,
118
+ graderFalseAlarms,
119
+ costUsd: (tokens * JEV_PRICE_INPUT_PER_MILLION_USD) / 1_000_000,
120
+ ...(typeof reply.model === "string" && reply.model.length > 0 ? { answeredModel: reply.model } : {}),
121
+ };
122
+ },
123
+ };
124
+ }
@@ -0,0 +1,10 @@
1
+ import type { SimulatorModel } from "../runner/simulatorModel.js";
2
+ import { type FailureClassifier } from "./types.js";
3
+ /**
4
+ * Judge-model backend: the same one-shot model call the agent simulator uses, with a fixed prompt and a JSON reply.
5
+ * `model` is any `SimulatorModel`; the Host builds it from the agent backend.
6
+ */
7
+ export declare function createJudgeClassifier(options: {
8
+ model: SimulatorModel;
9
+ modelId: string;
10
+ }): FailureClassifier;
@@ -0,0 +1,76 @@
1
+ import { TRIAGE_BUCKETS } from "./constants.js";
2
+ import { normalizeBucketProbabilities } from "./jevClassifier.js";
3
+ import { failureTypesFor, judgeSystemPrompt, judgeUserPrompt } from "./prompts.js";
4
+ import { ClassifierError } from "./types.js";
5
+ const JUDGE_CALL_TIMEOUT_MS = 120_000;
6
+ function extractJson(text) {
7
+ const start = text.indexOf("{");
8
+ const end = text.lastIndexOf("}");
9
+ if (start < 0 || end <= start)
10
+ return null;
11
+ try {
12
+ const parsed = JSON.parse(text.slice(start, end + 1));
13
+ return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : null;
14
+ }
15
+ catch {
16
+ return null;
17
+ }
18
+ }
19
+ function num(value) {
20
+ return typeof value === "number" && Number.isFinite(value) ? Math.min(1, Math.max(0, value)) : undefined;
21
+ }
22
+ /**
23
+ * Judge-model backend: the same one-shot model call the agent simulator uses, with a fixed prompt and a JSON reply.
24
+ * `model` is any `SimulatorModel`; the Host builds it from the agent backend.
25
+ */
26
+ export function createJudgeClassifier(options) {
27
+ return {
28
+ source: "judge",
29
+ model: options.modelId,
30
+ async classify(input) {
31
+ const signal = input.signal ?? AbortSignal.timeout(JUDGE_CALL_TIMEOUT_MS);
32
+ let reply;
33
+ try {
34
+ reply = await options.model.complete({
35
+ system: judgeSystemPrompt(),
36
+ user: judgeUserPrompt({
37
+ targetKind: input.targetKind,
38
+ state: input.state,
39
+ graderIds: input.graderQuestions.map((q) => q.graderId),
40
+ }),
41
+ signal,
42
+ });
43
+ }
44
+ catch {
45
+ throw new ClassifierError("CLASSIFIER_FAILED", "The judge model call failed");
46
+ }
47
+ const parsed = extractJson(reply.text);
48
+ const bucketRaw = parsed?.bucket;
49
+ if (parsed === null || typeof bucketRaw !== "string" || !TRIAGE_BUCKETS.includes(bucketRaw)) {
50
+ throw new ClassifierError("CLASSIFIER_BAD_REPLY", "The judge model did not return a valid bucket");
51
+ }
52
+ const bucket = bucketRaw;
53
+ const confidence = num(parsed.confidence) ?? 0.5;
54
+ const types = failureTypesFor(input.targetKind);
55
+ const failureType = typeof parsed.failure_type === "string" && types.includes(parsed.failure_type) ? parsed.failure_type : null;
56
+ const known = new Set(input.graderQuestions.map((q) => q.graderId));
57
+ const alarms = Array.isArray(parsed.grader_false_alarms) ? parsed.grader_false_alarms : [];
58
+ const graderFalseAlarms = alarms.flatMap((entry) => {
59
+ const rec = typeof entry === "object" && entry !== null ? entry : {};
60
+ const p = num(rec.probability);
61
+ return typeof rec.grader_id === "string" && known.has(rec.grader_id) && p !== undefined
62
+ ? [{ graderId: rec.grader_id, probability: p }]
63
+ : [];
64
+ });
65
+ return {
66
+ bucket,
67
+ confidence,
68
+ bucketProbabilities: normalizeBucketProbabilities(undefined, bucket, confidence),
69
+ failureType,
70
+ graderFalseAlarms,
71
+ costUsd: reply.usage?.costUsd ?? 0,
72
+ ...(reply.usage?.model !== undefined ? { answeredModel: reply.usage.model } : {}),
73
+ };
74
+ },
75
+ };
76
+ }
@@ -0,0 +1,16 @@
1
+ import { type TriageBucket } from "./constants.js";
2
+ /** Changing any text here requires bumping TRIAGE_PROMPT_VERSION in src/evals/constants.ts. */
3
+ export declare const BUCKET_CRITERIA: Record<TriageBucket, string>;
4
+ export declare const FAILURE_TYPE_CRITERIA: Record<string, string>;
5
+ export declare function failureTypesFor(kind: "stage" | "agent"): readonly string[];
6
+ export declare function bucketCriteriaMap(): Record<string, string>;
7
+ export declare function failureTypeCriteriaMap(kind: "stage" | "agent"): Record<string, string>;
8
+ export declare const BUCKET_QUESTION = "Why did this eval result fail? Choose who is at fault: the target, a grader, or the test case. Choose unclear when unsure.";
9
+ export declare const FAILURE_TYPE_QUESTION = "Which kind of failure is this? Choose the closest type.";
10
+ export declare const falseAlarmQuestion: (graderId: string) => string;
11
+ export declare function judgeSystemPrompt(): string;
12
+ export declare function judgeUserPrompt(input: {
13
+ targetKind: "stage" | "agent";
14
+ state: string;
15
+ graderIds: string[];
16
+ }): string;