@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.
Files changed (4) hide show
  1. package/dist/cli.cjs +3 -3
  2. package/dist/index.cjs +1990 -1715
  3. package/dist/index.js +1470 -1667
  4. 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.9.0" || 0}
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
- // 动态导入 open 模块,兼容 ESM/CJS 环境
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
- return await (0, open_1.default)(url, options);
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(["createCollection", "updateCollection"])
5271
- .describe(`createCollection: 创建集合
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: false,
5350
+ destructiveHint: true,
5300
5351
  idempotentHint: false,
5301
5352
  openWorldHint: true,
5302
5353
  category: CATEGORY,
5303
5354
  },
5304
5355
  }, async ({ action, collectionName, updateOptions }) => {
5305
- try {
5306
- const cloudbase = await getManager();
5307
- if (action === "createCollection") {
5308
- const result = await cloudbase.database.createCollection(collectionName);
5309
- (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
5310
- return {
5311
- content: [
5312
- {
5313
- type: "text",
5314
- text: JSON.stringify({
5315
- success: true,
5316
- requestId: result.RequestId,
5317
- action,
5318
- message: "云开发数据库集合创建成功",
5319
- }, null, 2),
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
- catch (error) {
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: false,
5385
+ success: true,
5386
+ requestId: result.RequestId,
5353
5387
  action,
5354
- error: error.message,
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([zod_1.z.object({}).passthrough(), zod_1.z.string()])
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
- try {
5390
- const cloudbase = await getManager();
5391
- const instanceId = await getDatabaseInstanceId(getManager);
5392
- // 兼容对象和字符串
5393
- const toJSONString = (v) => typeof v === "object" && v !== null ? JSON.stringify(v) : v;
5394
- const result = await cloudbase.commonService("tcb", "2018-06-08").call({
5395
- Action: "QueryRecords",
5396
- Param: {
5397
- TableName: collectionName,
5398
- MgoQuery: toJSONString(query),
5399
- MgoProjection: toJSONString(projection),
5400
- MgoSort: toJSONString(sort),
5401
- MgoLimit: limit ?? 100, // 默认返回100条,避免底层SDK缺参报错
5402
- MgoOffset: offset,
5403
- Tag: instanceId,
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
- (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
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.enum(["insert", "update", "delete"])
5443
- .describe(`createCollection: 创建数据
5444
- updateCollection: 更新数据
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
- try {
5545
- const cloudbase = await getManager();
5546
- const instanceId = await getDatabaseInstanceId(getManager);
5547
- // 将对象数组序列化为字符串数组
5548
- const docsAsStrings = documents.map((doc) => JSON.stringify(doc));
5549
- const result = await cloudbase.commonService("tcb", "2018-06-08").call({
5550
- Action: "PutItem",
5551
- Param: {
5552
- TableName: collectionName,
5553
- MgoDocs: docsAsStrings,
5554
- Tag: instanceId,
5555
- },
5556
- });
5557
- (0, cloudbase_manager_js_1.logCloudBaseResult)(logger, result);
5558
- return JSON.stringify({
5559
- success: true,
5560
- requestId: result.RequestId,
5561
- insertedIds: result.InsertedIds,
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
- try {
5575
- const cloudbase = await getManager();
5576
- const instanceId = await getDatabaseInstanceId(getManager);
5577
- const toJSONString = (v) => typeof v === "object" && v !== null ? JSON.stringify(v) : v;
5578
- const result = await cloudbase.commonService("tcb", "2018-06-08").call({
5579
- Action: "UpdateItem",
5580
- Param: {
5581
- TableName: collectionName,
5582
- MgoQuery: toJSONString(query),
5583
- MgoUpdate: toJSONString(update),
5584
- MgoIsMulti: isMulti,
5585
- MgoUpsert: upsert,
5586
- Tag: instanceId,
5587
- },
5588
- });
5589
- (0, cloudbase_manager_js_1.logCloudBaseResult)(logger, result);
5590
- return JSON.stringify({
5591
- success: true,
5592
- requestId: result.RequestId,
5593
- modifiedCount: result.ModifiedNum,
5594
- matchedCount: result.MatchedNum,
5595
- upsertedId: result.UpsertedId,
5596
- message: "文档更新成功",
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
- try {
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: "DeleteItem",
5614
- Param: {
5615
- TableName: collectionName,
5616
- MgoQuery: toJSONString(query),
5617
- MgoIsMulti: isMulti,
5618
- Tag: instanceId,
5619
- },
5620
- });
5621
- (0, cloudbase_manager_js_1.logCloudBaseResult)(logger, result);
5622
- return JSON.stringify({
5623
- success: true,
5624
- requestId: result.RequestId,
5625
- deleted: result.Deleted,
5626
- message: "文档删除成功",
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
- try {
6206
- const cloudbase = await getManager();
6207
- let currentEnvId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
6208
- let result;
6209
- switch (action) {
6210
- case "get":
6211
- if (!name) {
6212
- throw new Error("获取数据模型需要提供模型名称");
6213
- }
6214
- try {
6215
- result = await cloudbase.commonService("lowcode").call({
6216
- Action: "DescribeBasicDataSource",
6217
- Param: {
6218
- EnvId: currentEnvId,
6219
- Name: name,
6220
- },
6221
- });
6222
- (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
6223
- // 只保留基础字段,过滤掉冗余信息,并简化Schema
6224
- let simplifiedSchema = null;
6225
- // 解析并简化Schema
6226
- if (result.Data.Schema) {
6227
- try {
6228
- const schema = JSON.parse(result.Data.Schema);
6229
- const properties = schema.properties || {};
6230
- // 提取用户定义的字段(排除系统字段)
6231
- const userFields = Object.keys(properties)
6232
- .filter((key) => !properties[key]["x-system"]) // 排除系统字段
6233
- .map((key) => {
6234
- const field = properties[key];
6235
- return parseFieldStructure(field, key, schema);
6236
- });
6237
- // 提取关联关系
6238
- const relations = userFields
6239
- .filter((field) => field.linkage)
6240
- .map((field) => ({
6241
- field: field.name,
6242
- type: field.format,
6243
- title: field.title,
6244
- targetModel: field.linkage.parentDataSourceName,
6245
- foreignKey: field.linkage.parentFieldKey,
6246
- displayField: field.linkage.parentFieldTitle,
6247
- }));
6248
- simplifiedSchema = {
6249
- userFields,
6250
- relations,
6251
- totalFields: Object.keys(properties).length,
6252
- userFieldsCount: userFields.length,
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
- // 尝试生成Mermaid图表
6260
- let mermaidDiagram = null;
6261
- if (result.Data.Schema &&
6262
- jsonSchemaToMermaid &&
6263
- simplifiedSchema &&
6264
- !simplifiedSchema.error) {
6265
- try {
6266
- const mainSchema = JSON.parse(result.Data.Schema);
6267
- const schemasMap = {
6268
- [name]: mainSchema,
6269
- };
6270
- // 获取关联模型的 schema
6271
- if (simplifiedSchema.relations &&
6272
- simplifiedSchema.relations.length > 0) {
6273
- const relatedModelNames = [
6274
- ...new Set(simplifiedSchema.relations.map((rel) => rel.targetModel)),
6275
- ];
6276
- for (const relatedModelName of relatedModelNames) {
6277
- try {
6278
- const relatedResult = await cloudbase
6279
- .commonService("lowcode")
6280
- .call({
6281
- Action: "DescribeBasicDataSource",
6282
- Param: {
6283
- EnvId: currentEnvId,
6284
- Name: relatedModelName,
6285
- },
6286
- });
6287
- if (relatedResult.Data && relatedResult.Data.Schema) {
6288
- schemasMap[relatedModelName] = JSON.parse(relatedResult.Data.Schema);
6289
- }
6290
- }
6291
- catch (e) {
6292
- console.warn(`获取关联模型 ${relatedModelName} schema 失败:`, e);
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
- const simplifiedModel = {
6304
- DbInstanceType: result.Data.DbInstanceType,
6305
- Title: result.Data.Title,
6306
- Description: result.Data.Description,
6307
- Name: result.Data.Name,
6308
- UpdatedAt: result.Data.UpdatedAt,
6309
- Schema: simplifiedSchema,
6310
- mermaid: mermaidDiagram,
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: true,
6349
+ success: false,
6318
6350
  action: "get",
6319
- data: simplifiedModel,
6320
- message: "获取数据模型成功",
6351
+ error: "ResourceNotFound",
6352
+ message: `数据模型 ${name} 不存在`,
6321
6353
  }, null, 2),
6322
6354
  },
6323
6355
  ],
6324
6356
  };
6325
6357
  }
6326
- catch (error) {
6327
- if (error.original?.Code === "ResourceNotFound") {
6328
- return {
6329
- content: [
6330
- {
6331
- type: "text",
6332
- text: JSON.stringify({
6333
- success: false,
6334
- action: "get",
6335
- error: "ResourceNotFound",
6336
- message: `数据模型 ${name} 不存在`,
6337
- }, null, 2),
6338
- },
6339
- ],
6340
- };
6341
- }
6342
- throw error;
6343
- }
6344
- case "list":
6345
- // 构建请求参数
6346
- const listParams = {
6347
- EnvId: currentEnvId,
6348
- PageIndex: 1,
6349
- PageSize: 1000,
6350
- QuerySystemModel: true, // 查询系统模型
6351
- QueryConnector: 0, // 0 表示数据模型
6352
- };
6353
- // 只有当 names 参数存在且不为空时才添加过滤条件
6354
- if (names && names.length > 0) {
6355
- listParams.DataSourceNames = names;
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: "DescribeDataSourceList",
6359
- Param: listParams,
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
- const models = result.Data?.Rows || [];
6363
- // 只保留基础字段,list操作不返回Schema
6364
- const simplifiedModels = models.map((model) => ({
6365
- DbInstanceType: model.DbInstanceType,
6366
- Title: model.Title,
6367
- Description: model.Description,
6368
- Name: model.Name,
6369
- UpdatedAt: model.UpdatedAt,
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: "list",
6378
- data: simplifiedModels,
6379
- count: simplifiedModels.length,
6380
- message: "获取数据模型列表成功",
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
- case "docs":
6386
- if (!name) {
6387
- throw new Error("生成SDK文档需要提供模型名称");
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: true,
6474
+ success: false,
6441
6475
  action: "docs",
6442
- modelName: name,
6443
- modelTitle: result.Data.Title,
6444
- docs,
6445
- message: "SDK使用文档生成成功",
6476
+ error: "ResourceNotFound",
6477
+ message: `数据模型 ${name} 不存在`,
6446
6478
  }, null, 2),
6447
6479
  },
6448
6480
  ],
6449
6481
  };
6450
6482
  }
6451
- catch (error) {
6452
- if (error.original?.Code === "ResourceNotFound") {
6453
- return {
6454
- content: [
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
- try {
6561
- const cloudbase = await getManager();
6562
- let currentEnvId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
6563
- // 使用mermaidToJsonSchema转换Mermaid图表
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: status === "success",
6647
- requestId: result.RequestId,
6648
- taskId: taskId,
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
- catch (error) {
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
- error: error.message || error.original?.Message || "未知错误",
6673
- code: error.original?.Code,
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
- try {
7495
- const manager = await getManager();
7496
- const EnvId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
7497
- const result = await manager.commonService().call({
7498
- Action: 'ActivateInviteCode',
7499
- Param: { InviteCode, EnvId }
7500
- });
7501
- (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
7502
- return {
7503
- content: [
7504
- {
7505
- type: "text",
7506
- text: JSON.stringify({
7507
- ErrorCode: result?.ErrorCode || '',
7508
- ErrorMsg: result?.ErrorMsg || '',
7509
- RequestId: result?.RequestId || ''
7510
- }, null, 2)
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
- try {
7574
- const input = args;
7575
- const manager = await getManager();
7576
- if (!manager) {
7577
- throw new Error("Failed to initialize CloudBase manager. Please check your credentials and environment configuration.");
7578
- }
7579
- const storageService = manager.storage;
7580
- switch (input.action) {
7581
- case 'list': {
7582
- const result = await storageService.listDirectoryFiles(input.cloudPath);
7583
- return {
7584
- content: [
7585
- {
7586
- type: "text",
7587
- text: JSON.stringify({
7588
- success: true,
7589
- data: {
7590
- action: 'list',
7591
- cloudPath: input.cloudPath,
7592
- files: result || [],
7593
- totalCount: result?.length || 0
7594
- },
7595
- message: `Successfully listed ${result?.length || 0} files in directory '${input.cloudPath}'`
7596
- }, null, 2)
7597
- }
7598
- ]
7599
- };
7600
- }
7601
- case 'info': {
7602
- const result = await storageService.getFileInfo(input.cloudPath);
7603
- return {
7604
- content: [
7605
- {
7606
- type: "text",
7607
- text: JSON.stringify({
7608
- success: true,
7609
- data: {
7610
- action: 'info',
7611
- cloudPath: input.cloudPath,
7612
- fileInfo: result
7613
- },
7614
- message: `Successfully retrieved file info for '${input.cloudPath}'`
7615
- }, null, 2)
7616
- }
7617
- ]
7618
- };
7619
- }
7620
- case 'url': {
7621
- const result = await storageService.getTemporaryUrl([{
7622
- cloudPath: input.cloudPath,
7623
- maxAge: input.maxAge || 3600
7624
- }]);
7625
- return {
7626
- content: [
7627
- {
7628
- type: "text",
7629
- text: JSON.stringify({
7630
- success: true,
7631
- data: {
7632
- action: 'url',
7633
- cloudPath: input.cloudPath,
7634
- temporaryUrl: result[0]?.url || "",
7635
- expireTime: `${input.maxAge || 3600}秒`,
7636
- fileId: result[0]?.fileId || ""
7637
- },
7638
- message: `Successfully generated temporary URL for '${input.cloudPath}'`
7639
- }, null, 2)
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
- catch (error) {
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
- try {
7677
- const input = args;
7678
- const manager = await getManager();
7679
- if (!manager) {
7680
- throw new Error("Failed to initialize CloudBase manager. Please check your credentials and environment configuration.");
7681
- }
7682
- const storageService = manager.storage;
7683
- switch (input.action) {
7684
- case 'upload': {
7685
- if (input.isDirectory) {
7686
- // 上传目录
7687
- await storageService.uploadDirectory({
7688
- localPath: input.localPath,
7689
- cloudPath: input.cloudPath,
7690
- onProgress: (progressData) => {
7691
- console.log("Upload directory progress:", progressData);
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
- case 'download': {
7731
- if (input.isDirectory) {
7732
- // 下载目录
7733
- await storageService.downloadDirectory({
7734
- cloudPath: input.cloudPath,
7735
- localPath: input.localPath
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
- case 'delete': {
7764
- if (!input.force) {
7765
- return {
7766
- content: [
7767
- {
7768
- type: "text",
7769
- text: JSON.stringify({
7770
- success: false,
7771
- error: "Delete operation requires confirmation",
7772
- message: "Please set force: true to confirm deletion. This action cannot be undone."
7773
- }, null, 2)
7774
- }
7775
- ]
7776
- };
7777
- }
7778
- if (input.isDirectory) {
7779
- // 删除目录
7780
- await storageService.deleteDirectory(input.cloudPath);
7781
- }
7782
- else {
7783
- // 删除文件
7784
- await storageService.deleteFile([input.cloudPath]);
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: true,
7792
- data: {
7793
- action: 'delete',
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
- default:
7805
- throw new Error(`Unsupported action: ${input.action}`);
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
- catch (error) {
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
- try {
7995
- const input = args;
7996
- const manager = await getManager();
7997
- if (!manager) {
7998
- throw new Error("Failed to initialize CloudBase manager. Please check your credentials and environment configuration.");
7999
- }
8000
- const cloudrunService = manager.cloudrun;
8001
- switch (input.action) {
8002
- case 'list': {
8003
- const listParams = {
8004
- pageSize: input.pageSize,
8005
- pageNum: input.pageNum,
8006
- };
8007
- if (input.serverName) {
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
- case 'detail': {
8036
- const serverName = input.detailServerName || input.serverName;
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
- case 'templates': {
8068
- const result = await cloudrunService.getTemplates();
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: true,
8075
- data: {
8076
- templates: result || []
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
- default:
8085
- throw new Error(`Unsupported action: ${input.action}`);
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
- catch (error) {
8089
- return {
8090
- content: [
8091
- {
8092
- type: "text",
8093
- text: JSON.stringify({
8094
- success: false,
8095
- error: error.message || 'Unknown error occurred',
8096
- message: "Failed to query CloudRun information. Please check your permissions and try again."
8097
- }, null, 2)
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
- try {
8119
- const input = args;
8120
- const manager = await getManager();
8121
- if (!manager) {
8122
- throw new Error("Failed to initialize CloudBase manager. Please check your credentials and environment configuration.");
8123
- }
8124
- const cloudrunService = manager.cloudrun;
8125
- let targetPath;
8126
- // Validate and normalize path for operations that require it
8127
- if (input.targetPath) {
8128
- targetPath = validateAndNormalizePath(input.targetPath);
8129
- }
8130
- switch (input.action) {
8131
- case 'createAgent': {
8132
- if (!targetPath) {
8133
- throw new Error("targetPath is required for createAgent operation");
8134
- }
8135
- if (!input.agentConfig) {
8136
- throw new Error("agentConfig is required for createAgent operation");
8137
- }
8138
- const { agentName, botTag, description, template = 'blank' } = input.agentConfig;
8139
- // Generate BotId
8140
- const botId = botTag ? `ibot-${agentName}-${botTag}` : `ibot-${agentName}-${Date.now()}`;
8141
- // Create Agent using CloudBase Manager
8142
- const agentResult = await manager.agent.createFunctionAgent(targetPath, {
8143
- Name: agentName,
8144
- BotId: botId,
8145
- Introduction: description || `Agent created by ${agentName}`,
8146
- Avatar: undefined
8147
- });
8148
- // Create project directory
8149
- const projectDir = path_1.default.join(targetPath, input.serverName);
8150
- if (!fs_1.default.existsSync(projectDir)) {
8151
- fs_1.default.mkdirSync(projectDir, { recursive: true });
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
- // Generate package.json
8154
- const packageJson = {
8155
- name: input.serverName,
8156
- version: "1.0.0",
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
- fs_1.default.writeFileSync(path_1.default.join(projectDir, 'index.js'), indexJsContent);
8219
- // Generate cloudbaserc.json
8220
- const currentEnvId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
8221
- const cloudbasercContent = {
8222
- envId: currentEnvId,
8223
- cloudrun: {
8224
- name: input.serverName
8225
- }
8226
- };
8227
- fs_1.default.writeFileSync(path_1.default.join(projectDir, 'cloudbaserc.json'), JSON.stringify(cloudbasercContent, null, 2));
8228
- // Generate README.md
8229
- const readmeContent = `# ${agentName} Agent
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
- fs_1.default.writeFileSync(path_1.default.join(projectDir, 'README.md'), readmeContent);
8275
- return {
8276
- content: [
8277
- {
8278
- type: "text",
8279
- text: JSON.stringify({
8280
- success: true,
8281
- data: {
8282
- agentName: agentName,
8283
- botId: botId,
8284
- projectDir: projectDir,
8285
- serverName: input.serverName,
8286
- template: template,
8287
- filesCreated: ['package.json', 'index.js', 'cloudbaserc.json', 'README.md']
8288
- },
8289
- message: `Successfully created Agent '${agentName}' with BotId '${botId}' in ${projectDir}`
8290
- }, null, 2)
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
- case 'deploy': {
8296
- if (!targetPath) {
8297
- throw new Error("targetPath is required for deploy operation");
8298
- }
8299
- // Determine service type - use input.serverType if provided, otherwise auto-detect
8300
- let serverType;
8301
- if (input.serverType) {
8302
- serverType = input.serverType;
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
- else {
8305
- try {
8306
- // First try to get existing service details
8307
- const details = await cloudrunService.detail({ serverName: input.serverName });
8308
- serverType = details.BaseInfo?.ServerType || 'container';
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
- catch (e) {
8311
- // If service doesn't exist, determine by project structure
8312
- const dockerfilePath = path_1.default.join(targetPath, 'Dockerfile');
8313
- if (fs_1.default.existsSync(dockerfilePath)) {
8314
- serverType = 'container';
8315
- }
8316
- else {
8317
- // Check if it's a Node.js function project (has package.json with specific structure)
8318
- const packageJsonPath = path_1.default.join(targetPath, 'package.json');
8319
- if (fs_1.default.existsSync(packageJsonPath)) {
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
- catch (parseError) {
8235
+ else {
8332
8236
  serverType = 'container';
8333
8237
  }
8334
8238
  }
8335
- else {
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
- serviceUrl = ""; // URL not available
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
- case 'run': {
8440
- if (!targetPath) {
8441
- throw new Error("targetPath is required for run operation");
8442
- }
8443
- // Do not support container services locally: basic heuristic - if Dockerfile exists, treat as container
8444
- const dockerfilePath = path_1.default.join(targetPath, 'Dockerfile');
8445
- if (fs_1.default.existsSync(dockerfilePath)) {
8446
- throw new Error("Local run is only supported for function-type CloudRun services. Container services are not supported.");
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
- // Check if this is an Agent project
8449
- const isAgent = checkIfAgentProject(targetPath);
8450
- const runMode = input.runOptions?.runMode || (isAgent ? 'agent' : 'normal');
8451
- // Check if service is already running and verify process exists
8452
- if (runningProcesses.has(input.serverName)) {
8453
- const existingPid = runningProcesses.get(input.serverName);
8454
- try {
8455
- // Check if process actually exists
8456
- process.kill(existingPid, 0);
8457
- return {
8458
- content: [
8459
- {
8460
- type: "text",
8461
- text: JSON.stringify({
8462
- success: true,
8463
- data: {
8464
- serviceName: input.serverName,
8465
- status: 'running',
8466
- pid: existingPid,
8467
- cwd: targetPath
8468
- },
8469
- message: `Service '${input.serverName}' is already running locally (pid=${existingPid})`
8470
- }, null, 2)
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
- catch (error) {
8476
- // Process doesn't exist, remove from tracking
8477
- runningProcesses.delete(input.serverName);
8303
+ else {
8304
+ serviceUrl = ""; // URL not available
8478
8305
  }
8479
8306
  }
8480
- const runPort = input.runOptions?.port ?? 3000;
8481
- const extraEnv = input.runOptions?.envParams ?? {};
8482
- // Set environment variables for functions-framework
8483
- const env = {
8484
- ...process.env,
8485
- PORT: String(runPort),
8486
- ...extraEnv,
8487
- // Add functions-framework specific environment variables
8488
- ENABLE_CORS: 'true',
8489
- ALLOWED_ORIGINS: '*'
8490
- };
8491
- // Choose execution method based on run mode
8492
- let child;
8493
- let command;
8494
- if (runMode === 'agent') {
8495
- // For Agent mode, use a different approach since functions-framework doesn't support Agent mode
8496
- // We'll use a custom script that sets up the Agent environment
8497
- command = `node -e "
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
- child = (0, child_process_1.spawn)(process.execPath, ['-e', command], {
8507
- cwd: targetPath,
8508
- env,
8509
- stdio: ['ignore', 'pipe', 'pipe'],
8510
- detached: true
8511
- });
8512
- }
8513
- else {
8514
- // Normal function mode
8515
- command = `node -e "
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
- child = (0, child_process_1.spawn)(process.execPath, ['-e', command], {
8524
- cwd: targetPath,
8525
- env,
8526
- stdio: ['ignore', 'pipe', 'pipe'],
8527
- detached: true
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
- case 'download': {
8565
- if (!targetPath) {
8566
- throw new Error("targetPath is required for download operation");
8567
- }
8568
- const result = await cloudrunService.download({
8569
- serverName: input.serverName,
8570
- targetPath: targetPath,
8571
- });
8572
- // Generate cloudbaserc.json configuration file
8573
- const currentEnvId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
8574
- const cloudbasercPath = path_1.default.join(targetPath, 'cloudbaserc.json');
8575
- const cloudbasercContent = {
8576
- envId: currentEnvId,
8577
- cloudrun: {
8578
- name: input.serverName
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
- try {
8582
- fs_1.default.writeFileSync(cloudbasercPath, JSON.stringify(cloudbasercContent, null, 2));
8583
- }
8584
- catch (error) {
8585
- // Ignore cloudbaserc.json creation errors
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
- case 'delete': {
8606
- if (!input.force) {
8607
- return {
8608
- content: [
8609
- {
8610
- type: "text",
8611
- text: JSON.stringify({
8612
- success: false,
8613
- error: "Delete operation requires confirmation",
8614
- message: "Please set force: true to confirm deletion of the service. This action cannot be undone."
8615
- }, null, 2)
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
- const result = await cloudrunService.delete({
8621
- serverName: input.serverName,
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
- case 'init': {
8640
- if (!targetPath) {
8641
- throw new Error("targetPath is required for init operation");
8642
- }
8643
- const result = await cloudrunService.init({
8644
- serverName: input.serverName,
8645
- targetPath: targetPath,
8646
- template: input.template,
8647
- });
8648
- // Generate cloudbaserc.json configuration file
8649
- const currentEnvId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
8650
- const cloudbasercPath = path_1.default.join(targetPath, input.serverName, 'cloudbaserc.json');
8651
- const cloudbasercContent = {
8652
- envId: currentEnvId,
8653
- cloudrun: {
8654
- name: input.serverName
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
- try {
8658
- fs_1.default.writeFileSync(cloudbasercPath, JSON.stringify(cloudbasercContent, null, 2));
8659
- }
8660
- catch (error) {
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: true,
8669
- data: {
8670
- serviceName: input.serverName,
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
- default:
8683
- throw new Error(`Unsupported action: ${input.action}`);
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
- catch (error) {
8687
- return {
8688
- content: [
8689
- {
8690
- type: "text",
8691
- text: JSON.stringify({
8692
- success: false,
8693
- error: error.message || 'Unknown error occurred',
8694
- message: `Failed to ${args.action} CloudRun service. Please check your permissions and parameters.`
8695
- }, null, 2)
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.9.0" || 0;
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.9.0" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
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
- try {
12474
- const cloudbase = await getManager();
12475
- let result;
12476
- if (resourceType === "noSqlDatabase") {
12477
- // 查询数据库安全规则
12478
- result = await cloudbase.commonService().call({
12479
- Action: "DescribeSafeRule",
12480
- Param: {
12481
- CollectionName: resourceId,
12482
- EnvId: envId,
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
- catch (error) {
12544
- return {
12545
- content: [
12546
- {
12547
- type: "text",
12548
- text: JSON.stringify({
12549
- success: false,
12550
- error: error.message,
12551
- message: "安全规则读取失败",
12552
- }, null, 2),
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
- try {
12584
- const cloudbase = await getManager();
12585
- const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
12586
- let result;
12587
- if (resourceType === "noSqlDatabase") {
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("云函数自定义安全规则(CUSTOM)必须提供 rule 字段");
12462
+ throw new Error("noSQL 数据库自定义安全规则(CUSTOM)必须提供 rule 字段");
12619
12463
  result = await cloudbase.commonService().call({
12620
- Action: "ModifySecurityRule",
12464
+ Action: "ModifySafeRule",
12621
12465
  Param: {
12622
- AclTag: aclTag,
12466
+ CollectionName: resourceId,
12623
12467
  EnvId: envId,
12624
- ResourceType: "FUNCTION",
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 if (resourceType === "storage") {
12631
- if (aclTag === "CUSTOM") {
12632
- if (!rule)
12633
- throw new Error("存储自定义安全规则(CUSTOM)必须提供 rule 字段");
12634
- result = await cloudbase.commonService().call({
12635
- Action: "ModifyStorageSafeRule",
12636
- Param: {
12637
- Bucket: resourceId,
12638
- EnvId: envId,
12639
- AclTag: aclTag,
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
- else if (resourceType === "sqlDatabase") {
12658
- if (aclTag === "CUSTOM") {
12659
- throw new Error("SQL 数据库不支持自定义安全规则(CUSTOM");
12660
- }
12661
- const schema = envId;
12662
- const tableName = resourceId;
12663
- const instanceId = "default";
12664
- const resource = `${instanceId}#${schema}#${tableName}`;
12665
- const resourceType = "table";
12666
- const effect = "allow";
12667
- const policyList = [
12668
- "allUser",
12669
- "anonymousUser",
12670
- "externalUser",
12671
- "internalUser",
12672
- ].map((roleIdentity) => ({
12673
- RoleIdentity: roleIdentity,
12674
- ResourceType: resourceType,
12675
- ResourceId: resource,
12676
- RowPermission: [],
12677
- Effect: effect,
12678
- }));
12679
- policyList[0].RowPermission = getRowPermission(aclTag);
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
- PolicyList: policyList,
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
- throw new Error(`不支持的资源类型: ${resourceType}`);
12702
- }
12703
- return {
12704
- content: [
12705
- {
12706
- type: "text",
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
- catch (error) {
12718
- return {
12719
- content: [
12720
- {
12721
- type: "text",
12722
- text: JSON.stringify({
12723
- success: false,
12724
- error: error.message,
12725
- message: "安全规则写入失败",
12726
- }, null, 2),
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
- try {
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: error.message,
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
- try {
13686
- const cloudbase = await getManager();
13687
- const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
13688
- // TODO: 考虑是否有支持指定其他 instance、schema 的需求
13689
- const schemaId = envId;
13690
- const instanceId = "default";
13691
- const result = await cloudbase.commonService("tcb", "2018-06-08").call({
13692
- Action: "RunSql",
13693
- Param: {
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
- Sql: sql,
13696
- DbInstance: {
13697
- EnvId: envId,
13698
- InstanceId: instanceId,
13699
- Schema: schemaId,
13700
- },
13533
+ InstanceId: instanceId,
13534
+ Schema: schemaId,
13701
13535
  },
13702
- });
13703
- (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
13704
- return {
13705
- content: [
13706
- {
13707
- type: "text",
13708
- text: JSON.stringify({
13709
- success: true,
13710
- message: "SQL query executed successfully",
13711
- result,
13712
- }, null, 2),
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
- try {
13750
- const cloudbase = await getManager();
13751
- const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
13752
- // TODO: 考虑是否有支持指定其他 instance、schema 的需求
13753
- const schemaId = envId;
13754
- const instanceId = "default";
13755
- const result = await cloudbase.commonService("tcb", "2018-06-08").call({
13756
- Action: "RunSql",
13757
- Param: {
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
- Sql: sql,
13760
- DbInstance: {
13761
- EnvId: envId,
13762
- InstanceId: instanceId,
13763
- Schema: schemaId,
13764
- },
13580
+ InstanceId: instanceId,
13581
+ Schema: schemaId,
13765
13582
  },
13766
- });
13767
- (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
13768
- return {
13769
- content: [
13770
- {
13771
- type: "text",
13772
- text: JSON.stringify({
13773
- success: true,
13774
- 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.`,
13775
- result,
13776
- }, null, 2),
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