@cloudcli-ai/cloudcli 1.34.0 → 1.35.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 (324) hide show
  1. package/README.de.md +9 -1
  2. package/README.ja.md +8 -0
  3. package/README.ko.md +9 -1
  4. package/README.md +16 -3
  5. package/README.ru.md +9 -1
  6. package/README.tr.md +8 -1
  7. package/README.zh-CN.md +9 -1
  8. package/README.zh-TW.md +9 -1
  9. package/dist/api-docs.html +36 -18
  10. package/dist/assets/index-CtwxqzGG.js +1407 -0
  11. package/dist/assets/index-DlvtxFyt.css +32 -0
  12. package/dist/index.html +2 -2
  13. package/dist-server/server/browser-use-mcp.js +350 -0
  14. package/dist-server/server/browser-use-mcp.js.map +1 -0
  15. package/dist-server/server/claude-sdk.js +25 -5
  16. package/dist-server/server/claude-sdk.js.map +1 -1
  17. package/dist-server/server/cli.js +14 -6
  18. package/dist-server/server/cli.js.map +1 -1
  19. package/dist-server/server/computer-use-agent.js +242 -0
  20. package/dist-server/server/computer-use-agent.js.map +1 -0
  21. package/dist-server/server/computer-use-mcp.js +519 -0
  22. package/dist-server/server/computer-use-mcp.js.map +1 -0
  23. package/dist-server/server/cursor-cli.js +27 -11
  24. package/dist-server/server/cursor-cli.js.map +1 -1
  25. package/dist-server/server/gemini-cli.js +17 -2
  26. package/dist-server/server/gemini-cli.js.map +1 -1
  27. package/dist-server/server/index.js +149 -40
  28. package/dist-server/server/index.js.map +1 -1
  29. package/dist-server/server/load-env.js +1 -1
  30. package/dist-server/server/load-env.js.map +1 -1
  31. package/dist-server/server/modules/browser-use/browser-use-mcp.routes.js +107 -0
  32. package/dist-server/server/modules/browser-use/browser-use-mcp.routes.js.map +1 -0
  33. package/dist-server/server/modules/browser-use/browser-use.routes.js +93 -0
  34. package/dist-server/server/modules/browser-use/browser-use.routes.js.map +1 -0
  35. package/dist-server/server/modules/browser-use/browser-use.service.js +688 -0
  36. package/dist-server/server/modules/browser-use/browser-use.service.js.map +1 -0
  37. package/dist-server/server/modules/browser-use/tests/browser-use.service.test.js +8 -0
  38. package/dist-server/server/modules/browser-use/tests/browser-use.service.test.js.map +1 -0
  39. package/dist-server/server/modules/computer-use/actions/raw-action-dispatcher.js +55 -0
  40. package/dist-server/server/modules/computer-use/actions/raw-action-dispatcher.js.map +1 -0
  41. package/dist-server/server/modules/computer-use/actions/raw-action-types.js +2 -0
  42. package/dist-server/server/modules/computer-use/actions/raw-action-types.js.map +1 -0
  43. package/dist-server/server/modules/computer-use/computer-executor.js +212 -0
  44. package/dist-server/server/modules/computer-use/computer-executor.js.map +1 -0
  45. package/dist-server/server/modules/computer-use/computer-semantics.service.js +422 -0
  46. package/dist-server/server/modules/computer-use/computer-semantics.service.js.map +1 -0
  47. package/dist-server/server/modules/computer-use/computer-use-mcp.routes.js +126 -0
  48. package/dist-server/server/modules/computer-use/computer-use-mcp.routes.js.map +1 -0
  49. package/dist-server/server/modules/computer-use/computer-use.routes.js +196 -0
  50. package/dist-server/server/modules/computer-use/computer-use.routes.js.map +1 -0
  51. package/dist-server/server/modules/computer-use/computer-use.service.js +759 -0
  52. package/dist-server/server/modules/computer-use/computer-use.service.js.map +1 -0
  53. package/dist-server/server/modules/computer-use/desktop-agent-relay.service.js +126 -0
  54. package/dist-server/server/modules/computer-use/desktop-agent-relay.service.js.map +1 -0
  55. package/dist-server/server/modules/computer-use/index.js +3 -0
  56. package/dist-server/server/modules/computer-use/index.js.map +1 -0
  57. package/dist-server/server/modules/computer-use/semantics/adapters/helper-semantic-adapter.js +59 -0
  58. package/dist-server/server/modules/computer-use/semantics/adapters/helper-semantic-adapter.js.map +1 -0
  59. package/dist-server/server/modules/computer-use/semantics/adapters/macos/macos-semantic-adapter.js +5 -0
  60. package/dist-server/server/modules/computer-use/semantics/adapters/macos/macos-semantic-adapter.js.map +1 -0
  61. package/dist-server/server/modules/computer-use/semantics/adapters/semantic-adapter.js +2 -0
  62. package/dist-server/server/modules/computer-use/semantics/adapters/semantic-adapter.js.map +1 -0
  63. package/dist-server/server/modules/computer-use/semantics/adapters/windows/windows-semantic-adapter.js +5 -0
  64. package/dist-server/server/modules/computer-use/semantics/adapters/windows/windows-semantic-adapter.js.map +1 -0
  65. package/dist-server/server/modules/computer-use/semantics/bin/darwin-arm64/CloudCLISemantics +0 -0
  66. package/dist-server/server/modules/computer-use/semantics/bin/darwin-x64/CloudCLISemantics +0 -0
  67. package/dist-server/server/modules/computer-use/semantics/bin/win32-arm64/CloudCLISemantics.exe +0 -0
  68. package/dist-server/server/modules/computer-use/semantics/bin/win32-x64/CloudCLISemantics.exe +0 -0
  69. package/dist-server/server/modules/computer-use/semantics/helpers/semantic-helper-process.js +106 -0
  70. package/dist-server/server/modules/computer-use/semantics/helpers/semantic-helper-process.js.map +1 -0
  71. package/dist-server/server/modules/computer-use/semantics/helpers/semantic-helper-resolver.js +78 -0
  72. package/dist-server/server/modules/computer-use/semantics/helpers/semantic-helper-resolver.js.map +1 -0
  73. package/dist-server/server/modules/computer-use/semantics/semantic-session-store.js +68 -0
  74. package/dist-server/server/modules/computer-use/semantics/semantic-session-store.js.map +1 -0
  75. package/dist-server/server/modules/computer-use/semantics/semantic-tool-dispatcher.js +16 -0
  76. package/dist-server/server/modules/computer-use/semantics/semantic-tool-dispatcher.js.map +1 -0
  77. package/dist-server/server/modules/computer-use/semantics/semantic-types.js +2 -0
  78. package/dist-server/server/modules/computer-use/semantics/semantic-types.js.map +1 -0
  79. package/dist-server/server/modules/database/index.js +1 -0
  80. package/dist-server/server/modules/database/index.js.map +1 -1
  81. package/dist-server/server/modules/database/migrations.js +23 -1
  82. package/dist-server/server/modules/database/migrations.js.map +1 -1
  83. package/dist-server/server/modules/database/repositories/notification-channel-endpoints.js +100 -0
  84. package/dist-server/server/modules/database/repositories/notification-channel-endpoints.js.map +1 -0
  85. package/dist-server/server/modules/database/repositories/notification-preferences.js +8 -0
  86. package/dist-server/server/modules/database/repositories/notification-preferences.js.map +1 -1
  87. package/dist-server/server/modules/database/repositories/sessions.db.js +173 -17
  88. package/dist-server/server/modules/database/repositories/sessions.db.js.map +1 -1
  89. package/dist-server/server/modules/database/schema.js +26 -0
  90. package/dist-server/server/modules/database/schema.js.map +1 -1
  91. package/dist-server/server/modules/database/tests/projects.db.integration.test.js.map +1 -0
  92. package/dist-server/server/modules/database/tests/sessions-provider-mapping.test.js +78 -0
  93. package/dist-server/server/modules/database/tests/sessions-provider-mapping.test.js.map +1 -0
  94. package/dist-server/server/modules/database/{repositories → tests}/sessions.db.integration.test.js +10 -0
  95. package/dist-server/server/modules/database/tests/sessions.db.integration.test.js.map +1 -0
  96. package/dist-server/server/modules/notifications/index.js +4 -0
  97. package/dist-server/server/modules/notifications/index.js.map +1 -0
  98. package/dist-server/server/modules/notifications/notifications.routes.js +115 -0
  99. package/dist-server/server/modules/notifications/notifications.routes.js.map +1 -0
  100. package/dist-server/server/modules/notifications/services/desktop-notification-clients.service.js +97 -0
  101. package/dist-server/server/modules/notifications/services/desktop-notification-clients.service.js.map +1 -0
  102. package/dist-server/server/modules/notifications/services/notification-orchestrator.service.js +229 -0
  103. package/dist-server/server/modules/notifications/services/notification-orchestrator.service.js.map +1 -0
  104. package/dist-server/server/modules/notifications/websocket/desktop-notifications-websocket.service.js +79 -0
  105. package/dist-server/server/modules/notifications/websocket/desktop-notifications-websocket.service.js.map +1 -0
  106. package/dist-server/server/modules/projects/services/project-management.service.js +0 -4
  107. package/dist-server/server/modules/projects/services/project-management.service.js.map +1 -1
  108. package/dist-server/server/modules/projects/services/projects-with-sessions-fetch.service.js +10 -38
  109. package/dist-server/server/modules/projects/services/projects-with-sessions-fetch.service.js.map +1 -1
  110. package/dist-server/server/modules/providers/index.js +1 -0
  111. package/dist-server/server/modules/providers/index.js.map +1 -1
  112. package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js +24 -1
  113. package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js.map +1 -1
  114. package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js +9 -12
  115. package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js.map +1 -1
  116. package/dist-server/server/modules/providers/list/claude/claude-skills.provider.js +7 -0
  117. package/dist-server/server/modules/providers/list/claude/claude-skills.provider.js.map +1 -1
  118. package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js +7 -3
  119. package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js.map +1 -1
  120. package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js +3 -9
  121. package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js.map +1 -1
  122. package/dist-server/server/modules/providers/list/codex/codex-skills.provider.js +7 -0
  123. package/dist-server/server/modules/providers/list/codex/codex-skills.provider.js.map +1 -1
  124. package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js +13 -22
  125. package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js.map +1 -1
  126. package/dist-server/server/modules/providers/list/cursor/cursor-skills.provider.js +7 -0
  127. package/dist-server/server/modules/providers/list/cursor/cursor-skills.provider.js.map +1 -1
  128. package/dist-server/server/modules/providers/list/gemini/gemini-models.provider.js +5 -8
  129. package/dist-server/server/modules/providers/list/gemini/gemini-models.provider.js.map +1 -1
  130. package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js +6 -6
  131. package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js.map +1 -1
  132. package/dist-server/server/modules/providers/list/gemini/gemini-skills.provider.js +7 -0
  133. package/dist-server/server/modules/providers/list/gemini/gemini-skills.provider.js.map +1 -1
  134. package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js +17 -3
  135. package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js.map +1 -1
  136. package/dist-server/server/modules/providers/list/opencode/opencode-sessions.provider.js +9 -10
  137. package/dist-server/server/modules/providers/list/opencode/opencode-sessions.provider.js.map +1 -1
  138. package/dist-server/server/modules/providers/provider.routes.js +123 -1
  139. package/dist-server/server/modules/providers/provider.routes.js.map +1 -1
  140. package/dist-server/server/modules/providers/services/mcp.service.js +23 -0
  141. package/dist-server/server/modules/providers/services/mcp.service.js.map +1 -1
  142. package/dist-server/server/modules/providers/services/provider-capabilities.service.js +65 -0
  143. package/dist-server/server/modules/providers/services/provider-capabilities.service.js.map +1 -0
  144. package/dist-server/server/modules/providers/services/provider-models.service.js +1 -1
  145. package/dist-server/server/modules/providers/services/provider-models.service.js.map +1 -1
  146. package/dist-server/server/modules/providers/services/sessions-watcher.service.js +62 -23
  147. package/dist-server/server/modules/providers/services/sessions-watcher.service.js.map +1 -1
  148. package/dist-server/server/modules/providers/services/sessions.service.js +62 -4
  149. package/dist-server/server/modules/providers/services/sessions.service.js.map +1 -1
  150. package/dist-server/server/modules/providers/services/skills.service.js +11 -0
  151. package/dist-server/server/modules/providers/services/skills.service.js.map +1 -1
  152. package/dist-server/server/modules/providers/shared/skills/skills.provider.js +163 -1
  153. package/dist-server/server/modules/providers/shared/skills/skills.provider.js.map +1 -1
  154. package/dist-server/server/modules/providers/tests/opencode-sessions.test.js +45 -0
  155. package/dist-server/server/modules/providers/tests/opencode-sessions.test.js.map +1 -1
  156. package/dist-server/server/modules/providers/tests/skills.test.js +160 -0
  157. package/dist-server/server/modules/providers/tests/skills.test.js.map +1 -1
  158. package/dist-server/server/modules/websocket/index.js +1 -0
  159. package/dist-server/server/modules/websocket/index.js.map +1 -1
  160. package/dist-server/server/modules/websocket/services/chat-run-registry.service.js +252 -0
  161. package/dist-server/server/modules/websocket/services/chat-run-registry.service.js.map +1 -0
  162. package/dist-server/server/modules/websocket/services/chat-session-writer.service.js +105 -0
  163. package/dist-server/server/modules/websocket/services/chat-session-writer.service.js.map +1 -0
  164. package/dist-server/server/modules/websocket/services/chat-websocket.service.js +218 -156
  165. package/dist-server/server/modules/websocket/services/chat-websocket.service.js.map +1 -1
  166. package/dist-server/server/modules/websocket/services/desktop-agent-websocket.service.js +39 -0
  167. package/dist-server/server/modules/websocket/services/desktop-agent-websocket.service.js.map +1 -0
  168. package/dist-server/server/modules/websocket/services/shell-websocket.service.js +83 -31
  169. package/dist-server/server/modules/websocket/services/shell-websocket.service.js.map +1 -1
  170. package/dist-server/server/modules/websocket/services/websocket-server.service.js +10 -0
  171. package/dist-server/server/modules/websocket/services/websocket-server.service.js.map +1 -1
  172. package/dist-server/server/modules/websocket/tests/chat-run-registry.test.js +216 -0
  173. package/dist-server/server/modules/websocket/tests/chat-run-registry.test.js.map +1 -0
  174. package/dist-server/server/openai-codex.js +24 -14
  175. package/dist-server/server/openai-codex.js.map +1 -1
  176. package/dist-server/server/opencode-cli.js +21 -8
  177. package/dist-server/server/opencode-cli.js.map +1 -1
  178. package/dist-server/server/opencode-cli.test.js +19 -1
  179. package/dist-server/server/opencode-cli.test.js.map +1 -1
  180. package/dist-server/server/routes/settings.js +1 -1
  181. package/dist-server/server/routes/settings.js.map +1 -1
  182. package/dist-server/server/services/notification-orchestrator.js +1 -176
  183. package/dist-server/server/services/notification-orchestrator.js.map +1 -1
  184. package/dist-server/server/services/tests/notification-orchestrator.test.js +64 -0
  185. package/dist-server/server/services/tests/notification-orchestrator.test.js.map +1 -0
  186. package/dist-server/server/shared/{claude-cli-path.test.js → tests/claude-cli-path.test.js} +1 -1
  187. package/dist-server/server/shared/tests/claude-cli-path.test.js.map +1 -0
  188. package/dist-server/server/shared/tests/slice-tail-page.test.js +35 -0
  189. package/dist-server/server/shared/tests/slice-tail-page.test.js.map +1 -0
  190. package/dist-server/server/shared/utils.js +73 -1
  191. package/dist-server/server/shared/utils.js.map +1 -1
  192. package/dist-server/server/voice-proxy.js +226 -0
  193. package/dist-server/server/voice-proxy.js.map +1 -0
  194. package/electron/assets/logo-macos.icns +0 -0
  195. package/electron/assets/logo-macos.png +0 -0
  196. package/electron/assets/logo-windows.ico +0 -0
  197. package/electron/cloud.js +260 -0
  198. package/electron/computerAgent.js +290 -0
  199. package/electron/desktopNotifications.js +378 -0
  200. package/electron/desktopWindow.js +781 -0
  201. package/electron/launcher/index.html +14 -0
  202. package/electron/launcher/launcher.css +801 -0
  203. package/electron/launcher/launcher.js +829 -0
  204. package/electron/localServer.js +550 -0
  205. package/electron/main.js +1060 -0
  206. package/electron/preload.cjs +63 -0
  207. package/electron/scripts/generate-macos-icon.js +62 -0
  208. package/electron/serverInstaller.js +277 -0
  209. package/electron/tabs.js +87 -0
  210. package/electron/viewHost.js +331 -0
  211. package/package.json +86 -5
  212. package/public/api-docs.html +36 -18
  213. package/scripts/build-computer-semantics.mjs +133 -0
  214. package/scripts/copy-computer-semantics-bin.mjs +24 -0
  215. package/scripts/release/build-server-bundle.js +176 -0
  216. package/scripts/release/prepare-desktop-app.js +158 -0
  217. package/server/browser-use-mcp.ts +384 -0
  218. package/server/claude-sdk.js +27 -5
  219. package/server/cli.js +15 -6
  220. package/server/computer-use-agent.ts +279 -0
  221. package/server/computer-use-mcp.ts +574 -0
  222. package/server/cursor-cli.js +27 -11
  223. package/server/gemini-cli.js +17 -2
  224. package/server/index.js +151 -47
  225. package/server/load-env.js +1 -1
  226. package/server/modules/browser-use/browser-use-mcp.routes.ts +120 -0
  227. package/server/modules/browser-use/browser-use.routes.ts +96 -0
  228. package/server/modules/browser-use/browser-use.service.ts +836 -0
  229. package/server/modules/browser-use/tests/browser-use.service.test.ts +10 -0
  230. package/server/modules/computer-use/actions/raw-action-dispatcher.ts +67 -0
  231. package/server/modules/computer-use/actions/raw-action-types.ts +28 -0
  232. package/server/modules/computer-use/computer-executor.ts +242 -0
  233. package/server/modules/computer-use/computer-semantics.service.ts +460 -0
  234. package/server/modules/computer-use/computer-use-mcp.routes.ts +141 -0
  235. package/server/modules/computer-use/computer-use.routes.ts +211 -0
  236. package/server/modules/computer-use/computer-use.service.ts +920 -0
  237. package/server/modules/computer-use/desktop-agent-relay.service.ts +158 -0
  238. package/server/modules/computer-use/index.ts +2 -0
  239. package/server/modules/computer-use/semantics/adapters/helper-semantic-adapter.ts +82 -0
  240. package/server/modules/computer-use/semantics/adapters/macos/macos-semantic-adapter.ts +5 -0
  241. package/server/modules/computer-use/semantics/adapters/semantic-adapter.ts +23 -0
  242. package/server/modules/computer-use/semantics/adapters/windows/windows-semantic-adapter.ts +5 -0
  243. package/server/modules/computer-use/semantics/bin/darwin-arm64/CloudCLISemantics +0 -0
  244. package/server/modules/computer-use/semantics/bin/darwin-x64/CloudCLISemantics +0 -0
  245. package/server/modules/computer-use/semantics/bin/win32-arm64/CloudCLISemantics.exe +0 -0
  246. package/server/modules/computer-use/semantics/bin/win32-x64/CloudCLISemantics.exe +0 -0
  247. package/server/modules/computer-use/semantics/helpers/macos/CloudCLISemantics.swift +467 -0
  248. package/server/modules/computer-use/semantics/helpers/semantic-helper-process.ts +124 -0
  249. package/server/modules/computer-use/semantics/helpers/semantic-helper-resolver.ts +97 -0
  250. package/server/modules/computer-use/semantics/helpers/windows/CloudCLISemantics.csproj +11 -0
  251. package/server/modules/computer-use/semantics/helpers/windows/Program.cs +534 -0
  252. package/server/modules/computer-use/semantics/semantic-session-store.ts +87 -0
  253. package/server/modules/computer-use/semantics/semantic-tool-dispatcher.ts +17 -0
  254. package/server/modules/computer-use/semantics/semantic-types.ts +58 -0
  255. package/server/modules/database/index.ts +1 -0
  256. package/server/modules/database/migrations.ts +25 -0
  257. package/server/modules/database/repositories/notification-channel-endpoints.ts +153 -0
  258. package/server/modules/database/repositories/notification-preferences.ts +12 -1
  259. package/server/modules/database/repositories/sessions.db.ts +227 -23
  260. package/server/modules/database/schema.ts +27 -0
  261. package/server/modules/database/tests/sessions-provider-mapping.test.ts +108 -0
  262. package/server/modules/database/{repositories → tests}/sessions.db.integration.test.ts +12 -0
  263. package/server/modules/notifications/index.ts +13 -0
  264. package/server/modules/notifications/notifications.routes.ts +127 -0
  265. package/server/modules/notifications/services/desktop-notification-clients.service.ts +124 -0
  266. package/server/modules/notifications/services/notification-orchestrator.service.js +288 -0
  267. package/server/modules/notifications/websocket/desktop-notifications-websocket.service.ts +109 -0
  268. package/server/modules/projects/services/project-management.service.ts +0 -8
  269. package/server/modules/projects/services/projects-with-sessions-fetch.service.ts +12 -53
  270. package/server/modules/providers/README.md +1 -1
  271. package/server/modules/providers/index.ts +1 -0
  272. package/server/modules/providers/list/claude/claude-session-synchronizer.provider.ts +26 -1
  273. package/server/modules/providers/list/claude/claude-sessions.provider.ts +9 -14
  274. package/server/modules/providers/list/claude/claude-skills.provider.ts +8 -0
  275. package/server/modules/providers/list/codex/codex-session-synchronizer.provider.ts +7 -3
  276. package/server/modules/providers/list/codex/codex-sessions.provider.ts +3 -12
  277. package/server/modules/providers/list/codex/codex-skills.provider.ts +8 -0
  278. package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +13 -22
  279. package/server/modules/providers/list/cursor/cursor-skills.provider.ts +8 -0
  280. package/server/modules/providers/list/gemini/gemini-models.provider.ts +5 -8
  281. package/server/modules/providers/list/gemini/gemini-sessions.provider.ts +6 -6
  282. package/server/modules/providers/list/gemini/gemini-skills.provider.ts +8 -0
  283. package/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.ts +18 -4
  284. package/server/modules/providers/list/opencode/opencode-sessions.provider.ts +9 -12
  285. package/server/modules/providers/provider.routes.ts +167 -1
  286. package/server/modules/providers/services/mcp.service.ts +26 -0
  287. package/server/modules/providers/services/provider-capabilities.service.ts +91 -0
  288. package/server/modules/providers/services/provider-models.service.ts +1 -1
  289. package/server/modules/providers/services/sessions-watcher.service.ts +71 -25
  290. package/server/modules/providers/services/sessions.service.ts +79 -4
  291. package/server/modules/providers/services/skills.service.ts +25 -1
  292. package/server/modules/providers/shared/skills/skills.provider.ts +223 -0
  293. package/server/modules/providers/tests/opencode-sessions.test.ts +49 -0
  294. package/server/modules/providers/tests/skills.test.ts +212 -0
  295. package/server/modules/websocket/README.md +33 -27
  296. package/server/modules/websocket/index.ts +1 -0
  297. package/server/modules/websocket/services/chat-run-registry.service.ts +327 -0
  298. package/server/modules/websocket/services/chat-session-writer.service.ts +145 -0
  299. package/server/modules/websocket/services/chat-websocket.service.ts +292 -207
  300. package/server/modules/websocket/services/desktop-agent-websocket.service.ts +51 -0
  301. package/server/modules/websocket/services/shell-websocket.service.ts +108 -32
  302. package/server/modules/websocket/services/websocket-server.service.ts +12 -0
  303. package/server/modules/websocket/tests/chat-run-registry.test.ts +244 -0
  304. package/server/openai-codex.js +24 -14
  305. package/server/opencode-cli.js +21 -8
  306. package/server/opencode-cli.test.js +20 -1
  307. package/server/routes/settings.js +6 -1
  308. package/server/services/notification-orchestrator.js +3 -224
  309. package/server/services/tests/notification-orchestrator.test.js +80 -0
  310. package/server/shared/interfaces.ts +15 -0
  311. package/server/shared/tests/slice-tail-page.test.ts +42 -0
  312. package/server/shared/types.ts +84 -1
  313. package/server/shared/utils.ts +95 -1
  314. package/server/voice-proxy.js +224 -0
  315. package/dist/assets/index-73Xw3i9v.css +0 -32
  316. package/dist/assets/index-BIHaviaA.js +0 -1361
  317. package/dist/modelConstants.js +0 -854
  318. package/dist-server/server/modules/database/repositories/projects.db.integration.test.js.map +0 -1
  319. package/dist-server/server/modules/database/repositories/sessions.db.integration.test.js.map +0 -1
  320. package/dist-server/server/shared/claude-cli-path.test.js.map +0 -1
  321. package/public/modelConstants.js +0 -854
  322. /package/dist-server/server/modules/database/{repositories → tests}/projects.db.integration.test.js +0 -0
  323. /package/server/modules/database/{repositories → tests}/projects.db.integration.test.ts +0 -0
  324. /package/server/shared/{claude-cli-path.test.ts → tests/claude-cli-path.test.ts} +0 -0
