@minniexcode/codex-switch 0.0.5 → 0.0.7
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.AI.md +5 -2
- package/README.md +44 -100
- package/dist/app/add-provider.js +28 -4
- package/dist/app/edit-provider.js +47 -19
- package/dist/app/export-providers.js +2 -2
- package/dist/app/get-current-profile.js +1 -1
- package/dist/app/get-status.js +10 -3
- package/dist/app/import-providers.js +15 -7
- package/dist/app/init-codex.js +68 -0
- package/dist/app/list-backups.js +1 -1
- package/dist/app/list-config-profiles.js +3 -2
- package/dist/app/list-providers.js +2 -1
- package/dist/app/remove-provider.js +2 -2
- package/dist/app/rollback-backup.js +1 -1
- package/dist/app/rollback-latest.js +1 -1
- package/dist/app/run-doctor.js +83 -6
- package/dist/app/run-mutation.js +2 -2
- package/dist/app/setup-codex.js +21 -12
- package/dist/app/show-config.js +11 -3
- package/dist/app/show-provider.js +1 -1
- package/dist/app/switch-provider.js +16 -9
- package/dist/cli/add-interactive.js +7 -104
- package/dist/cli/args.js +6 -135
- package/dist/cli/help.js +8 -313
- package/dist/cli/interactive.js +17 -225
- package/dist/cli/output.js +21 -6
- package/dist/cli/prompt.js +4 -106
- package/dist/cli.js +10 -404
- package/dist/commands/args.js +132 -0
- package/dist/commands/dispatch.js +16 -0
- package/dist/commands/handlers.js +460 -0
- package/dist/commands/help.js +120 -0
- package/dist/commands/registry.js +351 -0
- package/dist/commands/types.js +2 -0
- package/dist/domain/config.js +235 -21
- package/dist/domain/providers.js +16 -2
- package/dist/domain/setup.js +1 -0
- package/dist/infra/backup-repo.js +9 -206
- package/dist/infra/codex-cli.js +9 -126
- package/dist/infra/codex-paths.js +6 -67
- package/dist/infra/config-repo.js +59 -0
- package/dist/infra/fs-utils.js +8 -93
- package/dist/infra/lock-repo.js +4 -95
- package/dist/infra/providers-repo.js +8 -94
- package/dist/interaction/add-interactive.js +99 -0
- package/dist/interaction/interactive.js +289 -0
- package/dist/interaction/prompt.js +110 -0
- package/dist/runtime/codex-cli.js +130 -0
- package/dist/runtime/codex-probe.js +57 -0
- package/dist/runtime/types.js +2 -0
- package/dist/storage/auth-repo.js +160 -0
- package/dist/storage/backup-repo.js +210 -0
- package/dist/storage/codex-paths.js +71 -0
- package/dist/storage/config-repo.js +266 -0
- package/dist/storage/fs-utils.js +97 -0
- package/dist/storage/lock-repo.js +99 -0
- package/dist/storage/providers-repo.js +98 -0
- package/docs/Design/codex-switch-v0.0.5-design.md +32 -22
- package/docs/Design/codex-switch-v0.0.6-design.md +708 -0
- package/docs/Design/codex-switch-v0.0.7-design.md +862 -0
- package/docs/PRD/codex-switch-prd-v0.0.5-to-v0.1.0.md +227 -89
- package/docs/PRD/codex-switch-prd-v0.1.0.md +200 -226
- package/docs/PRD/codex-switch-prd.md +1 -1
- package/docs/Reference/codex-config-reference.md +604 -0
- package/docs/Reference/codex-config-reference.zh-CN.md +633 -0
- package/docs/cli-usage.md +78 -29
- package/docs/codex-switch-technical-architecture.md +73 -4
- package/docs/test-report-0.0.5.md +163 -0
- package/docs/test-report-0.0.7.md +118 -0
- package/docs/testing.md +151 -0
- package/package.json +1 -1
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.listConfigProfilesView = listConfigProfilesView;
|
|
4
4
|
const config_1 = require("../domain/config");
|
|
5
|
-
const config_repo_1 = require("../
|
|
6
|
-
const providers_repo_1 = require("../
|
|
5
|
+
const config_repo_1 = require("../storage/config-repo");
|
|
6
|
+
const providers_repo_1 = require("../storage/providers-repo");
|
|
7
7
|
/**
|
|
8
8
|
* Returns the lightweight config profile listing.
|
|
9
9
|
*/
|
|
@@ -16,6 +16,7 @@ function listConfigProfilesView(args) {
|
|
|
16
16
|
isActive: profile.isActive,
|
|
17
17
|
linkedProviders: profile.linkedProviders,
|
|
18
18
|
model: profile.model,
|
|
19
|
+
modelProvider: profile.modelProvider,
|
|
19
20
|
baseUrl: profile.baseUrl,
|
|
20
21
|
source: profile.source,
|
|
21
22
|
}));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.listProviders = listProviders;
|
|
4
|
-
const providers_repo_1 = require("../
|
|
4
|
+
const providers_repo_1 = require("../storage/providers-repo");
|
|
5
5
|
/**
|
|
6
6
|
* Returns the sorted list of configured providers for display.
|
|
7
7
|
*/
|
|
@@ -11,6 +11,7 @@ function listProviders(providersPath) {
|
|
|
11
11
|
const items = names.map((name) => ({
|
|
12
12
|
name,
|
|
13
13
|
profile: providers.providers[name].profile,
|
|
14
|
+
envKey: providers.providers[name].envKey,
|
|
14
15
|
note: providers.providers[name].note ?? null,
|
|
15
16
|
tags: providers.providers[name].tags ?? [],
|
|
16
17
|
}));
|
|
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.removeProvider = removeProvider;
|
|
4
4
|
const errors_1 = require("../domain/errors");
|
|
5
5
|
const config_1 = require("../domain/config");
|
|
6
|
-
const config_repo_1 = require("../
|
|
7
|
-
const providers_repo_1 = require("../
|
|
6
|
+
const config_repo_1 = require("../storage/config-repo");
|
|
7
|
+
const providers_repo_1 = require("../storage/providers-repo");
|
|
8
8
|
const run_mutation_1 = require("./run-mutation");
|
|
9
9
|
/**
|
|
10
10
|
* Removes a provider from the managed providers registry.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.rollbackBackup = rollbackBackup;
|
|
4
4
|
const errors_1 = require("../domain/errors");
|
|
5
|
-
const backup_repo_1 = require("../
|
|
5
|
+
const backup_repo_1 = require("../storage/backup-repo");
|
|
6
6
|
/**
|
|
7
7
|
* Restores either the latest backup or a specific historical backup by id.
|
|
8
8
|
*/
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.rollbackLatest = rollbackLatest;
|
|
4
4
|
const errors_1 = require("../domain/errors");
|
|
5
|
-
const backup_repo_1 = require("../
|
|
5
|
+
const backup_repo_1 = require("../storage/backup-repo");
|
|
6
6
|
/**
|
|
7
7
|
* Restores the most recent mutation backup recorded by codex-switch.
|
|
8
8
|
*/
|
package/dist/app/run-doctor.js
CHANGED
|
@@ -37,10 +37,12 @@ exports.runDoctor = runDoctor;
|
|
|
37
37
|
const fs = __importStar(require("node:fs"));
|
|
38
38
|
const config_1 = require("../domain/config");
|
|
39
39
|
const runtime_state_1 = require("../domain/runtime-state");
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
const providers_repo_1 = require("../infra/providers-repo");
|
|
40
|
+
const config_repo_1 = require("../storage/config-repo");
|
|
41
|
+
const providers_repo_1 = require("../storage/providers-repo");
|
|
43
42
|
const errors_1 = require("../domain/errors");
|
|
43
|
+
const codex_probe_1 = require("../runtime/codex-probe");
|
|
44
|
+
const auth_repo_1 = require("../storage/auth-repo");
|
|
45
|
+
const providers_1 = require("../domain/providers");
|
|
44
46
|
/**
|
|
45
47
|
* Performs consistency checks across config.toml, providers.json, and the local Codex CLI.
|
|
46
48
|
*/
|
|
@@ -78,6 +80,7 @@ function runDoctor(args) {
|
|
|
78
80
|
try {
|
|
79
81
|
providers = (0, providers_repo_1.readProvidersFile)(args.providersPath);
|
|
80
82
|
if (document) {
|
|
83
|
+
// Preserve domain issue codes while translating them into user-facing diagnostic messages.
|
|
81
84
|
for (const issue of (0, config_1.collectConfigConsistencyIssues)(document, providers)) {
|
|
82
85
|
issues.push({
|
|
83
86
|
...issue,
|
|
@@ -95,12 +98,60 @@ function runDoctor(args) {
|
|
|
95
98
|
});
|
|
96
99
|
}
|
|
97
100
|
}
|
|
101
|
+
const authState = (0, auth_repo_1.readManagedAuthState)(args.authPath);
|
|
102
|
+
if (authState.exists && !authState.valid) {
|
|
103
|
+
issues.push({
|
|
104
|
+
code: "AUTH_JSON_INVALID",
|
|
105
|
+
message: authState.parseError ?? "auth.json is invalid.",
|
|
106
|
+
file: args.authPath,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
if (document?.activeProfile && providers) {
|
|
110
|
+
const matches = (0, providers_1.findProvidersByProfile)(providers, document.activeProfile);
|
|
111
|
+
if (matches.length === 1) {
|
|
112
|
+
const activeProvider = providers.providers[matches[0]];
|
|
113
|
+
const payload = authState.payload ?? {};
|
|
114
|
+
const actualKeys = authState.managedSecretKeys;
|
|
115
|
+
if (authState.authMode !== null && authState.authMode !== "apikey") {
|
|
116
|
+
issues.push({
|
|
117
|
+
code: "AUTH_JSON_INVALID",
|
|
118
|
+
message: `auth.json auth_mode must be "apikey", found "${authState.authMode}".`,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
if (!actualKeys.includes(activeProvider.envKey) || actualKeys.length !== 1) {
|
|
122
|
+
issues.push({
|
|
123
|
+
code: "AUTH_JSON_ENV_KEY_MISMATCH",
|
|
124
|
+
message: `auth.json managed env key does not match active provider "${matches[0]}".`,
|
|
125
|
+
provider: matches[0],
|
|
126
|
+
expectedEnvKey: activeProvider.envKey,
|
|
127
|
+
actualEnvKeys: actualKeys,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
if (payload[activeProvider.envKey] !== activeProvider.apiKey) {
|
|
131
|
+
issues.push({
|
|
132
|
+
code: "AUTH_JSON_APIKEY_MISMATCH",
|
|
133
|
+
message: `auth.json secret value does not match active provider "${matches[0]}".`,
|
|
134
|
+
provider: matches[0],
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Drift inspection still runs when files are missing so status output can explain partial state.
|
|
98
140
|
const drift = (0, runtime_state_1.inspectLiveStateDrift)(currentProfile, providers);
|
|
99
|
-
const codexCheck = (0,
|
|
141
|
+
const codexCheck = (0, codex_probe_1.probeCodexRuntime)();
|
|
100
142
|
if (!codexCheck.ok) {
|
|
143
|
+
const message = codexCheck.reason === "missing"
|
|
144
|
+
? "codex CLI is not available on PATH."
|
|
145
|
+
: codexCheck.reason === "unsupported"
|
|
146
|
+
? "codex CLI version is below the supported minimum."
|
|
147
|
+
: "codex CLI probe failed.";
|
|
101
148
|
issues.push({
|
|
102
|
-
code: "
|
|
103
|
-
|
|
149
|
+
code: codexCheck.reason === "unsupported"
|
|
150
|
+
? "CODEX_VERSION_UNSUPPORTED"
|
|
151
|
+
: codexCheck.reason === "missing"
|
|
152
|
+
? "CODEX_NOT_INSTALLED"
|
|
153
|
+
: "CODEX_LOGIN_FAILED",
|
|
154
|
+
message,
|
|
104
155
|
cause: codexCheck.cause,
|
|
105
156
|
});
|
|
106
157
|
}
|
|
@@ -111,10 +162,14 @@ function runDoctor(args) {
|
|
|
111
162
|
codexDir: args.codexDir,
|
|
112
163
|
storage: (0, runtime_state_1.getStorageRoles)(),
|
|
113
164
|
liveState: drift,
|
|
165
|
+
auth: authState,
|
|
114
166
|
},
|
|
115
167
|
warnings: issues.length === 0 ? [] : [`doctor found ${issues.length} issue(s)`],
|
|
116
168
|
};
|
|
117
169
|
}
|
|
170
|
+
/**
|
|
171
|
+
* Maps structured config consistency issues onto stable human-readable diagnostic text.
|
|
172
|
+
*/
|
|
118
173
|
function renderConfigIssueMessage(issue) {
|
|
119
174
|
switch (issue.code) {
|
|
120
175
|
case "ORPHANED_PROFILE_REFERENCE":
|
|
@@ -125,7 +180,29 @@ function renderConfigIssueMessage(issue) {
|
|
|
125
180
|
return `Profile "${issue.profile}" is shared by multiple providers.`;
|
|
126
181
|
case "ORPHANED_PROFILE_SECTION":
|
|
127
182
|
return `Profile section "${issue.profile}" is not linked to any provider.`;
|
|
183
|
+
case "MODEL_PROVIDER_MISSING":
|
|
184
|
+
return `Profile "${issue.profile}" is missing model_provider.`;
|
|
185
|
+
case "MODEL_PROVIDER_NAME_MISMATCH":
|
|
186
|
+
return `Profile "${issue.profile}" must use matching model_provider name "${issue.profile}", found "${issue.modelProvider}".`;
|
|
187
|
+
case "MODEL_PROVIDER_SECTION_MISSING":
|
|
188
|
+
return `Model provider section "${issue.modelProvider}" for profile "${issue.profile}" is missing from config.toml.`;
|
|
189
|
+
case "MODEL_PROVIDER_BASE_URL_MISSING":
|
|
190
|
+
return `Model provider section "${issue.modelProvider}" for profile "${issue.profile}" is missing base_url.`;
|
|
191
|
+
case "MODEL_PROVIDER_ENV_KEY_MISSING":
|
|
192
|
+
return `Model provider section "${issue.modelProvider}" for profile "${issue.profile}" is missing env_key.`;
|
|
193
|
+
case "PROVIDER_ENV_KEY_MISMATCH":
|
|
194
|
+
return `Provider "${issue.provider}" envKey does not match runtime env_key for profile "${issue.profile}".`;
|
|
195
|
+
case "ACTIVE_PROVIDER_UNRESOLVED":
|
|
196
|
+
return `Active profile "${issue.profile}" maps to multiple providers and cannot determine the current auth mirror owner.`;
|
|
197
|
+
case "AUTH_JSON_INVALID":
|
|
198
|
+
return String(issue.message ?? issue.reason ?? "auth.json is invalid.");
|
|
199
|
+
case "AUTH_JSON_ENV_KEY_MISMATCH":
|
|
200
|
+
return `auth.json managed env key does not match provider "${String(issue.provider ?? "")}".`;
|
|
201
|
+
case "AUTH_JSON_APIKEY_MISMATCH":
|
|
202
|
+
return `auth.json secret does not match provider "${String(issue.provider ?? "")}".`;
|
|
128
203
|
case "DESTRUCTIVE_REMOVE_BLOCKED":
|
|
129
204
|
return `Provider "${issue.provider}" cannot be removed while "${issue.activeProfile}" remains active.`;
|
|
205
|
+
default:
|
|
206
|
+
return String(issue.code ?? "UNKNOWN_ISSUE");
|
|
130
207
|
}
|
|
131
208
|
}
|
package/dist/app/run-mutation.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.runMutation = runMutation;
|
|
4
4
|
const errors_1 = require("../domain/errors");
|
|
5
|
-
const backup_repo_1 = require("../
|
|
6
|
-
const lock_repo_1 = require("../
|
|
5
|
+
const backup_repo_1 = require("../storage/backup-repo");
|
|
6
|
+
const lock_repo_1 = require("../storage/lock-repo");
|
|
7
7
|
/**
|
|
8
8
|
* Runs a write operation under a lock with automatic backup and rollback handling.
|
|
9
9
|
*/
|
package/dist/app/setup-codex.js
CHANGED
|
@@ -33,22 +33,23 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.
|
|
36
|
+
exports.migrateCodex = migrateCodex;
|
|
37
37
|
const fs = __importStar(require("node:fs"));
|
|
38
38
|
const setup_1 = require("../domain/setup");
|
|
39
39
|
const errors_1 = require("../domain/errors");
|
|
40
40
|
const config_1 = require("../domain/config");
|
|
41
|
-
const codex_cli_1 = require("../
|
|
42
|
-
const config_repo_1 = require("../
|
|
43
|
-
const fs_utils_1 = require("../
|
|
44
|
-
const providers_repo_1 = require("../
|
|
41
|
+
const codex_cli_1 = require("../runtime/codex-cli");
|
|
42
|
+
const config_repo_1 = require("../storage/config-repo");
|
|
43
|
+
const fs_utils_1 = require("../storage/fs-utils");
|
|
44
|
+
const providers_repo_1 = require("../storage/providers-repo");
|
|
45
|
+
const auth_repo_1 = require("../storage/auth-repo");
|
|
45
46
|
const run_doctor_1 = require("./run-doctor");
|
|
46
47
|
const run_mutation_1 = require("./run-mutation");
|
|
47
48
|
const MIN_CODEX_VERSION = "0.0.1";
|
|
48
49
|
/**
|
|
49
|
-
*
|
|
50
|
+
* Migrates unmanaged Codex config profiles into a managed providers.json registry.
|
|
50
51
|
*/
|
|
51
|
-
function
|
|
52
|
+
function migrateCodex(args) {
|
|
52
53
|
const available = (0, codex_cli_1.checkCodexAvailable)();
|
|
53
54
|
if (!available.ok) {
|
|
54
55
|
throw (0, errors_1.cliError)("CODEX_NOT_INSTALLED", "codex CLI is not available.", {
|
|
@@ -70,8 +71,9 @@ function setupCodex(args) {
|
|
|
70
71
|
}
|
|
71
72
|
const document = (0, config_repo_1.readStructuredConfig)(args.configPath);
|
|
72
73
|
const profileViews = (0, config_1.buildManagedProfileViews)(document, null);
|
|
74
|
+
// Migrate can only adopt unmanaged profiles that already contain enough runtime data to become managed.
|
|
73
75
|
const adoptableProfiles = profileViews
|
|
74
|
-
.filter((view) => view.source === "unmanaged" && view.model && view.baseUrl)
|
|
76
|
+
.filter((view) => view.source === "unmanaged" && view.model && view.modelProvider === view.name && view.baseUrl && view.envKey)
|
|
75
77
|
.map((view) => view.name)
|
|
76
78
|
.sort();
|
|
77
79
|
if (profileViews.length === 0) {
|
|
@@ -81,20 +83,20 @@ function setupCodex(args) {
|
|
|
81
83
|
}
|
|
82
84
|
const invalidAdoptProfiles = args.adoptProfiles.filter((profile) => !adoptableProfiles.includes(profile));
|
|
83
85
|
if (invalidAdoptProfiles.length > 0) {
|
|
84
|
-
throw (0, errors_1.cliError)("INVALID_ARGUMENT", "
|
|
86
|
+
throw (0, errors_1.cliError)("INVALID_ARGUMENT", "migrate only adopts unmanaged profiles that already contain model, model_provider, and matching model_providers base_url/env_key.", {
|
|
85
87
|
invalidProfiles: invalidAdoptProfiles.sort(),
|
|
86
88
|
adoptableProfiles,
|
|
87
89
|
});
|
|
88
90
|
}
|
|
89
91
|
if (args.adoptProfiles.length === 0) {
|
|
90
|
-
throw (0, errors_1.cliError)("INVALID_ARGUMENT", "
|
|
92
|
+
throw (0, errors_1.cliError)("INVALID_ARGUMENT", "migrate requires at least one explicit profile to adopt.", {
|
|
91
93
|
adoptableProfiles,
|
|
92
94
|
});
|
|
93
95
|
}
|
|
94
96
|
const drafts = (0, setup_1.buildSetupDrafts)(args.adoptProfiles, args.providerDetailsByProfile);
|
|
95
97
|
const incompleteProfiles = (0, setup_1.findIncompleteSetupProfiles)(drafts);
|
|
96
98
|
if (incompleteProfiles.length > 0) {
|
|
97
|
-
throw (0, errors_1.cliError)("INVALID_ARGUMENT", "
|
|
99
|
+
throw (0, errors_1.cliError)("INVALID_ARGUMENT", "migrate requires complete provider data for every selected profile.", {
|
|
98
100
|
incompleteProfiles,
|
|
99
101
|
});
|
|
100
102
|
}
|
|
@@ -117,15 +119,20 @@ function setupCodex(args) {
|
|
|
117
119
|
codexDir: args.codexDir,
|
|
118
120
|
backupsDir: args.backupsDir,
|
|
119
121
|
latestBackupPath: args.latestBackupPath,
|
|
120
|
-
operation: "
|
|
122
|
+
operation: "migrate",
|
|
121
123
|
files: [
|
|
122
124
|
{ absolutePath: args.providersPath, relativePath: "providers.json" },
|
|
123
125
|
{ absolutePath: args.configPath, relativePath: "config.toml" },
|
|
126
|
+
{ absolutePath: args.authPath, relativePath: "auth.json" },
|
|
124
127
|
],
|
|
125
128
|
mutate: () => {
|
|
129
|
+
// migrate currently preserves config structure and only asserts that the file remains writable inside the mutation flow.
|
|
126
130
|
const configPlan = (0, config_repo_1.createConfigMutationPlan)(document, {});
|
|
127
131
|
(0, providers_repo_1.writeProvidersFile)(args.providersPath, finalProviders);
|
|
128
132
|
(0, config_repo_1.applyConfigMutation)(args.configPath, document, configPlan);
|
|
133
|
+
const activeProviderName = (0, config_repo_1.resolveActiveProviderName)(document, finalProviders);
|
|
134
|
+
const existingAuth = (0, auth_repo_1.readAuthFileIfExists)(args.authPath);
|
|
135
|
+
(0, auth_repo_1.writeAuthFile)(args.authPath, finalProviders.providers[activeProviderName], existingAuth ?? undefined);
|
|
129
136
|
return {
|
|
130
137
|
codexDir: args.codexDir,
|
|
131
138
|
strategy: args.strategy,
|
|
@@ -140,10 +147,12 @@ function setupCodex(args) {
|
|
|
140
147
|
};
|
|
141
148
|
},
|
|
142
149
|
});
|
|
150
|
+
// Re-run doctor on the final state so migrate returns immediate post-migration diagnostics.
|
|
143
151
|
const doctor = (0, run_doctor_1.runDoctor)({
|
|
144
152
|
codexDir: args.codexDir,
|
|
145
153
|
configPath: args.configPath,
|
|
146
154
|
providersPath: args.providersPath,
|
|
155
|
+
authPath: args.authPath,
|
|
147
156
|
});
|
|
148
157
|
return {
|
|
149
158
|
data: {
|
package/dist/app/show-config.js
CHANGED
|
@@ -3,8 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.showConfig = showConfig;
|
|
4
4
|
const config_1 = require("../domain/config");
|
|
5
5
|
const errors_1 = require("../domain/errors");
|
|
6
|
-
const
|
|
7
|
-
const
|
|
6
|
+
const providers_1 = require("../domain/providers");
|
|
7
|
+
const config_repo_1 = require("../storage/config-repo");
|
|
8
|
+
const providers_repo_1 = require("../storage/providers-repo");
|
|
8
9
|
/**
|
|
9
10
|
* Returns the structured config view, optionally filtered to one profile.
|
|
10
11
|
*/
|
|
@@ -28,7 +29,14 @@ function showConfig(args) {
|
|
|
28
29
|
data: {
|
|
29
30
|
activeProfile: document.activeProfile,
|
|
30
31
|
selectedProfile,
|
|
31
|
-
profiles
|
|
32
|
+
profiles: profiles.map((profile) => ({
|
|
33
|
+
...profile,
|
|
34
|
+
managedProviderEnvKeys: (0, providers_1.findProvidersByProfile)(providers, profile.name).map((providerName) => ({
|
|
35
|
+
providerName,
|
|
36
|
+
envKey: providers.providers[providerName].envKey,
|
|
37
|
+
matchesRuntime: providers.providers[providerName].envKey === profile.envKey,
|
|
38
|
+
})),
|
|
39
|
+
})),
|
|
32
40
|
},
|
|
33
41
|
};
|
|
34
42
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.showProvider = showProvider;
|
|
4
4
|
const providers_1 = require("../domain/providers");
|
|
5
|
-
const providers_repo_1 = require("../
|
|
5
|
+
const providers_repo_1 = require("../storage/providers-repo");
|
|
6
6
|
/**
|
|
7
7
|
* Returns a single provider record, with text-mode callers able to use a masked preview.
|
|
8
8
|
*/
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.switchProvider = switchProvider;
|
|
4
4
|
const errors_1 = require("../domain/errors");
|
|
5
|
-
const config_repo_1 = require("../
|
|
6
|
-
const
|
|
7
|
-
const
|
|
5
|
+
const config_repo_1 = require("../storage/config-repo");
|
|
6
|
+
const providers_repo_1 = require("../storage/providers-repo");
|
|
7
|
+
const auth_repo_1 = require("../storage/auth-repo");
|
|
8
8
|
const run_mutation_1 = require("./run-mutation");
|
|
9
9
|
/**
|
|
10
|
-
* Switches the active Codex profile and
|
|
10
|
+
* Switches the active Codex profile and rewrites auth.json for the target provider.
|
|
11
11
|
*/
|
|
12
12
|
function switchProvider(args) {
|
|
13
13
|
const providers = (0, providers_repo_1.readProvidersFile)(args.providersPath);
|
|
@@ -18,6 +18,15 @@ function switchProvider(args) {
|
|
|
18
18
|
});
|
|
19
19
|
}
|
|
20
20
|
const document = (0, config_repo_1.ensureProfileExists)(args.configPath, provider.profile, args.providerName);
|
|
21
|
+
const envKey = (0, config_repo_1.requireRuntimeEnvKey)(document, provider.profile);
|
|
22
|
+
if (provider.envKey !== envKey) {
|
|
23
|
+
throw (0, errors_1.cliError)("PROVIDER_ENV_KEY_MISMATCH", `Provider "${args.providerName}" envKey does not match runtime env_key.`, {
|
|
24
|
+
provider: args.providerName,
|
|
25
|
+
profile: provider.profile,
|
|
26
|
+
providerEnvKey: provider.envKey,
|
|
27
|
+
runtimeEnvKey: envKey,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
21
30
|
return (0, run_mutation_1.runMutation)({
|
|
22
31
|
codexDir: args.codexDir,
|
|
23
32
|
backupsDir: args.backupsDir,
|
|
@@ -31,15 +40,13 @@ function switchProvider(args) {
|
|
|
31
40
|
const configPlan = (0, config_repo_1.createConfigMutationPlan)(document, {
|
|
32
41
|
setActiveProfile: provider.profile,
|
|
33
42
|
});
|
|
34
|
-
// Update the runtime profile first so any subsequent login is associated with the new target.
|
|
35
43
|
(0, config_repo_1.applyConfigMutation)(args.configPath, document, configPlan);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
44
|
+
const existingAuth = (0, auth_repo_1.readAuthFileIfExists)(args.authPath);
|
|
45
|
+
(0, auth_repo_1.writeAuthFile)(args.authPath, provider, existingAuth ?? undefined);
|
|
39
46
|
return {
|
|
40
47
|
provider: args.providerName,
|
|
41
48
|
profile: provider.profile,
|
|
42
|
-
|
|
49
|
+
envKey: provider.envKey,
|
|
43
50
|
};
|
|
44
51
|
},
|
|
45
52
|
});
|
|
@@ -1,108 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.COMMON_TAG_CHOICES = void 0;
|
|
4
|
-
exports.collectAddInput = collectAddInput;
|
|
5
|
-
exports.createNonInteractiveAddError = createNonInteractiveAddError;
|
|
6
|
-
exports.promptTags = promptTags;
|
|
7
|
-
exports.parseTags = parseTags;
|
|
8
|
-
const errors_1 = require("../domain/errors");
|
|
9
|
-
exports.COMMON_TAG_CHOICES = ["free", "paid", "daily", "backup"];
|
|
3
|
+
exports.promptTags = exports.createNonInteractiveAddError = exports.COMMON_TAG_CHOICES = exports.collectAddInput = void 0;
|
|
10
4
|
/**
|
|
11
|
-
*
|
|
5
|
+
* Compatibility facade that re-exports interactive add helpers for older imports.
|
|
12
6
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
: await promptProviderName(runtime, providerExists);
|
|
19
|
-
const profile = defaults.profile ? normalizeRequiredValue(defaults.profile) : await promptRequiredValue(runtime, "Profile");
|
|
20
|
-
const apiKey = defaults.apiKey
|
|
21
|
-
? normalizeRequiredValue(defaults.apiKey)
|
|
22
|
-
: await promptConfirmedSecret(runtime, "API key", "Confirm API key");
|
|
23
|
-
const baseUrl = defaults.baseUrl ?? normalizeOptionalValue(await runtime.inputText("Base URL (optional)"));
|
|
24
|
-
const note = defaults.note ?? normalizeOptionalValue(await runtime.inputText("Note (optional)"));
|
|
25
|
-
const tags = defaults.tags.length > 0 ? defaults.tags : await promptTags(runtime);
|
|
26
|
-
return {
|
|
27
|
-
providerName,
|
|
28
|
-
profile,
|
|
29
|
-
apiKey,
|
|
30
|
-
baseUrl,
|
|
31
|
-
note,
|
|
32
|
-
tags,
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Throws a consistent error when interactive add is unavailable.
|
|
37
|
-
*/
|
|
38
|
-
function createNonInteractiveAddError() {
|
|
39
|
-
return (0, errors_1.cliError)("INVALID_ARGUMENT", "add requires <provider>, --profile, and --api-key when running without an interactive TTY.", {
|
|
40
|
-
suggestion: "Run in a terminal TTY or pass all required values explicitly.",
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
async function promptProviderName(runtime, providerExists) {
|
|
44
|
-
while (true) {
|
|
45
|
-
const providerName = await promptRequiredValue(runtime, "Provider name");
|
|
46
|
-
if (providerExists(providerName)) {
|
|
47
|
-
runtime.writeLine(`Provider "${providerName}" already exists. Choose a different name.`);
|
|
48
|
-
continue;
|
|
49
|
-
}
|
|
50
|
-
return providerName;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
async function promptRequiredValue(runtime, label) {
|
|
54
|
-
while (true) {
|
|
55
|
-
const value = normalizeRequiredValue(await runtime.inputText(label));
|
|
56
|
-
if (value.length > 0) {
|
|
57
|
-
return value;
|
|
58
|
-
}
|
|
59
|
-
runtime.writeLine(`${label} is required.`);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
async function promptConfirmedSecret(runtime, label, confirmationLabel) {
|
|
63
|
-
while (true) {
|
|
64
|
-
const first = normalizeRequiredValue(await runtime.inputSecret(label));
|
|
65
|
-
if (first.length === 0) {
|
|
66
|
-
runtime.writeLine(`${label} is required.`);
|
|
67
|
-
continue;
|
|
68
|
-
}
|
|
69
|
-
const second = normalizeRequiredValue(await runtime.inputSecret(confirmationLabel));
|
|
70
|
-
if (second.length === 0) {
|
|
71
|
-
runtime.writeLine(`${confirmationLabel} is required.`);
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
|
-
if (first !== second) {
|
|
75
|
-
runtime.writeLine("API key entries did not match. Try again.");
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
return first;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
function normalizeRequiredValue(value) {
|
|
82
|
-
return value.trim();
|
|
83
|
-
}
|
|
84
|
-
function normalizeOptionalValue(value) {
|
|
85
|
-
const normalized = value.trim();
|
|
86
|
-
return normalized === "" ? null : normalized;
|
|
87
|
-
}
|
|
88
|
-
async function promptTags(runtime, defaults = []) {
|
|
89
|
-
const defaultPresetTags = defaults.filter(isCommonTag);
|
|
90
|
-
const defaultCustomTags = defaults.filter((tag) => !isCommonTag(tag));
|
|
91
|
-
const presetTags = await runtime.selectMany("Select tags (optional)", exports.COMMON_TAG_CHOICES.map((tag) => ({ value: tag, label: tag })), { defaultValues: defaultPresetTags });
|
|
92
|
-
const customTags = parseTags(await runtime.inputText("Custom tags (optional, comma-separated)", {
|
|
93
|
-
defaultValue: defaultCustomTags.join(", "),
|
|
94
|
-
}));
|
|
95
|
-
return dedupeTags([...presetTags, ...customTags]);
|
|
96
|
-
}
|
|
97
|
-
function parseTags(value) {
|
|
98
|
-
return dedupeTags(value
|
|
99
|
-
.split(",")
|
|
100
|
-
.map((tag) => tag.trim())
|
|
101
|
-
.filter((tag) => tag.length > 0));
|
|
102
|
-
}
|
|
103
|
-
function isCommonTag(tag) {
|
|
104
|
-
return exports.COMMON_TAG_CHOICES.includes(tag);
|
|
105
|
-
}
|
|
106
|
-
function dedupeTags(tags) {
|
|
107
|
-
return Array.from(new Set(tags));
|
|
108
|
-
}
|
|
7
|
+
var add_interactive_1 = require("../interaction/add-interactive");
|
|
8
|
+
Object.defineProperty(exports, "collectAddInput", { enumerable: true, get: function () { return add_interactive_1.collectAddInput; } });
|
|
9
|
+
Object.defineProperty(exports, "COMMON_TAG_CHOICES", { enumerable: true, get: function () { return add_interactive_1.COMMON_TAG_CHOICES; } });
|
|
10
|
+
Object.defineProperty(exports, "createNonInteractiveAddError", { enumerable: true, get: function () { return add_interactive_1.createNonInteractiveAddError; } });
|
|
11
|
+
Object.defineProperty(exports, "promptTags", { enumerable: true, get: function () { return add_interactive_1.promptTags; } });
|