@desplega.ai/agent-swarm 2.5.4 → 2.7.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 (354) hide show
  1. package/README.md +4 -2
  2. package/dist/{acp-adapter-ek38cwsv.js → acp-adapter-ma1js5n7.js} +9 -9
  3. package/dist/{actions-92mepq03.js → actions-1vhmtvg9.js} +21 -21
  4. package/dist/{amp-adapter-9gaxg015.js → amp-adapter-sxqqvmdk.js} +4 -4
  5. package/dist/{app-ctn8gsgx.js → app-mwx1d5a9.js} +3 -3
  6. package/dist/{assistant-zyr5kz47.js → assistant-yx1p6g82.js} +30 -26
  7. package/dist/{boot-reembed-w75maga2.js → boot-reembed-5h37a2c2.js} +1 -1
  8. package/dist/{boot-reembed-dwzfttdr.js → boot-reembed-7h78vmvv.js} +2 -1
  9. package/dist/{boot-scrub-sweep-e9kq43kf.js → boot-scrub-sweep-8mawd4gw.js} +4 -4
  10. package/dist/{boot-seeds-x28v3fhb.js → boot-seeds-ca84dhnn.js} +4 -4
  11. package/dist/{claude-adapter-f0afqnne.js → claude-adapter-wqt4hfkq.js} +9 -9
  12. package/dist/{claude-managed-adapter-x81a7r65.js → claude-managed-adapter-6fjqtr2z.js} +2 -2
  13. package/dist/{claude-managed-setup-bqzwjd9x.js → claude-managed-setup-rqv98sea.js} +10 -3
  14. package/dist/{claude-sdk-session-7b7whkaq.js → claude-sdk-session-f29f3b2x.js} +11 -11
  15. package/dist/{cli-sxgtf5fw.js → cli-07q03xm2.js} +1 -1
  16. package/dist/{cli-kxpfx2xr.js → cli-0z1xjzwa.js} +2 -2
  17. package/dist/{cli-g9vd9ece.js → cli-1hhbzkbb.js} +14 -16
  18. package/dist/{cli-qqzmjxkf.js → cli-1m9x8dr5.js} +11 -6
  19. package/dist/{cli-jbnn4vxb.js → cli-2pvzmas1.js} +3 -3
  20. package/dist/{cli-x77gen2p.js → cli-2y7v133v.js} +7 -7
  21. package/dist/{cli-dew6x255.js → cli-39aet655.js} +2 -2
  22. package/dist/{cli-g1cw7xtt.js → cli-39rrw8yp.js} +1 -1
  23. package/dist/{cli-jb30dzvk.js → cli-48gxjmcz.js} +530 -190
  24. package/dist/{cli-pzatvw94.js → cli-54sj64fc.js} +2 -2
  25. package/dist/{cli-bvpgr9ny.js → cli-60sty27p.js} +5 -5
  26. package/dist/{cli-asq5ydm4.js → cli-6a9qfa8b.js} +411 -69
  27. package/dist/{cli-277c31dw.js → cli-6mgdba42.js} +225 -3
  28. package/dist/{cli-19202kew.js → cli-6srv653c.js} +5 -5
  29. package/dist/{cli-n4c8e3s5.js → cli-708wdy32.js} +1 -1
  30. package/dist/{cli-pasyvjmm.js → cli-737pyqxr.js} +1 -1
  31. package/dist/{cli-6x9ma5w5.js → cli-803188pb.js} +1 -1
  32. package/dist/{cli-hh5we352.js → cli-86ehn4s5.js} +7 -7
  33. package/dist/{cli-9s05422w.js → cli-8mbc9za9.js} +1 -1
  34. package/dist/{cli-ff1tm9n9.js → cli-8wmj18cz.js} +1 -1
  35. package/dist/{cli-1r5ad7j5.js → cli-9gsm2rzp.js} +12 -12
  36. package/dist/{cli-mz9afxxf.js → cli-9pshx6rd.js} +17 -3
  37. package/dist/{cli-s682zgqz.js → cli-a6ds2epe.js} +1 -1
  38. package/dist/{cli-6a1xg1p7.js → cli-a89zdqz9.js} +2 -2
  39. package/dist/{cli-03vpq45j.js → cli-ay40dnj3.js} +2 -2
  40. package/dist/{cli-tsma7p8v.js → cli-aypd09nf.js} +2 -2
  41. package/dist/{cli-ethgy7ha.js → cli-b3yzyc57.js} +2 -2
  42. package/dist/{cli-bn0rewsy.js → cli-c081bj3b.js} +2 -2
  43. package/dist/{cli-mmhj8vd7.js → cli-c668vvcf.js} +11 -2
  44. package/dist/{cli-sbwsxvtd.js → cli-d20qvpr2.js} +2 -2
  45. package/dist/{cli-c952c7ac.js → cli-e1595bgx.js} +3 -3
  46. package/dist/{cli-621ce7kw.js → cli-f12mr20z.js} +3 -3
  47. package/dist/{cli-dqygeeh5.js → cli-f1e0ptjj.js} +10 -1
  48. package/dist/{cli-xzfq4at3.js → cli-f4dbh7a5.js} +16 -12
  49. package/dist/{cli-ha9rmwgq.js → cli-fb8m699c.js} +2 -2
  50. package/dist/{cli-5bnsc0e1.js → cli-gsfk58nw.js} +5 -5
  51. package/dist/cli-gt4h8cxw.js +895 -0
  52. package/dist/{cli-nwyw3zhg.js → cli-gxee0bqa.js} +1 -1
  53. package/dist/{cli-25n3mv5d.js → cli-h5jeg46p.js} +6 -6
  54. package/dist/{cli-gn5af0x5.js → cli-he9gbdx0.js} +62 -12
  55. package/dist/{cli-gbfxp48k.js → cli-j0ppywdr.js} +42 -35
  56. package/dist/{cli-k4tjsdx9.js → cli-j3y0x2n4.js} +277 -199
  57. package/dist/{cli-7p4jxgtt.js → cli-j9bpmykh.js} +75 -27
  58. package/dist/{cli-dabehxhp.js → cli-kt907da6.js} +1 -1
  59. package/dist/{cli-wx2nj19m.js → cli-kv7sbc2c.js} +6 -6
  60. package/dist/{cli-abs8ndtr.js → cli-m30k9777.js} +26 -26
  61. package/dist/{cli-cz5nmdxt.js → cli-m5e802r7.js} +2 -2
  62. package/dist/{cli-0shx9j93.js → cli-pfk92eqz.js} +2 -2
  63. package/dist/{cli-xtrz6bzs.js → cli-ptfq202x.js} +5 -3
  64. package/dist/{cli-6n8axjv1.js → cli-qj442fws.js} +2 -2
  65. package/dist/{cli-c61mbdds.js → cli-rd5m70gj.js} +4 -4
  66. package/dist/{cli-eftzyh9y.js → cli-s09j9vp5.js} +2 -2
  67. package/dist/{cli-m4ecdxvz.js → cli-s0mgx214.js} +7 -7
  68. package/dist/{cli-wghjkr0e.js → cli-sgqm2582.js} +10 -7
  69. package/dist/{cli-2655k16q.js → cli-sjctjr48.js} +2 -2
  70. package/dist/{cli-nzfnt2gs.js → cli-tf1n0r0b.js} +1 -1
  71. package/dist/{cli-x0f2v69c.js → cli-twctnkng.js} +12 -7
  72. package/dist/{cli-j6rktc91.js → cli-v6shg7na.js} +1 -1
  73. package/dist/{cli-gx4rm0qx.js → cli-vz78s5wm.js} +1 -1
  74. package/dist/{cli-gwhjmh8g.js → cli-wqr7cea4.js} +5 -5
  75. package/dist/{cli-e42vss7b.js → cli-x37r7qwf.js} +16 -8
  76. package/dist/{cli-4b2z6n0m.js → cli-yd2nreqw.js} +17 -8
  77. package/dist/{cli-64mh9mf3.js → cli-ymjpkxgn.js} +69 -17
  78. package/dist/{cli-5kqnemen.js → cli-yvy48785.js} +1 -1
  79. package/dist/{cli-9j129brq.js → cli-yxbsmx56.js} +6 -6
  80. package/dist/cli.js +22 -20
  81. package/dist/{codex-adapter-wch12q99.js → codex-adapter-zk59x2zh.js} +7 -7
  82. package/dist/{codex-hook-brpnycn5.js → codex-hook-xyjhvxwd.js} +1 -1
  83. package/dist/{codex-login-rn7c5gxt.js → codex-login-8cg0vhf2.js} +1 -1
  84. package/dist/{codex-session-runner-41pfcr95.js → codex-session-runner-kh6s4j3n.js} +8 -8
  85. package/dist/{commands-9849dkj6.js → commands-68et1qv2.js} +2 -2
  86. package/dist/{controller-ja0sd95p.js → controller-fyrbnzg4.js} +4 -4
  87. package/dist/{controllers-connect-xp05dj6x.js → controllers-connect-nep9h2xv.js} +23 -23
  88. package/dist/{cursor-adapter-623qxqew.js → cursor-adapter-yss3pg7t.js} +2 -2
  89. package/dist/{db-w759qmx0.js → db-28gjyvxj.js} +4 -2
  90. package/dist/{db-47vj40dy.js → db-8ftwvzba.js} +3 -3
  91. package/dist/{devin-adapter-4ycy4vrf.js → devin-adapter-byen2cxt.js} +1 -1
  92. package/dist/{dispatcher-7b8e4z2j.js → dispatcher-hayexmkr.js} +20 -20
  93. package/dist/{docker-s84hjs91.js → docker-fdzyewpz.js} +2 -2
  94. package/dist/{dsh-adapter-2ezw3xea.js → dsh-adapter-46wawff9.js} +2 -2
  95. package/dist/{e2b-9gkdhm3c.js → e2b-222hsajc.js} +2 -2
  96. package/dist/{e2b-cjtf8k1z.js → e2b-fn3zacvt.js} +2 -2
  97. package/dist/{easter-egg-3d-e4qv8dxj.js → easter-egg-3d-8d1e0h4m.js} +1 -1
  98. package/dist/{event-bus-3z78ep5n.js → event-bus-pghg8hqy.js} +1 -1
  99. package/dist/{execute-0xpz8950.js → execute-cjrfxfnm.js} +1 -1
  100. package/dist/{external-channel-e2s028da.js → external-channel-xbmxcg09.js} +2 -2
  101. package/dist/{grok-adapter-ys7gaqee.js → grok-adapter-ag4wks2a.js} +10 -10
  102. package/dist/handlers-tzmevqb5.js +41 -0
  103. package/dist/{heartbeat-w3mntghj.js → heartbeat-psfvcgwp.js} +23 -23
  104. package/dist/{hook-g7kvv6x9.js → hook-8pz04697.js} +6 -6
  105. package/dist/{hook-3jjywnpb.js → hook-cyq4mryn.js} +8 -8
  106. package/dist/{http-tkp7d4kb.js → http-haj1nd6k.js} +921 -169
  107. package/dist/{index-q7m26kvs.js → index-jwt2bj6f.js} +265 -97
  108. package/dist/{index-3n8m9ea2.js → index-q52f47pe.js} +1 -1
  109. package/dist/{index-31ceyf42.js → index-syvhnvtw.js} +1 -1
  110. package/dist/index-y1ajx04a.js +43 -0
  111. package/dist/{index-1ef1myq2.js → index-z5h22pes.js} +20 -20
  112. package/dist/{index-xdaahthb.js → index-zyq8ct52.js} +20 -20
  113. package/dist/{keepalive-v4ta8wgg.js → keepalive-xdvsamvj.js} +4 -4
  114. package/dist/lead-hqg57kdp.js +79 -0
  115. package/dist/{maintenance-84n1ex21.js → maintenance-4y2xzh3a.js} +1 -1
  116. package/dist/{oauth-refresh-sweep-vjnnandw.js → oauth-refresh-sweep-jd4r7zbs.js} +9 -4
  117. package/dist/{onboard-sfmpe4np.js → onboard-18447q9q.js} +6 -6
  118. package/dist/{opencode-adapter-jmpst4q4.js → opencode-adapter-26b2frdf.js} +7 -7
  119. package/dist/{otel-impl-v6cc0zve.js → otel-impl-f9tgr8yw.js} +2 -2
  120. package/dist/{pi-mono-adapter-fk8fkcf6.js → pi-mono-adapter-qn6qbga1.js} +38 -17
  121. package/dist/{pricing-refresh-fsk1e1zc.js → pricing-refresh-dw2tgb53.js} +3 -3
  122. package/dist/{rbac-roles-prmkdnkw.js → rbac-roles-aygm2760.js} +2 -2
  123. package/dist/{rbac-roles-zxmxqa39.js → rbac-roles-s4nwj2m3.js} +1 -1
  124. package/dist/render-v2-yfvdfr0x.js +16 -0
  125. package/dist/{resume-frdtgfa0.js → resume-1bmvjbf3.js} +9 -9
  126. package/dist/{runtime-bt5pkpm1.js → runtime-f7tpzedy.js} +1 -1
  127. package/dist/{session-access-fpez4y5q.js → session-access-r5garej6.js} +4 -4
  128. package/dist/session-source-backfill-424wzv0r.js +110 -0
  129. package/dist/{setup-mq6m3m8q.js → setup-8tygvxkq.js} +1 -1
  130. package/dist/{virtual-modules-mnfbh5mr.js → virtual-modules-xsw323b3.js} +2 -2
  131. package/dist/{work-objects-kfahhjsq.js → work-objects-ggnghpgf.js} +23 -23
  132. package/dist/worker-sqjd1nqf.js +79 -0
  133. package/dist/{x-pbpezr0s.js → x-wxrzvzx8.js} +2 -2
  134. package/openapi.json +1324 -14
  135. package/package.json +5 -3
  136. package/src/assets/source-key.ts +95 -0
  137. package/src/be/automation-preflight.ts +2 -0
  138. package/src/be/db/api-keys.ts +89 -0
  139. package/src/be/db/session-labels.ts +28 -0
  140. package/src/be/db/session-moves.ts +5 -6
  141. package/src/be/db/session-tree.ts +153 -14
  142. package/src/be/db/tasks/read.ts +11 -0
  143. package/src/be/db/tasks/write.ts +6 -1
  144. package/src/be/db/workflow-runs.ts +219 -6
  145. package/src/be/db-retention.ts +61 -6
  146. package/src/be/db.ts +135 -132
  147. package/src/be/memory/providers/openai-embedding.ts +5 -1
  148. package/src/be/memory/task-learning.ts +155 -0
  149. package/src/be/migrations/244_api_key_validation.sql +4 -0
  150. package/src/be/migrations/245_script_executor.sql +3 -0
  151. package/src/be/oauth-refresh-sweep.ts +2 -1
  152. package/src/be/onboarding.ts +4 -0
  153. package/src/be/scripts/boot-reembed.ts +2 -0
  154. package/src/be/scripts/db.ts +14 -4
  155. package/src/be/scripts/embeddings.ts +2 -0
  156. package/src/be/scripts/run-saved.ts +1 -0
  157. package/src/be/scripts/typecheck.ts +10 -4
  158. package/src/be/seed-skills/index.ts +7 -0
  159. package/src/be/session-source-backfill.ts +163 -0
  160. package/src/be/swarm-config-guard.ts +1 -0
  161. package/src/comb/review-batch.ts +28 -1
  162. package/src/comb/templates.ts +7 -2
  163. package/src/commands/claude-managed-setup.ts +7 -1
  164. package/src/commands/credential-refresh.ts +76 -1
  165. package/src/commands/credential-wait.ts +2 -2
  166. package/src/commands/onboard/compose-generator.ts +5 -3
  167. package/src/commands/provider-credentials.ts +212 -171
  168. package/src/commands/runner.ts +25 -4
  169. package/src/extensions/apply-task-create.ts +8 -1
  170. package/src/extensions/contract-types.generated.ts +1 -1
  171. package/src/extensions/contract.ts +5 -0
  172. package/src/heartbeat/heartbeat.ts +14 -1
  173. package/src/heartbeat/script-runner-probe.ts +47 -0
  174. package/src/http/all-routes.ts +2 -0
  175. package/src/http/api-keys.ts +77 -9
  176. package/src/http/assets.ts +15 -0
  177. package/src/http/codex-oauth-accounts.ts +191 -0
  178. package/src/http/comb.ts +15 -2
  179. package/src/http/config.ts +1 -1
  180. package/src/http/core.ts +6 -0
  181. package/src/http/fleet-benchmark.ts +5 -2
  182. package/src/http/idempotency-key.ts +1 -1
  183. package/src/http/index.ts +14 -3
  184. package/src/http/integrations.ts +5 -1
  185. package/src/http/kv.ts +8 -3
  186. package/src/http/onboarding.ts +6 -1
  187. package/src/http/pages-public.ts +38 -5
  188. package/src/http/pool-keys.ts +354 -0
  189. package/src/http/scripts.ts +27 -0
  190. package/src/http/sessions.ts +37 -12
  191. package/src/http/stats.ts +1 -0
  192. package/src/http/status.ts +26 -12
  193. package/src/http/tasks.ts +3 -0
  194. package/src/http/used-by.ts +7 -2
  195. package/src/http/workflows.ts +88 -9
  196. package/src/http/x.ts +5 -0
  197. package/src/integrations/chat-sdk/inbound.ts +27 -0
  198. package/src/kv-reserved-namespaces.ts +19 -0
  199. package/src/prompts/base-prompt.ts +21 -1
  200. package/src/prompts/session-templates.ts +17 -3
  201. package/src/providers/acp-targets.ts +1 -1
  202. package/src/providers/amp-adapter.ts +1 -1
  203. package/src/providers/claude-adapter.ts +5 -1
  204. package/src/providers/claude-managed-adapter.ts +16 -9
  205. package/src/providers/codex-adapter.ts +71 -11
  206. package/src/providers/dsh-adapter.ts +1 -1
  207. package/src/providers/pi-mono-adapter.ts +41 -11
  208. package/src/scheduler/scheduler.ts +5 -3
  209. package/src/scripts-runtime/eval-harness.ts +8 -1
  210. package/src/scripts-runtime/executors/native.ts +22 -16
  211. package/src/scripts-runtime/executors/quickjs-prelude.ts +103 -1
  212. package/src/scripts-runtime/executors/quickjs-runner.ts +2 -1
  213. package/src/scripts-runtime/executors/quickjs.ts +7 -0
  214. package/src/scripts-runtime/executors/registry.ts +32 -0
  215. package/src/scripts-runtime/executors/types.ts +7 -0
  216. package/src/scripts-runtime/host-validated-args.ts +133 -0
  217. package/src/scripts-runtime/loader.ts +30 -3
  218. package/src/scripts-runtime/swarm-sdk.ts +16 -3
  219. package/src/scripts-runtime/types/stdlib.d.ts +10 -2
  220. package/src/scripts-runtime/types/swarm-extension.d.ts +17 -8
  221. package/src/scripts-runtime/types/swarm-sdk.d.ts +10 -2
  222. package/src/slack/assistant.ts +7 -0
  223. package/src/slack/channel-labels.ts +74 -0
  224. package/src/slack/handlers.ts +8 -0
  225. package/src/slack/inbound-files.ts +5 -2
  226. package/src/slack/thread-buffer.ts +4 -0
  227. package/src/tasks/sibling-awareness.ts +12 -3
  228. package/src/telemetry-context.ts +5 -6
  229. package/src/telemetry-identity.ts +3 -3
  230. package/src/tests/api-key-status-by-suffix.test.ts +242 -0
  231. package/src/tests/api-keys-validation.test.ts +170 -0
  232. package/src/tests/base-prompt.test.ts +70 -2
  233. package/src/tests/claude-managed-adapter.test.ts +46 -0
  234. package/src/tests/claude-routes-e2e.test.ts +7 -2
  235. package/src/tests/codex-credential-pools.test.ts +120 -0
  236. package/src/tests/codex-gateway-route.test.ts +165 -0
  237. package/src/tests/codex-oauth-accounts.test.ts +357 -0
  238. package/src/tests/comb-review-batch.test.ts +63 -2
  239. package/src/tests/community-linear-delivery-loop.test.ts +2099 -0
  240. package/src/tests/config-pool-keys.test.ts +533 -0
  241. package/src/tests/credential-check.test.ts +294 -4
  242. package/src/tests/credential-refresh.test.ts +172 -1
  243. package/src/tests/db-retention.test.ts +9 -3
  244. package/src/tests/db-task-read-contract.test.ts +1 -0
  245. package/src/tests/db-task-write-contract.test.ts +1 -3
  246. package/src/tests/docs-index-footprint.test.js +3 -3
  247. package/src/tests/docs-index.test.ts +135 -0
  248. package/src/tests/dsh-adapter.test.ts +1 -1
  249. package/src/tests/extensions-pre-task.test.ts +53 -1
  250. package/src/tests/fetch-resolved-env.test.ts +16 -2
  251. package/src/tests/fixtures/extensions/record-task-create/hooks.ts +9 -0
  252. package/src/tests/fixtures/extensions/record-task-create/manifest.json +7 -0
  253. package/src/tests/fleet-benchmark.test.ts +8 -0
  254. package/src/tests/get-workflow-run-tool.test.ts +98 -0
  255. package/src/tests/heartbeat-checklist.test.ts +89 -0
  256. package/src/tests/heartbeat-script-runner-probe.test.ts +83 -0
  257. package/src/tests/integrations-http.test.ts +32 -2
  258. package/src/tests/internal-ai/complete-structured.test.ts +37 -1
  259. package/src/tests/internal-ai/credentials.test.ts +23 -0
  260. package/src/tests/kv-http.test.ts +32 -0
  261. package/src/tests/kv-tool.test.ts +25 -0
  262. package/src/tests/multi-runtime-registration.test.ts +12 -12
  263. package/src/tests/oauth-refresh-sweep.test.ts +34 -1
  264. package/src/tests/onboard-compose.test.ts +20 -0
  265. package/src/tests/onboarding.test.ts +108 -1
  266. package/src/tests/openai-embedding-credentials.test.ts +35 -0
  267. package/src/tests/opencode-adapter.test.ts +2 -1
  268. package/src/tests/openrouter-attribution-call-sites.test.ts +2 -2
  269. package/src/tests/org-website.test.ts +36 -0
  270. package/src/tests/pages-frame-ancestors.test.ts +162 -0
  271. package/src/tests/pi-codemode.test.ts +2 -1
  272. package/src/tests/pi-mono-adapter.test.ts +54 -0
  273. package/src/tests/pi-native-mcp.test.ts +13 -1
  274. package/src/tests/pi-tool-exposure.test.ts +8 -8
  275. package/src/tests/probe-tool-schema-tokens.test.ts +144 -0
  276. package/src/tests/prompt-template-session.test.ts +4 -3
  277. package/src/tests/provider-key-probes.test.ts +181 -0
  278. package/src/tests/rbac-e2e-helpers.test.ts +88 -1
  279. package/src/tests/rbac-e2e-helpers.ts +36 -11
  280. package/src/tests/request-composition-derive.test.ts +329 -0
  281. package/src/tests/script-connections.test.ts +4 -0
  282. package/src/tests/script-executor-conformance.test.ts +36 -1
  283. package/src/tests/script-executor-quickjs-pool.test.ts +50 -0
  284. package/src/tests/script-executor-quickjs.test.ts +140 -0
  285. package/src/tests/script-host-validated-args-native.test.ts +196 -0
  286. package/src/tests/script-per-script-executor.test.ts +415 -0
  287. package/src/tests/script-runs-retention.test.ts +212 -0
  288. package/src/tests/scripts-external-api.test.ts +45 -0
  289. package/src/tests/sdk-allowlist.test.ts +42 -2
  290. package/src/tests/self-improvement.test.ts +4 -4
  291. package/src/tests/session-source-backfill.test.ts +429 -0
  292. package/src/tests/session-source-keys.test.ts +236 -0
  293. package/src/tests/session-source-labels.test.ts +419 -0
  294. package/src/tests/sessions-detail-batch.test.ts +2 -0
  295. package/src/tests/sessions-move.test.ts +131 -0
  296. package/src/tests/sessions-tree.test.ts +299 -2
  297. package/src/tests/slack-inbound-files.test.ts +103 -23
  298. package/src/tests/status.test.ts +101 -18
  299. package/src/tests/store-progress-learning.test.ts +288 -0
  300. package/src/tests/tasks-workflow-run-filter.test.ts +146 -0
  301. package/src/tests/test-net.ts +31 -0
  302. package/src/tests/transcription.test.ts +8 -0
  303. package/src/tests/ui-logs-parser.test.ts +180 -0
  304. package/src/tests/used-by-route.test.ts +11 -0
  305. package/src/tests/workflow-cascade-cancel.test.ts +172 -0
  306. package/src/tests/workflow-engine-v2.test.ts +116 -1
  307. package/src/tests/workflow-http-v2.test.ts +131 -0
  308. package/src/tests/workflow-mcp-trigger-schema.test.ts +209 -0
  309. package/src/tests/workflow-run-finished-event.test.ts +263 -0
  310. package/src/tests/workflow-step-order.test.ts +92 -0
  311. package/src/tests/workflow-sub-workflow.test.ts +30 -0
  312. package/src/tests/workflow-swarm-script.test.ts +34 -0
  313. package/src/tools/get-tasks.ts +8 -0
  314. package/src/tools/kv/kv-read-auth.ts +4 -2
  315. package/src/tools/script-common.ts +1 -0
  316. package/src/tools/script-run.ts +7 -0
  317. package/src/tools/script-upsert.ts +7 -0
  318. package/src/tools/store-progress.ts +67 -1
  319. package/src/tools/task-action.ts +1 -1
  320. package/src/tools/workflows/get-workflow-run.ts +14 -4
  321. package/src/tools/workflows/trigger-workflow.ts +104 -10
  322. package/src/types.ts +36 -1
  323. package/src/utils/company-profile.ts +51 -1
  324. package/src/utils/credentials.ts +10 -4
  325. package/src/utils/internal-ai/complete-structured.ts +5 -0
  326. package/src/utils/internal-ai/credentials.ts +4 -3
  327. package/src/utils/provider-key-probes.ts +328 -0
  328. package/src/utils/transcription.ts +4 -1
  329. package/src/workflows/engine.ts +18 -16
  330. package/src/workflows/executors/sub-workflow.ts +8 -1
  331. package/src/workflows/executors/swarm-script.ts +5 -0
  332. package/src/workflows/foreach-driver.ts +5 -11
  333. package/src/workflows/node-timeout.ts +30 -0
  334. package/templates/ai-toolbox.manifest.json +2 -2
  335. package/templates/community/linear-delivery-loop/PLAYBOOK.md +323 -0
  336. package/templates/community/linear-delivery-loop/README.md +38 -0
  337. package/templates/community/linear-delivery-loop/config.example.json +31 -0
  338. package/templates/community/linear-delivery-loop/lead-prompt.md +34 -0
  339. package/templates/community/linear-delivery-loop/schedule.json +10 -0
  340. package/templates/community/linear-delivery-loop/scripts/linear-delivery-setup.ts +148 -0
  341. package/templates/community/linear-delivery-loop/scripts/linear-delivery-tick.ts +1781 -0
  342. package/templates/skills/researching/content.md +2 -0
  343. package/templates/skills/swarm-docs/config.json +14 -0
  344. package/templates/skills/swarm-docs/content.md +144 -0
  345. package/templates/skills/swarm-scripts/SKILL.md +1 -0
  346. package/templates/skills/swarm-scripts/content.md +1 -0
  347. package/dist/cli-7421jzsw.js +0 -84
  348. package/dist/cli-e45e4m6b.js +0 -413
  349. package/dist/cli-zw88zjba.js +0 -307
  350. package/dist/handlers-wy1dr6ja.js +0 -41
  351. package/dist/index-nmm79qgr.js +0 -43
  352. package/dist/lead-sawnyqxk.js +0 -79
  353. package/dist/render-v2-pjwxvnkw.js +0 -12
  354. package/dist/worker-v5e5rxj3.js +0 -79
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  renderSteeringDelivery
3
- } from "./cli-sxgtf5fw.js";
3
+ } from "./cli-07q03xm2.js";
4
4
  import {
5
5
  authJsonToCredentialSelection,
6
6
  credentialsToAuthJson,
7
7
  loadAllCodexOAuthSlots
8
- } from "./cli-kxpfx2xr.js";
8
+ } from "./cli-0z1xjzwa.js";
9
9
  import {
10
10
  effectiveReasoningEffort
11
- } from "./cli-bn0rewsy.js";
11
+ } from "./cli-c081bj3b.js";
12
12
  import {
13
13
  isSkillLoaderCall,
14
14
  skillFromToolArgs,
@@ -19,8 +19,15 @@ import {
19
19
  orgIdentityStatus,
20
20
  renderMemoriesPrompt,
21
21
  isUnknownModelError,
22
+ timedFetch,
23
+ checkAnthropicApiKey,
24
+ checkOpenAiApiKey,
25
+ checkXaiApiKey,
26
+ checkOpenRouter,
27
+ checkDeepSeekApiKey,
28
+ checkOpenAICompatibleProvider,
22
29
  writeSkillsToFilesystem
23
- } from "./cli-277c31dw.js";
30
+ } from "./cli-6mgdba42.js";
24
31
  import {
25
32
  isPollTracingEnabled,
26
33
  initOtel,
@@ -30,7 +37,7 @@ import {
30
37
  injectTraceContext2,
31
38
  initialize,
32
39
  ensure
33
- } from "./cli-abs8ndtr.js";
40
+ } from "./cli-m30k9777.js";
34
41
  import {
35
42
  MAX_RATE_LIMIT_RESET_MS,
36
43
  isRateLimitMessage,
@@ -38,7 +45,7 @@ import {
38
45
  CODEX_CREDITS_EXHAUSTED_COOLDOWN_MS,
39
46
  resolveCodexCreditsExhaustedCooldownMs,
40
47
  parseRateLimitResetTime
41
- } from "./cli-gx4rm0qx.js";
48
+ } from "./cli-vz78s5wm.js";
42
49
  import {
43
50
  terminateRegisteredProcessGroups
44
51
  } from "./cli-3ggwdtb0.js";
