@nanocollective/nanocoder 1.20.4 → 1.22.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 (486) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +157 -72
  3. package/assets/nanocoder-vscode.vsix +0 -0
  4. package/dist/ai-sdk-client/ai-sdk-client.d.ts.map +1 -1
  5. package/dist/ai-sdk-client/ai-sdk-client.js.map +1 -1
  6. package/dist/ai-sdk-client/chat/chat-handler.d.ts +1 -0
  7. package/dist/ai-sdk-client/chat/chat-handler.d.ts.map +1 -1
  8. package/dist/ai-sdk-client/chat/chat-handler.js +66 -7
  9. package/dist/ai-sdk-client/chat/chat-handler.js.map +1 -1
  10. package/dist/ai-sdk-client/error-handling/tool-error-detector.d.ts +8 -0
  11. package/dist/ai-sdk-client/error-handling/tool-error-detector.d.ts.map +1 -0
  12. package/dist/ai-sdk-client/error-handling/tool-error-detector.js +52 -0
  13. package/dist/ai-sdk-client/error-handling/tool-error-detector.js.map +1 -0
  14. package/dist/ai-sdk-client/providers/provider-factory.d.ts +6 -3
  15. package/dist/ai-sdk-client/providers/provider-factory.d.ts.map +1 -1
  16. package/dist/ai-sdk-client/providers/provider-factory.js +18 -4
  17. package/dist/ai-sdk-client/providers/provider-factory.js.map +1 -1
  18. package/dist/ai-sdk-client/tools/tool-prompt-formatter.d.ts +8 -0
  19. package/dist/ai-sdk-client/tools/tool-prompt-formatter.d.ts.map +1 -0
  20. package/dist/ai-sdk-client/tools/tool-prompt-formatter.js +97 -0
  21. package/dist/ai-sdk-client/tools/tool-prompt-formatter.js.map +1 -0
  22. package/dist/app/App.d.ts.map +1 -1
  23. package/dist/app/App.js +22 -12
  24. package/dist/app/App.js.map +1 -1
  25. package/dist/app/components/modal-selectors.d.ts +6 -7
  26. package/dist/app/components/modal-selectors.d.ts.map +1 -1
  27. package/dist/app/components/modal-selectors.js +10 -10
  28. package/dist/app/components/modal-selectors.js.map +1 -1
  29. package/dist/app/components/settings-selector.d.ts +6 -0
  30. package/dist/app/components/settings-selector.d.ts.map +1 -0
  31. package/dist/app/components/settings-selector.js +289 -0
  32. package/dist/app/components/settings-selector.js.map +1 -0
  33. package/dist/app/utils/app-util.d.ts.map +1 -1
  34. package/dist/app/utils/app-util.js +178 -13
  35. package/dist/app/utils/app-util.js.map +1 -1
  36. package/dist/cli.js +22 -0
  37. package/dist/cli.js.map +1 -1
  38. package/dist/client-factory.d.ts.map +1 -1
  39. package/dist/client-factory.js +23 -20
  40. package/dist/client-factory.js.map +1 -1
  41. package/dist/commands/clear.d.ts.map +1 -1
  42. package/dist/commands/clear.js +8 -5
  43. package/dist/commands/clear.js.map +1 -1
  44. package/dist/commands/compact.d.ts +24 -0
  45. package/dist/commands/compact.d.ts.map +1 -0
  46. package/dist/commands/compact.js +31 -0
  47. package/dist/commands/compact.js.map +1 -0
  48. package/dist/commands/custom-commands.d.ts.map +1 -1
  49. package/dist/commands/custom-commands.js +1 -1
  50. package/dist/commands/custom-commands.js.map +1 -1
  51. package/dist/commands/exit.d.ts +1 -0
  52. package/dist/commands/exit.d.ts.map +1 -1
  53. package/dist/commands/exit.js +14 -0
  54. package/dist/commands/exit.js.map +1 -1
  55. package/dist/commands/explorer.d.ts +3 -0
  56. package/dist/commands/explorer.d.ts.map +1 -0
  57. package/dist/commands/explorer.js +10 -0
  58. package/dist/commands/explorer.js.map +1 -0
  59. package/dist/commands/help.d.ts.map +1 -1
  60. package/dist/commands/help.js +1 -1
  61. package/dist/commands/help.js.map +1 -1
  62. package/dist/commands/index.d.ts +6 -3
  63. package/dist/commands/index.d.ts.map +1 -1
  64. package/dist/commands/index.js +6 -3
  65. package/dist/commands/index.js.map +1 -1
  66. package/dist/commands/init.d.ts.map +1 -1
  67. package/dist/commands/init.js +1 -1
  68. package/dist/commands/init.js.map +1 -1
  69. package/dist/commands/lsp.d.ts.map +1 -1
  70. package/dist/commands/lsp.js +1 -1
  71. package/dist/commands/lsp.js.map +1 -1
  72. package/dist/commands/mcp.d.ts.map +1 -1
  73. package/dist/commands/mcp.js +15 -21
  74. package/dist/commands/mcp.js.map +1 -1
  75. package/dist/commands/model-database.d.ts.map +1 -1
  76. package/dist/commands/model-database.js +3 -3
  77. package/dist/commands/model-database.js.map +1 -1
  78. package/dist/commands/settings.d.ts +3 -0
  79. package/dist/commands/settings.d.ts.map +1 -0
  80. package/dist/commands/{theme.js → settings.js} +4 -4
  81. package/dist/commands/settings.js.map +1 -0
  82. package/dist/commands/setup-mcp.d.ts +3 -0
  83. package/dist/commands/setup-mcp.d.ts.map +1 -0
  84. package/dist/commands/setup-mcp.js +15 -0
  85. package/dist/commands/setup-mcp.js.map +1 -0
  86. package/dist/commands/setup-providers.d.ts +3 -0
  87. package/dist/commands/setup-providers.d.ts.map +1 -0
  88. package/dist/commands/{setup-config.js → setup-providers.js} +4 -4
  89. package/dist/commands/setup-providers.js.map +1 -0
  90. package/dist/commands/tasks.d.ts +3 -0
  91. package/dist/commands/tasks.d.ts.map +1 -0
  92. package/dist/commands/tasks.js +117 -0
  93. package/dist/commands/tasks.js.map +1 -0
  94. package/dist/commands/usage.d.ts.map +1 -1
  95. package/dist/commands/usage.js +31 -9
  96. package/dist/commands/usage.js.map +1 -1
  97. package/dist/components/assistant-message.d.ts.map +1 -1
  98. package/dist/components/assistant-message.js +39 -6
  99. package/dist/components/assistant-message.js.map +1 -1
  100. package/dist/components/checkpoint-selector.d.ts.map +1 -1
  101. package/dist/components/checkpoint-selector.js +3 -3
  102. package/dist/components/checkpoint-selector.js.map +1 -1
  103. package/dist/components/file-explorer/index.d.ts +3 -0
  104. package/dist/components/file-explorer/index.d.ts.map +1 -0
  105. package/dist/components/file-explorer/index.js +318 -0
  106. package/dist/components/file-explorer/index.js.map +1 -0
  107. package/dist/components/file-explorer/tree-item.d.ts +3 -0
  108. package/dist/components/file-explorer/tree-item.d.ts.map +1 -0
  109. package/dist/components/file-explorer/tree-item.js +42 -0
  110. package/dist/components/file-explorer/tree-item.js.map +1 -0
  111. package/dist/components/file-explorer/utils.d.ts +18 -0
  112. package/dist/components/file-explorer/utils.d.ts.map +1 -0
  113. package/dist/components/file-explorer/utils.js +51 -0
  114. package/dist/components/file-explorer/utils.js.map +1 -0
  115. package/dist/components/file-explorer.d.ts +2 -0
  116. package/dist/components/file-explorer.d.ts.map +1 -0
  117. package/dist/components/file-explorer.js +3 -0
  118. package/dist/components/file-explorer.js.map +1 -0
  119. package/dist/components/message-box.d.ts +1 -0
  120. package/dist/components/message-box.d.ts.map +1 -1
  121. package/dist/components/message-box.js +2 -2
  122. package/dist/components/message-box.js.map +1 -1
  123. package/dist/components/model-selector.d.ts.map +1 -1
  124. package/dist/components/model-selector.js +3 -3
  125. package/dist/components/model-selector.js.map +1 -1
  126. package/dist/components/provider-selector.d.ts.map +1 -1
  127. package/dist/components/provider-selector.js +1 -1
  128. package/dist/components/provider-selector.js.map +1 -1
  129. package/dist/components/security-disclaimer.d.ts.map +1 -1
  130. package/dist/components/security-disclaimer.js +1 -1
  131. package/dist/components/security-disclaimer.js.map +1 -1
  132. package/dist/components/status.d.ts +11 -0
  133. package/dist/components/status.d.ts.map +1 -1
  134. package/dist/components/status.js +4 -4
  135. package/dist/components/status.js.map +1 -1
  136. package/dist/components/task-list-display.d.ts +8 -0
  137. package/dist/components/task-list-display.d.ts.map +1 -0
  138. package/dist/components/task-list-display.js +26 -0
  139. package/dist/components/task-list-display.js.map +1 -0
  140. package/dist/components/tool-message.d.ts.map +1 -1
  141. package/dist/components/tool-message.js +1 -1
  142. package/dist/components/tool-message.js.map +1 -1
  143. package/dist/components/ui/styled-title.js +38 -38
  144. package/dist/components/usage/progress-bar.d.ts.map +1 -1
  145. package/dist/components/usage/progress-bar.js +6 -3
  146. package/dist/components/usage/progress-bar.js.map +1 -1
  147. package/dist/components/usage/usage-display.d.ts.map +1 -1
  148. package/dist/components/usage/usage-display.js +1 -1
  149. package/dist/components/usage/usage-display.js.map +1 -1
  150. package/dist/components/user-input.d.ts.map +1 -1
  151. package/dist/components/user-input.js +36 -16
  152. package/dist/components/user-input.js.map +1 -1
  153. package/dist/components/user-message.d.ts.map +1 -1
  154. package/dist/components/user-message.js +43 -12
  155. package/dist/components/user-message.js.map +1 -1
  156. package/dist/components/welcome-message.d.ts.map +1 -1
  157. package/dist/components/welcome-message.js +6 -2
  158. package/dist/components/welcome-message.js.map +1 -1
  159. package/dist/config/index.d.ts +7 -1
  160. package/dist/config/index.d.ts.map +1 -1
  161. package/dist/config/index.js +100 -16
  162. package/dist/config/index.js.map +1 -1
  163. package/dist/config/mcp-config-loader.d.ts +31 -0
  164. package/dist/config/mcp-config-loader.d.ts.map +1 -0
  165. package/dist/config/mcp-config-loader.js +341 -0
  166. package/dist/config/mcp-config-loader.js.map +1 -0
  167. package/dist/config/nanocoder-tools-config.d.ts +7 -0
  168. package/dist/config/nanocoder-tools-config.d.ts.map +1 -0
  169. package/dist/config/nanocoder-tools-config.js +14 -0
  170. package/dist/config/nanocoder-tools-config.js.map +1 -0
  171. package/dist/config/preferences.d.ts +4 -0
  172. package/dist/config/preferences.d.ts.map +1 -1
  173. package/dist/config/preferences.js +14 -0
  174. package/dist/config/preferences.js.map +1 -1
  175. package/dist/config/themes.d.ts.map +1 -1
  176. package/dist/config/themes.js +340 -0
  177. package/dist/config/themes.js.map +1 -1
  178. package/dist/config/validation.d.ts +11 -0
  179. package/dist/config/validation.d.ts.map +1 -0
  180. package/dist/config/validation.js +71 -0
  181. package/dist/config/validation.js.map +1 -0
  182. package/dist/constants.d.ts +3 -0
  183. package/dist/constants.d.ts.map +1 -1
  184. package/dist/constants.js +63 -0
  185. package/dist/constants.js.map +1 -1
  186. package/dist/hooks/chat-handler/conversation/conversation-loop.d.ts +3 -1
  187. package/dist/hooks/chat-handler/conversation/conversation-loop.d.ts.map +1 -1
  188. package/dist/hooks/chat-handler/conversation/conversation-loop.js +52 -18
  189. package/dist/hooks/chat-handler/conversation/conversation-loop.js.map +1 -1
  190. package/dist/hooks/chat-handler/useChatHandler.d.ts.map +1 -1
  191. package/dist/hooks/chat-handler/useChatHandler.js +7 -0
  192. package/dist/hooks/chat-handler/useChatHandler.js.map +1 -1
  193. package/dist/hooks/useAppHandlers.d.ts +3 -2
  194. package/dist/hooks/useAppHandlers.d.ts.map +1 -1
  195. package/dist/hooks/useAppHandlers.js +67 -4
  196. package/dist/hooks/useAppHandlers.js.map +1 -1
  197. package/dist/hooks/useAppInitialization.d.ts.map +1 -1
  198. package/dist/hooks/useAppInitialization.js +14 -4
  199. package/dist/hooks/useAppInitialization.js.map +1 -1
  200. package/dist/hooks/useAppState.d.ts +6 -4
  201. package/dist/hooks/useAppState.d.ts.map +1 -1
  202. package/dist/hooks/useAppState.js +9 -6
  203. package/dist/hooks/useAppState.js.map +1 -1
  204. package/dist/hooks/useModeHandlers.d.ts +12 -10
  205. package/dist/hooks/useModeHandlers.d.ts.map +1 -1
  206. package/dist/hooks/useModeHandlers.js +52 -42
  207. package/dist/hooks/useModeHandlers.js.map +1 -1
  208. package/dist/hooks/useTerminalWidth.d.ts +1 -1
  209. package/dist/hooks/useTerminalWidth.d.ts.map +1 -1
  210. package/dist/hooks/useTerminalWidth.js +2 -2
  211. package/dist/hooks/useTerminalWidth.js.map +1 -1
  212. package/dist/hooks/useUIState.d.ts +2 -0
  213. package/dist/hooks/useUIState.d.ts.map +1 -1
  214. package/dist/hooks/useUIState.js +11 -1
  215. package/dist/hooks/useUIState.js.map +1 -1
  216. package/dist/mcp/mcp-client.d.ts +2 -0
  217. package/dist/mcp/mcp-client.d.ts.map +1 -1
  218. package/dist/mcp/mcp-client.js +13 -1
  219. package/dist/mcp/mcp-client.js.map +1 -1
  220. package/dist/models/models-dev-client.d.ts.map +1 -1
  221. package/dist/models/models-dev-client.js +61 -37
  222. package/dist/models/models-dev-client.js.map +1 -1
  223. package/dist/services/bash-executor.d.ts.map +1 -1
  224. package/dist/services/bash-executor.js +7 -0
  225. package/dist/services/bash-executor.js.map +1 -1
  226. package/dist/test-utils/cli-test-harness.d.ts +181 -0
  227. package/dist/test-utils/cli-test-harness.d.ts.map +1 -0
  228. package/dist/test-utils/cli-test-harness.js +413 -0
  229. package/dist/test-utils/cli-test-harness.js.map +1 -0
  230. package/dist/tools/execute-bash.d.ts.map +1 -1
  231. package/dist/tools/execute-bash.js +10 -2
  232. package/dist/tools/execute-bash.js.map +1 -1
  233. package/dist/tools/git/git-add.d.ts +8 -0
  234. package/dist/tools/git/git-add.d.ts.map +1 -0
  235. package/dist/tools/git/git-add.js +141 -0
  236. package/dist/tools/git/git-add.js.map +1 -0
  237. package/dist/tools/git/git-branch.d.ts +8 -0
  238. package/dist/tools/git/git-branch.d.ts.map +1 -0
  239. package/dist/tools/git/git-branch.js +251 -0
  240. package/dist/tools/git/git-branch.js.map +1 -0
  241. package/dist/tools/git/git-commit.d.ts +8 -0
  242. package/dist/tools/git/git-commit.d.ts.map +1 -0
  243. package/dist/tools/git/git-commit.js +176 -0
  244. package/dist/tools/git/git-commit.js.map +1 -0
  245. package/dist/tools/git/git-diff.d.ts +8 -0
  246. package/dist/tools/git/git-diff.d.ts.map +1 -0
  247. package/dist/tools/git/git-diff.js +136 -0
  248. package/dist/tools/git/git-diff.js.map +1 -0
  249. package/dist/tools/git/git-log.d.ts +8 -0
  250. package/dist/tools/git/git-log.d.ts.map +1 -0
  251. package/dist/tools/git/git-log.js +146 -0
  252. package/dist/tools/git/git-log.js.map +1 -0
  253. package/dist/tools/git/git-pr.d.ts +8 -0
  254. package/dist/tools/git/git-pr.d.ts.map +1 -0
  255. package/dist/tools/git/git-pr.js +252 -0
  256. package/dist/tools/git/git-pr.js.map +1 -0
  257. package/dist/tools/git/git-pull.d.ts +8 -0
  258. package/dist/tools/git/git-pull.d.ts.map +1 -0
  259. package/dist/tools/git/git-pull.js +151 -0
  260. package/dist/tools/git/git-pull.js.map +1 -0
  261. package/dist/tools/git/git-push.d.ts +8 -0
  262. package/dist/tools/git/git-push.d.ts.map +1 -0
  263. package/dist/tools/git/git-push.js +157 -0
  264. package/dist/tools/git/git-push.js.map +1 -0
  265. package/dist/tools/git/git-reset.d.ts +8 -0
  266. package/dist/tools/git/git-reset.d.ts.map +1 -0
  267. package/dist/tools/git/git-reset.js +183 -0
  268. package/dist/tools/git/git-reset.js.map +1 -0
  269. package/dist/tools/git/git-stash.d.ts +8 -0
  270. package/dist/tools/git/git-stash.d.ts.map +1 -0
  271. package/dist/tools/git/git-stash.js +260 -0
  272. package/dist/tools/git/git-stash.js.map +1 -0
  273. package/dist/tools/git/git-status.d.ts +8 -0
  274. package/dist/tools/git/git-status.d.ts.map +1 -0
  275. package/dist/tools/git/git-status.js +233 -0
  276. package/dist/tools/git/git-status.js.map +1 -0
  277. package/dist/tools/git/index.d.ts +9 -12
  278. package/dist/tools/git/index.d.ts.map +1 -1
  279. package/dist/tools/git/index.js +43 -11
  280. package/dist/tools/git/index.js.map +1 -1
  281. package/dist/tools/git/utils.d.ts +136 -23
  282. package/dist/tools/git/utils.d.ts.map +1 -1
  283. package/dist/tools/git/utils.js +405 -360
  284. package/dist/tools/git/utils.js.map +1 -1
  285. package/dist/tools/index.d.ts.map +1 -1
  286. package/dist/tools/index.js +15 -9
  287. package/dist/tools/index.js.map +1 -1
  288. package/dist/tools/string-replace.d.ts.map +1 -1
  289. package/dist/tools/string-replace.js +74 -17
  290. package/dist/tools/string-replace.js.map +1 -1
  291. package/dist/tools/tasks/create-task.d.ts +3 -0
  292. package/dist/tools/tasks/create-task.d.ts.map +1 -0
  293. package/dist/tools/tasks/create-task.js +101 -0
  294. package/dist/tools/tasks/create-task.js.map +1 -0
  295. package/dist/tools/tasks/delete-task.d.ts +3 -0
  296. package/dist/tools/tasks/delete-task.d.ts.map +1 -0
  297. package/dist/tools/tasks/delete-task.js +101 -0
  298. package/dist/tools/tasks/delete-task.js.map +1 -0
  299. package/dist/tools/tasks/index.d.ts +7 -0
  300. package/dist/tools/tasks/index.d.ts.map +1 -0
  301. package/dist/tools/tasks/index.js +6 -0
  302. package/dist/tools/tasks/index.js.map +1 -0
  303. package/dist/tools/tasks/list-tasks.d.ts +3 -0
  304. package/dist/tools/tasks/list-tasks.d.ts.map +1 -0
  305. package/dist/tools/tasks/list-tasks.js +67 -0
  306. package/dist/tools/tasks/list-tasks.js.map +1 -0
  307. package/dist/tools/tasks/storage.d.ts +7 -0
  308. package/dist/tools/tasks/storage.d.ts.map +1 -0
  309. package/dist/tools/tasks/storage.js +31 -0
  310. package/dist/tools/tasks/storage.js.map +1 -0
  311. package/dist/tools/tasks/types.d.ts +11 -0
  312. package/dist/tools/tasks/types.d.ts.map +1 -0
  313. package/dist/tools/tasks/types.js +2 -0
  314. package/dist/tools/tasks/types.js.map +1 -0
  315. package/dist/tools/tasks/update-task.d.ts +3 -0
  316. package/dist/tools/tasks/update-task.d.ts.map +1 -0
  317. package/dist/tools/tasks/update-task.js +142 -0
  318. package/dist/tools/tasks/update-task.js.map +1 -0
  319. package/dist/tools/tool-manager.d.ts +1 -0
  320. package/dist/tools/tool-manager.d.ts.map +1 -1
  321. package/dist/tools/write-file.d.ts.map +1 -1
  322. package/dist/tools/write-file.js +52 -3
  323. package/dist/tools/write-file.js.map +1 -1
  324. package/dist/types/app.d.ts +3 -2
  325. package/dist/types/app.d.ts.map +1 -1
  326. package/dist/types/config.d.ts +54 -27
  327. package/dist/types/config.d.ts.map +1 -1
  328. package/dist/types/file-explorer.d.ts +14 -0
  329. package/dist/types/file-explorer.d.ts.map +1 -0
  330. package/dist/types/file-explorer.js +2 -0
  331. package/dist/types/file-explorer.js.map +1 -0
  332. package/dist/types/mcp.d.ts +1 -0
  333. package/dist/types/mcp.d.ts.map +1 -1
  334. package/dist/types/ui.d.ts +2 -2
  335. package/dist/types/ui.d.ts.map +1 -1
  336. package/dist/utils/auto-compact.d.ts +23 -0
  337. package/dist/utils/auto-compact.d.ts.map +1 -0
  338. package/dist/utils/auto-compact.js +149 -0
  339. package/dist/utils/auto-compact.js.map +1 -0
  340. package/dist/utils/completion-note.d.ts +3 -0
  341. package/dist/utils/completion-note.d.ts.map +1 -0
  342. package/dist/utils/completion-note.js +39 -0
  343. package/dist/utils/completion-note.js.map +1 -0
  344. package/dist/utils/compression-backup.d.ts +14 -0
  345. package/dist/utils/compression-backup.d.ts.map +1 -0
  346. package/dist/utils/compression-backup.js +31 -0
  347. package/dist/utils/compression-backup.js.map +1 -0
  348. package/dist/utils/file-tree.d.ts +37 -0
  349. package/dist/utils/file-tree.d.ts.map +1 -0
  350. package/dist/utils/file-tree.js +122 -0
  351. package/dist/utils/file-tree.js.map +1 -0
  352. package/dist/utils/indentation-normalizer.d.ts +10 -0
  353. package/dist/utils/indentation-normalizer.d.ts.map +1 -1
  354. package/dist/utils/indentation-normalizer.js +48 -0
  355. package/dist/utils/indentation-normalizer.js.map +1 -1
  356. package/dist/utils/logging/config.d.ts +11 -0
  357. package/dist/utils/logging/config.d.ts.map +1 -1
  358. package/dist/utils/logging/config.js +19 -4
  359. package/dist/utils/logging/config.js.map +1 -1
  360. package/dist/utils/logging/logger-provider.d.ts +15 -0
  361. package/dist/utils/logging/logger-provider.d.ts.map +1 -1
  362. package/dist/utils/logging/logger-provider.js +48 -24
  363. package/dist/utils/logging/logger-provider.js.map +1 -1
  364. package/dist/utils/message-compression.d.ts +55 -0
  365. package/dist/utils/message-compression.d.ts.map +1 -0
  366. package/dist/utils/message-compression.js +401 -0
  367. package/dist/utils/message-compression.js.map +1 -0
  368. package/dist/vscode/protocol.d.ts +5 -1
  369. package/dist/vscode/protocol.d.ts.map +1 -1
  370. package/dist/vscode/vscode-server.d.ts +4 -0
  371. package/dist/vscode/vscode-server.d.ts.map +1 -1
  372. package/dist/vscode/vscode-server.js +10 -0
  373. package/dist/vscode/vscode-server.js.map +1 -1
  374. package/dist/wizards/mcp-wizard.d.ts +8 -0
  375. package/dist/wizards/mcp-wizard.d.ts.map +1 -0
  376. package/dist/wizards/mcp-wizard.js +256 -0
  377. package/dist/wizards/mcp-wizard.js.map +1 -0
  378. package/dist/wizards/provider-wizard.d.ts +8 -0
  379. package/dist/wizards/provider-wizard.d.ts.map +1 -0
  380. package/dist/wizards/provider-wizard.js +254 -0
  381. package/dist/wizards/provider-wizard.js.map +1 -0
  382. package/dist/wizards/steps/location-step.d.ts +10 -0
  383. package/dist/wizards/steps/location-step.d.ts.map +1 -0
  384. package/dist/{wizard → wizards}/steps/location-step.js +7 -10
  385. package/dist/wizards/steps/location-step.js.map +1 -0
  386. package/dist/{wizard → wizards}/steps/mcp-step.d.ts +3 -1
  387. package/dist/wizards/steps/mcp-step.d.ts.map +1 -0
  388. package/dist/{wizard → wizards}/steps/mcp-step.js +14 -11
  389. package/dist/wizards/steps/mcp-step.js.map +1 -0
  390. package/dist/wizards/steps/provider-step.d.ts +11 -0
  391. package/dist/wizards/steps/provider-step.d.ts.map +1 -0
  392. package/dist/{wizard → wizards}/steps/provider-step.js +12 -10
  393. package/dist/wizards/steps/provider-step.js.map +1 -0
  394. package/dist/{wizard → wizards}/steps/summary-step.d.ts +3 -2
  395. package/dist/wizards/steps/summary-step.d.ts.map +1 -0
  396. package/dist/{wizard → wizards}/steps/summary-step.js +2 -2
  397. package/dist/wizards/steps/summary-step.js.map +1 -0
  398. package/dist/{wizard → wizards}/templates/mcp-templates.d.ts +1 -0
  399. package/dist/wizards/templates/mcp-templates.d.ts.map +1 -0
  400. package/dist/wizards/templates/mcp-templates.js.map +1 -0
  401. package/dist/wizards/templates/provider-templates.d.ts.map +1 -0
  402. package/dist/{wizard → wizards}/templates/provider-templates.js +73 -8
  403. package/dist/wizards/templates/provider-templates.js.map +1 -0
  404. package/dist/wizards/utils/fetch-cloud-models.d.ts.map +1 -0
  405. package/dist/wizards/utils/fetch-cloud-models.js.map +1 -0
  406. package/dist/wizards/utils/fetch-local-models.d.ts.map +1 -0
  407. package/dist/wizards/utils/fetch-local-models.js.map +1 -0
  408. package/dist/wizards/validation.d.ts +72 -0
  409. package/dist/wizards/validation.d.ts.map +1 -0
  410. package/dist/{wizard → wizards}/validation.js +64 -1
  411. package/dist/wizards/validation.js.map +1 -0
  412. package/package.json +21 -6
  413. package/source/app/prompts/main-prompt.md +75 -68
  414. package/dist/commands/setup-config.d.ts +0 -3
  415. package/dist/commands/setup-config.d.ts.map +0 -1
  416. package/dist/commands/setup-config.js.map +0 -1
  417. package/dist/commands/theme.d.ts +0 -3
  418. package/dist/commands/theme.d.ts.map +0 -1
  419. package/dist/commands/theme.js.map +0 -1
  420. package/dist/commands/title-shape.d.ts +0 -3
  421. package/dist/commands/title-shape.d.ts.map +0 -1
  422. package/dist/commands/title-shape.js +0 -54
  423. package/dist/commands/title-shape.js.map +0 -1
  424. package/dist/components/theme-selector.d.ts +0 -8
  425. package/dist/components/theme-selector.d.ts.map +0 -1
  426. package/dist/components/theme-selector.js +0 -51
  427. package/dist/components/theme-selector.js.map +0 -1
  428. package/dist/components/title-shape-selector.d.ts +0 -8
  429. package/dist/components/title-shape-selector.d.ts.map +0 -1
  430. package/dist/components/title-shape-selector.js +0 -108
  431. package/dist/components/title-shape-selector.js.map +0 -1
  432. package/dist/tools/git/git-branch-suggest.d.ts +0 -9
  433. package/dist/tools/git/git-branch-suggest.d.ts.map +0 -1
  434. package/dist/tools/git/git-branch-suggest.js +0 -326
  435. package/dist/tools/git/git-branch-suggest.js.map +0 -1
  436. package/dist/tools/git/git-create-pr.d.ts +0 -9
  437. package/dist/tools/git/git-create-pr.d.ts.map +0 -1
  438. package/dist/tools/git/git-create-pr.js +0 -404
  439. package/dist/tools/git/git-create-pr.js.map +0 -1
  440. package/dist/tools/git/git-smart-commit.d.ts +0 -9
  441. package/dist/tools/git/git-smart-commit.d.ts.map +0 -1
  442. package/dist/tools/git/git-smart-commit.js +0 -308
  443. package/dist/tools/git/git-smart-commit.js.map +0 -1
  444. package/dist/tools/git/git-status-enhanced.d.ts +0 -9
  445. package/dist/tools/git/git-status-enhanced.d.ts.map +0 -1
  446. package/dist/tools/git/git-status-enhanced.js +0 -305
  447. package/dist/tools/git/git-status-enhanced.js.map +0 -1
  448. package/dist/tools/git/types.d.ts +0 -103
  449. package/dist/tools/git/types.d.ts.map +0 -1
  450. package/dist/tools/git/types.js +0 -7
  451. package/dist/tools/git/types.js.map +0 -1
  452. package/dist/utils/gradient-utils.d.ts +0 -25
  453. package/dist/utils/gradient-utils.d.ts.map +0 -1
  454. package/dist/utils/gradient-utils.js +0 -45
  455. package/dist/utils/gradient-utils.js.map +0 -1
  456. package/dist/wizard/config-wizard.d.ts +0 -8
  457. package/dist/wizard/config-wizard.d.ts.map +0 -1
  458. package/dist/wizard/config-wizard.js +0 -212
  459. package/dist/wizard/config-wizard.js.map +0 -1
  460. package/dist/wizard/steps/location-step.d.ts +0 -9
  461. package/dist/wizard/steps/location-step.d.ts.map +0 -1
  462. package/dist/wizard/steps/location-step.js.map +0 -1
  463. package/dist/wizard/steps/mcp-step.d.ts.map +0 -1
  464. package/dist/wizard/steps/mcp-step.js.map +0 -1
  465. package/dist/wizard/steps/provider-step.d.ts +0 -9
  466. package/dist/wizard/steps/provider-step.d.ts.map +0 -1
  467. package/dist/wizard/steps/provider-step.js.map +0 -1
  468. package/dist/wizard/steps/summary-step.d.ts.map +0 -1
  469. package/dist/wizard/steps/summary-step.js.map +0 -1
  470. package/dist/wizard/templates/mcp-templates.d.ts.map +0 -1
  471. package/dist/wizard/templates/mcp-templates.js.map +0 -1
  472. package/dist/wizard/templates/provider-templates.d.ts.map +0 -1
  473. package/dist/wizard/templates/provider-templates.js.map +0 -1
  474. package/dist/wizard/utils/fetch-cloud-models.d.ts.map +0 -1
  475. package/dist/wizard/utils/fetch-cloud-models.js.map +0 -1
  476. package/dist/wizard/utils/fetch-local-models.d.ts.map +0 -1
  477. package/dist/wizard/utils/fetch-local-models.js.map +0 -1
  478. package/dist/wizard/validation.d.ts +0 -64
  479. package/dist/wizard/validation.d.ts.map +0 -1
  480. package/dist/wizard/validation.js.map +0 -1
  481. /package/dist/{wizard → wizards}/templates/mcp-templates.js +0 -0
  482. /package/dist/{wizard → wizards}/templates/provider-templates.d.ts +0 -0
  483. /package/dist/{wizard → wizards}/utils/fetch-cloud-models.d.ts +0 -0
  484. /package/dist/{wizard → wizards}/utils/fetch-cloud-models.js +0 -0
  485. /package/dist/{wizard → wizards}/utils/fetch-local-models.d.ts +0 -0
  486. /package/dist/{wizard → wizards}/utils/fetch-local-models.js +0 -0
