@desplega.ai/agent-swarm 2.5.4 → 2.6.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 (271) hide show
  1. package/README.md +2 -2
  2. package/dist/{acp-adapter-ek38cwsv.js → acp-adapter-dgfakfpw.js} +9 -9
  3. package/dist/{actions-92mepq03.js → actions-fbqma8aa.js} +21 -21
  4. package/dist/{amp-adapter-9gaxg015.js → amp-adapter-en0jy6hs.js} +4 -4
  5. package/dist/{app-ctn8gsgx.js → app-k8a5cgpp.js} +3 -3
  6. package/dist/{assistant-zyr5kz47.js → assistant-a16433gr.js} +29 -25
  7. package/dist/{boot-reembed-dwzfttdr.js → boot-reembed-6c1sjfnr.js} +1 -1
  8. package/dist/{boot-reembed-w75maga2.js → boot-reembed-f4nn561n.js} +1 -1
  9. package/dist/{boot-scrub-sweep-e9kq43kf.js → boot-scrub-sweep-d4w9gajf.js} +4 -4
  10. package/dist/{boot-seeds-x28v3fhb.js → boot-seeds-9bmkspyw.js} +4 -4
  11. package/dist/{claude-adapter-f0afqnne.js → claude-adapter-nys1kjxa.js} +9 -9
  12. package/dist/{claude-managed-adapter-x81a7r65.js → claude-managed-adapter-55207973.js} +2 -2
  13. package/dist/{claude-managed-setup-bqzwjd9x.js → claude-managed-setup-3cm35gey.js} +10 -3
  14. package/dist/{claude-sdk-session-7b7whkaq.js → claude-sdk-session-nw5yd8cp.js} +11 -11
  15. package/dist/{cli-c61mbdds.js → cli-03gg9pd1.js} +4 -4
  16. package/dist/{cli-kxpfx2xr.js → cli-0z1xjzwa.js} +2 -2
  17. package/dist/cli-1tem6ns9.js +894 -0
  18. package/dist/{cli-jbnn4vxb.js → cli-24j1jeeb.js} +3 -3
  19. package/dist/{cli-pzatvw94.js → cli-2sjhpsns.js} +2 -2
  20. package/dist/{cli-dew6x255.js → cli-39aet655.js} +2 -2
  21. package/dist/{cli-g1cw7xtt.js → cli-39rrw8yp.js} +1 -1
  22. package/dist/{cli-x0f2v69c.js → cli-3aqd4jaa.js} +12 -7
  23. package/dist/{cli-gbfxp48k.js → cli-3fwqy71j.js} +15 -15
  24. package/dist/{cli-7p4jxgtt.js → cli-3gfvmzht.js} +6 -6
  25. package/dist/{cli-03vpq45j.js → cli-3ndmpxxv.js} +2 -2
  26. package/dist/{cli-asq5ydm4.js → cli-4hxrf0p4.js} +131 -50
  27. package/dist/{cli-mz9afxxf.js → cli-4rf0f5vg.js} +15 -3
  28. package/dist/{cli-k4tjsdx9.js → cli-5rj83bam.js} +272 -195
  29. package/dist/{cli-sbwsxvtd.js → cli-5sckpqcx.js} +2 -2
  30. package/dist/{cli-cz5nmdxt.js → cli-683y0b3a.js} +2 -2
  31. package/dist/{cli-ethgy7ha.js → cli-6y51ryva.js} +2 -2
  32. package/dist/{cli-n4c8e3s5.js → cli-708wdy32.js} +1 -1
  33. package/dist/{cli-pasyvjmm.js → cli-737pyqxr.js} +1 -1
  34. package/dist/{cli-gx4rm0qx.js → cli-7enjwya9.js} +1 -1
  35. package/dist/{cli-6x9ma5w5.js → cli-803188pb.js} +1 -1
  36. package/dist/{cli-hh5we352.js → cli-9abdgn5t.js} +7 -7
  37. package/dist/{cli-ff1tm9n9.js → cli-a2rr0fmg.js} +1 -1
  38. package/dist/{cli-c952c7ac.js → cli-a34pr3w1.js} +2 -2
  39. package/dist/{cli-s682zgqz.js → cli-abkm71vr.js} +1 -1
  40. package/dist/{cli-mmhj8vd7.js → cli-ag2yrnt5.js} +11 -2
  41. package/dist/{cli-bvpgr9ny.js → cli-aj8djyqt.js} +5 -5
  42. package/dist/{cli-gwhjmh8g.js → cli-art7c1zh.js} +5 -5
  43. package/dist/{cli-5bnsc0e1.js → cli-az25fn5f.js} +4 -4
  44. package/dist/{cli-9s05422w.js → cli-bqztfyve.js} +1 -1
  45. package/dist/{cli-bn0rewsy.js → cli-c081bj3b.js} +2 -2
  46. package/dist/{cli-1r5ad7j5.js → cli-c2habvsf.js} +12 -12
  47. package/dist/{cli-64mh9mf3.js → cli-ca6banwz.js} +69 -17
  48. package/dist/{cli-25n3mv5d.js → cli-cz37jqss.js} +5 -5
  49. package/dist/{cli-6n8axjv1.js → cli-d2dpf95n.js} +2 -2
  50. package/dist/{cli-gn5af0x5.js → cli-emhjcj2y.js} +11 -11
  51. package/dist/{cli-6a1xg1p7.js → cli-esakngh8.js} +2 -2
  52. package/dist/{cli-ha9rmwgq.js → cli-fb8m699c.js} +2 -2
  53. package/dist/{cli-4b2z6n0m.js → cli-ffvsj2qw.js} +17 -8
  54. package/dist/{cli-abs8ndtr.js → cli-g20jjwt4.js} +26 -26
  55. package/dist/{cli-jb30dzvk.js → cli-g8ka5j4j.js} +446 -164
  56. package/dist/{cli-19202kew.js → cli-gf95q3bm.js} +5 -5
  57. package/dist/{cli-eftzyh9y.js → cli-gnsb1zxa.js} +2 -2
  58. package/dist/{cli-nwyw3zhg.js → cli-gxee0bqa.js} +1 -1
  59. package/dist/{cli-e42vss7b.js → cli-hfeb68z4.js} +5 -5
  60. package/dist/{cli-g9vd9ece.js → cli-k21gx5ht.js} +14 -16
  61. package/dist/{cli-tsma7p8v.js → cli-kf4jree9.js} +2 -2
  62. package/dist/{cli-dabehxhp.js → cli-kt907da6.js} +1 -1
  63. package/dist/{cli-wx2nj19m.js → cli-m5a9m0ak.js} +6 -6
  64. package/dist/{cli-621ce7kw.js → cli-m70bajzr.js} +3 -3
  65. package/dist/{cli-9j129brq.js → cli-mtnj4fwa.js} +6 -6
  66. package/dist/{cli-xzfq4at3.js → cli-mvjz5an3.js} +15 -11
  67. package/dist/{cli-277c31dw.js → cli-n7asmce6.js} +225 -3
  68. package/dist/{cli-xtrz6bzs.js → cli-nn6vx2mq.js} +1 -1
  69. package/dist/{cli-2655k16q.js → cli-nq677csy.js} +1 -1
  70. package/dist/{cli-0shx9j93.js → cli-pfk92eqz.js} +2 -2
  71. package/dist/{cli-wghjkr0e.js → cli-sqma6vw1.js} +10 -7
  72. package/dist/{cli-nzfnt2gs.js → cli-tf1n0r0b.js} +1 -1
  73. package/dist/{cli-qqzmjxkf.js → cli-v49fkghp.js} +11 -6
  74. package/dist/{cli-x77gen2p.js → cli-w2656ka1.js} +7 -7
  75. package/dist/{cli-5kqnemen.js → cli-yvy48785.js} +1 -1
  76. package/dist/{cli-m4ecdxvz.js → cli-zqne1qcj.js} +7 -7
  77. package/dist/cli.js +17 -17
  78. package/dist/{codex-adapter-wch12q99.js → codex-adapter-d95q4qsn.js} +7 -7
  79. package/dist/{codex-login-rn7c5gxt.js → codex-login-8cg0vhf2.js} +1 -1
  80. package/dist/{codex-session-runner-41pfcr95.js → codex-session-runner-gdwd8h0c.js} +8 -8
  81. package/dist/{commands-9849dkj6.js → commands-jqmgk54b.js} +2 -2
  82. package/dist/{controller-ja0sd95p.js → controller-z3jq589f.js} +4 -4
  83. package/dist/{controllers-connect-xp05dj6x.js → controllers-connect-r2za39ef.js} +23 -23
  84. package/dist/{cursor-adapter-623qxqew.js → cursor-adapter-4mr4jgkw.js} +2 -2
  85. package/dist/{db-47vj40dy.js → db-ppv2tze7.js} +3 -3
  86. package/dist/{db-w759qmx0.js → db-w36wwb5g.js} +4 -2
  87. package/dist/{devin-adapter-4ycy4vrf.js → devin-adapter-byen2cxt.js} +1 -1
  88. package/dist/{dispatcher-7b8e4z2j.js → dispatcher-pv5h77vf.js} +20 -20
  89. package/dist/{docker-s84hjs91.js → docker-fdzyewpz.js} +2 -2
  90. package/dist/{dsh-adapter-2ezw3xea.js → dsh-adapter-d4pdpb3r.js} +2 -2
  91. package/dist/{e2b-9gkdhm3c.js → e2b-222hsajc.js} +2 -2
  92. package/dist/{e2b-cjtf8k1z.js → e2b-fn3zacvt.js} +2 -2
  93. package/dist/{easter-egg-3d-e4qv8dxj.js → easter-egg-3d-4sp4dvmc.js} +1 -1
  94. package/dist/{event-bus-3z78ep5n.js → event-bus-pghg8hqy.js} +1 -1
  95. package/dist/{execute-0xpz8950.js → execute-jev839y1.js} +1 -1
  96. package/dist/{external-channel-e2s028da.js → external-channel-y6nkzhnn.js} +2 -2
  97. package/dist/{grok-adapter-ys7gaqee.js → grok-adapter-t08b9ntm.js} +10 -10
  98. package/dist/handlers-eqsnmv95.js +41 -0
  99. package/dist/{heartbeat-w3mntghj.js → heartbeat-vn31xwdk.js} +23 -23
  100. package/dist/{hook-g7kvv6x9.js → hook-6d0zbvvt.js} +6 -6
  101. package/dist/{hook-3jjywnpb.js → hook-cpjs8q51.js} +8 -8
  102. package/dist/{http-tkp7d4kb.js → http-9c6medda.js} +856 -99
  103. package/dist/{index-xdaahthb.js → index-38t35h0n.js} +20 -20
  104. package/dist/{index-3n8m9ea2.js → index-g6k9tctj.js} +1 -1
  105. package/dist/{index-1ef1myq2.js → index-k0yt1tvq.js} +20 -20
  106. package/dist/{index-31ceyf42.js → index-pkma1yf8.js} +1 -1
  107. package/dist/{index-q7m26kvs.js → index-qhjf2htm.js} +13 -10
  108. package/dist/index-yqgbfgaj.js +43 -0
  109. package/dist/{keepalive-v4ta8wgg.js → keepalive-em0117bp.js} +4 -4
  110. package/dist/lead-23e7z59t.js +79 -0
  111. package/dist/{maintenance-84n1ex21.js → maintenance-kbme3qy9.js} +1 -1
  112. package/dist/{oauth-refresh-sweep-vjnnandw.js → oauth-refresh-sweep-xysj4yse.js} +3 -3
  113. package/dist/{onboard-sfmpe4np.js → onboard-p6q0vz97.js} +3 -3
  114. package/dist/{opencode-adapter-jmpst4q4.js → opencode-adapter-esv3k9yn.js} +7 -7
  115. package/dist/{otel-impl-v6cc0zve.js → otel-impl-54qhqh1z.js} +2 -2
  116. package/dist/{pi-mono-adapter-fk8fkcf6.js → pi-mono-adapter-mymbwhj0.js} +10 -10
  117. package/dist/{pricing-refresh-fsk1e1zc.js → pricing-refresh-yb75wv33.js} +3 -3
  118. package/dist/{rbac-roles-prmkdnkw.js → rbac-roles-1vp2mw4p.js} +2 -2
  119. package/dist/{rbac-roles-zxmxqa39.js → rbac-roles-dexhc9x8.js} +1 -1
  120. package/dist/render-v2-tjay5hhf.js +16 -0
  121. package/dist/{resume-frdtgfa0.js → resume-8ayf37g5.js} +9 -9
  122. package/dist/{runtime-bt5pkpm1.js → runtime-hqe5cqcd.js} +1 -1
  123. package/dist/{session-access-fpez4y5q.js → session-access-fdhp987s.js} +4 -4
  124. package/dist/session-source-backfill-qgtc86z1.js +110 -0
  125. package/dist/{setup-mq6m3m8q.js → setup-4rrmqcq3.js} +1 -1
  126. package/dist/{virtual-modules-mnfbh5mr.js → virtual-modules-52km00d6.js} +2 -2
  127. package/dist/{work-objects-kfahhjsq.js → work-objects-p28fgd70.js} +23 -23
  128. package/dist/worker-e3w7vye1.js +79 -0
  129. package/dist/{x-pbpezr0s.js → x-wxrzvzx8.js} +2 -2
  130. package/openapi.json +1274 -32
  131. package/package.json +1 -1
  132. package/src/assets/source-key.ts +95 -0
  133. package/src/be/db/api-keys.ts +80 -0
  134. package/src/be/db/session-labels.ts +28 -0
  135. package/src/be/db/session-moves.ts +5 -6
  136. package/src/be/db/session-tree.ts +153 -14
  137. package/src/be/db/tasks/read.ts +11 -0
  138. package/src/be/db/tasks/write.ts +6 -1
  139. package/src/be/db/workflow-runs.ts +183 -1
  140. package/src/be/db-retention.ts +61 -6
  141. package/src/be/db.ts +59 -114
  142. package/src/be/memory/providers/openai-embedding.ts +5 -1
  143. package/src/be/migrations/244_api_key_validation.sql +4 -0
  144. package/src/be/onboarding.ts +4 -0
  145. package/src/be/scripts/typecheck.ts +1 -1
  146. package/src/be/session-source-backfill.ts +163 -0
  147. package/src/be/swarm-config-guard.ts +1 -0
  148. package/src/comb/review-batch.ts +28 -1
  149. package/src/comb/templates.ts +7 -2
  150. package/src/commands/claude-managed-setup.ts +7 -1
  151. package/src/commands/credential-refresh.ts +76 -1
  152. package/src/commands/credential-wait.ts +2 -2
  153. package/src/commands/provider-credentials.ts +210 -170
  154. package/src/commands/runner.ts +25 -4
  155. package/src/extensions/apply-task-create.ts +8 -1
  156. package/src/extensions/contract-types.generated.ts +1 -1
  157. package/src/extensions/contract.ts +5 -0
  158. package/src/http/all-routes.ts +2 -0
  159. package/src/http/api-keys.ts +53 -0
  160. package/src/http/assets.ts +15 -0
  161. package/src/http/codex-oauth-accounts.ts +191 -0
  162. package/src/http/comb.ts +15 -2
  163. package/src/http/config.ts +1 -1
  164. package/src/http/core.ts +6 -0
  165. package/src/http/fleet-benchmark.ts +5 -2
  166. package/src/http/index.ts +11 -0
  167. package/src/http/integrations.ts +5 -1
  168. package/src/http/kv.ts +8 -3
  169. package/src/http/onboarding.ts +6 -1
  170. package/src/http/pool-keys.ts +354 -0
  171. package/src/http/sessions.ts +37 -12
  172. package/src/http/stats.ts +1 -0
  173. package/src/http/status.ts +26 -12
  174. package/src/http/tasks.ts +3 -0
  175. package/src/http/used-by.ts +7 -2
  176. package/src/http/workflows.ts +78 -9
  177. package/src/integrations/chat-sdk/inbound.ts +27 -0
  178. package/src/kv-reserved-namespaces.ts +19 -0
  179. package/src/providers/acp-targets.ts +1 -1
  180. package/src/providers/amp-adapter.ts +1 -1
  181. package/src/providers/claude-adapter.ts +5 -1
  182. package/src/providers/claude-managed-adapter.ts +16 -9
  183. package/src/providers/codex-adapter.ts +71 -11
  184. package/src/scheduler/scheduler.ts +3 -2
  185. package/src/scripts-runtime/swarm-sdk.ts +7 -1
  186. package/src/scripts-runtime/types/stdlib.d.ts +1 -1
  187. package/src/scripts-runtime/types/swarm-extension.d.ts +17 -8
  188. package/src/scripts-runtime/types/swarm-sdk.d.ts +1 -1
  189. package/src/slack/assistant.ts +7 -0
  190. package/src/slack/channel-labels.ts +74 -0
  191. package/src/slack/handlers.ts +8 -0
  192. package/src/slack/inbound-files.ts +5 -2
  193. package/src/slack/thread-buffer.ts +4 -0
  194. package/src/tasks/sibling-awareness.ts +12 -3
  195. package/src/telemetry-context.ts +5 -6
  196. package/src/telemetry-identity.ts +3 -3
  197. package/src/tests/api-keys-validation.test.ts +170 -0
  198. package/src/tests/claude-managed-adapter.test.ts +46 -0
  199. package/src/tests/claude-routes-e2e.test.ts +7 -2
  200. package/src/tests/codex-credential-pools.test.ts +120 -0
  201. package/src/tests/codex-gateway-route.test.ts +165 -0
  202. package/src/tests/codex-oauth-accounts.test.ts +357 -0
  203. package/src/tests/comb-review-batch.test.ts +63 -2
  204. package/src/tests/config-pool-keys.test.ts +533 -0
  205. package/src/tests/credential-check.test.ts +290 -2
  206. package/src/tests/credential-refresh.test.ts +172 -1
  207. package/src/tests/db-retention.test.ts +9 -3
  208. package/src/tests/db-task-read-contract.test.ts +1 -0
  209. package/src/tests/db-task-write-contract.test.ts +1 -3
  210. package/src/tests/docs-index-footprint.test.js +3 -3
  211. package/src/tests/extensions-pre-task.test.ts +53 -1
  212. package/src/tests/fixtures/extensions/record-task-create/hooks.ts +9 -0
  213. package/src/tests/fixtures/extensions/record-task-create/manifest.json +7 -0
  214. package/src/tests/fleet-benchmark.test.ts +8 -0
  215. package/src/tests/get-workflow-run-tool.test.ts +98 -0
  216. package/src/tests/integrations-http.test.ts +32 -2
  217. package/src/tests/internal-ai/complete-structured.test.ts +37 -1
  218. package/src/tests/internal-ai/credentials.test.ts +23 -0
  219. package/src/tests/kv-http.test.ts +32 -0
  220. package/src/tests/kv-tool.test.ts +25 -0
  221. package/src/tests/multi-runtime-registration.test.ts +12 -12
  222. package/src/tests/onboarding.test.ts +108 -1
  223. package/src/tests/openai-embedding-credentials.test.ts +35 -0
  224. package/src/tests/openrouter-attribution-call-sites.test.ts +2 -2
  225. package/src/tests/org-website.test.ts +36 -0
  226. package/src/tests/provider-key-probes.test.ts +181 -0
  227. package/src/tests/rbac-e2e-helpers.test.ts +88 -1
  228. package/src/tests/rbac-e2e-helpers.ts +36 -11
  229. package/src/tests/script-connections.test.ts +2 -0
  230. package/src/tests/script-runs-retention.test.ts +212 -0
  231. package/src/tests/sdk-allowlist.test.ts +39 -0
  232. package/src/tests/session-source-backfill.test.ts +429 -0
  233. package/src/tests/session-source-keys.test.ts +236 -0
  234. package/src/tests/session-source-labels.test.ts +419 -0
  235. package/src/tests/sessions-detail-batch.test.ts +2 -0
  236. package/src/tests/sessions-move.test.ts +131 -0
  237. package/src/tests/sessions-tree.test.ts +299 -2
  238. package/src/tests/slack-inbound-files.test.ts +103 -23
  239. package/src/tests/status.test.ts +101 -18
  240. package/src/tests/tasks-workflow-run-filter.test.ts +146 -0
  241. package/src/tests/test-net.ts +31 -0
  242. package/src/tests/transcription.test.ts +8 -0
  243. package/src/tests/used-by-route.test.ts +11 -0
  244. package/src/tests/workflow-cascade-cancel.test.ts +172 -0
  245. package/src/tests/workflow-http-v2.test.ts +131 -0
  246. package/src/tests/workflow-step-order.test.ts +92 -0
  247. package/src/tests/workflow-sub-workflow.test.ts +30 -0
  248. package/src/tools/get-tasks.ts +8 -0
  249. package/src/tools/kv/kv-read-auth.ts +4 -2
  250. package/src/tools/task-action.ts +1 -1
  251. package/src/tools/workflows/get-workflow-run.ts +14 -4
  252. package/src/types.ts +24 -0
  253. package/src/utils/company-profile.ts +51 -1
  254. package/src/utils/credentials.ts +5 -2
  255. package/src/utils/internal-ai/complete-structured.ts +5 -0
  256. package/src/utils/internal-ai/credentials.ts +4 -3
  257. package/src/utils/provider-key-probes.ts +328 -0
  258. package/src/utils/transcription.ts +4 -1
  259. package/src/workflows/executors/sub-workflow.ts +8 -1
  260. package/templates/ai-toolbox.manifest.json +2 -2
  261. package/templates/skills/researching/content.md +2 -0
  262. package/templates/skills/swarm-scripts/SKILL.md +1 -0
  263. package/templates/skills/swarm-scripts/content.md +1 -0
  264. package/dist/cli-7421jzsw.js +0 -84
  265. package/dist/cli-e45e4m6b.js +0 -413
  266. package/dist/cli-zw88zjba.js +0 -307
  267. package/dist/handlers-wy1dr6ja.js +0 -41
  268. package/dist/index-nmm79qgr.js +0 -43
  269. package/dist/lead-sawnyqxk.js +0 -79
  270. package/dist/render-v2-pjwxvnkw.js +0 -12
  271. package/dist/worker-v5e5rxj3.js +0 -79