@@ -48,44 +55,44 @@ import {
48
55
  canonicalAzureDevOpsRepoUrl,
49
56
  parseAzureDevOpsRepoUrl,
50
57
  resolveScriptsOnlyMode
51
- } from "./cli-asq5ydm4.js";
58
+ } from "./cli-6a9qfa8b.js";
52
59
  import {
53
60
  ACP_TARGET_IDS,
54
61
  isAcpTarget
55
- } from "./cli-5kqnemen.js";
62
+ } from "./cli-yvy48785.js";
56
63
  import {
57
64
  checkAmpCredentials2,
58
65
  liveTestAmpCredentials2
59
- } from "./cli-wx2nj19m.js";
66
+ } from "./cli-kv7sbc2c.js";
60
67
  import {
61
68
  checkClaudeCredentials2
62
- } from "./cli-g9vd9ece.js";
69
+ } from "./cli-1hhbzkbb.js";
63
70
  import {
64
71
  checkClaudeManagedCredentials2
65
- } from "./cli-4b2z6n0m.js";
72
+ } from "./cli-yd2nreqw.js";
66
73
  import {
67
74
  codexUserHome,
68
75
  checkCodexCredentials2
69
- } from "./cli-64mh9mf3.js";
76
+ } from "./cli-ymjpkxgn.js";
70
77
  import {
71
78
  checkCursorCredentials2
72
- } from "./cli-25n3mv5d.js";
79
+ } from "./cli-h5jeg46p.js";
73
80
  import {
74
81
  checkDevinCredentials2
75
- } from "./cli-g1cw7xtt.js";
82
+ } from "./cli-39rrw8yp.js";
76
83
  import {
77
84
  checkDshCredentials2
78
- } from "./cli-5bnsc0e1.js";
85
+ } from "./cli-gsfk58nw.js";
79
86
  import {
80
87
  checkOpencodeCredentials2
81
- } from "./cli-hh5we352.js";
88
+ } from "./cli-86ehn4s5.js";
82
89
  import {
83
90
  checkGrokCredentials2
84
- } from "./cli-621ce7kw.js";
91
+ } from "./cli-f12mr20z.js";
85
92
  import {
86
93
  getContextWindowSize,
87
94
  init_context_window
88
- } from "./cli-0shx9j93.js";
95
+ } from "./cli-pfk92eqz.js";
89
96
  import {
90
97
  CODEX_OAUTH_POOL_SLOTS_ENV,
91
98
  isCodexOAuthConfigKey,
@@ -94,7 +101,7 @@ import {
94
101
  } from "./cli-j4bwnpkm.js";
95
102
  import {
96
103
  validateJsonSchema
97
- } from "./cli-gbfxp48k.js";
104
+ } from "./cli-j0ppywdr.js";
98
105
  import {
99
106
  mapTriggerSurface,
100
107
  init_telemetry_context,
@@ -112,7 +119,7 @@ import {
112
119
  init_vcs_repo_match,
113
120
  isApiDrainingResponse,
114
121
  init_api_drain
115
- } from "./cli-jb30dzvk.js";
122
+ } from "./cli-48gxjmcz.js";
116
123
  import {
117
124
  parseWorkerModelTierOverrides,
118
125
  resolveTaskModelSelection,
@@ -120,7 +127,7 @@ import {
120
127
  ProviderNameSchema,
121
128
  WorkerNudgeSchema,
122
129
  init_types
123
- } from "./cli-mz9afxxf.js";
130
+ } from "./cli-9pshx6rd.js";
124
131
  import {
125
132
  generateDefaultClaudeMd2,
126
133
  generateDefaultSoulMd2,
@@ -144,50 +151,43 @@ import {
144
151
  resolveClaudeMdPath,
145
152
  syncProfileFilesToServer,
146
153
  init_profile_sync
147
- } from "./cli-e42vss7b.js";
154
+ } from "./cli-x37r7qwf.js";
148
155
  import {
149
156
  isSteeringEnabled2,
150
157
  init_steering_enabled
151
158
  } from "./cli-4sydckyj.js";
