@minniexcode/codex-switch 0.1.0 → 0.1.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/README.md CHANGED
@@ -1,183 +1,215 @@
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.1`
12
+
13
+ This is the current stable release line. `0.1.1` aligns the public docs with the Codex `0.134.0+` runtime contract where top-level `model` and `model_provider` select the active route.
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
+ - `switch` projects the selected provider into the target Codex runtime as top-level `model` plus `model_provider`.
62
+ - `status` is the main read command after switching.
63
+ - `doctor` is the main repair-oriented diagnostic command.
64
+
65
+ ## Runtime Routing Model
66
+
67
+ For Codex `0.134.0+`, the active runtime route is selected through top-level `model` and `model_provider` in `config.toml`.
68
+
69
+ `codex-switch` treats that route as the runtime contract:
70
+
71
+ - top-level `model` selects the active model id
72
+ - top-level `model_provider` selects the active provider route
73
+ - managed `[model_providers.<id>]` entries are the projected runtime provider definitions
74
+ - `--profile` is only an alias for the managed `model_provider` id, not the primary runtime selector
75
+
76
+ Direct-provider projection writes:
77
+
78
+ - top-level `model`
79
+ - top-level `model_provider`
80
+ - `[model_providers.<id>]`
81
+ - `auth.json` with `OPENAI_API_KEY`
82
+
83
+ 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.
84
+
85
+ For managed OpenAI-compatible routes, the projected provider entry keeps the fixed runtime shape:
86
+
87
+ ```toml
88
+ model = "gpt-5.5"
89
+ model_provider = "my-provider"
90
+
91
+ [model_providers.my-provider]
92
+ name = "my-provider"
93
+ base_url = "https://gateway.example.com/v1"
94
+ wire_api = "responses"
95
+ requires_openai_auth = true
96
+ ```
97
+
98
+ ## Advanced Adopt Workflow
99
+
100
+ Use `migrate` only when you already have Codex runtime state that should be adopted into managed `providers.json` state:
101
+
102
+ ```bash
103
+ codexs init
104
+ codexs migrate
105
+ ```
106
+
107
+ `migrate` is an advanced adopt helper. It is not the default first step for a fresh install.
108
+
109
+ ## Command Surface
110
+
111
+ ```bash
112
+ codexs init
113
+ codexs login copilot
114
+ codexs migrate
115
+ codexs list
116
+ codexs show <provider>
117
+ codexs current
118
+ codexs status
119
+ codexs config show [profile]
120
+ codexs config list-profiles
121
+ codexs add <provider> --model <model> --api-key <key> [--base-url <url>]
122
+ codexs add <provider> --copilot --model <model>
123
+ codexs edit <provider>
124
+ codexs switch <provider>
125
+ codexs remove <provider> [--force] [--switch-to <provider>]
126
+ codexs import <file>
127
+ codexs export <file> [--force]
128
+ codexs bridge start [provider]
129
+ codexs bridge status [provider]
130
+ codexs bridge stop [provider]
131
+ codexs backups list
132
+ codexs rollback [backup-id]
133
+ codexs doctor
134
+ ```
135
+
136
+ `setup` still exists only as a deprecated compatibility entry that points callers to `init` or `migrate`.
137
+
138
+ ## Runtime Model
139
+
140
+ Tool home:
141
+
142
+ ```text
143
+ ~/.config/codex-switch/
144
+ codex-switch.json
145
+ providers.json
146
+ backups/
147
+ runtime/
148
+ runtimes/
149
+ ```
150
+
151
+ Target Codex runtime:
152
+
153
+ ```text
154
+ ~/.codex/
155
+ config.toml
156
+ auth.json
157
+ ```
158
+
159
+ Key points:
160
+
161
+ - `providers.json` is the managed provider registry and lives under the tool home.
162
+ - `codex-switch.json` stores tool-level metadata such as `defaultCodexDir`.
163
+ - `config.toml` remains the active runtime routing file in the target Codex directory.
164
+ - `auth.json` remains the active auth projection file in the target Codex directory.
165
+ - Direct providers rewrite `OPENAI_API_KEY` into the active runtime projection.
166
+ - Copilot providers keep upstream GitHub authentication in the official Copilot runtime while `codex-switch` manages local bridge state and routing.
167
+
168
+ Path controls:
169
+
170
+ - `--codex-dir <path>` targets a specific Codex runtime directory.
171
+ - `CODEXS_CODEX_DIR` provides the default target runtime when `--codex-dir` is not passed.
172
+ - `CODEXS_HOME` overrides the tool home location.
173
+
174
+ ## Automation Notes
175
+
176
+ This CLI supports both human TTY usage and non-interactive automation.
177
+
178
+ Global flags:
179
+
180
+ ```bash
181
+ --json
182
+ --codex-dir <path>
183
+ --help
184
+ --version
185
+ ```
186
+
187
+ Operational limits:
188
+
189
+ - `login copilot` requires a real TTY and does not support `--json`.
190
+ - `migrate` remains interactive when provider adoption requires human input.
191
+ - Automation should pass explicit arguments and prefer `--json` for stable parsing.
192
+
193
+ ## Local Development
194
+
195
+ ```bash
196
+ npm run build
197
+ npm test
198
+ npx tsc --noEmit
199
+ node dist/cli.js --help
200
+ npm pack --dry-run
201
+ ```
202
+
203
+ ## Documentation
204
+
205
+ - [Chinese README](./README.CN.md)
206
+ - [AI README](./README.AI.md)
207
+ - [Detailed CLI Usage](./docs/cli-usage.md)
208
+ - [Testing Guide](./docs/Tests/testing.md)
209
+ - [Product Overview](./docs/codex-switch-product-overview.md)
210
+ - [Release PRD 0.1.1](./docs/PRD/codex-switch-prd-v0.1.1.md)
211
+ - [Release Design 0.1.1](./docs/Design/codex-switch-v0.1.1-design.md)
212
+
213
+ ## License
214
+
215
+ 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");
@@ -91,24 +90,19 @@ async function addProvider(args) {
91
90
  }
92
91
  }
93
92
  const document = (0, config_repo_1.readStructuredConfig)(args.configPath);
94
- const existingProfile = document.profiles.find((profile) => profile.name === args.profile);
95
93
  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,
94
+ const inheritedModel = document.currentModel ?? undefined;
95
+ const providerModel = args.model ?? inheritedModel;
96
+ if (!providerModel) {
97
+ throw (0, errors_1.cliError)("MANAGED_PROFILE_FIELDS_MISSING", `Provider "${args.providerName}" requires a model.`, {
99
98
  provider: args.providerName,
99
+ modelProvider: args.profile,
100
+ missingFields: ["model"],
101
+ suggestion: "Pass `--model <name>` or set a top-level model in config.toml first.",
100
102
  });
101
103
  }
102
104
  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() === "")) {
105
+ if (!args.copilot && (!directBaseUrl || directBaseUrl.trim() === "") && !existingModelProvider) {
112
106
  throw (0, errors_1.cliError)("MANAGED_PROFILE_FIELDS_MISSING", `Model provider "${args.profile}" requires base_url.`, {
113
107
  profile: args.profile,
114
108
  modelProvider: args.profile,
@@ -119,14 +113,9 @@ async function addProvider(args) {
119
113
  ? {
120
114
  [args.profile]: (0, providers_1.buildCopilotModelProviderProjection)(runtime),
121
115
  }
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
- }
116
+ : {
117
+ [args.profile]: (0, providers_1.buildDirectModelProviderProjection)(args.profile, (directBaseUrl ?? existingModelProvider?.baseUrl ?? "").trim()),
118
+ };
130
119
  const apiKey = args.copilot ? args.bridgeApiKey ?? crypto.randomBytes(24).toString("hex") : args.apiKey;
131
120
  const baseUrl = args.copilot ? (0, providers_1.buildCopilotBridgeBaseUrl)(runtime) : args.baseUrl ?? undefined;
132
121
  const next = {
@@ -135,6 +124,7 @@ async function addProvider(args) {
135
124
  [args.providerName]: (0, providers_1.cleanProviderRecord)({
136
125
  profile: args.profile,
137
126
  apiKey,
127
+ model: providerModel,
138
128
  baseUrl,
139
129
  note: args.note ?? undefined,
140
130
  tags: args.tags,
@@ -153,14 +143,16 @@ async function addProvider(args) {
153
143
  ],
154
144
  mutate: () => {
155
145
  const configPlan = (0, config_repo_1.createConfigMutationPlan)(document, {
156
- upsertProfiles,
157
146
  upsertModelProviders,
147
+ scrubModelProviderEnvKeys: [args.profile],
158
148
  });
159
149
  // Persist only the normalized provider payload so later reads are deterministic.
160
150
  (0, providers_repo_1.writeProvidersFile)(args.providersPath, next);
161
151
  (0, config_repo_1.applyConfigMutation)(args.configPath, document, configPlan);
162
152
  return {
163
153
  provider: args.providerName,
154
+ model: providerModel,
155
+ modelProvider: args.profile,
164
156
  profile: args.profile,
165
157
  runtimeKind: runtime?.kind ?? null,
166
158
  createdProfileSections: configPlan.createdProfileSections,
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.editProvider = editProvider;
4
4
  const errors_1 = require("../domain/errors");
5
- const config_1 = require("../domain/config");
6
5
  const providers_1 = require("../domain/providers");
7
6
  const config_repo_1 = require("../storage/config-repo");
8
7
  const fs_utils_1 = require("../storage/fs-utils");
@@ -24,6 +23,7 @@ function editProvider(args) {
24
23
  }
25
24
  const updatedFields = [];
26
25
  const nextProfile = args.profile ?? current.profile;
26
+ const nextModel = args.model === null ? undefined : args.model ?? current.model;
27
27
  if (args.profile !== undefined && args.profile !== current.profile) {
28
28
  updatedFields.push("profile");
29
29
  }
@@ -33,6 +33,9 @@ function editProvider(args) {
33
33
  if (args.baseUrl !== undefined && (args.baseUrl ?? undefined) !== current.baseUrl) {
34
34
  updatedFields.push("baseUrl");
35
35
  }
36
+ if (args.model !== undefined && args.model !== current.model) {
37
+ updatedFields.push("model");
38
+ }
36
39
  if (args.note !== undefined && (args.note ?? undefined) !== current.note) {
37
40
  updatedFields.push("note");
38
41
  }
@@ -41,87 +44,46 @@ function editProvider(args) {
41
44
  }
42
45
  const oldProfile = current.profile;
43
46
  const newProfile = nextProfile;
44
- const targetSection = document.profiles.find((profile) => profile.name === newProfile) ?? null;
45
47
  const targetModelProviderSection = document.modelProviders.find((entry) => entry.name === newProfile) ?? null;
46
- const targetProfileExists = Boolean(targetSection);
47
- let upsertProfiles;
48
48
  let upsertModelProviders;
49
- if (!targetProfileExists) {
50
- if (!args.createProfile) {
51
- throw (0, errors_1.cliError)("PROFILE_NOT_FOUND", `Profile "${newProfile}" does not exist in config.toml.`, {
52
- profile: newProfile,
53
- provider: args.providerName,
54
- });
55
- }
56
- if (!args.baseUrl || args.baseUrl.trim() === "") {
49
+ const resolvedBaseUrl = (args.baseUrl ?? current.baseUrl ?? targetModelProviderSection?.baseUrl ?? "").trim();
50
+ if (!current.runtime) {
51
+ if (!resolvedBaseUrl) {
57
52
  throw (0, errors_1.cliError)("MANAGED_PROFILE_FIELDS_MISSING", `Model provider "${newProfile}" requires base_url.`, {
58
53
  profile: newProfile,
59
54
  modelProvider: newProfile,
60
55
  missingFields: ["base_url"],
61
56
  });
62
57
  }
63
- upsertProfiles = {
64
- [newProfile]: (0, config_1.validateManagedProfileCreation)(newProfile, {
65
- model: args.model ?? undefined,
66
- modelProvider: newProfile,
67
- }),
68
- };
69
58
  upsertModelProviders = {
70
- [newProfile]: (0, providers_1.buildDirectModelProviderProjection)(newProfile, args.baseUrl),
59
+ [newProfile]: (0, providers_1.buildDirectModelProviderProjection)(newProfile, resolvedBaseUrl),
71
60
  };
72
61
  }
73
- else {
74
- (0, config_repo_1.requireManagedProfileRuntime)(document, providers, newProfile);
75
- }
76
- if (targetProfileExists &&
77
- !current.runtime &&
78
- args.baseUrl !== undefined &&
79
- args.baseUrl !== null) {
62
+ else if (targetModelProviderSection || args.profile !== undefined) {
80
63
  upsertModelProviders = {
81
64
  ...(upsertModelProviders ?? {}),
82
- [newProfile]: (0, providers_1.buildDirectModelProviderProjection)(newProfile, args.baseUrl),
65
+ [newProfile]: {
66
+ ...(current.runtime
67
+ ? {
68
+ baseUrl: current.baseUrl ?? targetModelProviderSection?.baseUrl ?? "",
69
+ name: "copilot",
70
+ requiresOpenAiAuth: true,
71
+ wireApi: "responses",
72
+ }
73
+ : (0, providers_1.buildDirectModelProviderProjection)(newProfile, resolvedBaseUrl)),
74
+ },
83
75
  };
84
76
  }
85
77
  const nextRecord = (0, providers_1.cleanProviderRecord)({
86
78
  profile: newProfile,
87
79
  apiKey: args.apiKey ?? current.apiKey,
80
+ model: nextModel,
88
81
  baseUrl: args.baseUrl === null ? undefined : args.baseUrl ?? current.baseUrl,
89
82
  note: args.note === null ? undefined : args.note ?? current.note,
90
83
  tags: args.tags ?? current.tags,
84
+ runtime: current.runtime,
91
85
  });
92
- if (targetProfileExists && args.model !== undefined) {
93
- upsertProfiles = {
94
- [newProfile]: {
95
- ...(args.model !== undefined && args.model !== null ? { model: args.model } : {}),
96
- },
97
- };
98
- if (args.model !== undefined && targetSection?.model !== args.model && !updatedFields.includes("model")) {
99
- updatedFields.push("model");
100
- }
101
- }
102
- // Compute profile link ownership after the edit so lifecycle planning can decide whether sections stay, move, or delete.
103
- const remainingLinksByProfile = new Map();
104
- for (const [name, provider] of Object.entries(providers.providers)) {
105
- if (name === args.providerName) {
106
- continue;
107
- }
108
- const list = remainingLinksByProfile.get(provider.profile) ?? [];
109
- list.push(name);
110
- remainingLinksByProfile.set(provider.profile, list);
111
- }
112
- if (newProfile !== oldProfile) {
113
- const list = remainingLinksByProfile.get(newProfile) ?? [];
114
- list.push(args.providerName);
115
- remainingLinksByProfile.set(newProfile, list);
116
- }
117
- const lifecycle = (0, config_1.planProfileLifecycleOutcome)({
118
- providerName: args.providerName,
119
- oldProfile,
120
- newProfile,
121
- activeProfile: document.activeProfile,
122
- remainingLinksByProfile,
123
- switchToProfile: args.switchToProfile ?? null,
124
- });
86
+ const isActive = document.currentModelProvider === oldProfile;
125
87
  return (0, run_mutation_1.runMutation)({
126
88
  lockPath: args.lockPath,
127
89
  backupsDir: args.backupsDir,
@@ -133,10 +95,12 @@ function editProvider(args) {
133
95
  ],
134
96
  mutate: () => {
135
97
  const configPlan = (0, config_repo_1.createConfigMutationPlan)(document, {
136
- upsertProfiles,
137
98
  upsertModelProviders,
138
- deleteProfiles: lifecycle.deletedProfileSections,
139
- setActiveProfile: lifecycle.nextActiveProfile,
99
+ setCurrentModel: isActive ? nextModel ?? document.currentModel : undefined,
100
+ setCurrentModelProvider: isActive ? newProfile : undefined,
101
+ deleteLegacyProfile: isActive,
102
+ deleteLegacyProfilesByName: isActive ? [newProfile] : [],
103
+ scrubModelProviderEnvKeys: [newProfile],
140
104
  });
141
105
  const nextProviders = {
142
106
  providers: {
@@ -149,12 +113,13 @@ function editProvider(args) {
149
113
  (0, config_repo_1.applyConfigMutation)(args.configPath, document, configPlan);
150
114
  return {
151
115
  provider: args.providerName,
116
+ modelProvider: newProfile,
152
117
  updatedFields,
153
118
  createdProfileSections: configPlan.createdProfileSections,
154
119
  createdModelProviderSections: configPlan.createdModelProviderSections,
155
120
  deletedProfileSections: configPlan.deletedProfileSections,
156
- keptSharedProfiles: lifecycle.keptSharedProfiles,
157
- switchedActiveProfile: lifecycle.switchedActiveProfile,
121
+ keptSharedProfiles: [],
122
+ switchedActiveProfile: isActive && newProfile !== oldProfile,
158
123
  adoptedProfiles: [],
159
124
  repairedProfiles: [],
160
125
  };