@@ -1,10 +1,40 @@
1
1
  /**
2
- * Git Workflow Utilities
2
+ * Git Utilities
3
3
  *
4
4
  * Shared utilities for git operations including command execution,
5
- * diff parsing, and analysis functions.
5
+ * status parsing, and availability checks.
6
6
  */
7
- import { spawn } from 'node:child_process';
7
+ import { execSync, spawn } from 'node:child_process';
8
+ // ============================================================================
9
+ // Availability Checks (Synchronous - for conditional tool registration)
10
+ // ============================================================================
11
+ /**
12
+ * Check if git is available on the system (synchronous)
13
+ */
14
+ export function isGitAvailable() {
15
+ try {
16
+ execSync('git --version', { stdio: 'ignore' });
17
+ return true;
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ }
23
+ /**
24
+ * Check if gh CLI is available on the system (synchronous)
25
+ */
26
+ export function isGhAvailable() {
27
+ try {
28
+ execSync('gh --version', { stdio: 'ignore' });
29
+ return true;
30
+ }
31
+ catch {
32
+ return false;
33
+ }
34
+ }
35
+ // ============================================================================
36
+ // Git Command Execution
37
+ // ============================================================================
8
38
  /**
9
39
  * Execute a git command and return the output
10
40
  */
@@ -21,13 +51,9 @@ export async function execGit(args) {
21
51
  });
