@ai-coders/context 0.3.1 → 0.5.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 (514) hide show
  1. package/README.md +269 -29
  2. package/dist/fragments/compose.d.ts +30 -0
  3. package/dist/fragments/compose.d.ts.map +1 -0
  4. package/dist/fragments/compose.js +274 -0
  5. package/dist/fragments/compose.js.map +1 -0
  6. package/dist/fragments/extractors/index.d.ts +26 -0
  7. package/dist/fragments/extractors/index.d.ts.map +1 -0
  8. package/dist/fragments/extractors/index.js +58 -0
  9. package/dist/fragments/extractors/index.js.map +1 -0
  10. package/dist/fragments/extractors/module.d.ts +12 -0
  11. package/dist/fragments/extractors/module.d.ts.map +1 -0
  12. package/dist/fragments/extractors/module.js +302 -0
  13. package/dist/fragments/extractors/module.js.map +1 -0
  14. package/dist/fragments/extractors/project.d.ts +12 -0
  15. package/dist/fragments/extractors/project.d.ts.map +1 -0
  16. package/dist/fragments/extractors/project.js +274 -0
  17. package/dist/fragments/extractors/project.js.map +1 -0
  18. package/dist/fragments/extractors/semantic.d.ts +12 -0
  19. package/dist/fragments/extractors/semantic.d.ts.map +1 -0
  20. package/dist/fragments/extractors/semantic.js +329 -0
  21. package/dist/fragments/extractors/semantic.js.map +1 -0
  22. package/dist/fragments/index.d.ts +47 -0
  23. package/dist/fragments/index.d.ts.map +1 -0
  24. package/dist/fragments/index.js +75 -0
  25. package/dist/fragments/index.js.map +1 -0
  26. package/dist/fragments/query.d.ts +101 -0
  27. package/dist/fragments/query.d.ts.map +1 -0
  28. package/dist/fragments/query.js +200 -0
  29. package/dist/fragments/query.js.map +1 -0
  30. package/dist/fragments/render/compact.d.ts +15 -0
  31. package/dist/fragments/render/compact.d.ts.map +1 -0
  32. package/dist/fragments/render/compact.js +209 -0
  33. package/dist/fragments/render/compact.js.map +1 -0
  34. package/dist/fragments/render/index.d.ts +17 -0
  35. package/dist/fragments/render/index.d.ts.map +1 -0
  36. package/dist/fragments/render/index.js +40 -0
  37. package/dist/fragments/render/index.js.map +1 -0
  38. package/dist/fragments/render/json.d.ts +9 -0
  39. package/dist/fragments/render/json.d.ts.map +1 -0
  40. package/dist/fragments/render/json.js +44 -0
  41. package/dist/fragments/render/json.js.map +1 -0
  42. package/dist/fragments/render/markdown.d.ts +9 -0
  43. package/dist/fragments/render/markdown.d.ts.map +1 -0
  44. package/dist/fragments/render/markdown.js +291 -0
  45. package/dist/fragments/render/markdown.js.map +1 -0
  46. package/dist/fragments/store.d.ts +49 -0
  47. package/dist/fragments/store.d.ts.map +1 -0
  48. package/dist/fragments/store.js +161 -0
  49. package/dist/fragments/store.js.map +1 -0
  50. package/dist/fragments/types.d.ts +241 -0
  51. package/dist/fragments/types.d.ts.map +1 -0
  52. package/dist/fragments/types.js +8 -0
  53. package/dist/fragments/types.js.map +1 -0
  54. package/dist/generators/agents/agentConfig.d.ts.map +1 -1
  55. package/dist/generators/agents/agentConfig.js +42 -0
  56. package/dist/generators/agents/agentConfig.js.map +1 -1
  57. package/dist/generators/agents/agentGenerator.d.ts +8 -2
  58. package/dist/generators/agents/agentGenerator.d.ts.map +1 -1
  59. package/dist/generators/agents/agentGenerator.js +112 -54
  60. package/dist/generators/agents/agentGenerator.js.map +1 -1
  61. package/dist/generators/agents/agentTypes.d.ts +1 -1
  62. package/dist/generators/agents/agentTypes.d.ts.map +1 -1
  63. package/dist/generators/agents/agentTypes.js +4 -1
  64. package/dist/generators/agents/agentTypes.js.map +1 -1
  65. package/dist/generators/agents/templates/indexTemplate.d.ts.map +1 -1
  66. package/dist/generators/agents/templates/indexTemplate.js +2 -1
  67. package/dist/generators/agents/templates/indexTemplate.js.map +1 -1
  68. package/dist/generators/agents/templates/playbookTemplate.d.ts +3 -2
  69. package/dist/generators/agents/templates/playbookTemplate.d.ts.map +1 -1
  70. package/dist/generators/agents/templates/playbookTemplate.js +144 -10
  71. package/dist/generators/agents/templates/playbookTemplate.js.map +1 -1
  72. package/dist/generators/agents/templates/types.d.ts +9 -1
  73. package/dist/generators/agents/templates/types.d.ts.map +1 -1
  74. package/dist/generators/documentation/documentationGenerator.d.ts +5 -1
  75. package/dist/generators/documentation/documentationGenerator.d.ts.map +1 -1
  76. package/dist/generators/documentation/documentationGenerator.js +106 -18
  77. package/dist/generators/documentation/documentationGenerator.js.map +1 -1
  78. package/dist/generators/documentation/guideRegistry.d.ts.map +1 -1
  79. package/dist/generators/documentation/guideRegistry.js +0 -8
  80. package/dist/generators/documentation/guideRegistry.js.map +1 -1
  81. package/dist/generators/documentation/templates/apiReferenceTemplate.d.ts +2 -0
  82. package/dist/generators/documentation/templates/apiReferenceTemplate.d.ts.map +1 -0
  83. package/dist/generators/documentation/templates/apiReferenceTemplate.js +469 -0
  84. package/dist/generators/documentation/templates/apiReferenceTemplate.js.map +1 -0
  85. package/dist/generators/documentation/templates/architectureTemplate.d.ts.map +1 -1
  86. package/dist/generators/documentation/templates/architectureTemplate.js +175 -41
  87. package/dist/generators/documentation/templates/architectureTemplate.js.map +1 -1
  88. package/dist/generators/documentation/templates/common.d.ts +28 -1
  89. package/dist/generators/documentation/templates/common.d.ts.map +1 -1
  90. package/dist/generators/documentation/templates/common.js +130 -10
  91. package/dist/generators/documentation/templates/common.js.map +1 -1
  92. package/dist/generators/documentation/templates/dataFlowTemplate.d.ts.map +1 -1
  93. package/dist/generators/documentation/templates/dataFlowTemplate.js +98 -33
  94. package/dist/generators/documentation/templates/dataFlowTemplate.js.map +1 -1
  95. package/dist/generators/documentation/templates/developmentWorkflowTemplate.d.ts.map +1 -1
  96. package/dist/generators/documentation/templates/developmentWorkflowTemplate.js +2 -34
  97. package/dist/generators/documentation/templates/developmentWorkflowTemplate.js.map +1 -1
  98. package/dist/generators/documentation/templates/glossaryTemplate.d.ts +1 -1
  99. package/dist/generators/documentation/templates/glossaryTemplate.d.ts.map +1 -1
  100. package/dist/generators/documentation/templates/glossaryTemplate.js +51 -37
  101. package/dist/generators/documentation/templates/glossaryTemplate.js.map +1 -1
  102. package/dist/generators/documentation/templates/index.d.ts +4 -0
  103. package/dist/generators/documentation/templates/index.d.ts.map +1 -1
  104. package/dist/generators/documentation/templates/index.js +9 -1
  105. package/dist/generators/documentation/templates/index.js.map +1 -1
  106. package/dist/generators/documentation/templates/indexTemplate.d.ts.map +1 -1
  107. package/dist/generators/documentation/templates/indexTemplate.js +1 -32
  108. package/dist/generators/documentation/templates/indexTemplate.js.map +1 -1
  109. package/dist/generators/documentation/templates/migrationTemplate.d.ts +2 -0
  110. package/dist/generators/documentation/templates/migrationTemplate.d.ts.map +1 -0
  111. package/dist/generators/documentation/templates/migrationTemplate.js +400 -0
  112. package/dist/generators/documentation/templates/migrationTemplate.js.map +1 -0
  113. package/dist/generators/documentation/templates/onboardingTemplate.d.ts +2 -0
  114. package/dist/generators/documentation/templates/onboardingTemplate.d.ts.map +1 -0
  115. package/dist/generators/documentation/templates/onboardingTemplate.js +409 -0
  116. package/dist/generators/documentation/templates/onboardingTemplate.js.map +1 -0
  117. package/dist/generators/documentation/templates/projectOverviewTemplate.d.ts.map +1 -1
  118. package/dist/generators/documentation/templates/projectOverviewTemplate.js +97 -38
  119. package/dist/generators/documentation/templates/projectOverviewTemplate.js.map +1 -1
  120. package/dist/generators/documentation/templates/securityTemplate.d.ts.map +1 -1
  121. package/dist/generators/documentation/templates/securityTemplate.js +1 -32
  122. package/dist/generators/documentation/templates/securityTemplate.js.map +1 -1
  123. package/dist/generators/documentation/templates/testingTemplate.d.ts.map +1 -1
  124. package/dist/generators/documentation/templates/testingTemplate.js +1 -33
  125. package/dist/generators/documentation/templates/testingTemplate.js.map +1 -1
  126. package/dist/generators/documentation/templates/toolingTemplate.d.ts.map +1 -1
  127. package/dist/generators/documentation/templates/toolingTemplate.js +2 -33
  128. package/dist/generators/documentation/templates/toolingTemplate.js.map +1 -1
  129. package/dist/generators/documentation/templates/troubleshootingTemplate.d.ts +2 -0
  130. package/dist/generators/documentation/templates/troubleshootingTemplate.d.ts.map +1 -0
  131. package/dist/generators/documentation/templates/troubleshootingTemplate.js +270 -0
  132. package/dist/generators/documentation/templates/troubleshootingTemplate.js.map +1 -0
  133. package/dist/generators/documentation/templates/types.d.ts +2 -1
  134. package/dist/generators/documentation/templates/types.d.ts.map +1 -1
  135. package/dist/generators/plans/planGenerator.d.ts +4 -0
  136. package/dist/generators/plans/planGenerator.d.ts.map +1 -1
  137. package/dist/generators/plans/planGenerator.js +30 -2
  138. package/dist/generators/plans/planGenerator.js.map +1 -1
  139. package/dist/generators/plans/templates/indexTemplate.d.ts.map +1 -1
  140. package/dist/generators/plans/templates/indexTemplate.js +5 -13
  141. package/dist/generators/plans/templates/indexTemplate.js.map +1 -1
  142. package/dist/generators/plans/templates/planTemplate.d.ts.map +1 -1
  143. package/dist/generators/plans/templates/planTemplate.js +123 -30
  144. package/dist/generators/plans/templates/planTemplate.js.map +1 -1
  145. package/dist/generators/plans/templates/types.d.ts +10 -0
  146. package/dist/generators/plans/templates/types.d.ts.map +1 -1
  147. package/dist/generators/shared/generatorUtils.d.ts +1 -1
  148. package/dist/generators/shared/generatorUtils.d.ts.map +1 -1
  149. package/dist/generators/shared/generatorUtils.js +7 -10
  150. package/dist/generators/shared/generatorUtils.js.map +1 -1
  151. package/dist/index.d.ts +2 -2
  152. package/dist/index.d.ts.map +1 -1
  153. package/dist/index.js +459 -1073
  154. package/dist/index.js.map +1 -1
  155. package/dist/prompts/defaults.d.ts +2 -2
  156. package/dist/prompts/defaults.d.ts.map +1 -1
  157. package/dist/prompts/defaults.js +26 -56
  158. package/dist/prompts/defaults.js.map +1 -1
  159. package/dist/services/ai/agentEvents.d.ts +45 -0
  160. package/dist/services/ai/agentEvents.d.ts.map +1 -0
  161. package/dist/services/ai/agentEvents.js +61 -0
  162. package/dist/services/ai/agentEvents.js.map +1 -0
  163. package/dist/services/ai/agents/documentationAgent.d.ts +53 -0
  164. package/dist/services/ai/agents/documentationAgent.d.ts.map +1 -0
  165. package/dist/services/ai/agents/documentationAgent.js +243 -0
  166. package/dist/services/ai/agents/documentationAgent.js.map +1 -0
  167. package/dist/services/ai/agents/index.d.ts +7 -0
  168. package/dist/services/ai/agents/index.d.ts.map +1 -0
  169. package/dist/services/ai/agents/index.js +10 -0
  170. package/dist/services/ai/agents/index.js.map +1 -0
  171. package/dist/services/ai/agents/planAgent.d.ts +68 -0
  172. package/dist/services/ai/agents/planAgent.d.ts.map +1 -0
  173. package/dist/services/ai/agents/planAgent.js +389 -0
  174. package/dist/services/ai/agents/planAgent.js.map +1 -0
  175. package/dist/services/ai/agents/playbookAgent.d.ts +54 -0
  176. package/dist/services/ai/agents/playbookAgent.d.ts.map +1 -0
  177. package/dist/services/ai/agents/playbookAgent.js +265 -0
  178. package/dist/services/ai/agents/playbookAgent.js.map +1 -0
  179. package/dist/services/ai/aiSdkClient.d.ts +67 -0
  180. package/dist/services/ai/aiSdkClient.d.ts.map +1 -0
  181. package/dist/services/ai/aiSdkClient.js +143 -0
  182. package/dist/services/ai/aiSdkClient.js.map +1 -0
  183. package/dist/services/ai/index.d.ts +7 -0
  184. package/dist/services/ai/index.d.ts.map +1 -0
  185. package/dist/services/ai/index.js +49 -0
  186. package/dist/services/ai/index.js.map +1 -0
  187. package/dist/services/ai/providerFactory.d.ts +35 -0
  188. package/dist/services/ai/providerFactory.d.ts.map +1 -0
  189. package/dist/services/ai/providerFactory.js +107 -0
  190. package/dist/services/ai/providerFactory.js.map +1 -0
  191. package/dist/services/ai/schemas.d.ts +331 -0
  192. package/dist/services/ai/schemas.d.ts.map +1 -0
  193. package/dist/services/ai/schemas.js +236 -0
  194. package/dist/services/ai/schemas.js.map +1 -0
  195. package/dist/services/ai/tools/analyzeSymbolsTool.d.ts +33 -0
  196. package/dist/services/ai/tools/analyzeSymbolsTool.d.ts.map +1 -0
  197. package/dist/services/ai/tools/analyzeSymbolsTool.js +57 -0
  198. package/dist/services/ai/tools/analyzeSymbolsTool.js.map +1 -0
  199. package/dist/services/ai/tools/checkScaffoldingTool.d.ts +18 -0
  200. package/dist/services/ai/tools/checkScaffoldingTool.d.ts.map +1 -0
  201. package/dist/services/ai/tools/checkScaffoldingTool.js +86 -0
  202. package/dist/services/ai/tools/checkScaffoldingTool.js.map +1 -0
  203. package/dist/services/ai/tools/fillScaffoldingTool.d.ts +38 -0
  204. package/dist/services/ai/tools/fillScaffoldingTool.d.ts.map +1 -0
  205. package/dist/services/ai/tools/fillScaffoldingTool.js +259 -0
  206. package/dist/services/ai/tools/fillScaffoldingTool.js.map +1 -0
  207. package/dist/services/ai/tools/getFileStructureTool.d.ts +29 -0
  208. package/dist/services/ai/tools/getFileStructureTool.d.ts.map +1 -0
  209. package/dist/services/ai/tools/getFileStructureTool.js +48 -0
  210. package/dist/services/ai/tools/getFileStructureTool.js.map +1 -0
  211. package/dist/services/ai/tools/index.d.ts +20 -0
  212. package/dist/services/ai/tools/index.d.ts.map +1 -0
  213. package/dist/services/ai/tools/index.js +62 -0
  214. package/dist/services/ai/tools/index.js.map +1 -0
  215. package/dist/services/ai/tools/initializeContextTool.d.ts +25 -0
  216. package/dist/services/ai/tools/initializeContextTool.d.ts.map +1 -0
  217. package/dist/services/ai/tools/initializeContextTool.js +121 -0
  218. package/dist/services/ai/tools/initializeContextTool.js.map +1 -0
  219. package/dist/services/ai/tools/listFilesTool.d.ts +18 -0
  220. package/dist/services/ai/tools/listFilesTool.d.ts.map +1 -0
  221. package/dist/services/ai/tools/listFilesTool.js +34 -0
  222. package/dist/services/ai/tools/listFilesTool.js.map +1 -0
  223. package/dist/services/ai/tools/readFileTool.d.ts +17 -0
  224. package/dist/services/ai/tools/readFileTool.d.ts.map +1 -0
  225. package/dist/services/ai/tools/readFileTool.js +63 -0
  226. package/dist/services/ai/tools/readFileTool.js.map +1 -0
  227. package/dist/services/ai/tools/scaffoldPlanTool.d.ts +19 -0
  228. package/dist/services/ai/tools/scaffoldPlanTool.d.ts.map +1 -0
  229. package/dist/services/ai/tools/scaffoldPlanTool.js +81 -0
  230. package/dist/services/ai/tools/scaffoldPlanTool.js.map +1 -0
  231. package/dist/services/ai/tools/searchCodeTool.d.ts +25 -0
  232. package/dist/services/ai/tools/searchCodeTool.d.ts.map +1 -0
  233. package/dist/services/ai/tools/searchCodeTool.js +96 -0
  234. package/dist/services/ai/tools/searchCodeTool.js.map +1 -0
  235. package/dist/services/baseLLMClient.d.ts +3 -3
  236. package/dist/services/baseLLMClient.d.ts.map +1 -1
  237. package/dist/services/baseLLMClient.js +44 -5
  238. package/dist/services/baseLLMClient.js.map +1 -1
  239. package/dist/services/fill/fillService.d.ts +11 -5
  240. package/dist/services/fill/fillService.d.ts.map +1 -1
  241. package/dist/services/fill/fillService.js +152 -88
  242. package/dist/services/fill/fillService.js.map +1 -1
  243. package/dist/services/init/initService.d.ts +3 -2
  244. package/dist/services/init/initService.d.ts.map +1 -1
  245. package/dist/services/init/initService.js +54 -19
  246. package/dist/services/init/initService.js.map +1 -1
  247. package/dist/services/llmClientFactory.d.ts +37 -9
  248. package/dist/services/llmClientFactory.d.ts.map +1 -1
  249. package/dist/services/llmClientFactory.js +54 -94
  250. package/dist/services/llmClientFactory.js.map +1 -1
  251. package/dist/services/mcp/index.d.ts +2 -0
  252. package/dist/services/mcp/index.d.ts.map +1 -0
  253. package/dist/services/mcp/index.js +7 -0
  254. package/dist/services/mcp/index.js.map +1 -0
  255. package/dist/services/mcp/mcpServer.d.ts +45 -0
  256. package/dist/services/mcp/mcpServer.d.ts.map +1 -0
  257. package/dist/services/mcp/mcpServer.js +371 -0
  258. package/dist/services/mcp/mcpServer.js.map +1 -0
  259. package/dist/services/openRouterClient.d.ts +0 -3
  260. package/dist/services/openRouterClient.d.ts.map +1 -1
  261. package/dist/services/openRouterClient.js +2 -49
  262. package/dist/services/openRouterClient.js.map +1 -1
  263. package/dist/services/passthrough/commandRouter.d.ts +53 -0
  264. package/dist/services/passthrough/commandRouter.d.ts.map +1 -0
  265. package/dist/services/passthrough/commandRouter.js +349 -0
  266. package/dist/services/passthrough/commandRouter.js.map +1 -0
  267. package/dist/services/passthrough/index.d.ts +7 -0
  268. package/dist/services/passthrough/index.d.ts.map +1 -0
  269. package/dist/services/passthrough/index.js +23 -0
  270. package/dist/services/passthrough/index.js.map +1 -0
  271. package/dist/services/passthrough/protocol.d.ts +269 -0
  272. package/dist/services/passthrough/protocol.d.ts.map +1 -0
  273. package/dist/services/passthrough/protocol.js +151 -0
  274. package/dist/services/passthrough/protocol.js.map +1 -0
  275. package/dist/services/passthrough/stdinReader.d.ts +42 -0
  276. package/dist/services/passthrough/stdinReader.d.ts.map +1 -0
  277. package/dist/services/passthrough/stdinReader.js +111 -0
  278. package/dist/services/passthrough/stdinReader.js.map +1 -0
  279. package/dist/services/plan/planService.d.ts +5 -5
  280. package/dist/services/plan/planService.d.ts.map +1 -1
  281. package/dist/services/plan/planService.js +52 -53
  282. package/dist/services/plan/planService.js.map +1 -1
  283. package/dist/services/semantic/codebaseAnalyzer.d.ts +40 -0
  284. package/dist/services/semantic/codebaseAnalyzer.d.ts.map +1 -0
  285. package/dist/services/semantic/codebaseAnalyzer.js +540 -0
  286. package/dist/services/semantic/codebaseAnalyzer.js.map +1 -0
  287. package/dist/services/semantic/contextBuilder.d.ts +79 -0
  288. package/dist/services/semantic/contextBuilder.d.ts.map +1 -0
  289. package/dist/services/semantic/contextBuilder.js +538 -0
  290. package/dist/services/semantic/contextBuilder.js.map +1 -0
  291. package/dist/services/semantic/index.d.ts +12 -0
  292. package/dist/services/semantic/index.d.ts.map +1 -0
  293. package/dist/services/semantic/index.js +33 -0
  294. package/dist/services/semantic/index.js.map +1 -0
  295. package/dist/services/semantic/lsp/index.d.ts +2 -0
  296. package/dist/services/semantic/lsp/index.d.ts.map +1 -0
  297. package/dist/services/semantic/lsp/index.js +6 -0
  298. package/dist/services/semantic/lsp/index.js.map +1 -0
  299. package/dist/services/semantic/lsp/lspLayer.d.ts +32 -0
  300. package/dist/services/semantic/lsp/lspLayer.d.ts.map +1 -0
  301. package/dist/services/semantic/lsp/lspLayer.js +378 -0
  302. package/dist/services/semantic/lsp/lspLayer.js.map +1 -0
  303. package/dist/services/semantic/treeSitter/index.d.ts +2 -0
  304. package/dist/services/semantic/treeSitter/index.d.ts.map +1 -0
  305. package/dist/services/semantic/treeSitter/index.js +6 -0
  306. package/dist/services/semantic/treeSitter/index.js.map +1 -0
  307. package/dist/services/semantic/treeSitter/treeSitterLayer.d.ts +37 -0
  308. package/dist/services/semantic/treeSitter/treeSitterLayer.d.ts.map +1 -0
  309. package/dist/services/semantic/treeSitter/treeSitterLayer.js +518 -0
  310. package/dist/services/semantic/treeSitter/treeSitterLayer.js.map +1 -0
  311. package/dist/services/semantic/types.d.ts +122 -0
  312. package/dist/services/semantic/types.d.ts.map +1 -0
  313. package/dist/services/semantic/types.js +31 -0
  314. package/dist/services/semantic/types.js.map +1 -0
  315. package/dist/services/serve/index.d.ts +2 -0
  316. package/dist/services/serve/index.d.ts.map +1 -0
  317. package/dist/services/serve/index.js +6 -0
  318. package/dist/services/serve/index.js.map +1 -0
  319. package/dist/services/serve/serveService.d.ts +38 -0
  320. package/dist/services/serve/serveService.d.ts.map +1 -0
  321. package/dist/services/serve/serveService.js +99 -0
  322. package/dist/services/serve/serveService.js.map +1 -0
  323. package/dist/services/shared/llmConfig.d.ts +19 -3
  324. package/dist/services/shared/llmConfig.d.ts.map +1 -1
  325. package/dist/services/shared/llmConfig.js +44 -57
  326. package/dist/services/shared/llmConfig.js.map +1 -1
  327. package/dist/services/sync/index.d.ts +6 -0
  328. package/dist/services/sync/index.d.ts.map +1 -0
  329. package/dist/services/sync/index.js +16 -0
  330. package/dist/services/sync/index.js.map +1 -0
  331. package/dist/services/sync/markdownReferenceHandler.d.ts +3 -0
  332. package/dist/services/sync/markdownReferenceHandler.d.ts.map +1 -0
  333. package/dist/services/sync/markdownReferenceHandler.js +133 -0
  334. package/dist/services/sync/markdownReferenceHandler.js.map +1 -0
  335. package/dist/services/sync/presets.d.ts +6 -0
  336. package/dist/services/sync/presets.d.ts.map +1 -0
  337. package/dist/services/sync/presets.js +49 -0
  338. package/dist/services/sync/presets.js.map +1 -0
  339. package/dist/services/sync/symlinkHandler.d.ts +7 -0
  340. package/dist/services/sync/symlinkHandler.d.ts.map +1 -0
  341. package/dist/services/sync/symlinkHandler.js +129 -0
  342. package/dist/services/sync/symlinkHandler.js.map +1 -0
  343. package/dist/services/sync/syncService.d.ts +15 -0
  344. package/dist/services/sync/syncService.d.ts.map +1 -0
  345. package/dist/services/sync/syncService.js +222 -0
  346. package/dist/services/sync/syncService.js.map +1 -0
  347. package/dist/services/sync/types.d.ts +62 -0
  348. package/dist/services/sync/types.d.ts.map +1 -0
  349. package/dist/services/sync/types.js +3 -0
  350. package/dist/services/sync/types.js.map +1 -0
  351. package/dist/types.d.ts +8 -2
  352. package/dist/types.d.ts.map +1 -1
  353. package/dist/utils/cliUI.d.ts +33 -0
  354. package/dist/utils/cliUI.d.ts.map +1 -1
  355. package/dist/utils/cliUI.js +157 -107
  356. package/dist/utils/cliUI.js.map +1 -1
  357. package/dist/utils/contentSanitizer.d.ts +42 -0
  358. package/dist/utils/contentSanitizer.d.ts.map +1 -0
  359. package/dist/utils/contentSanitizer.js +238 -0
  360. package/dist/utils/contentSanitizer.js.map +1 -0
  361. package/dist/utils/fileMapper.d.ts +1 -1
  362. package/dist/utils/fileMapper.d.ts.map +1 -1
  363. package/dist/utils/fileMapper.js +40 -19
  364. package/dist/utils/fileMapper.js.map +1 -1
  365. package/dist/utils/gitService.d.ts.map +1 -1
  366. package/dist/utils/gitService.js +12 -14
  367. package/dist/utils/gitService.js.map +1 -1
  368. package/dist/utils/i18n.d.ts +96 -43
  369. package/dist/utils/i18n.d.ts.map +1 -1
  370. package/dist/utils/i18n.js +194 -88
  371. package/dist/utils/i18n.js.map +1 -1
  372. package/dist/utils/prompts/configSummary.d.ts +7 -0
  373. package/dist/utils/prompts/configSummary.d.ts.map +1 -0
  374. package/dist/utils/prompts/configSummary.js +63 -0
  375. package/dist/utils/prompts/configSummary.js.map +1 -0
  376. package/dist/utils/prompts/index.d.ts +22 -0
  377. package/dist/utils/prompts/index.d.ts.map +1 -0
  378. package/dist/utils/prompts/index.js +122 -0
  379. package/dist/utils/prompts/index.js.map +1 -0
  380. package/dist/utils/prompts/llmPrompts.d.ts +11 -0
  381. package/dist/utils/prompts/llmPrompts.d.ts.map +1 -0
  382. package/dist/utils/prompts/llmPrompts.js +96 -0
  383. package/dist/utils/prompts/llmPrompts.js.map +1 -0
  384. package/dist/utils/prompts/smartDefaults.d.ts +15 -0
  385. package/dist/utils/prompts/smartDefaults.d.ts.map +1 -0
  386. package/dist/utils/prompts/smartDefaults.js +105 -0
  387. package/dist/utils/prompts/smartDefaults.js.map +1 -0
  388. package/dist/utils/prompts/types.d.ts +38 -0
  389. package/dist/utils/prompts/types.d.ts.map +1 -0
  390. package/dist/utils/prompts/types.js +3 -0
  391. package/dist/utils/prompts/types.js.map +1 -0
  392. package/dist/utils/theme.d.ts +66 -0
  393. package/dist/utils/theme.d.ts.map +1 -0
  394. package/dist/utils/theme.js +93 -0
  395. package/dist/utils/theme.js.map +1 -0
  396. package/dist/version.d.ts +8 -0
  397. package/dist/version.d.ts.map +1 -0
  398. package/dist/version.js +15 -0
  399. package/dist/version.js.map +1 -0
  400. package/package.json +18 -11
  401. package/prompts/update_plan_prompt.md +4 -5
  402. package/prompts/update_scaffold_prompt.md +14 -35
  403. package/dist/commands/shared/agents.d.ts +0 -2
  404. package/dist/commands/shared/agents.d.ts.map +0 -1
  405. package/dist/commands/shared/agents.js +0 -15
  406. package/dist/commands/shared/agents.js.map +0 -1
  407. package/dist/commands/shared/selection.d.ts +0 -12
  408. package/dist/commands/shared/selection.d.ts.map +0 -1
  409. package/dist/commands/shared/selection.js +0 -95
  410. package/dist/commands/shared/selection.js.map +0 -1
  411. package/dist/generators/agents/contextUtils.d.ts +0 -8
  412. package/dist/generators/agents/contextUtils.d.ts.map +0 -1
  413. package/dist/generators/agents/contextUtils.js +0 -15
  414. package/dist/generators/agents/contextUtils.js.map +0 -1
  415. package/dist/generators/agents/promptFormatter.d.ts +0 -9
  416. package/dist/generators/agents/promptFormatter.d.ts.map +0 -1
  417. package/dist/generators/agents/promptFormatter.js +0 -84
  418. package/dist/generators/agents/promptFormatter.js.map +0 -1
  419. package/dist/generators/analyzers/codebaseAnalyzer.d.ts +0 -45
  420. package/dist/generators/analyzers/codebaseAnalyzer.d.ts.map +0 -1
  421. package/dist/generators/analyzers/codebaseAnalyzer.js +0 -293
  422. package/dist/generators/analyzers/codebaseAnalyzer.js.map +0 -1
  423. package/dist/generators/analyzers/index.d.ts +0 -3
  424. package/dist/generators/analyzers/index.d.ts.map +0 -1
  425. package/dist/generators/analyzers/index.js +0 -6
  426. package/dist/generators/analyzers/index.js.map +0 -1
  427. package/dist/generators/documentation/documentationTemplates.d.ts +0 -21
  428. package/dist/generators/documentation/documentationTemplates.d.ts.map +0 -1
  429. package/dist/generators/documentation/documentationTemplates.js +0 -359
  430. package/dist/generators/documentation/documentationTemplates.js.map +0 -1
  431. package/dist/generators/documentation/documentationTypes.d.ts +0 -11
  432. package/dist/generators/documentation/documentationTypes.d.ts.map +0 -1
  433. package/dist/generators/documentation/documentationTypes.js +0 -22
  434. package/dist/generators/documentation/documentationTypes.js.map +0 -1
  435. package/dist/generators/documentation/documentationUtils.d.ts +0 -7
  436. package/dist/generators/documentation/documentationUtils.d.ts.map +0 -1
  437. package/dist/generators/documentation/documentationUtils.js +0 -28
  438. package/dist/generators/documentation/documentationUtils.js.map +0 -1
  439. package/dist/generators/documentation/incrementalDocumentationGenerator.d.ts +0 -33
  440. package/dist/generators/documentation/incrementalDocumentationGenerator.d.ts.map +0 -1
  441. package/dist/generators/documentation/incrementalDocumentationGenerator.js +0 -400
  442. package/dist/generators/documentation/incrementalDocumentationGenerator.js.map +0 -1
  443. package/dist/generators/documentation/templates/frontMatter.d.ts +0 -11
  444. package/dist/generators/documentation/templates/frontMatter.d.ts.map +0 -1
  445. package/dist/generators/documentation/templates/frontMatter.js +0 -29
  446. package/dist/generators/documentation/templates/frontMatter.js.map +0 -1
  447. package/dist/generators/documentation/templates.d.ts +0 -31
  448. package/dist/generators/documentation/templates.d.ts.map +0 -1
  449. package/dist/generators/documentation/templates.js +0 -566
  450. package/dist/generators/documentation/templates.js.map +0 -1
  451. package/dist/generators/guidelines/agentIntegration.d.ts +0 -43
  452. package/dist/generators/guidelines/agentIntegration.d.ts.map +0 -1
  453. package/dist/generators/guidelines/agentIntegration.js +0 -157
  454. package/dist/generators/guidelines/agentIntegration.js.map +0 -1
  455. package/dist/generators/guidelines/guidelineTypes.d.ts +0 -40
  456. package/dist/generators/guidelines/guidelineTypes.d.ts.map +0 -1
  457. package/dist/generators/guidelines/guidelineTypes.js +0 -144
  458. package/dist/generators/guidelines/guidelineTypes.js.map +0 -1
  459. package/dist/generators/guidelines/guidelinesAnalyzer.d.ts +0 -30
  460. package/dist/generators/guidelines/guidelinesAnalyzer.d.ts.map +0 -1
  461. package/dist/generators/guidelines/guidelinesAnalyzer.js +0 -263
  462. package/dist/generators/guidelines/guidelinesAnalyzer.js.map +0 -1
  463. package/dist/generators/guidelines/guidelinesGenerator.d.ts +0 -30
  464. package/dist/generators/guidelines/guidelinesGenerator.d.ts.map +0 -1
  465. package/dist/generators/guidelines/guidelinesGenerator.js +0 -249
  466. package/dist/generators/guidelines/guidelinesGenerator.js.map +0 -1
  467. package/dist/generators/guidelines/guidelinesTemplates.d.ts +0 -23
  468. package/dist/generators/guidelines/guidelinesTemplates.d.ts.map +0 -1
  469. package/dist/generators/guidelines/guidelinesTemplates.js +0 -304
  470. package/dist/generators/guidelines/guidelinesTemplates.js.map +0 -1
  471. package/dist/generators/guidelines/index.d.ts +0 -6
  472. package/dist/generators/guidelines/index.d.ts.map +0 -1
  473. package/dist/generators/guidelines/index.js +0 -16
  474. package/dist/generators/guidelines/index.js.map +0 -1
  475. package/dist/generators/moduleGrouper.d.ts +0 -14
  476. package/dist/generators/moduleGrouper.d.ts.map +0 -1
  477. package/dist/generators/moduleGrouper.js +0 -82
  478. package/dist/generators/moduleGrouper.js.map +0 -1
  479. package/dist/generators/projectAnalyzer.d.ts +0 -14
  480. package/dist/generators/projectAnalyzer.d.ts.map +0 -1
  481. package/dist/generators/projectAnalyzer.js +0 -217
  482. package/dist/generators/projectAnalyzer.js.map +0 -1
  483. package/dist/services/anthropicClient.d.ts +0 -12
  484. package/dist/services/anthropicClient.d.ts.map +0 -1
  485. package/dist/services/anthropicClient.js +0 -98
  486. package/dist/services/anthropicClient.js.map +0 -1
  487. package/dist/services/changeAnalyzer.d.ts +0 -44
  488. package/dist/services/changeAnalyzer.d.ts.map +0 -1
  489. package/dist/services/changeAnalyzer.js +0 -344
  490. package/dist/services/changeAnalyzer.js.map +0 -1
  491. package/dist/services/geminiClient.d.ts +0 -12
  492. package/dist/services/geminiClient.d.ts.map +0 -1
  493. package/dist/services/geminiClient.js +0 -96
  494. package/dist/services/geminiClient.js.map +0 -1
  495. package/dist/services/grokClient.d.ts +0 -12
  496. package/dist/services/grokClient.d.ts.map +0 -1
  497. package/dist/services/grokClient.js +0 -101
  498. package/dist/services/grokClient.js.map +0 -1
  499. package/dist/services/openaiClient.d.ts +0 -12
  500. package/dist/services/openaiClient.d.ts.map +0 -1
  501. package/dist/services/openaiClient.js +0 -98
  502. package/dist/services/openaiClient.js.map +0 -1
  503. package/dist/utils/interactiveMode.d.ts +0 -21
  504. package/dist/utils/interactiveMode.d.ts.map +0 -1
  505. package/dist/utils/interactiveMode.js +0 -737
  506. package/dist/utils/interactiveMode.js.map +0 -1
  507. package/dist/utils/pricing.d.ts +0 -14
  508. package/dist/utils/pricing.d.ts.map +0 -1
  509. package/dist/utils/pricing.js +0 -115
  510. package/dist/utils/pricing.js.map +0 -1
  511. package/dist/utils/tokenEstimator.d.ts +0 -28
  512. package/dist/utils/tokenEstimator.d.ts.map +0 -1
  513. package/dist/utils/tokenEstimator.js +0 -134
  514. package/dist/utils/tokenEstimator.js.map +0 -1
