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
@@ -523,6 +523,8 @@ var init_task = __esm({
523
523
  "use strict";
524
524
  init_esm_shims();
525
525
  TaskStatus = {
526
+ QUEUED: "queued",
527
+ // Task created but not yet running (waiting for executor to drain queue)
526
528
  CREATED: "created",
527
529
  RUNNING: "running",
528
530
  STOPPING: "stopping",
@@ -553,6 +555,21 @@ function normalizeRole(role) {
553
555
  if (role === "owner") return ROLES.SUPERADMIN;
554
556
  return role || ROLES.MEMBER;
555
557
  }
558
+ function toAgenticToolsStatus(stored) {
559
+ if (!stored) return void 0;
560
+ const out = {};
561
+ for (const [tool, fields] of Object.entries(stored)) {
562
+ if (!fields) continue;
563
+ const flags = {};
564
+ for (const [field, value] of Object.entries(fields)) {
565
+ if (value) flags[field] = true;
566
+ }
567
+ if (Object.keys(flags).length > 0) {
568
+ out[tool] = flags;
569
+ }
570
+ }
571
+ return Object.keys(out).length > 0 ? out : void 0;
572
+ }
556
573
  var ROLES, ROLE_RANK;
557
574
  var init_user = __esm({
558
575
  "src/types/user.ts"() {
@@ -759,6 +776,7 @@ var init_schema_postgres = __esm({
759
776
  completed_at: t.timestamp("completed_at"),
760
777
  status: text("status", {
761
778
  enum: [
779
+ "queued",
762
780
  "created",
763
781
  "running",
764
782
  "stopping",
@@ -770,6 +788,8 @@ var init_schema_postgres = __esm({
770
788
  "stopped"
771
789
  ]
772
790
  }).notNull(),
791
+ // Queue position (lower drains first); only populated for status='queued'
792
+ queue_position: integer("queue_position"),
773
793
  // User attribution
774
794
  created_by: varchar("created_by", { length: 36 }).notNull().default("anonymous"),
775
795
  // MD5 of SDK session file at task completion (only populated when stateless_fs_mode is enabled)
@@ -779,7 +799,12 @@ var init_schema_postgres = __esm({
779
799
  (table) => ({
780
800
  sessionIdx: index("tasks_session_idx").on(table.session_id),
781
801
  statusIdx: index("tasks_status_idx").on(table.status),
782
- createdIdx: index("tasks_created_idx").on(table.created_at)
802
+ createdIdx: index("tasks_created_idx").on(table.created_at),
803
+ queueIdx: index("tasks_queue_idx").on(table.session_id, table.status, table.queue_position),
804
+ // Partial unique index — defense-in-depth for `tasks.createPending` race
805
+ // serialization. Only QUEUED rows are constrained; CREATED/RUNNING/done
806
+ // rows have NULL queue_position and are unaffected.
807
+ queuedPositionUnique: uniqueIndex("tasks_queued_position_unique").on(table.session_id, table.queue_position).where(sql`${table.status} = 'queued'`)
783
808
  })
784
809
  );
785
810
  serializedSessions = pgTable(
@@ -839,11 +864,9 @@ var init_schema_postgres = __esm({
839
864
  // First 200 chars for list views
840
865
  // Parent tool use ID (for nested tool calls - e.g., Task tool spawning Read/Grep)
841
866
  parent_tool_use_id: text("parent_tool_use_id"),
842
- // Message queueing fields
843
- status: text("status", { enum: ["queued"] }),
844
- // 'queued' or null (normal message)
845
- queue_position: integer("queue_position"),
846
- // Position in queue (1, 2, 3, ...)
867
+ // NOTE: queueing moved off `messages` and onto `tasks.status='queued'` as
868
+ // of migration sqlite/0040 (postgres/0030). The legacy `status` and
869
+ // `queue_position` columns are gone — see `tasks.queue_position` instead.
847
870
  // Full data (JSON blob)
848
871
  data: t.json("data").$type().notNull()
849
872
  },
@@ -851,8 +874,7 @@ var init_schema_postgres = __esm({
851
874
  // Indexes for efficient lookups
852
875
  sessionIdx: index("messages_session_id_idx").on(table.session_id),
853
876
  taskIdx: index("messages_task_id_idx").on(table.task_id),
854
- sessionIndexIdx: index("messages_session_index_idx").on(table.session_id, table.index),
855
- queueIdx: index("messages_queue_idx").on(table.session_id, table.status, table.queue_position)
877
+ sessionIndexIdx: index("messages_session_index_idx").on(table.session_id, table.index)
856
878
  })
857
879
  );
858
880
  boards = pgTable(
@@ -1497,6 +1519,7 @@ var init_schema_sqlite = __esm({
1497
1519
  completed_at: t2.timestamp("completed_at"),
1498
1520
  status: text2("status", {
1499
1521
  enum: [
1522
+ "queued",
1500
1523
  "created",
1501
1524
  "running",
1502
1525
  "stopping",
@@ -1508,6 +1531,8 @@ var init_schema_sqlite = __esm({
1508
1531
  "stopped"
1509
1532
  ]
1510
1533
  }).notNull(),
1534
+ // Queue position (lower drains first); only populated for status='queued'
1535
+ queue_position: integer2("queue_position"),
1511
1536
  // User attribution
1512
1537
  created_by: text2("created_by", { length: 36 }).notNull().default("anonymous"),
1513
1538
  // MD5 of SDK session file at task completion (only populated when stateless_fs_mode is enabled)
@@ -1517,7 +1542,12 @@ var init_schema_sqlite = __esm({
1517
1542
  (table) => ({
1518
1543
  sessionIdx: index2("tasks_session_idx").on(table.session_id),
1519
1544
  statusIdx: index2("tasks_status_idx").on(table.status),
1520
- createdIdx: index2("tasks_created_idx").on(table.created_at)
1545
+ createdIdx: index2("tasks_created_idx").on(table.created_at),
1546
+ queueIdx: index2("tasks_queue_idx").on(table.session_id, table.status, table.queue_position),
1547
+ // Partial unique index — defense-in-depth for `tasks.createPending` race
1548
+ // serialization. Only QUEUED rows are constrained; CREATED/RUNNING/done
1549
+ // rows have NULL queue_position and are unaffected.
1550
+ queuedPositionUnique: uniqueIndex2("tasks_queued_position_unique").on(table.session_id, table.queue_position).where(sql2`${table.status} = 'queued'`)
1521
1551
  })
1522
1552
  );
1523
1553
  serializedSessions2 = sqliteTable(
@@ -1577,11 +1607,9 @@ var init_schema_sqlite = __esm({
1577
1607
  // First 200 chars for list views
1578
1608
  // Parent tool use ID (for nested tool calls - e.g., Task tool spawning Read/Grep)
1579
1609
  parent_tool_use_id: text2("parent_tool_use_id"),
1580
- // Message queueing fields
1581
- status: text2("status", { enum: ["queued"] }),
1582
- // 'queued' or null (normal message)
1583
- queue_position: integer2("queue_position"),
1584
- // Position in queue (1, 2, 3, ...)
1610
+ // NOTE: queueing moved off `messages` and onto `tasks.status='queued'` as
1611
+ // of migration sqlite/0040 (postgres/0030). The legacy `status` and
1612
+ // `queue_position` columns are gone — see `tasks.queue_position` instead.
1585
1613
  // Full data (JSON blob)
1586
1614
  data: t2.json("data").$type().notNull()
1587
1615
  },
@@ -1589,8 +1617,7 @@ var init_schema_sqlite = __esm({
1589
1617
  // Indexes for efficient lookups
1590
1618
  sessionIdx: index2("messages_session_id_idx").on(table.session_id),
1591
1619
  taskIdx: index2("messages_task_id_idx").on(table.task_id),
1592
- sessionIndexIdx: index2("messages_session_index_idx").on(table.session_id, table.index),
1593
- queueIdx: index2("messages_queue_idx").on(table.session_id, table.status, table.queue_position)
1620
+ sessionIndexIdx: index2("messages_session_index_idx").on(table.session_id, table.index)
1594
1621
  })
1595
1622
  );
1596
1623
  boards2 = sqliteTable(
@@ -5473,8 +5500,6 @@ var MessagesRepository = class {
5473
5500
  content: row.data.content,
5474
5501
  tool_uses: row.data.tool_uses,
5475
5502
  parent_tool_use_id: row.parent_tool_use_id || void 0,
5476
- status: row.status,
5477
- queue_position: row.queue_position ?? void 0,
5478
5503
  metadata: row.data.metadata
5479
5504
  };
5480
5505
  }
@@ -5493,8 +5518,6 @@ var MessagesRepository = class {
5493
5518
  timestamp: new Date(message.timestamp),
5494
5519
  content_preview: message.content_preview,
5495
5520
  parent_tool_use_id: message.parent_tool_use_id || null,
5496
- status: message.status || null,
5497
- queue_position: message.queue_position ?? null,
5498
5521
  data: {
5499
5522
  content: message.content,
5500
5523
  tool_uses: message.tool_uses,
@@ -5593,68 +5616,6 @@ var MessagesRepository = class {
5593
5616
  async delete(messageId) {
5594
5617
  await deleteFrom(this.db, messages3).where(eq10(messages3.message_id, messageId)).run();
5595
5618
  }
5596
- /**
5597
- * Create a queued message
5598
- * NOTE: Queued messages always store prompt as string content
5599
- * This ensures compatibility with prompt execution endpoint
5600
- *
5601
- * @param sessionId - Session to queue message for
5602
- * @param prompt - Message content (string)
5603
- * @param metadata - Optional metadata (e.g., is_agor_callback, source, child_session_id)
5604
- */
5605
- async createQueued(sessionId, prompt, metadata) {
5606
- if (!prompt || typeof prompt !== "string") {
5607
- throw new Error("Prompt must be a non-empty string");
5608
- }
5609
- const { generateId: generateId2 } = await Promise.resolve().then(() => (init_ids(), ids_exports));
5610
- const result = await select(this.db).from(messages3).where(and6(eq10(messages3.session_id, sessionId), eq10(messages3.status, "queued"))).all();
5611
- const maxPosition = result.reduce(
5612
- (max, row) => Math.max(max, row.queue_position || 0),
5613
- 0
5614
- );
5615
- const nextPosition = maxPosition + 1;
5616
- const messageType = metadata?.is_agor_callback ? "system" : "user";
5617
- const message = {
5618
- message_id: generateId2(),
5619
- session_id: sessionId,
5620
- type: messageType,
5621
- role: "user",
5622
- // Always 'user' for right-side positioning
5623
- index: -1,
5624
- // Not in conversation yet
5625
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
5626
- content_preview: prompt.substring(0, 200),
5627
- content: prompt,
5628
- // Always string for queued messages
5629
- status: "queued",
5630
- queue_position: nextPosition,
5631
- task_id: void 0,
5632
- metadata
5633
- // Include metadata (is_agor_callback, source, child_session_id, etc.)
5634
- };
5635
- return this.create(message);
5636
- }
5637
- /**
5638
- * Find queued messages for a session
5639
- */
5640
- async findQueued(sessionId) {
5641
- const { asc: asc2 } = await import("drizzle-orm");
5642
- const rows = await select(this.db).from(messages3).where(and6(eq10(messages3.session_id, sessionId), eq10(messages3.status, "queued"))).orderBy(asc2(messages3.queue_position)).all();
5643
- return rows.map((r) => this.rowToMessage(r));
5644
- }
5645
- /**
5646
- * Get next queued message
5647
- */
5648
- async getNextQueued(sessionId) {
5649
- const queued = await this.findQueued(sessionId);
5650
- return queued[0] || null;
5651
- }
5652
- /**
5653
- * Delete queued message (when processing or user cancels)
5654
- */
5655
- async deleteQueued(messageId) {
5656
- await this.delete(messageId);
5657
- }
5658
5619
  };
5659
5620
 
5660
5621
  // src/db/repositories/repos.ts
@@ -6331,7 +6292,7 @@ init_esm_shims();
6331
6292
  init_types();
6332
6293
  init_config_manager();
6333
6294
  init_ids();
6334
- import { and as and9, desc as desc2, eq as eq14, inArray as inArray2, isNotNull as isNotNull2, isNull as isNull2, like as like9, or as or3, sql as sql7 } from "drizzle-orm";
6295
+ import { and as and9, desc as desc2, eq as eq14, inArray as inArray2, isNotNull as isNotNull2, like as like9, or as or3, sql as sql7 } from "drizzle-orm";
6335
6296
  init_database_wrapper();
6336
6297
  init_schema();
6337
6298
  var SessionRepository = class {
@@ -6817,14 +6778,7 @@ var SessionRepository = class {
6817
6778
  for (const sessionId of sessionIds) {
6818
6779
  const query = select(this.db, {
6819
6780
  data: messagesTable.data
6820
- }).from(messagesTable).where(
6821
- and9(
6822
- eq14(messagesTable.session_id, sessionId),
6823
- eq14(messagesTable.role, "assistant"),
6824
- isNull2(messagesTable.status)
6825
- // Exclude queued messages
6826
- )
6827
- );
6781
+ }).from(messagesTable).where(and9(eq14(messagesTable.session_id, sessionId), eq14(messagesTable.role, "assistant")));
6828
6782
  const lastMessage = await query.orderBy(desc2(messagesTable.index)).limit(1).one();
6829
6783
  if (lastMessage) {
6830
6784
  const messageData = lastMessage.data;
@@ -7112,6 +7066,7 @@ var TaskRepository = class {
7112
7066
  task_id: row.task_id,
7113
7067
  session_id: row.session_id,
7114
7068
  status: row.status,
7069
+ queue_position: row.queue_position ?? void 0,
7115
7070
  created_at: new Date(row.created_at).toISOString(),
7116
7071
  completed_at: row.completed_at ? new Date(row.completed_at).toISOString() : void 0,
7117
7072
  created_by: row.created_by,
@@ -7139,11 +7094,11 @@ var TaskRepository = class {
7139
7094
  // Always use server timestamp, ignore client-provided value
7140
7095
  completed_at: task.completed_at ? new Date(task.completed_at) : void 0,
7141
7096
  status: task.status ?? TaskStatus.CREATED,
7097
+ queue_position: task.queue_position ?? null,
7142
7098
  created_by: task.created_by ?? "anonymous",
7143
7099
  session_md5: task.session_md5 ?? null,
7144
7100
  data: {
7145
- description: task.description ?? "",
7146
- full_prompt: task.full_prompt ?? task.description ?? "",
7101
+ full_prompt: task.full_prompt ?? "",
7147
7102
  message_range: task.message_range ?? {
7148
7103
  start_index: 0,
7149
7104
  end_index: 0,
@@ -7165,8 +7120,10 @@ var TaskRepository = class {
7165
7120
  computed_context_window: task.computed_context_window,
7166
7121
  // Cumulative context window (computed by tool.computeContextWindow())
7167
7122
  report: task.report,
7168
- permission_request: task.permission_request
7123
+ permission_request: task.permission_request,
7169
7124
  // Permission state for UI approval flow
7125
+ metadata: task.metadata
7126
+ // Generic metadata bag (e.g., is_agor_callback, source)
7170
7127
  }
7171
7128
  };
7172
7129
  }
@@ -7293,7 +7250,12 @@ var TaskRepository = class {
7293
7250
  }
7294
7251
  /**
7295
7252
  * Find orphaned tasks (running, stopping, awaiting permission, or awaiting input)
7296
- * These are tasks that were interrupted when daemon stopped
7253
+ * These are tasks that were interrupted when daemon stopped.
7254
+ *
7255
+ * NOTE: QUEUED tasks are intentionally NOT considered orphans — they were
7256
+ * never spawned, so they have no executor to recover. The startup queue
7257
+ * drainer (see register-routes.ts processNextQueuedTask) picks them up
7258
+ * once any session goes idle. See never-lose-prompt §C.
7297
7259
  */
7298
7260
  async findOrphaned() {
7299
7261
  try {
@@ -7345,6 +7307,7 @@ var TaskRepository = class {
7345
7307
  const insertData = this.taskToInsert(merged);
7346
7308
  await update(txAsDb(tx), tasks3).set({
7347
7309
  status: insertData.status,
7310
+ queue_position: insertData.queue_position,
7348
7311
  completed_at: insertData.completed_at,
7349
7312
  session_md5: insertData.session_md5,
7350
7313
  data: insertData.data
@@ -7379,6 +7342,92 @@ var TaskRepository = class {
7379
7342
  );
7380
7343
  }
7381
7344
  }
7345
+ /**
7346
+ * Create a pending task — either CREATED (will spawn immediately) or
7347
+ * QUEUED (will drain later) — owning the sentinel defaults that the
7348
+ * caller would otherwise have to assemble by hand.
7349
+ *
7350
+ * For QUEUED tasks, `queue_position = max(queue_position) + 1` is computed
7351
+ * inside a transaction so concurrent writers don't both observe the same
7352
+ * max and collide. (The schema also carries a partial unique index on
7353
+ * `(session_id, queue_position) WHERE status='queued'` as a belt-and-
7354
+ * suspenders against transaction-isolation surprises.)
7355
+ *
7356
+ * Sentinel contract: while a task carries `message_range.start_index = -1`
7357
+ * and `git_state.sha_at_start = ''`, it has not yet been pinned to real
7358
+ * conversation/git state. spawnTaskExecutor is the sole place that
7359
+ * overwrites these on the way to RUNNING.
7360
+ */
7361
+ async createPending(input) {
7362
+ const taskBase = {
7363
+ session_id: input.session_id,
7364
+ full_prompt: input.full_prompt,
7365
+ created_by: input.created_by,
7366
+ status: input.status,
7367
+ metadata: input.metadata,
7368
+ // Sentinels — overwritten by spawnTaskExecutor at the status → RUNNING
7369
+ // transition. While `start_index === -1` / `sha_at_start === ''`, the
7370
+ // task is intentionally unpinned.
7371
+ message_range: {
7372
+ start_index: -1,
7373
+ end_index: -1,
7374
+ start_timestamp: (/* @__PURE__ */ new Date()).toISOString()
7375
+ },
7376
+ git_state: {
7377
+ ref_at_start: "",
7378
+ sha_at_start: ""
7379
+ },
7380
+ tool_use_count: 0
7381
+ };
7382
+ if (input.status === TaskStatus.CREATED) {
7383
+ return this.create(taskBase);
7384
+ }
7385
+ return this.db.transaction(async (tx) => {
7386
+ const positionRow = await select(txAsDb(tx), {
7387
+ maxPos: sql8`max(${tasks3.queue_position})`
7388
+ }).from(tasks3).where(sql8`${tasks3.session_id} = ${input.session_id} AND ${tasks3.status} = 'queued'`).one();
7389
+ const nextPosition = (positionRow?.maxPos ?? 0) + 1;
7390
+ const insertData = this.taskToInsert({
7391
+ ...taskBase,
7392
+ queue_position: nextPosition
7393
+ });
7394
+ await insert(txAsDb(tx), tasks3).values(insertData).run();
7395
+ const row = await select(txAsDb(tx)).from(tasks3).where(eq16(tasks3.task_id, insertData.task_id)).one();
7396
+ if (!row) {
7397
+ throw new RepositoryError("Failed to retrieve created queued task");
7398
+ }
7399
+ return this.rowToTask(row);
7400
+ });
7401
+ }
7402
+ /**
7403
+ * Find all QUEUED tasks for a session, ordered by queue_position ascending.
7404
+ */
7405
+ async findQueued(sessionId) {
7406
+ try {
7407
+ const rows = await select(this.db).from(tasks3).where(sql8`${tasks3.session_id} = ${sessionId} AND ${tasks3.status} = 'queued'`).orderBy(tasks3.queue_position).all();
7408
+ return rows.map((row) => this.rowToTask(row));
7409
+ } catch (error) {
7410
+ throw new RepositoryError(
7411
+ `Failed to find queued tasks: ${error instanceof Error ? error.message : String(error)}`,
7412
+ error
7413
+ );
7414
+ }
7415
+ }
7416
+ /**
7417
+ * Return the next QUEUED task to drain (lowest queue_position) for a session,
7418
+ * or null if none.
7419
+ */
7420
+ async getNextQueued(sessionId) {
7421
+ try {
7422
+ const row = await select(this.db).from(tasks3).where(sql8`${tasks3.session_id} = ${sessionId} AND ${tasks3.status} = 'queued'`).orderBy(tasks3.queue_position).limit(1).one();
7423
+ return row ? this.rowToTask(row) : null;
7424
+ } catch (error) {
7425
+ throw new RepositoryError(
7426
+ `Failed to get next queued task: ${error instanceof Error ? error.message : String(error)}`,
7427
+ error
7428
+ );
7429
+ }
7430
+ }
7382
7431
  /**
7383
7432
  * Count tasks for a session
7384
7433
  */
@@ -7779,7 +7828,7 @@ var UserApiKeysRepository = class {
7779
7828
  init_esm_shims();
7780
7829
  init_database_wrapper();
7781
7830
  init_schema();
7782
- import { and as and13, eq as eq19, isNull as isNull3 } from "drizzle-orm";
7831
+ import { and as and13, eq as eq19, isNull as isNull2 } from "drizzle-orm";
7783
7832
  function rowToToken(row) {
7784
7833
  return {
7785
7834
  user_id: row.user_id ?? null,
@@ -7795,7 +7844,7 @@ function rowToToken(row) {
7795
7844
  }
7796
7845
  function matchKey(userId, serverId) {
7797
7846
  return and13(
7798
- userId === null ? isNull3(userMcpOauthTokens3.user_id) : eq19(userMcpOauthTokens3.user_id, userId),
7847
+ userId === null ? isNull2(userMcpOauthTokens3.user_id) : eq19(userMcpOauthTokens3.user_id, userId),
7799
7848
  eq19(userMcpOauthTokens3.mcp_server_id, serverId)
7800
7849
  );
7801
7850
  }
@@ -7947,6 +7996,7 @@ var UserMCPOAuthTokenRepository = class {
7947
7996
 
7948
7997
  // src/db/repositories/users.ts
7949
7998
  init_esm_shims();
7999
+ init_types();
7950
8000
  import { eq as eq20, like as like12 } from "drizzle-orm";
7951
8001
 
7952
8002
  // src/config/env-vars.ts
@@ -7986,8 +8036,9 @@ var UsersRepository = class {
7986
8036
  this.db = db;
7987
8037
  }
7988
8038
  /**
7989
- * Convert database row to User type
7990
- * Note: Converts encrypted API keys (strings) to boolean flags for API exposure
8039
+ * Convert database row to User type.
8040
+ * Converts the encrypted `agentic_tools` blob to a boolean presence DTO so
8041
+ * decrypted credentials never leave this repository.
7991
8042
  */
7992
8043
  rowToUser(row) {
7993
8044
  return {
@@ -8003,13 +8054,8 @@ var UsersRepository = class {
8003
8054
  must_change_password: row.must_change_password,
8004
8055
  avatar: row.data.avatar,
8005
8056
  preferences: row.data.preferences,
8006
- // Convert encrypted keys to boolean flags (true = key exists, false/undefined = no key)
8007
- api_keys: row.data.api_keys ? {
8008
- ANTHROPIC_API_KEY: !!row.data.api_keys.ANTHROPIC_API_KEY,
8009
- OPENAI_API_KEY: !!row.data.api_keys.OPENAI_API_KEY,
8010
- GEMINI_API_KEY: !!row.data.api_keys.GEMINI_API_KEY,
8011
- COPILOT_GITHUB_TOKEN: !!row.data.api_keys.COPILOT_GITHUB_TOKEN
8012
- } : void 0,
8057
+ // Convert encrypted per-tool credential blobs into boolean presence flags.
8058
+ agentic_tools: toAgenticToolsStatus(row.data.agentic_tools),
8013
8059
  // Convert stored env vars to presence + scope metadata (never exposes secrets).
8014
8060
  // Handles both legacy string form and v0.5 object form via normalizeStoredEnvMap.
8015
8061
  // The schema stores `scope` as a generic string (no SQL CHECK constraint); the
@@ -8053,10 +8099,17 @@ var UsersRepository = class {
8053
8099
  data: {
8054
8100
  avatar: user.avatar,
8055
8101
  preferences: user.preferences,
8056
- // Use raw API keys if provided (for internal operations like setApiKey)
8057
- api_keys: user.api_keys_raw,
8058
- env_vars: void 0,
8059
- // Not implemented yet
8102
+ // Encrypted per-tool credentials. Only forwarded when caller passes the
8103
+ // raw shape (internal credential mutators); regular updates leave it undefined,
8104
+ // letting the merge in `update()` reuse the existing on-disk blob.
8105
+ // Cast: schema declares `opencode: Record<string, never>` (no fields by
8106
+ // contract); StoredAgenticTools widens that to string values for shape
8107
+ // uniformity. Runtime never writes opencode, so the cast is safe.
8108
+ agentic_tools: user.agentic_tools_raw,
8109
+ // Same pass-through as agentic_tools: env_vars are encrypted blobs
8110
+ // not represented on the public DTO. `update()` threads the raw value
8111
+ // from the existing row so a generic field update doesn't wipe them.
8112
+ env_vars: user.env_vars_raw,
8060
8113
  default_agentic_config: user.default_agentic_config
8061
8114
  }
8062
8115
  };
@@ -8168,7 +8221,14 @@ var UsersRepository = class {
8168
8221
  );
8169
8222
  }
8170
8223
  }
8224
+ const rawRow = await this.getRawRow(fullId);
8171
8225
  const merged = { ...current, ...updates };
8226
+ if (rawRow?.data.agentic_tools) {
8227
+ merged.agentic_tools_raw = rawRow.data.agentic_tools;
8228
+ }
8229
+ if (rawRow?.data.env_vars) {
8230
+ merged.env_vars_raw = rawRow.data.env_vars;
8231
+ }
8172
8232
  const insertData = this.userToInsert(merged);
8173
8233
  await update(this.db, users3).set({
8174
8234
  ...insertData,
@@ -8203,96 +8263,103 @@ var UsersRepository = class {
8203
8263
  }
8204
8264
  }
8205
8265
  /**
8206
- * Get decrypted API key for a user and service
8266
+ * Get the full decrypted credential bag for a single agentic tool.
8207
8267
  *
8208
- * @param userId - User ID
8209
- * @param service - Service name ('anthropic', 'openai', 'gemini')
8210
- * @returns Decrypted API key or null if not found
8268
+ * Returns `null` when the user has no stored config for that tool.
8269
+ * Fields that fail to decrypt are dropped from the returned object and
8270
+ * logged callers see "missing field" rather than a thrown error so a
8271
+ * single corrupt value doesn't poison an entire SDK spawn.
8211
8272
  */
8212
- async getApiKey(userId, service) {
8273
+ async getToolConfig(userId, tool) {
8213
8274
  const row = await this.getRawRow(userId);
8214
- if (!row || !row.data.api_keys) {
8215
- return null;
8216
- }
8217
- const keyMap = {
8218
- anthropic: "ANTHROPIC_API_KEY",
8219
- openai: "OPENAI_API_KEY",
8220
- gemini: "GEMINI_API_KEY",
8221
- copilot: "COPILOT_GITHUB_TOKEN"
8222
- };
8223
- const encryptedKey = row.data.api_keys[keyMap[service]];
8224
- if (!encryptedKey) {
8225
- return null;
8275
+ if (!row) return null;
8276
+ const stored = row.data.agentic_tools;
8277
+ const fields = stored?.[tool];
8278
+ if (!fields || Object.keys(fields).length === 0) return null;
8279
+ const out = {};
8280
+ for (const [field, encrypted] of Object.entries(fields)) {
8281
+ if (!encrypted) continue;
8282
+ try {
8283
+ out[field] = decryptApiKey(encrypted);
8284
+ } catch (error) {
8285
+ console.error(
8286
+ `[users] Failed to decrypt ${tool}.${field} for user ${userId.substring(0, 8)}: ${error.message}`
8287
+ );
8288
+ }
8226
8289
  }
8290
+ return Object.keys(out).length > 0 ? out : null;
8291
+ }
8292
+ /**
8293
+ * Get a single decrypted credential field for a tool.
8294
+ *
8295
+ * Returns `null` when the field is unset OR when decryption fails (logged).
8296
+ * Throws only on storage-layer errors, not on missing/corrupt values.
8297
+ */
8298
+ async getToolConfigField(userId, tool, field) {
8299
+ const row = await this.getRawRow(userId);
8300
+ if (!row) return null;
8301
+ const stored = row.data.agentic_tools;
8302
+ const encrypted = stored?.[tool]?.[field];
8303
+ if (!encrypted) return null;
8227
8304
  try {
8228
- return decryptApiKey(encryptedKey);
8305
+ return decryptApiKey(encrypted);
8229
8306
  } catch (error) {
8230
- throw new RepositoryError(`Failed to decrypt API key for service ${service}`, error);
8307
+ console.error(
8308
+ `[users] Failed to decrypt ${tool}.${field} for user ${userId.substring(0, 8)}: ${error.message}`
8309
+ );
8310
+ return null;
8231
8311
  }
8232
8312
  }
8233
8313
  /**
8234
- * Set encrypted API key for a user and service
8314
+ * Set (encrypt + persist) a single credential field for a tool.
8235
8315
  *
8236
- * @param userId - User ID
8237
- * @param service - Service name ('anthropic', 'openai', 'gemini')
8238
- * @param apiKey - Plaintext API key to encrypt and store
8316
+ * Field names are env-var-shaped (e.g. ANTHROPIC_API_KEY, ANTHROPIC_BASE_URL)
8317
+ * and are stored encrypted regardless of whether the value is a secret —
8318
+ * keeping the on-disk shape uniform avoids decrypt-vs-plain branching at
8319
+ * read time. UI controls own the text-vs-password rendering distinction.
8239
8320
  */
8240
- async setApiKey(userId, service, apiKey) {
8321
+ async setToolConfigField(userId, tool, field, value) {
8241
8322
  const fullId = await this.resolveId(userId);
8242
8323
  const row = await this.getRawRow(fullId);
8243
8324
  if (!row) {
8244
8325
  throw new EntityNotFoundError("User", userId);
8245
8326
  }
8246
- const keyMap = {
8247
- anthropic: "ANTHROPIC_API_KEY",
8248
- openai: "OPENAI_API_KEY",
8249
- gemini: "GEMINI_API_KEY",
8250
- copilot: "COPILOT_GITHUB_TOKEN"
8251
- };
8252
- const encryptedKey = encryptApiKey(apiKey);
8253
- const updatedApiKeys = {
8254
- ...row.data.api_keys || {},
8255
- [keyMap[service]]: encryptedKey
8256
- };
8257
- const user = this.rowToUser(row);
8258
- const updateData = {
8259
- ...user,
8260
- api_keys_raw: updatedApiKeys
8327
+ const stored = row.data.agentic_tools ?? {};
8328
+ const next = {
8329
+ ...stored,
8330
+ [tool]: {
8331
+ ...stored[tool] ?? {},
8332
+ [field]: encryptApiKey(value)
8333
+ }
8261
8334
  };
8262
- const insertData = this.userToInsert(updateData);
8263
8335
  await update(this.db, users3).set({
8264
- ...insertData,
8336
+ data: { ...row.data, agentic_tools: next },
8265
8337
  updated_at: /* @__PURE__ */ new Date()
8266
8338
  }).where(eq20(users3.user_id, fullId)).run();
8267
8339
  }
8268
8340
  /**
8269
- * Delete API key for a user and service
8341
+ * Delete a single credential field for a tool.
8270
8342
  *
8271
- * @param userId - User ID
8272
- * @param service - Service name ('anthropic', 'openai', 'gemini')
8343
+ * If the tool's bucket becomes empty after the delete, the bucket itself is
8344
+ * removed so `data.agentic_tools` doesn't accumulate empty objects.
8273
8345
  */
8274
- async deleteApiKey(userId, service) {
8346
+ async deleteToolConfigField(userId, tool, field) {
8275
8347
  const fullId = await this.resolveId(userId);
8276
8348
  const row = await this.getRawRow(fullId);
8277
8349
  if (!row) {
8278
8350
  throw new EntityNotFoundError("User", userId);
8279
8351
  }
8280
- const keyMap = {
8281
- anthropic: "ANTHROPIC_API_KEY",
8282
- openai: "OPENAI_API_KEY",
8283
- gemini: "GEMINI_API_KEY",
8284
- copilot: "COPILOT_GITHUB_TOKEN"
8285
- };
8286
- const updatedApiKeys = { ...row.data.api_keys || {} };
8287
- delete updatedApiKeys[keyMap[service]];
8288
- const user = this.rowToUser(row);
8289
- const updateData = {
8290
- ...user,
8291
- api_keys_raw: updatedApiKeys
8292
- };
8293
- const insertData = this.userToInsert(updateData);
8352
+ const stored = row.data.agentic_tools ?? {};
8353
+ const toolFields = { ...stored[tool] ?? {} };
8354
+ delete toolFields[field];
8355
+ const next = { ...stored };
8356
+ if (Object.keys(toolFields).length > 0) {
8357
+ next[tool] = toolFields;
8358
+ } else {
8359
+ delete next[tool];
8360
+ }
8294
8361
  await update(this.db, users3).set({
8295
- ...insertData,
8362
+ data: { ...row.data, agentic_tools: next },
8296
8363
  updated_at: /* @__PURE__ */ new Date()
8297
8364
  }).where(eq20(users3.user_id, fullId)).run();
8298
8365
  }
@@ -8304,18 +8371,7 @@ init_types();
8304
8371
  init_ids();
8305
8372
  init_database_wrapper();
8306
8373
  init_schema();
8307
- import {
8308
- and as and14,
8309
- desc as desc3,
8310
- eq as eq21,
8311
- getTableColumns,
8312
- inArray as inArray3,
8313
- isNotNull as isNotNull3,
8314
- isNull as isNull4,
8315
- like as like13,
8316
- or as or4,
8317
- sql as sql9
8318
- } from "drizzle-orm";
8374
+ import { and as and14, desc as desc3, eq as eq21, getTableColumns, inArray as inArray3, isNotNull as isNotNull3, like as like13, or as or4, sql as sql9 } from "drizzle-orm";
8319
8375
  var WorktreeRepository = class {
8320
8376
  constructor(db) {
8321
8377
  this.db = db;
@@ -8843,14 +8899,7 @@ var WorktreeRepository = class {
8843
8899
  for (const sessionId of sessionIds) {
8844
8900
  const query = select(this.db, {
8845
8901
  data: messagesTable.data
8846
- }).from(messagesTable).where(
8847
- and14(
8848
- eq21(messagesTable.session_id, sessionId),
8849
- eq21(messagesTable.role, "assistant"),
8850
- isNull4(messagesTable.status)
8851
- // Exclude queued messages
8852
- )
8853
- );
8902
+ }).from(messagesTable).where(and14(eq21(messagesTable.session_id, sessionId), eq21(messagesTable.role, "assistant")));
8854
8903
  const lastMessage = await query.orderBy(desc3(messagesTable.index)).limit(1).one();
8855
8904
  if (lastMessage) {
8856
8905
  const messageData = lastMessage.data;