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