@benbenwu/zcf 3.6.4

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 (94) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +193 -0
  3. package/bin/zcf.mjs +2 -0
  4. package/dist/chunks/api-providers.mjs +137 -0
  5. package/dist/chunks/claude-code-config-manager.mjs +731 -0
  6. package/dist/chunks/claude-code-incremental-manager.mjs +601 -0
  7. package/dist/chunks/codex-config-switch.mjs +394 -0
  8. package/dist/chunks/codex-provider-manager.mjs +197 -0
  9. package/dist/chunks/codex-uninstaller.mjs +422 -0
  10. package/dist/chunks/commands.mjs +118 -0
  11. package/dist/chunks/features.mjs +632 -0
  12. package/dist/chunks/simple-config.mjs +7904 -0
  13. package/dist/cli.d.mts +1 -0
  14. package/dist/cli.d.ts +1 -0
  15. package/dist/cli.mjs +2013 -0
  16. package/dist/i18n/locales/en/api.json +53 -0
  17. package/dist/i18n/locales/en/ccr.json +65 -0
  18. package/dist/i18n/locales/en/cli.json +55 -0
  19. package/dist/i18n/locales/en/codex.json +123 -0
  20. package/dist/i18n/locales/en/cometix.json +29 -0
  21. package/dist/i18n/locales/en/common.json +20 -0
  22. package/dist/i18n/locales/en/configuration.json +85 -0
  23. package/dist/i18n/locales/en/errors.json +26 -0
  24. package/dist/i18n/locales/en/installation.json +80 -0
  25. package/dist/i18n/locales/en/language.json +19 -0
  26. package/dist/i18n/locales/en/mcp.json +24 -0
  27. package/dist/i18n/locales/en/menu.json +51 -0
  28. package/dist/i18n/locales/en/multi-config.json +79 -0
  29. package/dist/i18n/locales/en/tools.json +15 -0
  30. package/dist/i18n/locales/en/uninstall.json +56 -0
  31. package/dist/i18n/locales/en/updater.json +25 -0
  32. package/dist/i18n/locales/en/workflow.json +23 -0
  33. package/dist/i18n/locales/zh-CN/api.json +53 -0
  34. package/dist/i18n/locales/zh-CN/ccr.json +65 -0
  35. package/dist/i18n/locales/zh-CN/cli.json +55 -0
  36. package/dist/i18n/locales/zh-CN/codex.json +123 -0
  37. package/dist/i18n/locales/zh-CN/cometix.json +29 -0
  38. package/dist/i18n/locales/zh-CN/common.json +20 -0
  39. package/dist/i18n/locales/zh-CN/configuration.json +85 -0
  40. package/dist/i18n/locales/zh-CN/errors.json +26 -0
  41. package/dist/i18n/locales/zh-CN/installation.json +80 -0
  42. package/dist/i18n/locales/zh-CN/language.json +19 -0
  43. package/dist/i18n/locales/zh-CN/mcp.json +24 -0
  44. package/dist/i18n/locales/zh-CN/menu.json +51 -0
  45. package/dist/i18n/locales/zh-CN/multi-config.json +79 -0
  46. package/dist/i18n/locales/zh-CN/tools.json +15 -0
  47. package/dist/i18n/locales/zh-CN/uninstall.json +56 -0
  48. package/dist/i18n/locales/zh-CN/updater.json +25 -0
  49. package/dist/i18n/locales/zh-CN/workflow.json +23 -0
  50. package/dist/index.d.mts +324 -0
  51. package/dist/index.d.ts +324 -0
  52. package/dist/index.mjs +19 -0
  53. package/dist/shared/zcf.DGjQxTq_.mjs +34 -0
  54. package/package.json +117 -0
  55. package/templates/CLAUDE.md +221 -0
  56. package/templates/claude-code/CLAUDE.md +250 -0
  57. package/templates/claude-code/common/settings.json +48 -0
  58. package/templates/claude-code/en/workflow/bmad/commands/bmad-init.md +275 -0
  59. package/templates/claude-code/en/workflow/common/agents/get-current-datetime.md +29 -0
  60. package/templates/claude-code/en/workflow/common/agents/init-architect.md +114 -0
  61. package/templates/claude-code/en/workflow/common/commands/init-project.md +53 -0
  62. package/templates/claude-code/en/workflow/plan/agents/planner.md +116 -0
  63. package/templates/claude-code/en/workflow/plan/agents/ui-ux-designer.md +91 -0
  64. package/templates/claude-code/en/workflow/plan/commands/feat.md +105 -0
  65. package/templates/claude-code/zh-CN/workflow/bmad/commands/bmad-init.md +275 -0
  66. package/templates/claude-code/zh-CN/workflow/common/agents/get-current-datetime.md +29 -0
  67. package/templates/claude-code/zh-CN/workflow/common/agents/init-architect.md +114 -0
  68. package/templates/claude-code/zh-CN/workflow/common/commands/init-project.md +53 -0
  69. package/templates/claude-code/zh-CN/workflow/plan/agents/planner.md +116 -0
  70. package/templates/claude-code/zh-CN/workflow/plan/agents/ui-ux-designer.md +91 -0
  71. package/templates/claude-code/zh-CN/workflow/plan/commands/feat.md +105 -0
  72. package/templates/codex/common/config.toml +0 -0
  73. package/templates/common/output-styles/en/engineer-professional.md +88 -0
  74. package/templates/common/output-styles/en/laowang-engineer.md +127 -0
  75. package/templates/common/output-styles/en/leibus-engineer.md +251 -0
  76. package/templates/common/output-styles/en/nekomata-engineer.md +120 -0
  77. package/templates/common/output-styles/en/ojousama-engineer.md +121 -0
  78. package/templates/common/output-styles/en/rem-engineer.md +173 -0
  79. package/templates/common/output-styles/zh-CN/engineer-professional.md +89 -0
  80. package/templates/common/output-styles/zh-CN/laowang-engineer.md +127 -0
  81. package/templates/common/output-styles/zh-CN/leibus-engineer.md +251 -0
  82. package/templates/common/output-styles/zh-CN/nekomata-engineer.md +120 -0
  83. package/templates/common/output-styles/zh-CN/ojousama-engineer.md +121 -0
  84. package/templates/common/output-styles/zh-CN/rem-engineer.md +179 -0
  85. package/templates/common/workflow/git/en/git-cleanBranches.md +102 -0
  86. package/templates/common/workflow/git/en/git-commit.md +205 -0
  87. package/templates/common/workflow/git/en/git-rollback.md +90 -0
  88. package/templates/common/workflow/git/en/git-worktree.md +276 -0
  89. package/templates/common/workflow/git/zh-CN/git-cleanBranches.md +102 -0
  90. package/templates/common/workflow/git/zh-CN/git-commit.md +205 -0
  91. package/templates/common/workflow/git/zh-CN/git-rollback.md +90 -0
  92. package/templates/common/workflow/git/zh-CN/git-worktree.md +276 -0
  93. package/templates/common/workflow/sixStep/en/workflow.md +251 -0
  94. package/templates/common/workflow/sixStep/zh-CN/workflow.md +215 -0
