@desplega.ai/agent-swarm 2.3.0 → 2.4.1

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 (332) hide show
  1. package/README.md +1 -0
  2. package/dist/{acp-adapter-v85a2bqy.js → acp-adapter-zvzr538d.js} +9 -9
  3. package/dist/{actions-zgcxfspj.js → actions-jhtqdw69.js} +21 -19
  4. package/dist/{amp-adapter-jw9xfz42.js → amp-adapter-bd84rhs2.js} +4 -4
  5. package/dist/{app-4e1s4675.js → app-kreq1gwg.js} +3 -3
  6. package/dist/{assistant-v238n9dk.js → assistant-3k22sbsq.js} +23 -21
  7. package/dist/{boot-reembed-p666cw5n.js → boot-reembed-e53x6b9v.js} +1 -1
  8. package/dist/{boot-reembed-w6pm64j4.js → boot-reembed-f6z923ny.js} +1 -1
  9. package/dist/{boot-scrub-sweep-jcyjagn3.js → boot-scrub-sweep-0538vsb7.js} +4 -4
  10. package/dist/{boot-seeds-gbedmamp.js → boot-seeds-6wxqkfk2.js} +4 -4
  11. package/dist/{claude-adapter-q7wspzt8.js → claude-adapter-gfts5044.js} +9 -9
  12. package/dist/{claude-managed-adapter-n7ahjyx6.js → claude-managed-adapter-h2y889ge.js} +3 -3
  13. package/dist/{claude-managed-setup-wza784fb.js → claude-managed-setup-h00hsgtz.js} +2 -2
  14. package/dist/{claude-sdk-session-yf400ptr.js → claude-sdk-session-56besmfz.js} +13 -13
  15. package/dist/{cli-65q70v2v.js → cli-0bh477zn.js} +33 -6
  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-7gh7020n.js → cli-1dmcq2eh.js} +1 -1
  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-7ayprxp7.js → cli-2dfbv8qr.js} +8 -0
  22. package/dist/{cli-30m5q8mc.js → cli-3kh4kpqy.js} +6 -6
  23. package/dist/{cli-qrwp40st.js → cli-3p8fqcnh.js} +2 -2
  24. package/dist/{cli-y3dvz6ge.js → cli-3r448dqn.js} +3 -3
  25. package/dist/{cli-a17tzmn0.js → cli-3tnpj2bh.js} +7 -7
  26. package/dist/{cli-ea7chd26.js → cli-471qk6s2.js} +93 -46
  27. package/dist/{cli-a49vpbf3.js → cli-5kqnemen.js} +1 -1
  28. package/dist/{cli-0rh20bp3.js → cli-6ncjvx55.js} +3 -3
  29. package/dist/{cli-fb6t92v8.js → cli-6x9ma5w5.js} +1 -1
  30. package/dist/{cli-k28p6xh7.js → cli-7225gwj7.js} +2 -2
  31. package/dist/{cli-8cvvytad.js → cli-8nyhf7za.js} +3 -3
  32. package/dist/{cli-e09hj50q.js → cli-8wkb09q5.js} +11 -11
  33. package/dist/{cli-j0v75y13.js → cli-a0kcty51.js} +4 -4
  34. package/dist/{cli-zes4tsbb.js → cli-a4gvwttf.js} +4 -4
  35. package/dist/{cli-jhp7w1fy.js → cli-a5ebc95n.js} +2 -2
  36. package/dist/{cli-5d1m1qca.js → cli-ash6xxk7.js} +2 -2
  37. package/dist/{cli-fp4xbw07.js → cli-axh29tyr.js} +14 -12
  38. package/dist/{cli-p22zdvnt.js → cli-bn0rewsy.js} +3 -3
  39. package/dist/{cli-hz64bcnj.js → cli-bn5kevnf.js} +11 -373
  40. package/dist/{cli-8jtrekpy.js → cli-d2mb5s8a.js} +7 -7
  41. package/dist/{cli-c5sbmw1v.js → cli-d82btycs.js} +94 -15
  42. package/dist/{cli-vjfpshn3.js → cli-ejs3m1sx.js} +1 -1
  43. package/dist/{cli-yv0vgscc.js → cli-fpmsqq59.js} +18 -2
  44. package/dist/cli-fz9kewbh.js +382 -0
  45. package/dist/{cli-4s1kqrqg.js → cli-g0hgtz4p.js} +6 -6
  46. package/dist/{cli-hn3pftj2.js → cli-gf0kfg81.js} +7 -7
  47. package/dist/{cli-d43xqzbe.js → cli-hqhzg1qq.js} +2 -2
  48. package/dist/{cli-azs9bhc5.js → cli-j4rqdf2n.js} +2 -2
  49. package/dist/{cli-wtg6edvd.js → cli-jh0qcrga.js} +1 -1
  50. package/dist/{cli-kqypty34.js → cli-k9z4zd4p.js} +6 -5
  51. package/dist/{cli-jhmjwqcg.js → cli-kmqgmcnb.js} +47 -14
  52. package/dist/{cli-8qsx817b.js → cli-kr2pmfqx.js} +583 -769
  53. package/dist/{cli-4g629sgr.js → cli-m2qgh5sv.js} +20 -1
  54. package/dist/{cli-9e9kjqsj.js → cli-mfe7f7b5.js} +2 -2
  55. package/dist/{cli-x3en6ct3.js → cli-nwyw3zhg.js} +1 -1
  56. package/dist/{cli-6vcyw6v7.js → cli-nx462e4v.js} +5 -3
  57. package/dist/{cli-tr24eeny.js → cli-p0rakbrk.js} +9 -9
  58. package/dist/{cli-4hmaheb6.js → cli-p6argxh9.js} +9 -9
  59. package/dist/{cli-3avfh5az.js → cli-pemywhfq.js} +2 -2
  60. package/dist/{cli-etvn5ej2.js → cli-pnp2j5zg.js} +2 -2
  61. package/dist/{cli-wk8ccrz6.js → cli-pw7v69vp.js} +2 -2
  62. package/dist/{cli-ka01m5rb.js → cli-rdq7tzwm.js} +17 -14
  63. package/dist/{cli-re4wkbzx.js → cli-rqqsfz30.js} +677 -104
  64. package/dist/{cli-xgn4rwyv.js → cli-s48yvzb8.js} +4 -4
  65. package/dist/{cli-zv4vy2b0.js → cli-s95dknxh.js} +1 -1
  66. package/dist/{cli-g6p7c2my.js → cli-sjyetj21.js} +2 -2
  67. package/dist/{cli-rdr166ht.js → cli-smvcw9z5.js} +1 -1
  68. package/dist/{cli-fhvqt2fp.js → cli-sv5gb0yb.js} +1 -1
  69. package/dist/{cli-yv3n83x8.js → cli-syhq378v.js} +2 -2
  70. package/dist/{cli-q1812jbw.js → cli-tbhwrxpt.js} +9 -9
  71. package/dist/{cli-w7z94e6c.js → cli-tx00c0h6.js} +4 -2
  72. package/dist/{cli-dxwh4j32.js → cli-vy0fay6k.js} +46 -37
  73. package/dist/{cli-ptkpaqfy.js → cli-wt645v7q.js} +1 -1
  74. package/dist/{cli-ppapy34w.js → cli-wxbn3yfx.js} +2 -2
  75. package/dist/{cli-cby329ny.js → cli-x5mq1fyq.js} +3 -3
  76. package/dist/{cli-rc3r0bnh.js → cli-xbzvet96.js} +6 -6
  77. package/dist/{cli-4mkvwgzr.js → cli-xf234ws8.js} +1 -1
  78. package/dist/{cli-6p7ddg72.js → cli-xftrvxag.js} +5 -5
  79. package/dist/cli-z071fb95.js +848 -0
  80. package/dist/{cli-1v8w782f.js → cli-z1ew8vbq.js} +14 -7
  81. package/dist/{cli-9td5ss65.js → cli-zfg9enh9.js} +3 -3
  82. package/dist/{cli-yxqag76b.js → cli-zw88zjba.js} +1 -1
  83. package/dist/cli.js +19 -19
  84. package/dist/{codex-adapter-nhjj2veb.js → codex-adapter-p6rmm7vv.js} +6 -6
  85. package/dist/{codex-hook-x6tm6y5m.js → codex-hook-x7nejyrr.js} +8 -5
  86. package/dist/{codex-login-35p4sk85.js → codex-login-m819c41r.js} +1 -1
  87. package/dist/{codex-session-runner-6hggrjbx.js → codex-session-runner-8vd5t9t0.js} +7 -7
  88. package/dist/{commands-mrw1ph2w.js → commands-7ems2p13.js} +2 -2
  89. package/dist/{controller-pt1zam5w.js → controller-m263fg43.js} +4 -4
  90. package/dist/{controllers-connect-ymw5541d.js → controllers-connect-bg33ae53.js} +28 -24
  91. package/dist/{cursor-adapter-cf4zh5x0.js → cursor-adapter-cz6nm6mj.js} +3 -3
  92. package/dist/{db-hy80219q.js → db-w505dwa8.js} +2 -2
  93. package/dist/{db-hhpy6m4x.js → db-ys2rbdft.js} +3 -2
  94. package/dist/{devin-adapter-7egzmt0k.js → devin-adapter-zgqadvnm.js} +1 -1
  95. package/dist/{dispatcher-6pdjtkr1.js → dispatcher-0s0mckqr.js} +20 -18
  96. package/dist/{docker-njavd3fb.js → docker-fkgtr75t.js} +2 -2
  97. package/dist/{dsh-adapter-fbx06re2.js → dsh-adapter-3n3net33.js} +3 -3
  98. package/dist/{e2b-5r6a5jeb.js → e2b-7am6tmq6.js} +2 -2
  99. package/dist/{e2b-pw1nvtmh.js → e2b-thdcxtjd.js} +2 -2
  100. package/dist/{easter-egg-3d-6hg2r942.js → easter-egg-3d-5cgynaja.js} +1 -1
  101. package/dist/{event-bus-101fenkh.js → event-bus-9vpk8gmq.js} +1 -1
  102. package/dist/{execute-bcqc69a5.js → execute-t4e6m3rw.js} +1 -1
  103. package/dist/{external-channel-j6vb6ya1.js → external-channel-5b23fv8z.js} +2 -2
  104. package/dist/{google-generative-ai-phpmwxvg.js → google-generative-ai-bmq8gkf3.js} +1 -1
  105. package/dist/{google-vertex-es9ybgdy.js → google-vertex-b1rvp52s.js} +1 -1
  106. package/dist/{grok-adapter-1193sprp.js → grok-adapter-q9fghe5q.js} +10 -10
  107. package/dist/handlers-mqrym347.js +39 -0
  108. package/dist/{heartbeat-h1w1ktce.js → heartbeat-tww6yx1w.js} +23 -21
  109. package/dist/{hook-ejja4bpe.js → hook-dx0pkvar.js} +16 -9
  110. package/dist/{hook-skrbja18.js → hook-pvmh9b6m.js} +6 -6
  111. package/dist/{http-mzh41mfj.js → http-k2ejbt05.js} +975 -292
  112. package/dist/{index-6rmnn89d.js → index-2z710v4x.js} +10 -10
  113. package/dist/{index-xmmkyx82.js → index-dgz61nff.js} +20 -18
  114. package/dist/{index-wgsw9xcz.js → index-g6tbb6ve.js} +1 -1
  115. package/dist/index-h2ek08d6.js +40 -0
  116. package/dist/index-pqfwh9nn.js +41 -0
  117. package/dist/{index-epr2gnbw.js → index-x5aktmp8.js} +1 -1
  118. package/dist/{index-x0q2a4f9.js → index-ysd45kgc.js} +1 -1
  119. package/dist/{index-g909y089.js → index-zgvqzjsw.js} +8 -8
  120. package/dist/{keepalive-4djvbm2j.js → keepalive-nhvpw10z.js} +4 -4
  121. package/dist/lead-jb6sf69z.js +78 -0
  122. package/dist/{maintenance-f3xhnjsm.js → maintenance-agakc519.js} +1 -1
  123. package/dist/{oauth-refresh-sweep-fpd6x6rw.js → oauth-refresh-sweep-4dcbhtn0.js} +3 -3
  124. package/dist/{onboard-196tjgyn.js → onboard-4n2kwa4v.js} +3 -3
  125. package/dist/{opencode-adapter-eeesgfqk.js → opencode-adapter-3s7ax02e.js} +7 -7
  126. package/dist/{otel-impl-g8fh4c21.js → otel-impl-tfa12080.js} +2 -2
  127. package/dist/{pi-mono-adapter-zasp3ze3.js → pi-mono-adapter-ytp7gz8b.js} +24 -13
  128. package/dist/{pricing-refresh-sdcf5yaz.js → pricing-refresh-3cqx3f3x.js} +3 -3
  129. package/dist/{rbac-roles-bsp5657v.js → rbac-roles-9fae5rnv.js} +5 -3
  130. package/dist/{rbac-roles-2x4g1wb5.js → rbac-roles-y6zbfzve.js} +2 -2
  131. package/dist/{render-v2-0pyb39bb.js → render-v2-emawjvc4.js} +3 -3
  132. package/dist/{resume-a86tkj6r.js → resume-zhgts7h7.js} +10 -8
  133. package/dist/{runtime-ar8310ba.js → runtime-xe3aqy4x.js} +1 -1
  134. package/dist/session-access-cm823e06.js +25 -0
  135. package/dist/{setup-ypbzcapd.js → setup-tkp99w1e.js} +1 -1
  136. package/dist/{virtual-modules-wzk6jf3a.js → virtual-modules-4r3zkc20.js} +2 -2
  137. package/dist/{work-objects-yjp8de12.js → work-objects-f722h263.js} +23 -21
  138. package/dist/worker-p7f336rq.js +78 -0
  139. package/dist/{x-8ewt8gxn.js → x-y45mthwn.js} +2 -2
  140. package/openapi.json +1086 -305
  141. package/package.json +2 -2
  142. package/src/apps/action-caller.ts +6 -0
  143. package/src/apps/action-runner.ts +146 -0
  144. package/src/apps/row-store.ts +4 -2
  145. package/src/apps/script-types.ts +17 -4
  146. package/src/be/db/active-sessions.ts +5 -0
  147. package/src/be/db/session-visibility.ts +29 -0
  148. package/src/be/db/tasks/read.ts +61 -3
  149. package/src/be/db/tasks/write.ts +15 -6
  150. package/src/be/db.ts +106 -37
  151. package/src/be/events.ts +11 -0
  152. package/src/be/fleet-benchmark-stats.ts +10 -5
  153. package/src/be/migrations/230_session_shares.sql +23 -0
  154. package/src/be/models-catalog.ts +4 -0
  155. package/src/be/onboarding.ts +6 -0
  156. package/src/be/rbac-roles.ts +2 -0
  157. package/src/be/scripts/typecheck.ts +13 -0
  158. package/src/be/session-shares.ts +244 -0
  159. package/src/be/swarm-config-guard.ts +33 -3
  160. package/src/be/telemetry-enable.ts +1 -1
  161. package/src/commands/provider-credentials.ts +12 -2
  162. package/src/commands/runner.ts +14 -0
  163. package/src/heartbeat/heartbeat.ts +2 -2
  164. package/src/hooks/codex-hook.ts +6 -2
  165. package/src/hooks/hook.ts +7 -0
  166. package/src/hooks/pr-body-guard.ts +38 -11
  167. package/src/hooks/pr-room-guard.ts +88 -0
  168. package/src/http/active-sessions.ts +13 -2
  169. package/src/http/agents.ts +11 -3
  170. package/src/http/all-routes.ts +1 -0
  171. package/src/http/api-keys.ts +3 -1
  172. package/src/http/approval-requests.ts +2 -1
  173. package/src/http/apps.ts +118 -190
  174. package/src/http/config.ts +3 -0
  175. package/src/http/context.ts +2 -0
  176. package/src/http/core.ts +39 -2
  177. package/src/http/events.ts +6 -2
  178. package/src/http/favorite-owner.ts +1 -1
  179. package/src/http/fleet-benchmark.ts +79 -30
  180. package/src/http/fs.ts +38 -3
  181. package/src/http/global-config.ts +7 -0
  182. package/src/http/index.ts +3 -1
  183. package/src/http/memory.ts +3 -1
  184. package/src/http/ranking.ts +351 -0
  185. package/src/http/realtime.ts +26 -21
  186. package/src/http/route-def.ts +77 -11
  187. package/src/http/script-runs.ts +2 -1
  188. package/src/http/scripts.ts +8 -0
  189. package/src/http/session-access.ts +179 -0
  190. package/src/http/session-data.ts +10 -2
  191. package/src/http/sessions.ts +212 -12
  192. package/src/http/stats.ts +7 -3
  193. package/src/http/tasks.ts +85 -8
  194. package/src/http/telemetry-ui.ts +1 -1
  195. package/src/http/used-by.ts +64 -20
  196. package/src/http/users.ts +2 -2
  197. package/src/prompts/session-templates.ts +3 -1
  198. package/src/providers/amp-adapter.ts +1 -1
  199. package/src/providers/pi-mono-adapter.ts +15 -0
  200. package/src/providers/reasoning-effort.ts +2 -1
  201. package/src/providers/types.ts +2 -0
  202. package/src/ranking/telemetry-ranking.ts +119 -0
  203. package/src/ranking/usage.ts +57 -0
  204. package/src/rbac/admission.ts +22 -7
  205. package/src/rbac/legacy-policy.ts +2 -0
  206. package/src/rbac/permissions.ts +9 -0
  207. package/src/realtime/auth.ts +69 -0
  208. package/src/realtime/tickets.ts +4 -1
  209. package/src/realtime/transport.ts +77 -9
  210. package/src/scripts-runtime/sdk-allowlist.ts +7 -0
  211. package/src/scripts-runtime/types/stdlib.d.ts +31 -0
  212. package/src/scripts-runtime/types/swarm-sdk.d.ts +31 -0
  213. package/src/server.ts +4 -0
  214. package/src/slack/blocks.ts +18 -0
  215. package/src/slack/dm.ts +29 -0
  216. package/src/telemetry-context.ts +19 -1
  217. package/src/telemetry-contract/EVENTS.md +45 -8
  218. package/src/telemetry-contract/SOURCE.json +38 -4
  219. package/src/telemetry-contract/catalog.json +294 -5
  220. package/src/telemetry-contract/ranking/fixtures/expected.json +30 -0
  221. package/src/telemetry-contract/ranking/fixtures/invalid/bad-category.json +11 -0
  222. package/src/telemetry-contract/ranking/fixtures/invalid/bad-claim.json +11 -0
  223. package/src/telemetry-contract/ranking/fixtures/invalid/blank-description.json +11 -0
  224. package/src/telemetry-contract/ranking/fixtures/invalid/blank-name.json +11 -0
  225. package/src/telemetry-contract/ranking/fixtures/invalid/description-too-long.json +11 -0
  226. package/src/telemetry-contract/ranking/fixtures/invalid/domain-uppercase.json +11 -0
  227. package/src/telemetry-contract/ranking/fixtures/invalid/domain-with-scheme.json +11 -0
  228. package/src/telemetry-contract/ranking/fixtures/invalid/domain-with-www.json +11 -0
  229. package/src/telemetry-contract/ranking/fixtures/invalid/http-source-url.json +11 -0
  230. package/src/telemetry-contract/ranking/fixtures/invalid/missing-description.json +10 -0
  231. package/src/telemetry-contract/ranking/fixtures/invalid/missing-version.json +10 -0
  232. package/src/telemetry-contract/ranking/fixtures/invalid/name-not-string.json +11 -0
  233. package/src/telemetry-contract/ranking/fixtures/invalid/name-too-long.json +11 -0
  234. package/src/telemetry-contract/ranking/fixtures/invalid/not-object.json +1 -0
  235. package/src/telemetry-contract/ranking/fixtures/invalid/null.json +1 -0
  236. package/src/telemetry-contract/ranking/fixtures/invalid/other-with-subcategory.json +11 -0
  237. package/src/telemetry-contract/ranking/fixtures/invalid/oversize.json +1 -0
  238. package/src/telemetry-contract/ranking/fixtures/invalid/short-claim.json +11 -0
  239. package/src/telemetry-contract/ranking/fixtures/invalid/subcategory-other-category.json +11 -0
  240. package/src/telemetry-contract/ranking/fixtures/invalid/trailing-data.json +1 -0
  241. package/src/telemetry-contract/ranking/fixtures/invalid/unknown-field.json +12 -0
  242. package/src/telemetry-contract/ranking/fixtures/invalid/unsupported-version.json +11 -0
  243. package/src/telemetry-contract/ranking/fixtures/invalid/updated-at-not-date.json +11 -0
  244. package/src/telemetry-contract/ranking/fixtures/invalid/updated-at-offset.json +11 -0
  245. package/src/telemetry-contract/ranking/fixtures/invalid/wrong-case-field.json +11 -0
  246. package/src/telemetry-contract/ranking/fixtures/valid/category-without-subcategory.json +11 -0
  247. package/src/telemetry-contract/ranking/fixtures/valid/full.json +11 -0
  248. package/src/telemetry-contract/ranking/fixtures/valid/minimal.json +11 -0
  249. package/src/telemetry-contract/ranking/fixtures/valid/no-claim.json +10 -0
  250. package/src/telemetry-contract/ranking/fixtures/valid/padded-text.json +11 -0
  251. package/src/telemetry-contract/ranking/fixtures/valid/unicode-name.json +11 -0
  252. package/src/telemetry-contract/ranking/listing.v1.schema.json +61 -0
  253. package/src/telemetry-contract/ranking/taxonomy.json +8 -0
  254. package/src/telemetry-contract/ranking-taxonomy.gen.ts +11 -0
  255. package/src/telemetry-contract/types.gen.ts +963 -58
  256. package/src/telemetry-identity.ts +47 -9
  257. package/src/telemetry-snapshot.ts +9 -1
  258. package/src/telemetry-ui-events.ts +9 -2
  259. package/src/telemetry.ts +40 -5
  260. package/src/tests/app-action-run-tool.test.ts +178 -0
  261. package/src/tests/app-row-tools.test.ts +360 -0
  262. package/src/tests/apps-rbac.test.ts +189 -2
  263. package/src/tests/apps-script-types.test.ts +16 -3
  264. package/src/tests/credential-check.test.ts +38 -0
  265. package/src/tests/db-extraction-contract.test.ts +1 -0
  266. package/src/tests/db-task-read-contract.test.ts +1 -0
  267. package/src/tests/docs-index-footprint.test.js +2 -2
  268. package/src/tests/fleet-benchmark.test.ts +122 -2
  269. package/src/tests/http-users.test.ts +62 -1
  270. package/src/tests/model-catalog-table.test.ts +63 -0
  271. package/src/tests/model-profiles-api.test.ts +19 -7
  272. package/src/tests/models-catalog.test.ts +50 -0
  273. package/src/tests/onboarding.test.ts +21 -0
  274. package/src/tests/org-identity.test.ts +44 -0
  275. package/src/tests/org-website.test.ts +62 -0
  276. package/src/tests/pi-mono-adapter.test.ts +23 -0
  277. package/src/tests/pr-body-leaks.test.ts +4 -0
  278. package/src/tests/pr-room-guard.test.ts +242 -0
  279. package/src/tests/ranking-listing.test.ts +97 -0
  280. package/src/tests/ranking-route.test.ts +321 -0
  281. package/src/tests/ranking-usage.test.ts +50 -0
  282. package/src/tests/rbac-admission-e2e.test.ts +8 -0
  283. package/src/tests/rbac-admission.test.ts +38 -0
  284. package/src/tests/rbac-charact-http.test.ts +4 -3
  285. package/src/tests/rbac-engine.test.ts +2 -0
  286. package/src/tests/rbac-roles.test.ts +2 -0
  287. package/src/tests/realtime-room-surfaces.test.ts +3 -1
  288. package/src/tests/realtime-session-join-race.test.ts +142 -0
  289. package/src/tests/realtime-tickets.test.ts +24 -17
  290. package/src/tests/realtime-transport.test.ts +91 -0
  291. package/src/tests/reasoning-effort.test.ts +39 -3
  292. package/src/tests/runner-harness-telemetry-env.test.ts +56 -1
  293. package/src/tests/session-route-posture.test.ts +639 -0
  294. package/src/tests/session-sharing-routes.test.ts +282 -0
  295. package/src/tests/session-sharing.test.ts +526 -0
  296. package/src/tests/sessions-detail-batch.test.ts +7 -1
  297. package/src/tests/slack-tool-blocks.test.ts +101 -0
  298. package/src/tests/slack-update.test.ts +55 -0
  299. package/src/tests/slack-user-dm.test.ts +177 -0
  300. package/src/tests/swarm-tool-result-gate.test.ts +2 -4
  301. package/src/tests/telemetry-context.test.ts +128 -2
  302. package/src/tests/telemetry-ui-route.test.ts +123 -0
  303. package/src/tests/tool-annotations.test.ts +3 -2
  304. package/src/tests/used-by-route.test.ts +153 -9
  305. package/src/tests/workflow-agent-task-retry.test.ts +130 -4
  306. package/src/tests/workflow-wait-recovery.test.ts +116 -4
  307. package/src/tools/app-action-run.ts +63 -0
  308. package/src/tools/app-rows.ts +234 -0
  309. package/src/tools/model-catalog/index.ts +1 -1
  310. package/src/tools/slack-post.ts +18 -12
  311. package/src/tools/slack-read.ts +13 -1
  312. package/src/tools/slack-reply.ts +7 -10
  313. package/src/tools/slack-start-thread.ts +18 -11
  314. package/src/tools/slack-update.ts +2 -9
  315. package/src/tools/tool-config.ts +8 -0
  316. package/src/tools/utils.ts +1 -1
  317. package/src/tools/workflows/retry-workflow-run.ts +1 -1
  318. package/src/types.ts +52 -0
  319. package/src/utils/company-profile.ts +24 -0
  320. package/src/utils/org-identity.ts +33 -0
  321. package/src/utils/org-website.ts +58 -21
  322. package/src/workflows/recovery.ts +10 -22
  323. package/src/workflows/resume.ts +16 -0
  324. package/src/workflows/task-step-routing.ts +47 -7
  325. package/templates/skills/apps/SKILL.md +58 -2
  326. package/templates/skills/apps/content.md +58 -2
  327. package/dist/handlers-tb3xgjnm.js +0 -37
  328. package/dist/index-nyfcdpky.js +0 -39
  329. package/dist/index-vjn3wbzf.js +0 -38
  330. package/dist/lead-61kqp604.js +0 -76
  331. package/dist/worker-4ptnn1ge.js +0 -76
  332. package/dist/{cli-n5mrsg0f.js → cli-60cgh1rv.js} +3 -3
