@cloudcli-ai/cloudcli 1.36.2 → 1.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (539) hide show
  1. package/dist/assets/index-DSlds633.css +32 -0
  2. package/dist/assets/{index-CDGzV0LN.js → index-eGqPeIEu.js} +375 -267
  3. package/dist/index.html +2 -2
  4. package/dist-server/server/constants/config.js.map +1 -1
  5. package/dist-server/server/index.js +73 -1224
  6. package/dist-server/server/index.js.map +1 -1
  7. package/dist-server/server/load-env.js +17 -4
  8. package/dist-server/server/load-env.js.map +1 -1
  9. package/dist-server/server/modules/agent/agent.module.js +37 -0
  10. package/dist-server/server/modules/agent/agent.module.js.map +1 -0
  11. package/dist-server/server/modules/agent/agent.routes.js +1161 -0
  12. package/dist-server/server/modules/agent/agent.routes.js.map +1 -0
  13. package/dist-server/server/modules/agent/index.js +3 -0
  14. package/dist-server/server/modules/agent/index.js.map +1 -0
  15. package/dist-server/server/modules/agent/tests/agent.routes.test.js +176 -0
  16. package/dist-server/server/modules/agent/tests/agent.routes.test.js.map +1 -0
  17. package/dist-server/server/modules/assets/assets.routes.js +56 -15
  18. package/dist-server/server/modules/assets/assets.routes.js.map +1 -1
  19. package/dist-server/server/modules/assets/index.js +2 -2
  20. package/dist-server/server/modules/assets/index.js.map +1 -1
  21. package/dist-server/server/modules/assets/services/image-assets.service.js +39 -1
  22. package/dist-server/server/modules/assets/services/image-assets.service.js.map +1 -1
  23. package/dist-server/server/modules/assets/tests/image-assets.service.test.js +21 -1
  24. package/dist-server/server/modules/assets/tests/image-assets.service.test.js.map +1 -1
  25. package/dist-server/server/{middleware/auth.js → modules/auth/auth.middleware.js} +30 -8
  26. package/dist-server/server/modules/auth/auth.middleware.js.map +1 -0
  27. package/dist-server/server/modules/auth/auth.module.js +29 -0
  28. package/dist-server/server/modules/auth/auth.module.js.map +1 -0
  29. package/dist-server/server/modules/auth/auth.routes.js +45 -0
  30. package/dist-server/server/modules/auth/auth.routes.js.map +1 -0
  31. package/dist-server/server/modules/auth/auth.service.js +113 -0
  32. package/dist-server/server/modules/auth/auth.service.js.map +1 -0
  33. package/dist-server/server/modules/auth/index.js +9 -0
  34. package/dist-server/server/modules/auth/index.js.map +1 -0
  35. package/dist-server/server/modules/auth/tests/auth.service.test.js +80 -0
  36. package/dist-server/server/modules/auth/tests/auth.service.test.js.map +1 -0
  37. package/dist-server/server/{browser-use-mcp.js → modules/browser-use/browser-use-mcp.js} +3 -1
  38. package/dist-server/server/modules/browser-use/browser-use-mcp.js.map +1 -0
  39. package/dist-server/server/modules/browser-use/browser-use.service.js +3 -4
  40. package/dist-server/server/modules/browser-use/browser-use.service.js.map +1 -1
  41. package/dist-server/server/modules/browser-use/index.js +9 -0
  42. package/dist-server/server/modules/browser-use/index.js.map +1 -0
  43. package/dist-server/server/modules/cli/cli.js +11 -0
  44. package/dist-server/server/modules/cli/cli.js.map +1 -0
  45. package/dist-server/server/modules/cli/cli.module.js +86 -0
  46. package/dist-server/server/modules/cli/cli.module.js.map +1 -0
  47. package/dist-server/server/modules/cli/cli.service.js +244 -0
  48. package/dist-server/server/modules/cli/cli.service.js.map +1 -0
  49. package/dist-server/server/modules/cli/index.js +3 -0
  50. package/dist-server/server/modules/cli/index.js.map +1 -0
  51. package/dist-server/server/modules/cli/sandbox.service.js +332 -0
  52. package/dist-server/server/modules/cli/sandbox.service.js.map +1 -0
  53. package/dist-server/server/modules/cli/tests/cli.service.test.js +78 -0
  54. package/dist-server/server/modules/cli/tests/cli.service.test.js.map +1 -0
  55. package/dist-server/server/modules/cli/tests/sandbox.service.test.js +55 -0
  56. package/dist-server/server/modules/cli/tests/sandbox.service.test.js.map +1 -0
  57. package/dist-server/server/modules/commands/commands.module.js +20 -0
  58. package/dist-server/server/modules/commands/commands.module.js.map +1 -0
  59. package/dist-server/server/modules/commands/commands.routes.js +497 -0
  60. package/dist-server/server/modules/commands/commands.routes.js.map +1 -0
  61. package/dist-server/server/modules/commands/index.js +3 -0
  62. package/dist-server/server/modules/commands/index.js.map +1 -0
  63. package/dist-server/server/modules/commands/tests/commands.test.js +96 -0
  64. package/dist-server/server/modules/commands/tests/commands.test.js.map +1 -0
  65. package/dist-server/server/modules/database/index.js +1 -0
  66. package/dist-server/server/modules/database/index.js.map +1 -1
  67. package/dist-server/server/modules/database/migrations.js +13 -0
  68. package/dist-server/server/modules/database/migrations.js.map +1 -1
  69. package/dist-server/server/modules/database/repositories/sessions.db.js +14 -1
  70. package/dist-server/server/modules/database/repositories/sessions.db.js.map +1 -1
  71. package/dist-server/server/modules/database/schema.js +4 -0
  72. package/dist-server/server/modules/database/schema.js.map +1 -1
  73. package/dist-server/server/modules/file-tree/file-tree.module.js +91 -0
  74. package/dist-server/server/modules/file-tree/file-tree.module.js.map +1 -0
  75. package/dist-server/server/modules/file-tree/file-tree.routes.js +208 -0
  76. package/dist-server/server/modules/file-tree/file-tree.routes.js.map +1 -0
  77. package/dist-server/server/modules/file-tree/file-tree.service.js +544 -0
  78. package/dist-server/server/modules/file-tree/file-tree.service.js.map +1 -0
  79. package/dist-server/server/modules/file-tree/index.js +3 -0
  80. package/dist-server/server/modules/file-tree/index.js.map +1 -0
  81. package/dist-server/server/modules/file-tree/tests/file-tree.routes.test.js +123 -0
  82. package/dist-server/server/modules/file-tree/tests/file-tree.routes.test.js.map +1 -0
  83. package/dist-server/server/modules/file-tree/tests/file-tree.service.test.js +184 -0
  84. package/dist-server/server/modules/file-tree/tests/file-tree.service.test.js.map +1 -0
  85. package/dist-server/server/modules/git/git-parsing.service.js +61 -0
  86. package/dist-server/server/modules/git/git-parsing.service.js.map +1 -0
  87. package/dist-server/server/modules/git/git.module.js +14 -0
  88. package/dist-server/server/modules/git/git.module.js.map +1 -0
  89. package/dist-server/server/modules/git/git.routes.js +1339 -0
  90. package/dist-server/server/modules/git/git.routes.js.map +1 -0
  91. package/dist-server/server/modules/git/index.js +3 -0
  92. package/dist-server/server/modules/git/index.js.map +1 -0
  93. package/dist-server/server/modules/git/tests/git-init.routes.test.js +48 -0
  94. package/dist-server/server/modules/git/tests/git-init.routes.test.js.map +1 -0
  95. package/dist-server/server/{routes → modules/git/tests}/git.test.js +1 -1
  96. package/dist-server/server/modules/git/tests/git.test.js.map +1 -0
  97. package/dist-server/server/modules/notifications/index.js +15 -1
  98. package/dist-server/server/modules/notifications/index.js.map +1 -1
  99. package/dist-server/server/modules/notifications/tests/notification-orchestrator.integration.test.js +44 -0
  100. package/dist-server/server/modules/notifications/tests/notification-orchestrator.integration.test.js.map +1 -0
  101. package/dist-server/server/{services/vapid-keys.js → modules/notifications/vapid-keys.service.js} +3 -2
  102. package/dist-server/server/modules/notifications/vapid-keys.service.js.map +1 -0
  103. package/dist-server/server/modules/plugins/index.js +9 -0
  104. package/dist-server/server/modules/plugins/index.js.map +1 -0
  105. package/dist-server/server/{utils/plugin-process-manager.js → modules/plugins/plugin-process.service.js} +3 -2
  106. package/dist-server/server/modules/plugins/plugin-process.service.js.map +1 -0
  107. package/dist-server/server/{utils/plugin-loader.js → modules/plugins/plugin-registry.service.js} +2 -1
  108. package/dist-server/server/modules/plugins/plugin-registry.service.js.map +1 -0
  109. package/dist-server/server/modules/plugins/plugins.module.js +30 -0
  110. package/dist-server/server/modules/plugins/plugins.module.js.map +1 -0
  111. package/dist-server/server/modules/plugins/plugins.routes.js +70 -0
  112. package/dist-server/server/modules/plugins/plugins.routes.js.map +1 -0
  113. package/dist-server/server/modules/plugins/plugins.service.js +123 -0
  114. package/dist-server/server/modules/plugins/plugins.service.js.map +1 -0
  115. package/dist-server/server/modules/plugins/tests/plugins.service.test.js +28 -0
  116. package/dist-server/server/modules/plugins/tests/plugins.service.test.js.map +1 -0
  117. package/dist-server/server/modules/projects/index.js +5 -0
  118. package/dist-server/server/modules/projects/index.js.map +1 -1
  119. package/dist-server/server/modules/providers/index.js +3 -0
  120. package/dist-server/server/modules/providers/index.js.map +1 -1
  121. package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js +6 -0
  122. package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js.map +1 -1
  123. package/dist-server/server/modules/providers/list/claude/claude-models.provider.js +1 -4
  124. package/dist-server/server/modules/providers/list/claude/claude-models.provider.js.map +1 -1
  125. package/dist-server/server/{claude-sdk.js → modules/providers/list/claude/claude-runtime.provider.js} +62 -41
  126. package/dist-server/server/modules/providers/list/claude/claude-runtime.provider.js.map +1 -0
  127. package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js +6 -4
  128. package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js.map +1 -1
  129. package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js +23 -4
  130. package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js.map +1 -1
  131. package/dist-server/server/modules/providers/list/claude/claude.provider.js +2 -0
  132. package/dist-server/server/modules/providers/list/claude/claude.provider.js.map +1 -1
  133. package/dist-server/server/modules/providers/list/codex/codex-models.provider.js +1 -4
  134. package/dist-server/server/modules/providers/list/codex/codex-models.provider.js.map +1 -1
  135. package/dist-server/server/{openai-codex.js → modules/providers/list/codex/codex-runtime.provider.js} +48 -34
  136. package/dist-server/server/modules/providers/list/codex/codex-runtime.provider.js.map +1 -0
  137. package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js +19 -1
  138. package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js.map +1 -1
  139. package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js +290 -6
  140. package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js.map +1 -1
  141. package/dist-server/server/modules/providers/list/codex/codex-skills.provider.js +5 -0
  142. package/dist-server/server/modules/providers/list/codex/codex-skills.provider.js.map +1 -1
  143. package/dist-server/server/modules/providers/list/codex/codex.provider.js +2 -0
  144. package/dist-server/server/modules/providers/list/codex/codex.provider.js.map +1 -1
  145. package/dist-server/server/modules/providers/list/cursor/cursor-models.provider.js +1 -4
  146. package/dist-server/server/modules/providers/list/cursor/cursor-models.provider.js.map +1 -1
  147. package/dist-server/server/{cursor-cli.js → modules/providers/list/cursor/cursor-runtime.provider.js} +40 -28
  148. package/dist-server/server/modules/providers/list/cursor/cursor-runtime.provider.js.map +1 -0
  149. package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js +21 -14
  150. package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js.map +1 -1
  151. package/dist-server/server/modules/providers/list/cursor/cursor.provider.js +2 -0
  152. package/dist-server/server/modules/providers/list/cursor/cursor.provider.js.map +1 -1
  153. package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js +7 -5
  154. package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js.map +1 -1
  155. package/dist-server/server/{opencode-cli.js → modules/providers/list/opencode/opencode-runtime.provider.js} +38 -25
  156. package/dist-server/server/modules/providers/list/opencode/opencode-runtime.provider.js.map +1 -0
  157. package/dist-server/server/{opencode-cli.test.js → modules/providers/list/opencode/opencode-runtime.provider.test.js} +27 -4
  158. package/dist-server/server/modules/providers/list/opencode/opencode-runtime.provider.test.js.map +1 -0
  159. package/dist-server/server/modules/providers/list/opencode/opencode-sessions.provider.js +11 -5
  160. package/dist-server/server/modules/providers/list/opencode/opencode-sessions.provider.js.map +1 -1
  161. package/dist-server/server/modules/providers/list/opencode/opencode.provider.js +2 -0
  162. package/dist-server/server/modules/providers/list/opencode/opencode.provider.js.map +1 -1
  163. package/dist-server/server/modules/providers/provider.routes.js +33 -9
  164. package/dist-server/server/modules/providers/provider.routes.js.map +1 -1
  165. package/dist-server/server/modules/providers/services/provider-capabilities.service.js +5 -1
  166. package/dist-server/server/modules/providers/services/provider-capabilities.service.js.map +1 -1
  167. package/dist-server/server/modules/providers/services/provider-models.service.js +110 -15
  168. package/dist-server/server/modules/providers/services/provider-models.service.js.map +1 -1
  169. package/dist-server/server/modules/providers/services/provider-runtime.service.js +66 -0
  170. package/dist-server/server/modules/providers/services/provider-runtime.service.js.map +1 -0
  171. package/dist-server/server/modules/providers/services/provider-token-usage.service.js +268 -0
  172. package/dist-server/server/modules/providers/services/provider-token-usage.service.js.map +1 -0
  173. package/dist-server/server/modules/providers/services/sessions-watcher.service.js +2 -0
  174. package/dist-server/server/modules/providers/services/sessions-watcher.service.js.map +1 -1
  175. package/dist-server/server/modules/providers/services/sessions.service.js +54 -0
  176. package/dist-server/server/modules/providers/services/sessions.service.js.map +1 -1
  177. package/dist-server/server/modules/providers/shared/base/abstract.provider.js +2 -3
  178. package/dist-server/server/modules/providers/shared/base/abstract.provider.js.map +1 -1
  179. package/dist-server/server/modules/providers/tests/claude-auth.test.js +122 -0
  180. package/dist-server/server/modules/providers/tests/claude-auth.test.js.map +1 -0
  181. package/dist-server/server/modules/providers/tests/claude-sessions.test.js +44 -0
  182. package/dist-server/server/modules/providers/tests/claude-sessions.test.js.map +1 -0
  183. package/dist-server/server/modules/providers/tests/codex-sessions.test.js +70 -0
  184. package/dist-server/server/modules/providers/tests/codex-sessions.test.js.map +1 -1
  185. package/dist-server/server/modules/providers/tests/{provider-image-history.test.js → provider-attachment-history.test.js} +60 -2
  186. package/dist-server/server/modules/providers/tests/provider-attachment-history.test.js.map +1 -0
  187. package/dist-server/server/modules/providers/tests/provider-models.service.test.js +148 -61
  188. package/dist-server/server/modules/providers/tests/provider-models.service.test.js.map +1 -1
  189. package/dist-server/server/modules/providers/tests/provider-runtime.service.test.js +130 -0
  190. package/dist-server/server/modules/providers/tests/provider-runtime.service.test.js.map +1 -0
  191. package/dist-server/server/modules/providers/tests/provider-token-usage.service.test.js +165 -0
  192. package/dist-server/server/modules/providers/tests/provider-token-usage.service.test.js.map +1 -0
  193. package/dist-server/server/modules/providers/tests/sessions-details.test.js +62 -0
  194. package/dist-server/server/modules/providers/tests/sessions-details.test.js.map +1 -0
  195. package/dist-server/server/modules/providers/tests/skills.test.js +4 -2
  196. package/dist-server/server/modules/providers/tests/skills.test.js.map +1 -1
  197. package/dist-server/server/modules/settings/index.js +3 -0
  198. package/dist-server/server/modules/settings/index.js.map +1 -0
  199. package/dist-server/server/modules/settings/settings.module.js +35 -0
  200. package/dist-server/server/modules/settings/settings.module.js.map +1 -0
  201. package/dist-server/server/modules/settings/settings.routes.js +34 -0
  202. package/dist-server/server/modules/settings/settings.routes.js.map +1 -0
  203. package/dist-server/server/modules/settings/settings.service.js +116 -0
  204. package/dist-server/server/modules/settings/settings.service.js.map +1 -0
  205. package/dist-server/server/modules/settings/tests/settings.service.test.js +48 -0
  206. package/dist-server/server/modules/settings/tests/settings.service.test.js.map +1 -0
  207. package/dist-server/server/modules/system/index.js +3 -0
  208. package/dist-server/server/modules/system/index.js.map +1 -0
  209. package/dist-server/server/modules/system/system.module.js +44 -0
  210. package/dist-server/server/modules/system/system.module.js.map +1 -0
  211. package/dist-server/server/modules/system/system.routes.js +16 -0
  212. package/dist-server/server/modules/system/system.routes.js.map +1 -0
  213. package/dist-server/server/modules/system/system.service.js +45 -0
  214. package/dist-server/server/modules/system/system.service.js.map +1 -0
  215. package/dist-server/server/modules/system/tests/system.service.test.js +100 -0
  216. package/dist-server/server/modules/system/tests/system.service.test.js.map +1 -0
  217. package/dist-server/server/modules/taskmaster/index.js +3 -0
  218. package/dist-server/server/modules/taskmaster/index.js.map +1 -0
  219. package/dist-server/server/modules/taskmaster/taskmaster.module.js +20 -0
  220. package/dist-server/server/modules/taskmaster/taskmaster.module.js.map +1 -0
  221. package/dist-server/server/modules/taskmaster/taskmaster.routes.js +1372 -0
  222. package/dist-server/server/modules/taskmaster/taskmaster.routes.js.map +1 -0
  223. package/dist-server/server/modules/taskmaster/taskmaster.service.js +107 -0
  224. package/dist-server/server/modules/taskmaster/taskmaster.service.js.map +1 -0
  225. package/dist-server/server/modules/taskmaster/tests/taskmaster.routes.test.js +132 -0
  226. package/dist-server/server/modules/taskmaster/tests/taskmaster.routes.test.js.map +1 -0
  227. package/dist-server/server/modules/taskmaster/tests/taskmaster.service.test.js +85 -0
  228. package/dist-server/server/modules/taskmaster/tests/taskmaster.service.test.js.map +1 -0
  229. package/dist-server/server/modules/user/index.js +3 -0
  230. package/dist-server/server/modules/user/index.js.map +1 -0
  231. package/dist-server/server/modules/user/tests/user.service.test.js +53 -0
  232. package/dist-server/server/modules/user/tests/user.service.test.js.map +1 -0
  233. package/dist-server/server/modules/user/user.module.js +47 -0
  234. package/dist-server/server/modules/user/user.module.js.map +1 -0
  235. package/dist-server/server/modules/user/user.routes.js +44 -0
  236. package/dist-server/server/modules/user/user.routes.js.map +1 -0
  237. package/dist-server/server/modules/user/user.service.js +59 -0
  238. package/dist-server/server/modules/user/user.service.js.map +1 -0
  239. package/dist-server/server/modules/voice/index.js +3 -0
  240. package/dist-server/server/modules/voice/index.js.map +1 -0
  241. package/dist-server/server/modules/voice/tests/voice.service.test.js +86 -0
  242. package/dist-server/server/modules/voice/tests/voice.service.test.js.map +1 -0
  243. package/dist-server/server/modules/voice/voice.module.js +44 -0
  244. package/dist-server/server/modules/voice/voice.module.js.map +1 -0
  245. package/dist-server/server/modules/voice/voice.routes.js +87 -0
  246. package/dist-server/server/modules/voice/voice.routes.js.map +1 -0
  247. package/dist-server/server/modules/voice/voice.service.js +148 -0
  248. package/dist-server/server/modules/voice/voice.service.js.map +1 -0
  249. package/dist-server/server/modules/websocket/services/chat-session-writer.service.js +2 -2
  250. package/dist-server/server/modules/websocket/services/chat-websocket.service.js +40 -29
  251. package/dist-server/server/modules/websocket/services/chat-websocket.service.js.map +1 -1
  252. package/dist-server/server/modules/websocket/services/shell-websocket.service.js +76 -8
  253. package/dist-server/server/modules/websocket/services/shell-websocket.service.js.map +1 -1
  254. package/dist-server/server/modules/websocket/services/websocket-server.service.js +51 -20
  255. package/dist-server/server/modules/websocket/services/websocket-server.service.js.map +1 -1
  256. package/dist-server/server/modules/websocket/tests/{chat-image-filter.test.js → chat-attachment-filter.test.js} +10 -3
  257. package/dist-server/server/modules/websocket/tests/chat-attachment-filter.test.js.map +1 -0
  258. package/dist-server/server/modules/websocket/tests/shell-websocket.service.test.js +97 -0
  259. package/dist-server/server/modules/websocket/tests/shell-websocket.service.test.js.map +1 -0
  260. package/dist-server/server/modules/websocket/tests/websocket-heartbeat.service.test.js +61 -0
  261. package/dist-server/server/modules/websocket/tests/websocket-heartbeat.service.test.js.map +1 -0
  262. package/dist-server/server/modules/worktrees/index.js +3 -0
  263. package/dist-server/server/modules/worktrees/index.js.map +1 -0
  264. package/dist-server/server/modules/worktrees/services/worktree-create-and-open.service.js +37 -0
  265. package/dist-server/server/modules/worktrees/services/worktree-create-and-open.service.js.map +1 -0
  266. package/dist-server/server/modules/worktrees/services/worktree-create.service.js +67 -0
  267. package/dist-server/server/modules/worktrees/services/worktree-create.service.js.map +1 -0
  268. package/dist-server/server/modules/worktrees/services/worktree-git.service.js +172 -0
  269. package/dist-server/server/modules/worktrees/services/worktree-git.service.js.map +1 -0
  270. package/dist-server/server/modules/worktrees/services/worktree-list.service.js +91 -0
  271. package/dist-server/server/modules/worktrees/services/worktree-list.service.js.map +1 -0
  272. package/dist-server/server/modules/worktrees/services/worktree-merge.service.js +118 -0
  273. package/dist-server/server/modules/worktrees/services/worktree-merge.service.js.map +1 -0
  274. package/dist-server/server/modules/worktrees/services/worktree-open.service.js +58 -0
  275. package/dist-server/server/modules/worktrees/services/worktree-open.service.js.map +1 -0
  276. package/dist-server/server/modules/worktrees/services/worktree-remove.service.js +65 -0
  277. package/dist-server/server/modules/worktrees/services/worktree-remove.service.js.map +1 -0
  278. package/dist-server/server/modules/worktrees/tests/worktree-create-and-open.service.test.js +58 -0
  279. package/dist-server/server/modules/worktrees/tests/worktree-create-and-open.service.test.js.map +1 -0
  280. package/dist-server/server/modules/worktrees/tests/worktree-create.service.test.js +85 -0
  281. package/dist-server/server/modules/worktrees/tests/worktree-create.service.test.js.map +1 -0
  282. package/dist-server/server/modules/worktrees/tests/worktree-git.service.test.js +58 -0
  283. package/dist-server/server/modules/worktrees/tests/worktree-git.service.test.js.map +1 -0
  284. package/dist-server/server/modules/worktrees/tests/worktree-list.service.test.js +34 -0
  285. package/dist-server/server/modules/worktrees/tests/worktree-list.service.test.js.map +1 -0
  286. package/dist-server/server/modules/worktrees/tests/worktree-merge.service.test.js +137 -0
  287. package/dist-server/server/modules/worktrees/tests/worktree-merge.service.test.js.map +1 -0
  288. package/dist-server/server/modules/worktrees/tests/worktree-open.service.test.js +99 -0
  289. package/dist-server/server/modules/worktrees/tests/worktree-open.service.test.js.map +1 -0
  290. package/dist-server/server/modules/worktrees/tests/worktree-remove.service.test.js +157 -0
  291. package/dist-server/server/modules/worktrees/tests/worktree-remove.service.test.js.map +1 -0
  292. package/dist-server/server/modules/worktrees/tests/worktrees.routes.test.js +167 -0
  293. package/dist-server/server/modules/worktrees/tests/worktrees.routes.test.js.map +1 -0
  294. package/dist-server/server/modules/worktrees/worktrees.module.js +97 -0
  295. package/dist-server/server/modules/worktrees/worktrees.module.js.map +1 -0
  296. package/dist-server/server/modules/worktrees/worktrees.routes.js +84 -0
  297. package/dist-server/server/modules/worktrees/worktrees.routes.js.map +1 -0
  298. package/dist-server/server/shared/image-attachments.js +90 -17
  299. package/dist-server/server/shared/image-attachments.js.map +1 -1
  300. package/dist-server/server/shared/tests/image-attachments.test.js +43 -1
  301. package/dist-server/server/shared/tests/image-attachments.test.js.map +1 -1
  302. package/dist-server/server/shared/utils.js +66 -142
  303. package/dist-server/server/shared/utils.js.map +1 -1
  304. package/electron/localServer.js +1 -2
  305. package/package.json +8 -4
  306. package/server/index.ts +401 -0
  307. package/server/{load-env.js → load-env.ts} +18 -5
  308. package/server/modules/agent/agent.module.ts +51 -0
  309. package/server/modules/agent/agent.routes.ts +1287 -0
  310. package/server/modules/agent/index.ts +2 -0
  311. package/server/modules/agent/tests/agent.routes.test.ts +205 -0
  312. package/server/modules/assets/assets.routes.ts +63 -16
  313. package/server/modules/assets/index.ts +2 -2
  314. package/server/modules/assets/services/image-assets.service.ts +46 -1
  315. package/server/modules/assets/tests/image-assets.service.test.ts +28 -0
  316. package/server/{middleware/auth.js → modules/auth/auth.middleware.ts} +38 -7
  317. package/server/modules/auth/auth.module.ts +38 -0
  318. package/server/modules/auth/auth.routes.ts +57 -0
  319. package/server/modules/auth/auth.service.ts +155 -0
  320. package/server/modules/auth/index.ts +9 -0
  321. package/server/modules/auth/tests/auth.service.test.ts +95 -0
  322. package/server/{browser-use-mcp.ts → modules/browser-use/browser-use-mcp.ts} +3 -1
  323. package/server/modules/browser-use/browser-use.service.ts +3 -4
  324. package/server/modules/browser-use/index.ts +8 -0
  325. package/server/modules/cli/cli.module.ts +96 -0
  326. package/server/modules/cli/cli.service.ts +281 -0
  327. package/server/modules/cli/cli.ts +13 -0
  328. package/server/modules/cli/index.ts +2 -0
  329. package/server/modules/cli/sandbox.service.ts +413 -0
  330. package/server/modules/cli/tests/cli.service.test.ts +91 -0
  331. package/server/modules/cli/tests/sandbox.service.test.ts +61 -0
  332. package/server/modules/commands/commands.module.ts +22 -0
  333. package/server/{routes/commands.js → modules/commands/commands.routes.ts} +44 -36
  334. package/server/modules/commands/index.ts +2 -0
  335. package/server/modules/commands/tests/commands.test.ts +119 -0
  336. package/server/modules/database/index.ts +1 -0
  337. package/server/modules/database/migrations.ts +15 -0
  338. package/server/modules/database/repositories/sessions.db.ts +19 -1
  339. package/server/modules/database/schema.ts +4 -0
  340. package/server/modules/file-tree/file-tree.module.ts +112 -0
  341. package/server/modules/file-tree/file-tree.routes.ts +258 -0
  342. package/server/modules/file-tree/file-tree.service.ts +616 -0
  343. package/server/modules/file-tree/index.ts +2 -0
  344. package/server/modules/file-tree/tests/file-tree.routes.test.ts +157 -0
  345. package/server/modules/file-tree/tests/file-tree.service.test.ts +220 -0
  346. package/server/modules/git/git-parsing.service.ts +66 -0
  347. package/server/modules/git/git.module.ts +22 -0
  348. package/server/{routes/git.js → modules/git/git.routes.ts} +91 -132
  349. package/server/modules/git/index.ts +2 -0
  350. package/server/modules/git/tests/git-init.routes.test.ts +52 -0
  351. package/server/{routes/git.test.js → modules/git/tests/git.test.ts} +3 -3
  352. package/server/modules/notifications/index.ts +9 -0
  353. package/server/modules/notifications/tests/notification-orchestrator.integration.test.ts +55 -0
  354. package/server/{services/vapid-keys.js → modules/notifications/vapid-keys.service.ts} +3 -1
  355. package/server/modules/plugins/index.ts +9 -0
  356. package/server/{utils/plugin-process-manager.js → modules/plugins/plugin-process.service.ts} +3 -1
  357. package/server/{utils/plugin-loader.js → modules/plugins/plugin-registry.service.ts} +1 -0
  358. package/server/modules/plugins/plugins.module.ts +33 -0
  359. package/server/modules/plugins/plugins.routes.ts +66 -0
  360. package/server/modules/plugins/plugins.service.ts +147 -0
  361. package/server/modules/plugins/tests/plugins.service.test.ts +32 -0
  362. package/server/modules/projects/index.ts +5 -0
  363. package/server/modules/providers/README.md +41 -9
  364. package/server/modules/providers/index.ts +4 -0
  365. package/server/modules/providers/list/claude/claude-auth.provider.ts +8 -0
  366. package/server/modules/providers/list/claude/claude-models.provider.ts +1 -12
  367. package/server/{claude-sdk.js → modules/providers/list/claude/claude-runtime.provider.js} +66 -44
  368. package/server/modules/providers/list/claude/claude-session-synchronizer.provider.ts +6 -4
  369. package/server/modules/providers/list/claude/claude-sessions.provider.ts +27 -4
  370. package/server/modules/providers/list/claude/claude.provider.ts +3 -0
  371. package/server/modules/providers/list/codex/codex-models.provider.ts +0 -9
  372. package/server/{openai-codex.js → modules/providers/list/codex/codex-runtime.provider.js} +54 -36
  373. package/server/modules/providers/list/codex/codex-session-synchronizer.provider.ts +21 -1
  374. package/server/modules/providers/list/codex/codex-sessions.provider.ts +331 -7
  375. package/server/modules/providers/list/codex/codex-skills.provider.ts +5 -0
  376. package/server/modules/providers/list/codex/codex.provider.ts +3 -0
  377. package/server/modules/providers/list/cursor/cursor-models.provider.ts +0 -9
  378. package/server/{cursor-cli.js → modules/providers/list/cursor/cursor-runtime.provider.js} +58 -27
  379. package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +26 -15
  380. package/server/modules/providers/list/cursor/cursor.provider.ts +3 -0
  381. package/server/modules/providers/list/opencode/opencode-models.provider.ts +7 -10
  382. package/server/{opencode-cli.js → modules/providers/list/opencode/opencode-runtime.provider.js} +56 -28
  383. package/server/{opencode-cli.test.js → modules/providers/list/opencode/opencode-runtime.provider.test.js} +41 -3
  384. package/server/modules/providers/list/opencode/opencode-sessions.provider.ts +13 -5
  385. package/server/modules/providers/list/opencode/opencode.provider.ts +3 -0
  386. package/server/modules/providers/provider.routes.ts +47 -10
  387. package/server/modules/providers/services/provider-capabilities.service.ts +7 -1
  388. package/server/modules/providers/services/provider-models.service.ts +131 -23
  389. package/server/modules/providers/services/provider-runtime.service.ts +109 -0
  390. package/server/modules/providers/services/provider-token-usage.service.ts +357 -0
  391. package/server/modules/providers/services/sessions-watcher.service.ts +2 -0
  392. package/server/modules/providers/services/sessions.service.ts +79 -0
  393. package/server/modules/providers/shared/base/abstract.provider.ts +4 -3
  394. package/server/modules/providers/tests/claude-auth.test.ts +150 -0
  395. package/server/modules/providers/tests/claude-sessions.test.ts +61 -0
  396. package/server/modules/providers/tests/codex-sessions.test.ts +81 -0
  397. package/server/modules/providers/tests/{provider-image-history.test.ts → provider-attachment-history.test.ts} +68 -1
  398. package/server/modules/providers/tests/provider-models.service.test.ts +450 -349
  399. package/server/modules/providers/tests/provider-runtime.service.test.ts +142 -0
  400. package/server/modules/providers/tests/provider-token-usage.service.test.ts +185 -0
  401. package/server/modules/providers/tests/sessions-details.test.ts +73 -0
  402. package/server/modules/providers/tests/skills.test.ts +9 -2
  403. package/server/modules/settings/index.ts +2 -0
  404. package/server/modules/settings/settings.module.ts +50 -0
  405. package/server/modules/settings/settings.routes.ts +51 -0
  406. package/server/modules/settings/settings.service.ts +186 -0
  407. package/server/modules/settings/tests/settings.service.test.ts +54 -0
  408. package/server/modules/system/index.ts +2 -0
  409. package/server/modules/system/system.module.ts +62 -0
  410. package/server/modules/system/system.routes.ts +21 -0
  411. package/server/modules/system/system.service.ts +76 -0
  412. package/server/modules/system/tests/system.service.test.ts +118 -0
  413. package/server/modules/taskmaster/index.ts +2 -0
  414. package/server/modules/taskmaster/taskmaster.module.ts +24 -0
  415. package/server/modules/taskmaster/taskmaster.routes.ts +1482 -0
  416. package/server/modules/taskmaster/taskmaster.service.ts +132 -0
  417. package/server/modules/taskmaster/tests/taskmaster.routes.test.ts +144 -0
  418. package/server/modules/taskmaster/tests/taskmaster.service.test.ts +97 -0
  419. package/server/modules/user/index.ts +2 -0
  420. package/server/modules/user/tests/user.service.test.ts +61 -0
  421. package/server/modules/user/user.module.ts +58 -0
  422. package/server/modules/user/user.routes.ts +50 -0
  423. package/server/modules/user/user.service.ts +85 -0
  424. package/server/modules/voice/index.ts +2 -0
  425. package/server/modules/voice/tests/voice.service.test.ts +98 -0
  426. package/server/modules/voice/voice.module.ts +47 -0
  427. package/server/modules/voice/voice.routes.ts +113 -0
  428. package/server/modules/voice/voice.service.ts +192 -0
  429. package/server/modules/websocket/README.md +7 -7
  430. package/server/modules/websocket/services/chat-session-writer.service.ts +2 -2
  431. package/server/modules/websocket/services/chat-websocket.service.ts +73 -61
  432. package/server/modules/websocket/services/shell-websocket.service.ts +88 -12
  433. package/server/modules/websocket/services/websocket-server.service.ts +63 -19
  434. package/server/modules/websocket/tests/{chat-image-filter.test.ts → chat-attachment-filter.test.ts} +17 -2
  435. package/server/modules/websocket/tests/shell-websocket.service.test.ts +119 -0
  436. package/server/modules/websocket/tests/websocket-heartbeat.service.test.ts +78 -0
  437. package/server/modules/worktrees/index.ts +2 -0
  438. package/server/modules/worktrees/services/worktree-create-and-open.service.ts +53 -0
  439. package/server/modules/worktrees/services/worktree-create.service.ts +104 -0
  440. package/server/modules/worktrees/services/worktree-git.service.ts +207 -0
  441. package/server/modules/worktrees/services/worktree-list.service.ts +143 -0
  442. package/server/modules/worktrees/services/worktree-merge.service.ts +157 -0
  443. package/server/modules/worktrees/services/worktree-open.service.ts +85 -0
  444. package/server/modules/worktrees/services/worktree-remove.service.ts +88 -0
  445. package/server/modules/worktrees/tests/worktree-create-and-open.service.test.ts +68 -0
  446. package/server/modules/worktrees/tests/worktree-create.service.test.ts +142 -0
  447. package/server/modules/worktrees/tests/worktree-git.service.test.ts +84 -0
  448. package/server/modules/worktrees/tests/worktree-list.service.test.ts +45 -0
  449. package/server/modules/worktrees/tests/worktree-merge.service.test.ts +213 -0
  450. package/server/modules/worktrees/tests/worktree-open.service.test.ts +122 -0
  451. package/server/modules/worktrees/tests/worktree-remove.service.test.ts +227 -0
  452. package/server/modules/worktrees/tests/worktrees.routes.test.ts +199 -0
  453. package/server/modules/worktrees/worktrees.module.ts +113 -0
  454. package/server/modules/worktrees/worktrees.routes.ts +116 -0
  455. package/server/shared/image-attachments.ts +112 -18
  456. package/server/shared/interfaces.ts +29 -19
  457. package/server/shared/tests/image-attachments.test.ts +55 -0
  458. package/server/shared/types.ts +658 -21
  459. package/server/shared/utils.ts +77 -212
  460. package/dist/assets/index-DLmhQ15L.css +0 -32
  461. package/dist-server/server/browser-use-mcp.js.map +0 -1
  462. package/dist-server/server/claude-sdk.js.map +0 -1
  463. package/dist-server/server/cli.js +0 -647
  464. package/dist-server/server/cli.js.map +0 -1
  465. package/dist-server/server/cursor-cli.js.map +0 -1
  466. package/dist-server/server/middleware/auth.js.map +0 -1
  467. package/dist-server/server/modules/providers/tests/provider-image-history.test.js.map +0 -1
  468. package/dist-server/server/modules/websocket/tests/chat-image-filter.test.js.map +0 -1
  469. package/dist-server/server/openai-codex.js.map +0 -1
  470. package/dist-server/server/opencode-cli.js.map +0 -1
  471. package/dist-server/server/opencode-cli.test.js.map +0 -1
  472. package/dist-server/server/routes/agent.js +0 -1155
  473. package/dist-server/server/routes/agent.js.map +0 -1
  474. package/dist-server/server/routes/auth.js +0 -119
  475. package/dist-server/server/routes/auth.js.map +0 -1
  476. package/dist-server/server/routes/commands.js +0 -492
  477. package/dist-server/server/routes/commands.js.map +0 -1
  478. package/dist-server/server/routes/cursor.js +0 -49
  479. package/dist-server/server/routes/cursor.js.map +0 -1
  480. package/dist-server/server/routes/git.js +0 -1389
  481. package/dist-server/server/routes/git.js.map +0 -1
  482. package/dist-server/server/routes/git.test.js.map +0 -1
  483. package/dist-server/server/routes/mcp-utils.js +0 -29
  484. package/dist-server/server/routes/mcp-utils.js.map +0 -1
  485. package/dist-server/server/routes/plugins.js +0 -266
  486. package/dist-server/server/routes/plugins.js.map +0 -1
  487. package/dist-server/server/routes/settings.js +0 -249
  488. package/dist-server/server/routes/settings.js.map +0 -1
  489. package/dist-server/server/routes/taskmaster.js +0 -1362
  490. package/dist-server/server/routes/taskmaster.js.map +0 -1
  491. package/dist-server/server/routes/tests/commands.test.js +0 -76
  492. package/dist-server/server/routes/tests/commands.test.js.map +0 -1
  493. package/dist-server/server/routes/user.js +0 -116
  494. package/dist-server/server/routes/user.js.map +0 -1
  495. package/dist-server/server/services/notification-orchestrator.js +0 -2
  496. package/dist-server/server/services/notification-orchestrator.js.map +0 -1
  497. package/dist-server/server/services/tests/notification-orchestrator.test.js +0 -64
  498. package/dist-server/server/services/tests/notification-orchestrator.test.js.map +0 -1
  499. package/dist-server/server/services/vapid-keys.js.map +0 -1
  500. package/dist-server/server/utils/colors.js +0 -20
  501. package/dist-server/server/utils/colors.js.map +0 -1
  502. package/dist-server/server/utils/commandParser.js +0 -255
  503. package/dist-server/server/utils/commandParser.js.map +0 -1
  504. package/dist-server/server/utils/gitConfig.js +0 -37
  505. package/dist-server/server/utils/gitConfig.js.map +0 -1
  506. package/dist-server/server/utils/mcp-detector.js +0 -134
  507. package/dist-server/server/utils/mcp-detector.js.map +0 -1
  508. package/dist-server/server/utils/plugin-loader.js.map +0 -1
  509. package/dist-server/server/utils/plugin-process-manager.js.map +0 -1
  510. package/dist-server/server/utils/runtime-paths.js +0 -30
  511. package/dist-server/server/utils/runtime-paths.js.map +0 -1
  512. package/dist-server/server/utils/taskmaster-websocket.js +0 -124
  513. package/dist-server/server/utils/taskmaster-websocket.js.map +0 -1
  514. package/dist-server/server/utils/url-detection.js +0 -58
  515. package/dist-server/server/utils/url-detection.js.map +0 -1
  516. package/dist-server/server/voice-proxy.js +0 -226
  517. package/dist-server/server/voice-proxy.js.map +0 -1
  518. package/server/cli.js +0 -695
  519. package/server/index.js +0 -1651
  520. package/server/routes/agent.js +0 -1257
  521. package/server/routes/auth.js +0 -137
  522. package/server/routes/cursor.js +0 -52
  523. package/server/routes/mcp-utils.js +0 -31
  524. package/server/routes/plugins.js +0 -307
  525. package/server/routes/settings.js +0 -282
  526. package/server/routes/taskmaster.js +0 -1470
  527. package/server/routes/tests/commands.test.js +0 -82
  528. package/server/routes/user.js +0 -124
  529. package/server/services/notification-orchestrator.js +0 -7
  530. package/server/services/tests/notification-orchestrator.test.js +0 -80
  531. package/server/utils/colors.js +0 -21
  532. package/server/utils/commandParser.js +0 -305
  533. package/server/utils/gitConfig.js +0 -35
  534. package/server/utils/mcp-detector.js +0 -147
  535. package/server/utils/runtime-paths.js +0 -37
  536. package/server/utils/taskmaster-websocket.js +0 -135
  537. package/server/utils/url-detection.js +0 -71
  538. package/server/voice-proxy.js +0 -224
  539. /package/server/constants/{config.js → config.ts} +0 -0
