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
@@ -0,0 +1,74 @@
1
+ import { E as EffortLevel, a as Session } from './session-MNU4BQv4.cjs';
2
+
3
+ /**
4
+ * Model configuration normalization
5
+ *
6
+ * Single source of truth for turning a partial model-config input (from an
7
+ * MCP tool arg, a user default, a worktree setting, etc.) into the canonical
8
+ * shape persisted on `Session['model_config']`.
9
+ *
10
+ * Callers compose these helpers into a precedence chain instead of hand-rolling
11
+ * the normalization at every session-creation site (MCP create, spawn service,
12
+ * worktree auto-create, gateway session creation, ...). Centralizing here:
13
+ *
14
+ * - Guarantees every site writes the same shape (mode default, updated_at
15
+ * stamp, conditional effort/provider inclusion), avoiding drift.
16
+ * - Makes it safe to add a new optional field (e.g. a future `notes` or
17
+ * `temperature`) in exactly one place.
18
+ * - Returns `undefined` when there is no usable model, so callers can chain
19
+ * with `??` or feed a list into `resolveModelConfigPrecedence`.
20
+ */
21
+
22
+ /**
23
+ * Loose input shape accepted by the resolver.
24
+ *
25
+ * Mirrors `Session['model_config']` but every field is optional so we can
26
+ * accept partials from MCP Zod schemas, user/tool defaults, worktree
27
+ * overrides, and legacy callers — then either normalize or reject them
28
+ * based on whether `model` is set.
29
+ */
30
+ type ModelConfigInput = {
31
+ mode?: 'alias' | 'exact';
32
+ model?: string;
33
+ effort?: EffortLevel;
34
+ provider?: string;
35
+ };
36
+ /**
37
+ * Canonical persisted shape — a non-null `Session.model_config`.
38
+ */
39
+ type ResolvedModelConfig = NonNullable<Session['model_config']>;
40
+ /**
41
+ * Normalize a partial model-config into the shape persisted on
42
+ * `session.model_config`. Returns `undefined` if no usable `model` was
43
+ * provided, so callers can fall through to the next source in a precedence
44
+ * chain.
45
+ *
46
+ * Behavior:
47
+ * - `mode` defaults to `'alias'` (matches every legacy call site).
48
+ * - `updated_at` is stamped from `opts.now ?? new Date()` (injectable for
49
+ * determinism in tests).
50
+ * - `effort` and `provider` are only included when explicitly defined, so
51
+ * we never write `undefined` values onto the persisted object.
52
+ */
53
+ declare function resolveModelConfig(input: ModelConfigInput | undefined | null, opts?: {
54
+ now?: Date;
55
+ }): ResolvedModelConfig | undefined;
56
+ /**
57
+ * Walk a precedence list (highest priority first) and return the first
58
+ * source that yields a resolvable model config. Mirrors the "explicit arg >
59
+ * worktree override > user default" pattern used at session-create time.
60
+ *
61
+ * Example:
62
+ * ```ts
63
+ * const modelConfig = resolveModelConfigPrecedence([
64
+ * args.modelConfig, // explicit MCP arg
65
+ * worktree.modelConfig, // worktree override
66
+ * userToolDefaults?.modelConfig, // user default
67
+ * ]);
68
+ * ```
69
+ */
70
+ declare function resolveModelConfigPrecedence(sources: Array<ModelConfigInput | undefined | null>, opts?: {
71
+ now?: Date;
72
+ }): ResolvedModelConfig | undefined;
73
+
74
+ export { type ModelConfigInput as M, type ResolvedModelConfig as R, resolveModelConfigPrecedence as a, resolveModelConfig as r };
@@ -87,6 +87,7 @@ __export(config_manager_exports, {
87
87
  getWorktreesDir: () => getWorktreesDir,
88
88
  getWorktreesDirAsync: () => getWorktreesDirAsync,
89
89
  initConfig: () => initConfig,
90
+ isConfigCredentialKey: () => isConfigCredentialKey,
90
91
  isUnixImpersonationEnabled: () => isUnixImpersonationEnabled,
91
92
  isWorktreeRbacEnabled: () => isWorktreeRbacEnabled,
92
93
  loadConfig: () => loadConfig,
@@ -353,6 +354,9 @@ function loadConfigSync() {
353
354
  );
354
355
  }
355
356
  }
