@gguf/coder 0.3.0 → 0.3.1

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 (414) hide show
  1. package/.editorconfig +16 -0
  2. package/.env.example +63 -0
  3. package/.gitattributes +1 -0
  4. package/.semgrepignore +19 -0
  5. package/coder-dummy-file.ts +52 -0
  6. package/coder.config.example.json +59 -0
  7. package/coder.config.json +13 -0
  8. package/color_picker.html +36 -0
  9. package/package.json +2 -14
  10. package/scripts/extract-changelog.js +73 -0
  11. package/scripts/fetch-models.js +143 -0
  12. package/scripts/test.sh +40 -0
  13. package/scripts/update-homebrew-formula.sh +125 -0
  14. package/scripts/update-nix-version.sh +157 -0
  15. package/source/ai-sdk-client/AISDKClient.spec.ts +117 -0
  16. package/source/ai-sdk-client/AISDKClient.ts +155 -0
  17. package/source/ai-sdk-client/chat/chat-handler.spec.ts +121 -0
  18. package/source/ai-sdk-client/chat/chat-handler.ts +276 -0
  19. package/source/ai-sdk-client/chat/streaming-handler.spec.ts +173 -0
  20. package/source/ai-sdk-client/chat/streaming-handler.ts +110 -0
  21. package/source/ai-sdk-client/chat/tool-processor.spec.ts +92 -0
  22. package/source/ai-sdk-client/chat/tool-processor.ts +70 -0
  23. package/source/ai-sdk-client/converters/message-converter.spec.ts +220 -0
  24. package/source/ai-sdk-client/converters/message-converter.ts +113 -0
  25. package/source/ai-sdk-client/converters/tool-converter.spec.ts +90 -0
  26. package/source/ai-sdk-client/converters/tool-converter.ts +46 -0
  27. package/source/ai-sdk-client/error-handling/error-extractor.spec.ts +55 -0
  28. package/source/ai-sdk-client/error-handling/error-extractor.ts +15 -0
  29. package/source/ai-sdk-client/error-handling/error-parser.spec.ts +169 -0
  30. package/source/ai-sdk-client/error-handling/error-parser.ts +161 -0
  31. package/source/ai-sdk-client/index.ts +7 -0
  32. package/source/ai-sdk-client/providers/provider-factory.spec.ts +71 -0
  33. package/source/ai-sdk-client/providers/provider-factory.ts +41 -0
  34. package/source/ai-sdk-client/types.ts +9 -0
  35. package/source/ai-sdk-client-empty-message.spec.ts +141 -0
  36. package/source/ai-sdk-client-error-handling.spec.ts +186 -0
  37. package/source/ai-sdk-client-maxretries.spec.ts +114 -0
  38. package/source/ai-sdk-client-preparestep.spec.ts +279 -0
  39. package/source/app/App.spec.tsx +32 -0
  40. package/source/app/App.tsx +480 -0
  41. package/source/app/components/AppContainer.spec.tsx +96 -0
  42. package/source/app/components/AppContainer.tsx +56 -0
  43. package/source/app/components/ChatInterface.spec.tsx +163 -0
  44. package/source/app/components/ChatInterface.tsx +144 -0
  45. package/source/app/components/ModalSelectors.spec.tsx +141 -0
  46. package/source/app/components/ModalSelectors.tsx +135 -0
  47. package/source/app/helpers.spec.ts +97 -0
  48. package/source/app/helpers.ts +63 -0
  49. package/source/app/index.ts +4 -0
  50. package/source/app/types.ts +39 -0
  51. package/source/app/utils/appUtils.ts +294 -0
  52. package/source/app/utils/conversationState.ts +310 -0
  53. package/source/app.spec.tsx +244 -0
  54. package/source/cli.spec.ts +73 -0
  55. package/source/cli.tsx +51 -0
  56. package/source/client-factory.spec.ts +48 -0
  57. package/source/client-factory.ts +178 -0
  58. package/source/command-parser.spec.ts +127 -0
  59. package/source/command-parser.ts +36 -0
  60. package/source/commands/checkpoint.spec.tsx +277 -0
  61. package/source/commands/checkpoint.tsx +366 -0
  62. package/source/commands/clear.tsx +22 -0
  63. package/source/commands/custom-commands.tsx +121 -0
  64. package/source/commands/exit.ts +21 -0
  65. package/source/commands/export.spec.tsx +131 -0
  66. package/source/commands/export.tsx +79 -0
  67. package/source/commands/help.tsx +120 -0
  68. package/source/commands/index.ts +17 -0
  69. package/source/commands/init.tsx +339 -0
  70. package/source/commands/lsp-command.spec.tsx +281 -0
  71. package/source/commands/lsp.tsx +120 -0
  72. package/source/commands/mcp-command.spec.tsx +313 -0
  73. package/source/commands/mcp.tsx +162 -0
  74. package/source/commands/model-database.spec.tsx +758 -0
  75. package/source/commands/model-database.tsx +418 -0
  76. package/source/commands/model.ts +12 -0
  77. package/source/commands/provider.ts +12 -0
  78. package/source/commands/setup-config.tsx +16 -0
  79. package/source/commands/simple-commands.spec.tsx +175 -0
  80. package/source/commands/status.ts +12 -0
  81. package/source/commands/theme.ts +12 -0
  82. package/source/commands/update.spec.tsx +261 -0
  83. package/source/commands/update.tsx +201 -0
  84. package/source/commands/usage.spec.tsx +495 -0
  85. package/source/commands/usage.tsx +100 -0
  86. package/source/commands.spec.ts +436 -0
  87. package/source/commands.ts +83 -0
  88. package/source/components/assistant-message.spec.tsx +796 -0
  89. package/source/components/assistant-message.tsx +34 -0
  90. package/source/components/bash-execution-indicator.tsx +21 -0
  91. package/source/components/cancelling-indicator.tsx +16 -0
  92. package/source/components/chat-queue.spec.tsx +83 -0
  93. package/source/components/chat-queue.tsx +36 -0
  94. package/source/components/checkpoint-display.spec.tsx +219 -0
  95. package/source/components/checkpoint-display.tsx +126 -0
  96. package/source/components/checkpoint-selector.spec.tsx +173 -0
  97. package/source/components/checkpoint-selector.tsx +173 -0
  98. package/source/components/development-mode-indicator.spec.tsx +268 -0
  99. package/source/components/development-mode-indicator.tsx +38 -0
  100. package/source/components/message-box.spec.tsx +427 -0
  101. package/source/components/message-box.tsx +87 -0
  102. package/source/components/model-selector.tsx +132 -0
  103. package/source/components/provider-selector.tsx +75 -0
  104. package/source/components/random-spinner.tsx +19 -0
  105. package/source/components/security-disclaimer.tsx +73 -0
  106. package/source/components/status-connection-display.spec.tsx +133 -0
  107. package/source/components/status.tsx +267 -0
  108. package/source/components/theme-selector.tsx +126 -0
  109. package/source/components/tool-confirmation.tsx +190 -0
  110. package/source/components/tool-execution-indicator.tsx +33 -0
  111. package/source/components/tool-message.tsx +85 -0
  112. package/source/components/ui/titled-box.spec.tsx +207 -0
  113. package/source/components/ui/titled-box.tsx +57 -0
  114. package/source/components/usage/progress-bar.spec.tsx +398 -0
  115. package/source/components/usage/progress-bar.tsx +30 -0
  116. package/source/components/usage/usage-display.spec.tsx +780 -0
  117. package/source/components/usage/usage-display.tsx +291 -0
  118. package/source/components/user-input.spec.tsx +327 -0
  119. package/source/components/user-input.tsx +533 -0
  120. package/source/components/user-message.spec.tsx +230 -0
  121. package/source/components/user-message.tsx +84 -0
  122. package/source/components/welcome-message.tsx +76 -0
  123. package/source/config/env-substitution.ts +65 -0
  124. package/source/config/index.spec.ts +171 -0
  125. package/source/config/index.ts +154 -0
  126. package/source/config/paths.spec.ts +241 -0
  127. package/source/config/paths.ts +55 -0
  128. package/source/config/preferences.ts +51 -0
  129. package/source/config/themes.ts +315 -0
  130. package/source/constants.ts +130 -0
  131. package/source/context/mode-context.spec.ts +79 -0
  132. package/source/context/mode-context.ts +24 -0
  133. package/source/custom-commands/executor.spec.ts +142 -0
  134. package/source/custom-commands/executor.ts +64 -0
  135. package/source/custom-commands/loader.spec.ts +314 -0
  136. package/source/custom-commands/loader.ts +153 -0
  137. package/source/custom-commands/parser.ts +196 -0
  138. package/source/hooks/chat-handler/conversation/conversation-loop.spec.ts +39 -0
  139. package/source/hooks/chat-handler/conversation/conversation-loop.tsx +511 -0
  140. package/source/hooks/chat-handler/conversation/tool-executor.spec.ts +50 -0
  141. package/source/hooks/chat-handler/conversation/tool-executor.tsx +109 -0
  142. package/source/hooks/chat-handler/index.ts +12 -0
  143. package/source/hooks/chat-handler/state/streaming-state.spec.ts +26 -0
  144. package/source/hooks/chat-handler/state/streaming-state.ts +19 -0
  145. package/source/hooks/chat-handler/types.ts +38 -0
  146. package/source/hooks/chat-handler/useChatHandler.spec.tsx +321 -0
  147. package/source/hooks/chat-handler/useChatHandler.tsx +194 -0
  148. package/source/hooks/chat-handler/utils/context-checker.spec.ts +60 -0
  149. package/source/hooks/chat-handler/utils/context-checker.tsx +73 -0
  150. package/source/hooks/chat-handler/utils/message-helpers.spec.ts +42 -0
  151. package/source/hooks/chat-handler/utils/message-helpers.tsx +36 -0
  152. package/source/hooks/chat-handler/utils/tool-filters.spec.ts +109 -0
  153. package/source/hooks/chat-handler/utils/tool-filters.ts +64 -0
  154. package/source/hooks/useAppHandlers.tsx +291 -0
  155. package/source/hooks/useAppInitialization.tsx +422 -0
  156. package/source/hooks/useAppState.tsx +311 -0
  157. package/source/hooks/useDirectoryTrust.tsx +98 -0
  158. package/source/hooks/useInputState.ts +414 -0
  159. package/source/hooks/useModeHandlers.tsx +302 -0
  160. package/source/hooks/useNonInteractiveMode.ts +140 -0
  161. package/source/hooks/useTerminalWidth.tsx +81 -0
  162. package/source/hooks/useTheme.ts +18 -0
  163. package/source/hooks/useToolHandler.tsx +349 -0
  164. package/source/hooks/useUIState.ts +61 -0
  165. package/source/init/agents-template-generator.ts +421 -0
  166. package/source/init/existing-rules-extractor.ts +319 -0
  167. package/source/init/file-scanner.spec.ts +227 -0
  168. package/source/init/file-scanner.ts +238 -0
  169. package/source/init/framework-detector.ts +382 -0
  170. package/source/init/language-detector.ts +269 -0
  171. package/source/init/project-analyzer.spec.ts +231 -0
  172. package/source/init/project-analyzer.ts +458 -0
  173. package/source/lsp/index.ts +31 -0
  174. package/source/lsp/lsp-client.spec.ts +508 -0
  175. package/source/lsp/lsp-client.ts +487 -0
  176. package/source/lsp/lsp-manager.spec.ts +477 -0
  177. package/source/lsp/lsp-manager.ts +419 -0
  178. package/source/lsp/protocol.spec.ts +502 -0
  179. package/source/lsp/protocol.ts +360 -0
  180. package/source/lsp/server-discovery.spec.ts +654 -0
  181. package/source/lsp/server-discovery.ts +515 -0
  182. package/source/markdown-parser/html-entities.spec.ts +88 -0
  183. package/source/markdown-parser/html-entities.ts +45 -0
  184. package/source/markdown-parser/index.spec.ts +281 -0
  185. package/source/markdown-parser/index.ts +126 -0
  186. package/source/markdown-parser/table-parser.spec.ts +133 -0
  187. package/source/markdown-parser/table-parser.ts +114 -0
  188. package/source/markdown-parser/utils.spec.ts +70 -0
  189. package/source/markdown-parser/utils.ts +13 -0
  190. package/source/mcp/mcp-client.spec.ts +81 -0
  191. package/source/mcp/mcp-client.ts +625 -0
  192. package/source/mcp/transport-factory.spec.ts +406 -0
  193. package/source/mcp/transport-factory.ts +312 -0
  194. package/source/message-handler.ts +67 -0
  195. package/source/model-database/database-engine.spec.ts +494 -0
  196. package/source/model-database/database-engine.ts +50 -0
  197. package/source/model-database/model-database.spec.ts +363 -0
  198. package/source/model-database/model-database.ts +91 -0
  199. package/source/model-database/model-engine.spec.ts +447 -0
  200. package/source/model-database/model-engine.ts +65 -0
  201. package/source/model-database/model-fetcher.spec.ts +583 -0
  202. package/source/model-database/model-fetcher.ts +330 -0
  203. package/source/models/index.ts +1 -0
  204. package/source/models/models-cache.spec.ts +214 -0
  205. package/source/models/models-cache.ts +78 -0
  206. package/source/models/models-dev-client.spec.ts +379 -0
  207. package/source/models/models-dev-client.ts +329 -0
  208. package/source/models/models-types.ts +68 -0
  209. package/source/prompt-history.ts +155 -0
  210. package/source/security/command-injection.spec.ts +240 -0
  211. package/source/services/checkpoint-manager.spec.ts +523 -0
  212. package/source/services/checkpoint-manager.ts +466 -0
  213. package/source/services/file-snapshot.spec.ts +569 -0
  214. package/source/services/file-snapshot.ts +220 -0
  215. package/source/test-utils/render-with-theme.tsx +48 -0
  216. package/source/tokenization/index.ts +1 -0
  217. package/source/tokenization/tokenizer-factory.spec.ts +170 -0
  218. package/source/tokenization/tokenizer-factory.ts +125 -0
  219. package/source/tokenization/tokenizers/anthropic-tokenizer.spec.ts +200 -0
  220. package/source/tokenization/tokenizers/anthropic-tokenizer.ts +43 -0
  221. package/source/tokenization/tokenizers/fallback-tokenizer.spec.ts +236 -0
  222. package/source/tokenization/tokenizers/fallback-tokenizer.ts +26 -0
  223. package/source/tokenization/tokenizers/llama-tokenizer.spec.ts +224 -0
  224. package/source/tokenization/tokenizers/llama-tokenizer.ts +41 -0
  225. package/source/tokenization/tokenizers/openai-tokenizer.spec.ts +184 -0
  226. package/source/tokenization/tokenizers/openai-tokenizer.ts +57 -0
  227. package/source/tool-calling/index.ts +5 -0
  228. package/source/tool-calling/json-parser.spec.ts +639 -0
  229. package/source/tool-calling/json-parser.ts +247 -0
  230. package/source/tool-calling/tool-parser.spec.ts +395 -0
  231. package/source/tool-calling/tool-parser.ts +120 -0
  232. package/source/tool-calling/xml-parser.spec.ts +662 -0
  233. package/source/tool-calling/xml-parser.ts +289 -0
  234. package/source/tools/execute-bash.spec.tsx +353 -0
  235. package/source/tools/execute-bash.tsx +219 -0
  236. package/source/tools/execute-function.spec.ts +130 -0
  237. package/source/tools/fetch-url.spec.tsx +342 -0
  238. package/source/tools/fetch-url.tsx +172 -0
  239. package/source/tools/find-files.spec.tsx +924 -0
  240. package/source/tools/find-files.tsx +293 -0
  241. package/source/tools/index.ts +102 -0
  242. package/source/tools/lsp-get-diagnostics.tsx +192 -0
  243. package/source/tools/needs-approval.spec.ts +282 -0
  244. package/source/tools/read-file.spec.tsx +801 -0
  245. package/source/tools/read-file.tsx +387 -0
  246. package/source/tools/search-file-contents.spec.tsx +1273 -0
  247. package/source/tools/search-file-contents.tsx +293 -0
  248. package/source/tools/string-replace.spec.tsx +730 -0
  249. package/source/tools/string-replace.tsx +548 -0
  250. package/source/tools/tool-manager.ts +210 -0
  251. package/source/tools/tool-registry.spec.ts +415 -0
  252. package/source/tools/tool-registry.ts +228 -0
  253. package/source/tools/web-search.tsx +223 -0
  254. package/source/tools/write-file.spec.tsx +559 -0
  255. package/source/tools/write-file.tsx +228 -0
  256. package/source/types/app.ts +37 -0
  257. package/source/types/checkpoint.ts +48 -0
  258. package/source/types/commands.ts +46 -0
  259. package/source/types/components.ts +27 -0
  260. package/source/types/config.ts +103 -0
  261. package/source/types/core-connection-status.spec.ts +67 -0
  262. package/source/types/core.ts +181 -0
  263. package/source/types/hooks.ts +50 -0
  264. package/source/types/index.ts +12 -0
  265. package/source/types/markdown-parser.ts +11 -0
  266. package/source/types/mcp.ts +52 -0
  267. package/source/types/system.ts +16 -0
  268. package/source/types/tokenization.ts +41 -0
  269. package/source/types/ui.ts +40 -0
  270. package/source/types/usage.ts +58 -0
  271. package/source/types/utils.ts +16 -0
  272. package/source/usage/calculator.spec.ts +385 -0
  273. package/source/usage/calculator.ts +104 -0
  274. package/source/usage/storage.spec.ts +703 -0
  275. package/source/usage/storage.ts +238 -0
  276. package/source/usage/tracker.spec.ts +456 -0
  277. package/source/usage/tracker.ts +102 -0
  278. package/source/utils/atomic-deletion.spec.ts +194 -0
  279. package/source/utils/atomic-deletion.ts +127 -0
  280. package/source/utils/bounded-map.spec.ts +300 -0
  281. package/source/utils/bounded-map.ts +193 -0
  282. package/source/utils/checkpoint-utils.spec.ts +222 -0
  283. package/source/utils/checkpoint-utils.ts +92 -0
  284. package/source/utils/error-formatter.spec.ts +169 -0
  285. package/source/utils/error-formatter.ts +194 -0
  286. package/source/utils/file-autocomplete.spec.ts +173 -0
  287. package/source/utils/file-autocomplete.ts +196 -0
  288. package/source/utils/file-cache.spec.ts +309 -0
  289. package/source/utils/file-cache.ts +195 -0
  290. package/source/utils/file-content-loader.spec.ts +180 -0
  291. package/source/utils/file-content-loader.ts +179 -0
  292. package/source/utils/file-mention-handler.spec.ts +261 -0
  293. package/source/utils/file-mention-handler.ts +84 -0
  294. package/source/utils/file-mention-parser.spec.ts +182 -0
  295. package/source/utils/file-mention-parser.ts +170 -0
  296. package/source/utils/fuzzy-matching.spec.ts +149 -0
  297. package/source/utils/fuzzy-matching.ts +146 -0
  298. package/source/utils/indentation-normalizer.spec.ts +216 -0
  299. package/source/utils/indentation-normalizer.ts +76 -0
  300. package/source/utils/installation-detector.spec.ts +178 -0
  301. package/source/utils/installation-detector.ts +153 -0
  302. package/source/utils/logging/config.spec.ts +311 -0
  303. package/source/utils/logging/config.ts +210 -0
  304. package/source/utils/logging/console-facade.spec.ts +184 -0
  305. package/source/utils/logging/console-facade.ts +384 -0
  306. package/source/utils/logging/correlation.spec.ts +679 -0
  307. package/source/utils/logging/correlation.ts +474 -0
  308. package/source/utils/logging/formatters.spec.ts +464 -0
  309. package/source/utils/logging/formatters.ts +207 -0
  310. package/source/utils/logging/health-monitor/alerts/alert-manager.spec.ts +93 -0
  311. package/source/utils/logging/health-monitor/alerts/alert-manager.ts +79 -0
  312. package/source/utils/logging/health-monitor/checks/configuration-check.spec.ts +56 -0
  313. package/source/utils/logging/health-monitor/checks/configuration-check.ts +43 -0
  314. package/source/utils/logging/health-monitor/checks/logging-check.spec.ts +56 -0
  315. package/source/utils/logging/health-monitor/checks/logging-check.ts +58 -0
  316. package/source/utils/logging/health-monitor/checks/memory-check.spec.ts +100 -0
  317. package/source/utils/logging/health-monitor/checks/memory-check.ts +78 -0
  318. package/source/utils/logging/health-monitor/checks/performance-check.spec.ts +56 -0
  319. package/source/utils/logging/health-monitor/checks/performance-check.ts +56 -0
  320. package/source/utils/logging/health-monitor/checks/request-check.spec.ts +56 -0
  321. package/source/utils/logging/health-monitor/checks/request-check.ts +76 -0
  322. package/source/utils/logging/health-monitor/core/health-check-runner.spec.ts +70 -0
  323. package/source/utils/logging/health-monitor/core/health-check-runner.ts +138 -0
  324. package/source/utils/logging/health-monitor/core/health-monitor.spec.ts +58 -0
  325. package/source/utils/logging/health-monitor/core/health-monitor.ts +344 -0
  326. package/source/utils/logging/health-monitor/core/scoring.spec.ts +65 -0
  327. package/source/utils/logging/health-monitor/core/scoring.ts +91 -0
  328. package/source/utils/logging/health-monitor/index.ts +15 -0
  329. package/source/utils/logging/health-monitor/instances.ts +48 -0
  330. package/source/utils/logging/health-monitor/middleware/http-middleware.spec.ts +141 -0
  331. package/source/utils/logging/health-monitor/middleware/http-middleware.ts +75 -0
  332. package/source/utils/logging/health-monitor/types.ts +126 -0
  333. package/source/utils/logging/index.spec.ts +284 -0
  334. package/source/utils/logging/index.ts +236 -0
  335. package/source/utils/logging/integration.spec.ts +441 -0
  336. package/source/utils/logging/log-method-factory.spec.ts +573 -0
  337. package/source/utils/logging/log-method-factory.ts +233 -0
  338. package/source/utils/logging/log-query/aggregation/aggregator.spec.ts +277 -0
  339. package/source/utils/logging/log-query/aggregation/aggregator.ts +159 -0
  340. package/source/utils/logging/log-query/aggregation/facet-generator.spec.ts +159 -0
  341. package/source/utils/logging/log-query/aggregation/facet-generator.ts +47 -0
  342. package/source/utils/logging/log-query/index.ts +23 -0
  343. package/source/utils/logging/log-query/query/filter-predicates.spec.ts +247 -0
  344. package/source/utils/logging/log-query/query/filter-predicates.ts +154 -0
  345. package/source/utils/logging/log-query/query/query-builder.spec.ts +182 -0
  346. package/source/utils/logging/log-query/query/query-builder.ts +151 -0
  347. package/source/utils/logging/log-query/query/query-engine.spec.ts +214 -0
  348. package/source/utils/logging/log-query/query/query-engine.ts +45 -0
  349. package/source/utils/logging/log-query/storage/circular-buffer.spec.ts +143 -0
  350. package/source/utils/logging/log-query/storage/circular-buffer.ts +75 -0
  351. package/source/utils/logging/log-query/storage/index-manager.spec.ts +150 -0
  352. package/source/utils/logging/log-query/storage/index-manager.ts +71 -0
  353. package/source/utils/logging/log-query/storage/log-storage.spec.ts +257 -0
  354. package/source/utils/logging/log-query/storage/log-storage.ts +80 -0
  355. package/source/utils/logging/log-query/types.ts +163 -0
  356. package/source/utils/logging/log-query/utils/helpers.spec.ts +263 -0
  357. package/source/utils/logging/log-query/utils/helpers.ts +72 -0
  358. package/source/utils/logging/log-query/utils/sorting.spec.ts +182 -0
  359. package/source/utils/logging/log-query/utils/sorting.ts +61 -0
  360. package/source/utils/logging/logger-provider.spec.ts +262 -0
  361. package/source/utils/logging/logger-provider.ts +362 -0
  362. package/source/utils/logging/performance.spec.ts +209 -0
  363. package/source/utils/logging/performance.ts +757 -0
  364. package/source/utils/logging/pino-logger.spec.ts +425 -0
  365. package/source/utils/logging/pino-logger.ts +514 -0
  366. package/source/utils/logging/redaction.spec.ts +490 -0
  367. package/source/utils/logging/redaction.ts +267 -0
  368. package/source/utils/logging/request-tracker.spec.ts +1198 -0
  369. package/source/utils/logging/request-tracker.ts +803 -0
  370. package/source/utils/logging/transports.spec.ts +505 -0
  371. package/source/utils/logging/transports.ts +305 -0
  372. package/source/utils/logging/types.ts +216 -0
  373. package/source/utils/message-builder.spec.ts +179 -0
  374. package/source/utils/message-builder.ts +101 -0
  375. package/source/utils/message-queue.tsx +486 -0
  376. package/source/utils/paste-detection.spec.ts +69 -0
  377. package/source/utils/paste-detection.ts +124 -0
  378. package/source/utils/paste-roundtrip.spec.ts +442 -0
  379. package/source/utils/paste-utils.spec.ts +128 -0
  380. package/source/utils/paste-utils.ts +52 -0
  381. package/source/utils/programming-language-helper.spec.ts +74 -0
  382. package/source/utils/programming-language-helper.ts +32 -0
  383. package/source/utils/prompt-assembly.spec.ts +221 -0
  384. package/source/utils/prompt-processor.ts +173 -0
  385. package/source/utils/tool-args-parser.spec.ts +136 -0
  386. package/source/utils/tool-args-parser.ts +54 -0
  387. package/source/utils/tool-cancellation.spec.ts +230 -0
  388. package/source/utils/tool-cancellation.ts +28 -0
  389. package/source/utils/tool-result-display.spec.tsx +469 -0
  390. package/source/utils/tool-result-display.tsx +90 -0
  391. package/source/utils/update-checker.spec.ts +383 -0
  392. package/source/utils/update-checker.ts +183 -0
  393. package/source/wizard/config-wizard.spec.tsx +103 -0
  394. package/source/wizard/config-wizard.tsx +382 -0
  395. package/source/wizard/steps/location-step.spec.tsx +186 -0
  396. package/source/wizard/steps/location-step.tsx +147 -0
  397. package/source/wizard/steps/mcp-step.spec.tsx +607 -0
  398. package/source/wizard/steps/mcp-step.tsx +632 -0
  399. package/source/wizard/steps/provider-step.spec.tsx +342 -0
  400. package/source/wizard/steps/provider-step.tsx +957 -0
  401. package/source/wizard/steps/summary-step.spec.tsx +749 -0
  402. package/source/wizard/steps/summary-step.tsx +228 -0
  403. package/source/wizard/templates/mcp-templates.spec.ts +613 -0
  404. package/source/wizard/templates/mcp-templates.ts +570 -0
  405. package/source/wizard/templates/provider-templates.spec.ts +152 -0
  406. package/source/wizard/templates/provider-templates.ts +485 -0
  407. package/source/wizard/utils/fetch-cloud-models.spec.ts +428 -0
  408. package/source/wizard/utils/fetch-cloud-models.ts +223 -0
  409. package/source/wizard/utils/fetch-local-models.spec.ts +297 -0
  410. package/source/wizard/utils/fetch-local-models.ts +192 -0
  411. package/source/wizard/validation-array.spec.ts +264 -0
  412. package/source/wizard/validation.spec.ts +373 -0
  413. package/source/wizard/validation.ts +232 -0
  414. package/source/app/prompts/main-prompt.md +0 -122