@@ -0,0 +1,63 @@
1
+ const { contextBridge, ipcRenderer } = require('electron');
2
+
3
+ function isCloudCliAppOrigin(location) {
4
+ if (location.protocol === 'file:') return true;
5
+
6
+ if (location.protocol === 'http:') {
7
+ return location.hostname === '127.0.0.1' || location.hostname === 'localhost';
8
+ }
9
+
10
+ return location.protocol === 'https:' && (
11
+ location.hostname === 'cloudcli.ai' || location.hostname.endsWith('.cloudcli.ai')
12
+ );
13
+ }
14
+
15
+ function onDesktopStateUpdated(callback) {
16
+ const listener = (_event, state) => callback(state);
17
+ ipcRenderer.on('cloudcli-desktop:state-updated', listener);
18
+ return () => {
19
+ ipcRenderer.removeListener('cloudcli-desktop:state-updated', listener);
20
+ };
21
+ }
22
+
23
+ if (isCloudCliAppOrigin(window.location)) {
24
+ contextBridge.exposeInMainWorld('cloudcliDesktopNotifications', {
25
+ getState: () => ipcRenderer.invoke('cloudcli-desktop:get-state'),
26
+ update: (settings) => ipcRenderer.invoke('cloudcli-desktop:update-desktop-notifications', settings),
27
+ onStateUpdated: onDesktopStateUpdated,
28
+ });
29
+ }
30
+
31
+ if (window.location.protocol === 'file:') {
32
+ contextBridge.exposeInMainWorld('cloudcliDesktop', {
33
+ connectCloud: () => ipcRenderer.invoke('cloudcli-desktop:connect-cloud'),
34
+ disconnectCloud: () => ipcRenderer.invoke('cloudcli-desktop:disconnect-cloud'),
35
+ copyDiagnostics: () => ipcRenderer.invoke('cloudcli-desktop:copy-diagnostics'),
36
+ copyLocalWebUrl: () => ipcRenderer.invoke('cloudcli-desktop:copy-local-web-url'),
37
+ getState: () => ipcRenderer.invoke('cloudcli-desktop:get-state'),
38
+ openCloudDashboard: () => ipcRenderer.invoke('cloudcli-desktop:open-cloud-dashboard'),
39
+ openEnvironment: (environmentId) => ipcRenderer.invoke('cloudcli-desktop:open-environment', environmentId),
40
+ runActiveEnvironmentAction: (action) => ipcRenderer.invoke('cloudcli-desktop:run-active-environment-action', action),
41
+ openLocal: () => ipcRenderer.invoke('cloudcli-desktop:open-local'),
42
+ openLocalWebUi: () => ipcRenderer.invoke('cloudcli-desktop:open-local-web-ui'),
43
+ refreshEnvironments: () => ipcRenderer.invoke('cloudcli-desktop:refresh-environments'),
44
+ refreshActiveTab: () => ipcRenderer.invoke('cloudcli-desktop:reload-active-tab'),
45
+ showEnvironmentPicker: () => ipcRenderer.invoke('cloudcli-desktop:show-environment-picker'),
46
+ showLauncher: () => ipcRenderer.invoke('cloudcli-desktop:show-launcher'),
47
+ showComputerAccess: () => ipcRenderer.invoke('cloudcli-desktop:show-computer-access'),
48
+ showLocalSettings: () => ipcRenderer.invoke('cloudcli-desktop:show-local-settings'),
49
+ updateComputerUse: (settings) => ipcRenderer.invoke('cloudcli-desktop:update-computer-use', settings),
50
+ requestComputerUsePermission: (permission) => ipcRenderer.invoke('cloudcli-desktop:request-computer-use-permission', permission),
51
+ showDesktopSettings: () => ipcRenderer.invoke('cloudcli-desktop:show-desktop-settings'),
52
+ closeSettingsWindow: () => ipcRenderer.invoke('cloudcli-desktop:close-settings-window'),
53
+ showActiveEnvironmentActionsMenu: () => ipcRenderer.invoke('cloudcli-desktop:show-active-environment-actions-menu'),
54
+ showEnvironmentActionsMenu: (environmentId) => ipcRenderer.invoke('cloudcli-desktop:show-environment-actions-menu', environmentId),
55
+ switchTab: (tabId) => ipcRenderer.invoke('cloudcli-desktop:switch-tab', tabId),
56
+ closeTab: (tabId) => ipcRenderer.invoke('cloudcli-desktop:close-tab', tabId),
57
+ updateSetting: (key, value) => ipcRenderer.invoke('cloudcli-desktop:update-setting', key, value),
58
+ onStateUpdated: onDesktopStateUpdated,
59
+ onLauncherCommand: (callback) => {
60
+ ipcRenderer.on('cloudcli-desktop:launcher-command', (_event, command) => callback(command));
61
+ },
62
+ });
63
+ }
@@ -0,0 +1,62 @@
1
+ import fs from 'node:fs/promises';
2
+ import sharp from 'sharp';
3
+
4
+ const size = 1024;
5
+ const assetsDir = 'electron/assets';
6
+ const iconPath = 'electron/assets/logo-macos.png';
7
+ const icnsPath = 'electron/assets/logo-macos.icns';
8
+
9
+ function renderSvg(entrySize) {
10
+ const scale = entrySize / 32;
11
+ return `
12
+ <svg xmlns="http://www.w3.org/2000/svg" width="${entrySize}" height="${entrySize}" viewBox="0 0 ${entrySize} ${entrySize}">
13
+ <rect width="${entrySize}" height="${entrySize}" fill="#2563eb"/>
14
+ <path
15
+ d="M${8 * scale} ${9 * scale}C${8 * scale} ${8.44772 * scale} ${8.44772 * scale} ${8 * scale} ${9 * scale} ${8 * scale}H${23 * scale}C${23.5523 * scale} ${8 * scale} ${24 * scale} ${8.44772 * scale} ${24 * scale} ${9 * scale}V${18 * scale}C${24 * scale} ${18.5523 * scale} ${23.5523 * scale} ${19 * scale} ${23 * scale} ${19 * scale}H${12 * scale}L${8 * scale} ${23 * scale}V${9 * scale}Z"
16
+ stroke="white"
17
+ stroke-width="${2 * scale}"
18
+ stroke-linecap="round"
19
+ stroke-linejoin="round"
20
+ fill="none"
21
+ />
22
+ </svg>`;
23
+ }
24
+
25
+ async function renderPng(entrySize) {
26
+ return sharp(Buffer.from(renderSvg(entrySize)))
27
+ .png()
28
+ .toBuffer();
29
+ }
30
+
31
+ await fs.mkdir(assetsDir, { recursive: true });
32
+ await fs.writeFile(iconPath, await renderPng(size));
33
+
34
+ const icnsEntries = [
35
+ ['icp4', 16],
36
+ ['icp5', 32],
37
+ ['icp6', 64],
38
+ ['ic07', 128],
39
+ ['ic08', 256],
40
+ ['ic09', 512],
41
+ ['ic10', 1024],
42
+ ['ic11', 32],
43
+ ['ic12', 64],
44
+ ['ic13', 256],
45
+ ['ic14', 512],
46
+ ];
47
+
48
+ const blocks = await Promise.all(icnsEntries.map(async ([type, entrySize]) => {
49
+ const png = await renderPng(entrySize);
50
+ const block = Buffer.alloc(8 + png.length);
51
+ block.write(type, 0, 4, 'ascii');
52
+ block.writeUInt32BE(block.length, 4);
53
+ png.copy(block, 8);
54
+ return block;
55
+ }));
56
+
57
+ const totalLength = 8 + blocks.reduce((sum, block) => sum + block.length, 0);
58
+ const header = Buffer.alloc(8);
59
+ header.write('icns', 0, 4, 'ascii');
60
+ header.writeUInt32BE(totalLength, 4);
61
+
62
+ await fs.writeFile(icnsPath, Buffer.concat([header, ...blocks], totalLength));
@@ -0,0 +1,277 @@
1
+ import { spawn } from 'node:child_process';
2
+ import crypto from 'node:crypto';
3
+ import fs from 'node:fs/promises';
4
+ import { createReadStream, createWriteStream } from 'node:fs';
5
+ import https from 'node:https';
6
+ import os from 'node:os';
7
+ import path from 'node:path';
8
+
9
+ /**
10
+ * Installs the versioned local server runtime used by CloudCLI Desktop.
11
+ *
12
+ * Server bundles are cached under:
13
+ * ~/.cloudcli/server/<version>/dist-server/server/index.js
14
+ */
15
+
16
+ const DEFAULT_INSTALL_ROOT = path.join(os.homedir(), '.cloudcli', 'server');
17
+ const DEFAULT_BUNDLE_BASE_URL = 'https://github.com/siteboon/claudecodeui/releases/download';
18
+ const MAX_REDIRECTS = 5;
19
+ const LOCAL_DOWNLOAD_HOSTS = new Set(['localhost', '127.0.0.1', '::1']);
20
+
21
+ function mapArch(arch = process.arch) {
22
+ return arch === 'arm64' ? 'arm64' : 'x64';
23
+ }
24
+
25
+ function mapPlatform(platform = process.platform) {
26
+ if (platform === 'darwin') return 'mac';
27
+ if (platform === 'win32') return 'win';
28
+ return 'linux';
29
+ }
30
+
31
+ export class ServerInstaller {
32
+ constructor({
33
+ version,
34
+ platform = process.platform,
35
+ arch = process.arch,
36
+ installRoot = process.env.CLOUDCLI_SERVER_DIR || DEFAULT_INSTALL_ROOT,
37
+ bundleBaseUrl = process.env.CLOUDCLI_SERVER_BUNDLE_URL || DEFAULT_BUNDLE_BASE_URL,
38
+ bundleReleaseTag = process.env.CLOUDCLI_SERVER_BUNDLE_RELEASE_TAG || '',
39
+ onLog,
40
+ } = {}) {
41
+ if (!version) throw new Error('ServerInstaller requires the app version');
42
+ this.version = version;
43
+ this.platform = mapPlatform(platform);
44
+ this.arch = mapArch(arch);
45
+ this.installRoot = installRoot;
46
+ this.bundleBaseUrl = bundleBaseUrl.replace(/\/+$/, '');
47
+ this.bundleReleaseTag = bundleReleaseTag || `v${this.version}`;
48
+ this.onLog = typeof onLog === 'function' ? onLog : () => {};
49
+ }
50
+
51
+ /** Directory the current version's server is (or will be) installed in. */
52
+ getVersionDir() {
53
+ return path.join(this.installRoot, this.version);
54
+ }
55
+
56
+ /** Absolute path to the server entry once installed. */
57
+ getServerEntry() {
58
+ return path.join(this.getVersionDir(), 'dist-server', 'server', 'index.js');
59
+ }
60
+
61
+ getBundleName() {
62
+ return `cloudcli-local-server-${this.version}-${this.platform}-${this.arch}.tar.gz`;
63
+ }
64
+
65
+ getBundleUrl() {
66
+ const url = new URL(`${this.bundleBaseUrl}/${this.bundleReleaseTag}/${this.getBundleName()}`);
67
+ if (url.protocol !== 'https:' && !(url.protocol === 'http:' && LOCAL_DOWNLOAD_HOSTS.has(url.hostname))) {
68
+ throw new Error(`Refusing unsupported server bundle URL: ${url.toString()}`);
69
+ }
70
+ return url.toString();
71
+ }
72
+
73
+ log(line) {
74
+ this.onLog(String(line));
75
+ }
76
+
77
+ async isInstalled() {
78
+ try {
79
+ const marker = JSON.parse(
80
+ await fs.readFile(path.join(this.getVersionDir(), '.installed.json'), 'utf8'),
81
+ );
82
+ if (marker.version !== this.version) return false;
83
+ await fs.access(this.getServerEntry());
84
+ return true;
85
+ } catch {
86
+ return false;
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Ensures the server for this version is installed, downloading + extracting
92
+ * it if needed. Returns the resolved server entry path.
93
+ */
94
+ async ensureInstalled() {
95
+ if (await this.isInstalled()) {
96
+ this.log(`Local server ${this.version} already installed.`);
97
+ return this.getServerEntry();
98
+ }
99
+
100
+ const versionDir = this.getVersionDir();
101
+ const tmpDir = path.join(this.installRoot, `.tmp-${this.version}-${process.pid}`);
102
+ const archivePath = path.join(tmpDir, this.getBundleName());
103
+
104
+ await fs.mkdir(tmpDir, { recursive: true });
105
+ try {
106
+ const url = this.getBundleUrl();
107
+ this.log(`Downloading local server bundle…`);
108
+ this.log(url);
109
+ await this.#download(url, archivePath);
110
+ await this.#verifyChecksum(url, archivePath);
111
+
112
+ this.log('Extracting local server…');
113
+ await fs.rm(versionDir, { recursive: true, force: true });
114
+ await fs.mkdir(versionDir, { recursive: true });
115
+ await this.#validateArchive(archivePath);
116
+ await this.#extract(archivePath, versionDir);
117
+
118
+ const entry = this.getServerEntry();
119
+ await fs.access(entry);
120
+
121
+ await fs.writeFile(
122
+ path.join(versionDir, '.installed.json'),
123
+ JSON.stringify({ version: this.version, installedAt: new Date().toISOString() }, null, 2),
124
+ 'utf8',
125
+ );
126
+ this.log(`Local server ${this.version} installed.`);
127
+ return entry;
128
+ } catch (error) {
129
+ await fs.rm(versionDir, { recursive: true, force: true }).catch(() => {});
130
+ throw new Error(`Failed to install local server: ${error.message}`);
131
+ } finally {
132
+ await fs.rm(tmpDir, { recursive: true, force: true }).catch(() => {});
133
+ }
134
+ }
135
+
136
+ #download(url, destPath, redirectsLeft = MAX_REDIRECTS) {
137
+ return new Promise((resolve, reject) => {
138
+ const req = https.get(url, (res) => {
139
+ const { statusCode, headers } = res;
140
+
141
+ if (statusCode >= 300 && statusCode < 400 && headers.location) {
142
+ res.resume();
143
+ if (redirectsLeft <= 0) {
144
+ reject(new Error('Too many redirects'));
145
+ return;
146
+ }
147
+ const next = new URL(headers.location, url).toString();
148
+ resolve(this.#download(next, destPath, redirectsLeft - 1));
149
+ return;
150
+ }
151
+
152
+ if (statusCode !== 200) {
153
+ res.resume();
154
+ reject(new Error(`Download failed with HTTP ${statusCode}`));
155
+ return;
156
+ }
157
+
158
+ const total = Number(headers['content-length']) || 0;
159
+ let received = 0;
160
+ let lastPct = -1;
161
+ const out = createWriteStream(destPath);
162
+
163
+ res.on('data', (chunk) => {
164
+ received += chunk.length;
165
+ if (total) {
166
+ const pct = Math.floor((received / total) * 100);
167
+ if (pct !== lastPct && pct % 10 === 0) {
168
+ lastPct = pct;
169
+ this.log(`Downloading… ${pct}%`);
170
+ }
171
+ }
172
+ });
173
+ res.pipe(out);
174
+ out.on('finish', () => out.close(resolve));
175
+ out.on('error', reject);
176
+ res.on('error', reject);
177
+ });
178
+ req.on('error', reject);
179
+ });
180
+ }
181
+
182
+ async #verifyChecksum(url, archivePath) {
183
+ let expected;
184
+ try {
185
+ expected = (await this.#fetchText(`${url}.sha256`)).trim().split(/\s+/)[0];
186
+ } catch (error) {
187
+ throw new Error(`Could not verify server bundle checksum: ${error.message}`);
188
+ }
189
+ const actual = await this.#sha256(archivePath);
190
+ if (expected.toLowerCase() !== actual.toLowerCase()) {
191
+ throw new Error('Checksum mismatch — refusing to install');
192
+ }
193
+ this.log('Checksum verified.');
194
+ }
195
+
196
+ #fetchText(url, redirectsLeft = MAX_REDIRECTS) {
197
+ return new Promise((resolve, reject) => {
198
+ https
199
+ .get(url, (res) => {
200
+ const { statusCode, headers } = res;
201
+ if (statusCode >= 300 && statusCode < 400 && headers.location) {
202
+ res.resume();
203
+ if (redirectsLeft <= 0) return reject(new Error('Too many redirects'));
204
+ return resolve(this.#fetchText(new URL(headers.location, url).toString(), redirectsLeft - 1));
205
+ }
206
+ if (statusCode !== 200) {
207
+ res.resume();
208
+ return reject(new Error(`HTTP ${statusCode}`));
209
+ }
210
+ let body = '';
211
+ res.setEncoding('utf8');
212
+ res.on('data', (c) => (body += c));
213
+ res.on('end', () => resolve(body));
214
+ res.on('error', reject);
215
+ })
216
+ .on('error', reject);
217
+ });
218
+ }
219
+
220
+ #sha256(filePath) {
221
+ return new Promise((resolve, reject) => {
222
+ const hash = crypto.createHash('sha256');
223
+ const stream = createReadStream(filePath);
224
+ stream.on('data', (c) => hash.update(c));
225
+ stream.on('end', () => resolve(hash.digest('hex')));
226
+ stream.on('error', reject);
227
+ });
228
+ }
229
+
230
+ #extract(archivePath, destDir) {
231
+ return new Promise((resolve, reject) => {
232
+ const child = spawn('tar', ['-xzf', archivePath, '-C', destDir], {
233
+ stdio: ['ignore', 'ignore', 'pipe'],
234
+ windowsHide: true,
235
+ });
236
+ let stderr = '';
237
+ child.stderr?.on('data', (c) => (stderr += c));
238
+ child.once('error', reject);
239
+ child.once('exit', (code) => {
240
+ if (code === 0) resolve();
241
+ else reject(new Error(`tar exited with code ${code}: ${stderr.trim()}`));
242
+ });
243
+ });
244
+ }
245
+
246
+ #validateArchive(archivePath) {
247
+ return new Promise((resolve, reject) => {
248
+ const child = spawn('tar', ['-tzf', archivePath], {
249
+ stdio: ['ignore', 'pipe', 'pipe'],
250
+ windowsHide: true,
251
+ });
252
+ let stdout = '';
253
+ let stderr = '';
254
+ child.stdout?.on('data', (c) => { stdout += c; });
255
+ child.stderr?.on('data', (c) => { stderr += c; });
256
+ child.once('error', reject);
257
+ child.once('exit', (code) => {
258
+ if (code !== 0) {
259
+ reject(new Error(`tar list exited with code ${code}: ${stderr.trim()}`));
260
+ return;
261
+ }
262
+ for (const entry of stdout.split(/\r?\n/).filter(Boolean)) {
263
+ const normalized = entry.replace(/\\/g, '/');
264
+ if (
265
+ path.isAbsolute(normalized)
266
+ || /^[a-zA-Z]:\//.test(normalized)
267
+ || normalized.split('/').includes('..')
268
+ ) {
269
+ reject(new Error(`Refusing unsafe archive entry: ${entry}`));
270
+ return;
271
+ }
272
+ }
273
+ resolve();
274
+ });
275
+ });
276
+ }
277
+ }
@@ -0,0 +1,87 @@
1
+ export class TabsController {
2
+ constructor() {
3
+ this.activeTabId = 'home';
4
+ this.tabs = [
5
+ {
6
+ id: 'home',
7
+ title: 'Launcher',
8
+ kind: 'launcher',
9
+ closable: false,
10
+ },
11
+ ];
12
+ }
13
+
14
+ getTabIdForTarget(target) {
15
+ if (target.kind === 'launcher') return 'home';
16
+ if (target.kind === 'remote' && target.id) return `remote:${target.id}`;
17
+ return target.kind;
18
+ }
19
+
20
+ upsertTarget(target) {
21
+ const tabId = this.getTabIdForTarget(target);
22
+ const existingTab = this.tabs.find((tab) => tab.id === tabId);
23
+ const nextTab = {
24
+ id: tabId,
25
+ title: target.kind === 'launcher' ? 'Launcher' : target.name,
26
+ kind: target.kind,
27
+ target,
28
+ closable: tabId !== 'home',
29
+ };
30
+
31
+ if (existingTab) {
32
+ Object.assign(existingTab, nextTab);
33
+ } else {
34
+ this.tabs.push(nextTab);
35
+ }
36
+
37
+ this.activeTabId = tabId;
38
+ return nextTab;
39
+ }
40
+
41
+ activate(tabId) {
42
+ const tab = this.tabs.find((item) => item.id === tabId);
43
+ if (!tab) return null;
44
+ this.activeTabId = tab.id;
45
+ return tab;
46
+ }
47
+
48
+ remove(tabId) {
49
+ const tab = this.tabs.find((item) => item.id === tabId);
50
+ if (!tab || !tab.closable) return null;
51
+ this.tabs = this.tabs.filter((item) => item.id !== tabId);
52
+ if (this.activeTabId === tabId) {
53
+ this.activeTabId = 'home';
54
+ }
55
+ return tab;
56
+ }
57
+
58
+ removeByKind(kind) {
59
+ const removed = this.tabs.filter((tab) => tab.kind === kind && tab.closable);
60
+ if (!removed.length) return [];
61
+
62
+ const removedIds = new Set(removed.map((tab) => tab.id));
63
+ this.tabs = this.tabs.filter((tab) => !removedIds.has(tab.id));
64
+ if (removedIds.has(this.activeTabId)) {
65
+ this.activeTabId = 'home';
66
+ }
67
+ return removed;
68
+ }
69
+
70
+ getActiveTab() {
71
+ return this.getTab(this.activeTabId);
72
+ }
73
+
74
+ getTab(tabId) {
75
+ return this.tabs.find((item) => item.id === tabId) || null;
76
+ }
77
+
78
+ getSerializableTabs() {
79
+ return this.tabs.map((tab) => ({
80
+ id: tab.id,
81
+ title: tab.title,
82
+ kind: tab.kind,
83
+ closable: tab.closable,
84
+ active: tab.id === this.activeTabId,
85
+ }));
86
+ }
87
+ }