@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
@@ -0,0 +1,98 @@
1
+ import assert from 'node:assert/strict';
2
+ import test from 'node:test';
3
+
4
+ import { createVoiceService } from '../voice.service.js';
5
+
6
+ const defaults = {
7
+ baseUrl: 'https://voice.example/v1',
8
+ apiKey: 'server-key',
9
+ sttModel: 'whisper-1',
10
+ ttsModel: 'tts-1',
11
+ ttsVoice: 'alloy',
12
+ };
13
+
14
+ test('reports whether the server-controlled backend is configured', () => {
15
+ const service = createVoiceService({
16
+ defaults: { ...defaults, baseUrl: '' },
17
+ timeoutMs: 1_000,
18
+ fetchBackend: async () => {
19
+ throw new Error('fetch should not run');
20
+ },
21
+ });
22
+
23
+ assert.deepEqual(service.getHealth(), { configured: false });
24
+ });
25
+
26
+ test('transcribes with injected fetch and request-level credential/model overrides', async () => {
27
+ let requestedUrl = '';
28
+ let requestedOptions: RequestInit | undefined;
29
+ const service = createVoiceService({
30
+ defaults,
31
+ timeoutMs: 1_000,
32
+ fetchBackend: async (url, options) => {
33
+ requestedUrl = url;
34
+ requestedOptions = options;
35
+ return new Response(JSON.stringify({ text: 'hello' }), { status: 200 });
36
+ },
37
+ });
38
+
39
+ const result = await service.transcribe({
40
+ audio: {
41
+ bytes: Buffer.from('audio'),
42
+ mimeType: 'audio/webm',
43
+ fileName: 'recording.webm',
44
+ },
45
+ overrides: { apiKey: 'request-key', sttModel: 'custom-whisper' },
46
+ });
47
+
48
+ assert.deepEqual(result, { ok: true, value: { text: 'hello' } });
49
+ assert.equal(requestedUrl, 'https://voice.example/v1/audio/transcriptions');
50
+ assert.equal((requestedOptions?.headers as Record<string, string>).Authorization, 'Bearer request-key');
51
+ assert.equal((requestedOptions?.body as FormData).get('model'), 'custom-whisper');
52
+ });
53
+
54
+ test('forwards the explicit TTS format and maps backend authentication failures', async () => {
55
+ let requestBody = '';
56
+ const service = createVoiceService({
57
+ defaults,
58
+ timeoutMs: 1_000,
59
+ fetchBackend: async (_url, options) => {
60
+ requestBody = String(options.body);
61
+ return new Response('unauthorized', { status: 401 });
62
+ },
63
+ });
64
+
65
+ const result = await service.synthesizeSpeech({
66
+ text: 'Read this',
67
+ overrides: { ttsFormat: 'wav' },
68
+ });
69
+
70
+ assert.deepEqual(JSON.parse(requestBody), {
71
+ model: 'tts-1',
72
+ voice: 'alloy',
73
+ input: 'Read this',
74
+ response_format: 'wav',
75
+ });
76
+ assert.deepEqual(result, {
77
+ ok: false,
78
+ status: 502,
79
+ error: 'Voice backend rejected the request (check the API key).',
80
+ });
81
+ });
82
+
83
+ test('blocks link-local metadata destinations before calling the fetch adapter', async () => {
84
+ let fetchCalls = 0;
85
+ const service = createVoiceService({
86
+ defaults: { ...defaults, baseUrl: 'http://169.254.169.254/latest' },
87
+ timeoutMs: 1_000,
88
+ fetchBackend: async () => {
89
+ fetchCalls += 1;
90
+ return new Response();
91
+ },
92
+ });
93
+
94
+ const result = await service.synthesizeSpeech({ text: 'hello', overrides: {} });
95
+
96
+ assert.deepEqual(result, { ok: false, status: 400, error: 'Invalid voice backend URL.' });
97
+ assert.equal(fetchCalls, 0);
98
+ });
@@ -0,0 +1,47 @@
1
+ import multer from 'multer';
2
+
3
+ import { createVoiceRouter } from './voice.routes.js';
4
+ import { createVoiceService } from './voice.service.js';
5
+
6
+ const DEFAULT_VOICE_TIMEOUT_MS = 300_000;
7
+ const parsedTimeoutMs = Number(process.env.VOICE_TIMEOUT_MS);
8
+ const voiceTimeoutMs = Number.isFinite(parsedTimeoutMs) && parsedTimeoutMs > 0
9
+ ? parsedTimeoutMs
10
+ : DEFAULT_VOICE_TIMEOUT_MS;
11
+
12
+ const voiceService = createVoiceService({
13
+ defaults: {
14
+ // The server-controlled URL is intentional: frontend-configured custom
15
+ // backends are called directly by the browser and never become SSRF input.
16
+ baseUrl: (process.env.VOICE_API_BASE_URL || '').replace(/\/$/, ''),
17
+ apiKey: process.env.VOICE_API_KEY || '',
18
+ sttModel: process.env.VOICE_STT_MODEL || 'whisper-1',
19
+ ttsModel: process.env.VOICE_TTS_MODEL || 'tts-1',
20
+ ttsVoice: process.env.VOICE_TTS_VOICE || 'alloy',
21
+ },
22
+ timeoutMs: voiceTimeoutMs,
23
+ fetchBackend: async (url, options) => {
24
+ const abortController = new AbortController();
25
+ const timeoutHandle = setTimeout(() => abortController.abort(), voiceTimeoutMs);
26
+ try {
27
+ return await fetch(url, {
28
+ redirect: 'manual',
29
+ ...options,
30
+ signal: abortController.signal,
31
+ });
32
+ } finally {
33
+ clearTimeout(timeoutHandle);
34
+ }
35
+ },
36
+ });
37
+
38
+ const audioUpload = multer({
39
+ storage: multer.memoryStorage(),
40
+ limits: { fileSize: 25 * 1024 * 1024 },
41
+ });
42
+
43
+ /** Voice router assembled for the server entrypoint. */
44
+ export const voiceRoutes = createVoiceRouter({
45
+ voiceService,
46
+ parseAudioUpload: audioUpload.single('audio'),
47
+ });
@@ -0,0 +1,113 @@
1
+ import { Readable } from 'node:stream';
2
+
3
+ import express from 'express';
4
+
5
+ import type { VoiceRequestOverrides, VoiceService, VoiceServiceResult } from '@/shared/types.js';
6
+ import { asyncHandler } from '@/shared/utils.js';
7
+
8
+ type VoiceRouterDependencies = {
9
+ voiceService: VoiceService;
10
+ parseAudioUpload: express.RequestHandler;
11
+ };
12
+
13
+ function readHeaderValue(value: string | string[] | undefined): string | undefined {
14
+ const normalizedValue = Array.isArray(value) ? value[0] : value;
15
+ const trimmedValue = normalizedValue?.trim();
16
+ return trimmedValue || undefined;
17
+ }
18
+
19
+ function parseVoiceOverrides(request: express.Request): VoiceRequestOverrides {
20
+ return {
21
+ apiKey: readHeaderValue(request.headers['x-voice-api-key']),
22
+ sttModel: readHeaderValue(request.headers['x-voice-stt-model']),
23
+ ttsModel: readHeaderValue(request.headers['x-voice-tts-model']),
24
+ ttsVoice: readHeaderValue(request.headers['x-voice-tts-voice']),
25
+ ttsFormat: readHeaderValue(request.headers['x-voice-tts-format']),
26
+ };
27
+ }
28
+
29
+ function sendFailure<TValue>(
30
+ response: express.Response,
31
+ result: VoiceServiceResult<TValue>,
32
+ ): result is Extract<VoiceServiceResult<TValue>, { ok: false }> {
33
+ if (result.ok) {
34
+ return false;
35
+ }
36
+
37
+ response.status(result.status).json({ error: result.error });
38
+ return true;
39
+ }
40
+
41
+ /**
42
+ * Creates the transport-only router used by the Voice composition root. It is
43
+ * exported for Voice route tests; other modules consume only the composed
44
+ * router exposed from the Voice barrel.
45
+ */
46
+ export function createVoiceRouter(dependencies: VoiceRouterDependencies): express.Router {
47
+ const router = express.Router();
48
+
49
+ router.get('/health', (_request, response) => {
50
+ response.json(dependencies.voiceService.getHealth());
51
+ });
52
+
53
+ router.post('/transcribe', (request, response, next) => {
54
+ dependencies.parseAudioUpload(request, response, (uploadError?: unknown) => {
55
+ if (uploadError) {
56
+ const message = uploadError instanceof Error ? uploadError.message : String(uploadError);
57
+ response.status(400).json({ error: message });
58
+ return;
59
+ }
60
+
61
+ // Multer uses a callback API, so bridge its parsed request into the async
62
+ // service call and forward unexpected rejections to Express middleware.
63
+ void (async () => {
64
+ if (!request.file) {
65
+ response.status(400).json({ error: 'No audio uploaded' });
66
+ return;
67
+ }
68
+
69
+ const result = await dependencies.voiceService.transcribe({
70
+ audio: {
71
+ bytes: request.file.buffer,
72
+ mimeType: request.file.mimetype || 'audio/webm',
73
+ fileName: request.file.originalname || 'recording.webm',
74
+ },
75
+ overrides: parseVoiceOverrides(request),
76
+ });
77
+
78
+ if (sendFailure(response, result)) {
79
+ return;
80
+ }
81
+
82
+ response.json(result.value);
83
+ })().catch(next);
84
+ });
85
+ });
86
+
87
+ router.post('/tts', asyncHandler(async (request, response) => {
88
+ const text = request.body?.text;
89
+ if (typeof text !== 'string' || !text.trim()) {
90
+ response.status(400).json({ error: 'text required' });
91
+ return;
92
+ }
93
+
94
+ const result = await dependencies.voiceService.synthesizeSpeech({
95
+ text,
96
+ overrides: parseVoiceOverrides(request),
97
+ });
98
+ if (sendFailure(response, result)) {
99
+ return;
100
+ }
101
+
102
+ response.setHeader('Content-Type', result.value.contentType);
103
+ response.setHeader('Cache-Control', 'no-store');
104
+ if (!result.value.body) {
105
+ response.end();
106
+ return;
107
+ }
108
+
109
+ Readable.fromWeb(result.value.body).on('error', (error) => response.destroy(error)).pipe(response);
110
+ }));
111
+
112
+ return router;
113
+ }
@@ -0,0 +1,192 @@
1
+ import type {
2
+ VoiceAudioUpload,
3
+ VoiceRequestOverrides,
4
+ VoiceService,
5
+ VoiceServiceResult,
6
+ VoiceSpeechPayload,
7
+ } from '@/shared/types.js';
8
+
9
+ type VoiceServiceDependencies = {
10
+ defaults: {
11
+ baseUrl: string;
12
+ apiKey: string;
13
+ sttModel: string;
14
+ ttsModel: string;
15
+ ttsVoice: string;
16
+ };
17
+ timeoutMs: number;
18
+ fetchBackend(url: string, options: RequestInit): Promise<Response>;
19
+ };
20
+
21
+ type ResolvedVoiceConfig = VoiceServiceDependencies['defaults'] & {
22
+ ttsFormat: string;
23
+ };
24
+
25
+ function resolveVoiceConfig(
26
+ defaults: VoiceServiceDependencies['defaults'],
27
+ overrides: VoiceRequestOverrides,
28
+ ): ResolvedVoiceConfig {
29
+ return {
30
+ baseUrl: defaults.baseUrl,
31
+ apiKey: overrides.apiKey || defaults.apiKey,
32
+ sttModel: overrides.sttModel || defaults.sttModel,
33
+ ttsModel: overrides.ttsModel || defaults.ttsModel,
34
+ ttsVoice: overrides.ttsVoice || defaults.ttsVoice,
35
+ ttsFormat: overrides.ttsFormat?.trim() ?? '',
36
+ };
37
+ }
38
+
39
+ function validateBackendBaseUrl(baseUrl: string): boolean {
40
+ try {
41
+ const parsedUrl = new URL(baseUrl);
42
+ if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {
43
+ return false;
44
+ }
45
+
46
+ // Local and private backends are supported intentionally. Only link-local
47
+ // metadata addresses remain blocked as a defense in depth measure.
48
+ return parsedUrl.hostname !== '169.254.169.254'
49
+ && !parsedUrl.hostname.startsWith('169.254.');
50
+ } catch {
51
+ return false;
52
+ }
53
+ }
54
+
55
+ function authorizationHeader(apiKey: string): Record<string, string> {
56
+ return apiKey ? { Authorization: `Bearer ${apiKey}` } : {};
57
+ }
58
+
59
+ function backendFailure(status: number, responseText?: string): VoiceServiceResult<never> {
60
+ if (status === 401 || status === 403) {
61
+ return {
62
+ ok: false,
63
+ status: 502,
64
+ error: 'Voice backend rejected the request (check the API key).',
65
+ };
66
+ }
67
+
68
+ return {
69
+ ok: false,
70
+ status,
71
+ error: responseText || 'voice backend error',
72
+ };
73
+ }
74
+
75
+ function unreachableBackendFailure(error: unknown, timeoutMs: number): VoiceServiceResult<never> {
76
+ if (error instanceof Error && error.name === 'AbortError') {
77
+ return {
78
+ ok: false,
79
+ status: 504,
80
+ error: `Voice backend timed out after ${Math.round(timeoutMs / 1000)}s. Check your voice backend.`,
81
+ };
82
+ }
83
+
84
+ const message = error instanceof Error ? error.message : String(error);
85
+ return {
86
+ ok: false,
87
+ status: 502,
88
+ error: `Voice backend unreachable: ${message}`,
89
+ };
90
+ }
91
+
92
+ function validateConfiguredBackend(config: ResolvedVoiceConfig): VoiceServiceResult<never> | null {
93
+ if (!config.baseUrl) {
94
+ return { ok: false, status: 503, error: 'No voice backend configured' };
95
+ }
96
+
97
+ if (!validateBackendBaseUrl(config.baseUrl)) {
98
+ return { ok: false, status: 400, error: 'Invalid voice backend URL.' };
99
+ }
100
+
101
+ return null;
102
+ }
103
+
104
+ function createTranscriptionFormData(audio: VoiceAudioUpload, sttModel: string): FormData {
105
+ const formData = new FormData();
106
+ formData.append('file', new Blob([audio.bytes], { type: audio.mimeType }), audio.fileName);
107
+ formData.append('model', sttModel);
108
+ return formData;
109
+ }
110
+
111
+ /**
112
+ * Creates the Voice application service used by the Voice composition root and
113
+ * its unit tests. The outbound request function and server configuration are
114
+ * required so the service never reads globals or creates production defaults.
115
+ */
116
+ export function createVoiceService(dependencies: VoiceServiceDependencies): VoiceService {
117
+ return {
118
+ getHealth: () => ({ configured: Boolean(dependencies.defaults.baseUrl) }),
119
+
120
+ async transcribe(input) {
121
+ const config = resolveVoiceConfig(dependencies.defaults, input.overrides);
122
+ const configurationFailure = validateConfiguredBackend(config);
123
+ if (configurationFailure) {
124
+ return configurationFailure;
125
+ }
126
+
127
+ try {
128
+ const response = await dependencies.fetchBackend(
129
+ `${config.baseUrl}/audio/transcriptions`,
130
+ {
131
+ method: 'POST',
132
+ headers: authorizationHeader(config.apiKey),
133
+ body: createTranscriptionFormData(input.audio, config.sttModel),
134
+ },
135
+ );
136
+ const responseText = await response.text();
137
+ if (!response.ok) {
138
+ return backendFailure(response.status, responseText);
139
+ }
140
+
141
+ try {
142
+ const parsed = JSON.parse(responseText) as { text?: unknown };
143
+ return {
144
+ ok: true,
145
+ value: { text: typeof parsed.text === 'string' ? parsed.text : '' },
146
+ };
147
+ } catch {
148
+ return { ok: true, value: { text: responseText } };
149
+ }
150
+ } catch (error) {
151
+ return unreachableBackendFailure(error, dependencies.timeoutMs);
152
+ }
153
+ },
154
+
155
+ async synthesizeSpeech(input) {
156
+ const config = resolveVoiceConfig(dependencies.defaults, input.overrides);
157
+ const configurationFailure = validateConfiguredBackend(config);
158
+ if (configurationFailure) {
159
+ return configurationFailure;
160
+ }
161
+
162
+ try {
163
+ const response = await dependencies.fetchBackend(`${config.baseUrl}/audio/speech`, {
164
+ method: 'POST',
165
+ headers: {
166
+ 'Content-Type': 'application/json',
167
+ ...authorizationHeader(config.apiKey),
168
+ },
169
+ body: JSON.stringify({
170
+ model: config.ttsModel,
171
+ voice: config.ttsVoice,
172
+ input: input.text,
173
+ ...(config.ttsFormat ? { response_format: config.ttsFormat } : {}),
174
+ }),
175
+ });
176
+
177
+ if (!response.ok) {
178
+ const responseText = await response.text().catch(() => 'tts failed');
179
+ return backendFailure(response.status, responseText);
180
+ }
181
+
182
+ const value: VoiceSpeechPayload = {
183
+ contentType: response.headers.get('content-type') || 'audio/mpeg',
184
+ body: response.body,
185
+ };
186
+ return { ok: true, value };
187
+ } catch (error) {
188
+ return unreachableBackendFailure(error, dependencies.timeoutMs);
189
+ }
190
+ },
191
+ };
192
+ }
@@ -19,7 +19,7 @@ Shared chat client registry and open-state constant used by other modules.
19
19
 
