@desplega.ai/agent-swarm 2.7.4 → 2.7.5

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 (253) hide show
  1. package/README.md +1 -1
  2. package/dist/acp-adapter-g3ads55s.js +15 -0
  3. package/dist/{actions-gfrr9vb7.js → actions-zwfykqqk.js} +18 -18
  4. package/dist/{amp-adapter-0s58gm46.js → amp-adapter-z3s0ssdt.js} +3 -3
  5. package/dist/{app-stvq692g.js → app-vmp4fgep.js} +3 -3
  6. package/dist/{assistant-5s37fr9n.js → assistant-vwde653f.js} +28 -21
  7. package/dist/{boot-reembed-yzy1841n.js → boot-reembed-375t7tbk.js} +1 -1
  8. package/dist/{boot-reembed-cv82gz7y.js → boot-reembed-gq9rcpnj.js} +1 -1
  9. package/dist/{boot-scrub-sweep-8k4q95ap.js → boot-scrub-sweep-nd938kyf.js} +4 -4
  10. package/dist/{boot-seeds-ftt9htah.js → boot-seeds-aykx51v3.js} +4 -4
  11. package/dist/{boxd-515v1t8z.js → boxd-k1j26g3h.js} +1 -1
  12. package/dist/{claude-adapter-t00wrzeh.js → claude-adapter-8j4hm099.js} +7 -7
  13. package/dist/{claude-managed-adapter-g6vmjccb.js → claude-managed-adapter-dvs2xw5n.js} +2 -2
  14. package/dist/{claude-managed-setup-afpa82f7.js → claude-managed-setup-0wyynpn1.js} +3 -3
  15. package/dist/{claude-sdk-session-vj0c2azx.js → claude-sdk-session-q6wj5hmy.js} +9 -9
  16. package/dist/{cli-wndv9p7g.js → cli-0731hvbw.js} +6 -6
  17. package/dist/{cli-d2pzqej1.js → cli-0bxqnvq9.js} +719 -7
  18. package/dist/{cli-jkt52mgt.js → cli-0gey5fzy.js} +2 -2
  19. package/dist/{cli-1yekbyqm.js → cli-1338796d.js} +205 -48
  20. package/dist/{cli-1s1dqn1j.js → cli-1ayk1eas.js} +171 -123
  21. package/dist/{cli-a4btqqft.js → cli-1b7btd38.js} +1 -1
  22. package/dist/{cli-a2jw6ee5.js → cli-1p89xny0.js} +1 -1
  23. package/dist/{cli-v726afdm.js → cli-2pnswgh8.js} +1 -1
  24. package/dist/{cli-kvtc7aez.js → cli-3h4nhjn8.js} +42 -14
  25. package/dist/{cli-655xm9ms.js → cli-583frbyr.js} +1 -1
  26. package/dist/{cli-4r12t6w6.js → cli-5c4hjzne.js} +101 -4
  27. package/dist/{cli-az0bpf8p.js → cli-5pag6rmn.js} +3 -3
  28. package/dist/{cli-36g23z21.js → cli-6s7vdcta.js} +4 -4
  29. package/dist/{cli-rtk9g7av.js → cli-73jzwksr.js} +6 -2
  30. package/dist/{cli-jg0nfda6.js → cli-75gkpjvw.js} +52 -21
  31. package/dist/{cli-a81qevyg.js → cli-7a42nfy0.js} +20 -36
  32. package/dist/{cli-0sbkss7h.js → cli-7wcyk2s5.js} +2 -2
  33. package/dist/{cli-41z8xwj0.js → cli-7wspm5gm.js} +14 -4
  34. package/dist/{cli-byqfbnjw.js → cli-82ae98pz.js} +9 -9
  35. package/dist/{cli-bq2pcphn.js → cli-8hs41zy2.js} +1 -1
  36. package/dist/{cli-vqgnyh76.js → cli-98rw5dt5.js} +15 -3
  37. package/dist/{cli-9cctx1tn.js → cli-a22h291q.js} +1 -1
  38. package/dist/{cli-j4kt1mpb.js → cli-a47xy8eq.js} +3 -3
  39. package/dist/{cli-ycm6180s.js → cli-a7v854rf.js} +5 -3
  40. package/dist/{cli-98pke4vk.js → cli-ae7mrdf9.js} +2 -2
  41. package/dist/{cli-ahd90bwt.js → cli-afrrppsw.js} +6 -6
  42. package/dist/{cli-8yy525ad.js → cli-bhjt02p8.js} +2 -2
  43. package/dist/{cli-v1yw3wha.js → cli-bnz7a7qf.js} +4 -4
  44. package/dist/{cli-j4kw3rsx.js → cli-cm5yqn35.js} +18 -0
  45. package/dist/{cli-h55y2bjc.js → cli-dhar9qay.js} +2 -2
  46. package/dist/{cli-5gr1g711.js → cli-fqzx7gwa.js} +2 -2
  47. package/dist/{cli-tzrpv5sc.js → cli-ftyxyspd.js} +1 -1
  48. package/dist/cli-fw2w0kva.js +47 -0
  49. package/dist/{cli-2dfbv8qr.js → cli-fy6x31ps.js} +1 -0
  50. package/dist/{cli-mvckssyq.js → cli-g61qxmge.js} +5 -5
  51. package/dist/{cli-aq58fk5m.js → cli-g83s9ewh.js} +7 -1
  52. package/dist/{cli-224epwwf.js → cli-hn9hxmz9.js} +3 -3
  53. package/dist/{cli-5hjced2v.js → cli-j3jvnpe8.js} +6 -6
  54. package/dist/{cli-dae4sbgy.js → cli-jm2vfpfd.js} +2 -2
  55. package/dist/{cli-zn15c46z.js → cli-mjzynrse.js} +1 -1
  56. package/dist/{cli-a1fhj4n9.js → cli-mmwm7zbf.js} +2 -2
  57. package/dist/{cli-cq1pf336.js → cli-mry0qzym.js} +5 -5
  58. package/dist/{cli-bwty35gx.js → cli-mthwvjre.js} +1 -1
  59. package/dist/{cli-s0exq74r.js → cli-nmbmy64z.js} +3 -3
  60. package/dist/{cli-wcmnan2g.js → cli-nn4d8dne.js} +5 -5
  61. package/dist/{cli-jg4p5t36.js → cli-nzxr556s.js} +121 -51
  62. package/dist/{cli-bcz074zx.js → cli-p599f1qm.js} +1 -1
  63. package/dist/{cli-k76tgq03.js → cli-pywf3eh5.js} +2 -2
  64. package/dist/{cli-wk9md5px.js → cli-qxnf8z2z.js} +2 -2
  65. package/dist/{cli-je8yeyc5.js → cli-rhw40jgb.js} +5 -5
  66. package/dist/{cli-avgcz4ra.js → cli-rm6hqj3z.js} +406 -35
  67. package/dist/{cli-0fgr1w9b.js → cli-rpm2sgv0.js} +2 -2
  68. package/dist/{cli-t282jgab.js → cli-rqkxrmgw.js} +12 -12
  69. package/dist/{cli-2qpvmmkw.js → cli-s0qnd4wv.js} +1 -1
  70. package/dist/{cli-pwyevs29.js → cli-spknvxbq.js} +22 -21
  71. package/dist/{cli-9y354g3j.js → cli-srye3vdt.js} +1 -1
  72. package/dist/{cli-pe09p6dv.js → cli-tqgg40ek.js} +1 -1
  73. package/dist/{cli-f255yaqn.js → cli-vbyfwh92.js} +3 -3
  74. package/dist/{cli-gcbdjt47.js → cli-vfym7wmz.js} +6 -6
  75. package/dist/{cli-edmm9d9y.js → cli-vqypxzh4.js} +7 -7
  76. package/dist/{cli-1gm8jcyr.js → cli-wvaawacd.js} +13 -13
  77. package/dist/{cli-eny54typ.js → cli-wx3rhnm0.js} +1 -1
  78. package/dist/{cli-b1afgtj3.js → cli-xbkdm710.js} +3 -3
  79. package/dist/{cli-mc97xy2s.js → cli-xtjhfmpc.js} +16 -4
  80. package/dist/{cli-eqx6k993.js → cli-y24sc29k.js} +25 -13
  81. package/dist/{cli-ktmvb20s.js → cli-z6jkx23q.js} +12 -12
  82. package/dist/{cli-7n5sbw0z.js → cli-z8eh3ex8.js} +5 -5
  83. package/dist/cli-zh3fp8v2.js +151 -0
  84. package/dist/{cli-13jvmew3.js → cli-zppwg9p9.js} +7 -7
  85. package/dist/cli.js +18 -18
  86. package/dist/{codex-adapter-g0gctw29.js → codex-adapter-q6k3gnyg.js} +5 -5
  87. package/dist/{codex-hook-vrzz2xhr.js → codex-hook-9efm2x1m.js} +1 -1
  88. package/dist/{codex-login-0gg46ygn.js → codex-login-y0pmff1c.js} +1 -1
  89. package/dist/{codex-session-runner-dr2cxe1c.js → codex-session-runner-3mwmk3d9.js} +6 -6
  90. package/dist/{commands-1p07cvff.js → commands-evrenjn9.js} +2 -2
  91. package/dist/{controller-z0s7sv6r.js → controller-xjp8vswh.js} +4 -4
  92. package/dist/{controllers-connect-x9kvvhyk.js → controllers-connect-pp5jnxvc.js} +20 -20
  93. package/dist/{cursor-adapter-m5b98pvk.js → cursor-adapter-yf47w4t0.js} +2 -2
  94. package/dist/{db-rsh04kh3.js → db-rgfsh91f.js} +2 -2
  95. package/dist/{db-capk2raj.js → db-zxpw6aht.js} +3 -3
  96. package/dist/{devin-adapter-yxm87fe9.js → devin-adapter-r9phbnc9.js} +1 -1
  97. package/dist/{dispatcher-304q6fwa.js → dispatcher-smasgws7.js} +17 -17
  98. package/dist/{docker-7rxt0rry.js → docker-rrjhaqt9.js} +2 -2
  99. package/dist/{dsh-adapter-btewem0y.js → dsh-adapter-ftyy8dnp.js} +2 -2
  100. package/dist/{e2b-renc0k8q.js → e2b-qcaj675y.js} +2 -2
  101. package/dist/{e2b-7fc9b9bd.js → e2b-w1p0bnpm.js} +2 -2
  102. package/dist/{easter-egg-3d-fm1p3n4d.js → easter-egg-3d-yyts7p16.js} +1 -1
  103. package/dist/{embedding-space-s68v49ct.js → embedding-space-1z0mbg95.js} +6 -6
  104. package/dist/{embeddings-4ms3604w.js → embeddings-ygeg7tm7.js} +1 -1
  105. package/dist/{event-bus-dfjx2qdh.js → event-bus-g0ka3pbw.js} +1 -1
  106. package/dist/{execute-mcdgccjs.js → execute-14qhqp4d.js} +1 -1
  107. package/dist/{external-channel-9dxwfztn.js → external-channel-ttgrs3sx.js} +2 -2
  108. package/dist/fx-adapter-gt6pncj2.js +18 -0
  109. package/dist/{grok-adapter-05ecv4h0.js → grok-adapter-sm4m5k4g.js} +8 -8
  110. package/dist/handlers-vwmba1m2.js +31 -0
  111. package/dist/{heartbeat-3n94heh3.js → heartbeat-qahz4p62.js} +20 -20
  112. package/dist/{hook-zxwje86c.js → hook-4fd5wq5w.js} +4 -4
  113. package/dist/{hook-aadrn69x.js → hook-kj3d398m.js} +6 -6
  114. package/dist/{http-xzxk9mst.js → http-1ted0j1k.js} +100 -64
  115. package/dist/index-5r71rf98.js +32 -0
  116. package/dist/{index-d34f6r87.js → index-6rq3r5zb.js} +1 -1
  117. package/dist/{index-9j4zwcht.js → index-7v51awbn.js} +158 -672
  118. package/dist/index-anmwxs87.js +29 -0
  119. package/dist/{index-qeb82z37.js → index-q4b917zs.js} +1 -1
  120. package/dist/index-spp0ra5c.js +36 -0
  121. package/dist/{keepalive-w4aakbyk.js → keepalive-6cf311t5.js} +4 -4
  122. package/dist/lead-fjy418cw.js +69 -0
  123. package/dist/{maintenance-hbptpk6p.js → maintenance-a4bm1bmt.js} +1 -1
  124. package/dist/{oauth-refresh-sweep-217semrv.js → oauth-refresh-sweep-3h0dfw1k.js} +3 -3
  125. package/dist/{onboard-vz2s5df3.js → onboard-myn5hraa.js} +3 -3
  126. package/dist/{opencode-adapter-gtfd7d7v.js → opencode-adapter-p2nkb5am.js} +5 -5
  127. package/dist/{otel-impl-aefave37.js → otel-impl-a1a0ef6b.js} +2 -2
  128. package/dist/{pi-mono-adapter-f8h5yseh.js → pi-mono-adapter-rzmpb72a.js} +117 -23
  129. package/dist/{pricing-refresh-m1yhh9ya.js → pricing-refresh-83drrnxj.js} +3 -3
  130. package/dist/{rbac-roles-svj72cdf.js → rbac-roles-0fb6e7pj.js} +2 -2
  131. package/dist/{rbac-roles-rrw8twdz.js → rbac-roles-s8y6ecb5.js} +1 -1
  132. package/dist/{render-v2-amwbnfxh.js → render-v2-twmbgrz4.js} +3 -3
  133. package/dist/{resume-9cd6wf6z.js → resume-zfqc36xj.js} +7 -7
  134. package/dist/{runtime-fp4vrx7m.js → runtime-qwggdpqr.js} +1 -1
  135. package/dist/{session-access-21t6yjyg.js → session-access-sc9pn9da.js} +4 -4
  136. package/dist/{session-source-backfill-pxbzcsc6.js → session-source-backfill-qh07xr8g.js} +3 -3
  137. package/dist/{setup-4592tqz4.js → setup-4fr0m7a1.js} +1 -1
  138. package/dist/{virtual-modules-gzfnpmnz.js → virtual-modules-fh4ha15b.js} +2 -2
  139. package/dist/{work-objects-t9tcf174.js → work-objects-0wr8zxct.js} +20 -20
  140. package/dist/worker-0c5tyzqe.js +69 -0
  141. package/dist/{worker-follow-up-q32jh4yk.js → worker-follow-up-ktyyazyp.js} +17 -17
  142. package/dist/{x-b6wxntdt.js → x-vmmye1kb.js} +2 -2
  143. package/openapi.json +97 -32
  144. package/package.json +1 -1
  145. package/src/be/db/session-summaries.ts +8 -2
  146. package/src/be/db/session-tree.ts +174 -61
  147. package/src/be/db/session-visibility.ts +5 -4
  148. package/src/be/db.ts +8 -4
  149. package/src/be/migrations/259_session_summaries_open_tasks.sql +111 -0
  150. package/src/be/model-validation.ts +5 -1
  151. package/src/be/pricing-normalize.ts +7 -2
  152. package/src/be/scripts/typecheck.ts +1 -0
  153. package/src/be/seed/schedules-seeder.ts +135 -9
  154. package/src/be/seed/workflows-seeder.ts +65 -1
  155. package/src/be/seed-pricing.ts +23 -0
  156. package/src/be/steering.ts +50 -3
  157. package/src/be/swarm-config-guard.ts +1 -0
  158. package/src/commands/provider-credentials.ts +29 -2
  159. package/src/commands/runner.ts +86 -5
  160. package/src/extensions/contract-types.generated.ts +1 -1
  161. package/src/extensions/contract.ts +27 -1
  162. package/src/extensions/dispatcher.ts +4 -0
  163. package/src/http/agents.ts +1 -0
  164. package/src/http/mcp-bridge.ts +4 -0
  165. package/src/integrations/chat-sdk/inbound.ts +15 -5
  166. package/src/integrations/chat-sdk/steering.ts +3 -1
  167. package/src/kv-reserved-namespaces.ts +2 -0
  168. package/src/prompts/base-prompt.ts +4 -1
  169. package/src/prompts/session-templates.ts +26 -0
  170. package/src/providers/acp-adapter.ts +190 -26
  171. package/src/providers/acp-targets.ts +306 -6
  172. package/src/providers/amp-adapter.ts +1 -1
  173. package/src/providers/codex-adapter.ts +9 -44
  174. package/src/providers/codex-oauth/flow.ts +24 -3
  175. package/src/providers/codex-oauth/storage.ts +56 -17
  176. package/src/providers/codex-oauth/subscription.ts +67 -0
  177. package/src/providers/fx-adapter.ts +211 -0
  178. package/src/providers/index.ts +5 -1
  179. package/src/providers/mcp-loopback-proxy.ts +94 -0
  180. package/src/providers/pi-mono-adapter.ts +98 -13
  181. package/src/providers/pricing-sources.md +8 -0
  182. package/src/providers/reasoning-effort.ts +17 -1
  183. package/src/providers/types.ts +2 -1
  184. package/src/scheduler/scheduler.ts +36 -3
  185. package/src/scripts-runtime/sdk-allowlist.ts +1 -0
  186. package/src/scripts-runtime/types/stdlib.d.ts +5 -0
  187. package/src/scripts-runtime/types/swarm-extension.d.ts +33 -0
  188. package/src/scripts-runtime/types/swarm-sdk.d.ts +5 -0
  189. package/src/server.ts +7 -0
  190. package/src/slack/assistant.ts +17 -1
  191. package/src/slack/handlers.ts +18 -5
  192. package/src/slack/left-threads.ts +65 -0
  193. package/src/slack/steering.ts +3 -0
  194. package/src/slack/thread-buffer.ts +40 -16
  195. package/src/tests/acp-adapter.test.ts +79 -0
  196. package/src/tests/base-prompt.test.ts +12 -0
  197. package/src/tests/chat-sdk-inbound.test.ts +30 -0
  198. package/src/tests/chatgpt-subscription-model-groups.test.ts +62 -0
  199. package/src/tests/chatgpt-subscription-pi.test.ts +170 -0
  200. package/src/tests/chatgpt-subscription-session-bench.test.ts +198 -0
  201. package/src/tests/codex-oauth-credential-info.test.ts +40 -0
  202. package/src/tests/codex-oauth-refresh-egress.test.ts +194 -0
  203. package/src/tests/context-window.test.ts +7 -0
  204. package/src/tests/explicit-model-validation.test.ts +99 -0
  205. package/src/tests/extensions-run-context.test.ts +11 -0
  206. package/src/tests/extensions-steering.test.ts +353 -0
  207. package/src/tests/extensions-validate.test.ts +5 -0
  208. package/src/tests/fixtures/extensions/steering-policy/hooks.ts +39 -0
  209. package/src/tests/fixtures/extensions/steering-policy/manifest.json +7 -0
  210. package/src/tests/fixtures/fake-fx.ts +167 -0
  211. package/src/tests/fixtures/fx/acp-responses-recorded.json +157 -0
  212. package/src/tests/fixtures/fx/acp-updates-recorded.jsonl +15 -0
  213. package/src/tests/fx-adapter.test.ts +771 -0
  214. package/src/tests/grok-adapter.test.ts +36 -0
  215. package/src/tests/mcp-loopback-proxy.test.ts +193 -0
  216. package/src/tests/model-tier-resolution.test.ts +3 -3
  217. package/src/tests/pricing-refresh.test.ts +5 -5
  218. package/src/tests/prompt-template-session.test.ts +5 -3
  219. package/src/tests/provider-registration.test.ts +2 -1
  220. package/src/tests/query-audit-plans.test.ts +3 -2
  221. package/src/tests/script-connections.test.ts +2 -0
  222. package/src/tests/seed-model-profiles.test.ts +2 -2
  223. package/src/tests/seed-schedules.test.ts +138 -0
  224. package/src/tests/session-cost-recompute-unit.test.ts +39 -0
  225. package/src/tests/session-costs-golden.test.ts +26 -0
  226. package/src/tests/session-summaries-plans.test.ts +120 -0
  227. package/src/tests/session-summaries.test.ts +72 -12
  228. package/src/tests/sessions-tree.test.ts +11 -3
  229. package/src/tests/slack-leave-thread.test.ts +431 -0
  230. package/src/tests/tool-annotations.test.ts +2 -1
  231. package/src/tests/workflow-engine-v2.test.ts +42 -0
  232. package/src/tests/workflow-script-principal.test.ts +207 -7
  233. package/src/tools/slack-leave-thread.ts +104 -0
  234. package/src/tools/steer-task.ts +3 -2
  235. package/src/tools/tool-config.ts +2 -1
  236. package/src/types.ts +19 -0
  237. package/src/utils/codex-auth-failure.ts +30 -0
  238. package/src/utils/context-window.ts +4 -1
  239. package/src/utils/credentials.ts +7 -0
  240. package/src/utils/fx-models.ts +43 -0
  241. package/src/workflows/cooldown.ts +3 -2
  242. package/src/workflows/engine.ts +24 -9
  243. package/templates/schedules/dreaming-daily/config.json +1 -1
  244. package/templates/schedules/dreaming-daily/content.md +6 -14
  245. package/templates/skills/swarm-docs/content.md +1 -0
  246. package/templates/workflows/dreaming/content.md +5 -1
  247. package/dist/acp-adapter-96dc64m2.js +0 -15
  248. package/dist/handlers-jg7v74ty.js +0 -31
  249. package/dist/index-8c1zbz59.js +0 -29
  250. package/dist/index-8k8tmfxd.js +0 -32
  251. package/dist/index-hq617xdj.js +0 -36
  252. package/dist/lead-567kw7x3.js +0 -68
  253. package/dist/worker-fjdqra6q.js +0 -68
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  openAICompatibleKeyVars,
3
3
  init_src2
