@desplega.ai/agent-swarm 2.7.4 → 2.7.6

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 (326) hide show
  1. package/README.md +1 -1
  2. package/dist/acp-adapter-bp91d37f.js +15 -0
  3. package/dist/{actions-gfrr9vb7.js → actions-yj0eeaqh.js} +19 -18
  4. package/dist/{amp-adapter-0s58gm46.js → amp-adapter-4pg9h34q.js} +3 -3
  5. package/dist/{app-stvq692g.js → app-909e97cr.js} +3 -3
  6. package/dist/{assistant-5s37fr9n.js → assistant-qdyb5fyy.js} +32 -23
  7. package/dist/{boot-reembed-yzy1841n.js → boot-reembed-fk0s9z18.js} +1 -1
  8. package/dist/{boot-reembed-cv82gz7y.js → boot-reembed-gs1rzrnh.js} +1 -1
  9. package/dist/{boot-scrub-sweep-8k4q95ap.js → boot-scrub-sweep-4qfd4kfx.js} +4 -4
  10. package/dist/{boot-seeds-ftt9htah.js → boot-seeds-yr00k13d.js} +4 -4
  11. package/dist/{boxd-515v1t8z.js → boxd-vdmfssd9.js} +5 -5
  12. package/dist/{claude-adapter-t00wrzeh.js → claude-adapter-qta1f1xn.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-sc6j4dm0.js} +3 -3
  15. package/dist/{claude-sdk-session-vj0c2azx.js → claude-sdk-session-zgrz6yvc.js} +9175 -9076
  16. package/dist/{cli-gjr2y2xk.js → cli-0agcv1v5.js} +4 -1
  17. package/dist/{cli-edmm9d9y.js → cli-0at8w34w.js} +7 -7
  18. package/dist/{cli-a81qevyg.js → cli-0qatpy8q.js} +20 -36
  19. package/dist/{cli-bcz074zx.js → cli-0yv5z2pg.js} +1 -1
  20. package/dist/{cli-a4btqqft.js → cli-1b7btd38.js} +1 -1
  21. package/dist/{cli-a2jw6ee5.js → cli-1p89xny0.js} +1 -1
  22. package/dist/{cli-v726afdm.js → cli-2pnswgh8.js} +1 -1
  23. package/dist/{cli-jkt52mgt.js → cli-386tyxxg.js} +2 -2
  24. package/dist/{cli-az0bpf8p.js → cli-3ypk9vk1.js} +3 -3
  25. package/dist/{cli-wk9md5px.js → cli-436532ck.js} +4 -4
  26. package/dist/{cli-7n5sbw0z.js → cli-4necwtsv.js} +5 -5
  27. package/dist/cli-54t00gt8.js +151 -0
  28. package/dist/{cli-655xm9ms.js → cli-583frbyr.js} +1 -1
  29. package/dist/{cli-4r12t6w6.js → cli-5c4hjzne.js} +101 -4
  30. package/dist/{cli-hf6zt5m6.js → cli-69szn7w7.js} +17 -1
  31. package/dist/{cli-rtk9g7av.js → cli-73jzwksr.js} +6 -2
  32. package/dist/{cli-jg0nfda6.js → cli-75gkpjvw.js} +52 -21
  33. package/dist/{cli-wcmnan2g.js → cli-89knwags.js} +5 -5
  34. package/dist/{cli-pwyevs29.js → cli-8bc1w0tw.js} +22 -21
  35. package/dist/{cli-t282jgab.js → cli-8snvgs5r.js} +41 -16
  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-ycm6180s.js → cli-a7v854rf.js} +5 -3
  39. package/dist/{cli-98pke4vk.js → cli-ae7mrdf9.js} +2 -2
  40. package/dist/{cli-je8yeyc5.js → cli-bjb3z51z.js} +5 -5
  41. package/dist/{cli-mc97xy2s.js → cli-c60vetmm.js} +16 -4
  42. package/dist/{cli-j4kw3rsx.js → cli-cm5yqn35.js} +18 -0
  43. package/dist/{cli-wndv9p7g.js → cli-decfb6v8.js} +6 -6
  44. package/dist/{cli-h55y2bjc.js → cli-dhar9qay.js} +2 -2
  45. package/dist/{cli-8yy525ad.js → cli-drr5v6av.js} +2 -2
  46. package/dist/{cli-5gr1g711.js → cli-dxae2yg7.js} +2 -2
  47. package/dist/{cli-pe09p6dv.js → cli-e3r2neck.js} +8 -7
  48. package/dist/{cli-13jvmew3.js → cli-ekwks2vs.js} +7 -7
  49. package/dist/{cli-jg4p5t36.js → cli-es6va8jk.js} +121 -51
  50. package/dist/{cli-j4kt1mpb.js → cli-faxe6thg.js} +3 -3
  51. package/dist/{cli-tzrpv5sc.js → cli-ftyxyspd.js} +1 -1
  52. package/dist/cli-fw2w0kva.js +47 -0
  53. package/dist/{cli-2dfbv8qr.js → cli-fy6x31ps.js} +1 -0
  54. package/dist/{cli-aq58fk5m.js → cli-g83s9ewh.js} +7 -1
  55. package/dist/cli-gdhpcbhf.js +55 -0
  56. package/dist/{cli-82jg7fp9.js → cli-he5nxaa8.js} +1 -1
  57. package/dist/{cli-8veytvbh.js → cli-he9wchme.js} +1 -1
  58. package/dist/{cli-k76tgq03.js → cli-hgaazk69.js} +2 -2
  59. package/dist/{cli-d2pzqej1.js → cli-hr2e2fft.js} +741 -7
  60. package/dist/{cli-dae4sbgy.js → cli-jm2vfpfd.js} +2 -2
  61. package/dist/{cli-1s1dqn1j.js → cli-k2gzwsj2.js} +297 -140
  62. package/dist/{cli-b1afgtj3.js → cli-kqdg1bsb.js} +3 -3
  63. package/dist/cli-m2z8jagn.js +12078 -0
  64. package/dist/{cli-mvckssyq.js → cli-m48g6p95.js} +5 -5
  65. package/dist/{cli-bwty35gx.js → cli-mthwvjre.js} +1 -1
  66. package/dist/{cli-41z8xwj0.js → cli-nhrvpaj7.js} +34 -8
  67. package/dist/{cli-ahd90bwt.js → cli-nwj0ee2w.js} +6 -6
  68. package/dist/{cli-kvtc7aez.js → cli-p5gp8pcx.js} +44 -14
  69. package/dist/{cli-avgcz4ra.js → cli-pd7vagab.js} +436 -171
  70. package/dist/{cli-zn15c46z.js → cli-q0k1w5zd.js} +1 -1
  71. package/dist/{cli-bq2pcphn.js → cli-rmmmrjkd.js} +1 -1
  72. package/dist/{cli-2qpvmmkw.js → cli-s0qnd4wv.js} +1 -1
  73. package/dist/{cli-kg8hchyg.js → cli-sa02jsqt.js} +1 -1
  74. package/dist/{cli-1yekbyqm.js → cli-shpbx5ee.js} +283 -82
  75. package/dist/{cli-9y354g3j.js → cli-srye3vdt.js} +1 -1
  76. package/dist/{cli-byqfbnjw.js → cli-svj5090z.js} +9 -9
  77. package/dist/{cli-gcbdjt47.js → cli-vfym7wmz.js} +6 -6
  78. package/dist/{cli-v1yw3wha.js → cli-vvpx3gsx.js} +4 -4
  79. package/dist/{cli-a1fhj4n9.js → cli-w6dt9ged.js} +2 -2
  80. package/dist/{cli-1gm8jcyr.js → cli-waqbxg08.js} +5232 -68
  81. package/dist/{cli-5hjced2v.js → cli-wp9sp1qb.js} +6 -6
  82. package/dist/{cli-eny54typ.js → cli-wx3rhnm0.js} +1 -1
  83. package/dist/{cli-s0exq74r.js → cli-xbbndvjy.js} +3 -3
  84. package/dist/{cli-f255yaqn.js → cli-xds5f77d.js} +3 -3
  85. package/dist/{cli-0sbkss7h.js → cli-xnqgpshy.js} +2 -2
  86. package/dist/{cli-0fgr1w9b.js → cli-xnrwazav.js} +20 -3
  87. package/dist/{cli-gf5hbmdr.js → cli-yjdgea32.js} +3 -3
  88. package/dist/{cli-cq1pf336.js → cli-yn4kxs06.js} +124 -11
  89. package/dist/{cli-224epwwf.js → cli-yx4kfngt.js} +3 -3
  90. package/dist/{cli-eqx6k993.js → cli-yy3rhsdw.js} +47 -13
  91. package/dist/{cli-36g23z21.js → cli-zbbwez0r.js} +4 -4
  92. package/dist/{cli-ktmvb20s.js → cli-zm72anhg.js} +12 -12
  93. package/dist/cli.js +26 -25
  94. package/dist/{codex-adapter-g0gctw29.js → codex-adapter-ayd1fb6h.js} +5 -5
  95. package/dist/{codex-hook-vrzz2xhr.js → codex-hook-9efm2x1m.js} +1 -1
  96. package/dist/{codex-login-0gg46ygn.js → codex-login-y0pmff1c.js} +1 -1
  97. package/dist/{codex-session-runner-dr2cxe1c.js → codex-session-runner-jesa32xc.js} +6 -6
  98. package/dist/{commands-1p07cvff.js → commands-hanewgf2.js} +9 -3
  99. package/dist/{controller-z0s7sv6r.js → controller-dt1n3c1q.js} +9 -4
  100. package/dist/{controllers-connect-x9kvvhyk.js → controllers-connect-xx8x64n5.js} +22 -21
  101. package/dist/{cursor-adapter-m5b98pvk.js → cursor-adapter-9s4dwwdw.js} +2 -2
  102. package/dist/{db-capk2raj.js → db-3vttcbv4.js} +3 -3
  103. package/dist/{db-rsh04kh3.js → db-9dv0g1ab.js} +12 -4
  104. package/dist/{devin-adapter-yxm87fe9.js → devin-adapter-r9phbnc9.js} +1 -1
  105. package/dist/{devtools-82fzqra8.js → devtools-qxfgbsqz.js} +1 -1
  106. package/dist/{dispatcher-304q6fwa.js → dispatcher-tx9hd1sv.js} +18 -17
  107. package/dist/{docker-7rxt0rry.js → docker-c1a3gqmf.js} +91 -24
  108. package/dist/{dsh-adapter-btewem0y.js → dsh-adapter-007y4ejs.js} +2 -2
  109. package/dist/{e2b-renc0k8q.js → e2b-a19d28rz.js} +4 -4
  110. package/dist/{e2b-7fc9b9bd.js → e2b-we6hs6q5.js} +6 -6
  111. package/dist/{easter-egg-3d-fm1p3n4d.js → easter-egg-3d-rgbrqb8s.js} +1 -1
  112. package/dist/{embedding-space-s68v49ct.js → embedding-space-ny1e2940.js} +6 -6
  113. package/dist/{embeddings-4ms3604w.js → embeddings-2t386t13.js} +1 -1
  114. package/dist/{event-bus-dfjx2qdh.js → event-bus-g0ka3pbw.js} +1 -1
  115. package/dist/{execute-mcdgccjs.js → execute-pksh0ceh.js} +1 -1
  116. package/dist/{external-channel-9dxwfztn.js → external-channel-phgmhmd7.js} +2 -2
  117. package/dist/fx-adapter-fy8rr921.js +18 -0
  118. package/dist/{google-generative-ai-yvmdxyxa.js → google-generative-ai-8y3m3k4b.js} +1 -1
  119. package/dist/{google-vertex-jrtdh9gs.js → google-vertex-w3v98n7b.js} +1 -1
  120. package/dist/{grok-adapter-05ecv4h0.js → grok-adapter-q0abvpaj.js} +8 -8
  121. package/dist/handlers-by3sfxyx.js +32 -0
  122. package/dist/{heartbeat-3n94heh3.js → heartbeat-kadyek8p.js} +21 -20
  123. package/dist/{hook-aadrn69x.js → hook-5zs3msf6.js} +6 -6
  124. package/dist/{hook-zxwje86c.js → hook-9k551xnj.js} +4 -4
  125. package/dist/{http-xzxk9mst.js → http-mhz9vw1f.js} +272 -103
  126. package/dist/index-4f2pvxae.js +37 -0
  127. package/dist/index-98gz7tmp.js +30 -0
  128. package/dist/{index-5rk6rfzr.js → index-fvzke5kx.js} +1 -1
  129. package/dist/index-k08z2cak.js +33 -0
  130. package/dist/{index-yqhz88yy.js → index-pxn30mse.js} +8 -8
  131. package/dist/{index-d34f6r87.js → index-q361cg2f.js} +1 -1
  132. package/dist/{index-9j4zwcht.js → index-rvr00sg7.js} +168 -675
  133. package/dist/{index-qeb82z37.js → index-vdygbq10.js} +1 -1
  134. package/dist/{keepalive-w4aakbyk.js → keepalive-w56f32cg.js} +4 -4
  135. package/dist/lead-enq35nqp.js +70 -0
  136. package/dist/{maintenance-hbptpk6p.js → maintenance-7mdgxcea.js} +1 -1
  137. package/dist/{oauth-refresh-sweep-217semrv.js → oauth-refresh-sweep-29txy9vk.js} +3 -3
  138. package/dist/{onboard-vz2s5df3.js → onboard-kpsrkarj.js} +5 -5
  139. package/dist/{opencode-adapter-gtfd7d7v.js → opencode-adapter-j25vm3rr.js} +5 -5
  140. package/dist/{otel-impl-aefave37.js → otel-impl-6kkct7a8.js} +2 -2
  141. package/dist/{pi-mono-adapter-f8h5yseh.js → pi-mono-adapter-exhkzhn2.js} +117 -23
  142. package/dist/{pricing-refresh-m1yhh9ya.js → pricing-refresh-n2x7jh6k.js} +3 -3
  143. package/dist/{rbac-roles-rrw8twdz.js → rbac-roles-81ypx6es.js} +1 -1
  144. package/dist/{rbac-roles-svj72cdf.js → rbac-roles-b5htkjby.js} +2 -2
  145. package/dist/{render-v2-amwbnfxh.js → render-v2-qn6jmpk4.js} +3 -3
  146. package/dist/{resume-9cd6wf6z.js → resume-wd30wx23.js} +7 -7
  147. package/dist/{runtime-fp4vrx7m.js → runtime-4hsg7h60.js} +1 -1
  148. package/dist/{session-access-21t6yjyg.js → session-access-5qvfevhk.js} +4 -4
  149. package/dist/{session-source-backfill-pxbzcsc6.js → session-source-backfill-n1czavbr.js} +3 -3
  150. package/dist/{setup-4592tqz4.js → setup-dnb56qy5.js} +3 -3
  151. package/dist/{virtual-modules-gzfnpmnz.js → virtual-modules-76xxv9fs.js} +2 -2
  152. package/dist/{work-objects-t9tcf174.js → work-objects-4n21tfkm.js} +21 -20
  153. package/dist/{worker-follow-up-q32jh4yk.js → worker-follow-up-77hvzxww.js} +18 -17
  154. package/dist/worker-gg1576j3.js +70 -0
  155. package/dist/{x-b6wxntdt.js → x-vmmye1kb.js} +2 -2
  156. package/openapi.json +189 -32
  157. package/package.json +8 -7
  158. package/src/be/db/script-runs.ts +23 -0
  159. package/src/be/db/session-summaries.ts +8 -2
  160. package/src/be/db/session-tree.ts +174 -61
  161. package/src/be/db/session-visibility.ts +5 -4
  162. package/src/be/db/tasks/read.ts +122 -3
  163. package/src/be/db-client.ts +8 -5
  164. package/src/be/db.ts +23 -8
  165. package/src/be/memory/providers/sqlite-store.ts +49 -12
  166. package/src/be/migrations/259_session_summaries_open_tasks.sql +111 -0
  167. package/src/be/migrations/260_runtime_pool_cache.sql +20 -0
  168. package/src/be/migrations/262_session_visibility_indexes.sql +18 -0
  169. package/src/be/migrations/263_task_list_filter_index.sql +11 -0
  170. package/src/be/migrations/264_slack_thread_cover_index.sql +9 -0
  171. package/src/be/migrations/266_script_runs_source_task.sql +11 -0
  172. package/src/be/model-validation.ts +5 -1
  173. package/src/be/pricing-normalize.ts +7 -2
  174. package/src/be/runtime-pools/cache-cleanup.ts +109 -0
  175. package/src/be/runtime-pools/db.ts +65 -6
  176. package/src/be/runtime-pools/remote-controller.ts +5 -0
  177. package/src/be/runtime-pools/supervisor.ts +33 -2
  178. package/src/be/scripts/typecheck.ts +23 -0
  179. package/src/be/seed/schedules-seeder.ts +135 -9
  180. package/src/be/seed/workflows-seeder.ts +65 -1
  181. package/src/be/seed-pricing.ts +23 -0
  182. package/src/be/seed-scripts/catalog/task-failure-audit.ts +5 -1
  183. package/src/be/steering.ts +50 -3
  184. package/src/be/swarm-config-guard.ts +1 -0
  185. package/src/commands/controller.ts +4 -0
  186. package/src/commands/entrypoint-api-readiness.ts +74 -0
  187. package/src/commands/provider-credentials.ts +29 -2
  188. package/src/commands/runner.ts +86 -5
  189. package/src/extensions/contract-types.generated.ts +1 -1
  190. package/src/extensions/contract.ts +27 -1
  191. package/src/extensions/dispatcher.ts +4 -0
  192. package/src/http/agents.ts +1 -0
  193. package/src/http/index.ts +1 -1
  194. package/src/http/list-total-cache.ts +14 -7
  195. package/src/http/mcp-bridge.ts +4 -0
  196. package/src/http/memory.ts +38 -9
  197. package/src/http/script-runs.ts +174 -5
  198. package/src/http/status.ts +10 -2
  199. package/src/http/tasks.ts +4 -2
  200. package/src/integrations/chat-sdk/inbound.ts +15 -5
  201. package/src/integrations/chat-sdk/steering.ts +3 -1
  202. package/src/kv-reserved-namespaces.ts +2 -0
  203. package/src/prompts/base-prompt.ts +4 -1
  204. package/src/prompts/session-templates.ts +26 -0
  205. package/src/providers/acp-adapter.ts +190 -26
  206. package/src/providers/acp-targets.ts +306 -6
  207. package/src/providers/amp-adapter.ts +1 -1
  208. package/src/providers/codex-adapter.ts +9 -44
  209. package/src/providers/codex-oauth/flow.ts +24 -3
  210. package/src/providers/codex-oauth/storage.ts +56 -17
  211. package/src/providers/codex-oauth/subscription.ts +67 -0
  212. package/src/providers/fx-adapter.ts +211 -0
  213. package/src/providers/index.ts +5 -1
  214. package/src/providers/mcp-loopback-proxy.ts +94 -0
  215. package/src/providers/pi-mono-adapter.ts +98 -13
  216. package/src/providers/pricing-sources.md +8 -0
  217. package/src/providers/reasoning-effort.ts +17 -1
  218. package/src/providers/types.ts +2 -1
  219. package/src/runtime-providers/controller-protocol.ts +14 -1
  220. package/src/runtime-providers/controller.ts +5 -0
  221. package/src/runtime-providers/docker.ts +108 -23
  222. package/src/runtime-providers/types.ts +16 -0
  223. package/src/scheduler/scheduler.ts +36 -3
  224. package/src/script-workflows/workflow-ctx.ts +8 -0
  225. package/src/scripts-runtime/sdk-allowlist.ts +1 -0
  226. package/src/scripts-runtime/types/stdlib.d.ts +27 -0
  227. package/src/scripts-runtime/types/swarm-extension.d.ts +33 -0
  228. package/src/scripts-runtime/types/swarm-sdk.d.ts +27 -0
  229. package/src/server-user.ts +1 -0
  230. package/src/server.ts +7 -0
  231. package/src/slack/assistant.ts +17 -1
  232. package/src/slack/commands.ts +5 -1
  233. package/src/slack/handlers.ts +53 -5
  234. package/src/slack/left-threads.ts +88 -0
  235. package/src/slack/steering.ts +3 -0
  236. package/src/slack/thread-buffer.ts +40 -16
  237. package/src/tasks/follow-up-redelegation-guard.ts +155 -0
  238. package/src/tests/acp-adapter.test.ts +79 -0
  239. package/src/tests/base-prompt.test.ts +12 -0
  240. package/src/tests/chat-sdk-inbound.test.ts +30 -0
  241. package/src/tests/chatgpt-subscription-model-groups.test.ts +62 -0
  242. package/src/tests/chatgpt-subscription-pi.test.ts +170 -0
  243. package/src/tests/chatgpt-subscription-session-bench.test.ts +198 -0
  244. package/src/tests/claude-artifacts-read-script.test.ts +209 -0
  245. package/src/tests/codex-oauth-credential-info.test.ts +40 -0
  246. package/src/tests/codex-oauth-refresh-egress.test.ts +194 -0
  247. package/src/tests/context-window.test.ts +7 -0
  248. package/src/tests/db-client.test.ts +21 -0
  249. package/src/tests/db-task-read-contract.test.ts +8 -2
  250. package/src/tests/db-task-write-contract.test.ts +5 -1
  251. package/src/tests/entrypoint-api-readiness.test.ts +416 -210
  252. package/src/tests/explicit-model-validation.test.ts +113 -8
  253. package/src/tests/extensions-run-context.test.ts +11 -0
  254. package/src/tests/extensions-steering.test.ts +353 -0
  255. package/src/tests/extensions-validate.test.ts +5 -0
  256. package/src/tests/fixtures/extensions/steering-policy/hooks.ts +39 -0
  257. package/src/tests/fixtures/extensions/steering-policy/manifest.json +7 -0
  258. package/src/tests/fixtures/fake-fx.ts +167 -0
  259. package/src/tests/fixtures/fx/acp-responses-recorded.json +157 -0
  260. package/src/tests/fixtures/fx/acp-updates-recorded.jsonl +15 -0
  261. package/src/tests/follow-up-redelivery-guard.test.ts +432 -202
  262. package/src/tests/fx-adapter.test.ts +771 -0
  263. package/src/tests/grok-adapter.test.ts +36 -0
  264. package/src/tests/list-total-cache.test.ts +27 -2
  265. package/src/tests/mcp-loopback-proxy.test.ts +193 -0
  266. package/src/tests/memory-fts-populate.test.ts +11 -9
  267. package/src/tests/memory-retrieval-purge.test.ts +80 -0
  268. package/src/tests/migration-260-runtime-pool-cache.test.ts +118 -0
  269. package/src/tests/model-tier-resolution.test.ts +3 -3
  270. package/src/tests/pricing-refresh.test.ts +5 -5
  271. package/src/tests/prompt-template-session.test.ts +5 -3
  272. package/src/tests/provider-registration.test.ts +2 -1
  273. package/src/tests/query-audit-plans.test.ts +30 -2
  274. package/src/tests/runtime-cache-cleanup.test.ts +367 -0
  275. package/src/tests/runtime-e2b-pools.test.ts +41 -0
  276. package/src/tests/runtime-pools-db.test.ts +98 -0
  277. package/src/tests/runtime-pools-http.test.ts +29 -0
  278. package/src/tests/runtime-providers-docker.test.ts +253 -0
  279. package/src/tests/runtime-remote-controller.test.ts +66 -2
  280. package/src/tests/runtime-supervisor.test.ts +66 -2
  281. package/src/tests/script-connections.test.ts +13 -0
  282. package/src/tests/script-runs-http.test.ts +684 -2
  283. package/src/tests/seed-model-profiles.test.ts +2 -2
  284. package/src/tests/seed-schedules.test.ts +138 -0
  285. package/src/tests/seed-scripts.test.ts +26 -0
  286. package/src/tests/session-cost-recompute-unit.test.ts +39 -0
  287. package/src/tests/session-costs-golden.test.ts +26 -0
  288. package/src/tests/session-summaries-plans.test.ts +120 -0
  289. package/src/tests/session-summaries.test.ts +72 -12
  290. package/src/tests/sessions-tree.test.ts +11 -3
  291. package/src/tests/slack-leave-thread.test.ts +571 -0
  292. package/src/tests/slack-render-v2-query-plans.test.ts +24 -2
  293. package/src/tests/status.test.ts +11 -0
  294. package/src/tests/tasks-readable-row.test.ts +155 -0
  295. package/src/tests/tool-annotations.test.ts +2 -1
  296. package/src/tests/workflow-engine-v2.test.ts +42 -0
  297. package/src/tests/workflow-script-principal.test.ts +207 -7
  298. package/src/tools/send-task.ts +35 -47
  299. package/src/tools/slack-leave-thread.ts +104 -0
  300. package/src/tools/steer-task.ts +3 -2
  301. package/src/tools/task-dedup.ts +45 -21
  302. package/src/tools/tool-config.ts +2 -1
  303. package/src/types.ts +57 -0
  304. package/src/utils/codex-auth-failure.ts +30 -0
  305. package/src/utils/context-window.ts +4 -1
  306. package/src/utils/credentials.ts +7 -0
  307. package/src/utils/fx-models.ts +43 -0
  308. package/src/workflows/cooldown.ts +3 -2
  309. package/src/workflows/engine.ts +24 -9
  310. package/templates/schedules/dreaming-daily/config.json +1 -1
  311. package/templates/schedules/dreaming-daily/content.md +6 -14
  312. package/templates/skills/composio-google-docs/content.md +10 -0
  313. package/templates/skills/script-workflows/content.md +19 -1
  314. package/templates/skills/swarm-docs/content.md +2 -0
  315. package/templates/skills/swarm-scripts/SKILL.md +2 -0
  316. package/templates/skills/swarm-scripts/content.md +2 -0
  317. package/templates/workflows/dreaming/content.md +5 -1
  318. package/dist/acp-adapter-96dc64m2.js +0 -15
  319. package/dist/cli-dznrgaep.js +0 -30
  320. package/dist/cli-w3hcrxht.js +0 -6985
  321. package/dist/handlers-jg7v74ty.js +0 -31
  322. package/dist/index-8c1zbz59.js +0 -29
  323. package/dist/index-8k8tmfxd.js +0 -32
  324. package/dist/index-hq617xdj.js +0 -36
  325. package/dist/lead-567kw7x3.js +0 -68
  326. package/dist/worker-fjdqra6q.js +0 -68
