@desplega.ai/agent-swarm 2.5.3 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (349) hide show
  1. package/README.md +2 -2
  2. package/dist/{acp-adapter-gr2fcyyj.js → acp-adapter-dgfakfpw.js} +9 -9
  3. package/dist/{actions-wv766ghf.js → actions-fbqma8aa.js} +21 -21
  4. package/dist/{amp-adapter-speb906t.js → amp-adapter-en0jy6hs.js} +4 -4
  5. package/dist/{app-ag29n14f.js → app-k8a5cgpp.js} +3 -3
  6. package/dist/{assistant-3x8bz3eg.js → assistant-a16433gr.js} +30 -26
  7. package/dist/{boot-reembed-jsmfrpzf.js → boot-reembed-6c1sjfnr.js} +1 -1
  8. package/dist/{boot-reembed-5b3d2eea.js → boot-reembed-f4nn561n.js} +1 -1
  9. package/dist/{boot-scrub-sweep-s73gerxy.js → boot-scrub-sweep-d4w9gajf.js} +4 -4
  10. package/dist/{boot-seeds-5zmax2wr.js → boot-seeds-9bmkspyw.js} +4 -4
  11. package/dist/{claude-adapter-hswdnm3t.js → claude-adapter-nys1kjxa.js} +9 -9
  12. package/dist/{claude-managed-adapter-cvbzj1h6.js → claude-managed-adapter-55207973.js} +3 -3
  13. package/dist/{claude-managed-setup-3k8m3hhc.js → claude-managed-setup-3cm35gey.js} +11 -4
  14. package/dist/{claude-sdk-session-fkbyk66x.js → claude-sdk-session-nw5yd8cp.js} +9313 -9260
  15. package/dist/{cli-210xd1f4.js → cli-03gg9pd1.js} +4 -4
  16. package/dist/{cli-kxpfx2xr.js → cli-0z1xjzwa.js} +2 -2
  17. package/dist/cli-1tem6ns9.js +894 -0
  18. package/dist/{cli-25j01dpj.js → cli-24j1jeeb.js} +3 -3
  19. package/dist/{cli-ta8bd7th.js → cli-2sjhpsns.js} +2 -2
  20. package/dist/{cli-p859hcc8.js → cli-39aet655.js} +2 -2
  21. package/dist/{cli-g1cw7xtt.js → cli-39rrw8yp.js} +1 -1
  22. package/dist/{cli-e2ar4bp1.js → cli-3aqd4jaa.js} +121 -47
  23. package/dist/{cli-jjznk3f7.js → cli-3fwqy71j.js} +69 -35
  24. package/dist/{cli-p9rafdrb.js → cli-3gfvmzht.js} +7 -7
  25. package/dist/{cli-03vpq45j.js → cli-3ndmpxxv.js} +2 -2
  26. package/dist/{cli-aecdcr77.js → cli-4hxrf0p4.js} +228 -74
  27. package/dist/{cli-mz9afxxf.js → cli-4rf0f5vg.js} +15 -3
  28. package/dist/{cli-qzme5949.js → cli-5rj83bam.js} +284 -202
  29. package/dist/{cli-fsdprwrg.js → cli-5sckpqcx.js} +2 -2
  30. package/dist/{cli-cz5nmdxt.js → cli-683y0b3a.js} +2 -2
  31. package/dist/{cli-3ngdk5te.js → cli-6y51ryva.js} +2 -2
  32. package/dist/{cli-n4c8e3s5.js → cli-708wdy32.js} +1 -1
  33. package/dist/{cli-pasyvjmm.js → cli-737pyqxr.js} +1 -1
  34. package/dist/{cli-gx4rm0qx.js → cli-7enjwya9.js} +1 -1
  35. package/dist/{cli-6x9ma5w5.js → cli-803188pb.js} +1 -1
  36. package/dist/{cli-avdvgcay.js → cli-9abdgn5t.js} +28 -9
  37. package/dist/{cli-99xgw26r.js → cli-a2rr0fmg.js} +1 -1
  38. package/dist/{cli-e5bxnjps.js → cli-a34pr3w1.js} +7 -7
  39. package/dist/{cli-502eqv93.js → cli-abkm71vr.js} +1 -1
  40. package/dist/{cli-mmhj8vd7.js → cli-ag2yrnt5.js} +11 -2
  41. package/dist/{cli-n45mr7zh.js → cli-aj8djyqt.js} +5 -5
  42. package/dist/{cli-1fc85mvt.js → cli-art7c1zh.js} +5 -5
  43. package/dist/{cli-40jsnrjm.js → cli-az25fn5f.js} +10 -8
  44. package/dist/{cli-9s05422w.js → cli-bqztfyve.js} +1 -1
  45. package/dist/{cli-bn0rewsy.js → cli-c081bj3b.js} +2 -2
  46. package/dist/{cli-svrj71pg.js → cli-c2habvsf.js} +12 -12
  47. package/dist/{cli-s49hpn37.js → cli-ca6banwz.js} +85 -19
  48. package/dist/{cli-hhxjnjzs.js → cli-cz37jqss.js} +12 -10
  49. package/dist/{cli-6n8axjv1.js → cli-d2dpf95n.js} +2 -2
  50. package/dist/{cli-tx00c0h6.js → cli-dqygeeh5.js} +17 -1
  51. package/dist/{cli-z21whrrg.js → cli-emhjcj2y.js} +17 -17
  52. package/dist/{cli-e8jyq7d8.js → cli-esakngh8.js} +7 -3
  53. package/dist/{cli-ha9rmwgq.js → cli-fb8m699c.js} +2 -2
  54. package/dist/{cli-35gtk1p6.js → cli-ffvsj2qw.js} +44 -13
  55. package/dist/{cli-ce0ak9ms.js → cli-g20jjwt4.js} +26 -26
  56. package/dist/{cli-kxawjrxg.js → cli-g8ka5j4j.js} +772 -194
  57. package/dist/{cli-vwn81jbs.js → cli-gf95q3bm.js} +5 -5
  58. package/dist/{cli-s53vp709.js → cli-gnsb1zxa.js} +2 -2
  59. package/dist/{cli-nwyw3zhg.js → cli-gxee0bqa.js} +1 -1
  60. package/dist/{cli-gpv60278.js → cli-hfeb68z4.js} +7 -7
  61. package/dist/{cli-0ebey9hg.js → cli-j6rktc91.js} +1 -1
  62. package/dist/{cli-ewm3pwbq.js → cli-k21gx5ht.js} +46 -23
  63. package/dist/{cli-egjggehm.js → cli-kf4jree9.js} +2 -2
  64. package/dist/{cli-dabehxhp.js → cli-kt907da6.js} +1 -1
  65. package/dist/{cli-p0rzjkya.js → cli-m5a9m0ak.js} +32 -13
  66. package/dist/{cli-fzcn3d87.js → cli-m70bajzr.js} +3 -3
  67. package/dist/{cli-w1zwctj2.js → cli-mtnj4fwa.js} +11 -5
  68. package/dist/{cli-gpsz7g88.js → cli-mvjz5an3.js} +16 -12
  69. package/dist/{cli-hcpj2xqz.js → cli-n7asmce6.js} +225 -3
  70. package/dist/{cli-y561h5a9.js → cli-nn6vx2mq.js} +5 -5
  71. package/dist/cli-nq677csy.js +140 -0
  72. package/dist/{cli-a5ebc95n.js → cli-pfk92eqz.js} +18 -15
  73. package/dist/{cli-p6zs9h4y.js → cli-rr7zx19j.js} +767 -249
  74. package/dist/{cli-qgf8emrn.js → cli-sqma6vw1.js} +10 -7
  75. package/dist/{cli-0xk505e8.js → cli-sxgtf5fw.js} +1 -1
  76. package/dist/{cli-nzfnt2gs.js → cli-tf1n0r0b.js} +1 -1
  77. package/dist/{cli-qqzmjxkf.js → cli-v49fkghp.js} +11 -6
  78. package/dist/{cli-x77gen2p.js → cli-w2656ka1.js} +7 -7
  79. package/dist/{cli-5kqnemen.js → cli-yvy48785.js} +1 -1
  80. package/dist/{cli-8s5wx3nz.js → cli-zqne1qcj.js} +44 -17
  81. package/dist/cli.js +22 -22
  82. package/dist/{codex-adapter-n8ka66vf.js → codex-adapter-d95q4qsn.js} +7 -7
  83. package/dist/{codex-hook-e2he7aca.js → codex-hook-brpnycn5.js} +1 -1
  84. package/dist/{codex-login-rn7c5gxt.js → codex-login-8cg0vhf2.js} +1 -1
  85. package/dist/{codex-session-runner-fsebts37.js → codex-session-runner-gdwd8h0c.js} +8 -8
  86. package/dist/{commands-t04rt2pc.js → commands-jqmgk54b.js} +2 -2
  87. package/dist/{controller-rgna04r2.js → controller-z3jq589f.js} +30 -4
  88. package/dist/{controllers-connect-bqm1rtft.js → controllers-connect-r2za39ef.js} +23 -23
  89. package/dist/{cursor-adapter-swr2k95y.js → cursor-adapter-4mr4jgkw.js} +2 -3
  90. package/dist/{db-a4m7haw0.js → db-ppv2tze7.js} +3 -3
  91. package/dist/{db-24ck09xy.js → db-w36wwb5g.js} +4 -2
  92. package/dist/{devin-adapter-4ycy4vrf.js → devin-adapter-byen2cxt.js} +1 -1
  93. package/dist/{dispatcher-nwf9ss0q.js → dispatcher-pv5h77vf.js} +20 -20
  94. package/dist/{docker-nfy2gc8t.js → docker-fdzyewpz.js} +4 -4
  95. package/dist/{dsh-adapter-kpdnhjst.js → dsh-adapter-d4pdpb3r.js} +2 -3
  96. package/dist/{e2b-9gkdhm3c.js → e2b-222hsajc.js} +2 -2
  97. package/dist/{e2b-cjtf8k1z.js → e2b-fn3zacvt.js} +2 -2
  98. package/dist/{easter-egg-3d-e4qv8dxj.js → easter-egg-3d-4sp4dvmc.js} +1 -1
  99. package/dist/{event-bus-3z78ep5n.js → event-bus-pghg8hqy.js} +1 -1
  100. package/dist/{execute-0xpz8950.js → execute-jev839y1.js} +1 -1
  101. package/dist/{external-channel-j1e2p34p.js → external-channel-y6nkzhnn.js} +2 -2
  102. package/dist/{grok-adapter-qtjz0whk.js → grok-adapter-t08b9ntm.js} +10 -10
  103. package/dist/handlers-eqsnmv95.js +41 -0
  104. package/dist/{heartbeat-vtesda5d.js → heartbeat-vn31xwdk.js} +23 -23
  105. package/dist/{hook-b2hhj6rd.js → hook-6d0zbvvt.js} +6 -5
  106. package/dist/{hook-8wqaszda.js → hook-cpjs8q51.js} +13 -7
  107. package/dist/{http-mxcqhhcs.js → http-9c6medda.js} +1085 -136
  108. package/dist/{index-spwxjgay.js → index-38t35h0n.js} +20 -20
  109. package/dist/{index-1r8wfpzs.js → index-g6k9tctj.js} +1 -1
  110. package/dist/{index-srg522m6.js → index-k0yt1tvq.js} +20 -20
  111. package/dist/{index-31ceyf42.js → index-pkma1yf8.js} +1 -1
  112. package/dist/{index-n1vbvta9.js → index-qhjf2htm.js} +29 -24
  113. package/dist/index-yqgbfgaj.js +43 -0
  114. package/dist/{keepalive-dsd8rtgx.js → keepalive-em0117bp.js} +4 -4
  115. package/dist/lead-23e7z59t.js +79 -0
  116. package/dist/{maintenance-jqmqwnet.js → maintenance-kbme3qy9.js} +1 -1
  117. package/dist/{oauth-refresh-sweep-q2c3bnvm.js → oauth-refresh-sweep-xysj4yse.js} +3 -3
  118. package/dist/{onboard-w4yd7s8t.js → onboard-p6q0vz97.js} +3 -3
  119. package/dist/{opencode-adapter-9tppvxar.js → opencode-adapter-esv3k9yn.js} +7 -7
  120. package/dist/{otel-impl-f36byzbd.js → otel-impl-54qhqh1z.js} +2 -2
  121. package/dist/{pi-mono-adapter-tqsge1ay.js → pi-mono-adapter-mymbwhj0.js} +41 -14
  122. package/dist/{pricing-refresh-xvak5p4v.js → pricing-refresh-yb75wv33.js} +3 -3
  123. package/dist/{rbac-roles-gfn30fb8.js → rbac-roles-1vp2mw4p.js} +2 -2
  124. package/dist/{rbac-roles-682k2mt5.js → rbac-roles-dexhc9x8.js} +1 -1
  125. package/dist/render-v2-tjay5hhf.js +16 -0
  126. package/dist/{resume-2dvq348g.js → resume-8ayf37g5.js} +11 -9
  127. package/dist/{runtime-bt5pkpm1.js → runtime-hqe5cqcd.js} +1 -1
  128. package/dist/{session-access-7f21ekq9.js → session-access-fdhp987s.js} +4 -4
  129. package/dist/session-source-backfill-qgtc86z1.js +110 -0
  130. package/dist/{setup-epffxtbk.js → setup-4rrmqcq3.js} +1 -1
  131. package/dist/{virtual-modules-mnfbh5mr.js → virtual-modules-52km00d6.js} +2 -2
  132. package/dist/{work-objects-xz1a5rqk.js → work-objects-p28fgd70.js} +23 -23
  133. package/dist/worker-e3w7vye1.js +79 -0
  134. package/dist/{x-pbpezr0s.js → x-wxrzvzx8.js} +2 -2
  135. package/openapi.json +1323 -16
  136. package/package.json +5 -5
  137. package/plugin/commands/create-pr.md +2 -2
  138. package/plugin/pi-skills/create-pr/SKILL.md +2 -2
  139. package/src/assets/source-key.ts +95 -0
  140. package/src/be/db/api-keys.ts +80 -0
  141. package/src/be/db/approvals.ts +48 -0
  142. package/src/be/db/session-labels.ts +28 -0
  143. package/src/be/db/session-moves.ts +5 -6
  144. package/src/be/db/session-tree.ts +153 -14
  145. package/src/be/db/tasks/read.ts +11 -0
  146. package/src/be/db/tasks/write.ts +21 -6
  147. package/src/be/db/workflow-idempotency.ts +183 -0
  148. package/src/be/db/workflow-runs.ts +500 -7
  149. package/src/be/db-retention.ts +61 -6
  150. package/src/be/db.ts +126 -131
  151. package/src/be/memory/providers/openai-embedding.ts +5 -1
  152. package/src/be/migrations/242_workflow_idempotency_keys.sql +40 -0
  153. package/src/be/migrations/244_api_key_validation.sql +4 -0
  154. package/src/be/onboarding.ts +4 -0
  155. package/src/be/scripts/typecheck.ts +1 -1
  156. package/src/be/sealed-json.ts +1 -0
  157. package/src/be/seed-scripts/catalog/compound-insights.inline.ts +2 -2
  158. package/src/be/seed-scripts/catalog/compound-insights.ts +2 -2
  159. package/src/be/seed-skills/bundled-files.generated.json +1 -1
  160. package/src/be/session-source-backfill.ts +163 -0
  161. package/src/be/sql-connections.ts +7 -1
  162. package/src/be/swarm-config-guard.ts +3 -0
  163. package/src/be/users.ts +9 -0
  164. package/src/comb/review-batch.ts +28 -1
  165. package/src/comb/templates.ts +7 -2
  166. package/src/commands/claude-managed-setup.ts +7 -1
  167. package/src/commands/controller.ts +33 -0
  168. package/src/commands/credential-refresh.ts +76 -1
  169. package/src/commands/credential-wait.ts +2 -2
  170. package/src/commands/provider-credentials.ts +210 -170
  171. package/src/commands/runner.ts +31 -6
  172. package/src/extensions/apply-task-create.ts +64 -11
  173. package/src/extensions/contract-types.generated.ts +1 -1
  174. package/src/extensions/contract.ts +30 -0
  175. package/src/extensions/dispatcher.ts +4 -0
  176. package/src/extensions/post-bridge.ts +8 -0
  177. package/src/hooks/context-bound-note.ts +196 -0
  178. package/src/hooks/hook.ts +12 -0
  179. package/src/http/all-routes.ts +2 -0
  180. package/src/http/api-keys.ts +53 -0
  181. package/src/http/assets.ts +15 -0
  182. package/src/http/codex-oauth-accounts.ts +191 -0
  183. package/src/http/comb.ts +15 -2
  184. package/src/http/config.ts +49 -17
  185. package/src/http/core.ts +6 -0
  186. package/src/http/fleet-benchmark.ts +5 -2
  187. package/src/http/idempotency-key.ts +117 -0
  188. package/src/http/index.ts +11 -0
  189. package/src/http/integrations.ts +5 -1
  190. package/src/http/kv.ts +8 -3
  191. package/src/http/onboarding.ts +6 -1
  192. package/src/http/pool-keys.ts +354 -0
  193. package/src/http/sessions.ts +37 -12
  194. package/src/http/stats.ts +1 -0
  195. package/src/http/status.ts +26 -12
  196. package/src/http/tasks.ts +3 -0
  197. package/src/http/used-by.ts +7 -2
  198. package/src/http/workflows.ts +207 -33
  199. package/src/integrations/chat-sdk/inbound.ts +27 -0
  200. package/src/kv-reserved-namespaces.ts +19 -0
  201. package/src/prompts/context-bound-note.ts +48 -0
  202. package/src/prompts/session-templates.ts +25 -1
  203. package/src/providers/acp-targets.ts +1 -1
  204. package/src/providers/amp-adapter.ts +30 -8
  205. package/src/providers/claude-adapter.ts +34 -5
  206. package/src/providers/claude-managed-adapter.ts +42 -9
  207. package/src/providers/claude-sdk-session.ts +10 -0
  208. package/src/providers/claude-session-events.ts +13 -0
  209. package/src/providers/codex-adapter.ts +83 -11
  210. package/src/providers/opencode-adapter.ts +18 -0
  211. package/src/providers/pi-mono-adapter.ts +35 -0
  212. package/src/runtime-providers/docker.ts +6 -2
  213. package/src/scheduler/scheduler.ts +3 -2
  214. package/src/scripts-runtime/swarm-sdk.ts +7 -1
  215. package/src/scripts-runtime/types/stdlib.d.ts +1 -1
  216. package/src/scripts-runtime/types/swarm-extension.d.ts +52 -8
  217. package/src/scripts-runtime/types/swarm-sdk.d.ts +1 -1
  218. package/src/slack/assistant.ts +7 -0
  219. package/src/slack/channel-labels.ts +74 -0
  220. package/src/slack/handlers.ts +8 -0
  221. package/src/slack/inbound-files.ts +5 -2
  222. package/src/slack/thread-buffer.ts +4 -0
  223. package/src/tasks/sibling-awareness.ts +12 -3
  224. package/src/telemetry-context.ts +5 -6
  225. package/src/telemetry-identity.ts +3 -3
  226. package/src/tests/amp-adapter.test.ts +97 -0
  227. package/src/tests/api-keys-validation.test.ts +170 -0
  228. package/src/tests/approval-requests.test.ts +10 -7
  229. package/src/tests/approval-sweeps.test.ts +12 -6
  230. package/src/tests/base-prompt.test.ts +1 -1
  231. package/src/tests/claude-hook-output.test.ts +79 -1
  232. package/src/tests/claude-managed-adapter.test.ts +321 -0
  233. package/src/tests/claude-routes-e2e.test.ts +7 -2
  234. package/src/tests/codex-adapter.test.ts +163 -0
  235. package/src/tests/codex-credential-pools.test.ts +120 -0
  236. package/src/tests/codex-gateway-route.test.ts +165 -0
  237. package/src/tests/codex-oauth-accounts.test.ts +357 -0
  238. package/src/tests/comb-review-batch.test.ts +63 -2
  239. package/src/tests/config-pool-keys.test.ts +533 -0
  240. package/src/tests/context-bound-note.test.ts +269 -0
  241. package/src/tests/credential-check.test.ts +290 -2
  242. package/src/tests/credential-refresh.test.ts +172 -1
  243. package/src/tests/db-retention.test.ts +9 -3
  244. package/src/tests/db-task-read-contract.test.ts +1 -0
  245. package/src/tests/db-task-write-contract.test.ts +1 -3
  246. package/src/tests/docs-index-footprint.test.js +3 -3
  247. package/src/tests/extensions-pre-task.test.ts +325 -0
  248. package/src/tests/fetch-resolved-env.test.ts +17 -0
  249. package/src/tests/fixtures/extensions/record-blocks/hooks.ts +10 -0
  250. package/src/tests/fixtures/extensions/record-blocks/manifest.json +7 -0
  251. package/src/tests/fixtures/extensions/record-task-create/hooks.ts +9 -0
  252. package/src/tests/fixtures/extensions/record-task-create/manifest.json +7 -0
  253. package/src/tests/fixtures/fake-amp.ts +22 -8
  254. package/src/tests/fixtures/held-template-render.ts +42 -0
  255. package/src/tests/fixtures/workflow-idempotency-trigger.child.ts +73 -0
  256. package/src/tests/fleet-benchmark.test.ts +8 -0
  257. package/src/tests/get-workflow-run-tool.test.ts +98 -0
  258. package/src/tests/integrations-http.test.ts +32 -2
  259. package/src/tests/internal-ai/complete-structured.test.ts +37 -1
  260. package/src/tests/internal-ai/credentials.test.ts +23 -0
  261. package/src/tests/kv-http.test.ts +32 -0
  262. package/src/tests/kv-tool.test.ts +25 -0
  263. package/src/tests/multi-runtime-registration.test.ts +12 -12
  264. package/src/tests/onboarding.test.ts +108 -1
  265. package/src/tests/openai-embedding-credentials.test.ts +35 -0
  266. package/src/tests/openapi-route-headers.test.ts +2 -0
  267. package/src/tests/opencode-adapter.test.ts +134 -0
  268. package/src/tests/openrouter-attribution-call-sites.test.ts +2 -2
  269. package/src/tests/org-website.test.ts +36 -0
  270. package/src/tests/pi-mono-adapter.test.ts +105 -0
  271. package/src/tests/prompt-template-session.test.ts +4 -3
  272. package/src/tests/provider-key-probes.test.ts +181 -0
  273. package/src/tests/rbac-e2e-helpers.test.ts +88 -1
  274. package/src/tests/rbac-e2e-helpers.ts +36 -11
  275. package/src/tests/runner-push-delivery.test.ts +25 -0
  276. package/src/tests/runtime-controller-liveness.test.ts +133 -0
  277. package/src/tests/runtime-providers-docker.test.ts +2 -0
  278. package/src/tests/script-connections.test.ts +5 -0
  279. package/src/tests/script-run-config-scope.test.ts +91 -3
  280. package/src/tests/script-runs-retention.test.ts +212 -0
  281. package/src/tests/sdk-allowlist.test.ts +39 -0
  282. package/src/tests/session-logs.test.ts +70 -0
  283. package/src/tests/session-source-backfill.test.ts +429 -0
  284. package/src/tests/session-source-keys.test.ts +236 -0
  285. package/src/tests/session-source-labels.test.ts +419 -0
  286. package/src/tests/sessions-detail-batch.test.ts +2 -0
  287. package/src/tests/sessions-move.test.ts +131 -0
  288. package/src/tests/sessions-tree.test.ts +336 -2
  289. package/src/tests/slack-inbound-files.test.ts +103 -23
  290. package/src/tests/status.test.ts +101 -18
  291. package/src/tests/tasks-workflow-run-filter.test.ts +146 -0
  292. package/src/tests/test-net.ts +31 -0
  293. package/src/tests/transcription.test.ts +8 -0
  294. package/src/tests/used-by-route.test.ts +11 -0
  295. package/src/tests/workflow-cascade-cancel.test.ts +1341 -0
  296. package/src/tests/workflow-foreach-supersede-retry.test.ts +488 -0
  297. package/src/tests/workflow-http-v2.test.ts +131 -0
  298. package/src/tests/workflow-idempotency.test.ts +915 -0
  299. package/src/tests/workflow-step-order.test.ts +92 -0
  300. package/src/tests/workflow-sub-workflow.test.ts +30 -0
  301. package/src/tools/get-tasks.ts +8 -0
  302. package/src/tools/kv/kv-read-auth.ts +4 -2
  303. package/src/tools/task-action.ts +1 -1
  304. package/src/tools/workflows/cancel-workflow-run.ts +1 -1
  305. package/src/tools/workflows/get-workflow-run.ts +14 -4
  306. package/src/types.ts +24 -0
  307. package/src/utils/company-profile.ts +51 -1
  308. package/src/utils/context-window.ts +8 -6
  309. package/src/utils/credentials.ts +5 -2
  310. package/src/utils/internal-ai/complete-structured.ts +5 -0
  311. package/src/utils/internal-ai/credentials.ts +4 -3
  312. package/src/utils/provider-key-probes.ts +328 -0
  313. package/src/utils/transcription.ts +4 -1
  314. package/src/workflows/approval-cancel.ts +15 -13
  315. package/src/workflows/approval-notifications.ts +5 -1
  316. package/src/workflows/checkpoint.ts +6 -3
  317. package/src/workflows/engine.ts +30 -8
  318. package/src/workflows/executors/foreach.ts +2 -2
  319. package/src/workflows/executors/sub-workflow.ts +8 -1
  320. package/src/workflows/foreach-driver.ts +10 -3
  321. package/src/workflows/foreach-join.ts +29 -6
  322. package/src/workflows/recovery.ts +6 -1
  323. package/src/workflows/resume.ts +168 -56
  324. package/src/workflows/retry-poller.ts +49 -3
  325. package/src/workflows/task-step-routing.ts +29 -7
  326. package/templates/ai-toolbox.manifest.json +8 -8
  327. package/templates/community/open-prompt-showreel/PLAYBOOK.md +5 -6
  328. package/templates/community/open-prompt-showreel/lead-prompt.md +1 -1
  329. package/templates/community/open-prompt-showreel/skills/open-prompt-showreel/SKILL.md +4 -4
  330. package/templates/skills/agent-browser/SKILL.md +4 -4
  331. package/templates/skills/agent-browser/content.md +4 -4
  332. package/templates/skills/code-quality/config.json +1 -1
  333. package/templates/skills/code-quality/content.md +2 -2
  334. package/templates/skills/delegate-work/content.md +29 -25
  335. package/templates/skills/delegate-work/files/scripts/codex-exec.sh +5 -5
  336. package/templates/skills/qa/content.md +2 -2
  337. package/templates/skills/researching/content.md +4 -0
  338. package/templates/skills/swarm-scripts/SKILL.md +1 -0
  339. package/templates/skills/swarm-scripts/content.md +1 -0
  340. package/templates/skills/work-on-task/SKILL.md +1 -1
  341. package/templates/skills/work-on-task/content.md +1 -1
  342. package/dist/cli-7421jzsw.js +0 -84
  343. package/dist/cli-e45e4m6b.js +0 -413
  344. package/dist/cli-zw88zjba.js +0 -307
  345. package/dist/handlers-19xr6dnz.js +0 -41
  346. package/dist/index-kw2mmat7.js +0 -43
  347. package/dist/lead-zyerk1x2.js +0 -79
  348. package/dist/render-v2-hgytz8nn.js +0 -12
  349. package/dist/worker-42t8emjt.js +0 -79
