agor-live 0.17.2 → 0.17.3

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 (316) hide show
  1. package/dist/cli/lib/banner.d.ts +1 -1
  2. package/dist/cli/lib/banner.js +1 -1
  3. package/dist/cli/lib/check-migrations.test.js +9627 -9112
  4. package/dist/cli/lib/daemon-manager.test.js +9632 -9117
  5. package/dist/cli/lib/help.js +1 -1
  6. package/dist/core/api/index.d.cts +3 -3
  7. package/dist/core/api/index.d.ts +3 -3
  8. package/dist/core/{board-comment-DIdOJrSF.d.cts → board-comment-CCFVVN7K.d.cts} +0 -2
  9. package/dist/core/{board-comment-3N-jSgsk.d.ts → board-comment-iT3DgZb4.d.ts} +0 -2
  10. package/dist/core/claude/index.cjs +29 -19
  11. package/dist/core/claude/index.d.cts +2 -2
  12. package/dist/core/claude/index.d.ts +2 -2
  13. package/dist/core/claude/index.js +32 -33
  14. package/dist/core/client/index.cjs +49 -0
  15. package/dist/core/client/index.d.cts +7 -7
  16. package/dist/core/client/index.d.ts +7 -7
  17. package/dist/core/client/index.js +46 -0
  18. package/dist/core/{client-B5PyIvNc.d.cts → client-CemqXk0v.d.cts} +116 -100
  19. package/dist/core/{client-C1CsRi19.d.ts → client-uYEOha6g.d.ts} +116 -100
  20. package/dist/core/config/browser.d.cts +3 -3
  21. package/dist/core/config/browser.d.ts +3 -3
  22. package/dist/core/config/index.cjs +84 -41
  23. package/dist/core/config/index.d.cts +59 -17
  24. package/dist/core/config/index.d.ts +59 -17
  25. package/dist/core/config/index.js +86 -55
  26. package/dist/core/{config-manager-TxxjFMRd.d.cts → config-manager-B8TP9Kz0.d.cts} +12 -3
  27. package/dist/core/{config-manager-DTrsj6G3.d.ts → config-manager-CDEB0FY4.d.ts} +12 -3
  28. package/dist/core/{config-services-YEZ4DwCD.d.cts → config-services-CXyQKEK5.d.cts} +1 -1
  29. package/dist/core/{config-services-DcO2GRgh.d.ts → config-services-DhM7_yWn.d.ts} +1 -1
  30. package/dist/core/db/index.cjs +235 -175
  31. package/dist/core/db/index.d.cts +190 -147
  32. package/dist/core/db/index.d.ts +190 -147
  33. package/dist/core/db/index.js +239 -190
  34. package/dist/core/db/session-guard.d.cts +4 -4
  35. package/dist/core/db/session-guard.d.ts +4 -4
  36. package/dist/core/drizzle/postgres/0028_queued_tasks.sql +8 -0
  37. package/dist/core/drizzle/postgres/0030_migrate_queued_messages.sql +24 -0
  38. package/dist/core/drizzle/postgres/0031_restructure_agentic_tool_config.sql +201 -0
  39. package/dist/core/drizzle/postgres/meta/_journal.json +21 -0
  40. package/dist/core/drizzle/sqlite/0039_queued_tasks.sql +13 -0
  41. package/dist/core/drizzle/sqlite/0040_migrate_queued_messages.sql +61 -0
  42. package/dist/core/drizzle/sqlite/0041_restructure_agentic_tool_config.sql +204 -0
  43. package/dist/core/drizzle/sqlite/meta/_journal.json +21 -0
  44. package/dist/core/gateway/index.d.cts +2 -2
  45. package/dist/core/gateway/index.d.ts +2 -2
  46. package/dist/core/{gateway-BnOlAelY.d.cts → gateway-BWq4j_Ll.d.cts} +1 -1
  47. package/dist/core/{gateway-B_4X-v07.d.ts → gateway-C3Jm_akw.d.ts} +1 -1
  48. package/dist/core/git/index.d.cts +4 -4
  49. package/dist/core/git/index.d.ts +4 -4
  50. package/dist/core/index.cjs +474 -201
  51. package/dist/core/index.d.cts +12 -10
  52. package/dist/core/index.d.ts +12 -10
  53. package/dist/core/index.js +473 -216
  54. package/dist/core/lib/feathers-validation.cjs +2 -1
  55. package/dist/core/lib/feathers-validation.d.cts +1 -1
  56. package/dist/core/lib/feathers-validation.d.ts +1 -1
  57. package/dist/core/lib/feathers-validation.js +2 -1
  58. package/dist/core/mcp/index.cjs +26 -16
  59. package/dist/core/mcp/index.js +26 -16
  60. package/dist/core/{message-DinITA7a.d.cts → message-CSWOsdcZ.d.cts} +1 -9
  61. package/dist/core/{message-CHUUP6OS.d.ts → message-DZa8g0s0.d.ts} +1 -9
  62. package/dist/core/models/index.d.cts +3 -73
  63. package/dist/core/models/index.d.ts +3 -73
  64. package/dist/core/package.json +5 -0
  65. package/dist/core/permissions/index.d.cts +1 -1
  66. package/dist/core/permissions/index.d.ts +1 -1
  67. package/dist/core/resolve-config-BcL-Hv8k.d.ts +74 -0
  68. package/dist/core/resolve-config-DTCxuSBx.d.cts +74 -0
  69. package/dist/core/seed/index.cjs +145 -98
  70. package/dist/core/seed/index.js +148 -112
  71. package/dist/core/{session-guard-C0LkDEN7.d.ts → session-guard-BFqVtBoS.d.ts} +1 -1
  72. package/dist/core/{session-guard-kvAx_8Fb.d.cts → session-guard-KHh0cnET.d.cts} +1 -1
  73. package/dist/core/sessions/index.cjs +184 -0
  74. package/dist/core/sessions/index.d.cts +79 -0
  75. package/dist/core/sessions/index.d.ts +79 -0
  76. package/dist/core/sessions/index.js +157 -0
  77. package/dist/core/{task-BLPFCORT.d.ts → task-BHV-YHg1.d.ts} +41 -3
  78. package/dist/core/{task-wht1RJEL.d.cts → task-C2Hy7H6u.d.cts} +41 -3
  79. package/dist/core/templates/session-context.d.cts +1 -1
  80. package/dist/core/templates/session-context.d.ts +1 -1
  81. package/dist/core/tools/mcp/oauth-mcp-transport.cjs +168 -66
  82. package/dist/core/tools/mcp/oauth-mcp-transport.d.cts +92 -16
  83. package/dist/core/tools/mcp/oauth-mcp-transport.d.ts +92 -16
  84. package/dist/core/tools/mcp/oauth-mcp-transport.js +165 -66
  85. package/dist/core/tools/mcp/oauth-refresh.cjs +43 -53
  86. package/dist/core/tools/mcp/oauth-refresh.d.cts +3 -3
  87. package/dist/core/tools/mcp/oauth-refresh.d.ts +3 -3
  88. package/dist/core/tools/mcp/oauth-refresh.js +58 -78
  89. package/dist/core/types/index.cjs +49 -0
  90. package/dist/core/types/index.d.cts +7 -7
  91. package/dist/core/types/index.d.ts +7 -7
  92. package/dist/core/types/index.js +46 -0
  93. package/dist/core/{types-DNqfdt1z.d.cts → types-D4Rl6ZKN.d.cts} +18 -2
  94. package/dist/core/{types-DqPMmTad.d.ts → types-n61iaXub.d.ts} +18 -2
  95. package/dist/core/unix/index.cjs +164 -110
  96. package/dist/core/unix/index.d.cts +7 -8
  97. package/dist/core/unix/index.d.ts +7 -8
  98. package/dist/core/unix/index.js +167 -124
  99. package/dist/core/{user-DkNdeFoz.d.cts → user-CpfkcV2C.d.cts} +139 -13
  100. package/dist/core/{user-BfVWBmXA.d.ts → user-DP-XZMIM.d.ts} +139 -13
  101. package/dist/core/utils/permission-mode-mapper.d.cts +0 -2
  102. package/dist/core/utils/permission-mode-mapper.d.ts +0 -2
  103. package/dist/daemon/index.js +2976 -2791
  104. package/dist/daemon/main.js +2976 -2791
  105. package/dist/daemon/mcp/server.js +177 -134
  106. package/dist/daemon/mcp/tools/analytics.js +19 -5
  107. package/dist/daemon/mcp/tools/artifacts.js +19 -5
  108. package/dist/daemon/mcp/tools/boards.js +19 -5
  109. package/dist/daemon/mcp/tools/card-types.js +19 -5
  110. package/dist/daemon/mcp/tools/cards.js +19 -5
  111. package/dist/daemon/mcp/tools/environment.js +19 -5
  112. package/dist/daemon/mcp/tools/mcp-servers.d.ts +29 -2
  113. package/dist/daemon/mcp/tools/mcp-servers.js +64 -54
  114. package/dist/daemon/mcp/tools/messages.js +19 -5
  115. package/dist/daemon/mcp/tools/repos.js +19 -5
  116. package/dist/daemon/mcp/tools/search.js +19 -5
  117. package/dist/daemon/mcp/tools/sessions.js +175 -53
  118. package/dist/daemon/mcp/tools/tasks.js +19 -5
  119. package/dist/daemon/mcp/tools/users.js +19 -5
  120. package/dist/daemon/mcp/tools/worktrees.js +37 -38
  121. package/dist/daemon/register-hooks.js +52 -1
  122. package/dist/daemon/register-routes.js +436 -424
  123. package/dist/daemon/register-services.js +255 -140
  124. package/dist/daemon/services/config.d.ts +7 -1
  125. package/dist/daemon/services/config.js +3 -2
  126. package/dist/daemon/services/gateway.js +28 -15
  127. package/dist/daemon/services/mcp-servers.d.ts +7 -2
  128. package/dist/daemon/services/repos.js +2 -0
  129. package/dist/daemon/services/sessions.d.ts +1 -1
  130. package/dist/daemon/services/sessions.js +8 -16
  131. package/dist/daemon/services/tasks.js +16 -10
  132. package/dist/daemon/services/terminals.js +2 -0
  133. package/dist/daemon/services/users.d.ts +27 -11
  134. package/dist/daemon/services/users.js +89 -43
  135. package/dist/daemon/services/worktree-owners.js +2 -0
  136. package/dist/daemon/services/worktrees.js +2 -0
  137. package/dist/daemon/setup/index.js +5 -2
  138. package/dist/daemon/setup/socketio.d.ts +10 -1
  139. package/dist/daemon/setup/socketio.js +7 -3
  140. package/dist/daemon/startup.js +13 -1
  141. package/dist/daemon/utils/apply-session-config-defaults.d.ts +54 -0
  142. package/dist/daemon/utils/apply-session-config-defaults.js +46 -0
  143. package/dist/daemon/utils/spawn-executor.js +2 -0
  144. package/dist/daemon/utils/worktree-authorization.d.ts +2 -4
  145. package/dist/executor/commands/zellij.d.ts.map +1 -1
  146. package/dist/executor/commands/zellij.js +2 -2
  147. package/dist/executor/handlers/sdk/base-executor.d.ts +4 -3
  148. package/dist/executor/handlers/sdk/base-executor.d.ts.map +1 -1
  149. package/dist/executor/handlers/sdk/base-executor.js +11 -5
  150. package/dist/executor/payload-types.d.ts +14 -14
  151. package/dist/executor/sdk-handlers/claude/claude-tool.d.ts.map +1 -1
  152. package/dist/executor/sdk-handlers/claude/claude-tool.js +9 -4
  153. package/dist/executor/sdk-handlers/claude/import/task-extractor.d.ts.map +1 -1
  154. package/dist/executor/sdk-handlers/claude/import/task-extractor.js +0 -5
  155. package/dist/executor/sdk-handlers/claude/message-builder.d.ts +23 -2
  156. package/dist/executor/sdk-handlers/claude/message-builder.d.ts.map +1 -1
  157. package/dist/executor/sdk-handlers/claude/message-builder.js +33 -2
  158. package/dist/executor/sdk-handlers/claude/permissions/permission-hooks.d.ts +9 -1
  159. package/dist/executor/sdk-handlers/claude/permissions/permission-hooks.d.ts.map +1 -1
  160. package/dist/executor/sdk-handlers/claude/permissions/permission-hooks.js +12 -0
  161. package/dist/executor/sdk-handlers/claude/query-builder.d.ts.map +1 -1
  162. package/dist/executor/sdk-handlers/claude/query-builder.js +11 -6
  163. package/dist/executor/sdk-handlers/codex/codex-tool.d.ts +0 -5
  164. package/dist/executor/sdk-handlers/codex/codex-tool.d.ts.map +1 -1
  165. package/dist/executor/sdk-handlers/codex/codex-tool.js +9 -24
  166. package/dist/executor/sdk-handlers/codex/prompt-service.d.ts +15 -2
  167. package/dist/executor/sdk-handlers/codex/prompt-service.d.ts.map +1 -1
  168. package/dist/executor/sdk-handlers/codex/prompt-service.js +39 -10
  169. package/dist/executor/sdk-handlers/copilot/copilot-tool.d.ts +0 -5
  170. package/dist/executor/sdk-handlers/copilot/copilot-tool.d.ts.map +1 -1
  171. package/dist/executor/sdk-handlers/copilot/copilot-tool.js +5 -22
  172. package/dist/executor/sdk-handlers/gemini/gemini-tool.d.ts +0 -5
  173. package/dist/executor/sdk-handlers/gemini/gemini-tool.d.ts.map +1 -1
  174. package/dist/executor/sdk-handlers/gemini/gemini-tool.js +9 -24
  175. package/dist/ui/assets/{CodeEditor.inner-CO-5PAnZ.js → CodeEditor.inner-CVLqZBtM.js} +1 -1
  176. package/dist/ui/assets/{CodeEditor.inner-CO-5PAnZ.js.gz → CodeEditor.inner-CVLqZBtM.js.gz} +0 -0
  177. package/dist/ui/assets/{_basePickBy-DfxojsEt.js → _basePickBy-CFq5ES2J.js} +1 -1
  178. package/dist/ui/assets/_basePickBy-CFq5ES2J.js.gz +0 -0
  179. package/dist/ui/assets/{_baseUniq-DWFPJOTC.js → _baseUniq-C4uKBvNt.js} +1 -1
  180. package/dist/ui/assets/_baseUniq-C4uKBvNt.js.gz +0 -0
  181. package/dist/ui/assets/{arc-vMZ_XGSI.js → arc-BnrcXDJJ.js} +1 -1
  182. package/dist/ui/assets/arc-BnrcXDJJ.js.gz +0 -0
  183. package/dist/ui/assets/{architectureDiagram-VXUJARFQ-DGpk_uOD.js → architectureDiagram-VXUJARFQ-DD9HD-WR.js} +1 -1
  184. package/dist/ui/assets/architectureDiagram-VXUJARFQ-DD9HD-WR.js.gz +0 -0
  185. package/dist/ui/assets/{base-80a1f760-BsVlOKqO.js → base-80a1f760-BK1VmxWU.js} +1 -1
  186. package/dist/ui/assets/{blockDiagram-VD42YOAC-BkRnxc94.js → blockDiagram-VD42YOAC-LBAckZZe.js} +1 -1
  187. package/dist/ui/assets/blockDiagram-VD42YOAC-LBAckZZe.js.gz +0 -0
  188. package/dist/ui/assets/{c4Diagram-YG6GDRKO-Dcf-anJy.js → c4Diagram-YG6GDRKO-yEdylcYP.js} +1 -1
  189. package/dist/ui/assets/{c4Diagram-YG6GDRKO-Dcf-anJy.js.gz → c4Diagram-YG6GDRKO-yEdylcYP.js.gz} +0 -0
  190. package/dist/ui/assets/channel-CMN-iY3Q.js +1 -0
  191. package/dist/ui/assets/{chunk-4BX2VUAB-C4oVWDo8.js → chunk-4BX2VUAB-IHtzKbmQ.js} +1 -1
  192. package/dist/ui/assets/{chunk-55IACEB6-CsBbTu57.js → chunk-55IACEB6-C4o5tv_F.js} +1 -1
  193. package/dist/ui/assets/{chunk-B4BG7PRW-DtkeCZab.js → chunk-B4BG7PRW-EPkzLvlB.js} +1 -1
  194. package/dist/ui/assets/chunk-B4BG7PRW-EPkzLvlB.js.gz +0 -0
  195. package/dist/ui/assets/{chunk-DI55MBZ5-BQ_asW-1.js → chunk-DI55MBZ5-CW-Bzkzj.js} +1 -1
  196. package/dist/ui/assets/chunk-DI55MBZ5-CW-Bzkzj.js.gz +0 -0
  197. package/dist/ui/assets/{chunk-FMBD7UC4-DAdcLNG-.js → chunk-FMBD7UC4-DvGU02Io.js} +1 -1
  198. package/dist/ui/assets/{chunk-QN33PNHL-Do2zad3m.js → chunk-QN33PNHL-C-PIlz9n.js} +1 -1
  199. package/dist/ui/assets/{chunk-QZHKN3VN-CyhMmSdC.js → chunk-QZHKN3VN-BhpJFm6h.js} +1 -1
  200. package/dist/ui/assets/{chunk-TZMSLE5B-DlPypnIq.js → chunk-TZMSLE5B-Biake8IU.js} +1 -1
  201. package/dist/ui/assets/chunk-TZMSLE5B-Biake8IU.js.gz +0 -0
  202. package/dist/ui/assets/classDiagram-2ON5EDUG-Bz1et8oA.js +1 -0
  203. package/dist/ui/assets/classDiagram-v2-WZHVMYZB-Bz1et8oA.js +1 -0
  204. package/dist/ui/assets/clone-Dxo5sEAf.js +1 -0
  205. package/dist/ui/assets/{consoleHook-59e792cb-DHYIclEd.js → consoleHook-59e792cb-BzEkHWE8.js} +1 -1
  206. package/dist/ui/assets/consoleHook-59e792cb-BzEkHWE8.js.gz +0 -0
  207. package/dist/ui/assets/{cose-bilkent-S5V4N54A-DotJH9qH.js → cose-bilkent-S5V4N54A-vAiVi74s.js} +1 -1
  208. package/dist/ui/assets/cose-bilkent-S5V4N54A-vAiVi74s.js.gz +0 -0
  209. package/dist/ui/assets/{dagre-6UL2VRFP-Btssr8QF.js → dagre-6UL2VRFP-C8w7TshD.js} +1 -1
  210. package/dist/ui/assets/dagre-6UL2VRFP-C8w7TshD.js.gz +0 -0
  211. package/dist/ui/assets/{diagram-PSM6KHXK-D5_Jkog3.js → diagram-PSM6KHXK-CvnjEmtQ.js} +1 -1
  212. package/dist/ui/assets/diagram-PSM6KHXK-CvnjEmtQ.js.gz +0 -0
  213. package/dist/ui/assets/{diagram-QEK2KX5R-DlPEVSL5.js → diagram-QEK2KX5R-D245unng.js} +1 -1
  214. package/dist/ui/assets/diagram-QEK2KX5R-D245unng.js.gz +0 -0
  215. package/dist/ui/assets/{diagram-S2PKOQOG-CjO1k8aG.js → diagram-S2PKOQOG-DgGUHL8Z.js} +1 -1
  216. package/dist/ui/assets/diagram-S2PKOQOG-DgGUHL8Z.js.gz +0 -0
  217. package/dist/ui/assets/{erDiagram-Q2GNP2WA-3cO02-K3.js → erDiagram-Q2GNP2WA-Cf5paK9b.js} +1 -1
  218. package/dist/ui/assets/erDiagram-Q2GNP2WA-Cf5paK9b.js.gz +0 -0
  219. package/dist/ui/assets/{flowDiagram-NV44I4VS-CajTpSxI.js → flowDiagram-NV44I4VS-BJpHmEXV.js} +1 -1
  220. package/dist/ui/assets/flowDiagram-NV44I4VS-BJpHmEXV.js.gz +0 -0
  221. package/dist/ui/assets/{ganttDiagram-LVOFAZNH-CnY_bV3o.js → ganttDiagram-LVOFAZNH-zOyTZcXC.js} +1 -1
  222. package/dist/ui/assets/{ganttDiagram-LVOFAZNH-CnY_bV3o.js.gz → ganttDiagram-LVOFAZNH-zOyTZcXC.js.gz} +0 -0
  223. package/dist/ui/assets/{gitGraphDiagram-NY62KEGX-CH16bg-j.js → gitGraphDiagram-NY62KEGX-B0uxwqMv.js} +1 -1
  224. package/dist/ui/assets/gitGraphDiagram-NY62KEGX-B0uxwqMv.js.gz +0 -0
  225. package/dist/ui/assets/{graph-IQoZvE3o.js → graph-NWXc73TO.js} +1 -1
  226. package/dist/ui/assets/graph-NWXc73TO.js.gz +0 -0
  227. package/dist/ui/assets/{index-599aeaf7-RUCkgwsg.js → index-599aeaf7-BKmNqoNF.js} +1 -1
  228. package/dist/ui/assets/index-599aeaf7-BKmNqoNF.js.gz +0 -0
  229. package/dist/ui/assets/{index-B3AvIgqP.js → index-BRYNiHLB.js} +345 -349
  230. package/dist/ui/assets/index-BRYNiHLB.js.gz +0 -0
  231. package/dist/ui/assets/{index-QV5-5yA2.js → index-BX6Xmhes.js} +1 -1
  232. package/dist/ui/assets/index-BX6Xmhes.js.gz +0 -0
  233. package/dist/ui/assets/{index-ChmRuj_T.js → index-W1hIq1uU.js} +1 -1
  234. package/dist/ui/assets/index-W1hIq1uU.js.gz +0 -0
  235. package/dist/ui/assets/{index-C-quzPWC.js → index-ctuok0zf.js} +1 -1
  236. package/dist/ui/assets/index-ctuok0zf.js.gz +0 -0
  237. package/dist/ui/assets/{infoDiagram-ER5ION4S-2e4gZVGT.js → infoDiagram-ER5ION4S-CquCuoTH.js} +1 -1
  238. package/dist/ui/assets/{journeyDiagram-XKPGCS4Q-B5bgV3GH.js → journeyDiagram-XKPGCS4Q-B_XkufZ8.js} +1 -1
  239. package/dist/ui/assets/journeyDiagram-XKPGCS4Q-B_XkufZ8.js.gz +0 -0
  240. package/dist/ui/assets/{kanban-definition-3W4ZIXB7-Bp-aWRSc.js → kanban-definition-3W4ZIXB7-C2Bo9HkB.js} +1 -1
  241. package/dist/ui/assets/kanban-definition-3W4ZIXB7-C2Bo9HkB.js.gz +0 -0
  242. package/dist/ui/assets/katex-C6wkUDai.css +1 -0
  243. package/dist/ui/assets/{katex-DGRguze2.css.gz → katex-C6wkUDai.css.gz} +0 -0
  244. package/dist/ui/assets/{layout-BH-2XJZq.js → layout-D9A7Uaku.js} +1 -1
  245. package/dist/ui/assets/layout-D9A7Uaku.js.gz +0 -0
  246. package/dist/ui/assets/{linear-DCYXhl_f.js → linear-BJUwJsxE.js} +1 -1
  247. package/dist/ui/assets/linear-BJUwJsxE.js.gz +0 -0
  248. package/dist/ui/assets/{mermaid.core-BAuL6kgQ.js → mermaid.core-DcOEcjcA.js} +5 -5
  249. package/dist/ui/assets/mermaid.core-DcOEcjcA.js.gz +0 -0
  250. package/dist/ui/assets/{mindmap-definition-VGOIOE7T-DpH5N-N0.js → mindmap-definition-VGOIOE7T-BFT1m7BG.js} +1 -1
  251. package/dist/ui/assets/mindmap-definition-VGOIOE7T-BFT1m7BG.js.gz +0 -0
  252. package/dist/ui/assets/{pieDiagram-ADFJNKIX-BB8fBxj1.js → pieDiagram-ADFJNKIX-BFaX1oBV.js} +1 -1
  253. package/dist/ui/assets/pieDiagram-ADFJNKIX-BFaX1oBV.js.gz +0 -0
  254. package/dist/ui/assets/{quadrantDiagram-AYHSOK5B-D6oZLdUD.js → quadrantDiagram-AYHSOK5B-DQps5392.js} +1 -1
  255. package/dist/ui/assets/quadrantDiagram-AYHSOK5B-DQps5392.js.gz +0 -0
  256. package/dist/ui/assets/{requirementDiagram-UZGBJVZJ-B4uGPp8w.js → requirementDiagram-UZGBJVZJ-3EZ5KWEi.js} +1 -1
  257. package/dist/ui/assets/requirementDiagram-UZGBJVZJ-3EZ5KWEi.js.gz +0 -0
  258. package/dist/ui/assets/{sankeyDiagram-TZEHDZUN-MXhIjhme.js → sankeyDiagram-TZEHDZUN-D0qcydqq.js} +1 -1
  259. package/dist/ui/assets/sankeyDiagram-TZEHDZUN-D0qcydqq.js.gz +0 -0
  260. package/dist/ui/assets/{sequenceDiagram-WL72ISMW-Cm53TYug.js → sequenceDiagram-WL72ISMW-BCR5gaaN.js} +1 -1
  261. package/dist/ui/assets/sequenceDiagram-WL72ISMW-BCR5gaaN.js.gz +0 -0
  262. package/dist/ui/assets/{stateDiagram-FKZM4ZOC-BVuxUkj5.js → stateDiagram-FKZM4ZOC-BvX4FLQ9.js} +1 -1
  263. package/dist/ui/assets/stateDiagram-FKZM4ZOC-BvX4FLQ9.js.gz +0 -0
  264. package/dist/ui/assets/stateDiagram-v2-4FDKWEC3-CxLDvgTF.js +1 -0
  265. package/dist/ui/assets/{timeline-definition-IT6M3QCI-CMypNiEP.js → timeline-definition-IT6M3QCI-_AWp5LJn.js} +1 -1
  266. package/dist/ui/assets/timeline-definition-IT6M3QCI-_AWp5LJn.js.gz +0 -0
  267. package/dist/ui/assets/{treemap-KMMF4GRG-BEtnV3BT.js → treemap-KMMF4GRG-BZ9FBl5-.js} +1 -1
  268. package/dist/ui/assets/treemap-KMMF4GRG-BZ9FBl5-.js.gz +0 -0
  269. package/dist/ui/assets/{xychartDiagram-PRI3JC2R-BnioEYUM.js → xychartDiagram-PRI3JC2R-_wB7yuVd.js} +1 -1
  270. package/dist/ui/assets/xychartDiagram-PRI3JC2R-_wB7yuVd.js.gz +0 -0
  271. package/dist/ui/index.html +1 -1
  272. package/package.json +8 -8
  273. package/dist/ui/assets/_basePickBy-DfxojsEt.js.gz +0 -0
  274. package/dist/ui/assets/_baseUniq-DWFPJOTC.js.gz +0 -0
  275. package/dist/ui/assets/arc-vMZ_XGSI.js.gz +0 -0
  276. package/dist/ui/assets/architectureDiagram-VXUJARFQ-DGpk_uOD.js.gz +0 -0
  277. package/dist/ui/assets/blockDiagram-VD42YOAC-BkRnxc94.js.gz +0 -0
  278. package/dist/ui/assets/channel-B9aI4bYN.js +0 -1
  279. package/dist/ui/assets/chunk-B4BG7PRW-DtkeCZab.js.gz +0 -0
  280. package/dist/ui/assets/chunk-DI55MBZ5-BQ_asW-1.js.gz +0 -0
  281. package/dist/ui/assets/chunk-TZMSLE5B-DlPypnIq.js.gz +0 -0
  282. package/dist/ui/assets/classDiagram-2ON5EDUG-p-68WO4Z.js +0 -1
  283. package/dist/ui/assets/classDiagram-v2-WZHVMYZB-p-68WO4Z.js +0 -1
  284. package/dist/ui/assets/clone-DzK5ogfn.js +0 -1
  285. package/dist/ui/assets/consoleHook-59e792cb-DHYIclEd.js.gz +0 -0
  286. package/dist/ui/assets/cose-bilkent-S5V4N54A-DotJH9qH.js.gz +0 -0
  287. package/dist/ui/assets/dagre-6UL2VRFP-Btssr8QF.js.gz +0 -0
  288. package/dist/ui/assets/diagram-PSM6KHXK-D5_Jkog3.js.gz +0 -0
  289. package/dist/ui/assets/diagram-QEK2KX5R-DlPEVSL5.js.gz +0 -0
  290. package/dist/ui/assets/diagram-S2PKOQOG-CjO1k8aG.js.gz +0 -0
  291. package/dist/ui/assets/erDiagram-Q2GNP2WA-3cO02-K3.js.gz +0 -0
  292. package/dist/ui/assets/flowDiagram-NV44I4VS-CajTpSxI.js.gz +0 -0
  293. package/dist/ui/assets/gitGraphDiagram-NY62KEGX-CH16bg-j.js.gz +0 -0
  294. package/dist/ui/assets/graph-IQoZvE3o.js.gz +0 -0
  295. package/dist/ui/assets/index-599aeaf7-RUCkgwsg.js.gz +0 -0
  296. package/dist/ui/assets/index-B3AvIgqP.js.gz +0 -0
  297. package/dist/ui/assets/index-C-quzPWC.js.gz +0 -0
  298. package/dist/ui/assets/index-ChmRuj_T.js.gz +0 -0
  299. package/dist/ui/assets/index-QV5-5yA2.js.gz +0 -0
  300. package/dist/ui/assets/journeyDiagram-XKPGCS4Q-B5bgV3GH.js.gz +0 -0
  301. package/dist/ui/assets/kanban-definition-3W4ZIXB7-Bp-aWRSc.js.gz +0 -0
  302. package/dist/ui/assets/katex-DGRguze2.css +0 -1
  303. package/dist/ui/assets/layout-BH-2XJZq.js.gz +0 -0
  304. package/dist/ui/assets/linear-DCYXhl_f.js.gz +0 -0
  305. package/dist/ui/assets/mermaid.core-BAuL6kgQ.js.gz +0 -0
  306. package/dist/ui/assets/mindmap-definition-VGOIOE7T-DpH5N-N0.js.gz +0 -0
  307. package/dist/ui/assets/pieDiagram-ADFJNKIX-BB8fBxj1.js.gz +0 -0
  308. package/dist/ui/assets/quadrantDiagram-AYHSOK5B-D6oZLdUD.js.gz +0 -0
  309. package/dist/ui/assets/requirementDiagram-UZGBJVZJ-B4uGPp8w.js.gz +0 -0
  310. package/dist/ui/assets/sankeyDiagram-TZEHDZUN-MXhIjhme.js.gz +0 -0
  311. package/dist/ui/assets/sequenceDiagram-WL72ISMW-Cm53TYug.js.gz +0 -0
  312. package/dist/ui/assets/stateDiagram-FKZM4ZOC-BVuxUkj5.js.gz +0 -0
  313. package/dist/ui/assets/stateDiagram-v2-4FDKWEC3-8Jeww6Dc.js +0 -1
  314. package/dist/ui/assets/timeline-definition-IT6M3QCI-CMypNiEP.js.gz +0 -0
  315. package/dist/ui/assets/treemap-KMMF4GRG-BEtnV3BT.js.gz +0 -0
  316. package/dist/ui/assets/xychartDiagram-PRI3JC2R-BnioEYUM.js.gz +0 -0
