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,383 @@
1
+ import { join } from "path";
2
+ import { Task, TaskContext, BTSConfig, TaskDocumentation } from "../types";
3
+ import { TaskRepository } from "./storage/types";
4
+ import { configManager } from "./config";
5
+ import { readFileSync, existsSync, readdirSync, statSync } from "fs";
6
+ import { logger } from "./logger";
7
+
8
+ export interface FileStats {
9
+ mtime: number;
10
+ isDirectory: boolean;
11
+ }
12
+
13
+ export interface ContextCallbacks {
14
+ readFile: (path: string) => Promise<string | null>;
15
+ fileExists: (path: string) => Promise<boolean>;
16
+ listFiles: (dir: string) => Promise<string[]>;
17
+ stat: (path: string) => Promise<FileStats | null>;
18
+ }
19
+
20
+ export function createDefaultContextCallbacks(): ContextCallbacks {
21
+ return {
22
+ readFile: async (path: string) => {
23
+ if (existsSync(path)) {
24
+ return readFileSync(path, "utf-8");
25
+ }
26
+ return null;
27
+ },
28
+ fileExists: async (path: string) => {
29
+ return existsSync(path);
30
+ },
31
+ listFiles: async (dir: string) => {
32
+ if (existsSync(dir) && statSync(dir).isDirectory()) {
33
+ return readdirSync(dir);
34
+ }
35
+ return [];
36
+ },
37
+ stat: async (path: string) => {
38
+ if (existsSync(path)) {
39
+ const stats = statSync(path);
40
+ return {
41
+ mtime: stats.mtime.getTime(),
42
+ isDirectory: stats.isDirectory(),
43
+ };
44
+ }
45
+ return null;
46
+ },
47
+ };
48
+ }
49
+
50
+ export class ContextBuilder {
51
+ private storage: TaskRepository;
52
+ private callbacks: ContextCallbacks;
53
+ private taskOMatic: string | null = null;
54
+ private initialized = false;
55
+
56
+ constructor(storage: TaskRepository, callbacks?: ContextCallbacks) {
57
+ this.storage = storage;
58
+ this.callbacks = callbacks || createDefaultContextCallbacks();
59
+ }
60
+
61
+ private ensureInitialized(): void {
62
+ if (this.initialized) {
63
+ return;
64
+ }
65
+
66
+ this.taskOMatic = configManager.getTaskOMaticDir();
67
+ this.initialized = true;
68
+ }
69
+
70
+ /**
71
+ * Build comprehensive context for AI operations
72
+ */
73
+ async buildContext(taskId: string): Promise<TaskContext> {
74
+ this.ensureInitialized();
75
+
76
+ const task = await this.storage.getTask(taskId);
77
+ if (!task) {
78
+ throw new Error(`Task with ID ${taskId} not found`);
79
+ }
80
+
81
+ const stack = await this.getStackConfig();
82
+ const documentation = this.getTaskDocumentation(task);
83
+ const fullContent = await this.getTaskFullContent(task);
84
+ const prdContent = task.prdFile
85
+ ? await this.getPRDContent(task.prdFile)
86
+ : await this.getRelevantPRDContent(task.title, task.description);
87
+
88
+ return {
89
+ task: {
90
+ id: task.id,
91
+ title: task.title,
92
+ description: task.description ?? "",
93
+ fullContent,
94
+ },
95
+ stack,
96
+ documentation: documentation
97
+ ? {
98
+ recap: documentation.recap,
99
+ files: documentation.files.map((file) => ({
100
+ path: file,
101
+ // Content loading is skipped as per original code comment
102
+ })),
103
+ }
104
+ : undefined,
105
+ existingContent: documentation?.recap,
106
+ prdContent,
107
+ existingResearch: documentation?.research || {},
108
+ };
109
+ }
110
+
111
+ /**
112
+ * Build context for new tasks (without requiring existing task)
113
+ */
114
+ async buildContextForNewTask(
115
+ title: string,
116
+ description?: string,
117
+ prdFile?: string
118
+ ): Promise<TaskContext> {
119
+ this.ensureInitialized();
120
+
121
+ const stack = await this.getStackConfig();
122
+ const prdContent = prdFile
123
+ ? await this.getPRDContent(prdFile)
124
+ : await this.getRelevantPRDContent(title, description);
125
+
126
+ return {
127
+ task: {
128
+ id: "new-task",
129
+ title,
130
+ description: description ?? "",
131
+ fullContent: undefined,
132
+ },
133
+ stack,
134
+ documentation: undefined, // New tasks don't have documentation yet
135
+ existingContent: undefined,
136
+ prdContent,
137
+ };
138
+ }
139
+
140
+ /**
141
+ * Get stack configuration from project (set by bootstrap)
142
+ */
143
+ private async getStackConfig(): Promise<BTSConfig | undefined> {
144
+ if (!this.taskOMatic) {
145
+ return undefined;
146
+ }
147
+
148
+ // Return sensible defaults for Better-T-Stack
149
+ const fallbackConfig: BTSConfig = {
150
+ projectName: "default",
151
+ frontend: "next",
152
+ backend: "convex",
153
+ database: "none", // Convex has its own database
154
+ auth: "better-auth",
155
+ runtime: "none",
156
+ api: "none",
157
+ payments: "none",
158
+ orm: "none", // Convex doesn't use ORM
159
+ dbSetup: "none",
160
+ packageManager: "npm",
161
+ git: true,
162
+ webDeploy: "none",
163
+ serverDeploy: "none",
164
+ install: true,
165
+ addons: ["turborepo"],
166
+ examples: [],
167
+ };
168
+ try {
169
+ const stackFile = join(this.taskOMatic, "stack.json");
170
+ const content = await this.callbacks.readFile(stackFile);
171
+
172
+ if (content) {
173
+ const config = JSON.parse(content) as BTSConfig;
174
+ config._source = "file"; // Track source
175
+ return config;
176
+ }
177
+ fallbackConfig._source = "fallback"; // Track source
178
+ return fallbackConfig;
179
+ } catch (error) {
180
+ logger.warn(
181
+ `Failed to load stack configuration, using defaults: ${error}`
182
+ );
183
+ fallbackConfig._source = "fallback"; // Track source
184
+ return fallbackConfig;
185
+ }
186
+ }
187
+
188
+ /**
189
+ * Get task documentation references
190
+ */
191
+ private getTaskDocumentation(task: Task): TaskDocumentation | undefined {
192
+ return task.documentation;
193
+ }
194
+
195
+ /**
196
+ * Get full task content from MD file
197
+ */
198
+ private async getTaskFullContent(task: Task): Promise<string | undefined> {
199
+ if (!task.contentFile || !this.taskOMatic) {
200
+ return undefined;
201
+ }
202
+
203
+ try {
204
+ const contentPath = join(this.taskOMatic, task.contentFile);
205
+ return (await this.callbacks.readFile(contentPath)) || undefined;
206
+ } catch (error) {
207
+ logger.warn(
208
+ `Failed to read task content file ${task.contentFile}: ${error}`
209
+ );
210
+ }
211
+ return undefined;
212
+ }
213
+
214
+ /**
215
+ * Read documentation file content
216
+ */
217
+ private async readDocumentationFile(filePath: string): Promise<string> {
218
+ if (!this.taskOMatic) {
219
+ return `# ContextBuilder Not Initialized\n\nFile: ${filePath}\n\nContextBuilder has not been properly initialized.`;
220
+ }
221
+
222
+ try {
223
+ const fullPath = join(this.taskOMatic, filePath);
224
+ const content = await this.callbacks.readFile(fullPath);
225
+ if (content) {
226
+ return content;
227
+ }
228
+ return `# Documentation File Not Found\n\nFile: ${filePath}\n\nThis documentation file could not be found on disk.`;
229
+ } catch (error) {
230
+ return `# Error Reading Documentation\n\nFile: ${filePath}\n\nError: ${
231
+ error instanceof Error ? error.message : "Unknown error"
232
+ }`;
233
+ }
234
+ }
235
+
236
+ /**
237
+ * Check if documentation is fresh (less than 7 days old)
238
+ */
239
+ isDocumentationFresh(documentation: TaskDocumentation): boolean {
240
+ const sevenDaysAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;
241
+ return documentation.lastFetched > sevenDaysAgo;
242
+ }
243
+
244
+ /**
245
+ * Check if documentation is stale (more than 30 days old)
246
+ */
247
+ isDocumentationStale(documentation: TaskDocumentation): boolean {
248
+ const thirtyDaysAgo = Date.now() - 30 * 24 * 60 * 60 * 1000;
249
+ return documentation.lastFetched < thirtyDaysAgo;
250
+ }
251
+
252
+ /**
253
+ * Get PRD content from file path
254
+ */
255
+ private async getPRDContent(prdFile: string): Promise<string | undefined> {
256
+ if (!this.taskOMatic) {
257
+ return undefined;
258
+ }
259
+
260
+ try {
261
+ // Handle relative paths from .task-o-matic directory
262
+ const fullPath = prdFile.startsWith("/")
263
+ ? prdFile
264
+ : join(this.taskOMatic, prdFile);
265
+
266
+ return (await this.callbacks.readFile(fullPath)) || undefined;
267
+ } catch (error) {
268
+ logger.warn(`Failed to read PRD file ${prdFile}: ${error}`);
269
+ return undefined;
270
+ }
271
+ }
272
+
273
+ /**
274
+ * Get relevant PRD content based on task title/description
275
+ */
276
+ private async getRelevantPRDContent(
277
+ taskTitle?: string,
278
+ taskDescription?: string
279
+ ): Promise<string | undefined> {
280
+ if (!this.taskOMatic) return undefined;
281
+
282
+ // Look for PRD files in known locations
283
+ const prdPaths = [
284
+ join(this.taskOMatic, "prd"),
285
+ join(this.taskOMatic, "..", "docs"),
286
+ join(configManager.getWorkingDirectory(), ".task-o-matic", "prd"),
287
+ join(configManager.getWorkingDirectory(), "prd"),
288
+ join(configManager.getWorkingDirectory(), "docs"),
289
+ ];
290
+
291
+ for (const prdPath of prdPaths) {
292
+ if (await this.callbacks.fileExists(prdPath)) {
293
+ try {
294
+ // Look for ANY text files in PRD directory
295
+ const files = await this.callbacks.listFiles(prdPath);
296
+ const prdFiles = files.filter(
297
+ (f) => f.endsWith(".md") || f.endsWith(".txt")
298
+ );
299
+
300
+ if (prdFiles.length > 0) {
301
+ // Get the MOST RECENT PRD file by modification time
302
+ const prdFilesWithStats = await Promise.all(
303
+ prdFiles.map(async (file) => {
304
+ const path = join(prdPath, file);
305
+ const stats = await this.callbacks.stat(path);
306
+ return {
307
+ file,
308
+ path,
309
+ mtime: stats ? stats.mtime : 0,
310
+ };
311
+ })
312
+ );
313
+
314
+ prdFilesWithStats.sort((a, b) => b.mtime - a.mtime); // Sort by newest first
315
+ const mostRecentPrd = prdFilesWithStats[0];
316
+ return (
317
+ (await this.callbacks.readFile(mostRecentPrd.path)) || undefined
318
+ );
319
+ }
320
+ } catch (error) {
321
+ logger.warn(`Failed to read PRD directory ${prdPath}: ${error}`);
322
+ }
323
+ }
324
+ }
325
+
326
+ return undefined;
327
+ }
328
+
329
+ /**
330
+ * Format context for AI prompts
331
+ */
332
+ formatContextForAI(context: TaskContext): string {
333
+ let formatted = `# Task Context\n\n`;
334
+
335
+ formatted += `## Task Information\n`;
336
+ formatted += `- **ID**: ${context.task.id}\n`;
337
+ formatted += `- **Title**: ${context.task.title}\n`;
338
+ formatted += `- **Description**: ${context.task.description}\n`;
339
+
340
+ if (context.task.fullContent) {
341
+ formatted += `- **Full Content**:\n${context.task.fullContent}\n\n`;
342
+ }
343
+
344
+ if (context.prdContent) {
345
+ formatted += `## Product Requirements Document\n`;
346
+ formatted += `${context.prdContent}\n\n`;
347
+ }
348
+
349
+ if (context.stack) {
350
+ formatted += `## Technology Stack\n`;
351
+ formatted += `- **Project**: ${context.stack.projectName}\n`;
352
+ formatted += `- **Frontend**: ${context.stack.frontend}\n`;
353
+ formatted += `- **Backend**: ${context.stack.backend}\n`;
354
+ if (context.stack.database !== "none") {
355
+ formatted += `- **Database**: ${context.stack.database}\n`;
356
+ }
357
+ if (context.stack.orm !== "none") {
358
+ formatted += `- **ORM**: ${context.stack.orm}\n`;
359
+ }
360
+ formatted += `- **Auth**: ${context.stack.auth}\n`;
361
+ if (context.stack.addons.length > 0) {
362
+ formatted += `- **Addons**: ${context.stack.addons.join(", ")}\n`;
363
+ }
364
+ formatted += `- **Package Manager**: ${context.stack.packageManager}\n`;
365
+ formatted += `\n`;
366
+ }
367
+
368
+ if (context.documentation) {
369
+ formatted += `## Available Documentation\n`;
370
+ formatted += `**Recap**: ${context.documentation.recap}\n\n`;
371
+
372
+ if (context.documentation.files.length > 0) {
373
+ formatted += `### Documentation Files\n\n`;
374
+ context.documentation.files.forEach((file, index) => {
375
+ formatted += `#### ${index + 1}. ${file.path}\n`;
376
+ // formatted += `${file.content}\n\n`;
377
+ });
378
+ }
379
+ }
380
+
381
+ return formatted;
382
+ }
383
+ }
@@ -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 ClaudeCodeExecutor implements ExternalExecutor {
7
+ name = "claude";
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("--model", 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("-r", finalConfig.sessionId);
41
+ logger.progress(`🔄 Resuming session: ${finalConfig.sessionId}`);
42
+ }
43
+
44
+ // Add --print for non-interactive mode (required for automation)
45
+ // args.push("-p");
46
+
47
+ // Auto-approve file edits for automation
48
+ args.push("--permission-mode", "acceptEdits");
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(`claude ${args.join(" ")}`);
56
+ return;
57
+ }
58
+
59
+ // Launch claude and wait for it to complete
60
+ const child = spawn("claude", 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("✅ Claude Code execution completed successfully");
69
+ resolve();
70
+ } else {
71
+ const error = new Error(`Claude 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 Claude Code: ${error.message}`);
79
+ reject(error);
80
+ });
81
+ });
82
+ }
83
+ }
@@ -0,0 +1,85 @@
1
+ import { spawn } from "node:child_process";
2
+
3
+ import type { ExecutorConfig, ExternalExecutor } from "../../types";
4
+ import { logger } from "../logger";
5
+
6
+ export class CodexExecutor implements ExternalExecutor {
7
+ name = "codex";
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 - structure depends on session resumption
27
+ const args: string[] = [];
28
+
29
+ // Add model via config if specified (codex uses -c for config overrides)
30
+ if (finalConfig.model) {
31
+ args.push("-c", `model="${finalConfig.model}"`);
32
+ logger.progress(`🤖 Using model: ${finalConfig.model}`);
33
+ }
34
+
35
+ // Session resumption uses different subcommand
36
+ if (finalConfig.continueLastSession) {
37
+ // Use 'exec resume --last' subcommand
38
+ args.push("exec", "resume", "--last");
39
+ logger.progress("🔄 Continuing last session");
40
+ } else if (finalConfig.sessionId) {
41
+ // Use 'exec resume <session-id>' subcommand
42
+ args.push("exec", "resume", finalConfig.sessionId);
43
+ logger.progress(`🔄 Resuming session: ${finalConfig.sessionId}`);
44
+ } else {
45
+ // Normal execution
46
+ args.push("exec");
47
+ }
48
+
49
+ // Add full write access for automation
50
+ args.push("--sandbox", "workspace-write");
51
+
52
+ // Add prompt as positional argument
53
+ args.push(message);
54
+
55
+ if (dry) {
56
+ logger.progress(`🔧 Using executor: ${this.name}`);
57
+ logger.progress(`codex ${args.join(" ")}`);
58
+ return;
59
+ }
60
+
61
+ // Launch codex and wait for it to complete
62
+ const child = spawn("codex", args, {
63
+ stdio: "inherit", // Give tool full terminal control
64
+ });
65
+
66
+ // Wait for completion (blocking)
67
+ await new Promise<void>((resolve, reject) => {
68
+ child.on("close", (code: number) => {
69
+ if (code === 0) {
70
+ logger.success("✅ Codex CLI execution completed successfully");
71
+ resolve();
72
+ } else {
73
+ const error = new Error(`Codex CLI exited with code ${code}`);
74
+ logger.error(`❌ ${error.message}`);
75
+ reject(error);
76
+ }
77
+ });
78
+
79
+ child.on("error", (error: Error) => {
80
+ logger.error(`❌ Failed to launch Codex CLI: ${error.message}`);
81
+ reject(error);
82
+ });
83
+ });
84
+ }
85
+ }
@@ -0,0 +1,28 @@
1
+ import { ExternalExecutor, ExecutorTool, ExecutorConfig } from "../../types";
2
+ import { OpencodeExecutor } from "./opencode-executor";
3
+ import { ClaudeCodeExecutor } from "./claude-code-executor";
4
+ import { GeminiExecutor } from "./gemini-executor";
5
+ import { CodexExecutor } from "./codex-executor";
6
+ import { KiloExecutor } from "./kilo-executor";
7
+
8
+ export class ExecutorFactory {
9
+ static create(
10
+ tool: ExecutorTool = "opencode",
11
+ config?: ExecutorConfig
12
+ ): ExternalExecutor {
13
+ switch (tool) {
14
+ case "opencode":
15
+ return new OpencodeExecutor(config);
16
+ case "claude":
17
+ return new ClaudeCodeExecutor(config);
18
+ case "gemini":
19
+ return new GeminiExecutor(config);
20
+ case "codex":
21
+ return new CodexExecutor(config);
22
+ case "kilo":
23
+ return new KiloExecutor(config);
24
+ default:
25
+ throw new Error(`Unknown executor tool: ${tool}`);
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,80 @@
1
+ import { spawn } from "node:child_process";
2
+
3
+ import type { ExecutorConfig, ExternalExecutor } from "../../types";
4
+ import { logger } from "../logger";
5
+
6
+ export class GeminiExecutor implements ExternalExecutor {
7
+ name = "gemini";
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("-r", "latest");
38
+ logger.progress("🔄 Continuing last session");
39
+ } else if (finalConfig.sessionId) {
40
+ args.push("-r", finalConfig.sessionId);
41
+ logger.progress(`🔄 Resuming session: ${finalConfig.sessionId}`);
42
+ }
43
+
44
+ // Enable auto-approval of all tools (yolo mode) - required for file writes
45
+ args.push("--yolo");
46
+
47
+ // Add prompt as positional argument (the -p flag is deprecated)
48
+ args.push(message);
49
+
50
+ if (dry) {
51
+ logger.progress(`🔧 Using executor: ${this.name}`);
52
+ logger.progress(`gemini ${args.join(" ")}`);
53
+ return;
54
+ }
55
+
56
+ // Launch gemini and wait for it to complete
57
+ const child = spawn("gemini", args, {
58
+ stdio: "inherit", // Give tool full terminal control
59
+ });
60
+
61
+ // Wait for completion (blocking)
62
+ await new Promise<void>((resolve, reject) => {
63
+ child.on("close", (code: number) => {
64
+ if (code === 0) {
65
+ logger.success("✅ Gemini CLI execution completed successfully");
66
+ resolve();
67
+ } else {
68
+ const error = new Error(`Gemini CLI exited with code ${code}`);
69
+ logger.error(`❌ ${error.message}`);
70
+ reject(error);
71
+ }
72
+ });
73
+
74
+ child.on("error", (error: Error) => {
75
+ logger.error(`❌ Failed to launch Gemini CLI: ${error.message}`);
76
+ reject(error);
77
+ });
78
+ });
79
+ }
80
+ }