@desplega.ai/agent-swarm 1.158.0 → 1.160.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 (378) hide show
  1. package/README.md +1 -1
  2. package/dist/{acp-adapter-xaq4n6pc.js → acp-adapter-2mjwcsfh.js} +124 -27
  3. package/dist/{actions-p9hz5yat.js → actions-e43rxskr.js} +35 -30
  4. package/dist/{anthropic-messages-51pz26qe.js → anthropic-messages-5qx80j9k.js} +106 -16
  5. package/dist/{app-g26wdcz6.js → app-mc7xfagn.js} +12 -10
  6. package/dist/{assistant-wydfqkb3.js → assistant-sedkzv3b.js} +42 -31
  7. package/dist/{azure-openai-responses-8gksqtmz.js → azure-openai-responses-nfb21z9a.js} +13 -14
  8. package/dist/{boot-reembed-se8zmdcp.js → boot-reembed-cqz9swn5.js} +13 -12
  9. package/dist/{boot-reembed-g5ckg9yb.js → boot-reembed-m3656j2n.js} +14 -13
  10. package/dist/{boot-scrub-logs-wfxqan61.js → boot-scrub-logs-xbxf5d7w.js} +11 -9
  11. package/dist/boot-seeds-gsetbs5y.js +28 -0
  12. package/dist/{claude-adapter-tv2x4f36.js → claude-adapter-dc6289mc.js} +28 -23
  13. package/dist/{claude-managed-adapter-41b2s7fd.js → claude-managed-adapter-naaw51me.js} +4 -3
  14. package/dist/{claude-managed-setup-60g8aazx.js → claude-managed-setup-eacvchx0.js} +12 -3
  15. package/dist/claude-sdk-session-bqp2xvym.js +29722 -0
  16. package/dist/{cli-987hg0aa.js → cli-0jwe9034.js} +2 -2
  17. package/dist/{cli-vj6h9kc2.js → cli-0m7wct0d.js} +59 -1
  18. package/dist/{cli-c07r9a2m.js → cli-0q3avq3s.js} +12 -11
  19. package/dist/{cli-19jenss3.js → cli-0wgxmwf6.js} +31 -10
  20. package/dist/cli-0x01kwrd.js +491 -0
  21. package/dist/cli-0xqde53b.js +176 -0
  22. package/dist/cli-10nhj6xq.js +8355 -0
  23. package/dist/{cli-tt9k8r35.js → cli-12tszpk9.js} +479 -910
  24. package/dist/{cli-5b6b62tz.js → cli-13hw4z91.js} +1 -1
  25. package/dist/{cli-cqt19wg6.js → cli-1a2j50m0.js} +11 -2
  26. package/dist/{cli-xberxa1r.js → cli-25fcq4b4.js} +2 -2
  27. package/dist/{cli-npssxgaz.js → cli-2pdaysab.js} +52 -2
  28. package/dist/cli-3qhyh31j.js +166 -0
  29. package/dist/cli-447dt1h3.js +3828 -0
  30. package/dist/cli-4derpgyk.js +115 -0
  31. package/dist/{cli-00w2c66p.js → cli-523679eh.js} +13 -2
  32. package/dist/{cli-y95wp3tg.js → cli-58e8yr0d.js} +1 -1
  33. package/dist/{cli-24k806sc.js → cli-5nbmpy8w.js} +3 -3
  34. package/dist/{cli-53sz8gkz.js → cli-6cs6wzxt.js} +1 -1
  35. package/dist/cli-741yb0xx.js +1027 -0
  36. package/dist/cli-74h9hscv.js +69 -0
  37. package/dist/cli-7cxw8b60.js +14910 -0
  38. package/dist/{cli-xhaeg2nc.js → cli-7e398j1h.js} +1 -1
  39. package/dist/cli-7kyk9jr3.js +22 -0
  40. package/dist/cli-89s4ngw3.js +183 -0
  41. package/dist/{cli-9b13ggd1.js → cli-89v6kyq7.js} +1 -0
  42. package/dist/{cli-ftfvggzx.js → cli-9hsgwz4w.js} +1045 -581
  43. package/dist/{cli-rqz8qbw7.js → cli-a8dvhzrt.js} +59 -20
  44. package/dist/{cli-j57qkrpq.js → cli-azhgzetg.js} +395 -56
  45. package/dist/cli-br0qdrnp.js +2150 -0
  46. package/dist/{cli-rj19hc34.js → cli-btfv8y88.js} +1 -1
  47. package/dist/{cli-8qmme6vd.js → cli-c8a36vcc.js} +2 -2
  48. package/dist/cli-cpvsaqsw.js +333 -0
  49. package/dist/cli-d5czme6m.js +17805 -0
  50. package/dist/{cli-h38x0qhg.js → cli-et8m9xsv.js} +4 -3
  51. package/dist/{cli-x24pshtq.js → cli-evvtk35y.js} +6 -6
  52. package/dist/{cli-7s3syk22.js → cli-f8gy6r2r.js} +5 -5
  53. package/dist/{cli-zt1227k1.js → cli-fkqhbg8g.js} +5 -3
  54. package/dist/{cli-9httdpyq.js → cli-g2whhdrf.js} +1 -1
  55. package/dist/cli-gt4hxb8p.js +99 -0
  56. package/dist/{cli-s8eet254.js → cli-jajnsm8q.js} +37184 -53838
  57. package/dist/{cli-7gtvvpbh.js → cli-jayjpjmb.js} +21 -12
  58. package/dist/{cli-68w09sjw.js → cli-jyk0ynw2.js} +27 -89
  59. package/dist/{cli-aehm1rbq.js → cli-jz4w45qt.js} +1152 -61
  60. package/dist/cli-kmcpfwn2.js +333856 -0
  61. package/dist/{cli-4198qc9v.js → cli-ktmyrtpn.js} +19 -3
  62. package/dist/{cli-j55n64b6.js → cli-mfe5btp9.js} +505 -189
  63. package/dist/{cli-q67y4wzm.js → cli-phsaj4xq.js} +24 -2
  64. package/dist/{cli-1hkrch3k.js → cli-pm1rst0h.js} +46 -7
  65. package/dist/{cli-pw9rj5t9.js → cli-pqetb83f.js} +1 -176
  66. package/dist/{cli-ggm92wcn.js → cli-ptr8h7kp.js} +20 -1
  67. package/dist/{cli-s8s499xy.js → cli-qbksc292.js} +3 -2
  68. package/dist/{cli-47m6dkd3.js → cli-qydf22qq.js} +597 -346
  69. package/dist/{cli-3gmcwfyx.js → cli-r1mxd1xh.js} +13 -6
  70. package/dist/cli-rb9m6rpe.js +4980 -0
  71. package/dist/cli-rykfmgwg.js +102 -0
  72. package/dist/{cli-5d10vd2m.js → cli-shkxm1vn.js} +6 -5
  73. package/dist/{cli-eetrvv91.js → cli-t3p77qk1.js} +1 -1
  74. package/dist/cli-tfky2838.js +756 -0
  75. package/dist/{cli-g8djp6qe.js → cli-tmqt7dpj.js} +40 -0
  76. package/dist/{cli-fgqxwrpv.js → cli-tpq83z89.js} +1631 -127
  77. package/dist/cli-trc24wk2.js +143 -0
  78. package/dist/{cli-aky8tctm.js → cli-tzx2ke1v.js} +3 -3
  79. package/dist/cli-v7fn5gms.js +1425 -0
  80. package/dist/{cli-wscdvcqz.js → cli-vctdqs5h.js} +1 -1
  81. package/dist/{cli-cw9zck8j.js → cli-xjcywfsf.js} +8 -4
  82. package/dist/{cli-k0g1sjzm.js → cli-ybgv4kw2.js} +18 -11
  83. package/dist/{cli-rjehvrts.js → cli-ydmcgve1.js} +8 -8
  84. package/dist/{cli-vhjwh6cz.js → cli-ygwm91nt.js} +1 -1
  85. package/dist/{cli-mcnhgnn1.js → cli-ykk5jaax.js} +184 -26
  86. package/dist/{cli-de1396j2.js → cli-ywybs5as.js} +7 -1
  87. package/dist/cli-zpep9q5e.js +491 -0
  88. package/dist/cli.js +41 -32
  89. package/dist/cloudflare-workers-ai-system-one-k6fbxw9d.js +46 -0
  90. package/dist/{codex-adapter-cnm8wk11.js → codex-adapter-nmxcatww.js} +26 -17
  91. package/dist/{codex-hook-9hptmdhj.js → codex-hook-20me6byw.js} +2 -2
  92. package/dist/{codex-login-x3jk4etn.js → codex-login-w6fz4xbz.js} +50 -5
  93. package/dist/{codex-session-runner-gfg547zj.js → codex-session-runner-90aa80ev.js} +24 -17
  94. package/dist/{commands-e3bn0p75.js → commands-8wcq1kn7.js} +11 -9
  95. package/dist/{db-03v9kzr2.js → db-j40kc4se.js} +25 -11
  96. package/dist/{devin-adapter-8vgkwh29.js → devin-adapter-dpsv6hd9.js} +1 -1
  97. package/dist/{dispatcher-nrmg8yht.js → dispatcher-4zqy768d.js} +34 -29
  98. package/dist/{dsh-adapter-k03nfqa6.js → dsh-adapter-mpnzgztj.js} +3 -3
  99. package/dist/{e2b-93x1k0j5.js → e2b-ez07znam.js} +4 -3
  100. package/dist/execute-6e7qeyk4.js +1017 -0
  101. package/dist/{google-generative-ai-bxmv50nc.js → google-generative-ai-k6n5nbpp.js} +6 -5
  102. package/dist/{google-vertex-809af514.js → google-vertex-44xxtcvp.js} +6 -5
  103. package/dist/{handlers-aqcedbyb.js → handlers-kjdce1w5.js} +37 -32
  104. package/dist/{hook-ybvmrmhq.js → hook-czx13n12.js} +19 -15
  105. package/dist/{hook-7vkskkre.js → hook-r2t4bqfg.js} +18 -14
  106. package/dist/{http-2eqa8t24.js → http-3bbb19be.js} +900 -145
  107. package/dist/{index-f6cryxwe.js → index-4a5njnm1.js} +2 -59
  108. package/dist/{index-x71bvq0p.js → index-668me3f0.js} +35 -30
  109. package/dist/{index-c6zsv1bd.js → index-7aj368tw.js} +13 -12
  110. package/dist/{index-1yks3qcr.js → index-fg0dsp6c.js} +34 -29
  111. package/dist/{index-chgdkq36.js → index-kkv84jq9.js} +34 -29
  112. package/dist/{index-a3vn96n8.js → index-zg7vp46x.js} +198 -54
  113. package/dist/{keepalive-vtkf5n99.js → keepalive-yra8dy57.js} +13 -11
  114. package/dist/{lead-h3sp357x.js → lead-va0pad2c.js} +54 -49
  115. package/dist/llama-cpp-classify-tgj35k8d.js +335 -0
  116. package/dist/{maintenance-jzeqtk3q.js → maintenance-hqewtmyg.js} +14 -13
  117. package/dist/{mistral-conversations-zx0kn554.js → mistral-conversations-pc3ntnxt.js} +14 -17
  118. package/dist/{oauth-refresh-sweep-qp3dzmdp.js → oauth-refresh-sweep-7rdt1m9n.js} +12 -10
  119. package/dist/{onboard-tmsp0qbz.js → onboard-j6ms6d0x.js} +6 -5
  120. package/dist/{openai-codex-responses-4vjqzvjp.js → openai-codex-responses-bbancrr0.js} +21 -8
  121. package/dist/{openai-completions-9hjrqbw8.js → openai-completions-jpaj5g2b.js} +9 -12
  122. package/dist/{openai-responses-7b1pn0xt.js → openai-responses-200k1wx4.js} +23 -18
  123. package/dist/{opencode-adapter-x6x2da1z.js → opencode-adapter-89rabkw2.js} +8 -7
  124. package/dist/{openrouter-images-9f9ek4rw.js → openrouter-images-8yx3487g.js} +5 -7
  125. package/dist/{otel-impl-9mz73q65.js → otel-impl-a792rjz0.js} +1 -1
  126. package/dist/{pi-messages-txpjj39q.js → pi-messages-vxdt8v7j.js} +2 -1
  127. package/dist/{pi-mono-adapter-m6dvv0dz.js → pi-mono-adapter-g7qzvr3v.js} +295 -70
  128. package/dist/pricing-refresh-wx0tp7cb.js +39 -0
  129. package/dist/quickjs-r1pq2107.wasm +0 -0
  130. package/dist/{rbac-roles-c9wqz83x.js → rbac-roles-8tzawacv.js} +12 -10
  131. package/dist/{render-v2-gryrh9h8.js → render-v2-mm7zswb8.js} +12 -10
  132. package/dist/runtime-zyssgse0.js +24 -0
  133. package/dist/{setup-q9720bt6.js → setup-8y70ys6t.js} +6 -5
  134. package/dist/typesafe-system-one-2ef30pec.js +27 -0
  135. package/dist/{virtual-modules-3htpgn8x.js → virtual-modules-6nmk7h3n.js} +22 -13
  136. package/dist/{work-objects-b76x7deb.js → work-objects-fg6xkb0n.js} +37 -32
  137. package/dist/{worker-6vrxbv41.js → worker-wmwhxsph.js} +54 -49
  138. package/openapi.json +1314 -91
  139. package/package.json +12 -11
  140. package/src/be/db/agents.ts +20 -0
  141. package/src/be/db/api-keys.ts +70 -0
  142. package/src/be/db/tasks/human-free.ts +442 -0
  143. package/src/be/db/tasks/read.ts +56 -1
  144. package/src/be/db/tasks/write.ts +107 -11
  145. package/src/be/db.ts +274 -188
  146. package/src/be/harness-model-support.ts +182 -0
  147. package/src/be/human-free-drain.ts +67 -0
  148. package/src/be/memory/providers/sqlite-store.ts +51 -15
  149. package/src/be/migrations/182_task_human_free_flag.sql +63 -0
  150. package/src/be/migrations/183_human_free_reclassify_queue.sql +25 -0
  151. package/src/be/migrations/184_model_catalog.sql +120 -0
  152. package/src/be/migrations/185_api_key_auth_failures.sql +6 -0
  153. package/src/be/migrations/186_api_key_seat_mismatch.sql +8 -0
  154. package/src/be/model-catalog-store.ts +644 -0
  155. package/src/be/model-tier-keys.ts +46 -0
  156. package/src/be/model-tier-resolution.ts +534 -0
  157. package/src/be/model-validation.ts +188 -0
  158. package/src/be/models-catalog.ts +61 -7
  159. package/src/be/modelsdev-cache.json +82 -0
  160. package/src/be/modelsdev-cache.ts +2 -0
  161. package/src/be/pricing-refresh.ts +154 -12
  162. package/src/be/scripts/typecheck.ts +15 -0
  163. package/src/be/seed/runner.ts +18 -12
  164. package/src/be/seed/types.ts +1 -0
  165. package/src/be/seed-scripts/catalog/task-failure-audit.ts +61 -9
  166. package/src/be/swarm-config-guard.ts +8 -0
  167. package/src/cli.tsx +10 -0
  168. package/src/commands/claude-managed-setup.ts +3 -1
  169. package/src/commands/codex-login.ts +67 -0
  170. package/src/commands/credential-outcome-report.ts +191 -0
  171. package/src/commands/rate-limit-outcome.ts +34 -4
  172. package/src/commands/runner.ts +357 -186
  173. package/src/commands/seat-mismatch-report.ts +46 -0
  174. package/src/extensions/apply-task-create.ts +27 -1
  175. package/src/extensions/contract-types.generated.ts +1 -1
  176. package/src/heartbeat/heartbeat.ts +79 -17
  177. package/src/heartbeat/templates.ts +2 -2
  178. package/src/http/agents.ts +62 -1
  179. package/src/http/api-keys.ts +140 -2
  180. package/src/http/codex-oauth-keep-warm.ts +3 -5
  181. package/src/http/index.ts +8 -0
  182. package/src/http/memory.ts +12 -5
  183. package/src/http/models-catalog.ts +357 -8
  184. package/src/http/poll.ts +54 -3
  185. package/src/http/schedules.ts +51 -6
  186. package/src/http/script-runs.ts +12 -0
  187. package/src/http/session-data.ts +2 -5
  188. package/src/http/stats.ts +6 -8
  189. package/src/http/status.ts +15 -1
  190. package/src/http/tasks.ts +90 -7
  191. package/src/http/usage-cache.ts +56 -15
  192. package/src/http/workflows.ts +46 -8
  193. package/src/mcp-client/http-client.ts +5 -0
  194. package/src/memory/recall-query.ts +74 -0
  195. package/src/prompts/base-prompt.ts +15 -4
  196. package/src/prompts/session-templates.ts +23 -1
  197. package/src/providers/acp-adapter.ts +1 -0
  198. package/src/providers/claude-adapter.ts +14 -5
  199. package/src/providers/claude-managed-adapter.ts +1 -0
  200. package/src/providers/claude-managed-models.ts +47 -161
  201. package/src/providers/claude-sdk-session.ts +3 -1
  202. package/src/providers/codex-adapter.ts +14 -14
  203. package/src/providers/codex-models.ts +65 -198
  204. package/src/providers/devin-adapter.ts +1 -0
  205. package/src/providers/dsh-adapter.ts +2 -1
  206. package/src/providers/harness-version.ts +83 -7
  207. package/src/providers/opencode-adapter.ts +53 -1
  208. package/src/providers/pi-binary-root/src/extensions/codemode/worker.ts +11 -0
  209. package/src/providers/pi-codemode-runtime.ts +17 -0
  210. package/src/providers/pi-mono-adapter.ts +361 -83
  211. package/src/providers/pi-mono-extension.ts +16 -1
  212. package/src/providers/reasoning-effort.ts +44 -140
  213. package/src/providers/types.ts +8 -0
  214. package/src/rbac/legacy-policy.ts +43 -0
  215. package/src/rbac/permissions.ts +15 -0
  216. package/src/scripts-runtime/sdk-allowlist.ts +4 -0
  217. package/src/scripts-runtime/types/stdlib.d.ts +15 -0
  218. package/src/scripts-runtime/types/swarm-extension.d.ts +3 -0
  219. package/src/scripts-runtime/types/swarm-sdk.d.ts +15 -0
  220. package/src/server.ts +6 -0
  221. package/src/slack/assistant.ts +13 -0
  222. package/src/slack/message-text.ts +56 -2
  223. package/src/slack/render-v2.ts +87 -37
  224. package/src/slack/session-status.ts +541 -0
  225. package/src/slack/thread-buffer.ts +10 -2
  226. package/src/tasks/sibling-awareness.ts +3 -2
  227. package/src/telemetry.ts +5 -4
  228. package/src/templates.d.ts +6 -0
  229. package/src/tests/agents-list-model-display.test.ts +4 -6
  230. package/src/tests/api-key-auth-failure-route.test.ts +142 -0
  231. package/src/tests/api-key-tracking.test.ts +368 -1
  232. package/src/tests/base-prompt.test.ts +43 -2
  233. package/src/tests/claude-adapter.test.ts +68 -0
  234. package/src/tests/claude-managed-adapter.test.ts +12 -18
  235. package/src/tests/codex-adapter.test.ts +2 -1
  236. package/src/tests/codex-auth-failure.test.ts +52 -0
  237. package/src/tests/codex-gpt6-release.test.ts +66 -5
  238. package/src/tests/codex-login.test.ts +116 -0
  239. package/src/tests/context-window.test.ts +7 -5
  240. package/src/tests/credential-exhaustion-policy.test.ts +118 -3
  241. package/src/tests/credential-outcome-report.test.ts +171 -0
  242. package/src/tests/credential-status-api.test.ts +103 -2
  243. package/src/tests/db-extraction-contract.test.ts +1 -0
  244. package/src/tests/db-task-read-contract.test.ts +10 -1
  245. package/src/tests/db-task-write-contract.test.ts +535 -2
  246. package/src/tests/docs-index-footprint.test.js +3 -3
  247. package/src/tests/dokploy-deploy.test.ts +315 -0
  248. package/src/tests/dsh-adapter.test.ts +1 -1
  249. package/src/tests/explicit-model-validation.test.ts +583 -0
  250. package/src/tests/extensions-pre-task.test.ts +73 -0
  251. package/src/tests/fetch-resolved-env.test.ts +46 -0
  252. package/src/tests/hang-watchdog-worker.ts +47 -0
  253. package/src/tests/hang-watchdog.test.ts +45 -0
  254. package/src/tests/hang-watchdog.ts +30 -0
  255. package/src/tests/harness-model-guard.test.ts +123 -0
  256. package/src/tests/harness-model-support.test.ts +374 -0
  257. package/src/tests/harness-version.test.ts +70 -3
  258. package/src/tests/heartbeat-checklist-config.test.ts +71 -0
  259. package/src/tests/heartbeat-checklist.test.ts +4 -2
  260. package/src/tests/heartbeat-orphan-resume.test.ts +48 -0
  261. package/src/tests/http-task-write-ownership.test.ts +172 -0
  262. package/src/tests/human-free-flag.test.ts +279 -0
  263. package/src/tests/human-free-oracle.ts +57 -0
  264. package/src/tests/human-free-reclassify.test.ts +669 -0
  265. package/src/tests/memory-fts-populate.test.ts +139 -0
  266. package/src/tests/memory-http-recall-gating.test.ts +125 -1
  267. package/src/tests/migration-046-budgets.test.ts +3 -3
  268. package/src/tests/model-catalog-migration.test.ts +134 -0
  269. package/src/tests/model-catalog-table.test.ts +249 -0
  270. package/src/tests/model-catalog-write-access.test.ts +387 -0
  271. package/src/tests/model-rate-limit-windows.test.ts +19 -0
  272. package/src/tests/model-tier-resolution.test.ts +611 -0
  273. package/src/tests/models-catalog.test.ts +1 -1
  274. package/src/tests/multi-runtime-enabled-stats.test.ts +65 -1
  275. package/src/tests/opencode-adapter.test.ts +157 -2
  276. package/src/tests/package-publish.test.ts +137 -36
  277. package/src/tests/pi-codemode.test.ts +246 -0
  278. package/src/tests/pi-mono-adapter.test.ts +3 -0
  279. package/src/tests/pi-native-mcp.test.ts +193 -0
  280. package/src/tests/pi-tool-exposure.test.ts +374 -0
  281. package/src/tests/preload.ts +3 -0
  282. package/src/tests/pricing-routes.test.ts +2 -2
  283. package/src/tests/prompt-template-session.test.ts +5 -3
  284. package/src/tests/rate-limit-event.test.ts +65 -0
  285. package/src/tests/rate-limit-outcome.test.ts +90 -0
  286. package/src/tests/rbac-engine.test.ts +77 -3
  287. package/src/tests/reasoning-effort.test.ts +109 -0
  288. package/src/tests/refresh-modelsdev-carryforward.test.ts +5 -5
  289. package/src/tests/runner-key-completion-outcome.test.ts +112 -0
  290. package/src/tests/runner-key-outcome-late-reset.test.ts +224 -0
  291. package/src/tests/runner-registration-retry.test.ts +149 -0
  292. package/src/tests/runtime-model-catalog.test.ts +86 -0
  293. package/src/tests/script-connections.test.ts +9 -0
  294. package/src/tests/seat-mismatch-report.test.ts +85 -0
  295. package/src/tests/seed-scripts.test.ts +138 -0
  296. package/src/tests/seed.test.ts +25 -0
  297. package/src/tests/session-costs.test.ts +14 -11
  298. package/src/tests/slack-message-text.test.ts +101 -0
  299. package/src/tests/slack-render-v2.test.ts +96 -0
  300. package/src/tests/slack-session-status.test.ts +626 -0
  301. package/src/tests/slack-thread-buffer-context.test.ts +93 -0
  302. package/src/tests/status.test.ts +29 -0
  303. package/src/tests/steering-promotion.test.ts +51 -0
  304. package/src/tests/store-progress-ownership.test.ts +136 -0
  305. package/src/tests/subscription-plans.test.ts +28 -0
  306. package/src/tests/task-cascade-fail.test.ts +148 -2
  307. package/src/tests/task-citations.test.ts +3 -2
  308. package/src/tests/tool-annotations.test.ts +1 -1
  309. package/src/tests/usage-cache.test.ts +166 -0
  310. package/src/tests/workflow-agent-task.test.ts +30 -0
  311. package/src/tests/workflow-executors.test.ts +5 -2
  312. package/src/tests/workflow-system-one-decision-review.test.ts +1021 -0
  313. package/src/tests/workflow-system-one-decision-save-warnings.test.ts +365 -0
  314. package/src/tests/workflow-system-one-decision.test.ts +2063 -0
  315. package/src/tests/workflow-triggers-v2.test.ts +320 -0
  316. package/src/tools/model-catalog/index.ts +137 -0
  317. package/src/tools/schedules/create-schedule.ts +17 -2
  318. package/src/tools/schedules/patch-schedule.ts +31 -1
  319. package/src/tools/schedules/update-schedule.ts +31 -1
  320. package/src/tools/send-task.ts +18 -1
  321. package/src/tools/store-progress.ts +49 -4
  322. package/src/tools/task-action.ts +14 -1
  323. package/src/tools/tool-config.ts +3 -1
  324. package/src/tools/workflows/create-workflow.ts +17 -4
  325. package/src/tools/workflows/patch-workflow-node.ts +17 -7
  326. package/src/tools/workflows/patch-workflow.ts +9 -2
  327. package/src/tools/workflows/update-workflow.ts +17 -4
  328. package/src/types.ts +41 -1
  329. package/src/utils/codex-auth-failure.ts +34 -0
  330. package/src/utils/context-window.ts +47 -53
  331. package/src/utils/credentials.ts +72 -30
  332. package/src/utils/error-tracker.ts +80 -0
  333. package/src/utils/harness-cli-version.ts +115 -0
  334. package/src/utils/harness-model-error.ts +33 -0
  335. package/src/utils/model-rate-limit-windows.ts +12 -0
  336. package/src/utils/runtime-model-catalog.ts +152 -0
  337. package/src/utils/spawn-model-guard.ts +43 -0
  338. package/src/utils/subscription-plans.ts +22 -0
  339. package/src/workflows/approval-resolution.ts +39 -0
  340. package/src/workflows/definition.ts +7 -0
  341. package/src/workflows/engine.ts +69 -1
  342. package/src/workflows/executors/agent-task.ts +16 -6
  343. package/src/workflows/executors/base.ts +53 -0
  344. package/src/workflows/executors/human-in-the-loop.ts +8 -8
  345. package/src/workflows/executors/index.ts +1 -0
  346. package/src/workflows/executors/registry.ts +2 -0
  347. package/src/workflows/executors/system-one-decision.ts +1232 -0
  348. package/src/workflows/executors/system-one-providers.ts +301 -0
  349. package/src/workflows/executors/workflow-llm.ts +13 -1
  350. package/src/workflows/model-validation.ts +45 -0
  351. package/src/workflows/patch-definition.ts +5 -0
  352. package/src/workflows/readiness.ts +86 -0
  353. package/src/workflows/recovery.ts +12 -12
  354. package/src/workflows/resume.ts +23 -9
  355. package/src/workflows/triggers.ts +85 -0
  356. package/templates/schedules/daily-blocker-digest/content.md +4 -5
  357. package/templates/skills/agent-browser/SKILL.md +6 -5
  358. package/templates/skills/agent-browser/content.md +6 -5
  359. package/templates/skills/heartbeat-runbook/config.json +1 -1
  360. package/templates/skills/heartbeat-runbook/content.md +2 -2
  361. package/templates/skills/swarm-scripts/SKILL.md +1 -1
  362. package/templates/skills/swarm-scripts/content.md +1 -1
  363. package/templates/skills/workflow-iterate/content.md +82 -1
  364. package/templates/workflows/claude-code-changelog-watch/content.md +2 -0
  365. package/templates/workflows/pr-review-status-sweep/content.md +2 -0
  366. package/dist/boot-seeds-s3q01xj3.js +0 -26
  367. package/dist/claude-sdk-session-t442qz6f.js +0 -39108
  368. package/dist/cli-0xjkj1j7.js +0 -61
  369. package/dist/cli-20cj37vt.js +0 -335561
  370. package/dist/cli-2djtr51b.js +0 -48
  371. package/dist/cli-65hjmev5.js +0 -1141
  372. package/dist/cli-aw1jwp1r.js +0 -14075
  373. package/dist/cli-h967nb6r.js +0 -6603
  374. package/dist/cli-vapyk8sw.js +0 -20
  375. package/dist/cli-ws6rqycm.js +0 -247
  376. package/dist/pricing-refresh-v1cbr9te.js +0 -27
  377. package/src/providers/modelsdev-reasoning.json +0 -6453
  378. package/dist/{index-f24115ge.js → index-2wsdsnmm.js} +3 -3