@@ -16293,11 +16293,47 @@ async function getOAuthStatus(ctx, mcpServer) {
16293
16293
  }
16294
16294
  return { authenticated: false };
16295
16295
  }
16296
+ async function summarizeMcpServer(ctx, mcpServer) {
16297
+ const authType = mcpServer.auth?.type || "none";
16298
+ const oauthMode = mcpServer.auth?.oauth_mode || "per_user";
16299
+ const { authenticated } = await getOAuthStatus(ctx, mcpServer);
16300
+ return {
16301
+ mcp_server_id: mcpServer.mcp_server_id,
16302
+ name: mcpServer.name,
16303
+ display_name: mcpServer.display_name,
16304
+ transport: mcpServer.transport,
16305
+ auth_type: authType,
16306
+ oauth_mode: oauthMode,
16307
+ oauth_authenticated: authenticated,
16308
+ enabled: mcpServer.enabled
16309
+ };
16310
+ }
16311
+ async function listAttachedMcpServers(ctx, sessionId, opts = {}) {
16312
+ const sessionMCPServers = await ctx.app.service("session-mcp-servers").find({
16313
+ ...ctx.baseServiceParams,
16314
+ query: {
16315
+ session_id: sessionId,
16316
+ ...opts.includeDisabled ? {} : { enabled: true },
16317
+ $limit: 100
16318
+ }
16319
+ });
16320
+ const data = Array.isArray(sessionMCPServers) ? sessionMCPServers : sessionMCPServers.data;
16321
+ const summaries = [];
16322
+ for (const sms of data) {
16323
+ try {
16324
+ const mcpServer = await ctx.app.service("mcp-servers").get(sms.mcp_server_id, ctx.baseServiceParams);
16325
+ summaries.push(await summarizeMcpServer(ctx, mcpServer));
16326
+ } catch (error48) {
16327
+ console.warn(`Failed to fetch MCP server ${sms.mcp_server_id}:`, error48);
16328
+ }
16329
+ }
16330
+ return summaries;
16331
+ }
16296
16332
  function registerMcpServerTools(server, ctx) {
16297
16333
  server.registerTool(
16298
16334
  "agor_mcp_servers_list",
16299
16335
  {
16300
- description: "List MCP servers available to the current session. Shows each server's name, transport type, authentication type, and OAuth connection status. Use this to see which external tools/services are configured and whether they need authentication.",
16336
+ description: "List the MCP-server catalog the current user can access (i.e. servers eligible to attach to a session). Each entry includes name, transport, auth type, and OAuth status. Use this to discover IDs to pass to `agor_sessions_create({ mcpServerIds })`. To see which servers are currently ATTACHED to a session, read `attached_mcp_servers` from `agor_sessions_get_current` or `agor_sessions_get`.",
16301
16337
  annotations: { readOnlyHint: true },
16302
16338
  inputSchema: external_exports2.object({
16303
16339
  includeDisabled: external_exports2.boolean().optional().describe("Include disabled MCP servers (default: false)")
@@ -16305,62 +16341,20 @@ function registerMcpServerTools(server, ctx) {
16305
16341
  },
16306
16342
  async (args) => {
16307
16343
  const includeDisabled = args.includeDisabled === true;
16308
- const sessionMCPServers = await ctx.app.service("session-mcp-servers").find({
16344
+ const result = await ctx.app.service("mcp-servers").find({
16309
16345
  ...ctx.baseServiceParams,
16310
16346
  query: {
16311
- session_id: ctx.sessionId,
16347
+ scope: "global",
16312
16348
  ...includeDisabled ? {} : { enabled: true },
16313
16349
  $limit: 100
16314
16350
  }
16315
16351
  });
16352
+ const data = Array.isArray(result) ? result : result.data;
16316
16353
  const servers = [];
16317
- const sessionMCPData = Array.isArray(sessionMCPServers) ? sessionMCPServers : sessionMCPServers.data;
16318
- const mcpServerIds = sessionMCPData.map(
16319
- (sms) => sms.mcp_server_id
16320
- );
16321
- for (const serverId of mcpServerIds) {
16322
- try {
16323
- const mcpServer = await ctx.app.service("mcp-servers").get(serverId, ctx.baseServiceParams);
16324
- const authType = mcpServer.auth?.type || "none";
16325
- const oauthMode = mcpServer.auth?.oauth_mode || "per_user";
16326
- const { authenticated } = await getOAuthStatus(ctx, mcpServer);
16327
- servers.push({
16328
- mcp_server_id: mcpServer.mcp_server_id,
16329
- name: mcpServer.name,
16330
- display_name: mcpServer.display_name,
16331
- transport: mcpServer.transport,
16332
- auth_type: authType,
16333
- oauth_mode: oauthMode,
16334
- oauth_authenticated: authenticated,
16335
- enabled: mcpServer.enabled
16336
- });
16337
- } catch (error48) {
16338
- console.warn(`Failed to fetch MCP server ${serverId}:`, error48);
16339
- }
16340
- }
16341
- const globalServers = await ctx.app.service("mcp-servers").find({
16342
- ...ctx.baseServiceParams,
16343
- query: { scope: "global", ...includeDisabled ? {} : { enabled: true }, $limit: 100 }
16344
- });
16345
- for (const mcpServer of Array.isArray(globalServers) ? globalServers : globalServers.data) {
16346
- if (!mcpServerIds.includes(mcpServer.mcp_server_id)) {
16347
- const authType = mcpServer.auth?.type || "none";
16348
- const oauthMode = mcpServer.auth?.oauth_mode || "per_user";
16349
- const { authenticated } = await getOAuthStatus(ctx, mcpServer);
16350
- servers.push({
16351
- mcp_server_id: mcpServer.mcp_server_id,
16352
- name: mcpServer.name,
16353
- display_name: mcpServer.display_name,
16354
- transport: mcpServer.transport,
16355
- auth_type: authType,
16356
- oauth_mode: oauthMode,
16357
- oauth_authenticated: authenticated,
16358
- enabled: mcpServer.enabled
16359
- });
16360
- }
16354
+ for (const mcpServer of data) {
16355
+ servers.push(await summarizeMcpServer(ctx, mcpServer));
16361
16356
  }
16362
16357
  return textResult({
16363
- session_id: ctx.sessionId,
16364
16358
  mcp_servers: servers,
16365
16359
  summary: {
16366
16360
  total: servers.length,
@@ -16797,11 +16791,24 @@ var init_search = __esm({
16797
16791
 
16798
16792
  // src/mcp/tools/sessions.ts
16799
16793
  import { WorktreeRepository as WorktreeRepository3 } from "@agor/core/db";
16800
- import { resolveModelConfigPrecedence } from "@agor/core/models";
16794
+ import {
16795
+ AVAILABLE_CLAUDE_MODEL_ALIASES,
16796
+ CODEX_MODEL_METADATA,
16797
+ DEFAULT_CLAUDE_MODEL,
16798
+ DEFAULT_CODEX_MODEL,
16799
+ DEFAULT_GEMINI_MODEL,
16800
+ GEMINI_MODELS
16801
+ } from "@agor/core/models";
16802
+ import { resolveSessionDefaults } from "@agor/core/sessions";
16801
16803
  import {
16802
16804
  AGENTIC_TOOL_CAPABILITIES,
16803
16805
  getSessionType
16804
16806
  } from "@agor/core/types";
16807
+ function coerceModelConfig(input) {
16808
+ if (input === void 0) return void 0;
16809
+ if (typeof input === "string") return { model: input };
16810
+ return input;
16811
+ }
16805
16812
  function registerSessionTools(server, ctx) {
16806
16813
  server.registerTool(
16807
16814
  "agor_sessions_list",
@@ -16854,7 +16861,7 @@ function registerSessionTools(server, ctx) {
16854
16861
  server.registerTool(
16855
16862
  "agor_sessions_get",
16856
16863
  {
16857
- description: "Get detailed information about a specific session, including genealogy and current state. The response includes a `url` field with a clickable link to view the session in the UI.",
16864
+ description: "Get detailed information about a specific session, including genealogy, current state, and the MCP servers currently attached to it (with OAuth status \u2014 check `attached_mcp_servers[].oauth_authenticated` to spot servers needing auth). The response includes a `url` field with a clickable link to view the session in the UI.",
16858
16865
  annotations: { readOnlyHint: true },
16859
16866
  inputSchema: external_exports2.object({
16860
16867
  sessionId: external_exports2.string().describe("Session ID (UUIDv7 or short ID like 01a1b2c3)")
@@ -16867,13 +16874,14 @@ function registerSessionTools(server, ctx) {
16867
16874
  _last_message_truncation_length: 500
16868
16875
  };
16869
16876
  const session = await ctx.app.service("sessions").get(args.sessionId, sessionParams);
16870
- return textResult(session);
16877
+ const attached_mcp_servers = await listAttachedMcpServers(ctx, session.session_id);
16878
+ return textResult({ ...session, attached_mcp_servers });
16871
16879
  }
16872
16880
  );
16873
16881
  server.registerTool(
16874
16882
  "agor_sessions_get_current",
16875
16883
  {
16876
- description: "Get information about the current session (the one making this MCP call). Returns session details plus denormalized worktree, repo, and board context \u2014 useful for introspection and getting IDs needed by other tools.",
16884
+ description: "Get information about the current session (the one making this MCP call). Returns session details, denormalized worktree/repo/board context, and the MCP servers attached to this session (each with `oauth_authenticated` so callers can spot servers needing auth). To browse the broader catalog of servers eligible to attach, use `agor_mcp_servers_list`.",
16877
16885
  annotations: { readOnlyHint: true },
16878
16886
  inputSchema: external_exports2.object({})
16879
16887
  },
@@ -16923,11 +16931,13 @@ function registerSessionTools(server, ctx) {
16923
16931
  } catch {
16924
16932
  }
16925
16933
  }
16934
+ const attached_mcp_servers = await listAttachedMcpServers(ctx, ctx.sessionId);
16926
16935
  return textResult({
16927
16936
  session,
16928
16937
  worktree,
16929
16938
  repo,
16930
- board
16939
+ board,
16940
+ attached_mcp_servers
16931
16941
  });
16932
16942
  }
16933
16943
  );
@@ -17084,10 +17094,10 @@ function registerSessionTools(server, ctx) {
17084
17094
  extraInstructions: args.extraInstructions,
17085
17095
  task_id: args.taskId,
17086
17096
  mcpServerIds: args.mcpServerIds,
17087
- modelConfig: args.modelConfig
17097
+ modelConfig: coerceModelConfig(args.modelConfig)
17088
17098
  };
17089
17099
  const childSession = await ctx.app.service("sessions").spawn(ctx.sessionId, spawnData, ctx.baseServiceParams);
17090
- const promptResponse = await ctx.app.service("/sessions/:id/prompt").create(
17100
+ const task = await ctx.app.service("/sessions/:id/prompt").create(
17091
17101
  {
17092
17102
  prompt: args.prompt,
17093
17103
  permissionMode: childSession.permission_config?.mode || "acceptEdits",
@@ -17100,8 +17110,8 @@ function registerSessionTools(server, ctx) {
17100
17110
  );
17101
17111
  return textResult({
17102
17112
  session: childSession,
17103
- taskId: promptResponse.taskId,
17104
- status: promptResponse.status,
17113
+ taskId: task.task_id,
17114
+ status: task.status,
17105
17115
  note: "Subsession created and prompt execution started in background."
17106
17116
  });
17107
17117
  }
@@ -17131,22 +17141,23 @@ function registerSessionTools(server, ctx) {
17131
17141
  const mode = args.mode;
17132
17142
  const sessionId = await resolveSessionId(ctx, args.sessionId);
17133
17143
  if (mode === "continue") {
17134
- const promptResponse = await ctx.app.service("/sessions/:id/prompt").create(
17144
+ const task = await ctx.app.service("/sessions/:id/prompt").create(
17135
17145
  { prompt: args.prompt, stream: true },
17136
17146
  { ...ctx.baseServiceParams, route: { id: sessionId } }
17137
17147
  );
17138
- if (promptResponse.queued) {
17148
+ if (task.status === "queued") {
17139
17149
  return textResult({
17140
17150
  success: true,
17141
17151
  queued: true,
17142
- queue_position: promptResponse.queue_position,
17152
+ taskId: task.task_id,
17153
+ queue_position: task.queue_position,
17143
17154
  note: "Session is busy. Prompt has been queued and will execute automatically when the session becomes idle."
17144
17155
  });
17145
17156
  }
17146
17157
  return textResult({
17147
17158
  success: true,
17148
- taskId: promptResponse.taskId,
17149
- status: promptResponse.status,
17159
+ taskId: task.task_id,
17160
+ status: task.status,
17150
17161
  note: "Prompt added to existing session and execution started."
17151
17162
  });
17152
17163
  } else if (mode === "fork" || mode === "btw") {
@@ -17175,7 +17186,7 @@ function registerSessionTools(server, ctx) {
17175
17186
  await ctx.app.service("sessions").patch(forkedSession.session_id, forkPatch, ctx.baseServiceParams);
17176
17187
  }
17177
17188
  const updatedSession = await ctx.app.service("sessions").get(forkedSession.session_id, ctx.baseServiceParams);
17178
- const promptResponse = await ctx.app.service("/sessions/:id/prompt").create(
17189
+ const task = await ctx.app.service("/sessions/:id/prompt").create(
17179
17190
  {
17180
17191
  prompt: args.prompt,
17181
17192
  permissionMode: updatedSession.permission_config?.mode,
@@ -17186,21 +17197,21 @@ function registerSessionTools(server, ctx) {
17186
17197
  const note = mode === "btw" ? 'Ephemeral "btw" fork created. Result will be sent back via callback when done, then the fork will auto-archive.' : "Forked session created and prompt execution started.";
17187
17198
  return textResult({
17188
17199
  session: updatedSession,
17189
- taskId: promptResponse.taskId,
17190
- status: promptResponse.status,
17200
+ taskId: task.task_id,
17201
+ status: task.status,
17191
17202
  note
17192
17203
  });
17193
17204
  } else if (mode === "subsession") {
17194
17205
  const spawnData = {
17195
17206
  prompt: args.prompt,
17196
17207
  mcpServerIds: args.mcpServerIds,
17197
- modelConfig: args.modelConfig
17208
+ modelConfig: coerceModelConfig(args.modelConfig)
17198
17209
  };
17199
17210
  if (args.title) spawnData.title = args.title;
17200
17211
  if (args.agenticTool) spawnData.agent = args.agenticTool;
17201
17212
  if (args.taskId) spawnData.task_id = args.taskId;
17202
17213
  const childSession = await ctx.app.service("sessions").spawn(sessionId, spawnData, ctx.baseServiceParams);
17203
- const promptResponse = await ctx.app.service("/sessions/:id/prompt").create(
17214
+ const task = await ctx.app.service("/sessions/:id/prompt").create(
17204
17215
  {
17205
17216
  prompt: args.prompt,
17206
17217
  permissionMode: childSession.permission_config?.mode,
@@ -17210,8 +17221,8 @@ function registerSessionTools(server, ctx) {
17210
17221
  );
17211
17222
  return textResult({
17212
17223
  session: childSession,
17213
- taskId: promptResponse.taskId,
17214
- status: promptResponse.status,
17224
+ taskId: task.task_id,
17225
+ status: task.status,
17215
17226
  note: "Subsession created and prompt execution started."
17216
17227
  });
17217
17228
  }
@@ -17221,7 +17232,7 @@ function registerSessionTools(server, ctx) {
17221
17232
  server.registerTool(
17222
17233
  "agor_sessions_create",
17223
17234
  {
17224
- description: "Create a new session in an existing worktree. Use for starting fresh work on a new task in the same codebase (e.g., new feature branch, separate investigation). Unlike spawn, this creates an independent session with no parent-child relationship. MCP servers are inherited from the worktree (if configured) or user defaults, or can be overridden via `mcpServerIds`. Model selection falls back to user defaults and can be overridden via `modelConfig`. Supports optional callbacks to notify the creating session when the new session completes.",
17235
+ description: 'Create a new session in an existing worktree. Use for starting fresh work on a new task in the same codebase (e.g., new feature branch, separate investigation). Unlike spawn, this creates an independent session with no parent-child relationship. MCP servers are inherited from the worktree (if configured) or user defaults, or can be overridden via `mcpServerIds`. Model selection falls back to user defaults and can be overridden via `modelConfig` (accepts either a model ID string like "claude-opus-4-6" or a full {mode, model, effort, provider} object \u2014 call `agor_models_list` to discover valid model IDs per agenticTool). Supports optional callbacks to notify the creating session when the new session completes.',
17225
17236
  inputSchema: external_exports2.object({
17226
17237
  worktreeId: external_exports2.string().describe("Worktree ID where the session will run (required)"),
17227
17238
  agenticTool: external_exports2.enum(["claude-code", "codex", "gemini"]).describe("Which agent to use for this session (required)"),
@@ -17255,27 +17266,20 @@ function registerSessionTools(server, ctx) {
17255
17266
  const { getGitState, getCurrentBranch } = await import("@agor/core/git");
17256
17267
  const currentSha = await getGitState(worktree.path);
17257
17268
  const currentRef = await getCurrentBranch(worktree.path);
17258
- const { getDefaultPermissionMode } = await import("@agor/core/types");
17259
- const { mapPermissionMode } = await import("@agor/core/utils/permission-mode-mapper");
17260
- const userToolDefaults = user?.default_agentic_config?.[agenticTool];
17261
- const requestedMode = userToolDefaults?.permissionMode || getDefaultPermissionMode(agenticTool);
17262
- const permissionMode = mapPermissionMode(requestedMode, agenticTool);
17263
- const permissionConfig = {
17264
- mode: permissionMode,
17265
- allowedTools: []
17266
- };
17267
- if (agenticTool === "codex" && userToolDefaults?.codexSandboxMode && userToolDefaults?.codexApprovalPolicy) {
17268
- permissionConfig.codex = {
17269
- sandboxMode: userToolDefaults.codexSandboxMode,
17270
- approvalPolicy: userToolDefaults.codexApprovalPolicy,
17271
- networkAccess: userToolDefaults.codexNetworkAccess
17272
- };
17273
- }
17274
- const modelConfig = resolveModelConfigPrecedence([
17275
- args.modelConfig,
17276
- userToolDefaults?.modelConfig
17277
- ]);
17278
- const mcpServerIds = args.mcpServerIds !== void 0 ? await Promise.all(args.mcpServerIds.map((id) => resolveMcpServerId(ctx, id))) : worktree.mcp_server_ids && worktree.mcp_server_ids.length > 0 ? worktree.mcp_server_ids : userToolDefaults?.mcpServerIds || [];
17269
+ const explicitMcpServerIds = args.mcpServerIds !== void 0 ? await Promise.all(args.mcpServerIds.map((id) => resolveMcpServerId(ctx, id))) : void 0;
17270
+ const resolvedDefaults = resolveSessionDefaults({
17271
+ agenticTool,
17272
+ user,
17273
+ worktree,
17274
+ overrides: {
17275
+ modelConfig: coerceModelConfig(args.modelConfig),
17276
+ mcpServerIds: explicitMcpServerIds
17277
+ }
17278
+ });
17279
+ const permissionConfig = resolvedDefaults.permission_config;
17280
+ const modelConfig = resolvedDefaults.model_config;
17281
+ const mcpServerIds = resolvedDefaults.mcp_server_ids;
17282
+ const permissionMode = permissionConfig.mode;
17279
17283
  const mcpServerIdsFromArgs = args.mcpServerIds !== void 0;
17280
17284
  const callbackConfig = {};
17281
17285
  const effectiveCallbackSessionId = args.callbackSessionId || ctx.sessionId;
@@ -17331,9 +17335,9 @@ function registerSessionTools(server, ctx) {
17331
17335
  if (mcpServerIds && mcpServerIds.length > 0) {
17332
17336
  for (const mcpServerId of mcpServerIds) {
17333
17337
  try {
17334
- await ctx.app.service("session-mcp-servers").create(
17335
- { session_id: session.session_id, mcp_server_id: mcpServerId },
17336
- ctx.baseServiceParams
17338
+ await ctx.app.service("/sessions/:id/mcp-servers").create(
17339
+ { mcpServerId },
17340
+ { ...ctx.baseServiceParams, route: { id: session.session_id } }
17337
17341
  );
17338
17342
  } catch (error48) {
17339
17343
  const reason = error48 instanceof Error ? error48.message : String(error48);
@@ -17347,9 +17351,9 @@ function registerSessionTools(server, ctx) {
17347
17351
  }
17348
17352
  }
17349
17353
  }
17350
- let promptResponse = null;
17354
+ let initialTask = null;
17351
17355
  if (args.initialPrompt) {
17352
- promptResponse = await ctx.app.service("/sessions/:id/prompt").create(
17356
+ initialTask = await ctx.app.service("/sessions/:id/prompt").create(
17353
17357
  { prompt: args.initialPrompt, permissionMode, stream: true },
17354
17358
  { ...ctx.baseServiceParams, route: { id: session.session_id } }
17355
17359
  );
@@ -17358,7 +17362,7 @@ function registerSessionTools(server, ctx) {
17358
17362
  const mcpFailureNote = mcpAttachFailures.length > 0 ? ` Warning: ${mcpAttachFailures.length} requested MCP server(s) failed to attach \u2014 see mcpAttachFailures.` : "";
17359
17363
  return textResult({
17360
17364
  session,
17361
- taskId: promptResponse?.taskId,
17365
+ taskId: initialTask?.task_id,
17362
17366
  note: args.initialPrompt ? `Session created and initial prompt execution started.${callbackNote}${mcpFailureNote}` : `Session created successfully.${callbackNote}${mcpFailureNote}`,
17363
17367
  ...mcpAttachFailures.length > 0 && { mcpAttachFailures }
17364
17368
  });
@@ -17619,8 +17623,56 @@ function registerSessionTools(server, ctx) {
17619
17623
  });
17620
17624
  }
17621
17625
  );
17626
+ server.registerTool(
17627
+ "agor_models_list",
17628
+ {
17629
+ description: "List valid model IDs grouped by agenticTool. Use this to discover what to pass for `modelConfig` (or its string shorthand) in agor_sessions_create / spawn / prompt. Sourced live from the daemon model registry \u2014 when new models ship and the registry is updated, this tool returns them on the next call.",
17630
+ annotations: { readOnlyHint: true },
17631
+ inputSchema: external_exports2.object({
17632
+ agenticTool: external_exports2.enum(["claude-code", "codex", "gemini"]).optional().describe("Filter to a single agentic tool. Omit to return all tools.")
17633
+ })
17634
+ },
17635
+ async (args) => {
17636
+ const claudeModels = AVAILABLE_CLAUDE_MODEL_ALIASES.map((m) => ({
17637
+ id: m.id,
17638
+ displayName: m.displayName,
17639
+ description: m.description,
17640
+ family: m.family
17641
+ }));
17642
+ const codexModels = Object.entries(CODEX_MODEL_METADATA).map(([id, meta3]) => ({
17643
+ id,
17644
+ displayName: meta3.name,
17645
+ description: meta3.description
17646
+ }));
17647
+ const geminiModels = Object.entries(GEMINI_MODELS).map(([id, meta3]) => ({
17648
+ id,
17649
+ displayName: meta3.name,
17650
+ description: meta3.description,
17651
+ useCase: meta3.useCase
17652
+ }));
17653
+ const all = {
17654
+ "claude-code": {
17655
+ default: DEFAULT_CLAUDE_MODEL,
17656
+ models: claudeModels
17657
+ },
17658
+ codex: {
17659
+ default: DEFAULT_CODEX_MODEL,
17660
+ models: codexModels
17661
+ },
17662
+ gemini: {
17663
+ default: DEFAULT_GEMINI_MODEL,
17664
+ models: geminiModels,
17665
+ note: "Gemini models are normally fetched live from the Google API per-user. This is the static fallback list \u2014 newer models may exist."
17666
+ }
17667
+ };
17668
+ if (args.agenticTool) {
17669
+ return textResult({ [args.agenticTool]: all[args.agenticTool] });
17670
+ }
17671
+ return textResult(all);
17672
+ }
17673
+ );
17622
17674
  }
17623
- var modelConfigInputSchema;
17675
+ var modelConfigObjectSchema, modelConfigInputSchema;
17624
17676
  var init_sessions = __esm({
17625
17677
  "src/mcp/tools/sessions.ts"() {
17626
17678
  "use strict";
@@ -17628,15 +17680,22 @@ var init_sessions = __esm({
17628
17680
  init_worktree_authorization();
17629
17681
  init_resolve_ids();
17630
17682
  init_server();
17631
- modelConfigInputSchema = external_exports2.object({
17683
+ init_mcp_servers();
17684
+ modelConfigObjectSchema = external_exports2.object({
17632
17685
  mode: external_exports2.enum(["alias", "exact"]).optional().describe("Model selection mode (default: 'alias')"),
17633
17686
  // .min(1): reject empty-string model explicitly so callers don't silently
17634
17687
  // fall through to user defaults when they meant to pin a specific model.
17635
17688
  model: external_exports2.string().min(1).describe("Model identifier (e.g. 'claude-opus-4-6', 'claude-sonnet-4-6')"),
17636
17689
  effort: external_exports2.enum(["low", "medium", "high", "max"]).optional().describe("Reasoning effort level (default: high)"),
17637
17690
  provider: external_exports2.string().optional().describe("Provider ID (OpenCode only, e.g. 'anthropic')")
17638
- }).optional().describe(
17639
- "Model override for this session. When set, overrides the user default model_config. Threaded through to the spawned agent process so it actually runs on the requested model."
17691
+ });
17692
+ modelConfigInputSchema = external_exports2.union([
17693
+ external_exports2.string().min(1).describe(
17694
+ "Shorthand: just the model ID string (e.g. 'claude-opus-4-6'). Equivalent to { model: <id> }."
17695
+ ),
17696
+ modelConfigObjectSchema
17697
+ ]).optional().describe(
17698
+ "Model override for this session. Pass either a model ID string (e.g. 'claude-opus-4-6') or a full { mode, model, effort, provider } object. Overrides the user default model_config and is threaded through to the spawned agent process. Call agor_models_list to discover valid model IDs per agenticTool."
17640
17699
  );
17641
17700
  }
17642
17701
  });
@@ -17838,7 +17897,7 @@ var init_users = __esm({
17838
17897
  // src/mcp/tools/worktrees.ts
17839
17898
  import { isWorktreeRbacEnabled as isWorktreeRbacEnabled2 } from "@agor/core/config";
17840
17899
  import { WorktreeRepository as WorktreeRepository4 } from "@agor/core/db";
17841
- import { resolveModelConfig } from "@agor/core/models";
17900
+ import { resolveSessionDefaults as resolveSessionDefaults2 } from "@agor/core/sessions";
17842
17901
  import { getAssistantConfig, isAssistant, WORKTREE_PERMISSION_LEVELS as WORKTREE_PERMISSION_LEVELS2 } from "@agor/core/types";
17843
17902
  import { computeZoneRelativePosition } from "@agor/core/utils/board-placement";
17844
17903
  import { normalizeOptionalHttpUrl } from "@agor/core/utils/url";
@@ -18274,27 +18333,28 @@ function registerWorktreeTools(server, ctx) {
18274
18333
  };
18275
18334
  const renderedPrompt = renderTemplate(zone.trigger.template, templateContext);
18276
18335
  if (renderedPrompt) {
18277
- const promptResponse = await ctx.app.service("/sessions/:id/prompt").create(
18336
+ const task = await ctx.app.service("/sessions/:id/prompt").create(
18278
18337
  { prompt: renderedPrompt, stream: true },
18279
18338
  { ...ctx.baseServiceParams, route: { id: targetSessionId } }
18280
18339
  );
18281
- if (promptResponse.queued) {
18340
+ if (task.status === "queued") {
18282
18341
  promptResult = {
18283
18342
  queued: true,
18284
- queue_position: promptResponse.queue_position,
18343
+ taskId: task.task_id,
18344
+ queue_position: task.queue_position,
18285
18345
  sessionId: targetSessionId,
18286
18346
  note: "Session is busy. Zone trigger prompt has been queued."
18287
18347
  };
18288
18348
  console.log(
18289
- `\u{1F4EC} Zone trigger queued for session ${targetSessionId.substring(0, 8)} at position ${promptResponse.queue_position}`
18349
+ `\u{1F4EC} Zone trigger queued for session ${targetSessionId.substring(0, 8)} at position ${task.queue_position}`
18290
18350
  );
18291
18351
  } else {
18292
18352
  promptResult = {
18293
- taskId: promptResponse.taskId,
18353
+ taskId: task.task_id,
18294
18354
  sessionId: targetSessionId,
18295
18355
  note: "Zone trigger prompt sent to target session"
18296
18356
  };
18297
- console.log(`\u2705 Zone trigger executed: task ${promptResponse.taskId.substring(0, 8)}`);
18357
+ console.log(`\u2705 Zone trigger executed: task ${task.task_id.substring(0, 8)}`);
18298
18358
  }
18299
18359
  } else {
18300
18360
  promptResult = {
@@ -18334,24 +18394,11 @@ function registerWorktreeTools(server, ctx) {
18334
18394
  const { getGitState, getCurrentBranch } = await import("@agor/core/git");
18335
18395
  const currentSha = await getGitState(worktree.path);
18336
18396
  const currentRef = await getCurrentBranch(worktree.path);
18337
- const { getDefaultPermissionMode } = await import("@agor/core/types");
18338
- const { mapPermissionMode } = await import("@agor/core/utils/permission-mode-mapper");
18339
- const userToolDefaults = user?.default_agentic_config?.[agenticTool];
18340
- const requestedMode = userToolDefaults?.permissionMode || getDefaultPermissionMode(agenticTool);
18341
- const permissionMode = mapPermissionMode(requestedMode, agenticTool);
18342
- const permissionConfig = {
18343
- mode: permissionMode,
18344
- allowedTools: []
18345
- };
18346
- if (agenticTool === "codex" && userToolDefaults?.codexSandboxMode && userToolDefaults?.codexApprovalPolicy) {
18347
- permissionConfig.codex = {
18348
- sandboxMode: userToolDefaults.codexSandboxMode,
18349
- approvalPolicy: userToolDefaults.codexApprovalPolicy,
18350
- networkAccess: userToolDefaults.codexNetworkAccess
18351
- };
18352
- }
18353
- const modelConfig = resolveModelConfig(userToolDefaults?.modelConfig);
18354
- const mcpServerIds = worktree.mcp_server_ids && worktree.mcp_server_ids.length > 0 ? worktree.mcp_server_ids : userToolDefaults?.mcpServerIds || [];
18397
+ const {
18398
+ permission_config: permissionConfig,
18399
+ model_config: modelConfig,
18400
+ mcp_server_ids: mcpServerIds
18401
+ } = resolveSessionDefaults2({ agenticTool, user, worktree });
18355
18402
  const sessionData = {
18356
18403
  worktree_id: worktreeId,
18357
18404
  agentic_tool: agenticTool,
@@ -18376,12 +18423,9 @@ function registerWorktreeTools(server, ctx) {
18376
18423
  if (mcpServerIds.length > 0) {
18377
18424
  for (const mcpServerId of mcpServerIds) {
18378
18425
  try {
18379
- await ctx.app.service("session-mcp-servers").create(
18380
- {
18381
- session_id: newSession.session_id,
18382
- mcp_server_id: mcpServerId
18383
- },
18384
- ctx.baseServiceParams
18426
+ await ctx.app.service("/sessions/:id/mcp-servers").create(
18427
+ { mcpServerId },
18428
+ { ...ctx.baseServiceParams, route: { id: newSession.session_id } }
18385
18429
  );
18386
18430
  } catch (error48) {
18387
18431
  console.warn(
@@ -18391,16 +18435,16 @@ function registerWorktreeTools(server, ctx) {
18391
18435
  }
18392
18436
  console.log(`\u2705 Attached ${mcpServerIds.length} MCP servers`);
18393
18437
  }
18394
- const promptResponse = await ctx.app.service("/sessions/:id/prompt").create(
18438
+ const task = await ctx.app.service("/sessions/:id/prompt").create(
18395
18439
  { prompt: renderedPrompt, stream: true },
18396
18440
  { ...ctx.baseServiceParams, route: { id: newSession.session_id } }
18397
18441
  );
18398
18442
  promptResult = {
18399
- taskId: promptResponse.taskId,
18443
+ taskId: task.task_id,
18400
18444
  sessionId: newSession.session_id,
18401
18445
  note: `always_new trigger: created session ${newSession.session_id.substring(0, 8)} (${agenticTool}) and sent prompt`
18402
18446
  };
18403
- console.log(`\u2705 Zone trigger executed: task ${promptResponse.taskId.substring(0, 8)}`);
18447
+ console.log(`\u2705 Zone trigger executed: task ${task.task_id.substring(0, 8)}`);
18404
18448
  } else {
18405
18449
  promptResult = {
18406
18450
  note: "Zone trigger template rendered to empty string (check template syntax)"
@@ -19545,16 +19589,10 @@ async function registerRoutes(ctx) {
19545
19589
  return {
19546
19590
  accessToken,
19547
19591
  refreshToken: newRefreshToken,
19548
- user: {
19549
- user_id: user.user_id,
19550
- email: user.email,
19551
- name: user.name,
19552
- emoji: user.emoji,
19553
- role: user.role
19554
- }
19592
+ user
19555
19593
  };
19556
19594
  } catch (_error) {
19557
- throw new Error("Invalid or expired refresh token");
19595
+ throw new NotAuthenticated6("Invalid or expired refresh token");
19558
19596
  }
19559
19597
  }
19560
19598
  });
@@ -19766,6 +19804,188 @@ async function registerRoutes(ctx) {
19766
19804
  throw error48;
19767
19805
  }
19768
19806
  }
19807
+ async function spawnTaskExecutor(task, options, params) {
19808
+ const session = await sessionsService.get(task.session_id, params);
19809
+ const messageStartIndex = await sessionsRepository.countMessages(task.session_id);
19810
+ const startTimestamp = (/* @__PURE__ */ new Date()).toISOString();
19811
+ const { captureGitStateViaShell: captureGitStateViaShell2 } = await Promise.resolve().then(() => (init_git_shell_capture(), git_shell_capture_exports));
19812
+ let gitStateAtStart = "unknown";
19813
+ let refAtStart = "unknown";
19814
+ if (session.worktree_id) {
19815
+ try {
19816
+ const worktree = await app.service("worktrees").get(session.worktree_id, params);
19817
+ const gitState = await captureGitStateViaShell2(worktree.path);
19818
+ gitStateAtStart = gitState.sha;
19819
+ refAtStart = gitState.ref;
19820
+ if (gitStateAtStart === "unknown") {
19821
+ console.warn(
19822
+ `[Git State] captureGitStateViaShell returned 'unknown' for worktree ${worktree.path} (ref: ${refAtStart})`
19823
+ );
19824
+ }
19825
+ } catch (error48) {
19826
+ console.warn(
19827
+ `[Git State] Failed to get git state for worktree ${session.worktree_id}:`,
19828
+ error48
19829
+ );
19830
+ }
19831
+ }
19832
+ const updatedTask = await app.service("tasks").patch(
19833
+ task.task_id,
19834
+ {
19835
+ status: TaskStatus.RUNNING,
19836
+ started_at: startTimestamp,
19837
+ queue_position: void 0,
19838
+ message_range: {
19839
+ start_index: messageStartIndex,
19840
+ end_index: messageStartIndex + 1,
19841
+ start_timestamp: startTimestamp,
19842
+ end_timestamp: startTimestamp
19843
+ },
19844
+ git_state: {
19845
+ ref_at_start: refAtStart,
19846
+ sha_at_start: gitStateAtStart
19847
+ }
19848
+ },
19849
+ params
19850
+ );
19851
+ if (config2.execution?.daemon_writes_user_message !== false) {
19852
+ try {
19853
+ const isCallback = task.metadata?.is_agor_callback === true;
19854
+ const messageMetadata = {};
19855
+ if (isCallback) {
19856
+ messageMetadata.is_agor_callback = true;
19857
+ }
19858
+ const source = task.metadata?.source ?? options.messageSource;
19859
+ if (source) {
19860
+ messageMetadata.source = source;
19861
+ }
19862
+ const userMessage = {
19863
+ message_id: generateId2(),
19864
+ session_id: task.session_id,
19865
+ // Callback messages are typed `system` so the UI shows the special
19866
+ // Agor-callback styling. Normal prompts stay `user`.
19867
+ type: isCallback ? "system" : "user",
19868
+ role: "user",
19869
+ index: messageStartIndex,
19870
+ timestamp: startTimestamp,
19871
+ content_preview: task.full_prompt.substring(0, 200),
19872
+ content: task.full_prompt,
19873
+ task_id: task.task_id,
19874
+ metadata: Object.keys(messageMetadata).length > 0 ? messageMetadata : void 0
19875
+ };
19876
+ await app.service("messages").create(userMessage, params);
19877
+ } catch (msgErr) {
19878
+ console.warn(
19879
+ `\u26A0\uFE0F [Daemon] Failed to write initial user-message row for task ${task.task_id.substring(0, 8)} (executor will retry):`,
19880
+ msgErr
19881
+ );
19882
+ }
19883
+ }
19884
+ await app.service("sessions").patch(
19885
+ task.session_id,
19886
+ {
19887
+ status: SessionStatus2.RUNNING,
19888
+ ready_for_prompt: false,
19889
+ tasks: [...session.tasks, task.task_id]
19890
+ },
19891
+ params
19892
+ );
19893
+ let promptForExecutor = task.full_prompt;
19894
+ const prompterUserId = params.user?.user_id;
19895
+ if (prompterUserId && prompterUserId !== session.created_by) {
19896
+ try {
19897
+ const prompterUserRepo = new UsersRepository2(db);
19898
+ const prompterUser = await prompterUserRepo.findById(prompterUserId);
19899
+ if (prompterUser) {
19900
+ const prompterName = sanitizeUserField(prompterUser.name || prompterUser.email);
19901
+ const prompterEmail = sanitizeUserField(prompterUser.email);
19902
+ promptForExecutor = `[Prompted by: ${prompterName} (${prompterEmail})]
19903
+
19904
+ ${task.full_prompt}`;
19905
+ }
19906
+ } catch (err) {
19907
+ console.warn(
19908
+ `[Prompt] Failed to look up prompter user ${prompterUserId.substring(0, 8)}:`,
19909
+ err
19910
+ );
19911
+ }
19912
+ }
19913
+ const useStreaming = options.stream !== false;
19914
+ const sessionId = task.session_id;
19915
+ const taskId = task.task_id;
19916
+ setImmediate(async () => {
19917
+ try {
19918
+ console.log(
19919
+ `\u{1F680} [Daemon] Routing ${session.agentic_tool} to Feathers/WebSocket executor (task ${taskId.substring(0, 8)})`
19920
+ );
19921
+ await sessionsService.executeTask(
19922
+ sessionId,
19923
+ {
19924
+ taskId,
19925
+ prompt: promptForExecutor,
19926
+ permissionMode: options.permissionMode,
19927
+ stream: useStreaming,
19928
+ messageSource: options.messageSource
19929
+ },
19930
+ params
19931
+ );
19932
+ console.log(
19933
+ `\u2705 [Daemon] Executor spawned for session ${sessionId.substring(0, 8)}, waiting for task completion`
19934
+ );
19935
+ } catch (error48) {
19936
+ const errorMessage = error48 instanceof Error ? error48.message : String(error48);
19937
+ console.error(
19938
+ `\u274C [Daemon] Executor spawn failed for session=${sessionId.substring(0, 8)} task=${taskId.substring(0, 8)} agent=${session.agentic_tool} unix_username=${session.unix_username ?? "null"}: ${errorMessage}`,
19939
+ error48
19940
+ );
19941
+ await safePatch(
19942
+ "tasks",
19943
+ taskId,
19944
+ {
19945
+ status: TaskStatus.FAILED,
19946
+ completed_at: (/* @__PURE__ */ new Date()).toISOString(),
19947
+ error_message: errorMessage
19948
+ },
19949
+ "Task",
19950
+ params
19951
+ );
19952
+ try {
19953
+ const sysIndex = await sessionsRepository.countMessages(sessionId);
19954
+ const errorContent = `\u26A0\uFE0F The agent failed to start.
19955
+
19956
+ ${errorMessage}`;
19957
+ const sysMessage = {
19958
+ message_id: generateId2(),
19959
+ session_id: sessionId,
19960
+ type: "system",
19961
+ role: "assistant",
19962
+ index: sysIndex,
19963
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
19964
+ content_preview: errorContent.substring(0, 200),
19965
+ content: errorContent,
19966
+ task_id: taskId,
19967
+ metadata: { is_meta: true }
19968
+ };
19969
+ await app.service("messages").create(sysMessage, params);
19970
+ } catch (sysErr) {
19971
+ console.warn(
19972
+ "[Daemon] Failed to write system error message after spawn failure:",
19973
+ sysErr
19974
+ );
19975
+ }
19976
+ try {
19977
+ app.service("tasks").emit("failed", {
19978
+ task_id: taskId,
19979
+ session_id: sessionId,
19980
+ error_message: errorMessage
19981
+ });
19982
+ } catch (emitErr) {
19983
+ console.warn("[Daemon] Failed to emit tasks:failed event:", emitErr);
19984
+ }
19985
+ }
19986
+ });
19987
+ return updatedTask;
19988
+ }
19769
19989
  registerAuthenticatedRoute(
19770
19990
  app,
19771
19991
  "/sessions/:id/prompt",
@@ -19810,232 +20030,61 @@ async function registerRoutes(ctx) {
19810
20030
  if (session.status === SessionStatus2.STOPPING) {
19811
20031
  throw new Error("Cannot send prompt: session is currently stopping");
19812
20032
  }
19813
- const isInternalCall = !params.provider;
19814
- if (!(data._fromQueue && isInternalCall)) {
19815
- const queueCheckRepo = new MessagesRepository(db);
19816
- const queuedItems = await queueCheckRepo.findQueued(id);
19817
- const hasQueuedItems = queuedItems.length > 0;
19818
- if (session.status !== SessionStatus2.IDLE || hasQueuedItems) {
19819
- const queuedMessage = await queueCheckRepo.createQueued(id, data.prompt, {
19820
- queued_by_user_id: params.user?.user_id
19821
- });
19822
- console.log(
19823
- `\u{1F4EC} [Prompt] Auto-queued message for session ${id.substring(0, 8)} at position ${queuedMessage.queue_position} (session status: ${session.status}, existing queue items: ${queuedItems.length})`
19824
- );
19825
- app.service("messages").emit("queued", queuedMessage);
19826
- if (session.status === SessionStatus2.IDLE) {
19827
- setImmediate(async () => {
19828
- try {
19829
- await sessionsService.triggerQueueProcessing(id, params);
19830
- } catch (error48) {
19831
- console.error(
19832
- `\u274C [Prompt] Failed to trigger queue processing after auto-queue:`,
19833
- error48
19834
- );
19835
- }
19836
- });
20033
+ const taskRepo = new TaskRepository(db);
20034
+ const queuedTasks = await taskRepo.findQueued(id);
20035
+ const shouldQueue = session.status !== SessionStatus2.IDLE || queuedTasks.length > 0;
20036
+ const createdBy = params.user?.user_id ?? "anonymous";
20037
+ if (shouldQueue) {
20038
+ const queuedTask = await taskRepo.createPending({
20039
+ session_id: id,
20040
+ full_prompt: data.prompt,
20041
+ created_by: createdBy,
20042
+ status: TaskStatus.QUEUED,
20043
+ metadata: {
20044
+ ...params.user?.user_id ? { queued_by_user_id: params.user.user_id } : {},
20045
+ ...messageSource ? { source: messageSource } : {}
19837
20046
  }
19838
- return {
19839
- success: true,
19840
- queued: true,
19841
- message: queuedMessage,
19842
- queue_position: queuedMessage.queue_position
19843
- };
20047
+ });
20048
+ console.log(
20049
+ `\u{1F4EC} [Prompt] Auto-queued task for session ${id.substring(0, 8)} at position ${queuedTask.queue_position} (session status: ${session.status}, existing queue items: ${queuedTasks.length})`
20050
+ );
20051
+ app.service("tasks").emit("queued", queuedTask);
20052
+ if (session.status === SessionStatus2.IDLE) {
20053
+ setImmediate(async () => {
20054
+ try {
20055
+ await sessionsService.triggerQueueProcessing(id, params);
20056
+ } catch (error48) {
20057
+ console.error(
20058
+ `\u274C [Prompt] Failed to trigger queue processing after auto-queue:`,
20059
+ error48
20060
+ );
20061
+ }
20062
+ });
19844
20063
  }
20064
+ return queuedTask;
19845
20065
  }
19846
20066
  console.log(` Session agent: ${session.agentic_tool}`);
19847
20067
  console.log(
19848
20068
  ` Session permission_config.mode: ${session.permission_config?.mode || "not set"}`
19849
20069
  );
19850
- const messageStartIndex = await sessionsRepository.countMessages(id);
19851
- const startTimestamp = (/* @__PURE__ */ new Date()).toISOString();
19852
- const { captureGitStateViaShell: captureGitStateViaShell2 } = await Promise.resolve().then(() => (init_git_shell_capture(), git_shell_capture_exports));
19853
- let gitStateAtStart = "unknown";
19854
- let refAtStart = "unknown";
19855
- if (session.worktree_id) {
19856
- try {
19857
- const worktreesService2 = app.service("worktrees");
19858
- const worktree = await worktreesService2.get(session.worktree_id, params);
19859
- console.log(
19860
- `[Git State] Capturing git state at task start for worktree ${worktree.path}`
19861
- );
19862
- const gitState = await captureGitStateViaShell2(worktree.path);
19863
- gitStateAtStart = gitState.sha;
19864
- refAtStart = gitState.ref;
19865
- if (gitStateAtStart === "unknown") {
19866
- console.warn(
19867
- `[Git State] captureGitStateViaShell returned 'unknown' for worktree ${worktree.path} (ref: ${refAtStart})`
19868
- );
19869
- }
19870
- } catch (error48) {
19871
- console.warn(
19872
- `[Git State] Failed to get git state for worktree ${session.worktree_id}:`,
19873
- error48
19874
- );
19875
- }
19876
- }
19877
- const task = await tasksService.create(
19878
- {
19879
- session_id: id,
19880
- status: TaskStatus.RUNNING,
19881
- started_at: (/* @__PURE__ */ new Date()).toISOString(),
19882
- description: data.prompt.substring(0, 120),
19883
- full_prompt: data.prompt,
19884
- message_range: {
19885
- start_index: messageStartIndex,
19886
- end_index: messageStartIndex + 1,
19887
- start_timestamp: startTimestamp,
19888
- end_timestamp: startTimestamp
19889
- },
19890
- tool_use_count: 0,
19891
- git_state: {
19892
- ref_at_start: refAtStart,
19893
- sha_at_start: gitStateAtStart
19894
- }
19895
- },
19896
- params
19897
- );
19898
- await app.service("sessions").patch(
19899
- id,
20070
+ const task = await taskRepo.createPending({
20071
+ session_id: id,
20072
+ full_prompt: data.prompt,
20073
+ created_by: createdBy,
20074
+ status: TaskStatus.CREATED,
20075
+ metadata: messageSource ? { source: messageSource } : void 0
20076
+ });
20077
+ app.service("tasks").emit("created", task);
20078
+ const runningTask = await spawnTaskExecutor(
20079
+ task,
19900
20080
  {
19901
- tasks: [...session.tasks, task.task_id]
20081
+ permissionMode: data.permissionMode,
20082
+ stream: data.stream !== false,
20083
+ messageSource
19902
20084
  },
19903
20085
  params
19904
20086
  );
19905
- const _streamingCallbacks = {
19906
- onStreamStart: (messageId, metadata) => {
19907
- console.debug(
19908
- `\u{1F4E1} [${(/* @__PURE__ */ new Date()).toISOString()}] Streaming start: ${messageId.substring(0, 8)}`
19909
- );
19910
- app.service("messages").emit("streaming:start", {
19911
- message_id: messageId,
19912
- ...metadata
19913
- });
19914
- },
19915
- onStreamChunk: (messageId, chunk) => {
19916
- app.service("messages").emit("streaming:chunk", {
19917
- message_id: messageId,
19918
- session_id: id,
19919
- chunk
19920
- });
19921
- },
19922
- onStreamEnd: (messageId) => {
19923
- console.debug(
19924
- `\u{1F4E1} [${(/* @__PURE__ */ new Date()).toISOString()}] Streaming end: ${messageId.substring(0, 8)}`
19925
- );
19926
- app.service("messages").emit("streaming:end", {
19927
- message_id: messageId,
19928
- session_id: id
19929
- });
19930
- },
19931
- onStreamError: (messageId, error48) => {
19932
- console.error(`\u274C Streaming error for message ${messageId.substring(0, 8)}:`, error48);
19933
- app.service("messages").emit("streaming:error", {
19934
- message_id: messageId,
19935
- session_id: id,
19936
- error: error48.message
19937
- });
19938
- },
19939
- onThinkingStart: (messageId, metadata) => {
19940
- console.debug(
19941
- `\u{1F4E1} [${(/* @__PURE__ */ new Date()).toISOString()}] Thinking start: ${messageId.substring(0, 8)}`
19942
- );
19943
- app.service("messages").emit("thinking:start", {
19944
- message_id: messageId,
19945
- ...metadata
19946
- });
19947
- },
19948
- onThinkingChunk: (messageId, chunk) => {
19949
- app.service("messages").emit("thinking:chunk", {
19950
- message_id: messageId,
19951
- session_id: id,
19952
- chunk
19953
- });
19954
- },
19955
- onThinkingEnd: (messageId) => {
19956
- console.debug(
19957
- `\u{1F4E1} [${(/* @__PURE__ */ new Date()).toISOString()}] Thinking end: ${messageId.substring(0, 8)}`
19958
- );
19959
- app.service("messages").emit("thinking:end", {
19960
- message_id: messageId,
19961
- session_id: id
19962
- });
19963
- }
19964
- };
19965
- const useStreaming = data.stream !== false;
19966
- let promptForExecutor = data.prompt;
19967
- const prompterUserId = params.user?.user_id;
19968
- if (prompterUserId && prompterUserId !== session.created_by) {
19969
- try {
19970
- const prompterUserRepo = new UsersRepository2(db);
19971
- const prompterUser = await prompterUserRepo.findById(prompterUserId);
19972
- if (prompterUser) {
19973
- const prompterName = sanitizeUserField(prompterUser.name || prompterUser.email);
19974
- const prompterEmail = sanitizeUserField(prompterUser.email);
19975
- promptForExecutor = `[Prompted by: ${prompterName} (${prompterEmail})]
19976
-
19977
- ${data.prompt}`;
19978
- }
19979
- } catch (err) {
19980
- console.warn(
19981
- `[Prompt] Failed to look up prompter user ${prompterUserId.substring(0, 8)}:`,
19982
- err
19983
- );
19984
- }
19985
- }
19986
- setImmediate(async () => {
19987
- try {
19988
- console.log(
19989
- `\u{1F680} [Daemon] Routing ${session.agentic_tool} to Feathers/WebSocket executor`
19990
- );
19991
- await sessionsService.executeTask(
19992
- id,
19993
- {
19994
- taskId: task.task_id,
19995
- prompt: promptForExecutor,
19996
- permissionMode: data.permissionMode,
19997
- stream: useStreaming,
19998
- messageSource
19999
- },
20000
- params
20001
- );
20002
- console.log(
20003
- `\u2705 [Daemon] Executor spawned for session ${id.substring(0, 8)}, waiting for task completion`
20004
- );
20005
- } catch (error48) {
20006
- const errorMessage = error48 instanceof Error ? error48.message : String(error48);
20007
- console.error(
20008
- `\u274C [Daemon] Executor spawn failed for session=${id.substring(0, 8)} task=${task.task_id.substring(0, 8)} agent=${session.agentic_tool} unix_username=${session.unix_username ?? "null"}: ${errorMessage}`,
20009
- error48
20010
- );
20011
- await safePatch(
20012
- "tasks",
20013
- task.task_id,
20014
- {
20015
- status: TaskStatus.FAILED,
20016
- completed_at: (/* @__PURE__ */ new Date()).toISOString(),
20017
- error_message: errorMessage
20018
- },
20019
- "Task",
20020
- params
20021
- );
20022
- try {
20023
- app.service("tasks").emit("failed", {
20024
- task_id: task.task_id,
20025
- session_id: id,
20026
- error_message: errorMessage
20027
- });
20028
- } catch (emitErr) {
20029
- console.warn("[Daemon] Failed to emit tasks:failed event:", emitErr);
20030
- }
20031
- }
20032
- });
20033
- return {
20034
- success: true,
20035
- taskId: task.task_id,
20036
- status: TaskStatus.RUNNING,
20037
- streaming: useStreaming
20038
- };
20087
+ return runningTask;
20039
20088
  }
20040
20089
  },
20041
20090
  {
@@ -20286,7 +20335,7 @@ ${data.prompt}`;
20286
20335
  id,
20287
20336
  {
20288
20337
  status: SessionStatus2.IDLE,
20289
- ready_for_prompt: false
20338
+ ready_for_prompt: true
20290
20339
  },
20291
20340
  params
20292
20341
  );
@@ -20324,7 +20373,7 @@ ${data.prompt}`;
20324
20373
  id,
20325
20374
  {
20326
20375
  status: SessionStatus2.IDLE,
20327
- ready_for_prompt: false
20376
+ ready_for_prompt: true
20328
20377
  },
20329
20378
  params
20330
20379
  );
@@ -20341,31 +20390,13 @@ ${data.prompt}`;
20341
20390
  );
20342
20391
  registerAuthenticatedRoute(
20343
20392
  app,
20344
- "/sessions/:id/messages/queue",
20393
+ "/sessions/:id/tasks/queue",
20345
20394
  {
20346
- async create(data, params) {
20347
- const sessionId = params.route?.id;
20348
- if (!sessionId) throw new Error("Session ID required");
20349
- if (!data.prompt) throw new Error("Prompt required");
20350
- const _session = await sessionsService.get(sessionId, params);
20351
- const messageRepo = new MessagesRepository(db);
20352
- const queuedMessage = await messageRepo.createQueued(sessionId, data.prompt, {
20353
- queued_by_user_id: params.user?.user_id
20354
- });
20355
- console.log(
20356
- `\u{1F4EC} Queued message for session ${sessionId.substring(0, 8)} at position ${queuedMessage.queue_position}`
20357
- );
20358
- app.service("messages").emit("queued", queuedMessage);
20359
- return {
20360
- success: true,
20361
- message: queuedMessage
20362
- };
20363
- },
20364
20395
  async find(params) {
20365
20396
  const sessionId = params.route?.id;
20366
20397
  if (!sessionId) throw new Error("Session ID required");
20367
- const messageRepo = new MessagesRepository(db);
20368
- const queued = await messageRepo.findQueued(sessionId);
20398
+ const taskQueueRepo = new TaskRepository(db);
20399
+ const queued = await taskQueueRepo.findQueued(sessionId);
20369
20400
  return {
20370
20401
  total: queued.length,
20371
20402
  data: queued
@@ -20374,14 +20405,13 @@ ${data.prompt}`;
20374
20405
  // biome-ignore lint/suspicious/noExplicitAny: Service type not compatible with Express
20375
20406
  },
20376
20407
  {
20377
- create: { role: ROLES5.MEMBER, action: "queue messages" },
20378
20408
  find: { role: ROLES5.MEMBER, action: "view queue" }
20379
20409
  },
20380
20410
  requireAuth
20381
20411
  );
20382
20412
  const queueProcessingLocks = /* @__PURE__ */ new Map();
20383
20413
  const queueRetryScheduled = /* @__PURE__ */ new Set();
20384
- async function processNextQueuedMessage(sessionId, params) {
20414
+ async function processNextQueuedTask(sessionId, params) {
20385
20415
  const existingLock = queueProcessingLocks.get(sessionId);
20386
20416
  if (existingLock) {
20387
20417
  console.log(
@@ -20393,7 +20423,7 @@ ${data.prompt}`;
20393
20423
  setImmediate(async () => {
20394
20424
  queueRetryScheduled.delete(sessionId);
20395
20425
  try {
20396
- await processNextQueuedMessage(sessionId, params);
20426
+ await processNextQueuedTask(sessionId, params);
20397
20427
  } catch (error48) {
20398
20428
  console.error(
20399
20429
  `\u274C [Queue] Retry failed for session ${sessionId.substring(0, 8)}:`,
@@ -20404,7 +20434,7 @@ ${data.prompt}`;
20404
20434
  }
20405
20435
  return;
20406
20436
  }
20407
- const processingPromise = processNextQueuedMessageInternal(sessionId, params);
20437
+ const processingPromise = processNextQueuedTaskInternal(sessionId, params);
20408
20438
  queueProcessingLocks.set(
20409
20439
  sessionId,
20410
20440
  processingPromise.catch(() => {
@@ -20416,69 +20446,51 @@ ${data.prompt}`;
20416
20446
  queueProcessingLocks.delete(sessionId);
20417
20447
  }
20418
20448
  }
20419
- async function processNextQueuedMessageInternal(sessionId, params) {
20420
- const messageRepo = new MessagesRepository(db);
20421
- const nextMessage = await messageRepo.getNextQueued(sessionId);
20422
- if (!nextMessage) {
20423
- console.log(`\u{1F4ED} No queued messages for session ${sessionId.substring(0, 8)}`);
20449
+ async function processNextQueuedTaskInternal(sessionId, params) {
20450
+ const taskRepo = new TaskRepository(db);
20451
+ const nextTask = await taskRepo.getNextQueued(sessionId);
20452
+ if (!nextTask) {
20453
+ console.log(`\u{1F4ED} No queued tasks for session ${sessionId.substring(0, 8)}`);
20424
20454
  return;
20425
20455
  }
20426
- const userId = nextMessage.metadata?.queued_by_user_id;
20456
+ const userId = nextTask.metadata?.queued_by_user_id;
20427
20457
  const userRepo = new UsersRepository2(db);
20428
20458
  const queuedByUser = userId ? await userRepo.findById(userId) : void 0;
20429
- const messageParams = queuedByUser ? {
20459
+ const taskParams = queuedByUser ? {
20430
20460
  ...params,
20431
20461
  user: queuedByUser
20432
20462
  } : params;
20433
20463
  console.log(
20434
- `\u{1F4EC} Processing queued message ${nextMessage.message_id.substring(0, 8)} with user context: ${queuedByUser ? queuedByUser.user_id.substring(0, 8) : "none"}`
20464
+ `\u{1F4EC} Processing queued task ${nextTask.task_id.substring(0, 8)} (position ${nextTask.queue_position}) with user context: ${queuedByUser ? queuedByUser.user_id.substring(0, 8) : "none"}`
20435
20465
  );
20436
- const session = await sessionsService.get(sessionId, messageParams);
20466
+ const session = await sessionsService.get(sessionId, taskParams);
20437
20467
  if (session.status !== SessionStatus2.IDLE) {
20438
20468
  console.log(
20439
- `\u23F8\uFE0F [Queue] Session ${sessionId.substring(0, 8)} is ${session.status}, message ${nextMessage.message_id.substring(0, 8)} waiting in queue (will be processed when session becomes IDLE via patch hook)`
20469
+ `\u23F8\uFE0F [Queue] Session ${sessionId.substring(0, 8)} is ${session.status}, task ${nextTask.task_id.substring(0, 8)} waiting in queue (will be processed when session becomes IDLE via patch hook)`
20440
20470
  );
20441
20471
  return;
20442
20472
  }
20443
- console.log(
20444
- `\u{1F4EC} Processing queued message ${nextMessage.message_id.substring(0, 8)} (position ${nextMessage.queue_position})`
20445
- );
20446
- const prompt = nextMessage.content;
20447
- const messagesServiceInst = app.service("messages");
20448
- try {
20449
- const stillExists = await messagesServiceInst.get(nextMessage.message_id, messageParams);
20450
- if (!stillExists || stillExists.status !== "queued") {
20451
- console.log(
20452
- `\u26A0\uFE0F Queued message ${nextMessage.message_id.substring(0, 8)} was deleted or modified, skipping`
20453
- );
20454
- return;
20455
- }
20456
- } catch (_error) {
20457
- console.log(
20458
- `\u26A0\uFE0F Queued message ${nextMessage.message_id.substring(0, 8)} no longer exists, skipping`
20459
- );
20473
+ const stillQueued = await taskRepo.findById(nextTask.task_id);
20474
+ if (!stillQueued || stillQueued.status !== TaskStatus.QUEUED) {
20475
+ console.log(`\u26A0\uFE0F Queued task ${nextTask.task_id.substring(0, 8)} no longer queued, skipping`);
20460
20476
  return;
20461
20477
  }
20462
- await messagesServiceInst.remove(nextMessage.message_id, messageParams);
20463
- const promptService = app.service("/sessions/:id/prompt");
20464
- await promptService.create(
20478
+ const source = nextTask.metadata?.source;
20479
+ await spawnTaskExecutor(
20480
+ stillQueued,
20465
20481
  {
20466
- prompt,
20467
20482
  stream: true,
20468
- _fromQueue: true
20483
+ messageSource: source
20469
20484
  },
20470
- {
20471
- ...messageParams,
20472
- route: { id: sessionId }
20473
- }
20485
+ taskParams
20474
20486
  );
20475
- console.log(`\u2705 Queued message triggered for session ${sessionId.substring(0, 8)}`);
20487
+ console.log(`\u2705 Queued task drained for session ${sessionId.substring(0, 8)}`);
20476
20488
  }
20477
20489
  sessionsService.setQueueProcessor(async (sessionId, params) => {
20478
20490
  try {
20479
- await processNextQueuedMessage(sessionId, params || {});
20491
+ await processNextQueuedTask(sessionId, params || {});
20480
20492
  } catch (error48) {
20481
- console.error(`\u274C [Sessions] Failed to process queued message:`, error48);
20493
+ console.error(`\u274C [Sessions] Failed to process queued task:`, error48);
20482
20494
  }
20483
20495
  });
20484
20496
  registerAuthenticatedRoute(