20
20
  ## Why Dependency Injection Is Used
21
21
 
22
- The module receives runtime-specific functions from `server/index.js` instead of importing legacy runtime files directly.
22
+ The module receives runtime-specific functions from `server/index.ts` instead of importing legacy runtime files directly.
23
23
 
24
24
  Benefits:
25
25
 
@@ -117,8 +117,8 @@ The frontend only ever knows the **app session id** (allocated by
117
117
  `POST /api/providers/sessions` or discovered via the session index). The
118
118
  provider-native id (JSONL file name, CLI resume id) stays inside the backend:
119
119
 
120
- 1. `chat.send` resolves the app id to `{ provider, provider_session_id, project_path }` from the sessions DB.
121
- 2. The provider runtime receives the provider-native id for resume.
120
+ 1. `chat.send` resolves the app id to `{ provider, project_path }` from the sessions DB and passes the **app session id** to the provider runtime.
121
+ 2. The provider runtime resolves the provider-native id from the sessions DB itself (`sessionsService.resolveProviderSessionId`) at the exact points its CLI/SDK needs it (resume flags, provider-owned databases). Runtimes key their process maps by the app session id, so abort and pending-approval lookups use app ids too.
122
122
  3. The `ChatSessionWriter` remaps every outbound event back to the app id, and turns `session_created` announcements into a DB mapping update instead of forwarding them.