22
52
  proc.on('close', (code) => {
23
53
  if (code === 0) {
24
- // Use trimEnd() instead of trim() to preserve leading whitespace
25
- // which is significant in porcelain output (e.g., " M" vs "M ")
26
54
  resolve(stdout.trimEnd());
27
55
  }
28
56
  else {
29
- // Non-zero exit code indicates an error
30
- // Include stderr in error message for context
31
57
  const errorMessage = stderr.trim() || `Git command failed with exit code ${code}`;
32
58
  reject(new Error(errorMessage));
33
59
  }
@@ -38,29 +64,109 @@ export async function execGit(args) {
38
64
  });
39
65
  }
40
66
  /**
41
- * Check if current directory is a git repository
67
+ * Execute a gh CLI command and return the output
68
+ */
69
+ export async function execGh(args) {
70
+ return new Promise((resolve, reject) => {
71
+ const proc = spawn('gh', args);
72
+ let stdout = '';
73
+ let stderr = '';
74
+ proc.stdout.on('data', (data) => {
75
+ stdout += data.toString();
76
+ });
77
+ proc.stderr.on('data', (data) => {
78
+ stderr += data.toString();
79
+ });
80
+ proc.on('close', (code) => {
81
+ if (code === 0) {
82
+ resolve(stdout.trimEnd());
83
+ }
84
+ else {
85
+ const errorMessage = stderr.trim() || `gh command failed with exit code ${code}`;
86
+ reject(new Error(errorMessage));
87
+ }
88
+ });
89
+ proc.on('error', error => {
90
+ reject(new Error(`Failed to execute gh: ${error.message}`));
91
+ });
92
+ });
93
+ }
94
+ // ============================================================================
95
+ // Repository State Checks
96
+ // ============================================================================
97
+ /**
98
+ * Check if there are uncommitted changes (staged or unstaged)
99
+ */
100
+ export async function hasUncommittedChanges() {
101
+ try {
102
+ const status = await execGit(['status', '--porcelain']);
103
+ return status.trim().length > 0;
104
+ }
105
+ catch {
106
+ return false;
107
+ }
108
+ }
109
+ /**
110
+ * Check if there are staged changes
111
+ */
112
+ export async function hasStagedChanges() {
113
+ try {
114
+ const diff = await execGit(['diff', '--cached', '--name-only']);
115
+ return diff.trim().length > 0;
116
+ }
117
+ catch {
118
+ return false;
119
+ }
120
+ }
121
+ /**
122
+ * Check if a rebase is in progress
123
+ */
124
+ export async function isRebaseInProgress() {
125
+ try {
126
+ await execGit(['rev-parse', '--git-path', 'rebase-merge']);
127
+ const result = await execGit([
128
+ 'rev-parse',
129
+ '--verify',
130
+ '--quiet',
131
+ 'REBASE_HEAD',
132
+ ]);
133
+ return result !== '';
134
+ }
135
+ catch {
136
+ return false;
137
+ }
138
+ }
139
+ /**
140
+ * Check if a merge is in progress
42
141
  */
