cckit 0.2.0 → 0.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 +182 -24
- package/dist/commands.d.ts +4 -0
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +216 -15
- package/dist/commands.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +27 -1
- package/dist/config.js.map +1 -1
- package/dist/i18n.d.ts +1 -0
- package/dist/i18n.d.ts.map +1 -1
- package/dist/i18n.js +18 -11
- package/dist/i18n.js.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts.map +1 -1
- package/dist/providers.js +27 -5
- package/dist/providers.js.map +1 -1
- package/dist/proxy-manager.d.ts +38 -0
- package/dist/proxy-manager.d.ts.map +1 -0
- package/dist/proxy-manager.js +1 -0
- package/dist/proxy-manager.js.map +1 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/constants.d.ts +1 -1
- package/dist/utils/constants.js +1 -1
- package/dist/utils/helpers.d.ts.map +1 -1
- package/dist/utils/helpers.js +9 -7
- package/dist/utils/helpers.js.map +1 -1
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# cckit (Node.js Edition)
|
|
2
2
|
|
|
3
|
-
Code Kit for Claude Model Switching - Support 智谱
|
|
3
|
+
Code Kit for Claude Model Switching - Support 智谱 Coding Plan, MiniMax Coding Plan, Kimi Coding Plan, 快手 StreamLake Coding Plan, 火山引擎 Coding Plan, ZenMux.ai, and official Claude
|
|
4
4
|
|
|
5
5
|
A CLI tool for managing and switching between different Claude model providers and their configurations. Features support for model gateways like ZenMux.ai and Kuaishou StreamLake that provide unified access to multiple AI providers.
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
|
-
- **Multiple Provider Support**: Configure and switch between 智谱
|
|
9
|
+
- **Multiple Provider Support**: Configure and switch between 智谱 Coding Plan, MiniMax Coding Plan, Kimi Coding Plan, 快手 StreamLake Coding Plan, 火山引擎 Coding Plan, 阿里云 Coding Plan, 腾讯云 Coding Plan, 讯飞 Coding Plan, ZenMux.ai, official Claude, and custom providers
|
|
10
10
|
- **Easy Configuration**: Simple command-line interface for managing API keys and settings
|
|
11
11
|
- **Claude Integration**: Automatically updates Claude Code configuration files
|
|
12
12
|
- **Export/Import**: Backup and restore your provider configurations
|
|
@@ -26,6 +26,129 @@ pnpm add -g cckit
|
|
|
26
26
|
yarn global add cckit
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
+
## Quick Start (Interactive Mode)
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# Start interactive configuration wizard (recommended for first-time users)
|
|
33
|
+
cckit interactive
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Interactive Mode Details
|
|
37
|
+
|
|
38
|
+
The interactive wizard (`cckit interactive`) provides a user-friendly, step-by-step configuration experience with arrow key selection:
|
|
39
|
+
|
|
40
|
+
### Step-by-Step Guide
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
▸ Step 1: 选择要配置的 AI 提供商
|
|
44
|
+
```
|
|
45
|
+
Use ↑/↓ arrow keys to select from:
|
|
46
|
+
- **Preset Providers**: 智谱 Coding Plan, MiniMax Coding Plan, Kimi Coding Plan, ZenMux, 快手 StreamLake Coding Plan, 火山引擎 Coding Plan, 阿里云 Coding Plan, 腾讯云 Coding Plan, 讯飞 Coding Plan, Claude
|
|
47
|
+
- **Custom Provider**: For local LLMs (Ollama, LocalAI, LM Studio) or any OpenAI-compatible API
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
▸ Step 2: 配置 [Provider Name]
|
|
51
|
+
```
|
|
52
|
+
- Enter your API key (required)
|
|
53
|
+
- For custom providers: Enter the base URL (e.g., `http://localhost:11434/v1`)
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
▸ Step 3: 设置模型
|
|
57
|
+
```
|
|
58
|
+
- Enter the model name (default value provided based on provider)
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
▸ Step 4: 保存配置
|
|
62
|
+
```
|
|
63
|
+
- If existing configurations found, choose to update or create new
|
|
64
|
+
- Configuration saved to `~/.cckit/config.json`
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
▸ Step 5: 测试连接
|
|
68
|
+
```
|
|
69
|
+
- Optional: Test the connection to verify API key and endpoint
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
▸ Step 6: 切换 Provider
|
|
73
|
+
```
|
|
74
|
+
- Optional: Switch to the newly configured provider immediately
|
|
75
|
+
|
|
76
|
+
### Features
|
|
77
|
+
|
|
78
|
+
- **Arrow Key Navigation**: Easy selection with keyboard
|
|
79
|
+
- **Smart Defaults**: Pre-filled model names based on provider
|
|
80
|
+
- **Existing Config Detection**: Detects and offers to update existing configurations
|
|
81
|
+
- **Connection Testing**: Verify setup before switching
|
|
82
|
+
- **Immediate Switch**: Option to activate the provider right away
|
|
83
|
+
|
|
84
|
+
### Example Session
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
$ cckit interactive
|
|
88
|
+
|
|
89
|
+
___ ___ / ___ ( ) __ ___
|
|
90
|
+
// ) ) // ) ) //\ \ / / / /
|
|
91
|
+
// // // \ \ / / / /
|
|
92
|
+
((____ ((____ // \ \ / / / /
|
|
93
|
+
交互式配置向导
|
|
94
|
+
|
|
95
|
+
▸ Step 1: 选择要配置的 AI 提供商
|
|
96
|
+
|
|
97
|
+
? 请选择提供商: (Use arrow keys)
|
|
98
|
+
❯ 智谱 Coding Plan (GLM)
|
|
99
|
+
MiniMax Coding Plan
|
|
100
|
+
Kimi Coding Plan
|
|
101
|
+
ZenMux.ai
|
|
102
|
+
快手 StreamLake Coding Plan
|
|
103
|
+
火山引擎 Coding Plan
|
|
104
|
+
阿里云 Coding Plan
|
|
105
|
+
腾讯云 Coding Plan
|
|
106
|
+
讯飞 Coding Plan
|
|
107
|
+
Claude (Official)
|
|
108
|
+
自定义 Provider (Local LLM / OpenAI Compatible)
|
|
109
|
+
|
|
110
|
+
▸ Step 2: 配置 智谱 Coding Plan
|
|
111
|
+
|
|
112
|
+
? 请输入 API Key: [your-api-key]
|
|
113
|
+
|
|
114
|
+
▸ Step 3: 设置模型
|
|
115
|
+
|
|
116
|
+
? 请输入模型名称: (GLM-4.7)
|
|
117
|
+
|
|
118
|
+
▸ Step 4: 保存配置
|
|
119
|
+
|
|
120
|
+
✓ 配置已保存 (id: zhipu_xxx)
|
|
121
|
+
Provider: 智谱 Coding Plan
|
|
122
|
+
Model: GLM-4.7
|
|
123
|
+
|
|
124
|
+
▸ Step 5: 测试连接
|
|
125
|
+
|
|
126
|
+
? 是否测试连接? (Y/n)
|
|
127
|
+
|
|
128
|
+
✓ 连接成功!
|
|
129
|
+
响应时间: 234ms
|
|
130
|
+
|
|
131
|
+
▸ Step 6: 切换 Provider
|
|
132
|
+
|
|
133
|
+
? 是否立即切换到该 Provider? (Y/n)
|
|
134
|
+
|
|
135
|
+
✓ 已切换到 智谱 Coding Plan
|
|
136
|
+
请重启终端或新开会话以使配置生效
|
|
137
|
+
|
|
138
|
+
___ ___ / ___ ( ) __ ___
|
|
139
|
+
// ) ) // ) ) //\ \ / / / /
|
|
140
|
+
// // // \ \ / / / /
|
|
141
|
+
((____ ((____ // \ \ / / / /
|
|
142
|
+
配置完成! ✓
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The interactive wizard will guide you through:
|
|
146
|
+
1. Selecting an AI provider (智谱 Coding Plan, MiniMax Coding Plan, Kimi Coding Plan, Claude, ZenMux, 快手 StreamLake Coding Plan, 火山引擎 Coding Plan, 阿里云 Coding Plan, 腾讯云 Coding Plan, 讯飞 Coding Plan, or Custom)
|
|
147
|
+
2. Entering your API key
|
|
148
|
+
3. Setting up the model name
|
|
149
|
+
4. Testing the connection
|
|
150
|
+
5. Switching to the configured provider
|
|
151
|
+
|
|
29
152
|
## Usage
|
|
30
153
|
|
|
31
154
|
### Basic Commands
|
|
@@ -67,9 +190,9 @@ cckit remove-model <provider> <model>
|
|
|
67
190
|
|
|
68
191
|
### Supported Providers
|
|
69
192
|
|
|
70
|
-
#### 智谱
|
|
193
|
+
#### 智谱 Coding Plan - [https://www.bigmodel.cn/claude-code?ic=AFDPNDPWIF](https://www.bigmodel.cn/claude-code?ic=AFDPNDPWIF)
|
|
71
194
|
```bash
|
|
72
|
-
# Configure 智谱
|
|
195
|
+
# Configure 智谱 Coding Plan with a single model
|
|
73
196
|
cckit configure zhipu --api-key "your-api-key" --model "GLM-4.7"
|
|
74
197
|
|
|
75
198
|
# Configure with multiple models
|
|
@@ -84,13 +207,13 @@ cckit set-model zhipu "GLM-4-Plus"
|
|
|
84
207
|
# Remove a model
|
|
85
208
|
cckit remove-model zhipu "GLM-4.7"
|
|
86
209
|
|
|
87
|
-
# Switch to 智谱
|
|
210
|
+
# Switch to 智谱 Coding Plan
|
|
88
211
|
cckit switch zhipu
|
|
89
212
|
```
|
|
90
213
|
|
|
91
|
-
#### MiniMax - [https://platform.minimaxi.com/subscribe/coding-plan](https://platform.minimaxi.com/subscribe/coding-plan?code=3FiunKqPhD&source=link)
|
|
214
|
+
#### MiniMax Coding Plan - [https://platform.minimaxi.com/subscribe/coding-plan](https://platform.minimaxi.com/subscribe/coding-plan?code=3FiunKqPhD&source=link)
|
|
92
215
|
```bash
|
|
93
|
-
# Configure MiniMax with multiple models
|
|
216
|
+
# Configure MiniMax Coding Plan with multiple models
|
|
94
217
|
cckit configure minimax --api-key "your-api-key" --model "MiniMax-M2" --model "MiniMax-M4"
|
|
95
218
|
|
|
96
219
|
# List models
|
|
@@ -102,13 +225,13 @@ cckit set-model minimax "MiniMax-M4"
|
|
|
102
225
|
# Remove a model
|
|
103
226
|
cckit remove-model minimax "MiniMax-M2"
|
|
104
227
|
|
|
105
|
-
# Switch to MiniMax
|
|
228
|
+
# Switch to MiniMax Coding Plan
|
|
106
229
|
cckit switch minimax
|
|
107
230
|
```
|
|
108
231
|
|
|
109
|
-
#### Kimi
|
|
232
|
+
#### Kimi Coding Plan - [https://www.kimi.com/coding/docs/](https://www.kimi.com/coding/docs/)
|
|
110
233
|
```bash
|
|
111
|
-
# Configure Kimi with multiple models
|
|
234
|
+
# Configure Kimi Coding Plan with multiple models
|
|
112
235
|
cckit configure kimi --api-key "your-api-key" --model "kimi-for-coding" --model "kimi-plus"
|
|
113
236
|
|
|
114
237
|
# List models
|
|
@@ -117,7 +240,7 @@ cckit models kimi
|
|
|
117
240
|
# Set active model
|
|
118
241
|
cckit set-model kimi "kimi-plus"
|
|
119
242
|
|
|
120
|
-
# Switch to Kimi
|
|
243
|
+
# Switch to Kimi Coding Plan
|
|
121
244
|
cckit switch kimi
|
|
122
245
|
```
|
|
123
246
|
|
|
@@ -151,9 +274,9 @@ cckit set-model claude "claude-3-opus-20250219"
|
|
|
151
274
|
cckit switch claude
|
|
152
275
|
```
|
|
153
276
|
|
|
154
|
-
####
|
|
277
|
+
#### 快手 StreamLake Coding Plan - [快手万擎引擎](https://streamlake.com/marketing/coding-plan)
|
|
155
278
|
```bash
|
|
156
|
-
# Configure
|
|
279
|
+
# Configure 快手 StreamLake Coding Plan with multiple models
|
|
157
280
|
cckit configure streamlake --api-key "your-streamlake-api-key" --model "kat-coder-pro-v1" --model "claude-3-opus-20250219"
|
|
158
281
|
|
|
159
282
|
# List models
|
|
@@ -162,13 +285,13 @@ cckit models streamlake
|
|
|
162
285
|
# Set active model
|
|
163
286
|
cckit set-model streamlake "claude-3-opus-20250219"
|
|
164
287
|
|
|
165
|
-
# Switch to
|
|
288
|
+
# Switch to 快手 StreamLake Coding Plan
|
|
166
289
|
cckit switch streamlake
|
|
167
290
|
```
|
|
168
291
|
|
|
169
|
-
####
|
|
292
|
+
#### 火山引擎 Coding Plan [火山方舟](https://www.volcengine.com/activity/codingplan)
|
|
170
293
|
```bash
|
|
171
|
-
# Configure
|
|
294
|
+
# Configure 火山引擎 Coding Plan with multiple models
|
|
172
295
|
cckit configure volcengine --api-key "your-ark-api-key" --model "ark-code-latest" --model "ark-code-pro"
|
|
173
296
|
|
|
174
297
|
# List models
|
|
@@ -177,7 +300,7 @@ cckit models volcengine
|
|
|
177
300
|
# Set active model
|
|
178
301
|
cckit set-model volcengine "ark-code-pro"
|
|
179
302
|
|
|
180
|
-
# Switch to
|
|
303
|
+
# Switch to 火山引擎 Coding Plan
|
|
181
304
|
cckit switch volcengine
|
|
182
305
|
```
|
|
183
306
|
|
|
@@ -196,6 +319,36 @@ cckit set-model aliyun "glm-5"
|
|
|
196
319
|
cckit switch aliyun
|
|
197
320
|
```
|
|
198
321
|
|
|
322
|
+
#### Tencent [腾讯云 Coding Plan]
|
|
323
|
+
```bash
|
|
324
|
+
# Configure Tencent Coding Plan with multiple models
|
|
325
|
+
cckit configure tencent --api-key "your-api-key" --model "GLM-5" --model "MiniMax-M2.5" --model "Kimi-K2.5"
|
|
326
|
+
|
|
327
|
+
# List models
|
|
328
|
+
cckit models tencent
|
|
329
|
+
|
|
330
|
+
# Set active model
|
|
331
|
+
cckit set-model tencent "MiniMax-M2.5"
|
|
332
|
+
|
|
333
|
+
# Switch to Tencent
|
|
334
|
+
cckit switch tencent
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
#### XFYun [讯飞 Coding Plan]
|
|
338
|
+
```bash
|
|
339
|
+
# Configure XFYun Coding Plan with multiple models
|
|
340
|
+
cckit configure xfyun --api-key "your-api-key" --model "GLM-5" --model "MiniMax-M2.5" --model "Kimi-K2.5"
|
|
341
|
+
|
|
342
|
+
# List models
|
|
343
|
+
cckit models xfyun
|
|
344
|
+
|
|
345
|
+
# Set active model
|
|
346
|
+
cckit set-model xfyun "MiniMax-M2.5"
|
|
347
|
+
|
|
348
|
+
# Switch to XFYun
|
|
349
|
+
cckit switch xfyun
|
|
350
|
+
```
|
|
351
|
+
|
|
199
352
|
#### Custom Provider - Local/OpaqueAI/OpenAI Compatible APIs
|
|
200
353
|
|
|
201
354
|
Configure custom providers for local LLMs (Ollama, LocalAI, LM Studio), opaque API endpoints, or any Anthropic-compatible API:
|
|
@@ -239,6 +392,9 @@ cckit import backup.json
|
|
|
239
392
|
|
|
240
393
|
# Reset to default Claude configuration
|
|
241
394
|
cckit reset
|
|
395
|
+
|
|
396
|
+
# Interactive configuration wizard (new!)
|
|
397
|
+
cckit interactive
|
|
242
398
|
```
|
|
243
399
|
|
|
244
400
|
## Configuration
|
|
@@ -259,13 +415,15 @@ The active model is used when Claude Code switches to that provider. If no expli
|
|
|
259
415
|
|
|
260
416
|
| Provider | Default Model | Auth Method | Capabilities | Default Base URL |
|
|
261
417
|
|----------|---------------|-------------|--------------|------------------|
|
|
262
|
-
| 智谱
|
|
263
|
-
| MiniMax | MiniMax-M2 | ANTHROPIC_AUTH_TOKEN | Chat, Code Generation, Multi-language | https://api.minimaxi.com/anthropic |
|
|
264
|
-
| Kimi | kimi-for-coding | ANTHROPIC_API_KEY | Chat, Long Context, Code Generation | https://api.kimi.com/coding/ |
|
|
418
|
+
| 智谱 Coding Plan | GLM-4.7 | ANTHROPIC_AUTH_TOKEN | Chat, Code Generation, Chinese Support | https://open.bigmodel.cn/api/anthropic |
|
|
419
|
+
| MiniMax Coding Plan | MiniMax-M2 | ANTHROPIC_AUTH_TOKEN | Chat, Code Generation, Multi-language | https://api.minimaxi.com/anthropic |
|
|
420
|
+
| Kimi Coding Plan | kimi-for-coding | ANTHROPIC_API_KEY | Chat, Long Context, Code Generation | https://api.kimi.com/coding/ |
|
|
265
421
|
| ZenMux.ai | claude-3-5-sonnet-20241022 | ANTHROPIC_API_KEY | Model Gateway, Multi-provider, Claude Compatible | https://zenmux.ai/api/anthropic |
|
|
266
|
-
|
|
|
267
|
-
|
|
|
268
|
-
|
|
|
422
|
+
| 快手 StreamLake Coding Plan | kat-coder-pro-v1 | ANTHROPIC_API_KEY | Chat, Code Generation, Chinese Support, Video Understanding | https://wanqing.streamlakeapi.com/api/gateway/v1/endpoints/kat-coder-pro-v1/claude-code-proxy |
|
|
423
|
+
| 火山引擎 Coding Plan | ark-code-latest | ANTHROPIC_AUTH_TOKEN | Chat, Code Generation, Chinese Support | https://ark.cn-beijing.volces.com/api/coding |
|
|
424
|
+
| 阿里云 Coding Plan | claude-sonnet-4-20250514 | ANTHROPIC_AUTH_TOKEN | Chat, Code Generation, Chinese Support, Multimodal | https://coding.dashscope.aliyuncs.com/apps/anthropic |
|
|
425
|
+
| 腾讯云 Coding Plan | GLM-5 | ANTHROPIC_AUTH_TOKEN | Chat, Code Generation, Chinese Support, Multimodal | https://api.lkeap.cloud.tencent.com/coding/anthropic |
|
|
426
|
+
| 讯飞 Coding Plan | GLM-5 | ANTHROPIC_AUTH_TOKEN | Chat, Code Generation, Chinese Support, Multimodal | https://maas-coding-api.cn-huabei-1.xf-yun.com/anthropic |
|
|
269
427
|
| Claude | claude-3-5-sonnet-20241022 | ANTHROPIC_API_KEY | Chat, Code Generation, Analysis, Multimodal | Official |
|
|
270
428
|
| Custom | - | ANTHROPIC_API_KEY | Custom, User-defined, Local LLM, Anthropic Compatible API | User-defined |
|
|
271
429
|
|
|
@@ -299,7 +457,7 @@ For more build options and details, see [BUILD.md](BUILD.md).
|
|
|
299
457
|
|
|
300
458
|
## Requirements
|
|
301
459
|
|
|
302
|
-
- Node.js
|
|
460
|
+
- Node.js 20 or higher
|
|
303
461
|
- pnpm (or npm/yarn)
|
|
304
462
|
- Claude Code installed
|
|
305
463
|
- Valid API keys for the providers you want to use
|
package/dist/commands.d.ts
CHANGED
|
@@ -2,6 +2,10 @@ import { ConfigManager } from './config.js';
|
|
|
2
2
|
export declare class Commands {
|
|
3
3
|
private configManager;
|
|
4
4
|
constructor(configManager: ConfigManager);
|
|
5
|
+
/**
|
|
6
|
+
* Interactive configuration wizard with arrow key selection
|
|
7
|
+
*/
|
|
8
|
+
interactive(): Promise<void>;
|
|
5
9
|
list(): void;
|
|
6
10
|
switch(providerId: string): void;
|
|
7
11
|
current(): void;
|
package/dist/commands.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,aAAa,EAAsD,MAAM,aAAa,CAAC;AAahG,qBAAa,QAAQ;IACP,OAAO,CAAC,aAAa;gBAAb,aAAa,EAAE,aAAa;IAEhD;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAmOlC,IAAI,IAAI,IAAI;IAsCZ,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAmBhC,OAAO,IAAI,IAAI;IAkCf,SAAS,CACP,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,MAAM,EAAE,GAChB,IAAI;IAuEP,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IA6CxB,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA8B7C,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IA6B1B,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuFpE,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IA2CxD,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAkB7B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAa1B,KAAK,IAAI,IAAI;IASb,OAAO,CAAC,sBAAsB;YAoChB,YAAY;CAM3B"}
|
package/dist/commands.js
CHANGED
|
@@ -1,13 +1,215 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import fs from 'fs';
|
|
3
|
-
import
|
|
3
|
+
import { select, input, confirm } from '@inquirer/prompts';
|
|
4
4
|
import { createProvider } from './config.js';
|
|
5
|
-
import { testProvider } from './providers.js';
|
|
5
|
+
import { testProvider, PROVIDER_CONFIGS } from './providers.js';
|
|
6
6
|
import { i18n } from './i18n.js';
|
|
7
7
|
export class Commands {
|
|
8
8
|
constructor(configManager) {
|
|
9
9
|
this.configManager = configManager;
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Interactive configuration wizard with arrow key selection
|
|
13
|
+
*/
|
|
14
|
+
async interactive() {
|
|
15
|
+
console.log();
|
|
16
|
+
console.log(chalk.blue.bold(' ___ ___ / ___ ( ) __ ___ '));
|
|
17
|
+
console.log(chalk.blue.bold(' // ) ) // ) ) //\\ \\ / / / / '));
|
|
18
|
+
console.log(chalk.blue.bold(' // // // \\ \\ / / / / '));
|
|
19
|
+
console.log(chalk.blue.bold(' ((____ ((____ // \\ \\ / / / / '));
|
|
20
|
+
console.log(chalk.cyan.bold(' 交互式配置向导'));
|
|
21
|
+
console.log();
|
|
22
|
+
// Step 1: Select provider type using arrow keys
|
|
23
|
+
console.log();
|
|
24
|
+
console.log(chalk.cyan.bold('▸ Step 1: 选择要配置的 AI 提供商'));
|
|
25
|
+
console.log();
|
|
26
|
+
const providerTypes = Object.entries(PROVIDER_CONFIGS)
|
|
27
|
+
.filter(([key]) => key !== 'custom')
|
|
28
|
+
.map(([key, config]) => ({
|
|
29
|
+
value: key,
|
|
30
|
+
name: config.display_name,
|
|
31
|
+
defaultModel: config.default_model,
|
|
32
|
+
}));
|
|
33
|
+
const providerTypeChoices = [
|
|
34
|
+
...providerTypes.map((p) => ({
|
|
35
|
+
value: { type: 'preset', id: p.value, name: p.name, defaultModel: p.defaultModel },
|
|
36
|
+
name: p.name,
|
|
37
|
+
})),
|
|
38
|
+
{
|
|
39
|
+
value: { type: 'custom' },
|
|
40
|
+
name: chalk.green('自定义 Provider (Local LLM / OpenAI Compatible)'),
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
const providerChoice = await select({
|
|
44
|
+
message: '请选择提供商',
|
|
45
|
+
choices: providerTypeChoices,
|
|
46
|
+
pageSize: 12,
|
|
47
|
+
});
|
|
48
|
+
let providerType;
|
|
49
|
+
let providerName;
|
|
50
|
+
let defaultModel;
|
|
51
|
+
if (providerChoice.type === 'custom') {
|
|
52
|
+
providerType = 'custom';
|
|
53
|
+
providerName = await input({
|
|
54
|
+
message: '请输入自定义 Provider 名称 (例如: ollama, my-api)',
|
|
55
|
+
default: 'ollama',
|
|
56
|
+
});
|
|
57
|
+
defaultModel = 'llama3';
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
providerType = providerChoice.id;
|
|
61
|
+
providerName = providerChoice.name;
|
|
62
|
+
defaultModel = providerChoice.defaultModel;
|
|
63
|
+
}
|
|
64
|
+
console.log();
|
|
65
|
+
console.log(chalk.cyan.bold(`▸ Step 2: 配置 ${providerName}`));
|
|
66
|
+
console.log();
|
|
67
|
+
// Step 2: Enter API key
|
|
68
|
+
const apiKey = await input({
|
|
69
|
+
message: '请输入 API Key',
|
|
70
|
+
validate: (value) => {
|
|
71
|
+
if (!value || value.trim() === '') {
|
|
72
|
+
return 'API Key 不能为空';
|
|
73
|
+
}
|
|
74
|
+
return true;
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
// Step 3: Enter base URL (for custom providers)
|
|
78
|
+
let baseUrl;
|
|
79
|
+
if (providerType === 'custom') {
|
|
80
|
+
baseUrl = await input({
|
|
81
|
+
message: '请输入 Base URL',
|
|
82
|
+
default: 'http://localhost:11434/v1',
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
// Step 4: Enter model name
|
|
86
|
+
console.log();
|
|
87
|
+
console.log(chalk.cyan.bold('▸ Step 3: 设置模型'));
|
|
88
|
+
console.log();
|
|
89
|
+
const modelInput = await input({
|
|
90
|
+
message: '请输入模型名称 (多个模型用逗号分隔,如: claude-3-opus, claude-3-sonnet)',
|
|
91
|
+
default: defaultModel,
|
|
92
|
+
});
|
|
93
|
+
// Parse model names: split by comma and trim whitespace
|
|
94
|
+
const models = modelInput
|
|
95
|
+
.split(',')
|
|
96
|
+
.map((m) => m.trim())
|
|
97
|
+
.filter((m) => m.length > 0);
|
|
98
|
+
const model = models[0] || defaultModel;
|
|
99
|
+
// Step 5: Save configuration
|
|
100
|
+
console.log();
|
|
101
|
+
console.log(chalk.cyan.bold('▸ Step 4: 保存配置'));
|
|
102
|
+
console.log();
|
|
103
|
+
const providers = this.configManager.listProviders();
|
|
104
|
+
const sameTypeProviders = providers.filter((p) => p.provider_type === providerType);
|
|
105
|
+
let provider;
|
|
106
|
+
// If there are existing providers of the same type, ask user what to do
|
|
107
|
+
if (sameTypeProviders.length > 0 && providerType !== 'custom') {
|
|
108
|
+
const updateChoices = [
|
|
109
|
+
...sameTypeProviders.map((p, i) => ({
|
|
110
|
+
value: { action: 'update', index: i },
|
|
111
|
+
name: `${p.name} (模型: ${p.current_model || p.models[0] || 'none'})`,
|
|
112
|
+
})),
|
|
113
|
+
{
|
|
114
|
+
value: { action: 'create' },
|
|
115
|
+
name: chalk.green(`创建新的 ${providerName} 配置`),
|
|
116
|
+
},
|
|
117
|
+
];
|
|
118
|
+
const updateChoice = await select({
|
|
119
|
+
message: `发现 ${sameTypeProviders.length} 个已存在的配置,请选择`,
|
|
120
|
+
choices: updateChoices,
|
|
121
|
+
});
|
|
122
|
+
if (updateChoice.action === 'update') {
|
|
123
|
+
const existingProvider = sameTypeProviders[updateChoice.index];
|
|
124
|
+
existingProvider.api_key = apiKey;
|
|
125
|
+
if (baseUrl)
|
|
126
|
+
existingProvider.base_url = baseUrl;
|
|
127
|
+
// Add all new models that don't already exist
|
|
128
|
+
for (const m of models) {
|
|
129
|
+
if (!existingProvider.models.includes(m)) {
|
|
130
|
+
existingProvider.models.push(m);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
existingProvider.current_model = model;
|
|
134
|
+
existingProvider.updated_at = new Date().toISOString();
|
|
135
|
+
provider = existingProvider;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
else if (providerType === 'custom') {
|
|
139
|
+
// For custom providers, check if a provider with the same name exists
|
|
140
|
+
const existingCustomProvider = providers.find((p) => p.provider_type === 'custom' && p.name === providerName);
|
|
141
|
+
if (existingCustomProvider) {
|
|
142
|
+
const shouldUpdate = await confirm({
|
|
143
|
+
message: `发现已存在的 "${providerName}" 配置,是否更新?`,
|
|
144
|
+
default: true,
|
|
145
|
+
});
|
|
146
|
+
if (shouldUpdate) {
|
|
147
|
+
existingCustomProvider.api_key = apiKey;
|
|
148
|
+
if (baseUrl)
|
|
149
|
+
existingCustomProvider.base_url = baseUrl;
|
|
150
|
+
// Add all new models that don't already exist
|
|
151
|
+
for (const m of models) {
|
|
152
|
+
if (!existingCustomProvider.models.includes(m)) {
|
|
153
|
+
existingCustomProvider.models.push(m);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
existingCustomProvider.current_model = model;
|
|
157
|
+
existingCustomProvider.updated_at = new Date().toISOString();
|
|
158
|
+
provider = existingCustomProvider;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// If provider is not set, create a new one
|
|
163
|
+
if (!provider) {
|
|
164
|
+
provider = createProvider(providerType, providerName, apiKey, baseUrl, models);
|
|
165
|
+
provider.current_model = model;
|
|
166
|
+
}
|
|
167
|
+
this.configManager.saveProvider(provider);
|
|
168
|
+
console.log(chalk.green(`✓ 配置已保存 (id: ${provider.id})`));
|
|
169
|
+
console.log(` ${i18n.general.provider_label()}: ${providerName}`);
|
|
170
|
+
console.log(` ${i18n.general.model_label()}: ${models.join(', ')}`);
|
|
171
|
+
// Step 6: Ask to test connection
|
|
172
|
+
console.log();
|
|
173
|
+
console.log(chalk.cyan.bold('▸ Step 5: 测试连接'));
|
|
174
|
+
console.log();
|
|
175
|
+
const shouldTest = await confirm({
|
|
176
|
+
message: '是否测试连接?',
|
|
177
|
+
default: true,
|
|
178
|
+
});
|
|
179
|
+
if (shouldTest) {
|
|
180
|
+
console.log(chalk.yellow(`正在测试 ${providerName} 连接...`));
|
|
181
|
+
const result = await testProvider(provider);
|
|
182
|
+
if (result.success) {
|
|
183
|
+
console.log(chalk.green(`✓ 连接成功!`));
|
|
184
|
+
if (result.response_time_ms) {
|
|
185
|
+
console.log(chalk.dim(` 响应时间: ${result.response_time_ms}ms`));
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
console.log(chalk.red(`✗ 连接失败: ${result.message}`));
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
// Step 7: Ask to switch
|
|
193
|
+
console.log();
|
|
194
|
+
console.log(chalk.cyan.bold('▸ Step 6: 切换 Provider'));
|
|
195
|
+
console.log();
|
|
196
|
+
const shouldSwitch = await confirm({
|
|
197
|
+
message: '是否立即切换到该 Provider?',
|
|
198
|
+
default: true,
|
|
199
|
+
});
|
|
200
|
+
if (shouldSwitch) {
|
|
201
|
+
this.configManager.switchProvider(provider.id);
|
|
202
|
+
console.log(chalk.green.bold(`✓ 已切换到 ${providerName}`));
|
|
203
|
+
console.log(chalk.dim(i18n.cli.restart_note()));
|
|
204
|
+
}
|
|
205
|
+
console.log();
|
|
206
|
+
console.log(chalk.green.bold(' ___ ___ / ___ ( ) __ ___ '));
|
|
207
|
+
console.log(chalk.green.bold(' // ) ) // ) ) //\\ \\ / / / / '));
|
|
208
|
+
console.log(chalk.green.bold(' // // // \\ \\ / / / / '));
|
|
209
|
+
console.log(chalk.green.bold(' ((____ ((____ // \\ \\ / / / / '));
|
|
210
|
+
console.log(chalk.cyan.bold(' 配置完成! ✓'));
|
|
211
|
+
console.log();
|
|
212
|
+
}
|
|
11
213
|
list() {
|
|
12
214
|
console.log(chalk.blue.bold(i18n.cli.list_title()));
|
|
13
215
|
console.log();
|
|
@@ -15,7 +217,9 @@ export class Commands {
|
|
|
15
217
|
const currentProvider = this.configManager.getCurrentProvider();
|
|
16
218
|
for (const provider of providers) {
|
|
17
219
|
const isCurrent = currentProvider?.id === provider.id;
|
|
18
|
-
const status = isCurrent
|
|
220
|
+
const status = isCurrent
|
|
221
|
+
? chalk.green.bold(i18n.status.active())
|
|
222
|
+
: chalk.dim(i18n.status.inactive());
|
|
19
223
|
const providerName = this.getProviderDisplayName(provider.provider_type, provider.name, true);
|
|
20
224
|
console.log(` ${status} ${chalk.bold(providerName)}`);
|
|
21
225
|
console.log(` ${i18n.general.id_label()}: ${chalk.dim(provider.id)}`);
|
|
@@ -71,17 +275,20 @@ export class Commands {
|
|
|
71
275
|
if (!provider) {
|
|
72
276
|
const providerTypeMap = {
|
|
73
277
|
zhipu: ['zhipu', i18n.providers.get_display_name('zhipu')],
|
|
74
|
-
|
|
278
|
+
智谱: ['zhipu', i18n.providers.get_display_name('zhipu')],
|
|
75
279
|
minimax: ['minimax', i18n.providers.get_display_name('minimax')],
|
|
76
280
|
kimi: ['kimi', i18n.providers.get_display_name('kimi')],
|
|
77
281
|
claude: ['claude', i18n.providers.get_display_name('claude')],
|
|
78
282
|
zenmux: ['zenmux', i18n.providers.get_display_name('zenmux')],
|
|
79
283
|
streamlake: ['streamlake', i18n.providers.get_display_name('streamlake')],
|
|
80
284
|
kuaishou: ['streamlake', i18n.providers.get_display_name('streamlake')],
|
|
81
|
-
|
|
285
|
+
快手: ['streamlake', i18n.providers.get_display_name('streamlake')],
|
|
82
286
|
volcengine: ['volcengine', i18n.providers.get_display_name('volcengine')],
|
|
83
287
|
aliyun: ['aliyun', i18n.providers.get_display_name('aliyun')],
|
|
84
|
-
|
|
288
|
+
阿里云: ['aliyun', i18n.providers.get_display_name('aliyun')],
|
|
289
|
+
tencent: ['tencent', i18n.providers.get_display_name('tencent')],
|
|
290
|
+
腾讯: ['tencent', i18n.providers.get_display_name('tencent')],
|
|
291
|
+
腾讯云: ['tencent', i18n.providers.get_display_name('tencent')],
|
|
85
292
|
};
|
|
86
293
|
// Check if this is a custom provider (format: custom:<name> or just a new name)
|
|
87
294
|
if (providerId.startsWith('custom:')) {
|
|
@@ -348,15 +555,9 @@ export class Commands {
|
|
|
348
555
|
return colorFn(displayName);
|
|
349
556
|
}
|
|
350
557
|
async askForSwitch(providerName) {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
});
|
|
355
|
-
return new Promise((resolve) => {
|
|
356
|
-
rl.question(`Do you want to switch to ${providerName} now? [y/N]: `, (answer) => {
|
|
357
|
-
rl.close();
|
|
358
|
-
resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
|
|
359
|
-
});
|
|
558
|
+
return confirm({
|
|
559
|
+
message: `Do you want to switch to ${providerName} now?`,
|
|
560
|
+
default: false,
|
|
360
561
|
});
|
|
361
562
|
}
|
|
362
563
|
}
|