123
123
 
124
124
  ### Chat Message Dispatch
@@ -129,10 +129,10 @@ flowchart TD
129
129
  B -->|invalid| C[send kind:protocol_error]
130
130
  B -->|ok| D{data.type}
131
131
 
132
- D -->|chat.send| E[resolve session row -> startRun -> spawnFns provider]
133
- D -->|chat.abort| F[abortFns provider + synthetic complete]
132
+ D -->|chat.send| E[resolve session row -> startRun -> providerRuntimeService.run]
133
+ D -->|chat.abort| F[providerRuntimeService.abort + synthetic complete]
134
134
  D -->|chat.subscribe| G[chat_subscribed ack + attach socket + replay events seq > lastSeq]
135
- D -->|chat.permission-response| H[resolveToolApproval]
135
+ D -->|chat.permission-response| H[providerRuntimeService.resolveToolApproval]
136
136
  D -->|other| I[send kind:protocol_error]
137
137
  ```
138
138
 
@@ -269,5 +269,5 @@ To add a new websocket route:
269
269
  1. Add a new handler service under `services/`.
270
270
  2. Extend `WebSocketServerDependencies` in `websocket-server.service.ts` if needed.
271
271
  3. Add a new pathname branch in the router.
272
- 4. Wire dependency injection from `server/index.js`.
272
+ 4. Wire dependency injection from `server/index.ts`.
273
273
  5. Keep `index.ts` as barrel-only export surface.
@@ -32,8 +32,8 @@ type ChatSessionWriterOptions = {
32
32
  *
33
33
  * It exposes the exact same surface as `WebSocketWriter` (`send`,
34
34
  * `setSessionId`, `getSessionId`, `updateWebSocket`, `userId`,
35
- * `isWebSocketWriter`) so the provider runtimes (`claude-sdk.js`,
36
- * `cursor-cli.js`, ...) need zero changes — but everything that flows through
35
+ * `isWebSocketWriter`) so the provider runtime adapters need zero changes —
36
+ * but everything that flows through
37
37
  * it is translated from the provider's world into the app's protocol:
38
38
  *
39
39
  * - `session_created` events are swallowed and turned into a provider-id