@desplega.ai/agent-swarm 2.2.0 → 2.4.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 (266) hide show
  1. package/README.md +1 -0
  2. package/dist/{acp-adapter-k0vwfyvn.js → acp-adapter-kedstxx6.js} +6 -6
  3. package/dist/{actions-w4pnb8vz.js → actions-vget6r1k.js} +18 -16
  4. package/dist/{amp-adapter-0cmxb2t5.js → amp-adapter-xeb5mktv.js} +2 -2
  5. package/dist/{app-zneem7g9.js → app-mqap8t8m.js} +3 -3
  6. package/dist/{assistant-wbzd2rnr.js → assistant-h0gv97mv.js} +20 -18
  7. package/dist/{boot-reembed-4kx69j3g.js → boot-reembed-qr8a894z.js} +1 -1
  8. package/dist/{boot-reembed-db0wwgy1.js → boot-reembed-rj85jjhw.js} +1 -1
  9. package/dist/{boot-scrub-sweep-tfv4d3mm.js → boot-scrub-sweep-eyfvn6v9.js} +3 -3
  10. package/dist/{boot-seeds-w2hmkxn5.js → boot-seeds-xs9a8dx1.js} +4 -4
  11. package/dist/{claude-adapter-5qrc2paq.js → claude-adapter-bm23cye7.js} +5 -5
  12. package/dist/{claude-managed-adapter-n7ahjyx6.js → claude-managed-adapter-1mwrsm9d.js} +2 -2
  13. package/dist/{claude-managed-setup-7ra32em4.js → claude-managed-setup-gkfgks4j.js} +1 -1
  14. package/dist/{claude-sdk-session-cd02gc76.js → claude-sdk-session-apb4ypz3.js} +5 -5
  15. package/dist/cli-02vhhssk.js +848 -0
  16. package/dist/{cli-4ync7m60.js → cli-0ebey9hg.js} +1 -1
  17. package/dist/{cli-665j3feb.js → cli-0xk505e8.js} +1 -1
  18. package/dist/{cli-8c1m9mhy.js → cli-1cevz46c.js} +5 -5
  19. package/dist/{cli-gzvb3d4a.js → cli-1jx0srjt.js} +3 -3
  20. package/dist/{cli-zj4d6afs.js → cli-1pa3rz69.js} +21 -6
  21. package/dist/{cli-vmbakbq0.js → cli-2rwet3r7.js} +1 -1
  22. package/dist/{cli-azs9bhc5.js → cli-3wjs22x3.js} +2 -2
  23. package/dist/{cli-tba8fxf9.js → cli-4fhyq711.js} +45 -36
  24. package/dist/{cli-ak4c12mh.js → cli-5ff2sjyt.js} +1 -1
  25. package/dist/{cli-6q7pyd3k.js → cli-5s5hx57y.js} +5 -3
  26. package/dist/{cli-h23mr2s6.js → cli-6ftrrwm1.js} +9 -371
  27. package/dist/{cli-9ac0mkg5.js → cli-8b9wvjps.js} +1 -1
  28. package/dist/cli-8cxkw1f5.js +382 -0
  29. package/dist/{cli-xhgtay7w.js → cli-8rwvksbc.js} +2 -2
  30. package/dist/{cli-e09hj50q.js → cli-8wkb09q5.js} +11 -11
  31. package/dist/{cli-ksrphveb.js → cli-a1esmmee.js} +14 -2
  32. package/dist/{cli-xnp2vkx7.js → cli-avmqhatn.js} +7 -7
  33. package/dist/{cli-xx13gqf3.js → cli-b80a1100.js} +1 -1
  34. package/dist/{cli-z1hh99j0.js → cli-bfc3k1x5.js} +3 -3
  35. package/dist/{cli-0k9rcwfy.js → cli-bhwa8rzc.js} +33 -15
  36. package/dist/{cli-8cvvytad.js → cli-bn26xbcs.js} +2 -2
  37. package/dist/{cli-k28p6xh7.js → cli-c8fwpgqb.js} +1 -1
  38. package/dist/{cli-rc3r0bnh.js → cli-ccn0eybf.js} +1 -1
  39. package/dist/{cli-9td5ss65.js → cli-dsgj3e7a.js} +2 -2
  40. package/dist/{cli-jrk8mj0t.js → cli-ecshf504.js} +2 -2
  41. package/dist/{cli-raejy0mp.js → cli-eqgfs202.js} +1 -1
  42. package/dist/{cli-ppapy34w.js → cli-f3nx1h8z.js} +2 -2
  43. package/dist/{cli-c9vrwcpb.js → cli-ffbrkh1r.js} +74 -35
  44. package/dist/{cli-mnry16kh.js → cli-kk2r80n5.js} +4 -4
  45. package/dist/{cli-c0dpzwnx.js → cli-kz116kvw.js} +3 -3
  46. package/dist/{cli-e5y285rg.js → cli-mvg2hf8p.js} +4 -4
  47. package/dist/{cli-2jm992rm.js → cli-mz1ezzzh.js} +2 -2
  48. package/dist/{cli-dw0njd9q.js → cli-nme7wery.js} +6 -6
  49. package/dist/{cli-mvsfbbgq.js → cli-nrrg0fvy.js} +18 -4
  50. package/dist/{cli-8jtrekpy.js → cli-p1m2b6gc.js} +7 -7
  51. package/dist/{cli-4c7k75rq.js → cli-rg7ntypm.js} +378 -84
  52. package/dist/{cli-z3dk189k.js → cli-rsd7ga7v.js} +10 -8
  53. package/dist/{cli-etvn5ej2.js → cli-sppc0cmw.js} +1 -1
  54. package/dist/{cli-8w65vwee.js → cli-tg9ksbn8.js} +1 -1
  55. package/dist/{cli-th8krqbf.js → cli-tgvpmnwz.js} +2 -2
  56. package/dist/{cli-hwc4a9xm.js → cli-tj4j2ts4.js} +6 -6
  57. package/dist/{cli-jhhb2v9n.js → cli-ttaz6c7m.js} +2 -2
  58. package/dist/{cli-w7z94e6c.js → cli-tx00c0h6.js} +4 -2
  59. package/dist/{cli-4g629sgr.js → cli-wrv09v7q.js} +20 -1
  60. package/dist/{cli-cby329ny.js → cli-wyrr38xm.js} +2 -2
  61. package/dist/{cli-5ks6x36q.js → cli-x1p5dhq2.js} +3 -3
  62. package/dist/{cli-bddxamg7.js → cli-x719j3vs.js} +220 -629
  63. package/dist/{cli-ztcxv5nv.js → cli-xfe63zx3.js} +1 -1
  64. package/dist/{cli-q6gw45wj.js → cli-ywyrffff.js} +1 -1
  65. package/dist/{cli-p46xdr1m.js → cli-zvze9rbm.js} +1 -1
  66. package/dist/cli.js +15 -15
  67. package/dist/{codex-adapter-m0fx3v3s.js → codex-adapter-pp2gq8gr.js} +3 -3
  68. package/dist/{codex-hook-x6tm6y5m.js → codex-hook-qwzccd64.js} +1 -1
  69. package/dist/{codex-session-runner-j9m2gfyy.js → codex-session-runner-0vzn09t8.js} +3 -3
  70. package/dist/{commands-ktnqwrv4.js → commands-psqhkttb.js} +2 -2
  71. package/dist/{controller-nex2he8v.js → controller-t20vz2k8.js} +2 -2
  72. package/dist/{controllers-connect-6yhwqv9v.js → controllers-connect-gkxmqw9d.js} +24 -20
  73. package/dist/{cursor-adapter-02s5ekva.js → cursor-adapter-3v542qe5.js} +1 -1
  74. package/dist/{db-jvr86v7f.js → db-2xbyenjr.js} +2 -2
  75. package/dist/{db-19tw9r5s.js → db-nc1rd869.js} +3 -2
  76. package/dist/{dispatcher-d3mnsg2y.js → dispatcher-ewceb8ts.js} +17 -15
  77. package/dist/{dsh-adapter-63rvej88.js → dsh-adapter-75xwh78t.js} +1 -1
  78. package/dist/{easter-egg-3d-6hg2r942.js → easter-egg-3d-xsc47jwf.js} +1 -1
  79. package/dist/{execute-bcqc69a5.js → execute-gzmw1mnw.js} +1 -1
  80. package/dist/{external-channel-44cwer32.js → external-channel-a5dsmxn4.js} +2 -2
  81. package/dist/{google-generative-ai-phpmwxvg.js → google-generative-ai-bmq8gkf3.js} +1 -1
  82. package/dist/{google-vertex-es9ybgdy.js → google-vertex-b1rvp52s.js} +1 -1
  83. package/dist/{grok-adapter-ysp907f6.js → grok-adapter-vj88xr23.js} +7 -7
  84. package/dist/handlers-zbs90bny.js +39 -0
  85. package/dist/{heartbeat-2etacsqq.js → heartbeat-t2m9r3wa.js} +20 -18
  86. package/dist/{hook-mzxxs5n2.js → hook-8femx1bg.js} +4 -4
  87. package/dist/{hook-3kvmax6d.js → hook-xa677f8r.js} +5 -5
  88. package/dist/{http-fn978m0g.js → http-xpmmq028.js} +940 -269
  89. package/dist/{index-e4tsa1h7.js → index-8pwc1jc8.js} +17 -15
  90. package/dist/{index-w2wr89xd.js → index-cdzyfrsp.js} +1 -1
  91. package/dist/{index-1r8hw4vd.js → index-dg2tmj99.js} +17 -15
  92. package/dist/index-nxa6me0q.js +41 -0
  93. package/dist/{index-039x2sag.js → index-s7ckdajq.js} +42 -14
  94. package/dist/{index-wgsw9xcz.js → index-syztqdt6.js} +1 -1
  95. package/dist/{index-x0q2a4f9.js → index-ysd45kgc.js} +1 -1
  96. package/dist/{index-g909y089.js → index-zgvqzjsw.js} +8 -8
  97. package/dist/{keepalive-d4nzs76x.js → keepalive-3nr4st3r.js} +3 -3
  98. package/dist/{lead-8h5n9k5f.js → lead-td8h2sfn.js} +33 -31
  99. package/dist/{maintenance-ea6jfw42.js → maintenance-verwpe2c.js} +1 -1
  100. package/dist/{oauth-refresh-sweep-3f25djq3.js → oauth-refresh-sweep-9q2t0y3q.js} +2 -2
  101. package/dist/{onboard-pvk7hdb2.js → onboard-aytqedmq.js} +2 -2
  102. package/dist/{opencode-adapter-eeesgfqk.js → opencode-adapter-f4hryjny.js} +4 -4
  103. package/dist/{otel-impl-qb7nhgdp.js → otel-impl-hckw4wt1.js} +1 -1
  104. package/dist/{pi-mono-adapter-zasp3ze3.js → pi-mono-adapter-hxby0ce1.js} +6 -6
  105. package/dist/{pricing-refresh-6ehwkcmp.js → pricing-refresh-5nvme3sm.js} +3 -3
  106. package/dist/{rbac-roles-km0f9cmm.js → rbac-roles-pd8c26m1.js} +5 -3
  107. package/dist/{rbac-roles-9648nh00.js → rbac-roles-vbpy21mg.js} +2 -2
  108. package/dist/{render-v2-xkze1wef.js → render-v2-7nqgvk2q.js} +3 -3
  109. package/dist/{resume-tq0bbvt5.js → resume-b6djcj3c.js} +6 -6
  110. package/dist/{runtime-ar8310ba.js → runtime-txrxc9za.js} +1 -1
  111. package/dist/session-access-fc3f9y12.js +25 -0
  112. package/dist/{setup-rnrazxvd.js → setup-n39szm6b.js} +1 -1
  113. package/dist/{virtual-modules-wzk6jf3a.js → virtual-modules-wyp2k6z3.js} +2 -2
  114. package/dist/{work-objects-e75q2rqs.js → work-objects-jem2fre0.js} +20 -18
  115. package/dist/{worker-4ww4hjef.js → worker-wr6xgfr2.js} +33 -31
  116. package/openapi.json +1011 -115
  117. package/package.json +2 -2
  118. package/src/apps/action-caller.ts +6 -0
  119. package/src/apps/script-types.ts +16 -3
  120. package/src/be/asset-key-audit.ts +4 -13
  121. package/src/be/db/active-sessions.ts +5 -0
  122. package/src/be/db/session-visibility.ts +29 -0
  123. package/src/be/db/tasks/read.ts +61 -3
  124. package/src/be/db/tasks/write.ts +15 -6
  125. package/src/be/db.ts +149 -66
  126. package/src/be/events.ts +11 -0
  127. package/src/be/migrations/227_inbox_item_state_last_read_at.sql +1 -0
  128. package/src/be/migrations/230_session_shares.sql +23 -0
  129. package/src/be/rbac-roles.ts +2 -0
  130. package/src/be/seed-scripts/catalog/heartbeat-jev-gate.ts +22 -4
  131. package/src/be/session-shares.ts +244 -0
  132. package/src/be/swarm-config-guard.ts +23 -2
  133. package/src/commands/runner.ts +11 -0
  134. package/src/heartbeat/heartbeat.ts +25 -7
  135. package/src/http/active-sessions.ts +13 -2
  136. package/src/http/agents.ts +10 -3
  137. package/src/http/all-routes.ts +1 -0
  138. package/src/http/api-keys.ts +3 -1
  139. package/src/http/approval-requests.ts +2 -1
  140. package/src/http/apps.ts +36 -11
  141. package/src/http/assets.ts +26 -4
  142. package/src/http/config.ts +3 -0
  143. package/src/http/context.ts +2 -0
  144. package/src/http/core.ts +39 -2
  145. package/src/http/events.ts +6 -2
  146. package/src/http/favorite-owner.ts +1 -1
  147. package/src/http/fs.ts +38 -3
  148. package/src/http/inbox-state.ts +58 -8
  149. package/src/http/index.ts +3 -1
  150. package/src/http/memory.ts +3 -1
  151. package/src/http/ranking.ts +367 -0
  152. package/src/http/realtime.ts +26 -21
  153. package/src/http/route-def.ts +77 -11
  154. package/src/http/script-runs.ts +2 -1
  155. package/src/http/scripts.ts +8 -0
  156. package/src/http/session-access.ts +179 -0
  157. package/src/http/session-data.ts +10 -2
  158. package/src/http/sessions.ts +212 -12
  159. package/src/http/stats.ts +7 -3
  160. package/src/http/tasks.ts +83 -7
  161. package/src/http/used-by.ts +11 -3
  162. package/src/kv-reserved-namespaces.ts +1 -0
  163. package/src/prompts/session-templates.ts +3 -1
  164. package/src/providers/amp-adapter.ts +1 -1
  165. package/src/ranking/telemetry-ranking.ts +147 -0
  166. package/src/ranking/usage.ts +57 -0
  167. package/src/rbac/admission.ts +22 -7
  168. package/src/rbac/legacy-policy.ts +2 -0
  169. package/src/rbac/permissions.ts +9 -0
  170. package/src/realtime/auth.ts +69 -0
  171. package/src/realtime/tickets.ts +4 -1
  172. package/src/realtime/transport.ts +77 -9
  173. package/src/slack/blocks.ts +18 -0
  174. package/src/slack/dm.ts +29 -0
  175. package/src/telemetry-contract/EVENTS.md +3 -0
  176. package/src/telemetry-contract/SOURCE.json +37 -4
  177. package/src/telemetry-contract/catalog.json +69 -0
  178. package/src/telemetry-contract/ranking/fixtures/expected.json +30 -0
  179. package/src/telemetry-contract/ranking/fixtures/invalid/bad-category.json +11 -0
  180. package/src/telemetry-contract/ranking/fixtures/invalid/bad-claim.json +11 -0
  181. package/src/telemetry-contract/ranking/fixtures/invalid/blank-description.json +11 -0
  182. package/src/telemetry-contract/ranking/fixtures/invalid/blank-name.json +11 -0
  183. package/src/telemetry-contract/ranking/fixtures/invalid/description-too-long.json +11 -0
  184. package/src/telemetry-contract/ranking/fixtures/invalid/domain-uppercase.json +11 -0
  185. package/src/telemetry-contract/ranking/fixtures/invalid/domain-with-scheme.json +11 -0
  186. package/src/telemetry-contract/ranking/fixtures/invalid/domain-with-www.json +11 -0
  187. package/src/telemetry-contract/ranking/fixtures/invalid/http-source-url.json +11 -0
  188. package/src/telemetry-contract/ranking/fixtures/invalid/missing-description.json +10 -0
  189. package/src/telemetry-contract/ranking/fixtures/invalid/missing-version.json +10 -0
  190. package/src/telemetry-contract/ranking/fixtures/invalid/name-not-string.json +11 -0
  191. package/src/telemetry-contract/ranking/fixtures/invalid/name-too-long.json +11 -0
  192. package/src/telemetry-contract/ranking/fixtures/invalid/not-object.json +1 -0
  193. package/src/telemetry-contract/ranking/fixtures/invalid/null.json +1 -0
  194. package/src/telemetry-contract/ranking/fixtures/invalid/other-with-subcategory.json +11 -0
  195. package/src/telemetry-contract/ranking/fixtures/invalid/oversize.json +1 -0
  196. package/src/telemetry-contract/ranking/fixtures/invalid/short-claim.json +11 -0
  197. package/src/telemetry-contract/ranking/fixtures/invalid/subcategory-other-category.json +11 -0
  198. package/src/telemetry-contract/ranking/fixtures/invalid/trailing-data.json +1 -0
  199. package/src/telemetry-contract/ranking/fixtures/invalid/unknown-field.json +12 -0
  200. package/src/telemetry-contract/ranking/fixtures/invalid/unsupported-version.json +11 -0
  201. package/src/telemetry-contract/ranking/fixtures/invalid/updated-at-not-date.json +11 -0
  202. package/src/telemetry-contract/ranking/fixtures/invalid/updated-at-offset.json +11 -0
  203. package/src/telemetry-contract/ranking/fixtures/invalid/wrong-case-field.json +11 -0
  204. package/src/telemetry-contract/ranking/fixtures/valid/category-without-subcategory.json +11 -0
  205. package/src/telemetry-contract/ranking/fixtures/valid/full.json +11 -0
  206. package/src/telemetry-contract/ranking/fixtures/valid/minimal.json +11 -0
  207. package/src/telemetry-contract/ranking/fixtures/valid/padded-text.json +11 -0
  208. package/src/telemetry-contract/ranking/fixtures/valid/unicode-name.json +11 -0
  209. package/src/telemetry-contract/ranking/listing.v1.schema.json +61 -0
  210. package/src/telemetry-contract/ranking/taxonomy.json +8 -0
  211. package/src/telemetry-contract/ranking-taxonomy.gen.ts +11 -0
  212. package/src/telemetry-contract/types.gen.ts +708 -1
  213. package/src/telemetry.ts +26 -2
  214. package/src/tests/apps-rbac.test.ts +189 -2
  215. package/src/tests/apps-script-types.test.ts +16 -3
  216. package/src/tests/asset-key-api.test.ts +128 -0
  217. package/src/tests/asset-key-invariants.test.ts +179 -3
  218. package/src/tests/asset-key-migration.test.ts +35 -0
  219. package/src/tests/check-pr-body.test.ts +23 -0
  220. package/src/tests/check-ranking-entry.test.ts +146 -0
  221. package/src/tests/db-extraction-contract.test.ts +1 -0
  222. package/src/tests/db-task-read-contract.test.ts +1 -0
  223. package/src/tests/docs-index-footprint.test.js +2 -2
  224. package/src/tests/heartbeat-checklist.test.ts +88 -0
  225. package/src/tests/heartbeat-jev-gate.test.ts +394 -10
  226. package/src/tests/inbox-state.test.ts +167 -0
  227. package/src/tests/kv-tool.test.ts +15 -0
  228. package/src/tests/org-identity.test.ts +44 -0
  229. package/src/tests/ranking-listing.test.ts +112 -0
  230. package/src/tests/ranking-route.test.ts +319 -0
  231. package/src/tests/ranking-usage.test.ts +50 -0
  232. package/src/tests/rbac-admission-e2e.test.ts +8 -0
  233. package/src/tests/rbac-admission.test.ts +38 -0
  234. package/src/tests/rbac-charact-http.test.ts +4 -3
  235. package/src/tests/rbac-engine.test.ts +2 -0
  236. package/src/tests/rbac-roles.test.ts +2 -0
  237. package/src/tests/realtime-room-surfaces.test.ts +3 -1
  238. package/src/tests/realtime-session-join-race.test.ts +142 -0
  239. package/src/tests/realtime-tickets.test.ts +24 -17
  240. package/src/tests/realtime-transport.test.ts +91 -0
  241. package/src/tests/script-connections.test.ts +2 -0
  242. package/src/tests/session-route-posture.test.ts +639 -0
  243. package/src/tests/session-sharing-routes.test.ts +282 -0
  244. package/src/tests/session-sharing.test.ts +526 -0
  245. package/src/tests/sessions-detail-batch.test.ts +7 -1
  246. package/src/tests/slack-tool-blocks.test.ts +101 -0
  247. package/src/tests/slack-update.test.ts +55 -0
  248. package/src/tests/slack-user-dm.test.ts +177 -0
  249. package/src/tests/used-by-route.test.ts +10 -0
  250. package/src/tools/slack-post.ts +18 -12
  251. package/src/tools/slack-read.ts +13 -1
  252. package/src/tools/slack-reply.ts +7 -10
  253. package/src/tools/slack-start-thread.ts +18 -11
  254. package/src/tools/slack-update.ts +2 -9
  255. package/src/types.ts +37 -0
  256. package/src/utils/org-identity.ts +33 -0
  257. package/templates/skills/apps/SKILL.md +17 -0
  258. package/templates/skills/apps/content.md +17 -0
  259. package/templates/skills/code-quality/content.md +2 -2
  260. package/templates/skills/pages/content.md +4 -0
  261. package/templates/skills/swarm-scripts/SKILL.md +6 -0
  262. package/templates/skills/swarm-scripts/content.md +6 -0
  263. package/dist/handlers-t5pbabwf.js +0 -37
  264. package/dist/index-qyjbb7br.js +0 -39
  265. package/dist/{cli-n5mrsg0f.js → cli-60cgh1rv.js} +3 -3
  266. /package/dist/{cli-j0v75y13.js → cli-y83zk5sb.js} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@desplega.ai/agent-swarm",
