@cloudcli-ai/cloudcli 1.33.3 → 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 (329) 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 +26 -6
  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-models.provider.js +5 -0
  113. package/dist-server/server/modules/providers/list/claude/claude-models.provider.js.map +1 -1
  114. package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js +24 -1
  115. package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js.map +1 -1
  116. package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js +9 -12
  117. package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js.map +1 -1
  118. package/dist-server/server/modules/providers/list/claude/claude-skills.provider.js +7 -0
  119. package/dist-server/server/modules/providers/list/claude/claude-skills.provider.js.map +1 -1
  120. package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js +7 -3
  121. package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js.map +1 -1
  122. package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js +3 -9
  123. package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js.map +1 -1
  124. package/dist-server/server/modules/providers/list/codex/codex-skills.provider.js +7 -0
  125. package/dist-server/server/modules/providers/list/codex/codex-skills.provider.js.map +1 -1
  126. package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js +13 -22
  127. package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js.map +1 -1
  128. package/dist-server/server/modules/providers/list/cursor/cursor-skills.provider.js +7 -0
  129. package/dist-server/server/modules/providers/list/cursor/cursor-skills.provider.js.map +1 -1
  130. package/dist-server/server/modules/providers/list/gemini/gemini-models.provider.js +5 -8
  131. package/dist-server/server/modules/providers/list/gemini/gemini-models.provider.js.map +1 -1
  132. package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js +6 -6
  133. package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js.map +1 -1
  134. package/dist-server/server/modules/providers/list/gemini/gemini-skills.provider.js +7 -0
  135. package/dist-server/server/modules/providers/list/gemini/gemini-skills.provider.js.map +1 -1
  136. package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js +17 -3
  137. package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js.map +1 -1
  138. package/dist-server/server/modules/providers/list/opencode/opencode-sessions.provider.js +9 -10
  139. package/dist-server/server/modules/providers/list/opencode/opencode-sessions.provider.js.map +1 -1
  140. package/dist-server/server/modules/providers/provider.routes.js +123 -1
  141. package/dist-server/server/modules/providers/provider.routes.js.map +1 -1
  142. package/dist-server/server/modules/providers/services/mcp.service.js +23 -0
  143. package/dist-server/server/modules/providers/services/mcp.service.js.map +1 -1
  144. package/dist-server/server/modules/providers/services/provider-capabilities.service.js +65 -0
  145. package/dist-server/server/modules/providers/services/provider-capabilities.service.js.map +1 -0
  146. package/dist-server/server/modules/providers/services/provider-models.service.js +1 -1
  147. package/dist-server/server/modules/providers/services/provider-models.service.js.map +1 -1
  148. package/dist-server/server/modules/providers/services/sessions-watcher.service.js +62 -23
  149. package/dist-server/server/modules/providers/services/sessions-watcher.service.js.map +1 -1
  150. package/dist-server/server/modules/providers/services/sessions.service.js +62 -4
  151. package/dist-server/server/modules/providers/services/sessions.service.js.map +1 -1
  152. package/dist-server/server/modules/providers/services/skills.service.js +11 -0
  153. package/dist-server/server/modules/providers/services/skills.service.js.map +1 -1
  154. package/dist-server/server/modules/providers/shared/skills/skills.provider.js +163 -1
  155. package/dist-server/server/modules/providers/shared/skills/skills.provider.js.map +1 -1
  156. package/dist-server/server/modules/providers/tests/opencode-sessions.test.js +45 -0
  157. package/dist-server/server/modules/providers/tests/opencode-sessions.test.js.map +1 -1
  158. package/dist-server/server/modules/providers/tests/skills.test.js +160 -0
  159. package/dist-server/server/modules/providers/tests/skills.test.js.map +1 -1
  160. package/dist-server/server/modules/websocket/index.js +1 -0
  161. package/dist-server/server/modules/websocket/index.js.map +1 -1
  162. package/dist-server/server/modules/websocket/services/chat-run-registry.service.js +252 -0
  163. package/dist-server/server/modules/websocket/services/chat-run-registry.service.js.map +1 -0
  164. package/dist-server/server/modules/websocket/services/chat-session-writer.service.js +105 -0
  165. package/dist-server/server/modules/websocket/services/chat-session-writer.service.js.map +1 -0
  166. package/dist-server/server/modules/websocket/services/chat-websocket.service.js +218 -156
  167. package/dist-server/server/modules/websocket/services/chat-websocket.service.js.map +1 -1
  168. package/dist-server/server/modules/websocket/services/desktop-agent-websocket.service.js +39 -0
  169. package/dist-server/server/modules/websocket/services/desktop-agent-websocket.service.js.map +1 -0
  170. package/dist-server/server/modules/websocket/services/shell-websocket.service.js +83 -31
  171. package/dist-server/server/modules/websocket/services/shell-websocket.service.js.map +1 -1
  172. package/dist-server/server/modules/websocket/services/websocket-server.service.js +10 -0
  173. package/dist-server/server/modules/websocket/services/websocket-server.service.js.map +1 -1
  174. package/dist-server/server/modules/websocket/tests/chat-run-registry.test.js +216 -0
  175. package/dist-server/server/modules/websocket/tests/chat-run-registry.test.js.map +1 -0
  176. package/dist-server/server/openai-codex.js +24 -14
  177. package/dist-server/server/openai-codex.js.map +1 -1
  178. package/dist-server/server/opencode-cli.js +21 -8
  179. package/dist-server/server/opencode-cli.js.map +1 -1
  180. package/dist-server/server/opencode-cli.test.js +19 -1
  181. package/dist-server/server/opencode-cli.test.js.map +1 -1
  182. package/dist-server/server/routes/agent.js +1 -1
  183. package/dist-server/server/routes/settings.js +1 -1
  184. package/dist-server/server/routes/settings.js.map +1 -1
  185. package/dist-server/server/services/notification-orchestrator.js +1 -176
  186. package/dist-server/server/services/notification-orchestrator.js.map +1 -1
  187. package/dist-server/server/services/tests/notification-orchestrator.test.js +64 -0
  188. package/dist-server/server/services/tests/notification-orchestrator.test.js.map +1 -0
  189. package/dist-server/server/shared/{claude-cli-path.test.js → tests/claude-cli-path.test.js} +1 -1
  190. package/dist-server/server/shared/tests/claude-cli-path.test.js.map +1 -0
  191. package/dist-server/server/shared/tests/slice-tail-page.test.js +35 -0
  192. package/dist-server/server/shared/tests/slice-tail-page.test.js.map +1 -0
  193. package/dist-server/server/shared/utils.js +73 -1
  194. package/dist-server/server/shared/utils.js.map +1 -1
  195. package/dist-server/server/voice-proxy.js +226 -0
  196. package/dist-server/server/voice-proxy.js.map +1 -0
  197. package/electron/assets/logo-macos.icns +0 -0
  198. package/electron/assets/logo-macos.png +0 -0
  199. package/electron/assets/logo-windows.ico +0 -0
  200. package/electron/cloud.js +260 -0
  201. package/electron/computerAgent.js +290 -0
  202. package/electron/desktopNotifications.js +378 -0
  203. package/electron/desktopWindow.js +781 -0
  204. package/electron/launcher/index.html +14 -0
  205. package/electron/launcher/launcher.css +801 -0
  206. package/electron/launcher/launcher.js +829 -0
  207. package/electron/localServer.js +550 -0
  208. package/electron/main.js +1060 -0
  209. package/electron/preload.cjs +63 -0
  210. package/electron/scripts/generate-macos-icon.js +62 -0
  211. package/electron/serverInstaller.js +277 -0
  212. package/electron/tabs.js +87 -0
  213. package/electron/viewHost.js +331 -0
  214. package/package.json +86 -5
  215. package/public/api-docs.html +36 -18
  216. package/scripts/build-computer-semantics.mjs +133 -0
  217. package/scripts/copy-computer-semantics-bin.mjs +24 -0
  218. package/scripts/release/build-server-bundle.js +176 -0
  219. package/scripts/release/prepare-desktop-app.js +158 -0
  220. package/server/browser-use-mcp.ts +384 -0
  221. package/server/claude-sdk.js +28 -6
  222. package/server/cli.js +15 -6
  223. package/server/computer-use-agent.ts +279 -0
  224. package/server/computer-use-mcp.ts +574 -0
  225. package/server/cursor-cli.js +27 -11
  226. package/server/gemini-cli.js +17 -2
  227. package/server/index.js +151 -47
  228. package/server/load-env.js +1 -1
  229. package/server/modules/browser-use/browser-use-mcp.routes.ts +120 -0
  230. package/server/modules/browser-use/browser-use.routes.ts +96 -0
  231. package/server/modules/browser-use/browser-use.service.ts +836 -0
  232. package/server/modules/browser-use/tests/browser-use.service.test.ts +10 -0
  233. package/server/modules/computer-use/actions/raw-action-dispatcher.ts +67 -0
  234. package/server/modules/computer-use/actions/raw-action-types.ts +28 -0
  235. package/server/modules/computer-use/computer-executor.ts +242 -0
  236. package/server/modules/computer-use/computer-semantics.service.ts +460 -0
  237. package/server/modules/computer-use/computer-use-mcp.routes.ts +141 -0
  238. package/server/modules/computer-use/computer-use.routes.ts +211 -0
  239. package/server/modules/computer-use/computer-use.service.ts +920 -0
  240. package/server/modules/computer-use/desktop-agent-relay.service.ts +158 -0
  241. package/server/modules/computer-use/index.ts +2 -0
  242. package/server/modules/computer-use/semantics/adapters/helper-semantic-adapter.ts +82 -0
  243. package/server/modules/computer-use/semantics/adapters/macos/macos-semantic-adapter.ts +5 -0
  244. package/server/modules/computer-use/semantics/adapters/semantic-adapter.ts +23 -0
  245. package/server/modules/computer-use/semantics/adapters/windows/windows-semantic-adapter.ts +5 -0
  246. package/server/modules/computer-use/semantics/bin/darwin-arm64/CloudCLISemantics +0 -0
  247. package/server/modules/computer-use/semantics/bin/darwin-x64/CloudCLISemantics +0 -0
  248. package/server/modules/computer-use/semantics/bin/win32-arm64/CloudCLISemantics.exe +0 -0
  249. package/server/modules/computer-use/semantics/bin/win32-x64/CloudCLISemantics.exe +0 -0
  250. package/server/modules/computer-use/semantics/helpers/macos/CloudCLISemantics.swift +467 -0
  251. package/server/modules/computer-use/semantics/helpers/semantic-helper-process.ts +124 -0
  252. package/server/modules/computer-use/semantics/helpers/semantic-helper-resolver.ts +97 -0
  253. package/server/modules/computer-use/semantics/helpers/windows/CloudCLISemantics.csproj +11 -0
  254. package/server/modules/computer-use/semantics/helpers/windows/Program.cs +534 -0
  255. package/server/modules/computer-use/semantics/semantic-session-store.ts +87 -0
  256. package/server/modules/computer-use/semantics/semantic-tool-dispatcher.ts +17 -0
  257. package/server/modules/computer-use/semantics/semantic-types.ts +58 -0
  258. package/server/modules/database/index.ts +1 -0
  259. package/server/modules/database/migrations.ts +25 -0
  260. package/server/modules/database/repositories/notification-channel-endpoints.ts +153 -0
  261. package/server/modules/database/repositories/notification-preferences.ts +12 -1
  262. package/server/modules/database/repositories/sessions.db.ts +227 -23
  263. package/server/modules/database/schema.ts +27 -0
  264. package/server/modules/database/tests/sessions-provider-mapping.test.ts +108 -0
  265. package/server/modules/database/{repositories → tests}/sessions.db.integration.test.ts +12 -0
  266. package/server/modules/notifications/index.ts +13 -0
  267. package/server/modules/notifications/notifications.routes.ts +127 -0
  268. package/server/modules/notifications/services/desktop-notification-clients.service.ts +124 -0
  269. package/server/modules/notifications/services/notification-orchestrator.service.js +288 -0
  270. package/server/modules/notifications/websocket/desktop-notifications-websocket.service.ts +109 -0
  271. package/server/modules/projects/services/project-management.service.ts +0 -8
  272. package/server/modules/projects/services/projects-with-sessions-fetch.service.ts +12 -53
  273. package/server/modules/providers/README.md +1 -1
  274. package/server/modules/providers/index.ts +1 -0
  275. package/server/modules/providers/list/claude/claude-models.provider.ts +5 -0
  276. package/server/modules/providers/list/claude/claude-session-synchronizer.provider.ts +26 -1
  277. package/server/modules/providers/list/claude/claude-sessions.provider.ts +9 -14
  278. package/server/modules/providers/list/claude/claude-skills.provider.ts +8 -0
  279. package/server/modules/providers/list/codex/codex-session-synchronizer.provider.ts +7 -3
  280. package/server/modules/providers/list/codex/codex-sessions.provider.ts +3 -12
  281. package/server/modules/providers/list/codex/codex-skills.provider.ts +8 -0
  282. package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +13 -22
  283. package/server/modules/providers/list/cursor/cursor-skills.provider.ts +8 -0
  284. package/server/modules/providers/list/gemini/gemini-models.provider.ts +5 -8
  285. package/server/modules/providers/list/gemini/gemini-sessions.provider.ts +6 -6
  286. package/server/modules/providers/list/gemini/gemini-skills.provider.ts +8 -0
  287. package/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.ts +18 -4
  288. package/server/modules/providers/list/opencode/opencode-sessions.provider.ts +9 -12
  289. package/server/modules/providers/provider.routes.ts +167 -1
  290. package/server/modules/providers/services/mcp.service.ts +26 -0
  291. package/server/modules/providers/services/provider-capabilities.service.ts +91 -0
  292. package/server/modules/providers/services/provider-models.service.ts +1 -1
  293. package/server/modules/providers/services/sessions-watcher.service.ts +71 -25
  294. package/server/modules/providers/services/sessions.service.ts +79 -4
  295. package/server/modules/providers/services/skills.service.ts +25 -1
  296. package/server/modules/providers/shared/skills/skills.provider.ts +223 -0
  297. package/server/modules/providers/tests/opencode-sessions.test.ts +49 -0
  298. package/server/modules/providers/tests/skills.test.ts +212 -0
  299. package/server/modules/websocket/README.md +33 -27
  300. package/server/modules/websocket/index.ts +1 -0
  301. package/server/modules/websocket/services/chat-run-registry.service.ts +327 -0
  302. package/server/modules/websocket/services/chat-session-writer.service.ts +145 -0
  303. package/server/modules/websocket/services/chat-websocket.service.ts +292 -207
  304. package/server/modules/websocket/services/desktop-agent-websocket.service.ts +51 -0
  305. package/server/modules/websocket/services/shell-websocket.service.ts +108 -32
  306. package/server/modules/websocket/services/websocket-server.service.ts +12 -0
  307. package/server/modules/websocket/tests/chat-run-registry.test.ts +244 -0
  308. package/server/openai-codex.js +24 -14
  309. package/server/opencode-cli.js +21 -8
  310. package/server/opencode-cli.test.js +20 -1
  311. package/server/routes/agent.js +1 -1
  312. package/server/routes/settings.js +6 -1
  313. package/server/services/notification-orchestrator.js +3 -224
  314. package/server/services/tests/notification-orchestrator.test.js +80 -0
  315. package/server/shared/interfaces.ts +15 -0
  316. package/server/shared/tests/slice-tail-page.test.ts +42 -0
  317. package/server/shared/types.ts +84 -1
  318. package/server/shared/utils.ts +95 -1
  319. package/server/voice-proxy.js +224 -0
  320. package/dist/assets/index-73Xw3i9v.css +0 -32
  321. package/dist/assets/index-9n7A21AT.js +0 -1361
  322. package/dist/modelConstants.js +0 -848
  323. package/dist-server/server/modules/database/repositories/projects.db.integration.test.js.map +0 -1
  324. package/dist-server/server/modules/database/repositories/sessions.db.integration.test.js.map +0 -1
  325. package/dist-server/server/shared/claude-cli-path.test.js.map +0 -1
  326. package/public/modelConstants.js +0 -848
  327. /package/dist-server/server/modules/database/{repositories → tests}/projects.db.integration.test.js +0 -0
  328. /package/server/modules/database/{repositories → tests}/projects.db.integration.test.ts +0 -0
  329. /package/server/shared/{claude-cli-path.test.ts → tests/claude-cli-path.test.ts} +0 -0