@@ -150,6 +150,8 @@ import {
150
150
  TelegramBotApiError,
151
151
  callTelegramBotApi,
152
152
  isTrustedTeamsServiceUrl,
153
+ getSessionLabels,
154
+ rememberSessionLabel,
153
155
  isChatSdkStopping,
154
156
  startChatSdk,
155
157
  getChatInstance,
@@ -176,6 +178,7 @@ import {
176
178
  extractAndVerifyCookie,
177
179
  pageSessionSetCookies,
178
180
  resolveHttpRequestAuth,
181
+ getDeploymentEnvValue,
179
182
  loadGlobalConfigsIntoEnv,
180
183
  reloadGlobalConfigsAndIntegrations,
181
184
  scheduleIntegrationsReload,
@@ -227,6 +230,7 @@ import {
227
230
  getTasksOutputSchema,
228
231
  getTasksHandler,
229
232
  reservedNamespaceError,
233
+ privateNamespaceError,
230
234
  reservedRoomKeyError,
231
235
  updateMcpServerChecked,
232
236
  updateTouchesStdioExecution,
@@ -289,17 +293,23 @@ import {
289
293
  hasCapability,
290
294
  getEnabledCapabilities,
291
295
  createServer
292
- } from "./cli-asq5ydm4.js";
296
+ } from "./cli-4hxrf0p4.js";
293
297
  import {
294
298
  chatThreadOfContextKey,
295
299
  agentContextKey,
296
300
  pageContextKey,
297
301
  init_context_key,
302
+ sourceOfKey,
303
+ SOURCE_GROUPS_READ_ONLY,
304
+ sourceMoveError,
305
+ init_source_key,
298
306
  init_catalog,
299
307
  catalog_default,
300
308
  COMPANY_TEAM_SIZES,
301
309
  COMPANY_USE_CASES,
302
310
  USER_FUNCTIONS,
311
+ reportedUseCase,
312
+ reportedUserFunction,
303
313
  init_company_profile,
304
314
  TELEMETRY_PROXY_ORIGIN,
305
315
  normalizeOrgWebsite,
@@ -347,6 +357,7 @@ import {
347
357
  resolveTriggerSurface,
348
358
  emitTaskTelemetry,
349
359
  init_telemetry_trigger,
360
+ CODEX_AUTH_FAILURE_BENCH_THRESHOLD,
350
361
  CODEX_AUTH_WATCH_NAMESPACE,
351
362
  codexAuthBenchMarkerKey,
352
363
  init_codex_auth_failure,
@@ -410,6 +421,7 @@ import {
410
421
  listPrefixRoots,
411
422
  listSharedPrefixRoots,
412
423
  init_session_moves,
424
+ getSessionGroupKey,
413
425
  getSessionReadState,
414
426
  getSessionTree,
415
427
  triageSessionList,
@@ -446,6 +458,11 @@ import {
446
458
  assertWorkflowIdempotencyKeyUnused,
447
459
  recordAcceptedWorkflowOperation,
448
460
  init_workflow_idempotency,
461
+ getWorkflowRunSummary,
462
+ getWorkflowRunStepsSlimByRunId,
463
+ WORKFLOW_RUN_TREE_MAX_DEPTH,
464
+ WorkflowRunTreeError,
465
+ getWorkflowRunTree,
449
466
  getWorkflowRunParent,
450
467
  init_workflow_runs,
451
468
  CHAT_SDK_ADAPTER_NAMES,
@@ -537,6 +554,9 @@ import {
537
554
  init_steering,
538
555
  refreshActiveSessionOnActivity2,
539
556
  recordKeySeatMismatch2,
557
+ recordKeyValidation2,
558
+ retirePoolKeyStatus,
559
+ init_api_keys,
540
560
  getScriptRunExecutionArgs2,
541
561
  updateTaskVcs2,
542
562
  upsertAssetKeyMapping2,
@@ -743,7 +763,7 @@ import {
743
763
  countScriptRunJournalSteps2,
744
764
  countScriptRunJournalAgentTaskSteps2,
745
765
  init_db3
746
- } from "./cli-jb30dzvk.js";
766
+ } from "./cli-g8ka5j4j.js";
747
767
  import {
748
768
  PRIMARY_ROLE_NAMES2,
749
769
  getUserGrant2,
@@ -754,26 +774,26 @@ import {
754
774
  assertNotLastAdmin2,
755
775
  setUserRoles2,
756
776
  init_rbac_roles
757
- } from "./cli-ff1tm9n9.js";
758
- import"./cli-c61mbdds.js";
777
+ } from "./cli-a2rr0fmg.js";
778
+ import"./cli-03gg9pd1.js";
759
779
  import {
760
780
  normalizeModelKey
761
- } from "./cli-sbwsxvtd.js";
781
+ } from "./cli-5sckpqcx.js";
762
782
  import {
763
783
  upsertModelCatalogOverlay,
764
784
  deleteModelCatalogOverlay,
765
785
  loadModelsCatalog,
766
786
  requestModelCatalogRefresh2
767
- } from "./cli-bvpgr9ny.js";
787
+ } from "./cli-aj8djyqt.js";
768
788
  import {
769
789
  AMP_ESTIMATE_MODELS,
770
790
  ampBillsCacheWrites,
771
791
  resolveAmpModel
772
- } from "./cli-9s05422w.js";
792
+ } from "./cli-bqztfyve.js";
773
793
  import {
774
794
  workflowEventBus2,
775
795
  init_event_bus
776
- } from "./cli-dabehxhp.js";
796
+ } from "./cli-kt907da6.js";
777
797
  import {
778
798
  automationIntegrationFixUrl,
779
799
  preflightAutomation,
@@ -809,7 +829,7 @@ import {
809
829
  generateEdges,
810
830
  definitionNodeIds,
811
831
  validateDefinition
812
- } from "./cli-gbfxp48k.js";
832
+ } from "./cli-3fwqy71j.js";
813
833
  import {
814
834
  require_dist2,
815
835
  isInvalidClientError,
@@ -889,14 +909,14 @@ import {
889
909
  typecheckWithAmbient,
890
910
  typecheckScript,
891
911
  parseSkillContent
892
- } from "./cli-7p4jxgtt.js";
912
+ } from "./cli-3gfvmzht.js";
893
913
  import {
894
914
  buildAuthorizationUrl,
895
915
  exchangeAuthorizationCode,
896
916
  oauthAppRowToProviderConfig,
897
917
  forceRefreshAuthorizationOrThrow,
898
918
  forceRefreshTokenOrThrow
899
- } from "./cli-tsma7p8v.js";
919
+ } from "./cli-kf4jree9.js";
900
920
  import {
901
921
  signalProcessGroup,
902
922
  detachedProcessGroup,
@@ -924,27 +944,31 @@ import {
924
944
  getTaskCitationsForTasks,
925
945
  initialize,
926
946
  ensure,
947
+ callSlackWithRetry2,
948
+ slackErrorCode2,
927
949
  getSlackApp2,
928
950
  startSlackApp2,
929
951
  stopSlackApp2
930
- } from "./cli-abs8ndtr.js";
931
- import"./cli-eftzyh9y.js";
932
- import"./cli-qqzmjxkf.js";
952
+ } from "./cli-g20jjwt4.js";
953
+ import"./cli-gnsb1zxa.js";
954
+ import"./cli-v49fkghp.js";
933
955
  import {
934
956
  _fetchHolder,
935
957
  CLIENT_ID,
958
+ decodeJwt,
936
959
  exchangeAuthorizationCode2,
937
960
  getAccountId,
961
+ extractChatgptPlanType,
938
962
  deriveCodexKeySuffix,
939
963
  MAX_CODEX_OAUTH_SLOT,
940
964
  codexOAuthKeyForSlot,
941
965
  loadAllCodexOAuthSlots,
942
966
  getValidCodexOAuth
943
- } from "./cli-kxpfx2xr.js";
967
+ } from "./cli-0z1xjzwa.js";
944
968
  import {
945
969
  retryFailedRun2,
946
970
  cancelWorkflowRun2
947
- } from "./cli-x0f2v69c.js";
971
+ } from "./cli-3aqd4jaa.js";
948
972
  import {
949
973
  duplicateGuardedQueryKey,
950
974
  warnIfCorsAllowsAnyOrigin,
@@ -989,7 +1013,7 @@ import {
989
1013
  bodyListTask,
990
1014
  describeRequestRoute,
991
1015
  route
992
- } from "./cli-gwhjmh8g.js";
1016
+ } from "./cli-art7c1zh.js";
993
1017
  import {
994
1018
  FilesError,
995
1019
  normalizeFilesError,
@@ -1017,13 +1041,13 @@ import {
1017
1041
  resolvePoolDelivery2,
1018
1042
  createPoolAgent2,
1019
1043
  init_db
1020
- } from "./cli-19202kew.js";
1044
+ } from "./cli-gf95q3bm.js";
1021
1045
  import {
1022
1046
  RATING_MODEL_MAX_LENGTH,
1023
1047
  REFERENCES_SOURCE_MAX_LENGTH,
1024
1048
  sanitizeReferencesSource
1025
1049
  } from "./cli-3h26v7yj.js";
