@cloudcli-ai/cloudcli 1.29.5 → 1.31.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 (354) hide show
  1. package/README.de.md +1 -1
  2. package/README.ja.md +1 -1
  3. package/README.ko.md +1 -1
  4. package/README.md +1 -1
  5. package/README.ru.md +1 -1
  6. package/README.tr.md +252 -0
  7. package/README.zh-CN.md +1 -1
  8. package/dist/assets/index-DF8TTVHl.css +32 -0
  9. package/dist/assets/index-DbZAcc9z.js +1262 -0
  10. package/dist/index.html +2 -2
  11. package/dist-server/server/claude-sdk.js +13 -8
  12. package/dist-server/server/claude-sdk.js.map +1 -1
  13. package/dist-server/server/cursor-cli.js +7 -7
  14. package/dist-server/server/cursor-cli.js.map +1 -1
  15. package/dist-server/server/gemini-cli.js +5 -5
  16. package/dist-server/server/gemini-cli.js.map +1 -1
  17. package/dist-server/server/gemini-response-handler.js +2 -2
  18. package/dist-server/server/gemini-response-handler.js.map +1 -1
  19. package/dist-server/server/index.js +139 -977
  20. package/dist-server/server/index.js.map +1 -1
  21. package/dist-server/server/middleware/auth.js +1 -1
  22. package/dist-server/server/middleware/auth.js.map +1 -1
  23. package/dist-server/server/modules/database/connection.js +125 -0
  24. package/dist-server/server/modules/database/connection.js.map +1 -0
  25. package/dist-server/server/modules/database/index.js +13 -0
  26. package/dist-server/server/modules/database/index.js.map +1 -0
  27. package/dist-server/server/modules/database/init-db.js +18 -0
  28. package/dist-server/server/modules/database/init-db.js.map +1 -0
  29. package/dist-server/server/modules/database/migrations.js +370 -0
  30. package/dist-server/server/modules/database/migrations.js.map +1 -0
  31. package/dist-server/server/modules/database/repositories/api-keys.js +72 -0
  32. package/dist-server/server/modules/database/repositories/api-keys.js.map +1 -0
  33. package/dist-server/server/modules/database/repositories/app-config.js +47 -0
  34. package/dist-server/server/modules/database/repositories/app-config.js.map +1 -0
  35. package/dist-server/server/modules/database/repositories/credentials.js +68 -0
  36. package/dist-server/server/modules/database/repositories/credentials.js.map +1 -0
  37. package/dist-server/server/modules/database/repositories/github-tokens.js +54 -0
  38. package/dist-server/server/modules/database/repositories/github-tokens.js.map +1 -0
  39. package/dist-server/server/modules/database/repositories/notification-preferences.js +72 -0
  40. package/dist-server/server/modules/database/repositories/notification-preferences.js.map +1 -0
  41. package/dist-server/server/modules/database/repositories/projects.db.integration.test.js +64 -0
  42. package/dist-server/server/modules/database/repositories/projects.db.integration.test.js.map +1 -0
  43. package/dist-server/server/modules/database/repositories/projects.db.js +160 -0
  44. package/dist-server/server/modules/database/repositories/projects.db.js.map +1 -0
  45. package/dist-server/server/modules/database/repositories/push-subscriptions.js +49 -0
  46. package/dist-server/server/modules/database/repositories/push-subscriptions.js.map +1 -0
  47. package/dist-server/server/modules/database/repositories/scan-state.db.js +31 -0
  48. package/dist-server/server/modules/database/repositories/scan-state.db.js.map +1 -0
  49. package/dist-server/server/modules/database/repositories/sessions.db.js +109 -0
  50. package/dist-server/server/modules/database/repositories/sessions.db.js.map +1 -0
  51. package/dist-server/server/modules/database/repositories/users.js +88 -0
  52. package/dist-server/server/modules/database/repositories/users.js.map +1 -0
  53. package/dist-server/server/modules/database/repositories/vapid-keys.js +38 -0
  54. package/dist-server/server/modules/database/repositories/vapid-keys.js.map +1 -0
  55. package/dist-server/server/modules/database/schema.js +143 -0
  56. package/dist-server/server/modules/database/schema.js.map +1 -0
  57. package/dist-server/server/modules/projects/index.js +4 -0
  58. package/dist-server/server/modules/projects/index.js.map +1 -0
  59. package/dist-server/server/modules/projects/projects.routes.js +188 -0
  60. package/dist-server/server/modules/projects/projects.routes.js.map +1 -0
  61. package/dist-server/server/modules/projects/services/project-clone.service.js +219 -0
  62. package/dist-server/server/modules/projects/services/project-clone.service.js.map +1 -0
  63. package/dist-server/server/modules/projects/services/project-delete.service.js +65 -0
  64. package/dist-server/server/modules/projects/services/project-delete.service.js.map +1 -0
  65. package/dist-server/server/modules/projects/services/project-management.service.js +93 -0
  66. package/dist-server/server/modules/projects/services/project-management.service.js.map +1 -0
  67. package/dist-server/server/modules/projects/services/project-star.service.js +60 -0
  68. package/dist-server/server/modules/projects/services/project-star.service.js.map +1 -0
  69. package/dist-server/server/modules/projects/services/projects-has-taskmaster.service.js +167 -0
  70. package/dist-server/server/modules/projects/services/projects-has-taskmaster.service.js.map +1 -0
  71. package/dist-server/server/modules/projects/services/projects-with-sessions-fetch.service.js +169 -0
  72. package/dist-server/server/modules/projects/services/projects-with-sessions-fetch.service.js.map +1 -0
  73. package/dist-server/server/modules/projects/tests/project-clone.service.test.js +126 -0
  74. package/dist-server/server/modules/projects/tests/project-clone.service.test.js.map +1 -0
  75. package/dist-server/server/modules/projects/tests/project-management.service.test.js +85 -0
  76. package/dist-server/server/modules/projects/tests/project-management.service.test.js.map +1 -0
  77. package/dist-server/server/modules/projects/tests/project-star.service.test.js +95 -0
  78. package/dist-server/server/modules/projects/tests/project-star.service.test.js.map +1 -0
  79. package/dist-server/server/modules/projects/tests/projects-has-taskmaster.service.test.js +87 -0
  80. package/dist-server/server/modules/projects/tests/projects-has-taskmaster.service.test.js.map +1 -0
  81. package/dist-server/server/modules/providers/index.js +4 -0
  82. package/dist-server/server/modules/providers/index.js.map +1 -0
  83. package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js +103 -0
  84. package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js.map +1 -0
  85. package/dist-server/server/modules/providers/list/claude/claude-mcp.provider.js +103 -0
  86. package/dist-server/server/modules/providers/list/claude/claude-mcp.provider.js.map +1 -0
  87. package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js +63 -0
  88. package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js.map +1 -0
  89. package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js +403 -0
  90. package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js.map +1 -0
  91. package/dist-server/server/modules/providers/list/claude/claude.provider.js +15 -0
  92. package/dist-server/server/modules/providers/list/claude/claude.provider.js.map +1 -0
  93. package/dist-server/server/modules/providers/list/codex/codex-auth.provider.js +84 -0
  94. package/dist-server/server/modules/providers/list/codex/codex-auth.provider.js.map +1 -0
  95. package/dist-server/server/modules/providers/list/codex/codex-mcp.provider.js +107 -0
  96. package/dist-server/server/modules/providers/list/codex/codex-mcp.provider.js.map +1 -0
  97. package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js +71 -0
  98. package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js.map +1 -0
  99. package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js +494 -0
  100. package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js.map +1 -0
  101. package/dist-server/server/modules/providers/list/codex/codex.provider.js +15 -0
  102. package/dist-server/server/modules/providers/list/codex/codex.provider.js.map +1 -0
  103. package/dist-server/server/modules/providers/list/cursor/cursor-auth.provider.js +118 -0
  104. package/dist-server/server/modules/providers/list/cursor/cursor-auth.provider.js.map +1 -0
  105. package/dist-server/server/modules/providers/list/cursor/cursor-mcp.provider.js +80 -0
  106. package/dist-server/server/modules/providers/list/cursor/cursor-mcp.provider.js.map +1 -0
  107. package/dist-server/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.js +127 -0
  108. package/dist-server/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.js.map +1 -0
  109. package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js +369 -0
  110. package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js.map +1 -0
  111. package/dist-server/server/modules/providers/list/cursor/cursor.provider.js +15 -0
  112. package/dist-server/server/modules/providers/list/cursor/cursor.provider.js.map +1 -0
  113. package/dist-server/server/modules/providers/list/gemini/gemini-auth.provider.js +131 -0
  114. package/dist-server/server/modules/providers/list/gemini/gemini-auth.provider.js.map +1 -0
  115. package/dist-server/server/modules/providers/list/gemini/gemini-mcp.provider.js +82 -0
  116. package/dist-server/server/modules/providers/list/gemini/gemini-mcp.provider.js.map +1 -0
  117. package/dist-server/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.js +296 -0
  118. package/dist-server/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.js.map +1 -0
  119. package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js +474 -0
  120. package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js.map +1 -0
  121. package/dist-server/server/modules/providers/list/gemini/gemini.provider.js +15 -0
  122. package/dist-server/server/modules/providers/list/gemini/gemini.provider.js.map +1 -0
  123. package/dist-server/server/modules/providers/provider.registry.js +31 -0
  124. package/dist-server/server/modules/providers/provider.registry.js.map +1 -0
  125. package/dist-server/server/modules/providers/provider.routes.js +331 -0
  126. package/dist-server/server/modules/providers/provider.routes.js.map +1 -0
  127. package/dist-server/server/modules/providers/services/mcp.service.js +69 -0
  128. package/dist-server/server/modules/providers/services/mcp.service.js.map +1 -0
  129. package/dist-server/server/modules/providers/services/provider-auth.service.js +25 -0
  130. package/dist-server/server/modules/providers/services/provider-auth.service.js.map +1 -0
  131. package/dist-server/server/modules/providers/services/session-conversations-search.service.js +868 -0
  132. package/dist-server/server/modules/providers/services/session-conversations-search.service.js.map +1 -0
  133. package/dist-server/server/modules/providers/services/session-synchronizer.service.js +56 -0
  134. package/dist-server/server/modules/providers/services/session-synchronizer.service.js.map +1 -0
  135. package/dist-server/server/modules/providers/services/sessions-watcher.service.js +234 -0
  136. package/dist-server/server/modules/providers/services/sessions-watcher.service.js.map +1 -0
  137. package/dist-server/server/modules/providers/services/sessions.service.js +104 -0
  138. package/dist-server/server/modules/providers/services/sessions.service.js.map +1 -0
  139. package/dist-server/server/modules/providers/shared/base/abstract.provider.js +14 -0
  140. package/dist-server/server/modules/providers/shared/base/abstract.provider.js.map +1 -0
  141. package/dist-server/server/modules/providers/shared/mcp/mcp.provider.js +102 -0
  142. package/dist-server/server/modules/providers/shared/mcp/mcp.provider.js.map +1 -0
  143. package/dist-server/server/modules/providers/tests/mcp.test.js +250 -0
  144. package/dist-server/server/modules/providers/tests/mcp.test.js.map +1 -0
  145. package/dist-server/server/modules/websocket/index.js +3 -0
  146. package/dist-server/server/modules/websocket/index.js.map +1 -0
  147. package/dist-server/server/modules/websocket/services/chat-websocket.service.js +188 -0
  148. package/dist-server/server/modules/websocket/services/chat-websocket.service.js.map +1 -0
  149. package/dist-server/server/modules/websocket/services/plugin-websocket-proxy.service.js +52 -0
  150. package/dist-server/server/modules/websocket/services/plugin-websocket-proxy.service.js.map +1 -0
  151. package/dist-server/server/modules/websocket/services/shell-websocket.service.js +334 -0
  152. package/dist-server/server/modules/websocket/services/shell-websocket.service.js.map +1 -0
  153. package/dist-server/server/modules/websocket/services/websocket-auth.service.js +32 -0
  154. package/dist-server/server/modules/websocket/services/websocket-auth.service.js.map +1 -0
  155. package/dist-server/server/modules/websocket/services/websocket-server.service.js +36 -0
  156. package/dist-server/server/modules/websocket/services/websocket-server.service.js.map +1 -0
  157. package/dist-server/server/modules/websocket/services/websocket-state.service.js +14 -0
  158. package/dist-server/server/modules/websocket/services/websocket-state.service.js.map +1 -0
  159. package/dist-server/server/modules/websocket/services/websocket-writer.service.js +32 -0
  160. package/dist-server/server/modules/websocket/services/websocket-writer.service.js.map +1 -0
  161. package/dist-server/server/openai-codex.js +5 -5
  162. package/dist-server/server/openai-codex.js.map +1 -1
  163. package/dist-server/server/routes/agent.js +10 -17
  164. package/dist-server/server/routes/agent.js.map +1 -1
  165. package/dist-server/server/routes/auth.js +3 -1
  166. package/dist-server/server/routes/auth.js.map +1 -1
  167. package/dist-server/server/routes/commands.js +1 -45
  168. package/dist-server/server/routes/commands.js.map +1 -1
  169. package/dist-server/server/routes/cursor.js +9 -489
  170. package/dist-server/server/routes/cursor.js.map +1 -1
  171. package/dist-server/server/routes/gemini.js +2 -2
  172. package/dist-server/server/routes/gemini.js.map +1 -1
  173. package/dist-server/server/routes/git.js +33 -29
  174. package/dist-server/server/routes/git.js.map +1 -1
  175. package/dist-server/server/routes/mcp-utils.js +1 -18
  176. package/dist-server/server/routes/mcp-utils.js.map +1 -1
  177. package/dist-server/server/routes/settings.js +11 -1
  178. package/dist-server/server/routes/settings.js.map +1 -1
  179. package/dist-server/server/routes/taskmaster.js +97 -569
  180. package/dist-server/server/routes/taskmaster.js.map +1 -1
  181. package/dist-server/server/routes/user.js +1 -1
  182. package/dist-server/server/routes/user.js.map +1 -1
  183. package/dist-server/server/services/notification-orchestrator.js +2 -2
  184. package/dist-server/server/services/notification-orchestrator.js.map +1 -1
  185. package/dist-server/server/services/vapid-keys.js +2 -1
  186. package/dist-server/server/services/vapid-keys.js.map +1 -1
  187. package/dist-server/server/shared/interfaces.js +2 -0
  188. package/dist-server/server/shared/interfaces.js.map +1 -0
  189. package/dist-server/server/shared/types.js +2 -0
  190. package/dist-server/server/shared/types.js.map +1 -0
  191. package/dist-server/server/shared/utils.js +551 -0
  192. package/dist-server/server/shared/utils.js.map +1 -0
  193. package/dist-server/server/utils/mcp-detector.js +0 -49
  194. package/dist-server/server/utils/mcp-detector.js.map +1 -1
  195. package/dist-server/server/utils/taskmaster-websocket.js +18 -12
  196. package/dist-server/server/utils/taskmaster-websocket.js.map +1 -1
  197. package/dist-server/shared/modelConstants.js +3 -1
  198. package/dist-server/shared/modelConstants.js.map +1 -1
  199. package/package.json +7 -2
  200. package/server/claude-sdk.js +14 -8
  201. package/server/cursor-cli.js +7 -7
  202. package/server/gemini-cli.js +5 -5
  203. package/server/gemini-response-handler.js +2 -2
  204. package/server/index.js +173 -1035
  205. package/server/middleware/auth.js +1 -1
  206. package/server/modules/database/connection.ts +143 -0
  207. package/server/modules/database/index.ts +12 -0
  208. package/server/modules/database/init-db.ts +17 -0
  209. package/server/modules/database/migrations.ts +442 -0
  210. package/server/modules/database/repositories/api-keys.ts +119 -0
  211. package/server/modules/database/repositories/app-config.ts +53 -0
  212. package/server/modules/database/repositories/credentials.ts +106 -0
  213. package/server/modules/database/repositories/github-tokens.ts +100 -0
  214. package/server/modules/database/repositories/notification-preferences.ts +103 -0
  215. package/server/modules/database/repositories/projects.db.integration.test.ts +72 -0
  216. package/server/modules/database/repositories/projects.db.ts +183 -0
  217. package/server/modules/database/repositories/push-subscriptions.ts +80 -0
  218. package/server/modules/database/repositories/scan-state.db.ts +42 -0
  219. package/server/modules/database/repositories/sessions.db.ts +174 -0
  220. package/server/modules/database/repositories/users.ts +140 -0
  221. package/server/modules/database/repositories/vapid-keys.ts +57 -0
  222. package/server/modules/database/schema.ts +152 -0
  223. package/server/modules/projects/index.ts +6 -0
  224. package/server/modules/projects/projects.routes.ts +247 -0
  225. package/server/modules/projects/services/project-clone.service.ts +321 -0
  226. package/server/modules/projects/services/project-delete.service.ts +75 -0
  227. package/server/modules/projects/services/project-management.service.ts +150 -0
  228. package/server/modules/projects/services/project-star.service.ts +78 -0
  229. package/server/modules/projects/services/projects-has-taskmaster.service.ts +248 -0
  230. package/server/modules/projects/services/projects-with-sessions-fetch.service.ts +285 -0
  231. package/server/modules/projects/tests/project-clone.service.test.ts +183 -0
  232. package/server/modules/projects/tests/project-management.service.test.ts +117 -0
  233. package/server/modules/projects/tests/project-star.service.test.ts +123 -0
  234. package/server/modules/projects/tests/projects-has-taskmaster.service.test.ts +105 -0
  235. package/server/modules/providers/index.ts +4 -0
  236. package/server/modules/providers/list/claude/claude-auth.provider.ts +123 -0
  237. package/server/modules/providers/list/claude/claude-mcp.provider.ts +135 -0
  238. package/server/modules/providers/list/claude/claude-session-synchronizer.provider.ts +110 -0
  239. package/server/modules/providers/list/claude/claude-sessions.provider.ts +475 -0
  240. package/server/modules/providers/list/claude/claude.provider.ts +17 -0
  241. package/server/modules/providers/list/codex/codex-auth.provider.ts +100 -0
  242. package/server/modules/providers/list/codex/codex-mcp.provider.ts +135 -0
  243. package/server/modules/providers/list/codex/codex-session-synchronizer.provider.ts +119 -0
  244. package/server/modules/providers/list/codex/codex-sessions.provider.ts +564 -0
  245. package/server/modules/providers/list/codex/codex.provider.ts +17 -0
  246. package/server/modules/providers/list/cursor/cursor-auth.provider.ts +143 -0
  247. package/server/modules/providers/list/cursor/cursor-mcp.provider.ts +108 -0
  248. package/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.ts +176 -0
  249. package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +421 -0
  250. package/server/modules/providers/list/cursor/cursor.provider.ts +17 -0
  251. package/server/modules/providers/list/gemini/gemini-auth.provider.ts +151 -0
  252. package/server/modules/providers/list/gemini/gemini-mcp.provider.ts +110 -0
  253. package/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.ts +401 -0
  254. package/server/modules/providers/list/gemini/gemini-sessions.provider.ts +541 -0
  255. package/server/modules/providers/list/gemini/gemini.provider.ts +17 -0
  256. package/server/modules/providers/provider.registry.ts +36 -0
  257. package/server/modules/providers/provider.routes.ts +425 -0
  258. package/server/modules/providers/services/mcp.service.ts +94 -0
  259. package/server/modules/providers/services/provider-auth.service.ts +26 -0
  260. package/server/modules/providers/services/session-conversations-search.service.ts +1167 -0
  261. package/server/modules/providers/services/session-synchronizer.service.ts +74 -0
  262. package/server/modules/providers/services/sessions-watcher.service.ts +283 -0
  263. package/server/modules/providers/services/sessions.service.ts +130 -0
  264. package/server/modules/providers/shared/base/abstract.provider.ts +27 -0
  265. package/server/modules/providers/shared/mcp/mcp.provider.ts +151 -0
  266. package/server/modules/providers/tests/mcp.test.ts +293 -0
  267. package/server/modules/websocket/README.md +267 -0
  268. package/server/modules/websocket/index.ts +2 -0
  269. package/server/modules/websocket/services/chat-websocket.service.ts +271 -0
  270. package/server/modules/websocket/services/plugin-websocket-proxy.service.ts +65 -0
  271. package/server/modules/websocket/services/shell-websocket.service.ts +453 -0
  272. package/server/modules/websocket/services/websocket-auth.service.ts +54 -0
  273. package/server/modules/websocket/services/websocket-server.service.ts +58 -0
  274. package/server/modules/websocket/services/websocket-state.service.ts +16 -0
  275. package/server/modules/websocket/services/websocket-writer.service.ts +38 -0
  276. package/server/openai-codex.js +5 -5
  277. package/server/routes/agent.js +11 -16
  278. package/server/routes/auth.js +4 -2
  279. package/server/routes/commands.js +1 -50
  280. package/server/routes/cursor.js +15 -527
  281. package/server/routes/gemini.js +3 -2
  282. package/server/routes/git.js +33 -28
  283. package/server/routes/mcp-utils.js +2 -19
  284. package/server/routes/settings.js +11 -1
  285. package/server/routes/taskmaster.js +107 -602
  286. package/server/routes/user.js +1 -1
  287. package/server/services/notification-orchestrator.js +3 -2
  288. package/server/services/vapid-keys.js +2 -1
  289. package/server/shared/interfaces.ts +92 -0
  290. package/server/shared/types.ts +327 -0
  291. package/server/shared/utils.ts +669 -0
  292. package/server/tsconfig.json +6 -3
  293. package/server/utils/mcp-detector.js +0 -51
  294. package/server/utils/taskmaster-websocket.js +19 -13
  295. package/shared/modelConstants.js +3 -1
  296. package/dist/assets/index-BBAE1OJ_.css +0 -32
  297. package/dist/assets/index-Ci1GOyV7.js +0 -1262
  298. package/dist-server/server/database/db.js +0 -535
  299. package/dist-server/server/database/db.js.map +0 -1
  300. package/dist-server/server/database/schema.js +0 -97
  301. package/dist-server/server/database/schema.js.map +0 -1
  302. package/dist-server/server/projects.js +0 -2325
  303. package/dist-server/server/projects.js.map +0 -1
  304. package/dist-server/server/providers/claude/adapter.js +0 -266
  305. package/dist-server/server/providers/claude/adapter.js.map +0 -1
  306. package/dist-server/server/providers/claude/status.js +0 -121
  307. package/dist-server/server/providers/claude/status.js.map +0 -1
  308. package/dist-server/server/providers/codex/adapter.js +0 -232
  309. package/dist-server/server/providers/codex/adapter.js.map +0 -1
  310. package/dist-server/server/providers/codex/status.js +0 -70
  311. package/dist-server/server/providers/codex/status.js.map +0 -1
  312. package/dist-server/server/providers/cursor/adapter.js +0 -342
  313. package/dist-server/server/providers/cursor/adapter.js.map +0 -1
  314. package/dist-server/server/providers/cursor/status.js +0 -118
  315. package/dist-server/server/providers/cursor/status.js.map +0 -1
  316. package/dist-server/server/providers/gemini/adapter.js +0 -174
  317. package/dist-server/server/providers/gemini/adapter.js.map +0 -1
  318. package/dist-server/server/providers/gemini/status.js +0 -104
  319. package/dist-server/server/providers/gemini/status.js.map +0 -1
  320. package/dist-server/server/providers/registry.js +0 -58
  321. package/dist-server/server/providers/registry.js.map +0 -1
  322. package/dist-server/server/providers/types.js +0 -117
  323. package/dist-server/server/providers/types.js.map +0 -1
  324. package/dist-server/server/providers/utils.js +0 -28
  325. package/dist-server/server/providers/utils.js.map +0 -1
  326. package/dist-server/server/routes/cli-auth.js +0 -25
  327. package/dist-server/server/routes/cli-auth.js.map +0 -1
  328. package/dist-server/server/routes/codex.js +0 -294
  329. package/dist-server/server/routes/codex.js.map +0 -1
  330. package/dist-server/server/routes/mcp.js +0 -480
  331. package/dist-server/server/routes/mcp.js.map +0 -1
  332. package/dist-server/server/routes/messages.js +0 -56
  333. package/dist-server/server/routes/messages.js.map +0 -1
  334. package/dist-server/server/routes/projects.js +0 -505
  335. package/dist-server/server/routes/projects.js.map +0 -1
  336. package/server/database/db.js +0 -593
  337. package/server/database/schema.js +0 -102
  338. package/server/projects.js +0 -2555
  339. package/server/providers/claude/adapter.js +0 -278
  340. package/server/providers/claude/status.js +0 -136
  341. package/server/providers/codex/adapter.js +0 -248
  342. package/server/providers/codex/status.js +0 -78
  343. package/server/providers/cursor/adapter.js +0 -348
  344. package/server/providers/cursor/status.js +0 -128
  345. package/server/providers/gemini/adapter.js +0 -186
  346. package/server/providers/gemini/status.js +0 -111
  347. package/server/providers/registry.js +0 -67
  348. package/server/providers/types.js +0 -132
  349. package/server/providers/utils.js +0 -29
  350. package/server/routes/cli-auth.js +0 -27
  351. package/server/routes/codex.js +0 -329
  352. package/server/routes/mcp.js +0 -552
  353. package/server/routes/messages.js +0 -61
  354. package/server/routes/projects.js +0 -548
