@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.
- package/.editorconfig +16 -0
- package/.env.example +63 -0
- package/.gitattributes +1 -0
- package/.semgrepignore +19 -0
- package/coder-dummy-file.ts +52 -0
- package/coder.config.example.json +59 -0
- package/coder.config.json +13 -0
- package/color_picker.html +36 -0
- package/package.json +2 -14
- package/scripts/extract-changelog.js +73 -0
- package/scripts/fetch-models.js +143 -0
- package/scripts/test.sh +40 -0
- package/scripts/update-homebrew-formula.sh +125 -0
- package/scripts/update-nix-version.sh +157 -0
- package/source/ai-sdk-client/AISDKClient.spec.ts +117 -0
- package/source/ai-sdk-client/AISDKClient.ts +155 -0
- package/source/ai-sdk-client/chat/chat-handler.spec.ts +121 -0
- package/source/ai-sdk-client/chat/chat-handler.ts +276 -0
- package/source/ai-sdk-client/chat/streaming-handler.spec.ts +173 -0
- package/source/ai-sdk-client/chat/streaming-handler.ts +110 -0
- package/source/ai-sdk-client/chat/tool-processor.spec.ts +92 -0
- package/source/ai-sdk-client/chat/tool-processor.ts +70 -0
- package/source/ai-sdk-client/converters/message-converter.spec.ts +220 -0
- package/source/ai-sdk-client/converters/message-converter.ts +113 -0
- package/source/ai-sdk-client/converters/tool-converter.spec.ts +90 -0
- package/source/ai-sdk-client/converters/tool-converter.ts +46 -0
- package/source/ai-sdk-client/error-handling/error-extractor.spec.ts +55 -0
- package/source/ai-sdk-client/error-handling/error-extractor.ts +15 -0
- package/source/ai-sdk-client/error-handling/error-parser.spec.ts +169 -0
- package/source/ai-sdk-client/error-handling/error-parser.ts +161 -0
- package/source/ai-sdk-client/index.ts +7 -0
- package/source/ai-sdk-client/providers/provider-factory.spec.ts +71 -0
- package/source/ai-sdk-client/providers/provider-factory.ts +41 -0
- package/source/ai-sdk-client/types.ts +9 -0
- package/source/ai-sdk-client-empty-message.spec.ts +141 -0
- package/source/ai-sdk-client-error-handling.spec.ts +186 -0
- package/source/ai-sdk-client-maxretries.spec.ts +114 -0
- package/source/ai-sdk-client-preparestep.spec.ts +279 -0
- package/source/app/App.spec.tsx +32 -0
- package/source/app/App.tsx +480 -0
- package/source/app/components/AppContainer.spec.tsx +96 -0
- package/source/app/components/AppContainer.tsx +56 -0
- package/source/app/components/ChatInterface.spec.tsx +163 -0
- package/source/app/components/ChatInterface.tsx +144 -0
- package/source/app/components/ModalSelectors.spec.tsx +141 -0
- package/source/app/components/ModalSelectors.tsx +135 -0
- package/source/app/helpers.spec.ts +97 -0
- package/source/app/helpers.ts +63 -0
- package/source/app/index.ts +4 -0
- package/source/app/types.ts +39 -0
- package/source/app/utils/appUtils.ts +294 -0
- package/source/app/utils/conversationState.ts +310 -0
- package/source/app.spec.tsx +244 -0
- package/source/cli.spec.ts +73 -0
- package/source/cli.tsx +51 -0
- package/source/client-factory.spec.ts +48 -0
- package/source/client-factory.ts +178 -0
- package/source/command-parser.spec.ts +127 -0
- package/source/command-parser.ts +36 -0
- package/source/commands/checkpoint.spec.tsx +277 -0
- package/source/commands/checkpoint.tsx +366 -0
- package/source/commands/clear.tsx +22 -0
- package/source/commands/custom-commands.tsx +121 -0
- package/source/commands/exit.ts +21 -0
- package/source/commands/export.spec.tsx +131 -0
- package/source/commands/export.tsx +79 -0
- package/source/commands/help.tsx +120 -0
- package/source/commands/index.ts +17 -0
- package/source/commands/init.tsx +339 -0
- package/source/commands/lsp-command.spec.tsx +281 -0
- package/source/commands/lsp.tsx +120 -0
- package/source/commands/mcp-command.spec.tsx +313 -0
- package/source/commands/mcp.tsx +162 -0
- package/source/commands/model-database.spec.tsx +758 -0
- package/source/commands/model-database.tsx +418 -0
- package/source/commands/model.ts +12 -0
- package/source/commands/provider.ts +12 -0
- package/source/commands/setup-config.tsx +16 -0
- package/source/commands/simple-commands.spec.tsx +175 -0
- package/source/commands/status.ts +12 -0
- package/source/commands/theme.ts +12 -0
- package/source/commands/update.spec.tsx +261 -0
- package/source/commands/update.tsx +201 -0
- package/source/commands/usage.spec.tsx +495 -0
- package/source/commands/usage.tsx +100 -0
- package/source/commands.spec.ts +436 -0
- package/source/commands.ts +83 -0
- package/source/components/assistant-message.spec.tsx +796 -0
- package/source/components/assistant-message.tsx +34 -0
- package/source/components/bash-execution-indicator.tsx +21 -0
- package/source/components/cancelling-indicator.tsx +16 -0
- package/source/components/chat-queue.spec.tsx +83 -0
- package/source/components/chat-queue.tsx +36 -0
- package/source/components/checkpoint-display.spec.tsx +219 -0
- package/source/components/checkpoint-display.tsx +126 -0
- package/source/components/checkpoint-selector.spec.tsx +173 -0
- package/source/components/checkpoint-selector.tsx +173 -0
- package/source/components/development-mode-indicator.spec.tsx +268 -0
- package/source/components/development-mode-indicator.tsx +38 -0
- package/source/components/message-box.spec.tsx +427 -0
- package/source/components/message-box.tsx +87 -0
- package/source/components/model-selector.tsx +132 -0
- package/source/components/provider-selector.tsx +75 -0
- package/source/components/random-spinner.tsx +19 -0
- package/source/components/security-disclaimer.tsx +73 -0
- package/source/components/status-connection-display.spec.tsx +133 -0
- package/source/components/status.tsx +267 -0
- package/source/components/theme-selector.tsx +126 -0
- package/source/components/tool-confirmation.tsx +190 -0
- package/source/components/tool-execution-indicator.tsx +33 -0
- package/source/components/tool-message.tsx +85 -0
- package/source/components/ui/titled-box.spec.tsx +207 -0
- package/source/components/ui/titled-box.tsx +57 -0
- package/source/components/usage/progress-bar.spec.tsx +398 -0
- package/source/components/usage/progress-bar.tsx +30 -0
- package/source/components/usage/usage-display.spec.tsx +780 -0
- package/source/components/usage/usage-display.tsx +291 -0
- package/source/components/user-input.spec.tsx +327 -0
- package/source/components/user-input.tsx +533 -0
- package/source/components/user-message.spec.tsx +230 -0
- package/source/components/user-message.tsx +84 -0
- package/source/components/welcome-message.tsx +76 -0
- package/source/config/env-substitution.ts +65 -0
- package/source/config/index.spec.ts +171 -0
- package/source/config/index.ts +154 -0
- package/source/config/paths.spec.ts +241 -0
- package/source/config/paths.ts +55 -0
- package/source/config/preferences.ts +51 -0
- package/source/config/themes.ts +315 -0
- package/source/constants.ts +130 -0
- package/source/context/mode-context.spec.ts +79 -0
- package/source/context/mode-context.ts +24 -0
- package/source/custom-commands/executor.spec.ts +142 -0
- package/source/custom-commands/executor.ts +64 -0
- package/source/custom-commands/loader.spec.ts +314 -0
- package/source/custom-commands/loader.ts +153 -0
- package/source/custom-commands/parser.ts +196 -0
- package/source/hooks/chat-handler/conversation/conversation-loop.spec.ts +39 -0
- package/source/hooks/chat-handler/conversation/conversation-loop.tsx +511 -0
- package/source/hooks/chat-handler/conversation/tool-executor.spec.ts +50 -0
- package/source/hooks/chat-handler/conversation/tool-executor.tsx +109 -0
- package/source/hooks/chat-handler/index.ts +12 -0
- package/source/hooks/chat-handler/state/streaming-state.spec.ts +26 -0
- package/source/hooks/chat-handler/state/streaming-state.ts +19 -0
- package/source/hooks/chat-handler/types.ts +38 -0
- package/source/hooks/chat-handler/useChatHandler.spec.tsx +321 -0
- package/source/hooks/chat-handler/useChatHandler.tsx +194 -0
- package/source/hooks/chat-handler/utils/context-checker.spec.ts +60 -0
- package/source/hooks/chat-handler/utils/context-checker.tsx +73 -0
- package/source/hooks/chat-handler/utils/message-helpers.spec.ts +42 -0
- package/source/hooks/chat-handler/utils/message-helpers.tsx +36 -0
- package/source/hooks/chat-handler/utils/tool-filters.spec.ts +109 -0
- package/source/hooks/chat-handler/utils/tool-filters.ts +64 -0
- package/source/hooks/useAppHandlers.tsx +291 -0
- package/source/hooks/useAppInitialization.tsx +422 -0
- package/source/hooks/useAppState.tsx +311 -0
- package/source/hooks/useDirectoryTrust.tsx +98 -0
- package/source/hooks/useInputState.ts +414 -0
- package/source/hooks/useModeHandlers.tsx +302 -0
- package/source/hooks/useNonInteractiveMode.ts +140 -0
- package/source/hooks/useTerminalWidth.tsx +81 -0
- package/source/hooks/useTheme.ts +18 -0
- package/source/hooks/useToolHandler.tsx +349 -0
- package/source/hooks/useUIState.ts +61 -0
- package/source/init/agents-template-generator.ts +421 -0
- package/source/init/existing-rules-extractor.ts +319 -0
- package/source/init/file-scanner.spec.ts +227 -0
- package/source/init/file-scanner.ts +238 -0
- package/source/init/framework-detector.ts +382 -0
- package/source/init/language-detector.ts +269 -0
- package/source/init/project-analyzer.spec.ts +231 -0
- package/source/init/project-analyzer.ts +458 -0
- package/source/lsp/index.ts +31 -0
- package/source/lsp/lsp-client.spec.ts +508 -0
- package/source/lsp/lsp-client.ts +487 -0
- package/source/lsp/lsp-manager.spec.ts +477 -0
- package/source/lsp/lsp-manager.ts +419 -0
- package/source/lsp/protocol.spec.ts +502 -0
- package/source/lsp/protocol.ts +360 -0
- package/source/lsp/server-discovery.spec.ts +654 -0
- package/source/lsp/server-discovery.ts +515 -0
- package/source/markdown-parser/html-entities.spec.ts +88 -0
- package/source/markdown-parser/html-entities.ts +45 -0
- package/source/markdown-parser/index.spec.ts +281 -0
- package/source/markdown-parser/index.ts +126 -0
- package/source/markdown-parser/table-parser.spec.ts +133 -0
- package/source/markdown-parser/table-parser.ts +114 -0
- package/source/markdown-parser/utils.spec.ts +70 -0
- package/source/markdown-parser/utils.ts +13 -0
- package/source/mcp/mcp-client.spec.ts +81 -0
- package/source/mcp/mcp-client.ts +625 -0
- package/source/mcp/transport-factory.spec.ts +406 -0
- package/source/mcp/transport-factory.ts +312 -0
- package/source/message-handler.ts +67 -0
- package/source/model-database/database-engine.spec.ts +494 -0
- package/source/model-database/database-engine.ts +50 -0
- package/source/model-database/model-database.spec.ts +363 -0
- package/source/model-database/model-database.ts +91 -0
- package/source/model-database/model-engine.spec.ts +447 -0
- package/source/model-database/model-engine.ts +65 -0
- package/source/model-database/model-fetcher.spec.ts +583 -0
- package/source/model-database/model-fetcher.ts +330 -0
- package/source/models/index.ts +1 -0
- package/source/models/models-cache.spec.ts +214 -0
- package/source/models/models-cache.ts +78 -0
- package/source/models/models-dev-client.spec.ts +379 -0
- package/source/models/models-dev-client.ts +329 -0
- package/source/models/models-types.ts +68 -0
- package/source/prompt-history.ts +155 -0
- package/source/security/command-injection.spec.ts +240 -0
- package/source/services/checkpoint-manager.spec.ts +523 -0
- package/source/services/checkpoint-manager.ts +466 -0
- package/source/services/file-snapshot.spec.ts +569 -0
- package/source/services/file-snapshot.ts +220 -0
- package/source/test-utils/render-with-theme.tsx +48 -0
- package/source/tokenization/index.ts +1 -0
- package/source/tokenization/tokenizer-factory.spec.ts +170 -0
- package/source/tokenization/tokenizer-factory.ts +125 -0
- package/source/tokenization/tokenizers/anthropic-tokenizer.spec.ts +200 -0
- package/source/tokenization/tokenizers/anthropic-tokenizer.ts +43 -0
- package/source/tokenization/tokenizers/fallback-tokenizer.spec.ts +236 -0
- package/source/tokenization/tokenizers/fallback-tokenizer.ts +26 -0
- package/source/tokenization/tokenizers/llama-tokenizer.spec.ts +224 -0
- package/source/tokenization/tokenizers/llama-tokenizer.ts +41 -0
- package/source/tokenization/tokenizers/openai-tokenizer.spec.ts +184 -0
- package/source/tokenization/tokenizers/openai-tokenizer.ts +57 -0
- package/source/tool-calling/index.ts +5 -0
- package/source/tool-calling/json-parser.spec.ts +639 -0
- package/source/tool-calling/json-parser.ts +247 -0
- package/source/tool-calling/tool-parser.spec.ts +395 -0
- package/source/tool-calling/tool-parser.ts +120 -0
- package/source/tool-calling/xml-parser.spec.ts +662 -0
- package/source/tool-calling/xml-parser.ts +289 -0
- package/source/tools/execute-bash.spec.tsx +353 -0
- package/source/tools/execute-bash.tsx +219 -0
- package/source/tools/execute-function.spec.ts +130 -0
- package/source/tools/fetch-url.spec.tsx +342 -0
- package/source/tools/fetch-url.tsx +172 -0
- package/source/tools/find-files.spec.tsx +924 -0
- package/source/tools/find-files.tsx +293 -0
- package/source/tools/index.ts +102 -0
- package/source/tools/lsp-get-diagnostics.tsx +192 -0
- package/source/tools/needs-approval.spec.ts +282 -0
- package/source/tools/read-file.spec.tsx +801 -0
- package/source/tools/read-file.tsx +387 -0
- package/source/tools/search-file-contents.spec.tsx +1273 -0
- package/source/tools/search-file-contents.tsx +293 -0
- package/source/tools/string-replace.spec.tsx +730 -0
- package/source/tools/string-replace.tsx +548 -0
- package/source/tools/tool-manager.ts +210 -0
- package/source/tools/tool-registry.spec.ts +415 -0
- package/source/tools/tool-registry.ts +228 -0
- package/source/tools/web-search.tsx +223 -0
- package/source/tools/write-file.spec.tsx +559 -0
- package/source/tools/write-file.tsx +228 -0
- package/source/types/app.ts +37 -0
- package/source/types/checkpoint.ts +48 -0
- package/source/types/commands.ts +46 -0
- package/source/types/components.ts +27 -0
- package/source/types/config.ts +103 -0
- package/source/types/core-connection-status.spec.ts +67 -0
- package/source/types/core.ts +181 -0
- package/source/types/hooks.ts +50 -0
- package/source/types/index.ts +12 -0
- package/source/types/markdown-parser.ts +11 -0
- package/source/types/mcp.ts +52 -0
- package/source/types/system.ts +16 -0
- package/source/types/tokenization.ts +41 -0
- package/source/types/ui.ts +40 -0
- package/source/types/usage.ts +58 -0
- package/source/types/utils.ts +16 -0
- package/source/usage/calculator.spec.ts +385 -0
- package/source/usage/calculator.ts +104 -0
- package/source/usage/storage.spec.ts +703 -0
- package/source/usage/storage.ts +238 -0
- package/source/usage/tracker.spec.ts +456 -0
- package/source/usage/tracker.ts +102 -0
- package/source/utils/atomic-deletion.spec.ts +194 -0
- package/source/utils/atomic-deletion.ts +127 -0
- package/source/utils/bounded-map.spec.ts +300 -0
- package/source/utils/bounded-map.ts +193 -0
- package/source/utils/checkpoint-utils.spec.ts +222 -0
- package/source/utils/checkpoint-utils.ts +92 -0
- package/source/utils/error-formatter.spec.ts +169 -0
- package/source/utils/error-formatter.ts +194 -0
- package/source/utils/file-autocomplete.spec.ts +173 -0
- package/source/utils/file-autocomplete.ts +196 -0
- package/source/utils/file-cache.spec.ts +309 -0
- package/source/utils/file-cache.ts +195 -0
- package/source/utils/file-content-loader.spec.ts +180 -0
- package/source/utils/file-content-loader.ts +179 -0
- package/source/utils/file-mention-handler.spec.ts +261 -0
- package/source/utils/file-mention-handler.ts +84 -0
- package/source/utils/file-mention-parser.spec.ts +182 -0
- package/source/utils/file-mention-parser.ts +170 -0
- package/source/utils/fuzzy-matching.spec.ts +149 -0
- package/source/utils/fuzzy-matching.ts +146 -0
- package/source/utils/indentation-normalizer.spec.ts +216 -0
- package/source/utils/indentation-normalizer.ts +76 -0
- package/source/utils/installation-detector.spec.ts +178 -0
- package/source/utils/installation-detector.ts +153 -0
- package/source/utils/logging/config.spec.ts +311 -0
- package/source/utils/logging/config.ts +210 -0
- package/source/utils/logging/console-facade.spec.ts +184 -0
- package/source/utils/logging/console-facade.ts +384 -0
- package/source/utils/logging/correlation.spec.ts +679 -0
- package/source/utils/logging/correlation.ts +474 -0
- package/source/utils/logging/formatters.spec.ts +464 -0
- package/source/utils/logging/formatters.ts +207 -0
- package/source/utils/logging/health-monitor/alerts/alert-manager.spec.ts +93 -0
- package/source/utils/logging/health-monitor/alerts/alert-manager.ts +79 -0
- package/source/utils/logging/health-monitor/checks/configuration-check.spec.ts +56 -0
- package/source/utils/logging/health-monitor/checks/configuration-check.ts +43 -0
- package/source/utils/logging/health-monitor/checks/logging-check.spec.ts +56 -0
- package/source/utils/logging/health-monitor/checks/logging-check.ts +58 -0
- package/source/utils/logging/health-monitor/checks/memory-check.spec.ts +100 -0
- package/source/utils/logging/health-monitor/checks/memory-check.ts +78 -0
- package/source/utils/logging/health-monitor/checks/performance-check.spec.ts +56 -0
- package/source/utils/logging/health-monitor/checks/performance-check.ts +56 -0
- package/source/utils/logging/health-monitor/checks/request-check.spec.ts +56 -0
- package/source/utils/logging/health-monitor/checks/request-check.ts +76 -0
- package/source/utils/logging/health-monitor/core/health-check-runner.spec.ts +70 -0
- package/source/utils/logging/health-monitor/core/health-check-runner.ts +138 -0
- package/source/utils/logging/health-monitor/core/health-monitor.spec.ts +58 -0
- package/source/utils/logging/health-monitor/core/health-monitor.ts +344 -0
- package/source/utils/logging/health-monitor/core/scoring.spec.ts +65 -0
- package/source/utils/logging/health-monitor/core/scoring.ts +91 -0
- package/source/utils/logging/health-monitor/index.ts +15 -0
- package/source/utils/logging/health-monitor/instances.ts +48 -0
- package/source/utils/logging/health-monitor/middleware/http-middleware.spec.ts +141 -0
- package/source/utils/logging/health-monitor/middleware/http-middleware.ts +75 -0
- package/source/utils/logging/health-monitor/types.ts +126 -0
- package/source/utils/logging/index.spec.ts +284 -0
- package/source/utils/logging/index.ts +236 -0
- package/source/utils/logging/integration.spec.ts +441 -0
- package/source/utils/logging/log-method-factory.spec.ts +573 -0
- package/source/utils/logging/log-method-factory.ts +233 -0
- package/source/utils/logging/log-query/aggregation/aggregator.spec.ts +277 -0
- package/source/utils/logging/log-query/aggregation/aggregator.ts +159 -0
- package/source/utils/logging/log-query/aggregation/facet-generator.spec.ts +159 -0
- package/source/utils/logging/log-query/aggregation/facet-generator.ts +47 -0
- package/source/utils/logging/log-query/index.ts +23 -0
- package/source/utils/logging/log-query/query/filter-predicates.spec.ts +247 -0
- package/source/utils/logging/log-query/query/filter-predicates.ts +154 -0
- package/source/utils/logging/log-query/query/query-builder.spec.ts +182 -0
- package/source/utils/logging/log-query/query/query-builder.ts +151 -0
- package/source/utils/logging/log-query/query/query-engine.spec.ts +214 -0
- package/source/utils/logging/log-query/query/query-engine.ts +45 -0
- package/source/utils/logging/log-query/storage/circular-buffer.spec.ts +143 -0
- package/source/utils/logging/log-query/storage/circular-buffer.ts +75 -0
- package/source/utils/logging/log-query/storage/index-manager.spec.ts +150 -0
- package/source/utils/logging/log-query/storage/index-manager.ts +71 -0
- package/source/utils/logging/log-query/storage/log-storage.spec.ts +257 -0
- package/source/utils/logging/log-query/storage/log-storage.ts +80 -0
- package/source/utils/logging/log-query/types.ts +163 -0
- package/source/utils/logging/log-query/utils/helpers.spec.ts +263 -0
- package/source/utils/logging/log-query/utils/helpers.ts +72 -0
- package/source/utils/logging/log-query/utils/sorting.spec.ts +182 -0
- package/source/utils/logging/log-query/utils/sorting.ts +61 -0
- package/source/utils/logging/logger-provider.spec.ts +262 -0
- package/source/utils/logging/logger-provider.ts +362 -0
- package/source/utils/logging/performance.spec.ts +209 -0
- package/source/utils/logging/performance.ts +757 -0
- package/source/utils/logging/pino-logger.spec.ts +425 -0
- package/source/utils/logging/pino-logger.ts +514 -0
- package/source/utils/logging/redaction.spec.ts +490 -0
- package/source/utils/logging/redaction.ts +267 -0
- package/source/utils/logging/request-tracker.spec.ts +1198 -0
- package/source/utils/logging/request-tracker.ts +803 -0
- package/source/utils/logging/transports.spec.ts +505 -0
- package/source/utils/logging/transports.ts +305 -0
- package/source/utils/logging/types.ts +216 -0
- package/source/utils/message-builder.spec.ts +179 -0
- package/source/utils/message-builder.ts +101 -0
- package/source/utils/message-queue.tsx +486 -0
- package/source/utils/paste-detection.spec.ts +69 -0
- package/source/utils/paste-detection.ts +124 -0
- package/source/utils/paste-roundtrip.spec.ts +442 -0
- package/source/utils/paste-utils.spec.ts +128 -0
- package/source/utils/paste-utils.ts +52 -0
- package/source/utils/programming-language-helper.spec.ts +74 -0
- package/source/utils/programming-language-helper.ts +32 -0
- package/source/utils/prompt-assembly.spec.ts +221 -0
- package/source/utils/prompt-processor.ts +173 -0
- package/source/utils/tool-args-parser.spec.ts +136 -0
- package/source/utils/tool-args-parser.ts +54 -0
- package/source/utils/tool-cancellation.spec.ts +230 -0
- package/source/utils/tool-cancellation.ts +28 -0
- package/source/utils/tool-result-display.spec.tsx +469 -0
- package/source/utils/tool-result-display.tsx +90 -0
- package/source/utils/update-checker.spec.ts +383 -0
- package/source/utils/update-checker.ts +183 -0
- package/source/wizard/config-wizard.spec.tsx +103 -0
- package/source/wizard/config-wizard.tsx +382 -0
- package/source/wizard/steps/location-step.spec.tsx +186 -0
- package/source/wizard/steps/location-step.tsx +147 -0
- package/source/wizard/steps/mcp-step.spec.tsx +607 -0
- package/source/wizard/steps/mcp-step.tsx +632 -0
- package/source/wizard/steps/provider-step.spec.tsx +342 -0
- package/source/wizard/steps/provider-step.tsx +957 -0
- package/source/wizard/steps/summary-step.spec.tsx +749 -0
- package/source/wizard/steps/summary-step.tsx +228 -0
- package/source/wizard/templates/mcp-templates.spec.ts +613 -0
- package/source/wizard/templates/mcp-templates.ts +570 -0
- package/source/wizard/templates/provider-templates.spec.ts +152 -0
- package/source/wizard/templates/provider-templates.ts +485 -0
- package/source/wizard/utils/fetch-cloud-models.spec.ts +428 -0
- package/source/wizard/utils/fetch-cloud-models.ts +223 -0
- package/source/wizard/utils/fetch-local-models.spec.ts +297 -0
- package/source/wizard/utils/fetch-local-models.ts +192 -0
- package/source/wizard/validation-array.spec.ts +264 -0
- package/source/wizard/validation.spec.ts +373 -0
- package/source/wizard/validation.ts +232 -0
- 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,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
|
+
}
|