@@ -1,18 +1,31 @@
1
- import { promises as fs } from "fs";
2
- import os from "os";
1
+ // @ts-nocheck -- temporary while command handlers are extracted into the injected service.
3
2
  import path from "path";
4
3
 
5
4
  import express from "express";
6
5
 
7
- import { providerModelsService } from "../modules/providers/services/provider-models.service.js";
8
- import { parseFrontMatter } from "../shared/frontmatter.js";
9
- import { findAppRoot, getModuleDir } from "../utils/runtime-paths.js";
10
-
11
- const __dirname = getModuleDir(import.meta.url);
12
- // This route reads the top-level package.json for the status command, so it needs the real
13
- // app root even after compilation moves the route file under dist-server/server/routes.
14
- const APP_ROOT = findAppRoot(__dirname);
6
+ import { parseFrontMatter } from "../../shared/frontmatter.js";
7
+
8
+ type CommandsRouterDependencies = {
9
+ fileSystem: typeof import('node:fs/promises');
10
+ homeDirectory(): string;
11
+ appRoot: string;
12
+ models: typeof import('../providers/index.js').providerModelsService;
13
+ runtime: {
14
+ uptime(): number;
15
+ memoryUsage(): NodeJS.MemoryUsage;
16
+ version: string;
17
+ platform: NodeJS.Platform;
18
+ pid: number;
19
+ };
20
+ };
15
21
 