@@ -0,0 +1,64 @@
1
+ import {substituteTemplateVariables} from '@/custom-commands/parser';
2
+ import type {CustomCommand} from '@/types/index';
3
+
4
+ export class CustomCommandExecutor {
5
+ /**
6
+ * Execute a custom command with given arguments
7
+ */
8
+ execute(command: CustomCommand, args: string[]): string {
9
+ // Build template variables from parameters and arguments
10
+ const variables: Record<string, string> = {};
11
+
12
+ if (command.metadata.parameters && command.metadata.parameters.length > 0) {
13
+ // Map arguments to parameters
14
+ command.metadata.parameters.forEach((param: string, index: number) => {
15
+ variables[param] = args[index] || '';
16
+ });
17
+
18
+ // Also provide all args as a single variable
19
+ variables['args'] = args.join(' ');
20
+ }
21
+
22
+ // Add some default context variables
23
+ variables['cwd'] = process.cwd();
24
+ variables['command'] = command.fullName;
25
+
26
+ // Substitute variables in the command content
27
+ const promptContent = substituteTemplateVariables(
28
+ command.content,
29
+ variables,
30
+ );
31
+
32
+ // Add a note about this being a custom command that can be improved
33
+ const fullPrompt = `[Executing custom command: /${command.fullName}]\n\n${promptContent}\n\n[Note: If this custom command could be improved, please provide feedback on how to enhance it.]`;
34
+
35
+ // Execute the prompt as if the user typed it
36
+ return fullPrompt;
37
+ }
38
+
39
+ /**
40
+ * Format command help text
41
+ */
42
+ formatHelp(command: CustomCommand): string {
43
+ const parts: string[] = [`/${command.fullName}`];
44
+
45
+ if (command.metadata.parameters && command.metadata.parameters.length > 0) {
46
+ parts.push(
47
+ command.metadata.parameters.map((p: string) => `<${p}>`).join(' '),
48
+ );
49
+ }
50
+
51
+ if (command.metadata.description) {
52
+ parts.push(`- ${command.metadata.description}`);
53
+ }
54
+
55
+ if (command.metadata.aliases && command.metadata.aliases.length > 0) {
56
+ const aliasNames = command.metadata.aliases.map((a: string) =>
57
+ command.namespace ? `${command.namespace}:${a}` : a,
58
+ );
59
+ parts.push(`(aliases: ${aliasNames.join(', ')})`);
60
+ }
61
+
62
+ return parts.join(' ');
63
+ }
64
+ }
@@ -0,0 +1,314 @@
1
+ import { writeFileSync, rmSync, existsSync, mkdirSync } from 'fs';
2
+ import { tmpdir } from 'os';
3
+ import { join } from 'path';
4
+ import test from 'ava';
5
+ import { CustomCommandLoader } from './loader';
6
+
7
+ // Helper to create a valid custom command file
8
+ function createCommandFile(path: string, content: string) {
9
+ const fullContent = `---
10
+ description: ${content}
11
+ ---
12
+
13
+ ${content}`;
14
+ writeFileSync(path, fullContent, 'utf-8');
15
+ }
16
+
17
+ // Helper to create a unique test directory for each test
18
+ function createTestDir(testName: string): string {
19
+ const dir = join(tmpdir(), `coder-cmd-test-${Date.now()}-${testName}`);
20
+ mkdirSync(dir, {recursive: true});
21
+ return dir;
22
+ }
23
+
24
+ // Helper to clean up test directory
25
+ function cleanupTestDir(dir: string) {
26
+ if (existsSync(dir)) {
27
+ rmSync(dir, {recursive: true, force: true});
28
+ }
29
+ }
30
+
31
+ test('CustomCommandLoader - constructor initializes with project root', t => {
32
+ const testDir = createTestDir('constructor');
33
+ t.teardown(() => cleanupTestDir(testDir));
34
+
35
+ const loader = new CustomCommandLoader(testDir);
36
+ t.truthy(loader);
37
+ });
38
+
39
+ test('CustomCommandLoader - constructor uses cwd when no path provided', t => {
40
+ const loader = new CustomCommandLoader();
41
+ t.truthy(loader);
42
+ });
43
+
44
+ test('CustomCommandLoader - hasCustomCommands returns false when no commands directory', t => {
45
+ const testDir = createTestDir('has-no-commands');
46
+ t.teardown(() => cleanupTestDir(testDir));
47
+
48
+ const loader = new CustomCommandLoader(testDir);
49
+ t.false(loader.hasCustomCommands());
50
+ });
51
+
52
+ test('CustomCommandLoader - hasCustomCommands returns true when commands directory exists', t => {
53
+ const testDir = createTestDir('has-commands');
54
+ t.teardown(() => cleanupTestDir(testDir));
55
+
56
+ const commandsDir = join(testDir, '.coder', 'commands');
57
+ mkdirSync(commandsDir, {recursive: true});
58
+
59
+ const loader = new CustomCommandLoader(testDir);
60
+ t.true(loader.hasCustomCommands());
61
+ });
62
+
63
+ test('CustomCommandLoader - getCommandsDirectory returns correct path', t => {
64
+ const testDir = createTestDir('get-dir');
65
+ t.teardown(() => cleanupTestDir(testDir));
66
+
67
+ const loader = new CustomCommandLoader(testDir);
68
+ const expectedPath = join(testDir, '.coder', 'commands');
69
+ t.is(loader.getCommandsDirectory(), expectedPath);
70
+ });
71
+
72
+ test('CustomCommandLoader - loadCommands with no commands directory', t => {
73
+ const testDir = createTestDir('no-dir');
74
+ t.teardown(() => cleanupTestDir(testDir));
75
+
76
+ const loader = new CustomCommandLoader(testDir);
77
+ t.notThrows(() => loader.loadCommands());
78
+
79
+ const commands = loader.getAllCommands();
80
+ t.is(commands.length, 0);
81
+ });
82
+
83
+ test('CustomCommandLoader - loadCommands loads single command', t => {
84
+ const testDir = createTestDir('single-cmd');
85
+ t.teardown(() => cleanupTestDir(testDir));
86
+
87
+ const commandsDir = join(testDir, '.coder', 'commands');
88
+ mkdirSync(commandsDir, {recursive: true});
89
+ createCommandFile(join(commandsDir, 'test.md'), 'A test command');
90
+
91
+ const loader = new CustomCommandLoader(testDir);
92
+ loader.loadCommands();
93
+
94
+ const commands = loader.getAllCommands();
95
+ t.is(commands.length, 1);
96
+ t.is(commands[0].name, 'test');
97
+ });
98
+
99
+ test('CustomCommandLoader - loadCommands loads multiple commands', t => {
100
+ const testDir = createTestDir('multi-cmd');
101
+ t.teardown(() => cleanupTestDir(testDir));
102
+
103
+ const commandsDir = join(testDir, '.coder', 'commands');
104
+ mkdirSync(commandsDir, {recursive: true});
105
+ createCommandFile(join(commandsDir, 'cmd1.md'), 'Command 1');
106
+ createCommandFile(join(commandsDir, 'cmd2.md'), 'Command 2');
107
+ createCommandFile(join(commandsDir, 'cmd3.md'), 'Command 3');
108
+
109
+ const loader = new CustomCommandLoader(testDir);
110
+ loader.loadCommands();
111
+
112
+ const commands = loader.getAllCommands();
113
+ t.is(commands.length, 3);
114
+ });
115
+
116
+ test('CustomCommandLoader - loadCommands loads namespaced commands', t => {
117
+ const testDir = createTestDir('namespace');
118
+ t.teardown(() => cleanupTestDir(testDir));
119
+
120
+ const commandsDir = join(testDir, '.coder', 'commands');
121
+ const namespaceDir = join(commandsDir, 'git');
122
+ mkdirSync(namespaceDir, {recursive: true});
123
+ createCommandFile(join(namespaceDir, 'commit.md'), 'Git commit command');
124
+
125
+ const loader = new CustomCommandLoader(testDir);
126
+ loader.loadCommands();
127
+
128
+ const command = loader.getCommand('git:commit');
129
+ t.truthy(command);
130
+ t.is(command?.name, 'commit');
131
+ t.is(command?.namespace, 'git');
132
+ t.is(command?.fullName, 'git:commit');
133
+ });
134
+
135
+ test('CustomCommandLoader - getCommand retrieves command by name', t => {
136
+ const testDir = createTestDir('get-cmd');
137
+ t.teardown(() => cleanupTestDir(testDir));
138
+
139
+ const commandsDir = join(testDir, '.coder', 'commands');
140
+ mkdirSync(commandsDir, {recursive: true});
141
+ createCommandFile(join(commandsDir, 'test.md'), 'Test command');
142
+
143
+ const loader = new CustomCommandLoader(testDir);
144
+ loader.loadCommands();
145
+
146
+ const command = loader.getCommand('test');
147
+ t.truthy(command);
148
+ t.is(command?.name, 'test');
149
+ });
150
+
151
+ test('CustomCommandLoader - getCommand returns undefined for non-existent command', t => {
152
+ const testDir = createTestDir('get-nonexistent');
153
+ t.teardown(() => cleanupTestDir(testDir));
154
+
155
+ const loader = new CustomCommandLoader(testDir);
156
+ loader.loadCommands();
157
+
158
+ const command = loader.getCommand('nonexistent');
159
+ t.is(command, undefined);
160
+ });
161
+
162
+ test('CustomCommandLoader - getAllCommands returns array', t => {
163
+ const testDir = createTestDir('get-all');
164
+ t.teardown(() => cleanupTestDir(testDir));
165
+
166
+ const commandsDir = join(testDir, '.coder', 'commands');
167
+ mkdirSync(commandsDir, {recursive: true});
168
+ createCommandFile(join(commandsDir, 'test.md'), 'Test command');
169
+
170
+ const loader = new CustomCommandLoader(testDir);
171
+ loader.loadCommands();
172
+
173
+ const commands = loader.getAllCommands();
174
+ t.true(Array.isArray(commands));
175
+ t.is(commands.length, 1);
176
+ });
177
+
178
+ test('CustomCommandLoader - getSuggestions returns matching commands', t => {
179
+ const testDir = createTestDir('suggestions');
180
+ t.teardown(() => cleanupTestDir(testDir));
181
+
182
+ const commandsDir = join(testDir, '.coder', 'commands');
183
+ mkdirSync(commandsDir, {recursive: true});
184
+ createCommandFile(join(commandsDir, 'test1.md'), 'Test 1');
185
+ createCommandFile(join(commandsDir, 'test2.md'), 'Test 2');
186
+ createCommandFile(join(commandsDir, 'other.md'), 'Other');
187
+
188
+ const loader = new CustomCommandLoader(testDir);
189
+ loader.loadCommands();
190
+
191
+ const suggestions = loader.getSuggestions('test');
192
+
193
+ t.true(suggestions.includes('test1'));
194
+ t.true(suggestions.includes('test2'));
195
+ t.false(suggestions.includes('other'));
196
+ });
197
+
198
+ test('CustomCommandLoader - getSuggestions is case insensitive', t => {
199
+ const testDir = createTestDir('case-insensitive');
200
+ t.teardown(() => cleanupTestDir(testDir));
201
+
202
+ const commandsDir = join(testDir, '.coder', 'commands');
203
+ mkdirSync(commandsDir, {recursive: true});
204
+ createCommandFile(join(commandsDir, 'MyCommand.md'), 'My command');
205
+
206
+ const loader = new CustomCommandLoader(testDir);
207
+ loader.loadCommands();
208
+
209
+ const suggestionsLower = loader.getSuggestions('mycommand');
210
+ const suggestionsUpper = loader.getSuggestions('MYCOMMAND');
211
+
212
+ t.true(suggestionsLower.includes('MyCommand'));
213
+ t.true(suggestionsUpper.includes('MyCommand'));
214
+ });
215
+
216
+ test('CustomCommandLoader - getSuggestions returns empty array when no matches', t => {
217
+ const testDir = createTestDir('no-matches');
218
+ t.teardown(() => cleanupTestDir(testDir));
219
+
220
+ const loader = new CustomCommandLoader(testDir);
221
+ loader.loadCommands();
222
+
223
+ const suggestions = loader.getSuggestions('nonexistent');
224
+ t.deepEqual(suggestions, []);
225
+ });
226
+
227
+ test('CustomCommandLoader - loadCommands clears existing commands', t => {
228
+ const testDir = createTestDir('clears');
229
+ t.teardown(() => cleanupTestDir(testDir));
230
+
231
+ const commandsDir = join(testDir, '.coder', 'commands');
232
+ mkdirSync(commandsDir, {recursive: true});
233
+ createCommandFile(join(commandsDir, 'test.md'), 'Test');
234
+
235
+ const loader = new CustomCommandLoader(testDir);
236
+ loader.loadCommands();
237
+ t.is(loader.getAllCommands().length, 1);
238
+
239
+ // Reload
240
+ loader.loadCommands();
241
+ t.is(loader.getAllCommands().length, 1);
242
+ });
243
+
244
+ test('CustomCommandLoader - loadCommands handles invalid command files gracefully', t => {
245
+ const testDir = createTestDir('invalid');
246
+ t.teardown(() => cleanupTestDir(testDir));
247
+
248
+ const commandsDir = join(testDir, '.coder', 'commands');
249
+ mkdirSync(commandsDir, {recursive: true});
250
+
251
+ // Create invalid file (no frontmatter)
252
+ writeFileSync(join(commandsDir, 'invalid.md'), 'Just content without frontmatter', 'utf-8');
253
+
254
+ // Create valid file
255
+ createCommandFile(join(commandsDir, 'valid.md'), 'Valid command');
256
+
257
+ const loader = new CustomCommandLoader(testDir);
258
+ t.notThrows(() => loader.loadCommands());
259
+
260
+ // Should still load the valid command
261
+ const commands = loader.getAllCommands();
262
+ t.true(commands.some(c => c.name === 'valid'));
263
+ });
264
+
265
+ test('CustomCommandLoader - handles deeply nested namespaces', t => {
266
+ const testDir = createTestDir('nested');
267
+ t.teardown(() => cleanupTestDir(testDir));
268
+
269
+ const commandsDir = join(testDir, '.coder', 'commands');
270
+ const deepDir = join(commandsDir, 'level1', 'level2', 'level3');
271
+ mkdirSync(deepDir, {recursive: true});
272
+ createCommandFile(join(deepDir, 'deep.md'), 'Deep command');
273
+
274
+ const loader = new CustomCommandLoader(testDir);
275
+ loader.loadCommands();
276
+
277
+ const command = loader.getCommand('level1:level2:level3:deep');
278
+ t.truthy(command);
279
+ t.is(command?.fullName, 'level1:level2:level3:deep');
280
+ });
281
+
282
+ test('CustomCommandLoader - ignores non-markdown files', t => {
283
+ const testDir = createTestDir('ignore-non-md');
284
+ t.teardown(() => cleanupTestDir(testDir));
285
+
286
+ const commandsDir = join(testDir, '.coder', 'commands');
287
+ mkdirSync(commandsDir, {recursive: true});
288
+ createCommandFile(join(commandsDir, 'test.md'), 'Test command');
289
+ writeFileSync(join(commandsDir, 'test.txt'), 'Not a command', 'utf-8');
290
+ writeFileSync(join(commandsDir, 'test.js'), 'console.log("test");', 'utf-8');
291
+
292
+ const loader = new CustomCommandLoader(testDir);
293
+ loader.loadCommands();
294
+
295
+ // Should only load the .md file
296
+ t.is(loader.getAllCommands().length, 1);
297
+ });
298
+
299
+ test('CustomCommandLoader - loadCommands clears aliases on reload', t => {
300
+ const testDir = createTestDir('clear-aliases');
301
+ t.teardown(() => cleanupTestDir(testDir));
302
+
303
+ const commandsDir = join(testDir, '.coder', 'commands');
304
+ mkdirSync(commandsDir, {recursive: true});
305
+ createCommandFile(join(commandsDir, 'test.md'), 'Test');
306
+
307
+ const loader = new CustomCommandLoader(testDir);
308
+ loader.loadCommands();
309
+ t.is(loader.getAllCommands().length, 1);
310
+
311
+ // Reload
312
+ loader.loadCommands();
313
+ t.is(loader.getAllCommands().length, 1);
314
+ });
@@ -0,0 +1,153 @@
1
+ import {existsSync, readdirSync, statSync} from 'fs';
2
+ import {basename, join} from 'path';
3
+ import {parseCommandFile} from '@/custom-commands/parser';
4
+ import type {CustomCommand} from '@/types/index';
5
+ import {logError} from '@/utils/message-queue';
6
+
7
+ export class CustomCommandLoader {
8
+ private commands: Map<string, CustomCommand> = new Map();
9
+ private aliases: Map<string, string> = new Map(); // alias -> command name
10
+ private projectRoot: string;
11
+ private commandsDir: string;
12
+
13
+ constructor(projectRoot: string = process.cwd()) {
14
+ this.projectRoot = projectRoot;
15
+ // nosemgrep
16
+ this.commandsDir = join(projectRoot, '.coder', 'commands'); // nosemgrep
17
+ }
18
+
19
+ /**
20
+ * Load all custom commands from the .coder/commands directory
21
+ */
22
+ loadCommands(): void {
23
+ this.commands.clear();
24
+ this.aliases.clear();
25
+
26
+ if (!existsSync(this.commandsDir)) {
27
+ return; // No custom commands directory
28
+ }
29
+
30
+ this.scanDirectory(this.commandsDir);
31
+ }
32
+
33
+ /**
34
+ * Recursively scan directory for .md files
35
+ */
36
+ private scanDirectory(dir: string, namespace?: string): void {
37
+ const entries = readdirSync(dir);
38
+
39
+ for (const entry of entries) {
40
+ const fullPath = join(dir, entry); // nosemgrep
41
+ const stat = statSync(fullPath);
42
+
43
+ if (stat.isDirectory()) {
44
+ // Subdirectory becomes a namespace
45
+ const subNamespace = namespace ? `${namespace}:${entry}` : entry;
46
+ this.scanDirectory(fullPath, subNamespace);
47
+ } else if (entry.endsWith('.md')) {
48
+ // Parse and register command
49
+ this.loadCommand(fullPath, namespace);
50
+ }
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Load a single command file
56
+ */
57
+ private loadCommand(filePath: string, namespace?: string): void {
58
+ try {
59
+ const parsed = parseCommandFile(filePath);
60
+ const commandName = basename(filePath, '.md');
61
+ const fullName = namespace ? `${namespace}:${commandName}` : commandName;
62
+
63
+ const command: CustomCommand = {
64
+ name: commandName,
65
+ path: filePath,
66
+ namespace,
67
+ fullName,
68
+ metadata: parsed.metadata,
69
+ content: parsed.content,
70
+ };
71
+
72
+ // Register main command
73
+ this.commands.set(fullName, command);
74
+
75
+ // Register aliases
76
+ if (parsed.metadata.aliases) {
77
+ for (const alias of parsed.metadata.aliases) {
78
+ const fullAlias = namespace ? `${namespace}:${alias}` : alias;
79
+ this.aliases.set(fullAlias, fullName);
80
+ }
81
+ }
82
+ } catch (error) {
83
+ logError(
84
+ `Failed to load custom command from ${filePath}: ${String(error)}`,
85
+ );
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Get a command by name (checking aliases too)
91
+ */
92
+ getCommand(name: string): CustomCommand | undefined {
93
+ // Check direct command name
94
+ const command = this.commands.get(name);
95
+ if (command) return command;
96
+
97
+ // Check aliases
98
+ const aliasTarget = this.aliases.get(name);
99
+ if (aliasTarget) {
100
+ return this.commands.get(aliasTarget);
101
+ }
102
+
103
+ return undefined;
104
+ }
105
+
106
+ /**
107
+ * Get all available commands
108
+ */
109
+ getAllCommands(): CustomCommand[] {
110
+ return Array.from(this.commands.values());
111
+ }
112
+
113
+ /**
114
+ * Get command suggestions for autocomplete
115
+ */
116
+ getSuggestions(prefix: string): string[] {
117
+ const suggestions: string[] = [];
118
+ const lowerPrefix = prefix.toLowerCase();
119
+
120
+ // Add matching command names
121
+ for (const [name, _command] of this.commands.entries()) {
122
+ if (name.toLowerCase().startsWith(lowerPrefix)) {
123
+ suggestions.push(name);
124
+ }
125
+ }
126
+
127
+ // Add matching aliases
128
+ for (const [alias, _target] of this.aliases.entries()) {
129
+ if (
130
+ alias.toLowerCase().startsWith(lowerPrefix) &&
131
+ !suggestions.includes(alias)
132
+ ) {
133
+ suggestions.push(alias);
134
+ }
135
+ }
136
+
137
+ return suggestions.sort();
138
+ }
139
+
140
+ /**
141
+ * Check if commands directory exists
142
+ */
143
+ hasCustomCommands(): boolean {
144
+ return existsSync(this.commandsDir);
145
+ }
146
+
147
+ /**
148
+ * Get the commands directory path
149
+ */
150
+ getCommandsDirectory(): string {
151
+ return this.commandsDir;
152
+ }
153
+ }