@nanocollective/nanocoder 1.23.0 → 1.24.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 (433) hide show
  1. package/LICENSE.md +1 -15
  2. package/README.md +25 -884
  3. package/assets/nanocoder-vscode.vsix +0 -0
  4. package/dist/ai-sdk-client/ai-sdk-client.d.ts +3 -2
  5. package/dist/ai-sdk-client/ai-sdk-client.d.ts.map +1 -1
  6. package/dist/ai-sdk-client/ai-sdk-client.js +16 -2
  7. package/dist/ai-sdk-client/ai-sdk-client.js.map +1 -1
  8. package/dist/ai-sdk-client/chat/chat-handler.d.ts +2 -1
  9. package/dist/ai-sdk-client/chat/chat-handler.d.ts.map +1 -1
  10. package/dist/ai-sdk-client/chat/chat-handler.js +37 -70
  11. package/dist/ai-sdk-client/chat/chat-handler.js.map +1 -1
  12. package/dist/ai-sdk-client/chat/streaming-handler.d.ts +2 -2
  13. package/dist/ai-sdk-client/chat/streaming-handler.d.ts.map +1 -1
  14. package/dist/ai-sdk-client/chat/streaming-handler.js +4 -23
  15. package/dist/ai-sdk-client/chat/streaming-handler.js.map +1 -1
  16. package/dist/ai-sdk-client/error-handling/error-parser.d.ts.map +1 -1
  17. package/dist/ai-sdk-client/error-handling/error-parser.js +7 -2
  18. package/dist/ai-sdk-client/error-handling/error-parser.js.map +1 -1
  19. package/dist/ai-sdk-client/providers/provider-factory.d.ts +2 -1
  20. package/dist/ai-sdk-client/providers/provider-factory.d.ts.map +1 -1
  21. package/dist/ai-sdk-client/providers/provider-factory.js +55 -0
  22. package/dist/ai-sdk-client/providers/provider-factory.js.map +1 -1
  23. package/dist/app/App.d.ts +1 -1
  24. package/dist/app/App.d.ts.map +1 -1
  25. package/dist/app/App.js +66 -50
  26. package/dist/app/App.js.map +1 -1
  27. package/dist/app/components/chat-input.d.ts +4 -1
  28. package/dist/app/components/chat-input.d.ts.map +1 -1
  29. package/dist/app/components/chat-input.js +4 -3
  30. package/dist/app/components/chat-input.js.map +1 -1
  31. package/dist/app/components/modal-selectors.d.ts +6 -7
  32. package/dist/app/components/modal-selectors.d.ts.map +1 -1
  33. package/dist/app/components/modal-selectors.js +11 -7
  34. package/dist/app/components/modal-selectors.js.map +1 -1
  35. package/dist/app/components/settings-selector.d.ts.map +1 -1
  36. package/dist/app/components/settings-selector.js +3 -3
  37. package/dist/app/components/settings-selector.js.map +1 -1
  38. package/dist/app/helpers.d.ts.map +1 -1
  39. package/dist/app/helpers.js +2 -4
  40. package/dist/app/helpers.js.map +1 -1
  41. package/dist/app/index.d.ts +0 -1
  42. package/dist/app/index.d.ts.map +1 -1
  43. package/dist/app/index.js +0 -1
  44. package/dist/app/index.js.map +1 -1
  45. package/dist/app/types.d.ts +2 -0
  46. package/dist/app/types.d.ts.map +1 -1
  47. package/dist/app/utils/app-util.d.ts +1 -5
  48. package/dist/app/utils/app-util.d.ts.map +1 -1
  49. package/dist/app/utils/app-util.js +60 -460
  50. package/dist/app/utils/app-util.js.map +1 -1
  51. package/dist/app/utils/handlers/compact-handler.d.ts +6 -0
  52. package/dist/app/utils/handlers/compact-handler.d.ts.map +1 -0
  53. package/dist/app/utils/handlers/compact-handler.js +148 -0
  54. package/dist/app/utils/handlers/compact-handler.js.map +1 -0
  55. package/dist/app/utils/handlers/context-max-handler.d.ts +11 -0
  56. package/dist/app/utils/handlers/context-max-handler.d.ts.map +1 -0
  57. package/dist/app/utils/handlers/context-max-handler.js +102 -0
  58. package/dist/app/utils/handlers/context-max-handler.js.map +1 -0
  59. package/dist/app/utils/handlers/create-handler.d.ts +17 -0
  60. package/dist/app/utils/handlers/create-handler.d.ts.map +1 -0
  61. package/dist/app/utils/handlers/create-handler.js +112 -0
  62. package/dist/app/utils/handlers/create-handler.js.map +1 -0
  63. package/dist/app/utils/handlers/session-handler.d.ts +8 -0
  64. package/dist/app/utils/handlers/session-handler.d.ts.map +1 -0
  65. package/dist/app/utils/handlers/session-handler.js +99 -0
  66. package/dist/app/utils/handlers/session-handler.js.map +1 -0
  67. package/dist/auth/github-copilot.d.ts +44 -0
  68. package/dist/auth/github-copilot.d.ts.map +1 -0
  69. package/dist/auth/github-copilot.js +178 -0
  70. package/dist/auth/github-copilot.js.map +1 -0
  71. package/dist/cli.js +64 -3
  72. package/dist/cli.js.map +1 -1
  73. package/dist/client-factory.d.ts +1 -1
  74. package/dist/client-factory.d.ts.map +1 -1
  75. package/dist/client-factory.js +39 -8
  76. package/dist/client-factory.js.map +1 -1
  77. package/dist/commands/compact.d.ts +1 -6
  78. package/dist/commands/compact.d.ts.map +1 -1
  79. package/dist/commands/compact.js +2 -13
  80. package/dist/commands/compact.js.map +1 -1
  81. package/dist/commands/context-max.d.ts +1 -2
  82. package/dist/commands/context-max.d.ts.map +1 -1
  83. package/dist/commands/context-max.js +2 -9
  84. package/dist/commands/context-max.js.map +1 -1
  85. package/dist/commands/copilot-login-command.d.ts +3 -0
  86. package/dist/commands/copilot-login-command.d.ts.map +1 -0
  87. package/dist/commands/copilot-login-command.js +9 -0
  88. package/dist/commands/copilot-login-command.js.map +1 -0
  89. package/dist/commands/copilot-login.d.ts +9 -0
  90. package/dist/commands/copilot-login.d.ts.map +1 -0
  91. package/dist/commands/copilot-login.js +70 -0
  92. package/dist/commands/copilot-login.js.map +1 -0
  93. package/dist/commands/create-stub-command.d.ts +8 -0
  94. package/dist/commands/create-stub-command.d.ts.map +1 -0
  95. package/dist/commands/create-stub-command.js +14 -0
  96. package/dist/commands/create-stub-command.js.map +1 -0
  97. package/dist/commands/explorer.d.ts +1 -2
  98. package/dist/commands/explorer.d.ts.map +1 -1
  99. package/dist/commands/explorer.js +2 -9
  100. package/dist/commands/explorer.js.map +1 -1
  101. package/dist/commands/help.d.ts.map +1 -1
  102. package/dist/commands/help.js +1 -1
  103. package/dist/commands/help.js.map +1 -1
  104. package/dist/commands/ide.d.ts +1 -2
  105. package/dist/commands/ide.d.ts.map +1 -1
  106. package/dist/commands/ide.js +2 -9
  107. package/dist/commands/ide.js.map +1 -1
  108. package/dist/commands/index.d.ts +2 -0
  109. package/dist/commands/index.d.ts.map +1 -1
  110. package/dist/commands/index.js +2 -0
  111. package/dist/commands/index.js.map +1 -1
  112. package/dist/commands/init.d.ts.map +1 -1
  113. package/dist/commands/init.js +2 -1
  114. package/dist/commands/init.js.map +1 -1
  115. package/dist/commands/model.d.ts +1 -2
  116. package/dist/commands/model.d.ts.map +1 -1
  117. package/dist/commands/model.js +2 -10
  118. package/dist/commands/model.js.map +1 -1
  119. package/dist/commands/provider.d.ts +1 -2
  120. package/dist/commands/provider.d.ts.map +1 -1
  121. package/dist/commands/provider.js +2 -10
  122. package/dist/commands/provider.js.map +1 -1
  123. package/dist/commands/resume.d.ts +8 -0
  124. package/dist/commands/resume.d.ts.map +1 -0
  125. package/dist/commands/resume.js +11 -0
  126. package/dist/commands/resume.js.map +1 -0
  127. package/dist/commands/settings.d.ts +1 -2
  128. package/dist/commands/settings.d.ts.map +1 -1
  129. package/dist/commands/settings.js +2 -10
  130. package/dist/commands/settings.js.map +1 -1
  131. package/dist/commands/status.d.ts +1 -2
  132. package/dist/commands/status.d.ts.map +1 -1
  133. package/dist/commands/status.js +2 -10
  134. package/dist/commands/status.js.map +1 -1
  135. package/dist/components/assistant-message.d.ts.map +1 -1
  136. package/dist/components/assistant-message.js +2 -27
  137. package/dist/components/assistant-message.js.map +1 -1
  138. package/dist/components/provider-selector.d.ts.map +1 -1
  139. package/dist/components/provider-selector.js +4 -3
  140. package/dist/components/provider-selector.js.map +1 -1
  141. package/dist/components/session-selector.d.ts +12 -0
  142. package/dist/components/session-selector.d.ts.map +1 -0
  143. package/dist/components/session-selector.js +108 -0
  144. package/dist/components/session-selector.js.map +1 -0
  145. package/dist/components/tool-confirmation.d.ts.map +1 -1
  146. package/dist/components/tool-confirmation.js +9 -6
  147. package/dist/components/tool-confirmation.js.map +1 -1
  148. package/dist/components/ui/styled-title.js +2 -2
  149. package/dist/components/ui/styled-title.js.map +1 -1
  150. package/dist/components/user-input.d.ts +3 -1
  151. package/dist/components/user-input.d.ts.map +1 -1
  152. package/dist/components/user-input.js +35 -23
  153. package/dist/components/user-input.js.map +1 -1
  154. package/dist/components/user-message.d.ts.map +1 -1
  155. package/dist/components/user-message.js +1 -23
  156. package/dist/components/user-message.js.map +1 -1
  157. package/dist/components/vscode-extension-prompt.d.ts +6 -1
  158. package/dist/components/vscode-extension-prompt.d.ts.map +1 -1
  159. package/dist/components/vscode-extension-prompt.js +80 -36
  160. package/dist/components/vscode-extension-prompt.js.map +1 -1
  161. package/dist/config/copilot-credentials.d.ts +27 -0
  162. package/dist/config/copilot-credentials.d.ts.map +1 -0
  163. package/dist/config/copilot-credentials.js +81 -0
  164. package/dist/config/copilot-credentials.js.map +1 -0
  165. package/dist/config/index.d.ts +0 -2
  166. package/dist/config/index.d.ts.map +1 -1
  167. package/dist/config/index.js +63 -27
  168. package/dist/config/index.js.map +1 -1
  169. package/dist/config/mcp-config-loader.d.ts +2 -3
  170. package/dist/config/mcp-config-loader.d.ts.map +1 -1
  171. package/dist/config/mcp-config-loader.js +136 -181
  172. package/dist/config/mcp-config-loader.js.map +1 -1
  173. package/dist/config/nanocoder-tools-config.js +2 -2
  174. package/dist/config/nanocoder-tools-config.js.map +1 -1
  175. package/dist/config/themes.d.ts.map +1 -1
  176. package/dist/config/themes.js +9 -766
  177. package/dist/config/themes.js.map +1 -1
  178. package/dist/config/validation.d.ts.map +1 -1
  179. package/dist/config/validation.js +0 -19
  180. package/dist/config/validation.js.map +1 -1
  181. package/dist/custom-commands/parser.d.ts.map +1 -1
  182. package/dist/custom-commands/parser.js +0 -9
  183. package/dist/custom-commands/parser.js.map +1 -1
  184. package/dist/hooks/chat-handler/conversation/conversation-loop.d.ts +5 -0
  185. package/dist/hooks/chat-handler/conversation/conversation-loop.d.ts.map +1 -1
  186. package/dist/hooks/chat-handler/conversation/conversation-loop.js +78 -97
  187. package/dist/hooks/chat-handler/conversation/conversation-loop.js.map +1 -1
  188. package/dist/hooks/chat-handler/conversation/tool-executor.d.ts +7 -2
  189. package/dist/hooks/chat-handler/conversation/tool-executor.d.ts.map +1 -1
  190. package/dist/hooks/chat-handler/conversation/tool-executor.js +109 -41
  191. package/dist/hooks/chat-handler/conversation/tool-executor.js.map +1 -1
  192. package/dist/hooks/chat-handler/types.d.ts +3 -0
  193. package/dist/hooks/chat-handler/types.d.ts.map +1 -1
  194. package/dist/hooks/chat-handler/useChatHandler.d.ts +1 -1
  195. package/dist/hooks/chat-handler/useChatHandler.d.ts.map +1 -1
  196. package/dist/hooks/chat-handler/useChatHandler.js +7 -1
  197. package/dist/hooks/chat-handler/useChatHandler.js.map +1 -1
  198. package/dist/hooks/useAppHandlers.d.ts +8 -1
  199. package/dist/hooks/useAppHandlers.d.ts.map +1 -1
  200. package/dist/hooks/useAppHandlers.js +119 -13
  201. package/dist/hooks/useAppHandlers.js.map +1 -1
  202. package/dist/hooks/useAppInitialization.d.ts +5 -3
  203. package/dist/hooks/useAppInitialization.d.ts.map +1 -1
  204. package/dist/hooks/useAppInitialization.js +51 -30
  205. package/dist/hooks/useAppInitialization.js.map +1 -1
  206. package/dist/hooks/useAppState.d.ts +15 -10
  207. package/dist/hooks/useAppState.d.ts.map +1 -1
  208. package/dist/hooks/useAppState.js +37 -28
  209. package/dist/hooks/useAppState.js.map +1 -1
  210. package/dist/hooks/useModeHandlers.d.ts +8 -14
  211. package/dist/hooks/useModeHandlers.d.ts.map +1 -1
  212. package/dist/hooks/useModeHandlers.js +31 -101
  213. package/dist/hooks/useModeHandlers.js.map +1 -1
  214. package/dist/hooks/useNonInteractiveMode.d.ts +7 -0
  215. package/dist/hooks/useNonInteractiveMode.d.ts.map +1 -1
  216. package/dist/hooks/useNonInteractiveMode.js +39 -2
  217. package/dist/hooks/useNonInteractiveMode.js.map +1 -1
  218. package/dist/hooks/useSessionAutosave.d.ts +16 -0
  219. package/dist/hooks/useSessionAutosave.d.ts.map +1 -0
  220. package/dist/hooks/useSessionAutosave.js +133 -0
  221. package/dist/hooks/useSessionAutosave.js.map +1 -0
  222. package/dist/hooks/useToolHandler.d.ts +2 -1
  223. package/dist/hooks/useToolHandler.d.ts.map +1 -1
  224. package/dist/hooks/useToolHandler.js +9 -3
  225. package/dist/hooks/useToolHandler.js.map +1 -1
  226. package/dist/mcp/mcp-client.d.ts.map +1 -1
  227. package/dist/mcp/mcp-client.js +3 -2
  228. package/dist/mcp/mcp-client.js.map +1 -1
  229. package/dist/mcp/transport-factory.d.ts.map +1 -1
  230. package/dist/mcp/transport-factory.js +4 -36
  231. package/dist/mcp/transport-factory.js.map +1 -1
  232. package/dist/models/models-dev-client.d.ts.map +1 -1
  233. package/dist/models/models-dev-client.js +21 -14
  234. package/dist/models/models-dev-client.js.map +1 -1
  235. package/dist/session/session-manager.d.ts +57 -0
  236. package/dist/session/session-manager.d.ts.map +1 -0
  237. package/dist/session/session-manager.js +361 -0
  238. package/dist/session/session-manager.js.map +1 -0
  239. package/dist/test-utils/render-with-theme.d.ts.map +1 -1
  240. package/dist/test-utils/render-with-theme.js +2 -1
  241. package/dist/test-utils/render-with-theme.js.map +1 -1
  242. package/dist/tool-calling/tool-parser.d.ts +3 -2
  243. package/dist/tool-calling/tool-parser.d.ts.map +1 -1
  244. package/dist/tool-calling/tool-parser.js +6 -27
  245. package/dist/tool-calling/tool-parser.js.map +1 -1
  246. package/dist/tools/execute-bash.d.ts.map +1 -1
  247. package/dist/tools/execute-bash.js +5 -0
  248. package/dist/tools/execute-bash.js.map +1 -1
  249. package/dist/tools/fetch-url.d.ts.map +1 -1
  250. package/dist/tools/fetch-url.js +11 -2
  251. package/dist/tools/fetch-url.js.map +1 -1
  252. package/dist/tools/file-ops/copy-file.d.ts.map +1 -1
  253. package/dist/tools/file-ops/copy-file.js +6 -36
  254. package/dist/tools/file-ops/copy-file.js.map +1 -1
  255. package/dist/tools/file-ops/create-directory.d.ts.map +1 -1
  256. package/dist/tools/file-ops/create-directory.js +2 -19
  257. package/dist/tools/file-ops/create-directory.js.map +1 -1
  258. package/dist/tools/file-ops/delete-file.d.ts.map +1 -1
  259. package/dist/tools/file-ops/delete-file.js +6 -20
  260. package/dist/tools/file-ops/delete-file.js.map +1 -1
  261. package/dist/tools/file-ops/move-file.d.ts.map +1 -1
  262. package/dist/tools/file-ops/move-file.js +6 -36
  263. package/dist/tools/file-ops/move-file.js.map +1 -1
  264. package/dist/tools/file-ops/string-replace-preview.d.ts +10 -0
  265. package/dist/tools/file-ops/string-replace-preview.d.ts.map +1 -0
  266. package/dist/tools/file-ops/string-replace-preview.js +171 -0
  267. package/dist/tools/file-ops/string-replace-preview.js.map +1 -0
  268. package/dist/tools/file-ops/string-replace.d.ts.map +1 -1
  269. package/dist/tools/file-ops/string-replace.js +9 -292
  270. package/dist/tools/file-ops/string-replace.js.map +1 -1
  271. package/dist/tools/file-ops/write-file.d.ts.map +1 -1
  272. package/dist/tools/file-ops/write-file.js +7 -66
  273. package/dist/tools/file-ops/write-file.js.map +1 -1
  274. package/dist/tools/find-files.d.ts.map +1 -1
  275. package/dist/tools/find-files.js +1 -0
  276. package/dist/tools/find-files.js.map +1 -1
  277. package/dist/tools/git/git-diff.d.ts.map +1 -1
  278. package/dist/tools/git/git-diff.js +1 -0
  279. package/dist/tools/git/git-diff.js.map +1 -1
  280. package/dist/tools/git/git-log.d.ts.map +1 -1
  281. package/dist/tools/git/git-log.js +1 -0
  282. package/dist/tools/git/git-log.js.map +1 -1
  283. package/dist/tools/git/git-status.d.ts.map +1 -1
  284. package/dist/tools/git/git-status.js +1 -0
  285. package/dist/tools/git/git-status.js.map +1 -1
  286. package/dist/tools/index.d.ts +1 -0
  287. package/dist/tools/index.d.ts.map +1 -1
  288. package/dist/tools/index.js +7 -0
  289. package/dist/tools/index.js.map +1 -1
  290. package/dist/tools/list-directory.d.ts.map +1 -1
  291. package/dist/tools/list-directory.js +2 -1
  292. package/dist/tools/list-directory.js.map +1 -1
  293. package/dist/tools/lsp-get-diagnostics.d.ts.map +1 -1
  294. package/dist/tools/lsp-get-diagnostics.js +1 -5
  295. package/dist/tools/lsp-get-diagnostics.js.map +1 -1
  296. package/dist/tools/read-file.d.ts.map +1 -1
  297. package/dist/tools/read-file.js +1 -0
  298. package/dist/tools/read-file.js.map +1 -1
  299. package/dist/tools/search-file-contents.d.ts.map +1 -1
  300. package/dist/tools/search-file-contents.js +1 -0
  301. package/dist/tools/search-file-contents.js.map +1 -1
  302. package/dist/tools/tasks/list-tasks.d.ts.map +1 -1
  303. package/dist/tools/tasks/list-tasks.js +1 -0
  304. package/dist/tools/tasks/list-tasks.js.map +1 -1
  305. package/dist/tools/tool-manager.d.ts +10 -0
  306. package/dist/tools/tool-manager.d.ts.map +1 -1
  307. package/dist/tools/tool-manager.js +16 -2
  308. package/dist/tools/tool-manager.js.map +1 -1
  309. package/dist/tools/tool-registry.d.ts +9 -1
  310. package/dist/tools/tool-registry.d.ts.map +1 -1
  311. package/dist/tools/tool-registry.js +17 -1
  312. package/dist/tools/tool-registry.js.map +1 -1
  313. package/dist/tools/web-search.d.ts.map +1 -1
  314. package/dist/tools/web-search.js +1 -0
  315. package/dist/tools/web-search.js.map +1 -1
  316. package/dist/types/app.d.ts +3 -0
  317. package/dist/types/app.d.ts.map +1 -1
  318. package/dist/types/commands.d.ts +1 -2
  319. package/dist/types/commands.d.ts.map +1 -1
  320. package/dist/types/config.d.ts +11 -15
  321. package/dist/types/config.d.ts.map +1 -1
  322. package/dist/types/core.d.ts +13 -3
  323. package/dist/types/core.d.ts.map +1 -1
  324. package/dist/types/core.js.map +1 -1
  325. package/dist/types/markdown-parser.d.ts +2 -10
  326. package/dist/types/markdown-parser.d.ts.map +1 -1
  327. package/dist/types/mcp.d.ts +2 -28
  328. package/dist/types/mcp.d.ts.map +1 -1
  329. package/dist/types/ui.d.ts +1 -1
  330. package/dist/types/ui.d.ts.map +1 -1
  331. package/dist/utils/ansi-truncate.d.ts +6 -0
  332. package/dist/utils/ansi-truncate.d.ts.map +1 -0
  333. package/dist/utils/ansi-truncate.js +39 -0
  334. package/dist/utils/ansi-truncate.js.map +1 -0
  335. package/dist/utils/installation-detector.d.ts +6 -0
  336. package/dist/utils/installation-detector.d.ts.map +1 -1
  337. package/dist/utils/installation-detector.js +33 -19
  338. package/dist/utils/installation-detector.js.map +1 -1
  339. package/dist/utils/logging/health-monitor/checks/memory-check.d.ts.map +1 -1
  340. package/dist/utils/logging/health-monitor/checks/memory-check.js +2 -1
  341. package/dist/utils/logging/health-monitor/checks/memory-check.js.map +1 -1
  342. package/dist/utils/logging/health-monitor/core/health-monitor.d.ts.map +1 -1
  343. package/dist/utils/logging/health-monitor/core/health-monitor.js +3 -2
  344. package/dist/utils/logging/health-monitor/core/health-monitor.js.map +1 -1
  345. package/dist/utils/logging/performance.d.ts.map +1 -1
  346. package/dist/utils/logging/performance.js +21 -17
  347. package/dist/utils/logging/performance.js.map +1 -1
  348. package/dist/utils/logging/pino-logger.d.ts.map +1 -1
  349. package/dist/utils/logging/pino-logger.js +7 -8
  350. package/dist/utils/logging/pino-logger.js.map +1 -1
  351. package/dist/utils/logging/redaction.d.ts.map +1 -1
  352. package/dist/utils/logging/redaction.js +2 -0
  353. package/dist/utils/logging/redaction.js.map +1 -1
  354. package/dist/utils/logging/request-tracker.d.ts.map +1 -1
  355. package/dist/utils/logging/request-tracker.js +6 -5
  356. package/dist/utils/logging/request-tracker.js.map +1 -1
  357. package/dist/utils/logging/safe-process.d.ts +16 -0
  358. package/dist/utils/logging/safe-process.d.ts.map +1 -0
  359. package/dist/utils/logging/safe-process.js +37 -0
  360. package/dist/utils/logging/safe-process.js.map +1 -0
  361. package/dist/utils/logging/types.d.ts +0 -3
  362. package/dist/utils/logging/types.d.ts.map +1 -1
  363. package/dist/utils/message-builder.d.ts +0 -5
  364. package/dist/utils/message-builder.d.ts.map +1 -1
  365. package/dist/utils/message-builder.js +0 -8
  366. package/dist/utils/message-builder.js.map +1 -1
  367. package/dist/utils/path-validation.d.ts.map +1 -1
  368. package/dist/utils/path-validation.js +3 -1
  369. package/dist/utils/path-validation.js.map +1 -1
  370. package/dist/utils/path-validators.d.ts +16 -0
  371. package/dist/utils/path-validators.d.ts.map +1 -0
  372. package/dist/utils/path-validators.js +55 -0
  373. package/dist/utils/path-validators.js.map +1 -0
  374. package/dist/utils/response-formatter.d.ts.map +1 -1
  375. package/dist/utils/response-formatter.js +2 -17
  376. package/dist/utils/response-formatter.js.map +1 -1
  377. package/dist/utils/text-wrapping.d.ts +8 -0
  378. package/dist/utils/text-wrapping.d.ts.map +1 -0
  379. package/dist/utils/text-wrapping.js +29 -0
  380. package/dist/utils/text-wrapping.js.map +1 -0
  381. package/dist/utils/tool-approval.d.ts +6 -0
  382. package/dist/utils/tool-approval.d.ts.map +1 -0
  383. package/dist/utils/tool-approval.js +15 -0
  384. package/dist/utils/tool-approval.js.map +1 -0
  385. package/dist/utils/tool-result-display.d.ts +15 -1
  386. package/dist/utils/tool-result-display.d.ts.map +1 -1
  387. package/dist/utils/tool-result-display.js +93 -3
  388. package/dist/utils/tool-result-display.js.map +1 -1
  389. package/dist/vscode/extension-installer.d.ts +34 -7
  390. package/dist/vscode/extension-installer.d.ts.map +1 -1
  391. package/dist/vscode/extension-installer.js +151 -64
  392. package/dist/vscode/extension-installer.js.map +1 -1
  393. package/dist/vscode/index.d.ts +1 -1
  394. package/dist/vscode/index.d.ts.map +1 -1
  395. package/dist/vscode/index.js +1 -1
  396. package/dist/vscode/index.js.map +1 -1
  397. package/dist/wizards/mcp-wizard.d.ts.map +1 -1
  398. package/dist/wizards/mcp-wizard.js +2 -1
  399. package/dist/wizards/mcp-wizard.js.map +1 -1
  400. package/dist/wizards/provider-wizard.d.ts.map +1 -1
  401. package/dist/wizards/provider-wizard.js +4 -2
  402. package/dist/wizards/provider-wizard.js.map +1 -1
  403. package/dist/wizards/steps/location-step.d.ts.map +1 -1
  404. package/dist/wizards/steps/location-step.js +2 -1
  405. package/dist/wizards/steps/location-step.js.map +1 -1
  406. package/dist/wizards/steps/mcp-step.d.ts.map +1 -1
  407. package/dist/wizards/steps/mcp-step.js +2 -1
  408. package/dist/wizards/steps/mcp-step.js.map +1 -1
  409. package/dist/wizards/steps/provider-step.d.ts.map +1 -1
  410. package/dist/wizards/steps/provider-step.js +4 -1
  411. package/dist/wizards/steps/provider-step.js.map +1 -1
  412. package/dist/wizards/steps/summary-step.d.ts.map +1 -1
  413. package/dist/wizards/steps/summary-step.js +2 -1
  414. package/dist/wizards/steps/summary-step.js.map +1 -1
  415. package/dist/wizards/templates/mcp-templates.d.ts +0 -8
  416. package/dist/wizards/templates/mcp-templates.d.ts.map +1 -1
  417. package/dist/wizards/templates/mcp-templates.js.map +1 -1
  418. package/dist/wizards/templates/provider-templates.d.ts.map +1 -1
  419. package/dist/wizards/templates/provider-templates.js +59 -0
  420. package/dist/wizards/templates/provider-templates.js.map +1 -1
  421. package/dist/wizards/validation.d.ts.map +1 -1
  422. package/dist/wizards/validation.js +0 -1
  423. package/dist/wizards/validation.js.map +1 -1
  424. package/package.json +20 -12
  425. package/source/config/themes.json +787 -0
  426. package/dist/ai-sdk-client/chat/tool-processor.d.ts +0 -10
  427. package/dist/ai-sdk-client/chat/tool-processor.d.ts.map +0 -1
  428. package/dist/ai-sdk-client/chat/tool-processor.js +0 -58
  429. package/dist/ai-sdk-client/chat/tool-processor.js.map +0 -1
  430. package/dist/tool-calling/json-parser.d.ts +0 -28
  431. package/dist/tool-calling/json-parser.d.ts.map +0 -1
  432. package/dist/tool-calling/json-parser.js +0 -219
  433. package/dist/tool-calling/json-parser.js.map +0 -1