@@ -12,14 +12,23 @@ import fs from 'fs';
12
12
  import path from 'path';
13
13
  import { promises as fsPromises } from 'fs';
14
14
  import { spawn } from 'child_process';
15
- import { fileURLToPath } from 'url';
16
- import { dirname } from 'path';
17
- import os from 'os';
18
- import { extractProjectDirectory } from '../projects.js';
15
+ import { projectsDb } from '../modules/database/index.js';
19
16
  import { detectTaskMasterMCPServer } from '../utils/mcp-detector.js';
20
17
  import { broadcastTaskMasterProjectUpdate, broadcastTaskMasterTasksUpdate } from '../utils/taskmaster-websocket.js';
21
- const __filename = fileURLToPath(import.meta.url);
22
- const __dirname = dirname(__filename);
18
+ /**
19
+ * Resolve the absolute project directory from a DB-assigned `projectId`.
20
+ *
21
+ * TaskMaster routes used to accept a Claude-encoded folder name (`projectName`)
22
+ * and derive the path from JSONL history. After the projectId migration the
23
+ * only identifier we accept is the primary key of the `projects` table, so
24
+ * every handler calls this helper and 404s when the id is unknown.
25
+ */
26
+ async function resolveProjectPathFromId(projectId) {
27
+ if (!projectId) {
28
+ return null;
29
+ }
30
+ return projectsDb.getProjectPathById(projectId);
31
+ }
23
32
  const router = express.Router();