43
- export async function isGitRepository() {
142
+ export async function isMergeInProgress() {
44
143
  try {
45
- await execGit(['rev-parse', '--is-inside-work-tree']);
144
+ await execGit(['rev-parse', '--verify', '--quiet', 'MERGE_HEAD']);
46
145
  return true;
47
146
  }
48
147
  catch {
49
148
  return false;
50
149
  }
51
150
  }
151
+ // ============================================================================
152
+ // Branch Operations
153
+ // ============================================================================
52
154
  /**
53
155
  * Get the current branch name
54
156
  */
55
157
  export async function getCurrentBranch() {
56
- return execGit(['rev-parse', '--abbrev-ref', 'HEAD']);
158
+ try {
159
+ return await execGit(['rev-parse', '--abbrev-ref', 'HEAD']);
160
+ }
161
+ catch {
162
+ return 'HEAD'; // Detached HEAD state
163
+ }
57
164
  }
58
165
  /**
59
166
  * Get the default branch (main or master)
60
167
  */
61
168
  export async function getDefaultBranch() {
62
169
  try {
63
- // Try to get from remote origin
64
170
  const remoteBranch = await execGit([
65
171
  'symbolic-ref',
66
172
  'refs/remotes/origin/HEAD',
@@ -80,57 +186,197 @@ export async function getDefaultBranch() {
80
186
  return 'master';
81
187
  }
82
188
  catch {
83
- return 'main'; // Default to main
189
+ return 'main';
84
190
  }
85
191
  }
86
192
  }
87
193
  }
88
194
  /**
89
- * Parse git diff --stat output to extract file changes
195
+ * Check if a branch exists
90
196
  */
91
- export function parseDiffStat(diffStat) {
92
- const files = [];
93
- const lines = diffStat.split('\n').filter(line => line.trim());
94
- for (const line of lines) {
95
- // Skip summary line (e.g., "3 files changed, 10 insertions(+), 5 deletions(-)")
96
- if (line.includes('files changed') || line.includes('file changed')) {
97
- continue;
98
- }
99
- // Parse line format: " path/to/file.ts | 10 ++++---"
100
- const match = line.match(/^\s*(.+?)\s+\|\s+(\d+|Bin)/);
101
- if (match) {
102
- const path = match[1].trim();
103
- const isBinary = match[2] === 'Bin';
104
- // Count + and - signs for additions/deletions
105
- const changesMatch = line.match(/\|.*?(\d+)?\s*([+-]+)?/);
106
- let additions = 0;
107
- let deletions = 0;
108
- if (changesMatch && changesMatch[2]) {
109
- additions = (changesMatch[2].match(/\+/g) || []).length;
110
- deletions = (changesMatch[2].match(/-/g) || []).length;
111
- }
112
- // Detect renames (format: old => new)
113
- const renameMatch = path.match(/(.+)\s*=>\s*(.+)/);
114
- let finalPath = path;
115
- let oldPath;
116
- let status = 'modified';
117
- if (renameMatch) {
118
- // Handle various rename formats
119
- oldPath = renameMatch[1].trim();
120
- finalPath = renameMatch[2].trim();
121
- status = 'renamed';
197
+ export async function branchExists(name) {
198
+ try {
199
+ await execGit(['rev-parse', '--verify', `refs/heads/${name}`]);
200
+ return true;
201
+ }
202
+ catch {
203
+ return false;
204
+ }
205
+ }
206
+ /**
207
+ * Get the upstream branch for the current branch
208
+ */
209
+ export async function getUpstreamBranch() {
210
+ try {
211
+ return await execGit(['rev-parse', '--abbrev-ref', '@{upstream}']);
212
+ }
213
+ catch {
214
+ return null;
215
+ }
216
+ }
217
+ /**
218
+ * Get ahead/behind counts relative to upstream
219
+ */
220
+ export async function getAheadBehind() {
221
+ try {
222
+ const upstream = await getUpstreamBranch();
223
+ if (!upstream)
224
+ return { ahead: 0, behind: 0 };
225
+ const result = await execGit([
226
+ 'rev-list',
227
+ '--left-right',
228
+ '--count',
229
+ `${upstream}...HEAD`,
230
+ ]);
231
+ const [behind, ahead] = result.split('\t').map(n => parseInt(n, 10) || 0);
232
+ return { ahead, behind };
233
+ }
234
+ catch {
235
+ return { ahead: 0, behind: 0 };
236
+ }
237
+ }
238
+ /**
239
+ * Get list of local branches
240
+ */
241
+ export async function getLocalBranches() {
242
+ try {
243
+ const output = await execGit([
244
+ 'branch',
245
+ '--format=%(refname:short)|%(upstream:short)|%(upstream:track,nobracket)|%(HEAD)',
246
+ ]);
247
+ return output
248
+ .split('\n')
249
+ .filter(line => line.trim())
250
+ .map(line => {
251
+ const [name, upstream, track, head] = line.split('|');
252
+ let ahead = 0;
253
+ let behind = 0;
254
+ if (track) {
255
+ const aheadMatch = track.match(/ahead (\d+)/);
256
+ const behindMatch = track.match(/behind (\d+)/);
257
+ if (aheadMatch)
258
+ ahead = parseInt(aheadMatch[1], 10);
259
+ if (behindMatch)
260
+ behind = parseInt(behindMatch[1], 10);
122
261
  }
123
- files.push({
124
- path: finalPath,
125
- status,
126
- oldPath,
127
- additions,
128
- deletions,
129
- isBinary,
130
- });
131
- }
262
+ return {
263
+ name: name || '',
264
+ current: head === '*',
265
+ upstream: upstream || undefined,
266
+ ahead,
267
+ behind,
268
+ };
269
+ });
270
+ }
271
+ catch {
272
+ return [];
273
+ }
274
+ }
275
+ /**
276
+ * Get list of remote branches
277
+ */
278
+ export async function getRemoteBranches() {
279
+ try {
280
+ const output = await execGit(['branch', '-r', '--format=%(refname:short)']);
281
+ return output
282
+ .split('\n')
283
+ .filter(line => line.trim() && !line.includes('HEAD'));
284
+ }
285
+ catch {
286
+ return [];
287
+ }
288
+ }
289
+ // ============================================================================
290
+ // Commit Operations
291
+ // ============================================================================
292
+ /**
293
+ * Get unpushed commits (commits ahead of upstream)
294
+ */
295
+ export async function getUnpushedCommits() {
296
+ try {
297
+ const upstream = await getUpstreamBranch();
298
+ if (!upstream)
299
+ return [];
300
+ return await getCommits({ range: `${upstream}..HEAD` });
301
+ }
302
+ catch {
303
+ return [];
304
+ }
305
+ }
306
+ /**
307
+ * Check if the last commit has been pushed
308
+ */
309
+ export async function isLastCommitPushed() {
310
+ try {
311
+ const upstream = await getUpstreamBranch();
312
+ if (!upstream)
313
+ return false;
314
+ const { ahead } = await getAheadBehind();
315
+ return ahead === 0;
316
+ }
317
+ catch {
318
+ return false;
319
+ }
320
+ }
321
+ /**
322
+ * Get commits with various filters
323
+ */
324
+ export async function getCommits(options) {
325
+ try {
326
+ const args = ['log', '--format=%H|%h|%an|%ae|%ad|%ar|%s', '--date=short'];
327
+ if (options.count)
328
+ args.push(`-n`, options.count.toString());
329
+ if (options.range)
330
+ args.push(options.range);
331
+ if (options.author)
332
+ args.push(`--author=${options.author}`);
333
+ if (options.since)
334
+ args.push(`--since=${options.since}`);
335
+ if (options.grep)
336
+ args.push(`--grep=${options.grep}`);
337
+ if (options.file)
338
+ args.push('--', options.file);
339
+ const output = await execGit(args);
340
+ if (!output.trim())
341
+ return [];
342
+ return output.split('\n').map(line => {
343
+ const [hash, shortHash, author, email, date, relativeDate, subject] = line.split('|');
344
+ return {
345
+ hash: hash || '',
346
+ shortHash: shortHash || '',
347
+ author: author || '',
348
+ email: email || '',
349
+ date: date || '',
350
+ relativeDate: relativeDate || '',
351
+ subject: subject || '',
352
+ body: '',
353
+ };
354
+ });
355
+ }
356
+ catch {
357
+ return [];
358
+ }
359
+ }
360
+ // ============================================================================
361
+ // Status Parsing
362
+ // ============================================================================
363
+ /**
364
+ * Map git status character to FileChangeStatus
365
+ */
366
+ function mapStatusChar(char) {
367
+ switch (char) {
368
+ case 'A':
369
+ return 'added';
370
+ case 'D':
371
+ return 'deleted';
372
+ case 'R':
373
+ return 'renamed';
374
+ case 'C':
375
+ return 'copied';
376
+ case 'M':
377
+ default:
378
+ return 'modified';
132
379
  }
133
- return files;
134
380
  }
135
381
  /**
136
382
  * Parse git status --porcelain output
@@ -140,15 +386,18 @@ export function parseGitStatus(statusOutput) {
140
386
  const unstaged = [];
141
387
  const untracked = [];
142
388
  const conflicts = [];
143
- const lines = statusOutput.split('\n').filter(line => line.trim());
389
+ const lines = statusOutput.split('\n').filter(line => line);
144
390
  for (const line of lines) {
145
391
  if (line.length < 3)
146
392
  continue;
147
393
  const indexStatus = line[0];
148
394
  const workTreeStatus = line[1];
149
- const path = line.slice(3).trim();
150
- // Detect conflicts (both modified)
151
- if (indexStatus === 'U' || workTreeStatus === 'U') {
395
+ const path = line.slice(3);
396
+ // Detect conflicts
397
+ if (indexStatus === 'U' ||
398
+ workTreeStatus === 'U' ||
399
+ (indexStatus === 'A' && workTreeStatus === 'A') ||
400
+ (indexStatus === 'D' && workTreeStatus === 'D')) {
152
401
  conflicts.push(path);
153
402
  continue;
154
403
  }
@@ -157,7 +406,7 @@ export function parseGitStatus(statusOutput) {
157
406
  untracked.push(path);
158
407
  continue;
159
408
  }
160
- // Staged changes (index status)
409
+ // Staged changes
161
410
  if (indexStatus !== ' ' && indexStatus !== '?') {
162
411
  staged.push({
163
412
  path,
@@ -167,7 +416,7 @@ export function parseGitStatus(statusOutput) {
167
416
  isBinary: false,
168
417
  });
169
418
  }
170
- // Unstaged changes (work tree status)
419
+ // Unstaged changes
171
420
  if (workTreeStatus !== ' ' && workTreeStatus !== '?') {
172
421
  unstaged.push({
173
422
  path,
@@ -181,331 +430,127 @@ export function parseGitStatus(statusOutput) {
181
430
  return { staged, unstaged, untracked, conflicts };
182
431
  }
183
432
  /**
184
- * Map git status character to FileChangeStatus
185
- */
186
- function mapStatusChar(char) {
187
- switch (char) {
188
- case 'A':
189
- return 'added';
190
- case 'D':
191
- return 'deleted';
192
- case 'R':
193
- return 'renamed';
194
- case 'C':
195
- return 'copied';
196
- case 'M':
197
- default:
198
- return 'modified';
199
- }
200
- }
201
- /**
202
- * Analyze staged changes to suggest commit type
203
- */
204
- export function analyzeChangesForCommitType(files) {
205
- // Check file patterns to determine commit type
206
- const paths = files.map(f => f.path.toLowerCase());
207
- // Test files
208
- if (paths.every(p => p.includes('test') ||
209
- p.includes('spec') ||
210
- p.includes('__tests__') ||
211
- p.endsWith('.test.ts') ||
212
- p.endsWith('.test.tsx') ||
213
- p.endsWith('.spec.ts') ||
214
- p.endsWith('.spec.tsx'))) {
215
- return 'test';
216
- }
217
- // Documentation
218
- if (paths.every(p => p.endsWith('.md') ||
219
- p.includes('readme') ||
220
- p.includes('docs/') ||
221
- p.includes('documentation'))) {
222
- return 'docs';
223
- }
224
- // CI/CD
225
- if (paths.every(p => p.includes('.github/') ||
226
- p.includes('.gitlab-ci') ||
227
- p.includes('jenkinsfile') ||
228
- p.includes('.circleci') ||
229
- p.includes('.travis'))) {
230
- return 'ci';
231
- }
232
- // Build configuration
233
- if (paths.every(p => p.includes('package.json') ||
234
- p.includes('webpack') ||
235
- p.includes('vite') ||
236
- p.includes('rollup') ||
237
- p.includes('tsconfig') ||
238
- p.includes('babel') ||
239
- p.includes('eslint') ||
240
- p.includes('prettier'))) {
241
- return 'build';
242
- }
243
- // Style changes (CSS, formatting)
244
- if (paths.every(p => p.endsWith('.css') ||
245
- p.endsWith('.scss') ||
246
- p.endsWith('.less') ||
247
- p.endsWith('.styled.ts') ||
248
- p.endsWith('.styled.tsx'))) {
249
- return 'style';
250
- }
251
- // All new files = likely a feature
252
- if (files.every(f => f.status === 'added')) {
253
- return 'feat';
254
- }
255
- // All deletions = likely chore/cleanup
256
- if (files.every(f => f.status === 'deleted')) {
257
- return 'chore';
258
- }
259
- // If files contain "fix" in path or small changes in specific files
260
- if (paths.some(p => p.includes('fix')) ||
261
- (files.length <= 3 && files.every(f => f.additions + f.deletions < 20))) {
262
- return 'fix';
263
- }
264
- // Default to feat for larger changes
265
- return 'feat';
266
- }
267
- /**
268
- * Suggest a scope based on file paths
433
+ * Get diff stats for files (additions/deletions)
269
434
  */
270
- export function suggestScope(files) {
271
- if (files.length === 0)
272
- return undefined;
273
- const paths = files.map(f => f.path);
274
- // Extract common directory patterns
275
- const directories = paths.map(p => {
276
- const parts = p.split('/');
277
- // Return second level for src/components/Button.tsx -> components
278
- if (parts[0] === 'source' || parts[0] === 'src') {
279
- return parts[1];
280
- }
281
- return parts[0];
282
- });
283
- // Find most common directory
284
- const counts = new Map();
285
- for (const dir of directories) {
286
- if (dir) {
287
- counts.set(dir, (counts.get(dir) || 0) + 1);
435
+ export async function getDiffStats(staged = false) {
436
+ const stats = new Map();
437
+ try {
438
+ const args = ['diff', '--numstat'];
439
+ if (staged)
440
+ args.push('--cached');
441
+ const output = await execGit(args);
442
+ if (!output.trim())
443
+ return stats;
444
+ for (const line of output.split('\n')) {
445
+ const parts = line.split('\t');
446
+ if (parts.length >= 3) {
447
+ const additions = parts[0] === '-' ? 0 : parseInt(parts[0], 10) || 0;
448
+ const deletions = parts[1] === '-' ? 0 : parseInt(parts[1], 10) || 0;
449
+ const path = parts[2];
450
+ stats.set(path, { additions, deletions });
451
+ }
288
452
  }
289
453
  }
290
- // If all files are in same directory, use it as scope
291
- if (counts.size === 1) {
292
- const scope = directories[0];
293
- // Don't use generic names as scope
294
- if (scope && !['lib', 'utils', 'helpers', 'common'].includes(scope)) {
295
- return scope;
296
- }
454
+ catch {
455
+ // Ignore errors
297
456
  }
298
- return undefined;
299
- }
300
- /**
301
- * Detect potential breaking changes in the diff
302
- */
303
- async function detectBreakingChanges(files) {
304
- // For now, we'll check file patterns that commonly indicate breaking changes
305
- const riskyPaths = files.filter(f => f.path.includes('types') ||
306
- f.path.includes('interfaces') ||
307
- f.path.includes('api') ||
308
- f.path.includes('schema') ||
309
- f.path.includes('public'));
310
- // If modifying public API files with deletions
311
- if (riskyPaths.length > 0 && riskyPaths.some(f => f.deletions > 0)) {
312
- return {
313
- isBreaking: true,
314
- reason: `Modifying public API files: ${riskyPaths.map(f => f.path).join(', ')}`,
315
- };
316
- }
317
- return { isBreaking: false };
457
+ return stats;
318
458
  }
459
+ // ============================================================================
460
+ // Stash Operations
461
+ // ============================================================================
319
462
  /**
320
- * Analyze staged changes comprehensively
463
+ * Get list of stashes
321
464
  */
322
- export async function analyzeStagedChanges() {
323
- // Get diff stat
324
- const diffStat = await execGit(['diff', '--staged', '--stat']);
325
- const files = parseDiffStat(diffStat);
326
- // Get name-status for accurate file status (A=added, M=modified, D=deleted, R=renamed)
327
- const nameStatus = await execGit(['diff', '--staged', '--name-status']);
328
- const statusLines = nameStatus.split('\n').filter(line => line.trim());
329
- for (const line of statusLines) {
330
- const parts = line.split('\t');
331
- if (parts.length >= 2) {
332
- const statusCode = parts[0][0]; // First char is status (A, M, D, R, C)
333
- const path = parts.length === 3 ? parts[2] : parts[1]; // For renames, new path is third
334
- const file = files.find(f => f.path === path);
335
- if (file) {
336
- switch (statusCode) {
337
- case 'A':
338
- file.status = 'added';
339
- break;
340
- case 'D':
341
- file.status = 'deleted';
342
- break;
343
- case 'R':
344
- file.status = 'renamed';
345
- break;
346
- case 'C':
347
- file.status = 'copied';
348
- break;
349
- // M stays as 'modified' (default)
350
- }
351
- }
352
- }
465
+ export async function getStashList() {
466
+ try {
467
+ const output = await execGit(['stash', 'list', '--format=%gd|%gs|%cr']);
468
+ if (!output.trim())
469
+ return [];
470
+ return output.split('\n').map((line, index) => {
471
+ const [ref, message, date] = line.split('|');
472
+ const branchMatch = message?.match(/WIP on ([^:]+):/);
473
+ return {
474
+ index,
475
+ message: message || ref || `stash@{${index}}`,
476
+ branch: branchMatch?.[1] || 'unknown',
477
+ date: date || '',
478
+ };
479
+ });
353
480
  }
354
- // Get numstat for accurate counts
355
- const numstat = await execGit(['diff', '--staged', '--numstat']);
356
- const numstatLines = numstat.split('\n').filter(line => line.trim());
357
- for (const line of numstatLines) {
358
- const parts = line.split('\t');
359
- if (parts.length >= 3) {
360
- // Parse with NaN guard - default to 0 if parsing fails
361
- const additionsRaw = parseInt(parts[0], 10);
362
- const deletionsRaw = parseInt(parts[1], 10);
363
- const additions = parts[0] === '-' || Number.isNaN(additionsRaw) ? 0 : additionsRaw;
364
- const deletions = parts[1] === '-' || Number.isNaN(deletionsRaw) ? 0 : deletionsRaw;
365
- const path = parts[2];
366
- // Use exact path matching to avoid substring false positives
367
- const file = files.find(f => f.path === path);
368
- if (file) {
369
- file.additions = additions;
370
- file.deletions = deletions;
371
- }
372
- }
481
+ catch {
482
+ return [];
373
483
  }
374
- const totalAdditions = files.reduce((sum, f) => sum + f.additions, 0);
375
- const totalDeletions = files.reduce((sum, f) => sum + f.deletions, 0);
376
- const suggestedType = analyzeChangesForCommitType(files);
377
- const suggestedScope = suggestScope(files);
378
- const { isBreaking, reason } = await detectBreakingChanges(files);
379
- return {
380
- files,
381
- totalAdditions,
382
- totalDeletions,
383
- totalFiles: files.length,
384
- suggestedType,
385
- suggestedScope,
386
- isBreakingChange: isBreaking,
387
- breakingChangeReason: reason,
388
- };
389
484
  }
390
485
  /**
391
- * Get enhanced git status
486
+ * Get stash count
392
487
  */
393
- export async function getEnhancedStatus() {
394
- // Get porcelain status
395
- const statusOutput = await execGit(['status', '--porcelain']);
396
- const { staged, unstaged, untracked, conflicts } = parseGitStatus(statusOutput);
397
- // Get branch info
398
- const branch = await getCurrentBranch();
399
- // Get upstream info
400
- let upstream;
401
- let ahead = 0;
402
- let behind = 0;
488
+ export async function getStashCount() {
403
489
  try {
404
- upstream = await execGit(['rev-parse', '--abbrev-ref', '@{upstream}']);
405
- const aheadBehind = await execGit([
406
- 'rev-list',
407
- '--left-right',
408
- '--count',
409
- `${upstream}...HEAD`,
410
- ]);
411
- const [behindCount, aheadCount] = aheadBehind
412
- .split('\t')
413
- .map(n => parseInt(n, 10));
414
- ahead = aheadCount || 0;
415
- behind = behindCount || 0;
490
+ const output = await execGit(['stash', 'list']);
491
+ if (!output.trim())
492
+ return 0;
493
+ return output.split('\n').length;
416
494
  }
417
495
  catch {
418
- // No upstream configured
419
- }
420
- // Build summary
421
- const summaryParts = [];
422
- if (staged.length > 0)
423
- summaryParts.push(`${staged.length} staged`);
424
- if (unstaged.length > 0)
425
- summaryParts.push(`${unstaged.length} modified`);
426
- if (untracked.length > 0)
427
- summaryParts.push(`${untracked.length} untracked`);
428
- if (conflicts.length > 0)
429
- summaryParts.push(`${conflicts.length} conflicts`);
430
- if (ahead > 0)
431
- summaryParts.push(`${ahead} ahead`);
432
- if (behind > 0)
433
- summaryParts.push(`${behind} behind`);
434
- const summary = summaryParts.length > 0 ? summaryParts.join(', ') : 'Working tree clean';
435
- return {
436
- branch,
437
- upstream,
438
- ahead,
439
- behind,
440
- staged,
441
- unstaged,
442
- untracked,
443
- hasConflicts: conflicts.length > 0,
444
- conflicts,
445
- summary,
446
- };
496
+ return 0;
497
+ }
447
498
  }
499
+ // ============================================================================
500
+ // Remote Operations
501
+ // ============================================================================
448
502
  /**
449
- * Get commits between current branch and target
503
+ * Check if a remote exists
450
504
  */
451
- export async function getCommitsBetween(targetBranch) {
505
+ export async function remoteExists(name) {
452
506
  try {
453
- const log = await execGit([
454
- 'log',
455
- `${targetBranch}..HEAD`,
456
- '--format=%H%n%s%n%b%n---COMMIT_SEPARATOR---',
457
- ]);
458
- if (!log.trim()) {
459
- return [];
460
- }
461
- const commitBlocks = log
462
- .split('---COMMIT_SEPARATOR---')
463
- .filter(b => b.trim());
464
- return commitBlocks.map(block => {
465
- const lines = block.trim().split('\n');
466
- return {
467
- hash: lines[0] || '',
468
- subject: lines[1] || '',
469
- body: lines.slice(2).join('\n').trim(),
470
- };
471
- });
507
+ const remotes = await execGit(['remote']);
508
+ return remotes.split('\n').includes(name);
472
509
  }
473
510
  catch {
474
- return [];
511
+ return false;
475
512
  }
476
513
  }
514
+ // ============================================================================
515
+ // Diff Output Helpers
516
+ // ============================================================================
477
517
  /**
478
- * Get list of contributors who have modified the changed files
518
+ * Truncate diff output if too long
479
519
  */
480
- export async function getSuggestedReviewers(files) {
481
- const reviewers = new Set();
482
- for (const file of files.slice(0, 5)) {
483
- // Limit to avoid too many git commands
484
- try {
485
- const log = await execGit([
486
- 'log',
487
- '--format=%ae',
488
- '-n',
489
- '5',
490
- '--',
491
- file.path,
492
- ]);
493
- for (const email of log.split('\n').filter(e => e.trim())) {
494
- reviewers.add(email.trim());
495
- }
496
- }
497
- catch {
498
- // File might be new
499
- }
500
- }
501
- // Remove current user
502
- try {
503
- const currentUser = await execGit(['config', 'user.email']);
504
- reviewers.delete(currentUser.trim());
520
+ export function truncateDiff(diff, maxLines = 500) {
521
+ const lines = diff.split('\n');
522
+ const totalLines = lines.length;
523
+ if (totalLines <= maxLines) {
524
+ return { content: diff, truncated: false, totalLines };
505
525
  }
506
- catch {
507
- // Config might not be set
526
+ const truncatedContent = lines.slice(0, maxLines).join('\n');
527
+ return {
528
+ content: truncatedContent +
529
+ `\n\n... [Diff truncated: showing ${maxLines} of ${totalLines} lines]`,
530
+ truncated: true,
531
+ totalLines,
532
+ };
533
+ }
534
+ // ============================================================================
535
+ // Formatting Helpers
536
+ // ============================================================================
537
+ /**
538
+ * Format file status character for display
539
+ */
540
+ export function formatStatusChar(status) {
541
+ switch (status) {
542
+ case 'added':
543
+ return 'A';
544
+ case 'modified':
545
+ return 'M';
546
+ case 'deleted':
547
+ return 'D';
548
+ case 'renamed':
549
+ return 'R';
550
+ case 'copied':
551
+ return 'C';
552
+ default:
553
+ return '?';
508
554
  }
509
- return Array.from(reviewers).slice(0, 5);
510
555
  }
511
556
  //# sourceMappingURL=utils.js.map