@@ -1,19 +1,18 @@
1
- import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
2
- import { join } from 'node:path';
3
1
  import React from 'react';
4
2
  import { parseInput } from '../../command-parser.js';
5
3
  import { commandRegistry } from '../../commands.js';
4
+ import { CopilotLogin } from '../../commands/copilot-login.js';
6
5
  import BashProgress from '../../components/bash-progress.js';
7
6
  import { ErrorMessage, InfoMessage, SuccessMessage, } from '../../components/message-box.js';
8
7
  import { DELAY_COMMAND_COMPLETE_MS } from '../../constants.js';
9
- import { getModelContextLimit, getSessionContextLimit, resetSessionContextLimit, setSessionContextLimit, } from '../../models/index.js';
10
8
  import { CheckpointManager } from '../../services/checkpoint-manager.js';
11
- import { createTokenizer } from '../../tokenization/index.js';
12
9
  import { executeBashCommand, formatBashResultForLLM } from '../../tools/execute-bash.js';
13
- import { setAutoCompactEnabled, setAutoCompactThreshold, } from '../../utils/auto-compact.js';
14
- import { compressionBackup } from '../../utils/compression-backup.js';
15
- import { compressMessages } from '../../utils/message-compression.js';
16
- import { processPromptTemplate } from '../../utils/prompt-processor.js';
10
+ import { handleCompactCommand } from './handlers/compact-handler.js';
11
+ import { handleContextMaxCommand } from './handlers/context-max-handler.js';
12
+ import { handleCommandCreate, handleScheduleCreate, handleScheduleStart, } from './handlers/create-handler.js';
13
+ import { handleResumeCommand } from './handlers/session-handler.js';
14
+ // Re-export for consumers that import parseContextLimit from here
15
+ export { parseContextLimit } from './handlers/context-max-handler.js';
17
16
  /** Command names that require special handling in the app */