3
- "version": "2.2.0",
3
+ "version": "2.4.0",
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",
@@ -209,7 +209,7 @@
209
209
  "@chat-adapter/teams": "4.41.1",
210
210
  "@chat-adapter/telegram": "4.41.1",
211
211
  "@cursor/sdk": "1.0.38",
212
- "@desplega.ai/agent-fs-just-bash": "0.17.0",
212
+ "@desplega.ai/agent-fs-just-bash": "0.18.4",
213
213
  "@desplega.ai/business-use": "^0.4.2",
214
214
  "@earendil-works/pi-agent-core": "^1.3.0",
215
215
  "@earendil-works/pi-ai": "^1.3.0",
@@ -0,0 +1,6 @@
1
+ export type AppActionCaller = {
2
+ kind: "user" | "agent" | "operator" | "guest";
3
+ id: string | null;
4
+ name?: string;
5
+ pageId?: string;
6
+ };
@@ -8,6 +8,13 @@ const APP_TYPES_PREAMBLE = `// ── Swarm Apps: generated per-app types (sourc
8
8
  // Rows are the app's declared columns plus the 5 system columns. Query
9
9
  // overloads narrow only when appId AND query are string literals.
10
10
 
11
+ export type AppActionCaller = {
12
+ kind: "user" | "agent" | "operator" | "guest";
13
+ id: string | null;
14
+ name?: string;
15
+ pageId?: string;
16
+ };
17
+
11
18
  export interface SwarmAppQueryResult<Row> {
12
19
  success: boolean;
13
20
  status: number;
@@ -175,9 +182,8 @@ function renderQuery(
175
182
  }
176
183
 
177
184
  function renderApp(app: AppRecord, namespace: string): string {
178
- // Reserve the generated alias so a model named `actionName` dedupes to
179
- // `ActionName_2` instead of colliding with `type ActionName`.
180
- const modelNames = new Set<string>(["ActionName"]);
185
+ // Reserve action types so model names cannot collide with them.
186
+ const modelNames = new Set<string>(["ActionName", "ActionArgs", "AppActionCaller"]);
181
187
  const renderedModels = Object.entries(app.definition.models).map(([modelName, model]) =>
182
188
  renderModel(modelName, model, modelNames),
183
189
  );
@@ -202,6 +208,13 @@ ${renderedModels.map((model) => model.source).join("\n\n")}
202
208
 
203
209
  /** Declared actions. Invocation is REST-only: POST /api/apps/<id>/actions/<name>. */
204
210
  export type ActionName = ${actionType};
211
+
212
+ /** Script action arguments include server-stamped app and caller context. */
213
+ export interface ActionArgs {
214
+ app: { id: ${JSON.stringify(app.id)} };
215
+ caller: AppActionCaller;
216
+ [key: string]: unknown;
217
+ }
205
218
  }
206
219
 
207
220
  export interface SwarmSdk {
@@ -90,9 +90,7 @@ function auditKeyRow(
90
90
 
91
91
  type AttachmentMappingAuditRow = {
92
92
  attachment_id: string;
93
- task_key: string;
94
93
  mapping_id: string | null;
95
- mapping_key: string | null;
96
94
  };
97
95
 
98
96
  type MappingSourceAuditRow = {
@@ -118,9 +116,7 @@ export function auditAssetKeys(db: Database): AssetKeyAuditResult {
118
116
  .prepare<AttachmentMappingAuditRow, []>(
119
117
  `SELECT
