@cloudbase/cloudbase-mcp 2.36.0 → 2.36.1
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 +1111 -129
- package/dist/index.d.ts +12 -1
- package/dist/index.js +1111 -129
- package/package.json +2 -1
- package/server.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -199828,6 +199828,7 @@ exports.resolveAuthProgressState = resolveAuthProgressState;
|
|
|
199828
199828
|
exports.rejectAuthProgressState = rejectAuthProgressState;
|
|
199829
199829
|
exports.resetAuthProgressState = resetAuthProgressState;
|
|
199830
199830
|
exports.getCredentialSource = getCredentialSource;
|
|
199831
|
+
exports.isEnvCredentialRemovableByLogout = isEnvCredentialRemovableByLogout;
|
|
199831
199832
|
exports.peekLoginState = peekLoginState;
|
|
199832
199833
|
exports.ensureLogin = ensureLogin;
|
|
199833
199834
|
exports.getLoginState = getLoginState;
|
|
@@ -200261,6 +200262,21 @@ function readProjectCredentialFile(projectRoot) {
|
|
|
200261
200262
|
return null;
|
|
200262
200263
|
}
|
|
200263
200264
|
}
|
|
200265
|
+
/**
|
|
200266
|
+
* 删掉项目级凭据文件。只删这一个文件,目录留着——删目录会顺带清掉同在里面的
|
|
200267
|
+
* `project.json` 等项目配置。
|
|
200268
|
+
*
|
|
200269
|
+
* 不走 toolbox 的 `logout({cwd})`:那个接口会**无条件先删全局凭据**,而「退出本项目」
|
|
200270
|
+
* 不该把用户的账号级登录一起注销掉。
|
|
200271
|
+
*/
|
|
200272
|
+
function deleteProjectCredentialFile(projectRoot) {
|
|
200273
|
+
try {
|
|
200274
|
+
(0, node_fs_1.unlinkSync)((0, node_path_1.join)((0, toolbox_1.getProjectDir)(projectRoot), "auth.json"));
|
|
200275
|
+
}
|
|
200276
|
+
catch {
|
|
200277
|
+
// 文件本来就不在:登出是幂等的,不报错
|
|
200278
|
+
}
|
|
200279
|
+
}
|
|
200264
200280
|
/**
|
|
200265
200281
|
* 项目级凭据优先于账号级全局登录态。
|
|
200266
200282
|
*
|
|
@@ -200318,6 +200334,32 @@ function clearAdoptedProjectEnv() {
|
|
|
200318
200334
|
function isAdoptedProjectCredential(apiKey, envId) {
|
|
200319
200335
|
return adoptedProjectApiKey !== null && apiKey === adoptedProjectApiKey && envId === adoptedProjectEnvId;
|
|
200320
200336
|
}
|
|
200337
|
+
/**
|
|
200338
|
+
* env 里的这一份凭据能不能被 `logout()` 清掉。
|
|
200339
|
+
*
|
|
200340
|
+
* 能清掉的只有两种情况:是我们从项目级凭据文件回填的,或者它与当前项目级凭据文件里
|
|
200341
|
+
* 那一份相同(`auth(login_by_api_key)` 写进程 env 的同时也把同一个 key 落到项目级)。
|
|
200342
|
+
* 这两种都能沿 `logout()` 清掉:删项目级文件、再清 env。
|
|
200343
|
+
*
|
|
200344
|
+
* 其余情况是用户自己在 shell 或宿主配置里设的变量,进程删不掉,只能提示他去源头改。
|
|
200345
|
+
*/
|
|
200346
|
+
function isEnvCredentialRemovableByLogout() {
|
|
200347
|
+
const apiKey = getCloudBaseApiKeyFromEnv();
|
|
200348
|
+
const envId = process.env.CLOUDBASE_ENV_ID;
|
|
200349
|
+
if (!apiKey || !envId) {
|
|
200350
|
+
return false;
|
|
200351
|
+
}
|
|
200352
|
+
if (isAdoptedProjectCredential(apiKey, envId)) {
|
|
200353
|
+
return true;
|
|
200354
|
+
}
|
|
200355
|
+
try {
|
|
200356
|
+
const stored = readProjectCredentialFile((0, project_config_js_1.requireProjectRoot)());
|
|
200357
|
+
return stored?.apiKey === apiKey && stored?.envId === envId;
|
|
200358
|
+
}
|
|
200359
|
+
catch {
|
|
200360
|
+
return false;
|
|
200361
|
+
}
|
|
200362
|
+
}
|
|
200321
200363
|
/**
|
|
200322
200364
|
* 全局凭据文件 `~/.config/.cloudbase/auth.json` 与 CloudBase CLI 共用一份:用户会在终端里
|
|
200323
200365
|
* `tcb login`,宿主连接器的登录按钮执行的也是 `tcb login --flow web --yes`,两者都在
|
|
@@ -200359,6 +200401,8 @@ async function peekLoginState(options) {
|
|
|
200359
200401
|
dropStaleCredentialStoreCache();
|
|
200360
200402
|
credentialSource = null;
|
|
200361
200403
|
const envVarLoginState = normalizeLoginStateFromEnvVars(options);
|
|
200404
|
+
// 回填的那份 key 换不出临时密钥时置位:项目级文件里是同一份,不必再试一次
|
|
200405
|
+
let projectCredentialSkipped = false;
|
|
200362
200406
|
if (envVarLoginState) {
|
|
200363
200407
|
// API Key 模式:需要先用 API Key 换取临时密钥
|
|
200364
200408
|
if ('_type' in envVarLoginState && envVarLoginState._type === 'api_key') {
|
|
@@ -200380,16 +200424,28 @@ async function peekLoginState(options) {
|
|
|
200380
200424
|
}
|
|
200381
200425
|
catch (e) {
|
|
200382
200426
|
(0, logger_js_1.debug)("peekLoginState: API Key login failed", { error: e instanceof Error ? e.message : String(e) });
|
|
200383
|
-
|
|
200427
|
+
// 我们回填的那份失效(密钥被撤、环境被删):先清掉残留,别让它一直占着 env
|
|
200428
|
+
// 把状态查询、登出、重新登录全堵死;项目文件本身不动,用户重新登录会覆盖它。
|
|
200429
|
+
// 清完继续往下走,让账号级登录态接上。
|
|
200430
|
+
if (isAdoptedProjectCredential(envVarLoginState.apiKey, envVarLoginState.envId)) {
|
|
200431
|
+
clearAdoptedProjectEnv();
|
|
200432
|
+
projectCredentialSkipped = true;
|
|
200433
|
+
}
|
|
200434
|
+
else {
|
|
200435
|
+
// 用户自己在 shell / 宿主配置里设的变量,登不登得上由他那边决定
|
|
200436
|
+
return null;
|
|
200437
|
+
}
|
|
200384
200438
|
}
|
|
200385
200439
|
}
|
|
200386
|
-
|
|
200387
|
-
|
|
200388
|
-
|
|
200389
|
-
|
|
200440
|
+
if (!projectCredentialSkipped) {
|
|
200441
|
+
// 腾讯云密钥模式:直接返回
|
|
200442
|
+
(0, logger_js_1.debug)("loginByApiSecret");
|
|
200443
|
+
credentialSource = "env";
|
|
200444
|
+
return envVarLoginState;
|
|
200445
|
+
}
|
|
200390
200446
|
}
|
|
200391
200447
|
// 项目级凭据优先于账号级登录态(与 readProjectEnvId 同一原则)
|
|
200392
|
-
const projectLoginState = await resolveProjectLoginState();
|
|
200448
|
+
const projectLoginState = projectCredentialSkipped ? null : await resolveProjectLoginState();
|
|
200393
200449
|
if (projectLoginState) {
|
|
200394
200450
|
credentialSource = "project";
|
|
200395
200451
|
return projectLoginState;
|
|
@@ -200488,21 +200544,44 @@ async function ensureLogin(options) {
|
|
|
200488
200544
|
async function getLoginState(options) {
|
|
200489
200545
|
return ensureLogin(options);
|
|
200490
200546
|
}
|
|
200547
|
+
/**
|
|
200548
|
+
* 退出登录:只清「当前生效的那一份」。
|
|
200549
|
+
*
|
|
200550
|
+
* 项目级凭据优先于账号级登录态,所以项目里有 API Key 时,登出只删项目文件、清掉
|
|
200551
|
+
* 回填的环境变量,账号登录原样保留(删完它自动接上)。再调一次才轮到全局。
|
|
200552
|
+
*
|
|
200553
|
+
* 不把 cwd 交给 toolbox 的 `logout()`:那个接口会**无条件先删全局凭据**,
|
|
200554
|
+
* 「退出本项目」不该把用户的账号级登录一起注销掉。
|
|
200555
|
+
*/
|
|
200491
200556
|
async function logout(_options) {
|
|
200492
200557
|
// 先同步缓存再删:否则 toolbox 会把本进程启动时的陈旧快照写回盘,
|
|
200493
200558
|
// 把外部(CLI / 宿主登录按钮)刚写入的凭据一起抹掉。
|
|
200494
200559
|
dropStaleCredentialStoreCache();
|
|
200495
|
-
|
|
200560
|
+
const removed = [];
|
|
200561
|
+
let projectRoot;
|
|
200496
200562
|
try {
|
|
200497
|
-
|
|
200563
|
+
projectRoot = (0, project_config_js_1.requireProjectRoot)();
|
|
200498
200564
|
}
|
|
200499
200565
|
catch {
|
|
200500
|
-
|
|
200566
|
+
// 宿主配置目录等非法项目根:没有项目级凭据
|
|
200567
|
+
projectRoot = undefined;
|
|
200568
|
+
}
|
|
200569
|
+
const envApiKey = getCloudBaseApiKeyFromEnv();
|
|
200570
|
+
const hasProjectCredential = !!(projectRoot && readProjectCredentialFile(projectRoot));
|
|
200571
|
+
// env 里那份是用户自己设的(进程删不掉)时,既不算项目级生效,也不该顺手注销账号登录
|
|
200572
|
+
const projectInEffect = hasProjectCredential && (!envApiKey || isEnvCredentialRemovableByLogout());
|
|
200573
|
+
if (projectInEffect && projectRoot) {
|
|
200574
|
+
deleteProjectCredentialFile(projectRoot);
|
|
200575
|
+
clearAdoptedProjectEnv();
|
|
200576
|
+
removed.push("project");
|
|
200577
|
+
}
|
|
200578
|
+
else if (!envApiKey) {
|
|
200579
|
+
await auth.logout();
|
|
200580
|
+
removed.push("global");
|
|
200501
200581
|
}
|
|
200502
|
-
await auth.logout(cwd ? { cwd } : undefined);
|
|
200503
|
-
clearAdoptedProjectEnv();
|
|
200504
200582
|
credentialSource = null;
|
|
200505
200583
|
resetAuthProgressState();
|
|
200584
|
+
return { removed };
|
|
200506
200585
|
}
|
|
200507
200586
|
|
|
200508
200587
|
|
|
@@ -202665,7 +202744,7 @@ exports.cloudrun = (0, types_js_1.defineModule)({
|
|
|
202665
202744
|
"error.envNotInitialized": "当前环境({envId})尚未初始化云托管(CloudRun Env)。不能直接创建服务(CreateCloudRunServer 在无大租户记录时会默认创建到小租户,产生错误的小租户服务与版本)。\n请先开通云托管环境,再重试部署:\n- MCP:manageCloudRun(action=\"initEnv\", envId=\"{envId}\")(异步开通,幂等;开通完成后可用 queryCloudRun(action=\"envStatus\", envId=\"{envId}\") 查询 Status=normal)\n- 或控制台:环境 → 云托管 → 开通(https://tcb.cloud.tencent.com/dev?envId={envId}#/platform-run)\n初始化完成后重新调用 manageCloudRun(action=\"deploy\")。",
|
|
202666
202745
|
"error.actionFailed": "[{context}] {baseMessage}",
|
|
202667
202746
|
"error.buildManage": "[manageCloudRun/{action}] {baseMessage}\n建议:{suggestions}",
|
|
202668
|
-
"error.deployTaskRunning": "服务 `{serverName}`
|
|
202747
|
+
"error.deployTaskRunning": "服务 `{serverName}` 当前已有部署任务在执行。**不要再发起 deploy**:先用 queryCloudRun(action=\"getManageTask\", serverName=\"{serverName}\") 读取该任务的真实状态——已结束就重新部署,长时间停在非终态则带上该输出联系 CloudBase 平台排查。",
|
|
202669
202748
|
"error.deployTaskRunningForce": "注意:`force=true` 仅跳过本工具的确认提示,不会取消或覆盖平台上的发布任务。请先用 queryCloudRun(action=\"getManageTask\", serverName=\"{serverName}\") 确认任务真实状态:若任务已结束却仍报此错,或任务长时间停在非终态,请携带该输出联系 CloudBase 平台排查该环境的发布任务。",
|
|
202670
202749
|
"error.vpcRequired": "CreateCloudRunServer 需要有效 VPC:请传 serverConfig.VpcConf(VpcId+SubnetId),或在 initEnv 时传入 vpcId/subnetIds(环境开通后 deploy 会自动从 EnvBaseInfo 回填)。若平台拒绝系统创建网络,必须指定上海地域 VPC。",
|
|
202671
202750
|
"error.genericRetry": "请检查服务状态、部署参数和目标目录后重试。",
|
|
@@ -202855,7 +202934,7 @@ exports.cloudrun = (0, types_js_1.defineModule)({
|
|
|
202855
202934
|
"error.envNotInitialized": "The current environment ({envId}) has not initialized CloudRun (CloudRun Env). You cannot create services directly (without a large-tenant record, CreateCloudRunServer defaults to the small tenant, producing wrong small-tenant services and versions).\nProvision the CloudRun env first, then retry the deploy:\n- MCP: manageCloudRun(action=\"initEnv\", envId=\"{envId}\") (async, idempotent; once done, query Status=normal via queryCloudRun(action=\"envStatus\", envId=\"{envId}\"))\n- Or console: Environment → CloudRun → Provision (https://tcb.cloud.tencent.com/dev?envId={envId}#/platform-run)\nAfter initialization, call manageCloudRun(action=\"deploy\") again.",
|
|
202856
202935
|
"error.actionFailed": "[{context}] {baseMessage}",
|
|
202857
202936
|
"error.buildManage": "[manageCloudRun/{action}] {baseMessage}\nSuggestions: {suggestions}",
|
|
202858
|
-
"error.deployTaskRunning": "Service `{serverName}` already has a deploy task running.
|
|
202937
|
+
"error.deployTaskRunning": "Service `{serverName}` already has a deploy task running. Do NOT call deploy again: first read the real task state with queryCloudRun(action=\"getManageTask\", serverName=\"{serverName}\") - redeploy once it has finished, or contact the CloudBase platform with that output if it stays in a non-terminal state for a long time.",
|
|
202859
202938
|
"error.deployTaskRunningForce": "Note: `force=true` only skips this tool's confirmation prompt; it does not cancel or override the platform-side deploy task. First confirm the real task state with queryCloudRun(action=\"getManageTask\", serverName=\"{serverName}\"): if the task has already finished but this error persists, or it stays in a non-terminal state for a long time, contact the CloudBase platform with that output to investigate this environment's deploy task.",
|
|
202860
202939
|
"error.vpcRequired": "CreateCloudRunServer requires a valid VPC: pass serverConfig.VpcConf (VpcId+SubnetId), or pass vpcId/subnetIds during initEnv (after provisioning, deploy auto-fills from EnvBaseInfo). If the platform rejects system-created networks, you must specify a Shanghai-region VPC.",
|
|
202861
202940
|
"error.genericRetry": "Check the service status, deploy parameters, and target directory, then retry.",
|
|
@@ -204459,9 +204538,12 @@ exports.env = (0, types_js_1.defineModule)({
|
|
|
204459
204538
|
"auth.envReadyWithHint": "环境设置成功,当前环境: {envId}{regionHint}",
|
|
204460
204539
|
"auth.regionHint": ",地域: {region}",
|
|
204461
204540
|
"auth.regionHintUnverified": "。未在当前探测地域中确认该 envId,已按唯一 ID 直绑;若后续接口仍指向错误地域,请设置 TCB_REGION 或 queryEnv(action=\"list\", region=...)",
|
|
204462
|
-
"auth.logoutNotAllowedApiKey": "
|
|
204541
|
+
"auth.logoutNotAllowedApiKey": "当前是 API Key 认证模式,凭据来自环境变量 {varName}。这个变量不是本进程设的、也不由本进程清除,所以没有执行登出。要切换认证方式:在 shell 里 unset {varName},或从启动本 MCP 的客户端配置里移除它,然后重启。",
|
|
204463
204542
|
"auth.logoutConfirmRequired": "action=logout 时必须传 confirm=\"yes\"",
|
|
204464
204543
|
"auth.loggedOut": "✅ 已退出登录",
|
|
204544
|
+
"auth.loggedOutProject": "✅ 已移除本项目的 API Key 登录。这台机器上若还有账号登录,它仍然有效;要一起退出请再执行一次 logout。",
|
|
204545
|
+
"auth.apiKeySwitchHintRemovable": "如需改用账号登录,先执行 logout 退出本项目 API Key,再 start_auth 授权。",
|
|
204546
|
+
"auth.apiKeySwitchHintExternal": "这个 key 来自外部环境变量,MCP 无法退出它;如需改用账号登录,先在 shell 或客户端配置里移除 {varName} 并重启。",
|
|
204465
204547
|
"auth.tempCredNotLoggedIn": "当前未登录,请先完成管理端认证后再获取临时密钥。",
|
|
204466
204548
|
"auth.tempCredConfirmRequired": "action=get_temp_credentials 时必须显式传 confirm=\"yes\",以确认你要导出当前管理端临时密钥。",
|
|
204467
204549
|
"auth.tempCredUnsupportedType": "当前登录态不是可导出的临时密钥。仅支持通过 Web / device 登录得到的临时密钥,永久密钥登录不允许导出。",
|
|
@@ -204722,9 +204804,12 @@ exports.env = (0, types_js_1.defineModule)({
|
|
|
204722
204804
|
"auth.envReadyWithHint": "Environment bound successfully. Current env: {envId}{regionHint}",
|
|
204723
204805
|
"auth.regionHint": ", region: {region}",
|
|
204724
204806
|
"auth.regionHintUnverified": ". This envId was not confirmed in the probed regions, so it was bound directly by its unique ID; if later APIs still target the wrong region, set TCB_REGION or use queryEnv(action=\"list\", region=...)",
|
|
204725
|
-
"auth.logoutNotAllowedApiKey": "API Key authentication mode is in use and
|
|
204807
|
+
"auth.logoutNotAllowedApiKey": "API Key authentication mode is in use, and the credential comes from the {varName} environment variable. This process neither set nor can remove that variable, so logout was skipped. To switch authentication methods, unset {varName} in your shell or remove it from the MCP client configuration, then restart.",
|
|
204726
204808
|
"auth.logoutConfirmRequired": "confirm=\"yes\" must be passed when action=logout",
|
|
204727
204809
|
"auth.loggedOut": "✅ Logged out",
|
|
204810
|
+
"auth.loggedOutProject": "✅ Removed this project's API Key login. An account login on this machine is still active; call logout again to sign out of it.",
|
|
204811
|
+
"auth.apiKeySwitchHintRemovable": "To switch to account login, run logout to remove this project's API Key, then start_auth.",
|
|
204812
|
+
"auth.apiKeySwitchHintExternal": "This key comes from an external environment variable and cannot be removed by MCP. To switch to account login, unset {varName} in your shell or client configuration and restart.",
|
|
204728
204813
|
"auth.tempCredNotLoggedIn": "Not logged in. Complete management-plane authentication before fetching temporary credentials.",
|
|
204729
204814
|
"auth.tempCredConfirmRequired": "confirm=\"yes\" must be passed explicitly when action=get_temp_credentials, to confirm that you want to export the current management-plane temporary credentials.",
|
|
204730
204815
|
"auth.tempCredUnsupportedType": "The current login state is not an exportable temporary credential. Only temporary credentials obtained via Web / device login are supported; permanent key logins cannot be exported.",
|
|
@@ -205103,9 +205188,12 @@ exports.functions = (0, types_js_1.defineModule)({
|
|
|
205103
205188
|
"\n- `limit`: 分页数量,默认值由后端决定" +
|
|
205104
205189
|
"\n- `offset`: 分页偏移,从 0 开始" +
|
|
205105
205190
|
"\n- 示例:`queryFunctions(action=\"listFunctions\", offset=10, limit=10)`" +
|
|
205106
|
-
"\n\n**查询 CloudBase
|
|
205191
|
+
"\n\n**查询 CloudBase 云函数日志**:`action=\"listFunctionLogs\"`,需要提供 `functionName`。日志从 CLS 检索(底层 GetFunctionLogs 接口已下线)。" +
|
|
205107
205192
|
"\n- 示例:`queryFunctions(action=\"listFunctionLogs\", functionName=\"my-function\")`" +
|
|
205108
|
-
"\n-
|
|
205193
|
+
"\n- 不传 startTime/endTime 时默认查最近 1 天;跨度不能超过 1 天,单次最多返回 100 条" +
|
|
205194
|
+
"\n- 返回 `hasMore=true` 表示还有更早的日志:把返回的 `context` 原样传回取下一页(`offset` 只在前 100 条内生效)" +
|
|
205195
|
+
"\n- `logs[]` 已解析成 requestId / log / statusCode / retCode / durationMs / memoryMb / timestamp" +
|
|
205196
|
+
"\n- 想看某一次调用的完整过程(START、业务日志、REPORT):`queryFunctions(action=\"getFunctionLogDetail\", requestId=\"xxx\")`" +
|
|
205109
205197
|
"\n\n**定时任务 / cron / 定时跑**:使用 `listFunctionTriggers` 查询函数的 timer 触发器配置。" +
|
|
205110
205198
|
"\n\n**版本与流量路由**:`listVersionByFunction` 列出已发布版本(对齐 tcb fn list-function-versions);`getFunctionAlias` 查看别名/灰度配置(对齐 tcb fn get-route,aliasName 默认 `$DEFAULT`)。" +
|
|
205111
205199
|
"\n\n**层(Layer)说明**:" +
|
|
@@ -205175,8 +205263,8 @@ exports.functions = (0, types_js_1.defineModule)({
|
|
|
205175
205263
|
endTimeInvalid: "endTime 格式错误: \"{value}\"。必须使用 YYYY-MM-DD HH:mm:ss 格式(如 2024-01-01 23:59:59)",
|
|
205176
205264
|
logRangeInvalidDatetime: "startTime 和 endTime 必须是有效的日期时间字符串",
|
|
205177
205265
|
logRangeTooLong: "startTime 和 endTime 间隔不能超过一天",
|
|
205178
|
-
logsInvalidParamTips: "常见原因:\n1. startTime/endTime 格式错误,必须为 YYYY-MM-DD HH:mm:ss(如 2024-01-01 00:00:00),不支持 ISO 8601 或时间戳\n2. startTime 和 endTime 间隔超过一天\n3. functionName
|
|
205179
|
-
logDetailInvalidParamTips: "常见原因:\n1. startTime/endTime 格式错误,必须为 YYYY-MM-DD HH:mm:ss(如 2024-01-01 00:00:00),不支持 ISO 8601 或时间戳\n2. startTime 和 endTime 间隔超过一天\n
|
|
205266
|
+
logsInvalidParamTips: "常见原因:\n1. startTime/endTime 格式错误,必须为 YYYY-MM-DD HH:mm:ss(如 2024-01-01 00:00:00),不支持 ISO 8601 或时间戳\n2. startTime 和 endTime 间隔超过一天\n3. functionName 与日志里的 function_name 不一致(大小写敏感),或 qualifier 不匹配\n建议:不传 startTime/endTime 时默认查询最近一天的日志。",
|
|
205267
|
+
logDetailInvalidParamTips: "常见原因:\n1. startTime/endTime 格式错误,必须为 YYYY-MM-DD HH:mm:ss(如 2024-01-01 00:00:00),不支持 ISO 8601 或时间戳\n2. startTime 和 endTime 间隔超过一天\n3. requestId 不在该时间窗口内(日志按请求开始时间归档)\n建议:先用 listFunctionLogs 定位到 requestId 再查详情。",
|
|
205180
205268
|
paramRequired: "{action} 操作时,{param} 参数是必需的",
|
|
205181
205269
|
"deployStatus.cloudMode": "{action} 在 cloud mode 下不可用:异步部署任务只由 buildStrategy=cloud/local 的真实部署创建,而这两种策略的真实执行在 cloud mode 下都不支持(需要读取本地构建上下文或本地 Docker),因此不会存在任何 taskId。buildStrategy=image 走同步部署,直接在 manageFunctions 的返回里拿结果,也不需要查询部署状态。如需异步镜像构建部署,请改用本地 MCP 模式。",
|
|
205182
205270
|
deployTaskNotFound: "未找到部署任务 {taskId};部署任务不存在,可能已过期、不属于当前环境 {envId},或 MCP Server 已重启(任务仅保存在 MCP 进程内存中)。",
|
|
@@ -205191,7 +205279,11 @@ exports.functions = (0, types_js_1.defineModule)({
|
|
|
205191
205279
|
"reason.viewLogs": "查看该函数的执行日志",
|
|
205192
205280
|
"reason.updateConfig": "更新该函数配置",
|
|
205193
205281
|
"reason.checkGateway": "查看该函数是否已暴露网关访问入口",
|
|
205194
|
-
"reason.logDetail": "按 requestId
|
|
205282
|
+
"reason.logDetail": "按 requestId 查看该次调用的完整日志",
|
|
205283
|
+
"reason.nextLogPage": "带上 context 取下一页(更早的)日志",
|
|
205284
|
+
"reason.widenLogRange": "放宽时间范围后重新查询该函数的日志",
|
|
205285
|
+
"reason.createLogService": "开通环境日志服务后再查询函数日志",
|
|
205286
|
+
"reason.searchClsFallback": "改用 queryLogs 直接按同一条 CLS 语句检索",
|
|
205195
205287
|
"reason.attachLayer": "为该函数追加绑定层",
|
|
205196
205288
|
"reason.reorderLayers": "整体调整层顺序或绑定列表",
|
|
205197
205289
|
"reason.layerVersions": "查看某个层的版本列表",
|
|
@@ -205236,6 +205328,10 @@ exports.functions = (0, types_js_1.defineModule)({
|
|
|
205236
205328
|
gotFunctionDetail: "已获取函数 {fnName} 的详情",
|
|
205237
205329
|
gotFunctionLogs: "已获取函数 {fnName} 的日志列表",
|
|
205238
205330
|
gotLogDetail: "已获取 requestId={requestId} 的日志详情",
|
|
205331
|
+
"logs.emptyByFunction": "在 {start} ~ {end} 之间没有查到函数 {fnName} 的日志。常见原因:该时间段内函数没有被调用、日志已过保留期、或 functionName / qualifier 不匹配。可以放宽时间范围后重试。",
|
|
205332
|
+
"logs.emptyByRequest": "在 {start} ~ {end} 之间没有查到 requestId={requestId} 的日志。请确认时间范围覆盖了这次调用(日志按请求开始时间归档),或先用 listFunctionLogs 定位到的 requestId。",
|
|
205333
|
+
"logs.serviceNotEnabled": "当前环境还没有开通日志服务,云函数日志查不到。请先调用 manageLogs(action=\"createLogService\", confirm=true) 开通,再重新查询。",
|
|
205334
|
+
"logs.queryFailed": "查询云函数日志失败:{message}",
|
|
205239
205335
|
gotFunctionLayers: "已获取函数 {fnName} 当前绑定的层",
|
|
205240
205336
|
gotLayers: "已获取 {count} 条层记录",
|
|
205241
205337
|
gotLayerVersions: "已获取层 {layerName} 的版本列表",
|
|
@@ -205316,16 +205412,17 @@ exports.functions = (0, types_js_1.defineModule)({
|
|
|
205316
205412
|
"schema.create.layers": "Layer 配置",
|
|
205317
205413
|
"schema.manageLayer.name": "层名称",
|
|
205318
205414
|
"schema.manageLayer.version": "层版本号",
|
|
205319
|
-
"schema.query.action": "只读操作类型:\n- `listFunctions`: 列出所有 CloudBase 云函数\n- `getFunctionDetail`: 获取 CloudBase 云函数详情(需要 functionName)\n- `listFunctionLogs`:
|
|
205415
|
+
"schema.query.action": "只读操作类型:\n- `listFunctions`: 列出所有 CloudBase 云函数\n- `getFunctionDetail`: 获取 CloudBase 云函数详情(需要 functionName)\n- `listFunctionLogs`: 查询云函数执行日志(需要 functionName;走 CLS 检索,默认最近 1 天,单次最多 100 条,翻页传 context)\n- `getFunctionLogDetail`: 获取某次调用的完整日志序列(需要 requestId,取自 listFunctionLogs 的 logs[].requestId)\n- `listFunctionLayers`: 列出函数绑定的层\n- `listLayers`: 列出所有层(账号级视图,含其他环境创建的层)\n- `listLayerVersions`: 列出层的版本(注意:是 Versions 不是 Version;账号级视图)\n- `getLayerVersionDetail`: 获取层版本详情(账号级视图)\n- `listFunctionTriggers`: 列出函数触发器(用于查看定时任务 / cron / timer 配置)\n- `getFunctionDownloadUrl`: 获取函数代码下载地址\n- `getFunctionDeployStatus`: 按 taskId 查询异步部署状态、阶段进度和最终结果。返回 data.build(构建子状态)、data.deploy(部署子状态)、data.progress(阶段事件);status=running 时 data.result 与 data.error 一律为 null,不得报告部署完成。调用方必须持续轮询直到 status=succeeded/failed;status=expired 表示任务超过最长保留时间(2 小时)被终结,云端可能仍在部署,需用 getFunctionDetail 确认。任务只保存在 MCP 进程内存中,过期或 MCP Server 重启后返回 errorCode=DEPLOY_TASK_NOT_FOUND;任务按环境隔离,只能查到当前环境自己发起的部署。cloud mode 下本 action 不可用:异步任务只由 buildStrategy=cloud/local 的真实部署创建,而这两种策略在 cloud mode 下都不支持真实执行,image 策略则走同步部署不产生 taskId。\n- `listVersionByFunction`: 列出函数已发布版本(对齐 tcb fn list-function-versions / SDK listVersionByFunction;需要 functionName)\n- `getFunctionAlias`: 查询函数别名与流量路由(对齐 tcb fn get-route / SDK getFunctionAlias;需要 functionName;aliasName 默认 $DEFAULT)\n- `getFunctionUploadUrl`: 获取函数代码包的 COS 预签名上传地址(ZIP 两段式部署阶段 A):PUT 代码 zip 到 uploadUrl(uploadHeaders 非空时须随请求携带对应请求头),再调用 manageFunctions 的 createFunction/updateFunctionCode 并传 code 三元组(阶段 B)。functionName 可选,仅用于生成上传对象 key。返回的 uploadUrl 含凭据签名,不得写入日志或持久化;阶段 B 会校验三元组的桶与地域必须是本环境自有存储桶,因此该地址只能用于取到它的那个环境;地址默认 300 秒内有效",
|
|
205320
205416
|
"schema.query.functionName": "CloudBase 云函数名称。`getFunctionDetail`、`listFunctionLogs`、`listFunctionLayers`、`listFunctionTriggers`、`getFunctionDownloadUrl`、`listVersionByFunction`、`getFunctionAlias` 时必填;`getFunctionUploadUrl` 可选(仅用于生成上传对象 key)",
|
|
205321
|
-
"schema.query.limit": "分页数量(limit)。列表类 action
|
|
205322
|
-
"schema.query.offset": "分页偏移(offset)。列表类 action 可选,默认 0",
|
|
205417
|
+
"schema.query.limit": "分页数量(limit)。列表类 action 可选,默认值由后端决定;日志类 action 单次最多 100 条,默认 20",
|
|
205418
|
+
"schema.query.offset": "分页偏移(offset)。列表类 action 可选,默认 0。日志类 action 只在前 100 条内生效,更早的日志请用返回的 context 翻页",
|
|
205323
205419
|
"schema.query.codeSecret": "代码保护密钥,用于解密函数代码",
|
|
205324
205420
|
"schema.query.revealEnvValues": "getFunctionDetail / listFunctionTriggers / listFunctionLayers 时是否返回环境变量明文值。默认 false:Value 脱敏为 ***,仅保留 Key 与 ValueLength,足以确认配置了哪些变量及变更是否生效;true 时返回明文,敏感变量会进入模型上下文,谨慎使用。如需查看明文,建议优先使用控制台或 CLI",
|
|
205325
|
-
"schema.query.startTime": "日志查询开始时间,格式必须为 YYYY-MM-DD HH:mm:ss(如 2024-01-01 00:00:00
|
|
205326
|
-
"schema.query.endTime": "日志查询结束时间,格式必须为 YYYY-MM-DD HH:mm:ss(如 2024-01-01 23:59:59
|
|
205327
|
-
"schema.query.requestId": "日志请求 ID。`getFunctionLogDetail`
|
|
205328
|
-
"schema.query.qualifier": "函数版本别名,如 $LATEST、$DEFAULT
|
|
205421
|
+
"schema.query.startTime": "日志查询开始时间,格式必须为 YYYY-MM-DD HH:mm:ss(如 2024-01-01 00:00:00,按北京时间理解)。与 endTime 间隔不能超过一天。不传时默认查询最近一天",
|
|
205422
|
+
"schema.query.endTime": "日志查询结束时间,格式必须为 YYYY-MM-DD HH:mm:ss(如 2024-01-01 23:59:59,按北京时间理解)。与 startTime 间隔不能超过一天。不传时默认为当前时间",
|
|
205423
|
+
"schema.query.requestId": "日志请求 ID。`getFunctionLogDetail` 操作必填;取自 `listFunctionLogs` 返回的 logs[].requestId,也可传具体业务日志里出现的 RequestId",
|
|
205424
|
+
"schema.query.qualifier": "函数版本别名,如 $LATEST、$DEFAULT。日志查询时可选,作为 CLS 检索条件",
|
|
205425
|
+
"schema.query.context": "日志翻页游标。把上一次 `listFunctionLogs` 返回的 `context` 原样传回即可取下一页;不要自己构造,null 表示没有更多",
|
|
205329
205426
|
"schema.query.runtime": "层查询的运行时筛选,如 Nodejs18.15",
|
|
205330
205427
|
"schema.query.searchKey": "层名称搜索关键字",
|
|
205331
205428
|
"schema.query.layerName": "层名称。`listLayerVersions`、`getLayerVersionDetail` 操作必填。层为账号级共享命名空间;推荐固定格式 `{layerName}_{当前envId}`(如 common_cloud1-d9ghadgak3edf6b36)",
|
|
@@ -205384,9 +205481,12 @@ exports.functions = (0, types_js_1.defineModule)({
|
|
|
205384
205481
|
"\n- `limit`: page size, the default is decided by the backend" +
|
|
205385
205482
|
"\n- `offset`: pagination offset, starting from 0" +
|
|
205386
205483
|
"\n- Example: `queryFunctions(action=\"listFunctions\", offset=10, limit=10)`" +
|
|
205387
|
-
"\n\n**Querying cloud function logs**: use `action=\"listFunctionLogs\"`, which requires
|
|
205484
|
+
"\n\n**Querying cloud function logs**: use `action=\"listFunctionLogs\"`, which requires `functionName`. Logs are retrieved from CLS (the underlying GetFunctionLogs API has been retired)." +
|
|
205388
205485
|
"\n- Example: `queryFunctions(action=\"listFunctionLogs\", functionName=\"my-function\")`" +
|
|
205389
|
-
"\n-
|
|
205486
|
+
"\n- Without startTime/endTime it queries the last day; the span must not exceed 1 day and a single call returns at most 100 entries" +
|
|
205487
|
+
"\n- `hasMore=true` means older logs exist: pass the returned `context` back unchanged to fetch the next page (`offset` only works within the first 100 entries)" +
|
|
205488
|
+
"\n- Each `logs[]` item is parsed into requestId / log / statusCode / retCode / durationMs / memoryMb / timestamp" +
|
|
205489
|
+
"\n- To see the full sequence of one invocation (START, business logs, REPORT): `queryFunctions(action=\"getFunctionLogDetail\", requestId=\"xxx\")`" +
|
|
205390
205490
|
"\n\n**Scheduled tasks / cron / timers**: use `listFunctionTriggers` to query a function's timer trigger configuration." +
|
|
205391
205491
|
"\n\n**Versions and traffic routing**: `listVersionByFunction` lists published versions (aligns with tcb fn list-function-versions); `getFunctionAlias` views alias / canary config (aligns with tcb fn get-route; aliasName defaults to `$DEFAULT`)." +
|
|
205392
205492
|
"\n\n**Layers**:" +
|
|
@@ -205456,8 +205556,8 @@ exports.functions = (0, types_js_1.defineModule)({
|
|
|
205456
205556
|
endTimeInvalid: "Invalid endTime: \"{value}\". It must use the YYYY-MM-DD HH:mm:ss format (e.g. 2024-01-01 23:59:59)",
|
|
205457
205557
|
logRangeInvalidDatetime: "startTime and endTime must be valid datetime strings",
|
|
205458
205558
|
logRangeTooLong: "The interval between startTime and endTime must not exceed one day",
|
|
205459
|
-
logsInvalidParamTips: "Common causes:\n1. startTime/endTime format error; it must be YYYY-MM-DD HH:mm:ss (e.g. 2024-01-01 00:00:00); ISO 8601 or timestamps are not supported\n2. The interval between startTime and endTime exceeds one day\n3. functionName does not
|
|
205460
|
-
logDetailInvalidParamTips: "Common causes:\n1. startTime/endTime format error; it must be YYYY-MM-DD HH:mm:ss (e.g. 2024-01-01 00:00:00); ISO 8601 or timestamps are not supported\n2. The interval between startTime and endTime exceeds one day\
|
|
205559
|
+
logsInvalidParamTips: "Common causes:\n1. startTime/endTime format error; it must be YYYY-MM-DD HH:mm:ss (e.g. 2024-01-01 00:00:00); ISO 8601 or timestamps are not supported\n2. The interval between startTime and endTime exceeds one day\n3. functionName does not match function_name in the logs (case-sensitive), or qualifier does not match\nTip: without startTime/endTime, logs from the most recent day are queried by default.",
|
|
205560
|
+
logDetailInvalidParamTips: "Common causes:\n1. startTime/endTime format error; it must be YYYY-MM-DD HH:mm:ss (e.g. 2024-01-01 00:00:00); ISO 8601 or timestamps are not supported\n2. The interval between startTime and endTime exceeds one day\n3. requestId falls outside that window (logs are filed by request start time)\nTip: locate the requestId with listFunctionLogs first.",
|
|
205461
205561
|
paramRequired: "The {param} parameter is required for the {action} action",
|
|
205462
205562
|
"deployStatus.cloudMode": "{action} is unavailable in cloud mode: async deployment tasks are only created by real deployments with buildStrategy=cloud/local, and real execution of both strategies is unsupported in cloud mode (they need the local build context or local Docker), so no taskId can exist. buildStrategy=image uses synchronous deployment and returns the result directly from manageFunctions, so no deployment status query is needed. For async image build deployment, switch to local MCP mode.",
|
|
205463
205563
|
deployTaskNotFound: "Deployment task {taskId} not found; the task does not exist — it may have expired, belong to a different environment than {envId}, or the MCP Server was restarted (tasks are only kept in MCP process memory).",
|
|
@@ -205472,7 +205572,11 @@ exports.functions = (0, types_js_1.defineModule)({
|
|
|
205472
205572
|
"reason.viewLogs": "View the execution logs of this function",
|
|
205473
205573
|
"reason.updateConfig": "Update this function's configuration",
|
|
205474
205574
|
"reason.checkGateway": "Check whether this function has an exposed gateway access URL",
|
|
205475
|
-
"reason.logDetail": "View
|
|
205575
|
+
"reason.logDetail": "View the full logs of that invocation by requestId",
|
|
205576
|
+
"reason.nextLogPage": "Pass context back to fetch the next (older) page of logs",
|
|
205577
|
+
"reason.widenLogRange": "Query this function's logs again with a wider time range",
|
|
205578
|
+
"reason.createLogService": "Enable the environment log service before querying function logs",
|
|
205579
|
+
"reason.searchClsFallback": "Search CLS directly with queryLogs using the same query string",
|
|
205476
205580
|
"reason.attachLayer": "Attach an additional layer to this function",
|
|
205477
205581
|
"reason.reorderLayers": "Adjust layer order or the binding list as a whole",
|
|
205478
205582
|
"reason.layerVersions": "View the version list of a layer",
|
|
@@ -205517,6 +205621,10 @@ exports.functions = (0, types_js_1.defineModule)({
|
|
|
205517
205621
|
gotFunctionDetail: "Retrieved details of function {fnName}",
|
|
205518
205622
|
gotFunctionLogs: "Retrieved the log list of function {fnName}",
|
|
205519
205623
|
gotLogDetail: "Retrieved the log detail for requestId={requestId}",
|
|
205624
|
+
"logs.emptyByFunction": "No logs found for function {fnName} between {start} and {end}. Common causes: the function was not invoked in that window, the logs have passed their retention period, or functionName / qualifier does not match. Widen the time range and retry.",
|
|
205625
|
+
"logs.emptyByRequest": "No logs found for requestId={requestId} between {start} and {end}. Make sure the window covers that invocation (logs are filed by request start time), or use a requestId located through listFunctionLogs.",
|
|
205626
|
+
"logs.serviceNotEnabled": "The log service is not enabled for this environment, so function logs cannot be read. Call manageLogs(action=\"createLogService\", confirm=true) first, then query again.",
|
|
205627
|
+
"logs.queryFailed": "Failed to query function logs: {message}",
|
|
205520
205628
|
gotFunctionLayers: "Retrieved the layers currently bound to function {fnName}",
|
|
205521
205629
|
gotLayers: "Retrieved {count} layer records",
|
|
205522
205630
|
gotLayerVersions: "Retrieved the version list of layer {layerName}",
|
|
@@ -205597,16 +205705,17 @@ exports.functions = (0, types_js_1.defineModule)({
|
|
|
205597
205705
|
"schema.create.layers": "Layer configuration",
|
|
205598
205706
|
"schema.manageLayer.name": "Layer name",
|
|
205599
205707
|
"schema.manageLayer.version": "Layer version number",
|
|
205600
|
-
"schema.query.action": "Read-only action type:\n- `listFunctions`: list all CloudBase cloud functions\n- `getFunctionDetail`: get function details (requires functionName)\n- `listFunctionLogs`: query function execution logs (requires functionName)\n- `getFunctionLogDetail`: get log
|
|
205708
|
+
"schema.query.action": "Read-only action type:\n- `listFunctions`: list all CloudBase cloud functions\n- `getFunctionDetail`: get function details (requires functionName)\n- `listFunctionLogs`: query function execution logs (requires functionName; retrieved via CLS, defaults to the last day, at most 100 entries per call, pass context to page)\n- `getFunctionLogDetail`: get the full log sequence of one invocation (requires requestId, taken from logs[].requestId of listFunctionLogs)\n- `listFunctionLayers`: list layers bound to a function\n- `listLayers`: list all layers (account-level view, including layers from other environments)\n- `listLayerVersions`: list layer versions (Versions, not Version; account-level view)\n- `getLayerVersionDetail`: get layer version details (account-level view)\n- `listFunctionTriggers`: list function triggers (scheduled task / cron / timer configuration)\n- `getFunctionDownloadUrl`: get the function code download URL\n- `getFunctionDeployStatus`: query async deployment status, stage progress, and final result by taskId. Returns data.build, data.deploy, and data.progress. While status=running, data.result and data.error are null and deployment must not be reported as complete. Keep polling until status=succeeded/failed. status=expired means the task exceeded the 2-hour retention limit; cloud deployment may still be running, so confirm with getFunctionDetail. Tasks exist only in MCP process memory; expired tasks or a restarted MCP Server return errorCode=DEPLOY_TASK_NOT_FOUND. Tasks are isolated by environment. This action is unavailable in cloud mode because real cloud/local builds cannot run there, while image deployment is synchronous and creates no taskId.\n- `listVersionByFunction`: list published function versions (aligns with tcb fn list-function-versions / SDK listVersionByFunction; requires functionName)\n- `getFunctionAlias`: get function alias and traffic routing (aligns with tcb fn get-route / SDK getFunctionAlias; requires functionName; aliasName defaults to $DEFAULT)\n- `getFunctionUploadUrl`: get a COS presigned upload URL for a function code package (two-phase ZIP deployment phase A): PUT the code zip to uploadUrl (include the corresponding request headers when uploadHeaders is non-empty), then call manageFunctions createFunction/updateFunctionCode with the code triplet (phase B). functionName is optional and only shapes the upload object key. The uploadUrl carries credential-bound signatures; never log or persist it; phase B verifies that the triplet's bucket and region are this environment's own bucket, so an address is only usable in the environment it was minted for; the address is valid for 300 seconds by default",
|
|
205601
205709
|
"schema.query.functionName": "CloudBase cloud function name. Required for `getFunctionDetail`, `listFunctionLogs`, `listFunctionLayers`, `listFunctionTriggers`, `getFunctionDownloadUrl`, `listVersionByFunction`, and `getFunctionAlias`. Optional for `getFunctionUploadUrl` (only used to generate the upload object key).",
|
|
205602
|
-
"schema.query.limit": "Page size (limit). Optional for list actions; the backend determines the default.",
|
|
205603
|
-
"schema.query.offset": "Pagination offset. Optional for list actions; defaults to 0.",
|
|
205710
|
+
"schema.query.limit": "Page size (limit). Optional for list actions; the backend determines the default. Log actions return at most 100 entries and default to 20.",
|
|
205711
|
+
"schema.query.offset": "Pagination offset. Optional for list actions; defaults to 0. For log actions it only works within the first 100 entries — use the returned context to page further back.",
|
|
205604
205712
|
"schema.query.codeSecret": "Code protection secret used to decrypt function code.",
|
|
205605
205713
|
"schema.query.revealEnvValues": "Whether `getFunctionDetail` / `listFunctionTriggers` / `listFunctionLayers` returns plaintext environment variable values. Defaults to false: Value is masked as ***, while Key and ValueLength remain, which is sufficient to verify configured variables and changes. true returns plaintext and may expose secrets to the model context; use cautiously. Prefer the console or CLI for plaintext values.",
|
|
205606
|
-
"schema.query.startTime": "Log query start time in YYYY-MM-DD HH:mm:ss format (for example, 2024-01-01 00:00:00). The interval to endTime must not exceed one day. Defaults to the most recent day when omitted.",
|
|
205607
|
-
"schema.query.endTime": "Log query end time in YYYY-MM-DD HH:mm:ss format (for example, 2024-01-01 23:59:59). The interval from startTime must not exceed one day. Defaults to the current time when omitted.",
|
|
205608
|
-
"schema.query.requestId": "Log request ID. Required for `getFunctionLogDetail`;
|
|
205609
|
-
"schema.query.qualifier": "Function version alias, such as $LATEST or $DEFAULT. Optional for log queries.",
|
|
205714
|
+
"schema.query.startTime": "Log query start time in YYYY-MM-DD HH:mm:ss format (for example, 2024-01-01 00:00:00, interpreted as Beijing time). The interval to endTime must not exceed one day. Defaults to the most recent day when omitted.",
|
|
205715
|
+
"schema.query.endTime": "Log query end time in YYYY-MM-DD HH:mm:ss format (for example, 2024-01-01 23:59:59, interpreted as Beijing time). The interval from startTime must not exceed one day. Defaults to the current time when omitted.",
|
|
205716
|
+
"schema.query.requestId": "Log request ID. Required for `getFunctionLogDetail`; take it from logs[].requestId returned by `listFunctionLogs`, or use the RequestId printed in a business log line.",
|
|
205717
|
+
"schema.query.qualifier": "Function version alias, such as $LATEST or $DEFAULT. Optional for log queries; used as a CLS filter.",
|
|
205718
|
+
"schema.query.context": "Log pagination cursor. Pass the `context` returned by the previous `listFunctionLogs` call back unchanged to fetch the next page; never construct it yourself. null means there are no more results.",
|
|
205610
205719
|
"schema.query.runtime": "Runtime filter for layer queries, such as Nodejs18.15.",
|
|
205611
205720
|
"schema.query.searchKey": "Layer name search keyword.",
|
|
205612
205721
|
"schema.query.layerName": "Layer name. Required for `listLayerVersions` and `getLayerVersionDetail`. Layers use an account-level shared namespace; use the fixed format `{layerName}_{current envId}` (for example, common_cloud1-d9ghadgak3edf6b36).",
|
|
@@ -205672,9 +205781,9 @@ exports.gateway = void 0;
|
|
|
205672
205781
|
const types_js_1 = __webpack_require__(89921);
|
|
205673
205782
|
exports.gateway = (0, types_js_1.defineModule)({
|
|
205674
205783
|
"query.title": "查询 CloudBase 网关",
|
|
205675
|
-
"query.description": "CloudBase HTTP 网关统一只读入口(Domain/Route)。查询域名下路径路由及其上游:WEB_SCF/SCF=云函数,CBR=云托管,STATIC_STORE=静态托管,LH=轻量应用服务器。主键为 Domain + Path;listRoutes / getRoute / listCustomDomains / getPrivilege。getPrivilege 查询 HTTP 网关总开关(enableService)与访问鉴权(enableAuth
|
|
205784
|
+
"query.description": "CloudBase HTTP 网关统一只读入口(Domain/Route)。查询域名下路径路由及其上游:WEB_SCF/SCF=云函数,CBR=云托管,STATIC_STORE=静态托管,STORAGE=云存储,LH=轻量应用服务器。主键为 Domain + Path;listRoutes / getRoute / listCustomDomains / getPrivilege / cachePurgeTask。getPrivilege 查询 HTTP 网关总开关(enableService)与访问鉴权(enableAuth)状态。cachePurgeTask 查询域名缓存清除任务(先 manageGateway purgeCache 拿 TaskId)。实现自定义域名访问前,先 listCustomDomains:若已有自定义域名,优先 createRoute 挂路由(无需证书 ID);仅在没有可用自定义域名时才 bindCustomDomain。",
|
|
205676
205785
|
"manage.title": "管理 CloudBase 网关",
|
|
205677
|
-
"manage.description": "CloudBase HTTP 网关统一写入口(Domain/Route)。createRoute/updateRoute/deleteRoute 把域名下的 path 转到上游;enableRoute/disableRoute 启用或禁用已有路由(底层 ModifyHTTPServiceRoute 的 Routes[].Enable,不是 ModifyGatewayRoute)。未传 domain 时用 DomainType=HTTPSERVICE 的 IsDefault 默认 HTTP 域名(形如 *.{region}.app.tcloudbase.com),不会使用静态托管 CDN 域名(*.tcloudbaseapp.com,DomainType=STATIC_STORE)。这是网关默认域上的路径路由,不是 STATIC_STORE 上游绑定;STATIC_STORE 上游必须显式传 upstreamResourceType=STATIC_STORE。关闭静态托管默认域名(*.tcloudbaseapp.com):先 queryGateway(listRoutes) 找到 DomainType=STATIC_STORE 且 IsDefault=true 的 domain,再 manageGateway(action=\"disableRoute\", domain=该域名, path=\"/\");勿用 manageHosting。创建后可用 queryGateway(action=\"listRoutes\") 核对 Domain / DomainType / Path / UpstreamResourceType。上游类型只用一个参数 upstreamResourceType(也可写在 route.upstreamResourceType,route 优先):WEB_SCF=HTTP云函数,SCF=Event云函数,CBR=云托管,STATIC_STORE=静态托管,LH=轻量应用服务器;配合 targetName 或 route.serviceName(云函数名/云托管服务名/静态托管实例名,常见 staticstore
|
|
205786
|
+
"manage.description": "CloudBase HTTP 网关统一写入口(Domain/Route)。createRoute/updateRoute/deleteRoute 把域名下的 path 转到上游;enableRoute/disableRoute 启用或禁用已有路由(底层 ModifyHTTPServiceRoute 的 Routes[].Enable,不是 ModifyGatewayRoute)。未传 domain 时用 DomainType=HTTPSERVICE 的 IsDefault 默认 HTTP 域名(形如 *.{region}.app.tcloudbase.com),不会使用静态托管 CDN 域名(*.tcloudbaseapp.com,DomainType=STATIC_STORE)。这是网关默认域上的路径路由,不是 STATIC_STORE 上游绑定;STATIC_STORE 上游必须显式传 upstreamResourceType=STATIC_STORE。关闭静态托管默认域名(*.tcloudbaseapp.com):先 queryGateway(listRoutes) 找到 DomainType=STATIC_STORE 且 IsDefault=true 的 domain,再 manageGateway(action=\"disableRoute\", domain=该域名, path=\"/\");勿用 manageHosting。创建后可用 queryGateway(action=\"listRoutes\") 核对 Domain / DomainType / Path / UpstreamResourceType。上游类型只用一个参数 upstreamResourceType(也可写在 route.upstreamResourceType,route 优先):WEB_SCF=HTTP云函数,SCF=Event云函数,CBR=云托管,STATIC_STORE=静态托管,STORAGE=云存储,LH=轻量应用服务器;配合 targetName 或 route.serviceName(云函数名/云托管服务名/静态托管实例名,常见 staticstore/云存储实例名)。createRoute 只建网关入口,不改上游权限。enablePathTransmission:默认 false 剥触发路径前缀;true 透传完整路径(CBR 多路由、WEB_SCF 自管子路径常需 true;STATIC_STORE 自定义触发路径映射站点根通常 false)。⚠️ 自定义域名访问:若环境已有自定义域名(先 queryGateway listCustomDomains),优先 createRoute 并显式传入该 domain,无需 certificateId;仅首次绑定全新自定义域名时用 bindCustomDomain(certificateId 可选:未传时按域名自动检索证书,单证书自动选用、多证书返回选择指引)。createRoute / bindCustomDomain 创建前会调用 VerifyHTTPServiceRoute 做归属权等预检(探测→创建);失败时返回 data.checks 与 DNS TXT 指引,配置后重试。CORS/安全域名(浏览器跨域白名单,与本工具的网关自定义域名无关)用 manageEnv(action=addSecurityDomain/removeSecurityDomain)。enableService/authSwitch:HTTP 网关总开关与访问鉴权开关;createRoute 后若访问报 HTTPSERVICE_NONACTIVATED,通常是总开关未开启(用 queryGateway getPrivilege 查询、enableService 开启)。purgeCache:清除域名缓存(CDN/EO,按 URL/前缀/整站),返回 TaskId 后用 queryGateway cachePurgeTask 查进度。路由级还支持 enableSafeDomain(跨域/合法域名校验)、pathRewrite(路径重写)、qpsPolicy(限频)、extension(自定义请求/响应头与缓存规则);域名级支持 protocol 与 domainExtension。updateRoute 只传要改的字段即可,未传的 CORS/重写/限频/扩展配置会保持原值。",
|
|
205678
205787
|
"verify.failWithDns": "HTTP 服务域名配置预检未通过:域名归属权校验失败。请按 data.checks 中 ownership.dnsRecords 配置 DNS TXT 记录后重试。",
|
|
205679
205788
|
"verify.fail": "HTTP 服务域名配置预检未通过。请根据 data.checks 修复问题后重试。",
|
|
205680
205789
|
"verify.failWithDnsReason": "配置 DNS TXT(主机记录/记录类型/记录值见 data.checks[].dnsRecords)后重新调用本 action",
|
|
@@ -205692,7 +205801,7 @@ exports.gateway = (0, types_js_1.defineModule)({
|
|
|
205692
205801
|
"privilege.nonActivatedHint": ";若路由创建成功但访问报 HTTPSERVICE_NONACTIVATED(403),请先开启 HTTP 网关",
|
|
205693
205802
|
"privilege.enableServiceReason": "开启 HTTP 网关总开关(EnableService),开启后路由即可通过默认域访问",
|
|
205694
205803
|
"defaultDomain.notReady": "环境默认 HTTP 访问域名未就绪或未开通。请先在控制台开通 HTTP 访问服务,或用 queryGateway(action=\"listRoutes\") 确认 Domains 中是否存在 DomainType=HTTPSERVICE 且 IsDefault=true 的域名(形如 *.{region}.app.tcloudbase.com);不要使用静态托管域名(*.tcloudbaseapp.com)。也可以显式传入 domain 后重试 createRoute/updateRoute/deleteRoute。",
|
|
205695
|
-
"upstreamTypeRequired": "必须提供 upstreamResourceType(或 route.upstreamResourceType):WEB_SCF=HTTP云函数,SCF=Event云函数,CBR=云托管,STATIC_STORE=静态托管,LH=轻量应用服务器。禁止仅凭 targetName/serviceName 推断上游类型。",
|
|
205804
|
+
"upstreamTypeRequired": "必须提供 upstreamResourceType(或 route.upstreamResourceType):WEB_SCF=HTTP云函数,SCF=Event云函数,CBR=云托管,STATIC_STORE=静态托管,STORAGE=云存储,LH=轻量应用服务器。禁止仅凭 targetName/serviceName 推断上游类型。",
|
|
205696
205805
|
"upstreamNameRequired": "必须提供 targetName 或 route.serviceName 作为上游资源名称:云函数名、云托管服务名,或静态托管实例名(常见为 staticstore)。",
|
|
205697
205806
|
"toggle.pathRequired": "action=enableRoute/disableRoute 时必须提供 path 或 route.path(例如 \"/\" 或 \"/api\")",
|
|
205698
205807
|
"toggle.notFound": "未找到路径 {path} 的路由{domainSuffix}{upstreamSuffix}。请先用 queryGateway(action=\"listRoutes\") 确认 Domain / Path,再调用 enableRoute/disableRoute。关闭静态托管默认域名(*.tcloudbaseapp.com)时,请显式传 domain=该 STATIC_STORE IsDefault 域名,并通常 path=\"/\"。",
|
|
@@ -205758,14 +205867,32 @@ exports.gateway = (0, types_js_1.defineModule)({
|
|
|
205758
205867
|
"authSwitch.onMessage": "HTTP 访问服务鉴权开启成功",
|
|
205759
205868
|
"authSwitch.offMessage": "HTTP 访问服务鉴权关闭成功",
|
|
205760
205869
|
"authSwitch.verifyReason": "复核 HTTP 网关总开关与访问鉴权状态",
|
|
205870
|
+
"purgeCache.domainRequired": "action=purgeCache 时必须提供 domain",
|
|
205871
|
+
"purgeCache.targetsRequired": "action=purgeCache 时必须提供 targets:PURGE_URL 传完整 URL、PURGE_PREFIX 传路径前缀、PURGE_HOST 传待刷新的域名",
|
|
205872
|
+
"purgeCache.message": "已提交 {count} 个目标的缓存清除任务;CDN/EO 刷新通常数秒到数分钟,请用 queryGateway(action=\"cachePurgeTask\") 按 TaskId 查进度",
|
|
205873
|
+
"purgeCache.verifyReason": "查询缓存清除任务状态",
|
|
205874
|
+
"query.cachePurgeTask": "已获取 {count} 条缓存清除任务记录",
|
|
205875
|
+
"query.cachePurgeTaskDomainRequired": "action=cachePurgeTask 时必须提供 domain",
|
|
205876
|
+
"cache.domainNotFound": "未找到域名 {domain} 的接入配置,无法确定缓存层。请先用 queryGateway(action=\"listRoutes\") 确认域名。",
|
|
205877
|
+
"cache.notManaged": "域名 {domain} 的接入方式是 {accessType},CloudBase 侧没有该域名的 CDN/EO 缓存,缓存刷新不适用(DIRECT 直连与 CUSTOM 自有 CDN 的缓存不由平台托管)。如需刷新,请先把域名切到 CDN 或 EO 接入。",
|
|
205878
|
+
"cache.typeMismatch": "域名 {domain} 的接入方式是 {accessType},不能按 cacheType={requested} 刷新。省略 cacheType 就会按接入方式自动匹配。",
|
|
205761
205879
|
// Input schema parameter descriptions
|
|
205762
|
-
"schema.query.action": "只读操作类型:listRoutes、getRoute、listCustomDomains、getPrivilege。" +
|
|
205880
|
+
"schema.query.action": "只读操作类型:listRoutes、getRoute、listCustomDomains、getPrivilege、cachePurgeTask。" +
|
|
205763
205881
|
"getPrivilege 无需其他参数,直接返回 HTTP 网关总开关与访问鉴权状态。" +
|
|
205882
|
+
"cachePurgeTask 需要 domain(可选 cacheType/taskId/purgeType/startTime/endTime/offset/limit)。" +
|
|
205764
205883
|
"自定义域名访问场景先 listCustomDomains 确认是否已有域名可复用。",
|
|
205765
205884
|
"schema.query.targetName": "上游资源名过滤(UpstreamResourceName):云函数名、云托管服务名,或静态托管实例名(常见 staticstore)。",
|
|
205766
205885
|
"schema.query.routeId": "路由 ID。getRoute 时可选",
|
|
205767
205886
|
"schema.query.path": "路由路径。getRoute / listRoutes 过滤时可选",
|
|
205768
|
-
"schema.query.domain": "域名。getRoute / listRoutes
|
|
205887
|
+
"schema.query.domain": "域名。getRoute / listRoutes 过滤时可选;cachePurgeTask 时必填",
|
|
205888
|
+
"schema.query.cacheType": "缓存层(仅 cachePurgeTask):CDN 或 EO。省略时按域名接入方式自动匹配(EO→EO、CDN→CDN);" +
|
|
205889
|
+
"DIRECT / CUSTOM / NONE 的域没有 CloudBase 托管的缓存,会直接拒绝并说明原因。",
|
|
205890
|
+
"schema.query.taskId": "缓存清除任务 ID(仅 cachePurgeTask,可选过滤)",
|
|
205891
|
+
"schema.query.purgeType": "清除方式过滤(仅 cachePurgeTask):PURGE_URL=按 URL、PURGE_PREFIX=按前缀、PURGE_HOST=整站",
|
|
205892
|
+
"schema.query.startTime": "任务开始时间(仅 cachePurgeTask,可选)。格式 YYYY-MM-DD HH:mm:ss",
|
|
205893
|
+
"schema.query.endTime": "任务结束时间(仅 cachePurgeTask,可选)。格式 YYYY-MM-DD HH:mm:ss",
|
|
205894
|
+
"schema.query.offset": "分页偏移(仅 cachePurgeTask,可选)",
|
|
205895
|
+
"schema.query.limit": "返回数量上限(仅 cachePurgeTask,可选)",
|
|
205769
205896
|
"schema.manage.action": "写操作:createRoute/updateRoute/deleteRoute 管理路由;enableRoute/disableRoute 启用或禁用已有路由(需 path,建议显式传 domain);" +
|
|
205770
205897
|
"bindCustomDomain/deleteCustomDomain 管理自定义域名;" +
|
|
205771
205898
|
"enableService/authSwitch 开关 HTTP 网关总开关与访问鉴权(需配合 enable 参数)。" +
|
|
@@ -205775,13 +205902,15 @@ exports.gateway = (0, types_js_1.defineModule)({
|
|
|
205775
205902
|
"已有自定义域名时优先 createRoute(domain=已有域名) 实现访问,不必再次 bindCustomDomain / 传入 certificateId;" +
|
|
205776
205903
|
"bindCustomDomain 仅用于首次绑定新域名(certificateId 可选,未传则按域名自动检索;可选 accessType=DIRECT|CDN|CUSTOM,CUSTOM 需 customCname;普通场景用默认 DIRECT)。" +
|
|
205777
205904
|
"createRoute/bindCustomDomain 创建前会 VerifyHTTPServiceRoute 预检;失败时按返回的 DNS TXT 指引配置后重试。" +
|
|
205905
|
+
"purgeCache 清除域名缓存:需 domain 与 targets(配 purgeType=PURGE_URL|PURGE_PREFIX|PURGE_HOST,可选 cacheType=CDN|EO)。" +
|
|
205778
205906
|
"接入说明:https://docs.cloudbase.net/service/custom-domain",
|
|
205779
205907
|
"schema.manage.targetName": "上游资源名称(UpstreamResourceName),与 route.serviceName 二选一(route 优先)。" +
|
|
205780
205908
|
"云函数=函数名;云托管=服务名;静态托管=实例名(常见 staticstore)。不会自动推断上游类型。",
|
|
205781
205909
|
"schema.manage.path": "触发路径(网关匹配前缀),默认 /{上游名}。例:云函数 /api/hello、云托管 /api、静态托管 / 或 /app。" +
|
|
205782
205910
|
"只建网关入口;与 enablePathTransmission 共同决定上游实际收到的路径。",
|
|
205783
205911
|
"schema.manage.upstreamResourceType": "上游类型(与 route.upstreamResourceType 二选一,route 优先)。" +
|
|
205784
|
-
"WEB_SCF=HTTP云函数,SCF=Event云函数,CBR=云托管,STATIC_STORE=静态托管,LH=轻量应用服务器。" +
|
|
205912
|
+
"WEB_SCF=HTTP云函数,SCF=Event云函数,CBR=云托管,STATIC_STORE=静态托管,STORAGE=云存储,LH=轻量应用服务器。" +
|
|
205913
|
+
"STORAGE 的 UpstreamResourceName 是云存储实例名,可先用 queryStorage 查实例。" +
|
|
205785
205914
|
"createRoute/updateRoute 必填其一;勿把 manageFunctions 的 type=HTTP|Event 传到本字段。",
|
|
205786
205915
|
"schema.manage.auth": "网关路径鉴权(EnableAuth)。匿名/浏览器公网访问通常 false。" +
|
|
205787
205916
|
"只控制网关入口;云函数安全规则、云托管鉴权、静态托管权限需各自工具另行配置。",
|
|
@@ -205790,6 +205919,30 @@ exports.gateway = (0, types_js_1.defineModule)({
|
|
|
205790
205919
|
"CBR 云托管(Express 等自管子路由)与 WEB_SCF 多路径函数常需 true;" +
|
|
205791
205920
|
"STATIC_STORE 把触发路径映射到站点根目录(如 /app → 托管 /)时通常 false;" +
|
|
205792
205921
|
"单入口/根路径处理保持 false。也可用 route.enablePathTransmission(route 优先)。",
|
|
205922
|
+
"schema.manage.enableSafeDomain": "跨域/合法域名校验(EnableSafeDomain),即控制台的「跨域设置」。true 时校验请求来源域名," +
|
|
205923
|
+
"false 时不校验(浏览器直连调用 API 的常见选择)。也可用 route.enableSafeDomain(route 优先)。",
|
|
205924
|
+
"schema.manage.pathRewrite": "路径重写(PathRewrite),形如 {prefix:\"/v1\", staticStorePrefix:\"app\"}。" +
|
|
205925
|
+
"prefix=命中路径前缀后替换为的内容;staticStorePrefix=静态托管场景下的目标前缀。" +
|
|
205926
|
+
"不需要改写就省略;也可用 route.pathRewrite(route 优先)。",
|
|
205927
|
+
"schema.manage.qpsPolicy": "限频(QPSPolicy),即控制台的「频限」。{total:总 QPS, perClient:{limitBy:\"ClientIP\"|\"UserID\", limitValue:单客户端 QPS}}。" +
|
|
205928
|
+
"不传则不限频;也可用 route.qpsPolicy(route 优先)。",
|
|
205929
|
+
"schema.manage.extension": "路由级扩展(Extension),可配自定义请求/响应头与缓存规则。" +
|
|
205930
|
+
"{headersHandler:{requestHeadersToAdd,requestHeadersToRemove,responseHeadersToAdd,responseHeadersToRemove}," +
|
|
205931
|
+
"cache:{rules:[{description,enable,condition:{target,matchType,values},actions:[{type:\"Cache\"|\"CacheKey\",cache,cacheKey}]}]}}。" +
|
|
205932
|
+
"⚠️ 默认域(*.{region}.app.tcloudbase.com)不支持自定义响应头,后端会拒绝(实测 2026-10-21),需要自定义域名才能配。" +
|
|
205933
|
+
"也可用 route.extension(route 优先)。",
|
|
205934
|
+
"schema.manage.extension.header.key": "请求/响应头名称,如 X-Frame-Options",
|
|
205935
|
+
"schema.manage.extension.header.value": "请求/响应头取值,如 SAMEORIGIN",
|
|
205936
|
+
"schema.manage.extension.header.action": "写入策略(可选):APPEND_IF_EXISTS_OR_ADD 追加;ADD_IF_ABSENT 不存在才加;" +
|
|
205937
|
+
"OVERWRITE_IF_EXISTS_OR_ADD 覆盖或新增;OVERWRITE_IF_EXISTS 仅覆盖已存在的",
|
|
205938
|
+
"schema.manage.extension.cacheCondition": "缓存规则匹配条件:target=url_path/file_extension/full_uri,matchType=prefix/suffix/contains/exact,values=匹配值数组",
|
|
205939
|
+
"schema.manage.extension.cacheActions": "缓存动作数组:type=Cache 配 cache{followOrigin,noCache,cacheTime,maxAgeTime}(三者互斥,需开启其一);" +
|
|
205940
|
+
"type=CacheKey 配 cacheKey{fullUrlCache,queryStringSwitch,queryStringAction,queryStringValues}",
|
|
205941
|
+
"schema.manage.domainExtension": "域名级扩展(Extension),作用于整个域名(含该域名下所有路径)的自定义头与缓存规则,结构同 extension。" +
|
|
205942
|
+
"缓存规则通常配在域名级;仅 createRoute/updateRoute/bindCustomDomain 生效。" +
|
|
205943
|
+
"⚠️ 同 extension:默认域不支持自定义响应头,需自定义域名。",
|
|
205944
|
+
"schema.manage.protocol": "域名协议(Protocol),仅 createRoute/updateRoute/bindCustomDomain 生效:" +
|
|
205945
|
+
"HTTP / HTTPS / HTTP_AND_HTTPS / HTTP_TO_HTTPS / HTTPS_TO_HTTP。省略则沿用域名现有配置。",
|
|
205793
205946
|
"schema.manage.route.serviceName": "上游实例名:云函数名 / 云托管服务名 / 静态托管实例名(常见 staticstore)/ LH 实例。优先于顶层 targetName。",
|
|
205794
205947
|
"schema.manage.route.upstreamResourceType": "同顶层 upstreamResourceType。route 内设置时优先于顶层。",
|
|
205795
205948
|
"schema.manage.route.enablePathTransmission": "同顶层 enablePathTransmission。route 内设置时优先于顶层。",
|
|
@@ -205797,6 +205950,10 @@ exports.gateway = (0, types_js_1.defineModule)({
|
|
|
205797
205950
|
"enable=false 禁用该 Domain+Path(访问返回 GATEWAY_ROUTE_DISABLED);" +
|
|
205798
205951
|
"enable=true 重新启用。updateRoute 也可用顶层 enable 表达同一语义;" +
|
|
205799
205952
|
"也可用专用 action enableRoute/disableRoute。route.enable 优先于顶层 enable。",
|
|
205953
|
+
"schema.manage.route.enableSafeDomain": "同顶层 enableSafeDomain(跨域/合法域名校验)。route 内设置时优先于顶层。",
|
|
205954
|
+
"schema.manage.route.pathRewrite": "同顶层 pathRewrite。route 内设置时优先于顶层。",
|
|
205955
|
+
"schema.manage.route.qpsPolicy": "同顶层 qpsPolicy(限频)。route 内设置时优先于顶层。",
|
|
205956
|
+
"schema.manage.route.extension": "同顶层 extension(路由级自定义头与缓存规则)。route 内设置时优先于顶层。",
|
|
205800
205957
|
"schema.manage.route": "路由对象(可选写法)。例:云函数 {upstreamResourceType:\"WEB_SCF\",serviceName:\"fn\",path:\"/api\"};" +
|
|
205801
205958
|
"云托管 {upstreamResourceType:\"CBR\",serviceName:\"svc\",path:\"/api\"};" +
|
|
205802
205959
|
"静态托管 {upstreamResourceType:\"STATIC_STORE\",serviceName:\"staticstore\",path:\"/\"};" +
|
|
@@ -205821,11 +205978,15 @@ exports.gateway = (0, types_js_1.defineModule)({
|
|
|
205821
205978
|
"updateRoute 可选:映射到 Routes[].Enable(也可用 route.enable,route 优先;" +
|
|
205822
205979
|
"也可用专用 action enableRoute/disableRoute)。" +
|
|
205823
205980
|
"省略或非布尔值在 enableService/authSwitch 会返回参数错误。",
|
|
205981
|
+
"schema.manage.cacheType": "缓存层(仅 purgeCache):CDN 或 EO。省略时按域名接入方式自动匹配(EO→EO、CDN→CDN);" +
|
|
205982
|
+
"DIRECT / CUSTOM / NONE 的域没有 CloudBase 托管的缓存,会直接拒绝并说明原因。",
|
|
205983
|
+
"schema.manage.purgeType": "清除方式(仅 purgeCache,默认 PURGE_URL):PURGE_URL=按完整 URL、PURGE_PREFIX=按路径前缀、PURGE_HOST=整个域名",
|
|
205984
|
+
"schema.manage.targets": "清除目标(仅 purgeCache,必填):PURGE_URL 传 https://域名/路径 形式;PURGE_PREFIX 传 /static/ 这样的前缀;PURGE_HOST 传域名本身",
|
|
205824
205985
|
}, {
|
|
205825
205986
|
"query.title": "Query CloudBase Gateway",
|
|
205826
|
-
"query.description": "Unified read-only entry for the CloudBase HTTP gateway (Domain/Route). Query path routes under a domain and their upstreams: WEB_SCF/SCF=cloud functions, CBR=CloudRun, STATIC_STORE=static hosting, LH=Lighthouse. The primary key is Domain + Path; listRoutes / getRoute / listCustomDomains / getPrivilege. getPrivilege queries the HTTP gateway master switch (enableService) and access auth (enableAuth) status. Before setting up custom domain access, run listCustomDomains first: if a custom domain already exists, prefer createRoute to attach a route (no certificate ID needed); use bindCustomDomain only when no usable custom domain exists.",
|
|
205987
|
+
"query.description": "Unified read-only entry for the CloudBase HTTP gateway (Domain/Route). Query path routes under a domain and their upstreams: WEB_SCF/SCF=cloud functions, CBR=CloudRun, STATIC_STORE=static hosting, STORAGE=cloud storage, LH=Lighthouse. The primary key is Domain + Path; listRoutes / getRoute / listCustomDomains / getPrivilege / cachePurgeTask. getPrivilege queries the HTTP gateway master switch (enableService) and access auth (enableAuth) status. cachePurgeTask queries cache purge tasks for a domain (use the TaskId from manageGateway purgeCache). Before setting up custom domain access, run listCustomDomains first: if a custom domain already exists, prefer createRoute to attach a route (no certificate ID needed); use bindCustomDomain only when no usable custom domain exists.",
|
|
205827
205988
|
"manage.title": "Manage CloudBase Gateway",
|
|
205828
|
-
"manage.description": "Unified write entry for the CloudBase HTTP gateway (Domain/Route). createRoute/updateRoute/deleteRoute forward a path under a domain to an upstream; enableRoute/disableRoute enable or disable existing routes (Routes[].Enable of ModifyHTTPServiceRoute underneath, not ModifyGatewayRoute). When domain is omitted, the IsDefault default HTTP domain with DomainType=HTTPSERVICE (like *.{region}.app.tcloudbase.com) is used; static-hosting CDN domains (*.tcloudbaseapp.com, DomainType=STATIC_STORE) are never used. These are path routes on the gateway default domain, not STATIC_STORE upstream bindings; a STATIC_STORE upstream must pass upstreamResourceType=STATIC_STORE explicitly. To disable the static-hosting default domain (*.tcloudbaseapp.com): first queryGateway(listRoutes) to find the domain with DomainType=STATIC_STORE and IsDefault=true, then manageGateway(action=\"disableRoute\", domain=that domain, path=\"/\"); do not use manageHosting. After creation, verify Domain / DomainType / Path / UpstreamResourceType via queryGateway(action=\"listRoutes\"). The upstream type uses a single parameter upstreamResourceType (or route.upstreamResourceType, route wins): WEB_SCF=HTTP cloud function, SCF=Event cloud function, CBR=CloudRun, STATIC_STORE=static hosting, LH=Lighthouse; together with targetName or route.serviceName (function name / CloudRun service name / static-hosting instance name, commonly staticstore). createRoute only creates the gateway entry and does not change upstream permissions. enablePathTransmission: default false strips the trigger path prefix; true forwards the full path (CBR multi-route and WEB_SCF self-managed sub-paths often need true; STATIC_STORE custom trigger path mapping to site root usually false). ⚠️ Custom domain access: if the env already has a custom domain (queryGateway listCustomDomains first), prefer createRoute with that domain explicitly, no certificateId needed; use bindCustomDomain only when binding a brand-new custom domain for the first time (certificateId optional: when omitted, certificates are auto-searched by domain — a single cert is auto-selected, multiple certs return selection guidance). createRoute / bindCustomDomain call VerifyHTTPServiceRoute for ownership pre-checks before creation (probe → create); on failure, data.checks and DNS TXT guidance are returned; configure and retry. CORS/security domains (browser cross-origin allowlist, unrelated to the gateway custom domains of this tool) use manageEnv(action=addSecurityDomain/removeSecurityDomain). enableService/authSwitch: HTTP gateway master switch and access auth switch; if access returns HTTPSERVICE_NONACTIVATED after createRoute, the master switch is usually off (query via queryGateway getPrivilege, enable via enableService).",
|
|
205989
|
+
"manage.description": "Unified write entry for the CloudBase HTTP gateway (Domain/Route). createRoute/updateRoute/deleteRoute forward a path under a domain to an upstream; enableRoute/disableRoute enable or disable existing routes (Routes[].Enable of ModifyHTTPServiceRoute underneath, not ModifyGatewayRoute). When domain is omitted, the IsDefault default HTTP domain with DomainType=HTTPSERVICE (like *.{region}.app.tcloudbase.com) is used; static-hosting CDN domains (*.tcloudbaseapp.com, DomainType=STATIC_STORE) are never used. These are path routes on the gateway default domain, not STATIC_STORE upstream bindings; a STATIC_STORE upstream must pass upstreamResourceType=STATIC_STORE explicitly. To disable the static-hosting default domain (*.tcloudbaseapp.com): first queryGateway(listRoutes) to find the domain with DomainType=STATIC_STORE and IsDefault=true, then manageGateway(action=\"disableRoute\", domain=that domain, path=\"/\"); do not use manageHosting. After creation, verify Domain / DomainType / Path / UpstreamResourceType via queryGateway(action=\"listRoutes\"). The upstream type uses a single parameter upstreamResourceType (or route.upstreamResourceType, route wins): WEB_SCF=HTTP cloud function, SCF=Event cloud function, CBR=CloudRun, STATIC_STORE=static hosting, STORAGE=cloud storage, LH=Lighthouse; together with targetName or route.serviceName (function name / CloudRun service name / static-hosting instance name, commonly staticstore / cloud storage instance name). createRoute only creates the gateway entry and does not change upstream permissions. enablePathTransmission: default false strips the trigger path prefix; true forwards the full path (CBR multi-route and WEB_SCF self-managed sub-paths often need true; STATIC_STORE custom trigger path mapping to site root usually false). ⚠️ Custom domain access: if the env already has a custom domain (queryGateway listCustomDomains first), prefer createRoute with that domain explicitly, no certificateId needed; use bindCustomDomain only when binding a brand-new custom domain for the first time (certificateId optional: when omitted, certificates are auto-searched by domain — a single cert is auto-selected, multiple certs return selection guidance). createRoute / bindCustomDomain call VerifyHTTPServiceRoute for ownership pre-checks before creation (probe → create); on failure, data.checks and DNS TXT guidance are returned; configure and retry. CORS/security domains (browser cross-origin allowlist, unrelated to the gateway custom domains of this tool) use manageEnv(action=addSecurityDomain/removeSecurityDomain). enableService/authSwitch: HTTP gateway master switch and access auth switch; if access returns HTTPSERVICE_NONACTIVATED after createRoute, the master switch is usually off (query via queryGateway getPrivilege, enable via enableService). purgeCache clears domain cache (CDN/EO by URL/prefix/host) and returns a TaskId; check progress with queryGateway cachePurgeTask. Route-level extras: enableSafeDomain (CORS / legit-domain check), pathRewrite (path rewriting), qpsPolicy (rate limiting), extension (custom request/response headers and cache rules); domain-level: protocol and domainExtension. updateRoute only needs the fields you want to change — untouched CORS/rewrite/QPS/extension settings are carried over from the live route.",
|
|
205829
205990
|
"verify.failWithDns": "HTTP service domain pre-check failed: domain ownership verification failed. Configure the DNS TXT records per ownership.dnsRecords in data.checks, then retry.",
|
|
205830
205991
|
"verify.fail": "HTTP service domain pre-check failed. Fix the issues per data.checks, then retry.",
|
|
205831
205992
|
"verify.failWithDnsReason": "Configure the DNS TXT records (host/record type/record value in data.checks[].dnsRecords), then call this action again",
|
|
@@ -205843,7 +206004,7 @@ exports.gateway = (0, types_js_1.defineModule)({
|
|
|
205843
206004
|
"privilege.nonActivatedHint": "; if the route is created successfully but access returns HTTPSERVICE_NONACTIVATED (403), enable the HTTP gateway first",
|
|
205844
206005
|
"privilege.enableServiceReason": "Turn on the HTTP gateway master switch (EnableService); once on, routes are accessible via the default domain",
|
|
205845
206006
|
"defaultDomain.notReady": "The env default HTTP access domain is not ready or not provisioned. Enable the HTTP access service in the console first, or use queryGateway(action=\"listRoutes\") to confirm that Domains contains a domain with DomainType=HTTPSERVICE and IsDefault=true (shaped like *.{region}.app.tcloudbase.com); do not use static-hosting domains (*.tcloudbaseapp.com). You may also pass domain explicitly and retry createRoute/updateRoute/deleteRoute.",
|
|
205846
|
-
"upstreamTypeRequired": "upstreamResourceType (or route.upstreamResourceType) is required: WEB_SCF=HTTP cloud function, SCF=Event cloud function, CBR=CloudRun, STATIC_STORE=static hosting, LH=Lighthouse. Do not infer the upstream type from targetName/serviceName alone.",
|
|
206007
|
+
"upstreamTypeRequired": "upstreamResourceType (or route.upstreamResourceType) is required: WEB_SCF=HTTP cloud function, SCF=Event cloud function, CBR=CloudRun, STATIC_STORE=static hosting, STORAGE=cloud storage, LH=Lighthouse. Do not infer the upstream type from targetName/serviceName alone.",
|
|
205847
206008
|
"upstreamNameRequired": "targetName or route.serviceName is required as the upstream resource name: a cloud function name, CloudRun service name, or static-hosting instance name (commonly staticstore).",
|
|
205848
206009
|
"toggle.pathRequired": "path or route.path is required for action=enableRoute/disableRoute (e.g. \"/\" or \"/api\")",
|
|
205849
206010
|
"toggle.notFound": "No route found for path {path}{domainSuffix}{upstreamSuffix}. Use queryGateway(action=\"listRoutes\") first to confirm Domain / Path, then call enableRoute/disableRoute. When disabling the static-hosting default domain (*.tcloudbaseapp.com), pass domain=that STATIC_STORE IsDefault domain explicitly, usually with path=\"/\".",
|
|
@@ -205909,14 +206070,32 @@ exports.gateway = (0, types_js_1.defineModule)({
|
|
|
205909
206070
|
"authSwitch.onMessage": "HTTP access service auth enabled successfully",
|
|
205910
206071
|
"authSwitch.offMessage": "HTTP access service auth disabled successfully",
|
|
205911
206072
|
"authSwitch.verifyReason": "Verify the HTTP gateway master switch and access auth status",
|
|
206073
|
+
"purgeCache.domainRequired": "domain is required for action=purgeCache",
|
|
206074
|
+
"purgeCache.targetsRequired": "targets is required for action=purgeCache: full URLs for PURGE_URL, path prefixes for PURGE_PREFIX, or the domain itself for PURGE_HOST",
|
|
206075
|
+
"purgeCache.message": "Submitted a cache purge task for {count} target(s); CDN/EO purges usually take seconds to minutes — check progress with queryGateway(action=\"cachePurgeTask\") by TaskId",
|
|
206076
|
+
"purgeCache.verifyReason": "Query the cache purge task status",
|
|
206077
|
+
"query.cachePurgeTask": "Retrieved {count} cache purge task record(s)",
|
|
206078
|
+
"query.cachePurgeTaskDomainRequired": "domain is required for action=cachePurgeTask",
|
|
206079
|
+
"cache.domainNotFound": "No access configuration found for domain {domain}, so the cache layer is undetermined. Confirm the domain with queryGateway(action=\"listRoutes\") first.",
|
|
206080
|
+
"cache.notManaged": "Domain {domain} uses access type {accessType}; CloudBase does not host a CDN/EO cache for it, so cache purging does not apply (DIRECT and CUSTOM own-CDN caches are not managed by the platform). Switch the domain to CDN or EO access first.",
|
|
206081
|
+
"cache.typeMismatch": "Domain {domain} uses access type {accessType} and cannot be purged with cacheType={requested}. Omit cacheType to match the access type automatically.",
|
|
205912
206082
|
// Input schema parameter descriptions
|
|
205913
|
-
"schema.query.action": "Read-only action: listRoutes, getRoute, listCustomDomains, getPrivilege. " +
|
|
206083
|
+
"schema.query.action": "Read-only action: listRoutes, getRoute, listCustomDomains, getPrivilege, cachePurgeTask. " +
|
|
205914
206084
|
"getPrivilege needs no other parameter and returns the HTTP gateway master switch and access auth status directly. " +
|
|
206085
|
+
"cachePurgeTask requires domain (optional cacheType/taskId/purgeType/startTime/endTime/offset/limit). " +
|
|
205915
206086
|
"For custom domain access, run listCustomDomains first to check whether an existing domain can be reused.",
|
|
205916
206087
|
"schema.query.targetName": "Upstream resource name filter (UpstreamResourceName): a cloud function name, CloudRun service name, or static-hosting instance name (commonly staticstore).",
|
|
205917
206088
|
"schema.query.routeId": "Route ID. Optional for getRoute",
|
|
205918
206089
|
"schema.query.path": "Route path. Optional as a getRoute / listRoutes filter",
|
|
205919
|
-
"schema.query.domain": "Domain. Optional as a getRoute / listRoutes filter",
|
|
206090
|
+
"schema.query.domain": "Domain. Optional as a getRoute / listRoutes filter; required for cachePurgeTask",
|
|
206091
|
+
"schema.query.cacheType": "Cache layer (cachePurgeTask only): CDN or EO. When omitted it is matched from the domain access type (EO→EO, CDN→CDN); " +
|
|
206092
|
+
"DIRECT / CUSTOM / NONE domains have no CloudBase-hosted cache and are rejected with an explanation.",
|
|
206093
|
+
"schema.query.taskId": "Cache purge task ID (cachePurgeTask only, optional filter)",
|
|
206094
|
+
"schema.query.purgeType": "Purge type filter (cachePurgeTask only): PURGE_URL=by URL, PURGE_PREFIX=by path prefix, PURGE_HOST=whole domain",
|
|
206095
|
+
"schema.query.startTime": "Task start time (cachePurgeTask only, optional). Format YYYY-MM-DD HH:mm:ss",
|
|
206096
|
+
"schema.query.endTime": "Task end time (cachePurgeTask only, optional). Format YYYY-MM-DD HH:mm:ss",
|
|
206097
|
+
"schema.query.offset": "Pagination offset (cachePurgeTask only, optional)",
|
|
206098
|
+
"schema.query.limit": "Max records to return (cachePurgeTask only, optional)",
|
|
205920
206099
|
"schema.manage.action": "Write actions: createRoute/updateRoute/deleteRoute manage routes; enableRoute/disableRoute enable or disable an existing route (path required, passing domain explicitly is recommended); " +
|
|
205921
206100
|
"bindCustomDomain/deleteCustomDomain manage custom domains; " +
|
|
205922
206101
|
"enableService/authSwitch toggle the HTTP gateway master switch and access auth (requires the enable parameter). " +
|
|
@@ -205926,13 +206105,15 @@ exports.gateway = (0, types_js_1.defineModule)({
|
|
|
205926
206105
|
"When a custom domain already exists, prefer createRoute(domain=existing domain) for access instead of calling bindCustomDomain / passing certificateId again; " +
|
|
205927
206106
|
"bindCustomDomain is only for binding a new domain the first time (certificateId is optional — when omitted, certificates are searched by domain; optional accessType=DIRECT|CDN|CUSTOM, CUSTOM requires customCname; use the default DIRECT for normal cases). " +
|
|
205928
206107
|
"createRoute/bindCustomDomain run a VerifyHTTPServiceRoute pre-check before creation; on failure, follow the returned DNS TXT guidance and retry. " +
|
|
206108
|
+
"purgeCache clears domain cache: requires domain and targets (with purgeType=PURGE_URL|PURGE_PREFIX|PURGE_HOST, optional cacheType=CDN|EO). " +
|
|
205929
206109
|
"Setup guide: https://docs.cloudbase.net/service/custom-domain",
|
|
205930
206110
|
"schema.manage.targetName": "Upstream resource name (UpstreamResourceName); use either this or route.serviceName (route wins). " +
|
|
205931
206111
|
"Cloud function=function name; CloudRun=service name; static hosting=instance name (commonly staticstore). The upstream type is never inferred automatically.",
|
|
205932
206112
|
"schema.manage.path": "Trigger path (the gateway match prefix), defaults to /{upstream name}. Examples: cloud function /api/hello, CloudRun /api, static hosting / or /app. " +
|
|
205933
206113
|
"This only creates the gateway entry; together with enablePathTransmission it determines the path the upstream actually receives.",
|
|
205934
206114
|
"schema.manage.upstreamResourceType": "Upstream type (use either this or route.upstreamResourceType, route wins). " +
|
|
205935
|
-
"WEB_SCF=HTTP cloud function, SCF=Event cloud function, CBR=CloudRun, STATIC_STORE=static hosting, LH=Lighthouse. " +
|
|
206115
|
+
"WEB_SCF=HTTP cloud function, SCF=Event cloud function, CBR=CloudRun, STATIC_STORE=static hosting, STORAGE=cloud storage, LH=Lighthouse. " +
|
|
206116
|
+
"For STORAGE, UpstreamResourceName is the cloud storage instance name — look it up with queryStorage first. " +
|
|
205936
206117
|
"One of them is required for createRoute/updateRoute; do not pass the manageFunctions type=HTTP|Event value into this field.",
|
|
205937
206118
|
"schema.manage.auth": "Gateway path auth (EnableAuth). Usually false for anonymous/browser public access. " +
|
|
205938
206119
|
"It only controls the gateway entry; cloud function security rules, CloudRun auth, and static hosting permissions must be configured with their own tools.",
|
|
@@ -205941,6 +206122,31 @@ exports.gateway = (0, types_js_1.defineModule)({
|
|
|
205941
206122
|
"CBR CloudRun (Express and similar self-managed sub-routes) and multi-path WEB_SCF functions often need true; " +
|
|
205942
206123
|
"STATIC_STORE mapping a trigger path to the site root (e.g. /app → hosting /) is usually false; " +
|
|
205943
206124
|
"keep false for single-entry/root-path handling. route.enablePathTransmission also works (route wins).",
|
|
206125
|
+
"schema.manage.enableSafeDomain": "CORS / legit-domain check (EnableSafeDomain), the console's \"cross-origin settings\". " +
|
|
206126
|
+
"true validates the request origin; false skips the check (common for browser-to-API calls). " +
|
|
206127
|
+
"route.enableSafeDomain also works (route wins).",
|
|
206128
|
+
"schema.manage.pathRewrite": "Path rewriting (PathRewrite), e.g. {prefix:\"/v1\", staticStorePrefix:\"app\"}. " +
|
|
206129
|
+
"prefix replaces the matched path prefix; staticStorePrefix is the target prefix for static hosting. " +
|
|
206130
|
+
"Omit when no rewriting is needed; route.pathRewrite also works (route wins).",
|
|
206131
|
+
"schema.manage.qpsPolicy": "Rate limiting (QPSPolicy), the console's \"frequency limit\". {total: total QPS, perClient:{limitBy:\"ClientIP\"|\"UserID\", limitValue: per-client QPS}}. " +
|
|
206132
|
+
"Omit for no limit; route.qpsPolicy also works (route wins).",
|
|
206133
|
+
"schema.manage.extension": "Route-level extension (Extension): custom request/response headers and cache rules. " +
|
|
206134
|
+
"{headersHandler:{requestHeadersToAdd,requestHeadersToRemove,responseHeadersToAdd,responseHeadersToRemove}," +
|
|
206135
|
+
"cache:{rules:[{description,enable,condition:{target,matchType,values},actions:[{type:\"Cache\"|\"CacheKey\",cache,cacheKey}]}]}}. " +
|
|
206136
|
+
"⚠️ The default domain (*.{region}.app.tcloudbase.com) rejects custom response headers (verified 2026-10-21); a custom domain is required. " +
|
|
206137
|
+
"route.extension also works (route wins).",
|
|
206138
|
+
"schema.manage.extension.header.key": "Header name, e.g. X-Frame-Options",
|
|
206139
|
+
"schema.manage.extension.header.value": "Header value, e.g. SAMEORIGIN",
|
|
206140
|
+
"schema.manage.extension.header.action": "Write strategy (optional): APPEND_IF_EXISTS_OR_ADD appends; ADD_IF_ABSENT only adds when missing; " +
|
|
206141
|
+
"OVERWRITE_IF_EXISTS_OR_ADD overwrites or adds; OVERWRITE_IF_EXISTS only overwrites existing",
|
|
206142
|
+
"schema.manage.extension.cacheCondition": "Cache rule match condition: target=url_path/file_extension/full_uri, matchType=prefix/suffix/contains/exact, values=match value list",
|
|
206143
|
+
"schema.manage.extension.cacheActions": "Cache action list: type=Cache with cache{followOrigin,noCache,cacheTime,maxAgeTime} (mutually exclusive — enable one); " +
|
|
206144
|
+
"type=CacheKey with cacheKey{fullUrlCache,queryStringSwitch,queryStringAction,queryStringValues}",
|
|
206145
|
+
"schema.manage.domainExtension": "Domain-level extension (Extension) applied to the whole domain (all paths): custom headers and cache rules, same shape as extension. " +
|
|
206146
|
+
"Cache rules usually belong here; only effective for createRoute/updateRoute/bindCustomDomain. " +
|
|
206147
|
+
"⚠️ Same as extension: the default domain rejects custom response headers; a custom domain is required.",
|
|
206148
|
+
"schema.manage.protocol": "Domain protocol (Protocol), effective for createRoute/updateRoute/bindCustomDomain only: " +
|
|
206149
|
+
"HTTP / HTTPS / HTTP_AND_HTTPS / HTTP_TO_HTTPS / HTTPS_TO_HTTP. Omit to keep the domain's current setting.",
|
|
205944
206150
|
"schema.manage.route.serviceName": "Upstream instance name: cloud function name / CloudRun service name / static-hosting instance name (commonly staticstore) / LH instance. Takes precedence over the top-level targetName.",
|
|
205945
206151
|
"schema.manage.route.upstreamResourceType": "Same as the top-level upstreamResourceType. When set inside route, it takes precedence over the top level.",
|
|
205946
206152
|
"schema.manage.route.enablePathTransmission": "Same as the top-level enablePathTransmission. When set inside route, it takes precedence over the top level.",
|
|
@@ -205948,6 +206154,10 @@ exports.gateway = (0, types_js_1.defineModule)({
|
|
|
205948
206154
|
"enable=false disables this Domain+Path (access returns GATEWAY_ROUTE_DISABLED); " +
|
|
205949
206155
|
"enable=true re-enables it. updateRoute can express the same semantics with the top-level enable; " +
|
|
205950
206156
|
"the dedicated actions enableRoute/disableRoute also work. route.enable takes precedence over the top-level enable.",
|
|
206157
|
+
"schema.manage.route.enableSafeDomain": "Same as the top-level enableSafeDomain (CORS / legit-domain check). When set inside route, it takes precedence.",
|
|
206158
|
+
"schema.manage.route.pathRewrite": "Same as the top-level pathRewrite. When set inside route, it takes precedence.",
|
|
206159
|
+
"schema.manage.route.qpsPolicy": "Same as the top-level qpsPolicy (rate limiting). When set inside route, it takes precedence.",
|
|
206160
|
+
"schema.manage.route.extension": "Same as the top-level extension (route-level custom headers and cache rules). When set inside route, it takes precedence.",
|
|
205951
206161
|
"schema.manage.route": "Route object (an optional form). Examples: cloud function {upstreamResourceType:\"WEB_SCF\",serviceName:\"fn\",path:\"/api\"}; " +
|
|
205952
206162
|
"CloudRun {upstreamResourceType:\"CBR\",serviceName:\"svc\",path:\"/api\"}; " +
|
|
205953
206163
|
"static hosting {upstreamResourceType:\"STATIC_STORE\",serviceName:\"staticstore\",path:\"/\"}; " +
|
|
@@ -205972,6 +206182,10 @@ exports.gateway = (0, types_js_1.defineModule)({
|
|
|
205972
206182
|
"optional for updateRoute: maps to Routes[].Enable (route.enable also works and wins; " +
|
|
205973
206183
|
"the dedicated actions enableRoute/disableRoute are available too). " +
|
|
205974
206184
|
"Omitting it or passing a non-boolean returns a parameter error for enableService/authSwitch.",
|
|
206185
|
+
"schema.manage.cacheType": "Cache layer (purgeCache only): CDN or EO. When omitted it is matched from the domain access type (EO→EO, CDN→CDN); " +
|
|
206186
|
+
"DIRECT / CUSTOM / NONE domains have no CloudBase-hosted cache and are rejected with an explanation.",
|
|
206187
|
+
"schema.manage.purgeType": "Purge type (purgeCache only, default PURGE_URL): PURGE_URL=by full URL, PURGE_PREFIX=by path prefix, PURGE_HOST=whole domain",
|
|
206188
|
+
"schema.manage.targets": "Purge targets (purgeCache only, required): full https://domain/path URLs for PURGE_URL; prefixes such as /static/ for PURGE_PREFIX; the domain itself for PURGE_HOST",
|
|
205975
206189
|
});
|
|
205976
206190
|
|
|
205977
206191
|
|
|
@@ -226345,42 +226559,68 @@ function registerEnvTools(server) {
|
|
|
226345
226559
|
// API Key mode: exchange for temporary credentials
|
|
226346
226560
|
const apiKeyFromEnv = (0, auth_js_1.getCloudBaseApiKeyFromEnv)();
|
|
226347
226561
|
if (apiKeyFromEnv && process.env.CLOUDBASE_ENV_ID) {
|
|
226562
|
+
// 项目级 key 与账号登录并存时,项目级优先——设备码/网页授权即使走完也不生效,
|
|
226563
|
+
// 所以短路段必须说清「怎么切」,否则用户会以为换号成功
|
|
226564
|
+
const removable = (0, auth_js_1.isEnvCredentialRemovableByLogout)();
|
|
226565
|
+
const apiKeyEnvId = process.env.CLOUDBASE_ENV_ID;
|
|
226566
|
+
const switchHint = "\n" +
|
|
226567
|
+
(removable
|
|
226568
|
+
? (0, index_js_1.t)("env.auth.apiKeySwitchHintRemovable", undefined, outLang)
|
|
226569
|
+
: (0, index_js_1.t)("env.auth.apiKeySwitchHintExternal", {
|
|
226570
|
+
varName: process.env.CLOUDBASE_API_KEY
|
|
226571
|
+
? "CLOUDBASE_API_KEY"
|
|
226572
|
+
: "CLOUDBASE_APIKEY",
|
|
226573
|
+
}, outLang));
|
|
226574
|
+
const logoutNextStep = removable
|
|
226575
|
+
? (0, tool_result_js_1.buildAuthNextStep)("logout", {
|
|
226576
|
+
suggestedArgs: { action: "logout", confirm: "yes" },
|
|
226577
|
+
})
|
|
226578
|
+
: undefined;
|
|
226579
|
+
// peek 发现回填的那份已失效时会把 env 清掉:那就不是「登录失败」,
|
|
226580
|
+
// 而是「旧 key 已经作废」,直接往下走正常登录流程
|
|
226581
|
+
let adoptedKeyDropped = false;
|
|
226348
226582
|
try {
|
|
226349
226583
|
const existingLoginState = await (0, auth_js_1.peekLoginState)();
|
|
226350
226584
|
if (existingLoginState) {
|
|
226351
226585
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
226352
226586
|
ok: true,
|
|
226353
226587
|
code: "AUTH_READY",
|
|
226354
|
-
message: await appendApiKeyCamWarningIfNeeded(existingLoginState, (0, index_js_1.t)("env.auth.apiKeyAutoLogin", undefined, outLang)),
|
|
226588
|
+
message: (await appendApiKeyCamWarningIfNeeded(existingLoginState, (0, index_js_1.t)("env.auth.apiKeyAutoLogin", undefined, outLang))) + switchHint,
|
|
226355
226589
|
auth_mode: "api_key",
|
|
226356
|
-
envId:
|
|
226590
|
+
envId: apiKeyEnvId,
|
|
226591
|
+
...(logoutNextStep ? { next_step: logoutNextStep } : {}),
|
|
226357
226592
|
});
|
|
226358
226593
|
}
|
|
226594
|
+
adoptedKeyDropped = !(0, auth_js_1.getCloudBaseApiKeyFromEnv)();
|
|
226359
226595
|
}
|
|
226360
226596
|
catch (e) {
|
|
226361
226597
|
// peekLoginState threw; log and fall through to diagnostic
|
|
226362
226598
|
(0, logger_js_1.debug)("start_auth: peekLoginState threw", { error: e instanceof Error ? e.message : String(e) });
|
|
226363
226599
|
}
|
|
226364
|
-
|
|
226365
|
-
|
|
226366
|
-
|
|
226367
|
-
|
|
226368
|
-
|
|
226369
|
-
(0, index_js_1.t)("env.auth.
|
|
226370
|
-
|
|
226371
|
-
|
|
226372
|
-
|
|
226373
|
-
|
|
226600
|
+
if (!adoptedKeyDropped) {
|
|
226601
|
+
// API Key exchange failed: return diagnostic details
|
|
226602
|
+
const exchangeRegion = (0, site_map_js_1.resolveApiKeyExchangeRegion)();
|
|
226603
|
+
const endpoint = process.env.CLOUDBASE_API_ENDPOINT ||
|
|
226604
|
+
`https://${apiKeyEnvId}.${exchangeRegion ?? "ap-shanghai"}.tcb-api.tencentcloudapi.com`;
|
|
226605
|
+
const diagMessage = (0, index_js_1.t)("env.auth.apiKeyEnvExchangeFailed", undefined, outLang) +
|
|
226606
|
+
(0, index_js_1.t)("env.auth.apiKeyDiagEnv", {
|
|
226607
|
+
envId: String(apiKeyEnvId),
|
|
226608
|
+
apiKeyPrefix: apiKeyFromEnv.slice(0, 20),
|
|
226609
|
+
site: process.env.TCB_SITE || (0, index_js_1.t)("env.auth.siteUnset", undefined, outLang),
|
|
226610
|
+
gatewayRegion: exchangeRegion ?? (0, index_js_1.t)("env.auth.gatewayRegionDefault", undefined, outLang),
|
|
226611
|
+
endpoint,
|
|
226612
|
+
}, outLang) +
|
|
226613
|
+
switchHint;
|
|
226614
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
226615
|
+
ok: false,
|
|
226616
|
+
code: "API_KEY_AUTH_FAILED",
|
|
226617
|
+
message: diagMessage,
|
|
226618
|
+
auth_mode: "api_key",
|
|
226619
|
+
envId: apiKeyEnvId,
|
|
226374
226620
|
endpoint,
|
|
226375
|
-
|
|
226376
|
-
|
|
226377
|
-
|
|
226378
|
-
code: "API_KEY_AUTH_FAILED",
|
|
226379
|
-
message: diagMessage,
|
|
226380
|
-
auth_mode: "api_key",
|
|
226381
|
-
envId: process.env.CLOUDBASE_ENV_ID,
|
|
226382
|
-
endpoint,
|
|
226383
|
-
});
|
|
226621
|
+
...(logoutNextStep ? { next_step: logoutNextStep } : {}),
|
|
226622
|
+
});
|
|
226623
|
+
}
|
|
226384
226624
|
}
|
|
226385
226625
|
const region = server.cloudBaseOptions?.region || process.env.TCB_REGION;
|
|
226386
226626
|
const auth = toolbox_1.AuthSupervisor.getInstance({});
|
|
@@ -226709,12 +226949,19 @@ function registerEnvTools(server) {
|
|
|
226709
226949
|
});
|
|
226710
226950
|
}
|
|
226711
226951
|
if (action === "logout") {
|
|
226712
|
-
//
|
|
226713
|
-
|
|
226952
|
+
// 用户自己在 shell / 宿主配置里设的 API Key 变量,进程内删不掉,只能提示去源头改;
|
|
226953
|
+
// 按项目保存的那一份(我们回填的,或 login_by_api_key 写下的)能清,走正常登出。
|
|
226954
|
+
if ((0, auth_js_1.getCloudBaseApiKeyFromEnv)() &&
|
|
226955
|
+
process.env.CLOUDBASE_ENV_ID &&
|
|
226956
|
+
!(0, auth_js_1.isEnvCredentialRemovableByLogout)()) {
|
|
226714
226957
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
226715
226958
|
ok: false,
|
|
226716
226959
|
code: "LOGOUT_NOT_ALLOWED",
|
|
226717
|
-
message: (0, index_js_1.t)("env.auth.logoutNotAllowedApiKey",
|
|
226960
|
+
message: (0, index_js_1.t)("env.auth.logoutNotAllowedApiKey", {
|
|
226961
|
+
varName: process.env.CLOUDBASE_API_KEY
|
|
226962
|
+
? "CLOUDBASE_API_KEY"
|
|
226963
|
+
: "CLOUDBASE_APIKEY",
|
|
226964
|
+
}, outLang),
|
|
226718
226965
|
auth_mode: "api_key",
|
|
226719
226966
|
});
|
|
226720
226967
|
}
|
|
@@ -226728,12 +226975,15 @@ function registerEnvTools(server) {
|
|
|
226728
226975
|
}),
|
|
226729
226976
|
});
|
|
226730
226977
|
}
|
|
226731
|
-
await (0, auth_js_1.logout)();
|
|
226978
|
+
const { removed } = await (0, auth_js_1.logout)();
|
|
226732
226979
|
(0, cloudbase_manager_js_1.resetCloudBaseManagerCache)();
|
|
226733
226980
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
226734
226981
|
ok: true,
|
|
226735
226982
|
code: "LOGGED_OUT",
|
|
226736
|
-
|
|
226983
|
+
removed_scopes: removed,
|
|
226984
|
+
message: removed.includes("project")
|
|
226985
|
+
? (0, index_js_1.t)("env.auth.loggedOutProject", undefined, outLang)
|
|
226986
|
+
: (0, index_js_1.t)("env.auth.loggedOut", undefined, outLang),
|
|
226737
226987
|
});
|
|
226738
226988
|
}
|
|
226739
226989
|
if (action === "get_temp_credentials") {
|
|
@@ -229512,8 +229762,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
229512
229762
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
229513
229763
|
};
|
|
229514
229764
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
229515
|
-
exports.CUSTOM_IMAGE_RUNTIME = exports.MASKED_ENV_VALUE = exports.LAYER_SOFT_WARN = exports.DEFAULT_FUNCTION_ALIAS = exports.MANAGE_FUNCTION_ACTIONS = exports.QUERY_FUNCTION_ACTIONS = exports.TRIGGER_CONFIG_EXAMPLES = exports.SUPPORTED_TRIGGER_TYPES = exports.DEFAULT_NODEJS_RUNTIME = exports.SUPPORTED_NODEJS_RUNTIMES = exports.RECOMMENDED_RUNTIMES = exports.DEFAULT_RUNTIME = exports.ALL_SUPPORTED_RUNTIMES = exports.SUPPORTED_RUNTIMES = exports.FUNCTION_UPLOAD_TARGET_NOT_FOUND_ERROR_CODE = void 0;
|
|
229765
|
+
exports.CUSTOM_IMAGE_RUNTIME = exports.MASKED_ENV_VALUE = exports.LAYER_SOFT_WARN = exports.FUNCTION_LOG_SERVICE_NOT_ENABLED_ERROR_CODE = exports.FUNCTION_LOG_QUERY_ERROR_CODE = exports.DEFAULT_FUNCTION_ALIAS = exports.MANAGE_FUNCTION_ACTIONS = exports.QUERY_FUNCTION_ACTIONS = exports.TRIGGER_CONFIG_EXAMPLES = exports.SUPPORTED_TRIGGER_TYPES = exports.DEFAULT_NODEJS_RUNTIME = exports.SUPPORTED_NODEJS_RUNTIMES = exports.RECOMMENDED_RUNTIMES = exports.DEFAULT_RUNTIME = exports.ALL_SUPPORTED_RUNTIMES = exports.SUPPORTED_RUNTIMES = exports.FUNCTION_UPLOAD_TARGET_NOT_FOUND_ERROR_CODE = void 0;
|
|
229516
229766
|
exports.formatRuntimeList = formatRuntimeList;
|
|
229767
|
+
exports.formatClsTime = formatClsTime;
|
|
229768
|
+
exports.buildFunctionLogClsQuery = buildFunctionLogClsQuery;
|
|
229769
|
+
exports.resolveFunctionLogWindow = resolveFunctionLogWindow;
|
|
229770
|
+
exports.parseFunctionLogItem = parseFunctionLogItem;
|
|
229771
|
+
exports.isLogServiceNotEnabledMessage = isLogServiceNotEnabledMessage;
|
|
229517
229772
|
exports.layerNameIncludesEnvId = layerNameIncludesEnvId;
|
|
229518
229773
|
exports.buildCreateLayerNameWarning = buildCreateLayerNameWarning;
|
|
229519
229774
|
exports.maskFunctionDetailEnvValues = maskFunctionDetailEnvValues;
|
|
@@ -229677,6 +229932,125 @@ exports.MANAGE_FUNCTION_ACTIONS = [
|
|
|
229677
229932
|
];
|
|
229678
229933
|
/** Default SCF traffic alias used by CloudBase CLI `fn get-route` / `fn config-route`. */
|
|
229679
229934
|
exports.DEFAULT_FUNCTION_ALIAS = "$DEFAULT";
|
|
229935
|
+
/**
|
|
229936
|
+
* 云函数日志的 CLS 检索底座。
|
|
229937
|
+
*
|
|
229938
|
+
* 底层 `GetFunctionLogs` / `GetFunctionLogDetail` 已下线(`@cloudbase/manager-node` 5.8.8 起
|
|
229939
|
+
* `getFunctionLogsV2` / `getFunctionLogDetail` 直接抛错),云函数日志只能从 CLS 取。CLS 里每条
|
|
229940
|
+
* 云函数日志是按请求聚合的 JSON,`function_name` / `request_id` / `qualifier` / `src` 都是扁平
|
|
229941
|
+
* 字段,可以直接做检索条件,不需要再扫全量日志。
|
|
229942
|
+
*/
|
|
229943
|
+
const FUNCTION_LOG_CLS_SOURCE = "(src:app OR src:system)";
|
|
229944
|
+
/** SearchClsLog 单次返回上限。 */
|
|
229945
|
+
const FUNCTION_LOG_MAX_LIMIT = 100;
|
|
229946
|
+
const FUNCTION_LOG_DEFAULT_LIMIT = 20;
|
|
229947
|
+
const FUNCTION_LOG_WINDOW_MS = 24 * 60 * 60 * 1000;
|
|
229948
|
+
/**
|
|
229949
|
+
* CLS 的时间入参固定按北京时间理解(与返回的 `Timestamp` 一致),
|
|
229950
|
+
* 托管形态的服务进程可能是 UTC,所以这里显式加偏移,不依赖进程时区。
|
|
229951
|
+
*/
|
|
229952
|
+
const CLS_TIME_OFFSET_MS = 8 * 60 * 60 * 1000;
|
|
229953
|
+
/** CLS 检索语法里 `key:"value"` 的值需要转义反斜杠与双引号。 */
|
|
229954
|
+
function escapeClsValue(value) {
|
|
229955
|
+
return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
229956
|
+
}
|
|
229957
|
+
/** CLS 入参/展示用的时间格式:YYYY-MM-DD HH:mm:ss(北京时间)。 */
|
|
229958
|
+
function formatClsTime(time) {
|
|
229959
|
+
return new Date(time + CLS_TIME_OFFSET_MS).toISOString().slice(0, 19).replace("T", " ");
|
|
229960
|
+
}
|
|
229961
|
+
function buildFunctionLogClsQuery(input) {
|
|
229962
|
+
const clauses = [FUNCTION_LOG_CLS_SOURCE];
|
|
229963
|
+
if (input.functionName) {
|
|
229964
|
+
clauses.push(`function_name:"${escapeClsValue(input.functionName)}"`);
|
|
229965
|
+
}
|
|
229966
|
+
if (input.qualifier) {
|
|
229967
|
+
clauses.push(`qualifier:"${escapeClsValue(input.qualifier)}"`);
|
|
229968
|
+
}
|
|
229969
|
+
if (input.requestId) {
|
|
229970
|
+
clauses.push(`request_id:"${escapeClsValue(input.requestId)}"`);
|
|
229971
|
+
}
|
|
229972
|
+
return clauses.join(" AND ");
|
|
229973
|
+
}
|
|
229974
|
+
/** 只传一端时把窗口收敛到 24 小时以内,CLS 与旧接口都限制单次跨度。 */
|
|
229975
|
+
function resolveFunctionLogWindow(startTime, endTime, now = Date.now()) {
|
|
229976
|
+
if (startTime && endTime) {
|
|
229977
|
+
return { StartTime: startTime, EndTime: endTime };
|
|
229978
|
+
}
|
|
229979
|
+
if (startTime) {
|
|
229980
|
+
const start = new Date(startTime).getTime();
|
|
229981
|
+
// 单一 startTime 时至少给出一分钟窗口:起止相同(或 start 在未来)时 CLS 会直接判非法。
|
|
229982
|
+
const end = Number.isFinite(start)
|
|
229983
|
+
? Math.max(start + 60_000, Math.min(now, start + FUNCTION_LOG_WINDOW_MS))
|
|
229984
|
+
: now;
|
|
229985
|
+
return { StartTime: startTime, EndTime: formatClsTime(end) };
|
|
229986
|
+
}
|
|
229987
|
+
if (endTime) {
|
|
229988
|
+
const end = new Date(endTime).getTime();
|
|
229989
|
+
const start = Number.isFinite(end) ? end - FUNCTION_LOG_WINDOW_MS : now - FUNCTION_LOG_WINDOW_MS;
|
|
229990
|
+
return { StartTime: formatClsTime(start), EndTime: endTime };
|
|
229991
|
+
}
|
|
229992
|
+
return { StartTime: formatClsTime(now - FUNCTION_LOG_WINDOW_MS), EndTime: formatClsTime(now) };
|
|
229993
|
+
}
|
|
229994
|
+
/**
|
|
229995
|
+
* 把 CLS 的日志条目还原成调用方关心的字段。
|
|
229996
|
+
*
|
|
229997
|
+
* 解析失败时(例如用户自己打的纯文本日志)保留原文放进 `log`,不让一条脏数据毁掉整页结果。
|
|
229998
|
+
*/
|
|
229999
|
+
function parseFunctionLogItem(item) {
|
|
230000
|
+
const content = typeof item.Content === "string" ? item.Content : "";
|
|
230001
|
+
let parsed = null;
|
|
230002
|
+
try {
|
|
230003
|
+
const value = JSON.parse(content);
|
|
230004
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
230005
|
+
parsed = value;
|
|
230006
|
+
}
|
|
230007
|
+
}
|
|
230008
|
+
catch {
|
|
230009
|
+
parsed = null;
|
|
230010
|
+
}
|
|
230011
|
+
const timestamp = item.Timestamp ?? "";
|
|
230012
|
+
if (!parsed) {
|
|
230013
|
+
return {
|
|
230014
|
+
requestId: "",
|
|
230015
|
+
functionName: "",
|
|
230016
|
+
qualifier: "",
|
|
230017
|
+
source: "",
|
|
230018
|
+
log: content,
|
|
230019
|
+
statusCode: "",
|
|
230020
|
+
retCode: "",
|
|
230021
|
+
durationMs: null,
|
|
230022
|
+
memoryMb: null,
|
|
230023
|
+
memUsageBytes: null,
|
|
230024
|
+
requestSource: "",
|
|
230025
|
+
timestamp,
|
|
230026
|
+
};
|
|
230027
|
+
}
|
|
230028
|
+
const str = (value) => value === undefined || value === null ? "" : String(value);
|
|
230029
|
+
const num = (value) => {
|
|
230030
|
+
const parsedNumber = Number(value);
|
|
230031
|
+
return Number.isFinite(parsedNumber) ? parsedNumber : null;
|
|
230032
|
+
};
|
|
230033
|
+
return {
|
|
230034
|
+
requestId: str(parsed.request_id),
|
|
230035
|
+
functionName: str(parsed.function_name),
|
|
230036
|
+
qualifier: str(parsed.qualifier || parsed.alias),
|
|
230037
|
+
source: str(parsed.src),
|
|
230038
|
+
log: str(parsed.log || parsed.tcb_log),
|
|
230039
|
+
statusCode: str(parsed.status_code),
|
|
230040
|
+
retCode: str(parsed.ret_code),
|
|
230041
|
+
durationMs: num(parsed.duration),
|
|
230042
|
+
memoryMb: num(parsed.memory),
|
|
230043
|
+
memUsageBytes: num(parsed.mem_usage),
|
|
230044
|
+
requestSource: str(parsed.request_source),
|
|
230045
|
+
timestamp,
|
|
230046
|
+
};
|
|
230047
|
+
}
|
|
230048
|
+
exports.FUNCTION_LOG_QUERY_ERROR_CODE = "FUNCTION_LOG_QUERY_FAILED";
|
|
230049
|
+
exports.FUNCTION_LOG_SERVICE_NOT_ENABLED_ERROR_CODE = "LOG_SERVICE_NOT_ENABLED";
|
|
230050
|
+
/** 未开通日志服务时 CLS 报的是 topic 不存在,按这个特征把它翻译成可执行的下一步。 */
|
|
230051
|
+
function isLogServiceNotEnabledMessage(message) {
|
|
230052
|
+
return /TopicNotExist|TopicIsolated|topic[\s\S]{0,20}not\s*exist|日志服务未开通/i.test(message);
|
|
230053
|
+
}
|
|
229680
230054
|
/** Layer soft-warn copy — account-scoped SCF LayerName guidance (no hard fail). */
|
|
229681
230055
|
exports.LAYER_SOFT_WARN = {
|
|
229682
230056
|
createNameFormat: (envId) => (0, index_js_1.t)("functions.layerWarn.createNameFormat", { envId }),
|
|
@@ -230144,6 +230518,81 @@ function registerFunctionTools(server) {
|
|
|
230144
230518
|
}
|
|
230145
230519
|
}
|
|
230146
230520
|
};
|
|
230521
|
+
/**
|
|
230522
|
+
* 云函数日志统一走 CLS。查询失败时分两类给出可执行的下一步:
|
|
230523
|
+
* 日志服务没开通 ⇒ 引导开通;其它失败 ⇒ 引导到 queryLogs 用同一条检索语句重试。
|
|
230524
|
+
*/
|
|
230525
|
+
const throwLogQueryError = (error, scope) => {
|
|
230526
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
230527
|
+
if (isLogServiceNotEnabledMessage(message)) {
|
|
230528
|
+
(0, tool_result_js_1.throwToolPayloadError)({
|
|
230529
|
+
success: false,
|
|
230530
|
+
errorCode: exports.FUNCTION_LOG_SERVICE_NOT_ENABLED_ERROR_CODE,
|
|
230531
|
+
data: { ...scope },
|
|
230532
|
+
message: (0, index_js_1.t)("functions.logs.serviceNotEnabled"),
|
|
230533
|
+
nextActions: [
|
|
230534
|
+
{
|
|
230535
|
+
tool: "manageLogs",
|
|
230536
|
+
action: "createLogService",
|
|
230537
|
+
reason: (0, index_js_1.t)("functions.reason.createLogService"),
|
|
230538
|
+
suggested_args: { action: "createLogService", confirm: true },
|
|
230539
|
+
},
|
|
230540
|
+
],
|
|
230541
|
+
});
|
|
230542
|
+
}
|
|
230543
|
+
(0, tool_result_js_1.throwToolPayloadError)({
|
|
230544
|
+
success: false,
|
|
230545
|
+
errorCode: exports.FUNCTION_LOG_QUERY_ERROR_CODE,
|
|
230546
|
+
data: { ...scope, rawError: message },
|
|
230547
|
+
message: (0, index_js_1.t)("functions.logs.queryFailed", { message }),
|
|
230548
|
+
nextActions: [
|
|
230549
|
+
{
|
|
230550
|
+
tool: "queryLogs",
|
|
230551
|
+
action: "searchLogs",
|
|
230552
|
+
reason: (0, index_js_1.t)("functions.reason.searchClsFallback"),
|
|
230553
|
+
suggested_args: {
|
|
230554
|
+
action: "searchLogs",
|
|
230555
|
+
service: "tcb",
|
|
230556
|
+
queryString: buildFunctionLogClsQuery({
|
|
230557
|
+
functionName: scope.functionName,
|
|
230558
|
+
requestId: scope.requestId,
|
|
230559
|
+
}),
|
|
230560
|
+
startTime: scope.window.StartTime,
|
|
230561
|
+
endTime: scope.window.EndTime,
|
|
230562
|
+
},
|
|
230563
|
+
},
|
|
230564
|
+
],
|
|
230565
|
+
});
|
|
230566
|
+
};
|
|
230567
|
+
/**
|
|
230568
|
+
* 空结果不等于「函数没被调用」:日志服务没开通时 CLS 同样返回空。
|
|
230569
|
+
* 这里只在真的查到空结果时多做一次开销很小的探活,避免把「没开通」误报成「没日志」。
|
|
230570
|
+
*/
|
|
230571
|
+
const assertLogServiceEnabled = async (logService) => {
|
|
230572
|
+
try {
|
|
230573
|
+
if (await logService.checkLogServiceEnabled()) {
|
|
230574
|
+
return;
|
|
230575
|
+
}
|
|
230576
|
+
}
|
|
230577
|
+
catch {
|
|
230578
|
+
// 探活失败不制造新的错误源:保持「该时间段没有日志」的原始结论。
|
|
230579
|
+
return;
|
|
230580
|
+
}
|
|
230581
|
+
(0, tool_result_js_1.throwToolPayloadError)({
|
|
230582
|
+
success: false,
|
|
230583
|
+
errorCode: exports.FUNCTION_LOG_SERVICE_NOT_ENABLED_ERROR_CODE,
|
|
230584
|
+
data: { enabled: false },
|
|
230585
|
+
message: (0, index_js_1.t)("functions.logs.serviceNotEnabled"),
|
|
230586
|
+
nextActions: [
|
|
230587
|
+
{
|
|
230588
|
+
tool: "manageLogs",
|
|
230589
|
+
action: "createLogService",
|
|
230590
|
+
reason: (0, index_js_1.t)("functions.reason.createLogService"),
|
|
230591
|
+
suggested_args: { action: "createLogService", confirm: true },
|
|
230592
|
+
},
|
|
230593
|
+
],
|
|
230594
|
+
});
|
|
230595
|
+
};
|
|
230147
230596
|
const normalizeManageLayers = (layers) => normalizeFunctionLayers((layers ?? []).map((layer) => ({
|
|
230148
230597
|
LayerName: layer.layerName ?? layer.LayerName,
|
|
230149
230598
|
LayerVersion: layer.layerVersion ?? layer.LayerVersion,
|
|
@@ -230265,39 +230714,86 @@ function registerFunctionTools(server) {
|
|
|
230265
230714
|
}
|
|
230266
230715
|
validateLogRange(input.startTime, input.endTime, input.offset, input.limit);
|
|
230267
230716
|
const cloudbase = await getManager();
|
|
230268
|
-
|
|
230717
|
+
const window = resolveFunctionLogWindow(input.startTime, input.endTime);
|
|
230718
|
+
const limit = Math.min(Math.max(input.limit ?? FUNCTION_LOG_DEFAULT_LIMIT, 1), FUNCTION_LOG_MAX_LIMIT);
|
|
230719
|
+
const offset = Math.max(input.offset ?? 0, 0);
|
|
230720
|
+
// SearchClsLog 单次最多 100 条且没有 offset 入参:不带游标时多取 offset+limit 再本地
|
|
230721
|
+
// 切片,带游标(context)时游标本身已经记录了偏移,直接返回当页。
|
|
230722
|
+
const fetchLimit = Math.min(offset + limit, FUNCTION_LOG_MAX_LIMIT);
|
|
230723
|
+
const queryString = buildFunctionLogClsQuery({
|
|
230724
|
+
functionName: input.functionName,
|
|
230725
|
+
requestId: input.requestId,
|
|
230726
|
+
qualifier: input.qualifier,
|
|
230727
|
+
});
|
|
230728
|
+
let logResults = {};
|
|
230269
230729
|
try {
|
|
230270
|
-
result = await cloudbase.
|
|
230271
|
-
|
|
230272
|
-
|
|
230273
|
-
|
|
230274
|
-
|
|
230275
|
-
|
|
230276
|
-
|
|
230277
|
-
|
|
230730
|
+
const result = await cloudbase.log.searchClsLog({
|
|
230731
|
+
queryString,
|
|
230732
|
+
StartTime: window.StartTime,
|
|
230733
|
+
EndTime: window.EndTime,
|
|
230734
|
+
Limit: fetchLimit,
|
|
230735
|
+
Context: input.context,
|
|
230736
|
+
Sort: "desc",
|
|
230737
|
+
service: "tcb",
|
|
230278
230738
|
});
|
|
230739
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
230740
|
+
logResults = result.LogResults ?? {};
|
|
230279
230741
|
}
|
|
230280
230742
|
catch (error) {
|
|
230281
|
-
|
|
230282
|
-
if (/invalid parameter/i.test(errMsg)) {
|
|
230283
|
-
throw new Error(`${errMsg}\n\n${(0, index_js_1.t)("functions.logsInvalidParamTips")}`);
|
|
230284
|
-
}
|
|
230285
|
-
throw error;
|
|
230743
|
+
throwLogQueryError(error, { functionName: input.functionName, window });
|
|
230286
230744
|
}
|
|
230287
|
-
|
|
230745
|
+
const entries = (logResults.Results ?? []).map(parseFunctionLogItem);
|
|
230746
|
+
const logs = input.context ? entries : entries.slice(offset, offset + limit);
|
|
230747
|
+
if (logs.length === 0) {
|
|
230748
|
+
await assertLogServiceEnabled(cloudbase.log);
|
|
230749
|
+
}
|
|
230750
|
+
const hasMore = !logResults.ListOver && Boolean(logResults.Context);
|
|
230288
230751
|
return buildEnvelope({
|
|
230289
230752
|
action: input.action,
|
|
230290
230753
|
functionName: input.functionName,
|
|
230291
|
-
|
|
230292
|
-
|
|
230293
|
-
|
|
230294
|
-
|
|
230295
|
-
|
|
230296
|
-
|
|
230297
|
-
|
|
230298
|
-
|
|
230299
|
-
|
|
230300
|
-
|
|
230754
|
+
service: "tcb",
|
|
230755
|
+
queryString,
|
|
230756
|
+
startTime: window.StartTime,
|
|
230757
|
+
endTime: window.EndTime,
|
|
230758
|
+
logs,
|
|
230759
|
+
count: logs.length,
|
|
230760
|
+
context: logResults.Context ?? null,
|
|
230761
|
+
hasMore,
|
|
230762
|
+
}, logs.length > 0
|
|
230763
|
+
? (0, index_js_1.t)("functions.gotFunctionLogs", { fnName: input.functionName })
|
|
230764
|
+
: (0, index_js_1.t)("functions.logs.emptyByFunction", {
|
|
230765
|
+
fnName: input.functionName,
|
|
230766
|
+
start: window.StartTime,
|
|
230767
|
+
end: window.EndTime,
|
|
230768
|
+
}), hasMore
|
|
230769
|
+
? [
|
|
230770
|
+
{
|
|
230771
|
+
tool: "queryFunctions",
|
|
230772
|
+
action: "listFunctionLogs",
|
|
230773
|
+
reason: (0, index_js_1.t)("functions.reason.nextLogPage"),
|
|
230774
|
+
suggested_args: {
|
|
230775
|
+
action: "listFunctionLogs",
|
|
230776
|
+
functionName: input.functionName,
|
|
230777
|
+
context: logResults.Context,
|
|
230778
|
+
startTime: window.StartTime,
|
|
230779
|
+
endTime: window.EndTime,
|
|
230780
|
+
limit,
|
|
230781
|
+
},
|
|
230782
|
+
},
|
|
230783
|
+
]
|
|
230784
|
+
: [
|
|
230785
|
+
{
|
|
230786
|
+
tool: "queryFunctions",
|
|
230787
|
+
action: "getFunctionLogDetail",
|
|
230788
|
+
reason: (0, index_js_1.t)("functions.reason.logDetail"),
|
|
230789
|
+
suggested_args: {
|
|
230790
|
+
action: "getFunctionLogDetail",
|
|
230791
|
+
requestId: logs[0]?.requestId || "<日志里的 requestId>",
|
|
230792
|
+
startTime: window.StartTime,
|
|
230793
|
+
endTime: window.EndTime,
|
|
230794
|
+
},
|
|
230795
|
+
},
|
|
230796
|
+
]);
|
|
230301
230797
|
}
|
|
230302
230798
|
case "getFunctionLogDetail": {
|
|
230303
230799
|
if (!input.requestId) {
|
|
@@ -230305,27 +230801,67 @@ function registerFunctionTools(server) {
|
|
|
230305
230801
|
}
|
|
230306
230802
|
validateLogRange(input.startTime, input.endTime);
|
|
230307
230803
|
const cloudbase = await getManager();
|
|
230308
|
-
|
|
230804
|
+
const window = resolveFunctionLogWindow(input.startTime, input.endTime);
|
|
230805
|
+
const queryString = buildFunctionLogClsQuery({
|
|
230806
|
+
functionName: input.functionName,
|
|
230807
|
+
requestId: input.requestId,
|
|
230808
|
+
qualifier: input.qualifier,
|
|
230809
|
+
});
|
|
230810
|
+
let logResults = {};
|
|
230309
230811
|
try {
|
|
230310
|
-
result = await cloudbase.
|
|
230311
|
-
|
|
230312
|
-
|
|
230313
|
-
|
|
230812
|
+
const result = await cloudbase.log.searchClsLog({
|
|
230813
|
+
queryString,
|
|
230814
|
+
StartTime: window.StartTime,
|
|
230815
|
+
EndTime: window.EndTime,
|
|
230816
|
+
Limit: FUNCTION_LOG_MAX_LIMIT,
|
|
230817
|
+
Sort: "asc",
|
|
230818
|
+
service: "tcb",
|
|
230314
230819
|
});
|
|
230820
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
230821
|
+
logResults = result.LogResults ?? {};
|
|
230315
230822
|
}
|
|
230316
230823
|
catch (error) {
|
|
230317
|
-
|
|
230318
|
-
|
|
230319
|
-
|
|
230320
|
-
|
|
230321
|
-
|
|
230824
|
+
throwLogQueryError(error, { requestId: input.requestId, window });
|
|
230825
|
+
}
|
|
230826
|
+
// 一次调用在 CLS 里是多条记录(START / 业务日志 / REPORT),按时间升序拼回完整过程。
|
|
230827
|
+
const entries = (logResults.Results ?? []).map(parseFunctionLogItem);
|
|
230828
|
+
if (entries.length === 0) {
|
|
230829
|
+
await assertLogServiceEnabled(cloudbase.log);
|
|
230830
|
+
return buildEnvelope({
|
|
230831
|
+
action: input.action,
|
|
230832
|
+
requestId: input.requestId,
|
|
230833
|
+
queryString,
|
|
230834
|
+
startTime: window.StartTime,
|
|
230835
|
+
endTime: window.EndTime,
|
|
230836
|
+
logs: [],
|
|
230837
|
+
count: 0,
|
|
230838
|
+
}, (0, index_js_1.t)("functions.logs.emptyByRequest", {
|
|
230839
|
+
requestId: input.requestId,
|
|
230840
|
+
start: window.StartTime,
|
|
230841
|
+
end: window.EndTime,
|
|
230842
|
+
}), [
|
|
230843
|
+
{
|
|
230844
|
+
tool: "queryFunctions",
|
|
230845
|
+
action: "listFunctionLogs",
|
|
230846
|
+
reason: (0, index_js_1.t)("functions.reason.widenLogRange"),
|
|
230847
|
+
suggested_args: {
|
|
230848
|
+
action: "listFunctionLogs",
|
|
230849
|
+
functionName: input.functionName || "<函数名>",
|
|
230850
|
+
startTime: window.StartTime,
|
|
230851
|
+
endTime: window.EndTime,
|
|
230852
|
+
},
|
|
230853
|
+
},
|
|
230854
|
+
]);
|
|
230322
230855
|
}
|
|
230323
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
230324
230856
|
return buildEnvelope({
|
|
230325
230857
|
action: input.action,
|
|
230326
230858
|
requestId: input.requestId,
|
|
230327
|
-
|
|
230328
|
-
|
|
230859
|
+
functionName: entries[0]?.functionName || input.functionName || null,
|
|
230860
|
+
queryString,
|
|
230861
|
+
startTime: window.StartTime,
|
|
230862
|
+
endTime: window.EndTime,
|
|
230863
|
+
logs: entries,
|
|
230864
|
+
count: entries.length,
|
|
230329
230865
|
}, (0, index_js_1.t)("functions.gotLogDetail", { requestId: input.requestId }));
|
|
230330
230866
|
}
|
|
230331
230867
|
case "listFunctionLayers": {
|
|
@@ -231701,6 +232237,7 @@ function registerFunctionTools(server) {
|
|
|
231701
232237
|
.optional()
|
|
231702
232238
|
.describe("functions.schema.query.requestId"),
|
|
231703
232239
|
qualifier: zod_1.z.string().optional().describe("functions.schema.query.qualifier"),
|
|
232240
|
+
context: zod_1.z.string().optional().describe("functions.schema.query.context"),
|
|
231704
232241
|
runtime: zod_1.z.string().optional().describe("functions.schema.query.runtime"),
|
|
231705
232242
|
searchKey: zod_1.z.string().optional().describe("functions.schema.query.searchKey"),
|
|
231706
232243
|
layerName: zod_1.z
|
|
@@ -231827,6 +232364,7 @@ const QUERY_GATEWAY_ACTIONS = [
|
|
|
231827
232364
|
"getRoute",
|
|
231828
232365
|
"listCustomDomains",
|
|
231829
232366
|
"getPrivilege",
|
|
232367
|
+
"cachePurgeTask",
|
|
231830
232368
|
];
|
|
231831
232369
|
const MANAGE_GATEWAY_ACTIONS = [
|
|
231832
232370
|
"createRoute",
|
|
@@ -231838,6 +232376,7 @@ const MANAGE_GATEWAY_ACTIONS = [
|
|
|
231838
232376
|
"deleteCustomDomain",
|
|
231839
232377
|
"enableService",
|
|
231840
232378
|
"authSwitch",
|
|
232379
|
+
"purgeCache",
|
|
231841
232380
|
];
|
|
231842
232381
|
/** DomainType of the environment default HTTP service (gateway) domain. */
|
|
231843
232382
|
const HTTP_SERVICE_DOMAIN_TYPE = "HTTPSERVICE";
|
|
@@ -231847,6 +232386,24 @@ const UPSTREAM_RESOURCE_TYPES = [
|
|
|
231847
232386
|
"CBR",
|
|
231848
232387
|
"STATIC_STORE",
|
|
231849
232388
|
"LH",
|
|
232389
|
+
"STORAGE",
|
|
232390
|
+
];
|
|
232391
|
+
/** Domain-level protocol accepted by HTTPServiceDomainParam. */
|
|
232392
|
+
const DOMAIN_PROTOCOLS = [
|
|
232393
|
+
"HTTP",
|
|
232394
|
+
"HTTPS",
|
|
232395
|
+
"HTTP_AND_HTTPS",
|
|
232396
|
+
"HTTP_TO_HTTPS",
|
|
232397
|
+
"HTTPS_TO_HTTP",
|
|
232398
|
+
];
|
|
232399
|
+
/** Cache layer that owns the purged objects (CDN vs EdgeOne). */
|
|
232400
|
+
const CACHE_TYPES = ["CDN", "EO"];
|
|
232401
|
+
const PURGE_TYPES = ["PURGE_URL", "PURGE_PREFIX", "PURGE_HOST"];
|
|
232402
|
+
const HEADER_ADD_ACTIONS = [
|
|
232403
|
+
"APPEND_IF_EXISTS_OR_ADD",
|
|
232404
|
+
"ADD_IF_ABSENT",
|
|
232405
|
+
"OVERWRITE_IF_EXISTS_OR_ADD",
|
|
232406
|
+
"OVERWRITE_IF_EXISTS",
|
|
231850
232407
|
];
|
|
231851
232408
|
function normalizeAccessPath(path) {
|
|
231852
232409
|
if (!path) {
|
|
@@ -231854,6 +232411,225 @@ function normalizeAccessPath(path) {
|
|
|
231854
232411
|
}
|
|
231855
232412
|
return path.startsWith("/") ? path : `/${path}`;
|
|
231856
232413
|
}
|
|
232414
|
+
// ---------------------------------------------------------------------------
|
|
232415
|
+
// Route/Domain extension schemas (aligned with manager-node HTTPServiceRouteParam)
|
|
232416
|
+
// ---------------------------------------------------------------------------
|
|
232417
|
+
const headerToAddSchema = zod_1.z.object({
|
|
232418
|
+
key: zod_1.z.string().describe("gateway.schema.manage.extension.header.key"),
|
|
232419
|
+
value: zod_1.z.string().describe("gateway.schema.manage.extension.header.value"),
|
|
232420
|
+
action: zod_1.z
|
|
232421
|
+
.enum(HEADER_ADD_ACTIONS)
|
|
232422
|
+
.optional()
|
|
232423
|
+
.describe("gateway.schema.manage.extension.header.action"),
|
|
232424
|
+
});
|
|
232425
|
+
const headersHandlerSchema = zod_1.z.object({
|
|
232426
|
+
requestHeadersToAdd: zod_1.z.array(headerToAddSchema).optional(),
|
|
232427
|
+
requestHeadersToRemove: zod_1.z.array(zod_1.z.string()).optional(),
|
|
232428
|
+
responseHeadersToAdd: zod_1.z.array(headerToAddSchema).optional(),
|
|
232429
|
+
responseHeadersToRemove: zod_1.z.array(zod_1.z.string()).optional(),
|
|
232430
|
+
});
|
|
232431
|
+
const cacheRuleSchema = zod_1.z.object({
|
|
232432
|
+
description: zod_1.z.string().optional(),
|
|
232433
|
+
enable: zod_1.z.boolean().optional(),
|
|
232434
|
+
condition: zod_1.z
|
|
232435
|
+
.object({
|
|
232436
|
+
target: zod_1.z.enum(["url_path", "file_extension", "full_uri"]).optional(),
|
|
232437
|
+
matchType: zod_1.z.enum(["prefix", "suffix", "contains", "exact"]).optional(),
|
|
232438
|
+
values: zod_1.z.array(zod_1.z.string()).optional(),
|
|
232439
|
+
})
|
|
232440
|
+
.describe("gateway.schema.manage.extension.cacheCondition"),
|
|
232441
|
+
actions: zod_1.z
|
|
232442
|
+
.array(zod_1.z.object({
|
|
232443
|
+
type: zod_1.z.enum(["Cache", "CacheKey"]).optional(),
|
|
232444
|
+
cache: zod_1.z
|
|
232445
|
+
.object({
|
|
232446
|
+
followOrigin: zod_1.z.boolean().optional(),
|
|
232447
|
+
noCache: zod_1.z.boolean().optional(),
|
|
232448
|
+
cacheTime: zod_1.z.number().int().min(0).optional(),
|
|
232449
|
+
maxAgeTime: zod_1.z.number().int().min(0).optional(),
|
|
232450
|
+
})
|
|
232451
|
+
.optional(),
|
|
232452
|
+
cacheKey: zod_1.z
|
|
232453
|
+
.object({
|
|
232454
|
+
fullUrlCache: zod_1.z.enum(["on", "off"]).optional(),
|
|
232455
|
+
queryStringSwitch: zod_1.z.enum(["on", "off"]).optional(),
|
|
232456
|
+
queryStringAction: zod_1.z.enum(["includeCustom", "excludeCustom"]).optional(),
|
|
232457
|
+
queryStringValues: zod_1.z.array(zod_1.z.string()).optional(),
|
|
232458
|
+
})
|
|
232459
|
+
.optional(),
|
|
232460
|
+
}))
|
|
232461
|
+
.describe("gateway.schema.manage.extension.cacheActions"),
|
|
232462
|
+
});
|
|
232463
|
+
const extensionSchema = zod_1.z.object({
|
|
232464
|
+
headersHandler: headersHandlerSchema.optional(),
|
|
232465
|
+
cache: zod_1.z.object({ rules: zod_1.z.array(cacheRuleSchema).optional() }).optional(),
|
|
232466
|
+
});
|
|
232467
|
+
const pathRewriteSchema = zod_1.z.object({
|
|
232468
|
+
prefix: zod_1.z.string().optional(),
|
|
232469
|
+
staticStorePrefix: zod_1.z.string().optional(),
|
|
232470
|
+
});
|
|
232471
|
+
const qpsPolicySchema = zod_1.z.object({
|
|
232472
|
+
total: zod_1.z.number().int().min(0).optional(),
|
|
232473
|
+
perClient: zod_1.z
|
|
232474
|
+
.object({
|
|
232475
|
+
limitBy: zod_1.z.enum(["ClientIP", "UserID"]).optional(),
|
|
232476
|
+
limitValue: zod_1.z.number().int().min(1).optional(),
|
|
232477
|
+
})
|
|
232478
|
+
.optional(),
|
|
232479
|
+
});
|
|
232480
|
+
function toHeadersHandler(input) {
|
|
232481
|
+
if (!input) {
|
|
232482
|
+
return undefined;
|
|
232483
|
+
}
|
|
232484
|
+
const output = {};
|
|
232485
|
+
const toHeader = (item) => item.action
|
|
232486
|
+
? { Key: item.key, Value: item.value, Action: item.action }
|
|
232487
|
+
: { Key: item.key, Value: item.value };
|
|
232488
|
+
if (input.requestHeadersToAdd?.length) {
|
|
232489
|
+
output.RequestHeadersToAdd = input.requestHeadersToAdd.map(toHeader);
|
|
232490
|
+
}
|
|
232491
|
+
if (input.requestHeadersToRemove?.length) {
|
|
232492
|
+
output.RequestHeadersToRemove = input.requestHeadersToRemove;
|
|
232493
|
+
}
|
|
232494
|
+
if (input.responseHeadersToAdd?.length) {
|
|
232495
|
+
output.ResponseHeadersToAdd = input.responseHeadersToAdd.map(toHeader);
|
|
232496
|
+
}
|
|
232497
|
+
if (input.responseHeadersToRemove?.length) {
|
|
232498
|
+
output.ResponseHeadersToRemove = input.responseHeadersToRemove;
|
|
232499
|
+
}
|
|
232500
|
+
return Object.keys(output).length ? output : undefined;
|
|
232501
|
+
}
|
|
232502
|
+
function toCacheSet(input) {
|
|
232503
|
+
if (!input?.rules?.length) {
|
|
232504
|
+
return undefined;
|
|
232505
|
+
}
|
|
232506
|
+
return {
|
|
232507
|
+
Rules: input.rules.map((rule) => ({
|
|
232508
|
+
...(rule.description !== undefined ? { Description: rule.description } : {}),
|
|
232509
|
+
...(rule.enable !== undefined ? { Enable: rule.enable } : {}),
|
|
232510
|
+
Condition: {
|
|
232511
|
+
...(rule.condition?.target ? { Target: rule.condition.target } : {}),
|
|
232512
|
+
...(rule.condition?.matchType ? { MatchType: rule.condition.matchType } : {}),
|
|
232513
|
+
...(rule.condition?.values ? { Values: rule.condition.values } : {}),
|
|
232514
|
+
},
|
|
232515
|
+
Actions: (rule.actions ?? []).map((action) => ({
|
|
232516
|
+
...(action.type ? { Type: action.type } : {}),
|
|
232517
|
+
...(action.cache
|
|
232518
|
+
? {
|
|
232519
|
+
Cache: {
|
|
232520
|
+
...(action.cache.followOrigin !== undefined
|
|
232521
|
+
? { FollowOrigin: action.cache.followOrigin }
|
|
232522
|
+
: {}),
|
|
232523
|
+
...(action.cache.noCache !== undefined
|
|
232524
|
+
? { NoCache: action.cache.noCache }
|
|
232525
|
+
: {}),
|
|
232526
|
+
...(action.cache.cacheTime !== undefined
|
|
232527
|
+
? { CacheTime: action.cache.cacheTime }
|
|
232528
|
+
: {}),
|
|
232529
|
+
...(action.cache.maxAgeTime !== undefined
|
|
232530
|
+
? { MaxAgeTime: action.cache.maxAgeTime }
|
|
232531
|
+
: {}),
|
|
232532
|
+
},
|
|
232533
|
+
}
|
|
232534
|
+
: {}),
|
|
232535
|
+
...(action.cacheKey
|
|
232536
|
+
? {
|
|
232537
|
+
CacheKey: {
|
|
232538
|
+
...(action.cacheKey.fullUrlCache
|
|
232539
|
+
? { FullURLCache: action.cacheKey.fullUrlCache }
|
|
232540
|
+
: {}),
|
|
232541
|
+
...(action.cacheKey.queryStringSwitch
|
|
232542
|
+
? { QueryStringSwitch: action.cacheKey.queryStringSwitch }
|
|
232543
|
+
: {}),
|
|
232544
|
+
...(action.cacheKey.queryStringAction
|
|
232545
|
+
? { QueryStringAction: action.cacheKey.queryStringAction }
|
|
232546
|
+
: {}),
|
|
232547
|
+
...(action.cacheKey.queryStringValues
|
|
232548
|
+
? { QueryStringValues: action.cacheKey.queryStringValues }
|
|
232549
|
+
: {}),
|
|
232550
|
+
},
|
|
232551
|
+
}
|
|
232552
|
+
: {}),
|
|
232553
|
+
})),
|
|
232554
|
+
})),
|
|
232555
|
+
};
|
|
232556
|
+
}
|
|
232557
|
+
function toExtension(input) {
|
|
232558
|
+
if (!input) {
|
|
232559
|
+
return undefined;
|
|
232560
|
+
}
|
|
232561
|
+
const output = {};
|
|
232562
|
+
const headersHandler = toHeadersHandler(input.headersHandler);
|
|
232563
|
+
if (headersHandler) {
|
|
232564
|
+
output.HeadersHandler = headersHandler;
|
|
232565
|
+
}
|
|
232566
|
+
const cache = toCacheSet(input.cache);
|
|
232567
|
+
if (cache) {
|
|
232568
|
+
output.Cache = cache;
|
|
232569
|
+
}
|
|
232570
|
+
return Object.keys(output).length ? output : undefined;
|
|
232571
|
+
}
|
|
232572
|
+
function toPathRewrite(input) {
|
|
232573
|
+
if (!input) {
|
|
232574
|
+
return undefined;
|
|
232575
|
+
}
|
|
232576
|
+
const output = {};
|
|
232577
|
+
if (typeof input.prefix === "string") {
|
|
232578
|
+
output.Prefix = input.prefix;
|
|
232579
|
+
}
|
|
232580
|
+
if (typeof input.staticStorePrefix === "string") {
|
|
232581
|
+
output.StaticStorePrefix = input.staticStorePrefix;
|
|
232582
|
+
}
|
|
232583
|
+
return Object.keys(output).length ? output : undefined;
|
|
232584
|
+
}
|
|
232585
|
+
function toQpsPolicy(input) {
|
|
232586
|
+
if (!input) {
|
|
232587
|
+
return undefined;
|
|
232588
|
+
}
|
|
232589
|
+
const output = {};
|
|
232590
|
+
if (typeof input.total === "number") {
|
|
232591
|
+
output.QPSTotal = input.total;
|
|
232592
|
+
}
|
|
232593
|
+
if (input.perClient) {
|
|
232594
|
+
const perClient = {};
|
|
232595
|
+
if (input.perClient.limitBy) {
|
|
232596
|
+
perClient.LimitBy = input.perClient.limitBy;
|
|
232597
|
+
}
|
|
232598
|
+
if (typeof input.perClient.limitValue === "number") {
|
|
232599
|
+
perClient.LimitValue = input.perClient.limitValue;
|
|
232600
|
+
}
|
|
232601
|
+
if (Object.keys(perClient).length) {
|
|
232602
|
+
output.QPSPerClient = perClient;
|
|
232603
|
+
}
|
|
232604
|
+
}
|
|
232605
|
+
return Object.keys(output).length ? output : undefined;
|
|
232606
|
+
}
|
|
232607
|
+
/**
|
|
232608
|
+
* Route fields that ModifyHTTPServiceRoute replaces wholesale. When an update
|
|
232609
|
+
* omits one of them, the existing value must be carried over — otherwise a
|
|
232610
|
+
* partial update (e.g. only bumping QPS) would silently wipe CORS / rewrite /
|
|
232611
|
+
* headers / cache rules.
|
|
232612
|
+
*/
|
|
232613
|
+
const PRESERVED_ROUTE_FIELDS = [
|
|
232614
|
+
"EnableAuth",
|
|
232615
|
+
"EnableSafeDomain",
|
|
232616
|
+
"EnablePathTransmission",
|
|
232617
|
+
"PathRewrite",
|
|
232618
|
+
"QPSPolicy",
|
|
232619
|
+
"Extension",
|
|
232620
|
+
"Enable",
|
|
232621
|
+
];
|
|
232622
|
+
function carryOverRouteFields(route, existing) {
|
|
232623
|
+
if (!existing) {
|
|
232624
|
+
return route;
|
|
232625
|
+
}
|
|
232626
|
+
for (const field of PRESERVED_ROUTE_FIELDS) {
|
|
232627
|
+
if (route[field] === undefined && existing[field] !== undefined) {
|
|
232628
|
+
route[field] = existing[field];
|
|
232629
|
+
}
|
|
232630
|
+
}
|
|
232631
|
+
return route;
|
|
232632
|
+
}
|
|
231857
232633
|
/**
|
|
231858
232634
|
* Collect FAIL items from VerifyHTTPServiceRoute, mapping DNS records to
|
|
231859
232635
|
* lowercase field names for MCP structured output (aligned with CLI 3.8.1).
|
|
@@ -232296,16 +233072,13 @@ function registerGatewayTools(server) {
|
|
|
232296
233072
|
});
|
|
232297
233073
|
const path = normalizeAccessPath(input.route?.path ?? input.path ?? `/${upstreamResourceName}`);
|
|
232298
233074
|
const domain = await resolveRouteDomain(input.domain);
|
|
232299
|
-
const
|
|
232300
|
-
|
|
232301
|
-
|
|
232302
|
-
|
|
232303
|
-
|
|
232304
|
-
const
|
|
232305
|
-
|
|
232306
|
-
: input.enablePathTransmission !== undefined
|
|
232307
|
-
? input.enablePathTransmission
|
|
232308
|
-
: undefined;
|
|
233075
|
+
const pick = (routeValue, topValue) => routeValue !== undefined ? routeValue : topValue;
|
|
233076
|
+
const enableAuth = pick(input.route?.auth, input.auth);
|
|
233077
|
+
const enableSafeDomain = pick(input.route?.enableSafeDomain, input.enableSafeDomain);
|
|
233078
|
+
const enablePathTransmission = pick(input.route?.enablePathTransmission, input.enablePathTransmission);
|
|
233079
|
+
const routePathRewrite = toPathRewrite(pick(input.route?.pathRewrite, input.pathRewrite));
|
|
233080
|
+
const routeQpsPolicy = toQpsPolicy(pick(input.route?.qpsPolicy, input.qpsPolicy));
|
|
233081
|
+
const routeExtension = toExtension(pick(input.route?.extension, input.extension));
|
|
232309
233082
|
// Route enable: prefer route.enable. For updateRoute only, top-level
|
|
232310
233083
|
// enable also maps to Route.Enable (enableService/authSwitch use the
|
|
232311
233084
|
// same field name but different actions).
|
|
@@ -232319,18 +233092,35 @@ function registerGatewayTools(server) {
|
|
|
232319
233092
|
Path: path,
|
|
232320
233093
|
UpstreamResourceType: upstreamResourceType,
|
|
232321
233094
|
UpstreamResourceName: upstreamResourceName,
|
|
232322
|
-
EnableAuth: enableAuth,
|
|
232323
233095
|
};
|
|
233096
|
+
if (enableAuth !== undefined) {
|
|
233097
|
+
route.EnableAuth = enableAuth;
|
|
233098
|
+
}
|
|
233099
|
+
if (enableSafeDomain !== undefined) {
|
|
233100
|
+
route.EnableSafeDomain = enableSafeDomain;
|
|
233101
|
+
}
|
|
232324
233102
|
if (enablePathTransmission !== undefined) {
|
|
232325
233103
|
route.EnablePathTransmission = enablePathTransmission;
|
|
232326
233104
|
}
|
|
233105
|
+
if (routePathRewrite) {
|
|
233106
|
+
route.PathRewrite = routePathRewrite;
|
|
233107
|
+
}
|
|
233108
|
+
if (routeQpsPolicy) {
|
|
233109
|
+
route.QPSPolicy = routeQpsPolicy;
|
|
233110
|
+
}
|
|
233111
|
+
if (routeExtension) {
|
|
233112
|
+
route.Extension = routeExtension;
|
|
233113
|
+
}
|
|
232327
233114
|
if (routeEnable !== undefined) {
|
|
232328
233115
|
route.Enable = routeEnable;
|
|
232329
233116
|
}
|
|
233117
|
+
const domainExtension = toExtension(input.domainExtension);
|
|
232330
233118
|
return {
|
|
232331
233119
|
EnvId: await resolveEnvId(),
|
|
232332
233120
|
Domain: {
|
|
232333
233121
|
Domain: domain,
|
|
233122
|
+
...(input.protocol ? { Protocol: input.protocol } : {}),
|
|
233123
|
+
...(domainExtension ? { Extension: domainExtension } : {}),
|
|
232334
233124
|
Routes: [route],
|
|
232335
233125
|
},
|
|
232336
233126
|
resolved: {
|
|
@@ -232339,6 +233129,7 @@ function registerGatewayTools(server) {
|
|
|
232339
233129
|
upstreamResourceType,
|
|
232340
233130
|
upstreamResourceName,
|
|
232341
233131
|
enableAuth,
|
|
233132
|
+
enableSafeDomain,
|
|
232342
233133
|
enablePathTransmission,
|
|
232343
233134
|
enable: routeEnable,
|
|
232344
233135
|
},
|
|
@@ -232387,6 +233178,57 @@ function registerGatewayTools(server) {
|
|
|
232387
233178
|
}
|
|
232388
233179
|
return matches[0];
|
|
232389
233180
|
};
|
|
233181
|
+
/**
|
|
233182
|
+
* Locate the live record (domain + route) so partial updates can carry over
|
|
233183
|
+
* fields the caller did not touch.
|
|
233184
|
+
*/
|
|
233185
|
+
const findExistingRouteRecord = async (domain, path) => {
|
|
233186
|
+
const result = await listHttpServiceRoutes({ domain });
|
|
233187
|
+
const domainRecord = (result.Domains ?? []).find((item) => item.Domain === domain);
|
|
233188
|
+
const route = (domainRecord?.Routes ?? []).find((item) => normalizeAccessPath(String(item.Path ?? "")) ===
|
|
233189
|
+
path);
|
|
233190
|
+
return {
|
|
233191
|
+
domainRecord,
|
|
233192
|
+
route: route,
|
|
233193
|
+
};
|
|
233194
|
+
};
|
|
233195
|
+
/** CDN vs EO is decided by the domain's access type; default to CDN. */
|
|
233196
|
+
/**
|
|
233197
|
+
* 缓存层由域名的接入方式决定,不能猜。
|
|
233198
|
+
*
|
|
233199
|
+
* - EO / CDN → 对应缓存层
|
|
233200
|
+
* - DIRECT / CUSTOM / NONE → CloudBase 侧没有托管缓存,刷新不适用。
|
|
233201
|
+
* 实测(2026-10-21)对 DIRECT 域发 CDN 刷新,PurgeHTTPServiceCache 会「成功」登记
|
|
233202
|
+
* 一个任务,而 DescribeHTTPServiceCachePurgeTask 随后抛 Third Service Error ——
|
|
233203
|
+
* 即后端对 DIRECT 域缺校验、返回不可读错误。这里提前拦住并说明原因。
|
|
233204
|
+
*/
|
|
233205
|
+
const resolveDomainCacheType = async (domain, preferred) => {
|
|
233206
|
+
const findDomain = (result) => (result.Domains ?? []).find((item) => item.Domain === domain);
|
|
233207
|
+
let record = findDomain(await listHttpServiceRoutes({ domain }));
|
|
233208
|
+
if (!record) {
|
|
233209
|
+
// 域名下暂时没有路由时,筛 Domain 可能查不到,退回全量再找一次。
|
|
233210
|
+
record = findDomain(await listHttpServiceRoutes());
|
|
233211
|
+
}
|
|
233212
|
+
if (!record) {
|
|
233213
|
+
throw new Error((0, index_js_1.t)("gateway.cache.domainNotFound", { domain }));
|
|
233214
|
+
}
|
|
233215
|
+
const accessType = String(record.AccessType ?? "");
|
|
233216
|
+
const boundCacheType = accessType === "EO" ? "EO" : accessType === "CDN" ? "CDN" : undefined;
|
|
233217
|
+
if (!boundCacheType) {
|
|
233218
|
+
throw new Error((0, index_js_1.t)("gateway.cache.notManaged", {
|
|
233219
|
+
domain,
|
|
233220
|
+
accessType: accessType || "UNKNOWN",
|
|
233221
|
+
}));
|
|
233222
|
+
}
|
|
233223
|
+
if (preferred && preferred !== boundCacheType) {
|
|
233224
|
+
throw new Error((0, index_js_1.t)("gateway.cache.typeMismatch", {
|
|
233225
|
+
domain,
|
|
233226
|
+
accessType: boundCacheType,
|
|
233227
|
+
requested: preferred,
|
|
233228
|
+
}));
|
|
233229
|
+
}
|
|
233230
|
+
return boundCacheType;
|
|
233231
|
+
};
|
|
232390
233232
|
const routeMutationNextActions = (targetName) => [
|
|
232391
233233
|
{
|
|
232392
233234
|
tool: "queryGateway",
|
|
@@ -232499,6 +233341,34 @@ function registerGatewayTools(server) {
|
|
|
232499
233341
|
},
|
|
232500
233342
|
]);
|
|
232501
233343
|
}
|
|
233344
|
+
case "cachePurgeTask": {
|
|
233345
|
+
if (!input.domain) {
|
|
233346
|
+
throw new Error((0, index_js_1.t)("gateway.query.cachePurgeTaskDomainRequired"));
|
|
233347
|
+
}
|
|
233348
|
+
const cacheType = await resolveDomainCacheType(input.domain, input.cacheType);
|
|
233349
|
+
const cloudbase = await getManager();
|
|
233350
|
+
const result = await cloudbase.env.describeHttpServiceCachePurgeTask({
|
|
233351
|
+
EnvId: await resolveEnvId(),
|
|
233352
|
+
Domain: input.domain,
|
|
233353
|
+
CacheType: cacheType,
|
|
233354
|
+
...(input.taskId ? { TaskId: input.taskId } : {}),
|
|
233355
|
+
...(input.purgeType ? { PurgeType: input.purgeType } : {}),
|
|
233356
|
+
...(input.startTime ? { StartTime: input.startTime } : {}),
|
|
233357
|
+
...(input.endTime ? { EndTime: input.endTime } : {}),
|
|
233358
|
+
...(input.offset !== undefined ? { Offset: input.offset } : {}),
|
|
233359
|
+
...(input.limit !== undefined ? { Limit: input.limit } : {}),
|
|
233360
|
+
});
|
|
233361
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
233362
|
+
const tasks = Array.isArray(result?.Tasks) ? result.Tasks : [];
|
|
233363
|
+
return buildEnvelope({
|
|
233364
|
+
action: input.action,
|
|
233365
|
+
domain: input.domain,
|
|
233366
|
+
cacheType,
|
|
233367
|
+
tasks,
|
|
233368
|
+
total: result?.TotalCount ?? tasks.length,
|
|
233369
|
+
raw: result,
|
|
233370
|
+
}, (0, index_js_1.t)("gateway.query.cachePurgeTask", { count: tasks.length }));
|
|
233371
|
+
}
|
|
232502
233372
|
default:
|
|
232503
233373
|
throw new Error((0, index_js_1.t)("gateway.error.unsupportedAction", { action: input.action }));
|
|
232504
233374
|
}
|
|
@@ -232607,6 +233477,7 @@ function registerGatewayTools(server) {
|
|
|
232607
233477
|
upstreamResourceType: payload.resolved.upstreamResourceType,
|
|
232608
233478
|
upstreamResourceName: payload.resolved.upstreamResourceName,
|
|
232609
233479
|
auth: payload.resolved.enableAuth ?? null,
|
|
233480
|
+
enableSafeDomain: payload.resolved.enableSafeDomain ?? null,
|
|
232610
233481
|
enablePathTransmission: payload.resolved.enablePathTransmission ?? null,
|
|
232611
233482
|
accessUrl: `https://${payload.resolved.domain}${payload.resolved.path}`,
|
|
232612
233483
|
accessUrls: [`https://${payload.resolved.domain}${payload.resolved.path}`],
|
|
@@ -232635,6 +233506,14 @@ function registerGatewayTools(server) {
|
|
|
232635
233506
|
case "updateRoute": {
|
|
232636
233507
|
const cloudbase = await getManager();
|
|
232637
233508
|
const payload = await normalizeRoutePayload(input);
|
|
233509
|
+
// Preserve untouched route/domain fields from the live record: the
|
|
233510
|
+
// backend replaces the whole route entry, so a partial update would
|
|
233511
|
+
// otherwise wipe CORS / rewrite / QPS / headers / cache settings.
|
|
233512
|
+
const existing = await findExistingRouteRecord(payload.resolved.domain, payload.resolved.path);
|
|
233513
|
+
carryOverRouteFields(payload.Domain.Routes[0], existing.route);
|
|
233514
|
+
if (!payload.Domain.Protocol && existing.domainRecord?.Protocol) {
|
|
233515
|
+
payload.Domain.Protocol = existing.domainRecord.Protocol;
|
|
233516
|
+
}
|
|
232638
233517
|
const result = await cloudbase.env.modifyHttpServiceRoute({
|
|
232639
233518
|
EnvId: payload.EnvId,
|
|
232640
233519
|
Domain: payload.Domain,
|
|
@@ -232652,6 +233531,7 @@ function registerGatewayTools(server) {
|
|
|
232652
233531
|
upstreamResourceType: payload.resolved.upstreamResourceType,
|
|
232653
233532
|
upstreamResourceName: payload.resolved.upstreamResourceName,
|
|
232654
233533
|
auth: payload.resolved.enableAuth ?? null,
|
|
233534
|
+
enableSafeDomain: payload.resolved.enableSafeDomain ?? null,
|
|
232655
233535
|
enablePathTransmission: payload.resolved.enablePathTransmission ?? null,
|
|
232656
233536
|
enable: payload.resolved.enable ?? null,
|
|
232657
233537
|
...(accessUrl
|
|
@@ -232733,6 +233613,11 @@ function registerGatewayTools(server) {
|
|
|
232733
233613
|
if (enablePathTransmission !== undefined) {
|
|
232734
233614
|
route.EnablePathTransmission = enablePathTransmission;
|
|
232735
233615
|
}
|
|
233616
|
+
if (input.enableSafeDomain !== undefined) {
|
|
233617
|
+
route.EnableSafeDomain = input.enableSafeDomain;
|
|
233618
|
+
}
|
|
233619
|
+
// Toggling Enable must not drop CORS / rewrite / QPS / headers / cache.
|
|
233620
|
+
carryOverRouteFields(route, existing);
|
|
232736
233621
|
const cloudbase = await getManager();
|
|
232737
233622
|
const result = await cloudbase.env.modifyHttpServiceRoute({
|
|
232738
233623
|
EnvId: await resolveEnvId(),
|
|
@@ -232827,6 +233712,7 @@ function registerGatewayTools(server) {
|
|
|
232827
233712
|
CertId: input.certificateId || "",
|
|
232828
233713
|
AccessType: accessType,
|
|
232829
233714
|
Enable: input.enable !== undefined ? input.enable : true,
|
|
233715
|
+
...(input.protocol ? { Protocol: input.protocol } : {}),
|
|
232830
233716
|
...(input.customCname ? { CustomCname: input.customCname } : {}),
|
|
232831
233717
|
};
|
|
232832
233718
|
const verifyFailure = await verifyHttpServiceRouteOrFail({
|
|
@@ -232848,6 +233734,7 @@ function registerGatewayTools(server) {
|
|
|
232848
233734
|
Domain: input.domain,
|
|
232849
233735
|
CertId: certificateId,
|
|
232850
233736
|
AccessType: accessType,
|
|
233737
|
+
...(input.protocol ? { Protocol: input.protocol } : {}),
|
|
232851
233738
|
...(input.enable !== undefined
|
|
232852
233739
|
? { Enable: input.enable }
|
|
232853
233740
|
: {}),
|
|
@@ -232978,6 +233865,43 @@ function registerGatewayTools(server) {
|
|
|
232978
233865
|
},
|
|
232979
233866
|
]);
|
|
232980
233867
|
}
|
|
233868
|
+
case "purgeCache": {
|
|
233869
|
+
if (!input.domain) {
|
|
233870
|
+
throw new Error((0, index_js_1.t)("gateway.purgeCache.domainRequired"));
|
|
233871
|
+
}
|
|
233872
|
+
const targets = (input.targets ?? [])
|
|
233873
|
+
.map((item) => (typeof item === "string" ? item.trim() : ""))
|
|
233874
|
+
.filter(Boolean);
|
|
233875
|
+
if (!targets.length) {
|
|
233876
|
+
throw new Error((0, index_js_1.t)("gateway.purgeCache.targetsRequired"));
|
|
233877
|
+
}
|
|
233878
|
+
const purgeType = input.purgeType ?? "PURGE_URL";
|
|
233879
|
+
const cacheType = await resolveDomainCacheType(input.domain, input.cacheType);
|
|
233880
|
+
const cloudbase = await getManager();
|
|
233881
|
+
const result = await cloudbase.env.purgeHttpServiceCache({
|
|
233882
|
+
EnvId: await resolveEnvId(),
|
|
233883
|
+
Domain: input.domain,
|
|
233884
|
+
CacheType: cacheType,
|
|
233885
|
+
PurgeType: purgeType,
|
|
233886
|
+
Targets: targets,
|
|
233887
|
+
});
|
|
233888
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
233889
|
+
return buildEnvelope({
|
|
233890
|
+
action: input.action,
|
|
233891
|
+
domain: input.domain,
|
|
233892
|
+
cacheType,
|
|
233893
|
+
purgeType,
|
|
233894
|
+
targets,
|
|
233895
|
+
taskId: result?.TaskId ?? null,
|
|
233896
|
+
raw: result,
|
|
233897
|
+
}, (0, index_js_1.t)("gateway.purgeCache.message", { count: targets.length }), [
|
|
233898
|
+
{
|
|
233899
|
+
tool: "queryGateway",
|
|
233900
|
+
action: "cachePurgeTask",
|
|
233901
|
+
reason: (0, index_js_1.t)("gateway.purgeCache.verifyReason"),
|
|
233902
|
+
},
|
|
233903
|
+
]);
|
|
233904
|
+
}
|
|
232981
233905
|
default:
|
|
232982
233906
|
throw new Error((0, index_js_1.t)("gateway.error.unsupportedAction", { action: input.action }));
|
|
232983
233907
|
}
|
|
@@ -232996,6 +233920,19 @@ function registerGatewayTools(server) {
|
|
|
232996
233920
|
routeId: zod_1.z.string().optional().describe("gateway.schema.query.routeId"),
|
|
232997
233921
|
path: zod_1.z.string().optional().describe("gateway.schema.query.path"),
|
|
232998
233922
|
domain: zod_1.z.string().optional().describe("gateway.schema.query.domain"),
|
|
233923
|
+
cacheType: zod_1.z
|
|
233924
|
+
.enum(CACHE_TYPES)
|
|
233925
|
+
.optional()
|
|
233926
|
+
.describe("gateway.schema.query.cacheType"),
|
|
233927
|
+
taskId: zod_1.z.string().optional().describe("gateway.schema.query.taskId"),
|
|
233928
|
+
purgeType: zod_1.z
|
|
233929
|
+
.enum(PURGE_TYPES)
|
|
233930
|
+
.optional()
|
|
233931
|
+
.describe("gateway.schema.query.purgeType"),
|
|
233932
|
+
startTime: zod_1.z.string().optional().describe("gateway.schema.query.startTime"),
|
|
233933
|
+
endTime: zod_1.z.string().optional().describe("gateway.schema.query.endTime"),
|
|
233934
|
+
offset: zod_1.z.number().int().min(0).optional().describe("gateway.schema.query.offset"),
|
|
233935
|
+
limit: zod_1.z.number().int().min(1).optional().describe("gateway.schema.query.limit"),
|
|
232999
233936
|
},
|
|
233000
233937
|
annotations: {
|
|
233001
233938
|
readOnlyHint: true,
|
|
@@ -233025,6 +233962,26 @@ function registerGatewayTools(server) {
|
|
|
233025
233962
|
.boolean()
|
|
233026
233963
|
.optional()
|
|
233027
233964
|
.describe("gateway.schema.manage.enablePathTransmission"),
|
|
233965
|
+
enableSafeDomain: zod_1.z
|
|
233966
|
+
.boolean()
|
|
233967
|
+
.optional()
|
|
233968
|
+
.describe("gateway.schema.manage.enableSafeDomain"),
|
|
233969
|
+
pathRewrite: pathRewriteSchema
|
|
233970
|
+
.optional()
|
|
233971
|
+
.describe("gateway.schema.manage.pathRewrite"),
|
|
233972
|
+
qpsPolicy: qpsPolicySchema
|
|
233973
|
+
.optional()
|
|
233974
|
+
.describe("gateway.schema.manage.qpsPolicy"),
|
|
233975
|
+
extension: extensionSchema
|
|
233976
|
+
.optional()
|
|
233977
|
+
.describe("gateway.schema.manage.extension"),
|
|
233978
|
+
domainExtension: extensionSchema
|
|
233979
|
+
.optional()
|
|
233980
|
+
.describe("gateway.schema.manage.domainExtension"),
|
|
233981
|
+
protocol: zod_1.z
|
|
233982
|
+
.enum(DOMAIN_PROTOCOLS)
|
|
233983
|
+
.optional()
|
|
233984
|
+
.describe("gateway.schema.manage.protocol"),
|
|
233028
233985
|
route: zod_1.z
|
|
233029
233986
|
.object({
|
|
233030
233987
|
path: zod_1.z.string().optional(),
|
|
@@ -233041,6 +233998,19 @@ function registerGatewayTools(server) {
|
|
|
233041
233998
|
.boolean()
|
|
233042
233999
|
.optional()
|
|
233043
234000
|
.describe("gateway.schema.manage.route.enablePathTransmission"),
|
|
234001
|
+
enableSafeDomain: zod_1.z
|
|
234002
|
+
.boolean()
|
|
234003
|
+
.optional()
|
|
234004
|
+
.describe("gateway.schema.manage.route.enableSafeDomain"),
|
|
234005
|
+
pathRewrite: pathRewriteSchema
|
|
234006
|
+
.optional()
|
|
234007
|
+
.describe("gateway.schema.manage.route.pathRewrite"),
|
|
234008
|
+
qpsPolicy: qpsPolicySchema
|
|
234009
|
+
.optional()
|
|
234010
|
+
.describe("gateway.schema.manage.route.qpsPolicy"),
|
|
234011
|
+
extension: extensionSchema
|
|
234012
|
+
.optional()
|
|
234013
|
+
.describe("gateway.schema.manage.route.extension"),
|
|
233044
234014
|
enable: zod_1.z
|
|
233045
234015
|
.boolean()
|
|
233046
234016
|
.optional()
|
|
@@ -233062,6 +234032,18 @@ function registerGatewayTools(server) {
|
|
|
233062
234032
|
.optional()
|
|
233063
234033
|
.describe("gateway.schema.manage.customCname"),
|
|
233064
234034
|
enable: zod_1.z.boolean().optional().describe("gateway.schema.manage.enable"),
|
|
234035
|
+
cacheType: zod_1.z
|
|
234036
|
+
.enum(CACHE_TYPES)
|
|
234037
|
+
.optional()
|
|
234038
|
+
.describe("gateway.schema.manage.cacheType"),
|
|
234039
|
+
purgeType: zod_1.z
|
|
234040
|
+
.enum(PURGE_TYPES)
|
|
234041
|
+
.optional()
|
|
234042
|
+
.describe("gateway.schema.manage.purgeType"),
|
|
234043
|
+
targets: zod_1.z
|
|
234044
|
+
.array(zod_1.z.string())
|
|
234045
|
+
.optional()
|
|
234046
|
+
.describe("gateway.schema.manage.targets"),
|
|
233065
234047
|
},
|
|
233066
234048
|
annotations: {
|
|
233067
234049
|
readOnlyHint: false,
|
|
@@ -242137,7 +243119,7 @@ class TelemetryReporter {
|
|
|
242137
243119
|
const arch = os_1.default.arch(); // 系统架构
|
|
242138
243120
|
// Build-time injected version; guard for vitest / non-webpack runtimes.
|
|
242139
243121
|
const mcpVersion = process.env.npm_package_version ||
|
|
242140
|
-
( true ? "2.36.
|
|
243122
|
+
( true ? "2.36.1" : 0);
|
|
242141
243123
|
return {
|
|
242142
243124
|
userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
|
|
242143
243125
|
deviceId: this.deviceId,
|
|
@@ -243092,7 +244074,7 @@ function isReturnedFailureResult(result) {
|
|
|
243092
244074
|
* 所以两条路径对同一个底层错误得到的文本逐字相同(🆔 RequestId + 📦 版本页脚都在这里)。
|
|
243093
244075
|
*/
|
|
243094
244076
|
function buildFailureClientText(errorMessage, requestId, server) {
|
|
243095
|
-
const mcpVersion = true ? "2.36.
|
|
244077
|
+
const mcpVersion = true ? "2.36.1" : 0;
|
|
243096
244078
|
const requestIdSuffix = requestId ? `\n🆔 RequestId: ${requestId}` : '';
|
|
243097
244079
|
return `${errorMessage}${requestIdSuffix}\n\n📦 CloudBase MCP v${mcpVersion}\n${contributionHint(server)}`;
|
|
243098
244080
|
}
|