@gguf/coder 0.2.9 → 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/dist/tools/execute-bash.js +3 -3
- package/dist/tools/execute-bash.js.map +1 -1
- package/dist/tools/fetch-url.js +3 -3
- package/dist/tools/fetch-url.js.map +1 -1
- package/dist/tools/find-files.d.ts.map +1 -1
- package/dist/tools/find-files.js +1 -1
- package/dist/tools/find-files.js.map +1 -1
- package/dist/tools/lsp-get-diagnostics.js +1 -1
- package/dist/tools/lsp-get-diagnostics.js.map +1 -1
- package/dist/tools/read-file.d.ts.map +1 -1
- package/dist/tools/read-file.js +6 -6
- package/dist/tools/read-file.js.map +1 -1
- package/dist/tools/search-file-contents.d.ts.map +1 -1
- package/dist/tools/search-file-contents.js +1 -1
- package/dist/tools/search-file-contents.js.map +1 -1
- package/dist/tools/string-replace.js +11 -11
- package/dist/tools/string-replace.js.map +1 -1
- package/dist/tools/web-search.d.ts.map +1 -1
- package/dist/tools/web-search.js +3 -3
- package/dist/tools/web-search.js.map +1 -1
- package/dist/tools/write-file.js +4 -4
- package/dist/tools/write-file.js.map +1 -1
- package/dist/utils/tool-result-display.d.ts.map +1 -1
- package/dist/utils/tool-result-display.js +3 -3
- package/dist/utils/tool-result-display.js.map +1 -1
- 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,173 @@
|
|
|
1
|
+
import {renderWithTheme} from '@/test-utils/render-with-theme';
|
|
2
|
+
import type {CheckpointListItem} from '@/types/checkpoint';
|
|
3
|
+
import test from 'ava';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import CheckpointSelector from './checkpoint-selector';
|
|
6
|
+
|
|
7
|
+
const createMockCheckpoint = (
|
|
8
|
+
name: string,
|
|
9
|
+
overrides: Partial<CheckpointListItem['metadata']> = {},
|
|
10
|
+
): CheckpointListItem => ({
|
|
11
|
+
name,
|
|
12
|
+
metadata: {
|
|
13
|
+
name,
|
|
14
|
+
timestamp: new Date().toISOString(),
|
|
15
|
+
messageCount: 10,
|
|
16
|
+
filesChanged: ['file1.ts', 'file2.ts'],
|
|
17
|
+
provider: {name: 'Test Provider', model: 'test-model'},
|
|
18
|
+
description: 'Test checkpoint',
|
|
19
|
+
...overrides,
|
|
20
|
+
},
|
|
21
|
+
sizeBytes: 1024,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test('CheckpointSelector renders empty state when no checkpoints', t => {
|
|
25
|
+
const {lastFrame} = renderWithTheme(
|
|
26
|
+
<CheckpointSelector
|
|
27
|
+
checkpoints={[]}
|
|
28
|
+
onSelect={() => {}}
|
|
29
|
+
onCancel={() => {}}
|
|
30
|
+
currentMessageCount={0}
|
|
31
|
+
/>,
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const output = lastFrame() || '';
|
|
35
|
+
t.true(output.includes('No Checkpoints'));
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test('CheckpointSelector renders checkpoint list', t => {
|
|
39
|
+
const checkpoints = [
|
|
40
|
+
createMockCheckpoint('checkpoint-1'),
|
|
41
|
+
createMockCheckpoint('checkpoint-2'),
|
|
42
|
+
];
|
|
43
|
+
const {lastFrame} = renderWithTheme(
|
|
44
|
+
<CheckpointSelector
|
|
45
|
+
checkpoints={checkpoints}
|
|
46
|
+
onSelect={() => {}}
|
|
47
|
+
onCancel={() => {}}
|
|
48
|
+
currentMessageCount={0}
|
|
49
|
+
/>,
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const output = lastFrame() || '';
|
|
53
|
+
t.true(output.includes('checkpoint-1'));
|
|
54
|
+
t.true(output.includes('checkpoint-2'));
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('CheckpointSelector renders title', t => {
|
|
58
|
+
const checkpoints = [createMockCheckpoint('test')];
|
|
59
|
+
const {lastFrame} = renderWithTheme(
|
|
60
|
+
<CheckpointSelector
|
|
61
|
+
checkpoints={checkpoints}
|
|
62
|
+
onSelect={() => {}}
|
|
63
|
+
onCancel={() => {}}
|
|
64
|
+
currentMessageCount={0}
|
|
65
|
+
/>,
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
const output = lastFrame() || '';
|
|
69
|
+
t.true(output.includes('Select Checkpoint'));
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test('CheckpointSelector renders navigation help', t => {
|
|
73
|
+
const checkpoints = [createMockCheckpoint('test')];
|
|
74
|
+
const {lastFrame} = renderWithTheme(
|
|
75
|
+
<CheckpointSelector
|
|
76
|
+
checkpoints={checkpoints}
|
|
77
|
+
onSelect={() => {}}
|
|
78
|
+
onCancel={() => {}}
|
|
79
|
+
currentMessageCount={0}
|
|
80
|
+
/>,
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
const output = lastFrame() || '';
|
|
84
|
+
// The component should show some navigation instructions
|
|
85
|
+
t.truthy(output.length > 0);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test('CheckpointSelector shows message count in checkpoint label', t => {
|
|
89
|
+
const checkpoints = [createMockCheckpoint('test', {messageCount: 42})];
|
|
90
|
+
const {lastFrame} = renderWithTheme(
|
|
91
|
+
<CheckpointSelector
|
|
92
|
+
checkpoints={checkpoints}
|
|
93
|
+
onSelect={() => {}}
|
|
94
|
+
onCancel={() => {}}
|
|
95
|
+
currentMessageCount={0}
|
|
96
|
+
/>,
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
const output = lastFrame() || '';
|
|
100
|
+
// The label format includes "42 msgs"
|
|
101
|
+
t.true(output.includes('42'));
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test('CheckpointSelector shows files count in checkpoint label', t => {
|
|
105
|
+
const checkpoints = [
|
|
106
|
+
createMockCheckpoint('test', {
|
|
107
|
+
filesChanged: ['a.ts', 'b.ts', 'c.ts'],
|
|
108
|
+
}),
|
|
109
|
+
];
|
|
110
|
+
const {lastFrame} = renderWithTheme(
|
|
111
|
+
<CheckpointSelector
|
|
112
|
+
checkpoints={checkpoints}
|
|
113
|
+
onSelect={() => {}}
|
|
114
|
+
onCancel={() => {}}
|
|
115
|
+
currentMessageCount={0}
|
|
116
|
+
/>,
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
const output = lastFrame() || '';
|
|
120
|
+
// The label format includes "3 files"
|
|
121
|
+
t.true(output.includes('3'));
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test('CheckpointSelector renders without crashing with onError prop', t => {
|
|
125
|
+
const checkpoints = [createMockCheckpoint('test')];
|
|
126
|
+
const {lastFrame} = renderWithTheme(
|
|
127
|
+
<CheckpointSelector
|
|
128
|
+
checkpoints={checkpoints}
|
|
129
|
+
onSelect={() => {}}
|
|
130
|
+
onCancel={() => {}}
|
|
131
|
+
onError={() => {}}
|
|
132
|
+
currentMessageCount={0}
|
|
133
|
+
/>,
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
const output = lastFrame() || '';
|
|
137
|
+
t.true(output.includes('test'));
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test('CheckpointSelector renders multiple checkpoints in list', t => {
|
|
141
|
+
const checkpoints = [
|
|
142
|
+
createMockCheckpoint('first-checkpoint'),
|
|
143
|
+
createMockCheckpoint('second-checkpoint'),
|
|
144
|
+
createMockCheckpoint('third-checkpoint'),
|
|
145
|
+
];
|
|
146
|
+
const {lastFrame} = renderWithTheme(
|
|
147
|
+
<CheckpointSelector
|
|
148
|
+
checkpoints={checkpoints}
|
|
149
|
+
onSelect={() => {}}
|
|
150
|
+
onCancel={() => {}}
|
|
151
|
+
currentMessageCount={0}
|
|
152
|
+
/>,
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
const output = lastFrame() || '';
|
|
156
|
+
t.true(output.includes('first-checkpoint'));
|
|
157
|
+
t.true(output.includes('second-checkpoint'));
|
|
158
|
+
t.true(output.includes('third-checkpoint'));
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test('CheckpointSelector empty state message mentions create command', t => {
|
|
162
|
+
const {lastFrame} = renderWithTheme(
|
|
163
|
+
<CheckpointSelector
|
|
164
|
+
checkpoints={[]}
|
|
165
|
+
onSelect={() => {}}
|
|
166
|
+
onCancel={() => {}}
|
|
167
|
+
currentMessageCount={0}
|
|
168
|
+
/>,
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
const output = lastFrame() || '';
|
|
172
|
+
t.true(output.includes('checkpoint create'));
|
|
173
|
+
});
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import {TitledBox} from '@/components/ui/titled-box';
|
|
2
|
+
import {useTerminalWidth} from '@/hooks/useTerminalWidth';
|
|
3
|
+
import {useTheme} from '@/hooks/useTheme';
|
|
4
|
+
import type {CheckpointListItem} from '@/types/checkpoint';
|
|
5
|
+
import {formatRelativeTime} from '@/utils/checkpoint-utils';
|
|
6
|
+
import {Box, Text, useInput} from 'ink';
|
|
7
|
+
import SelectInput from 'ink-select-input';
|
|
8
|
+
import {useState} from 'react';
|
|
9
|
+
|
|
10
|
+
interface CheckpointSelectorProps {
|
|
11
|
+
checkpoints: CheckpointListItem[];
|
|
12
|
+
onSelect: (checkpointName: string, createBackup: boolean) => void;
|
|
13
|
+
onCancel: () => void;
|
|
14
|
+
onError?: (error: Error) => void;
|
|
15
|
+
currentMessageCount: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface CheckpointOption {
|
|
19
|
+
label: string;
|
|
20
|
+
value: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default function CheckpointSelector({
|
|
24
|
+
checkpoints,
|
|
25
|
+
onSelect,
|
|
26
|
+
onCancel,
|
|
27
|
+
currentMessageCount,
|
|
28
|
+
}: CheckpointSelectorProps) {
|
|
29
|
+
const boxWidth = useTerminalWidth();
|
|
30
|
+
const {colors} = useTheme();
|
|
31
|
+
const [selectedCheckpoint, setSelectedCheckpoint] = useState<string | null>(
|
|
32
|
+
null,
|
|
33
|
+
);
|
|
34
|
+
const [awaitingBackupConfirmation, setAwaitingBackupConfirmation] =
|
|
35
|
+
useState(false);
|
|
36
|
+
|
|
37
|
+
useInput((inputChar, key) => {
|
|
38
|
+
if (key.escape) {
|
|
39
|
+
onCancel();
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (awaitingBackupConfirmation) {
|
|
44
|
+
const char = inputChar.toLowerCase();
|
|
45
|
+
if (char === 'y' || char === '\r' || char === '\n') {
|
|
46
|
+
if (selectedCheckpoint) {
|
|
47
|
+
onSelect(selectedCheckpoint, true);
|
|
48
|
+
}
|
|
49
|
+
} else if (char === 'n') {
|
|
50
|
+
if (selectedCheckpoint) {
|
|
51
|
+
onSelect(selectedCheckpoint, false);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const handleCheckpointSelect = (item: CheckpointOption) => {
|
|
58
|
+
setSelectedCheckpoint(item.value);
|
|
59
|
+
if (currentMessageCount > 0) {
|
|
60
|
+
setAwaitingBackupConfirmation(true);
|
|
61
|
+
} else {
|
|
62
|
+
onSelect(item.value, false);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
if (awaitingBackupConfirmation && selectedCheckpoint) {
|
|
67
|
+
const checkpoint = checkpoints.find(c => c.name === selectedCheckpoint);
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<TitledBox
|
|
71
|
+
title="Checkpoint Load - Backup Confirmation"
|
|
72
|
+
width={boxWidth}
|
|
73
|
+
borderColor={colors.warning}
|
|
74
|
+
paddingX={2}
|
|
75
|
+
paddingY={1}
|
|
76
|
+
marginBottom={1}
|
|
77
|
+
>
|
|
78
|
+
<Box flexDirection="column">
|
|
79
|
+
<Box marginBottom={1}>
|
|
80
|
+
<Text color={colors.white}>
|
|
81
|
+
You have {currentMessageCount} message(s) in the current session.
|
|
82
|
+
</Text>
|
|
83
|
+
</Box>
|
|
84
|
+
|
|
85
|
+
{checkpoint && (
|
|
86
|
+
<Box flexDirection="column" marginBottom={1}>
|
|
87
|
+
<Text color={colors.secondary}>
|
|
88
|
+
Loading checkpoint:{' '}
|
|
89
|
+
<Text color={colors.primary}>{checkpoint.name}</Text>
|
|
90
|
+
</Text>
|
|
91
|
+
<Text color={colors.secondary}>
|
|
92
|
+
• {checkpoint.metadata.messageCount} messages
|
|
93
|
+
</Text>
|
|
94
|
+
<Text color={colors.secondary}>
|
|
95
|
+
• {checkpoint.metadata.filesChanged.length} files
|
|
96
|
+
</Text>
|
|
97
|
+
<Text color={colors.secondary}>
|
|
98
|
+
• Created {formatRelativeTime(checkpoint.metadata.timestamp)}
|
|
99
|
+
</Text>
|
|
100
|
+
</Box>
|
|
101
|
+
)}
|
|
102
|
+
|
|
103
|
+
<Box marginBottom={1}>
|
|
104
|
+
<Text color={colors.warning} bold>
|
|
105
|
+
Create a backup of current session before loading?
|
|
106
|
+
</Text>
|
|
107
|
+
</Box>
|
|
108
|
+
|
|
109
|
+
<Box marginBottom={1}>
|
|
110
|
+
<Text color={colors.white}>
|
|
111
|
+
[Y] Yes, create backup [N] No, skip backup [Esc] Cancel
|
|
112
|
+
</Text>
|
|
113
|
+
</Box>
|
|
114
|
+
|
|
115
|
+
<Box>
|
|
116
|
+
<Text color={colors.secondary} dimColor>
|
|
117
|
+
Press Y/Enter to backup, N to skip, or Esc to cancel
|
|
118
|
+
</Text>
|
|
119
|
+
</Box>
|
|
120
|
+
</Box>
|
|
121
|
+
</TitledBox>
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const options: CheckpointOption[] = checkpoints.map(checkpoint => ({
|
|
126
|
+
label: `${checkpoint.name} - ${checkpoint.metadata.messageCount} msgs, ${
|
|
127
|
+
checkpoint.metadata.filesChanged.length
|
|
128
|
+
} files - ${formatRelativeTime(checkpoint.metadata.timestamp)}`,
|
|
129
|
+
value: checkpoint.name,
|
|
130
|
+
}));
|
|
131
|
+
|
|
132
|
+
if (options.length === 0) {
|
|
133
|
+
return (
|
|
134
|
+
<TitledBox
|
|
135
|
+
title="No Checkpoints Available"
|
|
136
|
+
width={boxWidth}
|
|
137
|
+
borderColor={colors.secondary}
|
|
138
|
+
paddingX={2}
|
|
139
|
+
paddingY={1}
|
|
140
|
+
marginBottom={1}
|
|
141
|
+
>
|
|
142
|
+
<Box flexDirection="column">
|
|
143
|
+
<Text color={colors.white}>
|
|
144
|
+
No checkpoints found. Create one with /checkpoint create [name]
|
|
145
|
+
</Text>
|
|
146
|
+
<Box marginTop={1}>
|
|
147
|
+
<Text color={colors.secondary}>Press Escape to cancel</Text>
|
|
148
|
+
</Box>
|
|
149
|
+
</Box>
|
|
150
|
+
</TitledBox>
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return (
|
|
155
|
+
<TitledBox
|
|
156
|
+
title="Select Checkpoint to Load"
|
|
157
|
+
width={boxWidth}
|
|
158
|
+
borderColor={colors.primary}
|
|
159
|
+
paddingX={2}
|
|
160
|
+
paddingY={1}
|
|
161
|
+
marginBottom={1}
|
|
162
|
+
>
|
|
163
|
+
<Box flexDirection="column">
|
|
164
|
+
<SelectInput items={options} onSelect={handleCheckpointSelect} />
|
|
165
|
+
<Box marginTop={1}>
|
|
166
|
+
<Text color={colors.secondary}>
|
|
167
|
+
Use ↑↓ arrows to select, Enter to confirm, Escape to cancel
|
|
168
|
+
</Text>
|
|
169
|
+
</Box>
|
|
170
|
+
</Box>
|
|
171
|
+
</TitledBox>
|
|
172
|
+
);
|
|
173
|
+
}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import {render} from 'ink-testing-library';
|
|
2
|
+
import test from 'ava';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import {DevelopmentModeIndicator} from './development-mode-indicator';
|
|
5
|
+
|
|
6
|
+
// Mock colors object matching the theme structure
|
|
7
|
+
const mockColors = {
|
|
8
|
+
primary: '#FFFFFF',
|
|
9
|
+
secondary: '#808080',
|
|
10
|
+
info: '#00FFFF',
|
|
11
|
+
warning: '#FFA500',
|
|
12
|
+
error: '#FF0000',
|
|
13
|
+
success: '#00FF00',
|
|
14
|
+
tool: '#FF00FF',
|
|
15
|
+
white: '#FFFFFF',
|
|
16
|
+
black: '#000000',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// Component Rendering Tests
|
|
21
|
+
// ============================================================================
|
|
22
|
+
|
|
23
|
+
test('DevelopmentModeIndicator renders with normal mode', t => {
|
|
24
|
+
const {lastFrame} = render(
|
|
25
|
+
<DevelopmentModeIndicator developmentMode="normal" colors={mockColors} />,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const output = lastFrame();
|
|
29
|
+
t.truthy(output);
|
|
30
|
+
t.regex(output!, /normal mode on/);
|
|
31
|
+
t.regex(output!, /Shift\+Tab to cycle/);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('DevelopmentModeIndicator renders with auto-accept mode', t => {
|
|
35
|
+
const {lastFrame} = render(
|
|
36
|
+
<DevelopmentModeIndicator
|
|
37
|
+
developmentMode="auto-accept"
|
|
38
|
+
colors={mockColors}
|
|
39
|
+
/>,
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const output = lastFrame();
|
|
43
|
+
t.truthy(output);
|
|
44
|
+
t.regex(output!, /auto-accept mode on/);
|
|
45
|
+
t.regex(output!, /Shift\+Tab to cycle/);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('DevelopmentModeIndicator renders with plan mode', t => {
|
|
49
|
+
const {lastFrame} = render(
|
|
50
|
+
<DevelopmentModeIndicator developmentMode="plan" colors={mockColors} />,
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const output = lastFrame();
|
|
54
|
+
t.truthy(output);
|
|
55
|
+
t.regex(output!, /plan mode on/);
|
|
56
|
+
t.regex(output!, /Shift\+Tab to cycle/);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test('DevelopmentModeIndicator renders without crashing', t => {
|
|
60
|
+
const {unmount} = render(
|
|
61
|
+
<DevelopmentModeIndicator developmentMode="normal" colors={mockColors} />,
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
t.notThrows(() => unmount());
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// ============================================================================
|
|
68
|
+
// Props Tests
|
|
69
|
+
// ============================================================================
|
|
70
|
+
|
|
71
|
+
test('DevelopmentModeIndicator accepts all valid development modes', t => {
|
|
72
|
+
const modes = ['normal', 'auto-accept', 'plan'] as const;
|
|
73
|
+
|
|
74
|
+
for (const mode of modes) {
|
|
75
|
+
t.notThrows(() => {
|
|
76
|
+
render(
|
|
77
|
+
<DevelopmentModeIndicator developmentMode={mode} colors={mockColors} />,
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test('DevelopmentModeIndicator accepts colors object', t => {
|
|
84
|
+
t.notThrows(() => {
|
|
85
|
+
render(
|
|
86
|
+
<DevelopmentModeIndicator
|
|
87
|
+
developmentMode="normal"
|
|
88
|
+
colors={mockColors}
|
|
89
|
+
/>,
|
|
90
|
+
);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// ============================================================================
|
|
95
|
+
// Display Name Tests
|
|
96
|
+
// ============================================================================
|
|
97
|
+
|
|
98
|
+
test('DevelopmentModeIndicator has correct display name', t => {
|
|
99
|
+
t.is(DevelopmentModeIndicator.displayName, 'DevelopmentModeIndicator');
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// ============================================================================
|
|
103
|
+
// Content Tests
|
|
104
|
+
// ============================================================================
|
|
105
|
+
|
|
106
|
+
test('DevelopmentModeIndicator shows mode label in bold', t => {
|
|
107
|
+
const {lastFrame} = render(
|
|
108
|
+
<DevelopmentModeIndicator developmentMode="normal" colors={mockColors} />,
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
const output = lastFrame();
|
|
112
|
+
// Bold is represented by ANSI escape codes, check for the label
|
|
113
|
+
t.regex(output!, /normal mode on/);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test('DevelopmentModeIndicator shows instructions', t => {
|
|
117
|
+
const {lastFrame} = render(
|
|
118
|
+
<DevelopmentModeIndicator developmentMode="normal" colors={mockColors} />,
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
const output = lastFrame();
|
|
122
|
+
t.regex(output!, /\(Shift\+Tab to cycle\)/);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test('DevelopmentModeIndicator normal mode uses correct label', t => {
|
|
126
|
+
const {lastFrame} = render(
|
|
127
|
+
<DevelopmentModeIndicator developmentMode="normal" colors={mockColors} />,
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
const output = lastFrame();
|
|
131
|
+
t.regex(output!, /normal mode on/);
|
|
132
|
+
t.notRegex(output!, /auto-accept mode on/);
|
|
133
|
+
t.notRegex(output!, /plan mode on/);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test('DevelopmentModeIndicator auto-accept mode uses correct label', t => {
|
|
137
|
+
const {lastFrame} = render(
|
|
138
|
+
<DevelopmentModeIndicator
|
|
139
|
+
developmentMode="auto-accept"
|
|
140
|
+
colors={mockColors}
|
|
141
|
+
/>,
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
const output = lastFrame();
|
|
145
|
+
t.regex(output!, /auto-accept mode on/);
|
|
146
|
+
t.notRegex(output!, /normal mode on/);
|
|
147
|
+
t.notRegex(output!, /plan mode on/);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
test('DevelopmentModeIndicator plan mode uses correct label', t => {
|
|
151
|
+
const {lastFrame} = render(
|
|
152
|
+
<DevelopmentModeIndicator developmentMode="plan" colors={mockColors} />,
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
const output = lastFrame();
|
|
156
|
+
t.regex(output!, /plan mode on/);
|
|
157
|
+
t.notRegex(output!, /normal mode on/);
|
|
158
|
+
t.notRegex(output!, /auto-accept mode on/);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// ============================================================================
|
|
162
|
+
// Memoization Tests
|
|
163
|
+
// ============================================================================
|
|
164
|
+
|
|
165
|
+
test('DevelopmentModeIndicator is memoized', t => {
|
|
166
|
+
// React.memo components should have the same reference when props don't change
|
|
167
|
+
const firstRender = render(
|
|
168
|
+
<DevelopmentModeIndicator developmentMode="normal" colors={mockColors} />,
|
|
169
|
+
);
|
|
170
|
+
const firstOutput = firstRender.lastFrame();
|
|
171
|
+
|
|
172
|
+
const secondRender = render(
|
|
173
|
+
<DevelopmentModeIndicator developmentMode="normal" colors={mockColors} />,
|
|
174
|
+
);
|
|
175
|
+
const secondOutput = secondRender.lastFrame();
|
|
176
|
+
|
|
177
|
+
// Should produce the same output with same props
|
|
178
|
+
t.is(firstOutput, secondOutput);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test('DevelopmentModeIndicator updates when developmentMode changes', t => {
|
|
182
|
+
const {lastFrame, rerender} = render(
|
|
183
|
+
<DevelopmentModeIndicator developmentMode="normal" colors={mockColors} />,
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
const normalOutput = lastFrame();
|
|
187
|
+
t.regex(normalOutput!, /normal mode on/);
|
|
188
|
+
|
|
189
|
+
rerender(
|
|
190
|
+
<DevelopmentModeIndicator
|
|
191
|
+
developmentMode="auto-accept"
|
|
192
|
+
colors={mockColors}
|
|
193
|
+
/>,
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
const autoAcceptOutput = lastFrame();
|
|
197
|
+
t.regex(autoAcceptOutput!, /auto-accept mode on/);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// ============================================================================
|
|
201
|
+
// Structure Tests
|
|
202
|
+
// ============================================================================
|
|
203
|
+
|
|
204
|
+
test('DevelopmentModeIndicator has correct structure', t => {
|
|
205
|
+
const {lastFrame} = render(
|
|
206
|
+
<DevelopmentModeIndicator developmentMode="normal" colors={mockColors} />,
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
const output = lastFrame();
|
|
210
|
+
// Should have both the mode label and the instructions
|
|
211
|
+
t.regex(output!, /normal mode on/);
|
|
212
|
+
t.regex(output!, /\(Shift\+Tab to cycle\)/);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
test('DevelopmentModeIndicator component can be unmounted', t => {
|
|
216
|
+
const {unmount} = render(
|
|
217
|
+
<DevelopmentModeIndicator developmentMode="normal" colors={mockColors} />,
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
t.notThrows(() => {
|
|
221
|
+
unmount();
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
// ============================================================================
|
|
226
|
+
// Edge Cases
|
|
227
|
+
// ============================================================================
|
|
228
|
+
|
|
229
|
+
test('DevelopmentModeIndicator handles rapid mode changes', t => {
|
|
230
|
+
const {lastFrame, rerender} = render(
|
|
231
|
+
<DevelopmentModeIndicator developmentMode="normal" colors={mockColors} />,
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
// Cycle through modes rapidly
|
|
235
|
+
rerender(
|
|
236
|
+
<DevelopmentModeIndicator
|
|
237
|
+
developmentMode="auto-accept"
|
|
238
|
+
colors={mockColors}
|
|
239
|
+
/>,
|
|
240
|
+
);
|
|
241
|
+
rerender(
|
|
242
|
+
<DevelopmentModeIndicator developmentMode="plan" colors={mockColors} />,
|
|
243
|
+
);
|
|
244
|
+
rerender(
|
|
245
|
+
<DevelopmentModeIndicator developmentMode="normal" colors={mockColors} />,
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
const output = lastFrame();
|
|
249
|
+
t.regex(output!, /normal mode on/);
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
test('DevelopmentModeIndicator handles custom colors', t => {
|
|
253
|
+
const customColors = {
|
|
254
|
+
...mockColors,
|
|
255
|
+
secondary: '#123456',
|
|
256
|
+
info: '#789ABC',
|
|
257
|
+
warning: '#DEF012',
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
t.notThrows(() => {
|
|
261
|
+
render(
|
|
262
|
+
<DevelopmentModeIndicator
|
|
263
|
+
developmentMode="normal"
|
|
264
|
+
colors={customColors}
|
|
265
|
+
/>,
|
|
266
|
+
);
|
|
267
|
+
});
|
|
268
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type {useTheme} from '@/hooks/useTheme';
|
|
2
|
+
import {DEVELOPMENT_MODE_LABELS} from '@/types/core';
|
|
3
|
+
import type {DevelopmentMode} from '@/types/core';
|
|
4
|
+
import {Box, Text} from 'ink';
|
|
5
|
+
import React from 'react';
|
|
6
|
+
|
|
7
|
+
interface DevelopmentModeIndicatorProps {
|
|
8
|
+
developmentMode: DevelopmentMode;
|
|
9
|
+
colors: ReturnType<typeof useTheme>['colors'];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Development mode indicator component
|
|
14
|
+
* Shows the current development mode (normal/auto-accept/plan) and instructions
|
|
15
|
+
* Always visible to help users understand the current mode
|
|
16
|
+
*/
|
|
17
|
+
export const DevelopmentModeIndicator = React.memo(
|
|
18
|
+
({developmentMode, colors}: DevelopmentModeIndicatorProps) => {
|
|
19
|
+
return (
|
|
20
|
+
<Box marginTop={1}>
|
|
21
|
+
<Text
|
|
22
|
+
color={
|
|
23
|
+
developmentMode === 'normal'
|
|
24
|
+
? colors.secondary
|
|
25
|
+
: developmentMode === 'auto-accept'
|
|
26
|
+
? colors.info
|
|
27
|
+
: colors.warning
|
|
28
|
+
}
|
|
29
|
+
>
|
|
30
|
+
<Text bold>{DEVELOPMENT_MODE_LABELS[developmentMode]}</Text>{' '}
|
|
31
|
+
<Text dimColor>(Shift+Tab to cycle)</Text>
|
|
32
|
+
</Text>
|
|
33
|
+
</Box>
|
|
34
|
+
);
|
|
35
|
+
},
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
DevelopmentModeIndicator.displayName = 'DevelopmentModeIndicator';
|