@desplega.ai/agent-swarm 2.4.3 → 2.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (270) hide show
  1. package/dist/{acp-adapter-1885dpr7.js → acp-adapter-2wdkktv6.js} +1 -2
  2. package/dist/{actions-pn76n32q.js → actions-c40ebcm4.js} +18 -18
  3. package/dist/{amp-adapter-af84rx1d.js → amp-adapter-wb67m95z.js} +2 -2
  4. package/dist/{app-6sv8mhzm.js → app-353vre8g.js} +3 -3
  5. package/dist/{assistant-sc2tf825.js → assistant-sj1njh23.js} +21 -21
  6. package/dist/{boot-reembed-y3m0ydzj.js → boot-reembed-b9c3az3c.js} +1 -1
  7. package/dist/{boot-reembed-gvxjs2py.js → boot-reembed-qdkvxeem.js} +1 -1
  8. package/dist/{boot-scrub-sweep-1j9mk05f.js → boot-scrub-sweep-m3wh8eks.js} +2 -2
  9. package/dist/{boot-seeds-37sp626b.js → boot-seeds-j2273s54.js} +4 -4
  10. package/dist/{claude-adapter-rp0jtnwr.js → claude-adapter-m7q0a085.js} +2 -2
  11. package/dist/{claude-managed-adapter-h2y889ge.js → claude-managed-adapter-5ptb6tzs.js} +2 -2
  12. package/dist/{claude-managed-setup-rdt248k7.js → claude-managed-setup-smrqk5j5.js} +3 -3
  13. package/dist/{claude-sdk-session-53rcw5we.js → claude-sdk-session-38xnz21e.js} +8284 -8267
  14. package/dist/{cli-6eyncg0y.js → cli-018r4jq6.js} +34 -6
  15. package/dist/{cli-sds5zzs8.js → cli-1f3qzw6y.js} +78 -12
  16. package/dist/{cli-f0p0f6ja.js → cli-1sp861s4.js} +7 -7
  17. package/dist/{cli-dm8p2dpf.js → cli-1syn2xy1.js} +10 -10
  18. package/dist/{cli-tkf4x6ha.js → cli-37j04k05.js} +11 -11
  19. package/dist/{cli-v87dr6e3.js → cli-3a45zcgm.js} +1 -1
  20. package/dist/{cli-1n9gdg56.js → cli-43x64hv3.js} +4 -4
  21. package/dist/{cli-p0qerd2r.js → cli-4zfqgjc5.js} +2 -2
  22. package/dist/{cli-aa3tb29r.js → cli-7c9qs530.js} +1 -1
  23. package/dist/{cli-9qtjfd60.js → cli-848hxdwj.js} +1 -1
  24. package/dist/{cli-1xsraagq.js → cli-94gwyg7m.js} +8 -8
  25. package/dist/{cli-0dxxwfkt.js → cli-9hstj09h.js} +17 -14
  26. package/dist/{cli-1012xb7j.js → cli-9yqgm9nd.js} +22 -22
  27. package/dist/{cli-pygdsgh8.js → cli-a92r1127.js} +1 -1
  28. package/dist/{cli-8vverzf7.js → cli-ba8ne1es.js} +5 -0
  29. package/dist/{cli-bxrqvpg5.js → cli-be2161h1.js} +7 -7
  30. package/dist/{cli-npfe9t1s.js → cli-bnes4z6b.js} +2 -2
  31. package/dist/{cli-aypbg9r2.js → cli-cxxe61f6.js} +1 -1
  32. package/dist/{cli-vq9gqarq.js → cli-dk44dxec.js} +1 -1
  33. package/dist/{cli-836ehxmt.js → cli-eww120g8.js} +3 -2
  34. package/dist/{cli-a0kcty51.js → cli-f01h25yt.js} +1 -1
  35. package/dist/{cli-mzkwkbdy.js → cli-f0g3pgvf.js} +1 -1
  36. package/dist/{cli-1ma335fz.js → cli-ftc1g5tj.js} +2 -2
  37. package/dist/{cli-4yef8ghv.js → cli-fv5hepyy.js} +3 -3
  38. package/dist/{cli-58vwn100.js → cli-g35m2xwm.js} +4 -4
  39. package/dist/{cli-qje9k2nh.js → cli-g9ypd5en.js} +12 -2
  40. package/dist/{cli-gx0j2khs.js → cli-j99azg3g.js} +3 -3
  41. package/dist/{cli-er83cjbn.js → cli-k8g16gz3.js} +416 -116
  42. package/dist/{cli-qp2m4btv.js → cli-kpw04va0.js} +2 -2
  43. package/dist/{cli-8y99kfey.js → cli-ms85309d.js} +33 -15
  44. package/dist/{cli-kgnkyabk.js → cli-n72rg53p.js} +1555 -645
  45. package/dist/{cli-e4d78xsv.js → cli-p14m2cnp.js} +1 -1
  46. package/dist/{cli-1eszr343.js → cli-qfxc84gh.js} +1 -1
  47. package/dist/{cli-wk28hzqn.js → cli-qwhy2qma.js} +1 -1
  48. package/dist/{cli-73ezfhha.js → cli-st8aw1m6.js} +228 -11
  49. package/dist/{cli-zvbb4n0e.js → cli-tw4p90jb.js} +92 -192
  50. package/dist/{cli-038fga5k.js → cli-v0yrfmdh.js} +148 -183
  51. package/dist/{cli-6aen3ezb.js → cli-v8fjakwf.js} +1 -1
  52. package/dist/{cli-99jez72r.js → cli-w9etnnxk.js} +6 -1
  53. package/dist/{cli-vcgscaan.js → cli-wt0jf9hm.js} +217 -80
  54. package/dist/{cli-s9rr4gr2.js → cli-xpa64rek.js} +1065 -305
  55. package/dist/{cli-h0mgxann.js → cli-z7d29rw9.js} +2 -2
  56. package/dist/cli.js +45 -20
  57. package/dist/{codex-adapter-2zrmab9b.js → codex-adapter-tn6k5mkg.js} +1 -1
  58. package/dist/{codex-session-runner-kbkz62vc.js → codex-session-runner-7vjt7jbw.js} +1 -1
  59. package/dist/{commands-hd574th6.js → commands-t7rz9146.js} +2 -2
  60. package/dist/{controller-pz5mcfg4.js → controller-m2jasma5.js} +2 -2
  61. package/dist/{controllers-connect-5rgq2hfk.js → controllers-connect-9ftpex99.js} +19 -19
  62. package/dist/{cursor-adapter-mgaprq0j.js → cursor-adapter-mjv79e4z.js} +1 -1
  63. package/dist/{db-6nf1207q.js → db-6sfrn9g3.js} +1 -1
  64. package/dist/{db-h06dxp05.js → db-rn673r06.js} +3 -3
  65. package/dist/{dispatcher-zthpy4m1.js → dispatcher-c155xz0p.js} +17 -17
  66. package/dist/{dsh-adapter-64dhw0j7.js → dsh-adapter-3mmszc1x.js} +1 -1
  67. package/dist/{external-channel-x01t7ke6.js → external-channel-35k6tkv8.js} +2 -2
  68. package/dist/{grok-adapter-h21jv594.js → grok-adapter-tfrq7tg1.js} +2 -3
  69. package/dist/handlers-7gw64dxw.js +39 -0
  70. package/dist/{heartbeat-zzfksckz.js → heartbeat-dyg4npkp.js} +20 -20
  71. package/dist/{hook-z4zhzj1f.js → hook-drspbwpe.js} +1 -1
  72. package/dist/{hook-3xfqhh2s.js → hook-x26b31bg.js} +1 -1
  73. package/dist/{http-q813tmya.js → http-pk972xyw.js} +571 -294
  74. package/dist/{index-va3y63es.js → index-6srwvd5b.js} +1 -2
  75. package/dist/{index-x8xbyn1t.js → index-arytgj5q.js} +1 -1
  76. package/dist/{index-wbbs14c5.js → index-bgdyvcnv.js} +17 -17
  77. package/dist/{index-s98037v0.js → index-cbxkmfc5.js} +1 -2
  78. package/dist/{index-c4ykd0f1.js → index-dr94zbnh.js} +13348 -11611
  79. package/dist/{index-m0a4ydqj.js → index-gabbcdn2.js} +17 -17
  80. package/dist/{index-220tk9bw.js → index-jwxkkex2.js} +139 -76
  81. package/dist/index-tfb26zhy.js +41 -0
  82. package/dist/{keepalive-y5t1my7m.js → keepalive-7yrng7px.js} +3 -3
  83. package/dist/{lead-2xwtq66b.js → lead-7e02z839.js} +29 -30
  84. package/dist/{maintenance-ybfsaedv.js → maintenance-e6cemdqt.js} +1 -1
  85. package/dist/{node-3v3f08f7.js → node-de6akczr.js} +10 -9
  86. package/dist/{oauth-refresh-sweep-909jmn12.js → oauth-refresh-sweep-yw3xdbcj.js} +2 -2
  87. package/dist/{onboard-xn6fkkys.js → onboard-0a9y5yrc.js} +2 -2
  88. package/dist/{otel-impl-e6mn0z13.js → otel-impl-trjpkfb7.js} +1 -1
  89. package/dist/{pricing-refresh-ygd362ep.js → pricing-refresh-d2b5my0y.js} +3 -3
  90. package/dist/{rbac-roles-mb470p4e.js → rbac-roles-hey3yv9d.js} +2 -2
  91. package/dist/{rbac-roles-c9axvfnz.js → rbac-roles-nxh5ahwk.js} +2 -2
  92. package/dist/{registry-rxw10xzg.js → registry-ajhexe44.js} +1 -1
  93. package/dist/{render-v2-g0306nh1.js → render-v2-rr3p2atg.js} +3 -3
  94. package/dist/{resume-v315hnq6.js → resume-2efkf1s1.js} +5 -5
  95. package/dist/{session-access-2zg285a1.js → session-access-s2mttxpw.js} +6 -4
  96. package/dist/{setup-a4mtf02k.js → setup-vypma5yt.js} +1 -1
  97. package/dist/{work-objects-9fr0fgtn.js → work-objects-rvhckdkp.js} +20 -20
  98. package/dist/{worker-qae22jeb.js → worker-5snytpbd.js} +29 -30
  99. package/dist/worker-token-xf11yyds.js +136 -0
  100. package/openapi.json +303 -13
  101. package/package.json +8 -8
  102. package/src/apps/action-runner.ts +4 -0
  103. package/src/apps/catalog.generated.json +209 -4
  104. package/src/apps/page-validator.ts +21 -3
  105. package/src/be/chunking.ts +42 -9
  106. package/src/be/db/tasks/draft-text.ts +15 -0
  107. package/src/be/db/tasks/read.ts +14 -1
  108. package/src/be/db.ts +5 -1
  109. package/src/be/memory/index-content.ts +36 -17
  110. package/src/be/memory/providers/openai-embedding.ts +115 -61
  111. package/src/be/memory/providers/sqlite-store.ts +69 -23
  112. package/src/be/memory/reranker.ts +31 -1
  113. package/src/be/memory/search-candidates.ts +47 -0
  114. package/src/be/memory/types.ts +14 -0
  115. package/src/be/migrations/232_agent_session_tokens.sql +41 -0
  116. package/src/be/scripts/typecheck.ts +2 -0
  117. package/src/be/seed-scripts/catalog/heartbeat-jev-gate.ts +116 -55
  118. package/src/be/seed-scripts/index.ts +2 -2
  119. package/src/be/swarm-config-guard.ts +40 -1
  120. package/src/be/task-attachment-store.ts +30 -0
  121. package/src/be/users.ts +169 -12
  122. package/src/cli.tsx +24 -0
  123. package/src/commands/worker-token.ts +164 -0
  124. package/src/extensions/catalog.generated.json +4 -4
  125. package/src/extensions/contract-types.generated.ts +1 -1
  126. package/src/extensions/contract.ts +7 -0
  127. package/src/fs/provider.ts +13 -1
  128. package/src/heartbeat/heartbeat.ts +31 -11
  129. package/src/http/apps.ts +43 -5
  130. package/src/http/codex-oauth-keep-warm.ts +27 -9
  131. package/src/http/config.ts +5 -3
  132. package/src/http/core.ts +2 -0
  133. package/src/http/fs.ts +54 -34
  134. package/src/http/mcp-body.ts +37 -0
  135. package/src/http/mcp-user.ts +3 -5
  136. package/src/http/mcp.ts +6 -7
  137. package/src/http/memory.ts +26 -15
  138. package/src/http/page-proxy.ts +61 -5
  139. package/src/http/pages-public.ts +27 -44
  140. package/src/http/pages.ts +4 -4
  141. package/src/http/script-runs.ts +2 -0
  142. package/src/http/session-access.ts +51 -2
  143. package/src/http/sessions.ts +249 -10
  144. package/src/http/tasks.ts +4 -32
  145. package/src/http/users.ts +12 -1
  146. package/src/integrations/chat-sdk/adapters.ts +7 -3
  147. package/src/integrations/chat-sdk/attachments.ts +90 -12
  148. package/src/integrations/chat-sdk/facts.ts +120 -0
  149. package/src/integrations/chat-sdk/inbound.ts +156 -8
  150. package/src/integrations/chat-sdk/limits.ts +24 -0
  151. package/src/integrations/chat-sdk/outbound-files.ts +186 -0
  152. package/src/integrations/chat-sdk/outbound.ts +234 -4
  153. package/src/integrations/chat-sdk/relay.ts +4 -1
  154. package/src/integrations/chat-sdk/router.ts +28 -2
  155. package/src/integrations/chat-sdk/steering.ts +9 -0
  156. package/src/integrations/chat-sdk/templates.ts +14 -0
  157. package/src/integrations/chat-sdk/thread-buffer.ts +4 -0
  158. package/src/mcp-limits.ts +20 -0
  159. package/src/pages/browser-sdk.ts +8 -3
  160. package/src/pages/feedback-overlay.ts +1 -1
  161. package/src/providers/acp-adapter.ts +33 -13
  162. package/src/providers/acp-swarm-events.ts +1 -1
  163. package/src/providers/amp-adapter.ts +1 -1
  164. package/src/providers/codex-adapter.ts +106 -119
  165. package/src/providers/codex-agents-md.ts +35 -229
  166. package/src/providers/codex-oauth/storage.ts +1 -1
  167. package/src/providers/cursor-adapter.ts +1 -1
  168. package/src/rbac/legacy-policy.ts +3 -1
  169. package/src/rbac/permissions.ts +4 -0
  170. package/src/realtime/transport.ts +1 -2
  171. package/src/script-workflows/workflow-ctx.ts +1 -0
  172. package/src/scripts-runtime/types/stdlib.d.ts +2 -0
  173. package/src/scripts-runtime/types/swarm-extension.d.ts +8 -0
  174. package/src/scripts-runtime/types/swarm-sdk.d.ts +2 -0
  175. package/src/server-user.ts +2 -0
  176. package/src/server.ts +2 -0
  177. package/src/slack/assistant.ts +2 -2
  178. package/src/slack/files.ts +2 -0
  179. package/src/slack/handlers.ts +4 -4
  180. package/src/slack/inbound-files.ts +39 -6
  181. package/src/slack/thread-buffer.ts +2 -1
  182. package/src/tasks/task-terminal-effects.ts +21 -17
  183. package/src/tests/acp-adapter.test.ts +10 -23
  184. package/src/tests/acp-fake-agent.ts +36 -0
  185. package/src/tests/acp-swarm-events.test.ts +1 -1
  186. package/src/tests/agent-session-tokens.test.ts +452 -0
  187. package/src/tests/apps-action-parent-task.test.ts +295 -0
  188. package/src/tests/apps-card-grid.test.ts +197 -0
  189. package/src/tests/apps-catalog-additions.test.ts +120 -0
  190. package/src/tests/apps-tree.test.ts +129 -0
  191. package/src/tests/chat-sdk-attachments-reply.test.ts +52 -0
  192. package/src/tests/chat-sdk-config.test.ts +11 -0
  193. package/src/tests/chat-sdk-facts.test.ts +23 -0
  194. package/src/tests/chat-sdk-inbound.test.ts +558 -4
  195. package/src/tests/chat-sdk-outbound-files.test.ts +652 -0
  196. package/src/tests/codex-adapter.test.ts +167 -242
  197. package/src/tests/codex-oauth-keep-warm.test.ts +85 -1
  198. package/src/tests/config-api-only-keys.test.ts +9 -0
  199. package/src/tests/config-session-auth.test.ts +14 -0
  200. package/src/tests/cors-allowlist.test.ts +1 -1
  201. package/src/tests/docs-index-footprint.test.js +2 -2
  202. package/src/tests/extensions-example-slack-reply-gate.test.ts +262 -91
  203. package/src/tests/grok-adapter.test.ts +3 -3
  204. package/src/tests/heartbeat-checklist.test.ts +33 -0
  205. package/src/tests/heartbeat-jev-gate-credentials.test.ts +44 -0
  206. package/src/tests/heartbeat-jev-gate.test.ts +265 -1
  207. package/src/tests/kv-page-proxy.test.ts +91 -5
  208. package/src/tests/launch-password-rejection.test.ts +2 -2
  209. package/src/tests/mcp-input-caps.test.ts +294 -0
  210. package/src/tests/memory-chunked-search-starvation.test.ts +200 -0
  211. package/src/tests/memory-embedding-input-cap.test.ts +114 -0
  212. package/src/tests/memory.test.ts +14 -0
  213. package/src/tests/migration-232-agent-session-tokens.test.ts +67 -0
  214. package/src/tests/page-guest-session.test.ts +19 -8
  215. package/src/tests/page-proxy-authed.test.ts +1 -1
  216. package/src/tests/page-proxy.test.ts +17 -10
  217. package/src/tests/page-session.test.ts +102 -1
  218. package/src/tests/pages-authed-mode.test.ts +82 -12
  219. package/src/tests/pages-password-mode.test.ts +5 -5
  220. package/src/tests/rbac-engine.test.ts +1 -0
  221. package/src/tests/realtime-transport.test.ts +13 -7
  222. package/src/tests/runtime-child-token-cleanup.test.ts +3 -3
  223. package/src/tests/script-connections.test.ts +2 -0
  224. package/src/tests/script-runs-http.test.ts +84 -0
  225. package/src/tests/scripts-http.test.ts +10 -1
  226. package/src/tests/session-route-posture.test.ts +2 -0
  227. package/src/tests/swarm-config-export-to-env.test.ts +22 -3
  228. package/src/tests/task-audio-transcription.test.ts +299 -0
  229. package/src/tests/task-completion-memory-chunking.test.ts +434 -0
  230. package/src/tests/task-terminal-secret-scrub.test.ts +6 -1
  231. package/src/tests/transcription.test.ts +299 -0
  232. package/src/tests/worker-token-cli.test.ts +76 -0
  233. package/src/tests/workflow-executors.test.ts +4 -2
  234. package/src/tests/workflow-system-one-decision-providers.test.ts +98 -1
  235. package/src/tests/workflow-system-one-decision.test.ts +2 -1
  236. package/src/tests/workflow-system-one-extraction.test.ts +805 -0
  237. package/src/tools/chat-access.ts +10 -0
  238. package/src/tools/chat-post.ts +31 -11
  239. package/src/tools/chat-reply.ts +32 -10
  240. package/src/tools/memory-search.ts +3 -1
  241. package/src/tools/system-one-decide.ts +17 -4
  242. package/src/types.ts +8 -1
  243. package/src/utils/config-env-export.ts +3 -1
  244. package/src/utils/page-session.ts +133 -20
  245. package/src/utils/request-auth-context.ts +2 -1
  246. package/src/utils/transcription.ts +246 -0
  247. package/src/workflows/definition.ts +7 -1
  248. package/src/workflows/engine.ts +18 -12
  249. package/src/workflows/executors/index.ts +1 -0
  250. package/src/workflows/executors/registry.ts +2 -0
  251. package/src/workflows/executors/system-one-decision.ts +84 -262
  252. package/src/workflows/executors/system-one-extract-wire.ts +57 -0
  253. package/src/workflows/executors/system-one-extraction.ts +830 -0
  254. package/src/workflows/executors/system-one-providers.ts +316 -114
  255. package/src/workflows/executors/system-one-transport.ts +264 -0
  256. package/templates/extensions/slack-reply-gate/README.md +24 -22
  257. package/templates/extensions/slack-reply-gate/hooks.ts +146 -95
  258. package/templates/extensions/slack-reply-gate/manifest.json +2 -2
  259. package/templates/official/lead/HEARTBEAT.md +1 -1
  260. package/templates/skills/apps/SKILL.md +31 -7
  261. package/templates/skills/apps/content.md +31 -7
  262. package/templates/skills/chat-sdk/content.md +6 -2
  263. package/templates/skills/code-quality/content.md +2 -1
  264. package/templates/skills/heartbeat-runbook/content.md +8 -8
  265. package/templates/skills/pages/content.md +6 -4
  266. package/templates/skills/swarm-scripts/SKILL.md +2 -2
  267. package/templates/skills/swarm-scripts/content.md +2 -2
  268. package/dist/cli-v1sjhn52.js +0 -7
  269. package/dist/handlers-2qjw434w.js +0 -39
  270. package/dist/index-d0g18bax.js +0 -41
