@pikecode/api-key-manager 1.0.14 → 1.0.15
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 +11 -40
- package/package.json +1 -1
- package/src/commands/add.js +20 -85
- package/src/commands/list.js +8 -25
- package/src/commands/switch.js +9 -16
- package/src/utils/env-launcher.js +22 -56
- package/src/utils/provider-status-checker.js +0 -15
- package/src/utils/ui-helper.js +1 -6
package/README.md
CHANGED
|
@@ -6,11 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
- ✨ **快速切换** - 一键切换不同的 API 提供商配置
|
|
8
8
|
- 🔐 **安全存储** - 本地安全存储 API 密钥
|
|
9
|
-
- 🌍 **多提供商支持** - 支持多个 API 提供商(Anthropic
|
|
9
|
+
- 🌍 **多提供商支持** - 支持多个 API 提供商(Anthropic)
|
|
10
10
|
- 🎯 **灵活配置** - 支持多种认证模式(API Key、Auth Token、OAuth)
|
|
11
11
|
- 🚀 **开箱即用** - 无需复杂配置
|
|
12
12
|
- 💾 **环境变量管理** - 自动设置和管理环境变量
|
|
13
|
-
- 🛠️ **多 IDE 支持** - 支持 Claude Code 和 Codex
|
|
14
13
|
|
|
15
14
|
## 安装
|
|
16
15
|
|
|
@@ -37,11 +36,6 @@ akm current
|
|
|
37
36
|
akm list
|
|
38
37
|
```
|
|
39
38
|
|
|
40
|
-
## IDE 特定指南
|
|
41
|
-
|
|
42
|
-
- **[Codex 配置指南](./CODEX_SETUP_GUIDE.md)** - 详细的 Codex 安装和使用指南
|
|
43
|
-
- **[IDE 隔离设计](./IDE_ISOLATION_DESIGN.md)** - Codex 和 Claude Code 隔离机制说明
|
|
44
|
-
|
|
45
39
|
## 命令
|
|
46
40
|
|
|
47
41
|
| 命令 | 说明 |
|
|
@@ -60,13 +54,12 @@ akm list
|
|
|
60
54
|
示例配置结构:
|
|
61
55
|
```json
|
|
62
56
|
{
|
|
63
|
-
"version": "
|
|
57
|
+
"version": "2.0.0",
|
|
64
58
|
"currentProvider": "provider-name",
|
|
65
59
|
"providers": {
|
|
66
60
|
"claude-provider": {
|
|
67
61
|
"name": "claude-provider",
|
|
68
62
|
"displayName": "Claude Code Provider",
|
|
69
|
-
"ideName": "claude",
|
|
70
63
|
"authMode": "oauth_token",
|
|
71
64
|
"authToken": "sk-ant-oat01-...",
|
|
72
65
|
"baseUrl": null,
|
|
@@ -76,30 +69,16 @@ akm list
|
|
|
76
69
|
"smallFast": "claude-haiku-4"
|
|
77
70
|
}
|
|
78
71
|
},
|
|
79
|
-
"
|
|
80
|
-
"name": "
|
|
81
|
-
"displayName": "
|
|
82
|
-
"ideName": "codex",
|
|
72
|
+
"claude-api-key": {
|
|
73
|
+
"name": "claude-api-key",
|
|
74
|
+
"displayName": "Claude Code - API Key",
|
|
83
75
|
"authMode": "api_key",
|
|
84
|
-
"authToken": "sk-...",
|
|
85
|
-
"baseUrl":
|
|
86
|
-
"tokenType":
|
|
76
|
+
"authToken": "sk-ant-...",
|
|
77
|
+
"baseUrl": "https://api.anthropic.com",
|
|
78
|
+
"tokenType": "api_key",
|
|
87
79
|
"models": {
|
|
88
|
-
"primary":
|
|
89
|
-
"smallFast":
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
"codex-chatgpt": {
|
|
93
|
-
"name": "codex-chatgpt",
|
|
94
|
-
"displayName": "Codex ChatGPT Login",
|
|
95
|
-
"ideName": "codex",
|
|
96
|
-
"authMode": "chatgpt_login",
|
|
97
|
-
"authToken": null,
|
|
98
|
-
"baseUrl": null,
|
|
99
|
-
"tokenType": null,
|
|
100
|
-
"models": {
|
|
101
|
-
"primary": null,
|
|
102
|
-
"smallFast": null
|
|
80
|
+
"primary": "claude-sonnet-4",
|
|
81
|
+
"smallFast": "claude-haiku-4"
|
|
103
82
|
}
|
|
104
83
|
}
|
|
105
84
|
}
|
|
@@ -115,21 +94,13 @@ akm list
|
|
|
115
94
|
- `auth_token` - 认证令牌模式(仅 ANTHROPIC_AUTH_TOKEN)
|
|
116
95
|
- 环境变量:CLAUDE_CODE_OAUTH_TOKEN、ANTHROPIC_API_KEY、ANTHROPIC_AUTH_TOKEN、ANTHROPIC_BASE_URL
|
|
117
96
|
|
|
118
|
-
### Codex - OpenAI Codex 代码生成工具
|
|
119
|
-
- 认证模式:
|
|
120
|
-
- `chatgpt_login` - ChatGPT 登录模式(推荐,使用 ChatGPT 账户登录)
|
|
121
|
-
- `api_key` - OpenAI API 密钥模式
|
|
122
|
-
- 环境变量:OPENAI_API_KEY、OPENAI_API_BASE(可选)
|
|
123
|
-
- 官方包:`npm install -g @openai/codex`
|
|
124
|
-
|
|
125
97
|
## 支持的认证模式
|
|
126
98
|
|
|
127
99
|
| 模式 | IDE | 说明 |
|
|
128
100
|
|------|-----|------|
|
|
129
101
|
| **oauth_token** | Claude Code | OAuth 令牌模式 |
|
|
130
|
-
| **api_key** | Claude Code
|
|
102
|
+
| **api_key** | Claude Code | 标准 API 密钥模式 |
|
|
131
103
|
| **auth_token** | Claude Code | 认证令牌模式 |
|
|
132
|
-
| **chatgpt_login** | Codex | ChatGPT 登录模式(推荐) |
|
|
133
104
|
|
|
134
105
|
## 快捷键
|
|
135
106
|
|
package/package.json
CHANGED
package/src/commands/add.js
CHANGED
|
@@ -34,18 +34,17 @@ class ProviderAdder extends BaseCommand {
|
|
|
34
34
|
}, '取消添加');
|
|
35
35
|
|
|
36
36
|
try {
|
|
37
|
-
//
|
|
37
|
+
// 首先选择是否使用预设配置
|
|
38
38
|
const typeAnswer = await this.prompt([
|
|
39
39
|
{
|
|
40
40
|
type: 'list',
|
|
41
41
|
name: 'providerType',
|
|
42
|
-
message: '
|
|
42
|
+
message: '选择供应商类型:',
|
|
43
43
|
choices: [
|
|
44
|
-
{ name: '🔒 官方 Claude Code (OAuth)
|
|
45
|
-
{ name: '
|
|
46
|
-
{ name: '⚙️ Codex - OpenAI Codex (ChatGPT 登录或 API Key)', value: 'custom_codex' }
|
|
44
|
+
{ name: '🔒 官方 Claude Code (OAuth)', value: 'official_oauth' },
|
|
45
|
+
{ name: '⚙️ 自定义配置', value: 'custom' }
|
|
47
46
|
],
|
|
48
|
-
default: '
|
|
47
|
+
default: 'custom'
|
|
49
48
|
}
|
|
50
49
|
]);
|
|
51
50
|
|
|
@@ -54,12 +53,8 @@ class ProviderAdder extends BaseCommand {
|
|
|
54
53
|
|
|
55
54
|
if (typeAnswer.providerType === 'official_oauth') {
|
|
56
55
|
return await this.addOfficialOAuthProvider();
|
|
57
|
-
} else if (typeAnswer.providerType === 'custom_codex') {
|
|
58
|
-
// 直接进入 Codex 配置流程,跳过 IDE 选择
|
|
59
|
-
return await this.addCustomProvider(true);
|
|
60
56
|
} else {
|
|
61
|
-
|
|
62
|
-
return await this.addCustomProvider(false);
|
|
57
|
+
return await this.addCustomProvider();
|
|
63
58
|
}
|
|
64
59
|
} catch (error) {
|
|
65
60
|
// 移除 ESC 键监听
|
|
@@ -156,9 +151,8 @@ class ProviderAdder extends BaseCommand {
|
|
|
156
151
|
}
|
|
157
152
|
}
|
|
158
153
|
|
|
159
|
-
async addCustomProvider(
|
|
160
|
-
|
|
161
|
-
console.log(UIHelper.createTitle(`添加${ideLabel}供应商`, UIHelper.icons.add));
|
|
154
|
+
async addCustomProvider() {
|
|
155
|
+
console.log(UIHelper.createTitle('添加自定义供应商', UIHelper.icons.add));
|
|
162
156
|
console.log();
|
|
163
157
|
console.log(UIHelper.createTooltip('请填写供应商配置信息'));
|
|
164
158
|
console.log();
|
|
@@ -202,41 +196,13 @@ class ProviderAdder extends BaseCommand {
|
|
|
202
196
|
},
|
|
203
197
|
{
|
|
204
198
|
type: 'list',
|
|
205
|
-
name: '
|
|
206
|
-
message: '
|
|
199
|
+
name: 'authMode',
|
|
200
|
+
message: '选择认证模式:',
|
|
207
201
|
choices: [
|
|
208
|
-
{ name: '
|
|
209
|
-
{ name: '
|
|
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' }
|
|
210
205
|
],
|
|
211
|
-
default: forceCodex ? 'codex' : 'claude',
|
|
212
|
-
// 如果来自 Codex 快捷方式,跳过此选择(IDE 已确定为 Codex)
|
|
213
|
-
when: () => !forceCodex
|
|
214
|
-
},
|
|
215
|
-
{
|
|
216
|
-
type: 'list',
|
|
217
|
-
name: 'authMode',
|
|
218
|
-
message: (answers) => {
|
|
219
|
-
if (answers.ideName === 'codex') {
|
|
220
|
-
return '选择 Codex 认证模式:';
|
|
221
|
-
}
|
|
222
|
-
return '选择 Claude Code 认证模式:';
|
|
223
|
-
},
|
|
224
|
-
choices: (answers) => {
|
|
225
|
-
if (answers.ideName === 'codex') {
|
|
226
|
-
// Codex 的认证模式选择
|
|
227
|
-
// @openai/codex 支持两种方式:ChatGPT 登录 (推荐) 或 OpenAI API Key
|
|
228
|
-
return [
|
|
229
|
-
{ name: '🔐 ChatGPT 登录 (推荐) - 使用 ChatGPT 账户登录', value: 'chatgpt_login' },
|
|
230
|
-
{ name: '🔑 OpenAI API Key - 使用 OPENAI_API_KEY', value: 'api_key' }
|
|
231
|
-
];
|
|
232
|
-
}
|
|
233
|
-
// Claude Code 的认证模式选择
|
|
234
|
-
return [
|
|
235
|
-
{ name: '🔑 通用API密钥模式 - 支持 ANTHROPIC_API_KEY 和 ANTHROPIC_AUTH_TOKEN', value: 'api_key' },
|
|
236
|
-
{ name: '🔐 认证令牌模式 (仅 ANTHROPIC_AUTH_TOKEN) - 适用于某些服务商', value: 'auth_token' },
|
|
237
|
-
{ name: '🌐 OAuth令牌模式 (CLAUDE_CODE_OAUTH_TOKEN) - 适用于官方Claude Code', value: 'oauth_token' }
|
|
238
|
-
];
|
|
239
|
-
},
|
|
240
206
|
default: 'api_key'
|
|
241
207
|
},
|
|
242
208
|
{
|
|
@@ -248,18 +214,12 @@ class ProviderAdder extends BaseCommand {
|
|
|
248
214
|
{ name: '🔐 ANTHROPIC_AUTH_TOKEN - 认证令牌', value: 'auth_token' }
|
|
249
215
|
],
|
|
250
216
|
default: 'api_key',
|
|
251
|
-
|
|
252
|
-
// Codex 的 api_key 模式固定使用 OPENAI_API_KEY
|
|
253
|
-
when: (answers) => answers.ideName === 'claude' && answers.authMode === 'api_key'
|
|
217
|
+
when: (answers) => answers.authMode === 'api_key'
|
|
254
218
|
},
|
|
255
219
|
{
|
|
256
220
|
type: 'input',
|
|
257
221
|
name: 'baseUrl',
|
|
258
222
|
message: (answers) => {
|
|
259
|
-
// 根据认证模式显示不同的提示
|
|
260
|
-
if (answers.ideName === 'codex' && answers.authMode === 'api_key') {
|
|
261
|
-
return '请输入OpenAI API基础URL (可选,默认为官方API):';
|
|
262
|
-
}
|
|
263
223
|
if (answers.authMode === 'auth_token') {
|
|
264
224
|
return '请输入API基础URL (如使用官方API可留空):';
|
|
265
225
|
}
|
|
@@ -270,43 +230,20 @@ class ProviderAdder extends BaseCommand {
|
|
|
270
230
|
if (input === '' && answers.authMode === 'auth_token') {
|
|
271
231
|
return true;
|
|
272
232
|
}
|
|
273
|
-
//
|
|
274
|
-
if (input
|
|
275
|
-
return true;
|
|
276
|
-
}
|
|
277
|
-
// Claude Code 的 api_key 模式需要有效的 URL
|
|
278
|
-
if (!input && answers.ideName === 'claude' && answers.authMode === 'api_key') {
|
|
233
|
+
// 其他模式需要有效的 URL
|
|
234
|
+
if (!input && answers.authMode === 'api_key') {
|
|
279
235
|
return 'API基础URL不能为空';
|
|
280
236
|
}
|
|
281
|
-
|
|
282
|
-
if (
|
|
283
|
-
const error = validator.validateUrl(input);
|
|
284
|
-
if (error) return error;
|
|
285
|
-
}
|
|
237
|
+
const error = validator.validateUrl(input);
|
|
238
|
+
if (error) return error;
|
|
286
239
|
return true;
|
|
287
240
|
},
|
|
288
|
-
|
|
289
|
-
when: (answers) => {
|
|
290
|
-
if (answers.ideName === 'codex') {
|
|
291
|
-
return answers.authMode === 'api_key';
|
|
292
|
-
}
|
|
293
|
-
return answers.authMode === 'api_key' || answers.authMode === 'auth_token';
|
|
294
|
-
}
|
|
241
|
+
when: (answers) => answers.authMode === 'api_key' || answers.authMode === 'auth_token'
|
|
295
242
|
},
|
|
296
243
|
{
|
|
297
244
|
type: 'input',
|
|
298
245
|
name: 'authToken',
|
|
299
246
|
message: (answers) => {
|
|
300
|
-
// Codex 的特殊处理
|
|
301
|
-
if (answers.ideName === 'codex') {
|
|
302
|
-
if (answers.authMode === 'api_key') {
|
|
303
|
-
return '请输入OpenAI API Key (OPENAI_API_KEY):';
|
|
304
|
-
}
|
|
305
|
-
// chatgpt_login 模式不需要输入 Token
|
|
306
|
-
return '请输入认证令牌:';
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
// Claude Code 的处理
|
|
310
247
|
switch (answers.authMode) {
|
|
311
248
|
case 'api_key':
|
|
312
249
|
const tokenTypeLabel = answers.tokenType === 'auth_token' ? 'ANTHROPIC_AUTH_TOKEN' : 'ANTHROPIC_API_KEY';
|
|
@@ -323,9 +260,7 @@ class ProviderAdder extends BaseCommand {
|
|
|
323
260
|
const error = validator.validateToken(input);
|
|
324
261
|
if (error) return error;
|
|
325
262
|
return true;
|
|
326
|
-
}
|
|
327
|
-
// Codex 的 chatgpt_login 模式不需要输入 Token
|
|
328
|
-
when: (answers) => !(answers.ideName === 'codex' && answers.authMode === 'chatgpt_login')
|
|
263
|
+
}
|
|
329
264
|
},
|
|
330
265
|
{
|
|
331
266
|
type: 'confirm',
|
package/src/commands/list.js
CHANGED
|
@@ -33,32 +33,18 @@ class ProviderLister {
|
|
|
33
33
|
const availabilityText = this._formatAvailability(availability);
|
|
34
34
|
const nameColor = isCurrent ? chalk.green : chalk.white;
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
const ideIcon = provider.ideName === 'codex' ? '⚙️' : '🚀';
|
|
38
|
-
const ideLabel = provider.ideName === 'codex' ? 'Codex' : 'Claude Code';
|
|
39
|
-
|
|
40
|
-
console.log(`${status} ${availabilityIcon} ${nameColor(provider.name)} (${provider.displayName}) [${ideIcon} ${ideLabel}] - ${availabilityText}`);
|
|
36
|
+
console.log(`${status} ${availabilityIcon} ${nameColor(provider.name)} (${provider.displayName}) - ${availabilityText}`);
|
|
41
37
|
|
|
42
38
|
// 显示认证模式
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
chatgpt_login: 'ChatGPT 登录'
|
|
49
|
-
};
|
|
50
|
-
} else {
|
|
51
|
-
// Claude Code 认证模式
|
|
52
|
-
authModeDisplay = {
|
|
53
|
-
api_key: '通用API密钥模式',
|
|
54
|
-
auth_token: '认证令牌模式',
|
|
55
|
-
oauth_token: 'OAuth令牌模式'
|
|
56
|
-
};
|
|
57
|
-
}
|
|
39
|
+
const authModeDisplay = {
|
|
40
|
+
api_key: '通用API密钥模式',
|
|
41
|
+
auth_token: '认证令牌模式',
|
|
42
|
+
oauth_token: 'OAuth令牌模式'
|
|
43
|
+
};
|
|
58
44
|
console.log(chalk.gray(` 认证模式: ${authModeDisplay[provider.authMode] || provider.authMode}`));
|
|
59
45
|
|
|
60
|
-
// 如果是
|
|
61
|
-
if (provider.
|
|
46
|
+
// 如果是 api_key 模式,显示 tokenType
|
|
47
|
+
if (provider.authMode === 'api_key' && provider.tokenType) {
|
|
62
48
|
const tokenTypeDisplay = provider.tokenType === 'auth_token' ? 'ANTHROPIC_AUTH_TOKEN' : 'ANTHROPIC_API_KEY';
|
|
63
49
|
console.log(chalk.gray(` Token类型: ${tokenTypeDisplay}`));
|
|
64
50
|
}
|
|
@@ -67,11 +53,8 @@ class ProviderLister {
|
|
|
67
53
|
console.log(chalk.gray(` API基础URL: ${provider.baseUrl}`));
|
|
68
54
|
}
|
|
69
55
|
|
|
70
|
-
// 仅在有 authToken 时显示(Codex ChatGPT 登录模式没有 Token)
|
|
71
56
|
if (provider.authToken) {
|
|
72
57
|
console.log(chalk.gray(` Token: ${provider.authToken.substring(0, 10)}...`));
|
|
73
|
-
} else if (provider.ideName === 'codex') {
|
|
74
|
-
console.log(chalk.gray(` 认证: ChatGPT 交互式登录(无需 Token)`));
|
|
75
58
|
}
|
|
76
59
|
|
|
77
60
|
if (provider.launchArgs && provider.launchArgs.length > 0) {
|
package/src/commands/switch.js
CHANGED
|
@@ -40,13 +40,11 @@ class EnvSwitcher extends BaseCommand {
|
|
|
40
40
|
console.log();
|
|
41
41
|
console.log(UIHelper.createCard('供应商', UIHelper.formatProvider(provider), UIHelper.icons.info));
|
|
42
42
|
console.log();
|
|
43
|
-
// 根据 IDE 类型动态显示启动提示
|
|
44
|
-
const launchLabel = provider.ideName === 'codex' ? '启动 Codex' : '启动 Claude Code';
|
|
45
43
|
console.log(UIHelper.createHintLine([
|
|
46
44
|
['空格', '切换选中'],
|
|
47
45
|
['A', '全选'],
|
|
48
46
|
['I', '反选'],
|
|
49
|
-
['Enter',
|
|
47
|
+
['Enter', '启动 Claude Code'],
|
|
50
48
|
['ESC', '返回供应商选择']
|
|
51
49
|
]));
|
|
52
50
|
console.log();
|
|
@@ -200,12 +198,10 @@ class EnvSwitcher extends BaseCommand {
|
|
|
200
198
|
|
|
201
199
|
async launchProvider(provider, selectedLaunchArgs) {
|
|
202
200
|
try {
|
|
203
|
-
//
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
201
|
+
// 执行 Claude Code 设置兼容性检查
|
|
202
|
+
const shouldContinue = await this.ensureClaudeSettingsCompatibility(provider);
|
|
203
|
+
if (!shouldContinue) {
|
|
204
|
+
return;
|
|
209
205
|
}
|
|
210
206
|
|
|
211
207
|
this.clearScreen();
|
|
@@ -232,20 +228,17 @@ class EnvSwitcher extends BaseCommand {
|
|
|
232
228
|
|
|
233
229
|
UIHelper.clearLoadingAnimation(loadingInterval);
|
|
234
230
|
|
|
235
|
-
|
|
236
|
-
const ideName = provider.ideName === 'codex' ? 'Codex' : 'Claude Code';
|
|
237
|
-
const ideIcon = provider.ideName === 'codex' ? '⚙️' : '🚀';
|
|
238
|
-
console.log(UIHelper.createCard('准备就绪', `环境配置完成,正在启动 ${ideIcon} ${ideName}...`, UIHelper.icons.success));
|
|
231
|
+
console.log(UIHelper.createCard('准备就绪', '环境配置完成,正在启动 🚀 Claude Code...', UIHelper.icons.success));
|
|
239
232
|
console.log();
|
|
240
233
|
|
|
241
|
-
//
|
|
234
|
+
// 设置环境变量并启动 Claude Code
|
|
242
235
|
await executeWithEnv(provider, selectedLaunchArgs);
|
|
243
|
-
|
|
236
|
+
|
|
244
237
|
} catch (error) {
|
|
245
238
|
UIHelper.clearLoadingAnimation(loadingInterval);
|
|
246
239
|
throw error;
|
|
247
240
|
}
|
|
248
|
-
|
|
241
|
+
|
|
249
242
|
} catch (error) {
|
|
250
243
|
await this.handleError(error, '启动供应商');
|
|
251
244
|
}
|
|
@@ -24,79 +24,45 @@ function clearTerminal() {
|
|
|
24
24
|
function buildEnvVariables(config) {
|
|
25
25
|
const env = { ...process.env };
|
|
26
26
|
|
|
27
|
-
// Claude Code
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
// 根据 tokenType 选择设置哪种 token
|
|
35
|
-
if (config.tokenType === 'auth_token') {
|
|
36
|
-
env.ANTHROPIC_AUTH_TOKEN = config.authToken;
|
|
37
|
-
} else {
|
|
38
|
-
// 默认使用 ANTHROPIC_API_KEY
|
|
39
|
-
env.ANTHROPIC_API_KEY = config.authToken;
|
|
40
|
-
}
|
|
41
|
-
} else {
|
|
42
|
-
// auth_token 模式
|
|
43
|
-
env.ANTHROPIC_BASE_URL = config.baseUrl;
|
|
27
|
+
// Claude Code 配置
|
|
28
|
+
if (config.authMode === 'oauth_token') {
|
|
29
|
+
env.CLAUDE_CODE_OAUTH_TOKEN = config.authToken;
|
|
30
|
+
} else if (config.authMode === 'api_key') {
|
|
31
|
+
env.ANTHROPIC_BASE_URL = config.baseUrl;
|
|
32
|
+
// 根据 tokenType 选择设置哪种 token
|
|
33
|
+
if (config.tokenType === 'auth_token') {
|
|
44
34
|
env.ANTHROPIC_AUTH_TOKEN = config.authToken;
|
|
35
|
+
} else {
|
|
36
|
+
// 默认使用 ANTHROPIC_API_KEY
|
|
37
|
+
env.ANTHROPIC_API_KEY = config.authToken;
|
|
45
38
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (config.models && config.models.smallFast) {
|
|
52
|
-
env.ANTHROPIC_SMALL_FAST_MODEL = config.models.smallFast;
|
|
53
|
-
}
|
|
39
|
+
} else {
|
|
40
|
+
// auth_token 模式
|
|
41
|
+
env.ANTHROPIC_BASE_URL = config.baseUrl;
|
|
42
|
+
env.ANTHROPIC_AUTH_TOKEN = config.authToken;
|
|
54
43
|
}
|
|
55
44
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
// 2. OpenAI API Key - 通过 OPENAI_API_KEY 环境变量
|
|
60
|
-
if (config.ideName === 'codex') {
|
|
61
|
-
if (config.authMode === 'api_key' && config.authToken) {
|
|
62
|
-
// 使用 OpenAI API Key 方式
|
|
63
|
-
// Codex 通过 OPENAI_API_KEY 环境变量读取 API 密钥
|
|
64
|
-
env.OPENAI_API_KEY = config.authToken;
|
|
45
|
+
if (config.models && config.models.primary) {
|
|
46
|
+
env.ANTHROPIC_MODEL = config.models.primary;
|
|
47
|
+
}
|
|
65
48
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
env.OPENAI_API_BASE = config.baseUrl;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
// 如果是 chatgpt_login 模式,不需要设置环境变量
|
|
72
|
-
// Codex 会启动交互式登录流程
|
|
49
|
+
if (config.models && config.models.smallFast) {
|
|
50
|
+
env.ANTHROPIC_SMALL_FAST_MODEL = config.models.smallFast;
|
|
73
51
|
}
|
|
74
52
|
|
|
75
53
|
return env;
|
|
76
54
|
}
|
|
77
55
|
|
|
78
56
|
async function executeWithEnv(config, launchArgs = []) {
|
|
79
|
-
// 安全检查:确保 ideName 被明确设置
|
|
80
|
-
if (!config.ideName) {
|
|
81
|
-
throw new Error('供应商配置缺少 ideName 字段,无法启动 IDE');
|
|
82
|
-
}
|
|
83
|
-
|
|
84
57
|
const env = buildEnvVariables(config);
|
|
85
58
|
const args = [...launchArgs];
|
|
86
59
|
|
|
87
60
|
clearTerminal();
|
|
88
61
|
|
|
89
|
-
|
|
90
|
-
// 这是关键的 IDE 选择点 - 避免任何混淆
|
|
91
|
-
const isCodex = config.ideName === 'codex';
|
|
92
|
-
const command = isCodex ? 'codex' : 'claude';
|
|
93
|
-
const description = isCodex ? 'Codex' : 'Claude Code';
|
|
94
|
-
const ideIcon = isCodex ? '⚙️' : '🚀';
|
|
95
|
-
|
|
96
|
-
console.log(`\n启动 ${ideIcon} ${description}...\n`);
|
|
62
|
+
console.log('\n启动 Claude Code...\n');
|
|
97
63
|
|
|
98
64
|
return new Promise((resolve, reject) => {
|
|
99
|
-
const child = spawn(
|
|
65
|
+
const child = spawn('claude', args, {
|
|
100
66
|
stdio: 'inherit',
|
|
101
67
|
env,
|
|
102
68
|
shell: true
|
|
@@ -106,7 +72,7 @@ async function executeWithEnv(config, launchArgs = []) {
|
|
|
106
72
|
if (code === 0) {
|
|
107
73
|
resolve();
|
|
108
74
|
} else {
|
|
109
|
-
reject(new Error(
|
|
75
|
+
reject(new Error(`Claude Code 退出,代码: ${code}`));
|
|
110
76
|
}
|
|
111
77
|
});
|
|
112
78
|
|
|
@@ -13,21 +13,6 @@ class ProviderStatusChecker {
|
|
|
13
13
|
return this._result('unknown', '未找到配置', null);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
// Codex 的特殊处理
|
|
17
|
-
if (provider.ideName === 'codex') {
|
|
18
|
-
if (provider.authMode === 'chatgpt_login') {
|
|
19
|
-
return this._result('online', '使用 ChatGPT 登录', null);
|
|
20
|
-
}
|
|
21
|
-
if (provider.authMode === 'api_key' && !provider.authToken) {
|
|
22
|
-
return this._result('unknown', '未配置 OpenAI API Key', null);
|
|
23
|
-
}
|
|
24
|
-
// Codex 的 api_key 模式支持检测(通过 OpenAI API)
|
|
25
|
-
// 但目前我们暂不实现 OpenAI SDK 的检测,只提示已配置
|
|
26
|
-
if (provider.authMode === 'api_key') {
|
|
27
|
-
return this._result('online', '已配置 OpenAI API Key', null);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
16
|
if (provider.authMode === 'oauth_token') {
|
|
32
17
|
return this._result('unknown', '暂不支持 OAuth 令牌检测', null);
|
|
33
18
|
}
|
package/src/utils/ui-helper.js
CHANGED
|
@@ -78,12 +78,7 @@ class UIHelper {
|
|
|
78
78
|
const statusText = this.createStatus(status, provider.name);
|
|
79
79
|
const displayName = this.colors.secondary(`(${provider.displayName})`);
|
|
80
80
|
|
|
81
|
-
|
|
82
|
-
const ideIcon = provider.ideName === 'codex' ? '⚙️' : '🚀';
|
|
83
|
-
const ideLabel = provider.ideName === 'codex' ? 'Codex' : 'Claude Code';
|
|
84
|
-
const ideText = this.colors.muted(`[${ideIcon} ${ideLabel}]`);
|
|
85
|
-
|
|
86
|
-
return `${statusText} ${displayName} ${ideText}`;
|
|
81
|
+
return `${statusText} ${displayName}`;
|
|
87
82
|
}
|
|
88
83
|
|
|
89
84
|
// 创建进度条
|