diff --git a/docs/devapp-yulan-command-routing.md b/docs/devapp-yulan-command-routing.md index 4f95c984..6f0a2f69 100644 --- a/docs/devapp-yulan-command-routing.md +++ b/docs/devapp-yulan-command-routing.md @@ -128,13 +128,13 @@ Do not send confirmation fields such as `confirmCreate`, `confirmUpdate`, `confi | Area | CLI command | MCP tool | Backend HSF facade | Current backend status | Open-source DWS status | | --- | --- | --- | --- | --- | --- | -| App query | `devapp list` | `list_open_dev_apps_by_condition` | `OpenInnerAppQueryFacade.listByCondition` | Implemented | Hardcoded helper | -| App detail | `devapp get` | `get_open_dev_app_detail` | `OpenInnerAppQueryFacade.getDetail` | Implemented | Hardcoded helper | -| App create | `devapp create` | `create_inner_app` | `OpenInnerAppManageFacade.create` | Implemented | Hardcoded helper | -| App update | `devapp update` | `update_inner_app` | `OpenInnerAppManageFacade.update` | Implemented | Hardcoded helper | -| App delete | `devapp delete` | `delete_inner_app` | `OpenInnerAppManageFacade.delete` | Implemented | Hardcoded helper | +| App query | `devapp list` | `list_open_dev_app` | `OpenInnerAppQueryFacade.listByCondition` | Implemented | Hardcoded helper | +| App detail | `devapp get` | `get_dev_app` | `OpenInnerAppQueryFacade.getDetail` | Implemented | Hardcoded helper | +| App create | `devapp create` | `create_dev_app` | `OpenInnerAppManageFacade.create` | Implemented | Hardcoded helper | +| App update | `devapp update` | `update_dev_app` | `OpenInnerAppManageFacade.update` | Implemented | Hardcoded helper | +| App delete | `devapp delete` | `delete_dev_app` | `OpenInnerAppManageFacade.delete` | Implemented | Hardcoded helper | | Credentials | `devapp credentials get` | `get_open_dev_app_credentials` | `OpenInnerAppQueryFacade.getCredentials` | Implemented | Hardcoded helper | -| Web app | `devapp webapp get/config` | `get_webapp_config`/`set_webapp_config` | Webapp facade | Implemented | Hardcoded helper; verified `config` then `get` returns `agentId/h5PageType/homepageLink/pcHomepageLink/ompLink`; before config, `get` may only return `agentId`. | +| Web app | `devapp webapp get/config` | `get_webapp_config`/`set_webapp_config` | Webapp facade | Implemented | Hardcoded helper; locator fields are `unifiedAppId/appKey`; config fields are `h5PageType/homepageUrl/pcHomepageUrl/ompUrl`. | | Permission list | `devapp permission list/search/detail` | `list_open_dev_app_permissions` | `OpenInnerAppPermissionFacade.list` | Implemented | Hardcoded helper | | Permission apply | `devapp permission add` | `apply_open_dev_app_permissions` | `OpenInnerAppPermissionFacade.apply` | Implemented | Hardcoded helper | | Permission remove | `devapp permission remove` | `remove_open_dev_app_permission` | `OpenInnerAppPermissionFacade.remove` | Implemented | Hardcoded helper | @@ -179,36 +179,34 @@ MCP output configuration should keep the wrapper fields and configure success as `ServiceResult.success == true`. DWS/Agent normalization can add `ok`, `reason`, `summary`, and `nextAction`, but raw `errorCode/errorMsg` must remain visible. +Naming convention: + +- Public CLI flags use user-facing names: `--name`, `--desc`, `--icon`, `--homepage-url`. +- MCP app create/update currently keep backend request field names: `appName`, `appDesc`, `appIcon`. +- MCP app list/detail use the simplified locator/search fields: `unifiedAppId`, `appKey`, `name`. +- The CLI helper owns the translation, for example `--name` -> `appName` for create/update and + `--name` -> `name` for list/detail. + ### 3.2 P0 Tool Contracts -#### list_open_dev_apps_by_condition +#### list_open_dev_app | Item | Contract | | --- | --- | | CLI | `dws devapp list` | | HSF facade | `OpenInnerAppQueryFacade.listByCondition` | | Request shape | One object with system context and optional list filters. | -| Required public fields | None; default `currentPage=1`, `pageSize=20`. | +| Required public fields | None; default `pageSize=20`. | | Identity source | `corpId/userId` from MCP system context. | Input fields: | Field | Type | CLI flag | Required | Notes | | --- | --- | --- | --- | --- | -| `currentPage` | number | `--page` | no | 1-based page number. | | `pageSize` | number | `--page-size` | no | Default 20; cap by backend. | -| `appName` | string | `--name` | no | App name keyword. | -| `agentId` | number | `--agent-id` | no | Exact DingTalk app agentId. | -| `appId` | number | `--app-id` | no | Compatible app id. | +| `cursor` | string | `--cursor` | no | Cursor from previous response; empty for first page. | +| `name` | string | `--name` | no | App name keyword. | | `appKey` | string | `--app-key` | no | DingTalk appKey/clientId. | -| `customKey` | string | `--custom-key` | no | Custom key. | -| `appGroupId` | number | `--app-group-id` | no | App group id. | -| `creator` | string | `--creator` | no | Creator name keyword. | -| `robotName` | string | `--robot-name` | no | Bot name keyword. | -| `developType` | number/string | `--develop-type` | no | Use backend enum if schema exposes one. | -| `filterCoolApp` | number/boolean | `--filter-cool-app` | no | Only expose when backend semantics are documented. | -| `sortType` | string | `--sort` | no | Example: `gmt_modified`. | -| `sortOrder` | string | `--order` | no | `asc` or `desc`. | Normalized response: @@ -216,15 +214,12 @@ Normalized response: { "ok": true, "operation": "app.list", - "page": {"currentPage": 1, "pageSize": 20, "total": 0}, + "page": {"pageSize": 20, "nextCursor": ""}, "apps": [ { "unifiedAppId": "UNIFIED_APP_ID", - "appName": "DemoApp", - "agentId": 123456, - "appId": 123, + "name": "DemoApp", "appKey": "dingxxx", - "customKey": "custom-key", "creator": "Creator", "robotName": "BotName", "gmtModified": "2026-06-05T00:00:00+08:00" @@ -234,7 +229,7 @@ Normalized response: } ``` -#### get_open_dev_app_detail +#### get_dev_app | Item | Contract | | --- | --- | @@ -249,11 +244,8 @@ Locator fields: | Field | Type | CLI flag | Notes | | --- | --- | --- | --- | | `unifiedAppId` | string | `--unified-app-id` | Preferred. | -| `agentId` | number | `--agent-id` | Exact id. | -| `appId` | number | `--app-id` | Compatible id. | | `appKey` | string | `--app-key` | appKey/clientId. | -| `customKey` | string | `--custom-key` | Custom key. | -| `appName` | string | `--name` | Fuzzy; must resolve uniquely before writes. | +| `name` | string | `--name` | Fuzzy; must resolve uniquely before writes. | Detail response should include identifiers and configuration summary, but not full `clientSecret/appSecret`: @@ -264,11 +256,8 @@ full `clientSecret/appSecret`: "operation": "app.get", "app": { "unifiedAppId": "UNIFIED_APP_ID", - "appName": "DemoApp", - "agentId": 123456, - "appId": 123, + "name": "DemoApp", "appKey": "dingxxx", - "customKey": "custom-key", "developType": "internal", "creator": "Creator", "visibility": "partial_members", @@ -279,7 +268,7 @@ full `clientSecret/appSecret`: } ``` -#### create_inner_app +#### create_dev_app | Item | Contract | | --- | --- | @@ -305,8 +294,7 @@ Response: "operation": "app.create", "app": { "unifiedAppId": "UNIFIED_APP_ID", - "appName": "DemoApp", - "agentId": 123456, + "name": "DemoApp", "appKey": "dingxxx" }, "nextAction": "run devapp get or configure permissions", @@ -314,7 +302,7 @@ Response: } ``` -#### update_inner_app +#### update_dev_app | Item | Contract | | --- | --- | @@ -324,7 +312,7 @@ Response: | Required public fields | One app locator and at least one changed field. | | Write guard | CLI `--dry-run`, then `--yes`; no MCP confirm field. | -Locator fields are the same as `get_open_dev_app_detail`, but the Agent should +Locator fields are the same as `get_dev_app`, but the Agent should prefer `unifiedAppId` after resolving a unique app. Update fields: @@ -340,7 +328,7 @@ Update fields: Response should return the updated app summary plus a `changedFields` array when available. -#### delete_inner_app +#### delete_dev_app | Item | Contract | | --- | --- | @@ -361,21 +349,21 @@ backend fields. | CLI | `dws devapp permission list/search/detail` | | HSF facade | `OpenInnerAppPermissionFacade.list` | | Request shape | One object with system context, app locator, and optional filters. | -| Required public fields | One app locator. | +| Required public fields | `unifiedAppId`. | | Web semantics | Equivalent to grouped `scope/list` for APP and SNS scopes. | Input fields: | Field | Type | CLI flag | Required | Notes | | --- | --- | --- | --- | --- | -| `unifiedAppId` | string | `--unified-app-id` | one locator | Preferred. | -| `agentId` | number | `--agent-id` | one locator | Compatible. | +| `unifiedAppId` | string | `--unified-app-id` | yes | Unified app id. | | `keyword` | string | `--keyword` | no | Maps to Web `key`. | | `apiStatus` | string | `--api-status` | no | Web `apiStatus` filter. | | `authStatus` | string | `--status` | no | `ALL/AUTHED/UNAUTHED`, post-filter. | -| `firstLevelType` | string | `--scope-type` | no | `APP/SNS`; empty returns both. | +| `scopeType` | string | `--scope-type` | no | `APP/SNS`; empty returns both. | | `scopeValue` | string | `--scope` | no | Detail mode and exact post-filter. | -| `limit` | number | `--limit` | no | Agent display cap; no server pagination. | +| `pageSize` | number | `--page-size` | no | Return count cap; default 20. | +| `cursor` | string | `--cursor` | no | Cursor from previous response; empty for first page. | Normalized response should flatten `appScopes` and `snsScopes` into one `permissions[]` list while preserving group metadata: @@ -389,7 +377,7 @@ Normalized response should flatten `appScopes` and `snsScopes` into one { "scopeValue": "qyapi_robot_sendmsg", "scopeName": "企业内机器人发消息权限", - "firstLevelType": "APP", + "scopeType": "APP", "categoryTitle": "机器人", "authed": true, "canEdit": true, @@ -400,7 +388,7 @@ Normalized response should flatten `appScopes` and `snsScopes` into one } ], "summary": {"totalMatched": 1, "returnedCount": 1}, - "truncated": false, + "nextCursor": "", "raw": {} } ``` @@ -412,15 +400,14 @@ Normalized response should flatten `appScopes` and `snsScopes` into one | CLI | `dws devapp permission add` | | HSF facade | `OpenInnerAppPermissionFacade.apply` | | Request shape | One object with system context, app locator, and `scopeValues`. | -| Required public fields | One app locator and non-empty `scopeValues`. | +| Required public fields | `unifiedAppId` and non-empty `scopeValues`. | | Write guard | CLI `--dry-run`, then `--yes`; no MCP confirm field. | Input fields: | Field | Type | CLI flag | Required | Notes | | --- | --- | --- | --- | --- | -| `unifiedAppId` | string | `--unified-app-id` | one locator | Preferred. | -| `agentId` | number | `--agent-id` | one locator | Compatible. | +| `unifiedAppId` | string | `--unified-app-id` | yes | Unified app id. | | `scopeValues` | string[] | `--permissions` | yes | Comma-separated in CLI; must come from list response. | Response must distinguish direct apply, version-staged apply, rejected scopes, and @@ -450,15 +437,14 @@ current app version. Approver selection is handled by the version flow. | CLI | `dws devapp permission remove` | | HSF facade | `OpenInnerAppPermissionFacade.remove` | | Request shape | One object with system context, app locator, and one `scopeValue`. | -| Required public fields | One app locator and one `scopeValue`. | +| Required public fields | `unifiedAppId` and one `scopeValue`. | | Write guard | CLI `--dry-run`, then `--yes`; no MCP confirm field. | Input fields: | Field | Type | CLI flag | Required | Notes | | --- | --- | --- | --- | --- | -| `unifiedAppId` | string | `--unified-app-id` | one locator | Preferred. | -| `agentId` | number | `--agent-id` | one locator | Compatible. | +| `unifiedAppId` | string | `--unified-app-id` | yes | Unified app id. | | `scopeValue` | string | `--permission` | yes | Remove exactly one permission. | Expected structured failures: @@ -498,36 +484,26 @@ Tool override examples: ```json { "toolOverrides": { - "list_open_dev_apps_by_condition": { + "list_open_dev_app": { "cliName": "list", "description": "查询开放平台企业内部应用列表", "flags": { - "currentPage": {"alias": "page", "default": 1}, "pageSize": {"alias": "page-size", "default": 20}, - "appName": {"alias": "name"}, - "agentId": {"alias": "agent-id"}, - "appId": {"alias": "app-id"}, - "appKey": {"alias": "app-key"}, - "customKey": {"alias": "custom-key"}, - "creator": {"alias": "creator"}, - "robotName": {"alias": "robot-name"}, - "sortType": {"alias": "sort"}, - "sortOrder": {"alias": "order"} + "cursor": {"alias": "cursor"}, + "name": {"alias": "name"}, + "appKey": {"alias": "app-key"} } }, - "get_open_dev_app_detail": { + "get_dev_app": { "cliName": "get", "description": "查询开放平台企业内部应用详情", "flags": { "unifiedAppId": {"alias": "unified-app-id"}, - "agentId": {"alias": "agent-id"}, - "appId": {"alias": "app-id"}, "appKey": {"alias": "app-key"}, - "customKey": {"alias": "custom-key"}, - "appName": {"alias": "name"} + "name": {"alias": "name"} } }, - "create_inner_app": { + "create_dev_app": { "cliName": "create", "description": "创建开放平台企业内部应用", "isSensitive": true, @@ -537,35 +513,26 @@ Tool override examples: "appIcon": {"alias": "icon"} } }, - "update_inner_app": { + "update_dev_app": { "cliName": "update", "description": "修改开放平台企业内部应用基础信息", "isSensitive": true, "flags": { "unifiedAppId": {"alias": "unified-app-id"}, - "agentId": {"alias": "agent-id"}, - "appId": {"alias": "app-id"}, "appKey": {"alias": "app-key"}, - "customKey": {"alias": "custom-key"}, - "currentAppName": {"alias": "current-name"}, "appName": {"alias": "name"}, "appDesc": {"alias": "desc"}, - "appIcon": {"alias": "icon"}, - "international": {"alias": "international"}, - "supportHarmony": {"alias": "support-harmony", "type": "bool"} + "appIcon": {"alias": "icon"} } }, - "delete_inner_app": { + "delete_dev_app": { "cliName": "delete", "description": "删除开放平台企业内部应用", "isSensitive": true, "flags": { "unifiedAppId": {"alias": "unified-app-id"}, - "agentId": {"alias": "agent-id"}, - "appId": {"alias": "app-id"}, - "appName": {"alias": "name"}, "appKey": {"alias": "app-key"}, - "customKey": {"alias": "custom-key"} + "name": {"alias": "name"} } }, "list_open_dev_app_permissions": { @@ -574,13 +541,13 @@ Tool override examples: "description": "查询开放平台应用权限列表,默认同时返回 APP 应用权限和 SNS 个人权限", "flags": { "unifiedAppId": {"alias": "unified-app-id"}, - "agentId": {"alias": "agent-id"}, "keyword": {"alias": "keyword"}, "apiStatus": {"alias": "api-status"}, "authStatus": {"alias": "status", "default": "ALL"}, - "firstLevelType": {"alias": "scope-type"}, + "scopeType": {"alias": "scope-type"}, "scopeValue": {"alias": "scope"}, - "limit": {"alias": "limit", "default": "20"} + "pageSize": {"alias": "page-size", "default": "20"}, + "cursor": {"alias": "cursor"} } }, "apply_open_dev_app_permissions": { @@ -590,7 +557,6 @@ Tool override examples: "isSensitive": true, "flags": { "unifiedAppId": {"alias": "unified-app-id"}, - "agentId": {"alias": "agent-id"}, "scopeValues": { "alias": "permissions", "type": "stringSlice", @@ -606,7 +572,6 @@ Tool override examples: "isSensitive": true, "flags": { "unifiedAppId": {"alias": "unified-app-id"}, - "agentId": {"alias": "agent-id"}, "scopeValue": { "alias": "permission", "required": true, @@ -639,16 +604,14 @@ Application identity must be resolved before detail and write commands. | Priority | Identifier | Rule | | --- | --- | --- | | 1 | `unifiedAppId` | Preferred unique id for write operations. | -| 2 | `agentId/appId` | Compatible exact identifier. | -| 3 | `appKey/clientId` | Call list/detail and require one result. | -| 4 | `customKey` | Call list/detail and require one result. | -| 5 | `appName/name` | Fuzzy search; write operations require one result. | +| 2 | `appKey/clientId` | Call list/detail and require one result. | +| 3 | `name` | Fuzzy search; write operations require one result. | Agent rule: 1. Never choose the first row when multiple apps match. -2. Show candidates with `appName`, `unifiedAppId`, `agentId`, `appKey/clientId`, `creator`, and modified time. -3. Ask the user to pick `unifiedAppId` or `agentId` for write operations. +2. Show candidates with `name`, `unifiedAppId`, `appKey/clientId`, `creator`, and modified time. +3. Ask the user to pick `unifiedAppId` for write operations when multiple apps match. MCP calls must rely on system context for caller identity: @@ -666,31 +629,26 @@ Open-source DWS and Agent must not pass `orgId` or `uid` as user input. ```bash dws devapp list --page 1 --page-size 20 --format json dws devapp list --name DemoApp --format json -dws devapp list --agent-id AGENT_ID --format json dws devapp list --app-key dingxxx --format json -dws devapp list --creator 张三 --format json -dws devapp list --robot-name 小钉 --format json +dws devapp list --page-size 20 --cursor NEXT_CURSOR --format json ``` MCP payload: ```json { - "currentPage": 1, "pageSize": 20, - "appName": "DemoApp", - "sortType": "gmt_modified", - "sortOrder": "desc" + "name": "DemoApp" } ``` -Pagination is supported for app list through `currentPage/pageSize`, both 1-based. Search filters are optional. A baseline call should pass only pagination and sort fields. +Pagination is cursor based. A baseline call should pass only `pageSize`; use the response `nextCursor` for the next page. ### 6.2 Get ```bash dws devapp get --unified-app-id UNIFIED_APP_ID --format json -dws devapp get --agent-id AGENT_ID --format json +dws devapp get --app-key dingxxx --format json dws devapp get --name DemoApp --format json ``` @@ -702,7 +660,7 @@ MCP payload: } ``` -`get` may show `clientId/appKey/agentId`, but it must not be used to read full `clientSecret/appSecret`. Secret read belongs to `credentials get`. +`get` may show `clientId/appKey`, but it must not be used to read full `clientSecret/appSecret`. Secret read belongs to `credentials get`. ### 6.3 Create @@ -764,7 +722,7 @@ MCP payload: } ``` -Valid locator fields are `unifiedAppId`, `agentId`, `appId`, `appName`, `appKey`, and `customKey`. Name/key locators must uniquely resolve. +Valid public locator fields are `unifiedAppId`, `appKey`, and `name`. Name/key locators must uniquely resolve. ## 7. Credentials @@ -772,7 +730,8 @@ Target command: ```bash dws devapp credentials get --unified-app-id UNIFIED_APP_ID --format json -dws devapp credentials get --agent-id AGENT_ID --format json +dws devapp credentials get --app-key dingxxx --format json +dws devapp credentials get --name DemoApp --format json ``` Current status: @@ -786,7 +745,7 @@ Target fields: | Field | Notes | | --- | --- | -| `unifiedAppId/agentId/appName` | App summary. | +| `unifiedAppId/name` | App summary. | | `clientId/appKey` | Non-secret identifiers. | | `clientSecret/appSecret` | Returned by the dedicated credentials tool; treat as sensitive output. | | `currentSecretStatus` | Current secret state. | @@ -809,10 +768,10 @@ Returned groups: "success": true, "data": { "snsScopes": [ - {"title": "个人权限", "firstLevelType": "SNS", "scopeList": []} + {"title": "个人权限", "scopeType": "SNS", "scopeList": []} ], "appScopes": [ - {"title": "通讯录管理", "firstLevelType": "APP", "scopeList": []} + {"title": "通讯录管理", "scopeType": "APP", "scopeList": []} ] } } @@ -835,7 +794,7 @@ MCP payload for normal list: { "unifiedAppId": "UNIFIED_APP_ID", "authStatus": "ALL", - "limit": 20 + "pageSize": 20 } ``` @@ -846,7 +805,7 @@ MCP payload for search: "unifiedAppId": "UNIFIED_APP_ID", "keyword": "机器人发送消息", "authStatus": "UNAUTHED", - "limit": 10 + "pageSize": 10 } ``` @@ -856,7 +815,7 @@ MCP payload for detail: { "unifiedAppId": "UNIFIED_APP_ID", "scopeValue": "qyapi_robot_sendmsg", - "limit": 1 + "pageSize": 1 } ``` @@ -864,16 +823,16 @@ Input fields: | Field | Type | Required | Notes | | --- | --- | --- | --- | -| `unifiedAppId` | string | one of app id fields | Preferred app locator. | -| `agentId` | number | one of app id fields | Compatible app locator. | +| `unifiedAppId` | string | yes | Unified app id. | | `keyword` | string | no | Maps to Web `key`. | | `apiStatus` | string | no | Maps to Web `apiStatus`. | | `authStatus` | string | no | `ALL/AUTHED/UNAUTHED`, post-filter. | -| `firstLevelType` | string | no | `APP/SNS`; empty returns both. | +| `scopeType` | string | no | `APP/SNS`; empty returns both. | | `scopeValue` | string | no | Detail mode and exact post-filter. | -| `limit` | number | no | Default 20, hard cap 50. | +| `pageSize` | number | no | Default 20, hard cap 50. | +| `cursor` | string | no | Cursor from previous response; empty for first page. | -Permission list has no server pagination. Web also loads the full grouped list. Use `keyword` to reduce server-side results, then use `limit` to control Agent context. +Permission list uses cursor pagination. Use `keyword` to reduce server-side results and `pageSize/cursor` to control Agent context. Default response must flatten APP and SNS scopes into one stable `permissions[]` array: @@ -885,7 +844,7 @@ Default response must flatten APP and SNS scopes into one stable `permissions[]` "scopeValue": "qyapi_robot_sendmsg", "scopeName": "企业内机器人发消息权限", "scopeDesc": "企业内机器人发消息权限", - "firstLevelType": "APP", + "scopeType": "APP", "categoryTitle": "机器人", "authed": true, "canEdit": true, @@ -918,7 +877,7 @@ Default response must flatten APP and SNS scopes into one stable `permissions[]` { "scopeValue": "Contact.User.mobile", "scopeName": "个人手机号信息", - "firstLevelType": "SNS", + "scopeType": "SNS", "authed": false, "canEdit": true, "requiredApproval": true, @@ -933,7 +892,7 @@ Agent selection order: 1. Exact `scopeValue`. 2. Matched `apiList[].name`. 3. Scope name or description. -4. Category title and `firstLevelType`. +4. Category title and `scopeType`. Agent must pass final `scopeValue` to add/remove. Do not pass API name, API uuid, or category title into write tools. @@ -1074,7 +1033,7 @@ Positive `devapp` signals: | Signal | Route | | --- | --- | | `开放平台应用`, `开发者后台应用`, `企业内部应用`, `内部应用` | `devapp` | -| `agentId`, `clientId`, `appKey`, `customKey`, `appSecret`, `clientSecret` | `devapp` | +| `unifiedAppId`, `clientId`, `appKey`, `appSecret`, `clientSecret` | `devapp` | | `应用权限`, `权限点`, `API 权限`, `APP/SNS 权限`, `scopeValue` | `devapp permission ...` | | `事件订阅`, `订阅事件`, `退订事件`, `eventCode`, `可订阅事件` in an app context | `devapp event ...` | | `应用版本`, `版本发布`, `选审批人`, `发布审核` in developer backend context | `devapp version ...` | @@ -1120,11 +1079,11 @@ Intent table: | User intent | Command | Tool | | --- | --- | --- | -| "查应用/搜索应用" | `devapp list` | `list_open_dev_apps_by_condition` | -| "看应用详情/clientId/agentId" | `devapp get` | `get_open_dev_app_detail` | -| "创建应用" | `devapp create` | `create_inner_app` | -| "修改名称/描述/图标" | `devapp update` | `update_inner_app` | -| "删除应用" | `devapp delete` | `delete_inner_app` | +| "查应用/搜索应用" | `devapp list` | `list_open_dev_app` | +| "看应用详情/clientId/appKey" | `devapp get` | `get_dev_app` | +| "创建应用" | `devapp create` | `create_dev_app` | +| "修改名称/描述/图标" | `devapp update` | `update_dev_app` | +| "删除应用" | `devapp delete` | `delete_dev_app` | | "查权限/搜索 API 权限" | `permission list` | `list_open_dev_app_permissions` | | "这个权限覆盖哪些 API" | `permission list --scope` | `list_open_dev_app_permissions` | | "申请权限/开通权限" | `permission add` | `apply_open_dev_app_permissions` | @@ -1217,7 +1176,7 @@ Do not add confirmation booleans to MCP payloads. These belong to the CLI layer: | User request | Agent recipe | | --- | --- | | "查 DemoApp 应用" | `devapp list --name DemoApp`; if one result, optionally `devapp get`; if multiple, show candidates. | -| "这个 agentId 是哪个应用" | `devapp get --agent-id AGENT_ID`; if backend requires list semantics, use `devapp list --agent-id AGENT_ID`. | +| "这个 appKey 是哪个应用" | `devapp get --app-key APP_KEY`; if multiple apps match, ask for `unifiedAppId`. | | "创建企业内部应用" | `devapp create --name ... --type internal --dry-run`; after confirmation, repeat with `--yes`. | | "修改应用描述/图标" | Resolve `unifiedAppId`; `devapp update --unified-app-id ... --desc/icon ... --dry-run`; after confirmation, `--yes`. | | "删除应用" | Resolve unique app; show app summary; `devapp delete ... --dry-run`; after confirmation, `--yes`. | @@ -1237,9 +1196,9 @@ writing: 2. If the user gives an API name, search with `keyword`, then match `apiList[].name` or `apiPreview.name`. 3. If the user gives a human permission name, match `scopeName/scopeDesc`. -4. If multiple scopes remain, show `scopeValue`, `scopeName`, `firstLevelType`, +4. If multiple scopes remain, show `scopeValue`, `scopeName`, `scopeType`, `authed`, `requiredApproval`, and `apiPreview`, then ask for one. -5. For list output, cap the displayed list with `limit`; for detail output, call +5. For list output, cap the displayed list with `pageSize`; for detail output, call with `scopeValue` and return the full API coverage for one scope only. `requiredApproval=true` is not a blocker for permission add. It means the add @@ -1279,8 +1238,7 @@ details: "operation": "permission.add", "app": { "unifiedAppId": "UNIFIED_APP_ID", - "agentId": 123456, - "appName": "DemoApp" + "name": "DemoApp" }, "summary": { "appliedCount": 1, @@ -1383,7 +1341,7 @@ For each P0 tool: 6. Configure tool input JSON Schema with only Agent-facing fields. 7. Map `corpId/userId` from system context to the business request object. 8. Review every recommended mapping manually, especially fields named - `agentId`, `appId`, `appKey`, or `userId`. + `unifiedAppId`, `appKey`, `name`, or `userId`. 9. Keep `ServiceResult` output wrapper and success rule `ServiceResult.success == true`. 10. Remove blank error-text optimization rows; preserve raw @@ -1396,12 +1354,12 @@ P0 debug inputs: | Tool | Baseline debug input | | --- | --- | -| `list_open_dev_apps_by_condition` | `{"currentPage":1,"pageSize":10}` | -| `get_open_dev_app_detail` | `{"unifiedAppId":"UNIFIED_APP_ID"}` | -| `create_inner_app` | `{"appName":"DemoApp","appDesc":"internal app"}` | -| `update_inner_app` | `{"unifiedAppId":"UNIFIED_APP_ID","appDesc":"new desc"}` | -| `delete_inner_app` | `{"unifiedAppId":"UNIFIED_APP_ID"}` | -| `list_open_dev_app_permissions` | `{"unifiedAppId":"UNIFIED_APP_ID","authStatus":"ALL","limit":20}` | +| `list_open_dev_app` | `{"pageSize":10}` | +| `get_dev_app` | `{"unifiedAppId":"UNIFIED_APP_ID"}` | +| `create_dev_app` | `{"appName":"DemoApp","appDesc":"internal app"}` | +| `update_dev_app` | `{"unifiedAppId":"UNIFIED_APP_ID","appDesc":"new desc"}` | +| `delete_dev_app` | `{"unifiedAppId":"UNIFIED_APP_ID"}` | +| `list_open_dev_app_permissions` | `{"unifiedAppId":"UNIFIED_APP_ID","authStatus":"ALL","pageSize":20}` | | `apply_open_dev_app_permissions` | `{"unifiedAppId":"UNIFIED_APP_ID","scopeValues":["SCOPE_VALUE"]}` | | `remove_open_dev_app_permission` | `{"unifiedAppId":"UNIFIED_APP_ID","scopeValue":"SCOPE_VALUE"}` | @@ -1414,8 +1372,8 @@ After publish, verify the service through MCP before using DWS: 1. Run MCP `initialize`. 2. Run `tools/list` and confirm all expected P0 tool keys exist. -3. Call `list_open_dev_apps_by_condition` with only pagination. -4. Call one exact locator scenario, such as `get_open_dev_app_detail`. +3. Call `list_open_dev_app` with only pagination. +4. Call one exact locator scenario, such as `get_dev_app`. 5. Call permission list with `authStatus=ALL` and confirm APP and SNS scopes are both represented. 6. Confirm failures preserve `errorCode/errorMsg`. @@ -1495,8 +1453,8 @@ the following are true: | `dws devapp get --name DemoApp --format json` with multiple matches | Stops and returns candidates. | | `dws devapp create --name T --type internal --dry-run --format json` | Prints payload only; no MCP call. | | `dws devapp create --name T --type internal --format json` | Refuses because write confirmation is missing. | -| `dws devapp create --name T --type internal --yes --format json` | Calls `create_inner_app`. | -| `dws devapp update --unified-app-id X --desc Y --yes --format json` | Calls `update_inner_app`. | +| `dws devapp create --name T --type internal --yes --format json` | Calls `create_dev_app`. | +| `dws devapp update --unified-app-id X --desc Y --yes --format json` | Calls `update_dev_app`. | | `dws devapp delete --unified-app-id X --format json` | Refuses because delete confirmation is missing. | | `dws devapp permission list --unified-app-id X --format json` | Returns flattened APP and SNS permissions. | | `dws devapp permission list --unified-app-id X --keyword "发送消息" --format json` | Returns candidate `permissions[]`; no automatic apply. | diff --git a/internal/helpers/devapp.go b/internal/helpers/devapp.go index 27ffeb67..1fb64fee 100644 --- a/internal/helpers/devapp.go +++ b/internal/helpers/devapp.go @@ -28,6 +28,15 @@ import ( const ( devAppProduct = "devapp" + devAppListTool = "list_open_dev_app" + devAppGetTool = "get_dev_app" + devAppCreateTool = "create_dev_app" + devAppUpdateTool = "update_dev_app" + devAppDeleteTool = "delete_dev_app" + devAppDisableTool = "disable_dev_app" + devAppEnableTool = "enable_dev_app" + devAppCredentialsGet = "get_open_dev_app_credentials" + devAppMemberListTool = "list_open_dev_app_members" devAppMemberAddTool = "add_open_dev_app_members" devAppMemberRemoveTool = "remove_open_dev_app_members" @@ -217,9 +226,9 @@ func newDevAppCommand(runner executor.Runner) *cobra.Command { newDevAppGetCommand(runner), newDevAppCreateCommand(runner), newDevAppUpdateCommand(runner), - newDevAppLifecycleCommand(runner, "delete", "删除开放平台企业内部应用", "delete_inner_app"), - newDevAppLifecycleCommand(runner, "inactive", "停用开放平台企业内部应用", "inactive_inner_app"), - newDevAppLifecycleCommand(runner, "active", "启用开放平台企业内部应用", "active_inner_app"), + newDevAppLifecycleCommand(runner, "delete", "删除开放平台企业内部应用", devAppDeleteTool), + newDevAppLifecycleCommand(runner, "inactive", "停用开放平台企业内部应用", devAppDisableTool), + newDevAppLifecycleCommand(runner, "active", "启用开放平台企业内部应用", devAppEnableTool), credentials, webapp, permission, @@ -236,42 +245,25 @@ func newDevAppListCommand(runner executor.Runner) *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "查询开放平台企业内部应用列表", - Example: " dws devapp list --name DemoApp --page 1 --page-size 20 --format json", + Example: " dws devapp list --name DemoApp --page-size 20 --format json", Args: cobra.NoArgs, DisableAutoGenTag: true, RunE: func(cmd *cobra.Command, args []string) error { params := map[string]any{ - "currentPage": devAppIntFlag(cmd, "page"), - "pageSize": devAppIntFlag(cmd, "page-size"), + "pageSize": devAppIntFlag(cmd, "page-size"), } - devAppPutString(params, "appName", devAppFlagOrFallback(cmd, "name", "keyword")) - devAppPutInt(params, "agentId", devAppIntFlag(cmd, "agent-id")) - devAppPutInt(params, "appId", devAppIntFlag(cmd, "app-id")) + devAppPutString(params, "cursor", devAppStringFlag(cmd, "cursor")) + devAppPutString(params, "name", devAppFlagOrFallback(cmd, "name", "keyword")) devAppPutString(params, "appKey", devAppStringFlag(cmd, "app-key")) - devAppPutString(params, "customKey", devAppStringFlag(cmd, "custom-key")) - devAppPutInt(params, "appGroupId", devAppIntFlag(cmd, "app-group-id")) - devAppPutString(params, "creator", devAppStringFlag(cmd, "creator")) - devAppPutString(params, "robotName", devAppStringFlag(cmd, "robot-name")) - devAppPutInt(params, "developType", devAppIntFlag(cmd, "develop-type")) - devAppPutInt(params, "filterCoolApp", devAppIntFlag(cmd, "filter-cool-app")) - devAppPutString(params, "sortType", devAppStringFlag(cmd, "sort")) - devAppPutString(params, "sortOrder", devAppStringFlag(cmd, "order")) - return runDevAppTool(runner, cmd, "list_open_dev_apps_by_condition", params) + return runDevAppTool(runner, cmd, devAppListTool, params) }, } - cmd.Flags().Int("page", 1, "分页页码,从 1 开始") cmd.Flags().Int("page-size", 20, "分页大小") + cmd.Flags().String("cursor", "", "游标分页 cursor,首次查询为空") cmd.Flags().String("name", "", "应用名称关键词") cmd.Flags().String("keyword", "", "--name 的兼容别名") _ = cmd.Flags().MarkHidden("keyword") - addDevAppLocatorFlagsWithoutName(cmd) - cmd.Flags().Int("app-group-id", 0, "应用分组 ID") - cmd.Flags().String("creator", "", "创建人名称关键词") - cmd.Flags().String("robot-name", "", "机器人名称关键词") - cmd.Flags().Int("develop-type", 0, "开发类型枚举;不确定时不要传") - cmd.Flags().Int("filter-cool-app", 0, "酷应用过滤枚举;不确定时不要传") - cmd.Flags().String("sort", "", "排序字段,如 gmt_modified") - cmd.Flags().String("order", "", "排序方向 asc 或 desc") + cmd.Flags().String("app-key", "", "appKey/clientId") preferLegacyLeaf(cmd) return cmd } @@ -280,18 +272,18 @@ func newDevAppGetCommand(runner executor.Runner) *cobra.Command { cmd := &cobra.Command{ Use: "get", Short: "查询开放平台企业内部应用详情", - Example: " dws devapp get --agent-id 123456 --format json", + Example: " dws devapp get --unified-app-id UNIFIED_APP_ID --format json", Args: cobra.NoArgs, DisableAutoGenTag: true, RunE: func(cmd *cobra.Command, args []string) error { - params := devAppLocatorParams(cmd, true) + params := devAppMcpLocatorParams(cmd, true) if len(params) == 0 { - return devAppLocatorRequired(true) + return devAppMcpLocatorRequired(true) } - return runDevAppTool(runner, cmd, "get_open_dev_app_detail", params) + return runDevAppTool(runner, cmd, devAppGetTool, params) }, } - addDevAppLocatorFlags(cmd) + addDevAppMcpLocatorFlags(cmd, true) preferLegacyLeaf(cmd) return cmd } @@ -318,7 +310,7 @@ func newDevAppCreateCommand(runner executor.Runner) *cobra.Command { params := map[string]any{"appName": name} devAppPutString(params, "appDesc", devAppStringFlag(cmd, "desc")) devAppPutString(params, "appIcon", devAppStringFlag(cmd, "icon")) - return runDevAppTool(runner, cmd, "create_inner_app", params) + return runDevAppTool(runner, cmd, devAppCreateTool, params) }, } cmd.Flags().String("name", "", "应用名称 (必填)") @@ -333,16 +325,16 @@ func newDevAppUpdateCommand(runner executor.Runner) *cobra.Command { cmd := &cobra.Command{ Use: "update", Short: "修改开放平台企业内部应用基础信息", - Example: " dws devapp update --agent-id 123456 --name DemoApp2 --dry-run --format json", + Example: " dws devapp update --unified-app-id UNIFIED_APP_ID --name DemoApp2 --dry-run --format json", Args: cobra.NoArgs, DisableAutoGenTag: true, RunE: func(cmd *cobra.Command, args []string) error { if err := devAppRequireWriteGuard(cmd, "update"); err != nil { return err } - params := devAppLocatorParams(cmd, false) + params := devAppMcpLocatorParams(cmd, false) if len(params) == 0 { - return devAppLocatorRequired(false) + return devAppMcpLocatorRequired(false) } updates := 0 if v := devAppStringFlag(cmd, "name"); v != "" { @@ -360,10 +352,10 @@ func newDevAppUpdateCommand(runner executor.Runner) *cobra.Command { if updates == 0 { return apperrors.NewValidation("at least one update field is required: --name, --desc, or --icon") } - return runDevAppTool(runner, cmd, "update_inner_app", params) + return runDevAppTool(runner, cmd, devAppUpdateTool, params) }, } - addDevAppLocatorFlagsWithoutName(cmd) + addDevAppMcpLocatorFlags(cmd, false) cmd.Flags().String("name", "", "新的应用名称") cmd.Flags().String("desc", "", "新的应用描述") cmd.Flags().String("icon", "", "新的应用图标 mediaId") @@ -375,18 +367,18 @@ func newDevAppCredentialsGetCommand(runner executor.Runner) *cobra.Command { cmd := &cobra.Command{ Use: "get", Short: "读取开放平台应用凭证", - Example: " dws devapp credentials get --agent-id 123456 --format json", + Example: " dws devapp credentials get --unified-app-id UNIFIED_APP_ID --format json", Args: cobra.NoArgs, DisableAutoGenTag: true, RunE: func(cmd *cobra.Command, args []string) error { - params := devAppLocatorParams(cmd, false) + params := devAppCredentialsLocatorParams(cmd) if len(params) == 0 { - return devAppLocatorRequired(false) + return devAppCredentialsLocatorRequired() } - return runDevAppTool(runner, cmd, "get_open_dev_app_credentials", params) + return runDevAppTool(runner, cmd, devAppCredentialsGet, params) }, } - addDevAppLocatorFlagsWithoutName(cmd) + addDevAppCredentialsLocatorFlags(cmd) preferLegacyLeaf(cmd) return cmd } @@ -401,14 +393,14 @@ func newDevAppLifecycleCommand(runner executor.Runner, use, short, tool string) if err := devAppRequireWriteGuard(cmd, use); err != nil { return err } - params := devAppLocatorParams(cmd, false) + params := devAppMcpLocatorParams(cmd, true) if len(params) == 0 { - return devAppLocatorRequired(false) + return devAppMcpLocatorRequired(true) } return runDevAppTool(runner, cmd, tool, params) }, } - addDevAppLocatorFlagsWithoutName(cmd) + addDevAppMcpLocatorFlags(cmd, true) preferLegacyLeaf(cmd) return cmd } @@ -417,18 +409,18 @@ func newDevAppWebappGetCommand(runner executor.Runner) *cobra.Command { cmd := &cobra.Command{ Use: "get", Short: "查询网页应用配置", - Example: " dws devapp webapp get --agent-id 123456 --format json", + Example: " dws devapp webapp get --unified-app-id UNIFIED_APP_ID --format json", Args: cobra.NoArgs, DisableAutoGenTag: true, RunE: func(cmd *cobra.Command, args []string) error { - params := devAppAppLocatorParams(cmd) + params := devAppMcpLocatorParams(cmd, false) if len(params) == 0 { - return devAppAppLocatorRequired() + return devAppMcpLocatorRequired(false) } return runDevAppTool(runner, cmd, "get_webapp_config", params) }, } - addDevAppAppLocatorFlags(cmd) + addDevAppMcpLocatorFlags(cmd, false) preferLegacyLeaf(cmd) return cmd } @@ -437,45 +429,51 @@ func newDevAppWebappConfigCommand(runner executor.Runner) *cobra.Command { cmd := &cobra.Command{ Use: "config", Short: "配置网页应用能力", - Example: " dws devapp webapp config --agent-id 123456 --homepage-link https://example.com --dry-run --format json", + Example: " dws devapp webapp config --unified-app-id UNIFIED_APP_ID --homepage-url https://example.com --dry-run --format json", Args: cobra.NoArgs, DisableAutoGenTag: true, RunE: func(cmd *cobra.Command, args []string) error { if err := devAppRequireWriteGuard(cmd, "webapp config"); err != nil { return err } - params := devAppAppLocatorParams(cmd) + params := devAppMcpLocatorParams(cmd, true) if len(params) == 0 { - return devAppAppLocatorRequired() + return devAppMcpLocatorRequired(true) } updates := 0 if v := devAppStringFlag(cmd, "h5-page-type"); v != "" { params["h5PageType"] = v updates++ } - if v := devAppStringFlag(cmd, "homepage-link"); v != "" { - params["homepageLink"] = v + if v := devAppFlagOrFallback(cmd, "homepage-url", "homepage-link"); v != "" { + params["homepageUrl"] = v updates++ } - if v := devAppStringFlag(cmd, "pc-homepage-link"); v != "" { - params["pcHomepageLink"] = v + if v := devAppFlagOrFallback(cmd, "pc-homepage-url", "pc-homepage-link"); v != "" { + params["pcHomepageUrl"] = v updates++ } - if v := devAppStringFlag(cmd, "omp-link"); v != "" { - params["ompLink"] = v + if v := devAppFlagOrFallback(cmd, "omp-url", "omp-link"); v != "" { + params["ompUrl"] = v updates++ } if updates == 0 { - return apperrors.NewValidation("at least one webapp field is required: --h5-page-type, --homepage-link, --pc-homepage-link, or --omp-link") + return apperrors.NewValidation("at least one webapp field is required: --h5-page-type, --homepage-url, --pc-homepage-url, or --omp-url") } return runDevAppTool(runner, cmd, "set_webapp_config", params) }, } - addDevAppAppLocatorFlags(cmd) + addDevAppMcpLocatorFlags(cmd, true) cmd.Flags().String("h5-page-type", "", "网页应用生效端/页面类型") - cmd.Flags().String("homepage-link", "", "移动端首页地址") - cmd.Flags().String("pc-homepage-link", "", "PC 端首页地址") - cmd.Flags().String("omp-link", "", "管理后台地址") + cmd.Flags().String("homepage-url", "", "移动端首页地址") + cmd.Flags().String("homepage-link", "", "--homepage-url 的兼容别名") + _ = cmd.Flags().MarkHidden("homepage-link") + cmd.Flags().String("pc-homepage-url", "", "PC 端首页地址") + cmd.Flags().String("pc-homepage-link", "", "--pc-homepage-url 的兼容别名") + _ = cmd.Flags().MarkHidden("pc-homepage-link") + cmd.Flags().String("omp-url", "", "管理后台地址") + cmd.Flags().String("omp-link", "", "--omp-url 的兼容别名") + _ = cmd.Flags().MarkHidden("omp-link") preferLegacyLeaf(cmd) return cmd } @@ -485,25 +483,25 @@ func newDevAppPermissionListCommand(runner executor.Runner) *cobra.Command { Use: "list", Aliases: []string{"search", "detail"}, Short: "查询开放平台应用权限列表", - Example: " dws devapp permission list --agent-id 123456 --keyword 通讯录 --limit 20 --format json", + Example: " dws devapp permission list --unified-app-id UNIFIED_APP_ID --keyword 通讯录 --page-size 20 --format json", Args: cobra.NoArgs, DisableAutoGenTag: true, RunE: func(cmd *cobra.Command, args []string) error { - params := devAppAppLocatorParams(cmd) + params := devAppPermissionLocatorParams(cmd) if len(params) == 0 { - return devAppAppLocatorRequired() + return devAppPermissionLocatorRequired() } devAppPutString(params, "keyword", devAppStringFlag(cmd, "keyword")) devAppPutString(params, "scopeValue", devAppFlagOrFallback(cmd, "scope", "permission")) devAppPutString(params, "authStatus", strings.ToUpper(devAppStringFlag(cmd, "status"))) - devAppPutString(params, "firstLevelType", strings.ToUpper(devAppStringFlag(cmd, "scope-type"))) + devAppPutString(params, "scopeType", strings.ToUpper(devAppStringFlag(cmd, "scope-type"))) devAppPutString(params, "apiStatus", devAppStringFlag(cmd, "api-status")) - devAppPutInt(params, "limit", devAppIntFlag(cmd, "limit")) - devAppPutInt(params, "offset", devAppIntFlag(cmd, "offset")) + devAppPutString(params, "cursor", devAppStringFlag(cmd, "cursor")) + devAppPutInt(params, "pageSize", devAppIntFlag(cmd, "page-size")) return runDevAppTool(runner, cmd, "list_open_dev_app_permissions", params) }, } - addDevAppAppLocatorFlags(cmd) + addDevAppPermissionLocatorFlags(cmd) cmd.Flags().String("keyword", "", "权限名、权限点、接口名关键词") cmd.Flags().String("scope", "", "精确权限点 scopeValue") cmd.Flags().String("permission", "", "--scope 的兼容别名") @@ -511,8 +509,8 @@ func newDevAppPermissionListCommand(runner executor.Runner) *cobra.Command { cmd.Flags().String("status", "ALL", "权限状态:ALL、AUTHED、UNAUTHED") cmd.Flags().String("scope-type", "", "权限一级类型:APP 或 SNS") cmd.Flags().String("api-status", "", "开发者后台 apiStatus 过滤") - cmd.Flags().Int("limit", 20, "返回数量上限") - cmd.Flags().Int("offset", 0, "返回偏移量") + cmd.Flags().Int("page-size", 20, "返回数量上限") + cmd.Flags().String("cursor", "", "游标分页 cursor,首次查询为空") preferLegacyLeaf(cmd) return cmd } @@ -521,16 +519,16 @@ func newDevAppPermissionAddCommand(runner executor.Runner) *cobra.Command { cmd := &cobra.Command{ Use: "add", Short: "申请开放平台应用权限点", - Example: " dws devapp permission add --agent-id 123456 --permissions Contact.User.mobile --dry-run --format json", + Example: " dws devapp permission add --unified-app-id UNIFIED_APP_ID --permissions Contact.User.mobile --dry-run --format json", Args: cobra.NoArgs, DisableAutoGenTag: true, RunE: func(cmd *cobra.Command, args []string) error { if err := devAppRequireWriteGuard(cmd, "permission add"); err != nil { return err } - params := devAppAppLocatorParams(cmd) + params := devAppPermissionLocatorParams(cmd) if len(params) == 0 { - return devAppAppLocatorRequired() + return devAppPermissionLocatorRequired() } scopes := devAppPermissionScopes(cmd) if len(scopes) == 0 { @@ -540,7 +538,7 @@ func newDevAppPermissionAddCommand(runner executor.Runner) *cobra.Command { return runDevAppTool(runner, cmd, "apply_open_dev_app_permissions", params) }, } - addDevAppAppLocatorFlags(cmd) + addDevAppPermissionLocatorFlags(cmd) cmd.Flags().StringSlice("permissions", nil, "权限点 scopeValue,多个用逗号分隔") cmd.Flags().String("scope", "", "--permissions 的兼容别名,单个权限点 scopeValue") cmd.Flags().String("permission", "", "--permissions 的兼容别名,单个权限点 scopeValue") @@ -554,16 +552,16 @@ func newDevAppPermissionRemoveCommand(runner executor.Runner) *cobra.Command { cmd := &cobra.Command{ Use: "remove", Short: "取消开放平台应用权限点", - Example: " dws devapp permission remove --agent-id 123456 --permission Contact.User.mobile --dry-run --format json", + Example: " dws devapp permission remove --unified-app-id UNIFIED_APP_ID --permission Contact.User.mobile --dry-run --format json", Args: cobra.NoArgs, DisableAutoGenTag: true, RunE: func(cmd *cobra.Command, args []string) error { if err := devAppRequireWriteGuard(cmd, "permission remove"); err != nil { return err } - params := devAppAppLocatorParams(cmd) + params := devAppPermissionLocatorParams(cmd) if len(params) == 0 { - return devAppAppLocatorRequired() + return devAppPermissionLocatorRequired() } scope := devAppFlagOrFallback(cmd, "permission", "scope") if scope == "" { @@ -573,7 +571,7 @@ func newDevAppPermissionRemoveCommand(runner executor.Runner) *cobra.Command { return runDevAppTool(runner, cmd, "remove_open_dev_app_permission", params) }, } - addDevAppAppLocatorFlags(cmd) + addDevAppPermissionLocatorFlags(cmd) cmd.Flags().String("permission", "", "待取消权限点 scopeValue") cmd.Flags().String("scope", "", "--permission 的兼容别名") _ = cmd.Flags().MarkHidden("scope") @@ -1259,50 +1257,61 @@ func splitDevAppList(raw string) []string { return values } -func addDevAppLocatorFlags(cmd *cobra.Command) { - addDevAppLocatorFlagsWithoutName(cmd) - cmd.Flags().String("name", "", "应用名称关键词;写操作前必须唯一命中") -} - -func addDevAppLocatorFlagsWithoutName(cmd *cobra.Command) { - addDevAppAppLocatorFlags(cmd) - cmd.Flags().Int("app-id", 0, "兼容 appId") - cmd.Flags().String("app-key", "", "appKey/clientId") - cmd.Flags().String("custom-key", "", "customKey") -} - -func addDevAppAppLocatorFlags(cmd *cobra.Command) { +func addDevAppMcpLocatorFlags(cmd *cobra.Command, includeName bool) { cmd.Flags().String("unified-app-id", "", "统一应用 ID") - cmd.Flags().Int("agent-id", 0, "应用 agentId") -} - -func devAppLocatorParams(cmd *cobra.Command, includeName bool) map[string]any { - params := devAppAppLocatorParams(cmd) - devAppPutInt(params, "appId", devAppIntFlag(cmd, "app-id")) - devAppPutString(params, "appKey", devAppStringFlag(cmd, "app-key")) - devAppPutString(params, "customKey", devAppStringFlag(cmd, "custom-key")) + cmd.Flags().String("app-key", "", "appKey/clientId") if includeName { - devAppPutString(params, "appName", devAppStringFlag(cmd, "name")) + cmd.Flags().String("name", "", "应用名称关键词;写操作前必须唯一命中") } - return params } -func devAppAppLocatorParams(cmd *cobra.Command) map[string]any { +func devAppMcpLocatorParams(cmd *cobra.Command, includeName bool) map[string]any { params := map[string]any{} devAppPutString(params, "unifiedAppId", devAppStringFlag(cmd, "unified-app-id")) - devAppPutInt(params, "agentId", devAppIntFlag(cmd, "agent-id")) + devAppPutString(params, "appKey", devAppStringFlag(cmd, "app-key")) + if includeName { + devAppPutString(params, "name", devAppStringFlag(cmd, "name")) + } return params } -func devAppLocatorRequired(includeName bool) error { - if includeName { - return apperrors.NewValidation("one app locator is required: --agent-id, --unified-app-id, --app-key, --custom-key, --app-id, or --name") - } - return apperrors.NewValidation("one app locator is required: --agent-id, --unified-app-id, --app-key, --custom-key, or --app-id") +func addDevAppCredentialsLocatorFlags(cmd *cobra.Command) { + cmd.Flags().String("unified-app-id", "", "统一应用 ID") + cmd.Flags().String("app-key", "", "appKey/clientId") + cmd.Flags().String("name", "", "应用名称关键词;必须唯一命中") } -func devAppAppLocatorRequired() error { - return apperrors.NewValidation("one app locator is required: --agent-id or --unified-app-id") +func devAppCredentialsLocatorParams(cmd *cobra.Command) map[string]any { + params := map[string]any{} + devAppPutString(params, "unifiedAppId", devAppStringFlag(cmd, "unified-app-id")) + devAppPutString(params, "appKey", devAppStringFlag(cmd, "app-key")) + devAppPutString(params, "appName", devAppStringFlag(cmd, "name")) + return params +} + +func devAppCredentialsLocatorRequired() error { + return apperrors.NewValidation("one app locator is required: --unified-app-id, --app-key, or --name") +} + +func devAppMcpLocatorRequired(includeName bool) error { + if includeName { + return apperrors.NewValidation("one app locator is required: --unified-app-id, --app-key, or --name") + } + return apperrors.NewValidation("one app locator is required: --unified-app-id or --app-key") +} + +func addDevAppPermissionLocatorFlags(cmd *cobra.Command) { + cmd.Flags().String("unified-app-id", "", "统一应用 ID") +} + +func devAppPermissionLocatorParams(cmd *cobra.Command) map[string]any { + params := map[string]any{} + devAppPutString(params, "unifiedAppId", devAppStringFlag(cmd, "unified-app-id")) + return params +} + +func devAppPermissionLocatorRequired() error { + return apperrors.NewValidation("one app locator is required: --unified-app-id") } func devAppRequireWriteGuard(cmd *cobra.Command, operation string) error { diff --git a/internal/helpers/devapp_test.go b/internal/helpers/devapp_test.go index 7f0567b6..af49d182 100644 --- a/internal/helpers/devapp_test.go +++ b/internal/helpers/devapp_test.go @@ -484,20 +484,19 @@ func TestDevAppListBuildsListByConditionParams(t *testing.T) { var out bytes.Buffer root.SetOut(&out) root.SetErr(&out) - root.SetArgs([]string{"list", "--name", "Waker", "--page", "2", "--page-size", "5", "--sort", "gmt_modified", "--order", "desc"}) + root.SetArgs([]string{"list", "--name", "Waker", "--app-key", "dingxxx", "--page-size", "5", "--cursor", "next-1"}) if err := root.Execute(); err != nil { t.Fatalf("Execute() error = %v\noutput:\n%s", err, out.String()) } - if got := runner.last.Tool; got != "list_open_dev_apps_by_condition" { - t.Fatalf("Tool = %q, want list_open_dev_apps_by_condition", got) + if got := runner.last.Tool; got != "list_open_dev_app" { + t.Fatalf("Tool = %q, want list_open_dev_app", got) } want := map[string]any{ - "currentPage": 2, - "pageSize": 5, - "appName": "Waker", - "sortType": "gmt_modified", - "sortOrder": "desc", + "pageSize": 5, + "cursor": "next-1", + "name": "Waker", + "appKey": "dingxxx", } if !reflect.DeepEqual(runner.last.Params, want) { t.Fatalf("Params = %#v, want %#v", runner.last.Params, want) @@ -515,8 +514,8 @@ func TestDevAppGetBuildsDetailParams(t *testing.T) { if err := root.Execute(); err != nil { t.Fatalf("Execute() error = %v\noutput:\n%s", err, out.String()) } - if got := runner.last.Tool; got != "get_open_dev_app_detail" { - t.Fatalf("Tool = %q, want get_open_dev_app_detail", got) + if got := runner.last.Tool; got != "get_dev_app" { + t.Fatalf("Tool = %q, want get_dev_app", got) } want := map[string]any{"unifiedAppId": "u-1"} if !reflect.DeepEqual(runner.last.Params, want) { @@ -545,8 +544,8 @@ func TestDevAppCreateUsesCurrentInnerToolAndWriteGuard(t *testing.T) { if err := root.Execute(); err != nil { t.Fatalf("Execute() error = %v\noutput:\n%s", err, out.String()) } - if got := runner.last.Tool; got != "create_inner_app" { - t.Fatalf("Tool = %q, want create_inner_app", got) + if got := runner.last.Tool; got != "create_dev_app" { + t.Fatalf("Tool = %q, want create_dev_app", got) } want := map[string]any{"appName": "Demo", "appDesc": "internal app"} @@ -561,15 +560,15 @@ func TestDevAppUpdateUsesCurrentInnerTool(t *testing.T) { var out bytes.Buffer root.SetOut(&out) root.SetErr(&out) - root.SetArgs([]string{"devapp", "update", "--agent-id", "123", "--desc", "new desc", "--yes"}) + root.SetArgs([]string{"devapp", "update", "--unified-app-id", "u-1", "--desc", "new desc", "--yes"}) if err := root.Execute(); err != nil { t.Fatalf("Execute() error = %v\noutput:\n%s", err, out.String()) } - if got := runner.last.Tool; got != "update_inner_app" { - t.Fatalf("Tool = %q, want update_inner_app", got) + if got := runner.last.Tool; got != "update_dev_app" { + t.Fatalf("Tool = %q, want update_dev_app", got) } - want := map[string]any{"agentId": 123, "appDesc": "new desc"} + want := map[string]any{"unifiedAppId": "u-1", "appDesc": "new desc"} if !reflect.DeepEqual(runner.last.Params, want) { t.Fatalf("Params = %#v, want %#v", runner.last.Params, want) } @@ -583,21 +582,21 @@ func TestDevAppLifecycleBuildsLocatorParams(t *testing.T) { wantParams map[string]any }{ { - name: "delete by agent id", - args: []string{"delete", "--agent-id", "123", "--yes"}, - wantTool: "delete_inner_app", - wantParams: map[string]any{"agentId": 123}, + name: "delete by name", + args: []string{"delete", "--name", "Demo", "--yes"}, + wantTool: "delete_dev_app", + wantParams: map[string]any{"name": "Demo"}, }, { name: "inactive by unified app id", args: []string{"inactive", "--unified-app-id", "u-1", "--yes"}, - wantTool: "inactive_inner_app", + wantTool: "disable_dev_app", wantParams: map[string]any{"unifiedAppId": "u-1"}, }, { name: "active by app key", args: []string{"active", "--app-key", "dingxxx", "--yes"}, - wantTool: "active_inner_app", + wantTool: "enable_dev_app", wantParams: map[string]any{"appKey": "dingxxx"}, }, } @@ -639,12 +638,12 @@ func TestDevAppWebappCommandsBuildParams(t *testing.T) { }, { name: "config", - args: []string{"webapp", "config", "--unified-app-id", "u-1", "--homepage-link", "https://example.com", "--pc-homepage-link", "https://pc.example.com", "--yes"}, + args: []string{"webapp", "config", "--unified-app-id", "u-1", "--homepage-url", "https://example.com", "--pc-homepage-url", "https://pc.example.com", "--yes"}, wantTool: "set_webapp_config", wantParams: map[string]any{ - "unifiedAppId": "u-1", - "homepageLink": "https://example.com", - "pcHomepageLink": "https://pc.example.com", + "unifiedAppId": "u-1", + "homepageUrl": "https://example.com", + "pcHomepageUrl": "https://pc.example.com", }, }, } @@ -680,31 +679,32 @@ func TestDevAppPermissionCommandsBuildParams(t *testing.T) { }{ { name: "list", - args: []string{"permission", "list", "--agent-id", "123", "--keyword", "手机号", "--status", "all", "--limit", "5"}, + args: []string{"permission", "list", "--unified-app-id", "u-1", "--keyword", "手机号", "--status", "all", "--page-size", "5", "--cursor", "next-1"}, wantTool: "list_open_dev_app_permissions", wantParams: map[string]any{ - "agentId": 123, - "keyword": "手机号", - "authStatus": "ALL", - "limit": 5, + "unifiedAppId": "u-1", + "keyword": "手机号", + "authStatus": "ALL", + "pageSize": 5, + "cursor": "next-1", }, }, { name: "add", - args: []string{"permission", "add", "--agent-id", "123", "--permissions", "Contact.User.mobile,qyapi_robot_sendmsg", "--yes"}, + args: []string{"permission", "add", "--unified-app-id", "u-1", "--permissions", "Contact.User.mobile,qyapi_robot_sendmsg", "--yes"}, wantTool: "apply_open_dev_app_permissions", wantParams: map[string]any{ - "agentId": 123, - "scopeValues": []string{"Contact.User.mobile", "qyapi_robot_sendmsg"}, + "unifiedAppId": "u-1", + "scopeValues": []string{"Contact.User.mobile", "qyapi_robot_sendmsg"}, }, }, { name: "remove", - args: []string{"permission", "remove", "--agent-id", "123", "--permission", "Contact.User.mobile", "--yes"}, + args: []string{"permission", "remove", "--unified-app-id", "u-1", "--permission", "Contact.User.mobile", "--yes"}, wantTool: "remove_open_dev_app_permission", wantParams: map[string]any{ - "agentId": 123, - "scopeValue": "Contact.User.mobile", + "unifiedAppId": "u-1", + "scopeValue": "Contact.User.mobile", }, }, } @@ -737,7 +737,7 @@ func TestDevAppCredentialsGetBuildsParams(t *testing.T) { var out bytes.Buffer root.SetOut(&out) root.SetErr(&out) - root.SetArgs([]string{"devapp", "credentials", "get", "--agent-id", "123"}) + root.SetArgs([]string{"devapp", "credentials", "get", "--unified-app-id", "u-1"}) if err := root.Execute(); err != nil { t.Fatalf("Execute() error = %v\noutput:\n%s", err, out.String()) @@ -745,7 +745,7 @@ func TestDevAppCredentialsGetBuildsParams(t *testing.T) { if got := runner.last.Tool; got != "get_open_dev_app_credentials" { t.Fatalf("Tool = %q, want get_open_dev_app_credentials", got) } - want := map[string]any{"agentId": 123} + want := map[string]any{"unifiedAppId": "u-1"} if !reflect.DeepEqual(runner.last.Params, want) { t.Fatalf("Params = %#v, want %#v", runner.last.Params, want) } @@ -766,7 +766,7 @@ func TestDevAppCredentialsGetKeepsSecretFields(t *testing.T) { var out bytes.Buffer root.SetOut(&out) root.SetErr(&out) - root.SetArgs([]string{"devapp", "credentials", "get", "--agent-id", "123"}) + root.SetArgs([]string{"devapp", "credentials", "get", "--unified-app-id", "u-1"}) if err := root.Execute(); err != nil { t.Fatalf("Execute() error = %v\noutput:\n%s", err, out.String()) diff --git a/skills/dingtalk-devapp/SKILL.md b/skills/dingtalk-devapp/SKILL.md index 664f1cf9..6a13b89c 100644 --- a/skills/dingtalk-devapp/SKILL.md +++ b/skills/dingtalk-devapp/SKILL.md @@ -1,6 +1,6 @@ --- name: dingtalk-devapp -description: 钉钉开放平台应用管理。Use when 用户说 开发者后台应用/开放平台应用/企业内部应用/查应用/创建应用/修改应用/删除应用/停用应用/启用应用/应用成员/安全配置/IP白名单/登录重定向/端内免登/agentId/clientId/appKey/appSecret/应用权限/权限点/创建机器人/智能体机器人/机器人配置/机器人回调/应用版本/版本发布/发布审核/选审批人/事件订阅/订阅事件/退订事件/eventCode。Distinct from dingtalk-devdoc(开放平台文档搜索) and dingtalk-doc(钉钉云文档)。命令前缀:dws devapp(兼容别名 dws app)。 +description: 钉钉开放平台应用管理。Use when 用户说 开发者后台应用/开放平台应用/企业内部应用/查应用/创建应用/修改应用/删除应用/停用应用/启用应用/应用成员/安全配置/IP白名单/登录重定向/端内免登/unifiedAppId/clientId/appKey/appSecret/应用权限/权限点/创建机器人/智能体机器人/机器人配置/机器人回调/应用版本/版本发布/发布审核/选审批人/事件订阅/订阅事件/退订事件/eventCode。Distinct from dingtalk-devdoc(开放平台文档搜索) and dingtalk-doc(钉钉云文档)。命令前缀:dws devapp(兼容别名 dws app)。 cli_version: ">=1.0.15" metadata: category: product @@ -19,7 +19,7 @@ metadata: `应用` 是泛词。只有出现以下信号才路由到 devapp: - `开放平台应用/开发者后台应用/企业内部应用/内部应用` -- `agentId/clientId/appKey/appSecret/customKey` +- `unifiedAppId/clientId/appKey/appSecret` - `应用权限/权限点/scopeValue/应用成员/安全配置/IP 白名单` - `创建机器人/智能体机器人/机器人配置/机器人回调地址`(→ `robot`) - `应用版本/版本发布/发布审核/选审批人`(→ `version`) @@ -31,7 +31,7 @@ metadata: 1. 所有命令加 `--format json`。 2. 写操作先 `--dry-run`,确认后才加 `--yes`。 -3. 应用名/appKey/customKey 命中多条时展示候选,不取第一条。 +3. 应用名/appKey 命中多条时展示候选,不取第一条。 4. 权限申请/取消只接受 `scopeValue`,不传 API 名或分组名。 5. 主动读取密钥走 `credentials get`;任何 `devapp get`/详情返回里的 `clientSecret/appSecret` 都按敏感凭证脱敏,不向用户展开。 diff --git a/skills/dingtalk-devapp/references/app-crud.md b/skills/dingtalk-devapp/references/app-crud.md index 7898e729..0d773886 100644 --- a/skills/dingtalk-devapp/references/app-crud.md +++ b/skills/dingtalk-devapp/references/app-crud.md @@ -9,31 +9,26 @@ | 优先级 | 标识 | 处理 | |--------|------|------| | 1 | `--unified-app-id` | 直接使用 | -| 2 | `--agent-id` / `--app-id` | 直接使用 | -| 3 | `--app-key` / `--custom-key` | 先查询,唯一命中才继续 | -| 4 | `--name` | 模糊搜索,写操作必须唯一命中 | +| 2 | `--app-key` | appKey/clientId,唯一命中才继续 | +| 3 | `--name` | 应用名称关键词,写操作必须唯一命中 | ## 应用列表 ```bash dws devapp list --format json dws devapp list --name DemoApp --format json -dws devapp list --agent-id 123456 --format json -dws devapp list --creator 张三 --sort gmt_modified --order desc --format json +dws devapp list --app-key dingxxx --format json +dws devapp list --name DemoApp --page-size 20 --cursor NEXT_CURSOR --format json ``` -MCP tool: `list_open_dev_apps_by_condition` +MCP tool: `list_open_dev_app` | CLI | MCP | 说明 | |-----|-----|------| -| `--page` | `currentPage` | 1-based,默认 1 | | `--page-size` | `pageSize` | 默认 20 | -| `--name` / `--keyword` | `appName` | 应用名搜索 | -| `--agent-id` | `agentId` | 精确定位 | +| `--cursor` | `cursor` | 游标,首次为空,用上一页 `nextCursor` 继续 | +| `--name` / `--keyword` | `name` | 应用名搜索 | | `--app-key` | `appKey` | appKey/clientId | -| `--creator` | `creator` | 创建人关键词 | -| `--sort` | `sortType` | 如 `gmt_modified` | -| `--order` | `sortOrder` | `asc` / `desc` | ## 应用状态字段 @@ -52,10 +47,11 @@ MCP tool: `list_open_dev_apps_by_condition` ```bash dws devapp get --unified-app-id UNIFIED_APP_ID --format json -dws devapp get --agent-id 123456 --format json +dws devapp get --app-key dingxxx --format json +dws devapp get --name DemoApp --format json ``` -MCP tool: `get_open_dev_app_detail` +MCP tool: `get_dev_app` 详情主要用于定位和核验应用。若上游偶尔随详情返回 `clientSecret/appSecret`,必须脱敏处理,不要复制到回答里;主动读取凭证仍走 `credentials get`。 @@ -66,7 +62,7 @@ dws devapp create --name DemoApp --desc "内部应用" --type internal --dry-run dws devapp create --name DemoApp --desc "内部应用" --type internal --yes --format json ``` -MCP tool: `create_inner_app` +MCP tool: `create_dev_app` | CLI | MCP | 必填 | |-----|-----|------| @@ -83,7 +79,7 @@ dws devapp update --unified-app-id ID --name DemoApp2 --desc "新描述" --dry-r dws devapp update --unified-app-id ID --name DemoApp2 --desc "新描述" --yes --format json ``` -MCP tool: `update_inner_app` +MCP tool: `update_dev_app` 至少提供一个更新字段:`--name` / `--desc` / `--icon`。 @@ -97,7 +93,7 @@ dws devapp active --unified-app-id ID --dry-run --format json dws devapp active --unified-app-id ID --yes --format json ``` -MCP tools: `inactive_inner_app` / `active_inner_app` +MCP tools: `disable_dev_app` / `enable_dev_app` 停用保留数据但应用不可用,可通过 `active` 恢复。 @@ -110,7 +106,7 @@ dws devapp delete --unified-app-id ID --dry-run --format json dws devapp delete --unified-app-id ID --yes --format json ``` -MCP tool: `delete_inner_app` +MCP tool: `delete_dev_app` 删除前必须展示应用摘要。删除为异步操作,成功后应用延迟从列表消失。 diff --git a/skills/dingtalk-devapp/references/credentials-webapp.md b/skills/dingtalk-devapp/references/credentials-webapp.md index 0f1dec02..9ce8010f 100644 --- a/skills/dingtalk-devapp/references/credentials-webapp.md +++ b/skills/dingtalk-devapp/references/credentials-webapp.md @@ -4,7 +4,8 @@ ```bash dws devapp credentials get --unified-app-id UNIFIED_APP_ID --format json -dws devapp credentials get --agent-id 123456 --format json +dws devapp credentials get --app-key dingxxx --format json +dws devapp credentials get --name DemoApp --format json ``` MCP tool: `get_open_dev_app_credentials` @@ -28,19 +29,19 @@ MCP tool: `get_open_dev_app_credentials` ## 网页应用查询 ```bash -dws devapp webapp get --agent-id 123456 --format json dws devapp webapp get --unified-app-id UNIFIED_APP_ID --format json +dws devapp webapp get --app-key dingxxx --format json ``` MCP tool: `get_webapp_config` -未配置网页应用前可能只返回 `agentId`。 +未配置网页应用前可能只返回空配置。 ## 网页应用配置 ```bash -dws devapp webapp config --agent-id 123456 --homepage-link https://example.com/mobile --dry-run --format json -dws devapp webapp config --agent-id 123456 --homepage-link https://example.com/mobile --pc-homepage-link https://example.com/pc --yes --format json +dws devapp webapp config --unified-app-id UNIFIED_APP_ID --homepage-url https://example.com/mobile --dry-run --format json +dws devapp webapp config --unified-app-id UNIFIED_APP_ID --homepage-url https://example.com/mobile --pc-homepage-url https://example.com/pc --yes --format json ``` MCP tool: `set_webapp_config` @@ -48,8 +49,8 @@ MCP tool: `set_webapp_config` | CLI | MCP | 说明 | |-----|-----|------| | `--h5-page-type` | `h5PageType` | 网页应用生效端 | -| `--homepage-link` | `homepageLink` | 移动端首页地址 | -| `--pc-homepage-link` | `pcHomepageLink` | PC 端首页地址 | -| `--omp-link` | `ompLink` | 管理后台地址 | +| `--homepage-url` | `homepageUrl` | 移动端首页地址 | +| `--pc-homepage-url` | `pcHomepageUrl` | PC 端首页地址 | +| `--omp-url` | `ompUrl` | 管理后台地址 | 至少提供一个配置字段。`h5PageType` 未显式传入时,不要假设固定默认值;配置后以 `webapp get` 回读为准(实跑可能返回 `mobile`)。 diff --git a/skills/dingtalk-devapp/references/permissions.md b/skills/dingtalk-devapp/references/permissions.md index 17cc6d95..3b5a310c 100644 --- a/skills/dingtalk-devapp/references/permissions.md +++ b/skills/dingtalk-devapp/references/permissions.md @@ -16,13 +16,12 @@ MCP tool: `list_open_dev_app_permissions` | CLI | MCP | 说明 | |-----|-----|------| | `--unified-app-id` | `unifiedAppId` | 应用定位 | -| `--agent-id` | `agentId` | 应用定位 | | `--keyword` | `keyword` | 权限名/API 名关键词 | | `--status` | `authStatus` | `ALL` / `AUTHED` / `UNAUTHED` | -| `--scope-type` | `firstLevelType` | `APP` / `SNS`,为空返回两者 | +| `--scope-type` | `scopeType` | `APP` / `SNS`,为空返回两者 | | `--scope` | `scopeValue` | 单权限详情模式 | -| `--limit` | `limit` | 每页返回数量,默认 20,建议不超过 50 | -| `--offset` | `offset` | 翻页偏移量,默认 0 | +| `--page-size` | `pageSize` | 每页返回数量,默认 20,建议不超过 50 | +| `--cursor` | `cursor` | 游标,首次为空,用上一页 `nextCursor` 继续 | **状态判断:** @@ -47,15 +46,14 @@ MCP tool: `list_open_dev_app_permissions` **翻页:** -权限列表支持 `--limit` + `--offset` 分页。一个应用可能有 150+ 个权限点,一次查不完时用 offset 翻页: +权限列表支持 `--page-size` + `--cursor` 分页。一个应用可能有 150+ 个权限点,一次查不完时用返回的 `nextCursor` 继续: ```bash -dws devapp permission list --unified-app-id ID --limit 50 --format json # 第 1 页 -dws devapp permission list --unified-app-id ID --limit 50 --offset 50 --format json # 第 2 页 -dws devapp permission list --unified-app-id ID --limit 50 --offset 100 --format json # 第 3 页 +dws devapp permission list --unified-app-id ID --page-size 50 --format json +dws devapp permission list --unified-app-id ID --page-size 50 --cursor NEXT_CURSOR --format json ``` -当返回条数 < limit 时表示已到末尾。 +当返回无 `nextCursor` 或返回条数小于 `pageSize` 时表示已到末尾。 **规则:** - `permission search` 和 `permission detail` 是 `list` 的 CLI 别名,不是独立 MCP tool。 diff --git a/skills/dingtalk-devapp/references/workflows.md b/skills/dingtalk-devapp/references/workflows.md index bed457c6..b07be648 100644 --- a/skills/dingtalk-devapp/references/workflows.md +++ b/skills/dingtalk-devapp/references/workflows.md @@ -8,7 +8,7 @@ 1. 创建应用 dws devapp create --name "应用名" --desc "描述" --type internal --dry-run --format json → 确认后加 --yes - → 记录返回的 unifiedAppId 和 agentId + → 记录返回的 unifiedAppId 和 appKey 2. 确认创建成功 dws devapp get --unified-app-id --format json @@ -17,12 +17,12 @@ dws devapp credentials get --unified-app-id --format json 4. 配置网页应用(按需) - dws devapp webapp config --agent-id --homepage-link --dry-run --format json + dws devapp webapp config --unified-app-id --homepage-url --dry-run --format json → 确认后加 --yes 5. 验证网页应用配置 - dws devapp webapp get --agent-id --format json - → 确认返回 homepageLink/pcHomepageLink 等 + dws devapp webapp get --unified-app-id --format json + → 确认返回 homepageUrl/pcHomepageUrl 等 6. 申请权限(按需) dws devapp permission list --unified-app-id --keyword "关键词" --format json diff --git a/skills/mono/references/products/devapp.md b/skills/mono/references/products/devapp.md index 570549c2..6f512755 100644 --- a/skills/mono/references/products/devapp.md +++ b/skills/mono/references/products/devapp.md @@ -8,7 +8,7 @@ 1. 所有命令加 `--format json`。 2. 写操作先 `--dry-run`,确认后才加 `--yes`。 -3. 应用名/appKey/customKey 命中多条时展示候选,不取第一条。 +3. 应用名/appKey 命中多条时展示候选,不取第一条。 4. 权限申请/取消只接受 `scopeValue`,不传 API 名或分组名。 5. 主动读取密钥走 `credentials get`;任何 `devapp get`/详情返回里的 `clientSecret/appSecret` 都按敏感凭证脱敏,不向用户展开。 @@ -17,9 +17,8 @@ | 优先级 | 标识 | 处理 | |--------|------|------| | 1 | `--unified-app-id` | 直接使用 | -| 2 | `--agent-id` / `--app-id` | 直接使用 | -| 3 | `--app-key` / `--custom-key` | 先查询,唯一命中才继续 | -| 4 | `--name` | 模糊搜索,写操作必须唯一命中 | +| 2 | `--app-key` | appKey/clientId,唯一命中才继续 | +| 3 | `--name` | 应用名称关键词,写操作必须唯一命中 | --- @@ -30,21 +29,17 @@ ```bash dws devapp list --format json dws devapp list --name DemoApp --format json -dws devapp list --agent-id 123456 --format json +dws devapp list --app-key dingxxx --format json ``` -MCP tool: `list_open_dev_apps_by_condition` +MCP tool: `list_open_dev_app` | CLI | MCP | 说明 | |-----|-----|------| -| `--page` | `currentPage` | 1-based,默认 1 | | `--page-size` | `pageSize` | 默认 20 | -| `--name` / `--keyword` | `appName` | 应用名搜索 | -| `--agent-id` | `agentId` | 精确定位 | +| `--cursor` | `cursor` | 游标,首次为空 | +| `--name` / `--keyword` | `name` | 应用名搜索 | | `--app-key` | `appKey` | appKey/clientId | -| `--creator` | `creator` | 创建人关键词 | -| `--sort` | `sortType` | 如 `gmt_modified` | -| `--order` | `sortOrder` | `asc` / `desc` | 应用状态字段:列表/详情原始字段里如果出现 `status` / `appStatus`,`0=IN_ACTIVE` 已停用、`1=ACTIVE` 已激活、`2=WAIT_ACTIVE` 待激活、`3=EXPIRED` 已过期。执行 `inactive/active` 后必须回读 `get` 或 `list`:看到 `status=0` 才算停用完成,看到 `status=1` 才算启用完成。`versionStatus` 是版本状态,不要和应用启停状态混用。 @@ -54,7 +49,7 @@ MCP tool: `list_open_dev_apps_by_condition` dws devapp get --unified-app-id UNIFIED_APP_ID --format json ``` -MCP tool: `get_open_dev_app_detail` +MCP tool: `get_dev_app` 详情主要用于定位和核验应用。若上游偶尔随详情返回 `clientSecret/appSecret`,必须脱敏处理,不要复制到回答里;主动读取凭证仍走 `credentials get`。 @@ -65,7 +60,7 @@ dws devapp create --name DemoApp --desc "内部应用" --type internal --dry-run dws devapp create --name DemoApp --desc "内部应用" --type internal --yes --format json ``` -MCP tool: `create_inner_app`。`--type` 只做 CLI 校验,当前仅支持 `internal`。 +MCP tool: `create_dev_app`。`--type` 只做 CLI 校验,当前仅支持 `internal`。 ### 修改 @@ -73,7 +68,7 @@ MCP tool: `create_inner_app`。`--type` 只做 CLI 校验,当前仅支持 `int dws devapp update --unified-app-id ID --name DemoApp2 --desc "新描述" --dry-run --format json ``` -MCP tool: `update_inner_app`。至少一个更新字段:`--name` / `--desc` / `--icon`。 +MCP tool: `update_dev_app`。至少一个更新字段:`--name` / `--desc` / `--icon`。 ### 停用 / 启用 @@ -82,7 +77,7 @@ dws devapp inactive --unified-app-id ID --dry-run --format json dws devapp active --unified-app-id ID --dry-run --format json ``` -MCP tools: `inactive_inner_app` / `active_inner_app` +MCP tools: `disable_dev_app` / `enable_dev_app` ### 删除 @@ -90,7 +85,7 @@ MCP tools: `inactive_inner_app` / `active_inner_app` dws devapp delete --unified-app-id ID --dry-run --format json ``` -MCP tool: `delete_inner_app`。删除前必须展示应用摘要,异步生效。 +MCP tool: `delete_dev_app`。删除前必须展示应用摘要,异步生效。 --- @@ -107,8 +102,8 @@ MCP tool: `get_open_dev_app_credentials`。返回含 `clientSecret/appSecret`, ### 网页应用 ```bash -dws devapp webapp get --agent-id AGENT_ID --format json -dws devapp webapp config --agent-id AGENT_ID --homepage-link https://example.com --dry-run --format json +dws devapp webapp get --unified-app-id UNIFIED_APP_ID --format json +dws devapp webapp config --unified-app-id UNIFIED_APP_ID --homepage-url https://example.com --dry-run --format json ``` MCP tools: `get_webapp_config` / `set_webapp_config` @@ -133,10 +128,10 @@ MCP tool: `list_open_dev_app_permissions` |-----|-----|------| | `--keyword` | `keyword` | 关键词搜索 | | `--status` | `authStatus` | `ALL/AUTHED/UNAUTHED` | -| `--scope-type` | `firstLevelType` | `APP/SNS`,空返回两者 | +| `--scope-type` | `scopeType` | `APP/SNS`,空返回两者 | | `--scope` | `scopeValue` | 单权限详情模式 | -| `--limit` | `limit` | 每页数量,默认 20,建议不超过 50 | -| `--offset` | `offset` | 翻页偏移量,默认 0 | +| `--page-size` | `pageSize` | 每页数量,默认 20,建议不超过 50 | +| `--cursor` | `cursor` | 游标,首次为空,用上一页 `nextCursor` 继续 | 权限状态判断: @@ -148,7 +143,7 @@ MCP tool: `list_open_dev_app_permissions` - `status=3` 停止申请,展示 `applyDisabledReason/displayMessage`。 - `authedStatusDesc` 细分展示:`OPENED`/`APPLIED`/`TO_BE_PUBLISHED` 表示已开通、已申请或待发布;`NOT_OPEN`/`NOT_APPLIED` 表示未开通/未申请;`AUDIT_PROCESSING` 表示审批中;`AUDIT_REFUSE` 表示审批未通过。能否操作仍以 `status`、`canEdit`、`canApplyDirectly`、`allowedActions` 为准。 -翻页:`--limit 50 --offset 0`(第1页)、`--offset 50`(第2页)、`--offset 100`(第3页),返回条数 < limit 表示末尾。 +翻页:首次传 `--page-size 50`,后续传 `--cursor NEXT_CURSOR`。无 `nextCursor` 或返回条数小于 `pageSize` 表示末尾。 ### 申请权限 diff --git a/skills/multi/dingtalk-devapp/SKILL.md b/skills/multi/dingtalk-devapp/SKILL.md index e53e513c..478caf07 100644 --- a/skills/multi/dingtalk-devapp/SKILL.md +++ b/skills/multi/dingtalk-devapp/SKILL.md @@ -1,6 +1,6 @@ --- name: dingtalk-devapp -description: 钉钉开放平台应用管理。Use when 用户说 开发者后台应用/开放平台应用/企业内部应用/查应用/创建应用/修改应用/删除应用/停用应用/启用应用/应用成员/安全配置/IP白名单/登录重定向/端内免登/agentId/clientId/appKey/appSecret/应用权限/权限点/创建机器人/智能体机器人/机器人配置/机器人回调/应用版本/版本发布/发布审核/选审批人/事件订阅/订阅事件/退订事件/eventCode。Distinct from dingtalk-devdoc(开放平台文档搜索) and dingtalk-doc(钉钉云文档)。命令前缀:dws devapp(兼容别名 dws app)。 +description: 钉钉开放平台应用管理。Use when 用户说 开发者后台应用/开放平台应用/企业内部应用/查应用/创建应用/修改应用/删除应用/停用应用/启用应用/应用成员/安全配置/IP白名单/登录重定向/端内免登/unifiedAppId/clientId/appKey/appSecret/应用权限/权限点/创建机器人/智能体机器人/机器人配置/机器人回调/应用版本/版本发布/发布审核/选审批人/事件订阅/订阅事件/退订事件/eventCode。Distinct from dingtalk-devdoc(开放平台文档搜索) and dingtalk-doc(钉钉云文档)。命令前缀:dws devapp(兼容别名 dws app)。 cli_version: ">=1.0.15" metadata: category: product @@ -25,7 +25,7 @@ metadata: `应用` 是泛词。只有出现以下信号才路由到 devapp: - `开放平台应用/开发者后台应用/企业内部应用/内部应用` -- `agentId/clientId/appKey/appSecret/customKey` +- `unifiedAppId/clientId/appKey/appSecret` - `应用权限/权限点/scopeValue/应用成员/安全配置/IP 白名单` - `创建机器人/智能体机器人/机器人配置/机器人回调地址`(→ `robot`) - `应用版本/版本发布/发布审核/选审批人`(→ `version`) @@ -37,7 +37,7 @@ metadata: 1. 所有命令加 `--format json`。 2. 写操作先 `--dry-run`,确认后才加 `--yes`。 -3. 应用名/appKey/customKey 命中多条时展示候选,不取第一条。 +3. 应用名/appKey 命中多条时展示候选,不取第一条。 4. 权限申请/取消只接受 `scopeValue`,不传 API 名或分组名。 5. 主动读取密钥走 `credentials get`;任何 `devapp get`/详情返回里的 `clientSecret/appSecret` 都按敏感凭证脱敏,不向用户展开。 diff --git a/skills/multi/dingtalk-devapp/references/app-crud.md b/skills/multi/dingtalk-devapp/references/app-crud.md index 7898e729..0d773886 100644 --- a/skills/multi/dingtalk-devapp/references/app-crud.md +++ b/skills/multi/dingtalk-devapp/references/app-crud.md @@ -9,31 +9,26 @@ | 优先级 | 标识 | 处理 | |--------|------|------| | 1 | `--unified-app-id` | 直接使用 | -| 2 | `--agent-id` / `--app-id` | 直接使用 | -| 3 | `--app-key` / `--custom-key` | 先查询,唯一命中才继续 | -| 4 | `--name` | 模糊搜索,写操作必须唯一命中 | +| 2 | `--app-key` | appKey/clientId,唯一命中才继续 | +| 3 | `--name` | 应用名称关键词,写操作必须唯一命中 | ## 应用列表 ```bash dws devapp list --format json dws devapp list --name DemoApp --format json -dws devapp list --agent-id 123456 --format json -dws devapp list --creator 张三 --sort gmt_modified --order desc --format json +dws devapp list --app-key dingxxx --format json +dws devapp list --name DemoApp --page-size 20 --cursor NEXT_CURSOR --format json ``` -MCP tool: `list_open_dev_apps_by_condition` +MCP tool: `list_open_dev_app` | CLI | MCP | 说明 | |-----|-----|------| -| `--page` | `currentPage` | 1-based,默认 1 | | `--page-size` | `pageSize` | 默认 20 | -| `--name` / `--keyword` | `appName` | 应用名搜索 | -| `--agent-id` | `agentId` | 精确定位 | +| `--cursor` | `cursor` | 游标,首次为空,用上一页 `nextCursor` 继续 | +| `--name` / `--keyword` | `name` | 应用名搜索 | | `--app-key` | `appKey` | appKey/clientId | -| `--creator` | `creator` | 创建人关键词 | -| `--sort` | `sortType` | 如 `gmt_modified` | -| `--order` | `sortOrder` | `asc` / `desc` | ## 应用状态字段 @@ -52,10 +47,11 @@ MCP tool: `list_open_dev_apps_by_condition` ```bash dws devapp get --unified-app-id UNIFIED_APP_ID --format json -dws devapp get --agent-id 123456 --format json +dws devapp get --app-key dingxxx --format json +dws devapp get --name DemoApp --format json ``` -MCP tool: `get_open_dev_app_detail` +MCP tool: `get_dev_app` 详情主要用于定位和核验应用。若上游偶尔随详情返回 `clientSecret/appSecret`,必须脱敏处理,不要复制到回答里;主动读取凭证仍走 `credentials get`。 @@ -66,7 +62,7 @@ dws devapp create --name DemoApp --desc "内部应用" --type internal --dry-run dws devapp create --name DemoApp --desc "内部应用" --type internal --yes --format json ``` -MCP tool: `create_inner_app` +MCP tool: `create_dev_app` | CLI | MCP | 必填 | |-----|-----|------| @@ -83,7 +79,7 @@ dws devapp update --unified-app-id ID --name DemoApp2 --desc "新描述" --dry-r dws devapp update --unified-app-id ID --name DemoApp2 --desc "新描述" --yes --format json ``` -MCP tool: `update_inner_app` +MCP tool: `update_dev_app` 至少提供一个更新字段:`--name` / `--desc` / `--icon`。 @@ -97,7 +93,7 @@ dws devapp active --unified-app-id ID --dry-run --format json dws devapp active --unified-app-id ID --yes --format json ``` -MCP tools: `inactive_inner_app` / `active_inner_app` +MCP tools: `disable_dev_app` / `enable_dev_app` 停用保留数据但应用不可用,可通过 `active` 恢复。 @@ -110,7 +106,7 @@ dws devapp delete --unified-app-id ID --dry-run --format json dws devapp delete --unified-app-id ID --yes --format json ``` -MCP tool: `delete_inner_app` +MCP tool: `delete_dev_app` 删除前必须展示应用摘要。删除为异步操作,成功后应用延迟从列表消失。 diff --git a/skills/multi/dingtalk-devapp/references/credentials-webapp.md b/skills/multi/dingtalk-devapp/references/credentials-webapp.md index 0f1dec02..9ce8010f 100644 --- a/skills/multi/dingtalk-devapp/references/credentials-webapp.md +++ b/skills/multi/dingtalk-devapp/references/credentials-webapp.md @@ -4,7 +4,8 @@ ```bash dws devapp credentials get --unified-app-id UNIFIED_APP_ID --format json -dws devapp credentials get --agent-id 123456 --format json +dws devapp credentials get --app-key dingxxx --format json +dws devapp credentials get --name DemoApp --format json ``` MCP tool: `get_open_dev_app_credentials` @@ -28,19 +29,19 @@ MCP tool: `get_open_dev_app_credentials` ## 网页应用查询 ```bash -dws devapp webapp get --agent-id 123456 --format json dws devapp webapp get --unified-app-id UNIFIED_APP_ID --format json +dws devapp webapp get --app-key dingxxx --format json ``` MCP tool: `get_webapp_config` -未配置网页应用前可能只返回 `agentId`。 +未配置网页应用前可能只返回空配置。 ## 网页应用配置 ```bash -dws devapp webapp config --agent-id 123456 --homepage-link https://example.com/mobile --dry-run --format json -dws devapp webapp config --agent-id 123456 --homepage-link https://example.com/mobile --pc-homepage-link https://example.com/pc --yes --format json +dws devapp webapp config --unified-app-id UNIFIED_APP_ID --homepage-url https://example.com/mobile --dry-run --format json +dws devapp webapp config --unified-app-id UNIFIED_APP_ID --homepage-url https://example.com/mobile --pc-homepage-url https://example.com/pc --yes --format json ``` MCP tool: `set_webapp_config` @@ -48,8 +49,8 @@ MCP tool: `set_webapp_config` | CLI | MCP | 说明 | |-----|-----|------| | `--h5-page-type` | `h5PageType` | 网页应用生效端 | -| `--homepage-link` | `homepageLink` | 移动端首页地址 | -| `--pc-homepage-link` | `pcHomepageLink` | PC 端首页地址 | -| `--omp-link` | `ompLink` | 管理后台地址 | +| `--homepage-url` | `homepageUrl` | 移动端首页地址 | +| `--pc-homepage-url` | `pcHomepageUrl` | PC 端首页地址 | +| `--omp-url` | `ompUrl` | 管理后台地址 | 至少提供一个配置字段。`h5PageType` 未显式传入时,不要假设固定默认值;配置后以 `webapp get` 回读为准(实跑可能返回 `mobile`)。 diff --git a/skills/multi/dingtalk-devapp/references/permissions.md b/skills/multi/dingtalk-devapp/references/permissions.md index 17cc6d95..3b5a310c 100644 --- a/skills/multi/dingtalk-devapp/references/permissions.md +++ b/skills/multi/dingtalk-devapp/references/permissions.md @@ -16,13 +16,12 @@ MCP tool: `list_open_dev_app_permissions` | CLI | MCP | 说明 | |-----|-----|------| | `--unified-app-id` | `unifiedAppId` | 应用定位 | -| `--agent-id` | `agentId` | 应用定位 | | `--keyword` | `keyword` | 权限名/API 名关键词 | | `--status` | `authStatus` | `ALL` / `AUTHED` / `UNAUTHED` | -| `--scope-type` | `firstLevelType` | `APP` / `SNS`,为空返回两者 | +| `--scope-type` | `scopeType` | `APP` / `SNS`,为空返回两者 | | `--scope` | `scopeValue` | 单权限详情模式 | -| `--limit` | `limit` | 每页返回数量,默认 20,建议不超过 50 | -| `--offset` | `offset` | 翻页偏移量,默认 0 | +| `--page-size` | `pageSize` | 每页返回数量,默认 20,建议不超过 50 | +| `--cursor` | `cursor` | 游标,首次为空,用上一页 `nextCursor` 继续 | **状态判断:** @@ -47,15 +46,14 @@ MCP tool: `list_open_dev_app_permissions` **翻页:** -权限列表支持 `--limit` + `--offset` 分页。一个应用可能有 150+ 个权限点,一次查不完时用 offset 翻页: +权限列表支持 `--page-size` + `--cursor` 分页。一个应用可能有 150+ 个权限点,一次查不完时用返回的 `nextCursor` 继续: ```bash -dws devapp permission list --unified-app-id ID --limit 50 --format json # 第 1 页 -dws devapp permission list --unified-app-id ID --limit 50 --offset 50 --format json # 第 2 页 -dws devapp permission list --unified-app-id ID --limit 50 --offset 100 --format json # 第 3 页 +dws devapp permission list --unified-app-id ID --page-size 50 --format json +dws devapp permission list --unified-app-id ID --page-size 50 --cursor NEXT_CURSOR --format json ``` -当返回条数 < limit 时表示已到末尾。 +当返回无 `nextCursor` 或返回条数小于 `pageSize` 时表示已到末尾。 **规则:** - `permission search` 和 `permission detail` 是 `list` 的 CLI 别名,不是独立 MCP tool。 diff --git a/skills/multi/dingtalk-devapp/references/workflows.md b/skills/multi/dingtalk-devapp/references/workflows.md index bed457c6..b07be648 100644 --- a/skills/multi/dingtalk-devapp/references/workflows.md +++ b/skills/multi/dingtalk-devapp/references/workflows.md @@ -8,7 +8,7 @@ 1. 创建应用 dws devapp create --name "应用名" --desc "描述" --type internal --dry-run --format json → 确认后加 --yes - → 记录返回的 unifiedAppId 和 agentId + → 记录返回的 unifiedAppId 和 appKey 2. 确认创建成功 dws devapp get --unified-app-id --format json @@ -17,12 +17,12 @@ dws devapp credentials get --unified-app-id --format json 4. 配置网页应用(按需) - dws devapp webapp config --agent-id --homepage-link --dry-run --format json + dws devapp webapp config --unified-app-id --homepage-url --dry-run --format json → 确认后加 --yes 5. 验证网页应用配置 - dws devapp webapp get --agent-id --format json - → 确认返回 homepageLink/pcHomepageLink 等 + dws devapp webapp get --unified-app-id --format json + → 确认返回 homepageUrl/pcHomepageUrl 等 6. 申请权限(按需) dws devapp permission list --unified-app-id --keyword "关键词" --format json