@cloudbase/cli 2.8.2-beta.0 → 2.8.2-beta.2
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/lib/commands/ai/index.js +0 -1
- package/lib/utils/ai/claudeWindows.js +62 -0
- package/lib/utils/ai/const.js +3 -2
- package/lib/utils/ai/ensureFiles.js +1 -0
- package/lib/utils/ai/router.js +138 -98
- package/lib/utils/ai/setup.js +3 -3
- package/package.json +1 -1
- package/types/utils/ai/claudeWindows.d.ts +2 -0
- package/types/utils/ai/const.d.ts +2 -1
- package/types/utils/ai/router.d.ts +1 -1
package/lib/commands/ai/index.js
CHANGED
|
@@ -84,7 +84,6 @@ let AICommand = class AICommand extends common_1.Command {
|
|
|
84
84
|
return yield this.showConfig(configManager, log);
|
|
85
85
|
}
|
|
86
86
|
if (!(yield configManager.isConfigured())) {
|
|
87
|
-
log.info('AI 功能未配置,正在启动配置向导...');
|
|
88
87
|
const wizard = new setup_1.AISetupWizard(envId);
|
|
89
88
|
const { defaultAgent } = yield wizard.setUpDefault(log);
|
|
90
89
|
agent = defaultAgent;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.claudeWindowsCheck = void 0;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const output_1 = require("../output");
|
|
7
|
+
function claudeWindowsCheck(log) {
|
|
8
|
+
const claudeWindowsCheck = checkWindowsClaudeOk();
|
|
9
|
+
if ('error' in claudeWindowsCheck) {
|
|
10
|
+
log.error(claudeWindowsCheck.error);
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.claudeWindowsCheck = claudeWindowsCheck;
|
|
15
|
+
function checkWindowsClaudeOk() {
|
|
16
|
+
if (process.platform !== 'win32')
|
|
17
|
+
return { success: true };
|
|
18
|
+
if (process.env.CLAUDE_CODE_GIT_BASH_PATH) {
|
|
19
|
+
if (pathExistsOnWindows(process.env.CLAUDE_CODE_GIT_BASH_PATH))
|
|
20
|
+
return { success: true };
|
|
21
|
+
return {
|
|
22
|
+
error: `环境变量 CLAUDE_CODE_GIT_BASH_PATH 指定的路径 "${process.env.CLAUDE_CODE_GIT_BASH_PATH}" 不存在,请检查`
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
let gitExecutablePath = resolveWindowsExecutablePath('git');
|
|
26
|
+
if (gitExecutablePath) {
|
|
27
|
+
let bashExeCandidate = path_1.win32.join(gitExecutablePath, '..', '..', 'bin', 'bash.exe');
|
|
28
|
+
if (pathExistsOnWindows(bashExeCandidate))
|
|
29
|
+
return { success: true };
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
error: `Claude Code 在 Windows 上需要 git-bash (https://git-scm.com/downloads/win)。如果已安装但不在 PATH 中,请设置环境变量 CLAUDE_CODE_GIT_BASH_PATH 指向你的 bash.exe,类似:CLAUDE_CODE_GIT_BASH_PATH=C:\\Program Files\\Git\\bin\\bash.exe
|
|
33
|
+
或者使用 WSL 运行。详情可阅读官方文档 ${(0, output_1.genClickableLink)('https://docs.anthropic.com/zh-CN/docs/claude-code/setup#windows-%E8%AE%BE%E7%BD%AE')}`
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function pathExistsOnWindows(targetPath) {
|
|
37
|
+
try {
|
|
38
|
+
return (0, child_process_1.execSync)(`dir "${targetPath}"`, { stdio: 'pipe' });
|
|
39
|
+
}
|
|
40
|
+
catch (_a) {
|
|
41
|
+
return !1;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function resolveWindowsExecutablePath(executableName) {
|
|
45
|
+
if (executableName === 'git') {
|
|
46
|
+
let candidatePaths = [
|
|
47
|
+
'C:\\Program Files\\Git\\cmd\\git.exe',
|
|
48
|
+
'C:\\Program Files (x86)\\Git\\cmd\\git.exe'
|
|
49
|
+
];
|
|
50
|
+
for (let candidatePath of candidatePaths)
|
|
51
|
+
if (pathExistsOnWindows(candidatePath))
|
|
52
|
+
return candidatePath;
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
return ((0, child_process_1.execSync)(`where.exe ${executableName}`, { stdio: 'pipe', encoding: 'utf8' }).trim()
|
|
56
|
+
.split(`\r
|
|
57
|
+
`)[0] || null);
|
|
58
|
+
}
|
|
59
|
+
catch (_a) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
package/lib/utils/ai/const.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.LIST_HINT = exports.getBooleanHint = exports.getDefaultModelByBaseUrl = exports.BASE_URL_MODEL_MAPPING = exports.getAgentConfigValidator = exports.getDefaultConfig = exports.CLOUDBASE_PROVIDERS = exports.AGENTS = exports.NONE = exports.AIDER = exports.CODEX = exports.QWEN = exports.CLAUDE = exports.DEFAULT_CONFIG = exports.CLOUDBASE_MCP_CONFIG_PATH = exports.CLAUDE_CODE_ROUTER_LOG_PATH = exports.CLAUDE_CODE_ROUTER_CONFIG_PATH = exports.ENV_LOCAL_PATH = exports.CONFIG_PATH = void 0;
|
|
6
|
+
exports.LIST_HINT = exports.getBooleanHint = exports.getDefaultModelByBaseUrl = exports.BASE_URL_MODEL_MAPPING = exports.getAgentConfigValidator = exports.getDefaultConfig = exports.CLOUDBASE_PROVIDERS = exports.AGENTS = exports.NONE = exports.AIDER = exports.CODEX = exports.QWEN = exports.CLAUDE = exports.DEFAULT_CONFIG = exports.CLOUDBASE_MCP_CONFIG_PATH = exports.CLAUDE_CODE_ROUTER_LOGS_DIR_PATH = exports.CLAUDE_CODE_ROUTER_LOG_PATH = exports.CLAUDE_CODE_ROUTER_CONFIG_PATH = exports.ENV_LOCAL_PATH = exports.CONFIG_PATH = void 0;
|
|
7
7
|
const os_1 = __importDefault(require("os"));
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const v3_1 = __importDefault(require("zod/v3"));
|
|
@@ -11,6 +11,7 @@ exports.CONFIG_PATH = path_1.default.join(process.cwd(), 'cloudbaserc.json');
|
|
|
11
11
|
exports.ENV_LOCAL_PATH = path_1.default.join(process.cwd(), '.env.local');
|
|
12
12
|
exports.CLAUDE_CODE_ROUTER_CONFIG_PATH = path_1.default.join(os_1.default.homedir(), '.claude-code-router', 'config.json');
|
|
13
13
|
exports.CLAUDE_CODE_ROUTER_LOG_PATH = path_1.default.join(os_1.default.homedir(), '.claude-code-router', 'claude-code-router.log');
|
|
14
|
+
exports.CLAUDE_CODE_ROUTER_LOGS_DIR_PATH = path_1.default.join(os_1.default.homedir(), '.claude-code-router', 'logs');
|
|
14
15
|
exports.CLOUDBASE_MCP_CONFIG_PATH = path_1.default.join(os_1.default.homedir(), '.cloudbase-env-id');
|
|
15
16
|
exports.DEFAULT_CONFIG = `{
|
|
16
17
|
"envId": "{{env.ENV_ID}}"
|
|
@@ -168,4 +169,4 @@ function getBooleanHint(defaultValue) {
|
|
|
168
169
|
return `y 是${defaultValue === true ? '(留空默认)' : ''}; n 否${defaultValue === false ? '(留空默认)' : ''}; enter 确认`;
|
|
169
170
|
}
|
|
170
171
|
exports.getBooleanHint = getBooleanHint;
|
|
171
|
-
exports.LIST_HINT = '
|
|
172
|
+
exports.LIST_HINT = '使用上下键选择,按下 Enter 键确认选项';
|
|
@@ -21,6 +21,7 @@ function ensureFiles() {
|
|
|
21
21
|
if (!(yield fs_extra_1.default.exists(const_1.CONFIG_PATH))) {
|
|
22
22
|
yield fs_extra_1.default.writeFile(const_1.CONFIG_PATH, const_1.DEFAULT_CONFIG);
|
|
23
23
|
}
|
|
24
|
+
yield fs_extra_1.default.ensureDir(const_1.CLAUDE_CODE_ROUTER_LOGS_DIR_PATH);
|
|
24
25
|
});
|
|
25
26
|
}
|
|
26
27
|
exports.ensureFiles = ensureFiles;
|
package/lib/utils/ai/router.js
CHANGED
|
@@ -52,68 +52,49 @@ const const_1 = require("./const");
|
|
|
52
52
|
const utils_1 = require("../../commands/utils");
|
|
53
53
|
const auth_1 = require("../../auth");
|
|
54
54
|
const nodeVersion_1 = require("./nodeVersion");
|
|
55
|
+
const claudeWindows_1 = require("./claudeWindows");
|
|
55
56
|
const IDE_FILE_MAPPINGS = {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
cursor: [
|
|
58
|
+
{ path: '.cursor/rules/cloudbase-rules.mdc' },
|
|
59
|
+
{ path: '.cursor/mcp.json', isMcpConfig: true }
|
|
59
60
|
],
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
windsurf: [{ path: '.windsurf/rules/cloudbase-rules.md' }],
|
|
62
|
+
codebuddy: [{ path: '.rules/cloudbase-rules.md' }],
|
|
63
|
+
'claude-code': [{ path: 'CLAUDE.md' }, { path: '.mcp.json', isMcpConfig: true }],
|
|
64
|
+
cline: [{ path: '.clinerules/cloudbase-rules.mdc' }],
|
|
65
|
+
'gemini-cli': [
|
|
66
|
+
{ path: '.gemini/GEMINI.md' },
|
|
67
|
+
{ path: '.gemini/settings.json', isMcpConfig: true }
|
|
62
68
|
],
|
|
63
|
-
|
|
64
|
-
|
|
69
|
+
opencode: [{ path: '.opencode.json', isMcpConfig: true }],
|
|
70
|
+
'qwen-code': [{ path: '.qwen/QWEN.md' }, { path: '.qwen/settings.json', isMcpConfig: true }],
|
|
71
|
+
'baidu-comate': [
|
|
72
|
+
{ path: '.comate/rules/cloudbase-rules.mdr' },
|
|
73
|
+
{ path: '.comate/rules/cloudbaase-rules.mdr' },
|
|
74
|
+
{ path: '.comate/mcp.json', isMcpConfig: true }
|
|
65
75
|
],
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
76
|
+
'openai-codex-cli': [{ path: '.codex/config.toml', isMcpConfig: true }, { path: 'AGENTS.md' }],
|
|
77
|
+
'augment-code': [{ path: '.augment-guidelines' }],
|
|
78
|
+
'github-copilot': [{ path: '.github/copilot-instructions.md' }],
|
|
79
|
+
roocode: [
|
|
80
|
+
{ path: '.roo/rules/cloudbaase-rules.md' },
|
|
81
|
+
{ path: '.roo/mcp.json', isMcpConfig: true }
|
|
69
82
|
],
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
],
|
|
73
|
-
|
|
74
|
-
".gemini/GEMINI.md",
|
|
75
|
-
".gemini/settings.json"
|
|
76
|
-
],
|
|
77
|
-
"opencode": [
|
|
78
|
-
".opencode.json"
|
|
79
|
-
],
|
|
80
|
-
"qwen-code": [
|
|
81
|
-
".qwen/QWEN.md",
|
|
82
|
-
".qwen/settings.json"
|
|
83
|
-
],
|
|
84
|
-
"baidu-comate": [
|
|
85
|
-
".comate/rules/cloudbase-rules.mdr",
|
|
86
|
-
".comate/rules/cloudbaase-rules.mdr",
|
|
87
|
-
".comate/mcp.json"
|
|
88
|
-
],
|
|
89
|
-
"openai-codex-cli": [
|
|
90
|
-
".codex/config.toml",
|
|
91
|
-
"AGENTS.md",
|
|
92
|
-
],
|
|
93
|
-
"augment-code": [
|
|
94
|
-
".augment-guidelines"
|
|
95
|
-
],
|
|
96
|
-
"github-copilot": [
|
|
97
|
-
".github/copilot-instructions.md"
|
|
98
|
-
],
|
|
99
|
-
"roocode": [
|
|
100
|
-
".roo/rules/cloudbaase-rules.md",
|
|
101
|
-
".roo/mcp.json"
|
|
102
|
-
],
|
|
103
|
-
"tongyi-lingma": [
|
|
104
|
-
".lingma/rules/cloudbaase-rules.md"
|
|
105
|
-
],
|
|
106
|
-
"trae": [
|
|
107
|
-
".trae/rules/cloudbase-rules.md"
|
|
108
|
-
],
|
|
109
|
-
"vscode": [
|
|
110
|
-
".vscode/mcp.json",
|
|
111
|
-
".vscode/settings.json"
|
|
112
|
-
],
|
|
113
|
-
"aider": [
|
|
114
|
-
"mcp.json"
|
|
115
|
-
]
|
|
83
|
+
'tongyi-lingma': [{ path: '.lingma/rules/cloudbaase-rules.md' }],
|
|
84
|
+
trae: [{ path: '.trae/rules/cloudbase-rules.md' }],
|
|
85
|
+
vscode: [{ path: '.vscode/mcp.json', isMcpConfig: true }, { path: '.vscode/settings.json' }],
|
|
86
|
+
aider: [{ path: 'mcp.json', isMcpConfig: true }]
|
|
116
87
|
};
|
|
88
|
+
const MCP_CONFIG_SET = new Set(Object.values(IDE_FILE_MAPPINGS).reduce((acc, descriptors) => {
|
|
89
|
+
for (const d of descriptors) {
|
|
90
|
+
if (d.isMcpConfig)
|
|
91
|
+
acc.push(d.path);
|
|
92
|
+
}
|
|
93
|
+
return acc;
|
|
94
|
+
}, []));
|
|
95
|
+
function inferConfigFormat(filePath) {
|
|
96
|
+
return filePath.toLowerCase().endsWith('.toml') ? 'toml' : 'json';
|
|
97
|
+
}
|
|
117
98
|
class AICommandRouter {
|
|
118
99
|
constructor() {
|
|
119
100
|
this.configManager = new config_1.AIConfigManager();
|
|
@@ -183,21 +164,8 @@ class AICommandRouter {
|
|
|
183
164
|
if (templateType === 'none') {
|
|
184
165
|
return;
|
|
185
166
|
}
|
|
186
|
-
const shouldCheckOverwrite = yield this.shouldCheckOverwrite(templateType);
|
|
187
|
-
let overwrite = false;
|
|
188
|
-
if (shouldCheckOverwrite) {
|
|
189
|
-
const { confirmOverwrite } = yield inquirer_1.default.prompt([
|
|
190
|
-
{
|
|
191
|
-
type: 'confirm',
|
|
192
|
-
name: 'confirmOverwrite',
|
|
193
|
-
message: `检测到已存在文件,是否覆盖? ${(0, const_1.getBooleanHint)(false)}`,
|
|
194
|
-
default: false
|
|
195
|
-
}
|
|
196
|
-
]);
|
|
197
|
-
overwrite = confirmOverwrite;
|
|
198
|
-
}
|
|
199
167
|
log.info(`📦 正在下载并解压 ${templateType} 模板...`);
|
|
200
|
-
yield this.downloadAndExtractTemplate(templateType,
|
|
168
|
+
yield this.downloadAndExtractTemplate(templateType, log);
|
|
201
169
|
log.info(`✅ ${templateType} 模板配置完成`);
|
|
202
170
|
}
|
|
203
171
|
catch (error) {
|
|
@@ -206,7 +174,7 @@ class AICommandRouter {
|
|
|
206
174
|
}
|
|
207
175
|
});
|
|
208
176
|
}
|
|
209
|
-
downloadAndExtractTemplate(templateType,
|
|
177
|
+
downloadAndExtractTemplate(templateType, log) {
|
|
210
178
|
var _a, e_1, _b, _c;
|
|
211
179
|
return __awaiter(this, void 0, void 0, function* () {
|
|
212
180
|
const fs = yield Promise.resolve().then(() => __importStar(require('fs-extra')));
|
|
@@ -277,6 +245,15 @@ class AICommandRouter {
|
|
|
277
245
|
entry.autodrain();
|
|
278
246
|
continue;
|
|
279
247
|
}
|
|
248
|
+
if (MCP_CONFIG_SET.has(entryPath)) {
|
|
249
|
+
try {
|
|
250
|
+
yield this.mergeMcpConfig(entry, destPath, inferConfigFormat(entryPath), log);
|
|
251
|
+
}
|
|
252
|
+
catch (e) {
|
|
253
|
+
log.warn(`MCP 配置合并失败 ${entryPath}:${e.message},已跳过`);
|
|
254
|
+
}
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
280
257
|
if (entryPath === 'cloudbaserc.json' && (yield fs.pathExists(destPath))) {
|
|
281
258
|
try {
|
|
282
259
|
const templateContent = yield entry.buffer();
|
|
@@ -306,9 +283,19 @@ class AICommandRouter {
|
|
|
306
283
|
}
|
|
307
284
|
continue;
|
|
308
285
|
}
|
|
309
|
-
if (
|
|
310
|
-
|
|
311
|
-
|
|
286
|
+
if (yield fs.pathExists(destPath)) {
|
|
287
|
+
const { confirmOverwriteFile } = yield inquirer_1.default.prompt([
|
|
288
|
+
{
|
|
289
|
+
type: 'confirm',
|
|
290
|
+
name: 'confirmOverwriteFile',
|
|
291
|
+
message: `检测到已存在文件 ${entryPath},是否覆盖? ${(0, const_1.getBooleanHint)(false)}`,
|
|
292
|
+
default: false
|
|
293
|
+
}
|
|
294
|
+
]);
|
|
295
|
+
if (!confirmOverwriteFile) {
|
|
296
|
+
entry.autodrain();
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
312
299
|
}
|
|
313
300
|
yield fs.ensureDir(path.dirname(destPath));
|
|
314
301
|
yield new Promise((res, rej) => {
|
|
@@ -365,12 +352,6 @@ class AICommandRouter {
|
|
|
365
352
|
return { success: false, message: `# 请查阅 ${agent} 的官方安装文档` };
|
|
366
353
|
}
|
|
367
354
|
}
|
|
368
|
-
shouldCheckOverwrite(templateType) {
|
|
369
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
370
|
-
const fs = yield Promise.resolve().then(() => __importStar(require('fs-extra')));
|
|
371
|
-
return (yield fs.pathExists('.mcp.json')) || (yield fs.pathExists('CLAUDE.md'));
|
|
372
|
-
});
|
|
373
|
-
}
|
|
374
355
|
executeCommand(command, args, env, log) {
|
|
375
356
|
return __awaiter(this, void 0, void 0, function* () {
|
|
376
357
|
return new Promise((resolve, reject) => {
|
|
@@ -452,14 +433,20 @@ class AICommandRouter {
|
|
|
452
433
|
return __awaiter(this, void 0, void 0, function* () {
|
|
453
434
|
switch (agent) {
|
|
454
435
|
case const_1.CLAUDE.value:
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
436
|
+
try {
|
|
437
|
+
if (agentConfig.type === 'cloudbase') {
|
|
438
|
+
return yield this.executeClaudeCloudbaseAgent(agentConfig, additionalArgs, log);
|
|
439
|
+
}
|
|
440
|
+
else if (agentConfig.type === 'custom') {
|
|
441
|
+
return yield this.executeClaudeAgent(agentConfig, additionalArgs, log);
|
|
442
|
+
}
|
|
443
|
+
else {
|
|
444
|
+
return yield this.executeNoneClaudeAgent(additionalArgs, log);
|
|
445
|
+
}
|
|
460
446
|
}
|
|
461
|
-
|
|
462
|
-
|
|
447
|
+
catch (_) {
|
|
448
|
+
(0, claudeWindows_1.claudeWindowsCheck)(log);
|
|
449
|
+
return process.exit(1);
|
|
463
450
|
}
|
|
464
451
|
case const_1.QWEN.value:
|
|
465
452
|
if (agentConfig.type === 'cloudbase') {
|
|
@@ -924,14 +911,17 @@ class AICommandRouter {
|
|
|
924
911
|
const path = yield Promise.resolve().then(() => __importStar(require('path')));
|
|
925
912
|
try {
|
|
926
913
|
log.info('🔧 正在修改 MCP 配置文件...');
|
|
927
|
-
for (const [
|
|
928
|
-
for (const
|
|
929
|
-
|
|
914
|
+
for (const [, files] of Object.entries(IDE_FILE_MAPPINGS)) {
|
|
915
|
+
for (const descriptor of files) {
|
|
916
|
+
if (!descriptor.isMcpConfig)
|
|
917
|
+
continue;
|
|
918
|
+
const filePath = path.join(extractDir, descriptor.path);
|
|
930
919
|
if (yield fs.pathExists(filePath)) {
|
|
931
|
-
|
|
920
|
+
const format = inferConfigFormat(descriptor.path);
|
|
921
|
+
if (format === 'json') {
|
|
932
922
|
yield this.modifyMCPJsonFile(filePath, log);
|
|
933
923
|
}
|
|
934
|
-
else if (
|
|
924
|
+
else if (format === 'toml') {
|
|
935
925
|
yield this.modifyMCPTomlFile(filePath, log);
|
|
936
926
|
}
|
|
937
927
|
}
|
|
@@ -956,12 +946,13 @@ class AICommandRouter {
|
|
|
956
946
|
return obj;
|
|
957
947
|
}
|
|
958
948
|
if (Array.isArray(obj)) {
|
|
959
|
-
return obj.map(item => modifyCommands(item));
|
|
949
|
+
return obj.map((item) => modifyCommands(item));
|
|
960
950
|
}
|
|
961
951
|
const result = Object.assign({}, obj);
|
|
962
952
|
if (result.command === 'npx' && Array.isArray(result.args)) {
|
|
963
953
|
const argsStr = result.args.join(' ');
|
|
964
|
-
if (argsStr.includes('npm-global-exec@latest') &&
|
|
954
|
+
if (argsStr.includes('npm-global-exec@latest') &&
|
|
955
|
+
argsStr.includes('@cloudbase/cloudbase-mcp@latest')) {
|
|
965
956
|
result.command = 'cloudbase-mcp';
|
|
966
957
|
result.args = [];
|
|
967
958
|
result.env = {
|
|
@@ -990,7 +981,7 @@ class AICommandRouter {
|
|
|
990
981
|
modifyMCPTomlFile(filePath, log) {
|
|
991
982
|
return __awaiter(this, void 0, void 0, function* () {
|
|
992
983
|
const fs = yield Promise.resolve().then(() => __importStar(require('fs-extra')));
|
|
993
|
-
const toml = require('toml');
|
|
984
|
+
const toml = yield Promise.resolve().then(() => __importStar(require('toml')));
|
|
994
985
|
try {
|
|
995
986
|
const content = yield fs.readFile(filePath, 'utf-8');
|
|
996
987
|
const config = toml.parse(content);
|
|
@@ -1000,7 +991,7 @@ class AICommandRouter {
|
|
|
1000
991
|
return obj;
|
|
1001
992
|
}
|
|
1002
993
|
if (Array.isArray(obj)) {
|
|
1003
|
-
return obj.map(item => modifyCommands(item));
|
|
994
|
+
return obj.map((item) => modifyCommands(item));
|
|
1004
995
|
}
|
|
1005
996
|
const result = Object.assign({}, obj);
|
|
1006
997
|
if (result.command === 'npx' && Array.isArray(result.args)) {
|
|
@@ -1032,6 +1023,53 @@ class AICommandRouter {
|
|
|
1032
1023
|
}
|
|
1033
1024
|
});
|
|
1034
1025
|
}
|
|
1026
|
+
mergeMcpConfig(entry, destPath, format, log) {
|
|
1027
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1028
|
+
const fs = yield Promise.resolve().then(() => __importStar(require('fs-extra')));
|
|
1029
|
+
const path = yield Promise.resolve().then(() => __importStar(require('path')));
|
|
1030
|
+
const incomingStr = (yield entry.buffer()).toString('utf8');
|
|
1031
|
+
const deepMerge = (target, source) => {
|
|
1032
|
+
if (typeof target !== 'object' || typeof source !== 'object' || !target || !source) {
|
|
1033
|
+
return target;
|
|
1034
|
+
}
|
|
1035
|
+
const result = Array.isArray(target) ? [...target] : Object.assign(Object.assign({}, source), target);
|
|
1036
|
+
for (const key of Object.keys(source)) {
|
|
1037
|
+
if (key in target &&
|
|
1038
|
+
typeof target[key] === 'object' &&
|
|
1039
|
+
typeof source[key] === 'object') {
|
|
1040
|
+
result[key] = deepMerge(target[key], source[key]);
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
return result;
|
|
1044
|
+
};
|
|
1045
|
+
yield fs.ensureDir(path.dirname(destPath));
|
|
1046
|
+
if (format === 'json') {
|
|
1047
|
+
const incomingObj = JSON.parse(incomingStr);
|
|
1048
|
+
if (yield fs.pathExists(destPath)) {
|
|
1049
|
+
const existingObj = yield fs.readJson(destPath);
|
|
1050
|
+
const merged = deepMerge(existingObj, incomingObj);
|
|
1051
|
+
yield fs.writeJson(destPath, merged, { spaces: 2 });
|
|
1052
|
+
}
|
|
1053
|
+
else {
|
|
1054
|
+
yield fs.writeJson(destPath, incomingObj, { spaces: 2 });
|
|
1055
|
+
}
|
|
1056
|
+
return;
|
|
1057
|
+
}
|
|
1058
|
+
const toml = yield Promise.resolve().then(() => __importStar(require('toml')));
|
|
1059
|
+
const incomingObj = toml.parse(incomingStr);
|
|
1060
|
+
if (yield fs.pathExists(destPath)) {
|
|
1061
|
+
const existingStr = yield fs.readFile(destPath, 'utf-8');
|
|
1062
|
+
const existingObj = toml.parse(existingStr);
|
|
1063
|
+
const merged = deepMerge(existingObj, incomingObj);
|
|
1064
|
+
const out = this.objectToToml(merged);
|
|
1065
|
+
yield fs.writeFile(destPath, out, 'utf-8');
|
|
1066
|
+
}
|
|
1067
|
+
else {
|
|
1068
|
+
const out = this.objectToToml(incomingObj);
|
|
1069
|
+
yield fs.writeFile(destPath, out, 'utf-8');
|
|
1070
|
+
}
|
|
1071
|
+
});
|
|
1072
|
+
}
|
|
1035
1073
|
objectToToml(obj, prefix = '') {
|
|
1036
1074
|
const lines = [];
|
|
1037
1075
|
for (const [key, value] of Object.entries(obj)) {
|
|
@@ -1041,12 +1079,14 @@ class AICommandRouter {
|
|
|
1041
1079
|
lines.push(this.objectToToml(value, fullKey));
|
|
1042
1080
|
}
|
|
1043
1081
|
else if (Array.isArray(value)) {
|
|
1044
|
-
const arrayStr = value
|
|
1082
|
+
const arrayStr = value
|
|
1083
|
+
.map((item) => {
|
|
1045
1084
|
if (typeof item === 'string') {
|
|
1046
1085
|
return `"${item}"`;
|
|
1047
1086
|
}
|
|
1048
1087
|
return item;
|
|
1049
|
-
})
|
|
1088
|
+
})
|
|
1089
|
+
.join(', ');
|
|
1050
1090
|
lines.push(`${key} = [${arrayStr}]`);
|
|
1051
1091
|
}
|
|
1052
1092
|
else if (typeof value === 'string') {
|
package/lib/utils/ai/setup.js
CHANGED
|
@@ -229,7 +229,7 @@ class AISetupWizard {
|
|
|
229
229
|
choices: [
|
|
230
230
|
{ name: '使用 CloudBase 服务,一键登录,无需配置', value: 'cloudbase' },
|
|
231
231
|
{ name: '自配置 API KEY 和 Base URL', value: 'custom' },
|
|
232
|
-
{ name: '
|
|
232
|
+
{ name: '暂不配置,使用 Claude Code 内置鉴权方式(如 OAuth)', value: 'none' }
|
|
233
233
|
],
|
|
234
234
|
default: 'cloudbase'
|
|
235
235
|
}
|
|
@@ -296,7 +296,7 @@ class AISetupWizard {
|
|
|
296
296
|
choices: [
|
|
297
297
|
{ name: '使用 CloudBase 服务,一键登录,无需配置', value: 'cloudbase' },
|
|
298
298
|
{ name: '自配置 API KEY 和 Base URL', value: 'custom' },
|
|
299
|
-
{ name: '
|
|
299
|
+
{ name: '暂不配置,使用 Qwen Code 内置鉴权方式(如 OAuth)', value: 'none' }
|
|
300
300
|
],
|
|
301
301
|
default: 'cloudbase'
|
|
302
302
|
}
|
|
@@ -348,7 +348,7 @@ class AISetupWizard {
|
|
|
348
348
|
choices: [
|
|
349
349
|
{ name: '使用 CloudBase 服务,一键登录,无需配置', value: 'cloudbase' },
|
|
350
350
|
{ name: '自配置 API KEY 和 Base URL', value: 'custom' },
|
|
351
|
-
{ name: '
|
|
351
|
+
{ name: '暂不配置,使用 OpenAI Codex 内置鉴权方式(如 OAuth)', value: 'none' }
|
|
352
352
|
],
|
|
353
353
|
default: 'cloudbase'
|
|
354
354
|
}
|
package/package.json
CHANGED
|
@@ -3,6 +3,7 @@ export declare const CONFIG_PATH: string;
|
|
|
3
3
|
export declare const ENV_LOCAL_PATH: string;
|
|
4
4
|
export declare const CLAUDE_CODE_ROUTER_CONFIG_PATH: string;
|
|
5
5
|
export declare const CLAUDE_CODE_ROUTER_LOG_PATH: string;
|
|
6
|
+
export declare const CLAUDE_CODE_ROUTER_LOGS_DIR_PATH: string;
|
|
6
7
|
export declare const CLOUDBASE_MCP_CONFIG_PATH: string;
|
|
7
8
|
export declare const DEFAULT_CONFIG = "{\n \"envId\": \"{{env.ENV_ID}}\"\n}";
|
|
8
9
|
export declare const CLAUDE: {
|
|
@@ -328,4 +329,4 @@ export declare const BASE_URL_MODEL_MAPPING: {
|
|
|
328
329
|
};
|
|
329
330
|
export declare function getDefaultModelByBaseUrl(baseUrl: string): string;
|
|
330
331
|
export declare function getBooleanHint(defaultValue?: boolean): string;
|
|
331
|
-
export declare const LIST_HINT = "\u4F7F\u7528\u4E0A\u4E0B\u952E\u9009\u62E9\uFF0C\
|
|
332
|
+
export declare const LIST_HINT = "\u4F7F\u7528\u4E0A\u4E0B\u952E\u9009\u62E9\uFF0C\u6309\u4E0B Enter \u952E\u786E\u8BA4\u9009\u9879";
|
|
@@ -13,7 +13,6 @@ export declare class AICommandRouter {
|
|
|
13
13
|
private downloadTemplate;
|
|
14
14
|
private downloadAndExtractTemplate;
|
|
15
15
|
private getInstallCommand;
|
|
16
|
-
private shouldCheckOverwrite;
|
|
17
16
|
private executeCommand;
|
|
18
17
|
private isToolAvailable;
|
|
19
18
|
private validateAgentConfig;
|
|
@@ -41,6 +40,7 @@ export declare class AICommandRouter {
|
|
|
41
40
|
private modifyMCPConfigs;
|
|
42
41
|
private modifyMCPJsonFile;
|
|
43
42
|
private modifyMCPTomlFile;
|
|
43
|
+
private mergeMcpConfig;
|
|
44
44
|
private objectToToml;
|
|
45
45
|
}
|
|
46
46
|
export {};
|