@pikecode/api-key-manager 2.0.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/LICENSE +21 -0
- package/README.md +232 -0
- package/bin/akm.js +101 -0
- package/bin/cc.js +101 -0
- package/package.json +71 -0
- package/src/CommandRegistry.js +74 -0
- package/src/commands/BaseCommand.js +212 -0
- package/src/commands/add.js +514 -0
- package/src/commands/current.js +94 -0
- package/src/commands/edit.js +208 -0
- package/src/commands/list.js +122 -0
- package/src/commands/remove.js +150 -0
- package/src/commands/switch.js +1479 -0
- package/src/config.js +250 -0
- package/src/index.js +19 -0
- package/src/navigation/EscNavigationManager.js +213 -0
- package/src/utils/claude-settings.js +150 -0
- package/src/utils/config-opener.js +44 -0
- package/src/utils/env-launcher.js +80 -0
- package/src/utils/error-handler.js +53 -0
- package/src/utils/inquirer-setup.js +89 -0
- package/src/utils/logger.js +41 -0
- package/src/utils/provider-status-checker.js +210 -0
- package/src/utils/storage.js +55 -0
- package/src/utils/terminal-format.js +41 -0
- package/src/utils/ui-helper.js +227 -0
- package/src/utils/update-checker.js +121 -0
- package/src/utils/validator.js +157 -0
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
const inquirer = require('inquirer');
|
|
2
|
+
const chalk = require('chalk');
|
|
3
|
+
const { ConfigManager } = require('../config');
|
|
4
|
+
const { validator } = require('../utils/validator');
|
|
5
|
+
const { Logger } = require('../utils/logger');
|
|
6
|
+
const { UIHelper } = require('../utils/ui-helper');
|
|
7
|
+
const { BaseCommand } = require('./BaseCommand');
|
|
8
|
+
|
|
9
|
+
class ProviderAdder extends BaseCommand {
|
|
10
|
+
constructor() {
|
|
11
|
+
super();
|
|
12
|
+
this.configManager = new ConfigManager();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async interactive() {
|
|
16
|
+
console.log(UIHelper.createTitle('添加新供应商', UIHelper.icons.add));
|
|
17
|
+
console.log();
|
|
18
|
+
console.log(UIHelper.createTooltip('选择供应商类型或手动配置'));
|
|
19
|
+
console.log();
|
|
20
|
+
console.log(UIHelper.createStepIndicator(1, 3, '选择供应商类型'));
|
|
21
|
+
console.log(UIHelper.createHintLine([
|
|
22
|
+
['↑ / ↓', '选择类型'],
|
|
23
|
+
['Enter', '确认'],
|
|
24
|
+
['ESC', '取消添加']
|
|
25
|
+
]));
|
|
26
|
+
console.log();
|
|
27
|
+
|
|
28
|
+
// 设置 ESC 键监听
|
|
29
|
+
const escListener = this.createESCListener(() => {
|
|
30
|
+
Logger.info('取消添加供应商');
|
|
31
|
+
// 使用CommandRegistry避免循环引用
|
|
32
|
+
const { registry } = require('../CommandRegistry');
|
|
33
|
+
registry.executeCommand('switch');
|
|
34
|
+
}, '取消添加');
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
// 首先选择是否使用预设配置
|
|
38
|
+
const typeAnswer = await this.prompt([
|
|
39
|
+
{
|
|
40
|
+
type: 'list',
|
|
41
|
+
name: 'providerType',
|
|
42
|
+
message: '选择供应商类型:',
|
|
43
|
+
choices: [
|
|
44
|
+
{ name: '🔒 官方 Claude Code (OAuth)', value: 'official_oauth' },
|
|
45
|
+
{ name: '⚙️ 自定义配置', value: 'custom' }
|
|
46
|
+
],
|
|
47
|
+
default: 'custom'
|
|
48
|
+
}
|
|
49
|
+
]);
|
|
50
|
+
|
|
51
|
+
// 移除 ESC 键监听
|
|
52
|
+
this.removeESCListener(escListener);
|
|
53
|
+
|
|
54
|
+
if (typeAnswer.providerType === 'official_oauth') {
|
|
55
|
+
return await this.addOfficialOAuthProvider();
|
|
56
|
+
} else {
|
|
57
|
+
return await this.addCustomProvider();
|
|
58
|
+
}
|
|
59
|
+
} catch (error) {
|
|
60
|
+
// 移除 ESC 键监听
|
|
61
|
+
this.removeESCListener(escListener);
|
|
62
|
+
if (this.isEscCancelled(error)) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async addOfficialOAuthProvider() {
|
|
70
|
+
console.log(UIHelper.createTitle('添加官方 OAuth 供应商', UIHelper.icons.add));
|
|
71
|
+
console.log();
|
|
72
|
+
console.log(UIHelper.createTooltip('配置官方 Claude Code OAuth 认证'));
|
|
73
|
+
console.log();
|
|
74
|
+
console.log(UIHelper.createStepIndicator(2, 3, '填写官方 OAuth 信息'));
|
|
75
|
+
console.log(UIHelper.createHintLine([
|
|
76
|
+
['Enter', '确认输入'],
|
|
77
|
+
['Tab', '切换字段'],
|
|
78
|
+
['ESC', '取消添加']
|
|
79
|
+
]));
|
|
80
|
+
console.log();
|
|
81
|
+
|
|
82
|
+
// 设置 ESC 键监听
|
|
83
|
+
const escListener = this.createESCListener(() => {
|
|
84
|
+
Logger.info('取消添加供应商');
|
|
85
|
+
// 使用CommandRegistry避免循环引用
|
|
86
|
+
const { registry } = require('../CommandRegistry');
|
|
87
|
+
registry.executeCommand('switch');
|
|
88
|
+
}, '取消添加');
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
const answers = await this.prompt([
|
|
92
|
+
{
|
|
93
|
+
type: 'input',
|
|
94
|
+
name: 'name',
|
|
95
|
+
message: '请输入供应商名称 (用于命令行):',
|
|
96
|
+
default: 'claude-official',
|
|
97
|
+
validate: (input) => {
|
|
98
|
+
const error = validator.validateName(input);
|
|
99
|
+
if (error) return error;
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
type: 'input',
|
|
105
|
+
name: 'displayName',
|
|
106
|
+
message: '请输入供应商显示名称:',
|
|
107
|
+
default: 'Claude Code 官方 (OAuth)',
|
|
108
|
+
validate: (input) => {
|
|
109
|
+
const error = validator.validateDisplayName(input);
|
|
110
|
+
if (error) return error;
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
type: 'input',
|
|
116
|
+
name: 'authToken',
|
|
117
|
+
message: '请输入 OAuth Token (sk-ant-oat01-...):',
|
|
118
|
+
validate: (input) => {
|
|
119
|
+
if (!input || !input.startsWith('sk-ant-oat01-')) {
|
|
120
|
+
return '请输入有效的 OAuth Token (格式: sk-ant-oat01-...)';
|
|
121
|
+
}
|
|
122
|
+
const error = validator.validateToken(input);
|
|
123
|
+
if (error) return error;
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
type: 'confirm',
|
|
129
|
+
name: 'setAsDefault',
|
|
130
|
+
message: '是否设置为当前供应商?',
|
|
131
|
+
default: true
|
|
132
|
+
}
|
|
133
|
+
]);
|
|
134
|
+
|
|
135
|
+
// 移除 ESC 键监听
|
|
136
|
+
this.removeESCListener(escListener);
|
|
137
|
+
|
|
138
|
+
// 使用官方 OAuth 配置
|
|
139
|
+
await this.saveProvider({
|
|
140
|
+
...answers,
|
|
141
|
+
authMode: 'oauth_token',
|
|
142
|
+
baseUrl: null // OAuth 模式不需要 baseUrl
|
|
143
|
+
});
|
|
144
|
+
} catch (error) {
|
|
145
|
+
// 移除 ESC 键监听
|
|
146
|
+
this.removeESCListener(escListener);
|
|
147
|
+
if (this.isEscCancelled(error)) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
throw error;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async addCustomProvider() {
|
|
155
|
+
console.log(UIHelper.createTitle('添加自定义供应商', UIHelper.icons.add));
|
|
156
|
+
console.log();
|
|
157
|
+
console.log(UIHelper.createTooltip('请填写供应商配置信息'));
|
|
158
|
+
console.log();
|
|
159
|
+
console.log(UIHelper.createStepIndicator(2, 3, '填写供应商信息'));
|
|
160
|
+
console.log(UIHelper.createHintLine([
|
|
161
|
+
['Enter', '确认输入'],
|
|
162
|
+
['Tab', '切换字段'],
|
|
163
|
+
['ESC', '取消添加']
|
|
164
|
+
]));
|
|
165
|
+
console.log();
|
|
166
|
+
|
|
167
|
+
// 设置 ESC 键监听
|
|
168
|
+
const escListener = this.createESCListener(() => {
|
|
169
|
+
Logger.info('取消添加供应商');
|
|
170
|
+
// 使用CommandRegistry避免循环引用
|
|
171
|
+
const { registry } = require('../CommandRegistry');
|
|
172
|
+
registry.executeCommand('switch');
|
|
173
|
+
}, '取消添加');
|
|
174
|
+
|
|
175
|
+
try {
|
|
176
|
+
const answers = await this.prompt([
|
|
177
|
+
{
|
|
178
|
+
type: 'input',
|
|
179
|
+
name: 'name',
|
|
180
|
+
message: '请输入供应商名称 (用于命令行):',
|
|
181
|
+
validate: (input) => {
|
|
182
|
+
const error = validator.validateName(input);
|
|
183
|
+
if (error) return error;
|
|
184
|
+
return true;
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
type: 'input',
|
|
189
|
+
name: 'displayName',
|
|
190
|
+
message: '请输入供应商显示名称 (可选,默认为供应商名称):',
|
|
191
|
+
validate: (input) => {
|
|
192
|
+
const error = validator.validateDisplayName(input);
|
|
193
|
+
if (error) return error;
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
type: 'list',
|
|
199
|
+
name: 'authMode',
|
|
200
|
+
message: '选择认证模式:',
|
|
201
|
+
choices: [
|
|
202
|
+
{ name: '🔑 通用API密钥模式 - 支持 ANTHROPIC_API_KEY 和 ANTHROPIC_AUTH_TOKEN', value: 'api_key' },
|
|
203
|
+
{ name: '🔐 认证令牌模式 (仅 ANTHROPIC_AUTH_TOKEN) - 适用于某些服务商', value: 'auth_token' },
|
|
204
|
+
{ name: '🌐 OAuth令牌模式 (CLAUDE_CODE_OAUTH_TOKEN) - 适用于官方Claude Code', value: 'oauth_token' }
|
|
205
|
+
],
|
|
206
|
+
default: 'api_key'
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
type: 'list',
|
|
210
|
+
name: 'tokenType',
|
|
211
|
+
message: '选择Token类型:',
|
|
212
|
+
choices: [
|
|
213
|
+
{ name: '🔑 ANTHROPIC_API_KEY - 通用API密钥', value: 'api_key' },
|
|
214
|
+
{ name: '🔐 ANTHROPIC_AUTH_TOKEN - 认证令牌', value: 'auth_token' }
|
|
215
|
+
],
|
|
216
|
+
default: 'api_key',
|
|
217
|
+
when: (answers) => answers.authMode === 'api_key'
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
type: 'input',
|
|
221
|
+
name: 'baseUrl',
|
|
222
|
+
message: '请输入API基础URL:',
|
|
223
|
+
validate: (input) => {
|
|
224
|
+
const error = validator.validateUrl(input);
|
|
225
|
+
if (error) return error;
|
|
226
|
+
return true;
|
|
227
|
+
},
|
|
228
|
+
when: (answers) => answers.authMode === 'api_key' || answers.authMode === 'auth_token'
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
type: 'input',
|
|
232
|
+
name: 'authToken',
|
|
233
|
+
message: (answers) => {
|
|
234
|
+
switch (answers.authMode) {
|
|
235
|
+
case 'api_key':
|
|
236
|
+
const tokenTypeLabel = answers.tokenType === 'auth_token' ? 'ANTHROPIC_AUTH_TOKEN' : 'ANTHROPIC_API_KEY';
|
|
237
|
+
return `请输入Token (${tokenTypeLabel}):`;
|
|
238
|
+
case 'auth_token':
|
|
239
|
+
return '请输入认证令牌 (ANTHROPIC_AUTH_TOKEN):';
|
|
240
|
+
case 'oauth_token':
|
|
241
|
+
return '请输入OAuth令牌 (CLAUDE_CODE_OAUTH_TOKEN):';
|
|
242
|
+
default:
|
|
243
|
+
return '请输入认证令牌:';
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
validate: (input) => {
|
|
247
|
+
const error = validator.validateToken(input);
|
|
248
|
+
if (error) return error;
|
|
249
|
+
return true;
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
type: 'confirm',
|
|
254
|
+
name: 'setAsDefault',
|
|
255
|
+
message: '是否设置为当前供应商?',
|
|
256
|
+
default: true
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
type: 'confirm',
|
|
260
|
+
name: 'configureLaunchArgs',
|
|
261
|
+
message: '是否配置启动参数?',
|
|
262
|
+
default: false
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
type: 'confirm',
|
|
266
|
+
name: 'configureModels',
|
|
267
|
+
message: '是否配置模型参数?',
|
|
268
|
+
default: false
|
|
269
|
+
}
|
|
270
|
+
]);
|
|
271
|
+
|
|
272
|
+
// 移除 ESC 键监听
|
|
273
|
+
this.removeESCListener(escListener);
|
|
274
|
+
|
|
275
|
+
await this.saveProvider(answers);
|
|
276
|
+
} catch (error) {
|
|
277
|
+
// 移除 ESC 键监听
|
|
278
|
+
this.removeESCListener(escListener);
|
|
279
|
+
throw error;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
async saveProvider(answers) {
|
|
284
|
+
try {
|
|
285
|
+
await this.configManager.load();
|
|
286
|
+
|
|
287
|
+
if (this.configManager.getProvider(answers.name)) {
|
|
288
|
+
const shouldOverwrite = await this.confirmOverwrite(answers.name);
|
|
289
|
+
if (!shouldOverwrite) {
|
|
290
|
+
Logger.warning('操作已取消');
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const launchArgs = answers.configureLaunchArgs
|
|
296
|
+
? await this.promptLaunchArgsSelection()
|
|
297
|
+
: [];
|
|
298
|
+
|
|
299
|
+
const modelConfig = answers.configureModels
|
|
300
|
+
? await this.promptModelConfiguration()
|
|
301
|
+
: { primaryModel: null, smallFastModel: null };
|
|
302
|
+
|
|
303
|
+
await this.configManager.addProvider(answers.name, {
|
|
304
|
+
displayName: answers.displayName || answers.name,
|
|
305
|
+
baseUrl: answers.baseUrl,
|
|
306
|
+
authToken: answers.authToken,
|
|
307
|
+
authMode: answers.authMode,
|
|
308
|
+
tokenType: answers.tokenType, // 仅在 authMode 为 'api_key' 时使用
|
|
309
|
+
launchArgs,
|
|
310
|
+
primaryModel: modelConfig.primaryModel,
|
|
311
|
+
smallFastModel: modelConfig.smallFastModel,
|
|
312
|
+
setAsDefault: answers.setAsDefault
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
this.printProviderSummary(answers, launchArgs, modelConfig);
|
|
316
|
+
await this.pauseBeforeReturn();
|
|
317
|
+
|
|
318
|
+
const { registry } = require('../CommandRegistry');
|
|
319
|
+
return await registry.executeCommand('switch');
|
|
320
|
+
} catch (error) {
|
|
321
|
+
if (this.isEscCancelled(error)) {
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
Logger.error(`添加供应商失败: ${error.message}`);
|
|
325
|
+
throw error;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
async confirmOverwrite(name) {
|
|
330
|
+
const escListener = this.createESCListener(() => {
|
|
331
|
+
Logger.info('取消覆盖供应商');
|
|
332
|
+
const { switchCommand } = require('./switch');
|
|
333
|
+
switchCommand();
|
|
334
|
+
}, '取消覆盖');
|
|
335
|
+
|
|
336
|
+
try {
|
|
337
|
+
const { overwrite } = await this.prompt([
|
|
338
|
+
{
|
|
339
|
+
type: 'confirm',
|
|
340
|
+
name: 'overwrite',
|
|
341
|
+
message: `供应商 '${name}' 已存在,是否覆盖?`,
|
|
342
|
+
default: false
|
|
343
|
+
}
|
|
344
|
+
]);
|
|
345
|
+
|
|
346
|
+
this.removeESCListener(escListener);
|
|
347
|
+
return overwrite;
|
|
348
|
+
} catch (error) {
|
|
349
|
+
this.removeESCListener(escListener);
|
|
350
|
+
throw error;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
async promptLaunchArgsSelection() {
|
|
355
|
+
console.log(UIHelper.createTitle('配置启动参数', UIHelper.icons.settings));
|
|
356
|
+
console.log();
|
|
357
|
+
console.log(UIHelper.createTooltip('选择要使用的启动参数'));
|
|
358
|
+
console.log();
|
|
359
|
+
console.log(UIHelper.createStepIndicator(3, 3, '可选: 配置启动参数'));
|
|
360
|
+
console.log(UIHelper.createHintLine([
|
|
361
|
+
['空格', '切换选中'],
|
|
362
|
+
['A', '全选'],
|
|
363
|
+
['I', '反选'],
|
|
364
|
+
['Enter', '确认选择'],
|
|
365
|
+
['ESC', '跳过配置']
|
|
366
|
+
]));
|
|
367
|
+
console.log();
|
|
368
|
+
|
|
369
|
+
const escListener = this.createESCListener(() => {
|
|
370
|
+
Logger.info('跳过启动参数配置');
|
|
371
|
+
}, '跳过配置');
|
|
372
|
+
|
|
373
|
+
try {
|
|
374
|
+
const { launchArgs } = await this.prompt([
|
|
375
|
+
{
|
|
376
|
+
type: 'checkbox',
|
|
377
|
+
name: 'launchArgs',
|
|
378
|
+
message: '请选择启动参数:',
|
|
379
|
+
choices: validator.getAvailableLaunchArgs().map(arg => ({
|
|
380
|
+
name: `${arg.name} - ${arg.description}`,
|
|
381
|
+
value: arg.name,
|
|
382
|
+
checked: false
|
|
383
|
+
}))
|
|
384
|
+
}
|
|
385
|
+
]);
|
|
386
|
+
|
|
387
|
+
this.removeESCListener(escListener);
|
|
388
|
+
return launchArgs;
|
|
389
|
+
} catch (error) {
|
|
390
|
+
this.removeESCListener(escListener);
|
|
391
|
+
if (this.isEscCancelled(error)) {
|
|
392
|
+
return [];
|
|
393
|
+
}
|
|
394
|
+
throw error;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
async promptModelConfiguration() {
|
|
399
|
+
console.log(UIHelper.createTitle('配置模型参数', UIHelper.icons.settings));
|
|
400
|
+
console.log();
|
|
401
|
+
console.log(UIHelper.createTooltip('配置主模型和快速模型(可选)'));
|
|
402
|
+
console.log();
|
|
403
|
+
console.log(UIHelper.createStepIndicator(3, 3, '可选: 配置模型参数'));
|
|
404
|
+
console.log(UIHelper.createHintLine([
|
|
405
|
+
['Enter', '确认输入'],
|
|
406
|
+
['ESC', '跳过配置']
|
|
407
|
+
]));
|
|
408
|
+
console.log();
|
|
409
|
+
|
|
410
|
+
const escListener = this.createESCListener(() => {
|
|
411
|
+
Logger.info('跳过模型参数配置');
|
|
412
|
+
}, '跳过配置');
|
|
413
|
+
|
|
414
|
+
try {
|
|
415
|
+
const responses = await this.prompt([
|
|
416
|
+
{
|
|
417
|
+
type: 'input',
|
|
418
|
+
name: 'primaryModel',
|
|
419
|
+
message: '主模型 (ANTHROPIC_MODEL):',
|
|
420
|
+
default: '',
|
|
421
|
+
validate: (input) => {
|
|
422
|
+
const error = validator.validateModel(input);
|
|
423
|
+
if (error) return error;
|
|
424
|
+
return true;
|
|
425
|
+
}
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
type: 'input',
|
|
429
|
+
name: 'smallFastModel',
|
|
430
|
+
message: '快速模型 (ANTHROPIC_SMALL_FAST_MODEL):',
|
|
431
|
+
default: '',
|
|
432
|
+
validate: (input) => {
|
|
433
|
+
const error = validator.validateModel(input);
|
|
434
|
+
if (error) return error;
|
|
435
|
+
return true;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
]);
|
|
439
|
+
|
|
440
|
+
this.removeESCListener(escListener);
|
|
441
|
+
return {
|
|
442
|
+
primaryModel: responses.primaryModel,
|
|
443
|
+
smallFastModel: responses.smallFastModel
|
|
444
|
+
};
|
|
445
|
+
} catch (error) {
|
|
446
|
+
this.removeESCListener(escListener);
|
|
447
|
+
if (this.isEscCancelled(error)) {
|
|
448
|
+
return { primaryModel: null, smallFastModel: null };
|
|
449
|
+
}
|
|
450
|
+
throw error;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
printProviderSummary(answers, launchArgs, modelConfig) {
|
|
455
|
+
const finalDisplayName = answers.displayName || answers.name;
|
|
456
|
+
Logger.success(`供应商 '${finalDisplayName}' 添加成功!`);
|
|
457
|
+
|
|
458
|
+
console.log(chalk.blue('\n配置详情:'));
|
|
459
|
+
console.log(chalk.gray(` 名称: ${answers.name}`));
|
|
460
|
+
console.log(chalk.gray(` 显示名称: ${finalDisplayName}`));
|
|
461
|
+
|
|
462
|
+
const authModeDisplay = {
|
|
463
|
+
api_key: '通用API密钥模式',
|
|
464
|
+
auth_token: '认证令牌模式 (仅 ANTHROPIC_AUTH_TOKEN)',
|
|
465
|
+
oauth_token: 'OAuth令牌模式 (CLAUDE_CODE_OAUTH_TOKEN)'
|
|
466
|
+
};
|
|
467
|
+
|
|
468
|
+
console.log(chalk.gray(` 认证模式: ${authModeDisplay[answers.authMode] || answers.authMode}`));
|
|
469
|
+
|
|
470
|
+
// 如果是 api_key 模式,显示 tokenType
|
|
471
|
+
if (answers.authMode === 'api_key' && answers.tokenType) {
|
|
472
|
+
const tokenTypeDisplay = answers.tokenType === 'auth_token' ? 'ANTHROPIC_AUTH_TOKEN' : 'ANTHROPIC_API_KEY';
|
|
473
|
+
console.log(chalk.gray(` Token类型: ${tokenTypeDisplay}`));
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
if (answers.baseUrl) {
|
|
477
|
+
console.log(chalk.gray(` 基础URL: ${answers.baseUrl}`));
|
|
478
|
+
}
|
|
479
|
+
console.log(chalk.gray(` Token: ${answers.authToken}`));
|
|
480
|
+
|
|
481
|
+
if (launchArgs.length > 0) {
|
|
482
|
+
console.log(chalk.gray(` 启动参数: ${launchArgs.join(' ')}`));
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
if (modelConfig.primaryModel) {
|
|
486
|
+
console.log(chalk.gray(` 主模型: ${modelConfig.primaryModel}`));
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
if (modelConfig.smallFastModel) {
|
|
490
|
+
console.log(chalk.gray(` 快速模型: ${modelConfig.smallFastModel}`));
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
console.log(chalk.green('\n🎉 供应商添加完成!正在返回主界面...'));
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
async pauseBeforeReturn(delay = 1500) {
|
|
497
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
async function addCommand() {
|
|
502
|
+
const adder = new ProviderAdder();
|
|
503
|
+
try {
|
|
504
|
+
await adder.interactive();
|
|
505
|
+
} catch (error) {
|
|
506
|
+
if (!adder.isEscCancelled(error)) {
|
|
507
|
+
Logger.error(`添加供应商失败: ${error.message}`);
|
|
508
|
+
}
|
|
509
|
+
} finally {
|
|
510
|
+
adder.destroy();
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
module.exports = { addCommand, ProviderAdder };
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const { ConfigManager } = require('../config');
|
|
3
|
+
const { Logger } = require('../utils/logger');
|
|
4
|
+
|
|
5
|
+
class CurrentConfig {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.configManager = new ConfigManager();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async show() {
|
|
11
|
+
try {
|
|
12
|
+
await this.configManager.ensureLoaded();
|
|
13
|
+
const currentProvider = this.configManager.getCurrentProvider();
|
|
14
|
+
|
|
15
|
+
if (!currentProvider) {
|
|
16
|
+
Logger.warning('未设置当前供应商');
|
|
17
|
+
Logger.info('请使用 "cc <供应商名>" 切换供应商');
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
console.log(chalk.blue('\n📍 当前配置:'));
|
|
22
|
+
console.log(chalk.gray('═'.repeat(60)));
|
|
23
|
+
|
|
24
|
+
console.log(chalk.green(`供应商: ${currentProvider.displayName}`));
|
|
25
|
+
console.log(chalk.gray(`内部名称: ${currentProvider.name}`));
|
|
26
|
+
|
|
27
|
+
// 显示认证模式
|
|
28
|
+
const authModeDisplay = {
|
|
29
|
+
api_key: '通用API密钥模式',
|
|
30
|
+
auth_token: '认证令牌模式',
|
|
31
|
+
oauth_token: 'OAuth令牌模式'
|
|
32
|
+
};
|
|
33
|
+
console.log(chalk.gray(`认证模式: ${authModeDisplay[currentProvider.authMode] || currentProvider.authMode}`));
|
|
34
|
+
|
|
35
|
+
// 如果是 api_key 模式,显示 tokenType
|
|
36
|
+
if (currentProvider.authMode === 'api_key' && currentProvider.tokenType) {
|
|
37
|
+
const tokenTypeDisplay = currentProvider.tokenType === 'auth_token' ? 'ANTHROPIC_AUTH_TOKEN' : 'ANTHROPIC_API_KEY';
|
|
38
|
+
console.log(chalk.gray(`Token类型: ${tokenTypeDisplay}`));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (currentProvider.baseUrl) {
|
|
42
|
+
console.log(chalk.gray(`基础URL: ${currentProvider.baseUrl}`));
|
|
43
|
+
}
|
|
44
|
+
console.log(chalk.gray(`认证Token: ${currentProvider.authToken}`));
|
|
45
|
+
console.log(chalk.gray(`创建时间: ${new Date(currentProvider.createdAt).toLocaleString()}`));
|
|
46
|
+
console.log(chalk.gray(`最后使用: ${new Date(currentProvider.lastUsed).toLocaleString()}`));
|
|
47
|
+
|
|
48
|
+
// 显示模型配置
|
|
49
|
+
if (currentProvider.models && (currentProvider.models.primary || currentProvider.models.smallFast)) {
|
|
50
|
+
console.log(chalk.gray(`主模型: ${currentProvider.models.primary || '未设置'}`));
|
|
51
|
+
console.log(chalk.gray(`快速模型: ${currentProvider.models.smallFast || '未设置'}`));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
console.log(chalk.gray('═'.repeat(60)));
|
|
55
|
+
|
|
56
|
+
// 显示环境变量设置方式
|
|
57
|
+
console.log(chalk.blue('\n🔧 环境变量设置:'));
|
|
58
|
+
if (currentProvider.baseUrl) {
|
|
59
|
+
console.log(chalk.gray(`set ANTHROPIC_BASE_URL=${currentProvider.baseUrl}`));
|
|
60
|
+
}
|
|
61
|
+
if (currentProvider.authMode === 'oauth_token') {
|
|
62
|
+
console.log(chalk.gray(`set CLAUDE_CODE_OAUTH_TOKEN=${currentProvider.authToken}`));
|
|
63
|
+
} else if (currentProvider.authMode === 'api_key') {
|
|
64
|
+
// 根据 tokenType 显示对应的环境变量
|
|
65
|
+
if (currentProvider.tokenType === 'auth_token') {
|
|
66
|
+
console.log(chalk.gray(`set ANTHROPIC_AUTH_TOKEN=${currentProvider.authToken}`));
|
|
67
|
+
} else {
|
|
68
|
+
console.log(chalk.gray(`set ANTHROPIC_API_KEY=${currentProvider.authToken}`));
|
|
69
|
+
}
|
|
70
|
+
} else {
|
|
71
|
+
// auth_token 模式
|
|
72
|
+
console.log(chalk.gray(`set ANTHROPIC_AUTH_TOKEN=${currentProvider.authToken}`));
|
|
73
|
+
}
|
|
74
|
+
if (currentProvider.models?.primary) {
|
|
75
|
+
console.log(chalk.gray(`set ANTHROPIC_MODEL=${currentProvider.models.primary}`));
|
|
76
|
+
}
|
|
77
|
+
if (currentProvider.models?.smallFast) {
|
|
78
|
+
console.log(chalk.gray(`set ANTHROPIC_SMALL_FAST_MODEL=${currentProvider.models.smallFast}`));
|
|
79
|
+
}
|
|
80
|
+
console.log(chalk.gray('claude'));
|
|
81
|
+
|
|
82
|
+
} catch (error) {
|
|
83
|
+
Logger.error(`获取当前配置失败: ${error.message}`);
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function currentCommand() {
|
|
90
|
+
const current = new CurrentConfig();
|
|
91
|
+
await current.show();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports = { currentCommand, CurrentConfig };
|