zcf 3.1.3 → 3.2.0
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 +50 -21
- package/dist/chunks/claude-code-config-manager.mjs +705 -0
- package/dist/chunks/claude-code-incremental-manager.mjs +393 -0
- package/dist/chunks/codex-config-switch.mjs +2 -174
- package/dist/chunks/codex-provider-manager.mjs +193 -0
- package/dist/chunks/codex-uninstaller.mjs +1 -1
- package/dist/chunks/commands.mjs +117 -0
- package/dist/chunks/simple-config.mjs +578 -193
- package/dist/cli.mjs +284 -142
- package/dist/i18n/locales/en/api.json +1 -2
- package/dist/i18n/locales/en/cli.json +2 -0
- package/dist/i18n/locales/en/codex.json +0 -1
- package/dist/i18n/locales/en/common.json +2 -2
- package/dist/i18n/locales/en/errors.json +1 -0
- package/dist/i18n/locales/en/multi-config.json +61 -0
- package/dist/i18n/locales/zh-CN/api.json +1 -2
- package/dist/i18n/locales/zh-CN/cli.json +2 -0
- package/dist/i18n/locales/zh-CN/codex.json +0 -1
- package/dist/i18n/locales/zh-CN/common.json +2 -2
- package/dist/i18n/locales/zh-CN/errors.json +1 -0
- package/dist/i18n/locales/zh-CN/multi-config.json +61 -0
- package/dist/index.d.mts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/templates/claude-code/en/workflow/git/commands/git-commit.md +1 -0
- package/templates/claude-code/zh-CN/workflow/git/commands/git-commit.md +1 -0
- package/templates/codex/en/workflow/git/prompts/git-cleanBranches.md +102 -0
- package/templates/codex/en/workflow/git/prompts/git-commit.md +158 -0
- package/templates/codex/en/workflow/git/prompts/git-rollback.md +90 -0
- package/templates/codex/en/workflow/git/prompts/git-worktree.md +276 -0
- package/templates/codex/en/workflow/sixStep/prompts/workflow.md +140 -121
- package/templates/codex/zh-CN/workflow/git/prompts/git-cleanBranches.md +102 -0
- package/templates/codex/zh-CN/workflow/git/prompts/git-commit.md +158 -0
- package/templates/codex/zh-CN/workflow/git/prompts/git-rollback.md +90 -0
- package/templates/codex/zh-CN/workflow/git/prompts/git-worktree.md +276 -0
- package/templates/codex/zh-CN/workflow/sixStep/prompts/workflow.md +16 -33
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
import ansis from 'ansis';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { a2 as ensureI18nInitialized, a3 as i18n, a4 as addNumbersToChoices, a5 as validateApiKey } from './simple-config.mjs';
|
|
4
|
+
import { ClaudeCodeConfigManager } from './claude-code-config-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 'ora';
|
|
14
|
+
import 'semver';
|
|
15
|
+
import 'smol-toml';
|
|
16
|
+
import 'tinyexec';
|
|
17
|
+
import 'node:fs/promises';
|
|
18
|
+
import 'i18next';
|
|
19
|
+
import 'i18next-fs-backend';
|
|
20
|
+
|
|
21
|
+
function getAuthTypeLabel(authType) {
|
|
22
|
+
ensureI18nInitialized();
|
|
23
|
+
switch (authType) {
|
|
24
|
+
case "api_key":
|
|
25
|
+
return i18n.t("multi-config:authType.api_key");
|
|
26
|
+
case "auth_token":
|
|
27
|
+
return i18n.t("multi-config:authType.auth_token");
|
|
28
|
+
case "ccr_proxy":
|
|
29
|
+
return i18n.t("multi-config:authType.ccr_proxy");
|
|
30
|
+
default:
|
|
31
|
+
return authType;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async function configureIncrementalManagement() {
|
|
35
|
+
ensureI18nInitialized();
|
|
36
|
+
const config = ClaudeCodeConfigManager.readConfig();
|
|
37
|
+
if (!config || !config.profiles || Object.keys(config.profiles).length === 0) {
|
|
38
|
+
await handleAddProfile();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const profiles = Object.values(config.profiles);
|
|
42
|
+
const currentProfile = config.currentProfileId ? config.profiles[config.currentProfileId] : null;
|
|
43
|
+
console.log(ansis.cyan(i18n.t("multi-config:incrementalManagementTitle")));
|
|
44
|
+
console.log(ansis.gray(i18n.t("multi-config:currentProfileCount", { count: profiles.length })));
|
|
45
|
+
if (currentProfile) {
|
|
46
|
+
console.log(ansis.gray(i18n.t("multi-config:currentDefaultProfile", { profile: currentProfile.name })));
|
|
47
|
+
}
|
|
48
|
+
const choices = [
|
|
49
|
+
{ name: i18n.t("multi-config:addProfile"), value: "add" },
|
|
50
|
+
{ name: i18n.t("multi-config:editProfile"), value: "edit" },
|
|
51
|
+
{ name: i18n.t("multi-config:deleteProfile"), value: "delete" },
|
|
52
|
+
{ name: i18n.t("common:skip"), value: "skip" }
|
|
53
|
+
];
|
|
54
|
+
const { action } = await inquirer.prompt([{
|
|
55
|
+
type: "list",
|
|
56
|
+
name: "action",
|
|
57
|
+
message: i18n.t("multi-config:selectAction"),
|
|
58
|
+
choices: addNumbersToChoices(choices)
|
|
59
|
+
}]);
|
|
60
|
+
if (!action || action === "skip") {
|
|
61
|
+
console.log(ansis.yellow(i18n.t("common:skip")));
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
switch (action) {
|
|
65
|
+
case "add":
|
|
66
|
+
await handleAddProfile();
|
|
67
|
+
break;
|
|
68
|
+
case "edit":
|
|
69
|
+
await handleEditProfile(profiles);
|
|
70
|
+
break;
|
|
71
|
+
case "delete":
|
|
72
|
+
await handleDeleteProfile(profiles);
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async function promptContinueAdding() {
|
|
77
|
+
const { continueAdding } = await inquirer.prompt([{
|
|
78
|
+
type: "confirm",
|
|
79
|
+
name: "continueAdding",
|
|
80
|
+
message: i18n.t("multi-config:addAnotherProfilePrompt"),
|
|
81
|
+
default: false
|
|
82
|
+
}]);
|
|
83
|
+
return continueAdding;
|
|
84
|
+
}
|
|
85
|
+
async function handleAddProfile() {
|
|
86
|
+
console.log(ansis.cyan(`
|
|
87
|
+
${i18n.t("multi-config:addingNewProfile")}`));
|
|
88
|
+
const answers = await inquirer.prompt([
|
|
89
|
+
{
|
|
90
|
+
type: "input",
|
|
91
|
+
name: "profileName",
|
|
92
|
+
message: i18n.t("multi-config:profileNamePrompt"),
|
|
93
|
+
validate: (input) => {
|
|
94
|
+
const trimmed = input.trim();
|
|
95
|
+
if (!trimmed) {
|
|
96
|
+
return i18n.t("multi-config:profileNameRequired");
|
|
97
|
+
}
|
|
98
|
+
if (!/^[\w\-\s\u4E00-\u9FA5]+$/.test(trimmed)) {
|
|
99
|
+
return i18n.t("multi-config:profileNameInvalid");
|
|
100
|
+
}
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
type: "list",
|
|
106
|
+
name: "authType",
|
|
107
|
+
message: i18n.t("multi-config:authTypePrompt"),
|
|
108
|
+
choices: [
|
|
109
|
+
{ name: i18n.t("multi-config:authType.api_key"), value: "api_key" },
|
|
110
|
+
{ name: i18n.t("multi-config:authType.auth_token"), value: "auth_token" }
|
|
111
|
+
],
|
|
112
|
+
default: "api_key"
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
type: "input",
|
|
116
|
+
name: "baseUrl",
|
|
117
|
+
message: i18n.t("multi-config:baseUrlPrompt"),
|
|
118
|
+
default: "https://api.anthropic.com",
|
|
119
|
+
when: (answers2) => answers2.authType !== "ccr_proxy",
|
|
120
|
+
validate: (input) => {
|
|
121
|
+
const trimmed = input.trim();
|
|
122
|
+
if (!trimmed) {
|
|
123
|
+
return i18n.t("multi-config:baseUrlRequired");
|
|
124
|
+
}
|
|
125
|
+
try {
|
|
126
|
+
new URL(trimmed);
|
|
127
|
+
return true;
|
|
128
|
+
} catch {
|
|
129
|
+
return i18n.t("multi-config:baseUrlInvalid");
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
type: "password",
|
|
135
|
+
name: "apiKey",
|
|
136
|
+
message: i18n.t("multi-config:apiKeyPrompt") + i18n.t("common:inputHidden"),
|
|
137
|
+
when: (answers2) => answers2.authType !== "ccr_proxy",
|
|
138
|
+
validate: (input) => {
|
|
139
|
+
const trimmed = input.trim();
|
|
140
|
+
if (!trimmed) {
|
|
141
|
+
return i18n.t("multi-config:apiKeyRequired");
|
|
142
|
+
}
|
|
143
|
+
const validation = validateApiKey(trimmed);
|
|
144
|
+
if (!validation.isValid) {
|
|
145
|
+
return validation.error || "Invalid API key format";
|
|
146
|
+
}
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
type: "confirm",
|
|
152
|
+
name: "setAsDefault",
|
|
153
|
+
message: i18n.t("multi-config:setAsDefaultPrompt"),
|
|
154
|
+
default: true
|
|
155
|
+
}
|
|
156
|
+
]);
|
|
157
|
+
const profileName = answers.profileName.trim();
|
|
158
|
+
const profileId = ClaudeCodeConfigManager.generateProfileId(profileName);
|
|
159
|
+
const profile = {
|
|
160
|
+
id: profileId,
|
|
161
|
+
name: profileName,
|
|
162
|
+
authType: answers.authType
|
|
163
|
+
};
|
|
164
|
+
if (answers.authType !== "ccr_proxy") {
|
|
165
|
+
profile.apiKey = answers.apiKey.trim();
|
|
166
|
+
profile.baseUrl = answers.baseUrl.trim();
|
|
167
|
+
}
|
|
168
|
+
const existingProfile = ClaudeCodeConfigManager.getProfileByName(profile.name);
|
|
169
|
+
if (existingProfile) {
|
|
170
|
+
const { overwrite } = await inquirer.prompt([{
|
|
171
|
+
type: "confirm",
|
|
172
|
+
name: "overwrite",
|
|
173
|
+
message: i18n.t("multi-config:profileDuplicatePrompt", {
|
|
174
|
+
name: profile.name,
|
|
175
|
+
source: i18n.t("multi-config:existingConfig")
|
|
176
|
+
}),
|
|
177
|
+
default: false
|
|
178
|
+
}]);
|
|
179
|
+
if (!overwrite) {
|
|
180
|
+
console.log(ansis.yellow(i18n.t("multi-config:profileDuplicateSkipped", { name: profile.name })));
|
|
181
|
+
const shouldContinue2 = await promptContinueAdding();
|
|
182
|
+
if (shouldContinue2) {
|
|
183
|
+
await handleAddProfile();
|
|
184
|
+
}
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const updateResult = await ClaudeCodeConfigManager.updateProfile(existingProfile.id, {
|
|
188
|
+
name: profile.name,
|
|
189
|
+
authType: profile.authType,
|
|
190
|
+
apiKey: profile.apiKey,
|
|
191
|
+
baseUrl: profile.baseUrl
|
|
192
|
+
});
|
|
193
|
+
if (updateResult.success) {
|
|
194
|
+
console.log(ansis.green(i18n.t("multi-config:profileUpdated", { name: profile.name })));
|
|
195
|
+
if (updateResult.backupPath) {
|
|
196
|
+
console.log(ansis.gray(i18n.t("common:backupCreated", { path: updateResult.backupPath })));
|
|
197
|
+
}
|
|
198
|
+
if (answers.setAsDefault) {
|
|
199
|
+
const switchResult = await ClaudeCodeConfigManager.switchProfile(existingProfile.id);
|
|
200
|
+
if (switchResult.success) {
|
|
201
|
+
console.log(ansis.green(i18n.t("multi-config:profileSetAsDefault", { name: profile.name })));
|
|
202
|
+
await ClaudeCodeConfigManager.applyProfileSettings({ ...profile, id: existingProfile.id });
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
} else {
|
|
206
|
+
console.log(ansis.red(i18n.t("multi-config:profileUpdateFailed", { error: updateResult.error || "" })));
|
|
207
|
+
}
|
|
208
|
+
} else {
|
|
209
|
+
const result = await ClaudeCodeConfigManager.addProfile(profile);
|
|
210
|
+
if (result.success) {
|
|
211
|
+
const runtimeProfile = result.addedProfile || { ...profile, id: profileId };
|
|
212
|
+
console.log(ansis.green(i18n.t("multi-config:profileAdded", { name: runtimeProfile.name })));
|
|
213
|
+
if (result.backupPath) {
|
|
214
|
+
console.log(ansis.gray(i18n.t("common:backupCreated", { path: result.backupPath })));
|
|
215
|
+
}
|
|
216
|
+
if (answers.setAsDefault) {
|
|
217
|
+
const switchResult = await ClaudeCodeConfigManager.switchProfile(runtimeProfile.id);
|
|
218
|
+
if (switchResult.success) {
|
|
219
|
+
console.log(ansis.green(i18n.t("multi-config:profileSetAsDefault", { name: runtimeProfile.name })));
|
|
220
|
+
await ClaudeCodeConfigManager.applyProfileSettings(runtimeProfile);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
} else {
|
|
224
|
+
console.log(ansis.red(i18n.t("multi-config:profileAddFailed", { error: result.error })));
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
const shouldContinue = await promptContinueAdding();
|
|
228
|
+
if (shouldContinue) {
|
|
229
|
+
await handleAddProfile();
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
async function handleEditProfile(profiles) {
|
|
233
|
+
const choices = profiles.map((profile) => ({
|
|
234
|
+
name: `${profile.name} (${getAuthTypeLabel(profile.authType)})`,
|
|
235
|
+
value: profile.id
|
|
236
|
+
}));
|
|
237
|
+
const { selectedProfileId } = await inquirer.prompt([{
|
|
238
|
+
type: "list",
|
|
239
|
+
name: "selectedProfileId",
|
|
240
|
+
message: i18n.t("multi-config:selectProfileToEdit"),
|
|
241
|
+
choices: addNumbersToChoices(choices)
|
|
242
|
+
}]);
|
|
243
|
+
if (!selectedProfileId) {
|
|
244
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
const selectedProfile = profiles.find((p) => p.id === selectedProfileId);
|
|
248
|
+
if (!selectedProfile) {
|
|
249
|
+
console.log(ansis.red(i18n.t("multi-config:profileNotFound")));
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
console.log(ansis.cyan(`
|
|
253
|
+
${i18n.t("multi-config:editingProfile", { name: selectedProfile.name })}`));
|
|
254
|
+
const answers = await inquirer.prompt([
|
|
255
|
+
{
|
|
256
|
+
type: "input",
|
|
257
|
+
name: "profileName",
|
|
258
|
+
message: i18n.t("multi-config:profileNamePrompt"),
|
|
259
|
+
default: selectedProfile.name,
|
|
260
|
+
validate: (input) => {
|
|
261
|
+
const trimmed = input.trim();
|
|
262
|
+
if (!trimmed) {
|
|
263
|
+
return i18n.t("multi-config:profileNameRequired");
|
|
264
|
+
}
|
|
265
|
+
if (!/^[\w\-\s\u4E00-\u9FA5]+$/.test(trimmed)) {
|
|
266
|
+
return i18n.t("multi-config:profileNameInvalid");
|
|
267
|
+
}
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
type: "input",
|
|
273
|
+
name: "baseUrl",
|
|
274
|
+
message: i18n.t("multi-config:baseUrlPrompt"),
|
|
275
|
+
default: selectedProfile.baseUrl || "https://api.anthropic.com",
|
|
276
|
+
when: () => selectedProfile.authType !== "ccr_proxy",
|
|
277
|
+
validate: (input) => {
|
|
278
|
+
const trimmed = input.trim();
|
|
279
|
+
if (!trimmed) {
|
|
280
|
+
return i18n.t("multi-config:baseUrlRequired");
|
|
281
|
+
}
|
|
282
|
+
try {
|
|
283
|
+
new URL(trimmed);
|
|
284
|
+
return true;
|
|
285
|
+
} catch {
|
|
286
|
+
return i18n.t("multi-config:baseUrlInvalid");
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
type: "password",
|
|
292
|
+
name: "apiKey",
|
|
293
|
+
message: i18n.t("multi-config:apiKeyPrompt") + i18n.t("common:inputHidden"),
|
|
294
|
+
default: selectedProfile.apiKey,
|
|
295
|
+
when: () => selectedProfile.authType !== "ccr_proxy",
|
|
296
|
+
validate: (input) => {
|
|
297
|
+
const trimmed = input.trim();
|
|
298
|
+
if (!trimmed) {
|
|
299
|
+
return i18n.t("multi-config:apiKeyRequired");
|
|
300
|
+
}
|
|
301
|
+
const validation = validateApiKey(trimmed);
|
|
302
|
+
if (!validation.isValid) {
|
|
303
|
+
return validation.error || "Invalid API key format";
|
|
304
|
+
}
|
|
305
|
+
return true;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
]);
|
|
309
|
+
const updateData = {
|
|
310
|
+
name: answers.profileName.trim()
|
|
311
|
+
};
|
|
312
|
+
if (selectedProfile.authType !== "ccr_proxy") {
|
|
313
|
+
updateData.apiKey = answers.apiKey.trim();
|
|
314
|
+
updateData.baseUrl = answers.baseUrl.trim();
|
|
315
|
+
}
|
|
316
|
+
const result = await ClaudeCodeConfigManager.updateProfile(selectedProfile.id, updateData);
|
|
317
|
+
if (result.success) {
|
|
318
|
+
console.log(ansis.green(i18n.t("multi-config:profileUpdated", { name: updateData.name })));
|
|
319
|
+
if (result.backupPath) {
|
|
320
|
+
console.log(ansis.gray(i18n.t("common:backupCreated", { path: result.backupPath })));
|
|
321
|
+
}
|
|
322
|
+
const currentConfig = ClaudeCodeConfigManager.readConfig();
|
|
323
|
+
if (currentConfig?.currentProfileId === selectedProfile.id) {
|
|
324
|
+
const updatedProfile = ClaudeCodeConfigManager.getProfileById(selectedProfile.id);
|
|
325
|
+
if (updatedProfile) {
|
|
326
|
+
await ClaudeCodeConfigManager.applyProfileSettings(updatedProfile);
|
|
327
|
+
console.log(ansis.green(i18n.t("multi-config:settingsApplied")));
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
} else {
|
|
331
|
+
console.log(ansis.red(i18n.t("multi-config:profileUpdateFailed", { error: result.error })));
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
async function handleDeleteProfile(profiles) {
|
|
335
|
+
if (profiles.length <= 1) {
|
|
336
|
+
console.log(ansis.yellow(i18n.t("multi-config:cannotDeleteLast")));
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
const choices = profiles.map((profile) => ({
|
|
340
|
+
name: `${profile.name} (${getAuthTypeLabel(profile.authType)})`,
|
|
341
|
+
value: profile.id
|
|
342
|
+
}));
|
|
343
|
+
const { selectedProfileIds } = await inquirer.prompt({
|
|
344
|
+
type: "checkbox",
|
|
345
|
+
name: "selectedProfileIds",
|
|
346
|
+
message: i18n.t("multi-config:selectProfilesToDelete"),
|
|
347
|
+
choices: addNumbersToChoices(choices),
|
|
348
|
+
validate: (input) => {
|
|
349
|
+
if (input.length === 0) {
|
|
350
|
+
return i18n.t("multi-config:selectAtLeastOne");
|
|
351
|
+
}
|
|
352
|
+
if (input.length >= profiles.length) {
|
|
353
|
+
return i18n.t("multi-config:cannotDeleteAll");
|
|
354
|
+
}
|
|
355
|
+
return true;
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
if (!selectedProfileIds || selectedProfileIds.length === 0) {
|
|
359
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
const selectedNames = selectedProfileIds.map(
|
|
363
|
+
(id) => profiles.find((p) => p.id === id)?.name || id
|
|
364
|
+
);
|
|
365
|
+
const { confirmed } = await inquirer.prompt([{
|
|
366
|
+
type: "confirm",
|
|
367
|
+
name: "confirmed",
|
|
368
|
+
message: i18n.t("multi-config:confirmDeleteProfiles", { providers: selectedNames.join(", ") }),
|
|
369
|
+
default: false
|
|
370
|
+
}]);
|
|
371
|
+
if (!confirmed) {
|
|
372
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
const result = await ClaudeCodeConfigManager.deleteProfiles(selectedProfileIds);
|
|
376
|
+
if (result.success) {
|
|
377
|
+
console.log(ansis.green(i18n.t("multi-config:profilesDeleted", { count: selectedProfileIds.length })));
|
|
378
|
+
if (result.backupPath) {
|
|
379
|
+
console.log(ansis.gray(i18n.t("common:backupCreated", { path: result.backupPath })));
|
|
380
|
+
}
|
|
381
|
+
if (result.newCurrentProfileId) {
|
|
382
|
+
const newProfile = ClaudeCodeConfigManager.getProfileById(result.newCurrentProfileId);
|
|
383
|
+
if (newProfile) {
|
|
384
|
+
console.log(ansis.cyan(i18n.t("multi-config:newDefaultProfile", { profile: newProfile.name })));
|
|
385
|
+
await ClaudeCodeConfigManager.applyProfileSettings(newProfile);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
} else {
|
|
389
|
+
console.log(ansis.red(i18n.t("multi-config:profilesDeleteFailed", { error: result.error })));
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
export { configureIncrementalManagement };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import ansis from 'ansis';
|
|
2
2
|
import inquirer from 'inquirer';
|
|
3
|
-
import {
|
|
3
|
+
import { a2 as ensureI18nInitialized, ad as detectConfigManagementMode, a3 as i18n, a4 as addNumbersToChoices } from './simple-config.mjs';
|
|
4
|
+
import { deleteProviders, editExistingProvider, addProviderToExisting } from './codex-provider-manager.mjs';
|
|
4
5
|
import 'node:fs';
|
|
5
6
|
import 'node:process';
|
|
6
7
|
import 'node:child_process';
|
|
@@ -17,179 +18,6 @@ import 'node:fs/promises';
|
|
|
17
18
|
import 'i18next';
|
|
18
19
|
import 'i18next-fs-backend';
|
|
19
20
|
|
|
20
|
-
const ERROR_MESSAGES = {
|
|
21
|
-
NO_CONFIG: "No existing configuration found",
|
|
22
|
-
BACKUP_FAILED: "Failed to create backup",
|
|
23
|
-
PROVIDER_EXISTS: (id) => `Provider with ID "${id}" already exists`,
|
|
24
|
-
PROVIDER_NOT_FOUND: (id) => `Provider with ID "${id}" not found`,
|
|
25
|
-
NO_PROVIDERS_SPECIFIED: "No providers specified for deletion",
|
|
26
|
-
PROVIDERS_NOT_FOUND: (providers) => `Some providers not found: ${providers.join(", ")}`,
|
|
27
|
-
CANNOT_DELETE_ALL: "Cannot delete all providers. At least one provider must remain."
|
|
28
|
-
};
|
|
29
|
-
async function addProviderToExisting(provider, apiKey) {
|
|
30
|
-
try {
|
|
31
|
-
const existingConfig = readCodexConfig();
|
|
32
|
-
if (!existingConfig) {
|
|
33
|
-
return {
|
|
34
|
-
success: false,
|
|
35
|
-
error: ERROR_MESSAGES.NO_CONFIG
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
const existingProvider = existingConfig.providers.find((p) => p.id === provider.id);
|
|
39
|
-
if (existingProvider) {
|
|
40
|
-
return {
|
|
41
|
-
success: false,
|
|
42
|
-
error: ERROR_MESSAGES.PROVIDER_EXISTS(provider.id)
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
const backupPath = backupCodexComplete();
|
|
46
|
-
if (!backupPath) {
|
|
47
|
-
return {
|
|
48
|
-
success: false,
|
|
49
|
-
error: ERROR_MESSAGES.BACKUP_FAILED
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
const updatedConfig = {
|
|
53
|
-
...existingConfig,
|
|
54
|
-
providers: [...existingConfig.providers, provider]
|
|
55
|
-
};
|
|
56
|
-
writeCodexConfig(updatedConfig);
|
|
57
|
-
const authEntries = {};
|
|
58
|
-
authEntries[provider.envKey] = 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 : "Unknown error"
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
async function editExistingProvider(providerId, updates) {
|
|
73
|
-
try {
|
|
74
|
-
const existingConfig = readCodexConfig();
|
|
75
|
-
if (!existingConfig) {
|
|
76
|
-
return {
|
|
77
|
-
success: false,
|
|
78
|
-
error: ERROR_MESSAGES.NO_CONFIG
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
const providerIndex = existingConfig.providers.findIndex((p) => p.id === providerId);
|
|
82
|
-
if (providerIndex === -1) {
|
|
83
|
-
return {
|
|
84
|
-
success: false,
|
|
85
|
-
error: ERROR_MESSAGES.PROVIDER_NOT_FOUND(providerId)
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
const backupPath = backupCodexComplete();
|
|
89
|
-
if (!backupPath) {
|
|
90
|
-
return {
|
|
91
|
-
success: false,
|
|
92
|
-
error: ERROR_MESSAGES.BACKUP_FAILED
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
const updatedProvider = {
|
|
96
|
-
...existingConfig.providers[providerIndex],
|
|
97
|
-
...updates.name && { name: updates.name },
|
|
98
|
-
...updates.baseUrl && { baseUrl: updates.baseUrl },
|
|
99
|
-
...updates.wireApi && { wireApi: updates.wireApi }
|
|
100
|
-
};
|
|
101
|
-
const updatedProviders = [...existingConfig.providers];
|
|
102
|
-
updatedProviders[providerIndex] = updatedProvider;
|
|
103
|
-
const updatedConfig = {
|
|
104
|
-
...existingConfig,
|
|
105
|
-
providers: updatedProviders
|
|
106
|
-
};
|
|
107
|
-
writeCodexConfig(updatedConfig);
|
|
108
|
-
if (updates.apiKey) {
|
|
109
|
-
const authEntries = {};
|
|
110
|
-
authEntries[updatedProvider.envKey] = updates.apiKey;
|
|
111
|
-
writeAuthFile(authEntries);
|
|
112
|
-
}
|
|
113
|
-
return {
|
|
114
|
-
success: true,
|
|
115
|
-
backupPath,
|
|
116
|
-
updatedProvider
|
|
117
|
-
};
|
|
118
|
-
} catch (error) {
|
|
119
|
-
return {
|
|
120
|
-
success: false,
|
|
121
|
-
error: error instanceof Error ? error.message : "Unknown error"
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
async function deleteProviders(providerIds) {
|
|
126
|
-
try {
|
|
127
|
-
const existingConfig = readCodexConfig();
|
|
128
|
-
if (!existingConfig) {
|
|
129
|
-
return {
|
|
130
|
-
success: false,
|
|
131
|
-
error: ERROR_MESSAGES.NO_CONFIG
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
if (!providerIds || providerIds.length === 0) {
|
|
135
|
-
return {
|
|
136
|
-
success: false,
|
|
137
|
-
error: ERROR_MESSAGES.NO_PROVIDERS_SPECIFIED
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
const notFoundProviders = providerIds.filter(
|
|
141
|
-
(id) => !existingConfig.providers.some((p) => p.id === id)
|
|
142
|
-
);
|
|
143
|
-
if (notFoundProviders.length > 0) {
|
|
144
|
-
return {
|
|
145
|
-
success: false,
|
|
146
|
-
error: ERROR_MESSAGES.PROVIDERS_NOT_FOUND(notFoundProviders)
|
|
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: ERROR_MESSAGES.CANNOT_DELETE_ALL
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
const backupPath = backupCodexComplete();
|
|
159
|
-
if (!backupPath) {
|
|
160
|
-
return {
|
|
161
|
-
success: false,
|
|
162
|
-
error: ERROR_MESSAGES.BACKUP_FAILED
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
let newDefaultProvider = existingConfig.modelProvider;
|
|
166
|
-
if (providerIds.includes(existingConfig.modelProvider || "")) {
|
|
167
|
-
newDefaultProvider = remainingProviders[0].id;
|
|
168
|
-
}
|
|
169
|
-
const updatedConfig = {
|
|
170
|
-
...existingConfig,
|
|
171
|
-
modelProvider: newDefaultProvider,
|
|
172
|
-
providers: remainingProviders
|
|
173
|
-
};
|
|
174
|
-
writeCodexConfig(updatedConfig);
|
|
175
|
-
const result = {
|
|
176
|
-
success: true,
|
|
177
|
-
backupPath,
|
|
178
|
-
deletedProviders: providerIds,
|
|
179
|
-
remainingProviders
|
|
180
|
-
};
|
|
181
|
-
if (newDefaultProvider !== existingConfig.modelProvider) {
|
|
182
|
-
result.newDefaultProvider = newDefaultProvider || void 0;
|
|
183
|
-
}
|
|
184
|
-
return result;
|
|
185
|
-
} catch (error) {
|
|
186
|
-
return {
|
|
187
|
-
success: false,
|
|
188
|
-
error: error instanceof Error ? error.message : "Unknown error"
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
21
|
async function configureIncrementalManagement() {
|
|
194
22
|
ensureI18nInitialized();
|
|
195
23
|
const managementMode = detectConfigManagementMode();
|