@@ -0,0 +1,136 @@
1
+ import {
2
+ getApiKey,
3
+ init_api_key
4
+ } from "./cli-pax9q4ff.js";
5
+
6
+ // src/commands/worker-token.ts
7
+ init_api_key();
8
+ var WORKER_TOKEN_USAGE = `Usage:
9
+ agent-swarm worker-token <create|rotate|revoke> (--agent-id <id> | --name <name>) [options]
10
+
11
+ Options:
12
+ --agent-id <id> Agent the token is bound to
13
+ --name <name> Agent name. create makes the agent when no agent has this name
14
+ --ttl-days <n> Token lifetime (create, rotate). Default: no expiry
15
+ --grace-sec <n> How long the old token keeps working after rotate (default 300)
16
+ --api-url <url> Swarm API URL (default: MCP_BASE_URL or http://localhost:3013)
17
+ --api-key <key> Operator swarm API key (default: AGENT_SWARM_API_KEY or API_KEY, falling back to 123123)
18
+ -h, --help Show this help`;
19
+ var ACTIONS = new Set(["create", "rotate", "revoke"]);
20
+ function parseWorkerTokenArgs(args) {
21
+ const parsed = { showHelp: false };
22
+ const number = (flag, value, min) => {
23
+ const n = Number(value);
24
+ if (!Number.isInteger(n) || n < min)
25
+ parsed.error = `${flag} must be an integer >= ${min}`;
26
+ return n;
27
+ };
28
+ for (let i = 0;i < args.length; i++) {
29
+ const arg = args[i];
30
+ if (arg === "--help" || arg === "-h")
31
+ parsed.showHelp = true;
32
+ else if (arg === "--agent-id")
33
+ parsed.agentId = args[++i];
34
+ else if (arg === "--name")
35
+ parsed.name = args[++i];
36
+ else if (arg === "--api-url")
37
+ parsed.apiUrl = args[++i];
38
+ else if (arg === "--api-key")
39
+ parsed.apiKey = args[++i];
40
+ else if (arg === "--ttl-days")
41
+ parsed.ttlDays = number(arg, args[++i], 1);
42
+ else if (arg === "--grace-sec")
43
+ parsed.graceSec = number(arg, args[++i], 0);
44
+ else if (!parsed.action && ACTIONS.has(arg))
45
+ parsed.action = arg;
46
+ else
47
+ parsed.error = `Unknown argument: ${arg}`;
48
+ }
49
+ if (parsed.error || parsed.showHelp)
50
+ return parsed;
51
+ if (!parsed.action)
52
+ parsed.error = "Missing action: create, rotate, or revoke";
53
+ else if (!parsed.agentId === !parsed.name)
54
+ parsed.error = "Pass exactly one of --agent-id or --name";
55
+ return parsed;
56
+ }
57
+ async function readError(res) {
58
+ const text = await res.text().catch(() => "");
59
+ try {
60
+ return JSON.parse(text).error ?? text;
61
+ } catch {
62
+ return text;
63
+ }
64
+ }
65
+ async function runWorkerToken(args, deps = {}) {
66
+ const env = deps.env ?? process.env;
67
+ const doFetch = deps.fetch ?? fetch;
68
+ const stdout = deps.stdout ?? ((line) => console.log(line));
69
+ const stderr = deps.stderr ?? ((line) => console.error(line));
70
+ const parsed = parseWorkerTokenArgs(args);
71
+ if (parsed.showHelp) {
72
+ stdout(WORKER_TOKEN_USAGE);
73
+ return 0;
74
+ }
75
+ if (parsed.error) {
76
+ stderr(`${parsed.error}
77
+
78
+ ${WORKER_TOKEN_USAGE}`);
79
+ return 1;
80
+ }
81
+ const apiUrl = (parsed.apiUrl ?? env.MCP_BASE_URL ?? "http://localhost:3013").replace(/\/+$/, "");
82
+ const apiKey = parsed.apiKey ?? (getApiKey(env) || "123123");
83
+ const headers = { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" };
84
+ let agentId = parsed.agentId;
85
+ let name;
86
+ if (!agentId) {
87
+ const res = await doFetch(`${apiUrl}/api/agents`, { headers });
88
+ if (!res.ok) {
89
+ stderr(`Listing agents failed (${res.status}): ${await readError(res)}`);
90
+ return 1;
91
+ }
92
+ const { agents } = await res.json();
93
+ const matches = agents.filter((agent) => agent.name === parsed.name);
94
+ if (matches.length > 1) {
95
+ stderr(`Several agents are named "${parsed.name}"; pass --agent-id instead`);
96
+ return 1;
97
+ }
98
+ agentId = matches[0]?.id;
99
+ if (!agentId) {
100
+ if (parsed.action !== "create") {
101
+ stderr(`No agent is named "${parsed.name}"`);
102
+ return 1;
103
+ }
104
+ agentId = crypto.randomUUID();
105
+ name = parsed.name;
106
+ }
107
+ }
108
+ const base = `${apiUrl}/api/agents/${encodeURIComponent(agentId)}/token`;
109
+ const ttlMs = parsed.ttlDays === undefined ? undefined : parsed.ttlDays * 86400000;
110
+ const res = parsed.action === "revoke" ? await doFetch(base, { method: "DELETE", headers }) : await doFetch(parsed.action === "rotate" ? `${base}/rotate` : base, {
111
+ method: "POST",
112
+ headers,
113
+ body: JSON.stringify(parsed.action === "rotate" ? { graceSec: parsed.graceSec, ttlMs } : { name, ttlMs })
114
+ });
115
+ if (!res.ok) {
116
+ stderr(`worker-token ${parsed.action} failed (${res.status}): ${await readError(res)}`);
117
+ return 1;
118
+ }
119
+ if (parsed.action === "revoke") {
120
+ const { revoked } = await res.json();
121
+ stderr(`Revoked ${revoked} worker token(s) of agent ${agentId}.`);
122
+ return 0;
123
+ }
124
+ const token = await res.json();
125
+ if (token.agentCreated)
126
+ stderr(`Created agent ${agentId} (${name}).`);
127
+ stderr(`Worker token for agent ${agentId}, ${token.expiresAt ? `expires ${token.expiresAt}` : "no expiry"}.`);
128
+ if (token.previousExpiresAt)
129
+ stderr(`The previous token stops working at ${token.previousExpiresAt}.`);
130
+ stderr(`Set it as the worker's API_KEY with AGENT_ID=${agentId}. It is shown only once.`);
131
+ stdout(token.plaintext);
132
+ return 0;
133
+ }
134
+ export {
135
+ runWorkerToken
136
+ };
package/openapi.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "openapi": "3.1.0",
3
3
  "info": {
4
4
  "title": "Agent Swarm API",
5
- "version": "2.4.3",
5
+ "version": "2.4.5",
6
6
  "description": "Multi-agent orchestration API for Claude Code, Codex, and Gemini CLI. Enables task distribution, agent communication, and service discovery.\n\nMCP tools are documented separately in [MCP.md](./MCP.md)."
7
7
  },
8
8
  "servers": [
@@ -4680,7 +4680,7 @@
4680
4680
  },
4681
4681
  "type": {
4682
4682
  "type": "string",
4683
- "description": "Executor type: 'agent-task', 'script', 'swarm-script', 'raw-llm', 'system-one-decision', 'validate', 'property-match'"
4683
+ "description": "Executor type: 'agent-task', 'script', 'swarm-script', 'raw-llm', 'system-one-decision', 'system-one-extraction', 'validate', 'property-match'"
4684
4684
  },
4685
4685
  "label": {
4686
4686
  "type": "string",
@@ -4689,7 +4689,7 @@
4689
4689
  "config": {
4690
4690
  "type": "object",
4691
4691
  "additionalProperties": {},
4692
- "description": "Executor-specific config. For agent-task: { template, outputSchema?, agentId?, routingReason?, routingNote?, tags?, priority?, dir?, vcsRepo?, model? }; configured agentId defaults routingReason to human_pinned. For script: { runtime, script, args?, timeout? }. For swarm-script: { scriptName, scope?, pinHash?, args?, fsMode?, timeoutMs? (1000-300000) }. For system-one-decision (typed decisions, Jev by default): { provider? ('typesafe' default | 'openrouter' | 'laya'; a literal, never a {{token}}), state, questions: { <id>: { type: 'noul'|'choice'|'score', instructions, criteria? } }, returns: { <id>: { type } }, model? (provider-specific; unset = the provider's default, and laya has none so it sends no model and picks its own checkpoint), timeoutMs?, maxRetries? (0-3), humanReview? { band: { min, max } (0-1, inclusive), approvers: { users?, roles?, policy }, title?, timeout?, notifications? } }; each provider needs its own global secret (TYPESAFE_API_KEY, OPENROUTER_API_KEY, or LAYA_API_KEY; laya also needs the global config LAYA_URL), and a save warns and a run fails before any node executes when one is missing; system-one-decision nodes must not set retry or validation.retry. With humanReview, an answer whose confidence is inside the band waits for a person (human-in-the-loop approval), and next must map ports { approved, rejected?, timeout? }. Agent-task templates and ordinary config values support {{interpolation}} from the node's inputs context, including trigger and declared upstream aliases. SECURITY: executable source for script/swarm-script nodes does not interpolate trigger.* or upstream node outputs; only input/workflow/swarm/run values are allowed in inline script source, and named swarm-script source is not workflow-interpolated. Pass dynamic values through config.args instead (inline script receives them as argv, with runtime: \"bash\" running bash -c <script> ...args so args[0] is $0 and args[1] is $1; swarm-script receives its args object). NOTE: config.outputSchema on agent-task nodes validates the AGENT's raw JSON output, while node-level outputSchema validates the EXECUTOR's return value ({taskId, taskOutput})."
4692
+ "description": "Executor-specific config. For agent-task: { template, outputSchema?, agentId?, routingReason?, routingNote?, tags?, priority?, dir?, vcsRepo?, model? }; configured agentId defaults routingReason to human_pinned. For script: { runtime, script, args?, timeout? }. For swarm-script: { scriptName, scope?, pinHash?, args?, fsMode?, timeoutMs? (1000-300000) }. For system-one-decision (typed decisions, Jev by default): { provider? ('typesafe' default | 'openrouter' | 'laya'; a literal, never a {{token}}), state, questions: { <id>: { type: 'noul'|'choice'|'score', instructions, criteria? } }, returns: { <id>: { type } }, model? (provider-specific; unset = the provider's default, and laya has none so it sends no model and picks its own checkpoint), timeoutMs?, maxRetries? (0-3), humanReview? { band: { min, max } (0-1, inclusive), approvers: { users?, roles?, policy }, title?, timeout?, notifications? } }; each provider needs its own global secret (TYPESAFE_API_KEY, OPENROUTER_API_KEY, or LAYA_API_KEY; laya also needs the global config LAYA_URL), and a save warns and a run fails before any node executes when one is missing; system-one-decision nodes must not set retry or validation.retry. With humanReview, an answer whose confidence is inside the band waits for a person (human-in-the-loop approval), and next must map ports { approved, rejected?, timeout? }. For system-one-extraction (typed extraction, Cloudflare Clairic by default): { provider? ('cloudflare'; a literal), state (text to read; may be empty when images are sent), fields: { <id>: { type: 'text'|'number'|'date'|'time'|'datetime'|'duration'|'list'|'estimate'|'forecast', instructions?, ...type options (number: unit?, integer?, decimals?; duration: unit? (seconds..years), integer?, decimals?; list: items ('text'|'number'|'date'); estimate: min, max, step?, scale?, unit?; forecast: min, max, horizon?, interval?, scale?, unit?; text/number/date/time/datetime/duration: null_threshold?) } }, images? (max 4 base64 data: URLs or { content_type, base64 }), referenceDate? (YYYY-MM-DD), model?, timeoutMs?, maxRetries? (0-3) }; output answers.<id> carries value (null when the input does not say), guess, p_null, confidence, span/spans, and for estimate/forecast median/p10/p90. Needs the global secret CLOUDFLARE_API_TOKEN (or CLOUDFLARE_API_KEY) and the global config CLOUDFLARE_ACCOUNT_ID; must not set retry or validation.retry. Agent-task templates and ordinary config values support {{interpolation}} from the node's inputs context, including trigger and declared upstream aliases. SECURITY: executable source for script/swarm-script nodes does not interpolate trigger.* or upstream node outputs; only input/workflow/swarm/run values are allowed in inline script source, and named swarm-script source is not workflow-interpolated. Pass dynamic values through config.args instead (inline script receives them as argv, with runtime: \"bash\" running bash -c <script> ...args so args[0] is $0 and args[1] is $1; swarm-script receives its args object). NOTE: config.outputSchema on agent-task nodes validates the AGENT's raw JSON output, while node-level outputSchema validates the EXECUTOR's return value ({taskId, taskOutput})."
4693
4693
  },
4694
4694
  "next": {
4695
4695
  "anyOf": [
@@ -5131,7 +5131,7 @@
5131
5131
  "properties": {
5132
5132
  "type": {
5133
5133
  "type": "string",
5134
- "description": "Executor type: 'agent-task', 'script', 'swarm-script', 'raw-llm', 'system-one-decision', 'validate', 'property-match'"
5134
+ "description": "Executor type: 'agent-task', 'script', 'swarm-script', 'raw-llm', 'system-one-decision', 'system-one-extraction', 'validate', 'property-match'"
5135
5135
  },
5136
5136
  "label": {
5137
5137
  "type": "string",
@@ -5140,7 +5140,7 @@
5140
5140
  "config": {
5141
5141
  "type": "object",
5142
5142
  "additionalProperties": {},
5143
- "description": "Executor-specific config. For agent-task: { template, outputSchema?, agentId?, routingReason?, routingNote?, tags?, priority?, dir?, vcsRepo?, model? }; configured agentId defaults routingReason to human_pinned. For script: { runtime, script, args?, timeout? }. For swarm-script: { scriptName, scope?, pinHash?, args?, fsMode?, timeoutMs? (1000-300000) }. For system-one-decision (typed decisions, Jev by default): { provider? ('typesafe' default | 'openrouter' | 'laya'; a literal, never a {{token}}), state, questions: { <id>: { type: 'noul'|'choice'|'score', instructions, criteria? } }, returns: { <id>: { type } }, model? (provider-specific; unset = the provider's default, and laya has none so it sends no model and picks its own checkpoint), timeoutMs?, maxRetries? (0-3), humanReview? { band: { min, max } (0-1, inclusive), approvers: { users?, roles?, policy }, title?, timeout?, notifications? } }; each provider needs its own global secret (TYPESAFE_API_KEY, OPENROUTER_API_KEY, or LAYA_API_KEY; laya also needs the global config LAYA_URL), and a save warns and a run fails before any node executes when one is missing; system-one-decision nodes must not set retry or validation.retry. With humanReview, an answer whose confidence is inside the band waits for a person (human-in-the-loop approval), and next must map ports { approved, rejected?, timeout? }. Agent-task templates and ordinary config values support {{interpolation}} from the node's inputs context, including trigger and declared upstream aliases. SECURITY: executable source for script/swarm-script nodes does not interpolate trigger.* or upstream node outputs; only input/workflow/swarm/run values are allowed in inline script source, and named swarm-script source is not workflow-interpolated. Pass dynamic values through config.args instead (inline script receives them as argv, with runtime: \"bash\" running bash -c <script> ...args so args[0] is $0 and args[1] is $1; swarm-script receives its args object). NOTE: config.outputSchema on agent-task nodes validates the AGENT's raw JSON output, while node-level outputSchema validates the EXECUTOR's return value ({taskId, taskOutput})."
5143
+ "description": "Executor-specific config. For agent-task: { template, outputSchema?, agentId?, routingReason?, routingNote?, tags?, priority?, dir?, vcsRepo?, model? }; configured agentId defaults routingReason to human_pinned. For script: { runtime, script, args?, timeout? }. For swarm-script: { scriptName, scope?, pinHash?, args?, fsMode?, timeoutMs? (1000-300000) }. For system-one-decision (typed decisions, Jev by default): { provider? ('typesafe' default | 'openrouter' | 'laya'; a literal, never a {{token}}), state, questions: { <id>: { type: 'noul'|'choice'|'score', instructions, criteria? } }, returns: { <id>: { type } }, model? (provider-specific; unset = the provider's default, and laya has none so it sends no model and picks its own checkpoint), timeoutMs?, maxRetries? (0-3), humanReview? { band: { min, max } (0-1, inclusive), approvers: { users?, roles?, policy }, title?, timeout?, notifications? } }; each provider needs its own global secret (TYPESAFE_API_KEY, OPENROUTER_API_KEY, or LAYA_API_KEY; laya also needs the global config LAYA_URL), and a save warns and a run fails before any node executes when one is missing; system-one-decision nodes must not set retry or validation.retry. With humanReview, an answer whose confidence is inside the band waits for a person (human-in-the-loop approval), and next must map ports { approved, rejected?, timeout? }. For system-one-extraction (typed extraction, Cloudflare Clairic by default): { provider? ('cloudflare'; a literal), state (text to read; may be empty when images are sent), fields: { <id>: { type: 'text'|'number'|'date'|'time'|'datetime'|'duration'|'list'|'estimate'|'forecast', instructions?, ...type options (number: unit?, integer?, decimals?; duration: unit? (seconds..years), integer?, decimals?; list: items ('text'|'number'|'date'); estimate: min, max, step?, scale?, unit?; forecast: min, max, horizon?, interval?, scale?, unit?; text/number/date/time/datetime/duration: null_threshold?) } }, images? (max 4 base64 data: URLs or { content_type, base64 }), referenceDate? (YYYY-MM-DD), model?, timeoutMs?, maxRetries? (0-3) }; output answers.<id> carries value (null when the input does not say), guess, p_null, confidence, span/spans, and for estimate/forecast median/p10/p90. Needs the global secret CLOUDFLARE_API_TOKEN (or CLOUDFLARE_API_KEY) and the global config CLOUDFLARE_ACCOUNT_ID; must not set retry or validation.retry. Agent-task templates and ordinary config values support {{interpolation}} from the node's inputs context, including trigger and declared upstream aliases. SECURITY: executable source for script/swarm-script nodes does not interpolate trigger.* or upstream node outputs; only input/workflow/swarm/run values are allowed in inline script source, and named swarm-script source is not workflow-interpolated. Pass dynamic values through config.args instead (inline script receives them as argv, with runtime: \"bash\" running bash -c <script> ...args so args[0] is $0 and args[1] is $1; swarm-script receives its args object). NOTE: config.outputSchema on agent-task nodes validates the AGENT's raw JSON output, while node-level outputSchema validates the EXECUTOR's return value ({taskId, taskOutput})."
5144
5144
  },
5145
5145
  "next": {
5146
5146
  "anyOf": [
@@ -9751,6 +9751,10 @@
9751
9751
  "input": {
9752
9752
  "type": "object",
9753
9753
  "additionalProperties": {}
9754
+ },
9755
+ "parentTaskId": {
9756
+ "type": "string",
9757
+ "minLength": 1
9754
9758
  }
9755
9759
  }
9756
9760
  }
@@ -9938,7 +9942,7 @@
9938
9942
  }
9939
9943
  },
9940
9944
  "400": {
9941
- "description": "Invalid action input or stale script reference",
9945
+ "description": "Invalid action input, stale script reference, or parentTaskId on a non-task action",
9942
9946
  "content": {
9943
9947
  "application/json": {
9944
9948
  "schema": {
@@ -9958,7 +9962,7 @@
9958
9962
  }
9959
9963
  },
9960
9964
  "404": {
9961
- "description": "App or action not found",
9965
+ "description": "App, action, or parent task not found",
9962
9966
  "content": {
9963
9967
  "application/json": {
9964
9968
  "schema": {
@@ -16632,7 +16636,7 @@
16632
16636
  "/api/oauth/keep-warm/codex": {
16633
16637
  "post": {
16634
16638
  "summary": "Locked keep-warm refresh sweep across all Codex OAuth pool slots",
16635
- "description": "Enumerates codex_oauth_* slots and refreshes any older than ~7 days through the same locked getValidCodexOAuth path used at task time. Skips slots with a codex-auth-watch bench marker (auth-failure bench or codex-auth-expiry-watch).",
16639
+ "description": "Enumerates codex_oauth_* slots and refreshes any older than CODEX_OAUTH_KEEP_WARM_MAX_AGE_HOURS (default 120 hours) through the same locked getValidCodexOAuth path used at task time. Skips slots with a codex-auth-watch bench marker (auth-failure bench or codex-auth-expiry-watch).",
16636
16640
  "tags": [
16637
16641
  "OAuth"
16638
16642
  ],
@@ -20918,7 +20922,7 @@
20918
20922
  },
20919
20923
  "post": {
20920
20924
  "summary": "Upload a binary task file attachment",
20921
- "description": "Accepts a raw binary request body. Pass the display/path name as the `name` query parameter.",
20925
+ "description": "Accepts a raw binary request body. Pass the display/path name as the `name` query parameter. An `audio/*` file uploaded to a `draft` task gets a `[File: …]` line and its transcript (or why there is none) appended to the task text before the response; a failed transcription never fails the upload.",
20922
20926
  "tags": [
20923
20927
  "FS"
20924
20928
  ],
@@ -46582,6 +46586,13 @@
46582
46586
  "minimum": 0,
46583
46587
  "maximum": 100
46584
46588
  },
46589
+ "dependsOn": {
46590
+ "type": "array",
46591
+ "items": {
46592
+ "type": "string",
46593
+ "format": "uuid"
46594
+ }
46595
+ },
46585
46596
  "offerMode": {
46586
46597
  "type": "boolean"
46587
46598
  },
@@ -47902,7 +47913,7 @@
47902
47913
  "/api/sessions/tokens": {
47903
47914
  "post": {
47904
47915
  "summary": "Mint an ephemeral task or runtime token",
47905
- "description": "Operators can mint task or runtime tokens. Runtime tokens can mint task tokens for their own assigned tasks. Child tokens expire with their parent runtime.",
47916
+ "description": "Operators can mint task or runtime tokens. Runtime and agent tokens can mint task tokens for their own assigned tasks. A child token never outlives its parent and is revoked with it.",
47906
47917
  "tags": [
47907
47918
  "Sessions"
47908
47919
  ],
@@ -48001,7 +48012,7 @@
48001
48012
  "/api/sessions/tokens/{tokenId}": {
48002
48013
  "delete": {
48003
48014
  "summary": "Revoke an ephemeral session token",
48004
- "description": "Operators can revoke any ephemeral token. With runtime pools enabled, runtime tokens can revoke their own child task tokens. Repeated revocation has no effect.",
48015
+ "description": "Operators can revoke any ephemeral token. Agent tokens, and runtime tokens when runtime pools are enabled, can revoke their own child task tokens. Repeated revocation has no effect.",
48005
48016
  "tags": [
48006
48017
  "Sessions"
48007
48018
  ],
@@ -48047,6 +48058,285 @@
48047
48058
  }
48048
48059
  }
48049
48060
  },
48061
+ "/api/agents/{id}/token": {
48062
+ "post": {
48063
+ "operationId": "agents_mintWorkerToken",
48064
+ "summary": "Mint an agent-bound worker token",
48065
+ "description": "Returns the token once. A worker runs on it in place of the swarm API key and acts only as this agent. Creates the agent when it does not exist and `name` is given. Fails with 409 when the agent already holds an active token.",
48066
+ "tags": [
48067
+ "Sessions"
48068
+ ],
48069
+ "security": [
48070
+ {
48071
+ "bearerAuth": []
48072
+ }
48073
+ ],
48074
+ "parameters": [
48075
+ {
48076
+ "schema": {
48077
+ "type": "string",
48078
+ "minLength": 1
48079
+ },
48080
+ "required": true,
48081
+ "name": "id",
48082
+ "in": "path"
48083
+ }
48084
+ ],
48085
+ "requestBody": {
48086
+ "content": {
48087
+ "application/json": {
48088
+ "schema": {
48089
+ "type": "object",
48090
+ "properties": {
48091
+ "name": {
48092
+ "type": "string",
48093
+ "minLength": 1
48094
+ },
48095
+ "ttlMs": {
48096
+ "type": "integer",
48097
+ "exclusiveMinimum": 0,
48098
+ "description": "Token lifetime in ms. Omit for the default (no expiry)."
48099
+ }
48100
+ },
48101
+ "additionalProperties": false
48102
+ }
48103
+ }
48104
+ }
48105
+ },
48106
+ "responses": {
48107
+ "200": {
48108
+ "description": "Minted worker token",
48109
+ "content": {
48110
+ "application/json": {
48111
+ "schema": {
48112
+ "type": "object",
48113
+ "properties": {
48114
+ "agentId": {
48115
+ "type": "string"
48116
+ },
48117
+ "tokenId": {
48118
+ "type": "string"
48119
+ },
48120
+ "plaintext": {
48121
+ "type": "string"
48122
+ },
48123
+ "expiresAt": {
48124
+ "type": [
48125
+ "string",
48126
+ "null"
48127
+ ],
48128
+ "description": "null when the token does not expire"
48129
+ },
48130
+ "agentCreated": {
48131
+ "type": "boolean"
48132
+ }
48133
+ },
48134
+ "required": [
48135
+ "agentId",
48136
+ "tokenId",
48137
+ "plaintext",
48138
+ "expiresAt",
48139
+ "agentCreated"
48140
+ ]
48141
+ }
48142
+ }
48143
+ }
48144
+ },
48145
+ "403": {
48146
+ "description": "Operator or user credentials required",
48147
+ "content": {
48148
+ "application/json": {
48149
+ "schema": {
48150
+ "$ref": "#/components/schemas/ErrorResponse"
48151
+ }
48152
+ }
48153
+ }
48154
+ },
48155
+ "404": {
48156
+ "description": "Agent not found and no name given",
48157
+ "content": {
48158
+ "application/json": {
48159
+ "schema": {
48160
+ "$ref": "#/components/schemas/ErrorResponse"
48161
+ }
48162
+ }
48163
+ }
48164
+ },
48165
+ "409": {
48166
+ "description": "Agent already holds an active token",
48167
+ "content": {
48168
+ "application/json": {
48169
+ "schema": {
48170
+ "$ref": "#/components/schemas/ErrorResponse"
48171
+ }
48172
+ }
48173
+ }
48174
+ }
48175
+ }
48176
+ },
48177
+ "delete": {
48178
+ "operationId": "agents_revokeWorkerToken",
48179
+ "summary": "Revoke an agent-bound worker token",
48180
+ "description": "Revokes every active worker token of the agent and the task tokens they minted. Open realtime connections on them close.",
48181
+ "tags": [
48182
+ "Sessions"
48183
+ ],
48184
+ "security": [
48185
+ {
48186
+ "bearerAuth": []
48187
+ }
48188
+ ],
48189
+ "parameters": [
48190
+ {
48191
+ "schema": {
48192
+ "type": "string",
48193
+ "minLength": 1
48194
+ },
48195
+ "required": true,
48196
+ "name": "id",
48197
+ "in": "path"
48198
+ }
48199
+ ],
48200
+ "responses": {
48201
+ "200": {
48202
+ "description": "Number of worker tokens revoked (0 when none was active)",
48203
+ "content": {
48204
+ "application/json": {
48205
+ "schema": {
48206
+ "type": "object",
48207
+ "properties": {
48208
+ "revoked": {
48209
+ "type": "integer"
48210
+ }
48211
+ },
48212
+ "required": [
48213
+ "revoked"
48214
+ ]
48215
+ }
48216
+ }
48217
+ }
48218
+ },
48219
+ "403": {
48220
+ "description": "Operator or user credentials required",
48221
+ "content": {
48222
+ "application/json": {
48223
+ "schema": {
48224
+ "$ref": "#/components/schemas/ErrorResponse"
48225
+ }
48226
+ }
48227
+ }
48228
+ }
48229
+ }
48230
+ }
48231
+ },
48232
+ "/api/agents/{id}/token/rotate": {
48233
+ "post": {
48234
+ "operationId": "agents_rotateWorkerToken",
48235
+ "summary": "Rotate an agent-bound worker token",
48236
+ "description": "Returns a new token once. The previous token keeps working for `graceSec` (default 300), then expires. Use revoke for a token that must stop now.",
48237
+ "tags": [
48238
+ "Sessions"
48239
+ ],
48240
+ "security": [
48241
+ {
48242
+ "bearerAuth": []
48243
+ }
48244
+ ],
48245
+ "parameters": [
48246
+ {
48247
+ "schema": {
48248
+ "type": "string",
48249
+ "minLength": 1
48250
+ },
48251
+ "required": true,
48252
+ "name": "id",
48253
+ "in": "path"
48254
+ }
48255
+ ],
48256
+ "requestBody": {
48257
+ "content": {
48258
+ "application/json": {
48259
+ "schema": {
48260
+ "type": "object",
48261
+ "properties": {
48262
+ "graceSec": {
48263
+ "type": "integer",
48264
+ "minimum": 0,
48265
+ "maximum": 86400
48266
+ },
48267
+ "ttlMs": {
48268
+ "type": "integer",
48269
+ "exclusiveMinimum": 0,
48270
+ "description": "Token lifetime in ms. Omit for the default (no expiry)."
48271
+ }
48272
+ },
48273
+ "additionalProperties": false
48274
+ }
48275
+ }
48276
+ }
48277
+ },
48278
+ "responses": {
48279
+ "200": {
48280
+ "description": "New worker token",
48281
+ "content": {
48282
+ "application/json": {
48283
+ "schema": {
48284
+ "type": "object",
48285
+ "properties": {
48286
+ "agentId": {
48287
+ "type": "string"
48288
+ },
48289
+ "tokenId": {
48290
+ "type": "string"
48291
+ },
48292
+ "plaintext": {
48293
+ "type": "string"
48294
+ },
48295
+ "expiresAt": {
48296
+ "type": [
48297
+ "string",
48298
+ "null"
48299
+ ],
48300
+ "description": "null when the token does not expire"
48301
+ },
48302
+ "previousExpiresAt": {
48303
+ "type": "string"
48304
+ }
48305
+ },
48306
+ "required": [
48307
+ "agentId",
48308
+ "tokenId",
48309
+ "plaintext",
48310
+ "expiresAt",
48311
+ "previousExpiresAt"
48312
+ ]
48313
+ }
48314
+ }
48315
+ }
48316
+ },
48317
+ "403": {
48318
+ "description": "Operator or user credentials required",
48319
+ "content": {
48320
+ "application/json": {
48321
+ "schema": {
48322
+ "$ref": "#/components/schemas/ErrorResponse"
48323
+ }
48324
+ }
48325
+ }
48326
+ },
48327
+ "404": {
48328
+ "description": "Agent holds no active token",
48329
+ "content": {
48330
+ "application/json": {
48331
+ "schema": {
48332
+ "$ref": "#/components/schemas/ErrorResponse"
48333
+ }
48334
+ }
48335
+ }
48336
+ }
48337
+ }
48338
+ }
48339
+ },
48050
48340
  "/api/sessions": {
48051
48341
  "get": {
48052
48342
  "summary": "List recent task sessions (root tasks + chain summary)",
@@ -60111,7 +60401,7 @@
60111
60401
  "properties": {
60112
60402
  "type": {
60113
60403
  "type": "string",
60114
- "description": "Executor type: 'agent-task', 'script', 'swarm-script', 'raw-llm', 'system-one-decision', 'validate', 'property-match'"
60404
+ "description": "Executor type: 'agent-task', 'script', 'swarm-script', 'raw-llm', 'system-one-decision', 'system-one-extraction', 'validate', 'property-match'"
60115
60405
  },
60116
60406
  "label": {
60117
60407
  "type": "string",
@@ -60120,7 +60410,7 @@
60120
60410
  "config": {
60121
60411
  "type": "object",
60122
60412
  "additionalProperties": {},
60123
- "description": "Executor-specific config. For agent-task: { template, outputSchema?, agentId?, routingReason?, routingNote?, tags?, priority?, dir?, vcsRepo?, model? }; configured agentId defaults routingReason to human_pinned. For script: { runtime, script, args?, timeout? }. For swarm-script: { scriptName, scope?, pinHash?, args?, fsMode?, timeoutMs? (1000-300000) }. For system-one-decision (typed decisions, Jev by default): { provider? ('typesafe' default | 'openrouter' | 'laya'; a literal, never a {{token}}), state, questions: { <id>: { type: 'noul'|'choice'|'score', instructions, criteria? } }, returns: { <id>: { type } }, model? (provider-specific; unset = the provider's default, and laya has none so it sends no model and picks its own checkpoint), timeoutMs?, maxRetries? (0-3), humanReview? { band: { min, max } (0-1, inclusive), approvers: { users?, roles?, policy }, title?, timeout?, notifications? } }; each provider needs its own global secret (TYPESAFE_API_KEY, OPENROUTER_API_KEY, or LAYA_API_KEY; laya also needs the global config LAYA_URL), and a save warns and a run fails before any node executes when one is missing; system-one-decision nodes must not set retry or validation.retry. With humanReview, an answer whose confidence is inside the band waits for a person (human-in-the-loop approval), and next must map ports { approved, rejected?, timeout? }. Agent-task templates and ordinary config values support {{interpolation}} from the node's inputs context, including trigger and declared upstream aliases. SECURITY: executable source for script/swarm-script nodes does not interpolate trigger.* or upstream node outputs; only input/workflow/swarm/run values are allowed in inline script source, and named swarm-script source is not workflow-interpolated. Pass dynamic values through config.args instead (inline script receives them as argv, with runtime: \"bash\" running bash -c <script> ...args so args[0] is $0 and args[1] is $1; swarm-script receives its args object). NOTE: config.outputSchema on agent-task nodes validates the AGENT's raw JSON output, while node-level outputSchema validates the EXECUTOR's return value ({taskId, taskOutput})."
60413
+ "description": "Executor-specific config. For agent-task: { template, outputSchema?, agentId?, routingReason?, routingNote?, tags?, priority?, dir?, vcsRepo?, model? }; configured agentId defaults routingReason to human_pinned. For script: { runtime, script, args?, timeout? }. For swarm-script: { scriptName, scope?, pinHash?, args?, fsMode?, timeoutMs? (1000-300000) }. For system-one-decision (typed decisions, Jev by default): { provider? ('typesafe' default | 'openrouter' | 'laya'; a literal, never a {{token}}), state, questions: { <id>: { type: 'noul'|'choice'|'score', instructions, criteria? } }, returns: { <id>: { type } }, model? (provider-specific; unset = the provider's default, and laya has none so it sends no model and picks its own checkpoint), timeoutMs?, maxRetries? (0-3), humanReview? { band: { min, max } (0-1, inclusive), approvers: { users?, roles?, policy }, title?, timeout?, notifications? } }; each provider needs its own global secret (TYPESAFE_API_KEY, OPENROUTER_API_KEY, or LAYA_API_KEY; laya also needs the global config LAYA_URL), and a save warns and a run fails before any node executes when one is missing; system-one-decision nodes must not set retry or validation.retry. With humanReview, an answer whose confidence is inside the band waits for a person (human-in-the-loop approval), and next must map ports { approved, rejected?, timeout? }. For system-one-extraction (typed extraction, Cloudflare Clairic by default): { provider? ('cloudflare'; a literal), state (text to read; may be empty when images are sent), fields: { <id>: { type: 'text'|'number'|'date'|'time'|'datetime'|'duration'|'list'|'estimate'|'forecast', instructions?, ...type options (number: unit?, integer?, decimals?; duration: unit? (seconds..years), integer?, decimals?; list: items ('text'|'number'|'date'); estimate: min, max, step?, scale?, unit?; forecast: min, max, horizon?, interval?, scale?, unit?; text/number/date/time/datetime/duration: null_threshold?) } }, images? (max 4 base64 data: URLs or { content_type, base64 }), referenceDate? (YYYY-MM-DD), model?, timeoutMs?, maxRetries? (0-3) }; output answers.<id> carries value (null when the input does not say), guess, p_null, confidence, span/spans, and for estimate/forecast median/p10/p90. Needs the global secret CLOUDFLARE_API_TOKEN (or CLOUDFLARE_API_KEY) and the global config CLOUDFLARE_ACCOUNT_ID; must not set retry or validation.retry. Agent-task templates and ordinary config values support {{interpolation}} from the node's inputs context, including trigger and declared upstream aliases. SECURITY: executable source for script/swarm-script nodes does not interpolate trigger.* or upstream node outputs; only input/workflow/swarm/run values are allowed in inline script source, and named swarm-script source is not workflow-interpolated. Pass dynamic values through config.args instead (inline script receives them as argv, with runtime: \"bash\" running bash -c <script> ...args so args[0] is $0 and args[1] is $1; swarm-script receives its args object). NOTE: config.outputSchema on agent-task nodes validates the AGENT's raw JSON output, while node-level outputSchema validates the EXECUTOR's return value ({taskId, taskOutput})."
60124
60414
  },
60125
60415
  "next": {
60126
60416
  "anyOf": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@desplega.ai/agent-swarm",
3
- "version": "2.4.3",
3
+ "version": "2.4.5",
4
4
  "description": "agent-swarm.dev — an open-source operating system for AI work: a lead agent breaks goals into tasks, routes them to specialized workers such as Claude Code or Codex, runs each worker in an isolated container, and preserves shared memory, tools, schedules, and review gates so delegated work compounds across sessions.",
5
5
  "keywords": [
6
6
  "agent-swarm.dev",
@@ -179,8 +179,8 @@
179
179
  "@desplega/model-catalog": "workspace:*",
180
180
  "@desplega/model-routing": "workspace:*",
181
181
  "@faker-js/faker": "^10.4.0",
182
- "@opencode/plugin": "2.0.32",
183
- "@opencode/sdk": "2.0.32",
182
+ "@opencode/plugin": "2.1.2",
183
+ "@opencode/sdk": "2.1.2",
184
184
  "@oxlint/plugins": "1.78.0",
185
185
  "@types/bun": "latest",
186
186
  "dependency-cruiser": "^18.0.0",
@@ -198,17 +198,17 @@
198
198
  "bun": ">=1.3.12"
199
199
  },
200
200
  "dependencies": {
201
- "@agentclientprotocol/sdk": "1.9.0",
201
+ "@agentclientprotocol/sdk": "2.0.0",
202
202
  "@ai-sdk/openai": "^3.0.41",
203
- "@anthropic-ai/claude-agent-sdk": "0.3.304",
204
- "@anthropic-ai/sdk": "^0.135.0",
203
+ "@anthropic-ai/claude-agent-sdk": "0.3.306",
204
+ "@anthropic-ai/sdk": "^0.137.0",
205
205
  "@asteasolutions/zod-to-openapi": "^8.0.0",
206
206
  "@aws-sdk/client-bedrock": "3.1048.0",
207
207
  "@chat-adapter/discord": "4.41.1",
208
208
  "@chat-adapter/slack": "4.41.1",
209
209
  "@chat-adapter/teams": "4.41.1",
210
210
  "@chat-adapter/telegram": "4.41.1",
211
- "@cursor/sdk": "1.0.38",
211
+ "@cursor/sdk": "1.0.40",
212
212
  "@desplega.ai/agent-fs-just-bash": "0.18.5",
213
213
  "@desplega.ai/business-use": "^0.4.2",
214
214
  "@earendil-works/pi-agent-core": "^1.3.0",
@@ -217,7 +217,7 @@
217
217
  "@inkjs/ui": "^2.0.0",
218
218
  "@jitl/quickjs-singlefile-mjs-release-sync": "0.32.0",
219
219
  "@linear/sdk": "^77.0.0",
220
- "@modelcontextprotocol/sdk": "1.31.0",
220
+ "@modelcontextprotocol/sdk": "1.32.1",
221
221
  "@openai/codex": "0.163.0",
222
222
  "@openfort/openfort-node": "^0.9.1",
223
223
  "@opentelemetry/api": "^1.9.1",
@@ -24,12 +24,15 @@ export async function runAppAction({
24
24
  app,
25
25
  name,
26
26
  input = {},
27
+ parentTaskId,
27
28
  caller,
28
29
  actor,
29
30
  }: {
30
31
  app: AppRecord;
31
32
  name: string;
32
33
  input?: Record<string, unknown>;
34
+ /** Task-kind actions only: chains the created task under an existing one. The HTTP route rejects it (400) for script and sync actions, which never read it. */
35
+ parentTaskId?: string;
33
36
  caller: AppActionCaller;
34
37
  actor: string;
35
38
  }) {
@@ -136,6 +139,7 @@ export async function runAppAction({
136
139
  // swarm-tasks source can pull them back via config.assetKey.
137
140
  key: normalizeAssetKey(`shared/app:${app.id}/action:${name}/`),
138
141
  ...(actor.startsWith("user:") ? { requestedByUserId: actor.slice("user:".length) } : {}),
142
+ ...(parentTaskId ? { parentTaskId } : {}),
139
143
  },
140
144
  { origin: "app" },
141
145
  );