24
33
  /**
25
34
  * Check if TaskMaster CLI is installed globally
@@ -87,131 +96,6 @@ async function checkTaskMasterInstallation() {
87
96
  });
88
97
  });
89
98
  }
90
- /**
91
- * Detect .taskmaster folder presence in a given project directory
92
- * @param {string} projectPath - Absolute path to project directory
93
- * @returns {Promise<Object>} Detection result with status and metadata
94
- */
95
- async function detectTaskMasterFolder(projectPath) {
96
- try {
97
- const taskMasterPath = path.join(projectPath, '.taskmaster');
98
- // Check if .taskmaster directory exists
99
- try {
100
- const stats = await fsPromises.stat(taskMasterPath);
101
- if (!stats.isDirectory()) {
102
- return {
103
- hasTaskmaster: false,
104
- reason: '.taskmaster exists but is not a directory'
105
- };
106
- }
107
- }
108
- catch (error) {
109
- if (error.code === 'ENOENT') {
110
- return {
111
- hasTaskmaster: false,
112
- reason: '.taskmaster directory not found'
113
- };
114
- }
115
- throw error;
116
- }
117
- // Check for key TaskMaster files
118
- const keyFiles = [
119
- 'tasks/tasks.json',
120
- 'config.json'
121
- ];
122
- const fileStatus = {};
123
- let hasEssentialFiles = true;
124
- for (const file of keyFiles) {
125
- const filePath = path.join(taskMasterPath, file);
126
- try {
127
- await fsPromises.access(filePath, fs.constants.R_OK);
128
- fileStatus[file] = true;
129
- }
130
- catch (error) {
131
- fileStatus[file] = false;
132
- if (file === 'tasks/tasks.json') {
133
- hasEssentialFiles = false;
134
- }
135
- }
136
- }
137
- // Parse tasks.json if it exists for metadata
138
- let taskMetadata = null;
139
- if (fileStatus['tasks/tasks.json']) {
140
- try {
141
- const tasksPath = path.join(taskMasterPath, 'tasks/tasks.json');
142
- const tasksContent = await fsPromises.readFile(tasksPath, 'utf8');
143
- const tasksData = JSON.parse(tasksContent);
144
- // Handle both tagged and legacy formats
145
- let tasks = [];
146
- if (tasksData.tasks) {
147
- // Legacy format
148
- tasks = tasksData.tasks;
149
- }
150
- else {
151
- // Tagged format - get tasks from all tags
152
- Object.values(tasksData).forEach(tagData => {
153
- if (tagData.tasks) {
154
- tasks = tasks.concat(tagData.tasks);
155
- }
156
- });
157
- }
158
- // Calculate task statistics
159
- const stats = tasks.reduce((acc, task) => {
160
- acc.total++;
161
- acc[task.status] = (acc[task.status] || 0) + 1;
162
- // Count subtasks
163
- if (task.subtasks) {
164
- task.subtasks.forEach(subtask => {
165
- acc.subtotalTasks++;
166
- acc.subtasks = acc.subtasks || {};
167
- acc.subtasks[subtask.status] = (acc.subtasks[subtask.status] || 0) + 1;
168
- });
169
- }
170
- return acc;
171
- }, {
172
- total: 0,
173
- subtotalTasks: 0,
174
- pending: 0,
175
- 'in-progress': 0,
176
- done: 0,
177
- review: 0,
178
- deferred: 0,
179
- cancelled: 0,
180
- subtasks: {}
181
- });
182
- taskMetadata = {
183
- taskCount: stats.total,
184
- subtaskCount: stats.subtotalTasks,
185
- completed: stats.done || 0,
186
- pending: stats.pending || 0,
187
- inProgress: stats['in-progress'] || 0,
188
- review: stats.review || 0,
189
- completionPercentage: stats.total > 0 ? Math.round((stats.done / stats.total) * 100) : 0,
190
- lastModified: (await fsPromises.stat(tasksPath)).mtime.toISOString()
191
- };
192
- }
193
- catch (parseError) {
194
- console.warn('Failed to parse tasks.json:', parseError.message);
195
- taskMetadata = { error: 'Failed to parse tasks.json' };
196
- }
197
- }
198
- return {
199
- hasTaskmaster: true,
200
- hasEssentialFiles,
201
- files: fileStatus,
202
- metadata: taskMetadata,
203
- path: taskMasterPath
204
- };
205
- }
206
- catch (error) {
207
- console.error('Error detecting TaskMaster folder:', error);
208
- return {
209
- hasTaskmaster: false,
210
- reason: `Error checking directory: ${error.message}`
211
- };
212
- }
213
- }
214
- // MCP detection is now handled by the centralized utility
215
99
  // API Routes
