@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,144 @@
1
+ import express from 'express';
2
+ import bcrypt from 'bcrypt';
3
+
4
+ import { userDb } from '../modules/database/index.js';
5
+ import { getConnection } from '../modules/database/connection.js';
6
+ import { generateToken, authenticateToken } from '../middleware/auth.js';
7
+
8
+ const router = express.Router();
9
+ const db = getConnection();
10
+
11
+ // Check auth status and setup requirements
12
+ router.get('/status', async (req, res) => {
13
+ try {
14
+ const hasUsers = await userDb.hasUsers();
15
+ res.json({
16
+ needsSetup: !hasUsers,
17
+ isAuthenticated: false // Will be overridden by frontend if token exists
18
+ });
19
+ } catch (error) {
20
+ console.error('Auth status error:', error);
21
+ res.status(500).json({ error: 'Internal server error' });
22
+ }
23
+ });
24
+
25
+ // User registration
26
+ router.post('/register', async (req, res) => {
27
+ try {
28
+ const hasUsers = await userDb.hasUsers();
29
+ if (hasUsers) {
30
+ return res.status(403).json({ error: 'Public registration is disabled' });
31
+ }
32
+
33
+ const { username, password } = req.body;
34
+
35
+ // Validate input
36
+ if (!username || !password) {
37
+ return res.status(400).json({ error: 'Username and password are required' });
38
+ }
39
+
40
+ if (username.length < 3) {
41
+ return res.status(400).json({ error: 'Username must be at least 3 characters' });
42
+ }
43
+
44
+ if (password.length < 8) {
45
+ return res.status(400).json({ error: 'Password must be at least 8 characters' });
46
+ }
47
+
48
+ if (!/[A-Z]/.test(password) || !/[a-z]/.test(password) || !/[0-9]/.test(password)) {
49
+ return res.status(400).json({ error: 'Password must contain uppercase, lowercase, and a number' });
50
+ }
51
+
52
+ // Use a transaction to prevent race conditions
53
+ db.prepare('BEGIN').run();
54
+ try {
55
+ // Hash password
56
+ const saltRounds = 12;
57
+ const passwordHash = await bcrypt.hash(password, saltRounds);
58
+
59
+ // Create user
60
+ const user = userDb.createUser(username, passwordHash, { isAdmin: true });
61
+
62
+ // Generate token
63
+ const token = generateToken(user);
64
+
65
+ db.prepare('COMMIT').run();
66
+
67
+ // Update last login (non-fatal, outside transaction)
68
+ userDb.updateLastLogin(user.id);
69
+
70
+ res.json({
71
+ success: true,
72
+ user: { id: user.id, username: user.username, isAdmin: user.isAdmin },
73
+ token
74
+ });
75
+ } catch (error) {
76
+ db.prepare('ROLLBACK').run();
77
+ throw error;
78
+ }
79
+
80
+ } catch (error) {
81
+ console.error('Registration error:', error);
82
+ if (error.code === 'SQLITE_CONSTRAINT_UNIQUE') {
83
+ res.status(409).json({ error: 'Username already exists' });
84
+ } else {
85
+ res.status(500).json({ error: 'Internal server error' });
86
+ }
87
+ }
88
+ });
89
+
90
+ // User login
91
+ router.post('/login', async (req, res) => {
92
+ try {
93
+ const { username, password } = req.body;
94
+
95
+ // Validate input
96
+ if (!username || !password) {
97
+ return res.status(400).json({ error: 'Username and password are required' });
98
+ }
99
+
100
+ // Get user from database
101
+ const user = userDb.getUserByUsername(username);
102
+ if (!user) {
103
+ return res.status(401).json({ error: 'Invalid username or password' });
104
+ }
105
+
106
+ // Verify password
107
+ const isValidPassword = await bcrypt.compare(password, user.password_hash);
108
+ if (!isValidPassword) {
109
+ return res.status(401).json({ error: 'Invalid username or password' });
110
+ }
111
+
112
+ // Generate token
113
+ const token = generateToken(user);
114
+
115
+ // Update last login
116
+ userDb.updateLastLogin(user.id);
117
+
118
+ res.json({
119
+ success: true,
120
+ user: { id: user.id, username: user.username },
121
+ token
122
+ });
123
+
124
+ } catch (error) {
125
+ console.error('Login error:', error);
126
+ res.status(500).json({ error: 'Internal server error' });
127
+ }
128
+ });
129
+
130
+ // Get current user (protected route)
131
+ router.get('/user', authenticateToken, (req, res) => {
132
+ res.json({
133
+ user: req.user
134
+ });
135
+ });
136
+
137
+ // Logout (client-side token removal, but this endpoint can be used for logging)
138
+ router.post('/logout', authenticateToken, (req, res) => {
139
+ // In a simple JWT system, logout is mainly client-side
140
+ // This endpoint exists for consistency and potential future logging
141
+ res.json({ success: true, message: 'Logged out successfully' });
142
+ });
143
+
144
+ export default router;
@@ -0,0 +1,556 @@
1
+ import { promises as fs } from 'fs';
2
+ import os from 'os';
3
+ import path from 'path';
4
+
5
+ import express from 'express';
6
+
7
+ import { CLAUDE_MODELS, CURSOR_MODELS, CODEX_MODELS } from '../../shared/modelConstants.js';
8
+ import { parseFrontMatter } from '../shared/frontmatter.js';
9
+ import { findAppRoot, getModuleDir } from '../utils/runtime-paths.js';
10
+
11
+ const __dirname = getModuleDir(import.meta.url);
12
+ // This route reads the top-level package.json for the status command, so it needs the real
13
+ // app root even after compilation moves the route file under dist-server/server/routes.
14
+ const APP_ROOT = findAppRoot(__dirname);
15
+
16
+ const router = express.Router();
17
+
18
+ /**
19
+ * Recursively scan directory for command files (.md)
20
+ * @param {string} dir - Directory to scan
21
+ * @param {string} baseDir - Base directory for relative paths
22
+ * @param {string} namespace - Namespace for commands (e.g., 'project', 'user')
23
+ * @returns {Promise<Array>} Array of command objects
24
+ */
25
+ async function scanCommandsDirectory(dir, baseDir, namespace) {
26
+ const commands = [];
27
+
28
+ try {
29
+ // Check if directory exists
30
+ await fs.access(dir);
31
+
32
+ const entries = await fs.readdir(dir, { withFileTypes: true });
33
+
34
+ for (const entry of entries) {
35
+ const fullPath = path.join(dir, entry.name);
36
+
37
+ if (entry.isDirectory()) {
38
+ // Recursively scan subdirectories
39
+ const subCommands = await scanCommandsDirectory(fullPath, baseDir, namespace);
40
+ commands.push(...subCommands);
41
+ } else if (entry.isFile() && entry.name.endsWith('.md')) {
42
+ // Parse markdown file for metadata
43
+ try {
44
+ const content = await fs.readFile(fullPath, 'utf8');
45
+ const { data: frontmatter, content: commandContent } = parseFrontMatter(content);
46
+
47
+ // Calculate relative path from baseDir for command name
48
+ const relativePath = path.relative(baseDir, fullPath);
49
+ // Remove .md extension and convert to command name
50
+ const commandName = '/' + relativePath.replace(/\.md$/, '').replace(/\\/g, '/');
51
+
52
+ // Extract description from frontmatter or first line of content
53
+ let description = frontmatter.description || '';
54
+ if (!description) {
55
+ const firstLine = commandContent.trim().split('\n')[0];
56
+ description = firstLine.replace(/^#+\s*/, '').trim();
57
+ }
58
+
59
+ commands.push({
60
+ name: commandName,
61
+ path: fullPath,
62
+ relativePath,
63
+ description,
64
+ namespace,
65
+ metadata: frontmatter
66
+ });
67
+ } catch (err) {
68
+ console.error(`Error parsing command file ${fullPath}:`, err.message);
69
+ }
70
+ }
71
+ }
72
+ } catch (err) {
73
+ // Directory doesn't exist or can't be accessed - this is okay
74
+ if (err.code !== 'ENOENT' && err.code !== 'EACCES') {
75
+ console.error(`Error scanning directory ${dir}:`, err.message);
76
+ }
77
+ }
78
+
79
+ return commands;
80
+ }
81
+
82
+ /**
83
+ * Built-in commands that are always available
84
+ */
85
+ const builtInCommands = [
86
+ {
87
+ name: '/help',
88
+ description: 'Show help documentation for Claude Code',
89
+ namespace: 'builtin',
90
+ metadata: { type: 'builtin' }
91
+ },
92
+ {
93
+ name: '/clear',
94
+ description: 'Clear the conversation history',
95
+ namespace: 'builtin',
96
+ metadata: { type: 'builtin' }
97
+ },
98
+ {
99
+ name: '/model',
100
+ description: 'Switch or view the current AI model',
101
+ namespace: 'builtin',
102
+ metadata: { type: 'builtin' }
103
+ },
104
+ {
105
+ name: '/cost',
106
+ description: 'Display token usage and cost information',
107
+ namespace: 'builtin',
108
+ metadata: { type: 'builtin' }
109
+ },
110
+ {
111
+ name: '/memory',
112
+ description: 'Open CLAUDE.md memory file for editing',
113
+ namespace: 'builtin',
114
+ metadata: { type: 'builtin' }
115
+ },
116
+ {
117
+ name: '/config',
118
+ description: 'Open settings and configuration',
119
+ namespace: 'builtin',
120
+ metadata: { type: 'builtin' }
121
+ },
122
+ {
123
+ name: '/status',
124
+ description: 'Show system status and version information',
125
+ namespace: 'builtin',
126
+ metadata: { type: 'builtin' }
127
+ },
128
+ {
129
+ name: '/rewind',
130
+ description: 'Rewind the conversation to a previous state',
131
+ namespace: 'builtin',
132
+ metadata: { type: 'builtin' }
133
+ }
134
+ ];
135
+
136
+ /**
137
+ * Built-in command handlers
138
+ * Each handler returns { type: 'builtin', action: string, data: any }
139
+ */
140
+ const builtInHandlers = {
141
+ '/help': async (args, context) => {
142
+ const helpText = `# Claude Code Commands
143
+
144
+ ## Built-in Commands
145
+
146
+ ${builtInCommands.map(cmd => `### ${cmd.name}
147
+ ${cmd.description}
148
+ `).join('\n')}
149
+
150
+ ## Custom Commands
151
+
152
+ Custom commands can be created in:
153
+ - Project: \`.claude/commands/\` (project-specific)
154
+ - User: \`~/.claude/commands/\` (available in all projects)
155
+
156
+ ### Command Syntax
157
+
158
+ - **Arguments**: Use \`$ARGUMENTS\` for all args or \`$1\`, \`$2\`, etc. for positional
159
+ - **File Includes**: Use \`@filename\` to include file contents
160
+ - **Bash Commands**: Use \`!command\` to execute bash commands
161
+
162
+ ### Examples
163
+
164
+ \`\`\`markdown
165
+ /mycommand arg1 arg2
166
+ \`\`\`
167
+ `;
168
+
169
+ return {
170
+ type: 'builtin',
171
+ action: 'help',
172
+ data: {
173
+ content: helpText,
174
+ format: 'markdown'
175
+ }
176
+ };
177
+ },
178
+
179
+ '/clear': async (args, context) => {
180
+ return {
181
+ type: 'builtin',
182
+ action: 'clear',
183
+ data: {
184
+ message: 'Conversation history cleared'
185
+ }
186
+ };
187
+ },
188
+
189
+ '/model': async (args, context) => {
190
+ // Read available models from centralized constants
191
+ const availableModels = {
192
+ claude: CLAUDE_MODELS.OPTIONS.map(o => o.value),
193
+ cursor: CURSOR_MODELS.OPTIONS.map(o => o.value),
194
+ codex: CODEX_MODELS.OPTIONS.map(o => o.value)
195
+ };
196
+
197
+ const currentProvider = context?.provider || 'claude';
198
+ const currentModel = context?.model || CLAUDE_MODELS.DEFAULT;
199
+
200
+ return {
201
+ type: 'builtin',
202
+ action: 'model',
203
+ data: {
204
+ current: {
205
+ provider: currentProvider,
206
+ model: currentModel
207
+ },
208
+ available: availableModels,
209
+ message: args.length > 0
210
+ ? `Switching to model: ${args[0]}`
211
+ : `Current model: ${currentModel}`
212
+ }
213
+ };
214
+ },
215
+
216
+ '/cost': async (args, context) => {
217
+ const tokenUsage = context?.tokenUsage || {};
218
+ const provider = context?.provider || 'claude';
219
+ const model =
220
+ context?.model ||
221
+ (provider === 'cursor'
222
+ ? CURSOR_MODELS.DEFAULT
223
+ : provider === 'codex'
224
+ ? CODEX_MODELS.DEFAULT
225
+ : CLAUDE_MODELS.DEFAULT);
226
+
227
+ const used = Number(tokenUsage.used ?? tokenUsage.totalUsed ?? tokenUsage.total_tokens ?? 0) || 0;
228
+ const total =
229
+ Number(
230
+ tokenUsage.total ??
231
+ tokenUsage.contextWindow ??
232
+ parseInt(process.env.CONTEXT_WINDOW || '160000', 10),
233
+ ) || 160000;
234
+ const percentage = total > 0 ? Number(((used / total) * 100).toFixed(1)) : 0;
235
+
236
+ const inputTokensRaw =
237
+ Number(
238
+ tokenUsage.inputTokens ??
239
+ tokenUsage.input ??
240
+ tokenUsage.cumulativeInputTokens ??
241
+ tokenUsage.promptTokens ??
242
+ 0,
243
+ ) || 0;
244
+ const outputTokens =
245
+ Number(
246
+ tokenUsage.outputTokens ??
247
+ tokenUsage.output ??
248
+ tokenUsage.cumulativeOutputTokens ??
249
+ tokenUsage.completionTokens ??
250
+ 0,
251
+ ) || 0;
252
+ const cacheTokens =
253
+ Number(
254
+ tokenUsage.cacheReadTokens ??
255
+ tokenUsage.cacheCreationTokens ??
256
+ tokenUsage.cacheTokens ??
257
+ tokenUsage.cachedTokens ??
258
+ 0,
259
+ ) || 0;
260
+
261
+ // If we only have total used tokens, treat them as input for display/estimation.
262
+ const inputTokens =
263
+ inputTokensRaw > 0 || outputTokens > 0 || cacheTokens > 0 ? inputTokensRaw + cacheTokens : used;
264
+
265
+ // Rough default rates by provider (USD / 1M tokens).
266
+ const pricingByProvider = {
267
+ claude: { input: 3, output: 15 },
268
+ cursor: { input: 3, output: 15 },
269
+ codex: { input: 1.5, output: 6 },
270
+ };
271
+ const rates = pricingByProvider[provider] || pricingByProvider.claude;
272
+
273
+ const inputCost = (inputTokens / 1_000_000) * rates.input;
274
+ const outputCost = (outputTokens / 1_000_000) * rates.output;
275
+ const totalCost = inputCost + outputCost;
276
+
277
+ return {
278
+ type: 'builtin',
279
+ action: 'cost',
280
+ data: {
281
+ tokenUsage: {
282
+ used,
283
+ total,
284
+ percentage,
285
+ },
286
+ cost: {
287
+ input: inputCost.toFixed(4),
288
+ output: outputCost.toFixed(4),
289
+ total: totalCost.toFixed(4),
290
+ },
291
+ model,
292
+ },
293
+ };
294
+ },
295
+
296
+ '/status': async (args, context) => {
297
+ // Read version from package.json
298
+ const packageJsonPath = path.join(APP_ROOT, 'package.json');
299
+ let version = 'unknown';
300
+ let packageName = 'claude-code-ui';
301
+
302
+ try {
303
+ const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
304
+ version = packageJson.version;
305
+ packageName = packageJson.name;
306
+ } catch (err) {
307
+ console.error('Error reading package.json:', err);
308
+ }
309
+
310
+ const uptime = process.uptime();
311
+ const uptimeMinutes = Math.floor(uptime / 60);
312
+ const uptimeHours = Math.floor(uptimeMinutes / 60);
313
+ const uptimeFormatted = uptimeHours > 0
314
+ ? `${uptimeHours}h ${uptimeMinutes % 60}m`
315
+ : `${uptimeMinutes}m`;
316
+
317
+ return {
318
+ type: 'builtin',
319
+ action: 'status',
320
+ data: {
321
+ version,
322
+ packageName,
323
+ uptime: uptimeFormatted,
324
+ uptimeSeconds: Math.floor(uptime),
325
+ model: context?.model || CLAUDE_MODELS.DEFAULT,
326
+ provider: context?.provider || 'claude',
327
+ nodeVersion: process.version,
328
+ platform: process.platform
329
+ }
330
+ };
331
+ },
332
+
333
+ '/memory': async (args, context) => {
334
+ const projectPath = context?.projectPath;
335
+
336
+ if (!projectPath) {
337
+ return {
338
+ type: 'builtin',
339
+ action: 'memory',
340
+ data: {
341
+ error: 'No project selected',
342
+ message: 'Please select a project to access its CLAUDE.md file'
343
+ }
344
+ };
345
+ }
346
+
347
+ const claudeMdPath = path.join(projectPath, 'CLAUDE.md');
348
+
349
+ // Check if CLAUDE.md exists
350
+ let exists = false;
351
+ try {
352
+ await fs.access(claudeMdPath);
353
+ exists = true;
354
+ } catch (err) {
355
+ // File doesn't exist
356
+ }
357
+
358
+ return {
359
+ type: 'builtin',
360
+ action: 'memory',
361
+ data: {
362
+ path: claudeMdPath,
363
+ exists,
364
+ message: exists
365
+ ? `Opening CLAUDE.md at ${claudeMdPath}`
366
+ : `CLAUDE.md not found at ${claudeMdPath}. Create it to store project-specific instructions.`
367
+ }
368
+ };
369
+ },
370
+
371
+ '/config': async (args, context) => {
372
+ return {
373
+ type: 'builtin',
374
+ action: 'config',
375
+ data: {
376
+ message: 'Opening settings...'
377
+ }
378
+ };
379
+ },
380
+
381
+ '/rewind': async (args, context) => {
382
+ const steps = args[0] ? parseInt(args[0]) : 1;
383
+
384
+ if (isNaN(steps) || steps < 1) {
385
+ return {
386
+ type: 'builtin',
387
+ action: 'rewind',
388
+ data: {
389
+ error: 'Invalid steps parameter',
390
+ message: 'Usage: /rewind [number] - Rewind conversation by N steps (default: 1)'
391
+ }
392
+ };
393
+ }
394
+
395
+ return {
396
+ type: 'builtin',
397
+ action: 'rewind',
398
+ data: {
399
+ steps,
400
+ message: `Rewinding conversation by ${steps} step${steps > 1 ? 's' : ''}...`
401
+ }
402
+ };
403
+ }
404
+ };
405
+
406
+ /**
407
+ * POST /api/commands/list
408
+ * List all available commands from project and user directories
409
+ */
410
+ router.post('/list', async (req, res) => {
411
+ try {
412
+ const { projectPath } = req.body;
413
+ const allCommands = [...builtInCommands];
414
+
415
+ // Scan project-level commands (.claude/commands/)
416
+ if (projectPath) {
417
+ const projectCommandsDir = path.join(projectPath, '.claude', 'commands');
418
+ const projectCommands = await scanCommandsDirectory(
419
+ projectCommandsDir,
420
+ projectCommandsDir,
421
+ 'project'
422
+ );
423
+ allCommands.push(...projectCommands);
424
+ }
425
+
426
+ // Scan user-level commands (~/.claude/commands/)
427
+ const homeDir = os.homedir();
428
+ const userCommandsDir = path.join(homeDir, '.claude', 'commands');
429
+ const userCommands = await scanCommandsDirectory(
430
+ userCommandsDir,
431
+ userCommandsDir,
432
+ 'user'
433
+ );
434
+ allCommands.push(...userCommands);
435
+
436
+ // Separate built-in and custom commands
437
+ const customCommands = allCommands.filter(cmd => cmd.namespace !== 'builtin');
438
+
439
+ // Sort commands alphabetically by name
440
+ customCommands.sort((a, b) => a.name.localeCompare(b.name));
441
+
442
+ res.json({
443
+ builtIn: builtInCommands,
444
+ custom: customCommands,
445
+ count: allCommands.length
446
+ });
447
+ } catch (error) {
448
+ console.error('Error listing commands:', error);
449
+ res.status(500).json({
450
+ error: 'Failed to list commands',
451
+ message: error.message
452
+ });
453
+ }
454
+ });
455
+
456
+ /**
457
+ * POST /api/commands/execute
458
+ * Execute a command with argument replacement
459
+ * This endpoint prepares the command content but doesn't execute bash commands yet
460
+ * (that will be handled in the command parser utility)
461
+ */
462
+ router.post('/execute', async (req, res) => {
463
+ try {
464
+ const { commandName, commandPath, args = [], context = {} } = req.body;
465
+
466
+ if (!commandName) {
467
+ return res.status(400).json({
468
+ error: 'Command name is required'
469
+ });
470
+ }
471
+
472
+ // Handle built-in commands
473
+ const handler = builtInHandlers[commandName];
474
+ if (handler) {
475
+ try {
476
+ const result = await handler(args, context);
477
+ return res.json({
478
+ ...result,
479
+ command: commandName
480
+ });
481
+ } catch (error) {
482
+ console.error(`Error executing built-in command ${commandName}:`, error);
483
+ return res.status(500).json({
484
+ error: 'Command execution failed',
485
+ message: error.message,
486
+ command: commandName
487
+ });
488
+ }
489
+ }
490
+
491
+ // Handle custom commands
492
+ if (!commandPath) {
493
+ return res.status(400).json({
494
+ error: 'Command path is required for custom commands'
495
+ });
496
+ }
497
+
498
+ // Load command content
499
+ // Security: validate commandPath is within allowed directories
500
+ {
501
+ const resolvedPath = path.resolve(commandPath);
502
+ const userBase = path.resolve(path.join(os.homedir(), '.claude', 'commands'));
503
+ const projectBase = context?.projectPath
504
+ ? path.resolve(path.join(context.projectPath, '.claude', 'commands'))
505
+ : null;
506
+ const isUnder = (base) => {
507
+ const rel = path.relative(base, resolvedPath);
508
+ return rel !== '' && !rel.startsWith('..') && !path.isAbsolute(rel);
509
+ };
510
+ if (!(isUnder(userBase) || (projectBase && isUnder(projectBase)))) {
511
+ return res.status(403).json({
512
+ error: 'Access denied',
513
+ message: 'Command must be in .claude/commands directory'
514
+ });
515
+ }
516
+ }
517
+ const content = await fs.readFile(commandPath, 'utf8');
518
+ const { data: metadata, content: commandContent } = parseFrontMatter(content);
519
+ // Basic argument replacement (will be enhanced in command parser utility)
520
+ let processedContent = commandContent;
521
+
522
+ // Replace $ARGUMENTS with all arguments joined
523
+ const argsString = args.join(' ');
524
+ processedContent = processedContent.replace(/\$ARGUMENTS/g, argsString);
525
+
526
+ // Replace $1, $2, etc. with positional arguments
527
+ args.forEach((arg, index) => {
528
+ const placeholder = `$${index + 1}`;
529
+ processedContent = processedContent.replace(new RegExp(`\\${placeholder}\\b`, 'g'), arg);
530
+ });
531
+
532
+ res.json({
533
+ type: 'custom',
534
+ command: commandName,
535
+ content: processedContent,
536
+ metadata,
537
+ hasFileIncludes: processedContent.includes('@'),
538
+ hasBashCommands: processedContent.includes('!')
539
+ });
540
+ } catch (error) {
541
+ if (error.code === 'ENOENT') {
542
+ return res.status(404).json({
543
+ error: 'Command not found',
544
+ message: `Command file not found: ${req.body.commandPath}`
545
+ });
546
+ }
547
+
548
+ console.error('Error executing command:', error);
549
+ res.status(500).json({
550
+ error: 'Failed to execute command',
551
+ message: error.message
552
+ });
553
+ }
554
+ });
555
+
556
+ export default router;