@minniexcode/codex-switch 0.1.0 → 0.1.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.
Files changed (68) hide show
  1. package/README.AI.md +141 -110
  2. package/README.CN.md +215 -179
  3. package/README.md +224 -183
  4. package/dist/app/add-provider.js +16 -23
  5. package/dist/app/bridge.js +2 -1
  6. package/dist/app/edit-provider.js +30 -65
  7. package/dist/app/get-current-profile.js +15 -3
  8. package/dist/app/get-status.js +11 -8
  9. package/dist/app/list-config-profiles.js +3 -1
  10. package/dist/app/list-providers.js +10 -4
  11. package/dist/app/remove-provider.js +52 -19
  12. package/dist/app/run-doctor.js +26 -29
  13. package/dist/app/setup-codex.js +3 -3
  14. package/dist/app/show-config.js +3 -1
  15. package/dist/app/switch-provider.js +38 -6
  16. package/dist/cli/output.js +29 -19
  17. package/dist/commands/handlers.js +3 -2
  18. package/dist/commands/help.js +3 -3
  19. package/dist/commands/registry.js +29 -29
  20. package/dist/domain/config.js +293 -209
  21. package/dist/domain/providers.js +8 -0
  22. package/dist/domain/runtime-state.js +15 -15
  23. package/dist/domain/setup.js +3 -1
  24. package/dist/interaction/interactive.js +2 -2
  25. package/dist/runtime/codex-version.js +7 -0
  26. package/dist/runtime/copilot-adapter.js +326 -70
  27. package/dist/runtime/copilot-bridge-worker.js +27 -2
  28. package/dist/runtime/copilot-bridge.js +192 -10
  29. package/dist/runtime/copilot-cli.js +7 -0
  30. package/dist/runtime/copilot-installer.js +59 -1
  31. package/dist/runtime/copilot-sdk-loader.js +4 -1
  32. package/dist/storage/config-repo.js +6 -14
  33. package/docs/Design/codex-switch-v0.1.0-design.md +32 -152
  34. package/docs/Design/codex-switch-v0.1.1-design.md +22 -0
  35. package/docs/Design/codex-switch-v0.1.2-design.md +65 -0
  36. package/docs/PRD/codex-switch-prd-v0.1.0.md +65 -217
  37. package/docs/PRD/codex-switch-prd-v0.1.1.md +26 -0
  38. package/docs/PRD/codex-switch-prd-v0.1.2.md +41 -0
  39. package/docs/Reference/codex-config-reference.md +41 -0
  40. package/docs/Reference/codex-config-reference.zh-CN.md +41 -0
  41. package/docs/Tests/testing.md +1 -1
  42. package/docs/cli-usage.md +290 -223
  43. package/docs/codex-switch-command-design.md +2 -2
  44. package/docs/codex-switch-product-overview.md +18 -13
  45. package/docs/codex-switch-product-research.md +2 -2
  46. package/docs/codex-switch-technical-architecture.md +84 -1115
  47. package/package.json +2 -2
  48. package/docs/Design/codex-switch-copilot-integration-design.md +0 -517
  49. package/docs/Design/codex-switch-v0.0.10-design.md +0 -669
  50. package/docs/Design/codex-switch-v0.0.11-design.md +0 -824
  51. package/docs/Design/codex-switch-v0.0.12-design.md +0 -343
  52. package/docs/Design/codex-switch-v0.0.4-design.md +0 -874
  53. package/docs/Design/codex-switch-v0.0.5-design.md +0 -932
  54. package/docs/Design/codex-switch-v0.0.6-design.md +0 -708
  55. package/docs/Design/codex-switch-v0.0.7-design.md +0 -862
  56. package/docs/Design/codex-switch-v0.0.8-design.md +0 -132
  57. package/docs/Design/codex-switch-v0.0.9-design.md +0 -182
  58. package/docs/Design/codex-switch-v0.0.9-to-v0.0.12-roadmap.md +0 -413
  59. package/docs/PRD/codex-switch-prd-v0.0.10.md +0 -406
  60. package/docs/PRD/codex-switch-prd-v0.0.11.md +0 -577
  61. package/docs/PRD/codex-switch-prd-v0.0.12.md +0 -279
  62. package/docs/PRD/codex-switch-prd-v0.0.5-to-v0.1.0.md +0 -446
  63. package/docs/PRD/codex-switch-prd-v0.0.8.md +0 -62
  64. package/docs/PRD/codex-switch-prd-v0.0.9.md +0 -166
  65. package/docs/PRD/codex-switch-prd.md +0 -650
  66. package/docs/Tests/test-report-0.0.5.md +0 -163
  67. package/docs/Tests/test-report-0.0.7.md +0 -118
  68. package/docs/Tests/testing-bridge-v0.0.9.md +0 -367
