zcf 3.3.0 → 3.3.2
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 +37 -2
- package/dist/chunks/api-providers.mjs +18 -5
- package/dist/chunks/claude-code-config-manager.mjs +7 -7
- package/dist/chunks/claude-code-incremental-manager.mjs +164 -1
- package/dist/chunks/codex-config-switch.mjs +130 -4
- package/dist/chunks/codex-provider-manager.mjs +3 -2
- package/dist/chunks/codex-uninstaller.mjs +19 -24
- package/dist/chunks/commands.mjs +1 -1
- package/dist/chunks/features.mjs +13 -13
- package/dist/chunks/simple-config.mjs +12 -12
- package/dist/cli.mjs +3 -3
- package/dist/i18n/locales/en/codex.json +7 -0
- package/dist/i18n/locales/en/multi-config.json +6 -0
- package/dist/i18n/locales/zh-CN/codex.json +7 -0
- package/dist/i18n/locales/zh-CN/multi-config.json +6 -0
- package/dist/index.d.mts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.mjs +1 -1
- package/package.json +9 -3
- package/templates/CLAUDE.md +1 -0
- package/templates/claude-code/CLAUDE.md +1 -0
package/README.md
CHANGED
|
@@ -27,6 +27,15 @@
|
|
|
27
27
|
[](https://share.302.ai/gAT9VG)
|
|
28
28
|
[302.AI](https://share.302.ai/gAT9VG) is a pay-as-you-go enterprise AI resource hub that offers the latest and most comprehensive AI models and APIs on the market, along with a variety of ready-to-use online AI applications.
|
|
29
29
|
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
<table>
|
|
33
|
+
<tr>
|
|
34
|
+
<td width="180"><a href="https://www.packyapi.com/register?aff=zcf"><img src="./src/assets/packycode.png" alt="PackyCode" width="150"></a></td>
|
|
35
|
+
<td>Thanks to PackyCode for sponsoring this project! PackyCode is a reliable and efficient API relay service provider, offering relay services for Claude Code, Codex, Gemini, and more. PackyCode provides special discounts for our software users: register using <a href="https://www.packyapi.com/register?aff=zcf">this link</a> and enter the "zcf" promo code during recharge to get 10% off.</td>
|
|
36
|
+
</tr>
|
|
37
|
+
</table>
|
|
38
|
+
|
|
30
39
|
## 🚀 Quick Start
|
|
31
40
|
|
|
32
41
|
### 🎯 Recommended: Use Interactive Menu (v2.0 New)
|
|
@@ -130,6 +139,22 @@ npx zcf i --skip-prompt \
|
|
|
130
139
|
--api-url "https://xxx.xxx" \
|
|
131
140
|
--api-model "claude-sonnet-4-5" \
|
|
132
141
|
--api-fast-model "claude-haiku-4-5"
|
|
142
|
+
|
|
143
|
+
# Multiple API configurations (JSON string)
|
|
144
|
+
npx zcf i -s --api-configs '[
|
|
145
|
+
{"provider":"302ai","key":"sk-xxx"},
|
|
146
|
+
{"provider":"glm","key":"sk-yyy"},
|
|
147
|
+
{"name":"custom","type":"api_key","key":"sk-zzz","url":"https://custom.api.com","primaryModel":"claude-sonnet-4-5","fastModel":"claude-haiku-4-5","default":true}
|
|
148
|
+
]'
|
|
149
|
+
|
|
150
|
+
# Multiple API configurations (JSON file)
|
|
151
|
+
npx zcf i -s --api-configs-file ./api-configs.json
|
|
152
|
+
|
|
153
|
+
# For Codex with multiple providers
|
|
154
|
+
npx zcf i -s -T cx --api-configs '[
|
|
155
|
+
{"provider":"302ai","key":"sk-xxx"},
|
|
156
|
+
{"name":"custom","type":"api_key","key":"sk-yyy","url":"https://custom.api.com","primaryModel":"gpt-5","default":true}
|
|
157
|
+
]'
|
|
133
158
|
```
|
|
134
159
|
|
|
135
160
|
#### 🎯 API Provider Presets (v3.3.0+ New)
|
|
@@ -138,6 +163,7 @@ ZCF now supports API provider presets that automatically configure baseUrl and m
|
|
|
138
163
|
|
|
139
164
|
**Supported Providers:**
|
|
140
165
|
- `302ai` - [302.AI](https://share.302.ai/gAT9VG) API Service
|
|
166
|
+
- `packycode` - [PackyCode](https://www.packyapi.com/register?aff=zcf) API Service
|
|
141
167
|
- `glm` - GLM (z.ai)
|
|
142
168
|
- `minimax` - MiniMax API Service
|
|
143
169
|
- `kimi` - Kimi (Moonshot AI)
|
|
@@ -151,6 +177,9 @@ npx zcf i --skip-prompt --provider 302ai --api-key "sk-xxx"
|
|
|
151
177
|
# or shorthand
|
|
152
178
|
npx zcf i -s -p 302ai -k "sk-xxx"
|
|
153
179
|
|
|
180
|
+
# Using PackyCode provider
|
|
181
|
+
npx zcf i -s -p packycode -k "sk-xxx"
|
|
182
|
+
|
|
154
183
|
# Using GLM provider
|
|
155
184
|
npx zcf i -s -p glm -k "sk-xxx"
|
|
156
185
|
|
|
@@ -181,7 +210,7 @@ When using `--skip-prompt`, the following parameters are available:
|
|
|
181
210
|
| Parameter | Description | Values | Required | Default |
|
|
182
211
|
| ---------------------------- | -------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
|
183
212
|
| `--skip-prompt, -s` | Skip all interactive prompts | - | Yes (for non-interactive mode) | - |
|
|
184
|
-
| `--provider, -p` | API provider preset (v3.3.0+ New) | `302ai`, `glm`, `minimax`, `kimi`, `custom`
|
|
213
|
+
| `--provider, -p` | API provider preset (v3.3.0+ New) | `302ai`, `packycode`, `glm`, `minimax`, `kimi`, `custom` | No | - (Simplifies configuration by auto-filling baseUrl and models) |
|
|
185
214
|
| `--lang, -l` | ZCF display language (applies to all commands) | `zh-CN`, `en` | No | `en` or user's saved preference |
|
|
186
215
|
| `--config-lang, -c` | Configuration language (template files language) | `zh-CN`, `en` | No | `en` |
|
|
187
216
|
| `--ai-output-lang, -a` | AI output language | `zh-CN`, `en`, custom string | No | `en` |
|
|
@@ -197,6 +226,9 @@ When using `--skip-prompt`, the following parameters are available:
|
|
|
197
226
|
| `--output-styles, -o` | Output styles to install (multi-select, comma-separated) | `engineer-professional`, `nekomata-engineer`, `laowang-engineer`, `ojousama-engineer`, or `skip` for none | No | `all` |
|
|
198
227
|
| `--default-output-style, -d` | Default output style | Same as output styles plus built-in: `default`, `explanatory`, `learning` | No | `engineer-professional` |
|
|
199
228
|
| `--install-cometix-line, -x` | Install CCometixLine statusline tool | `true`, `false` | No | `true` |
|
|
229
|
+
| `--code-type, -T` | Target code tool type | `claude-code`, `codex`, `cc`, `cx` | No | Current active tool type from ZCF config |
|
|
230
|
+
| `--api-configs` | Multiple API configurations (JSON string) | JSON array string of API configuration objects | No | - (Mutually exclusive with `--api-configs-file`) |
|
|
231
|
+
| `--api-configs-file` | Multiple API configurations (JSON file path) | Path to JSON file containing API configuration array | No | - (Mutually exclusive with `--api-configs`) |
|
|
200
232
|
|
|
201
233
|
#### 🤖 Codex Support (v3.0.0+ New)
|
|
202
234
|
|
|
@@ -270,7 +302,7 @@ ZCF now supports customizable AI output styles to personalize your Claude Code e
|
|
|
270
302
|
|
|
271
303
|
<p align="center">
|
|
272
304
|
<a href="https://github.com/Haleclipse">
|
|
273
|
-
<img src="./src/assets/Haleclipse.
|
|
305
|
+
<img src="./src/assets/Haleclipse.webp" alt="Halley-chan" width="200"/>
|
|
274
306
|
</a>
|
|
275
307
|
<div align="center">Tsundere <a href="https://github.com/Haleclipse">Halley-chan</a> Ojou-sama ( ̄▽ ̄)ゞ</div>
|
|
276
308
|
</p>
|
|
@@ -454,6 +486,7 @@ ZCF provides flexible API configuration options for both Claude Code and Codex:
|
|
|
454
486
|
|
|
455
487
|
Choose from popular API providers with pre-configured settings:
|
|
456
488
|
- **302.AI** - Pay-as-you-go AI service with comprehensive model support
|
|
489
|
+
- **PackyCode** - PackyCode API Service
|
|
457
490
|
- **GLM (智谱AI)** - Zhipu AI's GLM models
|
|
458
491
|
- **MiniMax** - MiniMax AI service
|
|
459
492
|
- **Kimi (Moonshot AI)** - Moonshot's Kimi models
|
|
@@ -911,6 +944,7 @@ If you find this project helpful, please consider sponsoring its development. Yo
|
|
|
911
944
|
|
|
912
945
|
A huge thank you to all our sponsors for their generous support!
|
|
913
946
|
- [302.AI](https://share.302.ai/gAT9VG) (first corporate sponsorship 🤠)
|
|
947
|
+
- [PackyCode](https://www.packyapi.com/register?aff=zcf) (first API proxy service sponsor 🧝🏻♀️)
|
|
914
948
|
- Tc (first sponsor)
|
|
915
949
|
- Argolinhas (first ko-fi sponsor ٩(•̤̀ᵕ•̤́๑))
|
|
916
950
|
- r\*r (first anonymous sponsor 🤣)
|
|
@@ -920,6 +954,7 @@ A huge thank you to all our sponsors for their generous support!
|
|
|
920
954
|
- [chamo101](https://github.com/chamo101) (first GitHub issue sponsor 🎉)
|
|
921
955
|
- 初屿贤 (first Codex user sponsor 🙅🏻♂️)
|
|
922
956
|
- Protein (first 1688 sponsor 😏)
|
|
957
|
+
- [musistudio](https://github.com/musistudio) (first open source project author sponsor, the author of [CCR](https://github.com/musistudio/claude-code-router) 🤩)
|
|
923
958
|
- [BeatSeat](https://github.com/BeatSeat) (community expert 😎, provided $1000 Claude credits)
|
|
924
959
|
- [wenwen](https://github.com/wenwen12345) (community expert 🤓, provided daily $100 Claude&GPT credits)
|
|
925
960
|
- 16°C coffee (My best friend 🤪, offered ChatGPT Pro $200 package)
|
|
@@ -13,6 +13,20 @@ const API_PROVIDER_PRESETS = [
|
|
|
13
13
|
},
|
|
14
14
|
description: "302.AI API Service"
|
|
15
15
|
},
|
|
16
|
+
{
|
|
17
|
+
id: "packycode",
|
|
18
|
+
name: "PackyCode",
|
|
19
|
+
supportedCodeTools: ["claude-code", "codex"],
|
|
20
|
+
claudeCode: {
|
|
21
|
+
baseUrl: "https://www.packyapi.com",
|
|
22
|
+
authType: "auth_token"
|
|
23
|
+
},
|
|
24
|
+
codex: {
|
|
25
|
+
baseUrl: "https://www.packyapi.com/v1",
|
|
26
|
+
wireApi: "responses"
|
|
27
|
+
},
|
|
28
|
+
description: "PackyCode API Service"
|
|
29
|
+
},
|
|
16
30
|
{
|
|
17
31
|
id: "glm",
|
|
18
32
|
name: "GLM",
|
|
@@ -49,14 +63,13 @@ const API_PROVIDER_PRESETS = [
|
|
|
49
63
|
name: "Kimi",
|
|
50
64
|
supportedCodeTools: ["claude-code", "codex"],
|
|
51
65
|
claudeCode: {
|
|
52
|
-
baseUrl: "https://api.
|
|
53
|
-
authType: "auth_token"
|
|
54
|
-
defaultModels: ["kimi-k2-0905-preview", "kimi-k2-turbo-preview"]
|
|
66
|
+
baseUrl: "https://api.kimi.com/coding/",
|
|
67
|
+
authType: "auth_token"
|
|
55
68
|
},
|
|
56
69
|
codex: {
|
|
57
|
-
baseUrl: "https://api.
|
|
70
|
+
baseUrl: "https://api.kimi.com/coding/v1",
|
|
58
71
|
wireApi: "chat",
|
|
59
|
-
defaultModel: "kimi-
|
|
72
|
+
defaultModel: "kimi-for-coding"
|
|
60
73
|
},
|
|
61
74
|
description: "Kimi (Moonshot AI)"
|
|
62
75
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import dayjs from 'dayjs';
|
|
2
2
|
import { join } from 'pathe';
|
|
3
|
-
import {
|
|
3
|
+
import { q as ZCF_CONFIG_FILE, Z as ZCF_CONFIG_DIR, ae as ensureDir, af as readDefaultTomlConfig, ag as createDefaultTomlConfig, ah as exists, ai as readJsonConfig, aj as writeTomlConfig, S as SETTINGS_FILE, ak as copyFile } from './simple-config.mjs';
|
|
4
4
|
import 'node:fs';
|
|
5
5
|
import 'node:process';
|
|
6
6
|
import 'ansis';
|
|
@@ -182,15 +182,15 @@ class ClaudeCodeConfigManager {
|
|
|
182
182
|
* Apply profile settings to Claude Code runtime
|
|
183
183
|
*/
|
|
184
184
|
static async applyProfileSettings(profile) {
|
|
185
|
-
const { ensureI18nInitialized, i18n } = await import('./simple-config.mjs').then(function (n) { return n.
|
|
185
|
+
const { ensureI18nInitialized, i18n } = await import('./simple-config.mjs').then(function (n) { return n.b4; });
|
|
186
186
|
ensureI18nInitialized();
|
|
187
187
|
try {
|
|
188
188
|
if (!profile) {
|
|
189
|
-
const { switchToOfficialLogin } = await import('./simple-config.mjs').then(function (n) { return n.
|
|
189
|
+
const { switchToOfficialLogin } = await import('./simple-config.mjs').then(function (n) { return n.b8; });
|
|
190
190
|
switchToOfficialLogin();
|
|
191
191
|
return;
|
|
192
192
|
}
|
|
193
|
-
const { readJsonConfig: readJsonConfig2, writeJsonConfig } = await import('./simple-config.mjs').then(function (n) { return n.
|
|
193
|
+
const { readJsonConfig: readJsonConfig2, writeJsonConfig } = await import('./simple-config.mjs').then(function (n) { return n.b6; });
|
|
194
194
|
const settings = readJsonConfig2(SETTINGS_FILE) || {};
|
|
195
195
|
if (!settings.env)
|
|
196
196
|
settings.env = {};
|
|
@@ -202,7 +202,7 @@ class ClaudeCodeConfigManager {
|
|
|
202
202
|
settings.env.ANTHROPIC_AUTH_TOKEN = profile.apiKey;
|
|
203
203
|
delete settings.env.ANTHROPIC_API_KEY;
|
|
204
204
|
} else if (profile.authType === "ccr_proxy") {
|
|
205
|
-
const { readCcrConfig } = await import('./simple-config.mjs').then(function (n) { return n.
|
|
205
|
+
const { readCcrConfig } = await import('./simple-config.mjs').then(function (n) { return n.b9; });
|
|
206
206
|
const ccrConfig = readCcrConfig();
|
|
207
207
|
if (!ccrConfig) {
|
|
208
208
|
throw new Error(i18n.t("ccr:ccrNotConfigured") || "CCR proxy configuration not found");
|
|
@@ -232,7 +232,7 @@ class ClaudeCodeConfigManager {
|
|
|
232
232
|
delete settings.env.ANTHROPIC_SMALL_FAST_MODEL;
|
|
233
233
|
}
|
|
234
234
|
writeJsonConfig(SETTINGS_FILE, settings);
|
|
235
|
-
const { setPrimaryApiKey, addCompletedOnboarding } = await import('./simple-config.mjs').then(function (n) { return n.
|
|
235
|
+
const { setPrimaryApiKey, addCompletedOnboarding } = await import('./simple-config.mjs').then(function (n) { return n.b7; });
|
|
236
236
|
setPrimaryApiKey();
|
|
237
237
|
addCompletedOnboarding();
|
|
238
238
|
if (shouldRestartCcr) {
|
|
@@ -589,7 +589,7 @@ class ClaudeCodeConfigManager {
|
|
|
589
589
|
*/
|
|
590
590
|
static async syncCcrProfile() {
|
|
591
591
|
try {
|
|
592
|
-
const { readCcrConfig } = await import('./simple-config.mjs').then(function (n) { return n.
|
|
592
|
+
const { readCcrConfig } = await import('./simple-config.mjs').then(function (n) { return n.b9; });
|
|
593
593
|
const ccrConfig = readCcrConfig();
|
|
594
594
|
if (!ccrConfig) {
|
|
595
595
|
await this.ensureCcrProfileExists(ccrConfig);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import ansis from 'ansis';
|
|
2
2
|
import inquirer from 'inquirer';
|
|
3
|
-
import {
|
|
3
|
+
import { aa as ensureI18nInitialized, ab as i18n, ac as addNumbersToChoices, ad as validateApiKey } from './simple-config.mjs';
|
|
4
4
|
import { ClaudeCodeConfigManager } from './claude-code-config-manager.mjs';
|
|
5
5
|
import 'node:fs';
|
|
6
6
|
import 'node:process';
|
|
@@ -48,6 +48,7 @@ async function configureIncrementalManagement() {
|
|
|
48
48
|
const choices = [
|
|
49
49
|
{ name: i18n.t("multi-config:addProfile"), value: "add" },
|
|
50
50
|
{ name: i18n.t("multi-config:editProfile"), value: "edit" },
|
|
51
|
+
{ name: i18n.t("multi-config:copyProfile"), value: "copy" },
|
|
51
52
|
{ name: i18n.t("multi-config:deleteProfile"), value: "delete" },
|
|
52
53
|
{ name: i18n.t("common:skip"), value: "skip" }
|
|
53
54
|
];
|
|
@@ -68,6 +69,9 @@ async function configureIncrementalManagement() {
|
|
|
68
69
|
case "edit":
|
|
69
70
|
await handleEditProfile(profiles);
|
|
70
71
|
break;
|
|
72
|
+
case "copy":
|
|
73
|
+
await handleCopyProfile(profiles);
|
|
74
|
+
break;
|
|
71
75
|
case "delete":
|
|
72
76
|
await handleDeleteProfile(profiles);
|
|
73
77
|
break;
|
|
@@ -99,11 +103,13 @@ ${i18n.t("multi-config:addingNewProfile")}`));
|
|
|
99
103
|
}]);
|
|
100
104
|
let prefilledBaseUrl;
|
|
101
105
|
let prefilledAuthType;
|
|
106
|
+
let prefilledDefaultModels;
|
|
102
107
|
if (selectedProvider !== "custom") {
|
|
103
108
|
const provider = providers.find((p) => p.id === selectedProvider);
|
|
104
109
|
if (provider?.claudeCode) {
|
|
105
110
|
prefilledBaseUrl = provider.claudeCode.baseUrl;
|
|
106
111
|
prefilledAuthType = provider.claudeCode.authType;
|
|
112
|
+
prefilledDefaultModels = provider.claudeCode.defaultModels;
|
|
107
113
|
console.log(ansis.gray(i18n.t("api:providerSelected", { name: provider.name })));
|
|
108
114
|
}
|
|
109
115
|
}
|
|
@@ -204,6 +210,13 @@ ${i18n.t("multi-config:addingNewProfile")}`));
|
|
|
204
210
|
if (modelConfig.fastModel.trim()) {
|
|
205
211
|
profile.fastModel = modelConfig.fastModel.trim();
|
|
206
212
|
}
|
|
213
|
+
} else if (prefilledDefaultModels?.length) {
|
|
214
|
+
if (prefilledDefaultModels[0]?.trim()) {
|
|
215
|
+
profile.primaryModel = prefilledDefaultModels[0].trim();
|
|
216
|
+
}
|
|
217
|
+
if (prefilledDefaultModels[1]?.trim()) {
|
|
218
|
+
profile.fastModel = prefilledDefaultModels[1].trim();
|
|
219
|
+
}
|
|
207
220
|
}
|
|
208
221
|
const existingProfile = ClaudeCodeConfigManager.getProfileByName(profile.name);
|
|
209
222
|
if (existingProfile) {
|
|
@@ -348,12 +361,28 @@ ${i18n.t("multi-config:editingProfile", { name: selectedProfile.name })}`));
|
|
|
348
361
|
}
|
|
349
362
|
}
|
|
350
363
|
]);
|
|
364
|
+
let modelConfig = null;
|
|
365
|
+
if (selectedProfile.authType !== "ccr_proxy") {
|
|
366
|
+
const { promptCustomModels } = await import('./features.mjs');
|
|
367
|
+
modelConfig = await promptCustomModels(
|
|
368
|
+
selectedProfile.primaryModel,
|
|
369
|
+
selectedProfile.fastModel
|
|
370
|
+
);
|
|
371
|
+
}
|
|
351
372
|
const updateData = {
|
|
352
373
|
name: answers.profileName.trim()
|
|
353
374
|
};
|
|
354
375
|
if (selectedProfile.authType !== "ccr_proxy") {
|
|
355
376
|
updateData.apiKey = answers.apiKey.trim();
|
|
356
377
|
updateData.baseUrl = answers.baseUrl.trim();
|
|
378
|
+
if (modelConfig) {
|
|
379
|
+
if (modelConfig.primaryModel.trim()) {
|
|
380
|
+
updateData.primaryModel = modelConfig.primaryModel.trim();
|
|
381
|
+
}
|
|
382
|
+
if (modelConfig.fastModel.trim()) {
|
|
383
|
+
updateData.fastModel = modelConfig.fastModel.trim();
|
|
384
|
+
}
|
|
385
|
+
}
|
|
357
386
|
}
|
|
358
387
|
const result = await ClaudeCodeConfigManager.updateProfile(selectedProfile.id, updateData);
|
|
359
388
|
if (result.success) {
|
|
@@ -373,6 +402,140 @@ ${i18n.t("multi-config:editingProfile", { name: selectedProfile.name })}`));
|
|
|
373
402
|
console.log(ansis.red(i18n.t("multi-config:profileUpdateFailed", { error: result.error })));
|
|
374
403
|
}
|
|
375
404
|
}
|
|
405
|
+
async function handleCopyProfile(profiles) {
|
|
406
|
+
const choices = profiles.map((profile) => ({
|
|
407
|
+
name: `${profile.name} (${getAuthTypeLabel(profile.authType)})`,
|
|
408
|
+
value: profile.id
|
|
409
|
+
}));
|
|
410
|
+
const { selectedProfileId } = await inquirer.prompt([{
|
|
411
|
+
type: "list",
|
|
412
|
+
name: "selectedProfileId",
|
|
413
|
+
message: i18n.t("multi-config:selectProfileToCopy"),
|
|
414
|
+
choices: addNumbersToChoices(choices)
|
|
415
|
+
}]);
|
|
416
|
+
if (!selectedProfileId) {
|
|
417
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
const selectedProfile = profiles.find((p) => p.id === selectedProfileId);
|
|
421
|
+
if (!selectedProfile) {
|
|
422
|
+
console.log(ansis.red(i18n.t("multi-config:profileNotFound")));
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
console.log(ansis.cyan(`
|
|
426
|
+
${i18n.t("multi-config:copyingProfile", { name: selectedProfile.name })}`));
|
|
427
|
+
const copiedName = `${selectedProfile.name}-copy`;
|
|
428
|
+
const questions = [
|
|
429
|
+
{
|
|
430
|
+
type: "input",
|
|
431
|
+
name: "profileName",
|
|
432
|
+
message: i18n.t("multi-config:profileNamePrompt"),
|
|
433
|
+
default: copiedName,
|
|
434
|
+
validate: (input) => {
|
|
435
|
+
const trimmed = input.trim();
|
|
436
|
+
if (!trimmed) {
|
|
437
|
+
return i18n.t("multi-config:profileNameRequired");
|
|
438
|
+
}
|
|
439
|
+
if (!/^[\w\-\s.\u4E00-\u9FA5]+$/.test(trimmed)) {
|
|
440
|
+
return i18n.t("multi-config:profileNameInvalid");
|
|
441
|
+
}
|
|
442
|
+
return true;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
];
|
|
446
|
+
if (selectedProfile.authType !== "ccr_proxy") {
|
|
447
|
+
questions.push(
|
|
448
|
+
{
|
|
449
|
+
type: "input",
|
|
450
|
+
name: "baseUrl",
|
|
451
|
+
message: i18n.t("multi-config:baseUrlPrompt"),
|
|
452
|
+
default: selectedProfile.baseUrl || "https://api.anthropic.com",
|
|
453
|
+
validate: (input) => {
|
|
454
|
+
const trimmed = input.trim();
|
|
455
|
+
if (!trimmed) {
|
|
456
|
+
return i18n.t("multi-config:baseUrlRequired");
|
|
457
|
+
}
|
|
458
|
+
try {
|
|
459
|
+
new URL(trimmed);
|
|
460
|
+
return true;
|
|
461
|
+
} catch {
|
|
462
|
+
return i18n.t("multi-config:baseUrlInvalid");
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
type: "input",
|
|
468
|
+
name: "apiKey",
|
|
469
|
+
message: i18n.t("multi-config:apiKeyPrompt"),
|
|
470
|
+
default: selectedProfile.apiKey,
|
|
471
|
+
validate: (input) => {
|
|
472
|
+
const trimmed = input.trim();
|
|
473
|
+
if (!trimmed) {
|
|
474
|
+
return i18n.t("multi-config:apiKeyRequired");
|
|
475
|
+
}
|
|
476
|
+
const validation = validateApiKey(trimmed);
|
|
477
|
+
if (!validation.isValid) {
|
|
478
|
+
return validation.error || "Invalid API key format";
|
|
479
|
+
}
|
|
480
|
+
return true;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
const answers = await inquirer.prompt(questions);
|
|
486
|
+
let modelConfig = null;
|
|
487
|
+
if (selectedProfile.authType !== "ccr_proxy") {
|
|
488
|
+
const { promptCustomModels } = await import('./features.mjs');
|
|
489
|
+
modelConfig = await promptCustomModels(
|
|
490
|
+
selectedProfile.primaryModel,
|
|
491
|
+
selectedProfile.fastModel
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
const { setAsDefault } = await inquirer.prompt([
|
|
495
|
+
{
|
|
496
|
+
type: "confirm",
|
|
497
|
+
name: "setAsDefault",
|
|
498
|
+
message: i18n.t("multi-config:setAsDefaultPrompt"),
|
|
499
|
+
default: false
|
|
500
|
+
}
|
|
501
|
+
]);
|
|
502
|
+
const profileName = answers.profileName.trim();
|
|
503
|
+
const profileId = ClaudeCodeConfigManager.generateProfileId(profileName);
|
|
504
|
+
const copiedProfile = {
|
|
505
|
+
id: profileId,
|
|
506
|
+
name: profileName,
|
|
507
|
+
authType: selectedProfile.authType
|
|
508
|
+
};
|
|
509
|
+
if (selectedProfile.authType !== "ccr_proxy") {
|
|
510
|
+
copiedProfile.apiKey = answers.apiKey.trim();
|
|
511
|
+
copiedProfile.baseUrl = answers.baseUrl.trim();
|
|
512
|
+
if (modelConfig) {
|
|
513
|
+
if (modelConfig.primaryModel.trim()) {
|
|
514
|
+
copiedProfile.primaryModel = modelConfig.primaryModel.trim();
|
|
515
|
+
}
|
|
516
|
+
if (modelConfig.fastModel.trim()) {
|
|
517
|
+
copiedProfile.fastModel = modelConfig.fastModel.trim();
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
const result = await ClaudeCodeConfigManager.addProfile(copiedProfile);
|
|
522
|
+
if (result.success) {
|
|
523
|
+
const runtimeProfile = result.addedProfile || { ...copiedProfile, id: profileId };
|
|
524
|
+
console.log(ansis.green(i18n.t("multi-config:profileCopied", { name: runtimeProfile.name })));
|
|
525
|
+
if (result.backupPath) {
|
|
526
|
+
console.log(ansis.gray(i18n.t("common:backupCreated", { path: result.backupPath })));
|
|
527
|
+
}
|
|
528
|
+
if (setAsDefault) {
|
|
529
|
+
const switchResult = await ClaudeCodeConfigManager.switchProfile(runtimeProfile.id);
|
|
530
|
+
if (switchResult.success) {
|
|
531
|
+
console.log(ansis.green(i18n.t("multi-config:profileSetAsDefault", { name: runtimeProfile.name })));
|
|
532
|
+
await ClaudeCodeConfigManager.applyProfileSettings(runtimeProfile);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
} else {
|
|
536
|
+
console.log(ansis.red(i18n.t("multi-config:profileCopyFailed", { error: result.error })));
|
|
537
|
+
}
|
|
538
|
+
}
|
|
376
539
|
async function handleDeleteProfile(profiles) {
|
|
377
540
|
if (profiles.length <= 1) {
|
|
378
541
|
console.log(ansis.yellow(i18n.t("multi-config:cannotDeleteLast")));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import ansis from 'ansis';
|
|
2
2
|
import inquirer from 'inquirer';
|
|
3
|
-
import {
|
|
4
|
-
import { deleteProviders,
|
|
3
|
+
import { aa as ensureI18nInitialized, al as detectConfigManagementMode, ab as i18n, ac as addNumbersToChoices, ai as readJsonConfig, l as CODEX_AUTH_FILE } from './simple-config.mjs';
|
|
4
|
+
import { deleteProviders, addProviderToExisting, editExistingProvider } from './codex-provider-manager.mjs';
|
|
5
5
|
import 'node:fs';
|
|
6
6
|
import 'node:process';
|
|
7
7
|
import 'node:child_process';
|
|
@@ -33,6 +33,7 @@ async function configureIncrementalManagement() {
|
|
|
33
33
|
const choices = [
|
|
34
34
|
{ name: i18n.t("codex:addProvider"), value: "add" },
|
|
35
35
|
{ name: i18n.t("codex:editProvider"), value: "edit" },
|
|
36
|
+
{ name: i18n.t("codex:copyProvider"), value: "copy" },
|
|
36
37
|
{ name: i18n.t("codex:deleteProvider"), value: "delete" },
|
|
37
38
|
{ name: i18n.t("common:skip"), value: "skip" }
|
|
38
39
|
];
|
|
@@ -53,6 +54,9 @@ async function configureIncrementalManagement() {
|
|
|
53
54
|
case "edit":
|
|
54
55
|
await handleEditProvider(managementMode.providers);
|
|
55
56
|
break;
|
|
57
|
+
case "copy":
|
|
58
|
+
await handleCopyProvider(managementMode.providers);
|
|
59
|
+
break;
|
|
56
60
|
case "delete":
|
|
57
61
|
await handleDeleteProvider(managementMode.providers);
|
|
58
62
|
break;
|
|
@@ -165,7 +169,7 @@ async function handleAddProvider() {
|
|
|
165
169
|
default: true
|
|
166
170
|
}]);
|
|
167
171
|
if (setAsDefault) {
|
|
168
|
-
const { switchToProvider } = await import('./simple-config.mjs').then(function (n) { return n.
|
|
172
|
+
const { switchToProvider } = await import('./simple-config.mjs').then(function (n) { return n.bb; });
|
|
169
173
|
const switched = await switchToProvider(provider.id);
|
|
170
174
|
if (switched) {
|
|
171
175
|
console.log(ansis.green(i18n.t("multi-config:profileSetAsDefault", { name: provider.name })));
|
|
@@ -195,6 +199,8 @@ async function handleEditProvider(providers) {
|
|
|
195
199
|
console.log(ansis.red(i18n.t("codex:providerNotFound")));
|
|
196
200
|
return;
|
|
197
201
|
}
|
|
202
|
+
const existingAuth = readJsonConfig(CODEX_AUTH_FILE, { defaultValue: {} }) || {};
|
|
203
|
+
const existingApiKey = existingAuth[provider.envKey] || "";
|
|
198
204
|
const answers = await inquirer.prompt([
|
|
199
205
|
{
|
|
200
206
|
type: "input",
|
|
@@ -231,14 +237,26 @@ async function handleEditProvider(providers) {
|
|
|
231
237
|
type: "input",
|
|
232
238
|
name: "apiKey",
|
|
233
239
|
message: i18n.t("codex:providerApiKeyPrompt"),
|
|
240
|
+
default: existingApiKey,
|
|
241
|
+
// Show old API key from auth.json
|
|
234
242
|
validate: (input) => !!input.trim() || i18n.t("codex:providerApiKeyRequired")
|
|
235
243
|
}
|
|
236
244
|
]);
|
|
245
|
+
const { model } = await inquirer.prompt([
|
|
246
|
+
{
|
|
247
|
+
type: "input",
|
|
248
|
+
name: "model",
|
|
249
|
+
message: i18n.t("codex:providerModelPrompt"),
|
|
250
|
+
default: provider.model || "gpt-5-codex",
|
|
251
|
+
validate: (input) => !!input.trim() || i18n.t("codex:providerModelRequired")
|
|
252
|
+
}
|
|
253
|
+
]);
|
|
237
254
|
const updates = {
|
|
238
255
|
name: answers.providerName.trim(),
|
|
239
256
|
baseUrl: answers.baseUrl.trim(),
|
|
240
257
|
wireApi: answers.wireApi,
|
|
241
|
-
apiKey: answers.apiKey.trim()
|
|
258
|
+
apiKey: answers.apiKey.trim(),
|
|
259
|
+
model: model.trim()
|
|
242
260
|
};
|
|
243
261
|
const result = await editExistingProvider(selectedProviderId, updates);
|
|
244
262
|
if (result.success) {
|
|
@@ -250,6 +268,114 @@ async function handleEditProvider(providers) {
|
|
|
250
268
|
console.log(ansis.red(i18n.t("codex:providerUpdateFailed", { error: result.error })));
|
|
251
269
|
}
|
|
252
270
|
}
|
|
271
|
+
async function handleCopyProvider(providers) {
|
|
272
|
+
const choices = providers.map((provider2) => ({
|
|
273
|
+
name: `${provider2.name} (${provider2.baseUrl})`,
|
|
274
|
+
value: provider2.id
|
|
275
|
+
}));
|
|
276
|
+
const { selectedProviderId } = await inquirer.prompt([{
|
|
277
|
+
type: "list",
|
|
278
|
+
name: "selectedProviderId",
|
|
279
|
+
message: i18n.t("codex:selectProviderToCopy"),
|
|
280
|
+
choices: addNumbersToChoices(choices)
|
|
281
|
+
}]);
|
|
282
|
+
if (!selectedProviderId) {
|
|
283
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
const provider = providers.find((p) => p.id === selectedProviderId);
|
|
287
|
+
if (!provider) {
|
|
288
|
+
console.log(ansis.red(i18n.t("codex:providerNotFound")));
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
console.log(ansis.cyan(`
|
|
292
|
+
${i18n.t("codex:copyingProvider", { name: provider.name })}`));
|
|
293
|
+
const existingAuth = readJsonConfig(CODEX_AUTH_FILE, { defaultValue: {} }) || {};
|
|
294
|
+
const existingApiKey = existingAuth[provider.envKey] || "";
|
|
295
|
+
const copiedName = `${provider.name}-copy`;
|
|
296
|
+
const answers = await inquirer.prompt([
|
|
297
|
+
{
|
|
298
|
+
type: "input",
|
|
299
|
+
name: "providerName",
|
|
300
|
+
message: i18n.t("codex:providerNamePrompt"),
|
|
301
|
+
default: copiedName,
|
|
302
|
+
validate: (input) => {
|
|
303
|
+
const trimmed = input.trim();
|
|
304
|
+
if (!trimmed)
|
|
305
|
+
return i18n.t("codex:providerNameRequired");
|
|
306
|
+
if (!/^[\w\-\s.]+$/.test(trimmed))
|
|
307
|
+
return i18n.t("codex:providerNameInvalid");
|
|
308
|
+
return true;
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
type: "input",
|
|
313
|
+
name: "baseUrl",
|
|
314
|
+
message: i18n.t("codex:providerBaseUrlPrompt"),
|
|
315
|
+
default: provider.baseUrl,
|
|
316
|
+
validate: (input) => !!input.trim() || i18n.t("codex:providerBaseUrlRequired")
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
type: "list",
|
|
320
|
+
name: "wireApi",
|
|
321
|
+
message: i18n.t("codex:providerProtocolPrompt"),
|
|
322
|
+
choices: [
|
|
323
|
+
{ name: i18n.t("codex:protocolResponses"), value: "responses" },
|
|
324
|
+
{ name: i18n.t("codex:protocolChat"), value: "chat" }
|
|
325
|
+
],
|
|
326
|
+
default: provider.wireApi
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
type: "input",
|
|
330
|
+
name: "apiKey",
|
|
331
|
+
message: i18n.t("codex:providerApiKeyPrompt"),
|
|
332
|
+
default: existingApiKey,
|
|
333
|
+
// Show old API key from auth.json
|
|
334
|
+
validate: (input) => !!input.trim() || i18n.t("codex:providerApiKeyRequired")
|
|
335
|
+
}
|
|
336
|
+
]);
|
|
337
|
+
const { model } = await inquirer.prompt([
|
|
338
|
+
{
|
|
339
|
+
type: "input",
|
|
340
|
+
name: "model",
|
|
341
|
+
message: i18n.t("codex:providerModelPrompt"),
|
|
342
|
+
default: provider.model || "gpt-5-codex",
|
|
343
|
+
validate: (input) => !!input.trim() || i18n.t("codex:providerModelRequired")
|
|
344
|
+
}
|
|
345
|
+
]);
|
|
346
|
+
const providerId = answers.providerName.trim().toLowerCase().replace(/\s+/g, "-").replace(/\./g, "-").replace(/[^a-z0-9\-]/g, "");
|
|
347
|
+
const copiedProvider = {
|
|
348
|
+
id: providerId,
|
|
349
|
+
name: answers.providerName.trim(),
|
|
350
|
+
baseUrl: answers.baseUrl.trim(),
|
|
351
|
+
wireApi: answers.wireApi,
|
|
352
|
+
envKey: `${providerId.toUpperCase().replace(/-/g, "_")}_API_KEY`,
|
|
353
|
+
requiresOpenaiAuth: provider.requiresOpenaiAuth ?? true,
|
|
354
|
+
model: model.trim()
|
|
355
|
+
};
|
|
356
|
+
const result = await addProviderToExisting(copiedProvider, answers.apiKey.trim(), false);
|
|
357
|
+
if (result.success) {
|
|
358
|
+
console.log(ansis.green(i18n.t("codex:providerCopied", { name: result.addedProvider?.name })));
|
|
359
|
+
if (result.backupPath) {
|
|
360
|
+
console.log(ansis.gray(i18n.t("common:backupCreated", { path: result.backupPath })));
|
|
361
|
+
}
|
|
362
|
+
const { setAsDefault } = await inquirer.prompt([{
|
|
363
|
+
type: "confirm",
|
|
364
|
+
name: "setAsDefault",
|
|
365
|
+
message: i18n.t("multi-config:setAsDefaultPrompt"),
|
|
366
|
+
default: false
|
|
367
|
+
}]);
|
|
368
|
+
if (setAsDefault) {
|
|
369
|
+
const { switchToProvider } = await import('./simple-config.mjs').then(function (n) { return n.bb; });
|
|
370
|
+
const switched = await switchToProvider(copiedProvider.id);
|
|
371
|
+
if (switched) {
|
|
372
|
+
console.log(ansis.green(i18n.t("multi-config:profileSetAsDefault", { name: copiedProvider.name })));
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
} else {
|
|
376
|
+
console.log(ansis.red(i18n.t("codex:providerCopyFailed", { error: result.error })));
|
|
377
|
+
}
|
|
378
|
+
}
|
|
253
379
|
async function handleDeleteProvider(providers) {
|
|
254
380
|
const choices = providers.map((provider) => ({
|
|
255
381
|
name: `${provider.name} (${provider.baseUrl})`,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { am as readCodexConfig, an as backupCodexComplete, ao as writeCodexConfig, ap as writeAuthFile } from './simple-config.mjs';
|
|
2
2
|
import 'node:fs';
|
|
3
3
|
import 'node:process';
|
|
4
4
|
import 'ansis';
|
|
@@ -106,7 +106,8 @@ async function editExistingProvider(providerId, updates) {
|
|
|
106
106
|
...existingConfig.providers[providerIndex],
|
|
107
107
|
...updates.name && { name: updates.name },
|
|
108
108
|
...updates.baseUrl && { baseUrl: updates.baseUrl },
|
|
109
|
-
...updates.wireApi && { wireApi: updates.wireApi }
|
|
109
|
+
...updates.wireApi && { wireApi: updates.wireApi },
|
|
110
|
+
...updates.model && { model: updates.model }
|
|
110
111
|
};
|
|
111
112
|
const updatedProviders = [...existingConfig.providers];
|
|
112
113
|
updatedProviders[providerIndex] = updatedProvider;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { homedir } from 'node:os';
|
|
2
1
|
import { pathExists } from 'fs-extra';
|
|
3
2
|
import { join } from 'pathe';
|
|
4
3
|
import { exec } from 'tinyexec';
|
|
5
|
-
import {
|
|
4
|
+
import { j as CODEX_DIR, k as CODEX_CONFIG_FILE, ab as i18n, l as CODEX_AUTH_FILE, n as CODEX_AGENTS_FILE, p as CODEX_PROMPTS_DIR } from './simple-config.mjs';
|
|
6
5
|
import { m as moveToTrash } from '../shared/zcf.DGjQxTq_.mjs';
|
|
7
6
|
import 'node:fs';
|
|
8
7
|
import 'node:process';
|
|
9
8
|
import 'ansis';
|
|
10
9
|
import 'inquirer';
|
|
11
10
|
import 'node:child_process';
|
|
11
|
+
import 'node:os';
|
|
12
12
|
import 'node:util';
|
|
13
13
|
import 'dayjs';
|
|
14
14
|
import 'node:url';
|
|
@@ -23,12 +23,7 @@ import 'trash';
|
|
|
23
23
|
class CodexUninstaller {
|
|
24
24
|
_lang;
|
|
25
25
|
conflictResolution = /* @__PURE__ */ new Map();
|
|
26
|
-
|
|
27
|
-
CODEX_CONFIG_FILE = join(this.CODEX_DIR, "config.toml");
|
|
28
|
-
CODEX_AUTH_FILE = join(this.CODEX_DIR, "auth.json");
|
|
29
|
-
CODEX_AGENTS_FILE = join(this.CODEX_DIR, "AGENTS.md");
|
|
30
|
-
CODEX_PROMPTS_DIR = join(this.CODEX_DIR, "prompts");
|
|
31
|
-
CODEX_BACKUP_DIR = join(this.CODEX_DIR, "backup");
|
|
26
|
+
CODEX_BACKUP_DIR = join(CODEX_DIR, "backup");
|
|
32
27
|
constructor(lang = "en") {
|
|
33
28
|
this._lang = lang;
|
|
34
29
|
this.conflictResolution.set("cli-package", ["config", "auth"]);
|
|
@@ -47,8 +42,8 @@ class CodexUninstaller {
|
|
|
47
42
|
warnings: []
|
|
48
43
|
};
|
|
49
44
|
try {
|
|
50
|
-
if (await pathExists(
|
|
51
|
-
const trashResult = await moveToTrash(
|
|
45
|
+
if (await pathExists(CODEX_CONFIG_FILE)) {
|
|
46
|
+
const trashResult = await moveToTrash(CODEX_CONFIG_FILE);
|
|
52
47
|
if (!trashResult[0]?.success) {
|
|
53
48
|
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
54
49
|
}
|
|
@@ -75,8 +70,8 @@ class CodexUninstaller {
|
|
|
75
70
|
warnings: []
|
|
76
71
|
};
|
|
77
72
|
try {
|
|
78
|
-
if (await pathExists(
|
|
79
|
-
const trashResult = await moveToTrash(
|
|
73
|
+
if (await pathExists(CODEX_AUTH_FILE)) {
|
|
74
|
+
const trashResult = await moveToTrash(CODEX_AUTH_FILE);
|
|
80
75
|
if (!trashResult[0]?.success) {
|
|
81
76
|
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
82
77
|
}
|
|
@@ -103,8 +98,8 @@ class CodexUninstaller {
|
|
|
103
98
|
warnings: []
|
|
104
99
|
};
|
|
105
100
|
try {
|
|
106
|
-
if (await pathExists(
|
|
107
|
-
const trashResult = await moveToTrash(
|
|
101
|
+
if (await pathExists(CODEX_AGENTS_FILE)) {
|
|
102
|
+
const trashResult = await moveToTrash(CODEX_AGENTS_FILE);
|
|
108
103
|
if (!trashResult[0]?.success) {
|
|
109
104
|
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
110
105
|
}
|
|
@@ -131,8 +126,8 @@ class CodexUninstaller {
|
|
|
131
126
|
warnings: []
|
|
132
127
|
};
|
|
133
128
|
try {
|
|
134
|
-
if (await pathExists(
|
|
135
|
-
const trashResult = await moveToTrash(
|
|
129
|
+
if (await pathExists(CODEX_PROMPTS_DIR)) {
|
|
130
|
+
const trashResult = await moveToTrash(CODEX_PROMPTS_DIR);
|
|
136
131
|
if (!trashResult[0]?.success) {
|
|
137
132
|
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
138
133
|
}
|
|
@@ -184,9 +179,9 @@ class CodexUninstaller {
|
|
|
184
179
|
warnings: []
|
|
185
180
|
};
|
|
186
181
|
try {
|
|
187
|
-
if (await pathExists(
|
|
182
|
+
if (await pathExists(CODEX_CONFIG_FILE)) {
|
|
188
183
|
const { readFileSync, writeFileSync } = await import('node:fs');
|
|
189
|
-
const content = readFileSync(
|
|
184
|
+
const content = readFileSync(CODEX_CONFIG_FILE, "utf-8");
|
|
190
185
|
const lines = content.split("\n");
|
|
191
186
|
const newLines = [];
|
|
192
187
|
let inProviderSection = false;
|
|
@@ -210,7 +205,7 @@ class CodexUninstaller {
|
|
|
210
205
|
newLines.push(line);
|
|
211
206
|
}
|
|
212
207
|
if (configModified) {
|
|
213
|
-
writeFileSync(
|
|
208
|
+
writeFileSync(CODEX_CONFIG_FILE, newLines.join("\n"));
|
|
214
209
|
result.removedConfigs.push(i18n.t("codex:apiConfigRemoved"));
|
|
215
210
|
}
|
|
216
211
|
result.success = true;
|
|
@@ -263,9 +258,9 @@ class CodexUninstaller {
|
|
|
263
258
|
warnings: []
|
|
264
259
|
};
|
|
265
260
|
try {
|
|
266
|
-
if (await pathExists(
|
|
261
|
+
if (await pathExists(CODEX_CONFIG_FILE)) {
|
|
267
262
|
const { readFileSync, writeFileSync } = await import('node:fs');
|
|
268
|
-
const content = readFileSync(
|
|
263
|
+
const content = readFileSync(CODEX_CONFIG_FILE, "utf-8");
|
|
269
264
|
const lines = content.split("\n");
|
|
270
265
|
const newLines = [];
|
|
271
266
|
let inMcpSection = false;
|
|
@@ -285,7 +280,7 @@ class CodexUninstaller {
|
|
|
285
280
|
newLines.push(line);
|
|
286
281
|
}
|
|
287
282
|
if (configModified) {
|
|
288
|
-
writeFileSync(
|
|
283
|
+
writeFileSync(CODEX_CONFIG_FILE, newLines.join("\n"));
|
|
289
284
|
result.removedConfigs.push(i18n.t("codex:mcpConfigRemoved"));
|
|
290
285
|
}
|
|
291
286
|
result.success = true;
|
|
@@ -310,8 +305,8 @@ class CodexUninstaller {
|
|
|
310
305
|
warnings: []
|
|
311
306
|
};
|
|
312
307
|
try {
|
|
313
|
-
if (await pathExists(
|
|
314
|
-
const trashResult = await moveToTrash(
|
|
308
|
+
if (await pathExists(CODEX_DIR)) {
|
|
309
|
+
const trashResult = await moveToTrash(CODEX_DIR);
|
|
315
310
|
if (!trashResult[0]?.success) {
|
|
316
311
|
result.warnings.push(`Failed to move ~/.codex/ to trash: ${trashResult[0]?.error || "Unknown error"}`);
|
|
317
312
|
}
|
package/dist/chunks/commands.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { exec } from 'node:child_process';
|
|
2
2
|
import { promisify } from 'node:util';
|
|
3
3
|
import ansis from 'ansis';
|
|
4
|
-
import {
|
|
4
|
+
import { aa as ensureI18nInitialized, ab as i18n } from './simple-config.mjs';
|
|
5
5
|
import 'node:fs';
|
|
6
6
|
import 'node:process';
|
|
7
7
|
import 'inquirer';
|
package/dist/chunks/features.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import ansis from 'ansis';
|
|
2
2
|
import inquirer from 'inquirer';
|
|
3
|
-
import {
|
|
3
|
+
import { ab as i18n, aa as ensureI18nInitialized, x as SUPPORTED_LANGS, ac as addNumbersToChoices, y as LANG_LABELS, aq as updateZcfConfig, ar as changeLanguage, as as readZcfConfig, o as openSettingsJson, d as importRecommendedPermissions, b as importRecommendedEnv, a1 as applyAiLanguageDirective, at as configureOutputStyle, $ as getExistingModelConfig, X as updateCustomModel, Y as updateDefaultModel, au as isWindows, F as readMcpConfig, K as fixWindowsMcpConfig, G as writeMcpConfig, av as selectMcpServices, H as backupMcpConfig, aw as getMcpServices, J as buildMcpServerConfig, I as mergeMcpServers, ax as isCcrInstalled, ay as installCcr, az as setupCcrConfiguration, a0 as getExistingApiConfig, a3 as promptApiConfigurationAction, aA as modifyApiConfigPartially, ad as validateApiKey, V as configureApi, aB as formatApiKeyDisplay, a2 as switchToOfficialLogin } from './simple-config.mjs';
|
|
4
4
|
import 'node:fs';
|
|
5
5
|
import 'node:process';
|
|
6
6
|
import 'node:child_process';
|
|
@@ -288,18 +288,18 @@ ${ansis.blue(`\u2139 ${i18n.t("configuration:existingModelConfig") || "Existing
|
|
|
288
288
|
updateDefaultModel(model);
|
|
289
289
|
console.log(ansis.green(`\u2714 ${i18n.t("configuration:modelConfigured") || "Default model configured"}`));
|
|
290
290
|
}
|
|
291
|
-
async function promptCustomModels() {
|
|
291
|
+
async function promptCustomModels(defaultPrimaryModel, defaultFastModel) {
|
|
292
292
|
const { primaryModel } = await inquirer.prompt({
|
|
293
293
|
type: "input",
|
|
294
294
|
name: "primaryModel",
|
|
295
295
|
message: `${i18n.t("configuration:enterPrimaryModel")}${i18n.t("common:emptyToSkip")}`,
|
|
296
|
-
default: ""
|
|
296
|
+
default: defaultPrimaryModel || ""
|
|
297
297
|
});
|
|
298
298
|
const { fastModel } = await inquirer.prompt({
|
|
299
299
|
type: "input",
|
|
300
300
|
name: "fastModel",
|
|
301
301
|
message: `${i18n.t("configuration:enterFastModel")}${i18n.t("common:emptyToSkip")}`,
|
|
302
|
-
default: ""
|
|
302
|
+
default: defaultFastModel || ""
|
|
303
303
|
});
|
|
304
304
|
return { primaryModel, fastModel };
|
|
305
305
|
}
|
|
@@ -344,7 +344,7 @@ ${ansis.blue(`\u2139 ${i18n.t("configuration:existingLanguageConfig") || "Existi
|
|
|
344
344
|
return;
|
|
345
345
|
}
|
|
346
346
|
}
|
|
347
|
-
const { selectAiOutputLanguage } = await import('./simple-config.mjs').then(function (n) { return n.
|
|
347
|
+
const { selectAiOutputLanguage } = await import('./simple-config.mjs').then(function (n) { return n.ba; });
|
|
348
348
|
const aiOutputLang = await selectAiOutputLanguage();
|
|
349
349
|
applyAiLanguageDirective(aiOutputLang);
|
|
350
350
|
updateZcfConfig({ aiOutputLang });
|
|
@@ -377,7 +377,7 @@ async function changeScriptLanguageFeature(currentLang) {
|
|
|
377
377
|
}
|
|
378
378
|
async function configureCodexDefaultModelFeature() {
|
|
379
379
|
ensureI18nInitialized();
|
|
380
|
-
const { readCodexConfig } = await import('./simple-config.mjs').then(function (n) { return n.
|
|
380
|
+
const { readCodexConfig } = await import('./simple-config.mjs').then(function (n) { return n.bb; });
|
|
381
381
|
const existingConfig = readCodexConfig();
|
|
382
382
|
const currentModel = existingConfig?.model;
|
|
383
383
|
if (currentModel) {
|
|
@@ -482,7 +482,7 @@ ${ansis.blue(`\u2139 ${i18n.t("configuration:existingLanguageConfig") || "Existi
|
|
|
482
482
|
return;
|
|
483
483
|
}
|
|
484
484
|
}
|
|
485
|
-
const { selectAiOutputLanguage } = await import('./simple-config.mjs').then(function (n) { return n.
|
|
485
|
+
const { selectAiOutputLanguage } = await import('./simple-config.mjs').then(function (n) { return n.ba; });
|
|
486
486
|
const aiOutputLang = await selectAiOutputLanguage();
|
|
487
487
|
await updateCodexLanguageDirective(aiOutputLang);
|
|
488
488
|
updateZcfConfig({ aiOutputLang });
|
|
@@ -490,14 +490,14 @@ ${ansis.blue(`\u2139 ${i18n.t("configuration:existingLanguageConfig") || "Existi
|
|
|
490
490
|
} else if (option === "systemPrompt") {
|
|
491
491
|
const zcfConfig = readZcfConfig();
|
|
492
492
|
const currentLang = zcfConfig?.aiOutputLang || "English";
|
|
493
|
-
const { runCodexSystemPromptSelection } = await import('./simple-config.mjs').then(function (n) { return n.
|
|
493
|
+
const { runCodexSystemPromptSelection } = await import('./simple-config.mjs').then(function (n) { return n.bb; });
|
|
494
494
|
await runCodexSystemPromptSelection();
|
|
495
495
|
await ensureLanguageDirectiveInAgents(currentLang);
|
|
496
496
|
console.log(ansis.green(`\u2714 ${i18n.t("configuration:systemPromptConfigured")}`));
|
|
497
497
|
}
|
|
498
498
|
}
|
|
499
499
|
async function updateCodexModelProvider(modelProvider) {
|
|
500
|
-
const { readCodexConfig, writeCodexConfig, backupCodexConfig, getBackupMessage } = await import('./simple-config.mjs').then(function (n) { return n.
|
|
500
|
+
const { readCodexConfig, writeCodexConfig, backupCodexConfig, getBackupMessage } = await import('./simple-config.mjs').then(function (n) { return n.bb; });
|
|
501
501
|
const backupPath = backupCodexConfig();
|
|
502
502
|
if (backupPath) {
|
|
503
503
|
console.log(ansis.gray(getBackupMessage(backupPath)));
|
|
@@ -518,7 +518,7 @@ async function updateCodexModelProvider(modelProvider) {
|
|
|
518
518
|
writeCodexConfig(updatedConfig);
|
|
519
519
|
}
|
|
520
520
|
async function ensureLanguageDirectiveInAgents(aiOutputLang) {
|
|
521
|
-
const { readFile, writeFile, exists } = await import('./simple-config.mjs').then(function (n) { return n.
|
|
521
|
+
const { readFile, writeFile, exists } = await import('./simple-config.mjs').then(function (n) { return n.b5; });
|
|
522
522
|
const { homedir } = await import('node:os');
|
|
523
523
|
const { join } = await import('pathe');
|
|
524
524
|
const CODEX_AGENTS_FILE = join(homedir(), ".codex", "AGENTS.md");
|
|
@@ -536,7 +536,7 @@ async function ensureLanguageDirectiveInAgents(aiOutputLang) {
|
|
|
536
536
|
const langLabel = languageLabels[aiOutputLang] || aiOutputLang;
|
|
537
537
|
const hasLanguageDirective = /\*\*Most Important:\s*Always respond in [^*]+\*\*/i.test(content);
|
|
538
538
|
if (!hasLanguageDirective) {
|
|
539
|
-
const { backupCodexAgents, getBackupMessage } = await import('./simple-config.mjs').then(function (n) { return n.
|
|
539
|
+
const { backupCodexAgents, getBackupMessage } = await import('./simple-config.mjs').then(function (n) { return n.bb; });
|
|
540
540
|
const backupPath = backupCodexAgents();
|
|
541
541
|
if (backupPath) {
|
|
542
542
|
console.log(ansis.gray(getBackupMessage(backupPath)));
|
|
@@ -553,8 +553,8 @@ async function ensureLanguageDirectiveInAgents(aiOutputLang) {
|
|
|
553
553
|
}
|
|
554
554
|
}
|
|
555
555
|
async function updateCodexLanguageDirective(aiOutputLang) {
|
|
556
|
-
const { readFile, writeFile, exists } = await import('./simple-config.mjs').then(function (n) { return n.
|
|
557
|
-
const { backupCodexAgents, getBackupMessage } = await import('./simple-config.mjs').then(function (n) { return n.
|
|
556
|
+
const { readFile, writeFile, exists } = await import('./simple-config.mjs').then(function (n) { return n.b5; });
|
|
557
|
+
const { backupCodexAgents, getBackupMessage } = await import('./simple-config.mjs').then(function (n) { return n.bb; });
|
|
558
558
|
const { homedir } = await import('node:os');
|
|
559
559
|
const { join } = await import('pathe');
|
|
560
560
|
const CODEX_AGENTS_FILE = join(homedir(), ".codex", "AGENTS.md");
|
|
@@ -16,7 +16,7 @@ import { rm, mkdir, copyFile as copyFile$1 } from 'node:fs/promises';
|
|
|
16
16
|
import i18next from 'i18next';
|
|
17
17
|
import Backend from 'i18next-fs-backend';
|
|
18
18
|
|
|
19
|
-
const version = "3.3.
|
|
19
|
+
const version = "3.3.2";
|
|
20
20
|
const homepage = "https://github.com/UfoMiao/zcf";
|
|
21
21
|
|
|
22
22
|
const i18n = i18next.createInstance();
|
|
@@ -381,6 +381,11 @@ const SETTINGS_FILE = join(CLAUDE_DIR, "settings.json");
|
|
|
381
381
|
const CLAUDE_MD_FILE = join(CLAUDE_DIR, "CLAUDE.md");
|
|
382
382
|
const ClAUDE_CONFIG_FILE = join(homedir(), ".claude.json");
|
|
383
383
|
const CLAUDE_VSC_CONFIG_FILE = join(CLAUDE_DIR, "config.json");
|
|
384
|
+
const CODEX_DIR = join(homedir(), ".codex");
|
|
385
|
+
const CODEX_CONFIG_FILE = join(CODEX_DIR, "config.toml");
|
|
386
|
+
const CODEX_AUTH_FILE = join(CODEX_DIR, "auth.json");
|
|
387
|
+
const CODEX_AGENTS_FILE = join(CODEX_DIR, "AGENTS.md");
|
|
388
|
+
const CODEX_PROMPTS_DIR = join(CODEX_DIR, "prompts");
|
|
384
389
|
const ZCF_CONFIG_DIR = join(homedir(), ".ufomiao", "zcf");
|
|
385
390
|
const ZCF_CONFIG_FILE = join(ZCF_CONFIG_DIR, "config.toml");
|
|
386
391
|
const LEGACY_ZCF_CONFIG_FILES = [
|
|
@@ -442,6 +447,11 @@ const constants = {
|
|
|
442
447
|
CLAUDE_DIR: CLAUDE_DIR,
|
|
443
448
|
CLAUDE_MD_FILE: CLAUDE_MD_FILE,
|
|
444
449
|
CLAUDE_VSC_CONFIG_FILE: CLAUDE_VSC_CONFIG_FILE,
|
|
450
|
+
CODEX_AGENTS_FILE: CODEX_AGENTS_FILE,
|
|
451
|
+
CODEX_AUTH_FILE: CODEX_AUTH_FILE,
|
|
452
|
+
CODEX_CONFIG_FILE: CODEX_CONFIG_FILE,
|
|
453
|
+
CODEX_DIR: CODEX_DIR,
|
|
454
|
+
CODEX_PROMPTS_DIR: CODEX_PROMPTS_DIR,
|
|
445
455
|
CODE_TOOL_ALIASES: CODE_TOOL_ALIASES,
|
|
446
456
|
CODE_TOOL_BANNERS: CODE_TOOL_BANNERS,
|
|
447
457
|
CODE_TOOL_TYPES: CODE_TOOL_TYPES,
|
|
@@ -1350,11 +1360,6 @@ function switchToOfficialLogin$1() {
|
|
|
1350
1360
|
delete vscConfig.primaryApiKey;
|
|
1351
1361
|
writeJsonConfig(CLAUDE_VSC_CONFIG_FILE, vscConfig);
|
|
1352
1362
|
}
|
|
1353
|
-
const mcpConfig = readMcpConfig();
|
|
1354
|
-
if (mcpConfig) {
|
|
1355
|
-
delete mcpConfig.hasCompletedOnboarding;
|
|
1356
|
-
writeMcpConfig(mcpConfig);
|
|
1357
|
-
}
|
|
1358
1363
|
console.log(i18n.t("api:officialLoginConfigured"));
|
|
1359
1364
|
return true;
|
|
1360
1365
|
} catch (error) {
|
|
@@ -2915,11 +2920,6 @@ async function configureCodexMcp(options) {
|
|
|
2915
2920
|
console.log(ansis.green(i18n.t("codex:mcpConfigured")));
|
|
2916
2921
|
}
|
|
2917
2922
|
|
|
2918
|
-
const CODEX_DIR = join(homedir(), ".codex");
|
|
2919
|
-
const CODEX_CONFIG_FILE = join(CODEX_DIR, "config.toml");
|
|
2920
|
-
const CODEX_AUTH_FILE = join(CODEX_DIR, "auth.json");
|
|
2921
|
-
const CODEX_AGENTS_FILE = join(CODEX_DIR, "AGENTS.md");
|
|
2922
|
-
const CODEX_PROMPTS_DIR = join(CODEX_DIR, "prompts");
|
|
2923
2923
|
function getRootDir$1() {
|
|
2924
2924
|
const currentFilePath = fileURLToPath(import.meta.url);
|
|
2925
2925
|
let dir = dirname(currentFilePath);
|
|
@@ -6045,4 +6045,4 @@ async function openSettingsJson() {
|
|
|
6045
6045
|
}
|
|
6046
6046
|
}
|
|
6047
6047
|
|
|
6048
|
-
export {
|
|
6048
|
+
export { getExistingModelConfig as $, API_DEFAULT_URL as A, getAiOutputLanguageLabel as B, CLAUDE_DIR as C, DEFAULT_CODE_TOOL_TYPE as D, getMcpConfigPath as E, readMcpConfig as F, writeMcpConfig as G, backupMcpConfig as H, mergeMcpServers as I, buildMcpServerConfig as J, fixWindowsMcpConfig as K, LEGACY_ZCF_CONFIG_FILES as L, addCompletedOnboarding as M, ensureApiKeyApproved as N, removeApiKeyFromRejected as O, manageApiKeyApproval as P, setPrimaryApiKey as Q, ensureClaudeDir as R, SETTINGS_FILE as S, backupExistingConfig as T, copyConfigFiles as U, configureApi as V, mergeConfigs as W, updateCustomModel as X, updateDefaultModel as Y, ZCF_CONFIG_DIR as Z, mergeSettingsFile as _, commandExists as a, switchToOfficialLogin as a$, getExistingApiConfig as a0, applyAiLanguageDirective as a1, switchToOfficialLogin$1 as a2, promptApiConfigurationAction as a3, isClaudeCodeInstalled as a4, installClaudeCode as a5, isLocalClaudeCodeInstalled as a6, getInstallationStatus as a7, removeLocalClaudeCode as a8, setInstallMethod as a9, modifyApiConfigPartially as aA, formatApiKeyDisplay as aB, readCcrConfig as aC, configureCcrFeature as aD, handleExitPromptError as aE, handleGeneralError as aF, COMETIX_COMMAND_NAME as aG, COMETIX_COMMANDS as aH, installCometixLine as aI, checkAndUpdateTools as aJ, runCodexUpdate as aK, resolveCodeType as aL, writeJsonConfig as aM, displayBanner as aN, version as aO, resolveAiOutputLanguage as aP, updatePromptOnly as aQ, selectAndInstallWorkflows as aR, checkClaudeCodeVersionAndPrompt as aS, displayBannerWithInfo as aT, runCodexUninstall as aU, configureCodexMcp as aV, configureCodexApi as aW, runCodexWorkflowImportWithLanguageSelection as aX, runCodexFullInit as aY, switchCodexProvider as aZ, listCodexProviders as a_, ensureI18nInitialized as aa, i18n as ab, addNumbersToChoices as ac, validateApiKey as ad, ensureDir as ae, readDefaultTomlConfig as af, createDefaultTomlConfig as ag, exists as ah, readJsonConfig as ai, writeTomlConfig as aj, copyFile as ak, detectConfigManagementMode as al, readCodexConfig as am, backupCodexComplete as an, writeCodexConfig as ao, writeAuthFile as ap, updateZcfConfig as aq, changeLanguage as ar, readZcfConfig as as, configureOutputStyle as at, isWindows as au, selectMcpServices as av, getMcpServices as aw, isCcrInstalled as ax, installCcr as ay, setupCcrConfiguration as az, importRecommendedEnv as b, switchToProvider as b0, readZcfConfigAsync as b1, initI18n as b2, selectScriptLanguage as b3, index as b4, fsOperations as b5, jsonConfig as b6, claudeConfig as b7, config$1 as b8, config as b9, prompts as ba, codex as bb, cleanupPermissions as c, importRecommendedPermissions as d, CLAUDE_MD_FILE as e, ClAUDE_CONFIG_FILE as f, getPlatform as g, CLAUDE_VSC_CONFIG_FILE as h, init as i, CODEX_DIR as j, CODEX_CONFIG_FILE as k, CODEX_AUTH_FILE as l, mergeAndCleanPermissions as m, CODEX_AGENTS_FILE as n, openSettingsJson as o, CODEX_PROMPTS_DIR as p, ZCF_CONFIG_FILE as q, CODE_TOOL_TYPES as r, CODE_TOOL_BANNERS as s, CODE_TOOL_ALIASES as t, isCodeToolType as u, API_ENV_KEY as v, resolveCodeToolType as w, SUPPORTED_LANGS as x, LANG_LABELS as y, AI_OUTPUT_LANGUAGES as z };
|
package/dist/cli.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import cac from 'cac';
|
|
3
3
|
import ansis from 'ansis';
|
|
4
|
-
import {
|
|
4
|
+
import { aa as ensureI18nInitialized, ab as i18n, aC as readCcrConfig, ax as isCcrInstalled, ay as installCcr, aD as configureCcrFeature, aE as handleExitPromptError, aF as handleGeneralError, aG as COMETIX_COMMAND_NAME, aH as COMETIX_COMMANDS, aI as installCometixLine, ac as addNumbersToChoices, aJ as checkAndUpdateTools, aK as runCodexUpdate, aL as resolveCodeType$1, ai as readJsonConfig, aM as writeJsonConfig, q as ZCF_CONFIG_FILE, aN as displayBanner, as as readZcfConfig, aq as updateZcfConfig, aO as version, aP as resolveAiOutputLanguage, aQ as updatePromptOnly, aR as selectAndInstallWorkflows, aS as checkClaudeCodeVersionAndPrompt, w as resolveCodeToolType$1, D as DEFAULT_CODE_TOOL_TYPE, u as isCodeToolType, aT as displayBannerWithInfo, s as CODE_TOOL_BANNERS, aU as runCodexUninstall, aV as configureCodexMcp, aW as configureCodexApi, aX as runCodexWorkflowImportWithLanguageSelection, aY as runCodexFullInit, i as init, aZ as switchCodexProvider, a_ as listCodexProviders, am as readCodexConfig, a$ as switchToOfficialLogin, b0 as switchToProvider, b1 as readZcfConfigAsync, b2 as initI18n, b3 as selectScriptLanguage, ar as changeLanguage } from './chunks/simple-config.mjs';
|
|
5
5
|
import { existsSync } from 'node:fs';
|
|
6
6
|
import { homedir } from 'node:os';
|
|
7
7
|
import inquirer from 'inquirer';
|
|
@@ -1177,7 +1177,7 @@ async function update(options = {}) {
|
|
|
1177
1177
|
}
|
|
1178
1178
|
return;
|
|
1179
1179
|
}
|
|
1180
|
-
const { resolveTemplateLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.
|
|
1180
|
+
const { resolveTemplateLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.ba; });
|
|
1181
1181
|
const configLang = await resolveTemplateLanguage(
|
|
1182
1182
|
options.configLang,
|
|
1183
1183
|
// Command line option
|
|
@@ -1733,7 +1733,7 @@ async function handleClaudeCodeInteractiveSwitch() {
|
|
|
1733
1733
|
});
|
|
1734
1734
|
const isCcrMode = currentProfileId2 === "ccr-proxy";
|
|
1735
1735
|
choices2.push({
|
|
1736
|
-
name: isCcrMode ? `${ansis.green("\u25CF ")}
|
|
1736
|
+
name: isCcrMode ? `${ansis.green("\u25CF ")}${i18n.t("multi-config:ccrProxyOption")} ${ansis.yellow(`(${i18n.t("common:current")})`)}` : ` ${i18n.t("multi-config:ccrProxyOption")}`,
|
|
1737
1737
|
value: "ccr"
|
|
1738
1738
|
});
|
|
1739
1739
|
Object.values(profiles).filter((profile) => profile.id !== "ccr-proxy").forEach((profile) => {
|
|
@@ -70,8 +70,15 @@
|
|
|
70
70
|
"selectAction": "Select action",
|
|
71
71
|
"addProvider": "Add provider",
|
|
72
72
|
"editProvider": "Edit provider",
|
|
73
|
+
"copyProvider": "Copy provider",
|
|
73
74
|
"deleteProvider": "Delete provider",
|
|
74
75
|
"selectProviderToEdit": "Select provider to edit",
|
|
76
|
+
"selectProviderToCopy": "Select provider to copy",
|
|
77
|
+
"copyingProvider": "Copying provider: {{name}}",
|
|
78
|
+
"providerCopied": "✔ Successfully copied provider: {{name}}",
|
|
79
|
+
"providerCopyFailed": "❌ Failed to copy provider: {{error}}",
|
|
80
|
+
"providerModelPrompt": "Model name (e.g. gpt-5-codex)",
|
|
81
|
+
"providerModelRequired": "Model name is required",
|
|
75
82
|
"selectProvidersToDelete": "Select providers to delete (multiple)",
|
|
76
83
|
"selectAtLeastOne": "Please select at least one provider",
|
|
77
84
|
"cannotDeleteAll": "Cannot delete all providers, at least one must remain",
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"currentDefaultProfile": "Current default profile: {{profile}}",
|
|
20
20
|
"addProfile": "Add Profile",
|
|
21
21
|
"editProfile": "Edit Profile",
|
|
22
|
+
"copyProfile": "Copy Profile",
|
|
22
23
|
"deleteProfile": "Delete Profile",
|
|
23
24
|
"selectAction": "Select action",
|
|
24
25
|
"addingNewProfile": "Adding New Profile",
|
|
@@ -35,6 +36,7 @@
|
|
|
35
36
|
"authType.api_key": "API Key",
|
|
36
37
|
"authType.auth_token": "Auth Token",
|
|
37
38
|
"authType.ccr_proxy": "CCR Proxy",
|
|
39
|
+
"ccrProxyOption": "Use CCR Proxy",
|
|
38
40
|
"profileAdded": "✔ Successfully added profile: {{name}}",
|
|
39
41
|
"profileAddFailed": "❌ Failed to add profile: {{error}}",
|
|
40
42
|
"profileDuplicatePrompt": "Profile '{{name}}' already exists in {{source}}, overwrite it?",
|
|
@@ -47,6 +49,10 @@
|
|
|
47
49
|
"profileUpdated": "✔ Successfully updated profile: {{name}}",
|
|
48
50
|
"profileUpdateFailed": "❌ Failed to update profile: {{error}}",
|
|
49
51
|
"selectProfileToEdit": "Select profile to edit",
|
|
52
|
+
"selectProfileToCopy": "Select profile to copy",
|
|
53
|
+
"copyingProfile": "Copying profile: {{name}}",
|
|
54
|
+
"profileCopied": "✔ Successfully copied profile: {{name}}",
|
|
55
|
+
"profileCopyFailed": "❌ Failed to copy profile: {{error}}",
|
|
50
56
|
"selectProfilesToDelete": "Select profiles to delete (multiple)",
|
|
51
57
|
"selectAtLeastOne": "Please select at least one profile",
|
|
52
58
|
"cannotDeleteAll": "Cannot delete all profiles, at least one must remain",
|
|
@@ -70,8 +70,15 @@
|
|
|
70
70
|
"selectAction": "请选择操作",
|
|
71
71
|
"addProvider": "添加供应商",
|
|
72
72
|
"editProvider": "编辑供应商",
|
|
73
|
+
"copyProvider": "复制供应商",
|
|
73
74
|
"deleteProvider": "删除供应商",
|
|
74
75
|
"selectProviderToEdit": "选择要编辑的供应商",
|
|
76
|
+
"selectProviderToCopy": "选择要复制的供应商",
|
|
77
|
+
"copyingProvider": "正在复制供应商:{{name}}",
|
|
78
|
+
"providerCopied": "✔ 已成功复制供应商:{{name}}",
|
|
79
|
+
"providerCopyFailed": "❌ 复制供应商失败:{{error}}",
|
|
80
|
+
"providerModelPrompt": "模型名称(如 gpt-5-codex)",
|
|
81
|
+
"providerModelRequired": "必须填写模型名称",
|
|
75
82
|
"selectProvidersToDelete": "选择要删除的供应商(多选)",
|
|
76
83
|
"selectAtLeastOne": "请至少选择一个供应商",
|
|
77
84
|
"cannotDeleteAll": "不能删除所有供应商,至少需要保留一个",
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"currentDefaultProfile": "当前默认配置:{{profile}}",
|
|
20
20
|
"addProfile": "添加配置",
|
|
21
21
|
"editProfile": "编辑配置",
|
|
22
|
+
"copyProfile": "复制配置",
|
|
22
23
|
"deleteProfile": "删除配置",
|
|
23
24
|
"selectAction": "请选择操作",
|
|
24
25
|
"addingNewProfile": "添加新配置",
|
|
@@ -35,6 +36,7 @@
|
|
|
35
36
|
"authType.api_key": "API Key",
|
|
36
37
|
"authType.auth_token": "Auth Token",
|
|
37
38
|
"authType.ccr_proxy": "CCR 代理",
|
|
39
|
+
"ccrProxyOption": "使用 CCR 代理",
|
|
38
40
|
"profileAdded": "✔ 已成功添加配置:{{name}}",
|
|
39
41
|
"profileAddFailed": "❌ 添加配置失败:{{error}}",
|
|
40
42
|
"profileDuplicatePrompt": "配置「{{name}}」已经存在于{{source}},是否覆盖?",
|
|
@@ -47,6 +49,10 @@
|
|
|
47
49
|
"profileUpdated": "✔ 已成功更新配置:{{name}}",
|
|
48
50
|
"profileUpdateFailed": "❌ 更新配置失败:{{error}}",
|
|
49
51
|
"selectProfileToEdit": "选择要编辑的配置",
|
|
52
|
+
"selectProfileToCopy": "选择要复制的配置",
|
|
53
|
+
"copyingProfile": "正在复制配置:{{name}}",
|
|
54
|
+
"profileCopied": "✔ 已成功复制配置:{{name}}",
|
|
55
|
+
"profileCopyFailed": "❌ 复制配置失败:{{error}}",
|
|
50
56
|
"selectProfilesToDelete": "选择要删除的配置(多选)",
|
|
51
57
|
"selectAtLeastOne": "请至少选择一个配置",
|
|
52
58
|
"cannotDeleteAll": "不能删除所有配置,至少需要保留一个",
|
package/dist/index.d.mts
CHANGED
|
@@ -3,6 +3,11 @@ declare const SETTINGS_FILE: string;
|
|
|
3
3
|
declare const CLAUDE_MD_FILE: string;
|
|
4
4
|
declare const ClAUDE_CONFIG_FILE: string;
|
|
5
5
|
declare const CLAUDE_VSC_CONFIG_FILE: string;
|
|
6
|
+
declare const CODEX_DIR: string;
|
|
7
|
+
declare const CODEX_CONFIG_FILE: string;
|
|
8
|
+
declare const CODEX_AUTH_FILE: string;
|
|
9
|
+
declare const CODEX_AGENTS_FILE: string;
|
|
10
|
+
declare const CODEX_PROMPTS_DIR: string;
|
|
6
11
|
declare const ZCF_CONFIG_DIR: string;
|
|
7
12
|
declare const ZCF_CONFIG_FILE: string;
|
|
8
13
|
declare const LEGACY_ZCF_CONFIG_FILES: string[];
|
|
@@ -168,7 +173,6 @@ declare function applyAiLanguageDirective(aiOutputLang: AiOutputLanguage | strin
|
|
|
168
173
|
* Switch to official login mode - remove all third-party API configurations
|
|
169
174
|
* Removes: ANTHROPIC_BASE_URL, ANTHROPIC_AUTH_TOKEN, ANTHROPIC_API_KEY from settings.json
|
|
170
175
|
* Removes: primaryApiKey from ~/.claude/config.json
|
|
171
|
-
* Removes: hasCompletedOnboarding from ~/.claude.json
|
|
172
176
|
*/
|
|
173
177
|
declare function switchToOfficialLogin(): boolean;
|
|
174
178
|
/**
|
|
@@ -229,5 +233,5 @@ declare function importRecommendedEnv(): Promise<void>;
|
|
|
229
233
|
declare function importRecommendedPermissions(): Promise<void>;
|
|
230
234
|
declare function openSettingsJson(): Promise<void>;
|
|
231
235
|
|
|
232
|
-
export { AI_OUTPUT_LANGUAGES, API_DEFAULT_URL, API_ENV_KEY, CLAUDE_DIR, CLAUDE_MD_FILE, CLAUDE_VSC_CONFIG_FILE, CODE_TOOL_ALIASES, CODE_TOOL_BANNERS, CODE_TOOL_TYPES, ClAUDE_CONFIG_FILE, DEFAULT_CODE_TOOL_TYPE, LANG_LABELS, LEGACY_ZCF_CONFIG_FILES, SETTINGS_FILE, SUPPORTED_LANGS, ZCF_CONFIG_DIR, ZCF_CONFIG_FILE, addCompletedOnboarding, applyAiLanguageDirective, backupExistingConfig, backupMcpConfig, buildMcpServerConfig, cleanupPermissions, commandExists, configureApi, copyConfigFiles, ensureApiKeyApproved, ensureClaudeDir, fixWindowsMcpConfig, getAiOutputLanguageLabel, getExistingApiConfig, getExistingModelConfig, getInstallationStatus, getMcpConfigPath, getPlatform, importRecommendedEnv, importRecommendedPermissions, init, installClaudeCode, isClaudeCodeInstalled, isCodeToolType, isLocalClaudeCodeInstalled, manageApiKeyApproval, mergeAndCleanPermissions, mergeConfigs, mergeMcpServers, mergeSettingsFile, openSettingsJson, promptApiConfigurationAction, readMcpConfig, removeApiKeyFromRejected, removeLocalClaudeCode, resolveCodeToolType, setInstallMethod, setPrimaryApiKey, switchToOfficialLogin, updateCustomModel, updateDefaultModel, writeMcpConfig };
|
|
236
|
+
export { AI_OUTPUT_LANGUAGES, API_DEFAULT_URL, API_ENV_KEY, CLAUDE_DIR, CLAUDE_MD_FILE, CLAUDE_VSC_CONFIG_FILE, CODEX_AGENTS_FILE, CODEX_AUTH_FILE, CODEX_CONFIG_FILE, CODEX_DIR, CODEX_PROMPTS_DIR, CODE_TOOL_ALIASES, CODE_TOOL_BANNERS, CODE_TOOL_TYPES, ClAUDE_CONFIG_FILE, DEFAULT_CODE_TOOL_TYPE, LANG_LABELS, LEGACY_ZCF_CONFIG_FILES, SETTINGS_FILE, SUPPORTED_LANGS, ZCF_CONFIG_DIR, ZCF_CONFIG_FILE, addCompletedOnboarding, applyAiLanguageDirective, backupExistingConfig, backupMcpConfig, buildMcpServerConfig, cleanupPermissions, commandExists, configureApi, copyConfigFiles, ensureApiKeyApproved, ensureClaudeDir, fixWindowsMcpConfig, getAiOutputLanguageLabel, getExistingApiConfig, getExistingModelConfig, getInstallationStatus, getMcpConfigPath, getPlatform, importRecommendedEnv, importRecommendedPermissions, init, installClaudeCode, isClaudeCodeInstalled, isCodeToolType, isLocalClaudeCodeInstalled, manageApiKeyApproval, mergeAndCleanPermissions, mergeConfigs, mergeMcpServers, mergeSettingsFile, openSettingsJson, promptApiConfigurationAction, readMcpConfig, removeApiKeyFromRejected, removeLocalClaudeCode, resolveCodeToolType, setInstallMethod, setPrimaryApiKey, switchToOfficialLogin, updateCustomModel, updateDefaultModel, writeMcpConfig };
|
|
233
237
|
export type { AiOutputLanguage, ApiConfig, ClaudeConfiguration, CodeToolType, InstallationStatus, McpServerConfig, McpService, SupportedLang };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,11 @@ declare const SETTINGS_FILE: string;
|
|
|
3
3
|
declare const CLAUDE_MD_FILE: string;
|
|
4
4
|
declare const ClAUDE_CONFIG_FILE: string;
|
|
5
5
|
declare const CLAUDE_VSC_CONFIG_FILE: string;
|
|
6
|
+
declare const CODEX_DIR: string;
|
|
7
|
+
declare const CODEX_CONFIG_FILE: string;
|
|
8
|
+
declare const CODEX_AUTH_FILE: string;
|
|
9
|
+
declare const CODEX_AGENTS_FILE: string;
|
|
10
|
+
declare const CODEX_PROMPTS_DIR: string;
|
|
6
11
|
declare const ZCF_CONFIG_DIR: string;
|
|
7
12
|
declare const ZCF_CONFIG_FILE: string;
|
|
8
13
|
declare const LEGACY_ZCF_CONFIG_FILES: string[];
|
|
@@ -168,7 +173,6 @@ declare function applyAiLanguageDirective(aiOutputLang: AiOutputLanguage | strin
|
|
|
168
173
|
* Switch to official login mode - remove all third-party API configurations
|
|
169
174
|
* Removes: ANTHROPIC_BASE_URL, ANTHROPIC_AUTH_TOKEN, ANTHROPIC_API_KEY from settings.json
|
|
170
175
|
* Removes: primaryApiKey from ~/.claude/config.json
|
|
171
|
-
* Removes: hasCompletedOnboarding from ~/.claude.json
|
|
172
176
|
*/
|
|
173
177
|
declare function switchToOfficialLogin(): boolean;
|
|
174
178
|
/**
|
|
@@ -229,5 +233,5 @@ declare function importRecommendedEnv(): Promise<void>;
|
|
|
229
233
|
declare function importRecommendedPermissions(): Promise<void>;
|
|
230
234
|
declare function openSettingsJson(): Promise<void>;
|
|
231
235
|
|
|
232
|
-
export { AI_OUTPUT_LANGUAGES, API_DEFAULT_URL, API_ENV_KEY, CLAUDE_DIR, CLAUDE_MD_FILE, CLAUDE_VSC_CONFIG_FILE, CODE_TOOL_ALIASES, CODE_TOOL_BANNERS, CODE_TOOL_TYPES, ClAUDE_CONFIG_FILE, DEFAULT_CODE_TOOL_TYPE, LANG_LABELS, LEGACY_ZCF_CONFIG_FILES, SETTINGS_FILE, SUPPORTED_LANGS, ZCF_CONFIG_DIR, ZCF_CONFIG_FILE, addCompletedOnboarding, applyAiLanguageDirective, backupExistingConfig, backupMcpConfig, buildMcpServerConfig, cleanupPermissions, commandExists, configureApi, copyConfigFiles, ensureApiKeyApproved, ensureClaudeDir, fixWindowsMcpConfig, getAiOutputLanguageLabel, getExistingApiConfig, getExistingModelConfig, getInstallationStatus, getMcpConfigPath, getPlatform, importRecommendedEnv, importRecommendedPermissions, init, installClaudeCode, isClaudeCodeInstalled, isCodeToolType, isLocalClaudeCodeInstalled, manageApiKeyApproval, mergeAndCleanPermissions, mergeConfigs, mergeMcpServers, mergeSettingsFile, openSettingsJson, promptApiConfigurationAction, readMcpConfig, removeApiKeyFromRejected, removeLocalClaudeCode, resolveCodeToolType, setInstallMethod, setPrimaryApiKey, switchToOfficialLogin, updateCustomModel, updateDefaultModel, writeMcpConfig };
|
|
236
|
+
export { AI_OUTPUT_LANGUAGES, API_DEFAULT_URL, API_ENV_KEY, CLAUDE_DIR, CLAUDE_MD_FILE, CLAUDE_VSC_CONFIG_FILE, CODEX_AGENTS_FILE, CODEX_AUTH_FILE, CODEX_CONFIG_FILE, CODEX_DIR, CODEX_PROMPTS_DIR, CODE_TOOL_ALIASES, CODE_TOOL_BANNERS, CODE_TOOL_TYPES, ClAUDE_CONFIG_FILE, DEFAULT_CODE_TOOL_TYPE, LANG_LABELS, LEGACY_ZCF_CONFIG_FILES, SETTINGS_FILE, SUPPORTED_LANGS, ZCF_CONFIG_DIR, ZCF_CONFIG_FILE, addCompletedOnboarding, applyAiLanguageDirective, backupExistingConfig, backupMcpConfig, buildMcpServerConfig, cleanupPermissions, commandExists, configureApi, copyConfigFiles, ensureApiKeyApproved, ensureClaudeDir, fixWindowsMcpConfig, getAiOutputLanguageLabel, getExistingApiConfig, getExistingModelConfig, getInstallationStatus, getMcpConfigPath, getPlatform, importRecommendedEnv, importRecommendedPermissions, init, installClaudeCode, isClaudeCodeInstalled, isCodeToolType, isLocalClaudeCodeInstalled, manageApiKeyApproval, mergeAndCleanPermissions, mergeConfigs, mergeMcpServers, mergeSettingsFile, openSettingsJson, promptApiConfigurationAction, readMcpConfig, removeApiKeyFromRejected, removeLocalClaudeCode, resolveCodeToolType, setInstallMethod, setPrimaryApiKey, switchToOfficialLogin, updateCustomModel, updateDefaultModel, writeMcpConfig };
|
|
233
237
|
export type { AiOutputLanguage, ApiConfig, ClaudeConfiguration, CodeToolType, InstallationStatus, McpServerConfig, McpService, SupportedLang };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { z as AI_OUTPUT_LANGUAGES, A as API_DEFAULT_URL, v as API_ENV_KEY, C as CLAUDE_DIR, e as CLAUDE_MD_FILE, h as CLAUDE_VSC_CONFIG_FILE, n as CODEX_AGENTS_FILE, l as CODEX_AUTH_FILE, k as CODEX_CONFIG_FILE, j as CODEX_DIR, p as CODEX_PROMPTS_DIR, t as CODE_TOOL_ALIASES, s as CODE_TOOL_BANNERS, r as CODE_TOOL_TYPES, f as ClAUDE_CONFIG_FILE, D as DEFAULT_CODE_TOOL_TYPE, y as LANG_LABELS, L as LEGACY_ZCF_CONFIG_FILES, S as SETTINGS_FILE, x as SUPPORTED_LANGS, Z as ZCF_CONFIG_DIR, q as ZCF_CONFIG_FILE, M as addCompletedOnboarding, a1 as applyAiLanguageDirective, T as backupExistingConfig, H as backupMcpConfig, J as buildMcpServerConfig, c as cleanupPermissions, a as commandExists, V as configureApi, U as copyConfigFiles, N as ensureApiKeyApproved, R as ensureClaudeDir, K as fixWindowsMcpConfig, B as getAiOutputLanguageLabel, a0 as getExistingApiConfig, $ as getExistingModelConfig, a7 as getInstallationStatus, E as getMcpConfigPath, g as getPlatform, b as importRecommendedEnv, d as importRecommendedPermissions, i as init, a5 as installClaudeCode, a4 as isClaudeCodeInstalled, u as isCodeToolType, a6 as isLocalClaudeCodeInstalled, P as manageApiKeyApproval, m as mergeAndCleanPermissions, W as mergeConfigs, I as mergeMcpServers, _ as mergeSettingsFile, o as openSettingsJson, a3 as promptApiConfigurationAction, F as readMcpConfig, O as removeApiKeyFromRejected, a8 as removeLocalClaudeCode, w as resolveCodeToolType, a9 as setInstallMethod, Q as setPrimaryApiKey, a2 as switchToOfficialLogin, X as updateCustomModel, Y as updateDefaultModel, G as writeMcpConfig } from './chunks/simple-config.mjs';
|
|
2
2
|
import 'node:fs';
|
|
3
3
|
import 'node:process';
|
|
4
4
|
import 'ansis';
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zcf",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "3.3.
|
|
5
|
-
"description": "Zero-Config Code Flow - One-click configuration tool for
|
|
4
|
+
"version": "3.3.2",
|
|
5
|
+
"description": "Zero-Config Code Flow - One-click configuration tool for Code Cli",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Miao Da",
|
|
8
8
|
"email": "ufo025174@gmail.com",
|
|
@@ -18,12 +18,15 @@
|
|
|
18
18
|
"keywords": [
|
|
19
19
|
"claude",
|
|
20
20
|
"claude-code",
|
|
21
|
+
"codex",
|
|
21
22
|
"config",
|
|
22
23
|
"cli",
|
|
23
24
|
"setup",
|
|
24
25
|
"zero-config",
|
|
25
26
|
"zcf",
|
|
26
27
|
"anthropic",
|
|
28
|
+
"openai",
|
|
29
|
+
"ChatGPT",
|
|
27
30
|
"ai",
|
|
28
31
|
"automation",
|
|
29
32
|
"mcp"
|
|
@@ -99,6 +102,9 @@
|
|
|
99
102
|
"update:deps": "pnpx taze major -r -w",
|
|
100
103
|
"release": "pnpm build && changeset publish",
|
|
101
104
|
"commitlint": "commitlint",
|
|
102
|
-
"commitlint:check": "commitlint --from HEAD~1 --to HEAD --verbose"
|
|
105
|
+
"commitlint:check": "commitlint --from HEAD~1 --to HEAD --verbose",
|
|
106
|
+
"docs:dev": "pnpm -F @zcf/docs dev",
|
|
107
|
+
"docs:build": "pnpm -F @zcf/docs build",
|
|
108
|
+
"docs:preview": "pnpm -F @zcf/docs preview"
|
|
103
109
|
}
|
|
104
110
|
}
|
package/templates/CLAUDE.md
CHANGED