@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,662 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import {XMLToolCallParser} from './xml-parser';
|
|
3
|
+
|
|
4
|
+
console.log(`\nxml-parser.spec.ts`);
|
|
5
|
+
|
|
6
|
+
// Basic parsing tests
|
|
7
|
+
test('parseToolCalls - parses simple tool call', t => {
|
|
8
|
+
const content = '<read_file><path>/test/file.txt</path></read_file>';
|
|
9
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
10
|
+
|
|
11
|
+
t.is(result.length, 1);
|
|
12
|
+
t.is(result[0].toolName, 'read_file');
|
|
13
|
+
t.deepEqual(result[0].parameters, {path: '/test/file.txt'});
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test('parseToolCalls - parses multiple parameters', t => {
|
|
17
|
+
const content =
|
|
18
|
+
'<create_file><path>/test/new.txt</path><content>Hello World</content><mode>0644</mode></create_file>';
|
|
19
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
20
|
+
|
|
21
|
+
t.is(result.length, 1);
|
|
22
|
+
t.is(result[0].toolName, 'create_file');
|
|
23
|
+
t.deepEqual(result[0].parameters, {
|
|
24
|
+
path: '/test/new.txt',
|
|
25
|
+
content: 'Hello World',
|
|
26
|
+
mode: '0644',
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('parseToolCalls - parses multiple tool calls', t => {
|
|
31
|
+
const content = `<read_file><path>/test/file1.txt</path></read_file>
|
|
32
|
+
<read_file><path>/test/file2.txt</path></read_file>`;
|
|
33
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
34
|
+
|
|
35
|
+
t.is(result.length, 2);
|
|
36
|
+
t.is(result[0].toolName, 'read_file');
|
|
37
|
+
t.deepEqual(result[0].parameters, {path: '/test/file1.txt'});
|
|
38
|
+
t.is(result[1].toolName, 'read_file');
|
|
39
|
+
t.deepEqual(result[1].parameters, {path: '/test/file2.txt'});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('parseToolCalls - handles empty parameters', t => {
|
|
43
|
+
const content = '<list_files></list_files>';
|
|
44
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
45
|
+
|
|
46
|
+
t.is(result.length, 1);
|
|
47
|
+
t.is(result[0].toolName, 'list_files');
|
|
48
|
+
t.deepEqual(result[0].parameters, {});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test('parseToolCalls - handles empty parameter values', t => {
|
|
52
|
+
const content = '<search><query></query><path>/test</path></search>';
|
|
53
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
54
|
+
|
|
55
|
+
t.is(result.length, 1);
|
|
56
|
+
t.is(result[0].toolName, 'search');
|
|
57
|
+
t.deepEqual(result[0].parameters, {query: '', path: '/test'});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// JSON parameter tests
|
|
61
|
+
test('parseToolCalls - parses JSON array parameters', t => {
|
|
62
|
+
const content =
|
|
63
|
+
'<batch_read><files>["file1.txt", "file2.txt", "file3.txt"]</files></batch_read>';
|
|
64
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
65
|
+
|
|
66
|
+
t.is(result.length, 1);
|
|
67
|
+
t.is(result[0].toolName, 'batch_read');
|
|
68
|
+
t.deepEqual(result[0].parameters, {
|
|
69
|
+
files: ['file1.txt', 'file2.txt', 'file3.txt'],
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test('parseToolCalls - parses JSON object parameters', t => {
|
|
74
|
+
const content =
|
|
75
|
+
'<configure><options>{"timeout": 5000, "retries": 3}</options></configure>';
|
|
76
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
77
|
+
|
|
78
|
+
t.is(result.length, 1);
|
|
79
|
+
t.is(result[0].toolName, 'configure');
|
|
80
|
+
t.deepEqual(result[0].parameters, {
|
|
81
|
+
options: {timeout: 5000, retries: 3},
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('parseToolCalls - parses JSON boolean parameters', t => {
|
|
86
|
+
const content =
|
|
87
|
+
'<set_flag><enabled>true</enabled><verbose>false</verbose></set_flag>';
|
|
88
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
89
|
+
|
|
90
|
+
t.is(result.length, 1);
|
|
91
|
+
t.is(result[0].toolName, 'set_flag');
|
|
92
|
+
t.deepEqual(result[0].parameters, {enabled: true, verbose: false});
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test('parseToolCalls - parses JSON number parameters', t => {
|
|
96
|
+
const content = '<calculate><x>42</x><y>3.14</y><z>-10</z></calculate>';
|
|
97
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
98
|
+
|
|
99
|
+
t.is(result.length, 1);
|
|
100
|
+
t.is(result[0].toolName, 'calculate');
|
|
101
|
+
t.deepEqual(result[0].parameters, {x: 42, y: 3.14, z: -10});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test('parseToolCalls - treats invalid JSON as string', t => {
|
|
105
|
+
const content = '<test><invalid>{not valid json}</invalid></test>';
|
|
106
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
107
|
+
|
|
108
|
+
t.is(result.length, 1);
|
|
109
|
+
t.is(result[0].toolName, 'test');
|
|
110
|
+
t.deepEqual(result[0].parameters, {invalid: '{not valid json}'});
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Markdown code block tests
|
|
114
|
+
test('parseToolCalls - extracts tool calls from markdown code blocks', t => {
|
|
115
|
+
const content =
|
|
116
|
+
'```xml\n<read_file><path>/test/file.txt</path></read_file>\n```';
|
|
117
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
118
|
+
|
|
119
|
+
t.is(result.length, 1);
|
|
120
|
+
t.is(result[0].toolName, 'read_file');
|
|
121
|
+
t.deepEqual(result[0].parameters, {path: '/test/file.txt'});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test('parseToolCalls - handles code blocks without language identifier', t => {
|
|
125
|
+
const content =
|
|
126
|
+
'```\n<read_file><path>/test/file.txt</path></read_file>\n```';
|
|
127
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
128
|
+
|
|
129
|
+
t.is(result.length, 1);
|
|
130
|
+
t.is(result[0].toolName, 'read_file');
|
|
131
|
+
t.deepEqual(result[0].parameters, {path: '/test/file.txt'});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test('parseToolCalls - handles code blocks with various languages', t => {
|
|
135
|
+
const content =
|
|
136
|
+
'```typescript\n<read_file><path>/test/file.txt</path></read_file>\n```';
|
|
137
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
138
|
+
|
|
139
|
+
t.is(result.length, 1);
|
|
140
|
+
t.is(result[0].toolName, 'read_file');
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// tool_call wrapper tests
|
|
144
|
+
test('parseToolCalls - removes tool_call wrapper tags', t => {
|
|
145
|
+
const content =
|
|
146
|
+
'<tool_call><read_file><path>/test/file.txt</path></read_file></tool_call>';
|
|
147
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
148
|
+
|
|
149
|
+
t.is(result.length, 1);
|
|
150
|
+
t.is(result[0].toolName, 'read_file');
|
|
151
|
+
t.deepEqual(result[0].parameters, {path: '/test/file.txt'});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
test('parseToolCalls - skips tool_call tags when found as top-level match', t => {
|
|
155
|
+
const content =
|
|
156
|
+
'<tool_call><read_file><path>/test/file.txt</path></read_file></tool_call>';
|
|
157
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
158
|
+
|
|
159
|
+
// Should parse read_file, not tool_call
|
|
160
|
+
t.is(result.length, 1);
|
|
161
|
+
t.is(result[0].toolName, 'read_file');
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// Special characters and content tests
|
|
165
|
+
test('parseToolCalls - handles multiline content', t => {
|
|
166
|
+
const content = `<create_file>
|
|
167
|
+
<path>/test/file.txt</path>
|
|
168
|
+
<content>Line 1
|
|
169
|
+
Line 2
|
|
170
|
+
Line 3</content>
|
|
171
|
+
</create_file>`;
|
|
172
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
173
|
+
|
|
174
|
+
t.is(result.length, 1);
|
|
175
|
+
t.is(result[0].toolName, 'create_file');
|
|
176
|
+
t.is(result[0].parameters.path, '/test/file.txt');
|
|
177
|
+
t.is(result[0].parameters.content, 'Line 1\nLine 2\nLine 3');
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
test('parseToolCalls - handles special characters in content', t => {
|
|
181
|
+
const content =
|
|
182
|
+
'<execute_bash><command>echo "Hello & goodbye" | grep -v "test"</command></execute_bash>';
|
|
183
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
184
|
+
|
|
185
|
+
t.is(result.length, 1);
|
|
186
|
+
t.is(result[0].toolName, 'execute_bash');
|
|
187
|
+
t.deepEqual(result[0].parameters, {
|
|
188
|
+
command: 'echo "Hello & goodbye" | grep -v "test"',
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
test('parseToolCalls - handles XML-like content in parameters', t => {
|
|
193
|
+
const content =
|
|
194
|
+
'<create_file><content><div>HTML content</div></content></create_file>';
|
|
195
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
196
|
+
|
|
197
|
+
t.is(result.length, 1);
|
|
198
|
+
t.is(result[0].toolName, 'create_file');
|
|
199
|
+
// Should capture the innermost match first
|
|
200
|
+
t.truthy(result[0].parameters.content);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
test('parseToolCalls - handles escaped characters', t => {
|
|
204
|
+
const content = '<test><value><tag></value></test>';
|
|
205
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
206
|
+
|
|
207
|
+
t.is(result.length, 1);
|
|
208
|
+
t.is(result[0].toolName, 'test');
|
|
209
|
+
t.deepEqual(result[0].parameters, {value: '<tag>'});
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
// Edge cases
|
|
213
|
+
test('parseToolCalls - returns empty array for no tool calls', t => {
|
|
214
|
+
const content = 'Just some regular text without any tool calls';
|
|
215
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
216
|
+
|
|
217
|
+
t.deepEqual(result, []);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
test('parseToolCalls - handles empty string', t => {
|
|
221
|
+
const content = '';
|
|
222
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
223
|
+
|
|
224
|
+
t.deepEqual(result, []);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
test('parseToolCalls - handles whitespace-only content', t => {
|
|
228
|
+
const content = ' \n\t\n ';
|
|
229
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
230
|
+
|
|
231
|
+
t.deepEqual(result, []);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
test('parseToolCalls - handles unclosed tags gracefully', t => {
|
|
235
|
+
const content = '<read_file><path>/test/file.txt</path>';
|
|
236
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
237
|
+
|
|
238
|
+
// Should not match incomplete XML
|
|
239
|
+
t.deepEqual(result, []);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
test('parseToolCalls - handles mismatched tags gracefully', t => {
|
|
243
|
+
const content = '<read_file><path>/test/file.txt</wrong_close></read_file>';
|
|
244
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
245
|
+
|
|
246
|
+
// Regex should still match the outer tags
|
|
247
|
+
t.is(result.length, 1);
|
|
248
|
+
t.is(result[0].toolName, 'read_file');
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
test('parseToolCalls - handles nested tool names', t => {
|
|
252
|
+
// Parameters can have same name as parent tool
|
|
253
|
+
const content = '<read_file><read_file>nested_value</read_file></read_file>';
|
|
254
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
255
|
+
|
|
256
|
+
// Should parse the outer read_file
|
|
257
|
+
t.truthy(result.length > 0);
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
test('parseToolCalls - handles tool names with underscores and numbers', t => {
|
|
261
|
+
const content = '<tool_name_123><param_1>value</param_1></tool_name_123>';
|
|
262
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
263
|
+
|
|
264
|
+
t.is(result.length, 1);
|
|
265
|
+
t.is(result[0].toolName, 'tool_name_123');
|
|
266
|
+
t.deepEqual(result[0].parameters, {param_1: 'value'});
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
test('parseToolCalls - handles case sensitivity', t => {
|
|
270
|
+
const content = '<ReadFile><Path>/test/file.txt</Path></ReadFile>';
|
|
271
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
272
|
+
|
|
273
|
+
t.is(result.length, 1);
|
|
274
|
+
t.is(result[0].toolName, 'ReadFile');
|
|
275
|
+
t.deepEqual(result[0].parameters, {Path: '/test/file.txt'});
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
// convertToToolCalls tests
|
|
279
|
+
test('convertToToolCalls - converts parsed calls to ToolCall format', t => {
|
|
280
|
+
const parsed = [
|
|
281
|
+
{toolName: 'read_file', parameters: {path: '/test/file.txt'}},
|
|
282
|
+
{toolName: 'create_file', parameters: {path: '/new.txt', content: 'test'}},
|
|
283
|
+
];
|
|
284
|
+
|
|
285
|
+
const result = XMLToolCallParser.convertToToolCalls(parsed);
|
|
286
|
+
|
|
287
|
+
t.is(result.length, 2);
|
|
288
|
+
t.is(result[0].id, 'xml_call_0');
|
|
289
|
+
t.is(result[0].function.name, 'read_file');
|
|
290
|
+
t.deepEqual(result[0].function.arguments, {path: '/test/file.txt'});
|
|
291
|
+
t.is(result[1].id, 'xml_call_1');
|
|
292
|
+
t.is(result[1].function.name, 'create_file');
|
|
293
|
+
t.deepEqual(result[1].function.arguments, {
|
|
294
|
+
path: '/new.txt',
|
|
295
|
+
content: 'test',
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
test('convertToToolCalls - generates unique IDs', t => {
|
|
300
|
+
const parsed = [
|
|
301
|
+
{toolName: 'tool1', parameters: {}},
|
|
302
|
+
{toolName: 'tool2', parameters: {}},
|
|
303
|
+
{toolName: 'tool3', parameters: {}},
|
|
304
|
+
];
|
|
305
|
+
|
|
306
|
+
const result = XMLToolCallParser.convertToToolCalls(parsed);
|
|
307
|
+
|
|
308
|
+
const ids = result.map(call => call.id);
|
|
309
|
+
const uniqueIds = new Set(ids);
|
|
310
|
+
t.is(ids.length, uniqueIds.size);
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
// removeToolCallsFromContent tests
|
|
314
|
+
test('removeToolCallsFromContent - removes tool calls from plain text', t => {
|
|
315
|
+
const content = `Here is some text
|
|
316
|
+
<read_file><path>/test/file.txt</path></read_file>
|
|
317
|
+
And some more text`;
|
|
318
|
+
|
|
319
|
+
const result = XMLToolCallParser.removeToolCallsFromContent(content);
|
|
320
|
+
|
|
321
|
+
t.is(result, 'Here is some text\n\nAnd some more text');
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
test('removeToolCallsFromContent - removes code blocks containing tool calls', t => {
|
|
325
|
+
const content = `Some text
|
|
326
|
+
\`\`\`xml
|
|
327
|
+
<read_file><path>/test/file.txt</path></read_file>
|
|
328
|
+
\`\`\`
|
|
329
|
+
More text`;
|
|
330
|
+
|
|
331
|
+
const result = XMLToolCallParser.removeToolCallsFromContent(content);
|
|
332
|
+
|
|
333
|
+
t.is(result, 'Some text\n\nMore text');
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
test('removeToolCallsFromContent - keeps code blocks without tool calls', t => {
|
|
337
|
+
const content = `Some text
|
|
338
|
+
\`\`\`javascript
|
|
339
|
+
const x = 42;
|
|
340
|
+
\`\`\`
|
|
341
|
+
More text`;
|
|
342
|
+
|
|
343
|
+
const result = XMLToolCallParser.removeToolCallsFromContent(content);
|
|
344
|
+
|
|
345
|
+
t.true(result.includes('const x = 42;'));
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
test('removeToolCallsFromContent - removes multiple tool calls', t => {
|
|
349
|
+
const content = `Text
|
|
350
|
+
<read_file><path>/file1.txt</path></read_file>
|
|
351
|
+
Middle text
|
|
352
|
+
<read_file><path>/file2.txt</path></read_file>
|
|
353
|
+
End text`;
|
|
354
|
+
|
|
355
|
+
const result = XMLToolCallParser.removeToolCallsFromContent(content);
|
|
356
|
+
|
|
357
|
+
t.false(result.includes('<read_file>'));
|
|
358
|
+
t.true(result.includes('Text'));
|
|
359
|
+
t.true(result.includes('Middle text'));
|
|
360
|
+
t.true(result.includes('End text'));
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
test('removeToolCallsFromContent - removes tool_call wrappers', t => {
|
|
364
|
+
const content = `Text
|
|
365
|
+
<tool_call><read_file><path>/test.txt</path></read_file></tool_call>
|
|
366
|
+
More text`;
|
|
367
|
+
|
|
368
|
+
const result = XMLToolCallParser.removeToolCallsFromContent(content);
|
|
369
|
+
|
|
370
|
+
t.false(result.includes('<tool_call>'));
|
|
371
|
+
t.false(result.includes('<read_file>'));
|
|
372
|
+
t.true(result.includes('Text'));
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
test('removeToolCallsFromContent - cleans up excessive whitespace', t => {
|
|
376
|
+
const content = `Line 1
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
<read_file><path>/test.txt</path></read_file>
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
Line 2`;
|
|
383
|
+
|
|
384
|
+
const result = XMLToolCallParser.removeToolCallsFromContent(content);
|
|
385
|
+
|
|
386
|
+
// Should reduce multiple newlines to double newlines
|
|
387
|
+
t.false(result.includes('\n\n\n'));
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
test('removeToolCallsFromContent - handles empty content', t => {
|
|
391
|
+
const content = '';
|
|
392
|
+
const result = XMLToolCallParser.removeToolCallsFromContent(content);
|
|
393
|
+
|
|
394
|
+
t.is(result, '');
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
test('removeToolCallsFromContent - handles content with only tool calls', t => {
|
|
398
|
+
const content = '<read_file><path>/test.txt</path></read_file>';
|
|
399
|
+
const result = XMLToolCallParser.removeToolCallsFromContent(content);
|
|
400
|
+
|
|
401
|
+
t.is(result, '');
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
// hasToolCalls tests
|
|
405
|
+
test('hasToolCalls - returns true for content with tool calls', t => {
|
|
406
|
+
const content = '<read_file><path>/test/file.txt</path></read_file>';
|
|
407
|
+
const result = XMLToolCallParser.hasToolCalls(content);
|
|
408
|
+
|
|
409
|
+
t.true(result);
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
test('hasToolCalls - returns true for tool calls in code blocks', t => {
|
|
413
|
+
const content =
|
|
414
|
+
'```\n<read_file><path>/test/file.txt</path></read_file>\n```';
|
|
415
|
+
const result = XMLToolCallParser.hasToolCalls(content);
|
|
416
|
+
|
|
417
|
+
t.true(result);
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
test('hasToolCalls - returns false for plain text', t => {
|
|
421
|
+
const content = 'Just some regular text';
|
|
422
|
+
const result = XMLToolCallParser.hasToolCalls(content);
|
|
423
|
+
|
|
424
|
+
t.false(result);
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
test('hasToolCalls - returns false for empty string', t => {
|
|
428
|
+
const content = '';
|
|
429
|
+
const result = XMLToolCallParser.hasToolCalls(content);
|
|
430
|
+
|
|
431
|
+
t.false(result);
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
test('hasToolCalls - returns false for incomplete XML', t => {
|
|
435
|
+
const content = '<read_file><path>/test';
|
|
436
|
+
const result = XMLToolCallParser.hasToolCalls(content);
|
|
437
|
+
|
|
438
|
+
t.false(result);
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
// detectMalformedToolCall tests
|
|
442
|
+
test('detectMalformedToolCall - detects [tool_use: name] syntax', t => {
|
|
443
|
+
const content = '[tool_use: read_file]';
|
|
444
|
+
const result = XMLToolCallParser.detectMalformedToolCall(content);
|
|
445
|
+
|
|
446
|
+
t.truthy(result);
|
|
447
|
+
t.true(result!.error.includes('[tool_use: name]'));
|
|
448
|
+
t.true(result!.examples.includes('native tool calling'));
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
test('detectMalformedToolCall - detects [Tool: name] syntax', t => {
|
|
452
|
+
const content = '[Tool: read_file]';
|
|
453
|
+
const result = XMLToolCallParser.detectMalformedToolCall(content);
|
|
454
|
+
|
|
455
|
+
t.truthy(result);
|
|
456
|
+
t.true(result!.error.includes('[tool_use: name]'));
|
|
457
|
+
t.true(result!.examples.includes('native tool calling'));
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
test('detectMalformedToolCall - detects [Tool: name] in context', t => {
|
|
461
|
+
const content =
|
|
462
|
+
'Let me read the file for you.\n\n[Tool: read_file]\nThe file contains...';
|
|
463
|
+
const result = XMLToolCallParser.detectMalformedToolCall(content);
|
|
464
|
+
|
|
465
|
+
t.truthy(result);
|
|
466
|
+
t.true(result!.error.includes('[tool_use: name]'));
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
test('detectMalformedToolCall - detects <function=name> syntax', t => {
|
|
470
|
+
const content = '<function=read_file><path>/test.txt</path></function>';
|
|
471
|
+
const result = XMLToolCallParser.detectMalformedToolCall(content);
|
|
472
|
+
|
|
473
|
+
t.truthy(result);
|
|
474
|
+
t.true(result!.error.includes('<function=name>'));
|
|
475
|
+
t.true(result!.examples.includes('native tool calling'));
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
test('detectMalformedToolCall - detects <parameter=name> syntax', t => {
|
|
479
|
+
const content =
|
|
480
|
+
'<read_file><parameter=path>/test.txt</parameter></read_file>';
|
|
481
|
+
const result = XMLToolCallParser.detectMalformedToolCall(content);
|
|
482
|
+
|
|
483
|
+
t.truthy(result);
|
|
484
|
+
t.true(result!.error.includes('<parameter=name>'));
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
test('detectMalformedToolCall - detects generic </parameter> closing tag', t => {
|
|
488
|
+
const content =
|
|
489
|
+
'<read_file><parameter=path>/test.txt</parameter></read_file>';
|
|
490
|
+
const result = XMLToolCallParser.detectMalformedToolCall(content);
|
|
491
|
+
|
|
492
|
+
t.truthy(result);
|
|
493
|
+
t.truthy(result!.error);
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
test('detectMalformedToolCall - detects generic </function> closing tag', t => {
|
|
497
|
+
const content = '<function=read_file><path>/test.txt</path></function>';
|
|
498
|
+
const result = XMLToolCallParser.detectMalformedToolCall(content);
|
|
499
|
+
|
|
500
|
+
t.truthy(result);
|
|
501
|
+
t.truthy(result!.error);
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
test('detectMalformedToolCall - returns null for valid XML', t => {
|
|
505
|
+
const content = '<read_file><path>/test.txt</path></read_file>';
|
|
506
|
+
const result = XMLToolCallParser.detectMalformedToolCall(content);
|
|
507
|
+
|
|
508
|
+
t.is(result, null);
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
test('detectMalformedToolCall - returns null for plain text', t => {
|
|
512
|
+
const content = 'Just regular text';
|
|
513
|
+
const result = XMLToolCallParser.detectMalformedToolCall(content);
|
|
514
|
+
|
|
515
|
+
t.is(result, null);
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
test('detectMalformedToolCall - includes helpful examples in error', t => {
|
|
519
|
+
const content = '<function=test><param>value</param></function>';
|
|
520
|
+
const result = XMLToolCallParser.detectMalformedToolCall(content);
|
|
521
|
+
|
|
522
|
+
t.truthy(result);
|
|
523
|
+
t.true(result!.examples.includes('native tool calling'));
|
|
524
|
+
t.true(result!.examples.includes('function calling interface'));
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
// Complex integration tests
|
|
528
|
+
test('full workflow - parse, convert, and extract multiple tool calls', t => {
|
|
529
|
+
const content = `Let me help you with that.
|
|
530
|
+
|
|
531
|
+
\`\`\`xml
|
|
532
|
+
<read_file><path>/src/app.ts</path></read_file>
|
|
533
|
+
<read_file><path>/src/config.ts</path></read_file>
|
|
534
|
+
\`\`\`
|
|
535
|
+
|
|
536
|
+
I'll read those files for you.`;
|
|
537
|
+
|
|
538
|
+
// Check detection
|
|
539
|
+
t.true(XMLToolCallParser.hasToolCalls(content));
|
|
540
|
+
|
|
541
|
+
// Parse
|
|
542
|
+
const parsed = XMLToolCallParser.parseToolCalls(content);
|
|
543
|
+
t.is(parsed.length, 2);
|
|
544
|
+
|
|
545
|
+
// Convert
|
|
546
|
+
const toolCalls = XMLToolCallParser.convertToToolCalls(parsed);
|
|
547
|
+
t.is(toolCalls.length, 2);
|
|
548
|
+
t.is(toolCalls[0].function.name, 'read_file');
|
|
549
|
+
t.is(toolCalls[1].function.name, 'read_file');
|
|
550
|
+
|
|
551
|
+
// Remove from content
|
|
552
|
+
const cleaned = XMLToolCallParser.removeToolCallsFromContent(content);
|
|
553
|
+
t.false(cleaned.includes('<read_file>'));
|
|
554
|
+
t.true(cleaned.includes('Let me help you'));
|
|
555
|
+
t.true(cleaned.includes("I'll read those files"));
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
test('full workflow - handles mixed content with malformed detection', t => {
|
|
559
|
+
const malformedContent = '<function=test><param>value</param></function>';
|
|
560
|
+
|
|
561
|
+
// Should detect malformation
|
|
562
|
+
const malformed = XMLToolCallParser.detectMalformedToolCall(malformedContent);
|
|
563
|
+
t.truthy(malformed);
|
|
564
|
+
|
|
565
|
+
// Should not parse as valid tool calls
|
|
566
|
+
const parsed = XMLToolCallParser.parseToolCalls(malformedContent);
|
|
567
|
+
t.is(parsed.length, 0);
|
|
568
|
+
|
|
569
|
+
// Should not be detected as having tool calls
|
|
570
|
+
t.false(XMLToolCallParser.hasToolCalls(malformedContent));
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
test('stress test - handles large number of tool calls', t => {
|
|
574
|
+
const toolCalls = Array.from(
|
|
575
|
+
{length: 100},
|
|
576
|
+
(_, i) => `<read_file><path>/file${i}.txt</path></read_file>`,
|
|
577
|
+
).join('\n');
|
|
578
|
+
|
|
579
|
+
const parsed = XMLToolCallParser.parseToolCalls(toolCalls);
|
|
580
|
+
t.is(parsed.length, 100);
|
|
581
|
+
|
|
582
|
+
const converted = XMLToolCallParser.convertToToolCalls(parsed);
|
|
583
|
+
t.is(converted.length, 100);
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
test('stress test - handles deeply nested parameters', t => {
|
|
587
|
+
const content =
|
|
588
|
+
'<test><config>{"level1": {"level2": {"level3": {"value": 42}}}}</config></test>';
|
|
589
|
+
const parsed = XMLToolCallParser.parseToolCalls(content);
|
|
590
|
+
|
|
591
|
+
t.is(parsed.length, 1);
|
|
592
|
+
t.deepEqual(parsed[0].parameters.config, {
|
|
593
|
+
level1: {level2: {level3: {value: 42}}},
|
|
594
|
+
});
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
test('stress test - handles very long parameter values', t => {
|
|
598
|
+
const longValue = 'x'.repeat(10000);
|
|
599
|
+
const content = `<test><data>${longValue}</data></test>`;
|
|
600
|
+
const parsed = XMLToolCallParser.parseToolCalls(content);
|
|
601
|
+
|
|
602
|
+
t.is(parsed.length, 1);
|
|
603
|
+
t.is((parsed[0].parameters.data as string).length, 10000);
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
// HTML tag rejection tests
|
|
607
|
+
test('parseToolCalls - rejects HTML div tags', t => {
|
|
608
|
+
const content = '<div><p>Some HTML content</p></div>';
|
|
609
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
610
|
+
|
|
611
|
+
t.is(result.length, 0);
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
test('parseToolCalls - rejects HTML ul/li list tags', t => {
|
|
615
|
+
const content = '<ul><li>Item 1</li><li>Item 2</li></ul>';
|
|
616
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
617
|
+
|
|
618
|
+
t.is(result.length, 0);
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
test('parseToolCalls - rejects HTML table tags', t => {
|
|
622
|
+
const content = '<table><tr><td>Cell 1</td><td>Cell 2</td></tr></table>';
|
|
623
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
624
|
+
|
|
625
|
+
t.is(result.length, 0);
|
|
626
|
+
});
|
|
627
|
+
|
|
628
|
+
test('parseToolCalls - rejects HTML header tags', t => {
|
|
629
|
+
const content = '<h1>Title</h1><h2>Subtitle</h2>';
|
|
630
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
631
|
+
|
|
632
|
+
t.is(result.length, 0);
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
test('parseToolCalls - rejects HTML formatting tags', t => {
|
|
636
|
+
const content = '<strong>Bold</strong><em>Italic</em>';
|
|
637
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
638
|
+
|
|
639
|
+
t.is(result.length, 0);
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
test('parseToolCalls - rejects mixed HTML and valid tool calls correctly', t => {
|
|
643
|
+
const content = `<div>Some HTML</div>
|
|
644
|
+
<read_file><path>/test.txt</path></read_file>
|
|
645
|
+
<p>More HTML</p>`;
|
|
646
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
647
|
+
|
|
648
|
+
// Should only parse the valid tool call, not the HTML
|
|
649
|
+
t.is(result.length, 1);
|
|
650
|
+
t.is(result[0].toolName, 'read_file');
|
|
651
|
+
});
|
|
652
|
+
|
|
653
|
+
test('parseToolCalls - allows valid tool calls with HTML-like parameter content', t => {
|
|
654
|
+
const content =
|
|
655
|
+
'<create_file><path>/test.html</path><content><div>HTML content</div></content></create_file>';
|
|
656
|
+
const result = XMLToolCallParser.parseToolCalls(content);
|
|
657
|
+
|
|
658
|
+
// Should parse the tool call, with HTML as parameter value
|
|
659
|
+
t.is(result.length, 1);
|
|
660
|
+
t.is(result[0].toolName, 'create_file');
|
|
661
|
+
t.truthy(result[0].parameters.content);
|
|
662
|
+
});
|