@cloudbase/cloudbase-mcp 2.32.1 → 2.32.3
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 +5 -5
- package/dist/index.cjs +326 -33
- package/dist/index.js +293 -27
- package/package.json +1 -1
- package/server.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -4220,6 +4220,31 @@ function applyBoundEnvRegion(server, region) {
|
|
|
4220
4220
|
server.cloudBaseOptions.region = region;
|
|
4221
4221
|
}
|
|
4222
4222
|
}
|
|
4223
|
+
/**
|
|
4224
|
+
* 绑定环境后固化站点:region 歧义(如 ap-singapore 同时属于 domestic 与 intl)且
|
|
4225
|
+
* 未显式指定 site 时,若仅一个凭证槽位可用,则将 TCB_SITE 固定为该站点,
|
|
4226
|
+
* 避免后续资源调用再次落入歧义默认分支(issue #960)。
|
|
4227
|
+
*/
|
|
4228
|
+
async function applyBoundEnvSite(server, region) {
|
|
4229
|
+
if (!region || (0, site_map_js_1.getSite)(region) !== "ambiguous") {
|
|
4230
|
+
return;
|
|
4231
|
+
}
|
|
4232
|
+
if ((0, site_map_js_1.normalizeSite)(process.env.TCB_SITE)) {
|
|
4233
|
+
return; // 已显式指定 site,不覆盖
|
|
4234
|
+
}
|
|
4235
|
+
const usableSites = await (0, auth_js_1.listUsableCredentialSites)();
|
|
4236
|
+
if (usableSites.length !== 1) {
|
|
4237
|
+
return; // 无法唯一判定时不猜测,保持既有歧义回退逻辑
|
|
4238
|
+
}
|
|
4239
|
+
process.env.TCB_SITE = usableSites[0];
|
|
4240
|
+
if (server.cloudBaseOptions) {
|
|
4241
|
+
server.cloudBaseOptions.site = usableSites[0];
|
|
4242
|
+
}
|
|
4243
|
+
(0, logger_js_1.debug)("applyBoundEnvSite: pinned TCB_SITE from the only usable credential slot", {
|
|
4244
|
+
region,
|
|
4245
|
+
site: usableSites[0],
|
|
4246
|
+
});
|
|
4247
|
+
}
|
|
4223
4248
|
const CODEBUDDY_AUTH_ACTIONS = ["status", "set_env", "login_by_api_key"];
|
|
4224
4249
|
const DEFAULT_AUTH_ACTIONS = [
|
|
4225
4250
|
"status",
|
|
@@ -5494,7 +5519,17 @@ function registerEnvTools(server) {
|
|
|
5494
5519
|
: {}),
|
|
5495
5520
|
onDeviceCode: deviceOnCode,
|
|
5496
5521
|
})
|
|
5497
|
-
.then(() => {
|
|
5522
|
+
.then(async () => {
|
|
5523
|
+
// toolbox 将新凭证写入 flat 'credential',这里迁移为分槽格式
|
|
5524
|
+
//(legacy flat 等价 domestic 槽位),对齐 ensureLogin() 的分槽行为
|
|
5525
|
+
try {
|
|
5526
|
+
await (0, auth_js_1.ensureSlottedCredential)();
|
|
5527
|
+
}
|
|
5528
|
+
catch (err) {
|
|
5529
|
+
(0, logger_js_1.debug)("device auth: slotted credential migration failed", {
|
|
5530
|
+
error: err instanceof Error ? err.message : String(err),
|
|
5531
|
+
});
|
|
5532
|
+
}
|
|
5498
5533
|
(0, auth_js_1.resolveAuthProgressState)();
|
|
5499
5534
|
})
|
|
5500
5535
|
.catch((err) => {
|
|
@@ -5706,7 +5741,17 @@ function registerEnvTools(server) {
|
|
|
5706
5741
|
});
|
|
5707
5742
|
}
|
|
5708
5743
|
await cloudbase_manager_js_1.envManager.setEnvId(envId);
|
|
5744
|
+
// 跨客户端通用事件推送(MCP 协议 notification,无 id):任何客户端
|
|
5745
|
+
// (如 dsh-plugin 面板)都能通过 notifications/cloudbase/env_changed
|
|
5746
|
+
// 感知环境变更,替代客户端本地推断与兜底轮询。通知失败不影响主流程。
|
|
5747
|
+
void server.server
|
|
5748
|
+
.notification({
|
|
5749
|
+
method: "notifications/cloudbase/env_changed",
|
|
5750
|
+
params: { envId },
|
|
5751
|
+
})
|
|
5752
|
+
.catch(() => { });
|
|
5709
5753
|
applyBoundEnvRegion(server, target?.region);
|
|
5754
|
+
await applyBoundEnvSite(server, target?.region);
|
|
5710
5755
|
const regionHint = target?.region
|
|
5711
5756
|
? `,地域: ${target.region}`
|
|
5712
5757
|
: target
|
|
@@ -29542,14 +29587,20 @@ async function throwPendingAuthError() {
|
|
|
29542
29587
|
async function throwEnvRequiredError(options) {
|
|
29543
29588
|
const envCandidates = options?.envCandidates ?? (await listAvailableEnvCandidates(options));
|
|
29544
29589
|
const singleEnvId = envCandidates.length === 1 ? envCandidates[0].envId : undefined;
|
|
29590
|
+
// 终止性引导:明确「重试当前工具不会成功」,给出可直接执行的替代动作与
|
|
29591
|
+
// 无头/无人值守环境的 fallback(CLOUDBASE_ENV_ID 或宿主配置传入 envId),
|
|
29592
|
+
// 避免客户端把本错误当作可重试错误陷入死循环(2026-08-20 单日 15 万次重试风暴)。
|
|
29593
|
+
const retryHint = "重试当前工具不会成功,请停止原样重试。";
|
|
29594
|
+
const headlessHint = "若运行在无浏览器/无人值守环境而无法交互完成登录绑定,可在启动 MCP 前设置 CLOUDBASE_ENV_ID 环境变量指定默认环境。";
|
|
29595
|
+
const message = envCandidates.length === 0
|
|
29596
|
+
? `当前已登录,但还没有可用环境。${retryHint}请改为在腾讯云控制台创建 CloudBase 环境后重新绑定;${headlessHint}`
|
|
29597
|
+
: envCandidates.length === 1
|
|
29598
|
+
? `当前已登录,但尚未绑定环境。${retryHint}请先调用 auth(action="set_env", envId="${singleEnvId}") 完成绑定后再继续;${headlessHint}`
|
|
29599
|
+
: `当前已登录,但尚未绑定环境。${retryHint}请先调用 auth(action="set_env", envId=候选环境之一) 完成绑定后再继续;${headlessHint}`;
|
|
29545
29600
|
(0, tool_result_js_1.throwToolPayloadError)({
|
|
29546
29601
|
ok: false,
|
|
29547
29602
|
code: "ENV_REQUIRED",
|
|
29548
|
-
message
|
|
29549
|
-
? "当前已登录,但还没有可用环境,请先调用 auth 工具完成环境选择或创建环境。"
|
|
29550
|
-
: envCandidates.length === 1
|
|
29551
|
-
? `当前已登录,但尚未绑定环境。可直接选择环境 ${singleEnvId}。`
|
|
29552
|
-
: "当前已登录,但尚未绑定环境,请先调用 auth 工具选择环境。",
|
|
29603
|
+
message,
|
|
29553
29604
|
env_candidates: envCandidates,
|
|
29554
29605
|
next_step: (0, tool_result_js_1.buildAuthNextStep)("set_env", {
|
|
29555
29606
|
requiredParams: singleEnvId ? undefined : ["envId"],
|
|
@@ -73039,10 +73090,16 @@ function registerMsgPushTools(server) {
|
|
|
73039
73090
|
return buildTransportUnavailablePayload("queryMessagePush", action);
|
|
73040
73091
|
}
|
|
73041
73092
|
if (action === "list") {
|
|
73042
|
-
const [state,
|
|
73093
|
+
const [state, containerRaw] = await Promise.all([
|
|
73043
73094
|
readCallbackConfig(server, appid),
|
|
73044
|
-
|
|
73095
|
+
// 兼容性降级:微信侧 apihttpagent 通道不支持 getcontainercallbackconfig
|
|
73096
|
+
// (ret=-9991)时,容器配置读取失败不阻断 list(pushMode 默认 cloudfunction)
|
|
73097
|
+
readContainerConfig(server, appid).catch((e) => {
|
|
73098
|
+
console.warn(`[msg-push] 读取云托管容器配置失败,降级为云函数模式推断: ${e instanceof Error ? e.message : String(e)}`);
|
|
73099
|
+
return null;
|
|
73100
|
+
}),
|
|
73045
73101
|
]);
|
|
73102
|
+
const container = containerRaw;
|
|
73046
73103
|
const pushMode = resolvePushMode(container);
|
|
73047
73104
|
const callbacks = env
|
|
73048
73105
|
? state.list.filter((c) => c.env === env)
|
|
@@ -129447,9 +129504,55 @@ function buildUploadErrorMessage(error, localPath) {
|
|
|
129447
129504
|
}
|
|
129448
129505
|
return `[manageHosting(upload)] ${baseMessage}\n建议:${suggestions.join(' ')}`;
|
|
129449
129506
|
}
|
|
129507
|
+
/**
|
|
129508
|
+
* TCB 管控面 DescribeStaticStore 接口 QPS 限流(20 次/秒)。
|
|
129509
|
+
* Manager SDK 的 hosting.deleteFiles / uploadFiles / findFiles 等每次调用
|
|
129510
|
+
* 都会先 checkStatus() → getInfo() → DescribeStaticStore(无缓存),
|
|
129511
|
+
* AI 连续快速删除多个文件或失败后立即重试时极易触发该限流。
|
|
129512
|
+
*/
|
|
129513
|
+
const DESCRIBE_STATIC_STORE_RATE_LIMIT_RE = /\[DescribeStaticStore\][\s\S]*exceeds the frequency limit `20` for a second/i;
|
|
129514
|
+
function buildDeleteErrorMessage(error) {
|
|
129515
|
+
const baseMessage = error instanceof Error ? error.message : String(error);
|
|
129516
|
+
if (DESCRIBE_STATIC_STORE_RATE_LIMIT_RE.test(baseMessage)) {
|
|
129517
|
+
return (`[manageHosting(delete)] ${baseMessage}\n` +
|
|
129518
|
+
'原因:静态托管底层 DescribeStaticStore 管控接口有 20 次/秒的 QPS 限制,' +
|
|
129519
|
+
'连续快速删除多个文件(或失败后立即重试)容易触发限流,删除操作本身可能已经部分生效。\n' +
|
|
129520
|
+
'处理建议:\n' +
|
|
129521
|
+
'1) 等待 1-2 秒后重试本次删除,不要立即连续重试;\n' +
|
|
129522
|
+
'2) 批量删除多个文件时,逐次调用并保持间隔(建议每秒不超过 10 次),不要并发或循环快速重试;\n' +
|
|
129523
|
+
'3) 同一目录下的多个文件可改用 isDir=true 一次删除整个目录,减少调用次数;\n' +
|
|
129524
|
+
'4) 若不确定删除是否已生效,可调用 queryHosting(action="findFiles") 核对。');
|
|
129525
|
+
}
|
|
129526
|
+
return `[manageHosting(delete)] ${baseMessage}`;
|
|
129527
|
+
}
|
|
129450
129528
|
function isRecord(value) {
|
|
129451
129529
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
129452
129530
|
}
|
|
129531
|
+
/**
|
|
129532
|
+
* Manager SDK hosting.deleteFiles 对 COS 删除失败不抛异常,返回
|
|
129533
|
+
* { Deleted: [], Error: [e] };此处提取 Error 数组为可读字符串列表,
|
|
129534
|
+
* 供 delete 路径做失败判定与引导。
|
|
129535
|
+
*/
|
|
129536
|
+
function extractDeleteErrors(result) {
|
|
129537
|
+
if (!isRecord(result)) {
|
|
129538
|
+
return [];
|
|
129539
|
+
}
|
|
129540
|
+
const rawErrors = result.Error ?? result.error;
|
|
129541
|
+
if (!Array.isArray(rawErrors)) {
|
|
129542
|
+
return [];
|
|
129543
|
+
}
|
|
129544
|
+
return rawErrors
|
|
129545
|
+
.map((item) => {
|
|
129546
|
+
if (typeof item === 'string' && item.trim()) {
|
|
129547
|
+
return item.trim();
|
|
129548
|
+
}
|
|
129549
|
+
if (isRecord(item) && typeof item.message === 'string') {
|
|
129550
|
+
return item.message;
|
|
129551
|
+
}
|
|
129552
|
+
return JSON.stringify(item);
|
|
129553
|
+
})
|
|
129554
|
+
.filter(Boolean);
|
|
129555
|
+
}
|
|
129453
129556
|
function getRecordString(record, keys) {
|
|
129454
129557
|
for (const key of keys) {
|
|
129455
129558
|
const value = record[key];
|
|
@@ -129674,11 +129777,24 @@ async function getHostingStoreOrThrow(cloudbase, cloudBaseOptions, logger) {
|
|
|
129674
129777
|
}
|
|
129675
129778
|
throw new Error(`当前环境 ${envId} 未发现静态托管资源配置,无法上传文件。请先确认 MCP 已绑定到已开通静态托管的 CloudBase 环境;如需切换环境,请调用 auth(action="set_env", envId="目标环境ID") 后重试。`);
|
|
129676
129779
|
}
|
|
129780
|
+
function enrichRateLimitMessage(message) {
|
|
129781
|
+
// delete 路径已由 buildDeleteErrorMessage 提供完整引导,避免重复追加
|
|
129782
|
+
if (message.includes('QPS 限制') || message.includes('等待 1-2 秒后重试')) {
|
|
129783
|
+
return message;
|
|
129784
|
+
}
|
|
129785
|
+
if (DESCRIBE_STATIC_STORE_RATE_LIMIT_RE.test(message)) {
|
|
129786
|
+
return (`${message}\n` +
|
|
129787
|
+
'原因:静态托管底层 DescribeStaticStore 管控接口有 20 次/秒的 QPS 限制,' +
|
|
129788
|
+
'连续快速调用(或失败后立即重试)容易触发限流,本次查询/操作可能没有完整生效。\n' +
|
|
129789
|
+
'处理建议:等待 1-2 秒后重试,不要连续快速重试;多个文件操作请逐次调用并保持间隔。');
|
|
129790
|
+
}
|
|
129791
|
+
return message;
|
|
129792
|
+
}
|
|
129677
129793
|
function buildFailureResult(action, error) {
|
|
129678
129794
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
129679
129795
|
success: false,
|
|
129680
129796
|
errorCode: `HOSTING_${action.toUpperCase()}_FAILED`,
|
|
129681
|
-
message: error instanceof Error ? error.message : String(error),
|
|
129797
|
+
message: enrichRateLimitMessage(error instanceof Error ? error.message : String(error)),
|
|
129682
129798
|
});
|
|
129683
129799
|
}
|
|
129684
129800
|
function normalizeFileFields(files) {
|
|
@@ -129858,7 +129974,7 @@ function registerHostingTools(server) {
|
|
|
129858
129974
|
});
|
|
129859
129975
|
server.registerTool('manageHosting', {
|
|
129860
129976
|
title: '管理 CloudBase 静态托管',
|
|
129861
|
-
description: '管理 CloudBase 静态托管的变更操作。action=upload 上传本地构建产物到共享域名(域名格式:<envId>-<appId>.tcloudbaseapp.com/<cloudPath>);action=delete 删除托管文件或目录(必须 confirm=true);action=setWebsiteDocument 设置首页/错误页/路由规则;action=enableService 开通静态托管;action=bindDomain / unbindDomain / updateDomain 管理自定义域名;action=downloadFile / downloadDirectory 下载托管内容到本地。⚠️ 本工具没有关闭默认域名(*.tcloudbaseapp.com)的 action;要禁用该默认公网域名,请用 manageGateway(action="disableRoute", domain=该 STATIC_STORE IsDefault 域名, path="/")(底层 ModifyHTTPServiceRoute,不是 ModifyGatewayRoute)。⚠️ 新项目部署优先使用 manageApps(部署到独立子域名),本工具适合已有老项目继续使用或作为 manageApps 的 fallback。manageApps 与 manageHosting 域名不同,切换会导致老链接失效。若任务只是查看配置、文件或域名状态,请改用 queryHosting。',
|
|
129977
|
+
description: '管理 CloudBase 静态托管的变更操作。action=upload 上传本地构建产物到共享域名(域名格式:<envId>-<appId>.tcloudbaseapp.com/<cloudPath>);action=delete 删除托管文件或目录(必须 confirm=true);action=setWebsiteDocument 设置首页/错误页/路由规则;action=enableService 开通静态托管;action=bindDomain / unbindDomain / updateDomain 管理自定义域名;action=downloadFile / downloadDirectory 下载托管内容到本地。⚠️ 底层每次托管操作都会请求 DescribeStaticStore 管控接口(20 次/秒 QPS 限制):批量删除多个文件请逐次调用并保持间隔(建议每秒不超过 10 次),同一目录下多个文件可优先用 isDir=true 一次删除整个目录;若报错含 "frequency limit" 说明触发了限流,请等待 1-2 秒后重试,不要连续快速重试。⚠️ 本工具没有关闭默认域名(*.tcloudbaseapp.com)的 action;要禁用该默认公网域名,请用 manageGateway(action="disableRoute", domain=该 STATIC_STORE IsDefault 域名, path="/")(底层 ModifyHTTPServiceRoute,不是 ModifyGatewayRoute)。⚠️ 新项目部署优先使用 manageApps(部署到独立子域名),本工具适合已有老项目继续使用或作为 manageApps 的 fallback。manageApps 与 manageHosting 域名不同,切换会导致老链接失效。若任务只是查看配置、文件或域名状态,请改用 queryHosting。',
|
|
129862
129978
|
inputSchema: manageHostingInputSchema,
|
|
129863
129979
|
annotations: {
|
|
129864
129980
|
readOnlyHint: false,
|
|
@@ -130028,14 +130144,27 @@ function registerHostingTools(server) {
|
|
|
130028
130144
|
if (!input.confirm) {
|
|
130029
130145
|
throw new Error('manageHosting(action="delete") 是破坏性操作,必须显式传 confirm=true。');
|
|
130030
130146
|
}
|
|
130031
|
-
|
|
130032
|
-
|
|
130033
|
-
|
|
130034
|
-
|
|
130147
|
+
let result;
|
|
130148
|
+
try {
|
|
130149
|
+
result = await cloudbase.hosting.deleteFiles({
|
|
130150
|
+
cloudPath: input.cloudPath,
|
|
130151
|
+
isDir: input.isDir ?? false,
|
|
130152
|
+
});
|
|
130153
|
+
}
|
|
130154
|
+
catch (error) {
|
|
130155
|
+
throw new Error(buildDeleteErrorMessage(error));
|
|
130156
|
+
}
|
|
130035
130157
|
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
130158
|
+
// Manager SDK 的 deleteFiles 对 COS 单文件删除失败不抛异常,
|
|
130159
|
+
// 而是返回 { Deleted: [], Error: [e] },需要显式检查 Error 数组。
|
|
130160
|
+
const deleteErrors = extractDeleteErrors(result);
|
|
130036
130161
|
// Post-validation: verify deletion was successful
|
|
130037
130162
|
let deleteVerified = true;
|
|
130038
130163
|
let verificationError;
|
|
130164
|
+
if (deleteErrors.length > 0) {
|
|
130165
|
+
deleteVerified = false;
|
|
130166
|
+
verificationError = `删除请求未生效:${deleteErrors.join(';')}`;
|
|
130167
|
+
}
|
|
130039
130168
|
try {
|
|
130040
130169
|
const checkResult = await cloudbase.hosting.findFiles({
|
|
130041
130170
|
prefix: input.cloudPath,
|
|
@@ -130043,7 +130172,7 @@ function registerHostingTools(server) {
|
|
|
130043
130172
|
});
|
|
130044
130173
|
if (Array.isArray(checkResult) && checkResult.length > 0) {
|
|
130045
130174
|
deleteVerified = false;
|
|
130046
|
-
verificationError = `删除后验证失败:文件仍在静态托管中`;
|
|
130175
|
+
verificationError = verificationError ?? `删除后验证失败:文件仍在静态托管中`;
|
|
130047
130176
|
}
|
|
130048
130177
|
}
|
|
130049
130178
|
catch (error) {
|
|
@@ -130062,7 +130191,11 @@ function registerHostingTools(server) {
|
|
|
130062
130191
|
},
|
|
130063
130192
|
message: deleteVerified
|
|
130064
130193
|
? `已删除静态托管${input.isDir ? '目录' : '文件'} \`${input.cloudPath}\`。`
|
|
130065
|
-
:
|
|
130194
|
+
: `删除操作已提交,但验证发现文件可能未完全删除。` +
|
|
130195
|
+
`可能原因:底层 COS 删除请求失败(如文件不存在、存储桶权限不足),或触发 DescribeStaticStore 限流后删除未生效。` +
|
|
130196
|
+
`建议:1) 等待 1-2 秒后用 queryHosting(action="findFiles", prefix="${input.cloudPath}") 核对文件状态;` +
|
|
130197
|
+
`2) 若确认文件仍存在,重新调用 manageHosting(action="delete", confirm=true) 重试;` +
|
|
130198
|
+
`3) 批量删除多个文件请逐次调用并保持间隔(DescribeStaticStore 有 20 次/秒 QPS 限制)。`,
|
|
130066
130199
|
});
|
|
130067
130200
|
}
|
|
130068
130201
|
case 'setWebsiteDocument': {
|
|
@@ -138362,6 +138495,11 @@ function buildCapiErrorMessage(service, action, error) {
|
|
|
138362
138495
|
function registerCapiTools(server) {
|
|
138363
138496
|
const cloudBaseOptions = server.cloudBaseOptions;
|
|
138364
138497
|
const logger = server.logger;
|
|
138498
|
+
// commonService 透传调用只依赖凭据上下文(secretId/secretKey/token/region),
|
|
138499
|
+
// EnvId 由 params 携带,不依赖 MCP 绑定的环境。强制绑定会在「已登录但未绑环境」
|
|
138500
|
+
// 场景把 DescribeEnvs/CreateEnv/CAM 等无 env 依赖的 Action 全部挡在 ENV_REQUIRED,
|
|
138501
|
+
// 并诱发无头客户端原样重试风暴(2026-08-20 单日 15 万次报错),故豁免环境绑定。
|
|
138502
|
+
const getManager = () => (0, cloudbase_manager_js_1.getCloudBaseManager)({ cloudBaseOptions, requireEnvId: false });
|
|
138365
138503
|
server.registerTool?.("callCloudApi", {
|
|
138366
138504
|
title: "调用云API",
|
|
138367
138505
|
description: `通用的云 API 调用工具,主要用于 CloudBase / 腾讯云管控面与依赖资源相关 API 调用。调用前请先确认 service、Action 与 Param,避免猜测 Action 名称。如果你的目标是通过 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 分类如下:
|
|
@@ -149409,7 +149547,7 @@ class TelemetryReporter {
|
|
|
149409
149547
|
const arch = os_1.default.arch(); // 系统架构
|
|
149410
149548
|
// Build-time injected version; guard for vitest / non-webpack runtimes.
|
|
149411
149549
|
const mcpVersion = process.env.npm_package_version ||
|
|
149412
|
-
( true ? "2.32.
|
|
149550
|
+
( true ? "2.32.3" : 0);
|
|
149413
149551
|
return {
|
|
149414
149552
|
userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
|
|
149415
149553
|
deviceId: this.deviceId,
|
|
@@ -177120,20 +177258,26 @@ async function resolvePgDbContext(cloudBaseOptions, args) {
|
|
|
177120
177258
|
envId,
|
|
177121
177259
|
instanceId: args?.instanceId ?? "cloudbase-pg",
|
|
177122
177260
|
defaultSchema: args?.defaultSchema ?? "public",
|
|
177123
|
-
role: args?.role ??
|
|
177261
|
+
role: args?.role ?? PG_DEFAULT_ROLE,
|
|
177124
177262
|
};
|
|
177125
177263
|
}
|
|
177126
177264
|
/** Default / recommended roles for CloudBase PG ExecutePGSql.Role */
|
|
177127
|
-
const PG_DEFAULT_ROLE = "
|
|
177265
|
+
const PG_DEFAULT_ROLE = "cloudbase_postgres";
|
|
177128
177266
|
const PG_RECOMMENDED_ROLES = [
|
|
177129
|
-
"
|
|
177267
|
+
"cloudbase_postgres",
|
|
177130
177268
|
"anon",
|
|
177131
177269
|
"authenticated",
|
|
177132
177270
|
"service_role",
|
|
177133
177271
|
];
|
|
177272
|
+
/**
|
|
177273
|
+
* Platform-owned admin roles. cloudbase_admin is the platform management
|
|
177274
|
+
* account and must not be used by user-facing ExecutePGSql calls.
|
|
177275
|
+
*/
|
|
177276
|
+
const PG_PLATFORM_RESERVED_ROLES = ["cloudbase_admin"];
|
|
177134
177277
|
/**
|
|
177135
177278
|
* Roles that look like login/instance principals and routinely fail SET ROLE
|
|
177136
177279
|
* in beacon data (e.g. postgres, postgres_pgdb_<id>). Reject before the API call.
|
|
177280
|
+
* Also rejects platform-reserved roles (cloudbase_admin) that are not for user calls.
|
|
177137
177281
|
*/
|
|
177138
177282
|
function isLikelyInvalidPgExecuteRole(role) {
|
|
177139
177283
|
const normalized = role.trim();
|
|
@@ -177143,6 +177287,10 @@ function isLikelyInvalidPgExecuteRole(role) {
|
|
|
177143
177287
|
if (normalized === "postgres") {
|
|
177144
177288
|
return true;
|
|
177145
177289
|
}
|
|
177290
|
+
// Platform management account, reserved for the platform itself.
|
|
177291
|
+
if (PG_PLATFORM_RESERVED_ROLES.includes(normalized)) {
|
|
177292
|
+
return true;
|
|
177293
|
+
}
|
|
177146
177294
|
// Instance-derived login principals, not valid ExecutePGSql Role targets
|
|
177147
177295
|
if (/^postgres_pgdb_[a-z0-9]+$/i.test(normalized)) {
|
|
177148
177296
|
return true;
|
|
@@ -177179,8 +177327,10 @@ function isPgRoleExecutionError(message) {
|
|
|
177179
177327
|
}
|
|
177180
177328
|
function buildPgRoleGuidanceMessage(attemptedRole) {
|
|
177181
177329
|
const recommended = PG_RECOMMENDED_ROLES.join(", ");
|
|
177330
|
+
const reserved = PG_PLATFORM_RESERVED_ROLES.join(", ");
|
|
177182
177331
|
return (`PostgreSQL role "${attemptedRole}" cannot be used with ExecutePGSql (SET ROLE failed or role does not exist). ` +
|
|
177183
177332
|
`Do not invent roles like postgres / postgres_pgdb_* from env or instance names. ` +
|
|
177333
|
+
`Platform-reserved roles (${reserved}) are the platform management account and must not be used by user calls. ` +
|
|
177184
177334
|
`Omit role (defaults to ${PG_DEFAULT_ROLE}) or pass one of: ${recommended}. ` +
|
|
177185
177335
|
`To list roles that exist in this database, retry with role=${PG_DEFAULT_ROLE} and SQL: SELECT rolname FROM pg_roles ORDER BY rolname;`);
|
|
177186
177336
|
}
|
|
@@ -179449,7 +179599,7 @@ function registerPGDatabaseTools(server, providedDeps) {
|
|
|
179449
179599
|
.optional()
|
|
179450
179600
|
.describe(`可选的 PostgreSQL role,传给 Manager SDK executePGSql 的 Role(平台会 SET ROLE)。默认 ${PG_DEFAULT_ROLE}。` +
|
|
179451
179601
|
`推荐取值:${PG_RECOMMENDED_ROLES.join(" / ")}。` +
|
|
179452
|
-
`不要传 postgres、postgres_pgdb_
|
|
179602
|
+
`不要传 postgres、postgres_pgdb_*、平台保留角色(${PG_PLATFORM_RESERVED_ROLES.join("、")},为平台管理账号不对用户开放)或从环境名臆造的角色;不确定时省略本字段,或先用 ${PG_DEFAULT_ROLE} 执行 SELECT rolname FROM pg_roles。`),
|
|
179453
179603
|
objectName: zod_1.z
|
|
179454
179604
|
.string()
|
|
179455
179605
|
.optional()
|
|
@@ -192954,6 +193104,87 @@ module.exports = Tar;
|
|
|
192954
193104
|
*/
|
|
192955
193105
|
|
|
192956
193106
|
|
|
193107
|
+
/***/ }),
|
|
193108
|
+
|
|
193109
|
+
/***/ 60827:
|
|
193110
|
+
/***/ ((__unused_webpack_module, exports) => {
|
|
193111
|
+
|
|
193112
|
+
"use strict";
|
|
193113
|
+
|
|
193114
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
193115
|
+
exports.REPEAT_GUARD_THRESHOLD = void 0;
|
|
193116
|
+
exports.applyRepeatGuardToPayload = applyRepeatGuardToPayload;
|
|
193117
|
+
exports.resetRepeatGuard = resetRepeatGuard;
|
|
193118
|
+
exports.__resetRepeatGuardForTests = __resetRepeatGuardForTests;
|
|
193119
|
+
/**
|
|
193120
|
+
* 连续重复错误熔断(repeat guard)。
|
|
193121
|
+
*
|
|
193122
|
+
* 背景:无头自动化客户端收到结构化引导错误(如 ENV_REQUIRED)后,可能不执行
|
|
193123
|
+
* 引导动作而是原样重试,形成重试风暴(2026-08-20 单日 15 万次同文案报错)。
|
|
193124
|
+
* 本模块在同一进程(≈同一 MCP session)内跟踪连续相同错误:
|
|
193125
|
+
* - 连续次数达到阈值后,在 payload 注入 repeat_guard 升级字段,提醒模型
|
|
193126
|
+
* 「原样重试无效,必须先完成 next_step 指向的修复动作」;
|
|
193127
|
+
* - 不改写 message 本身,保持灯塔侧按错误文案聚合的稳定性;
|
|
193128
|
+
* - 任一工具调用成功即整体清零(说明循环已被打破)。
|
|
193129
|
+
*/
|
|
193130
|
+
exports.REPEAT_GUARD_THRESHOLD = 3;
|
|
193131
|
+
const REPEAT_GUARD_KEY_MAX_LENGTH = 200;
|
|
193132
|
+
let lastKey = null;
|
|
193133
|
+
let consecutiveCount = 0;
|
|
193134
|
+
function buildRepeatGuardKey(payload) {
|
|
193135
|
+
const code = typeof payload.code === "string" ? payload.code : "";
|
|
193136
|
+
const message = typeof payload.message === "string" ? payload.message : "";
|
|
193137
|
+
return `${code}|${message.slice(0, REPEAT_GUARD_KEY_MAX_LENGTH)}`;
|
|
193138
|
+
}
|
|
193139
|
+
function buildRepeatGuardNotice(count) {
|
|
193140
|
+
return (`当前会话已连续 ${count} 次返回相同错误。原样重试不会成功:` +
|
|
193141
|
+
"请停止重试当前调用,先按 payload 中的 message / next_step 完成修复动作" +
|
|
193142
|
+
"(如完成 auth 登录或绑定环境),或调整参数后再继续。");
|
|
193143
|
+
}
|
|
193144
|
+
/**
|
|
193145
|
+
* 记录一次结构化工具错误;达到阈值时返回注入 repeat_guard 的新 payload。
|
|
193146
|
+
*/
|
|
193147
|
+
function applyRepeatGuardToPayload(payload) {
|
|
193148
|
+
if (!payload || typeof payload !== "object") {
|
|
193149
|
+
return payload;
|
|
193150
|
+
}
|
|
193151
|
+
const key = buildRepeatGuardKey(payload);
|
|
193152
|
+
if (key === lastKey) {
|
|
193153
|
+
consecutiveCount += 1;
|
|
193154
|
+
}
|
|
193155
|
+
else {
|
|
193156
|
+
lastKey = key;
|
|
193157
|
+
consecutiveCount = 1;
|
|
193158
|
+
}
|
|
193159
|
+
if (consecutiveCount < exports.REPEAT_GUARD_THRESHOLD) {
|
|
193160
|
+
return payload;
|
|
193161
|
+
}
|
|
193162
|
+
const code = typeof payload.code === "string" && payload.code.length > 0
|
|
193163
|
+
? payload.code
|
|
193164
|
+
: "UNKNOWN";
|
|
193165
|
+
const repeatGuard = {
|
|
193166
|
+
code,
|
|
193167
|
+
consecutive_count: consecutiveCount,
|
|
193168
|
+
threshold: exports.REPEAT_GUARD_THRESHOLD,
|
|
193169
|
+
notice: buildRepeatGuardNotice(consecutiveCount),
|
|
193170
|
+
};
|
|
193171
|
+
return { ...payload, repeat_guard: repeatGuard };
|
|
193172
|
+
}
|
|
193173
|
+
/**
|
|
193174
|
+
* 工具调用成功时清零计数。
|
|
193175
|
+
*/
|
|
193176
|
+
function resetRepeatGuard() {
|
|
193177
|
+
lastKey = null;
|
|
193178
|
+
consecutiveCount = 0;
|
|
193179
|
+
}
|
|
193180
|
+
/**
|
|
193181
|
+
* 测试辅助:恢复初始状态。
|
|
193182
|
+
*/
|
|
193183
|
+
function __resetRepeatGuardForTests() {
|
|
193184
|
+
resetRepeatGuard();
|
|
193185
|
+
}
|
|
193186
|
+
|
|
193187
|
+
|
|
192957
193188
|
/***/ }),
|
|
192958
193189
|
|
|
192959
193190
|
/***/ 60890:
|
|
@@ -222687,7 +222918,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
|
222687
222918
|
exports.CloudBaseContext = void 0;
|
|
222688
222919
|
const constant_1 = __webpack_require__(40762);
|
|
222689
222920
|
class CloudBaseContext {
|
|
222690
|
-
constructor({ secretId = '', secretKey = '', token = '', proxy = '', region = '', envType = '', useInternalEndpoint = undefined, internalEndpointRegion = undefined }) {
|
|
222921
|
+
constructor({ secretId = '', secretKey = '', token = '', proxy = '', region = '', envType = '', useInternalEndpoint = undefined, internalEndpointRegion = undefined, requestFn = undefined }) {
|
|
222691
222922
|
this.secretId = secretId;
|
|
222692
222923
|
this.secretKey = secretKey;
|
|
222693
222924
|
this.token = token;
|
|
@@ -222696,6 +222927,7 @@ class CloudBaseContext {
|
|
|
222696
222927
|
this.envType = envType;
|
|
222697
222928
|
this.useInternalEndpoint = useInternalEndpoint;
|
|
222698
222929
|
this.internalEndpointRegion = internalEndpointRegion;
|
|
222930
|
+
this.requestFn = requestFn;
|
|
222699
222931
|
}
|
|
222700
222932
|
isInternalEndpoint() {
|
|
222701
222933
|
return this.useInternalEndpoint !== undefined ? this.useInternalEndpoint : constant_1.USE_INTERNAL_ENDPOINT;
|
|
@@ -233109,6 +233341,7 @@ const cloud_mode_js_1 = __webpack_require__(89684);
|
|
|
233109
233341
|
const logger_js_1 = __webpack_require__(13039);
|
|
233110
233342
|
const telemetry_js_1 = __webpack_require__(45880);
|
|
233111
233343
|
const tool_result_js_1 = __webpack_require__(9835);
|
|
233344
|
+
const repeat_error_guard_js_1 = __webpack_require__(60827);
|
|
233112
233345
|
/**
|
|
233113
233346
|
* Mirror annotations.category into _meta.category.
|
|
233114
233347
|
*
|
|
@@ -233180,7 +233413,7 @@ ${envIdSection}
|
|
|
233180
233413
|
## 环境信息
|
|
233181
233414
|
- 操作系统: ${os_1.default.type()} ${os_1.default.release()}
|
|
233182
233415
|
- Node.js版本: ${process.version}
|
|
233183
|
-
- MCP 版本:${process.env.npm_package_version || ( true ? "2.32.
|
|
233416
|
+
- MCP 版本:${process.env.npm_package_version || ( true ? "2.32.3" : 0)}
|
|
233184
233417
|
- 系统架构: ${os_1.default.arch()}
|
|
233185
233418
|
- 时间: ${new Date().toISOString()}
|
|
233186
233419
|
- 请求ID: ${requestId}
|
|
@@ -233226,6 +233459,8 @@ function createWrappedHandler(name, handler, server) {
|
|
|
233226
233459
|
// 执行原始处理函数
|
|
233227
233460
|
const result = await handler(args);
|
|
233228
233461
|
success = true;
|
|
233462
|
+
// 任一工具成功说明重复错误循环已被打破,清零连续错误计数
|
|
233463
|
+
(0, repeat_error_guard_js_1.resetRepeatGuard)();
|
|
233229
233464
|
requestId = extractRequestIdFromToolResult(result);
|
|
233230
233465
|
const duration = Date.now() - startTime;
|
|
233231
233466
|
(0, logger_js_1.debug)(`工具执行成功: ${name}`, { duration, requestId: requestId || undefined });
|
|
@@ -233250,7 +233485,9 @@ function createWrappedHandler(name, handler, server) {
|
|
|
233250
233485
|
// Preserve structured tool guidance such as next_step.
|
|
233251
233486
|
// These errors are expected control flow and should be serialized by the outer server wrapper.
|
|
233252
233487
|
if ((0, tool_result_js_1.isToolPayloadError)(error)) {
|
|
233253
|
-
|
|
233488
|
+
// 连续相同结构化错误达到阈值时注入 repeat_guard 升级提示,
|
|
233489
|
+
// 打断无头客户端的原样重试循环(不改写 message,保持遥测聚合稳定)
|
|
233490
|
+
throw new tool_result_js_1.ToolPayloadError((0, repeat_error_guard_js_1.applyRepeatGuardToPayload)(error.payload));
|
|
233254
233491
|
}
|
|
233255
233492
|
// In tests, avoid any extra work that may block (envId lookup, issue link generation, etc.)
|
|
233256
233493
|
if (isTestEnvironment) {
|
|
@@ -233261,7 +233498,7 @@ function createWrappedHandler(name, handler, server) {
|
|
|
233261
233498
|
requestId: (typeof error === 'object' && error && 'requestId' in error) ? error.requestId : '',
|
|
233262
233499
|
ide: server.ide || process.env.INTEGRATION_IDE || ''
|
|
233263
233500
|
});
|
|
233264
|
-
const mcpVersion = true ? "2.32.
|
|
233501
|
+
const mcpVersion = true ? "2.32.3" : 0;
|
|
233265
233502
|
const requestIdSuffix = requestId ? `\n🆔 RequestId: ${requestId}` : '';
|
|
233266
233503
|
const enhancedErrorMessage = `${errorMessage}${requestIdSuffix}\n\n📦 CloudBase MCP v${mcpVersion}\n🔗 遇到问题?请复制以下链接到浏览器打开\n即可自动携带错误详情快速创建 GitHub Issue:\n${issueLink}`;
|
|
233267
233504
|
// 创建新的错误对象,保持原有的错误类型但更新消息
|
|
@@ -252650,7 +252887,7 @@ function registerSetupTools(server) {
|
|
|
252650
252887
|
server.registerTool("downloadTemplate", {
|
|
252651
252888
|
title: "下载项目模板",
|
|
252652
252889
|
description: `自动下载并部署CloudBase项目模板。
|
|
252653
|
-
**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.32.
|
|
252890
|
+
**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.32.3" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
|
|
252654
252891
|
inputSchema: {
|
|
252655
252892
|
template: zod_1.z
|
|
252656
252893
|
.enum(["react", "vue", "miniprogram", "uniapp", "rules"])
|
|
@@ -254688,6 +254925,8 @@ exports.setPendingAuthProgressState = setPendingAuthProgressState;
|
|
|
254688
254925
|
exports.resolveAuthProgressState = resolveAuthProgressState;
|
|
254689
254926
|
exports.rejectAuthProgressState = rejectAuthProgressState;
|
|
254690
254927
|
exports.resetAuthProgressState = resetAuthProgressState;
|
|
254928
|
+
exports.ensureSlottedCredential = ensureSlottedCredential;
|
|
254929
|
+
exports.listUsableCredentialSites = listUsableCredentialSites;
|
|
254691
254930
|
exports.peekLoginState = peekLoginState;
|
|
254692
254931
|
exports.ensureLogin = ensureLogin;
|
|
254693
254932
|
exports.getLoginState = getLoginState;
|
|
@@ -255035,6 +255274,20 @@ function isUsableCredential(value) {
|
|
|
255035
255274
|
typeof value === "object" &&
|
|
255036
255275
|
Object.keys(value).length > 0);
|
|
255037
255276
|
}
|
|
255277
|
+
/**
|
|
255278
|
+
* 返回当前存在可用凭证的 site 槽位列表(凭证续期失败视为不可用)。
|
|
255279
|
+
* 用于歧义 region(如 ap-singapore)时判定用户实际所属站点。
|
|
255280
|
+
*/
|
|
255281
|
+
async function listUsableCredentialSites() {
|
|
255282
|
+
const usable = [];
|
|
255283
|
+
for (const site of ["domestic", "intl"]) {
|
|
255284
|
+
const state = await resolveSiteLoginState(site).catch(() => null);
|
|
255285
|
+
if (state) {
|
|
255286
|
+
usable.push(site);
|
|
255287
|
+
}
|
|
255288
|
+
}
|
|
255289
|
+
return usable;
|
|
255290
|
+
}
|
|
255038
255291
|
async function peekLoginState(options) {
|
|
255039
255292
|
const envVarLoginState = normalizeLoginStateFromEnvVars(options);
|
|
255040
255293
|
if (envVarLoginState) {
|
|
@@ -255057,8 +255310,23 @@ async function peekLoginState(options) {
|
|
|
255057
255310
|
return envVarLoginState;
|
|
255058
255311
|
}
|
|
255059
255312
|
// 按 site 读取分槽凭证(缺省按 TCB_SITE/region 解析站点,默认 domestic)
|
|
255060
|
-
const
|
|
255061
|
-
const
|
|
255313
|
+
const explicitSite = (0, site_map_js_1.normalizeSite)(options?.site) ?? (0, site_map_js_1.normalizeSite)(process.env.TCB_SITE);
|
|
255314
|
+
const site = explicitSite ?? (0, site_map_js_1.resolveSite)(options?.region);
|
|
255315
|
+
let slotLoginState = await resolveSiteLoginState(site);
|
|
255316
|
+
// 歧义 region(如 ap-singapore 同时属于 domestic 与 intl)且未显式指定 site 时,
|
|
255317
|
+
// 解析槽位为空则回退检查另一槽位:仅另一槽位有可用凭证时直接使用,
|
|
255318
|
+
// 避免对单站点用户误报 AUTH_REQUIRED(如国内站 ap-singapore 环境场景)。
|
|
255319
|
+
if (!slotLoginState && !explicitSite && (0, site_map_js_1.getSite)(options?.region) === "ambiguous") {
|
|
255320
|
+
const fallbackSite = site === "domestic" ? "intl" : "domestic";
|
|
255321
|
+
const fallbackLoginState = await resolveSiteLoginState(fallbackSite);
|
|
255322
|
+
if (fallbackLoginState) {
|
|
255323
|
+
(0, logger_js_1.debug)("peekLoginState: ambiguous region, using the only usable site slot", {
|
|
255324
|
+
resolvedSite: site,
|
|
255325
|
+
fallbackSite,
|
|
255326
|
+
});
|
|
255327
|
+
return fallbackLoginState;
|
|
255328
|
+
}
|
|
255329
|
+
}
|
|
255062
255330
|
if (slotLoginState) {
|
|
255063
255331
|
return slotLoginState;
|
|
255064
255332
|
}
|
|
@@ -270513,12 +270781,13 @@ function getDate(timestamp) {
|
|
|
270513
270781
|
}
|
|
270514
270782
|
class CloudService {
|
|
270515
270783
|
/* eslint-disable-next-line */
|
|
270516
|
-
constructor(context, service, version, baseParams) {
|
|
270784
|
+
constructor(context, service, version, baseParams, requestFn) {
|
|
270517
270785
|
this.service = service;
|
|
270518
270786
|
this.version = version;
|
|
270519
270787
|
this.timeout = 60000;
|
|
270520
270788
|
this.baseParams = baseParams || {};
|
|
270521
270789
|
this.cloudBaseContext = context;
|
|
270790
|
+
this.requestFn = requestFn !== null && requestFn !== void 0 ? requestFn : context === null || context === void 0 ? void 0 : context.requestFn;
|
|
270522
270791
|
}
|
|
270523
270792
|
get baseUrl() {
|
|
270524
270793
|
const internalEndpoint = this.cloudBaseContext.isInternalEndpoint();
|
|
@@ -270550,9 +270819,32 @@ class CloudService {
|
|
|
270550
270819
|
}
|
|
270551
270820
|
}
|
|
270552
270821
|
async request(action, data = {}, method = 'POST') {
|
|
270822
|
+
var _a;
|
|
270553
270823
|
this.action = action;
|
|
270554
|
-
this.data = deepRemoveVoid(Object.assign(Object.assign({}, data), this.baseParams));
|
|
270555
270824
|
this.method = method;
|
|
270825
|
+
this.data = deepRemoveVoid(Object.assign(Object.assign({}, data), this.baseParams));
|
|
270826
|
+
// 如果注入了 requestFn,直接委托,跳过 TC3 签名逻辑
|
|
270827
|
+
if (this.requestFn) {
|
|
270828
|
+
try {
|
|
270829
|
+
const result = await this.requestFn({
|
|
270830
|
+
service: this.service,
|
|
270831
|
+
action,
|
|
270832
|
+
version: this.version,
|
|
270833
|
+
region: (_a = this.cloudBaseContext.region) !== null && _a !== void 0 ? _a : '',
|
|
270834
|
+
payload: this.data,
|
|
270835
|
+
});
|
|
270836
|
+
return result;
|
|
270837
|
+
}
|
|
270838
|
+
catch (e) {
|
|
270839
|
+
if (e.name === 'CloudBaseError') {
|
|
270840
|
+
throw e;
|
|
270841
|
+
}
|
|
270842
|
+
throw new error_1.CloudBaseError(e.message, {
|
|
270843
|
+
action,
|
|
270844
|
+
code: e.code
|
|
270845
|
+
});
|
|
270846
|
+
}
|
|
270847
|
+
}
|
|
270556
270848
|
this.url = this.baseUrl;
|
|
270557
270849
|
let { secretId, secretKey, token } = this.cloudBaseContext;
|
|
270558
270850
|
// 当在云函数环境下执行时,可init时不传入密钥,取环境变量中密钥使用
|
|
@@ -315767,9 +316059,9 @@ class CloudBase {
|
|
|
315767
316059
|
}
|
|
315768
316060
|
constructor(config = {}) {
|
|
315769
316061
|
this.cloudBaseConfig = {};
|
|
315770
|
-
let { secretId, secretKey, token, envId, proxy, region, envType, useInternalEndpoint, internalEndpointRegion } = config;
|
|
315771
|
-
// config 中传入的 secretId secretkey
|
|
315772
|
-
if ((secretId && !secretKey) || (!secretId && secretKey)) {
|
|
316062
|
+
let { secretId, secretKey, token, envId, proxy, region, envType, useInternalEndpoint, internalEndpointRegion, requestFn } = config;
|
|
316063
|
+
// config 中传入的 secretId secretkey 必须同时存在(有 requestFn 时可以不传)
|
|
316064
|
+
if (!requestFn && ((secretId && !secretKey) || (!secretId && secretKey))) {
|
|
315773
316065
|
throw new Error('secretId and secretKey must be a pair');
|
|
315774
316066
|
}
|
|
315775
316067
|
this.cloudBaseConfig = {
|
|
@@ -315782,6 +316074,7 @@ class CloudBase {
|
|
|
315782
316074
|
region,
|
|
315783
316075
|
useInternalEndpoint,
|
|
315784
316076
|
internalEndpointRegion,
|
|
316077
|
+
requestFn,
|
|
315785
316078
|
};
|
|
315786
316079
|
// 初始化 context
|
|
315787
316080
|
this.context = new context_1.CloudBaseContext(this.cloudBaseConfig);
|