@relayflows/sdk 2.0.42 → 2.0.43

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 (370) hide show
  1. package/dist/adapters/base.d.ts +12 -1
  2. package/dist/adapters/base.d.ts.map +1 -1
  3. package/dist/adapters/base.js +11 -1
  4. package/dist/adapters/base.js.map +1 -1
  5. package/dist/adapters/claude.d.ts.map +1 -1
  6. package/dist/adapters/claude.js +8 -4
  7. package/dist/adapters/claude.js.map +1 -1
  8. package/dist/adapters/codex.d.ts.map +1 -1
  9. package/dist/adapters/codex.js +15 -6
  10. package/dist/adapters/codex.js.map +1 -1
  11. package/dist/agent-resume.d.ts +8 -0
  12. package/dist/agent-resume.d.ts.map +1 -0
  13. package/dist/agent-resume.js +37 -0
  14. package/dist/agent-resume.js.map +1 -0
  15. package/dist/agent-transcript.d.ts.map +1 -1
  16. package/dist/agent-transcript.js +5 -3
  17. package/dist/agent-transcript.js.map +1 -1
  18. package/dist/authored-flow-error.d.ts +10 -2
  19. package/dist/authored-flow-error.d.ts.map +1 -1
  20. package/dist/authored-flow-error.js.map +1 -1
  21. package/dist/authored-flow-executor.d.ts.map +1 -1
  22. package/dist/authored-flow-executor.js +16 -2
  23. package/dist/authored-flow-executor.js.map +1 -1
  24. package/dist/authored-flow-loader.d.ts +6 -0
  25. package/dist/authored-flow-loader.d.ts.map +1 -1
  26. package/dist/authored-flow-loader.js +18 -6
  27. package/dist/authored-flow-loader.js.map +1 -1
  28. package/dist/authored-helper-effect.js +3 -2
  29. package/dist/authored-helper-effect.js.map +1 -1
  30. package/dist/authored-human.d.ts +2 -0
  31. package/dist/authored-human.d.ts.map +1 -1
  32. package/dist/authored-human.js +4 -0
  33. package/dist/authored-human.js.map +1 -1
  34. package/dist/authored-memory.d.ts +47 -2
  35. package/dist/authored-memory.d.ts.map +1 -1
  36. package/dist/authored-memory.js +394 -15
  37. package/dist/authored-memory.js.map +1 -1
  38. package/dist/authored-node-entry.js +6 -1
  39. package/dist/authored-node-entry.js.map +1 -1
  40. package/dist/authored-node-runner.d.ts +1 -1
  41. package/dist/authored-node-runner.d.ts.map +1 -1
  42. package/dist/authored-node-runner.js +6 -3
  43. package/dist/authored-node-runner.js.map +1 -1
  44. package/dist/authored-root-readback.d.ts +21 -0
  45. package/dist/authored-root-readback.d.ts.map +1 -0
  46. package/dist/authored-root-readback.js +90 -0
  47. package/dist/authored-root-readback.js.map +1 -0
  48. package/dist/authored-root.d.ts.map +1 -1
  49. package/dist/authored-root.js +53 -74
  50. package/dist/authored-root.js.map +1 -1
  51. package/dist/authored-step-output.d.ts +2 -0
  52. package/dist/authored-step-output.d.ts.map +1 -1
  53. package/dist/authored-step-output.js +1 -0
  54. package/dist/authored-step-output.js.map +1 -1
  55. package/dist/authored-worker-step.d.ts.map +1 -1
  56. package/dist/authored-worker-step.js +26 -4
  57. package/dist/authored-worker-step.js.map +1 -1
  58. package/dist/cli/check-helper-body.d.ts +2 -2
  59. package/dist/cli/check-helper-body.d.ts.map +1 -1
  60. package/dist/cli/check-helper-body.js +7 -2
  61. package/dist/cli/check-helper-body.js.map +1 -1
  62. package/dist/cli/check-helper-surface.d.ts +8 -0
  63. package/dist/cli/check-helper-surface.d.ts.map +1 -0
  64. package/dist/cli/check-helper-surface.js +37 -0
  65. package/dist/cli/check-helper-surface.js.map +1 -0
  66. package/dist/cli/check-triggers.d.ts +4 -3
  67. package/dist/cli/check-triggers.d.ts.map +1 -1
  68. package/dist/cli/check-triggers.js +7 -3
  69. package/dist/cli/check-triggers.js.map +1 -1
  70. package/dist/cli/check.d.ts +7 -1
  71. package/dist/cli/check.d.ts.map +1 -1
  72. package/dist/cli/check.js +35 -8
  73. package/dist/cli/check.js.map +1 -1
  74. package/dist/cli/cloud-answer.d.ts +9 -0
  75. package/dist/cli/cloud-answer.d.ts.map +1 -0
  76. package/dist/cli/cloud-answer.js +39 -0
  77. package/dist/cli/cloud-answer.js.map +1 -0
  78. package/dist/cli/cloud-connect-cli.d.ts +2 -1
  79. package/dist/cli/cloud-connect-cli.d.ts.map +1 -1
  80. package/dist/cli/cloud-connect-cli.js +10 -2
  81. package/dist/cli/cloud-connect-cli.js.map +1 -1
  82. package/dist/cli/cloud-human.d.ts +7 -0
  83. package/dist/cli/cloud-human.d.ts.map +1 -0
  84. package/dist/cli/cloud-human.js +22 -0
  85. package/dist/cli/cloud-human.js.map +1 -0
  86. package/dist/cli/cloud-live.d.ts +2 -2
  87. package/dist/cli/cloud-live.d.ts.map +1 -1
  88. package/dist/cli/cloud-live.js +9 -2
  89. package/dist/cli/cloud-live.js.map +1 -1
  90. package/dist/cli/cloud-mirror-session.d.ts.map +1 -1
  91. package/dist/cli/cloud-mirror-session.js +3 -2
  92. package/dist/cli/cloud-mirror-session.js.map +1 -1
  93. package/dist/cli/cloud-run.d.ts +1 -1
  94. package/dist/cli/cloud-run.d.ts.map +1 -1
  95. package/dist/cli/cloud-run.js +12 -0
  96. package/dist/cli/cloud-run.js.map +1 -1
  97. package/dist/cli/detached-record.d.ts +22 -0
  98. package/dist/cli/detached-record.d.ts.map +1 -0
  99. package/dist/cli/detached-record.js +57 -0
  100. package/dist/cli/detached-record.js.map +1 -0
  101. package/dist/cli/detached-run.d.ts +28 -0
  102. package/dist/cli/detached-run.d.ts.map +1 -0
  103. package/dist/cli/detached-run.js +122 -0
  104. package/dist/cli/detached-run.js.map +1 -0
  105. package/dist/cli/diagnostic-fold.d.ts +19 -0
  106. package/dist/cli/diagnostic-fold.d.ts.map +1 -0
  107. package/dist/cli/diagnostic-fold.js +19 -0
  108. package/dist/cli/diagnostic-fold.js.map +1 -0
  109. package/dist/cli/direct-run.d.ts.map +1 -1
  110. package/dist/cli/direct-run.js +16 -2
  111. package/dist/cli/direct-run.js.map +1 -1
  112. package/dist/cli/eval.d.ts +22 -0
  113. package/dist/cli/eval.d.ts.map +1 -0
  114. package/dist/cli/eval.js +131 -0
  115. package/dist/cli/eval.js.map +1 -0
  116. package/dist/cli/journal-timeout.d.ts +12 -0
  117. package/dist/cli/journal-timeout.d.ts.map +1 -0
  118. package/dist/cli/journal-timeout.js +42 -0
  119. package/dist/cli/journal-timeout.js.map +1 -0
  120. package/dist/cli/local-agent-remedy.d.ts.map +1 -1
  121. package/dist/cli/local-agent-remedy.js +5 -4
  122. package/dist/cli/local-agent-remedy.js.map +1 -1
  123. package/dist/cli/observer-session.d.ts +1 -0
  124. package/dist/cli/observer-session.d.ts.map +1 -1
  125. package/dist/cli/observer-session.js +8 -1
  126. package/dist/cli/observer-session.js.map +1 -1
  127. package/dist/cli/reuse.d.ts +8 -0
  128. package/dist/cli/reuse.d.ts.map +1 -1
  129. package/dist/cli/reuse.js +24 -0
  130. package/dist/cli/reuse.js.map +1 -1
  131. package/dist/cli/run.d.ts +8 -2
  132. package/dist/cli/run.d.ts.map +1 -1
  133. package/dist/cli/run.js +72 -56
  134. package/dist/cli/run.js.map +1 -1
  135. package/dist/cli/running-step.d.ts +9 -0
  136. package/dist/cli/running-step.d.ts.map +1 -0
  137. package/dist/cli/running-step.js +156 -0
  138. package/dist/cli/running-step.js.map +1 -0
  139. package/dist/cli-adapter.d.ts +3 -1
  140. package/dist/cli-adapter.d.ts.map +1 -1
  141. package/dist/cli-adapter.js +6 -2
  142. package/dist/cli-adapter.js.map +1 -1
  143. package/dist/cli-commands.d.ts +77 -11
  144. package/dist/cli-commands.d.ts.map +1 -1
  145. package/dist/cli-commands.js +41 -7
  146. package/dist/cli-commands.js.map +1 -1
  147. package/dist/cli-watch.d.ts +6 -2
  148. package/dist/cli-watch.d.ts.map +1 -1
  149. package/dist/cli-watch.js +7 -6
  150. package/dist/cli-watch.js.map +1 -1
  151. package/dist/cli.d.ts +22 -1
  152. package/dist/cli.d.ts.map +1 -1
  153. package/dist/cli.js +154 -50
  154. package/dist/cli.js.map +1 -1
  155. package/dist/cloud-answer.d.ts +35 -0
  156. package/dist/cloud-answer.d.ts.map +1 -0
  157. package/dist/cloud-answer.js +194 -0
  158. package/dist/cloud-answer.js.map +1 -0
  159. package/dist/cloud-auth-store.d.ts +46 -0
  160. package/dist/cloud-auth-store.d.ts.map +1 -0
  161. package/dist/cloud-auth-store.js +171 -0
  162. package/dist/cloud-auth-store.js.map +1 -0
  163. package/dist/cloud-http.d.ts +7 -16
  164. package/dist/cloud-http.d.ts.map +1 -1
  165. package/dist/cloud-http.js +59 -40
  166. package/dist/cloud-http.js.map +1 -1
  167. package/dist/cloud-human-wait.d.ts +10 -0
  168. package/dist/cloud-human-wait.d.ts.map +1 -0
  169. package/dist/cloud-human-wait.js +17 -0
  170. package/dist/cloud-human-wait.js.map +1 -0
  171. package/dist/cloud-mirror-transport.d.ts.map +1 -1
  172. package/dist/cloud-mirror-transport.js +1 -0
  173. package/dist/cloud-mirror-transport.js.map +1 -1
  174. package/dist/cloud-run-record.d.ts +7 -2
  175. package/dist/cloud-run-record.d.ts.map +1 -1
  176. package/dist/cloud-run-record.js +13 -5
  177. package/dist/cloud-run-record.js.map +1 -1
  178. package/dist/cloud-run.d.ts +9 -0
  179. package/dist/cloud-run.d.ts.map +1 -1
  180. package/dist/cloud-run.js +36 -2
  181. package/dist/cloud-run.js.map +1 -1
  182. package/dist/communication/local.d.ts.map +1 -1
  183. package/dist/communication/local.js +6 -1
  184. package/dist/communication/local.js.map +1 -1
  185. package/dist/communication/worker.d.ts.map +1 -1
  186. package/dist/communication/worker.js +12 -2
  187. package/dist/communication/worker.js.map +1 -1
  188. package/dist/compile.d.ts.map +1 -1
  189. package/dist/compile.js +5 -3
  190. package/dist/compile.js.map +1 -1
  191. package/dist/daemon-spec-validation.d.ts +31 -0
  192. package/dist/daemon-spec-validation.d.ts.map +1 -0
  193. package/dist/daemon-spec-validation.js +115 -0
  194. package/dist/daemon-spec-validation.js.map +1 -0
  195. package/dist/failure-kinds.d.ts +6 -4
  196. package/dist/failure-kinds.d.ts.map +1 -1
  197. package/dist/failure-kinds.js +17 -1
  198. package/dist/failure-kinds.js.map +1 -1
  199. package/dist/flow-eval-cloud.d.ts +25 -0
  200. package/dist/flow-eval-cloud.d.ts.map +1 -0
  201. package/dist/flow-eval-cloud.js +108 -0
  202. package/dist/flow-eval-cloud.js.map +1 -0
  203. package/dist/flow-eval-error.d.ts +7 -0
  204. package/dist/flow-eval-error.d.ts.map +1 -0
  205. package/dist/flow-eval-error.js +10 -0
  206. package/dist/flow-eval-error.js.map +1 -0
  207. package/dist/flow-eval-gate.d.ts +15 -0
  208. package/dist/flow-eval-gate.d.ts.map +1 -0
  209. package/dist/flow-eval-gate.js +102 -0
  210. package/dist/flow-eval-gate.js.map +1 -0
  211. package/dist/flow-eval-local.d.ts +54 -0
  212. package/dist/flow-eval-local.d.ts.map +1 -0
  213. package/dist/flow-eval-local.js +220 -0
  214. package/dist/flow-eval-local.js.map +1 -0
  215. package/dist/flow-eval-outcome.d.ts +22 -0
  216. package/dist/flow-eval-outcome.d.ts.map +1 -0
  217. package/dist/flow-eval-outcome.js +37 -0
  218. package/dist/flow-eval-outcome.js.map +1 -0
  219. package/dist/flow-eval-report.d.ts +106 -0
  220. package/dist/flow-eval-report.d.ts.map +1 -0
  221. package/dist/flow-eval-report.js +4 -0
  222. package/dist/flow-eval-report.js.map +1 -0
  223. package/dist/flow-eval-suite.d.ts +46 -0
  224. package/dist/flow-eval-suite.d.ts.map +1 -0
  225. package/dist/flow-eval-suite.js +144 -0
  226. package/dist/flow-eval-suite.js.map +1 -0
  227. package/dist/flow-eval-version.d.ts +59 -0
  228. package/dist/flow-eval-version.d.ts.map +1 -0
  229. package/dist/flow-eval-version.js +303 -0
  230. package/dist/flow-eval-version.js.map +1 -0
  231. package/dist/flow-eval.d.ts +41 -0
  232. package/dist/flow-eval.d.ts.map +1 -0
  233. package/dist/flow-eval.js +201 -0
  234. package/dist/flow-eval.js.map +1 -0
  235. package/dist/helper-operation-use.d.ts +18 -0
  236. package/dist/helper-operation-use.d.ts.map +1 -0
  237. package/dist/helper-operation-use.js +336 -0
  238. package/dist/helper-operation-use.js.map +1 -0
  239. package/dist/helper-preflight.d.ts.map +1 -1
  240. package/dist/helper-preflight.js +16 -2
  241. package/dist/helper-preflight.js.map +1 -1
  242. package/dist/helper-reference.d.ts +33 -0
  243. package/dist/helper-reference.d.ts.map +1 -1
  244. package/dist/helper-reference.js +5 -5
  245. package/dist/helper-reference.js.map +1 -1
  246. package/dist/index.d.ts +6 -1
  247. package/dist/index.d.ts.map +1 -1
  248. package/dist/index.js +5 -1
  249. package/dist/index.js.map +1 -1
  250. package/dist/journal-budgeted-reads.d.ts +41 -0
  251. package/dist/journal-budgeted-reads.d.ts.map +1 -0
  252. package/dist/journal-budgeted-reads.js +142 -0
  253. package/dist/journal-budgeted-reads.js.map +1 -0
  254. package/dist/journal-client.d.ts +34 -29
  255. package/dist/journal-client.d.ts.map +1 -1
  256. package/dist/journal-client.js +45 -151
  257. package/dist/journal-client.js.map +1 -1
  258. package/dist/journal-connection.d.ts +42 -0
  259. package/dist/journal-connection.d.ts.map +1 -0
  260. package/dist/journal-connection.js +209 -0
  261. package/dist/journal-connection.js.map +1 -0
  262. package/dist/journal-read-policy.d.ts +38 -0
  263. package/dist/journal-read-policy.d.ts.map +1 -0
  264. package/dist/journal-read-policy.js +126 -0
  265. package/dist/journal-read-policy.js.map +1 -0
  266. package/dist/named-gate-lowering.d.ts.map +1 -1
  267. package/dist/named-gate-lowering.js +2 -6
  268. package/dist/named-gate-lowering.js.map +1 -1
  269. package/dist/re2js-embedded.d.ts +3 -0
  270. package/dist/re2js-embedded.d.ts.map +1 -0
  271. package/dist/re2js-embedded.js +4 -0
  272. package/dist/re2js-embedded.js.map +1 -0
  273. package/dist/spec.d.ts +10 -0
  274. package/dist/spec.d.ts.map +1 -1
  275. package/dist/spec.js.map +1 -1
  276. package/dist/step-fields.d.ts +1 -1
  277. package/dist/step-fields.js +1 -1
  278. package/dist/step-fields.js.map +1 -1
  279. package/dist/validate.d.ts.map +1 -1
  280. package/dist/validate.js +15 -0
  281. package/dist/validate.js.map +1 -1
  282. package/dist/worker-cli.d.ts +3 -1
  283. package/dist/worker-cli.d.ts.map +1 -1
  284. package/dist/worker-cli.js +15 -5
  285. package/dist/worker-cli.js.map +1 -1
  286. package/dist/worker-lease.d.ts.map +1 -1
  287. package/dist/worker-lease.js +11 -3
  288. package/dist/worker-lease.js.map +1 -1
  289. package/dist/worker.js +1 -1
  290. package/dist/worker.js.map +1 -1
  291. package/package.json +5 -3
  292. package/src/adapters/base.ts +16 -1
  293. package/src/adapters/claude.ts +8 -4
  294. package/src/adapters/codex.ts +15 -6
  295. package/src/agent-resume.ts +36 -0
  296. package/src/agent-transcript.ts +5 -3
  297. package/src/authored-flow-error.ts +9 -0
  298. package/src/authored-flow-executor.ts +18 -1
  299. package/src/authored-flow-loader.ts +27 -10
  300. package/src/authored-helper-effect.ts +3 -2
  301. package/src/authored-human.ts +5 -0
  302. package/src/authored-memory.ts +445 -15
  303. package/src/authored-node-entry.ts +6 -1
  304. package/src/authored-node-runner.ts +6 -3
  305. package/src/authored-root-readback.ts +100 -0
  306. package/src/authored-root.ts +58 -85
  307. package/src/authored-step-output.ts +3 -0
  308. package/src/authored-worker-step.ts +29 -4
  309. package/src/cli/check-helper-body.ts +9 -3
  310. package/src/cli/check-helper-surface.ts +43 -0
  311. package/src/cli/check-triggers.ts +9 -4
  312. package/src/cli/check.ts +37 -7
  313. package/src/cli/cloud-answer.ts +40 -0
  314. package/src/cli/cloud-connect-cli.ts +9 -2
  315. package/src/cli/cloud-human.ts +24 -0
  316. package/src/cli/cloud-live.ts +10 -5
  317. package/src/cli/cloud-mirror-session.ts +3 -2
  318. package/src/cli/cloud-run.ts +10 -1
  319. package/src/cli/detached-record.ts +71 -0
  320. package/src/cli/detached-run.ts +131 -0
  321. package/src/cli/diagnostic-fold.ts +28 -0
  322. package/src/cli/direct-run.ts +14 -1
  323. package/src/cli/eval.ts +141 -0
  324. package/src/cli/journal-timeout.ts +49 -0
  325. package/src/cli/local-agent-remedy.ts +6 -4
  326. package/src/cli/observer-session.ts +7 -1
  327. package/src/cli/reuse.ts +25 -0
  328. package/src/cli/run.ts +75 -67
  329. package/src/cli/running-step.ts +140 -0
  330. package/src/cli-adapter.ts +7 -1
  331. package/src/cli-commands.ts +43 -7
  332. package/src/cli-watch.ts +8 -5
  333. package/src/cli.ts +158 -51
  334. package/src/cloud-answer.ts +202 -0
  335. package/src/cloud-auth-store.ts +185 -0
  336. package/src/cloud-http.ts +61 -50
  337. package/src/cloud-human-wait.ts +23 -0
  338. package/src/cloud-mirror-transport.ts +1 -0
  339. package/src/cloud-run-record.ts +14 -5
  340. package/src/cloud-run.ts +46 -2
  341. package/src/communication/local.ts +6 -1
  342. package/src/communication/worker.ts +11 -3
  343. package/src/compile.ts +5 -3
  344. package/src/daemon-spec-validation.ts +126 -0
  345. package/src/failure-kinds.ts +17 -1
  346. package/src/flow-eval-cloud.ts +114 -0
  347. package/src/flow-eval-error.ts +10 -0
  348. package/src/flow-eval-gate.ts +114 -0
  349. package/src/flow-eval-local.ts +236 -0
  350. package/src/flow-eval-outcome.ts +43 -0
  351. package/src/flow-eval-report.ts +102 -0
  352. package/src/flow-eval-suite.ts +169 -0
  353. package/src/flow-eval-version.ts +316 -0
  354. package/src/flow-eval.ts +234 -0
  355. package/src/helper-operation-use.ts +285 -0
  356. package/src/helper-preflight.ts +17 -2
  357. package/src/helper-reference.ts +6 -6
  358. package/src/index.ts +15 -1
  359. package/src/journal-budgeted-reads.ts +134 -0
  360. package/src/journal-client.ts +59 -166
  361. package/src/journal-connection.ts +222 -0
  362. package/src/journal-read-policy.ts +123 -0
  363. package/src/named-gate-lowering.ts +2 -6
  364. package/src/re2js-embedded.ts +3 -0
  365. package/src/spec.ts +10 -0
  366. package/src/step-fields.ts +1 -1
  367. package/src/validate.ts +14 -0
  368. package/src/worker-cli.ts +14 -3
  369. package/src/worker-lease.ts +11 -3
  370. package/src/worker.ts +1 -1