@@ -72,6 +72,7 @@ import {
72
72
  hasNonTerminalRerouteDecisionChild2,
73
73
  getAgentCurrentTask2,
74
74
  findTaskByVcs2,
75
+ readableSessionCondition,
75
76
  getAllTasks2,
76
77
  getPendingChatRelayTasks2,
77
78
  giveUpStaleChatRelays2,
@@ -89,6 +90,7 @@ import {
89
90
  getLatestLeadTaskByContextKey2,
90
91
  findCompletedTaskInThread2,
91
92
  findRecentCancelledTaskInThread2,
93
+ init_read,
92
94
  listModelProfiles,
93
95
  getModelProfileByName,
94
96
  modelProfileRefError,
@@ -330,19 +332,19 @@ import {
330
332
  recordInlineScriptRun2,
331
333
  exports_db,
332
334
  init_db3
333
- } from "./cli-re4wkbzx.js";
335
+ } from "./cli-rqqsfz30.js";
334
336
  import {
335
337
  getUserGrant2,
336
338
  init_rbac_roles
337
- } from "./cli-6vcyw6v7.js";
339
+ } from "./cli-nx462e4v.js";
338
340
  import {
339
341
  ensurePricingSeeded2,
340
342
  ensureRbacSeeded2,
341
343
  ensureModelProfilesSeeded2
342
- } from "./cli-xgn4rwyv.js";
344
+ } from "./cli-s48yvzb8.js";
343
345
  import {
344
346
  loadModelsDevCache
345
- } from "./cli-qrwp40st.js";
347
+ } from "./cli-3p8fqcnh.js";
346
348
  import {
347
349
  buildCatalogEntries,
348
350
  listModelCatalog,
@@ -352,12 +354,12 @@ import {
352
354
  loadModelsCatalog,
353
355
  requestModelCatalogRefresh2,
354
356
  startPricingRefreshLoop2
355
- } from "./cli-kqypty34.js";
357
+ } from "./cli-k9z4zd4p.js";
356
358
  import {
357
359
  ampPinProviderError,
358
360
  ampPinCatalogError,
359
361
  ampModelError
360
- } from "./cli-fhvqt2fp.js";
362
+ } from "./cli-sv5gb0yb.js";
361
363
  import {
362
364
  notifyAutomationPreflightFailure,
363
365
  isNeedsSetupFailure,
@@ -395,6 +397,7 @@ import {
395
397
  cancelWorkflowRunRows2,
396
398
  cancelWorkflowRun2,
397
399
  resumeWaitState2,
400
+ recoverResolvedWaitState2,
398
401
  resumeFromChildRun2,
399
402
  initWaitBusSubscriptions2,
400
403
  TriggerSchemaError,
@@ -408,7 +411,7 @@ import {
408
411
  buildNodeInterpolationCtx,
409
412
  interpolateNodeConfig,
410
413
  scriptBodyInterpolationError
411
- } from "./cli-jhmjwqcg.js";
414
+ } from "./cli-kmqgmcnb.js";
412
415
  import {
413
416
  require_dist2,
414
417
  publicEndpointSsrfOptions,
@@ -465,14 +468,14 @@ import {
465
468
  deleteApp,
466
469
  typecheckScript,
467
470
  parseSkillContent
468
- } from "./cli-65q70v2v.js";
471
+ } from "./cli-0bh477zn.js";
469
472
  import {
470
473
  buildAuthorizationUrl,
471
474
  onAuthorizationRefreshed,
472
475
  ensureAuthorizationTokenOrThrow,
473
476
  ensureToken,
474
477
  ensureTokenOrThrow
475
- } from "./cli-g6p7c2my.js";
478
+ } from "./cli-sjyetj21.js";
476
479
  import {
477
480
  detachedProcessGroup,
478
481
  registerProcessGroup,
@@ -484,6 +487,7 @@ import {
484
487
  getTaskLink,
485
488
  getTaskUrl,
486
489
  markdownToSlack,
490
+ buildMrkdwnSectionBlocks,
487
491
  buildCaptionBlock,
488
492
  taskCitationIssues,
489
493
  stripInvalidTaskCitations,
@@ -501,14 +505,14 @@ import {
501
505
  getSlackApp2,
502
506
  startSlackApp2,
503
507
  stopSlackApp2
504
- } from "./cli-dxwh4j32.js";
508
+ } from "./cli-vy0fay6k.js";
505
509
  import {
506
510
  slackCode,
507
511
  slackMissingScopeMessage,
508
512
  withAutoJoin,
509
513
  externalChannelToolError2,
510
514
  getChannelBlockReason2
511
- } from "./cli-9e9kjqsj.js";
515
+ } from "./cli-mfe7f7b5.js";
512
516
  import {
513
517
  BaseExecutor,
514
518
  postApprovalCancellationUpdates,
@@ -525,11 +529,36 @@ import {
525
529
  definitionNodeIds,
526
530
  validateDefinition,
527
531
  applyDefinitionPatch
528
- } from "./cli-q1812jbw.js";
532
+ } from "./cli-tbhwrxpt.js";
529
533
  import {
530
534
  workflowEventBus2,
531
535
  init_event_bus
532
- } from "./cli-ptkpaqfy.js";
536
+ } from "./cli-wt645v7q.js";
537
+ import {
538
+ duplicateGuardedQueryKey,
539
+ parseQueryParams,
540
+ getPathSegments,
541
+ agentWithCapacity,
542
+ BODY_TOO_LARGE,
543
+ enforceContentLengthCap,
544
+ json,
545
+ jsonError,
546
+ getSessionRoot,
547
+ sessionAccessForRoot,
548
+ resolveTaskAuditUserId,
549
+ resolveHttpFavoriteOwner,
550
+ resolveSessionActor2,
551
+ SESSION_READ_DENIED2,
552
+ canReadSession2,
553
+ readableByFor2,
554
+ pathSessionDenial2,
555
+ userAgentIdentityDenial2,
556
+ runtimeInstanceHeader,
557
+ routeRegistry,
558
+ isPublicRoute,
559
+ findRoute,
560
+ route
561
+ } from "./cli-z071fb95.js";
533
562
  import {
534
563
  isMultiRuntimeEnabled
535
564
  } from "./cli-7a91w22y.js";
@@ -539,23 +568,9 @@ import {
539
568
  getFileStorageProvider2
540
569
  } from "./cli-qje9k2nh.js";
541
570
  import {
542
- findUserById,
543
- findUserByExternalId,
544
- findUserByEmail,
545
- findUsersByName,
546
- getUserIdentities,
547
- recordIdentityEvent,
548
- findOrCreateUserByEmail,
549
- linkIdentity,
550
- unlinkIdentity,
551
- resolveUserByToken,
552
- revokeRuntimeTokensForRuntime,
553
- resolveSessionToken,
554
- fingerprintApiKey,
555
- init_users,
556
571
  getRuntimePool2,
557
572
  init_db
558
- } from "./cli-hz64bcnj.js";
573
+ } from "./cli-bn5kevnf.js";
559
574
  import {
560
575
  getMemoryRaterNames,
561
576
  REFERENCES_SOURCE_MAX_LENGTH,
@@ -566,7 +581,7 @@ import {
566
581
  COMPOSIO_HTTP_METHODS,
567
582
  executeComposioRequest,
568
583
  composioArgsFromParts
569
- } from "./cli-rdr166ht.js";
584
+ } from "./cli-smvcw9z5.js";
570
585
  import {
571
586
  require_fast_deep_equal
572
587
  } from "./cli-bhp11egn.js";
@@ -580,7 +595,23 @@ import {
580
595
  import {
581
596
  canProvisionKind,
582
597
  init_runtime_providers
583
- } from "./cli-wk8ccrz6.js";
598
+ } from "./cli-pw7v69vp.js";
599
+ import {
600
+ findUserById,
601
+ findUserByExternalId,
602
+ findUserByEmail,
603
+ findUsersByName,
604
+ getUserIdentities,
605
+ recordIdentityEvent,
606
+ findOrCreateUserByEmail,
607
+ linkIdentity,
608
+ unlinkIdentity,
609
+ resolveUserByToken,
610
+ revokeRuntimeTokensForRuntime,
611
+ resolveSessionToken,
612
+ fingerprintApiKey,
613
+ init_users
614
+ } from "./cli-fz9kewbh.js";
584
615
  import {
585
616
  isRbacEnabled,
586
617
  decideAdmission,
@@ -589,7 +620,7 @@ import {
589
620
  init_elevated_agents,
590
621
  can,
591
622
  init_rbac
592
- } from "./cli-zj4d6afs.js";
623
+ } from "./cli-1pa3rz69.js";
593
624
  import {
594
625
  normalizeAssetKey,
595
626
  parseAssetKey,
@@ -649,7 +680,7 @@ import {
649
680
  KvNamespaceSchema,
650
681
  KvKeySchema,
651
682
  init_types
652
- } from "./cli-yv0vgscc.js";
683
+ } from "./cli-fpmsqq59.js";
653
684
  import {
654
685
  generateDefaultClaudeMd2,
655
686
  generateDefaultSoulMd2,
@@ -658,7 +689,7 @@ import {
658
689
  taskAttachmentFetchCommand,
659
690
  taskAttachmentDisplayUrl,
660
691
  init_task_attachment_links
661
- } from "./cli-cby329ny.js";
692
+ } from "./cli-x5mq1fyq.js";
662
693
  import {
663
694
  getSlackConfiguration,
664
695
  init_config
@@ -677,7 +708,7 @@ import {
677
708
  init_registry,
678
709
  resolveTemplate,
679
710
  init_resolver
680
- } from "./cli-w7z94e6c.js";
711
+ } from "./cli-tx00c0h6.js";
681
712
  import {
682
713
  init_zod
683
714
  } from "./cli-4chz1hye.js";
