task-o-matic-core 0.1.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 (447) hide show
  1. package/README.md +646 -0
  2. package/dist/index.d.ts +27 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +46 -0
  5. package/dist/lib/ai-service/ai-operations.d.ts +45 -0
  6. package/dist/lib/ai-service/ai-operations.d.ts.map +1 -0
  7. package/dist/lib/ai-service/ai-operations.js +60 -0
  8. package/dist/lib/ai-service/base-operations.d.ts +43 -0
  9. package/dist/lib/ai-service/base-operations.d.ts.map +1 -0
  10. package/dist/lib/ai-service/base-operations.js +119 -0
  11. package/dist/lib/ai-service/documentation-operations.d.ts +18 -0
  12. package/dist/lib/ai-service/documentation-operations.d.ts.map +1 -0
  13. package/dist/lib/ai-service/documentation-operations.js +308 -0
  14. package/dist/lib/ai-service/filesystem-tools.d.ts +69 -0
  15. package/dist/lib/ai-service/filesystem-tools.d.ts.map +1 -0
  16. package/dist/lib/ai-service/filesystem-tools.js +70 -0
  17. package/dist/lib/ai-service/json-parser.d.ts +34 -0
  18. package/dist/lib/ai-service/json-parser.d.ts.map +1 -0
  19. package/dist/lib/ai-service/json-parser.js +177 -0
  20. package/dist/lib/ai-service/mcp-client.d.ts +9 -0
  21. package/dist/lib/ai-service/mcp-client.d.ts.map +1 -0
  22. package/dist/lib/ai-service/mcp-client.js +48 -0
  23. package/dist/lib/ai-service/model-provider.d.ts +12 -0
  24. package/dist/lib/ai-service/model-provider.d.ts.map +1 -0
  25. package/dist/lib/ai-service/model-provider.js +146 -0
  26. package/dist/lib/ai-service/prd-operations.d.ts +25 -0
  27. package/dist/lib/ai-service/prd-operations.d.ts.map +1 -0
  28. package/dist/lib/ai-service/prd-operations.js +592 -0
  29. package/dist/lib/ai-service/research-tools.d.ts +4 -0
  30. package/dist/lib/ai-service/research-tools.d.ts.map +1 -0
  31. package/dist/lib/ai-service/research-tools.js +8 -0
  32. package/dist/lib/ai-service/retry-handler.d.ts +8 -0
  33. package/dist/lib/ai-service/retry-handler.d.ts.map +1 -0
  34. package/dist/lib/ai-service/retry-handler.js +63 -0
  35. package/dist/lib/ai-service/task-operations.d.ts +13 -0
  36. package/dist/lib/ai-service/task-operations.d.ts.map +1 -0
  37. package/dist/lib/ai-service/task-operations.js +220 -0
  38. package/dist/lib/benchmark/registry.d.ts +11 -0
  39. package/dist/lib/benchmark/registry.d.ts.map +1 -0
  40. package/dist/lib/benchmark/registry.js +212 -0
  41. package/dist/lib/benchmark/runner.d.ts +6 -0
  42. package/dist/lib/benchmark/runner.d.ts.map +1 -0
  43. package/dist/lib/benchmark/runner.js +150 -0
  44. package/dist/lib/benchmark/storage.d.ts +13 -0
  45. package/dist/lib/benchmark/storage.d.ts.map +1 -0
  46. package/dist/lib/benchmark/storage.js +100 -0
  47. package/dist/lib/benchmark/types.d.ts +104 -0
  48. package/dist/lib/benchmark/types.d.ts.map +1 -0
  49. package/dist/lib/benchmark/types.js +2 -0
  50. package/dist/lib/better-t-stack-cli.d.ts +50 -0
  51. package/dist/lib/better-t-stack-cli.d.ts.map +1 -0
  52. package/dist/lib/better-t-stack-cli.js +428 -0
  53. package/dist/lib/bootstrap/cli-bootstrap.d.ts +14 -0
  54. package/dist/lib/bootstrap/cli-bootstrap.d.ts.map +1 -0
  55. package/dist/lib/bootstrap/cli-bootstrap.js +322 -0
  56. package/dist/lib/bootstrap/index.d.ts +3 -0
  57. package/dist/lib/bootstrap/index.d.ts.map +1 -0
  58. package/dist/lib/bootstrap/index.js +18 -0
  59. package/dist/lib/bootstrap/medusa-bootstrap.d.ts +14 -0
  60. package/dist/lib/bootstrap/medusa-bootstrap.d.ts.map +1 -0
  61. package/dist/lib/bootstrap/medusa-bootstrap.js +215 -0
  62. package/dist/lib/config-validation.d.ts +215 -0
  63. package/dist/lib/config-validation.d.ts.map +1 -0
  64. package/dist/lib/config-validation.js +254 -0
  65. package/dist/lib/config.d.ts +55 -0
  66. package/dist/lib/config.d.ts.map +1 -0
  67. package/dist/lib/config.js +351 -0
  68. package/dist/lib/context-builder.d.ts +66 -0
  69. package/dist/lib/context-builder.d.ts.map +1 -0
  70. package/dist/lib/context-builder.js +322 -0
  71. package/dist/lib/executors/claude-code-executor.d.ts +9 -0
  72. package/dist/lib/executors/claude-code-executor.d.ts.map +1 -0
  73. package/dist/lib/executors/claude-code-executor.js +69 -0
  74. package/dist/lib/executors/codex-executor.d.ts +9 -0
  75. package/dist/lib/executors/codex-executor.d.ts.map +1 -0
  76. package/dist/lib/executors/codex-executor.js +73 -0
  77. package/dist/lib/executors/executor-factory.d.ts +5 -0
  78. package/dist/lib/executors/executor-factory.d.ts.map +1 -0
  79. package/dist/lib/executors/executor-factory.js +27 -0
  80. package/dist/lib/executors/gemini-executor.d.ts +9 -0
  81. package/dist/lib/executors/gemini-executor.d.ts.map +1 -0
  82. package/dist/lib/executors/gemini-executor.js +67 -0
  83. package/dist/lib/executors/kilo-executor.d.ts +9 -0
  84. package/dist/lib/executors/kilo-executor.d.ts.map +1 -0
  85. package/dist/lib/executors/kilo-executor.js +69 -0
  86. package/dist/lib/executors/opencode-executor.d.ts +9 -0
  87. package/dist/lib/executors/opencode-executor.d.ts.map +1 -0
  88. package/dist/lib/executors/opencode-executor.js +67 -0
  89. package/dist/lib/git-utils.d.ts +88 -0
  90. package/dist/lib/git-utils.d.ts.map +1 -0
  91. package/dist/lib/git-utils.js +242 -0
  92. package/dist/lib/hooks.d.ts +73 -0
  93. package/dist/lib/hooks.d.ts.map +1 -0
  94. package/dist/lib/hooks.js +62 -0
  95. package/dist/lib/index.d.ts +100 -0
  96. package/dist/lib/index.d.ts.map +1 -0
  97. package/dist/lib/index.js +143 -0
  98. package/dist/lib/logger.d.ts +20 -0
  99. package/dist/lib/logger.d.ts.map +1 -0
  100. package/dist/lib/logger.js +32 -0
  101. package/dist/lib/notifications.d.ts +7 -0
  102. package/dist/lib/notifications.d.ts.map +1 -0
  103. package/dist/lib/notifications.js +81 -0
  104. package/dist/lib/prompt-builder.d.ts +70 -0
  105. package/dist/lib/prompt-builder.d.ts.map +1 -0
  106. package/dist/lib/prompt-builder.js +344 -0
  107. package/dist/lib/prompt-registry.d.ts +22 -0
  108. package/dist/lib/prompt-registry.d.ts.map +1 -0
  109. package/dist/lib/prompt-registry.js +409 -0
  110. package/dist/lib/provider-defaults.json +32 -0
  111. package/dist/lib/storage/file-system.d.ts +57 -0
  112. package/dist/lib/storage/file-system.d.ts.map +1 -0
  113. package/dist/lib/storage/file-system.js +638 -0
  114. package/dist/lib/storage/storage-callbacks.d.ts +17 -0
  115. package/dist/lib/storage/storage-callbacks.d.ts.map +1 -0
  116. package/dist/lib/storage/storage-callbacks.js +94 -0
  117. package/dist/lib/storage/types.d.ts +43 -0
  118. package/dist/lib/storage/types.d.ts.map +1 -0
  119. package/dist/lib/storage/types.js +2 -0
  120. package/dist/lib/task-execution-core.d.ts +7 -0
  121. package/dist/lib/task-execution-core.d.ts.map +1 -0
  122. package/dist/lib/task-execution-core.js +381 -0
  123. package/dist/lib/task-execution.d.ts +7 -0
  124. package/dist/lib/task-execution.d.ts.map +1 -0
  125. package/dist/lib/task-execution.js +40 -0
  126. package/dist/lib/task-loop-execution.d.ts +7 -0
  127. package/dist/lib/task-loop-execution.d.ts.map +1 -0
  128. package/dist/lib/task-loop-execution.js +156 -0
  129. package/dist/lib/task-planning.d.ts +29 -0
  130. package/dist/lib/task-planning.d.ts.map +1 -0
  131. package/dist/lib/task-planning.js +103 -0
  132. package/dist/lib/task-review.d.ts +27 -0
  133. package/dist/lib/task-review.d.ts.map +1 -0
  134. package/dist/lib/task-review.js +103 -0
  135. package/dist/lib/validation.d.ts +26 -0
  136. package/dist/lib/validation.d.ts.map +1 -0
  137. package/dist/lib/validation.js +98 -0
  138. package/dist/prompts/documentation-detection.d.ts +2 -0
  139. package/dist/prompts/documentation-detection.d.ts.map +1 -0
  140. package/dist/prompts/documentation-detection.js +24 -0
  141. package/dist/prompts/documentation-recap.d.ts +3 -0
  142. package/dist/prompts/documentation-recap.d.ts.map +1 -0
  143. package/dist/prompts/documentation-recap.js +13 -0
  144. package/dist/prompts/index.d.ts +15 -0
  145. package/dist/prompts/index.d.ts.map +1 -0
  146. package/dist/prompts/index.js +30 -0
  147. package/dist/prompts/prd-combination.d.ts +2 -0
  148. package/dist/prompts/prd-combination.d.ts.map +1 -0
  149. package/dist/prompts/prd-combination.js +35 -0
  150. package/dist/prompts/prd-generation.d.ts +2 -0
  151. package/dist/prompts/prd-generation.d.ts.map +1 -0
  152. package/dist/prompts/prd-generation.js +49 -0
  153. package/dist/prompts/prd-parsing.d.ts +3 -0
  154. package/dist/prompts/prd-parsing.d.ts.map +1 -0
  155. package/dist/prompts/prd-parsing.js +172 -0
  156. package/dist/prompts/prd-question-answer.d.ts +3 -0
  157. package/dist/prompts/prd-question-answer.d.ts.map +1 -0
  158. package/dist/prompts/prd-question-answer.js +27 -0
  159. package/dist/prompts/prd-question.d.ts +3 -0
  160. package/dist/prompts/prd-question.d.ts.map +1 -0
  161. package/dist/prompts/prd-question.js +40 -0
  162. package/dist/prompts/prd-rework.d.ts +3 -0
  163. package/dist/prompts/prd-rework.d.ts.map +1 -0
  164. package/dist/prompts/prd-rework.js +81 -0
  165. package/dist/prompts/prd-suggest-stack.d.ts +3 -0
  166. package/dist/prompts/prd-suggest-stack.d.ts.map +1 -0
  167. package/dist/prompts/prd-suggest-stack.js +99 -0
  168. package/dist/prompts/task-breakdown.d.ts +3 -0
  169. package/dist/prompts/task-breakdown.d.ts.map +1 -0
  170. package/dist/prompts/task-breakdown.js +151 -0
  171. package/dist/prompts/task-enhancement.d.ts +3 -0
  172. package/dist/prompts/task-enhancement.d.ts.map +1 -0
  173. package/dist/prompts/task-enhancement.js +140 -0
  174. package/dist/prompts/task-execution.d.ts +3 -0
  175. package/dist/prompts/task-execution.d.ts.map +1 -0
  176. package/dist/prompts/task-execution.js +24 -0
  177. package/dist/prompts/task-planning.d.ts +3 -0
  178. package/dist/prompts/task-planning.d.ts.map +1 -0
  179. package/dist/prompts/task-planning.js +66 -0
  180. package/dist/prompts/workflow-assistance.d.ts +32 -0
  181. package/dist/prompts/workflow-assistance.d.ts.map +1 -0
  182. package/dist/prompts/workflow-assistance.js +130 -0
  183. package/dist/prompts/workflow-prompts.d.ts +9 -0
  184. package/dist/prompts/workflow-prompts.d.ts.map +1 -0
  185. package/dist/prompts/workflow-prompts.js +93 -0
  186. package/dist/services/benchmark.d.ts +26 -0
  187. package/dist/services/benchmark.d.ts.map +1 -0
  188. package/dist/services/benchmark.js +343 -0
  189. package/dist/services/prd.d.ts +136 -0
  190. package/dist/services/prd.d.ts.map +1 -0
  191. package/dist/services/prd.js +550 -0
  192. package/dist/services/tasks.d.ts +388 -0
  193. package/dist/services/tasks.d.ts.map +1 -0
  194. package/dist/services/tasks.js +1150 -0
  195. package/dist/services/workflow-ai-assistant.d.ts +74 -0
  196. package/dist/services/workflow-ai-assistant.d.ts.map +1 -0
  197. package/dist/services/workflow-ai-assistant.js +175 -0
  198. package/dist/services/workflow-benchmark.d.ts +34 -0
  199. package/dist/services/workflow-benchmark.d.ts.map +1 -0
  200. package/dist/services/workflow-benchmark.js +318 -0
  201. package/dist/services/workflow.d.ts +107 -0
  202. package/dist/services/workflow.d.ts.map +1 -0
  203. package/dist/services/workflow.js +580 -0
  204. package/dist/test/hooks.test.d.ts +2 -0
  205. package/dist/test/hooks.test.d.ts.map +1 -0
  206. package/dist/test/hooks.test.js +67 -0
  207. package/dist/test/integration/callbacks.test.d.ts +2 -0
  208. package/dist/test/integration/callbacks.test.d.ts.map +1 -0
  209. package/dist/test/integration/callbacks.test.js +64 -0
  210. package/dist/test/lib/ai-service/task-operations.test.d.ts +2 -0
  211. package/dist/test/lib/ai-service/task-operations.test.d.ts.map +1 -0
  212. package/dist/test/lib/ai-service/task-operations.test.js +362 -0
  213. package/dist/test/lib/config.test.d.ts +2 -0
  214. package/dist/test/lib/config.test.d.ts.map +1 -0
  215. package/dist/test/lib/config.test.js +128 -0
  216. package/dist/test/lib/git-utils.test.d.ts +2 -0
  217. package/dist/test/lib/git-utils.test.d.ts.map +1 -0
  218. package/dist/test/lib/git-utils.test.js +168 -0
  219. package/dist/test/mocks/mock-ai-operations.d.ts +15 -0
  220. package/dist/test/mocks/mock-ai-operations.d.ts.map +1 -0
  221. package/dist/test/mocks/mock-ai-operations.js +107 -0
  222. package/dist/test/mocks/mock-context-builder.d.ts +10 -0
  223. package/dist/test/mocks/mock-context-builder.d.ts.map +1 -0
  224. package/dist/test/mocks/mock-context-builder.js +81 -0
  225. package/dist/test/mocks/mock-model-provider.d.ts +7 -0
  226. package/dist/test/mocks/mock-model-provider.d.ts.map +1 -0
  227. package/dist/test/mocks/mock-model-provider.js +21 -0
  228. package/dist/test/mocks/mock-service-factory.d.ts +11 -0
  229. package/dist/test/mocks/mock-service-factory.d.ts.map +1 -0
  230. package/dist/test/mocks/mock-service-factory.js +61 -0
  231. package/dist/test/mocks/mock-storage.d.ts +50 -0
  232. package/dist/test/mocks/mock-storage.d.ts.map +1 -0
  233. package/dist/test/mocks/mock-storage.js +145 -0
  234. package/dist/test/model-parsing.test.d.ts +2 -0
  235. package/dist/test/model-parsing.test.d.ts.map +1 -0
  236. package/dist/test/model-parsing.test.js +73 -0
  237. package/dist/test/services/task-service.test.d.ts +2 -0
  238. package/dist/test/services/task-service.test.d.ts.map +1 -0
  239. package/dist/test/services/task-service.test.js +459 -0
  240. package/dist/test/storage.test.d.ts +2 -0
  241. package/dist/test/storage.test.d.ts.map +1 -0
  242. package/dist/test/storage.test.js +207 -0
  243. package/dist/test/task-loop-git.test.d.ts +2 -0
  244. package/dist/test/task-loop-git.test.d.ts.map +1 -0
  245. package/dist/test/task-loop-git.test.js +95 -0
  246. package/dist/test/test-mock-setup.d.ts +26 -0
  247. package/dist/test/test-mock-setup.d.ts.map +1 -0
  248. package/dist/test/test-mock-setup.js +41 -0
  249. package/dist/test/test-setup.d.ts +9 -0
  250. package/dist/test/test-setup.d.ts.map +1 -0
  251. package/dist/test/test-setup.js +44 -0
  252. package/dist/test/test-utils.d.ts +22 -0
  253. package/dist/test/test-utils.d.ts.map +1 -0
  254. package/dist/test/test-utils.js +37 -0
  255. package/dist/test/utils/ai-operation-utility.test.d.ts +2 -0
  256. package/dist/test/utils/ai-operation-utility.test.d.ts.map +1 -0
  257. package/dist/test/utils/ai-operation-utility.test.js +290 -0
  258. package/dist/test/utils/error-handling.test.d.ts +2 -0
  259. package/dist/test/utils/error-handling.test.d.ts.map +1 -0
  260. package/dist/test/utils/error-handling.test.js +231 -0
  261. package/dist/test/utils/file-utils.test.d.ts +2 -0
  262. package/dist/test/utils/file-utils.test.d.ts.map +1 -0
  263. package/dist/test/utils/file-utils.test.js +76 -0
  264. package/dist/test/utils/id-generator.test.d.ts +2 -0
  265. package/dist/test/utils/id-generator.test.d.ts.map +1 -0
  266. package/dist/test/utils/id-generator.test.js +41 -0
  267. package/dist/test/utils/model-parser.test.d.ts +2 -0
  268. package/dist/test/utils/model-parser.test.d.ts.map +1 -0
  269. package/dist/test/utils/model-parser.test.js +65 -0
  270. package/dist/test/validation.test.d.ts +2 -0
  271. package/dist/test/validation.test.d.ts.map +1 -0
  272. package/dist/test/validation.test.js +22 -0
  273. package/dist/types/callbacks.d.ts +30 -0
  274. package/dist/types/callbacks.d.ts.map +1 -0
  275. package/dist/types/callbacks.js +2 -0
  276. package/dist/types/index.d.ts +435 -0
  277. package/dist/types/index.d.ts.map +1 -0
  278. package/dist/types/index.js +30 -0
  279. package/dist/types/mcp.d.ts +3 -0
  280. package/dist/types/mcp.d.ts.map +1 -0
  281. package/dist/types/mcp.js +3 -0
  282. package/dist/types/options.d.ts +112 -0
  283. package/dist/types/options.d.ts.map +1 -0
  284. package/dist/types/options.js +2 -0
  285. package/dist/types/results.d.ts +200 -0
  286. package/dist/types/results.d.ts.map +1 -0
  287. package/dist/types/results.js +2 -0
  288. package/dist/types/workflow-options.d.ts +82 -0
  289. package/dist/types/workflow-options.d.ts.map +1 -0
  290. package/dist/types/workflow-options.js +2 -0
  291. package/dist/types/workflow-results.d.ts +82 -0
  292. package/dist/types/workflow-results.d.ts.map +1 -0
  293. package/dist/types/workflow-results.js +2 -0
  294. package/dist/utils/ai-config-builder.d.ts +14 -0
  295. package/dist/utils/ai-config-builder.d.ts.map +1 -0
  296. package/dist/utils/ai-config-builder.js +22 -0
  297. package/dist/utils/ai-operation-utility.d.ts +142 -0
  298. package/dist/utils/ai-operation-utility.d.ts.map +1 -0
  299. package/dist/utils/ai-operation-utility.js +303 -0
  300. package/dist/utils/ai-service-factory.d.ts +34 -0
  301. package/dist/utils/ai-service-factory.d.ts.map +1 -0
  302. package/dist/utils/ai-service-factory.js +99 -0
  303. package/dist/utils/error-utils.d.ts +70 -0
  304. package/dist/utils/error-utils.d.ts.map +1 -0
  305. package/dist/utils/error-utils.js +104 -0
  306. package/dist/utils/file-utils.d.ts +107 -0
  307. package/dist/utils/file-utils.d.ts.map +1 -0
  308. package/dist/utils/file-utils.js +171 -0
  309. package/dist/utils/id-generator.d.ts +92 -0
  310. package/dist/utils/id-generator.d.ts.map +1 -0
  311. package/dist/utils/id-generator.js +146 -0
  312. package/dist/utils/metadata-utils.d.ts +40 -0
  313. package/dist/utils/metadata-utils.d.ts.map +1 -0
  314. package/dist/utils/metadata-utils.js +43 -0
  315. package/dist/utils/model-executor-parser.d.ts +38 -0
  316. package/dist/utils/model-executor-parser.d.ts.map +1 -0
  317. package/dist/utils/model-executor-parser.js +69 -0
  318. package/dist/utils/model-parser.d.ts +6 -0
  319. package/dist/utils/model-parser.d.ts.map +1 -0
  320. package/dist/utils/model-parser.js +49 -0
  321. package/dist/utils/stack-formatter.d.ts +12 -0
  322. package/dist/utils/stack-formatter.d.ts.map +1 -0
  323. package/dist/utils/stack-formatter.js +36 -0
  324. package/dist/utils/storage-utils.d.ts +49 -0
  325. package/dist/utils/storage-utils.d.ts.map +1 -0
  326. package/dist/utils/storage-utils.js +80 -0
  327. package/dist/utils/streaming-utils.d.ts +38 -0
  328. package/dist/utils/streaming-utils.d.ts.map +1 -0
  329. package/dist/utils/streaming-utils.js +64 -0
  330. package/dist/utils/task-o-matic-error.d.ts +206 -0
  331. package/dist/utils/task-o-matic-error.d.ts.map +1 -0
  332. package/dist/utils/task-o-matic-error.js +304 -0
  333. package/package.json +40 -0
  334. package/src/index.ts +36 -0
  335. package/src/lib/ai-service/ai-operations.ts +310 -0
  336. package/src/lib/ai-service/base-operations.ts +139 -0
  337. package/src/lib/ai-service/documentation-operations.ts +438 -0
  338. package/src/lib/ai-service/filesystem-tools.ts +73 -0
  339. package/src/lib/ai-service/gemini-proxy.ts.bak +52 -0
  340. package/src/lib/ai-service/json-parser.ts +203 -0
  341. package/src/lib/ai-service/mcp-client.ts +54 -0
  342. package/src/lib/ai-service/model-provider.ts +192 -0
  343. package/src/lib/ai-service/prd-operations.ts +854 -0
  344. package/src/lib/ai-service/research-tools.ts +207 -0
  345. package/src/lib/ai-service/retry-handler.ts +89 -0
  346. package/src/lib/ai-service/task-operations.ts +342 -0
  347. package/src/lib/benchmark/registry.ts +307 -0
  348. package/src/lib/benchmark/runner.ts +190 -0
  349. package/src/lib/benchmark/storage.ts +140 -0
  350. package/src/lib/benchmark/types.ts +121 -0
  351. package/src/lib/better-t-stack-cli.ts +524 -0
  352. package/src/lib/bootstrap/cli-bootstrap.ts +397 -0
  353. package/src/lib/bootstrap/index.ts +2 -0
  354. package/src/lib/bootstrap/medusa-bootstrap.ts +261 -0
  355. package/src/lib/config-validation.ts +278 -0
  356. package/src/lib/config.ts +435 -0
  357. package/src/lib/context-builder.ts +383 -0
  358. package/src/lib/executors/claude-code-executor.ts +83 -0
  359. package/src/lib/executors/codex-executor.ts +85 -0
  360. package/src/lib/executors/executor-factory.ts +28 -0
  361. package/src/lib/executors/gemini-executor.ts +80 -0
  362. package/src/lib/executors/kilo-executor.ts +83 -0
  363. package/src/lib/executors/opencode-executor.ts +81 -0
  364. package/src/lib/git-utils.ts +334 -0
  365. package/src/lib/hooks.ts +121 -0
  366. package/src/lib/index.ts +166 -0
  367. package/src/lib/logger.ts +43 -0
  368. package/src/lib/notifications.ts +103 -0
  369. package/src/lib/prompt-builder.ts +471 -0
  370. package/src/lib/prompt-registry.ts +491 -0
  371. package/src/lib/provider-defaults.json +32 -0
  372. package/src/lib/storage/file-system.ts +864 -0
  373. package/src/lib/storage/storage-callbacks.ts +120 -0
  374. package/src/lib/storage/types.ts +58 -0
  375. package/src/lib/task-execution-core.ts +591 -0
  376. package/src/lib/task-execution.ts +59 -0
  377. package/src/lib/task-loop-execution.ts +214 -0
  378. package/src/lib/task-planning.ts +157 -0
  379. package/src/lib/task-review.ts +138 -0
  380. package/src/lib/validation.ts +140 -0
  381. package/src/prompts/documentation-detection.ts +21 -0
  382. package/src/prompts/documentation-recap.ts +11 -0
  383. package/src/prompts/index.ts +14 -0
  384. package/src/prompts/prd-combination.ts +32 -0
  385. package/src/prompts/prd-generation.ts +46 -0
  386. package/src/prompts/prd-parsing.ts +170 -0
  387. package/src/prompts/prd-question-answer.ts +25 -0
  388. package/src/prompts/prd-question.ts +38 -0
  389. package/src/prompts/prd-rework.ts +79 -0
  390. package/src/prompts/prd-suggest-stack.ts +97 -0
  391. package/src/prompts/task-breakdown.ts +149 -0
  392. package/src/prompts/task-enhancement.ts +138 -0
  393. package/src/prompts/task-execution.ts +22 -0
  394. package/src/prompts/task-planning.ts +64 -0
  395. package/src/prompts/workflow-assistance.ts +151 -0
  396. package/src/prompts/workflow-prompts.ts +97 -0
  397. package/src/services/benchmark.ts +433 -0
  398. package/src/services/prd.ts +845 -0
  399. package/src/services/tasks.ts +1515 -0
  400. package/src/services/workflow-ai-assistant.ts +298 -0
  401. package/src/services/workflow-benchmark.ts +339 -0
  402. package/src/services/workflow.ts +779 -0
  403. package/src/test/hooks.test.ts +77 -0
  404. package/src/test/integration/callbacks.test.ts +39 -0
  405. package/src/test/lib/ai-service/task-operations.test.ts +430 -0
  406. package/src/test/lib/config.test.ts +150 -0
  407. package/src/test/lib/git-utils.test.ts +198 -0
  408. package/src/test/mocks/mock-ai-operations.ts +205 -0
  409. package/src/test/mocks/mock-context-builder.ts +84 -0
  410. package/src/test/mocks/mock-model-provider.ts +21 -0
  411. package/src/test/mocks/mock-service-factory.ts +64 -0
  412. package/src/test/mocks/mock-storage.ts +204 -0
  413. package/src/test/model-parsing.test.ts +78 -0
  414. package/src/test/services/task-service.test.ts +551 -0
  415. package/src/test/storage.test.ts +206 -0
  416. package/src/test/task-loop-git.test.ts +142 -0
  417. package/src/test/test-mock-setup.ts +46 -0
  418. package/src/test/test-setup.ts +48 -0
  419. package/src/test/test-utils.ts +45 -0
  420. package/src/test/utils/ai-operation-utility.test.ts +306 -0
  421. package/src/test/utils/error-handling.test.ts +241 -0
  422. package/src/test/utils/file-utils.test.ts +80 -0
  423. package/src/test/utils/id-generator.test.ts +44 -0
  424. package/src/test/utils/model-parser.test.ts +67 -0
  425. package/src/test/validation.test.ts +19 -0
  426. package/src/types/callbacks.ts +14 -0
  427. package/src/types/index.ts +628 -0
  428. package/src/types/mcp.ts +5 -0
  429. package/src/types/options.ts +165 -0
  430. package/src/types/results.ts +216 -0
  431. package/src/types/workflow-options.ts +113 -0
  432. package/src/types/workflow-results.ts +87 -0
  433. package/src/utils/ai-config-builder.ts +33 -0
  434. package/src/utils/ai-operation-utility.ts +380 -0
  435. package/src/utils/ai-service-factory.ts +125 -0
  436. package/src/utils/error-utils.ts +124 -0
  437. package/src/utils/file-utils.ts +197 -0
  438. package/src/utils/id-generator.ts +168 -0
  439. package/src/utils/metadata-utils.ts +48 -0
  440. package/src/utils/model-executor-parser.ts +80 -0
  441. package/src/utils/model-parser.ts +58 -0
  442. package/src/utils/stack-formatter.ts +53 -0
  443. package/src/utils/storage-utils.ts +94 -0
  444. package/src/utils/streaming-utils.ts +91 -0
  445. package/src/utils/task-o-matic-error.ts +393 -0
  446. package/tsconfig.json +20 -0
  447. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,854 @@