18
17
  const SPECIAL_COMMANDS = {
19
18
  CLEAR: 'clear',
@@ -27,8 +26,6 @@ const SPECIAL_COMMANDS = {
27
26
  CHECKPOINT: 'checkpoint',
28
27
  EXPLORER: 'explorer',
29
28
  IDE: 'ide',
30
- SCHEDULE: 'schedule',
31
- COMMANDS: 'commands',
32
29
  };
33
30
  /** Checkpoint subcommands */
34
31
  const CHECKPOINT_SUBCOMMANDS = {
@@ -43,25 +40,19 @@ function getErrorMessage(error, fallback = 'Unknown error') {
43
40
  }
44
41
  /**
45
42
  * Handles bash commands prefixed with !
46
- * Uses the unified bash executor service for real-time progress updates
47
43
  */
48
44
  async function handleBashCommand(bashCommand, options) {
49
45
  const { onAddToChatQueue, setLiveComponent, setIsToolExecuting, onCommandComplete, getNextComponentKey, setMessages, messages, } = options;
50
- // Block user input while executing
51
46
  setIsToolExecuting(true);
52
47
  try {
53
- // Start execution and get the execution ID
54
48
  const { executionId, promise } = executeBashCommand(bashCommand);
55
- // Set as live component for real-time updates (renders outside Static)
56
49
  setLiveComponent(React.createElement(BashProgress, {
57
50
  key: `bash-progress-live-${getNextComponentKey()}`,
58
51
  executionId,
59
52
  command: bashCommand,
60
53
  isLive: true,
61
54
  }));
62
- // Wait for execution to complete
63
55
  const result = await promise;
64
- // Clear live component and add static completed version to chat queue
65
56
  setLiveComponent(null);
66
57
  onAddToChatQueue(React.createElement(BashProgress, {
67
58
  key: `bash-progress-complete-${getNextComponentKey()}`,
@@ -69,9 +60,7 @@ async function handleBashCommand(bashCommand, options) {
69
60
  command: bashCommand,
70
61
  completedState: result,
71
62
  }));
72
- // Format result for LLM context
73
63
  const llmContext = formatBashResultForLLM(result);
74
- // Add the output to the LLM context for future interactions
75
64
  if (llmContext) {
76
65
  const userMessage = {
77
66
  role: 'user',
@@ -81,24 +70,20 @@ async function handleBashCommand(bashCommand, options) {
81
70
  }
82
71
  }
83
72
  catch (error) {
84
- // Clear live component on error
85
73
  setLiveComponent(null);
86
- // Show error message if command fails
87
74
  onAddToChatQueue(React.createElement(ErrorMessage, {
88
75
  key: `bash-error-${getNextComponentKey()}`,
89
76
  message: `Error executing command: ${getErrorMessage(error, String(error))}`,
90
77
  }));
91
78
  }
92
79
  finally {
93
- // Re-enable user input
94
80
  setIsToolExecuting(false);
95
- // Signal completion for non-interactive mode
96
81
  onCommandComplete?.();
97
82
  }
98
83
  }
99
84
  /**
100
- * Handles custom user-defined commands
101
- * Returns true if a custom command was found and handled
85
+ * Handles custom user-defined commands.
86
+ * Returns true if a custom command was found and handled.
102
87
  */
103
88
  async function handleCustomCommand(message, commandName, options) {
104
89
  const { customCommandCache, customCommandLoader, customCommandExecutor, onHandleChatMessage, onCommandComplete, } = options;
@@ -107,40 +92,34 @@ async function handleCustomCommand(message, commandName, options) {
107
92
  if (!customCommand) {
108
93
  return false;
109
94
  }
110
- // Execute custom command with any arguments
111
- // Slice past '/' + commandName + space to get the arguments
112
95
  const args = message
113
96
  .slice(commandName.length + 2)
114
97
  .trim()
115
98
  .split(/\s+/)
116
99
  .filter(arg => arg);
117
100
  const processedPrompt = customCommandExecutor?.execute(customCommand, args);
118
- // Send the processed prompt to the AI
119
101
  if (processedPrompt) {
120
102
  await onHandleChatMessage(processedPrompt);
121
103
  }
122
104
  else {
123
- // Custom command didn't generate a prompt, signal completion
124
105
  onCommandComplete?.();
125
106
  }
126
107
  return true;
127
108
  }
128
109
  /**
129
110
  * Handles special commands that need app state access (/clear, /model, etc.)
130
- * Returns true if a special command was handled
111
+ * Returns true if a special command was handled.
131
112
  */
132
113
  async function handleSpecialCommand(commandName, options) {
133
114
  const { onClearMessages, onEnterModelSelectionMode, onEnterProviderSelectionMode, onEnterModelDatabaseMode, onEnterConfigWizardMode, onEnterSettingsMode, onEnterMcpWizardMode, onEnterExplorerMode, onShowStatus, onCommandComplete, onAddToChatQueue, getNextComponentKey, } = options;
134
115
  switch (commandName) {
135
116
  case SPECIAL_COMMANDS.CLEAR:
136
117
  await onClearMessages();
137
- // Show success message
138
118
  onAddToChatQueue(React.createElement(SuccessMessage, {
139
119
  key: `clear-success-${getNextComponentKey()}`,
140
120
  message: 'Chat cleared.',
141
121
  hideBox: true,
142
122
  }));
143
- // Give React time to render before signaling completion
144
123
  setTimeout(() => onCommandComplete?.(), DELAY_COMMAND_COMPLETE_MS);
145
124
  return true;
146
125
  case SPECIAL_COMMANDS.MODEL:
@@ -169,7 +148,6 @@ async function handleSpecialCommand(commandName, options) {
169
148
  return true;
170
149
  case SPECIAL_COMMANDS.STATUS:
171
150
  onShowStatus();
172
- // Status adds to queue synchronously, give React time to render
173
151
  setTimeout(() => onCommandComplete?.(), DELAY_COMMAND_COMPLETE_MS);
174
152
  return true;
175
153
  case SPECIAL_COMMANDS.EXPLORER:
@@ -185,402 +163,11 @@ async function handleSpecialCommand(commandName, options) {
185
163
  }
186
164
  }
187
165
  /**
188
- * Handles /schedule start as a special case that enters scheduler mode.
189
- * Other /schedule subcommands go through the normal command registry.
190
- * Returns true if handled.
191
- */
192
- async function handleScheduleStart(commandParts, options) {
193
- if (commandParts[0] !== SPECIAL_COMMANDS.SCHEDULE ||
194
- commandParts[1] !== 'start') {
195
- return false;
196
- }
197
- const { onEnterSchedulerMode, onCommandComplete } = options;
198
- if (onEnterSchedulerMode) {
199
- onEnterSchedulerMode();
200
- onCommandComplete?.();
201
- }
202
- else {
203
- options.onAddToChatQueue(React.createElement(ErrorMessage, {
204
- key: `schedule-error-${options.getNextComponentKey()}`,
205
- message: 'Scheduler mode is not available.',
206
- }));
207
- onCommandComplete?.();
208
- }
209
- return true;
210
- }
211
- /**
212
- * Handles /schedule create — creates the schedule file and prompts the AI to help write it.
213
- * Returns true if handled.
214
- */
215
- async function handleScheduleCreate(commandParts, options) {
216
- if (commandParts[0] !== SPECIAL_COMMANDS.SCHEDULE ||
217
- commandParts[1] !== 'create') {
218
- return false;
219
- }
220
- const { onAddToChatQueue, onHandleChatMessage, onCommandComplete, getNextComponentKey, } = options;
221
- const fileName = commandParts[2];
222
- if (!fileName) {
223
- onAddToChatQueue(React.createElement(ErrorMessage, {
224
- key: `schedule-create-error-${getNextComponentKey()}`,
225
- message: 'Usage: /schedule create <name>\nExample: /schedule create deps-update',
226
- }));
227
- onCommandComplete?.();
228
- return true;
229
- }
230
- const safeName = fileName.endsWith('.md') ? fileName : `${fileName}.md`;
231
- const schedulesDir = join(process.cwd(), '.nanocoder', 'schedules');
232
- const filePath = join(schedulesDir, safeName);
233
- if (existsSync(filePath)) {
234
- onAddToChatQueue(React.createElement(ErrorMessage, {
235
- key: `schedule-create-exists-${getNextComponentKey()}`,
236
- message: `Schedule file already exists: .nanocoder/schedules/${safeName}`,
237
- }));
238
- onCommandComplete?.();
239
- return true;
240
- }
241
- mkdirSync(schedulesDir, { recursive: true });
242
- const template = `---
243
- description: ${safeName.replace(/\.md$/, '')} scheduled command
244
- ---
245
-
246
- `;
247
- writeFileSync(filePath, template, 'utf-8');
248
- onAddToChatQueue(React.createElement(SuccessMessage, {
249
- key: `schedule-created-${getNextComponentKey()}`,
250
- message: `Created schedule file: .nanocoder/schedules/${safeName}`,
251
- hideBox: true,
252
- }));
253
- // Ask the AI to help write the schedule command content
254
- await onHandleChatMessage(`I just created a new schedule command file at .nanocoder/schedules/${safeName}. Help me write the content for this scheduled task. Ask me what I want this scheduled job to do, then write the markdown prompt into the file using the write_file tool. The file should contain a clear prompt that instructs the AI agent what to do when this schedule runs. Keep the YAML frontmatter at the top with the description field.`);
255
- return true;
256
- }
257
- /**
258
- * Handles /commands create — creates the command file and prompts the AI to help write it.
259
- * Returns true if handled.
260
- */
261
- async function handleCommandCreate(commandParts, options) {
262
- if ((commandParts[0] !== SPECIAL_COMMANDS.COMMANDS &&
263
- commandParts[0] !== 'custom-commands') ||
264
- commandParts[1] !== 'create') {
265
- return false;
266
- }
267
- const { onAddToChatQueue, onHandleChatMessage, onCommandComplete, getNextComponentKey, } = options;
268
- const fileName = commandParts[2];
269
- if (!fileName) {
270
- onAddToChatQueue(React.createElement(ErrorMessage, {
271
- key: `commands-create-error-${getNextComponentKey()}`,
272
- message: 'Usage: /commands create <name>\nExample: /commands create review-code',
273
- }));
274
- onCommandComplete?.();
275
- return true;
276
- }
277
- const safeName = fileName.endsWith('.md') ? fileName : `${fileName}.md`;
278
- const commandsDir = join(process.cwd(), '.nanocoder', 'commands');
279
- const filePath = join(commandsDir, safeName);
280
- if (existsSync(filePath)) {
281
- onAddToChatQueue(React.createElement(ErrorMessage, {
282
- key: `commands-create-exists-${getNextComponentKey()}`,
283
- message: `Command file already exists: .nanocoder/commands/${safeName}`,
284
- }));
285
- onCommandComplete?.();
286
- return true;
287
- }
288
- mkdirSync(commandsDir, { recursive: true });
289
- const template = `---
290
- description: ${safeName.replace(/\.md$/, '')} custom command
291
- ---
292
-
293
- `;
294
- writeFileSync(filePath, template, 'utf-8');
295
- onAddToChatQueue(React.createElement(SuccessMessage, {
296
- key: `commands-created-${getNextComponentKey()}`,
297
- message: `Created command file: .nanocoder/commands/${safeName}`,
298
- hideBox: true,
299
- }));
300
- // Ask the AI to help write the custom command content
301
- const commandBaseName = safeName.replace(/\.md$/, '');
302
- await onHandleChatMessage(`I just created a new custom command file at .nanocoder/commands/${safeName}. Help me write the content for this command. Ask me what I want this command to do, then write the markdown prompt into the file using the write_file tool. The file should contain a clear prompt that instructs the AI what to do when this command is invoked via /${commandBaseName}. Keep the YAML frontmatter at the top.
303
-
304
- Here is an example of the frontmatter format with all available fields:
305
-
306
- ---
307
- description: Generate unit tests for a file
308
- aliases: [test, unittest]
309
- parameters: [filename]
310
- tags: [testing, quality]
311
- triggers: [write tests, unit test]
312
- estimated-tokens: 2000
313
- resources: true
314
- category: testing
315
- version: 1.0.0
316
- author: user
317
- examples:
318
- - /gen-tests src/utils.ts
319
- - /gen-tests lib/parser.ts
320
- references: [docs/testing-guide.md]
321
- dependencies: [lint]
322
- ---
323
- Generate comprehensive unit tests for {{filename}}...
324
-
325
- All fields are optional except description. Use whichever fields are appropriate for the user's needs. Parameters defined here can be used as {{param}} placeholders in the prompt body.`);
326
- return true;
327
- }
328
- // Handles compact command, Returns true if compact command was handled
329
- async function handleCompactCommand(commandParts, options) {
330
- const { onAddToChatQueue, onCommandComplete, getNextComponentKey, messages, setMessages, provider, model, } = options;
331
- // Check if this is a compact command
332
- if (commandParts[0] !== 'compact') {
333
- return false;
334
- }
335
- // Parse arguments
336
- const args = commandParts.slice(1);
337
- let mode = 'default';
338
- let preview = false;
339
- for (let i = 0; i < args.length; i++) {
340
- const arg = args[i];
341
- if (arg === '--aggressive') {
342
- mode = 'aggressive';
343
- }
344
- else if (arg === '--conservative') {
345
- mode = 'conservative';
346
- }
347
- else if (arg === '--preview') {
348
- preview = true;
349
- }
350
- else if (arg === '--default') {
351
- mode = 'default';
352
- }
353
- else if (arg === '--restore') {
354
- // Restore messages from backup
355
- const restored = compressionBackup.restore();
356
- if (restored) {
357
- setMessages(restored);
358
- onAddToChatQueue(React.createElement(SuccessMessage, {
359
- key: `compact-restore-${getNextComponentKey()}`,
360
- message: `Restored ${restored.length} messages from backup.`,
361
- hideBox: true,
362
- }));
363
- compressionBackup.clearBackup();
364
- }
365
- else {
366
- onAddToChatQueue(React.createElement(ErrorMessage, {
367
- key: `compact-restore-error-${getNextComponentKey()}`,
368
- message: 'No backup available to restore.',
369
- hideBox: true,
370
- }));
371
- }
372
- setTimeout(() => onCommandComplete?.(), DELAY_COMMAND_COMPLETE_MS);
373
- return true;
374
- }
375
- else if (arg === '--auto-on') {
376
- // Enable auto-compact for current session
377
- setAutoCompactEnabled(true);
378
- onAddToChatQueue(React.createElement(SuccessMessage, {
379
- key: `compact-auto-on-${getNextComponentKey()}`,
380
- message: 'Auto-compact enabled for this session.',
381
- hideBox: true,
382
- }));
383
- setTimeout(() => onCommandComplete?.(), DELAY_COMMAND_COMPLETE_MS);
384
- return true;
385
- }
386
- else if (arg === '--auto-off') {
387
- // Disable auto compact for current session
388
- setAutoCompactEnabled(false);
389
- onAddToChatQueue(React.createElement(SuccessMessage, {
390
- key: `compact-auto-off-${getNextComponentKey()}`,
391
- message: 'Auto-compact disabled for this session.',
392
- hideBox: true,
393
- }));
394
- setTimeout(() => onCommandComplete?.(), DELAY_COMMAND_COMPLETE_MS);
395
- return true;
396
- }
397
- else if (arg === '--threshold' && i + 1 < args.length) {
398
- // Set threshold for current session
399
- const thresholdValue = Number.parseFloat(args[i + 1]);
400
- if (Number.isNaN(thresholdValue) ||
401
- thresholdValue < 50 ||
402
- thresholdValue > 95) {
403
- onAddToChatQueue(React.createElement(ErrorMessage, {
404
- key: `compact-threshold-error-${getNextComponentKey()}`,
405
- message: 'Threshold must be a number between 50 and 95.',
406
- hideBox: true,
407
- }));
408
- setTimeout(() => onCommandComplete?.(), DELAY_COMMAND_COMPLETE_MS);
409
- return true;
410
- }
411
- setAutoCompactThreshold(Math.round(thresholdValue));
412
- onAddToChatQueue(React.createElement(SuccessMessage, {
413
- key: `compact-threshold-${getNextComponentKey()}`,
414
- message: `Auto-compact threshold set to ${Math.round(thresholdValue)}% for this session.`,
415
- hideBox: true,
416
- }));
417
- setTimeout(() => onCommandComplete?.(), DELAY_COMMAND_COMPLETE_MS);
418
- return true;
419
- }
420
- }
421
- try {
422
- if (messages.length === 0) {
423
- onAddToChatQueue(React.createElement(InfoMessage, {
424
- key: `compact-info-${getNextComponentKey()}`,
425
- message: 'No messages to compact.',
426
- hideBox: true,
427
- }));
428
- onCommandComplete?.();
429
- return true;
430
- }
431
- // Create tokenizer
432
- const tokenizer = createTokenizer(provider, model);
433
- // Include system message in token calculations for consistency with /status and auto-compact
434
- const systemPrompt = processPromptTemplate();
435
- const systemMessage = { role: 'system', content: systemPrompt };
436
- const allMessages = [systemMessage, ...messages];
437
- // Perform compression (includes system message for accurate token counting)
438
- const result = compressMessages(allMessages, tokenizer, { mode });
439
- // Clean up tokenizer
440
- if (tokenizer.free) {
441
- tokenizer.free();
442
- }
443
- if (preview) {
444
- // Preview mode: show what would be compressed without applying
445
- const message = `Preview: Context would be compacted: ${result.originalTokenCount.toLocaleString()} tokens → ${result.compressedTokenCount.toLocaleString()} tokens (${Math.round(result.reductionPercentage)}% reduction)\n\nPreserved:\n• ${result.preservedInfo.keyDecisions} key decisions\n• ${result.preservedInfo.fileModifications} file modifications\n• ${result.preservedInfo.toolResults} tool results\n• ${result.preservedInfo.recentMessages} recent messages at full detail`;
446
- onAddToChatQueue(React.createElement(InfoMessage, {
447
- key: `compact-preview-${getNextComponentKey()}`,
448
- message,
449
- hideBox: false,
450
- }));
451
- }
452
- else {
453
- // Apply compression and store backup before compression
454
- compressionBackup.storeBackup(messages);
455
- // Filter out system messages from compressed result (they're managed separately)
456
- const compressedUserMessages = result.compressedMessages.filter(msg => msg.role !== 'system');
457
- setMessages(compressedUserMessages);
458
- // Show success message
459
- const message = `Context Compacted: ${result.originalTokenCount.toLocaleString()} tokens → ${result.compressedTokenCount.toLocaleString()} tokens (${Math.round(result.reductionPercentage)}% reduction)\n\nPreserved:\n• ${result.preservedInfo.keyDecisions} key decisions\n• ${result.preservedInfo.fileModifications} file modifications\n• ${result.preservedInfo.toolResults} tool results\n• ${result.preservedInfo.recentMessages} recent messages at full detail`;
460
- onAddToChatQueue(React.createElement(SuccessMessage, {
461
- key: `compact-success-${getNextComponentKey()}`,
462
- message,
463
- hideBox: false,
464
- }));
465
- }
466
- setTimeout(() => onCommandComplete?.(), DELAY_COMMAND_COMPLETE_MS);
467
- return true;
468
- }
469
- catch (error) {
470
- onAddToChatQueue(React.createElement(ErrorMessage, {
471
- key: `compact-error-${getNextComponentKey()}`,
472
- message: `Failed to compact messages: ${getErrorMessage(error)}`,
473
- hideBox: true,
474
- }));
475
- onCommandComplete?.();
476
- return true;
477
- }
478
- }
479
- /**
480
- * Parses a context limit value string, supporting k/K suffix.
481
- * e.g. "8192" -> 8192, "128k" -> 128000, "128K" -> 128000
482
- */
483
- export function parseContextLimit(value) {
484
- const trimmed = value.trim().toLowerCase();
485
- let multiplier = 1;
486
- let numStr = trimmed;
487
- if (trimmed.endsWith('k')) {
488
- multiplier = 1000;
489
- numStr = trimmed.slice(0, -1);
490
- }
491
- const parsed = Number.parseFloat(numStr);
492
- if (Number.isNaN(parsed) || parsed <= 0) {
493
- return null;
494
- }
495
- return Math.round(parsed * multiplier);
496
- }
497
- // Handles /context-max command. Returns true if handled.
498
- async function handleContextMaxCommand(commandParts, options) {
499
- const { onAddToChatQueue, onCommandComplete, getNextComponentKey, model } = options;
500
- if (commandParts[0] !== 'context-max') {
501
- return false;
502
- }
503
- const args = commandParts.slice(1);
504
- // /context-max --reset — clear session override
505
- if (args[0] === '--reset') {
506
- resetSessionContextLimit();
507
- onAddToChatQueue(React.createElement(SuccessMessage, {
508
- key: `context-max-reset-${getNextComponentKey()}`,
509
- message: 'Session context limit override cleared.',
510
- hideBox: true,
511
- }));
512
- setTimeout(() => onCommandComplete?.(), DELAY_COMMAND_COMPLETE_MS);
513
- return true;
514
- }
515
- // /context-max <number> — set session context limit
516
- if (args.length > 0) {
517
- const limit = parseContextLimit(args[0]);
518
- if (limit === null) {
519
- onAddToChatQueue(React.createElement(ErrorMessage, {
520
- key: `context-max-error-${getNextComponentKey()}`,
521
- message: 'Invalid context limit. Use a positive number, e.g. /context-max 8192 or /context-max 128k',
522
- }));
523
- setTimeout(() => onCommandComplete?.(), DELAY_COMMAND_COMPLETE_MS);
524
- return true;
525
- }
526
- setSessionContextLimit(limit);
527
- onAddToChatQueue(React.createElement(SuccessMessage, {
528
- key: `context-max-set-${getNextComponentKey()}`,
529
- message: `Session context limit set to ${limit.toLocaleString()} tokens.`,
530
- hideBox: true,
531
- }));
532
- setTimeout(() => onCommandComplete?.(), DELAY_COMMAND_COMPLETE_MS);
533
- return true;
534
- }
535
- // /context-max (no args) — show current effective context limit
536
- const sessionLimit = getSessionContextLimit();
537
- if (sessionLimit !== null) {
538
- onAddToChatQueue(React.createElement(InfoMessage, {
539
- key: `context-max-info-${getNextComponentKey()}`,
540
- message: `Context limit: ${sessionLimit.toLocaleString()} tokens (session override)`,
541
- hideBox: true,
542
- }));
543
- setTimeout(() => onCommandComplete?.(), DELAY_COMMAND_COMPLETE_MS);
544
- return true;
545
- }
546
- const envLimit = process.env.NANOCODER_CONTEXT_LIMIT;
547
- if (envLimit) {
548
- const parsed = Number.parseInt(envLimit, 10);
549
- if (!Number.isNaN(parsed) && parsed > 0) {
550
- onAddToChatQueue(React.createElement(InfoMessage, {
551
- key: `context-max-info-${getNextComponentKey()}`,
552
- message: `Context limit: ${parsed.toLocaleString()} tokens (NANOCODER_CONTEXT_LIMIT env)`,
553
- hideBox: true,
554
- }));
555
- setTimeout(() => onCommandComplete?.(), DELAY_COMMAND_COMPLETE_MS);
556
- return true;
557
- }
558
- }
559
- const modelLimit = await getModelContextLimit(model);
560
- if (modelLimit !== null) {
561
- onAddToChatQueue(React.createElement(InfoMessage, {
562
- key: `context-max-info-${getNextComponentKey()}`,
563
- message: `Context limit: ${modelLimit.toLocaleString()} tokens (model lookup)`,
564
- hideBox: true,
565
- }));
566
- }
567
- else {
568
- onAddToChatQueue(React.createElement(InfoMessage, {
569
- key: `context-max-info-${getNextComponentKey()}`,
570
- message: 'Context limit: Unknown. Use /context-max <number> to set one.',
571
- hideBox: true,
572
- }));
573
- }
574
- setTimeout(() => onCommandComplete?.(), DELAY_COMMAND_COMPLETE_MS);
575
- return true;
576
- }
577
- /**
578
- * Handles interactive checkpoint load command
579
- * Returns true if checkpoint load was handled
166
+ * Handles interactive checkpoint load command.
167
+ * Returns true if checkpoint load was handled.
580
168
  */
581
169
  async function handleCheckpointLoad(commandParts, options) {
582
170
  const { onAddToChatQueue, onEnterCheckpointLoadMode, onCommandComplete, getNextComponentKey, messages, } = options;
583
- // Check if this is an interactive checkpoint load command
584
171
  const isCheckpointLoad = commandParts[0] === SPECIAL_COMMANDS.CHECKPOINT &&
585
172
  (commandParts[1] === CHECKPOINT_SUBCOMMANDS.LOAD ||
586
173
  commandParts[1] === CHECKPOINT_SUBCOMMANDS.RESTORE) &&
@@ -614,7 +201,42 @@ async function handleCheckpointLoad(commandParts, options) {
614
201
  }
615
202
  }
616
203
  /**
617
- * Handles built-in commands via the command registry
204
+ * Handles /copilot-login as a live component.
205
+ * Returns true if handled.
206
+ */
207
+ function handleCopilotLogin(commandParts, options) {
208
+ if (commandParts[0] !== 'copilot-login') {
209
+ return false;
210
+ }
211
+ const { setLiveComponent, setIsToolExecuting, onAddToChatQueue, onCommandComplete, getNextComponentKey, } = options;
212
+ const providerName = commandParts[1]?.trim() || 'GitHub Copilot';
213
+ setIsToolExecuting(true);
214
+ setLiveComponent(React.createElement(CopilotLogin, {
215
+ key: `copilot-login-live-${getNextComponentKey()}`,
216
+ providerName,
217
+ onDone: result => {
218
+ setLiveComponent(null);
219
+ setIsToolExecuting(false);
220
+ if (result.success) {
221
+ onAddToChatQueue(React.createElement(SuccessMessage, {
222
+ key: `copilot-login-done-${getNextComponentKey()}`,
223
+ message: `Logged in. Credential saved for "${providerName}".`,
224
+ hideBox: true,
225
+ }));
226
+ }
227
+ else {
228
+ onAddToChatQueue(React.createElement(ErrorMessage, {
229
+ key: `copilot-login-error-${getNextComponentKey()}`,
230
+ message: result.error ?? 'Login failed.',
231
+ }));
232
+ }
233
+ onCommandComplete?.();
234
+ },
235
+ }));
236
+ return true;
237
+ }
238
+ /**
239
+ * Handles built-in commands via the command registry.
618
240
  */
619
241
  async function handleBuiltInCommand(message, options) {
620
242
  const { onAddToChatQueue, onCommandComplete, getNextComponentKey, messages } = options;
@@ -629,19 +251,15 @@ async function handleBuiltInCommand(message, options) {
629
251
  onCommandComplete?.();
630
252
  return;
631
253
  }
632
- // Handle React element result
633
254
  if (React.isValidElement(result)) {
634
- // Defer adding to chat queue to avoid "Cannot update a component while rendering" error
635
255
  queueMicrotask(() => {
636
256
  onAddToChatQueue(result);
637
257
  });
638
- // Give React time to render before signaling completion
639
258
  setTimeout(() => {
640
259
  onCommandComplete?.();
641
260
  }, DELAY_COMMAND_COMPLETE_MS);
642
261
  return;
643
262
  }
644
- // Handle string result
645
263
  if (typeof result === 'string' && result.trim()) {
646
264
  queueMicrotask(() => {
647
265
  onAddToChatQueue(React.createElement(InfoMessage, {
@@ -650,54 +268,40 @@ async function handleBuiltInCommand(message, options) {
650
268
  hideBox: true,
651
269
  }));
652
270
  });
653
- // Give React time to render before signaling completion
654
271
  setTimeout(() => {
655
272
  onCommandComplete?.();
656
273
  }, DELAY_COMMAND_COMPLETE_MS);
657
274
  return;
658
275
  }
659
- // No output to display, signal completion immediately
660
276
  onCommandComplete?.();
661
277
  }
662
278
  /**
663
- * Handles slash commands (prefixed with /)
279
+ * Handles slash commands (prefixed with /).
664
280
  */
665
281
  async function handleSlashCommand(message, options) {
666
282
  const commandName = message.slice(1).split(/\s+/)[0];
667
- // Try custom command first
668
283
  if (await handleCustomCommand(message, commandName, options)) {
669
284
  return;
670
285
  }
671
- // Try compact command
672
286
  const commandParts = message.slice(1).trim().split(/\s+/);
673
- if (await handleCompactCommand(commandParts, options)) {
287
+ if (await handleCompactCommand(commandParts, options))
674
288
  return;
675
- }
676
- // Try context-max command
677
- if (await handleContextMaxCommand(commandParts, options)) {
289
+ if (await handleContextMaxCommand(commandParts, options))
678
290
  return;
679
- }
680
- // Try /schedule start (enters scheduler mode)
681
- if (await handleScheduleStart(commandParts, options)) {
291
+ if (await handleScheduleStart(commandParts, options))
682
292
  return;
683
- }
684
- // Try /schedule create (creates file + AI assistance)
685
- if (await handleScheduleCreate(commandParts, options)) {
293
+ if (await handleScheduleCreate(commandParts, options))
686
294
  return;
687
- }
688
- // Try /commands create (creates file + AI assistance)
689
- if (await handleCommandCreate(commandParts, options)) {
295
+ if (await handleCommandCreate(commandParts, options))
690
296
  return;
691
- }
692
- // Try special command
693
- if (await handleSpecialCommand(commandName, options)) {
297
+ if (await handleSpecialCommand(commandName, options))
694
298
  return;
695
- }
696
- // Try checkpoint load
697
- if (await handleCheckpointLoad(commandParts, options)) {
299
+ if (await handleCheckpointLoad(commandParts, options))
300
+ return;
301
+ if (await handleResumeCommand(commandParts, options))
302
+ return;
303
+ if (handleCopilotLogin(commandParts, options))
698
304
  return;
699
- }
700
- // Fall back to built-in command
701
305
  await handleBuiltInCommand(message, options);
702
306
  }
703
307
  /**
@@ -706,22 +310,18 @@ async function handleSlashCommand(message, options) {
706
310
  */
707
311
  export async function handleMessageSubmission(message, options) {
708
312
  const parsedInput = parseInput(message);
709
- // Handle bash commands (prefixed with !)
710
313
  if (parsedInput.isBashCommand && parsedInput.bashCommand) {
711
314
  await handleBashCommand(parsedInput.bashCommand, options);
712
315
  return;
713
316
  }
714
- // Handle slash commands (prefixed with /)
715
317
  if (message.startsWith('/')) {
716
318
  await handleSlashCommand(message, options);
717
319
  return;
718
320
  }
719
- // Regular chat message - process with AI
720
321
  await options.onHandleChatMessage(message);
721
322
  }
722
323
  export function createClearMessagesHandler(setMessages, client) {
723
324
  return async () => {
724
- // Clear message history and client context
725
325
  setMessages([]);
726
326
  if (client) {
727
327
  await client.clearContext();