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/i18n/messages.ts
DELETED
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
export interface MessageBundle {
|
|
2
|
-
// 通用消息
|
|
3
|
-
welcome: string;
|
|
4
|
-
error: string;
|
|
5
|
-
success: string;
|
|
6
|
-
cancelled: string;
|
|
7
|
-
|
|
8
|
-
// 首次运行语言选择
|
|
9
|
-
firstRunWelcome: string;
|
|
10
|
-
firstRunDescription: string;
|
|
11
|
-
chooseLanguage: string;
|
|
12
|
-
languageOptions: {
|
|
13
|
-
chinese: string;
|
|
14
|
-
english: string;
|
|
15
|
-
autoDetect: string;
|
|
16
|
-
};
|
|
17
|
-
languageSetSuccess: string;
|
|
18
|
-
languageChangeHint: string;
|
|
19
|
-
|
|
20
|
-
// 主菜单
|
|
21
|
-
mainMenuTitle: string;
|
|
22
|
-
mainMenuOptions: {
|
|
23
|
-
switchProvider: string;
|
|
24
|
-
addProvider: string;
|
|
25
|
-
updateProvider: string;
|
|
26
|
-
removeProvider: string;
|
|
27
|
-
showStatus: string;
|
|
28
|
-
exit: string;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
// 供应商操作
|
|
32
|
-
noProvidersFound: string;
|
|
33
|
-
createFirstProvider: string;
|
|
34
|
-
providerAdded: string;
|
|
35
|
-
providerSwitched: string;
|
|
36
|
-
providerUpdated: string;
|
|
37
|
-
providerRemoved: string;
|
|
38
|
-
operationCancelled: string;
|
|
39
|
-
|
|
40
|
-
// 表单字段
|
|
41
|
-
forms: {
|
|
42
|
-
providerId: string;
|
|
43
|
-
providerName: string;
|
|
44
|
-
description: string;
|
|
45
|
-
baseUrl: string;
|
|
46
|
-
apiKey: string;
|
|
47
|
-
selectProvider: string;
|
|
48
|
-
confirmRemove: string;
|
|
49
|
-
continueOperation: string;
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
// 状态信息
|
|
53
|
-
status: {
|
|
54
|
-
title: string;
|
|
55
|
-
totalProviders: string;
|
|
56
|
-
currentProvider: string;
|
|
57
|
-
claudeConfig: string;
|
|
58
|
-
ccmConfig: string;
|
|
59
|
-
recentProviders: string;
|
|
60
|
-
lastUsed: string;
|
|
61
|
-
usage: string;
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
// 语言管理
|
|
65
|
-
language: {
|
|
66
|
-
current: string;
|
|
67
|
-
switchSuccess: string;
|
|
68
|
-
resetConfirm: string;
|
|
69
|
-
resetSuccess: string;
|
|
70
|
-
invalidLanguage: string;
|
|
71
|
-
availableCommands: string;
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
// 退出消息
|
|
75
|
-
exitMessage: string;
|
|
76
|
-
interruptMessage: string;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export const chineseMessages: MessageBundle = {
|
|
80
|
-
// 通用消息
|
|
81
|
-
welcome: '欢迎使用 CCM!',
|
|
82
|
-
error: '错误',
|
|
83
|
-
success: '成功',
|
|
84
|
-
cancelled: '操作已取消',
|
|
85
|
-
|
|
86
|
-
// 首次运行语言选择
|
|
87
|
-
firstRunWelcome: '🌍 欢迎使用 CCM!/ Welcome to CCM!',
|
|
88
|
-
firstRunDescription: '这是您首次运行 CCM。\nThis is your first time running CCM.',
|
|
89
|
-
chooseLanguage: '请选择您偏好的语言:\nPlease choose your preferred language:',
|
|
90
|
-
languageOptions: {
|
|
91
|
-
chinese: '🇨🇳 中文 (Chinese)',
|
|
92
|
-
english: '🇺🇸 English',
|
|
93
|
-
autoDetect: '🌐 自动检测 (Auto-detect based on system)'
|
|
94
|
-
},
|
|
95
|
-
languageSetSuccess: '语言已设置为中文',
|
|
96
|
-
languageChangeHint: '您可以稍后使用以下命令更改:ccman lang set <zh|en|auto>',
|
|
97
|
-
|
|
98
|
-
// 主菜单
|
|
99
|
-
mainMenuTitle: '您想要执行什么操作?',
|
|
100
|
-
mainMenuOptions: {
|
|
101
|
-
switchProvider: '切换供应商',
|
|
102
|
-
addProvider: '添加新供应商',
|
|
103
|
-
updateProvider: '更新供应商',
|
|
104
|
-
removeProvider: '删除供应商',
|
|
105
|
-
showStatus: '显示详细状态',
|
|
106
|
-
exit: '退出'
|
|
107
|
-
},
|
|
108
|
-
|
|
109
|
-
// 供应商操作
|
|
110
|
-
noProvidersFound: '未找到供应商配置。让我们创建您的第一个供应商。',
|
|
111
|
-
createFirstProvider: '创建您的第一个供应商',
|
|
112
|
-
providerAdded: '供应商添加成功',
|
|
113
|
-
providerSwitched: '供应商切换成功',
|
|
114
|
-
providerUpdated: '供应商更新成功',
|
|
115
|
-
providerRemoved: '供应商删除成功',
|
|
116
|
-
operationCancelled: '操作已取消',
|
|
117
|
-
|
|
118
|
-
// 表单字段
|
|
119
|
-
forms: {
|
|
120
|
-
providerId: '供应商ID(唯一标识符):',
|
|
121
|
-
providerName: '供应商名称:',
|
|
122
|
-
description: '描述:',
|
|
123
|
-
baseUrl: '基础URL:',
|
|
124
|
-
apiKey: 'API密钥:',
|
|
125
|
-
selectProvider: '选择供应商:',
|
|
126
|
-
confirmRemove: '确认删除此供应商吗?',
|
|
127
|
-
continueOperation: '是否要执行其他操作?'
|
|
128
|
-
},
|
|
129
|
-
|
|
130
|
-
// 状态信息
|
|
131
|
-
status: {
|
|
132
|
-
title: 'CCM 状态:',
|
|
133
|
-
totalProviders: '总供应商数:',
|
|
134
|
-
currentProvider: '当前供应商:',
|
|
135
|
-
claudeConfig: 'Claude配置:',
|
|
136
|
-
ccmConfig: 'CCM配置:',
|
|
137
|
-
recentProviders: '最近使用的供应商:',
|
|
138
|
-
lastUsed: '最后使用',
|
|
139
|
-
usage: '使用次数'
|
|
140
|
-
},
|
|
141
|
-
|
|
142
|
-
// 语言管理
|
|
143
|
-
language: {
|
|
144
|
-
current: '当前语言:',
|
|
145
|
-
switchSuccess: '语言切换成功',
|
|
146
|
-
resetConfirm: '这将重置语言设置并在下次运行时显示欢迎界面。继续吗?',
|
|
147
|
-
resetSuccess: '语言设置已重置。再次运行 ccman 以选择语言。',
|
|
148
|
-
invalidLanguage: '无效的语言选项。可用选项:zh, en, auto',
|
|
149
|
-
availableCommands: '您可以使用以下命令更改:ccman lang set <zh|en|auto>'
|
|
150
|
-
},
|
|
151
|
-
|
|
152
|
-
// 退出消息
|
|
153
|
-
exitMessage: '感谢使用 CCM。再见!',
|
|
154
|
-
interruptMessage: '\n\n用户取消操作。再见!'
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
export const englishMessages: MessageBundle = {
|
|
158
|
-
// 通用消息
|
|
159
|
-
welcome: 'Welcome to CCM!',
|
|
160
|
-
error: 'Error',
|
|
161
|
-
success: 'Success',
|
|
162
|
-
cancelled: 'Operation cancelled',
|
|
163
|
-
|
|
164
|
-
// 首次运行语言选择
|
|
165
|
-
firstRunWelcome: '🌍 Welcome to CCM! / 欢迎使用 CCM!',
|
|
166
|
-
firstRunDescription: 'This is your first time running CCM.\n这是您首次运行 CCM。',
|
|
167
|
-
chooseLanguage: 'Please choose your preferred language:\n请选择您偏好的语言:',
|
|
168
|
-
languageOptions: {
|
|
169
|
-
chinese: '🇨🇳 中文 (Chinese)',
|
|
170
|
-
english: '🇺🇸 English',
|
|
171
|
-
autoDetect: '🌐 Auto-detect based on system (基于系统自动检测)'
|
|
172
|
-
},
|
|
173
|
-
languageSetSuccess: 'Language set to English',
|
|
174
|
-
languageChangeHint: 'You can change this later with: ccman lang set <zh|en|auto>',
|
|
175
|
-
|
|
176
|
-
// 主菜单
|
|
177
|
-
mainMenuTitle: 'What would you like to do?',
|
|
178
|
-
mainMenuOptions: {
|
|
179
|
-
switchProvider: 'Switch provider',
|
|
180
|
-
addProvider: 'Add new provider',
|
|
181
|
-
updateProvider: 'Update provider',
|
|
182
|
-
removeProvider: 'Remove provider',
|
|
183
|
-
showStatus: 'Show detailed status',
|
|
184
|
-
exit: 'Exit'
|
|
185
|
-
},
|
|
186
|
-
|
|
187
|
-
// 供应商操作
|
|
188
|
-
noProvidersFound: 'No providers found. Let\'s create your first one.',
|
|
189
|
-
createFirstProvider: 'Create your first provider',
|
|
190
|
-
providerAdded: 'Provider added successfully',
|
|
191
|
-
providerSwitched: 'Provider switched successfully',
|
|
192
|
-
providerUpdated: 'Provider updated successfully',
|
|
193
|
-
providerRemoved: 'Provider removed successfully',
|
|
194
|
-
operationCancelled: 'Operation cancelled',
|
|
195
|
-
|
|
196
|
-
// 表单字段
|
|
197
|
-
forms: {
|
|
198
|
-
providerId: 'Provider ID (unique identifier):',
|
|
199
|
-
providerName: 'Provider name:',
|
|
200
|
-
description: 'Description:',
|
|
201
|
-
baseUrl: 'Base URL:',
|
|
202
|
-
apiKey: 'API Key:',
|
|
203
|
-
selectProvider: 'Select provider:',
|
|
204
|
-
confirmRemove: 'Are you sure you want to remove this provider?',
|
|
205
|
-
continueOperation: 'Would you like to perform another operation?'
|
|
206
|
-
},
|
|
207
|
-
|
|
208
|
-
// 状态信息
|
|
209
|
-
status: {
|
|
210
|
-
title: 'CCM Status:',
|
|
211
|
-
totalProviders: 'Total providers:',
|
|
212
|
-
currentProvider: 'Current provider:',
|
|
213
|
-
claudeConfig: 'Claude config:',
|
|
214
|
-
ccmConfig: 'CCM config:',
|
|
215
|
-
recentProviders: 'Recent providers:',
|
|
216
|
-
lastUsed: 'Last used',
|
|
217
|
-
usage: 'uses'
|
|
218
|
-
},
|
|
219
|
-
|
|
220
|
-
// 语言管理
|
|
221
|
-
language: {
|
|
222
|
-
current: 'Current language:',
|
|
223
|
-
switchSuccess: 'Language switched successfully',
|
|
224
|
-
resetConfirm: 'This will reset language setting and show the welcome screen on next run. Continue?',
|
|
225
|
-
resetSuccess: 'Language setting reset. Run ccman again to choose language.',
|
|
226
|
-
invalidLanguage: 'Invalid language option. Available: zh, en, auto',
|
|
227
|
-
availableCommands: 'You can change with: ccman lang set <zh|en|auto>'
|
|
228
|
-
},
|
|
229
|
-
|
|
230
|
-
// 退出消息
|
|
231
|
-
exitMessage: 'Thank you for using CCM. Goodbye!',
|
|
232
|
-
interruptMessage: '\n\nOperation cancelled by user. Goodbye!'
|
|
233
|
-
};
|
package/src/index.ts
DELETED
|
@@ -1,412 +0,0 @@
|
|
|
1
|
-
import { CCMConfigManager } from '../core/CCMConfigManager';
|
|
2
|
-
import { ClaudeConfigManager } from '../core/ClaudeConfigManager';
|
|
3
|
-
import { envConfig } from '../utils/env-config';
|
|
4
|
-
import {
|
|
5
|
-
AddProviderOptions,
|
|
6
|
-
ProviderListItem,
|
|
7
|
-
ProviderConfig,
|
|
8
|
-
OperationResult
|
|
9
|
-
} from '../types';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* 供应商管理器
|
|
13
|
-
* 核心业务逻辑:管理多个供应商配置并切换Claude配置
|
|
14
|
-
*/
|
|
15
|
-
export class ProviderManager {
|
|
16
|
-
private ccmConfig: CCMConfigManager;
|
|
17
|
-
private claudeConfig: ClaudeConfigManager;
|
|
18
|
-
|
|
19
|
-
constructor() {
|
|
20
|
-
this.ccmConfig = new CCMConfigManager();
|
|
21
|
-
// ClaudeConfigManager 将在 init() 中根据 CCM 配置初始化
|
|
22
|
-
this.claudeConfig = new ClaudeConfigManager();
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* 初始化
|
|
27
|
-
*/
|
|
28
|
-
async init(): Promise<void> {
|
|
29
|
-
await this.ccmConfig.init();
|
|
30
|
-
|
|
31
|
-
// 获取 CCM 配置中的 Claude 配置路径
|
|
32
|
-
const config = await this.ccmConfig.readConfig();
|
|
33
|
-
this.claudeConfig = new ClaudeConfigManager(config.claudeConfigPath);
|
|
34
|
-
|
|
35
|
-
await this.claudeConfig.ensureClaudeConfigDir();
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* 生成供应商唯一ID
|
|
40
|
-
* 基于名称生成,确保唯一性
|
|
41
|
-
*/
|
|
42
|
-
private async generateProviderId(name: string): Promise<string> {
|
|
43
|
-
// 基础ID:转换为小写,替换空格和特殊字符
|
|
44
|
-
const baseId = name
|
|
45
|
-
.toLowerCase()
|
|
46
|
-
.replace(/[^a-z0-9]/g, '-') // 替换非字母数字字符为连字符
|
|
47
|
-
.replace(/-+/g, '-') // 合并多个连字符
|
|
48
|
-
.replace(/^-|-$/g, ''); // 移除首尾连字符
|
|
49
|
-
|
|
50
|
-
// 检查ID是否已存在
|
|
51
|
-
const config = await this.ccmConfig.readConfig();
|
|
52
|
-
let finalId = baseId;
|
|
53
|
-
let counter = 1;
|
|
54
|
-
|
|
55
|
-
while (config.providers[finalId]) {
|
|
56
|
-
finalId = `${baseId}-${counter}`;
|
|
57
|
-
counter++;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return finalId;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* 添加新的供应商配置
|
|
65
|
-
*/
|
|
66
|
-
async addProvider(options: AddProviderOptions): Promise<OperationResult> {
|
|
67
|
-
try {
|
|
68
|
-
// 自动生成唯一ID
|
|
69
|
-
const providerId = await this.generateProviderId(options.name);
|
|
70
|
-
|
|
71
|
-
// 设置默认描述为供应商名称
|
|
72
|
-
const description = options.description || options.name;
|
|
73
|
-
|
|
74
|
-
// 创建供应商配置
|
|
75
|
-
const providerConfig: ProviderConfig = {
|
|
76
|
-
name: options.name,
|
|
77
|
-
description: description,
|
|
78
|
-
config: {
|
|
79
|
-
env: {
|
|
80
|
-
ANTHROPIC_AUTH_TOKEN: options.apiKey,
|
|
81
|
-
ANTHROPIC_BASE_URL: options.baseUrl,
|
|
82
|
-
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: 1,
|
|
83
|
-
CLAUDE_CODE_MAX_OUTPUT_TOKENS: 32000
|
|
84
|
-
},
|
|
85
|
-
permissions: {
|
|
86
|
-
allow: [],
|
|
87
|
-
deny: []
|
|
88
|
-
}
|
|
89
|
-
},
|
|
90
|
-
metadata: {
|
|
91
|
-
createdAt: new Date().toISOString(),
|
|
92
|
-
updatedAt: new Date().toISOString(),
|
|
93
|
-
usageCount: 0
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
// 保存供应商配置
|
|
98
|
-
await this.ccmConfig.writeProviderConfig(providerId, providerConfig);
|
|
99
|
-
|
|
100
|
-
// 更新主配置
|
|
101
|
-
const config = await this.ccmConfig.readConfig();
|
|
102
|
-
config.providers[providerId] = {
|
|
103
|
-
name: options.name,
|
|
104
|
-
configFile: `${providerId}.json`,
|
|
105
|
-
lastUsed: new Date().toISOString()
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
// 如果这是第一个供应商,设为当前并更新Claude配置
|
|
109
|
-
if (Object.keys(config.providers).length === 1) {
|
|
110
|
-
config.currentProvider = providerId;
|
|
111
|
-
|
|
112
|
-
// 更新Claude配置,首次可能需要备份
|
|
113
|
-
await this.claudeConfig.writeClaudeConfig(providerConfig.config);
|
|
114
|
-
|
|
115
|
-
// 增加使用次数
|
|
116
|
-
providerConfig.metadata.usageCount++;
|
|
117
|
-
await this.ccmConfig.writeProviderConfig(providerId, providerConfig);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
await this.ccmConfig.writeConfig(config);
|
|
121
|
-
|
|
122
|
-
return {
|
|
123
|
-
success: true,
|
|
124
|
-
message: `Successfully added provider '${options.name}' (ID: ${providerId})`,
|
|
125
|
-
data: { providerId } // 返回生成的ID
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
} catch (error) {
|
|
129
|
-
return {
|
|
130
|
-
success: false,
|
|
131
|
-
message: `Failed to add provider: ${error}`,
|
|
132
|
-
error: error instanceof Error ? error.message : String(error)
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* 删除供应商配置
|
|
139
|
-
*/
|
|
140
|
-
async removeProvider(providerId: string): Promise<OperationResult> {
|
|
141
|
-
try {
|
|
142
|
-
const config = await this.ccmConfig.readConfig();
|
|
143
|
-
|
|
144
|
-
if (!config.providers[providerId]) {
|
|
145
|
-
return {
|
|
146
|
-
success: false,
|
|
147
|
-
message: `Provider '${providerId}' not found`
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// 删除供应商配置文件
|
|
152
|
-
await this.ccmConfig.deleteProviderConfig(providerId);
|
|
153
|
-
|
|
154
|
-
// 从主配置中移除
|
|
155
|
-
delete config.providers[providerId];
|
|
156
|
-
|
|
157
|
-
// 如果删除的是当前供应商,重置当前供应商
|
|
158
|
-
if (config.currentProvider === providerId) {
|
|
159
|
-
const remainingProviders = Object.keys(config.providers);
|
|
160
|
-
config.currentProvider = remainingProviders.length > 0 ? remainingProviders[0] : '';
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
await this.ccmConfig.writeConfig(config);
|
|
164
|
-
|
|
165
|
-
return {
|
|
166
|
-
success: true,
|
|
167
|
-
message: `Successfully removed provider '${providerId}'`
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
} catch (error) {
|
|
171
|
-
return {
|
|
172
|
-
success: false,
|
|
173
|
-
message: `Failed to remove provider: ${error}`,
|
|
174
|
-
error: error instanceof Error ? error.message : String(error)
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* 切换到指定供应商
|
|
181
|
-
*/
|
|
182
|
-
async useProvider(providerId: string): Promise<OperationResult> {
|
|
183
|
-
try {
|
|
184
|
-
const config = await this.ccmConfig.readConfig();
|
|
185
|
-
|
|
186
|
-
if (!config.providers[providerId]) {
|
|
187
|
-
return {
|
|
188
|
-
success: false,
|
|
189
|
-
message: `Provider '${providerId}' not found`
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// 读取供应商配置
|
|
194
|
-
const providerConfig = await this.ccmConfig.readProviderConfig(providerId);
|
|
195
|
-
if (!providerConfig) {
|
|
196
|
-
return {
|
|
197
|
-
success: false,
|
|
198
|
-
message: `Provider config file for '${providerId}' not found`
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// 更新Claude配置(不需要备份,因为都是CCM管理的配置之间切换)
|
|
203
|
-
await this.claudeConfig.writeClaudeConfig(providerConfig.config, true);
|
|
204
|
-
|
|
205
|
-
// 更新CCM配置
|
|
206
|
-
config.currentProvider = providerId;
|
|
207
|
-
config.providers[providerId].lastUsed = new Date().toISOString();
|
|
208
|
-
await this.ccmConfig.writeConfig(config);
|
|
209
|
-
|
|
210
|
-
// 增加使用次数
|
|
211
|
-
providerConfig.metadata.usageCount++;
|
|
212
|
-
await this.ccmConfig.writeProviderConfig(providerId, providerConfig);
|
|
213
|
-
|
|
214
|
-
return {
|
|
215
|
-
success: true,
|
|
216
|
-
message: `Successfully switched to provider '${config.providers[providerId].name}'`
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
} catch (error) {
|
|
220
|
-
return {
|
|
221
|
-
success: false,
|
|
222
|
-
message: `Failed to switch provider: ${error}`,
|
|
223
|
-
error: error instanceof Error ? error.message : String(error)
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* 获取当前供应商
|
|
230
|
-
*/
|
|
231
|
-
async getCurrentProvider(): Promise<{ id: string; config: ProviderConfig } | null> {
|
|
232
|
-
try {
|
|
233
|
-
const config = await this.ccmConfig.readConfig();
|
|
234
|
-
|
|
235
|
-
if (!config.currentProvider) {
|
|
236
|
-
return null;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
const providerConfig = await this.ccmConfig.readProviderConfig(config.currentProvider);
|
|
240
|
-
if (!providerConfig) {
|
|
241
|
-
return null;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
return {
|
|
245
|
-
id: config.currentProvider,
|
|
246
|
-
config: providerConfig
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
} catch (error) {
|
|
250
|
-
return null;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* 列出所有供应商
|
|
256
|
-
*/
|
|
257
|
-
async listProviders(): Promise<ProviderListItem[]> {
|
|
258
|
-
try {
|
|
259
|
-
const config = await this.ccmConfig.readConfig();
|
|
260
|
-
const providers: ProviderListItem[] = [];
|
|
261
|
-
|
|
262
|
-
for (const [providerId, providerInfo] of Object.entries(config.providers)) {
|
|
263
|
-
const providerConfig = await this.ccmConfig.readProviderConfig(providerId);
|
|
264
|
-
|
|
265
|
-
if (providerConfig) {
|
|
266
|
-
const info = providerInfo as { name: string; configFile: string; lastUsed: string };
|
|
267
|
-
providers.push({
|
|
268
|
-
id: providerId,
|
|
269
|
-
name: providerConfig.name,
|
|
270
|
-
description: providerConfig.description,
|
|
271
|
-
baseUrl: providerConfig.config.env.ANTHROPIC_BASE_URL,
|
|
272
|
-
isCurrent: config.currentProvider === providerId,
|
|
273
|
-
lastUsed: info.lastUsed,
|
|
274
|
-
usageCount: providerConfig.metadata.usageCount
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
return providers.sort((a, b) => {
|
|
280
|
-
// 先按是否为当前排序,再按最后使用时间排序
|
|
281
|
-
if (a.isCurrent && !b.isCurrent) return -1;
|
|
282
|
-
if (!a.isCurrent && b.isCurrent) return 1;
|
|
283
|
-
|
|
284
|
-
const aTime = new Date(a.lastUsed || '').getTime();
|
|
285
|
-
const bTime = new Date(b.lastUsed || '').getTime();
|
|
286
|
-
return bTime - aTime;
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
} catch (error) {
|
|
290
|
-
return [];
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* 更新供应商配置
|
|
296
|
-
*/
|
|
297
|
-
async updateProvider(providerId: string, updates: Partial<AddProviderOptions>): Promise<OperationResult> {
|
|
298
|
-
try {
|
|
299
|
-
const providerConfig = await this.ccmConfig.readProviderConfig(providerId);
|
|
300
|
-
if (!providerConfig) {
|
|
301
|
-
return {
|
|
302
|
-
success: false,
|
|
303
|
-
message: `Provider '${providerId}' not found`
|
|
304
|
-
};
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// 更新配置
|
|
308
|
-
if (updates.name) {
|
|
309
|
-
providerConfig.name = updates.name;
|
|
310
|
-
}
|
|
311
|
-
if (updates.description) {
|
|
312
|
-
providerConfig.description = updates.description;
|
|
313
|
-
}
|
|
314
|
-
if (updates.baseUrl) {
|
|
315
|
-
providerConfig.config.env.ANTHROPIC_BASE_URL = updates.baseUrl;
|
|
316
|
-
}
|
|
317
|
-
if (updates.apiKey) {
|
|
318
|
-
providerConfig.config.env.ANTHROPIC_AUTH_TOKEN = updates.apiKey;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
await this.ccmConfig.writeProviderConfig(providerId, providerConfig);
|
|
322
|
-
|
|
323
|
-
// 如果更新的是当前供应商,同步更新Claude配置
|
|
324
|
-
const config = await this.ccmConfig.readConfig();
|
|
325
|
-
if (config.currentProvider === providerId) {
|
|
326
|
-
await this.claudeConfig.writeClaudeConfig(providerConfig.config, true);
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
// 更新主配置中的名称
|
|
330
|
-
if (updates.name) {
|
|
331
|
-
config.providers[providerId].name = updates.name;
|
|
332
|
-
await this.ccmConfig.writeConfig(config);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
return {
|
|
336
|
-
success: true,
|
|
337
|
-
message: `Successfully updated provider '${providerId}'`
|
|
338
|
-
};
|
|
339
|
-
|
|
340
|
-
} catch (error) {
|
|
341
|
-
return {
|
|
342
|
-
success: false,
|
|
343
|
-
message: `Failed to update provider: ${error}`,
|
|
344
|
-
error: error instanceof Error ? error.message : String(error)
|
|
345
|
-
};
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
/**
|
|
350
|
-
* 清除所有配置
|
|
351
|
-
*/
|
|
352
|
-
async clearAll(): Promise<OperationResult> {
|
|
353
|
-
try {
|
|
354
|
-
await this.ccmConfig.clearAll();
|
|
355
|
-
|
|
356
|
-
return {
|
|
357
|
-
success: true,
|
|
358
|
-
message: 'Successfully cleared all CCM configurations'
|
|
359
|
-
};
|
|
360
|
-
|
|
361
|
-
} catch (error) {
|
|
362
|
-
return {
|
|
363
|
-
success: false,
|
|
364
|
-
message: `Failed to clear configurations: ${error}`,
|
|
365
|
-
error: error instanceof Error ? error.message : String(error)
|
|
366
|
-
};
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
/**
|
|
371
|
-
* 获取统计信息
|
|
372
|
-
*/
|
|
373
|
-
async getStats(): Promise<{
|
|
374
|
-
totalProviders: number;
|
|
375
|
-
currentProvider: string | null;
|
|
376
|
-
claudeConfigPath: string;
|
|
377
|
-
ccmConfigPath: string;
|
|
378
|
-
ccmConfigFile: string;
|
|
379
|
-
providersDir: string;
|
|
380
|
-
environment: string;
|
|
381
|
-
}> {
|
|
382
|
-
try {
|
|
383
|
-
const config = await this.ccmConfig.readConfig();
|
|
384
|
-
const currentProvider = config.currentProvider ?
|
|
385
|
-
(config.providers[config.currentProvider]?.name || config.currentProvider) : null;
|
|
386
|
-
|
|
387
|
-
// 从静态配置获取环境信息
|
|
388
|
-
const environment = envConfig.getCurrentEnvironment();
|
|
389
|
-
|
|
390
|
-
return {
|
|
391
|
-
totalProviders: Object.keys(config.providers).length,
|
|
392
|
-
currentProvider,
|
|
393
|
-
claudeConfigPath: this.claudeConfig.getClaudeConfigPath(),
|
|
394
|
-
ccmConfigPath: this.ccmConfig.getConfigDir(),
|
|
395
|
-
ccmConfigFile: `${this.ccmConfig.getConfigDir()}/config.json`,
|
|
396
|
-
providersDir: this.ccmConfig.getProvidersDir(),
|
|
397
|
-
environment
|
|
398
|
-
};
|
|
399
|
-
|
|
400
|
-
} catch (error) {
|
|
401
|
-
return {
|
|
402
|
-
totalProviders: 0,
|
|
403
|
-
currentProvider: null,
|
|
404
|
-
claudeConfigPath: this.claudeConfig.getClaudeConfigPath(),
|
|
405
|
-
ccmConfigPath: this.ccmConfig.getConfigDir(),
|
|
406
|
-
ccmConfigFile: `${this.ccmConfig.getConfigDir()}/config.json`,
|
|
407
|
-
providersDir: this.ccmConfig.getProvidersDir(),
|
|
408
|
-
environment: 'unknown'
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
}
|