package/dist/index.js CHANGED
@@ -37,31 +37,30 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  return (mod && mod.__esModule) ? mod : { "default": mod };
38
38
  };
39
39
  Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.runInit = runInit;
40
41
  exports.runGenerate = runGenerate;
41
42
  exports.runAnalyze = runAnalyze;
42
43
  exports.runUpdate = runUpdate;
43
44
  exports.runPreview = runPreview;
44
45
  exports.runGuidelines = runGuidelines;
45
- exports.runInit = runInit;
46
+ exports.runLlmFill = runLlmFill;
46
47
  const commander_1 = require("commander");
47
48
  const path = __importStar(require("path"));
48
- const fs = __importStar(require("fs-extra"));
49
- const glob_1 = require("glob");
50
49
  const dotenv = __importStar(require("dotenv"));
51
- const chalk_1 = __importDefault(require("chalk"));
52
50
  const inquirer_1 = __importDefault(require("inquirer"));
53
- const fileMapper_1 = require("./utils/fileMapper");
54
- const documentationGenerator_1 = require("./generators/documentation/documentationGenerator");
55
- const agentGenerator_1 = require("./generators/agents/agentGenerator");
51
+ const theme_1 = require("./utils/theme");
56
52
  const planGenerator_1 = require("./generators/plans/planGenerator");