152
- import {
153
- normalizeProviderKeyAliases,
154
- ModelWindowExhaustedError,
155
- CLAUDE_CREDENTIALS_HINT,
156
- resolveCredentialPools,
157
- init_credentials
158
- } from "./cli-zw88zjba.js";
159
159
  import {
160
160
  init_templates3
161
- } from "./cli-j6rktc91.js";
161
+ } from "./cli-v6shg7na.js";
162
162
  import {
163
+ validateRoute,
164
+ deriveDefaultRoute,
165
+ init_src,
163
166
  modelFamilyOf,
164
167
  windowForModelFamily,
165
168
  parseModelLimitMessage,
166
169
  parseCreditsRequiredMessage,
167
- init_model_rate_limit_windows
168
- } from "./cli-7421jzsw.js";
169
- import {
170
- validateRoute,
171
- deriveDefaultRoute,
172
- init_src
173
- } from "./cli-e45e4m6b.js";
174
- import {
175
- getOpenRouterBaseUrl,
176
- getOpenRouterAttributionHeaders,
177
- init_openrouter_base_url
178
- } from "./cli-dfyv0jdy.js";
170
+ init_model_rate_limit_windows,
171
+ CREDENTIAL_POOL_VARS,
172
+ normalizeProviderKeyAliases,
173
+ ModelWindowExhaustedError,
174
+ splitCredentialPool,
175
+ CLAUDE_CREDENTIALS_HINT,
176
+ resolveCredentialPools,
177
+ init_credentials
178
+ } from "./cli-gt4h8cxw.js";
179
179
  import {
180
180
  interpolate,
181
181
  init_template,
182
182
  configureHttpResolver,
183
183
  resolveTemplateAsync,
184
184
  init_resolver
185
- } from "./cli-dqygeeh5.js";
185
+ } from "./cli-f1e0ptjj.js";
186
186
  import {
187
187
  runtimeHarnessSections,
188
188
  refreshRuntimeModelCatalog,
189
189
  init_runtime_model_catalog
190
- } from "./cli-6x9ma5w5.js";
190
+ } from "./cli-803188pb.js";
191
191
  import {
192
192
  getMcpBaseUrl,
193
193
  init_constants2
@@ -205,7 +205,7 @@ import {
205
205
  registerEnvSecrets,
206
206
  registerSensitiveKeyName,
207
207
  init_secret_scrubber
208
- } from "./cli-n4c8e3s5.js";
208
+ } from "./cli-708wdy32.js";
209
209
  import {
210
210
  harnessModelMismatch,
211
211
  openAICompatibleProviders,
@@ -213,9 +213,10 @@ import {
213
213
  providerBaseUrl,
214
214
  providerKeyFromEnv,
215
215
  init_src2
216
- } from "./cli-nwyw3zhg.js";
216
+ } from "./cli-gxee0bqa.js";
217
217
 
