@cloudbase/cloudbase-mcp 2.23.9 → 2.23.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +3 -3
- package/dist/index.cjs +551 -315
- package/dist/index.js +551 -315
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -122997,6 +122997,7 @@ const STORAGE_ACTIONS = [
|
|
|
122997
122997
|
"objectInfo",
|
|
122998
122998
|
"signUpload",
|
|
122999
122999
|
"signDownload",
|
|
123000
|
+
"createBucket",
|
|
123000
123001
|
];
|
|
123001
123002
|
function buildPgStorageResult(payload) {
|
|
123002
123003
|
return (0, tool_result_js_1.buildJsonToolResult)(payload);
|
|
@@ -123055,12 +123056,52 @@ async function handleBuckets(server) {
|
|
|
123055
123056
|
data: {
|
|
123056
123057
|
capability: "storageManagerSdkOrHttpApi",
|
|
123057
123058
|
envId: server.cloudBaseOptions?.envId ?? null,
|
|
123058
|
-
supportedActions: ["buckets", "config", "uploadPlan", "objectInfo"],
|
|
123059
|
+
supportedActions: ["buckets", "config", "uploadPlan", "objectInfo", "createBucket"],
|
|
123059
123060
|
note: "PG environment storage is exposed as metadata and implementation plans in MCP. Application data-plane upload/download should use SDK or HTTP API code.",
|
|
123060
123061
|
},
|
|
123061
123062
|
message: "Resolved PostgreSQL storage capability summary. Use uploadPlan for application-side upload implementation.",
|
|
123062
123063
|
});
|
|
123063
123064
|
}
|
|
123065
|
+
async function handleCreateBucket(args, server) {
|
|
123066
|
+
if (!args.bucket?.trim()) {
|
|
123067
|
+
return buildPgStorageResult({
|
|
123068
|
+
success: false,
|
|
123069
|
+
errorCode: "BUCKET_REQUIRED",
|
|
123070
|
+
message: "Provide bucket name to create a PG storage bucket.",
|
|
123071
|
+
});
|
|
123072
|
+
}
|
|
123073
|
+
const bucket = args.bucket.trim();
|
|
123074
|
+
const envId = server.cloudBaseOptions?.envId ?? "${envId}";
|
|
123075
|
+
return buildPgStorageResult({
|
|
123076
|
+
success: true,
|
|
123077
|
+
data: {
|
|
123078
|
+
action: "createBucket",
|
|
123079
|
+
bucket,
|
|
123080
|
+
description: `Creates PG storage bucket '${bucket}'`,
|
|
123081
|
+
plans: {
|
|
123082
|
+
sql: `INSERT INTO storage.buckets (id, name, public) VALUES ('${bucket}', '${bucket}', false);`,
|
|
123083
|
+
httpApi: {
|
|
123084
|
+
method: "POST",
|
|
123085
|
+
url: `https://${envId}.api.tcloudbasegateway.com/v1/storages/bucket/`,
|
|
123086
|
+
headers: {
|
|
123087
|
+
"Authorization": "Bearer {service_role_token}",
|
|
123088
|
+
"Content-Type": "application/json",
|
|
123089
|
+
},
|
|
123090
|
+
body: { name: bucket, public: false },
|
|
123091
|
+
},
|
|
123092
|
+
cli: `tcb db execute -e ${envId} --sql "INSERT INTO storage.buckets (id, name, public) VALUES ('${bucket}', '${bucket}', false);"`,
|
|
123093
|
+
},
|
|
123094
|
+
tokenRequired: "service_role",
|
|
123095
|
+
tokenGuide: "Use manageAppAuth(action='createApiKey', name='storage-server-key') to get a service_role level API key token.",
|
|
123096
|
+
nextSteps: [
|
|
123097
|
+
"Option A: Run the SQL via managePgDatabase(action='execute', confirm=true)",
|
|
123098
|
+
"Option B: Call the HTTP API with a service_role token",
|
|
123099
|
+
"Option C: Use CloudBase CLI: tcb db execute",
|
|
123100
|
+
],
|
|
123101
|
+
},
|
|
123102
|
+
message: `Generated bucket creation plan for '${bucket}'. Execute one of the provided plans to create the bucket, then configure RLS policies.`,
|
|
123103
|
+
});
|
|
123104
|
+
}
|
|
123064
123105
|
async function handleUploadPlan(args, server) {
|
|
123065
123106
|
const missingBucket = requireBucket(args);
|
|
123066
123107
|
if (missingBucket)
|
|
@@ -123131,7 +123172,7 @@ function registerPGStorageTools(server) {
|
|
|
123131
123172
|
inputSchema: {
|
|
123132
123173
|
action: zod_1.z
|
|
123133
123174
|
.enum(STORAGE_ACTIONS)
|
|
123134
|
-
.describe("操作类型:buckets/config=查询存储能力摘要;uploadPlan=生成 HTTP API/SDK 上传方案;objectInfo=生成对象元信息查询方案;signUpload/signDownload=显式的一次性签名 URL 请求占位"),
|
|
123175
|
+
.describe("操作类型:buckets/config=查询存储能力摘要;createBucket=生成 bucket 创建方案(SQL/HTTP API/CLI);uploadPlan=生成 HTTP API/SDK 上传方案;objectInfo=生成对象元信息查询方案;signUpload/signDownload=显式的一次性签名 URL 请求占位"),
|
|
123135
123176
|
bucket: zod_1.z.string().optional().describe("云存储 bucket 名称"),
|
|
123136
123177
|
objectKey: zod_1.z.string().optional().describe("单个对象 key"),
|
|
123137
123178
|
objectKeys: zod_1.z.array(zod_1.z.string()).optional().describe("多个对象 key,用于对象元信息查询规划"),
|
|
@@ -123155,6 +123196,8 @@ function registerPGStorageTools(server) {
|
|
|
123155
123196
|
case "buckets":
|
|
123156
123197
|
case "config":
|
|
123157
123198
|
return handleBuckets(server);
|
|
123199
|
+
case "createBucket":
|
|
123200
|
+
return handleCreateBucket(args, server);
|
|
123158
123201
|
case "uploadPlan":
|
|
123159
123202
|
return handleUploadPlan(args, server);
|
|
123160
123203
|
case "objectInfo":
|
|
@@ -136836,7 +136879,7 @@ class TelemetryReporter {
|
|
|
136836
136879
|
const nodeVersion = process.version; // Node.js版本
|
|
136837
136880
|
const arch = os_1.default.arch(); // 系统架构
|
|
136838
136881
|
// 从构建时注入的版本号获取MCP版本信息
|
|
136839
|
-
const mcpVersion = process.env.npm_package_version || "2.23.
|
|
136882
|
+
const mcpVersion = process.env.npm_package_version || "2.23.11" || 0;
|
|
136840
136883
|
return {
|
|
136841
136884
|
userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
|
|
136842
136885
|
deviceId: this.deviceId,
|
|
@@ -160299,6 +160342,7 @@ const MANAGE_ACTIONS = [
|
|
|
160299
160342
|
"listMigrations",
|
|
160300
160343
|
"migrationDetail",
|
|
160301
160344
|
"rollbackMigration",
|
|
160345
|
+
"repairMigration",
|
|
160302
160346
|
];
|
|
160303
160347
|
function buildPgToolResult(payload) {
|
|
160304
160348
|
return (0, tool_result_js_1.buildJsonToolResult)(payload);
|
|
@@ -160806,6 +160850,12 @@ async function executeManagerPGSql(context, sql, cloudBaseOptions) {
|
|
|
160806
160850
|
}
|
|
160807
160851
|
throw new Error("Current @cloudbase/manager-node runtime does not expose database.executePGSql or commonService fallback. Upgrade to @cloudbase/manager-node >= 5.4.0.");
|
|
160808
160852
|
}
|
|
160853
|
+
/** Generate a 14-digit migration version (YYYYMMDDHHMMSS) from current time */
|
|
160854
|
+
function generateMigrationVersion() {
|
|
160855
|
+
const d = new Date();
|
|
160856
|
+
const p = (n) => String(n).padStart(2, "0");
|
|
160857
|
+
return `${d.getFullYear()}${p(d.getMonth() + 1)}${p(d.getDate())}${p(d.getHours())}${p(d.getMinutes())}${p(d.getSeconds())}`;
|
|
160858
|
+
}
|
|
160809
160859
|
/** Call a CloudBase PG migration API via commonService fallback */
|
|
160810
160860
|
async function callPgMigrationApi(context, action, params, cloudBaseOptions) {
|
|
160811
160861
|
const manager = await (0, cloudbase_manager_js_1.getCloudBaseManager)({
|
|
@@ -161130,16 +161180,32 @@ async function handlePlanMigration(args, context, deps, cloudBaseOptions) {
|
|
|
161130
161180
|
message: "Provide migration SQL when action=planMigration.",
|
|
161131
161181
|
});
|
|
161132
161182
|
}
|
|
161183
|
+
if (!args.migrationName?.trim()) {
|
|
161184
|
+
return buildPgToolResult({
|
|
161185
|
+
success: false,
|
|
161186
|
+
errorCode: "MIGRATION_NAME_REQUIRED",
|
|
161187
|
+
message: "Provide migrationName (lowercase letters, digits and underscores, starting with a letter) when action=planMigration.",
|
|
161188
|
+
});
|
|
161189
|
+
}
|
|
161190
|
+
const version = args.migrationVersion?.trim() || generateMigrationVersion();
|
|
161191
|
+
const migration = {
|
|
161192
|
+
Version: version,
|
|
161193
|
+
Name: args.migrationName,
|
|
161194
|
+
Query: args.sql,
|
|
161195
|
+
};
|
|
161196
|
+
if (args.rollbackSql?.trim()) {
|
|
161197
|
+
migration.Rollback = args.rollbackSql;
|
|
161198
|
+
}
|
|
161133
161199
|
try {
|
|
161134
161200
|
const result = await callPgMigrationApi(context, "PreviewPGUserMigrations", {
|
|
161135
|
-
|
|
161201
|
+
Migrations: [migration],
|
|
161136
161202
|
}, cloudBaseOptions);
|
|
161137
161203
|
return buildPgToolResult({
|
|
161138
161204
|
success: true,
|
|
161139
161205
|
data: result,
|
|
161140
161206
|
message: "Migration plan generated via PreviewPGUserMigrations.",
|
|
161141
161207
|
nextActions: [
|
|
161142
|
-
buildNextAction(MANAGE_PG_DATABASE, "applyMigration", "Review the plan above. If it looks correct, call applyMigration to execute.", { action: "applyMigration", sql: args.sql, confirm: true }),
|
|
161208
|
+
buildNextAction(MANAGE_PG_DATABASE, "applyMigration", "Review the plan above. If it looks correct, call applyMigration to execute.", { action: "applyMigration", migrationName: args.migrationName, sql: args.sql, confirm: true, ...(args.rollbackSql ? { rollbackSql: args.rollbackSql } : {}) }),
|
|
161143
161209
|
],
|
|
161144
161210
|
});
|
|
161145
161211
|
}
|
|
@@ -161159,6 +161225,13 @@ async function handleApplyMigration(args, context, deps, cloudBaseOptions) {
|
|
|
161159
161225
|
message: "Provide migration SQL when action=applyMigration.",
|
|
161160
161226
|
});
|
|
161161
161227
|
}
|
|
161228
|
+
if (!args.migrationName?.trim()) {
|
|
161229
|
+
return buildPgToolResult({
|
|
161230
|
+
success: false,
|
|
161231
|
+
errorCode: "MIGRATION_NAME_REQUIRED",
|
|
161232
|
+
message: "Provide migrationName (lowercase letters, digits and underscores, starting with a letter) when action=applyMigration.",
|
|
161233
|
+
});
|
|
161234
|
+
}
|
|
161162
161235
|
if (args.confirm !== true) {
|
|
161163
161236
|
return buildPgToolResult({
|
|
161164
161237
|
success: false,
|
|
@@ -161166,10 +161239,24 @@ async function handleApplyMigration(args, context, deps, cloudBaseOptions) {
|
|
|
161166
161239
|
message: "PushPGUserMigrations requires confirm=true. Run with confirm=true to proceed.",
|
|
161167
161240
|
});
|
|
161168
161241
|
}
|
|
161242
|
+
const version = args.migrationVersion?.trim() || generateMigrationVersion();
|
|
161243
|
+
const migration = {
|
|
161244
|
+
Version: version,
|
|
161245
|
+
Name: args.migrationName,
|
|
161246
|
+
Query: args.sql,
|
|
161247
|
+
};
|
|
161248
|
+
if (args.rollbackSql?.trim()) {
|
|
161249
|
+
migration.Rollback = args.rollbackSql;
|
|
161250
|
+
}
|
|
161251
|
+
const params = { Migrations: [migration] };
|
|
161252
|
+
if (args.lockTimeoutMs !== undefined) {
|
|
161253
|
+
params.LockTimeoutMs = args.lockTimeoutMs;
|
|
161254
|
+
}
|
|
161255
|
+
if (args.statementTimeoutMs !== undefined) {
|
|
161256
|
+
params.StatementTimeoutMs = args.statementTimeoutMs;
|
|
161257
|
+
}
|
|
161169
161258
|
try {
|
|
161170
|
-
const result = await callPgMigrationApi(context, "PushPGUserMigrations",
|
|
161171
|
-
Sql: args.sql,
|
|
161172
|
-
}, cloudBaseOptions);
|
|
161259
|
+
const result = await callPgMigrationApi(context, "PushPGUserMigrations", params, cloudBaseOptions);
|
|
161173
161260
|
return buildPgToolResult({
|
|
161174
161261
|
success: true,
|
|
161175
161262
|
data: result,
|
|
@@ -161185,8 +161272,15 @@ async function handleApplyMigration(args, context, deps, cloudBaseOptions) {
|
|
|
161185
161272
|
}
|
|
161186
161273
|
}
|
|
161187
161274
|
async function handleListMigrations(args, context, deps, cloudBaseOptions) {
|
|
161275
|
+
const params = {};
|
|
161276
|
+
if (args.limit !== undefined) {
|
|
161277
|
+
params.Limit = args.limit;
|
|
161278
|
+
}
|
|
161279
|
+
if (args.offset !== undefined) {
|
|
161280
|
+
params.Offset = args.offset;
|
|
161281
|
+
}
|
|
161188
161282
|
try {
|
|
161189
|
-
const result = await callPgMigrationApi(context, "ListPGUserMigrations",
|
|
161283
|
+
const result = await callPgMigrationApi(context, "ListPGUserMigrations", params, cloudBaseOptions);
|
|
161190
161284
|
return buildPgToolResult({
|
|
161191
161285
|
success: true,
|
|
161192
161286
|
data: result,
|
|
@@ -161202,16 +161296,16 @@ async function handleListMigrations(args, context, deps, cloudBaseOptions) {
|
|
|
161202
161296
|
}
|
|
161203
161297
|
}
|
|
161204
161298
|
async function handleMigrationDetail(args, context, deps, cloudBaseOptions) {
|
|
161205
|
-
if (!args.
|
|
161299
|
+
if (!args.migrationVersion?.trim()) {
|
|
161206
161300
|
return buildPgToolResult({
|
|
161207
161301
|
success: false,
|
|
161208
|
-
errorCode: "
|
|
161209
|
-
message: "Provide
|
|
161302
|
+
errorCode: "MIGRATION_VERSION_REQUIRED",
|
|
161303
|
+
message: "Provide migrationVersion (14-digit timestamp YYYYMMDDHHMMSS) when action=migrationDetail.",
|
|
161210
161304
|
});
|
|
161211
161305
|
}
|
|
161212
161306
|
try {
|
|
161213
161307
|
const result = await callPgMigrationApi(context, "DescribePGUserMigration", {
|
|
161214
|
-
|
|
161308
|
+
MigrationVersion: args.migrationVersion,
|
|
161215
161309
|
}, cloudBaseOptions);
|
|
161216
161310
|
return buildPgToolResult({
|
|
161217
161311
|
success: true,
|
|
@@ -161228,11 +161322,11 @@ async function handleMigrationDetail(args, context, deps, cloudBaseOptions) {
|
|
|
161228
161322
|
}
|
|
161229
161323
|
}
|
|
161230
161324
|
async function handleRollbackMigration(args, context, deps, cloudBaseOptions) {
|
|
161231
|
-
if (!args.
|
|
161325
|
+
if (args.lastN === undefined || args.lastN < 1 || !Number.isInteger(args.lastN)) {
|
|
161232
161326
|
return buildPgToolResult({
|
|
161233
161327
|
success: false,
|
|
161234
|
-
errorCode: "
|
|
161235
|
-
message: "Provide
|
|
161328
|
+
errorCode: "LAST_N_REQUIRED",
|
|
161329
|
+
message: "Provide lastN (positive integer) when action=rollbackMigration.",
|
|
161236
161330
|
});
|
|
161237
161331
|
}
|
|
161238
161332
|
if (args.confirm !== true) {
|
|
@@ -161244,7 +161338,7 @@ async function handleRollbackMigration(args, context, deps, cloudBaseOptions) {
|
|
|
161244
161338
|
}
|
|
161245
161339
|
try {
|
|
161246
161340
|
const result = await callPgMigrationApi(context, "RollbackPGUserMigrations", {
|
|
161247
|
-
|
|
161341
|
+
LastN: args.lastN,
|
|
161248
161342
|
}, cloudBaseOptions);
|
|
161249
161343
|
return buildPgToolResult({
|
|
161250
161344
|
success: true,
|
|
@@ -161260,6 +161354,67 @@ async function handleRollbackMigration(args, context, deps, cloudBaseOptions) {
|
|
|
161260
161354
|
});
|
|
161261
161355
|
}
|
|
161262
161356
|
}
|
|
161357
|
+
async function handleRepairMigration(args, context, deps, cloudBaseOptions) {
|
|
161358
|
+
if (!args.migrationVersion?.trim()) {
|
|
161359
|
+
return buildPgToolResult({
|
|
161360
|
+
success: false,
|
|
161361
|
+
errorCode: "MIGRATION_VERSION_REQUIRED",
|
|
161362
|
+
message: "Provide migrationVersion (14-digit timestamp YYYYMMDDHHMMSS) when action=repairMigration.",
|
|
161363
|
+
});
|
|
161364
|
+
}
|
|
161365
|
+
if (!args.migrationName?.trim()) {
|
|
161366
|
+
return buildPgToolResult({
|
|
161367
|
+
success: false,
|
|
161368
|
+
errorCode: "MIGRATION_NAME_REQUIRED",
|
|
161369
|
+
message: "Provide migrationName when action=repairMigration.",
|
|
161370
|
+
});
|
|
161371
|
+
}
|
|
161372
|
+
if (!args.repairStatus) {
|
|
161373
|
+
return buildPgToolResult({
|
|
161374
|
+
success: false,
|
|
161375
|
+
errorCode: "REPAIR_STATUS_REQUIRED",
|
|
161376
|
+
message: "Provide repairStatus (applied or reverted) when action=repairMigration.",
|
|
161377
|
+
});
|
|
161378
|
+
}
|
|
161379
|
+
if (!args.repairReason?.trim()) {
|
|
161380
|
+
return buildPgToolResult({
|
|
161381
|
+
success: false,
|
|
161382
|
+
errorCode: "REPAIR_REASON_REQUIRED",
|
|
161383
|
+
message: "Provide repairReason when action=repairMigration.",
|
|
161384
|
+
});
|
|
161385
|
+
}
|
|
161386
|
+
if (args.repairStatus === "applied" && !args.sql?.trim()) {
|
|
161387
|
+
return buildPgToolResult({
|
|
161388
|
+
success: false,
|
|
161389
|
+
errorCode: "SQL_REQUIRED",
|
|
161390
|
+
message: "Provide sql (Query) when action=repairMigration with repairStatus=applied.",
|
|
161391
|
+
});
|
|
161392
|
+
}
|
|
161393
|
+
const params = {
|
|
161394
|
+
MigrationVersion: args.migrationVersion,
|
|
161395
|
+
Name: args.migrationName,
|
|
161396
|
+
Status: args.repairStatus,
|
|
161397
|
+
Reason: args.repairReason,
|
|
161398
|
+
};
|
|
161399
|
+
if (args.repairStatus === "applied" && args.sql?.trim()) {
|
|
161400
|
+
params.Query = args.sql;
|
|
161401
|
+
}
|
|
161402
|
+
try {
|
|
161403
|
+
const result = await callPgMigrationApi(context, "RepairPGUserMigrationHistory", params, cloudBaseOptions);
|
|
161404
|
+
return buildPgToolResult({
|
|
161405
|
+
success: true,
|
|
161406
|
+
data: result,
|
|
161407
|
+
message: "Migration history repaired via RepairPGUserMigrationHistory.",
|
|
161408
|
+
});
|
|
161409
|
+
}
|
|
161410
|
+
catch (error) {
|
|
161411
|
+
return buildPgToolResult({
|
|
161412
|
+
success: false,
|
|
161413
|
+
errorCode: "MIGRATION_API_ERROR",
|
|
161414
|
+
message: `RepairPGUserMigrationHistory failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
161415
|
+
});
|
|
161416
|
+
}
|
|
161417
|
+
}
|
|
161263
161418
|
async function handleGetPgSchema(args, context, deps) {
|
|
161264
161419
|
const objectName = args.objectName ?? "";
|
|
161265
161420
|
const parsed = parseSchemaQualifiedName(objectName);
|
|
@@ -161380,15 +161535,15 @@ function registerPGDatabaseTools(server, providedDeps) {
|
|
|
161380
161535
|
});
|
|
161381
161536
|
server.registerTool?.(MANAGE_PG_DATABASE, {
|
|
161382
161537
|
title: "管理 PostgreSQL 上下文或执行写入 SQL",
|
|
161383
|
-
description: "管理 CloudBase PostgreSQL:执行已确认的写入 SQL 或 DDL、SQL
|
|
161538
|
+
description: "管理 CloudBase PostgreSQL:执行已确认的写入 SQL 或 DDL、SQL 风险预检、迁移管理。建表、改 schema、数据结构变更优先使用 applyMigration(带版本管理与回滚),而非 execute。",
|
|
161384
161539
|
inputSchema: {
|
|
161385
161540
|
action: zod_1.z
|
|
161386
161541
|
.enum(MANAGE_ACTIONS)
|
|
161387
|
-
.describe("操作类型:execute=执行已确认的写入 SQL 或 DDL;dryRun=只分析 SQL 风险不执行;planMigration
|
|
161542
|
+
.describe("操作类型:execute=执行已确认的写入 SQL 或 DDL;dryRun=只分析 SQL 风险不执行;planMigration=预览迁移计划(需 migrationName + sql);applyMigration=应用迁移,建表/改 schema 首选(需 migrationName + sql + confirm=true);listMigrations=查询已应用的 Migration 列表(可传 limit/offset 分页);migrationDetail=查看单条 Migration 详情(需 migrationVersion);rollbackMigration=回滚最近 N 条 Migration(需 lastN + confirm=true);repairMigration=修复 Migration 历史记录(需 migrationVersion + migrationName + repairStatus + repairReason)"),
|
|
161388
161543
|
sql: zod_1.z
|
|
161389
161544
|
.string()
|
|
161390
161545
|
.optional()
|
|
161391
|
-
.describe("action=execute、dryRun、planMigration 或
|
|
161546
|
+
.describe("action=execute、dryRun、planMigration、applyMigration 或 repairMigration(applied) 使用的 SQL 语句"),
|
|
161392
161547
|
confirm: zod_1.z
|
|
161393
161548
|
.boolean()
|
|
161394
161549
|
.optional()
|
|
@@ -161412,7 +161567,58 @@ function registerPGDatabaseTools(server, providedDeps) {
|
|
|
161412
161567
|
objectName: zod_1.z
|
|
161413
161568
|
.string()
|
|
161414
161569
|
.optional()
|
|
161415
|
-
.describe("
|
|
161570
|
+
.describe("可选的对象名,当前仅用于非 migration 场景。migration 相关操作请使用 migrationName / migrationVersion / lastN。"),
|
|
161571
|
+
migrationName: zod_1.z
|
|
161572
|
+
.string()
|
|
161573
|
+
.regex(/^[a-z][a-z0-9_]*$/)
|
|
161574
|
+
.optional()
|
|
161575
|
+
.describe("plan/apply/repair 必填:migration 名称,小写字母开头,仅允许小写字母、数字和下划线。"),
|
|
161576
|
+
migrationVersion: zod_1.z
|
|
161577
|
+
.string()
|
|
161578
|
+
.regex(/^\d{14}$/)
|
|
161579
|
+
.optional()
|
|
161580
|
+
.describe("14 位时间戳 YYYYMMDDHHMMSS。detail/repair 必填;plan/apply 不传时自动生成。"),
|
|
161581
|
+
rollbackSql: zod_1.z
|
|
161582
|
+
.string()
|
|
161583
|
+
.optional()
|
|
161584
|
+
.describe("plan/apply 可选:回滚 SQL 语句。"),
|
|
161585
|
+
lastN: zod_1.z
|
|
161586
|
+
.number()
|
|
161587
|
+
.int()
|
|
161588
|
+
.positive()
|
|
161589
|
+
.optional()
|
|
161590
|
+
.describe("rollback 必填:回滚最近 N 条已应用的 Migration,正整数。"),
|
|
161591
|
+
limit: zod_1.z
|
|
161592
|
+
.number()
|
|
161593
|
+
.int()
|
|
161594
|
+
.min(1)
|
|
161595
|
+
.max(500)
|
|
161596
|
+
.optional()
|
|
161597
|
+
.describe("list 可选:返回数量上限,1-500,默认 100。"),
|
|
161598
|
+
offset: zod_1.z
|
|
161599
|
+
.number()
|
|
161600
|
+
.int()
|
|
161601
|
+
.min(0)
|
|
161602
|
+
.optional()
|
|
161603
|
+
.describe("list 可选:分页偏移,默认 0。"),
|
|
161604
|
+
lockTimeoutMs: zod_1.z
|
|
161605
|
+
.number()
|
|
161606
|
+
.int()
|
|
161607
|
+
.optional()
|
|
161608
|
+
.describe("apply 可选:获取数据库锁的最长时间(毫秒),默认 5000。"),
|
|
161609
|
+
statementTimeoutMs: zod_1.z
|
|
161610
|
+
.number()
|
|
161611
|
+
.int()
|
|
161612
|
+
.optional()
|
|
161613
|
+
.describe("apply 可选:单条 SQL 执行最长时间(毫秒),默认 300000。"),
|
|
161614
|
+
repairStatus: zod_1.z
|
|
161615
|
+
.enum(["applied", "reverted"])
|
|
161616
|
+
.optional()
|
|
161617
|
+
.describe("repair 必填:applied=标记为已应用(可补录 Query),reverted=删除 history 记录。"),
|
|
161618
|
+
repairReason: zod_1.z
|
|
161619
|
+
.string()
|
|
161620
|
+
.optional()
|
|
161621
|
+
.describe("repair 必填:修复原因。"),
|
|
161416
161622
|
},
|
|
161417
161623
|
annotations: {
|
|
161418
161624
|
readOnlyHint: false,
|
|
@@ -161448,13 +161654,15 @@ function registerPGDatabaseTools(server, providedDeps) {
|
|
|
161448
161654
|
case "applyMigration":
|
|
161449
161655
|
case "listMigrations":
|
|
161450
161656
|
case "migrationDetail":
|
|
161451
|
-
case "rollbackMigration":
|
|
161657
|
+
case "rollbackMigration":
|
|
161658
|
+
case "repairMigration": {
|
|
161452
161659
|
switch (args.action) {
|
|
161453
161660
|
case "planMigration": return handlePlanMigration(args, context, deps, cbOpts);
|
|
161454
161661
|
case "applyMigration": return handleApplyMigration(args, context, deps, cbOpts);
|
|
161455
161662
|
case "listMigrations": return handleListMigrations(args, context, deps, cbOpts);
|
|
161456
161663
|
case "migrationDetail": return handleMigrationDetail(args, context, deps, cbOpts);
|
|
161457
161664
|
case "rollbackMigration": return handleRollbackMigration(args, context, deps, cbOpts);
|
|
161665
|
+
case "repairMigration": return handleRepairMigration(args, context, deps, cbOpts);
|
|
161458
161666
|
default: return buildPgToolResult({ success: false, errorCode: "UNSUPPORTED_ACTION", message: `Unsupported action: ${args.action}` });
|
|
161459
161667
|
}
|
|
161460
161668
|
}
|
|
@@ -182984,6 +183192,12 @@ async function resolveSkillSearchRoots(options = {}) {
|
|
|
182984
183192
|
? path.resolve(path.dirname(cliEntryPath), "..", "..")
|
|
182985
183193
|
: undefined;
|
|
182986
183194
|
return filterExistingDirs([
|
|
183195
|
+
repoRoot
|
|
183196
|
+
? path.join(repoRoot, ".generated", "compat-config", ".agents", "skills")
|
|
183197
|
+
: undefined,
|
|
183198
|
+
repoRoot
|
|
183199
|
+
? path.join(repoRoot, ".generated", "compat-config", ".claude", "skills")
|
|
183200
|
+
: undefined,
|
|
182987
183201
|
repoRoot
|
|
182988
183202
|
? path.join(repoRoot, ".generated", "compat-config", ".codebuddy", "skills")
|
|
182989
183203
|
: undefined,
|
|
@@ -196564,7 +196778,7 @@ ${envIdSection}
|
|
|
196564
196778
|
## 环境信息
|
|
196565
196779
|
- 操作系统: ${os_1.default.type()} ${os_1.default.release()}
|
|
196566
196780
|
- Node.js版本: ${process.version}
|
|
196567
|
-
- MCP 版本:${process.env.npm_package_version || "2.23.
|
|
196781
|
+
- MCP 版本:${process.env.npm_package_version || "2.23.11" || 0}
|
|
196568
196782
|
- 系统架构: ${os_1.default.arch()}
|
|
196569
196783
|
- 时间: ${new Date().toISOString()}
|
|
196570
196784
|
- 请求ID: ${requestId}
|
|
@@ -196645,7 +196859,7 @@ function createWrappedHandler(name, handler, server) {
|
|
|
196645
196859
|
requestId: (typeof error === 'object' && error && 'requestId' in error) ? error.requestId : '',
|
|
196646
196860
|
ide: server.ide || process.env.INTEGRATION_IDE || ''
|
|
196647
196861
|
});
|
|
196648
|
-
const mcpVersion = true ? "2.23.
|
|
196862
|
+
const mcpVersion = true ? "2.23.11" : 0;
|
|
196649
196863
|
const requestIdSuffix = requestId ? `\n🆔 RequestId: ${requestId}` : '';
|
|
196650
196864
|
const enhancedErrorMessage = `${errorMessage}${requestIdSuffix}\n\n📦 CloudBase MCP v${mcpVersion}\n🔗 遇到问题?请复制以下链接到浏览器打开\n即可自动携带错误详情快速创建 GitHub Issue:\n${issueLink}`;
|
|
196651
196865
|
// 创建新的错误对象,保持原有的错误类型但更新消息
|
|
@@ -212269,7 +212483,7 @@ exports.IDE_TYPES = [
|
|
|
212269
212483
|
"openai-codex-cli", // OpenAI Codex CLI
|
|
212270
212484
|
"augment-code", // Augment Code
|
|
212271
212485
|
"github-copilot", // GitHub Copilot
|
|
212272
|
-
"roocode", // RooCode AI
|
|
212486
|
+
"roocode", // RooCode AI编辑器(已 deprecated 2026-05,可考虑引导转向 Cline/ZooCode)
|
|
212273
212487
|
"tongyi-lingma", // 通义灵码
|
|
212274
212488
|
"trae", // Trae AI编辑器
|
|
212275
212489
|
"qoder", // Qoder AI编辑器
|
|
@@ -212311,7 +212525,6 @@ exports.RAW_IDE_FILE_MAPPINGS = {
|
|
|
212311
212525
|
],
|
|
212312
212526
|
"baidu-comate": [
|
|
212313
212527
|
{ path: ".comate/rules/cloudbase-rules.mdr" },
|
|
212314
|
-
{ path: ".comate/rules/cloudbaase-rules.mdr" },
|
|
212315
212528
|
{ path: ".comate/mcp.json", isMcpConfig: true },
|
|
212316
212529
|
],
|
|
212317
212530
|
"openai-codex-cli": [
|
|
@@ -212321,10 +212534,10 @@ exports.RAW_IDE_FILE_MAPPINGS = {
|
|
|
212321
212534
|
"augment-code": [{ path: ".augment-guidelines" }],
|
|
212322
212535
|
"github-copilot": [{ path: ".github/copilot-instructions.md" }],
|
|
212323
212536
|
roocode: [
|
|
212324
|
-
{ path: ".roo/rules/
|
|
212537
|
+
{ path: ".roo/rules/cloudbase-rules.md" },
|
|
212325
212538
|
{ path: ".roo/mcp.json", isMcpConfig: true },
|
|
212326
212539
|
],
|
|
212327
|
-
"tongyi-lingma": [{ path: ".lingma/rules/
|
|
212540
|
+
"tongyi-lingma": [{ path: ".lingma/rules/cloudbase-rules.md" }],
|
|
212328
212541
|
trae: [{ path: ".trae/rules/" }],
|
|
212329
212542
|
qoder: [{ path: ".qoder/rules/" }],
|
|
212330
212543
|
antigravity: [{ path: ".agent/rules/" }],
|
|
@@ -212364,7 +212577,7 @@ const IDE_DESCRIPTIONS = {
|
|
|
212364
212577
|
"openai-codex-cli": "OpenAI Codex CLI",
|
|
212365
212578
|
"augment-code": "Augment Code",
|
|
212366
212579
|
"github-copilot": "GitHub Copilot",
|
|
212367
|
-
roocode: "RooCode AI
|
|
212580
|
+
roocode: "RooCode AI编辑器(deprecated)",
|
|
212368
212581
|
"tongyi-lingma": "通义灵码",
|
|
212369
212582
|
trae: "Trae AI编辑器",
|
|
212370
212583
|
qoder: "Qoder AI编辑器",
|
|
@@ -212659,7 +212872,7 @@ function registerSetupTools(server) {
|
|
|
212659
212872
|
server.registerTool("downloadTemplate", {
|
|
212660
212873
|
title: "下载项目模板",
|
|
212661
212874
|
description: `自动下载并部署CloudBase项目模板。
|
|
212662
|
-
**Note**: Call this tool when the user requests to create a new project using a CloudBase template.\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.23.
|
|
212875
|
+
**Note**: Call this tool when the user requests to create a new project using a CloudBase template.\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.23.11" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
|
|
212663
212876
|
inputSchema: {
|
|
212664
212877
|
template: zod_1.z
|
|
212665
212878
|
.enum(["react", "vue", "miniprogram", "uniapp", "rules"])
|
|
@@ -253709,6 +253922,7 @@ const os = __importStar(__webpack_require__(21820));
|
|
|
253709
253922
|
const path = __importStar(__webpack_require__(39902));
|
|
253710
253923
|
const zod_1 = __webpack_require__(21614);
|
|
253711
253924
|
const cloudbase_manager_js_1 = __webpack_require__(3431);
|
|
253925
|
+
const tool_result_js_1 = __webpack_require__(9835);
|
|
253712
253926
|
const MAX_INLINE_TEXT_BYTES = 256 * 1024;
|
|
253713
253927
|
const STORAGE_READ_TEMP_PREFIX = 'cloudbase-mcp-storage-read-';
|
|
253714
253928
|
// Input schema for queryStorage tool
|
|
@@ -253791,7 +254005,7 @@ function registerStorageTools(server) {
|
|
|
253791
254005
|
// Tool 1: queryStorage - 查询存储信息(只读操作)
|
|
253792
254006
|
server.registerTool("queryStorage", {
|
|
253793
254007
|
title: "查询 CloudBase 存储信息",
|
|
253794
|
-
description: "查询 CloudBase 云存储信息,支持列出目录文件、获取文件信息、获取临时下载链接等只读操作。返回的文件信息包括文件名、大小、修改时间、下载链接等。注意:action=url 返回的 temporaryUrl 是临时签名链接,有效期由 maxAge 参数决定(默认1小时),不要当作永久公网地址使用。工具还会基于 DescribeEnvs 返回的 Storages[0].CdnDomain 推导 publicUrl,⚠️ 警告:publicUrl 仅在存储桶 ACL 为公有读(所有用户可读)时才能被匿名访问;默认私有读写存储桶返回的 publicUrl 会 403,此时请继续使用 temporaryUrl 或先通过控制台/SDK 将目标路径设置为公有读。\n\n💡 存储桶 ACL 权限管理请使用 permissions 工具:queryPermissions(action=\"getResourcePermission\", resourceType=\"storage\", resourceId=\"bucket-name\") 查询,managePermissions(action=\"updateResourcePermission\", resourceType=\"storage\", resourceId=\"bucket-name\", permission=\"READONLY\") 设置。\n\n📦 CloudBase PG / pgstore 环境:`DescribeEnvs.Storages[]` 列出的 bucket 是旧 NoSQL 后端的,不等于 pgstore bucket。本工具用于查看常规存储;为 PG 浏览器上传准备 bucket 时,请确认目标 bucket 是 pgstore 后端可用的,否则浏览器 `app.storage.from().upload(...)` 会得到 `STORAGE_BUCKET_NOT_FOUND` 并出现 `PUT https://undefined/`。",
|
|
254008
|
+
description: "⚠️ PG 模式环境请使用 queryPgStorage 而非本工具(pgstore 与旧 COS 是两套独立系统)。\n\n查询 CloudBase 云存储信息,支持列出目录文件、获取文件信息、获取临时下载链接等只读操作。返回的文件信息包括文件名、大小、修改时间、下载链接等。注意:action=url 返回的 temporaryUrl 是临时签名链接,有效期由 maxAge 参数决定(默认1小时),不要当作永久公网地址使用。工具还会基于 DescribeEnvs 返回的 Storages[0].CdnDomain 推导 publicUrl,⚠️ 警告:publicUrl 仅在存储桶 ACL 为公有读(所有用户可读)时才能被匿名访问;默认私有读写存储桶返回的 publicUrl 会 403,此时请继续使用 temporaryUrl 或先通过控制台/SDK 将目标路径设置为公有读。\n\n💡 存储桶 ACL 权限管理请使用 permissions 工具:queryPermissions(action=\"getResourcePermission\", resourceType=\"storage\", resourceId=\"bucket-name\") 查询,managePermissions(action=\"updateResourcePermission\", resourceType=\"storage\", resourceId=\"bucket-name\", permission=\"READONLY\") 设置。\n\n📦 CloudBase PG / pgstore 环境:`DescribeEnvs.Storages[]` 列出的 bucket 是旧 NoSQL 后端的,不等于 pgstore bucket。本工具用于查看常规存储;为 PG 浏览器上传准备 bucket 时,请确认目标 bucket 是 pgstore 后端可用的,否则浏览器 `app.storage.from().upload(...)` 会得到 `STORAGE_BUCKET_NOT_FOUND` 并出现 `PUT https://undefined/`。",
|
|
253795
254009
|
inputSchema: queryStorageInputSchema,
|
|
253796
254010
|
annotations: {
|
|
253797
254011
|
readOnlyHint: true,
|
|
@@ -253800,125 +254014,89 @@ function registerStorageTools(server) {
|
|
|
253800
254014
|
}
|
|
253801
254015
|
}, async (args) => {
|
|
253802
254016
|
const input = args;
|
|
253803
|
-
|
|
253804
|
-
|
|
253805
|
-
|
|
253806
|
-
|
|
253807
|
-
const storageService = manager.storage;
|
|
253808
|
-
switch (input.action) {
|
|
253809
|
-
case 'list': {
|
|
253810
|
-
let files;
|
|
253811
|
-
if (storageOverrides?.listFiles) {
|
|
253812
|
-
files = await storageOverrides.listFiles({ cloudPath: input.cloudPath });
|
|
253813
|
-
}
|
|
253814
|
-
else {
|
|
253815
|
-
const result = await storageService.listDirectoryFiles(input.cloudPath);
|
|
253816
|
-
files = result || [];
|
|
253817
|
-
}
|
|
253818
|
-
return {
|
|
253819
|
-
content: [
|
|
253820
|
-
{
|
|
253821
|
-
type: "text",
|
|
253822
|
-
text: JSON.stringify({
|
|
253823
|
-
success: true,
|
|
253824
|
-
data: {
|
|
253825
|
-
action: 'list',
|
|
253826
|
-
cloudPath: input.cloudPath,
|
|
253827
|
-
files,
|
|
253828
|
-
totalCount: files.length
|
|
253829
|
-
},
|
|
253830
|
-
message: `Successfully listed ${files.length} files in directory '${input.cloudPath}'`
|
|
253831
|
-
}, null, 2)
|
|
253832
|
-
}
|
|
253833
|
-
]
|
|
253834
|
-
};
|
|
253835
|
-
}
|
|
253836
|
-
case 'info': {
|
|
253837
|
-
let fileInfo;
|
|
253838
|
-
if (storageOverrides?.getFileInfo) {
|
|
253839
|
-
fileInfo = await storageOverrides.getFileInfo({ cloudPath: input.cloudPath });
|
|
253840
|
-
}
|
|
253841
|
-
else {
|
|
253842
|
-
fileInfo = await storageService.getFileInfo(input.cloudPath);
|
|
253843
|
-
}
|
|
253844
|
-
return {
|
|
253845
|
-
content: [
|
|
253846
|
-
{
|
|
253847
|
-
type: "text",
|
|
253848
|
-
text: JSON.stringify({
|
|
253849
|
-
success: true,
|
|
253850
|
-
data: {
|
|
253851
|
-
action: 'info',
|
|
253852
|
-
cloudPath: input.cloudPath,
|
|
253853
|
-
fileInfo
|
|
253854
|
-
},
|
|
253855
|
-
message: `Successfully retrieved file info for '${input.cloudPath}'`
|
|
253856
|
-
}, null, 2)
|
|
253857
|
-
}
|
|
253858
|
-
]
|
|
253859
|
-
};
|
|
254017
|
+
try {
|
|
254018
|
+
const manager = await getManager();
|
|
254019
|
+
if (!manager) {
|
|
254020
|
+
throw new Error("Failed to initialize CloudBase manager. Please check your credentials and environment configuration.");
|
|
253860
254021
|
}
|
|
253861
|
-
|
|
253862
|
-
|
|
253863
|
-
|
|
253864
|
-
|
|
253865
|
-
|
|
253866
|
-
cloudPath: input.cloudPath
|
|
253867
|
-
|
|
253868
|
-
|
|
253869
|
-
|
|
253870
|
-
|
|
253871
|
-
|
|
253872
|
-
|
|
253873
|
-
|
|
253874
|
-
|
|
253875
|
-
|
|
253876
|
-
|
|
253877
|
-
|
|
253878
|
-
|
|
254022
|
+
const storageService = manager.storage;
|
|
254023
|
+
switch (input.action) {
|
|
254024
|
+
case 'list': {
|
|
254025
|
+
let files;
|
|
254026
|
+
if (storageOverrides?.listFiles) {
|
|
254027
|
+
files = await storageOverrides.listFiles({ cloudPath: input.cloudPath });
|
|
254028
|
+
}
|
|
254029
|
+
else {
|
|
254030
|
+
const result = await storageService.listDirectoryFiles(input.cloudPath);
|
|
254031
|
+
files = result || [];
|
|
254032
|
+
}
|
|
254033
|
+
return {
|
|
254034
|
+
content: [
|
|
254035
|
+
{
|
|
254036
|
+
type: "text",
|
|
254037
|
+
text: JSON.stringify({
|
|
254038
|
+
success: true,
|
|
254039
|
+
data: {
|
|
254040
|
+
action: 'list',
|
|
254041
|
+
cloudPath: input.cloudPath,
|
|
254042
|
+
files,
|
|
254043
|
+
totalCount: files.length
|
|
254044
|
+
},
|
|
254045
|
+
message: `Successfully listed ${files.length} files in directory '${input.cloudPath}'`
|
|
254046
|
+
}, null, 2)
|
|
254047
|
+
}
|
|
254048
|
+
]
|
|
254049
|
+
};
|
|
253879
254050
|
}
|
|
253880
|
-
|
|
253881
|
-
|
|
253882
|
-
|
|
253883
|
-
|
|
253884
|
-
});
|
|
253885
|
-
return {
|
|
253886
|
-
content: [
|
|
253887
|
-
{
|
|
253888
|
-
type: "text",
|
|
253889
|
-
text: JSON.stringify({
|
|
253890
|
-
success: true,
|
|
253891
|
-
data: {
|
|
253892
|
-
action: 'url',
|
|
253893
|
-
cloudPath: input.cloudPath,
|
|
253894
|
-
temporaryUrl,
|
|
253895
|
-
expireTime: `${input.maxAge || 3600}秒`,
|
|
253896
|
-
fileId,
|
|
253897
|
-
storageCdnDomain: publicAccess.storageCdnDomain,
|
|
253898
|
-
publicUrl: publicAccess.publicUrl,
|
|
253899
|
-
note: "temporaryUrl 是临时签名链接,会按 expireTime 过期。publicUrl 基于 DescribeEnvs 返回的 Storages[0].CdnDomain 推导,⚠️ 仅在存储桶 ACL 为公有读(所有用户可读)时才能被匿名访问;默认私有读写存储桶返回的 publicUrl 会 403,此时请继续使用 temporaryUrl 或先将目标路径设置为公有读。"
|
|
253900
|
-
},
|
|
253901
|
-
message: `Successfully generated temporary URL for '${input.cloudPath}'`
|
|
253902
|
-
}, null, 2)
|
|
253903
|
-
}
|
|
253904
|
-
]
|
|
253905
|
-
};
|
|
253906
|
-
}
|
|
253907
|
-
case 'read': {
|
|
253908
|
-
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), STORAGE_READ_TEMP_PREFIX));
|
|
253909
|
-
const localPath = path.join(tempDir, getStorageTempFileName(input.cloudPath));
|
|
253910
|
-
try {
|
|
253911
|
-
if (storageOverrides?.downloadFile) {
|
|
253912
|
-
await storageOverrides.downloadFile({ cloudPath: input.cloudPath, localPath });
|
|
254051
|
+
case 'info': {
|
|
254052
|
+
let fileInfo;
|
|
254053
|
+
if (storageOverrides?.getFileInfo) {
|
|
254054
|
+
fileInfo = await storageOverrides.getFileInfo({ cloudPath: input.cloudPath });
|
|
253913
254055
|
}
|
|
253914
254056
|
else {
|
|
253915
|
-
await storageService.
|
|
254057
|
+
fileInfo = await storageService.getFileInfo(input.cloudPath);
|
|
254058
|
+
}
|
|
254059
|
+
return {
|
|
254060
|
+
content: [
|
|
254061
|
+
{
|
|
254062
|
+
type: "text",
|
|
254063
|
+
text: JSON.stringify({
|
|
254064
|
+
success: true,
|
|
254065
|
+
data: {
|
|
254066
|
+
action: 'info',
|
|
254067
|
+
cloudPath: input.cloudPath,
|
|
254068
|
+
fileInfo
|
|
254069
|
+
},
|
|
254070
|
+
message: `Successfully retrieved file info for '${input.cloudPath}'`
|
|
254071
|
+
}, null, 2)
|
|
254072
|
+
}
|
|
254073
|
+
]
|
|
254074
|
+
};
|
|
254075
|
+
}
|
|
254076
|
+
case 'url': {
|
|
254077
|
+
let temporaryUrl = "";
|
|
254078
|
+
let fileId = "";
|
|
254079
|
+
if (storageOverrides?.getFileUrl) {
|
|
254080
|
+
const urlResult = await storageOverrides.getFileUrl({
|
|
253916
254081
|
cloudPath: input.cloudPath,
|
|
253917
|
-
|
|
254082
|
+
maxAge: input.maxAge || 3600,
|
|
253918
254083
|
});
|
|
254084
|
+
temporaryUrl = urlResult.url;
|
|
254085
|
+
fileId = urlResult.fileId || "";
|
|
254086
|
+
}
|
|
254087
|
+
else {
|
|
254088
|
+
const result = await storageService.getTemporaryUrl([{
|
|
254089
|
+
cloudPath: input.cloudPath,
|
|
254090
|
+
maxAge: input.maxAge || 3600
|
|
254091
|
+
}]);
|
|
254092
|
+
temporaryUrl = result[0]?.url || "";
|
|
254093
|
+
fileId = result[0]?.fileId || "";
|
|
253919
254094
|
}
|
|
253920
|
-
const
|
|
253921
|
-
|
|
254095
|
+
const publicAccess = await resolveStoragePublicAccess({
|
|
254096
|
+
cloudPath: input.cloudPath,
|
|
254097
|
+
cloudBaseOptions,
|
|
254098
|
+
manager,
|
|
254099
|
+
});
|
|
253922
254100
|
return {
|
|
253923
254101
|
content: [
|
|
253924
254102
|
{
|
|
@@ -253926,33 +254104,80 @@ function registerStorageTools(server) {
|
|
|
253926
254104
|
text: JSON.stringify({
|
|
253927
254105
|
success: true,
|
|
253928
254106
|
data: {
|
|
253929
|
-
action: '
|
|
254107
|
+
action: 'url',
|
|
253930
254108
|
cloudPath: input.cloudPath,
|
|
253931
|
-
|
|
253932
|
-
|
|
253933
|
-
|
|
253934
|
-
|
|
254109
|
+
temporaryUrl,
|
|
254110
|
+
expireTime: `${input.maxAge || 3600}秒`,
|
|
254111
|
+
fileId,
|
|
254112
|
+
storageCdnDomain: publicAccess.storageCdnDomain,
|
|
254113
|
+
publicUrl: publicAccess.publicUrl,
|
|
254114
|
+
note: "temporaryUrl 是临时签名链接,会按 expireTime 过期。publicUrl 基于 DescribeEnvs 返回的 Storages[0].CdnDomain 推导,⚠️ 仅在存储桶 ACL 为公有读(所有用户可读)时才能被匿名访问;默认私有读写存储桶返回的 publicUrl 会 403,此时请继续使用 temporaryUrl 或先将目标路径设置为公有读。"
|
|
253935
254115
|
},
|
|
253936
|
-
message:
|
|
253937
|
-
? `Successfully read text content for '${input.cloudPath}' (truncated to ${MAX_INLINE_TEXT_BYTES} bytes)`
|
|
253938
|
-
: `Successfully read text content for '${input.cloudPath}'`
|
|
254116
|
+
message: `Successfully generated temporary URL for '${input.cloudPath}'`
|
|
253939
254117
|
}, null, 2)
|
|
253940
254118
|
}
|
|
253941
254119
|
]
|
|
253942
254120
|
};
|
|
253943
254121
|
}
|
|
253944
|
-
|
|
253945
|
-
await fs.
|
|
254122
|
+
case 'read': {
|
|
254123
|
+
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), STORAGE_READ_TEMP_PREFIX));
|
|
254124
|
+
const localPath = path.join(tempDir, getStorageTempFileName(input.cloudPath));
|
|
254125
|
+
try {
|
|
254126
|
+
if (storageOverrides?.downloadFile) {
|
|
254127
|
+
await storageOverrides.downloadFile({ cloudPath: input.cloudPath, localPath });
|
|
254128
|
+
}
|
|
254129
|
+
else {
|
|
254130
|
+
await storageService.downloadFile({
|
|
254131
|
+
cloudPath: input.cloudPath,
|
|
254132
|
+
localPath
|
|
254133
|
+
});
|
|
254134
|
+
}
|
|
254135
|
+
const buffer = await fs.readFile(localPath);
|
|
254136
|
+
const decoded = decodeInlineTextContent(buffer);
|
|
254137
|
+
return {
|
|
254138
|
+
content: [
|
|
254139
|
+
{
|
|
254140
|
+
type: "text",
|
|
254141
|
+
text: JSON.stringify({
|
|
254142
|
+
success: true,
|
|
254143
|
+
data: {
|
|
254144
|
+
action: 'read',
|
|
254145
|
+
cloudPath: input.cloudPath,
|
|
254146
|
+
content: decoded.content,
|
|
254147
|
+
encoding: decoded.encoding,
|
|
254148
|
+
sizeBytes: decoded.sizeBytes,
|
|
254149
|
+
truncated: decoded.truncated
|
|
254150
|
+
},
|
|
254151
|
+
message: decoded.truncated
|
|
254152
|
+
? `Successfully read text content for '${input.cloudPath}' (truncated to ${MAX_INLINE_TEXT_BYTES} bytes)`
|
|
254153
|
+
: `Successfully read text content for '${input.cloudPath}'`
|
|
254154
|
+
}, null, 2)
|
|
254155
|
+
}
|
|
254156
|
+
]
|
|
254157
|
+
};
|
|
254158
|
+
}
|
|
254159
|
+
finally {
|
|
254160
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
|
254161
|
+
}
|
|
253946
254162
|
}
|
|
254163
|
+
default:
|
|
254164
|
+
throw new Error(`Unsupported action: ${input.action}`);
|
|
253947
254165
|
}
|
|
253948
|
-
|
|
253949
|
-
|
|
254166
|
+
}
|
|
254167
|
+
catch (error) {
|
|
254168
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
254169
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
254170
|
+
success: false,
|
|
254171
|
+
message: `queryStorage 操作失败: ${message}`,
|
|
254172
|
+
action: input.action,
|
|
254173
|
+
cloudPath: input.cloudPath,
|
|
254174
|
+
});
|
|
253950
254175
|
}
|
|
253951
254176
|
});
|
|
253952
254177
|
// Tool 2: manageStorage - 管理存储文件(写操作)
|
|
253953
254178
|
server.registerTool("manageStorage", {
|
|
253954
254179
|
title: "管理 CloudBase 存储文件",
|
|
253955
|
-
description: "管理 CloudBase 云存储文件,仅用于 COS/Storage 对象,不用于静态网站托管。支持上传文件/目录、下载文件/目录、删除文件/目录等操作。删除操作需要设置force=true进行确认,防止误删除重要文件。注意:上传后返回的 temporaryUrl 是临时签名链接,1小时后过期,不要当作永久公网地址写入配置或持久化存储。工具还会基于 DescribeEnvs 返回的 Storages[0].CdnDomain 推导 publicUrl,⚠️ 警告:publicUrl 仅在存储桶 ACL 为公有读(所有用户可读)时才能被匿名访问;默认私有读写存储桶返回的 publicUrl 会 403,此时请继续使用 temporaryUrl 或先通过控制台/SDK 将目标路径设置为公有读。\n\n💡 存储桶 ACL 权限管理请使用 permissions 工具:queryPermissions(action=\"getResourcePermission\", resourceType=\"storage\", resourceId=\"bucket-name\") 查询,managePermissions(action=\"updateResourcePermission\", resourceType=\"storage\", resourceId=\"bucket-name\", permission=\"READONLY\") 设置。\n\n📦 CloudBase PG / pgstore 桶必须先创建后使用(与 Supabase Storage 一致:upload 前 bucket 必须存在)。浏览器 SDK `app.storage.from().upload(path, file)` 不会自动建桶,且 `path` 的第一段就是 bucket 名(例如 `covers/foo.png` → bucket=`covers`);`from('covers')` 这个参数当前不会被拼到 path 里。如果上传时浏览器看到 `STORAGE_BUCKET_NOT_FOUND` 或 `PUT https://undefined/`(DevTools 表现为 `net::ERR_NAME_NOT_RESOLVED`),先用本工具或控制台确认 / 创建对应的 pgstore bucket,再让前端重试上传,不要让前端把上传失败静默吞掉。`DescribeEnvs.Storages[]` 返回的旧 NoSQL bucket(形如 `<hash>-<envId>-<appId>`)不是可用的 pgstore bucket,切勿当作默认目标使用。",
|
|
254180
|
+
description: "⚠️ PG 模式环境请使用 queryPgStorage 而非本工具(pgstore 与旧 COS 是两套独立系统)。\n\n管理 CloudBase 云存储文件,仅用于 COS/Storage 对象,不用于静态网站托管。支持上传文件/目录、下载文件/目录、删除文件/目录等操作。删除操作需要设置force=true进行确认,防止误删除重要文件。注意:上传后返回的 temporaryUrl 是临时签名链接,1小时后过期,不要当作永久公网地址写入配置或持久化存储。工具还会基于 DescribeEnvs 返回的 Storages[0].CdnDomain 推导 publicUrl,⚠️ 警告:publicUrl 仅在存储桶 ACL 为公有读(所有用户可读)时才能被匿名访问;默认私有读写存储桶返回的 publicUrl 会 403,此时请继续使用 temporaryUrl 或先通过控制台/SDK 将目标路径设置为公有读。\n\n💡 存储桶 ACL 权限管理请使用 permissions 工具:queryPermissions(action=\"getResourcePermission\", resourceType=\"storage\", resourceId=\"bucket-name\") 查询,managePermissions(action=\"updateResourcePermission\", resourceType=\"storage\", resourceId=\"bucket-name\", permission=\"READONLY\") 设置。\n\n📦 CloudBase PG / pgstore 桶必须先创建后使用(与 Supabase Storage 一致:upload 前 bucket 必须存在)。浏览器 SDK `app.storage.from().upload(path, file)` 不会自动建桶,且 `path` 的第一段就是 bucket 名(例如 `covers/foo.png` → bucket=`covers`);`from('covers')` 这个参数当前不会被拼到 path 里。如果上传时浏览器看到 `STORAGE_BUCKET_NOT_FOUND` 或 `PUT https://undefined/`(DevTools 表现为 `net::ERR_NAME_NOT_RESOLVED`),先用本工具或控制台确认 / 创建对应的 pgstore bucket,再让前端重试上传,不要让前端把上传失败静默吞掉。`DescribeEnvs.Storages[]` 返回的旧 NoSQL bucket(形如 `<hash>-<envId>-<appId>`)不是可用的 pgstore bucket,切勿当作默认目标使用。",
|
|
253956
254181
|
inputSchema: manageStorageInputSchema,
|
|
253957
254182
|
annotations: {
|
|
253958
254183
|
readOnlyHint: false,
|
|
@@ -253963,196 +254188,207 @@ function registerStorageTools(server) {
|
|
|
253963
254188
|
}
|
|
253964
254189
|
}, async (args) => {
|
|
253965
254190
|
const input = args;
|
|
253966
|
-
|
|
253967
|
-
|
|
253968
|
-
|
|
253969
|
-
|
|
253970
|
-
|
|
253971
|
-
|
|
253972
|
-
|
|
253973
|
-
|
|
253974
|
-
|
|
253975
|
-
|
|
253976
|
-
if (
|
|
253977
|
-
|
|
254191
|
+
try {
|
|
254192
|
+
const manager = await getManager();
|
|
254193
|
+
if (!manager) {
|
|
254194
|
+
throw new Error("Failed to initialize CloudBase manager. Please check your credentials and environment configuration.");
|
|
254195
|
+
}
|
|
254196
|
+
const storageService = manager.storage;
|
|
254197
|
+
switch (input.action) {
|
|
254198
|
+
case 'upload': {
|
|
254199
|
+
const localPath = input.localPath;
|
|
254200
|
+
const cloudPath = input.cloudPath;
|
|
254201
|
+
if (input.isDirectory) {
|
|
254202
|
+
if (storageOverrides?.uploadDirectory) {
|
|
254203
|
+
await storageOverrides.uploadDirectory({ localPath, cloudPath });
|
|
254204
|
+
}
|
|
254205
|
+
else {
|
|
254206
|
+
await storageService.uploadDirectory({
|
|
254207
|
+
localPath,
|
|
254208
|
+
cloudPath,
|
|
254209
|
+
onProgress: (progressData) => {
|
|
254210
|
+
console.log("Upload directory progress:", progressData);
|
|
254211
|
+
}
|
|
254212
|
+
});
|
|
254213
|
+
}
|
|
253978
254214
|
}
|
|
253979
254215
|
else {
|
|
253980
|
-
|
|
253981
|
-
localPath,
|
|
253982
|
-
|
|
253983
|
-
|
|
253984
|
-
|
|
253985
|
-
|
|
253986
|
-
|
|
254216
|
+
if (storageOverrides?.uploadFile) {
|
|
254217
|
+
await storageOverrides.uploadFile({ localPath, cloudPath });
|
|
254218
|
+
}
|
|
254219
|
+
else {
|
|
254220
|
+
await storageService.uploadFile({
|
|
254221
|
+
localPath,
|
|
254222
|
+
cloudPath,
|
|
254223
|
+
onProgress: (progressData) => {
|
|
254224
|
+
console.log("Upload file progress:", progressData);
|
|
254225
|
+
}
|
|
254226
|
+
});
|
|
254227
|
+
}
|
|
253987
254228
|
}
|
|
253988
|
-
|
|
253989
|
-
|
|
253990
|
-
|
|
253991
|
-
|
|
254229
|
+
// 上传成功后获取临时 URL 和公网访问信息
|
|
254230
|
+
let temporaryUrl = "";
|
|
254231
|
+
let fileId = "";
|
|
254232
|
+
if (storageOverrides?.getFileUrl) {
|
|
254233
|
+
const urlResult = await storageOverrides.getFileUrl({
|
|
254234
|
+
cloudPath: input.cloudPath,
|
|
254235
|
+
maxAge: 3600,
|
|
254236
|
+
});
|
|
254237
|
+
temporaryUrl = urlResult.url;
|
|
254238
|
+
fileId = urlResult.fileId || "";
|
|
253992
254239
|
}
|
|
253993
254240
|
else {
|
|
253994
|
-
|
|
253995
|
-
|
|
253996
|
-
|
|
253997
|
-
|
|
253998
|
-
|
|
253999
|
-
|
|
254000
|
-
|
|
254241
|
+
try {
|
|
254242
|
+
const fileUrls = await storageService.getTemporaryUrl([{
|
|
254243
|
+
cloudPath: input.cloudPath,
|
|
254244
|
+
maxAge: 3600
|
|
254245
|
+
}]);
|
|
254246
|
+
temporaryUrl = fileUrls[0]?.url || "";
|
|
254247
|
+
fileId = fileUrls[0]?.fileId || "";
|
|
254248
|
+
}
|
|
254249
|
+
catch {
|
|
254250
|
+
// StorageOverrides 下 getTemporaryUrl 可能不可用
|
|
254251
|
+
}
|
|
254001
254252
|
}
|
|
254002
|
-
|
|
254003
|
-
// 上传成功后获取临时 URL 和公网访问信息
|
|
254004
|
-
let temporaryUrl = "";
|
|
254005
|
-
let fileId = "";
|
|
254006
|
-
if (storageOverrides?.getFileUrl) {
|
|
254007
|
-
const urlResult = await storageOverrides.getFileUrl({
|
|
254008
|
-
cloudPath: input.cloudPath,
|
|
254009
|
-
maxAge: 3600,
|
|
254010
|
-
});
|
|
254011
|
-
temporaryUrl = urlResult.url;
|
|
254012
|
-
fileId = urlResult.fileId || "";
|
|
254013
|
-
}
|
|
254014
|
-
else {
|
|
254253
|
+
let publicAccess = {};
|
|
254015
254254
|
try {
|
|
254016
|
-
|
|
254017
|
-
|
|
254018
|
-
|
|
254019
|
-
|
|
254020
|
-
|
|
254021
|
-
fileId = fileUrls[0]?.fileId || "";
|
|
254255
|
+
publicAccess = await resolveStoragePublicAccess({
|
|
254256
|
+
cloudPath: input.cloudPath,
|
|
254257
|
+
cloudBaseOptions,
|
|
254258
|
+
manager,
|
|
254259
|
+
});
|
|
254022
254260
|
}
|
|
254023
254261
|
catch {
|
|
254024
|
-
//
|
|
254262
|
+
// DescribeEnvs 可能不支持(IDE 模式下会绕过)
|
|
254263
|
+
publicAccess = {};
|
|
254025
254264
|
}
|
|
254265
|
+
return {
|
|
254266
|
+
content: [
|
|
254267
|
+
{
|
|
254268
|
+
type: "text",
|
|
254269
|
+
text: JSON.stringify({
|
|
254270
|
+
success: true,
|
|
254271
|
+
data: {
|
|
254272
|
+
action: 'upload',
|
|
254273
|
+
localPath: input.localPath,
|
|
254274
|
+
cloudPath: input.cloudPath,
|
|
254275
|
+
isDirectory: input.isDirectory,
|
|
254276
|
+
temporaryUrl,
|
|
254277
|
+
expireTime: "1小时",
|
|
254278
|
+
storageCdnDomain: publicAccess.storageCdnDomain,
|
|
254279
|
+
publicUrl: publicAccess.publicUrl,
|
|
254280
|
+
note: "temporaryUrl 是临时签名链接,1小时后过期,不要当作永久公网地址写入配置或持久化存储。publicUrl 基于 DescribeEnvs 返回的 Storages[0].CdnDomain 推导,⚠️ 仅在存储桶 ACL 为公有读(所有用户可读)时才能被匿名访问;默认私有读写存储桶返回的 publicUrl 会 403,此时请继续使用 temporaryUrl 或先将目标路径设置为公有读。"
|
|
254281
|
+
},
|
|
254282
|
+
message: `Successfully uploaded ${input.isDirectory ? 'directory' : 'file'} from '${input.localPath}' to '${input.cloudPath}'`
|
|
254283
|
+
}, null, 2)
|
|
254284
|
+
}
|
|
254285
|
+
]
|
|
254286
|
+
};
|
|
254026
254287
|
}
|
|
254027
|
-
|
|
254028
|
-
|
|
254029
|
-
|
|
254030
|
-
|
|
254031
|
-
|
|
254032
|
-
|
|
254033
|
-
|
|
254034
|
-
|
|
254035
|
-
|
|
254036
|
-
|
|
254037
|
-
|
|
254038
|
-
|
|
254039
|
-
return {
|
|
254040
|
-
content: [
|
|
254041
|
-
{
|
|
254042
|
-
type: "text",
|
|
254043
|
-
text: JSON.stringify({
|
|
254044
|
-
success: true,
|
|
254045
|
-
data: {
|
|
254046
|
-
action: 'upload',
|
|
254047
|
-
localPath: input.localPath,
|
|
254048
|
-
cloudPath: input.cloudPath,
|
|
254049
|
-
isDirectory: input.isDirectory,
|
|
254050
|
-
temporaryUrl,
|
|
254051
|
-
expireTime: "1小时",
|
|
254052
|
-
storageCdnDomain: publicAccess.storageCdnDomain,
|
|
254053
|
-
publicUrl: publicAccess.publicUrl,
|
|
254054
|
-
note: "temporaryUrl 是临时签名链接,1小时后过期,不要当作永久公网地址写入配置或持久化存储。publicUrl 基于 DescribeEnvs 返回的 Storages[0].CdnDomain 推导,⚠️ 仅在存储桶 ACL 为公有读(所有用户可读)时才能被匿名访问;默认私有读写存储桶返回的 publicUrl 会 403,此时请继续使用 temporaryUrl 或先将目标路径设置为公有读。"
|
|
254055
|
-
},
|
|
254056
|
-
message: `Successfully uploaded ${input.isDirectory ? 'directory' : 'file'} from '${input.localPath}' to '${input.cloudPath}'`
|
|
254057
|
-
}, null, 2)
|
|
254288
|
+
case 'download': {
|
|
254289
|
+
const dlCloudPath = input.cloudPath;
|
|
254290
|
+
const dlLocalPath = input.localPath;
|
|
254291
|
+
if (input.isDirectory) {
|
|
254292
|
+
if (storageOverrides?.downloadDirectory) {
|
|
254293
|
+
await storageOverrides.downloadDirectory({ cloudPath: dlCloudPath, localPath: dlLocalPath });
|
|
254294
|
+
}
|
|
254295
|
+
else {
|
|
254296
|
+
await storageService.downloadDirectory({
|
|
254297
|
+
cloudPath: dlCloudPath,
|
|
254298
|
+
localPath: dlLocalPath
|
|
254299
|
+
});
|
|
254058
254300
|
}
|
|
254059
|
-
]
|
|
254060
|
-
};
|
|
254061
|
-
}
|
|
254062
|
-
case 'download': {
|
|
254063
|
-
const dlCloudPath = input.cloudPath;
|
|
254064
|
-
const dlLocalPath = input.localPath;
|
|
254065
|
-
if (input.isDirectory) {
|
|
254066
|
-
if (storageOverrides?.downloadDirectory) {
|
|
254067
|
-
await storageOverrides.downloadDirectory({ cloudPath: dlCloudPath, localPath: dlLocalPath });
|
|
254068
|
-
}
|
|
254069
|
-
else {
|
|
254070
|
-
await storageService.downloadDirectory({
|
|
254071
|
-
cloudPath: dlCloudPath,
|
|
254072
|
-
localPath: dlLocalPath
|
|
254073
|
-
});
|
|
254074
|
-
}
|
|
254075
|
-
}
|
|
254076
|
-
else {
|
|
254077
|
-
if (storageOverrides?.downloadFile) {
|
|
254078
|
-
await storageOverrides.downloadFile({ cloudPath: dlCloudPath, localPath: dlLocalPath });
|
|
254079
254301
|
}
|
|
254080
254302
|
else {
|
|
254081
|
-
|
|
254082
|
-
cloudPath: dlCloudPath,
|
|
254083
|
-
localPath: dlLocalPath
|
|
254084
|
-
});
|
|
254085
|
-
}
|
|
254086
|
-
}
|
|
254087
|
-
return {
|
|
254088
|
-
content: [
|
|
254089
|
-
{
|
|
254090
|
-
type: "text",
|
|
254091
|
-
text: JSON.stringify({
|
|
254092
|
-
success: true,
|
|
254093
|
-
data: {
|
|
254094
|
-
action: 'download',
|
|
254095
|
-
cloudPath: input.cloudPath,
|
|
254096
|
-
localPath: input.localPath,
|
|
254097
|
-
isDirectory: input.isDirectory
|
|
254098
|
-
},
|
|
254099
|
-
message: `Successfully downloaded ${input.isDirectory ? 'directory' : 'file'} from '${input.cloudPath}' to '${input.localPath}'`
|
|
254100
|
-
}, null, 2)
|
|
254303
|
+
if (storageOverrides?.downloadFile) {
|
|
254304
|
+
await storageOverrides.downloadFile({ cloudPath: dlCloudPath, localPath: dlLocalPath });
|
|
254101
254305
|
}
|
|
254102
|
-
|
|
254103
|
-
|
|
254104
|
-
|
|
254105
|
-
|
|
254106
|
-
|
|
254306
|
+
else {
|
|
254307
|
+
await storageService.downloadFile({
|
|
254308
|
+
cloudPath: dlCloudPath,
|
|
254309
|
+
localPath: dlLocalPath
|
|
254310
|
+
});
|
|
254311
|
+
}
|
|
254312
|
+
}
|
|
254107
254313
|
return {
|
|
254108
254314
|
content: [
|
|
254109
254315
|
{
|
|
254110
254316
|
type: "text",
|
|
254111
254317
|
text: JSON.stringify({
|
|
254112
|
-
success:
|
|
254113
|
-
|
|
254114
|
-
|
|
254318
|
+
success: true,
|
|
254319
|
+
data: {
|
|
254320
|
+
action: 'download',
|
|
254321
|
+
cloudPath: input.cloudPath,
|
|
254322
|
+
localPath: input.localPath,
|
|
254323
|
+
isDirectory: input.isDirectory
|
|
254324
|
+
},
|
|
254325
|
+
message: `Successfully downloaded ${input.isDirectory ? 'directory' : 'file'} from '${input.cloudPath}' to '${input.localPath}'`
|
|
254115
254326
|
}, null, 2)
|
|
254116
254327
|
}
|
|
254117
254328
|
]
|
|
254118
254329
|
};
|
|
254119
254330
|
}
|
|
254120
|
-
|
|
254121
|
-
if (
|
|
254122
|
-
|
|
254123
|
-
|
|
254124
|
-
|
|
254125
|
-
|
|
254331
|
+
case 'delete': {
|
|
254332
|
+
if (!input.force) {
|
|
254333
|
+
return {
|
|
254334
|
+
content: [
|
|
254335
|
+
{
|
|
254336
|
+
type: "text",
|
|
254337
|
+
text: JSON.stringify({
|
|
254338
|
+
success: false,
|
|
254339
|
+
error: "Delete operation requires confirmation",
|
|
254340
|
+
message: "Please set force: true to confirm deletion. This action cannot be undone."
|
|
254341
|
+
}, null, 2)
|
|
254342
|
+
}
|
|
254343
|
+
]
|
|
254344
|
+
};
|
|
254126
254345
|
}
|
|
254127
|
-
|
|
254128
|
-
|
|
254129
|
-
|
|
254130
|
-
|
|
254346
|
+
if (input.isDirectory) {
|
|
254347
|
+
if (storageOverrides?.deleteDirectory) {
|
|
254348
|
+
await storageOverrides.deleteDirectory({ cloudPath: input.cloudPath });
|
|
254349
|
+
}
|
|
254350
|
+
else {
|
|
254351
|
+
await storageService.deleteDirectory(input.cloudPath);
|
|
254352
|
+
}
|
|
254131
254353
|
}
|
|
254132
254354
|
else {
|
|
254133
|
-
|
|
254355
|
+
if (storageOverrides?.deleteFiles) {
|
|
254356
|
+
await storageOverrides.deleteFiles({ cloudPaths: [input.cloudPath] });
|
|
254357
|
+
}
|
|
254358
|
+
else {
|
|
254359
|
+
await storageService.deleteFile([input.cloudPath]);
|
|
254360
|
+
}
|
|
254134
254361
|
}
|
|
254362
|
+
return {
|
|
254363
|
+
content: [
|
|
254364
|
+
{
|
|
254365
|
+
type: "text",
|
|
254366
|
+
text: JSON.stringify({
|
|
254367
|
+
success: true,
|
|
254368
|
+
data: {
|
|
254369
|
+
action: 'delete',
|
|
254370
|
+
cloudPath: input.cloudPath,
|
|
254371
|
+
isDirectory: input.isDirectory,
|
|
254372
|
+
deleted: true
|
|
254373
|
+
},
|
|
254374
|
+
message: `Successfully deleted ${input.isDirectory ? 'directory' : 'file'} '${input.cloudPath}'`
|
|
254375
|
+
}, null, 2)
|
|
254376
|
+
}
|
|
254377
|
+
]
|
|
254378
|
+
};
|
|
254135
254379
|
}
|
|
254136
|
-
|
|
254137
|
-
|
|
254138
|
-
{
|
|
254139
|
-
type: "text",
|
|
254140
|
-
text: JSON.stringify({
|
|
254141
|
-
success: true,
|
|
254142
|
-
data: {
|
|
254143
|
-
action: 'delete',
|
|
254144
|
-
cloudPath: input.cloudPath,
|
|
254145
|
-
isDirectory: input.isDirectory,
|
|
254146
|
-
deleted: true
|
|
254147
|
-
},
|
|
254148
|
-
message: `Successfully deleted ${input.isDirectory ? 'directory' : 'file'} '${input.cloudPath}'`
|
|
254149
|
-
}, null, 2)
|
|
254150
|
-
}
|
|
254151
|
-
]
|
|
254152
|
-
};
|
|
254380
|
+
default:
|
|
254381
|
+
throw new Error(`Unsupported action: ${input.action}`);
|
|
254153
254382
|
}
|
|
254154
|
-
|
|
254155
|
-
|
|
254383
|
+
}
|
|
254384
|
+
catch (error) {
|
|
254385
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
254386
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
254387
|
+
success: false,
|
|
254388
|
+
message: `manageStorage 操作失败: ${message}`,
|
|
254389
|
+
action: input.action,
|
|
254390
|
+
cloudPath: input.cloudPath,
|
|
254391
|
+
});
|
|
254156
254392
|
}
|
|
254157
254393
|
});
|
|
254158
254394
|
}
|