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,83 @@
1
+ import { spawn } from "node:child_process";
2
+
3
+ import type { ExecutorConfig, ExternalExecutor } from "../../types";
4
+ import { logger } from "../logger";
5
+
6
+ export class KiloExecutor implements ExternalExecutor {
7
+ name = "kilo";
8
+ private config?: ExecutorConfig;
9
+
10
+ constructor(config?: ExecutorConfig) {
11
+ this.config = config;
12
+ }
13
+
14
+ supportsSessionResumption(): boolean {
15
+ return true;
16
+ }
17
+
18
+ async execute(
19
+ message: string,
20
+ dry: boolean = false,
21
+ config?: ExecutorConfig
22
+ ): Promise<void> {
23
+ // Merge constructor config with execution config (execution takes precedence)
24
+ const finalConfig = { ...this.config, ...config };
25
+
26
+ // Build arguments array
27
+ const args: string[] = [];
28
+
29
+ // Add model if specified
30
+ if (finalConfig.model) {
31
+ args.push("-mo", finalConfig.model);
32
+ logger.progress(`🤖 Using model: ${finalConfig.model}`);
33
+ }
34
+
35
+ // Add session resumption if specified
36
+ if (finalConfig.continueLastSession) {
37
+ args.push("-c");
38
+ logger.progress("🔄 Continuing last session");
39
+ } else if (finalConfig.sessionId) {
40
+ args.push("-s", finalConfig.sessionId);
41
+ logger.progress(`🔄 Resuming session: ${finalConfig.sessionId}`);
42
+ }
43
+
44
+ // Run in autonomous mode (non-interactive) for automation
45
+ args.push("--auto");
46
+
47
+ // Enable auto-approval of all tool permissions
48
+ args.push("--yolo");
49
+
50
+ // Add prompt as positional argument
51
+ args.push(message);
52
+
53
+ if (dry) {
54
+ logger.progress(`🔧 Using executor: ${this.name}`);
55
+ logger.progress(`kilocode ${args.join(" ")}`);
56
+ return;
57
+ }
58
+
59
+ // Launch kilocode and wait for it to complete
60
+ const child = spawn("kilocode", args, {
61
+ stdio: "inherit", // Give tool full terminal control
62
+ });
63
+
64
+ // Wait for completion (blocking)
65
+ await new Promise<void>((resolve, reject) => {
66
+ child.on("close", (code: number) => {
67
+ if (code === 0) {
68
+ logger.success("✅ Kilo Code execution completed successfully");
69
+ resolve();
70
+ } else {
71
+ const error = new Error(`Kilo Code exited with code ${code}`);
72
+ logger.error(`❌ ${error.message}`);
73
+ reject(error);
74
+ }
75
+ });
76
+
77
+ child.on("error", (error: Error) => {
78
+ logger.error(`❌ Failed to launch Kilo Code: ${error.message}`);
79
+ reject(error);
80
+ });
81
+ });
82
+ }
83
+ }
@@ -0,0 +1,81 @@
1
+ import { spawn } from "node:child_process";
2
+
3
+ import type { ExecutorConfig, ExternalExecutor } from "../../types";
4
+ import { logger } from "../logger";
5
+
6
+ export class OpencodeExecutor implements ExternalExecutor {
7
+ name = "opencode";
8
+ private config?: ExecutorConfig;
9
+
10
+ constructor(config?: ExecutorConfig) {
11
+ this.config = config;
12
+ }
13
+
14
+ supportsSessionResumption(): boolean {
15
+ return true;
16
+ }
17
+
18
+ async execute(
19
+ message: string,
20
+ dry: boolean = false,
21
+ config?: ExecutorConfig
22
+ ): Promise<void> {
23
+ // Merge constructor config with execution config (execution takes precedence)
24
+ const finalConfig = { ...this.config, ...config };
25
+
26
+ // Build arguments array
27
+ const args: string[] = [];
28
+
29
+ // Add model if specified
30
+ if (finalConfig.model) {
31
+ args.push("-m", finalConfig.model);
32
+ logger.progress(`🤖 Using model: ${finalConfig.model}`);
33
+ }
34
+
35
+ // Add session resumption if specified
36
+ if (finalConfig.continueLastSession) {
37
+ args.push("-c");
38
+ logger.progress("🔄 Continuing last session");
39
+ } else if (finalConfig.sessionId) {
40
+ args.push("-s", finalConfig.sessionId);
41
+ logger.progress(`🔄 Resuming session: ${finalConfig.sessionId}`);
42
+ }
43
+
44
+ // Use 'run' subcommand with message as positional argument
45
+ args.push("run", message);
46
+
47
+ if (dry) {
48
+ logger.progress(`🔧 Using executor: ${this.name}`);
49
+ // Quote arguments that contain spaces for display
50
+ const quotedArgs = args.map((arg) =>
51
+ arg.includes(" ") ? `"${arg.replace(/"/g, '\\"')}"` : arg
52
+ );
53
+ logger.progress(`opencode ${quotedArgs.join(" ")}`);
54
+ return;
55
+ }
56
+
57
+ // Launch opencode and wait for it to complete
58
+ const child = spawn("opencode", args, {
59
+ stdio: "inherit", // Give tool full terminal control
60
+ });
61
+
62
+ // Wait for completion (blocking)
63
+ await new Promise<void>((resolve, reject) => {
64
+ child.on("close", (code: number) => {
65
+ if (code === 0) {
66
+ logger.success("✅ Opencode execution completed successfully");
67
+ resolve();
68
+ } else {
69
+ const error = new Error(`Opencode exited with code ${code}`);
70
+ logger.error(`❌ ${error.message}`);
71
+ reject(error);
72
+ }
73
+ });
74
+
75
+ child.on("error", (error: Error) => {
76
+ logger.error(`❌ Failed to launch opencode: ${error.message}`);
77
+ reject(error);
78
+ });
79
+ });
80
+ }
81
+ }
@@ -0,0 +1,334 @@
1
+ import { exec } from "child_process";
2
+ import { promisify } from "util";
3
+ import { logger } from "./logger";
4
+ import { getAIOperations } from "../utils/ai-service-factory";
5
+
6
+ const execAsync = promisify(exec);
7
+
8
+ /**
9
+ * Git state captured before and after execution
10
+ */
11
+ export interface GitState {
12
+ beforeHead: string;
13
+ afterHead: string;
14
+ hasUncommittedChanges: boolean;
15
+ }
16
+
17
+ /**
18
+ * Commit information extracted from git state
19
+ */
20
+ export interface CommitInfo {
21
+ message: string;
22
+ files: string[];
23
+ }
24
+
25
+ /**
26
+ * Check if new commits were made since a given HEAD
27
+ * Used to detect if the AI agent already committed during execution
28
+ */
29
+ export async function hasNewCommitsSince(
30
+ beforeHead: string,
31
+ execFn: (
32
+ command: string
33
+ ) => Promise<{ stdout: string; stderr: string }> = execAsync
34
+ ): Promise<boolean> {
35
+ if (!beforeHead) return false;
36
+ try {
37
+ const { stdout } = await execFn("git rev-parse HEAD");
38
+ return stdout.trim() !== beforeHead;
39
+ } catch {
40
+ return false;
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Capture git state (HEAD commit and uncommitted changes)
46
+ */
47
+ export async function captureGitState(
48
+ execFn: (
49
+ command: string
50
+ ) => Promise<{ stdout: string; stderr: string }> = execAsync
51
+ ): Promise<Partial<GitState>> {
52
+ try {
53
+ const { stdout: headStdout } = await execFn("git rev-parse HEAD");
54
+ const { stdout: statusStdout } = await execFn("git status --porcelain");
55
+
56
+ return {
57
+ beforeHead: headStdout.trim(),
58
+ afterHead: headStdout.trim(),
59
+ hasUncommittedChanges: statusStdout.trim().length > 0,
60
+ };
61
+ } catch (e) {
62
+ // Git might not be initialized or no commits yet
63
+ return {};
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Extract commit message and file list from git state
69
+ * This function analyzes the actual git state to generate appropriate commit info
70
+ */
71
+ export async function extractCommitInfo(
72
+ taskId: string,
73
+ taskTitle: string,
74
+ executionMessage: string,
75
+ gitState: GitState,
76
+ execFn: (
77
+ command: string
78
+ ) => Promise<{ stdout: string; stderr: string }> = execAsync,
79
+ aiOps: any = getAIOperations()
80
+ ): Promise<CommitInfo> {
81
+ try {
82
+ // Case 1: Executor created a commit
83
+ if (gitState.beforeHead !== gitState.afterHead) {
84
+ logger.info("📝 Executor created a commit, extracting info...");
85
+ const { stdout } = await execFn(
86
+ `git show --stat --format="%s%n%b" ${gitState.afterHead}`
87
+ );
88
+
89
+ const lines = stdout.trim().split("\n");
90
+ const message = lines[0].trim();
91
+ // Parse files from stat output (e.g. " src/file.ts | 10 +")
92
+ const files = lines
93
+ .slice(1)
94
+ .filter((line) => line.includes("|"))
95
+ .map((line) => line.split("|")[0].trim());
96
+
97
+ return {
98
+ message,
99
+ files,
100
+ };
101
+ }
102
+
103
+ // Case 2: Executor left uncommitted changes
104
+ if (gitState.hasUncommittedChanges) {
105
+ logger.info(
106
+ "📝 Uncommitted changes detected, generating commit message..."
107
+ );
108
+
109
+ // Get the diff to send to AI
110
+ const { stdout: diff } = await execFn("git diff HEAD");
111
+
112
+ // Get list of changed files
113
+ const { stdout: status } = await execFn("git status --porcelain");
114
+ const files = status
115
+ .split("\n")
116
+ .filter((line) => line.length > 0)
117
+ .map((line) => line.substring(3).trim())
118
+ .filter((file) => file.length > 0);
119
+
120
+ // Use AI to generate commit message based on the diff
121
+ const prompt = `Based on the following git diff, generate a concise git commit message.
122
+
123
+ Task: ${taskTitle}
124
+
125
+ Git Diff:
126
+ ${diff.substring(0, 10000)} // Limit diff size
127
+
128
+ Please respond in JSON format:
129
+ {
130
+ "message": "concise commit message following conventional commits format"
131
+ }
132
+
133
+ The commit message should:
134
+ - Follow conventional commits format (feat:, fix:, refactor:, etc.)
135
+ - Be concise and descriptive
136
+ - Focus on what changed
137
+ `;
138
+
139
+ const response = await aiOps.streamText(
140
+ prompt,
141
+ undefined,
142
+ "You are a helpful assistant that generates git commit messages."
143
+ );
144
+
145
+ // Try to parse JSON from response
146
+ const jsonMatch = response.match(/\{[\s\S]*\}/);
147
+ let message = `feat: complete task ${taskTitle}`;
148
+
149
+ if (jsonMatch) {
150
+ try {
151
+ const parsed = JSON.parse(jsonMatch[0]);
152
+ if (parsed.message) {
153
+ message = parsed.message;
154
+ }
155
+ } catch (e) {
156
+ // Ignore parse error
157
+ }
158
+ }
159
+
160
+ return {
161
+ message,
162
+ files,
163
+ };
164
+ }
165
+
166
+ // Case 3: No changes detected
167
+ return {
168
+ message: `feat: complete task ${taskTitle}`,
169
+ files: [],
170
+ };
171
+ } catch (error) {
172
+ logger.warn(
173
+ `⚠️ Failed to extract commit info: ${
174
+ error instanceof Error ? error.message : "Unknown error"
175
+ }`
176
+ );
177
+ // Fallback commit info
178
+ return {
179
+ message: `feat: complete task ${taskTitle}`,
180
+ files: [],
181
+ };
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Auto-commit changes using the provided commit info
187
+ */
188
+ export async function autoCommit(
189
+ commitInfo: CommitInfo,
190
+ execFn: (
191
+ command: string
192
+ ) => Promise<{ stdout: string; stderr: string }> = execAsync
193
+ ): Promise<void> {
194
+ try {
195
+ const { message, files } = commitInfo;
196
+
197
+ if (files.length > 0) {
198
+ // Stage specific files
199
+ const gitAdd = `git add ${files.join(" ")}`;
200
+ logger.info(`📦 Staging files: ${gitAdd}`);
201
+ await execFn(gitAdd);
202
+ } else {
203
+ // Stage all changes
204
+ logger.info("📦 Staging all changes");
205
+ await execFn("git add .");
206
+ }
207
+
208
+ // Commit
209
+ const gitCommit = `git commit -m "${message}"`;
210
+ logger.info(`💾 Committing: ${message}`);
211
+ await execFn(gitCommit);
212
+
213
+ logger.success("✅ Changes committed successfully\n");
214
+ } catch (error) {
215
+ logger.warn(
216
+ `⚠️ Auto-commit failed: ${
217
+ error instanceof Error ? error.message : "Unknown error"
218
+ }\n`
219
+ );
220
+ }
221
+ }
222
+
223
+ /**
224
+ * Commit a specific file with a custom message
225
+ */
226
+ export async function commitFile(
227
+ filePath: string,
228
+ message: string,
229
+ execFn: (
230
+ command: string
231
+ ) => Promise<{ stdout: string; stderr: string }> = execAsync
232
+ ): Promise<void> {
233
+ try {
234
+ logger.info(`📦 Staging file: ${filePath}`);
235
+ await execFn(`git add ${filePath}`);
236
+ await execFn(`git commit -m "${message}"`);
237
+ logger.success("✅ File committed successfully");
238
+ } catch (e) {
239
+ logger.warn(
240
+ `⚠️ Failed to commit file: ${
241
+ e instanceof Error ? e.message : "Unknown error"
242
+ }`
243
+ );
244
+ }
245
+ }
246
+
247
+ // ============================================================================
248
+ // Benchmarking Git Utilities
249
+ // ============================================================================
250
+
251
+ /**
252
+ * Check if the working directory is clean
253
+ */
254
+ export async function isClean(
255
+ execFn: (
256
+ command: string
257
+ ) => Promise<{ stdout: string; stderr: string }> = execAsync
258
+ ): Promise<boolean> {
259
+ try {
260
+ const { stdout } = await execFn("git status --porcelain");
261
+ return stdout.trim().length === 0;
262
+ } catch (error) {
263
+ logger.warn("Could not check git status");
264
+ return false;
265
+ }
266
+ }
267
+
268
+ /**
269
+ * Get the current branch name
270
+ */
271
+ export async function getCurrentBranch(
272
+ execFn: (
273
+ command: string
274
+ ) => Promise<{ stdout: string; stderr: string }> = execAsync
275
+ ): Promise<string> {
276
+ try {
277
+ const { stdout } = await execFn("git rev-parse --abbrev-ref HEAD");
278
+ return stdout.trim();
279
+ } catch (error) {
280
+ throw new Error("Failed to get current branch");
281
+ }
282
+ }
283
+
284
+ /**
285
+ * Create a new branch for benchmarking
286
+ */
287
+ export async function createBenchmarkBranch(
288
+ name: string,
289
+ baseBranch: string = "HEAD",
290
+ execFn: (
291
+ command: string
292
+ ) => Promise<{ stdout: string; stderr: string }> = execAsync
293
+ ): Promise<void> {
294
+ try {
295
+ logger.info(`🌿 Creating benchmark branch: ${name} from ${baseBranch}`);
296
+ await execFn(`git checkout -b ${name} ${baseBranch}`);
297
+ } catch (error) {
298
+ throw new Error(`Failed to create benchmark branch ${name}: ${error}`);
299
+ }
300
+ }
301
+
302
+ /**
303
+ * Checkout an existing branch
304
+ */
305
+ export async function checkoutBranch(
306
+ name: string,
307
+ execFn: (
308
+ command: string
309
+ ) => Promise<{ stdout: string; stderr: string }> = execAsync
310
+ ): Promise<void> {
311
+ try {
312
+ logger.info(`🌿 Checking out branch: ${name}`);
313
+ await execFn(`git checkout ${name}`);
314
+ } catch (error) {
315
+ throw new Error(`Failed to checkout branch ${name}: ${error}`);
316
+ }
317
+ }
318
+
319
+ /**
320
+ * Delete a benchmark branch (force delete)
321
+ */
322
+ export async function cleanupBenchmarkBranch(
323
+ name: string,
324
+ execFn: (
325
+ command: string
326
+ ) => Promise<{ stdout: string; stderr: string }> = execAsync
327
+ ): Promise<void> {
328
+ try {
329
+ logger.info(`🗑️ Deleting benchmark branch: ${name}`);
330
+ await execFn(`git branch -D ${name}`);
331
+ } catch (error) {
332
+ logger.warn(`Failed to delete branch ${name}: ${error}`);
333
+ }
334
+ }
@@ -0,0 +1,121 @@
1
+ import { Task } from "../types";
2
+
3
+ // Define all possible event types
4
+ export type TaskEventType =
5
+ | "task:created"
6
+ | "task:updated"
7
+ | "task:deleted"
8
+ | "task:status-changed"
9
+ | "task:progress"
10
+ | "execution:start"
11
+ | "execution:end"
12
+ | "execution:error"
13
+ | "log:info"
14
+ | "log:warn"
15
+ | "log:error"
16
+ | "log:success"
17
+ | "log:progress";
18
+
19
+ // Log event payload
20
+ export interface LogEventPayload {
21
+ message: string;
22
+ context?: Record<string, unknown>;
23
+ }
24
+
25
+ // Define payload types for each event
26
+ export interface TaskEventPayloads {
27
+ "task:created": { task: Task };
28
+ "task:updated": { task: Task; changes: Partial<Task> };
29
+ "task:deleted": { taskId: string };
30
+ "task:status-changed": { task: Task; oldStatus: string; newStatus: string };
31
+ "task:progress": { taskId?: string; message: string; type?: string };
32
+ "execution:start": { taskId: string; tool: string };
33
+ "execution:end": { taskId: string; success: boolean };
34
+ "execution:error": { taskId: string; error: Error };
35
+ "log:info": LogEventPayload;
36
+ "log:warn": LogEventPayload;
37
+ "log:error": LogEventPayload;
38
+ "log:success": LogEventPayload;
39
+ "log:progress": LogEventPayload;
40
+ }
41
+
42
+ // Type for the event handler function
43
+ export type TaskEventHandler<T extends TaskEventType> = (
44
+ payload: TaskEventPayloads[T]
45
+ ) => Promise<void> | void;
46
+
47
+ class HookRegistry {
48
+ private static instance: HookRegistry;
49
+ private listeners: Map<TaskEventType, Set<TaskEventHandler<any>>>;
50
+
51
+ private constructor() {
52
+ this.listeners = new Map();
53
+ }
54
+
55
+ public static getInstance(): HookRegistry {
56
+ if (!HookRegistry.instance) {
57
+ HookRegistry.instance = new HookRegistry();
58
+ }
59
+ return HookRegistry.instance;
60
+ }
61
+
62
+ /**
63
+ * Register a handler for a specific event type
64
+ */
65
+ public on<T extends TaskEventType>(
66
+ type: T,
67
+ handler: TaskEventHandler<T>
68
+ ): void {
69
+ if (!this.listeners.has(type)) {
70
+ this.listeners.set(type, new Set());
71
+ }
72
+ this.listeners.get(type)!.add(handler);
73
+ }
74
+
75
+ /**
76
+ * Remove a handler
77
+ */
78
+ public off<T extends TaskEventType>(
79
+ type: T,
80
+ handler: TaskEventHandler<T>
81
+ ): void {
82
+ const handlers = this.listeners.get(type);
83
+ if (handlers) {
84
+ handlers.delete(handler);
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Emit an event to all registered handlers
90
+ * We don't await handlers to prevent blocking the main flow,
91
+ * but we catch errors to prevent crashes.
92
+ */
93
+ public async emit<T extends TaskEventType>(
94
+ type: T,
95
+ payload: TaskEventPayloads[T]
96
+ ): Promise<void> {
97
+ const handlers = this.listeners.get(type);
98
+ if (!handlers || handlers.size === 0) return;
99
+
100
+ const promises = Array.from(handlers).map(async (handler) => {
101
+ try {
102
+ await handler(payload);
103
+ } catch (error) {
104
+ // NOTE: Using console.error here intentionally - this is the hooks system
105
+ // that the logger depends on, so we can't use logger here (circular dependency)
106
+ console.error(`Error in hook handler for event ${type}:`, error);
107
+ }
108
+ });
109
+
110
+ await Promise.all(promises);
111
+ }
112
+
113
+ /**
114
+ * Clear all listeners (useful for testing)
115
+ */
116
+ public clear(): void {
117
+ this.listeners.clear();
118
+ }
119
+ }
120
+
121
+ export const hooks = HookRegistry.getInstance();