1
+ import { streamText } from "ai";
2
+ import type { ToolSet } from "ai";
3
+ import {
4
+ AIConfig,
5
+ Task,
6
+ AIPRDParseResult,
7
+ StreamingOptions,
8
+ RetryConfig,
9
+ ParsedAITask,
10
+ PRDResponse,
11
+ PRDQuestionResponse,
12
+ BTSConfig,
13
+ } from "../../types";
14
+ import { StackSuggestionResponse } from "../../types/results";
15
+ import { PromptBuilder } from "../prompt-builder";
16
+ import {
17
+ PRD_PARSING_SYSTEM_PROMPT,
18
+ PRD_REWORK_SYSTEM_PROMPT,
19
+ PRD_GENERATION_SYSTEM_PROMPT,
20
+ PRD_COMBINATION_SYSTEM_PROMPT,
21
+ PRD_SUGGEST_STACK_SYSTEM_PROMPT,
22
+ } from "../../prompts";
23
+ import { JSONParser } from "./json-parser";
24
+ import { RetryHandler } from "./retry-handler";
25
+ import { ModelProvider } from "./model-provider";
26
+ import { filesystemTools } from "./filesystem-tools";
27
+ import { BaseOperations } from "./base-operations";
28
+ import {
29
+ createStandardError,
30
+ TaskOMaticErrorCodes,
31
+ } from "../../utils/task-o-matic-error";
32
+
33
+ export class PRDOperations extends BaseOperations {
34
+ async parsePRD(
35
+ prdContent: string,
36
+ config?: Partial<AIConfig>,
37
+ promptOverride?: string,
38
+ userMessage?: string,
39
+ streamingOptions?: StreamingOptions,
40
+ retryConfig?: Partial<RetryConfig>,
41
+ workingDirectory?: string,
42
+ enableFilesystemTools?: boolean
43
+ ): Promise<AIPRDParseResult> {
44
+ // console.log(
45
+ // `[Library Debug] parsePRD called. Config arg has key: ${!!config?.apiKey} Provider internal key: ${!!this.modelProvider.getAIConfig()
46
+ // ?.apiKey}`
47
+ // );
48
+ return this.retryHandler.executeWithRetry(
49
+ async () => {
50
+ let stackInfo = "";
51
+ try {
52
+ stackInfo = await PromptBuilder.detectStackInfo(workingDirectory);
53
+ if (stackInfo === "Not detected") {
54
+ stackInfo = "";
55
+ }
56
+ } catch (error) {
57
+ // Stack info not available
58
+ }
59
+
60
+ let enhancedPrompt: string;
61
+ if (promptOverride) {
62
+ enhancedPrompt = promptOverride;
63
+ } else {
64
+ const variables: Record<string, string> = {
65
+ PRD_CONTENT: prdContent,
66
+ };
67
+
68
+ if (stackInfo) {
69
+ variables.STACK_INFO = stackInfo;
70
+ }
71
+
72
+ const promptResult = PromptBuilder.buildPrompt({
73
+ name: "prd-parsing",
74
+ type: "user",
75
+ variables,
76
+ });
77
+
78
+ if (!promptResult.success) {
79
+ throw createStandardError(
80
+ TaskOMaticErrorCodes.PRD_PARSING_ERROR,
81
+ `Failed to build PRD parsing prompt: ${promptResult.error}`,
82
+ {
83
+ context: "Prompt building failed during PRD parsing",
84
+ suggestions: [
85
+ "Verify prompt template exists",
86
+ "Check variable substitution",
87
+ ],
88
+ }
89
+ );
90
+ }
91
+
92
+ enhancedPrompt = promptResult.prompt!;
93
+ }
94
+
95
+ let response: string;
96
+
97
+ if (enableFilesystemTools) {
98
+ const model = this.modelProvider.getModel({
99
+ ...this.modelProvider.getAIConfig(),
100
+ ...config,
101
+ });
102
+
103
+ const allTools = {
104
+ ...filesystemTools,
105
+ };
106
+
107
+ const result = await streamText({
108
+ model,
109
+ tools: allTools,
110
+ system:
111
+ PRD_PARSING_SYSTEM_PROMPT +
112
+ `
113
+
114
+ You have access to filesystem tools that allow you to:
115
+ - readFile: Read the contents of any file in the project
116
+ - listDirectory: List contents of directories
117
+
118
+ Use these tools to understand the project structure, existing code patterns, and dependencies when parsing the PRD and creating tasks.`,
119
+ messages: [
120
+ { role: "user", content: userMessage || enhancedPrompt },
121
+ ],
122
+ maxRetries: 0,
123
+ onChunk: streamingOptions?.onChunk
124
+ ? ({ chunk }) => {
125
+ if (chunk.type === "text-delta") {
126
+ streamingOptions.onChunk!(chunk.text);
127
+ } else if (chunk.type === "reasoning-delta") {
128
+ streamingOptions.onReasoning?.(chunk.text);
129
+ }
130
+ }
131
+ : undefined,
132
+ onFinish: streamingOptions?.onFinish
133
+ ? ({ text, finishReason, usage }) => {
134
+ streamingOptions.onFinish!({
135
+ text,
136
+ finishReason,
137
+ usage,
138
+ isAborted: false,
139
+ });
140
+ }
141
+ : undefined,
142
+ });
143
+
144
+ response = await result.text;
145
+ } else {
146
+ response = await this.streamText(
147
+ "",
148
+ config,
149
+ PRD_PARSING_SYSTEM_PROMPT,
150
+ userMessage || enhancedPrompt,
151
+ streamingOptions,
152
+ { maxAttempts: 1 }
153
+ );
154
+ }
155
+
156
+ // Define union type for the AI response
157
+ type AIParsedResponse = PRDResponse | ParsedAITask[];
158
+
159
+ const parseResult =
160
+ this.jsonParser.parseJSONFromResponse<AIParsedResponse>(response);
161
+ if (!parseResult.success) {
162
+ throw createStandardError(
163
+ TaskOMaticErrorCodes.PRD_PARSING_ERROR,
164
+ parseResult.error || "Failed to parse PRD response",
165
+ {
166
+ context: "AI response parsing failed during PRD parsing",
167
+ suggestions: [
168
+ "Check AI response format",
169
+ "Verify JSON structure",
170
+ ],
171
+ }
172
+ );
173
+ }
174
+
175
+ const parsed = parseResult.data;
176
+
177
+ // Handle both { tasks: [...] } and [...] (array) formats
178
+ let tasksList: ParsedAITask[] = [];
179
+ let summary = "PRD parsed successfully";
180
+ let estimatedDuration = "Unknown";
181
+ let confidence = 0.7;
182
+
183
+ if (Array.isArray(parsed)) {
184
+ tasksList = parsed;
185
+ } else if (parsed && typeof parsed === "object") {
186
+ tasksList = parsed.tasks || [];
187
+ summary = parsed.summary || summary;
188
+ estimatedDuration = parsed.estimatedDuration || estimatedDuration;
189
+ confidence = parsed.confidence || confidence;
190
+ }
191
+
192
+ const tasks: Task[] = tasksList.map(
193
+ (task: ParsedAITask, index: number) => {
194
+ const taskId = (task.id as string) || (index + 1).toString();
195
+
196
+ const {
197
+ title,
198
+ description,
199
+ content,
200
+ effort,
201
+ dependencies,
202
+ ...extraData
203
+ } = task;
204
+
205
+ let fullContent = "";
206
+ if (description || content) {
207
+ fullContent = description || content || "";
208
+ }
209
+
210
+ if (Object.keys(extraData).length > 0) {
211
+ fullContent += "\n\n## Additional AI-Generated Information\n";
212
+ for (const [key, value] of Object.entries(extraData)) {
213
+ fullContent += `\n**${key}:** ${JSON.stringify(
214
+ value,
215
+ null,
216
+ 2
217
+ )}`;
218
+ }
219
+ }
220
+
221
+ return {
222
+ id: taskId,
223
+ title: task.title,
224
+ description: task.description || task.content || "",
225
+ content: fullContent,
226
+ status: "todo" as const,
227
+ createdAt: Date.now(),
228
+ updatedAt: Date.now(),
229
+ estimatedEffort: task.effort,
230
+ dependencies: task.dependencies || [],
231
+ tags: (task.tags as string[]) || [],
232
+ };
233
+ }
234
+ );
235
+
236
+ return {
237
+ tasks,
238
+ summary,
239
+ estimatedDuration,
240
+ confidence,
241
+ };
242
+ },
243
+ retryConfig,
244
+ "PRD parsing"
245
+ );
246
+ }
247
+
248
+ async reworkPRD(
249
+ prdContent: string,
250
+ feedback: string,
251
+ config?: Partial<AIConfig>,
252
+ promptOverride?: string,
253
+ userMessage?: string,
254
+ streamingOptions?: StreamingOptions,
255
+ retryConfig?: Partial<RetryConfig>,
256
+ workingDirectory?: string,
257
+ enableFilesystemTools?: boolean
258
+ ): Promise<string> {
259
+ return this.retryHandler.executeWithRetry(
260
+ async () => {
261
+ let stackInfo = "";
262
+ try {
263
+ stackInfo = await PromptBuilder.detectStackInfo(workingDirectory);
264
+ if (stackInfo === "Not detected") {
265
+ stackInfo = "";
266
+ }
267
+ } catch (error) {
268
+ // Stack info not available
269
+ }
270
+
271
+ let prompt: string;
272
+ if (promptOverride) {
273
+ prompt = promptOverride;
274
+ } else {
275
+ const variables: Record<string, string> = {
276
+ PRD_CONTENT: prdContent,
277
+ USER_FEEDBACK: feedback,
278
+ };
279
+
280
+ if (stackInfo) {
281
+ variables.STACK_INFO = stackInfo;
282
+ }
283
+
284
+ const promptResult = PromptBuilder.buildPrompt({
285
+ name: "prd-rework",
286
+ type: "user",
287
+ variables,
288
+ });
289
+
290
+ if (!promptResult.success) {
291
+ throw createStandardError(
292
+ TaskOMaticErrorCodes.PRD_GENERATION_ERROR,
293
+ `Failed to build PRD rework prompt: ${promptResult.error}`,
294
+ {
295
+ context: "Prompt building failed during PRD rework",
296
+ suggestions: [
297
+ "Verify prompt template exists",
298
+ "Check variable substitution",
299
+ ],
300
+ }
301
+ );
302
+ }
303
+
304
+ prompt = promptResult.prompt!;
305
+ }
306
+
307
+ if (enableFilesystemTools) {
308
+ const model = this.modelProvider.getModel({
309
+ ...this.modelProvider.getAIConfig(),
310
+ ...config,
311
+ });
312
+
313
+ const allTools = {
314
+ ...filesystemTools,
315
+ };
316
+
317
+ const result = await streamText({
318
+ model,
319
+ tools: allTools,
320
+ system:
321
+ PRD_REWORK_SYSTEM_PROMPT +
322
+ `
323
+
324
+ You have access to filesystem tools that allow you to:
325
+ - readFile: Read the contents of any file in the project
326
+ - listDirectory: List contents of directories
327
+
328
+ Use these tools to understand the current project structure, existing code patterns, and dependencies when reworking the PRD based on feedback.`,
329
+ messages: [{ role: "user", content: userMessage || prompt }],
330
+ maxRetries: 0,
331
+ onChunk: streamingOptions?.onChunk
332
+ ? ({ chunk }) => {
333
+ if (chunk.type === "text-delta") {
334
+ streamingOptions.onChunk!(chunk.text);
335
+ } else if (chunk.type === "reasoning-delta") {
336
+ streamingOptions.onReasoning?.(chunk.text);
337
+ }
338
+ }
339
+ : undefined,
340
+ onFinish: streamingOptions?.onFinish
341
+ ? ({ text, finishReason, usage }) => {
342
+ streamingOptions.onFinish!({
343
+ text,
344
+ finishReason,
345
+ usage,
346
+ isAborted: false,
347
+ });
348
+ }
349
+ : undefined,
350
+ });
351
+
352
+ return await result.text;
353
+ } else {
354
+ return this.streamText(
355
+ "",
356
+ config,
357
+ PRD_REWORK_SYSTEM_PROMPT,
358
+ userMessage || prompt,
359
+ streamingOptions,
360
+ { maxAttempts: 1 }
361
+ );
362
+ }
363
+ },
364
+ retryConfig,
365
+ "PRD rework"
366
+ );
367
+ }
368
+
369
+ async generatePRDQuestions(
370
+ prdContent: string,
371
+ config?: Partial<AIConfig>,
372
+ promptOverride?: string,
373
+ userMessage?: string,
374
+ streamingOptions?: StreamingOptions,
375
+ retryConfig?: Partial<RetryConfig>,
376
+ workingDirectory?: string,
377
+ enableFilesystemTools?: boolean
378
+ ): Promise<string[]> {
379
+ return this.retryHandler.executeWithRetry(
380
+ async () => {
381
+ let stackInfo = "";
382
+ try {
383
+ stackInfo = await PromptBuilder.detectStackInfo(workingDirectory);
384
+ if (stackInfo === "Not detected") {
385
+ stackInfo = "";
386
+ }
387
+ } catch (error) {
388
+ // Stack info not available
389
+ }
390
+
391
+ let prompt: string;
392
+ if (promptOverride) {
393
+ prompt = promptOverride;
394
+ } else {
395
+ const variables: Record<string, string> = {
396
+ PRD_CONTENT: prdContent,
397
+ };
398
+ if (stackInfo) {
399
+ variables.STACK_INFO = stackInfo;
400
+ }
401
+
402
+ const promptResult = PromptBuilder.buildPrompt({
403
+ name: "prd-question",
404
+ type: "user",
405
+ variables,
406
+ });
407
+
408
+ if (!promptResult.success) {
409
+ throw createStandardError(
410
+ TaskOMaticErrorCodes.PRD_GENERATION_ERROR,
411
+ `Failed to build PRD question prompt: ${promptResult.error}`,
412
+ {
413
+ context:
414
+ "Prompt building failed during PRD question generation",
415
+ suggestions: [
416
+ "Verify prompt template exists",
417
+ "Check variable substitution",
418
+ ],
419
+ }
420
+ );
421
+ }
422
+
423
+ prompt = promptResult.prompt!;
424
+ }
425
+
426
+ const { PRD_QUESTION_SYSTEM_PROMPT } = await import("../../prompts");
427
+
428
+ let response: string;
429
+
430
+ if (enableFilesystemTools) {
431
+ const model = this.modelProvider.getModel({
432
+ ...this.modelProvider.getAIConfig(),
433
+ ...config,
434
+ });
435
+
436
+ const allTools = { ...filesystemTools };
437
+
438
+ const result = await streamText({
439
+ model,
440
+ tools: allTools,
441
+ system:
442
+ PRD_QUESTION_SYSTEM_PROMPT +
443
+ `\n\nYou have access to filesystem tools to check existing code/structure if needed.`,
444
+ messages: [{ role: "user", content: userMessage || prompt }],
445
+ maxRetries: 0,
446
+ onChunk: streamingOptions?.onChunk
447
+ ? ({ chunk }) => {
448
+ if (chunk.type === "text-delta") {
449
+ streamingOptions.onChunk!(chunk.text);
450
+ } else if (chunk.type === "reasoning-delta") {
451
+ streamingOptions.onReasoning?.(chunk.text);
452
+ }
453
+ }
454
+ : undefined,
455
+ onFinish: streamingOptions?.onFinish
456
+ ? ({ text, finishReason, usage }) => {
457
+ streamingOptions.onFinish!({
458
+ text,
459
+ finishReason,
460
+ usage,
461
+ isAborted: false,
462
+ });
463
+ }
464
+ : undefined,
465
+ });
466
+
467
+ response = await result.text;
468
+ } else {
469
+ response = await this.streamText(
470
+ "",
471
+ config,
472
+ PRD_QUESTION_SYSTEM_PROMPT,
473
+ userMessage || prompt,
474
+ streamingOptions,
475
+ { maxAttempts: 1 }
476
+ );
477
+ }
478
+
479
+ const parseResult =
480
+ this.jsonParser.parseJSONFromResponse<PRDQuestionResponse>(response);
481
+ if (!parseResult.success) {
482
+ throw createStandardError(
483
+ TaskOMaticErrorCodes.PRD_GENERATION_ERROR,
484
+ parseResult.error || "Failed to parse PRD questions",
485
+ {
486
+ context:
487
+ "AI response parsing failed during PRD question generation",
488
+ suggestions: [
489
+ "Check AI response format",
490
+ "Verify JSON structure",
491
+ ],
492
+ }
493
+ );
494
+ }
495
+
496
+ return parseResult.data?.questions || [];
497
+ },
498
+ retryConfig,
499
+ "PRD questioning"
500
+ );
501
+ }
502
+
503
+ async answerPRDQuestions(
504
+ prdContent: string,
505
+ questions: string[],
506
+ config?: Partial<AIConfig>,
507
+ contextInfo?: {
508
+ stackInfo?: string;
509
+ projectDescription?: string;
510
+ },
511
+ streamingOptions?: StreamingOptions,
512
+ retryConfig?: Partial<RetryConfig>
513
+ ): Promise<Record<string, string>> {
514
+ return this.retryHandler.executeWithRetry(
515
+ async () => {
516
+ const questionsText = questions
517
+ .map((q, i) => `${i + 1}. ${q}`)
518
+ .join("\n");
519
+
520
+ const contextText = contextInfo
521
+ ? `\n\nProject Context:\n${
522
+ contextInfo.stackInfo
523
+ ? `Technology Stack: ${contextInfo.stackInfo}\n`
524
+ : ""
525
+ }${
526
+ contextInfo.projectDescription
527
+ ? `Project Description: ${contextInfo.projectDescription}\n`
528
+ : ""
529
+ }`
530
+ : "";
531
+
532
+ const promptResult = PromptBuilder.buildPrompt({
533
+ name: "prd-question-answer",
534
+ type: "user",
535
+ variables: {
536
+ PRD_CONTENT: prdContent,
537
+ QUESTIONS_TEXT: questionsText,
538
+ CONTEXT_TEXT: contextText,
539
+ },
540
+ });
541
+
542
+ if (!promptResult.success) {
543
+ throw createStandardError(
544
+ TaskOMaticErrorCodes.PRD_GENERATION_ERROR,
545
+ `Failed to build PRD question answer prompt: ${promptResult.error}`,
546
+ {
547
+ context: "Prompt building failed during PRD answer generation",
548
+ suggestions: [
549
+ "Verify prompt template exists",
550
+ "Check variable substitution",
551
+ ],
552
+ }
553
+ );
554
+ }
555
+
556
+ const systemPromptResult = PromptBuilder.buildPrompt({
557
+ name: "prd-question-answer",
558
+ type: "system",
559
+ variables: {},
560
+ });
561
+
562
+ const response = await this.streamText(
563
+ "",
564
+ config,
565
+ systemPromptResult.prompt!,
566
+ promptResult.prompt!,
567
+ streamingOptions,
568
+ { maxAttempts: 1 }
569
+ );
570
+
571
+ const parseResult = this.jsonParser.parseJSONFromResponse<{
572
+ answers: Record<string, string>;
573
+ }>(response);
574
+
575
+ if (!parseResult.success) {
576
+ throw createStandardError(
577
+ TaskOMaticErrorCodes.PRD_GENERATION_ERROR,
578
+ parseResult.error || "Failed to parse PRD answers response",
579
+ {
580
+ context:
581
+ "AI response parsing failed during PRD answer generation",
582
+ suggestions: [
583
+ "Check AI response format",
584
+ "Verify JSON structure",
585
+ ],
586
+ }
587
+ );
588
+ }
589
+
590
+ const answers: Record<string, string> = {};
591
+ const numberedAnswers = parseResult.data?.answers || {};
592
+
593
+ questions.forEach((question, index) => {
594
+ const key = String(index + 1);
595
+ if (numberedAnswers[key]) {
596
+ answers[question] = numberedAnswers[key];
597
+ }
598
+ });
599
+
600
+ return answers;
601
+ },
602
+ retryConfig,
603
+ "PRD question answering"
604
+ );
605
+ }
606
+
607
+ async generatePRD(
608
+ description: string,
609
+ config?: Partial<AIConfig>,
610
+ promptOverride?: string,
611
+ userMessage?: string,
612
+ streamingOptions?: StreamingOptions,
613
+ retryConfig?: Partial<RetryConfig>
614
+ ): Promise<string> {
615
+ return this.retryHandler.executeWithRetry(
616
+ async () => {
617
+ const systemPrompt = PRD_GENERATION_SYSTEM_PROMPT;
618
+ const userContent =
619
+ userMessage || `Product Description:\n${description}`;
620
+
621
+ return this.streamText(
622
+ "",
623
+ config,
624
+ systemPrompt,
625
+ userContent,
626
+ streamingOptions,
627
+ { maxAttempts: 1 }
628
+ );
629
+ },
630
+ retryConfig,
631
+ "PRD generation"
632
+ );
633
+ }
634
+
635
+ async combinePRDs(
636
+ prds: string[],
637
+ originalDescription: string,
638
+ config?: Partial<AIConfig>,
639
+ promptOverride?: string,
640
+ userMessage?: string,
641
+ streamingOptions?: StreamingOptions,
642
+ retryConfig?: Partial<RetryConfig>
643
+ ): Promise<string> {
644
+ return this.retryHandler.executeWithRetry(
645
+ async () => {
646
+ const systemPrompt = PRD_COMBINATION_SYSTEM_PROMPT;
647
+
648
+ let userContent = userMessage;
649
+ if (!userContent) {
650
+ userContent = `Original Description:\n${originalDescription}\n\n`;
651
+ userContent += `<generated_prds>\n`;
652
+ prds.forEach((prd, index) => {
653
+ userContent += ` <prd id="${index + 1}">\n${prd}\n </prd>\n`;
654
+ });
655
+ userContent += `</generated_prds>\n`;
656
+ }
657
+
658
+ return this.streamText(
659
+ "",
660
+ config,
661
+ systemPrompt,
662
+ userContent,
663
+ streamingOptions,
664
+ { maxAttempts: 1 }
665
+ );
666
+ },
667
+ retryConfig,
668
+ "PRD combination"
669
+ );
670
+ }
671
+
672
+ /**
673
+ * Suggest a technology stack based on PRD analysis.
674
+ */
675
+ async suggestStack(
676
+ prdContent: string,
677
+ projectName?: string,
678
+ config?: Partial<AIConfig>,
679
+ promptOverride?: string,
680
+ userMessage?: string,
681
+ streamingOptions?: StreamingOptions,
682
+ retryConfig?: Partial<RetryConfig>,
683
+ workingDirectory?: string,
684
+ enableFilesystemTools?: boolean
685
+ ): Promise<{ config: BTSConfig; reasoning: string }> {
686
+ return this.retryHandler.executeWithRetry(
687
+ async () => {
688
+ // Try to detect stack info for context
689
+ let stackInfo = "";
690
+ try {
691
+ stackInfo = await PromptBuilder.detectStackInfo(workingDirectory);
692
+ if (stackInfo === "Not detected") {
693
+ stackInfo = "";
694
+ }
695
+ } catch (error) {
696
+ // Stack info not available
697
+ }
698
+
699
+ let enhancedPrompt: string;
700
+ if (promptOverride) {
701
+ enhancedPrompt = promptOverride;
702
+ } else {
703
+ const variables: Record<string, string> = {
704
+ PRD_CONTENT: prdContent,
705
+ };
706
+
707
+ if (stackInfo) {
708
+ variables.STACK_INFO = `## Existing Stack Info\n${stackInfo}`;
709
+ }
710
+
711
+ if (projectName) {
712
+ variables.PROJECT_NAME = `## Project Name\nUse this project name: ${projectName}`;
713
+ }
714
+
715
+ const promptResult = PromptBuilder.buildPrompt({
716
+ name: "prd-suggest-stack",
717
+ type: "user",
718
+ variables,
719
+ });
720
+
721
+ if (!promptResult.success) {
722
+ throw createStandardError(
723
+ TaskOMaticErrorCodes.PRD_GENERATION_ERROR,
724
+ `Failed to build stack suggestion prompt: ${promptResult.error}`,
725
+ {
726
+ context: "Prompt building failed during stack suggestion",
727
+ suggestions: [
728
+ "Verify prompt template exists",
729
+ "Check variable substitution",
730
+ ],
731
+ }
732
+ );
733
+ }
734
+
735
+ enhancedPrompt = promptResult.prompt!;
736
+ }
737
+
738
+ let response: string;
739
+
740
+ if (enableFilesystemTools) {
741
+ const model = this.modelProvider.getModel({
742
+ ...this.modelProvider.getAIConfig(),
743
+ ...config,
744
+ });
745
+
746
+ const allTools = {
747
+ ...filesystemTools,
748
+ };
749
+
750
+ const result = await streamText({
751
+ model,
752
+ tools: allTools,
753
+ system:
754
+ PRD_SUGGEST_STACK_SYSTEM_PROMPT +
755
+ `\n\nYou have access to filesystem tools that allow you to:\n- readFile: Read the contents of any file in the project\n- listDirectory: List contents of directories\n\nUse these tools to understand the project structure and existing dependencies when suggesting the stack.`,
756
+ messages: [
757
+ { role: "user", content: userMessage || enhancedPrompt },
758
+ ],
759
+ maxRetries: 0,
760
+ onChunk: streamingOptions?.onChunk
761
+ ? ({ chunk }) => {
762
+ if (chunk.type === "text-delta") {
763
+ streamingOptions.onChunk!(chunk.text);
764
+ } else if (chunk.type === "reasoning-delta") {
765
+ streamingOptions.onReasoning?.(chunk.text);
766
+ }
767
+ }
768
+ : undefined,
769
+ onFinish: streamingOptions?.onFinish
770
+ ? ({ text, finishReason, usage }) => {
771
+ streamingOptions.onFinish!({
772
+ text,
773
+ finishReason,
774
+ usage,
775
+ isAborted: false,
776
+ });
777
+ }
778
+ : undefined,
779
+ });
780
+
781
+ response = await result.text;
782
+ } else {
783
+ response = await this.streamText(
784
+ "",
785
+ config,
786
+ PRD_SUGGEST_STACK_SYSTEM_PROMPT,
787
+ userMessage || enhancedPrompt,
788
+ streamingOptions,
789
+ { maxAttempts: 1 }
790
+ );
791
+ }
792
+
793
+ // Parse the JSON response
794
+ const parseResult =
795
+ this.jsonParser.parseJSONFromResponse<StackSuggestionResponse>(
796
+ response
797
+ );
798
+
799
+ if (!parseResult.success) {
800
+ throw createStandardError(
801
+ TaskOMaticErrorCodes.PRD_GENERATION_ERROR,
802
+ parseResult.error || "Failed to parse stack suggestion response",
803
+ {
804
+ context: "AI response parsing failed during stack suggestion",
805
+ suggestions: [
806
+ "Check AI response format",
807
+ "Verify JSON structure",
808
+ ],
809
+ }
810
+ );
811
+ }
812
+
813
+ const parsed = parseResult.data!;
814
+
815
+ // Validate and apply defaults to the config
816
+ const validatedConfig = this.validateStackConfig(
817
+ parsed.config || (parsed as unknown as Partial<BTSConfig>)
818
+ );
819
+
820
+ return {
821
+ config: validatedConfig,
822
+ reasoning: parsed.reasoning || "No reasoning provided.",
823
+ };
824
+ },
825
+ retryConfig,
826
+ "Stack suggestion"
827
+ );
828
+ }
829
+
830
+ /**
831
+ * Validate and apply defaults to a partial BTSConfig.
832
+ */
833
+ private validateStackConfig(partial: Partial<BTSConfig>): BTSConfig {
834
+ return {
835
+ projectName: partial.projectName || "my-project",
836
+ frontend: partial.frontend || "none",
837
+ backend: partial.backend || "none",
838
+ database: partial.database || "none",
839
+ orm: partial.orm || "none",
840
+ api: partial.api || "none",
841
+ auth: partial.auth || "none",
842
+ payments: partial.payments || "none",
843
+ dbSetup: partial.dbSetup || "none",
844
+ runtime: partial.runtime || "bun",
845
+ packageManager: partial.packageManager || "bun",
846
+ git: partial.git ?? true,
847
+ install: partial.install ?? true,
848
+ webDeploy: partial.webDeploy || "none",
849
+ serverDeploy: partial.serverDeploy || "none",
850
+ addons: Array.isArray(partial.addons) ? partial.addons : [],
851
+ examples: Array.isArray(partial.examples) ? partial.examples : [],
852
+ };
853
+ }
854
+ }