216
100
  /**
217
101
  * GET /api/taskmaster/installation-status
@@ -247,294 +131,21 @@ router.get('/installation-status', async (req, res) => {
247
131
  }
248
132
  });
249
133
  /**
250
- * GET /api/taskmaster/detect/:projectName
251
- * Detect TaskMaster configuration for a specific project
252
- */
253
- router.get('/detect/:projectName', async (req, res) => {
254
- try {
255
- const { projectName } = req.params;
256
- // Use the existing extractProjectDirectory function to get actual project path
257
- let projectPath;
258
- try {
259
- projectPath = await extractProjectDirectory(projectName);
260
- }
261
- catch (error) {
262
- console.error('Error extracting project directory:', error);
263
- return res.status(404).json({
264
- error: 'Project path not found',
265
- projectName,
266
- message: error.message
267
- });
268
- }
269
- // Verify the project path exists
270
- try {
271
- await fsPromises.access(projectPath, fs.constants.R_OK);
272
- }
273
- catch (error) {
274
- return res.status(404).json({
275
- error: 'Project path not accessible',
276
- projectPath,
277
- projectName,
278
- message: error.message
279
- });
280
- }
281
- // Run detection in parallel
282
- const [taskMasterResult, mcpResult] = await Promise.all([
283
- detectTaskMasterFolder(projectPath),
284
- detectTaskMasterMCPServer()
285
- ]);
286
- // Determine overall status
287
- let status = 'not-configured';
288
- if (taskMasterResult.hasTaskmaster && taskMasterResult.hasEssentialFiles) {
289
- if (mcpResult.hasMCPServer && mcpResult.isConfigured) {
290
- status = 'fully-configured';
291
- }
292
- else {
293
- status = 'taskmaster-only';
294
- }
295
- }
296
- else if (mcpResult.hasMCPServer && mcpResult.isConfigured) {
297
- status = 'mcp-only';
298
- }
299
- const responseData = {
300
- projectName,
301
- projectPath,
302
- status,
303
- taskmaster: taskMasterResult,
304
- mcp: mcpResult,
305
- timestamp: new Date().toISOString()
306
- };
307
- res.json(responseData);
308
- }
309
- catch (error) {
310
- console.error('TaskMaster detection error:', error);
311
- res.status(500).json({
312
- error: 'Failed to detect TaskMaster configuration',
313
- message: error.message
314
- });
315
- }
316
- });
317
- /**
318
- * GET /api/taskmaster/detect-all
319
- * Detect TaskMaster configuration for all known projects
320
- * This endpoint works with the existing projects system
321
- */
322
- router.get('/detect-all', async (req, res) => {
323
- try {
324
- // Import getProjects from the projects module
325
- const { getProjects } = await import('../projects.js');
326
- const projects = await getProjects();
327
- // Run detection for all projects in parallel
328
- const detectionPromises = projects.map(async (project) => {
329
- try {
330
- // Use the project's fullPath if available, otherwise extract the directory
331
- let projectPath;
332
- if (project.fullPath) {
333
- projectPath = project.fullPath;
334
- }
335
- else {
336
- try {
337
- projectPath = await extractProjectDirectory(project.name);
338
- }
339
- catch (error) {
340
- throw new Error(`Failed to extract project directory: ${error.message}`);
341
- }
342
- }
343
- const [taskMasterResult, mcpResult] = await Promise.all([
344
- detectTaskMasterFolder(projectPath),
345
- detectTaskMasterMCPServer()
346
- ]);
347
- // Determine status
348
- let status = 'not-configured';
349
- if (taskMasterResult.hasTaskmaster && taskMasterResult.hasEssentialFiles) {
350
- if (mcpResult.hasMCPServer && mcpResult.isConfigured) {
351
- status = 'fully-configured';
352
- }
353
- else {
354
- status = 'taskmaster-only';
355
- }
356
- }
357
- else if (mcpResult.hasMCPServer && mcpResult.isConfigured) {
358
- status = 'mcp-only';
359
- }
360
- return {
361
- projectName: project.name,
362
- displayName: project.displayName,
363
- projectPath,
364
- status,
365
- taskmaster: taskMasterResult,
366
- mcp: mcpResult
367
- };
368
- }
369
- catch (error) {
370
- return {
371
- projectName: project.name,
372
- displayName: project.displayName,
373
- status: 'error',
374
- error: error.message
375
- };
376
- }
377
- });
378
- const results = await Promise.all(detectionPromises);
379
- res.json({
380
- projects: results,
381
- summary: {
382
- total: results.length,
383
- fullyConfigured: results.filter(p => p.status === 'fully-configured').length,
384
- taskmasterOnly: results.filter(p => p.status === 'taskmaster-only').length,
385
- mcpOnly: results.filter(p => p.status === 'mcp-only').length,
386
- notConfigured: results.filter(p => p.status === 'not-configured').length,
387
- errors: results.filter(p => p.status === 'error').length
388
- },
389
- timestamp: new Date().toISOString()
390
- });
391
- }
392
- catch (error) {
393
- console.error('Bulk TaskMaster detection error:', error);
394
- res.status(500).json({
395
- error: 'Failed to detect TaskMaster configuration for projects',
396
- message: error.message
397
- });
398
- }
399
- });
400
- /**
401
- * POST /api/taskmaster/initialize/:projectName
402
- * Initialize TaskMaster in a project (placeholder for future CLI integration)
403
- */
404
- router.post('/initialize/:projectName', async (req, res) => {
405
- try {
406
- const { projectName } = req.params;
407
- const { rules } = req.body; // Optional rule profiles
408
- // This will be implemented in a later subtask with CLI integration
409
- res.status(501).json({
410
- error: 'TaskMaster initialization not yet implemented',
411
- message: 'This endpoint will execute task-master init via CLI in a future update',
412
- projectName,
413
- rules
414
- });
415
- }
416
- catch (error) {
417
- console.error('TaskMaster initialization error:', error);
418
- res.status(500).json({
419
- error: 'Failed to initialize TaskMaster',
420
- message: error.message
421
- });
422
- }
423
- });
424
- /**
425
- * GET /api/taskmaster/next/:projectName
426
- * Get the next recommended task using task-master CLI
427
- */
428
- router.get('/next/:projectName', async (req, res) => {
429
- try {
430
- const { projectName } = req.params;
431
- // Get project path
432
- let projectPath;
433
- try {
434
- projectPath = await extractProjectDirectory(projectName);
435
- }
436
- catch (error) {
437
- return res.status(404).json({
438
- error: 'Project not found',
439
- message: `Project "${projectName}" does not exist`
440
- });
441
- }
442
- // Try to execute task-master next command
443
- try {
444
- const { spawn } = await import('child_process');
445
- const nextTaskCommand = spawn('task-master', ['next'], {
446
- cwd: projectPath,
447
- stdio: ['pipe', 'pipe', 'pipe']
448
- });
449
- let stdout = '';
450
- let stderr = '';
451
- nextTaskCommand.stdout.on('data', (data) => {
452
- stdout += data.toString();
453
- });
454
- nextTaskCommand.stderr.on('data', (data) => {
455
- stderr += data.toString();
456
- });
457
- await new Promise((resolve, reject) => {
458
- nextTaskCommand.on('close', (code) => {
459
- if (code === 0) {
460
- resolve();
461
- }
462
- else {
463
- reject(new Error(`task-master next failed with code ${code}: ${stderr}`));
464
- }
465
- });
466
- nextTaskCommand.on('error', (error) => {
467
- reject(error);
468
- });
469
- });
470
- // Parse the output - task-master next usually returns JSON
471
- let nextTaskData = null;
472
- if (stdout.trim()) {
473
- try {
474
- nextTaskData = JSON.parse(stdout);
475
- }
476
- catch (parseError) {
477
- // If not JSON, treat as plain text
478
- nextTaskData = { message: stdout.trim() };
479
- }
480
- }
481
- res.json({
482
- projectName,
483
- projectPath,
484
- nextTask: nextTaskData,
485
- timestamp: new Date().toISOString()
486
- });
487
- }
488
- catch (cliError) {
489
- console.warn('Failed to execute task-master CLI:', cliError.message);
490
- // Fallback to loading tasks and finding next one locally
491
- // Use localhost to bypass proxy for internal server-to-server calls
492
- const tasksResponse = await fetch(`http://localhost:${process.env.SERVER_PORT || process.env.PORT || '3001'}/api/taskmaster/tasks/${encodeURIComponent(projectName)}`, {
493
- headers: {
494
- 'Authorization': req.headers.authorization
495
- }
496
- });
497
- if (tasksResponse.ok) {
498
- const tasksData = await tasksResponse.json();
499
- const nextTask = tasksData.tasks?.find(task => task.status === 'pending' || task.status === 'in-progress') || null;
500
- res.json({
501
- projectName,
502
- projectPath,
503
- nextTask,
504
- fallback: true,
505
- message: 'Used fallback method (CLI not available)',
506
- timestamp: new Date().toISOString()
507
- });
508
- }
509
- else {
510
- throw new Error('Failed to load tasks via fallback method');
511
- }
512
- }
513
- }
514
- catch (error) {
515
- console.error('TaskMaster next task error:', error);
516
- res.status(500).json({
517
- error: 'Failed to get next task',
518
- message: error.message
519
- });
520
- }
521
- });
522
- /**
523
- * GET /api/taskmaster/tasks/:projectName
134
+ * GET /api/taskmaster/tasks/:projectId
524
135
  * Load actual tasks from .taskmaster/tasks/tasks.json
136
+ *
137
+ * `projectId` is the DB primary key of the project; the folder is resolved via
138
+ * the projects table rather than extracted from Claude JSONL history.
525
139
  */