57
- const shared_1 = require("./generators/shared");
58
53
  const cliUI_1 = require("./utils/cliUI");
59
- const promptLoader_1 = require("./utils/promptLoader");
60
54
  const versionChecker_1 = require("./utils/versionChecker");
61
55
  const i18n_1 = require("./utils/i18n");
62
- const llmClientFactory_1 = require("./services/llmClientFactory");
63
- const guideRegistry_1 = require("./generators/documentation/guideRegistry");
64
- const agentTypes_1 = require("./generators/agents/agentTypes");
56
+ const initService_1 = require("./services/init/initService");
57
+ const fillService_1 = require("./services/fill/fillService");
58
+ const planService_1 = require("./services/plan/planService");
59
+ const syncService_1 = require("./services/sync/syncService");
60
+ const serve_1 = require("./services/serve");
61
+ const mcp_1 = require("./services/mcp");
62
+ const prompts_1 = require("./utils/prompts");
63
+ const version_1 = require("./version");
65
64
  dotenv.config();
66
65
  const initialLocale = (0, i18n_1.detectLocale)(process.argv.slice(2), process.env.AI_CONTEXT_LANG);
67
66
  let currentLocale = initialLocale;
@@ -73,28 +72,40 @@ const localeLabelKeys = {
73
72
  };
74
73
  const program = new commander_1.Command();
75
74
  const ui = new cliUI_1.CLIInterface(t);
76
- const VERSION = '0.3.1';
77
- const PACKAGE_NAME = '@ai-coders/context';
78
- const DEFAULT_MODEL = 'x-ai/grok-4-fast:free';
79
- const DOC_CHOICES = guideRegistry_1.DOCUMENT_GUIDES.map(guide => ({
80
- name: `${guide.title} (${guide.key})`,
81
- value: guide.key
82
- }));
83
- const AGENT_CHOICES = agentTypes_1.AGENT_TYPES.map(agent => ({
84
- name: formatAgentLabel(agent),
85
- value: agent
86
- }));
75
+ const DEFAULT_MODEL = 'gemini-3-flash-preview';
76
+ const initService = new initService_1.InitService({
77
+ ui,
78
+ t,
79
+ version: version_1.VERSION
80
+ });
81
+ const fillService = new fillService_1.FillService({
82
+ ui,
83
+ t,
84
+ version: version_1.VERSION,
85
+ defaultModel: DEFAULT_MODEL
86
+ });
87
+ const planService = new planService_1.PlanService({
88
+ ui,
89
+ t,
90
+ version: version_1.VERSION,
91
+ defaultModel: DEFAULT_MODEL
92
+ });
93
+ const syncService = new syncService_1.SyncService({
94
+ ui,
95
+ t,
96
+ version: version_1.VERSION
97
+ });
87
98
  program
88
99
  .name('ai-context')
89
100
  .description(t('cli.description'))
90
- .version(VERSION);
101
+ .version(version_1.VERSION);
91
102
  program.option('-l, --lang <locale>', t('global.options.lang'), initialLocale);
92
103
  let versionCheckPromise = null;