22
+ /** Creates Commands routes around explicit filesystem, model-catalog, and runtime adapters. */
23
+ export function createCommandsRouter(dependencies: CommandsRouterDependencies): express.Router {
24
+ const fs = dependencies.fileSystem;
25
+ const os = { homedir: dependencies.homeDirectory };
26
+ const APP_ROOT = dependencies.appRoot;
27
+ const providerModelsService = dependencies.models;
28
+ const process = dependencies.runtime;
16
29
  const router = express.Router();
17
30
 
18
31
  const MODEL_PROVIDERS = ["claude", "cursor", "codex", "opencode"];
@@ -33,30 +46,26 @@ const readModelProvider = (value) => {
33
46
  return MODEL_PROVIDERS.includes(normalized) ? normalized : "claude";
34
47
  };
35
48
 
36
- const hasConcreteSessionId = (value) =>
37
- typeof value === "string" && value.trim().length > 0;
38
-
39
- const resolveCommandModel = async (provider, catalog, sessionId) => {
40
- if (!hasConcreteSessionId(sessionId)) {
41
- return catalog.DEFAULT;
42
- }
43
-
44
- const currentActiveModel = await providerModelsService.getCurrentActiveModel(
45
- provider,
46
- sessionId,
47
- );
48
- return currentActiveModel?.model || catalog.DEFAULT;
49
+ /**
50
+ * Resolves the model a command should report.
51
+ *
52
+ * `context.model` is what the composer would send right now, so it stands in
53
+ * for a chat that has no session row yet; the service prefers the session's own
54
+ * recorded model whenever there is one.
55
+ */
56
+ const resolveCommandModel = async (modelsService, provider, context) => {
57
+ const resolved = await modelsService.resolveSessionModel(provider, {
58
+ sessionId: context?.sessionId,
59
+ requestedModel: context?.model,
60
+ });
61
+ return resolved.model;
49
62
  };
50
63
 
51
- export const executeModelsCommand = async (args, context) => {
64
+ const executeModelsCommand = async (args, context, modelsService) => {
52
65
  const currentProvider = readModelProvider(context?.provider);
53
- const result = await providerModelsService.getProviderModels(currentProvider);
66
+ const result = await modelsService.getProviderModels(currentProvider);
54
67
  const catalog = result.models;
55
- const currentModel = await resolveCommandModel(
56
- currentProvider,
57
- catalog,
58
- context?.sessionId,
59
- );
68
+ const currentModel = await resolveCommandModel(modelsService, currentProvider, context);
60
69
  const availableModels = catalog.OPTIONS.map((option) => option.value);
61
70
  const availableOptions = catalog.OPTIONS.map((option) => ({
62
71
  value: option.value,
@@ -249,13 +258,12 @@ Custom commands can be created in:
249
258
  };
250
259
  },
251
260
 
252
- "/models": executeModelsCommand,
261
+ "/models": (args, context) => executeModelsCommand(args, context, providerModelsService),
253
262
 
254
263
  "/cost": async (args, context) => {
255
264
  const tokenUsage = context?.tokenUsage || {};
256
265
  const provider = readModelProvider(context?.provider);
257
- const catalog = (await providerModelsService.getProviderModels(provider)).models;
258
- const model = await resolveCommandModel(provider, catalog, context?.sessionId);
266
+ const model = await resolveCommandModel(providerModelsService, provider, context);
259
267
 
260
268
  const reportedUsed =
261
269
  Number(
@@ -357,8 +365,7 @@ Custom commands can be created in:
357
365
  : `${uptimeMinutes}m`;
358
366
 
359
367
  const statusProvider = readModelProvider(context?.provider);
360
- const statusCatalog = (await providerModelsService.getProviderModels(statusProvider)).models;
361
- const model = await resolveCommandModel(statusProvider, statusCatalog, context?.sessionId);
368
+ const model = await resolveCommandModel(providerModelsService, statusProvider, context);
362
369
  const memoryUsage = process.memoryUsage();
363
370
 
364
371
  return {
@@ -593,4 +600,5 @@ router.post("/execute", async (req, res) => {
593
600
  }
594
601
  });
595
602
 
596
- export default router;
603
+ return router;
604
+ }
@@ -0,0 +1,2 @@
1
+ // commandsRoutes: used by the server entrypoint to mount protected slash-command endpoints.
2
+ export { commandsRoutes } from './commands.module.js';
@@ -0,0 +1,119 @@
1
+ import assert from 'node:assert/strict';
2
+ import { once } from 'node:events';
3
+ import type { AddressInfo } from 'node:net';
4
+ import test from 'node:test';
5
+
6
+ import express from 'express';
7
+
8
+ import { createCommandsRouter } from '../commands.routes.js';
9
+
10
+ /**
11
+ * Stands in for `providerModelsService`. `resolveSessionModel` mirrors the real
12
+ * precedence closely enough for the command handlers: a model recorded for the
13
+ * session wins, otherwise the client's requested model, otherwise the catalog
14
+ * default.
15
+ */
16
+ function createModelsService(sessionModels: Record<string, string> = {}) {
17
+ return {
18
+ getProviderModels: async () => ({
19
+ models: { OPTIONS: [{ value: 'default', label: 'Default' }], DEFAULT: 'default' },
20
+ cache: {
21
+ updatedAt: '2026-01-01T00:00:00.000Z',
22
+ expiresAt: '2026-01-02T00:00:00.000Z',
23
+ source: 'fresh' as const,
24
+ },
25
+ }),
26
+ getCurrentActiveModel: async () => ({ model: 'default' }),
27
+ setSessionModel: () => null,
28
+ resolveSessionModel: async (
29
+ provider: string,
30
+ options: { sessionId?: string | null; requestedModel?: string | null } = {},
31
+ ) => {
32
+ const recorded = options.sessionId ? sessionModels[options.sessionId] : undefined;
33
+ const model = recorded || options.requestedModel || 'default';
34
+ return {
35
+ provider,
36
+ sessionId: options.sessionId ?? null,
37
+ model,
38
+ source: model === 'default' ? 'default' : 'session',
39
+ };
40
+ },
41
+ resolveResumeModel: async () => undefined,
42
+ clearCache: () => undefined,
43
+ };
44
+ }
45
+
46
+ async function executeCommand(
47
+ commandName: string,
48
+ context: Record<string, unknown>,
49
+ sessionModels: Record<string, string> = {},
50
+ ): Promise<Record<string, unknown>> {
51
+ const router = createCommandsRouter({
52
+ fileSystem: {
53
+ readFile: async () => JSON.stringify({ name: 'claude-code-ui', version: '0.0.0-test' }),
54
+ } as unknown as typeof import('node:fs/promises'),
55
+ homeDirectory: () => '/home/test',
56
+ appRoot: '/app',
57
+ models: createModelsService(sessionModels) as never,
58
+ runtime: {
59
+ uptime: () => 0,
60
+ memoryUsage: () => ({ rss: 0, heapTotal: 0, heapUsed: 0, external: 0, arrayBuffers: 0 }),
61
+ version: 'v22', platform: 'linux', pid: 1,
62
+ },
63
+ });
64
+ const app = express().use(express.json()).use('/api/commands', router);
65
+ const server = app.listen(0, '127.0.0.1');
66
+ await once(server, 'listening');
67
+ try {
68
+ const address = server.address() as AddressInfo;
69
+ const response = await fetch(`http://127.0.0.1:${address.port}/api/commands/execute`, {
70
+ method: 'POST', headers: { 'content-type': 'application/json' },
71
+ body: JSON.stringify({ commandName, context }),
72
+ });
73
+ assert.equal(response.status, 200);
74
+ return await response.json() as Record<string, unknown>;
75
+ } finally {
76
+ await new Promise<void>((resolve) => server.close(() => resolve()));
77
+ }
78
+ }
79
+
80
+ test('models command returns models only for the active provider using injected catalog', async () => {
81
+ const result = await executeCommand('/models', { provider: 'codex' });
82
+ const data = result.data as Record<string, unknown>;
83
+ assert.deepEqual(Object.keys(data.available as object), ['codex']);
84
+ });
85
+
86
+ test('models command falls back to claude for unsupported providers', async () => {
87
+ const result = await executeCommand('/models', { provider: 'unknown-provider' });
88
+ const data = result.data as { current: { provider: string } };
89
+ assert.equal(data.current.provider, 'claude');
90
+ });
91
+
92
+ test('models command reports the model recorded for the session', async () => {
93
+ const result = await executeCommand(
94
+ '/models',
95
+ { provider: 'claude', sessionId: 'session-1', model: 'sonnet' },
96
+ { 'session-1': 'haiku' },
97
+ );
98
+
99
+ const data = result.data as { current: { model: string } };
100
+ assert.equal(data.current.model, 'haiku');
101
+ });
102
+
103
+ test('models command reports the composer model for a chat with no session yet', async () => {
104
+ const result = await executeCommand('/models', { provider: 'claude', model: 'haiku' });
105
+
106
+ const data = result.data as { current: { model: string } };
107
+ assert.equal(data.current.model, 'haiku');
108
+ });
109
+
110
+ test('cost and status commands report the same resolved model as /models', async () => {
111
+ const context = { provider: 'claude', sessionId: 'session-1', model: 'sonnet' };
112
+ const sessionModels = { 'session-1': 'haiku' };
113
+
114
+ const cost = await executeCommand('/cost', context, sessionModels);
115
+ const status = await executeCommand('/status', context, sessionModels);
116
+
117
+ assert.equal((cost.data as { model: string }).model, 'haiku');
118
+ assert.equal((status.data as { model: string }).model, 'haiku');
119
+ });
@@ -6,6 +6,7 @@ export { credentialsDb } from '@/modules/database/repositories/credentials.js';
6
6
  export { githubTokensDb } from '@/modules/database/repositories/github-tokens.js';
7
7
  export { notificationChannelEndpointsDb } from '@/modules/database/repositories/notification-channel-endpoints.js';
8
8
  export { notificationPreferencesDb } from '@/modules/database/repositories/notification-preferences.js';
9
+ // projectsDb: used by Projects, Worktrees, Git, WebSocket, and notification modules to persist and resolve project records.
9
10
  export { projectsDb } from '@/modules/database/repositories/projects.db.js';
10
11
  export { pushSubscriptionsDb } from '@/modules/database/repositories/push-subscriptions.js';
11
12
  export { scanStateDb } from '@/modules/database/repositories/scan-state.db.js';
@@ -402,6 +402,20 @@ const addProviderSessionIdMapping = (db: Database): void => {
402
402
  `);
403
403
  };
404
404
 
405
+ /**
406
+ * Adds the `model` column that records which model each session runs with.
407
+ *
408
+ * Left NULL for pre-existing rows on purpose: the model resolver falls back to
409
+ * the provider-native lookup for sessions the app has never sent on, so a
410
+ * backfilled guess would only mask the real value.
411
+ */
412
+ const addSessionModelColumn = (db: Database): void => {
413
+ const sessionsTableInfo = getTableInfo(db, 'sessions');
414
+ const columnNames = sessionsTableInfo.map((column) => column.name);
415
+
416
+ addColumnToTableIfNotExists(db, 'sessions', columnNames, 'model', 'TEXT');
417
+ };
418
+
405
419
  const ensureProjectsForSessionPaths = (db: Database): void => {
406
420
  if (!tableExists(db, 'sessions')) {
407
421
  return;
@@ -452,6 +466,7 @@ export const runMigrations = (db: Database) => {
452
466
  rebuildSessionsTableWithProjectSchema(db);
453
467
  migrateLegacySessionNames(db);
454
468
  addProviderSessionIdMapping(db);
469
+ addSessionModelColumn(db);
455
470
  ensureProjectsForSessionPaths(db);
456
471
 
457
472
  db.exec('CREATE INDEX IF NOT EXISTS idx_session_ids_lookup ON sessions(session_id)');
@@ -9,13 +9,15 @@ type SessionRow = {
9
9
  project_path: string | null;
10
10
  jsonl_path: string | null;
11
11
  custom_name: string | null;
12
+ /** Model this session runs with; NULL until the app records one for it. */
13
+ model: string | null;
12
14
  isArchived: number;
13
15
  created_at: string;
14
16
  updated_at: string;
15
17
  };
16
18
 
17
19
  const SESSION_ROW_COLUMNS =
18
- 'session_id, provider, provider_session_id, project_path, jsonl_path, custom_name, isArchived, created_at, updated_at';
20
+ 'session_id, provider, provider_session_id, project_path, jsonl_path, custom_name, model, isArchived, created_at, updated_at';
19
21
 
20
22
  const SQLITE_UTC_TIMESTAMP_REGEX = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
21
23
 
@@ -211,6 +213,22 @@ export const sessionsDb = {
211
213
  merge();
212
214
  },
213
215
 
216
+ /**
217
+ * Records the model one session runs with.
218
+ *
219
+ * Called both when the user picks a model for the session and on every send,
220
+ * so the row always reflects what the session last ran with and reopening it
221
+ * restores that model instead of a catalog default.
222
+ */
223
+ setSessionModel(sessionId: string, model: string): void {
224
+ const db = getConnection();
225
+ db.prepare(
226
+ `UPDATE sessions
227
+ SET model = ?
228
+ WHERE session_id = ?`
229
+ ).run(model, sessionId);
230
+ },
231
+
214
232
  updateSessionCustomName(sessionId: string, customName: string): void {
215
233
  const db = getConnection();
216
234
  db.prepare(
@@ -109,6 +109,10 @@ CREATE TABLE IF NOT EXISTS sessions (
109
109
  custom_name TEXT,
110
110
  project_path TEXT,
111
111
  jsonl_path TEXT,
112
+ -- Model this session runs with. Written when the user picks a model for the
113
+ -- session and on every send, so reopening a session restores the model it
114
+ -- was last used with instead of falling back to the catalog default.
115
+ model TEXT,
112
116
  isArchived BOOLEAN DEFAULT 0,
113
117
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
114
118
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
@@ -0,0 +1,112 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import fs, { promises as fsPromises } from 'node:fs';
3
+ import os from 'node:os';
4
+
5
+ import mime from 'mime-types';
6
+ import multer from 'multer';
7
+
8
+ import { projectsDb } from '@/modules/database/index.js';
9
+ import { createFileTreeRouter } from '@/modules/file-tree/file-tree.routes.js';
10
+ import { createFileTreeService } from '@/modules/file-tree/file-tree.service.js';
11
+ import type {
12
+ FileTreeFileSystem,
13
+ FileTreeLogger,
14
+ FileTreeProjectGateway,
15
+ FileTreeWorkspaceGateway,
16
+ } from '@/shared/types.js';
17
+ import { WORKSPACES_ROOT, validateWorkspacePath } from '@/shared/utils.js';
18
+
19
+ const MAXIMUM_UPLOAD_SIZE_MEGABYTES = 200;
20
+ const MAXIMUM_UPLOAD_SIZE_BYTES = MAXIMUM_UPLOAD_SIZE_MEGABYTES * 1024 * 1024;
21
+ const MAXIMUM_UPLOAD_FILE_COUNT = 20;
22
+
23
+ function readFileSystemConcurrency(): number {
24
+ const configuredConcurrency = Number.parseInt(process.env.FS_CONCURRENCY ?? '', 10);
25
+ return Number.isFinite(configuredConcurrency) && configuredConcurrency > 0
26
+ ? configuredConcurrency
27
+ : 64;
28
+ }
29
+
30
+ /**
31
+ * Production filesystem adapter owned by the File Tree composition root.
32
+ * Application services receive this complete capability explicitly and never
33
+ * import Node's mutable filesystem APIs themselves.
34
+ */
35
+ const fileTreeFileSystem: FileTreeFileSystem = {
36
+ access: (candidatePath) => fsPromises.access(candidatePath),
37
+ stat: (candidatePath) => fsPromises.stat(candidatePath),
38
+ lstat: (candidatePath) => fsPromises.lstat(candidatePath),
39
+ readdir: (directoryPath) => fsPromises.readdir(directoryPath, { withFileTypes: true }),
40
+ realpath: (candidatePath) => fsPromises.realpath(candidatePath),
41
+ readTextFile: (filePath) => fsPromises.readFile(filePath, 'utf8'),
42
+ writeTextFile: (filePath, content) => fsPromises.writeFile(filePath, content, 'utf8'),
43
+ async makeDirectory(directoryPath, recursive) {
44
+ await fsPromises.mkdir(directoryPath, { recursive });
45
+ },
46
+ rename: (oldPath, newPath) => fsPromises.rename(oldPath, newPath),
47
+ async removeDirectory(directoryPath) {
48
+ await fsPromises.rm(directoryPath, { recursive: true, force: true });
49
+ },
50
+ unlink: (filePath) => fsPromises.unlink(filePath),
51
+ copyFile: (sourcePath, destinationPath) => fsPromises.copyFile(sourcePath, destinationPath),
52
+ createReadStream: (filePath) => fs.createReadStream(filePath),
53
+ };
54
+
55
+ /**
56
+ * Database boundary used only by File Tree production composition.
57
+ * The Database module is consumed through its barrel; services and routes see
58
+ * only the narrow project-path lookup contract.
59
+ */
60
+ const fileTreeProjects: FileTreeProjectGateway = {
61
+ getProjectPathById: (projectId) => projectsDb.getProjectPathById(projectId),
62
+ };
63
+
64
+ /**
65
+ * Workspace-policy boundary used only by File Tree production composition.
66
+ * Keeping both the configured root and symlink-aware validator together makes
67
+ * the path policy explicit for every service instance.
68
+ */
69
+ const fileTreeWorkspace: FileTreeWorkspaceGateway = {
70
+ rootPath: WORKSPACES_ROOT,
71
+ validatePath: (candidatePath) => validateWorkspacePath(candidatePath),
72
+ };
73
+
74
+ const fileTreeLogger: FileTreeLogger = {
75
+ error: (message, error) => console.error(message, error),
76
+ };
77
+
78
+ const fileTreeServices = createFileTreeService({
79
+ fileSystem: fileTreeFileSystem,
80
+ projects: fileTreeProjects,
81
+ workspace: fileTreeWorkspace,
82
+ resolveMimeType: (filePath) => mime.lookup(filePath) || 'application/octet-stream',
83
+ fileSystemConcurrency: readFileSystemConcurrency(),
84
+ logger: fileTreeLogger,
85
+ });
86
+
87
+ const fileUploadMiddleware = multer({
88
+ storage: multer.diskStorage({
89
+ destination: os.tmpdir(),
90
+ filename: (_request, _file, callback) => {
91
+ callback(null, `cloudcli-file-upload-${randomUUID()}`);
92
+ },
93
+ }),
94
+ limits: {
95
+ fileSize: MAXIMUM_UPLOAD_SIZE_BYTES,
96
+ files: MAXIMUM_UPLOAD_FILE_COUNT,
97
+ },
98
+ }).array('files', MAXIMUM_UPLOAD_FILE_COUNT);
99
+
100
+ /**
101
+ * File Tree router used by the server entrypoint to mount the authenticated
102
+ * browsing, editing, file-management, and upload API under `/api/file-tree`.
103
+ */
104
+ export const fileTreeRoutes = createFileTreeRouter(
105
+ fileTreeServices,
106
+ fileUploadMiddleware,
107
+ {
108
+ maximumFileSizeMegabytes: MAXIMUM_UPLOAD_SIZE_MEGABYTES,
109
+ maximumFileCount: MAXIMUM_UPLOAD_FILE_COUNT,
110
+ },
111
+ fileTreeLogger,
112
+ );