4
- } from "./cli-4r12t6w6.js";
4
+ } from "./cli-5c4hjzne.js";
5
5
  import {
6
6
  __esm
7
7
  } from "./cli-242037k3.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  withRegistryCatalogSections,
3
3
  init_src2
4
- } from "./cli-4r12t6w6.js";
4
+ } from "./cli-5c4hjzne.js";
5
5
  import {
6
6
  __esm
7
7
  } from "./cli-242037k3.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  registerTemplate,
3
3
  init_registry3
4
- } from "./cli-j4kw3rsx.js";
4
+ } from "./cli-cm5yqn35.js";
5
5
  import {
6
6
  __esm
7
7
  } from "./cli-242037k3.js";
@@ -6,11 +6,12 @@ import {
6
6
  getLatestActiveTaskInThread2,
7
7
  getLatestLeadTaskInThread2,
8
8
  getMostRecentTaskInThread2,
9
+ SteeringBlockedError,
9
10
  requestSteering,
10
11
  init_steering2,
11
12
  createLogEntry2,
12
13
  init_db4
13
- } from "./cli-1s1dqn1j.js";
14
+ } from "./cli-1ayk1eas.js";
14
15
  import {
15
16
  ackSlackMessage,
16
17
  init_ack,
@@ -26,7 +27,7 @@ import {
26
27
  init_watcher,
27
28
  getSlackApp2,
28
29
  init_app3
29
- } from "./cli-1gm8jcyr.js";
30
+ } from "./cli-wvaawacd.js";
30
31
  import {
31
32
  TaskCreationBlockedError,
32
33
  init_errors2,
@@ -36,20 +37,22 @@ import {
36
37
  createSlackTaskWithFiles,
37
38
  notifySlackFileFailures,
38
39
  init_inbound_files,
40
+ isSlackThreadLeft,
41
+ init_left_threads,
39
42
  extractSlackMessageText,
40
43
  init_message_text,
41
44
  createAdditiveBuffer,
42
45
  init_additive_buffer
43
- } from "./cli-1yekbyqm.js";
46
+ } from "./cli-1338796d.js";
44
47
  import {
45
48
  resolveSlackUserId,
46
49
  rewriteSlackMentions,
47
50
  init_enrich
48
- } from "./cli-s0exq74r.js";
51
+ } from "./cli-nmbmy64z.js";
49
52
  import {
50
53
  findUserByExternalId,
51
54
  init_users
52
- } from "./cli-8yy525ad.js";
55
+ } from "./cli-bhjt02p8.js";
53
56
  import {
54
57
  isSteeringEnabled2,
55
58
  init_steering_enabled
@@ -57,7 +60,7 @@ import {
57
60
  import {
58
61
  scrubSecrets,
59
62
  init_secret_scrubber
60
- } from "./cli-a4btqqft.js";
63
+ } from "./cli-1b7btd38.js";
61
64
  import {
62
65
  __esm,
63
66
  __using,
@@ -135,7 +138,9 @@ async function requestSlackThreadSteering(args) {
135
138
  onUnsupported: "degrade",
136
139
  source: "slack",
137
140
  createdByKind: "user",
138
- createdByUserId: args.requestedByUserId
141
+ createdByUserId: args.requestedByUserId,
142
+ messageTimestamps: args.messageTimestamps,
143
+ slack: { channelId: args.channelId, threadTs: args.threadTs, userId: args.slackUserId }
139
144
  });
140
145
  for (const messageTs of args.messageTimestamps ?? []) {
141
146
  await createLogEntry2({
@@ -230,6 +235,10 @@ async function slackFlush(items, key, immediate) {
230
235
  return;
231
236
  }
232
237
  const { channelId, threadTs } = split;
238
+ if (await isSlackThreadLeft(channelId, threadTs)) {
239
+ console.log(`[Slack] Buffer flush: dropping ${items.length} message(s) in left thread ${key}`);
240
+ return;
241
+ }
233
242
  const originalRequesterId = items[0].userId;
234
243
  const botUserId = items.find((item) => item.botUserId)?.botUserId;
235
244
  console.log(`[Slack] Flushing buffer: ${key} (${items.length} messages, immediate=${immediate})`);
@@ -258,15 +267,32 @@ ${combinedText}`;
258
267
  }) : (await findUserByExternalId("slack", originalRequesterId))?.id;
259
268
  const nextSenderIndex = items.findIndex((item) => item.userId !== originalRequesterId);
260
269
  const steeringItems = nextSenderIndex === -1 ? items : items.slice(0, nextSenderIndex);
261
- const steering = files.length === 0 ? await requestSlackThreadSteering({
262
- channelId,
263
- threadTs,
264
- message: nextSenderIndex === -1 ? combinedText : await rewriteSlackMentions(steeringItems.map((item) => item.text).join(`
270
+ let steering;
271
+ try {
272
+ steering = files.length === 0 ? await requestSlackThreadSteering({
273
+ channelId,
274
+ threadTs,
275
+ message: nextSenderIndex === -1 ? combinedText : await rewriteSlackMentions(steeringItems.map((item) => item.text).join(`
265
276
  ---
266
277
  `), botUserId),
267
- messageTimestamps: steeringItems.map((item) => item.ts),
268
- requestedByUserId
269
- }) : null;
278
+ messageTimestamps: steeringItems.map((item) => item.ts),
279
+ requestedByUserId,
280
+ slackUserId: originalRequesterId
281
+ }) : null;
282
+ } catch (error) {
283
+ if (!(error instanceof SteeringBlockedError))
284
+ throw error;
285
+ console.info("[Slack] pre.task.steer blocked:", error.extension.name, error.reason);
286
+ if (app) {
287
+ for (const item of steeringItems) {
288
+ await ackSlackMessage(app.client, channelId, item.ts, "no_entry");
289
+ }
290
+ }
291
+ if (nextSenderIndex !== -1) {
292
+ await slackFlush(items.slice(nextSenderIndex), key, immediate);
293
+ }
294
+ return;
295
+ }
270
296
  if (steering) {
271
297
  console.log(`[Slack] Buffer flushed → steering ${steering.result.outcome} for task ${steering.task.id}`);
272
298
  const agent = steering.task.agentId ? await getAgentById2(steering.task.agentId) : undefined;
@@ -373,6 +399,7 @@ ${description}` : description;
373
399
  var BUFFER_TIMEOUT_MS, slackBuffer;
374
400
  var init_thread_buffer = __esm(() => {
375
401
  init_db4();
402
+ init_steering2();
376
403
  init_users();
377
404
  init_additive_buffer();
378
405
  init_context_key();
@@ -383,6 +410,7 @@ var init_thread_buffer = __esm(() => {
383
410
  init_blocks();
384
411
  init_enrich();
385
412
  init_inbound_files();
413
+ init_left_threads();
386
414
  init_message_text();
387
415
  init_render_v2();
388
416
  init_responses();
@@ -2,7 +2,7 @@ import {
2
2
  DEFAULT_E2B_API_BASE,
3
3
  redactWithEnv,
4
4
  init_env2
5
- } from "./cli-98pke4vk.js";
5
+ } from "./cli-ae7mrdf9.js";
6
6
  import {
7
7
  __toESM,
8
8
  __esm
@@ -2,6 +2,23 @@ import {
2
2
  __esm
3
3
  } from "./cli-242037k3.js";
4
4
 
5
+ // packages/model-catalog/src/chatgpt-subscription.ts
6
+ function chatgptSubscriptionModelId(model) {
7
+ const trimmed = model?.trim() ?? "";
8
+ const prefix = `${CHATGPT_SUBSCRIPTION_PROVIDER}/`;
9
+ if (!trimmed.toLowerCase().startsWith(prefix))
10
+ return null;
11
+ const id = trimmed.slice(prefix.length);
12
+ return id && !id.includes("/") ? id : null;
13
+ }
14
+ function isChatgptSubscriptionModel(model) {
15
+ return chatgptSubscriptionModelId(model) !== null;
16
+ }
17
+ var CHATGPT_SUBSCRIPTION_PROVIDER = "openai-codex", CHATGPT_SUBSCRIPTION_HARNESSES;
18
+ var init_chatgpt_subscription = __esm(() => {
19
+ CHATGPT_SUBSCRIPTION_HARNESSES = ["pi"];
20
+ });
21
+
5
22
  // packages/model-catalog/src/display.ts
6
23
  var init_display = () => {};
7
24
 
@@ -153,7 +170,27 @@ function harnessCatalogSection(harness) {
153
170
  return HARNESS_CATALOG_SECTION[harness] ?? null;
154
171
  }
155
172
  function isHarnessModelJudged(harness) {
156
- return !!harness && (harnessCatalogSection(harness) !== null || harness === "grok");
173
+ return !!harness && (harnessCatalogSection(harness) !== null || harness === "grok" || harness === "fx");
174
+ }
175
+ function fxModelRoute(model) {
176
+ const id = model.trim();
177
+ if (!id)
178
+ return { error: `An empty model has no fx route. ${FX_ROUTES_HINT}` };
179
+ const slash = id.indexOf("/");
180
+ if (slash < 0)
181
+ return { fxProvider: "openai", fxModel: id, keyVar: "OPENAI_API_KEY" };
182
+ const namespace = id.slice(0, slash).toLowerCase();
183
+ const rest = id.slice(slash + 1).trim();
184
+ if (namespace === "openrouter" && rest) {
185
+ return { fxProvider: "openrouter", fxModel: rest, keyVar: "OPENROUTER_API_KEY" };
186
+ }
187
+ if (namespace === "vercel" && rest) {
188
+ return { fxProvider: "gateway", fxModel: rest, keyVar: "AI_GATEWAY_API_KEY" };
189
+ }
190
+ const reason = FX_REJECTED_NAMESPACES[namespace];
191
+ return {
192
+ error: `Model "${id}" has no fx route${reason ? `: ${reason}` : ""}. ${FX_ROUTES_HINT}`
193
+ };
157
194
  }
158
195
  function normalizeGrokModel(model) {
159
196
  return model.trim().replace(XAI_PREFIX_RE, "");
@@ -228,8 +265,14 @@ function buildClaudeShortnameMap(models) {
228
265
  return out;
229
266
  }
230
267
  function harnessModelMismatch(model, harness, sections, context = {}) {
268
+ const subscriptionId = chatgptSubscriptionModelId(model);
269
+ if (harness && subscriptionId && !CHATGPT_SUBSCRIPTION_HARNESSES.includes(harness)) {
270
+ return subscriptionMismatchMessage(model.trim(), subscriptionId, harness, context);
271
+ }
231
272
  if (harness === "grok")
232
273
  return grokModelMismatch(model, sections, context);
274
+ if (harness === "fx")
275
+ return fxModelMismatch(model, sections, context);
233
276
  const section = harness ? harnessCatalogSection(harness) : null;
234
277
  if (!harness || !section)
235
278
  return null;
@@ -291,6 +334,37 @@ function grokModelMismatch(model, sections, context) {
291
334
  }
292
335
  return null;
293
336
  }
337
+ function fxModelMismatch(model, sections, context) {
338
+ const id = model.trim();
339
+ if (!id)
340
+ return null;
341
+ const agent = context.agentId ? ` of agent "${context.agentName ?? context.agentId}" (${context.agentId})` : "";
342
+ const fail = (reason) => `Model "${id}" does not run on the fx harness${agent}. ${reason} Use modelTier (smol, regular, smart, ultra) for portable intent, or omit model and let the assignee resolve it.`;
343
+ if (isAlias(id)) {
344
+ const parsed = parseAlias(id);
345
+ if (!parsed)
346
+ return null;
347
+ return parsed.kind === "openrouter" || parsed.kind === "openai" ? null : fail(`A latest:${parsed.kind} alias resolves to an id fx cannot route. ${FX_ROUTES_HINT}`);
348
+ }
349
+ const route = fxModelRoute(id);
350
+ if ("error" in route)
351
+ return fail(route.error);
352
+ if (route.fxProvider !== "openai")
353
+ return null;
354
+ if (Object.hasOwn(sections.openai?.models ?? {}, id))
355
+ return null;
356
+ for (const [name, other] of Object.entries(sections)) {
357
+ if (name === "openai" || !other?.models)
358
+ continue;
359
+ if (Object.hasOwn(other.models, id) || name === "anthropic" && isClaudeShortname(id, other)) {
360
+ return fail(`A bare id runs on OpenAI (OPENAI_API_KEY), and "${id}" is in the ${name} catalog, not openai. ${FX_ROUTES_HINT}`);
361
+ }
362
+ }
363
+ return null;
364
+ }
365
+ function isClaudeShortname(id, section) {
366
+ return Object.hasOwn(buildClaudeShortnameMap(section.models), id);
367
+ }
294
368
  function grokMismatchMessage(model, sections, context) {
295
369
  const agent = context.agentId ? ` of agent "${context.agentName ?? context.agentId}" (${context.agentId})` : "";
296
370
  const pool = sections.xai?.models ? [sections.xai.models] : Object.values(sections).map((section) => section?.models ?? {});
@@ -307,6 +381,11 @@ function grokMismatchMessage(model, sections, context) {
307
381
  const examples = ids.length ? ` (for example: ${ids.slice(0, MAX_EXAMPLE_IDS).join(", ")}${extra > 0 ? ` and ${extra} more` : ""})` : "";
308
382
  return `Model "${model}" does not run on the grok harness${agent}. The grok harness accepts xai catalog models${examples} and openrouter/<vendor>/<id>. Use modelTier (smol, regular, smart, ultra) for portable intent, or omit model and let the assignee resolve it.`;
309
383
  }
384
+ function subscriptionMismatchMessage(model, bareId, harness, context) {
385
+ const agent = context.agentId ? ` of agent "${context.agentName ?? context.agentId}" (${context.agentId})` : "";
386
+ const codexHint = harness === "codex" ? ` On codex, use "${bareId}": codex runs it on the pool directly.` : "";
387
+ return `Model "${model}" does not run on the ${harness} harness${agent}. The ChatGPT subscription prefix (openai-codex/) is for the ${CHATGPT_SUBSCRIPTION_HARNESSES.join(" and ")} harness.${codexHint}`;
388
+ }
310
389
  function harnessMismatchMessage(model, harness, section, own, context) {
311
390
  const agent = context.agentId ? ` of agent "${context.agentName ?? context.agentId}" (${context.agentId})` : "";
312
391
  const ids = harnessModelIds(harness, own);
@@ -314,14 +393,20 @@ function harnessMismatchMessage(model, harness, section, own, context) {
314
393
  const examples = ids.slice(0, MAX_EXAMPLE_IDS).join(", ") + (extra > 0 ? ` and ${extra} more` : "");
315
394
  return `Model "${model}" does not run on the ${harness} harness${agent}. The ${harness} harness accepts ${section} catalog models, for example: ${examples}. Use modelTier (smol, regular, smart, ultra) for portable intent, or omit model and let the assignee resolve it.`;
316
395
  }
317
- var HARNESS_CATALOG_SECTION, XAI_PREFIX_RE, GROK_ID_RE, DATED_ID_RE3, ISO_DATED_ID_RE, CODEX_EXCLUDED_TOKENS, CODEX_MIN_GPT_MAJOR = 5, CONTEXT_SUFFIX_RE, MAX_EXAMPLE_IDS = 8;
396
+ var HARNESS_CATALOG_SECTION, FX_REJECTED_NAMESPACES, FX_ROUTES_HINT = "The fx harness runs openrouter/<vendor>/<id> (OPENROUTER_API_KEY), vercel/<vendor>/<id> (AI_GATEWAY_API_KEY) or a bare OpenAI id (OPENAI_API_KEY).", XAI_PREFIX_RE, GROK_ID_RE, DATED_ID_RE3, ISO_DATED_ID_RE, CODEX_EXCLUDED_TOKENS, CODEX_MIN_GPT_MAJOR = 5, CONTEXT_SUFFIX_RE, MAX_EXAMPLE_IDS = 8;
318
397
  var init_harness_models = __esm(() => {
398
+ init_chatgpt_subscription();
319
399
  init_resolve_alias();
320
400
  HARNESS_CATALOG_SECTION = {
321
401
  claude: "anthropic",
322
402
  "claude-managed": "anthropic",
323
403
  codex: "openai"
324
404
  };
405
+ FX_REJECTED_NAMESPACES = {
406
+ nan: "fx rejects NaN's streams (InconsistentFinishReason on its trailing usage chunk, fx 0.0.15)",
407
+ helmcode: "Helmcode is not verified on fx yet",
408
+ anthropic: "fx cannot speak the Anthropic Messages API; use openrouter/anthropic/<id> or vercel/anthropic/<id>"
409
+ };
325
410
  XAI_PREFIX_RE = /^xai\//i;
326
411
  GROK_ID_RE = /^grok-[^/]+$/i;
327
412
  DATED_ID_RE3 = /-\d{8}$/;
@@ -671,6 +756,12 @@ function grokCatalogRef(model) {
671
756
  }
672
757
  return { providerId: "xai", modelId: id };
673
758
  }
759
+ function fxCatalogRef(model) {
760
+ const route = fxModelRoute(model);
761
+ if ("error" in route || route.fxProvider !== "gateway")
762
+ return null;
763
+ return { providerId: "vercel", modelId: route.fxModel };
764
+ }
674
765
  function cursorCatalogRef(model) {
675
766
  const id = model.trim().toLowerCase();
676
767
  if (/^(gpt-|o\d)/.test(id))
@@ -713,6 +804,9 @@ function applyHarnessOverrides(harness, modelId, facts, levels) {
713
804
  } else if (harness !== "codex" && harness !== "cursor" && harness !== "opencode" && harness !== "pi") {
714
805
  result = result.filter((l) => l !== "max");
715
806
  }
807
+ if (harness === "fx") {
808
+ result = result.filter((l) => l !== "off");
809
+ }
716
810
  if (harness === "codex") {
717
811
  const isCodexMax = /-codex-max$/.test(modelId);
718
812
  const isCodexNonMax = /-codex$/.test(modelId) && !isCodexMax;
@@ -738,6 +832,7 @@ function claudeCatalogModelId(modelId, models) {
738
832
  }
739
833
  var REASONING_EFFORT_LEVELS, REASONING_HARNESSES, FALLBACK_LEVELS, EFFORT_VALUE_MAP;
740
834
  var init_reasoning = __esm(() => {
835
+ init_chatgpt_subscription();
741
836
  init_harness_models();
742
837
  REASONING_EFFORT_LEVELS = ["off", "low", "medium", "high", "xhigh", "max"];
743
838
  REASONING_HARNESSES = [
@@ -748,7 +843,8 @@ var init_reasoning = __esm(() => {
748
843
  "dsh",
749
844
  "cursor",
750
845
  "amp",
751
- "grok"
846
+ "grok",
847
+ "fx"
752
848
  ];
753
849
  FALLBACK_LEVELS = ["low", "medium", "high"];
754
850
  EFFORT_VALUE_MAP = {
@@ -763,6 +859,7 @@ var init_reasoning = __esm(() => {
763
859
 
764
860
  // packages/model-catalog/src/index.ts
765
861
  var init_src2 = __esm(() => {
862
+ init_chatgpt_subscription();
766
863
  init_display();
767
864
  init_harness_models();
768
865
  init_merge();
@@ -773,4 +870,4 @@ var init_src2 = __esm(() => {
773
870
  init_resolve_alias();
774
871
  });
775
872
 
776
- export { isAlias, parseAlias, resolveAlias, harnessCatalogSection, isHarnessModelJudged, normalizeGrokModel, harnessModelIds, modelFamilyKey, buildClaudeShortnameMap, harnessModelMismatch, openAICompatibleProviders, openAICompatibleProviderIds, providerKeyVars, openAICompatibleKeyVars, baseUrlEnvVar, openAICompatibleBaseUrlVars, baseUrlOverride, ignoredBaseUrlVar, providerBaseUrl, openAICompatibleProvider, providerForModel, providerForKeyVar, providerKeyFromEnv, providerHarnessModels, withAgentChatRegistrySections, registryCatalogSections, withRegistryCatalogSections, dshCatalogRef, grokCatalogRef, cursorCatalogRef, reasoningLevelsFor, claudeCatalogModelId, init_src2 };
873
+ export { CHATGPT_SUBSCRIPTION_PROVIDER, chatgptSubscriptionModelId, isChatgptSubscriptionModel, isAlias, parseAlias, resolveAlias, harnessCatalogSection, isHarnessModelJudged, fxModelRoute, normalizeGrokModel, harnessModelIds, modelFamilyKey, buildClaudeShortnameMap, harnessModelMismatch, openAICompatibleProviders, openAICompatibleProviderIds, providerKeyVars, openAICompatibleKeyVars, baseUrlEnvVar, openAICompatibleBaseUrlVars, baseUrlOverride, ignoredBaseUrlVar, providerBaseUrl, openAICompatibleProvider, providerForModel, providerForKeyVar, providerKeyFromEnv, providerHarnessModels, withAgentChatRegistrySections, registryCatalogSections, withRegistryCatalogSections, dshCatalogRef, grokCatalogRef, fxCatalogRef, cursorCatalogRef, reasoningLevelsFor, claudeCatalogModelId, init_src2 };
@@ -2,7 +2,7 @@ import {
2
2
  isGrokOpenRouterModel,
3
3
  grokTargetProfile,
4
4
  ACPAdapter2
5
- } from "./cli-avgcz4ra.js";
5
+ } from "./cli-rm6hqj3z.js";
6
6
  import {
7
7
  getOpenRouterBaseUrl,
8
8
  getOpenRouterAttributionHeaders,
@@ -11,11 +11,11 @@ import {
11
11
  import {
12
12
  registerVolatileSecret,
13
13
  init_secret_scrubber
14
- } from "./cli-a4btqqft.js";
14
+ } from "./cli-1b7btd38.js";
15
15
  import {
16
16
  normalizeGrokModel,
17
17
  init_src2
18
- } from "./cli-4r12t6w6.js";
18
+ } from "./cli-5c4hjzne.js";
19
19
 
20
20
  // src/providers/grok-adapter.ts
21
21
  init_src2();
@@ -7,21 +7,21 @@ import {
7
7
  tierConfigKey,
8
8
  init_model_tier_keys,
9
9
  init_db4
10
- } from "./cli-1s1dqn1j.js";
10
+ } from "./cli-1ayk1eas.js";
11
11
  import {
12
12
  ensureRbacSeedsSynced2,
13
13
  init_rbac_roles
14
- } from "./cli-bq2pcphn.js";
14
+ } from "./cli-8hs41zy2.js";
15
15
  import {
16
16
  seedPricingFromModelsDev,
17
17
  init_seed_pricing
18
- } from "./cli-mc97xy2s.js";
18
+ } from "./cli-xtjhfmpc.js";
19
19
  import {
20
20
  MODEL_TIERS,
21
21
  DEFAULT_MODEL_TIER_MAP,
22
22
  ProviderNameSchema,
23
23
  init_types4
24
- } from "./cli-41z8xwj0.js";
24
+ } from "./cli-7wspm5gm.js";
25
25
  import {
26
26
  __esm
27
27
  } from "./cli-242037k3.js";
@@ -2,11 +2,12 @@ import {
2
2
  runtimeCatalogSection,
3
3
  runtimeCatalogModel,
4
4
  init_runtime_model_catalog
5
- } from "./cli-a2jw6ee5.js";
5
+ } from "./cli-1p89xny0.js";
6
6
  import {
7
+ chatgptSubscriptionModelId,
7
8
  buildClaudeShortnameMap,
8
9
  init_src2
9
- } from "./cli-4r12t6w6.js";
10
+ } from "./cli-5c4hjzne.js";
10
11
  import {
11
12
  __esm
12
13
  } from "./cli-242037k3.js";
@@ -32,6 +33,9 @@ function getContextWindowSize(model) {
32
33
  function getKnownContextWindowSize(model) {
33
34
  if (!model)
34
35
  return;
36
+ const subscriptionId = chatgptSubscriptionModelId(model);
37
+ if (subscriptionId)
38
+ return catalogContext("openai", subscriptionId);
35
39
  const slash = model.indexOf("/");
36
40
  if (slash > 0) {
37
41
  const scoped = catalogContext(model.slice(0, slash), model.slice(slash + 1));
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  scrubSecrets,
7
7
  init_secret_scrubber
8
- } from "./cli-a4btqqft.js";
8
+ } from "./cli-1b7btd38.js";
9
9
  import {
10
10
  __esm
11
11
  } from "./cli-242037k3.js";
@@ -116,13 +116,13 @@ async function refreshAccessToken(refreshToken) {
116
116
  })
117
117
  });
118
118
  if (!response.ok) {
119
- const text = await response.text().catch(() => "");
119
+ const text = redactTokens(await response.text().catch(() => ""), [refreshToken]);
120
120
  console.error("[codex-oauth] Token refresh failed:", response.status, text);
121
121
  return { type: "failed", status: response.status, error: text.slice(0, 300) };
122
122
  }
123
123
  const json = await response.json();
124
124
  if (!json.access_token || !json.refresh_token || typeof json.expires_in !== "number") {
125
- console.error("[codex-oauth] Token refresh response missing fields:", json);
125
+ console.error("[codex-oauth] Token refresh response missing fields; got keys:", Object.keys(json).join(", "));
126
126
  return { type: "failed" };
127
127
  }
128
128
  return {
@@ -132,10 +132,22 @@ async function refreshAccessToken(refreshToken) {
132
132
  expires: Date.now() + json.expires_in * 1000
133
133
  };
134
134
  } catch (error) {
135
- console.error("[codex-oauth] Token refresh error:", error);
135
+ const message = error instanceof Error ? error.message : String(error);
136
+ console.error("[codex-oauth] Token refresh error:", redactTokens(message, [refreshToken]));
136
137
  return { type: "failed" };
137
138
  }
138
139
  }
140
+ function redactTokens(text, tokens) {
141
+ let out = text;
142
+ for (const token of tokens) {
143
+ if (!token)
144
+ continue;
145
+ const forms = new Set([token, encodeURIComponent(token), JSON.stringify(token).slice(1, -1)]);
146
+ for (const form of forms)
147
+ out = out.split(form).join("[REDACTED:codex_oauth_token]");
148
+ }
149
+ return scrubSecrets(out);
150
+ }
139
151
  function getAccountId(accessToken) {
140
152
  const payload = decodeJwt(accessToken);
141
153
  const auth = payload?.[JWT_CLAIM_PATH];
@@ -384,6 +396,16 @@ function isStaleByAge(expires, maxAgeMs) {
384
396
  const issuedAt = expires - ACCESS_TOKEN_TTL_MS;
385
397
  return Date.now() - issuedAt > maxAgeMs;
386
398
  }
399
+ function buildPoolRevalidationFailureReason(err, slot) {
400
+ if (err instanceof CodexOAuthRefreshError) {
401
+ if (err.reason === "lock_timeout") {
402
+ return `[auth-error] Codex pool slot ${slot} [...${err.keySuffix}] revalidation failed: timed out waiting for the refresh lock — transient, will retry on next task.`;
403
+ }
404
+ return `[auth-error] Codex pool slot ${slot} [...${err.keySuffix}] revalidation failed: refresh rejected (${err.status ?? "unknown status"} ${scrubSecrets(err.body ?? "")}) — credential likely revoked; re-run codex-login for this slot.`;
405
+ }
406
+ const message = scrubSecrets(err instanceof Error ? err.message : String(err));
407
+ return `[auth-error] Codex pool slot ${slot} revalidation failed (not a confirmed auth rejection, transient): ${message}`;
408
+ }
387
409
  async function acquireCodexRefreshLock(apiUrl, apiKey, slot) {
388
410
  const key = codexOAuthKeyForSlot(slot);
389
411
  const res = await fetch(`${apiUrl}/api/oauth/refresh-locks/${encodeURIComponent(key)}`, {
@@ -465,22 +487,29 @@ async function loadAllCodexOAuthSlots(apiUrl, apiKey, options = {}) {
465
487
  }
466
488
  async function storeCodexOAuth(apiUrl, apiKey, creds, slot = 0) {
467
489
  const key = codexOAuthKeyForSlot(slot);
468
- const res = await fetch(`${apiUrl}/api/config`, {
469
- method: "PUT",
470
- headers: {
471
- "Content-Type": "application/json",
472
- Authorization: `Bearer ${apiKey}`
473
- },
474
- body: JSON.stringify({
475
- scope: "global",
476
- key,
477
- value: JSON.stringify(creds),
478
- isSecret: true,
479
- description: `Codex ChatGPT OAuth credentials slot ${slot} (stored by codex-login)`
480
- })
481
- });
490
+ const redact = (text) => redactTokens(text, [creds.access, creds.refresh]);
491
+ let res;
492
+ try {
493
+ res = await fetch(`${apiUrl}/api/config`, {
494
+ method: "PUT",
495
+ headers: {
496
+ "Content-Type": "application/json",
497
+ Authorization: `Bearer ${apiKey}`
498
+ },
499
+ body: JSON.stringify({
500
+ scope: "global",
501
+ key,
502
+ value: JSON.stringify(creds),
503
+ isSecret: true,
504
+ description: `Codex ChatGPT OAuth credentials slot ${slot} (stored by codex-login)`
505
+ })
506
+ });
507
+ } catch (error) {
508
+ const message = error instanceof Error ? error.message : String(error);
509
+ throw new Error(`Failed to store ${key} config: ${redact(message)}`);
510
+ }
482
511
  if (!res.ok) {
483
- const text = await res.text().catch(() => "");
512
+ const text = redact(await res.text().catch(() => ""));
484
513
  throw new Error(`Failed to store ${key} config: HTTP ${res.status} ${text}`);
485
514
  }
486
515
  }
@@ -531,7 +560,8 @@ async function persistCodexOAuth(apiUrl, apiKey, creds, slot = 0) {
531
560
  try {
532
561
  await storeCodexOAuth(apiUrl, apiKey, creds, slot);
533
562
  } catch (err) {
534
- console.error("[codex-oauth] persistCodexOAuth failed (non-fatal):", err);
563
+ const message = err instanceof Error ? err.message : String(err);
564
+ console.error("[codex-oauth] persistCodexOAuth failed (non-fatal):", redactTokens(message, [creds.access, creds.refresh]));
535
565
  }
536
566
  }
537
567
  async function getValidCodexOAuth(apiUrl, apiKey, slot = 0, opts) {
@@ -591,6 +621,7 @@ async function getValidCodexOAuth(apiUrl, apiKey, slot = 0, opts) {
591
621
  }
592
622
  var CODEX_OAUTH_KEY_LEGACY = "codex_oauth", MAX_CODEX_OAUTH_SLOT = 100, REFRESH_LOCK_TTL_MS, REFRESH_LOCK_WAIT_MS, REFRESH_LOCK_POLL_MS = 250, REFRESH_SKEW_MS, ACCESS_TOKEN_TTL_MS, CodexOAuthRefreshError;
593
623
  var init_storage = __esm(() => {
624
+ init_secret_scrubber();
594
625
  init_auth_json();
595
626
  init_flow();
596
627
  REFRESH_LOCK_TTL_MS = 2 * 60 * 1000;
@@ -615,4 +646,4 @@ var init_storage = __esm(() => {
615
646
  };
616
647
  });
617
648
 
618
- export { _fetchHolder, CLIENT_ID, decodeJwt, exchangeAuthorizationCode2, getAccountId, extractChatgptPlanType, extractChatgptUserId, loginCodexOAuth, init_flow, deriveCodexKeySuffix, authJsonToCredentialSelection, credentialsToAuthJson, init_auth_json, MAX_CODEX_OAUTH_SLOT, CodexOAuthRefreshError, codexOAuthKeyForSlot, loadAllCodexOAuthSlots, storeCodexOAuth, persistCodexOAuth, getValidCodexOAuth, init_storage };
649
+ export { _fetchHolder, CLIENT_ID, decodeJwt, exchangeAuthorizationCode2, getAccountId, extractChatgptPlanType, extractChatgptUserId, loginCodexOAuth, init_flow, deriveCodexKeySuffix, authJsonToCredentialSelection, credentialsToAuthJson, init_auth_json, MAX_CODEX_OAUTH_SLOT, buildPoolRevalidationFailureReason, codexOAuthKeyForSlot, loadAllCodexOAuthSlots, storeCodexOAuth, persistCodexOAuth, getValidCodexOAuth, init_storage };