93
104
  function scheduleVersionCheck(force = false) {
94
105
  if (!versionCheckPromise || force) {
95
106
  versionCheckPromise = (0, versionChecker_1.checkForUpdates)({
96
- packageName: PACKAGE_NAME,
97
- currentVersion: VERSION,
107
+ packageName: version_1.PACKAGE_NAME,
108
+ currentVersion: version_1.VERSION,
98
109
  ui,
99
110
  t,
100
111
  force
@@ -111,34 +122,13 @@ program
111
122
  .argument('<repo-path>', t('commands.init.arguments.repoPath'))
112
123
  .argument('[type]', t('commands.init.arguments.type'), 'both')
113
124
  .option('-o, --output <dir>', t('commands.init.options.output'), './.context')
114
- .option('--docs <keys...>', t('commands.init.options.docs'))
115
- .option('--agents <keys...>', t('commands.init.options.agents'))
116
125
  .option('--exclude <patterns...>', t('commands.init.options.exclude'))
117
126
  .option('--include <patterns...>', t('commands.init.options.include'))
118
127
  .option('-v, --verbose', t('commands.init.options.verbose'))
128
+ .option('--no-semantic', t('commands.init.options.noSemantic'))
119
129
  .action(async (repoPath, type, options) => {
120
130
  try {
121
- await runInit(repoPath, type, options);
122
- }
123
- catch (error) {
124
- ui.displayError(t('errors.init.scaffoldFailed'), error);
125
- process.exit(1);
126
- }
127
- });
128
- program
129
- .command('scaffold')
130
- .description(t('commands.scaffold.description'))
131
- .argument('<repo-path>', t('commands.init.arguments.repoPath'))
132
- .argument('[type]', t('commands.init.arguments.type'), 'both')
133
- .option('-o, --output <dir>', t('commands.init.options.output'), './.context')
134
- .option('--docs <keys...>', t('commands.init.options.docs'))
135
- .option('--agents <keys...>', t('commands.init.options.agents'))
136
- .option('--exclude <patterns...>', t('commands.init.options.exclude'))
137
- .option('--include <patterns...>', t('commands.init.options.include'))
138
- .option('-v, --verbose', t('commands.init.options.verbose'))
139
- .action(async (repoPath, type, options) => {
140
- try {
141
- await runInit(repoPath, type, options);
131
+ await initService.run(repoPath, type, options);
142
132
  }
143
133
  catch (error) {
144
134
  ui.displayError(t('errors.init.scaffoldFailed'), error);
@@ -155,17 +145,16 @@ program
155
145
  .option('-p, --provider <provider>', t('commands.fill.options.provider'))
156
146
  .option('--base-url <url>', t('commands.fill.options.baseUrl'))
157
147
  .option('--prompt <file>', t('commands.fill.options.prompt'))
158
- .option('--dry-run', t('commands.fill.options.dryRun'), false)
159
- .option('--all', t('commands.fill.options.all'), false)
160
148
  .option('--limit <number>', t('commands.fill.options.limit'), (value) => parseInt(value, 10))
161
- .option('--docs <keys...>', t('commands.fill.options.docs'))
162
- .option('--agents <keys...>', t('commands.fill.options.agents'))
163
149
  .option('--exclude <patterns...>', t('commands.fill.options.exclude'))
164
150
  .option('--include <patterns...>', t('commands.fill.options.include'))
165
151
  .option('-v, --verbose', t('commands.fill.options.verbose'))
152
+ .option('--no-semantic', t('commands.fill.options.noSemantic'))
153
+ .option('--languages <langs>', t('commands.fill.options.languages'))
154
+ .option('--use-lsp', t('commands.fill.options.useLsp'))
166
155
  .action(async (repoPath, options) => {
167
156
  try {
168
- await runLlmFill(repoPath, options);
157
+ await fillService.run(repoPath, options);
169
158
  }
170
159
  catch (error) {
171
160
  ui.displayError(t('errors.fill.failed'), error);
@@ -179,8 +168,6 @@ program
179
168
  .option('-o, --output <dir>', t('commands.plan.options.output'), './.context')
180
169
  .option('--title <title>', t('commands.plan.options.title'))
181
170
  .option('--summary <text>', t('commands.plan.options.summary'))
182
- .option('--agents <types...>', t('commands.plan.options.agents'))
183
- .option('--docs <keys...>', t('commands.plan.options.docs'))
184
171
  .option('-f, --force', t('commands.plan.options.force'))
185
172
  .option('--fill', t('commands.plan.options.fill'))
186
173
  .option('-r, --repo <path>', t('commands.plan.options.repo'))
@@ -193,27 +180,19 @@ program
193
180
  .option('--include <patterns...>', t('commands.plan.options.include'))
194
181
  .option('--exclude <patterns...>', t('commands.plan.options.exclude'))
195
182
  .option('-v, --verbose', t('commands.plan.options.verbose'))
183
+ .option('--no-semantic', t('commands.plan.options.noSemantic'))
184
+ .option('--no-lsp', t('commands.plan.options.noLsp'))
196
185
  .action(async (planName, rawOptions) => {
197
- const agentSelection = parseAgentSelection(rawOptions.agents);
198
- if (agentSelection.invalid.length > 0) {
199
- ui.displayWarning(t('warnings.agents.unknown', { values: agentSelection.invalid.join(', ') }));
200
- }
201
- const docSelection = parseDocSelection(rawOptions.docs);
202
- if (docSelection.invalid.length > 0) {
203
- ui.displayWarning(t('warnings.docs.unknown', { values: docSelection.invalid.join(', ') }));
204
- }
205
186
  const outputDir = path.resolve(rawOptions.output || './.context');
206
187
  if (rawOptions.fill) {
207
188
  try {
208
- await scaffoldPlanIfNeeded(planName, outputDir, {
189
+ await planService.scaffoldPlanIfNeeded(planName, outputDir, {
209
190
  title: rawOptions.title,
210
191
  summary: rawOptions.summary,
211
- agentSelection,
212
- docSelection,
213
192
  force: Boolean(rawOptions.force),
214
193
  verbose: Boolean(rawOptions.verbose)
215
194
  });
216
- await runPlanFill(planName, { ...rawOptions, output: outputDir });
195
+ await planService.fillPlan(planName, { ...rawOptions, output: outputDir });
217
196
  }
218
197
  catch (error) {
219
198
  ui.displayError(t('errors.plan.fillFailed'), error);
@@ -229,13 +208,13 @@ program
229
208
  outputDir,
230
209
  title: rawOptions.title,
231
210
  summary: rawOptions.summary,
232
- selectedAgentTypes: agentSelection.explicitNone ? null : agentSelection.selected,
233
- selectedDocKeys: docSelection.explicitNone ? null : docSelection.selected,
234
211
  force: Boolean(rawOptions.force),
235
- verbose: Boolean(rawOptions.verbose)
212
+ verbose: Boolean(rawOptions.verbose),
213
+ semantic: rawOptions.semantic !== false,
214
+ projectPath: rawOptions.repo ? path.resolve(rawOptions.repo) : path.resolve(rawOptions.output || './.context', '..')
236
215
  });
237
216
  ui.updateSpinner(t('spinner.plan.created'), 'success');
238
- ui.displaySuccess(t('success.plan.createdAt', { path: chalk_1.default.cyan(result.relativePath) }));
217
+ ui.displaySuccess(t('success.plan.createdAt', { path: theme_1.colors.accent(result.relativePath) }));
239
218
  }
240
219
  catch (error) {
241
220
  ui.updateSpinner(t('spinner.plan.creationFailed'), 'fail');
@@ -246,91 +225,85 @@ program
246
225
  ui.stopSpinner();
247
226
  }
248
227
  });
249
- async function runInit(repoPath, type, rawOptions) {
250
- const resolvedType = resolveScaffoldType(type, rawOptions);
251
- const docSelection = parseDocSelection(rawOptions.docs);
252
- const agentSelection = parseAgentSelection(rawOptions.agents);
253
- if (docSelection.invalid.length > 0) {
254
- ui.displayWarning(t('warnings.docs.unknown', { values: docSelection.invalid.join(', ') }));
255
- }
256
- if (agentSelection.invalid.length > 0) {
257
- ui.displayWarning(t('warnings.agents.unknown', { values: agentSelection.invalid.join(', ') }));
258
- }
259
- const options = {
260
- repoPath: path.resolve(repoPath),
261
- outputDir: path.resolve(rawOptions.output || './.context'),
262
- include: rawOptions.include,
263
- exclude: rawOptions.exclude || [],
264
- verbose: rawOptions.verbose || false,
265
- scaffoldDocs: shouldGenerateDocs(resolvedType, docSelection),
266
- scaffoldAgents: shouldGenerateAgents(resolvedType, agentSelection),
267
- selectedDocKeys: docSelection.selected,
268
- selectedAgentTypes: agentSelection.selected
269
- };
270
- if (!options.scaffoldDocs && !options.scaffoldAgents) {
271
- ui.displayWarning(t('warnings.scaffold.noneSelected'));
272
- return;
273
- }
274
- await ensurePaths(options);
275
- ui.displayWelcome(VERSION);
276
- ui.displayProjectInfo(options.repoPath, options.outputDir, resolvedType);
277
- const fileMapper = new fileMapper_1.FileMapper(options.exclude);
278
- ui.displayStep(1, 3, t('steps.init.analyze'));
279
- ui.startSpinner(t('spinner.repo.scanning'));
280
- const repoStructure = await fileMapper.mapRepository(options.repoPath, options.include);
281
- ui.updateSpinner(t('spinner.repo.scanComplete', {
282
- fileCount: repoStructure.totalFiles,
283
- directoryCount: repoStructure.directories.length
284
- }), 'success');
285
- let docsGenerated = 0;
286
- let agentsGenerated = 0;
287
- const docGenerator = new documentationGenerator_1.DocumentationGenerator();
288
- const agentGenerator = new agentGenerator_1.AgentGenerator();
289
- if (options.scaffoldDocs) {
290
- ui.displayStep(2, 3, t('steps.init.docs'));
291
- ui.startSpinner(t('spinner.docs.creating'));
292
- docsGenerated = await docGenerator.generateDocumentation(repoStructure, options.outputDir, { selectedDocs: options.selectedDocKeys }, options.verbose);
293
- ui.updateSpinner(t('spinner.docs.created', { count: docsGenerated }), 'success');
228
+ program
229
+ .command('sync-agents')
230
+ .description(t('commands.sync.description'))
231
+ .option('-s, --source <dir>', t('commands.sync.options.source'), './.context/agents')
232
+ .option('-t, --target <paths...>', t('commands.sync.options.target'))
233
+ .option('-m, --mode <type>', t('commands.sync.options.mode'), 'symlink')
234
+ .option('-p, --preset <name>', t('commands.sync.options.preset'))
235
+ .option('--force', t('commands.sync.options.force'))
236
+ .option('--dry-run', t('commands.sync.options.dryRun'))
237
+ .option('-v, --verbose', t('commands.sync.options.verbose'))
238
+ .action(async (options) => {
239
+ try {
240
+ await syncService.run(options);
294
241
  }
295
- if (options.scaffoldAgents) {
296
- ui.displayStep(3, options.scaffoldDocs ? 3 : 2, t('steps.init.agents'));
297
- ui.startSpinner(t('spinner.agents.creating'));
298
- agentsGenerated = await agentGenerator.generateAgentPrompts(repoStructure, options.outputDir, options.selectedAgentTypes, options.verbose);
299
- ui.updateSpinner(t('spinner.agents.created', { count: agentsGenerated }), 'success');
242
+ catch (error) {
243
+ ui.displayError(t('errors.sync.failed'), error);
244
+ process.exit(1);
300
245
  }
301
- ui.displayGenerationSummary(docsGenerated, agentsGenerated);
302
- ui.displaySuccess(t('success.scaffold.ready', { path: chalk_1.default.cyan(options.outputDir) }));
303
- }
304
- function resolveScaffoldType(type, rawOptions) {
305
- const normalized = (type || 'both').toLowerCase();
306
- const allowed = ['docs', 'agents', 'both'];
307
- if (!allowed.includes(normalized)) {
308
- throw new Error(t('errors.init.invalidType', { value: type, allowed: allowed.join(', ') }));
246
+ });
247
+ program
248
+ .command('serve')
249
+ .description('Start passthrough server for external AI agents (stdin/stdout JSON)')
250
+ .option('-r, --repo-path <path>', 'Default repository path for tools')
251
+ .option('-f, --format <format>', 'Output format: json or jsonl', 'jsonl')
252
+ .option('-v, --verbose', 'Enable verbose logging to stderr')
253
+ .action(async (options) => {
254
+ const service = new serve_1.ServeService({
255
+ repoPath: options.repoPath,
256
+ format: options.format,
257
+ verbose: options.verbose
258
+ });
259
+ try {
260
+ await service.run();
309
261
  }
310
- if (rawOptions.docsOnly) {
311
- return 'docs';
262
+ catch (error) {
263
+ if (options.verbose) {
264
+ process.stderr.write(`[serve] Error: ${error}\n`);
265
+ }
266
+ process.exit(1);
312
267
  }
313
- if (rawOptions.agentsOnly) {
314
- return 'agents';
268
+ });
269
+ program
270
+ .command('mcp')
271
+ .description('Start MCP (Model Context Protocol) server for Claude Code integration')
272
+ .option('-r, --repo-path <path>', 'Default repository path for tools')
273
+ .option('-v, --verbose', 'Enable verbose logging to stderr')
274
+ .action(async (options) => {
275
+ try {
276
+ const server = await (0, mcp_1.startMCPServer)({
277
+ repoPath: options.repoPath,
278
+ verbose: options.verbose
279
+ });
280
+ // Handle graceful shutdown
281
+ process.on('SIGINT', async () => {
282
+ await server.stop();
283
+ process.exit(0);
284
+ });
285
+ process.on('SIGTERM', async () => {
286
+ await server.stop();
287
+ process.exit(0);
288
+ });
315
289
  }
316
- return normalized;
317
- }
318
- async function ensurePaths(options) {
319
- const exists = await fs.pathExists(options.repoPath);
320
- if (!exists) {
321
- throw new Error(t('errors.common.repoMissing', { path: options.repoPath }));
290
+ catch (error) {
291
+ if (options.verbose) {
292
+ process.stderr.write(`[mcp] Error: ${error}\n`);
293
+ }
294
+ process.exit(1);
322
295
  }
323
- await fs.ensureDir(options.outputDir);
296
+ });
297
+ async function runInit(repoPath, type, rawOptions) {
298
+ await initService.run(repoPath, type, rawOptions);
324
299
  }
325
300
  async function runGenerate(repoPath, options) {
326
301
  const type = options?.docsOnly ? 'docs' : options?.agentsOnly ? 'agents' : (options?.type || 'both');
327
- await runInit(repoPath, type, {
302
+ await initService.run(repoPath, type, {
328
303
  output: options?.output ?? options?.outputDir ?? './.context',
329
304
  include: options?.include,
330
305
  exclude: options?.exclude,
331
306
  verbose: options?.verbose,
332
- docs: options?.docs,
333
- agents: options?.agents,
334
307
  docsOnly: options?.docsOnly,
335
308
  agentsOnly: options?.agentsOnly
336
309
  });
@@ -347,621 +320,8 @@ async function runPreview(..._args) {
347
320
  async function runGuidelines(..._args) {
348
321
  throw new Error(t('errors.commands.guidelinesRemoved'));
349
322
  }
350
- async function resolveLlmConfig(rawOptions, defaults) {
351
- const providerEnvMap = llmClientFactory_1.LLMClientFactory.getEnvironmentVariables();
352
- const defaultModels = llmClientFactory_1.LLMClientFactory.getDefaultModels();
353
- let provider = rawOptions.provider;
354
- let model = rawOptions.model;
355
- let apiKey = rawOptions.apiKey;
356
- if (!apiKey) {
357
- if (provider) {
358
- for (const envVar of providerEnvMap[provider]) {
359
- const value = process.env[envVar];
360
- if (value) {
361
- apiKey = value;
362
- break;
363
- }
364
- }
365
- }
366
- else {
367
- outer: for (const [prov, envVars] of Object.entries(providerEnvMap)) {
368
- for (const envVar of envVars) {
369
- const value = process.env[envVar];
370
- if (value) {
371
- apiKey = value;
372
- provider = prov;
373
- break outer;
374
- }
375
- }
376
- }
377
- }
378
- }
379
- if (!provider) {
380
- if (model) {
381
- provider = llmClientFactory_1.LLMClientFactory.detectProviderFromModel(model);
382
- }
383
- else if (apiKey) {
384
- provider = llmClientFactory_1.LLMClientFactory.getProviderFromApiKey(apiKey);
385
- }
386
- }
387
- if (!model) {
388
- if (provider === 'openrouter' && process.env.OPENROUTER_MODEL) {
389
- model = process.env.OPENROUTER_MODEL;
390
- }
391
- else if (provider && defaultModels[provider]?.length) {
392
- model = defaultModels[provider][0];
393
- }
394
- else {
395
- model = defaults.fallbackModel;
396
- provider = llmClientFactory_1.LLMClientFactory.detectProviderFromModel(model);
397
- }
398
- }
399
- if (!provider) {
400
- provider = llmClientFactory_1.LLMClientFactory.detectProviderFromModel(model || defaults.fallbackModel);
401
- }
402
- if (!apiKey) {
403
- for (const envVar of providerEnvMap[provider]) {
404
- const value = process.env[envVar];
405
- if (value) {
406
- apiKey = value;
407
- break;
408
- }
409
- }
410
- }
411
- if (!apiKey) {
412
- const envVars = providerEnvMap[provider];
413
- throw new Error(t('errors.fill.apiKeyMissing', {
414
- provider: provider.toUpperCase(),
415
- envVars: envVars.join(', ')
416
- }));
417
- }
418
- return {
419
- provider,
420
- model: model || defaults.fallbackModel,
421
- apiKey,
422
- baseUrl: rawOptions.baseUrl
423
- };
424
- }
425
323
  async function runLlmFill(repoPath, rawOptions) {
426
- const resolvedRepo = path.resolve(repoPath);
427
- const outputDir = path.resolve(rawOptions.output || './.context');
428
- const docsDir = path.join(outputDir, 'docs');
429
- const agentsDir = path.join(outputDir, 'agents');
430
- await ensureDirectoryExists(docsDir, t('errors.fill.missingDocsScaffold'));
431
- await ensureDirectoryExists(agentsDir, t('errors.fill.missingAgentsScaffold'));
432
- const docSelection = parseDocSelection(rawOptions.docs);
433
- const agentSelection = parseAgentSelection(rawOptions.agents);
434
- if (docSelection.invalid.length > 0) {
435
- ui.displayWarning(t('warnings.docs.unknown', { values: docSelection.invalid.join(', ') }));
436
- }
437
- if (agentSelection.invalid.length > 0) {
438
- ui.displayWarning(t('warnings.agents.unknown', { values: agentSelection.invalid.join(', ') }));
439
- }
440
- const { provider, model, apiKey, baseUrl } = await resolveLlmConfig(rawOptions, {
441
- fallbackModel: DEFAULT_MODEL
442
- });
443
- const scaffoldPrompt = await (0, promptLoader_1.resolveScaffoldPrompt)(rawOptions.prompt, missingPath => t('errors.fill.promptMissing', { path: missingPath }));
444
- const docAllowlist = docSelection.explicitNone
445
- ? new Set()
446
- : (0, guideRegistry_1.getDocFilesByKeys)(docSelection.selected);
447
- const agentAllowlist = agentSelection.explicitNone
448
- ? new Set()
449
- : getAgentFilesByTypes(agentSelection.selected);
450
- const options = {
451
- repoPath: resolvedRepo,
452
- outputDir,
453
- provider,
454
- model,
455
- apiKey,
456
- baseUrl,
457
- include: rawOptions.include,
458
- exclude: rawOptions.exclude,
459
- verbose: rawOptions.verbose || false,
460
- dryRun: rawOptions.dryRun || false,
461
- processAll: rawOptions.all || false,
462
- limit: rawOptions.limit,
463
- selectedDocKeys: docSelection.selected,
464
- selectedAgentTypes: agentSelection.selected,
465
- selectedDocFiles: docAllowlist,
466
- selectedAgentFiles: agentAllowlist
467
- };
468
- const scaffoldPromptDisplayPath = scaffoldPrompt.path
469
- ? path.relative(process.cwd(), scaffoldPrompt.path) || scaffoldPrompt.path
470
- : undefined;
471
- if (scaffoldPrompt.source === 'custom' && scaffoldPromptDisplayPath) {
472
- ui.displayInfo(t('info.prompt.title'), t('info.prompt.usingCustom', { path: scaffoldPromptDisplayPath }));
473
- }
474
- else if (scaffoldPrompt.source === 'package' && scaffoldPromptDisplayPath) {
475
- ui.displayInfo(t('info.prompt.title'), t('info.prompt.usingPackage', { path: scaffoldPromptDisplayPath }));
476
- }
477
- else {
478
- ui.displayInfo(t('info.prompt.title'), t('info.prompt.usingBundled'));
479
- }
480
- ui.displayWelcome(VERSION);
481
- ui.displayProjectInfo(options.repoPath, options.outputDir, `fill:${options.provider}`);
482
- const fileMapper = new fileMapper_1.FileMapper(options.exclude);
483
- ui.displayStep(1, 3, t('steps.fill.analyze'));
484
- ui.startSpinner(t('spinner.repo.scanning'));
485
- const repoStructure = await fileMapper.mapRepository(options.repoPath, options.include);
486
- ui.updateSpinner(t('spinner.repo.scanComplete', {
487
- fileCount: repoStructure.totalFiles,
488
- directoryCount: repoStructure.directories.length
489
- }), 'success');
490
- const systemPrompt = scaffoldPrompt.content;
491
- const llmClient = llmClientFactory_1.LLMClientFactory.createClient({
492
- apiKey: options.apiKey,
493
- model: options.model,
494
- provider: options.provider,
495
- baseUrl: options.baseUrl
496
- });
497
- const targets = await collectTargets(docsDir, agentsDir, options.processAll, options.limit, options.selectedDocFiles, options.selectedAgentFiles);
498
- if (targets.length === 0) {
499
- ui.displayWarning(t('warnings.fill.noTargets'));
500
- return;
501
- }
502
- const contextSummary = buildContextSummary(repoStructure);
503
- const results = [];
504
- ui.displayStep(2, 3, t('steps.fill.processFiles', { count: targets.length, model: options.model }));
505
- for (const target of targets) {
506
- const relativePath = path.relative(options.outputDir, target.fullPath);
507
- ui.startSpinner(t('spinner.fill.processing', { path: relativePath }));
508
- try {
509
- const currentContent = await fs.readFile(target.fullPath, 'utf-8');
510
- const userPrompt = buildUserPrompt(relativePath, currentContent, contextSummary, target.isAgent);
511
- const updatedContent = await llmClient.generateText(userPrompt, systemPrompt);
512
- if (!updatedContent || !updatedContent.trim()) {
513
- ui.updateSpinner(t('spinner.fill.noContent', { path: relativePath }), 'warn');
514
- results.push({ file: relativePath, status: 'skipped', message: t('messages.fill.emptyResponse') });
515
- continue;
516
- }
517
- if (options.dryRun) {
518
- ui.updateSpinner(t('spinner.fill.dryRunPreview', { path: relativePath }), 'info');
519
- console.log(chalk_1.default.gray(`\n${t('messages.fill.previewStart')}`));
520
- console.log(updatedContent.trim());
521
- console.log(chalk_1.default.gray(`${t('messages.fill.previewEnd')}\n`));
522
- }
523
- else {
524
- await fs.writeFile(target.fullPath, ensureTrailingNewline(updatedContent));
525
- ui.updateSpinner(t('spinner.fill.updated', { path: relativePath }), 'success');
526
- }
527
- results.push({ file: relativePath, status: options.dryRun ? 'skipped' : 'updated' });
528
- }
529
- catch (error) {
530
- ui.updateSpinner(t('spinner.fill.failed', { path: relativePath }), 'fail');
531
- results.push({
532
- file: relativePath,
533
- status: 'failed',
534
- message: error instanceof Error ? error.message : String(error)
535
- });
536
- }
537
- }
538
- ui.displayStep(3, 3, t('steps.fill.summary'));
539
- printLlmSummary(llmClient.getUsageStats(), results, options.dryRun);
540
- ui.displaySuccess(t('success.fill.completed'));
541
- }
542
- async function scaffoldPlanIfNeeded(planName, outputDir, options) {
543
- const resolvedOutput = path.resolve(outputDir);
544
- const plansDir = path.join(resolvedOutput, 'plans');
545
- const normalizedInput = planName.replace(/\.md$/i, '');
546
- const slug = shared_1.GeneratorUtils.slugify(normalizedInput);
547
- if (!slug) {
548
- throw new Error(t('errors.plan.invalidName'));
549
- }
550
- const planPath = path.join(plansDir, `${slug}.md`);
551
- const planExists = await fs.pathExists(planPath);
552
- if (planExists && !options.force) {
553
- return;
554
- }
555
- const generator = new planGenerator_1.PlanGenerator();
556
- const result = await generator.generatePlan({
557
- planName,
558
- outputDir: resolvedOutput,
559
- title: options.title,
560
- summary: options.summary,
561
- selectedAgentTypes: options.agentSelection
562
- ? options.agentSelection.explicitNone
563
- ? null
564
- : options.agentSelection.selected
565
- : undefined,
566
- selectedDocKeys: options.docSelection
567
- ? options.docSelection.explicitNone
568
- ? null
569
- : options.docSelection.selected
570
- : undefined,
571
- force: Boolean(options.force),
572
- verbose: Boolean(options.verbose)
573
- });
574
- const relativePath = result.relativePath;
575
- const message = planExists && options.force
576
- ? t('messages.plan.regenerated', { path: relativePath })
577
- : t('messages.plan.created', { path: relativePath });
578
- ui.displayInfo(t('info.plan.scaffolded.title'), message);
579
- }
580
- async function runPlanFill(planName, rawOptions) {
581
- const outputDir = path.resolve(rawOptions.output || './.context');
582
- const plansDir = path.join(outputDir, 'plans');
583
- await ensureDirectoryExists(plansDir, t('errors.plan.missingPlansDir'));
584
- const normalizedInput = planName.replace(/\.md$/i, '');
585
- const slug = shared_1.GeneratorUtils.slugify(normalizedInput);
586
- if (!slug) {
587
- throw new Error(t('errors.plan.invalidName'));
588
- }
589
- const candidateFiles = new Set();
590
- candidateFiles.add(path.join(plansDir, `${slug}.md`));
591
- if (planName.toLowerCase().endsWith('.md')) {
592
- candidateFiles.add(path.join(plansDir, planName));
593
- }
594
- let planPath;
595
- for (const candidate of candidateFiles) {
596
- if (await fs.pathExists(candidate)) {
597
- planPath = candidate;
598
- break;
599
- }
600
- }
601
- if (!planPath) {
602
- const expected = Array.from(candidateFiles).map(file => path.relative(process.cwd(), file)).join(' or ');
603
- throw new Error(t('errors.plan.notFound', { expected }));
604
- }
605
- const docsDir = path.join(outputDir, 'docs');
606
- const agentsDir = path.join(outputDir, 'agents');
607
- await ensureDirectoryExists(docsDir, t('errors.fill.missingDocsScaffold'));
608
- await ensureDirectoryExists(agentsDir, t('errors.fill.missingAgentsScaffold'));
609
- const repoPath = path.resolve(rawOptions.repo || process.cwd());
610
- if (!(await fs.pathExists(repoPath))) {
611
- throw new Error(t('errors.common.repoMissing', { path: repoPath }));
612
- }
613
- const { provider, model, apiKey, baseUrl } = await resolveLlmConfig(rawOptions, {
614
- fallbackModel: DEFAULT_MODEL
615
- });
616
- const planPrompt = await (0, promptLoader_1.resolvePlanPrompt)(rawOptions.prompt, missingPath => t('errors.fill.promptMissing', { path: missingPath }));
617
- const planContent = await fs.readFile(planPath, 'utf-8');
618
- const docsIndexPath = path.join(docsDir, 'README.md');
619
- const agentsIndexPath = path.join(agentsDir, 'README.md');
620
- const docsIndex = (await fs.pathExists(docsIndexPath)) ? await fs.readFile(docsIndexPath, 'utf-8') : undefined;
621
- const agentsIndex = (await fs.pathExists(agentsIndexPath)) ? await fs.readFile(agentsIndexPath, 'utf-8') : undefined;
622
- const referencedDocs = await loadReferencedMarkdown(docsDir, extractPlanReferences(planContent, 'docs'));
623
- const referencedAgents = await loadReferencedMarkdown(agentsDir, extractPlanReferences(planContent, 'agents'));
624
- const planPromptDisplayPath = planPrompt.path
625
- ? path.relative(process.cwd(), planPrompt.path) || planPrompt.path
626
- : undefined;
627
- if (planPrompt.source === 'custom' && planPromptDisplayPath) {
628
- ui.displayInfo(t('info.prompt.title'), t('info.prompt.usingCustom', { path: planPromptDisplayPath }));
629
- }
630
- else if (planPrompt.source === 'package' && planPromptDisplayPath) {
631
- ui.displayInfo(t('info.prompt.title'), t('info.prompt.usingPackage', { path: planPromptDisplayPath }));
632
- }
633
- else {
634
- ui.displayInfo(t('info.prompt.title'), t('info.prompt.usingBundled'));
635
- }
636
- ui.displayWelcome(VERSION);
637
- ui.displayProjectInfo(repoPath, outputDir, `plan-fill:${provider}`);
638
- const fileMapper = new fileMapper_1.FileMapper(rawOptions.exclude);
639
- ui.displayStep(1, 3, t('steps.plan.summary'));
640
- ui.startSpinner(t('spinner.planFill.analyzingRepo'));
641
- const repoStructure = await fileMapper.mapRepository(repoPath, rawOptions.include);
642
- const contextSummary = buildContextSummary(repoStructure);
643
- ui.updateSpinner(t('spinner.planFill.summaryReady'), 'success');
644
- const systemPrompt = planPrompt.content;
645
- const llmClient = llmClientFactory_1.LLMClientFactory.createClient({
646
- apiKey,
647
- model,
648
- provider,
649
- baseUrl
650
- });
651
- const planRelativePath = path.relative(outputDir, planPath);
652
- const results = [];
653
- ui.displayStep(2, 3, t('steps.plan.update', { path: planRelativePath, model }));
654
- ui.startSpinner(t('spinner.planFill.updating', { path: planRelativePath }));
655
- try {
656
- const userPrompt = buildPlanUserPrompt({
657
- relativePath: planRelativePath,
658
- planContent,
659
- contextSummary,
660
- docsIndex,
661
- agentsIndex,
662
- docs: referencedDocs,
663
- agents: referencedAgents
664
- });
665
- const updatedContent = await llmClient.generateText(userPrompt, systemPrompt);
666
- if (!updatedContent || !updatedContent.trim()) {
667
- ui.updateSpinner(t('spinner.planFill.noContent'), 'warn');
668
- results.push({ file: planRelativePath, status: 'skipped', message: t('messages.fill.emptyResponse') });
669
- }
670
- else if (rawOptions.dryRun) {
671
- ui.updateSpinner(t('spinner.planFill.dryRun'), 'info');
672
- console.log(chalk_1.default.gray(`\n${t('messages.fill.previewStart')}`));
673
- console.log(updatedContent.trim());
674
- console.log(chalk_1.default.gray(`${t('messages.fill.previewEnd')}\n`));
675
- results.push({ file: planRelativePath, status: 'skipped', message: 'dry-run' });
676
- }
677
- else {
678
- await fs.writeFile(planPath, ensureTrailingNewline(updatedContent));
679
- ui.updateSpinner(t('spinner.planFill.updated', { path: planRelativePath }), 'success');
680
- results.push({ file: planRelativePath, status: 'updated' });
681
- }
682
- }
683
- catch (error) {
684
- ui.updateSpinner(t('spinner.planFill.failed'), 'fail');
685
- results.push({
686
- file: planRelativePath,
687
- status: 'failed',
688
- message: error instanceof Error ? error.message : String(error)
689
- });
690
- }
691
- finally {
692
- ui.stopSpinner();
693
- }
694
- ui.displayStep(3, 3, t('steps.plan.summaryResults'));
695
- printLlmSummary(llmClient.getUsageStats(), results, Boolean(rawOptions.dryRun));
696
- ui.displaySuccess(t('success.plan.filled'));
697
- }
698
- async function ensureDirectoryExists(dir, message) {
699
- const exists = await fs.pathExists(dir);
700
- if (!exists) {
701
- throw new Error(message);
702
- }
703
- }
704
- async function collectTargets(docsDir, agentsDir, processAll, limit, docAllowlist, agentAllowlist) {
705
- const docFiles = await (0, glob_1.glob)('**/*.md', { cwd: docsDir, absolute: true });
706
- const agentFiles = await (0, glob_1.glob)('**/*.md', { cwd: agentsDir, absolute: true });
707
- const candidates = [...docFiles, ...agentFiles];
708
- const targets = [];
709
- for (const fullPath of candidates) {
710
- const content = await fs.readFile(fullPath, 'utf-8');
711
- const hasMarkers = /<!--\s*ai-task:/.test(content) || /<!--\s*ai-slot:/.test(content) || /TODO/.test(content);
712
- const isAgent = fullPath.includes(`${path.sep}agents${path.sep}`);
713
- const fileName = path.basename(fullPath);
714
- if (isAgent) {
715
- if (agentAllowlist && !agentAllowlist.has(fileName)) {
716
- continue;
717
- }
718
- }
719
- else {
720
- if (docAllowlist && !docAllowlist.has(fileName)) {
721
- continue;
722
- }
723
- }
724
- const explicitSelection = isAgent ? !!agentAllowlist : !!docAllowlist;
725
- const shouldInclude = processAll ||
726
- hasMarkers ||
727
- (explicitSelection && (isAgent ? agentAllowlist.has(fileName) : docAllowlist.has(fileName)));
728
- if (!shouldInclude) {
729
- continue;
730
- }
731
- targets.push({ fullPath, hasMarkers, isAgent });
732
- if (limit && targets.length >= limit) {
733
- break;
734
- }
735
- }
736
- return targets;
737
- }
738
- function buildContextSummary(repoStructure) {
739
- const directories = new Set();
740
- repoStructure.directories.forEach(dir => {
741
- const [first] = dir.relativePath.split(/[\\/]/).filter(Boolean);
742
- if (first) {
743
- directories.add(first);
744
- }
745
- });
746
- const topDirs = Array.from(directories).sort().slice(0, 12);
747
- const totalSizeMb = (repoStructure.totalSize / (1024 * 1024)).toFixed(2);
748
- return [
749
- `Top-level directories: ${topDirs.length ? topDirs.join(', ') : 'n/a'}`,
750
- `Total files scanned: ${repoStructure.totalFiles}`,
751
- `Repository size (approx.): ${totalSizeMb} MB`
752
- ].join('\n');
753
- }
754
- function buildUserPrompt(relativePath, currentContent, contextSummary, isAgent) {
755
- const guidance = [
756
- '- Preserve YAML front matter and existing `ai-task` sections.',
757
- '- Replace TODOs and resolve `ai-slot` placeholders with concrete information.',
758
- '- Ensure success criteria in the front matter are satisfied.',
759
- '- Return only the full updated Markdown for this file.'
760
- ];
761
- if (isAgent) {
762
- guidance.push('- Keep agent responsibilities, best practices, and documentation touchpoints aligned with the latest docs.');
763
- }
764
- else {
765
- guidance.push('- Maintain accurate cross-links between docs and referenced resources.');
766
- }
767
- return [
768
- `Target file: ${relativePath}`,
769
- 'Repository summary:',
770
- contextSummary,
771
- '',
772
- 'Guidance:',
773
- ...guidance,
774
- '',
775
- 'Current content:',
776
- '<file>',
777
- currentContent,
778
- '</file>'
779
- ].join('\n');
780
- }
781
- function buildPlanUserPrompt(context) {
782
- const guidance = [
783
- '- Preserve the YAML front matter and `ai-task` wrapper already in the plan.',
784
- '- Replace TODOs with concrete steps that align with the provided documentation and agent playbooks.',
785
- '- Keep the Agent Lineup and Documentation Touchpoints tables accurate and sorted.',
786
- '- Ensure the work is segmented into phases, each with numbered steps, named owners, deliverables, evidence expectations, and a concluding Git commit checkpoint.',
787
- '- Return only the full updated Markdown for this plan.'
788
- ];
789
- const sections = [
790
- `Target file: ${context.relativePath}`,
791
- 'Repository summary:',
792
- context.contextSummary,
793
- '',
794
- 'Guidance:',
795
- ...guidance,
796
- '',
797
- 'Current plan:',
798
- '<plan>',
799
- context.planContent,
800
- '</plan>'
801
- ];
802
- if (context.docsIndex) {
803
- sections.push('', 'Documentation index (docs/README.md):', '<docs-index>', context.docsIndex, '</docs-index>');
804
- }
805
- if (context.agentsIndex) {
806
- sections.push('', 'Agent handbook (agents/README.md):', '<agents-index>', context.agentsIndex, '</agents-index>');
807
- }
808
- context.docs.forEach(doc => {
809
- sections.push('', `Referenced documentation (${doc.path}):`, '<doc>', doc.content, '</doc>');
810
- });
811
- context.agents.forEach(agent => {
812
- sections.push('', `Referenced agent playbook (${agent.path}):`, '<agent>', agent.content, '</agent>');
813
- });
814
- return sections.join('\n');
815
- }
816
- function extractPlanReferences(content, type) {
817
- const regex = type === 'docs'
818
- ? /\]\(\.\.\/docs\/([^)#]+)(?:#[^)]*)?\)/g
819
- : /\]\(\.\.\/agents\/([^)#]+)(?:#[^)]*)?\)/g;
820
- const references = [];
821
- let match;
822
- while ((match = regex.exec(content)) !== null) {
823
- const rawPath = match[1].trim();
824
- if (!rawPath)
825
- continue;
826
- const normalized = rawPath.replace(/^\.\//, '').replace(/#.*$/, '');
827
- if (!normalized || normalized.includes('..'))
828
- continue;
829
- if (!references.includes(normalized)) {
830
- references.push(normalized);
831
- }
832
- }
833
- return references;
834
- }
835
- async function loadReferencedMarkdown(baseDir, fileNames) {
836
- const results = [];
837
- const seen = new Set();
838
- for (const name of fileNames) {
839
- const cleanName = name.replace(/#.*$/, '');
840
- if (!cleanName || seen.has(cleanName)) {
841
- continue;
842
- }
843
- const normalized = path.normalize(cleanName).replace(/^\.\//, '');
844
- if (normalized.includes('..')) {
845
- continue;
846
- }
847
- const fullPath = path.join(baseDir, normalized);
848
- if (!(await fs.pathExists(fullPath))) {
849
- continue;
850
- }
851
- const content = await fs.readFile(fullPath, 'utf-8');
852
- results.push({ path: normalized, content });
853
- seen.add(cleanName);
854
- }
855
- return results;
856
- }
857
- function ensureTrailingNewline(content) {
858
- return content.endsWith('\n') ? content : `${content}\n`;
859
- }
860
- function printLlmSummary(usage, results, dryRun) {
861
- const updated = results.filter(r => r.status === 'updated').length;
862
- const skipped = results.filter(r => r.status === 'skipped').length;
863
- const failed = results.filter(r => r.status === 'failed');
864
- console.log('\n' + chalk_1.default.bold('📄 LLM Fill Summary'));
865
- console.log(chalk_1.default.gray('─'.repeat(50)));
866
- console.log(`${chalk_1.default.blue('Updated files:')} ${chalk_1.default.white(updated.toString())}`);
867
- console.log(`${chalk_1.default.blue('Skipped files:')} ${chalk_1.default.white(skipped.toString())}${dryRun ? chalk_1.default.gray(' (dry run)') : ''}`);
868
- console.log(`${chalk_1.default.blue('Failures:')} ${failed.length}`);
869
- if (usage.totalCalls > 0) {
870
- console.log(chalk_1.default.gray('─'.repeat(50)));
871
- console.log(`${chalk_1.default.blue('LLM calls:')} ${usage.totalCalls}`);
872
- console.log(`${chalk_1.default.blue('Prompt tokens:')} ${usage.totalPromptTokens}`);
873
- console.log(`${chalk_1.default.blue('Completion tokens:')} ${usage.totalCompletionTokens}`);
874
- console.log(`${chalk_1.default.blue('Estimated cost:')} ${usage.estimatedCost.toFixed(4)}`);
875
- console.log(`${chalk_1.default.blue('Model:')} ${usage.model}`);
876
- }
877
- if (failed.length > 0) {
878
- console.log(chalk_1.default.gray('─'.repeat(50)));
879
- failed.forEach(f => {
880
- console.log(`${chalk_1.default.red('✖')} ${chalk_1.default.white(f.file)} — ${chalk_1.default.gray(f.message || 'Unknown error')}`);
881
- });
882
- }
883
- }
884
- function parseDocSelection(input) {
885
- if (input === undefined) {
886
- return { selected: undefined, invalid: [], provided: false, explicitNone: false };
887
- }
888
- if (Array.isArray(input) && input.length === 0) {
889
- return { selected: [], invalid: [], provided: true, explicitNone: true };
890
- }
891
- const values = toStringArray(input);
892
- const normalized = values.map(value => value.toLowerCase().replace(/\.md$/, ''));
893
- const valid = Array.from(new Set(normalized.filter(key => guideRegistry_1.DOCUMENT_GUIDE_KEYS.includes(key))));
894
- const invalid = normalized.filter(key => !guideRegistry_1.DOCUMENT_GUIDE_KEYS.includes(key));
895
- if (values.length > 0 && valid.length === 0 && invalid.length > 0) {
896
- return { selected: undefined, invalid, provided: true, explicitNone: false };
897
- }
898
- return { selected: valid.length > 0 ? valid : undefined, invalid, provided: true, explicitNone: false };
899
- }
900
- function parseAgentSelection(input) {
901
- if (input === undefined) {
902
- return { selected: undefined, invalid: [], provided: false, explicitNone: false };
903
- }
904
- if (Array.isArray(input) && input.length === 0) {
905
- return { selected: [], invalid: [], provided: true, explicitNone: true };
906
- }
907
- const values = toStringArray(input);
908
- const normalized = values.map(value => value.toLowerCase().replace(/\.md$/, ''));
909
- const allowed = new Set(agentTypes_1.AGENT_TYPES);
910
- const valid = Array.from(new Set(normalized.filter(value => allowed.has(value))));
911
- const invalid = normalized.filter(value => !allowed.has(value));
912
- if (values.length > 0 && valid.length === 0 && invalid.length > 0) {
913
- return { selected: undefined, invalid, provided: true, explicitNone: false };
914
- }
915
- return { selected: valid.length > 0 ? valid : undefined, invalid, provided: true, explicitNone: false };
916
- }
917
- function shouldGenerateDocs(resolvedType, selection) {
918
- if (selection.explicitNone) {
919
- return false;
920
- }
921
- if (resolvedType === 'agents') {
922
- return false;
923
- }
924
- if (!selection.provided) {
925
- return resolvedType === 'docs' || resolvedType === 'both';
926
- }
927
- if (selection.selected && selection.selected.length === 0) {
928
- return false;
929
- }
930
- return resolvedType === 'docs' || resolvedType === 'both';
931
- }
932
- function shouldGenerateAgents(resolvedType, selection) {
933
- if (selection.explicitNone) {
934
- return false;
935
- }
936
- if (resolvedType === 'docs') {
937
- return false;
938
- }
939
- if (!selection.provided) {
940
- return resolvedType === 'agents' || resolvedType === 'both';
941
- }
942
- if (selection.selected && selection.selected.length === 0) {
943
- return false;
944
- }
945
- return resolvedType === 'agents' || resolvedType === 'both';
946
- }
947
- function toStringArray(input) {
948
- if (Array.isArray(input)) {
949
- return input.map(item => item.toString().trim()).filter(Boolean);
950
- }
951
- if (input === null || input === undefined) {
952
- return [];
953
- }
954
- return input
955
- .toString()
956
- .split(',')
957
- .map((part) => part.trim())
958
- .filter(Boolean);
959
- }
960
- function formatAgentLabel(value) {
961
- return value
962
- .split('-')
963
- .map(segment => segment.charAt(0).toUpperCase() + segment.slice(1))
964
- .join(' ');
324
+ await fillService.run(repoPath, rawOptions);
965
325
  }
966
326
  async function selectLocale(showWelcome) {
967
327
  const { locale } = await inquirer_1.default.prompt([
@@ -980,7 +340,7 @@ async function selectLocale(showWelcome) {
980
340
  currentLocale = normalizedLocale;
981
341
  translateFn = (0, i18n_1.createTranslator)(normalizedLocale);
982
342
  if (showWelcome) {
983
- ui.displayWelcome(VERSION);
343
+ ui.displayWelcome(version_1.VERSION);
984
344
  }
985
345
  }
986
346
  async function runInteractive() {
@@ -996,6 +356,7 @@ async function runInteractive() {
996
356
  { name: t('prompts.main.choice.scaffold'), value: 'scaffold' },
997
357
  { name: t('prompts.main.choice.fill'), value: 'fill' },
998
358
  { name: t('prompts.main.choice.plan'), value: 'plan' },
359
+ { name: t('prompts.main.choice.syncAgents'), value: 'syncAgents' },
999
360
  { name: t('prompts.main.choice.changeLanguage'), value: 'changeLanguage' },
1000
361
  { name: t('prompts.main.choice.exit'), value: 'exit' }
1001
362
  ]
@@ -1015,9 +376,12 @@ async function runInteractive() {
1015
376
  else if (action === 'fill') {
1016
377
  await runInteractiveLlmFill();
1017
378
  }
1018
- else {
379
+ else if (action === 'plan') {
1019
380
  await runInteractivePlan();
1020
381
  }
382
+ else if (action === 'syncAgents') {
383
+ await runInteractiveSync();
384
+ }
1021
385
  ui.displayInfo(t('info.interactive.returning.title'), t('info.interactive.returning.detail'));
1022
386
  }
1023
387
  ui.displaySuccess(t('success.interactive.goodbye'));
@@ -1041,58 +405,19 @@ async function runInteractiveScaffold() {
1041
405
  default: defaultOutput
1042
406
  }
1043
407
  ]);
1044
- const { includeDocs } = await inquirer_1.default.prompt([
1045
- {
1046
- type: 'confirm',
1047
- name: 'includeDocs',
1048
- message: t('prompts.scaffold.includeDocs'),
1049
- default: true
1050
- }
1051
- ]);
1052
- let selectedDocs;
1053
- if (includeDocs) {
1054
- const { docs } = await inquirer_1.default.prompt([
1055
- {
1056
- type: 'checkbox',
1057
- name: 'docs',
1058
- message: t('prompts.scaffold.selectDocs'),
1059
- choices: DOC_CHOICES,
1060
- default: DOC_CHOICES.map(choice => choice.value)
1061
- }
1062
- ]);
1063
- selectedDocs = docs;
1064
- }
1065
- else {
1066
- selectedDocs = [];
1067
- }
1068
- const { includeAgents } = await inquirer_1.default.prompt([
408
+ const { scaffoldType } = await inquirer_1.default.prompt([
1069
409
  {
1070
- type: 'confirm',
1071
- name: 'includeAgents',
1072
- message: t('prompts.scaffold.includeAgents'),
1073
- default: true
410
+ type: 'list',
411
+ name: 'scaffoldType',
412
+ message: t('prompts.scaffold.type'),
413
+ choices: [
414
+ { name: t('prompts.scaffold.typeBoth'), value: 'both' },
415
+ { name: t('prompts.scaffold.typeDocs'), value: 'docs' },
416
+ { name: t('prompts.scaffold.typeAgents'), value: 'agents' }
417
+ ],
418
+ default: 'both'
1074
419
  }
1075
420
  ]);
1076
- let selectedAgents;
1077
- if (includeAgents) {
1078
- const { agents } = await inquirer_1.default.prompt([
1079
- {
1080
- type: 'checkbox',
1081
- name: 'agents',
1082
- message: t('prompts.scaffold.selectAgents'),
1083
- choices: AGENT_CHOICES,
1084
- default: AGENT_CHOICES.map(choice => choice.value)
1085
- }
1086
- ]);
1087
- selectedAgents = agents;
1088
- }
1089
- else {
1090
- selectedAgents = [];
1091
- }
1092
- if ((selectedDocs?.length ?? 0) === 0 && (selectedAgents?.length ?? 0) === 0) {
1093
- ui.displayWarning(t('warnings.interactive.nothingSelected'));
1094
- return;
1095
- }
1096
421
  const { verbose } = await inquirer_1.default.prompt([
1097
422
  {
1098
423
  type: 'confirm',
@@ -1101,30 +426,67 @@ async function runInteractiveScaffold() {
1101
426
  default: false
1102
427
  }
1103
428
  ]);
1104
- const scaffoldType = determineScaffoldType(selectedDocs, selectedAgents);
1105
429
  await runInit(resolvedRepo, scaffoldType, {
1106
430
  output: outputDir,
1107
- docs: selectedDocs,
1108
- agents: selectedAgents,
1109
- verbose
431
+ verbose,
432
+ semantic: true
1110
433
  });
1111
434
  }
1112
- function determineScaffoldType(docSelection, agentSelection) {
1113
- const docsSelected = docSelection === undefined ? true : docSelection.length > 0;
1114
- const agentsSelected = agentSelection === undefined ? true : agentSelection.length > 0;
1115
- if (docsSelected && agentsSelected)
1116
- return 'both';
1117
- if (docsSelected)
1118
- return 'docs';
1119
- return 'agents';
1120
- }
1121
435
  async function runInteractiveLlmFill() {
436
+ const defaults = await (0, prompts_1.detectSmartDefaults)();
437
+ const interactiveMode = await (0, prompts_1.promptInteractiveMode)(t);
438
+ if (interactiveMode === 'quick') {
439
+ // Quick mode: minimal prompts with smart defaults
440
+ const { confirmRepo } = await inquirer_1.default.prompt([
441
+ {
442
+ type: 'confirm',
443
+ name: 'confirmRepo',
444
+ message: `${t('prompts.quick.confirmRepo')} (${defaults.repoPath})`,
445
+ default: true
446
+ }
447
+ ]);
448
+ const resolvedRepo = confirmRepo ? defaults.repoPath : (await inquirer_1.default.prompt([
449
+ { type: 'input', name: 'repoPath', message: t('prompts.fill.repoPath'), default: defaults.repoPath }
450
+ ])).repoPath;
451
+ // Get LLM config (auto-detected or prompt for API key)
452
+ const llmConfig = await (0, prompts_1.promptLLMConfig)(t, { defaultModel: DEFAULT_MODEL, skipIfConfigured: true });
453
+ // Build summary
454
+ const summary = {
455
+ operation: 'fill',
456
+ repoPath: resolvedRepo,
457
+ outputDir: defaults.outputDir,
458
+ provider: llmConfig.provider,
459
+ model: llmConfig.model,
460
+ apiKeySource: llmConfig.autoDetected ? 'env' : llmConfig.apiKey ? 'provided' : 'none',
461
+ options: {
462
+ Semantic: true,
463
+ Languages: defaults.detectedLanguages.join(', '),
464
+ LSP: false
465
+ }
466
+ };
467
+ (0, prompts_1.displayConfigSummary)(summary, t);
468
+ const proceed = await (0, prompts_1.promptConfirmProceed)(t);
469
+ if (proceed) {
470
+ await fillService.run(resolvedRepo, {
471
+ output: defaults.outputDir,
472
+ model: llmConfig.model,
473
+ provider: llmConfig.provider,
474
+ apiKey: llmConfig.apiKey,
475
+ verbose: false,
476
+ semantic: true,
477
+ languages: defaults.detectedLanguages,
478
+ useLsp: false
479
+ });
480
+ }
481
+ return;
482
+ }
483
+ // Advanced mode: full configuration
1122
484
  const { repoPath } = await inquirer_1.default.prompt([
1123
485
  {
1124
486
  type: 'input',
1125
487
  name: 'repoPath',
1126
488
  message: t('prompts.fill.repoPath'),
1127
- default: process.cwd()
489
+ default: defaults.repoPath
1128
490
  }
1129
491
  ]);
1130
492
  const resolvedRepo = path.resolve(repoPath.trim() || '.');
@@ -1144,20 +506,6 @@ async function runInteractiveLlmFill() {
1144
506
  }
1145
507
  ]);
1146
508
  const promptPath = promptPathInput.trim() ? path.resolve(promptPathInput.trim()) : undefined;
1147
- const { dryRun, processAll } = await inquirer_1.default.prompt([
1148
- {
1149
- type: 'confirm',
1150
- name: 'dryRun',
1151
- message: t('prompts.fill.dryRun'),
1152
- default: true
1153
- },
1154
- {
1155
- type: 'confirm',
1156
- name: 'processAll',
1157
- message: t('prompts.fill.processAll'),
1158
- default: false
1159
- }
1160
- ]);
1161
509
  const { limit } = await inquirer_1.default.prompt([
1162
510
  {
1163
511
  type: 'input',
@@ -1168,131 +516,49 @@ async function runInteractiveLlmFill() {
1168
516
  ]);
1169
517
  const limitValue = limit ? parseInt(limit, 10) : undefined;
1170
518
  const parsedLimit = Number.isNaN(limitValue) ? undefined : limitValue;
1171
- const { includeDocs } = await inquirer_1.default.prompt([
1172
- {
1173
- type: 'confirm',
1174
- name: 'includeDocs',
1175
- message: t('prompts.fill.includeDocs'),
1176
- default: true
1177
- }
1178
- ]);
1179
- let selectedDocs;
1180
- if (includeDocs) {
1181
- const { docs } = await inquirer_1.default.prompt([
1182
- {
1183
- type: 'checkbox',
1184
- name: 'docs',
1185
- message: t('prompts.fill.selectDocs'),
1186
- choices: DOC_CHOICES,
1187
- default: DOC_CHOICES.map(choice => choice.value)
1188
- }
1189
- ]);
1190
- selectedDocs = docs;
1191
- }
1192
- else {
1193
- selectedDocs = [];
1194
- }
1195
- const { includeAgents } = await inquirer_1.default.prompt([
1196
- {
1197
- type: 'confirm',
1198
- name: 'includeAgents',
1199
- message: t('prompts.fill.includeAgents'),
1200
- default: true
1201
- }
1202
- ]);
1203
- let selectedAgents;
1204
- if (includeAgents) {
1205
- const { agents } = await inquirer_1.default.prompt([
1206
- {
1207
- type: 'checkbox',
1208
- name: 'agents',
1209
- message: t('prompts.fill.selectAgents'),
1210
- choices: AGENT_CHOICES,
1211
- default: AGENT_CHOICES.map(choice => choice.value)
1212
- }
1213
- ]);
1214
- selectedAgents = agents;
1215
- }
1216
- else {
1217
- selectedAgents = [];
1218
- }
1219
- if ((selectedDocs?.length ?? 0) === 0 && (selectedAgents?.length ?? 0) === 0) {
1220
- ui.displayWarning(t('warnings.interactive.nothingSelected'));
1221
- return;
1222
- }
1223
- const { specifyModel } = await inquirer_1.default.prompt([
1224
- {
1225
- type: 'confirm',
1226
- name: 'specifyModel',
1227
- message: t('prompts.fill.overrideModel'),
1228
- default: false
1229
- }
1230
- ]);
1231
- let provider;
1232
- let model;
1233
- if (specifyModel) {
1234
- const providerAnswer = await inquirer_1.default.prompt([
1235
- {
1236
- type: 'list',
1237
- name: 'provider',
1238
- message: t('prompts.fill.provider'),
1239
- choices: ['openrouter', 'openai', 'anthropic', 'gemini', 'grok']
1240
- }
1241
- ]);
1242
- provider = providerAnswer.provider;
1243
- const modelAnswer = await inquirer_1.default.prompt([
1244
- {
1245
- type: 'input',
1246
- name: 'model',
1247
- message: t('prompts.fill.model'),
1248
- default: DEFAULT_MODEL
1249
- }
1250
- ]);
1251
- model = modelAnswer.model.trim();
1252
- }
1253
- const { provideApiKey } = await inquirer_1.default.prompt([
1254
- {
1255
- type: 'confirm',
1256
- name: 'provideApiKey',
1257
- message: t('prompts.fill.provideApiKey'),
1258
- default: false
519
+ // Use shared LLM prompt helper
520
+ const llmConfig = await (0, prompts_1.promptLLMConfig)(t, { defaultModel: DEFAULT_MODEL, skipIfConfigured: false });
521
+ // Use shared analysis options prompt
522
+ const analysisOptions = await (0, prompts_1.promptAnalysisOptions)(t, {
523
+ languages: defaults.detectedLanguages,
524
+ useLsp: false
525
+ });
526
+ // Show summary before execution
527
+ const summary = {
528
+ operation: 'fill',
529
+ repoPath: resolvedRepo,
530
+ outputDir,
531
+ provider: llmConfig.provider,
532
+ model: llmConfig.model,
533
+ apiKeySource: llmConfig.autoDetected ? 'env' : llmConfig.apiKey ? 'provided' : 'none',
534
+ options: {
535
+ Semantic: analysisOptions.semantic,
536
+ Languages: analysisOptions.languages?.join(', ') || 'none',
537
+ LSP: analysisOptions.useLsp,
538
+ Verbose: analysisOptions.verbose,
539
+ ...(parsedLimit ? { Limit: String(parsedLimit) } : {})
1259
540
  }
1260
- ]);
1261
- let apiKey;
1262
- if (provideApiKey) {
1263
- const apiKeyAnswer = await inquirer_1.default.prompt([
1264
- {
1265
- type: 'password',
1266
- name: 'apiKey',
1267
- message: t('prompts.fill.apiKey'),
1268
- mask: '*'
1269
- }
1270
- ]);
1271
- apiKey = apiKeyAnswer.apiKey.trim();
541
+ };
542
+ (0, prompts_1.displayConfigSummary)(summary, t);
543
+ const proceed = await (0, prompts_1.promptConfirmProceed)(t);
544
+ if (proceed) {
545
+ await fillService.run(resolvedRepo, {
546
+ output: outputDir,
547
+ prompt: promptPath,
548
+ limit: parsedLimit,
549
+ model: llmConfig.model,
550
+ provider: llmConfig.provider,
551
+ apiKey: llmConfig.apiKey,
552
+ verbose: analysisOptions.verbose,
553
+ semantic: analysisOptions.semantic,
554
+ languages: analysisOptions.languages,
555
+ useLsp: analysisOptions.useLsp
556
+ });
1272
557
  }
1273
- const { verbose } = await inquirer_1.default.prompt([
1274
- {
1275
- type: 'confirm',
1276
- name: 'verbose',
1277
- message: t('prompts.common.verbose'),
1278
- default: false
1279
- }
1280
- ]);
1281
- await runLlmFill(resolvedRepo, {
1282
- output: outputDir,
1283
- prompt: promptPath,
1284
- docs: selectedDocs,
1285
- agents: selectedAgents,
1286
- dryRun,
1287
- all: processAll,
1288
- limit: parsedLimit,
1289
- model,
1290
- provider,
1291
- apiKey,
1292
- verbose
1293
- });
1294
558
  }
1295
559
  async function runInteractivePlan() {
560
+ const defaults = await (0, prompts_1.detectSmartDefaults)();
561
+ // Always ask for plan name first
1296
562
  const { planName } = await inquirer_1.default.prompt([
1297
563
  {
1298
564
  type: 'input',
@@ -1301,6 +567,82 @@ async function runInteractivePlan() {
1301
567
  default: 'new-plan'
1302
568
  }
1303
569
  ]);
570
+ const interactiveMode = await (0, prompts_1.promptInteractiveMode)(t);
571
+ if (interactiveMode === 'quick') {
572
+ // Quick mode: choose scaffold or fill with defaults
573
+ const { action } = await inquirer_1.default.prompt([
574
+ {
575
+ type: 'list',
576
+ name: 'action',
577
+ message: t('prompts.plan.mode'),
578
+ choices: [
579
+ { name: t('prompts.plan.modeScaffold'), value: 'scaffold' },
580
+ { name: t('prompts.plan.modeFill'), value: 'fill' }
581
+ ],
582
+ default: 'scaffold'
583
+ }
584
+ ]);
585
+ if (action === 'scaffold') {
586
+ // Quick scaffold: just create the template
587
+ const generator = new planGenerator_1.PlanGenerator();
588
+ ui.startSpinner(t('spinner.plan.creating'));
589
+ try {
590
+ const result = await generator.generatePlan({
591
+ planName,
592
+ outputDir: defaults.outputDir,
593
+ verbose: false,
594
+ semantic: true,
595
+ projectPath: defaults.repoPath
596
+ });
597
+ ui.updateSpinner(t('spinner.plan.created'), 'success');
598
+ ui.displaySuccess(t('success.plan.createdAt', { path: theme_1.colors.accent(result.relativePath) }));
599
+ }
600
+ catch (error) {
601
+ ui.updateSpinner(t('spinner.plan.creationFailed'), 'fail');
602
+ ui.displayError(t('errors.plan.creationFailed'), error);
603
+ }
604
+ finally {
605
+ ui.stopSpinner();
606
+ }
607
+ return;
608
+ }
609
+ // Quick fill: use auto-detected LLM config
610
+ const llmConfig = await (0, prompts_1.promptLLMConfig)(t, { defaultModel: DEFAULT_MODEL, skipIfConfigured: true });
611
+ const summary = {
612
+ operation: 'plan',
613
+ repoPath: defaults.repoPath,
614
+ outputDir: defaults.outputDir,
615
+ provider: llmConfig.provider,
616
+ model: llmConfig.model,
617
+ apiKeySource: llmConfig.autoDetected ? 'env' : llmConfig.apiKey ? 'provided' : 'none',
618
+ options: {
619
+ 'Plan Name': planName,
620
+ LSP: true,
621
+ 'Dry Run': false
622
+ }
623
+ };
624
+ (0, prompts_1.displayConfigSummary)(summary, t);
625
+ const proceed = await (0, prompts_1.promptConfirmProceed)(t);
626
+ if (proceed) {
627
+ try {
628
+ await planService.scaffoldPlanIfNeeded(planName, defaults.outputDir, {});
629
+ await planService.fillPlan(planName, {
630
+ output: defaults.outputDir,
631
+ repo: defaults.repoPath,
632
+ dryRun: false,
633
+ provider: llmConfig.provider,
634
+ model: llmConfig.model,
635
+ apiKey: llmConfig.apiKey,
636
+ lsp: true
637
+ });
638
+ }
639
+ catch (error) {
640
+ ui.displayError(t('errors.plan.fillFailed'), error);
641
+ }
642
+ }
643
+ return;
644
+ }
645
+ // Advanced mode: full configuration
1304
646
  const defaultOutput = path.resolve(process.cwd(), '.context');
1305
647
  const { mode } = await inquirer_1.default.prompt([
1306
648
  {
@@ -1331,50 +673,6 @@ async function runInteractivePlan() {
1331
673
  filter: (value) => value.trim()
1332
674
  }
1333
675
  ]);
1334
- const { includeAgents } = await inquirer_1.default.prompt([
1335
- {
1336
- type: 'confirm',
1337
- name: 'includeAgents',
1338
- message: t('prompts.plan.includeAgents'),
1339
- default: true
1340
- }
1341
- ]);
1342
- let selectedAgents = [];
1343
- if (includeAgents) {
1344
- const { agents } = await inquirer_1.default.prompt([
1345
- {
1346
- type: 'checkbox',
1347
- name: 'agents',
1348
- message: t('prompts.plan.selectAgents'),
1349
- choices: AGENT_CHOICES,
1350
- default: AGENT_CHOICES.map(choice => choice.value)
1351
- }
1352
- ]);
1353
- selectedAgents = agents;
1354
- }
1355
- const { includeDocs } = await inquirer_1.default.prompt([
1356
- {
1357
- type: 'confirm',
1358
- name: 'includeDocs',
1359
- message: t('prompts.plan.includeDocs'),
1360
- default: true
1361
- }
1362
- ]);
1363
- let selectedDocs = [];
1364
- if (includeDocs) {
1365
- const { docs } = await inquirer_1.default.prompt([
1366
- {
1367
- type: 'checkbox',
1368
- name: 'docs',
1369
- message: t('prompts.plan.selectDocs'),
1370
- choices: DOC_CHOICES,
1371
- default: DOC_CHOICES.map(choice => choice.value)
1372
- }
1373
- ]);
1374
- selectedDocs = docs;
1375
- }
1376
- const agentSelection = parseAgentSelection(selectedAgents);
1377
- const docSelection = parseDocSelection(selectedDocs);
1378
676
  const { repoPath } = await inquirer_1.default.prompt([
1379
677
  {
1380
678
  type: 'input',
@@ -1383,6 +681,8 @@ async function runInteractivePlan() {
1383
681
  default: process.cwd()
1384
682
  }
1385
683
  ]);
684
+ // Use shared LLM prompt helper
685
+ const llmConfig = await (0, prompts_1.promptLLMConfig)(t, { defaultModel: DEFAULT_MODEL, skipIfConfigured: false });
1386
686
  const { dryRun } = await inquirer_1.default.prompt([
1387
687
  {
1388
688
  type: 'confirm',
@@ -1391,24 +691,53 @@ async function runInteractivePlan() {
1391
691
  default: true
1392
692
  }
1393
693
  ]);
1394
- try {
1395
- const resolvedOutput = path.resolve(outputDir.trim() || defaultOutput);
1396
- await scaffoldPlanIfNeeded(planName, resolvedOutput, {
1397
- summary: summary || undefined,
1398
- agentSelection,
1399
- docSelection
1400
- });
1401
- await runPlanFill(planName, {
1402
- output: resolvedOutput,
1403
- repo: repoPath,
1404
- dryRun
1405
- });
1406
- }
1407
- catch (error) {
1408
- ui.displayError(t('errors.plan.fillFailed'), error);
694
+ const { useLsp } = await inquirer_1.default.prompt([
695
+ {
696
+ type: 'confirm',
697
+ name: 'useLsp',
698
+ message: t('prompts.plan.useLsp'),
699
+ default: true
700
+ }
701
+ ]);
702
+ // Show summary before execution
703
+ const configSummary = {
704
+ operation: 'plan',
705
+ repoPath,
706
+ outputDir,
707
+ provider: llmConfig.provider,
708
+ model: llmConfig.model,
709
+ apiKeySource: llmConfig.autoDetected ? 'env' : llmConfig.apiKey ? 'provided' : 'none',
710
+ options: {
711
+ 'Plan Name': planName,
712
+ LSP: useLsp,
713
+ 'Dry Run': dryRun
714
+ }
715
+ };
716
+ (0, prompts_1.displayConfigSummary)(configSummary, t);
717
+ const proceed = await (0, prompts_1.promptConfirmProceed)(t);
718
+ if (proceed) {
719
+ try {
720
+ const resolvedOutput = path.resolve(outputDir.trim() || defaultOutput);
721
+ await planService.scaffoldPlanIfNeeded(planName, resolvedOutput, {
722
+ summary: summary || undefined
723
+ });
724
+ await planService.fillPlan(planName, {
725
+ output: resolvedOutput,
726
+ repo: repoPath,
727
+ dryRun,
728
+ provider: llmConfig.provider,
729
+ model: llmConfig.model,
730
+ apiKey: llmConfig.apiKey,
731
+ lsp: useLsp
732
+ });
733
+ }
734
+ catch (error) {
735
+ ui.displayError(t('errors.plan.fillFailed'), error);
736
+ }
1409
737
  }
1410
738
  return;
1411
739
  }
740
+ // Scaffold mode
1412
741
  const { summary } = await inquirer_1.default.prompt([
1413
742
  {
1414
743
  type: 'input',
@@ -1417,48 +746,6 @@ async function runInteractivePlan() {
1417
746
  filter: (value) => value.trim()
1418
747
  }
1419
748
  ]);
1420
- const { includeAgents } = await inquirer_1.default.prompt([
1421
- {
1422
- type: 'confirm',
1423
- name: 'includeAgents',
1424
- message: t('prompts.plan.includeAgents'),
1425
- default: true
1426
- }
1427
- ]);
1428
- let selectedAgents = null;
1429
- if (includeAgents) {
1430
- const { agents } = await inquirer_1.default.prompt([
1431
- {
1432
- type: 'checkbox',
1433
- name: 'agents',
1434
- message: t('prompts.plan.selectAgents'),
1435
- choices: AGENT_CHOICES,
1436
- default: AGENT_CHOICES.map(choice => choice.value)
1437
- }
1438
- ]);
1439
- selectedAgents = agents.length > 0 ? agents : null;
1440
- }
1441
- const { includeDocs } = await inquirer_1.default.prompt([
1442
- {
1443
- type: 'confirm',
1444
- name: 'includeDocs',
1445
- message: t('prompts.plan.includeDocs'),
1446
- default: true
1447
- }
1448
- ]);
1449
- let selectedDocs = null;
1450
- if (includeDocs) {
1451
- const { docs } = await inquirer_1.default.prompt([
1452
- {
1453
- type: 'checkbox',
1454
- name: 'docs',
1455
- message: t('prompts.plan.selectDocs'),
1456
- choices: DOC_CHOICES,
1457
- default: DOC_CHOICES.map(choice => choice.value)
1458
- }
1459
- ]);
1460
- selectedDocs = docs.length > 0 ? docs : null;
1461
- }
1462
749
  const generator = new planGenerator_1.PlanGenerator();
1463
750
  ui.startSpinner(t('spinner.plan.creating'));
1464
751
  try {
@@ -1466,12 +753,12 @@ async function runInteractivePlan() {
1466
753
  planName,
1467
754
  outputDir: path.resolve(outputDir.trim() || defaultOutput),
1468
755
  summary: summary || undefined,
1469
- selectedAgentTypes: selectedAgents,
1470
- selectedDocKeys: selectedDocs,
1471
- verbose: false
756
+ verbose: false,
757
+ semantic: true,
758
+ projectPath: path.resolve(outputDir.trim() || defaultOutput, '..')
1472
759
  });
1473
760
  ui.updateSpinner(t('spinner.plan.created'), 'success');
1474
- ui.displaySuccess(t('success.plan.createdAt', { path: chalk_1.default.cyan(result.relativePath) }));
761
+ ui.displaySuccess(t('success.plan.createdAt', { path: theme_1.colors.accent(result.relativePath) }));
1475
762
  }
1476
763
  catch (error) {
1477
764
  ui.updateSpinner(t('spinner.plan.creationFailed'), 'fail');
@@ -1481,15 +768,81 @@ async function runInteractivePlan() {
1481
768
  ui.stopSpinner();
1482
769
  }
1483
770
  }
1484
- function getAgentFilesByTypes(types) {
1485
- if (!types || types.length === 0) {
1486
- return undefined;
771
+ async function runInteractiveSync() {
772
+ const defaults = await (0, prompts_1.detectSmartDefaults)();
773
+ const defaultSource = path.resolve(defaults.repoPath, '.context/agents');
774
+ // Simplified: single prompt for target selection with common presets
775
+ const { quickTarget } = await inquirer_1.default.prompt([
776
+ {
777
+ type: 'list',
778
+ name: 'quickTarget',
779
+ message: t('prompts.sync.quickTarget'),
780
+ choices: [
781
+ { name: t('prompts.sync.quickTarget.common'), value: 'common' },
782
+ { name: t('prompts.sync.quickTarget.claude'), value: 'claude' },
783
+ { name: t('prompts.sync.quickTarget.all'), value: 'all' },
784
+ { name: t('prompts.sync.quickTarget.custom'), value: 'custom' }
785
+ ],
786
+ default: 'common'
787
+ }
788
+ ]);
789
+ let preset;
790
+ let target;
791
+ let sourcePath = defaultSource;
792
+ if (quickTarget === 'custom') {
793
+ // Custom path: ask for source and target
794
+ const answers = await inquirer_1.default.prompt([
795
+ {
796
+ type: 'input',
797
+ name: 'sourcePath',
798
+ message: t('prompts.sync.source'),
799
+ default: defaultSource
800
+ },
801
+ {
802
+ type: 'input',
803
+ name: 'customPath',
804
+ message: t('prompts.sync.customPath')
805
+ }
806
+ ]);
807
+ sourcePath = answers.sourcePath;
808
+ target = [answers.customPath];
809
+ }
810
+ else if (quickTarget === 'common') {
811
+ // Common: Claude + GitHub - use explicit target paths instead of preset
812
+ target = [
813
+ path.resolve(defaults.repoPath, '.claude/agents'),
814
+ path.resolve(defaults.repoPath, '.github/agents')
815
+ ];
816
+ }
817
+ else {
818
+ preset = quickTarget;
819
+ }
820
+ // Show summary
821
+ const summary = {
822
+ operation: 'sync',
823
+ repoPath: sourcePath,
824
+ options: {
825
+ Target: quickTarget === 'custom' ? (target?.[0] || 'custom') : quickTarget,
826
+ Mode: 'symlink'
827
+ }
828
+ };
829
+ (0, prompts_1.displayConfigSummary)(summary, t);
830
+ const proceed = await (0, prompts_1.promptConfirmProceed)(t);
831
+ if (proceed) {
832
+ try {
833
+ await syncService.run({
834
+ source: sourcePath,
835
+ mode: 'symlink',
836
+ preset: preset,
837
+ target,
838
+ force: false,
839
+ dryRun: false
840
+ });
841
+ }
842
+ catch (error) {
843
+ ui.displayError(t('errors.sync.failed'), error);
844
+ }
1487
845
  }
1488
- const allowed = new Set(agentTypes_1.AGENT_TYPES);
1489
- const files = types
1490
- .filter(type => allowed.has(type))
1491
- .map(type => `${type}.md`);
1492
- return files.length ? new Set(files) : undefined;
1493
846
  }
1494
847
  function filterOutLocaleArgs(args) {
1495
848
  const filtered = [];
@@ -1516,10 +869,43 @@ async function main() {
1516
869
  }
1517
870
  await program.parseAsync(process.argv);
1518
871
  }
872
+ /**
873
+ * Check if an error is from user interrupt (Ctrl+C)
874
+ */
875
+ function isUserInterrupt(error) {
876
+ if (error instanceof Error) {
877
+ // Inquirer's ExitPromptError when user presses Ctrl+C
878
+ if (error.name === 'ExitPromptError')
879
+ return true;
880
+ // Check message patterns
881
+ if (error.message.includes('force closed'))
882
+ return true;
883
+ if (error.message.includes('User force closed'))
884
+ return true;
885
+ }
886
+ return false;
887
+ }
888
+ /**
889
+ * Handle graceful exit
890
+ */
891
+ function handleGracefulExit() {
892
+ console.log('');
893
+ ui.displaySuccess(t('success.interactive.goodbye'));
894
+ process.exit(0);
895
+ }
896
+ // Handle SIGINT (Ctrl+C) at process level
897
+ process.on('SIGINT', () => {
898
+ handleGracefulExit();
899
+ });
1519
900
  if (require.main === module) {
1520
901
  main().catch(error => {
1521
- ui.displayError(t('errors.cli.executionFailed'), error);
1522
- process.exit(1);
902
+ if (isUserInterrupt(error)) {
903
+ handleGracefulExit();
904
+ }
905
+ else {
906
+ ui.displayError(t('errors.cli.executionFailed'), error);
907
+ process.exit(1);
908
+ }
1523
909
  });
1524
910
  }
1525
911
  //# sourceMappingURL=index.js.map