@gguf/coder 0.3.1 → 0.3.2
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/package.json +2 -2
- package/pnpm-workspace.yaml +15 -0
- package/color_picker.html +0 -36
- package/scripts/extract-changelog.js +0 -73
- package/scripts/fetch-models.js +0 -143
- package/scripts/test.sh +0 -40
- package/scripts/update-homebrew-formula.sh +0 -125
- package/scripts/update-nix-version.sh +0 -157
- package/source/ai-sdk-client/AISDKClient.spec.ts +0 -117
- package/source/ai-sdk-client/AISDKClient.ts +0 -155
- package/source/ai-sdk-client/chat/chat-handler.spec.ts +0 -121
- package/source/ai-sdk-client/chat/chat-handler.ts +0 -276
- package/source/ai-sdk-client/chat/streaming-handler.spec.ts +0 -173
- package/source/ai-sdk-client/chat/streaming-handler.ts +0 -110
- package/source/ai-sdk-client/chat/tool-processor.spec.ts +0 -92
- package/source/ai-sdk-client/chat/tool-processor.ts +0 -70
- package/source/ai-sdk-client/converters/message-converter.spec.ts +0 -220
- package/source/ai-sdk-client/converters/message-converter.ts +0 -113
- package/source/ai-sdk-client/converters/tool-converter.spec.ts +0 -90
- package/source/ai-sdk-client/converters/tool-converter.ts +0 -46
- package/source/ai-sdk-client/error-handling/error-extractor.spec.ts +0 -55
- package/source/ai-sdk-client/error-handling/error-extractor.ts +0 -15
- package/source/ai-sdk-client/error-handling/error-parser.spec.ts +0 -169
- package/source/ai-sdk-client/error-handling/error-parser.ts +0 -161
- package/source/ai-sdk-client/index.ts +0 -7
- package/source/ai-sdk-client/providers/provider-factory.spec.ts +0 -71
- package/source/ai-sdk-client/providers/provider-factory.ts +0 -41
- package/source/ai-sdk-client/types.ts +0 -9
- package/source/ai-sdk-client-empty-message.spec.ts +0 -141
- package/source/ai-sdk-client-error-handling.spec.ts +0 -186
- package/source/ai-sdk-client-maxretries.spec.ts +0 -114
- package/source/ai-sdk-client-preparestep.spec.ts +0 -279
- package/source/app/App.spec.tsx +0 -32
- package/source/app/App.tsx +0 -480
- package/source/app/components/AppContainer.spec.tsx +0 -96
- package/source/app/components/AppContainer.tsx +0 -56
- package/source/app/components/ChatInterface.spec.tsx +0 -163
- package/source/app/components/ChatInterface.tsx +0 -144
- package/source/app/components/ModalSelectors.spec.tsx +0 -141
- package/source/app/components/ModalSelectors.tsx +0 -135
- package/source/app/helpers.spec.ts +0 -97
- package/source/app/helpers.ts +0 -63
- package/source/app/index.ts +0 -4
- package/source/app/types.ts +0 -39
- package/source/app/utils/appUtils.ts +0 -294
- package/source/app/utils/conversationState.ts +0 -310
- package/source/app.spec.tsx +0 -244
- package/source/cli.spec.ts +0 -73
- package/source/cli.tsx +0 -51
- package/source/client-factory.spec.ts +0 -48
- package/source/client-factory.ts +0 -178
- package/source/command-parser.spec.ts +0 -127
- package/source/command-parser.ts +0 -36
- package/source/commands/checkpoint.spec.tsx +0 -277
- package/source/commands/checkpoint.tsx +0 -366
- package/source/commands/clear.tsx +0 -22
- package/source/commands/custom-commands.tsx +0 -121
- package/source/commands/exit.ts +0 -21
- package/source/commands/export.spec.tsx +0 -131
- package/source/commands/export.tsx +0 -79
- package/source/commands/help.tsx +0 -120
- package/source/commands/index.ts +0 -17
- package/source/commands/init.tsx +0 -339
- package/source/commands/lsp-command.spec.tsx +0 -281
- package/source/commands/lsp.tsx +0 -120
- package/source/commands/mcp-command.spec.tsx +0 -313
- package/source/commands/mcp.tsx +0 -162
- package/source/commands/model-database.spec.tsx +0 -758
- package/source/commands/model-database.tsx +0 -418
- package/source/commands/model.ts +0 -12
- package/source/commands/provider.ts +0 -12
- package/source/commands/setup-config.tsx +0 -16
- package/source/commands/simple-commands.spec.tsx +0 -175
- package/source/commands/status.ts +0 -12
- package/source/commands/theme.ts +0 -12
- package/source/commands/update.spec.tsx +0 -261
- package/source/commands/update.tsx +0 -201
- package/source/commands/usage.spec.tsx +0 -495
- package/source/commands/usage.tsx +0 -100
- package/source/commands.spec.ts +0 -436
- package/source/commands.ts +0 -83
- package/source/components/assistant-message.spec.tsx +0 -796
- package/source/components/assistant-message.tsx +0 -34
- package/source/components/bash-execution-indicator.tsx +0 -21
- package/source/components/cancelling-indicator.tsx +0 -16
- package/source/components/chat-queue.spec.tsx +0 -83
- package/source/components/chat-queue.tsx +0 -36
- package/source/components/checkpoint-display.spec.tsx +0 -219
- package/source/components/checkpoint-display.tsx +0 -126
- package/source/components/checkpoint-selector.spec.tsx +0 -173
- package/source/components/checkpoint-selector.tsx +0 -173
- package/source/components/development-mode-indicator.spec.tsx +0 -268
- package/source/components/development-mode-indicator.tsx +0 -38
- package/source/components/message-box.spec.tsx +0 -427
- package/source/components/message-box.tsx +0 -87
- package/source/components/model-selector.tsx +0 -132
- package/source/components/provider-selector.tsx +0 -75
- package/source/components/random-spinner.tsx +0 -19
- package/source/components/security-disclaimer.tsx +0 -73
- package/source/components/status-connection-display.spec.tsx +0 -133
- package/source/components/status.tsx +0 -267
- package/source/components/theme-selector.tsx +0 -126
- package/source/components/tool-confirmation.tsx +0 -190
- package/source/components/tool-execution-indicator.tsx +0 -33
- package/source/components/tool-message.tsx +0 -85
- package/source/components/ui/titled-box.spec.tsx +0 -207
- package/source/components/ui/titled-box.tsx +0 -57
- package/source/components/usage/progress-bar.spec.tsx +0 -398
- package/source/components/usage/progress-bar.tsx +0 -30
- package/source/components/usage/usage-display.spec.tsx +0 -780
- package/source/components/usage/usage-display.tsx +0 -291
- package/source/components/user-input.spec.tsx +0 -327
- package/source/components/user-input.tsx +0 -533
- package/source/components/user-message.spec.tsx +0 -230
- package/source/components/user-message.tsx +0 -84
- package/source/components/welcome-message.tsx +0 -76
- package/source/config/env-substitution.ts +0 -65
- package/source/config/index.spec.ts +0 -171
- package/source/config/index.ts +0 -154
- package/source/config/paths.spec.ts +0 -241
- package/source/config/paths.ts +0 -55
- package/source/config/preferences.ts +0 -51
- package/source/config/themes.ts +0 -315
- package/source/constants.ts +0 -130
- package/source/context/mode-context.spec.ts +0 -79
- package/source/context/mode-context.ts +0 -24
- package/source/custom-commands/executor.spec.ts +0 -142
- package/source/custom-commands/executor.ts +0 -64
- package/source/custom-commands/loader.spec.ts +0 -314
- package/source/custom-commands/loader.ts +0 -153
- package/source/custom-commands/parser.ts +0 -196
- package/source/hooks/chat-handler/conversation/conversation-loop.spec.ts +0 -39
- package/source/hooks/chat-handler/conversation/conversation-loop.tsx +0 -511
- package/source/hooks/chat-handler/conversation/tool-executor.spec.ts +0 -50
- package/source/hooks/chat-handler/conversation/tool-executor.tsx +0 -109
- package/source/hooks/chat-handler/index.ts +0 -12
- package/source/hooks/chat-handler/state/streaming-state.spec.ts +0 -26
- package/source/hooks/chat-handler/state/streaming-state.ts +0 -19
- package/source/hooks/chat-handler/types.ts +0 -38
- package/source/hooks/chat-handler/useChatHandler.spec.tsx +0 -321
- package/source/hooks/chat-handler/useChatHandler.tsx +0 -194
- package/source/hooks/chat-handler/utils/context-checker.spec.ts +0 -60
- package/source/hooks/chat-handler/utils/context-checker.tsx +0 -73
- package/source/hooks/chat-handler/utils/message-helpers.spec.ts +0 -42
- package/source/hooks/chat-handler/utils/message-helpers.tsx +0 -36
- package/source/hooks/chat-handler/utils/tool-filters.spec.ts +0 -109
- package/source/hooks/chat-handler/utils/tool-filters.ts +0 -64
- package/source/hooks/useAppHandlers.tsx +0 -291
- package/source/hooks/useAppInitialization.tsx +0 -422
- package/source/hooks/useAppState.tsx +0 -311
- package/source/hooks/useDirectoryTrust.tsx +0 -98
- package/source/hooks/useInputState.ts +0 -414
- package/source/hooks/useModeHandlers.tsx +0 -302
- package/source/hooks/useNonInteractiveMode.ts +0 -140
- package/source/hooks/useTerminalWidth.tsx +0 -81
- package/source/hooks/useTheme.ts +0 -18
- package/source/hooks/useToolHandler.tsx +0 -349
- package/source/hooks/useUIState.ts +0 -61
- package/source/init/agents-template-generator.ts +0 -421
- package/source/init/existing-rules-extractor.ts +0 -319
- package/source/init/file-scanner.spec.ts +0 -227
- package/source/init/file-scanner.ts +0 -238
- package/source/init/framework-detector.ts +0 -382
- package/source/init/language-detector.ts +0 -269
- package/source/init/project-analyzer.spec.ts +0 -231
- package/source/init/project-analyzer.ts +0 -458
- package/source/lsp/index.ts +0 -31
- package/source/lsp/lsp-client.spec.ts +0 -508
- package/source/lsp/lsp-client.ts +0 -487
- package/source/lsp/lsp-manager.spec.ts +0 -477
- package/source/lsp/lsp-manager.ts +0 -419
- package/source/lsp/protocol.spec.ts +0 -502
- package/source/lsp/protocol.ts +0 -360
- package/source/lsp/server-discovery.spec.ts +0 -654
- package/source/lsp/server-discovery.ts +0 -515
- package/source/markdown-parser/html-entities.spec.ts +0 -88
- package/source/markdown-parser/html-entities.ts +0 -45
- package/source/markdown-parser/index.spec.ts +0 -281
- package/source/markdown-parser/index.ts +0 -126
- package/source/markdown-parser/table-parser.spec.ts +0 -133
- package/source/markdown-parser/table-parser.ts +0 -114
- package/source/markdown-parser/utils.spec.ts +0 -70
- package/source/markdown-parser/utils.ts +0 -13
- package/source/mcp/mcp-client.spec.ts +0 -81
- package/source/mcp/mcp-client.ts +0 -625
- package/source/mcp/transport-factory.spec.ts +0 -406
- package/source/mcp/transport-factory.ts +0 -312
- package/source/message-handler.ts +0 -67
- package/source/model-database/database-engine.spec.ts +0 -494
- package/source/model-database/database-engine.ts +0 -50
- package/source/model-database/model-database.spec.ts +0 -363
- package/source/model-database/model-database.ts +0 -91
- package/source/model-database/model-engine.spec.ts +0 -447
- package/source/model-database/model-engine.ts +0 -65
- package/source/model-database/model-fetcher.spec.ts +0 -583
- package/source/model-database/model-fetcher.ts +0 -330
- package/source/models/index.ts +0 -1
- package/source/models/models-cache.spec.ts +0 -214
- package/source/models/models-cache.ts +0 -78
- package/source/models/models-dev-client.spec.ts +0 -379
- package/source/models/models-dev-client.ts +0 -329
- package/source/models/models-types.ts +0 -68
- package/source/prompt-history.ts +0 -155
- package/source/security/command-injection.spec.ts +0 -240
- package/source/services/checkpoint-manager.spec.ts +0 -523
- package/source/services/checkpoint-manager.ts +0 -466
- package/source/services/file-snapshot.spec.ts +0 -569
- package/source/services/file-snapshot.ts +0 -220
- package/source/test-utils/render-with-theme.tsx +0 -48
- package/source/tokenization/index.ts +0 -1
- package/source/tokenization/tokenizer-factory.spec.ts +0 -170
- package/source/tokenization/tokenizer-factory.ts +0 -125
- package/source/tokenization/tokenizers/anthropic-tokenizer.spec.ts +0 -200
- package/source/tokenization/tokenizers/anthropic-tokenizer.ts +0 -43
- package/source/tokenization/tokenizers/fallback-tokenizer.spec.ts +0 -236
- package/source/tokenization/tokenizers/fallback-tokenizer.ts +0 -26
- package/source/tokenization/tokenizers/llama-tokenizer.spec.ts +0 -224
- package/source/tokenization/tokenizers/llama-tokenizer.ts +0 -41
- package/source/tokenization/tokenizers/openai-tokenizer.spec.ts +0 -184
- package/source/tokenization/tokenizers/openai-tokenizer.ts +0 -57
- package/source/tool-calling/index.ts +0 -5
- package/source/tool-calling/json-parser.spec.ts +0 -639
- package/source/tool-calling/json-parser.ts +0 -247
- package/source/tool-calling/tool-parser.spec.ts +0 -395
- package/source/tool-calling/tool-parser.ts +0 -120
- package/source/tool-calling/xml-parser.spec.ts +0 -662
- package/source/tool-calling/xml-parser.ts +0 -289
- package/source/tools/execute-bash.spec.tsx +0 -353
- package/source/tools/execute-bash.tsx +0 -219
- package/source/tools/execute-function.spec.ts +0 -130
- package/source/tools/fetch-url.spec.tsx +0 -342
- package/source/tools/fetch-url.tsx +0 -172
- package/source/tools/find-files.spec.tsx +0 -924
- package/source/tools/find-files.tsx +0 -293
- package/source/tools/index.ts +0 -102
- package/source/tools/lsp-get-diagnostics.tsx +0 -192
- package/source/tools/needs-approval.spec.ts +0 -282
- package/source/tools/read-file.spec.tsx +0 -801
- package/source/tools/read-file.tsx +0 -387
- package/source/tools/search-file-contents.spec.tsx +0 -1273
- package/source/tools/search-file-contents.tsx +0 -293
- package/source/tools/string-replace.spec.tsx +0 -730
- package/source/tools/string-replace.tsx +0 -548
- package/source/tools/tool-manager.ts +0 -210
- package/source/tools/tool-registry.spec.ts +0 -415
- package/source/tools/tool-registry.ts +0 -228
- package/source/tools/web-search.tsx +0 -223
- package/source/tools/write-file.spec.tsx +0 -559
- package/source/tools/write-file.tsx +0 -228
- package/source/types/app.ts +0 -37
- package/source/types/checkpoint.ts +0 -48
- package/source/types/commands.ts +0 -46
- package/source/types/components.ts +0 -27
- package/source/types/config.ts +0 -103
- package/source/types/core-connection-status.spec.ts +0 -67
- package/source/types/core.ts +0 -181
- package/source/types/hooks.ts +0 -50
- package/source/types/index.ts +0 -12
- package/source/types/markdown-parser.ts +0 -11
- package/source/types/mcp.ts +0 -52
- package/source/types/system.ts +0 -16
- package/source/types/tokenization.ts +0 -41
- package/source/types/ui.ts +0 -40
- package/source/types/usage.ts +0 -58
- package/source/types/utils.ts +0 -16
- package/source/usage/calculator.spec.ts +0 -385
- package/source/usage/calculator.ts +0 -104
- package/source/usage/storage.spec.ts +0 -703
- package/source/usage/storage.ts +0 -238
- package/source/usage/tracker.spec.ts +0 -456
- package/source/usage/tracker.ts +0 -102
- package/source/utils/atomic-deletion.spec.ts +0 -194
- package/source/utils/atomic-deletion.ts +0 -127
- package/source/utils/bounded-map.spec.ts +0 -300
- package/source/utils/bounded-map.ts +0 -193
- package/source/utils/checkpoint-utils.spec.ts +0 -222
- package/source/utils/checkpoint-utils.ts +0 -92
- package/source/utils/error-formatter.spec.ts +0 -169
- package/source/utils/error-formatter.ts +0 -194
- package/source/utils/file-autocomplete.spec.ts +0 -173
- package/source/utils/file-autocomplete.ts +0 -196
- package/source/utils/file-cache.spec.ts +0 -309
- package/source/utils/file-cache.ts +0 -195
- package/source/utils/file-content-loader.spec.ts +0 -180
- package/source/utils/file-content-loader.ts +0 -179
- package/source/utils/file-mention-handler.spec.ts +0 -261
- package/source/utils/file-mention-handler.ts +0 -84
- package/source/utils/file-mention-parser.spec.ts +0 -182
- package/source/utils/file-mention-parser.ts +0 -170
- package/source/utils/fuzzy-matching.spec.ts +0 -149
- package/source/utils/fuzzy-matching.ts +0 -146
- package/source/utils/indentation-normalizer.spec.ts +0 -216
- package/source/utils/indentation-normalizer.ts +0 -76
- package/source/utils/installation-detector.spec.ts +0 -178
- package/source/utils/installation-detector.ts +0 -153
- package/source/utils/logging/config.spec.ts +0 -311
- package/source/utils/logging/config.ts +0 -210
- package/source/utils/logging/console-facade.spec.ts +0 -184
- package/source/utils/logging/console-facade.ts +0 -384
- package/source/utils/logging/correlation.spec.ts +0 -679
- package/source/utils/logging/correlation.ts +0 -474
- package/source/utils/logging/formatters.spec.ts +0 -464
- package/source/utils/logging/formatters.ts +0 -207
- package/source/utils/logging/health-monitor/alerts/alert-manager.spec.ts +0 -93
- package/source/utils/logging/health-monitor/alerts/alert-manager.ts +0 -79
- package/source/utils/logging/health-monitor/checks/configuration-check.spec.ts +0 -56
- package/source/utils/logging/health-monitor/checks/configuration-check.ts +0 -43
- package/source/utils/logging/health-monitor/checks/logging-check.spec.ts +0 -56
- package/source/utils/logging/health-monitor/checks/logging-check.ts +0 -58
- package/source/utils/logging/health-monitor/checks/memory-check.spec.ts +0 -100
- package/source/utils/logging/health-monitor/checks/memory-check.ts +0 -78
- package/source/utils/logging/health-monitor/checks/performance-check.spec.ts +0 -56
- package/source/utils/logging/health-monitor/checks/performance-check.ts +0 -56
- package/source/utils/logging/health-monitor/checks/request-check.spec.ts +0 -56
- package/source/utils/logging/health-monitor/checks/request-check.ts +0 -76
- package/source/utils/logging/health-monitor/core/health-check-runner.spec.ts +0 -70
- package/source/utils/logging/health-monitor/core/health-check-runner.ts +0 -138
- package/source/utils/logging/health-monitor/core/health-monitor.spec.ts +0 -58
- package/source/utils/logging/health-monitor/core/health-monitor.ts +0 -344
- package/source/utils/logging/health-monitor/core/scoring.spec.ts +0 -65
- package/source/utils/logging/health-monitor/core/scoring.ts +0 -91
- package/source/utils/logging/health-monitor/index.ts +0 -15
- package/source/utils/logging/health-monitor/instances.ts +0 -48
- package/source/utils/logging/health-monitor/middleware/http-middleware.spec.ts +0 -141
- package/source/utils/logging/health-monitor/middleware/http-middleware.ts +0 -75
- package/source/utils/logging/health-monitor/types.ts +0 -126
- package/source/utils/logging/index.spec.ts +0 -284
- package/source/utils/logging/index.ts +0 -236
- package/source/utils/logging/integration.spec.ts +0 -441
- package/source/utils/logging/log-method-factory.spec.ts +0 -573
- package/source/utils/logging/log-method-factory.ts +0 -233
- package/source/utils/logging/log-query/aggregation/aggregator.spec.ts +0 -277
- package/source/utils/logging/log-query/aggregation/aggregator.ts +0 -159
- package/source/utils/logging/log-query/aggregation/facet-generator.spec.ts +0 -159
- package/source/utils/logging/log-query/aggregation/facet-generator.ts +0 -47
- package/source/utils/logging/log-query/index.ts +0 -23
- package/source/utils/logging/log-query/query/filter-predicates.spec.ts +0 -247
- package/source/utils/logging/log-query/query/filter-predicates.ts +0 -154
- package/source/utils/logging/log-query/query/query-builder.spec.ts +0 -182
- package/source/utils/logging/log-query/query/query-builder.ts +0 -151
- package/source/utils/logging/log-query/query/query-engine.spec.ts +0 -214
- package/source/utils/logging/log-query/query/query-engine.ts +0 -45
- package/source/utils/logging/log-query/storage/circular-buffer.spec.ts +0 -143
- package/source/utils/logging/log-query/storage/circular-buffer.ts +0 -75
- package/source/utils/logging/log-query/storage/index-manager.spec.ts +0 -150
- package/source/utils/logging/log-query/storage/index-manager.ts +0 -71
- package/source/utils/logging/log-query/storage/log-storage.spec.ts +0 -257
- package/source/utils/logging/log-query/storage/log-storage.ts +0 -80
- package/source/utils/logging/log-query/types.ts +0 -163
- package/source/utils/logging/log-query/utils/helpers.spec.ts +0 -263
- package/source/utils/logging/log-query/utils/helpers.ts +0 -72
- package/source/utils/logging/log-query/utils/sorting.spec.ts +0 -182
- package/source/utils/logging/log-query/utils/sorting.ts +0 -61
- package/source/utils/logging/logger-provider.spec.ts +0 -262
- package/source/utils/logging/logger-provider.ts +0 -362
- package/source/utils/logging/performance.spec.ts +0 -209
- package/source/utils/logging/performance.ts +0 -757
- package/source/utils/logging/pino-logger.spec.ts +0 -425
- package/source/utils/logging/pino-logger.ts +0 -514
- package/source/utils/logging/redaction.spec.ts +0 -490
- package/source/utils/logging/redaction.ts +0 -267
- package/source/utils/logging/request-tracker.spec.ts +0 -1198
- package/source/utils/logging/request-tracker.ts +0 -803
- package/source/utils/logging/transports.spec.ts +0 -505
- package/source/utils/logging/transports.ts +0 -305
- package/source/utils/logging/types.ts +0 -216
- package/source/utils/message-builder.spec.ts +0 -179
- package/source/utils/message-builder.ts +0 -101
- package/source/utils/message-queue.tsx +0 -486
- package/source/utils/paste-detection.spec.ts +0 -69
- package/source/utils/paste-detection.ts +0 -124
- package/source/utils/paste-roundtrip.spec.ts +0 -442
- package/source/utils/paste-utils.spec.ts +0 -128
- package/source/utils/paste-utils.ts +0 -52
- package/source/utils/programming-language-helper.spec.ts +0 -74
- package/source/utils/programming-language-helper.ts +0 -32
- package/source/utils/prompt-assembly.spec.ts +0 -221
- package/source/utils/prompt-processor.ts +0 -173
- package/source/utils/tool-args-parser.spec.ts +0 -136
- package/source/utils/tool-args-parser.ts +0 -54
- package/source/utils/tool-cancellation.spec.ts +0 -230
- package/source/utils/tool-cancellation.ts +0 -28
- package/source/utils/tool-result-display.spec.tsx +0 -469
- package/source/utils/tool-result-display.tsx +0 -90
- package/source/utils/update-checker.spec.ts +0 -383
- package/source/utils/update-checker.ts +0 -183
- package/source/wizard/config-wizard.spec.tsx +0 -103
- package/source/wizard/config-wizard.tsx +0 -382
- package/source/wizard/steps/location-step.spec.tsx +0 -186
- package/source/wizard/steps/location-step.tsx +0 -147
- package/source/wizard/steps/mcp-step.spec.tsx +0 -607
- package/source/wizard/steps/mcp-step.tsx +0 -632
- package/source/wizard/steps/provider-step.spec.tsx +0 -342
- package/source/wizard/steps/provider-step.tsx +0 -957
- package/source/wizard/steps/summary-step.spec.tsx +0 -749
- package/source/wizard/steps/summary-step.tsx +0 -228
- package/source/wizard/templates/mcp-templates.spec.ts +0 -613
- package/source/wizard/templates/mcp-templates.ts +0 -570
- package/source/wizard/templates/provider-templates.spec.ts +0 -152
- package/source/wizard/templates/provider-templates.ts +0 -485
- package/source/wizard/utils/fetch-cloud-models.spec.ts +0 -428
- package/source/wizard/utils/fetch-cloud-models.ts +0 -223
- package/source/wizard/utils/fetch-local-models.spec.ts +0 -297
- package/source/wizard/utils/fetch-local-models.ts +0 -192
- package/source/wizard/validation-array.spec.ts +0 -264
- package/source/wizard/validation.spec.ts +0 -373
- package/source/wizard/validation.ts +0 -232
|
@@ -1,382 +0,0 @@
|
|
|
1
|
-
import { spawnSync } from 'node:child_process';
|
|
2
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
|
-
import { dirname } from 'node:path';
|
|
4
|
-
import { TitledBox } from '@/components/ui/titled-box';
|
|
5
|
-
import { colors } from '@/config/index';
|
|
6
|
-
import { useResponsiveTerminal } from '@/hooks/useTerminalWidth';
|
|
7
|
-
import { logError } from '@/utils/message-queue';
|
|
8
|
-
import { Box, Text, useFocus, useInput } from 'ink';
|
|
9
|
-
import RandomSpinner from '@/components/random-spinner';
|
|
10
|
-
import { useEffect, useState } from 'react';
|
|
11
|
-
import type { ProviderConfig } from '../types/config';
|
|
12
|
-
import { type ConfigLocation, LocationStep } from './steps/location-step';
|
|
13
|
-
import { McpStep } from './steps/mcp-step';
|
|
14
|
-
import { ProviderStep } from './steps/provider-step';
|
|
15
|
-
import { SummaryStep } from './steps/summary-step';
|
|
16
|
-
import type { McpServerConfig } from './templates/mcp-templates';
|
|
17
|
-
import { buildConfigObject } from './validation';
|
|
18
|
-
|
|
19
|
-
interface ConfigWizardProps {
|
|
20
|
-
projectDir: string;
|
|
21
|
-
onComplete: (configPath: string) => void;
|
|
22
|
-
onCancel?: () => void;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
type WizardStep =
|
|
26
|
-
| 'location'
|
|
27
|
-
| 'providers'
|
|
28
|
-
| 'mcp'
|
|
29
|
-
| 'summary'
|
|
30
|
-
| 'editing'
|
|
31
|
-
| 'saving'
|
|
32
|
-
| 'complete';
|
|
33
|
-
|
|
34
|
-
export function ConfigWizard({
|
|
35
|
-
projectDir,
|
|
36
|
-
onComplete,
|
|
37
|
-
onCancel,
|
|
38
|
-
}: ConfigWizardProps) {
|
|
39
|
-
const [step, setStep] = useState<WizardStep>('location');
|
|
40
|
-
const [configPath, setConfigPath] = useState('');
|
|
41
|
-
const [providers, setProviders] = useState<ProviderConfig[]>([]);
|
|
42
|
-
const [mcpServers, setMcpServers] = useState<Record<string, McpServerConfig>>(
|
|
43
|
-
{},
|
|
44
|
-
);
|
|
45
|
-
const [error, setError] = useState<string | null>(null);
|
|
46
|
-
const { boxWidth, isNarrow } = useResponsiveTerminal();
|
|
47
|
-
|
|
48
|
-
// Capture focus to ensure keyboard handling works properly
|
|
49
|
-
useFocus({ autoFocus: true, id: 'config-wizard' });
|
|
50
|
-
|
|
51
|
-
// Load existing config if editing
|
|
52
|
-
useEffect(() => {
|
|
53
|
-
if (!configPath || !existsSync(configPath)) {
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Use a microtask to defer state updates
|
|
58
|
-
void Promise.resolve().then(() => {
|
|
59
|
-
try {
|
|
60
|
-
const configContent = readFileSync(configPath, 'utf-8');
|
|
61
|
-
const config = JSON.parse(configContent) as {
|
|
62
|
-
coder?: {
|
|
63
|
-
providers?: ProviderConfig[];
|
|
64
|
-
mcpServers?: Record<string, McpServerConfig>;
|
|
65
|
-
};
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
const newProviders = config.coder?.providers || [];
|
|
69
|
-
const newMcpServers = config.coder?.mcpServers || {};
|
|
70
|
-
|
|
71
|
-
setProviders(newProviders);
|
|
72
|
-
setMcpServers(newMcpServers);
|
|
73
|
-
} catch (err) {
|
|
74
|
-
logError('Failed to load existing configuration', true, {
|
|
75
|
-
context: { configPath },
|
|
76
|
-
error: err instanceof Error ? err.message : String(err),
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
}, [configPath]);
|
|
81
|
-
|
|
82
|
-
const handleLocationComplete = (_location: ConfigLocation, path: string) => {
|
|
83
|
-
setConfigPath(path);
|
|
84
|
-
setStep('providers');
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
const handleProvidersComplete = (newProviders: ProviderConfig[]) => {
|
|
88
|
-
setProviders(newProviders);
|
|
89
|
-
setStep('mcp');
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
const handleMcpComplete = (
|
|
93
|
-
newMcpServers: Record<string, McpServerConfig>,
|
|
94
|
-
) => {
|
|
95
|
-
setMcpServers(newMcpServers);
|
|
96
|
-
setStep('summary');
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
const handleSave = () => {
|
|
100
|
-
setStep('saving');
|
|
101
|
-
setError(null);
|
|
102
|
-
|
|
103
|
-
try {
|
|
104
|
-
// Build config object
|
|
105
|
-
const config = buildConfigObject(providers, mcpServers);
|
|
106
|
-
|
|
107
|
-
// Ensure directory exists
|
|
108
|
-
const dir = dirname(configPath);
|
|
109
|
-
if (!existsSync(dir)) {
|
|
110
|
-
mkdirSync(dir, { recursive: true });
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Write config file
|
|
114
|
-
writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
115
|
-
|
|
116
|
-
setStep('complete');
|
|
117
|
-
// Don't auto-complete - wait for user to press Enter
|
|
118
|
-
} catch (err) {
|
|
119
|
-
setError(
|
|
120
|
-
err instanceof Error ? err.message : 'Failed to save configuration',
|
|
121
|
-
);
|
|
122
|
-
setStep('summary');
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
const handleAddProviders = () => {
|
|
127
|
-
setStep('providers');
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
const handleAddMcpServers = () => {
|
|
131
|
-
setStep('mcp');
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
const handleCancel = () => {
|
|
135
|
-
if (onCancel) {
|
|
136
|
-
onCancel();
|
|
137
|
-
}
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
const openInEditor = () => {
|
|
141
|
-
try {
|
|
142
|
-
// Save current progress to file
|
|
143
|
-
const config = buildConfigObject(providers, mcpServers);
|
|
144
|
-
|
|
145
|
-
// Ensure directory exists
|
|
146
|
-
const dir = dirname(configPath);
|
|
147
|
-
if (!existsSync(dir)) {
|
|
148
|
-
mkdirSync(dir, { recursive: true });
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Write config file
|
|
152
|
-
writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
153
|
-
|
|
154
|
-
// Detect editor (respect $EDITOR or $VISUAL environment variables)
|
|
155
|
-
// Fall back to nano on Unix/Mac (much friendlier than vi!)
|
|
156
|
-
// On Windows, use notepad
|
|
157
|
-
const editor =
|
|
158
|
-
process.env.EDITOR ||
|
|
159
|
-
process.env.VISUAL ||
|
|
160
|
-
(process.platform === 'win32' ? 'notepad' : 'nano');
|
|
161
|
-
|
|
162
|
-
// Show cursor and restore terminal for editor
|
|
163
|
-
process.stdout.write('\x1B[?25h'); // Show cursor
|
|
164
|
-
process.stdin.setRawMode?.(false); // Disable raw mode
|
|
165
|
-
|
|
166
|
-
// Open editor and wait for it to close
|
|
167
|
-
const result = spawnSync(editor, [configPath], {
|
|
168
|
-
stdio: 'inherit', // Give editor full control of terminal
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
// Restore terminal state after editor closes
|
|
172
|
-
process.stdin.setRawMode?.(true); // Re-enable raw mode
|
|
173
|
-
process.stdout.write('\x1B[?25l'); // Hide cursor (Ink will manage it)
|
|
174
|
-
|
|
175
|
-
if (result.status === 0) {
|
|
176
|
-
// Reload the edited config
|
|
177
|
-
try {
|
|
178
|
-
const editedContent = readFileSync(configPath, 'utf-8');
|
|
179
|
-
const editedConfig = JSON.parse(editedContent) as {
|
|
180
|
-
coder?: {
|
|
181
|
-
providers?: ProviderConfig[];
|
|
182
|
-
mcpServers?: Record<string, McpServerConfig>;
|
|
183
|
-
};
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
// Update state with edited values
|
|
187
|
-
if (editedConfig.coder) {
|
|
188
|
-
setProviders(editedConfig.coder.providers || []);
|
|
189
|
-
setMcpServers(editedConfig.coder.mcpServers || {});
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// Return to summary to review changes
|
|
193
|
-
setStep('summary');
|
|
194
|
-
setError(null);
|
|
195
|
-
} catch (parseErr) {
|
|
196
|
-
setError(
|
|
197
|
-
parseErr instanceof Error
|
|
198
|
-
? `Invalid JSON: ${parseErr.message}`
|
|
199
|
-
: 'Failed to parse edited configuration',
|
|
200
|
-
);
|
|
201
|
-
setStep('summary');
|
|
202
|
-
}
|
|
203
|
-
} else {
|
|
204
|
-
setError('Editor exited with an error. Changes may not be saved.');
|
|
205
|
-
setStep('summary');
|
|
206
|
-
}
|
|
207
|
-
} catch (err) {
|
|
208
|
-
// Restore terminal state on error
|
|
209
|
-
process.stdin.setRawMode?.(true);
|
|
210
|
-
process.stdout.write('\x1B[?25l');
|
|
211
|
-
|
|
212
|
-
setError(
|
|
213
|
-
err instanceof Error
|
|
214
|
-
? `Failed to open editor: ${err.message}`
|
|
215
|
-
: 'Failed to open editor',
|
|
216
|
-
);
|
|
217
|
-
setStep('summary');
|
|
218
|
-
}
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
// Handle global keyboard shortcuts
|
|
222
|
-
useInput((input, key) => {
|
|
223
|
-
// In complete step, wait for Enter to finish
|
|
224
|
-
if (step === 'complete' && key.return) {
|
|
225
|
-
onComplete(configPath);
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// Escape - cancel/exit wizard completely
|
|
230
|
-
if (key.escape) {
|
|
231
|
-
if (onCancel) {
|
|
232
|
-
onCancel();
|
|
233
|
-
}
|
|
234
|
-
return;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// Ctrl+E to open editor (available after location is chosen)
|
|
238
|
-
if (
|
|
239
|
-
key.ctrl &&
|
|
240
|
-
input === 'e' &&
|
|
241
|
-
configPath &&
|
|
242
|
-
(step === 'providers' || step === 'mcp' || step === 'summary')
|
|
243
|
-
) {
|
|
244
|
-
openInEditor();
|
|
245
|
-
}
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
const renderStep = () => {
|
|
249
|
-
switch (step) {
|
|
250
|
-
case 'location': {
|
|
251
|
-
return (
|
|
252
|
-
<LocationStep
|
|
253
|
-
projectDir={projectDir}
|
|
254
|
-
onComplete={handleLocationComplete}
|
|
255
|
-
onBack={onCancel}
|
|
256
|
-
/>
|
|
257
|
-
);
|
|
258
|
-
}
|
|
259
|
-
case 'providers': {
|
|
260
|
-
return (
|
|
261
|
-
<ProviderStep
|
|
262
|
-
existingProviders={providers}
|
|
263
|
-
onComplete={handleProvidersComplete}
|
|
264
|
-
onBack={() => setStep('location')}
|
|
265
|
-
/>
|
|
266
|
-
);
|
|
267
|
-
}
|
|
268
|
-
case 'mcp': {
|
|
269
|
-
return (
|
|
270
|
-
<McpStep
|
|
271
|
-
existingServers={mcpServers}
|
|
272
|
-
onComplete={handleMcpComplete}
|
|
273
|
-
onBack={() => setStep('providers')}
|
|
274
|
-
/>
|
|
275
|
-
);
|
|
276
|
-
}
|
|
277
|
-
case 'summary': {
|
|
278
|
-
return (
|
|
279
|
-
<SummaryStep
|
|
280
|
-
configPath={configPath}
|
|
281
|
-
providers={providers}
|
|
282
|
-
mcpServers={mcpServers}
|
|
283
|
-
onSave={handleSave}
|
|
284
|
-
onAddProviders={handleAddProviders}
|
|
285
|
-
onAddMcpServers={handleAddMcpServers}
|
|
286
|
-
onCancel={handleCancel}
|
|
287
|
-
onBack={() => setStep('mcp')}
|
|
288
|
-
/>
|
|
289
|
-
);
|
|
290
|
-
}
|
|
291
|
-
case 'editing': {
|
|
292
|
-
return (
|
|
293
|
-
<Box flexDirection="column">
|
|
294
|
-
<Box marginBottom={1}>
|
|
295
|
-
<Text color={colors.primary}>Opening editor...</Text>
|
|
296
|
-
</Box>
|
|
297
|
-
<Box marginBottom={1}>
|
|
298
|
-
<Text dimColor>Configuration saved to: {configPath}</Text>
|
|
299
|
-
</Box>
|
|
300
|
-
<Box>
|
|
301
|
-
<Text color={colors.secondary}>
|
|
302
|
-
Save and close your editor to return to the wizard.
|
|
303
|
-
</Text>
|
|
304
|
-
</Box>
|
|
305
|
-
</Box>
|
|
306
|
-
);
|
|
307
|
-
}
|
|
308
|
-
case 'saving': {
|
|
309
|
-
return (
|
|
310
|
-
<Box flexDirection="column">
|
|
311
|
-
<Box>
|
|
312
|
-
<Text color={colors.success}>
|
|
313
|
-
<RandomSpinner /> Saving configuration...
|
|
314
|
-
</Text>
|
|
315
|
-
</Box>
|
|
316
|
-
</Box>
|
|
317
|
-
);
|
|
318
|
-
}
|
|
319
|
-
case 'complete': {
|
|
320
|
-
return (
|
|
321
|
-
<Box flexDirection="column">
|
|
322
|
-
<Box marginBottom={1}>
|
|
323
|
-
<Text color={colors.success} bold>
|
|
324
|
-
✓ Configuration saved!
|
|
325
|
-
</Text>
|
|
326
|
-
</Box>
|
|
327
|
-
<Box marginBottom={1}>
|
|
328
|
-
<Text dimColor>Saved to: {configPath}</Text>
|
|
329
|
-
</Box>
|
|
330
|
-
<Box>
|
|
331
|
-
<Text color={colors.secondary}>Press Enter to continue</Text>
|
|
332
|
-
</Box>
|
|
333
|
-
</Box>
|
|
334
|
-
);
|
|
335
|
-
}
|
|
336
|
-
default: {
|
|
337
|
-
return null;
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
};
|
|
341
|
-
|
|
342
|
-
return (
|
|
343
|
-
<TitledBox
|
|
344
|
-
title="Configuration Wizard"
|
|
345
|
-
width={boxWidth}
|
|
346
|
-
borderColor={colors.primary}
|
|
347
|
-
paddingX={2}
|
|
348
|
-
paddingY={1}
|
|
349
|
-
flexDirection="column"
|
|
350
|
-
marginBottom={1}
|
|
351
|
-
>
|
|
352
|
-
{error && (
|
|
353
|
-
<Box marginBottom={1}>
|
|
354
|
-
<Text color={colors.error}>Error: {error}</Text>
|
|
355
|
-
</Box>
|
|
356
|
-
)}
|
|
357
|
-
|
|
358
|
-
{renderStep()}
|
|
359
|
-
|
|
360
|
-
{(step === 'location' ||
|
|
361
|
-
step === 'providers' ||
|
|
362
|
-
step === 'mcp' ||
|
|
363
|
-
step === 'summary') &&
|
|
364
|
-
(isNarrow ? (
|
|
365
|
-
<Box marginTop={1} flexDirection="column">
|
|
366
|
-
<Text color={colors.secondary}>Esc: Exit wizard</Text>
|
|
367
|
-
<Text color={colors.secondary}>Shift+Tab: Go back</Text>
|
|
368
|
-
{configPath && (
|
|
369
|
-
<Text color={colors.secondary}>Ctrl+E: Edit manually</Text>
|
|
370
|
-
)}
|
|
371
|
-
</Box>
|
|
372
|
-
) : (
|
|
373
|
-
<Box marginTop={1}>
|
|
374
|
-
<Text color={colors.secondary}>
|
|
375
|
-
Esc: Exit wizard | Shift+Tab: Go back
|
|
376
|
-
{configPath && ' | Ctrl+E: Edit manually'}
|
|
377
|
-
</Text>
|
|
378
|
-
</Box>
|
|
379
|
-
))}
|
|
380
|
-
</TitledBox>
|
|
381
|
-
);
|
|
382
|
-
}
|
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
import test from 'ava';
|
|
2
|
-
import {render} from 'ink-testing-library';
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import {LocationStep} from './location-step.js';
|
|
5
|
-
|
|
6
|
-
// ============================================================================
|
|
7
|
-
// Tests for LocationStep Component Rendering
|
|
8
|
-
// ============================================================================
|
|
9
|
-
|
|
10
|
-
console.log(`\nlocation-step.spec.tsx – ${React.version}`);
|
|
11
|
-
|
|
12
|
-
test('LocationStep renders with location selection options', t => {
|
|
13
|
-
const {lastFrame} = render(
|
|
14
|
-
<LocationStep onComplete={() => {}} projectDir="/test/project" />,
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
const output = lastFrame();
|
|
18
|
-
t.truthy(output);
|
|
19
|
-
t.regex(output!, /Where would you like to create your configuration\?/);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
test('LocationStep shows project directory option', t => {
|
|
23
|
-
const {lastFrame} = render(
|
|
24
|
-
<LocationStep onComplete={() => {}} projectDir="/test/project" />,
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
const output = lastFrame();
|
|
28
|
-
t.regex(output!, /Current project directory/);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test('LocationStep shows global config option', t => {
|
|
32
|
-
const {lastFrame} = render(
|
|
33
|
-
<LocationStep onComplete={() => {}} projectDir="/test/project" />,
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
const output = lastFrame();
|
|
37
|
-
t.regex(output!, /Global user config/);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
test('LocationStep shows tip about config types', t => {
|
|
41
|
-
const {lastFrame} = render(
|
|
42
|
-
<LocationStep onComplete={() => {}} projectDir="/test/project" />,
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
const output = lastFrame();
|
|
46
|
-
t.regex(output!, /Project configs are useful for team settings/);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
// ============================================================================
|
|
50
|
-
// Tests for LocationStep Component Callbacks
|
|
51
|
-
// ============================================================================
|
|
52
|
-
|
|
53
|
-
test('LocationStep calls onComplete when provided', t => {
|
|
54
|
-
let completeCalled = false;
|
|
55
|
-
|
|
56
|
-
const {lastFrame} = render(
|
|
57
|
-
<LocationStep
|
|
58
|
-
onComplete={() => {
|
|
59
|
-
completeCalled = true;
|
|
60
|
-
}}
|
|
61
|
-
projectDir="/test/project"
|
|
62
|
-
/>,
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
t.truthy(lastFrame());
|
|
66
|
-
t.false(completeCalled); // Should not be called on render
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
test('LocationStep calls onBack when provided', t => {
|
|
70
|
-
let backCalled = false;
|
|
71
|
-
|
|
72
|
-
const {lastFrame} = render(
|
|
73
|
-
<LocationStep
|
|
74
|
-
onComplete={() => {}}
|
|
75
|
-
onBack={() => {
|
|
76
|
-
backCalled = true;
|
|
77
|
-
}}
|
|
78
|
-
projectDir="/test/project"
|
|
79
|
-
/>,
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
t.truthy(lastFrame());
|
|
83
|
-
t.false(backCalled); // Should not be called on render
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
// ============================================================================
|
|
87
|
-
// Tests for LocationStep Props Validation
|
|
88
|
-
// ============================================================================
|
|
89
|
-
|
|
90
|
-
test('LocationStep requires onComplete prop', t => {
|
|
91
|
-
const {lastFrame} = render(
|
|
92
|
-
<LocationStep onComplete={() => {}} projectDir="/test/project" />,
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
t.truthy(lastFrame());
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
test('LocationStep requires projectDir prop', t => {
|
|
99
|
-
const {lastFrame} = render(
|
|
100
|
-
<LocationStep onComplete={() => {}} projectDir="/test/project" />,
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
t.truthy(lastFrame());
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
test('LocationStep handles optional onBack prop', t => {
|
|
107
|
-
const {lastFrame} = render(
|
|
108
|
-
<LocationStep onComplete={() => {}} projectDir="/test/project" />,
|
|
109
|
-
);
|
|
110
|
-
|
|
111
|
-
t.truthy(lastFrame());
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
// ============================================================================
|
|
115
|
-
// Tests for LocationStep UI Elements
|
|
116
|
-
// ============================================================================
|
|
117
|
-
|
|
118
|
-
test('LocationStep renders SelectInput component', t => {
|
|
119
|
-
const {lastFrame} = render(
|
|
120
|
-
<LocationStep onComplete={() => {}} projectDir="/test/project" />,
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
const output = lastFrame();
|
|
124
|
-
t.truthy(output);
|
|
125
|
-
t.regex(output!, /Current project directory|Global user config/);
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
test('LocationStep renders with correct initial state', t => {
|
|
129
|
-
const {frames} = render(
|
|
130
|
-
<LocationStep onComplete={() => {}} projectDir="/test/project" />,
|
|
131
|
-
);
|
|
132
|
-
|
|
133
|
-
t.true(frames.length > 0);
|
|
134
|
-
|
|
135
|
-
const firstFrame = frames[0];
|
|
136
|
-
t.regex(firstFrame, /Where would you like to create your configuration\?/);
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
test('LocationStep renders without crashing', t => {
|
|
140
|
-
const {lastFrame} = render(
|
|
141
|
-
<LocationStep onComplete={() => {}} projectDir="/test/project" />,
|
|
142
|
-
);
|
|
143
|
-
|
|
144
|
-
t.truthy(lastFrame());
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
test('LocationStep accepts projectDir with different paths', t => {
|
|
148
|
-
const testPaths = [
|
|
149
|
-
'/home/user/project',
|
|
150
|
-
'/var/www/app',
|
|
151
|
-
'C:\\Users\\test\\project',
|
|
152
|
-
];
|
|
153
|
-
|
|
154
|
-
for (const projectDir of testPaths) {
|
|
155
|
-
const {lastFrame} = render(
|
|
156
|
-
<LocationStep onComplete={() => {}} projectDir={projectDir} />,
|
|
157
|
-
);
|
|
158
|
-
|
|
159
|
-
t.truthy(lastFrame());
|
|
160
|
-
}
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
// ============================================================================
|
|
164
|
-
// Tests for LocationStep Narrow Terminal Mode
|
|
165
|
-
// ============================================================================
|
|
166
|
-
|
|
167
|
-
test('LocationStep renders in narrow mode', t => {
|
|
168
|
-
// Note: This test verifies the component renders, but we can't easily
|
|
169
|
-
// simulate terminal width changes in tests
|
|
170
|
-
const {lastFrame} = render(
|
|
171
|
-
<LocationStep onComplete={() => {}} projectDir="/test/project" />,
|
|
172
|
-
);
|
|
173
|
-
|
|
174
|
-
t.truthy(lastFrame());
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
test('LocationStep shows config path information', t => {
|
|
178
|
-
const {lastFrame} = render(
|
|
179
|
-
<LocationStep onComplete={() => {}} projectDir="/test/project" />,
|
|
180
|
-
);
|
|
181
|
-
|
|
182
|
-
const output = lastFrame();
|
|
183
|
-
t.truthy(output);
|
|
184
|
-
// Should contain information about where configs will be created
|
|
185
|
-
t.regex(output!, /Current project directory|Global user config/);
|
|
186
|
-
});
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import { existsSync } from 'node:fs';
|
|
2
|
-
import { join } from 'node:path';
|
|
3
|
-
import { colors } from '@/config';
|
|
4
|
-
import { getConfigPath } from '@/config/paths';
|
|
5
|
-
import { useResponsiveTerminal } from '@/hooks/useTerminalWidth';
|
|
6
|
-
import { Box, Text, useInput } from 'ink';
|
|
7
|
-
import SelectInput from 'ink-select-input';
|
|
8
|
-
import { useState } from 'react';
|
|
9
|
-
|
|
10
|
-
export type ConfigLocation = 'project' | 'global';
|
|
11
|
-
|
|
12
|
-
interface LocationStepProps {
|
|
13
|
-
onComplete: (location: ConfigLocation, path: string) => void;
|
|
14
|
-
onBack?: () => void;
|
|
15
|
-
projectDir: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
interface LocationOption {
|
|
19
|
-
label: string;
|
|
20
|
-
value: ConfigLocation;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function LocationStep({
|
|
24
|
-
onComplete,
|
|
25
|
-
onBack,
|
|
26
|
-
projectDir,
|
|
27
|
-
}: LocationStepProps) {
|
|
28
|
-
const { isNarrow, truncatePath } = useResponsiveTerminal();
|
|
29
|
-
const projectPath = join(projectDir, 'coder.config.json');
|
|
30
|
-
const globalPath = join(getConfigPath(), 'coder.config.json');
|
|
31
|
-
|
|
32
|
-
const projectExists = existsSync(projectPath);
|
|
33
|
-
const globalExists = existsSync(globalPath);
|
|
34
|
-
|
|
35
|
-
const [mode, setMode] = useState<
|
|
36
|
-
'select-location' | 'existing-config' | null
|
|
37
|
-
>(() => {
|
|
38
|
-
// If project config exists, show existing config menu
|
|
39
|
-
if (projectExists) {
|
|
40
|
-
return 'existing-config';
|
|
41
|
-
}
|
|
42
|
-
// If global exists but project doesn't, still show location selection
|
|
43
|
-
// but we'll note the global config exists
|
|
44
|
-
return 'select-location';
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
const existingPath = projectExists ? projectPath : globalPath;
|
|
48
|
-
|
|
49
|
-
const locationOptions: LocationOption[] = [
|
|
50
|
-
{
|
|
51
|
-
label: `Current project directory`,
|
|
52
|
-
value: 'project',
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
label: `Global user config`,
|
|
56
|
-
value: 'global',
|
|
57
|
-
},
|
|
58
|
-
];
|
|
59
|
-
|
|
60
|
-
const existingConfigOptions = [
|
|
61
|
-
{ label: 'Edit this configuration', value: 'edit' },
|
|
62
|
-
{ label: 'Create new config in different location', value: 'new' },
|
|
63
|
-
];
|
|
64
|
-
|
|
65
|
-
const handleLocationSelect = (item: LocationOption) => {
|
|
66
|
-
const path = item.value === 'project' ? projectPath : globalPath;
|
|
67
|
-
onComplete(item.value, path);
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
const handleExistingConfigSelect = (item: { value: string }) => {
|
|
71
|
-
if (item.value === 'edit') {
|
|
72
|
-
const location: ConfigLocation = projectExists ? 'project' : 'global';
|
|
73
|
-
onComplete(location, existingPath);
|
|
74
|
-
} else if (item.value === 'new') {
|
|
75
|
-
setMode('select-location');
|
|
76
|
-
} else {
|
|
77
|
-
// Cancel
|
|
78
|
-
onBack?.();
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
// Handle Shift+Tab to go back from select-location to existing-config
|
|
83
|
-
useInput((_input, key) => {
|
|
84
|
-
if (key.shift && key.tab) {
|
|
85
|
-
// If we're in select-location mode and came from existing-config, go back
|
|
86
|
-
if (mode === 'select-location' && (projectExists || globalExists)) {
|
|
87
|
-
setMode('existing-config');
|
|
88
|
-
} else {
|
|
89
|
-
// Otherwise, let the parent wizard handle it
|
|
90
|
-
onBack?.();
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
if (mode === 'existing-config') {
|
|
96
|
-
return (
|
|
97
|
-
<Box flexDirection="column">
|
|
98
|
-
<Box marginBottom={1} flexDirection="column">
|
|
99
|
-
<Text bold color={colors.primary}>
|
|
100
|
-
Configuration found at:{' '}
|
|
101
|
-
</Text>
|
|
102
|
-
<Text color={colors.secondary}>
|
|
103
|
-
{isNarrow ? truncatePath(existingPath, 40) : existingPath}
|
|
104
|
-
</Text>
|
|
105
|
-
</Box>
|
|
106
|
-
<SelectInput
|
|
107
|
-
items={existingConfigOptions}
|
|
108
|
-
onSelect={(item: { value: string }) => handleExistingConfigSelect(item)}
|
|
109
|
-
/>
|
|
110
|
-
</Box>
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return (
|
|
115
|
-
<Box flexDirection="column">
|
|
116
|
-
<Box marginBottom={1}>
|
|
117
|
-
<Text bold color={colors.primary}>
|
|
118
|
-
{isNarrow
|
|
119
|
-
? 'Where to create config?'
|
|
120
|
-
: 'Where would you like to create your configuration?'}
|
|
121
|
-
</Text>
|
|
122
|
-
</Box>
|
|
123
|
-
{globalExists && !projectExists && (
|
|
124
|
-
<Box marginBottom={1} flexDirection="column">
|
|
125
|
-
<Text color={colors.warning}>
|
|
126
|
-
{isNarrow
|
|
127
|
-
? 'Note: Global config exists'
|
|
128
|
-
: 'Note: Global config exists at'}
|
|
129
|
-
</Text>
|
|
130
|
-
{!isNarrow && <Text color={colors.secondary}>{globalPath}</Text>}
|
|
131
|
-
</Box>
|
|
132
|
-
)}
|
|
133
|
-
<SelectInput
|
|
134
|
-
items={locationOptions}
|
|
135
|
-
onSelect={(item: LocationOption) => handleLocationSelect(item)}
|
|
136
|
-
/>
|
|
137
|
-
{!isNarrow && (
|
|
138
|
-
<Box marginTop={1}>
|
|
139
|
-
<Text color={colors.secondary}>
|
|
140
|
-
Tip: Project configs are useful for team settings. Global configs
|
|
141
|
-
work across all projects.
|
|
142
|
-
</Text>
|
|
143
|
-
</Box>
|
|
144
|
-
)}
|
|
145
|
-
</Box>
|
|
146
|
-
);
|
|
147
|
-
}
|