@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,1468 @@
1
+ /**
2
+ * TASKMASTER API ROUTES
3
+ * ====================
4
+ *
5
+ * This module provides API endpoints for TaskMaster integration including:
6
+ * - .taskmaster folder detection in project directories
7
+ * - MCP server configuration detection
8
+ * - TaskMaster state and metadata management
9
+ */
10
+
11
+ import express from 'express';
12
+ import fs from 'fs';
13
+ import path from 'path';
14
+ import { promises as fsPromises } from 'fs';
15
+ import { spawn } from 'child_process';
16
+ import { projectsDb } from '../modules/database/index.js';
17
+ import { detectTaskMasterMCPServer } from '../utils/mcp-detector.js';
18
+ import { broadcastTaskMasterProjectUpdate, broadcastTaskMasterTasksUpdate } from '../utils/taskmaster-websocket.js';
19
+
20
+ /**
21
+ * Resolve the absolute project directory from a DB-assigned `projectId`.
22
+ *
23
+ * TaskMaster routes used to accept a Claude-encoded folder name (`projectName`)
24
+ * and derive the path from JSONL history. After the projectId migration the
25
+ * only identifier we accept is the primary key of the `projects` table, so
26
+ * every handler calls this helper and 404s when the id is unknown.
27
+ */
28
+ async function resolveProjectPathFromId(userId, projectId) {
29
+ if (!projectId) {
30
+ return null;
31
+ }
32
+ return projectsDb.getProjectPathById(userId, projectId);
33
+ }
34
+
35
+ const router = express.Router();
36
+
37
+ /**
38
+ * Check if TaskMaster CLI is installed globally
39
+ * @returns {Promise<Object>} Installation status result
40
+ */
41
+ async function checkTaskMasterInstallation() {
42
+ return new Promise((resolve) => {
43
+ // Check if task-master command is available
44
+ const child = spawn('which', ['task-master'], {
45
+ stdio: ['ignore', 'pipe', 'pipe'],
46
+ shell: true
47
+ });
48
+
49
+ let output = '';
50
+ let errorOutput = '';
51
+
52
+ child.stdout.on('data', (data) => {
53
+ output += data.toString();
54
+ });
55
+
56
+ child.stderr.on('data', (data) => {
57
+ errorOutput += data.toString();
58
+ });
59
+
60
+ child.on('close', (code) => {
61
+ if (code === 0 && output.trim()) {
62
+ // TaskMaster is installed, get version
63
+ const versionChild = spawn('task-master', ['--version'], {
64
+ stdio: ['ignore', 'pipe', 'pipe'],
65
+ shell: true
66
+ });
67
+
68
+ let versionOutput = '';
69
+
70
+ versionChild.stdout.on('data', (data) => {
71
+ versionOutput += data.toString();
72
+ });
73
+
74
+ versionChild.on('close', (versionCode) => {
75
+ resolve({
76
+ isInstalled: true,
77
+ installPath: output.trim(),
78
+ version: versionCode === 0 ? versionOutput.trim() : 'unknown',
79
+ reason: null
80
+ });
81
+ });
82
+
83
+ versionChild.on('error', () => {
84
+ resolve({
85
+ isInstalled: true,
86
+ installPath: output.trim(),
87
+ version: 'unknown',
88
+ reason: null
89
+ });
90
+ });
91
+ } else {
92
+ resolve({
93
+ isInstalled: false,
94
+ installPath: null,
95
+ version: null,
96
+ reason: 'TaskMaster CLI not found in PATH'
97
+ });
98
+ }
99
+ });
100
+
101
+ child.on('error', (error) => {
102
+ resolve({
103
+ isInstalled: false,
104
+ installPath: null,
105
+ version: null,
106
+ reason: `Error checking installation: ${error.message}`
107
+ });
108
+ });
109
+ });
110
+ }
111
+
112
+ // API Routes
113
+
114
+ /**
115
+ * GET /api/taskmaster/installation-status
116
+ * Check if TaskMaster CLI is installed on the system
117
+ */
118
+ router.get('/installation-status', async (req, res) => {
119
+ try {
120
+ const installationStatus = await checkTaskMasterInstallation();
121
+
122
+ // Also check for MCP server configuration
123
+ const mcpStatus = await detectTaskMasterMCPServer();
124
+
125
+ res.json({
126
+ success: true,
127
+ installation: installationStatus,
128
+ mcpServer: mcpStatus,
129
+ isReady: installationStatus.isInstalled && mcpStatus.hasMCPServer
130
+ });
131
+ } catch (error) {
132
+ console.error('Error checking TaskMaster installation:', error);
133
+ res.status(500).json({
134
+ success: false,
135
+ error: 'Failed to check TaskMaster installation status',
136
+ installation: {
137
+ isInstalled: false,
138
+ reason: `Server error: ${error.message}`
139
+ },
140
+ mcpServer: {
141
+ hasMCPServer: false,
142
+ reason: `Server error: ${error.message}`
143
+ },
144
+ isReady: false
145
+ });
146
+ }
147
+ });
148
+
149
+ /**
150
+ * GET /api/taskmaster/tasks/:projectId
151
+ * Load actual tasks from .taskmaster/tasks/tasks.json
152
+ *
153
+ * `projectId` is the DB primary key of the project; the folder is resolved via
154
+ * the projects table rather than extracted from Claude JSONL history.
155
+ */
156
+ router.get('/tasks/:projectId', async (req, res) => {
157
+ try {
158
+ const { projectId } = req.params;
159
+
160
+ // Get project path via the DB; the legacy JSONL-based resolver is gone.
161
+ const projectPath = await resolveProjectPathFromId(req.user.id, projectId);
162
+ if (!projectPath) {
163
+ return res.status(404).json({
164
+ error: 'Project not found',
165
+ message: `Project "${projectId}" does not exist`
166
+ });
167
+ }
168
+
169
+ const taskMasterPath = path.join(projectPath, '.taskmaster');
170
+ const tasksFilePath = path.join(taskMasterPath, 'tasks', 'tasks.json');
171
+
172
+ // Check if tasks file exists
173
+ try {
174
+ await fsPromises.access(tasksFilePath);
175
+ } catch (error) {
176
+ return res.json({
177
+ projectId,
178
+ tasks: [],
179
+ message: 'No tasks.json file found'
180
+ });
181
+ }
182
+
183
+ // Read and parse tasks file
184
+ try {
185
+ const tasksContent = await fsPromises.readFile(tasksFilePath, 'utf8');
186
+ const tasksData = JSON.parse(tasksContent);
187
+
188
+ let tasks = [];
189
+ let currentTag = 'master';
190
+
191
+ // Handle both tagged and legacy formats
192
+ if (Array.isArray(tasksData)) {
193
+ // Legacy format
194
+ tasks = tasksData;
195
+ } else if (tasksData.tasks) {
196
+ // Simple format with tasks array
197
+ tasks = tasksData.tasks;
198
+ } else {
199
+ // Tagged format - get tasks from current tag or master
200
+ if (tasksData[currentTag] && tasksData[currentTag].tasks) {
201
+ tasks = tasksData[currentTag].tasks;
202
+ } else if (tasksData.master && tasksData.master.tasks) {
203
+ tasks = tasksData.master.tasks;
204
+ } else {
205
+ // Get tasks from first available tag
206
+ const firstTag = Object.keys(tasksData).find(key =>
207
+ tasksData[key].tasks && Array.isArray(tasksData[key].tasks)
208
+ );
209
+ if (firstTag) {
210
+ tasks = tasksData[firstTag].tasks;
211
+ currentTag = firstTag;
212
+ }
213
+ }
214
+ }
215
+
216
+ // Transform tasks to ensure all have required fields
217
+ const transformedTasks = tasks.map(task => ({
218
+ id: task.id,
219
+ title: task.title || 'Untitled Task',
220
+ description: task.description || '',
221
+ status: task.status || 'pending',
222
+ priority: task.priority || 'medium',
223
+ dependencies: task.dependencies || [],
224
+ createdAt: task.createdAt || task.created || new Date().toISOString(),
225
+ updatedAt: task.updatedAt || task.updated || new Date().toISOString(),
226
+ details: task.details || '',
227
+ testStrategy: task.testStrategy || task.test_strategy || '',
228
+ subtasks: task.subtasks || []
229
+ }));
230
+
231
+ res.json({
232
+ projectId,
233
+ projectPath,
234
+ tasks: transformedTasks,
235
+ currentTag,
236
+ totalTasks: transformedTasks.length,
237
+ tasksByStatus: {
238
+ pending: transformedTasks.filter(t => t.status === 'pending').length,
239
+ 'in-progress': transformedTasks.filter(t => t.status === 'in-progress').length,
240
+ done: transformedTasks.filter(t => t.status === 'done').length,
241
+ review: transformedTasks.filter(t => t.status === 'review').length,
242
+ deferred: transformedTasks.filter(t => t.status === 'deferred').length,
243
+ cancelled: transformedTasks.filter(t => t.status === 'cancelled').length
244
+ },
245
+ timestamp: new Date().toISOString()
246
+ });
247
+
248
+ } catch (parseError) {
249
+ console.error('Failed to parse tasks.json:', parseError);
250
+ return res.status(500).json({
251
+ error: 'Failed to parse tasks file',
252
+ message: parseError.message
253
+ });
254
+ }
255
+
256
+ } catch (error) {
257
+ console.error('TaskMaster tasks loading error:', error);
258
+ res.status(500).json({
259
+ error: 'Failed to load TaskMaster tasks',
260
+ message: error.message
261
+ });
262
+ }
263
+ });
264
+
265
+ /**
266
+ * GET /api/taskmaster/prd/:projectId
267
+ * List all PRD files in the project's .taskmaster/docs directory
268
+ */
269
+ router.get('/prd/:projectId', async (req, res) => {
270
+ try {
271
+ const { projectId } = req.params;
272
+
273
+ // projectId → projectPath lookup through the DB (post-migration).
274
+ const projectPath = await resolveProjectPathFromId(req.user.id, projectId);
275
+ if (!projectPath) {
276
+ return res.status(404).json({
277
+ error: 'Project not found',
278
+ message: `Project "${projectId}" does not exist`
279
+ });
280
+ }
281
+
282
+ const docsPath = path.join(projectPath, '.taskmaster', 'docs');
283
+
284
+ // Check if docs directory exists
285
+ try {
286
+ await fsPromises.access(docsPath, fs.constants.R_OK);
287
+ } catch (error) {
288
+ return res.json({
289
+ projectId,
290
+ prdFiles: [],
291
+ message: 'No .taskmaster/docs directory found'
292
+ });
293
+ }
294
+
295
+ // Read directory and filter for PRD files
296
+ try {
297
+ const files = await fsPromises.readdir(docsPath);
298
+ const prdFiles = [];
299
+
300
+ for (const file of files) {
301
+ const filePath = path.join(docsPath, file);
302
+ const stats = await fsPromises.stat(filePath);
303
+
304
+ if (stats.isFile() && (file.endsWith('.txt') || file.endsWith('.md'))) {
305
+ prdFiles.push({
306
+ name: file,
307
+ path: path.relative(projectPath, filePath),
308
+ size: stats.size,
309
+ modified: stats.mtime.toISOString(),
310
+ created: stats.birthtime.toISOString()
311
+ });
312
+ }
313
+ }
314
+
315
+ res.json({
316
+ projectId,
317
+ projectPath,
318
+ prdFiles: prdFiles.sort((a, b) => new Date(b.modified) - new Date(a.modified)),
319
+ timestamp: new Date().toISOString()
320
+ });
321
+
322
+ } catch (readError) {
323
+ console.error('Error reading docs directory:', readError);
324
+ return res.status(500).json({
325
+ error: 'Failed to read PRD files',
326
+ message: readError.message
327
+ });
328
+ }
329
+
330
+ } catch (error) {
331
+ console.error('PRD list error:', error);
332
+ res.status(500).json({
333
+ error: 'Failed to list PRD files',
334
+ message: error.message
335
+ });
336
+ }
337
+ });
338
+
339
+ /**
340
+ * POST /api/taskmaster/prd/:projectId
341
+ * Create or update a PRD file in the project's .taskmaster/docs directory
342
+ */
343
+ router.post('/prd/:projectId', async (req, res) => {
344
+ try {
345
+ const { projectId } = req.params;
346
+ const { fileName, content } = req.body;
347
+
348
+ if (!fileName || !content) {
349
+ return res.status(400).json({
350
+ error: 'Missing required fields',
351
+ message: 'fileName and content are required'
352
+ });
353
+ }
354
+
355
+ // Validate filename
356
+ if (!fileName.match(/^[\w\-. ]+\.(txt|md)$/)) {
357
+ return res.status(400).json({
358
+ error: 'Invalid filename',
359
+ message: 'Filename must end with .txt or .md and contain only alphanumeric characters, spaces, dots, and dashes'
360
+ });
361
+ }
362
+
363
+ // Resolve the project folder through the DB using the projectId param.
364
+ const projectPath = await resolveProjectPathFromId(req.user.id, projectId);
365
+ if (!projectPath) {
366
+ return res.status(404).json({
367
+ error: 'Project not found',
368
+ message: `Project "${projectId}" does not exist`
369
+ });
370
+ }
371
+
372
+ const docsPath = path.join(projectPath, '.taskmaster', 'docs');
373
+ const filePath = path.join(docsPath, fileName);
374
+
375
+ // Ensure docs directory exists
376
+ try {
377
+ await fsPromises.mkdir(docsPath, { recursive: true });
378
+ } catch (error) {
379
+ console.error('Failed to create docs directory:', error);
380
+ return res.status(500).json({
381
+ error: 'Failed to create directory',
382
+ message: error.message
383
+ });
384
+ }
385
+
386
+ // Write the PRD file
387
+ try {
388
+ await fsPromises.writeFile(filePath, content, 'utf8');
389
+
390
+ // Get file stats
391
+ const stats = await fsPromises.stat(filePath);
392
+
393
+ res.json({
394
+ projectId,
395
+ projectPath,
396
+ fileName,
397
+ filePath: path.relative(projectPath, filePath),
398
+ size: stats.size,
399
+ created: stats.birthtime.toISOString(),
400
+ modified: stats.mtime.toISOString(),
401
+ message: 'PRD file saved successfully',
402
+ timestamp: new Date().toISOString()
403
+ });
404
+
405
+ } catch (writeError) {
406
+ console.error('Failed to write PRD file:', writeError);
407
+ return res.status(500).json({
408
+ error: 'Failed to write PRD file',
409
+ message: writeError.message
410
+ });
411
+ }
412
+
413
+ } catch (error) {
414
+ console.error('PRD create/update error:', error);
415
+ res.status(500).json({
416
+ error: 'Failed to create/update PRD file',
417
+ message: error.message
418
+ });
419
+ }
420
+ });
421
+
422
+ /**
423
+ * GET /api/taskmaster/prd/:projectId/:fileName
424
+ * Get content of a specific PRD file
425
+ */
426
+ router.get('/prd/:projectId/:fileName', async (req, res) => {
427
+ try {
428
+ const { projectId, fileName } = req.params;
429
+
430
+ const projectPath = await resolveProjectPathFromId(req.user.id, projectId);
431
+ if (!projectPath) {
432
+ return res.status(404).json({
433
+ error: 'Project not found',
434
+ message: `Project "${projectId}" does not exist`
435
+ });
436
+ }
437
+
438
+ const filePath = path.join(projectPath, '.taskmaster', 'docs', fileName);
439
+
440
+ // Check if file exists
441
+ try {
442
+ await fsPromises.access(filePath, fs.constants.R_OK);
443
+ } catch (error) {
444
+ return res.status(404).json({
445
+ error: 'PRD file not found',
446
+ message: `File "${fileName}" does not exist`
447
+ });
448
+ }
449
+
450
+ // Read file content
451
+ try {
452
+ const content = await fsPromises.readFile(filePath, 'utf8');
453
+ const stats = await fsPromises.stat(filePath);
454
+
455
+ res.json({
456
+ projectId,
457
+ projectPath,
458
+ fileName,
459
+ filePath: path.relative(projectPath, filePath),
460
+ content,
461
+ size: stats.size,
462
+ created: stats.birthtime.toISOString(),
463
+ modified: stats.mtime.toISOString(),
464
+ timestamp: new Date().toISOString()
465
+ });
466
+
467
+ } catch (readError) {
468
+ console.error('Failed to read PRD file:', readError);
469
+ return res.status(500).json({
470
+ error: 'Failed to read PRD file',
471
+ message: readError.message
472
+ });
473
+ }
474
+
475
+ } catch (error) {
476
+ console.error('PRD read error:', error);
477
+ res.status(500).json({
478
+ error: 'Failed to read PRD file',
479
+ message: error.message
480
+ });
481
+ }
482
+ });
483
+
484
+ /**
485
+ * POST /api/taskmaster/init/:projectId
486
+ * Initialize TaskMaster in a project
487
+ */
488
+ router.post('/init/:projectId', async (req, res) => {
489
+ try {
490
+ const { projectId } = req.params;
491
+
492
+ const projectPath = await resolveProjectPathFromId(req.user.id, projectId);
493
+ if (!projectPath) {
494
+ return res.status(404).json({
495
+ error: 'Project not found',
496
+ message: `Project "${projectId}" does not exist`
497
+ });
498
+ }
499
+
500
+ // Check if TaskMaster is already initialized
501
+ const taskMasterPath = path.join(projectPath, '.taskmaster');
502
+ try {
503
+ await fsPromises.access(taskMasterPath, fs.constants.F_OK);
504
+ return res.status(400).json({
505
+ error: 'TaskMaster already initialized',
506
+ message: 'TaskMaster is already configured for this project'
507
+ });
508
+ } catch (error) {
509
+ // Directory doesn't exist, we can proceed
510
+ }
511
+
512
+ // Run taskmaster init command
513
+ const initProcess = spawn('npx', ['task-master', 'init'], {
514
+ cwd: projectPath,
515
+ stdio: ['pipe', 'pipe', 'pipe']
516
+ });
517
+
518
+ let stdout = '';
519
+ let stderr = '';
520
+
521
+ initProcess.stdout.on('data', (data) => {
522
+ stdout += data.toString();
523
+ });
524
+
525
+ initProcess.stderr.on('data', (data) => {
526
+ stderr += data.toString();
527
+ });
528
+
529
+ initProcess.on('close', (code) => {
530
+ if (code === 0) {
531
+ // Broadcast TaskMaster project update via WebSocket. The
532
+ // WebSocket payload keeps using `projectId` so the frontend
533
+ // can match notifications against the current selection.
534
+ if (req.app.locals.wss) {
535
+ broadcastTaskMasterProjectUpdate(
536
+ req.app.locals.wss,
537
+ projectId,
538
+ { hasTaskmaster: true, status: 'initialized' }
539
+ );
540
+ }
541
+
542
+ res.json({
543
+ projectId,
544
+ projectPath,
545
+ message: 'TaskMaster initialized successfully',
546
+ output: stdout,
547
+ timestamp: new Date().toISOString()
548
+ });
549
+ } else {
550
+ console.error('TaskMaster init failed:', stderr);
551
+ res.status(500).json({
552
+ error: 'Failed to initialize TaskMaster',
553
+ message: stderr || stdout,
554
+ code
555
+ });
556
+ }
557
+ });
558
+
559
+ // Send 'yes' responses to automated prompts
560
+ initProcess.stdin.write('yes\n');
561
+ initProcess.stdin.end();
562
+
563
+ } catch (error) {
564
+ console.error('TaskMaster init error:', error);
565
+ res.status(500).json({
566
+ error: 'Failed to initialize TaskMaster',
567
+ message: error.message
568
+ });
569
+ }
570
+ });
571
+
572
+ /**
573
+ * POST /api/taskmaster/add-task/:projectId
574
+ * Add a new task to the project
575
+ */
576
+ router.post('/add-task/:projectId', async (req, res) => {
577
+ try {
578
+ const { projectId } = req.params;
579
+ const { prompt, title, description, priority = 'medium', dependencies } = req.body;
580
+
581
+ if (!prompt && (!title || !description)) {
582
+ return res.status(400).json({
583
+ error: 'Missing required parameters',
584
+ message: 'Either "prompt" or both "title" and "description" are required'
585
+ });
586
+ }
587
+
588
+ const projectPath = await resolveProjectPathFromId(req.user.id, projectId);
589
+ if (!projectPath) {
590
+ return res.status(404).json({
591
+ error: 'Project not found',
592
+ message: `Project "${projectId}" does not exist`
593
+ });
594
+ }
595
+
596
+ // Build the task-master add-task command
597
+ const args = ['task-master-ai', 'add-task'];
598
+
599
+ if (prompt) {
600
+ args.push('--prompt', prompt);
601
+ args.push('--research'); // Use research for AI-generated tasks
602
+ } else {
603
+ args.push('--prompt', `Create a task titled "${title}" with description: ${description}`);
604
+ }
605
+
606
+ if (priority) {
607
+ args.push('--priority', priority);
608
+ }
609
+
610
+ if (dependencies) {
611
+ args.push('--dependencies', dependencies);
612
+ }
613
+
614
+ // Run task-master add-task command
615
+ const addTaskProcess = spawn('npx', args, {
616
+ cwd: projectPath,
617
+ stdio: ['pipe', 'pipe', 'pipe']
618
+ });
619
+
620
+ let stdout = '';
621
+ let stderr = '';
622
+
623
+ addTaskProcess.stdout.on('data', (data) => {
624
+ stdout += data.toString();
625
+ });
626
+
627
+ addTaskProcess.stderr.on('data', (data) => {
628
+ stderr += data.toString();
629
+ });
630
+
631
+ addTaskProcess.on('close', (code) => {
632
+ console.log('Add task process completed with code:', code);
633
+ console.log('Stdout:', stdout);
634
+ console.log('Stderr:', stderr);
635
+
636
+ if (code === 0) {
637
+ // Broadcast task update via WebSocket using the projectId so
638
+ // clients subscribed to this project get notified immediately.
639
+ if (req.app.locals.wss) {
640
+ broadcastTaskMasterTasksUpdate(
641
+ req.app.locals.wss,
642
+ projectId
643
+ );
644
+ }
645
+
646
+ res.json({
647
+ projectId,
648
+ projectPath,
649
+ message: 'Task added successfully',
650
+ output: stdout,
651
+ timestamp: new Date().toISOString()
652
+ });
653
+ } else {
654
+ console.error('Add task failed:', stderr);
655
+ res.status(500).json({
656
+ error: 'Failed to add task',
657
+ message: stderr || stdout,
658
+ code
659
+ });
660
+ }
661
+ });
662
+
663
+ addTaskProcess.stdin.end();
664
+
665
+ } catch (error) {
666
+ console.error('Add task error:', error);
667
+ res.status(500).json({
668
+ error: 'Failed to add task',
669
+ message: error.message
670
+ });
671
+ }
672
+ });
673
+
674
+ /**
675
+ * PUT /api/taskmaster/update-task/:projectId/:taskId
676
+ * Update a specific task using TaskMaster CLI
677
+ */
678
+ router.put('/update-task/:projectId/:taskId', async (req, res) => {
679
+ try {
680
+ const { projectId, taskId } = req.params;
681
+ const { title, description, status, priority, details } = req.body;
682
+
683
+ const projectPath = await resolveProjectPathFromId(req.user.id, projectId);
684
+ if (!projectPath) {
685
+ return res.status(404).json({
686
+ error: 'Project not found',
687
+ message: `Project "${projectId}" does not exist`
688
+ });
689
+ }
690
+
691
+ // If only updating status, use set-status command
692
+ if (status && Object.keys(req.body).length === 1) {
693
+ const setStatusProcess = spawn('npx', ['task-master-ai', 'set-status', `--id=${taskId}`, `--status=${status}`], {
694
+ cwd: projectPath,
695
+ stdio: ['pipe', 'pipe', 'pipe']
696
+ });
697
+
698
+ let stdout = '';
699
+ let stderr = '';
700
+
701
+ setStatusProcess.stdout.on('data', (data) => {
702
+ stdout += data.toString();
703
+ });
704
+
705
+ setStatusProcess.stderr.on('data', (data) => {
706
+ stderr += data.toString();
707
+ });
708
+
709
+ setStatusProcess.on('close', (code) => {
710
+ if (code === 0) {
711
+ // Broadcast task update via WebSocket
712
+ if (req.app.locals.wss) {
713
+ broadcastTaskMasterTasksUpdate(req.app.locals.wss, projectId);
714
+ }
715
+
716
+ res.json({
717
+ projectId,
718
+ projectPath,
719
+ taskId,
720
+ message: 'Task status updated successfully',
721
+ output: stdout,
722
+ timestamp: new Date().toISOString()
723
+ });
724
+ } else {
725
+ console.error('Set task status failed:', stderr);
726
+ res.status(500).json({
727
+ error: 'Failed to update task status',
728
+ message: stderr || stdout,
729
+ code
730
+ });
731
+ }
732
+ });
733
+
734
+ setStatusProcess.stdin.end();
735
+ } else {
736
+ // For other updates, use update-task command with a prompt describing the changes
737
+ const updates = [];
738
+ if (title) updates.push(`title: "${title}"`);
739
+ if (description) updates.push(`description: "${description}"`);
740
+ if (priority) updates.push(`priority: "${priority}"`);
741
+ if (details) updates.push(`details: "${details}"`);
742
+
743
+ const prompt = `Update task with the following changes: ${updates.join(', ')}`;
744
+
745
+ const updateProcess = spawn('npx', ['task-master-ai', 'update-task', `--id=${taskId}`, `--prompt=${prompt}`], {
746
+ cwd: projectPath,
747
+ stdio: ['pipe', 'pipe', 'pipe']
748
+ });
749
+
750
+ let stdout = '';
751
+ let stderr = '';
752
+
753
+ updateProcess.stdout.on('data', (data) => {
754
+ stdout += data.toString();
755
+ });
756
+
757
+ updateProcess.stderr.on('data', (data) => {
758
+ stderr += data.toString();
759
+ });
760
+
761
+ updateProcess.on('close', (code) => {
762
+ if (code === 0) {
763
+ // Broadcast task update via WebSocket
764
+ if (req.app.locals.wss) {
765
+ broadcastTaskMasterTasksUpdate(req.app.locals.wss, projectId);
766
+ }
767
+
768
+ res.json({
769
+ projectId,
770
+ projectPath,
771
+ taskId,
772
+ message: 'Task updated successfully',
773
+ output: stdout,
774
+ timestamp: new Date().toISOString()
775
+ });
776
+ } else {
777
+ console.error('Update task failed:', stderr);
778
+ res.status(500).json({
779
+ error: 'Failed to update task',
780
+ message: stderr || stdout,
781
+ code
782
+ });
783
+ }
784
+ });
785
+
786
+ updateProcess.stdin.end();
787
+ }
788
+
789
+ } catch (error) {
790
+ console.error('Update task error:', error);
791
+ res.status(500).json({
792
+ error: 'Failed to update task',
793
+ message: error.message
794
+ });
795
+ }
796
+ });
797
+
798
+ /**
799
+ * POST /api/taskmaster/parse-prd/:projectId
800
+ * Parse a PRD file to generate tasks
801
+ */
802
+ router.post('/parse-prd/:projectId', async (req, res) => {
803
+ try {
804
+ const { projectId } = req.params;
805
+ const { fileName = 'prd.txt', numTasks, append = false } = req.body;
806
+
807
+ const projectPath = await resolveProjectPathFromId(req.user.id, projectId);
808
+ if (!projectPath) {
809
+ return res.status(404).json({
810
+ error: 'Project not found',
811
+ message: `Project "${projectId}" does not exist`
812
+ });
813
+ }
814
+
815
+ const prdPath = path.join(projectPath, '.taskmaster', 'docs', fileName);
816
+
817
+ // Check if PRD file exists
818
+ try {
819
+ await fsPromises.access(prdPath, fs.constants.F_OK);
820
+ } catch (error) {
821
+ return res.status(404).json({
822
+ error: 'PRD file not found',
823
+ message: `File "${fileName}" does not exist in .taskmaster/docs/`
824
+ });
825
+ }
826
+
827
+ // Build the command args
828
+ const args = ['task-master-ai', 'parse-prd', prdPath];
829
+
830
+ if (numTasks) {
831
+ args.push('--num-tasks', numTasks.toString());
832
+ }
833
+
834
+ if (append) {
835
+ args.push('--append');
836
+ }
837
+
838
+ args.push('--research'); // Use research for better PRD parsing
839
+
840
+ // Run task-master parse-prd command
841
+ const parsePRDProcess = spawn('npx', args, {
842
+ cwd: projectPath,
843
+ stdio: ['pipe', 'pipe', 'pipe']
844
+ });
845
+
846
+ let stdout = '';
847
+ let stderr = '';
848
+
849
+ parsePRDProcess.stdout.on('data', (data) => {
850
+ stdout += data.toString();
851
+ });
852
+
853
+ parsePRDProcess.stderr.on('data', (data) => {
854
+ stderr += data.toString();
855
+ });
856
+
857
+ parsePRDProcess.on('close', (code) => {
858
+ if (code === 0) {
859
+ // Broadcast task update via WebSocket
860
+ if (req.app.locals.wss) {
861
+ broadcastTaskMasterTasksUpdate(
862
+ req.app.locals.wss,
863
+ projectId
864
+ );
865
+ }
866
+
867
+ res.json({
868
+ projectId,
869
+ projectPath,
870
+ prdFile: fileName,
871
+ message: 'PRD parsed and tasks generated successfully',
872
+ output: stdout,
873
+ timestamp: new Date().toISOString()
874
+ });
875
+ } else {
876
+ console.error('Parse PRD failed:', stderr);
877
+ res.status(500).json({
878
+ error: 'Failed to parse PRD',
879
+ message: stderr || stdout,
880
+ code
881
+ });
882
+ }
883
+ });
884
+
885
+ parsePRDProcess.stdin.end();
886
+
887
+ } catch (error) {
888
+ console.error('Parse PRD error:', error);
889
+ res.status(500).json({
890
+ error: 'Failed to parse PRD',
891
+ message: error.message
892
+ });
893
+ }
894
+ });
895
+
896
+ /**
897
+ * GET /api/taskmaster/prd-templates
898
+ * Get available PRD templates
899
+ */
900
+ router.get('/prd-templates', async (req, res) => {
901
+ try {
902
+ // Return built-in templates
903
+ const templates = [
904
+ {
905
+ id: 'web-app',
906
+ name: 'Web Application',
907
+ description: 'Template for web application projects with frontend and backend components',
908
+ category: 'web',
909
+ content: `# Product Requirements Document - Web Application
910
+
911
+ ## Overview
912
+ **Product Name:** [Your App Name]
913
+ **Version:** 1.0
914
+ **Date:** ${new Date().toISOString().split('T')[0]}
915
+ **Author:** [Your Name]
916
+
917
+ ## Executive Summary
918
+ Brief description of what this web application will do and why it's needed.
919
+
920
+ ## Product Goals
921
+ - Goal 1: [Specific measurable goal]
922
+ - Goal 2: [Specific measurable goal]
923
+ - Goal 3: [Specific measurable goal]
924
+
925
+ ## User Stories
926
+ ### Core Features
927
+ 1. **User Registration & Authentication**
928
+ - As a user, I want to create an account so I can access personalized features
929
+ - As a user, I want to log in securely so my data is protected
930
+ - As a user, I want to reset my password if I forget it
931
+
932
+ 2. **Main Application Features**
933
+ - As a user, I want to [core feature 1] so I can [benefit]
934
+ - As a user, I want to [core feature 2] so I can [benefit]
935
+ - As a user, I want to [core feature 3] so I can [benefit]
936
+
937
+ 3. **User Interface**
938
+ - As a user, I want a responsive design so I can use the app on any device
939
+ - As a user, I want intuitive navigation so I can easily find features
940
+
941
+ ## Technical Requirements
942
+ ### Frontend
943
+ - Framework: React/Vue/Angular or vanilla JavaScript
944
+ - Styling: CSS framework (Tailwind, Bootstrap, etc.)
945
+ - State Management: Redux/Vuex/Context API
946
+ - Build Tools: Webpack/Vite
947
+ - Testing: Jest/Vitest for unit tests
948
+
949
+ ### Backend
950
+ - Runtime: Node.js/Python/Java
951
+ - Database: PostgreSQL/MySQL/MongoDB
952
+ - API: RESTful API or GraphQL
953
+ - Authentication: JWT tokens
954
+ - Testing: Integration and unit tests
955
+
956
+ ### Infrastructure
957
+ - Hosting: Cloud provider (AWS, Azure, GCP)
958
+ - CI/CD: GitHub Actions/GitLab CI
959
+ - Monitoring: Application monitoring tools
960
+ - Security: HTTPS, input validation, rate limiting
961
+
962
+ ## Success Metrics
963
+ - User engagement metrics
964
+ - Performance benchmarks (load time < 2s)
965
+ - Error rates < 1%
966
+ - User satisfaction scores
967
+
968
+ ## Timeline
969
+ - Phase 1: Core functionality (4-6 weeks)
970
+ - Phase 2: Advanced features (2-4 weeks)
971
+ - Phase 3: Polish and launch (2 weeks)
972
+
973
+ ## Constraints & Assumptions
974
+ - Budget constraints
975
+ - Technical limitations
976
+ - Team size and expertise
977
+ - Timeline constraints`
978
+ },
979
+ {
980
+ id: 'api',
981
+ name: 'REST API',
982
+ description: 'Template for REST API development projects',
983
+ category: 'backend',
984
+ content: `# Product Requirements Document - REST API
985
+
986
+ ## Overview
987
+ **API Name:** [Your API Name]
988
+ **Version:** v1.0
989
+ **Date:** ${new Date().toISOString().split('T')[0]}
990
+ **Author:** [Your Name]
991
+
992
+ ## Executive Summary
993
+ Description of the API's purpose, target users, and primary use cases.
994
+
995
+ ## API Goals
996
+ - Goal 1: Provide secure data access
997
+ - Goal 2: Ensure scalable architecture
998
+ - Goal 3: Maintain high availability (99.9% uptime)
999
+
1000
+ ## Functional Requirements
1001
+ ### Core Endpoints
1002
+ 1. **Authentication Endpoints**
1003
+ - POST /api/auth/login - User authentication
1004
+ - POST /api/auth/logout - User logout
1005
+ - POST /api/auth/refresh - Token refresh
1006
+ - POST /api/auth/register - User registration
1007
+
1008
+ 2. **Data Management Endpoints**
1009
+ - GET /api/resources - List resources with pagination
1010
+ - GET /api/resources/{id} - Get specific resource
1011
+ - POST /api/resources - Create new resource
1012
+ - PUT /api/resources/{id} - Update existing resource
1013
+ - DELETE /api/resources/{id} - Delete resource
1014
+
1015
+ 3. **Administrative Endpoints**
1016
+ - GET /api/admin/users - Manage users (admin only)
1017
+ - GET /api/admin/analytics - System analytics
1018
+ - POST /api/admin/backup - Trigger system backup
1019
+
1020
+ ## Technical Requirements
1021
+ ### API Design
1022
+ - RESTful architecture following OpenAPI 3.0 specification
1023
+ - JSON request/response format
1024
+ - Consistent error response format
1025
+ - API versioning strategy
1026
+
1027
+ ### Authentication & Security
1028
+ - JWT token-based authentication
1029
+ - Role-based access control (RBAC)
1030
+ - Rate limiting (100 requests/minute per user)
1031
+ - Input validation and sanitization
1032
+ - HTTPS enforcement
1033
+
1034
+ ### Database
1035
+ - Database type: [PostgreSQL/MongoDB/MySQL]
1036
+ - Connection pooling
1037
+ - Database migrations
1038
+ - Backup and recovery procedures
1039
+
1040
+ ### Performance Requirements
1041
+ - Response time: < 200ms for 95% of requests
1042
+ - Throughput: 1000+ requests/second
1043
+ - Concurrent users: 10,000+
1044
+ - Database query optimization
1045
+
1046
+ ### Documentation
1047
+ - Auto-generated API documentation (Swagger/OpenAPI)
1048
+ - Code examples for common use cases
1049
+ - SDK development for major languages
1050
+ - Postman collection for testing
1051
+
1052
+ ## Error Handling
1053
+ - Standardized error codes and messages
1054
+ - Proper HTTP status codes
1055
+ - Detailed error logging
1056
+ - Graceful degradation strategies
1057
+
1058
+ ## Testing Strategy
1059
+ - Unit tests (80%+ coverage)
1060
+ - Integration tests for all endpoints
1061
+ - Load testing and performance testing
1062
+ - Security testing (OWASP compliance)
1063
+
1064
+ ## Monitoring & Logging
1065
+ - Application performance monitoring
1066
+ - Error tracking and alerting
1067
+ - Access logs and audit trails
1068
+ - Health check endpoints
1069
+
1070
+ ## Deployment
1071
+ - Containerized deployment (Docker)
1072
+ - CI/CD pipeline setup
1073
+ - Environment management (dev, staging, prod)
1074
+ - Blue-green deployment strategy
1075
+
1076
+ ## Success Metrics
1077
+ - API uptime > 99.9%
1078
+ - Average response time < 200ms
1079
+ - Zero critical security vulnerabilities
1080
+ - Developer adoption metrics`
1081
+ },
1082
+ {
1083
+ id: 'mobile-app',
1084
+ name: 'Mobile Application',
1085
+ description: 'Template for mobile app development projects (iOS/Android)',
1086
+ category: 'mobile',
1087
+ content: `# Product Requirements Document - Mobile Application
1088
+
1089
+ ## Overview
1090
+ **App Name:** [Your App Name]
1091
+ **Platform:** iOS / Android / Cross-platform
1092
+ **Version:** 1.0
1093
+ **Date:** ${new Date().toISOString().split('T')[0]}
1094
+ **Author:** [Your Name]
1095
+
1096
+ ## Executive Summary
1097
+ Brief description of the mobile app's purpose, target audience, and key value proposition.
1098
+
1099
+ ## Product Goals
1100
+ - Goal 1: [Specific user engagement goal]
1101
+ - Goal 2: [Specific functionality goal]
1102
+ - Goal 3: [Specific performance goal]
1103
+
1104
+ ## User Stories
1105
+ ### Core Features
1106
+ 1. **Onboarding & Authentication**
1107
+ - As a new user, I want a simple onboarding process
1108
+ - As a user, I want to sign up with email or social media
1109
+ - As a user, I want biometric authentication for security
1110
+
1111
+ 2. **Main App Features**
1112
+ - As a user, I want [core feature 1] accessible from home screen
1113
+ - As a user, I want [core feature 2] to work offline
1114
+ - As a user, I want to sync data across devices
1115
+
1116
+ 3. **User Experience**
1117
+ - As a user, I want intuitive navigation patterns
1118
+ - As a user, I want fast loading times
1119
+ - As a user, I want accessibility features
1120
+
1121
+ ## Technical Requirements
1122
+ ### Mobile Development
1123
+ - **Cross-platform:** React Native / Flutter / Xamarin
1124
+ - **Native:** Swift (iOS) / Kotlin (Android)
1125
+ - **State Management:** Redux / MobX / Provider
1126
+ - **Navigation:** React Navigation / Flutter Navigation
1127
+
1128
+ ### Backend Integration
1129
+ - REST API or GraphQL integration
1130
+ - Real-time features (WebSockets/Push notifications)
1131
+ - Offline data synchronization
1132
+ - Background processing
1133
+
1134
+ ### Device Features
1135
+ - Camera and photo library access
1136
+ - GPS location services
1137
+ - Push notifications
1138
+ - Biometric authentication
1139
+ - Device storage
1140
+
1141
+ ### Performance Requirements
1142
+ - App launch time < 3 seconds
1143
+ - Screen transition animations < 300ms
1144
+ - Memory usage optimization
1145
+ - Battery usage optimization
1146
+
1147
+ ## Platform-Specific Considerations
1148
+ ### iOS Requirements
1149
+ - iOS 13.0+ minimum version
1150
+ - App Store guidelines compliance
1151
+ - iOS design guidelines (Human Interface Guidelines)
1152
+ - TestFlight beta testing
1153
+
1154
+ ### Android Requirements
1155
+ - Android 8.0+ (API level 26) minimum
1156
+ - Google Play Store guidelines
1157
+ - Material Design guidelines
1158
+ - Google Play Console testing
1159
+
1160
+ ## User Interface Design
1161
+ - Responsive design for different screen sizes
1162
+ - Dark mode support
1163
+ - Accessibility compliance (WCAG 2.1)
1164
+ - Consistent design system
1165
+
1166
+ ## Security & Privacy
1167
+ - Secure data storage (Keychain/Keystore)
1168
+ - API communication encryption
1169
+ - Privacy policy compliance (GDPR/CCPA)
1170
+ - App security best practices
1171
+
1172
+ ## Testing Strategy
1173
+ - Unit testing (80%+ coverage)
1174
+ - UI/E2E testing (Detox/Appium)
1175
+ - Device testing on multiple screen sizes
1176
+ - Performance testing
1177
+ - Security testing
1178
+
1179
+ ## App Store Deployment
1180
+ - App store optimization (ASO)
1181
+ - App icons and screenshots
1182
+ - Store listing content
1183
+ - Release management strategy
1184
+
1185
+ ## Analytics & Monitoring
1186
+ - User analytics (Firebase/Analytics)
1187
+ - Crash reporting (Crashlytics/Sentry)
1188
+ - Performance monitoring
1189
+ - User feedback collection
1190
+
1191
+ ## Success Metrics
1192
+ - App store ratings > 4.0
1193
+ - User retention rates
1194
+ - Daily/Monthly active users
1195
+ - App performance metrics
1196
+ - Conversion rates`
1197
+ },
1198
+ {
1199
+ id: 'data-analysis',
1200
+ name: 'Data Analysis Project',
1201
+ description: 'Template for data analysis and visualization projects',
1202
+ category: 'data',
1203
+ content: `# Product Requirements Document - Data Analysis Project
1204
+
1205
+ ## Overview
1206
+ **Project Name:** [Your Analysis Project]
1207
+ **Analysis Type:** [Descriptive/Predictive/Prescriptive]
1208
+ **Date:** ${new Date().toISOString().split('T')[0]}
1209
+ **Author:** [Your Name]
1210
+
1211
+ ## Executive Summary
1212
+ Description of the business problem, data sources, and expected insights.
1213
+
1214
+ ## Project Goals
1215
+ - Goal 1: [Specific business question to answer]
1216
+ - Goal 2: [Specific prediction to make]
1217
+ - Goal 3: [Specific recommendation to provide]
1218
+
1219
+ ## Business Requirements
1220
+ ### Key Questions
1221
+ 1. What patterns exist in the current data?
1222
+ 2. What factors influence [target variable]?
1223
+ 3. What predictions can be made for [future outcome]?
1224
+ 4. What recommendations can improve [business metric]?
1225
+
1226
+ ### Success Criteria
1227
+ - Actionable insights for stakeholders
1228
+ - Statistical significance in findings
1229
+ - Reproducible analysis pipeline
1230
+ - Clear visualization and reporting
1231
+
1232
+ ## Data Requirements
1233
+ ### Data Sources
1234
+ 1. **Primary Data**
1235
+ - Source: [Database/API/Files]
1236
+ - Format: [CSV/JSON/SQL]
1237
+ - Size: [Volume estimate]
1238
+ - Update frequency: [Real-time/Daily/Monthly]
1239
+
1240
+ 2. **External Data**
1241
+ - Third-party APIs
1242
+ - Public datasets
1243
+ - Market research data
1244
+
1245
+ ### Data Quality Requirements
1246
+ - Data completeness (< 5% missing values)
1247
+ - Data accuracy validation
1248
+ - Data consistency checks
1249
+ - Historical data availability
1250
+
1251
+ ## Technical Requirements
1252
+ ### Data Pipeline
1253
+ - Data extraction and ingestion
1254
+ - Data cleaning and preprocessing
1255
+ - Data transformation and feature engineering
1256
+ - Data validation and quality checks
1257
+
1258
+ ### Analysis Tools
1259
+ - **Programming:** Python/R/SQL
1260
+ - **Libraries:** pandas, numpy, scikit-learn, matplotlib
1261
+ - **Visualization:** Tableau, PowerBI, or custom dashboards
1262
+ - **Version Control:** Git for code and DVC for data
1263
+
1264
+ ### Computing Resources
1265
+ - Local development environment
1266
+ - Cloud computing (AWS/GCP/Azure) if needed
1267
+ - Database access and permissions
1268
+ - Storage requirements
1269
+
1270
+ ## Analysis Methodology
1271
+ ### Data Exploration
1272
+ 1. Descriptive statistics and data profiling
1273
+ 2. Data visualization and pattern identification
1274
+ 3. Correlation analysis
1275
+ 4. Outlier detection and handling
1276
+
1277
+ ### Statistical Analysis
1278
+ 1. Hypothesis formulation
1279
+ 2. Statistical testing
1280
+ 3. Confidence intervals
1281
+ 4. Effect size calculations
1282
+
1283
+ ### Machine Learning (if applicable)
1284
+ 1. Feature selection and engineering
1285
+ 2. Model selection and training
1286
+ 3. Cross-validation and evaluation
1287
+ 4. Model interpretation and explainability
1288
+
1289
+ ## Deliverables
1290
+ ### Reports
1291
+ - Executive summary for stakeholders
1292
+ - Technical analysis report
1293
+ - Data quality report
1294
+ - Methodology documentation
1295
+
1296
+ ### Visualizations
1297
+ - Interactive dashboards
1298
+ - Static charts and graphs
1299
+ - Data story presentations
1300
+ - Key findings infographics
1301
+
1302
+ ### Code & Documentation
1303
+ - Reproducible analysis scripts
1304
+ - Data pipeline code
1305
+ - Documentation and comments
1306
+ - Testing and validation code
1307
+
1308
+ ## Timeline
1309
+ - Phase 1: Data collection and exploration (2 weeks)
1310
+ - Phase 2: Analysis and modeling (3 weeks)
1311
+ - Phase 3: Reporting and visualization (1 week)
1312
+ - Phase 4: Stakeholder presentation (1 week)
1313
+
1314
+ ## Risks & Assumptions
1315
+ - Data availability and quality risks
1316
+ - Technical complexity assumptions
1317
+ - Resource and timeline constraints
1318
+ - Stakeholder engagement assumptions
1319
+
1320
+ ## Success Metrics
1321
+ - Stakeholder satisfaction with insights
1322
+ - Accuracy of predictions (if applicable)
1323
+ - Business impact of recommendations
1324
+ - Reproducibility of results`
1325
+ }
1326
+ ];
1327
+
1328
+ res.json({
1329
+ templates,
1330
+ timestamp: new Date().toISOString()
1331
+ });
1332
+
1333
+ } catch (error) {
1334
+ console.error('PRD templates error:', error);
1335
+ res.status(500).json({
1336
+ error: 'Failed to get PRD templates',
1337
+ message: error.message
1338
+ });
1339
+ }
1340
+ });
1341
+
1342
+ /**
1343
+ * POST /api/taskmaster/apply-template/:projectId
1344
+ * Apply a PRD template to create a new PRD file
1345
+ */
1346
+ router.post('/apply-template/:projectId', async (req, res) => {
1347
+ try {
1348
+ const { projectId } = req.params;
1349
+ const { templateId, fileName = 'prd.txt', customizations = {} } = req.body;
1350
+
1351
+ if (!templateId) {
1352
+ return res.status(400).json({
1353
+ error: 'Missing required parameter',
1354
+ message: 'templateId is required'
1355
+ });
1356
+ }
1357
+
1358
+ const projectPath = await resolveProjectPathFromId(req.user.id, projectId);
1359
+ if (!projectPath) {
1360
+ return res.status(404).json({
1361
+ error: 'Project not found',
1362
+ message: `Project "${projectId}" does not exist`
1363
+ });
1364
+ }
1365
+
1366
+ // Get the template content (this would normally fetch from the templates list)
1367
+ const templates = await getAvailableTemplates();
1368
+ const template = templates.find(t => t.id === templateId);
1369
+
1370
+ if (!template) {
1371
+ return res.status(404).json({
1372
+ error: 'Template not found',
1373
+ message: `Template "${templateId}" does not exist`
1374
+ });
1375
+ }
1376
+
1377
+ // Apply customizations to template content
1378
+ let content = template.content;
1379
+
1380
+ // Replace placeholders with customizations
1381
+ for (const [key, value] of Object.entries(customizations)) {
1382
+ const placeholder = `[${key}]`;
1383
+ content = content.replace(new RegExp(placeholder.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'g'), value);
1384
+ }
1385
+
1386
+ // Ensure .taskmaster/docs directory exists
1387
+ const docsDir = path.join(projectPath, '.taskmaster', 'docs');
1388
+ try {
1389
+ await fsPromises.mkdir(docsDir, { recursive: true });
1390
+ } catch (error) {
1391
+ console.error('Failed to create docs directory:', error);
1392
+ }
1393
+
1394
+ const filePath = path.join(docsDir, fileName);
1395
+
1396
+ // Write the template content to the file
1397
+ try {
1398
+ await fsPromises.writeFile(filePath, content, 'utf8');
1399
+
1400
+ res.json({
1401
+ projectId,
1402
+ projectPath,
1403
+ templateId,
1404
+ templateName: template.name,
1405
+ fileName,
1406
+ filePath: filePath,
1407
+ message: 'PRD template applied successfully',
1408
+ timestamp: new Date().toISOString()
1409
+ });
1410
+
1411
+ } catch (writeError) {
1412
+ console.error('Failed to write PRD template:', writeError);
1413
+ return res.status(500).json({
1414
+ error: 'Failed to write PRD template',
1415
+ message: writeError.message
1416
+ });
1417
+ }
1418
+
1419
+ } catch (error) {
1420
+ console.error('Apply template error:', error);
1421
+ res.status(500).json({
1422
+ error: 'Failed to apply PRD template',
1423
+ message: error.message
1424
+ });
1425
+ }
1426
+ });
1427
+
1428
+ // Helper function to get available templates
1429
+ async function getAvailableTemplates() {
1430
+ // This could be extended to read from files or database
1431
+ return [
1432
+ {
1433
+ id: 'web-app',
1434
+ name: 'Web Application',
1435
+ description: 'Template for web application projects',
1436
+ category: 'web',
1437
+ content: `# Product Requirements Document - Web Application
1438
+
1439
+ ## Overview
1440
+ **Product Name:** [Your App Name]
1441
+ **Version:** 1.0
1442
+ **Date:** ${new Date().toISOString().split('T')[0]}
1443
+ **Author:** [Your Name]
1444
+
1445
+ ## Executive Summary
1446
+ Brief description of what this web application will do and why it's needed.
1447
+
1448
+ ## User Stories
1449
+ 1. As a user, I want [feature] so I can [benefit]
1450
+ 2. As a user, I want [feature] so I can [benefit]
1451
+ 3. As a user, I want [feature] so I can [benefit]
1452
+
1453
+ ## Technical Requirements
1454
+ - Frontend framework
1455
+ - Backend services
1456
+ - Database requirements
1457
+ - Security considerations
1458
+
1459
+ ## Success Metrics
1460
+ - User engagement metrics
1461
+ - Performance benchmarks
1462
+ - Business objectives`
1463
+ },
1464
+ // Add other templates here if needed
1465
+ ];
1466
+ }
1467
+
1468
+ export default router;