@@ -9,9 +9,17 @@ import {
9
9
  import {
10
10
  getApiKey
11
11
  } from "./cli-f14fvzag.js";
12
+ import {
13
+ DEFAULT_MODEL,
14
+ resolveCredential
15
+ } from "./cli-12tszpk9.js";
16
+ import {
17
+ DEFAULT_OPENROUTER_BASE_URL,
18
+ getOpenRouterBaseUrl
19
+ } from "./cli-3dpj7atn.js";
12
20
  import {
13
21
  embedScript
14
- } from "./cli-987hg0aa.js";
22
+ } from "./cli-0jwe9034.js";
15
23
  import {
16
24
  calculatePKCECodeChallenge,
17
25
  ensureAuthorizationTokenOrThrow,
@@ -23,11 +31,17 @@ import {
23
31
  oauthAppRowToProviderConfig,
24
32
  updateAuthorizationTokens,
25
33
  upsertAuthorization
26
- } from "./cli-53sz8gkz.js";
34
+ } from "./cli-6cs6wzxt.js";
35
+ import {
36
+ getSlackApp
37
+ } from "./cli-azhgzetg.js";
27
38
  import {
28
39
  CredentialBroker,
29
40
  DEFAULT_CREDENTIAL_BINDINGS,
41
+ claimApprovalCancellationNotification,
42
+ completeApprovalCancellationNotificationClaim,
30
43
  computeContentHash,
44
+ createTaskExtended,
31
45
  decryptSecret,
32
46
  encryptSecret,
33
47
  getDb,
@@ -36,18 +50,30 @@ import {
36
50
  getLeadAgent,
37
51
  getMcpServerById,
38
52
  getResolvedConfig,
53
+ getTaskById,
39
54
  init_credential_broker,
40
55
  init_crypto,
41
56
  init_date_utils,
42
57
  init_db,
43
58
  normalizeDateRequired,
44
59
  placeholderForConfigKey,
60
+ releaseApprovalCancellationNotificationClaim,
45
61
  upsertSwarmConfig
46
- } from "./cli-47m6dkd3.js";
62
+ } from "./cli-qydf22qq.js";
47
63
  import {
64
+ TERMINAL_TASK_STATUSES,
48
65
  defaultAssetKey,
49
- init_key
50
- } from "./cli-4198qc9v.js";
66
+ init_key,
67
+ init_types
68
+ } from "./cli-ktmyrtpn.js";
69
+ import {
70
+ init_resolver,
71
+ resolveTemplate
72
+ } from "./cli-ptr8h7kp.js";
73
+ import {
74
+ getAppUrl,
75
+ init_constants
76
+ } from "./cli-dv6cdjs2.js";
51
77
  import {
52
78
  init_env_flag,
53
79
  isEnvFlagEnabled
@@ -351,8 +377,8 @@ var require_luxon = __commonJS(function(exports) {
351
377
  }
352
378
 
353
379
  class InvalidUnitError extends LuxonError {
354
- constructor(unit) {
355
- super(`Invalid unit ${unit}`);
380
+ constructor(unit2) {
381
+ super(`Invalid unit ${unit2}`);
356
382
  }
357
383
  }
358
384
 
@@ -981,16 +1007,16 @@ var require_luxon = __commonJS(function(exports) {
981
1007
  this.rtf = getCachedRTF(intl, opts);
982
1008
  }
983
1009
  }
984
- format(count, unit) {
1010
+ format(count, unit2) {
985
1011
  if (this.rtf) {
986
- return this.rtf.format(count, unit);
1012
+ return this.rtf.format(count, unit2);
987
1013
  } else {
988
- return formatRelativeTime(unit, count, this.opts.numeric, this.opts.style !== "long");
1014
+ return formatRelativeTime(unit2, count, this.opts.numeric, this.opts.style !== "long");
989
1015
  }
990
1016
  }
991
- formatToParts(count, unit) {
1017
+ formatToParts(count, unit2) {
992
1018
  if (this.rtf) {
993
- return this.rtf.formatToParts(count, unit);
1019
+ return this.rtf.formatToParts(count, unit2);
994
1020
  } else {
995
1021
  return [];
996
1022
  }
@@ -1459,8 +1485,8 @@ var require_luxon = __commonJS(function(exports) {
1459
1485
  }
1460
1486
  var nonLeapLadder = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
1461
1487
  var leapLadder = [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335];
1462
- function unitOutOfRange(unit, value) {
1463
- return new Invalid("unit out of range", `you specified ${value} (of type ${typeof value}) as a ${unit}, which is invalid`);
1488
+ function unitOutOfRange(unit2, value) {
1489
+ return new Invalid("unit out of range", `you specified ${value} (of type ${typeof value}) as a ${unit2}, which is invalid`);
1464
1490
  }
1465
1491
  function dayOfWeek(year, month, day) {
1466
1492
  const d = new Date(Date.UTC(year, month - 1, day));
@@ -1928,7 +1954,7 @@ var require_luxon = __commonJS(function(exports) {
1928
1954
  function eraForDateTime(dt, length) {
1929
1955
  return eras(length)[dt.year < 0 ? 0 : 1];
1930
1956
  }
1931
- function formatRelativeTime(unit, count, numeric = "always", narrow = false) {
1957
+ function formatRelativeTime(unit2, count, numeric = "always", narrow = false) {
1932
1958
  const units = {
1933
1959
  years: ["year", "yr."],
1934
1960
  quarters: ["quarter", "qtr."],
@@ -1939,19 +1965,19 @@ var require_luxon = __commonJS(function(exports) {
1939
1965
  minutes: ["minute", "min."],
1940
1966
  seconds: ["second", "sec."]
1941
1967
  };
1942
- const lastable = ["hours", "minutes", "seconds"].indexOf(unit) === -1;
1968
+ const lastable = ["hours", "minutes", "seconds"].indexOf(unit2) === -1;
1943
1969
  if (numeric === "auto" && lastable) {
1944
- const isDay = unit === "days";
1970
+ const isDay = unit2 === "days";
1945
1971
  switch (count) {
1946
1972
  case 1:
1947
- return isDay ? "tomorrow" : `next ${units[unit][0]}`;
1973
+ return isDay ? "tomorrow" : `next ${units[unit2][0]}`;
1948
1974
  case -1:
1949
- return isDay ? "yesterday" : `last ${units[unit][0]}`;
1975
+ return isDay ? "yesterday" : `last ${units[unit2][0]}`;
1950
1976
  case 0:
1951
- return isDay ? "today" : `this ${units[unit][0]}`;
1977
+ return isDay ? "today" : `this ${units[unit2][0]}`;
1952
1978
  }
1953
1979
  }
1954
- const isInPast = Object.is(count, -0) || count < 0, fmtValue = Math.abs(count), singular = fmtValue === 1, lilUnits = units[unit], fmtUnit = narrow ? singular ? lilUnits[1] : lilUnits[2] || lilUnits[1] : singular ? units[unit][0] : unit;
1980
+ const isInPast = Object.is(count, -0) || count < 0, fmtValue = Math.abs(count), singular = fmtValue === 1, lilUnits = units[unit2], fmtUnit = narrow ? singular ? lilUnits[1] : lilUnits[2] || lilUnits[1] : singular ? units[unit2][0] : unit2;
1955
1981
  return isInPast ? `${fmtValue} ${fmtUnit} ago` : `in ${fmtValue} ${fmtUnit}`;
1956
1982
  }
1957
1983
  function stringifyTokens(splits, tokenToString) {
@@ -2612,9 +2638,9 @@ var require_luxon = __commonJS(function(exports) {
2612
2638
  function durationToMillis(matrix, vals) {
2613
2639
  var _vals$milliseconds;
2614
2640
  let sum = (_vals$milliseconds = vals.milliseconds) != null ? _vals$milliseconds : 0;
2615
- for (const unit of reverseUnits.slice(1)) {
2616
- if (vals[unit]) {
2617
- sum += vals[unit] * matrix[unit]["milliseconds"];
2641
+ for (const unit2 of reverseUnits.slice(1)) {
2642
+ if (vals[unit2]) {
2643
+ sum += vals[unit2] * matrix[unit2]["milliseconds"];
2618
2644
  }
2619
2645
  }
2620
2646
  return sum;
@@ -2728,7 +2754,7 @@ var require_luxon = __commonJS(function(exports) {
2728
2754
  });
2729
2755
  }
2730
2756
  }
2731
- static normalizeUnit(unit) {
2757
+ static normalizeUnit(unit2) {
2732
2758
  const normalized = {
2733
2759
  year: "years",
2734
2760
  years: "years",
@@ -2748,9 +2774,9 @@ var require_luxon = __commonJS(function(exports) {
2748
2774
  seconds: "seconds",
2749
2775
  millisecond: "milliseconds",
2750
2776
  milliseconds: "milliseconds"
2751
- }[unit ? unit.toLowerCase() : unit];
2777
+ }[unit2 ? unit2.toLowerCase() : unit2];
2752
2778
  if (!normalized)
2753
- throw new InvalidUnitError(unit);
2779
+ throw new InvalidUnitError(unit2);
2754
2780
  return normalized;
2755
2781
  }
2756
2782
  static isDuration(o) {
@@ -2773,8 +2799,8 @@ var require_luxon = __commonJS(function(exports) {
2773
2799
  if (!this.isValid)
2774
2800
  return INVALID$2;
2775
2801
  const showZeros = opts.showZeros !== false;
2776
- const l2 = orderedUnits$1.map((unit) => {
2777
- const val = this.values[unit];
2802
+ const l2 = orderedUnits$1.map((unit2) => {
2803
+ const val = this.values[unit2];
2778
2804
  if (isUndefined(val) || val === 0 && !showZeros) {
2779
2805
  return null;
2780
2806
  }
@@ -2782,7 +2808,7 @@ var require_luxon = __commonJS(function(exports) {
2782
2808
  style: "unit",
2783
2809
  unitDisplay: "long",
2784
2810
  ...opts,
2785
- unit: unit.slice(0, -1)
2811
+ unit: unit2.slice(0, -1)
2786
2812
  }).format(val);
2787
2813
  }).filter((n2) => n2);
2788
2814
  return this.loc.listFormatter({
@@ -2892,8 +2918,8 @@ var require_luxon = __commonJS(function(exports) {
2892
2918
  values: result
2893
2919
  }, true);
2894
2920
  }
2895
- get(unit) {
2896
- return this[Duration.normalizeUnit(unit)];
2921
+ get(unit2) {
2922
+ return this[Duration.normalizeUnit(unit2)];
2897
2923
  }
2898
2924
  set(values) {
2899
2925
  if (!this.isValid)
@@ -2923,8 +2949,8 @@ var require_luxon = __commonJS(function(exports) {
2923
2949
  };
2924
2950
  return clone$1(this, opts);
2925
2951
  }
2926
- as(unit) {
2927
- return this.isValid ? this.shiftTo(unit).get(unit) : NaN;
2952
+ as(unit2) {
2953
+ return this.isValid ? this.shiftTo(unit2).get(unit2) : NaN;
2928
2954
  }
2929
2955
  normalize() {
2930
2956
  if (!this.isValid)
@@ -3168,13 +3194,13 @@ var require_luxon = __commonJS(function(exports) {
3168
3194
  get invalidExplanation() {
3169
3195
  return this.invalid ? this.invalid.explanation : null;
3170
3196
  }
3171
- length(unit = "milliseconds") {
3172
- return this.isValid ? this.toDuration(...[unit]).get(unit) : NaN;
3197
+ length(unit2 = "milliseconds") {
3198
+ return this.isValid ? this.toDuration(...[unit2]).get(unit2) : NaN;
3173
3199
  }
3174
- count(unit = "milliseconds", opts) {
3200
+ count(unit2 = "milliseconds", opts) {
3175
3201
  if (!this.isValid)
3176
3202
  return NaN;
3177
- const start = this.start.startOf(unit, opts);
3203
+ const start = this.start.startOf(unit2, opts);
3178
3204
  let end;
3179
3205
  if (opts != null && opts.useLocaleWeeks) {
3180
3206
  end = this.end.reconfigure({
@@ -3183,11 +3209,11 @@ var require_luxon = __commonJS(function(exports) {
3183
3209
  } else {
3184
3210
  end = this.end;
3185
3211
  }
3186
- end = end.startOf(unit, opts);
3187
- return Math.floor(end.diff(start, unit).get(unit)) + (end.valueOf() !== this.end.valueOf());
3212
+ end = end.startOf(unit2, opts);
3213
+ return Math.floor(end.diff(start, unit2).get(unit2)) + (end.valueOf() !== this.end.valueOf());
3188
3214
  }
3189
- hasSame(unit) {
3190
- return this.isValid ? this.isEmpty() || this.e.minus(1).hasSame(this.s, unit) : false;
3215
+ hasSame(unit2) {
3216
+ return this.isValid ? this.isEmpty() || this.e.minus(1).hasSame(this.s, unit2) : false;
3191
3217
  }
3192
3218
  isEmpty() {
3193
3219
  return this.s.valueOf() === this.e.valueOf();
@@ -3370,11 +3396,11 @@ var require_luxon = __commonJS(function(exports) {
3370
3396
  return INVALID$1;
3371
3397
  return `${this.s.toFormat(dateFormat)}${separator}${this.e.toFormat(dateFormat)}`;
3372
3398
  }
3373
- toDuration(unit, opts) {
3399
+ toDuration(unit2, opts) {
3374
3400
  if (!this.isValid) {
3375
3401
  return Duration.invalid(this.invalidReason);
3376
3402
  }
3377
- return this.e.diff(this.s, unit, opts);
3403
+ return this.e.diff(this.s, unit2, opts);
3378
3404
  }
3379
3405
  mapEndpoints(mapFn) {
3380
3406
  return Interval.fromDateTimes(mapFn(this.s), mapFn(this.e));
@@ -3475,17 +3501,17 @@ var require_luxon = __commonJS(function(exports) {
3475
3501
  const results = {};
3476
3502
  const earlier = cursor;
3477
3503
  let lowestOrder, highWater;
3478
- for (const [unit, differ] of differs) {
3479
- if (units.indexOf(unit) >= 0) {
3480
- lowestOrder = unit;
3481
- results[unit] = differ(cursor, later);
3504
+ for (const [unit2, differ] of differs) {
3505
+ if (units.indexOf(unit2) >= 0) {
3506
+ lowestOrder = unit2;
3507
+ results[unit2] = differ(cursor, later);
3482
3508
  highWater = earlier.plus(results);
3483
3509
  if (highWater > later) {
3484
- results[unit]--;
3510
+ results[unit2]--;
3485
3511
  cursor = earlier.plus(results);
3486
3512
  if (cursor > later) {
3487
3513
  highWater = cursor;
3488
- results[unit]--;
3514
+ results[unit2]--;
3489
3515
  cursor = earlier.plus(results);
3490
3516
  }
3491
3517
  } else {
@@ -3670,11 +3696,11 @@ var require_luxon = __commonJS(function(exports) {
3670
3696
  return literal2(t);
3671
3697
  }
3672
3698
  };
3673
- const unit = unitate(token) || {
3699
+ const unit2 = unitate(token) || {
3674
3700
  invalidReason: MISSING_FTP
3675
3701
  };
3676
- unit.token = token;
3677
- return unit;
3702
+ unit2.token = token;
3703
+ return unit2;
3678
3704
  }
3679
3705
  var partTypeStyleToTokenVal = {
3680
3706
  year: {
@@ -4152,7 +4178,7 @@ var require_luxon = __commonJS(function(exports) {
4152
4178
  var orderedUnits = ["year", "month", "day", "hour", "minute", "second", "millisecond"];
4153
4179
  var orderedWeekUnits = ["weekYear", "weekNumber", "weekday", "hour", "minute", "second", "millisecond"];
4154
4180
  var orderedOrdinalUnits = ["year", "ordinal", "hour", "minute", "second", "millisecond"];
4155
- function normalizeUnit(unit) {
4181
+ function normalizeUnit(unit2) {
4156
4182
  const normalized = {
4157
4183
  year: "year",
4158
4184
  years: "year",
@@ -4178,13 +4204,13 @@ var require_luxon = __commonJS(function(exports) {
4178
4204
  weekyear: "weekYear",
4179
4205
  weekyears: "weekYear",
4180
4206
  ordinal: "ordinal"
4181
- }[unit.toLowerCase()];
4207
+ }[unit2.toLowerCase()];
4182
4208
  if (!normalized)
4183
- throw new InvalidUnitError(unit);
4209
+ throw new InvalidUnitError(unit2);
4184
4210
  return normalized;
4185
4211
  }
4186
- function normalizeUnitWithLocalWeeks(unit) {
4187
- switch (unit.toLowerCase()) {
4212
+ function normalizeUnitWithLocalWeeks(unit2) {
4213
+ switch (unit2.toLowerCase()) {
4188
4214
  case "localweekday":
4189
4215
  case "localweekdays":
4190
4216
  return "localWeekday";
@@ -4195,7 +4221,7 @@ var require_luxon = __commonJS(function(exports) {
4195
4221
  case "localweekyears":
4196
4222
  return "localWeekYear";
4197
4223
  default:
4198
- return normalizeUnit(unit);
4224
+ return normalizeUnit(unit2);
4199
4225
  }
4200
4226
  }
4201
4227
  function guessOffsetForZone(zone) {
@@ -4243,27 +4269,27 @@ var require_luxon = __commonJS(function(exports) {
4243
4269
  });
4244
4270
  }
4245
4271
  function diffRelative(start, end, opts) {
4246
- const round = isUndefined(opts.round) ? true : opts.round, rounding = isUndefined(opts.rounding) ? "trunc" : opts.rounding, format = (c, unit) => {
4272
+ const round = isUndefined(opts.round) ? true : opts.round, rounding = isUndefined(opts.rounding) ? "trunc" : opts.rounding, format = (c, unit2) => {
4247
4273
  c = roundTo(c, round || opts.calendary ? 0 : 2, opts.calendary ? "round" : rounding);
4248
4274
  const formatter = end.loc.clone(opts).relFormatter(opts);
4249
- return formatter.format(c, unit);
4250
- }, differ = (unit) => {
4275
+ return formatter.format(c, unit2);
4276
+ }, differ = (unit2) => {
4251
4277
  if (opts.calendary) {
4252
- if (!end.hasSame(start, unit)) {
4253
- return end.startOf(unit).diff(start.startOf(unit), unit).get(unit);
4278
+ if (!end.hasSame(start, unit2)) {
4279
+ return end.startOf(unit2).diff(start.startOf(unit2), unit2).get(unit2);
4254
4280
  } else
4255
4281
  return 0;
4256
4282
  } else {
4257
- return end.diff(start, unit).get(unit);
4283
+ return end.diff(start, unit2).get(unit2);
4258
4284
  }
4259
4285
  };
4260
4286
  if (opts.unit) {
4261
4287
  return format(differ(opts.unit), opts.unit);
4262
4288
  }
4263
- for (const unit of opts.units) {
4264
- const count = differ(unit);
4289
+ for (const unit2 of opts.units) {
4290
+ const count = differ(unit2);
4265
4291
  if (Math.abs(count) >= 1) {
4266
- return format(count, unit);
4292
+ return format(count, unit2);
4267
4293
  }
4268
4294
  }
4269
4295
  return format(start > end ? -0 : 0, opts.units[opts.units.length - 1]);
@@ -4502,8 +4528,8 @@ var require_luxon = __commonJS(function(exports) {
4502
4528
  zoneOffsetTs = undefined;
4503
4529
  zoneOffsetGuessCache.clear();
4504
4530
  }
4505
- get(unit) {
4506
- return this[unit];
4531
+ get(unit2) {
4532
+ return this[unit2];
4507
4533
  }
4508
4534
  get isValid() {
4509
4535
  return this.invalid === null;
@@ -4789,12 +4815,12 @@ var require_luxon = __commonJS(function(exports) {
4789
4815
  const dur = Duration.fromDurationLike(duration).negate();
4790
4816
  return clone(this, adjustTime(this, dur));
4791
4817
  }
4792
- startOf(unit, {
4818
+ startOf(unit2, {
4793
4819
  useLocaleWeeks = false
4794
4820
  } = {}) {
4795
4821
  if (!this.isValid)
4796
4822
  return this;
4797
- const o = {}, normalizedUnit = Duration.normalizeUnit(unit);
4823
+ const o = {}, normalizedUnit = Duration.normalizeUnit(unit2);
4798
4824
  switch (normalizedUnit) {
4799
4825
  case "years":
4800
4826
  o.month = 1;
@@ -4832,10 +4858,10 @@ var require_luxon = __commonJS(function(exports) {
4832
4858
  }
4833
4859
  return this.set(o);
4834
4860
  }
4835
- endOf(unit, opts) {
4861
+ endOf(unit2, opts) {
4836
4862
  return this.isValid ? this.plus({
4837
- [unit]: 1
4838
- }).startOf(unit, opts).minus(1) : this;
4863
+ [unit2]: 1
4864
+ }).startOf(unit2, opts).minus(1) : this;
4839
4865
  }
4840
4866
  toFormat(fmt, opts = {}) {
4841
4867
  return this.isValid ? Formatter.create(this.loc.redefaultToEN(opts)).formatDateTimeFromString(this, fmt) : INVALID;
@@ -4973,7 +4999,7 @@ var require_luxon = __commonJS(function(exports) {
4973
4999
  toJSDate() {
4974
5000
  return new Date(this.isValid ? this.ts : NaN);
4975
5001
  }
4976
- diff(otherDateTime, unit = "milliseconds", opts = {}) {
5002
+ diff(otherDateTime, unit2 = "milliseconds", opts = {}) {
4977
5003
  if (!this.isValid || !otherDateTime.isValid) {
4978
5004
  return Duration.invalid("created by diffing an invalid DateTime");
4979
5005
  }
@@ -4982,23 +5008,23 @@ var require_luxon = __commonJS(function(exports) {
4982
5008
  numberingSystem: this.numberingSystem,
4983
5009
  ...opts
4984
5010
  };
4985
- const units = maybeArray(unit).map(Duration.normalizeUnit), otherIsLater = otherDateTime.valueOf() > this.valueOf(), earlier = otherIsLater ? this : otherDateTime, later = otherIsLater ? otherDateTime : this, diffed = diff(earlier, later, units, durOpts);
5011
+ const units = maybeArray(unit2).map(Duration.normalizeUnit), otherIsLater = otherDateTime.valueOf() > this.valueOf(), earlier = otherIsLater ? this : otherDateTime, later = otherIsLater ? otherDateTime : this, diffed = diff(earlier, later, units, durOpts);
4986
5012
  return otherIsLater ? diffed.negate() : diffed;
4987
5013
  }
4988
- diffNow(unit = "milliseconds", opts = {}) {
4989
- return this.diff(DateTime.now(), unit, opts);
5014
+ diffNow(unit2 = "milliseconds", opts = {}) {
5015
+ return this.diff(DateTime.now(), unit2, opts);
4990
5016
  }
4991
5017
  until(otherDateTime) {
4992
5018
  return this.isValid ? Interval.fromDateTimes(this, otherDateTime) : this;
4993
5019
  }
4994
- hasSame(otherDateTime, unit, opts) {
5020
+ hasSame(otherDateTime, unit2, opts) {
4995
5021
  if (!this.isValid)
4996
5022
  return false;
4997
5023
  const inputMs = otherDateTime.valueOf();
4998
5024
  const adjustedToZone = this.setZone(otherDateTime.zone, {
4999
5025
  keepLocalTime: true
5000
5026
  });
5001
- return adjustedToZone.startOf(unit, opts) <= inputMs && inputMs <= adjustedToZone.endOf(unit, opts);
5027
+ return adjustedToZone.startOf(unit2, opts) <= inputMs && inputMs <= adjustedToZone.endOf(unit2, opts);
5002
5028
  }
5003
5029
  equals(other) {
5004
5030
  return this.isValid && other.isValid && this.valueOf() === other.valueOf() && this.zone.equals(other.zone) && this.loc.equals(other.loc);
@@ -5010,16 +5036,16 @@ var require_luxon = __commonJS(function(exports) {
5010
5036
  zone: this.zone
5011
5037
  }), padding = options.padding ? this < base ? -options.padding : options.padding : 0;
5012
5038
  let units = ["years", "months", "days", "hours", "minutes", "seconds"];
5013
- let unit = options.unit;
5039
+ let unit2 = options.unit;
5014
5040
  if (Array.isArray(options.unit)) {
5015
5041
  units = options.unit;
5016
- unit = undefined;
5042
+ unit2 = undefined;
5017
5043
  }
5018
5044
  return diffRelative(base, this.plus(padding), {
5019
5045
  ...options,
5020
5046
  numeric: "always",
5021
5047
  units,
5022
- unit
5048
+ unit: unit2
5023
5049
  });
5024
5050
  }
5025
5051
  toRelativeCalendar(options = {}) {
@@ -5309,19 +5335,19 @@ var require_CronDate = __commonJS(function(exports) {
5309
5335
  subtractSecond() {
5310
5336
  this.#date = this.#date.minus({ seconds: 1 });
5311
5337
  }
5312
- addUnit(unit) {
5313
- this.#verbMap.add[unit]();
5338
+ addUnit(unit2) {
5339
+ this.#verbMap.add[unit2]();
5314
5340
  }
5315
- subtractUnit(unit) {
5316
- this.#verbMap.subtract[unit]();
5341
+ subtractUnit(unit2) {
5342
+ this.#verbMap.subtract[unit2]();
5317
5343
  }
5318
- invokeDateOperation(verb, unit) {
5344
+ invokeDateOperation(verb, unit2) {
5319
5345
  if (verb === DateMathOp.Add) {
5320
- this.addUnit(unit);
5346
+ this.addUnit(unit2);
5321
5347
  return;
5322
5348
  }
5323
5349
  if (verb === DateMathOp.Subtract) {
5324
- this.subtractUnit(unit);
5350
+ this.subtractUnit(unit2);
5325
5351
  return;
5326
5352
  }
5327
5353
  throw new Error(`Invalid verb: ${verb}`);
@@ -5430,13 +5456,13 @@ var require_CronDate = __commonJS(function(exports) {
5430
5456
  }
5431
5457
  return day > lastDay - 7;
5432
5458
  }
5433
- applyDateOperation(op, unit, hoursLength) {
5434
- if (unit === TimeUnit.Month || unit === TimeUnit.Day) {
5435
- this.invokeDateOperation(op, unit);
5459
+ applyDateOperation(op, unit2, hoursLength) {
5460
+ if (unit2 === TimeUnit.Month || unit2 === TimeUnit.Day) {
5461
+ this.invokeDateOperation(op, unit2);
5436
5462
  return;
5437
5463
  }
5438
5464
  const previousHour = this.getHours();
5439
- this.invokeDateOperation(op, unit);
5465
+ this.invokeDateOperation(op, unit2);
5440
5466
  const currentHour = this.getHours();
5441
5467
  const diff = currentHour - previousHour;
5442
5468
  if (diff === 2) {
@@ -10312,17 +10338,17 @@ var require_typescript = __commonJS(function(exports, module) {
10312
10338
  }
10313
10339
  return true;
10314
10340
  }
10315
- function fail(message, stackCrawlMark) {
10341
+ function fail2(message, stackCrawlMark) {
10316
10342
  debugger;
10317
10343
  const e = new Error(message ? `Debug Failure. ${message}` : "Debug Failure.");
10318
10344
  if (Error.captureStackTrace) {
10319
- Error.captureStackTrace(e, stackCrawlMark || fail);
10345
+ Error.captureStackTrace(e, stackCrawlMark || fail2);
10320
10346
  }
10321
10347
  throw e;
10322
10348
  }
10323
- Debug2.fail = fail;
10349
+ Debug2.fail = fail2;
10324
10350
  function failBadSyntaxKind(node, message, stackCrawlMark) {
10325
- return fail(`${message || "Unexpected node."}\r
10351
+ return fail2(`${message || "Unexpected node."}\r
10326
10352
  Node ${formatSyntaxKind(node.kind)} was unexpected.`, stackCrawlMark || failBadSyntaxKind);
10327
10353
  }
10328
10354
  Debug2.failBadSyntaxKind = failBadSyntaxKind;
@@ -10333,38 +10359,38 @@ Node ${formatSyntaxKind(node.kind)} was unexpected.`, stackCrawlMark || failBadS
10333
10359
  message += `\r
10334
10360
  Verbose Debug Information: ` + (typeof verboseDebugInfo === "string" ? verboseDebugInfo : verboseDebugInfo());
10335
10361
  }
10336
- fail(message, stackCrawlMark || assert);
10362
+ fail2(message, stackCrawlMark || assert);
10337
10363
  }
10338
10364
  }
10339
10365
  Debug2.assert = assert;
10340
10366
  function assertEqual(a, b, msg, msg2, stackCrawlMark) {
10341
10367
  if (a !== b) {
10342
10368
  const message = msg ? msg2 ? `${msg} ${msg2}` : msg : "";
10343
- fail(`Expected ${a} === ${b}. ${message}`, stackCrawlMark || assertEqual);
10369
+ fail2(`Expected ${a} === ${b}. ${message}`, stackCrawlMark || assertEqual);
10344
10370
  }
10345
10371
  }
10346
10372
  Debug2.assertEqual = assertEqual;
10347
10373
  function assertLessThan(a, b, msg, stackCrawlMark) {
10348
10374
  if (a >= b) {
10349
- fail(`Expected ${a} < ${b}. ${msg || ""}`, stackCrawlMark || assertLessThan);
10375
+ fail2(`Expected ${a} < ${b}. ${msg || ""}`, stackCrawlMark || assertLessThan);
10350
10376
  }
10351
10377
  }
10352
10378
  Debug2.assertLessThan = assertLessThan;
10353
10379
  function assertLessThanOrEqual(a, b, stackCrawlMark) {
10354
10380
  if (a > b) {
10355
- fail(`Expected ${a} <= ${b}`, stackCrawlMark || assertLessThanOrEqual);
10381
+ fail2(`Expected ${a} <= ${b}`, stackCrawlMark || assertLessThanOrEqual);
10356
10382
  }
10357
10383
  }
10358
10384
  Debug2.assertLessThanOrEqual = assertLessThanOrEqual;
10359
10385
  function assertGreaterThanOrEqual(a, b, stackCrawlMark) {
10360
10386
  if (a < b) {
10361
- fail(`Expected ${a} >= ${b}`, stackCrawlMark || assertGreaterThanOrEqual);
10387
+ fail2(`Expected ${a} >= ${b}`, stackCrawlMark || assertGreaterThanOrEqual);
10362
10388
  }
10363
10389
  }
10364
10390
  Debug2.assertGreaterThanOrEqual = assertGreaterThanOrEqual;
10365
10391
  function assertIsDefined(value, message, stackCrawlMark) {
10366
10392
  if (value === undefined || value === null) {
10367
- fail(message, stackCrawlMark || assertIsDefined);
10393
+ fail2(message, stackCrawlMark || assertIsDefined);
10368
10394
  }
10369
10395
  }
10370
10396
  Debug2.assertIsDefined = assertIsDefined;
@@ -10386,7 +10412,7 @@ Verbose Debug Information: ` + (typeof verboseDebugInfo === "string" ? verboseDe
10386
10412
  Debug2.checkEachDefined = checkEachDefined;
10387
10413
  function assertNever(member, message = "Illegal value:", stackCrawlMark) {
10388
10414
  const detail = typeof member === "object" && hasProperty(member, "kind") && hasProperty(member, "pos") ? "SyntaxKind: " + formatSyntaxKind(member.kind) : JSON.stringify(member);
10389
- return fail(`${message} ${detail}`, stackCrawlMark || assertNever);
10415
+ return fail2(`${message} ${detail}`, stackCrawlMark || assertNever);
10390
10416
  }
10391
10417
  Debug2.assertNever = assertNever;
10392
10418
  function assertEachNode(nodes, test, message, stackCrawlMark) {
@@ -115317,30 +115343,30 @@ ${lanes.join(`
115317
115343
  function getSourceFileFromReference(referencingFile, ref) {
115318
115344
  return getSourceFileFromReferenceWorker(resolveTripleslashReference(ref.fileName, referencingFile.fileName), getSourceFile);
115319
115345
  }
115320
- function getSourceFileFromReferenceWorker(fileName, getSourceFile2, fail, reason) {
115346
+ function getSourceFileFromReferenceWorker(fileName, getSourceFile2, fail2, reason) {
115321
115347
  if (hasExtension(fileName)) {
115322
115348
  const canonicalFileName = host.getCanonicalFileName(fileName);
115323
115349
  if (!options.allowNonTsExtensions && !forEach(flatten(supportedExtensionsWithJsonIfResolveJsonModule), (extension) => fileExtensionIs(canonicalFileName, extension))) {
115324
- if (fail) {
115350
+ if (fail2) {
115325
115351
  if (hasJSFileExtension(canonicalFileName)) {
115326
- fail(Diagnostics.File_0_is_a_JavaScript_file_Did_you_mean_to_enable_the_allowJs_option, fileName);
115352
+ fail2(Diagnostics.File_0_is_a_JavaScript_file_Did_you_mean_to_enable_the_allowJs_option, fileName);
115327
115353
  } else {
115328
- fail(Diagnostics.File_0_has_an_unsupported_extension_The_only_supported_extensions_are_1, fileName, "'" + flatten(supportedExtensions).join("', '") + "'");
115354
+ fail2(Diagnostics.File_0_has_an_unsupported_extension_The_only_supported_extensions_are_1, fileName, "'" + flatten(supportedExtensions).join("', '") + "'");
115329
115355
  }
115330
115356
  }
115331
115357
  return;
115332
115358
  }
115333
115359
  const sourceFile = getSourceFile2(fileName);
115334
- if (fail) {
115360
+ if (fail2) {
115335
115361
  if (!sourceFile) {
115336
115362
  const redirect = getRedirectFromSourceFile(fileName);
115337
115363
  if (redirect == null ? undefined : redirect.outputDts) {
115338
- fail(Diagnostics.Output_file_0_has_not_been_built_from_source_file_1, redirect.outputDts, fileName);
115364
+ fail2(Diagnostics.Output_file_0_has_not_been_built_from_source_file_1, redirect.outputDts, fileName);
115339
115365
  } else {
115340
- fail(Diagnostics.File_0_not_found, fileName);
115366
+ fail2(Diagnostics.File_0_not_found, fileName);
115341
115367
  }
115342
115368
  } else if (isReferencedFile(reason) && canonicalFileName === host.getCanonicalFileName(getSourceFileByPath(reason.file).fileName)) {
115343
- fail(Diagnostics.A_file_cannot_have_a_reference_to_itself);
115369
+ fail2(Diagnostics.A_file_cannot_have_a_reference_to_itself);
115344
115370
  }
115345
115371
  }
115346
115372
  return sourceFile;
@@ -115348,13 +115374,13 @@ ${lanes.join(`
115348
115374
  const sourceFileNoExtension = options.allowNonTsExtensions && getSourceFile2(fileName);
115349
115375
  if (sourceFileNoExtension)
115350
115376
  return sourceFileNoExtension;
115351
- if (fail && options.allowNonTsExtensions) {
115352
- fail(Diagnostics.File_0_not_found, fileName);
115377
+ if (fail2 && options.allowNonTsExtensions) {
115378
+ fail2(Diagnostics.File_0_not_found, fileName);
115353
115379
  return;
115354
115380
  }
115355
115381
  const sourceFileWithAddedExtension = forEach(supportedExtensions[0], (extension) => getSourceFile2(fileName + extension));
115356
- if (fail && !sourceFileWithAddedExtension)
115357
- fail(Diagnostics.Could_not_resolve_the_path_0_with_the_extensions_Colon_1, fileName, "'" + flatten(supportedExtensions).join("', '") + "'");
115382
+ if (fail2 && !sourceFileWithAddedExtension)
115383
+ fail2(Diagnostics.Could_not_resolve_the_path_0_with_the_extensions_Colon_1, fileName, "'" + flatten(supportedExtensions).join("', '") + "'");
115358
115384
  return sourceFileWithAddedExtension;
115359
115385
  }
115360
115386
  }
@@ -175175,6 +175201,1468 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
175175
175201
  } });
175176
175202
  });
175177
175203
 
175204
+ // src/workflows/executors/system-one-decision.ts
175205
+ init_zod();
175206
+ init_secret_scrubber();
175207
+
175208
+ // src/workflows/executors/base.ts
175209
+ class BaseExecutor {
175210
+ deps;
175211
+ retryPolicy;
175212
+ constructor(deps) {
175213
+ this.deps = deps;
175214
+ }
175215
+ async checkReadiness(_nodes) {
175216
+ return [];
175217
+ }
175218
+ resolveApproval(_parkedOutput, _approval) {
175219
+ return null;
175220
+ }
175221
+ async run(input) {
175222
+ const configResult = this.configSchema.safeParse(input.config);
175223
+ if (!configResult.success) {
175224
+ return {
175225
+ status: "failed",
175226
+ error: `Input validation failed: ${configResult.error.message}`
175227
+ };
175228
+ }
175229
+ let result;
175230
+ try {
175231
+ result = await this.execute(configResult.data, input.context, input.meta);
175232
+ } catch (err) {
175233
+ return {
175234
+ status: "failed",
175235
+ error: `Executor threw: ${err instanceof Error ? err.message : String(err)}`
175236
+ };
175237
+ }
175238
+ if (result.status === "success" && result.output !== undefined) {
175239
+ const outputResult = this.outputSchema.safeParse(result.output);
175240
+ if (!outputResult.success) {
175241
+ return {
175242
+ status: "failed",
175243
+ error: `Output validation failed: ${outputResult.error.message}`
175244
+ };
175245
+ }
175246
+ }
175247
+ return result;
175248
+ }
175249
+ }
175250
+
175251
+ // src/workflows/executors/human-in-the-loop.ts
175252
+ init_zod();
175253
+ init_constants();
175254
+ init_secret_scrubber();
175255
+
175256
+ // src/workflows/approval-notifications.ts
175257
+ init_db();
175258
+ init_resolver();
175259
+ init_types();
175260
+ init_secret_scrubber();
175261
+ async function postApprovalCancellationUpdates(approvals, reason, client = getSlackApp()?.client) {
175262
+ if (!client)
175263
+ return;
175264
+ const text = `This approval is no longer actionable: ${reason}`;
175265
+ for (const approval of approvals) {
175266
+ const channels = approval.notificationChannels;
175267
+ const slackThreads = (channels ?? []).filter((notification) => notification.channel === "slack" && notification.messageTs);
175268
+ if (slackThreads.length === 0)
175269
+ continue;
175270
+ for (const notification of slackThreads) {
175271
+ if (notification.channel !== "slack" || !notification.messageTs)
175272
+ continue;
175273
+ const notificationKey = `${notification.target}:${notification.messageTs}`;
175274
+ const claim = await claimApprovalCancellationNotification(approval.id, notificationKey);
175275
+ if (!claim)
175276
+ continue;
175277
+ try {
175278
+ await client.chat.postMessage({
175279
+ channel: notification.target,
175280
+ thread_ts: notification.messageTs,
175281
+ text,
175282
+ unfurl_links: false,
175283
+ unfurl_media: false
175284
+ });
175285
+ await completeApprovalCancellationNotificationClaim(approval.id, notificationKey, claim.leaseToken);
175286
+ } catch (error) {
175287
+ await releaseApprovalCancellationNotificationClaim(approval.id, notificationKey, claim.leaseToken);
175288
+ console.error(`[HITL] Failed to post cancellation update for approval ${approval.id}:`, scrubSecrets(error instanceof Error ? error.message : String(error)));
175289
+ }
175290
+ }
175291
+ }
175292
+ }
175293
+ async function createApprovalFollowUpTask(request, templateEventType) {
175294
+ if (request.workflowRunId || !request.sourceTaskId)
175295
+ return false;
175296
+ const sourceTask = await getTaskById(request.sourceTaskId);
175297
+ if (!sourceTask)
175298
+ return false;
175299
+ if (templateEventType === "hitl.timeout" && TERMINAL_TASK_STATUSES.includes(sourceTask.status)) {
175300
+ return false;
175301
+ }
175302
+ const { text: taskText } = templateEventType === "hitl.follow_up" ? resolveTemplate("hitl.follow_up", {
175303
+ request_id: request.id,
175304
+ title: request.title,
175305
+ status: request.status,
175306
+ responses: formatResponses(request.questions, request.responses ?? {})
175307
+ }) : resolveTemplate("hitl.timeout", {
175308
+ request_id: request.id,
175309
+ title: request.title,
175310
+ expires_at: request.expiresAt ?? "",
175311
+ reason: request.resolutionReason ?? ""
175312
+ });
175313
+ await createTaskExtended(taskText, {
175314
+ agentId: sourceTask.agentId,
175315
+ routingReason: sourceTask.agentId ? "continuity" : undefined,
175316
+ routingSource: sourceTask.agentId ? "engine_default" : undefined,
175317
+ parentTaskId: request.sourceTaskId,
175318
+ source: "system",
175319
+ taskType: "hitl-follow-up",
175320
+ tags: ["hitl", "follow-up"],
175321
+ slackChannelId: sourceTask.slackChannelId ?? undefined,
175322
+ slackThreadTs: sourceTask.slackThreadTs ?? undefined,
175323
+ slackUserId: sourceTask.slackUserId ?? undefined
175324
+ });
175325
+ return true;
175326
+ }
175327
+ function formatResponses(questions, responses) {
175328
+ return questions.map((q) => {
175329
+ const answer = responses[q.id];
175330
+ let answerText;
175331
+ if (answer == null) {
175332
+ answerText = "(no answer)";
175333
+ } else if (q.type === "approval") {
175334
+ const a = answer;
175335
+ answerText = a.approved ? "Approved" : "Rejected";
175336
+ if (a.comment)
175337
+ answerText += ` — ${a.comment}`;
175338
+ } else if (typeof answer === "object") {
175339
+ answerText = JSON.stringify(answer);
175340
+ } else {
175341
+ answerText = String(answer);
175342
+ }
175343
+ return `- ${q.label}: ${answerText}`;
175344
+ }).join(`
175345
+ `);
175346
+ }
175347
+
175348
+ // src/workflows/executors/human-in-the-loop.ts
175349
+ var SelectOptionSchema = exports_external.object({
175350
+ value: exports_external.string(),
175351
+ label: exports_external.string(),
175352
+ description: exports_external.string().optional()
175353
+ });
175354
+ var QuestionSchema = exports_external.discriminatedUnion("type", [
175355
+ exports_external.object({
175356
+ id: exports_external.string(),
175357
+ type: exports_external.literal("approval"),
175358
+ label: exports_external.string(),
175359
+ required: exports_external.boolean().default(true),
175360
+ description: exports_external.string().optional()
175361
+ }),
175362
+ exports_external.object({
175363
+ id: exports_external.string(),
175364
+ type: exports_external.literal("text"),
175365
+ label: exports_external.string(),
175366
+ required: exports_external.boolean().default(true),
175367
+ description: exports_external.string().optional(),
175368
+ placeholder: exports_external.string().optional(),
175369
+ multiline: exports_external.boolean().optional()
175370
+ }),
175371
+ exports_external.object({
175372
+ id: exports_external.string(),
175373
+ type: exports_external.literal("single-select"),
175374
+ label: exports_external.string(),
175375
+ required: exports_external.boolean().default(true),
175376
+ description: exports_external.string().optional(),
175377
+ options: exports_external.array(SelectOptionSchema)
175378
+ }),
175379
+ exports_external.object({
175380
+ id: exports_external.string(),
175381
+ type: exports_external.literal("multi-select"),
175382
+ label: exports_external.string(),
175383
+ required: exports_external.boolean().default(true),
175384
+ description: exports_external.string().optional(),
175385
+ options: exports_external.array(SelectOptionSchema),
175386
+ minSelections: exports_external.number().int().min(0).optional(),
175387
+ maxSelections: exports_external.number().int().min(1).optional()
175388
+ }),
175389
+ exports_external.object({
175390
+ id: exports_external.string(),
175391
+ type: exports_external.literal("boolean"),
175392
+ label: exports_external.string(),
175393
+ required: exports_external.boolean().default(true),
175394
+ description: exports_external.string().optional(),
175395
+ defaultValue: exports_external.boolean().optional()
175396
+ })
175397
+ ]);
175398
+ var ApproverConfigSchema = exports_external.object({
175399
+ users: exports_external.array(exports_external.string()).optional(),
175400
+ roles: exports_external.array(exports_external.string()).optional(),
175401
+ policy: exports_external.union([exports_external.literal("any"), exports_external.literal("all"), exports_external.object({ min: exports_external.number().int().min(1) })])
175402
+ });
175403
+ var NotificationConfigSchema = exports_external.object({
175404
+ channel: exports_external.enum(["slack", "email"]),
175405
+ target: exports_external.string()
175406
+ });
175407
+ var HITLTimeoutSchema = exports_external.object({
175408
+ seconds: exports_external.number().int().min(1),
175409
+ action: exports_external.literal("reject")
175410
+ });
175411
+ var DYNAMIC_QUESTIONS_TOKEN_RE = /^\{\{[^}]+\}\}$/;
175412
+ var MAX_HITL_QUESTIONS = 100;
175413
+ var SLACK_SECTION_TEXT_LIMIT = 3000;
175414
+ var MAX_REPORTED_ISSUES = 5;
175415
+ var HITLConfigSchema = exports_external.object({
175416
+ title: exports_external.string(),
175417
+ questions: exports_external.union([
175418
+ exports_external.array(QuestionSchema).min(1),
175419
+ exports_external.string().regex(DYNAMIC_QUESTIONS_TOKEN_RE, "questions must be an array or one exact {{interpolation}} token")
175420
+ ]),
175421
+ approvers: ApproverConfigSchema,
175422
+ timeout: HITLTimeoutSchema.optional(),
175423
+ notifications: exports_external.array(NotificationConfigSchema).optional()
175424
+ });
175425
+ var HITLOutputSchema = exports_external.object({
175426
+ requestId: exports_external.string().uuid(),
175427
+ status: exports_external.string(),
175428
+ responses: exports_external.record(exports_external.string(), exports_external.unknown()).nullable()
175429
+ });
175430
+ function resolveHitlQuestions(value) {
175431
+ const fail = (reason) => ({
175432
+ ok: false,
175433
+ error: `human-in-the-loop questions ${reason}`
175434
+ });
175435
+ if (typeof value === "string") {
175436
+ return fail(value.trim() === "" ? "resolved to an empty value: the {{token}} did not resolve (check the node's inputs mapping and the upstream output)" : "resolved to a string; they must resolve to an array of question objects (use one exact {{token}} pointing at an array)");
175437
+ }
175438
+ if (!Array.isArray(value)) {
175439
+ return fail(`must resolve to an array of question objects, got ${value === null ? "null" : typeof value}`);
175440
+ }
175441
+ if (value.length === 0) {
175442
+ return fail("resolved to an empty array; refusing to create an approval card with no questions");
175443
+ }
175444
+ if (value.length > MAX_HITL_QUESTIONS) {
175445
+ return fail(`resolved to ${value.length} questions, over the limit of ${MAX_HITL_QUESTIONS} per card; split or group them upstream`);
175446
+ }
175447
+ const issues = [];
175448
+ const questions = [];
175449
+ const seenIds = new Set;
175450
+ value.forEach((raw, index) => {
175451
+ const parsed = QuestionSchema.safeParse(raw);
175452
+ if (!parsed.success) {
175453
+ for (const issue of parsed.error.issues) {
175454
+ const path = issue.path.length > 0 ? `.${issue.path.map(String).join(".")}` : "";
175455
+ issues.push(`[${index}]${path}: ${issue.message}`);
175456
+ }
175457
+ return;
175458
+ }
175459
+ const question = parsed.data;
175460
+ if (question.id.trim() === "") {
175461
+ issues.push(`[${index}].id: must be a non-empty string`);
175462
+ } else if (seenIds.has(question.id)) {
175463
+ issues.push(`[${index}].id: duplicate id "${question.id}" (responses are keyed by id)`);
175464
+ }
175465
+ seenIds.add(question.id);
175466
+ if ((question.type === "single-select" || question.type === "multi-select") && question.options.length === 0) {
175467
+ issues.push(`[${index}].options: a ${question.type} question needs at least one option`);
175468
+ }
175469
+ questions.push(question);
175470
+ });
175471
+ if (issues.length > 0) {
175472
+ const shown = issues.slice(0, MAX_REPORTED_ISSUES).join("; ");
175473
+ const more = issues.length > MAX_REPORTED_ISSUES ? `; and ${issues.length - MAX_REPORTED_ISSUES} more issue(s)` : "";
175474
+ return fail(`are invalid: ${shown}${more}`);
175475
+ }
175476
+ return { ok: true, questions };
175477
+ }
175478
+ function escapeSlackMrkdwn(text) {
175479
+ return text.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
175480
+ }
175481
+ function buildSlackQuestionsSummary(questions, timeoutText = "") {
175482
+ const header = `*Questions:*
175483
+ `;
175484
+ const lines = questions.map((q) => `• ${escapeSlackMrkdwn(q.label.replace(/\s+/g, " ").trim())}`);
175485
+ const fits = (shown, omitted) => {
175486
+ const tail = omitted > 0 ? `
175487
+ _…and ${omitted} more. Answer all of them on the dashboard._` : "";
175488
+ const text = `${header}${shown.join(`
175489
+ `)}${tail}${timeoutText}`;
175490
+ return text.length <= SLACK_SECTION_TEXT_LIMIT ? text : null;
175491
+ };
175492
+ const full = fits(lines, 0);
175493
+ if (full)
175494
+ return full;
175495
+ for (let count = lines.length - 1;count >= 0; count--) {
175496
+ const text = fits(lines.slice(0, count), lines.length - count);
175497
+ if (text)
175498
+ return text;
175499
+ }
175500
+ return `${header}_${questions.length} questions. Answer them on the dashboard._`;
175501
+ }
175502
+
175503
+ class HumanInTheLoopExecutor extends BaseExecutor {
175504
+ type = "human-in-the-loop";
175505
+ mode = "async";
175506
+ configSchema = HITLConfigSchema;
175507
+ outputSchema = HITLOutputSchema;
175508
+ async run(input) {
175509
+ const resolved = resolveHitlQuestions(input.config?.questions);
175510
+ if (!resolved.ok)
175511
+ return { status: "failed", error: resolved.error };
175512
+ return super.run({ ...input, config: { ...input.config, questions: resolved.questions } });
175513
+ }
175514
+ async execute(config, _context, meta) {
175515
+ const { db } = this.deps;
175516
+ const existing = await db.getApprovalRequestByStepId(meta.stepId);
175517
+ if (existing) {
175518
+ if (existing.status !== "pending") {
175519
+ if (existing.status === "cancelled") {
175520
+ return {
175521
+ status: "failed",
175522
+ error: `Approval request was cancelled: ${existing.resolutionReason ?? "workflow run cancelled"}`
175523
+ };
175524
+ }
175525
+ const nextPort = existing.status === "timeout" ? "timeout" : existing.status === "rejected" ? "rejected" : "approved";
175526
+ return {
175527
+ status: "success",
175528
+ output: {
175529
+ requestId: existing.id,
175530
+ status: existing.status,
175531
+ responses: existing.responses
175532
+ },
175533
+ nextPort
175534
+ };
175535
+ }
175536
+ return {
175537
+ status: "success",
175538
+ async: true,
175539
+ waitFor: "approval.resolved",
175540
+ correlationId: existing.id
175541
+ };
175542
+ }
175543
+ if (!Array.isArray(config.questions)) {
175544
+ return { status: "failed", error: "human-in-the-loop questions did not resolve to an array" };
175545
+ }
175546
+ const requestId = crypto.randomUUID();
175547
+ const created = await db.createApprovalRequest({
175548
+ id: requestId,
175549
+ title: config.title,
175550
+ questions: config.questions,
175551
+ approvers: config.approvers,
175552
+ workflowRunId: meta.runId,
175553
+ workflowRunStepId: meta.stepId,
175554
+ timeoutSeconds: config.timeout?.seconds,
175555
+ notificationChannels: config.notifications,
175556
+ createdBy: meta.requestedByUserId,
175557
+ requireActionableWorkflow: true
175558
+ });
175559
+ if (created.status === "cancelled") {
175560
+ return {
175561
+ status: "success",
175562
+ async: true,
175563
+ waitFor: "approval.resolved",
175564
+ correlationId: requestId
175565
+ };
175566
+ }
175567
+ if (config.notifications?.length) {
175568
+ this.dispatchNotifications(requestId, config, db).catch((err) => {
175569
+ console.error("[HITL] Unexpected error dispatching notifications:", scrubSecrets(err instanceof Error ? err.message : String(err)));
175570
+ });
175571
+ }
175572
+ return {
175573
+ status: "success",
175574
+ async: true,
175575
+ waitFor: "approval.resolved",
175576
+ correlationId: requestId
175577
+ };
175578
+ }
175579
+ async dispatchNotifications(requestId, config, db) {
175580
+ if (!config.notifications?.length)
175581
+ return;
175582
+ const approvalUrl = `${getAppUrl()}/approval-requests/${requestId}`;
175583
+ const updatedChannels = [...config.notifications];
175584
+ let updated = false;
175585
+ for (let i = 0;i < config.notifications.length; i++) {
175586
+ const notification = config.notifications[i];
175587
+ if (notification.channel === "email") {
175588
+ console.warn(`[HITL] Email notifications not yet supported (target: ${notification.target})`);
175589
+ continue;
175590
+ }
175591
+ if (notification.channel === "slack") {
175592
+ try {
175593
+ const { getSlackApp: getSlackApp2 } = await import("./app-mc7xfagn.js");
175594
+ const slackApp = getSlackApp2();
175595
+ if (!slackApp) {
175596
+ console.warn("[HITL] Slack not initialized — cannot send notification");
175597
+ continue;
175598
+ }
175599
+ const questions = Array.isArray(config.questions) ? config.questions : [];
175600
+ const questionsText = buildSlackQuestionsSummary(questions);
175601
+ const timeoutCaption = config.timeout ? [
175602
+ {
175603
+ type: "context",
175604
+ elements: [
175605
+ {
175606
+ type: "mrkdwn",
175607
+ text: `⏱ Timeout: ${formatTimeout(config.timeout.seconds)} — times out if not responded`
175608
+ }
175609
+ ]
175610
+ }
175611
+ ] : [];
175612
+ const blocks = [
175613
+ {
175614
+ type: "section",
175615
+ text: {
175616
+ type: "mrkdwn",
175617
+ text: `\uD83D\uDD14 *Approval Required: ${config.title}*`
175618
+ }
175619
+ },
175620
+ {
175621
+ type: "section",
175622
+ text: {
175623
+ type: "mrkdwn",
175624
+ text: questionsText
175625
+ }
175626
+ },
175627
+ {
175628
+ type: "actions",
175629
+ elements: [
175630
+ {
175631
+ type: "button",
175632
+ text: { type: "plain_text", text: "Review & Respond" },
175633
+ url: approvalUrl,
175634
+ style: "primary"
175635
+ }
175636
+ ]
175637
+ },
175638
+ ...timeoutCaption
175639
+ ];
175640
+ const result = await slackApp.client.chat.postMessage({
175641
+ channel: notification.target,
175642
+ text: `Approval Required: ${config.title} — ${approvalUrl}`,
175643
+ unfurl_links: false,
175644
+ unfurl_media: false,
175645
+ blocks
175646
+ });
175647
+ if (result.ts) {
175648
+ updatedChannels[i] = { ...notification, messageTs: result.ts };
175649
+ updated = true;
175650
+ }
175651
+ console.log(`[HITL] Slack notification sent to ${notification.target} for request ${requestId}`);
175652
+ } catch (err) {
175653
+ console.error(`[HITL] Failed to send Slack notification to ${notification.target}:`, scrubSecrets(err instanceof Error ? err.message : String(err)));
175654
+ }
175655
+ }
175656
+ }
175657
+ if (updated) {
175658
+ try {
175659
+ await db.updateApprovalRequestNotifications(requestId, updatedChannels);
175660
+ const latest = await db.getApprovalRequestById(requestId);
175661
+ if (latest?.status === "cancelled") {
175662
+ await postApprovalCancellationUpdates([latest], latest.resolutionReason ?? "Workflow run cancelled");
175663
+ }
175664
+ } catch (err) {
175665
+ console.error("[HITL] Failed to update notification channels in DB:", scrubSecrets(err instanceof Error ? err.message : String(err)));
175666
+ }
175667
+ }
175668
+ }
175669
+ }
175670
+ function formatTimeout(seconds) {
175671
+ if (seconds < 60)
175672
+ return `${seconds}s`;
175673
+ if (seconds < 3600)
175674
+ return `${Math.round(seconds / 60)}m`;
175675
+ const hours = Math.floor(seconds / 3600);
175676
+ const mins = Math.round(seconds % 3600 / 60);
175677
+ return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;
175678
+ }
175679
+
175680
+ // src/workflows/executors/workflow-llm.ts
175681
+ async function resolveWorkflowLlmConfig(requestedModel, env = process.env, options = {}) {
175682
+ const credential = await resolveCredential({ env });
175683
+ if (!credential) {
175684
+ throw new Error("No workflow LLM credential found. Set OPENROUTER_API_KEY or OPENAI_API_KEY.");
175685
+ }
175686
+ if (options.requireKind && credential.kind !== options.requireKind) {
175687
+ throw new Error(`No ${options.requireKind} credential found for this workflow LLM call.`);
175688
+ }
175689
+ if (credential.kind !== "openrouter" && credential.kind !== "openai") {
175690
+ throw new Error(`Workflow LLM nodes do not support the resolved ${credential.kind} credential yet. Set OPENROUTER_API_KEY or OPENAI_API_KEY.`);
175691
+ }
175692
+ const providerPrefix = `${credential.kind}/`;
175693
+ const model = requestedModel ?? DEFAULT_MODEL[credential.kind];
175694
+ return {
175695
+ apiKey: credential.apiKey,
175696
+ baseURL: credential.kind === "openrouter" ? getOpenRouterBaseUrl(env) : undefined,
175697
+ model: model.startsWith(providerPrefix) ? model.slice(providerPrefix.length) : model
175698
+ };
175699
+ }
175700
+
175701
+ // src/workflows/executors/system-one-providers.ts
175702
+ var TYPESAFE_KEY = "TYPESAFE_API_KEY";
175703
+ var OPENROUTER_KEY = "OPENROUTER_API_KEY";
175704
+ var LAYA_KEY = "LAYA_API_KEY";
175705
+ var LAYA_URL_KEY = "LAYA_URL";
175706
+ async function readGlobalConfig(db, key) {
175707
+ const rows = await db.getSwarmConfigs({ scope: "global", key });
175708
+ return rows.find((row) => row.scope === "global" && row.key === key)?.value;
175709
+ }
175710
+ var SYSTEM_ONE_PROVIDERS = {
175711
+ typesafe: {
175712
+ label: "TypeSafe",
175713
+ keyName: TYPESAFE_KEY,
175714
+ endpoint: "https://api.typesafe.ai/v1/systemone",
175715
+ defaultModel: "jev-latest",
175716
+ confidenceField: "confidence",
175717
+ readKey: ({ db }) => readGlobalConfig(db, TYPESAFE_KEY)
175718
+ },
175719
+ openrouter: {
175720
+ label: "OpenRouter",
175721
+ keyName: OPENROUTER_KEY,
175722
+ endpoint: "https://openrouter.ai/api/alpha/decisions",
175723
+ defaultModel: "~typesafe/jev-latest",
175724
+ confidenceField: "confidence",
175725
+ deploymentProblem(env) {
175726
+ return getOpenRouterBaseUrl(env) === DEFAULT_OPENROUTER_BASE_URL ? null : 'OPENROUTER_BASE_URL points at a gateway. SystemOne provider "openrouter" calls openrouter.ai directly and is not supported through a gateway; unset OPENROUTER_BASE_URL or use provider "typesafe".';
175727
+ },
175728
+ async readKey({ env }) {
175729
+ try {
175730
+ return (await resolveWorkflowLlmConfig(undefined, env, { requireKind: "openrouter" })).apiKey;
175731
+ } catch {
175732
+ return null;
175733
+ }
175734
+ }
175735
+ },
175736
+ laya: {
175737
+ label: "laya",
175738
+ keyName: LAYA_KEY,
175739
+ endpoint: { configKey: LAYA_URL_KEY, path: "/v1/systemone" },
175740
+ confidenceField: "answer_confidence",
175741
+ readKey: ({ db }) => readGlobalConfig(db, LAYA_KEY)
175742
+ }
175743
+ };
175744
+ var SYSTEM_ONE_PROVIDER_IDS = Object.keys(SYSTEM_ONE_PROVIDERS);
175745
+ var SYSTEM_ONE_DEFAULT_PROVIDER = "typesafe";
175746
+ function isSystemOneProviderId(value) {
175747
+ return typeof value === "string" && Object.hasOwn(SYSTEM_ONE_PROVIDERS, value);
175748
+ }
175749
+ function systemOneProviderOf(config) {
175750
+ if (config.provider === undefined)
175751
+ return SYSTEM_ONE_DEFAULT_PROVIDER;
175752
+ return isSystemOneProviderId(config.provider) ? config.provider : undefined;
175753
+ }
175754
+ var SET_IT = (keyName) => `Set ${keyName} as a global secret on the Secrets page (Settings > Secrets).`;
175755
+ var SET_URL = (configKey) => `Set ${configKey} as a global config value (set-config with scope global).`;
175756
+ function systemOneKeyMissingMessage(id) {
175757
+ const { label, keyName } = SYSTEM_ONE_PROVIDERS[id];
175758
+ return `${keyName} is not configured. SystemOne provider "${id}" needs a working ${label} API key. ${SET_IT(keyName)}`;
175759
+ }
175760
+ function systemOneKeyUnreadableMessage(id) {
175761
+ return `Could not read ${SYSTEM_ONE_PROVIDERS[id].keyName} from swarm config`;
175762
+ }
175763
+ function systemOneKeyMalformedMessage(id) {
175764
+ return `${SYSTEM_ONE_PROVIDERS[id].keyName} is not a valid bearer token value. ${SET_IT(SYSTEM_ONE_PROVIDERS[id].keyName)}`;
175765
+ }
175766
+ function systemOneKeyRejectedMessage(id, status, code) {
175767
+ const { label, keyName } = SYSTEM_ONE_PROVIDERS[id];
175768
+ const detail = code ? ` (${code})` : "";
175769
+ return `${keyName} was rejected by ${label} (HTTP ${status}${detail}). ` + `The key is invalid, revoked, or lacks access to the model. Replace it on the Secrets page (Settings > Secrets). No decision was made.`;
175770
+ }
175771
+ function urlKeyOf(provider) {
175772
+ return typeof provider.endpoint === "string" ? null : provider.endpoint.configKey;
175773
+ }
175774
+ function systemOneUrlMissingMessage(id) {
175775
+ const provider = SYSTEM_ONE_PROVIDERS[id];
175776
+ const configKey = urlKeyOf(provider) ?? "";
175777
+ return `${configKey} is not configured. SystemOne provider "${id}" needs the URL of a ${provider.label} server. ${SET_URL(configKey)}`;
175778
+ }
175779
+ function systemOneUrlUnreadableMessage(id) {
175780
+ return `Could not read ${urlKeyOf(SYSTEM_ONE_PROVIDERS[id]) ?? ""} from swarm config`;
175781
+ }
175782
+ function systemOneUrlInvalidMessage(id) {
175783
+ const provider = SYSTEM_ONE_PROVIDERS[id];
175784
+ const configKey = urlKeyOf(provider) ?? "";
175785
+ return `${configKey} is not a usable ${provider.label} server URL. It must be an https URL (http only for localhost) with no credentials, query, or fragment. ${SET_URL(configKey)}`;
175786
+ }
175787
+ function hasWhitespaceOrControl(value) {
175788
+ for (const char of value) {
175789
+ const code = char.charCodeAt(0);
175790
+ if (code <= 32 || code === 127)
175791
+ return true;
175792
+ }
175793
+ return false;
175794
+ }
175795
+ var LOOPBACK_HOSTS = new Set(["localhost", "127.0.0.1", "[::1]"]);
175796
+ function systemOneEndpointFromBase(base, path) {
175797
+ let url;
175798
+ try {
175799
+ url = new URL(base.trim());
175800
+ } catch {
175801
+ return null;
175802
+ }
175803
+ const secure = url.protocol === "https:";
175804
+ const loopback = url.protocol === "http:" && LOOPBACK_HOSTS.has(url.hostname);
175805
+ if (!secure && !loopback)
175806
+ return null;
175807
+ if (url.username || url.password || url.search || url.hash)
175808
+ return null;
175809
+ return `${url.origin}${url.pathname.replace(/\/+$/, "")}${path}`;
175810
+ }
175811
+ async function resolveSystemOneTarget(id, ctx, overrides = {}) {
175812
+ const provider = SYSTEM_ONE_PROVIDERS[id];
175813
+ const deploymentProblem = provider.deploymentProblem?.(ctx.env);
175814
+ if (deploymentProblem)
175815
+ return { ok: false, error: deploymentProblem };
175816
+ const errors = [];
175817
+ let endpoint;
175818
+ if (typeof provider.endpoint === "string") {
175819
+ endpoint = provider.endpoint;
175820
+ } else {
175821
+ const { configKey, path } = provider.endpoint;
175822
+ let base;
175823
+ let readable = true;
175824
+ try {
175825
+ base = await (overrides.serverUrl ? overrides.serverUrl(id) : readGlobalConfig(ctx.db, configKey));
175826
+ } catch {
175827
+ readable = false;
175828
+ errors.push(systemOneUrlUnreadableMessage(id));
175829
+ }
175830
+ if (readable) {
175831
+ if (!base || base.trim() === "") {
175832
+ errors.push(systemOneUrlMissingMessage(id));
175833
+ } else {
175834
+ const resolved = systemOneEndpointFromBase(base, path);
175835
+ if (resolved)
175836
+ endpoint = resolved;
175837
+ else
175838
+ errors.push(systemOneUrlInvalidMessage(id));
175839
+ }
175840
+ }
175841
+ }
175842
+ let apiKey;
175843
+ let keyProblem;
175844
+ try {
175845
+ apiKey = await (overrides.apiKey ? overrides.apiKey(id) : provider.readKey(ctx));
175846
+ } catch {
175847
+ keyProblem = systemOneKeyUnreadableMessage(id);
175848
+ }
175849
+ if (!keyProblem) {
175850
+ if (!apiKey || apiKey.trim() === "")
175851
+ keyProblem = systemOneKeyMissingMessage(id);
175852
+ else if (hasWhitespaceOrControl(apiKey))
175853
+ keyProblem = systemOneKeyMalformedMessage(id);
175854
+ }
175855
+ if (keyProblem)
175856
+ errors.push(keyProblem);
175857
+ if (errors.length > 0 || !endpoint || !apiKey)
175858
+ return { ok: false, error: errors.join(" ") };
175859
+ return { ok: true, apiKey, endpoint };
175860
+ }
175861
+
175862
+ // src/workflows/executors/system-one-decision.ts
175863
+ var SYSTEM_ONE_DECISION_NODE_TYPE = "system-one-decision";
175864
+ var SYSTEM_ONE_ENDPOINT = SYSTEM_ONE_PROVIDERS.typesafe.endpoint;
175865
+ var SYSTEM_ONE_API_KEY_CONFIG_KEY = SYSTEM_ONE_PROVIDERS.typesafe.keyName;
175866
+ var SYSTEM_ONE_DEFAULT_TIMEOUT_MS = 30000;
175867
+ var SYSTEM_ONE_MIN_TIMEOUT_MS = 1000;
175868
+ var SYSTEM_ONE_MAX_TIMEOUT_MS = 300000;
175869
+ var SYSTEM_ONE_DEFAULT_MAX_RETRIES = 2;
175870
+ var SYSTEM_ONE_MAX_RETRIES_LIMIT = 3;
175871
+ var CHOICE_MIN_OPTIONS = 2;
175872
+ var CHOICE_MAX_OPTIONS = 255;
175873
+ var SCORE_MIN_LEVELS = 2;
175874
+ var SCORE_MAX_LEVELS = 10;
175875
+ var DEADLINE_MARGIN_MS = 250;
175876
+ var BACKOFF_BASE_MS = 500;
175877
+ var BACKOFF_CAP_MS = 8000;
175878
+ var DISTRIBUTION_TOLERANCE = 0.02;
175879
+ var MAX_RESPONSE_CHARS = 1048576;
175880
+ var MAX_ERROR_BODY_CHARS = 65536;
175881
+ var REVIEW_PORTS = ["approved", "rejected", "timeout"];
175882
+ var ENGINE_RETRY_DEFAULT = 3;
175883
+ var SystemOneEntrySchema = exports_external.union([
175884
+ exports_external.string(),
175885
+ exports_external.null(),
175886
+ exports_external.array(exports_external.unknown()),
175887
+ exports_external.record(exports_external.string(), exports_external.unknown())
175888
+ ]);
175889
+ var SystemOneInstructionsSchema = SystemOneEntrySchema.refine((value) => value !== null && !(typeof value === "string" && value.trim() === ""), { message: "instructions must not be null or blank" });
175890
+ var SystemOneStateSchema = exports_external.union([
175891
+ exports_external.string().min(1, "state must not be empty"),
175892
+ exports_external.array(exports_external.string()).min(1, "state must not be an empty array"),
175893
+ exports_external.record(exports_external.string(), exports_external.unknown())
175894
+ ]);
175895
+ var NoulQuestionSchema = exports_external.strictObject({
175896
+ type: exports_external.literal("noul"),
175897
+ instructions: SystemOneInstructionsSchema,
175898
+ criteria: exports_external.strictObject({ true: SystemOneEntrySchema.optional(), false: SystemOneEntrySchema.optional() }).refine((criteria) => criteria.true !== undefined || criteria.false !== undefined, {
175899
+ message: "noul criteria must describe at least one of true / false"
175900
+ }).optional()
175901
+ });
175902
+ var ChoiceQuestionSchema = exports_external.strictObject({
175903
+ type: exports_external.literal("choice"),
175904
+ instructions: SystemOneInstructionsSchema,
175905
+ criteria: exports_external.record(exports_external.string().min(1), SystemOneEntrySchema).refine((criteria) => {
175906
+ const count = Object.keys(criteria).length;
175907
+ return count >= CHOICE_MIN_OPTIONS && count <= CHOICE_MAX_OPTIONS;
175908
+ }, {
175909
+ message: `choice criteria must define ${CHOICE_MIN_OPTIONS}-${CHOICE_MAX_OPTIONS} options`
175910
+ })
175911
+ });
175912
+ var ScoreQuestionSchema = exports_external.strictObject({
175913
+ type: exports_external.literal("score"),
175914
+ instructions: SystemOneInstructionsSchema,
175915
+ criteria: exports_external.array(SystemOneEntrySchema).min(SCORE_MIN_LEVELS).max(SCORE_MAX_LEVELS)
175916
+ });
175917
+ var SystemOneQuestionSchema = exports_external.discriminatedUnion("type", [
175918
+ NoulQuestionSchema,
175919
+ ChoiceQuestionSchema,
175920
+ ScoreQuestionSchema
175921
+ ]);
175922
+ var Unit = exports_external.number().min(0).max(1);
175923
+ var QUESTION_ID_RE = /^[A-Za-z_][A-Za-z0-9_-]*$/;
175924
+ var RESERVED_QUESTION_IDS = new Set([
175925
+ ...Object.getOwnPropertyNames(Object.prototype),
175926
+ "prototype"
175927
+ ]);
175928
+ var SystemOnePrimitiveTypeSchema = exports_external.enum(["noul", "choice", "score"]);
175929
+ var HumanReviewSchema = exports_external.strictObject({
175930
+ band: exports_external.strictObject({ min: Unit, max: Unit }).refine((band) => band.min <= band.max, { message: "band.min must not exceed band.max" }),
175931
+ approvers: ApproverConfigSchema,
175932
+ title: exports_external.string().min(1).optional(),
175933
+ timeout: HITLTimeoutSchema.optional(),
175934
+ notifications: exports_external.array(NotificationConfigSchema).optional()
175935
+ });
175936
+ var SystemOneDecisionConfigSchema = exports_external.strictObject({
175937
+ provider: exports_external.enum(SYSTEM_ONE_PROVIDER_IDS).default(SYSTEM_ONE_DEFAULT_PROVIDER),
175938
+ model: exports_external.string().min(1).optional(),
175939
+ state: SystemOneStateSchema,
175940
+ timeoutMs: exports_external.number().int().min(SYSTEM_ONE_MIN_TIMEOUT_MS).max(SYSTEM_ONE_MAX_TIMEOUT_MS).default(SYSTEM_ONE_DEFAULT_TIMEOUT_MS),
175941
+ maxRetries: exports_external.number().int().min(0).max(SYSTEM_ONE_MAX_RETRIES_LIMIT).default(SYSTEM_ONE_DEFAULT_MAX_RETRIES),
175942
+ questions: exports_external.record(exports_external.string().regex(QUESTION_ID_RE, "question ids must start with a letter or underscore and use only letters, digits, _ or -"), SystemOneQuestionSchema),
175943
+ returns: exports_external.record(exports_external.string(), exports_external.strictObject({ type: SystemOnePrimitiveTypeSchema })),
175944
+ humanReview: HumanReviewSchema.optional()
175945
+ }).superRefine((config, ctx) => {
175946
+ const questionIds = Object.keys(config.questions);
175947
+ if (questionIds.length === 0) {
175948
+ ctx.addIssue({
175949
+ code: "custom",
175950
+ path: ["questions"],
175951
+ message: "system-one-decision needs at least one question"
175952
+ });
175953
+ }
175954
+ for (const id of questionIds) {
175955
+ if (RESERVED_QUESTION_IDS.has(id)) {
175956
+ ctx.addIssue({
175957
+ code: "custom",
175958
+ path: ["questions", id],
175959
+ message: `"${id}" is reserved and cannot be a question id`
175960
+ });
175961
+ }
175962
+ const declared = Object.hasOwn(config.returns, id) ? config.returns[id] : undefined;
175963
+ if (!declared) {
175964
+ ctx.addIssue({
175965
+ code: "custom",
175966
+ path: ["returns"],
175967
+ message: `returns must declare question "${id}"`
175968
+ });
175969
+ } else if (declared.type !== config.questions[id]?.type) {
175970
+ ctx.addIssue({
175971
+ code: "custom",
175972
+ path: ["returns", id, "type"],
175973
+ message: `returns.${id}.type is "${declared.type}" but question "${id}" is "${config.questions[id]?.type}"`
175974
+ });
175975
+ }
175976
+ }
175977
+ for (const id of Object.keys(config.returns)) {
175978
+ if (!Object.hasOwn(config.questions, id)) {
175979
+ ctx.addIssue({
175980
+ code: "custom",
175981
+ path: ["returns", id],
175982
+ message: `returns declares "${id}" but no question has that id`
175983
+ });
175984
+ }
175985
+ }
175986
+ });
175987
+ var NoulAnswerSchema = exports_external.strictObject({ type: exports_external.literal("noul"), noul: Unit });
175988
+ var ChoiceAnswerSchema = exports_external.strictObject({
175989
+ type: exports_external.literal("choice"),
175990
+ choice: exports_external.string(),
175991
+ probabilities: exports_external.record(exports_external.string(), Unit),
175992
+ confidence: Unit
175993
+ });
175994
+ var ScoreAnswerSchema = exports_external.strictObject({
175995
+ type: exports_external.literal("score"),
175996
+ score: exports_external.number(),
175997
+ legend: exports_external.record(exports_external.string(), SystemOneEntrySchema),
175998
+ probabilities: exports_external.record(exports_external.string(), Unit),
175999
+ confidence: Unit
176000
+ });
176001
+ var SystemOneAnswerSchema = exports_external.discriminatedUnion("type", [
176002
+ NoulAnswerSchema,
176003
+ ChoiceAnswerSchema,
176004
+ ScoreAnswerSchema
176005
+ ]);
176006
+ var ReviewQuestionSchema = exports_external.strictObject({
176007
+ confidence: Unit,
176008
+ inBand: exports_external.boolean(),
176009
+ decidedBy: exports_external.enum(["model", "human"]),
176010
+ modelAnswer: exports_external.union([exports_external.string(), exports_external.number()]).optional()
176011
+ });
176012
+ var ReviewSchema = exports_external.strictObject({
176013
+ status: exports_external.enum(["not_required", "pending", "approved", "rejected", "timeout"]),
176014
+ approvalRequestId: exports_external.string().optional(),
176015
+ reason: exports_external.string().optional(),
176016
+ questions: exports_external.record(exports_external.string(), ReviewQuestionSchema)
176017
+ });
176018
+ var SystemOneDecisionOutputSchema = exports_external.object({
176019
+ model: exports_external.string().min(1),
176020
+ answers: exports_external.record(exports_external.string(), SystemOneAnswerSchema),
176021
+ usage: exports_external.object({
176022
+ input_tokens: exports_external.number().int().min(0),
176023
+ output_tokens: exports_external.number().int().min(0)
176024
+ }),
176025
+ requestId: exports_external.string().optional(),
176026
+ routing: exports_external.strictObject({ model: exports_external.string().min(1) }).optional(),
176027
+ review: ReviewSchema.optional()
176028
+ });
176029
+ function systemOneRetryViolations(node) {
176030
+ if (node.type !== SYSTEM_ONE_DECISION_NODE_TYPE)
176031
+ return [];
176032
+ const violations = [];
176033
+ const attempts = (retry) => retry ? retry.maxRetries ?? ENGINE_RETRY_DEFAULT : 0;
176034
+ if (attempts(node.retry) > 0) {
176035
+ violations.push(`Node "${node.id}" (system-one-decision) must not set retry.maxRetries > 0: the system-one-decision executor retries transient transport errors itself (config.maxRetries), and engine retries would re-send rejected requests`);
176036
+ }
176037
+ if (attempts(node.validation?.retry) > 0) {
176038
+ violations.push(`Node "${node.id}" (system-one-decision) must not set validation.retry.maxRetries > 0: a validation-driven retry would send another paid request`);
176039
+ }
176040
+ return violations;
176041
+ }
176042
+ function systemOneStaticShapeViolations(node) {
176043
+ if (node.type !== SYSTEM_ONE_DECISION_NODE_TYPE)
176044
+ return [];
176045
+ const violations = [];
176046
+ for (const field of ["questions", "returns"]) {
176047
+ const value = node.config[field];
176048
+ if (value !== undefined && (typeof value !== "object" || value === null || Array.isArray(value))) {
176049
+ violations.push(`Node "${node.id}" (system-one-decision) config.${field} must be an object: question ids and return types are static, only state and descriptions may use {{tokens}}`);
176050
+ }
176051
+ }
176052
+ const provider = node.config.provider;
176053
+ if (typeof provider === "string" && provider.includes("{{")) {
176054
+ violations.push(`Node "${node.id}" (system-one-decision) config.provider must be a literal (${SYSTEM_ONE_PROVIDER_IDS.join(", ")}), not a {{token}}: the provider decides which credential is checked before the run starts`);
176055
+ }
176056
+ if (isRecord(node.config.humanReview) && node.next != null) {
176057
+ if (typeof node.next === "string" || Array.isArray(node.next)) {
176058
+ violations.push(`Node "${node.id}" (system-one-decision) sets humanReview, so next must map output ports (${REVIEW_PORTS.join(", ")}): a single or list next would run the same successors after a rejection or a timeout`);
176059
+ } else {
176060
+ const ports = Object.keys(node.next);
176061
+ const unknown2 = ports.filter((port) => !REVIEW_PORTS.includes(port));
176062
+ if (unknown2.length > 0) {
176063
+ violations.push(`Node "${node.id}" (system-one-decision) sets humanReview, so next ports must be ${REVIEW_PORTS.join(", ")}; got ${unknown2.map((port) => `"${port}"`).join(", ")}`);
176064
+ }
176065
+ if (!ports.includes("approved")) {
176066
+ violations.push(`Node "${node.id}" (system-one-decision) sets humanReview, so next must define the "approved" port: it carries every answer that is accepted, by the model or by a person`);
176067
+ }
176068
+ }
176069
+ }
176070
+ return violations;
176071
+ }
176072
+ function systemOneUnresolvedError(nodeId, tokens) {
176073
+ const rendered = [...new Set(tokens)].map((token) => `{{${token}}}`).join(", ");
176074
+ return `SystemOne Decision node "${nodeId}" has unresolved interpolation token(s): ${rendered}. ` + "No request was sent. Declare the value in the node's inputs mapping or fix the path.";
176075
+ }
176076
+
176077
+ class SystemOneContractError extends Error {
176078
+ }
176079
+ function fail(message) {
176080
+ throw new SystemOneContractError(message);
176081
+ }
176082
+ function isRecord(value) {
176083
+ return typeof value === "object" && value !== null && !Array.isArray(value);
176084
+ }
176085
+ function unit(value, what) {
176086
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0 || value > 1) {
176087
+ fail(`${what} must be a finite number between 0 and 1`);
176088
+ }
176089
+ return value;
176090
+ }
176091
+ function distribution(value, keys, what) {
176092
+ if (!isRecord(value))
176093
+ fail(`${what} must be an object`);
176094
+ const actual = Object.keys(value);
176095
+ const missing = keys.filter((key) => !Object.hasOwn(value, key));
176096
+ const extra = actual.filter((key) => !keys.includes(key));
176097
+ if (missing.length > 0 || extra.length > 0) {
176098
+ fail(`${what} keys must be exactly the declared ${keys.length} option(s)` + (missing.length > 0 ? `; missing ${missing.length}` : "") + (extra.length > 0 ? `; ${extra.length} unexpected` : ""));
176099
+ }
176100
+ const out = {};
176101
+ let sum = 0;
176102
+ for (const key of keys) {
176103
+ const p = unit(value[key], `${what}["${key}"]`);
176104
+ out[key] = p;
176105
+ sum += p;
176106
+ }
176107
+ if (Math.abs(sum - 1) > DISTRIBUTION_TOLERANCE) {
176108
+ fail(`${what} must sum to 1 (within ${DISTRIBUTION_TOLERANCE})`);
176109
+ }
176110
+ return out;
176111
+ }
176112
+ function validateAnswer(id, question, raw, confidenceField) {
176113
+ const at = `answer "${id}"`;
176114
+ if (!isRecord(raw))
176115
+ fail(`${at} must be an object`);
176116
+ if (raw.type !== question.type) {
176117
+ fail(`${at} has type ${JSON.stringify(raw.type)} but the question declares "${question.type}"`);
176118
+ }
176119
+ switch (question.type) {
176120
+ case "noul":
176121
+ return { type: "noul", noul: unit(raw.noul, `${at}.noul`) };
176122
+ case "choice": {
176123
+ const options = Object.keys(question.criteria);
176124
+ if (typeof raw.choice !== "string" || !Object.hasOwn(question.criteria, raw.choice)) {
176125
+ fail(`${at}.choice is not one of the declared options`);
176126
+ }
176127
+ return {
176128
+ type: "choice",
176129
+ choice: raw.choice,
176130
+ probabilities: distribution(raw.probabilities, options, `${at}.probabilities`),
176131
+ confidence: unit(raw[confidenceField], `${at}.${confidenceField}`)
176132
+ };
176133
+ }
176134
+ case "score": {
176135
+ const indices = question.criteria.map((_, index) => String(index));
176136
+ const top = indices.length - 1;
176137
+ if (typeof raw.score !== "number" || !Number.isFinite(raw.score) || raw.score < 0 || raw.score > top) {
176138
+ fail(`${at}.score must be a finite number between 0 and ${top}`);
176139
+ }
176140
+ if (!isRecord(raw.legend))
176141
+ fail(`${at}.legend must be an object`);
176142
+ const legend = {};
176143
+ for (const key of indices) {
176144
+ if (!Object.hasOwn(raw.legend, key))
176145
+ fail(`${at}.legend is missing level ${key}`);
176146
+ const entry = SystemOneEntrySchema.safeParse(raw.legend[key]);
176147
+ if (!entry.success)
176148
+ fail(`${at}.legend["${key}"] must be a string, object, array, or null`);
176149
+ legend[key] = entry.data;
176150
+ }
176151
+ return {
176152
+ type: "score",
176153
+ score: raw.score,
176154
+ legend,
176155
+ probabilities: distribution(raw.probabilities, indices, `${at}.probabilities`),
176156
+ confidence: unit(raw[confidenceField], `${at}.${confidenceField}`)
176157
+ };
176158
+ }
176159
+ }
176160
+ }
176161
+ var MAX_ROUTING_MODEL_CHARS = 128;
176162
+ function readRoutingModel(routing) {
176163
+ if (!isRecord(routing))
176164
+ return;
176165
+ const { model } = routing;
176166
+ return typeof model === "string" && model !== "" && model.length <= MAX_ROUTING_MODEL_CHARS ? model : undefined;
176167
+ }
176168
+ function validateSystemOneResponse(questions, body, requestId, confidenceField = "confidence") {
176169
+ if (!isRecord(body))
176170
+ fail("response body must be a JSON object");
176171
+ if (typeof body.model !== "string" || body.model === "") {
176172
+ fail("response is missing the model that produced the answers");
176173
+ }
176174
+ if (!isRecord(body.answers))
176175
+ fail("response is missing the answers object");
176176
+ const usage = exports_external.object({ input_tokens: exports_external.number().int().min(0), output_tokens: exports_external.number().int().min(0) }).safeParse(body.usage);
176177
+ if (!usage.success)
176178
+ fail("response usage must report non-negative integer input_tokens and output_tokens");
176179
+ const declared = Object.keys(questions);
176180
+ const unexpected = Object.keys(body.answers).filter((id) => !Object.hasOwn(questions, id));
176181
+ if (unexpected.length > 0)
176182
+ fail(`response contains ${unexpected.length} answer(s) for undeclared questions`);
176183
+ const answers = {};
176184
+ for (const id of declared) {
176185
+ if (!Object.hasOwn(body.answers, id))
176186
+ fail(`response is missing the answer for question "${id}"`);
176187
+ const question = questions[id];
176188
+ if (!question)
176189
+ fail(`question "${id}" is not defined`);
176190
+ answers[id] = validateAnswer(id, question, body.answers[id], confidenceField);
176191
+ }
176192
+ if (declared.length === 0)
176193
+ fail("a system-one-decision call needs at least one question");
176194
+ const routingModel = readRoutingModel(body.routing);
176195
+ return {
176196
+ model: body.model,
176197
+ answers,
176198
+ usage: usage.data,
176199
+ ...requestId ? { requestId } : {},
176200
+ ...routingModel ? { routing: { model: routingModel } } : {}
176201
+ };
176202
+ }
176203
+ var REVIEW_CONFIRM_ID = "$confirm";
176204
+ var REVIEW_STATE_CHARS = 2000;
176205
+ var REVIEW_LABEL_CHARS = 160;
176206
+ var REVIEW_OPTION_CHARS = 200;
176207
+ var round6 = (value) => Math.round(value * 1e6) / 1e6;
176208
+ function answerConfidence(answer) {
176209
+ return answer.type === "noul" ? round6(Math.max(answer.noul, 1 - answer.noul)) : answer.confidence;
176210
+ }
176211
+ function clip(text, max) {
176212
+ return text.length > max ? `${text.slice(0, max - 1)}…` : text;
176213
+ }
176214
+ function showEntry(entry, max) {
176215
+ return clip(typeof entry === "string" ? entry : JSON.stringify(entry) ?? "", max);
176216
+ }
176217
+ function modelAnswerOf(answer) {
176218
+ return answer.type === "choice" ? answer.choice : answer.type === "score" ? answer.score : answer.noul;
176219
+ }
176220
+ function buildReviewCard(nodeId, config, review, parked) {
176221
+ const state = scrubSecrets(typeof config.state === "string" ? config.state : JSON.stringify(config.state) ?? "");
176222
+ const questions = [
176223
+ {
176224
+ id: REVIEW_CONFIRM_ID,
176225
+ type: "approval",
176226
+ label: "Accept these answers and continue?",
176227
+ required: true,
176228
+ description: `Model ${parked.model}. Input: ${clip(state, REVIEW_STATE_CHARS)}`
176229
+ }
176230
+ ];
176231
+ for (const [id, info] of Object.entries(parked.review?.questions ?? {})) {
176232
+ if (!info.inBand)
176233
+ continue;
176234
+ const question = config.questions[id];
176235
+ const answer = parked.answers[id];
176236
+ if (!question || !answer)
176237
+ continue;
176238
+ const label = `${id}: ${showEntry(question.instructions, REVIEW_LABEL_CHARS)}`;
176239
+ const said = `The model answered ${JSON.stringify(modelAnswerOf(answer))} at confidence ${info.confidence}.`;
176240
+ if (question.type === "choice" && answer.type === "choice") {
176241
+ questions.push({
176242
+ id,
176243
+ type: "single-select",
176244
+ label,
176245
+ required: false,
176246
+ description: `${said} Leave empty to confirm it, or pick another option.`,
176247
+ options: Object.entries(question.criteria).map(([value, entry]) => ({
176248
+ value,
176249
+ label: value,
176250
+ ...typeof entry === "string" && entry ? { description: clip(entry, REVIEW_OPTION_CHARS) } : {}
176251
+ }))
176252
+ });
176253
+ } else if (question.type === "score" && answer.type === "score") {
176254
+ questions.push({
176255
+ id,
176256
+ type: "single-select",
176257
+ label,
176258
+ required: false,
176259
+ description: `${said} Leave empty to confirm it, or pick a level.`,
176260
+ options: question.criteria.map((entry, level) => ({
176261
+ value: String(level),
176262
+ label: `${level}: ${showEntry(entry, REVIEW_OPTION_CHARS)}`
176263
+ }))
176264
+ });
176265
+ } else if (question.type === "noul" && answer.type === "noul") {
176266
+ questions.push({
176267
+ id,
176268
+ type: "boolean",
176269
+ label,
176270
+ required: false,
176271
+ defaultValue: answer.noul >= 0.5,
176272
+ description: `${said} The switch starts on the side the model took.`
176273
+ });
176274
+ }
176275
+ }
176276
+ return {
176277
+ title: review.title ?? `Review decision: ${nodeId}`,
176278
+ questions,
176279
+ approvers: review.approvers,
176280
+ ...review.timeout ? { timeout: review.timeout } : {},
176281
+ ...review.notifications ? { notifications: review.notifications } : {}
176282
+ };
176283
+ }
176284
+ function readHumanAnswer(answer, response) {
176285
+ if (response === undefined || response === null || response === "")
176286
+ return { kind: "confirm" };
176287
+ switch (answer.type) {
176288
+ case "choice":
176289
+ if (typeof response !== "string" || !Object.hasOwn(answer.probabilities, response)) {
176290
+ return { kind: "invalid" };
176291
+ }
176292
+ return response === answer.choice ? { kind: "confirm" } : { kind: "override", answer: { ...answer, choice: response } };
176293
+ case "score": {
176294
+ if (typeof response !== "string" || !Object.hasOwn(answer.legend, response)) {
176295
+ return { kind: "invalid" };
176296
+ }
176297
+ const level = Number(response);
176298
+ return level === answer.score ? { kind: "confirm" } : { kind: "override", answer: { ...answer, score: level } };
176299
+ }
176300
+ case "noul":
176301
+ if (typeof response !== "boolean")
176302
+ return { kind: "invalid" };
176303
+ return response === answer.noul >= 0.5 ? { kind: "confirm" } : { kind: "override", answer: { ...answer, noul: response ? 1 : 0 } };
176304
+ }
176305
+ }
176306
+ function resolveReviewedDecision(parkedOutput, approval) {
176307
+ const parked = SystemOneDecisionOutputSchema.safeParse(parkedOutput);
176308
+ if (!parked.success || parked.data.review?.status !== "pending")
176309
+ return null;
176310
+ const decision = parked.data;
176311
+ const parkedQuestions = decision.review?.questions ?? {};
176312
+ const finish = (status, answers2, questions2, reason) => ({
176313
+ output: {
176314
+ ...decision,
176315
+ answers: answers2,
176316
+ review: {
176317
+ status,
176318
+ approvalRequestId: approval.requestId,
176319
+ ...reason ? { reason } : {},
176320
+ questions: questions2
176321
+ }
176322
+ },
176323
+ nextPort: status
176324
+ });
176325
+ if (approval.status !== "approved") {
176326
+ return finish(approval.status, decision.answers, parkedQuestions);
176327
+ }
176328
+ const answers = { ...decision.answers };
176329
+ const questions = { ...parkedQuestions };
176330
+ for (const [id, info] of Object.entries(parkedQuestions)) {
176331
+ const modelAnswer = decision.answers[id];
176332
+ if (!info.inBand || !modelAnswer)
176333
+ continue;
176334
+ const human = readHumanAnswer(modelAnswer, approval.responses?.[id]);
176335
+ if (human.kind === "invalid") {
176336
+ return finish("rejected", decision.answers, parkedQuestions, `The response for "${id}" is not one of its options`);
176337
+ }
176338
+ if (human.kind === "override")
176339
+ answers[id] = human.answer;
176340
+ questions[id] = { ...info, decidedBy: "human", modelAnswer: modelAnswerOf(modelAnswer) };
176341
+ }
176342
+ return finish("approved", answers, questions);
176343
+ }
176344
+ var REQUEST_ID_RE = /^[A-Za-z0-9._:-]{1,128}$/;
176345
+ var ERROR_CODE_RE = /^[A-Za-z0-9._:-]{1,64}$/;
176346
+ function readRequestId(headers) {
176347
+ const value = headers.get("x-request-id") ?? headers.get("request-id");
176348
+ return value && REQUEST_ID_RE.test(value) ? value : undefined;
176349
+ }
176350
+ function parseRetryAfter(value, now) {
176351
+ if (!value)
176352
+ return;
176353
+ const trimmed = value.trim();
176354
+ if (/^\d+(\.\d+)?$/.test(trimmed))
176355
+ return Math.round(Number(trimmed) * 1000);
176356
+ const at = Date.parse(trimmed);
176357
+ return Number.isNaN(at) ? undefined : Math.max(0, at - now);
176358
+ }
176359
+ function readErrorCode(text) {
176360
+ if (text.length === 0 || text.length > MAX_ERROR_BODY_CHARS)
176361
+ return;
176362
+ let parsed;
176363
+ try {
176364
+ parsed = JSON.parse(text);
176365
+ } catch {
176366
+ return;
176367
+ }
176368
+ if (!isRecord(parsed))
176369
+ return;
176370
+ const nested = isRecord(parsed.error) ? parsed.error : undefined;
176371
+ const detail = isRecord(parsed.detail) ? parsed.detail : undefined;
176372
+ for (const candidate of [
176373
+ nested?.code,
176374
+ nested?.type,
176375
+ detail?.error_type,
176376
+ parsed.code,
176377
+ parsed.type
176378
+ ]) {
176379
+ if (typeof candidate === "string" && ERROR_CODE_RE.test(candidate))
176380
+ return candidate;
176381
+ }
176382
+ return;
176383
+ }
176384
+ function defaultSleep(ms, signal) {
176385
+ return new Promise((resolve) => {
176386
+ if (signal.aborted)
176387
+ return resolve();
176388
+ const timer = setTimeout(done, ms);
176389
+ function done() {
176390
+ clearTimeout(timer);
176391
+ signal.removeEventListener("abort", done);
176392
+ resolve();
176393
+ }
176394
+ signal.addEventListener("abort", done, { once: true });
176395
+ });
176396
+ }
176397
+
176398
+ class SystemOneDecisionExecutor extends BaseExecutor {
176399
+ options;
176400
+ type = SYSTEM_ONE_DECISION_NODE_TYPE;
176401
+ mode = "async";
176402
+ configSchema = SystemOneDecisionConfigSchema;
176403
+ outputSchema = SystemOneDecisionOutputSchema;
176404
+ constructor(deps, options = {}) {
176405
+ super(deps);
176406
+ this.options = options;
176407
+ }
176408
+ providerContext() {
176409
+ return { db: this.deps.db, env: this.options.env ?? process.env };
176410
+ }
176411
+ resolveTarget(id) {
176412
+ return resolveSystemOneTarget(id, this.providerContext(), {
176413
+ apiKey: this.options.getApiKey,
176414
+ serverUrl: this.options.getServerUrl
176415
+ });
176416
+ }
176417
+ async checkReadiness(nodes) {
176418
+ const nodeIdsByProvider = new Map;
176419
+ for (const node of nodes) {
176420
+ const id = systemOneProviderOf(node.config);
176421
+ if (id)
176422
+ nodeIdsByProvider.set(id, [...nodeIdsByProvider.get(id) ?? [], node.id]);
176423
+ }
176424
+ const problems = [];
176425
+ for (const [id, nodeIds] of nodeIdsByProvider) {
176426
+ const target = await this.resolveTarget(id);
176427
+ if (!target.ok)
176428
+ problems.push({ nodeIds, message: target.error });
176429
+ }
176430
+ return problems;
176431
+ }
176432
+ async execute(config, context, meta) {
176433
+ if (config.humanReview) {
176434
+ const existing = await this.deps.db.getApprovalRequestByStepId(meta.stepId);
176435
+ if (existing) {
176436
+ return this.handOffToReviewer(config, await this.readParked(meta.stepId), context, meta);
176437
+ }
176438
+ }
176439
+ const providerId = config.provider;
176440
+ const provider = SYSTEM_ONE_PROVIDERS[providerId];
176441
+ const target = await this.resolveTarget(providerId);
176442
+ if (!target.ok)
176443
+ return { status: "failed", error: target.error };
176444
+ const { apiKey, endpoint } = target;
176445
+ const model = config.model ?? provider.defaultModel;
176446
+ const body = JSON.stringify({
176447
+ state: config.state,
176448
+ ...model === undefined ? {} : { model },
176449
+ questions: config.questions
176450
+ });
176451
+ const scrub = (message) => message.split(apiKey).join("[REDACTED]");
176452
+ const sent = await this.send(providerId, endpoint, apiKey, body, config.timeoutMs, config.maxRetries);
176453
+ if (!sent.ok)
176454
+ return { status: "failed", error: scrub(sent.error) };
176455
+ let parsed;
176456
+ try {
176457
+ parsed = JSON.parse(sent.text);
176458
+ } catch {
176459
+ return { status: "failed", error: "SystemOne response was not valid JSON" };
176460
+ }
176461
+ let decision;
176462
+ try {
176463
+ decision = validateSystemOneResponse(config.questions, parsed, sent.requestId, provider.confidenceField);
176464
+ } catch (err) {
176465
+ if (err instanceof SystemOneContractError) {
176466
+ return {
176467
+ status: "failed",
176468
+ error: scrub(`SystemOne response failed validation: ${err.message}`)
176469
+ };
176470
+ }
176471
+ throw err;
176472
+ }
176473
+ if (!config.humanReview)
176474
+ return { status: "success", output: decision };
176475
+ return this.reviewDecision(config, config.humanReview, decision, context, meta);
176476
+ }
176477
+ async reviewDecision(config, review, decision, context, meta) {
176478
+ const questions = {};
176479
+ for (const [id, answer] of Object.entries(decision.answers)) {
176480
+ const confidence = answerConfidence(answer);
176481
+ questions[id] = {
176482
+ confidence,
176483
+ inBand: confidence >= review.band.min && confidence <= review.band.max,
176484
+ decidedBy: "model"
176485
+ };
176486
+ }
176487
+ if (!Object.values(questions).some((question) => question.inBand)) {
176488
+ return {
176489
+ status: "success",
176490
+ output: { ...decision, review: { status: "not_required", questions } },
176491
+ nextPort: "approved"
176492
+ };
176493
+ }
176494
+ const parked = {
176495
+ ...decision,
176496
+ review: { status: "pending", questions }
176497
+ };
176498
+ await this.deps.db.updateWorkflowRunStep(meta.stepId, { output: parked });
176499
+ return this.handOffToReviewer(config, parked, context, meta);
176500
+ }
176501
+ async readParked(stepId) {
176502
+ const step = await this.deps.db.getWorkflowRunStep(stepId);
176503
+ const parked = SystemOneDecisionOutputSchema.safeParse(step?.output);
176504
+ return parked.success && parked.data.review?.status === "pending" ? parked.data : null;
176505
+ }
176506
+ async handOffToReviewer(config, parked, context, meta) {
176507
+ if (!parked || !config.humanReview) {
176508
+ return {
176509
+ status: "failed",
176510
+ error: "The decision this step parked with is missing, so its approval cannot be resumed. Run the node again."
176511
+ };
176512
+ }
176513
+ const result = await new HumanInTheLoopExecutor(this.deps).run({
176514
+ config: buildReviewCard(meta.nodeId, config, config.humanReview, parked),
176515
+ context,
176516
+ meta
176517
+ });
176518
+ if (result.status === "failed")
176519
+ return { status: "failed", error: result.error };
176520
+ if ("async" in result)
176521
+ return result;
176522
+ const answered = result.output;
176523
+ const outcome = answered ? this.resolveApproval(parked, {
176524
+ requestId: answered.requestId,
176525
+ status: answered.status,
176526
+ responses: answered.responses
176527
+ }) : null;
176528
+ if (!outcome) {
176529
+ return {
176530
+ status: "failed",
176531
+ error: "The approval was answered but its result could not be applied"
176532
+ };
176533
+ }
176534
+ return {
176535
+ status: "success",
176536
+ output: outcome.output,
176537
+ nextPort: outcome.nextPort
176538
+ };
176539
+ }
176540
+ resolveApproval(parkedOutput, approval) {
176541
+ return resolveReviewedDecision(parkedOutput, approval);
176542
+ }
176543
+ async send(providerId, endpoint, apiKey, body, timeoutMs, maxRetries) {
176544
+ const doFetch = this.options.fetch ?? fetch;
176545
+ const sleep = this.options.sleep ?? defaultSleep;
176546
+ const now = this.options.now ?? Date.now;
176547
+ const random = this.options.random ?? Math.random;
176548
+ const deadlineAt = now() + timeoutMs - DEADLINE_MARGIN_MS;
176549
+ const controller = new AbortController;
176550
+ const timer = setTimeout(() => controller.abort(), Math.max(0, deadlineAt - now()));
176551
+ const timedOut = () => ({
176552
+ ok: false,
176553
+ error: `SystemOne request exceeded its ${timeoutMs}ms time budget`
176554
+ });
176555
+ try {
176556
+ for (let attempt = 0;; attempt++) {
176557
+ const result = await this.attemptOnce(doFetch, providerId, endpoint, apiKey, body, controller.signal, now);
176558
+ if (result.kind === "ok") {
176559
+ return { ok: true, text: result.text, requestId: result.requestId };
176560
+ }
176561
+ if (result.kind === "timeout" || controller.signal.aborted)
176562
+ return timedOut();
176563
+ const attempts = attempt + 1;
176564
+ const suffix = attempts > 1 ? ` after ${attempts} attempts` : "";
176565
+ if (!result.retryable || attempt >= maxRetries) {
176566
+ return { ok: false, error: `${result.message}${suffix}` };
176567
+ }
176568
+ const backoff = Math.min(BACKOFF_CAP_MS, BACKOFF_BASE_MS * 2 ** attempt);
176569
+ const delay = result.retryAfterMs ?? Math.round(backoff * (0.5 + random() * 0.5));
176570
+ if (delay >= deadlineAt - now()) {
176571
+ return {
176572
+ ok: false,
176573
+ error: `${result.message}${suffix}; the ${delay}ms retry delay does not fit the ${timeoutMs}ms time budget`
176574
+ };
176575
+ }
176576
+ await sleep(delay, controller.signal);
176577
+ if (controller.signal.aborted)
176578
+ return timedOut();
176579
+ }
176580
+ } finally {
176581
+ clearTimeout(timer);
176582
+ }
176583
+ }
176584
+ async attemptOnce(doFetch, providerId, endpoint, apiKey, body, signal, now) {
176585
+ let res;
176586
+ try {
176587
+ res = await doFetch(endpoint, {
176588
+ method: "POST",
176589
+ headers: {
176590
+ "content-type": "application/json",
176591
+ accept: "application/json",
176592
+ authorization: `Bearer ${apiKey}`
176593
+ },
176594
+ body,
176595
+ redirect: "manual",
176596
+ signal
176597
+ });
176598
+ } catch (err) {
176599
+ if (signal.aborted)
176600
+ return { kind: "timeout" };
176601
+ const code2 = err?.code;
176602
+ const detail2 = typeof code2 === "string" && /^[A-Z0-9_]{3,40}$/.test(code2) ? ` (${code2})` : "";
176603
+ return {
176604
+ kind: "fail",
176605
+ message: `SystemOne request failed: network error${detail2}`,
176606
+ retryable: true
176607
+ };
176608
+ }
176609
+ const requestId = readRequestId(res.headers);
176610
+ const withId = (message) => requestId ? `${message} [request ${requestId}]` : message;
176611
+ if (res.status >= 200 && res.status < 300) {
176612
+ let text;
176613
+ try {
176614
+ text = await res.text();
176615
+ } catch {
176616
+ if (signal.aborted)
176617
+ return { kind: "timeout" };
176618
+ return {
176619
+ kind: "fail",
176620
+ message: withId("SystemOne response body could not be read"),
176621
+ retryable: true
176622
+ };
176623
+ }
176624
+ if (text.length > MAX_RESPONSE_CHARS) {
176625
+ return {
176626
+ kind: "fail",
176627
+ message: withId("SystemOne response exceeded the size limit"),
176628
+ retryable: false
176629
+ };
176630
+ }
176631
+ return { kind: "ok", text, requestId };
176632
+ }
176633
+ if (res.status >= 300 && res.status < 400) {
176634
+ return {
176635
+ kind: "fail",
176636
+ message: withId(`SystemOne request was redirected (HTTP ${res.status}); redirects are refused`),
176637
+ retryable: false
176638
+ };
176639
+ }
176640
+ let errorText = "";
176641
+ try {
176642
+ errorText = await res.text();
176643
+ } catch {
176644
+ if (signal.aborted)
176645
+ return { kind: "timeout" };
176646
+ }
176647
+ const code = readErrorCode(errorText);
176648
+ if (res.status === 401 || res.status === 403) {
176649
+ return {
176650
+ kind: "fail",
176651
+ message: withId(systemOneKeyRejectedMessage(providerId, res.status, code)),
176652
+ retryable: false
176653
+ };
176654
+ }
176655
+ const detail = code ? ` (${code})` : "";
176656
+ const retryable = res.status === 408 || res.status === 429 || res.status >= 500;
176657
+ return {
176658
+ kind: "fail",
176659
+ message: withId(`SystemOne API returned HTTP ${res.status}${detail}`),
176660
+ retryable,
176661
+ retryAfterMs: retryable ? parseRetryAfter(res.headers.get("retry-after"), now()) : undefined
176662
+ };
176663
+ }
176664
+ }
176665
+
175178
176666
  // src/workflows/definition.ts
175179
176667
  function getNextTargets(next) {
175180
176668
  if (typeof next === "string")
@@ -175307,6 +176795,7 @@ function validateDefinition(def, registry, options = {}) {
175307
176795
  if (node.type === "human-in-the-loop" && typeof node.config.questions === "string" && !/^\{\{[^}]+\}\}$/.test(node.config.questions.trim())) {
175308
176796
  errors.push(`Node "${node.id}" human-in-the-loop config.questions must be an array or one exact {{interpolation}} token`);
175309
176797
  }
176798
+ errors.push(...systemOneStaticShapeViolations(node), ...systemOneRetryViolations(node));
175310
176799
  if (node.type === "foreach") {
175311
176800
  validateForeachNode(node, errors);
175312
176801
  if (node.id.includes("#")) {
@@ -182044,25 +183533,25 @@ init_db();
182044
183533
 
182045
183534
  // src/apps/format-upgrades.ts
182046
183535
  var CURRENT_APP_SCHEMA_VERSION = 1;
182047
- function isRecord(value) {
183536
+ function isRecord2(value) {
182048
183537
  return typeof value === "object" && value !== null && !Array.isArray(value);
182049
183538
  }
182050
183539
  function upgradeFrom0(raw) {
182051
183540
  const upgraded = { ...raw };
182052
- if (isRecord(upgraded.page) && !Object.hasOwn(upgraded, "pages")) {
183541
+ if (isRecord2(upgraded.page) && !Object.hasOwn(upgraded, "pages")) {
182053
183542
  upgraded.pages = { main: upgraded.page };
182054
183543
  upgraded.defaultPage = "main";
182055
183544
  }
182056
183545
  delete upgraded.page;
182057
- if (isRecord(upgraded.models)) {
183546
+ if (isRecord2(upgraded.models)) {
182058
183547
  upgraded.models = Object.fromEntries(Object.entries(upgraded.models).map(([modelName, model]) => {
182059
- if (!isRecord(model))
183548
+ if (!isRecord2(model))
182060
183549
  return [modelName, model];
182061
183550
  const upgradedModel = { ...model };
182062
183551
  delete upgradedModel.sources;
182063
- if (isRecord(upgradedModel.columns)) {
183552
+ if (isRecord2(upgradedModel.columns)) {
182064
183553
  upgradedModel.columns = Object.fromEntries(Object.entries(upgradedModel.columns).map(([columnName, column]) => {
182065
- if (!isRecord(column))
183554
+ if (!isRecord2(column))
182066
183555
  return [columnName, column];
182067
183556
  const upgradedColumn = { ...column };
182068
183557
  delete upgradedColumn.source;
@@ -182077,13 +183566,13 @@ function upgradeFrom0(raw) {
182077
183566
  }
182078
183567
  var APP_FORMAT_UPGRADES = [{ from: 0, to: 1, upgrade: upgradeFrom0 }];
182079
183568
  function schemaVersionOf(raw) {
182080
- if (!isRecord(raw) || typeof raw.schemaVersion !== "number" || !Number.isInteger(raw.schemaVersion)) {
183569
+ if (!isRecord2(raw) || typeof raw.schemaVersion !== "number" || !Number.isInteger(raw.schemaVersion)) {
182081
183570
  return 0;
182082
183571
  }
182083
183572
  return raw.schemaVersion;
182084
183573
  }
182085
183574
  function upgradeAppDefinition(raw) {
182086
- if (!isRecord(raw))
183575
+ if (!isRecord2(raw))
182087
183576
  return raw;
182088
183577
  let upgraded = raw;
182089
183578
  let version = schemaVersionOf(upgraded);
@@ -182667,6 +184156,21 @@ export interface SwarmSdk {
182667
184156
  config_set(args: { key: string; value: unknown; scope?: "global" | "agent" | "repo"; scopeId?: string; isSecret?: boolean }): Promise<unknown>;
182668
184157
  config_delete(args: { id: string }): Promise<unknown>;
182669
184158
 
184159
+ // --- write: model catalog ---
184160
+ modelCatalog_refresh(args?: { force?: boolean }): Promise<unknown>;
184161
+ modelCatalog_overlayUpsert(args: {
184162
+ provider: string;
184163
+ modelId: string;
184164
+ name?: string;
184165
+ releaseDate?: string;
184166
+ contextWindow?: number;
184167
+ maxOutput?: number;
184168
+ reasoningOptions?: Array<{ type: string; values?: string[] }>;
184169
+ pricing?: { input?: number; output?: number; cache_read?: number; cache_write?: number };
184170
+ reason: string;
184171
+ verifiedBy?: string;
184172
+ }): Promise<unknown>;
184173
+
182670
184174
  // --- write: slack ---
182671
184175
  slack_post(args: { channelId: string; message: string; blocks?: unknown }): Promise<unknown>;
182672
184176
  slack_reply(args: { channelId?: string; threadTs?: string; message: string; taskId?: string; blocks?: unknown }): Promise<unknown>;
@@ -183405,4 +184909,4 @@ void _scriptMain;
183405
184909
  });
183406
184910
  }
183407
184911
 
183408
- export { require_dist, isInvalidClientError, assertUrlSafe, publicEndpointSsrfOptions, discoverProtectedResourceMetadata, discoverAuthorizationServerMetadata, normalizeTokenEndpointAuthMethod, resolveAdvertisedTokenEndpointAuthMethod, authMethodForStoredClient, selectDcrTokenEndpointAuthMethod, registerClient, buildAuthorizeUrl, exchangeCodeForTokens, refreshMcpToken, revokeMcpToken, computeExpiresAt, getMcpOAuthToken, findReusableMcpOAuthClient, invalidateMcpOAuthClient, upsertMcpOAuthToken, applyMcpOAuthRefresh, markMcpOAuthTokenStatus, deleteMcpOAuthToken, insertMcpOAuthPending, consumeMcpOAuthPending, gcMcpOAuthPending, setMcpServerAuthMethod, ensureMcpToken, callMcpServerTool, listVendoredOpenapiEntries, ConnectionAuthInputSchema, connectionAuthSummary, listRelationalCredentialBindings, getCredentialBindingById, findCredentialBindingByIdentity, upsertCredentialBinding, disableCredentialBinding, listScriptConnections, listScriptConnectionsAsync, getScriptConnectionById, ScriptConnectionConflictError, connectionAuthInputFromFlat, upsertScriptConnection, refreshScriptConnection, setScriptConnectionEnabled, getScriptApiConnectionDescriptors, getScriptMcpConnectionDescriptors, getScriptApiTypes, getScriptMcpTypes, oauthAppToProviderConfig, getOAuthProviderConfig, getOAuthBindingTokenStatus, buildScriptCredentialBindingsWithFailures, buildScriptCredentialBindings, upsertScriptByName, getScript, getScriptById, getScriptVersion, listScripts, listScriptVersions, deleteScript, touchScratchScriptLastUsed, restoreScratchScriptLastUsedIfUnchanged, createScriptApi, listScriptApisForScript, getScriptApiById, getScriptApiSecret, updateScriptApi, rotateScriptApiSecret, deleteScriptApi, recordScriptApiUsage, buildSandboxedCommand, sandboxSpawnEnv, createCappedStreamState, snapshotCapped, readStreamCapped, writeBareImportShim, MIN_SCRIPT_WALL_CLOCK_MS, SCRIPT_LONG_TIMEOUT_HINT_MS, MAX_SCRIPT_WALL_CLOCK_MS, DEFAULT_SCRIPT_RESOURCES, require_typescript, checkImportAllowlist, validateScriptImports, runScript, getNextTargets, generateEdges, findEntryNodes, resolveValidationPort, getSuccessors, definitionNodeIds, validateDefinition, applyDefinitionPatch, extractScriptSignature, extractArgsJsonSchema, getSavedScriptOwnerAgentId, runSavedScriptAsAgent, resolveSyncRunAs, AppNameSchema, ColumnKindSchema, isIso8601Date, SYSTEM_COLUMN_KINDS, SORTABLE_SYSTEM_DATE_COLUMNS, AppElementsSchema, AppDefinitionSchema, collectScriptReferences, parseAppDefinition, applyAppDefinitionPatch, upgradeAppDefinition, decodeAppDefinition, appDefinitionNeedsRepair, createApp, getApp, listApps, listAppRecords, updateApp, deleteApp, getScriptAppTypes, SCRIPT_SDK_TYPES, scriptSdkTypesWithGeneratedApis, SCRIPT_STDLIB_MODULE_TYPES, scriptStdlibTypesWithGeneratedApis, typecheckWithAmbient, typecheckScript };
184912
+ export { require_dist, isInvalidClientError, assertUrlSafe, publicEndpointSsrfOptions, discoverProtectedResourceMetadata, discoverAuthorizationServerMetadata, normalizeTokenEndpointAuthMethod, resolveAdvertisedTokenEndpointAuthMethod, authMethodForStoredClient, selectDcrTokenEndpointAuthMethod, registerClient, buildAuthorizeUrl, exchangeCodeForTokens, refreshMcpToken, revokeMcpToken, computeExpiresAt, getMcpOAuthToken, findReusableMcpOAuthClient, invalidateMcpOAuthClient, upsertMcpOAuthToken, applyMcpOAuthRefresh, markMcpOAuthTokenStatus, deleteMcpOAuthToken, insertMcpOAuthPending, consumeMcpOAuthPending, gcMcpOAuthPending, setMcpServerAuthMethod, ensureMcpToken, callMcpServerTool, listVendoredOpenapiEntries, ConnectionAuthInputSchema, connectionAuthSummary, listRelationalCredentialBindings, getCredentialBindingById, findCredentialBindingByIdentity, upsertCredentialBinding, disableCredentialBinding, listScriptConnections, listScriptConnectionsAsync, getScriptConnectionById, ScriptConnectionConflictError, connectionAuthInputFromFlat, upsertScriptConnection, refreshScriptConnection, setScriptConnectionEnabled, getScriptApiConnectionDescriptors, getScriptMcpConnectionDescriptors, getScriptApiTypes, getScriptMcpTypes, oauthAppToProviderConfig, getOAuthProviderConfig, getOAuthBindingTokenStatus, buildScriptCredentialBindingsWithFailures, buildScriptCredentialBindings, upsertScriptByName, getScript, getScriptById, getScriptVersion, listScripts, listScriptVersions, deleteScript, touchScratchScriptLastUsed, restoreScratchScriptLastUsedIfUnchanged, createScriptApi, listScriptApisForScript, getScriptApiById, getScriptApiSecret, updateScriptApi, rotateScriptApiSecret, deleteScriptApi, recordScriptApiUsage, buildSandboxedCommand, sandboxSpawnEnv, createCappedStreamState, snapshotCapped, readStreamCapped, writeBareImportShim, MIN_SCRIPT_WALL_CLOCK_MS, SCRIPT_LONG_TIMEOUT_HINT_MS, MAX_SCRIPT_WALL_CLOCK_MS, DEFAULT_SCRIPT_RESOURCES, require_typescript, checkImportAllowlist, validateScriptImports, runScript, BaseExecutor, postApprovalCancellationUpdates, createApprovalFollowUpTask, HumanInTheLoopExecutor, resolveWorkflowLlmConfig, SYSTEM_ONE_DECISION_NODE_TYPE, systemOneRetryViolations, systemOneUnresolvedError, SystemOneDecisionExecutor, getNextTargets, generateEdges, findEntryNodes, resolveValidationPort, getSuccessors, definitionNodeIds, validateDefinition, applyDefinitionPatch, extractScriptSignature, extractArgsJsonSchema, getSavedScriptOwnerAgentId, runSavedScriptAsAgent, resolveSyncRunAs, AppNameSchema, ColumnKindSchema, isIso8601Date, SYSTEM_COLUMN_KINDS, SORTABLE_SYSTEM_DATE_COLUMNS, AppElementsSchema, AppDefinitionSchema, collectScriptReferences, parseAppDefinition, applyAppDefinitionPatch, upgradeAppDefinition, decodeAppDefinition, appDefinitionNeedsRepair, createApp, getApp, listApps, listAppRecords, updateApp, deleteApp, getScriptAppTypes, SCRIPT_SDK_TYPES, scriptSdkTypesWithGeneratedApis, SCRIPT_STDLIB_MODULE_TYPES, scriptStdlibTypesWithGeneratedApis, typecheckWithAmbient, typecheckScript };