357
+ function isConfigCredentialKey(key) {
358
+ return CONFIG_CREDENTIAL_KEYS.has(key);
359
+ }
356
360
  function getCredential(key) {
357
361
  try {
358
362
  const config = loadConfigSync();
@@ -448,7 +452,7 @@ async function getReposDirAsync() {
448
452
  async function getWorktreesDirAsync() {
449
453
  return import_node_path.default.join(await getDataHomeAsync(), "worktrees");
450
454
  }
451
- var import_node_fs, import_promises, import_node_os, import_node_path, import_js_yaml, PublicBaseUrlNotConfiguredError;
455
+ var import_node_fs, import_promises, import_node_os, import_node_path, import_js_yaml, PublicBaseUrlNotConfiguredError, CONFIG_CREDENTIAL_KEYS;
452
456
  var init_config_manager = __esm({
453
457
  "src/config/config-manager.ts"() {
454
458
  "use strict";
@@ -466,6 +470,13 @@ var init_config_manager = __esm({
466
470
  this.name = "PublicBaseUrlNotConfiguredError";
467
471
  }
468
472
  };
473
+ CONFIG_CREDENTIAL_KEYS = /* @__PURE__ */ new Set([
474
+ "ANTHROPIC_API_KEY",
475
+ "ANTHROPIC_AUTH_TOKEN",
476
+ "ANTHROPIC_BASE_URL",
477
+ "OPENAI_API_KEY",
478
+ "GEMINI_API_KEY"
479
+ ]);
469
480
  }
470
481
  });
471
482
 
@@ -887,6 +898,21 @@ var init_ui = __esm({
887
898
  });
888
899
 
889
900
  // src/types/user.ts
901
+ function toAgenticToolsStatus(stored) {
902
+ if (!stored) return void 0;
903
+ const out = {};
904
+ for (const [tool, fields] of Object.entries(stored)) {
905
+ if (!fields) continue;
906
+ const flags = {};
907
+ for (const [field, value] of Object.entries(fields)) {
908
+ if (value) flags[field] = true;
909
+ }
910
+ if (Object.keys(flags).length > 0) {
911
+ out[tool] = flags;
912
+ }
913
+ }
914
+ return Object.keys(out).length > 0 ? out : void 0;
915
+ }
890
916
  var ROLES, ROLE_RANK;
891
917
  var init_user = __esm({
892
918
  "src/types/user.ts"() {
@@ -1080,6 +1106,7 @@ var init_schema_postgres = __esm({
1080
1106
  completed_at: t.timestamp("completed_at"),
1081
1107
  status: (0, import_pg_core.text)("status", {
1082
1108
  enum: [
1109
+ "queued",
1083
1110
  "created",
1084
1111
  "running",
1085
1112
  "stopping",
@@ -1091,6 +1118,8 @@ var init_schema_postgres = __esm({
1091
1118
  "stopped"
1092
1119
  ]
1093
1120
  }).notNull(),
1121
+ // Queue position (lower drains first); only populated for status='queued'
1122
+ queue_position: (0, import_pg_core.integer)("queue_position"),
1094
1123
  // User attribution
1095
1124
  created_by: (0, import_pg_core.varchar)("created_by", { length: 36 }).notNull().default("anonymous"),
1096
1125
  // MD5 of SDK session file at task completion (only populated when stateless_fs_mode is enabled)
@@ -1100,7 +1129,12 @@ var init_schema_postgres = __esm({
1100
1129
  (table) => ({
1101
1130
  sessionIdx: (0, import_pg_core.index)("tasks_session_idx").on(table.session_id),
1102
1131
  statusIdx: (0, import_pg_core.index)("tasks_status_idx").on(table.status),
1103
- createdIdx: (0, import_pg_core.index)("tasks_created_idx").on(table.created_at)
1132
+ createdIdx: (0, import_pg_core.index)("tasks_created_idx").on(table.created_at),
1133
+ queueIdx: (0, import_pg_core.index)("tasks_queue_idx").on(table.session_id, table.status, table.queue_position),
1134
+ // Partial unique index — defense-in-depth for `tasks.createPending` race
1135
+ // serialization. Only QUEUED rows are constrained; CREATED/RUNNING/done
1136
+ // rows have NULL queue_position and are unaffected.
1137
+ queuedPositionUnique: (0, import_pg_core.uniqueIndex)("tasks_queued_position_unique").on(table.session_id, table.queue_position).where(import_drizzle_orm2.sql`${table.status} = 'queued'`)
1104
1138
  })
1105
1139
  );
1106
1140
  serializedSessions = (0, import_pg_core.pgTable)(
@@ -1160,11 +1194,9 @@ var init_schema_postgres = __esm({
1160
1194
  // First 200 chars for list views
1161
1195
  // Parent tool use ID (for nested tool calls - e.g., Task tool spawning Read/Grep)
1162
1196
  parent_tool_use_id: (0, import_pg_core.text)("parent_tool_use_id"),
1163
- // Message queueing fields
1164
- status: (0, import_pg_core.text)("status", { enum: ["queued"] }),
1165
- // 'queued' or null (normal message)
1166
- queue_position: (0, import_pg_core.integer)("queue_position"),
1167
- // Position in queue (1, 2, 3, ...)
1197
+ // NOTE: queueing moved off `messages` and onto `tasks.status='queued'` as
1198
+ // of migration sqlite/0040 (postgres/0030). The legacy `status` and
1199
+ // `queue_position` columns are gone — see `tasks.queue_position` instead.
1168
1200
  // Full data (JSON blob)
1169
1201
  data: t.json("data").$type().notNull()
1170
1202
  },
@@ -1172,8 +1204,7 @@ var init_schema_postgres = __esm({
1172
1204
  // Indexes for efficient lookups
1173
1205
  sessionIdx: (0, import_pg_core.index)("messages_session_id_idx").on(table.session_id),
1174
1206
  taskIdx: (0, import_pg_core.index)("messages_task_id_idx").on(table.task_id),
1175
- sessionIndexIdx: (0, import_pg_core.index)("messages_session_index_idx").on(table.session_id, table.index),
1176
- queueIdx: (0, import_pg_core.index)("messages_queue_idx").on(table.session_id, table.status, table.queue_position)
1207
+ sessionIndexIdx: (0, import_pg_core.index)("messages_session_index_idx").on(table.session_id, table.index)
1177
1208
  })
1178
1209
  );
1179
1210
  boards = (0, import_pg_core.pgTable)(
@@ -1810,6 +1841,7 @@ var init_schema_sqlite = __esm({
1810
1841
  completed_at: t2.timestamp("completed_at"),
1811
1842
  status: (0, import_sqlite_core.text)("status", {
1812
1843
  enum: [
1844
+ "queued",
1813
1845
  "created",
1814
1846
  "running",
1815
1847
  "stopping",
@@ -1821,6 +1853,8 @@ var init_schema_sqlite = __esm({
1821
1853
  "stopped"
1822
1854
  ]
1823
1855
  }).notNull(),
1856
+ // Queue position (lower drains first); only populated for status='queued'
1857
+ queue_position: (0, import_sqlite_core.integer)("queue_position"),
1824
1858
  // User attribution
1825
1859
  created_by: (0, import_sqlite_core.text)("created_by", { length: 36 }).notNull().default("anonymous"),
1826
1860
  // MD5 of SDK session file at task completion (only populated when stateless_fs_mode is enabled)
@@ -1830,7 +1864,12 @@ var init_schema_sqlite = __esm({
1830
1864
  (table) => ({
1831
1865
  sessionIdx: (0, import_sqlite_core.index)("tasks_session_idx").on(table.session_id),
1832
1866
  statusIdx: (0, import_sqlite_core.index)("tasks_status_idx").on(table.status),
1833
- createdIdx: (0, import_sqlite_core.index)("tasks_created_idx").on(table.created_at)
1867
+ createdIdx: (0, import_sqlite_core.index)("tasks_created_idx").on(table.created_at),
1868
+ queueIdx: (0, import_sqlite_core.index)("tasks_queue_idx").on(table.session_id, table.status, table.queue_position),
1869
+ // Partial unique index — defense-in-depth for `tasks.createPending` race
1870
+ // serialization. Only QUEUED rows are constrained; CREATED/RUNNING/done
1871
+ // rows have NULL queue_position and are unaffected.
1872
+ queuedPositionUnique: (0, import_sqlite_core.uniqueIndex)("tasks_queued_position_unique").on(table.session_id, table.queue_position).where(import_drizzle_orm3.sql`${table.status} = 'queued'`)
1834
1873
  })
1835
1874
  );
1836
1875
  serializedSessions2 = (0, import_sqlite_core.sqliteTable)(
@@ -1890,11 +1929,9 @@ var init_schema_sqlite = __esm({
1890
1929
  // First 200 chars for list views
1891
1930
  // Parent tool use ID (for nested tool calls - e.g., Task tool spawning Read/Grep)
1892
1931
  parent_tool_use_id: (0, import_sqlite_core.text)("parent_tool_use_id"),
1893
- // Message queueing fields
1894
- status: (0, import_sqlite_core.text)("status", { enum: ["queued"] }),
1895
- // 'queued' or null (normal message)
1896
- queue_position: (0, import_sqlite_core.integer)("queue_position"),
1897
- // Position in queue (1, 2, 3, ...)
1932
+ // NOTE: queueing moved off `messages` and onto `tasks.status='queued'` as
1933
+ // of migration sqlite/0040 (postgres/0030). The legacy `status` and
1934
+ // `queue_position` columns are gone — see `tasks.queue_position` instead.
1898
1935
  // Full data (JSON blob)
1899
1936
  data: t2.json("data").$type().notNull()
1900
1937
  },
@@ -1902,8 +1939,7 @@ var init_schema_sqlite = __esm({
1902
1939
  // Indexes for efficient lookups
1903
1940
  sessionIdx: (0, import_sqlite_core.index)("messages_session_id_idx").on(table.session_id),
1904
1941
  taskIdx: (0, import_sqlite_core.index)("messages_task_id_idx").on(table.task_id),
1905
- sessionIndexIdx: (0, import_sqlite_core.index)("messages_session_index_idx").on(table.session_id, table.index),
1906
- queueIdx: (0, import_sqlite_core.index)("messages_queue_idx").on(table.session_id, table.status, table.queue_position)
1942
+ sessionIndexIdx: (0, import_sqlite_core.index)("messages_session_index_idx").on(table.session_id, table.index)
1907
1943
  })
1908
1944
  );
1909
1945
  boards2 = (0, import_sqlite_core.sqliteTable)(
@@ -4234,6 +4270,7 @@ init_schema();
4234
4270
 
4235
4271
  // src/db/repositories/users.ts
4236
4272
  init_cjs_shims();
4273
+ init_types();
4237
4274
  var import_drizzle_orm22 = require("drizzle-orm");
4238
4275
 
4239
4276
  // src/config/env-vars.ts
@@ -4273,8 +4310,9 @@ var UsersRepository = class {
4273
4310
  this.db = db;
4274
4311
  }
4275
4312
  /**
4276
- * Convert database row to User type
4277
- * Note: Converts encrypted API keys (strings) to boolean flags for API exposure
4313
+ * Convert database row to User type.
4314
+ * Converts the encrypted `agentic_tools` blob to a boolean presence DTO so
4315
+ * decrypted credentials never leave this repository.
4278
4316
  */
4279
4317
  rowToUser(row) {
4280
4318
  return {
@@ -4290,13 +4328,8 @@ var UsersRepository = class {
4290
4328
  must_change_password: row.must_change_password,
4291
4329
  avatar: row.data.avatar,
4292
4330
  preferences: row.data.preferences,
4293
- // Convert encrypted keys to boolean flags (true = key exists, false/undefined = no key)
4294
- api_keys: row.data.api_keys ? {
4295
- ANTHROPIC_API_KEY: !!row.data.api_keys.ANTHROPIC_API_KEY,
4296
- OPENAI_API_KEY: !!row.data.api_keys.OPENAI_API_KEY,
4297
- GEMINI_API_KEY: !!row.data.api_keys.GEMINI_API_KEY,
4298
- COPILOT_GITHUB_TOKEN: !!row.data.api_keys.COPILOT_GITHUB_TOKEN
4299
- } : void 0,
4331
+ // Convert encrypted per-tool credential blobs into boolean presence flags.
4332
+ agentic_tools: toAgenticToolsStatus(row.data.agentic_tools),
4300
4333
  // Convert stored env vars to presence + scope metadata (never exposes secrets).
4301
4334
  // Handles both legacy string form and v0.5 object form via normalizeStoredEnvMap.
4302
4335
  // The schema stores `scope` as a generic string (no SQL CHECK constraint); the
@@ -4340,10 +4373,17 @@ var UsersRepository = class {
4340
4373
  data: {
4341
4374
  avatar: user.avatar,
4342
4375
  preferences: user.preferences,
4343
- // Use raw API keys if provided (for internal operations like setApiKey)
4344
- api_keys: user.api_keys_raw,
4345
- env_vars: void 0,
4346
- // Not implemented yet
4376
+ // Encrypted per-tool credentials. Only forwarded when caller passes the
4377
+ // raw shape (internal credential mutators); regular updates leave it undefined,
4378
+ // letting the merge in `update()` reuse the existing on-disk blob.
4379
+ // Cast: schema declares `opencode: Record<string, never>` (no fields by
4380
+ // contract); StoredAgenticTools widens that to string values for shape
4381
+ // uniformity. Runtime never writes opencode, so the cast is safe.
4382
+ agentic_tools: user.agentic_tools_raw,
4383
+ // Same pass-through as agentic_tools: env_vars are encrypted blobs
4384
+ // not represented on the public DTO. `update()` threads the raw value
4385
+ // from the existing row so a generic field update doesn't wipe them.
4386
+ env_vars: user.env_vars_raw,
4347
4387
  default_agentic_config: user.default_agentic_config
4348
4388
  }
4349
4389
  };
@@ -4455,7 +4495,14 @@ var UsersRepository = class {
4455
4495
  );
4456
4496
  }
4457
4497
  }
4498
+ const rawRow = await this.getRawRow(fullId);
4458
4499
  const merged = { ...current, ...updates };
4500
+ if (rawRow?.data.agentic_tools) {
4501
+ merged.agentic_tools_raw = rawRow.data.agentic_tools;
4502
+ }
4503
+ if (rawRow?.data.env_vars) {
4504
+ merged.env_vars_raw = rawRow.data.env_vars;
4505
+ }
4459
4506
  const insertData = this.userToInsert(merged);
4460
4507
  await update(this.db, users3).set({
4461
4508
  ...insertData,
@@ -4490,96 +4537,103 @@ var UsersRepository = class {
4490
4537
  }
4491
4538
  }
4492
4539
  /**
4493
- * Get decrypted API key for a user and service
4540
+ * Get the full decrypted credential bag for a single agentic tool.
4494
4541
  *
4495
- * @param userId - User ID
4496
- * @param service - Service name ('anthropic', 'openai', 'gemini')
4497
- * @returns Decrypted API key or null if not found
4542
+ * Returns `null` when the user has no stored config for that tool.
4543
+ * Fields that fail to decrypt are dropped from the returned object and
4544
+ * logged callers see "missing field" rather than a thrown error so a
4545
+ * single corrupt value doesn't poison an entire SDK spawn.
4498
4546
  */
4499
- async getApiKey(userId, service) {
4547
+ async getToolConfig(userId, tool) {
4500
4548
  const row = await this.getRawRow(userId);
4501
- if (!row || !row.data.api_keys) {
4502
- return null;
4503
- }
4504
- const keyMap = {
4505
- anthropic: "ANTHROPIC_API_KEY",
4506
- openai: "OPENAI_API_KEY",
4507
- gemini: "GEMINI_API_KEY",
4508
- copilot: "COPILOT_GITHUB_TOKEN"
4509
- };
4510
- const encryptedKey = row.data.api_keys[keyMap[service]];
4511
- if (!encryptedKey) {
4512
- return null;
4549
+ if (!row) return null;
4550
+ const stored = row.data.agentic_tools;
4551
+ const fields = stored?.[tool];
4552
+ if (!fields || Object.keys(fields).length === 0) return null;
4553
+ const out = {};
4554
+ for (const [field, encrypted] of Object.entries(fields)) {
4555
+ if (!encrypted) continue;
4556
+ try {
4557
+ out[field] = decryptApiKey(encrypted);
4558
+ } catch (error) {
4559
+ console.error(
4560
+ `[users] Failed to decrypt ${tool}.${field} for user ${userId.substring(0, 8)}: ${error.message}`
4561
+ );
4562
+ }
4513
4563
  }
4564
+ return Object.keys(out).length > 0 ? out : null;
4565
+ }
4566
+ /**
4567
+ * Get a single decrypted credential field for a tool.
4568
+ *
4569
+ * Returns `null` when the field is unset OR when decryption fails (logged).
4570
+ * Throws only on storage-layer errors, not on missing/corrupt values.
4571
+ */
4572
+ async getToolConfigField(userId, tool, field) {
4573
+ const row = await this.getRawRow(userId);
4574
+ if (!row) return null;
4575
+ const stored = row.data.agentic_tools;
4576
+ const encrypted = stored?.[tool]?.[field];
4577
+ if (!encrypted) return null;
4514
4578
  try {
4515
- return decryptApiKey(encryptedKey);
4579
+ return decryptApiKey(encrypted);
4516
4580
  } catch (error) {
4517
- throw new RepositoryError(`Failed to decrypt API key for service ${service}`, error);
4581
+ console.error(
4582
+ `[users] Failed to decrypt ${tool}.${field} for user ${userId.substring(0, 8)}: ${error.message}`
4583
+ );
4584
+ return null;
4518
4585
  }
4519
4586
  }
4520
4587
  /**
4521
- * Set encrypted API key for a user and service
4588
+ * Set (encrypt + persist) a single credential field for a tool.
4522
4589
  *
4523
- * @param userId - User ID
4524
- * @param service - Service name ('anthropic', 'openai', 'gemini')
4525
- * @param apiKey - Plaintext API key to encrypt and store
4590
+ * Field names are env-var-shaped (e.g. ANTHROPIC_API_KEY, ANTHROPIC_BASE_URL)
4591
+ * and are stored encrypted regardless of whether the value is a secret —
4592
+ * keeping the on-disk shape uniform avoids decrypt-vs-plain branching at
4593
+ * read time. UI controls own the text-vs-password rendering distinction.
4526
4594
  */
4527
- async setApiKey(userId, service, apiKey) {
4595
+ async setToolConfigField(userId, tool, field, value) {
4528
4596
  const fullId = await this.resolveId(userId);
4529
4597
  const row = await this.getRawRow(fullId);
4530
4598
  if (!row) {
4531
4599
  throw new EntityNotFoundError("User", userId);
4532
4600
  }
4533
- const keyMap = {
4534
- anthropic: "ANTHROPIC_API_KEY",
4535
- openai: "OPENAI_API_KEY",
4536
- gemini: "GEMINI_API_KEY",
4537
- copilot: "COPILOT_GITHUB_TOKEN"
4538
- };
4539
- const encryptedKey = encryptApiKey(apiKey);
4540
- const updatedApiKeys = {
4541
- ...row.data.api_keys || {},
4542
- [keyMap[service]]: encryptedKey
4543
- };
4544
- const user = this.rowToUser(row);
4545
- const updateData = {
4546
- ...user,
4547
- api_keys_raw: updatedApiKeys
4601
+ const stored = row.data.agentic_tools ?? {};
4602
+ const next = {
4603
+ ...stored,
4604
+ [tool]: {
4605
+ ...stored[tool] ?? {},
4606
+ [field]: encryptApiKey(value)
4607
+ }
4548
4608
  };
4549
- const insertData = this.userToInsert(updateData);
4550
4609
  await update(this.db, users3).set({
4551
- ...insertData,
4610
+ data: { ...row.data, agentic_tools: next },
4552
4611
  updated_at: /* @__PURE__ */ new Date()
4553
4612
  }).where((0, import_drizzle_orm22.eq)(users3.user_id, fullId)).run();
4554
4613
  }
4555
4614
  /**
4556
- * Delete API key for a user and service
4615
+ * Delete a single credential field for a tool.
4557
4616
  *
4558
- * @param userId - User ID
4559
- * @param service - Service name ('anthropic', 'openai', 'gemini')
4617
+ * If the tool's bucket becomes empty after the delete, the bucket itself is
4618
+ * removed so `data.agentic_tools` doesn't accumulate empty objects.
4560
4619
  */
4561
- async deleteApiKey(userId, service) {
4620
+ async deleteToolConfigField(userId, tool, field) {
4562
4621
  const fullId = await this.resolveId(userId);
4563
4622
  const row = await this.getRawRow(fullId);
4564
4623
  if (!row) {
4565
4624
  throw new EntityNotFoundError("User", userId);
4566
4625
  }
4567
- const keyMap = {
4568
- anthropic: "ANTHROPIC_API_KEY",
4569
- openai: "OPENAI_API_KEY",
4570
- gemini: "GEMINI_API_KEY",
4571
- copilot: "COPILOT_GITHUB_TOKEN"
4572
- };
4573
- const updatedApiKeys = { ...row.data.api_keys || {} };
4574
- delete updatedApiKeys[keyMap[service]];
4575
- const user = this.rowToUser(row);
4576
- const updateData = {
4577
- ...user,
4578
- api_keys_raw: updatedApiKeys
4579
- };
4580
- const insertData = this.userToInsert(updateData);
4626
+ const stored = row.data.agentic_tools ?? {};
4627
+ const toolFields = { ...stored[tool] ?? {} };
4628
+ delete toolFields[field];
4629
+ const next = { ...stored };
4630
+ if (Object.keys(toolFields).length > 0) {
4631
+ next[tool] = toolFields;
4632
+ } else {
4633
+ delete next[tool];
4634
+ }
4581
4635
  await update(this.db, users3).set({
4582
- ...insertData,
4636
+ data: { ...row.data, agentic_tools: next },
4583
4637
  updated_at: /* @__PURE__ */ new Date()
4584
4638
  }).where((0, import_drizzle_orm22.eq)(users3.user_id, fullId)).run();
4585
4639
  }
@@ -5119,14 +5173,7 @@ var WorktreeRepository = class {
5119
5173
  for (const sessionId of sessionIds) {
5120
5174
  const query = select(this.db, {
5121
5175
  data: messagesTable.data
5122
- }).from(messagesTable).where(
5123
- (0, import_drizzle_orm23.and)(
5124
- (0, import_drizzle_orm23.eq)(messagesTable.session_id, sessionId),
5125
- (0, import_drizzle_orm23.eq)(messagesTable.role, "assistant"),
5126
- (0, import_drizzle_orm23.isNull)(messagesTable.status)
5127
- // Exclude queued messages
5128
- )
5129
- );
5176
+ }).from(messagesTable).where((0, import_drizzle_orm23.and)((0, import_drizzle_orm23.eq)(messagesTable.session_id, sessionId), (0, import_drizzle_orm23.eq)(messagesTable.role, "assistant")));
5130
5177
  const lastMessage = await query.orderBy((0, import_drizzle_orm23.desc)(messagesTable.index)).limit(1).one();
5131
5178
  if (lastMessage) {
5132
5179
  const messageData = lastMessage.data;