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