@@ -0,0 +1,394 @@
1
+ import ansis from 'ansis';
2
+ import inquirer from 'inquirer';
3
+ import { an as ensureI18nInitialized, aA as detectConfigManagementMode, ao as i18n, ap as addNumbersToChoices, ar as promptBoolean, aw as readJsonConfig, l as CODEX_AUTH_FILE } from './simple-config.mjs';
4
+ import { deleteProviders, addProviderToExisting, editExistingProvider } from './codex-provider-manager.mjs';
5
+ import 'node:fs';
6
+ import 'node:process';
7
+ import 'node:child_process';
8
+ import 'node:os';
9
+ import 'node:util';
10
+ import 'dayjs';
11
+ import 'pathe';
12
+ import 'node:url';
13
+ import 'inquirer-toggle';
14
+ import 'ora';
15
+ import 'tinyexec';
16
+ import 'semver';
17
+ import '@rainbowatcher/toml-edit-js';
18
+ import 'node:fs/promises';
19
+ import 'i18next';
20
+ import 'i18next-fs-backend';
21
+
22
+ async function configureIncrementalManagement() {
23
+ ensureI18nInitialized();
24
+ const managementMode = detectConfigManagementMode();
25
+ if (managementMode.mode !== "management" || !managementMode.hasProviders) {
26
+ console.log(ansis.yellow(i18n.t("codex:noExistingProviders")));
27
+ return;
28
+ }
29
+ console.log(ansis.cyan(i18n.t("codex:incrementalManagementTitle")));
30
+ console.log(ansis.gray(i18n.t("codex:currentProviderCount", { count: managementMode.providerCount })));
31
+ if (managementMode.currentProvider) {
32
+ console.log(ansis.gray(i18n.t("codex:currentDefaultProvider", { provider: managementMode.currentProvider })));
33
+ }
34
+ const choices = [
35
+ { name: i18n.t("codex:addProvider"), value: "add" },
36
+ { name: i18n.t("codex:editProvider"), value: "edit" },
37
+ { name: i18n.t("codex:copyProvider"), value: "copy" },
38
+ { name: i18n.t("codex:deleteProvider"), value: "delete" },
39
+ { name: i18n.t("common:skip"), value: "skip" }
40
+ ];
41
+ const { action } = await inquirer.prompt([{
42
+ type: "list",
43
+ name: "action",
44
+ message: i18n.t("codex:selectAction"),
45
+ choices: addNumbersToChoices(choices)
46
+ }]);
47
+ if (!action || action === "skip") {
48
+ console.log(ansis.yellow(i18n.t("common:skip")));
49
+ return;
50
+ }
51
+ switch (action) {
52
+ case "add":
53
+ await handleAddProvider();
54
+ break;
55
+ case "edit":
56
+ await handleEditProvider(managementMode.providers);
57
+ break;
58
+ case "copy":
59
+ await handleCopyProvider(managementMode.providers);
60
+ break;
61
+ case "delete":
62
+ await handleDeleteProvider(managementMode.providers);
63
+ break;
64
+ }
65
+ }
66
+ async function handleAddProvider() {
67
+ const { getApiProviders } = await import('./api-providers.mjs');
68
+ const apiProviders = getApiProviders("codex");
69
+ const providerChoices = [
70
+ { name: i18n.t("api:customProvider"), value: "custom" },
71
+ ...apiProviders.map((p) => ({ name: p.name, value: p.id }))
72
+ ];
73
+ const { selectedProvider } = await inquirer.prompt([{
74
+ type: "list",
75
+ name: "selectedProvider",
76
+ message: i18n.t("api:selectApiProvider"),
77
+ choices: addNumbersToChoices(providerChoices)
78
+ }]);
79
+ let prefilledBaseUrl;
80
+ let prefilledWireApi;
81
+ let prefilledModel;
82
+ if (selectedProvider !== "custom") {
83
+ const provider2 = apiProviders.find((p) => p.id === selectedProvider);
84
+ if (provider2?.codex) {
85
+ prefilledBaseUrl = provider2.codex.baseUrl;
86
+ prefilledWireApi = provider2.codex.wireApi;
87
+ prefilledModel = provider2.codex.defaultModel;
88
+ console.log(ansis.gray(i18n.t("api:providerSelected", { name: provider2.name })));
89
+ }
90
+ }
91
+ const answers = await inquirer.prompt([
92
+ {
93
+ type: "input",
94
+ name: "providerName",
95
+ message: i18n.t("codex:providerNamePrompt"),
96
+ default: selectedProvider !== "custom" ? apiProviders.find((p) => p.id === selectedProvider)?.name : void 0,
97
+ validate: (input) => {
98
+ const trimmed = input.trim();
99
+ if (!trimmed)
100
+ return i18n.t("codex:providerNameRequired");
101
+ if (!/^[\w\-\s.]+$/.test(trimmed))
102
+ return i18n.t("codex:providerNameInvalid");
103
+ return true;
104
+ }
105
+ },
106
+ {
107
+ type: "input",
108
+ name: "baseUrl",
109
+ message: i18n.t("codex:providerBaseUrlPrompt"),
110
+ default: prefilledBaseUrl || "https://api.openai.com/v1",
111
+ when: () => selectedProvider === "custom",
112
+ validate: (input) => !!input.trim() || i18n.t("codex:providerBaseUrlRequired")
113
+ },
114
+ {
115
+ type: "input",
116
+ name: "apiKey",
117
+ message: selectedProvider !== "custom" ? i18n.t("api:enterProviderApiKey", { provider: apiProviders.find((p) => p.id === selectedProvider)?.name || selectedProvider }) : i18n.t("codex:providerApiKeyPrompt"),
118
+ validate: (input) => !!input.trim() || i18n.t("codex:providerApiKeyRequired")
119
+ }
120
+ ]);
121
+ const providerId = answers.providerName.trim().toLowerCase().replace(/\s+/g, "-").replace(/\./g, "-").replace(/[^a-z0-9\-]/g, "");
122
+ const managementMode = detectConfigManagementMode();
123
+ const existingProvider = managementMode.providers?.find((p) => p.id === providerId);
124
+ if (existingProvider) {
125
+ const shouldOverwrite = await promptBoolean({
126
+ message: i18n.t("codex:providerDuplicatePrompt", {
127
+ name: existingProvider.name,
128
+ source: i18n.t("codex:existingConfig")
129
+ }),
130
+ defaultValue: false
131
+ });
132
+ if (!shouldOverwrite) {
133
+ console.log(ansis.yellow(i18n.t("codex:providerDuplicateSkipped")));
134
+ return;
135
+ }
136
+ }
137
+ const provider = {
138
+ id: providerId,
139
+ name: answers.providerName.trim(),
140
+ baseUrl: selectedProvider === "custom" ? answers.baseUrl.trim() : prefilledBaseUrl,
141
+ wireApi: prefilledWireApi || "responses",
142
+ tempEnvKey: `${providerId.toUpperCase().replace(/-/g, "_")}_API_KEY`,
143
+ requiresOpenaiAuth: true,
144
+ model: prefilledModel || "gpt-5.2"
145
+ // Use provider's default model or fallback
146
+ };
147
+ const result = await addProviderToExisting(provider, answers.apiKey.trim(), true);
148
+ if (result.success) {
149
+ console.log(ansis.green(i18n.t("codex:providerAdded", { name: result.addedProvider?.name })));
150
+ if (result.backupPath) {
151
+ console.log(ansis.gray(i18n.t("common:backupCreated", { path: result.backupPath })));
152
+ }
153
+ const setAsDefault = await promptBoolean({
154
+ message: i18n.t("multi-config:setAsDefaultPrompt"),
155
+ defaultValue: true
156
+ });
157
+ if (setAsDefault) {
158
+ const { switchToProvider } = await import('./simple-config.mjs').then(function (n) { return n.bq; });
159
+ const switched = await switchToProvider(provider.id);
160
+ if (switched) {
161
+ console.log(ansis.green(i18n.t("multi-config:profileSetAsDefault", { name: provider.name })));
162
+ }
163
+ }
164
+ } else {
165
+ console.log(ansis.red(i18n.t("codex:providerAddFailed", { error: result.error })));
166
+ }
167
+ }
168
+ async function handleEditProvider(providers) {
169
+ const choices = providers.map((provider2) => ({
170
+ name: `${provider2.name} (${provider2.baseUrl})`,
171
+ value: provider2.id
172
+ }));
173
+ const { selectedProviderId } = await inquirer.prompt([{
174
+ type: "list",
175
+ name: "selectedProviderId",
176
+ message: i18n.t("codex:selectProviderToEdit"),
177
+ choices: addNumbersToChoices(choices)
178
+ }]);
179
+ if (!selectedProviderId) {
180
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
181
+ return;
182
+ }
183
+ const provider = providers.find((p) => p.id === selectedProviderId);
184
+ if (!provider) {
185
+ console.log(ansis.red(i18n.t("codex:providerNotFound")));
186
+ return;
187
+ }
188
+ const existingAuth = readJsonConfig(CODEX_AUTH_FILE, { defaultValue: {} }) || {};
189
+ const existingApiKey = existingAuth[provider.tempEnvKey] || "";
190
+ const answers = await inquirer.prompt([
191
+ {
192
+ type: "input",
193
+ name: "providerName",
194
+ message: i18n.t("codex:providerNamePrompt"),
195
+ default: provider.name,
196
+ validate: (input) => {
197
+ const trimmed = input.trim();
198
+ if (!trimmed)
199
+ return i18n.t("codex:providerNameRequired");
200
+ if (!/^[\w\-\s]+$/.test(trimmed))
201
+ return i18n.t("codex:providerNameInvalid");
202
+ return true;
203
+ }
204
+ },
205
+ {
206
+ type: "input",
207
+ name: "baseUrl",
208
+ message: i18n.t("codex:providerBaseUrlPrompt"),
209
+ default: provider.baseUrl,
210
+ validate: (input) => !!input.trim() || i18n.t("codex:providerBaseUrlRequired")
211
+ },
212
+ {
213
+ type: "input",
214
+ name: "apiKey",
215
+ message: i18n.t("codex:providerApiKeyPrompt"),
216
+ default: existingApiKey,
217
+ // Show old API key from auth.json
218
+ validate: (input) => !!input.trim() || i18n.t("codex:providerApiKeyRequired")
219
+ }
220
+ ]);
221
+ const { model } = await inquirer.prompt([
222
+ {
223
+ type: "input",
224
+ name: "model",
225
+ message: i18n.t("codex:providerModelPrompt"),
226
+ default: provider.model || "gpt-5.2",
227
+ validate: (input) => !!input.trim() || i18n.t("codex:providerModelRequired")
228
+ }
229
+ ]);
230
+ const updates = {
231
+ name: answers.providerName.trim(),
232
+ baseUrl: answers.baseUrl.trim(),
233
+ wireApi: "responses",
234
+ apiKey: answers.apiKey.trim(),
235
+ model: model.trim()
236
+ };
237
+ const result = await editExistingProvider(selectedProviderId, updates);
238
+ if (result.success) {
239
+ console.log(ansis.green(i18n.t("codex:providerUpdated", { name: result.updatedProvider?.name })));
240
+ if (result.backupPath) {
241
+ console.log(ansis.gray(i18n.t("common:backupCreated", { path: result.backupPath })));
242
+ }
243
+ } else {
244
+ console.log(ansis.red(i18n.t("codex:providerUpdateFailed", { error: result.error })));
245
+ }
246
+ }
247
+ async function handleCopyProvider(providers) {
248
+ const choices = providers.map((provider2) => ({
249
+ name: `${provider2.name} (${provider2.baseUrl})`,
250
+ value: provider2.id
251
+ }));
252
+ const { selectedProviderId } = await inquirer.prompt([{
253
+ type: "list",
254
+ name: "selectedProviderId",
255
+ message: i18n.t("codex:selectProviderToCopy"),
256
+ choices: addNumbersToChoices(choices)
257
+ }]);
258
+ if (!selectedProviderId) {
259
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
260
+ return;
261
+ }
262
+ const provider = providers.find((p) => p.id === selectedProviderId);
263
+ if (!provider) {
264
+ console.log(ansis.red(i18n.t("codex:providerNotFound")));
265
+ return;
266
+ }
267
+ console.log(ansis.cyan(`
268
+ ${i18n.t("codex:copyingProvider", { name: provider.name })}`));
269
+ const existingAuth = readJsonConfig(CODEX_AUTH_FILE, { defaultValue: {} }) || {};
270
+ const existingApiKey = existingAuth[provider.tempEnvKey] || "";
271
+ const copiedName = `${provider.name}-copy`;
272
+ const answers = await inquirer.prompt([
273
+ {
274
+ type: "input",
275
+ name: "providerName",
276
+ message: i18n.t("codex:providerNamePrompt"),
277
+ default: copiedName,
278
+ validate: (input) => {
279
+ const trimmed = input.trim();
280
+ if (!trimmed)
281
+ return i18n.t("codex:providerNameRequired");
282
+ if (!/^[\w\-\s.]+$/.test(trimmed))
283
+ return i18n.t("codex:providerNameInvalid");
284
+ return true;
285
+ }
286
+ },
287
+ {
288
+ type: "input",
289
+ name: "baseUrl",
290
+ message: i18n.t("codex:providerBaseUrlPrompt"),
291
+ default: provider.baseUrl,
292
+ validate: (input) => !!input.trim() || i18n.t("codex:providerBaseUrlRequired")
293
+ },
294
+ {
295
+ type: "input",
296
+ name: "apiKey",
297
+ message: i18n.t("codex:providerApiKeyPrompt"),
298
+ default: existingApiKey,
299
+ // Show old API key from auth.json
300
+ validate: (input) => !!input.trim() || i18n.t("codex:providerApiKeyRequired")
301
+ }
302
+ ]);
303
+ const { model } = await inquirer.prompt([
304
+ {
305
+ type: "input",
306
+ name: "model",
307
+ message: i18n.t("codex:providerModelPrompt"),
308
+ default: provider.model || "gpt-5.2",
309
+ validate: (input) => !!input.trim() || i18n.t("codex:providerModelRequired")
310
+ }
311
+ ]);
312
+ const providerId = answers.providerName.trim().toLowerCase().replace(/\s+/g, "-").replace(/\./g, "-").replace(/[^a-z0-9\-]/g, "");
313
+ const copiedProvider = {
314
+ id: providerId,
315
+ name: answers.providerName.trim(),
316
+ baseUrl: answers.baseUrl.trim(),
317
+ wireApi: "responses",
318
+ tempEnvKey: `${providerId.toUpperCase().replace(/-/g, "_")}_API_KEY`,
319
+ requiresOpenaiAuth: provider.requiresOpenaiAuth ?? true,
320
+ model: model.trim()
321
+ };
322
+ const result = await addProviderToExisting(copiedProvider, answers.apiKey.trim(), false);
323
+ if (result.success) {
324
+ console.log(ansis.green(i18n.t("codex:providerCopied", { name: result.addedProvider?.name })));
325
+ if (result.backupPath) {
326
+ console.log(ansis.gray(i18n.t("common:backupCreated", { path: result.backupPath })));
327
+ }
328
+ const setAsDefault = await promptBoolean({
329
+ message: i18n.t("multi-config:setAsDefaultPrompt"),
330
+ defaultValue: false
331
+ });
332
+ if (setAsDefault) {
333
+ const { switchToProvider } = await import('./simple-config.mjs').then(function (n) { return n.bq; });
334
+ const switched = await switchToProvider(copiedProvider.id);
335
+ if (switched) {
336
+ console.log(ansis.green(i18n.t("multi-config:profileSetAsDefault", { name: copiedProvider.name })));
337
+ }
338
+ }
339
+ } else {
340
+ console.log(ansis.red(i18n.t("codex:providerCopyFailed", { error: result.error })));
341
+ }
342
+ }
343
+ async function handleDeleteProvider(providers) {
344
+ const choices = providers.map((provider) => ({
345
+ name: `${provider.name} (${provider.baseUrl})`,
346
+ value: provider.id
347
+ }));
348
+ const { selectedProviderIds } = await inquirer.prompt({
349
+ type: "checkbox",
350
+ name: "selectedProviderIds",
351
+ message: i18n.t("codex:selectProvidersToDelete"),
352
+ choices,
353
+ validate: (input) => {
354
+ const selected = input;
355
+ if (!selected || selected.length === 0) {
356
+ return i18n.t("codex:selectAtLeastOne");
357
+ }
358
+ if (selected.length === providers.length) {
359
+ return i18n.t("codex:cannotDeleteAll");
360
+ }
361
+ return true;
362
+ }
363
+ });
364
+ if (!selectedProviderIds || selectedProviderIds.length === 0) {
365
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
366
+ return;
367
+ }
368
+ const selectedNames = selectedProviderIds.map(
369
+ (id) => providers.find((p) => p.id === id)?.name || id
370
+ ).join(", ");
371
+ const confirmDelete = await promptBoolean({
372
+ message: i18n.t("codex:confirmDeleteProviders", { providers: selectedNames }),
373
+ defaultValue: false
374
+ });
375
+ if (!confirmDelete) {
376
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
377
+ return;
378
+ }
379
+ const result = await deleteProviders(selectedProviderIds);
380
+ if (result.success) {
381
+ console.log(ansis.green(i18n.t("codex:providersDeleted", { count: selectedProviderIds.length })));
382
+ if (result.newDefaultProvider) {
383
+ console.log(ansis.cyan(i18n.t("codex:newDefaultProvider", { provider: result.newDefaultProvider })));
384
+ }
385
+ if (result.backupPath) {
386
+ console.log(ansis.gray(i18n.t("common:backupCreated", { path: result.backupPath })));
387
+ }
388
+ } else {
389
+ console.log(ansis.red(i18n.t("codex:providersDeleteFailed", { error: result.error })));
390
+ }
391
+ }
392
+ const codexConfigSwitch = { configureIncrementalManagement };
393
+
394
+ export { configureIncrementalManagement, codexConfigSwitch as default };
@@ -0,0 +1,197 @@
1
+ import { an as ensureI18nInitialized, aB as readCodexConfig, ao as i18n, aC as backupCodexComplete, aD as writeAuthFile } from './simple-config.mjs';
2
+ import 'node:fs';
3
+ import 'node:process';
4
+ import 'ansis';
5
+ import 'inquirer';
6
+ import 'node:child_process';
7
+ import 'node:os';
8
+ import 'node:util';
9
+ import 'dayjs';
10
+ import 'pathe';
11
+ import 'node:url';
12
+ import 'inquirer-toggle';
13
+ import 'ora';
14
+ import 'tinyexec';
15
+ import 'semver';
16
+ import '@rainbowatcher/toml-edit-js';
17
+ import 'node:fs/promises';
18
+ import 'i18next';
19
+ import 'i18next-fs-backend';
20
+
21
+ async function addProviderToExisting(provider, apiKey, allowOverwrite = false) {
22
+ ensureI18nInitialized();
23
+ try {
24
+ const existingConfig = readCodexConfig();
25
+ const existingProviderIndex = existingConfig?.providers.findIndex((p) => p.id === provider.id) ?? -1;
26
+ if (existingProviderIndex !== -1 && !allowOverwrite) {
27
+ return {
28
+ success: false,
29
+ error: i18n.t("codex:providerManager.providerExists", { id: provider.id })
30
+ };
31
+ }
32
+ let backupPath;
33
+ if (existingConfig) {
34
+ const backup = backupCodexComplete();
35
+ if (!backup) {
36
+ return {
37
+ success: false,
38
+ error: i18n.t("codex:providerManager.backupFailed")
39
+ };
40
+ }
41
+ backupPath = backup || void 0;
42
+ }
43
+ const { updateCodexApiFields, upsertCodexProvider } = await import('./simple-config.mjs').then(function (n) { return n.bp; });
44
+ if (!existingConfig) {
45
+ updateCodexApiFields({
46
+ model: provider.model,
47
+ modelProvider: provider.id,
48
+ modelProviderCommented: false
49
+ });
50
+ } else if (!existingConfig.modelProvider) {
51
+ updateCodexApiFields({
52
+ modelProvider: provider.id,
53
+ modelProviderCommented: false
54
+ });
55
+ }
56
+ upsertCodexProvider(provider.id, provider);
57
+ const authEntries = {};
58
+ authEntries[provider.tempEnvKey] = apiKey;
59
+ writeAuthFile(authEntries);
60
+ return {
61
+ success: true,
62
+ backupPath,
63
+ addedProvider: provider
64
+ };
65
+ } catch (error) {
66
+ return {
67
+ success: false,
68
+ error: error instanceof Error ? error.message : i18n.t("codex:providerManager.unknownError")
69
+ };
70
+ }
71
+ }
72
+ async function editExistingProvider(providerId, updates) {
73
+ ensureI18nInitialized();
74
+ try {
75
+ const existingConfig = readCodexConfig();
76
+ if (!existingConfig) {
77
+ return {
78
+ success: false,
79
+ error: i18n.t("codex:providerManager.noConfig")
80
+ };
81
+ }
82
+ const providerIndex = existingConfig.providers.findIndex((p) => p.id === providerId);
83
+ if (providerIndex === -1) {
84
+ return {
85
+ success: false,
86
+ error: i18n.t("codex:providerManager.providerNotFound", { id: providerId })
87
+ };
88
+ }
89
+ const backupPath = backupCodexComplete();
90
+ if (!backupPath) {
91
+ return {
92
+ success: false,
93
+ error: i18n.t("codex:providerManager.backupFailed")
94
+ };
95
+ }
96
+ const updatedProvider = {
97
+ ...existingConfig.providers[providerIndex],
98
+ ...updates.name && { name: updates.name },
99
+ ...updates.baseUrl && { baseUrl: updates.baseUrl },
100
+ ...updates.wireApi && { wireApi: updates.wireApi },
101
+ ...updates.model && { model: updates.model }
102
+ };
103
+ const { upsertCodexProvider } = await import('./simple-config.mjs').then(function (n) { return n.bp; });
104
+ upsertCodexProvider(providerId, updatedProvider);
105
+ if (updates.apiKey) {
106
+ const authEntries = {};
107
+ authEntries[updatedProvider.tempEnvKey] = updates.apiKey;
108
+ writeAuthFile(authEntries);
109
+ }
110
+ return {
111
+ success: true,
112
+ backupPath,
113
+ updatedProvider
114
+ };
115
+ } catch (error) {
116
+ return {
117
+ success: false,
118
+ error: error instanceof Error ? error.message : i18n.t("codex:providerManager.unknownError")
119
+ };
120
+ }
121
+ }
122
+ async function deleteProviders(providerIds) {
123
+ ensureI18nInitialized();
124
+ try {
125
+ const existingConfig = readCodexConfig();
126
+ if (!existingConfig) {
127
+ return {
128
+ success: false,
129
+ error: i18n.t("codex:providerManager.noConfig")
130
+ };
131
+ }
132
+ if (!providerIds || providerIds.length === 0) {
133
+ return {
134
+ success: false,
135
+ error: i18n.t("codex:providerManager.noProvidersSpecified")
136
+ };
137
+ }
138
+ const notFoundProviders = providerIds.filter(
139
+ (id) => !existingConfig.providers.some((p) => p.id === id)
140
+ );
141
+ if (notFoundProviders.length > 0) {
142
+ return {
143
+ success: false,
144
+ error: i18n.t("codex:providerManager.providersNotFound", {
145
+ providers: notFoundProviders.join(", ")
146
+ })
147
+ };
148
+ }
149
+ const remainingProviders = existingConfig.providers.filter(
150
+ (p) => !providerIds.includes(p.id)
151
+ );
152
+ if (remainingProviders.length === 0) {
153
+ return {
154
+ success: false,
155
+ error: i18n.t("codex:providerManager.cannotDeleteAll")
156
+ };
157
+ }
158
+ const backupPath = backupCodexComplete();
159
+ if (!backupPath) {
160
+ return {
161
+ success: false,
162
+ error: i18n.t("codex:providerManager.backupFailed")
163
+ };
164
+ }
165
+ let newDefaultProvider = existingConfig.modelProvider;
166
+ if (providerIds.includes(existingConfig.modelProvider || "")) {
167
+ newDefaultProvider = remainingProviders[0].id;
168
+ }
169
+ const { deleteCodexProvider, updateCodexApiFields } = await import('./simple-config.mjs').then(function (n) { return n.bp; });
170
+ if (newDefaultProvider !== existingConfig.modelProvider) {
171
+ updateCodexApiFields({
172
+ modelProvider: newDefaultProvider,
173
+ modelProviderCommented: false
174
+ });
175
+ }
176
+ for (const providerId of providerIds) {
177
+ deleteCodexProvider(providerId);
178
+ }
179
+ const result = {
180
+ success: true,
181
+ backupPath,
182
+ deletedProviders: providerIds,
183
+ remainingProviders
184
+ };
185
+ if (newDefaultProvider !== existingConfig.modelProvider) {
186
+ result.newDefaultProvider = newDefaultProvider || void 0;
187
+ }
188
+ return result;
189
+ } catch (error) {
190
+ return {
191
+ success: false,
192
+ error: error instanceof Error ? error.message : i18n.t("codex:providerManager.unknownError")
193
+ };
194
+ }
195
+ }
196
+
197
+ export { addProviderToExisting, deleteProviders, editExistingProvider };