@@ -689,7 +720,6 @@ import {
689
720
  init_json_schema_processors,
690
721
  init_core,
691
722
  datetime,
692
- ZodError,
693
723
  string2,
694
724
  uuid,
695
725
  number2,
@@ -721,7 +751,7 @@ import {
721
751
  import {
722
752
  init_package,
723
753
  package_default
724
- } from "./cli-5d1m1qca.js";
754
+ } from "./cli-ash6xxk7.js";
725
755
  import {
726
756
  realtimeBus,
727
757
  init_bus
@@ -754,7 +784,7 @@ import {
754
784
  registerVolatileSecret,
755
785
  registerSensitiveKeyName,
756
786
  init_secret_scrubber
757
- } from "./cli-4mkvwgzr.js";
787
+ } from "./cli-xf234ws8.js";
758
788
  import {
759
789
  isAlias,
760
790
  parseAlias,
@@ -768,7 +798,7 @@ import {
768
798
  openAICompatibleProviderIds,
769
799
  claudeCatalogModelId,
770
800
  init_src2
771
- } from "./cli-x3en6ct3.js";
801
+ } from "./cli-nwyw3zhg.js";
772
802
  import {
773
803
  __toESM,
774
804
  __commonJS,
@@ -20223,17 +20253,12 @@ async function recoverWaitStates(registry) {
20223
20253
  let recovered = 0;
20224
20254
  for (const stuck of stuckRuns) {
20225
20255
  try {
20226
- let resumeStatus;
20227
- let payload;
20228
- if (stuck.waitStatus === "fired") {
20229
- resumeStatus = "fired";
20230
- payload = stuck.firedPayload != null ? safeJsonParse(stuck.firedPayload) : undefined;
20231
- } else if (stuck.waitStatus === "timeout") {
20232
- resumeStatus = "timeout";
20256
+ if (stuck.waitStatus === "pending") {
20257
+ const status = stuck.waitMode === "time" ? "fired" : "timeout";
20258
+ await resumeWaitState2(stuck.waitId, status, undefined, registry);
20233
20259
  } else {
20234
- resumeStatus = stuck.waitMode === "time" ? "fired" : "timeout";
20260
+ await recoverResolvedWaitState2(stuck.waitId, registry);
20235
20261
  }
20236
- await resumeWaitState2(stuck.waitId, resumeStatus, payload, registry);
20237
20262
  recovered++;
20238
20263
  } catch (err) {
20239
20264
  if (await failRunOnUnreadableReplay(stuck.runId, err))
@@ -20243,13 +20268,6 @@ async function recoverWaitStates(registry) {
20243
20268
  }
20244
20269
  return recovered;
20245
20270
  }
20246
- function safeJsonParse(s) {
20247
- try {
20248
- return JSON.parse(s);
20249
- } catch {
20250
- return s;
20251
- }
20252
- }
20253
20271
  async function getRunIdsByStatus(status) {
20254
20272
  const rows = await getDbClient2().query("SELECT id FROM workflow_runs WHERE status = ?", [status]);
20255
20273
  return rows.map((r) => r.id);
@@ -21125,7 +21143,7 @@ class NotifyExecutor extends BaseExecutor {
21125
21143
  }
21126
21144
  }
21127
21145
  case "slack": {
21128
- const { getSlackApp } = await import("./app-4e1s4675.js");
21146
+ const { getSlackApp } = await import("./app-kreq1gwg.js");
21129
21147
  const app = getSlackApp();
21130
21148
  if (!app) {
21131
21149
  return {
@@ -23676,6 +23694,13 @@ var SDK_TOOL_NAME_MAP = {
23676
23694
  app_list: "app-list",
23677
23695
  app_patch: "app-patch",
23678
23696
  app_query: "app-query",
23697
+ app_rows_list: "app-rows-list",
23698
+ app_row_get: "app-row-get",
23699
+ app_row_create: "app-row-create",
23700
+ app_rows_create: "app-rows-create",
23701
+ app_row_patch: "app-row-patch",
23702
+ app_row_delete: "app-row-delete",
23703
+ app_rows_delete: "app-rows-delete",
23679
23704
  app_rollback: "app-rollback",
23680
23705
  app_sync: "app-sync",
23681
23706
  app_upsert: "app-upsert",
@@ -24132,7 +24157,7 @@ var NUDGES = {
24132
24157
  const definition = r.data?.app?.definition;
24133
24158
  const hasQueries = Object.keys(definition?.queries ?? {}).length > 0;
24134
24159
  const hasActions = Object.keys(definition?.actions ?? {}).length > 0;
24135
- return hasQueries || hasActions ? "This app's callable surface is `definition.queries` (run with `app-query`, passing any `$param` values) and `definition.actions` (invoke with `POST /api/apps/<id>/actions/<name>`; `sync` actions refresh sources)." : undefined;
24160
+ return hasQueries || hasActions ? "Run `definition.queries` with `app-query` and supply each `$param` value. Invoke `definition.actions` with `app-action-run` through MCP or `POST /api/apps/<id>/actions/<name>` through REST. Sync actions refresh sources." : undefined;
24136
24161
  },
24137
24162
  "kv-get": (r) => {
24138
24163
  if (!r.ok)
@@ -24480,7 +24505,7 @@ function setPreloadedTools(server, names) {
24480
24505
  async function applyPreToolCall(name, args, requestInfo, inputSchema) {
24481
24506
  if (requestInfo.callOrigin !== "mcp")
24482
24507
  return { args };
24483
- const dispatcher = await import("./dispatcher-6pdjtkr1.js");
24508
+ const dispatcher = await import("./dispatcher-0s0mckqr.js");
24484
24509
  const result = await dispatcher.dispatchPre("pre.tool.call", { tool: name, args, requestInfo }, inputSchema ? {
24485
24510
  validateModify: async (data) => {
24486
24511
  const schema = normalizeObjectSchema(inputSchema) ?? inputSchema;
@@ -24575,469 +24600,6 @@ var createToolRegistrar = (server) => {
24575
24600
  };
24576
24601
  };
24577
24602
 
24578
- // src/http/route-def.ts
24579
- init_zod();
24580
- init_node_env();
24581
- init_secret_scrubber();
24582
-
24583
- // src/http/utils.ts
24584
- init_db3();
24585
- init_env_flag();
24586
- init_node_env();
24587
- init_secret_scrubber();
24588
- function duplicateGuardedQueryKey(query) {
24589
- return ["agentId", "repoId", "includeSecrets", "resolveSecrets"].find((key) => query.getAll(key).length > 1);
24590
- }
24591
- var DEFAULT_ALLOWED_ORIGINS = [
24592
- "https://*.agent-swarm.dev",
24593
- "https://*.agent-swarm.cloud",
24594
- "http://localhost:5274",
24595
- "http://127.0.0.1:5274",
24596
- "http://[::1]:5274",
24597
- "https://ui.swarm.localhost:1355"
24598
- ];
24599
- var warnedAboutAllowAnyOrigin = false;
24600
- function warnIfCorsAllowsAnyOrigin() {
24601
- if (isEnvFlagEnabled("CORS_ALLOW_ANY_ORIGIN", false) && !warnedAboutAllowAnyOrigin) {
24602
- warnedAboutAllowAnyOrigin = true;
24603
- console.warn("[CORS] CORS_ALLOW_ANY_ORIGIN=true: any request origin can receive non-credentialed responses; cookie-authenticated responses still require CORS_ALLOWED_ORIGINS. Set CORS_ALLOWED_ORIGINS and disable CORS_ALLOW_ANY_ORIGIN to restrict access.");
24604
- }
24605
- }
24606
- function getAllowedOrigins() {
24607
- const raw = process.env.CORS_ALLOWED_ORIGINS;
24608
- if (!raw || !raw.trim())
24609
- return DEFAULT_ALLOWED_ORIGINS;
24610
- return raw.split(",").map((entry) => entry.trim()).filter(Boolean);
24611
- }
24612
- function isDevLoopbackOrigin(origin) {
24613
- if (getNodeEnv() !== "development")
24614
- return false;
24615
- return /^https?:\/\/(localhost|127\.0\.0\.1|\[::1\])(:\d{1,5})?$/.test(origin);
24616
- }
24617
- function originAllowedForCredentials(origin) {
24618
- if (isDevLoopbackOrigin(origin))
24619
- return true;
24620
- return getAllowedOrigins().some((entry) => {
24621
- if (!entry.includes("*"))
24622
- return entry === origin;
24623
- const pattern = /^([a-zA-Z][a-zA-Z0-9+.-]*):\/\/\*\.([a-zA-Z0-9.-]+)(:\d+)?$/.exec(entry);
24624
- const candidate = /^([a-zA-Z][a-zA-Z0-9+.-]*):\/\/([a-zA-Z0-9.-]+)(:\d+)?$/.exec(origin);
24625
- if (!pattern || !candidate)
24626
- return false;
24627
- if (pattern[1] !== candidate[1] || pattern[3] !== candidate[3])
24628
- return false;
24629
- const suffix = pattern[2].toLowerCase();
24630
- const hostname = candidate[2].toLowerCase();
24631
- const validLabel = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
24632
- if (![...suffix.split("."), ...hostname.split(".")].every((label) => validLabel.test(label))) {
24633
- return false;
24634
- }
24635
- return hostname.endsWith(`.${suffix}`);
24636
- });
24637
- }
24638
- function isOriginAllowedForCredentials(origin) {
24639
- const allowed = originAllowedForCredentials(origin);
24640
- if (!allowed) {
24641
- console.warn(`[CORS] Denied credentialed origin ${scrubSecrets(JSON.stringify(origin.slice(0, 512)))}; add the trusted SPA origin to CORS_ALLOWED_ORIGINS (custom values replace hosted/dev defaults).`);
24642
- }
24643
- return allowed;
24644
- }
24645
- function allowedCredentialRedirect(raw) {
24646
- if (!raw)
24647
- return;
24648
- try {
24649
- const redirect = new URL(raw);
24650
- if (redirect.protocol !== "http:" && redirect.protocol !== "https:")
24651
- return;
24652
- return originAllowedForCredentials(redirect.origin) ? redirect.toString() : undefined;
24653
- } catch {
24654
- return;
24655
- }
24656
- }
24657
- function setCorsHeaders(req, res) {
24658
- const rawOrigin = req.headers.origin;
24659
- const origin = Array.isArray(rawOrigin) ? rawOrigin[0] : rawOrigin;
24660
- const allowCredentials = origin ? isOriginAllowedForCredentials(origin) : false;
24661
- const allowAnyOrigin = isEnvFlagEnabled("CORS_ALLOW_ANY_ORIGIN", false);
24662
- if (allowAnyOrigin)
24663
- warnIfCorsAllowsAnyOrigin();
24664
- if (origin && !allowCredentials && !allowAnyOrigin) {
24665
- res.setHeader("Vary", "Origin");
24666
- return;
24667
- }
24668
- if (origin) {
24669
- res.setHeader("Access-Control-Allow-Origin", origin);
24670
- res.setHeader("Vary", "Origin");
24671
- if (allowCredentials)
24672
- res.setHeader("Access-Control-Allow-Credentials", "true");
24673
- const reqHeaders = req.headers["access-control-request-headers"];
24674
- const askedHeaders = Array.isArray(reqHeaders) ? reqHeaders.join(", ") : reqHeaders;
24675
- res.setHeader("Access-Control-Allow-Headers", askedHeaders ?? "Authorization, Content-Type, X-Agent-ID, X-Requested-With, X-Swarm-User-Id");
24676
- res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS");
24677
- res.setHeader("Access-Control-Expose-Headers", "Content-Type, Content-Length, ETag, Location");
24678
- } else {
24679
- res.setHeader("Access-Control-Allow-Origin", "*");
24680
- res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS");
24681
- res.setHeader("Access-Control-Allow-Headers", "*");
24682
- res.setHeader("Access-Control-Expose-Headers", "*");
24683
- }
24684
- }
24685
- function parseQueryParams(url) {
24686
- const queryIndex = url.indexOf("?");
24687
- if (queryIndex === -1)
24688
- return new URLSearchParams;
24689
- return new URLSearchParams(url.slice(queryIndex + 1));
24690
- }
24691
- function getPathSegments(url) {
24692
- const pathEnd = url.indexOf("?");
24693
- const path = pathEnd === -1 ? url : url.slice(0, pathEnd);
24694
- return path.split("/").filter(Boolean);
24695
- }
24696
- function abortedStatusCodeAttribute(headersSent, statusCode) {
24697
- return headersSent ? statusCode : undefined;
24698
- }
24699
- function wireHttpSpanLifecycle(res, span, getStatusCode, startTime) {
24700
- let spanEnded = false;
24701
- res.on("finish", () => {
24702
- if (spanEnded)
24703
- return;
24704
- spanEnded = true;
24705
- const statusCode = getStatusCode();
24706
- span.setAttributes({
24707
- "http.response.status_code": statusCode,
24708
- "agentswarm.http.duration_ms": Math.round((performance.now() - startTime) * 10) / 10
24709
- });
24710
- if (statusCode >= 500) {
24711
- span.setStatus({ code: 2, message: `HTTP ${statusCode}` });
24712
- }
24713
- span.end();
24714
- });
24715
- res.on("error", (err) => {
24716
- if (spanEnded)
24717
- return;
24718
- spanEnded = true;
24719
- if (err)
24720
- span.recordException(err);
24721
- span.setStatus({ code: 2, message: err?.message });
24722
- span.end();
24723
- });
24724
- res.on("close", () => {
24725
- if (spanEnded)
24726
- return;
24727
- spanEnded = true;
24728
- span.setAttributes({
24729
- "http.response.status_code": abortedStatusCodeAttribute(res.headersSent, getStatusCode()),
24730
- "agentswarm.http.duration_ms": Math.round((performance.now() - startTime) * 10) / 10,
24731
- "agentswarm.http.aborted": true
24732
- });
24733
- span.end();
24734
- });
24735
- }
24736
- function safeRequestUrlForLog(rawUrl) {
24737
- if (!rawUrl)
24738
- return "";
24739
- try {
24740
- const url = new URL(rawUrl, "http://localhost");
24741
- const params = Array.from(url.searchParams.keys());
24742
- if (params.length === 0)
24743
- return url.pathname;
24744
- const redactedQuery = params.map((key) => `${key}=[REDACTED]`).join("&");
24745
- return `${url.pathname}?${redactedQuery}`;
24746
- } catch {
24747
- const pathOnly = rawUrl.split("?")[0] || rawUrl;
24748
- return scrubSecrets(pathOnly);
24749
- }
24750
- }
24751
- async function agentWithCapacity(agent) {
24752
- const activeCount = await getActiveTaskCount2(agent.id);
24753
- const max = agent.maxTasks ?? 1;
24754
- return {
24755
- ...agent,
24756
- capacity: {
24757
- current: activeCount,
24758
- max,
24759
- available: Math.max(0, max - activeCount)
24760
- }
24761
- };
24762
- }
24763
-
24764
- class RequestBodyTooLargeError extends Error {
24765
- maxBytes;
24766
- constructor(maxBytes) {
24767
- super(`Payload too large (max ${maxBytes} bytes)`);
24768
- this.name = "RequestBodyTooLargeError";
24769
- this.maxBytes = maxBytes;
24770
- }
24771
- }
24772
- function requestContentLength(req) {
24773
- const raw = req.headers["content-length"];
24774
- const value = Array.isArray(raw) ? raw[0] : raw;
24775
- if (!value)
24776
- return;
24777
- const parsed = Number(value);
24778
- return Number.isFinite(parsed) && parsed >= 0 ? parsed : undefined;
24779
- }
24780
- async function parseBody(req, maxBytes = Number.POSITIVE_INFINITY) {
24781
- const contentLength = requestContentLength(req);
24782
- if (contentLength !== undefined && contentLength > maxBytes) {
24783
- req.resume();
24784
- throw new RequestBodyTooLargeError(maxBytes);
24785
- }
24786
- return await new Promise((resolve, reject) => {
24787
- const chunks = [];
24788
- let totalBytes = 0;
24789
- let settled = false;
24790
- const cleanup = () => {
24791
- req.off("data", onData);
24792
- req.off("end", onEnd);
24793
- req.off("error", onError);
24794
- req.off("aborted", onAborted);
24795
- req.off("close", onClose);
24796
- };
24797
- const rejectTooLarge = () => {
24798
- if (settled)
24799
- return;
24800
- settled = true;
24801
- reject(new RequestBodyTooLargeError(maxBytes));
24802
- req.resume();
24803
- };
24804
- const onData = (chunk) => {
24805
- if (settled)
24806
- return;
24807
- const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
24808
- totalBytes += buffer.byteLength;
24809
- if (totalBytes > maxBytes) {
24810
- rejectTooLarge();
24811
- return;
24812
- }
24813
- chunks.push(buffer);
24814
- };
24815
- const onEnd = () => {
24816
- if (settled) {
24817
- cleanup();
24818
- return;
24819
- }
24820
- settled = true;
24821
- cleanup();
24822
- const raw = Buffer.concat(chunks).toString();
24823
- if (raw.trim() === "") {
24824
- resolve({});
24825
- return;
24826
- }
24827
- try {
24828
- resolve(JSON.parse(raw));
24829
- } catch (error) {
24830
- reject(error);
24831
- }
24832
- };
24833
- const onError = (error) => {
24834
- cleanup();
24835
- if (!settled) {
24836
- settled = true;
24837
- reject(error);
24838
- }
24839
- };
24840
- const onAborted = () => onError(new Error("Request body was aborted"));
24841
- const onClose = () => {
24842
- if (!req.readableEnded)
24843
- onError(new Error("Request body closed before completion"));
24844
- };
24845
- req.on("data", onData);
24846
- req.on("end", onEnd);
24847
- req.on("error", onError);
24848
- req.on("aborted", onAborted);
24849
- req.on("close", onClose);
24850
- req.resume();
24851
- });
24852
- }
24853
- var BODY_TOO_LARGE = Symbol("body-too-large");
24854
- function enforceContentLengthCap(req, res, maxBytes) {
24855
- const raw = req.headers["content-length"];
24856
- const val = Array.isArray(raw) ? raw[0] : raw;
24857
- if (!val)
24858
- return null;
24859
- const n = Number(val);
24860
- if (!Number.isFinite(n) || n < 0)
24861
- return null;
24862
- if (n > maxBytes) {
24863
- res.writeHead(413, { "Content-Type": "application/json" });
24864
- res.end(JSON.stringify({ error: `Payload too large (max ${maxBytes} bytes)` }));
24865
- return BODY_TOO_LARGE;
24866
- }
24867
- return null;
24868
- }
24869
- function json(res, data, status = 200) {
24870
- res.writeHead(status, { "Content-Type": "application/json" });
24871
- res.end(JSON.stringify(data));
24872
- }
24873
- function jsonError(res, error, status = 400) {
24874
- res.writeHead(status, { "Content-Type": "application/json" });
24875
- res.end(JSON.stringify({ error: scrubSecrets(error) }));
24876
- }
24877
- function writeUnhandledError(res, err, req) {
24878
- const message = err instanceof Error ? err.message : String(err);
24879
- console.error(`[HTTP] ❌ ${req?.method ?? ""} ${safeRequestUrlForLog(req?.url)} → ${scrubSecrets(message)}`);
24880
- if (!res.headersSent) {
24881
- jsonError(res, message, 500);
24882
- } else if (!res.writableEnded) {
24883
- res.end();
24884
- }
24885
- }
24886
- function triggerSchemaErrorResponse(res, message, details) {
24887
- res.writeHead(400, { "Content-Type": "application/json" });
24888
- res.end(JSON.stringify({ error: "TriggerSchemaError", message, details }));
24889
- }
24890
- function deriveApiBaseUrl(req) {
24891
- const publicBase = process.env.PUBLIC_MCP_BASE_URL?.trim();
24892
- if (publicBase)
24893
- return publicBase.replace(/\/+$/, "");
24894
- const envBase = process.env.MCP_BASE_URL?.trim();
24895
- if (envBase)
24896
- return envBase.replace(/\/+$/, "");
24897
- const fwdProtoRaw = req.headers["x-forwarded-proto"];
24898
- const fwdHostRaw = req.headers["x-forwarded-host"];
24899
- const fwdProto = Array.isArray(fwdProtoRaw) ? fwdProtoRaw[0] : fwdProtoRaw;
24900
- const fwdHost = Array.isArray(fwdHostRaw) ? fwdHostRaw[0] : fwdHostRaw;
24901
- const proto = fwdProto?.split(",")[0]?.trim() || "http";
24902
- const host = fwdHost?.split(",")[0]?.trim() || req.headers.host;
24903
- if (host)
24904
- return `${proto}://${host}`;
24905
- return `http://localhost:${process.env.PORT || "3013"}`;
24906
- }
24907
- function httpServerSemconvAttributes(req) {
24908
- const headerValue = (v) => Array.isArray(v) ? v[0] : v;
24909
- const firstHop = (v) => headerValue(v)?.split(",")[0]?.trim() || undefined;
24910
- const fwdProto = firstHop(req.headers["x-forwarded-proto"]);
24911
- const host = firstHop(req.headers["x-forwarded-host"]) ?? headerValue(req.headers.host)?.trim();
24912
- return {
24913
- "server.address": host ? host.replace(/:\d+$/, "") || undefined : undefined,
24914
- "url.scheme": fwdProto ?? "http",
24915
- "network.protocol.version": req.httpVersion || undefined,
24916
- "user_agent.original": headerValue(req.headers["user-agent"])
24917
- };
24918
- }
24919
- function matchRoute(method, pathSegments, expectedMethod, pattern, exact = false) {
24920
- if (method !== expectedMethod)
24921
- return false;
24922
- for (let i = 0;i < pattern.length; i++) {
24923
- const seg = pattern[i];
24924
- if (seg === null) {
24925
- if (!pathSegments[i])
24926
- return false;
24927
- } else {
24928
- if (pathSegments[i] !== seg)
24929
- return false;
24930
- }
24931
- }
24932
- if (exact && pathSegments[pattern.length])
24933
- return false;
24934
- return true;
24935
- }
24936
-
24937
- // src/http/route-def.ts
24938
- var runtimeInstanceHeader = (operation) => object2({
24939
- "X-Runtime-Instance-ID": string2().optional().describe("Identifies the concrete runtime instance (worker process) making the call, " + `as generated at its boot. Required to ${operation} when multi-runtime mode ` + "(MULTI_RUNTIME_ENABLED) is on; ignored otherwise.")
24940
- });
24941
- var routeRegistry = [];
24942
- function isPublicRoute(method, pathSegments) {
24943
- for (const def of routeRegistry) {
24944
- if (def.auth?.apiKey === false) {
24945
- if (matchRoute(method, pathSegments, def.method.toUpperCase(), def.pattern, def.exact ?? true)) {
24946
- return true;
24947
- }
24948
- }
24949
- }
24950
- return false;
24951
- }
24952
- function findRoute(method, pathSegments) {
24953
- for (const def of routeRegistry) {
24954
- if (matchRoute(method, pathSegments, def.method.toUpperCase(), def.pattern, def.exact ?? true)) {
24955
- return def;
24956
- }
24957
- }
24958
- return;
24959
- }
24960
- var CORE_ROUTE_TEMPLATES = {
24961
- health: { path: "/health" },
24962
- "openapi.json": { path: "/openapi.json" },
24963
- docs: { path: "/docs", toleratesTrailingSlash: true },
24964
- me: { path: "/me", methods: ["GET"], toleratesQueryString: true },
24965
- "cancelled-tasks": {
24966
- path: "/cancelled-tasks",
24967
- methods: ["GET"],
24968
- toleratesQueryString: true
24969
- },
24970
- "internal/reload-config": { path: "/internal/reload-config", methods: ["POST"] },
24971
- mcp: { path: "/mcp", methods: ["GET", "POST", "DELETE"] },
24972
- "mcp-user": { path: "/mcp-user", methods: ["GET", "POST", "DELETE"] }
24973
- };
24974
- function describeRequestRoute(method, pathSegments, hasQueryString = false, hasTrailingSlash = false) {
24975
- const m = (method ?? "").toUpperCase() || "UNKNOWN";
24976
- const matched = findRoute(method, pathSegments);
24977
- if (matched)
24978
- return { spanName: `${m} ${matched.path}`, httpRoute: matched.path };
24979
- const coreTemplate = CORE_ROUTE_TEMPLATES[pathSegments.join("/")];
24980
- if (coreTemplate && (!coreTemplate.methods || coreTemplate.methods.includes(m)) && (!hasQueryString || coreTemplate.toleratesQueryString) && (!hasTrailingSlash || coreTemplate.toleratesTrailingSlash)) {
24981
- return { spanName: `${m} ${coreTemplate.path}`, httpRoute: coreTemplate.path };
24982
- }
24983
- const first = pathSegments[0];
24984
- return { spanName: first ? `${m} /${first}` : m };
24985
- }
24986
- var VALIDATE_RESPONSES = getNodeEnv() === "test" || getNodeEnv() === "development" || process.env.VALIDATE_HTTP_RESPONSES === "true";
24987
- function route(def) {
24988
- routeRegistry.push(def);
24989
- return {
24990
- def,
24991
- respond(res, code, data) {
24992
- if (VALIDATE_RESPONSES) {
24993
- const schema = def.responses[code]?.schema;
24994
- if (schema) {
24995
- const result = schema.safeParse(data);
24996
- if (!result.success) {
24997
- const detail = `Response schema violation: ${def.method.toUpperCase()} ${def.path} ${code} — ` + result.error.issues.map((i) => `${i.path.join(".") || "<root>"}: ${i.message}`).join("; ");
24998
- if (getNodeEnv() === "test") {
24999
- throw new Error(detail);
25000
- }
25001
- console.error(`[route-def] ${scrubSecrets(detail)}`);
25002
- }
25003
- }
25004
- }
25005
- res.writeHead(code, { "Content-Type": "application/json" });
25006
- res.end(JSON.stringify(data));
25007
- },
25008
- match(method, pathSegments) {
25009
- return matchRoute(method, pathSegments, def.method.toUpperCase(), def.pattern, def.exact ?? true);
25010
- },
25011
- async parse(req, res, pathSegments, queryParams) {
25012
- try {
25013
- const rawParams = {};
25014
- if (def.params) {
25015
- const paramNames = def.path.match(/\{(\w+)\}/g)?.map((p) => p.slice(1, -1)) ?? [];
25016
- for (let i = 0;i < def.pattern.length; i++) {
25017
- if (def.pattern[i] === null && paramNames.length > 0) {
25018
- rawParams[paramNames.shift()] = pathSegments[i] ?? "";
25019
- }
25020
- }
25021
- }
25022
- const params = def.params ? def.params.parse(rawParams) : undefined;
25023
- const query = def.query ? def.query.parse(Object.fromEntries(queryParams)) : undefined;
25024
- const body = def.body ? def.body.parse(await parseBody(req, def.maxBodyBytes)) : undefined;
25025
- return { params, query, body };
25026
- } catch (err) {
25027
- if (err instanceof ZodError) {
25028
- jsonError(res, `Validation error: ${err.issues.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ")}`, 400);
25029
- return null;
25030
- }
25031
- if (err instanceof RequestBodyTooLargeError) {
25032
- jsonError(res, err.message, 413);
25033
- return null;
25034
- }
25035
- throw err;
25036
- }
25037
- }
25038
- };
25039
- }
25040
-
25041
24603
  // src/http/mcp-bridge.ts
25042
24604
  var _bridgeServer = null;
25043
24605
  async function getBridgeServer() {
@@ -31701,7 +31263,7 @@ async function loadAdapter(name, config, logger) {
31701
31263
  return createTelegramAdapter({ ...base, allowUnverifiedWebhooks: false });
31702
31264
  }
31703
31265
  case "slack": {
31704
- const { createSlackAdapter } = await import("./index-g909y089.js");
31266
+ const { createSlackAdapter } = await import("./index-zgvqzjsw.js");
31705
31267
  return createSlackAdapter({
31706
31268
  ...base,
31707
31269
  signingSecret: config.signingSecret ?? "",
@@ -31720,7 +31282,7 @@ async function loadAdapter(name, config, logger) {
31720
31282
  });
31721
31283
  }
31722
31284
  case "teams": {
31723
- const { createTeamsAdapter } = await import("./index-x0q2a4f9.js");
31285
+ const { createTeamsAdapter } = await import("./index-ysd45kgc.js");
31724
31286
  const { teamsWebhookVerifier, teamsToken } = getChatSdkTestHooks();
31725
31287
  return createTeamsAdapter({
31726
31288
  ...base,
@@ -34256,7 +33818,7 @@ async function notifySlack(text) {
34256
33818
  return;
34257
33819
  }
34258
33820
  try {
34259
- const { getSlackApp } = await import("./app-4e1s4675.js");
33821
+ const { getSlackApp } = await import("./app-kreq1gwg.js");
34260
33822
  const app = getSlackApp();
34261
33823
  if (!app) {
34262
33824
  console.warn("[Jira webhook keepalive] Slack not available, cannot send notification");
@@ -34327,7 +33889,7 @@ async function deleteJiraWebhook(webhookId) {
34327
33889
  console.log(`[Jira webhook keepalive] Deleted webhook id=${webhookId}`);
34328
33890
  }
34329
33891
  async function overwriteWebhookIds(next) {
34330
- const { getDbClient } = await import("./db-hy80219q.js");
33892
+ const { getDbClient } = await import("./db-w505dwa8.js");
34331
33893
  await getDbClient().transaction(async (tx) => {
34332
33894
  const row = await tx.get("SELECT metadata FROM oauth_apps WHERE provider = 'jira'");
34333
33895
  if (!row) {
@@ -107677,7 +107239,7 @@ async function reloadGlobalConfigsAndIntegrations() {
107677
107239
  return runWithoutRequestAuth(() => reloadGlobalConfigsAndIntegrationsInner());
107678
107240
  }
107679
107241
  async function reloadGlobalConfigsAndIntegrationsInner() {
107680
- const { getEmbeddingProvider, resetEmbeddingProvider } = await import("./index-epr2gnbw.js");
107242
+ const { getEmbeddingProvider, resetEmbeddingProvider } = await import("./index-x5aktmp8.js");
107681
107243
  const wasEmbeddingsConfigured = getEmbeddingProvider().isConfigured();
107682
107244
  const updated = await loadGlobalConfigsIntoEnv(true);
107683
107245
  await syncTelemetryEnabled("settings").catch((err) => {
@@ -107693,10 +107255,10 @@ async function reloadGlobalConfigsAndIntegrationsInner() {
107693
107255
  integrations.push("embeddings");
107694
107256
  }
107695
107257
  if (!wasEmbeddingsConfigured && isEmbeddingsConfigured) {
107696
- import("./boot-reembed-p666cw5n.js").then(({ runBootReembed }) => runBootReembed()).catch((err) => {
107258
+ import("./boot-reembed-e53x6b9v.js").then(({ runBootReembed }) => runBootReembed()).catch((err) => {
107697
107259
  console.error("[config-reload] memory backfill failed (non-fatal):", err);
107698
107260
  });
107699
- import("./boot-reembed-w6pm64j4.js").then(({ runBootReembedScripts }) => runBootReembedScripts()).catch((err) => {
107261
+ import("./boot-reembed-f6z923ny.js").then(({ runBootReembedScripts }) => runBootReembedScripts()).catch((err) => {
107700
107262
  console.error("[config-reload] script backfill failed (non-fatal):", err);
107701
107263
  });
107702
107264
  }
@@ -107854,6 +107416,12 @@ async function handleCore(req, res, myAgentId, apiKey) {
107854
107416
  }
107855
107417
  setRequestAuth(req, auth);
107856
107418
  }
107419
+ const routeDef = findRoute(req.method, pathSegments);
107420
+ const agentIdentityDenial = await userAgentIdentityDenial2(req, routeDef, pathSegments);
107421
+ if (agentIdentityDenial) {
107422
+ jsonError(res, agentIdentityDenial, 403);
107423
+ return true;
107424
+ }
107857
107425
  if (auth?.kind === "agent") {
107858
107426
  const query = parseQueryParams(req.url || "");
107859
107427
  const duplicate = duplicateGuardedQueryKey(query);
@@ -107905,7 +107473,7 @@ async function handleCore(req, res, myAgentId, apiKey) {
107905
107473
  if (auth?.kind === "user" && isRbacEnabled()) {
107906
107474
  const grant = await getUserGrant2(auth.userId);
107907
107475
  if (!grant.grantsAll) {
107908
- const def = findRoute(req.method, pathSegments);
107476
+ const def = routeDef;
107909
107477
  const decision = decideAdmission({
107910
107478
  method: req.method ?? "",
107911
107479
  rbac: def?.rbac,
@@ -107924,6 +107492,13 @@ async function handleCore(req, res, myAgentId, apiKey) {
107924
107492
  }
107925
107493
  }
107926
107494
  }
107495
+ if (routeDef?.session) {
107496
+ const sessionDenial = await pathSessionDenial2(req, myAgentId, routeDef, pathSegments);
107497
+ if (sessionDenial) {
107498
+ jsonError(res, sessionDenial, 403);
107499
+ return true;
107500
+ }
107501
+ }
107927
107502
  if (req.method === "POST" && req.url === "/internal/reload-config") {
107928
107503
  try {
107929
107504
  const result = await reloadGlobalConfigsAndIntegrations();
@@ -107979,7 +107554,13 @@ async function handleCore(req, res, myAgentId, apiKey) {
107979
107554
  }
107980
107555
  const queryParams = parseQueryParams(req.url || "");
107981
107556
  const taskId = queryParams.get("taskId");
107557
+ const sessionActor = await resolveSessionActor2(req, myAgentId);
107982
107558
  if (taskId) {
107559
+ if (!await canReadSession2(req, myAgentId, taskId)) {
107560
+ res.writeHead(403, { "Content-Type": "application/json" });
107561
+ res.end(JSON.stringify({ error: SESSION_READ_DENIED2 }));
107562
+ return true;
107563
+ }
107983
107564
  const task = await getTaskById2(taskId);
107984
107565
  if (task && task.status === "cancelled") {
107985
107566
  res.writeHead(200, { "Content-Type": "application/json" });
@@ -107998,7 +107579,7 @@ async function handleCore(req, res, myAgentId, apiKey) {
107998
107579
  res.end(JSON.stringify({ cancelled: [] }));
107999
107580
  return true;
108000
107581
  }
108001
- const cancelledTasks = await getRecentlyCancelledTasksForAgent2(myAgentId);
107582
+ const cancelledTasks = await getRecentlyCancelledTasksForAgent2(myAgentId, readableByFor2(sessionActor));
108002
107583
  res.writeHead(200, { "Content-Type": "application/json" });
108003
107584
  res.end(JSON.stringify({ cancelled: cancelledTasks }));
108004
107585
  return true;
@@ -108212,15 +107793,21 @@ var registerAcceptSteerTool = (server) => {
108212
107793
  }, async (args, info, _meta) => acceptSteerHandler(ownerCtx(info), args));
108213
107794
  };
108214
107795
 
108215
- // src/tools/app-diff.ts
107796
+ // src/tools/app-action-run.ts
108216
107797
  init_zod();
108217
107798
 
108218
- // src/apps/version.ts
107799
+ // src/apps/action-runner.ts
107800
+ init_key();
108219
107801
  init_db3();
107802
+ init_db2();
107803
+ init_resolver();
107804
+ init_secret_scrubber();
108220
107805
 
108221
- // src/apps/schema-migrate.ts
107806
+ // src/apps/sync.ts
108222
107807
  init_zod();
108223
107808
  init_db3();
107809
+ init_db2();
107810
+ init_types();
108224
107811
  init_secret_scrubber();
108225
107812
 
108226
107813
  // src/apps/row-store.ts
@@ -108560,14 +108147,14 @@ async function rebuildAppColumnIndexUnlocked(appId, model, columnName, column, r
108560
108147
  });
108561
108148
  }
108562
108149
  }
108563
- function deleteAppRow(appId, model, _definition, rowId) {
108150
+ function deleteAppRow(appId, model, _definition, rowId, matches) {
108564
108151
  return withMutationLock(appId, model, async () => {
108565
108152
  const currentDefinition = await currentModelDefinition(appId, model);
108566
108153
  if (!currentDefinition)
108567
108154
  return false;
108568
108155
  const namespace = appsNamespace(appId);
108569
108156
  const row = await getAppRow(appId, model, rowId);
108570
- if (!row)
108157
+ if (!row || matches && !matches(row))
108571
108158
  return false;
108572
108159
  for (const key of indexKeys(model, currentDefinition, row))
108573
108160
  await deleteKv2(namespace, key);
@@ -108602,11 +108189,6 @@ function purgeAppRows(appId, models, afterPurge) {
108602
108189
  }
108603
108190
 
108604
108191
  // src/apps/sync.ts
108605
- init_zod();
108606
- init_db3();
108607
- init_db2();
108608
- init_types();
108609
- init_secret_scrubber();
108610
108192
  var MAX_PULL_RECORDS = 500;
108611
108193
  var MAX_PASS_WARNINGS = 20;
108612
108194
  var MAX_TASK_LIMIT = 200;
@@ -109192,7 +108774,176 @@ async function runAppSync(input) {
109192
108774
  return { ok: passes.every((pass) => pass.error === undefined), passes };
109193
108775
  }
109194
108776
 
108777
+ // src/apps/action-runner.ts
108778
+ function syncPassError(sync) {
108779
+ const failed = sync.passes.filter((pass) => pass.error !== undefined);
108780
+ if (failed.length === 0)
108781
+ return;
108782
+ return failed.map((pass) => `${pass.model}.${pass.source}: ${pass.error}`).join("; ");
108783
+ }
108784
+ async function runAppAction({
108785
+ app,
108786
+ name,
108787
+ input = {},
108788
+ caller,
108789
+ actor
108790
+ }) {
108791
+ const actions = app.definition.actions;
108792
+ if (!actions || !Object.hasOwn(actions, name)) {
108793
+ return { status: 404, body: { error: "app action not found" } };
108794
+ }
108795
+ const action = actions[name];
108796
+ if (action.kind === "script") {
108797
+ const script = await getScriptById(action.scriptId);
108798
+ if (!script) {
108799
+ return {
108800
+ status: 400,
108801
+ body: {
108802
+ error: "invalid app action",
108803
+ issues: [
108804
+ {
108805
+ path: `actions.${name}.scriptId`,
108806
+ message: `script "${action.scriptId}" no longer exists`
108807
+ }
108808
+ ]
108809
+ }
108810
+ };
108811
+ }
108812
+ const runAsAgentId = getSavedScriptOwnerAgentId(script);
108813
+ if (!runAsAgentId) {
108814
+ return {
108815
+ status: 400,
108816
+ body: { error: "agentId is required: this script has no owning agent to run as" }
108817
+ };
108818
+ }
108819
+ const output = await runSavedScriptAsAgent({
108820
+ script,
108821
+ input: { ...action.args, ...input, app: { id: app.id }, caller },
108822
+ agentId: runAsAgentId
108823
+ });
108824
+ const ok = output.exitCode === 0 && !output.error && !output.runtimeError;
108825
+ const error = ok ? undefined : output.runtimeError ? `${output.runtimeError.name}: ${output.runtimeError.message}` : output.error ?? `Script exited with code ${output.exitCode}`;
108826
+ return {
108827
+ status: 200,
108828
+ body: scrubObject({
108829
+ ok,
108830
+ result: output.result,
108831
+ stdout: output.stdout,
108832
+ ...error === undefined ? {} : { error },
108833
+ durationMs: output.durationMs
108834
+ })
108835
+ };
108836
+ }
108837
+ if (action.kind === "sync") {
108838
+ const startedAt = Date.now();
108839
+ const sync = await runAppSync({
108840
+ appId: app.id,
108841
+ ...action.model === undefined ? {} : { model: action.model },
108842
+ ...action.source === undefined ? {} : { source: action.source },
108843
+ invokedBy: actor
108844
+ });
108845
+ const durationMs = Date.now() - startedAt;
108846
+ if (sync.issues && sync.issues.length > 0) {
108847
+ return { status: 400, body: { error: "invalid sync action", issues: sync.issues } };
108848
+ }
108849
+ const error = syncPassError(sync);
108850
+ return {
108851
+ status: 200,
108852
+ body: scrubObject({
108853
+ ok: sync.ok,
108854
+ result: { passes: sync.passes },
108855
+ ...error === undefined ? {} : { error },
108856
+ durationMs
108857
+ })
108858
+ };
108859
+ }
108860
+ const lead = action.agentId ? null : await getLeadAgent2();
108861
+ const taskPrompt = resolveTemplate("task.app.action", {
108862
+ prompt: action.prompt,
108863
+ app_id: app.id,
108864
+ action_name: name,
108865
+ input_json: JSON.stringify(input),
108866
+ caller_json: JSON.stringify(caller)
108867
+ });
108868
+ const task = await createTaskWithSiblingAwareness(taskPrompt.text, {
108869
+ source: "api",
108870
+ agentId: action.agentId ?? lead?.id,
108871
+ routingReason: action.agentId ? "human_pinned" : lead ? "skill" : undefined,
108872
+ routingSource: action.agentId || lead ? "engine_default" : undefined,
108873
+ key: normalizeAssetKey(`shared/app:${app.id}/action:${name}/`),
108874
+ ...actor.startsWith("user:") ? { requestedByUserId: actor.slice("user:".length) } : {}
108875
+ }, { origin: "app" });
108876
+ return {
108877
+ status: 200,
108878
+ body: { ok: true, taskId: task.id, status: task.status }
108879
+ };
108880
+ }
108881
+
108882
+ // src/tools/app-action-run.ts
108883
+ init_db3();
108884
+ init_rbac();
108885
+ function registerAppActionRunTool(server) {
108886
+ createToolRegistrar(server)("app-action-run", {
108887
+ title: "Run an app action",
108888
+ description: "Run a declared app action as an agent. Scripts and extensions cannot invoke this tool.",
108889
+ annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true },
108890
+ rbac: { permission: "app.use" },
108891
+ inputSchema: object2({
108892
+ appId: string2().min(1),
108893
+ action: AppNameSchema,
108894
+ input: record2(string2(), unknown()).optional()
108895
+ }),
108896
+ outputSchema: swarmToolOutputSchema({
108897
+ ok: boolean().optional(),
108898
+ result: unknown().optional(),
108899
+ stdout: string2().optional(),
108900
+ error: string2().optional(),
108901
+ durationMs: number2().optional(),
108902
+ taskId: string2().optional(),
108903
+ status: string2().optional()
108904
+ })
108905
+ }, async ({ appId, action, input }, info) => {
108906
+ if (info.callOrigin === "script-sdk" || info.callOrigin === "extension")
108907
+ return toolErr("Scripts and extensions cannot run app actions.");
108908
+ if (!info.agentId)
108909
+ return toolErr('Agent ID not found. Set the "X-Agent-ID" header.');
108910
+ const agent = await getAgentById2(info.agentId);
108911
+ const decision = can({
108912
+ principal: { kind: "agent", agentId: info.agentId, isLead: agent?.isLead ?? false },
108913
+ verb: "app.use",
108914
+ resource: { kind: "app", appId },
108915
+ source: "mcp"
108916
+ });
108917
+ if (!decision.allow)
108918
+ return toolErr(decision.reason);
108919
+ const app = await getApp(appId);
108920
+ if (!app)
108921
+ return toolErr("App not found.");
108922
+ if (appDefinitionNeedsRepair(app))
108923
+ return toolErr("App definition needs repair.", { data: { issues: app.definitionError } });
108924
+ const output = await runAppAction({
108925
+ app,
108926
+ name: action,
108927
+ input,
108928
+ actor: `agent:${info.agentId}`,
108929
+ caller: { kind: "agent", id: info.agentId, ...agent?.name ? { name: agent.name } : {} }
108930
+ });
108931
+ if (output.status !== 200)
108932
+ return toolErr(output.body.error ?? "Action failed.", { data: output.body });
108933
+ return toolOk("Action invoked.", { data: output.body });
108934
+ });
108935
+ }
108936
+
108937
+ // src/tools/app-diff.ts
108938
+ init_zod();
108939
+
108940
+ // src/apps/version.ts
108941
+ init_db3();
108942
+
109195
108943
  // src/apps/schema-migrate.ts
108944
+ init_zod();
108945
+ init_db3();
108946
+ init_secret_scrubber();
109196
108947
  var MigrationValueSchema = union2([string2(), number2(), boolean()]);
109197
108948
  var AppMigrationDirectiveSchema = union2([
109198
108949
  object2({ set: MigrationValueSchema }).strict(),
@@ -110288,86 +110039,11 @@ async function upsertAppUserConfigValues(appId, scope, values) {
110288
110039
  }
110289
110040
 
110290
110041
  // src/http/apps.ts
110291
- init_key();
110292
110042
  init_db3();
110293
- init_db2();
110294
- init_resolver();
110295
110043
  init_rbac();
110296
110044
  init_types();
110297
110045
  init_request_auth_context();
110298
110046
  init_secret_scrubber();
110299
-
110300
- // src/be/audit-user.ts
110301
- init_request_auth_context();
110302
- init_db3();
110303
- init_users();
110304
- async function resolveTaskAuditUserId(sourceTaskId, callerAgentId) {
110305
- if (!callerAgentId)
110306
- return null;
110307
- let resolvedSourceTaskId = sourceTaskId;
110308
- if (!resolvedSourceTaskId) {
110309
- const currentTask = await getAgentCurrentTask2(callerAgentId);
110310
- if (currentTask)
110311
- resolvedSourceTaskId = currentTask.id;
110312
- }
110313
- if (!resolvedSourceTaskId)
110314
- return null;
110315
- const task = await getTaskById2(resolvedSourceTaskId);
110316
- if (!task)
110317
- return null;
110318
- if (task.agentId !== callerAgentId)
110319
- return null;
110320
- if (task.requestedByUserId)
110321
- return task.requestedByUserId;
110322
- if (task.slackUserId) {
110323
- const user = await findUserByExternalId("slack", task.slackUserId);
110324
- if (user)
110325
- return user.id;
110326
- }
110327
- return null;
110328
- }
110329
- async function resolveHttpAuditUserId(req, callerAgentId) {
110330
- const auth = getRequestAuth(req);
110331
- if (auth?.kind === "user")
110332
- return auth.userId;
110333
- const header = req.headers["x-source-task-id"];
110334
- const sourceTaskId = Array.isArray(header) ? header[0] : header;
110335
- return resolveTaskAuditUserId(sourceTaskId, callerAgentId);
110336
- }
110337
-
110338
- // src/http/favorite-owner.ts
110339
- init_users();
110340
- init_request_auth_context();
110341
- var DASHBOARD_USER_HEADER = "x-swarm-user-id";
110342
- function dashboardUserIdHeader(req) {
110343
- const raw = req.headers[DASHBOARD_USER_HEADER];
110344
- const value = (Array.isArray(raw) ? raw[0] : raw)?.trim();
110345
- return value ? value : null;
110346
- }
110347
- async function resolveHttpFavoriteOwner(req, callerAgentId, opts = {}) {
110348
- const auth = getRequestAuth(req);
110349
- if (auth?.kind === "user") {
110350
- return { scope: `user:${auth.userId}`, userId: auth.userId, actorId: auth.userId };
110351
- }
110352
- if (auth?.kind === "operator" && !callerAgentId) {
110353
- const pickedUserId = opts.dashboardUser === false || auth.page ? null : dashboardUserIdHeader(req);
110354
- if (pickedUserId) {
110355
- const user = await findUserById(pickedUserId);
110356
- if (user?.status === "active") {
110357
- return { scope: `user:${user.id}`, userId: user.id, actorId: user.id };
110358
- }
110359
- }
110360
- return {
110361
- scope: "operator",
110362
- userId: null,
110363
- actorId: auth.fingerprint
110364
- };
110365
- }
110366
- const userId = await resolveHttpAuditUserId(req, callerAgentId);
110367
- return userId ? { scope: `user:${userId}`, userId, actorId: userId } : null;
110368
- }
110369
-
110370
- // src/http/apps.ts
110371
110047
  var MAX_APP_BODY_BYTES = 5 * 1024 * 1024;
110372
110048
  var MAX_APP_ROW_BODY_BYTES = 1 * 1024 * 1024;
110373
110049
  var MAX_APP_BULK_ROWS_BODY_BYTES = 10 * 1024 * 1024;
@@ -110851,24 +110527,32 @@ var syncAppRoute = route({
110851
110527
  },
110852
110528
  rbac: { permission: "app.use" }
110853
110529
  });
110854
- async function authorizeApp(req, res, myAgentId, verb, resource) {
110530
+ async function authorizeAppCaller(req, res, myAgentId, verb, resource) {
110855
110531
  const auth = getRequestAuth(req);
110856
110532
  let principal;
110857
110533
  let actor;
110534
+ let caller;
110858
110535
  if (auth?.kind === "operator") {
110859
110536
  principal = { kind: "operator" };
110860
- actor = "operator";
110537
+ const agent = myAgentId && !auth.page ? await getAgentById2(myAgentId) : null;
110538
+ actor = agent ? `agent:${agent.id}` : "operator";
110539
+ caller = agent ? { kind: "agent", id: agent.id, name: agent.name } : { kind: "operator", id: null };
110861
110540
  } else if (auth?.kind === "user") {
110862
110541
  principal = { kind: "user", userId: auth.userId };
110863
110542
  actor = `user:${auth.userId}`;
110864
- } else if (auth?.kind === "guest") {
110543
+ caller = { kind: "user", id: auth.userId, name: auth.user.name };
110544
+ } else if (auth?.kind === "guest" || auth?.kind === "controller") {
110865
110545
  principal = { kind: "guest" };
110866
110546
  actor = "guest";
110547
+ caller = { kind: "guest", id: null };
110867
110548
  } else {
110868
110549
  const agent = myAgentId ? await getAgentById2(myAgentId) : null;
110869
110550
  principal = { kind: "agent", agentId: myAgentId ?? "", isLead: agent?.isLead ?? false };
110870
110551
  actor = myAgentId ? `agent:${myAgentId}` : "agent";
110552
+ caller = { kind: "agent", id: myAgentId ?? null, name: agent?.name };
110871
110553
  }
110554
+ if (auth?.page)
110555
+ caller.pageId = auth.page.id;
110872
110556
  const decision = can({
110873
110557
  principal,
110874
110558
  verb,
@@ -110876,10 +110560,13 @@ async function authorizeApp(req, res, myAgentId, verb, resource) {
110876
110560
  source: "http"
110877
110561
  });
110878
110562
  if (decision.allow)
110879
- return actor;
110563
+ return { actor, caller };
110880
110564
  jsonError(res, decision.reason, 403);
110881
110565
  return null;
110882
110566
  }
110567
+ async function authorizeApp(req, res, myAgentId, verb, resource) {
110568
+ return (await authorizeAppCaller(req, res, myAgentId, verb, resource))?.actor ?? null;
110569
+ }
110883
110570
  async function authorizeAppManage(req, res, myAgentId, appId) {
110884
110571
  return await authorizeApp(req, res, myAgentId, "app.manage", appId ? { kind: "app", appId } : { kind: "none" });
110885
110572
  }
@@ -110895,12 +110582,6 @@ function definitionNeedsRepair(res, app) {
110895
110582
  json(res, { error: "definition needs repair", issues: app.definitionError }, 409);
110896
110583
  return true;
110897
110584
  }
110898
- function syncPassError(sync) {
110899
- const failed = sync.passes.filter((pass) => pass.error !== undefined);
110900
- if (failed.length === 0)
110901
- return;
110902
- return failed.map((pass) => `${pass.model}.${pass.source}: ${pass.error}`).join("; ");
110903
- }
110904
110585
  function snapshotFailure(res) {
110905
110586
  jsonError(res, "failed to snapshot app", 500);
110906
110587
  }
@@ -111071,6 +110752,9 @@ function compareValues(left, right, direction, dateValues = false) {
111071
110752
  function rowValue(row, column) {
111072
110753
  return Object.hasOwn(row, column) ? row[column] : undefined;
111073
110754
  }
110755
+ function rowMatchesFilters(row, filters) {
110756
+ return filters.every((filter) => rowValue(row, filter.column) === filter.value);
110757
+ }
111074
110758
  function applyQuery(rows, query, model, params = {}, queryName = "<unnamed>") {
111075
110759
  const filters = resolveQueryFilters(query, model, params, queryName);
111076
110760
  let selected = rows.filter((row) => filters.every(([column, value]) => rowValue(row, column) === value));
@@ -111083,6 +110767,23 @@ function applyQuery(rows, query, model, params = {}, queryName = "<unnamed>") {
111083
110767
  }
111084
110768
  return selected.slice(0, query.limit ?? 200);
111085
110769
  }
110770
+ async function selectAppRows(appId, modelName, model, filters, sortRaw, limit = 200, systemColumns = false) {
110771
+ const rows = (await listAppRows(appId, modelName, filters.flatMap((filter) => typeof filter.value === "string" || typeof filter.value === "number" || typeof filter.value === "boolean" ? [{ column: filter.column, value: filter.value }] : []))).filter((row) => rowMatchesFilters(row, filters));
110772
+ if (sortRaw) {
110773
+ const [column, dir, extra] = sortRaw.split(":");
110774
+ if (extra !== undefined || !column || dir !== "asc" && dir !== "desc" || !SORTABLE_SYSTEM_DATE_COLUMNS.has(column) && !(systemColumns && Object.hasOwn(SYSTEM_COLUMN_KINDS, column)) && (!Object.hasOwn(model.columns, column) || model.columns[column].hidden === true)) {
110775
+ throw new AppRowValidationError([
110776
+ { path: "sort", message: "must be <column>:<asc|desc> for a known column" }
110777
+ ]);
110778
+ }
110779
+ rows.sort((a, b) => {
110780
+ const result = compareValues(rowValue(a, column), rowValue(b, column), dir, SORTABLE_SYSTEM_DATE_COLUMNS.has(column) || Object.hasOwn(model.columns, column) && model.columns[column].kind === "date");
110781
+ return result;
110782
+ });
110783
+ }
110784
+ const total = rows.length;
110785
+ return { rows: rows.slice(0, limit), total };
110786
+ }
111086
110787
  async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
111087
110788
  if (createAppRoute.match(req.method, pathSegments)) {
111088
110789
  if (enforceContentLengthCap(req, res, MAX_APP_BODY_BYTES) === BODY_TOO_LARGE)
@@ -111245,24 +110946,13 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
111245
110946
  json(res, { error: "invalid row query", issues }, 400);
111246
110947
  return true;
111247
110948
  }
111248
- const rows = (await listAppRows(parsed.params.id, parsed.params.model, filters.flatMap((filter) => typeof filter.value === "string" || typeof filter.value === "number" || typeof filter.value === "boolean" ? [{ column: filter.column, value: filter.value }] : []))).filter((row) => filters.every((filter) => rowValue(row, filter.column) === filter.value));
111249
- const sortRaw = parsed.query.sort;
111250
- if (sortRaw) {
111251
- const [column, dir, extra] = sortRaw.split(":");
111252
- if (extra !== undefined || !column || dir !== "asc" && dir !== "desc" || !SORTABLE_SYSTEM_DATE_COLUMNS.has(column) && (!Object.hasOwn(resolved.model.columns, column) || resolved.model.columns[column].hidden === true)) {
111253
- json(res, {
111254
- error: "invalid sort",
111255
- issues: [{ path: "sort", message: "must be <column>:<asc|desc> for a known column" }]
111256
- }, 400);
111257
- return true;
111258
- }
111259
- rows.sort((a, b) => {
111260
- const result = compareValues(rowValue(a, column), rowValue(b, column), dir, SORTABLE_SYSTEM_DATE_COLUMNS.has(column) || Object.hasOwn(resolved.model.columns, column) && resolved.model.columns[column].kind === "date");
111261
- return result;
111262
- });
110949
+ try {
110950
+ listRowsRoute.respond(res, 200, await selectAppRows(parsed.params.id, parsed.params.model, resolved.model, filters, parsed.query.sort, parsed.query.limit));
110951
+ } catch (error) {
110952
+ if (!(error instanceof AppRowValidationError))
110953
+ throw error;
110954
+ json(res, { error: "invalid sort", issues: error.issues }, 400);
111263
110955
  }
111264
- const total = rows.length;
111265
- listRowsRoute.respond(res, 200, { rows: rows.slice(0, parsed.query.limit ?? 200), total });
111266
110956
  return true;
111267
110957
  }
111268
110958
  if (getRowRoute.match(req.method, pathSegments)) {
@@ -111359,9 +111049,13 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
111359
111049
  const parsed = await runActionRoute.parse(req, res, pathSegments, queryParams);
111360
111050
  if (!parsed)
111361
111051
  return true;
111362
- const actor = await authorizeAppUse(req, res, myAgentId, parsed.params.id);
111363
- if (!actor)
111052
+ const identity = await authorizeAppCaller(req, res, myAgentId, "app.use", {
111053
+ kind: "app",
111054
+ appId: parsed.params.id
111055
+ });
111056
+ if (!identity)
111364
111057
  return true;
111058
+ const { actor, caller } = identity;
111365
111059
  const app = await getApp(parsed.params.id);
111366
111060
  if (!app) {
111367
111061
  jsonError(res, "app not found", 404);
@@ -111369,86 +111063,17 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
111369
111063
  }
111370
111064
  if (definitionNeedsRepair(res, app))
111371
111065
  return true;
111372
- const actions = app.definition.actions;
111373
- if (!actions || !Object.hasOwn(actions, parsed.params.name)) {
111374
- jsonError(res, "app action not found", 404);
111375
- return true;
111376
- }
111377
- const action = actions[parsed.params.name];
111378
- const input = parsed.body.input ?? {};
111379
- if (action.kind === "script") {
111380
- const script = await getScriptById(action.scriptId);
111381
- if (!script) {
111382
- json(res, {
111383
- error: "invalid app action",
111384
- issues: [
111385
- {
111386
- path: `actions.${parsed.params.name}.scriptId`,
111387
- message: `script "${action.scriptId}" no longer exists`
111388
- }
111389
- ]
111390
- }, 400);
111391
- return true;
111392
- }
111393
- const runAsAgentId = getSavedScriptOwnerAgentId(script);
111394
- if (!runAsAgentId) {
111395
- jsonError(res, "agentId is required: this script has no owning agent to run as", 400);
111396
- return true;
111397
- }
111398
- const output = await runSavedScriptAsAgent({
111399
- script,
111400
- input: { ...action.args, ...input, app: { id: app.id } },
111401
- agentId: runAsAgentId
111402
- });
111403
- const ok = output.exitCode === 0 && !output.error && !output.runtimeError;
111404
- const error = ok ? undefined : output.runtimeError ? `${output.runtimeError.name}: ${output.runtimeError.message}` : output.error ?? `Script exited with code ${output.exitCode}`;
111405
- runActionRoute.respond(res, 200, scrubObject({
111406
- ok,
111407
- result: output.result,
111408
- stdout: output.stdout,
111409
- ...error === undefined ? {} : { error },
111410
- durationMs: output.durationMs
111411
- }));
111412
- return true;
111413
- }
111414
- if (action.kind === "sync") {
111415
- const startedAt = Date.now();
111416
- const sync = await runAppSync({
111417
- appId: app.id,
111418
- ...action.model === undefined ? {} : { model: action.model },
111419
- ...action.source === undefined ? {} : { source: action.source },
111420
- invokedBy: actor
111421
- });
111422
- const durationMs = Date.now() - startedAt;
111423
- if (sync.issues && sync.issues.length > 0) {
111424
- json(res, { error: "invalid sync action", issues: sync.issues }, 400);
111425
- return true;
111426
- }
111427
- const error = syncPassError(sync);
111428
- runActionRoute.respond(res, 200, scrubObject({
111429
- ok: sync.ok,
111430
- result: { passes: sync.passes },
111431
- ...error === undefined ? {} : { error },
111432
- durationMs
111433
- }));
111434
- return true;
111435
- }
111436
- const lead = action.agentId ? null : await getLeadAgent2();
111437
- const taskPrompt = resolveTemplate("task.app.action", {
111438
- prompt: action.prompt,
111439
- app_id: app.id,
111440
- action_name: parsed.params.name,
111441
- input_json: JSON.stringify(input)
111066
+ const output = await runAppAction({
111067
+ app,
111068
+ name: parsed.params.name,
111069
+ input: parsed.body.input,
111070
+ caller,
111071
+ actor
111442
111072
  });
111443
- const task = await createTaskWithSiblingAwareness(taskPrompt.text, {
111444
- source: "api",
111445
- agentId: action.agentId ?? lead?.id,
111446
- routingReason: action.agentId ? "human_pinned" : lead ? "skill" : undefined,
111447
- routingSource: action.agentId || lead ? "engine_default" : undefined,
111448
- key: normalizeAssetKey(`shared/app:${app.id}/action:${parsed.params.name}/`),
111449
- ...actor.startsWith("user:") ? { requestedByUserId: actor.slice("user:".length) } : {}
111450
- }, { origin: "app" });
111451
- runActionRoute.respond(res, 200, { ok: true, taskId: task.id, status: task.status });
111073
+ if (output.status === 200)
111074
+ runActionRoute.respond(res, 200, output.body);
111075
+ else
111076
+ json(res, output.body, output.status);
111452
111077
  return true;
111453
111078
  }
111454
111079
  if (syncAppRoute.match(req.method, pathSegments)) {
@@ -112191,6 +111816,132 @@ var registerAppRollbackTool = (server) => {
112191
111816
  });
112192
111817
  };
112193
111818
 
111819
+ // src/tools/app-rows.ts
111820
+ init_zod();
111821
+ init_db3();
111822
+ init_rbac();
111823
+ var base = { appId: string2().min(1), model: AppNameSchema };
111824
+ var rowId = string2().min(1);
111825
+ var values = record2(string2(), unknown());
111826
+ var equals = record2(string2(), union2([string2(), number2(), boolean()]));
111827
+ var limit = number2().int().min(1).max(1000);
111828
+ var rowOutput = { row: looseObject({}).optional() };
111829
+ var rowsOutput = { rows: array2(looseObject({})).optional() };
111830
+ function checkSize(value, max) {
111831
+ if (Buffer.byteLength(JSON.stringify(value), "utf8") > max) {
111832
+ throw new AppRowValidationError([
111833
+ { path: "values", message: `Row input exceeds ${max} bytes.` }
111834
+ ]);
111835
+ }
111836
+ }
111837
+ function rowFilters(model, equals = {}) {
111838
+ return Object.entries(equals).map(([column, value]) => {
111839
+ const declared = Object.hasOwn(model.columns, column) ? model.columns[column] : undefined;
111840
+ if (!declared && !Object.hasOwn(SYSTEM_COLUMN_KINDS, column) || declared?.hidden) {
111841
+ throw new AppRowValidationError([
111842
+ { path: `equals.${column}`, message: "Unknown or hidden column." }
111843
+ ]);
111844
+ }
111845
+ if (!validValue(declared ?? { kind: SYSTEM_COLUMN_KINDS[column] }, value)) {
111846
+ throw new AppRowValidationError([
111847
+ { path: `equals.${column}`, message: "Filter value must match the column kind." }
111848
+ ]);
111849
+ }
111850
+ return { column, value };
111851
+ });
111852
+ }
111853
+ function registerAppRowTools(server) {
111854
+ function register(name, description, shape, output, operation, readOnly = false) {
111855
+ createToolRegistrar(server)(name, {
111856
+ title: description,
111857
+ description,
111858
+ annotations: { readOnlyHint: readOnly },
111859
+ rbac: { permission: "app.use" },
111860
+ inputSchema: object2({ ...base, ...shape }),
111861
+ outputSchema: swarmToolOutputSchema(output)
111862
+ }, async (args, info) => {
111863
+ if (!info.agentId)
111864
+ return toolErr('Agent ID not found. Set the "X-Agent-ID" header.');
111865
+ const { appId, model: modelName } = object2(base).parse(args);
111866
+ const agent = await getAgentById2(info.agentId);
111867
+ const decision = can({
111868
+ principal: { kind: "agent", agentId: info.agentId, isLead: agent?.isLead ?? false },
111869
+ verb: "app.use",
111870
+ resource: { kind: "app", appId },
111871
+ source: "mcp"
111872
+ });
111873
+ if (!decision.allow)
111874
+ return toolErr(decision.reason);
111875
+ const app = await getApp(appId);
111876
+ if (!app)
111877
+ return toolErr("App not found.");
111878
+ if (appDefinitionNeedsRepair(app))
111879
+ return toolErr("App definition needs repair.", { data: { issues: app.definitionError } });
111880
+ if (!Object.hasOwn(app.definition.models, modelName))
111881
+ return toolErr("Model not found.");
111882
+ try {
111883
+ return await operation(args, app.definition.models[modelName], `agent:${info.agentId}`);
111884
+ } catch (error) {
111885
+ if (error instanceof AppRowValidationError)
111886
+ return toolErr(error.message, { data: { issues: error.issues } });
111887
+ if (error instanceof AppRowAppNotFoundError)
111888
+ return toolErr(error.message);
111889
+ throw error;
111890
+ }
111891
+ });
111892
+ }
111893
+ register("app-rows-list", "List app rows with equality filters, sorting, and a limit.", {
111894
+ equals: equals.optional(),
111895
+ sort: string2().optional(),
111896
+ limit: limit.optional()
111897
+ }, { ...rowsOutput, total: number2().optional() }, async (args, model) => {
111898
+ const data = await selectAppRows(args.appId, args.model, model, rowFilters(model, args.equals), args.sort, args.limit, true);
111899
+ return toolOk(`Found ${data.total} row(s).`, { data });
111900
+ }, true);
111901
+ register("app-row-get", "Get an app row.", { rowId }, rowOutput, async (args) => {
111902
+ const row = await getAppRow(args.appId, args.model, args.rowId);
111903
+ return row ? toolOk("Row retrieved.", { data: { row } }) : toolErr("Row not found.");
111904
+ }, true);
111905
+ register("app-row-create", "Create an app row.", { values }, rowOutput, async (args, model, actor) => {
111906
+ checkSize({ values: args.values }, MAX_APP_ROW_BODY_BYTES);
111907
+ const row = await createAppRow(args.appId, args.model, model, args.values, { actor });
111908
+ return toolOk("Row created.", { data: { row } });
111909
+ });
111910
+ register("app-rows-create", "Create up to 500 app rows within 10 MiB.", {
111911
+ rows: array2(values).min(1).max(500)
111912
+ }, rowsOutput, async (args, model, actor) => {
111913
+ checkSize({ rows: args.rows }, MAX_APP_BULK_ROWS_BODY_BYTES);
111914
+ for (const values of args.rows)
111915
+ checkSize({ values }, MAX_APP_ROW_BODY_BYTES);
111916
+ const rows = await createAppRows(args.appId, args.model, model, args.rows, { actor });
111917
+ return toolOk(`Created ${rows.length} row(s).`, { data: { rows } });
111918
+ });
111919
+ register("app-row-patch", "Patch an app row.", { rowId, values }, rowOutput, async (args, model, actor) => {
111920
+ checkSize({ values: args.values }, MAX_APP_ROW_BODY_BYTES);
111921
+ const row = await patchAppRow(args.appId, args.model, model, args.rowId, args.values, {
111922
+ actor
111923
+ });
111924
+ return row ? toolOk("Row updated.", { data: { row } }) : toolErr("Row not found.");
111925
+ });
111926
+ register("app-row-delete", "Delete an app row.", { rowId }, { ok: boolean().optional() }, async (args, model) => {
111927
+ const deleted = await deleteAppRow(args.appId, args.model, model, args.rowId);
111928
+ return deleted ? toolOk("Row deleted.", { data: { ok: true } }) : toolErr("Row not found.");
111929
+ });
111930
+ register("app-rows-delete", "Delete matching app rows. Supply at least one equality filter.", {
111931
+ equals: equals.refine((value) => Object.keys(value).length > 0, "Supply at least one equality filter."),
111932
+ limit: limit.optional()
111933
+ }, { deleted: number2().optional() }, async (args, model) => {
111934
+ const filters = rowFilters(model, args.equals);
111935
+ const { rows } = await selectAppRows(args.appId, args.model, model, filters, undefined, args.limit ?? 1000, true);
111936
+ const matches = (row) => rowMatchesFilters(row, filters);
111937
+ let deleted = 0;
111938
+ for (const row of rows)
111939
+ if (await deleteAppRow(args.appId, args.model, model, row.id, matches))
111940
+ deleted++;
111941
+ return toolOk(`Deleted ${deleted} row(s).`, { data: { deleted } });
111942
+ });
111943
+ }
111944
+
112194
111945
  // src/tools/app-sync.ts
112195
111946
  init_zod();
112196
111947
  init_db3();
@@ -119423,7 +119174,7 @@ var registerModelCatalogOverlayUpsertTool = (server) => {
119423
119174
  description: "Add or update hand-verified facts for one model (e.g. a launch models.dev has not listed yet). Overlay fields win over models.dev; overlay prices fill pricing-table gaps so cost recompute prices the model. The row auto-expires once models.dev matches every fact you set.",
119424
119175
  annotations: { idempotentHint: true },
119425
119176
  inputSchema: object2({
119426
- provider: string2().min(1).describe(`models.dev provider id: anthropic, openai, openrouter, amazon-bedrock, opencode, ${openAICompatibleProviderIds().join(", ")}.`),
119177
+ provider: string2().min(1).describe(`models.dev provider id: anthropic, openai, openrouter, amazon-bedrock, opencode, opencode-go, ${openAICompatibleProviderIds().join(", ")}.`),
119427
119178
  modelId: string2().min(1).describe("Model id as models.dev keys it (e.g. claude-opus-5-5)."),
119428
119179
  name: string2().optional().describe("Display name."),
119429
119180
  releaseDate: string2().optional().describe("Release date, YYYY-MM-DD."),
@@ -121283,6 +121034,7 @@ init_context_key();
121283
121034
  init_runtime_pools_flag();
121284
121035
  var COMB_PRESENCE_NAMESPACE = /^presence:comb:[A-Za-z0-9_-]{1,64}:[A-Za-z0-9_-]{1,64}$/;
121285
121036
  var COMB_PRESENCE_OPERATIONS = new Set(["join", "leave", "presence"]);
121037
+ var SESSION_PRESENCE_NAMESPACE = /^presence:session:([A-Za-z0-9_-]{1,64})$/;
121286
121038
  function pageNamespace(pageId) {
121287
121039
  try {
121288
121040
  return pageContextKey({ pageId });
@@ -121375,6 +121127,9 @@ async function authorizeRoomNamespace(namespace, info, access, name) {
121375
121127
  }
121376
121128
  return null;
121377
121129
  }
121130
+ if (namespace.startsWith("presence:session:")) {
121131
+ return authorizeSessionPresence(namespace, info, access);
121132
+ }
121378
121133
  const reservedError = reservedNamespaceError(namespace);
121379
121134
  if (reservedError)
121380
121135
  return reservedError;
@@ -121410,6 +121165,48 @@ async function authorizeRoomNamespace(namespace, info, access, name) {
121410
121165
  }
121411
121166
  return null;
121412
121167
  }
121168
+ function sessionAccessTopic(rootTaskId) {
121169
+ return `session-access:${rootTaskId}`;
121170
+ }
121171
+ function sessionPresenceRoot(namespace) {
121172
+ return SESSION_PRESENCE_NAMESPACE.exec(namespace)?.[1];
121173
+ }
121174
+ async function authorizeSessionPresence(namespace, info, access) {
121175
+ const match = SESSION_PRESENCE_NAMESPACE.exec(namespace);
121176
+ if (!match)
121177
+ return "invalid session presence namespace";
121178
+ if (info.pageId || info.agentId || !info.isOperator && !info.userId) {
121179
+ return "Session presence requires dashboard authentication";
121180
+ }
121181
+ if (typeof access !== "string" || !COMB_PRESENCE_OPERATIONS.has(access)) {
121182
+ return "Session presence rooms only allow join, leave, and presence";
121183
+ }
121184
+ const principal = info.isOperator ? { kind: "operator" } : { kind: "user", userId: info.userId };
121185
+ if (!can({
121186
+ principal,
121187
+ verb: "session.presence",
121188
+ resource: { kind: "kv-namespace", namespace },
121189
+ source: info.callOrigin === "mcp" ? "mcp" : "http"
121190
+ }).allow) {
121191
+ return "Session presence requires the session.presence permission";
121192
+ }
121193
+ if (info.userId && isRbacEnabled()) {
121194
+ const grant = await getUserGrant2(info.userId);
121195
+ if (!grant.grantsAll && !grant.verbs.has("session.presence")) {
121196
+ return "Session presence requires the session.presence permission";
121197
+ }
121198
+ }
121199
+ const viewerId = info.isOperator ? info.dashboardUserId : info.userId;
121200
+ if (info.isOperator && !viewerId)
121201
+ return null;
121202
+ const root = await getSessionRoot(match[1]);
121203
+ if (!root || root.id !== match[1])
121204
+ return "session not found";
121205
+ if (await sessionAccessForRoot(viewerId ?? null, root) === "none") {
121206
+ return "You don't have access to this session";
121207
+ }
121208
+ return null;
121209
+ }
121413
121210
 
121414
121211
  // node_modules/lib0/map.js
121415
121212
  var create = () => new Map;
@@ -122125,7 +121922,7 @@ var varStorage = _localStorage;
122125
121922
 
122126
121923
  // node_modules/lib0/trait/equality.js
122127
121924
  var EqualityTraitSymbol = Symbol("Equality");
122128
- var equals = (a, b) => a === b || !!a?.[EqualityTraitSymbol]?.(b) || false;
121925
+ var equals2 = (a, b) => a === b || !!a?.[EqualityTraitSymbol]?.(b) || false;
122129
121926
 
122130
121927
  // node_modules/lib0/object.js
122131
121928
  var assign = Object.assign;
@@ -122151,7 +121948,7 @@ var every = (obj, f) => {
122151
121948
  return true;
122152
121949
  };
122153
121950
  var hasProperty = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
122154
- var equalFlat = (a, b) => a === b || size(a) === size(b) && every(a, (val, key) => (val !== undefined || hasProperty(b, key)) && equals(b[key], val));
121951
+ var equalFlat = (a, b) => a === b || size(a) === size(b) && every(a, (val, key) => (val !== undefined || hasProperty(b, key)) && equals2(b[key], val));
122155
121952
  var freeze = Object.freeze;
122156
121953
  var deepFreeze = (o) => {
122157
121954
  for (const key in o) {
@@ -128073,6 +127870,7 @@ init_db3();
128073
127870
  // src/be/events.ts
128074
127871
  init_secret_scrubber();
128075
127872
  init_db3();
127873
+ init_read();
128076
127874
  init_scrub_json();
128077
127875
 
128078
127876
  // src/be/memory/key-browser.ts
@@ -128402,6 +128200,13 @@ async function getEventCountsFiltered(filters) {
128402
128200
  async function getEventsFiltered(filters) {
128403
128201
  const conditions = [];
128404
128202
  const params = [];
128203
+ if (filters.readableBy) {
128204
+ const readable = readableSessionCondition(filters.readableBy.userId, "events.taskId", {
128205
+ nullable: true
128206
+ });
128207
+ conditions.push(readable.sql);
128208
+ params.push(...readable.params);
128209
+ }
128405
128210
  if (filters.category) {
128406
128211
  conditions.push("category = ?");
128407
128212
  params.push(filters.category);
@@ -132266,13 +132071,30 @@ var registerSlackListChannelsTool = (server) => {
132266
132071
  init_zod();
132267
132072
  init_db3();
132268
132073
  init_rbac();
132074
+
132075
+ // src/slack/dm.ts
132076
+ function isSlackUserId(id) {
132077
+ return /^[UW][A-Z0-9]+$/.test(id);
132078
+ }
132079
+ async function resolveSlackConversationId(client, channelId) {
132080
+ if (!isSlackUserId(channelId))
132081
+ return channelId;
132082
+ const result = await client.conversations.open({ users: channelId });
132083
+ const dmId = result.channel?.id;
132084
+ if (!dmId) {
132085
+ throw new Error(`conversations.open returned no DM channel for user ${channelId}`);
132086
+ }
132087
+ return dmId;
132088
+ }
132089
+
132090
+ // src/tools/slack-post.ts
132269
132091
  var registerSlackPostTool = (server) => {
132270
132092
  createToolRegistrar(server)("slack-post", {
132271
132093
  title: "Post message to Slack channel",
132272
132094
  description: "Post a message to a Slack channel. By default creates a new top-level message; pass `threadTs` to post as a threaded reply under an existing message (obtain the ts from `slack-start-thread`). Requires lead privileges.",
132273
132095
  annotations: { openWorldHint: true },
132274
132096
  inputSchema: object2({
132275
- channelId: string2().min(1).describe("The Slack channel ID to post to."),
132097
+ channelId: string2().min(1).describe("The Slack channel ID to post to. A user ID (U…/W…) posts in the bot's DM with that user."),
132276
132098
  message: string2().min(1).max(4000).describe("The message content to post."),
132277
132099
  blocks: array2(record2(string2(), unknown())).max(50).optional().describe("Optional Block Kit blocks. When omitted, a mrkdwn section is generated."),
132278
132100
  threadTs: string2().optional().describe("Optional parent message ts to thread under. Obtain via `slack-start-thread`. When omitted, posts as a new top-level message.")
@@ -132280,7 +132102,7 @@ var registerSlackPostTool = (server) => {
132280
132102
  outputSchema: swarmToolOutputSchema({
132281
132103
  messageTs: string2().optional()
132282
132104
  })
132283
- }, async ({ channelId, message, threadTs, blocks }, requestInfo, _meta) => {
132105
+ }, async ({ channelId: requestedChannelId, message, threadTs, blocks }, requestInfo, _meta) => {
132284
132106
  if (!requestInfo.agentId) {
132285
132107
  return toolErr("Agent ID not found.");
132286
132108
  }
@@ -132301,6 +132123,13 @@ var registerSlackPostTool = (server) => {
132301
132123
  if (!app) {
132302
132124
  return toolErr("Slack not configured.");
132303
132125
  }
132126
+ let channelId;
132127
+ try {
132128
+ channelId = await resolveSlackConversationId(app.client, requestedChannelId);
132129
+ } catch (error) {
132130
+ const errorMsg = error instanceof Error ? error.message : String(error);
132131
+ return toolErr(`Failed to open a DM with ${requestedChannelId}: ${errorMsg}`);
132132
+ }
132304
132133
  const blockReason = await getChannelBlockReason2(app.client, channelId);
132305
132134
  if (blockReason) {
132306
132135
  return toolErr(externalChannelToolError2(channelId, blockReason));
@@ -132311,15 +132140,7 @@ var registerSlackPostTool = (server) => {
132311
132140
  const contextKey = sourceTask?.contextKey;
132312
132141
  const tree = threadTs ? await getSlackTreeMessageByThread2(channelId, threadTs) : null;
132313
132142
  const messageBlocks = [
132314
- ...blocks ?? [
132315
- {
132316
- type: "section",
132317
- text: {
132318
- type: "mrkdwn",
132319
- text: slackMessage
132320
- }
132321
- }
132322
- ]
132143
+ ...blocks ?? buildMrkdwnSectionBlocks(slackMessage)
132323
132144
  ];
132324
132145
  if (sourceTask && tree) {
132325
132146
  if (messageBlocks.length >= 50) {
@@ -132403,7 +132224,7 @@ var registerSlackReadTool = (server) => {
132403
132224
  inputSchema: object2({
132404
132225
  inboxMessageId: uuid().optional().describe("Read thread history for an inbox message."),
132405
132226
  taskId: uuid().optional().describe("Read thread history for a task."),
132406
- channelId: string2().optional().describe("Slack channel ID to read from (requires lead privileges)."),
132227
+ channelId: string2().optional().describe("Slack channel ID to read from (requires lead privileges). A user ID (U…/W…) reads the bot's DM with that user."),
132407
132228
  threadTs: string2().optional().describe("Thread timestamp (required with channelId for thread history)."),
132408
132229
  limit: number2().int().min(1).max(100).default(20).describe("Maximum number of messages to retrieve (default: 20, max: 100)."),
132409
132230
  includeFiles: boolean().default(true).describe("Include file attachments in the response (default: true). From a task, they are also stored as attachments of that task.")
@@ -132471,6 +132292,14 @@ var registerSlackReadTool = (server) => {
132471
132292
  if (!app) {
132472
132293
  return toolErr("Slack not configured.", { data: { messages: [] } });
132473
132294
  }
132295
+ try {
132296
+ slackChannelId = await resolveSlackConversationId(app.client, slackChannelId);
132297
+ } catch (error) {
132298
+ const errorMsg = error instanceof Error ? error.message : String(error);
132299
+ return toolErr(`Failed to open a DM with ${slackChannelId}: ${errorMsg}`, {
132300
+ data: { messages: [] }
132301
+ });
132302
+ }
132474
132303
  const blockReason = await getChannelBlockReason2(app.client, slackChannelId);
132475
132304
  if (blockReason) {
132476
132305
  return toolErr(externalChannelToolError2(slackChannelId, blockReason), {
@@ -132679,15 +132508,7 @@ var registerSlackReplyTool = (server) => {
132679
132508
  const renderedBlocks = blocks?.map((block) => JSON.parse(JSON.stringify(block, (key, value) => key === "text" && typeof value === "string" ? stripInvalidTaskCitations(value, citations) : value?.type === "mrkdwn" && typeof value.text === "string" ? { ...value, text: renderTaskCitations(value.text, citations, "slack", false) } : value)));
132680
132509
  const tree = await getSlackTreeMessageByThread2(slackChannelId, slackThreadTs);
132681
132510
  const messageBlocks = [
132682
- ...renderedBlocks ?? [
132683
- {
132684
- type: "section",
132685
- text: {
132686
- type: "mrkdwn",
132687
- text: slackMessage
132688
- }
132689
- }
132690
- ]
132511
+ ...renderedBlocks ?? buildMrkdwnSectionBlocks(slackMessage)
132691
132512
  ];
132692
132513
  for (const group of taskCitationSourceGroups(blocks ? JSON.stringify(blocks) : message, citations)) {
132693
132514
  const caption = buildCaptionBlock(group.items, {
@@ -132760,7 +132581,7 @@ var registerSlackStartThreadTool = (server) => {
132760
132581
  description: "Post a new top-level message to a Slack channel and return its ts so the caller can thread replies under it. Pass the returned `ts` as `threadTs` on subsequent `slack-post` calls to keep replies in the same thread. Requires lead privileges.",
132761
132582
  annotations: { openWorldHint: true },
132762
132583
  inputSchema: object2({
132763
- channelId: string2().min(1).describe("The Slack channel ID to post to."),
132584
+ channelId: string2().min(1).describe("The Slack channel ID to post to. A user ID (U…/W…) opens the bot's DM with that user; use the returned channelId afterwards."),
132764
132585
  message: string2().min(1).max(4000).describe("The message content to post."),
132765
132586
  blocks: array2(record2(string2(), unknown())).max(50).optional().describe("Optional Block Kit blocks. When omitted, a mrkdwn section is generated.")
132766
132587
  }),
@@ -132769,7 +132590,7 @@ var registerSlackStartThreadTool = (server) => {
132769
132590
  ts: string2().optional(),
132770
132591
  messageTs: string2().optional()
132771
132592
  })
132772
- }, async ({ channelId, message, blocks }, requestInfo, _meta) => {
132593
+ }, async ({ channelId: requestedChannelId, message, blocks }, requestInfo, _meta) => {
132773
132594
  if (!requestInfo.agentId) {
132774
132595
  return toolErr("Agent ID not found.");
132775
132596
  }
@@ -132790,21 +132611,20 @@ var registerSlackStartThreadTool = (server) => {
132790
132611
  if (!app) {
132791
132612
  return toolErr("Slack not configured.");
132792
132613
  }
132614
+ let channelId;
132615
+ try {
132616
+ channelId = await resolveSlackConversationId(app.client, requestedChannelId);
132617
+ } catch (error) {
132618
+ const errorMsg = error instanceof Error ? error.message : String(error);
132619
+ return toolErr(`Failed to open a DM with ${requestedChannelId}: ${errorMsg}`);
132620
+ }
132793
132621
  const blockReason = await getChannelBlockReason2(app.client, channelId);
132794
132622
  if (blockReason) {
132795
132623
  return toolErr(externalChannelToolError2(channelId, blockReason));
132796
132624
  }
132797
132625
  try {
132798
132626
  const slackMessage = markdownToSlack(message);
132799
- const messageBlocks = blocks ?? [
132800
- {
132801
- type: "section",
132802
- text: {
132803
- type: "mrkdwn",
132804
- text: slackMessage
132805
- }
132806
- }
132807
- ];
132627
+ const messageBlocks = blocks ?? buildMrkdwnSectionBlocks(slackMessage);
132808
132628
  const result = await withAutoJoin(app.client, channelId, () => app.client.chat.postMessage({
132809
132629
  channel: channelId,
132810
132630
  text: slackMessage,
@@ -132894,15 +132714,7 @@ var registerSlackUpdateTool = (server) => {
132894
132714
  text: slackMessage,
132895
132715
  unfurl_links: false,
132896
132716
  unfurl_media: false,
132897
- blocks: [
132898
- {
132899
- type: "section",
132900
- text: {
132901
- type: "mrkdwn",
132902
- text: slackMessage
132903
- }
132904
- }
132905
- ]
132717
+ blocks: buildMrkdwnSectionBlocks(slackMessage)
132906
132718
  };
132907
132719
  const result = await app.client.chat.update(updatePayload);
132908
132720
  return toolOk("Message updated successfully.", { data: { messageTs: result.ts } });
@@ -134199,7 +134011,7 @@ async function emitBudgetRefusalSideEffects(ctx, inserted) {
134199
134011
  console.warn(`[budget-refusal-notify] Failed to create follow-up task for budget refusal (task=${ctx.task.id.slice(0, 8)}): ${err}`);
134200
134012
  }
134201
134013
  }
134202
- import("./event-bus-101fenkh.js").then(({ workflowEventBus }) => {
134014
+ import("./event-bus-9vpk8gmq.js").then(({ workflowEventBus }) => {
134203
134015
  workflowEventBus.emit("task.budget_refused", {
134204
134016
  taskId: ctx.task.id,
134205
134017
  agentId: ctx.agentId,
@@ -135749,7 +135561,7 @@ var registerRetryWorkflowRunTool = (server) => {
135749
135561
  createToolRegistrar(server)("retry-workflow-run", {
135750
135562
  title: "Retry Workflow Run",
135751
135563
  annotations: { destructiveHint: false },
135752
- description: "Retry a failed workflow run from the beginning. The run must be in 'failed' status.",
135564
+ description: "Resume the same failed workflow run from its failed step(s); completed steps are not re-run. Retrying re-creates the failed node's side effects (e.g. an agent task), so check the target state first if that work was already done manually.",
135753
135565
  inputSchema: object2({
135754
135566
  runId: string2().uuid().describe("Workflow run ID to retry")
135755
135567
  }),
@@ -136213,6 +136025,8 @@ async function createServer(opts = {}) {
136213
136025
  }
136214
136026
  if (hasCapability("pages")) {
136215
136027
  registerAppGetTool(server);
136028
+ registerAppRowTools(server);
136029
+ registerAppActionRunTool(server);
136216
136030
  registerAppHistoryTool(server);
136217
136031
  registerAppDiffTool(server);
136218
136032
  registerAppListTool(server);
@@ -136294,4 +136108,4 @@ async function createServer(opts = {}) {
136294
136108
  return server;
136295
136109
  }
136296
136110
 
136297
- export { DEFAULT_NEGOTIATED_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, isJSONRPCRequest, isJSONRPCResultResponse, isJSONRPCErrorResponse, JSONRPCMessageSchema, isInitializeRequest, McpServer, isGitHubEnabled, initGitHub, verifyWebhookSignature, isAgentMailEnabled, initAgentMail, verifyAgentMailWebhook, resolveIdentity, renderIdentity, createAdditiveBuffer, taskModelPin, resumedTaskModelSelection, listHarnessModelSupport, recordHarnessModelSupport, agentRanModel, getAgentHarnessCliVersion, setAgentHarnessCliVersion, sanitizeModelTierOverrides, parseModelTierOverridesHeader, setAgentModelTierOverrides, previewModelTiers, recordClaimModelResolution, harnessModelErrorFor, poolTaskRunsOnHarness, explicitModelError, explicitModelErrorForAgent, referencedBundlePaths, skillDirs, TaskCreationBlockedError, recordUnmappedIdentity, MAX_TASK_ATTACHMENT_BYTES, recordTaskAttachmentUpload, buildEffectiveText, bufferedFileFailures, fetchSlackFiles, createSlackTaskWithFiles, notifySlackFileFailures, isRuntimePoolWakeable, isAgentReachable, hasOtherUserMention, broadcastMatches, routeMessage, extractTaskFromMessage, extractSlackMessageText, recoverIncompleteRuns, handleWebhookTrigger, verifyHmacSignature, WebhookError, snapshotAndUpdateWorkflow, RawLlmConfigSchema, RawLlmOutputSchema, executeRawLlm, getExecutorRegistry2, initWorkflows2, dispatchScheduleTarget, calculateNextRun2, startScheduler2, stopScheduler2, runScheduleNow2, ExtensionAssetConflictError, ExtensionOwnershipError, getExtensionFiles, getExtensionById, getExtensionByName, listExtensions, listExtensionVersions, updateExtensionMeta, listExtensionRuns, SDK_ALLOWLIST, mcpToolNameForSdkMethod, mcpOverflowAuthError, hasKvViewArgs, resolveKvView, toolErr, createToolRegistrar, duplicateGuardedQueryKey, warnIfCorsAllowsAnyOrigin, isOriginAllowedForCredentials, allowedCredentialRedirect, setCorsHeaders, parseQueryParams, getPathSegments, wireHttpSpanLifecycle, safeRequestUrlForLog, agentWithCapacity, parseBody, BODY_TOO_LARGE, enforceContentLengthCap, json, jsonError, writeUnhandledError, triggerSchemaErrorResponse, deriveApiBaseUrl, httpServerSemconvAttributes, runtimeInstanceHeader, describeRequestRoute, route, handleMcpBridge, Redacted, SCRIPT_SDK_RESPONSE_LIMIT_BYTES, readScriptSdkJsonResponse, ExtensionConfigError, ExtensionLifecycleError, setExtensionLoopbackBaseUrl, enableExtension, disableExtension, activateVersion, ExtensionAssetsInvalidError, installExtensionWithAssets, uninstallExtension, reloadExtension, loadEnabledExtensions, stopExtensionRuntime, ExtensionAbortedError2, isRegistered2, isExtensionAgentId2, getExtensionBridgeToken2, resolveBridgeCallOrigin2, extensionIdForAgent2, runContext2, registerLoaded2, unregister2, listRegistered2, dispatchPre2, dispatchPost2, stripSiblingBlock, createTaskWithSiblingAwareness, isInboxAllowed, isSenderAllowed, handleMessageReceived, isAzureDevOpsEnabled, initAzureDevOps, verifyAzureDevOpsWebhook, repointTrackerSyncBySwarmId, isAzureDevOpsUrl, canonicalAzureDevOpsRepoUrl, parseAzureDevOpsRepoUrl, createdPullRequestOf, commentedPayloadOf, handlePullRequestCreated, handlePullRequestCommented, handleWorkItemCreated, handleWorkItemUpdated, handleWorkItemCommented, handleWorkItemDeleted, handleWorkItemRestored, initAzureDevOpsOutbound, AGENT_MAX_TASKS_CONFIG_KEY, reconcileAgentMaxTasksPolicy, resetAgentMaxTasksMirror, upsertSwarmConfigWithPolicyMirror, runtimeStaleThresholdMinutes, upsertRuntimeInstance, getRuntimeInstanceById, insertProvisioningRuntime, markRuntimeTerminated, touchRuntimeInstance, countActiveRuntimeInstancesForAgent, listRuntimeInstancesForAgent, setRuntimeCredentialReady, reconcileAgentStatusFromRuntimes, agentsWithLiveRuntime, expireStaleRuntimeInstances, listRuntimeInstancesForPool, enqueueAuditRow, enqueueAdmissionRow, flushAuditBuffer, startAuditWriter, stopAuditWriter, startAuditGc, stopAuditGc, getTelemetryIngestAnchor, initApiTelemetry, syncTelemetryEnabled, handlePullRequest, handleIssue, handleComment, handlePullRequestReview, handleCheckRun, handleCheckSuite, handleWorkflowRun, isGitLabEnabled, initGitLab, verifyGitLabWebhook, handleMergeRequest, handleIssue2, handleNote, handlePipeline, isChatSdkEnabled, getChatSdkConfig, errorMessage, resolveAdapterApiUrl, trackBackground, TelegramBotApiError, callTelegramBotApi, isTrustedTeamsServiceUrl, isChatSdkStopping, startChatSdk, getChatInstance, isChatAdapterConfigured, getChatSdkHealth, stopChatSdk, getJiraMetadata, updateJiraMetadata, clearJiraMetadata, registerJiraWebhook, deleteJiraWebhook, isJiraEnabled, initJira, handleJiraWebhook, handleAgentSessionEvent, handleIssueUpdate, handleIssueDelete, handleAgentSessionPrompted, isLinearEnabled, initLinear, parseCookieHeader, extractAndVerifyCookie, issuePageSessionCookie, resolveHttpRequestAuth, loadGlobalConfigsIntoEnv, reloadGlobalConfigsAndIntegrations, scheduleIntegrationsReload, handleCore, userCtx, resolveTaskAuditUserId, resolveHttpAuditUserId, resolveHttpFavoriteOwner, handleApps, cancelApprovalRequest, cancelApprovalRequestAndRun, getUserCommsPrefs, getTaskDetailsInputSchema, getTaskDetailsOutputSchema, getTaskDetailsHandler, cancelTaskInputSchema, cancelTaskOutputSchema, cancelTaskHandler, executeReadOnlyQuery, assertSelectOnlyQuery, handleDbQuery, snapshotMetric, AssetKeyAuthorizationError, authorizeAssetKeyWrite, getPageEditCounter, snapshotPage, assertOAuthAppUrlsSafe, assertOAuthEgressUrlSafe, listOAuthPresets, listOAuthPresetIds, getOAuthPreset, hydrateOAuthAppFromPreset, scopedResourceScopeIdSchema, resolveScopedResourceId, dedupeMemoryDocumentIds, recordMemoryAccesses, recordRetrievals, ExplicitSelfDuplicateError, applyRating, shouldPersistAutomaticTaskMemory, REBOOT_RETRY_PIN_TAG, getPinCandidateAgent, resolveLeadOnlyRecoveryAssignment, getResumeGeneration, getNextResumeGeneration, inheritedModelSelection, createWorkerTaskFollowUp, createResumeFollowUp, createRerouteDecisionTask, createPoolStarvationDecisionTask, guardTerminalTaskResultWrite, getTasksInputSchema, getTasksOutputSchema, getTasksHandler, reservedNamespaceError, reservedRoomKeyError, updateMcpServerChecked, updateTouchesStdioExecution, MemoryKeyError, refreshLinks, canReadMemory, getLinksForMemory, expandCandidatesWithGraph, indexMemoryContent, isApiDraining, drainApi, markKapsoMessageRead, sendKapsoReaction, getKapsoConfig, getKapsoNumberMapping, markKapsoMessageSeen, changesAllowMerge, updateSwarmRepoChecked, getCombConfig, resolveRoomNamespace, roomRequestInfo, authorizeRoomNamespace, RoomOperationSchema, removeAwarenessStates, roomTopic, decodeRoomSnapshot, roomView, getRoom, changeRoom, applyRoomUpdate, resetRoom, sweepRooms, closeRooms, removeNamespaceRooms, MEMORY_KEYS_DEFAULT_PREFIX, MEMORY_KEYS_MAX_LIMIT, estimateTokens, posteriorMean, listMemoryKeys, checkChunkIntegrity, getMemoryChunks, getPosteriorsByIds, createEvent, createEventsBatch, getEventCountsFiltered, getEventsFiltered, mergeScheduleTiming, validateRecurringTiming, checkOutputSchemaShape, sendTaskOutputSchema, sendTaskHandler, steerTaskUserInputSchema, steerTaskOutputSchema, steerTaskHandler, canClaim, emitBudgetRefusalSideEffects, workflowModelErrors, patchWorkflowDefinition, resolveScriptsOnlyMode, ALL_CAPABILITIES, hasCapability, getEnabledCapabilities, createServer };
136111
+ export { DEFAULT_NEGOTIATED_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, isJSONRPCRequest, isJSONRPCResultResponse, isJSONRPCErrorResponse, JSONRPCMessageSchema, isInitializeRequest, McpServer, isGitHubEnabled, initGitHub, verifyWebhookSignature, isAgentMailEnabled, initAgentMail, verifyAgentMailWebhook, resolveIdentity, renderIdentity, createAdditiveBuffer, taskModelPin, resumedTaskModelSelection, listHarnessModelSupport, recordHarnessModelSupport, agentRanModel, getAgentHarnessCliVersion, setAgentHarnessCliVersion, sanitizeModelTierOverrides, parseModelTierOverridesHeader, setAgentModelTierOverrides, previewModelTiers, recordClaimModelResolution, harnessModelErrorFor, poolTaskRunsOnHarness, explicitModelError, explicitModelErrorForAgent, referencedBundlePaths, skillDirs, TaskCreationBlockedError, recordUnmappedIdentity, MAX_TASK_ATTACHMENT_BYTES, recordTaskAttachmentUpload, buildEffectiveText, bufferedFileFailures, fetchSlackFiles, createSlackTaskWithFiles, notifySlackFileFailures, isRuntimePoolWakeable, isAgentReachable, hasOtherUserMention, broadcastMatches, routeMessage, extractTaskFromMessage, extractSlackMessageText, recoverIncompleteRuns, handleWebhookTrigger, verifyHmacSignature, WebhookError, snapshotAndUpdateWorkflow, RawLlmConfigSchema, RawLlmOutputSchema, executeRawLlm, getExecutorRegistry2, initWorkflows2, dispatchScheduleTarget, calculateNextRun2, startScheduler2, stopScheduler2, runScheduleNow2, ExtensionAssetConflictError, ExtensionOwnershipError, getExtensionFiles, getExtensionById, getExtensionByName, listExtensions, listExtensionVersions, updateExtensionMeta, listExtensionRuns, SDK_ALLOWLIST, mcpToolNameForSdkMethod, mcpOverflowAuthError, hasKvViewArgs, resolveKvView, toolErr, createToolRegistrar, handleMcpBridge, Redacted, SCRIPT_SDK_RESPONSE_LIMIT_BYTES, readScriptSdkJsonResponse, ExtensionConfigError, ExtensionLifecycleError, setExtensionLoopbackBaseUrl, enableExtension, disableExtension, activateVersion, ExtensionAssetsInvalidError, installExtensionWithAssets, uninstallExtension, reloadExtension, loadEnabledExtensions, stopExtensionRuntime, ExtensionAbortedError2, isRegistered2, isExtensionAgentId2, getExtensionBridgeToken2, resolveBridgeCallOrigin2, extensionIdForAgent2, runContext2, registerLoaded2, unregister2, listRegistered2, dispatchPre2, dispatchPost2, stripSiblingBlock, createTaskWithSiblingAwareness, isInboxAllowed, isSenderAllowed, handleMessageReceived, isAzureDevOpsEnabled, initAzureDevOps, verifyAzureDevOpsWebhook, repointTrackerSyncBySwarmId, isAzureDevOpsUrl, canonicalAzureDevOpsRepoUrl, parseAzureDevOpsRepoUrl, createdPullRequestOf, commentedPayloadOf, handlePullRequestCreated, handlePullRequestCommented, handleWorkItemCreated, handleWorkItemUpdated, handleWorkItemCommented, handleWorkItemDeleted, handleWorkItemRestored, initAzureDevOpsOutbound, AGENT_MAX_TASKS_CONFIG_KEY, reconcileAgentMaxTasksPolicy, resetAgentMaxTasksMirror, upsertSwarmConfigWithPolicyMirror, runtimeStaleThresholdMinutes, upsertRuntimeInstance, getRuntimeInstanceById, insertProvisioningRuntime, markRuntimeTerminated, touchRuntimeInstance, countActiveRuntimeInstancesForAgent, listRuntimeInstancesForAgent, setRuntimeCredentialReady, reconcileAgentStatusFromRuntimes, agentsWithLiveRuntime, expireStaleRuntimeInstances, listRuntimeInstancesForPool, enqueueAuditRow, enqueueAdmissionRow, flushAuditBuffer, startAuditWriter, stopAuditWriter, startAuditGc, stopAuditGc, getTelemetryIngestAnchor, initApiTelemetry, syncTelemetryEnabled, handlePullRequest, handleIssue, handleComment, handlePullRequestReview, handleCheckRun, handleCheckSuite, handleWorkflowRun, isGitLabEnabled, initGitLab, verifyGitLabWebhook, handleMergeRequest, handleIssue2, handleNote, handlePipeline, isChatSdkEnabled, getChatSdkConfig, errorMessage, resolveAdapterApiUrl, trackBackground, TelegramBotApiError, callTelegramBotApi, isTrustedTeamsServiceUrl, isChatSdkStopping, startChatSdk, getChatInstance, isChatAdapterConfigured, getChatSdkHealth, stopChatSdk, getJiraMetadata, updateJiraMetadata, clearJiraMetadata, registerJiraWebhook, deleteJiraWebhook, isJiraEnabled, initJira, handleJiraWebhook, handleAgentSessionEvent, handleIssueUpdate, handleIssueDelete, handleAgentSessionPrompted, isLinearEnabled, initLinear, parseCookieHeader, extractAndVerifyCookie, issuePageSessionCookie, resolveHttpRequestAuth, loadGlobalConfigsIntoEnv, reloadGlobalConfigsAndIntegrations, scheduleIntegrationsReload, handleCore, userCtx, handleApps, cancelApprovalRequest, cancelApprovalRequestAndRun, getUserCommsPrefs, getTaskDetailsInputSchema, getTaskDetailsOutputSchema, getTaskDetailsHandler, cancelTaskInputSchema, cancelTaskOutputSchema, cancelTaskHandler, executeReadOnlyQuery, assertSelectOnlyQuery, handleDbQuery, snapshotMetric, AssetKeyAuthorizationError, authorizeAssetKeyWrite, getPageEditCounter, snapshotPage, assertOAuthAppUrlsSafe, assertOAuthEgressUrlSafe, listOAuthPresets, listOAuthPresetIds, getOAuthPreset, hydrateOAuthAppFromPreset, scopedResourceScopeIdSchema, resolveScopedResourceId, dedupeMemoryDocumentIds, recordMemoryAccesses, recordRetrievals, ExplicitSelfDuplicateError, applyRating, shouldPersistAutomaticTaskMemory, REBOOT_RETRY_PIN_TAG, getPinCandidateAgent, resolveLeadOnlyRecoveryAssignment, getResumeGeneration, getNextResumeGeneration, inheritedModelSelection, createWorkerTaskFollowUp, createResumeFollowUp, createRerouteDecisionTask, createPoolStarvationDecisionTask, guardTerminalTaskResultWrite, getTasksInputSchema, getTasksOutputSchema, getTasksHandler, reservedNamespaceError, reservedRoomKeyError, updateMcpServerChecked, updateTouchesStdioExecution, MemoryKeyError, refreshLinks, canReadMemory, getLinksForMemory, expandCandidatesWithGraph, indexMemoryContent, isApiDraining, drainApi, markKapsoMessageRead, sendKapsoReaction, getKapsoConfig, getKapsoNumberMapping, markKapsoMessageSeen, changesAllowMerge, updateSwarmRepoChecked, getCombConfig, resolveRoomNamespace, roomRequestInfo, authorizeRoomNamespace, sessionAccessTopic, sessionPresenceRoot, RoomOperationSchema, removeAwarenessStates, roomTopic, decodeRoomSnapshot, roomView, getRoom, changeRoom, applyRoomUpdate, resetRoom, sweepRooms, closeRooms, removeNamespaceRooms, MEMORY_KEYS_DEFAULT_PREFIX, MEMORY_KEYS_MAX_LIMIT, estimateTokens, posteriorMean, listMemoryKeys, checkChunkIntegrity, getMemoryChunks, getPosteriorsByIds, createEvent, createEventsBatch, getEventCountsFiltered, getEventsFiltered, mergeScheduleTiming, validateRecurringTiming, checkOutputSchemaShape, sendTaskOutputSchema, sendTaskHandler, steerTaskUserInputSchema, steerTaskOutputSchema, steerTaskHandler, canClaim, emitBudgetRefusalSideEffects, workflowModelErrors, patchWorkflowDefinition, resolveScriptsOnlyMode, ALL_CAPABILITIES, hasCapability, getEnabledCapabilities, createServer };