@cloudbase/cloudbase-mcp 2.33.1 → 2.33.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +2 -2
- package/dist/index.cjs +1467 -1097
- package/dist/index.js +721 -88
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2109,6 +2109,7 @@ const storage_js_1 = __webpack_require__(3138);
|
|
|
2109
2109
|
const types_js_1 = __webpack_require__(2344);
|
|
2110
2110
|
const capi_js_1 = __webpack_require__(8900);
|
|
2111
2111
|
const cloudrun_js_1 = __webpack_require__(3277);
|
|
2112
|
+
const deploy_js_1 = __webpack_require__(3668);
|
|
2112
2113
|
const dataModel_js_1 = __webpack_require__(2722);
|
|
2113
2114
|
const gateway_js_1 = __webpack_require__(9921);
|
|
2114
2115
|
const agents_js_1 = __webpack_require__(8409);
|
|
@@ -2136,6 +2137,7 @@ const DEFAULT_PLUGINS = [
|
|
|
2136
2137
|
"setup",
|
|
2137
2138
|
"rag",
|
|
2138
2139
|
"cloudrun",
|
|
2140
|
+
"deploy",
|
|
2139
2141
|
"gateway",
|
|
2140
2142
|
"app-auth",
|
|
2141
2143
|
"apps",
|
|
@@ -2189,6 +2191,7 @@ const AVAILABLE_PLUGINS = {
|
|
|
2189
2191
|
agents: { name: "agents", register: agents_js_1.registerAgentTools },
|
|
2190
2192
|
apps: { name: "apps", register: apps_js_1.registerAppTools },
|
|
2191
2193
|
cloudrun: { name: "cloudrun", register: cloudrun_js_1.registerCloudRunTools },
|
|
2194
|
+
deploy: { name: "deploy", register: deploy_js_1.registerDeployTools },
|
|
2192
2195
|
capi: { name: "capi", register: capi_js_1.registerCapiTools },
|
|
2193
2196
|
"msg-push": { name: "msg-push", register: msg_push_js_1.registerMsgPushTools },
|
|
2194
2197
|
};
|
|
@@ -3932,7 +3935,7 @@ function registerAppTools(server) {
|
|
|
3932
3935
|
var __webpack_unused_export__;
|
|
3933
3936
|
|
|
3934
3937
|
__webpack_unused_export__ = ({ value: true });
|
|
3935
|
-
exports.rg = void 0;
|
|
3938
|
+
exports.rg = exports.AV = void 0;
|
|
3936
3939
|
__webpack_unused_export__ = assertTcbCloudRunActionAllowed;
|
|
3937
3940
|
__webpack_unused_export__ = resolveCloudApiRegionAndParams;
|
|
3938
3941
|
__webpack_unused_export__ = removeEmptyStringParams;
|
|
@@ -3946,7 +3949,7 @@ const tcb_action_index_js_1 = __webpack_require__(2550);
|
|
|
3946
3949
|
const CATEGORY = "cloud-api";
|
|
3947
3950
|
const CLOUDBASE_CONTROL_PLANE_DOC_URL = "https://cloud.tencent.com/document/product/876/34809";
|
|
3948
3951
|
const CLOUDBASE_DEPENDENCY_API_DOC_URL = "https://cloud.tencent.com/document/product/876/34808";
|
|
3949
|
-
|
|
3952
|
+
exports.AV = [
|
|
3950
3953
|
"tcb",
|
|
3951
3954
|
"tcbr",
|
|
3952
3955
|
"scf",
|
|
@@ -3955,6 +3958,8 @@ const ALLOWED_SERVICES = [
|
|
|
3955
3958
|
"lowcode",
|
|
3956
3959
|
"cdn",
|
|
3957
3960
|
"vpc",
|
|
3961
|
+
"monitor",
|
|
3962
|
+
"postgres",
|
|
3958
3963
|
];
|
|
3959
3964
|
/**
|
|
3960
3965
|
* Legacy tcb small-tenant CloudRun (CloudBase Run) API family — blocked.
|
|
@@ -4076,6 +4081,9 @@ function buildCapiDocGuidance(service) {
|
|
|
4076
4081
|
if (service === "tcb" || service === "tcbr" || service === "lowcode" || service === "scf") {
|
|
4077
4082
|
return `优先查阅 CloudBase API 概览 ${CLOUDBASE_CONTROL_PLANE_DOC_URL} 与云开发依赖资源接口指引 ${CLOUDBASE_DEPENDENCY_API_DOC_URL}。`;
|
|
4078
4083
|
}
|
|
4084
|
+
if (service === "monitor") {
|
|
4085
|
+
return `请优先核对云监控(腾讯云可观测平台)官方 API 文档:API 概览 https://cloud.tencent.com/document/product/649/30343 ,单 Action 详细文档在 https://cloud.tencent.com/document/api/248/ 产品线下。`;
|
|
4086
|
+
}
|
|
4079
4087
|
return `请优先核对对应官方云 API 文档;若你的场景其实是通过 HTTP 协议直接集成 auth/functions/cloudrun/storage/mysqldb 等 CloudBase 业务 API,请优先使用 OpenAPI / Swagger 或 searchKnowledgeBase(mode="openapi"),不要继续猜测管控面 Action。`;
|
|
4080
4088
|
}
|
|
4081
4089
|
/** Match CAM / authorization failures from Tencent Cloud control-plane APIs. */
|
|
@@ -4181,7 +4189,7 @@ function registerCapiTools(server) {
|
|
|
4181
4189
|
const getManager = () => (0, cloudbase_manager_js_1.getCloudBaseManager)({ cloudBaseOptions, requireEnvId: false });
|
|
4182
4190
|
server.registerTool?.("callCloudApi", {
|
|
4183
4191
|
title: "调用云API",
|
|
4184
|
-
description: `通用的云 API 调用工具,主要用于 CloudBase / 腾讯云管控面与依赖资源相关 API
|
|
4192
|
+
description: `通用的云 API 调用工具,主要用于 CloudBase / 腾讯云管控面与依赖资源相关 API 调用。**调用前必读接口索引** https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/api-reference.md (每日自动同步的 Action 级索引,含 rate limit;先查此索引确认 service/Action/参数,避免猜测 Action 名称;索引未覆盖的产品再去该产品官方 API 文档核对)。如果你的目标是通过 HTTP 协议直接集成 auth/functions/cloudrun/storage/mysqldb 等 CloudBase 业务 API,请不要优先使用 callCloudApi,而应优先查看对应 OpenAPI / Swagger。现有 OpenAPI / Swagger 能力不是通用的管控面 Action 集合;管控面 API 请优先参考 CloudBase API 概览 ${CLOUDBASE_CONTROL_PLANE_DOC_URL} 与云开发依赖资源接口指引 ${CLOUDBASE_DEPENDENCY_API_DOC_URL}。对于 tcb service,常用 Action 分类如下:
|
|
4185
4193
|
|
|
4186
4194
|
**环境管理**: \`CreateEnv\`、\`ModifyEnv\`、\`DescribeEnvs\`、\`DestroyEnv\`
|
|
4187
4195
|
**用户管理**: \`CreateUser\`、\`ModifyUser\`、\`DescribeUserList\`、\`DeleteUsers\`
|
|
@@ -4196,8 +4204,8 @@ function registerCapiTools(server) {
|
|
|
4196
4204
|
销毁环境时,常见做法是至少带上 \`EnvId\` 和 \`BypassCheck: true\`,如果环境已经处于隔离期再按文档补 \`IsForce: true\`。`,
|
|
4197
4205
|
inputSchema: {
|
|
4198
4206
|
service: zod_1.z
|
|
4199
|
-
.enum(
|
|
4200
|
-
.describe("选择要访问的服务。可选:tcb、tcbr、scf、sts、cam、lowcode、cdn、vpc
|
|
4207
|
+
.enum(exports.AV)
|
|
4208
|
+
.describe("选择要访问的服务。可选:tcb、tcbr、scf、sts、cam、lowcode、cdn、vpc、monitor(云监控/告警,version 需传 2018-07-24)、postgres(云数据库 PostgreSQL,version 需传 2017-03-12)。对于 tcb / scf / lowcode 等 CloudBase 管控面 Action,请优先查官方文档,不要直接猜测 Action。云托管统一走 tcbr(version 需传 2022-02-17)。"),
|
|
4201
4209
|
action: zod_1.z
|
|
4202
4210
|
.string()
|
|
4203
4211
|
.min(1)
|
|
@@ -4205,7 +4213,7 @@ function registerCapiTools(server) {
|
|
|
4205
4213
|
version: zod_1.z
|
|
4206
4214
|
.string()
|
|
4207
4215
|
.optional()
|
|
4208
|
-
.describe("API 版本(可选)。缺省时按 service 使用 SDK 内置默认版本;tcbr 必须传 \"2022-02-17\"(否则请求缺少 X-TC-Version
|
|
4216
|
+
.describe("API 版本(可选)。缺省时按 service 使用 SDK 内置默认版本;tcbr 必须传 \"2022-02-17\"(否则请求缺少 X-TC-Version 会失败),monitor 必须传 \"2018-07-24\"、postgres 必须传 \"2017-03-12\"(这两个 service 无内置默认版本,不传会失败)。示例:service=\"tcbr\", version=\"2022-02-17\", action=\"CreateCloudRunEnv\", params={EnvId:\"env-xxx\",PackageType:\"Standard\"}。"),
|
|
4209
4217
|
params: zod_1.z
|
|
4210
4218
|
.record(zod_1.z.any())
|
|
4211
4219
|
.optional()
|
|
@@ -4223,8 +4231,8 @@ function registerCapiTools(server) {
|
|
|
4223
4231
|
category: CATEGORY,
|
|
4224
4232
|
},
|
|
4225
4233
|
}, async ({ service, action, params, version, region, }) => {
|
|
4226
|
-
if (!
|
|
4227
|
-
throw new Error(`Service ${service} is not allowed. Allowed services: ${
|
|
4234
|
+
if (!exports.AV.includes(service)) {
|
|
4235
|
+
throw new Error(`Service ${service} is not allowed. Allowed services: ${exports.AV.join(", ")}`);
|
|
4228
4236
|
}
|
|
4229
4237
|
assertTcbCloudRunActionAllowed(service, action);
|
|
4230
4238
|
const { region: resolvedRegion, params: bodyParams } = resolveCloudApiRegionAndParams({ region, params });
|
|
@@ -8964,6 +8972,7 @@ const path = __importStar(__webpack_require__(2521));
|
|
|
8964
8972
|
const zod_1 = __webpack_require__(2971);
|
|
8965
8973
|
const cloudbase_manager_js_1 = __webpack_require__(3109);
|
|
8966
8974
|
const tool_result_js_1 = __webpack_require__(9645);
|
|
8975
|
+
const sql_risk_js_1 = __webpack_require__(9885);
|
|
8967
8976
|
const CATEGORY = "PostgreSQL database";
|
|
8968
8977
|
const QUERY_PG_DATABASE = "queryPgDatabase";
|
|
8969
8978
|
const MANAGE_PG_DATABASE = "managePgDatabase";
|
|
@@ -9123,33 +9132,9 @@ function normalizeLimit(limit, fallback = 20, max = 200) {
|
|
|
9123
9132
|
}
|
|
9124
9133
|
return Math.max(1, Math.min(max, Math.floor(limit)));
|
|
9125
9134
|
}
|
|
9126
|
-
function stripLeadingSqlComments(sql) {
|
|
9127
|
-
let normalized = sql.trim();
|
|
9128
|
-
while (normalized.length > 0) {
|
|
9129
|
-
if (normalized.startsWith("--")) {
|
|
9130
|
-
normalized = normalized.replace(/^--.*(?:\r?\n|$)/, "").trimStart();
|
|
9131
|
-
continue;
|
|
9132
|
-
}
|
|
9133
|
-
if (normalized.startsWith("#")) {
|
|
9134
|
-
normalized = normalized.replace(/^#.*(?:\r?\n|$)/, "").trimStart();
|
|
9135
|
-
continue;
|
|
9136
|
-
}
|
|
9137
|
-
if (normalized.startsWith("/*")) {
|
|
9138
|
-
normalized = normalized.replace(/^\/\*[\s\S]*?\*\//, "").trimStart();
|
|
9139
|
-
continue;
|
|
9140
|
-
}
|
|
9141
|
-
break;
|
|
9142
|
-
}
|
|
9143
|
-
return normalized;
|
|
9144
|
-
}
|
|
9145
|
-
function getSqlVerb(sql) {
|
|
9146
|
-
const normalized = stripLeadingSqlComments(sql);
|
|
9147
|
-
const match = normalized.match(/^([a-zA-Z]+)/);
|
|
9148
|
-
return match ? match[1].toUpperCase() : "";
|
|
9149
|
-
}
|
|
9150
9135
|
function isReadOnlySql(sql) {
|
|
9151
|
-
const normalized = stripLeadingSqlComments(sql);
|
|
9152
|
-
const verb = getSqlVerb(normalized);
|
|
9136
|
+
const normalized = (0, sql_risk_js_1.stripLeadingSqlComments)(sql);
|
|
9137
|
+
const verb = (0, sql_risk_js_1.getSqlVerb)(normalized);
|
|
9153
9138
|
const readOnlyVerbs = new Set([
|
|
9154
9139
|
"SELECT",
|
|
9155
9140
|
"SHOW",
|
|
@@ -9163,27 +9148,16 @@ function isReadOnlySql(sql) {
|
|
|
9163
9148
|
return !/\b(INSERT|UPDATE|DELETE|CREATE|ALTER|DROP|TRUNCATE|REPLACE|RENAME|GRANT|REVOKE|COMMENT|VACUUM|ANALYZE|FOR\s+UPDATE|FOR\s+SHARE)\b/i.test(normalized);
|
|
9164
9149
|
}
|
|
9165
9150
|
function buildLimitedReadOnlySql(sql, limit) {
|
|
9166
|
-
const normalized = stripLeadingSqlComments(sql).replace(/;\s*$/, "");
|
|
9167
|
-
const verb = getSqlVerb(normalized);
|
|
9151
|
+
const normalized = (0, sql_risk_js_1.stripLeadingSqlComments)(sql).replace(/;\s*$/, "");
|
|
9152
|
+
const verb = (0, sql_risk_js_1.getSqlVerb)(normalized);
|
|
9168
9153
|
if (!["SELECT", "WITH", "VALUES"].includes(verb)) {
|
|
9169
9154
|
return sql;
|
|
9170
9155
|
}
|
|
9171
9156
|
return `SELECT * FROM (${normalized}) AS cloudbase_mcp_readonly_limit LIMIT ${limit}`;
|
|
9172
9157
|
}
|
|
9173
|
-
function isDestructiveSql(sql) {
|
|
9174
|
-
const normalized = stripLeadingSqlComments(sql);
|
|
9175
|
-
const verb = getSqlVerb(normalized);
|
|
9176
|
-
if (["DROP", "TRUNCATE", "DELETE"].includes(verb)) {
|
|
9177
|
-
return true;
|
|
9178
|
-
}
|
|
9179
|
-
if (verb === "ALTER") {
|
|
9180
|
-
return /\b(DROP|RENAME)\b/i.test(normalized);
|
|
9181
|
-
}
|
|
9182
|
-
return false;
|
|
9183
|
-
}
|
|
9184
9158
|
function classifySqlRisk(sql) {
|
|
9185
|
-
const normalized = stripLeadingSqlComments(sql);
|
|
9186
|
-
const verb = getSqlVerb(normalized);
|
|
9159
|
+
const normalized = (0, sql_risk_js_1.stripLeadingSqlComments)(sql);
|
|
9160
|
+
const verb = (0, sql_risk_js_1.getSqlVerb)(normalized);
|
|
9187
9161
|
if (!verb) {
|
|
9188
9162
|
return {
|
|
9189
9163
|
risk: "unknown_risk",
|
|
@@ -9198,7 +9172,7 @@ function classifySqlRisk(sql) {
|
|
|
9198
9172
|
requiresConfirm: false,
|
|
9199
9173
|
};
|
|
9200
9174
|
}
|
|
9201
|
-
if (isDestructiveSql(normalized)) {
|
|
9175
|
+
if ((0, sql_risk_js_1.isDestructiveSql)(normalized)) {
|
|
9202
9176
|
return {
|
|
9203
9177
|
risk: "destructive",
|
|
9204
9178
|
readOnly: false,
|
|
@@ -9244,7 +9218,7 @@ function isSchemaDdlRisk(risk, sql) {
|
|
|
9244
9218
|
if (risk !== "destructive") {
|
|
9245
9219
|
return false;
|
|
9246
9220
|
}
|
|
9247
|
-
const verb = getSqlVerb(stripLeadingSqlComments(sql));
|
|
9221
|
+
const verb = (0, sql_risk_js_1.getSqlVerb)((0, sql_risk_js_1.stripLeadingSqlComments)(sql));
|
|
9248
9222
|
return ["DROP", "TRUNCATE", "ALTER"].includes(verb);
|
|
9249
9223
|
}
|
|
9250
9224
|
/**
|
|
@@ -9797,7 +9771,7 @@ function buildSchemaTable(schema, name) {
|
|
|
9797
9771
|
return `${schema}.${name}`;
|
|
9798
9772
|
}
|
|
9799
9773
|
function parseTargetTableFromSql(sql, defaultSchema) {
|
|
9800
|
-
const normalized = stripLeadingSqlComments(sql);
|
|
9774
|
+
const normalized = (0, sql_risk_js_1.stripLeadingSqlComments)(sql);
|
|
9801
9775
|
const identifier = String.raw `((?:[A-Za-z_][A-Za-z0-9_$]*\.)?[A-Za-z_][A-Za-z0-9_$]*)`;
|
|
9802
9776
|
const patterns = [
|
|
9803
9777
|
new RegExp(String.raw `\bcreate\s+(?:temporary\s+|temp\s+|unlogged\s+)?table\s+(?:if\s+not\s+exists\s+)?${identifier}`, "i"),
|
|
@@ -10204,7 +10178,7 @@ function renderParameterizedSql(sql, values) {
|
|
|
10204
10178
|
});
|
|
10205
10179
|
}
|
|
10206
10180
|
function inferCommand(sql) {
|
|
10207
|
-
return getSqlVerb(sql) || undefined;
|
|
10181
|
+
return (0, sql_risk_js_1.getSqlVerb)(sql) || undefined;
|
|
10208
10182
|
}
|
|
10209
10183
|
function createManagerPgClient(context, cloudBaseOptions) {
|
|
10210
10184
|
return {
|
|
@@ -10480,7 +10454,7 @@ async function handleExecuteSql(args, context, deps) {
|
|
|
10480
10454
|
success: true,
|
|
10481
10455
|
data: {
|
|
10482
10456
|
classification,
|
|
10483
|
-
command: result.command ?? getSqlVerb(args.sql),
|
|
10457
|
+
command: result.command ?? (0, sql_risk_js_1.getSqlVerb)(args.sql),
|
|
10484
10458
|
rowCount: result.rowCount ?? null,
|
|
10485
10459
|
previewRows: result.rows
|
|
10486
10460
|
.slice(0, 5)
|
|
@@ -12576,6 +12550,474 @@ function registerSQLDatabaseTools(server) {
|
|
|
12576
12550
|
}
|
|
12577
12551
|
|
|
12578
12552
|
|
|
12553
|
+
/***/ },
|
|
12554
|
+
|
|
12555
|
+
/***/ 3668
|
|
12556
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
12557
|
+
|
|
12558
|
+
|
|
12559
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12560
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
12561
|
+
};
|
|
12562
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
12563
|
+
exports.DEPLOY_ERROR_CODES = void 0;
|
|
12564
|
+
exports.registerDeployTools = registerDeployTools;
|
|
12565
|
+
const toolbox_1 = __webpack_require__(2090);
|
|
12566
|
+
const node_fs_1 = __importDefault(__webpack_require__(9627));
|
|
12567
|
+
const node_path_1 = __importDefault(__webpack_require__(5663));
|
|
12568
|
+
const zod_1 = __webpack_require__(2971);
|
|
12569
|
+
const cloudbase_manager_js_1 = __webpack_require__(3109);
|
|
12570
|
+
const json_content_js_1 = __webpack_require__(8027);
|
|
12571
|
+
const sql_risk_js_1 = __webpack_require__(9885);
|
|
12572
|
+
// 声明式部署可编排的资源类型,与 DeployOrchestrator 的部署顺序一致:
|
|
12573
|
+
// database → functions → app → hosting → gateway
|
|
12574
|
+
const RESOURCE_TYPES = ["database", "functions", "app", "hosting", "gateway"];
|
|
12575
|
+
/**
|
|
12576
|
+
* 声明式部署工具的稳定错误码。供 agent 程序化分支处理,不随文案调整而变化。
|
|
12577
|
+
* - CONFIG_NOT_FOUND:cwd 下未找到 cloudbaserc 配置文件
|
|
12578
|
+
* - CONFIG_INVALID:配置未通过 cloudbaserc schema 校验
|
|
12579
|
+
* - ENV_UNRESOLVED:无法确定目标环境 ID(配置/入参/登录态均缺失)
|
|
12580
|
+
* - INVALID_CONCURRENCY:并发数入参非法
|
|
12581
|
+
* - CONFIRM_REQUIRED:写操作未显式传 confirm=true
|
|
12582
|
+
* - DESTRUCTIVE_CONFIRM_REQUIRED:待执行的数据库迁移含破坏性语句,需额外传 confirmDestructive=true
|
|
12583
|
+
* - DEPLOY_FAILED:编排器执行失败或其它未分类错误(可能透传引擎 errorCode)
|
|
12584
|
+
*/
|
|
12585
|
+
exports.DEPLOY_ERROR_CODES = {
|
|
12586
|
+
CONFIG_NOT_FOUND: "CONFIG_NOT_FOUND",
|
|
12587
|
+
CONFIG_INVALID: "CONFIG_INVALID",
|
|
12588
|
+
ENV_UNRESOLVED: "ENV_UNRESOLVED",
|
|
12589
|
+
INVALID_CONCURRENCY: "INVALID_CONCURRENCY",
|
|
12590
|
+
CONFIRM_REQUIRED: "CONFIRM_REQUIRED",
|
|
12591
|
+
DESTRUCTIVE_CONFIRM_REQUIRED: "DESTRUCTIVE_CONFIRM_REQUIRED",
|
|
12592
|
+
DEPLOY_FAILED: "DEPLOY_FAILED",
|
|
12593
|
+
};
|
|
12594
|
+
/**
|
|
12595
|
+
* 携带稳定错误码的部署错误。抛出后由 buildErrorEnvelope 归一为信封的 errorCode 字段。
|
|
12596
|
+
*/
|
|
12597
|
+
class DeployError extends Error {
|
|
12598
|
+
code;
|
|
12599
|
+
constructor(code, message) {
|
|
12600
|
+
super(message);
|
|
12601
|
+
this.name = "DeployError";
|
|
12602
|
+
this.code = code;
|
|
12603
|
+
}
|
|
12604
|
+
}
|
|
12605
|
+
function buildEnvelope(data, message) {
|
|
12606
|
+
return { success: true, data, message };
|
|
12607
|
+
}
|
|
12608
|
+
function buildErrorEnvelope(error) {
|
|
12609
|
+
// DeployError 带显式错误码;引擎/SDK 抛出的错误若带 code 也透传;其余归为 DEPLOY_FAILED。
|
|
12610
|
+
let errorCode = exports.DEPLOY_ERROR_CODES.DEPLOY_FAILED;
|
|
12611
|
+
if (error instanceof DeployError) {
|
|
12612
|
+
errorCode = error.code;
|
|
12613
|
+
}
|
|
12614
|
+
else if (error &&
|
|
12615
|
+
typeof error === "object" &&
|
|
12616
|
+
"code" in error &&
|
|
12617
|
+
typeof error.code === "string" &&
|
|
12618
|
+
error.code.length > 0) {
|
|
12619
|
+
errorCode = error.code;
|
|
12620
|
+
}
|
|
12621
|
+
return {
|
|
12622
|
+
success: false,
|
|
12623
|
+
data: {},
|
|
12624
|
+
message: error instanceof Error ? error.message : String(error),
|
|
12625
|
+
errorCode,
|
|
12626
|
+
};
|
|
12627
|
+
}
|
|
12628
|
+
/**
|
|
12629
|
+
* 解析 cloudbaserc 声明式部署配置。
|
|
12630
|
+
*
|
|
12631
|
+
* 分两步完成:
|
|
12632
|
+
* 1. 定位并读取配置文件:searchConfig 从 cwd 探测 cloudbaserc.*(json/yaml/yml/js),
|
|
12633
|
+
* loadConfig 读取原始内容。读取阶段不强制 envId,
|
|
12634
|
+
* envId 由调用方按优先级单独确定,以支持用登录态环境部署未写死 envId 的配置。
|
|
12635
|
+
* 2. ConfigParser.parseRawConfig:按 mode 合并 envOverrides、下发 functionDefaultConfig
|
|
12636
|
+
* 到各函数、加载 .env / .env.local / .env.<mode> 并渲染 {{env.*}} / {{tcb.*}} 模板变量。
|
|
12637
|
+
*/
|
|
12638
|
+
async function resolveDeployConfig(options) {
|
|
12639
|
+
const found = await (0, toolbox_1.searchConfig)(options.cwd);
|
|
12640
|
+
if (!found?.filepath) {
|
|
12641
|
+
throw new DeployError(exports.DEPLOY_ERROR_CODES.CONFIG_NOT_FOUND, `未在 ${options.cwd} 找到 cloudbaserc 配置文件(支持 json/yaml/yml/js)`);
|
|
12642
|
+
}
|
|
12643
|
+
const rawConfig = await (0, toolbox_1.loadConfig)({ configPath: found.filepath });
|
|
12644
|
+
return toolbox_1.ConfigParser.parseRawConfig(rawConfig ?? {}, options.cwd, {
|
|
12645
|
+
mode: options.mode,
|
|
12646
|
+
});
|
|
12647
|
+
}
|
|
12648
|
+
/**
|
|
12649
|
+
* 确定部署使用的环境 ID。
|
|
12650
|
+
*
|
|
12651
|
+
* 优先级:显式传入的 envId > 解析后配置中的 envId > MCP 登录态 / 绑定环境。
|
|
12652
|
+
* 显式入参优先于配置文件,配置未写死 envId 时回退到当前会话绑定的环境。
|
|
12653
|
+
* 三者都无则抛出错误。
|
|
12654
|
+
*/
|
|
12655
|
+
async function resolveDeployEnvId(options) {
|
|
12656
|
+
if (options.envId && options.envId.length > 0) {
|
|
12657
|
+
return options.envId;
|
|
12658
|
+
}
|
|
12659
|
+
const configEnvId = options.config.envId;
|
|
12660
|
+
if (typeof configEnvId === "string" && configEnvId.length > 0) {
|
|
12661
|
+
return configEnvId;
|
|
12662
|
+
}
|
|
12663
|
+
const resolved = await (0, cloudbase_manager_js_1.getEnvId)(options.cloudBaseOptions);
|
|
12664
|
+
if (!resolved) {
|
|
12665
|
+
throw new DeployError(exports.DEPLOY_ERROR_CODES.ENV_UNRESOLVED, "未能确定部署环境 ID:请在 cloudbaserc 配置 envId、通过 envId 参数指定,或先登录并绑定环境。");
|
|
12666
|
+
}
|
|
12667
|
+
return resolved;
|
|
12668
|
+
}
|
|
12669
|
+
/**
|
|
12670
|
+
* 按 cloudbaserc schema 校验解析后的配置。
|
|
12671
|
+
*
|
|
12672
|
+
* 校验不通过时抛出错误,错误消息包含各字段的具体校验失败原因,供调用方定位问题。
|
|
12673
|
+
*/
|
|
12674
|
+
function assertConfigValid(config) {
|
|
12675
|
+
const result = (0, toolbox_1.validateCloudBaseConfigBySchema)(config);
|
|
12676
|
+
if (result.valid) {
|
|
12677
|
+
return;
|
|
12678
|
+
}
|
|
12679
|
+
const detail = result.errors
|
|
12680
|
+
.map((item) => `${item.dataPath || "<root>"} ${item.message}`)
|
|
12681
|
+
.join("; ");
|
|
12682
|
+
throw new DeployError(exports.DEPLOY_ERROR_CODES.CONFIG_INVALID, `cloudbaserc 配置校验未通过:${detail}`);
|
|
12683
|
+
}
|
|
12684
|
+
/**
|
|
12685
|
+
* 校验并发数取值,非法时抛出错误。
|
|
12686
|
+
*
|
|
12687
|
+
* 未指定时返回 undefined(由编排器使用默认串行);指定时必须为不小于 1 的整数。
|
|
12688
|
+
*/
|
|
12689
|
+
function normalizeConcurrency(concurrency) {
|
|
12690
|
+
if (concurrency === undefined) {
|
|
12691
|
+
return undefined;
|
|
12692
|
+
}
|
|
12693
|
+
if (!Number.isInteger(concurrency) || concurrency < 1) {
|
|
12694
|
+
throw new DeployError(exports.DEPLOY_ERROR_CODES.INVALID_CONCURRENCY, `无效的并发数 ${concurrency},应为不小于 1 的整数`);
|
|
12695
|
+
}
|
|
12696
|
+
return concurrency;
|
|
12697
|
+
}
|
|
12698
|
+
/**
|
|
12699
|
+
* 让 deployPlan 的预演结论与 deployApply 的实际执行语义对齐。
|
|
12700
|
+
*
|
|
12701
|
+
* 背景:编排器把「云端已存在的函数」标为 status='update',但 deployApply 在 yes!==true
|
|
12702
|
+
* 且无交互确认回调时,会对 functions+update 保守跳过(reason='no-confirm')。
|
|
12703
|
+
* 若 plan 原样返回 update,agent 预演看到「会更新」,实际执行却「跳过」——结论相反。
|
|
12704
|
+
*
|
|
12705
|
+
* 此函数按传入的 yes 复算 functions+update 的「有效动作」:
|
|
12706
|
+
* - yes===true:维持 update(执行时确实会覆盖)
|
|
12707
|
+
* - 否则:改标为 skip,并保留原始判定到 declaredStatus,action 说明为何跳过。
|
|
12708
|
+
* 其它资源类型与状态原样透传(database/app/hosting/gateway 的分类不受 yes 影响)。
|
|
12709
|
+
*/
|
|
12710
|
+
function reconcilePlanWithExecution(plan, yes) {
|
|
12711
|
+
if (!Array.isArray(plan)) {
|
|
12712
|
+
return [];
|
|
12713
|
+
}
|
|
12714
|
+
return plan.map((item) => {
|
|
12715
|
+
if (!item || typeof item !== "object") {
|
|
12716
|
+
return item;
|
|
12717
|
+
}
|
|
12718
|
+
if (item.type === "functions" && item.status === "update" && !yes) {
|
|
12719
|
+
return {
|
|
12720
|
+
...item,
|
|
12721
|
+
status: "skip",
|
|
12722
|
+
declaredStatus: "update",
|
|
12723
|
+
action: `已存在函数 ${item.name}:未传 yes=true,执行时将保守跳过(不覆盖)。传 yes=true 才会覆盖更新。`,
|
|
12724
|
+
};
|
|
12725
|
+
}
|
|
12726
|
+
return item;
|
|
12727
|
+
});
|
|
12728
|
+
}
|
|
12729
|
+
/**
|
|
12730
|
+
* 解析 migrations 目录(与引擎 DatabaseDeployer.resolveMigrationsDir 同规则):
|
|
12731
|
+
* 未配置默认 ./cloudbase/migrations;仅允许相对路径(禁止绝对路径 / 开头)。
|
|
12732
|
+
* 非法时返回 undefined(交由引擎在真正执行时抛出一致的错误,这里不抢报错)。
|
|
12733
|
+
*/
|
|
12734
|
+
function resolveMigrationsDir(cwd, migrations) {
|
|
12735
|
+
const raw = typeof migrations === "string" && migrations ? migrations : "./cloudbase/migrations";
|
|
12736
|
+
if (node_path_1.default.isAbsolute(raw) || raw.startsWith("/")) {
|
|
12737
|
+
return undefined;
|
|
12738
|
+
}
|
|
12739
|
+
return node_path_1.default.resolve(cwd, raw);
|
|
12740
|
+
}
|
|
12741
|
+
/**
|
|
12742
|
+
* 从 dry-run plan 中提取「待执行(pending)的数据库迁移标识」。
|
|
12743
|
+
*
|
|
12744
|
+
* 编排器把 database 计划聚合为单条 create 项,pending 迁移写在
|
|
12745
|
+
* changes[].to(field==='migration'),形如 "{version}_{name}"。
|
|
12746
|
+
* 只关注 pending:已 applied 的迁移不会被重复执行,不应触发破坏性确认门。
|
|
12747
|
+
*/
|
|
12748
|
+
function extractPendingMigrations(plan) {
|
|
12749
|
+
const result = [];
|
|
12750
|
+
for (const item of plan) {
|
|
12751
|
+
if (!item || item.type !== "database" || item.status !== "create") {
|
|
12752
|
+
continue;
|
|
12753
|
+
}
|
|
12754
|
+
const changes = item.changes;
|
|
12755
|
+
if (!Array.isArray(changes)) {
|
|
12756
|
+
continue;
|
|
12757
|
+
}
|
|
12758
|
+
for (const change of changes) {
|
|
12759
|
+
if (change?.field === "migration" && typeof change.to === "string" && change.to) {
|
|
12760
|
+
result.push(change.to);
|
|
12761
|
+
}
|
|
12762
|
+
}
|
|
12763
|
+
}
|
|
12764
|
+
return result;
|
|
12765
|
+
}
|
|
12766
|
+
/**
|
|
12767
|
+
* 检测「本次将要执行的数据库迁移」中是否含破坏性语句(DROP/TRUNCATE/DELETE、
|
|
12768
|
+
* ALTER ... DROP/RENAME)。
|
|
12769
|
+
*
|
|
12770
|
+
* 仅扫描 pending 迁移对应的本地 .sql 文件;已 applied 的不扫描,避免误拦。
|
|
12771
|
+
* 读文件失败(缺文件/目录非法)视为无法确认破坏性,返回空——真正的存在性/
|
|
12772
|
+
* 格式校验交由引擎执行时处理,这里只在能确证破坏性时加门,避免与引擎报错重复。
|
|
12773
|
+
*/
|
|
12774
|
+
function detectDestructiveMigrations(options) {
|
|
12775
|
+
const pending = extractPendingMigrations(options.plan);
|
|
12776
|
+
if (pending.length === 0) {
|
|
12777
|
+
return [];
|
|
12778
|
+
}
|
|
12779
|
+
const dbConfig = options.databaseConfig && typeof options.databaseConfig === "object"
|
|
12780
|
+
? options.databaseConfig
|
|
12781
|
+
: undefined;
|
|
12782
|
+
const migrationsDir = resolveMigrationsDir(options.cwd, dbConfig?.migrations);
|
|
12783
|
+
if (!migrationsDir) {
|
|
12784
|
+
return [];
|
|
12785
|
+
}
|
|
12786
|
+
const hits = [];
|
|
12787
|
+
for (const migration of pending) {
|
|
12788
|
+
const file = node_path_1.default.join(migrationsDir, `${migration}.sql`);
|
|
12789
|
+
let sqlText;
|
|
12790
|
+
try {
|
|
12791
|
+
sqlText = node_fs_1.default.readFileSync(file, "utf-8");
|
|
12792
|
+
}
|
|
12793
|
+
catch {
|
|
12794
|
+
// 文件读不到:不在此处报错,交给引擎执行时给出一致错误
|
|
12795
|
+
continue;
|
|
12796
|
+
}
|
|
12797
|
+
const statements = (0, sql_risk_js_1.findDestructiveStatements)(sqlText);
|
|
12798
|
+
if (statements.length > 0) {
|
|
12799
|
+
hits.push({ migration, file, statements });
|
|
12800
|
+
}
|
|
12801
|
+
}
|
|
12802
|
+
return hits;
|
|
12803
|
+
}
|
|
12804
|
+
function registerDeployTools(server) {
|
|
12805
|
+
const cloudBaseOptions = server.cloudBaseOptions;
|
|
12806
|
+
const getManager = () => (0, cloudbase_manager_js_1.getCloudBaseManager)({ cloudBaseOptions });
|
|
12807
|
+
// 工具一:deployPlan —— 只读,预演部署计划(dry-run)
|
|
12808
|
+
server.registerTool?.("deployPlan", {
|
|
12809
|
+
title: "预演 CloudBase 声明式部署计划",
|
|
12810
|
+
description: "解析 cloudbaserc 并计算声明式部署计划(dry-run,不产生任何变更)。" +
|
|
12811
|
+
"这是 deployApply 的预演对仗工具:plan 计算、deployApply 执行同一份 cloudbaserc。" +
|
|
12812
|
+
"返回每个资源的动作分类:create=新建,update=覆盖更新,skip=无变更/不会执行," +
|
|
12813
|
+
"conflict=检测到冲突需中断,deploy=直传覆盖。" +
|
|
12814
|
+
"计划已按 yes 复算为「实际会发生的动作」:不传 yes=true 时,云端已存在的函数会标为 skip" +
|
|
12815
|
+
"(并在 declaredStatus 保留 update),与 deployApply 的实际执行结果一致,避免预演与执行相反。" +
|
|
12816
|
+
"\n适用边界:本工具用于项目级声明式编排(一份 cloudbaserc 统一 plan/apply);" +
|
|
12817
|
+
"单资源临时直传请用 manageFunctions/manageHosting/manageApps。" +
|
|
12818
|
+
"\n- cwd:项目根目录,默认当前工作目录" +
|
|
12819
|
+
"\n- mode:环境名,命中 envOverrides.<mode> 时合并对应的多环境覆盖配置" +
|
|
12820
|
+
"\n- envId:目标环境 ID,优先级高于 cloudbaserc 中的 envId;不传则用配置值或当前绑定环境" +
|
|
12821
|
+
"\n- only:仅计算指定资源类型的计划" +
|
|
12822
|
+
"\n- skip:跳过指定资源类型" +
|
|
12823
|
+
"\n- yes:与 deployApply 的 yes 对齐,用于复算已存在函数的有效动作。" +
|
|
12824
|
+
"true=预演为覆盖更新(update);false(默认)=预演为保守跳过(skip)",
|
|
12825
|
+
inputSchema: {
|
|
12826
|
+
cwd: zod_1.z
|
|
12827
|
+
.string()
|
|
12828
|
+
.optional()
|
|
12829
|
+
.describe("项目根目录,从此目录向下搜索 cloudbaserc;默认当前工作目录"),
|
|
12830
|
+
mode: zod_1.z
|
|
12831
|
+
.string()
|
|
12832
|
+
.optional()
|
|
12833
|
+
.describe("环境名(如 production/staging),命中 envOverrides.<mode> 时合并覆盖"),
|
|
12834
|
+
envId: zod_1.z
|
|
12835
|
+
.string()
|
|
12836
|
+
.optional()
|
|
12837
|
+
.describe("目标环境 ID,优先级高于 cloudbaserc 中的 envId;不传则用配置值或当前绑定环境"),
|
|
12838
|
+
only: zod_1.z
|
|
12839
|
+
.array(zod_1.z.enum(RESOURCE_TYPES))
|
|
12840
|
+
.optional()
|
|
12841
|
+
.describe("仅计算指定资源类型的计划,可选值:database/functions/app/hosting/gateway"),
|
|
12842
|
+
skip: zod_1.z
|
|
12843
|
+
.array(zod_1.z.enum(RESOURCE_TYPES))
|
|
12844
|
+
.optional()
|
|
12845
|
+
.describe("跳过指定资源类型,可选值:database/functions/app/hosting/gateway"),
|
|
12846
|
+
yes: zod_1.z
|
|
12847
|
+
.boolean()
|
|
12848
|
+
.optional()
|
|
12849
|
+
.describe("与 deployApply 的 yes 对齐,用于复算已存在函数的有效动作。" +
|
|
12850
|
+
"true=预演为覆盖更新;false(默认)=预演为保守跳过"),
|
|
12851
|
+
},
|
|
12852
|
+
annotations: {
|
|
12853
|
+
readOnlyHint: true,
|
|
12854
|
+
openWorldHint: true,
|
|
12855
|
+
category: "deploy",
|
|
12856
|
+
},
|
|
12857
|
+
}, async ({ cwd, mode, envId: envIdInput, only, skip, yes, }) => {
|
|
12858
|
+
try {
|
|
12859
|
+
const projectRoot = cwd ?? process.cwd();
|
|
12860
|
+
const config = await resolveDeployConfig({ cwd: projectRoot, mode });
|
|
12861
|
+
assertConfigValid(config);
|
|
12862
|
+
const envId = await resolveDeployEnvId({
|
|
12863
|
+
envId: envIdInput,
|
|
12864
|
+
config,
|
|
12865
|
+
cloudBaseOptions,
|
|
12866
|
+
});
|
|
12867
|
+
const manager = await getManager();
|
|
12868
|
+
const rawPlan = await manager.getDeployOrchestrator().deployPlan({
|
|
12869
|
+
config,
|
|
12870
|
+
envId,
|
|
12871
|
+
cwd: projectRoot,
|
|
12872
|
+
only,
|
|
12873
|
+
skip,
|
|
12874
|
+
dryRun: true,
|
|
12875
|
+
});
|
|
12876
|
+
// 按 yes 复算为「实际会发生的动作」,使预演与 deployApply 的执行结果一致
|
|
12877
|
+
const plan = reconcilePlanWithExecution(rawPlan, yes === true);
|
|
12878
|
+
return (0, json_content_js_1.jsonContent)(buildEnvelope({ cwd: projectRoot, mode: mode ?? null, envId, yes: yes === true, plan }, "已生成声明式部署计划"));
|
|
12879
|
+
}
|
|
12880
|
+
catch (error) {
|
|
12881
|
+
return (0, json_content_js_1.jsonContent)(buildErrorEnvelope(error));
|
|
12882
|
+
}
|
|
12883
|
+
});
|
|
12884
|
+
// 工具二:deployApply —— 写操作,执行声明式部署(本地形态的 apply,与 deployPlan 对仗)
|
|
12885
|
+
server.registerTool?.("deployApply", {
|
|
12886
|
+
title: "执行 CloudBase 声明式部署(本地 apply)",
|
|
12887
|
+
description: "解析 cloudbaserc 并按 database→functions→app→hosting→gateway 顺序执行声明式部署。" +
|
|
12888
|
+
"这是 deployPlan 的执行对仗工具(plan 预演 / deployApply 执行同一份 cloudbaserc)," +
|
|
12889
|
+
"属于本地形态的 apply(读本地 cloudbaserc 并在本地构建上传)," +
|
|
12890
|
+
"是会变更云端资源的写操作,必须显式传 confirm=true 才会执行。" +
|
|
12891
|
+
"建议先用 deployPlan 预演,确认计划无误后再执行。" +
|
|
12892
|
+
"\n适用边界:本工具用于项目级声明式编排(一份 cloudbaserc 统一 plan/apply);" +
|
|
12893
|
+
"单资源临时直传请用 manageFunctions/manageHosting/manageApps。" +
|
|
12894
|
+
"\n- confirm:必须显式传 true 才执行部署,否则直接拒绝" +
|
|
12895
|
+
"\n- confirmDestructive:当本次待执行的数据库迁移含破坏性语句(DROP/TRUNCATE/DELETE、" +
|
|
12896
|
+
"ALTER…DROP/RENAME)时,除 confirm 外还必须显式传 confirmDestructive=true 才会执行;" +
|
|
12897
|
+
"否则拒绝并列出命中的迁移与语句。无破坏性迁移时该参数不生效" +
|
|
12898
|
+
"\n- cwd:项目根目录,默认当前工作目录" +
|
|
12899
|
+
"\n- mode:环境名,命中 envOverrides.<mode> 时合并对应的多环境覆盖配置" +
|
|
12900
|
+
"\n- envId:目标环境 ID,优先级高于 cloudbaserc 中的 envId;不传则用配置值或当前绑定环境" +
|
|
12901
|
+
"\n- only:仅部署指定资源类型" +
|
|
12902
|
+
"\n- skip:跳过指定资源类型" +
|
|
12903
|
+
"\n- yes:遇到已存在资源时的处理方式。true=直接覆盖更新;false(默认)=保守跳过," +
|
|
12904
|
+
"在无法交互确认的场景下已存在资源不会被覆盖(与 deployPlan 的 yes 语义一致)" +
|
|
12905
|
+
"\n- concurrency:同类型资源最大并行数,默认 1(串行)" +
|
|
12906
|
+
"\n- continueOnError:某个资源失败后继续部署其余资源(database 失败仍强制中断)",
|
|
12907
|
+
inputSchema: {
|
|
12908
|
+
confirm: zod_1.z
|
|
12909
|
+
.boolean()
|
|
12910
|
+
.optional()
|
|
12911
|
+
.describe("危险操作确认开关。部署会变更云端资源,必须显式传 confirm=true 才会执行"),
|
|
12912
|
+
confirmDestructive: zod_1.z
|
|
12913
|
+
.boolean()
|
|
12914
|
+
.optional()
|
|
12915
|
+
.describe("破坏性数据库变更确认开关。当待执行迁移含 DROP/TRUNCATE/DELETE 或 ALTER…DROP/RENAME 时," +
|
|
12916
|
+
"必须在 confirm=true 之外额外显式传 confirmDestructive=true;无破坏性迁移时不生效"),
|
|
12917
|
+
cwd: zod_1.z
|
|
12918
|
+
.string()
|
|
12919
|
+
.optional()
|
|
12920
|
+
.describe("项目根目录,从此目录向下搜索 cloudbaserc;默认当前工作目录"),
|
|
12921
|
+
mode: zod_1.z
|
|
12922
|
+
.string()
|
|
12923
|
+
.optional()
|
|
12924
|
+
.describe("环境名(如 production/staging),命中 envOverrides.<mode> 时合并覆盖"),
|
|
12925
|
+
envId: zod_1.z
|
|
12926
|
+
.string()
|
|
12927
|
+
.optional()
|
|
12928
|
+
.describe("目标环境 ID,优先级高于 cloudbaserc 中的 envId;不传则用配置值或当前绑定环境"),
|
|
12929
|
+
only: zod_1.z
|
|
12930
|
+
.array(zod_1.z.enum(RESOURCE_TYPES))
|
|
12931
|
+
.optional()
|
|
12932
|
+
.describe("仅部署指定资源类型,可选值:database/functions/app/hosting/gateway"),
|
|
12933
|
+
skip: zod_1.z
|
|
12934
|
+
.array(zod_1.z.enum(RESOURCE_TYPES))
|
|
12935
|
+
.optional()
|
|
12936
|
+
.describe("跳过指定资源类型,可选值:database/functions/app/hosting/gateway"),
|
|
12937
|
+
yes: zod_1.z
|
|
12938
|
+
.boolean()
|
|
12939
|
+
.optional()
|
|
12940
|
+
.describe("遇到已存在资源时是否直接覆盖更新。true=覆盖;false(默认)=保守跳过已存在资源"),
|
|
12941
|
+
concurrency: zod_1.z
|
|
12942
|
+
.number()
|
|
12943
|
+
.int()
|
|
12944
|
+
.min(1)
|
|
12945
|
+
.optional()
|
|
12946
|
+
.describe("同类型资源最大并行数,默认 1(串行);仅作用于同类型资源,跨类型依赖顺序不变"),
|
|
12947
|
+
continueOnError: zod_1.z
|
|
12948
|
+
.boolean()
|
|
12949
|
+
.optional()
|
|
12950
|
+
.describe("某个资源失败后是否继续部署其余资源;database 失败始终强制中断"),
|
|
12951
|
+
},
|
|
12952
|
+
annotations: {
|
|
12953
|
+
readOnlyHint: false,
|
|
12954
|
+
destructiveHint: true,
|
|
12955
|
+
openWorldHint: true,
|
|
12956
|
+
category: "deploy",
|
|
12957
|
+
},
|
|
12958
|
+
}, async ({ confirm, confirmDestructive, cwd, mode, envId: envIdInput, only, skip, yes, concurrency, continueOnError, }) => {
|
|
12959
|
+
try {
|
|
12960
|
+
if (confirm !== true) {
|
|
12961
|
+
throw new DeployError(exports.DEPLOY_ERROR_CODES.CONFIRM_REQUIRED, "部署会变更云端资源,必须显式传 confirm=true 才会执行。" +
|
|
12962
|
+
"建议先用 deployPlan 预演部署计划,确认无误后再执行。");
|
|
12963
|
+
}
|
|
12964
|
+
const projectRoot = cwd ?? process.cwd();
|
|
12965
|
+
const config = await resolveDeployConfig({ cwd: projectRoot, mode });
|
|
12966
|
+
assertConfigValid(config);
|
|
12967
|
+
const envId = await resolveDeployEnvId({
|
|
12968
|
+
envId: envIdInput,
|
|
12969
|
+
config,
|
|
12970
|
+
cloudBaseOptions,
|
|
12971
|
+
});
|
|
12972
|
+
const manager = await getManager();
|
|
12973
|
+
const orchestrator = manager.getDeployOrchestrator();
|
|
12974
|
+
// 破坏性数据库变更门:仅当 database 参与本次部署时,先 dry-run 取 pending 迁移,
|
|
12975
|
+
// 检测破坏性语句;命中且未额外确认则拒绝,独立于总 confirm 之外多一道门。
|
|
12976
|
+
const databaseParticipates = !!config.database &&
|
|
12977
|
+
(!only || only.includes("database")) &&
|
|
12978
|
+
!(skip ?? []).includes("database");
|
|
12979
|
+
if (databaseParticipates && confirmDestructive !== true) {
|
|
12980
|
+
const dryRunPlan = await orchestrator.deployPlan({
|
|
12981
|
+
config,
|
|
12982
|
+
envId,
|
|
12983
|
+
cwd: projectRoot,
|
|
12984
|
+
only,
|
|
12985
|
+
skip,
|
|
12986
|
+
dryRun: true,
|
|
12987
|
+
});
|
|
12988
|
+
const destructive = detectDestructiveMigrations({
|
|
12989
|
+
plan: Array.isArray(dryRunPlan) ? dryRunPlan : [],
|
|
12990
|
+
cwd: projectRoot,
|
|
12991
|
+
databaseConfig: config.database,
|
|
12992
|
+
});
|
|
12993
|
+
if (destructive.length > 0) {
|
|
12994
|
+
throw new DeployError(exports.DEPLOY_ERROR_CODES.DESTRUCTIVE_CONFIRM_REQUIRED, "本次待执行的数据库迁移包含破坏性语句(DROP/TRUNCATE/DELETE 或 ALTER…DROP/RENAME)," +
|
|
12995
|
+
"可能造成数据/结构不可逆丢失。请先备份或复核,确认后额外传 confirmDestructive=true 再执行。" +
|
|
12996
|
+
"命中迁移:" +
|
|
12997
|
+
destructive
|
|
12998
|
+
.map((d) => `${d.migration}(${d.statements.length} 条破坏性语句)`)
|
|
12999
|
+
.join(";"));
|
|
13000
|
+
}
|
|
13001
|
+
}
|
|
13002
|
+
const result = await orchestrator.deploy({
|
|
13003
|
+
config,
|
|
13004
|
+
envId,
|
|
13005
|
+
cwd: projectRoot,
|
|
13006
|
+
only,
|
|
13007
|
+
skip,
|
|
13008
|
+
yes: yes === true,
|
|
13009
|
+
concurrency: normalizeConcurrency(concurrency),
|
|
13010
|
+
continueOnError,
|
|
13011
|
+
});
|
|
13012
|
+
return (0, json_content_js_1.jsonContent)(buildEnvelope({ cwd: projectRoot, mode: mode ?? null, envId, result }, "声明式部署已执行"));
|
|
13013
|
+
}
|
|
13014
|
+
catch (error) {
|
|
13015
|
+
return (0, json_content_js_1.jsonContent)(buildErrorEnvelope(error));
|
|
13016
|
+
}
|
|
13017
|
+
});
|
|
13018
|
+
}
|
|
13019
|
+
|
|
13020
|
+
|
|
12579
13021
|
/***/ },
|
|
12580
13022
|
|
|
12581
13023
|
/***/ 7528
|
|
@@ -24825,7 +25267,7 @@ function registerSetupTools(server) {
|
|
|
24825
25267
|
server.registerTool("downloadTemplate", {
|
|
24826
25268
|
title: "下载项目模板",
|
|
24827
25269
|
description: `自动下载并部署CloudBase项目模板。
|
|
24828
|
-
**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.33.
|
|
25270
|
+
**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.33.2" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
|
|
24829
25271
|
inputSchema: {
|
|
24830
25272
|
template: zod_1.z
|
|
24831
25273
|
.enum(["react", "vue", "miniprogram", "uniapp", "rules"])
|
|
@@ -25801,6 +26243,7 @@ function registerPGStorageTools(server) {
|
|
|
25801
26243
|
|
|
25802
26244
|
|
|
25803
26245
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
26246
|
+
exports.CLOUD_INCOMPATIBLE_ACTION_LEVEL_EXCEPTIONS = exports.CLOUD_INCOMPATIBLE_TOOLS = void 0;
|
|
25804
26247
|
exports.isCloudMode = isCloudMode;
|
|
25805
26248
|
exports.enableCloudMode = enableCloudMode;
|
|
25806
26249
|
exports.getCloudModeStatus = getCloudModeStatus;
|
|
@@ -25846,6 +26289,65 @@ function getCloudModeStatus() {
|
|
|
25846
26289
|
}
|
|
25847
26290
|
return { enabled: false, source: null };
|
|
25848
26291
|
}
|
|
26292
|
+
/**
|
|
26293
|
+
* Tools that are incompatible with cloud mode because they read from or write to
|
|
26294
|
+
* the local filesystem (uploads, downloads, config files, or building an upload
|
|
26295
|
+
* artifact from `process.cwd()`). In cloud mode these top-level tools are not
|
|
26296
|
+
* registered at all; where a tool has both cloud-safe and local-only actions,
|
|
26297
|
+
* gating happens at the action level inside the tool instead (see
|
|
26298
|
+
* `ensureActionAllowedInCloudMode` in functions.ts / hosting.ts).
|
|
26299
|
+
*
|
|
26300
|
+
* IMPORTANT: keep this list in sync with the tools actually registered. Entries
|
|
26301
|
+
* that no longer match a registered tool name are dead (they silently gate
|
|
26302
|
+
* nothing). `CLOUD_INCOMPATIBLE_TOOLS.test.ts` asserts every entry here maps to
|
|
26303
|
+
* a known tool or a documented action-level exception to prevent silent rot.
|
|
26304
|
+
*/
|
|
26305
|
+
exports.CLOUD_INCOMPATIBLE_TOOLS = [
|
|
26306
|
+
// Auth tools - local file uploads
|
|
26307
|
+
'auth',
|
|
26308
|
+
// Storage tools - local file uploads / downloads.
|
|
26309
|
+
// NOTE: `uploadFile` is not a top-level tool name (storage upload is exposed
|
|
26310
|
+
// via `manageStorage`); kept here as a documented action-level exception.
|
|
26311
|
+
'uploadFile',
|
|
26312
|
+
'manageStorage',
|
|
26313
|
+
// Function tools - local code uploads.
|
|
26314
|
+
// NOTE: createFunction / updateFunctionCode are now actions of `manageFunctions`,
|
|
26315
|
+
// not top-level tools, so gating them here is a no-op kept for documentation.
|
|
26316
|
+
// The real cloud-mode guard for those actions lives in
|
|
26317
|
+
// functions.ts#ensureActionAllowedInCloudMode. Left here intentionally so the
|
|
26318
|
+
// sync test flags them as "action-level exceptions" rather than removing the
|
|
26319
|
+
// record of why they are not top-level tools.
|
|
26320
|
+
'updateFunctionCode',
|
|
26321
|
+
'createFunction',
|
|
26322
|
+
// Declarative deploy tools - read local cloudbaserc and build the upload
|
|
26323
|
+
// artifact from cwd (process.cwd() when no cwd is passed). Same class as the
|
|
26324
|
+
// function/upload tools above: they have no meaning without a local project.
|
|
26325
|
+
'deployApply',
|
|
26326
|
+
'deployPlan',
|
|
26327
|
+
// Download tools - local file downloads
|
|
26328
|
+
'downloadTemplate',
|
|
26329
|
+
// Setup tools - local config file operations.
|
|
26330
|
+
// NOTE: `setupEnvironmentId` is not a top-level tool name; kept as a documented
|
|
26331
|
+
// action-level exception (env binding is handled via `auth`/setup flows).
|
|
26332
|
+
'setupEnvironmentId',
|
|
26333
|
+
// CloudRun tools - local file operations
|
|
26334
|
+
'manageCloudRun',
|
|
26335
|
+
// manageApps is intentionally NOT listed: deployApp with localPath/filePath is
|
|
26336
|
+
// blocked per-action in apps.ts (CLOUD_MODE_UNSUPPORTED_ACTION) so cloud mode
|
|
26337
|
+
// can still use getUploadUrl + cosTimestamp, deleteApp, and deleteAppVersion.
|
|
26338
|
+
];
|
|
26339
|
+
/**
|
|
26340
|
+
* Tool names that appear in CLOUD_INCOMPATIBLE_TOOLS for documentation but are no
|
|
26341
|
+
* longer registered as top-level tools (their cloud gating is enforced at the
|
|
26342
|
+
* action level instead). The sync test treats these as expected, everything else
|
|
26343
|
+
* must resolve to a registered tool.
|
|
26344
|
+
*/
|
|
26345
|
+
exports.CLOUD_INCOMPATIBLE_ACTION_LEVEL_EXCEPTIONS = [
|
|
26346
|
+
'createFunction',
|
|
26347
|
+
'updateFunctionCode',
|
|
26348
|
+
'uploadFile',
|
|
26349
|
+
'setupEnvironmentId',
|
|
26350
|
+
];
|
|
25849
26351
|
/**
|
|
25850
26352
|
* Check if a tool should be registered in cloud mode
|
|
25851
26353
|
* @param toolName - The name of the tool
|
|
@@ -25856,29 +26358,7 @@ function shouldRegisterTool(toolName) {
|
|
|
25856
26358
|
if (!isCloudMode()) {
|
|
25857
26359
|
return true;
|
|
25858
26360
|
}
|
|
25859
|
-
|
|
25860
|
-
const cloudIncompatibleTools = [
|
|
25861
|
-
// Auth tools - local file uploads
|
|
25862
|
-
'auth',
|
|
25863
|
-
// Storage tools - local file uploads
|
|
25864
|
-
'uploadFile',
|
|
25865
|
-
// Hosting tools - action-level cloud gating is handled inside manageHosting
|
|
25866
|
-
// Function tools - local code uploads
|
|
25867
|
-
'updateFunctionCode',
|
|
25868
|
-
'createFunction', // also involves local files
|
|
25869
|
-
// Download tools - local file downloads
|
|
25870
|
-
'downloadTemplate',
|
|
25871
|
-
// Setup tools - local config file operations
|
|
25872
|
-
'setupEnvironmentId',
|
|
25873
|
-
// CloudRun tools - local file operations
|
|
25874
|
-
'manageCloudRun',
|
|
25875
|
-
// Download tools - local file downloads
|
|
25876
|
-
'manageStorage',
|
|
25877
|
-
// manageApps is intentionally NOT listed: deployApp with localPath/filePath is
|
|
25878
|
-
// blocked per-action in apps.ts (CLOUD_MODE_UNSUPPORTED_ACTION) so cloud mode
|
|
25879
|
-
// can still use getUploadUrl + cosTimestamp, deleteApp, and deleteAppVersion.
|
|
25880
|
-
];
|
|
25881
|
-
return !cloudIncompatibleTools.includes(toolName);
|
|
26361
|
+
return !exports.CLOUD_INCOMPATIBLE_TOOLS.includes(toolName);
|
|
25882
26362
|
}
|
|
25883
26363
|
|
|
25884
26364
|
|
|
@@ -27036,6 +27516,163 @@ function resolveSiteAndRegion(opts = {}) {
|
|
|
27036
27516
|
}
|
|
27037
27517
|
|
|
27038
27518
|
|
|
27519
|
+
/***/ },
|
|
27520
|
+
|
|
27521
|
+
/***/ 9885
|
|
27522
|
+
(__unused_webpack_module, exports) {
|
|
27523
|
+
|
|
27524
|
+
var __webpack_unused_export__;
|
|
27525
|
+
|
|
27526
|
+
/**
|
|
27527
|
+
* Shared SQL risk heuristics.
|
|
27528
|
+
*
|
|
27529
|
+
* Extracted from databasePG.ts so both the interactive PG execute path and the
|
|
27530
|
+
* declarative deploy path classify destructive SQL with the *same* rules,
|
|
27531
|
+
* avoiding drift between two independent detectors.
|
|
27532
|
+
*
|
|
27533
|
+
* These are conservative lexical heuristics, not a full SQL parser: they strip
|
|
27534
|
+
* leading comments, read the leading verb, and match destructive keywords. They
|
|
27535
|
+
* are meant to decide whether an *extra* human confirmation is warranted, not to
|
|
27536
|
+
* be a security boundary.
|
|
27537
|
+
*/
|
|
27538
|
+
__webpack_unused_export__ = ({ value: true });
|
|
27539
|
+
exports.stripLeadingSqlComments = stripLeadingSqlComments;
|
|
27540
|
+
exports.getSqlVerb = getSqlVerb;
|
|
27541
|
+
exports.isDestructiveSql = isDestructiveSql;
|
|
27542
|
+
__webpack_unused_export__ = splitSqlStatements;
|
|
27543
|
+
exports.findDestructiveStatements = findDestructiveStatements;
|
|
27544
|
+
/** Strip leading line (`--`, `#`) and block (`/* */`) comments and whitespace. */
|
|
27545
|
+
function stripLeadingSqlComments(sql) {
|
|
27546
|
+
let normalized = sql.trim();
|
|
27547
|
+
while (normalized.length > 0) {
|
|
27548
|
+
if (normalized.startsWith("--")) {
|
|
27549
|
+
normalized = normalized.replace(/^--.*(?:\r?\n|$)/, "").trimStart();
|
|
27550
|
+
continue;
|
|
27551
|
+
}
|
|
27552
|
+
if (normalized.startsWith("#")) {
|
|
27553
|
+
normalized = normalized.replace(/^#.*(?:\r?\n|$)/, "").trimStart();
|
|
27554
|
+
continue;
|
|
27555
|
+
}
|
|
27556
|
+
if (normalized.startsWith("/*")) {
|
|
27557
|
+
normalized = normalized.replace(/^\/\*[\s\S]*?\*\//, "").trimStart();
|
|
27558
|
+
continue;
|
|
27559
|
+
}
|
|
27560
|
+
break;
|
|
27561
|
+
}
|
|
27562
|
+
return normalized;
|
|
27563
|
+
}
|
|
27564
|
+
/** Return the leading SQL verb (uppercased), ignoring leading comments. */
|
|
27565
|
+
function getSqlVerb(sql) {
|
|
27566
|
+
const normalized = stripLeadingSqlComments(sql);
|
|
27567
|
+
const match = normalized.match(/^([a-zA-Z]+)/);
|
|
27568
|
+
return match ? match[1].toUpperCase() : "";
|
|
27569
|
+
}
|
|
27570
|
+
/**
|
|
27571
|
+
* Whether a *single* SQL statement is destructive (drops/truncates data or
|
|
27572
|
+
* removes/renames schema objects).
|
|
27573
|
+
*/
|
|
27574
|
+
function isDestructiveSql(sql) {
|
|
27575
|
+
const normalized = stripLeadingSqlComments(sql);
|
|
27576
|
+
const verb = getSqlVerb(normalized);
|
|
27577
|
+
if (["DROP", "TRUNCATE", "DELETE"].includes(verb)) {
|
|
27578
|
+
return true;
|
|
27579
|
+
}
|
|
27580
|
+
if (verb === "ALTER") {
|
|
27581
|
+
return /\b(DROP|RENAME)\b/i.test(normalized);
|
|
27582
|
+
}
|
|
27583
|
+
return false;
|
|
27584
|
+
}
|
|
27585
|
+
/**
|
|
27586
|
+
* Split a possibly multi-statement SQL script into individual statements.
|
|
27587
|
+
*
|
|
27588
|
+
* Naive split on `;` at statement boundaries, but aware of single/double quotes,
|
|
27589
|
+
* line/block comments, and PostgreSQL dollar-quoted strings ($$ ... $$ or
|
|
27590
|
+
* $tag$ ... $tag$) so semicolons inside string bodies / function definitions do
|
|
27591
|
+
* not split a statement. Good enough for the conservative destructive scan; not
|
|
27592
|
+
* a full parser.
|
|
27593
|
+
*/
|
|
27594
|
+
function splitSqlStatements(sqlText) {
|
|
27595
|
+
const statements = [];
|
|
27596
|
+
let current = "";
|
|
27597
|
+
let i = 0;
|
|
27598
|
+
const n = sqlText.length;
|
|
27599
|
+
while (i < n) {
|
|
27600
|
+
const ch = sqlText[i];
|
|
27601
|
+
const next = sqlText[i + 1];
|
|
27602
|
+
// line comment -- ... (to end of line)
|
|
27603
|
+
if (ch === "-" && next === "-") {
|
|
27604
|
+
const end = sqlText.indexOf("\n", i);
|
|
27605
|
+
const stop = end === -1 ? n : end + 1;
|
|
27606
|
+
current += sqlText.slice(i, stop);
|
|
27607
|
+
i = stop;
|
|
27608
|
+
continue;
|
|
27609
|
+
}
|
|
27610
|
+
// block comment /* ... */
|
|
27611
|
+
if (ch === "/" && next === "*") {
|
|
27612
|
+
const end = sqlText.indexOf("*/", i + 2);
|
|
27613
|
+
const stop = end === -1 ? n : end + 2;
|
|
27614
|
+
current += sqlText.slice(i, stop);
|
|
27615
|
+
i = stop;
|
|
27616
|
+
continue;
|
|
27617
|
+
}
|
|
27618
|
+
// single- or double-quoted string
|
|
27619
|
+
if (ch === "'" || ch === '"') {
|
|
27620
|
+
const quote = ch;
|
|
27621
|
+
current += ch;
|
|
27622
|
+
i += 1;
|
|
27623
|
+
while (i < n) {
|
|
27624
|
+
current += sqlText[i];
|
|
27625
|
+
// handle escaped quote by doubling ('' or "")
|
|
27626
|
+
if (sqlText[i] === quote) {
|
|
27627
|
+
if (sqlText[i + 1] === quote) {
|
|
27628
|
+
current += sqlText[i + 1];
|
|
27629
|
+
i += 2;
|
|
27630
|
+
continue;
|
|
27631
|
+
}
|
|
27632
|
+
i += 1;
|
|
27633
|
+
break;
|
|
27634
|
+
}
|
|
27635
|
+
i += 1;
|
|
27636
|
+
}
|
|
27637
|
+
continue;
|
|
27638
|
+
}
|
|
27639
|
+
// dollar-quoted string: $$ ... $$ or $tag$ ... $tag$
|
|
27640
|
+
if (ch === "$") {
|
|
27641
|
+
const tagMatch = sqlText.slice(i).match(/^\$([a-zA-Z_][a-zA-Z0-9_]*)?\$/);
|
|
27642
|
+
if (tagMatch) {
|
|
27643
|
+
const tag = tagMatch[0];
|
|
27644
|
+
const end = sqlText.indexOf(tag, i + tag.length);
|
|
27645
|
+
const stop = end === -1 ? n : end + tag.length;
|
|
27646
|
+
current += sqlText.slice(i, stop);
|
|
27647
|
+
i = stop;
|
|
27648
|
+
continue;
|
|
27649
|
+
}
|
|
27650
|
+
}
|
|
27651
|
+
if (ch === ";") {
|
|
27652
|
+
if (current.trim().length > 0) {
|
|
27653
|
+
statements.push(current.trim());
|
|
27654
|
+
}
|
|
27655
|
+
current = "";
|
|
27656
|
+
i += 1;
|
|
27657
|
+
continue;
|
|
27658
|
+
}
|
|
27659
|
+
current += ch;
|
|
27660
|
+
i += 1;
|
|
27661
|
+
}
|
|
27662
|
+
if (current.trim().length > 0) {
|
|
27663
|
+
statements.push(current.trim());
|
|
27664
|
+
}
|
|
27665
|
+
return statements;
|
|
27666
|
+
}
|
|
27667
|
+
/**
|
|
27668
|
+
* Scan a (possibly multi-statement) SQL script and return the destructive
|
|
27669
|
+
* statements found. Empty array means no destructive statement detected.
|
|
27670
|
+
*/
|
|
27671
|
+
function findDestructiveStatements(sqlText) {
|
|
27672
|
+
return splitSqlStatements(sqlText).filter((stmt) => isDestructiveSql(stmt));
|
|
27673
|
+
}
|
|
27674
|
+
|
|
27675
|
+
|
|
27039
27676
|
/***/ },
|
|
27040
27677
|
|
|
27041
27678
|
/***/ 5198
|
|
@@ -27109,7 +27746,7 @@ class TelemetryReporter {
|
|
|
27109
27746
|
const arch = os_1.default.arch(); // 系统架构
|
|
27110
27747
|
// Build-time injected version; guard for vitest / non-webpack runtimes.
|
|
27111
27748
|
const mcpVersion = process.env.npm_package_version ||
|
|
27112
|
-
( true ? "2.33.
|
|
27749
|
+
( true ? "2.33.2" : 0);
|
|
27113
27750
|
return {
|
|
27114
27751
|
userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
|
|
27115
27752
|
deviceId: this.deviceId,
|
|
@@ -27701,7 +28338,7 @@ ${envIdSection}
|
|
|
27701
28338
|
## 环境信息
|
|
27702
28339
|
- 操作系统: ${os_1.default.type()} ${os_1.default.release()}
|
|
27703
28340
|
- Node.js版本: ${process.version}
|
|
27704
|
-
- MCP 版本:${process.env.npm_package_version || ( true ? "2.33.
|
|
28341
|
+
- MCP 版本:${process.env.npm_package_version || ( true ? "2.33.2" : 0)}
|
|
27705
28342
|
- 系统架构: ${os_1.default.arch()}
|
|
27706
28343
|
- 时间: ${new Date().toISOString()}
|
|
27707
28344
|
- 请求ID: ${requestId}
|
|
@@ -27790,7 +28427,7 @@ function createWrappedHandler(name, handler, server) {
|
|
|
27790
28427
|
requestId,
|
|
27791
28428
|
ide: server.ide || process.env.INTEGRATION_IDE || ''
|
|
27792
28429
|
});
|
|
27793
|
-
const mcpVersion = true ? "2.33.
|
|
28430
|
+
const mcpVersion = true ? "2.33.2" : 0;
|
|
27794
28431
|
const requestIdSuffix = requestId ? `\n🆔 RequestId: ${requestId}` : '';
|
|
27795
28432
|
const enhancedErrorMessage = `${errorMessage}${requestIdSuffix}\n\n📦 CloudBase MCP v${mcpVersion}\n🔗 遇到问题?请复制以下链接到浏览器打开\n即可自动携带错误详情快速创建 GitHub Issue:\n${issueLink}`;
|
|
27796
28433
|
// 创建新的错误对象,保持原有的错误类型但更新消息
|
|
@@ -27959,7 +28596,7 @@ var x = (y) => {
|
|
|
27959
28596
|
var x = {}; __webpack_require__.d(x, y); return x
|
|
27960
28597
|
}
|
|
27961
28598
|
var y = (x) => (() => (x))
|
|
27962
|
-
module.exports = x({ ["AuthSupervisor"]: () => (__WEBPACK_EXTERNAL_MODULE__cloudbase_toolbox_034e5bd0__.AuthSupervisor), ["authStore"]: () => (__WEBPACK_EXTERNAL_MODULE__cloudbase_toolbox_034e5bd0__.authStore), ["loadEnvVariables"]: () => (__WEBPACK_EXTERNAL_MODULE__cloudbase_toolbox_034e5bd0__.loadEnvVariables), ["refreshTmpToken"]: () => (__WEBPACK_EXTERNAL_MODULE__cloudbase_toolbox_034e5bd0__.refreshTmpToken), ["resolveCredential"]: () => (__WEBPACK_EXTERNAL_MODULE__cloudbase_toolbox_034e5bd0__.resolveCredential) });
|
|
28599
|
+
module.exports = x({ ["AuthSupervisor"]: () => (__WEBPACK_EXTERNAL_MODULE__cloudbase_toolbox_034e5bd0__.AuthSupervisor), ["ConfigParser"]: () => (__WEBPACK_EXTERNAL_MODULE__cloudbase_toolbox_034e5bd0__.ConfigParser), ["authStore"]: () => (__WEBPACK_EXTERNAL_MODULE__cloudbase_toolbox_034e5bd0__.authStore), ["loadConfig"]: () => (__WEBPACK_EXTERNAL_MODULE__cloudbase_toolbox_034e5bd0__.loadConfig), ["loadEnvVariables"]: () => (__WEBPACK_EXTERNAL_MODULE__cloudbase_toolbox_034e5bd0__.loadEnvVariables), ["refreshTmpToken"]: () => (__WEBPACK_EXTERNAL_MODULE__cloudbase_toolbox_034e5bd0__.refreshTmpToken), ["resolveCredential"]: () => (__WEBPACK_EXTERNAL_MODULE__cloudbase_toolbox_034e5bd0__.resolveCredential), ["searchConfig"]: () => (__WEBPACK_EXTERNAL_MODULE__cloudbase_toolbox_034e5bd0__.searchConfig), ["validateCloudBaseConfigBySchema"]: () => (__WEBPACK_EXTERNAL_MODULE__cloudbase_toolbox_034e5bd0__.validateCloudBaseConfigBySchema) });
|
|
27963
28600
|
|
|
27964
28601
|
/***/ },
|
|
27965
28602
|
|
|
@@ -28078,13 +28715,9 @@ module.exports = x({ ["randomUUID"]: () => (__WEBPACK_EXTERNAL_MODULE_node_crypt
|
|
|
28078
28715
|
/***/ },
|
|
28079
28716
|
|
|
28080
28717
|
/***/ 9627
|
|
28081
|
-
(module
|
|
28718
|
+
(module) {
|
|
28082
28719
|
|
|
28083
|
-
|
|
28084
|
-
var x = {}; __webpack_require__.d(x, y); return x
|
|
28085
|
-
}
|
|
28086
|
-
var y = (x) => (() => (x))
|
|
28087
|
-
module.exports = x({ ["existsSync"]: () => (__WEBPACK_EXTERNAL_MODULE_node_fs_75ed2103__.existsSync), ["readFileSync"]: () => (__WEBPACK_EXTERNAL_MODULE_node_fs_75ed2103__.readFileSync) });
|
|
28720
|
+
module.exports = __WEBPACK_EXTERNAL_MODULE_node_fs_75ed2103__;
|
|
28088
28721
|
|
|
28089
28722
|
/***/ },
|
|
28090
28723
|
|