@@ -2,14 +2,14 @@ import {
2
2
  ACP_TARGET_IDS,
3
3
  isAcpTarget,
4
4
  getAcpTargetCatalogEntry
5
- } from "./cli-9cctx1tn.js";
5
+ } from "./cli-a22h291q.js";
6
6
  import {
7
7
  applyReasoningEffort
8
- } from "./cli-vqgnyh76.js";
8
+ } from "./cli-98rw5dt5.js";
9
9
  import {
10
10
  applyOpenRouterBaseUrlOverride2,
11
11
  buildOpenAICompatibleProviderBlock2
12
- } from "./cli-13jvmew3.js";
12
+ } from "./cli-ekwks2vs.js";
13
13
  import {
14
14
  fetchInstalledMcpServers
15
15
  } from "./cli-bst1vp7e.js";
@@ -17,7 +17,7 @@ import {
17
17
  getContextWindowSize,
18
18
  clampContextPercent,
19
19
  init_context_window
20
- } from "./cli-rtk9g7av.js";
20
+ } from "./cli-73jzwksr.js";
21
21
  import {
22
22
  detachedProcessGroup,
23
23
  registerProcessGroup,
@@ -27,6 +27,16 @@ import {
27
27
  import {
28
28
  init_v4
29
29
  } from "./cli-5xaqj21p.js";
30
+ import {
31
+ DEFAULT_MODEL_TIER_MAP,
32
+ init_types4
33
+ } from "./cli-nhrvpaj7.js";
34
+ import {
35
+ resolveTemplateFromCode,
36
+ resolveTemplateAsync,
37
+ init_resolver,
38
+ init_session_templates
39
+ } from "./cli-cm5yqn35.js";
30
40
  import {
31
41
  NEVER,
32
42
  string2,
@@ -48,18 +58,39 @@ import {
48
58
  import {
49
59
  init_package,
50
60
  package_default
51
- } from "./cli-pe09p6dv.js";
61
+ } from "./cli-e3r2neck.js";
52
62
  import {
53
63
  scrubSecrets,
54
64
  init_secret_scrubber
55
- } from "./cli-a4btqqft.js";
65
+ } from "./cli-1b7btd38.js";
56
66
  import {
67
+ fxModelRoute,
57
68
  normalizeGrokModel,
58
69
  baseUrlOverride,
59
70
  providerBaseUrl,
60
71
  providerForModel,
61
72
  init_src2
62
- } from "./cli-4r12t6w6.js";
73
+ } from "./cli-5c4hjzne.js";
74
+
75
+ // src/utils/fx-models.ts
76
+ init_src2();
77
+ init_types4();
78
+ var FX_ROUTE_KEY_VARS = [
79
+ "OPENROUTER_API_KEY",
80
+ "OPENAI_API_KEY",
81
+ "AI_GATEWAY_API_KEY"
82
+ ];
83
+ function resolveFxRoute(model) {
84
+ const value = model?.trim() || DEFAULT_MODEL_TIER_MAP.fx.regular;
85
+ const route = fxModelRoute(value);
86
+ return "error" in route ? route : { ...route, model: value };
87
+ }
88
+ function requireFxRoute(model) {
89
+ const route = resolveFxRoute(model);
90
+ if ("error" in route)
91
+ throw new Error(route.error);
92
+ return route;
93
+ }
63
94
 
64
95
  // node_modules/@agentclientprotocol/sdk/dist/v1/unstable/schema/index.js
65
96
  var AGENT_METHODS = {
@@ -1561,6 +1592,8 @@ var zSubagentUpdate = object2({
1561
1592
  state: defaultOnError(zStateUpdate.nullish(), () => {
1562
1593
  return;
1563
1594
  }),
1595
+ cwd: string2().nullish(),
1596
+ additionalDirectories: array2(string2()).nullish(),
1564
1597
  _meta: defaultOnError(record2(string2(), unknown()).nullish(), () => {
1565
1598
  return;
1566
1599
  })
@@ -2173,6 +2206,17 @@ var zCancelRequestNotification = object2({
2173
2206
 
2174
2207
  // node_modules/@agentclientprotocol/sdk/dist/core/jsonrpc.js
2175
2208
  var CANCEL_REQUEST_METHOD = "$/cancel_request";
2209
+ function treatSessionNotFoundAsSuccess(method, response, success) {
2210
+ if (method !== "session/close" && method !== "session/delete") {
2211
+ return response;
2212
+ }
2213
+ return response.catch((error) => {
2214
+ if (error instanceof RequestError && error.code === -32002) {
2215
+ return success();
2216
+ }
2217
+ throw error;
2218
+ });
2219
+ }
2176
2220
  function isRequestMessage(value) {
2177
2221
  return isJsonRpcEnvelope(value) && "id" in value && typeof value["method"] === "string" && isJsonRpcId(value["id"]);
2178
2222
  }
@@ -2205,28 +2249,6 @@ function isJsonRpcId(value) {
2205
2249
  function isResponseShapedMessage(value) {
2206
2250
  return isRecord(value) && !("method" in value) && (("id" in value) || ("result" in value) || ("error" in value));
2207
2251
  }
2208
- function isResponseBatch(batch) {
2209
- let hasValidCall = false;
2210
- let hasValidResponse = false;
2211
- let hasCallShape = false;
2212
- let hasResponseShape = false;
2213
- for (const entry of batch) {
2214
- hasValidCall ||= isRequestMessage(entry) || isNotificationMessage(entry);
2215
- hasValidResponse ||= isResponseMessage(entry);
2216
- if (!isRecord(entry)) {
2217
- continue;
2218
- }
2219
- hasCallShape ||= "method" in entry;
2220
- hasResponseShape ||= "result" in entry || "error" in entry;
2221
- }
2222
- if (hasValidCall) {
2223
- return false;
2224
- }
2225
- if (hasValidResponse) {
2226
- return true;
2227
- }
2228
- return hasResponseShape && !hasCallShape;
2229
- }
2230
2252
  function cancelRequestId(params) {
2231
2253
  if (!isRecord(params) || !isJsonRpcId(params["requestId"])) {
2232
2254
  return;
@@ -2340,7 +2362,6 @@ class RequestResponder {
2340
2362
  });
2341
2363
  }
2342
2364
  }
2343
- var requestBatchSizes = new WeakMap;
2344
2365
  var nullIdResponders = new WeakSet;
2345
2366
  class HandlerRegistration {
2346
2367
  disposeHandler;
@@ -2374,9 +2395,6 @@ class ConnectionContext {
2374
2395
  sendNotification(method, params) {
2375
2396
  return this.connection.sendNotification(method, params);
2376
2397
  }
2377
- sendBatch(entries) {
2378
- return this.connection.sendBatch(entries);
2379
- }
2380
2398
  sendCancelRequest(requestId) {
2381
2399
  return this.connection.sendCancelRequest(requestId);
2382
2400
  }
@@ -2405,7 +2423,6 @@ class Connection {
2405
2423
  retryQueue = [];
2406
2424
  context = new ConnectionContext(this);
2407
2425
  receiveReader;
2408
- allowBatches = true;
2409
2426
  constructor(requestHandlerOrStream, notificationHandlerOrHandlers, streamOrOptions, options) {
2410
2427
  if (typeof requestHandlerOrStream === "function") {
2411
2428
  const requestHandler = requestHandlerOrStream;
@@ -2466,55 +2483,13 @@ class Connection {
2466
2483
  return rejectedPromise(this.closedReason());
2467
2484
  }
2468
2485
  const request = this.prepareRequest(method, params, mapResponse, options);
2469
- const requestSent = this.sendWireMessage(request.message);
2486
+ const requestSent = this.sendMessage(request.message);
2470
2487
  requestSent.catch(() => {});
2471
2488
  if (options.cancellationSignal?.aborted) {
2472
2489
  request.cancel();
2473
2490
  }
2474
2491
  return request.response;
2475
2492
  }
2476
- sendBatch(entries) {
2477
- if (this.abortController.signal.aborted) {
2478
- return rejectedPromise(this.closedReason());
2479
- }
2480
- if (!this.allowBatches) {
2481
- return rejectedPromise(new TypeError("JSON-RPC batches are not supported on this connection"));
2482
- }
2483
- if (entries.length === 0) {
2484
- return rejectedPromise(new TypeError("JSON-RPC batch must contain at least one entry"));
2485
- }
2486
- const messages = [];
2487
- const cancellations = [];
2488
- const outputs = [];
2489
- for (const entry of entries) {
2490
- if (entry.kind === "notification") {
2491
- messages.push({
2492
- jsonrpc: "2.0",
2493
- method: entry.method,
2494
- params: entry.params
2495
- });
2496
- outputs.push(Promise.resolve(undefined));
2497
- continue;
2498
- }
2499
- const request = this.prepareRequest(entry.method, entry.params, entry.mapResponse, entry.options);
2500
- messages.push(request.message);
2501
- outputs.push(request.response);
2502
- cancellations.push({
2503
- signal: entry.options?.cancellationSignal,
2504
- cancel: request.cancel
2505
- });
2506
- }
2507
- const batch = messages;
2508
- const batchSent = this.sendWireMessage(batch);
2509
- for (const cancellation of cancellations) {
2510
- if (cancellation.signal?.aborted) {
2511
- cancellation.cancel();
2512
- }
2513
- }
2514
- const response = Promise.all([batchSent, ...outputs]).then(([, ...resolved]) => resolved);
2515
- response.catch(() => {});
2516
- return response;
2517
- }
2518
2493
  sendCancelRequest(requestId) {
2519
2494
  return this.sendNotification(CANCEL_REQUEST_METHOD, { requestId });
2520
2495
  }
@@ -2522,7 +2497,7 @@ class Connection {
2522
2497
  if (this.abortController.signal.aborted) {
2523
2498
  return rejectedPromise(this.closedReason());
2524
2499
  }
2525
- return this.sendWireMessage({ jsonrpc: "2.0", method, params });
2500
+ return this.sendMessage({ jsonrpc: "2.0", method, params });
2526
2501
  }
2527
2502
  prepareRequest(method, params, mapResponse, options = {}) {
2528
2503
  const id = this.nextRequestId++;
@@ -2582,7 +2557,6 @@ class Connection {
2582
2557
  this.stream = stream;
2583
2558
  this.staticHandlers = handlers;
2584
2559
  this.fallbackHandlers = [...options?.fallbackHandlers ?? []];
2585
- this.allowBatches = options?.allowBatches ?? true;
2586
2560
  this.closedPromise = new Promise((resolve) => {
2587
2561
  this.abortController.signal.addEventListener("abort", () => resolve());
2588
2562
  });
@@ -2615,7 +2589,7 @@ class Connection {
2615
2589
  if (done) {
2616
2590
  break;
2617
2591
  }
2618
- this.receiveWireMessage(message);
2592
+ this.receiveUnvalidatedMessage(message);
2619
2593
  }
2620
2594
  } finally {
2621
2595
  if (this.receiveReader === reader) {
@@ -2629,65 +2603,18 @@ class Connection {
2629
2603
  this.close(closeError);
2630
2604
  }
2631
2605
  }
2632
- receiveWireMessage(message) {
2606
+ receiveUnvalidatedMessage(message) {
2633
2607
  if (Array.isArray(message)) {
2634
- if (!this.allowBatches) {
2635
- this.close(new TypeError("JSON-RPC batches are not supported on this connection"));
2636
- return;
2637
- }
2638
- this.receiveBatch(message);
2608
+ this.sendMessage(protocolErrorResponse(RequestError.invalidRequest(undefined, "JSON-RPC batches are not supported"))).catch(() => {});
2639
2609
  return;
2640
2610
  }
2641
2611
  if (!isRequestMessage(message) && !isNotificationMessage(message) && !isResponseShapedMessage(message)) {
2642
- this.sendWireMessage(protocolErrorResponse(RequestError.invalidRequest(message))).catch(() => {});
2612
+ this.sendMessage(protocolErrorResponse(RequestError.invalidRequest(message))).catch(() => {});
2643
2613
  return;
2644
2614
  }
2645
2615
  this.receiveMessage(message);
2646
2616
  }
2647
- receiveBatch(batch) {
2648
- if (batch.length === 0) {
2649
- this.sendWireMessage(protocolErrorResponse(RequestError.invalidRequest(batch))).catch(() => {});
2650
- return;
2651
- }
2652
- const responseBatch = isResponseBatch(batch);
2653
- const responseCount = responseBatch ? 0 : batch.reduce((count, message) => count + (isNotificationMessage(message) ? 0 : 1), 0);
2654
- let remaining = responseCount;
2655
- let remainingNotifications = batch.reduce((count, message) => count + (isNotificationMessage(message) ? 1 : 0), 0);
2656
- let responseSent = false;
2657
- const responses = [];
2658
- const sendResponsesIfReady = async () => {
2659
- if (responseSent || remaining !== 0 || remainingNotifications !== 0 || responses.length === 0) {
2660
- return;
2661
- }
2662
- responseSent = true;
2663
- await this.sendWireMessage(responses);
2664
- };
2665
- const collectResponse = async (response) => {
2666
- responses.push(response);
2667
- remaining -= 1;
2668
- await sendResponsesIfReady();
2669
- };
2670
- for (const message of batch) {
2671
- if (responseBatch) {
2672
- if (isResponseShapedMessage(message)) {
2673
- this.receiveMessage(message);
2674
- }
2675
- continue;
2676
- }
2677
- if (!isRequestMessage(message) && !isNotificationMessage(message)) {
2678
- collectResponse(protocolErrorResponse(RequestError.invalidRequest(message))).catch(() => {});
2679
- continue;
2680
- }
2681
- const processing = this.receiveMessage(message, isRequestMessage(message) ? collectResponse : undefined, batch.length);
2682
- if (isNotificationMessage(message)) {
2683
- processing.finally(() => {
2684
- remainingNotifications -= 1;
2685
- sendResponsesIfReady().catch((error) => this.close(error));
2686
- });
2687
- }
2688
- }
2689
- }
2690
- receiveMessage(message, sendResponse, batchSize) {
2617
+ receiveMessage(message) {
2691
2618
  if (this.abortController.signal.aborted) {
2692
2619
  return Promise.resolve();
2693
2620
  }
@@ -2699,7 +2626,7 @@ class Connection {
2699
2626
  if (!("id" in message)) {
2700
2627
  this.handleProtocolNotification(message);
2701
2628
  }
2702
- return this.processIncomingMessage(this.toIncomingMessage(message, sendResponse, batchSize)).catch((error) => this.close(error));
2629
+ return this.processIncomingMessage(this.toIncomingMessage(message)).catch((error) => this.close(error));
2703
2630
  } else if ("id" in message) {
2704
2631
  this.handleResponse(message);
2705
2632
  } else {
@@ -2754,7 +2681,7 @@ class Connection {
2754
2681
  }
2755
2682
  }
2756
2683
  }
2757
- toIncomingMessage(message, sendResponse, batchSize) {
2684
+ toIncomingMessage(message) {
2758
2685
  if ("id" in message) {
2759
2686
  const abortController = new AbortController;
2760
2687
  this.incomingRequests.set(message.id, abortController);
@@ -2769,11 +2696,8 @@ class Connection {
2769
2696
  id: nullIdResponders.has(responder) ? null : message.id,
2770
2697
  ...result
2771
2698
  };
2772
- return sendResponse ? sendResponse(response) : this.sendWireMessage(response);
2699
+ return this.sendMessage(response);
2773
2700
  }, abortController.signal, finishRequest);
2774
- if (batchSize !== undefined) {
2775
- requestBatchSizes.set(responder, batchSize);
2776
- }
2777
2701
  return {
2778
2702
  kind: "request",
2779
2703
  method: message.method,
@@ -2824,7 +2748,7 @@ class Connection {
2824
2748
  closedReason() {
2825
2749
  return this.abortController.signal.reason ?? new Error("ACP connection closed");
2826
2750
  }
2827
- async sendWireMessage(message) {
2751
+ async sendMessage(message) {
2828
2752
  if (this.abortController.signal.aborted) {
2829
2753
  return rejectedPromise(this.closedReason());
2830
2754
  }
@@ -3154,7 +3078,9 @@ function ndJsonStream(output, input, options = {}) {
3154
3078
  await writeJson(protocolErrorResponse(RequestError.parseError()));
3155
3079
  return;
3156
3080
  }
3157
- if (isRecord(message) || Array.isArray(message)) {
3081
+ if (Array.isArray(message)) {
3082
+ await writeJson(protocolErrorResponse(RequestError.invalidRequest(undefined, "JSON-RPC batches are not supported")));
3083
+ } else if (isRecord(message)) {
3158
3084
  controller.enqueue(message);
3159
3085
  } else {
3160
3086
  await writeJson(protocolErrorResponse(RequestError.invalidRequest(message)));
@@ -3482,7 +3408,7 @@ class ClientContext extends AcpContext {
3482
3408
  }
3483
3409
  request(method, params, options) {
3484
3410
  const spec = agentRequestSpecsByMethod[method];
3485
- return this.sendRequest(method, params, spec?.mapResponse, options);
3411
+ return treatSessionNotFoundAsSuccess(method, this.sendRequest(method, params, spec?.mapResponse, options), () => spec?.mapResponse ? spec.mapResponse({}) : {});
3486
3412
  }
3487
3413
  notify(method, params) {
3488
3414
  return this.sendNotification(method, params);
@@ -3865,7 +3791,6 @@ function runConnectHandlers(connection, handlers) {
3865
3791
  var appBuilder = Symbol("appBuilder");
3866
3792
  var runAgentConnectHandlers = Symbol("runAgentConnectHandlers");
3867
3793
  var runClientConnectHandlers = Symbol("runClientConnectHandlers");
3868
- var stableConnectionOptions = { allowBatches: false };
3869
3794
  function client(options) {
3870
3795
  return new ClientApp(options);
3871
3796
  }
@@ -3951,7 +3876,7 @@ class ClientApp {
3951
3876
  return state;
3952
3877
  }
3953
3878
  const [thisStream, peerStream] = memoryStreamPair();
3954
- const peerRawConnection = target[appBuilder]().connect(peerStream, stableConnectionOptions);
3879
+ const peerRawConnection = target[appBuilder]().connect(peerStream);
3955
3880
  const peerConnection = agentConnection(peerRawConnection);
3956
3881
  const state = this.openStreamConnection(thisStream);
3957
3882
  state.rawConnection.closed.then(() => peerConnection.close());
@@ -3967,7 +3892,7 @@ class ClientApp {
3967
3892
  return state;
3968
3893
  }
3969
3894
  openStreamConnection(stream) {
3970
- const rawConnection = this.builder.connect(stream, stableConnectionOptions);
3895
+ const rawConnection = this.builder.connect(stream);
3971
3896
  return {
3972
3897
  rawConnection,
3973
3898
  connection: clientConnection(rawConnection, this.connectHandlers)
@@ -4180,10 +4105,13 @@ function translateAcpSessionNotification(notification) {
4180
4105
 
4181
4106
  // src/providers/acp-targets.ts
4182
4107
  init_src2();
4108
+ init_resolver();
4109
+ init_session_templates();
4183
4110
  init_context_window();
4184
- import { mkdir, mkdtemp, rm } from "node:fs/promises";
4111
+ import { chmod, mkdir, mkdtemp, rm } from "node:fs/promises";
4185
4112
  import { tmpdir } from "node:os";
4186
4113
  import { join } from "node:path";
4114
+ init_secret_scrubber();
4187
4115
  class AcpTargetResolutionError extends Error {
4188
4116
  constructor(message) {
4189
4117
  super(message);
@@ -4678,6 +4606,171 @@ var grokTargetProfile = {
4678
4606
  return `Grok rejected the credentials (XAI_API_KEY or OPENROUTER_API_KEY invalid or missing): ${message}`;
4679
4607
  }
4680
4608
  };
4609
+ var FX_SYSTEM_PROMPT_INLINE_MAX_BYTES = 60 * 1024;
4610
+ var FX_SYSTEM_PROMPT_HEAD_BYTES = 56 * 1024;
4611
+ var FX_SYSTEM_PROMPT_FILE_TEMPLATE = "system.agent.fx.system_prompt_file";
4612
+ var FX_CONTEXT_NOTICE_PREFIX = "[context] ";
4613
+ var FX_AUTH_ERROR_RE = /authentication is unavailable|credential is unavailable|MissingApiKey|unauthorized|\b401\b/i;
4614
+ function fxRunDir(config) {
4615
+ const safe = config.taskId.replace(/[^A-Za-z0-9._-]/g, "_") || "session";
4616
+ return join(tmpdir(), `fx-${safe}`);
4617
+ }
4618
+ function utf8Head(bytes, max) {
4619
+ let end = Math.min(max, bytes.length);
4620
+ while (end > 0 && end < bytes.length && ((bytes[end] ?? 0) & 192) === 128)
4621
+ end -= 1;
4622
+ return new TextDecoder().decode(bytes.subarray(0, end));
4623
+ }
4624
+ async function fxSystemPromptPointer(path) {
4625
+ try {
4626
+ const result = await resolveTemplateAsync(FX_SYSTEM_PROMPT_FILE_TEMPLATE, { path });
4627
+ if (!result.skipped && result.text.trim())
4628
+ return result.text;
4629
+ } catch {}
4630
+ return resolveTemplateFromCode(FX_SYSTEM_PROMPT_FILE_TEMPLATE, { path }).text;
4631
+ }
4632
+ async function fxSystemPrompt(systemPrompt, dir) {
4633
+ if (!systemPrompt.trim())
4634
+ return;
4635
+ const bytes = new TextEncoder().encode(systemPrompt);
4636
+ if (bytes.length <= FX_SYSTEM_PROMPT_INLINE_MAX_BYTES) {
4637
+ return { blocks: [{ type: "text", text: systemPrompt }] };
4638
+ }
4639
+ const artifactPath = join(dir, "SYSTEM.md");
4640
+ await mkdir(dir, { recursive: true });
4641
+ await Bun.write(artifactPath, systemPrompt);
4642
+ await chmod(artifactPath, 384);
4643
+ const head = utf8Head(bytes, FX_SYSTEM_PROMPT_HEAD_BYTES);
4644
+ const pointer = await fxSystemPromptPointer(artifactPath);
4645
+ return { blocks: [{ type: "text", text: `${head}
4646
+
4647
+ ${pointer}` }], artifactPath };
4648
+ }
4649
+ async function fxSessionExists(sessionId, home) {
4650
+ if (!home || !/^[A-Za-z0-9_-]+$/.test(sessionId))
4651
+ return false;
4652
+ return Bun.file(join(home, ".fx", "sessions", "v2", sessionId, "log.jsonl")).exists();
4653
+ }
4654
+ function rewriteFxEvent(event, update) {
4655
+ if (event.type === "message" && event.role === "assistant" && event.content.startsWith(FX_CONTEXT_NOTICE_PREFIX)) {
4656
+ return {
4657
+ type: "custom",
4658
+ name: "fx_context_notice",
4659
+ data: { text: event.content, messageId: event.messageId ?? null }
4660
+ };
4661
+ }
4662
+ if (event.type === "tool_start" && update?.sessionUpdate === "tool_call") {
4663
+ const mcp = update._meta?.fx?.toolCall?.mcp;
4664
+ if (typeof mcp?.server === "string" && typeof mcp.tool === "string" && mcp.server && mcp.tool) {
4665
+ return { ...event, toolName: `mcp__${mcp.server}__${mcp.tool}` };
4666
+ }
4667
+ const name = update.name;
4668
+ if (typeof name === "string" && name.trim())
4669
+ return { ...event, toolName: name.trim() };
4670
+ }
4671
+ return event;
4672
+ }
4673
+ async function steerFx({
4674
+ sessionId,
4675
+ delivery,
4676
+ initResult,
4677
+ prompt,
4678
+ onUpdate
4679
+ }) {
4680
+ if (delivery.mode !== "steer") {
4681
+ return { delivered: false, reason: `fx supports steer only, not ${delivery.mode}` };
4682
+ }
4683
+ const meta = initResult.agentCapabilities?._meta;
4684
+ if (meta?.fx?.steering !== true) {
4685
+ return { delivered: false, reason: "fx did not advertise _meta.fx.steering" };
4686
+ }
4687
+ return new Promise((resolve) => {
4688
+ let settled = false;
4689
+ let stopListening = () => {};
4690
+ const settle = (result) => {
4691
+ if (settled)
4692
+ return;
4693
+ settled = true;
4694
+ stopListening();
4695
+ resolve(result);
4696
+ };
4697
+ stopListening = onUpdate((update) => {
4698
+ if (update.sessionUpdate !== "user_message_chunk")
4699
+ return;
4700
+ const steering = update._meta?.fx?.steering;
4701
+ if (!steering || update.content.type !== "text" || update.content.text !== delivery.text) {
4702
+ return;
4703
+ }
4704
+ settle({ delivered: true, mode: "steer" });
4705
+ });
4706
+ prompt({
4707
+ sessionId,
4708
+ prompt: [{ type: "text", text: delivery.text }],
4709
+ _meta: { fx: { steer: true } }
4710
+ }).then((response) => {
4711
+ const state = response._meta?.fx?.steering;
4712
+ settle(state === "absorbed" ? { delivered: true, mode: "steer" } : {
4713
+ delivered: false,
4714
+ reason: `fx did not absorb the steer (stopReason ${response.stopReason}, steering ${JSON.stringify(state ?? null)})`
4715
+ });
4716
+ }, (err) => {
4717
+ const message = err instanceof Error ? err.message : String(err);
4718
+ settle({ delivered: false, reason: scrubSecrets(`fx steer failed: ${message}`) });
4719
+ });
4720
+ });
4721
+ }
4722
+ var fxTargetProfile = {
4723
+ target: "fx",
4724
+ command(config) {
4725
+ const binary = readEnv(config, "FX_BINARY")?.trim() || "fx";
4726
+ const route = requireFxRoute(config.model);
4727
+ return [
4728
+ binary,
4729
+ "acp",
4730
+ "--model",
4731
+ route.fxModel,
4732
+ "--log-file",
4733
+ join(fxRunDir(config), "acp.log")
4734
+ ];
4735
+ },
4736
+ env(config) {
4737
+ const route = requireFxRoute(config.model);
4738
+ const env = baseTargetEnv(config);
4739
+ copyEnvKeys(config, env, [route.keyVar]);
4740
+ env.FX_PROVIDER = route.fxProvider;
4741
+ env.FX_PERMISSION_MODE = "full-access";
4742
+ env.FX_AUTO_UPGRADE = "0";
4743
+ env.FX_NO_OPEN_BROWSER = "1";
4744
+ return env;
4745
+ },
4746
+ configuredOptions(config) {
4747
+ if (!config.reasoningEffort)
4748
+ return {};
4749
+ const effort = applyReasoningEffort("fx", config.model.trim(), config.reasoningEffort);
4750
+ return effort.kind === "fx-effort" ? { effort: effort.reasoningEffort } : {};
4751
+ },
4752
+ async writeSystemPromptArtifact(config) {
4753
+ await mkdir(fxRunDir(config), { recursive: true, mode: 448 });
4754
+ },
4755
+ async cleanupSystemPromptArtifact(config) {
4756
+ await rm(fxRunDir(config), { recursive: true, force: true });
4757
+ },
4758
+ sessionSystemPrompt(config) {
4759
+ return fxSystemPrompt(config.systemPrompt ?? "", fxRunDir(config));
4760
+ },
4761
+ requiresSecureMcpUrl: true,
4762
+ steer: steerFx,
4763
+ resume: {
4764
+ method: "session/resume",
4765
+ canResume: (sessionId) => fxSessionExists(sessionId, process.env.HOME)
4766
+ },
4767
+ rewriteEvent: rewriteFxEvent,
4768
+ describeError(message) {
4769
+ if (!FX_AUTH_ERROR_RE.test(message))
4770
+ return;
4771
+ return `fx could not authenticate the model route (OPENROUTER_API_KEY, OPENAI_API_KEY or AI_GATEWAY_API_KEY invalid or missing): ${message}`;
4772
+ }
4773
+ };
4681
4774
  function resolveAcpTarget(config) {
4682
4775
  const target = readEnv(config, "ACP_TARGET") ?? "custom";
4683
4776
  if (!isAcpTarget(target)) {
@@ -4701,6 +4794,69 @@ function resolveAcpTarget(config) {
4701
4794
  }
4702
4795
  }
4703
4796
 
4797
+ // src/providers/mcp-loopback-proxy.ts
4798
+ init_secret_scrubber();
4799
+ var DROPPED_REQUEST_HEADERS = [
4800
+ "host",
4801
+ "connection",
4802
+ "keep-alive",
4803
+ "proxy-connection",
4804
+ "transfer-encoding",
4805
+ "upgrade"
4806
+ ];
4807
+ var LOOPBACK_HOSTS = new Set(["localhost", "127.0.0.1", "[::1]", "::1"]);
4808
+ function needsLoopbackProxy(url) {
4809
+ let parsed;
4810
+ try {
4811
+ parsed = new URL(url);
4812
+ } catch {
4813
+ return false;
4814
+ }
4815
+ return parsed.protocol === "http:" && !LOOPBACK_HOSTS.has(parsed.hostname.toLowerCase());
4816
+ }
4817
+ async function startMcpLoopbackProxy(upstream) {
4818
+ const base = new URL(upstream);
4819
+ const prefix = base.pathname.replace(/\/+$/, "");
4820
+ const server = Bun.serve({
4821
+ hostname: "127.0.0.1",
4822
+ port: 0,
4823
+ idleTimeout: 0,
4824
+ async fetch(req) {
4825
+ const incoming = new URL(req.url);
4826
+ const target = new URL(base);
4827
+ target.pathname = `${prefix}${incoming.pathname}`;
4828
+ target.search = incoming.search;
4829
+ const headers = new Headers(req.headers);
4830
+ for (const name of DROPPED_REQUEST_HEADERS)
4831
+ headers.delete(name);
4832
+ try {
4833
+ const hasBody = req.method !== "GET" && req.method !== "HEAD";
4834
+ return await fetch(target, {
4835
+ method: req.method,
4836
+ headers,
4837
+ body: hasBody ? req.body : undefined,
4838
+ redirect: "manual",
4839
+ signal: req.signal,
4840
+ decompress: false
4841
+ });
4842
+ } catch (err) {
4843
+ const message = err instanceof Error ? err.message : String(err);
4844
+ return new Response(JSON.stringify({
4845
+ error: scrubSecrets(`MCP loopback proxy: upstream failed: ${message}`)
4846
+ }), { status: 502, headers: { "Content-Type": "application/json" } });
4847
+ }
4848
+ }
4849
+ });
4850
+ let stopped = null;
4851
+ return {
4852
+ url: `http://127.0.0.1:${server.port}`,
4853
+ stop() {
4854
+ stopped ??= server.stop(true);
4855
+ return stopped;
4856
+ }
4857
+ };
4858
+ }
4859
+
4704
4860
  // src/providers/acp-adapter.ts
4705
4861
  var ACP_LOG_MAX_CHARS = 30000;
4706
4862
  var ACP_CANCEL_SETTLE_MS = 3000;
@@ -4802,6 +4958,7 @@ class SwarmAcpClient {
4802
4958
  emit;
4803
4959
  target;
4804
4960
  reportedCostUsd = null;
4961
+ updateListeners = new Set;
4805
4962
  constructor(emit, target) {
4806
4963
  this.emit = emit;
4807
4964
  this.target = target;
@@ -4818,8 +4975,16 @@ class SwarmAcpClient {
4818
4975
  if (costUsd !== null)
4819
4976
  this.reportedCostUsd = costUsd;
4820
4977
  for (const event of translateAcpSessionNotification(params)) {
4821
- this.emit(this.target?.rewriteEvent?.(event) ?? event);
4978
+ this.emit(this.target?.rewriteEvent?.(event, params.update) ?? event);
4822
4979
  }
4980
+ for (const listener of this.updateListeners)
4981
+ listener(params.update);
4982
+ }
4983
+ onUpdate(listener) {
4984
+ this.updateListeners.add(listener);
4985
+ return () => {
4986
+ this.updateListeners.delete(listener);
4987
+ };
4823
4988
  }
4824
4989
  }
4825
4990
 
@@ -4830,6 +4995,7 @@ class ACPSession {
4830
4995
  config;
4831
4996
  providerName;
4832
4997
  target;
4998
+ extras;
4833
4999
  sessionId;
4834
5000
  listeners = new Set;
4835
5001
  pendingEvents = [];
@@ -4840,20 +5006,44 @@ class ACPSession {
4840
5006
  completionPromise;
4841
5007
  completionResolve;
4842
5008
  ephemeralTokenId = null;
4843
- constructor(agent, client, process2, config, sessionId, providerName, target, providerMeta, ephemeralTokenId) {
5009
+ deliverSteering;
5010
+ constructor(agent, client, process2, config, sessionId, providerName, target, providerMeta, ephemeralTokenId, extras) {
4844
5011
  this.agent = agent;
4845
5012
  this.client = client;
4846
5013
  this.process = process2;
4847
5014
  this.config = config;
4848
5015
  this.providerName = providerName;
4849
5016
  this.target = target;
5017
+ this.extras = extras;
4850
5018
  this.sessionId = sessionId;
4851
5019
  this.ephemeralTokenId = ephemeralTokenId ?? null;
4852
5020
  this.completionPromise = new Promise((resolve) => {
4853
5021
  this.completionResolve = resolve;
4854
5022
  });
5023
+ const steer = target.steer;
5024
+ if (steer && extras) {
5025
+ const initResult = extras.initResult;
5026
+ this.deliverSteering = async (delivery) => {
5027
+ if (this.completed || this.aborted) {
5028
+ return { delivered: false, reason: "The ACP session has already finished" };
5029
+ }
5030
+ return steer({
5031
+ sessionId,
5032
+ delivery,
5033
+ initResult,
5034
+ prompt: (params) => this.agent.request(methods.agent.session.prompt, params),
5035
+ onUpdate: (listener) => this.client.onUpdate(listener)
5036
+ });
5037
+ };
5038
+ }
4855
5039
  this.consumeStderr();
4856
- this.emit({ type: "session_init", sessionId, provider: providerName, providerMeta });
5040
+ this.emit({
5041
+ type: "session_init",
5042
+ sessionId,
5043
+ provider: providerName,
5044
+ providerMeta,
5045
+ ...extras?.harnessVariantMeta ? { harnessVariantMeta: extras.harnessVariantMeta } : {}
5046
+ });
4857
5047
  this.runPrompt();
4858
5048
  }
4859
5049
  onEvent(listener) {
@@ -5003,6 +5193,7 @@ class ACPSession {
5003
5193
  return;
5004
5194
  this.completed = true;
5005
5195
  this.completionResolve(result);
5196
+ stopProxies(this.extras?.proxies ?? []);
5006
5197
  if (this.ephemeralTokenId) {
5007
5198
  revokeAcpSessionToken(this.config.apiUrl, this.config.apiKey, this.ephemeralTokenId);
5008
5199
  }
@@ -5056,39 +5247,71 @@ class ACPAdapter2 {
5056
5247
  const stream = ndJsonStream2(fileSinkWritableStream(proc.stdin), proc.stdout);
5057
5248
  const agent = client().onRequest(methods.client.session.requestPermission, ({ params }) => client2.requestPermission(params)).onNotification(methods.client.session.update, ({ params }) => client2.sessionUpdate(params)).connect(stream).agent;
5058
5249
  let ephemeralToken = null;
5250
+ const proxies = [];
5059
5251
  try {
5060
- await agent.request(methods.agent.initialize, {
5252
+ const initResult = await agent.request(methods.agent.initialize, {
5061
5253
  protocolVersion: PROTOCOL_VERSION,
5062
5254
  clientInfo: { name: "agent-swarm", version: package_default.version },
5063
5255
  clientCapabilities: { session: { configOptions: { boolean: {} } } }
5064
5256
  });
5065
5257
  ephemeralToken = await mintAcpSessionToken(config.apiUrl, config.apiKey, config.agentId, config.taskId);
5066
5258
  const installedServers = await fetchInstalledMcpServers(config.apiUrl, config.apiKey, config.agentId, "claude");
5259
+ let mcpServers = [
5260
+ {
5261
+ type: "http",
5262
+ name: "swarm",
5263
+ url: `${config.apiUrl.replace(/\/+$/, "")}/mcp`,
5264
+ headers: [
5265
+ { name: "Authorization", value: `Bearer ${ephemeralToken.plaintext}` },
5266
+ { name: "X-Agent-ID", value: config.agentId },
5267
+ { name: "X-Source-Task-Id", value: config.taskId }
5268
+ ]
5269
+ },
5270
+ ...toAcpMcpServers(installedServers)
5271
+ ];
5272
+ if (target.requiresSecureMcpUrl) {
5273
+ mcpServers = await secureMcpServers(mcpServers, initResult.agentCapabilities?.mcpCapabilities?.sse === true, proxies);
5274
+ }
5067
5275
  const sessionMeta = target.sessionMeta?.(config);
5068
- const newSession = await agent.request(methods.agent.session.new, {
5069
- ...sessionMeta ? { _meta: sessionMeta } : {},
5070
- cwd: config.cwd,
5071
- mcpServers: [
5072
- {
5073
- type: "http",
5074
- name: "swarm",
5075
- url: `${config.apiUrl.replace(/\/+$/, "")}/mcp`,
5076
- headers: [
5077
- { name: "Authorization", value: `Bearer ${ephemeralToken.plaintext}` },
5078
- { name: "X-Agent-ID", value: config.agentId },
5079
- { name: "X-Source-Task-Id", value: config.taskId }
5080
- ]
5081
- },
5082
- ...toAcpMcpServers(installedServers)
5083
- ]
5084
- });
5276
+ const resumeId = target.resume ? config.resumeSessionId?.trim() : undefined;
5277
+ let sessionId;
5278
+ let advertisedOptions;
5279
+ if (resumeId && initResult.agentCapabilities?.sessionCapabilities?.resume) {
5280
+ const resumed = await agent.request(methods.agent.session.resume, {
5281
+ ...sessionMeta ? { _meta: sessionMeta } : {},
5282
+ sessionId: resumeId,
5283
+ cwd: config.cwd,
5284
+ mcpServers
5285
+ });
5286
+ sessionId = resumeId;
5287
+ advertisedOptions = resumed.configOptions ?? [];
5288
+ } else {
5289
+ if (resumeId) {
5290
+ console.warn("\x1B[33m[acp]\x1B[0m Target does not advertise session/resume; starting a new session");
5291
+ }
5292
+ const systemPrompt = await sessionSystemPromptBlocks(target, config, initResult);
5293
+ const newSessionParams = {
5294
+ ...sessionMeta ? { _meta: sessionMeta } : {},
5295
+ cwd: config.cwd,
5296
+ mcpServers,
5297
+ ...systemPrompt ? { systemPrompt } : {}
5298
+ };
5299
+ const newSession = await agent.request(methods.agent.session.new, newSessionParams);
5300
+ sessionId = newSession.sessionId;
5301
+ advertisedOptions = newSession.configOptions ?? [];
5302
+ }
5085
5303
  const configOptions = await applyConfiguredOptions({
5086
5304
  setSessionConfigOption: (params) => agent.request(methods.agent.session.setConfigOption, params)
5087
- }, newSession.sessionId, newSession.configOptions ?? [], target.configuredOptions(config));
5088
- session = new ACPSession(agent, client2, proc, config, newSession.sessionId, this.name, target, {
5305
+ }, sessionId, advertisedOptions, target.configuredOptions(config));
5306
+ const agentVersion = initResult.agentInfo?.version?.trim();
5307
+ session = new ACPSession(agent, client2, proc, config, sessionId, this.name, target, {
5089
5308
  target: target.target,
5090
5309
  configOptions: sanitizeAcpConfigOptions(configOptions)
5091
- }, ephemeralToken.tokenId);
5310
+ }, ephemeralToken.tokenId, {
5311
+ initResult,
5312
+ ...agentVersion ? { harnessVariantMeta: { version: scrubSecrets(agentVersion) } } : {},
5313
+ proxies
5314
+ });
5092
5315
  for (const event of preSessionEvents)
5093
5316
  session.emitFromAcp(event);
5094
5317
  session.waitForCompletion().finally(cleanupArtifact);
@@ -5098,12 +5321,14 @@ class ACPAdapter2 {
5098
5321
  revokeAcpSessionToken(config.apiUrl, config.apiKey, ephemeralToken.tokenId);
5099
5322
  }
5100
5323
  await terminateProcessGroup(proc.pid);
5324
+ await stopProxies(proxies);
5101
5325
  await cleanupArtifact();
5102
5326
  throw new Error(`ACP target failed during startup: ${describeTargetError(target, scrubSecrets(formatError(err)))}`);
5103
5327
  }
5104
5328
  }
5105
- async canResume(_sessionId) {
5106
- return false;
5329
+ async canResume(sessionId) {
5330
+ const resume = this.options.target?.resume;
5331
+ return resume ? resume.canResume(sessionId) : false;
5107
5332
  }
5108
5333
  formatCommand(commandName) {
5109
5334
  return `/${commandName}`;
@@ -5199,6 +5424,46 @@ function toAcpMcpServers(installed) {
5199
5424
  }
5200
5425
  return servers;
5201
5426
  }
5427
+ async function sessionSystemPromptBlocks(target, config, initResult) {
5428
+ if (!target.sessionSystemPrompt)
5429
+ return;
5430
+ if (!initResult.agentCapabilities?.sessionCapabilities?.systemPrompt) {
5431
+ console.warn("\x1B[33m[acp]\x1B[0m Target does not advertise sessionCapabilities.systemPrompt; the swarm system prompt is not sent");
5432
+ return;
5433
+ }
5434
+ const plan = await target.sessionSystemPrompt(config);
5435
+ return plan?.blocks.length ? plan.blocks : undefined;
5436
+ }
5437
+ async function secureMcpServers(servers, sseSupported, proxies) {
5438
+ const byOrigin = new Map;
5439
+ const result = [];
5440
+ for (const server of servers) {
5441
+ if (!("url" in server)) {
5442
+ result.push(server);
5443
+ continue;
5444
+ }
5445
+ if (server.type === "sse" && !sseSupported) {
5446
+ console.warn(`\x1B[33m[acp]\x1B[0m Skipping installed MCP server "${server.name}": the target does not support SSE MCP servers`);
5447
+ continue;
5448
+ }
5449
+ if (!needsLoopbackProxy(server.url)) {
5450
+ result.push(server);
5451
+ continue;
5452
+ }
5453
+ const url = new URL(server.url);
5454
+ let proxy = byOrigin.get(url.origin);
5455
+ if (!proxy) {
5456
+ proxy = await startMcpLoopbackProxy(url.origin);
5457
+ byOrigin.set(url.origin, proxy);
5458
+ proxies.push(proxy);
5459
+ }
5460
+ result.push({ ...server, url: `${proxy.url}${url.pathname}${url.search}` });
5461
+ }
5462
+ return result;
5463
+ }
5464
+ async function stopProxies(proxies) {
5465
+ await Promise.all(proxies.splice(0).map((proxy) => proxy.stop().catch(() => {})));
5466
+ }
5202
5467
  function describeTargetError(target, message) {
5203
5468
  return target.describeError?.(message) ?? message;
5204
5469
  }
@@ -5220,4 +5485,4 @@ function fileSinkWritableStream(sink) {
5220
5485
  });
5221
5486
  }
5222
5487
 
5223
- export { isGrokOpenRouterModel, grokTargetProfile, ACPAdapter2 };
5488
+ export { FX_ROUTE_KEY_VARS, requireFxRoute, isGrokOpenRouterModel, grokTargetProfile, fxSessionExists, fxTargetProfile, ACPAdapter2 };