zcf 3.2.2 → 3.3.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 +131 -24
- package/dist/chunks/api-providers.mjs +76 -0
- package/dist/chunks/claude-code-config-manager.mjs +21 -7
- package/dist/chunks/claude-code-incremental-manager.mjs +59 -17
- package/dist/chunks/codex-config-switch.mjs +72 -13
- package/dist/chunks/codex-provider-manager.mjs +18 -8
- package/dist/chunks/codex-uninstaller.mjs +1 -1
- package/dist/chunks/commands.mjs +1 -1
- package/dist/chunks/features.mjs +637 -0
- package/dist/chunks/simple-config.mjs +192 -40
- package/dist/cli.mjs +28 -615
- package/dist/i18n/locales/en/api.json +6 -1
- package/dist/i18n/locales/en/common.json +0 -1
- package/dist/i18n/locales/en/errors.json +2 -1
- package/dist/i18n/locales/en/multi-config.json +2 -1
- package/dist/i18n/locales/zh-CN/api.json +6 -1
- package/dist/i18n/locales/zh-CN/common.json +0 -1
- package/dist/i18n/locales/zh-CN/errors.json +2 -1
- package/dist/i18n/locales/zh-CN/multi-config.json +2 -1
- package/dist/index.d.mts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/templates/CLAUDE.md +190 -0
- package/templates/claude-code/en/output-styles/engineer-professional.md +2 -1
- package/templates/claude-code/en/output-styles/laowang-engineer.md +1 -0
- package/templates/claude-code/en/output-styles/nekomata-engineer.md +1 -0
- package/templates/claude-code/en/output-styles/ojousama-engineer.md +1 -0
- package/templates/claude-code/zh-CN/output-styles/engineer-professional.md +2 -1
- package/templates/claude-code/zh-CN/output-styles/laowang-engineer.md +1 -0
- package/templates/claude-code/zh-CN/output-styles/nekomata-engineer.md +1 -0
- package/templates/claude-code/zh-CN/output-styles/ojousama-engineer.md +1 -0
- package/templates/codex/en/system-prompt/engineer-professional.md +2 -1
- package/templates/codex/en/system-prompt/laowang-engineer.md +1 -0
- package/templates/codex/en/system-prompt/nekomata-engineer.md +1 -0
- package/templates/codex/en/system-prompt/ojousama-engineer.md +1 -0
- package/templates/codex/zh-CN/system-prompt/engineer-professional.md +2 -1
- package/templates/codex/zh-CN/system-prompt/laowang-engineer.md +1 -0
- package/templates/codex/zh-CN/system-prompt/nekomata-engineer.md +1 -0
- package/templates/codex/zh-CN/system-prompt/ojousama-engineer.md +1 -0
package/README.md
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
# ZCF - Zero-Config Code Flow
|
|
2
|
-
|
|
3
1
|
[![npm version][npm-version-src]][npm-version-href]
|
|
4
2
|
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
5
3
|
[![License][license-src]][license-href]
|
|
@@ -8,13 +6,26 @@
|
|
|
8
6
|
[![JSDocs][jsdocs-src]][jsdocs-href]
|
|
9
7
|
[![Ask DeepWiki][deepwiki-src]][deepwiki-href]
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
<div align="center">
|
|
10
|
+
<img src="./src/assets/banner.webp" alt="Banner"/>
|
|
11
|
+
|
|
12
|
+
<h1>
|
|
13
|
+
ZCF - Zero-Config Code Flow
|
|
14
|
+
</h1>
|
|
15
|
+
|
|
16
|
+
<p align="center">
|
|
17
|
+
<b>English</b> | <a href="README_zh-CN.md">中文</a> | <a href="README_ja-JP.md">日本語</a> | <a href="CHANGELOG.md">Changelog</a>
|
|
12
18
|
|
|
13
19
|
**✨ Quick Links**: [Codex Support](#-codex-support-v300-new) | [BMad Workflow](#-bmad-workflow-v27-new-feature) | [Spec Workflow](#-spec-workflow-v2124-new-feature) | [Open Web Search](#-open-web-search-v2129-new-feature) | [CCR Router](#-ccr-claude-code-router-support-v28-enhanced) | [CCometixLine](#-ccometixline-support-status-bar-tool-v299-new) | [Output Styles](#-ai-output-styles-v212-new-feature) | [Multi-Configuration Management](#-multi-configuration-management-v320-new)
|
|
14
20
|
|
|
15
21
|
> Zero-config, one-click setup for Claude Code & Codex with bilingual support, intelligent agent system and personalized AI assistant
|
|
22
|
+
</p>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
## ♥️ Sponsor AI API
|
|
16
26
|
|
|
17
|
-
](https://share.302.ai/gAT9VG)
|
|
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.
|
|
18
29
|
|
|
19
30
|
## 🚀 Quick Start
|
|
20
31
|
|
|
@@ -100,14 +111,17 @@ npx zcf ccr --all-lang zh-CN # Configure CCR in Chinese
|
|
|
100
111
|
For CI/CD and automated setups, use `--skip-prompt` with parameters:
|
|
101
112
|
|
|
102
113
|
```bash
|
|
103
|
-
#
|
|
114
|
+
# Using API provider preset (v3.3.0+ New - Simplified)
|
|
115
|
+
npx zcf i -s -p 302ai -k "sk-xxx"
|
|
116
|
+
|
|
117
|
+
# Shorthand version (traditional)
|
|
104
118
|
npx zcf i -s -g zh-CN -t api_key -k "sk-xxx" -u "https://xxx.xxx"
|
|
105
119
|
|
|
106
|
-
# Complete version
|
|
120
|
+
# Complete version (traditional)
|
|
107
121
|
npx zcf i --skip-prompt --all-lang zh-CN --api-type api_key --api-key "sk-xxx" --api-url "https://xxx.xxx"
|
|
108
122
|
|
|
109
|
-
#
|
|
110
|
-
npx zcf i -s -
|
|
123
|
+
# Using provider preset with custom models
|
|
124
|
+
npx zcf i -s -p 302ai -k "sk-xxx" -M "claude-sonnet-4-5" -F "claude-haiku-4-5"
|
|
111
125
|
|
|
112
126
|
# Complete version (with custom models)
|
|
113
127
|
npx zcf i --skip-prompt \
|
|
@@ -118,6 +132,48 @@ npx zcf i --skip-prompt \
|
|
|
118
132
|
--api-fast-model "claude-haiku-4-5"
|
|
119
133
|
```
|
|
120
134
|
|
|
135
|
+
#### 🎯 API Provider Presets (v3.3.0+ New)
|
|
136
|
+
|
|
137
|
+
ZCF now supports API provider presets that automatically configure baseUrl and models, simplifying configuration from 5+ parameters to just 2:
|
|
138
|
+
|
|
139
|
+
**Supported Providers:**
|
|
140
|
+
- `302ai` - [302.AI](https://share.302.ai/gAT9VG) API Service
|
|
141
|
+
- `glm` - GLM (z.ai)
|
|
142
|
+
- `minimax` - MiniMax API Service
|
|
143
|
+
- `kimi` - Kimi (Moonshot AI)
|
|
144
|
+
- `custom` - Custom API endpoint (requires manual URL configuration)
|
|
145
|
+
|
|
146
|
+
**Usage Examples:**
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# Using 302.AI provider
|
|
150
|
+
npx zcf i --skip-prompt --provider 302ai --api-key "sk-xxx"
|
|
151
|
+
# or shorthand
|
|
152
|
+
npx zcf i -s -p 302ai -k "sk-xxx"
|
|
153
|
+
|
|
154
|
+
# Using GLM provider
|
|
155
|
+
npx zcf i -s -p glm -k "sk-xxx"
|
|
156
|
+
|
|
157
|
+
# Using MiniMax provider
|
|
158
|
+
npx zcf i -s -p minimax -k "sk-xxx"
|
|
159
|
+
|
|
160
|
+
# Using Kimi provider
|
|
161
|
+
npx zcf i -s -p kimi -k "sk-xxx"
|
|
162
|
+
|
|
163
|
+
# Using custom provider (requires URL)
|
|
164
|
+
npx zcf i -s -p custom -k "sk-xxx" -u "https://api.example.com"
|
|
165
|
+
|
|
166
|
+
# For Codex
|
|
167
|
+
npx zcf i -s -T cx -p 302ai -k "sk-xxx"
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**Benefits:**
|
|
171
|
+
- ✅ Automatic baseUrl configuration
|
|
172
|
+
- ✅ Automatic authType selection
|
|
173
|
+
- ✅ Automatic model configuration (if available)
|
|
174
|
+
- ✅ Reduces configuration from 5+ parameters to 2
|
|
175
|
+
- ✅ Supports both Claude Code and Codex
|
|
176
|
+
|
|
121
177
|
#### Non-interactive Mode Parameters
|
|
122
178
|
|
|
123
179
|
When using `--skip-prompt`, the following parameters are available:
|
|
@@ -125,16 +181,17 @@ When using `--skip-prompt`, the following parameters are available:
|
|
|
125
181
|
| Parameter | Description | Values | Required | Default |
|
|
126
182
|
| ---------------------------- | -------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
|
127
183
|
| `--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` | No | - (Simplifies configuration by auto-filling baseUrl and models) |
|
|
128
185
|
| `--lang, -l` | ZCF display language (applies to all commands) | `zh-CN`, `en` | No | `en` or user's saved preference |
|
|
129
186
|
| `--config-lang, -c` | Configuration language (template files language) | `zh-CN`, `en` | No | `en` |
|
|
130
187
|
| `--ai-output-lang, -a` | AI output language | `zh-CN`, `en`, custom string | No | `en` |
|
|
131
188
|
| `--all-lang, -g` | Set all language parameters (applies to all commands) | `zh-CN`, `en`, custom string | No | - (Priority: `--all-lang` > `--lang` > saved user preference > interactive prompt. Custom string sets AI output language to custom while interaction and config languages remain 'en') |
|
|
132
189
|
| `--config-action, -r` | Config handling | `new`, `backup`, `merge`, `docs-only`, `skip` | No | `backup` |
|
|
133
|
-
| `--api-type, -t` | API configuration type | `auth_token`, `api_key`, `ccr_proxy`, `skip` | No | `skip`
|
|
190
|
+
| `--api-type, -t` | API configuration type | `auth_token`, `api_key`, `ccr_proxy`, `skip` | No | `skip` (auto-set to `api_key` when `--provider` is specified) |
|
|
134
191
|
| `--api-key, -k` | API key (for both API key and auth token types) | string | Required when `api-type` is not `skip` | - |
|
|
135
|
-
| `--api-url, -u` | Custom API URL | URL string | No | official API
|
|
136
|
-
| `--api-model, -M` | Primary API model | string (e.g., `claude-sonnet-4-5`) | No | -
|
|
137
|
-
| `--api-fast-model, -F` | Fast API model (Claude Code only) | string (e.g., `claude-haiku-4-5`) | No | -
|
|
192
|
+
| `--api-url, -u` | Custom API URL | URL string | No | official API (auto-filled when using `--provider`) |
|
|
193
|
+
| `--api-model, -M` | Primary API model | string (e.g., `claude-sonnet-4-5`) | No | - (auto-filled when using `--provider` if available) |
|
|
194
|
+
| `--api-fast-model, -F` | Fast API model (Claude Code only) | string (e.g., `claude-haiku-4-5`) | No | - (auto-filled when using `--provider` if available) |
|
|
138
195
|
| `--mcp-services, -m` | MCP services to install (multi-select, comma-separated) | `context7`, `open-websearch`, `spec-workflow`, `mcp-deepwiki`, `Playwright`, `exa`, `serena`, or `skip` for none | No | `all` |
|
|
139
196
|
| `--workflows, -w` | Workflows to install (multi-select, comma-separated) | `commonTools`, `sixStepsWorkflow`, `featPlanUx`, `gitWorkflow`, `bmadWorkflow`, or `skip` for none | No | `all` |
|
|
140
197
|
| `--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` |
|
|
@@ -211,6 +268,13 @@ ZCF allows seamless switching between Claude Code and Codex while preserving you
|
|
|
211
268
|
|
|
212
269
|
ZCF now supports customizable AI output styles to personalize your Claude Code experience:
|
|
213
270
|
|
|
271
|
+
<p align="center">
|
|
272
|
+
<a href="https://github.com/Haleclipse">
|
|
273
|
+
<img src="./src/assets/Haleclipse.gif" alt="Halley-chan" width="200"/>
|
|
274
|
+
</a>
|
|
275
|
+
<div align="center">Tsundere <a href="https://github.com/Haleclipse">Halley-chan</a> Ojou-sama ( ̄▽ ̄)ゞ</div>
|
|
276
|
+
</p>
|
|
277
|
+
|
|
214
278
|
**Available Output Styles:**
|
|
215
279
|
|
|
216
280
|
- `engineer-professional`: Professional software engineer following SOLID, KISS, DRY, YAGNI principles
|
|
@@ -384,12 +448,35 @@ After configuration:
|
|
|
384
448
|
|
|
385
449
|
### 🔐 API Configuration
|
|
386
450
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
-
|
|
451
|
+
ZCF provides flexible API configuration options for both Claude Code and Codex:
|
|
452
|
+
|
|
453
|
+
**Quick Setup with API Provider Presets (v3.3.0+ New):**
|
|
454
|
+
|
|
455
|
+
Choose from popular API providers with pre-configured settings:
|
|
456
|
+
- **302.AI** - Pay-as-you-go AI service with comprehensive model support
|
|
457
|
+
- **GLM (智谱AI)** - Zhipu AI's GLM models
|
|
458
|
+
- **MiniMax** - MiniMax AI service
|
|
459
|
+
- **Kimi (Moonshot AI)** - Moonshot's Kimi models
|
|
460
|
+
- **Custom Configuration** - Full manual configuration for any provider
|
|
461
|
+
|
|
462
|
+
When using a preset provider, you only need to:
|
|
463
|
+
1. Select the provider from the list
|
|
464
|
+
2. Enter your API key
|
|
465
|
+
|
|
466
|
+
The system automatically configures:
|
|
467
|
+
- API base URL
|
|
468
|
+
- Authentication type (API Key or Auth Token)
|
|
469
|
+
- Default models (if applicable)
|
|
470
|
+
- Wire API protocol (for Codex)
|
|
471
|
+
|
|
472
|
+
**Traditional Configuration Methods:**
|
|
473
|
+
|
|
474
|
+
- **Official Login**: Use official authentication system (no API configuration needed)
|
|
475
|
+
- **Auth Token**: For tokens obtained via OAuth or browser login
|
|
476
|
+
- **API Key**: For API keys from Anthropic Console or custom providers
|
|
477
|
+
- **CCR Proxy**: Configure Claude Code Router proxy
|
|
478
|
+
- **Custom API URL**: Support for any compatible API endpoint
|
|
479
|
+
- **Partial Modification**: Update only needed configuration items (v2.0+)
|
|
393
480
|
|
|
394
481
|
### 💾 Configuration Management
|
|
395
482
|
|
|
@@ -823,15 +910,26 @@ If you find this project helpful, please consider sponsoring its development. Yo
|
|
|
823
910
|
### Our Sponsors
|
|
824
911
|
|
|
825
912
|
A huge thank you to all our sponsors for their generous support!
|
|
826
|
-
|
|
913
|
+
- [302.AI](https://share.302.ai/gAT9VG) (first corporate sponsorship 🤠)
|
|
827
914
|
- Tc (first sponsor)
|
|
828
915
|
- Argolinhas (first ko-fi sponsor ٩(•̤̀ᵕ•̤́๑))
|
|
829
|
-
- r\*r (first anonymous sponsor🤣)
|
|
830
|
-
- \*\*康 (first KFC sponsor🍗)
|
|
831
|
-
- \*东 (first coffee sponsor☕️)
|
|
832
|
-
- 炼\*3 (first Termux user sponsor📱)
|
|
916
|
+
- r\*r (first anonymous sponsor 🤣)
|
|
917
|
+
- \*\*康 (first KFC sponsor 🍗)
|
|
918
|
+
- \*东 (first coffee sponsor ☕️)
|
|
919
|
+
- 炼\*3 (first Termux user sponsor 📱)
|
|
833
920
|
- [chamo101](https://github.com/chamo101) (first GitHub issue sponsor 🎉)
|
|
834
|
-
-
|
|
921
|
+
- 初屿贤 (first Codex user sponsor 🙅🏻♂️)
|
|
922
|
+
- Protein (first 1688 sponsor 😏)
|
|
923
|
+
- [BeatSeat](https://github.com/BeatSeat) (community expert 😎, provided $1000 Claude credits)
|
|
924
|
+
- [wenwen](https://github.com/wenwen12345) (community expert 🤓, provided daily $100 Claude&GPT credits)
|
|
925
|
+
- 16°C coffee (My best friend 🤪, offered ChatGPT Pro $200 package)
|
|
926
|
+
|
|
927
|
+
### Promotion Thanks
|
|
928
|
+
|
|
929
|
+
Thanks to the following authors for promoting this project:
|
|
930
|
+
|
|
931
|
+
- 逛逛 GitHub, article: https://mp.weixin.qq.com/s/phqwSRb16MKCHHVozTFeiQ
|
|
932
|
+
- Geek, tweet: https://x.com/geekbb/status/1955174718618866076
|
|
835
933
|
|
|
836
934
|
## 📄 License
|
|
837
935
|
|
|
@@ -839,6 +937,15 @@ A huge thank you to all our sponsors for their generous support!
|
|
|
839
937
|
|
|
840
938
|
---
|
|
841
939
|
|
|
940
|
+
## 🚀 Contributors
|
|
941
|
+
|
|
942
|
+
<a href="https://github.com/UfoMiao/zcf/graphs/contributors">
|
|
943
|
+
<img src="https://contrib.rocks/image?repo=UfoMiao/zcf" />
|
|
944
|
+
</a>
|
|
945
|
+
<br /><br />
|
|
946
|
+
|
|
947
|
+
## ⭐️ Star History
|
|
948
|
+
|
|
842
949
|
If this project helps you, please give me a ⭐️ Star!
|
|
843
950
|
|
|
844
951
|
[](https://star-history.com/#UfoMiao/zcf&Date)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
const API_PROVIDER_PRESETS = [
|
|
2
|
+
{
|
|
3
|
+
id: "302ai",
|
|
4
|
+
name: "302.AI",
|
|
5
|
+
supportedCodeTools: ["claude-code", "codex"],
|
|
6
|
+
claudeCode: {
|
|
7
|
+
baseUrl: "https://api.302.ai/cc",
|
|
8
|
+
authType: "api_key"
|
|
9
|
+
},
|
|
10
|
+
codex: {
|
|
11
|
+
baseUrl: "https://api.302.ai/v1",
|
|
12
|
+
wireApi: "responses"
|
|
13
|
+
},
|
|
14
|
+
description: "302.AI API Service"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
id: "glm",
|
|
18
|
+
name: "GLM",
|
|
19
|
+
supportedCodeTools: ["claude-code", "codex"],
|
|
20
|
+
claudeCode: {
|
|
21
|
+
baseUrl: "https://open.bigmodel.cn/api/anthropic",
|
|
22
|
+
authType: "auth_token"
|
|
23
|
+
},
|
|
24
|
+
codex: {
|
|
25
|
+
baseUrl: "https://open.bigmodel.cn/api/coding/paas/v4",
|
|
26
|
+
wireApi: "chat",
|
|
27
|
+
defaultModel: "GLM-4.6"
|
|
28
|
+
},
|
|
29
|
+
description: "GLM (\u667A\u8C31AI)"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: "minimax",
|
|
33
|
+
name: "MiniMax",
|
|
34
|
+
supportedCodeTools: ["claude-code", "codex"],
|
|
35
|
+
claudeCode: {
|
|
36
|
+
baseUrl: "https://api.minimaxi.com/anthropic",
|
|
37
|
+
authType: "auth_token",
|
|
38
|
+
defaultModels: ["MiniMax-M2", "MiniMax-M2"]
|
|
39
|
+
},
|
|
40
|
+
codex: {
|
|
41
|
+
baseUrl: "https://api.minimaxi.com/v1",
|
|
42
|
+
wireApi: "chat",
|
|
43
|
+
defaultModel: "MiniMax-M2"
|
|
44
|
+
},
|
|
45
|
+
description: "MiniMax API Service"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: "kimi",
|
|
49
|
+
name: "Kimi",
|
|
50
|
+
supportedCodeTools: ["claude-code", "codex"],
|
|
51
|
+
claudeCode: {
|
|
52
|
+
baseUrl: "https://api.moonshot.cn/anthropic",
|
|
53
|
+
authType: "auth_token",
|
|
54
|
+
defaultModels: ["kimi-k2-0905-preview", "kimi-k2-turbo-preview"]
|
|
55
|
+
},
|
|
56
|
+
codex: {
|
|
57
|
+
baseUrl: "https://api.moonshot.cn/v1",
|
|
58
|
+
wireApi: "chat",
|
|
59
|
+
defaultModel: "kimi-k2-0905-preview"
|
|
60
|
+
},
|
|
61
|
+
description: "Kimi (Moonshot AI)"
|
|
62
|
+
}
|
|
63
|
+
];
|
|
64
|
+
function getApiProviders(codeToolType) {
|
|
65
|
+
return API_PROVIDER_PRESETS.filter(
|
|
66
|
+
(provider) => provider.supportedCodeTools.includes(codeToolType)
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
function getProviderPreset(providerId) {
|
|
70
|
+
return API_PROVIDER_PRESETS.find((provider) => provider.id === providerId);
|
|
71
|
+
}
|
|
72
|
+
function getValidProviderIds() {
|
|
73
|
+
return API_PROVIDER_PRESETS.map((provider) => provider.id);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export { API_PROVIDER_PRESETS, getApiProviders, getProviderPreset, getValidProviderIds };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import dayjs from 'dayjs';
|
|
2
2
|
import { join } from 'pathe';
|
|
3
|
-
import { j as ZCF_CONFIG_FILE, Z as ZCF_CONFIG_DIR,
|
|
3
|
+
import { j as ZCF_CONFIG_FILE, Z as ZCF_CONFIG_DIR, a9 as ensureDir, aa as readDefaultTomlConfig, ab as createDefaultTomlConfig, ac as exists, ad as readJsonConfig, ae as writeTomlConfig, S as SETTINGS_FILE, af 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.a$; });
|
|
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.b3; });
|
|
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.b1; });
|
|
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.b4; });
|
|
206
206
|
const ccrConfig = readCcrConfig();
|
|
207
207
|
if (!ccrConfig) {
|
|
208
208
|
throw new Error(i18n.t("ccr:ccrNotConfigured") || "CCR proxy configuration not found");
|
|
@@ -221,8 +221,18 @@ class ClaudeCodeConfigManager {
|
|
|
221
221
|
else
|
|
222
222
|
delete settings.env.ANTHROPIC_BASE_URL;
|
|
223
223
|
}
|
|
224
|
+
if (profile.primaryModel) {
|
|
225
|
+
settings.env.ANTHROPIC_MODEL = profile.primaryModel;
|
|
226
|
+
} else {
|
|
227
|
+
delete settings.env.ANTHROPIC_MODEL;
|
|
228
|
+
}
|
|
229
|
+
if (profile.fastModel) {
|
|
230
|
+
settings.env.ANTHROPIC_SMALL_FAST_MODEL = profile.fastModel;
|
|
231
|
+
} else {
|
|
232
|
+
delete settings.env.ANTHROPIC_SMALL_FAST_MODEL;
|
|
233
|
+
}
|
|
224
234
|
writeJsonConfig(SETTINGS_FILE, settings);
|
|
225
|
-
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.b2; });
|
|
226
236
|
setPrimaryApiKey();
|
|
227
237
|
addCompletedOnboarding();
|
|
228
238
|
if (shouldRestartCcr) {
|
|
@@ -250,6 +260,10 @@ class ClaudeCodeConfigManager {
|
|
|
250
260
|
sanitized.apiKey = profile.apiKey;
|
|
251
261
|
if (profile.baseUrl)
|
|
252
262
|
sanitized.baseUrl = profile.baseUrl;
|
|
263
|
+
if (profile.primaryModel)
|
|
264
|
+
sanitized.primaryModel = profile.primaryModel;
|
|
265
|
+
if (profile.fastModel)
|
|
266
|
+
sanitized.fastModel = profile.fastModel;
|
|
253
267
|
return sanitized;
|
|
254
268
|
}
|
|
255
269
|
/**
|
|
@@ -575,7 +589,7 @@ class ClaudeCodeConfigManager {
|
|
|
575
589
|
*/
|
|
576
590
|
static async syncCcrProfile() {
|
|
577
591
|
try {
|
|
578
|
-
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.b4; });
|
|
579
593
|
const ccrConfig = readCcrConfig();
|
|
580
594
|
if (!ccrConfig) {
|
|
581
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 { a5 as ensureI18nInitialized, a6 as i18n, a7 as addNumbersToChoices, a8 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';
|
|
@@ -85,17 +85,40 @@ async function promptContinueAdding() {
|
|
|
85
85
|
async function handleAddProfile() {
|
|
86
86
|
console.log(ansis.cyan(`
|
|
87
87
|
${i18n.t("multi-config:addingNewProfile")}`));
|
|
88
|
+
const { getApiProviders } = await import('./api-providers.mjs');
|
|
89
|
+
const providers = getApiProviders("claude-code");
|
|
90
|
+
const providerChoices = [
|
|
91
|
+
{ name: i18n.t("api:customProvider"), value: "custom" },
|
|
92
|
+
...providers.map((p) => ({ name: p.name, value: p.id }))
|
|
93
|
+
];
|
|
94
|
+
const { selectedProvider } = await inquirer.prompt([{
|
|
95
|
+
type: "list",
|
|
96
|
+
name: "selectedProvider",
|
|
97
|
+
message: i18n.t("api:selectApiProvider"),
|
|
98
|
+
choices: addNumbersToChoices(providerChoices)
|
|
99
|
+
}]);
|
|
100
|
+
let prefilledBaseUrl;
|
|
101
|
+
let prefilledAuthType;
|
|
102
|
+
if (selectedProvider !== "custom") {
|
|
103
|
+
const provider = providers.find((p) => p.id === selectedProvider);
|
|
104
|
+
if (provider?.claudeCode) {
|
|
105
|
+
prefilledBaseUrl = provider.claudeCode.baseUrl;
|
|
106
|
+
prefilledAuthType = provider.claudeCode.authType;
|
|
107
|
+
console.log(ansis.gray(i18n.t("api:providerSelected", { name: provider.name })));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
88
110
|
const answers = await inquirer.prompt([
|
|
89
111
|
{
|
|
90
112
|
type: "input",
|
|
91
113
|
name: "profileName",
|
|
92
114
|
message: i18n.t("multi-config:profileNamePrompt"),
|
|
115
|
+
default: selectedProvider !== "custom" ? providers.find((p) => p.id === selectedProvider)?.name : void 0,
|
|
93
116
|
validate: (input) => {
|
|
94
117
|
const trimmed = input.trim();
|
|
95
118
|
if (!trimmed) {
|
|
96
119
|
return i18n.t("multi-config:profileNameRequired");
|
|
97
120
|
}
|
|
98
|
-
if (!/^[\w\-\s
|
|
121
|
+
if (!/^[\w\-\s.\u4E00-\u9FA5]+$/.test(trimmed)) {
|
|
99
122
|
return i18n.t("multi-config:profileNameInvalid");
|
|
100
123
|
}
|
|
101
124
|
return true;
|
|
@@ -109,14 +132,16 @@ ${i18n.t("multi-config:addingNewProfile")}`));
|
|
|
109
132
|
{ name: i18n.t("multi-config:authType.api_key"), value: "api_key" },
|
|
110
133
|
{ name: i18n.t("multi-config:authType.auth_token"), value: "auth_token" }
|
|
111
134
|
],
|
|
112
|
-
default: "api_key"
|
|
135
|
+
default: prefilledAuthType || "api_key",
|
|
136
|
+
when: () => selectedProvider === "custom"
|
|
137
|
+
// Only ask if custom
|
|
113
138
|
},
|
|
114
139
|
{
|
|
115
140
|
type: "input",
|
|
116
141
|
name: "baseUrl",
|
|
117
142
|
message: i18n.t("multi-config:baseUrlPrompt"),
|
|
118
|
-
default: "https://api.anthropic.com",
|
|
119
|
-
when: (answers2) => answers2.authType !== "ccr_proxy",
|
|
143
|
+
default: prefilledBaseUrl || "https://api.anthropic.com",
|
|
144
|
+
when: (answers2) => selectedProvider === "custom" && answers2.authType !== "ccr_proxy",
|
|
120
145
|
validate: (input) => {
|
|
121
146
|
const trimmed = input.trim();
|
|
122
147
|
if (!trimmed) {
|
|
@@ -131,10 +156,10 @@ ${i18n.t("multi-config:addingNewProfile")}`));
|
|
|
131
156
|
}
|
|
132
157
|
},
|
|
133
158
|
{
|
|
134
|
-
type: "
|
|
159
|
+
type: "input",
|
|
135
160
|
name: "apiKey",
|
|
136
|
-
message: i18n.t("
|
|
137
|
-
when: (answers2) => answers2.authType !== "ccr_proxy",
|
|
161
|
+
message: selectedProvider !== "custom" ? i18n.t("api:enterProviderApiKey", { provider: providers.find((p) => p.id === selectedProvider)?.name || selectedProvider }) : i18n.t("multi-config:apiKeyPrompt"),
|
|
162
|
+
when: (answers2) => selectedProvider === "custom" ? answers2.authType !== "ccr_proxy" : true,
|
|
138
163
|
validate: (input) => {
|
|
139
164
|
const trimmed = input.trim();
|
|
140
165
|
if (!trimmed) {
|
|
@@ -146,7 +171,14 @@ ${i18n.t("multi-config:addingNewProfile")}`));
|
|
|
146
171
|
}
|
|
147
172
|
return true;
|
|
148
173
|
}
|
|
149
|
-
}
|
|
174
|
+
}
|
|
175
|
+
]);
|
|
176
|
+
let modelConfig = null;
|
|
177
|
+
if (selectedProvider === "custom") {
|
|
178
|
+
const { promptCustomModels } = await import('./features.mjs');
|
|
179
|
+
modelConfig = await promptCustomModels();
|
|
180
|
+
}
|
|
181
|
+
const { setAsDefault } = await inquirer.prompt([
|
|
150
182
|
{
|
|
151
183
|
type: "confirm",
|
|
152
184
|
name: "setAsDefault",
|
|
@@ -159,11 +191,19 @@ ${i18n.t("multi-config:addingNewProfile")}`));
|
|
|
159
191
|
const profile = {
|
|
160
192
|
id: profileId,
|
|
161
193
|
name: profileName,
|
|
162
|
-
authType: answers.authType
|
|
194
|
+
authType: selectedProvider === "custom" ? answers.authType : prefilledAuthType
|
|
163
195
|
};
|
|
164
|
-
if (
|
|
196
|
+
if (profile.authType !== "ccr_proxy") {
|
|
165
197
|
profile.apiKey = answers.apiKey.trim();
|
|
166
|
-
profile.baseUrl = answers.baseUrl.trim();
|
|
198
|
+
profile.baseUrl = selectedProvider === "custom" ? answers.baseUrl.trim() : prefilledBaseUrl;
|
|
199
|
+
}
|
|
200
|
+
if (modelConfig) {
|
|
201
|
+
if (modelConfig.primaryModel.trim()) {
|
|
202
|
+
profile.primaryModel = modelConfig.primaryModel.trim();
|
|
203
|
+
}
|
|
204
|
+
if (modelConfig.fastModel.trim()) {
|
|
205
|
+
profile.fastModel = modelConfig.fastModel.trim();
|
|
206
|
+
}
|
|
167
207
|
}
|
|
168
208
|
const existingProfile = ClaudeCodeConfigManager.getProfileByName(profile.name);
|
|
169
209
|
if (existingProfile) {
|
|
@@ -188,14 +228,16 @@ ${i18n.t("multi-config:addingNewProfile")}`));
|
|
|
188
228
|
name: profile.name,
|
|
189
229
|
authType: profile.authType,
|
|
190
230
|
apiKey: profile.apiKey,
|
|
191
|
-
baseUrl: profile.baseUrl
|
|
231
|
+
baseUrl: profile.baseUrl,
|
|
232
|
+
primaryModel: profile.primaryModel,
|
|
233
|
+
fastModel: profile.fastModel
|
|
192
234
|
});
|
|
193
235
|
if (updateResult.success) {
|
|
194
236
|
console.log(ansis.green(i18n.t("multi-config:profileUpdated", { name: profile.name })));
|
|
195
237
|
if (updateResult.backupPath) {
|
|
196
238
|
console.log(ansis.gray(i18n.t("common:backupCreated", { path: updateResult.backupPath })));
|
|
197
239
|
}
|
|
198
|
-
if (
|
|
240
|
+
if (setAsDefault) {
|
|
199
241
|
const switchResult = await ClaudeCodeConfigManager.switchProfile(existingProfile.id);
|
|
200
242
|
if (switchResult.success) {
|
|
201
243
|
console.log(ansis.green(i18n.t("multi-config:profileSetAsDefault", { name: profile.name })));
|
|
@@ -213,7 +255,7 @@ ${i18n.t("multi-config:addingNewProfile")}`));
|
|
|
213
255
|
if (result.backupPath) {
|
|
214
256
|
console.log(ansis.gray(i18n.t("common:backupCreated", { path: result.backupPath })));
|
|
215
257
|
}
|
|
216
|
-
if (
|
|
258
|
+
if (setAsDefault) {
|
|
217
259
|
const switchResult = await ClaudeCodeConfigManager.switchProfile(runtimeProfile.id);
|
|
218
260
|
if (switchResult.success) {
|
|
219
261
|
console.log(ansis.green(i18n.t("multi-config:profileSetAsDefault", { name: runtimeProfile.name })));
|
|
@@ -288,9 +330,9 @@ ${i18n.t("multi-config:editingProfile", { name: selectedProfile.name })}`));
|
|
|
288
330
|
}
|
|
289
331
|
},
|
|
290
332
|
{
|
|
291
|
-
type: "
|
|
333
|
+
type: "input",
|
|
292
334
|
name: "apiKey",
|
|
293
|
-
message: i18n.t("multi-config:apiKeyPrompt")
|
|
335
|
+
message: i18n.t("multi-config:apiKeyPrompt"),
|
|
294
336
|
default: selectedProfile.apiKey,
|
|
295
337
|
when: () => selectedProfile.authType !== "ccr_proxy",
|
|
296
338
|
validate: (input) => {
|