@@ -0,0 +1,144 @@
1
+ // The frozen input set of a flow evaluation: its shape, strict parsing of
2
+ // untrusted suite JSON, and its identity hash.
3
+ import { createHash } from 'node:crypto';
4
+ import { readFile } from 'node:fs/promises';
5
+ import { canonicalize } from './canonical.js';
6
+ import { FlowEvalError } from './flow-eval-error.js';
7
+ import { snapshotJsonValue } from './json-value.js';
8
+ import { MAX_DIRECT_INPUT_BYTES } from './direct-input.js';
9
+ import { deepFreeze } from './flow-eval-version.js';
10
+ export const MAX_FLOW_EVAL_CASES = 1_000;
11
+ /** One case's input: no larger than `flows run --input` accepts. */
12
+ const INPUT_LIMITS = Object.freeze({ maxDepth: 64, maxNodes: 262_144, maxBytes: MAX_DIRECT_INPUT_BYTES });
13
+ /** Validate untrusted suite data (parsed JSON) into a frozen suite. */
14
+ export function parseFlowEvalSuite(value) {
15
+ const fail = (message) => { throw new FlowEvalError('invalid_suite', message); };
16
+ if (!isRecord(value))
17
+ fail('Suite must be a JSON object.');
18
+ const raw = value;
19
+ allowOnly(raw, ['name', 'cases', 'thresholds'], 'suite', fail);
20
+ if (typeof raw.name !== 'string' || raw.name.trim() === '')
21
+ fail('Suite needs a nonempty `name`.');
22
+ if (!Array.isArray(raw.cases) || raw.cases.length === 0)
23
+ fail('Suite needs a nonempty `cases` array.');
24
+ const rawCases = raw.cases;
25
+ if (rawCases.length > MAX_FLOW_EVAL_CASES)
26
+ fail(`Suite has ${rawCases.length} cases; the limit is ${MAX_FLOW_EVAL_CASES}.`);
27
+ const seen = new Set();
28
+ const cases = rawCases.map((entry, index) => {
29
+ const at = `cases[${index}]`;
30
+ if (!isRecord(entry))
31
+ fail(`${at} must be an object.`);
32
+ const item = entry;
33
+ allowOnly(item, ['id', 'input', 'expect'], at, fail);
34
+ if (typeof item.id !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u.test(item.id)) {
35
+ fail(`${at}.id must be 1-128 characters of letters, digits, '.', '_', ':' or '-'.`);
36
+ }
37
+ const id = item.id;
38
+ if (seen.has(id))
39
+ fail(`${at}.id "${id}" is not unique.`);
40
+ seen.add(id);
41
+ const testCase = { id };
42
+ if (Object.prototype.hasOwnProperty.call(item, 'input')) {
43
+ try {
44
+ testCase.input = snapshotJsonValue(item.input, `${at}.input`, INPUT_LIMITS);
45
+ }
46
+ catch (error) {
47
+ fail(`${at}.input is not JSON data: ${error instanceof Error ? error.message : String(error)}`);
48
+ }
49
+ }
50
+ if (item.expect !== undefined)
51
+ testCase.expect = parseExpectation(item.expect, `${at}.expect`, fail);
52
+ return testCase;
53
+ });
54
+ const suite = { name: raw.name, cases };
55
+ if (raw.thresholds !== undefined) {
56
+ if (!isRecord(raw.thresholds))
57
+ fail('`thresholds` must be an object.');
58
+ const t = raw.thresholds;
59
+ allowOnly(t, ['minPassRate', 'maxTotalCostUsd', 'maxP95LatencyMs'], 'thresholds', fail);
60
+ const thresholds = {};
61
+ if (t.minPassRate !== undefined) {
62
+ if (typeof t.minPassRate !== 'number' || !(t.minPassRate >= 0 && t.minPassRate <= 1))
63
+ fail('`thresholds.minPassRate` must be a number from 0 to 1.');
64
+ thresholds.minPassRate = t.minPassRate;
65
+ }
66
+ if (t.maxTotalCostUsd !== undefined)
67
+ thresholds.maxTotalCostUsd = nonNegative(t.maxTotalCostUsd, 'thresholds.maxTotalCostUsd', fail);
68
+ if (t.maxP95LatencyMs !== undefined)
69
+ thresholds.maxP95LatencyMs = nonNegative(t.maxP95LatencyMs, 'thresholds.maxP95LatencyMs', fail);
70
+ suite.thresholds = thresholds;
71
+ }
72
+ // Frozen in fact, not just by name: a scorer receives these cases, and must
73
+ // not be able to rename one or loosen an expectation for the cases after it.
74
+ return deepFreeze(suite);
75
+ }
76
+ /** Read and validate a suite file (JSON). */
77
+ export async function loadFlowEvalSuite(path) {
78
+ let text;
79
+ try {
80
+ text = await readFile(path, 'utf8');
81
+ }
82
+ catch {
83
+ throw new FlowEvalError('invalid_suite', `Suite file "${path}" is not readable.`);
84
+ }
85
+ let parsed;
86
+ try {
87
+ parsed = JSON.parse(text);
88
+ }
89
+ catch {
90
+ throw new FlowEvalError('invalid_suite', `Suite file "${path}" is not valid JSON.`);
91
+ }
92
+ return parseFlowEvalSuite(parsed);
93
+ }
94
+ /** The suite's identity: sha256 of its canonical JSON. */
95
+ export function flowEvalSuiteSha256(suite) {
96
+ return `sha256:${createHash('sha256').update(canonicalize(suite)).digest('hex')}`;
97
+ }
98
+ function parseExpectation(value, at, fail) {
99
+ if (!isRecord(value))
100
+ fail(`${at} must be an object.`);
101
+ const raw = value;
102
+ allowOnly(raw, ['completionReason', 'detailIncludes', 'detailMatches', 'maxLatencyMs', 'maxCostUsd'], at, fail);
103
+ const expect = {};
104
+ if (raw.completionReason !== undefined) {
105
+ if (typeof raw.completionReason !== 'string' || raw.completionReason === '')
106
+ fail(`${at}.completionReason must be a nonempty string.`);
107
+ expect.completionReason = raw.completionReason;
108
+ }
109
+ if (raw.detailIncludes !== undefined) {
110
+ if (!Array.isArray(raw.detailIncludes) || raw.detailIncludes.some(item => typeof item !== 'string'))
111
+ fail(`${at}.detailIncludes must be an array of strings.`);
112
+ expect.detailIncludes = [...raw.detailIncludes];
113
+ }
114
+ if (raw.detailMatches !== undefined) {
115
+ if (typeof raw.detailMatches !== 'string')
116
+ fail(`${at}.detailMatches must be a string.`);
117
+ try {
118
+ new RegExp(raw.detailMatches, 'u');
119
+ }
120
+ catch {
121
+ fail(`${at}.detailMatches is not a valid regular expression.`);
122
+ }
123
+ expect.detailMatches = raw.detailMatches;
124
+ }
125
+ if (raw.maxLatencyMs !== undefined)
126
+ expect.maxLatencyMs = nonNegative(raw.maxLatencyMs, `${at}.maxLatencyMs`, fail);
127
+ if (raw.maxCostUsd !== undefined)
128
+ expect.maxCostUsd = nonNegative(raw.maxCostUsd, `${at}.maxCostUsd`, fail);
129
+ return expect;
130
+ }
131
+ function allowOnly(raw, keys, at, fail) {
132
+ for (const key of Object.keys(raw))
133
+ if (!keys.includes(key))
134
+ fail(`${at} has unknown field "${key}".`);
135
+ }
136
+ function nonNegative(value, at, fail) {
137
+ if (typeof value !== 'number' || !Number.isFinite(value) || value < 0)
138
+ fail(`\`${at}\` must be a non-negative number.`);
139
+ return value;
140
+ }
141
+ export function isRecord(value) {
142
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
143
+ }
144
+ //# sourceMappingURL=flow-eval-suite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-eval-suite.js","sourceRoot":"","sources":["../src/flow-eval-suite.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import type { FlowSpec } from './spec.js';
2
+ /** A flow source path (`.flow.ts`, `.flow.yaml`, spec JSON) or an in-memory spec. */
3
+ export type FlowEvalTarget = {
4
+ path: string;
5
+ } | FlowSpec;
6
+ export interface FlowEvalVersion {
7
+ /** `sha256:<hex>` over the manifest (or the kernel spec hash for an in-memory spec). */
8
+ version: string;
9
+ /** Manifest paths, relative to the entry's directory; empty for an in-memory spec. */
10
+ files: string[];
11
+ }
12
+ /** Most local source files one version may span; past it the evaluation is refused, not truncated. */
13
+ export declare const MAX_FLOW_EVAL_SOURCES = 2000;
14
+ export declare function isPathTarget(flow: FlowEvalTarget): flow is {
15
+ path: string;
16
+ };
17
+ /** The version string alone. */
18
+ export declare function flowEvalVersion(flow: FlowEvalTarget): Promise<string>;
19
+ /** The version and the files it covers. */
20
+ export declare function flowEvalSources(flow: FlowEvalTarget): Promise<FlowEvalVersion>;
21
+ /** The sealed bytes a version names, from which every case gets its own copy. */
22
+ export interface FlowEvalSnapshot extends FlowEvalVersion {
23
+ /**
24
+ * A fresh, read-only copy for one case: its own directory, files and
25
+ * directories without write permission, written from the buffers the
26
+ * version hashed. An in-memory spec yields a deep-frozen clone.
27
+ */
28
+ materialize(): Promise<{
29
+ flow: FlowEvalTarget;
30
+ dispose(): Promise<void>;
31
+ }>;
32
+ }
33
+ /**
34
+ * Seal the flow before any case runs, and execute only copies of the seal.
35
+ *
36
+ * Hashing the working tree and then running it would let the tree change
37
+ * between the two — an edit made after a check and restored before the next
38
+ * would run bytes the report never named. The sources are read once, hashed,
39
+ * and held in memory; each case then runs a fresh read-only copy written from
40
+ * those buffers, so nothing a case does to its copy reaches the next case. A
41
+ * local module the manifest could not see (a computed
42
+ * `import(\`./rules/${kind}.js\`)`, a file read at runtime) is simply absent
43
+ * from the copy, so such a run fails instead of executing unjudged code.
44
+ *
45
+ * Trust boundary: evaluated code runs as the caller, so it can still reach
46
+ * anything the caller can — including `node_modules`, which is linked rather
47
+ * than copied and pinned by the lockfile in the manifest. Containing hostile
48
+ * code needs a sandbox; this seal makes sure the code that runs is the code
49
+ * the version names.
50
+ */
51
+ export declare function sealFlowEvalSnapshot(flow: FlowEvalTarget): Promise<FlowEvalSnapshot>;
52
+ export declare function deepFreeze<T>(value: T): T;
53
+ /**
54
+ * Relative module specifiers and relative `.flow.ts` string literals (the
55
+ * `use:` header) in a source file. A lexical scan, deliberately: computing a
56
+ * version must never execute the flow.
57
+ */
58
+ export declare function localSpecifiers(source: string): string[];
59
+ //# sourceMappingURL=flow-eval-version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-eval-version.d.ts","sourceRoot":"","sources":["../src/flow-eval-version.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C,qFAAqF;AACrF,MAAM,MAAM,cAAc,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,QAAQ,CAAC;AAEzD,MAAM,WAAW,eAAe;IAC9B,wFAAwF;IACxF,OAAO,EAAE,MAAM,CAAC;IAChB,sFAAsF;IACtF,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,sGAAsG;AACtG,eAAO,MAAM,qBAAqB,OAAQ,CAAC;AAK3C,wBAAgB,YAAY,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,IAAI;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAE3E;AAED,gCAAgC;AAChC,wBAAsB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAE3E;AAED,2CAA2C;AAC3C,wBAAsB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC,CAIpF;AAED,iFAAiF;AACjF,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACvD;;;;OAIG;IACH,WAAW,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,cAAc,CAAC;QAAC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC,CAAC;CAC5E;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAwC1F;AAkBD,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAMzC;AA4HD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAUxD"}
@@ -0,0 +1,303 @@
1
+ // What a flow evaluation judges, by content: the flow version.
2
+ //
3
+ // For a flow file the version is the sha256 of a manifest of every local
4
+ // source the run reads, not of the entry file alone. Editing a helper module,
5
+ // a `use`d flow, or the project's extension lock changes what executes, so it
6
+ // must change the version too — otherwise `expectVersion` would accept code it
7
+ // never judged. Packages under node_modules are not part of the manifest; they
8
+ // are pinned by the project's own lockfile, which is. An evaluation executes a
9
+ // sealed copy of exactly these bytes (`sealFlowEvalSnapshot`).
10
+ import { createHash } from 'node:crypto';
11
+ import { existsSync, statSync } from 'node:fs';
12
+ import { chmod, mkdir, mkdtemp, readdir, readFile, realpath, rm, symlink, writeFile } from 'node:fs/promises';
13
+ import { tmpdir } from 'node:os';
14
+ import { basename, dirname, join, relative, resolve, sep } from 'node:path';
15
+ import { canonicalize, specHash } from './canonical.js';
16
+ import { compileSpec, toKernelSpec } from './compile.js';
17
+ import { FlowEvalError } from './flow-eval-error.js';
18
+ import { parsePluginLock } from './plugin-lock.js';
19
+ import { pluginStoreDirectory } from './plugin-store.js';
20
+ /** Most local source files one version may span; past it the evaluation is refused, not truncated. */
21
+ export const MAX_FLOW_EVAL_SOURCES = 2_000;
22
+ const SOURCE_EXTENSIONS = ['.ts', '.mts', '.cts', '.js', '.mjs', '.cjs', '.json'];
23
+ const PROJECT_FILES = ['package.json', 'flows.json', 'flows.lock.json', 'package-lock.json', 'bun.lock', 'pnpm-lock.yaml', 'yarn.lock'];
24
+ export function isPathTarget(flow) {
25
+ return typeof flow.path === 'string' && !('steps' in flow);
26
+ }
27
+ /** The version string alone. */
28
+ export async function flowEvalVersion(flow) {
29
+ return (await flowEvalSources(flow)).version;
30
+ }
31
+ /** The version and the files it covers. */
32
+ export async function flowEvalSources(flow) {
33
+ if (!isPathTarget(flow))
34
+ return { version: `sha256:${specHash(toKernelSpec(compileSpec(flow)))}`, files: [] };
35
+ const { version, files } = await collectSources(flow.path);
36
+ return { version, files: files.map(file => file.path) };
37
+ }
38
+ /**
39
+ * Seal the flow before any case runs, and execute only copies of the seal.
40
+ *
41
+ * Hashing the working tree and then running it would let the tree change
42
+ * between the two — an edit made after a check and restored before the next
43
+ * would run bytes the report never named. The sources are read once, hashed,
44
+ * and held in memory; each case then runs a fresh read-only copy written from
45
+ * those buffers, so nothing a case does to its copy reaches the next case. A
46
+ * local module the manifest could not see (a computed
47
+ * `import(\`./rules/${kind}.js\`)`, a file read at runtime) is simply absent
48
+ * from the copy, so such a run fails instead of executing unjudged code.
49
+ *
50
+ * Trust boundary: evaluated code runs as the caller, so it can still reach
51
+ * anything the caller can — including `node_modules`, which is linked rather
52
+ * than copied and pinned by the lockfile in the manifest. Containing hostile
53
+ * code needs a sandbox; this seal makes sure the code that runs is the code
54
+ * the version names.
55
+ */
56
+ export async function sealFlowEvalSnapshot(flow) {
57
+ if (!isPathTarget(flow)) {
58
+ // Hash and execute the same detached copy: a caller mutating its object
59
+ // later cannot change what the remaining cases run.
60
+ const frozen = deepFreeze(structuredClone(flow));
61
+ return { ...(await flowEvalSources(frozen)), materialize: async () => ({ flow: frozen, dispose: async () => { } }) };
62
+ }
63
+ const sources = await collectSources(flow.path);
64
+ // Every node_modules Node would consult from the entry, at the same relative
65
+ // place: a nested package resolves some dependencies from higher levels.
66
+ const modules = ancestorNodeModules(dirname(sources.entry));
67
+ const root = commonDirectory([...sources.absolute.map(file => file.path), ...modules.map(dir => join(dir, '.'))]);
68
+ return {
69
+ version: sources.version,
70
+ files: sources.files.map(file => file.path),
71
+ materialize: async () => {
72
+ const directory = await mkdtemp(join(tmpdir(), 'flows-eval-snapshot-'));
73
+ const dispose = async () => {
74
+ await makeWritable(directory);
75
+ await rm(directory, { recursive: true, force: true });
76
+ };
77
+ try {
78
+ for (const file of sources.absolute) {
79
+ const target = join(directory, relative(root, file.path));
80
+ await mkdir(dirname(target), { recursive: true });
81
+ await writeFile(target, file.bytes, { mode: 0o444 });
82
+ }
83
+ for (const dir of modules) {
84
+ const link = join(directory, relative(root, dir));
85
+ await mkdir(dirname(link), { recursive: true });
86
+ await symlink(dir, link, 'dir');
87
+ }
88
+ await makeReadOnly(directory);
89
+ }
90
+ catch (error) {
91
+ await dispose();
92
+ throw error;
93
+ }
94
+ return { flow: { path: join(directory, relative(root, sources.entry)) }, dispose };
95
+ },
96
+ };
97
+ }
98
+ async function makeReadOnly(directory) {
99
+ for (const entry of await readdir(directory, { withFileTypes: true })) {
100
+ if (entry.isDirectory())
101
+ await makeReadOnly(join(directory, entry.name));
102
+ }
103
+ await chmod(directory, 0o555);
104
+ }
105
+ async function makeWritable(directory) {
106
+ try {
107
+ await chmod(directory, 0o755);
108
+ for (const entry of await readdir(directory, { withFileTypes: true })) {
109
+ if (entry.isDirectory())
110
+ await makeWritable(join(directory, entry.name));
111
+ }
112
+ }
113
+ catch { /* already gone */ }
114
+ }
115
+ export function deepFreeze(value) {
116
+ if (value !== null && typeof value === 'object' && !Object.isFrozen(value)) {
117
+ Object.freeze(value);
118
+ for (const nested of Object.values(value))
119
+ deepFreeze(nested);
120
+ }
121
+ return value;
122
+ }
123
+ async function collectSources(path) {
124
+ let entry;
125
+ try {
126
+ entry = await realpath(path);
127
+ }
128
+ catch {
129
+ throw new FlowEvalError('unreadable_flow', `Flow "${path}" is not readable.`);
130
+ }
131
+ const root = dirname(entry);
132
+ const contents = new Map();
133
+ const missing = new Set();
134
+ // One cap over everything sealed — sources, manifests, extension payloads —
135
+ // so no category can grow a version past it.
136
+ const add = async (file) => {
137
+ const known = contents.get(file);
138
+ if (known !== undefined)
139
+ return known;
140
+ if (contents.size >= MAX_FLOW_EVAL_SOURCES) {
141
+ throw new FlowEvalError('unreadable_flow', `Flow "${path}" reaches more than ${MAX_FLOW_EVAL_SOURCES} local files.`);
142
+ }
143
+ let bytes;
144
+ try {
145
+ bytes = await readFile(file);
146
+ }
147
+ catch {
148
+ throw new FlowEvalError('unreadable_flow', `Flow source "${file}" is not readable.`);
149
+ }
150
+ contents.set(file, bytes);
151
+ return bytes;
152
+ };
153
+ const pending = [entry];
154
+ while (pending.length > 0) {
155
+ const file = pending.pop();
156
+ if (contents.has(file))
157
+ continue;
158
+ const bytes = await add(file);
159
+ // The package scope that decides how this file loads (`"type"`), per file:
160
+ // a nested package.json can differ from the entry's.
161
+ const scope = nearestFile(dirname(file), 'package.json');
162
+ if (scope !== undefined)
163
+ await add(scope);
164
+ if (!/\.(?:[mc]?[jt]s)$/u.test(file))
165
+ continue;
166
+ for (const specifier of localSpecifiers(bytes.toString('utf8'))) {
167
+ const targets = resolveLocal(dirname(file), specifier);
168
+ if (targets.length === 0)
169
+ missing.add(`${relative(root, dirname(file)) || '.'}:${specifier}`);
170
+ for (const target of targets)
171
+ if (!contents.has(target))
172
+ pending.push(target);
173
+ }
174
+ }
175
+ // The nearest of each: package.json decides module semantics, flows.json and
176
+ // its lock the extensions, and a package lockfile pins node_modules. Each is
177
+ // found by walking up on its own, so a lockfile beside package.json (not
178
+ // beside flows.json) still pins the version.
179
+ for (const name of PROJECT_FILES) {
180
+ const file = nearestFile(root, name);
181
+ if (file !== undefined)
182
+ await add(file);
183
+ }
184
+ // Locked flow extensions load from the project's content-addressed store,
185
+ // so their payloads are part of what runs: hash and seal them too.
186
+ const lockPath = nearestFile(root, 'flows.lock.json');
187
+ if (lockPath !== undefined) {
188
+ let lock;
189
+ try {
190
+ lock = parsePluginLock(JSON.parse(contents.get(lockPath).toString('utf8')));
191
+ }
192
+ catch (error) {
193
+ throw new FlowEvalError('unreadable_flow', `flows.lock.json is not a valid plugin lock: ${error instanceof Error ? error.message : String(error)}`);
194
+ }
195
+ for (const entry of lock.plugins) {
196
+ const store = pluginStoreDirectory(dirname(lockPath), entry.name, entry.digest);
197
+ if (!existsSync(store)) {
198
+ throw new FlowEvalError('unreadable_flow', `Locked extension ${entry.name} is not materialized at ${store}; run \`flows plugin verify\`.`);
199
+ }
200
+ for (const file of await listFiles(store))
201
+ await add(file);
202
+ }
203
+ }
204
+ const absolute = [...contents.entries()].map(([file, bytes]) => ({ path: file, bytes }));
205
+ const files = absolute
206
+ .map(file => ({ path: relative(root, file.path) || basename(file.path), sha256: sha256(file.bytes) }))
207
+ .sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
208
+ // An unresolved import is part of the identity too: creating that file later changes what runs.
209
+ const manifest = { entry: basename(entry), files, missing: [...missing].sort() };
210
+ return { entry, version: `sha256:${sha256(canonicalize(manifest))}`, files, absolute };
211
+ }
212
+ async function listFiles(directory) {
213
+ const files = [];
214
+ for (const entry of await readdir(directory, { withFileTypes: true })) {
215
+ const path = join(directory, entry.name);
216
+ if (entry.isDirectory())
217
+ files.push(...await listFiles(path));
218
+ else if (entry.isFile())
219
+ files.push(path);
220
+ }
221
+ return files;
222
+ }
223
+ function commonDirectory(paths) {
224
+ let common = dirname(paths[0]);
225
+ for (const path of paths) {
226
+ while (common !== dirname(common) && path !== common && !path.startsWith(common + sep))
227
+ common = dirname(common);
228
+ }
229
+ return common;
230
+ }
231
+ function nearestFile(start, name) {
232
+ for (let directory = start;; directory = dirname(directory)) {
233
+ const candidate = join(directory, name);
234
+ if (existsSync(candidate))
235
+ return candidate;
236
+ if (dirname(directory) === directory)
237
+ return undefined;
238
+ }
239
+ }
240
+ function ancestorNodeModules(start) {
241
+ const found = [];
242
+ for (let directory = start;; directory = dirname(directory)) {
243
+ const candidate = join(directory, 'node_modules');
244
+ try {
245
+ if (statSync(candidate).isDirectory())
246
+ found.push(candidate);
247
+ }
248
+ catch { /* none here */ }
249
+ if (dirname(directory) === directory)
250
+ return found;
251
+ }
252
+ }
253
+ /**
254
+ * Relative module specifiers and relative `.flow.ts` string literals (the
255
+ * `use:` header) in a source file. A lexical scan, deliberately: computing a
256
+ * version must never execute the flow.
257
+ */
258
+ export function localSpecifiers(source) {
259
+ const found = new Set();
260
+ const patterns = [
261
+ /\b(?:import|export)\s+(?:type\s+)?[^'"`;]*?\bfrom\s*['"](\.{1,2}\/[^'"]+)['"]/gu,
262
+ /\bimport\s*['"](\.{1,2}\/[^'"]+)['"]/gu,
263
+ /\b(?:import|require)\s*\(\s*['"](\.{1,2}\/[^'"]+)['"]\s*\)/gu,
264
+ /['"](\.{1,2}\/[^'"\s]+\.flow\.ts)['"]/gu,
265
+ ];
266
+ for (const pattern of patterns)
267
+ for (const match of source.matchAll(pattern))
268
+ found.add(match[1]);
269
+ return [...found];
270
+ }
271
+ /**
272
+ * The files a relative specifier can load. Where a TypeScript sibling and a
273
+ * JavaScript file both match (`./x.js` beside `./x.ts`), both are returned:
274
+ * which one a loader picks is the loader's business, and the version must not
275
+ * hash one while the run executes the other.
276
+ */
277
+ function resolveLocal(from, specifier) {
278
+ const base = resolve(from, specifier.replace(/[?#].*$/u, ''));
279
+ const isFile = (candidate) => {
280
+ try {
281
+ return statSync(candidate).isFile();
282
+ }
283
+ catch {
284
+ return false;
285
+ }
286
+ };
287
+ // TypeScript's NodeNext convention: import './x.js' names ./x.ts.
288
+ const swapped = base.replace(/\.([mc]?)js$/u, '.$1ts');
289
+ const direct = [...new Set([swapped, base])].filter(isFile);
290
+ if (direct.length > 0)
291
+ return direct;
292
+ for (const candidate of [
293
+ ...SOURCE_EXTENSIONS.map(extension => base + extension),
294
+ ...SOURCE_EXTENSIONS.map(extension => join(base, `index${extension}`)),
295
+ ])
296
+ if (isFile(candidate))
297
+ return [candidate];
298
+ return [];
299
+ }
300
+ function sha256(data) {
301
+ return createHash('sha256').update(data).digest('hex');
302
+ }
303
+ //# sourceMappingURL=flow-eval-version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-eval-version.js","sourceRoot":"","sources":["../src/flow-eval-version.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import { type FlowEvalExecutor, type FlowEvalReport, type FlowEvalScorer } from './flow-eval-report.js';
2
+ import { type FlowEvalSuite } from './flow-eval-suite.js';
3
+ import { type FlowEvalTarget } from './flow-eval-version.js';
4
+ export { FlowEvalError, type FlowEvalErrorCode } from './flow-eval-error.js';
5
+ export { parseFlowEvalBaseline, type FlowEvalBaseline } from './flow-eval-gate.js';
6
+ export * from './flow-eval-report.js';
7
+ export { MAX_FLOW_EVAL_CASES, flowEvalSuiteSha256, loadFlowEvalSuite, parseFlowEvalSuite, type FlowEvalCase, type FlowEvalExpectation, type FlowEvalSuite, type FlowEvalThresholds, } from './flow-eval-suite.js';
8
+ export { MAX_FLOW_EVAL_SOURCES, flowEvalSources, flowEvalVersion, sealFlowEvalSnapshot, type FlowEvalSnapshot, type FlowEvalTarget, type FlowEvalVersion, } from './flow-eval-version.js';
9
+ export interface EvaluateFlowOptions {
10
+ flow: FlowEvalTarget;
11
+ suite: FlowEvalSuite;
12
+ executor: FlowEvalExecutor;
13
+ /** Recorded in the report; defaults to `custom`. */
14
+ executorName?: string;
15
+ scorers?: FlowEvalScorer[];
16
+ /** Cases executed at once. Defaults to 1, which keeps runs from contending. */
17
+ concurrency?: number;
18
+ /** Refuse unless the flow version is exactly this (`sha256:<hex>`). */
19
+ expectVersion?: string;
20
+ /** Refuse unless the suite hashes to exactly this (`sha256:<hex>`). */
21
+ expectSuiteSha256?: string;
22
+ /**
23
+ * A prior report on the same suite (parsed JSON is fine; it is validated
24
+ * before any case runs). Any case that passed there and does not pass here
25
+ * is a regression, and a regression fails the gate.
26
+ */
27
+ baseline?: unknown;
28
+ signal?: AbortSignal;
29
+ /** Clock injection for tests. */
30
+ now?: () => number;
31
+ }
32
+ /**
33
+ * Re-execute `flow` once per suite case and score the results.
34
+ *
35
+ * Never throws for a case that fails or errors: those are verdicts, recorded
36
+ * in the report. Throws `FlowEvalError` only when the evaluation itself is
37
+ * invalid (bad suite, baseline or options, or a pinned version/suite that does
38
+ * not match), and rethrows an abort.
39
+ */
40
+ export declare function evaluateFlow(options: EvaluateFlowOptions): Promise<FlowEvalReport>;
41
+ //# sourceMappingURL=flow-eval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-eval.d.ts","sourceRoot":"","sources":["../src/flow-eval.ts"],"names":[],"mappings":"AAsBA,OAAO,EAEoB,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAoB,KAAK,cAAc,EAC3G,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAA8D,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACtH,OAAO,EAA6D,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExH,OAAO,EAAE,aAAa,EAAE,KAAK,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC7E,OAAO,EAAE,qBAAqB,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACnF,cAAc,uBAAuB,CAAC;AACtC,OAAO,EACL,mBAAmB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,kBAAkB,EAC/E,KAAK,YAAY,EAAE,KAAK,mBAAmB,EAAE,KAAK,aAAa,EAAE,KAAK,kBAAkB,GACzF,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,qBAAqB,EAAE,eAAe,EAAE,eAAe,EAAE,oBAAoB,EAC7E,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,KAAK,eAAe,GACjE,MAAM,wBAAwB,CAAC;AAEhC,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC;IAC3B,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uEAAuE;IACvE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,iCAAiC;IACjC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,cAAc,CAAC,CAkExF"}