fix: align devapp cli with MCP schema
This commit is contained in:
1 parent
6f8c9173d3
commit
0f3c4ccbdd
14 files changed
+354
-402
No files matched your search
@@ -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. |
|
||||
|
||||
+122
-113
@@ -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 {
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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` 都按敏感凭证脱敏,不向用户展开。
|
||||
|
||||
|
||||
@@ -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`
|
||||
|
||||
删除前必须展示应用摘要。删除为异步操作,成功后应用延迟从列表消失。
|
||||
|
||||
|
||||
@@ -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`)。
|
||||
@@ -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。
|
||||
|
||||
@@ -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 <unifiedAppId> --format json
|
||||
@@ -17,12 +17,12 @@
|
||||
dws devapp credentials get --unified-app-id <unifiedAppId> --format json
|
||||
|
||||
4. 配置网页应用(按需)
|
||||
dws devapp webapp config --agent-id <agentId> --homepage-link <URL> --dry-run --format json
|
||||
dws devapp webapp config --unified-app-id <unifiedAppId> --homepage-url <URL> --dry-run --format json
|
||||
→ 确认后加 --yes
|
||||
|
||||
5. 验证网页应用配置
|
||||
dws devapp webapp get --agent-id <agentId> --format json
|
||||
→ 确认返回 homepageLink/pcHomepageLink 等
|
||||
dws devapp webapp get --unified-app-id <unifiedAppId> --format json
|
||||
→ 确认返回 homepageUrl/pcHomepageUrl 等
|
||||
|
||||
6. 申请权限(按需)
|
||||
dws devapp permission list --unified-app-id <unifiedAppId> --keyword "关键词" --format json
|
||||
|
||||
@@ -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` 表示末尾。
|
||||
|
||||
### 申请权限
|
||||
|
||||
|
||||
@@ -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` 都按敏感凭证脱敏,不向用户展开。
|
||||
|
||||
|
||||
@@ -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`
|
||||
|
||||
删除前必须展示应用摘要。删除为异步操作,成功后应用延迟从列表消失。
|
||||
|
||||
|
||||
@@ -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`)。
|
||||
@@ -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。
|
||||
|
||||
@@ -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 <unifiedAppId> --format json
|
||||
@@ -17,12 +17,12 @@
|
||||
dws devapp credentials get --unified-app-id <unifiedAppId> --format json
|
||||
|
||||
4. 配置网页应用(按需)
|
||||
dws devapp webapp config --agent-id <agentId> --homepage-link <URL> --dry-run --format json
|
||||
dws devapp webapp config --unified-app-id <unifiedAppId> --homepage-url <URL> --dry-run --format json
|
||||
→ 确认后加 --yes
|
||||
|
||||
5. 验证网页应用配置
|
||||
dws devapp webapp get --agent-id <agentId> --format json
|
||||
→ 确认返回 homepageLink/pcHomepageLink 等
|
||||
dws devapp webapp get --unified-app-id <unifiedAppId> --format json
|
||||
→ 确认返回 homepageUrl/pcHomepageUrl 等
|
||||
|
||||
6. 申请权限(按需)
|
||||
dws devapp permission list --unified-app-id <unifiedAppId> --keyword "关键词" --format json
|
||||
|
||||
Reference in new issue
Block a user