@glwhappen/web-code 1.32.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 (479) hide show
  1. package/LICENSE +718 -0
  2. package/README.de.md +250 -0
  3. package/README.ja.md +242 -0
  4. package/README.ko.md +242 -0
  5. package/README.md +252 -0
  6. package/README.ru.md +250 -0
  7. package/README.tr.md +252 -0
  8. package/README.zh-CN.md +242 -0
  9. package/dist/api-docs.html +879 -0
  10. package/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  11. package/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  12. package/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  13. package/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  14. package/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  15. package/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  16. package/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  17. package/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  18. package/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  19. package/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  20. package/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  21. package/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  22. package/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  23. package/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  24. package/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  25. package/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  26. package/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  27. package/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  28. package/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  29. package/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  30. package/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  31. package/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  32. package/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  33. package/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  34. package/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  35. package/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  36. package/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  37. package/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  38. package/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  39. package/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  40. package/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  41. package/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  42. package/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  43. package/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  44. package/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  45. package/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  46. package/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  47. package/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  48. package/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  49. package/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  50. package/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  51. package/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  52. package/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  53. package/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  54. package/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  55. package/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  56. package/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  57. package/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  58. package/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  59. package/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  60. package/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  61. package/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  62. package/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  63. package/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  64. package/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  65. package/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  66. package/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  67. package/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  68. package/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  69. package/dist/assets/index-Ct6oPUQk.css +32 -0
  70. package/dist/assets/index-u6XmIqLb.js +1346 -0
  71. package/dist/assets/vendor-codemirror-OwyKSvPE.js +41 -0
  72. package/dist/assets/vendor-react-BGZc9oRE.js +59 -0
  73. package/dist/assets/vendor-xterm-CJZjLICi.js +66 -0
  74. package/dist/clear-cache.html +85 -0
  75. package/dist/convert-icons.md +53 -0
  76. package/dist/favicon.png +0 -0
  77. package/dist/favicon.svg +9 -0
  78. package/dist/generate-icons.js +49 -0
  79. package/dist/icons/claude-ai-icon.svg +1 -0
  80. package/dist/icons/codex-white.svg +3 -0
  81. package/dist/icons/codex.svg +3 -0
  82. package/dist/icons/cursor-white.svg +12 -0
  83. package/dist/icons/cursor.svg +1 -0
  84. package/dist/icons/gemini-ai-icon.svg +1 -0
  85. package/dist/icons/icon-128x128.png +0 -0
  86. package/dist/icons/icon-128x128.svg +12 -0
  87. package/dist/icons/icon-144x144.png +0 -0
  88. package/dist/icons/icon-144x144.svg +12 -0
  89. package/dist/icons/icon-152x152.png +0 -0
  90. package/dist/icons/icon-152x152.svg +12 -0
  91. package/dist/icons/icon-192x192.png +0 -0
  92. package/dist/icons/icon-192x192.svg +12 -0
  93. package/dist/icons/icon-384x384.png +0 -0
  94. package/dist/icons/icon-384x384.svg +12 -0
  95. package/dist/icons/icon-512x512.png +0 -0
  96. package/dist/icons/icon-512x512.svg +12 -0
  97. package/dist/icons/icon-72x72.png +0 -0
  98. package/dist/icons/icon-72x72.svg +12 -0
  99. package/dist/icons/icon-96x96.png +0 -0
  100. package/dist/icons/icon-96x96.svg +12 -0
  101. package/dist/icons/icon-template.svg +12 -0
  102. package/dist/index.html +52 -0
  103. package/dist/logo-128.png +0 -0
  104. package/dist/logo-256.png +0 -0
  105. package/dist/logo-32.png +0 -0
  106. package/dist/logo-512.png +0 -0
  107. package/dist/logo-64.png +0 -0
  108. package/dist/logo.svg +17 -0
  109. package/dist/manifest.json +61 -0
  110. package/dist/screenshots/cli-selection.png +0 -0
  111. package/dist/screenshots/desktop-main.png +0 -0
  112. package/dist/screenshots/mobile-chat.png +0 -0
  113. package/dist/screenshots/tools-modal.png +0 -0
  114. package/dist/sw.js +124 -0
  115. package/dist-server/server/claude-sdk.js +738 -0
  116. package/dist-server/server/claude-sdk.js.map +1 -0
  117. package/dist-server/server/cli.js +641 -0
  118. package/dist-server/server/cli.js.map +1 -0
  119. package/dist-server/server/constants/config.js +6 -0
  120. package/dist-server/server/constants/config.js.map +1 -0
  121. package/dist-server/server/cursor-cli.js +271 -0
  122. package/dist-server/server/cursor-cli.js.map +1 -0
  123. package/dist-server/server/gemini-cli.js +539 -0
  124. package/dist-server/server/gemini-cli.js.map +1 -0
  125. package/dist-server/server/gemini-response-handler.js +72 -0
  126. package/dist-server/server/gemini-response-handler.js.map +1 -0
  127. package/dist-server/server/index.js +1340 -0
  128. package/dist-server/server/index.js.map +1 -0
  129. package/dist-server/server/load-env.js +32 -0
  130. package/dist-server/server/load-env.js.map +1 -0
  131. package/dist-server/server/middleware/auth.js +117 -0
  132. package/dist-server/server/middleware/auth.js.map +1 -0
  133. package/dist-server/server/modules/database/connection.js +125 -0
  134. package/dist-server/server/modules/database/connection.js.map +1 -0
  135. package/dist-server/server/modules/database/index.js +13 -0
  136. package/dist-server/server/modules/database/index.js.map +1 -0
  137. package/dist-server/server/modules/database/init-db.js +18 -0
  138. package/dist-server/server/modules/database/init-db.js.map +1 -0
  139. package/dist-server/server/modules/database/migrations.js +419 -0
  140. package/dist-server/server/modules/database/migrations.js.map +1 -0
  141. package/dist-server/server/modules/database/repositories/api-keys.js +72 -0
  142. package/dist-server/server/modules/database/repositories/api-keys.js.map +1 -0
  143. package/dist-server/server/modules/database/repositories/app-config.js +47 -0
  144. package/dist-server/server/modules/database/repositories/app-config.js.map +1 -0
  145. package/dist-server/server/modules/database/repositories/credentials.js +68 -0
  146. package/dist-server/server/modules/database/repositories/credentials.js.map +1 -0
  147. package/dist-server/server/modules/database/repositories/github-tokens.js +54 -0
  148. package/dist-server/server/modules/database/repositories/github-tokens.js.map +1 -0
  149. package/dist-server/server/modules/database/repositories/notification-preferences.js +72 -0
  150. package/dist-server/server/modules/database/repositories/notification-preferences.js.map +1 -0
  151. package/dist-server/server/modules/database/repositories/projects.db.integration.test.js +67 -0
  152. package/dist-server/server/modules/database/repositories/projects.db.integration.test.js.map +1 -0
  153. package/dist-server/server/modules/database/repositories/projects.db.js +185 -0
  154. package/dist-server/server/modules/database/repositories/projects.db.js.map +1 -0
  155. package/dist-server/server/modules/database/repositories/push-subscriptions.js +49 -0
  156. package/dist-server/server/modules/database/repositories/push-subscriptions.js.map +1 -0
  157. package/dist-server/server/modules/database/repositories/scan-state.db.js +31 -0
  158. package/dist-server/server/modules/database/repositories/scan-state.db.js.map +1 -0
  159. package/dist-server/server/modules/database/repositories/sessions.db.integration.test.js +64 -0
  160. package/dist-server/server/modules/database/repositories/sessions.db.integration.test.js.map +1 -0
  161. package/dist-server/server/modules/database/repositories/sessions.db.js +150 -0
  162. package/dist-server/server/modules/database/repositories/sessions.db.js.map +1 -0
  163. package/dist-server/server/modules/database/repositories/users.js +116 -0
  164. package/dist-server/server/modules/database/repositories/users.js.map +1 -0
  165. package/dist-server/server/modules/database/repositories/vapid-keys.js +38 -0
  166. package/dist-server/server/modules/database/repositories/vapid-keys.js.map +1 -0
  167. package/dist-server/server/modules/database/schema.js +150 -0
  168. package/dist-server/server/modules/database/schema.js.map +1 -0
  169. package/dist-server/server/modules/projects/index.js +4 -0
  170. package/dist-server/server/modules/projects/index.js.map +1 -0
  171. package/dist-server/server/modules/projects/projects.routes.js +225 -0
  172. package/dist-server/server/modules/projects/projects.routes.js.map +1 -0
  173. package/dist-server/server/modules/projects/services/project-clone.service.js +220 -0
  174. package/dist-server/server/modules/projects/services/project-clone.service.js.map +1 -0
  175. package/dist-server/server/modules/projects/services/project-delete.service.js +83 -0
  176. package/dist-server/server/modules/projects/services/project-delete.service.js.map +1 -0
  177. package/dist-server/server/modules/projects/services/project-management.service.js +99 -0
  178. package/dist-server/server/modules/projects/services/project-management.service.js.map +1 -0
  179. package/dist-server/server/modules/projects/services/project-star.service.js +60 -0
  180. package/dist-server/server/modules/projects/services/project-star.service.js.map +1 -0
  181. package/dist-server/server/modules/projects/services/projects-has-taskmaster.service.js +171 -0
  182. package/dist-server/server/modules/projects/services/projects-has-taskmaster.service.js.map +1 -0
  183. package/dist-server/server/modules/projects/services/projects-with-sessions-fetch.service.js +213 -0
  184. package/dist-server/server/modules/projects/services/projects-with-sessions-fetch.service.js.map +1 -0
  185. package/dist-server/server/modules/projects/tests/project-clone.service.test.js +129 -0
  186. package/dist-server/server/modules/projects/tests/project-clone.service.test.js.map +1 -0
  187. package/dist-server/server/modules/projects/tests/project-management.service.test.js +89 -0
  188. package/dist-server/server/modules/projects/tests/project-management.service.test.js.map +1 -0
  189. package/dist-server/server/modules/projects/tests/project-star.service.test.js +99 -0
  190. package/dist-server/server/modules/projects/tests/project-star.service.test.js.map +1 -0
  191. package/dist-server/server/modules/projects/tests/projects-has-taskmaster.service.test.js +88 -0
  192. package/dist-server/server/modules/projects/tests/projects-has-taskmaster.service.test.js.map +1 -0
  193. package/dist-server/server/modules/providers/index.js +5 -0
  194. package/dist-server/server/modules/providers/index.js.map +1 -0
  195. package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js +104 -0
  196. package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js.map +1 -0
  197. package/dist-server/server/modules/providers/list/claude/claude-mcp.provider.js +103 -0
  198. package/dist-server/server/modules/providers/list/claude/claude-mcp.provider.js.map +1 -0
  199. package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js +116 -0
  200. package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js.map +1 -0
  201. package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js +546 -0
  202. package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js.map +1 -0
  203. package/dist-server/server/modules/providers/list/claude/claude-skills.provider.js +198 -0
  204. package/dist-server/server/modules/providers/list/claude/claude-skills.provider.js.map +1 -0
  205. package/dist-server/server/modules/providers/list/claude/claude.provider.js +17 -0
  206. package/dist-server/server/modules/providers/list/claude/claude.provider.js.map +1 -0
  207. package/dist-server/server/modules/providers/list/codex/codex-auth.provider.js +84 -0
  208. package/dist-server/server/modules/providers/list/codex/codex-auth.provider.js.map +1 -0
  209. package/dist-server/server/modules/providers/list/codex/codex-mcp.provider.js +107 -0
  210. package/dist-server/server/modules/providers/list/codex/codex-mcp.provider.js.map +1 -0
  211. package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js +123 -0
  212. package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js.map +1 -0
  213. package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js +513 -0
  214. package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js.map +1 -0
  215. package/dist-server/server/modules/providers/list/codex/codex-skills.provider.js +82 -0
  216. package/dist-server/server/modules/providers/list/codex/codex-skills.provider.js.map +1 -0
  217. package/dist-server/server/modules/providers/list/codex/codex.provider.js +17 -0
  218. package/dist-server/server/modules/providers/list/codex/codex.provider.js.map +1 -0
  219. package/dist-server/server/modules/providers/list/cursor/cursor-auth.provider.js +118 -0
  220. package/dist-server/server/modules/providers/list/cursor/cursor-auth.provider.js.map +1 -0
  221. package/dist-server/server/modules/providers/list/cursor/cursor-mcp.provider.js +80 -0
  222. package/dist-server/server/modules/providers/list/cursor/cursor-mcp.provider.js.map +1 -0
  223. package/dist-server/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.js +105 -0
  224. package/dist-server/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.js.map +1 -0
  225. package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js +545 -0
  226. package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js.map +1 -0
  227. package/dist-server/server/modules/providers/list/cursor/cursor-skills.provider.js +28 -0
  228. package/dist-server/server/modules/providers/list/cursor/cursor-skills.provider.js.map +1 -0
  229. package/dist-server/server/modules/providers/list/cursor/cursor.provider.js +17 -0
  230. package/dist-server/server/modules/providers/list/cursor/cursor.provider.js.map +1 -0
  231. package/dist-server/server/modules/providers/list/gemini/gemini-auth.provider.js +254 -0
  232. package/dist-server/server/modules/providers/list/gemini/gemini-auth.provider.js.map +1 -0
  233. package/dist-server/server/modules/providers/list/gemini/gemini-mcp.provider.js +82 -0
  234. package/dist-server/server/modules/providers/list/gemini/gemini-mcp.provider.js.map +1 -0
  235. package/dist-server/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.js +312 -0
  236. package/dist-server/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.js.map +1 -0
  237. package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js +484 -0
  238. package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js.map +1 -0
  239. package/dist-server/server/modules/providers/list/gemini/gemini-skills.provider.js +33 -0
  240. package/dist-server/server/modules/providers/list/gemini/gemini-skills.provider.js.map +1 -0
  241. package/dist-server/server/modules/providers/list/gemini/gemini.provider.js +17 -0
  242. package/dist-server/server/modules/providers/list/gemini/gemini.provider.js.map +1 -0
  243. package/dist-server/server/modules/providers/provider.registry.js +31 -0
  244. package/dist-server/server/modules/providers/provider.registry.js.map +1 -0
  245. package/dist-server/server/modules/providers/provider.routes.js +377 -0
  246. package/dist-server/server/modules/providers/provider.routes.js.map +1 -0
  247. package/dist-server/server/modules/providers/services/mcp.service.js +69 -0
  248. package/dist-server/server/modules/providers/services/mcp.service.js.map +1 -0
  249. package/dist-server/server/modules/providers/services/provider-auth.service.js +25 -0
  250. package/dist-server/server/modules/providers/services/provider-auth.service.js.map +1 -0
  251. package/dist-server/server/modules/providers/services/session-conversations-search.service.js +984 -0
  252. package/dist-server/server/modules/providers/services/session-conversations-search.service.js.map +1 -0
  253. package/dist-server/server/modules/providers/services/session-synchronizer.service.js +56 -0
  254. package/dist-server/server/modules/providers/services/session-synchronizer.service.js.map +1 -0
  255. package/dist-server/server/modules/providers/services/sessions-watcher.service.js +269 -0
  256. package/dist-server/server/modules/providers/services/sessions-watcher.service.js.map +1 -0
  257. package/dist-server/server/modules/providers/services/sessions.service.js +179 -0
  258. package/dist-server/server/modules/providers/services/sessions.service.js.map +1 -0
  259. package/dist-server/server/modules/providers/services/skills.service.js +11 -0
  260. package/dist-server/server/modules/providers/services/skills.service.js.map +1 -0
  261. package/dist-server/server/modules/providers/shared/base/abstract.provider.js +14 -0
  262. package/dist-server/server/modules/providers/shared/base/abstract.provider.js.map +1 -0
  263. package/dist-server/server/modules/providers/shared/mcp/mcp.provider.js +102 -0
  264. package/dist-server/server/modules/providers/shared/mcp/mcp.provider.js.map +1 -0
  265. package/dist-server/server/modules/providers/shared/skills/skills.provider.js +45 -0
  266. package/dist-server/server/modules/providers/shared/skills/skills.provider.js.map +1 -0
  267. package/dist-server/server/modules/providers/tests/mcp.test.js +250 -0
  268. package/dist-server/server/modules/providers/tests/mcp.test.js.map +1 -0
  269. package/dist-server/server/modules/providers/tests/skills.test.js +226 -0
  270. package/dist-server/server/modules/providers/tests/skills.test.js.map +1 -0
  271. package/dist-server/server/modules/websocket/index.js +3 -0
  272. package/dist-server/server/modules/websocket/index.js.map +1 -0
  273. package/dist-server/server/modules/websocket/services/chat-websocket.service.js +192 -0
  274. package/dist-server/server/modules/websocket/services/chat-websocket.service.js.map +1 -0
  275. package/dist-server/server/modules/websocket/services/plugin-websocket-proxy.service.js +52 -0
  276. package/dist-server/server/modules/websocket/services/plugin-websocket-proxy.service.js.map +1 -0
  277. package/dist-server/server/modules/websocket/services/shell-websocket.service.js +360 -0
  278. package/dist-server/server/modules/websocket/services/shell-websocket.service.js.map +1 -0
  279. package/dist-server/server/modules/websocket/services/websocket-auth.service.js +32 -0
  280. package/dist-server/server/modules/websocket/services/websocket-auth.service.js.map +1 -0
  281. package/dist-server/server/modules/websocket/services/websocket-server.service.js +36 -0
  282. package/dist-server/server/modules/websocket/services/websocket-server.service.js.map +1 -0
  283. package/dist-server/server/modules/websocket/services/websocket-state.service.js +14 -0
  284. package/dist-server/server/modules/websocket/services/websocket-state.service.js.map +1 -0
  285. package/dist-server/server/modules/websocket/services/websocket-writer.service.js +32 -0
  286. package/dist-server/server/modules/websocket/services/websocket-writer.service.js.map +1 -0
  287. package/dist-server/server/openai-codex.js +418 -0
  288. package/dist-server/server/openai-codex.js.map +1 -0
  289. package/dist-server/server/routes/admin.js +109 -0
  290. package/dist-server/server/routes/admin.js.map +1 -0
  291. package/dist-server/server/routes/agent.js +1145 -0
  292. package/dist-server/server/routes/agent.js.map +1 -0
  293. package/dist-server/server/routes/auth.js +123 -0
  294. package/dist-server/server/routes/auth.js.map +1 -0
  295. package/dist-server/server/routes/commands.js +487 -0
  296. package/dist-server/server/routes/commands.js.map +1 -0
  297. package/dist-server/server/routes/cursor.js +49 -0
  298. package/dist-server/server/routes/cursor.js.map +1 -0
  299. package/dist-server/server/routes/gemini.js +25 -0
  300. package/dist-server/server/routes/gemini.js.map +1 -0
  301. package/dist-server/server/routes/git.js +1263 -0
  302. package/dist-server/server/routes/git.js.map +1 -0
  303. package/dist-server/server/routes/mcp-utils.js +29 -0
  304. package/dist-server/server/routes/mcp-utils.js.map +1 -0
  305. package/dist-server/server/routes/plugins.js +266 -0
  306. package/dist-server/server/routes/plugins.js.map +1 -0
  307. package/dist-server/server/routes/settings.js +259 -0
  308. package/dist-server/server/routes/settings.js.map +1 -0
  309. package/dist-server/server/routes/taskmaster.js +1360 -0
  310. package/dist-server/server/routes/taskmaster.js.map +1 -0
  311. package/dist-server/server/routes/user.js +115 -0
  312. package/dist-server/server/routes/user.js.map +1 -0
  313. package/dist-server/server/services/notification-orchestrator.js +177 -0
  314. package/dist-server/server/services/notification-orchestrator.js.map +1 -0
  315. package/dist-server/server/services/vapid-keys.js +27 -0
  316. package/dist-server/server/services/vapid-keys.js.map +1 -0
  317. package/dist-server/server/sessionManager.js +215 -0
  318. package/dist-server/server/sessionManager.js.map +1 -0
  319. package/dist-server/server/shared/claude-cli-path.js +103 -0
  320. package/dist-server/server/shared/claude-cli-path.js.map +1 -0
  321. package/dist-server/server/shared/claude-cli-path.test.js +45 -0
  322. package/dist-server/server/shared/claude-cli-path.test.js.map +1 -0
  323. package/dist-server/server/shared/default-user.js +29 -0
  324. package/dist-server/server/shared/default-user.js.map +1 -0
  325. package/dist-server/server/shared/frontmatter.js +16 -0
  326. package/dist-server/server/shared/frontmatter.js.map +1 -0
  327. package/dist-server/server/shared/interfaces.js +2 -0
  328. package/dist-server/server/shared/interfaces.js.map +1 -0
  329. package/dist-server/server/shared/types.js +2 -0
  330. package/dist-server/server/shared/types.js.map +1 -0
  331. package/dist-server/server/shared/utils.js +633 -0
  332. package/dist-server/server/shared/utils.js.map +1 -0
  333. package/dist-server/server/utils/colors.js +20 -0
  334. package/dist-server/server/utils/colors.js.map +1 -0
  335. package/dist-server/server/utils/commandParser.js +255 -0
  336. package/dist-server/server/utils/commandParser.js.map +1 -0
  337. package/dist-server/server/utils/gitConfig.js +36 -0
  338. package/dist-server/server/utils/gitConfig.js.map +1 -0
  339. package/dist-server/server/utils/mcp-detector.js +134 -0
  340. package/dist-server/server/utils/mcp-detector.js.map +1 -0
  341. package/dist-server/server/utils/plugin-loader.js +413 -0
  342. package/dist-server/server/utils/plugin-loader.js.map +1 -0
  343. package/dist-server/server/utils/plugin-process-manager.js +163 -0
  344. package/dist-server/server/utils/plugin-process-manager.js.map +1 -0
  345. package/dist-server/server/utils/runtime-paths.js +30 -0
  346. package/dist-server/server/utils/runtime-paths.js.map +1 -0
  347. package/dist-server/server/utils/taskmaster-websocket.js +124 -0
  348. package/dist-server/server/utils/taskmaster-websocket.js.map +1 -0
  349. package/dist-server/server/utils/url-detection.js +58 -0
  350. package/dist-server/server/utils/url-detection.js.map +1 -0
  351. package/dist-server/shared/modelConstants.js +99 -0
  352. package/dist-server/shared/modelConstants.js.map +1 -0
  353. package/dist-server/shared/networkHosts.js +20 -0
  354. package/dist-server/shared/networkHosts.js.map +1 -0
  355. package/package.json +169 -0
  356. package/scripts/fix-node-pty.js +67 -0
  357. package/server/claude-sdk.js +864 -0
  358. package/server/cli.js +688 -0
  359. package/server/constants/config.js +5 -0
  360. package/server/cursor-cli.js +334 -0
  361. package/server/gemini-cli.js +622 -0
  362. package/server/gemini-response-handler.js +79 -0
  363. package/server/index.js +1505 -0
  364. package/server/load-env.js +34 -0
  365. package/server/middleware/auth.js +142 -0
  366. package/server/modules/database/connection.ts +143 -0
  367. package/server/modules/database/index.ts +12 -0
  368. package/server/modules/database/init-db.ts +17 -0
  369. package/server/modules/database/migrations.ts +496 -0
  370. package/server/modules/database/repositories/api-keys.ts +119 -0
  371. package/server/modules/database/repositories/app-config.ts +53 -0
  372. package/server/modules/database/repositories/credentials.ts +106 -0
  373. package/server/modules/database/repositories/github-tokens.ts +100 -0
  374. package/server/modules/database/repositories/notification-preferences.ts +103 -0
  375. package/server/modules/database/repositories/projects.db.integration.test.ts +78 -0
  376. package/server/modules/database/repositories/projects.db.ts +210 -0
  377. package/server/modules/database/repositories/push-subscriptions.ts +80 -0
  378. package/server/modules/database/repositories/scan-state.db.ts +42 -0
  379. package/server/modules/database/repositories/sessions.db.integration.test.ts +78 -0
  380. package/server/modules/database/repositories/sessions.db.ts +230 -0
  381. package/server/modules/database/repositories/users.ts +186 -0
  382. package/server/modules/database/repositories/vapid-keys.ts +57 -0
  383. package/server/modules/database/schema.ts +159 -0
  384. package/server/modules/projects/index.ts +6 -0
  385. package/server/modules/projects/projects.routes.ts +292 -0
  386. package/server/modules/projects/services/project-clone.service.ts +327 -0
  387. package/server/modules/projects/services/project-delete.service.ts +95 -0
  388. package/server/modules/projects/services/project-management.service.ts +158 -0
  389. package/server/modules/projects/services/project-star.service.ts +78 -0
  390. package/server/modules/projects/services/projects-has-taskmaster.service.ts +257 -0
  391. package/server/modules/projects/services/projects-with-sessions-fetch.service.ts +355 -0
  392. package/server/modules/projects/tests/project-clone.service.test.ts +186 -0
  393. package/server/modules/projects/tests/project-management.service.test.ts +122 -0
  394. package/server/modules/projects/tests/project-star.service.test.ts +128 -0
  395. package/server/modules/projects/tests/projects-has-taskmaster.service.test.ts +107 -0
  396. package/server/modules/providers/README.md +346 -0
  397. package/server/modules/providers/index.ts +5 -0
  398. package/server/modules/providers/list/claude/claude-auth.provider.ts +124 -0
  399. package/server/modules/providers/list/claude/claude-mcp.provider.ts +135 -0
  400. package/server/modules/providers/list/claude/claude-session-synchronizer.provider.ts +179 -0
  401. package/server/modules/providers/list/claude/claude-sessions.provider.ts +642 -0
  402. package/server/modules/providers/list/claude/claude-skills.provider.ts +257 -0
  403. package/server/modules/providers/list/claude/claude.provider.ts +24 -0
  404. package/server/modules/providers/list/codex/codex-auth.provider.ts +100 -0
  405. package/server/modules/providers/list/codex/codex-mcp.provider.ts +135 -0
  406. package/server/modules/providers/list/codex/codex-session-synchronizer.provider.ts +182 -0
  407. package/server/modules/providers/list/codex/codex-sessions.provider.ts +589 -0
  408. package/server/modules/providers/list/codex/codex-skills.provider.ts +100 -0
  409. package/server/modules/providers/list/codex/codex.provider.ts +24 -0
  410. package/server/modules/providers/list/cursor/cursor-auth.provider.ts +143 -0
  411. package/server/modules/providers/list/cursor/cursor-mcp.provider.ts +108 -0
  412. package/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.ts +155 -0
  413. package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +624 -0
  414. package/server/modules/providers/list/cursor/cursor-skills.provider.ts +31 -0
  415. package/server/modules/providers/list/cursor/cursor.provider.ts +24 -0
  416. package/server/modules/providers/list/gemini/gemini-auth.provider.ts +307 -0
  417. package/server/modules/providers/list/gemini/gemini-mcp.provider.ts +110 -0
  418. package/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.ts +407 -0
  419. package/server/modules/providers/list/gemini/gemini-sessions.provider.ts +552 -0
  420. package/server/modules/providers/list/gemini/gemini-skills.provider.ts +36 -0
  421. package/server/modules/providers/list/gemini/gemini.provider.ts +24 -0
  422. package/server/modules/providers/provider.registry.ts +36 -0
  423. package/server/modules/providers/provider.routes.ts +488 -0
  424. package/server/modules/providers/services/mcp.service.ts +94 -0
  425. package/server/modules/providers/services/provider-auth.service.ts +26 -0
  426. package/server/modules/providers/services/session-conversations-search.service.ts +1319 -0
  427. package/server/modules/providers/services/session-synchronizer.service.ts +75 -0
  428. package/server/modules/providers/services/sessions-watcher.service.ts +318 -0
  429. package/server/modules/providers/services/sessions.service.ts +240 -0
  430. package/server/modules/providers/services/skills.service.ts +15 -0
  431. package/server/modules/providers/shared/base/abstract.provider.ts +29 -0
  432. package/server/modules/providers/shared/mcp/mcp.provider.ts +151 -0
  433. package/server/modules/providers/shared/skills/skills.provider.ts +64 -0
  434. package/server/modules/providers/tests/mcp.test.ts +293 -0
  435. package/server/modules/providers/tests/skills.test.ts +446 -0
  436. package/server/modules/websocket/README.md +267 -0
  437. package/server/modules/websocket/index.ts +2 -0
  438. package/server/modules/websocket/services/chat-websocket.service.ts +275 -0
  439. package/server/modules/websocket/services/plugin-websocket-proxy.service.ts +65 -0
  440. package/server/modules/websocket/services/shell-websocket.service.ts +489 -0
  441. package/server/modules/websocket/services/websocket-auth.service.ts +54 -0
  442. package/server/modules/websocket/services/websocket-server.service.ts +58 -0
  443. package/server/modules/websocket/services/websocket-state.service.ts +16 -0
  444. package/server/modules/websocket/services/websocket-writer.service.ts +38 -0
  445. package/server/openai-codex.js +474 -0
  446. package/server/routes/admin.js +128 -0
  447. package/server/routes/agent.js +1246 -0
  448. package/server/routes/auth.js +144 -0
  449. package/server/routes/commands.js +556 -0
  450. package/server/routes/cursor.js +52 -0
  451. package/server/routes/gemini.js +30 -0
  452. package/server/routes/git.js +1493 -0
  453. package/server/routes/mcp-utils.js +31 -0
  454. package/server/routes/plugins.js +307 -0
  455. package/server/routes/settings.js +286 -0
  456. package/server/routes/taskmaster.js +1468 -0
  457. package/server/routes/user.js +123 -0
  458. package/server/services/notification-orchestrator.js +228 -0
  459. package/server/services/vapid-keys.js +36 -0
  460. package/server/sessionManager.js +248 -0
  461. package/server/shared/claude-cli-path.test.ts +61 -0
  462. package/server/shared/claude-cli-path.ts +139 -0
  463. package/server/shared/default-user.ts +30 -0
  464. package/server/shared/frontmatter.ts +18 -0
  465. package/server/shared/interfaces.ts +111 -0
  466. package/server/shared/types.ts +406 -0
  467. package/server/shared/utils.ts +763 -0
  468. package/server/tsconfig.json +36 -0
  469. package/server/utils/colors.js +21 -0
  470. package/server/utils/commandParser.js +305 -0
  471. package/server/utils/gitConfig.js +34 -0
  472. package/server/utils/mcp-detector.js +147 -0
  473. package/server/utils/plugin-loader.js +457 -0
  474. package/server/utils/plugin-process-manager.js +184 -0
  475. package/server/utils/runtime-paths.js +37 -0
  476. package/server/utils/taskmaster-websocket.js +135 -0
  477. package/server/utils/url-detection.js +71 -0
  478. package/shared/modelConstants.js +107 -0
  479. package/shared/networkHosts.js +22 -0
