@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,319 @@
|
|
|
1
|
+
import {existsSync, readFileSync} from 'fs';
|
|
2
|
+
import {join} from 'path';
|
|
3
|
+
|
|
4
|
+
export interface ExistingRules {
|
|
5
|
+
source: string;
|
|
6
|
+
content: string;
|
|
7
|
+
type: 'agents' | 'rules' | 'instructions';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class ExistingRulesExtractor {
|
|
11
|
+
private static readonly AI_CONFIG_FILES = [
|
|
12
|
+
// AI agent specific files
|
|
13
|
+
'AGENTS.md',
|
|
14
|
+
'AGENT.md',
|
|
15
|
+
'CLAUDE.md',
|
|
16
|
+
'GEMINI.md',
|
|
17
|
+
'CURSOR.md',
|
|
18
|
+
|
|
19
|
+
// Rules files in various directories
|
|
20
|
+
'.cursor/rules',
|
|
21
|
+
'.clinerules/rules',
|
|
22
|
+
'.roorules/rules',
|
|
23
|
+
|
|
24
|
+
// Alternative locations
|
|
25
|
+
'.ai/rules',
|
|
26
|
+
'.ai/instructions',
|
|
27
|
+
'ai-instructions.md',
|
|
28
|
+
'coding-guidelines.md',
|
|
29
|
+
'dev-guidelines.md',
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
constructor(private projectPath: string) {}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Find and extract content from existing AI configuration files
|
|
36
|
+
*/
|
|
37
|
+
public extractExistingRules(): ExistingRules[] {
|
|
38
|
+
const found: ExistingRules[] = [];
|
|
39
|
+
|
|
40
|
+
for (const configFile of ExistingRulesExtractor.AI_CONFIG_FILES) {
|
|
41
|
+
const filePath = join(this.projectPath, configFile);
|
|
42
|
+
|
|
43
|
+
if (existsSync(filePath)) {
|
|
44
|
+
try {
|
|
45
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
46
|
+
const cleanContent = this.cleanAndExtractRelevantContent(
|
|
47
|
+
content,
|
|
48
|
+
configFile,
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
if (cleanContent.trim()) {
|
|
52
|
+
found.push({
|
|
53
|
+
source: configFile,
|
|
54
|
+
content: cleanContent,
|
|
55
|
+
type: this.determineFileType(configFile),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
} catch {
|
|
59
|
+
// Skip files we can't read
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return found;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Clean content and extract only AI-relevant information
|
|
70
|
+
*/
|
|
71
|
+
private cleanAndExtractRelevantContent(
|
|
72
|
+
content: string,
|
|
73
|
+
filename: string,
|
|
74
|
+
): string {
|
|
75
|
+
// Remove excessive markdown formatting but keep structure
|
|
76
|
+
let cleaned = content;
|
|
77
|
+
|
|
78
|
+
// Remove multiple consecutive empty lines
|
|
79
|
+
cleaned = cleaned.replace(/\n\s*\n\s*\n/g, '\n\n');
|
|
80
|
+
|
|
81
|
+
// Remove excessive header decoration
|
|
82
|
+
cleaned = cleaned.replace(/#{4,}/g, '###');
|
|
83
|
+
|
|
84
|
+
// For specific file types, extract relevant sections
|
|
85
|
+
if (
|
|
86
|
+
filename.toLowerCase().includes('claude') ||
|
|
87
|
+
filename.toLowerCase().includes('agents')
|
|
88
|
+
) {
|
|
89
|
+
return this.extractAIAgentSections(cleaned);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (filename.includes('rules')) {
|
|
93
|
+
return this.extractRulesSections(cleaned);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// For generic files, extract key sections
|
|
97
|
+
return this.extractGeneralInstructions(cleaned);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Extract AI agent specific sections
|
|
102
|
+
*/
|
|
103
|
+
private extractAIAgentSections(content: string): string {
|
|
104
|
+
const relevantSections: string[] = [];
|
|
105
|
+
const lines = content.split('\n');
|
|
106
|
+
let currentSection = '';
|
|
107
|
+
let inRelevantSection = false;
|
|
108
|
+
let sectionHeader = '';
|
|
109
|
+
|
|
110
|
+
const relevantHeaders = [
|
|
111
|
+
'coding',
|
|
112
|
+
'style',
|
|
113
|
+
'convention',
|
|
114
|
+
'pattern',
|
|
115
|
+
'architecture',
|
|
116
|
+
'testing',
|
|
117
|
+
'security',
|
|
118
|
+
'performance',
|
|
119
|
+
'build',
|
|
120
|
+
'deployment',
|
|
121
|
+
'project',
|
|
122
|
+
'structure',
|
|
123
|
+
'guidelines',
|
|
124
|
+
'rules',
|
|
125
|
+
'instructions',
|
|
126
|
+
'important',
|
|
127
|
+
'note',
|
|
128
|
+
'requirement',
|
|
129
|
+
'constraint',
|
|
130
|
+
];
|
|
131
|
+
|
|
132
|
+
for (const line of lines) {
|
|
133
|
+
const trimmed = line.trim().toLowerCase();
|
|
134
|
+
|
|
135
|
+
// Check if this is a header
|
|
136
|
+
if (line.match(/^#+\s/) || line.match(/^[=-]{3,}$/)) {
|
|
137
|
+
// Save previous section if it was relevant
|
|
138
|
+
if (inRelevantSection && currentSection.trim()) {
|
|
139
|
+
relevantSections.push(sectionHeader + '\n' + currentSection.trim());
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Check if new section is relevant
|
|
143
|
+
inRelevantSection = relevantHeaders.some(keyword =>
|
|
144
|
+
trimmed.includes(keyword),
|
|
145
|
+
);
|
|
146
|
+
sectionHeader = line;
|
|
147
|
+
currentSection = '';
|
|
148
|
+
} else if (inRelevantSection) {
|
|
149
|
+
currentSection += line + '\n';
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Don't forget the last section
|
|
154
|
+
if (inRelevantSection && currentSection.trim()) {
|
|
155
|
+
relevantSections.push(sectionHeader + '\n' + currentSection.trim());
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// If no specific sections found, extract key paragraphs
|
|
159
|
+
if (relevantSections.length === 0) {
|
|
160
|
+
return this.extractKeyParagraphs(content);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return relevantSections.join('\n\n');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Extract rules file content
|
|
168
|
+
*/
|
|
169
|
+
private extractRulesSections(content: string): string {
|
|
170
|
+
// Rules files are typically more concise, keep most content
|
|
171
|
+
const lines = content.split('\n');
|
|
172
|
+
const filtered = lines.filter(line => {
|
|
173
|
+
const trimmed = line.trim();
|
|
174
|
+
// Skip very generic lines
|
|
175
|
+
if (trimmed.length < 10) return true; // Keep short lines for structure
|
|
176
|
+
if (trimmed.includes('example') && trimmed.includes('only')) return false;
|
|
177
|
+
if (trimmed.includes('this is just') && trimmed.includes('example'))
|
|
178
|
+
return false;
|
|
179
|
+
return true;
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
return filtered.join('\n');
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Extract general instructions from any file
|
|
187
|
+
*/
|
|
188
|
+
private extractGeneralInstructions(content: string): string {
|
|
189
|
+
return this.extractKeyParagraphs(content);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Extract key paragraphs based on content analysis
|
|
194
|
+
*/
|
|
195
|
+
private extractKeyParagraphs(content: string): string {
|
|
196
|
+
const paragraphs = content.split('\n\n').filter(p => p.trim().length > 50);
|
|
197
|
+
const keyParagraphs: string[] = [];
|
|
198
|
+
|
|
199
|
+
const importantKeywords = [
|
|
200
|
+
'must',
|
|
201
|
+
'should',
|
|
202
|
+
'always',
|
|
203
|
+
'never',
|
|
204
|
+
'important',
|
|
205
|
+
'critical',
|
|
206
|
+
'required',
|
|
207
|
+
'mandatory',
|
|
208
|
+
'essential',
|
|
209
|
+
'convention',
|
|
210
|
+
'pattern',
|
|
211
|
+
'style',
|
|
212
|
+
'format',
|
|
213
|
+
'structure',
|
|
214
|
+
'architecture',
|
|
215
|
+
'test',
|
|
216
|
+
'security',
|
|
217
|
+
];
|
|
218
|
+
|
|
219
|
+
for (const paragraph of paragraphs) {
|
|
220
|
+
const lowerParagraph = paragraph.toLowerCase();
|
|
221
|
+
const relevanceScore = importantKeywords.reduce((score, keyword) => {
|
|
222
|
+
return score + (lowerParagraph.includes(keyword) ? 1 : 0);
|
|
223
|
+
}, 0);
|
|
224
|
+
|
|
225
|
+
// Include paragraphs with at least 2 important keywords
|
|
226
|
+
if (relevanceScore >= 2) {
|
|
227
|
+
keyParagraphs.push(paragraph.trim());
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// If we didn't find enough relevant content, take first few paragraphs
|
|
232
|
+
if (keyParagraphs.length === 0 && paragraphs.length > 0) {
|
|
233
|
+
return paragraphs.slice(0, 3).join('\n\n');
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return keyParagraphs.slice(0, 5).join('\n\n'); // Limit to 5 paragraphs max
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Determine the type of configuration file
|
|
241
|
+
*/
|
|
242
|
+
private determineFileType(
|
|
243
|
+
filename: string,
|
|
244
|
+
): 'agents' | 'rules' | 'instructions' {
|
|
245
|
+
const lower = filename.toLowerCase();
|
|
246
|
+
|
|
247
|
+
if (
|
|
248
|
+
lower.includes('agent') ||
|
|
249
|
+
lower.includes('claude') ||
|
|
250
|
+
lower.includes('gemini')
|
|
251
|
+
) {
|
|
252
|
+
return 'agents';
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (
|
|
256
|
+
lower.includes('rule') ||
|
|
257
|
+
lower.includes('.cursor/') ||
|
|
258
|
+
lower.includes('.clinerules/')
|
|
259
|
+
) {
|
|
260
|
+
return 'rules';
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return 'instructions';
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Merge existing rules into a single consolidated section
|
|
268
|
+
*/
|
|
269
|
+
public static mergeExistingRules(existingRules: ExistingRules[]): string {
|
|
270
|
+
if (existingRules.length === 0) {
|
|
271
|
+
return '';
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const sections: string[] = [];
|
|
275
|
+
sections.push('## Existing Project Guidelines');
|
|
276
|
+
sections.push('');
|
|
277
|
+
sections.push(
|
|
278
|
+
'*The following guidelines were found in existing AI configuration files:*',
|
|
279
|
+
);
|
|
280
|
+
sections.push('');
|
|
281
|
+
|
|
282
|
+
// Group by type
|
|
283
|
+
const agentRules = existingRules.filter(r => r.type === 'agents');
|
|
284
|
+
const ruleFiles = existingRules.filter(r => r.type === 'rules');
|
|
285
|
+
const instructions = existingRules.filter(r => r.type === 'instructions');
|
|
286
|
+
|
|
287
|
+
// Add agent-specific rules
|
|
288
|
+
if (agentRules.length > 0) {
|
|
289
|
+
sections.push('### AI Agent Guidelines');
|
|
290
|
+
for (const rule of agentRules) {
|
|
291
|
+
sections.push(`**From ${rule.source}:**`);
|
|
292
|
+
sections.push(rule.content);
|
|
293
|
+
sections.push('');
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Add rule files
|
|
298
|
+
if (ruleFiles.length > 0) {
|
|
299
|
+
sections.push('### Project Rules');
|
|
300
|
+
for (const rule of ruleFiles) {
|
|
301
|
+
sections.push(`**From ${rule.source}:**`);
|
|
302
|
+
sections.push(rule.content);
|
|
303
|
+
sections.push('');
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Add general instructions
|
|
308
|
+
if (instructions.length > 0) {
|
|
309
|
+
sections.push('### Additional Instructions');
|
|
310
|
+
for (const rule of instructions) {
|
|
311
|
+
sections.push(`**From ${rule.source}:**`);
|
|
312
|
+
sections.push(rule.content);
|
|
313
|
+
sections.push('');
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
return sections.join('\n');
|
|
318
|
+
}
|
|
319
|
+
}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { writeFileSync, rmSync, existsSync, mkdirSync } from 'fs';
|
|
2
|
+
import { tmpdir } from 'os';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import test from 'ava';
|
|
5
|
+
import { FileScanner } from './file-scanner';
|
|
6
|
+
|
|
7
|
+
// Create a temporary test directory
|
|
8
|
+
const testDir = join(tmpdir(), `coder-file-scanner-test-${Date.now()}`);
|
|
9
|
+
|
|
10
|
+
test.before(() => {
|
|
11
|
+
// Create test directory structure
|
|
12
|
+
mkdirSync(testDir, {recursive: true});
|
|
13
|
+
mkdirSync(join(testDir, 'src'), {recursive: true});
|
|
14
|
+
mkdirSync(join(testDir, 'test'), {recursive: true});
|
|
15
|
+
mkdirSync(join(testDir, 'docs'), {recursive: true});
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test.after.always(() => {
|
|
19
|
+
// Clean up test directory
|
|
20
|
+
if (existsSync(testDir)) {
|
|
21
|
+
rmSync(testDir, {recursive: true, force: true});
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('FileScanner - constructor initializes with root path', t => {
|
|
26
|
+
const scanner = new FileScanner(testDir);
|
|
27
|
+
|
|
28
|
+
t.truthy(scanner);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('FileScanner - scan returns ScanResult structure', t => {
|
|
32
|
+
const scanner = new FileScanner(testDir);
|
|
33
|
+
|
|
34
|
+
const result = scanner.scan();
|
|
35
|
+
|
|
36
|
+
t.true(Array.isArray(result.files));
|
|
37
|
+
t.true(Array.isArray(result.directories));
|
|
38
|
+
t.is(typeof result.totalFiles, 'number');
|
|
39
|
+
t.is(typeof result.scannedFiles, 'number');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('FileScanner - scan finds files in directory', t => {
|
|
43
|
+
// Create some test files
|
|
44
|
+
writeFileSync(join(testDir, 'package.json'), '{}', 'utf-8');
|
|
45
|
+
writeFileSync(join(testDir, 'README.md'), '# Test', 'utf-8');
|
|
46
|
+
writeFileSync(join(testDir, 'src', 'index.ts'), 'test', 'utf-8');
|
|
47
|
+
|
|
48
|
+
const scanner = new FileScanner(testDir);
|
|
49
|
+
const result = scanner.scan();
|
|
50
|
+
|
|
51
|
+
t.true(result.files.includes('package.json'));
|
|
52
|
+
t.true(result.files.includes('README.md'));
|
|
53
|
+
t.true(result.files.includes('src/index.ts'));
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('FileScanner - scan finds directories', t => {
|
|
57
|
+
const scanner = new FileScanner(testDir);
|
|
58
|
+
const result = scanner.scan();
|
|
59
|
+
|
|
60
|
+
t.true(result.directories.includes('src'));
|
|
61
|
+
t.true(result.directories.includes('test'));
|
|
62
|
+
t.true(result.directories.includes('docs'));
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test('FileScanner - scan ignores node_modules directory', t => {
|
|
66
|
+
// Create node_modules directory
|
|
67
|
+
mkdirSync(join(testDir, 'node_modules'), {recursive: true});
|
|
68
|
+
mkdirSync(join(testDir, 'node_modules', 'package'), {recursive: true});
|
|
69
|
+
writeFileSync(join(testDir, 'node_modules', 'package', 'test'), 'test', 'utf-8');
|
|
70
|
+
|
|
71
|
+
const scanner = new FileScanner(testDir);
|
|
72
|
+
const result = scanner.scan();
|
|
73
|
+
|
|
74
|
+
// node_modules should not be in files or directories
|
|
75
|
+
t.false(result.files.some(f => f.includes('node_modules')));
|
|
76
|
+
t.false(result.directories.some(d => d.includes('node_modules')));
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test('FileScanner - scan ignores .git directory', t => {
|
|
80
|
+
// Create .git directory
|
|
81
|
+
mkdirSync(join(testDir, '.git'), {recursive: true});
|
|
82
|
+
writeFileSync(join(testDir, '.git', 'config'), 'test', 'utf-8');
|
|
83
|
+
|
|
84
|
+
const scanner = new FileScanner(testDir);
|
|
85
|
+
const result = scanner.scan();
|
|
86
|
+
|
|
87
|
+
t.false(result.files.some(f => f.includes('.git')));
|
|
88
|
+
t.false(result.directories.some(d => d.includes('.git')));
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test('FileScanner - scan ignores dist directory', t => {
|
|
92
|
+
// Create dist directory
|
|
93
|
+
mkdirSync(join(testDir, 'dist'), {recursive: true});
|
|
94
|
+
writeFileSync(join(testDir, 'dist', 'bundle.js'), 'test', 'utf-8');
|
|
95
|
+
|
|
96
|
+
const scanner = new FileScanner(testDir);
|
|
97
|
+
const result = scanner.scan();
|
|
98
|
+
|
|
99
|
+
t.false(result.files.some(f => f.includes('dist')));
|
|
100
|
+
t.false(result.directories.some(d => d.includes('dist')));
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test('FileScanner - scan respects .gitignore patterns', t => {
|
|
104
|
+
// Create .gitignore file
|
|
105
|
+
writeFileSync(join(testDir, '.gitignore'), '*.log\ntemp/\n.cache', 'utf-8');
|
|
106
|
+
|
|
107
|
+
// Create files that should be ignored
|
|
108
|
+
writeFileSync(join(testDir, 'debug.log'), 'log', 'utf-8');
|
|
109
|
+
mkdirSync(join(testDir, 'temp'), {recursive: true});
|
|
110
|
+
writeFileSync(join(testDir, 'temp', 'file.txt'), 'test', 'utf-8');
|
|
111
|
+
|
|
112
|
+
const scanner = new FileScanner(testDir);
|
|
113
|
+
const result = scanner.scan();
|
|
114
|
+
|
|
115
|
+
// These files should be ignored
|
|
116
|
+
t.false(result.files.includes('debug.log'));
|
|
117
|
+
t.false(result.files.some(f => f.includes('temp')));
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test('FileScanner - getFilesByPattern filters files by pattern', t => {
|
|
121
|
+
// Create various files
|
|
122
|
+
writeFileSync(join(testDir, 'package.json'), '{}', 'utf-8');
|
|
123
|
+
writeFileSync(join(testDir, 'tsconfig.json'), '{}', 'utf-8');
|
|
124
|
+
writeFileSync(join(testDir, 'README.md'), '# Test', 'utf-8');
|
|
125
|
+
writeFileSync(join(testDir, 'src', 'index.ts'), 'test', 'utf-8');
|
|
126
|
+
|
|
127
|
+
const scanner = new FileScanner(testDir);
|
|
128
|
+
const jsonFiles = scanner.getFilesByPattern(['*.json']);
|
|
129
|
+
|
|
130
|
+
t.true(jsonFiles.includes('package.json'));
|
|
131
|
+
t.true(jsonFiles.includes('tsconfig.json'));
|
|
132
|
+
t.false(jsonFiles.includes('README.md'));
|
|
133
|
+
t.false(jsonFiles.includes('src/index.ts'));
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test('FileScanner - getFilesByPattern with multiple patterns', t => {
|
|
137
|
+
// Create files
|
|
138
|
+
writeFileSync(join(testDir, 'README.md'), '# Test', 'utf-8');
|
|
139
|
+
writeFileSync(join(testDir, 'CHANGELOG.md'), '# Changelog', 'utf-8');
|
|
140
|
+
writeFileSync(join(testDir, 'package.json'), '{}', 'utf-8');
|
|
141
|
+
writeFileSync(join(testDir, 'src', 'index.ts'), 'test', 'utf-8');
|
|
142
|
+
|
|
143
|
+
const scanner = new FileScanner(testDir);
|
|
144
|
+
const docsAndConfig = scanner.getFilesByPattern(['*.md', '*.json']);
|
|
145
|
+
|
|
146
|
+
t.true(docsAndConfig.includes('README.md'));
|
|
147
|
+
t.true(docsAndConfig.includes('CHANGELOG.md'));
|
|
148
|
+
t.true(docsAndConfig.includes('package.json'));
|
|
149
|
+
t.false(docsAndConfig.includes('src/index.ts'));
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
test('FileScanner - getProjectFiles returns categorized files', t => {
|
|
153
|
+
// Create various project files
|
|
154
|
+
writeFileSync(join(testDir, 'package.json'), '{}', 'utf-8');
|
|
155
|
+
writeFileSync(join(testDir, 'README.md'), '# Test', 'utf-8');
|
|
156
|
+
writeFileSync(join(testDir, 'Makefile'), 'build:', 'utf-8');
|
|
157
|
+
writeFileSync(join(testDir, 'test', 'index.spec.ts'), 'test', 'utf-8');
|
|
158
|
+
writeFileSync(join(testDir, 'tsconfig.json'), '{}', 'utf-8');
|
|
159
|
+
|
|
160
|
+
const scanner = new FileScanner(testDir);
|
|
161
|
+
const projectFiles = scanner.getProjectFiles();
|
|
162
|
+
|
|
163
|
+
t.true(Array.isArray(projectFiles.config));
|
|
164
|
+
t.true(Array.isArray(projectFiles.documentation));
|
|
165
|
+
t.true(Array.isArray(projectFiles.build));
|
|
166
|
+
t.true(Array.isArray(projectFiles.test));
|
|
167
|
+
|
|
168
|
+
t.true(projectFiles.config.includes('package.json'));
|
|
169
|
+
// tsconfig.json is in build files, not config
|
|
170
|
+
t.true(projectFiles.build.includes('tsconfig.json'));
|
|
171
|
+
t.true(projectFiles.documentation.includes('README.md'));
|
|
172
|
+
t.true(projectFiles.build.includes('Makefile'));
|
|
173
|
+
t.true(projectFiles.test.some(f => f.includes('index.spec')));
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
test('FileScanner - scan handles empty directory', t => {
|
|
177
|
+
const emptyDir = join(testDir, 'empty');
|
|
178
|
+
mkdirSync(emptyDir, {recursive: true});
|
|
179
|
+
|
|
180
|
+
const scanner = new FileScanner(emptyDir);
|
|
181
|
+
const result = scanner.scan();
|
|
182
|
+
|
|
183
|
+
t.is(result.files.length, 0);
|
|
184
|
+
t.is(result.directories.length, 0);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
test('FileScanner - scan counts files correctly', t => {
|
|
188
|
+
// Create some files
|
|
189
|
+
writeFileSync(join(testDir, 'file1.txt'), 'test', 'utf-8');
|
|
190
|
+
writeFileSync(join(testDir, 'file2.txt'), 'test', 'utf-8');
|
|
191
|
+
writeFileSync(join(testDir, 'file3.txt'), 'test', 'utf-8');
|
|
192
|
+
|
|
193
|
+
const scanner = new FileScanner(testDir);
|
|
194
|
+
const result = scanner.scan();
|
|
195
|
+
|
|
196
|
+
// Note: totalFiles includes both files and directories
|
|
197
|
+
t.true(result.totalFiles >= 3);
|
|
198
|
+
t.true(result.scannedFiles >= 3);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
test('FileScanner - getFilesByPattern with docs pattern', t => {
|
|
202
|
+
// Create documentation files
|
|
203
|
+
writeFileSync(join(testDir, 'README.md'), '# Test', 'utf-8');
|
|
204
|
+
writeFileSync(join(testDir, 'docs', 'guide.md'), '# Guide', 'utf-8');
|
|
205
|
+
writeFileSync(join(testDir, 'src', 'index.ts'), 'test', 'utf-8');
|
|
206
|
+
|
|
207
|
+
const scanner = new FileScanner(testDir);
|
|
208
|
+
const docPatterns = ['README*', '*.md', 'docs/*'];
|
|
209
|
+
const docs = scanner.getFilesByPattern(docPatterns);
|
|
210
|
+
|
|
211
|
+
t.true(docs.includes('README.md'));
|
|
212
|
+
t.true(docs.some(f => f.includes('docs/guide.md')));
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
test('FileScanner - scan handles subdirectories', t => {
|
|
216
|
+
// Create nested structure
|
|
217
|
+
mkdirSync(join(testDir, 'src', 'components'), {recursive: true});
|
|
218
|
+
writeFileSync(join(testDir, 'src', 'index.ts'), 'test', 'utf-8');
|
|
219
|
+
writeFileSync(join(testDir, 'src', 'components', 'Button.tsx'), 'test', 'utf-8');
|
|
220
|
+
|
|
221
|
+
const scanner = new FileScanner(testDir);
|
|
222
|
+
const result = scanner.scan();
|
|
223
|
+
|
|
224
|
+
t.true(result.files.includes('src/index.ts'));
|
|
225
|
+
t.true(result.files.includes('src/components/Button.tsx'));
|
|
226
|
+
t.true(result.directories.includes('src/components'));
|
|
227
|
+
});
|