@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,289 @@
|
|
|
1
|
+
import type {ToolCall} from '@/types/index';
|
|
2
|
+
|
|
3
|
+
interface ParsedToolCall {
|
|
4
|
+
toolName: string;
|
|
5
|
+
parameters: Record<string, unknown>;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Parses XML-formatted tool calls from non-function-calling models
|
|
10
|
+
* Expected format: <tool_name><param1>value1</param1><param2>value2</param2></tool_name>
|
|
11
|
+
*/
|
|
12
|
+
export class XMLToolCallParser {
|
|
13
|
+
private static readonly TOOL_CALL_REGEX = /<(\w+)>(.*?)<\/\1>/gs;
|
|
14
|
+
private static readonly PARAMETER_REGEX = /<(\w+)>(.*?)<\/\1>/gs;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Extracts tool calls from text content containing XML-formatted tool calls
|
|
18
|
+
*/
|
|
19
|
+
static parseToolCalls(content: string): ParsedToolCall[] {
|
|
20
|
+
const toolCalls: ParsedToolCall[] = [];
|
|
21
|
+
let match;
|
|
22
|
+
|
|
23
|
+
// Handle content that might be wrapped in markdown code blocks
|
|
24
|
+
let processedContent = content;
|
|
25
|
+
const codeBlockMatch = content.match(/```(?:\w+)?\s*\n?([\s\S]*?)\n?```/);
|
|
26
|
+
if (codeBlockMatch && codeBlockMatch[1]) {
|
|
27
|
+
processedContent = codeBlockMatch[1].trim();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Remove <tool_call> wrapper tags if present
|
|
31
|
+
processedContent = processedContent.replace(/<\/?tool_call>/g, '').trim();
|
|
32
|
+
|
|
33
|
+
// Find all tool call blocks
|
|
34
|
+
this.TOOL_CALL_REGEX.lastIndex = 0; // Reset regex state
|
|
35
|
+
while ((match = this.TOOL_CALL_REGEX.exec(processedContent)) !== null) {
|
|
36
|
+
const [fullMatch, toolName, innerXml] = match;
|
|
37
|
+
|
|
38
|
+
// Skip if this is a generic "tool_call" tag that slipped through
|
|
39
|
+
if (toolName === 'tool_call') {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Validate that this is a properly formed tool call
|
|
44
|
+
if (!this.isValidToolCall(fullMatch, toolName)) {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const parameters = this.parseParameters(innerXml);
|
|
49
|
+
|
|
50
|
+
toolCalls.push({
|
|
51
|
+
toolName,
|
|
52
|
+
parameters,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return toolCalls;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Validates that a matched string is a proper tool call
|
|
61
|
+
* Rejects partial matches, malformed syntax, and invalid structures
|
|
62
|
+
*/
|
|
63
|
+
private static isValidToolCall(fullMatch: string, toolName: string): boolean {
|
|
64
|
+
// Reject common HTML tags that might be in model output
|
|
65
|
+
const htmlTags = [
|
|
66
|
+
'div',
|
|
67
|
+
'span',
|
|
68
|
+
'p',
|
|
69
|
+
'a',
|
|
70
|
+
'ul',
|
|
71
|
+
'ol',
|
|
72
|
+
'li',
|
|
73
|
+
'table',
|
|
74
|
+
'tr',
|
|
75
|
+
'td',
|
|
76
|
+
'th',
|
|
77
|
+
'thead',
|
|
78
|
+
'tbody',
|
|
79
|
+
'h1',
|
|
80
|
+
'h2',
|
|
81
|
+
'h3',
|
|
82
|
+
'h4',
|
|
83
|
+
'h5',
|
|
84
|
+
'h6',
|
|
85
|
+
'br',
|
|
86
|
+
'hr',
|
|
87
|
+
'strong',
|
|
88
|
+
'em',
|
|
89
|
+
'code',
|
|
90
|
+
'pre',
|
|
91
|
+
'blockquote',
|
|
92
|
+
'img',
|
|
93
|
+
'section',
|
|
94
|
+
'article',
|
|
95
|
+
'header',
|
|
96
|
+
'footer',
|
|
97
|
+
'nav',
|
|
98
|
+
'aside',
|
|
99
|
+
];
|
|
100
|
+
if (htmlTags.includes(toolName.toLowerCase())) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Check for malformed attribute-style syntax like <function=name> or <parameter=name>
|
|
105
|
+
if (fullMatch.includes('=')) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Check if the closing tag is properly formed
|
|
110
|
+
if (!fullMatch.endsWith(`</${toolName}>`)) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Extract inner content between opening and closing tags
|
|
115
|
+
const innerContent = fullMatch.substring(
|
|
116
|
+
toolName.length + 2,
|
|
117
|
+
fullMatch.length - (toolName.length + 3),
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
// Valid tool calls should contain parameter tags (other XML tags inside)
|
|
121
|
+
// This prevents matching on standalone parameter tags from malformed XML
|
|
122
|
+
const hasNestedTags = /<\w+>/.test(innerContent);
|
|
123
|
+
|
|
124
|
+
// Tool names should contain underscores (snake_case convention for tools)
|
|
125
|
+
// or be reasonably long compound words
|
|
126
|
+
const hasUnderscore = toolName.includes('_');
|
|
127
|
+
|
|
128
|
+
// Allow if it has nested tags OR follows naming convention
|
|
129
|
+
if (!hasNestedTags && !hasUnderscore) {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Parses parameters from inner XML content
|
|
138
|
+
*/
|
|
139
|
+
private static parseParameters(innerXml: string): Record<string, unknown> {
|
|
140
|
+
const parameters: Record<string, unknown> = {};
|
|
141
|
+
let match;
|
|
142
|
+
|
|
143
|
+
// Reset regex state
|
|
144
|
+
this.PARAMETER_REGEX.lastIndex = 0;
|
|
145
|
+
|
|
146
|
+
while ((match = this.PARAMETER_REGEX.exec(innerXml)) !== null) {
|
|
147
|
+
const [, paramName, paramValue] = match;
|
|
148
|
+
|
|
149
|
+
// Trim whitespace from parameter value
|
|
150
|
+
const trimmedValue = paramValue.trim();
|
|
151
|
+
|
|
152
|
+
// Try to parse as JSON for complex objects/arrays
|
|
153
|
+
try {
|
|
154
|
+
parameters[paramName] = JSON.parse(trimmedValue) as unknown;
|
|
155
|
+
} catch {
|
|
156
|
+
// If not valid JSON, use as string (preserving internal whitespace/newlines)
|
|
157
|
+
parameters[paramName] = trimmedValue;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return parameters;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Converts parsed tool calls to the standard ToolCall format
|
|
166
|
+
*/
|
|
167
|
+
static convertToToolCalls(parsedCalls: ParsedToolCall[]): ToolCall[] {
|
|
168
|
+
return parsedCalls.map((call, index) => ({
|
|
169
|
+
id: `xml_call_${index}`,
|
|
170
|
+
function: {
|
|
171
|
+
name: call.toolName,
|
|
172
|
+
arguments: call.parameters,
|
|
173
|
+
},
|
|
174
|
+
}));
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Removes XML tool call blocks from content, leaving only the text
|
|
179
|
+
*/
|
|
180
|
+
static removeToolCallsFromContent(content: string): string {
|
|
181
|
+
let cleanedContent = content;
|
|
182
|
+
|
|
183
|
+
// Remove all markdown code blocks that contain XML tool calls (using global flag)
|
|
184
|
+
cleanedContent = cleanedContent.replace(
|
|
185
|
+
/```(?:\w+)?\s*\n?([\s\S]*?)\n?```/g,
|
|
186
|
+
(match, blockContent: string) => {
|
|
187
|
+
if (blockContent) {
|
|
188
|
+
// Reset regex and check if this block contains XML tool calls
|
|
189
|
+
this.TOOL_CALL_REGEX.lastIndex = 0;
|
|
190
|
+
if (this.TOOL_CALL_REGEX.test(blockContent)) {
|
|
191
|
+
// This code block contains XML tool calls, remove it entirely
|
|
192
|
+
return '';
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// Keep blocks that don't contain XML tool calls
|
|
196
|
+
return match;
|
|
197
|
+
},
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
// Remove XML tool calls that aren't in code blocks
|
|
201
|
+
this.TOOL_CALL_REGEX.lastIndex = 0;
|
|
202
|
+
cleanedContent = cleanedContent.replace(this.TOOL_CALL_REGEX, '');
|
|
203
|
+
|
|
204
|
+
// Remove any <tool_call> wrapper tags that may be left behind
|
|
205
|
+
cleanedContent = cleanedContent.replace(/<\/?tool_call>/g, '');
|
|
206
|
+
|
|
207
|
+
// Clean up whitespace artifacts left by removed tool calls
|
|
208
|
+
cleanedContent = cleanedContent
|
|
209
|
+
// Remove trailing whitespace from each line
|
|
210
|
+
.replace(/[ \t]+$/gm, '')
|
|
211
|
+
// Collapse multiple spaces (but not at start of line for indentation)
|
|
212
|
+
.replace(/([^ \t\n]) {2,}/g, '$1 ')
|
|
213
|
+
// Remove lines that are only whitespace
|
|
214
|
+
.replace(/^[ \t]+$/gm, '')
|
|
215
|
+
// Collapse 2+ consecutive blank lines to a single blank line
|
|
216
|
+
.replace(/\n{3,}/g, '\n\n')
|
|
217
|
+
.trim();
|
|
218
|
+
|
|
219
|
+
return cleanedContent;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Checks if content contains XML-formatted tool calls
|
|
224
|
+
*/
|
|
225
|
+
static hasToolCalls(content: string): boolean {
|
|
226
|
+
// Use parseToolCalls with validation to ensure we only detect valid tool calls
|
|
227
|
+
const toolCalls = this.parseToolCalls(content);
|
|
228
|
+
return toolCalls.length > 0;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Detects malformed XML tool call attempts and returns error details
|
|
233
|
+
* Returns null if no malformed tool calls detected
|
|
234
|
+
*/
|
|
235
|
+
static detectMalformedToolCall(
|
|
236
|
+
content: string,
|
|
237
|
+
): {error: string; examples: string} | null {
|
|
238
|
+
// Common malformed patterns
|
|
239
|
+
const patterns = [
|
|
240
|
+
{
|
|
241
|
+
// [tool_use: name] or [Tool: name] syntax (common with some models like GLM)
|
|
242
|
+
regex: /\[(?:tool_use|Tool):\s*(\w+)\]/i,
|
|
243
|
+
error:
|
|
244
|
+
'Invalid syntax: [tool_use: name] or [Tool: name] format is not supported',
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
// <function=name> syntax
|
|
248
|
+
regex: /<function=(\w+)>/,
|
|
249
|
+
error: 'Invalid syntax: <function=name> is not supported',
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
// <parameter=name> syntax
|
|
253
|
+
regex: /<parameter=(\w+)>/,
|
|
254
|
+
error: 'Invalid syntax: <parameter=name> is not supported',
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
// Generic closing </parameter> without proper name
|
|
258
|
+
regex: /<parameter=\w+>[\s\S]*?<\/parameter>/,
|
|
259
|
+
error:
|
|
260
|
+
'Invalid parameter syntax: parameters must use named tags, not generic <parameter> wrapper',
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
// Generic closing </function> when <function=name> was used
|
|
264
|
+
regex: /<function=\w+>[\s\S]*?<\/function>/,
|
|
265
|
+
error:
|
|
266
|
+
'Invalid function syntax: use simple named tags, not <function=name> wrapper',
|
|
267
|
+
},
|
|
268
|
+
];
|
|
269
|
+
|
|
270
|
+
for (const pattern of patterns) {
|
|
271
|
+
const match = content.match(pattern.regex);
|
|
272
|
+
if (match) {
|
|
273
|
+
return {
|
|
274
|
+
error: pattern.error,
|
|
275
|
+
examples: this.getCorrectFormatExamples(),
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Generates correct format examples for error messages
|
|
285
|
+
*/
|
|
286
|
+
private static getCorrectFormatExamples(): string {
|
|
287
|
+
return `Please use the native tool calling format provided by the system. The tools are already available to you - call them directly using the function calling interface.`;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import {render} from 'ink-testing-library';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import {themes} from '../config/themes';
|
|
5
|
+
import {ThemeContext} from '../hooks/useTheme';
|
|
6
|
+
import {executeBashTool} from './execute-bash';
|
|
7
|
+
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// Test Helpers
|
|
10
|
+
// ============================================================================
|
|
11
|
+
|
|
12
|
+
console.log(`\nexecute-bash.spec.tsx – ${React.version}`);
|
|
13
|
+
|
|
14
|
+
// Create a mock theme provider for tests
|
|
15
|
+
function TestThemeProvider({children}: {children: React.ReactNode}) {
|
|
16
|
+
const themeContextValue = {
|
|
17
|
+
currentTheme: 'tokyo-night' as const,
|
|
18
|
+
colors: themes['tokyo-night'].colors,
|
|
19
|
+
setCurrentTheme: () => {},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<ThemeContext.Provider value={themeContextValue}>
|
|
24
|
+
{children}
|
|
25
|
+
</ThemeContext.Provider>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// ============================================================================
|
|
30
|
+
// Tests for ExecuteBashFormatter Component Rendering
|
|
31
|
+
// ============================================================================
|
|
32
|
+
|
|
33
|
+
test('ExecuteBashFormatter renders with command', t => {
|
|
34
|
+
const formatter = executeBashTool.formatter;
|
|
35
|
+
if (!formatter) {
|
|
36
|
+
t.fail('Formatter is not defined');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const element = formatter({command: 'echo "hello"'}, 'hello');
|
|
41
|
+
const {lastFrame} = render(<TestThemeProvider>{element}</TestThemeProvider>);
|
|
42
|
+
|
|
43
|
+
const output = lastFrame();
|
|
44
|
+
t.truthy(output);
|
|
45
|
+
t.regex(output!, /execute_bash/);
|
|
46
|
+
t.regex(output!, /echo "hello"/);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('ExecuteBashFormatter displays output size', t => {
|
|
50
|
+
const formatter = executeBashTool.formatter;
|
|
51
|
+
if (!formatter) {
|
|
52
|
+
t.fail('Formatter is not defined');
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const result = 'test output';
|
|
57
|
+
const element = formatter({command: 'echo test'}, result);
|
|
58
|
+
const {lastFrame} = render(<TestThemeProvider>{element}</TestThemeProvider>);
|
|
59
|
+
|
|
60
|
+
const output = lastFrame();
|
|
61
|
+
t.truthy(output);
|
|
62
|
+
t.regex(output!, /characters/);
|
|
63
|
+
t.regex(output!, /tokens/);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test('ExecuteBashFormatter renders without result', t => {
|
|
67
|
+
const formatter = executeBashTool.formatter;
|
|
68
|
+
if (!formatter) {
|
|
69
|
+
t.fail('Formatter is not defined');
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const element = formatter({command: 'ls'});
|
|
74
|
+
const {lastFrame} = render(<TestThemeProvider>{element}</TestThemeProvider>);
|
|
75
|
+
|
|
76
|
+
const output = lastFrame();
|
|
77
|
+
t.truthy(output);
|
|
78
|
+
t.regex(output!, /execute_bash/);
|
|
79
|
+
t.regex(output!, /ls/);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test('ExecuteBashFormatter handles complex commands', t => {
|
|
83
|
+
const formatter = executeBashTool.formatter;
|
|
84
|
+
if (!formatter) {
|
|
85
|
+
t.fail('Formatter is not defined');
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const command = 'find . -name "*.ts" | grep -v node_modules';
|
|
90
|
+
const element = formatter({command}, 'file1.ts\nfile2.ts');
|
|
91
|
+
const {lastFrame} = render(<TestThemeProvider>{element}</TestThemeProvider>);
|
|
92
|
+
|
|
93
|
+
const output = lastFrame();
|
|
94
|
+
t.truthy(output);
|
|
95
|
+
t.regex(output!, /find/);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// ============================================================================
|
|
99
|
+
// Tests for execute_bash Tool Handler - Basic Functionality
|
|
100
|
+
// ============================================================================
|
|
101
|
+
|
|
102
|
+
test('execute_bash runs simple echo command', async t => {
|
|
103
|
+
const result = await executeBashTool.tool.execute!(
|
|
104
|
+
{command: 'echo "test output"'},
|
|
105
|
+
{toolCallId: 'test', messages: []},
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
t.truthy(result);
|
|
109
|
+
t.true(result.includes('test output'));
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test('execute_bash returns output from ls command', async t => {
|
|
113
|
+
const result = await executeBashTool.tool.execute!(
|
|
114
|
+
{command: 'ls'},
|
|
115
|
+
{toolCallId: 'test', messages: []},
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
t.truthy(result);
|
|
119
|
+
t.is(typeof result, 'string');
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
test('execute_bash handles command with pipes', async t => {
|
|
123
|
+
const result = await executeBashTool.tool.execute!(
|
|
124
|
+
{
|
|
125
|
+
command: 'echo "line1\nline2\nline3" | grep line2',
|
|
126
|
+
},
|
|
127
|
+
{toolCallId: 'test', messages: []},
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
t.truthy(result);
|
|
131
|
+
t.true(result.includes('line2'));
|
|
132
|
+
t.false(result.includes('line1'));
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test('execute_bash handles command with redirects', async t => {
|
|
136
|
+
const result = await executeBashTool.tool.execute!(
|
|
137
|
+
{
|
|
138
|
+
command: 'echo "test" 2>&1',
|
|
139
|
+
},
|
|
140
|
+
{toolCallId: 'test', messages: []},
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
t.truthy(result);
|
|
144
|
+
t.true(result.includes('test'));
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test('execute_bash preserves multiline output', async t => {
|
|
148
|
+
const result = await executeBashTool.tool.execute!(
|
|
149
|
+
{
|
|
150
|
+
command: 'echo "line1"; echo "line2"; echo "line3"',
|
|
151
|
+
},
|
|
152
|
+
{toolCallId: 'test', messages: []},
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
t.truthy(result);
|
|
156
|
+
t.true(result.includes('line1'));
|
|
157
|
+
t.true(result.includes('line2'));
|
|
158
|
+
t.true(result.includes('line3'));
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// ============================================================================
|
|
162
|
+
// Tests for execute_bash Tool Handler - Error Handling
|
|
163
|
+
// ============================================================================
|
|
164
|
+
|
|
165
|
+
test('execute_bash captures stderr output', async t => {
|
|
166
|
+
const result = await executeBashTool.tool.execute!(
|
|
167
|
+
{
|
|
168
|
+
command: 'echo "error message" >&2',
|
|
169
|
+
},
|
|
170
|
+
{toolCallId: 'test', messages: []},
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
t.truthy(result);
|
|
174
|
+
// Should include STDERR label when stderr is present
|
|
175
|
+
t.true(result.includes('STDERR') || result.includes('error message'));
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
test('execute_bash handles command not found', async t => {
|
|
179
|
+
const result = await executeBashTool.tool.execute!(
|
|
180
|
+
{
|
|
181
|
+
command: 'nonexistentcommand12345',
|
|
182
|
+
},
|
|
183
|
+
{toolCallId: 'test', messages: []},
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
t.truthy(result);
|
|
187
|
+
// Should capture the error output
|
|
188
|
+
t.true(
|
|
189
|
+
result.includes('not found') ||
|
|
190
|
+
result.includes('command not found') ||
|
|
191
|
+
result.includes('STDERR'),
|
|
192
|
+
);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
test('execute_bash handles syntax errors', async t => {
|
|
196
|
+
const result = await executeBashTool.tool.execute!(
|
|
197
|
+
{
|
|
198
|
+
command: 'echo "unclosed quote',
|
|
199
|
+
},
|
|
200
|
+
{toolCallId: 'test', messages: []},
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
t.truthy(result);
|
|
204
|
+
// Should capture the syntax error
|
|
205
|
+
t.is(typeof result, 'string');
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// ============================================================================
|
|
209
|
+
// Tests for execute_bash Tool Handler - Output Truncation
|
|
210
|
+
// ============================================================================
|
|
211
|
+
|
|
212
|
+
test('execute_bash truncates long output to 2000 characters', async t => {
|
|
213
|
+
// Generate output longer than 2000 characters
|
|
214
|
+
// Use POSIX-compatible syntax (seq instead of bash brace expansion)
|
|
215
|
+
const longCommand =
|
|
216
|
+
'seq 1 100 | while read i; do echo "This is a long line of text that repeats many times"; done';
|
|
217
|
+
const result = await executeBashTool.tool.execute!(
|
|
218
|
+
{command: longCommand},
|
|
219
|
+
{toolCallId: 'test', messages: []},
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
t.truthy(result);
|
|
223
|
+
// Should be truncated to around 2000 characters
|
|
224
|
+
t.true(
|
|
225
|
+
result.length <= 2100,
|
|
226
|
+
`Output length ${result.length} should be <= 2100`,
|
|
227
|
+
);
|
|
228
|
+
// Should include truncation message
|
|
229
|
+
t.true(result.includes('[Output truncated'));
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
test('execute_bash does not truncate short output', async t => {
|
|
233
|
+
const result = await executeBashTool.tool.execute!(
|
|
234
|
+
{
|
|
235
|
+
command: 'echo "short output"',
|
|
236
|
+
},
|
|
237
|
+
{toolCallId: 'test', messages: []},
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
t.truthy(result);
|
|
241
|
+
t.false(result.includes('[Output truncated'));
|
|
242
|
+
t.true(result.includes('short output'));
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
test('execute_bash returns plain string not JSON', async t => {
|
|
246
|
+
const result = await executeBashTool.tool.execute!(
|
|
247
|
+
{command: 'echo "test"'},
|
|
248
|
+
{toolCallId: 'test', messages: []},
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
t.truthy(result);
|
|
252
|
+
t.is(typeof result, 'string');
|
|
253
|
+
// Should NOT be JSON with fullOutput and llmContext
|
|
254
|
+
t.false(result.includes('fullOutput'));
|
|
255
|
+
t.false(result.includes('llmContext'));
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
// ============================================================================
|
|
259
|
+
// Tests for execute_bash Tool Handler - Special Characters
|
|
260
|
+
// ============================================================================
|
|
261
|
+
|
|
262
|
+
test('execute_bash handles special characters in output', async t => {
|
|
263
|
+
const result = await executeBashTool.tool.execute!(
|
|
264
|
+
{
|
|
265
|
+
command: 'echo "special: $@#%^&*()"',
|
|
266
|
+
},
|
|
267
|
+
{toolCallId: 'test', messages: []},
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
t.truthy(result);
|
|
271
|
+
t.true(result.includes('special'));
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
test('execute_bash handles quotes in commands', async t => {
|
|
275
|
+
const result = await executeBashTool.tool.execute!(
|
|
276
|
+
{
|
|
277
|
+
command: 'echo "He said \\"hello\\""',
|
|
278
|
+
},
|
|
279
|
+
{toolCallId: 'test', messages: []},
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
t.truthy(result);
|
|
283
|
+
t.true(result.includes('said'));
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
test('execute_bash handles newlines in command', async t => {
|
|
287
|
+
const result = await executeBashTool.tool.execute!(
|
|
288
|
+
{
|
|
289
|
+
command: 'echo "line1\nline2"',
|
|
290
|
+
},
|
|
291
|
+
{toolCallId: 'test', messages: []},
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
t.truthy(result);
|
|
295
|
+
t.is(typeof result, 'string');
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
// ============================================================================
|
|
299
|
+
// Tests for execute_bash Tool Configuration
|
|
300
|
+
// ============================================================================
|
|
301
|
+
|
|
302
|
+
test('execute_bash tool has correct name', t => {
|
|
303
|
+
t.is(executeBashTool.name, 'execute_bash');
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
test('execute_bash tool requires confirmation', t => {
|
|
307
|
+
// Execute bash should require confirmation for security
|
|
308
|
+
t.not(executeBashTool.tool.needsApproval, false);
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
test('execute_bash tool has handler function', t => {
|
|
312
|
+
t.is(typeof executeBashTool.tool.execute, 'function');
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
test('execute_bash tool has formatter function', t => {
|
|
316
|
+
t.is(typeof executeBashTool.formatter, 'function');
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
// ============================================================================
|
|
320
|
+
// Tests for execute_bash Tool Handler - Edge Cases
|
|
321
|
+
// ============================================================================
|
|
322
|
+
|
|
323
|
+
test('execute_bash handles empty command output', async t => {
|
|
324
|
+
const result = await executeBashTool.tool.execute!(
|
|
325
|
+
{command: 'true'},
|
|
326
|
+
{toolCallId: 'test', messages: []},
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
// Empty output returns empty string, which is falsy but valid
|
|
330
|
+
t.is(typeof result, 'string');
|
|
331
|
+
// Empty output is still a valid string
|
|
332
|
+
t.true(result.length >= 0);
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
test('execute_bash handles commands with no output', async t => {
|
|
336
|
+
const result = await executeBashTool.tool.execute!(
|
|
337
|
+
{command: ':'},
|
|
338
|
+
{toolCallId: 'test', messages: []},
|
|
339
|
+
);
|
|
340
|
+
|
|
341
|
+
// Empty output returns empty string, which is falsy but valid
|
|
342
|
+
t.is(typeof result, 'string');
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
test('execute_bash handles whitespace-only output', async t => {
|
|
346
|
+
const result = await executeBashTool.tool.execute!(
|
|
347
|
+
{command: 'echo " "'},
|
|
348
|
+
{toolCallId: 'test', messages: []},
|
|
349
|
+
);
|
|
350
|
+
|
|
351
|
+
t.truthy(result);
|
|
352
|
+
t.is(typeof result, 'string');
|
|
353
|
+
});
|