@pikecode/api-key-manager 1.0.45 → 1.1.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.
@@ -9,7 +9,7 @@ const { configManager } = require('../config');
9
9
  const { Logger } = require('../utils/logger');
10
10
  const { ProviderStatusChecker } = require('../utils/provider-status-checker');
11
11
  const { maybeMaskToken } = require('../utils/secrets');
12
- const { AUTH_MODE_DISPLAY, TOKEN_TYPE_DISPLAY, BASE_URL } = require('../constants');
12
+ const { AUTH_MODE_DISPLAY, BASE_URL } = require('../constants');
13
13
 
14
14
  /**
15
15
  * 供应商列表显示类
@@ -29,12 +29,14 @@ class ProviderLister {
29
29
  * @param {string|null} filter - 过滤器 ('codex', 'claude', 或 null 表示全部)
30
30
  * @param {Object} options - 显示选项
31
31
  * @param {boolean} [options.showToken=true] - 是否显示完整 token
32
+ * @param {boolean} [options.checkStatus=false] - 是否检测在线状态
32
33
  * @returns {Promise<void>}
33
34
  */
34
35
  async list(filter = null, options = {}) {
35
36
  try {
36
37
  // 默认显示完整 token,不再加密
37
38
  const showToken = options.showToken !== false;
39
+ const checkStatus = options.checkStatus === true;
38
40
  await this.configManager.ensureLoaded();
39
41
  let providers = this.configManager.listProviders();
40
42
  const currentProvider = this.configManager.getCurrentProvider();
@@ -46,7 +48,7 @@ class ProviderLister {
46
48
  providers = providers.filter(p => p.ideName !== 'codex');
47
49
  }
48
50
 
49
- const statusMap = await this.statusChecker.checkAll(providers);
51
+ const statusMap = checkStatus ? await this.statusChecker.checkAll(providers) : {};
50
52
 
51
53
  if (providers.length === 0) {
52
54
  if (filter) {
@@ -66,9 +68,6 @@ class ProviderLister {
66
68
  providers.forEach((provider, index) => {
67
69
  const isCurrent = provider.name === currentProvider?.name;
68
70
  const status = isCurrent ? '✅' : '🔹';
69
- const availability = statusMap[provider.name] || { state: 'unknown', label: '未知', latency: null };
70
- const availabilityIcon = this._iconForState(availability.state);
71
- const availabilityText = this._formatAvailability(availability);
72
71
  const nameColor = isCurrent ? chalk.green : chalk.white;
73
72
 
74
73
  // IDE 类型标签
@@ -78,7 +77,15 @@ class ProviderLister {
78
77
 
79
78
  // 如果有别名,显示别名
80
79
  const aliasText = provider.alias ? chalk.yellow(` [别名: ${provider.alias}]`) : '';
81
- console.log(`${status} ${availabilityIcon} ${ideTag} ${nameColor(provider.name)} (${provider.displayName})${aliasText} - ${availabilityText}`);
80
+
81
+ if (checkStatus) {
82
+ const availability = statusMap[provider.name] || { state: 'unknown', label: '未知', latency: null };
83
+ const availabilityIcon = this._iconForState(availability.state);
84
+ const availabilityText = this._formatAvailability(availability);
85
+ console.log(`${status} ${availabilityIcon} ${ideTag} ${nameColor(provider.name)} (${provider.displayName})${aliasText} - ${availabilityText}`);
86
+ } else {
87
+ console.log(`${status} ${ideTag} ${nameColor(provider.name)} (${provider.displayName})${aliasText}`);
88
+ }
82
89
 
83
90
  if (provider.ideName === 'codex') {
84
91
  console.log(chalk.gray(' IDE: Codex CLI'));
@@ -93,30 +100,20 @@ class ProviderLister {
93
100
  console.log(chalk.gray(` 认证模式: ${AUTH_MODE_DISPLAY[provider.authMode] || provider.authMode}`));
94
101
 
95
102
  // 根据不同模式显示对应的环境变量名称
96
- if (provider.authMode === 'oauth_token') {
97
- // OAuth 模式
98
- if (provider.authToken) {
99
- console.log(chalk.gray(` CLAUDE_CODE_OAUTH_TOKEN: ${maybeMaskToken(provider.authToken, showToken)}`));
100
- }
101
- if (provider.baseUrl) {
102
- console.log(chalk.gray(` ANTHROPIC_BASE_URL: ${provider.baseUrl}`));
103
- }
104
- } else if (provider.authMode === 'api_key') {
105
- // API Key 模式
103
+ if (provider.authMode === 'auth_token') {
106
104
  if (provider.baseUrl) {
107
105
  console.log(chalk.gray(` ANTHROPIC_BASE_URL: ${provider.baseUrl}`));
108
106
  }
109
107
  if (provider.authToken) {
110
- const tokenEnvName = TOKEN_TYPE_DISPLAY[provider.tokenType] || 'ANTHROPIC_API_KEY';
111
- console.log(chalk.gray(` ${tokenEnvName}: ${maybeMaskToken(provider.authToken, showToken)}`));
108
+ console.log(chalk.gray(` ANTHROPIC_AUTH_TOKEN: ${maybeMaskToken(provider.authToken, showToken)}`));
112
109
  }
113
110
  } else {
114
- // auth_token 模式
111
+ // API Key 模式(默认)
115
112
  if (provider.baseUrl) {
116
113
  console.log(chalk.gray(` ANTHROPIC_BASE_URL: ${provider.baseUrl}`));
117
114
  }
118
115
  if (provider.authToken) {
119
- console.log(chalk.gray(` ANTHROPIC_AUTH_TOKEN: ${maybeMaskToken(provider.authToken, showToken)}`));
116
+ console.log(chalk.gray(` ANTHROPIC_API_KEY: ${maybeMaskToken(provider.authToken, showToken)}`));
120
117
  }
121
118
  }
122
119
  }
@@ -0,0 +1,467 @@
1
+ /**
2
+ * MCP Server Management Command
3
+ * 管理 ~/.claude.json 中的 MCP 服务器配置
4
+ * @module commands/mcp
5
+ */
6
+
7
+ const fs = require('fs-extra');
8
+ const path = require('path');
9
+ const os = require('os');
10
+ const chalk = require('chalk');
11
+ const inquirer = require('inquirer');
12
+ const { Logger } = require('../utils/logger');
13
+ const { UIHelper } = require('../utils/ui-helper');
14
+ const { BaseCommand } = require('./BaseCommand');
15
+
16
+ const CLAUDE_JSON_PATH = path.join(os.homedir(), '.claude.json');
17
+
18
+ // 预设 MCP 服务器模板
19
+ const MCP_PRESETS = [
20
+ {
21
+ name: 'Playwright',
22
+ description: '浏览器自动化测试',
23
+ config: {
24
+ command: 'npx',
25
+ args: ['-y', '@playwright/mcp@latest'],
26
+ type: 'stdio'
27
+ }
28
+ },
29
+ {
30
+ name: 'filesystem',
31
+ description: '文件系统访问',
32
+ config: {
33
+ command: 'npx',
34
+ args: ['-y', '@modelcontextprotocol/server-filesystem', os.homedir()],
35
+ type: 'stdio'
36
+ }
37
+ },
38
+ {
39
+ name: 'memory',
40
+ description: '知识图谱记忆',
41
+ config: {
42
+ command: 'npx',
43
+ args: ['-y', '@modelcontextprotocol/server-memory'],
44
+ type: 'stdio'
45
+ }
46
+ },
47
+ {
48
+ name: 'fetch',
49
+ description: '网页内容获取',
50
+ config: {
51
+ command: 'npx',
52
+ args: ['-y', '@modelcontextprotocol/server-fetch'],
53
+ type: 'stdio'
54
+ }
55
+ }
56
+ ];
57
+
58
+ class McpManager extends BaseCommand {
59
+ constructor() {
60
+ super();
61
+ }
62
+
63
+ /**
64
+ * 读取 ~/.claude.json
65
+ */
66
+ async _readClaudeJson() {
67
+ if (!await fs.pathExists(CLAUDE_JSON_PATH)) {
68
+ return {};
69
+ }
70
+ return await fs.readJson(CLAUDE_JSON_PATH);
71
+ }
72
+
73
+ /**
74
+ * 写入 ~/.claude.json
75
+ */
76
+ async _writeClaudeJson(data) {
77
+ await fs.writeJson(CLAUDE_JSON_PATH, data, { spaces: 2 });
78
+ }
79
+
80
+ /**
81
+ * 获取 mcpServers 对象
82
+ */
83
+ _getMcpServers(data) {
84
+ return data.mcpServers || {};
85
+ }
86
+
87
+ /**
88
+ * 列出所有 MCP 服务器
89
+ */
90
+ async list() {
91
+ const data = await this._readClaudeJson();
92
+ const servers = this._getMcpServers(data);
93
+ const names = Object.keys(servers);
94
+
95
+ console.log(UIHelper.createTitle('MCP 服务器列表', '🔌'));
96
+ console.log();
97
+
98
+ if (names.length === 0) {
99
+ Logger.info('暂无 MCP 服务器配置。使用 akm mcp add 添加。');
100
+ return;
101
+ }
102
+
103
+ names.forEach(name => {
104
+ const server = servers[name];
105
+ const cmd = server.command || '(unknown)';
106
+ const args = (server.args || []).join(' ');
107
+ const envKeys = Object.keys(server.env || {});
108
+ const envInfo = envKeys.length > 0 ? chalk.gray(` env: ${envKeys.join(', ')}`) : '';
109
+
110
+ console.log(` ${chalk.cyan('●')} ${chalk.bold(name)}`);
111
+ console.log(` ${chalk.gray('命令:')} ${cmd} ${args}`);
112
+ if (server.type) {
113
+ console.log(` ${chalk.gray('类型:')} ${server.type}`);
114
+ }
115
+ if (envInfo) {
116
+ console.log(` ${envInfo}`);
117
+ }
118
+ console.log();
119
+ });
120
+
121
+ console.log(chalk.gray(` 共 ${names.length} 个 MCP 服务器`));
122
+ }
123
+
124
+ /**
125
+ * 添加 MCP 服务器
126
+ */
127
+ async add() {
128
+ console.log(UIHelper.createTitle('添加 MCP 服务器', '➕'));
129
+ console.log();
130
+
131
+ let sourceChoice;
132
+ try {
133
+ sourceChoice = await this.prompt([
134
+ {
135
+ type: 'list',
136
+ name: 'source',
137
+ message: '选择添加方式:',
138
+ choices: [
139
+ { name: '📦 从预设模板选择', value: 'preset' },
140
+ { name: '✏️ 手动配置', value: 'manual' },
141
+ new inquirer.Separator(),
142
+ { name: '取消', value: null }
143
+ ]
144
+ }
145
+ ]);
146
+ } catch (error) {
147
+ if (this.isEscCancelled(error)) return;
148
+ throw error;
149
+ }
150
+
151
+ if (!sourceChoice.source) {
152
+ Logger.info('操作已取消。');
153
+ return;
154
+ }
155
+
156
+ const data = await this._readClaudeJson();
157
+ const servers = this._getMcpServers(data);
158
+
159
+ if (sourceChoice.source === 'preset') {
160
+ await this._addFromPreset(data, servers);
161
+ } else {
162
+ await this._addManual(data, servers);
163
+ }
164
+ }
165
+
166
+ async _addFromPreset(data, servers) {
167
+ // 过滤掉已存在的预设
168
+ const available = MCP_PRESETS.filter(p => !servers[p.name]);
169
+
170
+ if (available.length === 0) {
171
+ Logger.info('所有预设模板已添加。可使用手动配置添加自定义服务器。');
172
+ return;
173
+ }
174
+
175
+ let selection;
176
+ try {
177
+ selection = await this.prompt([
178
+ {
179
+ type: 'checkbox',
180
+ name: 'presets',
181
+ message: '选择要添加的 MCP 服务器:',
182
+ choices: available.map(p => ({
183
+ name: `${p.name} - ${p.description}`,
184
+ value: p.name
185
+ })),
186
+ validate: input => input.length > 0 ? true : '请至少选择一个'
187
+ }
188
+ ]);
189
+ } catch (error) {
190
+ if (this.isEscCancelled(error)) return;
191
+ throw error;
192
+ }
193
+
194
+ if (!data.mcpServers) {
195
+ data.mcpServers = {};
196
+ }
197
+
198
+ selection.presets.forEach(name => {
199
+ const preset = MCP_PRESETS.find(p => p.name === name);
200
+ data.mcpServers[name] = { ...preset.config, env: {} };
201
+ });
202
+
203
+ await this._writeClaudeJson(data);
204
+ Logger.success(`已添加 ${selection.presets.length} 个 MCP 服务器: ${selection.presets.join(', ')}`);
205
+ }
206
+
207
+ async _addManual(data, servers) {
208
+ let config;
209
+ try {
210
+ config = await this.prompt([
211
+ {
212
+ type: 'input',
213
+ name: 'name',
214
+ message: '服务器名称:',
215
+ validate: input => {
216
+ if (!input || !input.trim()) return '名称不能为空';
217
+ if (servers[input.trim()]) return `'${input.trim()}' 已存在`;
218
+ return true;
219
+ }
220
+ },
221
+ {
222
+ type: 'input',
223
+ name: 'command',
224
+ message: '启动命令 (如 npx, node, python):',
225
+ validate: input => input && input.trim() ? true : '命令不能为空'
226
+ },
227
+ {
228
+ type: 'input',
229
+ name: 'args',
230
+ message: '命令参数 (空格分隔):',
231
+ default: ''
232
+ },
233
+ {
234
+ type: 'list',
235
+ name: 'type',
236
+ message: '通信类型:',
237
+ choices: [
238
+ { name: 'stdio (标准输入输出)', value: 'stdio' },
239
+ { name: 'sse (Server-Sent Events)', value: 'sse' }
240
+ ],
241
+ default: 'stdio'
242
+ },
243
+ {
244
+ type: 'input',
245
+ name: 'env',
246
+ message: '环境变量 (格式: KEY=VALUE, 多个用逗号分隔, 留空跳过):',
247
+ default: ''
248
+ }
249
+ ]);
250
+ } catch (error) {
251
+ if (this.isEscCancelled(error)) return;
252
+ throw error;
253
+ }
254
+
255
+ const name = config.name.trim();
256
+ const args = config.args.trim() ? config.args.trim().split(/\s+/) : [];
257
+ const env = {};
258
+ if (config.env.trim()) {
259
+ config.env.split(',').forEach(pair => {
260
+ const [key, ...valueParts] = pair.trim().split('=');
261
+ if (key) {
262
+ env[key.trim()] = valueParts.join('=').trim();
263
+ }
264
+ });
265
+ }
266
+
267
+ if (!data.mcpServers) {
268
+ data.mcpServers = {};
269
+ }
270
+
271
+ data.mcpServers[name] = {
272
+ command: config.command.trim(),
273
+ args,
274
+ env,
275
+ type: config.type
276
+ };
277
+
278
+ await this._writeClaudeJson(data);
279
+ Logger.success(`MCP 服务器 '${name}' 已添加。`);
280
+ }
281
+
282
+ /**
283
+ * 编辑 MCP 服务器
284
+ */
285
+ async edit() {
286
+ const data = await this._readClaudeJson();
287
+ const servers = this._getMcpServers(data);
288
+ const names = Object.keys(servers);
289
+
290
+ if (names.length === 0) {
291
+ Logger.warning('暂无 MCP 服务器配置。');
292
+ return;
293
+ }
294
+
295
+ let selection;
296
+ try {
297
+ selection = await this.prompt([
298
+ {
299
+ type: 'list',
300
+ name: 'name',
301
+ message: '选择要编辑的 MCP 服务器:',
302
+ choices: [
303
+ ...names.map(n => ({
304
+ name: `${n} ${chalk.gray('(' + (servers[n].command || '') + ')')}`,
305
+ value: n
306
+ })),
307
+ new inquirer.Separator(),
308
+ { name: '取消', value: null }
309
+ ]
310
+ }
311
+ ]);
312
+ } catch (error) {
313
+ if (this.isEscCancelled(error)) return;
314
+ throw error;
315
+ }
316
+
317
+ if (!selection.name) {
318
+ Logger.info('操作已取消。');
319
+ return;
320
+ }
321
+
322
+ const name = selection.name;
323
+ const server = servers[name];
324
+
325
+ let updates;
326
+ try {
327
+ updates = await this.prompt([
328
+ {
329
+ type: 'input',
330
+ name: 'command',
331
+ message: '启动命令:',
332
+ default: server.command || '',
333
+ validate: input => input && input.trim() ? true : '命令不能为空'
334
+ },
335
+ {
336
+ type: 'input',
337
+ name: 'args',
338
+ message: '命令参数 (空格分隔):',
339
+ default: (server.args || []).join(' ')
340
+ },
341
+ {
342
+ type: 'list',
343
+ name: 'type',
344
+ message: '通信类型:',
345
+ choices: [
346
+ { name: 'stdio (标准输入输出)', value: 'stdio' },
347
+ { name: 'sse (Server-Sent Events)', value: 'sse' }
348
+ ],
349
+ default: server.type || 'stdio'
350
+ },
351
+ {
352
+ type: 'input',
353
+ name: 'env',
354
+ message: '环境变量 (KEY=VALUE, 逗号分隔):',
355
+ default: Object.entries(server.env || {}).map(([k, v]) => `${k}=${v}`).join(', ')
356
+ }
357
+ ]);
358
+ } catch (error) {
359
+ if (this.isEscCancelled(error)) return;
360
+ throw error;
361
+ }
362
+
363
+ const args = updates.args.trim() ? updates.args.trim().split(/\s+/) : [];
364
+ const env = {};
365
+ if (updates.env.trim()) {
366
+ updates.env.split(',').forEach(pair => {
367
+ const [key, ...valueParts] = pair.trim().split('=');
368
+ if (key) {
369
+ env[key.trim()] = valueParts.join('=').trim();
370
+ }
371
+ });
372
+ }
373
+
374
+ data.mcpServers[name] = {
375
+ command: updates.command.trim(),
376
+ args,
377
+ env,
378
+ type: updates.type
379
+ };
380
+
381
+ await this._writeClaudeJson(data);
382
+ Logger.success(`MCP 服务器 '${name}' 已更新。`);
383
+ }
384
+
385
+ /**
386
+ * 删除 MCP 服务器
387
+ */
388
+ async remove() {
389
+ const data = await this._readClaudeJson();
390
+ const servers = this._getMcpServers(data);
391
+ const names = Object.keys(servers);
392
+
393
+ if (names.length === 0) {
394
+ Logger.warning('暂无 MCP 服务器配置。');
395
+ return;
396
+ }
397
+
398
+ let selection;
399
+ try {
400
+ selection = await this.prompt([
401
+ {
402
+ type: 'checkbox',
403
+ name: 'names',
404
+ message: '选择要删除的 MCP 服务器:',
405
+ choices: names.map(n => ({
406
+ name: `${n} ${chalk.gray('(' + (servers[n].command || '') + ' ' + (servers[n].args || []).join(' ') + ')')}`,
407
+ value: n
408
+ })),
409
+ validate: input => input.length > 0 ? true : '请至少选择一个'
410
+ }
411
+ ]);
412
+ } catch (error) {
413
+ if (this.isEscCancelled(error)) return;
414
+ throw error;
415
+ }
416
+
417
+ // 二次确认
418
+ let confirm;
419
+ try {
420
+ confirm = await this.prompt([
421
+ {
422
+ type: 'confirm',
423
+ name: 'ok',
424
+ message: `确认删除 ${selection.names.length} 个 MCP 服务器: ${selection.names.join(', ')}?`,
425
+ default: false
426
+ }
427
+ ]);
428
+ } catch (error) {
429
+ if (this.isEscCancelled(error)) return;
430
+ throw error;
431
+ }
432
+
433
+ if (!confirm.ok) {
434
+ Logger.info('操作已取消。');
435
+ return;
436
+ }
437
+
438
+ selection.names.forEach(name => {
439
+ delete data.mcpServers[name];
440
+ });
441
+
442
+ await this._writeClaudeJson(data);
443
+ Logger.success(`已删除 ${selection.names.length} 个 MCP 服务器: ${selection.names.join(', ')}`);
444
+ }
445
+ }
446
+
447
+ const VALID_SUBCOMMANDS = ['list', 'add', 'edit', 'remove'];
448
+
449
+ async function mcpCommand(subcommand) {
450
+ const manager = new McpManager();
451
+ try {
452
+ if (!VALID_SUBCOMMANDS.includes(subcommand)) {
453
+ Logger.error(`未知子命令: ${subcommand}`);
454
+ console.log(chalk.gray(` 可用子命令: ${VALID_SUBCOMMANDS.join(', ')}`));
455
+ return;
456
+ }
457
+ await manager[subcommand]();
458
+ } catch (error) {
459
+ if (!manager.isEscCancelled(error)) {
460
+ Logger.error(`MCP 操作失败: ${error.message}`);
461
+ }
462
+ } finally {
463
+ manager.destroy();
464
+ }
465
+ }
466
+
467
+ module.exports = { mcpCommand, McpManager, MCP_PRESETS };
@@ -17,7 +17,7 @@ const { findSettingsConflict, backupSettingsFile, clearConflictKeys, saveSetting
17
17
  const { BaseCommand } = require('./BaseCommand');
18
18
  const { validator } = require('../utils/validator');
19
19
  const { ProviderStatusChecker } = require('../utils/provider-status-checker');
20
- const { AUTH_MODE_DISPLAY, TOKEN_TYPE_DISPLAY, BASE_URL } = require('../constants');
20
+ const { AUTH_MODE_DISPLAY, BASE_URL } = require('../constants');
21
21
  const { LaunchArgsHelper } = require('./switch/launch-args-helper');
22
22
  const { StatusHelper } = require('./switch/status-helper');
23
23
 
@@ -1238,15 +1238,9 @@ class EnvSwitcher extends BaseCommand {
1238
1238
  ['认证模式', AUTH_MODE_DISPLAY[provider.authMode] || provider.authMode]
1239
1239
  ];
1240
1240
 
1241
- // 如果是 api_key 模式,添加 tokenType 信息
1242
- if (provider.authMode === 'api_key' && provider.tokenType) {
1243
- const tokenTypeDisplay = TOKEN_TYPE_DISPLAY[provider.tokenType];
1244
- details.push(['Token类型', tokenTypeDisplay]);
1245
- }
1246
-
1247
1241
  // 继续添加其他信息
1248
1242
  const baseUrlDisplay = provider.baseUrl
1249
- || ((provider.authMode === 'oauth_token' || provider.authMode === 'auth_token')
1243
+ || (provider.authMode === 'auth_token'
1250
1244
  ? BASE_URL.OFFICIAL_DEFAULT
1251
1245
  : '⚠️ 未设置');
1252
1246
  details.push(
@@ -1385,23 +1379,11 @@ class EnvSwitcher extends BaseCommand {
1385
1379
  name: 'authMode',
1386
1380
  message: '认证模式:',
1387
1381
  choices: [
1388
- { name: '🔑 通用API密钥模式 - 支持 ANTHROPIC_API_KEY 和 ANTHROPIC_AUTH_TOKEN', value: 'api_key' },
1389
- { name: '🔐 认证令牌模式 (仅 ANTHROPIC_AUTH_TOKEN) - 适用于某些服务商', value: 'auth_token' },
1390
- { name: '🌐 OAuth令牌模式 (CLAUDE_CODE_OAUTH_TOKEN) - 适用于官方Claude Code', value: 'oauth_token' }
1382
+ { name: '🔑 ANTHROPIC_API_KEY - 大多数第三方代理使用', value: 'api_key' },
1383
+ { name: '🔐 ANTHROPIC_AUTH_TOKEN - 部分服务商使用', value: 'auth_token' }
1391
1384
  ],
1392
1385
  default: provider.authMode || 'api_key'
1393
1386
  },
1394
- {
1395
- type: 'list',
1396
- name: 'tokenType',
1397
- message: 'Token类型:',
1398
- choices: [
1399
- { name: '🔑 ANTHROPIC_API_KEY - 通用API密钥', value: 'api_key' },
1400
- { name: '🔐 ANTHROPIC_AUTH_TOKEN - 认证令牌', value: 'auth_token' }
1401
- ],
1402
- default: provider.tokenType || 'api_key',
1403
- when: (answers) => answers.authMode === 'api_key'
1404
- },
1405
1387
  {
1406
1388
  type: 'input',
1407
1389
  name: 'primaryModel',
@@ -1447,17 +1429,8 @@ class EnvSwitcher extends BaseCommand {
1447
1429
  if (isCodex) {
1448
1430
  return 'API Key (OPENAI_API_KEY):';
1449
1431
  }
1450
- switch (answers.authMode) {
1451
- case 'api_key':
1452
- const tokenTypeLabel = answers.tokenType === 'auth_token' ? 'ANTHROPIC_AUTH_TOKEN' : 'ANTHROPIC_API_KEY';
1453
- return `Token (${tokenTypeLabel}):`;
1454
- case 'auth_token':
1455
- return '认证令牌 (ANTHROPIC_AUTH_TOKEN):';
1456
- case 'oauth_token':
1457
- return 'OAuth令牌 (CLAUDE_CODE_OAUTH_TOKEN):';
1458
- default:
1459
- return '认证令牌:';
1460
- }
1432
+ const envVar = answers.authMode === 'auth_token' ? 'ANTHROPIC_AUTH_TOKEN' : 'ANTHROPIC_API_KEY';
1433
+ return `Token (${envVar}):`;
1461
1434
  },
1462
1435
  default: provider.authToken,
1463
1436
  prefillDefault: true
@@ -1506,16 +1479,12 @@ class EnvSwitcher extends BaseCommand {
1506
1479
  // 更新供应商配置
1507
1480
  provider.displayName = answers.displayName || newName;
1508
1481
  provider.alias = answers.alias || null;
1509
- // oauth_token 模式不需要 baseUrl,显式设为 null
1510
- provider.baseUrl = answers.authMode === 'oauth_token' ? null : answers.baseUrl;
1482
+ provider.baseUrl = answers.baseUrl;
1511
1483
  provider.authToken = answers.authToken;
1512
1484
 
1513
1485
  // Claude Code 特定的更新
1514
1486
  if (!isCodex) {
1515
1487
  provider.authMode = answers.authMode;
1516
- if (answers.tokenType) {
1517
- provider.tokenType = answers.tokenType; // 仅在 authMode 为 'api_key' 时使用
1518
- }
1519
1488
 
1520
1489
  // 更新模型配置
1521
1490
  if (!provider.models) {
@@ -1526,7 +1495,6 @@ class EnvSwitcher extends BaseCommand {
1526
1495
  } else {
1527
1496
  // 确保 Codex 配置不包含 Claude 特定字段
1528
1497
  provider.authMode = null;
1529
- provider.tokenType = null;
1530
1498
  provider.models = null;
1531
1499
  }
1532
1500
 
package/src/config.js CHANGED
@@ -11,7 +11,6 @@ const chalk = require('chalk');
11
11
  * @property {string} authMode - 认证模式
12
12
  * @property {string} authToken - 认证令牌
13
13
  * @property {string|null} baseUrl - API 基础 URL
14
- * @property {string|null} tokenType - Token 类型
15
14
  * @property {Object|null} models - 模型配置
16
15
  * @property {string[]} launchArgs - 启动参数
17
16
  * @property {boolean} current - 是否为当前供应商
@@ -320,9 +319,6 @@ class ConfigManager {
320
319
  // Claude Code 特定字段
321
320
  if (!isCodex) {
322
321
  const authMode = providerConfig.authMode || existing?.authMode || 'api_key';
323
- const tokenType = authMode === 'api_key'
324
- ? (providerConfig.tokenType ?? existing?.tokenType ?? 'api_key')
325
- : null;
326
322
  const primaryModel = providerConfig.primaryModel !== undefined
327
323
  ? providerConfig.primaryModel
328
324
  : (existing?.models?.primary ?? null);
@@ -331,7 +327,6 @@ class ConfigManager {
331
327
  : (existing?.models?.smallFast ?? null);
332
328
 
333
329
  this.config.providers[name].authMode = authMode;
334
- this.config.providers[name].tokenType = tokenType;
335
330
  this.config.providers[name].models = {
336
331
  primary: primaryModel,
337
332
  smallFast: smallFastModel
@@ -339,7 +334,6 @@ class ConfigManager {
339
334
  } else {
340
335
  // Codex 不需要这些字段,设置为 null 以保持向后兼容
341
336
  this.config.providers[name].authMode = null;
342
- this.config.providers[name].tokenType = null;
343
337
  this.config.providers[name].models = null;
344
338
  }
345
339