@cloudbase/cloudbase-mcp 2.9.0 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +3 -3
- package/dist/index.cjs +1990 -1715
- package/dist/index.js +1470 -1667
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -562,7 +562,7 @@ ${envIdSection}
|
|
|
562
562
|
## 环境信息
|
|
563
563
|
- 操作系统: ${os_1.default.type()} ${os_1.default.release()}
|
|
564
564
|
- Node.js版本: ${process.version}
|
|
565
|
-
- MCP 版本:${process.env.npm_package_version || "2.
|
|
565
|
+
- MCP 版本:${process.env.npm_package_version || "2.11.0" || 0}
|
|
566
566
|
- 系统架构: ${os_1.default.arch()}
|
|
567
567
|
- 时间: ${new Date().toISOString()}
|
|
568
568
|
- 请求ID: ${requestId}
|
|
@@ -971,11 +971,43 @@ exports.resetInteractiveServer = resetInteractiveServer;
|
|
|
971
971
|
exports.getInteractiveServerSafe = getInteractiveServerSafe;
|
|
972
972
|
const express_1 = __importDefault(__webpack_require__(2674));
|
|
973
973
|
const http_1 = __importDefault(__webpack_require__(3782));
|
|
974
|
+
const child_process_1 = __webpack_require__(5814);
|
|
974
975
|
const open_1 = __importDefault(__webpack_require__(1622));
|
|
975
976
|
const ws_1 = __webpack_require__(6220);
|
|
976
977
|
const index_js_1 = __webpack_require__(9529);
|
|
977
978
|
const logger_js_1 = __webpack_require__(3039);
|
|
978
|
-
|
|
979
|
+
function isVSCodeEnvironment() {
|
|
980
|
+
return Boolean(process.env.VSCODE_IPC_HOOK_CLI ||
|
|
981
|
+
process.env.VSCODE_PID ||
|
|
982
|
+
process.env.TERM_PROGRAM === "vscode");
|
|
983
|
+
}
|
|
984
|
+
function parseBrowserCommand(browser) {
|
|
985
|
+
const parts = browser.match(/(?:[^\s"]+|"[^"]*")+/g) || [];
|
|
986
|
+
return parts.map((item) => item.replace(/^"(.*)"$/, "$1"));
|
|
987
|
+
}
|
|
988
|
+
async function openUrlByBrowserEnv(url) {
|
|
989
|
+
const browser = process.env.BROWSER?.trim();
|
|
990
|
+
if (!browser) {
|
|
991
|
+
return false;
|
|
992
|
+
}
|
|
993
|
+
const [command, ...args] = parseBrowserCommand(browser);
|
|
994
|
+
if (!command) {
|
|
995
|
+
return false;
|
|
996
|
+
}
|
|
997
|
+
const finalArgs = args.map((arg) => (arg === "%s" ? url : arg));
|
|
998
|
+
if (!args.includes("%s")) {
|
|
999
|
+
finalArgs.push(url);
|
|
1000
|
+
}
|
|
1001
|
+
return new Promise((resolve) => {
|
|
1002
|
+
(0, child_process_1.execFile)(command, finalArgs, (execError) => {
|
|
1003
|
+
resolve(!execError);
|
|
1004
|
+
});
|
|
1005
|
+
});
|
|
1006
|
+
}
|
|
1007
|
+
function shouldUseBrowserEnvFallback() {
|
|
1008
|
+
return process.platform === "linux" && isVSCodeEnvironment();
|
|
1009
|
+
}
|
|
1010
|
+
// Dynamic open behavior with IDE awareness and VSCode/Linux fallback
|
|
979
1011
|
async function openUrl(url, options, mcpServer) {
|
|
980
1012
|
// mcpServer 是 ExtendedMcpServer 实例,它有 server 和 ide 属性
|
|
981
1013
|
// server 属性是 MCP server 的内部 server 实例,有 sendLoggingMessage 方法
|
|
@@ -1007,13 +1039,28 @@ async function openUrl(url, options, mcpServer) {
|
|
|
1007
1039
|
return;
|
|
1008
1040
|
}
|
|
1009
1041
|
}
|
|
1010
|
-
//
|
|
1042
|
+
// 默认行为:直接打开网页(带 VSCode/Linux 降级逻辑)
|
|
1011
1043
|
(0, logger_js_1.debug)(`[openUrl] Opening URL in browser: ${url}`);
|
|
1012
1044
|
try {
|
|
1013
|
-
|
|
1045
|
+
const openOptions = options ? { url: true, ...options } : { url: true };
|
|
1046
|
+
const child = await (0, open_1.default)(url, openOptions);
|
|
1047
|
+
if (child?.once) {
|
|
1048
|
+
child.once("error", async () => {
|
|
1049
|
+
if (shouldUseBrowserEnvFallback()) {
|
|
1050
|
+
(0, logger_js_1.debug)("[openUrl] open() failed, trying BROWSER fallback");
|
|
1051
|
+
await openUrlByBrowserEnv(url);
|
|
1052
|
+
}
|
|
1053
|
+
});
|
|
1054
|
+
}
|
|
1055
|
+
return;
|
|
1014
1056
|
}
|
|
1015
1057
|
catch (err) {
|
|
1016
1058
|
(0, logger_js_1.error)(`Failed to open ${url} ${options} ${err instanceof Error ? err.message : err} `, err instanceof Error ? err : new Error(String(err)));
|
|
1059
|
+
if (shouldUseBrowserEnvFallback()) {
|
|
1060
|
+
(0, logger_js_1.debug)("[openUrl] open() threw, trying BROWSER fallback");
|
|
1061
|
+
await openUrlByBrowserEnv(url);
|
|
1062
|
+
return;
|
|
1063
|
+
}
|
|
1017
1064
|
(0, logger_js_1.warn)(`Please manually open: ${url}`);
|
|
1018
1065
|
}
|
|
1019
1066
|
}
|
|
@@ -5267,9 +5314,13 @@ checkIndex: 检查索引是否存在`),
|
|
|
5267
5314
|
title: "修改 NoSQL 数据库结构",
|
|
5268
5315
|
description: "修改 NoSQL 数据库结构",
|
|
5269
5316
|
inputSchema: {
|
|
5270
|
-
action: zod_1.z.enum([
|
|
5271
|
-
|
|
5272
|
-
updateCollection
|
|
5317
|
+
action: zod_1.z.enum([
|
|
5318
|
+
"createCollection",
|
|
5319
|
+
"updateCollection",
|
|
5320
|
+
"deleteCollection",
|
|
5321
|
+
]).describe(`createCollection: 创建集合
|
|
5322
|
+
updateCollection: 更新集合
|
|
5323
|
+
deleteCollection: 删除集合`),
|
|
5273
5324
|
collectionName: zod_1.z.string().describe("集合名称"),
|
|
5274
5325
|
updateOptions: zod_1.z
|
|
5275
5326
|
.object({
|
|
@@ -5296,68 +5347,72 @@ updateCollection: 更新集合`),
|
|
|
5296
5347
|
},
|
|
5297
5348
|
annotations: {
|
|
5298
5349
|
readOnlyHint: false,
|
|
5299
|
-
destructiveHint:
|
|
5350
|
+
destructiveHint: true,
|
|
5300
5351
|
idempotentHint: false,
|
|
5301
5352
|
openWorldHint: true,
|
|
5302
5353
|
category: CATEGORY,
|
|
5303
5354
|
},
|
|
5304
5355
|
}, async ({ action, collectionName, updateOptions }) => {
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
};
|
|
5323
|
-
}
|
|
5324
|
-
if (action === "updateCollection") {
|
|
5325
|
-
if (!updateOptions) {
|
|
5326
|
-
throw new Error("更新集合时必须提供 options");
|
|
5327
|
-
}
|
|
5328
|
-
const result = await cloudbase.database.updateCollection(collectionName, updateOptions);
|
|
5329
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
5330
|
-
return {
|
|
5331
|
-
content: [
|
|
5332
|
-
{
|
|
5333
|
-
type: "text",
|
|
5334
|
-
text: JSON.stringify({
|
|
5335
|
-
success: true,
|
|
5336
|
-
requestId: result.RequestId,
|
|
5337
|
-
action,
|
|
5338
|
-
message: "云开发数据库集合更新成功",
|
|
5339
|
-
}, null, 2),
|
|
5340
|
-
},
|
|
5341
|
-
],
|
|
5342
|
-
};
|
|
5343
|
-
}
|
|
5344
|
-
throw new Error(`不支持的操作类型: ${action}`);
|
|
5356
|
+
const cloudbase = await getManager();
|
|
5357
|
+
if (action === "createCollection") {
|
|
5358
|
+
const result = await cloudbase.database.createCollection(collectionName);
|
|
5359
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
5360
|
+
return {
|
|
5361
|
+
content: [
|
|
5362
|
+
{
|
|
5363
|
+
type: "text",
|
|
5364
|
+
text: JSON.stringify({
|
|
5365
|
+
success: true,
|
|
5366
|
+
requestId: result.RequestId,
|
|
5367
|
+
action,
|
|
5368
|
+
message: "云开发数据库集合创建成功",
|
|
5369
|
+
}, null, 2),
|
|
5370
|
+
},
|
|
5371
|
+
],
|
|
5372
|
+
};
|
|
5345
5373
|
}
|
|
5346
|
-
|
|
5374
|
+
if (action === "updateCollection") {
|
|
5375
|
+
if (!updateOptions) {
|
|
5376
|
+
throw new Error("更新集合时必须提供 options");
|
|
5377
|
+
}
|
|
5378
|
+
const result = await cloudbase.database.updateCollection(collectionName, updateOptions);
|
|
5379
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
5347
5380
|
return {
|
|
5348
5381
|
content: [
|
|
5349
5382
|
{
|
|
5350
5383
|
type: "text",
|
|
5351
5384
|
text: JSON.stringify({
|
|
5352
|
-
success:
|
|
5385
|
+
success: true,
|
|
5386
|
+
requestId: result.RequestId,
|
|
5353
5387
|
action,
|
|
5354
|
-
|
|
5355
|
-
message: "集合创建/更新操作失败",
|
|
5388
|
+
message: "云开发数据库集合更新成功",
|
|
5356
5389
|
}, null, 2),
|
|
5357
5390
|
},
|
|
5358
5391
|
],
|
|
5359
5392
|
};
|
|
5360
5393
|
}
|
|
5394
|
+
if (action === "deleteCollection") {
|
|
5395
|
+
const result = await cloudbase.database.deleteCollection(collectionName);
|
|
5396
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
5397
|
+
const body = {
|
|
5398
|
+
success: true,
|
|
5399
|
+
requestId: result.RequestId,
|
|
5400
|
+
action,
|
|
5401
|
+
message: result.Exists === false ? "集合不存在" : "云开发数据库集合删除成功",
|
|
5402
|
+
};
|
|
5403
|
+
if (result.Exists === false) {
|
|
5404
|
+
body.exists = false;
|
|
5405
|
+
}
|
|
5406
|
+
return {
|
|
5407
|
+
content: [
|
|
5408
|
+
{
|
|
5409
|
+
type: "text",
|
|
5410
|
+
text: JSON.stringify(body, null, 2),
|
|
5411
|
+
},
|
|
5412
|
+
],
|
|
5413
|
+
};
|
|
5414
|
+
}
|
|
5415
|
+
throw new Error(`不支持的操作类型: ${action}`);
|
|
5361
5416
|
});
|
|
5362
5417
|
// readNoSqlDatabaseContent
|
|
5363
5418
|
server.registerTool?.("readNoSqlDatabaseContent", {
|
|
@@ -5374,9 +5429,17 @@ updateCollection: 更新集合`),
|
|
|
5374
5429
|
.optional()
|
|
5375
5430
|
.describe("返回字段投影(对象或字符串,推荐对象)"),
|
|
5376
5431
|
sort: zod_1.z
|
|
5377
|
-
.union([
|
|
5432
|
+
.union([
|
|
5433
|
+
zod_1.z.array(zod_1.z
|
|
5434
|
+
.object({
|
|
5435
|
+
key: zod_1.z.string().describe("sort 字段名"),
|
|
5436
|
+
direction: zod_1.z.number().describe("排序方向,1:升序,-1:降序"),
|
|
5437
|
+
})
|
|
5438
|
+
.passthrough()),
|
|
5439
|
+
zod_1.z.string(),
|
|
5440
|
+
])
|
|
5378
5441
|
.optional()
|
|
5379
|
-
.describe("
|
|
5442
|
+
.describe("排序条件,使用对象或字符串。"),
|
|
5380
5443
|
limit: zod_1.z.number().optional().describe("返回数量限制"),
|
|
5381
5444
|
offset: zod_1.z.number().optional().describe("跳过的记录数"),
|
|
5382
5445
|
},
|
|
@@ -5386,63 +5449,45 @@ updateCollection: 更新集合`),
|
|
|
5386
5449
|
category: CATEGORY,
|
|
5387
5450
|
},
|
|
5388
5451
|
}, async ({ collectionName, query, projection, sort, limit, offset }) => {
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5452
|
+
const cloudbase = await getManager();
|
|
5453
|
+
const instanceId = await getDatabaseInstanceId(getManager);
|
|
5454
|
+
const toJSONString = (v) => typeof v === "object" && v !== null ? JSON.stringify(v) : v;
|
|
5455
|
+
const result = await cloudbase.commonService("tcb", "2018-06-08").call({
|
|
5456
|
+
Action: "QueryRecords",
|
|
5457
|
+
Param: {
|
|
5458
|
+
TableName: collectionName,
|
|
5459
|
+
MgoQuery: toJSONString(query),
|
|
5460
|
+
MgoProjection: toJSONString(projection),
|
|
5461
|
+
MgoSort: toJSONString(sort),
|
|
5462
|
+
MgoLimit: limit ?? 100,
|
|
5463
|
+
MgoOffset: offset,
|
|
5464
|
+
Tag: instanceId,
|
|
5465
|
+
},
|
|
5466
|
+
});
|
|
5467
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
5468
|
+
return {
|
|
5469
|
+
content: [
|
|
5470
|
+
{
|
|
5471
|
+
type: "text",
|
|
5472
|
+
text: JSON.stringify({
|
|
5473
|
+
success: true,
|
|
5474
|
+
requestId: result.RequestId,
|
|
5475
|
+
data: result.Data,
|
|
5476
|
+
pager: result.Pager,
|
|
5477
|
+
message: "文档查询成功",
|
|
5478
|
+
}, null, 2),
|
|
5404
5479
|
},
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
return {
|
|
5408
|
-
content: [
|
|
5409
|
-
{
|
|
5410
|
-
type: "text",
|
|
5411
|
-
text: JSON.stringify({
|
|
5412
|
-
success: true,
|
|
5413
|
-
requestId: result.RequestId,
|
|
5414
|
-
data: result.Data,
|
|
5415
|
-
pager: result.Pager,
|
|
5416
|
-
message: "文档查询成功",
|
|
5417
|
-
}, null, 2),
|
|
5418
|
-
},
|
|
5419
|
-
],
|
|
5420
|
-
};
|
|
5421
|
-
}
|
|
5422
|
-
catch (error) {
|
|
5423
|
-
return {
|
|
5424
|
-
content: [
|
|
5425
|
-
{
|
|
5426
|
-
type: "text",
|
|
5427
|
-
text: JSON.stringify({
|
|
5428
|
-
success: false,
|
|
5429
|
-
error: error.message,
|
|
5430
|
-
message: "文档查询失败",
|
|
5431
|
-
}, null, 2),
|
|
5432
|
-
},
|
|
5433
|
-
],
|
|
5434
|
-
};
|
|
5435
|
-
}
|
|
5480
|
+
],
|
|
5481
|
+
};
|
|
5436
5482
|
});
|
|
5437
5483
|
// writeNoSqlDatabaseContent
|
|
5438
5484
|
server.registerTool?.("writeNoSqlDatabaseContent", {
|
|
5439
5485
|
title: "修改 NoSQL 数据库数据记录",
|
|
5440
5486
|
description: "修改 NoSQL 数据库数据记录",
|
|
5441
5487
|
inputSchema: {
|
|
5442
|
-
action: zod_1.z
|
|
5443
|
-
.
|
|
5444
|
-
|
|
5445
|
-
deleteCollection: 删除数据`),
|
|
5488
|
+
action: zod_1.z
|
|
5489
|
+
.enum(["insert", "update", "delete"])
|
|
5490
|
+
.describe(`insert: 插入数据(新增文档)\nupdate: 更新数据\ndelete: 删除数据`),
|
|
5446
5491
|
collectionName: zod_1.z.string().describe("集合名称"),
|
|
5447
5492
|
documents: zod_1.z
|
|
5448
5493
|
.array(zod_1.z.object({}).passthrough())
|
|
@@ -5541,98 +5586,70 @@ deleteCollection: 删除数据`),
|
|
|
5541
5586
|
});
|
|
5542
5587
|
}
|
|
5543
5588
|
async function insertDocuments({ collectionName, documents, getManager, logger, }) {
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
|
|
5553
|
-
|
|
5554
|
-
|
|
5555
|
-
|
|
5556
|
-
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
|
|
5560
|
-
|
|
5561
|
-
|
|
5562
|
-
message: "文档插入成功",
|
|
5563
|
-
}, null, 2);
|
|
5564
|
-
}
|
|
5565
|
-
catch (error) {
|
|
5566
|
-
return JSON.stringify({
|
|
5567
|
-
success: false,
|
|
5568
|
-
error: error.message,
|
|
5569
|
-
message: "文档插入失败",
|
|
5570
|
-
}, null, 2);
|
|
5571
|
-
}
|
|
5589
|
+
const cloudbase = await getManager();
|
|
5590
|
+
const instanceId = await getDatabaseInstanceId(getManager);
|
|
5591
|
+
const docsAsStrings = documents.map((doc) => JSON.stringify(doc));
|
|
5592
|
+
const result = await cloudbase.commonService("tcb", "2018-06-08").call({
|
|
5593
|
+
Action: "PutItem",
|
|
5594
|
+
Param: {
|
|
5595
|
+
TableName: collectionName,
|
|
5596
|
+
MgoDocs: docsAsStrings,
|
|
5597
|
+
Tag: instanceId,
|
|
5598
|
+
},
|
|
5599
|
+
});
|
|
5600
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(logger, result);
|
|
5601
|
+
return JSON.stringify({
|
|
5602
|
+
success: true,
|
|
5603
|
+
requestId: result.RequestId,
|
|
5604
|
+
insertedIds: result.InsertedIds,
|
|
5605
|
+
message: "文档插入成功",
|
|
5606
|
+
}, null, 2);
|
|
5572
5607
|
}
|
|
5573
5608
|
async function updateDocuments({ collectionName, query, update, isMulti, upsert, getManager, logger, }) {
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
|
|
5577
|
-
|
|
5578
|
-
|
|
5579
|
-
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
}, null, 2);
|
|
5598
|
-
}
|
|
5599
|
-
catch (error) {
|
|
5600
|
-
return JSON.stringify({
|
|
5601
|
-
success: false,
|
|
5602
|
-
error: error.message,
|
|
5603
|
-
message: "文档更新失败",
|
|
5604
|
-
}, null, 2);
|
|
5605
|
-
}
|
|
5609
|
+
const cloudbase = await getManager();
|
|
5610
|
+
const instanceId = await getDatabaseInstanceId(getManager);
|
|
5611
|
+
const toJSONString = (v) => typeof v === "object" && v !== null ? JSON.stringify(v) : v;
|
|
5612
|
+
const result = await cloudbase.commonService("tcb", "2018-06-08").call({
|
|
5613
|
+
Action: "UpdateItem",
|
|
5614
|
+
Param: {
|
|
5615
|
+
TableName: collectionName,
|
|
5616
|
+
MgoQuery: toJSONString(query),
|
|
5617
|
+
MgoUpdate: toJSONString(update),
|
|
5618
|
+
MgoIsMulti: isMulti,
|
|
5619
|
+
MgoUpsert: upsert,
|
|
5620
|
+
Tag: instanceId,
|
|
5621
|
+
},
|
|
5622
|
+
});
|
|
5623
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(logger, result);
|
|
5624
|
+
return JSON.stringify({
|
|
5625
|
+
success: true,
|
|
5626
|
+
requestId: result.RequestId,
|
|
5627
|
+
modifiedCount: result.ModifiedNum,
|
|
5628
|
+
matchedCount: result.MatchedNum,
|
|
5629
|
+
upsertedId: result.UpsertedId,
|
|
5630
|
+
message: "文档更新成功",
|
|
5631
|
+
}, null, 2);
|
|
5606
5632
|
}
|
|
5607
5633
|
async function deleteDocuments({ collectionName, query, isMulti, getManager, logger, }) {
|
|
5608
|
-
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
}, null, 2);
|
|
5628
|
-
}
|
|
5629
|
-
catch (error) {
|
|
5630
|
-
return JSON.stringify({
|
|
5631
|
-
success: false,
|
|
5632
|
-
error: error.message,
|
|
5633
|
-
message: "文档删除失败",
|
|
5634
|
-
}, null, 2);
|
|
5635
|
-
}
|
|
5634
|
+
const cloudbase = await getManager();
|
|
5635
|
+
const instanceId = await getDatabaseInstanceId(getManager);
|
|
5636
|
+
const toJSONString = (v) => typeof v === "object" && v !== null ? JSON.stringify(v) : v;
|
|
5637
|
+
const result = await cloudbase.commonService("tcb", "2018-06-08").call({
|
|
5638
|
+
Action: "DeleteItem",
|
|
5639
|
+
Param: {
|
|
5640
|
+
TableName: collectionName,
|
|
5641
|
+
MgoQuery: toJSONString(query),
|
|
5642
|
+
MgoIsMulti: isMulti,
|
|
5643
|
+
Tag: instanceId,
|
|
5644
|
+
},
|
|
5645
|
+
});
|
|
5646
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(logger, result);
|
|
5647
|
+
return JSON.stringify({
|
|
5648
|
+
success: true,
|
|
5649
|
+
requestId: result.RequestId,
|
|
5650
|
+
deleted: result.Deleted,
|
|
5651
|
+
message: "文档删除成功",
|
|
5652
|
+
}, null, 2);
|
|
5636
5653
|
}
|
|
5637
5654
|
|
|
5638
5655
|
|
|
@@ -6202,289 +6219,271 @@ function registerDataModelTools(server) {
|
|
|
6202
6219
|
category: "database",
|
|
6203
6220
|
},
|
|
6204
6221
|
}, async ({ action, name, names, }) => {
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
|
|
6241
|
-
|
|
6242
|
-
|
|
6243
|
-
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
|
|
6252
|
-
|
|
6253
|
-
};
|
|
6254
|
-
}
|
|
6255
|
-
catch (e) {
|
|
6256
|
-
simplifiedSchema = { error: "Schema解析失败" };
|
|
6257
|
-
}
|
|
6222
|
+
const cloudbase = await getManager();
|
|
6223
|
+
let currentEnvId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
6224
|
+
let result;
|
|
6225
|
+
switch (action) {
|
|
6226
|
+
case "get":
|
|
6227
|
+
if (!name) {
|
|
6228
|
+
throw new Error("获取数据模型需要提供模型名称");
|
|
6229
|
+
}
|
|
6230
|
+
try {
|
|
6231
|
+
result = await cloudbase.commonService("lowcode").call({
|
|
6232
|
+
Action: "DescribeBasicDataSource",
|
|
6233
|
+
Param: {
|
|
6234
|
+
EnvId: currentEnvId,
|
|
6235
|
+
Name: name,
|
|
6236
|
+
},
|
|
6237
|
+
});
|
|
6238
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
6239
|
+
// 只保留基础字段,过滤掉冗余信息,并简化Schema
|
|
6240
|
+
let simplifiedSchema = null;
|
|
6241
|
+
// 解析并简化Schema
|
|
6242
|
+
if (result.Data.Schema) {
|
|
6243
|
+
try {
|
|
6244
|
+
const schema = JSON.parse(result.Data.Schema);
|
|
6245
|
+
const properties = schema.properties || {};
|
|
6246
|
+
// 提取用户定义的字段(排除系统字段)
|
|
6247
|
+
const userFields = Object.keys(properties)
|
|
6248
|
+
.filter((key) => !properties[key]["x-system"]) // 排除系统字段
|
|
6249
|
+
.map((key) => {
|
|
6250
|
+
const field = properties[key];
|
|
6251
|
+
return parseFieldStructure(field, key, schema);
|
|
6252
|
+
});
|
|
6253
|
+
// 提取关联关系
|
|
6254
|
+
const relations = userFields
|
|
6255
|
+
.filter((field) => field.linkage)
|
|
6256
|
+
.map((field) => ({
|
|
6257
|
+
field: field.name,
|
|
6258
|
+
type: field.format,
|
|
6259
|
+
title: field.title,
|
|
6260
|
+
targetModel: field.linkage.parentDataSourceName,
|
|
6261
|
+
foreignKey: field.linkage.parentFieldKey,
|
|
6262
|
+
displayField: field.linkage.parentFieldTitle,
|
|
6263
|
+
}));
|
|
6264
|
+
simplifiedSchema = {
|
|
6265
|
+
userFields,
|
|
6266
|
+
relations,
|
|
6267
|
+
totalFields: Object.keys(properties).length,
|
|
6268
|
+
userFieldsCount: userFields.length,
|
|
6269
|
+
};
|
|
6258
6270
|
}
|
|
6259
|
-
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
|
|
6269
|
-
|
|
6270
|
-
|
|
6271
|
-
|
|
6272
|
-
|
|
6273
|
-
|
|
6274
|
-
|
|
6275
|
-
|
|
6276
|
-
|
|
6277
|
-
|
|
6278
|
-
|
|
6279
|
-
|
|
6280
|
-
|
|
6281
|
-
|
|
6282
|
-
|
|
6283
|
-
|
|
6284
|
-
|
|
6285
|
-
|
|
6286
|
-
|
|
6287
|
-
|
|
6288
|
-
|
|
6289
|
-
}
|
|
6290
|
-
}
|
|
6291
|
-
|
|
6292
|
-
|
|
6271
|
+
catch (e) {
|
|
6272
|
+
simplifiedSchema = { error: "Schema解析失败" };
|
|
6273
|
+
}
|
|
6274
|
+
}
|
|
6275
|
+
// 尝试生成Mermaid图表
|
|
6276
|
+
let mermaidDiagram = null;
|
|
6277
|
+
if (result.Data.Schema &&
|
|
6278
|
+
jsonSchemaToMermaid &&
|
|
6279
|
+
simplifiedSchema &&
|
|
6280
|
+
!simplifiedSchema.error) {
|
|
6281
|
+
try {
|
|
6282
|
+
const mainSchema = JSON.parse(result.Data.Schema);
|
|
6283
|
+
const schemasMap = {
|
|
6284
|
+
[name]: mainSchema,
|
|
6285
|
+
};
|
|
6286
|
+
// 获取关联模型的 schema
|
|
6287
|
+
if (simplifiedSchema.relations &&
|
|
6288
|
+
simplifiedSchema.relations.length > 0) {
|
|
6289
|
+
const relatedModelNames = [
|
|
6290
|
+
...new Set(simplifiedSchema.relations.map((rel) => rel.targetModel)),
|
|
6291
|
+
];
|
|
6292
|
+
for (const relatedModelName of relatedModelNames) {
|
|
6293
|
+
try {
|
|
6294
|
+
const relatedResult = await cloudbase
|
|
6295
|
+
.commonService("lowcode")
|
|
6296
|
+
.call({
|
|
6297
|
+
Action: "DescribeBasicDataSource",
|
|
6298
|
+
Param: {
|
|
6299
|
+
EnvId: currentEnvId,
|
|
6300
|
+
Name: relatedModelName,
|
|
6301
|
+
},
|
|
6302
|
+
});
|
|
6303
|
+
if (relatedResult.Data && relatedResult.Data.Schema) {
|
|
6304
|
+
schemasMap[relatedModelName] = JSON.parse(relatedResult.Data.Schema);
|
|
6293
6305
|
}
|
|
6294
6306
|
}
|
|
6307
|
+
catch (e) {
|
|
6308
|
+
console.warn(`获取关联模型 ${relatedModelName} 的 schema 失败:`, e);
|
|
6309
|
+
}
|
|
6295
6310
|
}
|
|
6296
|
-
// 调用 jsonSchemaToMermaid,传入正确的参数格式
|
|
6297
|
-
mermaidDiagram = jsonSchemaToMermaid(schemasMap);
|
|
6298
|
-
}
|
|
6299
|
-
catch (e) {
|
|
6300
|
-
console.warn("生成Mermaid图表失败:", e);
|
|
6301
6311
|
}
|
|
6312
|
+
// 调用 jsonSchemaToMermaid,传入正确的参数格式
|
|
6313
|
+
mermaidDiagram = jsonSchemaToMermaid(schemasMap);
|
|
6302
6314
|
}
|
|
6303
|
-
|
|
6304
|
-
|
|
6305
|
-
|
|
6306
|
-
|
|
6307
|
-
|
|
6308
|
-
|
|
6309
|
-
|
|
6310
|
-
|
|
6311
|
-
|
|
6315
|
+
catch (e) {
|
|
6316
|
+
console.warn("生成Mermaid图表失败:", e);
|
|
6317
|
+
}
|
|
6318
|
+
}
|
|
6319
|
+
const simplifiedModel = {
|
|
6320
|
+
DbInstanceType: result.Data.DbInstanceType,
|
|
6321
|
+
Title: result.Data.Title,
|
|
6322
|
+
Description: result.Data.Description,
|
|
6323
|
+
Name: result.Data.Name,
|
|
6324
|
+
UpdatedAt: result.Data.UpdatedAt,
|
|
6325
|
+
Schema: simplifiedSchema,
|
|
6326
|
+
mermaid: mermaidDiagram,
|
|
6327
|
+
};
|
|
6328
|
+
return {
|
|
6329
|
+
content: [
|
|
6330
|
+
{
|
|
6331
|
+
type: "text",
|
|
6332
|
+
text: JSON.stringify({
|
|
6333
|
+
success: true,
|
|
6334
|
+
action: "get",
|
|
6335
|
+
data: simplifiedModel,
|
|
6336
|
+
message: "获取数据模型成功",
|
|
6337
|
+
}, null, 2),
|
|
6338
|
+
},
|
|
6339
|
+
],
|
|
6340
|
+
};
|
|
6341
|
+
}
|
|
6342
|
+
catch (error) {
|
|
6343
|
+
if (error.original?.Code === "ResourceNotFound") {
|
|
6312
6344
|
return {
|
|
6313
6345
|
content: [
|
|
6314
6346
|
{
|
|
6315
6347
|
type: "text",
|
|
6316
6348
|
text: JSON.stringify({
|
|
6317
|
-
success:
|
|
6349
|
+
success: false,
|
|
6318
6350
|
action: "get",
|
|
6319
|
-
|
|
6320
|
-
message:
|
|
6351
|
+
error: "ResourceNotFound",
|
|
6352
|
+
message: `数据模型 ${name} 不存在`,
|
|
6321
6353
|
}, null, 2),
|
|
6322
6354
|
},
|
|
6323
6355
|
],
|
|
6324
6356
|
};
|
|
6325
6357
|
}
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
|
|
6329
|
-
|
|
6330
|
-
|
|
6331
|
-
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
|
|
6346
|
-
|
|
6347
|
-
|
|
6348
|
-
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
|
|
6355
|
-
|
|
6356
|
-
|
|
6358
|
+
throw error;
|
|
6359
|
+
}
|
|
6360
|
+
case "list":
|
|
6361
|
+
// 构建请求参数
|
|
6362
|
+
const listParams = {
|
|
6363
|
+
EnvId: currentEnvId,
|
|
6364
|
+
PageIndex: 1,
|
|
6365
|
+
PageSize: 1000,
|
|
6366
|
+
QuerySystemModel: true, // 查询系统模型
|
|
6367
|
+
QueryConnector: 0, // 0 表示数据模型
|
|
6368
|
+
};
|
|
6369
|
+
// 只有当 names 参数存在且不为空时才添加过滤条件
|
|
6370
|
+
if (names && names.length > 0) {
|
|
6371
|
+
listParams.DataSourceNames = names;
|
|
6372
|
+
}
|
|
6373
|
+
result = await cloudbase.commonService("lowcode").call({
|
|
6374
|
+
Action: "DescribeDataSourceList",
|
|
6375
|
+
Param: listParams,
|
|
6376
|
+
});
|
|
6377
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
6378
|
+
const models = result.Data?.Rows || [];
|
|
6379
|
+
// 只保留基础字段,list操作不返回Schema
|
|
6380
|
+
const simplifiedModels = models.map((model) => ({
|
|
6381
|
+
DbInstanceType: model.DbInstanceType,
|
|
6382
|
+
Title: model.Title,
|
|
6383
|
+
Description: model.Description,
|
|
6384
|
+
Name: model.Name,
|
|
6385
|
+
UpdatedAt: model.UpdatedAt,
|
|
6386
|
+
}));
|
|
6387
|
+
return {
|
|
6388
|
+
content: [
|
|
6389
|
+
{
|
|
6390
|
+
type: "text",
|
|
6391
|
+
text: JSON.stringify({
|
|
6392
|
+
success: true,
|
|
6393
|
+
action: "list",
|
|
6394
|
+
data: simplifiedModels,
|
|
6395
|
+
count: simplifiedModels.length,
|
|
6396
|
+
message: "获取数据模型列表成功",
|
|
6397
|
+
}, null, 2),
|
|
6398
|
+
},
|
|
6399
|
+
],
|
|
6400
|
+
};
|
|
6401
|
+
case "docs":
|
|
6402
|
+
if (!name) {
|
|
6403
|
+
throw new Error("生成SDK文档需要提供模型名称");
|
|
6404
|
+
}
|
|
6405
|
+
try {
|
|
6406
|
+
// 先获取模型信息
|
|
6357
6407
|
result = await cloudbase.commonService("lowcode").call({
|
|
6358
|
-
Action: "
|
|
6359
|
-
Param:
|
|
6408
|
+
Action: "DescribeBasicDataSource",
|
|
6409
|
+
Param: {
|
|
6410
|
+
EnvId: currentEnvId,
|
|
6411
|
+
Name: name,
|
|
6412
|
+
},
|
|
6360
6413
|
});
|
|
6361
6414
|
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
6362
|
-
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6415
|
+
if (!result.Data) {
|
|
6416
|
+
throw new Error(`数据模型 ${name} 不存在`);
|
|
6417
|
+
}
|
|
6418
|
+
// 解析Schema获取字段信息
|
|
6419
|
+
let userFields = [];
|
|
6420
|
+
let relations = [];
|
|
6421
|
+
if (result.Data.Schema) {
|
|
6422
|
+
try {
|
|
6423
|
+
const schema = JSON.parse(result.Data.Schema);
|
|
6424
|
+
const properties = schema.properties || {};
|
|
6425
|
+
// 提取用户定义的字段
|
|
6426
|
+
userFields = Object.keys(properties)
|
|
6427
|
+
.filter((key) => !properties[key]["x-system"])
|
|
6428
|
+
.map((key) => {
|
|
6429
|
+
const field = properties[key];
|
|
6430
|
+
return parseFieldStructure(field, key, schema);
|
|
6431
|
+
});
|
|
6432
|
+
// 提取关联关系
|
|
6433
|
+
relations = userFields
|
|
6434
|
+
.filter((field) => field.linkage)
|
|
6435
|
+
.map((field) => ({
|
|
6436
|
+
field: field.name,
|
|
6437
|
+
type: field.format,
|
|
6438
|
+
title: field.title,
|
|
6439
|
+
targetModel: field.linkage.parentDataSourceName,
|
|
6440
|
+
foreignKey: field.linkage.parentFieldKey,
|
|
6441
|
+
displayField: field.linkage.parentFieldTitle,
|
|
6442
|
+
}));
|
|
6443
|
+
}
|
|
6444
|
+
catch (e) {
|
|
6445
|
+
// Schema解析失败,使用空数组
|
|
6446
|
+
console.error("Schema解析失败", e);
|
|
6447
|
+
}
|
|
6448
|
+
}
|
|
6449
|
+
// 生成SDK使用文档
|
|
6450
|
+
const docs = generateSDKDocs(result.Data.Name, result.Data.Title, userFields, relations);
|
|
6371
6451
|
return {
|
|
6372
6452
|
content: [
|
|
6373
6453
|
{
|
|
6374
6454
|
type: "text",
|
|
6375
6455
|
text: JSON.stringify({
|
|
6376
6456
|
success: true,
|
|
6377
|
-
action: "
|
|
6378
|
-
|
|
6379
|
-
|
|
6380
|
-
|
|
6457
|
+
action: "docs",
|
|
6458
|
+
modelName: name,
|
|
6459
|
+
modelTitle: result.Data.Title,
|
|
6460
|
+
docs,
|
|
6461
|
+
message: "SDK使用文档生成成功",
|
|
6381
6462
|
}, null, 2),
|
|
6382
6463
|
},
|
|
6383
6464
|
],
|
|
6384
6465
|
};
|
|
6385
|
-
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
}
|
|
6389
|
-
try {
|
|
6390
|
-
// 先获取模型信息
|
|
6391
|
-
result = await cloudbase.commonService("lowcode").call({
|
|
6392
|
-
Action: "DescribeBasicDataSource",
|
|
6393
|
-
Param: {
|
|
6394
|
-
EnvId: currentEnvId,
|
|
6395
|
-
Name: name,
|
|
6396
|
-
},
|
|
6397
|
-
});
|
|
6398
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
6399
|
-
if (!result.Data) {
|
|
6400
|
-
throw new Error(`数据模型 ${name} 不存在`);
|
|
6401
|
-
}
|
|
6402
|
-
// 解析Schema获取字段信息
|
|
6403
|
-
let userFields = [];
|
|
6404
|
-
let relations = [];
|
|
6405
|
-
if (result.Data.Schema) {
|
|
6406
|
-
try {
|
|
6407
|
-
const schema = JSON.parse(result.Data.Schema);
|
|
6408
|
-
const properties = schema.properties || {};
|
|
6409
|
-
// 提取用户定义的字段
|
|
6410
|
-
userFields = Object.keys(properties)
|
|
6411
|
-
.filter((key) => !properties[key]["x-system"])
|
|
6412
|
-
.map((key) => {
|
|
6413
|
-
const field = properties[key];
|
|
6414
|
-
return parseFieldStructure(field, key, schema);
|
|
6415
|
-
});
|
|
6416
|
-
// 提取关联关系
|
|
6417
|
-
relations = userFields
|
|
6418
|
-
.filter((field) => field.linkage)
|
|
6419
|
-
.map((field) => ({
|
|
6420
|
-
field: field.name,
|
|
6421
|
-
type: field.format,
|
|
6422
|
-
title: field.title,
|
|
6423
|
-
targetModel: field.linkage.parentDataSourceName,
|
|
6424
|
-
foreignKey: field.linkage.parentFieldKey,
|
|
6425
|
-
displayField: field.linkage.parentFieldTitle,
|
|
6426
|
-
}));
|
|
6427
|
-
}
|
|
6428
|
-
catch (e) {
|
|
6429
|
-
// Schema解析失败,使用空数组
|
|
6430
|
-
console.error("Schema解析失败", e);
|
|
6431
|
-
}
|
|
6432
|
-
}
|
|
6433
|
-
// 生成SDK使用文档
|
|
6434
|
-
const docs = generateSDKDocs(result.Data.Name, result.Data.Title, userFields, relations);
|
|
6466
|
+
}
|
|
6467
|
+
catch (error) {
|
|
6468
|
+
if (error.original?.Code === "ResourceNotFound") {
|
|
6435
6469
|
return {
|
|
6436
6470
|
content: [
|
|
6437
6471
|
{
|
|
6438
6472
|
type: "text",
|
|
6439
6473
|
text: JSON.stringify({
|
|
6440
|
-
success:
|
|
6474
|
+
success: false,
|
|
6441
6475
|
action: "docs",
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
docs,
|
|
6445
|
-
message: "SDK使用文档生成成功",
|
|
6476
|
+
error: "ResourceNotFound",
|
|
6477
|
+
message: `数据模型 ${name} 不存在`,
|
|
6446
6478
|
}, null, 2),
|
|
6447
6479
|
},
|
|
6448
6480
|
],
|
|
6449
6481
|
};
|
|
6450
6482
|
}
|
|
6451
|
-
|
|
6452
|
-
|
|
6453
|
-
|
|
6454
|
-
|
|
6455
|
-
{
|
|
6456
|
-
type: "text",
|
|
6457
|
-
text: JSON.stringify({
|
|
6458
|
-
success: false,
|
|
6459
|
-
action: "docs",
|
|
6460
|
-
error: "ResourceNotFound",
|
|
6461
|
-
message: `数据模型 ${name} 不存在`,
|
|
6462
|
-
}, null, 2),
|
|
6463
|
-
},
|
|
6464
|
-
],
|
|
6465
|
-
};
|
|
6466
|
-
}
|
|
6467
|
-
throw error;
|
|
6468
|
-
}
|
|
6469
|
-
default:
|
|
6470
|
-
throw new Error(`不支持的操作类型: ${action}`);
|
|
6471
|
-
}
|
|
6472
|
-
}
|
|
6473
|
-
catch (error) {
|
|
6474
|
-
return {
|
|
6475
|
-
content: [
|
|
6476
|
-
{
|
|
6477
|
-
type: "text",
|
|
6478
|
-
text: JSON.stringify({
|
|
6479
|
-
success: false,
|
|
6480
|
-
action,
|
|
6481
|
-
error: error.message || error.original?.Message || "未知错误",
|
|
6482
|
-
code: error.original?.Code,
|
|
6483
|
-
message: "数据模型操作失败",
|
|
6484
|
-
}, null, 2),
|
|
6485
|
-
},
|
|
6486
|
-
],
|
|
6487
|
-
};
|
|
6483
|
+
throw error;
|
|
6484
|
+
}
|
|
6485
|
+
default:
|
|
6486
|
+
throw new Error(`不支持的操作类型: ${action}`);
|
|
6488
6487
|
}
|
|
6489
6488
|
});
|
|
6490
6489
|
// modifyDataModel - 数据模型修改工具(创建/更新)
|
|
@@ -6557,126 +6556,108 @@ classDiagram
|
|
|
6557
6556
|
category: "database",
|
|
6558
6557
|
},
|
|
6559
6558
|
}, async ({ mermaidDiagram, action = "create", publish = false, dbInstanceType = "MYSQL", }) => {
|
|
6560
|
-
|
|
6561
|
-
|
|
6562
|
-
|
|
6563
|
-
|
|
6564
|
-
const schemas = mermaidToJsonSchema(mermaidDiagram);
|
|
6565
|
-
if (!schemas || Object.keys(schemas).length === 0) {
|
|
6566
|
-
return {
|
|
6567
|
-
content: [
|
|
6568
|
-
{
|
|
6569
|
-
type: "text",
|
|
6570
|
-
text: JSON.stringify({
|
|
6571
|
-
success: false,
|
|
6572
|
-
error: "No schemas generated from Mermaid diagram",
|
|
6573
|
-
message: "无法从Mermaid图表生成数据模型Schema",
|
|
6574
|
-
}, null, 2),
|
|
6575
|
-
},
|
|
6576
|
-
],
|
|
6577
|
-
};
|
|
6578
|
-
}
|
|
6579
|
-
// 创建数据模型列表
|
|
6580
|
-
const createDataModelList = Object.entries(schemas).map(([name, schema]) => {
|
|
6581
|
-
return {
|
|
6582
|
-
CreateSource: "cloudbase_create",
|
|
6583
|
-
Creator: null,
|
|
6584
|
-
DbLinkName: null,
|
|
6585
|
-
Description: schema.description ||
|
|
6586
|
-
`${schema.title || name}数据模型`,
|
|
6587
|
-
Schema: JSON.stringify(createBackendSchemaParams(schema)),
|
|
6588
|
-
Title: schema.title || name,
|
|
6589
|
-
Name: name,
|
|
6590
|
-
TableNameRule: "only_name",
|
|
6591
|
-
};
|
|
6592
|
-
});
|
|
6593
|
-
// 调用批量创建数据模型API
|
|
6594
|
-
const result = await cloudbase.commonService("lowcode").call({
|
|
6595
|
-
Action: "BatchCreateDataModelList",
|
|
6596
|
-
Param: {
|
|
6597
|
-
CreateDataModelList: createDataModelList,
|
|
6598
|
-
Creator: null,
|
|
6599
|
-
DbInstanceType: dbInstanceType,
|
|
6600
|
-
EnvId: currentEnvId,
|
|
6601
|
-
},
|
|
6602
|
-
});
|
|
6603
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
6604
|
-
const taskId = result.Data?.TaskId;
|
|
6605
|
-
if (!taskId) {
|
|
6606
|
-
return {
|
|
6607
|
-
content: [
|
|
6608
|
-
{
|
|
6609
|
-
type: "text",
|
|
6610
|
-
text: JSON.stringify({
|
|
6611
|
-
success: false,
|
|
6612
|
-
requestId: result.RequestId,
|
|
6613
|
-
error: "No TaskId returned",
|
|
6614
|
-
message: "创建任务失败,未返回任务ID",
|
|
6615
|
-
}, null, 2),
|
|
6616
|
-
},
|
|
6617
|
-
],
|
|
6618
|
-
};
|
|
6619
|
-
}
|
|
6620
|
-
// 轮询任务状态直至完成或超时
|
|
6621
|
-
const maxWaitTime = 30000; // 30秒超时
|
|
6622
|
-
const startTime = Date.now();
|
|
6623
|
-
let status = "init";
|
|
6624
|
-
let statusResult = null;
|
|
6625
|
-
while (status === "init" && Date.now() - startTime < maxWaitTime) {
|
|
6626
|
-
await new Promise((resolve) => setTimeout(resolve, 2000)); // 等待2秒
|
|
6627
|
-
statusResult = await cloudbase.commonService("lowcode").call({
|
|
6628
|
-
Action: "QueryModelTaskStatus",
|
|
6629
|
-
Param: {
|
|
6630
|
-
EnvId: currentEnvId,
|
|
6631
|
-
TaskId: taskId,
|
|
6632
|
-
},
|
|
6633
|
-
});
|
|
6634
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, statusResult);
|
|
6635
|
-
status = statusResult.Data?.Status || "init";
|
|
6636
|
-
}
|
|
6637
|
-
// 返回最终结果
|
|
6638
|
-
const models = Object.keys(schemas);
|
|
6639
|
-
const successModels = statusResult?.Data?.SuccessResourceIdList || [];
|
|
6640
|
-
const failedModels = models.filter((model) => !successModels.includes(model));
|
|
6559
|
+
const cloudbase = await getManager();
|
|
6560
|
+
let currentEnvId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
6561
|
+
const schemas = mermaidToJsonSchema(mermaidDiagram);
|
|
6562
|
+
if (!schemas || Object.keys(schemas).length === 0) {
|
|
6641
6563
|
return {
|
|
6642
6564
|
content: [
|
|
6643
6565
|
{
|
|
6644
6566
|
type: "text",
|
|
6645
6567
|
text: JSON.stringify({
|
|
6646
|
-
success:
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
models: models,
|
|
6650
|
-
successModels: successModels,
|
|
6651
|
-
failedModels: failedModels,
|
|
6652
|
-
status: status,
|
|
6653
|
-
action: action,
|
|
6654
|
-
message: status === "success"
|
|
6655
|
-
? `数据模型${action === "create" ? "创建" : "更新"}成功,共处理${models.length}个模型`
|
|
6656
|
-
: status === "init"
|
|
6657
|
-
? `任务超时,任务ID: ${taskId},请稍后手动查询状态`
|
|
6658
|
-
: `数据模型${action === "create" ? "创建" : "更新"}失败`,
|
|
6659
|
-
taskResult: statusResult?.Data,
|
|
6568
|
+
success: false,
|
|
6569
|
+
error: "No schemas generated from Mermaid diagram",
|
|
6570
|
+
message: "无法从Mermaid图表生成数据模型Schema",
|
|
6660
6571
|
}, null, 2),
|
|
6661
6572
|
},
|
|
6662
6573
|
],
|
|
6663
6574
|
};
|
|
6664
6575
|
}
|
|
6665
|
-
|
|
6576
|
+
// 创建数据模型列表
|
|
6577
|
+
const createDataModelList = Object.entries(schemas).map(([name, schema]) => {
|
|
6578
|
+
return {
|
|
6579
|
+
CreateSource: "cloudbase_create",
|
|
6580
|
+
Creator: null,
|
|
6581
|
+
DbLinkName: null,
|
|
6582
|
+
Description: schema.description ||
|
|
6583
|
+
`${schema.title || name}数据模型`,
|
|
6584
|
+
Schema: JSON.stringify(createBackendSchemaParams(schema)),
|
|
6585
|
+
Title: schema.title || name,
|
|
6586
|
+
Name: name,
|
|
6587
|
+
TableNameRule: "only_name",
|
|
6588
|
+
};
|
|
6589
|
+
});
|
|
6590
|
+
// 调用批量创建数据模型API
|
|
6591
|
+
const result = await cloudbase.commonService("lowcode").call({
|
|
6592
|
+
Action: "BatchCreateDataModelList",
|
|
6593
|
+
Param: {
|
|
6594
|
+
CreateDataModelList: createDataModelList,
|
|
6595
|
+
Creator: null,
|
|
6596
|
+
DbInstanceType: dbInstanceType,
|
|
6597
|
+
EnvId: currentEnvId,
|
|
6598
|
+
},
|
|
6599
|
+
});
|
|
6600
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
6601
|
+
const taskId = result.Data?.TaskId;
|
|
6602
|
+
if (!taskId) {
|
|
6666
6603
|
return {
|
|
6667
6604
|
content: [
|
|
6668
6605
|
{
|
|
6669
6606
|
type: "text",
|
|
6670
6607
|
text: JSON.stringify({
|
|
6671
6608
|
success: false,
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
message: "
|
|
6609
|
+
requestId: result.RequestId,
|
|
6610
|
+
error: "No TaskId returned",
|
|
6611
|
+
message: "创建任务失败,未返回任务ID",
|
|
6675
6612
|
}, null, 2),
|
|
6676
6613
|
},
|
|
6677
6614
|
],
|
|
6678
6615
|
};
|
|
6679
6616
|
}
|
|
6617
|
+
// 轮询任务状态直至完成或超时
|
|
6618
|
+
const maxWaitTime = 30000; // 30秒超时
|
|
6619
|
+
const startTime = Date.now();
|
|
6620
|
+
let status = "init";
|
|
6621
|
+
let statusResult = null;
|
|
6622
|
+
while (status === "init" && Date.now() - startTime < maxWaitTime) {
|
|
6623
|
+
await new Promise((resolve) => setTimeout(resolve, 2000)); // 等待2秒
|
|
6624
|
+
statusResult = await cloudbase.commonService("lowcode").call({
|
|
6625
|
+
Action: "QueryModelTaskStatus",
|
|
6626
|
+
Param: {
|
|
6627
|
+
EnvId: currentEnvId,
|
|
6628
|
+
TaskId: taskId,
|
|
6629
|
+
},
|
|
6630
|
+
});
|
|
6631
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, statusResult);
|
|
6632
|
+
status = statusResult.Data?.Status || "init";
|
|
6633
|
+
}
|
|
6634
|
+
// 返回最终结果
|
|
6635
|
+
const models = Object.keys(schemas);
|
|
6636
|
+
const successModels = statusResult?.Data?.SuccessResourceIdList || [];
|
|
6637
|
+
const failedModels = models.filter((model) => !successModels.includes(model));
|
|
6638
|
+
return {
|
|
6639
|
+
content: [
|
|
6640
|
+
{
|
|
6641
|
+
type: "text",
|
|
6642
|
+
text: JSON.stringify({
|
|
6643
|
+
success: status === "success",
|
|
6644
|
+
requestId: result.RequestId,
|
|
6645
|
+
taskId: taskId,
|
|
6646
|
+
models: models,
|
|
6647
|
+
successModels: successModels,
|
|
6648
|
+
failedModels: failedModels,
|
|
6649
|
+
status: status,
|
|
6650
|
+
action: action,
|
|
6651
|
+
message: status === "success"
|
|
6652
|
+
? `数据模型${action === "create" ? "创建" : "更新"}成功,共处理${models.length}个模型`
|
|
6653
|
+
: status === "init"
|
|
6654
|
+
? `任务超时,任务ID: ${taskId},请稍后手动查询状态`
|
|
6655
|
+
: `数据模型${action === "create" ? "创建" : "更新"}失败`,
|
|
6656
|
+
taskResult: statusResult?.Data,
|
|
6657
|
+
}, null, 2),
|
|
6658
|
+
},
|
|
6659
|
+
],
|
|
6660
|
+
};
|
|
6680
6661
|
});
|
|
6681
6662
|
}
|
|
6682
6663
|
|
|
@@ -7491,41 +7472,25 @@ function registerInviteCodeTools(server) {
|
|
|
7491
7472
|
]
|
|
7492
7473
|
};
|
|
7493
7474
|
}
|
|
7494
|
-
|
|
7495
|
-
|
|
7496
|
-
|
|
7497
|
-
|
|
7498
|
-
|
|
7499
|
-
|
|
7500
|
-
|
|
7501
|
-
|
|
7502
|
-
|
|
7503
|
-
|
|
7504
|
-
|
|
7505
|
-
|
|
7506
|
-
|
|
7507
|
-
|
|
7508
|
-
|
|
7509
|
-
|
|
7510
|
-
|
|
7511
|
-
|
|
7512
|
-
|
|
7513
|
-
};
|
|
7514
|
-
}
|
|
7515
|
-
catch (e) {
|
|
7516
|
-
return {
|
|
7517
|
-
content: [
|
|
7518
|
-
{
|
|
7519
|
-
type: "text",
|
|
7520
|
-
text: JSON.stringify({
|
|
7521
|
-
ErrorCode: e.code || 'Exception',
|
|
7522
|
-
ErrorMsg: '激活失败:' + e.message,
|
|
7523
|
-
RequestId: e.RequestId || ''
|
|
7524
|
-
}, null, 2)
|
|
7525
|
-
}
|
|
7526
|
-
]
|
|
7527
|
-
};
|
|
7528
|
-
}
|
|
7475
|
+
const manager = await getManager();
|
|
7476
|
+
const EnvId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
7477
|
+
const result = await manager.commonService().call({
|
|
7478
|
+
Action: 'ActivateInviteCode',
|
|
7479
|
+
Param: { InviteCode, EnvId }
|
|
7480
|
+
});
|
|
7481
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
7482
|
+
return {
|
|
7483
|
+
content: [
|
|
7484
|
+
{
|
|
7485
|
+
type: "text",
|
|
7486
|
+
text: JSON.stringify({
|
|
7487
|
+
ErrorCode: result?.ErrorCode || '',
|
|
7488
|
+
ErrorMsg: result?.ErrorMsg || '',
|
|
7489
|
+
RequestId: result?.RequestId || ''
|
|
7490
|
+
}, null, 2)
|
|
7491
|
+
}
|
|
7492
|
+
]
|
|
7493
|
+
};
|
|
7529
7494
|
});
|
|
7530
7495
|
}
|
|
7531
7496
|
|
|
@@ -7570,94 +7535,78 @@ function registerStorageTools(server) {
|
|
|
7570
7535
|
category: "storage"
|
|
7571
7536
|
}
|
|
7572
7537
|
}, async (args) => {
|
|
7573
|
-
|
|
7574
|
-
|
|
7575
|
-
|
|
7576
|
-
|
|
7577
|
-
|
|
7578
|
-
|
|
7579
|
-
|
|
7580
|
-
|
|
7581
|
-
|
|
7582
|
-
|
|
7583
|
-
|
|
7584
|
-
|
|
7585
|
-
|
|
7586
|
-
|
|
7587
|
-
|
|
7588
|
-
|
|
7589
|
-
|
|
7590
|
-
|
|
7591
|
-
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
|
|
7596
|
-
|
|
7597
|
-
|
|
7598
|
-
|
|
7599
|
-
|
|
7600
|
-
|
|
7601
|
-
|
|
7602
|
-
|
|
7603
|
-
|
|
7604
|
-
|
|
7605
|
-
|
|
7606
|
-
|
|
7607
|
-
|
|
7608
|
-
|
|
7609
|
-
|
|
7610
|
-
|
|
7611
|
-
|
|
7612
|
-
|
|
7613
|
-
|
|
7614
|
-
|
|
7615
|
-
|
|
7616
|
-
|
|
7617
|
-
|
|
7618
|
-
|
|
7619
|
-
|
|
7620
|
-
|
|
7621
|
-
|
|
7622
|
-
|
|
7623
|
-
|
|
7624
|
-
|
|
7625
|
-
|
|
7626
|
-
|
|
7627
|
-
|
|
7628
|
-
|
|
7629
|
-
|
|
7630
|
-
|
|
7631
|
-
|
|
7632
|
-
|
|
7633
|
-
|
|
7634
|
-
|
|
7635
|
-
|
|
7636
|
-
|
|
7637
|
-
|
|
7638
|
-
|
|
7639
|
-
|
|
7640
|
-
|
|
7641
|
-
|
|
7642
|
-
};
|
|
7643
|
-
}
|
|
7644
|
-
default:
|
|
7645
|
-
throw new Error(`Unsupported action: ${input.action}`);
|
|
7538
|
+
const input = args;
|
|
7539
|
+
const manager = await getManager();
|
|
7540
|
+
if (!manager) {
|
|
7541
|
+
throw new Error("Failed to initialize CloudBase manager. Please check your credentials and environment configuration.");
|
|
7542
|
+
}
|
|
7543
|
+
const storageService = manager.storage;
|
|
7544
|
+
switch (input.action) {
|
|
7545
|
+
case 'list': {
|
|
7546
|
+
const result = await storageService.listDirectoryFiles(input.cloudPath);
|
|
7547
|
+
return {
|
|
7548
|
+
content: [
|
|
7549
|
+
{
|
|
7550
|
+
type: "text",
|
|
7551
|
+
text: JSON.stringify({
|
|
7552
|
+
success: true,
|
|
7553
|
+
data: {
|
|
7554
|
+
action: 'list',
|
|
7555
|
+
cloudPath: input.cloudPath,
|
|
7556
|
+
files: result || [],
|
|
7557
|
+
totalCount: result?.length || 0
|
|
7558
|
+
},
|
|
7559
|
+
message: `Successfully listed ${result?.length || 0} files in directory '${input.cloudPath}'`
|
|
7560
|
+
}, null, 2)
|
|
7561
|
+
}
|
|
7562
|
+
]
|
|
7563
|
+
};
|
|
7564
|
+
}
|
|
7565
|
+
case 'info': {
|
|
7566
|
+
const result = await storageService.getFileInfo(input.cloudPath);
|
|
7567
|
+
return {
|
|
7568
|
+
content: [
|
|
7569
|
+
{
|
|
7570
|
+
type: "text",
|
|
7571
|
+
text: JSON.stringify({
|
|
7572
|
+
success: true,
|
|
7573
|
+
data: {
|
|
7574
|
+
action: 'info',
|
|
7575
|
+
cloudPath: input.cloudPath,
|
|
7576
|
+
fileInfo: result
|
|
7577
|
+
},
|
|
7578
|
+
message: `Successfully retrieved file info for '${input.cloudPath}'`
|
|
7579
|
+
}, null, 2)
|
|
7580
|
+
}
|
|
7581
|
+
]
|
|
7582
|
+
};
|
|
7583
|
+
}
|
|
7584
|
+
case 'url': {
|
|
7585
|
+
const result = await storageService.getTemporaryUrl([{
|
|
7586
|
+
cloudPath: input.cloudPath,
|
|
7587
|
+
maxAge: input.maxAge || 3600
|
|
7588
|
+
}]);
|
|
7589
|
+
return {
|
|
7590
|
+
content: [
|
|
7591
|
+
{
|
|
7592
|
+
type: "text",
|
|
7593
|
+
text: JSON.stringify({
|
|
7594
|
+
success: true,
|
|
7595
|
+
data: {
|
|
7596
|
+
action: 'url',
|
|
7597
|
+
cloudPath: input.cloudPath,
|
|
7598
|
+
temporaryUrl: result[0]?.url || "",
|
|
7599
|
+
expireTime: `${input.maxAge || 3600}秒`,
|
|
7600
|
+
fileId: result[0]?.fileId || ""
|
|
7601
|
+
},
|
|
7602
|
+
message: `Successfully generated temporary URL for '${input.cloudPath}'`
|
|
7603
|
+
}, null, 2)
|
|
7604
|
+
}
|
|
7605
|
+
]
|
|
7606
|
+
};
|
|
7646
7607
|
}
|
|
7647
|
-
|
|
7648
|
-
|
|
7649
|
-
return {
|
|
7650
|
-
content: [
|
|
7651
|
-
{
|
|
7652
|
-
type: "text",
|
|
7653
|
-
text: JSON.stringify({
|
|
7654
|
-
success: false,
|
|
7655
|
-
error: error.message || 'Unknown error occurred',
|
|
7656
|
-
message: `Failed to query storage information. Please check your permissions and parameters.`
|
|
7657
|
-
}, null, 2)
|
|
7658
|
-
}
|
|
7659
|
-
]
|
|
7660
|
-
};
|
|
7608
|
+
default:
|
|
7609
|
+
throw new Error(`Unsupported action: ${input.action}`);
|
|
7661
7610
|
}
|
|
7662
7611
|
});
|
|
7663
7612
|
// Tool 2: manageStorage - 管理存储文件(写操作)
|
|
@@ -7673,151 +7622,128 @@ function registerStorageTools(server) {
|
|
|
7673
7622
|
category: "storage"
|
|
7674
7623
|
}
|
|
7675
7624
|
}, async (args) => {
|
|
7676
|
-
|
|
7677
|
-
|
|
7678
|
-
|
|
7679
|
-
|
|
7680
|
-
|
|
7681
|
-
|
|
7682
|
-
|
|
7683
|
-
|
|
7684
|
-
|
|
7685
|
-
|
|
7686
|
-
|
|
7687
|
-
|
|
7688
|
-
|
|
7689
|
-
|
|
7690
|
-
|
|
7691
|
-
|
|
7692
|
-
}
|
|
7693
|
-
});
|
|
7694
|
-
}
|
|
7695
|
-
else {
|
|
7696
|
-
// 上传文件
|
|
7697
|
-
await storageService.uploadFile({
|
|
7698
|
-
localPath: input.localPath,
|
|
7699
|
-
cloudPath: input.cloudPath,
|
|
7700
|
-
onProgress: (progressData) => {
|
|
7701
|
-
console.log("Upload file progress:", progressData);
|
|
7702
|
-
}
|
|
7703
|
-
});
|
|
7704
|
-
}
|
|
7705
|
-
// 获取文件临时下载地址
|
|
7706
|
-
const fileUrls = await storageService.getTemporaryUrl([{
|
|
7707
|
-
cloudPath: input.cloudPath,
|
|
7708
|
-
maxAge: 3600 // 临时链接有效期1小时
|
|
7709
|
-
}]);
|
|
7710
|
-
return {
|
|
7711
|
-
content: [
|
|
7712
|
-
{
|
|
7713
|
-
type: "text",
|
|
7714
|
-
text: JSON.stringify({
|
|
7715
|
-
success: true,
|
|
7716
|
-
data: {
|
|
7717
|
-
action: 'upload',
|
|
7718
|
-
localPath: input.localPath,
|
|
7719
|
-
cloudPath: input.cloudPath,
|
|
7720
|
-
isDirectory: input.isDirectory,
|
|
7721
|
-
temporaryUrl: fileUrls[0]?.url || "",
|
|
7722
|
-
expireTime: "1小时"
|
|
7723
|
-
},
|
|
7724
|
-
message: `Successfully uploaded ${input.isDirectory ? 'directory' : 'file'} from '${input.localPath}' to '${input.cloudPath}'`
|
|
7725
|
-
}, null, 2)
|
|
7726
|
-
}
|
|
7727
|
-
]
|
|
7728
|
-
};
|
|
7625
|
+
const input = args;
|
|
7626
|
+
const manager = await getManager();
|
|
7627
|
+
if (!manager) {
|
|
7628
|
+
throw new Error("Failed to initialize CloudBase manager. Please check your credentials and environment configuration.");
|
|
7629
|
+
}
|
|
7630
|
+
const storageService = manager.storage;
|
|
7631
|
+
switch (input.action) {
|
|
7632
|
+
case 'upload': {
|
|
7633
|
+
if (input.isDirectory) {
|
|
7634
|
+
await storageService.uploadDirectory({
|
|
7635
|
+
localPath: input.localPath,
|
|
7636
|
+
cloudPath: input.cloudPath,
|
|
7637
|
+
onProgress: (progressData) => {
|
|
7638
|
+
console.log("Upload directory progress:", progressData);
|
|
7639
|
+
}
|
|
7640
|
+
});
|
|
7729
7641
|
}
|
|
7730
|
-
|
|
7731
|
-
|
|
7732
|
-
|
|
7733
|
-
|
|
7734
|
-
|
|
7735
|
-
|
|
7736
|
-
}
|
|
7737
|
-
}
|
|
7738
|
-
else {
|
|
7739
|
-
// 下载文件
|
|
7740
|
-
await storageService.downloadFile({
|
|
7741
|
-
cloudPath: input.cloudPath,
|
|
7742
|
-
localPath: input.localPath
|
|
7743
|
-
});
|
|
7744
|
-
}
|
|
7745
|
-
return {
|
|
7746
|
-
content: [
|
|
7747
|
-
{
|
|
7748
|
-
type: "text",
|
|
7749
|
-
text: JSON.stringify({
|
|
7750
|
-
success: true,
|
|
7751
|
-
data: {
|
|
7752
|
-
action: 'download',
|
|
7753
|
-
cloudPath: input.cloudPath,
|
|
7754
|
-
localPath: input.localPath,
|
|
7755
|
-
isDirectory: input.isDirectory
|
|
7756
|
-
},
|
|
7757
|
-
message: `Successfully downloaded ${input.isDirectory ? 'directory' : 'file'} from '${input.cloudPath}' to '${input.localPath}'`
|
|
7758
|
-
}, null, 2)
|
|
7759
|
-
}
|
|
7760
|
-
]
|
|
7761
|
-
};
|
|
7642
|
+
else {
|
|
7643
|
+
await storageService.uploadFile({
|
|
7644
|
+
localPath: input.localPath,
|
|
7645
|
+
cloudPath: input.cloudPath,
|
|
7646
|
+
onProgress: (progressData) => {
|
|
7647
|
+
console.log("Upload file progress:", progressData);
|
|
7648
|
+
}
|
|
7649
|
+
});
|
|
7762
7650
|
}
|
|
7763
|
-
|
|
7764
|
-
|
|
7765
|
-
|
|
7766
|
-
|
|
7767
|
-
|
|
7768
|
-
|
|
7769
|
-
|
|
7770
|
-
|
|
7771
|
-
|
|
7772
|
-
|
|
7773
|
-
|
|
7774
|
-
|
|
7775
|
-
|
|
7776
|
-
|
|
7777
|
-
|
|
7778
|
-
|
|
7779
|
-
|
|
7780
|
-
|
|
7781
|
-
|
|
7782
|
-
|
|
7783
|
-
|
|
7784
|
-
|
|
7785
|
-
|
|
7651
|
+
const fileUrls = await storageService.getTemporaryUrl([{
|
|
7652
|
+
cloudPath: input.cloudPath,
|
|
7653
|
+
maxAge: 3600
|
|
7654
|
+
}]);
|
|
7655
|
+
return {
|
|
7656
|
+
content: [
|
|
7657
|
+
{
|
|
7658
|
+
type: "text",
|
|
7659
|
+
text: JSON.stringify({
|
|
7660
|
+
success: true,
|
|
7661
|
+
data: {
|
|
7662
|
+
action: 'upload',
|
|
7663
|
+
localPath: input.localPath,
|
|
7664
|
+
cloudPath: input.cloudPath,
|
|
7665
|
+
isDirectory: input.isDirectory,
|
|
7666
|
+
temporaryUrl: fileUrls[0]?.url || "",
|
|
7667
|
+
expireTime: "1小时"
|
|
7668
|
+
},
|
|
7669
|
+
message: `Successfully uploaded ${input.isDirectory ? 'directory' : 'file'} from '${input.localPath}' to '${input.cloudPath}'`
|
|
7670
|
+
}, null, 2)
|
|
7671
|
+
}
|
|
7672
|
+
]
|
|
7673
|
+
};
|
|
7674
|
+
}
|
|
7675
|
+
case 'download': {
|
|
7676
|
+
if (input.isDirectory) {
|
|
7677
|
+
await storageService.downloadDirectory({
|
|
7678
|
+
cloudPath: input.cloudPath,
|
|
7679
|
+
localPath: input.localPath
|
|
7680
|
+
});
|
|
7681
|
+
}
|
|
7682
|
+
else {
|
|
7683
|
+
await storageService.downloadFile({
|
|
7684
|
+
cloudPath: input.cloudPath,
|
|
7685
|
+
localPath: input.localPath
|
|
7686
|
+
});
|
|
7687
|
+
}
|
|
7688
|
+
return {
|
|
7689
|
+
content: [
|
|
7690
|
+
{
|
|
7691
|
+
type: "text",
|
|
7692
|
+
text: JSON.stringify({
|
|
7693
|
+
success: true,
|
|
7694
|
+
data: {
|
|
7695
|
+
action: 'download',
|
|
7696
|
+
cloudPath: input.cloudPath,
|
|
7697
|
+
localPath: input.localPath,
|
|
7698
|
+
isDirectory: input.isDirectory
|
|
7699
|
+
},
|
|
7700
|
+
message: `Successfully downloaded ${input.isDirectory ? 'directory' : 'file'} from '${input.cloudPath}' to '${input.localPath}'`
|
|
7701
|
+
}, null, 2)
|
|
7702
|
+
}
|
|
7703
|
+
]
|
|
7704
|
+
};
|
|
7705
|
+
}
|
|
7706
|
+
case 'delete': {
|
|
7707
|
+
if (!input.force) {
|
|
7786
7708
|
return {
|
|
7787
7709
|
content: [
|
|
7788
7710
|
{
|
|
7789
7711
|
type: "text",
|
|
7790
7712
|
text: JSON.stringify({
|
|
7791
|
-
success:
|
|
7792
|
-
|
|
7793
|
-
|
|
7794
|
-
cloudPath: input.cloudPath,
|
|
7795
|
-
isDirectory: input.isDirectory,
|
|
7796
|
-
deleted: true
|
|
7797
|
-
},
|
|
7798
|
-
message: `Successfully deleted ${input.isDirectory ? 'directory' : 'file'} '${input.cloudPath}'`
|
|
7713
|
+
success: false,
|
|
7714
|
+
error: "Delete operation requires confirmation",
|
|
7715
|
+
message: "Please set force: true to confirm deletion. This action cannot be undone."
|
|
7799
7716
|
}, null, 2)
|
|
7800
7717
|
}
|
|
7801
7718
|
]
|
|
7802
7719
|
};
|
|
7803
7720
|
}
|
|
7804
|
-
|
|
7805
|
-
|
|
7721
|
+
if (input.isDirectory) {
|
|
7722
|
+
await storageService.deleteDirectory(input.cloudPath);
|
|
7723
|
+
}
|
|
7724
|
+
else {
|
|
7725
|
+
await storageService.deleteFile([input.cloudPath]);
|
|
7726
|
+
}
|
|
7727
|
+
return {
|
|
7728
|
+
content: [
|
|
7729
|
+
{
|
|
7730
|
+
type: "text",
|
|
7731
|
+
text: JSON.stringify({
|
|
7732
|
+
success: true,
|
|
7733
|
+
data: {
|
|
7734
|
+
action: 'delete',
|
|
7735
|
+
cloudPath: input.cloudPath,
|
|
7736
|
+
isDirectory: input.isDirectory,
|
|
7737
|
+
deleted: true
|
|
7738
|
+
},
|
|
7739
|
+
message: `Successfully deleted ${input.isDirectory ? 'directory' : 'file'} '${input.cloudPath}'`
|
|
7740
|
+
}, null, 2)
|
|
7741
|
+
}
|
|
7742
|
+
]
|
|
7743
|
+
};
|
|
7806
7744
|
}
|
|
7807
|
-
|
|
7808
|
-
|
|
7809
|
-
return {
|
|
7810
|
-
content: [
|
|
7811
|
-
{
|
|
7812
|
-
type: "text",
|
|
7813
|
-
text: JSON.stringify({
|
|
7814
|
-
success: false,
|
|
7815
|
-
error: error.message || 'Unknown error occurred',
|
|
7816
|
-
message: `Failed to manage storage. Please check your permissions and parameters.`
|
|
7817
|
-
}, null, 2)
|
|
7818
|
-
}
|
|
7819
|
-
]
|
|
7820
|
-
};
|
|
7745
|
+
default:
|
|
7746
|
+
throw new Error(`Unsupported action: ${input.action}`);
|
|
7821
7747
|
}
|
|
7822
7748
|
});
|
|
7823
7749
|
}
|
|
@@ -7991,113 +7917,97 @@ function registerCloudRunTools(server) {
|
|
|
7991
7917
|
category: "cloudrun"
|
|
7992
7918
|
}
|
|
7993
7919
|
}, async (args) => {
|
|
7994
|
-
|
|
7995
|
-
|
|
7996
|
-
|
|
7997
|
-
|
|
7998
|
-
|
|
7999
|
-
|
|
8000
|
-
|
|
8001
|
-
|
|
8002
|
-
|
|
8003
|
-
|
|
8004
|
-
|
|
8005
|
-
|
|
8006
|
-
|
|
8007
|
-
|
|
8008
|
-
listParams.serverName = input.serverName;
|
|
8009
|
-
}
|
|
8010
|
-
if (input.serverType) {
|
|
8011
|
-
listParams.serverType = input.serverType;
|
|
8012
|
-
}
|
|
8013
|
-
const result = await cloudrunService.list(listParams);
|
|
8014
|
-
return {
|
|
8015
|
-
content: [
|
|
8016
|
-
{
|
|
8017
|
-
type: "text",
|
|
8018
|
-
text: JSON.stringify({
|
|
8019
|
-
success: true,
|
|
8020
|
-
data: {
|
|
8021
|
-
services: result.ServerList || [],
|
|
8022
|
-
pagination: {
|
|
8023
|
-
total: result.Total || 0,
|
|
8024
|
-
pageSize: input.pageSize,
|
|
8025
|
-
pageNum: input.pageNum,
|
|
8026
|
-
totalPages: Math.ceil((result.Total || 0) / (input.pageSize || 10))
|
|
8027
|
-
}
|
|
8028
|
-
},
|
|
8029
|
-
message: `Found ${result.ServerList?.length || 0} CloudRun services`
|
|
8030
|
-
}, null, 2)
|
|
8031
|
-
}
|
|
8032
|
-
]
|
|
8033
|
-
};
|
|
7920
|
+
const input = args;
|
|
7921
|
+
const manager = await getManager();
|
|
7922
|
+
if (!manager) {
|
|
7923
|
+
throw new Error("Failed to initialize CloudBase manager. Please check your credentials and environment configuration.");
|
|
7924
|
+
}
|
|
7925
|
+
const cloudrunService = manager.cloudrun;
|
|
7926
|
+
switch (input.action) {
|
|
7927
|
+
case 'list': {
|
|
7928
|
+
const listParams = {
|
|
7929
|
+
pageSize: input.pageSize,
|
|
7930
|
+
pageNum: input.pageNum,
|
|
7931
|
+
};
|
|
7932
|
+
if (input.serverName) {
|
|
7933
|
+
listParams.serverName = input.serverName;
|
|
8034
7934
|
}
|
|
8035
|
-
|
|
8036
|
-
|
|
8037
|
-
const result = await cloudrunService.detail({ serverName });
|
|
8038
|
-
if (!result) {
|
|
8039
|
-
return {
|
|
8040
|
-
content: [
|
|
8041
|
-
{
|
|
8042
|
-
type: "text",
|
|
8043
|
-
text: JSON.stringify({
|
|
8044
|
-
success: false,
|
|
8045
|
-
error: `Service '${serverName}' not found`,
|
|
8046
|
-
message: "Please check the service name and try again."
|
|
8047
|
-
}, null, 2)
|
|
8048
|
-
}
|
|
8049
|
-
]
|
|
8050
|
-
};
|
|
8051
|
-
}
|
|
8052
|
-
return {
|
|
8053
|
-
content: [
|
|
8054
|
-
{
|
|
8055
|
-
type: "text",
|
|
8056
|
-
text: JSON.stringify({
|
|
8057
|
-
success: true,
|
|
8058
|
-
data: {
|
|
8059
|
-
service: result
|
|
8060
|
-
},
|
|
8061
|
-
message: `Retrieved details for service '${serverName}'`
|
|
8062
|
-
}, null, 2)
|
|
8063
|
-
}
|
|
8064
|
-
]
|
|
8065
|
-
};
|
|
7935
|
+
if (input.serverType) {
|
|
7936
|
+
listParams.serverType = input.serverType;
|
|
8066
7937
|
}
|
|
8067
|
-
|
|
8068
|
-
|
|
7938
|
+
const result = await cloudrunService.list(listParams);
|
|
7939
|
+
return {
|
|
7940
|
+
content: [
|
|
7941
|
+
{
|
|
7942
|
+
type: "text",
|
|
7943
|
+
text: JSON.stringify({
|
|
7944
|
+
success: true,
|
|
7945
|
+
data: {
|
|
7946
|
+
services: result.ServerList || [],
|
|
7947
|
+
pagination: {
|
|
7948
|
+
total: result.Total || 0,
|
|
7949
|
+
pageSize: input.pageSize,
|
|
7950
|
+
pageNum: input.pageNum,
|
|
7951
|
+
totalPages: Math.ceil((result.Total || 0) / (input.pageSize || 10))
|
|
7952
|
+
}
|
|
7953
|
+
},
|
|
7954
|
+
message: `Found ${result.ServerList?.length || 0} CloudRun services`
|
|
7955
|
+
}, null, 2)
|
|
7956
|
+
}
|
|
7957
|
+
]
|
|
7958
|
+
};
|
|
7959
|
+
}
|
|
7960
|
+
case 'detail': {
|
|
7961
|
+
const serverName = input.detailServerName || input.serverName;
|
|
7962
|
+
const result = await cloudrunService.detail({ serverName });
|
|
7963
|
+
if (!result) {
|
|
8069
7964
|
return {
|
|
8070
7965
|
content: [
|
|
8071
7966
|
{
|
|
8072
7967
|
type: "text",
|
|
8073
7968
|
text: JSON.stringify({
|
|
8074
|
-
success:
|
|
8075
|
-
|
|
8076
|
-
|
|
8077
|
-
},
|
|
8078
|
-
message: `Found ${result?.length || 0} available templates`
|
|
7969
|
+
success: false,
|
|
7970
|
+
error: `Service '${serverName}' not found`,
|
|
7971
|
+
message: "Please check the service name and try again."
|
|
8079
7972
|
}, null, 2)
|
|
8080
7973
|
}
|
|
8081
7974
|
]
|
|
8082
7975
|
};
|
|
8083
7976
|
}
|
|
8084
|
-
|
|
8085
|
-
|
|
7977
|
+
return {
|
|
7978
|
+
content: [
|
|
7979
|
+
{
|
|
7980
|
+
type: "text",
|
|
7981
|
+
text: JSON.stringify({
|
|
7982
|
+
success: true,
|
|
7983
|
+
data: {
|
|
7984
|
+
service: result
|
|
7985
|
+
},
|
|
7986
|
+
message: `Retrieved details for service '${serverName}'`
|
|
7987
|
+
}, null, 2)
|
|
7988
|
+
}
|
|
7989
|
+
]
|
|
7990
|
+
};
|
|
8086
7991
|
}
|
|
8087
|
-
|
|
8088
|
-
|
|
8089
|
-
|
|
8090
|
-
|
|
8091
|
-
|
|
8092
|
-
|
|
8093
|
-
|
|
8094
|
-
|
|
8095
|
-
|
|
8096
|
-
|
|
8097
|
-
|
|
8098
|
-
|
|
8099
|
-
|
|
8100
|
-
|
|
7992
|
+
case 'templates': {
|
|
7993
|
+
const result = await cloudrunService.getTemplates();
|
|
7994
|
+
return {
|
|
7995
|
+
content: [
|
|
7996
|
+
{
|
|
7997
|
+
type: "text",
|
|
7998
|
+
text: JSON.stringify({
|
|
7999
|
+
success: true,
|
|
8000
|
+
data: {
|
|
8001
|
+
templates: result || []
|
|
8002
|
+
},
|
|
8003
|
+
message: `Found ${result?.length || 0} available templates`
|
|
8004
|
+
}, null, 2)
|
|
8005
|
+
}
|
|
8006
|
+
]
|
|
8007
|
+
};
|
|
8008
|
+
}
|
|
8009
|
+
default:
|
|
8010
|
+
throw new Error(`Unsupported action: ${input.action}`);
|
|
8101
8011
|
}
|
|
8102
8012
|
});
|
|
8103
8013
|
// Track local running processes for CloudRun function services
|
|
@@ -8115,62 +8025,60 @@ function registerCloudRunTools(server) {
|
|
|
8115
8025
|
category: "cloudrun"
|
|
8116
8026
|
}
|
|
8117
8027
|
}, async (args) => {
|
|
8118
|
-
|
|
8119
|
-
|
|
8120
|
-
|
|
8121
|
-
|
|
8122
|
-
|
|
8123
|
-
|
|
8124
|
-
|
|
8125
|
-
|
|
8126
|
-
|
|
8127
|
-
|
|
8128
|
-
|
|
8129
|
-
|
|
8130
|
-
|
|
8131
|
-
|
|
8132
|
-
|
|
8133
|
-
|
|
8134
|
-
|
|
8135
|
-
|
|
8136
|
-
|
|
8137
|
-
|
|
8138
|
-
|
|
8139
|
-
|
|
8140
|
-
|
|
8141
|
-
|
|
8142
|
-
|
|
8143
|
-
|
|
8144
|
-
|
|
8145
|
-
|
|
8146
|
-
|
|
8147
|
-
|
|
8148
|
-
|
|
8149
|
-
|
|
8150
|
-
|
|
8151
|
-
|
|
8028
|
+
const input = args;
|
|
8029
|
+
const manager = await getManager();
|
|
8030
|
+
if (!manager) {
|
|
8031
|
+
throw new Error("Failed to initialize CloudBase manager. Please check your credentials and environment configuration.");
|
|
8032
|
+
}
|
|
8033
|
+
const cloudrunService = manager.cloudrun;
|
|
8034
|
+
let targetPath;
|
|
8035
|
+
if (input.targetPath) {
|
|
8036
|
+
targetPath = validateAndNormalizePath(input.targetPath);
|
|
8037
|
+
}
|
|
8038
|
+
switch (input.action) {
|
|
8039
|
+
case 'createAgent': {
|
|
8040
|
+
if (!targetPath) {
|
|
8041
|
+
throw new Error("targetPath is required for createAgent operation");
|
|
8042
|
+
}
|
|
8043
|
+
if (!input.agentConfig) {
|
|
8044
|
+
throw new Error("agentConfig is required for createAgent operation");
|
|
8045
|
+
}
|
|
8046
|
+
const { agentName, botTag, description, template = 'blank' } = input.agentConfig;
|
|
8047
|
+
// Generate BotId
|
|
8048
|
+
const botId = botTag ? `ibot-${agentName}-${botTag}` : `ibot-${agentName}-${Date.now()}`;
|
|
8049
|
+
// Create Agent using CloudBase Manager
|
|
8050
|
+
const agentResult = await manager.agent.createFunctionAgent(targetPath, {
|
|
8051
|
+
Name: agentName,
|
|
8052
|
+
BotId: botId,
|
|
8053
|
+
Introduction: description || `Agent created by ${agentName}`,
|
|
8054
|
+
Avatar: undefined
|
|
8055
|
+
});
|
|
8056
|
+
// Create project directory
|
|
8057
|
+
const projectDir = path_1.default.join(targetPath, input.serverName);
|
|
8058
|
+
if (!fs_1.default.existsSync(projectDir)) {
|
|
8059
|
+
fs_1.default.mkdirSync(projectDir, { recursive: true });
|
|
8060
|
+
}
|
|
8061
|
+
// Generate package.json
|
|
8062
|
+
const packageJson = {
|
|
8063
|
+
name: input.serverName,
|
|
8064
|
+
version: "1.0.0",
|
|
8065
|
+
description: description || `Agent created by ${agentName}`,
|
|
8066
|
+
main: "index.js",
|
|
8067
|
+
scripts: {
|
|
8068
|
+
"dev": "tcb cloudrun run --runMode=agent -w",
|
|
8069
|
+
"deploy": "tcb cloudrun deploy",
|
|
8070
|
+
"start": "node index.js"
|
|
8071
|
+
},
|
|
8072
|
+
dependencies: {
|
|
8073
|
+
"@cloudbase/aiagent-framework": "^1.0.0-beta.10"
|
|
8074
|
+
},
|
|
8075
|
+
devDependencies: {
|
|
8076
|
+
"@cloudbase/cli": "^2.6.16"
|
|
8152
8077
|
}
|
|
8153
|
-
|
|
8154
|
-
|
|
8155
|
-
|
|
8156
|
-
|
|
8157
|
-
description: description || `Agent created by ${agentName}`,
|
|
8158
|
-
main: "index.js",
|
|
8159
|
-
scripts: {
|
|
8160
|
-
"dev": "tcb cloudrun run --runMode=agent -w",
|
|
8161
|
-
"deploy": "tcb cloudrun deploy",
|
|
8162
|
-
"start": "node index.js"
|
|
8163
|
-
},
|
|
8164
|
-
dependencies: {
|
|
8165
|
-
"@cloudbase/aiagent-framework": "^1.0.0-beta.10"
|
|
8166
|
-
},
|
|
8167
|
-
devDependencies: {
|
|
8168
|
-
"@cloudbase/cli": "^2.6.16"
|
|
8169
|
-
}
|
|
8170
|
-
};
|
|
8171
|
-
fs_1.default.writeFileSync(path_1.default.join(projectDir, 'package.json'), JSON.stringify(packageJson, null, 2));
|
|
8172
|
-
// Generate index.js with Agent template
|
|
8173
|
-
const indexJsContent = `const { IBot } = require("@cloudbase/aiagent-framework");
|
|
8078
|
+
};
|
|
8079
|
+
fs_1.default.writeFileSync(path_1.default.join(projectDir, 'package.json'), JSON.stringify(packageJson, null, 2));
|
|
8080
|
+
// Generate index.js with Agent template
|
|
8081
|
+
const indexJsContent = `const { IBot } = require("@cloudbase/aiagent-framework");
|
|
8174
8082
|
const { BotRunner } = require("@cloudbase/aiagent-framework");
|
|
8175
8083
|
|
|
8176
8084
|
const ANSWER = "你好,我是一个智能体,但我只会说这一句话。";
|
|
@@ -8215,18 +8123,18 @@ exports.main = function (event, context) {
|
|
|
8215
8123
|
return BotRunner.run(event, context, new MyBot(context));
|
|
8216
8124
|
};
|
|
8217
8125
|
`;
|
|
8218
|
-
|
|
8219
|
-
|
|
8220
|
-
|
|
8221
|
-
|
|
8222
|
-
|
|
8223
|
-
|
|
8224
|
-
|
|
8225
|
-
|
|
8226
|
-
|
|
8227
|
-
|
|
8228
|
-
|
|
8229
|
-
|
|
8126
|
+
fs_1.default.writeFileSync(path_1.default.join(projectDir, 'index.js'), indexJsContent);
|
|
8127
|
+
// Generate cloudbaserc.json
|
|
8128
|
+
const currentEnvId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
8129
|
+
const cloudbasercContent = {
|
|
8130
|
+
envId: currentEnvId,
|
|
8131
|
+
cloudrun: {
|
|
8132
|
+
name: input.serverName
|
|
8133
|
+
}
|
|
8134
|
+
};
|
|
8135
|
+
fs_1.default.writeFileSync(path_1.default.join(projectDir, 'cloudbaserc.json'), JSON.stringify(cloudbasercContent, null, 2));
|
|
8136
|
+
// Generate README.md
|
|
8137
|
+
const readmeContent = `# ${agentName} Agent
|
|
8230
8138
|
|
|
8231
8139
|
这是一个基于函数型云托管的 AI 智能体。
|
|
8232
8140
|
|
|
@@ -8271,230 +8179,230 @@ for await (let x of res.textStream) {
|
|
|
8271
8179
|
</script>
|
|
8272
8180
|
\`\`\`
|
|
8273
8181
|
`;
|
|
8274
|
-
|
|
8275
|
-
|
|
8276
|
-
|
|
8277
|
-
|
|
8278
|
-
|
|
8279
|
-
|
|
8280
|
-
|
|
8281
|
-
|
|
8282
|
-
|
|
8283
|
-
|
|
8284
|
-
|
|
8285
|
-
|
|
8286
|
-
|
|
8287
|
-
|
|
8288
|
-
|
|
8289
|
-
|
|
8290
|
-
|
|
8291
|
-
|
|
8292
|
-
|
|
8293
|
-
|
|
8182
|
+
fs_1.default.writeFileSync(path_1.default.join(projectDir, 'README.md'), readmeContent);
|
|
8183
|
+
return {
|
|
8184
|
+
content: [
|
|
8185
|
+
{
|
|
8186
|
+
type: "text",
|
|
8187
|
+
text: JSON.stringify({
|
|
8188
|
+
success: true,
|
|
8189
|
+
data: {
|
|
8190
|
+
agentName: agentName,
|
|
8191
|
+
botId: botId,
|
|
8192
|
+
projectDir: projectDir,
|
|
8193
|
+
serverName: input.serverName,
|
|
8194
|
+
template: template,
|
|
8195
|
+
filesCreated: ['package.json', 'index.js', 'cloudbaserc.json', 'README.md']
|
|
8196
|
+
},
|
|
8197
|
+
message: `Successfully created Agent '${agentName}' with BotId '${botId}' in ${projectDir}`
|
|
8198
|
+
}, null, 2)
|
|
8199
|
+
}
|
|
8200
|
+
]
|
|
8201
|
+
};
|
|
8202
|
+
}
|
|
8203
|
+
case 'deploy': {
|
|
8204
|
+
if (!targetPath) {
|
|
8205
|
+
throw new Error("targetPath is required for deploy operation");
|
|
8294
8206
|
}
|
|
8295
|
-
|
|
8296
|
-
|
|
8297
|
-
|
|
8298
|
-
|
|
8299
|
-
|
|
8300
|
-
|
|
8301
|
-
|
|
8302
|
-
|
|
8207
|
+
// Determine service type - use input.serverType if provided, otherwise auto-detect
|
|
8208
|
+
let serverType;
|
|
8209
|
+
if (input.serverType) {
|
|
8210
|
+
serverType = input.serverType;
|
|
8211
|
+
}
|
|
8212
|
+
else {
|
|
8213
|
+
try {
|
|
8214
|
+
// First try to get existing service details
|
|
8215
|
+
const details = await cloudrunService.detail({ serverName: input.serverName });
|
|
8216
|
+
serverType = details.BaseInfo?.ServerType || 'container';
|
|
8303
8217
|
}
|
|
8304
|
-
|
|
8305
|
-
|
|
8306
|
-
|
|
8307
|
-
|
|
8308
|
-
serverType =
|
|
8218
|
+
catch (e) {
|
|
8219
|
+
// If service doesn't exist, determine by project structure
|
|
8220
|
+
const dockerfilePath = path_1.default.join(targetPath, 'Dockerfile');
|
|
8221
|
+
if (fs_1.default.existsSync(dockerfilePath)) {
|
|
8222
|
+
serverType = 'container';
|
|
8309
8223
|
}
|
|
8310
|
-
|
|
8311
|
-
//
|
|
8312
|
-
const
|
|
8313
|
-
if (fs_1.default.existsSync(
|
|
8314
|
-
|
|
8315
|
-
|
|
8316
|
-
|
|
8317
|
-
|
|
8318
|
-
|
|
8319
|
-
|
|
8320
|
-
try {
|
|
8321
|
-
const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf8'));
|
|
8322
|
-
// If it has function-specific dependencies or scripts, treat as function
|
|
8323
|
-
if (packageJson.dependencies?.['@cloudbase/aiagent-framework'] ||
|
|
8324
|
-
packageJson.scripts?.['dev']?.includes('cloudrun run')) {
|
|
8325
|
-
serverType = 'function';
|
|
8326
|
-
}
|
|
8327
|
-
else {
|
|
8328
|
-
serverType = 'container';
|
|
8329
|
-
}
|
|
8224
|
+
else {
|
|
8225
|
+
// Check if it's a Node.js function project (has package.json with specific structure)
|
|
8226
|
+
const packageJsonPath = path_1.default.join(targetPath, 'package.json');
|
|
8227
|
+
if (fs_1.default.existsSync(packageJsonPath)) {
|
|
8228
|
+
try {
|
|
8229
|
+
const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf8'));
|
|
8230
|
+
// If it has function-specific dependencies or scripts, treat as function
|
|
8231
|
+
if (packageJson.dependencies?.['@cloudbase/aiagent-framework'] ||
|
|
8232
|
+
packageJson.scripts?.['dev']?.includes('cloudrun run')) {
|
|
8233
|
+
serverType = 'function';
|
|
8330
8234
|
}
|
|
8331
|
-
|
|
8235
|
+
else {
|
|
8332
8236
|
serverType = 'container';
|
|
8333
8237
|
}
|
|
8334
8238
|
}
|
|
8335
|
-
|
|
8336
|
-
// No package.json, default to container
|
|
8239
|
+
catch (parseError) {
|
|
8337
8240
|
serverType = 'container';
|
|
8338
8241
|
}
|
|
8339
8242
|
}
|
|
8340
|
-
}
|
|
8341
|
-
}
|
|
8342
|
-
const deployParams = {
|
|
8343
|
-
serverName: input.serverName,
|
|
8344
|
-
targetPath: targetPath,
|
|
8345
|
-
force: input.force,
|
|
8346
|
-
serverType: serverType,
|
|
8347
|
-
};
|
|
8348
|
-
// Add server configuration if provided
|
|
8349
|
-
if (input.serverConfig) {
|
|
8350
|
-
deployParams.serverConfig = input.serverConfig;
|
|
8351
|
-
}
|
|
8352
|
-
const result = await cloudrunService.deploy(deployParams);
|
|
8353
|
-
// Generate cloudbaserc.json configuration file
|
|
8354
|
-
const currentEnvId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
8355
|
-
const cloudbasercPath = path_1.default.join(targetPath, 'cloudbaserc.json');
|
|
8356
|
-
const cloudbasercContent = {
|
|
8357
|
-
envId: currentEnvId,
|
|
8358
|
-
cloudrun: {
|
|
8359
|
-
name: input.serverName
|
|
8360
|
-
}
|
|
8361
|
-
};
|
|
8362
|
-
try {
|
|
8363
|
-
fs_1.default.writeFileSync(cloudbasercPath, JSON.stringify(cloudbasercContent, null, 2));
|
|
8364
|
-
}
|
|
8365
|
-
catch (error) {
|
|
8366
|
-
// Ignore cloudbaserc.json creation errors
|
|
8367
|
-
}
|
|
8368
|
-
// Send deployment notification to CodeBuddy IDE
|
|
8369
|
-
try {
|
|
8370
|
-
// Query service details to get access URL
|
|
8371
|
-
let serviceUrl = "";
|
|
8372
|
-
try {
|
|
8373
|
-
const serviceDetails = await cloudrunService.detail({ serverName: input.serverName });
|
|
8374
|
-
// Extract access URL from service details
|
|
8375
|
-
// Priority: DefaultDomainName > CustomDomainName > PublicDomain > InternalDomain
|
|
8376
|
-
const details = serviceDetails; // Use any to access dynamic properties
|
|
8377
|
-
if (details?.BaseInfo?.DefaultDomainName) {
|
|
8378
|
-
// DefaultDomainName is already a complete URL (e.g., https://...)
|
|
8379
|
-
serviceUrl = details.BaseInfo.DefaultDomainName;
|
|
8380
|
-
}
|
|
8381
|
-
else if (details?.BaseInfo?.CustomDomainName) {
|
|
8382
|
-
// CustomDomainName might be a domain without protocol
|
|
8383
|
-
const customDomain = details.BaseInfo.CustomDomainName;
|
|
8384
|
-
serviceUrl = customDomain.startsWith('http') ? customDomain : `https://${customDomain}`;
|
|
8385
|
-
}
|
|
8386
|
-
else if (details?.BaseInfo?.PublicDomain) {
|
|
8387
|
-
serviceUrl = `https://${details.BaseInfo.PublicDomain}`;
|
|
8388
|
-
}
|
|
8389
|
-
else if (details?.BaseInfo?.InternalDomain) {
|
|
8390
|
-
serviceUrl = `https://${details.BaseInfo.InternalDomain}`;
|
|
8391
|
-
}
|
|
8392
|
-
else if (details?.AccessInfo?.PublicDomain) {
|
|
8393
|
-
serviceUrl = `https://${details.AccessInfo.PublicDomain}`;
|
|
8394
|
-
}
|
|
8395
8243
|
else {
|
|
8396
|
-
|
|
8244
|
+
// No package.json, default to container
|
|
8245
|
+
serverType = 'container';
|
|
8397
8246
|
}
|
|
8398
8247
|
}
|
|
8399
|
-
catch (detailErr) {
|
|
8400
|
-
// If query fails, continue with empty URL
|
|
8401
|
-
serviceUrl = "";
|
|
8402
|
-
}
|
|
8403
|
-
// Extract project name from targetPath
|
|
8404
|
-
const projectName = path_1.default.basename(targetPath);
|
|
8405
|
-
// Build console URL
|
|
8406
|
-
const consoleUrl = `https://tcb.cloud.tencent.com/dev?envId=${currentEnvId}#/platform-run/service/detail?serverName=${input.serverName}&tabId=overview&envId=${currentEnvId}`;
|
|
8407
|
-
// Send notification
|
|
8408
|
-
await (0, notification_js_1.sendDeployNotification)(server, {
|
|
8409
|
-
deployType: 'cloudrun',
|
|
8410
|
-
url: serviceUrl,
|
|
8411
|
-
projectId: currentEnvId,
|
|
8412
|
-
projectName: projectName,
|
|
8413
|
-
consoleUrl: consoleUrl
|
|
8414
|
-
});
|
|
8415
|
-
}
|
|
8416
|
-
catch (notifyErr) {
|
|
8417
|
-
// Notification failure should not affect deployment flow
|
|
8418
|
-
// Error is already logged in sendDeployNotification
|
|
8419
8248
|
}
|
|
8420
|
-
return {
|
|
8421
|
-
content: [
|
|
8422
|
-
{
|
|
8423
|
-
type: "text",
|
|
8424
|
-
text: JSON.stringify({
|
|
8425
|
-
success: true,
|
|
8426
|
-
data: {
|
|
8427
|
-
serviceName: input.serverName,
|
|
8428
|
-
status: 'deployed',
|
|
8429
|
-
deployPath: targetPath,
|
|
8430
|
-
serverType: serverType,
|
|
8431
|
-
cloudbasercGenerated: true
|
|
8432
|
-
},
|
|
8433
|
-
message: `Successfully deployed ${serverType} service '${input.serverName}' from ${targetPath}`
|
|
8434
|
-
}, null, 2)
|
|
8435
|
-
}
|
|
8436
|
-
]
|
|
8437
|
-
};
|
|
8438
8249
|
}
|
|
8439
|
-
|
|
8440
|
-
|
|
8441
|
-
|
|
8442
|
-
|
|
8443
|
-
|
|
8444
|
-
|
|
8445
|
-
|
|
8446
|
-
|
|
8250
|
+
const deployParams = {
|
|
8251
|
+
serverName: input.serverName,
|
|
8252
|
+
targetPath: targetPath,
|
|
8253
|
+
force: input.force,
|
|
8254
|
+
serverType: serverType,
|
|
8255
|
+
};
|
|
8256
|
+
// Add server configuration if provided
|
|
8257
|
+
if (input.serverConfig) {
|
|
8258
|
+
deployParams.serverConfig = input.serverConfig;
|
|
8259
|
+
}
|
|
8260
|
+
const result = await cloudrunService.deploy(deployParams);
|
|
8261
|
+
// Generate cloudbaserc.json configuration file
|
|
8262
|
+
const currentEnvId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
8263
|
+
const cloudbasercPath = path_1.default.join(targetPath, 'cloudbaserc.json');
|
|
8264
|
+
const cloudbasercContent = {
|
|
8265
|
+
envId: currentEnvId,
|
|
8266
|
+
cloudrun: {
|
|
8267
|
+
name: input.serverName
|
|
8447
8268
|
}
|
|
8448
|
-
|
|
8449
|
-
|
|
8450
|
-
|
|
8451
|
-
|
|
8452
|
-
|
|
8453
|
-
|
|
8454
|
-
|
|
8455
|
-
|
|
8456
|
-
|
|
8457
|
-
|
|
8458
|
-
|
|
8459
|
-
|
|
8460
|
-
|
|
8461
|
-
|
|
8462
|
-
|
|
8463
|
-
|
|
8464
|
-
|
|
8465
|
-
|
|
8466
|
-
|
|
8467
|
-
|
|
8468
|
-
|
|
8469
|
-
|
|
8470
|
-
|
|
8471
|
-
|
|
8472
|
-
|
|
8473
|
-
|
|
8269
|
+
};
|
|
8270
|
+
try {
|
|
8271
|
+
fs_1.default.writeFileSync(cloudbasercPath, JSON.stringify(cloudbasercContent, null, 2));
|
|
8272
|
+
}
|
|
8273
|
+
catch (error) {
|
|
8274
|
+
// Ignore cloudbaserc.json creation errors
|
|
8275
|
+
}
|
|
8276
|
+
// Send deployment notification to CodeBuddy IDE
|
|
8277
|
+
try {
|
|
8278
|
+
// Query service details to get access URL
|
|
8279
|
+
let serviceUrl = "";
|
|
8280
|
+
try {
|
|
8281
|
+
const serviceDetails = await cloudrunService.detail({ serverName: input.serverName });
|
|
8282
|
+
// Extract access URL from service details
|
|
8283
|
+
// Priority: DefaultDomainName > CustomDomainName > PublicDomain > InternalDomain
|
|
8284
|
+
const details = serviceDetails; // Use any to access dynamic properties
|
|
8285
|
+
if (details?.BaseInfo?.DefaultDomainName) {
|
|
8286
|
+
// DefaultDomainName is already a complete URL (e.g., https://...)
|
|
8287
|
+
serviceUrl = details.BaseInfo.DefaultDomainName;
|
|
8288
|
+
}
|
|
8289
|
+
else if (details?.BaseInfo?.CustomDomainName) {
|
|
8290
|
+
// CustomDomainName might be a domain without protocol
|
|
8291
|
+
const customDomain = details.BaseInfo.CustomDomainName;
|
|
8292
|
+
serviceUrl = customDomain.startsWith('http') ? customDomain : `https://${customDomain}`;
|
|
8293
|
+
}
|
|
8294
|
+
else if (details?.BaseInfo?.PublicDomain) {
|
|
8295
|
+
serviceUrl = `https://${details.BaseInfo.PublicDomain}`;
|
|
8296
|
+
}
|
|
8297
|
+
else if (details?.BaseInfo?.InternalDomain) {
|
|
8298
|
+
serviceUrl = `https://${details.BaseInfo.InternalDomain}`;
|
|
8299
|
+
}
|
|
8300
|
+
else if (details?.AccessInfo?.PublicDomain) {
|
|
8301
|
+
serviceUrl = `https://${details.AccessInfo.PublicDomain}`;
|
|
8474
8302
|
}
|
|
8475
|
-
|
|
8476
|
-
|
|
8477
|
-
runningProcesses.delete(input.serverName);
|
|
8303
|
+
else {
|
|
8304
|
+
serviceUrl = ""; // URL not available
|
|
8478
8305
|
}
|
|
8479
8306
|
}
|
|
8480
|
-
|
|
8481
|
-
|
|
8482
|
-
|
|
8483
|
-
|
|
8484
|
-
|
|
8485
|
-
|
|
8486
|
-
|
|
8487
|
-
|
|
8488
|
-
|
|
8489
|
-
|
|
8490
|
-
|
|
8491
|
-
|
|
8492
|
-
|
|
8493
|
-
|
|
8494
|
-
|
|
8495
|
-
|
|
8496
|
-
|
|
8497
|
-
|
|
8307
|
+
catch (detailErr) {
|
|
8308
|
+
// If query fails, continue with empty URL
|
|
8309
|
+
serviceUrl = "";
|
|
8310
|
+
}
|
|
8311
|
+
// Extract project name from targetPath
|
|
8312
|
+
const projectName = path_1.default.basename(targetPath);
|
|
8313
|
+
// Build console URL
|
|
8314
|
+
const consoleUrl = `https://tcb.cloud.tencent.com/dev?envId=${currentEnvId}#/platform-run/service/detail?serverName=${input.serverName}&tabId=overview&envId=${currentEnvId}`;
|
|
8315
|
+
// Send notification
|
|
8316
|
+
await (0, notification_js_1.sendDeployNotification)(server, {
|
|
8317
|
+
deployType: 'cloudrun',
|
|
8318
|
+
url: serviceUrl,
|
|
8319
|
+
projectId: currentEnvId,
|
|
8320
|
+
projectName: projectName,
|
|
8321
|
+
consoleUrl: consoleUrl
|
|
8322
|
+
});
|
|
8323
|
+
}
|
|
8324
|
+
catch (notifyErr) {
|
|
8325
|
+
// Notification failure should not affect deployment flow
|
|
8326
|
+
// Error is already logged in sendDeployNotification
|
|
8327
|
+
}
|
|
8328
|
+
return {
|
|
8329
|
+
content: [
|
|
8330
|
+
{
|
|
8331
|
+
type: "text",
|
|
8332
|
+
text: JSON.stringify({
|
|
8333
|
+
success: true,
|
|
8334
|
+
data: {
|
|
8335
|
+
serviceName: input.serverName,
|
|
8336
|
+
status: 'deployed',
|
|
8337
|
+
deployPath: targetPath,
|
|
8338
|
+
serverType: serverType,
|
|
8339
|
+
cloudbasercGenerated: true
|
|
8340
|
+
},
|
|
8341
|
+
message: `Successfully deployed ${serverType} service '${input.serverName}' from ${targetPath}`
|
|
8342
|
+
}, null, 2)
|
|
8343
|
+
}
|
|
8344
|
+
]
|
|
8345
|
+
};
|
|
8346
|
+
}
|
|
8347
|
+
case 'run': {
|
|
8348
|
+
if (!targetPath) {
|
|
8349
|
+
throw new Error("targetPath is required for run operation");
|
|
8350
|
+
}
|
|
8351
|
+
// Do not support container services locally: basic heuristic - if Dockerfile exists, treat as container
|
|
8352
|
+
const dockerfilePath = path_1.default.join(targetPath, 'Dockerfile');
|
|
8353
|
+
if (fs_1.default.existsSync(dockerfilePath)) {
|
|
8354
|
+
throw new Error("Local run is only supported for function-type CloudRun services. Container services are not supported.");
|
|
8355
|
+
}
|
|
8356
|
+
// Check if this is an Agent project
|
|
8357
|
+
const isAgent = checkIfAgentProject(targetPath);
|
|
8358
|
+
const runMode = input.runOptions?.runMode || (isAgent ? 'agent' : 'normal');
|
|
8359
|
+
// Check if service is already running and verify process exists
|
|
8360
|
+
if (runningProcesses.has(input.serverName)) {
|
|
8361
|
+
const existingPid = runningProcesses.get(input.serverName);
|
|
8362
|
+
try {
|
|
8363
|
+
// Check if process actually exists
|
|
8364
|
+
process.kill(existingPid, 0);
|
|
8365
|
+
return {
|
|
8366
|
+
content: [
|
|
8367
|
+
{
|
|
8368
|
+
type: "text",
|
|
8369
|
+
text: JSON.stringify({
|
|
8370
|
+
success: true,
|
|
8371
|
+
data: {
|
|
8372
|
+
serviceName: input.serverName,
|
|
8373
|
+
status: 'running',
|
|
8374
|
+
pid: existingPid,
|
|
8375
|
+
cwd: targetPath
|
|
8376
|
+
},
|
|
8377
|
+
message: `Service '${input.serverName}' is already running locally (pid=${existingPid})`
|
|
8378
|
+
}, null, 2)
|
|
8379
|
+
}
|
|
8380
|
+
]
|
|
8381
|
+
};
|
|
8382
|
+
}
|
|
8383
|
+
catch (error) {
|
|
8384
|
+
// Process doesn't exist, remove from tracking
|
|
8385
|
+
runningProcesses.delete(input.serverName);
|
|
8386
|
+
}
|
|
8387
|
+
}
|
|
8388
|
+
const runPort = input.runOptions?.port ?? 3000;
|
|
8389
|
+
const extraEnv = input.runOptions?.envParams ?? {};
|
|
8390
|
+
// Set environment variables for functions-framework
|
|
8391
|
+
const env = {
|
|
8392
|
+
...process.env,
|
|
8393
|
+
PORT: String(runPort),
|
|
8394
|
+
...extraEnv,
|
|
8395
|
+
// Add functions-framework specific environment variables
|
|
8396
|
+
ENABLE_CORS: 'true',
|
|
8397
|
+
ALLOWED_ORIGINS: '*'
|
|
8398
|
+
};
|
|
8399
|
+
// Choose execution method based on run mode
|
|
8400
|
+
let child;
|
|
8401
|
+
let command;
|
|
8402
|
+
if (runMode === 'agent') {
|
|
8403
|
+
// For Agent mode, use a different approach since functions-framework doesn't support Agent mode
|
|
8404
|
+
// We'll use a custom script that sets up the Agent environment
|
|
8405
|
+
command = `node -e "
|
|
8498
8406
|
const { runCLI } = require('@cloudbase/functions-framework');
|
|
8499
8407
|
process.env.PORT = '${runPort}';
|
|
8500
8408
|
process.env.ENABLE_CORS = 'true';
|
|
@@ -8503,16 +8411,16 @@ for await (let x of res.textStream) {
|
|
|
8503
8411
|
${Object.entries(extraEnv).map(([key, value]) => `process.env.${key} = '${value}';`).join('\n')}
|
|
8504
8412
|
runCLI();
|
|
8505
8413
|
"`;
|
|
8506
|
-
|
|
8507
|
-
|
|
8508
|
-
|
|
8509
|
-
|
|
8510
|
-
|
|
8511
|
-
|
|
8512
|
-
|
|
8513
|
-
|
|
8514
|
-
|
|
8515
|
-
|
|
8414
|
+
child = (0, child_process_1.spawn)(process.execPath, ['-e', command], {
|
|
8415
|
+
cwd: targetPath,
|
|
8416
|
+
env,
|
|
8417
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
8418
|
+
detached: true
|
|
8419
|
+
});
|
|
8420
|
+
}
|
|
8421
|
+
else {
|
|
8422
|
+
// Normal function mode
|
|
8423
|
+
command = `node -e "
|
|
8516
8424
|
const { runCLI } = require('@cloudbase/functions-framework');
|
|
8517
8425
|
process.env.PORT = '${runPort}';
|
|
8518
8426
|
process.env.ENABLE_CORS = 'true';
|
|
@@ -8520,182 +8428,167 @@ for await (let x of res.textStream) {
|
|
|
8520
8428
|
${Object.entries(extraEnv).map(([key, value]) => `process.env.${key} = '${value}';`).join('\n')}
|
|
8521
8429
|
runCLI();
|
|
8522
8430
|
"`;
|
|
8523
|
-
|
|
8524
|
-
|
|
8525
|
-
|
|
8526
|
-
|
|
8527
|
-
|
|
8528
|
-
});
|
|
8529
|
-
}
|
|
8530
|
-
// Handle process exit to clean up tracking
|
|
8531
|
-
child.on('exit', (code, signal) => {
|
|
8532
|
-
runningProcesses.delete(input.serverName);
|
|
8533
|
-
});
|
|
8534
|
-
child.on('error', (error) => {
|
|
8535
|
-
runningProcesses.delete(input.serverName);
|
|
8431
|
+
child = (0, child_process_1.spawn)(process.execPath, ['-e', command], {
|
|
8432
|
+
cwd: targetPath,
|
|
8433
|
+
env,
|
|
8434
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
8435
|
+
detached: true
|
|
8536
8436
|
});
|
|
8537
|
-
child.unref();
|
|
8538
|
-
if (typeof child.pid !== 'number') {
|
|
8539
|
-
throw new Error('Failed to start local process: PID is undefined.');
|
|
8540
|
-
}
|
|
8541
|
-
runningProcesses.set(input.serverName, child.pid);
|
|
8542
|
-
return {
|
|
8543
|
-
content: [
|
|
8544
|
-
{
|
|
8545
|
-
type: "text",
|
|
8546
|
-
text: JSON.stringify({
|
|
8547
|
-
success: true,
|
|
8548
|
-
data: {
|
|
8549
|
-
serviceName: input.serverName,
|
|
8550
|
-
status: 'running',
|
|
8551
|
-
pid: child.pid,
|
|
8552
|
-
port: runPort,
|
|
8553
|
-
runMode: runMode,
|
|
8554
|
-
isAgent: isAgent,
|
|
8555
|
-
command: command,
|
|
8556
|
-
cwd: targetPath
|
|
8557
|
-
},
|
|
8558
|
-
message: `Started local run for ${runMode} service '${input.serverName}' on port ${runPort} (pid=${child.pid})`
|
|
8559
|
-
}, null, 2)
|
|
8560
|
-
}
|
|
8561
|
-
]
|
|
8562
|
-
};
|
|
8563
8437
|
}
|
|
8564
|
-
|
|
8565
|
-
|
|
8566
|
-
|
|
8567
|
-
|
|
8568
|
-
|
|
8569
|
-
|
|
8570
|
-
|
|
8571
|
-
|
|
8572
|
-
|
|
8573
|
-
|
|
8574
|
-
|
|
8575
|
-
|
|
8576
|
-
|
|
8577
|
-
|
|
8578
|
-
|
|
8438
|
+
// Handle process exit to clean up tracking
|
|
8439
|
+
child.on('exit', (code, signal) => {
|
|
8440
|
+
runningProcesses.delete(input.serverName);
|
|
8441
|
+
});
|
|
8442
|
+
child.on('error', (error) => {
|
|
8443
|
+
runningProcesses.delete(input.serverName);
|
|
8444
|
+
});
|
|
8445
|
+
child.unref();
|
|
8446
|
+
if (typeof child.pid !== 'number') {
|
|
8447
|
+
throw new Error('Failed to start local process: PID is undefined.');
|
|
8448
|
+
}
|
|
8449
|
+
runningProcesses.set(input.serverName, child.pid);
|
|
8450
|
+
return {
|
|
8451
|
+
content: [
|
|
8452
|
+
{
|
|
8453
|
+
type: "text",
|
|
8454
|
+
text: JSON.stringify({
|
|
8455
|
+
success: true,
|
|
8456
|
+
data: {
|
|
8457
|
+
serviceName: input.serverName,
|
|
8458
|
+
status: 'running',
|
|
8459
|
+
pid: child.pid,
|
|
8460
|
+
port: runPort,
|
|
8461
|
+
runMode: runMode,
|
|
8462
|
+
isAgent: isAgent,
|
|
8463
|
+
command: command,
|
|
8464
|
+
cwd: targetPath
|
|
8465
|
+
},
|
|
8466
|
+
message: `Started local run for ${runMode} service '${input.serverName}' on port ${runPort} (pid=${child.pid})`
|
|
8467
|
+
}, null, 2)
|
|
8579
8468
|
}
|
|
8580
|
-
|
|
8581
|
-
|
|
8582
|
-
|
|
8583
|
-
|
|
8584
|
-
|
|
8585
|
-
|
|
8586
|
-
}
|
|
8587
|
-
return {
|
|
8588
|
-
content: [
|
|
8589
|
-
{
|
|
8590
|
-
type: "text",
|
|
8591
|
-
text: JSON.stringify({
|
|
8592
|
-
success: true,
|
|
8593
|
-
data: {
|
|
8594
|
-
serviceName: input.serverName,
|
|
8595
|
-
downloadPath: targetPath,
|
|
8596
|
-
filesCount: 0,
|
|
8597
|
-
cloudbasercGenerated: true
|
|
8598
|
-
},
|
|
8599
|
-
message: `Successfully downloaded service '${input.serverName}' to ${targetPath}`
|
|
8600
|
-
}, null, 2)
|
|
8601
|
-
}
|
|
8602
|
-
]
|
|
8603
|
-
};
|
|
8469
|
+
]
|
|
8470
|
+
};
|
|
8471
|
+
}
|
|
8472
|
+
case 'download': {
|
|
8473
|
+
if (!targetPath) {
|
|
8474
|
+
throw new Error("targetPath is required for download operation");
|
|
8604
8475
|
}
|
|
8605
|
-
|
|
8606
|
-
|
|
8607
|
-
|
|
8608
|
-
|
|
8609
|
-
|
|
8610
|
-
|
|
8611
|
-
|
|
8612
|
-
|
|
8613
|
-
|
|
8614
|
-
|
|
8615
|
-
|
|
8616
|
-
}
|
|
8617
|
-
]
|
|
8618
|
-
};
|
|
8476
|
+
const result = await cloudrunService.download({
|
|
8477
|
+
serverName: input.serverName,
|
|
8478
|
+
targetPath: targetPath,
|
|
8479
|
+
});
|
|
8480
|
+
// Generate cloudbaserc.json configuration file
|
|
8481
|
+
const currentEnvId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
8482
|
+
const cloudbasercPath = path_1.default.join(targetPath, 'cloudbaserc.json');
|
|
8483
|
+
const cloudbasercContent = {
|
|
8484
|
+
envId: currentEnvId,
|
|
8485
|
+
cloudrun: {
|
|
8486
|
+
name: input.serverName
|
|
8619
8487
|
}
|
|
8620
|
-
|
|
8621
|
-
|
|
8622
|
-
|
|
8623
|
-
return {
|
|
8624
|
-
content: [
|
|
8625
|
-
{
|
|
8626
|
-
type: "text",
|
|
8627
|
-
text: JSON.stringify({
|
|
8628
|
-
success: true,
|
|
8629
|
-
data: {
|
|
8630
|
-
serviceName: input.serverName,
|
|
8631
|
-
status: 'deleted'
|
|
8632
|
-
},
|
|
8633
|
-
message: `Successfully deleted service '${input.serverName}'`
|
|
8634
|
-
}, null, 2)
|
|
8635
|
-
}
|
|
8636
|
-
]
|
|
8637
|
-
};
|
|
8488
|
+
};
|
|
8489
|
+
try {
|
|
8490
|
+
fs_1.default.writeFileSync(cloudbasercPath, JSON.stringify(cloudbasercContent, null, 2));
|
|
8638
8491
|
}
|
|
8639
|
-
|
|
8640
|
-
|
|
8641
|
-
|
|
8642
|
-
|
|
8643
|
-
|
|
8644
|
-
|
|
8645
|
-
|
|
8646
|
-
|
|
8647
|
-
|
|
8648
|
-
|
|
8649
|
-
|
|
8650
|
-
|
|
8651
|
-
|
|
8652
|
-
|
|
8653
|
-
|
|
8654
|
-
|
|
8492
|
+
catch (error) {
|
|
8493
|
+
// Ignore cloudbaserc.json creation errors
|
|
8494
|
+
}
|
|
8495
|
+
return {
|
|
8496
|
+
content: [
|
|
8497
|
+
{
|
|
8498
|
+
type: "text",
|
|
8499
|
+
text: JSON.stringify({
|
|
8500
|
+
success: true,
|
|
8501
|
+
data: {
|
|
8502
|
+
serviceName: input.serverName,
|
|
8503
|
+
downloadPath: targetPath,
|
|
8504
|
+
filesCount: 0,
|
|
8505
|
+
cloudbasercGenerated: true
|
|
8506
|
+
},
|
|
8507
|
+
message: `Successfully downloaded service '${input.serverName}' to ${targetPath}`
|
|
8508
|
+
}, null, 2)
|
|
8655
8509
|
}
|
|
8656
|
-
|
|
8657
|
-
|
|
8658
|
-
|
|
8659
|
-
|
|
8660
|
-
|
|
8661
|
-
// Ignore cloudbaserc.json creation errors
|
|
8662
|
-
}
|
|
8510
|
+
]
|
|
8511
|
+
};
|
|
8512
|
+
}
|
|
8513
|
+
case 'delete': {
|
|
8514
|
+
if (!input.force) {
|
|
8663
8515
|
return {
|
|
8664
8516
|
content: [
|
|
8665
8517
|
{
|
|
8666
8518
|
type: "text",
|
|
8667
8519
|
text: JSON.stringify({
|
|
8668
|
-
success:
|
|
8669
|
-
|
|
8670
|
-
|
|
8671
|
-
template: input.template,
|
|
8672
|
-
initPath: targetPath,
|
|
8673
|
-
projectDir: result.projectDir || path_1.default.join(targetPath, input.serverName),
|
|
8674
|
-
cloudbasercGenerated: true
|
|
8675
|
-
},
|
|
8676
|
-
message: `Successfully initialized service '${input.serverName}' with template '${input.template}' at ${targetPath}`
|
|
8520
|
+
success: false,
|
|
8521
|
+
error: "Delete operation requires confirmation",
|
|
8522
|
+
message: "Please set force: true to confirm deletion of the service. This action cannot be undone."
|
|
8677
8523
|
}, null, 2)
|
|
8678
8524
|
}
|
|
8679
8525
|
]
|
|
8680
8526
|
};
|
|
8681
8527
|
}
|
|
8682
|
-
|
|
8683
|
-
|
|
8528
|
+
const result = await cloudrunService.delete({
|
|
8529
|
+
serverName: input.serverName,
|
|
8530
|
+
});
|
|
8531
|
+
return {
|
|
8532
|
+
content: [
|
|
8533
|
+
{
|
|
8534
|
+
type: "text",
|
|
8535
|
+
text: JSON.stringify({
|
|
8536
|
+
success: true,
|
|
8537
|
+
data: {
|
|
8538
|
+
serviceName: input.serverName,
|
|
8539
|
+
status: 'deleted'
|
|
8540
|
+
},
|
|
8541
|
+
message: `Successfully deleted service '${input.serverName}'`
|
|
8542
|
+
}, null, 2)
|
|
8543
|
+
}
|
|
8544
|
+
]
|
|
8545
|
+
};
|
|
8684
8546
|
}
|
|
8685
|
-
|
|
8686
|
-
|
|
8687
|
-
|
|
8688
|
-
|
|
8689
|
-
|
|
8690
|
-
|
|
8691
|
-
|
|
8692
|
-
|
|
8693
|
-
|
|
8694
|
-
|
|
8695
|
-
|
|
8547
|
+
case 'init': {
|
|
8548
|
+
if (!targetPath) {
|
|
8549
|
+
throw new Error("targetPath is required for init operation");
|
|
8550
|
+
}
|
|
8551
|
+
const result = await cloudrunService.init({
|
|
8552
|
+
serverName: input.serverName,
|
|
8553
|
+
targetPath: targetPath,
|
|
8554
|
+
template: input.template,
|
|
8555
|
+
});
|
|
8556
|
+
// Generate cloudbaserc.json configuration file
|
|
8557
|
+
const currentEnvId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
8558
|
+
const cloudbasercPath = path_1.default.join(targetPath, input.serverName, 'cloudbaserc.json');
|
|
8559
|
+
const cloudbasercContent = {
|
|
8560
|
+
envId: currentEnvId,
|
|
8561
|
+
cloudrun: {
|
|
8562
|
+
name: input.serverName
|
|
8696
8563
|
}
|
|
8697
|
-
|
|
8698
|
-
|
|
8564
|
+
};
|
|
8565
|
+
try {
|
|
8566
|
+
fs_1.default.writeFileSync(cloudbasercPath, JSON.stringify(cloudbasercContent, null, 2));
|
|
8567
|
+
}
|
|
8568
|
+
catch (error) {
|
|
8569
|
+
// Ignore cloudbaserc.json creation errors
|
|
8570
|
+
}
|
|
8571
|
+
return {
|
|
8572
|
+
content: [
|
|
8573
|
+
{
|
|
8574
|
+
type: "text",
|
|
8575
|
+
text: JSON.stringify({
|
|
8576
|
+
success: true,
|
|
8577
|
+
data: {
|
|
8578
|
+
serviceName: input.serverName,
|
|
8579
|
+
template: input.template,
|
|
8580
|
+
initPath: targetPath,
|
|
8581
|
+
projectDir: result.projectDir || path_1.default.join(targetPath, input.serverName),
|
|
8582
|
+
cloudbasercGenerated: true
|
|
8583
|
+
},
|
|
8584
|
+
message: `Successfully initialized service '${input.serverName}' with template '${input.template}' at ${targetPath}`
|
|
8585
|
+
}, null, 2)
|
|
8586
|
+
}
|
|
8587
|
+
]
|
|
8588
|
+
};
|
|
8589
|
+
}
|
|
8590
|
+
default:
|
|
8591
|
+
throw new Error(`Unsupported action: ${input.action}`);
|
|
8699
8592
|
}
|
|
8700
8593
|
});
|
|
8701
8594
|
}
|
|
@@ -8770,7 +8663,7 @@ class TelemetryReporter {
|
|
|
8770
8663
|
const nodeVersion = process.version; // Node.js版本
|
|
8771
8664
|
const arch = os_1.default.arch(); // 系统架构
|
|
8772
8665
|
// 从构建时注入的版本号获取MCP版本信息
|
|
8773
|
-
const mcpVersion = process.env.npm_package_version || "2.
|
|
8666
|
+
const mcpVersion = process.env.npm_package_version || "2.11.0" || 0;
|
|
8774
8667
|
return {
|
|
8775
8668
|
userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
|
|
8776
8669
|
deviceId: this.deviceId,
|
|
@@ -10203,7 +10096,7 @@ function registerSetupTools(server) {
|
|
|
10203
10096
|
title: "下载项目模板",
|
|
10204
10097
|
description: `自动下载并部署CloudBase项目模板。⚠️ **MANDATORY FOR NEW PROJECTS** ⚠️
|
|
10205
10098
|
|
|
10206
|
-
**CRITICAL**: This tool MUST be called FIRST when starting a new project.\n\n支持的模板:\n- react: React + CloudBase 全栈应用模板\n- vue: Vue + CloudBase 全栈应用模板\n- miniprogram: 微信小程序 + 云开发模板 \n- uniapp: UniApp + CloudBase 跨端应用模板\n- rules: 只包含AI编辑器配置文件(包含Cursor、WindSurf、CodeBuddy等所有主流编辑器配置),适合在已有项目中补充AI编辑器配置\n\n支持的IDE类型:\n- all: 下载所有IDE配置\n- cursor: Cursor AI编辑器\n- 其他IDE类型见下方列表\n\n注意:如果未传入 ide 参数且无法从环境变量检测到 IDE,将提示错误并要求传入 ide 参数\n- windsurf: WindSurf AI编辑器\n- codebuddy: CodeBuddy AI编辑器\n- claude-code: Claude Code AI编辑器\n- cline: Cline AI编辑器\n- gemini-cli: Gemini CLI\n- opencode: OpenCode AI编辑器\n- qwen-code: 通义灵码\n- baidu-comate: 百度Comate\n- openai-codex-cli: OpenAI Codex CLI\n- augment-code: Augment Code\n- github-copilot: GitHub Copilot\n- roocode: RooCode AI编辑器\n- tongyi-lingma: 通义灵码\n- trae: Trae AI编辑器\n- qoder: Qoder AI编辑器\n- antigravity: Google Antigravity AI编辑器\n- vscode: Visual Studio Code\n- kiro: Kiro AI编辑器\n- aider: Aider AI编辑器\n\n特别说明:\n- rules 模板会自动包含当前 mcp 版本号信息(版本号:${ true ? "2.
|
|
10099
|
+
**CRITICAL**: This tool MUST be called FIRST when starting a new project.\n\n支持的模板:\n- react: React + CloudBase 全栈应用模板\n- vue: Vue + CloudBase 全栈应用模板\n- miniprogram: 微信小程序 + 云开发模板 \n- uniapp: UniApp + CloudBase 跨端应用模板\n- rules: 只包含AI编辑器配置文件(包含Cursor、WindSurf、CodeBuddy等所有主流编辑器配置),适合在已有项目中补充AI编辑器配置\n\n支持的IDE类型:\n- all: 下载所有IDE配置\n- cursor: Cursor AI编辑器\n- 其他IDE类型见下方列表\n\n注意:如果未传入 ide 参数且无法从环境变量检测到 IDE,将提示错误并要求传入 ide 参数\n- windsurf: WindSurf AI编辑器\n- codebuddy: CodeBuddy AI编辑器\n- claude-code: Claude Code AI编辑器\n- cline: Cline AI编辑器\n- gemini-cli: Gemini CLI\n- opencode: OpenCode AI编辑器\n- qwen-code: 通义灵码\n- baidu-comate: 百度Comate\n- openai-codex-cli: OpenAI Codex CLI\n- augment-code: Augment Code\n- github-copilot: GitHub Copilot\n- roocode: RooCode AI编辑器\n- tongyi-lingma: 通义灵码\n- trae: Trae AI编辑器\n- qoder: Qoder AI编辑器\n- antigravity: Google Antigravity AI编辑器\n- vscode: Visual Studio Code\n- kiro: Kiro AI编辑器\n- aider: Aider AI编辑器\n\n特别说明:\n- rules 模板会自动包含当前 mcp 版本号信息(版本号:${ true ? "2.11.0" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
|
|
10207
10100
|
inputSchema: {
|
|
10208
10101
|
template: zod_1.z
|
|
10209
10102
|
.enum(["react", "vue", "miniprogram", "uniapp", "rules"])
|
|
@@ -12470,90 +12363,70 @@ function registerSecurityRuleTools(server) {
|
|
|
12470
12363
|
},
|
|
12471
12364
|
}, async ({ resourceType, resourceId }) => {
|
|
12472
12365
|
const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
12473
|
-
|
|
12474
|
-
|
|
12475
|
-
|
|
12476
|
-
|
|
12477
|
-
|
|
12478
|
-
|
|
12479
|
-
|
|
12480
|
-
|
|
12481
|
-
|
|
12482
|
-
|
|
12483
|
-
|
|
12484
|
-
});
|
|
12485
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12486
|
-
}
|
|
12487
|
-
else if (resourceType === "function") {
|
|
12488
|
-
// 查询云函数安全规则
|
|
12489
|
-
result = await cloudbase.commonService().call({
|
|
12490
|
-
Action: "DescribeSecurityRule",
|
|
12491
|
-
Param: {
|
|
12492
|
-
ResourceType: "FUNCTION",
|
|
12493
|
-
EnvId: envId,
|
|
12494
|
-
},
|
|
12495
|
-
});
|
|
12496
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12497
|
-
}
|
|
12498
|
-
else if (resourceType === "storage") {
|
|
12499
|
-
// 查询存储安全规则
|
|
12500
|
-
result = await cloudbase.commonService().call({
|
|
12501
|
-
Action: "DescribeStorageSafeRule",
|
|
12502
|
-
Param: {
|
|
12503
|
-
Bucket: resourceId,
|
|
12504
|
-
EnvId: envId,
|
|
12505
|
-
},
|
|
12506
|
-
});
|
|
12507
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12508
|
-
}
|
|
12509
|
-
else if (resourceType === "sqlDatabase") {
|
|
12510
|
-
// TODO: 考虑是否有支持指定其他 instance、schema 的需求
|
|
12511
|
-
const instanceId = "default";
|
|
12512
|
-
const schema = envId;
|
|
12513
|
-
const tableName = resourceId;
|
|
12514
|
-
result = await cloudbase.commonService("lowcode").call({
|
|
12515
|
-
Action: "DescribeDataSourceBasicPolicy",
|
|
12516
|
-
Param: {
|
|
12517
|
-
EnvId: envId,
|
|
12518
|
-
ResourceType: "table",
|
|
12519
|
-
ResourceId: `${instanceId}#${schema}#${tableName}`,
|
|
12520
|
-
RoleIdentityList: ["allUser"],
|
|
12521
|
-
},
|
|
12522
|
-
});
|
|
12523
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12524
|
-
}
|
|
12525
|
-
else {
|
|
12526
|
-
throw new Error(`不支持的资源类型: ${resourceType}`);
|
|
12527
|
-
}
|
|
12528
|
-
return {
|
|
12529
|
-
content: [
|
|
12530
|
-
{
|
|
12531
|
-
type: "text",
|
|
12532
|
-
text: JSON.stringify({
|
|
12533
|
-
success: true,
|
|
12534
|
-
aclTag: result.AclTag,
|
|
12535
|
-
rule: result.Rule ?? null,
|
|
12536
|
-
raw: result,
|
|
12537
|
-
message: "安全规则读取成功",
|
|
12538
|
-
}, null, 2),
|
|
12539
|
-
},
|
|
12540
|
-
],
|
|
12541
|
-
};
|
|
12366
|
+
const cloudbase = await getManager();
|
|
12367
|
+
let result;
|
|
12368
|
+
if (resourceType === "noSqlDatabase") {
|
|
12369
|
+
result = await cloudbase.commonService().call({
|
|
12370
|
+
Action: "DescribeSafeRule",
|
|
12371
|
+
Param: {
|
|
12372
|
+
CollectionName: resourceId,
|
|
12373
|
+
EnvId: envId,
|
|
12374
|
+
},
|
|
12375
|
+
});
|
|
12376
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12542
12377
|
}
|
|
12543
|
-
|
|
12544
|
-
|
|
12545
|
-
|
|
12546
|
-
|
|
12547
|
-
|
|
12548
|
-
|
|
12549
|
-
|
|
12550
|
-
|
|
12551
|
-
|
|
12552
|
-
|
|
12553
|
-
|
|
12554
|
-
|
|
12555
|
-
|
|
12378
|
+
else if (resourceType === "function") {
|
|
12379
|
+
result = await cloudbase.commonService().call({
|
|
12380
|
+
Action: "DescribeSecurityRule",
|
|
12381
|
+
Param: {
|
|
12382
|
+
ResourceType: "FUNCTION",
|
|
12383
|
+
EnvId: envId,
|
|
12384
|
+
},
|
|
12385
|
+
});
|
|
12386
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12387
|
+
}
|
|
12388
|
+
else if (resourceType === "storage") {
|
|
12389
|
+
result = await cloudbase.commonService().call({
|
|
12390
|
+
Action: "DescribeStorageSafeRule",
|
|
12391
|
+
Param: {
|
|
12392
|
+
Bucket: resourceId,
|
|
12393
|
+
EnvId: envId,
|
|
12394
|
+
},
|
|
12395
|
+
});
|
|
12396
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12397
|
+
}
|
|
12398
|
+
else if (resourceType === "sqlDatabase") {
|
|
12399
|
+
const instanceId = "default";
|
|
12400
|
+
const schema = envId;
|
|
12401
|
+
const tableName = resourceId;
|
|
12402
|
+
result = await cloudbase.commonService("lowcode").call({
|
|
12403
|
+
Action: "DescribeDataSourceBasicPolicy",
|
|
12404
|
+
Param: {
|
|
12405
|
+
EnvId: envId,
|
|
12406
|
+
ResourceType: "table",
|
|
12407
|
+
ResourceId: `${instanceId}#${schema}#${tableName}`,
|
|
12408
|
+
RoleIdentityList: ["allUser"],
|
|
12409
|
+
},
|
|
12410
|
+
});
|
|
12411
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12412
|
+
}
|
|
12413
|
+
else {
|
|
12414
|
+
throw new Error(`不支持的资源类型: ${resourceType}`);
|
|
12556
12415
|
}
|
|
12416
|
+
return {
|
|
12417
|
+
content: [
|
|
12418
|
+
{
|
|
12419
|
+
type: "text",
|
|
12420
|
+
text: JSON.stringify({
|
|
12421
|
+
success: true,
|
|
12422
|
+
aclTag: result.AclTag,
|
|
12423
|
+
rule: result.Rule ?? null,
|
|
12424
|
+
raw: result,
|
|
12425
|
+
message: "安全规则读取成功",
|
|
12426
|
+
}, null, 2),
|
|
12427
|
+
},
|
|
12428
|
+
],
|
|
12429
|
+
};
|
|
12557
12430
|
});
|
|
12558
12431
|
// 写入安全规则 Tool
|
|
12559
12432
|
server.registerTool?.(exports.WRITE_SECURITY_RULE, {
|
|
@@ -12580,154 +12453,138 @@ function registerSecurityRuleTools(server) {
|
|
|
12580
12453
|
category: "security-rule",
|
|
12581
12454
|
},
|
|
12582
12455
|
}, async ({ resourceType, resourceId, aclTag, rule }) => {
|
|
12583
|
-
|
|
12584
|
-
|
|
12585
|
-
|
|
12586
|
-
|
|
12587
|
-
if (
|
|
12588
|
-
if (aclTag === "CUSTOM") {
|
|
12589
|
-
if (!rule)
|
|
12590
|
-
throw new Error("noSQL 数据库自定义安全规则(CUSTOM)必须提供 rule 字段");
|
|
12591
|
-
result = await cloudbase.commonService().call({
|
|
12592
|
-
Action: "ModifySafeRule",
|
|
12593
|
-
Param: {
|
|
12594
|
-
CollectionName: resourceId,
|
|
12595
|
-
EnvId: envId,
|
|
12596
|
-
AclTag: aclTag,
|
|
12597
|
-
Rule: rule,
|
|
12598
|
-
},
|
|
12599
|
-
});
|
|
12600
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12601
|
-
}
|
|
12602
|
-
else {
|
|
12603
|
-
result = await cloudbase.commonService().call({
|
|
12604
|
-
Action: "ModifyDatabaseACL",
|
|
12605
|
-
Param: {
|
|
12606
|
-
CollectionName: resourceId,
|
|
12607
|
-
EnvId: envId,
|
|
12608
|
-
AclTag: aclTag,
|
|
12609
|
-
},
|
|
12610
|
-
});
|
|
12611
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12612
|
-
}
|
|
12613
|
-
}
|
|
12614
|
-
else if (resourceType === "function") {
|
|
12615
|
-
if (aclTag !== "CUSTOM")
|
|
12616
|
-
throw new Error("云函数安全规则仅支持 CUSTOM 权限类别");
|
|
12456
|
+
const cloudbase = await getManager();
|
|
12457
|
+
const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
12458
|
+
let result;
|
|
12459
|
+
if (resourceType === "noSqlDatabase") {
|
|
12460
|
+
if (aclTag === "CUSTOM") {
|
|
12617
12461
|
if (!rule)
|
|
12618
|
-
throw new Error("
|
|
12462
|
+
throw new Error("noSQL 数据库自定义安全规则(CUSTOM)必须提供 rule 字段");
|
|
12619
12463
|
result = await cloudbase.commonService().call({
|
|
12620
|
-
Action: "
|
|
12464
|
+
Action: "ModifySafeRule",
|
|
12621
12465
|
Param: {
|
|
12622
|
-
|
|
12466
|
+
CollectionName: resourceId,
|
|
12623
12467
|
EnvId: envId,
|
|
12624
|
-
|
|
12468
|
+
AclTag: aclTag,
|
|
12625
12469
|
Rule: rule,
|
|
12626
12470
|
},
|
|
12627
12471
|
});
|
|
12628
12472
|
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12629
12473
|
}
|
|
12630
|
-
else
|
|
12631
|
-
|
|
12632
|
-
|
|
12633
|
-
|
|
12634
|
-
|
|
12635
|
-
|
|
12636
|
-
|
|
12637
|
-
|
|
12638
|
-
|
|
12639
|
-
|
|
12640
|
-
Rule: rule,
|
|
12641
|
-
},
|
|
12642
|
-
});
|
|
12643
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12644
|
-
}
|
|
12645
|
-
else {
|
|
12646
|
-
result = await cloudbase.commonService().call({
|
|
12647
|
-
Action: "ModifyStorageSafeRule",
|
|
12648
|
-
Param: {
|
|
12649
|
-
Bucket: resourceId,
|
|
12650
|
-
EnvId: envId,
|
|
12651
|
-
AclTag: aclTag,
|
|
12652
|
-
},
|
|
12653
|
-
});
|
|
12654
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12655
|
-
}
|
|
12474
|
+
else {
|
|
12475
|
+
result = await cloudbase.commonService().call({
|
|
12476
|
+
Action: "ModifyDatabaseACL",
|
|
12477
|
+
Param: {
|
|
12478
|
+
CollectionName: resourceId,
|
|
12479
|
+
EnvId: envId,
|
|
12480
|
+
AclTag: aclTag,
|
|
12481
|
+
},
|
|
12482
|
+
});
|
|
12483
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12656
12484
|
}
|
|
12657
|
-
|
|
12658
|
-
|
|
12659
|
-
|
|
12660
|
-
|
|
12661
|
-
|
|
12662
|
-
|
|
12663
|
-
|
|
12664
|
-
|
|
12665
|
-
|
|
12666
|
-
|
|
12667
|
-
|
|
12668
|
-
"
|
|
12669
|
-
|
|
12670
|
-
|
|
12671
|
-
|
|
12672
|
-
|
|
12673
|
-
|
|
12674
|
-
|
|
12675
|
-
|
|
12676
|
-
|
|
12677
|
-
|
|
12678
|
-
|
|
12679
|
-
|
|
12680
|
-
result = await cloudbase.commonService("lowcode").call({
|
|
12681
|
-
Action: "BatchCreateResourcePolicy",
|
|
12485
|
+
}
|
|
12486
|
+
else if (resourceType === "function") {
|
|
12487
|
+
if (aclTag !== "CUSTOM")
|
|
12488
|
+
throw new Error("云函数安全规则仅支持 CUSTOM 权限类别");
|
|
12489
|
+
if (!rule)
|
|
12490
|
+
throw new Error("云函数自定义安全规则(CUSTOM)必须提供 rule 字段");
|
|
12491
|
+
result = await cloudbase.commonService().call({
|
|
12492
|
+
Action: "ModifySecurityRule",
|
|
12493
|
+
Param: {
|
|
12494
|
+
AclTag: aclTag,
|
|
12495
|
+
EnvId: envId,
|
|
12496
|
+
ResourceType: "FUNCTION",
|
|
12497
|
+
Rule: rule,
|
|
12498
|
+
},
|
|
12499
|
+
});
|
|
12500
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12501
|
+
}
|
|
12502
|
+
else if (resourceType === "storage") {
|
|
12503
|
+
if (aclTag === "CUSTOM") {
|
|
12504
|
+
if (!rule)
|
|
12505
|
+
throw new Error("存储自定义安全规则(CUSTOM)必须提供 rule 字段");
|
|
12506
|
+
result = await cloudbase.commonService().call({
|
|
12507
|
+
Action: "ModifyStorageSafeRule",
|
|
12682
12508
|
Param: {
|
|
12509
|
+
Bucket: resourceId,
|
|
12683
12510
|
EnvId: envId,
|
|
12684
|
-
|
|
12511
|
+
AclTag: aclTag,
|
|
12512
|
+
Rule: rule,
|
|
12685
12513
|
},
|
|
12686
12514
|
});
|
|
12687
12515
|
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12688
|
-
function getRowPermission(policy) {
|
|
12689
|
-
return {
|
|
12690
|
-
READONLY: [
|
|
12691
|
-
{ Key: "all", Value: "r" },
|
|
12692
|
-
{ Key: "me", Value: "rw" },
|
|
12693
|
-
],
|
|
12694
|
-
PRIVATE: [{ Key: "me", Value: "rw" }],
|
|
12695
|
-
ADMINWRITE: [{ Key: "all", Value: "r" }],
|
|
12696
|
-
ADMINONLY: [],
|
|
12697
|
-
}[policy];
|
|
12698
|
-
}
|
|
12699
12516
|
}
|
|
12700
12517
|
else {
|
|
12701
|
-
|
|
12702
|
-
|
|
12703
|
-
|
|
12704
|
-
|
|
12705
|
-
|
|
12706
|
-
|
|
12707
|
-
text: JSON.stringify({
|
|
12708
|
-
success: true,
|
|
12709
|
-
requestId: result.RequestId,
|
|
12710
|
-
raw: result,
|
|
12711
|
-
message: "安全规则写入成功",
|
|
12712
|
-
}, null, 2),
|
|
12518
|
+
result = await cloudbase.commonService().call({
|
|
12519
|
+
Action: "ModifyStorageSafeRule",
|
|
12520
|
+
Param: {
|
|
12521
|
+
Bucket: resourceId,
|
|
12522
|
+
EnvId: envId,
|
|
12523
|
+
AclTag: aclTag,
|
|
12713
12524
|
},
|
|
12714
|
-
|
|
12715
|
-
|
|
12525
|
+
});
|
|
12526
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12527
|
+
}
|
|
12716
12528
|
}
|
|
12717
|
-
|
|
12718
|
-
|
|
12719
|
-
|
|
12720
|
-
|
|
12721
|
-
|
|
12722
|
-
|
|
12723
|
-
|
|
12724
|
-
|
|
12725
|
-
|
|
12726
|
-
|
|
12727
|
-
|
|
12728
|
-
|
|
12729
|
-
|
|
12529
|
+
else if (resourceType === "sqlDatabase") {
|
|
12530
|
+
if (aclTag === "CUSTOM") {
|
|
12531
|
+
throw new Error("SQL 数据库不支持自定义安全规则(CUSTOM)");
|
|
12532
|
+
}
|
|
12533
|
+
const schema = envId;
|
|
12534
|
+
const tableName = resourceId;
|
|
12535
|
+
const instanceId = "default";
|
|
12536
|
+
const resource = `${instanceId}#${schema}#${tableName}`;
|
|
12537
|
+
const resourceType = "table";
|
|
12538
|
+
const effect = "allow";
|
|
12539
|
+
const policyList = [
|
|
12540
|
+
"allUser",
|
|
12541
|
+
"anonymousUser",
|
|
12542
|
+
"externalUser",
|
|
12543
|
+
"internalUser",
|
|
12544
|
+
].map((roleIdentity) => ({
|
|
12545
|
+
RoleIdentity: roleIdentity,
|
|
12546
|
+
ResourceType: resourceType,
|
|
12547
|
+
ResourceId: resource,
|
|
12548
|
+
RowPermission: [],
|
|
12549
|
+
Effect: effect,
|
|
12550
|
+
}));
|
|
12551
|
+
policyList[0].RowPermission = getRowPermission(aclTag);
|
|
12552
|
+
result = await cloudbase.commonService("lowcode").call({
|
|
12553
|
+
Action: "BatchCreateResourcePolicy",
|
|
12554
|
+
Param: {
|
|
12555
|
+
EnvId: envId,
|
|
12556
|
+
PolicyList: policyList,
|
|
12557
|
+
},
|
|
12558
|
+
});
|
|
12559
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12560
|
+
function getRowPermission(policy) {
|
|
12561
|
+
return {
|
|
12562
|
+
READONLY: [
|
|
12563
|
+
{ Key: "all", Value: "r" },
|
|
12564
|
+
{ Key: "me", Value: "rw" },
|
|
12565
|
+
],
|
|
12566
|
+
PRIVATE: [{ Key: "me", Value: "rw" }],
|
|
12567
|
+
ADMINWRITE: [{ Key: "all", Value: "r" }],
|
|
12568
|
+
ADMINONLY: [],
|
|
12569
|
+
}[policy];
|
|
12570
|
+
}
|
|
12571
|
+
}
|
|
12572
|
+
else {
|
|
12573
|
+
throw new Error(`不支持的资源类型: ${resourceType}`);
|
|
12730
12574
|
}
|
|
12575
|
+
return {
|
|
12576
|
+
content: [
|
|
12577
|
+
{
|
|
12578
|
+
type: "text",
|
|
12579
|
+
text: JSON.stringify({
|
|
12580
|
+
success: true,
|
|
12581
|
+
requestId: result.RequestId,
|
|
12582
|
+
raw: result,
|
|
12583
|
+
message: "安全规则写入成功",
|
|
12584
|
+
}, null, 2),
|
|
12585
|
+
},
|
|
12586
|
+
],
|
|
12587
|
+
};
|
|
12731
12588
|
});
|
|
12732
12589
|
}
|
|
12733
12590
|
|
|
@@ -13410,64 +13267,44 @@ function registerDownloadTools(server) {
|
|
|
13410
13267
|
category: "download"
|
|
13411
13268
|
}
|
|
13412
13269
|
}, async ({ url, relativePath }) => {
|
|
13413
|
-
|
|
13414
|
-
// 验证相对路径安全性
|
|
13415
|
-
if (!isPathSafe(relativePath)) {
|
|
13416
|
-
return {
|
|
13417
|
-
content: [
|
|
13418
|
-
{
|
|
13419
|
-
type: "text",
|
|
13420
|
-
text: JSON.stringify({
|
|
13421
|
-
success: false,
|
|
13422
|
-
error: "不安全的相对路径",
|
|
13423
|
-
message: "相对路径包含路径遍历操作(../)或绝对路径,出于安全考虑已拒绝",
|
|
13424
|
-
suggestion: "请使用项目根目录下的相对路径,例如:'assets/images/logo.png'"
|
|
13425
|
-
}, null, 2)
|
|
13426
|
-
}
|
|
13427
|
-
]
|
|
13428
|
-
};
|
|
13429
|
-
}
|
|
13430
|
-
// 计算最终下载路径
|
|
13431
|
-
const targetPath = calculateDownloadPath(relativePath);
|
|
13432
|
-
const projectRoot = getProjectRoot();
|
|
13433
|
-
console.log(`📁 项目根目录: ${projectRoot}`);
|
|
13434
|
-
console.log(`📁 相对路径: ${relativePath}`);
|
|
13435
|
-
console.log(`📁 最终路径: ${targetPath}`);
|
|
13436
|
-
// 下载文件到指定路径
|
|
13437
|
-
const result = await downloadFileToPath(url, targetPath);
|
|
13438
|
-
return {
|
|
13439
|
-
content: [
|
|
13440
|
-
{
|
|
13441
|
-
type: "text",
|
|
13442
|
-
text: JSON.stringify({
|
|
13443
|
-
success: true,
|
|
13444
|
-
filePath: result.filePath,
|
|
13445
|
-
relativePath: relativePath,
|
|
13446
|
-
contentType: result.contentType,
|
|
13447
|
-
fileSize: result.fileSize,
|
|
13448
|
-
projectRoot: projectRoot,
|
|
13449
|
-
message: "文件下载成功到指定路径",
|
|
13450
|
-
note: `文件已保存到项目目录: ${relativePath}`
|
|
13451
|
-
}, null, 2)
|
|
13452
|
-
}
|
|
13453
|
-
]
|
|
13454
|
-
};
|
|
13455
|
-
}
|
|
13456
|
-
catch (error) {
|
|
13270
|
+
if (!isPathSafe(relativePath)) {
|
|
13457
13271
|
return {
|
|
13458
13272
|
content: [
|
|
13459
13273
|
{
|
|
13460
13274
|
type: "text",
|
|
13461
13275
|
text: JSON.stringify({
|
|
13462
13276
|
success: false,
|
|
13463
|
-
error:
|
|
13464
|
-
message: "
|
|
13465
|
-
suggestion: "
|
|
13277
|
+
error: "不安全的相对路径",
|
|
13278
|
+
message: "相对路径包含路径遍历操作(../)或绝对路径,出于安全考虑已拒绝",
|
|
13279
|
+
suggestion: "请使用项目根目录下的相对路径,例如:'assets/images/logo.png'"
|
|
13466
13280
|
}, null, 2)
|
|
13467
13281
|
}
|
|
13468
13282
|
]
|
|
13469
13283
|
};
|
|
13470
13284
|
}
|
|
13285
|
+
const targetPath = calculateDownloadPath(relativePath);
|
|
13286
|
+
const projectRoot = getProjectRoot();
|
|
13287
|
+
console.log(`📁 项目根目录: ${projectRoot}`);
|
|
13288
|
+
console.log(`📁 相对路径: ${relativePath}`);
|
|
13289
|
+
console.log(`📁 最终路径: ${targetPath}`);
|
|
13290
|
+
const result = await downloadFileToPath(url, targetPath);
|
|
13291
|
+
return {
|
|
13292
|
+
content: [
|
|
13293
|
+
{
|
|
13294
|
+
type: "text",
|
|
13295
|
+
text: JSON.stringify({
|
|
13296
|
+
success: true,
|
|
13297
|
+
filePath: result.filePath,
|
|
13298
|
+
relativePath: relativePath,
|
|
13299
|
+
contentType: result.contentType,
|
|
13300
|
+
fileSize: result.fileSize,
|
|
13301
|
+
projectRoot: projectRoot,
|
|
13302
|
+
message: "文件下载成功到指定路径",
|
|
13303
|
+
note: `文件已保存到项目目录: ${relativePath}`
|
|
13304
|
+
}, null, 2)
|
|
13305
|
+
}
|
|
13306
|
+
]
|
|
13307
|
+
};
|
|
13471
13308
|
});
|
|
13472
13309
|
}
|
|
13473
13310
|
|
|
@@ -13682,52 +13519,35 @@ function registerSQLDatabaseTools(server) {
|
|
|
13682
13519
|
category: CATEGORY,
|
|
13683
13520
|
},
|
|
13684
13521
|
}, async ({ sql }) => {
|
|
13685
|
-
|
|
13686
|
-
|
|
13687
|
-
|
|
13688
|
-
|
|
13689
|
-
|
|
13690
|
-
|
|
13691
|
-
|
|
13692
|
-
|
|
13693
|
-
|
|
13522
|
+
const cloudbase = await getManager();
|
|
13523
|
+
const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
13524
|
+
const schemaId = envId;
|
|
13525
|
+
const instanceId = "default";
|
|
13526
|
+
const result = await cloudbase.commonService("tcb", "2018-06-08").call({
|
|
13527
|
+
Action: "RunSql",
|
|
13528
|
+
Param: {
|
|
13529
|
+
EnvId: envId,
|
|
13530
|
+
Sql: sql,
|
|
13531
|
+
DbInstance: {
|
|
13694
13532
|
EnvId: envId,
|
|
13695
|
-
|
|
13696
|
-
|
|
13697
|
-
EnvId: envId,
|
|
13698
|
-
InstanceId: instanceId,
|
|
13699
|
-
Schema: schemaId,
|
|
13700
|
-
},
|
|
13533
|
+
InstanceId: instanceId,
|
|
13534
|
+
Schema: schemaId,
|
|
13701
13535
|
},
|
|
13702
|
-
}
|
|
13703
|
-
|
|
13704
|
-
|
|
13705
|
-
|
|
13706
|
-
|
|
13707
|
-
|
|
13708
|
-
|
|
13709
|
-
|
|
13710
|
-
|
|
13711
|
-
|
|
13712
|
-
|
|
13713
|
-
},
|
|
13714
|
-
|
|
13715
|
-
|
|
13716
|
-
}
|
|
13717
|
-
catch (error) {
|
|
13718
|
-
return {
|
|
13719
|
-
content: [
|
|
13720
|
-
{
|
|
13721
|
-
type: "text",
|
|
13722
|
-
text: JSON.stringify({
|
|
13723
|
-
success: false,
|
|
13724
|
-
error: error.message,
|
|
13725
|
-
message: "SQL query execution failed",
|
|
13726
|
-
}, null, 2),
|
|
13727
|
-
},
|
|
13728
|
-
],
|
|
13729
|
-
};
|
|
13730
|
-
}
|
|
13536
|
+
},
|
|
13537
|
+
});
|
|
13538
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
13539
|
+
return {
|
|
13540
|
+
content: [
|
|
13541
|
+
{
|
|
13542
|
+
type: "text",
|
|
13543
|
+
text: JSON.stringify({
|
|
13544
|
+
success: true,
|
|
13545
|
+
message: "SQL query executed successfully",
|
|
13546
|
+
result,
|
|
13547
|
+
}, null, 2),
|
|
13548
|
+
},
|
|
13549
|
+
],
|
|
13550
|
+
};
|
|
13731
13551
|
});
|
|
13732
13552
|
// executeWriteSQL
|
|
13733
13553
|
server.registerTool?.("executeWriteSQL", {
|
|
@@ -13746,52 +13566,35 @@ function registerSQLDatabaseTools(server) {
|
|
|
13746
13566
|
category: CATEGORY,
|
|
13747
13567
|
},
|
|
13748
13568
|
}, async ({ sql }) => {
|
|
13749
|
-
|
|
13750
|
-
|
|
13751
|
-
|
|
13752
|
-
|
|
13753
|
-
|
|
13754
|
-
|
|
13755
|
-
|
|
13756
|
-
|
|
13757
|
-
|
|
13569
|
+
const cloudbase = await getManager();
|
|
13570
|
+
const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
13571
|
+
const schemaId = envId;
|
|
13572
|
+
const instanceId = "default";
|
|
13573
|
+
const result = await cloudbase.commonService("tcb", "2018-06-08").call({
|
|
13574
|
+
Action: "RunSql",
|
|
13575
|
+
Param: {
|
|
13576
|
+
EnvId: envId,
|
|
13577
|
+
Sql: sql,
|
|
13578
|
+
DbInstance: {
|
|
13758
13579
|
EnvId: envId,
|
|
13759
|
-
|
|
13760
|
-
|
|
13761
|
-
EnvId: envId,
|
|
13762
|
-
InstanceId: instanceId,
|
|
13763
|
-
Schema: schemaId,
|
|
13764
|
-
},
|
|
13580
|
+
InstanceId: instanceId,
|
|
13581
|
+
Schema: schemaId,
|
|
13765
13582
|
},
|
|
13766
|
-
}
|
|
13767
|
-
|
|
13768
|
-
|
|
13769
|
-
|
|
13770
|
-
|
|
13771
|
-
|
|
13772
|
-
|
|
13773
|
-
|
|
13774
|
-
|
|
13775
|
-
|
|
13776
|
-
|
|
13777
|
-
},
|
|
13778
|
-
|
|
13779
|
-
|
|
13780
|
-
}
|
|
13781
|
-
catch (error) {
|
|
13782
|
-
return {
|
|
13783
|
-
content: [
|
|
13784
|
-
{
|
|
13785
|
-
type: "text",
|
|
13786
|
-
text: JSON.stringify({
|
|
13787
|
-
success: false,
|
|
13788
|
-
error: error.message,
|
|
13789
|
-
message: "SQL statement execution failed",
|
|
13790
|
-
}, null, 2),
|
|
13791
|
-
},
|
|
13792
|
-
],
|
|
13793
|
-
};
|
|
13794
|
-
}
|
|
13583
|
+
},
|
|
13584
|
+
});
|
|
13585
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
13586
|
+
return {
|
|
13587
|
+
content: [
|
|
13588
|
+
{
|
|
13589
|
+
type: "text",
|
|
13590
|
+
text: JSON.stringify({
|
|
13591
|
+
success: true,
|
|
13592
|
+
message: `SQL statement executed successfully. If you just created a table, make sure to check its security rule is set to a proper value by using \`${security_rule_js_1.WRITE_SECURITY_RULE}\` and \`${security_rule_js_1.READ_SECURITY_RULE}\` tools.`,
|
|
13593
|
+
result,
|
|
13594
|
+
}, null, 2),
|
|
13595
|
+
},
|
|
13596
|
+
],
|
|
13597
|
+
};
|
|
13795
13598
|
});
|
|
13796
13599
|
}
|
|
13797
13600
|
|