ccjk 2.0.20 → 2.2.1
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 +601 -35
- package/README.zh-CN.md +651 -0
- package/dist/chunks/api.mjs +100 -0
- package/dist/chunks/auto-updater.mjs +252 -0
- package/dist/chunks/ccjk-config.mjs +261 -0
- package/dist/chunks/ccr.mjs +77 -0
- package/dist/chunks/ccu.mjs +36 -0
- package/dist/chunks/check-updates.mjs +93 -0
- package/dist/chunks/claude-code-config-manager.mjs +28 -21
- package/dist/chunks/claude-code-incremental-manager.mjs +26 -18
- package/dist/chunks/claude-config.mjs +228 -0
- package/dist/chunks/codex.mjs +2134 -0
- package/dist/chunks/commands.mjs +2 -15
- package/dist/chunks/commit.mjs +119 -0
- package/dist/chunks/config-consolidator.mjs +281 -0
- package/dist/chunks/config-switch.mjs +302 -0
- package/dist/chunks/constants.mjs +156 -0
- package/dist/chunks/doctor.mjs +708 -0
- package/dist/chunks/features.mjs +35 -640
- package/dist/chunks/features2.mjs +661 -0
- package/dist/chunks/fs-operations.mjs +180 -0
- package/dist/chunks/index.mjs +3082 -0
- package/dist/chunks/index2.mjs +145 -0
- package/dist/chunks/init.mjs +2468 -0
- package/dist/chunks/interview.mjs +2916 -0
- package/dist/chunks/json-config.mjs +59 -0
- package/dist/chunks/marketplace.mjs +258 -0
- package/dist/chunks/mcp-doctor.mjs +160 -0
- package/dist/chunks/mcp-market.mjs +475 -0
- package/dist/chunks/mcp-performance.mjs +110 -0
- package/dist/chunks/mcp-profile.mjs +220 -0
- package/dist/chunks/mcp-release.mjs +138 -0
- package/dist/chunks/menu.mjs +3599 -0
- package/dist/chunks/notification.mjs +2336 -0
- package/dist/chunks/onboarding.mjs +711 -0
- package/dist/chunks/package.mjs +4 -0
- package/dist/chunks/permission-manager.mjs +210 -0
- package/dist/chunks/platform.mjs +321 -0
- package/dist/chunks/prompts.mjs +228 -0
- package/dist/chunks/session.mjs +355 -0
- package/dist/chunks/shencha.mjs +320 -0
- package/dist/chunks/skills-sync.mjs +4 -13
- package/dist/chunks/team.mjs +51 -0
- package/dist/chunks/tools.mjs +169 -0
- package/dist/chunks/uninstall.mjs +784 -0
- package/dist/chunks/update.mjs +104 -0
- package/dist/chunks/upgrade-manager.mjs +197 -0
- package/dist/chunks/workflows.mjs +100 -0
- package/dist/cli.mjs +581 -15348
- package/dist/i18n/locales/zh-CN/cli.json +1 -1
- package/dist/i18n/locales/zh-CN/common.json +1 -1
- package/dist/index.mjs +43 -2062
- package/dist/shared/ccjk.-FoZ3zat.mjs +761 -0
- package/dist/shared/ccjk.B7169qud.mjs +25 -0
- package/dist/shared/ccjk.BhKlRJ0h.mjs +114 -0
- package/dist/shared/ccjk.Bi-m3LKY.mjs +357 -0
- package/dist/shared/ccjk.COdsoe-Y.mjs +64 -0
- package/dist/shared/ccjk.CUdzQluX.mjs +46 -0
- package/dist/shared/ccjk.Cy-RH2qV.mjs +506 -0
- package/dist/shared/ccjk.DGjQxTq_.mjs +34 -0
- package/dist/shared/ccjk.DJM5aVQJ.mjs +586 -0
- package/dist/shared/ccjk.DhBeLRzf.mjs +28 -0
- package/dist/shared/ccjk.DwDtZ5cK.mjs +266 -0
- package/dist/shared/ccjk.n_AtlHzB.mjs +186 -0
- package/dist/shared/ccjk.qYAnUMuy.mjs +749 -0
- package/package.json +29 -25
- package/dist/chunks/codex-config-switch.mjs +0 -429
- package/dist/chunks/codex-provider-manager.mjs +0 -234
- package/dist/chunks/codex-uninstaller.mjs +0 -406
- package/dist/chunks/plugin-recommendation.mjs +0 -575
- package/dist/chunks/simple-config.mjs +0 -10950
|
@@ -0,0 +1,761 @@
|
|
|
1
|
+
import ansis from 'ansis';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { existsSync, readFileSync, mkdirSync } from 'node:fs';
|
|
4
|
+
import { homedir } from 'node:os';
|
|
5
|
+
import { join } from 'pathe';
|
|
6
|
+
import { writeFileAtomic } from '../chunks/fs-operations.mjs';
|
|
7
|
+
|
|
8
|
+
const PROVIDER_PRESETS = [
|
|
9
|
+
// === Official Anthropic ===
|
|
10
|
+
{
|
|
11
|
+
id: "anthropic",
|
|
12
|
+
name: "Anthropic (Official)",
|
|
13
|
+
nameZh: "Anthropic (\u5B98\u65B9)",
|
|
14
|
+
description: "Official Anthropic API - Best quality and reliability",
|
|
15
|
+
descriptionZh: "\u5B98\u65B9 Anthropic API - \u6700\u4F73\u8D28\u91CF\u548C\u7A33\u5B9A\u6027",
|
|
16
|
+
category: "official",
|
|
17
|
+
website: "https://console.anthropic.com",
|
|
18
|
+
requiresApiKey: true,
|
|
19
|
+
baseUrl: "https://api.anthropic.com",
|
|
20
|
+
models: [
|
|
21
|
+
"claude-sonnet-4-20250514",
|
|
22
|
+
"claude-opus-4-20250514",
|
|
23
|
+
"claude-3-5-sonnet-20241022",
|
|
24
|
+
"claude-3-5-haiku-20241022"
|
|
25
|
+
],
|
|
26
|
+
defaultModel: "claude-sonnet-4-20250514",
|
|
27
|
+
features: ["chat", "vision", "tools", "streaming", "thinking", "code"],
|
|
28
|
+
instructions: {
|
|
29
|
+
en: "Get your API key from https://console.anthropic.com/settings/keys",
|
|
30
|
+
zh: "\u4ECE https://console.anthropic.com/settings/keys \u83B7\u53D6 API \u5BC6\u94A5"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
// === OpenAI-Compatible Providers ===
|
|
34
|
+
{
|
|
35
|
+
id: "302ai",
|
|
36
|
+
name: "302.AI",
|
|
37
|
+
nameZh: "302.AI",
|
|
38
|
+
description: "Multi-model API platform with Claude support",
|
|
39
|
+
descriptionZh: "\u591A\u6A21\u578B API \u5E73\u53F0\uFF0C\u652F\u6301 Claude",
|
|
40
|
+
category: "openai-compatible",
|
|
41
|
+
website: "https://302.ai",
|
|
42
|
+
requiresApiKey: true,
|
|
43
|
+
baseUrl: "https://api.302.ai/v1",
|
|
44
|
+
models: [
|
|
45
|
+
"claude-sonnet-4-20250514",
|
|
46
|
+
"claude-3-5-sonnet-20241022",
|
|
47
|
+
"gpt-4o",
|
|
48
|
+
"gpt-4-turbo"
|
|
49
|
+
],
|
|
50
|
+
defaultModel: "claude-sonnet-4-20250514",
|
|
51
|
+
features: ["chat", "vision", "tools", "streaming", "code"],
|
|
52
|
+
instructions: {
|
|
53
|
+
en: "Register at 302.ai and get your API key from dashboard",
|
|
54
|
+
zh: "\u5728 302.ai \u6CE8\u518C\u5E76\u4ECE\u63A7\u5236\u53F0\u83B7\u53D6 API \u5BC6\u94A5"
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: "openrouter",
|
|
59
|
+
name: "OpenRouter",
|
|
60
|
+
nameZh: "OpenRouter",
|
|
61
|
+
description: "Unified API for multiple AI models",
|
|
62
|
+
descriptionZh: "\u7EDF\u4E00\u591A\u6A21\u578B API \u63A5\u53E3",
|
|
63
|
+
category: "openai-compatible",
|
|
64
|
+
website: "https://openrouter.ai",
|
|
65
|
+
requiresApiKey: true,
|
|
66
|
+
baseUrl: "https://openrouter.ai/api/v1",
|
|
67
|
+
models: [
|
|
68
|
+
"anthropic/claude-sonnet-4",
|
|
69
|
+
"anthropic/claude-3.5-sonnet",
|
|
70
|
+
"anthropic/claude-3.7-sonnet:thinking",
|
|
71
|
+
"google/gemini-2.5-pro-preview"
|
|
72
|
+
],
|
|
73
|
+
defaultModel: "anthropic/claude-sonnet-4",
|
|
74
|
+
features: ["chat", "vision", "tools", "streaming", "thinking", "code"],
|
|
75
|
+
transformer: {
|
|
76
|
+
use: ["openrouter"]
|
|
77
|
+
},
|
|
78
|
+
instructions: {
|
|
79
|
+
en: "Get your API key from https://openrouter.ai/keys",
|
|
80
|
+
zh: "\u4ECE https://openrouter.ai/keys \u83B7\u53D6 API \u5BC6\u94A5"
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
// === Chinese Providers ===
|
|
84
|
+
{
|
|
85
|
+
id: "deepseek",
|
|
86
|
+
name: "DeepSeek",
|
|
87
|
+
nameZh: "DeepSeek \u6DF1\u5EA6\u6C42\u7D22",
|
|
88
|
+
description: "High-performance Chinese AI with reasoning capabilities",
|
|
89
|
+
descriptionZh: "\u9AD8\u6027\u80FD\u56FD\u4EA7 AI\uFF0C\u652F\u6301\u6DF1\u5EA6\u63A8\u7406",
|
|
90
|
+
category: "chinese",
|
|
91
|
+
website: "https://platform.deepseek.com",
|
|
92
|
+
requiresApiKey: true,
|
|
93
|
+
baseUrl: "https://api.deepseek.com",
|
|
94
|
+
models: ["deepseek-chat", "deepseek-reasoner"],
|
|
95
|
+
defaultModel: "deepseek-chat",
|
|
96
|
+
features: ["chat", "tools", "streaming", "thinking", "code"],
|
|
97
|
+
transformer: {
|
|
98
|
+
"use": ["deepseek"],
|
|
99
|
+
"deepseek-chat": { use: ["tooluse"] }
|
|
100
|
+
},
|
|
101
|
+
instructions: {
|
|
102
|
+
en: "Get your API key from https://platform.deepseek.com/api_keys",
|
|
103
|
+
zh: "\u4ECE https://platform.deepseek.com/api_keys \u83B7\u53D6 API \u5BC6\u94A5"
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
id: "qwen",
|
|
108
|
+
name: "Qwen (Alibaba)",
|
|
109
|
+
nameZh: "\u901A\u4E49\u5343\u95EE (\u963F\u91CC\u5DF4\u5DF4)",
|
|
110
|
+
description: "Alibaba Cloud Qwen models via DashScope",
|
|
111
|
+
descriptionZh: "\u963F\u91CC\u4E91\u901A\u4E49\u5343\u95EE\u5927\u6A21\u578B",
|
|
112
|
+
category: "chinese",
|
|
113
|
+
website: "https://dashscope.console.aliyun.com",
|
|
114
|
+
requiresApiKey: true,
|
|
115
|
+
baseUrl: "https://dashscope.aliyuncs.com/compatible-mode/v1",
|
|
116
|
+
models: ["qwen3-coder-plus", "qwen-max", "qwen-turbo"],
|
|
117
|
+
defaultModel: "qwen3-coder-plus",
|
|
118
|
+
features: ["chat", "vision", "tools", "streaming", "code"],
|
|
119
|
+
transformer: {
|
|
120
|
+
"use": [["maxtoken", { max_tokens: 65536 }]],
|
|
121
|
+
"qwen3-coder-plus": { use: ["enhancetool"] }
|
|
122
|
+
},
|
|
123
|
+
instructions: {
|
|
124
|
+
en: "Get your API key from Alibaba Cloud DashScope console",
|
|
125
|
+
zh: "\u4ECE\u963F\u91CC\u4E91 DashScope \u63A7\u5236\u53F0\u83B7\u53D6 API \u5BC6\u94A5"
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
id: "siliconflow",
|
|
130
|
+
name: "SiliconFlow",
|
|
131
|
+
nameZh: "SiliconFlow \u7845\u57FA\u6D41\u52A8",
|
|
132
|
+
description: "High-speed inference for multiple models",
|
|
133
|
+
descriptionZh: "\u9AD8\u901F\u591A\u6A21\u578B\u63A8\u7406\u5E73\u53F0",
|
|
134
|
+
category: "chinese",
|
|
135
|
+
website: "https://siliconflow.cn",
|
|
136
|
+
requiresApiKey: true,
|
|
137
|
+
baseUrl: "https://api.siliconflow.cn/v1",
|
|
138
|
+
models: ["moonshotai/Kimi-K2-Instruct", "deepseek-ai/DeepSeek-V3"],
|
|
139
|
+
defaultModel: "moonshotai/Kimi-K2-Instruct",
|
|
140
|
+
features: ["chat", "tools", "streaming", "code"],
|
|
141
|
+
transformer: {
|
|
142
|
+
use: [["maxtoken", { max_tokens: 16384 }]]
|
|
143
|
+
},
|
|
144
|
+
instructions: {
|
|
145
|
+
en: "Get your API key from https://cloud.siliconflow.cn",
|
|
146
|
+
zh: "\u4ECE https://cloud.siliconflow.cn \u83B7\u53D6 API \u5BC6\u94A5"
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
id: "modelscope",
|
|
151
|
+
name: "ModelScope",
|
|
152
|
+
nameZh: "ModelScope \u9B54\u642D",
|
|
153
|
+
description: "Alibaba ModelScope inference platform",
|
|
154
|
+
descriptionZh: "\u963F\u91CC\u5DF4\u5DF4\u9B54\u642D\u63A8\u7406\u5E73\u53F0",
|
|
155
|
+
category: "chinese",
|
|
156
|
+
website: "https://modelscope.cn",
|
|
157
|
+
requiresApiKey: true,
|
|
158
|
+
baseUrl: "https://api-inference.modelscope.cn/v1",
|
|
159
|
+
models: [
|
|
160
|
+
"Qwen/Qwen3-Coder-480B-A35B-Instruct",
|
|
161
|
+
"Qwen/Qwen3-235B-A22B-Thinking-2507",
|
|
162
|
+
"ZhipuAI/GLM-4.5"
|
|
163
|
+
],
|
|
164
|
+
defaultModel: "Qwen/Qwen3-Coder-480B-A35B-Instruct",
|
|
165
|
+
features: ["chat", "tools", "streaming", "thinking", "code"],
|
|
166
|
+
transformer: {
|
|
167
|
+
"use": [["maxtoken", { max_tokens: 65536 }]],
|
|
168
|
+
"Qwen/Qwen3-Coder-480B-A35B-Instruct": { use: ["enhancetool"] },
|
|
169
|
+
"Qwen/Qwen3-235B-A22B-Thinking-2507": { use: ["reasoning"] }
|
|
170
|
+
},
|
|
171
|
+
instructions: {
|
|
172
|
+
en: "Get your API key from ModelScope console",
|
|
173
|
+
zh: "\u4ECE\u9B54\u642D\u63A7\u5236\u53F0\u83B7\u53D6 API \u5BC6\u94A5"
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
id: "volcengine",
|
|
178
|
+
name: "Volcengine (ByteDance)",
|
|
179
|
+
nameZh: "\u706B\u5C71\u5F15\u64CE (\u5B57\u8282\u8DF3\u52A8)",
|
|
180
|
+
description: "ByteDance AI platform with DeepSeek models",
|
|
181
|
+
descriptionZh: "\u5B57\u8282\u8DF3\u52A8 AI \u5E73\u53F0\uFF0C\u652F\u6301 DeepSeek",
|
|
182
|
+
category: "chinese",
|
|
183
|
+
website: "https://console.volcengine.com",
|
|
184
|
+
requiresApiKey: true,
|
|
185
|
+
baseUrl: "https://ark.cn-beijing.volces.com/api/v3",
|
|
186
|
+
models: ["deepseek-v3-250324", "deepseek-r1-250528"],
|
|
187
|
+
defaultModel: "deepseek-v3-250324",
|
|
188
|
+
features: ["chat", "tools", "streaming", "thinking", "code"],
|
|
189
|
+
transformer: {
|
|
190
|
+
use: ["deepseek"]
|
|
191
|
+
},
|
|
192
|
+
instructions: {
|
|
193
|
+
en: "Get your API key from Volcengine console",
|
|
194
|
+
zh: "\u4ECE\u706B\u5C71\u5F15\u64CE\u63A7\u5236\u53F0\u83B7\u53D6 API \u5BC6\u94A5"
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
id: "kimi",
|
|
199
|
+
name: "Kimi (Moonshot)",
|
|
200
|
+
nameZh: "Kimi (\u6708\u4E4B\u6697\u9762)",
|
|
201
|
+
description: "Moonshot AI with long context support",
|
|
202
|
+
descriptionZh: "\u6708\u4E4B\u6697\u9762 AI\uFF0C\u652F\u6301\u8D85\u957F\u4E0A\u4E0B\u6587",
|
|
203
|
+
category: "chinese",
|
|
204
|
+
website: "https://platform.moonshot.cn",
|
|
205
|
+
requiresApiKey: true,
|
|
206
|
+
baseUrl: "https://api.moonshot.cn/v1",
|
|
207
|
+
models: ["moonshot-v1-128k", "moonshot-v1-32k", "moonshot-v1-8k"],
|
|
208
|
+
defaultModel: "moonshot-v1-128k",
|
|
209
|
+
features: ["chat", "tools", "streaming", "code"],
|
|
210
|
+
instructions: {
|
|
211
|
+
en: "Get your API key from https://platform.moonshot.cn/console/api-keys",
|
|
212
|
+
zh: "\u4ECE https://platform.moonshot.cn/console/api-keys \u83B7\u53D6 API \u5BC6\u94A5"
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
id: "glm",
|
|
217
|
+
name: "GLM (Zhipu AI)",
|
|
218
|
+
nameZh: "GLM (\u667A\u8C31 AI)",
|
|
219
|
+
description: "Zhipu AI ChatGLM models",
|
|
220
|
+
descriptionZh: "\u667A\u8C31 AI ChatGLM \u5927\u6A21\u578B",
|
|
221
|
+
category: "chinese",
|
|
222
|
+
website: "https://open.bigmodel.cn",
|
|
223
|
+
requiresApiKey: true,
|
|
224
|
+
baseUrl: "https://open.bigmodel.cn/api/paas/v4",
|
|
225
|
+
models: ["glm-4-plus", "glm-4", "glm-4-flash"],
|
|
226
|
+
defaultModel: "glm-4-plus",
|
|
227
|
+
features: ["chat", "vision", "tools", "streaming", "code"],
|
|
228
|
+
instructions: {
|
|
229
|
+
en: "Get your API key from https://open.bigmodel.cn/usercenter/apikeys",
|
|
230
|
+
zh: "\u4ECE https://open.bigmodel.cn/usercenter/apikeys \u83B7\u53D6 API \u5BC6\u94A5"
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
// === Google Gemini ===
|
|
234
|
+
{
|
|
235
|
+
id: "gemini",
|
|
236
|
+
name: "Google Gemini",
|
|
237
|
+
nameZh: "Google Gemini",
|
|
238
|
+
description: "Google AI models with multimodal capabilities",
|
|
239
|
+
descriptionZh: "Google AI \u591A\u6A21\u6001\u6A21\u578B",
|
|
240
|
+
category: "openai-compatible",
|
|
241
|
+
website: "https://aistudio.google.com",
|
|
242
|
+
requiresApiKey: true,
|
|
243
|
+
baseUrl: "https://generativelanguage.googleapis.com/v1beta/models/",
|
|
244
|
+
models: ["gemini-2.5-flash", "gemini-2.5-pro", "gemini-pro"],
|
|
245
|
+
defaultModel: "gemini-2.5-flash",
|
|
246
|
+
features: ["chat", "vision", "tools", "streaming", "thinking", "code"],
|
|
247
|
+
transformer: {
|
|
248
|
+
use: ["gemini"]
|
|
249
|
+
},
|
|
250
|
+
instructions: {
|
|
251
|
+
en: "Get your API key from https://aistudio.google.com/app/apikey",
|
|
252
|
+
zh: "\u4ECE https://aistudio.google.com/app/apikey \u83B7\u53D6 API \u5BC6\u94A5"
|
|
253
|
+
}
|
|
254
|
+
},
|
|
255
|
+
// === Free Tier Providers ===
|
|
256
|
+
{
|
|
257
|
+
id: "groq",
|
|
258
|
+
name: "Groq",
|
|
259
|
+
nameZh: "Groq",
|
|
260
|
+
description: "Ultra-fast inference with free tier",
|
|
261
|
+
descriptionZh: "\u8D85\u5FEB\u63A8\u7406\uFF0C\u6709\u514D\u8D39\u989D\u5EA6",
|
|
262
|
+
category: "free",
|
|
263
|
+
website: "https://console.groq.com",
|
|
264
|
+
requiresApiKey: true,
|
|
265
|
+
baseUrl: "https://api.groq.com/openai/v1",
|
|
266
|
+
models: ["llama-3.3-70b-versatile", "mixtral-8x7b-32768"],
|
|
267
|
+
defaultModel: "llama-3.3-70b-versatile",
|
|
268
|
+
features: ["chat", "tools", "streaming", "code"],
|
|
269
|
+
instructions: {
|
|
270
|
+
en: "Get your free API key from https://console.groq.com/keys",
|
|
271
|
+
zh: "\u4ECE https://console.groq.com/keys \u83B7\u53D6\u514D\u8D39 API \u5BC6\u94A5"
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
// === Local Providers ===
|
|
275
|
+
{
|
|
276
|
+
id: "ollama",
|
|
277
|
+
name: "Ollama (Local)",
|
|
278
|
+
nameZh: "Ollama (\u672C\u5730)",
|
|
279
|
+
description: "Run AI models locally with Ollama",
|
|
280
|
+
descriptionZh: "\u4F7F\u7528 Ollama \u672C\u5730\u8FD0\u884C AI \u6A21\u578B",
|
|
281
|
+
category: "local",
|
|
282
|
+
website: "https://ollama.ai",
|
|
283
|
+
requiresApiKey: false,
|
|
284
|
+
baseUrl: "http://localhost:11434/v1",
|
|
285
|
+
models: ["llama3.2", "codellama", "qwen2.5-coder"],
|
|
286
|
+
defaultModel: "llama3.2",
|
|
287
|
+
features: ["chat", "streaming", "code"],
|
|
288
|
+
instructions: {
|
|
289
|
+
en: "Install Ollama from https://ollama.ai and run: ollama pull llama3.2",
|
|
290
|
+
zh: "\u4ECE https://ollama.ai \u5B89\u88C5 Ollama \u5E76\u8FD0\u884C: ollama pull llama3.2"
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
];
|
|
294
|
+
function getAllPresets() {
|
|
295
|
+
return PROVIDER_PRESETS;
|
|
296
|
+
}
|
|
297
|
+
function getPresetById(id) {
|
|
298
|
+
return PROVIDER_PRESETS.find((p) => p.id === id);
|
|
299
|
+
}
|
|
300
|
+
function getRecommendedPresets() {
|
|
301
|
+
const recommendedIds = ["anthropic", "302ai", "deepseek", "openrouter", "qwen"];
|
|
302
|
+
return recommendedIds.map((id) => getPresetById(id)).filter((p) => p !== void 0);
|
|
303
|
+
}
|
|
304
|
+
function getChinesePresets() {
|
|
305
|
+
return PROVIDER_PRESETS.filter(
|
|
306
|
+
(p) => p.category === "chinese" || p.id === "302ai"
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const CLAUDE_DIR = join(homedir(), ".claude");
|
|
311
|
+
const SETTINGS_FILE = join(CLAUDE_DIR, "settings.json");
|
|
312
|
+
function readSettings() {
|
|
313
|
+
if (!existsSync(SETTINGS_FILE)) {
|
|
314
|
+
return {};
|
|
315
|
+
}
|
|
316
|
+
try {
|
|
317
|
+
return JSON.parse(readFileSync(SETTINGS_FILE, "utf-8"));
|
|
318
|
+
} catch {
|
|
319
|
+
return {};
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
function writeSettings(settings) {
|
|
323
|
+
if (!existsSync(CLAUDE_DIR)) {
|
|
324
|
+
mkdirSync(CLAUDE_DIR, { recursive: true });
|
|
325
|
+
}
|
|
326
|
+
writeFileAtomic(SETTINGS_FILE, JSON.stringify(settings, null, 2));
|
|
327
|
+
}
|
|
328
|
+
function configureSimpleMode(config) {
|
|
329
|
+
try {
|
|
330
|
+
const settings = readSettings();
|
|
331
|
+
if (!settings.env) {
|
|
332
|
+
settings.env = {};
|
|
333
|
+
}
|
|
334
|
+
delete settings.env.ANTHROPIC_AUTH_TOKEN;
|
|
335
|
+
settings.env.ANTHROPIC_API_KEY = config.apiKey;
|
|
336
|
+
settings.env.ANTHROPIC_BASE_URL = config.baseUrl;
|
|
337
|
+
writeSettings(settings);
|
|
338
|
+
return {
|
|
339
|
+
success: true,
|
|
340
|
+
mode: "simple",
|
|
341
|
+
provider: config.provider,
|
|
342
|
+
message: `API configured successfully for ${config.provider}`
|
|
343
|
+
};
|
|
344
|
+
} catch (error) {
|
|
345
|
+
return {
|
|
346
|
+
success: false,
|
|
347
|
+
mode: "simple",
|
|
348
|
+
error: error instanceof Error ? error.message : String(error)
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
function configureOfficialMode(apiKey) {
|
|
353
|
+
try {
|
|
354
|
+
const settings = readSettings();
|
|
355
|
+
if (!settings.env) {
|
|
356
|
+
settings.env = {};
|
|
357
|
+
}
|
|
358
|
+
delete settings.env.ANTHROPIC_BASE_URL;
|
|
359
|
+
delete settings.env.ANTHROPIC_AUTH_TOKEN;
|
|
360
|
+
settings.env.ANTHROPIC_API_KEY = apiKey;
|
|
361
|
+
writeSettings(settings);
|
|
362
|
+
return {
|
|
363
|
+
success: true,
|
|
364
|
+
mode: "official",
|
|
365
|
+
provider: "anthropic",
|
|
366
|
+
message: "Official Anthropic API configured successfully"
|
|
367
|
+
};
|
|
368
|
+
} catch (error) {
|
|
369
|
+
return {
|
|
370
|
+
success: false,
|
|
371
|
+
mode: "official",
|
|
372
|
+
error: error instanceof Error ? error.message : String(error)
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
function configureWithPreset(preset, apiKey) {
|
|
377
|
+
if (preset.id === "anthropic") {
|
|
378
|
+
return configureOfficialMode(apiKey);
|
|
379
|
+
}
|
|
380
|
+
return configureSimpleMode({
|
|
381
|
+
mode: "simple",
|
|
382
|
+
provider: preset.id,
|
|
383
|
+
apiKey,
|
|
384
|
+
baseUrl: preset.baseUrl,
|
|
385
|
+
model: preset.defaultModel
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
function getCurrentConfig() {
|
|
389
|
+
try {
|
|
390
|
+
const settings = readSettings();
|
|
391
|
+
if (!settings.env) {
|
|
392
|
+
return null;
|
|
393
|
+
}
|
|
394
|
+
return {
|
|
395
|
+
ANTHROPIC_BASE_URL: settings.env.ANTHROPIC_BASE_URL,
|
|
396
|
+
ANTHROPIC_API_KEY: settings.env.ANTHROPIC_API_KEY,
|
|
397
|
+
ANTHROPIC_AUTH_TOKEN: settings.env.ANTHROPIC_AUTH_TOKEN
|
|
398
|
+
};
|
|
399
|
+
} catch {
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
function detectCurrentMode() {
|
|
404
|
+
const config = getCurrentConfig();
|
|
405
|
+
if (!config) {
|
|
406
|
+
return { mode: "none" };
|
|
407
|
+
}
|
|
408
|
+
if (config.ANTHROPIC_BASE_URL?.includes("127.0.0.1:3456") || config.ANTHROPIC_BASE_URL?.includes("localhost:3456")) {
|
|
409
|
+
return { mode: "ccr", provider: "ccr" };
|
|
410
|
+
}
|
|
411
|
+
if (!config.ANTHROPIC_BASE_URL || config.ANTHROPIC_BASE_URL.includes("api.anthropic.com")) {
|
|
412
|
+
if (config.ANTHROPIC_AUTH_TOKEN) {
|
|
413
|
+
return { mode: "official", provider: "anthropic-oauth" };
|
|
414
|
+
}
|
|
415
|
+
if (config.ANTHROPIC_API_KEY) {
|
|
416
|
+
return { mode: "official", provider: "anthropic" };
|
|
417
|
+
}
|
|
418
|
+
return { mode: "none" };
|
|
419
|
+
}
|
|
420
|
+
const baseUrl = config.ANTHROPIC_BASE_URL.toLowerCase();
|
|
421
|
+
let provider = "custom";
|
|
422
|
+
if (baseUrl.includes("302.ai"))
|
|
423
|
+
provider = "302ai";
|
|
424
|
+
else if (baseUrl.includes("openrouter.ai"))
|
|
425
|
+
provider = "openrouter";
|
|
426
|
+
else if (baseUrl.includes("deepseek.com"))
|
|
427
|
+
provider = "deepseek";
|
|
428
|
+
else if (baseUrl.includes("dashscope.aliyuncs.com"))
|
|
429
|
+
provider = "qwen";
|
|
430
|
+
else if (baseUrl.includes("siliconflow.cn"))
|
|
431
|
+
provider = "siliconflow";
|
|
432
|
+
else if (baseUrl.includes("modelscope.cn"))
|
|
433
|
+
provider = "modelscope";
|
|
434
|
+
else if (baseUrl.includes("volces.com"))
|
|
435
|
+
provider = "volcengine";
|
|
436
|
+
else if (baseUrl.includes("moonshot.cn"))
|
|
437
|
+
provider = "kimi";
|
|
438
|
+
else if (baseUrl.includes("bigmodel.cn"))
|
|
439
|
+
provider = "glm";
|
|
440
|
+
else if (baseUrl.includes("generativelanguage.googleapis.com"))
|
|
441
|
+
provider = "gemini";
|
|
442
|
+
else if (baseUrl.includes("groq.com"))
|
|
443
|
+
provider = "groq";
|
|
444
|
+
else if (baseUrl.includes("localhost:11434"))
|
|
445
|
+
provider = "ollama";
|
|
446
|
+
return { mode: "simple", provider };
|
|
447
|
+
}
|
|
448
|
+
function validateApiKey(apiKey, provider) {
|
|
449
|
+
if (!apiKey || apiKey.trim() === "") {
|
|
450
|
+
return { valid: false, message: "API key is required" };
|
|
451
|
+
}
|
|
452
|
+
if (provider === "anthropic") {
|
|
453
|
+
if (!apiKey.startsWith("sk-ant-")) {
|
|
454
|
+
return { valid: false, message: "Anthropic API key should start with sk-ant-" };
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
if (provider === "openrouter") {
|
|
458
|
+
if (!apiKey.startsWith("sk-or-")) {
|
|
459
|
+
return { valid: false, message: "OpenRouter API key should start with sk-or-" };
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
return { valid: true };
|
|
463
|
+
}
|
|
464
|
+
function quickSetup(providerId, apiKey) {
|
|
465
|
+
const preset = getPresetById(providerId);
|
|
466
|
+
if (!preset) {
|
|
467
|
+
return {
|
|
468
|
+
success: false,
|
|
469
|
+
mode: "simple",
|
|
470
|
+
error: `Unknown provider: ${providerId}`
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
if (preset.requiresApiKey) {
|
|
474
|
+
const validation = validateApiKey(apiKey, providerId);
|
|
475
|
+
if (!validation.valid) {
|
|
476
|
+
return {
|
|
477
|
+
success: false,
|
|
478
|
+
mode: "simple",
|
|
479
|
+
error: validation.message
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
return configureWithPreset(preset, apiKey);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
function displayCurrentStatus(lang = "en") {
|
|
487
|
+
const { mode, provider } = detectCurrentMode();
|
|
488
|
+
const config = getCurrentConfig();
|
|
489
|
+
console.log("");
|
|
490
|
+
console.log(ansis.cyan("\u2550".repeat(50)));
|
|
491
|
+
console.log(ansis.bold.cyan(lang === "zh-CN" ? " \u5F53\u524D API \u914D\u7F6E" : " Current API Configuration"));
|
|
492
|
+
console.log(ansis.cyan("\u2550".repeat(50)));
|
|
493
|
+
console.log("");
|
|
494
|
+
if (mode === "none") {
|
|
495
|
+
console.log(ansis.yellow(lang === "zh-CN" ? " \u26A0 \u672A\u914D\u7F6E API" : " \u26A0 No API configured"));
|
|
496
|
+
console.log("");
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
const modeLabels = {
|
|
500
|
+
official: lang === "zh-CN" ? "\u5B98\u65B9 Anthropic" : "Official Anthropic",
|
|
501
|
+
simple: lang === "zh-CN" ? "\u7B80\u5355\u6A21\u5F0F (API \u4E2D\u8F6C)" : "Simple Mode (API Proxy)",
|
|
502
|
+
ccr: lang === "zh-CN" ? "CCR \u9AD8\u7EA7\u8DEF\u7531" : "CCR Advanced Router"
|
|
503
|
+
};
|
|
504
|
+
console.log(` ${ansis.bold(lang === "zh-CN" ? "\u6A21\u5F0F:" : "Mode:")} ${ansis.green(modeLabels[mode])}`);
|
|
505
|
+
if (provider) {
|
|
506
|
+
const preset = getPresetById(provider);
|
|
507
|
+
const providerName = preset ? lang === "zh-CN" ? preset.nameZh : preset.name : provider;
|
|
508
|
+
console.log(` ${ansis.bold(lang === "zh-CN" ? "\u63D0\u4F9B\u5546:" : "Provider:")} ${ansis.cyan(providerName)}`);
|
|
509
|
+
}
|
|
510
|
+
if (config?.ANTHROPIC_BASE_URL) {
|
|
511
|
+
console.log(` ${ansis.bold("Base URL:")} ${ansis.gray(config.ANTHROPIC_BASE_URL)}`);
|
|
512
|
+
}
|
|
513
|
+
if (config?.ANTHROPIC_API_KEY) {
|
|
514
|
+
const masked = `${config.ANTHROPIC_API_KEY.substring(0, 10)}...`;
|
|
515
|
+
console.log(` ${ansis.bold("API Key:")} ${ansis.gray(masked)}`);
|
|
516
|
+
}
|
|
517
|
+
console.log("");
|
|
518
|
+
}
|
|
519
|
+
async function runConfigWizard(lang = "en") {
|
|
520
|
+
console.log("");
|
|
521
|
+
console.log(ansis.cyan("\u2550".repeat(50)));
|
|
522
|
+
console.log(ansis.bold.cyan(lang === "zh-CN" ? " API \u914D\u7F6E\u5411\u5BFC" : " API Configuration Wizard"));
|
|
523
|
+
console.log(ansis.cyan("\u2550".repeat(50)));
|
|
524
|
+
console.log("");
|
|
525
|
+
const modeChoices = [
|
|
526
|
+
{
|
|
527
|
+
name: lang === "zh-CN" ? "1. \u5FEB\u901F\u914D\u7F6E (\u63A8\u8350) - \u9009\u62E9\u9884\u8BBE\u63D0\u4F9B\u5546" : "1. Quick Setup (Recommended) - Choose preset provider",
|
|
528
|
+
value: "quick"
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
name: lang === "zh-CN" ? "2. \u5B98\u65B9 Anthropic API - \u76F4\u63A5\u8FDE\u63A5 Anthropic" : "2. Official Anthropic API - Direct connection",
|
|
532
|
+
value: "official"
|
|
533
|
+
},
|
|
534
|
+
{
|
|
535
|
+
name: lang === "zh-CN" ? "3. \u81EA\u5B9A\u4E49\u914D\u7F6E - \u624B\u52A8\u8F93\u5165 API \u5730\u5740\u548C\u5BC6\u94A5" : "3. Custom Configuration - Manual API URL and key",
|
|
536
|
+
value: "custom"
|
|
537
|
+
},
|
|
538
|
+
{
|
|
539
|
+
name: lang === "zh-CN" ? "4. CCR \u9AD8\u7EA7\u8DEF\u7531 - \u5B8C\u6574 Claude Code Router \u914D\u7F6E" : "4. CCR Advanced Router - Full Claude Code Router setup",
|
|
540
|
+
value: "ccr"
|
|
541
|
+
}
|
|
542
|
+
];
|
|
543
|
+
const { mode } = await inquirer.prompt({
|
|
544
|
+
type: "list",
|
|
545
|
+
name: "mode",
|
|
546
|
+
message: lang === "zh-CN" ? "\u9009\u62E9\u914D\u7F6E\u6A21\u5F0F:" : "Select configuration mode:",
|
|
547
|
+
choices: modeChoices
|
|
548
|
+
});
|
|
549
|
+
switch (mode) {
|
|
550
|
+
case "quick":
|
|
551
|
+
return await runQuickSetup(lang);
|
|
552
|
+
case "official":
|
|
553
|
+
return await runOfficialSetup(lang);
|
|
554
|
+
case "custom":
|
|
555
|
+
return await runCustomSetup(lang);
|
|
556
|
+
case "ccr":
|
|
557
|
+
return await runCcrSetup(lang);
|
|
558
|
+
default:
|
|
559
|
+
return { success: false, mode: "simple", error: "Unknown mode" };
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
async function runQuickSetup(lang) {
|
|
563
|
+
const recommended = getRecommendedPresets();
|
|
564
|
+
const chinese = getChinesePresets().filter((p) => !recommended.find((r) => r.id === p.id));
|
|
565
|
+
const all = getAllPresets();
|
|
566
|
+
const choices = [
|
|
567
|
+
new inquirer.Separator(lang === "zh-CN" ? "\u2500\u2500\u2500 \u63A8\u8350 \u2500\u2500\u2500" : "\u2500\u2500\u2500 Recommended \u2500\u2500\u2500"),
|
|
568
|
+
...recommended.map((p, i) => ({
|
|
569
|
+
name: `${i + 1}. ${lang === "zh-CN" ? p.nameZh : p.name} - ${lang === "zh-CN" ? p.descriptionZh : p.description}`,
|
|
570
|
+
value: p.id
|
|
571
|
+
})),
|
|
572
|
+
new inquirer.Separator(lang === "zh-CN" ? "\u2500\u2500\u2500 \u56FD\u5185\u670D\u52A1 \u2500\u2500\u2500" : "\u2500\u2500\u2500 Chinese Providers \u2500\u2500\u2500"),
|
|
573
|
+
...chinese.map((p, i) => ({
|
|
574
|
+
name: `${recommended.length + i + 1}. ${lang === "zh-CN" ? p.nameZh : p.name} - ${lang === "zh-CN" ? p.descriptionZh : p.description}`,
|
|
575
|
+
value: p.id
|
|
576
|
+
})),
|
|
577
|
+
new inquirer.Separator(lang === "zh-CN" ? "\u2500\u2500\u2500 \u66F4\u591A \u2500\u2500\u2500" : "\u2500\u2500\u2500 More \u2500\u2500\u2500"),
|
|
578
|
+
{
|
|
579
|
+
name: lang === "zh-CN" ? "\u67E5\u770B\u6240\u6709\u63D0\u4F9B\u5546..." : "View all providers...",
|
|
580
|
+
value: "__all__"
|
|
581
|
+
}
|
|
582
|
+
];
|
|
583
|
+
const { providerId } = await inquirer.prompt({
|
|
584
|
+
type: "list",
|
|
585
|
+
name: "providerId",
|
|
586
|
+
message: lang === "zh-CN" ? "\u9009\u62E9 API \u63D0\u4F9B\u5546:" : "Select API provider:",
|
|
587
|
+
choices,
|
|
588
|
+
pageSize: 15
|
|
589
|
+
});
|
|
590
|
+
let finalProviderId = providerId;
|
|
591
|
+
if (providerId === "__all__") {
|
|
592
|
+
const allChoices = all.map((p, i) => ({
|
|
593
|
+
name: `${i + 1}. [${p.category}] ${lang === "zh-CN" ? p.nameZh : p.name}`,
|
|
594
|
+
value: p.id
|
|
595
|
+
}));
|
|
596
|
+
const result2 = await inquirer.prompt({
|
|
597
|
+
type: "list",
|
|
598
|
+
name: "providerId",
|
|
599
|
+
message: lang === "zh-CN" ? "\u9009\u62E9\u63D0\u4F9B\u5546:" : "Select provider:",
|
|
600
|
+
choices: allChoices,
|
|
601
|
+
pageSize: 20
|
|
602
|
+
});
|
|
603
|
+
finalProviderId = result2.providerId;
|
|
604
|
+
}
|
|
605
|
+
const preset = getPresetById(finalProviderId);
|
|
606
|
+
if (!preset) {
|
|
607
|
+
return { success: false, mode: "simple", error: "Provider not found" };
|
|
608
|
+
}
|
|
609
|
+
console.log("");
|
|
610
|
+
console.log(ansis.cyan(`\u{1F4CB} ${lang === "zh-CN" ? preset.nameZh : preset.name}`));
|
|
611
|
+
if (preset.instructions) {
|
|
612
|
+
console.log(ansis.gray(` ${lang === "zh-CN" ? preset.instructions.zh : preset.instructions.en}`));
|
|
613
|
+
}
|
|
614
|
+
console.log("");
|
|
615
|
+
let apiKey = "";
|
|
616
|
+
if (preset.requiresApiKey) {
|
|
617
|
+
const { key } = await inquirer.prompt({
|
|
618
|
+
type: "password",
|
|
619
|
+
name: "key",
|
|
620
|
+
message: lang === "zh-CN" ? "\u8F93\u5165 API \u5BC6\u94A5:" : "Enter API key:",
|
|
621
|
+
mask: "*",
|
|
622
|
+
validate: (value) => {
|
|
623
|
+
if (!value)
|
|
624
|
+
return lang === "zh-CN" ? "API \u5BC6\u94A5\u4E0D\u80FD\u4E3A\u7A7A" : "API key is required";
|
|
625
|
+
return true;
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
apiKey = key;
|
|
629
|
+
}
|
|
630
|
+
const result = configureWithPreset(preset, apiKey);
|
|
631
|
+
if (result.success) {
|
|
632
|
+
console.log("");
|
|
633
|
+
console.log(ansis.green(`\u2714 ${lang === "zh-CN" ? "API \u914D\u7F6E\u6210\u529F!" : "API configured successfully!"}`));
|
|
634
|
+
console.log(ansis.gray(` ${lang === "zh-CN" ? "\u63D0\u4F9B\u5546:" : "Provider:"} ${lang === "zh-CN" ? preset.nameZh : preset.name}`));
|
|
635
|
+
console.log(ansis.gray(` ${lang === "zh-CN" ? "\u9ED8\u8BA4\u6A21\u578B:" : "Default model:"} ${preset.defaultModel}`));
|
|
636
|
+
console.log("");
|
|
637
|
+
}
|
|
638
|
+
return result;
|
|
639
|
+
}
|
|
640
|
+
async function runOfficialSetup(lang) {
|
|
641
|
+
console.log("");
|
|
642
|
+
console.log(ansis.cyan(lang === "zh-CN" ? "\u{1F4CB} \u5B98\u65B9 Anthropic API" : "\u{1F4CB} Official Anthropic API"));
|
|
643
|
+
console.log(ansis.gray(lang === "zh-CN" ? " \u4ECE https://console.anthropic.com/settings/keys \u83B7\u53D6 API \u5BC6\u94A5" : " Get your API key from https://console.anthropic.com/settings/keys"));
|
|
644
|
+
console.log("");
|
|
645
|
+
const { apiKey } = await inquirer.prompt({
|
|
646
|
+
type: "password",
|
|
647
|
+
name: "apiKey",
|
|
648
|
+
message: lang === "zh-CN" ? "\u8F93\u5165 Anthropic API \u5BC6\u94A5:" : "Enter Anthropic API key:",
|
|
649
|
+
mask: "*",
|
|
650
|
+
validate: (value) => {
|
|
651
|
+
if (!value)
|
|
652
|
+
return lang === "zh-CN" ? "API \u5BC6\u94A5\u4E0D\u80FD\u4E3A\u7A7A" : "API key is required";
|
|
653
|
+
if (!value.startsWith("sk-ant-")) {
|
|
654
|
+
return lang === "zh-CN" ? "Anthropic API \u5BC6\u94A5\u5E94\u4EE5 sk-ant- \u5F00\u5934" : "Anthropic API key should start with sk-ant-";
|
|
655
|
+
}
|
|
656
|
+
return true;
|
|
657
|
+
}
|
|
658
|
+
});
|
|
659
|
+
const result = configureOfficialMode(apiKey);
|
|
660
|
+
if (result.success) {
|
|
661
|
+
console.log("");
|
|
662
|
+
console.log(ansis.green(`\u2714 ${lang === "zh-CN" ? "\u5B98\u65B9 API \u914D\u7F6E\u6210\u529F!" : "Official API configured successfully!"}`));
|
|
663
|
+
console.log("");
|
|
664
|
+
}
|
|
665
|
+
return result;
|
|
666
|
+
}
|
|
667
|
+
async function runCustomSetup(lang) {
|
|
668
|
+
console.log("");
|
|
669
|
+
console.log(ansis.cyan(lang === "zh-CN" ? "\u{1F4CB} \u81EA\u5B9A\u4E49 API \u914D\u7F6E" : "\u{1F4CB} Custom API Configuration"));
|
|
670
|
+
console.log("");
|
|
671
|
+
const { baseUrl } = await inquirer.prompt({
|
|
672
|
+
type: "input",
|
|
673
|
+
name: "baseUrl",
|
|
674
|
+
message: lang === "zh-CN" ? "\u8F93\u5165 API Base URL:" : "Enter API Base URL:",
|
|
675
|
+
validate: (value) => {
|
|
676
|
+
if (!value)
|
|
677
|
+
return lang === "zh-CN" ? "URL \u4E0D\u80FD\u4E3A\u7A7A" : "URL is required";
|
|
678
|
+
if (!value.startsWith("http")) {
|
|
679
|
+
return lang === "zh-CN" ? "URL \u5FC5\u987B\u4EE5 http:// \u6216 https:// \u5F00\u5934" : "URL must start with http:// or https://";
|
|
680
|
+
}
|
|
681
|
+
return true;
|
|
682
|
+
}
|
|
683
|
+
});
|
|
684
|
+
const { apiKey } = await inquirer.prompt({
|
|
685
|
+
type: "password",
|
|
686
|
+
name: "apiKey",
|
|
687
|
+
message: lang === "zh-CN" ? "\u8F93\u5165 API \u5BC6\u94A5:" : "Enter API key:",
|
|
688
|
+
mask: "*",
|
|
689
|
+
validate: (value) => {
|
|
690
|
+
if (!value)
|
|
691
|
+
return lang === "zh-CN" ? "API \u5BC6\u94A5\u4E0D\u80FD\u4E3A\u7A7A" : "API key is required";
|
|
692
|
+
return true;
|
|
693
|
+
}
|
|
694
|
+
});
|
|
695
|
+
const result = configureSimpleMode({
|
|
696
|
+
mode: "simple",
|
|
697
|
+
provider: "custom",
|
|
698
|
+
apiKey,
|
|
699
|
+
baseUrl
|
|
700
|
+
});
|
|
701
|
+
if (result.success) {
|
|
702
|
+
console.log("");
|
|
703
|
+
console.log(ansis.green(`\u2714 ${lang === "zh-CN" ? "\u81EA\u5B9A\u4E49 API \u914D\u7F6E\u6210\u529F!" : "Custom API configured successfully!"}`));
|
|
704
|
+
console.log("");
|
|
705
|
+
}
|
|
706
|
+
return result;
|
|
707
|
+
}
|
|
708
|
+
async function runCcrSetup(lang) {
|
|
709
|
+
console.log("");
|
|
710
|
+
console.log(ansis.cyan(lang === "zh-CN" ? "\u{1F4CB} CCR \u9AD8\u7EA7\u8DEF\u7531\u914D\u7F6E" : "\u{1F4CB} CCR Advanced Router Configuration"));
|
|
711
|
+
console.log(ansis.gray(lang === "zh-CN" ? " CCR \u63D0\u4F9B\u5B8C\u6574\u7684\u6A21\u578B\u8DEF\u7531\u3001\u8F6C\u6362\u548C\u591A\u63D0\u4F9B\u5546\u652F\u6301" : " CCR provides full model routing, transformation, and multi-provider support"));
|
|
712
|
+
console.log("");
|
|
713
|
+
try {
|
|
714
|
+
const { setupCcrConfiguration } = await import('../chunks/init.mjs').then(function (n) { return n.F; });
|
|
715
|
+
const success = await setupCcrConfiguration();
|
|
716
|
+
return {
|
|
717
|
+
success,
|
|
718
|
+
mode: "ccr",
|
|
719
|
+
provider: "ccr",
|
|
720
|
+
message: success ? lang === "zh-CN" ? "CCR \u914D\u7F6E\u6210\u529F" : "CCR configured successfully" : lang === "zh-CN" ? "CCR \u914D\u7F6E\u5931\u8D25" : "CCR configuration failed"
|
|
721
|
+
};
|
|
722
|
+
} catch (error) {
|
|
723
|
+
return {
|
|
724
|
+
success: false,
|
|
725
|
+
mode: "ccr",
|
|
726
|
+
error: error instanceof Error ? error.message : String(error)
|
|
727
|
+
};
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
async function testApiConnection(lang = "en") {
|
|
731
|
+
const config = getCurrentConfig();
|
|
732
|
+
if (!config || !config.ANTHROPIC_API_KEY && !config.ANTHROPIC_AUTH_TOKEN) {
|
|
733
|
+
console.log(ansis.yellow(lang === "zh-CN" ? "\u26A0 \u672A\u914D\u7F6E API" : "\u26A0 No API configured"));
|
|
734
|
+
return false;
|
|
735
|
+
}
|
|
736
|
+
console.log(ansis.cyan(lang === "zh-CN" ? "\u{1F50D} \u6D4B\u8BD5 API \u8FDE\u63A5..." : "\u{1F50D} Testing API connection..."));
|
|
737
|
+
try {
|
|
738
|
+
const baseUrl = config.ANTHROPIC_BASE_URL || "https://api.anthropic.com";
|
|
739
|
+
const testUrl = baseUrl.includes("v1") ? baseUrl : `${baseUrl}/v1/models`;
|
|
740
|
+
const response = await fetch(testUrl, {
|
|
741
|
+
method: "GET",
|
|
742
|
+
headers: {
|
|
743
|
+
"x-api-key": config.ANTHROPIC_API_KEY || "",
|
|
744
|
+
"anthropic-version": "2023-06-01"
|
|
745
|
+
}
|
|
746
|
+
});
|
|
747
|
+
if (response.ok || response.status === 401) {
|
|
748
|
+
console.log(ansis.green(lang === "zh-CN" ? "\u2714 API \u8FDE\u63A5\u6210\u529F" : "\u2714 API connection successful"));
|
|
749
|
+
return true;
|
|
750
|
+
} else {
|
|
751
|
+
console.log(ansis.yellow(`\u26A0 API returned status: ${response.status}`));
|
|
752
|
+
return false;
|
|
753
|
+
}
|
|
754
|
+
} catch (error) {
|
|
755
|
+
console.log(ansis.red(lang === "zh-CN" ? "\u2716 API \u8FDE\u63A5\u5931\u8D25" : "\u2716 API connection failed"));
|
|
756
|
+
console.log(ansis.gray(` ${error instanceof Error ? error.message : String(error)}`));
|
|
757
|
+
return false;
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
export { displayCurrentStatus as d, getAllPresets as g, quickSetup as q, runConfigWizard as r, testApiConnection as t };
|