@cloudbase/cloudbase-mcp 2.34.3 → 2.34.4

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/index.js CHANGED
@@ -5185,9 +5185,9 @@ exports.permissions = void 0;
5185
5185
  const types_js_1 = __webpack_require__(9921);
5186
5186
  exports.permissions = (0, types_js_1.defineModule)({
5187
5187
  queryTitle: "查询 CloudBase 权限与用户配置",
5188
- queryDescription: "查询 CloudBase 权限与用户配置,支持查询资源权限(数据库/云函数/存储桶等)、角色列表/详情、应用用户列表/详情,以及网关 OPA 授权策略(对齐 CLI `tcb policy list/get`)。\n\n示例:\n- 查询存储桶权限:`action=\"getResourcePermission\", resourceType=\"storage\", resourceId=\"bucket-name\"`\n- 列出旧网关策略:`action=\"listPolicy\"`(PG / OPA 引擎环境返回空列表,与 CLI 一致)\n- 读取用户 Rego:`action=\"getPolicy\"`;平台扩展策略:`action=\"getPolicy\", extension=true`\n\n📌 跨后端边界提示:调用前先用 `envQuery(action=\"info\", envId=...)` 看 `EnvInfo.RuntimeBackends`。`resourceType=\"noSqlDatabase\"` 查询的是 CloudBase NoSQL 集合规则,与 CloudBase PostgreSQL(PG)表的行级安全(RLS)是两套独立机制——同一个 PG 环境里 NoSQL 集合若仍在使用,对那些集合查询本工具结果**仍然有效**。要查 PG 表 RLS,请改用 `queryPgDatabase(action=\"sql\", sql=\"SELECT * FROM pg_policies WHERE tablename=...\")`。本工具不涉及 MySQL 权限。\n\n⚠️ PostgreSQL 环境:平台 `DescribeResourcePermission` 对 PG 环境会直接拒绝。当 `resourceType=\"function\"` 时,本工具会自动回退到 Manager SDK `describeEnvAuthzConfig`(与 CLI `tcb policy get` 一致,读取 `authz.user.rego`)。显式 OPA 策略请用 `listPolicy` / `getPolicy`。\n\n⚠️ 角色类 action(`listRoles` / `getRole`)在 **PostgreSQL 类型环境**下平台侧一律拒绝(`The current API does not support PostgreSQL type environments.`)——这是平台能力边界,不是配置问题,**不要在 PG 环境反复重试**;PG 环境请改用 RLS(`managePgDatabase(action=\"execute\")` 跑 `CREATE POLICY`)或控制台管理权限。",
5188
+ queryDescription: "查询 CloudBase 权限与用户配置,支持查询资源权限(数据库/云函数/存储桶等)、角色列表/详情、应用用户列表/详情,以及网关 OPA 授权策略(对齐 CLI `tcb policy list/get`)。\n\n示例:\n- 查询存储桶权限:`action=\"getResourcePermission\", resourceType=\"storage\", resourceId=\"bucket-name\"`\n- 列出旧网关策略:`action=\"listPolicy\"`(PG / OPA 引擎环境返回空列表,与 CLI 一致)\n- 读取用户 Rego:`action=\"getPolicy\"`;平台扩展策略:`action=\"getPolicy\", extension=true`\n\n📌 跨后端边界提示:调用前先用 `queryEnv(action=\"info\", envId=...)` 看 `EnvInfo.RuntimeBackends`。`resourceType=\"noSqlDatabase\"` 查询的是 CloudBase NoSQL 集合规则,与 CloudBase PostgreSQL(PG)表的行级安全(RLS)是两套独立机制——同一个 PG 环境里 NoSQL 集合若仍在使用,对那些集合查询本工具结果**仍然有效**。要查 PG 表 RLS,请改用 `queryPgDatabase(action=\"sql\", sql=\"SELECT * FROM pg_policies WHERE tablename=...\")`。本工具不涉及 MySQL 权限。\n\n⚠️ PostgreSQL 环境:平台 `DescribeResourcePermission` 对 PG 环境会直接拒绝。当 `resourceType=\"function\"` 时,本工具会自动回退到 Manager SDK `describeEnvAuthzConfig`(与 CLI `tcb policy get` 一致,读取 `authz.user.rego`)。显式 OPA 策略请用 `listPolicy` / `getPolicy`。\n\n⚠️ 角色类 action(`listRoles` / `getRole`)在 **PostgreSQL 类型环境**下平台侧一律拒绝(`The current API does not support PostgreSQL type environments.`)——这是平台能力边界,不是配置问题,**不要在 PG 环境反复重试**;PG 环境请改用 RLS(`managePgDatabase(action=\"execute\")` 跑 `CREATE POLICY`)或控制台管理权限。",
5189
5189
  manageTitle: "管理 CloudBase 权限与用户配置",
5190
- manageDescription: "管理 CloudBase 权限与用户配置,支持修改资源权限(数据库/云函数/存储桶等)、角色管理、成员与策略增删、应用用户 CRUD,以及设置网关 OPA Rego 策略(对齐 CLI `tcb policy set`)。\n\n示例:\n- 设置存储桶为私有:`action=\"updateResourcePermission\", resourceType=\"storage\", resourceId=\"bucket-name\", permission=\"PRIVATE\"`\n- 创建角色:`action=\"createRole\", roleName=\"admin\", roleIdentity=\"admin\"`\n- 放开云函数匿名/未登录访问(PG 会走 OPA,对齐 CLI `tcb policy set`):`action=\"updateResourcePermission\", resourceType=\"function\", resourceId=\"myFn\", permission=\"CUSTOM\", securityRule='{\"invoke\":true}'`\n- 直接设置用户 Rego:`action=\"setPolicy\", regoContent=\"package authz.user\\n\\ndefault allow := false\\n\", confirm=true`(⚠️ 立即禁用旧网关鉴权)\n\n注意:`createUser` / `updateUser` 是环境侧应用用户管理能力,适合测试账号、管理员或预置用户,不应替代浏览器里的 Web SDK 注册表单;前端用户名密码注册应使用 `auth.signUp({ username, password })`,登录应使用 `auth.signInWithPassword({ username, password })`。直接在浏览器里用 `auth.signUp` 创建用户名密码用户取决于 SDK/provider 支持,使用前必须验证;不支持时应走后端或管理端边界,不能在浏览器暴露密钥。`securityRule` 的详细语义取决于 `resourceType`:`doc._openid`、`auth.openid`、查询条件子集校验,以及 `create` / `update` / `delete` JSON 模板仅适用于 `resourceType=\"noSqlDatabase\"` 的文档数据库安全规则;配置 `function` 或 `storage` 时,请参考各自官方安全规则文档,而不是复用 NoSQL 模板。\n\n📌 跨后端边界提示:调用前先用 `envQuery(action=\"info\", envId=...)` 看 `EnvInfo.RuntimeBackends`:\n- `resourceType=\"noSqlDatabase\"` 仅作用于 CloudBase NoSQL 文档数据库的集合;CloudBase PostgreSQL(PG)表的行级权限**不**受它控制——PG 表请改用 RLS:`managePgDatabase(action=\"execute\", confirm=true)` 跑 `ALTER TABLE ... ENABLE ROW LEVEL SECURITY` 与 `CREATE POLICY ...`。同一个 PG 环境里如果还有 NoSQL 集合在用,对那些**集合**继续使用 `noSqlDatabase` 规则是正确的——不是\"PG 环境就禁用本工具\"。\n- `resourceType=\"storage\"` 控制的是 NoSQL/COS 存储桶 ACL;PG 的 `pgstore` bucket 不在此 `resourceType` 覆盖范围内。\n- 本工具不涉及 MySQL;MySQL 数据库权限请走 MySQL 自身的 GRANT/REVOKE 语句(通过 `manageMysqlDatabase`)。\n\n⚠️ PostgreSQL 环境:平台 `ModifyResourcePermission` 对 PG 环境会直接拒绝。当 `resourceType=\"function\"` 时,本工具会自动回退到 Manager SDK `modifyEnvAuthzConfig`(与 CLI `tcb policy set` 一致,写入 `authz.user.rego`)。`securityRule` 可传完整 Rego(`package authz.user`)或 `'{\"invoke\":true}'`(自动生成放通 anonymous/unauthenticated 调 functions 的策略)。设置 Rego 后旧网关鉴权会失效,行为与 CLI 相同。显式 OPA 策略请优先用 `action=\"setPolicy\"`。\n\n⚠️ 角色类 action(`createRole` / `deleteRoles` / `updateRole`)在 **PostgreSQL 类型环境**下平台侧一律拒绝(`The current API does not support PostgreSQL type environments.`)——平台能力边界,不是配置问题,**不要在 PG 环境反复重试**;PG 环境请改用 RLS(`managePgDatabase(action=\"execute\")` 跑 `CREATE POLICY`)或控制台管理权限。",
5190
+ manageDescription: "管理 CloudBase 权限与用户配置,支持修改资源权限(数据库/云函数/存储桶等)、角色管理、成员与策略增删、应用用户 CRUD,以及设置网关 OPA Rego 策略(对齐 CLI `tcb policy set`)。\n\n示例:\n- 设置存储桶为私有:`action=\"updateResourcePermission\", resourceType=\"storage\", resourceId=\"bucket-name\", permission=\"PRIVATE\"`\n- 创建角色:`action=\"createRole\", roleName=\"admin\", roleIdentity=\"admin\"`\n- 放开云函数匿名/未登录访问(PG 会走 OPA,对齐 CLI `tcb policy set`):`action=\"updateResourcePermission\", resourceType=\"function\", resourceId=\"myFn\", permission=\"CUSTOM\", securityRule='{\"invoke\":true}'`\n- 直接设置用户 Rego:`action=\"setPolicy\", regoContent=\"package authz.user\\n\\ndefault allow := false\\n\", confirm=true`(⚠️ 立即禁用旧网关鉴权)\n\n注意:`createUser` / `updateUser` 是环境侧应用用户管理能力,适合测试账号、管理员或预置用户,不应替代浏览器里的 Web SDK 注册表单;前端用户名密码注册应使用 `auth.signUp({ username, password })`,登录应使用 `auth.signInWithPassword({ username, password })`。直接在浏览器里用 `auth.signUp` 创建用户名密码用户取决于 SDK/provider 支持,使用前必须验证;不支持时应走后端或管理端边界,不能在浏览器暴露密钥。`securityRule` 的详细语义取决于 `resourceType`:`doc._openid`、`auth.openid`、查询条件子集校验,以及 `create` / `update` / `delete` JSON 模板仅适用于 `resourceType=\"noSqlDatabase\"` 的文档数据库安全规则;配置 `function` 或 `storage` 时,请参考各自官方安全规则文档,而不是复用 NoSQL 模板。\n\n📌 跨后端边界提示:调用前先用 `queryEnv(action=\"info\", envId=...)` 看 `EnvInfo.RuntimeBackends`:\n- `resourceType=\"noSqlDatabase\"` 仅作用于 CloudBase NoSQL 文档数据库的集合;CloudBase PostgreSQL(PG)表的行级权限**不**受它控制——PG 表请改用 RLS:`managePgDatabase(action=\"execute\", confirm=true)` 跑 `ALTER TABLE ... ENABLE ROW LEVEL SECURITY` 与 `CREATE POLICY ...`。同一个 PG 环境里如果还有 NoSQL 集合在用,对那些**集合**继续使用 `noSqlDatabase` 规则是正确的——不是\"PG 环境就禁用本工具\"。\n- `resourceType=\"storage\"` 控制的是 NoSQL/COS 存储桶 ACL;PG 的 `pgstore` bucket 不在此 `resourceType` 覆盖范围内。\n- 本工具不涉及 MySQL;MySQL 数据库权限请走 MySQL 自身的 GRANT/REVOKE 语句(通过 `manageMysqlDatabase`)。\n\n⚠️ PostgreSQL 环境:平台 `ModifyResourcePermission` 对 PG 环境会直接拒绝。当 `resourceType=\"function\"` 时,本工具会自动回退到 Manager SDK `modifyEnvAuthzConfig`(与 CLI `tcb policy set` 一致,写入 `authz.user.rego`)。`securityRule` 可传完整 Rego(`package authz.user`)或 `'{\"invoke\":true}'`(自动生成放通 anonymous/unauthenticated 调 functions 的策略)。设置 Rego 后旧网关鉴权会失效,行为与 CLI 相同。显式 OPA 策略请优先用 `action=\"setPolicy\"`。\n\n⚠️ 角色类 action(`createRole` / `deleteRoles` / `updateRole`)在 **PostgreSQL 类型环境**下平台侧一律拒绝(`The current API does not support PostgreSQL type environments.`)——平台能力边界,不是配置问题,**不要在 PG 环境反复重试**;PG 环境请改用 RLS(`managePgDatabase(action=\"execute\")` 跑 `CREATE POLICY`)或控制台管理权限。",
5191
5191
  writeVerificationHint: "对于 {resourceId} 这类有后端权限控制的集合,前端调用 .doc(id).update() / .doc(id).remove() 后,不能只看是否没有抛异常。请显式检查返回结果中的 updated / deleted 是否大于 0;如果 result.code、result.message 存在,或 updated / deleted 为 0,要把它当作真实失败并向上抛错。",
5192
5192
  permissionPropagationHint: "刚更新完 {resourceId} 的安全规则时,后端权限通常在数秒到约 30 秒内生效。若紧接着的真实写操作仍返回 DATABASE_PERMISSION_DENIED,请先间隔数秒用同一登录态重试同一条 .doc(id).update() / .doc(id).remove();不要盲等数分钟,也不要立刻连续重写规则,更不要在短暂传播窗口里把旧拒绝直接当成规则表达式仍然错误。",
5193
5193
  validateRegoEmpty: "action=setPolicy 需要非空 regoContent(对齐 CLI `tcb policy set <regoContent>`)。",
@@ -5254,9 +5254,9 @@ exports.permissions = (0, types_js_1.defineModule)({
5254
5254
  setPolicySuccess: "用户 OPA Rego 策略设置成功(旧网关鉴权已失效)",
5255
5255
  }, {
5256
5256
  queryTitle: "Query CloudBase permissions and user config",
5257
- queryDescription: "Query CloudBase permissions and user config: resource permissions (database/functions/buckets etc.), role list/detail, app user list/detail, and gateway OPA authorization policies (aligned with CLI `tcb policy list/get`).\n\nExamples:\n- Query bucket permission: `action=\"getResourcePermission\", resourceType=\"storage\", resourceId=\"bucket-name\"`\n- List legacy gateway policies: `action=\"listPolicy\"` (returns an empty list on PG / OPA engine environments, consistent with the CLI)\n- Read user Rego: `action=\"getPolicy\"`; platform extension policy: `action=\"getPolicy\", extension=true`\n\n📌 Cross-backend boundary note: before calling, check `EnvInfo.RuntimeBackends` via `envQuery(action=\"info\", envId=...)`. `resourceType=\"noSqlDatabase\"` queries CloudBase NoSQL collection rules, which are a separate mechanism from row-level security (RLS) on CloudBase PostgreSQL (PG) tables — in the same PG environment, if NoSQL collections are still in use, querying them with this tool **remains valid**. To query PG table RLS, use `queryPgDatabase(action=\"sql\", sql=\"SELECT * FROM pg_policies WHERE tablename=...\")` instead. This tool does not cover MySQL permissions.\n\n⚠️ PostgreSQL environments: the platform `DescribeResourcePermission` API rejects PG environments outright. When `resourceType=\"function\"`, this tool automatically falls back to the Manager SDK `describeEnvAuthzConfig` (aligned with CLI `tcb policy get`, reading `authz.user.rego`). For explicit OPA policies use `listPolicy` / `getPolicy`.\n\n⚠️ Role actions (`listRoles` / `getRole`) are rejected outright by the platform on **PostgreSQL environments** (`The current API does not support PostgreSQL type environments.`). This is a platform capability boundary, not a configuration problem — **do not keep retrying on PG**; use RLS (`managePgDatabase(action=\"execute\")` with `CREATE POLICY`) or the console to manage permissions instead.",
5257
+ queryDescription: "Query CloudBase permissions and user config: resource permissions (database/functions/buckets etc.), role list/detail, app user list/detail, and gateway OPA authorization policies (aligned with CLI `tcb policy list/get`).\n\nExamples:\n- Query bucket permission: `action=\"getResourcePermission\", resourceType=\"storage\", resourceId=\"bucket-name\"`\n- List legacy gateway policies: `action=\"listPolicy\"` (returns an empty list on PG / OPA engine environments, consistent with the CLI)\n- Read user Rego: `action=\"getPolicy\"`; platform extension policy: `action=\"getPolicy\", extension=true`\n\n📌 Cross-backend boundary note: before calling, check `EnvInfo.RuntimeBackends` via `queryEnv(action=\"info\", envId=...)`. `resourceType=\"noSqlDatabase\"` queries CloudBase NoSQL collection rules, which are a separate mechanism from row-level security (RLS) on CloudBase PostgreSQL (PG) tables — in the same PG environment, if NoSQL collections are still in use, querying them with this tool **remains valid**. To query PG table RLS, use `queryPgDatabase(action=\"sql\", sql=\"SELECT * FROM pg_policies WHERE tablename=...\")` instead. This tool does not cover MySQL permissions.\n\n⚠️ PostgreSQL environments: the platform `DescribeResourcePermission` API rejects PG environments outright. When `resourceType=\"function\"`, this tool automatically falls back to the Manager SDK `describeEnvAuthzConfig` (aligned with CLI `tcb policy get`, reading `authz.user.rego`). For explicit OPA policies use `listPolicy` / `getPolicy`.\n\n⚠️ Role actions (`listRoles` / `getRole`) are rejected outright by the platform on **PostgreSQL environments** (`The current API does not support PostgreSQL type environments.`). This is a platform capability boundary, not a configuration problem — **do not keep retrying on PG**; use RLS (`managePgDatabase(action=\"execute\")` with `CREATE POLICY`) or the console to manage permissions instead.",
5258
5258
  manageTitle: "Manage CloudBase permissions and user config",
5259
- manageDescription: "Manage CloudBase permissions and user config: modify resource permissions (database/functions/buckets etc.), role management, member/policy add & remove, app user CRUD, and setting gateway OPA Rego policies (aligned with CLI `tcb policy set`).\n\nExamples:\n- Set a bucket to private: `action=\"updateResourcePermission\", resourceType=\"storage\", resourceId=\"bucket-name\", permission=\"PRIVATE\"`\n- Create a role: `action=\"createRole\", roleName=\"admin\", roleIdentity=\"admin\"`\n- Open a cloud function to anonymous/unauthenticated access (PG goes through OPA, aligned with CLI `tcb policy set`): `action=\"updateResourcePermission\", resourceType=\"function\", resourceId=\"myFn\", permission=\"CUSTOM\", securityRule='{\"invoke\":true}'`\n- Set user Rego directly: `action=\"setPolicy\", regoContent=\"package authz.user\\n\\ndefault allow := false\\n\", confirm=true` (⚠️ immediately disables legacy gateway authorization)\n\nNote: `createUser` / `updateUser` are environment-side app user management capabilities, suitable for test accounts, administrators, or pre-provisioned users; they should not replace the Web SDK signup form in the browser. For frontend username/password signup use `auth.signUp({ username, password })` and for login `auth.signInWithPassword({ username, password })`. Creating username/password users directly in the browser with `auth.signUp` depends on SDK/provider support and must be verified before use; if unsupported, go through a backend or management API boundary and never expose keys in the browser. The detailed semantics of `securityRule` depend on `resourceType`: `doc._openid`, `auth.openid`, query-condition subset validation, and the `create` / `update` / `delete` JSON templates only apply to document database security rules with `resourceType=\"noSqlDatabase\"`; when configuring `function` or `storage`, refer to their official security rule docs instead of reusing NoSQL templates.\n\n📌 Cross-backend boundary note: before calling, check `EnvInfo.RuntimeBackends` via `envQuery(action=\"info\", envId=...)`:\n- `resourceType=\"noSqlDatabase\"` only affects CloudBase NoSQL document database collections; row-level permissions of CloudBase PostgreSQL (PG) tables are **not** controlled by it — for PG tables use RLS instead: run `ALTER TABLE ... ENABLE ROW LEVEL SECURITY` and `CREATE POLICY ...` via `managePgDatabase(action=\"execute\", confirm=true)`. In the same PG environment, if NoSQL collections are still in use, continuing to use `noSqlDatabase` rules for those **collections** is correct — it does not mean \"this tool is disabled on PG environments\".\n- `resourceType=\"storage\"` controls NoSQL/COS bucket ACLs; PG `pgstore` buckets are not covered by this `resourceType`.\n- This tool does not cover MySQL; for MySQL database permissions use MySQL's own GRANT/REVOKE statements (via `manageMysqlDatabase`).\n\n⚠️ PostgreSQL environments: the platform `ModifyResourcePermission` API rejects PG environments outright. When `resourceType=\"function\"`, this tool automatically falls back to the Manager SDK `modifyEnvAuthzConfig` (aligned with CLI `tcb policy set`, writing `authz.user.rego`). `securityRule` accepts a full Rego document (`package authz.user`) or `'{\"invoke\":true}'` (auto-generates a policy allowing anonymous/unauthenticated calls to functions). Setting Rego disables legacy gateway authorization, same as the CLI. Prefer `action=\"setPolicy\"` for explicit OPA policies.\n\n⚠️ Role actions (`createRole` / `deleteRoles` / `updateRole`) are rejected outright by the platform on **PostgreSQL environments** (`The current API does not support PostgreSQL type environments.`). This is a platform capability boundary, not a configuration problem — **do not keep retrying on PG**; use RLS (`managePgDatabase(action=\"execute\")` with `CREATE POLICY`) or the console to manage permissions instead.",
5259
+ manageDescription: "Manage CloudBase permissions and user config: modify resource permissions (database/functions/buckets etc.), role management, member/policy add & remove, app user CRUD, and setting gateway OPA Rego policies (aligned with CLI `tcb policy set`).\n\nExamples:\n- Set a bucket to private: `action=\"updateResourcePermission\", resourceType=\"storage\", resourceId=\"bucket-name\", permission=\"PRIVATE\"`\n- Create a role: `action=\"createRole\", roleName=\"admin\", roleIdentity=\"admin\"`\n- Open a cloud function to anonymous/unauthenticated access (PG goes through OPA, aligned with CLI `tcb policy set`): `action=\"updateResourcePermission\", resourceType=\"function\", resourceId=\"myFn\", permission=\"CUSTOM\", securityRule='{\"invoke\":true}'`\n- Set user Rego directly: `action=\"setPolicy\", regoContent=\"package authz.user\\n\\ndefault allow := false\\n\", confirm=true` (⚠️ immediately disables legacy gateway authorization)\n\nNote: `createUser` / `updateUser` are environment-side app user management capabilities, suitable for test accounts, administrators, or pre-provisioned users; they should not replace the Web SDK signup form in the browser. For frontend username/password signup use `auth.signUp({ username, password })` and for login `auth.signInWithPassword({ username, password })`. Creating username/password users directly in the browser with `auth.signUp` depends on SDK/provider support and must be verified before use; if unsupported, go through a backend or management API boundary and never expose keys in the browser. The detailed semantics of `securityRule` depend on `resourceType`: `doc._openid`, `auth.openid`, query-condition subset validation, and the `create` / `update` / `delete` JSON templates only apply to document database security rules with `resourceType=\"noSqlDatabase\"`; when configuring `function` or `storage`, refer to their official security rule docs instead of reusing NoSQL templates.\n\n📌 Cross-backend boundary note: before calling, check `EnvInfo.RuntimeBackends` via `queryEnv(action=\"info\", envId=...)`:\n- `resourceType=\"noSqlDatabase\"` only affects CloudBase NoSQL document database collections; row-level permissions of CloudBase PostgreSQL (PG) tables are **not** controlled by it — for PG tables use RLS instead: run `ALTER TABLE ... ENABLE ROW LEVEL SECURITY` and `CREATE POLICY ...` via `managePgDatabase(action=\"execute\", confirm=true)`. In the same PG environment, if NoSQL collections are still in use, continuing to use `noSqlDatabase` rules for those **collections** is correct — it does not mean \"this tool is disabled on PG environments\".\n- `resourceType=\"storage\"` controls NoSQL/COS bucket ACLs; PG `pgstore` buckets are not covered by this `resourceType`.\n- This tool does not cover MySQL; for MySQL database permissions use MySQL's own GRANT/REVOKE statements (via `manageMysqlDatabase`).\n\n⚠️ PostgreSQL environments: the platform `ModifyResourcePermission` API rejects PG environments outright. When `resourceType=\"function\"`, this tool automatically falls back to the Manager SDK `modifyEnvAuthzConfig` (aligned with CLI `tcb policy set`, writing `authz.user.rego`). `securityRule` accepts a full Rego document (`package authz.user`) or `'{\"invoke\":true}'` (auto-generates a policy allowing anonymous/unauthenticated calls to functions). Setting Rego disables legacy gateway authorization, same as the CLI. Prefer `action=\"setPolicy\"` for explicit OPA policies.\n\n⚠️ Role actions (`createRole` / `deleteRoles` / `updateRole`) are rejected outright by the platform on **PostgreSQL environments** (`The current API does not support PostgreSQL type environments.`). This is a platform capability boundary, not a configuration problem — **do not keep retrying on PG**; use RLS (`managePgDatabase(action=\"execute\")` with `CREATE POLICY`) or the console to manage permissions instead.",
5260
5260
  writeVerificationHint: "For collections with backend permission control like {resourceId}, after the frontend calls .doc(id).update() / .doc(id).remove(), do not just check that no exception was thrown. Explicitly verify that updated / deleted in the result is greater than 0; if result.code or result.message exists, or updated / deleted is 0, treat it as a real failure and propagate the error.",
5261
5261
  permissionPropagationHint: "Right after updating security rules for {resourceId}, backend permissions usually take effect within a few seconds to about 30 seconds. If an immediate real write still returns DATABASE_PERMISSION_DENIED, wait a few seconds and retry the same .doc(id).update() / .doc(id).remove() with the same login state; do not wait blindly for minutes, do not immediately rewrite the rules repeatedly, and do not treat an old rejection during the short propagation window as evidence that the rule expression is still wrong.",
5262
5262
  validateRegoEmpty: "action=setPolicy requires non-empty regoContent (aligned with CLI `tcb policy set <regoContent>`).",
@@ -5354,11 +5354,11 @@ exports.rag = (0, types_js_1.defineModule)({
5354
5354
 
5355
5355
  返回内容包含该 skill 的 SKILL.md 全文,以及它在远端聚合仓(CNB raw)中的全部 .md 文件地址清单(SKILL.md 与 references/ 等,可直接 HTTP 抓取)。正文中代码栅栏之外的相对链接也会改写为绝对地址;若该 skill 在远端仓中不存在,则只返回内联内容并明确标注,不返回失效链接。
5356
5356
 
5357
- 固定技能文档 (skill) 查询当前支持 {skillCount} 个固定文档,分别是:
5358
- {skillList}
5357
+ 不确定该选哪个时:mode=skill 下不传 skillName、mode=openapi 下不传 apiName 直接调用,会返回当前可用清单及各自的适用场景 / 接口简介,再带上名称重新调用即可。可选名称也见本工具的 skillName / apiName 枚举(skill 共 {skillCount} 个,API 共 {openapiCount} 个)。
5359
5358
 
5360
- OpenAPI 文档 (openapi) 查询只需要传 mode="openapi" 和 apiName,不要传 action;action 仅用于 mode="docs"。当前支持 {openapiCount} 个 API 文档,分别是:
5361
- {openapiList}`,
5359
+ 注意:OpenAPI 文档 (openapi) 查询只需要传 mode="openapi" 和 apiName,不要传 action;action 仅用于 mode="docs"。`,
5360
+ skillCatalogHeader: "CloudBase 技能文档 (skill) 当前可用 {count} 个,用 mode=skill + skillName 读取其中一篇:",
5361
+ openapiCatalogHeader: "OpenAPI 文档 (openapi) 当前可用 {count} 个,用 mode=openapi + apiName 读取其中一篇:",
5362
5362
  skillListItem: "文档名:{name} 文档介绍:{description}",
5363
5363
  openapiListItem: "API名:{name} API介绍:{description}",
5364
5364
  paramRequired: "action={action} 时必须提供 {param}",
@@ -5402,11 +5402,11 @@ exports.rag = (0, types_js_1.defineModule)({
5402
5402
 
5403
5403
  The response contains the full SKILL.md of the skill plus the list of all its .md file URLs in the remote aggregate repo (CNB raw) — SKILL.md and references/ etc., fetchable over HTTP. Relative links outside code fences are rewritten to absolute URLs; when the skill is absent from the remote repo only the inline content is returned and that is stated explicitly, so no dead links are handed out.
5404
5404
 
5405
- Fixed skill doc (skill) queries currently support {skillCount} fixed docs:
5406
- {skillList}
5405
+ When unsure which one to pick: call with mode=skill and no skillName, or mode=openapi and no apiName, to get the current catalog with each entry's scenario / summary, then call again with the name. Available names are also listed in this tool's skillName / apiName enums (currently {skillCount} skills, {openapiCount} APIs).
5407
5406
 
5408
- OpenAPI doc (openapi) queries only need mode="openapi" and apiName; do not pass action — action is only for mode="docs". Currently {openapiCount} API docs are supported:
5409
- {openapiList}`,
5407
+ Note: OpenAPI doc (openapi) queries only need mode="openapi" and apiName; do not pass action — action is only for mode="docs".`,
5408
+ skillCatalogHeader: "CloudBase skill docs (skill), {count} available. Use mode=skill + skillName to read one:",
5409
+ openapiCatalogHeader: "OpenAPI docs (openapi), {count} available. Use mode=openapi + apiName to read one:",
5410
5410
  skillListItem: "Skill: {name} — Description: {description}",
5411
5411
  openapiListItem: "API: {name} — Description: {description}",
5412
5412
  paramRequired: "{param} is required when action={action}",
@@ -6185,7 +6185,8 @@ function registerAgentTools(server) {
6185
6185
  },
6186
6186
  annotations: {
6187
6187
  readOnlyHint: true,
6188
- openWorldHint: true,
6188
+ destructiveHint: false,
6189
+ openWorldHint: false,
6189
6190
  category: "agents",
6190
6191
  },
6191
6192
  }, async ({ action, agentId, pageNumber, pageSize, params, }) => {
@@ -6259,7 +6260,7 @@ function registerAgentTools(server) {
6259
6260
  readOnlyHint: false,
6260
6261
  destructiveHint: true,
6261
6262
  idempotentHint: false,
6262
- openWorldHint: true,
6263
+ openWorldHint: false,
6263
6264
  category: "agents",
6264
6265
  },
6265
6266
  }, async ({ action, agentId, name, description, runtime, timeout, memorySize, installDependency, zipFile, cosBucketRegion, tempCosObjectName, sessionConfig, cwd, params, }) => {
@@ -6714,7 +6715,8 @@ function registerAppAuthTools(server) {
6714
6715
  },
6715
6716
  annotations: {
6716
6717
  readOnlyHint: true,
6717
- openWorldHint: true,
6718
+ destructiveHint: false,
6719
+ openWorldHint: false,
6718
6720
  category: "auth",
6719
6721
  },
6720
6722
  }, async ({ action, providerId, clientId, keyType, pageNumber, pageSize, }) => withEnvelope(async () => {
@@ -6851,7 +6853,7 @@ function registerAppAuthTools(server) {
6851
6853
  readOnlyHint: false,
6852
6854
  destructiveHint: true,
6853
6855
  idempotentHint: false,
6854
- openWorldHint: true,
6856
+ openWorldHint: false,
6855
6857
  category: "auth",
6856
6858
  },
6857
6859
  }, async ({ action, patch, providerId, providerType, displayName, clientId, config, keyType, keyName, expireIn, keyId, }) => withEnvelope(async () => {
@@ -7163,7 +7165,8 @@ function registerAppTools(server) {
7163
7165
  },
7164
7166
  annotations: {
7165
7167
  readOnlyHint: true,
7166
- openWorldHint: true,
7168
+ destructiveHint: false,
7169
+ openWorldHint: false,
7167
7170
  category: "apps",
7168
7171
  },
7169
7172
  }, async ({ action, serviceName, searchKey, pageNo, pageSize, versionName, buildId, start, }) => {
@@ -7405,7 +7408,7 @@ function registerAppTools(server) {
7405
7408
  readOnlyHint: false,
7406
7409
  destructiveHint: true,
7407
7410
  idempotentHint: false,
7408
- openWorldHint: true,
7411
+ openWorldHint: false,
7409
7412
  category: "apps",
7410
7413
  },
7411
7414
  }, async ({ action, serviceName, filePath, cosTimestamp, appPath, buildPath, framework, nodeJsVersion, installCmd, buildCmd, deployCmd, ignore, versionName, }) => {
@@ -8081,7 +8084,7 @@ function registerCapiTools(server) {
8081
8084
  readOnlyHint: false,
8082
8085
  destructiveHint: true,
8083
8086
  idempotentHint: false,
8084
- openWorldHint: true,
8087
+ openWorldHint: false,
8085
8088
  category: CATEGORY,
8086
8089
  },
8087
8090
  }, async ({ service, action, params, version, region, }) => {
@@ -8483,7 +8486,7 @@ const ManageCloudRunInputSchema = {
8483
8486
  PolicyThreshold: zod_1.z.number().min(1).max(100).describe('扩缩容阈值,单位为百分比。如60表示当资源使用率达到60%时触发扩缩容')
8484
8487
  })).optional().describe('扩缩容配置数组,用于配置服务的自动扩缩容策略。可配置多个扩缩容策略'),
8485
8488
  CustomLogs: zod_1.z.string().optional().describe('自定义日志配置,用于配置服务的日志收集和存储策略'),
8486
- Port: zod_1.z.number().min(1).max(65535).optional().describe('服务监听端口配置。函数型服务固定为3000,容器型服务可自定义。服务代码必须监听此端口才能正常接收请求'),
8489
+ Port: zod_1.z.number().min(1).max(65535).optional().describe('服务监听端口配置。函数型服务固定为3000(函数框架自身监听该端口,业务代码不要自行 app.listen);容器型服务可自定义,业务代码必须监听此端口'),
8487
8490
  EnvParams: zod_1.z.string().optional().describe('环境变量配置,JSON字符串格式。用于传递配置信息给服务代码,如\'{"DATABASE_URL":"postgres://user:pass@10.x.x.x:5432/db","NODE_ENV":"production"}\'。SDK v5.6.1+ 会自动对传入的环境变量进行 AES-256-CBC 加密传输。⚠️ 若 EnvParams 含 DATABASE_URL / MYSQL_* / POSTGRES_* / REDIS_* 等传统 TCP 连库变量,必须同时配置 VpcConf,否则实例通常无法访问 VPC 内数据库'),
8488
8491
  Dockerfile: zod_1.z.string().optional().describe('Dockerfile文件名配置,仅容器型服务需要。指定用于构建容器镜像的Dockerfile文件路径,默认为项目根目录下的Dockerfile'),
8489
8492
  BuildDir: zod_1.z.string().optional().describe('构建目录配置,指定代码构建的目录路径。当代码结构与标准不同时使用,默认为项目根目录'),
@@ -9264,7 +9267,8 @@ function registerCloudRunTools(server) {
9264
9267
  inputSchema: queryCloudRunInputSchema,
9265
9268
  annotations: {
9266
9269
  readOnlyHint: true,
9267
- openWorldHint: true,
9270
+ destructiveHint: false,
9271
+ openWorldHint: false,
9268
9272
  category: "cloudrun"
9269
9273
  }
9270
9274
  }, async (args) => {
@@ -9723,7 +9727,7 @@ function registerCloudRunTools(server) {
9723
9727
  readOnlyHint: false,
9724
9728
  destructiveHint: true,
9725
9729
  idempotentHint: false,
9726
- openWorldHint: true,
9730
+ openWorldHint: false,
9727
9731
  category: "cloudrun"
9728
9732
  }
9729
9733
  }, async (args) => {
@@ -11341,7 +11345,8 @@ function registerDataModelTools(server) {
11341
11345
  },
11342
11346
  annotations: {
11343
11347
  readOnlyHint: true,
11344
- openWorldHint: true,
11348
+ destructiveHint: false,
11349
+ openWorldHint: false,
11345
11350
  category: "database",
11346
11351
  },
11347
11352
  }, async ({ action, name, names, }) => {
@@ -11680,7 +11685,7 @@ classDiagram
11680
11685
  readOnlyHint: false,
11681
11686
  destructiveHint: false,
11682
11687
  idempotentHint: false,
11683
- openWorldHint: true,
11688
+ openWorldHint: false,
11684
11689
  category: "database",
11685
11690
  },
11686
11691
  }, async ({ mermaidDiagram, action = "create", publish = false, dbInstanceType = "MYSQL", }) => {
@@ -12216,7 +12221,8 @@ checkIndex: 检查指定索引是否存在`),
12216
12221
  },
12217
12222
  annotations: {
12218
12223
  readOnlyHint: true,
12219
- openWorldHint: true,
12224
+ destructiveHint: false,
12225
+ openWorldHint: false,
12220
12226
  category: CATEGORY,
12221
12227
  },
12222
12228
  }, async ({ action, limit, offset, collectionName, indexName }) => {
@@ -12419,7 +12425,7 @@ deleteCollection: 删除集合`),
12419
12425
  readOnlyHint: false,
12420
12426
  destructiveHint: true,
12421
12427
  idempotentHint: false,
12422
- openWorldHint: true,
12428
+ openWorldHint: false,
12423
12429
  category: CATEGORY,
12424
12430
  },
12425
12431
  }, async ({ action, collectionName, updateOptions }) => {
@@ -12601,7 +12607,8 @@ deleteCollection: 删除集合`),
12601
12607
  },
12602
12608
  annotations: {
12603
12609
  readOnlyHint: true,
12604
- openWorldHint: true,
12610
+ destructiveHint: false,
12611
+ openWorldHint: false,
12605
12612
  category: CATEGORY,
12606
12613
  },
12607
12614
  }, async ({ collectionName, instanceId, query, projection, sort, limit, offset }) => {
@@ -12702,7 +12709,7 @@ deleteCollection: 删除集合`),
12702
12709
  readOnlyHint: false,
12703
12710
  destructiveHint: true,
12704
12711
  idempotentHint: false,
12705
- openWorldHint: true,
12712
+ openWorldHint: false,
12706
12713
  category: CATEGORY,
12707
12714
  },
12708
12715
  }, async ({ action, collectionName, instanceId, documents, query, update, isMulti, upsert, }) => {
@@ -15320,7 +15327,8 @@ function registerPGDatabaseTools(server, providedDeps) {
15320
15327
  },
15321
15328
  annotations: {
15322
15329
  readOnlyHint: true,
15323
- openWorldHint: true,
15330
+ destructiveHint: false,
15331
+ openWorldHint: false,
15324
15332
  category: CATEGORY,
15325
15333
  },
15326
15334
  }, async (args) => {
@@ -15479,7 +15487,7 @@ function registerPGDatabaseTools(server, providedDeps) {
15479
15487
  readOnlyHint: false,
15480
15488
  destructiveHint: true,
15481
15489
  idempotentHint: false,
15482
- openWorldHint: true,
15490
+ openWorldHint: false,
15483
15491
  category: CATEGORY,
15484
15492
  },
15485
15493
  }, async (args) => {
@@ -16489,7 +16497,8 @@ function registerSQLDatabaseTools(server) {
16489
16497
  },
16490
16498
  annotations: {
16491
16499
  readOnlyHint: true,
16492
- openWorldHint: true,
16500
+ destructiveHint: false,
16501
+ openWorldHint: false,
16493
16502
  category: CATEGORY,
16494
16503
  },
16495
16504
  }, async (args) => {
@@ -16558,7 +16567,7 @@ function registerSQLDatabaseTools(server) {
16558
16567
  readOnlyHint: false,
16559
16568
  destructiveHint: true,
16560
16569
  idempotentHint: false,
16561
- openWorldHint: true,
16570
+ openWorldHint: false,
16562
16571
  category: CATEGORY,
16563
16572
  },
16564
16573
  }, async (args) => {
@@ -16862,7 +16871,8 @@ function registerDeployTools(server) {
16862
16871
  annotations: {
16863
16872
  // 本地构建会执行 buildCommand 并写产物文件,不是 read-only;但不变更云端资源,非 destructive。
16864
16873
  readOnlyHint: false,
16865
- openWorldHint: true,
16874
+ destructiveHint: false,
16875
+ openWorldHint: false,
16866
16876
  category: "deploy",
16867
16877
  },
16868
16878
  }, async ({ cwd, mode }) => {
@@ -16934,7 +16944,8 @@ function registerDeployTools(server) {
16934
16944
  },
16935
16945
  annotations: {
16936
16946
  readOnlyHint: true,
16937
- openWorldHint: true,
16947
+ destructiveHint: false,
16948
+ openWorldHint: false,
16938
16949
  category: "deploy",
16939
16950
  },
16940
16951
  }, async ({ cwd, mode, envId: envIdInput, only, skip, yes, }) => {
@@ -17016,7 +17027,7 @@ function registerDeployTools(server) {
17016
17027
  annotations: {
17017
17028
  readOnlyHint: false,
17018
17029
  destructiveHint: true,
17019
- openWorldHint: true,
17030
+ openWorldHint: false,
17020
17031
  category: "deploy",
17021
17032
  },
17022
17033
  }, async ({ confirm, confirmDestructive, cwd, mode, envId: envIdInput, only, skip, yes, concurrency, continueOnError, }) => {
@@ -18780,7 +18791,7 @@ async function enrichEnvInfoWithMissingFields(manager, result, envId) {
18780
18791
  }
18781
18792
  }
18782
18793
  /**
18783
- * Project gateway Route.Enable onto envQuery(info) without mutating StaticDomain.
18794
+ * Project gateway Route.Enable onto queryEnv(info) without mutating StaticDomain.
18784
18795
  *
18785
18796
  * StaticStorages[].StaticDomain stays the cloud-API nominal hostname.
18786
18797
  * Sibling field staticDomainRouteEnabled (and EnvInfo-level mirrors for the
@@ -19339,7 +19350,7 @@ function registerEnvTools(server) {
19339
19350
  readOnlyHint: false,
19340
19351
  destructiveHint: false,
19341
19352
  idempotentHint: false,
19342
- openWorldHint: true,
19353
+ openWorldHint: false,
19343
19354
  category: "env",
19344
19355
  },
19345
19356
  }, async (rawArgs) => {
@@ -20307,7 +20318,8 @@ function registerEnvTools(server) {
20307
20318
  },
20308
20319
  annotations: {
20309
20320
  readOnlyHint: true,
20310
- openWorldHint: true,
20321
+ destructiveHint: false,
20322
+ openWorldHint: false,
20311
20323
  category: "env",
20312
20324
  },
20313
20325
  };
@@ -20339,9 +20351,9 @@ function registerEnvTools(server) {
20339
20351
  },
20340
20352
  annotations: {
20341
20353
  readOnlyHint: false,
20342
- destructiveHint: false, // 注意:delete操作虽然是破坏性的,但这里采用较宽松的标注
20354
+ destructiveHint: true,
20343
20355
  idempotentHint: false,
20344
- openWorldHint: true,
20356
+ openWorldHint: false,
20345
20357
  category: "env",
20346
20358
  },
20347
20359
  }, async ({ action, domains, }) => {
@@ -20425,7 +20437,7 @@ function registerEnvTools(server) {
20425
20437
  readOnlyHint: false,
20426
20438
  destructiveHint: true,
20427
20439
  idempotentHint: false,
20428
- openWorldHint: true,
20440
+ openWorldHint: false,
20429
20441
  category: "env",
20430
20442
  },
20431
20443
  }, async (rawArgs) => {
@@ -24057,7 +24069,8 @@ function registerFunctionTools(server) {
24057
24069
  },
24058
24070
  annotations: {
24059
24071
  readOnlyHint: true,
24060
- openWorldHint: true,
24072
+ destructiveHint: false,
24073
+ openWorldHint: false,
24061
24074
  category: "functions",
24062
24075
  },
24063
24076
  }, async (input) => withEnvelope(() => handleQueryFunctions(input)));
@@ -24142,7 +24155,7 @@ function registerFunctionTools(server) {
24142
24155
  readOnlyHint: false,
24143
24156
  destructiveHint: true,
24144
24157
  idempotentHint: false,
24145
- openWorldHint: true,
24158
+ openWorldHint: false,
24146
24159
  category: "functions",
24147
24160
  },
24148
24161
  }, async (input) => withEnvelope(() => handleManageFunctions(input)));
@@ -25348,7 +25361,8 @@ function registerGatewayTools(server) {
25348
25361
  },
25349
25362
  annotations: {
25350
25363
  readOnlyHint: true,
25351
- openWorldHint: true,
25364
+ destructiveHint: false,
25365
+ openWorldHint: false,
25352
25366
  category: "gateway",
25353
25367
  },
25354
25368
  }, async (input) => withEnvelope(() => handleQueryGateway(input)));
@@ -25466,7 +25480,7 @@ function registerGatewayTools(server) {
25466
25480
  readOnlyHint: false,
25467
25481
  destructiveHint: true,
25468
25482
  idempotentHint: false,
25469
- openWorldHint: true,
25483
+ openWorldHint: false,
25470
25484
  category: "gateway",
25471
25485
  },
25472
25486
  }, async (input) => withEnvelope(() => handleManageGateway(input)));
@@ -25908,6 +25922,15 @@ function buildWebsiteConfigNextStep() {
25908
25922
  },
25909
25923
  };
25910
25924
  }
25925
+ /**
25926
+ * 静态托管的对象 key 一律不带前导斜杠(`dir/f.txt` 而非 `/dir/f.txt`),但 agent
25927
+ * 从 URL 形态(`/index.html`)推路径时很自然带上斜杠。底层 SDK 的 `getCloudKey`
25928
+ * 只补尾部 `/`、不剥离前导 `/`,随后 `getBucket({ Prefix })` 做的是严格字节前缀
25929
+ * 匹配 ⇒ `/dir/` 匹配不到 `dir/f.txt`。因此所有对外传入的路径/前缀都先在此归一化。
25930
+ */
25931
+ function stripLeadingSlashes(value) {
25932
+ return value.replace(/^\/+/, '');
25933
+ }
25911
25934
  function buildFindFilesNextStep(prefix) {
25912
25935
  return {
25913
25936
  tool: 'queryHosting',
@@ -26136,7 +26159,8 @@ function registerHostingTools(server) {
26136
26159
  inputSchema: queryHostingInputSchema,
26137
26160
  annotations: {
26138
26161
  readOnlyHint: true,
26139
- openWorldHint: true,
26162
+ destructiveHint: false,
26163
+ openWorldHint: false,
26140
26164
  category: 'hosting',
26141
26165
  },
26142
26166
  }, async (args) => {
@@ -26179,8 +26203,11 @@ function registerHostingTools(server) {
26179
26203
  if (!input.prefix) {
26180
26204
  throw new Error((0, index_js_1.t)('hosting.findFilesPrefixRequired'));
26181
26205
  }
26206
+ // 读侧与 delete 侧同源:prefix 原样透传时,agent 按 URL 形态传的
26207
+ // `/assets/` 在 COS 侧严格前缀匹配命中 0 条,会被误读成「目录是空的」。
26208
+ const normalizedPrefix = stripLeadingSlashes(input.prefix);
26182
26209
  const result = await cloudbase.hosting.findFiles({
26183
- prefix: input.prefix,
26210
+ prefix: normalizedPrefix,
26184
26211
  marker: input.marker,
26185
26212
  maxKeys: input.maxKeys,
26186
26213
  });
@@ -26192,7 +26219,7 @@ function registerHostingTools(server) {
26192
26219
  success: true,
26193
26220
  data: {
26194
26221
  action: 'findFiles',
26195
- prefix: input.prefix,
26222
+ prefix: normalizedPrefix,
26196
26223
  marker: input.marker,
26197
26224
  maxKeys: input.maxKeys,
26198
26225
  files: normalizedFiles,
@@ -26201,7 +26228,7 @@ function registerHostingTools(server) {
26201
26228
  result,
26202
26229
  },
26203
26230
  message: (0, index_js_1.t)('hosting.findFilesSuccess', {
26204
- prefix: input.prefix,
26231
+ prefix: normalizedPrefix,
26205
26232
  count: normalizedFiles.length,
26206
26233
  more: nextMarker ? (0, index_js_1.t)('hosting.findFilesMore') : '',
26207
26234
  }),
@@ -26290,7 +26317,7 @@ function registerHostingTools(server) {
26290
26317
  readOnlyHint: false,
26291
26318
  destructiveHint: true,
26292
26319
  idempotentHint: false,
26293
- openWorldHint: true,
26320
+ openWorldHint: false,
26294
26321
  category: 'hosting',
26295
26322
  },
26296
26323
  }, async (args) => {
@@ -26452,10 +26479,18 @@ function registerHostingTools(server) {
26452
26479
  if (!input.confirm) {
26453
26480
  throw new Error((0, index_js_1.t)('hosting.deleteConfirmRequired'));
26454
26481
  }
26482
+ // 静态托管对象 key 不带前导斜杠。若不规范化,isDir=true 会走
26483
+ // storage.deleteDirectoryCustom,其前缀由 getCloudKey(cloudPath)
26484
+ // 生成且不做前导斜杠剥离,做严格字节前缀匹配时 `/dir/` 匹配不到
26485
+ // `dir/f.txt`,导致目录删除静默 no-op(Deleted:0,文件全在)。
26486
+ // 同时下面的回查 findFiles(prefix) 也是严格前缀匹配,带斜杠时
26487
+ // 同样命中 0 条,会把「没删到」误判成「删干净了 verified:true」。
26488
+ // 这里统一剥离前导斜杠,两种形态(/dir 与 dir)都按正确 key 处理。
26489
+ const normalizedCloudPath = stripLeadingSlashes(input.cloudPath);
26455
26490
  let result;
26456
26491
  try {
26457
26492
  result = await cloudbase.hosting.deleteFiles({
26458
- cloudPath: input.cloudPath,
26493
+ cloudPath: normalizedCloudPath,
26459
26494
  isDir: input.isDir ?? false,
26460
26495
  });
26461
26496
  }
@@ -26477,7 +26512,7 @@ function registerHostingTools(server) {
26477
26512
  }
26478
26513
  try {
26479
26514
  const checkResult = await cloudbase.hosting.findFiles({
26480
- prefix: input.cloudPath,
26515
+ prefix: normalizedCloudPath,
26481
26516
  maxKeys: 100,
26482
26517
  });
26483
26518
  // ⚠️ 回查有两个坑,都会让 verified 失真:
@@ -26488,8 +26523,7 @@ function registerHostingTools(server) {
26488
26523
  // /a/b.txt.bak 还在也会命中 → 把「已删成功」误判成未验证。
26489
26524
  // 单文件场景必须精确比对 Key(前缀场景见 normalizeFileFields 的 key 字段)。
26490
26525
  const remaining = normalizeFileFields(checkResult);
26491
- const stripLeadingSlash = (value) => value.replace(/^\/+/, '');
26492
- const targetPath = stripLeadingSlash(input.cloudPath ?? '');
26526
+ const targetPath = normalizedCloudPath;
26493
26527
  const stillExists = input.isDir
26494
26528
  ? remaining.length > 0
26495
26529
  : remaining.some((file) => {
@@ -26497,7 +26531,7 @@ function registerHostingTools(server) {
26497
26531
  // 拿不到 Key 时保守按「仍存在」处理,避免误报已验证
26498
26532
  if (!key)
26499
26533
  return true;
26500
- return stripLeadingSlash(key) === targetPath;
26534
+ return stripLeadingSlashes(key) === targetPath;
26501
26535
  });
26502
26536
  if (stillExists) {
26503
26537
  deleteVerified = false;
@@ -26523,7 +26557,11 @@ function registerHostingTools(server) {
26523
26557
  type: input.isDir ? (0, index_js_1.t)('hosting.typeDirectory') : (0, index_js_1.t)('hosting.typeFile'),
26524
26558
  cloudPath: input.cloudPath,
26525
26559
  })
26526
- : (0, index_js_1.t)('hosting.deleteUnverified', { cloudPath: input.cloudPath }),
26560
+ // 这里刻意插入规范化后的路径:该文案的 {cloudPath} 会被拼进
26561
+ // `queryHosting(action="findFiles", prefix="{cloudPath}")` 自查命令里,
26562
+ // 带前导斜杠的前缀在 COS 侧严格匹配不到任何对象,agent 照抄会得到
26563
+ // 「0 命中 ⇒ 看起来删干净了」的错误结论。
26564
+ : (0, index_js_1.t)('hosting.deleteUnverified', { cloudPath: normalizedCloudPath }),
26527
26565
  });
26528
26566
  }
26529
26567
  case 'setWebsiteDocument': {
@@ -26761,7 +26799,8 @@ function registerLogTools(server) {
26761
26799
  },
26762
26800
  annotations: {
26763
26801
  readOnlyHint: true,
26764
- openWorldHint: true,
26802
+ destructiveHint: false,
26803
+ openWorldHint: false,
26765
26804
  category: "logs",
26766
26805
  },
26767
26806
  }, async ({ action, queryString, service, startTime, endTime, limit, context, sort, }) => {
@@ -27310,7 +27349,8 @@ function registerMsgPushTools(server) {
27310
27349
  },
27311
27350
  annotations: {
27312
27351
  readOnlyHint: true,
27313
- openWorldHint: true,
27352
+ destructiveHint: false,
27353
+ openWorldHint: false,
27314
27354
  category: CATEGORY,
27315
27355
  },
27316
27356
  }, async ({ appid, env, action }) => {
@@ -27455,7 +27495,7 @@ function registerMsgPushTools(server) {
27455
27495
  readOnlyHint: false,
27456
27496
  destructiveHint: true,
27457
27497
  idempotentHint: true,
27458
- openWorldHint: true,
27498
+ openWorldHint: false,
27459
27499
  category: CATEGORY,
27460
27500
  },
27461
27501
  }, async ({ appid, env_id, function_name, action, msg_type, event_types, enable, qbase_container_path, qbase_env, text_mode, confirm, }) => {
@@ -28324,7 +28364,8 @@ function registerPermissionTools(server) {
28324
28364
  },
28325
28365
  annotations: {
28326
28366
  readOnlyHint: true,
28327
- openWorldHint: true,
28367
+ destructiveHint: false,
28368
+ openWorldHint: false,
28328
28369
  category: "permissions",
28329
28370
  },
28330
28371
  }, async ({ action, resourceType, resourceId, resourceIds, roleId, roleIdentity, roleName, uid, username, pageNo, pageSize, extension, policyResourceType, }) => withEnvelope(async () => {
@@ -28553,7 +28594,7 @@ function registerPermissionTools(server) {
28553
28594
  readOnlyHint: false,
28554
28595
  destructiveHint: true,
28555
28596
  idempotentHint: false,
28556
- openWorldHint: true,
28597
+ openWorldHint: false,
28557
28598
  category: "permissions",
28558
28599
  },
28559
28600
  }, async ({ action, resourceType, resourceId, permission, securityRule, roleId, roleIds, roleName, roleIdentity, description, memberUids, policies, policyIds, uid, uids, username, password, userStatus, regoContent, confirm, }) => withEnvelope(async () => {
@@ -29299,16 +29340,7 @@ async function registerRagTools(server) {
29299
29340
  title: "rag.title",
29300
29341
  description: (0, index_js_1.t)("rag.description", {
29301
29342
  skillCount: skills.length,
29302
- skillList: skills
29303
- .map((skill) => (0, index_js_1.t)("rag.skillListItem", {
29304
- name: path.basename(path.dirname(skill.absolutePath)),
29305
- description: skill.description,
29306
- }))
29307
- .join("\n"),
29308
29343
  openapiCount: openapis.length,
29309
- openapiList: openapis
29310
- .map((api) => (0, index_js_1.t)("rag.openapiListItem", { name: api.name, description: api.description }))
29311
- .join("\n"),
29312
29344
  }),
29313
29345
  inputSchema: {
29314
29346
  mode: SearchKnowledgeModeEnum,
@@ -29334,6 +29366,7 @@ async function registerRagTools(server) {
29334
29366
  },
29335
29367
  annotations: {
29336
29368
  readOnlyHint: true,
29369
+ destructiveHint: false,
29337
29370
  openWorldHint: true,
29338
29371
  category: "rag",
29339
29372
  },
@@ -29385,6 +29418,16 @@ async function registerRagTools(server) {
29385
29418
  }
29386
29419
  }
29387
29420
  if (mode === "skill") {
29421
+ // 不传 skillName:返回带适用场景的完整目录,让调用方按需发现后再取正文
29422
+ if (!skillName?.trim()) {
29423
+ return (0, json_content_js_1.jsonContent)([
29424
+ (0, index_js_1.t)("rag.skillCatalogHeader", { count: skillNames.length }),
29425
+ ...skills.map((item) => (0, index_js_1.t)("rag.skillListItem", {
29426
+ name: path.basename(path.dirname(item.absolutePath)),
29427
+ description: item.description,
29428
+ })),
29429
+ ].join("\n"));
29430
+ }
29388
29431
  const skill = skills.find((item) => item.absolutePath.includes(skillName));
29389
29432
  if (!skill) {
29390
29433
  const remoteHint = skillName?.trim()
@@ -29435,6 +29478,15 @@ async function registerRagTools(server) {
29435
29478
  return { content: [{ type: "text", text: sections.join("\n\n") }] };
29436
29479
  }
29437
29480
  if (mode === "openapi") {
29481
+ if (!apiName?.trim()) {
29482
+ return (0, json_content_js_1.jsonContent)([
29483
+ (0, index_js_1.t)("rag.openapiCatalogHeader", { count: openapiNames.length }),
29484
+ ...openapis.map((api) => (0, index_js_1.t)("rag.openapiListItem", {
29485
+ name: api.name,
29486
+ description: api.description,
29487
+ })),
29488
+ ].join("\n"));
29489
+ }
29438
29490
  const api = openapis.find((api) => api.name === apiName);
29439
29491
  if (!api) {
29440
29492
  return {
@@ -29491,7 +29543,7 @@ function extractDescriptionFromFrontMatter(content) {
29491
29543
  fm.push(lines[i]);
29492
29544
  const match = fm
29493
29545
  .join("\n")
29494
- .match(/^(?:decsription|description)\s*:\s*(.*)$/m);
29546
+ .match(/^description\s*:\s*(.*)$/m);
29495
29547
  return match ? match[1].trim() : null;
29496
29548
  }
29497
29549
  async function collectSkillDescriptions(rootDir) {
@@ -30457,7 +30509,8 @@ function registerStorageTools(server) {
30457
30509
  inputSchema: queryStorageInputSchema,
30458
30510
  annotations: {
30459
30511
  readOnlyHint: true,
30460
- openWorldHint: true,
30512
+ destructiveHint: false,
30513
+ openWorldHint: false,
30461
30514
  category: "storage"
30462
30515
  }
30463
30516
  }, async (args) => {
@@ -30637,7 +30690,7 @@ function registerStorageTools(server) {
30637
30690
  readOnlyHint: false,
30638
30691
  destructiveHint: true,
30639
30692
  idempotentHint: false,
30640
- openWorldHint: true,
30693
+ openWorldHint: false,
30641
30694
  category: "storage"
30642
30695
  }
30643
30696
  }, async (args) => {
@@ -31107,7 +31160,8 @@ function registerPGStorageTools(server) {
31107
31160
  },
31108
31161
  annotations: {
31109
31162
  readOnlyHint: true,
31110
- openWorldHint: true,
31163
+ destructiveHint: false,
31164
+ openWorldHint: false,
31111
31165
  category: CATEGORY,
31112
31166
  },
31113
31167
  }, async (args) => {
@@ -32354,7 +32408,7 @@ exports.SITE_REGION_MAP = {
32354
32408
  },
32355
32409
  };
32356
32410
  exports.dB = Object.keys(exports.SITE_REGION_MAP);
32357
- /** Regions accepted by envQuery(list) / cross-region DescribeEnvs probes. */
32411
+ /** Regions accepted by queryEnv(list) / cross-region DescribeEnvs probes. */
32358
32412
  exports.TCB_QUERY_REGIONS = [
32359
32413
  "ap-shanghai",
32360
32414
  "ap-guangzhou",
@@ -32724,7 +32778,7 @@ class TelemetryReporter {
32724
32778
  const arch = os_1.default.arch(); // 系统架构
32725
32779
  // Build-time injected version; guard for vitest / non-webpack runtimes.
32726
32780
  const mcpVersion = process.env.npm_package_version ||
32727
- ( true ? "2.34.3" : 0);
32781
+ ( true ? "2.34.4" : 0);
32728
32782
  return {
32729
32783
  userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
32730
32784
  deviceId: this.deviceId,
@@ -33342,7 +33396,7 @@ ${envIdSection}
33342
33396
  ## 环境信息
33343
33397
  - 操作系统: ${os_1.default.type()} ${os_1.default.release()}
33344
33398
  - Node.js版本: ${process.version}
33345
- - MCP 版本:${( true ? "2.34.3" : 0) || 0 || 0}
33399
+ - MCP 版本:${( true ? "2.34.4" : 0) || 0 || 0}
33346
33400
  - 系统架构: ${os_1.default.arch()}
33347
33401
  - 时间: ${new Date().toISOString()}
33348
33402
  - 请求ID: ${requestId}
@@ -33431,7 +33485,7 @@ function createWrappedHandler(name, handler, server) {
33431
33485
  requestId,
33432
33486
  ide: server.ide || process.env.INTEGRATION_IDE || ''
33433
33487
  });
33434
- const mcpVersion = true ? "2.34.3" : 0;
33488
+ const mcpVersion = true ? "2.34.4" : 0;
33435
33489
  const requestIdSuffix = requestId ? `\n🆔 RequestId: ${requestId}` : '';
33436
33490
  const enhancedErrorMessage = `${errorMessage}${requestIdSuffix}\n\n📦 CloudBase MCP v${mcpVersion}\n🔗 遇到问题?请复制以下链接到浏览器打开\n即可自动携带错误详情快速创建 GitHub Issue:\n${issueLink}`;
33437
33491
  // 创建新的错误对象,保持原有的错误类型但更新消息