@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,63 @@
1
+ import type {
2
+ NonInteractiveCompletionResult,
3
+ NonInteractiveModeState,
4
+ } from './types';
5
+
6
+ /**
7
+ * Helper function to determine if welcome message should be rendered
8
+ */
9
+ export function shouldRenderWelcome(nonInteractiveMode?: boolean): boolean {
10
+ return !nonInteractiveMode;
11
+ }
12
+
13
+ /**
14
+ * Helper function to determine if non-interactive mode processing is complete
15
+ */
16
+ export function isNonInteractiveModeComplete(
17
+ appState: NonInteractiveModeState,
18
+ startTime: number,
19
+ maxExecutionTimeMs: number,
20
+ ): NonInteractiveCompletionResult {
21
+ const isComplete =
22
+ !appState.isToolExecuting &&
23
+ !appState.isBashExecuting &&
24
+ !appState.isToolConfirmationMode;
25
+ const _hasMessages = appState.messages.length > 0;
26
+ const hasTimedOut = Date.now() - startTime > maxExecutionTimeMs;
27
+
28
+ // Check for error messages in the messages array
29
+ const hasErrorMessages = appState.messages.some(
30
+ (message: {role: string; content: string}) =>
31
+ message.role === 'error' ||
32
+ (typeof message.content === 'string' &&
33
+ message.content.toLowerCase().includes('error')),
34
+ );
35
+
36
+ // Check for tool approval required messages
37
+ const hasToolApprovalRequired = appState.messages.some(
38
+ (message: {role: string; content: string}) =>
39
+ typeof message.content === 'string' &&
40
+ message.content.includes('Tool approval required'),
41
+ );
42
+
43
+ if (hasTimedOut) {
44
+ return {shouldExit: true, reason: 'timeout'};
45
+ }
46
+
47
+ if (hasToolApprovalRequired) {
48
+ return {shouldExit: true, reason: 'tool-approval'};
49
+ }
50
+
51
+ if (hasErrorMessages) {
52
+ return {shouldExit: true, reason: 'error'};
53
+ }
54
+
55
+ // Exit when conversation is complete and either:
56
+ // - We have messages in history (for chat/bash commands), OR
57
+ // - Conversation is marked complete (for display-only commands like /mcp)
58
+ if (isComplete && appState.isConversationComplete) {
59
+ return {shouldExit: true, reason: 'complete'};
60
+ }
61
+
62
+ return {shouldExit: false, reason: null};
63
+ }
@@ -0,0 +1,4 @@
1
+ // Re-export the main App component and types
2
+ export {default} from './App';
3
+ export type {AppProps} from './types';
4
+ export {shouldRenderWelcome, isNonInteractiveModeComplete} from './helpers';
@@ -0,0 +1,39 @@
1
+ import type {LoggingCliConfig} from '@/utils/logging/types';
2
+
3
+ /**
4
+ * Props for the main App component
5
+ */
6
+ export interface AppProps {
7
+ nonInteractivePrompt?: string;
8
+ nonInteractiveMode?: boolean;
9
+ loggingConfig?: LoggingCliConfig;
10
+ }
11
+
12
+ /**
13
+ * Reasons for non-interactive mode completion
14
+ */
15
+ export type NonInteractiveExitReason =
16
+ | 'complete'
17
+ | 'timeout'
18
+ | 'error'
19
+ | 'tool-approval'
20
+ | null;
21
+
22
+ /**
23
+ * Result of checking non-interactive mode completion status
24
+ */
25
+ export interface NonInteractiveCompletionResult {
26
+ shouldExit: boolean;
27
+ reason: NonInteractiveExitReason;
28
+ }
29
+
30
+ /**
31
+ * State required for checking non-interactive mode completion
32
+ */
33
+ export interface NonInteractiveModeState {
34
+ isToolExecuting: boolean;
35
+ isBashExecuting: boolean;
36
+ isToolConfirmationMode: boolean;
37
+ isConversationComplete: boolean;
38
+ messages: Array<{role: string; content: string}>;
39
+ }
@@ -0,0 +1,294 @@
1
+ import {parseInput} from '@/command-parser';
2
+ import {commandRegistry} from '@/commands';
3
+ import {ErrorMessage, InfoMessage} from '@/components/message-box';
4
+ import ToolMessage from '@/components/tool-message';
5
+ import {
6
+ DELAY_COMMAND_COMPLETE_MS,
7
+ TRUNCATION_RESULT_STRING_LENGTH,
8
+ } from '@/constants';
9
+ import {CheckpointManager} from '@/services/checkpoint-manager';
10
+ import {toolRegistry} from '@/tools/index';
11
+ import type {LLMClient} from '@/types/core';
12
+ import type {Message, MessageSubmissionOptions} from '@/types/index';
13
+ import React from 'react';
14
+
15
+ export async function handleMessageSubmission(
16
+ message: string,
17
+ options: MessageSubmissionOptions,
18
+ ): Promise<void> {
19
+ const {
20
+ customCommandCache,
21
+ customCommandLoader,
22
+ customCommandExecutor,
23
+ onClearMessages,
24
+ onEnterModelSelectionMode,
25
+ onEnterProviderSelectionMode,
26
+ onEnterThemeSelectionMode,
27
+ onEnterModelDatabaseMode,
28
+ onEnterConfigWizardMode,
29
+ onEnterCheckpointLoadMode,
30
+ onShowStatus,
31
+ onHandleChatMessage,
32
+ onAddToChatQueue,
33
+ onCommandComplete,
34
+ componentKeyCounter,
35
+ setMessages,
36
+ messages,
37
+ setIsBashExecuting,
38
+ setCurrentBashCommand,
39
+ } = options; // Parse the input to determine its type
40
+ const parsedInput = parseInput(message);
41
+
42
+ // Handle bash commands (prefixed with !)
43
+ if (parsedInput.isBashCommand && parsedInput.bashCommand) {
44
+ const bashCommand = parsedInput.bashCommand;
45
+
46
+ // Set bash execution state to show spinner
47
+ setCurrentBashCommand(bashCommand);
48
+ setIsBashExecuting(true);
49
+
50
+ try {
51
+ // Execute the bash command
52
+ const resultString = await toolRegistry.execute_bash({
53
+ command: bashCommand,
54
+ });
55
+
56
+ // Parse the result
57
+ let result: {fullOutput: string; llmContext: string};
58
+ try {
59
+ result = JSON.parse(resultString) as {
60
+ fullOutput: string;
61
+ llmContext: string;
62
+ };
63
+ } catch {
64
+ // If parsing fails, treat as plain string
65
+ result = {
66
+ fullOutput: resultString,
67
+ llmContext:
68
+ resultString.length > TRUNCATION_RESULT_STRING_LENGTH
69
+ ? resultString.substring(0, TRUNCATION_RESULT_STRING_LENGTH)
70
+ : resultString,
71
+ };
72
+ }
73
+
74
+ // Create a proper display of the command and its full output
75
+ const commandOutput = `$ ${bashCommand}
76
+ ${result.fullOutput || '(No output)'}`;
77
+
78
+ // Add the command and its output to the chat queue
79
+ onAddToChatQueue(
80
+ React.createElement(ToolMessage, {
81
+ key: `bash-result-${componentKeyCounter}`,
82
+ message: commandOutput,
83
+ hideBox: true,
84
+ isBashMode: true,
85
+ }),
86
+ );
87
+
88
+ // Add the truncated output to the LLM context for future interactions
89
+ if (result.llmContext) {
90
+ const userMessage: Message = {
91
+ role: 'user',
92
+ content: `Bash command output:\n\`\`\`\n$ ${bashCommand}\n${result.llmContext}\n\`\`\``,
93
+ };
94
+ setMessages([...messages, userMessage]);
95
+ }
96
+
97
+ // Clear bash execution state
98
+ setIsBashExecuting(false);
99
+ setCurrentBashCommand('');
100
+
101
+ // Signal completion for non-interactive mode
102
+ onCommandComplete?.();
103
+ return;
104
+ } catch (error: unknown) {
105
+ // Show error message if command fails
106
+ const errorMessage =
107
+ error instanceof Error ? error.message : String(error);
108
+ onAddToChatQueue(
109
+ React.createElement(ErrorMessage, {
110
+ key: `bash-error-${componentKeyCounter}`,
111
+ message: `Error executing command: ${errorMessage}`,
112
+ }),
113
+ );
114
+
115
+ // Clear bash execution state
116
+ setIsBashExecuting(false);
117
+ setCurrentBashCommand('');
118
+
119
+ // Signal completion for non-interactive mode
120
+ onCommandComplete?.();
121
+
122
+ // Don't send to LLM - just return here
123
+ return;
124
+ }
125
+ }
126
+
127
+ // Handle regular commands (prefixed with /)
128
+ if (message.startsWith('/')) {
129
+ const commandName = message.slice(1).split(' ')[0];
130
+
131
+ // Check for custom command first
132
+ const customCommand =
133
+ customCommandCache.get(commandName) ||
134
+ customCommandLoader?.getCommand(commandName);
135
+
136
+ if (customCommand) {
137
+ // Execute custom command with any arguments
138
+ const args = message
139
+ .slice(commandName.length + 1)
140
+ .trim()
141
+ .split(/\s+/)
142
+ .filter(arg => arg);
143
+ const processedPrompt = customCommandExecutor?.execute(
144
+ customCommand,
145
+ args,
146
+ );
147
+
148
+ // Send the processed prompt to the AI
149
+ if (processedPrompt) {
150
+ await onHandleChatMessage(processedPrompt);
151
+ } else {
152
+ // Custom command didn't generate a prompt, signal completion
153
+ onCommandComplete?.();
154
+ }
155
+ return;
156
+ } else {
157
+ // Handle special commands that need app state access
158
+ if (commandName === 'clear') {
159
+ await onClearMessages();
160
+ onCommandComplete?.();
161
+ // Still show the clear command result
162
+ } else if (commandName === 'model') {
163
+ onEnterModelSelectionMode();
164
+ onCommandComplete?.();
165
+ return;
166
+ } else if (commandName === 'provider') {
167
+ onEnterProviderSelectionMode();
168
+ onCommandComplete?.();
169
+ return;
170
+ } else if (commandName === 'theme') {
171
+ onEnterThemeSelectionMode();
172
+ onCommandComplete?.();
173
+ return;
174
+ } else if (commandName === 'model-database') {
175
+ onEnterModelDatabaseMode();
176
+ onCommandComplete?.();
177
+ return;
178
+ } else if (commandName === 'setup-config') {
179
+ onEnterConfigWizardMode();
180
+ onCommandComplete?.();
181
+ return;
182
+ } else if (commandName === 'status') {
183
+ onShowStatus();
184
+ // Status adds to queue synchronously, give React time to render
185
+ setTimeout(() => onCommandComplete?.(), DELAY_COMMAND_COMPLETE_MS);
186
+ return;
187
+ }
188
+
189
+ // Handle checkpoint load specially for interactive mode
190
+ const commandParts = message.slice(1).trim().split(/\s+/);
191
+ if (
192
+ commandParts[0] === 'checkpoint' &&
193
+ (commandParts[1] === 'load' || commandParts[1] === 'restore') &&
194
+ commandParts.length === 2
195
+ ) {
196
+ // Interactive checkpoint load - no specific checkpoint name provided
197
+ try {
198
+ const manager = new CheckpointManager();
199
+ const checkpoints = await manager.listCheckpoints();
200
+
201
+ if (checkpoints.length === 0) {
202
+ onAddToChatQueue(
203
+ React.createElement(InfoMessage, {
204
+ key: `checkpoint-info-${componentKeyCounter}`,
205
+ message:
206
+ 'No checkpoints available. Create one with /checkpoint create [name]',
207
+ hideBox: true,
208
+ }),
209
+ );
210
+ return;
211
+ }
212
+
213
+ onEnterCheckpointLoadMode(checkpoints, messages.length);
214
+ return;
215
+ } catch (error) {
216
+ onAddToChatQueue(
217
+ React.createElement(ErrorMessage, {
218
+ key: `checkpoint-error-${componentKeyCounter}`,
219
+ message: `Failed to list checkpoints: ${
220
+ error instanceof Error ? error.message : 'Unknown error'
221
+ }`,
222
+ hideBox: true,
223
+ }),
224
+ );
225
+ return;
226
+ }
227
+ }
228
+
229
+ // Execute built-in command
230
+ const totalTokens = messages.reduce(
231
+ (sum, msg) => sum + options.getMessageTokens(msg),
232
+ 0,
233
+ );
234
+ const result = await commandRegistry.execute(message.slice(1), messages, {
235
+ provider: options.provider,
236
+ model: options.model,
237
+ tokens: totalTokens,
238
+ getMessageTokens: options.getMessageTokens,
239
+ });
240
+ if (result) {
241
+ // Check if result is JSX (React element)
242
+ // Defer adding to chat queue to avoid "Cannot update a component while rendering" error
243
+ if (React.isValidElement(result)) {
244
+ queueMicrotask(() => {
245
+ onAddToChatQueue(result);
246
+ });
247
+ // Give React time to render before signaling completion
248
+ setTimeout(() => {
249
+ onCommandComplete?.();
250
+ }, DELAY_COMMAND_COMPLETE_MS);
251
+ } else if (typeof result === 'string' && result.trim()) {
252
+ queueMicrotask(() => {
253
+ onAddToChatQueue(
254
+ React.createElement(InfoMessage, {
255
+ key: `command-result-${componentKeyCounter}`,
256
+ message: result,
257
+ hideBox: true,
258
+ }),
259
+ );
260
+ });
261
+ // Give React time to render before signaling completion
262
+ setTimeout(() => {
263
+ onCommandComplete?.();
264
+ }, DELAY_COMMAND_COMPLETE_MS);
265
+ } else {
266
+ // No output to display, signal completion immediately
267
+ onCommandComplete?.();
268
+ }
269
+ } else {
270
+ // No result, signal completion immediately
271
+ onCommandComplete?.();
272
+ }
273
+ }
274
+
275
+ // Return here to avoid sending to LLM
276
+ return;
277
+ }
278
+
279
+ // Regular chat message - process with AI
280
+ await onHandleChatMessage(message);
281
+ }
282
+
283
+ export function createClearMessagesHandler(
284
+ setMessages: (messages: Message[]) => void,
285
+ client: LLMClient | null,
286
+ ) {
287
+ return async () => {
288
+ // Clear message history and client context
289
+ setMessages([]);
290
+ if (client) {
291
+ await client.clearContext();
292
+ }
293
+ };
294
+ }
@@ -0,0 +1,310 @@
1
+ import type {Message, ToolCall} from '@/types/core';
2
+
3
+ interface ConversationProgress {
4
+ originalTask: string;
5
+ currentStep: number;
6
+ totalEstimatedSteps: number;
7
+ completedActions: string[];
8
+ nextAction?: string;
9
+ toolCallsExecuted: number;
10
+ lastToolCall?: ToolCall;
11
+ isRepeatingAction: boolean;
12
+ contextSummary?: string;
13
+ }
14
+
15
+ interface ConversationState {
16
+ progress: ConversationProgress;
17
+ lastAssistantMessage?: Message;
18
+ conversationStartTime: number;
19
+ toolExecutionCount: number;
20
+ recentToolCalls: ToolCall[];
21
+ }
22
+
23
+ export class ConversationStateManager {
24
+ private state: ConversationState | null = null;
25
+ private maxRecentToolCalls = 5;
26
+
27
+ /**
28
+ * Initialize conversation state from the first user message
29
+ */
30
+ initializeState(userMessage: string): ConversationState {
31
+ // Detect if this is a simple greeting to avoid over-interpreting
32
+ const isSimpleGreeting = this.isSimpleGreeting(userMessage);
33
+ this.state = {
34
+ progress: {
35
+ originalTask: userMessage,
36
+ currentStep: 1,
37
+ totalEstimatedSteps: isSimpleGreeting
38
+ ? 1
39
+ : this.estimateSteps(userMessage),
40
+ completedActions: [],
41
+ toolCallsExecuted: 0,
42
+ isRepeatingAction: false,
43
+ },
44
+ conversationStartTime: Date.now(),
45
+ toolExecutionCount: 0,
46
+ recentToolCalls: [],
47
+ };
48
+ return this.state;
49
+ }
50
+
51
+ /**
52
+ * Update state after tool execution
53
+ */
54
+ updateAfterToolExecution(toolCall: ToolCall, result: string): void {
55
+ if (!this.state) return;
56
+
57
+ // Add to recent tool calls
58
+ this.state.recentToolCalls.push(toolCall);
59
+ if (this.state.recentToolCalls.length > this.maxRecentToolCalls) {
60
+ this.state.recentToolCalls.shift();
61
+ }
62
+
63
+ // Check for repetition
64
+ const isRepeating = this.detectRepetition(toolCall);
65
+
66
+ // Update progress
67
+ this.state.progress.toolCallsExecuted++;
68
+ this.state.progress.lastToolCall = toolCall;
69
+ this.state.progress.isRepeatingAction = isRepeating;
70
+ this.state.progress.currentStep++;
71
+
72
+ // Add completed action
73
+ const actionDescription = this.describeToolAction(toolCall, result);
74
+ this.state.progress.completedActions.push(actionDescription);
75
+
76
+ // Update total estimated steps if needed
77
+ if (
78
+ this.state.progress.currentStep > this.state.progress.totalEstimatedSteps
79
+ ) {
80
+ this.state.progress.totalEstimatedSteps =
81
+ this.state.progress.currentStep + 2;
82
+ }
83
+
84
+ this.state.toolExecutionCount++;
85
+ }
86
+
87
+ /**
88
+ * Update assistant message in state
89
+ */
90
+ updateAssistantMessage(message: Message): void {
91
+ if (!this.state) return;
92
+ this.state.lastAssistantMessage = message;
93
+ }
94
+
95
+ /**
96
+ * Generate context-aware continuation prompt
97
+ */
98
+ generateContinuationContext(): string {
99
+ if (!this.state) return '';
100
+
101
+ const progress = this.state.progress;
102
+ let context = `[Task Progress: Step ${progress.currentStep} of ~${progress.totalEstimatedSteps}]\n`;
103
+ context += `[Original Task: "${progress.originalTask}"]\n\n`;
104
+
105
+ if (progress.completedActions.length > 0) {
106
+ context += `Recent actions completed:\n`;
107
+ progress.completedActions.slice(-3).forEach((action, i) => {
108
+ context += `${i + 1}. ${action}\n`;
109
+ });
110
+ context += '\n';
111
+ }
112
+
113
+ if (progress.isRepeatingAction) {
114
+ context += `⚠️ Warning: You may be repeating a similar action. Consider a different approach or move to the next step.\n\n`;
115
+ }
116
+
117
+ // Suggest next logical step
118
+ context += this.generateNextStepSuggestion();
119
+
120
+ context += `Continue working toward completing: "${progress.originalTask}"`;
121
+
122
+ return context;
123
+ }
124
+
125
+ /**
126
+ * Get current state
127
+ */
128
+ getState(): ConversationState | null {
129
+ return this.state;
130
+ }
131
+
132
+ /**
133
+ * Reset state
134
+ */
135
+ reset(): void {
136
+ this.state = null;
137
+ }
138
+
139
+ /**
140
+ * Estimate number of steps for a task
141
+ */
142
+ private estimateSteps(task: string): number {
143
+ const taskLower = task.toLowerCase();
144
+
145
+ // Simple heuristics based on task complexity
146
+ if (
147
+ taskLower.includes('create') ||
148
+ taskLower.includes('build') ||
149
+ taskLower.includes('implement')
150
+ ) {
151
+ return 5;
152
+ }
153
+ if (
154
+ taskLower.includes('fix') ||
155
+ taskLower.includes('debug') ||
156
+ taskLower.includes('troubleshoot')
157
+ ) {
158
+ return 4;
159
+ }
160
+ if (
161
+ taskLower.includes('analyze') ||
162
+ taskLower.includes('understand') ||
163
+ taskLower.includes('explain')
164
+ ) {
165
+ return 3;
166
+ }
167
+ if (
168
+ taskLower.includes('read') ||
169
+ taskLower.includes('show') ||
170
+ taskLower.includes('list')
171
+ ) {
172
+ return 2;
173
+ }
174
+
175
+ // Default based on length
176
+ return Math.max(3, Math.min(8, Math.ceil(task.length / 50)));
177
+ }
178
+
179
+ /**
180
+ * Detect if the current tool call is repetitive
181
+ */
182
+ private detectRepetition(toolCall: ToolCall): boolean {
183
+ if (!this.state || this.state.recentToolCalls.length < 2) return false;
184
+
185
+ const recentToolCalls = this.state.recentToolCalls;
186
+ const recent = recentToolCalls.slice(-2);
187
+ return recent.some(
188
+ prevCall =>
189
+ prevCall.function.name === toolCall.function.name &&
190
+ JSON.stringify(prevCall.function.arguments) ===
191
+ JSON.stringify(toolCall.function.arguments),
192
+ );
193
+ }
194
+
195
+ /**
196
+ * Describe what a tool action accomplished
197
+ */
198
+ private describeToolAction(toolCall: ToolCall, _result: string): string {
199
+ const toolName = toolCall.function.name;
200
+ const args = toolCall.function.arguments;
201
+
202
+ const getFilename = () => {
203
+ const filename = args.filename;
204
+ const path = args.path;
205
+ if (typeof filename === 'string') return filename;
206
+ if (typeof path === 'string') return path;
207
+ return 'unknown';
208
+ };
209
+
210
+ switch (toolName) {
211
+ case 'read_file':
212
+ return `Read file: ${getFilename()}`;
213
+ case 'write_file':
214
+ case 'create_file':
215
+ return `Created/wrote file: ${getFilename()}`;
216
+ case 'edit_file':
217
+ return `Edited file: ${getFilename()}`;
218
+ case 'execute_bash': {
219
+ const command = args.command;
220
+ const commandStr = typeof command === 'string' ? command : '';
221
+ return `Executed command: ${commandStr.substring(0, 50)}${
222
+ commandStr.length > 50 ? '...' : ''
223
+ }`;
224
+ }
225
+ default:
226
+ return `Used ${toolName}`;
227
+ }
228
+ }
229
+
230
+ /**
231
+ * Generate intelligent next step suggestions
232
+ */
233
+ private generateNextStepSuggestion(): string {
234
+ if (!this.state) return '';
235
+
236
+ const progress = this.state.progress;
237
+ const lastTool = progress.lastToolCall;
238
+
239
+ if (!lastTool) {
240
+ return 'Consider what information you need to gather first.\n\n';
241
+ }
242
+
243
+ const suggestions: string[] = [];
244
+
245
+ // Suggest logical next steps based on last tool
246
+ switch (lastTool.function.name) {
247
+ case 'read_file':
248
+ suggestions.push(
249
+ 'Based on the file contents, determine what changes or analysis are needed.',
250
+ );
251
+ break;
252
+ case 'execute_bash':
253
+ suggestions.push(
254
+ 'Review the command output and decide on the next action.',
255
+ );
256
+ break;
257
+ case 'create_file':
258
+ case 'write_file':
259
+ suggestions.push(
260
+ 'Consider testing or verifying the file you just created.',
261
+ );
262
+ break;
263
+ case 'edit_file':
264
+ suggestions.push(
265
+ 'Consider testing the changes or making additional modifications.',
266
+ );
267
+ break;
268
+ default:
269
+ suggestions.push('Use the tool result to inform your next action.');
270
+ }
271
+
272
+ // Add progress-based suggestions
273
+ if (progress.currentStep / progress.totalEstimatedSteps > 0.7) {
274
+ suggestions.push(
275
+ "You're near completion - focus on finalizing and testing.",
276
+ );
277
+ }
278
+
279
+ return suggestions.join(' ') + '\n\n';
280
+ }
281
+
282
+ /**
283
+ * Detect if a message is a simple greeting to avoid over-interpreting
284
+ */
285
+ private isSimpleGreeting(message: string): boolean {
286
+ const lowerMessage = message.toLowerCase().trim();
287
+ const greetings = [
288
+ 'hi',
289
+ 'hello',
290
+ 'hey',
291
+ 'hiya',
292
+ 'howdy',
293
+ 'good morning',
294
+ 'good afternoon',
295
+ 'good evening',
296
+ "what's up",
297
+ 'whats up',
298
+ 'sup',
299
+ 'yo',
300
+ ];
301
+
302
+ // Check if the entire message is just a greeting (with optional punctuation)
303
+ const cleanMessage = lowerMessage.replace(/[!?.,\s]+$/g, '');
304
+ return (
305
+ greetings.includes(cleanMessage) ||
306
+ (cleanMessage.length <= 10 &&
307
+ greetings.some(greeting => cleanMessage.includes(greeting)))
308
+ );
309
+ }
310
+ }