218
218
  // src/commands/runner.ts
219
+ init_src();
219
220
  import { existsSync, statSync } from "node:fs";
220
221
  import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
221
222
  init_base_prompt();
@@ -247,47 +248,47 @@ async function materializeCodexAuthJson(_slot, creds, deps = {}) {
247
248
  async function createProviderAdapter(provider) {
248
249
  switch (provider) {
249
250
  case "claude": {
250
- const { ClaudeAdapter } = await import("./claude-adapter-f0afqnne.js");
251
+ const { ClaudeAdapter } = await import("./claude-adapter-wqt4hfkq.js");
251
252
  return new ClaudeAdapter;
252
253
  }
253
254
  case "pi": {
254
- const { PiMonoAdapter } = await import("./pi-mono-adapter-fk8fkcf6.js");
255
+ const { PiMonoAdapter } = await import("./pi-mono-adapter-qn6qbga1.js");
255
256
  return new PiMonoAdapter;
256
257
  }
257
258
  case "codex": {
258
- const { CodexAdapter } = await import("./codex-adapter-wch12q99.js");
259
+ const { CodexAdapter } = await import("./codex-adapter-zk59x2zh.js");
259
260
  return new CodexAdapter;
260
261
  }
261
262
  case "claude-managed": {
262
- const { ClaudeManagedAdapter } = await import("./claude-managed-adapter-x81a7r65.js");
263
+ const { ClaudeManagedAdapter } = await import("./claude-managed-adapter-6fjqtr2z.js");
263
264
  return new ClaudeManagedAdapter;
264
265
  }
265
266
  case "devin": {
266
- const { DevinAdapter } = await import("./devin-adapter-4ycy4vrf.js");
267
+ const { DevinAdapter } = await import("./devin-adapter-byen2cxt.js");
267
268
  return new DevinAdapter;
268
269
  }
269
270
  case "opencode": {
270
- const { OpencodeAdapter } = await import("./opencode-adapter-jmpst4q4.js");
271
+ const { OpencodeAdapter } = await import("./opencode-adapter-26b2frdf.js");
271
272
  return new OpencodeAdapter;
272
273
  }
273
274
  case "dsh": {
274
- const { DshAdapter } = await import("./dsh-adapter-2ezw3xea.js");
275
+ const { DshAdapter } = await import("./dsh-adapter-46wawff9.js");
275
276
  return new DshAdapter;
276
277
  }
277
278
  case "amp": {
278
- const { AmpAdapter } = await import("./amp-adapter-9gaxg015.js");
279
+ const { AmpAdapter } = await import("./amp-adapter-sxqqvmdk.js");
279
280
  return new AmpAdapter;
280
281
  }
281
282
  case "cursor": {
282
- const { CursorAdapter } = await import("./cursor-adapter-623qxqew.js");
283
+ const { CursorAdapter } = await import("./cursor-adapter-yss3pg7t.js");
283
284
  return new CursorAdapter;
284
285
  }
285
286
  case "grok": {
286
- const { GrokAdapter } = await import("./grok-adapter-ys7gaqee.js");
287
+ const { GrokAdapter } = await import("./grok-adapter-ag4wks2a.js");
287
288
  return new GrokAdapter;
288
289
  }
289
290
  case "acp": {
290
- const { ACPAdapter } = await import("./acp-adapter-ek38cwsv.js");
291
+ const { ACPAdapter } = await import("./acp-adapter-ma1js5n7.js");
291
292
  return new ACPAdapter;
292
293
  }
293
294
  default:
@@ -1222,11 +1223,15 @@ async function reportCredentialOutcomeThenFinish(input, finish) {
1222
1223
  await finish();
1223
1224
  }
1224
1225
 
1226
+ // src/commands/credential-refresh.ts
1227
+ init_credentials();
1228
+ init_secret_scrubber();
1229
+
1225
1230
  // src/commands/provider-credentials.ts
1226
1231
  init_src2();
1227
1232
  init_src();
1228
1233
  init_credentials();
1229
- init_openrouter_base_url();
1234
+ init_env_flag();
1230
1235
  init_secret_scrubber();
1231
1236
  function isBedrockMode(env) {
1232
1237
  const mode = env.BEDROCK_AUTH_MODE?.toLowerCase();
@@ -1269,7 +1274,7 @@ var CREDENTIAL_PROVIDER_CHECKERS = {
1269
1274
  devin: (env) => checkDevinCredentials2(env),
1270
1275
  opencode: (env, opts) => checkOpencodeCredentials2(env, opts),
1271
1276
  pi: async (env, opts) => {
1272
- const { checkPiMonoCredentials, listPiOpencodeGoModelIds } = await import("./pi-mono-adapter-fk8fkcf6.js");
1277
+ const { checkPiMonoCredentials, listPiOpencodeGoModelIds } = await import("./pi-mono-adapter-qn6qbga1.js");
1273
1278
  return {
1274
1279
  ...await checkPiMonoCredentials(env, opts),
1275
1280
  opencodeGoModels: listPiOpencodeGoModelIds()
@@ -1302,27 +1307,6 @@ async function checkProviderCredentials(provider, env, opts) {
1302
1307
  }
1303
1308
  return checker(env, opts);
1304
1309
  }
1305
- var LIVE_TEST_TIMEOUT_MS = 5000;
1306
- async function timedFetch(url, init) {
1307
- const controller = new AbortController;
1308
- const timer = setTimeout(() => controller.abort(), LIVE_TEST_TIMEOUT_MS);
1309
- const start = Date.now();
1310
- try {
1311
- const res = await fetch(url, { ...init, signal: controller.signal });
1312
- let bodyText = "";
1313
- try {
1314
- bodyText = await res.text();
1315
- } catch {}
1316
- return {
1317
- ok: res.ok,
1318
- status: res.status,
1319
- bodyText,
1320
- latency_ms: Date.now() - start
1321
- };
1322
- } finally {
1323
- clearTimeout(timer);
1324
- }
1325
- }
1326
1310
  function asLiveError(err, latency_ms) {
1327
1311
  const raw = err instanceof Error ? err.message : String(err);
1328
1312
  return {
@@ -1331,75 +1315,56 @@ function asLiveError(err, latency_ms) {
1331
1315
  latency_ms
1332
1316
  };
1333
1317
  }
1334
- async function checkAnthropicApiKey(apiKey) {
1335
- const r = await timedFetch("https://api.anthropic.com/v1/models", {
1336
- method: "GET",
1337
- headers: { "x-api-key": apiKey, "anthropic-version": "2023-06-01" }
1338
- });
1339
- if (r.ok)
1340
- return { ok: true, latency_ms: r.latency_ms };
1341
- return {
1342
- ok: false,
1343
- error: scrubSecrets(`HTTP ${r.status}: ${r.bodyText.slice(0, 200)}`),
1344
- latency_ms: r.latency_ms
1345
- };
1318
+ async function checkEachKey(keyType, value, check) {
1319
+ const members = splitCredentialPool(value);
1320
+ if (members.length === 0)
1321
+ members.push(value.trim());
1322
+ const results = await Promise.all(members.map(async (member) => {
1323
+ const startedAt = Date.now();
1324
+ try {
1325
+ return await check(member);
1326
+ } catch (err) {
1327
+ return asLiveError(err, Date.now() - startedAt);
1328
+ }
1329
+ }));
1330
+ const latency_ms = Math.max(...results.map((result) => result.latency_ms));
1331
+ if (results.every((result) => result.skipped))
1332
+ return { ok: true, skipped: true, latency_ms };
1333
+ const keys = results.map((result, index) => ({
1334
+ keyType,
1335
+ index,
1336
+ suffix: members[index].slice(-5),
1337
+ ok: result.ok,
1338
+ ...result.error !== undefined ? { error: result.error } : {},
1339
+ ...result.httpStatus !== undefined ? { httpStatus: result.httpStatus } : {},
1340
+ latency_ms: result.latency_ms
1341
+ }));
1342
+ const failed = keys.filter((key) => !key.ok);
1343
+ if (failed.length === 0)
1344
+ return { ok: true, latency_ms, keys };
1345
+ const failures = failed.map((key) => `key ending ${key.suffix} (${key.httpStatus !== undefined ? `HTTP ${key.httpStatus}` : key.error ?? "Unknown error"})`).join(", ");
1346
+ if (failed.length < keys.length) {
1347
+ return {
1348
+ ok: true,
1349
+ latency_ms,
1350
+ keys,
1351
+ warning: `${failed.length} of ${keys.length} keys failed: ${failures}.`
1352
+ };
1353
+ }
1354
+ if (keys.length === 1) {
1355
+ return {
1356
+ ok: false,
1357
+ error: failed[0].error,
1358
+ httpStatus: failed[0].httpStatus,
1359
+ latency_ms,
1360
+ keys
1361
+ };
1362
+ }
1363
+ return { ok: false, error: `All ${keys.length} keys failed: ${failures}.`, latency_ms, keys };
1346
1364
  }
1347
1365
  function presenceCheckOk() {
1348
1366
  return { ok: true, latency_ms: 0 };
1349
1367
  }
1350
- async function checkOpenAiApiKey(apiKey) {
1351
- const r = await timedFetch("https://api.openai.com/v1/models", {
1352
- method: "GET",
1353
- headers: { Authorization: `Bearer ${apiKey}` }
1354
- });
1355
- if (r.ok)
1356
- return { ok: true, latency_ms: r.latency_ms };
1357
- return {
1358
- ok: false,
1359
- error: scrubSecrets(`HTTP ${r.status}: ${r.bodyText.slice(0, 200)}`),
1360
- latency_ms: r.latency_ms
1361
- };
1362
- }
1363
- async function checkXaiApiKey(apiKey) {
1364
- const r = await timedFetch("https://api.x.ai/v1/models", {
1365
- method: "GET",
1366
- headers: { Authorization: `Bearer ${apiKey}` }
1367
- });
1368
- if (r.ok)
1369
- return { ok: true, latency_ms: r.latency_ms };
1370
- return {
1371
- ok: false,
1372
- error: scrubSecrets(`HTTP ${r.status}: ${r.bodyText.slice(0, 200)}`),
1373
- latency_ms: r.latency_ms
1374
- };
1375
- }
1376
- async function checkOpenRouter(apiKey) {
1377
- const url = `${getOpenRouterBaseUrl()}/models`;
1378
- const r = await timedFetch(url, {
1379
- method: "GET",
1380
- headers: { ...getOpenRouterAttributionHeaders(url), Authorization: `Bearer ${apiKey}` }
1381
- });
1382
- if (r.ok)
1383
- return { ok: true, latency_ms: r.latency_ms };
1384
- return {
1385
- ok: false,
1386
- error: scrubSecrets(`HTTP ${r.status}: ${r.bodyText.slice(0, 200)}`),
1387
- latency_ms: r.latency_ms
1388
- };
1389
- }
1390
- async function checkOpenAICompatibleProvider(provider, apiKey, baseUrl = provider.baseUrl) {
1391
- const r = await timedFetch(`${baseUrl.replace(/\/+$/, "")}/models`, {
1392
- method: "GET",
1393
- headers: { Authorization: `Bearer ${apiKey}` }
1394
- });
1395
- if (r.ok)
1396
- return { ok: true, latency_ms: r.latency_ms };
1397
- return {
1398
- ok: false,
1399
- error: scrubSecrets(`HTTP ${r.status}: ${r.bodyText.slice(0, 200)}`),
1400
- latency_ms: r.latency_ms
1401
- };
1402
- }
1403
1368
  function codexAuthFileExists(env) {
1404
1369
  return checkCodexCredentials2(env).satisfiedBy === "file";
1405
1370
  }
@@ -1426,17 +1391,32 @@ async function validateProviderCredentials(provider, env = process.env, presence
1426
1391
  latency_ms: Date.now() - startedAt
1427
1392
  };
1428
1393
  }
1429
- const result = await validateRoute(route, env);
1430
- const latency_ms = Date.now() - startedAt;
1431
- if (result.status === "verified")
1432
- return { ok: true, latency_ms };
1433
- if (result.status === "configured")
1434
- return { ok: true, skipped: true, latency_ms };
1435
- return { ok: false, error: scrubSecrets(result.reason), latency_ms };
1394
+ const checkRoute = async (routeEnv) => {
1395
+ const start = Date.now();
1396
+ const result = await validateRoute(route, routeEnv);
1397
+ const latency_ms = Date.now() - start;
1398
+ if (result.status === "verified")
1399
+ return { ok: true, latency_ms };
1400
+ if (result.status === "configured")
1401
+ return { ok: true, skipped: true, latency_ms };
1402
+ return {
1403
+ ok: false,
1404
+ error: scrubSecrets(result.reason),
1405
+ httpStatus: result.httpStatus,
1406
+ latency_ms
1407
+ };
1408
+ };
1409
+ const keyVar = route.auth.kind === "subscription" ? "CLAUDE_CODE_OAUTH_TOKEN" : ("secretKey" in route.auth) ? route.auth.secretKey : undefined;
1410
+ const value = keyVar ? env[keyVar] : undefined;
1411
+ if (keyVar && value && CREDENTIAL_POOL_VARS.includes(keyVar)) {
1412
+ return checkEachKey(keyVar, value, (member) => checkRoute({ ...env, [keyVar]: member }));
1413
+ }
1414
+ return checkRoute(env);
1436
1415
  }
1437
1416
  case "claude-managed": {
1438
- if (env.ANTHROPIC_API_KEY)
1439
- return checkAnthropicApiKey(env.ANTHROPIC_API_KEY);
1417
+ if (env.ANTHROPIC_API_KEY) {
1418
+ return checkEachKey("ANTHROPIC_API_KEY", env.ANTHROPIC_API_KEY, checkAnthropicApiKey);
1419
+ }
1440
1420
  return {
1441
1421
  ok: false,
1442
1422
  error: "ANTHROPIC_API_KEY is not set.",
@@ -1444,14 +1424,30 @@ async function validateProviderCredentials(provider, env = process.env, presence
1444
1424
  };
1445
1425
  }
1446
1426
  case "codex": {
1427
+ const gateway = deriveDefaultRoute("codex", env);
1428
+ if (gateway) {
1429
+ const result = await validateRoute(gateway, env);
1430
+ const latency_ms = Date.now() - startedAt;
1431
+ if (result.status === "verified")
1432
+ return { ok: true, latency_ms };
1433
+ if (result.status === "configured")
1434
+ return { ok: true, skipped: true, latency_ms };
1435
+ return {
1436
+ ok: false,
1437
+ error: scrubSecrets(result.reason),
1438
+ httpStatus: result.httpStatus,
1439
+ latency_ms
1440
+ };
1441
+ }
1447
1442
  if (codexAuthFileExists(env))
1448
1443
  return presenceCheckOk();
1449
1444
  if (parseCodexOAuthAccess(env.CODEX_OAUTH))
1450
1445
  return presenceCheckOk();
1451
1446
  if (hasCodexOAuthPoolSlots(env))
1452
1447
  return presenceCheckOk();
1453
- if (env.OPENAI_API_KEY)
1454
- return checkOpenAiApiKey(env.OPENAI_API_KEY);
1448
+ if (env.OPENAI_API_KEY) {
1449
+ return checkEachKey("OPENAI_API_KEY", env.OPENAI_API_KEY, checkOpenAiApiKey);
1450
+ }
1455
1451
  return {
1456
1452
  ok: false,
1457
1453
  error: "No codex credential found (no ~/.codex/auth.json, CODEX_OAUTH, or OPENAI_API_KEY).",
@@ -1466,16 +1462,19 @@ async function validateProviderCredentials(provider, env = process.env, presence
1466
1462
  const status = presence ?? await checkProviderCredentials(provider, env);
1467
1463
  if (status.ready && status.satisfiedBy === "file")
1468
1464
  return presenceCheckOk();
1469
- if (env.OPENROUTER_API_KEY)
1470
- return checkOpenRouter(env.OPENROUTER_API_KEY);
1471
- if (env.ANTHROPIC_API_KEY)
1472
- return checkAnthropicApiKey(env.ANTHROPIC_API_KEY);
1473
- if (env.OPENAI_API_KEY)
1474
- return checkOpenAiApiKey(env.OPENAI_API_KEY);
1465
+ if (env.OPENROUTER_API_KEY) {
1466
+ return checkEachKey("OPENROUTER_API_KEY", env.OPENROUTER_API_KEY, checkOpenRouter);
1467
+ }
1468
+ if (env.ANTHROPIC_API_KEY) {
1469
+ return checkEachKey("ANTHROPIC_API_KEY", env.ANTHROPIC_API_KEY, checkAnthropicApiKey);
1470
+ }
1471
+ if (env.OPENAI_API_KEY) {
1472
+ return checkEachKey("OPENAI_API_KEY", env.OPENAI_API_KEY, checkOpenAiApiKey);
1473
+ }
1475
1474
  for (const direct of openAICompatibleProviders()) {
1476
1475
  const key = providerKeyFromEnv(direct, env);
1477
1476
  if (key) {
1478
- return checkOpenAICompatibleProvider(direct, key, providerBaseUrl(direct, env));
1477
+ return checkEachKey(direct.envVar, key, (member) => checkOpenAICompatibleProvider(direct, member, providerBaseUrl(direct, env)));
1479
1478
  }
1480
1479
  }
1481
1480
  if (status.ready)
@@ -1496,27 +1495,37 @@ async function validateProviderCredentials(provider, env = process.env, presence
1496
1495
  };
1497
1496
  }
1498
1497
  const baseUrl = env.DEVIN_API_BASE_URL ?? "https://api.devin.ai";
1499
- const r = await timedFetch(`${baseUrl.replace(/\/+$/, "")}/v3/self`, {
1500
- method: "GET",
1501
- headers: {
1502
- Authorization: `Bearer ${apiKey}`,
1503
- "Content-Type": "application/json"
1504
- }
1498
+ return checkEachKey("DEVIN_API_KEY", apiKey, async (member) => {
1499
+ const r = await timedFetch(`${baseUrl.replace(/\/+$/, "")}/v3/self`, {
1500
+ method: "GET",
1501
+ headers: {
1502
+ Authorization: `Bearer ${member}`,
1503
+ "Content-Type": "application/json"
1504
+ }
1505
+ });
1506
+ if (r.ok)
1507
+ return { ok: true, latency_ms: r.latency_ms };
1508
+ return {
1509
+ ok: false,
1510
+ error: scrubSecrets(`HTTP ${r.status}: ${r.bodyText.slice(0, 200)}`),
1511
+ httpStatus: r.status,
1512
+ latency_ms: r.latency_ms
1513
+ };
1505
1514
  });
1506
- if (r.ok)
1507
- return { ok: true, latency_ms: r.latency_ms };
1508
- return {
1509
- ok: false,
1510
- error: scrubSecrets(`HTTP ${r.status}: ${r.bodyText.slice(0, 200)}`),
1511
- latency_ms: r.latency_ms
1512
- };
1513
1515
  }
1514
- case "dsh":
1515
- return checkDshCredentials2(env).ready ? presenceCheckOk() : {
1516
+ case "dsh": {
1517
+ const deepseekKey = env.DEEPSEEK_API_KEY?.trim();
1518
+ if (deepseekKey)
1519
+ return checkEachKey("DEEPSEEK_API_KEY", deepseekKey, checkDeepSeekApiKey);
1520
+ const openRouterKey = env.OPENROUTER_API_KEY?.trim();
1521
+ if (openRouterKey)
1522
+ return checkEachKey("OPENROUTER_API_KEY", openRouterKey, checkOpenRouter);
1523
+ return {
1516
1524
  ok: false,
1517
1525
  error: "Set DEEPSEEK_API_KEY or OPENROUTER_API_KEY for dsh.",
1518
1526
  latency_ms: Date.now() - startedAt
1519
1527
  };
1528
+ }
1520
1529
  case "amp": {
1521
1530
  if (!checkAmpCredentials2(env).ready) {
1522
1531
  return {
@@ -1525,12 +1534,15 @@ async function validateProviderCredentials(provider, env = process.env, presence
1525
1534
  latency_ms: Date.now() - startedAt
1526
1535
  };
1527
1536
  }
1528
- const live = await liveTestAmpCredentials2(env);
1529
- return live.ok ? { ok: true, latency_ms: Date.now() - startedAt } : {
1530
- ok: false,
1531
- error: live.error ?? "amp usage failed",
1532
- latency_ms: Date.now() - startedAt
1533
- };
1537
+ return checkEachKey("AMP_API_KEY", env.AMP_API_KEY, async (member) => {
1538
+ const start = Date.now();
1539
+ const live = await liveTestAmpCredentials2({ ...env, AMP_API_KEY: member });
1540
+ return live.ok ? { ok: true, latency_ms: Date.now() - start } : {
1541
+ ok: false,
1542
+ error: live.error ?? "amp usage failed",
1543
+ latency_ms: Date.now() - start
1544
+ };
1545
+ });
1534
1546
  }
1535
1547
  case "cursor": {
1536
1548
  const apiKey = env.CURSOR_API_KEY?.trim();
@@ -1541,17 +1553,21 @@ async function validateProviderCredentials(provider, env = process.env, presence
1541
1553
  latency_ms: Date.now() - startedAt
1542
1554
  };
1543
1555
  }
1544
- const { liveTestCursorKey } = await import("./cursor-adapter-623qxqew.js");
1545
- const result = await liveTestCursorKey(apiKey);
1546
- return result.ok ? { ok: true, latency_ms: Date.now() - startedAt } : { ok: false, error: result.error, latency_ms: Date.now() - startedAt };
1556
+ const { liveTestCursorKey } = await import("./cursor-adapter-yss3pg7t.js");
1557
+ return checkEachKey("CURSOR_API_KEY", apiKey, async (member) => {
1558
+ const start = Date.now();
1559
+ const result = await liveTestCursorKey(member);
1560
+ return result.ok ? { ok: true, latency_ms: Date.now() - start } : { ok: false, error: result.error, latency_ms: Date.now() - start };
1561
+ });
1547
1562
  }
1548
1563
  case "grok": {
1549
1564
  const apiKey = env.XAI_API_KEY?.trim();
1550
1565
  if (apiKey)
1551
- return checkXaiApiKey(apiKey);
1566
+ return checkEachKey("XAI_API_KEY", apiKey, checkXaiApiKey);
1552
1567
  const openRouterKey = env.OPENROUTER_API_KEY?.trim();
1553
- if (openRouterKey)
1554
- return checkOpenRouter(openRouterKey);
1568
+ if (openRouterKey) {
1569
+ return checkEachKey("OPENROUTER_API_KEY", openRouterKey, checkOpenRouter);
1570
+ }
1555
1571
  return {
1556
1572
  ok: false,
1557
1573
  error: "Set XAI_API_KEY or OPENROUTER_API_KEY for grok.",
@@ -1572,7 +1588,7 @@ async function validateProviderCredentials(provider, env = process.env, presence
1572
1588
  }
1573
1589
  }
1574
1590
  function isCredCheckDisabled(env) {
1575
- return env.CRED_CHECK_DISABLE === "1";
1591
+ return isEnvFlagEnabled("CRED_CHECK_DISABLE", false, env);
1576
1592
  }
1577
1593
  async function buildCredStatusReport(provider, env, opts = {}, kind) {
1578
1594
  const presence = await checkProviderCredentials(provider, env, opts);
@@ -1583,7 +1599,9 @@ async function buildCredStatusReport(provider, env, opts = {}, kind) {
1583
1599
  ok: live.ok,
1584
1600
  error: live.error ?? null,
1585
1601
  latency_ms: live.latency_ms,
1586
- testedAt: Date.now()
1602
+ testedAt: Date.now(),
1603
+ ...live.warning !== undefined ? { warning: live.warning } : {},
1604
+ ...live.keys !== undefined ? { keys: live.keys } : {}
1587
1605
  };
1588
1606
  }
1589
1607
  const bedrock = presence.bedrockRegion !== undefined ? {
@@ -1678,13 +1696,56 @@ function buildLatestModelReport(opts) {
1678
1696
 
1679
1697
  // src/commands/credential-refresh.ts
1680
1698
  var CREDENTIAL_RETRY_INTERVAL_MS = 30000;
1699
+ var KEY_RECHECK_INTERVAL_MS = 10 * 60000;
1681
1700
  var BEDROCK_REFRESH_INTERVAL_MS = 5 * 60 * 1000;
1701
+ function credentialFingerprint(env) {
1702
+ return Bun.hash(JSON.stringify([...CREDENTIAL_POOL_VARS, "ANTHROPIC_AUTH_TOKEN", "ANTHROPIC_BASE_URL"].map((key) => env[key] ?? null))).toString();
1703
+ }
1704
+ function recheckableFailures(liveTest) {
1705
+ const keys = liveTest?.keys;
1706
+ if (keys?.length) {
1707
+ return keys.filter((key) => !key.ok && key.keyType !== "CLAUDE_CODE_OAUTH_TOKEN").length;
1708
+ }
1709
+ return liveTest?.ok === false ? 1 : 0;
1710
+ }
1711
+ async function reportKeyValidation(api, keys) {
1712
+ for (const keyType of new Set(keys.map((key) => key.keyType))) {
1713
+ try {
1714
+ const response = await fetch(`${api.apiUrl}/api/keys/report-validation`, {
1715
+ method: "POST",
1716
+ headers: {
1717
+ "Content-Type": "application/json",
1718
+ Authorization: `Bearer ${api.apiKey}`,
1719
+ "X-Agent-ID": api.agentId
1720
+ },
1721
+ body: JSON.stringify({
1722
+ keyType,
1723
+ keys: keys.filter((key) => key.keyType === keyType).map((key) => ({
1724
+ keyIndex: key.index,
1725
+ keySuffix: key.suffix,
1726
+ ok: key.ok,
1727
+ httpStatus: key.httpStatus
1728
+ }))
1729
+ }),
1730
+ signal: AbortSignal.timeout(5000)
1731
+ });
1732
+ if (!response.ok)
1733
+ throw new Error(`HTTP ${response.status}`);
1734
+ } catch (err) {
1735
+ const message = err instanceof Error ? err.message : String(err);
1736
+ console.warn(scrubSecrets(`[credentials] Failed to report key validation: ${message}`));
1737
+ }
1738
+ }
1739
+ }
1682
1740
  async function refreshCredentialStatus(api, state, harnessProvider, env, now = Date.now()) {
1683
1741
  if (isCredCheckDisabled(env) || state.inFlight)
1684
1742
  return;
1685
1743
  const providerChanged = state.harnessProvider !== harnessProvider;
1744
+ const fingerprint = credentialFingerprint(env);
1745
+ const fingerprintChanged = state.fingerprint !== fingerprint;
1686
1746
  const retryDue = state.ready !== true && now - state.lastRefreshAt >= CREDENTIAL_RETRY_INTERVAL_MS;
1687
- if (!providerChanged && !retryDue && !shouldRefreshBedrockStatus({
1747
+ const keyRecheckDue = state.rejectedKeys > 0 && now - state.lastRefreshAt >= KEY_RECHECK_INTERVAL_MS;
1748
+ if (!providerChanged && !fingerprintChanged && !retryDue && !keyRecheckDue && !shouldRefreshBedrockStatus({
1688
1749
  harnessProvider,
1689
1750
  env,
1690
1751
  lastRefreshAt: state.lastRefreshAt,
@@ -1706,8 +1767,14 @@ async function refreshCredentialStatus(api, state, harnessProvider, env, now = D
1706
1767
  missing: snapshot.missing,
1707
1768
  credStatus: snapshot
1708
1769
  });
1709
- if (state.harnessProvider === harnessProvider)
1770
+ if (state.harnessProvider === harnessProvider) {
1710
1771
  state.ready = snapshot.ready;
1772
+ state.fingerprint = fingerprint;
1773
+ state.rejectedKeys = recheckableFailures(snapshot.liveTest);
1774
+ const keys = snapshot.liveTest?.keys;
1775
+ if (keys?.length)
1776
+ await reportKeyValidation(api, keys);
1777
+ }
1711
1778
  } finally {
1712
1779
  state.inFlight = false;
1713
1780
  }
@@ -1735,7 +1802,7 @@ function resolveBackoff(override, env) {
1735
1802
  };
1736
1803
  return {
1737
1804
  initialMs: override?.initialMs ?? parsePositive(env.BOOT_INITIAL_BACKOFF_MS, 2000),
1738
- maxMs: override?.maxMs ?? parsePositive(env.BOOT_MAX_BACKOFF_MS, 30000),
1805
+ maxMs: override?.maxMs ?? parsePositive(env.BOOT_MAX_BACKOFF_MS, 1e4),
1739
1806
  maxWaitSeconds: override?.maxWaitSeconds ?? parsePositive(env.BOOT_MAX_WAIT_SECONDS, 0)
1740
1807
  };
1741
1808
  }
@@ -2499,6 +2566,7 @@ async function fetchResolvedEnv(apiUrl, apiKey, agentId, baseEnv = process.env,
2499
2566
  env
2500
2567
  });
2501
2568
  const effectiveModel = modelSelection.model || env.MODEL_OVERRIDE || "";
2569
+ const credentialEnv = { ...env };
2502
2570
  const credentialSelections = await resolveCredentialPools(env, {
2503
2571
  apiUrl,
2504
2572
  apiKey,
@@ -2507,7 +2575,7 @@ async function fetchResolvedEnv(apiUrl, apiKey, agentId, baseEnv = process.env,
2507
2575
  localBlocks: sessionContext?.localBlocks,
2508
2576
  enforceModelCapacity: sessionContext?.enforceModelCapacity
2509
2577
  });
2510
- return { env, credentialSelections, resolvedProvider, scriptsOnlyConfigValue };
2578
+ return { env, credentialEnv, credentialSelections, resolvedProvider, scriptsOnlyConfigValue };
2511
2579
  }
2512
2580
  async function ensureAgentFsCredentials(apiUrl, apiKey, agentId) {
2513
2581
  if (!apiUrl || !apiKey || !agentId || agentId === "unknown")
@@ -4324,7 +4392,7 @@ async function spawnProviderProcess(adapter, opts, logDir, isYolo) {
4324
4392
  const sessionEffort = effectiveReasoningEffort(adapter.name, model, reasoningEffortOverride);
4325
4393
  let oauthSelection;
4326
4394
  let oauthIsPoolBacked = false;
4327
- if (adapter.name === "codex") {
4395
+ if (adapter.name === "codex" && !deriveDefaultRoute("codex", freshEnv)) {
4328
4396
  const oauthInfo = await resolveCodexOAuthCredentialInfo(opts.apiUrl, opts.apiKey);
4329
4397
  oauthSelection = oauthInfo?.selection;
4330
4398
  oauthIsPoolBacked = oauthInfo?.isPoolBacked ?? false;
@@ -5434,8 +5502,11 @@ ${additionalSystemPrompt}` : basePrompt;
5434
5502
  harnessProvider: null,
5435
5503
  ready: null,
5436
5504
  lastRefreshAt: 0,
5437
- inFlight: false
5505
+ inFlight: false,
5506
+ fingerprint: null,
5507
+ rejectedKeys: 0
5438
5508
  };
5509
+ let latestCredentialEnv;
5439
5510
  let lastHarnessReconcileAt = 0;
5440
5511
  const HARNESS_RECONCILE_INTERVAL_MS = 1e4;
5441
5512
  let lastServerCapsRefreshAt = 0;
@@ -5650,6 +5721,11 @@ ${additionalSystemPrompt}` : basePrompt;
5650
5721
  credentialRefreshState.harnessProvider = state.harnessProvider;
5651
5722
  credentialRefreshState.ready = bootCredSnapshot?.ready ?? true;
5652
5723
  credentialRefreshState.lastRefreshAt = Date.now();
5724
+ credentialRefreshState.fingerprint = credentialFingerprint(process.env);
5725
+ credentialRefreshState.rejectedKeys = recheckableFailures(bootCredSnapshot?.liveTest);
5726
+ const keys = bootCredSnapshot?.liveTest?.keys;
5727
+ if (keys?.length)
5728
+ await reportKeyValidation(apiConfig, keys);
5653
5729
  } catch (error) {
5654
5730
  console.error(`[${role}] Failed to report credential readiness after recovery: ${error}`);
5655
5731
  process.exit(1);
@@ -6074,9 +6150,11 @@ ${additionalSystemPrompt}` : basePrompt;
6074
6150
  try {
6075
6151
  const {
6076
6152
  env: freshEnv,
6153
+ credentialEnv,
6077
6154
  resolvedProvider,
6078
6155
  scriptsOnlyConfigValue
6079
6156
  } = await fetchResolvedEnv(apiUrl, apiKey, agentId);
6157
+ latestCredentialEnv = credentialEnv;
6080
6158
  const nextScriptsOnly = resolveScriptsOnlyMode({
6081
6159
  env: process.env.SCRIPTS_ONLY_MCP,
6082
6160
  configValue: scriptsOnlyConfigValue
@@ -6089,7 +6167,7 @@ ${additionalSystemPrompt}` : basePrompt;
6089
6167
  console.warn(`[${role}] [harness] Reconcile fetch failed (non-fatal): ${err}`);
6090
6168
  }
6091
6169
  }
6092
- refreshCredentialStatus(apiConfig, credentialRefreshState, state.harnessProvider, process.env).catch((err) => console.warn(`[${role}] cred_status post_task refresh failed (non-fatal): ${err}`));
6170
+ refreshCredentialStatus(apiConfig, credentialRefreshState, state.harnessProvider, latestCredentialEnv ?? process.env).catch((err) => console.warn(`[${role}] cred_status post_task refresh failed (non-fatal): ${err}`));
6093
6171
  const now = Date.now();
6094
6172
  for (const [taskId, task] of state.activeTasks) {
6095
6173
  if (vcsDetectedTasks.has(taskId))