120
118
  a.id AS attachment_id,
121
- t."key" AS task_key,
122
- m.id AS mapping_id,
123
- m."key" AS mapping_key
119
+ m.id AS mapping_id
124
120
  FROM task_attachments a
125
121
  JOIN agent_tasks t ON t.id = a.task_id
126
122
  LEFT JOIN asset_key_mappings m
@@ -132,6 +128,9 @@ export function auditAssetKeys(db: Database): AssetKeyAuditResult {
132
128
  AND COALESCE(NULLIF(a.provider_key, ''), a.path) IS NOT NULL`,
133
129
  )
134
130
  .all();
131
+ // One file has one mapping, which follows its source attachment (checked below). Other
132
+ // tasks may attach the same file from any namespace, and a mapping detached from its
133
+ // deleted source keeps its own namespace, so neither is drift.
135
134
  for (const row of attachmentMappings) {
136
135
  if (!row.mapping_id) {
137
136
  issues.push({
@@ -141,14 +140,6 @@ export function auditAssetKeys(db: Database): AssetKeyAuditResult {
141
140
  entityId: row.attachment_id,
142
141
  message: "Agent-fs attachment has no logical namespace mapping.",
143
142
  });
144
- } else if (row.mapping_key !== row.task_key) {
145
- issues.push({
146
- severity: "warning",
147
- code: "provider-mapping-drift",
148
- entityType: "file",
149
- entityId: row.mapping_id,
150
- message: "Provider mapping namespace differs from its parent task namespace.",
151
- });
152
143
  }
153
144
  }
154
145
 
@@ -1,3 +1,4 @@
1
+ import type { ActiveSession } from "../../types";
1
2
  import { getDbClient } from "./runtime";
2
3
 
3
4
  /**
@@ -28,3 +29,7 @@ export async function refreshActiveSessionOnActivity(
28
29
  );
29
30
  return result.changes > 0;
30
31
  }
32
+
33
+ export async function getActiveSessionById(id: string): Promise<ActiveSession | null> {
34
+ return getDbClient().get<ActiveSession>("SELECT * FROM active_sessions WHERE id = ?", [id]);
35
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Session-list visibility for session sharing. `all`: sessions the viewer
3
+ * owns, ownerless sessions, and sessions shared with the viewer or everyone.
4
+ * `mine`: owned by the viewer. `shared`: owned by someone else and shared with
5
+ * the viewer or everyone. A null `userId` (a guest page session) owns nothing.
6
+ */
7
+ export type SessionViewer = { userId: string | null; scope: "all" | "mine" | "shared" };
8
+
9
+ /** SQL condition + params restricting root tasks (alias `r`) to what `viewer` may open. */
10
+ export function sessionViewerCondition(viewer: SessionViewer): {
11
+ sql: string;
12
+ params: (string | null)[];
13
+ } {
14
+ const shared = `EXISTS (SELECT 1 FROM session_shares s
15
+ WHERE s.rootTaskId = r.id AND s.revokedAt IS NULL AND (s.userId IS NULL OR s.userId = ?))`;
16
+ if (viewer.scope === "mine") {
17
+ return { sql: "r.requestedByUserId = ?", params: [viewer.userId] };
18
+ }
19
+ if (viewer.scope === "shared") {
20
+ return {
21
+ sql: `(r.requestedByUserId IS NOT NULL AND r.requestedByUserId IS NOT ? AND ${shared})`,
22
+ params: [viewer.userId, viewer.userId],
23
+ };
24
+ }
25
+ return {
26
+ sql: `(r.requestedByUserId IS NULL OR r.requestedByUserId = ? OR ${shared})`,
27
+ params: [viewer.userId, viewer.userId],
28
+ };
29
+ }
@@ -556,10 +556,14 @@ export async function hasNonTerminalRerouteDecisionChild(parentId: string): Prom
556
556
  return row !== undefined && row !== null;
557
557
  }
558
558
 
559
- export async function getTasksByAgentId(agentId: string): Promise<AgentTask[]> {
559
+ export async function getTasksByAgentId(
560
+ agentId: string,
561
+ readableBy?: { userId: string | null },
562
+ ): Promise<AgentTask[]> {
563
+ const readable = readableBy ? readableSessionCondition(readableBy.userId) : undefined;
560
564
  const rows = await getDbClient().query<AgentTaskRow>(
561
- "SELECT * FROM agent_tasks WHERE agentId = ? ORDER BY createdAt DESC",
562
- [agentId],
565
+ `SELECT * FROM agent_tasks WHERE agentId = ?${readable ? ` AND ${readable.sql}` : ""} ORDER BY createdAt DESC`,
566
+ [agentId, ...(readable?.params ?? [])],
563
567
  );
564
568
  return rows.map(rowToAgentTask);
565
569
  }
@@ -642,6 +646,48 @@ export interface TaskFilters {
642
646
  limit?: number;
643
647
  offset?: number;
644
648
  includeHeartbeat?: boolean;
649
+ /** Only tasks of sessions this user may read; `userId: null` is a guest. */
650
+ readableBy?: { userId: string | null };
651
+ }
652
+
653
+ /**
654
+ * The SQL twin of `sessionAccessForRoot` (../../session-shares). A session's
655
+ * root is its topmost existing task; the session is hidden when the root has
656
+ * an owner other than the user and no active share names the user or
657
+ * everyone. Descending from hidden roots is linear in their tasks at any chain
658
+ * depth, and as a WHERE term it keeps paging and `COUNT(*)` on the same rows.
659
+ * `parentTaskId` is fixed at insert to an existing task, so no parent cycle
660
+ * (which would have no root) can form.
661
+ *
662
+ * `taskIdColumn` applies the same filter to any table keyed by task id. A
663
+ * nullable column keeps its task-less rows: they belong to no session.
664
+ */
665
+ export function readableSessionCondition(
666
+ userId: string | null,
667
+ taskIdColumn = "agent_tasks.id",
668
+ opts: { nullable?: boolean } = {},
669
+ ): { sql: string; params: string[] } {
670
+ const otherOwner = userId
671
+ ? "r.requestedByUserId IS NOT NULL AND r.requestedByUserId != ?"
672
+ : "r.requestedByUserId IS NOT NULL";
673
+ const shareMatch = userId ? "(s.userId IS NULL OR s.userId = ?)" : "s.userId IS NULL";
674
+ const notHidden = `${taskIdColumn} NOT IN (
675
+ WITH RECURSIVE hidden(id) AS (
676
+ SELECT r.id FROM agent_tasks r
677
+ WHERE (r.parentTaskId IS NULL
678
+ OR NOT EXISTS (SELECT 1 FROM agent_tasks p WHERE p.id = r.parentTaskId))
679
+ AND ${otherOwner}
680
+ AND NOT EXISTS (SELECT 1 FROM session_shares s
681
+ WHERE s.rootTaskId = r.id AND s.revokedAt IS NULL AND ${shareMatch})
682
+ UNION ALL
683
+ SELECT c.id FROM agent_tasks c JOIN hidden ON c.parentTaskId = hidden.id
684
+ )
685
+ SELECT id FROM hidden
686
+ )`;
687
+ return {
688
+ sql: opts.nullable ? `(${taskIdColumn} IS NULL OR ${notHidden})` : notHidden,
689
+ params: userId ? [userId, userId] : [],
690
+ };
645
691
  }
646
692
 
647
693
  export function getAllTasks(filters?: TaskFilters): Promise<AgentTask[]>;
@@ -756,6 +802,12 @@ export async function getAllTasks(
756
802
  );
757
803
  }
758
804
 
805
+ if (filters?.readableBy) {
806
+ const readable = readableSessionCondition(filters.readableBy.userId);
807
+ conditions.push(readable.sql);
808
+ params.push(...readable.params);
809
+ }
810
+
759
811
  const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
760
812
  const limit = filters?.limit ?? 25;
761
813
  const offset = filters?.offset ?? 0;
@@ -916,6 +968,12 @@ export async function getTasksCount(
916
968
  );
917
969
  }
918
970
 
971
+ if (filters?.readableBy) {
972
+ const readable = readableSessionCondition(filters.readableBy.userId);
973
+ conditions.push(readable.sql);
974
+ params.push(...readable.params);
975
+ }
976
+
919
977
  const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
920
978
  const query = `SELECT COUNT(*) as count FROM agent_tasks ${whereClause}`;
921
979
 
@@ -27,6 +27,7 @@ import {
27
27
  type AgentTaskRow,
28
28
  getTaskById,
29
29
  NEVER_STARTED_TASK_STATUSES,
30
+ readableSessionCondition,
30
31
  rowToAgentTask,
31
32
  } from "./read";
32
33
 
@@ -1019,12 +1020,16 @@ export async function resumeTask(taskId: string): Promise<AgentTask | null> {
1019
1020
  * Used on startup to resume tasks that were interrupted by deployment.
1020
1021
  * Returns tasks ordered by creation time (oldest first for FIFO).
1021
1022
  */
1022
- export async function getPausedTasksForAgent(agentId: string): Promise<AgentTask[]> {
1023
+ export async function getPausedTasksForAgent(
1024
+ agentId: string,
1025
+ readableBy?: { userId: string | null },
1026
+ ): Promise<AgentTask[]> {
1027
+ const readable = readableBy ? readableSessionCondition(readableBy.userId) : undefined;
1023
1028
  const rows = await getDbClient().query<AgentTaskRow>(
1024
1029
  `SELECT * FROM agent_tasks
1025
- WHERE agentId = ? AND status = 'paused'
1030
+ WHERE agentId = ? AND status = 'paused'${readable ? ` AND ${readable.sql}` : ""}
1026
1031
  ORDER BY createdAt ASC, rowid ASC`,
1027
- [agentId],
1032
+ [agentId, ...(readable?.params ?? [])],
1028
1033
  );
1029
1034
  return rows.map(rowToAgentTask);
1030
1035
  }
@@ -1093,15 +1098,19 @@ export async function resetOrphanedInProgressTasksForAgent(
1093
1098
  * Used by hooks to detect task cancellation and stop the worker loop.
1094
1099
  * Returns tasks cancelled within the last 5 minutes.
1095
1100
  */
1096
- export async function getRecentlyCancelledTasksForAgent(agentId: string): Promise<AgentTask[]> {
1101
+ export async function getRecentlyCancelledTasksForAgent(
1102
+ agentId: string,
1103
+ readableBy?: { userId: string | null },
1104
+ ): Promise<AgentTask[]> {
1097
1105
  const fiveMinutesAgo = new Date(Date.now() - 5 * 60 * 1000).toISOString();
1106
+ const readable = readableBy ? readableSessionCondition(readableBy.userId) : undefined;
1098
1107
  const rows = await getDbClient().query<AgentTaskRow>(
1099
1108
  `SELECT * FROM agent_tasks
1100
1109
  WHERE agentId = ?
1101
1110
  AND status = 'cancelled'
1102
- AND finishedAt > ?
1111
+ AND finishedAt > ?${readable ? ` AND ${readable.sql}` : ""}
1103
1112
  ORDER BY finishedAt DESC`,
1104
- [agentId, fiveMinutesAgo],
1113
+ [agentId, fiveMinutesAgo, ...(readable?.params ?? [])],
1105
1114
  );
1106
1115
  return rows.map(rowToAgentTask);
1107
1116
  }