526
- router.get('/tasks/:projectName', async (req, res) => {
140
+ router.get('/tasks/:projectId', async (req, res) => {
527
141
  try {
528
- const { projectName } = req.params;
529
- // Get project path
530
- let projectPath;
531
- try {
532
- projectPath = await extractProjectDirectory(projectName);
533
- }
534
- catch (error) {
142
+ const { projectId } = req.params;
143
+ // Get project path via the DB; the legacy JSONL-based resolver is gone.
144
+ const projectPath = await resolveProjectPathFromId(projectId);
145
+ if (!projectPath) {
535
146
  return res.status(404).json({
536
147
  error: 'Project not found',
537
- message: `Project "${projectName}" does not exist`
148
+ message: `Project "${projectId}" does not exist`
538
149
  });
539
150
  }
540
151
  const taskMasterPath = path.join(projectPath, '.taskmaster');
@@ -545,7 +156,7 @@ router.get('/tasks/:projectName', async (req, res) => {
545
156
  }
546
157
  catch (error) {
547
158
  return res.json({
548
- projectName,
159
+ projectId,
549
160
  tasks: [],
550
161
  message: 'No tasks.json file found'
551
162
  });
@@ -597,7 +208,7 @@ router.get('/tasks/:projectName', async (req, res) => {
597
208
  subtasks: task.subtasks || []
598
209
  }));
599
210
  res.json({
600
- projectName,
211
+ projectId,
601
212
  projectPath,
602
213
  tasks: transformedTasks,
603
214
  currentTag,
@@ -630,21 +241,18 @@ router.get('/tasks/:projectName', async (req, res) => {
630
241
  }
631
242
  });
632
243
  /**
633
- * GET /api/taskmaster/prd/:projectName
244
+ * GET /api/taskmaster/prd/:projectId
634
245
  * List all PRD files in the project's .taskmaster/docs directory
635
246
  */
636
- router.get('/prd/:projectName', async (req, res) => {
247
+ router.get('/prd/:projectId', async (req, res) => {
637
248
  try {
638
- const { projectName } = req.params;
639
- // Get project path
640
- let projectPath;
641
- try {
642
- projectPath = await extractProjectDirectory(projectName);
643
- }
644
- catch (error) {
249
+ const { projectId } = req.params;
250
+ // projectId projectPath lookup through the DB (post-migration).
251
+ const projectPath = await resolveProjectPathFromId(projectId);
252
+ if (!projectPath) {
645
253
  return res.status(404).json({
646
254
  error: 'Project not found',
647
- message: `Project "${projectName}" does not exist`
255
+ message: `Project "${projectId}" does not exist`
648
256
  });
649
257
  }
650
258
  const docsPath = path.join(projectPath, '.taskmaster', 'docs');
@@ -654,7 +262,7 @@ router.get('/prd/:projectName', async (req, res) => {
654
262
  }
655
263
  catch (error) {
656
264
  return res.json({
657
- projectName,
265
+ projectId,
658
266
  prdFiles: [],
659
267
  message: 'No .taskmaster/docs directory found'
660
268
  });
@@ -677,7 +285,7 @@ router.get('/prd/:projectName', async (req, res) => {
677
285
  }
678
286
  }
679
287
  res.json({
680
- projectName,
288
+ projectId,
681
289
  projectPath,
682
290
  prdFiles: prdFiles.sort((a, b) => new Date(b.modified) - new Date(a.modified)),
683
291
  timestamp: new Date().toISOString()
@@ -700,12 +308,12 @@ router.get('/prd/:projectName', async (req, res) => {
700
308
  }
701
309
  });
702
310
  /**
703
- * POST /api/taskmaster/prd/:projectName
311
+ * POST /api/taskmaster/prd/:projectId
704
312
  * Create or update a PRD file in the project's .taskmaster/docs directory
705
313
  */
706
- router.post('/prd/:projectName', async (req, res) => {
314
+ router.post('/prd/:projectId', async (req, res) => {
707
315
  try {
708
- const { projectName } = req.params;
316
+ const { projectId } = req.params;
709
317
  const { fileName, content } = req.body;
710
318
  if (!fileName || !content) {
711
319
  return res.status(400).json({
@@ -720,15 +328,12 @@ router.post('/prd/:projectName', async (req, res) => {
720
328
  message: 'Filename must end with .txt or .md and contain only alphanumeric characters, spaces, dots, and dashes'
721
329
  });
722
330
  }
723
- // Get project path
724
- let projectPath;
725
- try {
726
- projectPath = await extractProjectDirectory(projectName);
727
- }
728
- catch (error) {
331
+ // Resolve the project folder through the DB using the projectId param.
332
+ const projectPath = await resolveProjectPathFromId(projectId);
333
+ if (!projectPath) {
729
334
  return res.status(404).json({
730
335
  error: 'Project not found',
731
- message: `Project "${projectName}" does not exist`
336
+ message: `Project "${projectId}" does not exist`
732
337
  });
733
338
  }
734
339
  const docsPath = path.join(projectPath, '.taskmaster', 'docs');
@@ -750,7 +355,7 @@ router.post('/prd/:projectName', async (req, res) => {
750
355
  // Get file stats
751
356
  const stats = await fsPromises.stat(filePath);
752
357
  res.json({
753
- projectName,
358
+ projectId,
754
359
  projectPath,
755
360
  fileName,
756
361
  filePath: path.relative(projectPath, filePath),
@@ -778,21 +383,17 @@ router.post('/prd/:projectName', async (req, res) => {
778
383
  }
779
384
  });
780
385
  /**
781
- * GET /api/taskmaster/prd/:projectName/:fileName
386
+ * GET /api/taskmaster/prd/:projectId/:fileName
782
387
  * Get content of a specific PRD file
783
388
  */
784
- router.get('/prd/:projectName/:fileName', async (req, res) => {
389
+ router.get('/prd/:projectId/:fileName', async (req, res) => {
785
390
  try {
786
- const { projectName, fileName } = req.params;
787
- // Get project path
788
- let projectPath;
789
- try {
790
- projectPath = await extractProjectDirectory(projectName);
791
- }
792
- catch (error) {
391
+ const { projectId, fileName } = req.params;
392
+ const projectPath = await resolveProjectPathFromId(projectId);
393
+ if (!projectPath) {
793
394
  return res.status(404).json({
794
395
  error: 'Project not found',
795
- message: `Project "${projectName}" does not exist`
396
+ message: `Project "${projectId}" does not exist`
796
397
  });
797
398
  }
798
399
  const filePath = path.join(projectPath, '.taskmaster', 'docs', fileName);
@@ -811,7 +412,7 @@ router.get('/prd/:projectName/:fileName', async (req, res) => {
811
412
  const content = await fsPromises.readFile(filePath, 'utf8');
812
413
  const stats = await fsPromises.stat(filePath);
813
414
  res.json({
814
- projectName,
415
+ projectId,
815
416
  projectPath,
816
417
  fileName,
817
418
  filePath: path.relative(projectPath, filePath),
@@ -839,77 +440,17 @@ router.get('/prd/:projectName/:fileName', async (req, res) => {
839
440
  }
840
441
  });
841
442
  /**
842
- * DELETE /api/taskmaster/prd/:projectName/:fileName
843
- * Delete a specific PRD file
844
- */
845
- router.delete('/prd/:projectName/:fileName', async (req, res) => {
846
- try {
847
- const { projectName, fileName } = req.params;
848
- // Get project path
849
- let projectPath;
850
- try {
851
- projectPath = await extractProjectDirectory(projectName);
852
- }
853
- catch (error) {
854
- return res.status(404).json({
855
- error: 'Project not found',
856
- message: `Project "${projectName}" does not exist`
857
- });
858
- }
859
- const filePath = path.join(projectPath, '.taskmaster', 'docs', fileName);
860
- // Check if file exists
861
- try {
862
- await fsPromises.access(filePath, fs.constants.F_OK);
863
- }
864
- catch (error) {
865
- return res.status(404).json({
866
- error: 'PRD file not found',
867
- message: `File "${fileName}" does not exist`
868
- });
869
- }
870
- // Delete the file
871
- try {
872
- await fsPromises.unlink(filePath);
873
- res.json({
874
- projectName,
875
- projectPath,
876
- fileName,
877
- message: 'PRD file deleted successfully',
878
- timestamp: new Date().toISOString()
879
- });
880
- }
881
- catch (deleteError) {
882
- console.error('Failed to delete PRD file:', deleteError);
883
- return res.status(500).json({
884
- error: 'Failed to delete PRD file',
885
- message: deleteError.message
886
- });
887
- }
888
- }
889
- catch (error) {
890
- console.error('PRD delete error:', error);
891
- res.status(500).json({
892
- error: 'Failed to delete PRD file',
893
- message: error.message
894
- });
895
- }
896
- });
897
- /**
898
- * POST /api/taskmaster/init/:projectName
443
+ * POST /api/taskmaster/init/:projectId
899
444
  * Initialize TaskMaster in a project
900
445
  */
901
- router.post('/init/:projectName', async (req, res) => {
446
+ router.post('/init/:projectId', async (req, res) => {
902
447
  try {
903
- const { projectName } = req.params;
904
- // Get project path
905
- let projectPath;
906
- try {
907
- projectPath = await extractProjectDirectory(projectName);
908
- }
909
- catch (error) {
448
+ const { projectId } = req.params;
449
+ const projectPath = await resolveProjectPathFromId(projectId);
450
+ if (!projectPath) {
910
451
  return res.status(404).json({
911
452
  error: 'Project not found',
912
- message: `Project "${projectName}" does not exist`
453
+ message: `Project "${projectId}" does not exist`
913
454
  });
914
455
  }
915
456
  // Check if TaskMaster is already initialized
@@ -939,12 +480,14 @@ router.post('/init/:projectName', async (req, res) => {
939
480
  });
940
481
  initProcess.on('close', (code) => {
941
482
  if (code === 0) {
942
- // Broadcast TaskMaster project update via WebSocket
483
+ // Broadcast TaskMaster project update via WebSocket. The
484
+ // WebSocket payload keeps using `projectId` so the frontend
485
+ // can match notifications against the current selection.
943
486
  if (req.app.locals.wss) {
944
- broadcastTaskMasterProjectUpdate(req.app.locals.wss, projectName, { hasTaskmaster: true, status: 'initialized' });
487
+ broadcastTaskMasterProjectUpdate(req.app.locals.wss, projectId, { hasTaskmaster: true, status: 'initialized' });
945
488
  }
946
489
  res.json({
947
- projectName,
490
+ projectId,
948
491
  projectPath,
949
492
  message: 'TaskMaster initialized successfully',
950
493
  output: stdout,
@@ -973,12 +516,12 @@ router.post('/init/:projectName', async (req, res) => {
973
516
  }
974
517
  });
975
518
  /**
976
- * POST /api/taskmaster/add-task/:projectName
519
+ * POST /api/taskmaster/add-task/:projectId
977
520
  * Add a new task to the project
978
521
  */
979
- router.post('/add-task/:projectName', async (req, res) => {
522
+ router.post('/add-task/:projectId', async (req, res) => {
980
523
  try {
981
- const { projectName } = req.params;
524
+ const { projectId } = req.params;
982
525
  const { prompt, title, description, priority = 'medium', dependencies } = req.body;
983
526
  if (!prompt && (!title || !description)) {
984
527
  return res.status(400).json({
@@ -986,15 +529,11 @@ router.post('/add-task/:projectName', async (req, res) => {
986
529
  message: 'Either "prompt" or both "title" and "description" are required'
987
530
  });
988
531
  }
989
- // Get project path
990
- let projectPath;
991
- try {
992
- projectPath = await extractProjectDirectory(projectName);
993
- }
994
- catch (error) {
532
+ const projectPath = await resolveProjectPathFromId(projectId);
533
+ if (!projectPath) {
995
534
  return res.status(404).json({
996
535
  error: 'Project not found',
997
- message: `Project "${projectName}" does not exist`
536
+ message: `Project "${projectId}" does not exist`
998
537
  });
999
538
  }
1000
539
  // Build the task-master add-task command
@@ -1030,12 +569,13 @@ router.post('/add-task/:projectName', async (req, res) => {
1030
569
  console.log('Stdout:', stdout);
1031
570
  console.log('Stderr:', stderr);
1032
571
  if (code === 0) {
1033
- // Broadcast task update via WebSocket
572
+ // Broadcast task update via WebSocket using the projectId so
573
+ // clients subscribed to this project get notified immediately.
1034
574
  if (req.app.locals.wss) {
1035
- broadcastTaskMasterTasksUpdate(req.app.locals.wss, projectName);
575
+ broadcastTaskMasterTasksUpdate(req.app.locals.wss, projectId);
1036
576
  }
1037
577
  res.json({
1038
- projectName,
578
+ projectId,
1039
579
  projectPath,
1040
580
  message: 'Task added successfully',
1041
581
  output: stdout,
@@ -1062,22 +602,18 @@ router.post('/add-task/:projectName', async (req, res) => {
1062
602
  }
1063
603
  });
1064
604
  /**
1065
- * PUT /api/taskmaster/update-task/:projectName/:taskId
605
+ * PUT /api/taskmaster/update-task/:projectId/:taskId
1066
606
  * Update a specific task using TaskMaster CLI
1067
607
  */
1068
- router.put('/update-task/:projectName/:taskId', async (req, res) => {
608
+ router.put('/update-task/:projectId/:taskId', async (req, res) => {
1069
609
  try {
1070
- const { projectName, taskId } = req.params;
610
+ const { projectId, taskId } = req.params;
1071
611
  const { title, description, status, priority, details } = req.body;
1072
- // Get project path
1073
- let projectPath;
1074
- try {
1075
- projectPath = await extractProjectDirectory(projectName);
1076
- }
1077
- catch (error) {
612
+ const projectPath = await resolveProjectPathFromId(projectId);
613
+ if (!projectPath) {
1078
614
  return res.status(404).json({
1079
615
  error: 'Project not found',
1080
- message: `Project "${projectName}" does not exist`
616
+ message: `Project "${projectId}" does not exist`
1081
617
  });
1082
618
  }
1083
619
  // If only updating status, use set-status command
@@ -1098,10 +634,10 @@ router.put('/update-task/:projectName/:taskId', async (req, res) => {
1098
634
  if (code === 0) {
1099
635
  // Broadcast task update via WebSocket
1100
636
  if (req.app.locals.wss) {
1101
- broadcastTaskMasterTasksUpdate(req.app.locals.wss, projectName);
637
+ broadcastTaskMasterTasksUpdate(req.app.locals.wss, projectId);
1102
638
  }
1103
639
  res.json({
1104
- projectName,
640
+ projectId,
1105
641
  projectPath,
1106
642
  taskId,
1107
643
  message: 'Task status updated successfully',
@@ -1148,10 +684,10 @@ router.put('/update-task/:projectName/:taskId', async (req, res) => {
1148
684
  if (code === 0) {
1149
685
  // Broadcast task update via WebSocket
1150
686
  if (req.app.locals.wss) {
1151
- broadcastTaskMasterTasksUpdate(req.app.locals.wss, projectName);
687
+ broadcastTaskMasterTasksUpdate(req.app.locals.wss, projectId);
1152
688
  }
1153
689
  res.json({
1154
- projectName,
690
+ projectId,
1155
691
  projectPath,
1156
692
  taskId,
1157
693
  message: 'Task updated successfully',
@@ -1180,22 +716,18 @@ router.put('/update-task/:projectName/:taskId', async (req, res) => {
1180
716
  }
1181
717
  });
1182
718
  /**
1183
- * POST /api/taskmaster/parse-prd/:projectName
719
+ * POST /api/taskmaster/parse-prd/:projectId
1184
720
  * Parse a PRD file to generate tasks
1185
721
  */
1186
- router.post('/parse-prd/:projectName', async (req, res) => {
722
+ router.post('/parse-prd/:projectId', async (req, res) => {
1187
723
  try {
1188
- const { projectName } = req.params;
724
+ const { projectId } = req.params;
1189
725
  const { fileName = 'prd.txt', numTasks, append = false } = req.body;
1190
- // Get project path
1191
- let projectPath;
1192
- try {
1193
- projectPath = await extractProjectDirectory(projectName);
1194
- }
1195
- catch (error) {
726
+ const projectPath = await resolveProjectPathFromId(projectId);
727
+ if (!projectPath) {
1196
728
  return res.status(404).json({
1197
729
  error: 'Project not found',
1198
- message: `Project "${projectName}" does not exist`
730
+ message: `Project "${projectId}" does not exist`
1199
731
  });
1200
732
  }
1201
733
  const prdPath = path.join(projectPath, '.taskmaster', 'docs', fileName);
@@ -1235,10 +767,10 @@ router.post('/parse-prd/:projectName', async (req, res) => {
1235
767
  if (code === 0) {
1236
768
  // Broadcast task update via WebSocket
1237
769
  if (req.app.locals.wss) {
1238
- broadcastTaskMasterTasksUpdate(req.app.locals.wss, projectName);
770
+ broadcastTaskMasterTasksUpdate(req.app.locals.wss, projectId);
1239
771
  }
1240
772
  res.json({
1241
- projectName,
773
+ projectId,
1242
774
  projectPath,
1243
775
  prdFile: fileName,
1244
776
  message: 'PRD parsed and tasks generated successfully',
@@ -1710,12 +1242,12 @@ Description of the business problem, data sources, and expected insights.
1710
1242
  }
1711
1243
  });
1712
1244
  /**
1713
- * POST /api/taskmaster/apply-template/:projectName
1245
+ * POST /api/taskmaster/apply-template/:projectId
1714
1246
  * Apply a PRD template to create a new PRD file
1715
1247
  */
1716
- router.post('/apply-template/:projectName', async (req, res) => {
1248
+ router.post('/apply-template/:projectId', async (req, res) => {
1717
1249
  try {
1718
- const { projectName } = req.params;
1250
+ const { projectId } = req.params;
1719
1251
  const { templateId, fileName = 'prd.txt', customizations = {} } = req.body;
1720
1252
  if (!templateId) {
1721
1253
  return res.status(400).json({
@@ -1723,15 +1255,11 @@ router.post('/apply-template/:projectName', async (req, res) => {
1723
1255
  message: 'templateId is required'
1724
1256
  });
1725
1257
  }
1726
- // Get project path
1727
- let projectPath;
1728
- try {
1729
- projectPath = await extractProjectDirectory(projectName);
1730
- }
1731
- catch (error) {
1258
+ const projectPath = await resolveProjectPathFromId(projectId);
1259
+ if (!projectPath) {
1732
1260
  return res.status(404).json({
1733
1261
  error: 'Project not found',
1734
- message: `Project "${projectName}" does not exist`
1262
+ message: `Project "${projectId}" does not exist`
1735
1263
  });
1736
1264
  }
1737
1265
  // Get the template content (this would normally fetch from the templates list)
@@ -1763,7 +1291,7 @@ router.post('/apply-template/:projectName', async (req, res) => {
1763
1291
  try {
1764
1292
  await fsPromises.writeFile(filePath, content, 'utf8');
1765
1293
  res.json({
1766
- projectName,
1294
+ projectId,
1767
1295
  projectPath,
1768
1296
  templateId,
1769
1297
  templateName: template.name,