@@ -0,0 +1,267 @@
1
+ # WebSocket Module
2
+
3
+ This module owns the server-side WebSocket gateway used by:
4
+
5
+ 1. Chat streaming (`/ws`)
6
+ 2. Interactive terminal sessions (`/shell`)
7
+ 3. Plugin WebSocket passthrough (`/plugin-ws/:pluginName`)
8
+
9
+ It is intentionally structured as **small services** plus a **barrel export** in `index.ts`.
10
+
11
+ ## Public API
12
+
13
+ `server/modules/websocket/index.ts` exports:
14
+
15
+ 1. `createWebSocketServer(server, dependencies)`
16
+ Creates and wires the shared `ws` server.
17
+ 2. `connectedClients` and `WS_OPEN_STATE`
18
+ Shared chat client registry and open-state constant used by other modules.
19
+
20
+ ## Why Dependency Injection Is Used
21
+
22
+ The module receives runtime-specific functions from `server/index.js` instead of importing legacy runtime files directly.
23
+
24
+ Benefits:
25
+
26
+ 1. Keeps module boundaries clean (`server/modules/*` architecture rule).
27
+ 2. Makes each service easier to test in isolation.
28
+ 3. Keeps WebSocket transport concerns separate from provider runtime concerns.
29
+
30
+ ## Service Map
31
+
32
+ | File | Responsibility |
33
+ |---|---|
34
+ | `services/websocket-server.service.ts` | Creates `WebSocketServer`, binds `verifyClient`, routes connection by pathname |
35
+ | `services/websocket-auth.service.ts` | Authenticates upgrade requests and attaches `request.user` |
36
+ | `services/chat-websocket.service.ts` | Handles `/ws` chat protocol and provider command/session control messages |
37
+ | `services/shell-websocket.service.ts` | Handles `/shell` PTY lifecycle, reconnect buffering, auth URL detection |
38
+ | `services/plugin-websocket-proxy.service.ts` | Bridges client socket to plugin socket |
39
+ | `services/websocket-writer.service.ts` | Adapts raw WebSocket to writer interface (`send`, `setSessionId`, `getSessionId`) |
40
+ | `services/websocket-state.service.ts` | Holds shared chat client set and open-state constant |
41
+
42
+ ## High-Level Architecture
43
+
44
+ ```mermaid
45
+ flowchart LR
46
+ A[HTTP Server] --> B[createWebSocketServer]
47
+ B --> C[verifyWebSocketClient]
48
+ B --> D{Pathname}
49
+ D -->|/ws| E[handleChatConnection]
50
+ D -->|/shell| F[handleShellConnection]
51
+ D -->|/plugin-ws/:name| G[handlePluginWsProxy]
52
+ D -->|other| H[close()]
53
+
54
+ E --> I[connectedClients Set]
55
+ E --> J[WebSocketWriter]
56
+ F --> K[ptySessionsMap]
57
+ G --> L[Upstream Plugin ws://127.0.0.1:port/ws]
58
+
59
+ I --> M[projects.service broadcastProgress]
60
+ I --> N[sessions-watcher.service projects_updated]
61
+ ```
62
+
63
+ ## Connection Handshake + Routing
64
+
65
+ ```mermaid
66
+ sequenceDiagram
67
+ participant Client
68
+ participant WSS as WebSocketServer
69
+ participant Auth as verifyWebSocketClient
70
+ participant Router as connection router
71
+ participant Chat as /ws handler
72
+ participant Shell as /shell handler
73
+ participant Proxy as /plugin-ws handler
74
+
75
+ Client->>WSS: Upgrade Request
76
+ WSS->>Auth: verifyClient(info)
77
+ alt Platform mode
78
+ Auth->>Auth: authenticateWebSocket(null)
79
+ Auth->>Auth: attach request.user
80
+ else OSS mode
81
+ Auth->>Auth: read token from ?token or Authorization
82
+ Auth->>Auth: authenticateWebSocket(token)
83
+ Auth->>Auth: attach request.user
84
+ end
85
+
86
+ alt Auth failed
87
+ Auth-->>WSS: false (reject handshake)
88
+ else Auth ok
89
+ Auth-->>WSS: true
90
+ WSS->>Router: on("connection", ws, request)
91
+ alt pathname == /ws
92
+ Router->>Chat: handleChatConnection(ws, request, deps.chat)
93
+ else pathname == /shell
94
+ Router->>Shell: handleShellConnection(ws, deps.shell)
95
+ else pathname startsWith /plugin-ws/
96
+ Router->>Proxy: handlePluginWsProxy(ws, pathname, getPluginPort)
97
+ else unknown
98
+ Router->>Router: ws.close()
99
+ end
100
+ end
101
+ ```
102
+
103
+ ## `/ws` Chat Flow
104
+
105
+ When a chat socket connects:
106
+
107
+ 1. Add socket to `connectedClients`.
108
+ 2. Build `WebSocketWriter` (captures `userId` from authenticated request).
109
+ 3. Parse each incoming message with `parseIncomingJsonObject`.
110
+ 4. Dispatch by `data.type`.
111
+ 5. On close, remove socket from `connectedClients`.
112
+
113
+ ### Chat Message Dispatch
114
+
115
+ ```mermaid
116
+ flowchart TD
117
+ A[Incoming WS message] --> B[parseIncomingJsonObject]
118
+ B -->|invalid| C[send {type:error}]
119
+ B -->|ok| D{data.type}
120
+
121
+ D -->|claude-command| E[queryClaudeSDK]
122
+ D -->|cursor-command| F[spawnCursor]
123
+ D -->|codex-command| G[queryCodex]
124
+ D -->|gemini-command| H[spawnGemini]
125
+ D -->|cursor-resume| I[spawnCursor resume]
126
+ D -->|abort-session| J[abort by provider]
127
+ D -->|claude-permission-response| K[resolveToolApproval]
128
+ D -->|cursor-abort| L[abortCursorSession]
129
+ D -->|check-session-status| M[is*SessionActive + optional reconnectSessionWriter]
130
+ D -->|get-pending-permissions| N[getPendingApprovalsForSession]
131
+ D -->|get-active-sessions| O[getActive*Sessions]
132
+ ```
133
+
134
+ ### Chat Notes
135
+
136
+ 1. `abort-session` returns a normalized `complete` message with `aborted: true`.
137
+ 2. `check-session-status` returns `{ type: "session-status", isProcessing }`.
138
+ 3. Claude status checks can reconnect output stream to the new socket via `reconnectSessionWriter`.
139
+
140
+ ## `/shell` Terminal Flow
141
+
142
+ The shell handler manages persistent PTY sessions keyed by:
143
+
144
+ `<projectPath>_<sessionIdOrDefault>[_cmd_<hash>]`
145
+
146
+ This enables reconnect behavior and isolates command-specific plain-shell sessions.
147
+
148
+ ### Shell Lifecycle
149
+
150
+ ```mermaid
151
+ stateDiagram-v2
152
+ [*] --> WaitingInit
153
+ WaitingInit --> ValidateInit: message.type == init
154
+ ValidateInit --> ReconnectExisting: session key exists and not login reset
155
+ ValidateInit --> SpawnNewPTY: valid path + valid sessionId
156
+ ValidateInit --> EmitError: invalid payload/path/sessionId
157
+
158
+ ReconnectExisting --> Running: attach ws, replay buffer
159
+ SpawnNewPTY --> Running: pty.spawn + wire onData/onExit
160
+
161
+ Running --> Running: input -> pty.write
162
+ Running --> Running: resize -> pty.resize
163
+ Running --> Running: onData -> buffer + output + auth_url detection
164
+ Running --> Exited: onExit
165
+ Running --> Detached: ws close
166
+
167
+ Detached --> Running: reconnect before timeout
168
+ Detached --> Killed: timeout reached -> pty.kill
169
+ Exited --> [*]
170
+ Killed --> [*]
171
+ EmitError --> WaitingInit
172
+ ```
173
+
174
+ ### Shell Behaviors in Detail
175
+
176
+ 1. `init`:
177
+ Reads `projectPath`, `sessionId`, `provider`, `hasSession`, `initialCommand`, `isPlainShell`.
178
+ 2. Login reset:
179
+ For login-like commands, existing keyed PTY session is killed and recreated.
180
+ 3. Validation:
181
+ Path must exist and be a directory; `sessionId` must match safe pattern.
182
+ 4. Command build:
183
+ Provider-specific command construction with resume semantics.
184
+ 5. PTY output buffering:
185
+ Stores up to 5000 chunks for replay on reconnect.
186
+ 6. URL detection:
187
+ Strips ANSI, accumulates text buffer, extracts URLs, emits `auth_url` once per normalized URL, supports `autoOpen`.
188
+ 7. Close behavior:
189
+ Socket disconnect does not instantly kill PTY; session is kept alive and terminated on timeout.
190
+
191
+ ## `/plugin-ws/:pluginName` Proxy Flow
192
+
193
+ ```mermaid
194
+ sequenceDiagram
195
+ participant Client
196
+ participant Proxy as handlePluginWsProxy
197
+ participant PM as getPluginPort
198
+ participant Upstream as Plugin WS
199
+
200
+ Client->>Proxy: Connect /plugin-ws/:name
201
+ Proxy->>Proxy: Validate pluginName regex
202
+ alt Invalid name
203
+ Proxy-->>Client: close(4400, "Invalid plugin name")
204
+ else Valid
205
+ Proxy->>PM: getPluginPort(name)
206
+ alt Plugin not running
207
+ Proxy-->>Client: close(4404, "Plugin not running")
208
+ else Port found
209
+ Proxy->>Upstream: new WebSocket(ws://127.0.0.1:port/ws)
210
+ Client-->>Upstream: relay messages bidirectionally
211
+ Upstream-->>Client: relay messages bidirectionally
212
+ Upstream-->>Client: close propagation
213
+ Client-->>Upstream: close propagation
214
+ Upstream-->>Client: close(4502, "Upstream error") on upstream error
215
+ end
216
+ end
217
+ ```
218
+
219
+ ## Shared Client Registry and Broadcasts
220
+
221
+ Only chat sockets (`/ws`) are tracked in `connectedClients`.
222
+
223
+ That shared set is consumed by:
224
+
225
+ 1. `modules/projects/services/projects-with-sessions-fetch.service.ts`
226
+ Broadcasts `loading_progress` while project snapshots are being built.
227
+ 2. `modules/providers/services/sessions-watcher.service.ts`
228
+ Broadcasts `projects_updated` when provider session artifacts change.
229
+
230
+ This design centralizes cross-module realtime fanout without requiring route-local references to WebSocket internals.
231
+
232
+ ## Writer Adapter (`WebSocketWriter`)
233
+
234
+ `WebSocketWriter` normalizes chat transport behavior to match existing writer-style interfaces used elsewhere.
235
+
236
+ Methods:
237
+
238
+ 1. `send(data)`
239
+ JSON-serializes and sends only if socket is open.
240
+ 2. `setSessionId(sessionId)` / `getSessionId()`
241
+ Supports provider session bookkeeping and resume flows.
242
+ 3. `updateWebSocket(newRawWs)`
243
+ Allows active session stream redirection on reconnect.
244
+
245
+ ## Error Handling and Close Codes
246
+
247
+ Current explicit close codes in this module:
248
+
249
+ 1. `4400`: Invalid plugin name
250
+ 2. `4404`: Plugin not running
251
+ 3. `4502`: Upstream plugin WebSocket error
252
+
253
+ Other errors:
254
+
255
+ 1. Chat handler catches and emits `{ type: "error", error }`.
256
+ 2. Shell handler catches and writes terminal-visible error output.
257
+ 3. Unknown websocket paths are closed immediately.
258
+
259
+ ## Extending This Module
260
+
261
+ To add a new websocket route:
262
+
263
+ 1. Add a new handler service under `services/`.
264
+ 2. Extend `WebSocketServerDependencies` in `websocket-server.service.ts` if needed.
265
+ 3. Add a new pathname branch in the router.
266
+ 4. Wire dependency injection from `server/index.js`.
267
+ 5. Keep `index.ts` as barrel-only export surface.
@@ -0,0 +1,2 @@
1
+ export { WS_OPEN_STATE, connectedClients } from './services/websocket-state.service.js';
2
+ export { createWebSocketServer } from './services/websocket-server.service.js';
@@ -0,0 +1,275 @@
1
+ import type { WebSocket } from 'ws';
2
+
3
+ import { connectedClients } from '@/modules/websocket/services/websocket-state.service.js';
4
+ import { WebSocketWriter } from '@/modules/websocket/services/websocket-writer.service.js';
5
+ import type {
6
+ AnyRecord,
7
+ AuthenticatedWebSocketRequest,
8
+ LLMProvider,
9
+ } from '@/shared/types.js';
10
+ import { createNormalizedMessage, parseIncomingJsonObject } from '@/shared/utils.js';
11
+
12
+ type ChatIncomingMessage = AnyRecord & {
13
+ type?: string;
14
+ command?: string;
15
+ options?: AnyRecord;
16
+ provider?: string;
17
+ sessionId?: string;
18
+ requestId?: string;
19
+ allow?: unknown;
20
+ updatedInput?: unknown;
21
+ message?: unknown;
22
+ rememberEntry?: unknown;
23
+ };
24
+
25
+ const DEFAULT_PROVIDER: LLMProvider = 'claude';
26
+
27
+ type ChatWebSocketDependencies = {
28
+ queryClaudeSDK: (command: string, options: unknown, writer: WebSocketWriter) => Promise<unknown>;
29
+ spawnCursor: (command: string, options: unknown, writer: WebSocketWriter) => Promise<unknown>;
30
+ queryCodex: (command: string, options: unknown, writer: WebSocketWriter) => Promise<unknown>;
31
+ spawnGemini: (command: string, options: unknown, writer: WebSocketWriter) => Promise<unknown>;
32
+ abortClaudeSDKSession: (sessionId: string, userId?: string | number | null) => Promise<boolean>;
33
+ abortCursorSession: (sessionId: string) => boolean;
34
+ abortCodexSession: (sessionId: string, userId?: string | number | null) => boolean;
35
+ abortGeminiSession: (sessionId: string) => boolean;
36
+ resolveToolApproval: (
37
+ requestId: string,
38
+ payload: {
39
+ allow: boolean;
40
+ updatedInput?: unknown;
41
+ message?: string;
42
+ rememberEntry?: unknown;
43
+ }
44
+ ) => void;
45
+ isClaudeSDKSessionActive: (sessionId: string, userId?: string | number | null) => boolean;
46
+ isCursorSessionActive: (sessionId: string) => boolean;
47
+ isCodexSessionActive: (sessionId: string, userId?: string | number | null) => boolean;
48
+ isGeminiSessionActive: (sessionId: string) => boolean;
49
+ reconnectSessionWriter: (sessionId: string, ws: WebSocket, userId?: string | number | null) => boolean;
50
+ getPendingApprovalsForSession: (sessionId: string, userId?: string | number | null) => unknown[];
51
+ getActiveClaudeSDKSessions: (userId?: string | number | null) => unknown;
52
+ getActiveCursorSessions: () => unknown;
53
+ getActiveCodexSessions: (userId?: string | number | null) => unknown;
54
+ getActiveGeminiSessions: () => unknown;
55
+ };
56
+
57
+ /**
58
+ * Normalizes potentially invalid provider names coming from websocket payloads.
59
+ */
60
+ function readProvider(value: unknown): LLMProvider {
61
+ if (value === 'claude' || value === 'cursor' || value === 'codex' || value === 'gemini') {
62
+ return value;
63
+ }
64
+
65
+ return DEFAULT_PROVIDER;
66
+ }
67
+
68
+ /**
69
+ * Extracts the authenticated request user id in the formats currently produced
70
+ * by platform and OSS auth code paths.
71
+ */
72
+ function readRequestUserId(
73
+ request: AuthenticatedWebSocketRequest | undefined
74
+ ): string | number | null {
75
+ const user = request?.user;
76
+ if (!user) {
77
+ return null;
78
+ }
79
+
80
+ if (typeof user.id === 'string' || typeof user.id === 'number') {
81
+ return user.id;
82
+ }
83
+
84
+ if (typeof user.userId === 'string' || typeof user.userId === 'number') {
85
+ return user.userId;
86
+ }
87
+
88
+ return null;
89
+ }
90
+
91
+ /**
92
+ * Handles authenticated chat websocket messages used by the main chat panel.
93
+ */
94
+ export function handleChatConnection(
95
+ ws: WebSocket,
96
+ request: AuthenticatedWebSocketRequest,
97
+ dependencies: ChatWebSocketDependencies
98
+ ): void {
99
+ console.log('[INFO] Chat WebSocket connected');
100
+ connectedClients.add(ws);
101
+
102
+ const writer = new WebSocketWriter(ws, readRequestUserId(request));
103
+
104
+ ws.on('message', async (rawMessage) => {
105
+ try {
106
+ const parsed = parseIncomingJsonObject(rawMessage);
107
+ if (!parsed) {
108
+ throw new Error('Invalid websocket payload');
109
+ }
110
+
111
+ const data = parsed as ChatIncomingMessage;
112
+ const messageType = data.type;
113
+ if (!messageType) {
114
+ throw new Error('Message type is required');
115
+ }
116
+
117
+ if (messageType === 'claude-command') {
118
+ await dependencies.queryClaudeSDK(data.command ?? '', data.options, writer);
119
+ return;
120
+ }
121
+
122
+ if (messageType === 'cursor-command') {
123
+ await dependencies.spawnCursor(data.command ?? '', data.options, writer);
124
+ return;
125
+ }
126
+
127
+ if (messageType === 'codex-command') {
128
+ await dependencies.queryCodex(data.command ?? '', data.options, writer);
129
+ return;
130
+ }
131
+
132
+ if (messageType === 'gemini-command') {
133
+ await dependencies.spawnGemini(data.command ?? '', data.options, writer);
134
+ return;
135
+ }
136
+
137
+ if (messageType === 'cursor-resume') {
138
+ await dependencies.spawnCursor(
139
+ '',
140
+ {
141
+ sessionId: data.sessionId,
142
+ resume: true,
143
+ cwd: data.options?.cwd,
144
+ },
145
+ writer
146
+ );
147
+ return;
148
+ }
149
+
150
+ if (messageType === 'abort-session') {
151
+ const provider = readProvider(data.provider);
152
+ const sessionId = typeof data.sessionId === 'string' ? data.sessionId : '';
153
+ const userId = writer.userId;
154
+ let success = false;
155
+
156
+ if (provider === 'cursor') {
157
+ success = dependencies.abortCursorSession(sessionId);
158
+ } else if (provider === 'codex') {
159
+ success = dependencies.abortCodexSession(sessionId, userId);
160
+ } else if (provider === 'gemini') {
161
+ success = dependencies.abortGeminiSession(sessionId);
162
+ } else {
163
+ success = await dependencies.abortClaudeSDKSession(sessionId, userId);
164
+ }
165
+
166
+ writer.send(
167
+ createNormalizedMessage({
168
+ kind: 'complete',
169
+ exitCode: success ? 0 : 1,
170
+ aborted: true,
171
+ success,
172
+ sessionId,
173
+ provider,
174
+ })
175
+ );
176
+ return;
177
+ }
178
+
179
+ if (messageType === 'claude-permission-response') {
180
+ if (typeof data.requestId === 'string' && data.requestId.length > 0) {
181
+ dependencies.resolveToolApproval(data.requestId, {
182
+ allow: Boolean(data.allow),
183
+ updatedInput: data.updatedInput,
184
+ message: typeof data.message === 'string' ? data.message : undefined,
185
+ rememberEntry: data.rememberEntry,
186
+ });
187
+ }
188
+ return;
189
+ }
190
+
191
+ if (messageType === 'cursor-abort') {
192
+ const sessionId = typeof data.sessionId === 'string' ? data.sessionId : '';
193
+ const success = dependencies.abortCursorSession(sessionId);
194
+ writer.send(
195
+ createNormalizedMessage({
196
+ kind: 'complete',
197
+ exitCode: success ? 0 : 1,
198
+ aborted: true,
199
+ success,
200
+ sessionId,
201
+ provider: 'cursor',
202
+ })
203
+ );
204
+ return;
205
+ }
206
+
207
+ if (messageType === 'check-session-status') {
208
+ const provider = readProvider(data.provider);
209
+ const sessionId = typeof data.sessionId === 'string' ? data.sessionId : '';
210
+ const userId = writer.userId;
211
+ let isActive = false;
212
+
213
+ if (provider === 'cursor') {
214
+ isActive = dependencies.isCursorSessionActive(sessionId);
215
+ } else if (provider === 'codex') {
216
+ isActive = dependencies.isCodexSessionActive(sessionId, userId);
217
+ } else if (provider === 'gemini') {
218
+ isActive = dependencies.isGeminiSessionActive(sessionId);
219
+ } else {
220
+ isActive = dependencies.isClaudeSDKSessionActive(sessionId, userId);
221
+ if (isActive) {
222
+ dependencies.reconnectSessionWriter(sessionId, ws, userId);
223
+ }
224
+ }
225
+
226
+ writer.send({
227
+ type: 'session-status',
228
+ sessionId,
229
+ provider,
230
+ isProcessing: isActive,
231
+ });
232
+ return;
233
+ }
234
+
235
+ if (messageType === 'get-pending-permissions') {
236
+ const sessionId = typeof data.sessionId === 'string' ? data.sessionId : '';
237
+ const userId = writer.userId;
238
+ if (sessionId && dependencies.isClaudeSDKSessionActive(sessionId, userId)) {
239
+ const pending = dependencies.getPendingApprovalsForSession(sessionId, userId);
240
+ writer.send({
241
+ type: 'pending-permissions-response',
242
+ sessionId,
243
+ data: pending,
244
+ });
245
+ }
246
+ return;
247
+ }
248
+
249
+ if (messageType === 'get-active-sessions') {
250
+ const userId = writer.userId;
251
+ writer.send({
252
+ type: 'active-sessions',
253
+ sessions: {
254
+ claude: dependencies.getActiveClaudeSDKSessions(userId),
255
+ cursor: dependencies.getActiveCursorSessions(),
256
+ codex: dependencies.getActiveCodexSessions(userId),
257
+ gemini: dependencies.getActiveGeminiSessions(),
258
+ },
259
+ });
260
+ }
261
+ } catch (error) {
262
+ const message = error instanceof Error ? error.message : String(error);
263
+ console.error('[ERROR] Chat WebSocket error:', message);
264
+ writer.send({
265
+ type: 'error',
266
+ error: message,
267
+ });
268
+ }
269
+ });
270
+
271
+ ws.on('close', () => {
272
+ console.log('[INFO] Chat client disconnected');
273
+ connectedClients.delete(ws);
274
+ });
275
+ }
@@ -0,0 +1,65 @@
1
+ import { WebSocket } from 'ws';
2
+
3
+ /**
4
+ * Proxies an authenticated client websocket to a plugin websocket endpoint.
5
+ */
6
+ export function handlePluginWsProxy(
7
+ clientWs: WebSocket,
8
+ pathname: string,
9
+ getPluginPort: (pluginName: string) => number | null
10
+ ): void {
11
+ const pluginName = pathname.replace('/plugin-ws/', '');
12
+ if (!pluginName || /[^a-zA-Z0-9_-]/.test(pluginName)) {
13
+ clientWs.close(4400, 'Invalid plugin name');
14
+ return;
15
+ }
16
+
17
+ const port = getPluginPort(pluginName);
18
+ if (!port) {
19
+ clientWs.close(4404, 'Plugin not running');
20
+ return;
21
+ }
22
+
23
+ const upstream = new WebSocket(`ws://127.0.0.1:${port}/ws`);
24
+
25
+ upstream.on('open', () => {
26
+ console.log(`[Plugins] WS proxy connected to "${pluginName}" on port ${port}`);
27
+ });
28
+
29
+ upstream.on('message', (data) => {
30
+ if (clientWs.readyState === WebSocket.OPEN) {
31
+ clientWs.send(data);
32
+ }
33
+ });
34
+
35
+ clientWs.on('message', (data) => {
36
+ if (upstream.readyState === WebSocket.OPEN) {
37
+ upstream.send(data);
38
+ }
39
+ });
40
+
41
+ upstream.on('close', () => {
42
+ if (clientWs.readyState === WebSocket.OPEN) {
43
+ clientWs.close();
44
+ }
45
+ });
46
+
47
+ clientWs.on('close', () => {
48
+ if (upstream.readyState === WebSocket.OPEN) {
49
+ upstream.close();
50
+ }
51
+ });
52
+
53
+ upstream.on('error', (error) => {
54
+ console.error(`[Plugins] WS proxy error for "${pluginName}":`, error.message);
55
+ if (clientWs.readyState === WebSocket.OPEN) {
56
+ clientWs.close(4502, 'Upstream error');
57
+ }
58
+ });
59
+
60
+ clientWs.on('error', () => {
61
+ if (upstream.readyState === WebSocket.OPEN) {
62
+ upstream.close();
63
+ }
64
+ });
65
+ }