@cloudbase/cloudbase-mcp 2.8.0 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -0
- package/dist/cli.cjs +3 -3
- package/dist/index.cjs +1524 -1700
- package/dist/index.js +1533 -1710
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -142,7 +142,7 @@ function registerEnvTools(server) {
|
|
|
142
142
|
// Get CLAUDE.md prompt content (skip for CodeBuddy IDE)
|
|
143
143
|
let promptContent = "";
|
|
144
144
|
const currentIde = server.ide || process.env.INTEGRATION_IDE;
|
|
145
|
-
if (currentIde !== "CodeBuddy") {
|
|
145
|
+
if (currentIde !== "CodeBuddy" && process.env.CLOUDBASE_GUIDE_PROMPT !== "false") {
|
|
146
146
|
try {
|
|
147
147
|
promptContent = await (0, rag_js_1.getClaudePrompt)();
|
|
148
148
|
}
|
|
@@ -245,7 +245,7 @@ function registerEnvTools(server) {
|
|
|
245
245
|
});
|
|
246
246
|
// Use commonService to call DescribeEnvs with filter parameters
|
|
247
247
|
// Filter parameters match the reference conditions provided by user
|
|
248
|
-
result = await cloudbaseList.commonService("tcb").call({
|
|
248
|
+
result = await cloudbaseList.commonService("tcb", "2018-06-08").call({
|
|
249
249
|
Action: "DescribeEnvs",
|
|
250
250
|
Param: {
|
|
251
251
|
EnvTypes: ["weda", "baas"], // Include weda and baas (normal) environments
|
|
@@ -328,7 +328,7 @@ function registerEnvTools(server) {
|
|
|
328
328
|
let responseText = JSON.stringify(result, null, 2);
|
|
329
329
|
// For info action, append CLAUDE.md prompt content (skip for CodeBuddy IDE)
|
|
330
330
|
const currentIde = server.ide || process.env.INTEGRATION_IDE;
|
|
331
|
-
if (action === "info" && currentIde !== "CodeBuddy") {
|
|
331
|
+
if (action === "info" && currentIde !== "CodeBuddy" && process.env.CLOUDBASE_GUIDE_PROMPT !== "false") {
|
|
332
332
|
try {
|
|
333
333
|
const promptContent = await (0, rag_js_1.getClaudePrompt)();
|
|
334
334
|
if (promptContent) {
|
|
@@ -431,7 +431,6 @@ const cloudbase_manager_js_1 = __webpack_require__(3431);
|
|
|
431
431
|
const CATEGORY = "cloud-api";
|
|
432
432
|
const ALLOWED_SERVICES = [
|
|
433
433
|
"tcb",
|
|
434
|
-
"flexdb",
|
|
435
434
|
"scf",
|
|
436
435
|
"sts",
|
|
437
436
|
"cam",
|
|
@@ -454,7 +453,7 @@ function registerCapiTools(server) {
|
|
|
454
453
|
inputSchema: {
|
|
455
454
|
service: zod_1.z
|
|
456
455
|
.enum(ALLOWED_SERVICES)
|
|
457
|
-
.describe("选择要访问的服务,必须先查看规则/技能确认是否可用。可选:tcb、
|
|
456
|
+
.describe("选择要访问的服务,必须先查看规则/技能确认是否可用。可选:tcb、scf、sts、cam、lowcode、cdn、vpc。"),
|
|
458
457
|
action: zod_1.z
|
|
459
458
|
.string()
|
|
460
459
|
.min(1)
|
|
@@ -563,7 +562,7 @@ ${envIdSection}
|
|
|
563
562
|
## 环境信息
|
|
564
563
|
- 操作系统: ${os_1.default.type()} ${os_1.default.release()}
|
|
565
564
|
- Node.js版本: ${process.version}
|
|
566
|
-
- MCP 版本:${process.env.npm_package_version || "2.
|
|
565
|
+
- MCP 版本:${process.env.npm_package_version || "2.10.0" || 0}
|
|
567
566
|
- 系统架构: ${os_1.default.arch()}
|
|
568
567
|
- 时间: ${new Date().toISOString()}
|
|
569
568
|
- 请求ID: ${requestId}
|
|
@@ -773,6 +772,7 @@ const invite_code_js_1 = __webpack_require__(4760);
|
|
|
773
772
|
const security_rule_js_1 = __webpack_require__(7862);
|
|
774
773
|
const cloud_mode_js_1 = __webpack_require__(9684);
|
|
775
774
|
const logger_js_1 = __webpack_require__(3039);
|
|
775
|
+
const tencet_cloud_js_1 = __webpack_require__(5018);
|
|
776
776
|
const tool_wrapper_js_1 = __webpack_require__(1363);
|
|
777
777
|
// 默认插件列表
|
|
778
778
|
const DEFAULT_PLUGINS = [
|
|
@@ -792,7 +792,11 @@ const DEFAULT_PLUGINS = [
|
|
|
792
792
|
"capi",
|
|
793
793
|
];
|
|
794
794
|
function registerDatabase(server) {
|
|
795
|
-
|
|
795
|
+
// Skip NoSQL database tools for international region (Singapore) as it doesn't support NoSQL DB
|
|
796
|
+
const region = server.cloudBaseOptions?.region || process.env.TCB_REGION;
|
|
797
|
+
if (!(0, tencet_cloud_js_1.isInternationalRegion)(region)) {
|
|
798
|
+
(0, databaseNoSQL_js_1.registerDatabaseTools)(server);
|
|
799
|
+
}
|
|
796
800
|
(0, databaseSQL_js_1.registerSQLDatabaseTools)(server);
|
|
797
801
|
(0, dataModel_js_1.registerDataModelTools)(server);
|
|
798
802
|
}
|
|
@@ -1197,7 +1201,7 @@ class InteractiveServer {
|
|
|
1197
1201
|
IsVisible: false,
|
|
1198
1202
|
Channels: ["dcloud", "iotenable", "tem", "scene_module"],
|
|
1199
1203
|
};
|
|
1200
|
-
envResult = await sessionData.manager.commonService("tcb").call({
|
|
1204
|
+
envResult = await sessionData.manager.commonService("tcb", "2018-06-08").call({
|
|
1201
1205
|
Action: "DescribeEnvs",
|
|
1202
1206
|
Param: queryParams,
|
|
1203
1207
|
});
|
|
@@ -4227,7 +4231,10 @@ async function getCloudBaseManager(options = {}) {
|
|
|
4227
4231
|
return createCloudBaseManagerWithOptions(cloudBaseOptions);
|
|
4228
4232
|
}
|
|
4229
4233
|
try {
|
|
4230
|
-
|
|
4234
|
+
// Get region from environment variable for auth URL
|
|
4235
|
+
// Note: At this point, cloudBaseOptions is undefined (checked above), so only use env var
|
|
4236
|
+
const region = process.env.TCB_REGION;
|
|
4237
|
+
const loginState = await (0, auth_js_1.getLoginState)({ region });
|
|
4231
4238
|
const { envId: loginEnvId, secretId, secretKey, token } = loginState;
|
|
4232
4239
|
let finalEnvId;
|
|
4233
4240
|
if (requireEnvId) {
|
|
@@ -4252,12 +4259,17 @@ async function getCloudBaseManager(options = {}) {
|
|
|
4252
4259
|
}
|
|
4253
4260
|
// envId priority: envManager.cachedEnvId > envManager.getEnvId() > loginState.envId > undefined
|
|
4254
4261
|
// Note: envManager.cachedEnvId has highest priority as it reflects user's latest environment switch
|
|
4262
|
+
// Region priority: process.env.TCB_REGION > undefined (use SDK default)
|
|
4263
|
+
// At this point, cloudBaseOptions is undefined (checked above), so only use env var if present
|
|
4264
|
+
// Reuse region variable declared above (line 259) for CloudBase initialization
|
|
4255
4265
|
const manager = new manager_node_1.default({
|
|
4256
4266
|
secretId,
|
|
4257
4267
|
secretKey,
|
|
4258
4268
|
envId: finalEnvId || loginEnvId,
|
|
4259
4269
|
token,
|
|
4260
4270
|
proxy: process.env.http_proxy,
|
|
4271
|
+
region,
|
|
4272
|
+
// REGION 国际站需要指定 region
|
|
4261
4273
|
});
|
|
4262
4274
|
return manager;
|
|
4263
4275
|
}
|
|
@@ -4267,15 +4279,18 @@ async function getCloudBaseManager(options = {}) {
|
|
|
4267
4279
|
}
|
|
4268
4280
|
}
|
|
4269
4281
|
/**
|
|
4270
|
-
*
|
|
4271
|
-
* @param cloudBaseOptions
|
|
4272
|
-
* @returns CloudBase manager
|
|
4282
|
+
* Create a manager with the provided CloudBase options, without using cache
|
|
4283
|
+
* @param cloudBaseOptions Provided CloudBase options
|
|
4284
|
+
* @returns CloudBase manager instance
|
|
4273
4285
|
*/
|
|
4274
4286
|
function createCloudBaseManagerWithOptions(cloudBaseOptions) {
|
|
4275
|
-
(0, logger_js_1.debug)('
|
|
4287
|
+
(0, logger_js_1.debug)('Create manager with provided CloudBase options:', cloudBaseOptions);
|
|
4288
|
+
// Region priority: cloudBaseOptions.region > process.env.TCB_REGION > undefined (use SDK default)
|
|
4289
|
+
const region = cloudBaseOptions.region ?? process.env.TCB_REGION ?? undefined;
|
|
4276
4290
|
const manager = new manager_node_1.default({
|
|
4277
4291
|
...cloudBaseOptions,
|
|
4278
4292
|
proxy: cloudBaseOptions.proxy || process.env.http_proxy,
|
|
4293
|
+
region
|
|
4279
4294
|
});
|
|
4280
4295
|
return manager;
|
|
4281
4296
|
}
|
|
@@ -4484,9 +4499,14 @@ async function _promptAndSetEnvironmentId(autoSelectSingle, options) {
|
|
|
4484
4499
|
}
|
|
4485
4500
|
// 1. 确保用户已登录
|
|
4486
4501
|
(0, logger_js_1.debug)("[interactive] Step 1: Checking login state...");
|
|
4502
|
+
// Get region from server options or environment variable for auth URL
|
|
4503
|
+
// Note: serverCloudBaseOptions will be declared later (line 282), so we get it here first
|
|
4504
|
+
const serverCloudBaseOptionsForAuth = server?.cloudBaseOptions;
|
|
4505
|
+
const region = serverCloudBaseOptionsForAuth?.region || process.env.TCB_REGION;
|
|
4487
4506
|
const loginState = await (0, auth_js_1.getLoginState)({
|
|
4488
4507
|
fromCloudBaseLoginPage: options?.loginFromCloudBaseLoginPage,
|
|
4489
4508
|
ignoreEnvVars: options?.ignoreEnvVars,
|
|
4509
|
+
region,
|
|
4490
4510
|
});
|
|
4491
4511
|
(0, logger_js_1.debug)("[interactive] Login state:", {
|
|
4492
4512
|
hasLoginState: !!loginState,
|
|
@@ -4518,6 +4538,14 @@ async function _promptAndSetEnvironmentId(autoSelectSingle, options) {
|
|
|
4518
4538
|
cloudBaseOptions: serverCloudBaseOptions,
|
|
4519
4539
|
});
|
|
4520
4540
|
(0, logger_js_1.debug)("[interactive] CloudBase manager obtained");
|
|
4541
|
+
// If envId is already set, return directly
|
|
4542
|
+
const envId = serverCloudBaseOptions?.envId || process.env.CLOUDBASE_ENV_ID;
|
|
4543
|
+
if (envId) {
|
|
4544
|
+
return {
|
|
4545
|
+
selectedEnvId: envId,
|
|
4546
|
+
cancelled: false,
|
|
4547
|
+
};
|
|
4548
|
+
}
|
|
4521
4549
|
// Step 2.1: Check and initialize TCB service if needed
|
|
4522
4550
|
// Check if retry is requested (from interactive server session data)
|
|
4523
4551
|
// Ensure server is resolved if it's a Promise (CLI mode)
|
|
@@ -4591,7 +4619,7 @@ async function _promptAndSetEnvironmentId(autoSelectSingle, options) {
|
|
|
4591
4619
|
let queryEnvSuccess = false;
|
|
4592
4620
|
let queryEnvError;
|
|
4593
4621
|
try {
|
|
4594
|
-
// Use
|
|
4622
|
+
// Use Service to call DescribeEnvs with filter parameters
|
|
4595
4623
|
// Filter parameters match the reference conditions provided by user
|
|
4596
4624
|
const queryParams = {
|
|
4597
4625
|
EnvTypes: ["weda", "baas"], // Include weda and baas (normal) environments
|
|
@@ -4599,7 +4627,7 @@ async function _promptAndSetEnvironmentId(autoSelectSingle, options) {
|
|
|
4599
4627
|
Channels: ["dcloud", "iotenable", "tem", "scene_module"], // Filter special channels
|
|
4600
4628
|
};
|
|
4601
4629
|
(0, logger_js_1.debug)("[interactive] DescribeEnvs params:", queryParams);
|
|
4602
|
-
envResult = await cloudbase.commonService("tcb").call({
|
|
4630
|
+
envResult = await cloudbase.commonService("tcb", "2018-06-08").call({
|
|
4603
4631
|
Action: "DescribeEnvs",
|
|
4604
4632
|
Param: queryParams,
|
|
4605
4633
|
});
|
|
@@ -4727,7 +4755,7 @@ async function _promptAndSetEnvironmentId(autoSelectSingle, options) {
|
|
|
4727
4755
|
// Sometimes creation is async and env might not be immediately available
|
|
4728
4756
|
(0, logger_js_1.debug)("[interactive] Verifying created environment exists in list...");
|
|
4729
4757
|
try {
|
|
4730
|
-
const verifyResult = await cloudbase.commonService("tcb").call({
|
|
4758
|
+
const verifyResult = await cloudbase.commonService("tcb", "2018-06-08").call({
|
|
4731
4759
|
Action: "DescribeEnvs",
|
|
4732
4760
|
Param: {
|
|
4733
4761
|
EnvTypes: ["weda", "baas"],
|
|
@@ -4912,6 +4940,15 @@ async function _promptAndSetEnvironmentId(autoSelectSingle, options) {
|
|
|
4912
4940
|
accountInfo.uin = String(loginState.uin);
|
|
4913
4941
|
(0, logger_js_1.debug)("[interactive] Using UIN from loginState:", { uin: accountInfo.uin });
|
|
4914
4942
|
}
|
|
4943
|
+
// Attach region from server options or environment variable fallback
|
|
4944
|
+
// Reuse serverCloudBaseOptions declared earlier (line 278)
|
|
4945
|
+
const currentServerCloudBaseOptions = server?.cloudBaseOptions;
|
|
4946
|
+
if (currentServerCloudBaseOptions?.region) {
|
|
4947
|
+
accountInfo.region = currentServerCloudBaseOptions.region;
|
|
4948
|
+
}
|
|
4949
|
+
else if (process.env.TCB_REGION) {
|
|
4950
|
+
accountInfo.region = process.env.TCB_REGION;
|
|
4951
|
+
}
|
|
4915
4952
|
// Report display_env_selection event
|
|
4916
4953
|
await telemetry_js_1.telemetryReporter.report('toolkit_env_setup', {
|
|
4917
4954
|
step: 'display_env_selection',
|
|
@@ -5230,9 +5267,10 @@ checkIndex: 检查索引是否存在`),
|
|
|
5230
5267
|
title: "修改 NoSQL 数据库结构",
|
|
5231
5268
|
description: "修改 NoSQL 数据库结构",
|
|
5232
5269
|
inputSchema: {
|
|
5233
|
-
action: zod_1.z.enum(["createCollection", "updateCollection"])
|
|
5270
|
+
action: zod_1.z.enum(["createCollection", "updateCollection", "deleteCollection"])
|
|
5234
5271
|
.describe(`createCollection: 创建集合
|
|
5235
|
-
updateCollection:
|
|
5272
|
+
updateCollection: 更新集合
|
|
5273
|
+
deleteCollection: 删除集合`),
|
|
5236
5274
|
collectionName: zod_1.z.string().describe("集合名称"),
|
|
5237
5275
|
updateOptions: zod_1.z
|
|
5238
5276
|
.object({
|
|
@@ -5259,68 +5297,74 @@ updateCollection: 更新集合`),
|
|
|
5259
5297
|
},
|
|
5260
5298
|
annotations: {
|
|
5261
5299
|
readOnlyHint: false,
|
|
5262
|
-
destructiveHint:
|
|
5300
|
+
destructiveHint: true,
|
|
5263
5301
|
idempotentHint: false,
|
|
5264
5302
|
openWorldHint: true,
|
|
5265
5303
|
category: CATEGORY,
|
|
5266
5304
|
},
|
|
5267
5305
|
}, async ({ action, collectionName, updateOptions }) => {
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
};
|
|
5286
|
-
}
|
|
5287
|
-
if (action === "updateCollection") {
|
|
5288
|
-
if (!updateOptions) {
|
|
5289
|
-
throw new Error("更新集合时必须提供 options");
|
|
5290
|
-
}
|
|
5291
|
-
const result = await cloudbase.database.updateCollection(collectionName, updateOptions);
|
|
5292
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
5293
|
-
return {
|
|
5294
|
-
content: [
|
|
5295
|
-
{
|
|
5296
|
-
type: "text",
|
|
5297
|
-
text: JSON.stringify({
|
|
5298
|
-
success: true,
|
|
5299
|
-
requestId: result.RequestId,
|
|
5300
|
-
action,
|
|
5301
|
-
message: "云开发数据库集合更新成功",
|
|
5302
|
-
}, null, 2),
|
|
5303
|
-
},
|
|
5304
|
-
],
|
|
5305
|
-
};
|
|
5306
|
-
}
|
|
5307
|
-
throw new Error(`不支持的操作类型: ${action}`);
|
|
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
|
+
};
|
|
5308
5323
|
}
|
|
5309
|
-
|
|
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);
|
|
5310
5330
|
return {
|
|
5311
5331
|
content: [
|
|
5312
5332
|
{
|
|
5313
5333
|
type: "text",
|
|
5314
5334
|
text: JSON.stringify({
|
|
5315
|
-
success:
|
|
5335
|
+
success: true,
|
|
5336
|
+
requestId: result.RequestId,
|
|
5316
5337
|
action,
|
|
5317
|
-
|
|
5318
|
-
message: "集合创建/更新操作失败",
|
|
5338
|
+
message: "云开发数据库集合更新成功",
|
|
5319
5339
|
}, null, 2),
|
|
5320
5340
|
},
|
|
5321
5341
|
],
|
|
5322
5342
|
};
|
|
5323
5343
|
}
|
|
5344
|
+
if (action === "deleteCollection") {
|
|
5345
|
+
const result = await cloudbase.database.deleteCollection(collectionName);
|
|
5346
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
5347
|
+
const body = {
|
|
5348
|
+
success: true,
|
|
5349
|
+
requestId: result.RequestId,
|
|
5350
|
+
action,
|
|
5351
|
+
message: result.Exists === false
|
|
5352
|
+
? "集合不存在"
|
|
5353
|
+
: "云开发数据库集合删除成功",
|
|
5354
|
+
};
|
|
5355
|
+
if (result.Exists === false) {
|
|
5356
|
+
body.exists = false;
|
|
5357
|
+
}
|
|
5358
|
+
return {
|
|
5359
|
+
content: [
|
|
5360
|
+
{
|
|
5361
|
+
type: "text",
|
|
5362
|
+
text: JSON.stringify(body, null, 2),
|
|
5363
|
+
},
|
|
5364
|
+
],
|
|
5365
|
+
};
|
|
5366
|
+
}
|
|
5367
|
+
throw new Error(`不支持的操作类型: ${action}`);
|
|
5324
5368
|
});
|
|
5325
5369
|
// readNoSqlDatabaseContent
|
|
5326
5370
|
server.registerTool?.("readNoSqlDatabaseContent", {
|
|
@@ -5349,53 +5393,36 @@ updateCollection: 更新集合`),
|
|
|
5349
5393
|
category: CATEGORY,
|
|
5350
5394
|
},
|
|
5351
5395
|
}, async ({ collectionName, query, projection, sort, limit, offset }) => {
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5396
|
+
const cloudbase = await getManager();
|
|
5397
|
+
const instanceId = await getDatabaseInstanceId(getManager);
|
|
5398
|
+
const toJSONString = (v) => typeof v === "object" && v !== null ? JSON.stringify(v) : v;
|
|
5399
|
+
const result = await cloudbase.commonService("tcb", "2018-06-08").call({
|
|
5400
|
+
Action: "QueryRecords",
|
|
5401
|
+
Param: {
|
|
5402
|
+
TableName: collectionName,
|
|
5403
|
+
MgoQuery: toJSONString(query),
|
|
5404
|
+
MgoProjection: toJSONString(projection),
|
|
5405
|
+
MgoSort: toJSONString(sort),
|
|
5406
|
+
MgoLimit: limit ?? 100,
|
|
5407
|
+
MgoOffset: offset,
|
|
5408
|
+
Tag: instanceId,
|
|
5409
|
+
},
|
|
5410
|
+
});
|
|
5411
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
5412
|
+
return {
|
|
5413
|
+
content: [
|
|
5414
|
+
{
|
|
5415
|
+
type: "text",
|
|
5416
|
+
text: JSON.stringify({
|
|
5417
|
+
success: true,
|
|
5418
|
+
requestId: result.RequestId,
|
|
5419
|
+
data: result.Data,
|
|
5420
|
+
pager: result.Pager,
|
|
5421
|
+
message: "文档查询成功",
|
|
5422
|
+
}, null, 2),
|
|
5367
5423
|
},
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
return {
|
|
5371
|
-
content: [
|
|
5372
|
-
{
|
|
5373
|
-
type: "text",
|
|
5374
|
-
text: JSON.stringify({
|
|
5375
|
-
success: true,
|
|
5376
|
-
requestId: result.RequestId,
|
|
5377
|
-
data: result.Data,
|
|
5378
|
-
pager: result.Pager,
|
|
5379
|
-
message: "文档查询成功",
|
|
5380
|
-
}, null, 2),
|
|
5381
|
-
},
|
|
5382
|
-
],
|
|
5383
|
-
};
|
|
5384
|
-
}
|
|
5385
|
-
catch (error) {
|
|
5386
|
-
return {
|
|
5387
|
-
content: [
|
|
5388
|
-
{
|
|
5389
|
-
type: "text",
|
|
5390
|
-
text: JSON.stringify({
|
|
5391
|
-
success: false,
|
|
5392
|
-
error: error.message,
|
|
5393
|
-
message: "文档查询失败",
|
|
5394
|
-
}, null, 2),
|
|
5395
|
-
},
|
|
5396
|
-
],
|
|
5397
|
-
};
|
|
5398
|
-
}
|
|
5424
|
+
],
|
|
5425
|
+
};
|
|
5399
5426
|
});
|
|
5400
5427
|
// writeNoSqlDatabaseContent
|
|
5401
5428
|
server.registerTool?.("writeNoSqlDatabaseContent", {
|
|
@@ -5403,9 +5430,7 @@ updateCollection: 更新集合`),
|
|
|
5403
5430
|
description: "修改 NoSQL 数据库数据记录",
|
|
5404
5431
|
inputSchema: {
|
|
5405
5432
|
action: zod_1.z.enum(["insert", "update", "delete"])
|
|
5406
|
-
.describe(`
|
|
5407
|
-
updateCollection: 更新数据
|
|
5408
|
-
deleteCollection: 删除数据`),
|
|
5433
|
+
.describe(`insert: 插入数据(新增文档)\nupdate: 更新数据\ndelete: 删除数据`),
|
|
5409
5434
|
collectionName: zod_1.z.string().describe("集合名称"),
|
|
5410
5435
|
documents: zod_1.z
|
|
5411
5436
|
.array(zod_1.z.object({}).passthrough())
|
|
@@ -5504,98 +5529,70 @@ deleteCollection: 删除数据`),
|
|
|
5504
5529
|
});
|
|
5505
5530
|
}
|
|
5506
5531
|
async function insertDocuments({ collectionName, documents, getManager, logger, }) {
|
|
5507
|
-
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
|
|
5521
|
-
|
|
5522
|
-
|
|
5523
|
-
|
|
5524
|
-
|
|
5525
|
-
message: "文档插入成功",
|
|
5526
|
-
}, null, 2);
|
|
5527
|
-
}
|
|
5528
|
-
catch (error) {
|
|
5529
|
-
return JSON.stringify({
|
|
5530
|
-
success: false,
|
|
5531
|
-
error: error.message,
|
|
5532
|
-
message: "文档插入失败",
|
|
5533
|
-
}, null, 2);
|
|
5534
|
-
}
|
|
5532
|
+
const cloudbase = await getManager();
|
|
5533
|
+
const instanceId = await getDatabaseInstanceId(getManager);
|
|
5534
|
+
const docsAsStrings = documents.map((doc) => JSON.stringify(doc));
|
|
5535
|
+
const result = await cloudbase.commonService("tcb", "2018-06-08").call({
|
|
5536
|
+
Action: "PutItem",
|
|
5537
|
+
Param: {
|
|
5538
|
+
TableName: collectionName,
|
|
5539
|
+
MgoDocs: docsAsStrings,
|
|
5540
|
+
Tag: instanceId,
|
|
5541
|
+
},
|
|
5542
|
+
});
|
|
5543
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(logger, result);
|
|
5544
|
+
return JSON.stringify({
|
|
5545
|
+
success: true,
|
|
5546
|
+
requestId: result.RequestId,
|
|
5547
|
+
insertedIds: result.InsertedIds,
|
|
5548
|
+
message: "文档插入成功",
|
|
5549
|
+
}, null, 2);
|
|
5535
5550
|
}
|
|
5536
5551
|
async function updateDocuments({ collectionName, query, update, isMulti, upsert, getManager, logger, }) {
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
|
|
5542
|
-
|
|
5543
|
-
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
|
|
5553
|
-
|
|
5554
|
-
|
|
5555
|
-
|
|
5556
|
-
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
|
|
5560
|
-
}, null, 2);
|
|
5561
|
-
}
|
|
5562
|
-
catch (error) {
|
|
5563
|
-
return JSON.stringify({
|
|
5564
|
-
success: false,
|
|
5565
|
-
error: error.message,
|
|
5566
|
-
message: "文档更新失败",
|
|
5567
|
-
}, null, 2);
|
|
5568
|
-
}
|
|
5552
|
+
const cloudbase = await getManager();
|
|
5553
|
+
const instanceId = await getDatabaseInstanceId(getManager);
|
|
5554
|
+
const toJSONString = (v) => typeof v === "object" && v !== null ? JSON.stringify(v) : v;
|
|
5555
|
+
const result = await cloudbase.commonService("tcb", "2018-06-08").call({
|
|
5556
|
+
Action: "UpdateItem",
|
|
5557
|
+
Param: {
|
|
5558
|
+
TableName: collectionName,
|
|
5559
|
+
MgoQuery: toJSONString(query),
|
|
5560
|
+
MgoUpdate: toJSONString(update),
|
|
5561
|
+
MgoIsMulti: isMulti,
|
|
5562
|
+
MgoUpsert: upsert,
|
|
5563
|
+
Tag: instanceId,
|
|
5564
|
+
},
|
|
5565
|
+
});
|
|
5566
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(logger, result);
|
|
5567
|
+
return JSON.stringify({
|
|
5568
|
+
success: true,
|
|
5569
|
+
requestId: result.RequestId,
|
|
5570
|
+
modifiedCount: result.ModifiedNum,
|
|
5571
|
+
matchedCount: result.MatchedNum,
|
|
5572
|
+
upsertedId: result.UpsertedId,
|
|
5573
|
+
message: "文档更新成功",
|
|
5574
|
+
}, null, 2);
|
|
5569
5575
|
}
|
|
5570
5576
|
async function deleteDocuments({ collectionName, query, isMulti, getManager, logger, }) {
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
|
|
5577
|
-
|
|
5578
|
-
|
|
5579
|
-
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
}, null, 2);
|
|
5591
|
-
}
|
|
5592
|
-
catch (error) {
|
|
5593
|
-
return JSON.stringify({
|
|
5594
|
-
success: false,
|
|
5595
|
-
error: error.message,
|
|
5596
|
-
message: "文档删除失败",
|
|
5597
|
-
}, null, 2);
|
|
5598
|
-
}
|
|
5577
|
+
const cloudbase = await getManager();
|
|
5578
|
+
const instanceId = await getDatabaseInstanceId(getManager);
|
|
5579
|
+
const toJSONString = (v) => typeof v === "object" && v !== null ? JSON.stringify(v) : v;
|
|
5580
|
+
const result = await cloudbase.commonService("tcb", "2018-06-08").call({
|
|
5581
|
+
Action: "DeleteItem",
|
|
5582
|
+
Param: {
|
|
5583
|
+
TableName: collectionName,
|
|
5584
|
+
MgoQuery: toJSONString(query),
|
|
5585
|
+
MgoIsMulti: isMulti,
|
|
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
|
+
deleted: result.Deleted,
|
|
5594
|
+
message: "文档删除成功",
|
|
5595
|
+
}, null, 2);
|
|
5599
5596
|
}
|
|
5600
5597
|
|
|
5601
5598
|
|
|
@@ -6148,12 +6145,12 @@ function registerDataModelTools(server) {
|
|
|
6148
6145
|
// 数据模型查询工具
|
|
6149
6146
|
server.registerTool?.("manageDataModel", {
|
|
6150
6147
|
title: "数据模型管理",
|
|
6151
|
-
description: "
|
|
6148
|
+
description: "数据模型查询工具,支持查询和列表数据模型(只读操作)。通过 action 参数区分操作类型:list=获取模型列表(不含Schema,可选 names 参数过滤),get=查询单个模型详情(含Schema字段列表、格式、关联关系等,需要提供 name 参数),docs=生成SDK使用文档(需要提供 name 参数)",
|
|
6152
6149
|
inputSchema: {
|
|
6153
6150
|
action: zod_1.z
|
|
6154
6151
|
.enum(["get", "list", "docs"])
|
|
6155
|
-
.describe("操作类型:get=查询单个模型(含Schema
|
|
6156
|
-
name: zod_1.z.string().optional().describe("
|
|
6152
|
+
.describe("操作类型:get=查询单个模型(含Schema字段列表、格式、关联关系,需要提供 name 参数),list=获取模型列表(不含Schema,可选 names 参数过滤),docs=生成SDK使用文档(需要提供 name 参数)"),
|
|
6153
|
+
name: zod_1.z.string().optional().describe("要查询的数据模型名称。当 action='get' 或 action='docs' 时,此参数为必填项,必须提供已存在的数据模型名称。可通过 action='list' 操作获取可用的模型名称列表"),
|
|
6157
6154
|
names: zod_1.z
|
|
6158
6155
|
.array(zod_1.z.string())
|
|
6159
6156
|
.optional()
|
|
@@ -6165,289 +6162,271 @@ function registerDataModelTools(server) {
|
|
|
6165
6162
|
category: "database",
|
|
6166
6163
|
},
|
|
6167
6164
|
}, async ({ action, name, names, }) => {
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
|
|
6187
|
-
|
|
6188
|
-
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
|
|
6192
|
-
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
6199
|
-
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
};
|
|
6217
|
-
}
|
|
6218
|
-
catch (e) {
|
|
6219
|
-
simplifiedSchema = { error: "Schema解析失败" };
|
|
6220
|
-
}
|
|
6165
|
+
const cloudbase = await getManager();
|
|
6166
|
+
let currentEnvId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
6167
|
+
let result;
|
|
6168
|
+
switch (action) {
|
|
6169
|
+
case "get":
|
|
6170
|
+
if (!name) {
|
|
6171
|
+
throw new Error("获取数据模型需要提供模型名称");
|
|
6172
|
+
}
|
|
6173
|
+
try {
|
|
6174
|
+
result = await cloudbase.commonService("lowcode").call({
|
|
6175
|
+
Action: "DescribeBasicDataSource",
|
|
6176
|
+
Param: {
|
|
6177
|
+
EnvId: currentEnvId,
|
|
6178
|
+
Name: name,
|
|
6179
|
+
},
|
|
6180
|
+
});
|
|
6181
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
6182
|
+
// 只保留基础字段,过滤掉冗余信息,并简化Schema
|
|
6183
|
+
let simplifiedSchema = null;
|
|
6184
|
+
// 解析并简化Schema
|
|
6185
|
+
if (result.Data.Schema) {
|
|
6186
|
+
try {
|
|
6187
|
+
const schema = JSON.parse(result.Data.Schema);
|
|
6188
|
+
const properties = schema.properties || {};
|
|
6189
|
+
// 提取用户定义的字段(排除系统字段)
|
|
6190
|
+
const userFields = Object.keys(properties)
|
|
6191
|
+
.filter((key) => !properties[key]["x-system"]) // 排除系统字段
|
|
6192
|
+
.map((key) => {
|
|
6193
|
+
const field = properties[key];
|
|
6194
|
+
return parseFieldStructure(field, key, schema);
|
|
6195
|
+
});
|
|
6196
|
+
// 提取关联关系
|
|
6197
|
+
const relations = userFields
|
|
6198
|
+
.filter((field) => field.linkage)
|
|
6199
|
+
.map((field) => ({
|
|
6200
|
+
field: field.name,
|
|
6201
|
+
type: field.format,
|
|
6202
|
+
title: field.title,
|
|
6203
|
+
targetModel: field.linkage.parentDataSourceName,
|
|
6204
|
+
foreignKey: field.linkage.parentFieldKey,
|
|
6205
|
+
displayField: field.linkage.parentFieldTitle,
|
|
6206
|
+
}));
|
|
6207
|
+
simplifiedSchema = {
|
|
6208
|
+
userFields,
|
|
6209
|
+
relations,
|
|
6210
|
+
totalFields: Object.keys(properties).length,
|
|
6211
|
+
userFieldsCount: userFields.length,
|
|
6212
|
+
};
|
|
6221
6213
|
}
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
|
|
6241
|
-
|
|
6242
|
-
|
|
6243
|
-
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
|
|
6252
|
-
}
|
|
6253
|
-
}
|
|
6254
|
-
|
|
6255
|
-
|
|
6214
|
+
catch (e) {
|
|
6215
|
+
simplifiedSchema = { error: "Schema解析失败" };
|
|
6216
|
+
}
|
|
6217
|
+
}
|
|
6218
|
+
// 尝试生成Mermaid图表
|
|
6219
|
+
let mermaidDiagram = null;
|
|
6220
|
+
if (result.Data.Schema &&
|
|
6221
|
+
jsonSchemaToMermaid &&
|
|
6222
|
+
simplifiedSchema &&
|
|
6223
|
+
!simplifiedSchema.error) {
|
|
6224
|
+
try {
|
|
6225
|
+
const mainSchema = JSON.parse(result.Data.Schema);
|
|
6226
|
+
const schemasMap = {
|
|
6227
|
+
[name]: mainSchema,
|
|
6228
|
+
};
|
|
6229
|
+
// 获取关联模型的 schema
|
|
6230
|
+
if (simplifiedSchema.relations &&
|
|
6231
|
+
simplifiedSchema.relations.length > 0) {
|
|
6232
|
+
const relatedModelNames = [
|
|
6233
|
+
...new Set(simplifiedSchema.relations.map((rel) => rel.targetModel)),
|
|
6234
|
+
];
|
|
6235
|
+
for (const relatedModelName of relatedModelNames) {
|
|
6236
|
+
try {
|
|
6237
|
+
const relatedResult = await cloudbase
|
|
6238
|
+
.commonService("lowcode")
|
|
6239
|
+
.call({
|
|
6240
|
+
Action: "DescribeBasicDataSource",
|
|
6241
|
+
Param: {
|
|
6242
|
+
EnvId: currentEnvId,
|
|
6243
|
+
Name: relatedModelName,
|
|
6244
|
+
},
|
|
6245
|
+
});
|
|
6246
|
+
if (relatedResult.Data && relatedResult.Data.Schema) {
|
|
6247
|
+
schemasMap[relatedModelName] = JSON.parse(relatedResult.Data.Schema);
|
|
6256
6248
|
}
|
|
6257
6249
|
}
|
|
6250
|
+
catch (e) {
|
|
6251
|
+
console.warn(`获取关联模型 ${relatedModelName} 的 schema 失败:`, e);
|
|
6252
|
+
}
|
|
6258
6253
|
}
|
|
6259
|
-
// 调用 jsonSchemaToMermaid,传入正确的参数格式
|
|
6260
|
-
mermaidDiagram = jsonSchemaToMermaid(schemasMap);
|
|
6261
|
-
}
|
|
6262
|
-
catch (e) {
|
|
6263
|
-
console.warn("生成Mermaid图表失败:", e);
|
|
6264
6254
|
}
|
|
6255
|
+
// 调用 jsonSchemaToMermaid,传入正确的参数格式
|
|
6256
|
+
mermaidDiagram = jsonSchemaToMermaid(schemasMap);
|
|
6265
6257
|
}
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
Title: result.Data.Title,
|
|
6269
|
-
Description: result.Data.Description,
|
|
6270
|
-
Name: result.Data.Name,
|
|
6271
|
-
UpdatedAt: result.Data.UpdatedAt,
|
|
6272
|
-
Schema: simplifiedSchema,
|
|
6273
|
-
mermaid: mermaidDiagram,
|
|
6274
|
-
};
|
|
6275
|
-
return {
|
|
6276
|
-
content: [
|
|
6277
|
-
{
|
|
6278
|
-
type: "text",
|
|
6279
|
-
text: JSON.stringify({
|
|
6280
|
-
success: true,
|
|
6281
|
-
action: "get",
|
|
6282
|
-
data: simplifiedModel,
|
|
6283
|
-
message: "获取数据模型成功",
|
|
6284
|
-
}, null, 2),
|
|
6285
|
-
},
|
|
6286
|
-
],
|
|
6287
|
-
};
|
|
6288
|
-
}
|
|
6289
|
-
catch (error) {
|
|
6290
|
-
if (error.original?.Code === "ResourceNotFound") {
|
|
6291
|
-
return {
|
|
6292
|
-
content: [
|
|
6293
|
-
{
|
|
6294
|
-
type: "text",
|
|
6295
|
-
text: JSON.stringify({
|
|
6296
|
-
success: false,
|
|
6297
|
-
action: "get",
|
|
6298
|
-
error: "ResourceNotFound",
|
|
6299
|
-
message: `数据模型 ${name} 不存在`,
|
|
6300
|
-
}, null, 2),
|
|
6301
|
-
},
|
|
6302
|
-
],
|
|
6303
|
-
};
|
|
6258
|
+
catch (e) {
|
|
6259
|
+
console.warn("生成Mermaid图表失败:", e);
|
|
6304
6260
|
}
|
|
6305
|
-
throw error;
|
|
6306
6261
|
}
|
|
6307
|
-
|
|
6308
|
-
|
|
6309
|
-
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
|
|
6262
|
+
const simplifiedModel = {
|
|
6263
|
+
DbInstanceType: result.Data.DbInstanceType,
|
|
6264
|
+
Title: result.Data.Title,
|
|
6265
|
+
Description: result.Data.Description,
|
|
6266
|
+
Name: result.Data.Name,
|
|
6267
|
+
UpdatedAt: result.Data.UpdatedAt,
|
|
6268
|
+
Schema: simplifiedSchema,
|
|
6269
|
+
mermaid: mermaidDiagram,
|
|
6315
6270
|
};
|
|
6316
|
-
// 只有当 names 参数存在且不为空时才添加过滤条件
|
|
6317
|
-
if (names && names.length > 0) {
|
|
6318
|
-
listParams.DataSourceNames = names;
|
|
6319
|
-
}
|
|
6320
|
-
result = await cloudbase.commonService("lowcode").call({
|
|
6321
|
-
Action: "DescribeDataSourceList",
|
|
6322
|
-
Param: listParams,
|
|
6323
|
-
});
|
|
6324
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
6325
|
-
const models = result.Data?.Rows || [];
|
|
6326
|
-
// 只保留基础字段,list操作不返回Schema
|
|
6327
|
-
const simplifiedModels = models.map((model) => ({
|
|
6328
|
-
DbInstanceType: model.DbInstanceType,
|
|
6329
|
-
Title: model.Title,
|
|
6330
|
-
Description: model.Description,
|
|
6331
|
-
Name: model.Name,
|
|
6332
|
-
UpdatedAt: model.UpdatedAt,
|
|
6333
|
-
}));
|
|
6334
6271
|
return {
|
|
6335
6272
|
content: [
|
|
6336
6273
|
{
|
|
6337
6274
|
type: "text",
|
|
6338
6275
|
text: JSON.stringify({
|
|
6339
6276
|
success: true,
|
|
6340
|
-
action: "
|
|
6341
|
-
data:
|
|
6342
|
-
|
|
6343
|
-
message: "获取数据模型列表成功",
|
|
6277
|
+
action: "get",
|
|
6278
|
+
data: simplifiedModel,
|
|
6279
|
+
message: "获取数据模型成功",
|
|
6344
6280
|
}, null, 2),
|
|
6345
6281
|
},
|
|
6346
6282
|
],
|
|
6347
6283
|
};
|
|
6348
|
-
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
}
|
|
6352
|
-
try {
|
|
6353
|
-
// 先获取模型信息
|
|
6354
|
-
result = await cloudbase.commonService("lowcode").call({
|
|
6355
|
-
Action: "DescribeBasicDataSource",
|
|
6356
|
-
Param: {
|
|
6357
|
-
EnvId: currentEnvId,
|
|
6358
|
-
Name: name,
|
|
6359
|
-
},
|
|
6360
|
-
});
|
|
6361
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
6362
|
-
if (!result.Data) {
|
|
6363
|
-
throw new Error(`数据模型 ${name} 不存在`);
|
|
6364
|
-
}
|
|
6365
|
-
// 解析Schema获取字段信息
|
|
6366
|
-
let userFields = [];
|
|
6367
|
-
let relations = [];
|
|
6368
|
-
if (result.Data.Schema) {
|
|
6369
|
-
try {
|
|
6370
|
-
const schema = JSON.parse(result.Data.Schema);
|
|
6371
|
-
const properties = schema.properties || {};
|
|
6372
|
-
// 提取用户定义的字段
|
|
6373
|
-
userFields = Object.keys(properties)
|
|
6374
|
-
.filter((key) => !properties[key]["x-system"])
|
|
6375
|
-
.map((key) => {
|
|
6376
|
-
const field = properties[key];
|
|
6377
|
-
return parseFieldStructure(field, key, schema);
|
|
6378
|
-
});
|
|
6379
|
-
// 提取关联关系
|
|
6380
|
-
relations = userFields
|
|
6381
|
-
.filter((field) => field.linkage)
|
|
6382
|
-
.map((field) => ({
|
|
6383
|
-
field: field.name,
|
|
6384
|
-
type: field.format,
|
|
6385
|
-
title: field.title,
|
|
6386
|
-
targetModel: field.linkage.parentDataSourceName,
|
|
6387
|
-
foreignKey: field.linkage.parentFieldKey,
|
|
6388
|
-
displayField: field.linkage.parentFieldTitle,
|
|
6389
|
-
}));
|
|
6390
|
-
}
|
|
6391
|
-
catch (e) {
|
|
6392
|
-
// Schema解析失败,使用空数组
|
|
6393
|
-
console.error("Schema解析失败", e);
|
|
6394
|
-
}
|
|
6395
|
-
}
|
|
6396
|
-
// 生成SDK使用文档
|
|
6397
|
-
const docs = generateSDKDocs(result.Data.Name, result.Data.Title, userFields, relations);
|
|
6284
|
+
}
|
|
6285
|
+
catch (error) {
|
|
6286
|
+
if (error.original?.Code === "ResourceNotFound") {
|
|
6398
6287
|
return {
|
|
6399
6288
|
content: [
|
|
6400
6289
|
{
|
|
6401
6290
|
type: "text",
|
|
6402
6291
|
text: JSON.stringify({
|
|
6403
|
-
success:
|
|
6404
|
-
action: "
|
|
6405
|
-
|
|
6406
|
-
|
|
6407
|
-
docs,
|
|
6408
|
-
message: "SDK使用文档生成成功",
|
|
6292
|
+
success: false,
|
|
6293
|
+
action: "get",
|
|
6294
|
+
error: "ResourceNotFound",
|
|
6295
|
+
message: `数据模型 ${name} 不存在`,
|
|
6409
6296
|
}, null, 2),
|
|
6410
6297
|
},
|
|
6411
6298
|
],
|
|
6412
6299
|
};
|
|
6413
6300
|
}
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
|
|
6301
|
+
throw error;
|
|
6302
|
+
}
|
|
6303
|
+
case "list":
|
|
6304
|
+
// 构建请求参数
|
|
6305
|
+
const listParams = {
|
|
6306
|
+
EnvId: currentEnvId,
|
|
6307
|
+
PageIndex: 1,
|
|
6308
|
+
PageSize: 1000,
|
|
6309
|
+
QuerySystemModel: true, // 查询系统模型
|
|
6310
|
+
QueryConnector: 0, // 0 表示数据模型
|
|
6311
|
+
};
|
|
6312
|
+
// 只有当 names 参数存在且不为空时才添加过滤条件
|
|
6313
|
+
if (names && names.length > 0) {
|
|
6314
|
+
listParams.DataSourceNames = names;
|
|
6315
|
+
}
|
|
6316
|
+
result = await cloudbase.commonService("lowcode").call({
|
|
6317
|
+
Action: "DescribeDataSourceList",
|
|
6318
|
+
Param: listParams,
|
|
6319
|
+
});
|
|
6320
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
6321
|
+
const models = result.Data?.Rows || [];
|
|
6322
|
+
// 只保留基础字段,list操作不返回Schema
|
|
6323
|
+
const simplifiedModels = models.map((model) => ({
|
|
6324
|
+
DbInstanceType: model.DbInstanceType,
|
|
6325
|
+
Title: model.Title,
|
|
6326
|
+
Description: model.Description,
|
|
6327
|
+
Name: model.Name,
|
|
6328
|
+
UpdatedAt: model.UpdatedAt,
|
|
6329
|
+
}));
|
|
6330
|
+
return {
|
|
6331
|
+
content: [
|
|
6332
|
+
{
|
|
6333
|
+
type: "text",
|
|
6334
|
+
text: JSON.stringify({
|
|
6335
|
+
success: true,
|
|
6336
|
+
action: "list",
|
|
6337
|
+
data: simplifiedModels,
|
|
6338
|
+
count: simplifiedModels.length,
|
|
6339
|
+
message: "获取数据模型列表成功",
|
|
6340
|
+
}, null, 2),
|
|
6341
|
+
},
|
|
6342
|
+
],
|
|
6343
|
+
};
|
|
6344
|
+
case "docs":
|
|
6345
|
+
if (!name) {
|
|
6346
|
+
throw new Error("生成SDK文档需要提供模型名称");
|
|
6347
|
+
}
|
|
6348
|
+
try {
|
|
6349
|
+
// 先获取模型信息
|
|
6350
|
+
result = await cloudbase.commonService("lowcode").call({
|
|
6351
|
+
Action: "DescribeBasicDataSource",
|
|
6352
|
+
Param: {
|
|
6353
|
+
EnvId: currentEnvId,
|
|
6354
|
+
Name: name,
|
|
6355
|
+
},
|
|
6356
|
+
});
|
|
6357
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
6358
|
+
if (!result.Data) {
|
|
6359
|
+
throw new Error(`数据模型 ${name} 不存在`);
|
|
6360
|
+
}
|
|
6361
|
+
// 解析Schema获取字段信息
|
|
6362
|
+
let userFields = [];
|
|
6363
|
+
let relations = [];
|
|
6364
|
+
if (result.Data.Schema) {
|
|
6365
|
+
try {
|
|
6366
|
+
const schema = JSON.parse(result.Data.Schema);
|
|
6367
|
+
const properties = schema.properties || {};
|
|
6368
|
+
// 提取用户定义的字段
|
|
6369
|
+
userFields = Object.keys(properties)
|
|
6370
|
+
.filter((key) => !properties[key]["x-system"])
|
|
6371
|
+
.map((key) => {
|
|
6372
|
+
const field = properties[key];
|
|
6373
|
+
return parseFieldStructure(field, key, schema);
|
|
6374
|
+
});
|
|
6375
|
+
// 提取关联关系
|
|
6376
|
+
relations = userFields
|
|
6377
|
+
.filter((field) => field.linkage)
|
|
6378
|
+
.map((field) => ({
|
|
6379
|
+
field: field.name,
|
|
6380
|
+
type: field.format,
|
|
6381
|
+
title: field.title,
|
|
6382
|
+
targetModel: field.linkage.parentDataSourceName,
|
|
6383
|
+
foreignKey: field.linkage.parentFieldKey,
|
|
6384
|
+
displayField: field.linkage.parentFieldTitle,
|
|
6385
|
+
}));
|
|
6386
|
+
}
|
|
6387
|
+
catch (e) {
|
|
6388
|
+
// Schema解析失败,使用空数组
|
|
6389
|
+
console.error("Schema解析失败", e);
|
|
6429
6390
|
}
|
|
6430
|
-
throw error;
|
|
6431
6391
|
}
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
|
|
6447
|
-
|
|
6448
|
-
}
|
|
6449
|
-
|
|
6450
|
-
|
|
6392
|
+
// 生成SDK使用文档
|
|
6393
|
+
const docs = generateSDKDocs(result.Data.Name, result.Data.Title, userFields, relations);
|
|
6394
|
+
return {
|
|
6395
|
+
content: [
|
|
6396
|
+
{
|
|
6397
|
+
type: "text",
|
|
6398
|
+
text: JSON.stringify({
|
|
6399
|
+
success: true,
|
|
6400
|
+
action: "docs",
|
|
6401
|
+
modelName: name,
|
|
6402
|
+
modelTitle: result.Data.Title,
|
|
6403
|
+
docs,
|
|
6404
|
+
message: "SDK使用文档生成成功",
|
|
6405
|
+
}, null, 2),
|
|
6406
|
+
},
|
|
6407
|
+
],
|
|
6408
|
+
};
|
|
6409
|
+
}
|
|
6410
|
+
catch (error) {
|
|
6411
|
+
if (error.original?.Code === "ResourceNotFound") {
|
|
6412
|
+
return {
|
|
6413
|
+
content: [
|
|
6414
|
+
{
|
|
6415
|
+
type: "text",
|
|
6416
|
+
text: JSON.stringify({
|
|
6417
|
+
success: false,
|
|
6418
|
+
action: "docs",
|
|
6419
|
+
error: "ResourceNotFound",
|
|
6420
|
+
message: `数据模型 ${name} 不存在`,
|
|
6421
|
+
}, null, 2),
|
|
6422
|
+
},
|
|
6423
|
+
],
|
|
6424
|
+
};
|
|
6425
|
+
}
|
|
6426
|
+
throw error;
|
|
6427
|
+
}
|
|
6428
|
+
default:
|
|
6429
|
+
throw new Error(`不支持的操作类型: ${action}`);
|
|
6451
6430
|
}
|
|
6452
6431
|
});
|
|
6453
6432
|
// modifyDataModel - 数据模型修改工具(创建/更新)
|
|
@@ -6520,126 +6499,108 @@ classDiagram
|
|
|
6520
6499
|
category: "database",
|
|
6521
6500
|
},
|
|
6522
6501
|
}, async ({ mermaidDiagram, action = "create", publish = false, dbInstanceType = "MYSQL", }) => {
|
|
6523
|
-
|
|
6524
|
-
|
|
6525
|
-
|
|
6526
|
-
|
|
6527
|
-
const schemas = mermaidToJsonSchema(mermaidDiagram);
|
|
6528
|
-
if (!schemas || Object.keys(schemas).length === 0) {
|
|
6529
|
-
return {
|
|
6530
|
-
content: [
|
|
6531
|
-
{
|
|
6532
|
-
type: "text",
|
|
6533
|
-
text: JSON.stringify({
|
|
6534
|
-
success: false,
|
|
6535
|
-
error: "No schemas generated from Mermaid diagram",
|
|
6536
|
-
message: "无法从Mermaid图表生成数据模型Schema",
|
|
6537
|
-
}, null, 2),
|
|
6538
|
-
},
|
|
6539
|
-
],
|
|
6540
|
-
};
|
|
6541
|
-
}
|
|
6542
|
-
// 创建数据模型列表
|
|
6543
|
-
const createDataModelList = Object.entries(schemas).map(([name, schema]) => {
|
|
6544
|
-
return {
|
|
6545
|
-
CreateSource: "cloudbase_create",
|
|
6546
|
-
Creator: null,
|
|
6547
|
-
DbLinkName: null,
|
|
6548
|
-
Description: schema.description ||
|
|
6549
|
-
`${schema.title || name}数据模型`,
|
|
6550
|
-
Schema: JSON.stringify(createBackendSchemaParams(schema)),
|
|
6551
|
-
Title: schema.title || name,
|
|
6552
|
-
Name: name,
|
|
6553
|
-
TableNameRule: "only_name",
|
|
6554
|
-
};
|
|
6555
|
-
});
|
|
6556
|
-
// 调用批量创建数据模型API
|
|
6557
|
-
const result = await cloudbase.commonService("lowcode").call({
|
|
6558
|
-
Action: "BatchCreateDataModelList",
|
|
6559
|
-
Param: {
|
|
6560
|
-
CreateDataModelList: createDataModelList,
|
|
6561
|
-
Creator: null,
|
|
6562
|
-
DbInstanceType: dbInstanceType,
|
|
6563
|
-
EnvId: currentEnvId,
|
|
6564
|
-
},
|
|
6565
|
-
});
|
|
6566
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
6567
|
-
const taskId = result.Data?.TaskId;
|
|
6568
|
-
if (!taskId) {
|
|
6569
|
-
return {
|
|
6570
|
-
content: [
|
|
6571
|
-
{
|
|
6572
|
-
type: "text",
|
|
6573
|
-
text: JSON.stringify({
|
|
6574
|
-
success: false,
|
|
6575
|
-
requestId: result.RequestId,
|
|
6576
|
-
error: "No TaskId returned",
|
|
6577
|
-
message: "创建任务失败,未返回任务ID",
|
|
6578
|
-
}, null, 2),
|
|
6579
|
-
},
|
|
6580
|
-
],
|
|
6581
|
-
};
|
|
6582
|
-
}
|
|
6583
|
-
// 轮询任务状态直至完成或超时
|
|
6584
|
-
const maxWaitTime = 30000; // 30秒超时
|
|
6585
|
-
const startTime = Date.now();
|
|
6586
|
-
let status = "init";
|
|
6587
|
-
let statusResult = null;
|
|
6588
|
-
while (status === "init" && Date.now() - startTime < maxWaitTime) {
|
|
6589
|
-
await new Promise((resolve) => setTimeout(resolve, 2000)); // 等待2秒
|
|
6590
|
-
statusResult = await cloudbase.commonService("lowcode").call({
|
|
6591
|
-
Action: "QueryModelTaskStatus",
|
|
6592
|
-
Param: {
|
|
6593
|
-
EnvId: currentEnvId,
|
|
6594
|
-
TaskId: taskId,
|
|
6595
|
-
},
|
|
6596
|
-
});
|
|
6597
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, statusResult);
|
|
6598
|
-
status = statusResult.Data?.Status || "init";
|
|
6599
|
-
}
|
|
6600
|
-
// 返回最终结果
|
|
6601
|
-
const models = Object.keys(schemas);
|
|
6602
|
-
const successModels = statusResult?.Data?.SuccessResourceIdList || [];
|
|
6603
|
-
const failedModels = models.filter((model) => !successModels.includes(model));
|
|
6502
|
+
const cloudbase = await getManager();
|
|
6503
|
+
let currentEnvId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
6504
|
+
const schemas = mermaidToJsonSchema(mermaidDiagram);
|
|
6505
|
+
if (!schemas || Object.keys(schemas).length === 0) {
|
|
6604
6506
|
return {
|
|
6605
6507
|
content: [
|
|
6606
6508
|
{
|
|
6607
6509
|
type: "text",
|
|
6608
6510
|
text: JSON.stringify({
|
|
6609
|
-
success:
|
|
6610
|
-
|
|
6611
|
-
|
|
6612
|
-
models: models,
|
|
6613
|
-
successModels: successModels,
|
|
6614
|
-
failedModels: failedModels,
|
|
6615
|
-
status: status,
|
|
6616
|
-
action: action,
|
|
6617
|
-
message: status === "success"
|
|
6618
|
-
? `数据模型${action === "create" ? "创建" : "更新"}成功,共处理${models.length}个模型`
|
|
6619
|
-
: status === "init"
|
|
6620
|
-
? `任务超时,任务ID: ${taskId},请稍后手动查询状态`
|
|
6621
|
-
: `数据模型${action === "create" ? "创建" : "更新"}失败`,
|
|
6622
|
-
taskResult: statusResult?.Data,
|
|
6511
|
+
success: false,
|
|
6512
|
+
error: "No schemas generated from Mermaid diagram",
|
|
6513
|
+
message: "无法从Mermaid图表生成数据模型Schema",
|
|
6623
6514
|
}, null, 2),
|
|
6624
6515
|
},
|
|
6625
6516
|
],
|
|
6626
6517
|
};
|
|
6627
6518
|
}
|
|
6628
|
-
|
|
6519
|
+
// 创建数据模型列表
|
|
6520
|
+
const createDataModelList = Object.entries(schemas).map(([name, schema]) => {
|
|
6521
|
+
return {
|
|
6522
|
+
CreateSource: "cloudbase_create",
|
|
6523
|
+
Creator: null,
|
|
6524
|
+
DbLinkName: null,
|
|
6525
|
+
Description: schema.description ||
|
|
6526
|
+
`${schema.title || name}数据模型`,
|
|
6527
|
+
Schema: JSON.stringify(createBackendSchemaParams(schema)),
|
|
6528
|
+
Title: schema.title || name,
|
|
6529
|
+
Name: name,
|
|
6530
|
+
TableNameRule: "only_name",
|
|
6531
|
+
};
|
|
6532
|
+
});
|
|
6533
|
+
// 调用批量创建数据模型API
|
|
6534
|
+
const result = await cloudbase.commonService("lowcode").call({
|
|
6535
|
+
Action: "BatchCreateDataModelList",
|
|
6536
|
+
Param: {
|
|
6537
|
+
CreateDataModelList: createDataModelList,
|
|
6538
|
+
Creator: null,
|
|
6539
|
+
DbInstanceType: dbInstanceType,
|
|
6540
|
+
EnvId: currentEnvId,
|
|
6541
|
+
},
|
|
6542
|
+
});
|
|
6543
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
6544
|
+
const taskId = result.Data?.TaskId;
|
|
6545
|
+
if (!taskId) {
|
|
6629
6546
|
return {
|
|
6630
6547
|
content: [
|
|
6631
6548
|
{
|
|
6632
6549
|
type: "text",
|
|
6633
6550
|
text: JSON.stringify({
|
|
6634
6551
|
success: false,
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
message: "
|
|
6552
|
+
requestId: result.RequestId,
|
|
6553
|
+
error: "No TaskId returned",
|
|
6554
|
+
message: "创建任务失败,未返回任务ID",
|
|
6638
6555
|
}, null, 2),
|
|
6639
6556
|
},
|
|
6640
6557
|
],
|
|
6641
6558
|
};
|
|
6642
6559
|
}
|
|
6560
|
+
// 轮询任务状态直至完成或超时
|
|
6561
|
+
const maxWaitTime = 30000; // 30秒超时
|
|
6562
|
+
const startTime = Date.now();
|
|
6563
|
+
let status = "init";
|
|
6564
|
+
let statusResult = null;
|
|
6565
|
+
while (status === "init" && Date.now() - startTime < maxWaitTime) {
|
|
6566
|
+
await new Promise((resolve) => setTimeout(resolve, 2000)); // 等待2秒
|
|
6567
|
+
statusResult = await cloudbase.commonService("lowcode").call({
|
|
6568
|
+
Action: "QueryModelTaskStatus",
|
|
6569
|
+
Param: {
|
|
6570
|
+
EnvId: currentEnvId,
|
|
6571
|
+
TaskId: taskId,
|
|
6572
|
+
},
|
|
6573
|
+
});
|
|
6574
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, statusResult);
|
|
6575
|
+
status = statusResult.Data?.Status || "init";
|
|
6576
|
+
}
|
|
6577
|
+
// 返回最终结果
|
|
6578
|
+
const models = Object.keys(schemas);
|
|
6579
|
+
const successModels = statusResult?.Data?.SuccessResourceIdList || [];
|
|
6580
|
+
const failedModels = models.filter((model) => !successModels.includes(model));
|
|
6581
|
+
return {
|
|
6582
|
+
content: [
|
|
6583
|
+
{
|
|
6584
|
+
type: "text",
|
|
6585
|
+
text: JSON.stringify({
|
|
6586
|
+
success: status === "success",
|
|
6587
|
+
requestId: result.RequestId,
|
|
6588
|
+
taskId: taskId,
|
|
6589
|
+
models: models,
|
|
6590
|
+
successModels: successModels,
|
|
6591
|
+
failedModels: failedModels,
|
|
6592
|
+
status: status,
|
|
6593
|
+
action: action,
|
|
6594
|
+
message: status === "success"
|
|
6595
|
+
? `数据模型${action === "create" ? "创建" : "更新"}成功,共处理${models.length}个模型`
|
|
6596
|
+
: status === "init"
|
|
6597
|
+
? `任务超时,任务ID: ${taskId},请稍后手动查询状态`
|
|
6598
|
+
: `数据模型${action === "create" ? "创建" : "更新"}失败`,
|
|
6599
|
+
taskResult: statusResult?.Data,
|
|
6600
|
+
}, null, 2),
|
|
6601
|
+
},
|
|
6602
|
+
],
|
|
6603
|
+
};
|
|
6643
6604
|
});
|
|
6644
6605
|
}
|
|
6645
6606
|
|
|
@@ -7454,41 +7415,25 @@ function registerInviteCodeTools(server) {
|
|
|
7454
7415
|
]
|
|
7455
7416
|
};
|
|
7456
7417
|
}
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
|
|
7460
|
-
|
|
7461
|
-
|
|
7462
|
-
|
|
7463
|
-
|
|
7464
|
-
|
|
7465
|
-
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
|
|
7469
|
-
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
|
|
7475
|
-
|
|
7476
|
-
};
|
|
7477
|
-
}
|
|
7478
|
-
catch (e) {
|
|
7479
|
-
return {
|
|
7480
|
-
content: [
|
|
7481
|
-
{
|
|
7482
|
-
type: "text",
|
|
7483
|
-
text: JSON.stringify({
|
|
7484
|
-
ErrorCode: e.code || 'Exception',
|
|
7485
|
-
ErrorMsg: '激活失败:' + e.message,
|
|
7486
|
-
RequestId: e.RequestId || ''
|
|
7487
|
-
}, null, 2)
|
|
7488
|
-
}
|
|
7489
|
-
]
|
|
7490
|
-
};
|
|
7491
|
-
}
|
|
7418
|
+
const manager = await getManager();
|
|
7419
|
+
const EnvId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
7420
|
+
const result = await manager.commonService().call({
|
|
7421
|
+
Action: 'ActivateInviteCode',
|
|
7422
|
+
Param: { InviteCode, EnvId }
|
|
7423
|
+
});
|
|
7424
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
7425
|
+
return {
|
|
7426
|
+
content: [
|
|
7427
|
+
{
|
|
7428
|
+
type: "text",
|
|
7429
|
+
text: JSON.stringify({
|
|
7430
|
+
ErrorCode: result?.ErrorCode || '',
|
|
7431
|
+
ErrorMsg: result?.ErrorMsg || '',
|
|
7432
|
+
RequestId: result?.RequestId || ''
|
|
7433
|
+
}, null, 2)
|
|
7434
|
+
}
|
|
7435
|
+
]
|
|
7436
|
+
};
|
|
7492
7437
|
});
|
|
7493
7438
|
}
|
|
7494
7439
|
|
|
@@ -7533,94 +7478,78 @@ function registerStorageTools(server) {
|
|
|
7533
7478
|
category: "storage"
|
|
7534
7479
|
}
|
|
7535
7480
|
}, async (args) => {
|
|
7536
|
-
|
|
7537
|
-
|
|
7538
|
-
|
|
7539
|
-
|
|
7540
|
-
|
|
7541
|
-
|
|
7542
|
-
|
|
7543
|
-
|
|
7544
|
-
|
|
7545
|
-
|
|
7546
|
-
|
|
7547
|
-
|
|
7548
|
-
|
|
7549
|
-
|
|
7550
|
-
|
|
7551
|
-
|
|
7552
|
-
|
|
7553
|
-
|
|
7554
|
-
|
|
7555
|
-
|
|
7556
|
-
|
|
7557
|
-
|
|
7558
|
-
|
|
7559
|
-
|
|
7560
|
-
|
|
7561
|
-
|
|
7562
|
-
|
|
7563
|
-
|
|
7564
|
-
|
|
7565
|
-
|
|
7566
|
-
|
|
7567
|
-
|
|
7568
|
-
|
|
7569
|
-
|
|
7570
|
-
|
|
7571
|
-
|
|
7572
|
-
|
|
7573
|
-
|
|
7574
|
-
|
|
7575
|
-
|
|
7576
|
-
|
|
7577
|
-
|
|
7578
|
-
|
|
7579
|
-
|
|
7580
|
-
|
|
7581
|
-
|
|
7582
|
-
|
|
7583
|
-
|
|
7584
|
-
|
|
7585
|
-
|
|
7586
|
-
|
|
7587
|
-
|
|
7588
|
-
|
|
7589
|
-
|
|
7590
|
-
|
|
7591
|
-
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
|
|
7596
|
-
|
|
7597
|
-
|
|
7598
|
-
|
|
7599
|
-
|
|
7600
|
-
|
|
7601
|
-
|
|
7602
|
-
|
|
7603
|
-
|
|
7604
|
-
|
|
7605
|
-
};
|
|
7606
|
-
}
|
|
7607
|
-
default:
|
|
7608
|
-
throw new Error(`Unsupported action: ${input.action}`);
|
|
7481
|
+
const input = args;
|
|
7482
|
+
const manager = await getManager();
|
|
7483
|
+
if (!manager) {
|
|
7484
|
+
throw new Error("Failed to initialize CloudBase manager. Please check your credentials and environment configuration.");
|
|
7485
|
+
}
|
|
7486
|
+
const storageService = manager.storage;
|
|
7487
|
+
switch (input.action) {
|
|
7488
|
+
case 'list': {
|
|
7489
|
+
const result = await storageService.listDirectoryFiles(input.cloudPath);
|
|
7490
|
+
return {
|
|
7491
|
+
content: [
|
|
7492
|
+
{
|
|
7493
|
+
type: "text",
|
|
7494
|
+
text: JSON.stringify({
|
|
7495
|
+
success: true,
|
|
7496
|
+
data: {
|
|
7497
|
+
action: 'list',
|
|
7498
|
+
cloudPath: input.cloudPath,
|
|
7499
|
+
files: result || [],
|
|
7500
|
+
totalCount: result?.length || 0
|
|
7501
|
+
},
|
|
7502
|
+
message: `Successfully listed ${result?.length || 0} files in directory '${input.cloudPath}'`
|
|
7503
|
+
}, null, 2)
|
|
7504
|
+
}
|
|
7505
|
+
]
|
|
7506
|
+
};
|
|
7507
|
+
}
|
|
7508
|
+
case 'info': {
|
|
7509
|
+
const result = await storageService.getFileInfo(input.cloudPath);
|
|
7510
|
+
return {
|
|
7511
|
+
content: [
|
|
7512
|
+
{
|
|
7513
|
+
type: "text",
|
|
7514
|
+
text: JSON.stringify({
|
|
7515
|
+
success: true,
|
|
7516
|
+
data: {
|
|
7517
|
+
action: 'info',
|
|
7518
|
+
cloudPath: input.cloudPath,
|
|
7519
|
+
fileInfo: result
|
|
7520
|
+
},
|
|
7521
|
+
message: `Successfully retrieved file info for '${input.cloudPath}'`
|
|
7522
|
+
}, null, 2)
|
|
7523
|
+
}
|
|
7524
|
+
]
|
|
7525
|
+
};
|
|
7526
|
+
}
|
|
7527
|
+
case 'url': {
|
|
7528
|
+
const result = await storageService.getTemporaryUrl([{
|
|
7529
|
+
cloudPath: input.cloudPath,
|
|
7530
|
+
maxAge: input.maxAge || 3600
|
|
7531
|
+
}]);
|
|
7532
|
+
return {
|
|
7533
|
+
content: [
|
|
7534
|
+
{
|
|
7535
|
+
type: "text",
|
|
7536
|
+
text: JSON.stringify({
|
|
7537
|
+
success: true,
|
|
7538
|
+
data: {
|
|
7539
|
+
action: 'url',
|
|
7540
|
+
cloudPath: input.cloudPath,
|
|
7541
|
+
temporaryUrl: result[0]?.url || "",
|
|
7542
|
+
expireTime: `${input.maxAge || 3600}秒`,
|
|
7543
|
+
fileId: result[0]?.fileId || ""
|
|
7544
|
+
},
|
|
7545
|
+
message: `Successfully generated temporary URL for '${input.cloudPath}'`
|
|
7546
|
+
}, null, 2)
|
|
7547
|
+
}
|
|
7548
|
+
]
|
|
7549
|
+
};
|
|
7609
7550
|
}
|
|
7610
|
-
|
|
7611
|
-
|
|
7612
|
-
return {
|
|
7613
|
-
content: [
|
|
7614
|
-
{
|
|
7615
|
-
type: "text",
|
|
7616
|
-
text: JSON.stringify({
|
|
7617
|
-
success: false,
|
|
7618
|
-
error: error.message || 'Unknown error occurred',
|
|
7619
|
-
message: `Failed to query storage information. Please check your permissions and parameters.`
|
|
7620
|
-
}, null, 2)
|
|
7621
|
-
}
|
|
7622
|
-
]
|
|
7623
|
-
};
|
|
7551
|
+
default:
|
|
7552
|
+
throw new Error(`Unsupported action: ${input.action}`);
|
|
7624
7553
|
}
|
|
7625
7554
|
});
|
|
7626
7555
|
// Tool 2: manageStorage - 管理存储文件(写操作)
|
|
@@ -7636,156 +7565,153 @@ function registerStorageTools(server) {
|
|
|
7636
7565
|
category: "storage"
|
|
7637
7566
|
}
|
|
7638
7567
|
}, async (args) => {
|
|
7639
|
-
|
|
7640
|
-
|
|
7641
|
-
|
|
7642
|
-
|
|
7643
|
-
|
|
7644
|
-
|
|
7645
|
-
|
|
7646
|
-
|
|
7647
|
-
|
|
7648
|
-
|
|
7649
|
-
|
|
7650
|
-
|
|
7651
|
-
|
|
7652
|
-
|
|
7653
|
-
|
|
7654
|
-
|
|
7655
|
-
}
|
|
7656
|
-
});
|
|
7657
|
-
}
|
|
7658
|
-
else {
|
|
7659
|
-
// 上传文件
|
|
7660
|
-
await storageService.uploadFile({
|
|
7661
|
-
localPath: input.localPath,
|
|
7662
|
-
cloudPath: input.cloudPath,
|
|
7663
|
-
onProgress: (progressData) => {
|
|
7664
|
-
console.log("Upload file progress:", progressData);
|
|
7665
|
-
}
|
|
7666
|
-
});
|
|
7667
|
-
}
|
|
7668
|
-
// 获取文件临时下载地址
|
|
7669
|
-
const fileUrls = await storageService.getTemporaryUrl([{
|
|
7670
|
-
cloudPath: input.cloudPath,
|
|
7671
|
-
maxAge: 3600 // 临时链接有效期1小时
|
|
7672
|
-
}]);
|
|
7673
|
-
return {
|
|
7674
|
-
content: [
|
|
7675
|
-
{
|
|
7676
|
-
type: "text",
|
|
7677
|
-
text: JSON.stringify({
|
|
7678
|
-
success: true,
|
|
7679
|
-
data: {
|
|
7680
|
-
action: 'upload',
|
|
7681
|
-
localPath: input.localPath,
|
|
7682
|
-
cloudPath: input.cloudPath,
|
|
7683
|
-
isDirectory: input.isDirectory,
|
|
7684
|
-
temporaryUrl: fileUrls[0]?.url || "",
|
|
7685
|
-
expireTime: "1小时"
|
|
7686
|
-
},
|
|
7687
|
-
message: `Successfully uploaded ${input.isDirectory ? 'directory' : 'file'} from '${input.localPath}' to '${input.cloudPath}'`
|
|
7688
|
-
}, null, 2)
|
|
7689
|
-
}
|
|
7690
|
-
]
|
|
7691
|
-
};
|
|
7568
|
+
const input = args;
|
|
7569
|
+
const manager = await getManager();
|
|
7570
|
+
if (!manager) {
|
|
7571
|
+
throw new Error("Failed to initialize CloudBase manager. Please check your credentials and environment configuration.");
|
|
7572
|
+
}
|
|
7573
|
+
const storageService = manager.storage;
|
|
7574
|
+
switch (input.action) {
|
|
7575
|
+
case 'upload': {
|
|
7576
|
+
if (input.isDirectory) {
|
|
7577
|
+
await storageService.uploadDirectory({
|
|
7578
|
+
localPath: input.localPath,
|
|
7579
|
+
cloudPath: input.cloudPath,
|
|
7580
|
+
onProgress: (progressData) => {
|
|
7581
|
+
console.log("Upload directory progress:", progressData);
|
|
7582
|
+
}
|
|
7583
|
+
});
|
|
7692
7584
|
}
|
|
7693
|
-
|
|
7694
|
-
|
|
7695
|
-
|
|
7696
|
-
|
|
7697
|
-
|
|
7698
|
-
|
|
7699
|
-
}
|
|
7700
|
-
}
|
|
7701
|
-
else {
|
|
7702
|
-
// 下载文件
|
|
7703
|
-
await storageService.downloadFile({
|
|
7704
|
-
cloudPath: input.cloudPath,
|
|
7705
|
-
localPath: input.localPath
|
|
7706
|
-
});
|
|
7707
|
-
}
|
|
7708
|
-
return {
|
|
7709
|
-
content: [
|
|
7710
|
-
{
|
|
7711
|
-
type: "text",
|
|
7712
|
-
text: JSON.stringify({
|
|
7713
|
-
success: true,
|
|
7714
|
-
data: {
|
|
7715
|
-
action: 'download',
|
|
7716
|
-
cloudPath: input.cloudPath,
|
|
7717
|
-
localPath: input.localPath,
|
|
7718
|
-
isDirectory: input.isDirectory
|
|
7719
|
-
},
|
|
7720
|
-
message: `Successfully downloaded ${input.isDirectory ? 'directory' : 'file'} from '${input.cloudPath}' to '${input.localPath}'`
|
|
7721
|
-
}, null, 2)
|
|
7722
|
-
}
|
|
7723
|
-
]
|
|
7724
|
-
};
|
|
7585
|
+
else {
|
|
7586
|
+
await storageService.uploadFile({
|
|
7587
|
+
localPath: input.localPath,
|
|
7588
|
+
cloudPath: input.cloudPath,
|
|
7589
|
+
onProgress: (progressData) => {
|
|
7590
|
+
console.log("Upload file progress:", progressData);
|
|
7591
|
+
}
|
|
7592
|
+
});
|
|
7725
7593
|
}
|
|
7726
|
-
|
|
7727
|
-
|
|
7728
|
-
|
|
7729
|
-
|
|
7730
|
-
|
|
7731
|
-
|
|
7732
|
-
|
|
7733
|
-
|
|
7734
|
-
|
|
7735
|
-
|
|
7736
|
-
|
|
7737
|
-
|
|
7738
|
-
|
|
7739
|
-
|
|
7740
|
-
|
|
7741
|
-
|
|
7742
|
-
|
|
7743
|
-
|
|
7744
|
-
|
|
7745
|
-
|
|
7746
|
-
|
|
7747
|
-
|
|
7748
|
-
|
|
7594
|
+
const fileUrls = await storageService.getTemporaryUrl([{
|
|
7595
|
+
cloudPath: input.cloudPath,
|
|
7596
|
+
maxAge: 3600
|
|
7597
|
+
}]);
|
|
7598
|
+
return {
|
|
7599
|
+
content: [
|
|
7600
|
+
{
|
|
7601
|
+
type: "text",
|
|
7602
|
+
text: JSON.stringify({
|
|
7603
|
+
success: true,
|
|
7604
|
+
data: {
|
|
7605
|
+
action: 'upload',
|
|
7606
|
+
localPath: input.localPath,
|
|
7607
|
+
cloudPath: input.cloudPath,
|
|
7608
|
+
isDirectory: input.isDirectory,
|
|
7609
|
+
temporaryUrl: fileUrls[0]?.url || "",
|
|
7610
|
+
expireTime: "1小时"
|
|
7611
|
+
},
|
|
7612
|
+
message: `Successfully uploaded ${input.isDirectory ? 'directory' : 'file'} from '${input.localPath}' to '${input.cloudPath}'`
|
|
7613
|
+
}, null, 2)
|
|
7614
|
+
}
|
|
7615
|
+
]
|
|
7616
|
+
};
|
|
7617
|
+
}
|
|
7618
|
+
case 'download': {
|
|
7619
|
+
if (input.isDirectory) {
|
|
7620
|
+
await storageService.downloadDirectory({
|
|
7621
|
+
cloudPath: input.cloudPath,
|
|
7622
|
+
localPath: input.localPath
|
|
7623
|
+
});
|
|
7624
|
+
}
|
|
7625
|
+
else {
|
|
7626
|
+
await storageService.downloadFile({
|
|
7627
|
+
cloudPath: input.cloudPath,
|
|
7628
|
+
localPath: input.localPath
|
|
7629
|
+
});
|
|
7630
|
+
}
|
|
7631
|
+
return {
|
|
7632
|
+
content: [
|
|
7633
|
+
{
|
|
7634
|
+
type: "text",
|
|
7635
|
+
text: JSON.stringify({
|
|
7636
|
+
success: true,
|
|
7637
|
+
data: {
|
|
7638
|
+
action: 'download',
|
|
7639
|
+
cloudPath: input.cloudPath,
|
|
7640
|
+
localPath: input.localPath,
|
|
7641
|
+
isDirectory: input.isDirectory
|
|
7642
|
+
},
|
|
7643
|
+
message: `Successfully downloaded ${input.isDirectory ? 'directory' : 'file'} from '${input.cloudPath}' to '${input.localPath}'`
|
|
7644
|
+
}, null, 2)
|
|
7645
|
+
}
|
|
7646
|
+
]
|
|
7647
|
+
};
|
|
7648
|
+
}
|
|
7649
|
+
case 'delete': {
|
|
7650
|
+
if (!input.force) {
|
|
7749
7651
|
return {
|
|
7750
7652
|
content: [
|
|
7751
7653
|
{
|
|
7752
7654
|
type: "text",
|
|
7753
7655
|
text: JSON.stringify({
|
|
7754
|
-
success:
|
|
7755
|
-
|
|
7756
|
-
|
|
7757
|
-
cloudPath: input.cloudPath,
|
|
7758
|
-
isDirectory: input.isDirectory,
|
|
7759
|
-
deleted: true
|
|
7760
|
-
},
|
|
7761
|
-
message: `Successfully deleted ${input.isDirectory ? 'directory' : 'file'} '${input.cloudPath}'`
|
|
7656
|
+
success: false,
|
|
7657
|
+
error: "Delete operation requires confirmation",
|
|
7658
|
+
message: "Please set force: true to confirm deletion. This action cannot be undone."
|
|
7762
7659
|
}, null, 2)
|
|
7763
7660
|
}
|
|
7764
7661
|
]
|
|
7765
7662
|
};
|
|
7766
7663
|
}
|
|
7767
|
-
|
|
7768
|
-
|
|
7664
|
+
if (input.isDirectory) {
|
|
7665
|
+
await storageService.deleteDirectory(input.cloudPath);
|
|
7666
|
+
}
|
|
7667
|
+
else {
|
|
7668
|
+
await storageService.deleteFile([input.cloudPath]);
|
|
7669
|
+
}
|
|
7670
|
+
return {
|
|
7671
|
+
content: [
|
|
7672
|
+
{
|
|
7673
|
+
type: "text",
|
|
7674
|
+
text: JSON.stringify({
|
|
7675
|
+
success: true,
|
|
7676
|
+
data: {
|
|
7677
|
+
action: 'delete',
|
|
7678
|
+
cloudPath: input.cloudPath,
|
|
7679
|
+
isDirectory: input.isDirectory,
|
|
7680
|
+
deleted: true
|
|
7681
|
+
},
|
|
7682
|
+
message: `Successfully deleted ${input.isDirectory ? 'directory' : 'file'} '${input.cloudPath}'`
|
|
7683
|
+
}, null, 2)
|
|
7684
|
+
}
|
|
7685
|
+
]
|
|
7686
|
+
};
|
|
7769
7687
|
}
|
|
7770
|
-
|
|
7771
|
-
|
|
7772
|
-
return {
|
|
7773
|
-
content: [
|
|
7774
|
-
{
|
|
7775
|
-
type: "text",
|
|
7776
|
-
text: JSON.stringify({
|
|
7777
|
-
success: false,
|
|
7778
|
-
error: error.message || 'Unknown error occurred',
|
|
7779
|
-
message: `Failed to manage storage. Please check your permissions and parameters.`
|
|
7780
|
-
}, null, 2)
|
|
7781
|
-
}
|
|
7782
|
-
]
|
|
7783
|
-
};
|
|
7688
|
+
default:
|
|
7689
|
+
throw new Error(`Unsupported action: ${input.action}`);
|
|
7784
7690
|
}
|
|
7785
7691
|
});
|
|
7786
7692
|
}
|
|
7787
7693
|
|
|
7788
7694
|
|
|
7695
|
+
/***/ }),
|
|
7696
|
+
|
|
7697
|
+
/***/ 5018:
|
|
7698
|
+
/***/ ((__unused_webpack_module, exports) => {
|
|
7699
|
+
|
|
7700
|
+
|
|
7701
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
7702
|
+
exports.isInternationalRegion = void 0;
|
|
7703
|
+
exports.isValidRegion = isValidRegion;
|
|
7704
|
+
const REGION = {
|
|
7705
|
+
SHANGHAI: 'ap-shanghai',
|
|
7706
|
+
SINGAPORE: 'ap-singapore',
|
|
7707
|
+
};
|
|
7708
|
+
const isInternationalRegion = (region) => region === REGION.SINGAPORE;
|
|
7709
|
+
exports.isInternationalRegion = isInternationalRegion;
|
|
7710
|
+
function isValidRegion(region) {
|
|
7711
|
+
return Object.values(REGION).includes(region);
|
|
7712
|
+
}
|
|
7713
|
+
|
|
7714
|
+
|
|
7789
7715
|
/***/ }),
|
|
7790
7716
|
|
|
7791
7717
|
/***/ 5023:
|
|
@@ -7934,113 +7860,97 @@ function registerCloudRunTools(server) {
|
|
|
7934
7860
|
category: "cloudrun"
|
|
7935
7861
|
}
|
|
7936
7862
|
}, async (args) => {
|
|
7937
|
-
|
|
7938
|
-
|
|
7939
|
-
|
|
7940
|
-
|
|
7941
|
-
|
|
7942
|
-
|
|
7943
|
-
|
|
7944
|
-
|
|
7945
|
-
|
|
7946
|
-
|
|
7947
|
-
|
|
7948
|
-
|
|
7949
|
-
|
|
7950
|
-
|
|
7951
|
-
listParams.serverName = input.serverName;
|
|
7952
|
-
}
|
|
7953
|
-
if (input.serverType) {
|
|
7954
|
-
listParams.serverType = input.serverType;
|
|
7955
|
-
}
|
|
7956
|
-
const result = await cloudrunService.list(listParams);
|
|
7957
|
-
return {
|
|
7958
|
-
content: [
|
|
7959
|
-
{
|
|
7960
|
-
type: "text",
|
|
7961
|
-
text: JSON.stringify({
|
|
7962
|
-
success: true,
|
|
7963
|
-
data: {
|
|
7964
|
-
services: result.ServerList || [],
|
|
7965
|
-
pagination: {
|
|
7966
|
-
total: result.Total || 0,
|
|
7967
|
-
pageSize: input.pageSize,
|
|
7968
|
-
pageNum: input.pageNum,
|
|
7969
|
-
totalPages: Math.ceil((result.Total || 0) / (input.pageSize || 10))
|
|
7970
|
-
}
|
|
7971
|
-
},
|
|
7972
|
-
message: `Found ${result.ServerList?.length || 0} CloudRun services`
|
|
7973
|
-
}, null, 2)
|
|
7974
|
-
}
|
|
7975
|
-
]
|
|
7976
|
-
};
|
|
7863
|
+
const input = args;
|
|
7864
|
+
const manager = await getManager();
|
|
7865
|
+
if (!manager) {
|
|
7866
|
+
throw new Error("Failed to initialize CloudBase manager. Please check your credentials and environment configuration.");
|
|
7867
|
+
}
|
|
7868
|
+
const cloudrunService = manager.cloudrun;
|
|
7869
|
+
switch (input.action) {
|
|
7870
|
+
case 'list': {
|
|
7871
|
+
const listParams = {
|
|
7872
|
+
pageSize: input.pageSize,
|
|
7873
|
+
pageNum: input.pageNum,
|
|
7874
|
+
};
|
|
7875
|
+
if (input.serverName) {
|
|
7876
|
+
listParams.serverName = input.serverName;
|
|
7977
7877
|
}
|
|
7978
|
-
|
|
7979
|
-
|
|
7980
|
-
const result = await cloudrunService.detail({ serverName });
|
|
7981
|
-
if (!result) {
|
|
7982
|
-
return {
|
|
7983
|
-
content: [
|
|
7984
|
-
{
|
|
7985
|
-
type: "text",
|
|
7986
|
-
text: JSON.stringify({
|
|
7987
|
-
success: false,
|
|
7988
|
-
error: `Service '${serverName}' not found`,
|
|
7989
|
-
message: "Please check the service name and try again."
|
|
7990
|
-
}, null, 2)
|
|
7991
|
-
}
|
|
7992
|
-
]
|
|
7993
|
-
};
|
|
7994
|
-
}
|
|
7995
|
-
return {
|
|
7996
|
-
content: [
|
|
7997
|
-
{
|
|
7998
|
-
type: "text",
|
|
7999
|
-
text: JSON.stringify({
|
|
8000
|
-
success: true,
|
|
8001
|
-
data: {
|
|
8002
|
-
service: result
|
|
8003
|
-
},
|
|
8004
|
-
message: `Retrieved details for service '${serverName}'`
|
|
8005
|
-
}, null, 2)
|
|
8006
|
-
}
|
|
8007
|
-
]
|
|
8008
|
-
};
|
|
7878
|
+
if (input.serverType) {
|
|
7879
|
+
listParams.serverType = input.serverType;
|
|
8009
7880
|
}
|
|
8010
|
-
|
|
8011
|
-
|
|
7881
|
+
const result = await cloudrunService.list(listParams);
|
|
7882
|
+
return {
|
|
7883
|
+
content: [
|
|
7884
|
+
{
|
|
7885
|
+
type: "text",
|
|
7886
|
+
text: JSON.stringify({
|
|
7887
|
+
success: true,
|
|
7888
|
+
data: {
|
|
7889
|
+
services: result.ServerList || [],
|
|
7890
|
+
pagination: {
|
|
7891
|
+
total: result.Total || 0,
|
|
7892
|
+
pageSize: input.pageSize,
|
|
7893
|
+
pageNum: input.pageNum,
|
|
7894
|
+
totalPages: Math.ceil((result.Total || 0) / (input.pageSize || 10))
|
|
7895
|
+
}
|
|
7896
|
+
},
|
|
7897
|
+
message: `Found ${result.ServerList?.length || 0} CloudRun services`
|
|
7898
|
+
}, null, 2)
|
|
7899
|
+
}
|
|
7900
|
+
]
|
|
7901
|
+
};
|
|
7902
|
+
}
|
|
7903
|
+
case 'detail': {
|
|
7904
|
+
const serverName = input.detailServerName || input.serverName;
|
|
7905
|
+
const result = await cloudrunService.detail({ serverName });
|
|
7906
|
+
if (!result) {
|
|
8012
7907
|
return {
|
|
8013
7908
|
content: [
|
|
8014
7909
|
{
|
|
8015
7910
|
type: "text",
|
|
8016
7911
|
text: JSON.stringify({
|
|
8017
|
-
success:
|
|
8018
|
-
|
|
8019
|
-
|
|
8020
|
-
},
|
|
8021
|
-
message: `Found ${result?.length || 0} available templates`
|
|
7912
|
+
success: false,
|
|
7913
|
+
error: `Service '${serverName}' not found`,
|
|
7914
|
+
message: "Please check the service name and try again."
|
|
8022
7915
|
}, null, 2)
|
|
8023
7916
|
}
|
|
8024
7917
|
]
|
|
8025
7918
|
};
|
|
8026
7919
|
}
|
|
8027
|
-
|
|
8028
|
-
|
|
7920
|
+
return {
|
|
7921
|
+
content: [
|
|
7922
|
+
{
|
|
7923
|
+
type: "text",
|
|
7924
|
+
text: JSON.stringify({
|
|
7925
|
+
success: true,
|
|
7926
|
+
data: {
|
|
7927
|
+
service: result
|
|
7928
|
+
},
|
|
7929
|
+
message: `Retrieved details for service '${serverName}'`
|
|
7930
|
+
}, null, 2)
|
|
7931
|
+
}
|
|
7932
|
+
]
|
|
7933
|
+
};
|
|
8029
7934
|
}
|
|
8030
|
-
|
|
8031
|
-
|
|
8032
|
-
|
|
8033
|
-
|
|
8034
|
-
|
|
8035
|
-
|
|
8036
|
-
|
|
8037
|
-
|
|
8038
|
-
|
|
8039
|
-
|
|
8040
|
-
|
|
8041
|
-
|
|
8042
|
-
|
|
8043
|
-
|
|
7935
|
+
case 'templates': {
|
|
7936
|
+
const result = await cloudrunService.getTemplates();
|
|
7937
|
+
return {
|
|
7938
|
+
content: [
|
|
7939
|
+
{
|
|
7940
|
+
type: "text",
|
|
7941
|
+
text: JSON.stringify({
|
|
7942
|
+
success: true,
|
|
7943
|
+
data: {
|
|
7944
|
+
templates: result || []
|
|
7945
|
+
},
|
|
7946
|
+
message: `Found ${result?.length || 0} available templates`
|
|
7947
|
+
}, null, 2)
|
|
7948
|
+
}
|
|
7949
|
+
]
|
|
7950
|
+
};
|
|
7951
|
+
}
|
|
7952
|
+
default:
|
|
7953
|
+
throw new Error(`Unsupported action: ${input.action}`);
|
|
8044
7954
|
}
|
|
8045
7955
|
});
|
|
8046
7956
|
// Track local running processes for CloudRun function services
|
|
@@ -8058,62 +7968,60 @@ function registerCloudRunTools(server) {
|
|
|
8058
7968
|
category: "cloudrun"
|
|
8059
7969
|
}
|
|
8060
7970
|
}, async (args) => {
|
|
8061
|
-
|
|
8062
|
-
|
|
8063
|
-
|
|
8064
|
-
|
|
8065
|
-
|
|
8066
|
-
|
|
8067
|
-
|
|
8068
|
-
|
|
8069
|
-
|
|
8070
|
-
|
|
8071
|
-
|
|
8072
|
-
|
|
8073
|
-
|
|
8074
|
-
|
|
8075
|
-
|
|
8076
|
-
|
|
8077
|
-
|
|
8078
|
-
|
|
8079
|
-
|
|
8080
|
-
|
|
8081
|
-
|
|
8082
|
-
|
|
8083
|
-
|
|
8084
|
-
|
|
8085
|
-
|
|
8086
|
-
|
|
8087
|
-
|
|
8088
|
-
|
|
8089
|
-
|
|
8090
|
-
|
|
8091
|
-
|
|
8092
|
-
|
|
8093
|
-
|
|
8094
|
-
|
|
7971
|
+
const input = args;
|
|
7972
|
+
const manager = await getManager();
|
|
7973
|
+
if (!manager) {
|
|
7974
|
+
throw new Error("Failed to initialize CloudBase manager. Please check your credentials and environment configuration.");
|
|
7975
|
+
}
|
|
7976
|
+
const cloudrunService = manager.cloudrun;
|
|
7977
|
+
let targetPath;
|
|
7978
|
+
if (input.targetPath) {
|
|
7979
|
+
targetPath = validateAndNormalizePath(input.targetPath);
|
|
7980
|
+
}
|
|
7981
|
+
switch (input.action) {
|
|
7982
|
+
case 'createAgent': {
|
|
7983
|
+
if (!targetPath) {
|
|
7984
|
+
throw new Error("targetPath is required for createAgent operation");
|
|
7985
|
+
}
|
|
7986
|
+
if (!input.agentConfig) {
|
|
7987
|
+
throw new Error("agentConfig is required for createAgent operation");
|
|
7988
|
+
}
|
|
7989
|
+
const { agentName, botTag, description, template = 'blank' } = input.agentConfig;
|
|
7990
|
+
// Generate BotId
|
|
7991
|
+
const botId = botTag ? `ibot-${agentName}-${botTag}` : `ibot-${agentName}-${Date.now()}`;
|
|
7992
|
+
// Create Agent using CloudBase Manager
|
|
7993
|
+
const agentResult = await manager.agent.createFunctionAgent(targetPath, {
|
|
7994
|
+
Name: agentName,
|
|
7995
|
+
BotId: botId,
|
|
7996
|
+
Introduction: description || `Agent created by ${agentName}`,
|
|
7997
|
+
Avatar: undefined
|
|
7998
|
+
});
|
|
7999
|
+
// Create project directory
|
|
8000
|
+
const projectDir = path_1.default.join(targetPath, input.serverName);
|
|
8001
|
+
if (!fs_1.default.existsSync(projectDir)) {
|
|
8002
|
+
fs_1.default.mkdirSync(projectDir, { recursive: true });
|
|
8003
|
+
}
|
|
8004
|
+
// Generate package.json
|
|
8005
|
+
const packageJson = {
|
|
8006
|
+
name: input.serverName,
|
|
8007
|
+
version: "1.0.0",
|
|
8008
|
+
description: description || `Agent created by ${agentName}`,
|
|
8009
|
+
main: "index.js",
|
|
8010
|
+
scripts: {
|
|
8011
|
+
"dev": "tcb cloudrun run --runMode=agent -w",
|
|
8012
|
+
"deploy": "tcb cloudrun deploy",
|
|
8013
|
+
"start": "node index.js"
|
|
8014
|
+
},
|
|
8015
|
+
dependencies: {
|
|
8016
|
+
"@cloudbase/aiagent-framework": "^1.0.0-beta.10"
|
|
8017
|
+
},
|
|
8018
|
+
devDependencies: {
|
|
8019
|
+
"@cloudbase/cli": "^2.6.16"
|
|
8095
8020
|
}
|
|
8096
|
-
|
|
8097
|
-
|
|
8098
|
-
|
|
8099
|
-
|
|
8100
|
-
description: description || `Agent created by ${agentName}`,
|
|
8101
|
-
main: "index.js",
|
|
8102
|
-
scripts: {
|
|
8103
|
-
"dev": "tcb cloudrun run --runMode=agent -w",
|
|
8104
|
-
"deploy": "tcb cloudrun deploy",
|
|
8105
|
-
"start": "node index.js"
|
|
8106
|
-
},
|
|
8107
|
-
dependencies: {
|
|
8108
|
-
"@cloudbase/aiagent-framework": "^1.0.0-beta.10"
|
|
8109
|
-
},
|
|
8110
|
-
devDependencies: {
|
|
8111
|
-
"@cloudbase/cli": "^2.6.16"
|
|
8112
|
-
}
|
|
8113
|
-
};
|
|
8114
|
-
fs_1.default.writeFileSync(path_1.default.join(projectDir, 'package.json'), JSON.stringify(packageJson, null, 2));
|
|
8115
|
-
// Generate index.js with Agent template
|
|
8116
|
-
const indexJsContent = `const { IBot } = require("@cloudbase/aiagent-framework");
|
|
8021
|
+
};
|
|
8022
|
+
fs_1.default.writeFileSync(path_1.default.join(projectDir, 'package.json'), JSON.stringify(packageJson, null, 2));
|
|
8023
|
+
// Generate index.js with Agent template
|
|
8024
|
+
const indexJsContent = `const { IBot } = require("@cloudbase/aiagent-framework");
|
|
8117
8025
|
const { BotRunner } = require("@cloudbase/aiagent-framework");
|
|
8118
8026
|
|
|
8119
8027
|
const ANSWER = "你好,我是一个智能体,但我只会说这一句话。";
|
|
@@ -8158,18 +8066,18 @@ exports.main = function (event, context) {
|
|
|
8158
8066
|
return BotRunner.run(event, context, new MyBot(context));
|
|
8159
8067
|
};
|
|
8160
8068
|
`;
|
|
8161
|
-
|
|
8162
|
-
|
|
8163
|
-
|
|
8164
|
-
|
|
8165
|
-
|
|
8166
|
-
|
|
8167
|
-
|
|
8168
|
-
|
|
8169
|
-
|
|
8170
|
-
|
|
8171
|
-
|
|
8172
|
-
|
|
8069
|
+
fs_1.default.writeFileSync(path_1.default.join(projectDir, 'index.js'), indexJsContent);
|
|
8070
|
+
// Generate cloudbaserc.json
|
|
8071
|
+
const currentEnvId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
8072
|
+
const cloudbasercContent = {
|
|
8073
|
+
envId: currentEnvId,
|
|
8074
|
+
cloudrun: {
|
|
8075
|
+
name: input.serverName
|
|
8076
|
+
}
|
|
8077
|
+
};
|
|
8078
|
+
fs_1.default.writeFileSync(path_1.default.join(projectDir, 'cloudbaserc.json'), JSON.stringify(cloudbasercContent, null, 2));
|
|
8079
|
+
// Generate README.md
|
|
8080
|
+
const readmeContent = `# ${agentName} Agent
|
|
8173
8081
|
|
|
8174
8082
|
这是一个基于函数型云托管的 AI 智能体。
|
|
8175
8083
|
|
|
@@ -8214,230 +8122,230 @@ for await (let x of res.textStream) {
|
|
|
8214
8122
|
</script>
|
|
8215
8123
|
\`\`\`
|
|
8216
8124
|
`;
|
|
8217
|
-
|
|
8218
|
-
|
|
8219
|
-
|
|
8220
|
-
|
|
8221
|
-
|
|
8222
|
-
|
|
8223
|
-
|
|
8224
|
-
|
|
8225
|
-
|
|
8226
|
-
|
|
8227
|
-
|
|
8228
|
-
|
|
8229
|
-
|
|
8230
|
-
|
|
8231
|
-
|
|
8232
|
-
|
|
8233
|
-
|
|
8234
|
-
|
|
8235
|
-
|
|
8236
|
-
|
|
8125
|
+
fs_1.default.writeFileSync(path_1.default.join(projectDir, 'README.md'), readmeContent);
|
|
8126
|
+
return {
|
|
8127
|
+
content: [
|
|
8128
|
+
{
|
|
8129
|
+
type: "text",
|
|
8130
|
+
text: JSON.stringify({
|
|
8131
|
+
success: true,
|
|
8132
|
+
data: {
|
|
8133
|
+
agentName: agentName,
|
|
8134
|
+
botId: botId,
|
|
8135
|
+
projectDir: projectDir,
|
|
8136
|
+
serverName: input.serverName,
|
|
8137
|
+
template: template,
|
|
8138
|
+
filesCreated: ['package.json', 'index.js', 'cloudbaserc.json', 'README.md']
|
|
8139
|
+
},
|
|
8140
|
+
message: `Successfully created Agent '${agentName}' with BotId '${botId}' in ${projectDir}`
|
|
8141
|
+
}, null, 2)
|
|
8142
|
+
}
|
|
8143
|
+
]
|
|
8144
|
+
};
|
|
8145
|
+
}
|
|
8146
|
+
case 'deploy': {
|
|
8147
|
+
if (!targetPath) {
|
|
8148
|
+
throw new Error("targetPath is required for deploy operation");
|
|
8237
8149
|
}
|
|
8238
|
-
|
|
8239
|
-
|
|
8240
|
-
|
|
8241
|
-
|
|
8242
|
-
|
|
8243
|
-
|
|
8244
|
-
|
|
8245
|
-
|
|
8150
|
+
// Determine service type - use input.serverType if provided, otherwise auto-detect
|
|
8151
|
+
let serverType;
|
|
8152
|
+
if (input.serverType) {
|
|
8153
|
+
serverType = input.serverType;
|
|
8154
|
+
}
|
|
8155
|
+
else {
|
|
8156
|
+
try {
|
|
8157
|
+
// First try to get existing service details
|
|
8158
|
+
const details = await cloudrunService.detail({ serverName: input.serverName });
|
|
8159
|
+
serverType = details.BaseInfo?.ServerType || 'container';
|
|
8246
8160
|
}
|
|
8247
|
-
|
|
8248
|
-
|
|
8249
|
-
|
|
8250
|
-
|
|
8251
|
-
serverType =
|
|
8161
|
+
catch (e) {
|
|
8162
|
+
// If service doesn't exist, determine by project structure
|
|
8163
|
+
const dockerfilePath = path_1.default.join(targetPath, 'Dockerfile');
|
|
8164
|
+
if (fs_1.default.existsSync(dockerfilePath)) {
|
|
8165
|
+
serverType = 'container';
|
|
8252
8166
|
}
|
|
8253
|
-
|
|
8254
|
-
//
|
|
8255
|
-
const
|
|
8256
|
-
if (fs_1.default.existsSync(
|
|
8257
|
-
|
|
8258
|
-
|
|
8259
|
-
|
|
8260
|
-
|
|
8261
|
-
|
|
8262
|
-
|
|
8263
|
-
try {
|
|
8264
|
-
const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf8'));
|
|
8265
|
-
// If it has function-specific dependencies or scripts, treat as function
|
|
8266
|
-
if (packageJson.dependencies?.['@cloudbase/aiagent-framework'] ||
|
|
8267
|
-
packageJson.scripts?.['dev']?.includes('cloudrun run')) {
|
|
8268
|
-
serverType = 'function';
|
|
8269
|
-
}
|
|
8270
|
-
else {
|
|
8271
|
-
serverType = 'container';
|
|
8272
|
-
}
|
|
8167
|
+
else {
|
|
8168
|
+
// Check if it's a Node.js function project (has package.json with specific structure)
|
|
8169
|
+
const packageJsonPath = path_1.default.join(targetPath, 'package.json');
|
|
8170
|
+
if (fs_1.default.existsSync(packageJsonPath)) {
|
|
8171
|
+
try {
|
|
8172
|
+
const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf8'));
|
|
8173
|
+
// If it has function-specific dependencies or scripts, treat as function
|
|
8174
|
+
if (packageJson.dependencies?.['@cloudbase/aiagent-framework'] ||
|
|
8175
|
+
packageJson.scripts?.['dev']?.includes('cloudrun run')) {
|
|
8176
|
+
serverType = 'function';
|
|
8273
8177
|
}
|
|
8274
|
-
|
|
8178
|
+
else {
|
|
8275
8179
|
serverType = 'container';
|
|
8276
8180
|
}
|
|
8277
8181
|
}
|
|
8278
|
-
|
|
8279
|
-
// No package.json, default to container
|
|
8182
|
+
catch (parseError) {
|
|
8280
8183
|
serverType = 'container';
|
|
8281
8184
|
}
|
|
8282
8185
|
}
|
|
8186
|
+
else {
|
|
8187
|
+
// No package.json, default to container
|
|
8188
|
+
serverType = 'container';
|
|
8189
|
+
}
|
|
8283
8190
|
}
|
|
8284
8191
|
}
|
|
8285
|
-
|
|
8286
|
-
|
|
8287
|
-
|
|
8288
|
-
|
|
8289
|
-
|
|
8290
|
-
|
|
8291
|
-
|
|
8292
|
-
|
|
8293
|
-
|
|
8294
|
-
|
|
8295
|
-
|
|
8296
|
-
|
|
8297
|
-
|
|
8298
|
-
|
|
8299
|
-
|
|
8300
|
-
|
|
8301
|
-
|
|
8302
|
-
|
|
8303
|
-
|
|
8304
|
-
};
|
|
8305
|
-
try {
|
|
8306
|
-
fs_1.default.writeFileSync(cloudbasercPath, JSON.stringify(cloudbasercContent, null, 2));
|
|
8307
|
-
}
|
|
8308
|
-
catch (error) {
|
|
8309
|
-
// Ignore cloudbaserc.json creation errors
|
|
8192
|
+
}
|
|
8193
|
+
const deployParams = {
|
|
8194
|
+
serverName: input.serverName,
|
|
8195
|
+
targetPath: targetPath,
|
|
8196
|
+
force: input.force,
|
|
8197
|
+
serverType: serverType,
|
|
8198
|
+
};
|
|
8199
|
+
// Add server configuration if provided
|
|
8200
|
+
if (input.serverConfig) {
|
|
8201
|
+
deployParams.serverConfig = input.serverConfig;
|
|
8202
|
+
}
|
|
8203
|
+
const result = await cloudrunService.deploy(deployParams);
|
|
8204
|
+
// Generate cloudbaserc.json configuration file
|
|
8205
|
+
const currentEnvId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
8206
|
+
const cloudbasercPath = path_1.default.join(targetPath, 'cloudbaserc.json');
|
|
8207
|
+
const cloudbasercContent = {
|
|
8208
|
+
envId: currentEnvId,
|
|
8209
|
+
cloudrun: {
|
|
8210
|
+
name: input.serverName
|
|
8310
8211
|
}
|
|
8311
|
-
|
|
8212
|
+
};
|
|
8213
|
+
try {
|
|
8214
|
+
fs_1.default.writeFileSync(cloudbasercPath, JSON.stringify(cloudbasercContent, null, 2));
|
|
8215
|
+
}
|
|
8216
|
+
catch (error) {
|
|
8217
|
+
// Ignore cloudbaserc.json creation errors
|
|
8218
|
+
}
|
|
8219
|
+
// Send deployment notification to CodeBuddy IDE
|
|
8220
|
+
try {
|
|
8221
|
+
// Query service details to get access URL
|
|
8222
|
+
let serviceUrl = "";
|
|
8312
8223
|
try {
|
|
8313
|
-
|
|
8314
|
-
|
|
8315
|
-
|
|
8316
|
-
|
|
8317
|
-
|
|
8318
|
-
//
|
|
8319
|
-
|
|
8320
|
-
if (details?.BaseInfo?.DefaultDomainName) {
|
|
8321
|
-
// DefaultDomainName is already a complete URL (e.g., https://...)
|
|
8322
|
-
serviceUrl = details.BaseInfo.DefaultDomainName;
|
|
8323
|
-
}
|
|
8324
|
-
else if (details?.BaseInfo?.CustomDomainName) {
|
|
8325
|
-
// CustomDomainName might be a domain without protocol
|
|
8326
|
-
const customDomain = details.BaseInfo.CustomDomainName;
|
|
8327
|
-
serviceUrl = customDomain.startsWith('http') ? customDomain : `https://${customDomain}`;
|
|
8328
|
-
}
|
|
8329
|
-
else if (details?.BaseInfo?.PublicDomain) {
|
|
8330
|
-
serviceUrl = `https://${details.BaseInfo.PublicDomain}`;
|
|
8331
|
-
}
|
|
8332
|
-
else if (details?.BaseInfo?.InternalDomain) {
|
|
8333
|
-
serviceUrl = `https://${details.BaseInfo.InternalDomain}`;
|
|
8334
|
-
}
|
|
8335
|
-
else if (details?.AccessInfo?.PublicDomain) {
|
|
8336
|
-
serviceUrl = `https://${details.AccessInfo.PublicDomain}`;
|
|
8337
|
-
}
|
|
8338
|
-
else {
|
|
8339
|
-
serviceUrl = ""; // URL not available
|
|
8340
|
-
}
|
|
8224
|
+
const serviceDetails = await cloudrunService.detail({ serverName: input.serverName });
|
|
8225
|
+
// Extract access URL from service details
|
|
8226
|
+
// Priority: DefaultDomainName > CustomDomainName > PublicDomain > InternalDomain
|
|
8227
|
+
const details = serviceDetails; // Use any to access dynamic properties
|
|
8228
|
+
if (details?.BaseInfo?.DefaultDomainName) {
|
|
8229
|
+
// DefaultDomainName is already a complete URL (e.g., https://...)
|
|
8230
|
+
serviceUrl = details.BaseInfo.DefaultDomainName;
|
|
8341
8231
|
}
|
|
8342
|
-
|
|
8343
|
-
//
|
|
8344
|
-
|
|
8232
|
+
else if (details?.BaseInfo?.CustomDomainName) {
|
|
8233
|
+
// CustomDomainName might be a domain without protocol
|
|
8234
|
+
const customDomain = details.BaseInfo.CustomDomainName;
|
|
8235
|
+
serviceUrl = customDomain.startsWith('http') ? customDomain : `https://${customDomain}`;
|
|
8236
|
+
}
|
|
8237
|
+
else if (details?.BaseInfo?.PublicDomain) {
|
|
8238
|
+
serviceUrl = `https://${details.BaseInfo.PublicDomain}`;
|
|
8239
|
+
}
|
|
8240
|
+
else if (details?.BaseInfo?.InternalDomain) {
|
|
8241
|
+
serviceUrl = `https://${details.BaseInfo.InternalDomain}`;
|
|
8242
|
+
}
|
|
8243
|
+
else if (details?.AccessInfo?.PublicDomain) {
|
|
8244
|
+
serviceUrl = `https://${details.AccessInfo.PublicDomain}`;
|
|
8245
|
+
}
|
|
8246
|
+
else {
|
|
8247
|
+
serviceUrl = ""; // URL not available
|
|
8345
8248
|
}
|
|
8346
|
-
// Extract project name from targetPath
|
|
8347
|
-
const projectName = path_1.default.basename(targetPath);
|
|
8348
|
-
// Build console URL
|
|
8349
|
-
const consoleUrl = `https://tcb.cloud.tencent.com/dev?envId=${currentEnvId}#/platform-run/service/detail?serverName=${input.serverName}&tabId=overview&envId=${currentEnvId}`;
|
|
8350
|
-
// Send notification
|
|
8351
|
-
await (0, notification_js_1.sendDeployNotification)(server, {
|
|
8352
|
-
deployType: 'cloudrun',
|
|
8353
|
-
url: serviceUrl,
|
|
8354
|
-
projectId: currentEnvId,
|
|
8355
|
-
projectName: projectName,
|
|
8356
|
-
consoleUrl: consoleUrl
|
|
8357
|
-
});
|
|
8358
8249
|
}
|
|
8359
|
-
catch (
|
|
8360
|
-
//
|
|
8361
|
-
|
|
8250
|
+
catch (detailErr) {
|
|
8251
|
+
// If query fails, continue with empty URL
|
|
8252
|
+
serviceUrl = "";
|
|
8362
8253
|
}
|
|
8363
|
-
|
|
8364
|
-
|
|
8365
|
-
|
|
8366
|
-
|
|
8367
|
-
|
|
8368
|
-
|
|
8369
|
-
|
|
8370
|
-
|
|
8371
|
-
|
|
8372
|
-
|
|
8373
|
-
|
|
8374
|
-
|
|
8375
|
-
},
|
|
8376
|
-
message: `Successfully deployed ${serverType} service '${input.serverName}' from ${targetPath}`
|
|
8377
|
-
}, null, 2)
|
|
8378
|
-
}
|
|
8379
|
-
]
|
|
8380
|
-
};
|
|
8254
|
+
// Extract project name from targetPath
|
|
8255
|
+
const projectName = path_1.default.basename(targetPath);
|
|
8256
|
+
// Build console URL
|
|
8257
|
+
const consoleUrl = `https://tcb.cloud.tencent.com/dev?envId=${currentEnvId}#/platform-run/service/detail?serverName=${input.serverName}&tabId=overview&envId=${currentEnvId}`;
|
|
8258
|
+
// Send notification
|
|
8259
|
+
await (0, notification_js_1.sendDeployNotification)(server, {
|
|
8260
|
+
deployType: 'cloudrun',
|
|
8261
|
+
url: serviceUrl,
|
|
8262
|
+
projectId: currentEnvId,
|
|
8263
|
+
projectName: projectName,
|
|
8264
|
+
consoleUrl: consoleUrl
|
|
8265
|
+
});
|
|
8381
8266
|
}
|
|
8382
|
-
|
|
8383
|
-
|
|
8384
|
-
|
|
8385
|
-
|
|
8386
|
-
|
|
8387
|
-
|
|
8388
|
-
|
|
8389
|
-
|
|
8390
|
-
|
|
8391
|
-
|
|
8392
|
-
|
|
8393
|
-
|
|
8394
|
-
|
|
8395
|
-
|
|
8396
|
-
|
|
8397
|
-
|
|
8398
|
-
|
|
8399
|
-
|
|
8400
|
-
|
|
8401
|
-
content: [
|
|
8402
|
-
{
|
|
8403
|
-
type: "text",
|
|
8404
|
-
text: JSON.stringify({
|
|
8405
|
-
success: true,
|
|
8406
|
-
data: {
|
|
8407
|
-
serviceName: input.serverName,
|
|
8408
|
-
status: 'running',
|
|
8409
|
-
pid: existingPid,
|
|
8410
|
-
cwd: targetPath
|
|
8411
|
-
},
|
|
8412
|
-
message: `Service '${input.serverName}' is already running locally (pid=${existingPid})`
|
|
8413
|
-
}, null, 2)
|
|
8414
|
-
}
|
|
8415
|
-
]
|
|
8416
|
-
};
|
|
8417
|
-
}
|
|
8418
|
-
catch (error) {
|
|
8419
|
-
// Process doesn't exist, remove from tracking
|
|
8420
|
-
runningProcesses.delete(input.serverName);
|
|
8267
|
+
catch (notifyErr) {
|
|
8268
|
+
// Notification failure should not affect deployment flow
|
|
8269
|
+
// Error is already logged in sendDeployNotification
|
|
8270
|
+
}
|
|
8271
|
+
return {
|
|
8272
|
+
content: [
|
|
8273
|
+
{
|
|
8274
|
+
type: "text",
|
|
8275
|
+
text: JSON.stringify({
|
|
8276
|
+
success: true,
|
|
8277
|
+
data: {
|
|
8278
|
+
serviceName: input.serverName,
|
|
8279
|
+
status: 'deployed',
|
|
8280
|
+
deployPath: targetPath,
|
|
8281
|
+
serverType: serverType,
|
|
8282
|
+
cloudbasercGenerated: true
|
|
8283
|
+
},
|
|
8284
|
+
message: `Successfully deployed ${serverType} service '${input.serverName}' from ${targetPath}`
|
|
8285
|
+
}, null, 2)
|
|
8421
8286
|
}
|
|
8287
|
+
]
|
|
8288
|
+
};
|
|
8289
|
+
}
|
|
8290
|
+
case 'run': {
|
|
8291
|
+
if (!targetPath) {
|
|
8292
|
+
throw new Error("targetPath is required for run operation");
|
|
8293
|
+
}
|
|
8294
|
+
// Do not support container services locally: basic heuristic - if Dockerfile exists, treat as container
|
|
8295
|
+
const dockerfilePath = path_1.default.join(targetPath, 'Dockerfile');
|
|
8296
|
+
if (fs_1.default.existsSync(dockerfilePath)) {
|
|
8297
|
+
throw new Error("Local run is only supported for function-type CloudRun services. Container services are not supported.");
|
|
8298
|
+
}
|
|
8299
|
+
// Check if this is an Agent project
|
|
8300
|
+
const isAgent = checkIfAgentProject(targetPath);
|
|
8301
|
+
const runMode = input.runOptions?.runMode || (isAgent ? 'agent' : 'normal');
|
|
8302
|
+
// Check if service is already running and verify process exists
|
|
8303
|
+
if (runningProcesses.has(input.serverName)) {
|
|
8304
|
+
const existingPid = runningProcesses.get(input.serverName);
|
|
8305
|
+
try {
|
|
8306
|
+
// Check if process actually exists
|
|
8307
|
+
process.kill(existingPid, 0);
|
|
8308
|
+
return {
|
|
8309
|
+
content: [
|
|
8310
|
+
{
|
|
8311
|
+
type: "text",
|
|
8312
|
+
text: JSON.stringify({
|
|
8313
|
+
success: true,
|
|
8314
|
+
data: {
|
|
8315
|
+
serviceName: input.serverName,
|
|
8316
|
+
status: 'running',
|
|
8317
|
+
pid: existingPid,
|
|
8318
|
+
cwd: targetPath
|
|
8319
|
+
},
|
|
8320
|
+
message: `Service '${input.serverName}' is already running locally (pid=${existingPid})`
|
|
8321
|
+
}, null, 2)
|
|
8322
|
+
}
|
|
8323
|
+
]
|
|
8324
|
+
};
|
|
8422
8325
|
}
|
|
8423
|
-
|
|
8424
|
-
|
|
8425
|
-
|
|
8426
|
-
|
|
8427
|
-
|
|
8428
|
-
|
|
8429
|
-
|
|
8430
|
-
|
|
8431
|
-
|
|
8432
|
-
|
|
8433
|
-
|
|
8434
|
-
|
|
8435
|
-
|
|
8436
|
-
|
|
8437
|
-
|
|
8438
|
-
|
|
8439
|
-
|
|
8440
|
-
|
|
8326
|
+
catch (error) {
|
|
8327
|
+
// Process doesn't exist, remove from tracking
|
|
8328
|
+
runningProcesses.delete(input.serverName);
|
|
8329
|
+
}
|
|
8330
|
+
}
|
|
8331
|
+
const runPort = input.runOptions?.port ?? 3000;
|
|
8332
|
+
const extraEnv = input.runOptions?.envParams ?? {};
|
|
8333
|
+
// Set environment variables for functions-framework
|
|
8334
|
+
const env = {
|
|
8335
|
+
...process.env,
|
|
8336
|
+
PORT: String(runPort),
|
|
8337
|
+
...extraEnv,
|
|
8338
|
+
// Add functions-framework specific environment variables
|
|
8339
|
+
ENABLE_CORS: 'true',
|
|
8340
|
+
ALLOWED_ORIGINS: '*'
|
|
8341
|
+
};
|
|
8342
|
+
// Choose execution method based on run mode
|
|
8343
|
+
let child;
|
|
8344
|
+
let command;
|
|
8345
|
+
if (runMode === 'agent') {
|
|
8346
|
+
// For Agent mode, use a different approach since functions-framework doesn't support Agent mode
|
|
8347
|
+
// We'll use a custom script that sets up the Agent environment
|
|
8348
|
+
command = `node -e "
|
|
8441
8349
|
const { runCLI } = require('@cloudbase/functions-framework');
|
|
8442
8350
|
process.env.PORT = '${runPort}';
|
|
8443
8351
|
process.env.ENABLE_CORS = 'true';
|
|
@@ -8446,16 +8354,16 @@ for await (let x of res.textStream) {
|
|
|
8446
8354
|
${Object.entries(extraEnv).map(([key, value]) => `process.env.${key} = '${value}';`).join('\n')}
|
|
8447
8355
|
runCLI();
|
|
8448
8356
|
"`;
|
|
8449
|
-
|
|
8450
|
-
|
|
8451
|
-
|
|
8452
|
-
|
|
8453
|
-
|
|
8454
|
-
|
|
8455
|
-
|
|
8456
|
-
|
|
8457
|
-
|
|
8458
|
-
|
|
8357
|
+
child = (0, child_process_1.spawn)(process.execPath, ['-e', command], {
|
|
8358
|
+
cwd: targetPath,
|
|
8359
|
+
env,
|
|
8360
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
8361
|
+
detached: true
|
|
8362
|
+
});
|
|
8363
|
+
}
|
|
8364
|
+
else {
|
|
8365
|
+
// Normal function mode
|
|
8366
|
+
command = `node -e "
|
|
8459
8367
|
const { runCLI } = require('@cloudbase/functions-framework');
|
|
8460
8368
|
process.env.PORT = '${runPort}';
|
|
8461
8369
|
process.env.ENABLE_CORS = 'true';
|
|
@@ -8463,182 +8371,167 @@ for await (let x of res.textStream) {
|
|
|
8463
8371
|
${Object.entries(extraEnv).map(([key, value]) => `process.env.${key} = '${value}';`).join('\n')}
|
|
8464
8372
|
runCLI();
|
|
8465
8373
|
"`;
|
|
8466
|
-
|
|
8467
|
-
|
|
8468
|
-
|
|
8469
|
-
|
|
8470
|
-
|
|
8471
|
-
});
|
|
8472
|
-
}
|
|
8473
|
-
// Handle process exit to clean up tracking
|
|
8474
|
-
child.on('exit', (code, signal) => {
|
|
8475
|
-
runningProcesses.delete(input.serverName);
|
|
8476
|
-
});
|
|
8477
|
-
child.on('error', (error) => {
|
|
8478
|
-
runningProcesses.delete(input.serverName);
|
|
8374
|
+
child = (0, child_process_1.spawn)(process.execPath, ['-e', command], {
|
|
8375
|
+
cwd: targetPath,
|
|
8376
|
+
env,
|
|
8377
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
8378
|
+
detached: true
|
|
8479
8379
|
});
|
|
8480
|
-
child.unref();
|
|
8481
|
-
if (typeof child.pid !== 'number') {
|
|
8482
|
-
throw new Error('Failed to start local process: PID is undefined.');
|
|
8483
|
-
}
|
|
8484
|
-
runningProcesses.set(input.serverName, child.pid);
|
|
8485
|
-
return {
|
|
8486
|
-
content: [
|
|
8487
|
-
{
|
|
8488
|
-
type: "text",
|
|
8489
|
-
text: JSON.stringify({
|
|
8490
|
-
success: true,
|
|
8491
|
-
data: {
|
|
8492
|
-
serviceName: input.serverName,
|
|
8493
|
-
status: 'running',
|
|
8494
|
-
pid: child.pid,
|
|
8495
|
-
port: runPort,
|
|
8496
|
-
runMode: runMode,
|
|
8497
|
-
isAgent: isAgent,
|
|
8498
|
-
command: command,
|
|
8499
|
-
cwd: targetPath
|
|
8500
|
-
},
|
|
8501
|
-
message: `Started local run for ${runMode} service '${input.serverName}' on port ${runPort} (pid=${child.pid})`
|
|
8502
|
-
}, null, 2)
|
|
8503
|
-
}
|
|
8504
|
-
]
|
|
8505
|
-
};
|
|
8506
8380
|
}
|
|
8507
|
-
|
|
8508
|
-
|
|
8509
|
-
|
|
8510
|
-
|
|
8511
|
-
|
|
8512
|
-
|
|
8513
|
-
|
|
8514
|
-
|
|
8515
|
-
|
|
8516
|
-
|
|
8517
|
-
|
|
8518
|
-
|
|
8519
|
-
|
|
8520
|
-
|
|
8521
|
-
|
|
8381
|
+
// Handle process exit to clean up tracking
|
|
8382
|
+
child.on('exit', (code, signal) => {
|
|
8383
|
+
runningProcesses.delete(input.serverName);
|
|
8384
|
+
});
|
|
8385
|
+
child.on('error', (error) => {
|
|
8386
|
+
runningProcesses.delete(input.serverName);
|
|
8387
|
+
});
|
|
8388
|
+
child.unref();
|
|
8389
|
+
if (typeof child.pid !== 'number') {
|
|
8390
|
+
throw new Error('Failed to start local process: PID is undefined.');
|
|
8391
|
+
}
|
|
8392
|
+
runningProcesses.set(input.serverName, child.pid);
|
|
8393
|
+
return {
|
|
8394
|
+
content: [
|
|
8395
|
+
{
|
|
8396
|
+
type: "text",
|
|
8397
|
+
text: JSON.stringify({
|
|
8398
|
+
success: true,
|
|
8399
|
+
data: {
|
|
8400
|
+
serviceName: input.serverName,
|
|
8401
|
+
status: 'running',
|
|
8402
|
+
pid: child.pid,
|
|
8403
|
+
port: runPort,
|
|
8404
|
+
runMode: runMode,
|
|
8405
|
+
isAgent: isAgent,
|
|
8406
|
+
command: command,
|
|
8407
|
+
cwd: targetPath
|
|
8408
|
+
},
|
|
8409
|
+
message: `Started local run for ${runMode} service '${input.serverName}' on port ${runPort} (pid=${child.pid})`
|
|
8410
|
+
}, null, 2)
|
|
8522
8411
|
}
|
|
8523
|
-
|
|
8524
|
-
|
|
8525
|
-
|
|
8526
|
-
|
|
8527
|
-
|
|
8528
|
-
|
|
8529
|
-
}
|
|
8530
|
-
return {
|
|
8531
|
-
content: [
|
|
8532
|
-
{
|
|
8533
|
-
type: "text",
|
|
8534
|
-
text: JSON.stringify({
|
|
8535
|
-
success: true,
|
|
8536
|
-
data: {
|
|
8537
|
-
serviceName: input.serverName,
|
|
8538
|
-
downloadPath: targetPath,
|
|
8539
|
-
filesCount: 0,
|
|
8540
|
-
cloudbasercGenerated: true
|
|
8541
|
-
},
|
|
8542
|
-
message: `Successfully downloaded service '${input.serverName}' to ${targetPath}`
|
|
8543
|
-
}, null, 2)
|
|
8544
|
-
}
|
|
8545
|
-
]
|
|
8546
|
-
};
|
|
8412
|
+
]
|
|
8413
|
+
};
|
|
8414
|
+
}
|
|
8415
|
+
case 'download': {
|
|
8416
|
+
if (!targetPath) {
|
|
8417
|
+
throw new Error("targetPath is required for download operation");
|
|
8547
8418
|
}
|
|
8548
|
-
|
|
8549
|
-
|
|
8550
|
-
|
|
8551
|
-
|
|
8552
|
-
|
|
8553
|
-
|
|
8554
|
-
|
|
8555
|
-
|
|
8556
|
-
|
|
8557
|
-
|
|
8558
|
-
|
|
8559
|
-
}
|
|
8560
|
-
]
|
|
8561
|
-
};
|
|
8419
|
+
const result = await cloudrunService.download({
|
|
8420
|
+
serverName: input.serverName,
|
|
8421
|
+
targetPath: targetPath,
|
|
8422
|
+
});
|
|
8423
|
+
// Generate cloudbaserc.json configuration file
|
|
8424
|
+
const currentEnvId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
8425
|
+
const cloudbasercPath = path_1.default.join(targetPath, 'cloudbaserc.json');
|
|
8426
|
+
const cloudbasercContent = {
|
|
8427
|
+
envId: currentEnvId,
|
|
8428
|
+
cloudrun: {
|
|
8429
|
+
name: input.serverName
|
|
8562
8430
|
}
|
|
8563
|
-
|
|
8564
|
-
|
|
8565
|
-
|
|
8566
|
-
return {
|
|
8567
|
-
content: [
|
|
8568
|
-
{
|
|
8569
|
-
type: "text",
|
|
8570
|
-
text: JSON.stringify({
|
|
8571
|
-
success: true,
|
|
8572
|
-
data: {
|
|
8573
|
-
serviceName: input.serverName,
|
|
8574
|
-
status: 'deleted'
|
|
8575
|
-
},
|
|
8576
|
-
message: `Successfully deleted service '${input.serverName}'`
|
|
8577
|
-
}, null, 2)
|
|
8578
|
-
}
|
|
8579
|
-
]
|
|
8580
|
-
};
|
|
8431
|
+
};
|
|
8432
|
+
try {
|
|
8433
|
+
fs_1.default.writeFileSync(cloudbasercPath, JSON.stringify(cloudbasercContent, null, 2));
|
|
8581
8434
|
}
|
|
8582
|
-
|
|
8583
|
-
|
|
8584
|
-
|
|
8585
|
-
|
|
8586
|
-
|
|
8587
|
-
|
|
8588
|
-
|
|
8589
|
-
|
|
8590
|
-
|
|
8591
|
-
|
|
8592
|
-
|
|
8593
|
-
|
|
8594
|
-
|
|
8595
|
-
|
|
8596
|
-
|
|
8597
|
-
|
|
8435
|
+
catch (error) {
|
|
8436
|
+
// Ignore cloudbaserc.json creation errors
|
|
8437
|
+
}
|
|
8438
|
+
return {
|
|
8439
|
+
content: [
|
|
8440
|
+
{
|
|
8441
|
+
type: "text",
|
|
8442
|
+
text: JSON.stringify({
|
|
8443
|
+
success: true,
|
|
8444
|
+
data: {
|
|
8445
|
+
serviceName: input.serverName,
|
|
8446
|
+
downloadPath: targetPath,
|
|
8447
|
+
filesCount: 0,
|
|
8448
|
+
cloudbasercGenerated: true
|
|
8449
|
+
},
|
|
8450
|
+
message: `Successfully downloaded service '${input.serverName}' to ${targetPath}`
|
|
8451
|
+
}, null, 2)
|
|
8598
8452
|
}
|
|
8599
|
-
|
|
8600
|
-
|
|
8601
|
-
|
|
8602
|
-
|
|
8603
|
-
|
|
8604
|
-
// Ignore cloudbaserc.json creation errors
|
|
8605
|
-
}
|
|
8453
|
+
]
|
|
8454
|
+
};
|
|
8455
|
+
}
|
|
8456
|
+
case 'delete': {
|
|
8457
|
+
if (!input.force) {
|
|
8606
8458
|
return {
|
|
8607
8459
|
content: [
|
|
8608
8460
|
{
|
|
8609
8461
|
type: "text",
|
|
8610
8462
|
text: JSON.stringify({
|
|
8611
|
-
success:
|
|
8612
|
-
|
|
8613
|
-
|
|
8614
|
-
template: input.template,
|
|
8615
|
-
initPath: targetPath,
|
|
8616
|
-
projectDir: result.projectDir || path_1.default.join(targetPath, input.serverName),
|
|
8617
|
-
cloudbasercGenerated: true
|
|
8618
|
-
},
|
|
8619
|
-
message: `Successfully initialized service '${input.serverName}' with template '${input.template}' at ${targetPath}`
|
|
8463
|
+
success: false,
|
|
8464
|
+
error: "Delete operation requires confirmation",
|
|
8465
|
+
message: "Please set force: true to confirm deletion of the service. This action cannot be undone."
|
|
8620
8466
|
}, null, 2)
|
|
8621
8467
|
}
|
|
8622
8468
|
]
|
|
8623
8469
|
};
|
|
8624
8470
|
}
|
|
8625
|
-
|
|
8626
|
-
|
|
8471
|
+
const result = await cloudrunService.delete({
|
|
8472
|
+
serverName: input.serverName,
|
|
8473
|
+
});
|
|
8474
|
+
return {
|
|
8475
|
+
content: [
|
|
8476
|
+
{
|
|
8477
|
+
type: "text",
|
|
8478
|
+
text: JSON.stringify({
|
|
8479
|
+
success: true,
|
|
8480
|
+
data: {
|
|
8481
|
+
serviceName: input.serverName,
|
|
8482
|
+
status: 'deleted'
|
|
8483
|
+
},
|
|
8484
|
+
message: `Successfully deleted service '${input.serverName}'`
|
|
8485
|
+
}, null, 2)
|
|
8486
|
+
}
|
|
8487
|
+
]
|
|
8488
|
+
};
|
|
8627
8489
|
}
|
|
8628
|
-
|
|
8629
|
-
|
|
8630
|
-
|
|
8631
|
-
|
|
8632
|
-
|
|
8633
|
-
|
|
8634
|
-
|
|
8635
|
-
|
|
8636
|
-
|
|
8637
|
-
|
|
8638
|
-
|
|
8490
|
+
case 'init': {
|
|
8491
|
+
if (!targetPath) {
|
|
8492
|
+
throw new Error("targetPath is required for init operation");
|
|
8493
|
+
}
|
|
8494
|
+
const result = await cloudrunService.init({
|
|
8495
|
+
serverName: input.serverName,
|
|
8496
|
+
targetPath: targetPath,
|
|
8497
|
+
template: input.template,
|
|
8498
|
+
});
|
|
8499
|
+
// Generate cloudbaserc.json configuration file
|
|
8500
|
+
const currentEnvId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
8501
|
+
const cloudbasercPath = path_1.default.join(targetPath, input.serverName, 'cloudbaserc.json');
|
|
8502
|
+
const cloudbasercContent = {
|
|
8503
|
+
envId: currentEnvId,
|
|
8504
|
+
cloudrun: {
|
|
8505
|
+
name: input.serverName
|
|
8639
8506
|
}
|
|
8640
|
-
|
|
8641
|
-
|
|
8507
|
+
};
|
|
8508
|
+
try {
|
|
8509
|
+
fs_1.default.writeFileSync(cloudbasercPath, JSON.stringify(cloudbasercContent, null, 2));
|
|
8510
|
+
}
|
|
8511
|
+
catch (error) {
|
|
8512
|
+
// Ignore cloudbaserc.json creation errors
|
|
8513
|
+
}
|
|
8514
|
+
return {
|
|
8515
|
+
content: [
|
|
8516
|
+
{
|
|
8517
|
+
type: "text",
|
|
8518
|
+
text: JSON.stringify({
|
|
8519
|
+
success: true,
|
|
8520
|
+
data: {
|
|
8521
|
+
serviceName: input.serverName,
|
|
8522
|
+
template: input.template,
|
|
8523
|
+
initPath: targetPath,
|
|
8524
|
+
projectDir: result.projectDir || path_1.default.join(targetPath, input.serverName),
|
|
8525
|
+
cloudbasercGenerated: true
|
|
8526
|
+
},
|
|
8527
|
+
message: `Successfully initialized service '${input.serverName}' with template '${input.template}' at ${targetPath}`
|
|
8528
|
+
}, null, 2)
|
|
8529
|
+
}
|
|
8530
|
+
]
|
|
8531
|
+
};
|
|
8532
|
+
}
|
|
8533
|
+
default:
|
|
8534
|
+
throw new Error(`Unsupported action: ${input.action}`);
|
|
8642
8535
|
}
|
|
8643
8536
|
});
|
|
8644
8537
|
}
|
|
@@ -8713,7 +8606,7 @@ class TelemetryReporter {
|
|
|
8713
8606
|
const nodeVersion = process.version; // Node.js版本
|
|
8714
8607
|
const arch = os_1.default.arch(); // 系统架构
|
|
8715
8608
|
// 从构建时注入的版本号获取MCP版本信息
|
|
8716
|
-
const mcpVersion = process.env.npm_package_version || "2.
|
|
8609
|
+
const mcpVersion = process.env.npm_package_version || "2.10.0" || 0;
|
|
8717
8610
|
return {
|
|
8718
8611
|
userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
|
|
8719
8612
|
deviceId: this.deviceId,
|
|
@@ -9083,12 +8976,12 @@ function registerFunctionTools(server) {
|
|
|
9083
8976
|
// getFunctionList - 获取云函数列表或详情(推荐)
|
|
9084
8977
|
server.registerTool?.("getFunctionList", {
|
|
9085
8978
|
title: "查询云函数列表或详情",
|
|
9086
|
-
description: "
|
|
8979
|
+
description: "获取云函数列表或单个函数详情。通过 action 参数区分操作类型:list=获取函数列表(默认,无需额外参数),detail=获取函数详情(需要提供 name 参数指定函数名称)",
|
|
9087
8980
|
inputSchema: {
|
|
9088
|
-
action: zod_1.z.enum(["list", "detail"]).optional().describe("操作类型:list
|
|
8981
|
+
action: zod_1.z.enum(["list", "detail"]).optional().describe("操作类型:list=获取函数列表(默认,无需额外参数),detail=获取函数详情(需要提供 name 参数)"),
|
|
9089
8982
|
limit: zod_1.z.number().optional().describe("范围(list 操作时使用)"),
|
|
9090
8983
|
offset: zod_1.z.number().optional().describe("偏移(list 操作时使用)"),
|
|
9091
|
-
name: zod_1.z.string().optional().describe("
|
|
8984
|
+
name: zod_1.z.string().optional().describe("要查询的函数名称。当 action='detail' 时,此参数为必填项,必须提供已存在的函数名称。可通过 action='list' 操作获取可用的函数名称列表"),
|
|
9092
8985
|
codeSecret: zod_1.z.string().optional().describe("代码保护密钥(detail 操作时使用)")
|
|
9093
8986
|
},
|
|
9094
8987
|
annotations: {
|
|
@@ -9328,17 +9221,30 @@ function registerFunctionTools(server) {
|
|
|
9328
9221
|
}
|
|
9329
9222
|
}, async ({ name, params }) => {
|
|
9330
9223
|
// 使用闭包中的 cloudBaseOptions
|
|
9331
|
-
|
|
9332
|
-
|
|
9333
|
-
|
|
9334
|
-
|
|
9335
|
-
|
|
9336
|
-
|
|
9337
|
-
|
|
9338
|
-
|
|
9339
|
-
|
|
9340
|
-
|
|
9341
|
-
|
|
9224
|
+
try {
|
|
9225
|
+
const cloudbase = await getManager();
|
|
9226
|
+
const result = await cloudbase.functions.invokeFunction(name, params);
|
|
9227
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
9228
|
+
return {
|
|
9229
|
+
content: [
|
|
9230
|
+
{
|
|
9231
|
+
type: "text",
|
|
9232
|
+
text: JSON.stringify(result, null, 2)
|
|
9233
|
+
}
|
|
9234
|
+
]
|
|
9235
|
+
};
|
|
9236
|
+
}
|
|
9237
|
+
catch (error) {
|
|
9238
|
+
const errorMessage = (error instanceof Error ? error.message : String(error));
|
|
9239
|
+
if (errorMessage.includes("Function not found") ||
|
|
9240
|
+
errorMessage.includes("函数不存在")) {
|
|
9241
|
+
throw new Error(`${errorMessage}\n\n` +
|
|
9242
|
+
`Tip: "invokeFunction" can only call deployed cloud functions. ` +
|
|
9243
|
+
`For database operations (such as creating collections), ` +
|
|
9244
|
+
`please use the appropriate database tools instead.`);
|
|
9245
|
+
}
|
|
9246
|
+
throw error;
|
|
9247
|
+
}
|
|
9342
9248
|
});
|
|
9343
9249
|
// getFunctionLogs - 获取云函数日志(新版,参数直接展开)
|
|
9344
9250
|
server.registerTool?.("getFunctionLogs", {
|
|
@@ -10133,15 +10039,14 @@ function registerSetupTools(server) {
|
|
|
10133
10039
|
title: "下载项目模板",
|
|
10134
10040
|
description: `自动下载并部署CloudBase项目模板。⚠️ **MANDATORY FOR NEW PROJECTS** ⚠️
|
|
10135
10041
|
|
|
10136
|
-
**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.
|
|
10042
|
+
**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.10.0" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
|
|
10137
10043
|
inputSchema: {
|
|
10138
10044
|
template: zod_1.z
|
|
10139
10045
|
.enum(["react", "vue", "miniprogram", "uniapp", "rules"])
|
|
10140
10046
|
.describe("要下载的模板类型"),
|
|
10141
10047
|
ide: zod_1.z
|
|
10142
10048
|
.enum(IDE_TYPES)
|
|
10143
|
-
.
|
|
10144
|
-
.describe("指定要下载的IDE类型。如果未指定,会根据 INTEGRATION_IDE 环境变量自动选择对应的IDE配置;如果环境变量也未设置,则必须传入此参数"),
|
|
10049
|
+
.describe("指定要下载的IDE类型。"),
|
|
10145
10050
|
overwrite: zod_1.z
|
|
10146
10051
|
.boolean()
|
|
10147
10052
|
.optional()
|
|
@@ -10156,7 +10061,7 @@ function registerSetupTools(server) {
|
|
|
10156
10061
|
},
|
|
10157
10062
|
}, async ({ template, ide, overwrite = false, }) => {
|
|
10158
10063
|
try {
|
|
10159
|
-
const ideResolution = resolveDownloadTemplateIDE(ide,
|
|
10064
|
+
const ideResolution = resolveDownloadTemplateIDE(ide, undefined);
|
|
10160
10065
|
if (!ideResolution.ok) {
|
|
10161
10066
|
const supportedIDEs = ideResolution.supportedIDEs.join(", ");
|
|
10162
10067
|
if (ideResolution.reason === "unmapped_integration_ide") {
|
|
@@ -11152,7 +11057,7 @@ async function checkAndInitTcbService(cloudbase, context) {
|
|
|
11152
11057
|
uin: newContext.uin,
|
|
11153
11058
|
tcbServiceChecked: newContext.tcbServiceChecked
|
|
11154
11059
|
});
|
|
11155
|
-
const checkResult = await cloudbase.commonService("tcb").call({
|
|
11060
|
+
const checkResult = await cloudbase.commonService("tcb", "2018-06-08").call({
|
|
11156
11061
|
Action: "CheckTcbService",
|
|
11157
11062
|
Param: {}
|
|
11158
11063
|
});
|
|
@@ -11173,7 +11078,7 @@ async function checkAndInitTcbService(cloudbase, context) {
|
|
|
11173
11078
|
(0, logger_js_1.debug)('[env-setup] TCB service not initialized, attempting to initialize...');
|
|
11174
11079
|
(0, logger_js_1.debug)('[env-setup] InitTcb params:', { Source: "qcloud", Channel: "mcp" });
|
|
11175
11080
|
try {
|
|
11176
|
-
const initResult = await cloudbase.commonService("tcb").call({
|
|
11081
|
+
const initResult = await cloudbase.commonService("tcb", "2018-06-08").call({
|
|
11177
11082
|
Action: "InitTcb",
|
|
11178
11083
|
Param: {
|
|
11179
11084
|
Source: "qcloud",
|
|
@@ -11261,7 +11166,7 @@ async function checkAndCreateFreeEnv(cloudbase, context) {
|
|
|
11261
11166
|
(0, logger_js_1.debug)('[env-setup] DescribeUserPromotionalActivity params:', {
|
|
11262
11167
|
Names: ["NewUser", "ReturningUser", "BaasFree"]
|
|
11263
11168
|
});
|
|
11264
|
-
const activityResult = await cloudbase.commonService("tcb").call({
|
|
11169
|
+
const activityResult = await cloudbase.commonService("tcb", "2018-06-08").call({
|
|
11265
11170
|
Action: "DescribeUserPromotionalActivity",
|
|
11266
11171
|
Param: {
|
|
11267
11172
|
Names: ["NewUser", "ReturningUser", "BaasFree"]
|
|
@@ -11312,7 +11217,7 @@ async function checkAndCreateFreeEnv(cloudbase, context) {
|
|
|
11312
11217
|
Source: "qcloud"
|
|
11313
11218
|
};
|
|
11314
11219
|
(0, logger_js_1.debug)('[env-setup] CreateFreeEnvByActivity params:', createParams);
|
|
11315
|
-
const createResult = await cloudbase.commonService("tcb").call({
|
|
11220
|
+
const createResult = await cloudbase.commonService("tcb", "2018-06-08").call({
|
|
11316
11221
|
Action: "CreateFreeEnvByActivity",
|
|
11317
11222
|
Param: createParams
|
|
11318
11223
|
});
|
|
@@ -11457,7 +11362,9 @@ async function checkAndCreateFreeEnv(cloudbase, context) {
|
|
|
11457
11362
|
*/
|
|
11458
11363
|
async function getUinForTelemetry() {
|
|
11459
11364
|
try {
|
|
11460
|
-
|
|
11365
|
+
// Get region from environment variable for auth URL
|
|
11366
|
+
const region = process.env.TCB_REGION;
|
|
11367
|
+
const loginState = await (0, auth_js_1.getLoginState)({ region });
|
|
11461
11368
|
// Try to extract UIN from loginState
|
|
11462
11369
|
// Note: actual field name may vary, adjust based on actual response
|
|
11463
11370
|
return loginState.uin || undefined;
|
|
@@ -12023,6 +11930,7 @@ exports.getLoginState = getLoginState;
|
|
|
12023
11930
|
exports.logout = logout;
|
|
12024
11931
|
const toolbox_1 = __webpack_require__(2090);
|
|
12025
11932
|
const logger_js_1 = __webpack_require__(3039);
|
|
11933
|
+
const tencet_cloud_js_1 = __webpack_require__(5018);
|
|
12026
11934
|
const auth = toolbox_1.AuthSupevisor.getInstance({});
|
|
12027
11935
|
async function getLoginState(options) {
|
|
12028
11936
|
const { TENCENTCLOUD_SECRETID, TENCENTCLOUD_SECRETKEY, TENCENTCLOUD_SESSIONTOKEN, } = process.env;
|
|
@@ -12040,9 +11948,10 @@ async function getLoginState(options) {
|
|
|
12040
11948
|
}
|
|
12041
11949
|
const loginState = await auth.getLoginState();
|
|
12042
11950
|
if (!loginState) {
|
|
12043
|
-
await auth.loginByWebAuth(options?.fromCloudBaseLoginPage
|
|
11951
|
+
await auth.loginByWebAuth((options?.fromCloudBaseLoginPage && !(0, tencet_cloud_js_1.isInternationalRegion)(options?.region))
|
|
12044
11952
|
? {
|
|
12045
11953
|
getAuthUrl: (url) => {
|
|
11954
|
+
// 国际站
|
|
12046
11955
|
const separator = url.includes('?') ? '&' : '?';
|
|
12047
11956
|
const urlWithParam = `${url}${separator}allowNoEnv=true`;
|
|
12048
11957
|
return `https://tcb.cloud.tencent.com/login?_redirect_uri=${encodeURIComponent(urlWithParam)}`;
|
|
@@ -12050,6 +11959,9 @@ async function getLoginState(options) {
|
|
|
12050
11959
|
}
|
|
12051
11960
|
: {
|
|
12052
11961
|
getAuthUrl: (url) => {
|
|
11962
|
+
if ((0, tencet_cloud_js_1.isInternationalRegion)(options?.region)) {
|
|
11963
|
+
url = url.replace('cloud.tencent.com', 'tencentcloud.com');
|
|
11964
|
+
}
|
|
12053
11965
|
const separator = url.includes('?') ? '&' : '?';
|
|
12054
11966
|
return `${url}${separator}allowNoEnv=true`;
|
|
12055
11967
|
},
|
|
@@ -12097,7 +12009,7 @@ function renderHeader(accountInfo, ide) {
|
|
|
12097
12009
|
<img class="logo" src="https://7463-tcb-advanced-a656fc-1257967285.tcb.qcloud.la/mcp/cloudbase-logo.svg" alt="CloudBase Logo" />
|
|
12098
12010
|
<span class="title">CloudBase</span>
|
|
12099
12011
|
</div>
|
|
12100
|
-
${hasAccount ? `
|
|
12012
|
+
${(hasAccount && accountInfo.region !== 'ap-singapore') ? /** 国际站不支持切 */ `
|
|
12101
12013
|
<div class="header-right">
|
|
12102
12014
|
<div class="account-section">
|
|
12103
12015
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
@@ -12105,6 +12017,7 @@ function renderHeader(accountInfo, ide) {
|
|
|
12105
12017
|
<circle cx="12" cy="7" r="4"/>
|
|
12106
12018
|
</svg>
|
|
12107
12019
|
<span class="account-uin">${accountInfo.uin}</span>
|
|
12020
|
+
${accountInfo.region ? `<span class="account-region">${accountInfo.region}</span>` : ''}
|
|
12108
12021
|
${!isCodeBuddy ? `
|
|
12109
12022
|
<button class="btn-switch" onclick="switchAccount()" title="切换账号">
|
|
12110
12023
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
@@ -12393,90 +12306,70 @@ function registerSecurityRuleTools(server) {
|
|
|
12393
12306
|
},
|
|
12394
12307
|
}, async ({ resourceType, resourceId }) => {
|
|
12395
12308
|
const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
12396
|
-
|
|
12397
|
-
|
|
12398
|
-
|
|
12399
|
-
|
|
12400
|
-
|
|
12401
|
-
|
|
12402
|
-
|
|
12403
|
-
|
|
12404
|
-
|
|
12405
|
-
|
|
12406
|
-
|
|
12407
|
-
|
|
12408
|
-
|
|
12409
|
-
|
|
12410
|
-
|
|
12411
|
-
|
|
12412
|
-
|
|
12413
|
-
|
|
12414
|
-
|
|
12415
|
-
|
|
12416
|
-
|
|
12417
|
-
|
|
12418
|
-
|
|
12419
|
-
|
|
12420
|
-
|
|
12421
|
-
|
|
12422
|
-
|
|
12423
|
-
|
|
12424
|
-
|
|
12425
|
-
|
|
12426
|
-
|
|
12427
|
-
|
|
12428
|
-
|
|
12429
|
-
|
|
12430
|
-
|
|
12431
|
-
|
|
12432
|
-
|
|
12433
|
-
|
|
12434
|
-
|
|
12435
|
-
|
|
12436
|
-
|
|
12437
|
-
|
|
12438
|
-
|
|
12439
|
-
|
|
12440
|
-
|
|
12441
|
-
|
|
12442
|
-
ResourceId: `${instanceId}#${schema}#${tableName}`,
|
|
12443
|
-
RoleIdentityList: ["allUser"],
|
|
12444
|
-
},
|
|
12445
|
-
});
|
|
12446
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12447
|
-
}
|
|
12448
|
-
else {
|
|
12449
|
-
throw new Error(`不支持的资源类型: ${resourceType}`);
|
|
12450
|
-
}
|
|
12451
|
-
return {
|
|
12452
|
-
content: [
|
|
12453
|
-
{
|
|
12454
|
-
type: "text",
|
|
12455
|
-
text: JSON.stringify({
|
|
12456
|
-
success: true,
|
|
12457
|
-
aclTag: result.AclTag,
|
|
12458
|
-
rule: result.Rule ?? null,
|
|
12459
|
-
raw: result,
|
|
12460
|
-
message: "安全规则读取成功",
|
|
12461
|
-
}, null, 2),
|
|
12462
|
-
},
|
|
12463
|
-
],
|
|
12464
|
-
};
|
|
12309
|
+
const cloudbase = await getManager();
|
|
12310
|
+
let result;
|
|
12311
|
+
if (resourceType === "noSqlDatabase") {
|
|
12312
|
+
result = await cloudbase.commonService().call({
|
|
12313
|
+
Action: "DescribeSafeRule",
|
|
12314
|
+
Param: {
|
|
12315
|
+
CollectionName: resourceId,
|
|
12316
|
+
EnvId: envId,
|
|
12317
|
+
},
|
|
12318
|
+
});
|
|
12319
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12320
|
+
}
|
|
12321
|
+
else if (resourceType === "function") {
|
|
12322
|
+
result = await cloudbase.commonService().call({
|
|
12323
|
+
Action: "DescribeSecurityRule",
|
|
12324
|
+
Param: {
|
|
12325
|
+
ResourceType: "FUNCTION",
|
|
12326
|
+
EnvId: envId,
|
|
12327
|
+
},
|
|
12328
|
+
});
|
|
12329
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12330
|
+
}
|
|
12331
|
+
else if (resourceType === "storage") {
|
|
12332
|
+
result = await cloudbase.commonService().call({
|
|
12333
|
+
Action: "DescribeStorageSafeRule",
|
|
12334
|
+
Param: {
|
|
12335
|
+
Bucket: resourceId,
|
|
12336
|
+
EnvId: envId,
|
|
12337
|
+
},
|
|
12338
|
+
});
|
|
12339
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12340
|
+
}
|
|
12341
|
+
else if (resourceType === "sqlDatabase") {
|
|
12342
|
+
const instanceId = "default";
|
|
12343
|
+
const schema = envId;
|
|
12344
|
+
const tableName = resourceId;
|
|
12345
|
+
result = await cloudbase.commonService("lowcode").call({
|
|
12346
|
+
Action: "DescribeDataSourceBasicPolicy",
|
|
12347
|
+
Param: {
|
|
12348
|
+
EnvId: envId,
|
|
12349
|
+
ResourceType: "table",
|
|
12350
|
+
ResourceId: `${instanceId}#${schema}#${tableName}`,
|
|
12351
|
+
RoleIdentityList: ["allUser"],
|
|
12352
|
+
},
|
|
12353
|
+
});
|
|
12354
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12465
12355
|
}
|
|
12466
|
-
|
|
12467
|
-
|
|
12468
|
-
content: [
|
|
12469
|
-
{
|
|
12470
|
-
type: "text",
|
|
12471
|
-
text: JSON.stringify({
|
|
12472
|
-
success: false,
|
|
12473
|
-
error: error.message,
|
|
12474
|
-
message: "安全规则读取失败",
|
|
12475
|
-
}, null, 2),
|
|
12476
|
-
},
|
|
12477
|
-
],
|
|
12478
|
-
};
|
|
12356
|
+
else {
|
|
12357
|
+
throw new Error(`不支持的资源类型: ${resourceType}`);
|
|
12479
12358
|
}
|
|
12359
|
+
return {
|
|
12360
|
+
content: [
|
|
12361
|
+
{
|
|
12362
|
+
type: "text",
|
|
12363
|
+
text: JSON.stringify({
|
|
12364
|
+
success: true,
|
|
12365
|
+
aclTag: result.AclTag,
|
|
12366
|
+
rule: result.Rule ?? null,
|
|
12367
|
+
raw: result,
|
|
12368
|
+
message: "安全规则读取成功",
|
|
12369
|
+
}, null, 2),
|
|
12370
|
+
},
|
|
12371
|
+
],
|
|
12372
|
+
};
|
|
12480
12373
|
});
|
|
12481
12374
|
// 写入安全规则 Tool
|
|
12482
12375
|
server.registerTool?.(exports.WRITE_SECURITY_RULE, {
|
|
@@ -12503,154 +12396,138 @@ function registerSecurityRuleTools(server) {
|
|
|
12503
12396
|
category: "security-rule",
|
|
12504
12397
|
},
|
|
12505
12398
|
}, async ({ resourceType, resourceId, aclTag, rule }) => {
|
|
12506
|
-
|
|
12507
|
-
|
|
12508
|
-
|
|
12509
|
-
|
|
12510
|
-
if (
|
|
12511
|
-
if (aclTag === "CUSTOM") {
|
|
12512
|
-
if (!rule)
|
|
12513
|
-
throw new Error("noSQL 数据库自定义安全规则(CUSTOM)必须提供 rule 字段");
|
|
12514
|
-
result = await cloudbase.commonService().call({
|
|
12515
|
-
Action: "ModifySafeRule",
|
|
12516
|
-
Param: {
|
|
12517
|
-
CollectionName: resourceId,
|
|
12518
|
-
EnvId: envId,
|
|
12519
|
-
AclTag: aclTag,
|
|
12520
|
-
Rule: rule,
|
|
12521
|
-
},
|
|
12522
|
-
});
|
|
12523
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12524
|
-
}
|
|
12525
|
-
else {
|
|
12526
|
-
result = await cloudbase.commonService().call({
|
|
12527
|
-
Action: "ModifyDatabaseACL",
|
|
12528
|
-
Param: {
|
|
12529
|
-
CollectionName: resourceId,
|
|
12530
|
-
EnvId: envId,
|
|
12531
|
-
AclTag: aclTag,
|
|
12532
|
-
},
|
|
12533
|
-
});
|
|
12534
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12535
|
-
}
|
|
12536
|
-
}
|
|
12537
|
-
else if (resourceType === "function") {
|
|
12538
|
-
if (aclTag !== "CUSTOM")
|
|
12539
|
-
throw new Error("云函数安全规则仅支持 CUSTOM 权限类别");
|
|
12399
|
+
const cloudbase = await getManager();
|
|
12400
|
+
const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
12401
|
+
let result;
|
|
12402
|
+
if (resourceType === "noSqlDatabase") {
|
|
12403
|
+
if (aclTag === "CUSTOM") {
|
|
12540
12404
|
if (!rule)
|
|
12541
|
-
throw new Error("
|
|
12405
|
+
throw new Error("noSQL 数据库自定义安全规则(CUSTOM)必须提供 rule 字段");
|
|
12542
12406
|
result = await cloudbase.commonService().call({
|
|
12543
|
-
Action: "
|
|
12407
|
+
Action: "ModifySafeRule",
|
|
12544
12408
|
Param: {
|
|
12545
|
-
|
|
12409
|
+
CollectionName: resourceId,
|
|
12546
12410
|
EnvId: envId,
|
|
12547
|
-
|
|
12411
|
+
AclTag: aclTag,
|
|
12548
12412
|
Rule: rule,
|
|
12549
12413
|
},
|
|
12550
12414
|
});
|
|
12551
12415
|
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12552
12416
|
}
|
|
12553
|
-
else
|
|
12554
|
-
|
|
12555
|
-
|
|
12556
|
-
|
|
12557
|
-
|
|
12558
|
-
|
|
12559
|
-
|
|
12560
|
-
|
|
12561
|
-
|
|
12562
|
-
|
|
12563
|
-
Rule: rule,
|
|
12564
|
-
},
|
|
12565
|
-
});
|
|
12566
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12567
|
-
}
|
|
12568
|
-
else {
|
|
12569
|
-
result = await cloudbase.commonService().call({
|
|
12570
|
-
Action: "ModifyStorageSafeRule",
|
|
12571
|
-
Param: {
|
|
12572
|
-
Bucket: resourceId,
|
|
12573
|
-
EnvId: envId,
|
|
12574
|
-
AclTag: aclTag,
|
|
12575
|
-
},
|
|
12576
|
-
});
|
|
12577
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12578
|
-
}
|
|
12417
|
+
else {
|
|
12418
|
+
result = await cloudbase.commonService().call({
|
|
12419
|
+
Action: "ModifyDatabaseACL",
|
|
12420
|
+
Param: {
|
|
12421
|
+
CollectionName: resourceId,
|
|
12422
|
+
EnvId: envId,
|
|
12423
|
+
AclTag: aclTag,
|
|
12424
|
+
},
|
|
12425
|
+
});
|
|
12426
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12579
12427
|
}
|
|
12580
|
-
|
|
12581
|
-
|
|
12582
|
-
|
|
12583
|
-
|
|
12584
|
-
|
|
12585
|
-
|
|
12586
|
-
|
|
12587
|
-
|
|
12588
|
-
|
|
12589
|
-
|
|
12590
|
-
|
|
12591
|
-
"
|
|
12592
|
-
|
|
12593
|
-
|
|
12594
|
-
|
|
12595
|
-
|
|
12596
|
-
|
|
12597
|
-
|
|
12598
|
-
|
|
12599
|
-
|
|
12600
|
-
|
|
12601
|
-
|
|
12602
|
-
|
|
12603
|
-
result = await cloudbase.commonService("lowcode").call({
|
|
12604
|
-
Action: "BatchCreateResourcePolicy",
|
|
12428
|
+
}
|
|
12429
|
+
else if (resourceType === "function") {
|
|
12430
|
+
if (aclTag !== "CUSTOM")
|
|
12431
|
+
throw new Error("云函数安全规则仅支持 CUSTOM 权限类别");
|
|
12432
|
+
if (!rule)
|
|
12433
|
+
throw new Error("云函数自定义安全规则(CUSTOM)必须提供 rule 字段");
|
|
12434
|
+
result = await cloudbase.commonService().call({
|
|
12435
|
+
Action: "ModifySecurityRule",
|
|
12436
|
+
Param: {
|
|
12437
|
+
AclTag: aclTag,
|
|
12438
|
+
EnvId: envId,
|
|
12439
|
+
ResourceType: "FUNCTION",
|
|
12440
|
+
Rule: rule,
|
|
12441
|
+
},
|
|
12442
|
+
});
|
|
12443
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12444
|
+
}
|
|
12445
|
+
else if (resourceType === "storage") {
|
|
12446
|
+
if (aclTag === "CUSTOM") {
|
|
12447
|
+
if (!rule)
|
|
12448
|
+
throw new Error("存储自定义安全规则(CUSTOM)必须提供 rule 字段");
|
|
12449
|
+
result = await cloudbase.commonService().call({
|
|
12450
|
+
Action: "ModifyStorageSafeRule",
|
|
12605
12451
|
Param: {
|
|
12452
|
+
Bucket: resourceId,
|
|
12606
12453
|
EnvId: envId,
|
|
12607
|
-
|
|
12454
|
+
AclTag: aclTag,
|
|
12455
|
+
Rule: rule,
|
|
12608
12456
|
},
|
|
12609
12457
|
});
|
|
12610
12458
|
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12611
|
-
function getRowPermission(policy) {
|
|
12612
|
-
return {
|
|
12613
|
-
READONLY: [
|
|
12614
|
-
{ Key: "all", Value: "r" },
|
|
12615
|
-
{ Key: "me", Value: "rw" },
|
|
12616
|
-
],
|
|
12617
|
-
PRIVATE: [{ Key: "me", Value: "rw" }],
|
|
12618
|
-
ADMINWRITE: [{ Key: "all", Value: "r" }],
|
|
12619
|
-
ADMINONLY: [],
|
|
12620
|
-
}[policy];
|
|
12621
|
-
}
|
|
12622
12459
|
}
|
|
12623
12460
|
else {
|
|
12624
|
-
|
|
12625
|
-
|
|
12626
|
-
|
|
12627
|
-
|
|
12628
|
-
|
|
12629
|
-
|
|
12630
|
-
text: JSON.stringify({
|
|
12631
|
-
success: true,
|
|
12632
|
-
requestId: result.RequestId,
|
|
12633
|
-
raw: result,
|
|
12634
|
-
message: "安全规则写入成功",
|
|
12635
|
-
}, null, 2),
|
|
12461
|
+
result = await cloudbase.commonService().call({
|
|
12462
|
+
Action: "ModifyStorageSafeRule",
|
|
12463
|
+
Param: {
|
|
12464
|
+
Bucket: resourceId,
|
|
12465
|
+
EnvId: envId,
|
|
12466
|
+
AclTag: aclTag,
|
|
12636
12467
|
},
|
|
12637
|
-
|
|
12638
|
-
|
|
12468
|
+
});
|
|
12469
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12470
|
+
}
|
|
12639
12471
|
}
|
|
12640
|
-
|
|
12641
|
-
|
|
12642
|
-
|
|
12643
|
-
|
|
12644
|
-
|
|
12645
|
-
|
|
12646
|
-
|
|
12647
|
-
|
|
12648
|
-
|
|
12649
|
-
|
|
12650
|
-
|
|
12651
|
-
|
|
12652
|
-
|
|
12472
|
+
else if (resourceType === "sqlDatabase") {
|
|
12473
|
+
if (aclTag === "CUSTOM") {
|
|
12474
|
+
throw new Error("SQL 数据库不支持自定义安全规则(CUSTOM)");
|
|
12475
|
+
}
|
|
12476
|
+
const schema = envId;
|
|
12477
|
+
const tableName = resourceId;
|
|
12478
|
+
const instanceId = "default";
|
|
12479
|
+
const resource = `${instanceId}#${schema}#${tableName}`;
|
|
12480
|
+
const resourceType = "table";
|
|
12481
|
+
const effect = "allow";
|
|
12482
|
+
const policyList = [
|
|
12483
|
+
"allUser",
|
|
12484
|
+
"anonymousUser",
|
|
12485
|
+
"externalUser",
|
|
12486
|
+
"internalUser",
|
|
12487
|
+
].map((roleIdentity) => ({
|
|
12488
|
+
RoleIdentity: roleIdentity,
|
|
12489
|
+
ResourceType: resourceType,
|
|
12490
|
+
ResourceId: resource,
|
|
12491
|
+
RowPermission: [],
|
|
12492
|
+
Effect: effect,
|
|
12493
|
+
}));
|
|
12494
|
+
policyList[0].RowPermission = getRowPermission(aclTag);
|
|
12495
|
+
result = await cloudbase.commonService("lowcode").call({
|
|
12496
|
+
Action: "BatchCreateResourcePolicy",
|
|
12497
|
+
Param: {
|
|
12498
|
+
EnvId: envId,
|
|
12499
|
+
PolicyList: policyList,
|
|
12500
|
+
},
|
|
12501
|
+
});
|
|
12502
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
12503
|
+
function getRowPermission(policy) {
|
|
12504
|
+
return {
|
|
12505
|
+
READONLY: [
|
|
12506
|
+
{ Key: "all", Value: "r" },
|
|
12507
|
+
{ Key: "me", Value: "rw" },
|
|
12508
|
+
],
|
|
12509
|
+
PRIVATE: [{ Key: "me", Value: "rw" }],
|
|
12510
|
+
ADMINWRITE: [{ Key: "all", Value: "r" }],
|
|
12511
|
+
ADMINONLY: [],
|
|
12512
|
+
}[policy];
|
|
12513
|
+
}
|
|
12514
|
+
}
|
|
12515
|
+
else {
|
|
12516
|
+
throw new Error(`不支持的资源类型: ${resourceType}`);
|
|
12653
12517
|
}
|
|
12518
|
+
return {
|
|
12519
|
+
content: [
|
|
12520
|
+
{
|
|
12521
|
+
type: "text",
|
|
12522
|
+
text: JSON.stringify({
|
|
12523
|
+
success: true,
|
|
12524
|
+
requestId: result.RequestId,
|
|
12525
|
+
raw: result,
|
|
12526
|
+
message: "安全规则写入成功",
|
|
12527
|
+
}, null, 2),
|
|
12528
|
+
},
|
|
12529
|
+
],
|
|
12530
|
+
};
|
|
12654
12531
|
});
|
|
12655
12532
|
}
|
|
12656
12533
|
|
|
@@ -13333,64 +13210,44 @@ function registerDownloadTools(server) {
|
|
|
13333
13210
|
category: "download"
|
|
13334
13211
|
}
|
|
13335
13212
|
}, async ({ url, relativePath }) => {
|
|
13336
|
-
|
|
13337
|
-
// 验证相对路径安全性
|
|
13338
|
-
if (!isPathSafe(relativePath)) {
|
|
13339
|
-
return {
|
|
13340
|
-
content: [
|
|
13341
|
-
{
|
|
13342
|
-
type: "text",
|
|
13343
|
-
text: JSON.stringify({
|
|
13344
|
-
success: false,
|
|
13345
|
-
error: "不安全的相对路径",
|
|
13346
|
-
message: "相对路径包含路径遍历操作(../)或绝对路径,出于安全考虑已拒绝",
|
|
13347
|
-
suggestion: "请使用项目根目录下的相对路径,例如:'assets/images/logo.png'"
|
|
13348
|
-
}, null, 2)
|
|
13349
|
-
}
|
|
13350
|
-
]
|
|
13351
|
-
};
|
|
13352
|
-
}
|
|
13353
|
-
// 计算最终下载路径
|
|
13354
|
-
const targetPath = calculateDownloadPath(relativePath);
|
|
13355
|
-
const projectRoot = getProjectRoot();
|
|
13356
|
-
console.log(`📁 项目根目录: ${projectRoot}`);
|
|
13357
|
-
console.log(`📁 相对路径: ${relativePath}`);
|
|
13358
|
-
console.log(`📁 最终路径: ${targetPath}`);
|
|
13359
|
-
// 下载文件到指定路径
|
|
13360
|
-
const result = await downloadFileToPath(url, targetPath);
|
|
13361
|
-
return {
|
|
13362
|
-
content: [
|
|
13363
|
-
{
|
|
13364
|
-
type: "text",
|
|
13365
|
-
text: JSON.stringify({
|
|
13366
|
-
success: true,
|
|
13367
|
-
filePath: result.filePath,
|
|
13368
|
-
relativePath: relativePath,
|
|
13369
|
-
contentType: result.contentType,
|
|
13370
|
-
fileSize: result.fileSize,
|
|
13371
|
-
projectRoot: projectRoot,
|
|
13372
|
-
message: "文件下载成功到指定路径",
|
|
13373
|
-
note: `文件已保存到项目目录: ${relativePath}`
|
|
13374
|
-
}, null, 2)
|
|
13375
|
-
}
|
|
13376
|
-
]
|
|
13377
|
-
};
|
|
13378
|
-
}
|
|
13379
|
-
catch (error) {
|
|
13213
|
+
if (!isPathSafe(relativePath)) {
|
|
13380
13214
|
return {
|
|
13381
13215
|
content: [
|
|
13382
13216
|
{
|
|
13383
13217
|
type: "text",
|
|
13384
13218
|
text: JSON.stringify({
|
|
13385
13219
|
success: false,
|
|
13386
|
-
error:
|
|
13387
|
-
message: "
|
|
13388
|
-
suggestion: "
|
|
13220
|
+
error: "不安全的相对路径",
|
|
13221
|
+
message: "相对路径包含路径遍历操作(../)或绝对路径,出于安全考虑已拒绝",
|
|
13222
|
+
suggestion: "请使用项目根目录下的相对路径,例如:'assets/images/logo.png'"
|
|
13389
13223
|
}, null, 2)
|
|
13390
13224
|
}
|
|
13391
13225
|
]
|
|
13392
13226
|
};
|
|
13393
13227
|
}
|
|
13228
|
+
const targetPath = calculateDownloadPath(relativePath);
|
|
13229
|
+
const projectRoot = getProjectRoot();
|
|
13230
|
+
console.log(`📁 项目根目录: ${projectRoot}`);
|
|
13231
|
+
console.log(`📁 相对路径: ${relativePath}`);
|
|
13232
|
+
console.log(`📁 最终路径: ${targetPath}`);
|
|
13233
|
+
const result = await downloadFileToPath(url, targetPath);
|
|
13234
|
+
return {
|
|
13235
|
+
content: [
|
|
13236
|
+
{
|
|
13237
|
+
type: "text",
|
|
13238
|
+
text: JSON.stringify({
|
|
13239
|
+
success: true,
|
|
13240
|
+
filePath: result.filePath,
|
|
13241
|
+
relativePath: relativePath,
|
|
13242
|
+
contentType: result.contentType,
|
|
13243
|
+
fileSize: result.fileSize,
|
|
13244
|
+
projectRoot: projectRoot,
|
|
13245
|
+
message: "文件下载成功到指定路径",
|
|
13246
|
+
note: `文件已保存到项目目录: ${relativePath}`
|
|
13247
|
+
}, null, 2)
|
|
13248
|
+
}
|
|
13249
|
+
]
|
|
13250
|
+
};
|
|
13394
13251
|
});
|
|
13395
13252
|
}
|
|
13396
13253
|
|
|
@@ -13605,52 +13462,35 @@ function registerSQLDatabaseTools(server) {
|
|
|
13605
13462
|
category: CATEGORY,
|
|
13606
13463
|
},
|
|
13607
13464
|
}, async ({ sql }) => {
|
|
13608
|
-
|
|
13609
|
-
|
|
13610
|
-
|
|
13611
|
-
|
|
13612
|
-
|
|
13613
|
-
|
|
13614
|
-
|
|
13615
|
-
|
|
13616
|
-
|
|
13465
|
+
const cloudbase = await getManager();
|
|
13466
|
+
const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
13467
|
+
const schemaId = envId;
|
|
13468
|
+
const instanceId = "default";
|
|
13469
|
+
const result = await cloudbase.commonService("tcb", "2018-06-08").call({
|
|
13470
|
+
Action: "RunSql",
|
|
13471
|
+
Param: {
|
|
13472
|
+
EnvId: envId,
|
|
13473
|
+
Sql: sql,
|
|
13474
|
+
DbInstance: {
|
|
13617
13475
|
EnvId: envId,
|
|
13618
|
-
|
|
13619
|
-
|
|
13620
|
-
EnvId: envId,
|
|
13621
|
-
InstanceId: instanceId,
|
|
13622
|
-
Schema: schemaId,
|
|
13623
|
-
},
|
|
13476
|
+
InstanceId: instanceId,
|
|
13477
|
+
Schema: schemaId,
|
|
13624
13478
|
},
|
|
13625
|
-
}
|
|
13626
|
-
|
|
13627
|
-
|
|
13628
|
-
|
|
13629
|
-
|
|
13630
|
-
|
|
13631
|
-
|
|
13632
|
-
|
|
13633
|
-
|
|
13634
|
-
|
|
13635
|
-
|
|
13636
|
-
},
|
|
13637
|
-
|
|
13638
|
-
|
|
13639
|
-
}
|
|
13640
|
-
catch (error) {
|
|
13641
|
-
return {
|
|
13642
|
-
content: [
|
|
13643
|
-
{
|
|
13644
|
-
type: "text",
|
|
13645
|
-
text: JSON.stringify({
|
|
13646
|
-
success: false,
|
|
13647
|
-
error: error.message,
|
|
13648
|
-
message: "SQL query execution failed",
|
|
13649
|
-
}, null, 2),
|
|
13650
|
-
},
|
|
13651
|
-
],
|
|
13652
|
-
};
|
|
13653
|
-
}
|
|
13479
|
+
},
|
|
13480
|
+
});
|
|
13481
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
13482
|
+
return {
|
|
13483
|
+
content: [
|
|
13484
|
+
{
|
|
13485
|
+
type: "text",
|
|
13486
|
+
text: JSON.stringify({
|
|
13487
|
+
success: true,
|
|
13488
|
+
message: "SQL query executed successfully",
|
|
13489
|
+
result,
|
|
13490
|
+
}, null, 2),
|
|
13491
|
+
},
|
|
13492
|
+
],
|
|
13493
|
+
};
|
|
13654
13494
|
});
|
|
13655
13495
|
// executeWriteSQL
|
|
13656
13496
|
server.registerTool?.("executeWriteSQL", {
|
|
@@ -13669,52 +13509,35 @@ function registerSQLDatabaseTools(server) {
|
|
|
13669
13509
|
category: CATEGORY,
|
|
13670
13510
|
},
|
|
13671
13511
|
}, async ({ sql }) => {
|
|
13672
|
-
|
|
13673
|
-
|
|
13674
|
-
|
|
13675
|
-
|
|
13676
|
-
|
|
13677
|
-
|
|
13678
|
-
|
|
13679
|
-
|
|
13680
|
-
|
|
13512
|
+
const cloudbase = await getManager();
|
|
13513
|
+
const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
13514
|
+
const schemaId = envId;
|
|
13515
|
+
const instanceId = "default";
|
|
13516
|
+
const result = await cloudbase.commonService("tcb", "2018-06-08").call({
|
|
13517
|
+
Action: "RunSql",
|
|
13518
|
+
Param: {
|
|
13519
|
+
EnvId: envId,
|
|
13520
|
+
Sql: sql,
|
|
13521
|
+
DbInstance: {
|
|
13681
13522
|
EnvId: envId,
|
|
13682
|
-
|
|
13683
|
-
|
|
13684
|
-
EnvId: envId,
|
|
13685
|
-
InstanceId: instanceId,
|
|
13686
|
-
Schema: schemaId,
|
|
13687
|
-
},
|
|
13523
|
+
InstanceId: instanceId,
|
|
13524
|
+
Schema: schemaId,
|
|
13688
13525
|
},
|
|
13689
|
-
}
|
|
13690
|
-
|
|
13691
|
-
|
|
13692
|
-
|
|
13693
|
-
|
|
13694
|
-
|
|
13695
|
-
|
|
13696
|
-
|
|
13697
|
-
|
|
13698
|
-
|
|
13699
|
-
|
|
13700
|
-
},
|
|
13701
|
-
|
|
13702
|
-
|
|
13703
|
-
}
|
|
13704
|
-
catch (error) {
|
|
13705
|
-
return {
|
|
13706
|
-
content: [
|
|
13707
|
-
{
|
|
13708
|
-
type: "text",
|
|
13709
|
-
text: JSON.stringify({
|
|
13710
|
-
success: false,
|
|
13711
|
-
error: error.message,
|
|
13712
|
-
message: "SQL statement execution failed",
|
|
13713
|
-
}, null, 2),
|
|
13714
|
-
},
|
|
13715
|
-
],
|
|
13716
|
-
};
|
|
13717
|
-
}
|
|
13526
|
+
},
|
|
13527
|
+
});
|
|
13528
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
13529
|
+
return {
|
|
13530
|
+
content: [
|
|
13531
|
+
{
|
|
13532
|
+
type: "text",
|
|
13533
|
+
text: JSON.stringify({
|
|
13534
|
+
success: true,
|
|
13535
|
+
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.`,
|
|
13536
|
+
result,
|
|
13537
|
+
}, null, 2),
|
|
13538
|
+
},
|
|
13539
|
+
],
|
|
13540
|
+
};
|
|
13718
13541
|
});
|
|
13719
13542
|
}
|
|
13720
13543
|
|