@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,208 @@
|
|
|
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 ProviderEditor extends BaseCommand {
|
|
10
|
+
constructor() {
|
|
11
|
+
super();
|
|
12
|
+
this.configManager = new ConfigManager();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async interactive(providerName) {
|
|
16
|
+
await this.configManager.load();
|
|
17
|
+
const providers = this.configManager.listProviders();
|
|
18
|
+
|
|
19
|
+
if (providers.length === 0) {
|
|
20
|
+
Logger.warning('没有可编辑的供应商配置。请先添加一个。');
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let providerToEdit;
|
|
25
|
+
if (providerName) {
|
|
26
|
+
providerToEdit = this.configManager.getProvider(providerName);
|
|
27
|
+
if (!providerToEdit) {
|
|
28
|
+
Logger.error(`供应商 '${providerName}' 不存在。`);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
} else {
|
|
32
|
+
let selection;
|
|
33
|
+
try {
|
|
34
|
+
selection = await this.prompt([
|
|
35
|
+
{
|
|
36
|
+
type: 'list',
|
|
37
|
+
name: 'selectedProviderName',
|
|
38
|
+
message: '请选择要编辑的供应商:',
|
|
39
|
+
choices: [
|
|
40
|
+
...providers.map(p => ({ name: p.displayName || p.name, value: p.name })),
|
|
41
|
+
new inquirer.Separator(),
|
|
42
|
+
{ name: '取消', value: null },
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
]);
|
|
46
|
+
} catch (error) {
|
|
47
|
+
if (this.isEscCancelled(error)) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const { selectedProviderName } = selection;
|
|
54
|
+
|
|
55
|
+
if (!selectedProviderName) {
|
|
56
|
+
Logger.info('操作已取消。');
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
providerToEdit = this.configManager.getProvider(selectedProviderName);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
console.log(UIHelper.createTitle(`编辑供应商: ${providerToEdit.displayName}`, UIHelper.icons.edit));
|
|
63
|
+
console.log();
|
|
64
|
+
console.log(UIHelper.createTooltip('请更新供应商配置信息。按 Enter 键接受默认值。'));
|
|
65
|
+
console.log();
|
|
66
|
+
|
|
67
|
+
const escListener = this.createESCListener(() => {
|
|
68
|
+
Logger.info('取消编辑供应商。');
|
|
69
|
+
const { registry } = require('../CommandRegistry');
|
|
70
|
+
registry.executeCommand('switch');
|
|
71
|
+
}, '取消编辑');
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
let answers;
|
|
75
|
+
try {
|
|
76
|
+
answers = await this.prompt([
|
|
77
|
+
{
|
|
78
|
+
type: 'input',
|
|
79
|
+
name: 'displayName',
|
|
80
|
+
message: '供应商显示名称:',
|
|
81
|
+
default: providerToEdit.displayName,
|
|
82
|
+
validate: (input) => validator.validateDisplayName(input) || true,
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
type: 'list',
|
|
86
|
+
name: 'authMode',
|
|
87
|
+
message: '认证模式:',
|
|
88
|
+
choices: [
|
|
89
|
+
{ name: '🔑 通用API密钥模式 - 支持 ANTHROPIC_API_KEY 和 ANTHROPIC_AUTH_TOKEN', value: 'api_key' },
|
|
90
|
+
{ name: '🔐 认证令牌模式 (仅 ANTHROPIC_AUTH_TOKEN) - 适用于某些服务商', value: 'auth_token' },
|
|
91
|
+
{ name: '🌐 OAuth令牌模式 (CLAUDE_CODE_OAUTH_TOKEN) - 适用于官方Claude Code', value: 'oauth_token' },
|
|
92
|
+
],
|
|
93
|
+
default: providerToEdit.authMode,
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
type: 'list',
|
|
97
|
+
name: 'tokenType',
|
|
98
|
+
message: 'Token类型:',
|
|
99
|
+
choices: [
|
|
100
|
+
{ name: '🔑 ANTHROPIC_API_KEY - 通用API密钥', value: 'api_key' },
|
|
101
|
+
{ name: '🔐 ANTHROPIC_AUTH_TOKEN - 认证令牌', value: 'auth_token' }
|
|
102
|
+
],
|
|
103
|
+
default: providerToEdit.tokenType || 'api_key',
|
|
104
|
+
when: (answers) => answers.authMode === 'api_key'
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
type: 'input',
|
|
108
|
+
name: 'baseUrl',
|
|
109
|
+
message: 'API基础URL:',
|
|
110
|
+
default: providerToEdit.baseUrl,
|
|
111
|
+
validate: (input) => validator.validateUrl(input) || true,
|
|
112
|
+
when: (answers) => answers.authMode === 'api_key' || answers.authMode === 'auth_token',
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
type: 'input',
|
|
116
|
+
name: 'authToken',
|
|
117
|
+
message: (answers) => {
|
|
118
|
+
switch (answers.authMode) {
|
|
119
|
+
case 'api_key':
|
|
120
|
+
const tokenTypeLabel = answers.tokenType === 'auth_token' ? 'ANTHROPIC_AUTH_TOKEN' : 'ANTHROPIC_API_KEY';
|
|
121
|
+
return `Token (${tokenTypeLabel}):`;
|
|
122
|
+
case 'auth_token': return '认证令牌 (ANTHROPIC_AUTH_TOKEN):';
|
|
123
|
+
case 'oauth_token': return 'OAuth令牌 (CLAUDE_CODE_OAUTH_TOKEN):';
|
|
124
|
+
default: return '认证令牌:';
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
default: providerToEdit.authToken,
|
|
128
|
+
validate: (input) => validator.validateToken(input) || true,
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
type: 'checkbox',
|
|
132
|
+
name: 'launchArgs',
|
|
133
|
+
message: '启动参数:',
|
|
134
|
+
choices: validator.getAvailableLaunchArgs().map(arg => ({
|
|
135
|
+
name: `${arg.label || arg.name} (${arg.name})${arg.description ? ' - ' + arg.description : ''}`,
|
|
136
|
+
value: arg.name,
|
|
137
|
+
checked: providerToEdit.launchArgs && providerToEdit.launchArgs.includes(arg.name),
|
|
138
|
+
})),
|
|
139
|
+
},
|
|
140
|
+
]);
|
|
141
|
+
} catch (error) {
|
|
142
|
+
this.removeESCListener(escListener);
|
|
143
|
+
if (this.isEscCancelled(error)) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
throw error;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
this.removeESCListener(escListener);
|
|
150
|
+
await this.saveProvider(providerToEdit.name, answers);
|
|
151
|
+
|
|
152
|
+
} catch (error) {
|
|
153
|
+
this.removeESCListener(escListener);
|
|
154
|
+
if (this.isEscCancelled(error)) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
throw error;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async saveProvider(name, answers) {
|
|
162
|
+
try {
|
|
163
|
+
// Re-use addProvider which can overwrite existing providers
|
|
164
|
+
await this.configManager.addProvider(name, {
|
|
165
|
+
displayName: answers.displayName,
|
|
166
|
+
baseUrl: answers.baseUrl,
|
|
167
|
+
authToken: answers.authToken,
|
|
168
|
+
authMode: answers.authMode,
|
|
169
|
+
tokenType: answers.tokenType, // 仅在 authMode 为 'api_key' 时使用
|
|
170
|
+
launchArgs: answers.launchArgs,
|
|
171
|
+
// Retain original model settings unless we add editing for them
|
|
172
|
+
primaryModel: this.configManager.getProvider(name).models.primary,
|
|
173
|
+
smallFastModel: this.configManager.getProvider(name).models.smallFast,
|
|
174
|
+
setAsDefault: false, // Don't change default status on edit
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
Logger.success(`供应商 '${answers.displayName}' 更新成功!`);
|
|
178
|
+
|
|
179
|
+
console.log(chalk.green('\n🎉 供应商编辑完成!正在返回主界面...'));
|
|
180
|
+
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
181
|
+
|
|
182
|
+
const { registry } = require('../CommandRegistry');
|
|
183
|
+
return await registry.executeCommand('switch');
|
|
184
|
+
|
|
185
|
+
} catch (error) {
|
|
186
|
+
if (this.isEscCancelled(error)) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
Logger.error(`更新供应商失败: ${error.message}`);
|
|
190
|
+
throw error;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
async function editCommand(providerName) {
|
|
196
|
+
const editor = new ProviderEditor();
|
|
197
|
+
try {
|
|
198
|
+
await editor.interactive(providerName);
|
|
199
|
+
} catch (error) {
|
|
200
|
+
if (!editor.isEscCancelled(error)) {
|
|
201
|
+
Logger.error(`编辑供应商失败: ${error.message}`);
|
|
202
|
+
}
|
|
203
|
+
} finally {
|
|
204
|
+
editor.destroy();
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
module.exports = { editCommand, ProviderEditor };
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const { ConfigManager } = require('../config');
|
|
3
|
+
const { Logger } = require('../utils/logger');
|
|
4
|
+
const { ProviderStatusChecker } = require('../utils/provider-status-checker');
|
|
5
|
+
|
|
6
|
+
class ProviderLister {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.configManager = new ConfigManager();
|
|
9
|
+
this.statusChecker = new ProviderStatusChecker();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async list() {
|
|
13
|
+
try {
|
|
14
|
+
await this.configManager.ensureLoaded();
|
|
15
|
+
const providers = this.configManager.listProviders();
|
|
16
|
+
const currentProvider = this.configManager.getCurrentProvider();
|
|
17
|
+
const statusMap = await this.statusChecker.checkAll(providers);
|
|
18
|
+
|
|
19
|
+
if (providers.length === 0) {
|
|
20
|
+
Logger.warning('暂无配置的供应商');
|
|
21
|
+
Logger.info('请使用 "akm add" 添加供应商配置');
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
console.log(chalk.blue('\n📋 供应商列表:'));
|
|
26
|
+
console.log(chalk.gray('═'.repeat(60)));
|
|
27
|
+
|
|
28
|
+
providers.forEach((provider, index) => {
|
|
29
|
+
const isCurrent = provider.name === currentProvider?.name;
|
|
30
|
+
const status = isCurrent ? '✅' : '🔹';
|
|
31
|
+
const availability = statusMap[provider.name] || { state: 'unknown', label: '未知', latency: null };
|
|
32
|
+
const availabilityIcon = this._iconForState(availability.state);
|
|
33
|
+
const availabilityText = this._formatAvailability(availability);
|
|
34
|
+
const nameColor = isCurrent ? chalk.green : chalk.white;
|
|
35
|
+
|
|
36
|
+
console.log(`${status} ${availabilityIcon} ${nameColor(provider.name)} (${provider.displayName}) - ${availabilityText}`);
|
|
37
|
+
|
|
38
|
+
// 显示认证模式
|
|
39
|
+
const authModeDisplay = {
|
|
40
|
+
api_key: '通用API密钥模式',
|
|
41
|
+
auth_token: '认证令牌模式',
|
|
42
|
+
oauth_token: 'OAuth令牌模式'
|
|
43
|
+
};
|
|
44
|
+
console.log(chalk.gray(` 认证模式: ${authModeDisplay[provider.authMode] || provider.authMode}`));
|
|
45
|
+
|
|
46
|
+
// 如果是 api_key 模式,显示 tokenType
|
|
47
|
+
if (provider.authMode === 'api_key' && provider.tokenType) {
|
|
48
|
+
const tokenTypeDisplay = provider.tokenType === 'auth_token' ? 'ANTHROPIC_AUTH_TOKEN' : 'ANTHROPIC_API_KEY';
|
|
49
|
+
console.log(chalk.gray(` Token类型: ${tokenTypeDisplay}`));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (provider.baseUrl) {
|
|
53
|
+
console.log(chalk.gray(` URL: ${provider.baseUrl}`));
|
|
54
|
+
}
|
|
55
|
+
console.log(chalk.gray(` Token: ${provider.authToken}`));
|
|
56
|
+
if (provider.launchArgs && provider.launchArgs.length > 0) {
|
|
57
|
+
console.log(chalk.gray(` 启动参数: ${provider.launchArgs.join(' ')}`));
|
|
58
|
+
}
|
|
59
|
+
if (provider.models && (provider.models.primary || provider.models.smallFast)) {
|
|
60
|
+
console.log(chalk.gray(` 主模型: ${provider.models.primary || '未设置'}`));
|
|
61
|
+
console.log(chalk.gray(` 快速模型: ${provider.models.smallFast || '未设置'}`));
|
|
62
|
+
}
|
|
63
|
+
console.log(chalk.gray(` 创建时间: ${new Date(provider.createdAt).toLocaleString()}`));
|
|
64
|
+
console.log(chalk.gray(` 最后使用: ${new Date(provider.lastUsed).toLocaleString()}`));
|
|
65
|
+
|
|
66
|
+
if (index < providers.length - 1) {
|
|
67
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
console.log(chalk.gray('═'.repeat(60)));
|
|
72
|
+
|
|
73
|
+
if (currentProvider) {
|
|
74
|
+
console.log(chalk.green(`\n当前供应商: ${currentProvider.displayName}`));
|
|
75
|
+
} else {
|
|
76
|
+
console.log(chalk.yellow('\n未设置当前供应商'));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
console.log(chalk.blue(`\n总计: ${providers.length} 个供应商`));
|
|
80
|
+
|
|
81
|
+
} catch (error) {
|
|
82
|
+
Logger.error(`获取供应商列表失败: ${error.message}`);
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
_iconForState(state) {
|
|
88
|
+
if (state === 'online') {
|
|
89
|
+
return '🟢';
|
|
90
|
+
}
|
|
91
|
+
if (state === 'degraded') {
|
|
92
|
+
return '🟡';
|
|
93
|
+
}
|
|
94
|
+
if (state === 'offline') {
|
|
95
|
+
return '🔴';
|
|
96
|
+
}
|
|
97
|
+
return '⚪';
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
_formatAvailability(availability) {
|
|
101
|
+
if (!availability) {
|
|
102
|
+
return '未知';
|
|
103
|
+
}
|
|
104
|
+
if (availability.state === 'online') {
|
|
105
|
+
return chalk.green(availability.label);
|
|
106
|
+
}
|
|
107
|
+
if (availability.state === 'degraded') {
|
|
108
|
+
return chalk.yellow(availability.label);
|
|
109
|
+
}
|
|
110
|
+
if (availability.state === 'offline') {
|
|
111
|
+
return chalk.red(availability.label);
|
|
112
|
+
}
|
|
113
|
+
return chalk.gray(availability.label || '未知');
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async function listCommand() {
|
|
118
|
+
const lister = new ProviderLister();
|
|
119
|
+
await lister.list();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
module.exports = { listCommand, ProviderLister };
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
const inquirer = require('inquirer');
|
|
2
|
+
const { ConfigManager } = require('../config');
|
|
3
|
+
const { Logger } = require('../utils/logger');
|
|
4
|
+
const { UIHelper } = require('../utils/ui-helper');
|
|
5
|
+
const { BaseCommand } = require('./BaseCommand');
|
|
6
|
+
|
|
7
|
+
class ProviderRemover extends BaseCommand {
|
|
8
|
+
constructor() {
|
|
9
|
+
super();
|
|
10
|
+
this.configManager = new ConfigManager();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async remove(providerName) {
|
|
14
|
+
try {
|
|
15
|
+
await this.configManager.ensureLoaded();
|
|
16
|
+
|
|
17
|
+
// 如果没有指定供应商名称,显示选择列表
|
|
18
|
+
if (!providerName) {
|
|
19
|
+
return await this.interactiveRemove();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// 直接删除指定供应商
|
|
23
|
+
if (!this.configManager.getProvider(providerName)) {
|
|
24
|
+
Logger.error(`供应商 '${providerName}' 不存在`);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const provider = this.configManager.getProvider(providerName);
|
|
29
|
+
let confirm;
|
|
30
|
+
try {
|
|
31
|
+
confirm = await this.prompt([
|
|
32
|
+
{
|
|
33
|
+
type: 'confirm',
|
|
34
|
+
name: 'confirm',
|
|
35
|
+
message: `确定要删除供应商 '${provider.displayName}' 吗?`,
|
|
36
|
+
default: false
|
|
37
|
+
}
|
|
38
|
+
]);
|
|
39
|
+
} catch (error) {
|
|
40
|
+
if (this.isEscCancelled(error)) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (!confirm.confirm) {
|
|
47
|
+
Logger.warning('删除操作已取消');
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
await this.configManager.removeProvider(providerName);
|
|
52
|
+
Logger.success(`供应商 '${provider.displayName}' 已删除`);
|
|
53
|
+
|
|
54
|
+
} catch (error) {
|
|
55
|
+
if (this.isEscCancelled(error)) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
Logger.error(`删除供应商失败: ${error.message}`);
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async interactiveRemove() {
|
|
64
|
+
await this.configManager.ensureLoaded();
|
|
65
|
+
const providers = this.configManager.listProviders();
|
|
66
|
+
|
|
67
|
+
if (providers.length === 0) {
|
|
68
|
+
Logger.warning('暂无配置的供应商');
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
console.log(UIHelper.createTitle('删除供应商', UIHelper.icons.delete));
|
|
73
|
+
console.log();
|
|
74
|
+
console.log(UIHelper.createTooltip('选择要删除的供应商'));
|
|
75
|
+
console.log();
|
|
76
|
+
|
|
77
|
+
const choices = providers.map(provider => ({
|
|
78
|
+
name: `${provider.current ? '✅' : '🔹'} ${provider.name} (${provider.displayName})${provider.current ? ' - 当前使用中' : ''}`,
|
|
79
|
+
value: provider.name,
|
|
80
|
+
short: provider.name
|
|
81
|
+
}));
|
|
82
|
+
|
|
83
|
+
choices.push(
|
|
84
|
+
new inquirer.Separator(),
|
|
85
|
+
{ name: '❌ 取消删除', value: '__CANCEL__' }
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
// 对于删除操作,不默认选中当前供应商,而是选中第一个非当前的供应商
|
|
89
|
+
const nonCurrentProvider = providers.find(p => !p.current);
|
|
90
|
+
const defaultChoice = nonCurrentProvider ? nonCurrentProvider.name : providers[0]?.name;
|
|
91
|
+
|
|
92
|
+
// 设置 ESC 键监听
|
|
93
|
+
const escListener = this.createESCListener(() => {
|
|
94
|
+
Logger.info('取消删除供应商');
|
|
95
|
+
// 使用CommandRegistry避免循环引用
|
|
96
|
+
const { registry } = require('../CommandRegistry');
|
|
97
|
+
registry.executeCommand('switch');
|
|
98
|
+
}, '取消删除');
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
let answer;
|
|
102
|
+
try {
|
|
103
|
+
answer = await this.prompt([
|
|
104
|
+
{
|
|
105
|
+
type: 'list',
|
|
106
|
+
name: 'provider',
|
|
107
|
+
message: '选择要删除的供应商:',
|
|
108
|
+
choices,
|
|
109
|
+
default: defaultChoice,
|
|
110
|
+
pageSize: 10
|
|
111
|
+
}
|
|
112
|
+
]);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
this.removeESCListener(escListener);
|
|
115
|
+
if (this.isEscCancelled(error)) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
this.removeESCListener(escListener);
|
|
122
|
+
|
|
123
|
+
if (answer.provider === '__CANCEL__') {
|
|
124
|
+
Logger.info('删除操作已取消');
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
await this.remove(answer.provider);
|
|
129
|
+
} catch (error) {
|
|
130
|
+
this.removeESCListener(escListener);
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async function removeCommand(providerName) {
|
|
137
|
+
const remover = new ProviderRemover();
|
|
138
|
+
try {
|
|
139
|
+
await remover.remove(providerName);
|
|
140
|
+
} catch (error) {
|
|
141
|
+
if (!remover.isEscCancelled(error)) {
|
|
142
|
+
Logger.error(`删除供应商失败: ${error.message}`);
|
|
143
|
+
}
|
|
144
|
+
} finally {
|
|
145
|
+
// 确保资源清理
|
|
146
|
+
remover.destroy();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
module.exports = { removeCommand, ProviderRemover };
|