@@ -0,0 +1,378 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { Notification } from 'electron';
4
+ import WebSocket from 'ws';
5
+
6
+ const RECONNECT_MIN_MS = 1000;
7
+ const RECONNECT_MAX_MS = 30000;
8
+ const TARGET_REGISTER_TIMEOUT_MS = 8000;
9
+
10
+ function toNotificationsWsUrl(httpUrl) {
11
+ try {
12
+ const parsed = new URL(httpUrl);
13
+ parsed.protocol = parsed.protocol === 'http:' ? 'ws:' : 'wss:';
14
+ parsed.pathname = '/desktop-notifications';
15
+ parsed.search = '';
16
+ parsed.hash = '';
17
+ return parsed.toString();
18
+ } catch {
19
+ return null;
20
+ }
21
+ }
22
+
23
+ function readJsonMessage(raw) {
24
+ try {
25
+ return JSON.parse(String(raw));
26
+ } catch {
27
+ return null;
28
+ }
29
+ }
30
+
31
+ async function requestJson(url, { method = 'POST', body = null, headers = {} } = {}) {
32
+ const controller = new AbortController();
33
+ const timeout = setTimeout(() => controller.abort(), TARGET_REGISTER_TIMEOUT_MS);
34
+ try {
35
+ const response = await fetch(url, {
36
+ method,
37
+ signal: controller.signal,
38
+ headers: {
39
+ 'Content-Type': 'application/json',
40
+ ...headers,
41
+ },
42
+ ...(body == null ? {} : { body: JSON.stringify(body) }),
43
+ });
44
+ const payload = await response.json().catch(() => ({}));
45
+ if (!response.ok) {
46
+ throw new Error(payload.error || `Request failed with status ${response.status}`);
47
+ }
48
+ return payload;
49
+ } finally {
50
+ clearTimeout(timeout);
51
+ }
52
+ }
53
+
54
+ export class DesktopNotificationsController {
55
+ constructor({
56
+ settingsPath,
57
+ appVersion,
58
+ appName,
59
+ getDeviceId,
60
+ getAccountEmail,
61
+ getRunningEnvironmentUrls,
62
+ getApiKey,
63
+ getAuthToken,
64
+ getIconPath,
65
+ openNotificationTarget,
66
+ onChange,
67
+ }) {
68
+ this.settingsPath = settingsPath;
69
+ this.appVersion = appVersion;
70
+ this.appName = appName;
71
+ this.getDeviceId = getDeviceId;
72
+ this.getAccountEmail = getAccountEmail;
73
+ this.getRunningEnvironmentUrls = getRunningEnvironmentUrls;
74
+ this.getApiKey = getApiKey;
75
+ this.getAuthToken = getAuthToken;
76
+ this.getIconPath = getIconPath;
77
+ this.openNotificationTarget = openNotificationTarget;
78
+ this.onChange = onChange;
79
+ this.settings = { enabled: false };
80
+ this.connections = new Map();
81
+ this.lastEvent = null;
82
+ this.lastError = null;
83
+ }
84
+
85
+ getState() {
86
+ const connectedTargets = [];
87
+ for (const [url, connection] of this.connections.entries()) {
88
+ if (connection.ws?.readyState === WebSocket.OPEN) {
89
+ connectedTargets.push(url);
90
+ }
91
+ }
92
+
93
+ return {
94
+ enabled: this.settings.enabled,
95
+ supported: Notification.isSupported(),
96
+ targetCount: this.connections.size,
97
+ connectedCount: connectedTargets.length,
98
+ connectedTargets,
99
+ lastEvent: this.lastEvent,
100
+ lastError: this.lastError,
101
+ };
102
+ }
103
+
104
+ async loadSettings() {
105
+ try {
106
+ const raw = await fs.readFile(this.settingsPath, 'utf8');
107
+ const stored = JSON.parse(raw);
108
+ this.settings = { enabled: Boolean(stored.enabled) };
109
+ } catch {
110
+ this.settings = { enabled: false };
111
+ }
112
+ return this.settings;
113
+ }
114
+
115
+ async saveSettings(next) {
116
+ const enabled = Boolean(next?.enabled);
117
+ if (!enabled && this.settings.enabled) {
118
+ await this.disableCurrentTargets();
119
+ }
120
+ this.settings = { enabled };
121
+ await fs.mkdir(path.dirname(this.settingsPath), { recursive: true });
122
+ await fs.writeFile(this.settingsPath, JSON.stringify(this.settings, null, 2), 'utf8');
123
+ await this.sync();
124
+ this.onChange?.();
125
+ return this.settings;
126
+ }
127
+
128
+ async sync() {
129
+ if (!this.settings.enabled) {
130
+ this.stop();
131
+ this.lastEvent = 'disabled';
132
+ this.onChange?.();
133
+ return;
134
+ }
135
+
136
+ if (!Notification.isSupported()) {
137
+ this.stop();
138
+ this.lastEvent = 'unsupported';
139
+ this.lastError = 'Native notifications are not supported on this system.';
140
+ this.onChange?.();
141
+ return;
142
+ }
143
+
144
+ const deviceId = this.getDeviceId?.();
145
+ if (!deviceId) {
146
+ this.stop();
147
+ this.lastEvent = 'missing-device';
148
+ this.lastError = 'Connect a CloudCLI account before enabling desktop notifications.';
149
+ this.onChange?.();
150
+ return;
151
+ }
152
+
153
+ const targets = (this.getRunningEnvironmentUrls?.() || [])
154
+ .map((httpUrl) => ({
155
+ httpUrl,
156
+ wsUrl: toNotificationsWsUrl(httpUrl),
157
+ }))
158
+ .filter((target) => target.wsUrl);
159
+
160
+ const nextWsUrls = new Set(targets.map((target) => target.wsUrl));
161
+ for (const [wsUrl, connection] of this.connections.entries()) {
162
+ if (!nextWsUrls.has(wsUrl)) {
163
+ this.closeConnection(connection);
164
+ this.connections.delete(wsUrl);
165
+ }
166
+ }
167
+
168
+ for (const target of targets) {
169
+ if (!this.connections.has(target.wsUrl)) {
170
+ void this.connect(target).catch((error) => {
171
+ this.lastEvent = 'connect-error';
172
+ this.lastError = error instanceof Error ? error.message : String(error);
173
+ this.onChange?.();
174
+ });
175
+ }
176
+ }
177
+
178
+ this.lastEvent = targets.length ? 'sync' : 'no-targets';
179
+ this.onChange?.();
180
+ }
181
+
182
+ async connect(target, attempt = 0) {
183
+ const existing = this.connections.get(target.wsUrl);
184
+ if (existing?.ws && [WebSocket.CONNECTING, WebSocket.OPEN].includes(existing.ws.readyState)) {
185
+ return;
186
+ }
187
+
188
+ const connection = {
189
+ ...target,
190
+ ws: null,
191
+ reconnectTimer: null,
192
+ closed: false,
193
+ attempt,
194
+ };
195
+ this.connections.set(target.wsUrl, connection);
196
+
197
+ const headers = await this.getTargetAuthHeaders(target.httpUrl);
198
+ if (connection.closed || this.connections.get(target.wsUrl) !== connection) {
199
+ return;
200
+ }
201
+
202
+ const ws = new WebSocket(target.wsUrl, { headers: Object.keys(headers).length ? headers : undefined });
203
+ connection.ws = ws;
204
+
205
+ ws.on('open', async () => {
206
+ try {
207
+ await this.registerTarget(target.httpUrl);
208
+ ws.send(JSON.stringify({
209
+ type: 'register',
210
+ deviceId: this.getDeviceId?.(),
211
+ label: this.getAccountEmail?.() || this.appName,
212
+ platform: process.platform,
213
+ appVersion: this.appVersion,
214
+ }));
215
+ connection.attempt = 0;
216
+ this.lastEvent = 'connected';
217
+ this.lastError = null;
218
+ this.onChange?.();
219
+ } catch (error) {
220
+ this.lastEvent = 'register-error';
221
+ this.lastError = error instanceof Error ? error.message : String(error);
222
+ this.onChange?.();
223
+ try { ws.close(); } catch {}
224
+ }
225
+ });
226
+
227
+ ws.on('message', (raw) => this.handleMessage(target, ws, raw));
228
+ ws.on('close', () => this.scheduleReconnect(target.wsUrl));
229
+ ws.on('error', (error) => {
230
+ this.lastEvent = 'socket-error';
231
+ this.lastError = error instanceof Error ? error.message : String(error);
232
+ this.onChange?.();
233
+ });
234
+ }
235
+
236
+ async registerTarget(httpUrl) {
237
+ const url = new URL('/api/notifications/endpoints/current', httpUrl).toString();
238
+ await requestJson(url, {
239
+ method: 'POST',
240
+ headers: await this.getTargetAuthHeaders(httpUrl),
241
+ body: {
242
+ channel: 'desktop',
243
+ endpointId: this.getDeviceId?.(),
244
+ label: this.getAccountEmail?.() || this.appName,
245
+ metadata: {
246
+ platform: process.platform,
247
+ appVersion: this.appVersion,
248
+ },
249
+ enabled: true,
250
+ },
251
+ });
252
+ }
253
+
254
+ async disableCurrentTargets() {
255
+ const deviceId = this.getDeviceId?.();
256
+ if (!deviceId) return;
257
+
258
+ const targets = new Set([
259
+ ...[...this.connections.values()].map((connection) => connection.httpUrl).filter(Boolean),
260
+ ...(this.getRunningEnvironmentUrls?.() || []),
261
+ ]);
262
+
263
+ const results = await Promise.allSettled([...targets].map(async (httpUrl) => {
264
+ const url = new URL(`/api/notifications/endpoints/desktop/${encodeURIComponent(deviceId)}`, httpUrl).toString();
265
+ await requestJson(url, {
266
+ method: 'PATCH',
267
+ headers: await this.getTargetAuthHeaders(httpUrl),
268
+ body: { enabled: false },
269
+ });
270
+ }));
271
+
272
+ const rejected = results.find((result) => result.status === 'rejected');
273
+ if (rejected) {
274
+ this.lastEvent = 'disable-endpoint-error';
275
+ this.lastError = rejected.reason instanceof Error ? rejected.reason.message : String(rejected.reason);
276
+ }
277
+ }
278
+
279
+ async getTargetAuthHeaders(httpUrl) {
280
+ const headers = {};
281
+ const apiKey = this.getApiKey?.();
282
+ if (apiKey) {
283
+ headers['X-API-Key'] = apiKey;
284
+ }
285
+
286
+ const authToken = await Promise.resolve(this.getAuthToken?.(httpUrl)).catch(() => null);
287
+ if (authToken) {
288
+ headers.Authorization = `Bearer ${authToken}`;
289
+ }
290
+ return headers;
291
+ }
292
+
293
+ handleMessage(target, ws, raw) {
294
+ const message = readJsonMessage(raw);
295
+ if (!message || message.type !== 'notification' || !message.payload) {
296
+ return;
297
+ }
298
+
299
+ const shown = this.showNativeNotification(target, message.payload);
300
+ if (shown && ws.readyState === WebSocket.OPEN) {
301
+ ws.send(JSON.stringify({
302
+ type: 'notification_ack',
303
+ id: message.id || message.payload?.data?.tag || null,
304
+ action: 'shown',
305
+ }));
306
+ }
307
+ }
308
+
309
+ showNativeNotification(target, payload) {
310
+ if (!Notification.isSupported()) return false;
311
+
312
+ const notification = new Notification({
313
+ title: payload.title || this.appName,
314
+ body: payload.body || '',
315
+ icon: this.getIconPath?.(),
316
+ silent: false,
317
+ });
318
+
319
+ notification.on('click', () => {
320
+ void this.openNotificationTarget?.({
321
+ environmentUrl: target.httpUrl,
322
+ sessionId: payload.data?.sessionId || null,
323
+ provider: payload.data?.provider || null,
324
+ }).catch((error) => {
325
+ this.lastEvent = 'click-error';
326
+ this.lastError = error instanceof Error ? error.message : String(error);
327
+ this.onChange?.();
328
+ });
329
+ });
330
+
331
+ notification.show();
332
+ this.lastEvent = 'notification-shown';
333
+ this.lastError = null;
334
+ this.onChange?.();
335
+ return true;
336
+ }
337
+
338
+ scheduleReconnect(wsUrl) {
339
+ const connection = this.connections.get(wsUrl);
340
+ if (!connection || connection.closed || !this.settings.enabled) {
341
+ return;
342
+ }
343
+
344
+ const attempt = connection.attempt + 1;
345
+ connection.attempt = attempt;
346
+ const delay = Math.min(RECONNECT_MAX_MS, RECONNECT_MIN_MS * (2 ** Math.min(attempt, 5)));
347
+ connection.reconnectTimer = setTimeout(() => {
348
+ if (!this.connections.has(wsUrl) || !this.settings.enabled) return;
349
+ void this.connect({
350
+ httpUrl: connection.httpUrl,
351
+ wsUrl: connection.wsUrl,
352
+ }, attempt).catch((error) => {
353
+ this.lastEvent = 'connect-error';
354
+ this.lastError = error instanceof Error ? error.message : String(error);
355
+ this.onChange?.();
356
+ });
357
+ }, delay);
358
+ this.lastEvent = 'reconnecting';
359
+ this.onChange?.();
360
+ }
361
+
362
+ closeConnection(connection) {
363
+ connection.closed = true;
364
+ if (connection.reconnectTimer) {
365
+ clearTimeout(connection.reconnectTimer);
366
+ connection.reconnectTimer = null;
367
+ }
368
+ try { connection.ws?.close(); } catch {}
369
+ }
370
+
371
+ stop() {
372
+ for (const connection of this.connections.values()) {
373
+ this.closeConnection(connection);
374
+ }
375
+ this.connections.clear();
376
+ this.onChange?.();
377
+ }
378
+ }