1026
- import"./cli-pasyvjmm.js";
1050
+ import"./cli-737pyqxr.js";
1027
1051
  import {
1028
1052
  startPoolRouting,
1029
1053
  stopPoolRouting,
@@ -1033,8 +1057,8 @@ import {
1033
1057
  checkHeartbeatChecklist2,
1034
1058
  runHeartbeatSweep2,
1035
1059
  stopHeartbeat2
1036
- } from "./cli-gn5af0x5.js";
1037
- import"./cli-6n8axjv1.js";
1060
+ } from "./cli-emhjcj2y.js";
1061
+ import"./cli-d2dpf95n.js";
1038
1062
  import {
1039
1063
  import_websocket,
1040
1064
  import_websocket_server
@@ -1043,18 +1067,18 @@ import {
1043
1067
  runtimeSupervisorStatus,
1044
1068
  startRuntimeSupervisor,
1045
1069
  stopRuntimeSupervisor
1046
- } from "./cli-1r5ad7j5.js";
1070
+ } from "./cli-c2habvsf.js";
1047
1071
  import"./cli-ns59dc6r.js";
1048
1072
  import {
1049
1073
  ACP_TARGET_IDS
1050
- } from "./cli-5kqnemen.js";
1074
+ } from "./cli-yvy48785.js";
1051
1075
  import {
1052
1076
  reasoningCapability,
1053
1077
  supportedReasoningLevels
1054
- } from "./cli-bn0rewsy.js";
1078
+ } from "./cli-c081bj3b.js";
1055
1079
  import {
1056
1080
  MAX_RATE_LIMIT_RESET_MS
1057
- } from "./cli-gx4rm0qx.js";
1081
+ } from "./cli-7enjwya9.js";
1058
1082
  import {
1059
1083
  isLeadChannelMonitoringEnabled,
1060
1084
  ORG_IDENTITY_KEYS,
@@ -1062,12 +1086,13 @@ import {
1062
1086
  SIMILARITY_THRESHOLD,
1063
1087
  memoryRelevance,
1064
1088
  isUnknownModelError,
1089
+ checkProviderPoolKey,
1065
1090
  writeSkillsToFilesystem
1066
- } from "./cli-277c31dw.js";
1091
+ } from "./cli-n7asmce6.js";
1067
1092
  import {
1068
1093
  inviteEmailToSharedOrg,
1069
1094
  ensureAgentFsCredentialsForAgent
1070
- } from "./cli-ethgy7ha.js";
1095
+ } from "./cli-6y51ryva.js";
1071
1096
  import {
1072
1097
  Anthropic
1073
1098
  } from "./cli-rr7zx19j.js";
@@ -1107,7 +1132,7 @@ import {
1107
1132
  revokeAgentTokens,
1108
1133
  fingerprintApiKey,
1109
1134
  init_users
1110
- } from "./cli-6a1xg1p7.js";
1135
+ } from "./cli-esakngh8.js";
1111
1136
  import"./cli-v41kn3cd.js";
1112
1137
  import"./cli-wgtk7xxr.js";
1113
1138
  import"./cli-1f0gp9vz.js";
@@ -1235,6 +1260,7 @@ import {
1235
1260
  ScriptRunListItemSchema,
1236
1261
  ScriptRunJournalEntrySchema,
1237
1262
  WorkflowRunStepSchema,
1263
+ WorkflowRunStepSlimSchema,
1238
1264
  PromptTemplateSchema,
1239
1265
  PromptTemplateHistorySchema,
1240
1266
  ScriptScopeSchema,
@@ -1271,31 +1297,35 @@ import {
1271
1297
  KvKeySchema,
1272
1298
  KvEntrySchema,
1273
1299
  init_types
1274
- } from "./cli-mz9afxxf.js";
1300
+ } from "./cli-4rf0f5vg.js";
1275
1301
  import {
1276
1302
  IDENTITY_FIELD_BUDGETS,
1277
1303
  IdentityFieldBudgetError,
1278
1304
  init_identity_field_budget
1279
- } from "./cli-e42vss7b.js";
1280
- import {
1281
- getSlackConfiguration,
1282
- init_config
1283
- } from "./cli-qeaq3j6t.js";
1305
+ } from "./cli-hfeb68z4.js";
1284
1306
  import {
1285
1307
  isSteeringEnabled2,
1286
1308
  init_steering_enabled
1287
1309
  } from "./cli-4sydckyj.js";
1288
1310
  import {
1289
- MODEL_SCOPED_WINDOWS,
1290
- activeModelBlocks,
1291
- init_model_rate_limit_windows
1292
- } from "./cli-7421jzsw.js";
1311
+ getSlackConfiguration,
1312
+ init_config
1313
+ } from "./cli-qeaq3j6t.js";
1293
1314
  import {
1294
1315
  SUBSCRIPTION_PLANS_CHECKED_AT,
1295
1316
  SUBSCRIPTION_PLANS,
1296
1317
  isSubscriptionPlanId,
1297
1318
  init_subscription_plans
1298
1319
  } from "./cli-7akn6ze9.js";
1320
+ import {
1321
+ MODEL_SCOPED_WINDOWS,
1322
+ activeModelBlocks,
1323
+ init_model_rate_limit_windows,
1324
+ CREDENTIAL_POOL_VARS,
1325
+ splitCredentialPool,
1326
+ selectCredential,
1327
+ init_credentials
1328
+ } from "./cli-1tem6ns9.js";
1299
1329
  import {
1300
1330
  getOpenRouterAttributionHeaders,
1301
1331
  init_openrouter_base_url
@@ -1344,7 +1374,7 @@ import {
1344
1374
  import {
1345
1375
  init_package,
1346
1376
  package_default
1347
- } from "./cli-xtrz6bzs.js";
1377
+ } from "./cli-nn6vx2mq.js";
1348
1378
  import {
1349
1379
  realtimeBus,
1350
1380
  init_bus
@@ -1372,12 +1402,15 @@ import {
1372
1402
  findSecretsIn,
1373
1403
  scrubObject,
1374
1404
  registerVolatileSecret,
1405
+ registerEnvSecrets,
1375
1406
  init_secret_scrubber
1376
- } from "./cli-n4c8e3s5.js";
1407
+ } from "./cli-708wdy32.js";
1377
1408
  import {
1378
1409
  isAlias,
1410
+ baseUrlEnvVar,
1411
+ providerForKeyVar,
1379
1412
  init_src2
1380
- } from "./cli-nwyw3zhg.js";
1413
+ } from "./cli-gxee0bqa.js";
1381
1414
  import {
1382
1415
  __toESM
1383
1416
  } from "./cli-242037k3.js";
@@ -1435,6 +1468,7 @@ init_db3();
1435
1468
 
1436
1469
  // src/be/db-retention.ts
1437
1470
  import { AsyncLocalStorage } from "node:async_hooks";
1471
+ init_types();
1438
1472
  init_env_flag();
1439
1473
  init_secret_scrubber();
1440
1474
  init_db3();
@@ -1479,6 +1513,19 @@ var DB_RETENTION_TABLES = [
1479
1513
  metricsKey: "contextVersions",
1480
1514
  initialBatchSize: 50,
1481
1515
  maxBatchSize: 100
1516
+ },
1517
+ {
1518
+ table: "script_runs",
1519
+ policy: "age",
1520
+ timeColumn: "startedAt",
1521
+ cutoffFormat: "sqliteDatetime",
1522
+ statusColumn: "status",
1523
+ terminalStatuses: TERMINAL_SCRIPT_RUN_STATUSES,
1524
+ keepWhenSet: "idempotencyKey",
1525
+ envKey: "SCRIPT_RUNS_RETENTION_DAYS",
1526
+ metricsKey: "scriptRuns",
1527
+ initialBatchSize: 100,
1528
+ maxBatchSize: 500
1482
1529
  }
1483
1530
  ];
1484
1531
 
@@ -1612,13 +1659,26 @@ function sweepStatements(table, value, now) {
1612
1659
  params: [value]
1613
1660
  };
1614
1661
  }
1615
- const cutoff = new Date(now.getTime() - value * DAY_MS).toISOString();
1662
+ const iso = new Date(now.getTime() - value * DAY_MS).toISOString();
1663
+ const cutoff = "cutoffFormat" in table ? `${iso.slice(0, 10)} ${iso.slice(11, 19)}` : iso;
1664
+ const conditions = [];
1665
+ const params = [];
1666
+ if ("terminalStatuses" in table) {
1667
+ conditions.push(`${table.statusColumn} IN (${table.terminalStatuses.map(() => "?").join(", ")})`);
1668
+ params.push(...table.terminalStatuses);
1669
+ }
1670
+ conditions.push(`${table.timeColumn} < ?`);
1671
+ params.push(cutoff);
1672
+ if ("keepWhenSet" in table) {
1673
+ conditions.push(`rowid NOT IN (SELECT rowid FROM ${table.table} WHERE ${table.keepWhenSet} IS NOT NULL)`);
1674
+ }
1675
+ const where = conditions.join(" AND ");
1616
1676
  return {
1617
- backlogSql: `SELECT COUNT(*) AS n FROM ${table.table} WHERE ${table.timeColumn} < ?`,
1677
+ backlogSql: `SELECT COUNT(*) AS n FROM ${table.table} WHERE ${where}`,
1618
1678
  deleteSql: `DELETE FROM ${table.table} WHERE rowid IN (
1619
- SELECT rowid FROM ${table.table} WHERE ${table.timeColumn} < ? ORDER BY ${table.timeColumn} LIMIT ?
1679
+ SELECT rowid FROM ${table.table} WHERE ${where} ORDER BY ${table.timeColumn} LIMIT ?
1620
1680
  )`,
1621
- params: [cutoff]
1681
+ params
1622
1682
  };
1623
1683
  }
1624
1684
  function dryRunEnabled(env = process.env) {
@@ -5455,6 +5515,33 @@ var reportRateLimit = route({
5455
5515
  },
5456
5516
  auth: { apiKey: true }
5457
5517
  });
