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,550 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.prdService = exports.PRDService = void 0;
37
+ exports.getPRDService = getPRDService;
38
+ const task_o_matic_error_1 = require("../utils/task-o-matic-error");
39
+ const fs_1 = require("fs");
40
+ const path_1 = require("path");
41
+ const ai_service_factory_1 = require("../utils/ai-service-factory");
42
+ const ai_config_builder_1 = require("../utils/ai-config-builder");
43
+ const config_1 = require("../lib/config");
44
+ const validation_1 = require("../lib/validation");
45
+ const streaming_utils_1 = require("../utils/streaming-utils");
46
+ const file_utils_1 = require("../utils/file-utils");
47
+ /**
48
+ * PRDService - Business logic for PRD operations
49
+ * Handles PRD parsing, task extraction, and PRD improvement
50
+ */
51
+ class PRDService {
52
+ storage;
53
+ aiOperations;
54
+ /**
55
+ * Create a new PRDService
56
+ *
57
+ * @param dependencies - Optional dependencies to inject (for testing)
58
+ */
59
+ constructor(dependencies = {}) {
60
+ // Use injected dependencies or fall back to singletons
61
+ this.storage = dependencies.storage ?? (0, ai_service_factory_1.getStorage)();
62
+ this.aiOperations = dependencies.aiOperations ?? (0, ai_service_factory_1.getAIOperations)();
63
+ }
64
+ async parsePRD(input) {
65
+ const startTime = Date.now();
66
+ const steps = [];
67
+ input.callbacks?.onProgress?.({
68
+ type: "started",
69
+ message: "Starting PRD parsing...",
70
+ });
71
+ // Validate file exists (DRY fix 1.2)
72
+ (0, file_utils_1.validateFileExists)(input.file, `PRD file not found: ${input.file}`);
73
+ // Ensure we're in a task-o-matic project
74
+ const taskOMaticDir = config_1.configManager.getTaskOMaticDir();
75
+ if (!(0, fs_1.existsSync)(taskOMaticDir)) {
76
+ throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.CONFIGURATION_ERROR, "Not a task-o-matic project. Run 'task-o-matic init init' first.", {
77
+ suggestions: ["Run `task-o-matic init init` in your project root."],
78
+ });
79
+ }
80
+ // Set working directory and reload config (DRY fix 1.4)
81
+ const workingDir = input.workingDirectory || process.cwd();
82
+ await (0, config_1.setupWorkingDirectory)(workingDir);
83
+ input.callbacks?.onProgress?.({
84
+ type: "progress",
85
+ message: "Reading PRD file...",
86
+ });
87
+ const prdContent = (0, fs_1.readFileSync)(input.file, "utf-8");
88
+ // Save PRD file to .task-o-matic/prd directory
89
+ input.callbacks?.onProgress?.({
90
+ type: "progress",
91
+ message: "Saving PRD to project directory...",
92
+ });
93
+ const stepStart1 = Date.now();
94
+ const prdDir = (0, path_1.join)(taskOMaticDir, "prd");
95
+ const prdFileName = (0, path_1.basename)(input.file);
96
+ const savedPrdPath = (0, path_1.join)(prdDir, prdFileName);
97
+ // Ensure PRD directory exists
98
+ if (!(0, fs_1.existsSync)(prdDir)) {
99
+ (0, fs_1.mkdirSync)(prdDir, { recursive: true });
100
+ }
101
+ // Copy PRD file to project directory
102
+ (0, fs_1.copyFileSync)(input.file, savedPrdPath);
103
+ // Get relative path from .task-o-matic directory for storage
104
+ const relativePrdPath = (0, path_1.relative)(taskOMaticDir, savedPrdPath);
105
+ steps.push({
106
+ step: "Save PRD File",
107
+ status: "completed",
108
+ duration: Date.now() - stepStart1,
109
+ });
110
+ // Validate AI provider if specified
111
+ if (input.aiOptions?.aiProvider &&
112
+ !(0, validation_1.isValidAIProvider)(input.aiOptions.aiProvider)) {
113
+ throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.AI_CONFIGURATION_ERROR, `Invalid AI provider: ${input.aiOptions.aiProvider}`, {
114
+ suggestions: ["Use a valid AI provider, e.g., 'openai', 'anthropic'"],
115
+ });
116
+ }
117
+ const aiConfig = (0, ai_config_builder_1.buildAIConfig)(input.aiOptions);
118
+ input.callbacks?.onProgress?.({
119
+ type: "progress",
120
+ message: "Parsing PRD with AI...",
121
+ });
122
+ const stepStart2 = Date.now();
123
+ // Use utility to wrap streaming options and capture metrics (DRY fix 1.1)
124
+ const { options: metricsStreamingOptions, getMetrics } = (0, streaming_utils_1.createMetricsStreamingOptions)(input.streamingOptions, stepStart2);
125
+ const result = await this.aiOperations.parsePRD(prdContent, aiConfig, input.promptOverride, input.messageOverride, metricsStreamingOptions, undefined, // retryConfig
126
+ workingDir, // Pass working directory to AI operations
127
+ input.enableFilesystemTools);
128
+ // Extract metrics after AI call
129
+ const { tokenUsage, timeToFirstToken } = getMetrics();
130
+ steps.push({
131
+ step: "AI Parsing",
132
+ status: "completed",
133
+ duration: Date.now() - stepStart2,
134
+ details: { tasksFound: result.tasks.length },
135
+ });
136
+ input.callbacks?.onProgress?.({
137
+ type: "progress",
138
+ message: `Creating ${result.tasks.length} tasks...`,
139
+ });
140
+ // Create tasks
141
+ const stepStart3 = Date.now();
142
+ const createdTasks = [];
143
+ for (let i = 0; i < result.tasks.length; i++) {
144
+ const task = result.tasks[i];
145
+ input.callbacks?.onProgress?.({
146
+ type: "progress",
147
+ message: `Creating task ${i + 1}/${result.tasks.length}: ${task.title}`,
148
+ current: i + 1,
149
+ total: result.tasks.length,
150
+ });
151
+ const createdTask = await this.storage.createTask({
152
+ id: task.id, // Preserve AI-generated ID for dependencies
153
+ title: task.title,
154
+ description: task.description,
155
+ content: task.content,
156
+ estimatedEffort: task.estimatedEffort,
157
+ status: "todo",
158
+ dependencies: task.dependencies,
159
+ tags: task.tags,
160
+ prdFile: relativePrdPath, // Reference to the PRD file
161
+ });
162
+ createdTasks.push(createdTask);
163
+ // Update AI metadata with the actual task ID
164
+ const aiMetadata = {
165
+ taskId: createdTask.id,
166
+ aiGenerated: true,
167
+ aiPrompt: input.promptOverride || "Parse PRD and extract tasks",
168
+ confidence: result.confidence,
169
+ aiProvider: input.aiOptions?.aiProvider,
170
+ aiModel: input.aiOptions?.aiModel,
171
+ generatedAt: Date.now(),
172
+ };
173
+ await this.storage.saveTaskAIMetadata(aiMetadata);
174
+ }
175
+ steps.push({
176
+ step: "Create Tasks",
177
+ status: "completed",
178
+ duration: Date.now() - stepStart3,
179
+ details: { count: createdTasks.length },
180
+ });
181
+ input.callbacks?.onProgress?.({
182
+ type: "completed",
183
+ message: `Successfully created ${createdTasks.length} tasks from PRD`,
184
+ });
185
+ const duration = Date.now() - startTime;
186
+ // Calculate cost if token usage is available
187
+ let cost;
188
+ if (tokenUsage) {
189
+ // Cost calculation would depend on the model
190
+ // For now, we'll leave it undefined and can add pricing later
191
+ // This matches the benchmark pattern where cost calculation is done elsewhere
192
+ }
193
+ return {
194
+ success: true,
195
+ prd: {
196
+ overview: result.summary || "",
197
+ objectives: [],
198
+ features: [],
199
+ },
200
+ tasks: createdTasks,
201
+ stats: {
202
+ tasksCreated: createdTasks.length,
203
+ duration,
204
+ aiProvider: input.aiOptions?.aiProvider || "default",
205
+ aiModel: input.aiOptions?.aiModel || "default",
206
+ tokenUsage,
207
+ timeToFirstToken,
208
+ cost,
209
+ },
210
+ steps,
211
+ };
212
+ }
213
+ async generateQuestions(input) {
214
+ input.callbacks?.onProgress?.({
215
+ type: "started",
216
+ message: "Generating clarifying questions...",
217
+ });
218
+ // Validate file exists (DRY fix 1.2)
219
+ (0, file_utils_1.validateFileExists)(input.file, `PRD file not found: ${input.file}`);
220
+ // Set working directory and reload config (DRY fix 1.4)
221
+ const workingDir = input.workingDirectory || process.cwd();
222
+ await (0, config_1.setupWorkingDirectory)(workingDir);
223
+ input.callbacks?.onProgress?.({
224
+ type: "progress",
225
+ message: "Reading PRD file...",
226
+ });
227
+ const prdContent = (0, fs_1.readFileSync)(input.file, "utf-8");
228
+ if (input.aiOptions?.aiProvider &&
229
+ !(0, validation_1.isValidAIProvider)(input.aiOptions.aiProvider)) {
230
+ throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.AI_CONFIGURATION_ERROR, `Invalid AI provider: ${input.aiOptions.aiProvider}`, {
231
+ suggestions: ["Use a valid AI provider, e.g., 'openai', 'anthropic'"],
232
+ });
233
+ }
234
+ const aiConfig = (0, ai_config_builder_1.buildAIConfig)(input.aiOptions);
235
+ input.callbacks?.onProgress?.({
236
+ type: "progress",
237
+ message: "Analyzing PRD with AI...",
238
+ });
239
+ const questions = await this.aiOperations.generatePRDQuestions(prdContent, aiConfig, input.promptOverride, input.messageOverride, input.streamingOptions, undefined, workingDir, input.enableFilesystemTools);
240
+ input.callbacks?.onProgress?.({
241
+ type: "completed",
242
+ message: `Generated ${questions.length} questions`,
243
+ });
244
+ return questions;
245
+ }
246
+ async reworkPRD(input) {
247
+ input.callbacks?.onProgress?.({
248
+ type: "started",
249
+ message: "Starting PRD improvement...",
250
+ });
251
+ // Validate file exists (DRY fix 1.2)
252
+ (0, file_utils_1.validateFileExists)(input.file, `PRD file not found: ${input.file}`);
253
+ // Set working directory and reload config (DRY fix 1.4)
254
+ const workingDir = input.workingDirectory || process.cwd();
255
+ await (0, config_1.setupWorkingDirectory)(workingDir);
256
+ input.callbacks?.onProgress?.({
257
+ type: "progress",
258
+ message: "Reading PRD file...",
259
+ });
260
+ const prdContent = (0, fs_1.readFileSync)(input.file, "utf-8");
261
+ // Validate AI provider if specified
262
+ if (input.aiOptions?.aiProvider &&
263
+ !(0, validation_1.isValidAIProvider)(input.aiOptions.aiProvider)) {
264
+ throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.AI_CONFIGURATION_ERROR, `Invalid AI provider: ${input.aiOptions.aiProvider}`, {
265
+ suggestions: ["Use a valid AI provider, e.g., 'openai', 'anthropic'"],
266
+ });
267
+ }
268
+ const aiConfig = (0, ai_config_builder_1.buildAIConfig)(input.aiOptions);
269
+ input.callbacks?.onProgress?.({
270
+ type: "progress",
271
+ message: "Calling AI to improve PRD...",
272
+ });
273
+ const improvedPRD = await this.aiOperations.reworkPRD(prdContent, input.feedback, aiConfig, input.promptOverride, input.messageOverride, input.streamingOptions, undefined, // retryConfig
274
+ workingDir, // Pass working directory to AI operations
275
+ input.enableFilesystemTools);
276
+ input.callbacks?.onProgress?.({
277
+ type: "progress",
278
+ message: "Saving improved PRD...",
279
+ });
280
+ const outputPath = input.output || input.file;
281
+ (0, fs_1.writeFileSync)(outputPath, improvedPRD);
282
+ input.callbacks?.onProgress?.({
283
+ type: "completed",
284
+ message: `PRD improved and saved to ${outputPath}`,
285
+ });
286
+ return outputPath;
287
+ }
288
+ async refinePRDWithQuestions(input) {
289
+ input.callbacks?.onProgress?.({
290
+ type: "started",
291
+ message: "Starting PRD question/refine process...",
292
+ });
293
+ // Step 1: Generate questions
294
+ input.callbacks?.onProgress?.({
295
+ type: "progress",
296
+ message: "Generating clarifying questions...",
297
+ });
298
+ const questions = await this.generateQuestions({
299
+ file: input.file,
300
+ workingDirectory: input.workingDirectory,
301
+ enableFilesystemTools: input.enableFilesystemTools,
302
+ aiOptions: input.aiOptions,
303
+ streamingOptions: input.streamingOptions,
304
+ callbacks: input.callbacks,
305
+ });
306
+ if (questions.length === 0) {
307
+ input.callbacks?.onProgress?.({
308
+ type: "completed",
309
+ message: "No questions generated - PRD appears complete",
310
+ });
311
+ return {
312
+ questions: [],
313
+ answers: {},
314
+ refinedPRDPath: input.file,
315
+ };
316
+ }
317
+ // Step 2: Get stack info for context
318
+ const workingDir = input.workingDirectory || process.cwd();
319
+ const PromptBuilder = (await Promise.resolve().then(() => __importStar(require("../lib/prompt-builder")))).PromptBuilder;
320
+ let stackInfo = "";
321
+ try {
322
+ stackInfo = await PromptBuilder.detectStackInfo(workingDir);
323
+ if (stackInfo === "Not detected") {
324
+ stackInfo = "";
325
+ }
326
+ }
327
+ catch (error) {
328
+ // Stack info not available
329
+ }
330
+ // Step 3: Get answers
331
+ let answers;
332
+ if (input.questionMode === "user") {
333
+ // User mode: return questions for CLI to prompt user
334
+ // Answers should be provided in input.answers
335
+ if (!input.answers || Object.keys(input.answers).length === 0) {
336
+ throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.INVALID_INPUT, "User mode selected but no answers provided. CLI layer should collect answers.");
337
+ }
338
+ answers = input.answers;
339
+ }
340
+ else {
341
+ // AI mode: use AI to answer questions with context
342
+ input.callbacks?.onProgress?.({
343
+ type: "progress",
344
+ message: "AI is answering questions...",
345
+ });
346
+ const prdContent = (0, fs_1.readFileSync)(input.file, "utf-8");
347
+ // Use questionAIOptions if provided, otherwise use main aiOptions
348
+ const answeringAIConfig = (0, ai_config_builder_1.buildAIConfig)(input.questionAIOptions || input.aiOptions);
349
+ answers = await this.aiOperations.answerPRDQuestions(prdContent, questions, answeringAIConfig, {
350
+ stackInfo,
351
+ }, input.streamingOptions);
352
+ }
353
+ // Step 4: Format questions + answers as structured feedback
354
+ let feedback = "Please incorporate the following clarifications into the PRD:\n\n";
355
+ questions.forEach((q, i) => {
356
+ feedback += `Q${i + 1}: ${q}\nA: ${answers[q] || "No answer provided"}\n\n`;
357
+ });
358
+ // Step 5: Automatically call reworkPRD with formatted feedback
359
+ input.callbacks?.onProgress?.({
360
+ type: "progress",
361
+ message: "Refining PRD with answers...",
362
+ });
363
+ const refinedPRDPath = await this.reworkPRD({
364
+ file: input.file,
365
+ feedback,
366
+ workingDirectory: input.workingDirectory,
367
+ enableFilesystemTools: input.enableFilesystemTools,
368
+ aiOptions: input.aiOptions,
369
+ streamingOptions: input.streamingOptions,
370
+ callbacks: input.callbacks,
371
+ });
372
+ input.callbacks?.onProgress?.({
373
+ type: "completed",
374
+ message: `PRD refined with ${questions.length} questions answered`,
375
+ });
376
+ return {
377
+ questions,
378
+ answers,
379
+ refinedPRDPath,
380
+ };
381
+ }
382
+ async generatePRD(input) {
383
+ const startTime = Date.now();
384
+ input.callbacks?.onProgress?.({
385
+ type: "started",
386
+ message: "Generating PRD...",
387
+ });
388
+ // Use utility to wrap streaming options and capture metrics
389
+ const { options: metricsStreamingOptions, getMetrics } = (0, streaming_utils_1.createMetricsStreamingOptions)(input.streamingOptions, startTime);
390
+ const aiConfig = (0, ai_config_builder_1.buildAIConfig)(input.aiOptions);
391
+ const content = await this.aiOperations.generatePRD(input.description, aiConfig, undefined, undefined, metricsStreamingOptions);
392
+ // Get metrics after AI operation
393
+ const { tokenUsage, timeToFirstToken } = getMetrics();
394
+ // Calculate cost if needed
395
+ let cost;
396
+ if (tokenUsage && tokenUsage.total > 0) {
397
+ cost = tokenUsage.total * 0.000001; // Placeholder cost calculation
398
+ }
399
+ // Save file using utility
400
+ const path = (0, file_utils_1.savePRDFile)(content, input.filename, input.outputDir);
401
+ input.callbacks?.onProgress?.({
402
+ type: "completed",
403
+ message: `PRD generated and saved to ${path}`,
404
+ });
405
+ return {
406
+ path,
407
+ content,
408
+ stats: {
409
+ duration: Date.now() - startTime,
410
+ tokenUsage,
411
+ timeToFirstToken,
412
+ cost,
413
+ },
414
+ };
415
+ }
416
+ async combinePRDs(input) {
417
+ const startTime = Date.now();
418
+ input.callbacks?.onProgress?.({
419
+ type: "started",
420
+ message: "Combining PRDs...",
421
+ });
422
+ // Use utility to wrap streaming options and capture metrics
423
+ const { options: metricsStreamingOptions, getMetrics } = (0, streaming_utils_1.createMetricsStreamingOptions)(input.streamingOptions, startTime);
424
+ const aiConfig = (0, ai_config_builder_1.buildAIConfig)(input.aiOptions);
425
+ const content = await this.aiOperations.combinePRDs(input.prds, input.originalDescription, aiConfig, undefined, undefined, metricsStreamingOptions);
426
+ // Get metrics after AI operation
427
+ const { tokenUsage, timeToFirstToken } = getMetrics();
428
+ // Calculate cost if needed
429
+ let cost;
430
+ if (tokenUsage && tokenUsage.total > 0) {
431
+ cost = tokenUsage.total * 0.000001;
432
+ }
433
+ // Save file using utility (defaults to "prd.md" if no filename, so we provide the default for combinePRDs)
434
+ const path = (0, file_utils_1.savePRDFile)(content, input.filename || "prd-master.md", input.outputDir);
435
+ input.callbacks?.onProgress?.({
436
+ type: "completed",
437
+ message: `Master PRD saved to ${path}`,
438
+ });
439
+ return {
440
+ path,
441
+ content,
442
+ stats: {
443
+ duration: Date.now() - startTime,
444
+ tokenUsage,
445
+ timeToFirstToken,
446
+ cost,
447
+ },
448
+ };
449
+ }
450
+ /**
451
+ * Suggest a technology stack based on PRD analysis.
452
+ */
453
+ async suggestStack(input) {
454
+ const startTime = Date.now();
455
+ input.callbacks?.onProgress?.({
456
+ type: "started",
457
+ message: "Analyzing PRD for stack suggestion...",
458
+ });
459
+ // Validate mutual exclusivity
460
+ if (input.file && input.content) {
461
+ throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.INVALID_INPUT, "Cannot specify both --file and --content", {
462
+ suggestions: ["Use either --file OR --content, not both."],
463
+ });
464
+ }
465
+ if (!input.file && !input.content) {
466
+ throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.INVALID_INPUT, "Must specify either --file or --content", {
467
+ suggestions: [
468
+ "Provide a PRD file with --file or content with --content.",
469
+ ],
470
+ });
471
+ }
472
+ // Get PRD content
473
+ let prdContent;
474
+ if (input.file) {
475
+ (0, file_utils_1.validateFileExists)(input.file, `PRD file not found: ${input.file}`);
476
+ prdContent = (0, fs_1.readFileSync)(input.file, "utf-8");
477
+ }
478
+ else {
479
+ prdContent = input.content;
480
+ }
481
+ // Set working directory
482
+ const workingDir = input.workingDirectory || process.cwd();
483
+ await (0, config_1.setupWorkingDirectory)(workingDir);
484
+ // Validate AI provider if specified
485
+ if (input.aiOptions?.aiProvider &&
486
+ !(0, validation_1.isValidAIProvider)(input.aiOptions.aiProvider)) {
487
+ throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.AI_CONFIGURATION_ERROR, `Invalid AI provider: ${input.aiOptions.aiProvider}`, {
488
+ suggestions: ["Use a valid AI provider, e.g., 'openai', 'anthropic'"],
489
+ });
490
+ }
491
+ const aiConfig = (0, ai_config_builder_1.buildAIConfig)(input.aiOptions);
492
+ input.callbacks?.onProgress?.({
493
+ type: "progress",
494
+ message: "Calling AI to analyze PRD...",
495
+ });
496
+ // Use utility to wrap streaming options and capture metrics
497
+ const { options: metricsStreamingOptions, getMetrics } = (0, streaming_utils_1.createMetricsStreamingOptions)(input.streamingOptions, startTime);
498
+ const result = await this.aiOperations.suggestStack(prdContent, input.projectName, aiConfig, input.promptOverride, input.messageOverride, metricsStreamingOptions, undefined, // retryConfig
499
+ workingDir, input.enableFilesystemTools);
500
+ // Get metrics after AI operation
501
+ const { tokenUsage, timeToFirstToken } = getMetrics();
502
+ // Calculate cost if needed
503
+ let cost;
504
+ if (tokenUsage && tokenUsage.total > 0) {
505
+ cost = tokenUsage.total * 0.000001; // Placeholder cost calculation
506
+ }
507
+ // Save if requested
508
+ let savedPath;
509
+ if (input.save || input.output) {
510
+ input.callbacks?.onProgress?.({
511
+ type: "progress",
512
+ message: "Saving stack configuration...",
513
+ });
514
+ savedPath = (0, file_utils_1.saveStackFile)(result.config, input.output);
515
+ }
516
+ input.callbacks?.onProgress?.({
517
+ type: "completed",
518
+ message: savedPath
519
+ ? `Stack suggestion saved to ${savedPath}`
520
+ : "Stack suggestion complete",
521
+ });
522
+ return {
523
+ success: true,
524
+ stack: result.config,
525
+ reasoning: result.reasoning,
526
+ savedPath,
527
+ stats: {
528
+ duration: Date.now() - startTime,
529
+ tokenUsage,
530
+ timeToFirstToken,
531
+ cost,
532
+ },
533
+ };
534
+ }
535
+ }
536
+ exports.PRDService = PRDService;
537
+ // Lazy singleton instance - only created when first accessed
538
+ let prdServiceInstance;
539
+ function getPRDService() {
540
+ if (!prdServiceInstance) {
541
+ prdServiceInstance = new PRDService();
542
+ }
543
+ return prdServiceInstance;
544
+ }
545
+ // Backward compatibility: export as const but use getter
546
+ exports.prdService = new Proxy({}, {
547
+ get(target, prop) {
548
+ return getPRDService()[prop];
549
+ },
550
+ });