ccman 1.0.1 → 2.0.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/.env.development +3 -0
- package/.env.production +3 -0
- package/.github/workflows/release.yml +5 -5
- package/CLAUDE.md +246 -185
- package/README.md +282 -249
- package/README_zh.md +283 -250
- package/dev-test.sh +40 -0
- package/dist/cli.js +425 -369
- package/dist/cli.js.map +1 -1
- package/dist/commands/lang.d.ts +3 -0
- package/dist/commands/lang.d.ts.map +1 -0
- package/dist/commands/lang.js +99 -0
- package/dist/commands/lang.js.map +1 -0
- package/dist/config/static-env.d.ts +14 -0
- package/dist/config/static-env.d.ts.map +1 -0
- package/dist/config/static-env.js +17 -0
- package/dist/config/static-env.js.map +1 -0
- package/dist/core/CCMConfigManager.d.ts +52 -0
- package/dist/core/CCMConfigManager.d.ts.map +1 -0
- package/dist/core/CCMConfigManager.js +203 -0
- package/dist/core/CCMConfigManager.js.map +1 -0
- package/dist/core/ClaudeConfigManager.d.ts +35 -0
- package/dist/core/ClaudeConfigManager.d.ts.map +1 -0
- package/dist/core/ClaudeConfigManager.js +149 -0
- package/dist/core/ClaudeConfigManager.js.map +1 -0
- package/dist/i18n/LanguageManager.d.ts +43 -0
- package/dist/i18n/LanguageManager.d.ts.map +1 -0
- package/dist/i18n/LanguageManager.js +157 -0
- package/dist/i18n/LanguageManager.js.map +1 -0
- package/dist/i18n/messages.d.ts +65 -0
- package/dist/i18n/messages.d.ts.map +1 -0
- package/dist/i18n/messages.js +144 -0
- package/dist/i18n/messages.js.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -8
- package/dist/index.js.map +1 -1
- package/dist/providers/ProviderManager.d.ts +58 -0
- package/dist/providers/ProviderManager.d.ts.map +1 -0
- package/dist/providers/ProviderManager.js +335 -0
- package/dist/providers/ProviderManager.js.map +1 -0
- package/dist/types/index.d.ts +78 -38
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -1
- package/dist/utils/env-config.d.ts +27 -0
- package/dist/utils/env-config.d.ts.map +1 -0
- package/dist/{config/constants.js → utils/env-config.js} +36 -50
- package/dist/utils/env-config.js.map +1 -0
- package/dist/utils/version.d.ts +2 -64
- package/dist/utils/version.d.ts.map +1 -1
- package/dist/utils/version.js +12 -158
- package/dist/utils/version.js.map +1 -1
- package/package.json +17 -16
- package/release-temp/README.md +282 -249
- package/release-temp/package.json +17 -16
- package/scripts/build-env.js +75 -0
- package/scripts/modules/create-tag.sh +53 -10
- package/scripts/modules/monitor-release.sh +40 -12
- package/scripts/modules/version-bump.sh +14 -17
- package/scripts/smart-release-v3.sh +20 -26
- package/src/cli.ts +462 -394
- package/src/commands/lang.ts +105 -0
- package/src/core/CCMConfigManager.ts +185 -0
- package/src/core/ClaudeConfigManager.ts +125 -0
- package/src/i18n/LanguageManager.ts +169 -0
- package/src/i18n/messages.ts +233 -0
- package/src/index.ts +4 -5
- package/src/providers/ProviderManager.ts +393 -0
- package/src/types/index.ts +80 -39
- package/src/utils/env-config.ts +53 -0
- package/src/utils/version.ts +11 -184
- package/dist/config/ConfigManager.d.ts +0 -67
- package/dist/config/ConfigManager.d.ts.map +0 -1
- package/dist/config/ConfigManager.js +0 -226
- package/dist/config/ConfigManager.js.map +0 -1
- package/dist/config/EnvironmentManager.d.ts +0 -83
- package/dist/config/EnvironmentManager.d.ts.map +0 -1
- package/dist/config/EnvironmentManager.js +0 -280
- package/dist/config/EnvironmentManager.js.map +0 -1
- package/dist/config/constants.d.ts +0 -40
- package/dist/config/constants.d.ts.map +0 -1
- package/dist/config/constants.js.map +0 -1
- package/dist/shell/ShellManager.d.ts +0 -81
- package/dist/shell/ShellManager.d.ts.map +0 -1
- package/dist/shell/ShellManager.js +0 -490
- package/dist/shell/ShellManager.js.map +0 -1
- package/src/config/ConfigManager.ts +0 -227
- package/src/config/EnvironmentManager.ts +0 -327
- package/src/config/constants.ts +0 -64
- package/src/shell/ShellManager.ts +0 -526
package/src/cli.ts
CHANGED
|
@@ -3,120 +3,415 @@
|
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
5
|
import inquirer from 'inquirer';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
6
|
+
import { ProviderManager } from './providers/ProviderManager';
|
|
7
|
+
import { AddProviderOptions } from './types';
|
|
8
|
+
import { LanguageManager } from './i18n/LanguageManager';
|
|
9
|
+
import { createLanguageCommands } from './commands/lang';
|
|
10
|
+
import { getPackageVersion } from './utils/version';
|
|
9
11
|
|
|
10
12
|
const program = new Command();
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
13
|
+
const providerManager = new ProviderManager();
|
|
14
|
+
const languageManager = new LanguageManager();
|
|
15
|
+
|
|
16
|
+
// 询问是否继续操作
|
|
17
|
+
async function askToContinue(): Promise<boolean> {
|
|
18
|
+
const messages = await languageManager.getMessages();
|
|
19
|
+
const answer = await inquirer.prompt([
|
|
20
|
+
{
|
|
21
|
+
type: 'confirm',
|
|
22
|
+
name: 'continue',
|
|
23
|
+
message: messages.forms.continueOperation,
|
|
24
|
+
default: true
|
|
25
|
+
}
|
|
26
|
+
]);
|
|
27
|
+
return answer.continue;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// 交互式配置菜单
|
|
31
|
+
async function showInteractiveMenu(): Promise<void> {
|
|
32
|
+
// 处理首次运行语言设置
|
|
33
|
+
await languageManager.handleFirstRun();
|
|
25
34
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
console.log(` Base URL: ${result.env.baseUrl}`);
|
|
29
|
-
}
|
|
35
|
+
// 获取当前语言的消息
|
|
36
|
+
const messages = await languageManager.getMessages();
|
|
30
37
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
// 设置 Ctrl+C 优雅退出处理
|
|
39
|
+
process.removeAllListeners('SIGINT');
|
|
40
|
+
process.on('SIGINT', () => {
|
|
41
|
+
console.log(chalk.yellow(messages.interruptMessage));
|
|
42
|
+
process.exit(0);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
let shouldContinue = true;
|
|
47
|
+
|
|
48
|
+
while (shouldContinue) {
|
|
49
|
+
await providerManager.init();
|
|
50
|
+
const providers = await providerManager.listProviders();
|
|
51
|
+
|
|
52
|
+
if (providers.length === 0) {
|
|
53
|
+
console.log(chalk.yellow(messages.noProvidersFound));
|
|
54
|
+
|
|
55
|
+
const answers = await inquirer.prompt([
|
|
56
|
+
{
|
|
57
|
+
type: 'input',
|
|
58
|
+
name: 'id',
|
|
59
|
+
message: messages.forms.providerId,
|
|
60
|
+
default: 'anthropic'
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
type: 'input',
|
|
64
|
+
name: 'name',
|
|
65
|
+
message: messages.forms.providerName,
|
|
66
|
+
default: 'Anthropic Official'
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
type: 'input',
|
|
70
|
+
name: 'description',
|
|
71
|
+
message: messages.forms.description,
|
|
72
|
+
default: 'Official Anthropic API'
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
type: 'input',
|
|
76
|
+
name: 'baseUrl',
|
|
77
|
+
message: messages.forms.baseUrl,
|
|
78
|
+
default: 'https://api.anthropic.com'
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
type: 'password',
|
|
82
|
+
name: 'apiKey',
|
|
83
|
+
message: messages.forms.apiKey,
|
|
84
|
+
mask: '*'
|
|
85
|
+
}
|
|
86
|
+
]);
|
|
87
|
+
|
|
88
|
+
const result = await providerManager.addProvider({
|
|
89
|
+
id: answers.id,
|
|
90
|
+
name: answers.name,
|
|
91
|
+
description: answers.description,
|
|
92
|
+
baseUrl: answers.baseUrl,
|
|
93
|
+
apiKey: answers.apiKey
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
if (result.success) {
|
|
97
|
+
console.log(chalk.green(`✓ ${result.message}`));
|
|
98
|
+
// 自动设为当前供应商
|
|
99
|
+
const useResult = await providerManager.useProvider(answers.id);
|
|
100
|
+
if (useResult.success) {
|
|
101
|
+
console.log(chalk.green(`✓ ${useResult.message}`));
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
console.error(chalk.red(`✗ ${result.message}`));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
console.log();
|
|
108
|
+
shouldContinue = await askToContinue();
|
|
109
|
+
continue;
|
|
41
110
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
111
|
+
|
|
112
|
+
const choices = providers.map(provider => ({
|
|
113
|
+
name: `${provider.name} (${provider.id}) - ${provider.baseUrl}${provider.isCurrent ? ' [current]' : ''}`,
|
|
114
|
+
value: provider.id
|
|
115
|
+
}));
|
|
116
|
+
|
|
117
|
+
const action = await inquirer.prompt([
|
|
45
118
|
{
|
|
46
119
|
type: 'list',
|
|
47
|
-
name: '
|
|
48
|
-
message:
|
|
120
|
+
name: 'action',
|
|
121
|
+
message: messages.mainMenuTitle,
|
|
49
122
|
choices: [
|
|
50
|
-
{ name:
|
|
51
|
-
{ name:
|
|
52
|
-
|
|
53
|
-
|
|
123
|
+
{ name: messages.mainMenuOptions.switchProvider, value: 'switch' },
|
|
124
|
+
{ name: messages.mainMenuOptions.addProvider, value: 'add' },
|
|
125
|
+
{ name: messages.mainMenuOptions.updateProvider, value: 'update' },
|
|
126
|
+
{ name: messages.mainMenuOptions.removeProvider, value: 'remove' },
|
|
127
|
+
{ name: messages.mainMenuOptions.showStatus, value: 'status' },
|
|
128
|
+
{ name: messages.mainMenuOptions.exit, value: 'exit' }
|
|
129
|
+
]
|
|
54
130
|
}
|
|
55
131
|
]);
|
|
56
|
-
|
|
57
|
-
if (
|
|
58
|
-
console.log(chalk.
|
|
59
|
-
|
|
132
|
+
|
|
133
|
+
if (action.action === 'exit') {
|
|
134
|
+
console.log(chalk.cyan(messages.exitMessage));
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
switch (action.action) {
|
|
139
|
+
case 'switch': {
|
|
140
|
+
const switchAnswer = await inquirer.prompt([
|
|
141
|
+
{
|
|
142
|
+
type: 'list',
|
|
143
|
+
name: 'id',
|
|
144
|
+
message: 'Select provider:',
|
|
145
|
+
choices
|
|
146
|
+
}
|
|
147
|
+
]);
|
|
60
148
|
|
|
61
|
-
|
|
62
|
-
|
|
149
|
+
const switchResult = await providerManager.useProvider(switchAnswer.id);
|
|
150
|
+
if (switchResult.success) {
|
|
151
|
+
console.log(chalk.green(`✓ ${switchResult.message}`));
|
|
63
152
|
} else {
|
|
64
|
-
console.
|
|
65
|
-
console.log(chalk.cyan('Please run manually: source ~/.bashrc (or ~/.zshrc)'));
|
|
153
|
+
console.error(chalk.red(`✗ ${switchResult.message}`));
|
|
66
154
|
}
|
|
67
|
-
|
|
68
|
-
console.log(
|
|
69
|
-
|
|
155
|
+
|
|
156
|
+
console.log();
|
|
157
|
+
shouldContinue = await askToContinue();
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
case 'add': {
|
|
162
|
+
const addAnswers = await inquirer.prompt([
|
|
163
|
+
{ type: 'input', name: 'id', message: 'Provider ID:' },
|
|
164
|
+
{ type: 'input', name: 'name', message: 'Provider name:' },
|
|
165
|
+
{ type: 'input', name: 'description', message: 'Description:' },
|
|
166
|
+
{ type: 'input', name: 'baseUrl', message: 'Base URL:' },
|
|
167
|
+
{ type: 'password', name: 'apiKey', message: 'API Key:', mask: '*' }
|
|
168
|
+
]);
|
|
169
|
+
|
|
170
|
+
const addResult = await providerManager.addProvider(addAnswers);
|
|
171
|
+
if (addResult.success) {
|
|
172
|
+
console.log(chalk.green(`✓ ${addResult.message}`));
|
|
173
|
+
} else {
|
|
174
|
+
console.error(chalk.red(`✗ ${addResult.message}`));
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
console.log();
|
|
178
|
+
shouldContinue = await askToContinue();
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
case 'update': {
|
|
183
|
+
const updateIdAnswer = await inquirer.prompt([
|
|
184
|
+
{
|
|
185
|
+
type: 'list',
|
|
186
|
+
name: 'id',
|
|
187
|
+
message: 'Select provider to update:',
|
|
188
|
+
choices
|
|
189
|
+
}
|
|
190
|
+
]);
|
|
191
|
+
|
|
192
|
+
const currentProvider = providers.find(p => p.id === updateIdAnswer.id);
|
|
193
|
+
if (currentProvider) {
|
|
194
|
+
const updateAnswers = await inquirer.prompt([
|
|
195
|
+
{ type: 'input', name: 'name', message: 'Provider name:', default: currentProvider.name },
|
|
196
|
+
{ type: 'input', name: 'description', message: 'Description:', default: currentProvider.description },
|
|
197
|
+
{ type: 'input', name: 'baseUrl', message: 'Base URL:', default: currentProvider.baseUrl },
|
|
198
|
+
{ type: 'password', name: 'apiKey', message: 'API Key (leave empty to keep current):', mask: '*' }
|
|
199
|
+
]);
|
|
200
|
+
|
|
201
|
+
const updateOptions: Partial<AddProviderOptions> = {
|
|
202
|
+
name: updateAnswers.name,
|
|
203
|
+
description: updateAnswers.description,
|
|
204
|
+
baseUrl: updateAnswers.baseUrl
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
if (updateAnswers.apiKey.trim()) {
|
|
208
|
+
updateOptions.apiKey = updateAnswers.apiKey;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const updateResult = await providerManager.updateProvider(updateIdAnswer.id, updateOptions);
|
|
212
|
+
if (updateResult.success) {
|
|
213
|
+
console.log(chalk.green(`✓ ${updateResult.message}`));
|
|
214
|
+
} else {
|
|
215
|
+
console.error(chalk.red(`✗ ${updateResult.message}`));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
console.log();
|
|
220
|
+
shouldContinue = await askToContinue();
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
case 'remove': {
|
|
225
|
+
const removeAnswer = await inquirer.prompt([
|
|
226
|
+
{
|
|
227
|
+
type: 'list',
|
|
228
|
+
name: 'id',
|
|
229
|
+
message: 'Select provider to remove:',
|
|
230
|
+
choices
|
|
231
|
+
}
|
|
232
|
+
]);
|
|
233
|
+
|
|
234
|
+
const confirmRemove = await inquirer.prompt([
|
|
235
|
+
{
|
|
236
|
+
type: 'confirm',
|
|
237
|
+
name: 'confirm',
|
|
238
|
+
message: `Are you sure you want to remove this provider?`,
|
|
239
|
+
default: false
|
|
240
|
+
}
|
|
241
|
+
]);
|
|
242
|
+
|
|
243
|
+
if (confirmRemove.confirm) {
|
|
244
|
+
const removeResult = await providerManager.removeProvider(removeAnswer.id);
|
|
245
|
+
if (removeResult.success) {
|
|
246
|
+
console.log(chalk.green(`✓ ${removeResult.message}`));
|
|
247
|
+
} else {
|
|
248
|
+
console.error(chalk.red(`✗ ${removeResult.message}`));
|
|
249
|
+
}
|
|
250
|
+
} else {
|
|
251
|
+
console.log(chalk.yellow('Operation cancelled'));
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
console.log();
|
|
255
|
+
shouldContinue = await askToContinue();
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
case 'status': {
|
|
260
|
+
const stats = await providerManager.getStats();
|
|
261
|
+
console.log();
|
|
262
|
+
console.log(chalk.blue('CCM Status:'));
|
|
263
|
+
console.log(`Total providers: ${stats.totalProviders}`);
|
|
264
|
+
console.log(`Current provider: ${stats.currentProvider || 'None'}`);
|
|
265
|
+
console.log(`Claude config: ${stats.claudeConfigPath}`);
|
|
266
|
+
console.log(`CCM config: ${stats.ccmConfigPath}`);
|
|
267
|
+
|
|
268
|
+
if (providers.length > 0) {
|
|
269
|
+
console.log();
|
|
270
|
+
console.log(chalk.blue('Recent providers:'));
|
|
271
|
+
providers
|
|
272
|
+
.filter(p => p.lastUsed)
|
|
273
|
+
.slice(0, 3)
|
|
274
|
+
.forEach(provider => {
|
|
275
|
+
const marker = provider.isCurrent ? chalk.green('* ') : ' ';
|
|
276
|
+
const name = provider.isCurrent ? chalk.green(provider.name) : provider.name;
|
|
277
|
+
const lastUsed = new Date(provider.lastUsed!).toLocaleDateString();
|
|
278
|
+
console.log(`${marker}${name} (${lastUsed}, ${provider.usageCount} uses)`);
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
console.log();
|
|
282
|
+
|
|
283
|
+
console.log();
|
|
284
|
+
shouldContinue = await askToContinue();
|
|
285
|
+
break;
|
|
70
286
|
}
|
|
71
287
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
console.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
288
|
+
} // while 循环结束
|
|
289
|
+
} catch (error) {
|
|
290
|
+
console.error(chalk.red(`✗ Error: ${error}`));
|
|
291
|
+
process.exit(1);
|
|
292
|
+
} finally {
|
|
293
|
+
// 恢复原始的 SIGINT 处理器
|
|
294
|
+
process.removeAllListeners('SIGINT');
|
|
78
295
|
}
|
|
79
296
|
}
|
|
80
297
|
|
|
81
298
|
program
|
|
82
299
|
.name('ccman')
|
|
83
|
-
.description('Claude Code Manager - Manage Claude
|
|
84
|
-
.version(
|
|
300
|
+
.description('Claude Code Manager - Manage Claude API configurations')
|
|
301
|
+
.version(getPackageVersion())
|
|
302
|
+
.hook('preAction', () => {
|
|
303
|
+
// 开发模式提示
|
|
304
|
+
if (process.env.CCM_CONFIG_DIR || process.env.CLAUDE_CONFIG_PATH) {
|
|
305
|
+
console.log(chalk.yellow('🔧 Development Mode:'));
|
|
306
|
+
if (process.env.CCM_CONFIG_DIR) {
|
|
307
|
+
console.log(chalk.yellow(` CCM Config: ${process.env.CCM_CONFIG_DIR}`));
|
|
308
|
+
}
|
|
309
|
+
if (process.env.CLAUDE_CONFIG_PATH) {
|
|
310
|
+
console.log(chalk.yellow(` Claude Config: ${process.env.CLAUDE_CONFIG_PATH}`));
|
|
311
|
+
}
|
|
312
|
+
console.log();
|
|
313
|
+
}
|
|
314
|
+
})
|
|
315
|
+
.action(async () => {
|
|
316
|
+
// 默认无参数时进入交互菜单
|
|
317
|
+
await showInteractiveMenu();
|
|
318
|
+
});
|
|
85
319
|
|
|
86
|
-
//
|
|
320
|
+
// 智能列表命令
|
|
87
321
|
program
|
|
88
|
-
.command('
|
|
89
|
-
.alias('
|
|
90
|
-
.description('List
|
|
91
|
-
.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
322
|
+
.command('ls')
|
|
323
|
+
.alias('list')
|
|
324
|
+
.description('List provider configurations')
|
|
325
|
+
.option('--current', 'Show only current provider details')
|
|
326
|
+
.option('--brief', 'Show brief summary')
|
|
327
|
+
.action(async (options?: { current?: boolean; brief?: boolean }) => {
|
|
328
|
+
try {
|
|
329
|
+
await providerManager.init();
|
|
330
|
+
|
|
331
|
+
if (options?.current) {
|
|
332
|
+
// 显示当前供应商详情
|
|
333
|
+
const currentProvider = await providerManager.getCurrentProvider();
|
|
334
|
+
|
|
335
|
+
if (!currentProvider) {
|
|
336
|
+
console.log(chalk.yellow('No provider is currently active.'));
|
|
337
|
+
console.log('Use "ccman use <id>" to activate a provider.');
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
98
340
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
341
|
+
console.log();
|
|
342
|
+
console.log(chalk.green(`Current provider: ${currentProvider.config.name} (${currentProvider.id})`));
|
|
343
|
+
console.log(`Description: ${currentProvider.config.description}`);
|
|
344
|
+
console.log(`Base URL: ${currentProvider.config.config.env.ANTHROPIC_BASE_URL}`);
|
|
345
|
+
console.log(`API Key: ${'*'.repeat(Math.min(currentProvider.config.config.env.ANTHROPIC_AUTH_TOKEN.length, 20))}`);
|
|
346
|
+
console.log(`Usage count: ${currentProvider.config.metadata.usageCount} times`);
|
|
347
|
+
console.log(`Last updated: ${new Date(currentProvider.config.metadata.updatedAt).toLocaleString()}`);
|
|
348
|
+
console.log();
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const providers = await providerManager.listProviders();
|
|
353
|
+
const stats = await providerManager.getStats();
|
|
354
|
+
|
|
355
|
+
// 显示状态和配置信息,不管是否有providers
|
|
356
|
+
console.log();
|
|
357
|
+
console.log(chalk.blue('CCM Status:'));
|
|
358
|
+
console.log(`Total providers: ${stats.totalProviders}`);
|
|
359
|
+
console.log(`Current provider: ${stats.currentProvider || 'None'}`);
|
|
360
|
+
console.log(`Environment: ${stats.environment}`);
|
|
361
|
+
console.log();
|
|
104
362
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
363
|
+
console.log(chalk.blue('Configuration Files:'));
|
|
364
|
+
console.log(`Claude config: ${chalk.cyan(stats.claudeConfigPath)}`);
|
|
365
|
+
console.log(`CCM config: ${chalk.cyan(stats.ccmConfigFile)}`);
|
|
366
|
+
console.log(`Providers dir: ${chalk.cyan(stats.providersDir)}`);
|
|
367
|
+
console.log();
|
|
368
|
+
|
|
369
|
+
if (providers.length === 0) {
|
|
370
|
+
console.log(chalk.yellow('No provider configurations found. Use "ccman add" to create one.'));
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (options?.brief) {
|
|
375
|
+
// 简洁模式
|
|
376
|
+
providers.forEach(provider => {
|
|
377
|
+
const marker = provider.isCurrent ? chalk.green('* ') : ' ';
|
|
378
|
+
const name = provider.isCurrent ? chalk.green(provider.name) : provider.name;
|
|
379
|
+
console.log(`${marker}${name} (${provider.id})`);
|
|
380
|
+
});
|
|
381
|
+
console.log();
|
|
382
|
+
return;
|
|
108
383
|
}
|
|
109
|
-
|
|
110
|
-
|
|
384
|
+
|
|
385
|
+
// 详细显示providers信息
|
|
386
|
+
console.log(chalk.blue('Providers:'));
|
|
387
|
+
providers.forEach(provider => {
|
|
388
|
+
const marker = provider.isCurrent ? chalk.green('* ') : ' ';
|
|
389
|
+
const name = provider.isCurrent ? chalk.green(provider.name) : provider.name;
|
|
390
|
+
console.log(`${marker}${name.padEnd(15)} ${provider.baseUrl}`);
|
|
391
|
+
console.log(`${' '.repeat(17)} ${provider.description}`);
|
|
392
|
+
|
|
393
|
+
if (provider.lastUsed) {
|
|
394
|
+
const lastUsed = new Date(provider.lastUsed).toLocaleDateString();
|
|
395
|
+
console.log(`${' '.repeat(17)} Last used: ${lastUsed}, Usage: ${provider.usageCount} times`);
|
|
396
|
+
}
|
|
397
|
+
console.log();
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
} catch (error) {
|
|
401
|
+
console.error(chalk.red(`✗ Error: ${error}`));
|
|
402
|
+
process.exit(1);
|
|
403
|
+
}
|
|
111
404
|
});
|
|
112
405
|
|
|
113
|
-
//
|
|
406
|
+
// 添加供应商
|
|
114
407
|
program
|
|
115
|
-
.command('add <name> <baseUrl> [apiKey]')
|
|
116
|
-
.description('Add a new
|
|
117
|
-
.option('--
|
|
118
|
-
.action(async (name: string, baseUrl: string, apiKey?: string, options?: {
|
|
408
|
+
.command('add <id> <name> <baseUrl> [apiKey]')
|
|
409
|
+
.description('Add a new provider configuration')
|
|
410
|
+
.option('-d, --description <desc>', 'Provider description')
|
|
411
|
+
.action(async (id: string, name: string, baseUrl: string, apiKey?: string, options?: { description?: string }) => {
|
|
119
412
|
try {
|
|
413
|
+
await providerManager.init();
|
|
414
|
+
|
|
120
415
|
if (!apiKey) {
|
|
121
416
|
const answer = await inquirer.prompt([
|
|
122
417
|
{
|
|
@@ -129,36 +424,43 @@ program
|
|
|
129
424
|
apiKey = answer.apiKey;
|
|
130
425
|
}
|
|
131
426
|
|
|
132
|
-
const addOptions:
|
|
427
|
+
const addOptions: AddProviderOptions = {
|
|
428
|
+
id,
|
|
133
429
|
name,
|
|
430
|
+
description: options?.description,
|
|
134
431
|
baseUrl,
|
|
135
|
-
apiKey: apiKey
|
|
136
|
-
autoWriteShell: options?.autoWrite
|
|
432
|
+
apiKey: apiKey!
|
|
137
433
|
};
|
|
138
434
|
|
|
139
|
-
const
|
|
140
|
-
console.log(chalk.green(`✓ Added environment group "${name}"`));
|
|
141
|
-
console.log(` Base URL: ${env.baseUrl}`);
|
|
142
|
-
console.log(` Created: ${new Date(env.createdAt).toLocaleString()}`);
|
|
435
|
+
const result = await providerManager.addProvider(addOptions);
|
|
143
436
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (!currentEnv || currentEnv.name !== name) {
|
|
147
|
-
const useAnswer = await inquirer.prompt([
|
|
148
|
-
{
|
|
149
|
-
type: 'confirm',
|
|
150
|
-
name: 'useCurrent',
|
|
151
|
-
message: `Set "${name}" as current environment?`,
|
|
152
|
-
default: true
|
|
153
|
-
}
|
|
154
|
-
]);
|
|
437
|
+
if (result.success) {
|
|
438
|
+
console.log(chalk.green(`✓ ${result.message}`));
|
|
155
439
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
440
|
+
// 询问是否设为当前供应商
|
|
441
|
+
const currentProvider = await providerManager.getCurrentProvider();
|
|
442
|
+
if (!currentProvider || currentProvider.id !== id) {
|
|
443
|
+
const useAnswer = await inquirer.prompt([
|
|
444
|
+
{
|
|
445
|
+
type: 'confirm',
|
|
446
|
+
name: 'useCurrent',
|
|
447
|
+
message: `Set "${name}" as current provider?`,
|
|
448
|
+
default: true
|
|
449
|
+
}
|
|
450
|
+
]);
|
|
451
|
+
|
|
452
|
+
if (useAnswer.useCurrent) {
|
|
453
|
+
const useResult = await providerManager.useProvider(id);
|
|
454
|
+
if (useResult.success) {
|
|
455
|
+
console.log(chalk.green(`✓ ${useResult.message}`));
|
|
456
|
+
} else {
|
|
457
|
+
console.error(chalk.red(`✗ ${useResult.message}`));
|
|
458
|
+
}
|
|
459
|
+
}
|
|
161
460
|
}
|
|
461
|
+
} else {
|
|
462
|
+
console.error(chalk.red(`✗ ${result.message}`));
|
|
463
|
+
process.exit(1);
|
|
162
464
|
}
|
|
163
465
|
|
|
164
466
|
} catch (error) {
|
|
@@ -167,16 +469,41 @@ program
|
|
|
167
469
|
}
|
|
168
470
|
});
|
|
169
471
|
|
|
170
|
-
//
|
|
472
|
+
// 使用供应商
|
|
171
473
|
program
|
|
172
|
-
.command('
|
|
173
|
-
.
|
|
174
|
-
.
|
|
175
|
-
.action(async (name: string) => {
|
|
474
|
+
.command('use <id>')
|
|
475
|
+
.description('Switch to a provider configuration')
|
|
476
|
+
.action(async (id: string) => {
|
|
176
477
|
try {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
478
|
+
await providerManager.init();
|
|
479
|
+
const result = await providerManager.useProvider(id);
|
|
480
|
+
|
|
481
|
+
if (result.success) {
|
|
482
|
+
console.log(chalk.green(`✓ ${result.message}`));
|
|
483
|
+
console.log(chalk.cyan('Claude Code configuration has been updated successfully!'));
|
|
484
|
+
} else {
|
|
485
|
+
console.error(chalk.red(`✗ ${result.message}`));
|
|
486
|
+
process.exit(1);
|
|
487
|
+
}
|
|
488
|
+
} catch (error) {
|
|
489
|
+
console.error(chalk.red(`✗ Error: ${error}`));
|
|
490
|
+
process.exit(1);
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
// 删除供应商
|
|
495
|
+
program
|
|
496
|
+
.command('rm <id>')
|
|
497
|
+
.alias('remove')
|
|
498
|
+
.description('Remove a provider configuration')
|
|
499
|
+
.action(async (id: string) => {
|
|
500
|
+
try {
|
|
501
|
+
await providerManager.init();
|
|
502
|
+
const providers = await providerManager.listProviders();
|
|
503
|
+
const provider = providers.find(p => p.id === id);
|
|
504
|
+
|
|
505
|
+
if (!provider) {
|
|
506
|
+
console.error(chalk.red(`✗ Provider '${id}' not found`));
|
|
180
507
|
process.exit(1);
|
|
181
508
|
}
|
|
182
509
|
|
|
@@ -184,14 +511,19 @@ program
|
|
|
184
511
|
{
|
|
185
512
|
type: 'confirm',
|
|
186
513
|
name: 'confirm',
|
|
187
|
-
message: `Are you sure you want to remove
|
|
514
|
+
message: `Are you sure you want to remove provider "${provider.name}" (${id})?`,
|
|
188
515
|
default: false
|
|
189
516
|
}
|
|
190
517
|
]);
|
|
191
518
|
|
|
192
519
|
if (answer.confirm) {
|
|
193
|
-
await
|
|
194
|
-
|
|
520
|
+
const result = await providerManager.removeProvider(id);
|
|
521
|
+
|
|
522
|
+
if (result.success) {
|
|
523
|
+
console.log(chalk.green(`✓ ${result.message}`));
|
|
524
|
+
} else {
|
|
525
|
+
console.error(chalk.red(`✗ ${result.message}`));
|
|
526
|
+
}
|
|
195
527
|
} else {
|
|
196
528
|
console.log(chalk.yellow('Operation cancelled'));
|
|
197
529
|
}
|
|
@@ -201,124 +533,18 @@ program
|
|
|
201
533
|
}
|
|
202
534
|
});
|
|
203
535
|
|
|
204
|
-
// 使用环境
|
|
205
|
-
program
|
|
206
|
-
.command('use <name>')
|
|
207
|
-
.description('Switch to an environment group')
|
|
208
|
-
.option('--no-auto-write', 'Do not automatically write to shell config')
|
|
209
|
-
.option('--auto-source', 'Automatically source shell config after writing (risky)')
|
|
210
|
-
.action(async (name: string, options?: { autoWrite: boolean; autoSource: boolean }) => {
|
|
211
|
-
try {
|
|
212
|
-
await performUseEnvironment(name, {
|
|
213
|
-
autoWrite: options?.autoWrite,
|
|
214
|
-
autoSource: options?.autoSource
|
|
215
|
-
});
|
|
216
|
-
} catch (error) {
|
|
217
|
-
console.error(chalk.red(`✗ Error: ${error}`));
|
|
218
|
-
process.exit(1);
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
// 显示当前环境
|
|
223
|
-
program
|
|
224
|
-
.command('current')
|
|
225
|
-
.description('Show current environment group')
|
|
226
|
-
.action(() => {
|
|
227
|
-
const currentEnv = envManager.getCurrentEnvironment();
|
|
228
|
-
|
|
229
|
-
if (!currentEnv) {
|
|
230
|
-
console.log(chalk.yellow('No environment is currently active.'));
|
|
231
|
-
console.log('Use "ccman use <name>" to activate an environment.');
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
console.log();
|
|
236
|
-
console.log(chalk.green(`Current environment: ${currentEnv.name}`));
|
|
237
|
-
console.log(`Base URL: ${currentEnv.baseUrl}`);
|
|
238
|
-
console.log(`API Key: ${'*'.repeat(Math.min(currentEnv.apiKey.length, 20))}`);
|
|
239
|
-
console.log(`Created: ${new Date(currentEnv.createdAt).toLocaleString()}`);
|
|
240
|
-
|
|
241
|
-
if (currentEnv.lastUsed) {
|
|
242
|
-
console.log(`Last used: ${new Date(currentEnv.lastUsed).toLocaleString()}`);
|
|
243
|
-
}
|
|
244
|
-
console.log();
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
// 生成环境变量脚本
|
|
248
|
-
program
|
|
249
|
-
.command('env')
|
|
250
|
-
.description('Generate shell script to set environment variables')
|
|
251
|
-
.action(() => {
|
|
252
|
-
try {
|
|
253
|
-
const script = envManager.generateEnvScript();
|
|
254
|
-
console.log(script);
|
|
255
|
-
} catch (error) {
|
|
256
|
-
console.error(chalk.red(`✗ Error: ${error}`));
|
|
257
|
-
process.exit(1);
|
|
258
|
-
}
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
// 测试环境
|
|
262
|
-
program
|
|
263
|
-
.command('test [name]')
|
|
264
|
-
.description('Test environment configuration (defaults to current)')
|
|
265
|
-
.action(async (name?: string) => {
|
|
266
|
-
const result = await envManager.testEnvironment(name);
|
|
267
|
-
|
|
268
|
-
if (result.success) {
|
|
269
|
-
console.log(chalk.green(`✓ ${result.message}`));
|
|
270
|
-
} else {
|
|
271
|
-
console.error(chalk.red(`✗ ${result.message}`));
|
|
272
|
-
if (result.error) {
|
|
273
|
-
console.error(chalk.gray(`Details: ${result.error}`));
|
|
274
|
-
}
|
|
275
|
-
process.exit(1);
|
|
276
|
-
}
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
// 显示统计信息
|
|
280
|
-
program
|
|
281
|
-
.command('status')
|
|
282
|
-
.description('Show CCM status and statistics')
|
|
283
|
-
.action(() => {
|
|
284
|
-
const stats = envManager.getStats();
|
|
285
|
-
const environments = envManager.listEnvironments();
|
|
286
|
-
|
|
287
|
-
console.log();
|
|
288
|
-
console.log(chalk.blue('CCM Status:'));
|
|
289
|
-
console.log(`Total environments: ${stats.totalEnvironments}`);
|
|
290
|
-
console.log(`Current environment: ${stats.currentEnvironment || 'None'}`);
|
|
291
|
-
console.log(`Shell integration: ${stats.hasShellIntegration ? 'Enabled' : 'Disabled'}`);
|
|
292
|
-
|
|
293
|
-
if (environments.length > 0) {
|
|
294
|
-
console.log();
|
|
295
|
-
console.log(chalk.blue('Recent environments:'));
|
|
296
|
-
const sortedEnvs = environments
|
|
297
|
-
.filter(env => env.lastUsed)
|
|
298
|
-
.sort((a, b) => new Date(b.lastUsed!).getTime() - new Date(a.lastUsed!).getTime())
|
|
299
|
-
.slice(0, 3);
|
|
300
|
-
|
|
301
|
-
sortedEnvs.forEach(env => {
|
|
302
|
-
const lastUsed = new Date(env.lastUsed!).toLocaleDateString();
|
|
303
|
-
console.log(` ${env.name} (${lastUsed})`);
|
|
304
|
-
});
|
|
305
|
-
}
|
|
306
|
-
console.log();
|
|
307
|
-
});
|
|
308
|
-
|
|
309
536
|
// 清除所有配置
|
|
310
537
|
program
|
|
311
538
|
.command('clear')
|
|
312
|
-
.alias('
|
|
313
|
-
.description('Clear all
|
|
539
|
+
.alias('reset')
|
|
540
|
+
.description('Clear all provider configurations (DESTRUCTIVE)')
|
|
314
541
|
.action(async () => {
|
|
315
542
|
try {
|
|
316
|
-
// 确认操作
|
|
317
543
|
const confirmAnswer = await inquirer.prompt([
|
|
318
544
|
{
|
|
319
545
|
type: 'confirm',
|
|
320
546
|
name: 'confirmed',
|
|
321
|
-
message: chalk.red('⚠️ This will remove ALL
|
|
547
|
+
message: chalk.red('⚠️ This will remove ALL provider configurations. Are you sure?'),
|
|
322
548
|
default: false
|
|
323
549
|
}
|
|
324
550
|
]);
|
|
@@ -328,183 +554,25 @@ program
|
|
|
328
554
|
return;
|
|
329
555
|
}
|
|
330
556
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
const result = await envManager.clearAll();
|
|
557
|
+
await providerManager.init();
|
|
558
|
+
const result = await providerManager.clearAll();
|
|
334
559
|
|
|
335
|
-
// 显示结果
|
|
336
|
-
console.log();
|
|
337
560
|
if (result.success) {
|
|
338
561
|
console.log(chalk.green(`✓ ${result.message}`));
|
|
562
|
+
console.log(chalk.cyan('CCM has been reset to initial state.'));
|
|
563
|
+
console.log(chalk.cyan('You can start fresh with: ccman'));
|
|
339
564
|
} else {
|
|
340
|
-
console.
|
|
565
|
+
console.error(chalk.red(`✗ ${result.message}`));
|
|
341
566
|
}
|
|
342
567
|
|
|
343
|
-
// 显示详细信息
|
|
344
|
-
if (result.details.length > 0) {
|
|
345
|
-
console.log();
|
|
346
|
-
result.details.forEach(detail => {
|
|
347
|
-
if (detail.startsWith('✓')) {
|
|
348
|
-
console.log(chalk.green(detail));
|
|
349
|
-
} else if (detail.startsWith('⚠')) {
|
|
350
|
-
console.log(chalk.yellow(detail));
|
|
351
|
-
} else if (detail.startsWith('✗')) {
|
|
352
|
-
console.log(chalk.red(detail));
|
|
353
|
-
} else {
|
|
354
|
-
console.log(detail);
|
|
355
|
-
}
|
|
356
|
-
});
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
console.log();
|
|
360
|
-
console.log(chalk.cyan('CCM has been reset to initial state.'));
|
|
361
|
-
console.log(chalk.cyan('You can start fresh with: ccman config'));
|
|
362
|
-
|
|
363
568
|
} catch (error) {
|
|
364
569
|
console.error(chalk.red(`✗ Error: ${error}`));
|
|
365
570
|
process.exit(1);
|
|
366
571
|
}
|
|
367
572
|
});
|
|
368
573
|
|
|
369
|
-
//
|
|
370
|
-
program
|
|
371
|
-
.command('config')
|
|
372
|
-
.description('Interactive configuration')
|
|
373
|
-
.action(async () => {
|
|
374
|
-
const environments = envManager.listEnvironments();
|
|
375
|
-
|
|
376
|
-
if (environments.length === 0) {
|
|
377
|
-
console.log(chalk.yellow('No environments found. Let\'s create your first one.'));
|
|
378
|
-
|
|
379
|
-
const answers = await inquirer.prompt([
|
|
380
|
-
{ type: 'input', name: 'name', message: 'Environment name:', default: 'default' },
|
|
381
|
-
{ type: 'input', name: 'baseUrl', message: 'Base URL:', default: 'https://api.anthropic.com' },
|
|
382
|
-
{ type: 'password', name: 'apiKey', message: 'API Key:', mask: '*' },
|
|
383
|
-
{ type: 'confirm', name: 'autoWrite', message: 'Automatically write to shell config?', default: true }
|
|
384
|
-
]);
|
|
385
|
-
|
|
386
|
-
try {
|
|
387
|
-
await envManager.addEnvironment({
|
|
388
|
-
name: answers.name,
|
|
389
|
-
baseUrl: answers.baseUrl,
|
|
390
|
-
apiKey: answers.apiKey,
|
|
391
|
-
autoWriteShell: answers.autoWrite
|
|
392
|
-
});
|
|
393
|
-
console.log(chalk.green(`✓ Created environment "${answers.name}"`));
|
|
394
|
-
} catch (error) {
|
|
395
|
-
console.error(chalk.red(`✗ Error: ${error}`));
|
|
396
|
-
}
|
|
397
|
-
return;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
const choices = environments.map(env => ({
|
|
401
|
-
name: `${env.name} (${env.baseUrl})${env.isCurrent ? ' [current]' : ''}`,
|
|
402
|
-
value: env.name
|
|
403
|
-
}));
|
|
404
|
-
|
|
405
|
-
const action = await inquirer.prompt([
|
|
406
|
-
{
|
|
407
|
-
type: 'list',
|
|
408
|
-
name: 'action',
|
|
409
|
-
message: 'What would you like to do?',
|
|
410
|
-
choices: [
|
|
411
|
-
{ name: 'Switch environment', value: 'switch' },
|
|
412
|
-
{ name: 'Add new environment', value: 'add' },
|
|
413
|
-
{ name: 'Edit environment', value: 'edit' },
|
|
414
|
-
{ name: 'Remove environment', value: 'remove' },
|
|
415
|
-
{ name: 'Show current status', value: 'status' }
|
|
416
|
-
]
|
|
417
|
-
}
|
|
418
|
-
]);
|
|
419
|
-
|
|
420
|
-
switch (action.action) {
|
|
421
|
-
case 'switch':
|
|
422
|
-
const switchAnswer = await inquirer.prompt([
|
|
423
|
-
{
|
|
424
|
-
type: 'list',
|
|
425
|
-
name: 'name',
|
|
426
|
-
message: 'Select environment:',
|
|
427
|
-
choices
|
|
428
|
-
}
|
|
429
|
-
]);
|
|
430
|
-
try {
|
|
431
|
-
await performUseEnvironment(switchAnswer.name);
|
|
432
|
-
} catch (error) {
|
|
433
|
-
console.error(chalk.red(`✗ Error: ${error}`));
|
|
434
|
-
}
|
|
435
|
-
break;
|
|
436
|
-
|
|
437
|
-
case 'add':
|
|
438
|
-
const addAnswers = await inquirer.prompt([
|
|
439
|
-
{ type: 'input', name: 'name', message: 'Environment name:' },
|
|
440
|
-
{ type: 'input', name: 'baseUrl', message: 'Base URL:' },
|
|
441
|
-
{ type: 'password', name: 'apiKey', message: 'API Key:', mask: '*' }
|
|
442
|
-
]);
|
|
443
|
-
try {
|
|
444
|
-
await envManager.addEnvironment(addAnswers);
|
|
445
|
-
console.log(chalk.green(`✓ Added environment "${addAnswers.name}"`));
|
|
446
|
-
} catch (error) {
|
|
447
|
-
console.error(chalk.red(`✗ Error: ${error}`));
|
|
448
|
-
}
|
|
449
|
-
break;
|
|
450
|
-
|
|
451
|
-
case 'edit':
|
|
452
|
-
const editEnvAnswer = await inquirer.prompt([
|
|
453
|
-
{
|
|
454
|
-
type: 'list',
|
|
455
|
-
name: 'name',
|
|
456
|
-
message: 'Select environment to edit:',
|
|
457
|
-
choices
|
|
458
|
-
}
|
|
459
|
-
]);
|
|
460
|
-
|
|
461
|
-
const currentConfig = envManager.getEnvironment(editEnvAnswer.name);
|
|
462
|
-
if (currentConfig) {
|
|
463
|
-
const editAnswers = await inquirer.prompt([
|
|
464
|
-
{ type: 'input', name: 'baseUrl', message: 'Base URL:', default: currentConfig.baseUrl },
|
|
465
|
-
{ type: 'password', name: 'apiKey', message: 'API Key:', mask: '*', default: currentConfig.apiKey }
|
|
466
|
-
]);
|
|
467
|
-
|
|
468
|
-
try {
|
|
469
|
-
await envManager.updateEnvironment(editEnvAnswer.name, {
|
|
470
|
-
baseUrl: editAnswers.baseUrl,
|
|
471
|
-
apiKey: editAnswers.apiKey
|
|
472
|
-
});
|
|
473
|
-
console.log(chalk.green(`✓ Updated environment "${editEnvAnswer.name}"`));
|
|
474
|
-
} catch (error) {
|
|
475
|
-
console.error(chalk.red(`✗ Error: ${error}`));
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
break;
|
|
479
|
-
|
|
480
|
-
case 'status':
|
|
481
|
-
{
|
|
482
|
-
const stats = envManager.getStats();
|
|
483
|
-
const environments = envManager.listEnvironments();
|
|
484
|
-
|
|
485
|
-
console.log();
|
|
486
|
-
console.log(chalk.blue('CCM Status:'));
|
|
487
|
-
console.log(`Total environments: ${stats.totalEnvironments}`);
|
|
488
|
-
console.log(`Current environment: ${stats.currentEnvironment || 'None'}`);
|
|
489
|
-
console.log(`Shell integration: ${stats.hasShellIntegration ? 'Enabled' : 'Disabled'}`);
|
|
490
|
-
|
|
491
|
-
if (environments.length > 0) {
|
|
492
|
-
console.log();
|
|
493
|
-
console.log(chalk.blue('Recent environments:'));
|
|
494
|
-
environments
|
|
495
|
-
.sort((a, b) => new Date(b.lastUsed || b.createdAt).getTime() - new Date(a.lastUsed || a.createdAt).getTime())
|
|
496
|
-
.slice(0, 3)
|
|
497
|
-
.forEach(env => {
|
|
498
|
-
const marker = env.isCurrent ? chalk.green('* ') : ' ';
|
|
499
|
-
const name = env.isCurrent ? chalk.green(env.name) : env.name;
|
|
500
|
-
console.log(`${marker}${name.padEnd(15)} ${env.baseUrl}`);
|
|
501
|
-
});
|
|
502
|
-
}
|
|
503
|
-
console.log();
|
|
504
|
-
}
|
|
505
|
-
break;
|
|
506
|
-
}
|
|
507
|
-
});
|
|
574
|
+
// 添加语言管理命令
|
|
575
|
+
program.addCommand(createLanguageCommands());
|
|
508
576
|
|
|
509
577
|
// 解析命令行参数
|
|
510
|
-
program.parse();
|
|
578
|
+
program.parse(process.argv);
|