5518
+ var reportValidation = route({
5519
+ method: "post",
5520
+ path: "/api/keys/report-validation",
5521
+ pattern: ["api", "keys", "report-validation"],
5522
+ summary: "Record live validation results for a credential pool",
5523
+ tags: ["API Keys"],
5524
+ body: object2({
5525
+ keyType: string2(),
5526
+ keys: array2(object2({
5527
+ keyIndex: number2().int().min(0),
5528
+ keySuffix: string2().min(1).max(10),
5529
+ ok: boolean(),
5530
+ httpStatus: number2().int().optional()
5531
+ })).min(1).max(100),
5532
+ scope: string2().optional(),
5533
+ scopeId: string2().optional()
5534
+ }),
5535
+ responses: {
5536
+ 200: { description: "Validation recorded", schema: successMessageSchema },
5537
+ 400: { description: "Validation error" },
5538
+ 401: { description: "Unauthorized" }
5539
+ },
5540
+ auth: { apiKey: true },
5541
+ rbac: {
5542
+ ungated: "worker credential telemetry, same posture as POST /api/keys/report-rate-limit"
5543
+ }
5544
+ });
5458
5545
  var reportAuthFailure = route({
5459
5546
  method: "post",
5460
5547
  path: "/api/keys/report-auth-failure",
@@ -5572,6 +5659,7 @@ var getAvailable = route({
5572
5659
  schema: object2({
5573
5660
  success: literal2(true),
5574
5661
  availableIndices: array2(number2().int()),
5662
+ rejectedIndices: array2(number2().int()).optional(),
5575
5663
  totalKeys: number2().int(),
5576
5664
  modelBlockedIndices: array2(number2().int()).optional(),
5577
5665
  earliestModelResetAt: string2().nullable().optional(),
@@ -5606,6 +5694,8 @@ var ApiKeyStatusSchema = object2({
5606
5694
  lastSeatMismatchModel: string2().nullable(),
5607
5695
  consecutiveAuthFailures: number2().int(),
5608
5696
  lastAuthFailureAt: string2().nullable(),
5697
+ lastValidationError: string2().nullable(),
5698
+ lastValidationFailedAt: string2().nullable(),
5609
5699
  modelLimits: array2(object2({
5610
5700
  model: string2(),
5611
5701
  window: string2(),
@@ -5828,6 +5918,19 @@ async function handleApiKeys(req, res, pathSegments, queryParams) {
5828
5918
  }
5829
5919
  return true;
5830
5920
  }
5921
+ if (reportValidation.match(req.method, pathSegments)) {
5922
+ const parsed = await reportValidation.parse(req, res, pathSegments, queryParams);
5923
+ if (!parsed)
5924
+ return true;
5925
+ const { keyType, keys, scope, scopeId } = parsed.body;
5926
+ try {
5927
+ await recordKeyValidation2(keyType, keys, scope, scopeId ?? null);
5928
+ reportValidation.respond(res, 200, { success: true, message: "Key validation recorded" });
5929
+ } catch (err) {
5930
+ jsonError(res, err instanceof Error ? err.message : "Failed to record key validation", 500);
5931
+ }
5932
+ return true;
5933
+ }
5831
5934
  if (reportAuthFailure.match(req.method, pathSegments)) {
5832
5935
  const parsed = await reportAuthFailure.parse(req, res, pathSegments, queryParams);
5833
5936
  if (!parsed)
@@ -5889,6 +5992,7 @@ async function handleApiKeys(req, res, pathSegments, queryParams) {
5889
5992
  getAvailable.respond(res, 200, {
5890
5993
  success: true,
5891
5994
  availableIndices: result.availableIndices,
5995
+ rejectedIndices: result.rejectedIndices,
5892
5996
  totalKeys,
5893
5997
  authFailureFence: result.authFailureFence,
5894
5998
  ...model !== undefined ? {
@@ -6160,7 +6264,11 @@ async function handleUsedBy(req, res, pathSegments, queryParams, myAgentId) {
6160
6264
  org_website: orgWebsite,
6161
6265
  ...orgDomain ? { org_domain: orgDomain } : {},
6162
6266
  granted,
6163
- ...granted ? { contact_email: contactEmail, contact_function: contactFunction, quote } : {},
6267
+ ...granted ? {
6268
+ contact_email: contactEmail,
6269
+ contact_function: reportedUserFunction(contactFunction),
6270
+ quote
6271
+ } : {},
6164
6272
  changed_at: changedAt
6165
6273
  }),
6166
6274
  signal: AbortSignal.timeout(TIMEOUT_MS)
@@ -7568,6 +7676,8 @@ async function approvalQuorumMet(approvers, votes) {
7568
7676
 
7569
7677
  // src/http/assets.ts
7570
7678
  init_zod();
7679
+ init_key();
7680
+ init_source_key();
7571
7681
  init_asset_key_audit();
7572
7682
  init_db3();
7573
7683
  init_db2();
@@ -7827,6 +7937,16 @@ async function handleAssets(req, res, pathSegments, queryParams, myAgentId) {
7827
7937
  jsonError(res, await canReadSession2(req, myAgentId, task.id) ? "You can view this session but not move it." : SESSION_READ_DENIED2, 403);
7828
7938
  return true;
7829
7939
  }
7940
+ const destination = normalizeAssetKey(parsed.body.key);
7941
+ if (sourceOfKey(destination)) {
7942
+ const rootId = task.parentTaskId ? (await getSessionRoot(task.id))?.id : task.id;
7943
+ const root = rootId === task.id ? task : rootId ? await getTaskById2(rootId) : null;
7944
+ const sourceError = sourceMoveError(destination, root ?? { id: task.id });
7945
+ if (sourceError) {
7946
+ jsonError(res, sourceError, 400);
7947
+ return true;
7948
+ }
7949
+ }
7830
7950
  const tasks = parsed.body.cascade ? await getRootTaskChain2(task.id) : [task];
7831
7951
  for (const target of tasks) {
7832
7952
  if (!await canMutateTaskNamespace(target, myAgentId, req)) {
@@ -8052,6 +8172,165 @@ async function handleBudgets(req, res, pathSegments, queryParams, _myAgentId) {
8052
8172
  return false;
8053
8173
  }
8054
8174
 
8175
+ // src/http/codex-oauth-accounts.ts
8176
+ init_zod();
8177
+ init_crypto();
8178
+ init_db3();
8179
+ init_api_keys();
8180
+ init_codex_auth_failure();
8181
+ var CodexAccountSchema = object2({
8182
+ slot: number2().int().min(0),
8183
+ configKey: string2(),
8184
+ legacy: boolean(),
8185
+ suffix: string2().nullable(),
8186
+ plan: string2().nullable(),
8187
+ email: string2().nullable(),
8188
+ status: _enum2(["ok", "needs_login", "unchecked"])
8189
+ });
8190
+ var CodexAccountsResponseSchema = object2({ accounts: array2(CodexAccountSchema) });
8191
+ var listAccounts = route({
8192
+ method: "get",
8193
+ path: "/api/codex-oauth/accounts",
8194
+ pattern: ["api", "codex-oauth", "accounts"],
8195
+ summary: "List stored Codex ChatGPT accounts",
8196
+ tags: ["Codex OAuth"],
8197
+ responses: {
8198
+ 200: { description: "Stored account metadata", schema: CodexAccountsResponseSchema },
8199
+ 403: { description: "Caller cannot read all secrets" }
8200
+ }
8201
+ });
8202
+ var deleteAccount = route({
8203
+ method: "delete",
8204
+ path: "/api/codex-oauth/accounts/{slot}",
8205
+ pattern: ["api", "codex-oauth", "accounts", null],
8206
+ summary: "Remove a stored Codex ChatGPT account",
8207
+ tags: ["Codex OAuth"],
8208
+ rbac: { permission: "config.delete.any" },
8209
+ params: object2({ slot: exports_coerce.number().int().min(0).max(MAX_CODEX_OAUTH_SLOT) }),
8210
+ responses: {
8211
+ 200: { description: "Remaining accounts", schema: CodexAccountsResponseSchema },
8212
+ 403: { description: "Config administration and permission to read all secrets required" },
8213
+ 404: { description: "Account slot does not exist" }
8214
+ }
8215
+ });
8216
+ async function accountRows() {
8217
+ const rows = await getDbClient2().query("SELECT key, value, encrypted FROM swarm_config WHERE scope = 'global' AND (key = 'codex_oauth' OR key GLOB 'codex_oauth_[0-9]*')");
8218
+ const hasSlotZero = rows.some((row) => row.key === "codex_oauth_0");
8219
+ return rows.flatMap((row) => {
8220
+ if (row.key === "codex_oauth") {
8221
+ return hasSlotZero ? [] : [{ ...row, slot: 0, legacy: true }];
8222
+ }
8223
+ const match = /^codex_oauth_(0|[1-9]\d*)$/.exec(row.key);
8224
+ if (!match)
8225
+ return [];
8226
+ const slot = Number(match[1]);
8227
+ return slot <= MAX_CODEX_OAUTH_SLOT ? [{ ...row, slot, legacy: false }] : [];
8228
+ }).sort((a, b) => a.slot - b.slot);
8229
+ }
8230
+ var AccountCredentialsSchema = object2({
8231
+ access: string2().min(1),
8232
+ refresh: string2().min(1),
8233
+ expires: number2().finite(),
8234
+ accountId: string2().min(1)
8235
+ });
8236
+ function readCredentials(row) {
8237
+ try {
8238
+ const value = row.encrypted ? decryptSecret(row.value, getEncryptionKey()) : row.value;
8239
+ return AccountCredentialsSchema.parse(JSON.parse(value));
8240
+ } catch {
8241
+ return null;
8242
+ }
8243
+ }
8244
+ function accountSuffix(row) {
8245
+ const credentials = readCredentials(row);
8246
+ return credentials ? deriveCodexKeySuffix(credentials.access, credentials.accountId) : null;
8247
+ }
8248
+ async function accountsResponse() {
8249
+ const rows = await accountRows();
8250
+ const statuses = await getKeyStatuses2("CODEX_OAUTH", "global", null);
8251
+ const accounts = [];
8252
+ for (const row of rows) {
8253
+ const account = {
8254
+ slot: row.slot,
8255
+ configKey: row.key,
8256
+ legacy: row.legacy,
8257
+ suffix: null,
8258
+ plan: null,
8259
+ email: null,
8260
+ status: "needs_login"
8261
+ };
8262
+ const credentials = readCredentials(row);
8263
+ if (!credentials) {
8264
+ accounts.push(account);
8265
+ continue;
8266
+ }
8267
+ account.suffix = deriveCodexKeySuffix(credentials.access, credentials.accountId);
8268
+ account.plan = extractChatgptPlanType(credentials.access);
8269
+ const profile = decodeJwt(credentials.access)?.["https://api.openai.com/profile"];
8270
+ if (profile && typeof profile === "object" && "email" in profile) {
8271
+ account.email = typeof profile.email === "string" && profile.email ? profile.email : null;
8272
+ }
8273
+ const status = statuses.find((entry) => entry.keySuffix === account.suffix);
8274
+ const marker = await getKv2(CODEX_AUTH_WATCH_NAMESPACE, codexAuthBenchMarkerKey(account.suffix));
8275
+ const statusBenched = status && status.consecutiveAuthFailures >= CODEX_AUTH_FAILURE_BENCH_THRESHOLD && status.status === "rate_limited";
8276
+ account.status = marker || statusBenched ? "needs_login" : status ? "ok" : "unchecked";
8277
+ accounts.push(account);
8278
+ }
8279
+ return { accounts };
8280
+ }
8281
+ async function ensureSecretRead(req, res) {
8282
+ if (await requestSecretReadScope(req) === "all")
8283
+ return true;
8284
+ jsonError(res, "Reading Codex accounts requires access to all secrets", 403);
8285
+ return false;
8286
+ }
8287
+ async function handleCodexOAuthAccounts(req, res, pathSegments, queryParams) {
8288
+ if (listAccounts.match(req.method, pathSegments)) {
8289
+ const parsed = await listAccounts.parse(req, res, pathSegments, queryParams);
8290
+ if (!parsed)
8291
+ return true;
8292
+ if (!await ensureSecretRead(req, res))
8293
+ return true;
8294
+ listAccounts.respond(res, 200, await accountsResponse());
8295
+ return true;
8296
+ }
8297
+ if (deleteAccount.match(req.method, pathSegments)) {
8298
+ const parsed = await deleteAccount.parse(req, res, pathSegments, queryParams);
8299
+ if (!parsed)
8300
+ return true;
8301
+ if (!await ensureConfigAdmin(req, res, "config.delete.any"))
8302
+ return true;
8303
+ if (!await ensureSecretRead(req, res))
8304
+ return true;
8305
+ const deletedKey = await getDbClient2().transaction(async () => {
8306
+ const rows = await accountRows();
8307
+ const account = rows.find((row) => row.slot === parsed.params.slot);
8308
+ if (!account || !await deleteSwarmConfigByKey2("global", null, account.key))
8309
+ return null;
8310
+ const suffix = accountSuffix(account);
8311
+ if (suffix) {
8312
+ const remaining = rows.flatMap((row) => {
8313
+ const keySuffix = row === account ? null : accountSuffix(row);
8314
+ return keySuffix ? [{ keySuffix, keyIndex: row.slot }] : [];
8315
+ });
8316
+ await retirePoolKeyStatus("CODEX_OAUTH", suffix, remaining);
8317
+ if (!remaining.some((row) => row.keySuffix === suffix)) {
8318
+ await deleteKv2(CODEX_AUTH_WATCH_NAMESPACE, codexAuthBenchMarkerKey(suffix));
8319
+ }
8320
+ }
8321
+ return account.key;
8322
+ });
8323
+ if (deletedKey === null) {
8324
+ jsonError(res, "Codex account slot does not exist", 404);
8325
+ return true;
8326
+ }
8327
+ await runConfigWriteSideEffects("global", deletedKey, "");
8328
+ deleteAccount.respond(res, 200, await accountsResponse());
8329
+ return true;
8330
+ }
8331
+ return false;
8332
+ }
8333
+
8055
8334
  // src/http/codex-oauth-device.ts
8056
8335
  init_zod();
8057
8336
  init_crypto();
@@ -8192,7 +8471,9 @@ var OnboardingSignalsSchema = object2({
8192
8471
  provider: ProviderNameSchema,
8193
8472
  state: _enum2(["unverified", "configured", "verified"]),
8194
8473
  workers: number2().int().nonnegative(),
8195
- verifiedWorkers: number2().int().nonnegative()
8474
+ verifiedWorkers: number2().int().nonnegative(),
8475
+ error: string2().nullable(),
8476
+ warning: string2().nullable()
8196
8477
  })),
8197
8478
  embeddings: object2({
8198
8479
  configured: boolean(),
@@ -9117,6 +9398,7 @@ function sentTaskId(thread, replies, serviceUserId) {
9117
9398
  // src/comb/review-batch.ts
9118
9399
  init_templates();
9119
9400
  var REVIEW_BATCH_MAX = 50;
9401
+ var REVIEW_NOTE_MAX = 4000;
9120
9402
  var REVIEW_BATCH_READ_CONCURRENCY = 5;
9121
9403
  var SENT_KV_NAMESPACE = "comb:sent";
9122
9404
  var PENDING_CLAIM_MS = 5 * 60000;
@@ -9147,6 +9429,9 @@ async function sendReviewBatch(input, deps = {}) {
9147
9429
  if (ids.length === 0 || ids.length > REVIEW_BATCH_MAX) {
9148
9430
  throw new ReviewBatchError(400, `Send between 1 and ${REVIEW_BATCH_MAX} comments`);
9149
9431
  }
9432
+ if ((input.note?.length ?? 0) > REVIEW_NOTE_MAX) {
9433
+ throw new ReviewBatchError(400, `The note is longer than ${REVIEW_NOTE_MAX} characters`);
9434
+ }
9150
9435
  const agentFs = combAgentFs();
9151
9436
  if (!agentFs)
9152
9437
  throw new ReviewBatchError(503, "agent-fs is not set up for this swarm");
@@ -9180,6 +9465,7 @@ async function sendReviewBatch(input, deps = {}) {
9180
9465
  }
9181
9466
  const wonIds = won.map((read) => read.id);
9182
9467
  let taskId = null;
9468
+ let leadState = "none";
9183
9469
  if (won.length > 0) {
9184
9470
  try {
9185
9471
  const text = await renderTaskText(input, won);
@@ -9190,6 +9476,7 @@ async function sendReviewBatch(input, deps = {}) {
9190
9476
  ]);
9191
9477
  }
9192
9478
  const lead = await getLeadAgent2();
9479
+ leadState = !lead ? "none" : lead.status === "offline" ? "offline" : "online";
9193
9480
  const task = await createTask(text, {
9194
9481
  agentId: lead?.id ?? "",
9195
9482
  routingReason: lead ? "skill" : undefined,
@@ -9226,7 +9513,7 @@ async function sendReviewBatch(input, deps = {}) {
9226
9513
  if (taskId === null && repaired.length === 0) {
9227
9514
  throw new ReviewBatchError(409, "Nothing to send", skipped);
9228
9515
  }
9229
- return { taskId, sent: wonIds, skipped, repaired };
9516
+ return taskId === null ? { taskId, sent: wonIds, skipped, repaired } : { taskId, sent: wonIds, skipped, repaired, lead: leadState };
9230
9517
  }
9231
9518
  async function mapLimited(items, limit, fn) {
9232
9519
  const results = new Array(items.length);
@@ -9371,6 +9658,7 @@ async function renderTaskText(input, reads) {
9371
9658
  requested_by: await requesterLabel(input.requestedByUserId),
9372
9659
  org_id: input.orgId,
9373
9660
  drive_id: input.driveId,
9661
+ note_block: noteBlock(input.note),
9374
9662
  comments_block: blocks.join(`
9375
9663
  `)
9376
9664
  });
@@ -9385,6 +9673,13 @@ function lineRange(comment) {
9385
9673
  const end = comment.lineEnd ?? comment.lineStart;
9386
9674
  return end === comment.lineStart ? `line ${comment.lineStart}` : `lines ${comment.lineStart}-${end}`;
9387
9675
  }
9676
+ function noteBlock(note) {
9677
+ const text = note?.trim();
9678
+ return text ? `
9679
+ Note from the sender, about all the comments:
9680
+ ${fenced(text)}
9681
+ ` : "";
9682
+ }
9388
9683
  function fenced(text) {
9389
9684
  const longest = (text.match(/`+/g) ?? []).reduce((max, run) => Math.max(max, run.length), 0);
9390
9685
  const fence = "`".repeat(Math.max(3, longest + 1));
@@ -9425,7 +9720,8 @@ var resultSchema = object2({
9425
9720
  taskId: string2().nullable(),
9426
9721
  sent: array2(string2()),
9427
9722
  skipped: array2(skippedSchema),
9428
- repaired: array2(object2({ id: string2(), taskId: string2() }))
9723
+ repaired: array2(object2({ id: string2(), taskId: string2() })),
9724
+ lead: _enum2(["online", "offline", "none"]).optional()
9429
9725
  });
9430
9726
  var batchErrorSchema = object2({ error: string2(), skipped: array2(skippedSchema) });
9431
9727
  function isDrivePath(path) {
@@ -9436,13 +9732,14 @@ var reviewBatchRoute = route({
9436
9732
  path: "/api/comb/review-batches",
9437
9733
  pattern: ["api", "comb", "review-batches"],
9438
9734
  summary: "Send agent-fs comments to the swarm as one lead task",
9439
- description: "Comb's 'Send to swarm'. The server reads each comment again from agent-fs with its bootstrap key, skips replies, resolved comments, and comments already sent, and creates ONE task for the lead. Each sent comment gets a `[comb:sent task=<id>]` reply from the swarm service account. A comment is sent at most once. When an earlier send lost its reply, the batch posts that reply again (`repaired`). Answers 404 while COMB_ENABLED is off.",
9735
+ description: "Comb's 'Send to swarm'. The server reads each comment again from agent-fs with its bootstrap key, skips replies, resolved comments, and comments already sent, and creates ONE task for the lead. Each sent comment gets a `[comb:sent task=<id>]` reply from the swarm service account. A comment is sent at most once. An optional `note` from the sender goes into the task text. When an earlier send lost its reply, the batch posts that reply again (`repaired`). Answers 404 while COMB_ENABLED is off.",
9440
9736
  tags: ["Comb"],
9441
9737
  body: object2({
9442
9738
  orgId: string2().min(1),
9443
9739
  driveId: string2().min(1),
9444
9740
  commentIds: array2(uuid()).min(1).max(REVIEW_BATCH_MAX),
9445
- scopePath: string2().min(1).max(1024).refine(isDrivePath, "scopePath must start with '/' and have no '.' or '..' segment")
9741
+ scopePath: string2().min(1).max(1024).refine(isDrivePath, "scopePath must start with '/' and have no '.' or '..' segment"),
9742
+ note: string2().max(REVIEW_NOTE_MAX).optional()
9446
9743
  }),
9447
9744
  responses: {
9448
9745
  200: {
@@ -9832,16 +10129,16 @@ declare module "swarm-extension" {
9832
10129
  | "schedule"
9833
10130
  | "slack"
9834
10131
  | "agentmail"
9835
- | "mcp"
9836
- | "api"
9837
- | "ui"
9838
10132
  | "github"
9839
10133
  | "gitlab"
9840
10134
  | "azure-devops"
9841
10135
  | "bitbucket"
9842
- | "system"
9843
10136
  | "linear"
9844
10137
  | "jira"
10138
+ | "mcp"
10139
+ | "api"
10140
+ | "ui"
10141
+ | "system"
9845
10142
  | "comb"
9846
10143
  | "chat"
9847
10144
  | undefined;
@@ -9950,16 +10247,16 @@ declare module "swarm-extension" {
9950
10247
  | "schedule"
9951
10248
  | "slack"
9952
10249
  | "agentmail"
9953
- | "mcp"
9954
- | "api"
9955
- | "ui"
9956
10250
  | "github"
9957
10251
  | "gitlab"
9958
10252
  | "azure-devops"
9959
10253
  | "bitbucket"
9960
- | "system"
9961
10254
  | "linear"
9962
10255
  | "jira"
10256
+ | "mcp"
10257
+ | "api"
10258
+ | "ui"
10259
+ | "system"
9963
10260
  | "comb"
9964
10261
  | "chat";
9965
10262
  tags: string[];
@@ -10224,6 +10521,15 @@ declare module "swarm-extension" {
10224
10521
  description: string;
10225
10522
  origin: TaskCreateOrigin;
10226
10523
  requestInfo?: RequestInfo;
10524
+ /** Slack ingress metadata; not persisted or writable through modify. */
10525
+ slack?: {
10526
+ trigger: "mention" | "thread-buffer";
10527
+ messages: {
10528
+ ts: string;
10529
+ userId: string;
10530
+ text: string;
10531
+ }[];
10532
+ };
10227
10533
  }
10228
10534
  /** A pre.task.create hook blocked a task before it was created. */
10229
10535
  export interface TaskBlockedEvent {
@@ -13653,6 +13959,7 @@ async function buildFleetBenchmarkResponse(now = new Date) {
13653
13959
  const team = _enum2(COMPANY_TEAM_SIZES).safeParse(teamSize);
13654
13960
  const use = _enum2(COMPANY_USE_CASES).safeParse(useCase);
13655
13961
  const peerGroup = normalizeOrgWebsite(website) && team.success && use.success ? { teamSize: team.data, useCase: use.data } : null;
13962
+ const proxyPeerGroup = peerGroup && reportedUseCase(peerGroup.useCase) ? peerGroup : null;
13656
13963
  const empty = {
13657
13964
  level: peerGroup ? "full" : "basic",
13658
13965
  peerGroup: null,
@@ -13679,7 +13986,7 @@ async function buildFleetBenchmarkResponse(now = new Date) {
13679
13986
  return { ...empty, state: "telemetry_off", local };
13680
13987
  if (finishedTasks < FLEET_MIN_FINISHED_TASKS)
13681
13988
  return { ...empty, state: "not_enough_tasks", local };
13682
- const fleet = await fleetBenchmarks(now.getTime(), peerGroup);
13989
+ const fleet = await fleetBenchmarks(now.getTime(), proxyPeerGroup);
13683
13990
  const responsePeerGroup = peerGroup && fleet?.peer_group ? {
13684
13991
  teamSize: fleet.peer_group.team_size,
13685
13992
  useCase: fleet.peer_group.use_case,
@@ -14736,6 +15043,9 @@ function buildSlackManifest(name) {
14736
15043
  return manifest;
14737
15044
  }
14738
15045
 
15046
+ // src/http/integrations.ts
15047
+ init_credentials();
15048
+
14739
15049
  // src/http/config-values.ts
14740
15050
  init_db3();
14741
15051
  async function resolveConfigValue(key) {
@@ -14910,7 +15220,7 @@ function createIntegrationsHandler(deps = {}) {
14910
15220
  return true;
14911
15221
  }
14912
15222
  try {
14913
- const client = buildClient(apiKey);
15223
+ const client = buildClient(selectCredential(apiKey, undefined, "ANTHROPIC_API_KEY").selected);
14914
15224
  const agent = await client.beta.agents.retrieve(agentId);
14915
15225
  const modelId = typeof agent.model === "string" ? agent.model : agent.model?.id ?? null;
14916
15226
  claudeManagedTestRoute.respond(res, 200, {
@@ -15187,8 +15497,8 @@ function authorizeWrite(namespace, ctx) {
15187
15497
  return null;
15188
15498
  }
15189
15499
  function authorizeRead(namespace, ctx) {
15190
- const overflowAuthErr = mcpOverflowAuthError(namespace, ctx.callerAgentId);
15191
- return overflowAuthErr ? { status: 403, message: overflowAuthErr } : null;
15500
+ const readErr = privateNamespaceError(namespace) ?? mcpOverflowAuthError(namespace, ctx.callerAgentId);
15501
+ return readErr ? { status: 403, message: readErr } : null;
15192
15502
  }
15193
15503
  function encodeValueOrError(res, value, valueType) {
15194
15504
  try {
@@ -21590,6 +21900,7 @@ init_db3();
21590
21900
  init_memory();
21591
21901
  init_constants();
21592
21902
  init_types();
21903
+ init_credentials();
21593
21904
  init_openrouter_base_url();
21594
21905
 
21595
21906
  // src/http/status.ts
@@ -21658,6 +21969,7 @@ var StatusIdentitySchema = object2({
21658
21969
  var StatusActivitySchema = object2({
21659
21970
  agents_online: number2().int().nonnegative(),
21660
21971
  leads_online: number2().int().nonnegative(),
21972
+ leads_ready: number2().int().nonnegative(),
21661
21973
  recent_tasks_count: number2().int().nonnegative()
21662
21974
  });
21663
21975
  var StatusCombSchema = object2({
@@ -22038,7 +22350,7 @@ async function buildSetup(automationSetup) {
22038
22350
  await firstTaskMilestone()
22039
22351
  ];
22040
22352
  }
22041
- function computeHealth(setup) {
22353
+ function computeHealth(setup, readyLeads) {
22042
22354
  const byId = new Map(setup.map((m) => [m.id, m]));
22043
22355
  const harness = byId.get("harness");
22044
22356
  const workers = byId.get("workers");
@@ -22046,6 +22358,8 @@ function computeHealth(setup) {
22046
22358
  return "broken";
22047
22359
  if (!workers || workers.state === "unverified")
22048
22360
  return "broken";
22361
+ if (readyLeads === 0)
22362
+ return "degraded";
22049
22363
  if (harness.state === "configured")
22050
22364
  return "degraded";
22051
22365
  for (const id of ["slack", "github", "linear", "jira"]) {
@@ -22063,12 +22377,13 @@ async function buildStatusPayload() {
22063
22377
  const toStatus = ({ failureReason: _, ...status }) => status;
22064
22378
  const automations = automationInputs.map((automation) => toStatus(preflightAutomation(automation, automationSetup))).sort((a, b) => a.name.localeCompare(b.name) || a.kind.localeCompare(b.kind));
22065
22379
  const activity = await getInstanceActivity2();
22380
+ const readyLeads = (await getReadyAgentCounts2()).leads;
22066
22381
  const instance = await getInstanceFeedbackSignals();
22067
22382
  return {
22068
22383
  runtime_pools: { enabled: isRuntimePoolsEnabled(), supervisor: runtimeSupervisorStatus() },
22069
22384
  identity: buildIdentity(),
22070
22385
  setup,
22071
- activity,
22386
+ activity: { ...activity, leads_ready: readyLeads },
22072
22387
  agent_fs: {
22073
22388
  configured: !!process.env.AGENT_FS_API_URL,
22074
22389
  base_url: process.env.AGENT_FS_API_URL ?? null,
@@ -22076,7 +22391,7 @@ async function buildStatusPayload() {
22076
22391
  comb: getCombStatus(await combServiceUserId)
22077
22392
  },
22078
22393
  automations,
22079
- health: computeHealth(setup),
22394
+ health: computeHealth(setup, readyLeads),
22080
22395
  telemetry: { enabled: isTelemetryEnabled() },
22081
22396
  instance
22082
22397
  };
@@ -22111,7 +22426,7 @@ var getStatus = route({
22111
22426
  path: "/status",
22112
22427
  pattern: ["status"],
22113
22428
  summary: "Identity + setup readiness + live activity for the swarm dashboard",
22114
- description: "Single source of truth consumed by the UI home page. Identity comes from SWARM_* envs; setup milestones each emit `unverified | configured | verified`; automations report `running | needs_setup` from the same runtime preflight used at dispatch; activity counts agents alive in the last 5 min and tasks created in the last 24h; agent_fs reports whether AGENT_FS_API_URL is set, plus the Comb settings (COMB_ENABLED, the browser-facing agent-fs URL, the shared org and drive ids, and the agent-fs user id of the swarm service account); telemetry reports the effective ANONYMIZED_TELEMETRY opt-out state.",
22429
+ description: "Single source of truth consumed by the UI home page. Identity comes from SWARM_* envs; setup milestones each emit `unverified | configured | verified`; automations report `running | needs_setup` from the same runtime preflight used at dispatch; activity counts agents alive in the last 5 min, leads that can take work (status idle or busy), and tasks created in the last 24h; agent_fs reports whether AGENT_FS_API_URL is set, plus the Comb settings (COMB_ENABLED, the browser-facing agent-fs URL, the shared org and drive ids, and the agent-fs user id of the swarm service account); telemetry reports the effective ANONYMIZED_TELEMETRY opt-out state.",
22115
22430
  tags: ["Status"],
22116
22431
  responses: {
22117
22432
  200: { description: "Status payload", schema: StatusResponseSchema },
@@ -22184,11 +22499,14 @@ async function buildSignals(state) {
22184
22499
  if (!provider.success)
22185
22500
  continue;
22186
22501
  const rollup = await rollupCredStatusForProvider(provider.data);
22502
+ const live = rollup.latestLiveTest;
22187
22503
  providers.push({
22188
22504
  provider: provider.data,
22189
22505
  state: rollup.state,
22190
22506
  workers: rollup.workers,
22191
- verifiedWorkers: rollup.verifiedWorkers
22507
+ verifiedWorkers: rollup.verifiedWorkers,
22508
+ error: live && !live.ok ? live.error ?? null : null,
22509
+ warning: live?.ok ? live.warning ?? null : null
22192
22510
  });
22193
22511
  }
22194
22512
  const integrations = await getAutomationSetupStates();
@@ -22334,7 +22652,7 @@ async function handleMemoryProbe(body) {
22334
22652
  const canReuseKey = reuseHost === undefined || endpoint.hostname === reuseHost;
22335
22653
  const reusedKey = !explicitKey && body.reuseKey && canReuseKey ? process.env[body.reuseKey] : undefined;
22336
22654
  const implicitKey = body.preset === "existing" ? process.env.EMBEDDING_API_KEY ?? process.env.OPENAI_API_KEY : undefined;
22337
- const apiKey = explicitKey ?? reusedKey ?? implicitKey;
22655
+ const apiKey = splitCredentialPool(explicitKey ?? reusedKey ?? implicitKey ?? "")[0];
22338
22656
  if (!apiKey) {
22339
22657
  return {
22340
22658
  ok: false,
@@ -22794,6 +23112,7 @@ var listTasks = route({
22794
23112
  status: string2().optional(),
22795
23113
  agentId: string2().optional(),
22796
23114
  scheduleId: string2().optional(),
23115
+ workflowRunId: string2().uuid().optional(),
22797
23116
  key: AssetKeySchema.optional(),
22798
23117
  keyPrefix: AssetKeySchema.optional(),
22799
23118
  search: string2().optional(),
@@ -23396,6 +23715,7 @@ async function handleTasks(req, res, pathSegments, queryParams, myAgentId) {
23396
23715
  status,
23397
23716
  agentId: parsed.query.agentId || undefined,
23398
23717
  scheduleId: parsed.query.scheduleId || undefined,
23718
+ workflowRunId: parsed.query.workflowRunId,
23399
23719
  key: parsed.query.key,
23400
23720
  keyPrefix: parsed.query.keyPrefix,
23401
23721
  search: parsed.query.search || undefined,
@@ -27302,6 +27622,298 @@ async function handlePoll(req, res, pathSegments, queryParams, myAgentId) {
27302
27622
  return false;
27303
27623
  }
27304
27624
 
27625
+ // src/http/pool-keys.ts
27626
+ init_src2();
27627
+ init_zod();
27628
+ init_db3();
27629
+ init_api_keys();
27630
+ init_swarm_config_guard();
27631
+ init_credentials();
27632
+ init_secret_scrubber();
27633
+ var PoolKeyStatusSchema = _enum2(["ok", "rejected", "rate_limited", "unchecked"]);
27634
+ var PoolKeySchema = object2({
27635
+ index: number2().int().min(0),
27636
+ suffix: string2(),
27637
+ status: PoolKeyStatusSchema,
27638
+ error: string2().nullable(),
27639
+ checkedAt: string2().nullable(),
27640
+ rateLimitedUntil: string2().nullable()
27641
+ });
27642
+ var PoolKeysResponseSchema = object2({
27643
+ key: string2(),
27644
+ source: _enum2(["stored", "env", "none"]),
27645
+ readOnly: boolean(),
27646
+ keys: array2(PoolKeySchema)
27647
+ });
27648
+ var PoolKeyCheckResultSchema = _enum2(["verified", "rejected", "not_tested"]);
27649
+ var PoolKeyCheckSchema = object2({
27650
+ suffix: string2(),
27651
+ result: PoolKeyCheckResultSchema,
27652
+ httpStatus: number2().nullable(),
27653
+ error: string2().nullable()
27654
+ });
27655
+ var poolVar = string2().refine((key) => key !== "CODEX_OAUTH" && CREDENTIAL_POOL_VARS.includes(key), "Choose a credential pool variable.");
27656
+ var getPoolKeys = route({
27657
+ method: "get",
27658
+ path: "/api/config/pool-keys",
27659
+ pattern: ["api", "config", "pool-keys"],
27660
+ summary: "List credential pool suffixes and status",
27661
+ tags: ["Config"],
27662
+ query: object2({ key: poolVar }),
27663
+ responses: {
27664
+ 200: { description: "Credential pool", schema: PoolKeysResponseSchema },
27665
+ 400: { description: "Invalid pool variable" },
27666
+ 403: { description: "Secret read permission required" }
27667
+ }
27668
+ });
27669
+ var addPoolKeys = route({
27670
+ method: "post",
27671
+ path: "/api/config/pool-keys",
27672
+ pattern: ["api", "config", "pool-keys"],
27673
+ summary: "Test and append keys to a credential pool",
27674
+ tags: ["Config"],
27675
+ rbac: { permission: "config.write.any" },
27676
+ body: object2({
27677
+ key: poolVar,
27678
+ value: string2(),
27679
+ baseUrl: string2().nullable().optional().describe("Base URL for the check only. Null tests the provider default. Omit to use the stored URL.")
27680
+ }),
27681
+ responses: {
27682
+ 200: {
27683
+ description: "Updated credential pool and checks",
27684
+ schema: PoolKeysResponseSchema.extend({ checks: array2(PoolKeyCheckSchema) })
27685
+ },
27686
+ 400: { description: "Invalid key" },
27687
+ 403: { description: "Config administration and permission to read all secrets required" },
27688
+ 409: { description: "Duplicate key or deployment env pool" },
27689
+ 422: {
27690
+ description: "Provider rejected a key. Nothing was saved.",
27691
+ schema: object2({ error: string2(), checks: array2(PoolKeyCheckSchema) })
27692
+ }
27693
+ }
27694
+ });
27695
+ var deletePoolKey = route({
27696
+ method: "delete",
27697
+ path: "/api/config/pool-keys",
27698
+ pattern: ["api", "config", "pool-keys"],
27699
+ summary: "Remove one credential pool member",
27700
+ tags: ["Config"],
27701
+ rbac: { permission: "config.delete.any" },
27702
+ query: object2({
27703
+ key: poolVar,
27704
+ index: exports_coerce.number().int().min(0),
27705
+ suffix: string2().min(1).max(5)
27706
+ }),
27707
+ responses: {
27708
+ 200: { description: "Updated credential pool", schema: PoolKeysResponseSchema },
27709
+ 400: { description: "Invalid pool member" },
27710
+ 403: { description: "Config administration and permission to read all secrets required" },
27711
+ 409: { description: "The pool changed or comes from the deployment env" }
27712
+ }
27713
+ });
27714
+ var ENV_POOL_ERROR = "These keys come from the deployment env. Change them there.";
27715
+ async function readPool(key) {
27716
+ const [row] = await getSwarmConfigs2({ scope: "global", key });
27717
+ const envValue = getDeploymentEnvValue(key);
27718
+ const source = row ? "stored" : envValue ? "env" : "none";
27719
+ const value = row?.value ?? envValue ?? "";
27720
+ registerEnvSecrets({ [key]: value });
27721
+ return { row, source, members: splitCredentialPool(value) };
27722
+ }
27723
+ async function poolResponse(key) {
27724
+ const pool = await readPool(key);
27725
+ const statuses = await getKeyStatuses2(key, "global", null);
27726
+ return {
27727
+ key,
27728
+ source: pool.source,
27729
+ readOnly: pool.source === "env",
27730
+ keys: pool.members.map((member, index) => {
27731
+ const suffix = member.slice(-5);
27732
+ const row = statuses.find((status) => status.keySuffix === suffix);
27733
+ const rejected = !!row?.lastValidationFailedAt;
27734
+ const limited = row?.status === "rate_limited" && !!row.rateLimitedUntil && Date.parse(row.rateLimitedUntil) > Date.now();
27735
+ return {
27736
+ index,
27737
+ suffix,
27738
+ status: rejected ? "rejected" : limited ? "rate_limited" : row ? "ok" : "unchecked",
27739
+ error: rejected ? scrubSecrets(row?.lastValidationError) || null : null,
27740
+ checkedAt: rejected ? row.lastValidationFailedAt : row?.updatedAt ?? null,
27741
+ rateLimitedUntil: row?.rateLimitedUntil ?? null
27742
+ };
27743
+ })
27744
+ };
27745
+ }
27746
+ function duplicateError(members, additions) {
27747
+ const seen = new Set(members);
27748
+ for (const member of additions) {
27749
+ if (seen.has(member))
27750
+ return `The key ending ${member.slice(-5)} is already in the pool.`;
27751
+ seen.add(member);
27752
+ }
27753
+ return null;
27754
+ }
27755
+ async function savePool(key, members, row) {
27756
+ const value = members.join(",");
27757
+ const validationError = validateConfigEntry({
27758
+ scope: "global",
27759
+ key,
27760
+ value,
27761
+ exportToEnv: row?.exportToEnv
27762
+ });
27763
+ if (validationError)
27764
+ return validationError;
27765
+ await upsertSwarmConfigWithPolicyMirror({
27766
+ scope: "global",
27767
+ key,
27768
+ value,
27769
+ isSecret: true,
27770
+ description: row?.description ?? null,
27771
+ envPath: row?.envPath ?? null,
27772
+ exportToEnv: row?.exportToEnv
27773
+ });
27774
+ return null;
27775
+ }
27776
+ async function ensureSecretRead2(req, res) {
27777
+ if (await requestSecretReadScope(req) === "all")
27778
+ return true;
27779
+ jsonError(res, "Reading credential pools requires permission to read all secrets.", 403);
27780
+ return false;
27781
+ }
27782
+ async function handlePoolKeys(req, res, pathSegments, queryParams) {
27783
+ if (getPoolKeys.match(req.method, pathSegments)) {
27784
+ const parsed = await getPoolKeys.parse(req, res, pathSegments, queryParams);
27785
+ if (!parsed)
27786
+ return true;
27787
+ if (!await ensureSecretRead2(req, res))
27788
+ return true;
27789
+ getPoolKeys.respond(res, 200, await poolResponse(parsed.query.key));
27790
+ return true;
27791
+ }
27792
+ if (addPoolKeys.match(req.method, pathSegments)) {
27793
+ const parsed = await addPoolKeys.parse(req, res, pathSegments, queryParams);
27794
+ if (!parsed)
27795
+ return true;
27796
+ if (!await ensureConfigAdmin(req, res, "config.write.any"))
27797
+ return true;
27798
+ if (!await ensureSecretRead2(req, res))
27799
+ return true;
27800
+ const { key, value, baseUrl } = parsed.body;
27801
+ const additions = value.split(",").map((part) => part.trim()).filter(Boolean);
27802
+ if (!additions.length) {
27803
+ jsonError(res, "Enter a key.", 400);
27804
+ return true;
27805
+ }
27806
+ if (additions.some((part) => /\s/.test(part))) {
27807
+ jsonError(res, "A key cannot contain spaces or line breaks.", 400);
27808
+ return true;
27809
+ }
27810
+ registerEnvSecrets({ [key]: additions.join(",") });
27811
+ const initial = await readPool(key);
27812
+ if (initial.source === "env") {
27813
+ jsonError(res, ENV_POOL_ERROR, 409);
27814
+ return true;
27815
+ }
27816
+ const duplicate = duplicateError(initial.members, additions);
27817
+ if (duplicate) {
27818
+ jsonError(res, scrubSecrets(duplicate), 409);
27819
+ return true;
27820
+ }
27821
+ const env = { ...process.env };
27822
+ const provider = providerForKeyVar(key);
27823
+ const baseUrlKey = key === "OPENROUTER_API_KEY" ? "OPENROUTER_BASE_URL" : provider ? baseUrlEnvVar(provider) : undefined;
27824
+ if (baseUrlKey && baseUrl !== undefined) {
27825
+ env[baseUrlKey] = baseUrl ?? "";
27826
+ } else if (baseUrlKey) {
27827
+ const [row] = await getSwarmConfigs2({ scope: "global", key: baseUrlKey });
27828
+ if (row)
27829
+ env[baseUrlKey] = row.value;
27830
+ }
27831
+ const checks = await Promise.all(additions.map(async (member) => {
27832
+ try {
27833
+ const probe = await checkProviderPoolKey(key, member, env);
27834
+ return {
27835
+ suffix: member.slice(-5),
27836
+ result: probe.skipped ? "not_tested" : probe.ok ? "verified" : probe.httpStatus === 401 ? "rejected" : "not_tested",
27837
+ httpStatus: probe.httpStatus ?? null,
27838
+ error: scrubSecrets(probe.error?.replaceAll(member, "[REDACTED]")) || null
27839
+ };
27840
+ } catch {
27841
+ return {
27842
+ suffix: member.slice(-5),
27843
+ result: "not_tested",
27844
+ httpStatus: null,
27845
+ error: "The provider check did not complete."
27846
+ };
27847
+ }
27848
+ }));
27849
+ const rejected = checks.find((check) => check.result === "rejected");
27850
+ if (rejected) {
27851
+ addPoolKeys.respond(res, 422, {
27852
+ error: scrubSecrets(`The key ending ${rejected.suffix} was rejected (HTTP 401). Nothing was saved.`),
27853
+ checks
27854
+ });
27855
+ return true;
27856
+ }
27857
+ const result = await getDbClient2().transaction(async () => {
27858
+ const current = await readPool(key);
27859
+ if (current.source === "env")
27860
+ return { error: ENV_POOL_ERROR, status: 409 };
27861
+ const duplicate = duplicateError(current.members, additions);
27862
+ if (duplicate)
27863
+ return { error: duplicate, status: 409 };
27864
+ const members = [...current.members, ...additions];
27865
+ const error = await savePool(key, members, current.row);
27866
+ if (error)
27867
+ return { error, status: 400 };
27868
+ await recordKeyValidation2(key, checks.flatMap((check, index) => check.result === "verified" ? [{ keyIndex: current.members.length + index, keySuffix: check.suffix, ok: true }] : []), "global", null, { retireAbsent: false });
27869
+ return { value: members.join(",") };
27870
+ });
27871
+ if ("error" in result) {
27872
+ jsonError(res, scrubSecrets(result.error), result.status);
27873
+ return true;
27874
+ }
27875
+ await runConfigWriteSideEffects("global", key, result.value);
27876
+ addPoolKeys.respond(res, 200, { ...await poolResponse(key), checks });
27877
+ return true;
27878
+ }
27879
+ if (deletePoolKey.match(req.method, pathSegments)) {
27880
+ const parsed = await deletePoolKey.parse(req, res, pathSegments, queryParams);
27881
+ if (!parsed)
27882
+ return true;
27883
+ if (!await ensureConfigAdmin(req, res, "config.delete.any"))
27884
+ return true;
27885
+ if (!await ensureSecretRead2(req, res))
27886
+ return true;
27887
+ const { key, index, suffix } = parsed.query;
27888
+ const result = await getDbClient2().transaction(async () => {
27889
+ const current = await readPool(key);
27890
+ if (current.source === "env")
27891
+ return { error: ENV_POOL_ERROR, status: 409 };
27892
+ if (!current.members[index] || current.members[index].slice(-5) !== suffix) {
27893
+ return { error: "The key list changed. Reload it and try again.", status: 409 };
27894
+ }
27895
+ const members = current.members.filter((_, position) => position !== index);
27896
+ if (members.length) {
27897
+ const error = await savePool(key, members, current.row);
27898
+ if (error)
27899
+ return { error, status: 400 };
27900
+ } else {
27901
+ await deleteSwarmConfigByKey2("global", null, key);
27902
+ }
27903
+ await retirePoolKeyStatus(key, suffix, members.map((member, keyIndex) => ({ keySuffix: member.slice(-5), keyIndex })));
27904
+ return { value: members.join(",") };
27905
+ });
27906
+ if ("error" in result) {
27907
+ jsonError(res, scrubSecrets(result.error), result.status);
27908
+ return true;
27909
+ }
27910
+ await runConfigWriteSideEffects("global", key, result.value);
27911
+ deletePoolKey.respond(res, 200, await poolResponse(key));
27912
+ return true;
27913
+ }
27914
+ return false;
27915
+ }
27916
+
27305
27917
  // src/http/pricing.ts
27306
27918
  init_zod();
27307
27919
  init_db3();
@@ -33672,6 +34284,7 @@ async function handleSessionData(req, res, pathSegments, queryParams, myAgentId)
33672
34284
  // src/http/sessions.ts
33673
34285
  init_zod();
33674
34286
  init_key();
34287
+ init_source_key();
33675
34288
  init_db3();
33676
34289
  init_session_moves();
33677
34290
  init_session_tree();
@@ -33680,6 +34293,74 @@ init_steering();
33680
34293
  init_users();
33681
34294
  init_rbac();
33682
34295
  init_bus();
34296
+
34297
+ // src/slack/channel-labels.ts
34298
+ var LABEL_TTL_MS = 24 * 60 * 60 * 1000;
34299
+ var FAILURE_TTL_MS = 10 * 60 * 1000;
34300
+ var FAILURE_CACHE_MAX = 500;
34301
+ var LOOKUP_QUEUE_MAX = 50;
34302
+ var inFlight2 = new Set;
34303
+ var failedUntil = new Map;
34304
+ var pending = Promise.resolve();
34305
+ async function channelLabel(client, id) {
34306
+ const result = await callSlackWithRetry2(client, "conversations.info", {
34307
+ channel: id.toUpperCase()
34308
+ });
34309
+ const channel = result.channel;
34310
+ if (result.ok === false || !channel)
34311
+ throw new Error("Channel lookup failed");
34312
+ if (channel.is_mpim)
34313
+ return "Group DM";
34314
+ if (channel.is_im && channel.user) {
34315
+ const result = await callSlackWithRetry2(client, "users.info", { user: channel.user });
34316
+ const user = result.user;
34317
+ const name = user?.profile?.display_name || user?.real_name || user?.profile?.real_name;
34318
+ if (result.ok !== false && name)
34319
+ return `DM · ${name}`;
34320
+ } else if (channel.name) {
34321
+ return `#${channel.name}`;
34322
+ }
34323
+ throw new Error("Channel label unavailable");
34324
+ }
34325
+ var CHANNEL_GROUP_KEY = /^shared\/slack\/([^/]+)\/$/;
34326
+ function warmSlackChannelLabels(groupKeys) {
34327
+ const client = getSlackApp2()?.client;
34328
+ if (!client)
34329
+ return;
34330
+ for (const groupKey of groupKeys) {
34331
+ const id = CHANNEL_GROUP_KEY.exec(groupKey)?.[1];
34332
+ if (!id)
34333
+ continue;
34334
+ if (inFlight2.has(id) || (failedUntil.get(id) ?? 0) > Date.now())
34335
+ continue;
34336
+ failedUntil.delete(id);
34337
+ if (inFlight2.size >= LOOKUP_QUEUE_MAX)
34338
+ continue;
34339
+ if (failedUntil.size + inFlight2.size >= FAILURE_CACHE_MAX) {
34340
+ const now = Date.now();
34341
+ for (const [failedId, until] of failedUntil) {
34342
+ if (until <= now)
34343
+ failedUntil.delete(failedId);
34344
+ }
34345
+ if (failedUntil.size + inFlight2.size >= FAILURE_CACHE_MAX)
34346
+ continue;
34347
+ }
34348
+ inFlight2.add(id);
34349
+ pending = pending.then(async () => {
34350
+ try {
34351
+ const label = await channelLabel(client, id);
34352
+ await rememberSessionLabel(groupKey, label, LABEL_TTL_MS);
34353
+ } catch (error) {
34354
+ failedUntil.set(id, Date.now() + FAILURE_TTL_MS);
34355
+ console.warn(`[Slack] Could not cache a session channel label: ${slackErrorCode2(error) ?? "unknown error"}`);
34356
+ } finally {
34357
+ inFlight2.delete(id);
34358
+ }
34359
+ });
34360
+ }
34361
+ }
34362
+
34363
+ // src/http/sessions.ts
33683
34364
  init_types();
33684
34365
  init_request_auth_context();
33685
34366
  init_runtime_pools_flag();
@@ -33742,6 +34423,7 @@ var SessionTreeGroupSchema = SessionSectionCountsSchema.extend({
33742
34423
  lastActivityAt: string2()
33743
34424
  });
33744
34425
  var SessionTreeResponseSchema = object2({
34426
+ labels: record2(string2(), string2()).optional(),
33745
34427
  groups: array2(SessionTreeGroupSchema),
33746
34428
  inbox: SessionSectionCountsSchema,
33747
34429
  later: SessionSectionCountsSchema,
@@ -34179,6 +34861,9 @@ async function checkSessionMove(rootTaskId, actor, req, myAgentId, options = {})
34179
34861
  }
34180
34862
  if (root.parentTaskId)
34181
34863
  return { reason: "Task is not a session root" };
34864
+ const sourceError = sourceMoveError(options.destination ?? null, root);
34865
+ if (sourceError)
34866
+ return { reason: sourceError };
34182
34867
  const tasks = await getRootTaskChain2(root.id);
34183
34868
  for (const task of tasks) {
34184
34869
  if (!await canMutateTaskNamespace(task, myAgentId, req)) {
@@ -34203,6 +34888,7 @@ var getSession = route({
34203
34888
  chain: array2(TaskWithSteeringSchema),
34204
34889
  access: SessionAccessSchema,
34205
34890
  owner: SessionOwnerSchema.nullable(),
34891
+ groupKey: string2(),
34206
34892
  approvals: array2(SessionApprovalSchema).optional(),
34207
34893
  readState: _enum2(["unread", "read", "later", "done"]).optional(),
34208
34894
  lastActivityAt: string2().optional()
@@ -34389,11 +35075,15 @@ async function handleSessions(req, res, pathSegments, queryParams, myAgentId) {
34389
35075
  if (!parsed)
34390
35076
  return true;
34391
35077
  const actor = await resolveSessionActor2(req, myAgentId);
34392
- sessionTree.respond(res, 200, await getSessionTree(actor, undefined, {
35078
+ const tree = await getSessionTree(actor, undefined, {
34393
35079
  mine: parsed.query.show !== "all",
34394
35080
  hideSource: parsed.query.hideSource,
34395
35081
  showSource: parsed.query.showSource
34396
- }));
35082
+ });
35083
+ const { sourceGroups, slackChannels, threadLabels, ...counts } = tree;
35084
+ const labels = { ...threadLabels, ...await getSessionLabels(sourceGroups) };
35085
+ warmSlackChannelLabels(slackChannels.map((id) => `shared/slack/${id}/`).filter((key) => labels[key] === undefined));
35086
+ sessionTree.respond(res, 200, { ...counts, labels });
34397
35087
  return true;
34398
35088
  }
34399
35089
  if (triageSessionListRoute.match(req.method, pathSegments)) {
@@ -34418,7 +35108,9 @@ async function handleSessions(req, res, pathSegments, queryParams, myAgentId) {
34418
35108
  const skipped = [];
34419
35109
  const moves = [];
34420
35110
  for (const rootId of new Set(parsed.body.rootTaskIds)) {
34421
- const checked = await checkSessionMove(rootId, actor, req, myAgentId);
35111
+ const checked = await checkSessionMove(rootId, actor, req, myAgentId, {
35112
+ destination: key
35113
+ });
34422
35114
  if ("reason" in checked) {
34423
35115
  skipped.push({ rootTaskId: rootId, reason: checked.reason });
34424
35116
  } else {
@@ -34439,6 +35131,10 @@ async function handleSessions(req, res, pathSegments, queryParams, myAgentId) {
34439
35131
  if (!parsed)
34440
35132
  return true;
34441
35133
  const from = normalizeAssetKey(parsed.body.from);
35134
+ if (sourceOfKey(from) || parsed.body.to && sourceOfKey(normalizeAssetKey(parsed.body.to))) {
35135
+ jsonError(res, SOURCE_GROUPS_READ_ONLY, 400);
35136
+ return true;
35137
+ }
34442
35138
  if (parseAssetKey(from).relativeSegments.length === 0) {
34443
35139
  jsonError(res, "Cannot move a namespace root", 400);
34444
35140
  return true;
@@ -34478,7 +35174,8 @@ async function handleSessions(req, res, pathSegments, queryParams, myAgentId) {
34478
35174
  continue;
34479
35175
  }
34480
35176
  const checked = await checkSessionMove(root.id, actor, req, myAgentId, {
34481
- ownerOnly: true
35177
+ ownerOnly: true,
35178
+ destination: nextKey
34482
35179
  });
34483
35180
  if ("reason" in checked) {
34484
35181
  skipped.push({ rootTaskId: root.id, reason: checked.reason });
@@ -34522,11 +35219,12 @@ async function handleSessions(req, res, pathSegments, queryParams, myAgentId) {
34522
35219
  } : null;
34523
35220
  const chain = await getRootTaskChain2(parsed.params.rootTaskId);
34524
35221
  const tasks = [root, ...chain];
34525
- const [steering, citations, approvals, read] = await Promise.all([
35222
+ const [steering, citations, approvals, read, groupKey] = await Promise.all([
34526
35223
  getTaskSteeringFieldsForTasks(tasks),
34527
35224
  getTaskCitationsForTasks(tasks.map((task) => task.id)),
34528
35225
  getPendingApprovalsForTasks2(tasks.map((task) => task.id)),
34529
- actor.kind === "user" && actor.userId ? getSessionReadState(sessionRoot.id, actor.userId) : Promise.resolve(null)
35226
+ actor.kind === "user" && actor.userId ? getSessionReadState(sessionRoot.id, actor.userId) : Promise.resolve(null),
35227
+ getSessionGroupKey(root)
34530
35228
  ]);
34531
35229
  const decorate = (task) => ({
34532
35230
  ...task,
@@ -34538,6 +35236,7 @@ async function handleSessions(req, res, pathSegments, queryParams, myAgentId) {
34538
35236
  chain: chain.map(decorate),
34539
35237
  access,
34540
35238
  owner,
35239
+ groupKey,
34541
35240
  ...approvals.length ? { approvals } : {},
34542
35241
  ...read ?? {}
34543
35242
  });
@@ -35926,7 +36625,8 @@ var SwarmMetricsSchema = object2({
35926
36625
  sessionLogs: RetentionTableStatsSchema.optional(),
35927
36626
  agentLog: RetentionTableStatsSchema.optional(),
35928
36627
  events: RetentionTableStatsSchema.optional(),
35929
- contextVersions: RetentionTableStatsSchema.optional()
36628
+ contextVersions: RetentionTableStatsSchema.optional(),
36629
+ scriptRuns: RetentionTableStatsSchema.optional()
35930
36630
  })
35931
36631
  });
35932
36632
  var ConcurrentContextSchema = object2({
@@ -39391,6 +40091,11 @@ var WorkflowRunPageSchema = object2({
39391
40091
  nextOffset: number2().int().optional()
39392
40092
  })
39393
40093
  });
40094
+ var WorkflowRunTreeSchema = object2({
40095
+ rootRunId: string2(),
40096
+ runs: array2(WorkflowRunSummarySchema),
40097
+ hasOpenWork: boolean()
40098
+ });
39394
40099
  var SuccessResponseSchema = object2({ success: literal2(true) });
39395
40100
  async function withSaveWarnings(workflow) {
39396
40101
  const warnings = await workflowSaveWarnings(workflow.definition, getExecutorRegistry2());
@@ -39605,20 +40310,45 @@ var getWorkflowRunRoute = route({
39605
40310
  path: "/api/workflow-runs/{id}",
39606
40311
  pattern: ["api", "workflow-runs", null],
39607
40312
  summary: "Get a workflow run with steps (includes retry columns)",
40313
+ description: "Returns the run with its `context` and every step with its `input` by default. A step's `input` is a snapshot of the context when the step started, so in runs with loops (polling, `wait`, iterations) the response grows with steps × context size. Pass `fields=slim` to drop `run.context` and `steps[].input`; outputs, errors, diagnostics, retry fields and `parent` stay.",
39608
40314
  tags: ["Workflows"],
39609
40315
  params: object2({ id: string2() }),
40316
+ query: object2({
40317
+ fields: _enum2(["full", "slim"]).optional()
40318
+ }),
39610
40319
  responses: {
39611
40320
  200: {
39612
40321
  description: "Workflow run details with steps including retry info",
39613
- schema: object2({
39614
- run: WorkflowRunSchema,
39615
- steps: array2(WorkflowRunStepSchema),
39616
- parent: WorkflowRunParentSchema.optional()
39617
- })
40322
+ schema: union2([
40323
+ object2({
40324
+ run: WorkflowRunSchema,
40325
+ steps: array2(WorkflowRunStepSchema),
40326
+ parent: WorkflowRunParentSchema.optional()
40327
+ }),
40328
+ object2({
40329
+ run: WorkflowRunSummarySchema,
40330
+ steps: array2(WorkflowRunStepSlimSchema),
40331
+ parent: WorkflowRunParentSchema.optional()
40332
+ })
40333
+ ])
39618
40334
  },
39619
40335
  404: { description: "Run not found" }
39620
40336
  }
39621
40337
  });
40338
+ var getWorkflowRunTreeRoute = route({
40339
+ method: "get",
40340
+ path: "/api/workflow-runs/{id}/tree",
40341
+ pattern: ["api", "workflow-runs", null, "tree"],
40342
+ summary: "Get a workflow run and every sub-workflow run below it",
40343
+ description: `Follows stored parent links (\`parentStepId\` → step → run) through every attempt of every step, terminal runs included. \`runs\` holds list rows without \`context\`, root first. \`hasOpenWork\` is true while any run in the tree is live, has a pending, running or waiting step, a queued retry, an open task or a pending approval; after a cancel it turns false once the tree has settled. Both come from one read snapshot. The tree is not paginated. Links that form a cycle or nest deeper than ${WORKFLOW_RUN_TREE_MAX_DEPTH} levels return 409.`,
40344
+ tags: ["Workflows"],
40345
+ params: object2({ id: string2() }),
40346
+ responses: {
40347
+ 200: { description: "The run tree", schema: WorkflowRunTreeSchema },
40348
+ 404: { description: "Run not found" },
40349
+ 409: { description: "Stored parent links form a cycle or nest past the depth bound" }
40350
+ }
40351
+ });
39622
40352
  var retryWorkflowRunRoute = route({
39623
40353
  method: "post",
39624
40354
  path: "/api/workflow-runs/{id}/retry",
@@ -40171,17 +40901,39 @@ async function handleWorkflows(req, res, pathSegments, queryParams, myAgentId) {
40171
40901
  const parsed = await getWorkflowRunRoute.parse(req, res, pathSegments, queryParams);
40172
40902
  if (!parsed)
40173
40903
  return true;
40174
- const run = await getWorkflowRun2(parsed.params.id, "display");
40904
+ const slim = parsed.query.fields === "slim";
40905
+ const run = slim ? await getWorkflowRunSummary(parsed.params.id) : await getWorkflowRun2(parsed.params.id, "display");
40175
40906
  if (!run) {
40176
40907
  res.writeHead(404);
40177
40908
  res.end();
40178
40909
  return true;
40179
40910
  }
40180
- const steps = await getWorkflowRunStepsByRunId2(parsed.params.id, "display");
40911
+ const steps = slim ? await getWorkflowRunStepsSlimByRunId(parsed.params.id) : await getWorkflowRunStepsByRunId2(parsed.params.id, "display");
40181
40912
  const parent = run.parentStepId ? await getWorkflowRunParent(run.parentStepId) : null;
40182
40913
  getWorkflowRunRoute.respond(res, 200, { run, steps, ...parent ? { parent } : {} });
40183
40914
  return true;
40184
40915
  }
40916
+ if (getWorkflowRunTreeRoute.match(req.method, pathSegments)) {
40917
+ const parsed = await getWorkflowRunTreeRoute.parse(req, res, pathSegments, queryParams);
40918
+ if (!parsed)
40919
+ return true;
40920
+ let tree;
40921
+ try {
40922
+ tree = await getWorkflowRunTree(parsed.params.id);
40923
+ } catch (err) {
40924
+ if (!(err instanceof WorkflowRunTreeError))
40925
+ throw err;
40926
+ jsonError(res, err.message, 409);
40927
+ return true;
40928
+ }
40929
+ if (!tree) {
40930
+ res.writeHead(404);
40931
+ res.end();
40932
+ return true;
40933
+ }
40934
+ getWorkflowRunTreeRoute.respond(res, 200, tree);
40935
+ return true;
40936
+ }
40185
40937
  if (retryWorkflowRunRoute.match(req.method, pathSegments)) {
40186
40938
  const parsed = await retryWorkflowRunRoute.parse(req, res, pathSegments, queryParams);
40187
40939
  if (!parsed)
@@ -40536,6 +41288,7 @@ var httpServer = createHttpServer(async (req, res) => {
40536
41288
  () => handleStatus(req, res, pathSegments, queryParams),
40537
41289
  () => handleOnboarding(req, res, pathSegments, queryParams),
40538
41290
  () => handleCodexOAuthDevice(req, res, pathSegments, queryParams),
41291
+ () => handleCodexOAuthAccounts(req, res, pathSegments, queryParams),
40539
41292
  () => handleActiveSessions(req, res, pathSegments, queryParams, myAgentId),
40540
41293
  () => handlePricing(req, res, pathSegments, queryParams, myAgentId),
40541
41294
  () => handleSchedules(req, res, pathSegments, queryParams, myAgentId),
@@ -40543,6 +41296,7 @@ var httpServer = createHttpServer(async (req, res) => {
40543
41296
  () => handleWorkflowEvents(req, res, pathSegments, queryParams),
40544
41297
  () => handleApprovalRequests(req, res, pathSegments, queryParams),
40545
41298
  () => handleApps(req, res, pathSegments, queryParams, myAgentId),
41299
+ () => handlePoolKeys(req, res, pathSegments, queryParams),
40546
41300
  () => handleConfig(req, res, pathSegments, queryParams),
40547
41301
  () => handleFs(req, res, pathSegments, queryParams, myAgentId),
40548
41302
  () => handleComb(req, res, pathSegments, queryParams, myAgentId),
@@ -40619,7 +41373,7 @@ var httpServer = createHttpServer(async (req, res) => {
40619
41373
  });
40620
41374
  });
40621
41375
  var detachRealtime = attachRealtimeTransport(httpServer);
40622
- var { attachControllerTransport } = await import("./controllers-connect-xp05dj6x.js");
41376
+ var { attachControllerTransport } = await import("./controllers-connect-r2za39ef.js");
40623
41377
  var detachControllers = attachControllerTransport(httpServer);
40624
41378
  var stopWorkerNudges = startWorkerNudgeListener();
40625
41379
  var stopRoomDeletion = realtimeBus.subscribe("room:namespace-deleted", (namespace) => {
@@ -40648,7 +41402,7 @@ async function shutdown() {
40648
41402
  sessionsProcessed: getServerSessionsProcessed()
40649
41403
  });
40650
41404
  if (hasCapability("scheduling")) {
40651
- const { stopScheduler } = await import("./index-xdaahthb.js");
41405
+ const { stopScheduler } = await import("./index-38t35h0n.js");
40652
41406
  stopScheduler();
40653
41407
  }
40654
41408
  stopHeartbeat2();
@@ -40660,7 +41414,7 @@ async function shutdown() {
40660
41414
  await stopSlackApp2();
40661
41415
  await stopChatSdk();
40662
41416
  if (process.env.OAUTH_KEEPALIVE_DISABLE !== "true") {
40663
- const { stopOAuthKeepalive } = await import("./keepalive-v4ta8wgg.js");
41417
+ const { stopOAuthKeepalive } = await import("./keepalive-em0117bp.js");
40664
41418
  await stopOAuthKeepalive();
40665
41419
  }
40666
41420
  stopOAuthPendingGc();
@@ -40740,21 +41494,21 @@ try {
40740
41494
  console.warn("[startup] CAPABILITIES upgrade seed failed (non-fatal):", err);
40741
41495
  }
40742
41496
  try {
40743
- const { ensurePricingSeeded } = await import("./boot-seeds-x28v3fhb.js");
41497
+ const { ensurePricingSeeded } = await import("./boot-seeds-9bmkspyw.js");
40744
41498
  ensurePricingSeeded();
40745
- const { startPricingRefreshLoop } = await import("./pricing-refresh-fsk1e1zc.js");
41499
+ const { startPricingRefreshLoop } = await import("./pricing-refresh-yb75wv33.js");
40746
41500
  startPricingRefreshLoop();
40747
41501
  } catch (err) {
40748
41502
  console.error("[startup] Failed to seed pricing rows:", err);
40749
41503
  }
40750
41504
  try {
40751
- const { ensureModelProfilesSeeded } = await import("./boot-seeds-x28v3fhb.js");
41505
+ const { ensureModelProfilesSeeded } = await import("./boot-seeds-9bmkspyw.js");
40752
41506
  await ensureModelProfilesSeeded();
40753
41507
  } catch (err) {
40754
41508
  console.error("[startup] Failed to seed model profiles:", err);
40755
41509
  }
40756
41510
  try {
40757
- const { ensureRbacSeeded } = await import("./boot-seeds-x28v3fhb.js");
41511
+ const { ensureRbacSeeded } = await import("./boot-seeds-9bmkspyw.js");
40758
41512
  ensureRbacSeeded();
40759
41513
  } catch (err) {
40760
41514
  console.error("[startup] Failed to sync RBAC seed rows:", err);
@@ -40762,7 +41516,7 @@ try {
40762
41516
  throw err;
40763
41517
  }
40764
41518
  try {
40765
- const { runAllSeeders } = await import("./index-q7m26kvs.js");
41519
+ const { runAllSeeders } = await import("./index-qhjf2htm.js");
40766
41520
  await runAllSeeders({ scriptEmbeddingMode: "skip" });
40767
41521
  } catch (err) {
40768
41522
  console.error("[startup] Failed to seed built-in entities:", err);
@@ -40825,41 +41579,44 @@ httpServer.listen(port, async () => {
40825
41579
  await initWorkflows2();
40826
41580
  await startScriptRunSupervisor(getMcpBaseUrl());
40827
41581
  if (hasCapability("scheduling")) {
40828
- const { startScheduler } = await import("./index-xdaahthb.js");
40829
- const { getExecutorRegistry } = await import("./index-1ef1myq2.js");
41582
+ const { startScheduler } = await import("./index-38t35h0n.js");
41583
+ const { getExecutorRegistry } = await import("./index-k0yt1tvq.js");
40830
41584
  const intervalMs = Number(process.env.SCHEDULER_INTERVAL_MS) || 1e4;
40831
41585
  startScheduler(getExecutorRegistry(), intervalMs, {
40832
41586
  runId: globalState.__runId
40833
41587
  });
40834
41588
  }
40835
41589
  if (!isEnvFlagEnabled("HEARTBEAT_DISABLE", false)) {
40836
- const { startHeartbeat } = await import("./index-nmm79qgr.js");
41590
+ const { startHeartbeat } = await import("./index-yqgbfgaj.js");
40837
41591
  const heartbeatMs = Number(process.env.HEARTBEAT_INTERVAL_MS) || 90000;
40838
41592
  startHeartbeat(heartbeatMs);
40839
41593
  }
40840
41594
  startPoolRouting();
40841
41595
  startRuntimeSupervisor();
40842
41596
  if (process.env.OAUTH_KEEPALIVE_DISABLE !== "true") {
40843
- const { startOAuthKeepalive } = await import("./keepalive-v4ta8wgg.js");
41597
+ const { startOAuthKeepalive } = await import("./keepalive-em0117bp.js");
40844
41598
  startOAuthKeepalive();
40845
41599
  }
40846
41600
  if (process.env.OAUTH_REFRESH_SWEEP_DISABLE !== "true") {
40847
- const { startOAuthRefreshSweep } = await import("./oauth-refresh-sweep-vjnnandw.js");
41601
+ const { startOAuthRefreshSweep } = await import("./oauth-refresh-sweep-xysj4yse.js");
40848
41602
  startOAuthRefreshSweep();
40849
41603
  }
40850
41604
  startOAuthPendingGc();
40851
41605
  await startMemoryGc();
40852
41606
  await startDbRetention();
40853
41607
  startHumanFreeDrain();
40854
- import("./boot-reembed-w75maga2.js").then(({ runBootReembed }) => runBootReembed()).catch((err) => {
41608
+ import("./boot-reembed-f4nn561n.js").then(({ runBootReembed }) => runBootReembed()).catch((err) => {
40855
41609
  console.error("[boot-reembed] startup backfill failed (non-fatal):", err);
40856
41610
  });
40857
- import("./boot-reembed-dwzfttdr.js").then(({ runBootReembedScripts }) => runBootReembedScripts()).catch((err) => {
41611
+ import("./boot-reembed-6c1sjfnr.js").then(({ runBootReembedScripts }) => runBootReembedScripts()).catch((err) => {
40858
41612
  console.error("[boot-reembed-scripts] startup backfill failed (non-fatal):", err);
40859
41613
  });
40860
- import("./boot-scrub-sweep-e9kq43kf.js").then(({ runBootScrubSweep }) => runBootScrubSweep()).catch((err) => {
41614
+ import("./boot-scrub-sweep-d4w9gajf.js").then(({ runBootScrubSweep }) => runBootScrubSweep()).catch((err) => {
40861
41615
  console.error("[boot-scrub-sweep] startup scrub failed (non-fatal):", err);
40862
41616
  });
41617
+ import("./session-source-backfill-qgtc86z1.js").then(({ runSessionSourceBackfill }) => runSessionSourceBackfill()).catch((err) => {
41618
+ console.error("[session-source-backfill] startup run failed (non-fatal):", err);
41619
+ });
40863
41620
  }).on("error", (err) => {
40864
41621
  console.error("HTTP Server Error:", err);
40865
41622
  });