package/README.md CHANGED
@@ -1,183 +1,224 @@
1
- # @minniexcode/codex-switch
2
-
3
- `@minniexcode/codex-switch` is a local-first CLI for managing and switching Codex provider and profile configuration safely.
4
-
5
- It keeps `codex-switch` tool state separate from the target Codex runtime, so provider management, backup flow, and runtime projection stay explicit instead of relying on manual file edits.
6
-
7
- Chinese version: [README.CN.md](./README.CN.md)
8
-
9
- ## Version
10
-
11
- Current package version: `0.1.0`
12
-
13
- This is the first stable release line. The current release focuses on keeping the primary workflows, help text, operational boundaries, and release docs aligned with the implementation.
14
-
15
- ## Install
16
-
17
- ```bash
18
- npm install -g @minniexcode/codex-switch
19
- ```
20
-
21
- Run without a global install:
22
-
23
- ```bash
24
- npx @minniexcode/codex-switch --help
25
- ```
26
-
27
- Built CLI entrypoint:
28
-
29
- ```bash
30
- codexs --help
31
- ```
32
-
33
- ## Primary Workflows
34
-
35
- Direct provider workflow:
36
-
37
- ```bash
38
- codexs init
39
- codexs add my-provider --profile my-provider --api-key sk-xxx
40
- codexs switch my-provider
41
- codexs status
42
- codexs doctor
43
- ```
44
-
45
- GitHub Copilot workflow:
46
-
47
- ```bash
48
- codexs init
49
- codexs login copilot
50
- codexs add copilot-main --copilot --profile copilot-main
51
- codexs switch copilot-main
52
- codexs status
53
- codexs doctor
54
- ```
55
-
56
- Notes:
57
-
58
- - `init` prepares the `codex-switch` tool home and managed state.
59
- - `login copilot` handles upstream Copilot onboarding and auth readiness.
60
- - `add --copilot` does not perform login for you; it assumes Copilot login is already ready.
61
- - `status` is the main read command after switching.
62
- - `doctor` is the main repair-oriented diagnostic command.
63
-
64
- ## Advanced Adopt Workflow
65
-
66
- Use `migrate` only when you already have Codex runtime state that should be adopted into managed `providers.json` state:
67
-
68
- ```bash
69
- codexs init
70
- codexs migrate
71
- ```
72
-
73
- `migrate` is an advanced adopt helper. It is not the default first step for a fresh install.
74
-
75
- ## Command Surface
76
-
77
- ```bash
78
- codexs init
79
- codexs login copilot
80
- codexs migrate
81
- codexs list
82
- codexs show <provider>
83
- codexs current
84
- codexs status
85
- codexs config show [profile]
86
- codexs config list-profiles
87
- codexs add <provider> --profile <name> --api-key <key>
88
- codexs add <provider> --copilot --profile <name>
89
- codexs edit <provider>
90
- codexs switch <provider>
91
- codexs remove <provider> [--force] [--switch-to <profile>]
92
- codexs import <file>
93
- codexs export <file> [--force]
94
- codexs bridge start [provider]
95
- codexs bridge status [provider]
96
- codexs bridge stop [provider]
97
- codexs backups list
98
- codexs rollback [backup-id]
99
- codexs doctor
100
- ```
101
-
102
- `setup` still exists only as a deprecated compatibility entry that points callers to `init` or `migrate`.
103
-
104
- ## Runtime Model
105
-
106
- `codex-switch` uses a dual-path model.
107
-
108
- Tool home:
109
-
110
- ```text
111
- ~/.config/codex-switch/
112
- codex-switch.json
113
- providers.json
114
- backups/
115
- runtime/
116
- runtimes/
117
- ```
118
-
119
- Target Codex runtime:
120
-
121
- ```text
122
- ~/.codex/
123
- config.toml
124
- auth.json
125
- ```
126
-
127
- Key points:
128
-
129
- - `providers.json` is the managed provider registry and lives under the tool home.
130
- - `codex-switch.json` stores tool-level metadata such as `defaultCodexDir`.
131
- - `config.toml` remains the active runtime routing file in the target Codex directory.
132
- - `auth.json` remains the active auth projection file in the target Codex directory.
133
- - Direct providers rewrite `OPENAI_API_KEY` into the active runtime projection.
134
- - Copilot providers keep upstream GitHub authentication in the official Copilot runtime while `codex-switch` manages local bridge state and routing.
135
-
136
- Path controls:
137
-
138
- - `--codex-dir <path>` targets a specific Codex runtime directory.
139
- - `CODEXS_CODEX_DIR` provides the default target runtime when `--codex-dir` is not passed.
140
- - `CODEXS_HOME` overrides the tool home location.
141
-
142
- ## Automation Notes
143
-
144
- This CLI supports both human TTY usage and non-interactive automation.
145
-
146
- Global flags:
147
-
148
- ```bash
149
- --json
150
- --codex-dir <path>
151
- --help
152
- --version
153
- ```
154
-
155
- Operational limits:
156
-
157
- - `login copilot` requires a real TTY and does not support `--json`.
158
- - `migrate` remains interactive when provider adoption requires human input.
159
- - Automation should pass explicit arguments and prefer `--json` for stable parsing.
160
-
161
- ## Local Development
162
-
163
- ```bash
164
- npm run build
165
- npm test
166
- npx tsc --noEmit
167
- node dist/cli.js --help
168
- npm pack --dry-run
169
- ```
170
-
171
- ## Documentation
172
-
173
- - [Chinese README](./README.CN.md)
174
- - [AI README](./README.AI.md)
175
- - [Detailed CLI Usage](./docs/cli-usage.md)
176
- - [Testing Guide](./docs/Tests/testing.md)
177
- - [Product Overview](./docs/codex-switch-product-overview.md)
178
- - [Release PRD 0.1.0](./docs/PRD/codex-switch-prd-v0.1.0.md)
179
- - [Release Gate PRD 0.1.0](./docs/PRD/codex-switch-prd-v0.1.0.md)
180
-
181
- ## License
182
-
183
- MIT
1
+ # @minniexcode/codex-switch
2
+
3
+ `@minniexcode/codex-switch` is a local-first CLI for managing and switching Codex provider and model-provider routing safely.
4
+
5
+ It keeps `codex-switch` tool state separate from the target Codex runtime, so provider management, backup flow, and runtime projection stay explicit instead of relying on manual file edits.
6
+
7
+ Chinese version: [README.CN.md](./README.CN.md)
8
+
9
+ ## Version
10
+
11
+ Current package version: `0.1.2`
12
+
13
+ This is the current stable documentation line. `0.1.2` is the Copilot runtime repair release, including the managed SDK pin and the Copilot-only `stream_idle_timeout_ms = 300000` projection used to prevent long prompt idle timeouts.
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ npm install -g @minniexcode/codex-switch
19
+ ```
20
+
21
+ Run without a global install:
22
+
23
+ ```bash
24
+ npx @minniexcode/codex-switch --help
25
+ ```
26
+
27
+ Built CLI entrypoint:
28
+
29
+ ```bash
30
+ codexs --help
31
+ ```
32
+
33
+ ## Primary Workflows
34
+
35
+ Direct provider workflow:
36
+
37
+ ```bash
38
+ codexs init
39
+ codexs add my-provider --model gpt-5.5 --base-url https://gateway.example.com/v1 --api-key sk-xxx
40
+ codexs switch my-provider
41
+ codexs status
42
+ codexs doctor
43
+ ```
44
+
45
+ GitHub Copilot workflow:
46
+
47
+ ```bash
48
+ codexs init
49
+ codexs login copilot
50
+ codexs add copilot-main --copilot --model gpt-4.1
51
+ codexs switch copilot-main
52
+ codexs status
53
+ codexs doctor
54
+ ```
55
+
56
+ Notes:
57
+
58
+ - `init` prepares the `codex-switch` tool home and managed state.
59
+ - `login copilot` handles upstream Copilot onboarding and auth readiness.
60
+ - `add --copilot` does not perform login for you; it assumes Copilot login is already ready.
61
+ - Copilot support is an experimental local bridge. The managed installer defaults to `@github/copilot-sdk@1.0.2`, Copilot runtime paths require Node.js `>=20`, and runtime checks separately reject older or prerelease SDK installs while validating API shape when the client or session is used.
62
+ - `switch` projects the selected provider into the target Codex runtime as top-level `model` plus `model_provider`.
63
+ - `status` is the main read command after switching.
64
+ - `doctor` is the main repair-oriented diagnostic command.
65
+
66
+ ## Runtime Routing Model
67
+
68
+ For Codex `0.134.0+`, the active runtime route is selected through top-level `model` and `model_provider` in `config.toml`.
69
+
70
+ `codex-switch` treats that route as the runtime contract:
71
+
72
+ - top-level `model` selects the active model id
73
+ - top-level `model_provider` selects the active provider route
74
+ - managed `[model_providers.<id>]` entries are the projected runtime provider definitions
75
+ - `--profile` is only an alias for the managed `model_provider` id, not the primary runtime selector
76
+
77
+ Direct-provider projection writes:
78
+
79
+ - top-level `model`
80
+ - top-level `model_provider`
81
+ - `[model_providers.<id>]`
82
+ - `auth.json` with `OPENAI_API_KEY`
83
+
84
+ Managed direct-provider projection does not keep `env_key` or `env_key_instructions` in the generated runtime config. `switch`, `add`, and `edit` clean old legacy projection fields before writing the active route.
85
+
86
+ For managed OpenAI-compatible routes, the projected provider entry keeps the fixed runtime shape:
87
+
88
+ ```toml
89
+ model = "gpt-5.5"
90
+ model_provider = "my-provider"
91
+
92
+ [model_providers.my-provider]
93
+ name = "my-provider"
94
+ base_url = "https://gateway.example.com/v1"
95
+ wire_api = "responses"
96
+ requires_openai_auth = true
97
+ ```
98
+
99
+ Managed Copilot projection additionally writes:
100
+
101
+ ```toml
102
+ stream_idle_timeout_ms = 300000
103
+ ```
104
+
105
+ ## Advanced Adopt Workflow
106
+
107
+ Use `migrate` only when you already have Codex runtime state that should be adopted into managed `providers.json` state:
108
+
109
+ ```bash
110
+ codexs init
111
+ codexs migrate
112
+ ```
113
+
114
+ `migrate` is an advanced adopt helper. It is not the default first step for a fresh install.
115
+
116
+ ## Command Surface
117
+
118
+ ```bash
119
+ codexs init
120
+ codexs login copilot
121
+ codexs migrate
122
+ codexs list
123
+ codexs show <provider>
124
+ codexs current
125
+ codexs status
126
+ codexs config show [profile]
127
+ codexs config list-profiles
128
+ codexs add <provider> --model <model> --api-key <key> [--base-url <url>]
129
+ codexs add <provider> --copilot --model <model>
130
+ codexs edit <provider>
131
+ codexs switch <provider>
132
+ codexs remove <provider> [--force] [--switch-to <provider>]
133
+ codexs import <file>
134
+ codexs export <file> [--force]
135
+ codexs bridge start [provider]
136
+ codexs bridge status [provider]
137
+ codexs bridge stop [provider]
138
+ codexs backups list
139
+ codexs rollback [backup-id]
140
+ codexs doctor
141
+ ```
142
+
143
+ `setup` still exists only as a deprecated compatibility entry that points callers to `init` or `migrate`.
144
+
145
+ ## Runtime Model
146
+
147
+ Tool home:
148
+
149
+ ```text
150
+ ~/.config/codex-switch/
151
+ codex-switch.json
152
+ providers.json
153
+ backups/
154
+ runtime/
155
+ runtimes/
156
+ ```
157
+
158
+ Target Codex runtime:
159
+
160
+ ```text
161
+ ~/.codex/
162
+ config.toml
163
+ auth.json
164
+ ```
165
+
166
+ Key points:
167
+
168
+ - `providers.json` is the managed provider registry and lives under the tool home.
169
+ - `codex-switch.json` stores tool-level metadata such as `defaultCodexDir`.
170
+ - `config.toml` remains the active runtime routing file in the target Codex directory.
171
+ - `auth.json` remains the active auth projection file in the target Codex directory.
172
+ - Direct providers rewrite `OPENAI_API_KEY` into the active runtime projection.
173
+ - Copilot providers keep upstream GitHub authentication in the official Copilot runtime while `codex-switch` manages local bridge state and routing.
174
+
175
+ Path controls:
176
+
177
+ - `--codex-dir <path>` targets a specific Codex runtime directory.
178
+ - `CODEXS_CODEX_DIR` provides the default target runtime when `--codex-dir` is not passed.
179
+ - `CODEXS_HOME` overrides the tool home location.
180
+
181
+ ## Automation Notes
182
+
183
+ This CLI supports both human TTY usage and non-interactive automation.
184
+
185
+ Global flags:
186
+
187
+ ```bash
188
+ --json
189
+ --codex-dir <path>
190
+ --help
191
+ --version
192
+ ```
193
+
194
+ Operational limits:
195
+
196
+ - `login copilot` requires a real TTY and does not support `--json`.
197
+ - `migrate` remains interactive when provider adoption requires human input.
198
+ - Automation should pass explicit arguments and prefer `--json` for stable parsing.
199
+
200
+ ## Local Development
201
+
202
+ ```bash
203
+ npm run build
204
+ npm test
205
+ npx tsc --noEmit
206
+ node dist/cli.js --help
207
+ npm pack --dry-run
208
+ ```
209
+
210
+ ## Documentation
211
+
212
+ - [Chinese README](./README.CN.md)
213
+ - [AI README](./README.AI.md)
214
+ - [Detailed CLI Usage](./docs/cli-usage.md)
215
+ - [Testing Guide](./docs/Tests/testing.md)
216
+ - [Product Overview](./docs/codex-switch-product-overview.md)
217
+ - [PRD 0.1.0](./docs/PRD/codex-switch-prd-v0.1.0.md)
218
+ - [PRD 0.1.1](./docs/PRD/codex-switch-prd-v0.1.1.md)
219
+ - [PRD 0.1.2](./docs/PRD/codex-switch-prd-v0.1.2.md)
220
+ - [Design 0.1.2](./docs/Design/codex-switch-v0.1.2-design.md)
221
+
222
+ ## License
223
+
224
+ MIT
@@ -35,7 +35,6 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.addProvider = addProvider;
37
37
  const crypto = __importStar(require("node:crypto"));
38
- const config_1 = require("../domain/config");
39
38
  const providers_1 = require("../domain/providers");
40
39
  const errors_1 = require("../domain/errors");
41
40
  const config_repo_1 = require("../storage/config-repo");
@@ -68,6 +67,7 @@ async function addProvider(args) {
68
67
  }
69
68
  : undefined;
70
69
  if (args.copilot) {
70
+ (0, copilot_installer_1.assertCopilotNodeRuntimeSupported)();
71
71
  const installStatus = (0, copilot_installer_1.probeCopilotSdkInstall)(args.runtimesDir);
72
72
  if (!installStatus.installed) {
73
73
  throw (0, errors_1.cliError)("COPILOT_SDK_MISSING", "The optional Copilot SDK runtime is not installed. Run `codexs login copilot` first.", {
@@ -91,24 +91,19 @@ async function addProvider(args) {
91
91
  }
92
92
  }
93
93
  const document = (0, config_repo_1.readStructuredConfig)(args.configPath);
94
- const existingProfile = document.profiles.find((profile) => profile.name === args.profile);
95
94
  const existingModelProvider = document.modelProviders.find((entry) => entry.name === args.profile);
96
- if (!existingProfile && !args.createProfile) {
97
- throw (0, errors_1.cliError)("PROFILE_NOT_FOUND", `Profile "${args.profile}" does not exist in config.toml.`, {
98
- profile: args.profile,
95
+ const inheritedModel = document.currentModel ?? undefined;
96
+ const providerModel = args.model ?? inheritedModel;
97
+ if (!providerModel) {
98
+ throw (0, errors_1.cliError)("MANAGED_PROFILE_FIELDS_MISSING", `Provider "${args.providerName}" requires a model.`, {
99
99
  provider: args.providerName,
100
+ modelProvider: args.profile,
101
+ missingFields: ["model"],
102
+ suggestion: "Pass `--model <name>` or set a top-level model in config.toml first.",
100
103
  });
101
104
  }
102
105
  const directBaseUrl = args.baseUrl;
103
- const upsertProfiles = !existingProfile && args.createProfile
104
- ? {
105
- [args.profile]: (0, config_1.validateManagedProfileCreation)(args.profile, {
106
- model: args.model ?? undefined,
107
- modelProvider: args.profile,
108
- }),
109
- }
110
- : undefined;
111
- if (!args.copilot && !existingModelProvider && args.createProfile && (!directBaseUrl || directBaseUrl.trim() === "")) {
106
+ if (!args.copilot && (!directBaseUrl || directBaseUrl.trim() === "") && !existingModelProvider) {
112
107
  throw (0, errors_1.cliError)("MANAGED_PROFILE_FIELDS_MISSING", `Model provider "${args.profile}" requires base_url.`, {
113
108
  profile: args.profile,
114
109
  modelProvider: args.profile,
@@ -119,14 +114,9 @@ async function addProvider(args) {
119
114
  ? {
120
115
  [args.profile]: (0, providers_1.buildCopilotModelProviderProjection)(runtime),
121
116
  }
122
- : !existingModelProvider && args.createProfile
123
- ? {
124
- [args.profile]: (0, providers_1.buildDirectModelProviderProjection)(args.profile, directBaseUrl),
125
- }
126
- : undefined;
127
- if (existingProfile) {
128
- (0, config_repo_1.requireManagedProfileRuntime)(document, providers, args.profile);
129
- }
117
+ : {
118
+ [args.profile]: (0, providers_1.buildDirectModelProviderProjection)(args.profile, (directBaseUrl ?? existingModelProvider?.baseUrl ?? "").trim()),
119
+ };
130
120
  const apiKey = args.copilot ? args.bridgeApiKey ?? crypto.randomBytes(24).toString("hex") : args.apiKey;
131
121
  const baseUrl = args.copilot ? (0, providers_1.buildCopilotBridgeBaseUrl)(runtime) : args.baseUrl ?? undefined;
132
122
  const next = {
@@ -135,6 +125,7 @@ async function addProvider(args) {
135
125
  [args.providerName]: (0, providers_1.cleanProviderRecord)({
136
126
  profile: args.profile,
137
127
  apiKey,
128
+ model: providerModel,
138
129
  baseUrl,
139
130
  note: args.note ?? undefined,
140
131
  tags: args.tags,
@@ -153,14 +144,16 @@ async function addProvider(args) {
153
144
  ],
154
145
  mutate: () => {
155
146
  const configPlan = (0, config_repo_1.createConfigMutationPlan)(document, {
156
- upsertProfiles,
157
147
  upsertModelProviders,
148
+ scrubModelProviderEnvKeys: [args.profile],
158
149
  });
159
150
  // Persist only the normalized provider payload so later reads are deterministic.
160
151
  (0, providers_repo_1.writeProvidersFile)(args.providersPath, next);
161
152
  (0, config_repo_1.applyConfigMutation)(args.configPath, document, configPlan);
162
153
  return {
163
154
  provider: args.providerName,
155
+ model: providerModel,
156
+ modelProvider: args.profile,
164
157
  profile: args.profile,
165
158
  runtimeKind: runtime?.kind ?? null,
166
159
  createdProfileSections: configPlan.createdProfileSections,
@@ -29,7 +29,7 @@ async function startBridge(args) {
29
29
  preferRuntimeState: false,
30
30
  });
31
31
  await requireBridgeRuntimeReadiness(args.runtimesDir);
32
- const bridge = await (0, copilot_bridge_1.ensureCopilotBridge)(target.providerName, target.provider, args.runtimeDir);
32
+ const bridge = await (0, copilot_bridge_1.ensureCopilotBridge)(target.providerName, target.provider, args.runtimeDir, args.runtimesDir);
33
33
  const nextProvider = bridge.portChanged ? rewriteBridgeProviderPort(target.provider, bridge.port) : target.provider;
34
34
  if (bridge.portChanged) {
35
35
  try {
@@ -242,6 +242,7 @@ async function promptForCopilotBridgeSelection(runtime, targets, commandName) {
242
242
  * Verifies that the local Copilot bridge prerequisites are available before startup.
243
243
  */
244
244
  async function requireBridgeRuntimeReadiness(runtimesDir) {
245
+ (0, copilot_installer_1.assertCopilotNodeRuntimeSupported)();
245
246
  const installStatus = (0, copilot_installer_1.probeCopilotSdkInstall)(runtimesDir);
246
247
  if (!installStatus.installed) {
247
248
  throw (0, errors_1.cliError)("COPILOT_SDK_MISSING", "The optional Copilot SDK runtime is not installed.", {