@@ -0,0 +1,48 @@
1
+ // Worker-side hooks do not load base-prompt, which normally registers these
2
+ // code-default templates.
3
+ import "./session-templates.ts";
4
+ import { resolveTemplateAsync, resolveTemplateFromCode } from "./resolver.ts";
5
+
6
+ const CONTEXT_BOUND_NOTE_TEMPLATE = "system.agent.context.bound_note";
7
+
8
+ /**
9
+ * `contextShare` for the note: " (21% of the 1,000,000-token window)", or ""
10
+ * when the model's window is unknown. Never a percent of the 200k fallback.
11
+ */
12
+ function contextShare(contextTokens: number, model: string | undefined): string {
13
+ if (!model) return "";
14
+ try {
15
+ // Lazy and synchronous: the catalog snapshot is large and the Claude hook
16
+ // process loads this module on every tool call, but renders the note at
17
+ // most once. Sync so in-process sessions render no later than before.
18
+ const { clampContextPercent, getKnownContextWindowSize } =
19
+ require("../utils/context-window.ts") as typeof import("../utils/context-window.ts");
20
+ const window = getKnownContextWindowSize(model);
21
+ const percent = clampContextPercent(contextTokens, window);
22
+ if (!window || percent === null) return "";
23
+ return ` (${Math.round(percent)}% of the ${window.toLocaleString("en-US")}-token window)`;
24
+ } catch {
25
+ return "";
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Render the one-time context-bound note. `model` is the session's model, for
31
+ * the window share. Returns "" when an operator disabled the template; falls
32
+ * back to the code default if resolution fails.
33
+ */
34
+ export async function renderContextBoundNote(
35
+ contextTokens: number,
36
+ model?: string,
37
+ ): Promise<string> {
38
+ const variables = {
39
+ contextTokens: Math.round(contextTokens).toLocaleString("en-US"),
40
+ contextShare: contextShare(contextTokens, model),
41
+ };
42
+ try {
43
+ const result = await resolveTemplateAsync(CONTEXT_BOUND_NOTE_TEMPLATE, variables);
44
+ return result.skipped ? "" : result.text;
45
+ } catch {
46
+ return resolveTemplateFromCode(CONTEXT_BOUND_NOTE_TEMPLATE, variables).text;
47
+ }
48
+ }
@@ -202,7 +202,7 @@ agent-fs is the shared drive between agents and people. Documents (reports, dige
202
202
  Pages: only for polished artifacts shared with a wider audience or explicitly requested; see \`pages\` skill.
203
203
  A tool a person will use, with data and actions: build an app. See the \`apps\` skill.
204
204
  Link env: \`APP_URL\` for pages, \`MCP_BASE_URL\` for the API, \`AGENT_FS_LIVE_URL\` for files. Report missing variables.
205
- For a file anyone outside the swarm opens, use an \`agent-fs share-create\` link; \`AGENT_FS_LIVE_URL\` links are for signed-in teammates.
205
+ Give people the live app link \`\${AGENT_FS_LIVE_URL}/file/~/<org>/<drive>/<path>\`. Make an \`agent-fs share-create\` link only when the requester asks for one or the reader has no agent-fs login.
206
206
  `,
207
207
  variables: [],
208
208
  category: "system",
@@ -353,6 +353,30 @@ Task: {{task}}{{progressLine}}
353
353
  category: "system",
354
354
  });
355
355
 
356
+ /**
357
+ * One-time note injected into a worker session once its latest main-thread
358
+ * request crosses CONTEXT_BOUND_NOTE_TOKENS (`renderContextBoundNote`, via
359
+ * `src/hooks/context-bound-note.ts`).
360
+ */
361
+ registerTemplate({
362
+ eventType: "system.agent.context.bound_note",
363
+ header: "",
364
+ defaultBody:
365
+ "Context is {{contextTokens}} tokens{{contextShare}}. Keep this task bounded: finish the current step, store-progress, and complete or defer instead of starting new exploration.",
366
+ variables: [
367
+ {
368
+ name: "contextTokens",
369
+ description: "Prompt size of the latest request (input + cache read + cache write tokens)",
370
+ },
371
+ {
372
+ name: "contextShare",
373
+ description:
374
+ 'How full the model\'s context window is, e.g. " (21% of the 1,000,000-token window)". Empty when the window is unknown',
375
+ },
376
+ ],
377
+ category: "system",
378
+ });
379
+
356
380
  /**
357
381
  * First message of a cursor session on the first-message path. Cursor keeps
358
382
  * its own system prompt there, so the swarm's rides on top of the task prompt.
@@ -359,7 +359,7 @@ const copilotTargetProfile: AcpTargetProfile = {
359
359
  },
360
360
  };
361
361
 
362
- /** Qwen Code's `--auth-type` choices (0.26.0). `qwen-oauth` needs a browser, so it is left out. */
362
+ /** Qwen Code's `--auth-type` choices (0.26.1). `qwen-oauth` needs a browser, so it is left out. */
363
363
  const QWEN_AUTH_TYPES = ["openai", "openai-responses", "anthropic", "gemini", "vertex-ai"] as const;
364
364
 
365
365
  // Qwen Code is a Gemini CLI fork: QWEN_SYSTEM_MD replaces its built-in prompt
@@ -2,6 +2,7 @@ import { existsSync, readFileSync, renameSync, rmSync, writeFileSync } from "nod
2
2
  import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
+ import { contextBoundNoteThreshold, createContextBoundNote } from "../hooks/context-bound-note";
5
6
  import {
6
7
  type AmpMode,
7
8
  type AmpModelSelection,
@@ -44,7 +45,7 @@ import type {
44
45
  * default; the image installs exactly this version and the per-task settings
45
46
  * set `amp.updates.mode: "disabled"`. Bump it deliberately, with a live run.
46
47
  */
47
- export const AMP_PACKAGE = "@ampcode/cli@0.0.1792756861-g6187a2";
48
+ export const AMP_PACKAGE = "@ampcode/cli@0.0.1792929650-g000512";
48
49
 
49
50
  /** MCP server name. Amp exposes its tools as `agent_swarm` / `store_progress` (dashes become underscores). */
50
51
  const AMP_MCP_SERVER_NAME = "agent-swarm";
@@ -442,6 +443,8 @@ interface QueuedSteer {
442
443
  * answer from the model that received it settles the steer.
443
444
  */
444
445
  receiver?: string | null;
446
+ /** The swarm's own note: rides a tool result or is dropped, never replayed as a new turn. */
447
+ internal?: boolean;
445
448
  resolve: (result: SteerDeliveryResult) => void;
446
449
  }
447
450
 
@@ -486,6 +489,8 @@ class AmpSession implements ProviderSession {
486
489
  private steeringSeq = 0;
487
490
  /** Accepted steering not yet consumed, by inbox file name. Each settles exactly once. */
488
491
  private steers = new Map<string, QueuedSteer>();
492
+ /** Fed each top-level request's prompt size; queues the one-time context-bound note. */
493
+ private readonly observeContextBound: (contextTokens: number | undefined) => Promise<void>;
489
494
 
490
495
  constructor(
491
496
  private proc: Bun.Subprocess<"pipe", "pipe", "pipe">,
@@ -523,6 +528,15 @@ class AmpSession implements ProviderSession {
523
528
  });
524
529
  }
525
530
  };
531
+ // The plugin's `tool.result` hook carries queued steering mid-turn; a note
532
+ // no tool result took is dropped at turn end (`onTurnEnd`).
533
+ this.observeContextBound = createContextBoundNote({
534
+ threshold: contextBoundNoteThreshold(run.env),
535
+ // A mode names no model in advance, so only a pinned model gets a window share.
536
+ model: () => run.selection.pin,
537
+ canDeliver: () => !this.inputClosed && !this.aborted,
538
+ inject: (note) => this.queueSteering(note, true),
539
+ });
526
540
  this.completion = this.runSession(prompt);
527
541
  }
528
542
 
@@ -553,13 +567,13 @@ class AmpSession implements ProviderSession {
553
567
  * check and the rename, no turn end can drain the inbox and close input, so
554
568
  * a message is either visible to the next drain or refused.
555
569
  */
556
- private queueSteering(text: string): Promise<SteerDeliveryResult> {
570
+ private queueSteering(text: string, internal = false): Promise<SteerDeliveryResult> {
557
571
  const name = `${String(++this.steeringSeq).padStart(6, "0")}.json`;
558
572
  const temp = join(this.run.steeringInbox, `.${name}.tmp`);
559
573
  writeFileSync(temp, JSON.stringify(text), { mode: 0o600 });
560
574
  renameSync(temp, join(this.run.steeringInbox, name));
561
575
  return new Promise((resolve) => {
562
- this.steers.set(name, { text, via: "inbox", resolve });
576
+ this.steers.set(name, { text, via: "inbox", internal, resolve });
563
577
  });
564
578
  }
565
579
 
@@ -631,8 +645,8 @@ class AmpSession implements ProviderSession {
631
645
  * Claim the messages no tool result carried, with the plugin's rename
632
646
  * protocol (`.json -> .stdin`). They stay open until Amp echoes them.
633
647
  */
634
- private takeSteering(): { name: string; text: string }[] {
635
- const taken: { name: string; text: string }[] = [];
648
+ private takeSteering(): { name: string; text: string; internal?: boolean }[] {
649
+ const taken: { name: string; text: string; internal?: boolean }[] = [];
636
650
  for (const [name, steer] of [...this.steers].sort(([a], [b]) => a.localeCompare(b))) {
637
651
  if (steer.via !== "inbox") continue;
638
652
  try {
@@ -641,7 +655,7 @@ class AmpSession implements ProviderSession {
641
655
  continue; // The plugin took it.
642
656
  }
643
657
  steer.via = "stdin";
644
- taken.push({ name, text: steer.text });
658
+ taken.push({ name, text: steer.text, internal: steer.internal });
645
659
  }
646
660
  return taken;
647
661
  }
@@ -704,11 +718,16 @@ class AmpSession implements ProviderSession {
704
718
  /**
705
719
  * A top-level assistant message with no tool call ends the turn. Steering
706
720
  * that arrived after the last tool result reached no hook, so it goes in as
707
- * the next user message and starts another turn.
721
+ * the next user message and starts another turn. The swarm's own note is
722
+ * withdrawn instead: it must not start a turn.
708
723
  */
709
724
  private onTurnEnd(): void {
710
725
  if (this.inputClosed) return;
711
- for (const { name, text } of this.takeSteering()) {
726
+ for (const { name, text, internal } of this.takeSteering()) {
727
+ if (internal) {
728
+ this.settleSteer(name, { delivered: false, reason: "no tool result carried the note" });
729
+ continue;
730
+ }
712
731
  this.writeInput(text).catch((error) => {
713
732
  this.settleSteer(name, {
714
733
  delivered: false,
@@ -817,6 +836,9 @@ class AmpSession implements ProviderSession {
817
836
  });
818
837
  // The window is not in the stream; the final snapshot after the export carries it.
819
838
  if (used > 0) this.emitContext(used, output, null);
839
+ // Only when a tool result follows to carry the note; the turn end drops
840
+ // a note no tool result carried.
841
+ if (topLevel && calledTool) void this.observeContextBound(input + cacheRead + cacheCreation);
820
842
  }
821
843
  if (topLevel && !calledTool && message.stop_reason !== "tool_use") this.onTurnEnd();
822
844
  }
@@ -17,6 +17,11 @@ import { dirname, join, resolve } from "node:path";
17
17
  import { promisify } from "node:util";
18
18
  import { deriveDefaultRoute, routeCredentialStatus, routeUnsetEnv } from "@desplega/model-routing";
19
19
  import { type Span, trace } from "@opentelemetry/api";
20
+ import {
21
+ contextBoundNoteMarkerPath,
22
+ contextStatePath,
23
+ recordContextState,
24
+ } from "../hooks/context-bound-note";
20
25
  import {
21
26
  type RunStopHookSessionSummaryOpts,
22
27
  runStopHookSessionSummarySubprocess,
@@ -130,10 +135,17 @@ async function writeTaskFile(key: string | number, data: TaskFileData): Promise<
130
135
  }
131
136
 
132
137
  export async function cleanupTaskFile(key: string | number): Promise<void> {
133
- try {
134
- await unlink(getTaskFilePath(key));
135
- } catch {
136
- // File might already be deleted or never created
138
+ const taskFilePath = getTaskFilePath(key);
139
+ for (const path of [
140
+ taskFilePath,
141
+ contextStatePath(taskFilePath),
142
+ contextBoundNoteMarkerPath(taskFilePath),
143
+ ]) {
144
+ try {
145
+ await unlink(path);
146
+ } catch {
147
+ // File might already be deleted or never created
148
+ }
137
149
  }
138
150
  }
139
151
 
@@ -909,6 +921,8 @@ class ClaudeSession implements ProviderSession {
909
921
  private appliedReasoningEffort: ReasoningEffort | null;
910
922
  /** Last non-empty assistant text seen; surfaced as ProviderResult.output — same pattern as pi-mono/claude-managed. */
911
923
  private lastAssistantText = "";
924
+ /** Last value written to the context state file read by the context-bound note hook. */
925
+ private lastContextTokens: number | undefined;
912
926
  /** Per-session stream-json transcript used by the parent-owned session summarizer. */
913
927
  private transcript: string[];
914
928
  /** Keeps the session heartbeat fresh while Claude idles on background tasks. */
@@ -1263,6 +1277,17 @@ class ClaudeSession implements ProviderSession {
1263
1277
  if (normalized.contextWindowSize) this.contextWindowSize = normalized.contextWindowSize;
1264
1278
  if (normalized.cost) setCost(normalized.cost);
1265
1279
  if (normalized.assistantText) this.lastAssistantText = normalized.assistantText;
1280
+ if (
1281
+ normalized.requestContextTokens !== undefined &&
1282
+ normalized.requestContextTokens !== this.lastContextTokens
1283
+ ) {
1284
+ this.lastContextTokens = normalized.requestContextTokens;
1285
+ recordContextState(
1286
+ getTaskFilePath(this.taskFileKey),
1287
+ normalized.requestContextTokens,
1288
+ this.model,
1289
+ );
1290
+ }
1266
1291
  this.transcript.push(...normalized.transcriptEntries);
1267
1292
  for (const event of normalized.events) this.emit(event);
1268
1293
 
@@ -1420,7 +1445,11 @@ export class ClaudeAdapter implements ProviderAdapter {
1420
1445
  // (headless) or block on the trust dialog (tmux), so seed trust for every session.
1421
1446
  if (isEnvFlagEnabled("CLAUDE_TRUST_PRESEED", true, sourceEnv)) {
1422
1447
  try {
1423
- await preseedClaudeTrustDialog(await resolveClaudeTrustDirs(config.cwd));
1448
+ // Seed the ~/.claude.json the CLI reads: its HOME comes from the session env.
1449
+ await preseedClaudeTrustDialog(
1450
+ await resolveClaudeTrustDirs(config.cwd),
1451
+ sourceEnv.HOME || undefined,
1452
+ );
1424
1453
  } catch (err) {
1425
1454
  console.warn(
1426
1455
  `\x1b[33m[claude]\x1b[0m ${scrubSecrets(`Failed to pre-seed trust for ${config.cwd}: ${err}`)}`,
@@ -56,6 +56,7 @@ import type {
56
56
  BetaManagedAgentsSessionEvent as SessionEvent,
57
57
  } from "@anthropic-ai/sdk/resources/beta/sessions";
58
58
 
59
+ import { contextBoundNoteThreshold, createContextBoundNote } from "../hooks/context-bound-note";
59
60
  import { checkToolLoop } from "../hooks/tool-loop-detection";
60
61
  import {
61
62
  CONTEXT_FORMULA,
@@ -63,6 +64,7 @@ import {
63
64
  computeContextUsedUnified,
64
65
  getContextWindowSize,
65
66
  } from "../utils/context-window";
67
+ import { selectCredential } from "../utils/credentials";
66
68
  import { scrubSecrets } from "../utils/secret-scrubber";
67
69
  import { computeClaudeManagedCostUsd } from "./claude-managed-models";
68
70
  import { getRuntimeFeePerHour } from "./claude-managed-pricing";
@@ -268,6 +270,12 @@ class ClaudeManagedSession implements ProviderSession {
268
270
  private readonly taskId: string | null;
269
271
  private aborted = false;
270
272
  private settled = false;
273
+ /** Prompt size of the latest model request: input + cache read + cache write. */
274
+ private lastRequestContextTokens: number | undefined;
275
+ /** Fed the latest request's prompt size on each tool call; steers the one-time context-bound note. */
276
+ private readonly observeContextBound: (contextTokens: number | undefined) => Promise<void>;
277
+ /** Tool calls the stream started and has not returned a result for. */
278
+ private readonly openToolCalls = new Set<string>();
271
279
 
272
280
  constructor(
273
281
  client: ManagedAgentsClient,
@@ -286,6 +294,14 @@ class ClaudeManagedSession implements ProviderSession {
286
294
  this.completionPromise = new Promise<ProviderResult>((resolve) => {
287
295
  this.resolveCompletion = resolve;
288
296
  });
297
+ this.observeContextBound = createContextBoundNote({
298
+ threshold: contextBoundNoteThreshold(config.env ?? process.env),
299
+ model: () => this.cost.model,
300
+ // A message with no tool call left to return, or after idle or abort,
301
+ // would start another turn.
302
+ canDeliver: () => !this.settled && !this.aborted && this.openToolCalls.size > 0,
303
+ inject: (note) => this.deliverSteering({ mode: "steer", text: note }),
304
+ });
289
305
 
290
306
  // Phase 5: adapter-side swarm hooks. Lower-latency cancellation poll,
291
307
  // tool-loop detection (the handler also calls `checkToolLoop` on
@@ -497,6 +513,11 @@ class ClaudeManagedSession implements ProviderSession {
497
513
  case "agent.tool_use": {
498
514
  const tu = event as BetaManagedAgentsAgentToolUseEvent;
499
515
  this.runToolLoopCheck(tu.name, tu.input);
516
+ // Only on tool calls: a message after the final reply would start another
517
+ // turn. The stream can send the call before its request ends, so this may
518
+ // read the previous request: at most one request late.
519
+ this.openToolCalls.add(tu.id);
520
+ void this.observeContextBound(this.lastRequestContextTokens);
500
521
  this.emit({
501
522
  type: "tool_start",
502
523
  toolCallId: tu.id,
@@ -509,6 +530,8 @@ class ClaudeManagedSession implements ProviderSession {
509
530
  const tu = event as BetaManagedAgentsAgentMCPToolUseEvent;
510
531
  const fqToolName = `${tu.mcp_server_name}:${tu.name}`;
511
532
  this.runToolLoopCheck(fqToolName, tu.input);
533
+ this.openToolCalls.add(tu.id);
534
+ void this.observeContextBound(this.lastRequestContextTokens);
512
535
  this.emit({
513
536
  type: "tool_start",
514
537
  toolCallId: tu.id,
@@ -519,6 +542,7 @@ class ClaudeManagedSession implements ProviderSession {
519
542
  }
520
543
  case "agent.tool_result": {
521
544
  const tr = event as BetaManagedAgentsAgentToolResultEvent;
545
+ this.openToolCalls.delete(tr.tool_use_id);
522
546
  this.emit({
523
547
  type: "tool_end",
524
548
  toolCallId: tr.tool_use_id,
@@ -533,6 +557,7 @@ class ClaudeManagedSession implements ProviderSession {
533
557
  }
534
558
  case "agent.mcp_tool_result": {
535
559
  const tr = event as BetaManagedAgentsAgentMCPToolResultEvent;
560
+ this.openToolCalls.delete(tr.mcp_tool_use_id);
536
561
  this.emit({
537
562
  type: "tool_end",
538
563
  toolCallId: tr.mcp_tool_use_id,
@@ -571,6 +596,8 @@ class ClaudeManagedSession implements ProviderSession {
571
596
  case "span.model_request_end": {
572
597
  const sp = event as BetaManagedAgentsSpanModelRequestEndEvent;
573
598
  const usage = sp.model_usage;
599
+ this.lastRequestContextTokens =
600
+ usage.input_tokens + usage.cache_read_input_tokens + usage.cache_creation_input_tokens;
574
601
  this.cost.inputTokens = (this.cost.inputTokens ?? 0) + usage.input_tokens;
575
602
  this.cost.outputTokens = (this.cost.outputTokens ?? 0) + usage.output_tokens;
576
603
  this.cost.cacheReadTokens =
@@ -836,7 +863,11 @@ export class ClaudeManagedAdapter implements ProviderAdapter {
836
863
  );
837
864
  }
838
865
 
839
- this.apiKey = process.env.ANTHROPIC_API_KEY as string;
866
+ this.apiKey = selectCredential(
867
+ process.env.ANTHROPIC_API_KEY as string,
868
+ undefined,
869
+ "ANTHROPIC_API_KEY",
870
+ ).selected;
840
871
  this.agentId = process.env.MANAGED_AGENT_ID as string;
841
872
  this.environmentId = process.env.MANAGED_ENVIRONMENT_ID as string;
842
873
 
@@ -853,6 +884,14 @@ export class ClaudeManagedAdapter implements ProviderAdapter {
853
884
  }
854
885
 
855
886
  async createSession(config: ProviderSessionConfig): Promise<ProviderSession> {
887
+ // Keep the runner's task selection instead of the container's pool.
888
+ const taskKey = config.env?.ANTHROPIC_API_KEY;
889
+ const client =
890
+ taskKey && this.client instanceof Anthropic
891
+ ? this.client.withOptions({
892
+ apiKey: selectCredential(taskKey, undefined, "ANTHROPIC_API_KEY").selected,
893
+ })
894
+ : this.client;
856
895
  // Native resume is deprecated. Follow-up continuity is delivered via the
857
896
  // context preamble (see src/commands/context-preamble.ts). Any stray
858
897
  // resumeSessionId is logged and ignored — we always create a fresh session.
@@ -916,16 +955,10 @@ export class ClaudeManagedAdapter implements ProviderAdapter {
916
955
  if (vaultIds.length > 0) {
917
956
  createParams.vault_ids = Array.from(new Set(vaultIds));
918
957
  }
919
- const created = await Promise.resolve(this.client.beta.sessions.create(createParams));
958
+ const created = await Promise.resolve(client.beta.sessions.create(createParams));
920
959
  const sessionId = created.id;
921
960
 
922
- return new ClaudeManagedSession(
923
- this.client,
924
- sessionId,
925
- config,
926
- userMessageContent,
927
- seenEventIds,
928
- );
961
+ return new ClaudeManagedSession(client, sessionId, config, userMessageContent, seenEventIds);
929
962
  }
930
963
 
931
964
  /**
@@ -9,6 +9,7 @@ import {
9
9
  type SpawnedProcess,
10
10
  type SpawnOptions,
11
11
  } from "@anthropic-ai/claude-agent-sdk";
12
+ import { recordContextState } from "../hooks/context-bound-note";
12
13
  import type { RunStopHookSessionSummaryOpts } from "../hooks/hook";
13
14
  import { getContextWindowSize } from "../utils/context-window";
14
15
  import {
@@ -316,6 +317,8 @@ class ClaudeSdkSession implements ProviderSession {
316
317
  private contextWindowSize: number;
317
318
  private transcript: string[];
318
319
  private lastAssistantText = "";
320
+ /** Last value written to the context state file read by the context-bound note hook. */
321
+ private lastContextTokens: number | undefined;
319
322
  private lastCost: CostData | undefined;
320
323
  private aborted = false;
321
324
  private abortReason = "cancelled";
@@ -434,6 +437,13 @@ class ClaudeSdkSession implements ProviderSession {
434
437
  if (normalized.contextWindowSize) this.contextWindowSize = normalized.contextWindowSize;
435
438
  if (normalized.cost) this.lastCost = normalized.cost;
436
439
  if (normalized.assistantText) this.lastAssistantText = normalized.assistantText;
440
+ if (
441
+ normalized.requestContextTokens !== undefined &&
442
+ normalized.requestContextTokens !== this.lastContextTokens
443
+ ) {
444
+ this.lastContextTokens = normalized.requestContextTokens;
445
+ recordContextState(this.options.taskFilePath, normalized.requestContextTokens, this.model);
446
+ }
437
447
  this.transcript.push(...normalized.transcriptEntries);
438
448
  for (const event of normalized.events) this.emit(event);
439
449
  trackErrorFromJson(json, this.errorTracker);
@@ -60,6 +60,11 @@ export type NormalizedClaudeMessage = {
60
60
  contextWindowSize?: number;
61
61
  cost?: CostData;
62
62
  assistantText?: string;
63
+ /**
64
+ * Prompt size of the latest main-thread request: input + cache read + cache
65
+ * write tokens. Unset for subagent messages and messages without usage.
66
+ */
67
+ requestContextTokens?: number;
63
68
  isResult: boolean;
64
69
  };
65
70
 
@@ -150,6 +155,7 @@ export function normalizeClaudeMessage(
150
155
  let model: string | undefined;
151
156
  let contextWindowSize: number | undefined;
152
157
  let assistantText: string | undefined;
158
+ let requestContextTokens: number | undefined;
153
159
 
154
160
  if (json.type === "system" && json.subtype === "init" && json.session_id) {
155
161
  sessionId = json.session_id;
@@ -227,6 +233,12 @@ export function normalizeClaudeMessage(
227
233
  outputTokens: usage.output_tokens ?? 0,
228
234
  contextFormula: CONTEXT_FORMULA,
229
235
  });
236
+ if (!json.parent_tool_use_id) {
237
+ requestContextTokens =
238
+ (usage.input_tokens ?? 0) +
239
+ (usage.cache_read_input_tokens ?? 0) +
240
+ (usage.cache_creation_input_tokens ?? 0);
241
+ }
230
242
  }
231
243
  }
232
244
 
@@ -247,6 +259,7 @@ export function normalizeClaudeMessage(
247
259
  contextWindowSize,
248
260
  cost,
249
261
  assistantText,
262
+ requestContextTokens,
250
263
  isResult: json.type === "result",
251
264
  };
252
265
  }