@minniexcode/codex-switch 0.0.4 → 0.0.6
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 +35 -97
- package/dist/app/add-provider.js +40 -3
- package/dist/app/edit-provider.js +76 -3
- 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 +47 -3
- package/dist/app/list-backups.js +1 -1
- package/dist/app/list-config-profiles.js +30 -0
- package/dist/app/list-providers.js +1 -1
- package/dist/app/remove-provider.js +35 -3
- package/dist/app/rollback-backup.js +1 -1
- package/dist/app/rollback-latest.js +1 -1
- package/dist/app/run-doctor.js +44 -26
- package/dist/app/run-mutation.js +2 -2
- package/dist/app/setup-codex.js +37 -20
- package/dist/app/show-config.js +34 -0
- package/dist/app/show-provider.js +1 -1
- package/dist/app/switch-provider.js +8 -5
- package/dist/cli/add-interactive.js +7 -106
- package/dist/cli/args.js +5 -126
- package/dist/cli/help.js +5 -276
- package/dist/cli/interactive.js +16 -171
- package/dist/cli/output.js +23 -1
- package/dist/cli/prompt.js +3 -108
- package/dist/cli.js +10 -315
- package/dist/commands/args.js +132 -0
- package/dist/commands/dispatch.js +16 -0
- package/dist/commands/handlers.js +391 -0
- package/dist/commands/help.js +119 -0
- package/dist/commands/registry.js +291 -0
- package/dist/commands/types.js +2 -0
- package/dist/domain/config.js +548 -39
- package/dist/infra/backup-repo.js +8 -208
- package/dist/infra/codex-cli.js +8 -113
- package/dist/infra/codex-discovery.js +3 -41
- package/dist/infra/codex-paths.js +5 -69
- package/dist/infra/config-repo.js +161 -9
- package/dist/infra/fs-utils.js +7 -95
- package/dist/infra/lock-repo.js +3 -97
- package/dist/infra/providers-repo.js +7 -96
- package/dist/interaction/add-interactive.js +108 -0
- package/dist/interaction/interactive.js +216 -0
- package/dist/interaction/prompt.js +110 -0
- package/dist/runtime/codex-cli.js +130 -0
- package/dist/runtime/codex-probe.js +50 -0
- package/dist/runtime/types.js +2 -0
- package/dist/storage/backup-repo.js +210 -0
- package/dist/storage/codex-paths.js +71 -0
- package/dist/storage/config-repo.js +208 -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 +932 -0
- package/docs/Design/codex-switch-v0.0.6-design.md +708 -0
- package/docs/PRD/codex-switch-prd-v0.0.5-to-v0.1.0.md +340 -0
- package/docs/PRD/codex-switch-prd-v0.1.0.md +215 -291
- package/docs/PRD/codex-switch-prd.md +1 -1
- package/docs/cli-usage.md +2 -1
- package/docs/codex-switch-technical-architecture.md +73 -4
- package/docs/test-report-0.0.5.md +163 -0
- package/docs/testing.md +131 -0
- package/package.json +1 -1
- /package/docs/{codex-switch-v0.0.4-design.md → Design/codex-switch-v0.0.4-design.md} +0 -0
package/dist/cli.js
CHANGED
|
@@ -1,68 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
-
if (k2 === undefined) k2 = k;
|
|
5
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
-
}
|
|
9
|
-
Object.defineProperty(o, k2, desc);
|
|
10
|
-
}) : (function(o, m, k, k2) {
|
|
11
|
-
if (k2 === undefined) k2 = k;
|
|
12
|
-
o[k2] = m[k];
|
|
13
|
-
}));
|
|
14
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
-
}) : function(o, v) {
|
|
17
|
-
o["default"] = v;
|
|
18
|
-
});
|
|
19
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
-
var ownKeys = function(o) {
|
|
21
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
-
var ar = [];
|
|
23
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
-
return ar;
|
|
25
|
-
};
|
|
26
|
-
return ownKeys(o);
|
|
27
|
-
};
|
|
28
|
-
return function (mod) {
|
|
29
|
-
if (mod && mod.__esModule) return mod;
|
|
30
|
-
var result = {};
|
|
31
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
-
__setModuleDefault(result, mod);
|
|
33
|
-
return result;
|
|
34
|
-
};
|
|
35
|
-
})();
|
|
36
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
4
|
exports.printHelp = printHelp;
|
|
38
5
|
exports.printVersion = printVersion;
|
|
39
|
-
exports.
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
const export_providers_1 = require("./app/export-providers");
|
|
44
|
-
const get_current_profile_1 = require("./app/get-current-profile");
|
|
45
|
-
const get_status_1 = require("./app/get-status");
|
|
46
|
-
const import_providers_1 = require("./app/import-providers");
|
|
47
|
-
const list_backups_1 = require("./app/list-backups");
|
|
48
|
-
const list_providers_1 = require("./app/list-providers");
|
|
49
|
-
const remove_provider_1 = require("./app/remove-provider");
|
|
50
|
-
const rollback_backup_1 = require("./app/rollback-backup");
|
|
51
|
-
const run_doctor_1 = require("./app/run-doctor");
|
|
52
|
-
const setup_codex_1 = require("./app/setup-codex");
|
|
53
|
-
const show_provider_1 = require("./app/show-provider");
|
|
54
|
-
const switch_provider_1 = require("./app/switch-provider");
|
|
6
|
+
exports.main = main;
|
|
7
|
+
const dispatch_1 = require("./commands/dispatch");
|
|
8
|
+
const args_1 = require("./commands/args");
|
|
9
|
+
const help_1 = require("./commands/help");
|
|
55
10
|
const errors_1 = require("./domain/errors");
|
|
56
|
-
const config_repo_1 = require("./infra/config-repo");
|
|
57
|
-
const providers_repo_1 = require("./infra/providers-repo");
|
|
58
|
-
const codex_paths_1 = require("./infra/codex-paths");
|
|
59
|
-
const args_1 = require("./cli/args");
|
|
60
|
-
const add_interactive_1 = require("./cli/add-interactive");
|
|
61
|
-
const help_1 = require("./cli/help");
|
|
62
|
-
const interactive_1 = require("./cli/interactive");
|
|
63
11
|
const output_1 = require("./cli/output");
|
|
64
|
-
const
|
|
65
|
-
const VERSION = "0.0.4";
|
|
12
|
+
const VERSION = "0.0.6";
|
|
66
13
|
/**
|
|
67
14
|
* Prints the command help text to stdout.
|
|
68
15
|
*/
|
|
@@ -85,10 +32,10 @@ function main() {
|
|
|
85
32
|
process.exit(0);
|
|
86
33
|
}
|
|
87
34
|
if (parsed.helpRequested) {
|
|
88
|
-
if (parsed.helpTarget && !(0, help_1.
|
|
89
|
-
(0, output_1.outputFailure)({ command: "help", options: parsed.globalOptions }, (0, errors_1.cliError)("INVALID_ARGUMENT", `Unknown help topic: ${parsed.helpTarget}`, {
|
|
90
|
-
availableCommands: (0, help_1.
|
|
91
|
-
}));
|
|
35
|
+
if (parsed.helpTarget && !(0, help_1.isKnownCommandNameForHelp)(parsed.helpTarget)) {
|
|
36
|
+
(0, output_1.outputFailure)({ command: "help", options: parsed.globalOptions }, (0, errors_1.normalizeError)((0, errors_1.cliError)("INVALID_ARGUMENT", `Unknown help topic: ${parsed.helpTarget}`, {
|
|
37
|
+
availableCommands: (0, help_1.getKnownCommandNames)(),
|
|
38
|
+
})));
|
|
92
39
|
return;
|
|
93
40
|
}
|
|
94
41
|
printHelp(parsed.helpTarget);
|
|
@@ -102,7 +49,7 @@ function main() {
|
|
|
102
49
|
command: parsed.command,
|
|
103
50
|
options: parsed.globalOptions,
|
|
104
51
|
};
|
|
105
|
-
executeCommand(ctx, parsed)
|
|
52
|
+
(0, dispatch_1.executeCommand)(ctx, parsed)
|
|
106
53
|
.then((result) => {
|
|
107
54
|
(0, output_1.outputSuccess)(ctx, result);
|
|
108
55
|
})
|
|
@@ -110,258 +57,6 @@ function main() {
|
|
|
110
57
|
(0, output_1.outputFailure)(ctx, (0, errors_1.normalizeError)(error));
|
|
111
58
|
});
|
|
112
59
|
}
|
|
113
|
-
/**
|
|
114
|
-
* Dispatches a parsed CLI command into the application layer.
|
|
115
|
-
*/
|
|
116
|
-
async function executeCommand(ctx, parsed, runtime = (0, prompt_1.createPromptRuntime)()) {
|
|
117
|
-
const paths = (0, codex_paths_1.createCodexPaths)(ctx.options.codexDir);
|
|
118
|
-
switch (ctx.command) {
|
|
119
|
-
case "list":
|
|
120
|
-
return (0, list_providers_1.listProviders)(paths.providersPath);
|
|
121
|
-
case "show": {
|
|
122
|
-
let providerName = parsed.positionals[0] ?? null;
|
|
123
|
-
if (!providerName && (0, interactive_1.canPrompt)(runtime, ctx.options.json)) {
|
|
124
|
-
providerName = await (0, interactive_1.promptForProviderSelection)(runtime, paths.providersPath, "Choose a provider to show");
|
|
125
|
-
}
|
|
126
|
-
if (!providerName) {
|
|
127
|
-
throw (0, errors_1.cliError)("INVALID_ARGUMENT", "Missing provider name for show command.");
|
|
128
|
-
}
|
|
129
|
-
return (0, show_provider_1.showProvider)({
|
|
130
|
-
providersPath: paths.providersPath,
|
|
131
|
-
providerName,
|
|
132
|
-
includeSecret: ctx.options.json,
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
case "current":
|
|
136
|
-
return (0, get_current_profile_1.getCurrentProfile)(paths.configPath);
|
|
137
|
-
case "status":
|
|
138
|
-
return (0, get_status_1.getStatus)(paths.codexDir, paths.configPath, paths.providersPath);
|
|
139
|
-
case "switch": {
|
|
140
|
-
let providerName = parsed.positionals[0] ?? null;
|
|
141
|
-
if (!providerName && (0, interactive_1.canPrompt)(runtime, ctx.options.json)) {
|
|
142
|
-
providerName = await (0, interactive_1.promptForProviderSelection)(runtime, paths.providersPath, "Choose a provider to switch to");
|
|
143
|
-
}
|
|
144
|
-
if (!providerName) {
|
|
145
|
-
throw (0, errors_1.cliError)("PROVIDER_NOT_FOUND", "Missing provider name for switch command.");
|
|
146
|
-
}
|
|
147
|
-
return (0, switch_provider_1.switchProvider)({
|
|
148
|
-
codexDir: paths.codexDir,
|
|
149
|
-
backupsDir: paths.backupsDir,
|
|
150
|
-
latestBackupPath: paths.latestBackupPath,
|
|
151
|
-
configPath: paths.configPath,
|
|
152
|
-
providersPath: paths.providersPath,
|
|
153
|
-
authPath: paths.authPath,
|
|
154
|
-
providerName,
|
|
155
|
-
noLogin: (0, args_1.hasFlag)(parsed.commandOptions, "--no-login"),
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
case "import": {
|
|
159
|
-
const sourceFile = parsed.positionals[0];
|
|
160
|
-
if (!sourceFile) {
|
|
161
|
-
throw (0, errors_1.cliError)("INVALID_ARGUMENT", "Missing import file path.");
|
|
162
|
-
}
|
|
163
|
-
const merge = (0, args_1.hasFlag)(parsed.commandOptions, "--merge");
|
|
164
|
-
if ((0, interactive_1.canPrompt)(runtime, ctx.options.json)) {
|
|
165
|
-
await (0, interactive_1.confirmImport)(runtime, sourceFile, merge);
|
|
166
|
-
}
|
|
167
|
-
return (0, import_providers_1.importProviders)({
|
|
168
|
-
codexDir: paths.codexDir,
|
|
169
|
-
backupsDir: paths.backupsDir,
|
|
170
|
-
latestBackupPath: paths.latestBackupPath,
|
|
171
|
-
providersPath: paths.providersPath,
|
|
172
|
-
sourceFile,
|
|
173
|
-
merge,
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
case "export": {
|
|
177
|
-
const targetFile = parsed.positionals[0];
|
|
178
|
-
if (!targetFile) {
|
|
179
|
-
throw (0, errors_1.cliError)("INVALID_ARGUMENT", "Missing export file path.");
|
|
180
|
-
}
|
|
181
|
-
let force = (0, args_1.hasFlag)(parsed.commandOptions, "--force");
|
|
182
|
-
if (!force && (0, interactive_1.canPrompt)(runtime, ctx.options.json) && (0, interactive_1.exportTargetExists)(targetFile)) {
|
|
183
|
-
const confirmed = await (0, interactive_1.confirmExportOverwrite)(runtime, targetFile);
|
|
184
|
-
if (!confirmed) {
|
|
185
|
-
throw (0, errors_1.cliError)("PROMPT_CANCELLED", "Export cancelled.");
|
|
186
|
-
}
|
|
187
|
-
force = true;
|
|
188
|
-
}
|
|
189
|
-
return (0, export_providers_1.exportProviders)({
|
|
190
|
-
providersPath: paths.providersPath,
|
|
191
|
-
targetFile,
|
|
192
|
-
force,
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
case "add": {
|
|
196
|
-
let providerName = parsed.positionals[0] ?? null;
|
|
197
|
-
let profile = (0, args_1.getSingleOption)(parsed.commandOptions, "--profile");
|
|
198
|
-
let apiKey = (0, args_1.getSingleOption)(parsed.commandOptions, "--api-key");
|
|
199
|
-
let baseUrl = (0, args_1.getSingleOption)(parsed.commandOptions, "--base-url", false);
|
|
200
|
-
let note = (0, args_1.getSingleOption)(parsed.commandOptions, "--note", false);
|
|
201
|
-
let tags = parsed.commandOptions.get("--tag") ?? [];
|
|
202
|
-
if (!providerName || !profile || !apiKey) {
|
|
203
|
-
if (ctx.options.json || !runtime.isInteractive()) {
|
|
204
|
-
throw (0, add_interactive_1.createNonInteractiveAddError)();
|
|
205
|
-
}
|
|
206
|
-
const prompted = await (0, add_interactive_1.collectAddInput)(runtime, {
|
|
207
|
-
providerName,
|
|
208
|
-
profile,
|
|
209
|
-
apiKey,
|
|
210
|
-
baseUrl,
|
|
211
|
-
note,
|
|
212
|
-
tags,
|
|
213
|
-
}, (candidate) => Boolean((0, providers_repo_1.readProvidersFileIfExists)(paths.providersPath).providers[candidate]));
|
|
214
|
-
providerName = prompted.providerName;
|
|
215
|
-
profile = prompted.profile;
|
|
216
|
-
apiKey = prompted.apiKey;
|
|
217
|
-
baseUrl = prompted.baseUrl ?? null;
|
|
218
|
-
note = prompted.note ?? null;
|
|
219
|
-
tags = prompted.tags;
|
|
220
|
-
}
|
|
221
|
-
return (0, add_provider_1.addProvider)({
|
|
222
|
-
codexDir: paths.codexDir,
|
|
223
|
-
backupsDir: paths.backupsDir,
|
|
224
|
-
latestBackupPath: paths.latestBackupPath,
|
|
225
|
-
providersPath: paths.providersPath,
|
|
226
|
-
providerName,
|
|
227
|
-
profile,
|
|
228
|
-
apiKey,
|
|
229
|
-
baseUrl,
|
|
230
|
-
note,
|
|
231
|
-
tags,
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
case "edit": {
|
|
235
|
-
let providerName = parsed.positionals[0] ?? null;
|
|
236
|
-
if (!providerName && (0, interactive_1.canPrompt)(runtime, ctx.options.json)) {
|
|
237
|
-
providerName = await (0, interactive_1.promptForProviderSelection)(runtime, paths.providersPath, "Choose a provider to edit");
|
|
238
|
-
}
|
|
239
|
-
if (!providerName) {
|
|
240
|
-
throw (0, errors_1.cliError)("INVALID_ARGUMENT", "Missing provider name for edit command.");
|
|
241
|
-
}
|
|
242
|
-
let profile = (0, args_1.getSingleOption)(parsed.commandOptions, "--profile", false) ?? undefined;
|
|
243
|
-
let apiKey = (0, args_1.getSingleOption)(parsed.commandOptions, "--api-key", false) ?? undefined;
|
|
244
|
-
let baseUrl = (0, args_1.getSingleOption)(parsed.commandOptions, "--base-url", false) ?? undefined;
|
|
245
|
-
let note = (0, args_1.getSingleOption)(parsed.commandOptions, "--note", false) ?? undefined;
|
|
246
|
-
let tags = parsed.commandOptions.has("--tag")
|
|
247
|
-
? parsed.commandOptions.get("--tag") ?? []
|
|
248
|
-
: undefined;
|
|
249
|
-
if (profile === undefined &&
|
|
250
|
-
apiKey === undefined &&
|
|
251
|
-
baseUrl === undefined &&
|
|
252
|
-
note === undefined &&
|
|
253
|
-
tags === undefined &&
|
|
254
|
-
(0, interactive_1.canPrompt)(runtime, ctx.options.json)) {
|
|
255
|
-
const provider = (0, providers_repo_1.readProvidersFileIfExists)(paths.providersPath).providers[providerName];
|
|
256
|
-
if (!provider) {
|
|
257
|
-
throw (0, errors_1.cliError)("PROVIDER_NOT_FOUND", `Provider "${providerName}" was not found.`);
|
|
258
|
-
}
|
|
259
|
-
const prompted = await (0, interactive_1.collectEditInput)(runtime, provider);
|
|
260
|
-
profile = prompted.profile;
|
|
261
|
-
apiKey = prompted.apiKey;
|
|
262
|
-
baseUrl = prompted.baseUrl;
|
|
263
|
-
note = prompted.note;
|
|
264
|
-
tags = prompted.tags;
|
|
265
|
-
}
|
|
266
|
-
if (profile === undefined && apiKey === undefined && baseUrl === undefined && note === undefined && tags === undefined) {
|
|
267
|
-
throw (0, errors_1.cliError)("INVALID_ARGUMENT", "edit requires at least one field to update.");
|
|
268
|
-
}
|
|
269
|
-
return (0, edit_provider_1.editProvider)({
|
|
270
|
-
codexDir: paths.codexDir,
|
|
271
|
-
backupsDir: paths.backupsDir,
|
|
272
|
-
latestBackupPath: paths.latestBackupPath,
|
|
273
|
-
providersPath: paths.providersPath,
|
|
274
|
-
providerName,
|
|
275
|
-
profile,
|
|
276
|
-
apiKey,
|
|
277
|
-
baseUrl,
|
|
278
|
-
note,
|
|
279
|
-
tags,
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
case "remove": {
|
|
283
|
-
let providerName = parsed.positionals[0] ?? null;
|
|
284
|
-
const force = (0, args_1.hasFlag)(parsed.commandOptions, "--force");
|
|
285
|
-
if (!providerName && (0, interactive_1.canPrompt)(runtime, ctx.options.json)) {
|
|
286
|
-
providerName = await (0, interactive_1.promptForProviderSelection)(runtime, paths.providersPath, "Choose a provider to remove");
|
|
287
|
-
}
|
|
288
|
-
if (!providerName) {
|
|
289
|
-
throw (0, errors_1.cliError)("PROVIDER_NOT_FOUND", "Missing provider name for remove command.");
|
|
290
|
-
}
|
|
291
|
-
if (!force && !(0, interactive_1.canPrompt)(runtime, ctx.options.json)) {
|
|
292
|
-
throw (0, errors_1.cliError)("INVALID_ARGUMENT", "remove requires --force.");
|
|
293
|
-
}
|
|
294
|
-
if ((0, interactive_1.canPrompt)(runtime, ctx.options.json)) {
|
|
295
|
-
await (0, interactive_1.confirmProviderRemoval)(runtime, providerName);
|
|
296
|
-
}
|
|
297
|
-
return (0, remove_provider_1.removeProvider)({
|
|
298
|
-
codexDir: paths.codexDir,
|
|
299
|
-
backupsDir: paths.backupsDir,
|
|
300
|
-
latestBackupPath: paths.latestBackupPath,
|
|
301
|
-
providersPath: paths.providersPath,
|
|
302
|
-
providerName,
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
case "doctor":
|
|
306
|
-
return (0, run_doctor_1.runDoctor)({
|
|
307
|
-
codexDir: paths.codexDir,
|
|
308
|
-
configPath: paths.configPath,
|
|
309
|
-
providersPath: paths.providersPath,
|
|
310
|
-
});
|
|
311
|
-
case "setup": {
|
|
312
|
-
const overwrite = (0, args_1.hasFlag)(parsed.commandOptions, "--overwrite");
|
|
313
|
-
const merge = (0, args_1.hasFlag)(parsed.commandOptions, "--merge");
|
|
314
|
-
if (overwrite && merge) {
|
|
315
|
-
throw (0, errors_1.cliError)("INVALID_ARGUMENT", "setup does not allow both --merge and --overwrite.");
|
|
316
|
-
}
|
|
317
|
-
let strategy = overwrite ? "overwrite" : merge ? "merge" : null;
|
|
318
|
-
const providersExists = fs.existsSync(paths.providersPath);
|
|
319
|
-
if (providersExists && strategy === null) {
|
|
320
|
-
if (!(0, interactive_1.canPrompt)(runtime, ctx.options.json)) {
|
|
321
|
-
throw (0, errors_1.cliError)("PROVIDERS_ALREADY_EXISTS", "providers.json already exists. Pass --merge or --overwrite.", {
|
|
322
|
-
file: paths.providersPath,
|
|
323
|
-
});
|
|
324
|
-
}
|
|
325
|
-
const selected = await (0, interactive_1.chooseSetupStrategy)(runtime);
|
|
326
|
-
if (selected === "cancel") {
|
|
327
|
-
throw (0, errors_1.cliError)("PROMPT_CANCELLED", "Setup cancelled.");
|
|
328
|
-
}
|
|
329
|
-
strategy = selected;
|
|
330
|
-
}
|
|
331
|
-
const profiles = Array.from((0, config_repo_1.listConfigProfiles)(paths.configPath)).sort();
|
|
332
|
-
let providerDetailsByProfile = {};
|
|
333
|
-
if ((0, interactive_1.canPrompt)(runtime, ctx.options.json)) {
|
|
334
|
-
providerDetailsByProfile = await (0, interactive_1.collectSetupProviderDetails)(runtime, profiles);
|
|
335
|
-
}
|
|
336
|
-
return (0, setup_codex_1.setupCodex)({
|
|
337
|
-
codexDirOption: ctx.options.codexDir,
|
|
338
|
-
codexDir: paths.codexDir,
|
|
339
|
-
configPath: paths.configPath,
|
|
340
|
-
providersPath: paths.providersPath,
|
|
341
|
-
backupsDir: paths.backupsDir,
|
|
342
|
-
latestBackupPath: paths.latestBackupPath,
|
|
343
|
-
strategy: strategy ?? "overwrite",
|
|
344
|
-
providerDetailsByProfile,
|
|
345
|
-
});
|
|
346
|
-
}
|
|
347
|
-
case "backups-list":
|
|
348
|
-
return (0, list_backups_1.listBackupEntries)(paths.backupsDir);
|
|
349
|
-
case "rollback":
|
|
350
|
-
if (parsed.positionals.length > 1) {
|
|
351
|
-
throw (0, errors_1.cliError)("INVALID_ARGUMENT", "rollback accepts at most one backup id.");
|
|
352
|
-
}
|
|
353
|
-
if ((0, interactive_1.canPrompt)(runtime, ctx.options.json)) {
|
|
354
|
-
await (0, interactive_1.confirmRollback)(runtime, paths.latestBackupPath, paths.backupsDir, parsed.positionals[0] ?? null);
|
|
355
|
-
}
|
|
356
|
-
return (0, rollback_backup_1.rollbackBackup)({
|
|
357
|
-
latestBackupPath: paths.latestBackupPath,
|
|
358
|
-
backupsDir: paths.backupsDir,
|
|
359
|
-
backupId: parsed.positionals[0] ?? null,
|
|
360
|
-
});
|
|
361
|
-
default:
|
|
362
|
-
throw (0, errors_1.cliError)("UNKNOWN_COMMAND", `Unknown command: ${ctx.command}`);
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
60
|
if (require.main === module) {
|
|
366
61
|
main();
|
|
367
62
|
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseArgs = parseArgs;
|
|
4
|
+
exports.hasFlag = hasFlag;
|
|
5
|
+
exports.getSingleOption = getSingleOption;
|
|
6
|
+
const errors_1 = require("../domain/errors");
|
|
7
|
+
const codex_paths_1 = require("../storage/codex-paths");
|
|
8
|
+
const registry_1 = require("./registry");
|
|
9
|
+
/**
|
|
10
|
+
* Parses argv into command positionals, global flags, and command-scoped options.
|
|
11
|
+
*/
|
|
12
|
+
function parseArgs(argv) {
|
|
13
|
+
let json = false;
|
|
14
|
+
let codexDir = (0, codex_paths_1.resolveCodexDir)();
|
|
15
|
+
let codexDirExplicit = false;
|
|
16
|
+
const remaining = [];
|
|
17
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
18
|
+
const value = argv[index];
|
|
19
|
+
if (value === "--json") {
|
|
20
|
+
json = true;
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (value === "--codex-dir") {
|
|
24
|
+
const next = argv[index + 1];
|
|
25
|
+
if (!next) {
|
|
26
|
+
throw (0, errors_1.cliError)("INVALID_ARGUMENT", "--codex-dir requires a path value.");
|
|
27
|
+
}
|
|
28
|
+
codexDir = (0, codex_paths_1.resolveCodexDir)(next);
|
|
29
|
+
codexDirExplicit = true;
|
|
30
|
+
index += 1;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
remaining.push(value);
|
|
34
|
+
}
|
|
35
|
+
if (remaining[0] === "help") {
|
|
36
|
+
return {
|
|
37
|
+
command: null,
|
|
38
|
+
positionals: [],
|
|
39
|
+
globalOptions: {
|
|
40
|
+
json,
|
|
41
|
+
codexDir,
|
|
42
|
+
codexDirExplicit,
|
|
43
|
+
},
|
|
44
|
+
commandOptions: new Map(),
|
|
45
|
+
helpRequested: true,
|
|
46
|
+
helpTarget: remaining.slice(1).join(" ") || null,
|
|
47
|
+
versionRequested: false,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
const versionRequested = remaining.includes("--version") || remaining.includes("-v");
|
|
51
|
+
if (versionRequested) {
|
|
52
|
+
return defaultParsed(null, {
|
|
53
|
+
json,
|
|
54
|
+
codexDir,
|
|
55
|
+
versionRequested: true,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
const { definition, consumedTokens } = (0, registry_1.resolveCommandFromArgv)(remaining);
|
|
59
|
+
const command = definition?.id ?? null;
|
|
60
|
+
const positionals = [];
|
|
61
|
+
const commandOptions = new Map();
|
|
62
|
+
let helpRequested = false;
|
|
63
|
+
const startIndex = consumedTokens > 0 ? consumedTokens : Math.min(remaining.length, 1);
|
|
64
|
+
for (let index = startIndex; index < remaining.length; index += 1) {
|
|
65
|
+
const value = remaining[index];
|
|
66
|
+
if (value === "--help" || value === "-h") {
|
|
67
|
+
helpRequested = true;
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (value.startsWith("--")) {
|
|
71
|
+
const optionName = value;
|
|
72
|
+
const next = remaining[index + 1];
|
|
73
|
+
if (!next || next.startsWith("--")) {
|
|
74
|
+
commandOptions.set(optionName, ["true"]);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const existing = commandOptions.get(optionName) ?? [];
|
|
78
|
+
existing.push(next);
|
|
79
|
+
commandOptions.set(optionName, existing);
|
|
80
|
+
index += 1;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
positionals.push(value);
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
command,
|
|
87
|
+
positionals,
|
|
88
|
+
globalOptions: {
|
|
89
|
+
json,
|
|
90
|
+
codexDir,
|
|
91
|
+
codexDirExplicit,
|
|
92
|
+
},
|
|
93
|
+
commandOptions,
|
|
94
|
+
helpRequested,
|
|
95
|
+
helpTarget: helpRequested && definition ? definition.tokens.join(" ") : null,
|
|
96
|
+
versionRequested: false,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Creates a parsed result for built-in synthetic commands such as help/version.
|
|
101
|
+
*/
|
|
102
|
+
function defaultParsed(command, overrides) {
|
|
103
|
+
return {
|
|
104
|
+
command,
|
|
105
|
+
positionals: [],
|
|
106
|
+
globalOptions: {
|
|
107
|
+
json: overrides?.json ?? false,
|
|
108
|
+
codexDir: overrides?.codexDir ?? (0, codex_paths_1.resolveCodexDir)(),
|
|
109
|
+
codexDirExplicit: false,
|
|
110
|
+
},
|
|
111
|
+
commandOptions: new Map(),
|
|
112
|
+
helpRequested: overrides?.helpRequested ?? false,
|
|
113
|
+
helpTarget: overrides?.helpTarget ?? null,
|
|
114
|
+
versionRequested: overrides?.versionRequested ?? false,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Checks whether a boolean-style option was supplied.
|
|
119
|
+
*/
|
|
120
|
+
function hasFlag(options, name) {
|
|
121
|
+
return options.has(name);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Returns the last supplied value for a single-valued command option.
|
|
125
|
+
*/
|
|
126
|
+
function getSingleOption(options, name, required = true) {
|
|
127
|
+
const values = options.get(name) ?? [];
|
|
128
|
+
if (values.length === 0) {
|
|
129
|
+
return required ? null : null;
|
|
130
|
+
}
|
|
131
|
+
return values[values.length - 1];
|
|
132
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.executeCommand = executeCommand;
|
|
4
|
+
const errors_1 = require("../domain/errors");
|
|
5
|
+
const prompt_1 = require("../interaction/prompt");
|
|
6
|
+
const registry_1 = require("./registry");
|
|
7
|
+
/**
|
|
8
|
+
* Resolves the shared command definition and executes its registered handler.
|
|
9
|
+
*/
|
|
10
|
+
async function executeCommand(ctx, parsed, runtime = (0, prompt_1.createPromptRuntime)()) {
|
|
11
|
+
const definition = (0, registry_1.findCommandDefinition)(ctx.command);
|
|
12
|
+
if (!definition) {
|
|
13
|
+
throw (0, errors_1.cliError)("UNKNOWN_COMMAND", `Unknown command: ${ctx.command}`);
|
|
14
|
+
}
|
|
15
|
+
return definition.handler(ctx, parsed, runtime);
|
|
16
|
+
}
|