From 6bf8c7707a67d6d9217696d07f80bb5874ab5132 Mon Sep 17 00:00:00 2001 From: V-LiuShuang Date: Fri, 9 Oct 2026 15:56:45 +0800 Subject: [PATCH] ddd --- API-2609.md | 887 ------------------------------ chat-openapi.md | 229 -------- devco-client.md | 88 --- harness-api.md | 594 -------------------- harness-chat.md | 1021 ---------------------------------- harness-properties.md | 362 ------------ mingyan.md | 32 -- mis-debugging.json | 142 ----- se-agent-mcp-tool.md | 1220 ----------------------------------------- v260921.md | 203 ------- v260930.md | 118 ---- 11 files changed, 4896 deletions(-) delete mode 100644 API-2609.md delete mode 100644 chat-openapi.md delete mode 100644 devco-client.md delete mode 100644 harness-api.md delete mode 100644 harness-chat.md delete mode 100644 harness-properties.md delete mode 100644 mingyan.md delete mode 100644 mis-debugging.json delete mode 100644 se-agent-mcp-tool.md delete mode 100644 v260921.md delete mode 100644 v260930.md diff --git a/API-2609.md b/API-2609.md deleted file mode 100644 index 2940dde..0000000 --- a/API-2609.md +++ /dev/null @@ -1,887 +0,0 @@ -# 数据统计 - -以下是关于数据统计的API文档。 - -## 提交用户点赞/取消赞/写评论 - -- 请求地址:/mcp/metrics/append -- 请求方式:POST - -### 请求参数 - -| 参数名称 | 是否必传 | 类型 | 描述 | -|:-----|:-----|:-----|:-----| -| tag | 是 | String | 资源类型(agent=智能体、skill=技能、mcp_server=MCP服务) | -| operateType | 是 | String | 操作类型(like=点赞、like_withdraw=取消赞、write_comment=写评论) | -| resourceId | 是 | String | 资源ID,Agent传ID、Skill传skillId、MCP传mcpServerUuid | -| comment.content | 否 | String | 评论内容,最大500字 | -| comment.star | 否 | Number | 星级,1~5 | - -### 请求示例 - -```bash -curl -X POST {gateway}/mcp/metrics/append \ - -H "Content-Type: application/json" \ - -d '{ - "tag": "agent", - "operateType": "write_comment", - "resourceId": "123456", - "comment": { - "content": "很好用的智能体", - "star": 5 - } - }' -``` - -### 响应参数 - -| 参数名称 | 类型 | 描述 | -|:-----|:-----|:-----| -| code | Number | 返回码(200=成功) | -| msg | String | 提示信息 | -| data | Boolean | 操作是否成功 | - -### 成功示例 - -```json -{ - "code": 200, - "msg": "操作成功", - "data": true -} -``` - -### 失败示例 - -```json -{ - "code": 500, - "msg": "错误信息" -} -``` - -## 查询用户点赞/取消赞/写评论 - -- 请求地址:/mcp/metrics/detail -- 请求方式:POST - -### 请求参数 - -| 参数名称 | 是否必传 | 类型 | 描述 | -|:-----|:-----|:-----|:-----| -| tag | 是 | String | 资源类型(agent=智能体、skill=技能、mcp_server=MCP服务) | -| resourceId | 是 | String | 资源ID,Agent传ID、Skill传skillId、MCP传mcpServerUuid | -| comment.pageNum | 否 | Number | 分页页码,默认1 | -| comment.pageSize | 否 | Number | 分页条数,默认25 | - -### 请求示例 - -```bash -curl -X GET '{gateway}/mcp/metrics/detail' \ - -H "Content-Type: application/json" \ - -d '{ - "tag": "agent", - "resourceId": "123456", - "comment": { - "pageNum": 1, - "pageSize": 25 - } - }' -``` - -### 响应参数 - -| 参数名称 | 类型 | 描述 | -|:-----|:-----|:-----| -| code | Number | 返回码(200=成功) | -| msg | String | 提示信息 | -| data | Object | 返回数据 | -| data.appendCount | Number | 已有多少人添加 | -| data.likeCount | Number | 已有多少人点赞 | -| data.comments | Object | 评分与评论分页数据 | -| data.comments.total | Number | 总记录数 | -| data.comments.rows | Array | 评论列表 | -| data.comments.rows[].commentId | Number | 评论ID | -| data.comments.rows[].userId | String | 用户ID | -| data.comments.rows[].username | String | 用户名 | -| data.comments.rows[].nickname | String | 昵称 | -| data.comments.rows[].comment | String | 评论内容 | -| data.comments.rows[].time | String | 评论时间,格式 yyyy-MM-dd HH:mm:ss | -| data.comments.rows[].star | Number | 评分星级,1~5 | - -### 成功示例 - -```json -{ - "code": 200, - "msg": "操作成功", - "data": { - "appendCount": "100", - "likeCount": "50", - "comments": { - "total": 10, - "rows": [ - { - "commentId": "1", - "userId": "100", - "username": "user001", - "nickname": "张三", - "comment": "很好用的智能体", - "time": "2024-01-01 12:00:00", - "star": 5 - } - ] - } - } -} -``` - -### 失败示例 - -```json -{ - "code": 500, - "msg": "错误信息" -} -``` - -## 用户删除评论 - -- 请求地址:/mcp/metrics/comment -- 请求方式:DELETE - -### 请求参数 - -| 参数名称 | 是否必传 | 类型 | 描述 | -|:-----|:-----|:-----|:-----| -| commentId | 是 | Number | 评论ID(Query参数) | - -### 请求示例 - -```bash -curl -X DELETE '{gateway}/mcp/metrics/comment?commentId={commentId}' -``` - -### 响应参数 - -| 参数名称 | 类型 | 描述 | -|:-----|:-----|:-----| -| code | Number | 返回码(200=成功) | -| msg | String | 提示信息 | -| data | Boolean | 操作是否成功 | - -### 成功示例 - -```json -{ - "code": 200, - "msg": "操作成功", - "data": true -} -``` - -### 失败示例 - -```json -{ - "code": 500, - "msg": "错误信息" -} -``` - -# 客户端软件包 - -以下是关于客户端软件包的API文档。 - -## 版本列表 - -- 请求地址:/system/client/software -- 请求方式:GET - -### 请求参数 - -| 参数名称 | 是否必传 | 类型 | 描述 | -|:-----|:-----|:-----|:-----| -| identity | 是 | String | 客户端标识,如 devco | -| canary | 否 | Boolean | 传true则查询范围覆盖灰度版,否则只查正式版 | - -### 请求示例 - -```bash -curl -X GET '{gateway}/system/client/software?identity={identity}&canary={canary}' -``` - -### 响应参数 - -| 参数名称 | 类型 | 描述 | -|:-----|:-----|:-----| -| code | Number | 返回码(200=成功) | -| msg | String | 提示信息 | -| data | Array | 版本列表 | -| data[].releaseId | Number | 版本记录 ID | -| data[].versionNo | String | 版本号 | -| data[].releaseTime | String | 发布时间,格式 yyyy-MM-dd HH:mm:ss | -| data[].releaseNotes | String | 更新内容 | -| data[].packageOssId | Number | 安装包 OSS 主键;前端据此请求预签名下载地址 | -| data[].packageName | String | 安装包文件名 | -| data[].packageSize | Number | 安装包大小(字节) | -| data[].packageSizeDisplay | String | 安装包大小展示文案,如 12.50 MB | - -### 成功示例 - -```json -{ - "code": 200, - "msg": "操作成功", - "data": [ - { - "releaseId": "123456", - "versionNo": "1.0.0", - "releaseTime": "2024-01-01 12:00:00", - "releaseNotes": "更新内容", - "packageOssId": "789", - "packageName": "devco-1.0.0.exe", - "packageSize": 52428800, - "packageSizeDisplay": "50.00 MB" - } - ] -} -``` - -### 失败示例 - -```json -{ - "code": 500, - "msg": "错误信息" -} -``` - -## 查看最新版本 - -- 请求地址:/system/client/software/latest -- 请求方式:GET - -### 请求参数 - -| 参数名称 | 是否必传 | 类型 | 描述 | -|:-----|:-----|:-----|:-----| -| identity | 是 | String | 客户端标识,如 devco | -| canary | 否 | Boolean | 传true则查询范围覆盖灰度版,否则只查正式版 | - -### 请求示例 - -```bash -curl -X GET '{gateway}/system/client/software/latest?identity={identity}&canary={canary}' -``` - -### 响应参数 - -| 参数名称 | 类型 | 描述 | -|:-----|:-----|:-----| -| code | Number | 返回码(200=成功) | -| msg | String | 提示信息 | -| data | Object | 版本信息 | -| data.releaseId | Number | 版本记录 ID | -| data.versionNo | String | 版本号 | -| data.releaseTime | String | 发布时间,格式 yyyy-MM-dd HH:mm:ss | -| data.releaseNotes | String | 更新内容 | -| data.packageOssId | Number | 安装包 OSS 主键 | -| data.packageName | String | 安装包文件名 | -| data.packageSize | Number | 安装包大小(字节) | -| data.packageSizeDisplay | String | 安装包大小展示文案,如 12.50 MB | - -### 成功示例 - -```json -{ - "code": 200, - "msg": "操作成功", - "data": { - "releaseId": "123456", - "versionNo": "1.0.0", - "releaseTime": "2024-01-01 12:00:00", - "releaseNotes": "更新内容", - "packageOssId": "789", - "packageName": "devco-1.0.0.exe", - "packageSize": 52428800, - "packageSizeDisplay": "50.00 MB" - } -} -``` - -### 失败示例 - -```json -{ - "code": 500, - "msg": "错误信息" -} -``` - -## 下载软件包 - -- 请求地址:/system/client/software/download/{ossId} -- 请求方式:GET - -### 请求参数 - -| 参数名称 | 是否必传 | 类型 | 描述 | -|:-----|:-----|:-----|:-----| -| ossId | 是 | Number | OSSID,安装包在OSS中的唯一标识 | - -### 请求示例 - -```bash -curl -X GET {gateway}/system/client/software/download/{ossId} -``` - -### 响应参数 - -直接返回文件流下载。 - -### 失败示例 - -```json -{ - "code": 500, - "msg": "错误信息" -} -``` - -## 查看版本信息 - -- 请求地址:/system/client/software/{releaseId} -- 请求方式:GET - -### 请求参数 - -| 参数名称 | 是否必传 | 类型 | 描述 | -|:-----|:-----|:-----|:-----| -| releaseId | 是 | Number | 版本ID | - -### 请求示例 - -```bash -curl -X GET {gateway}/system/client/software/{releaseId} -``` - -### 响应参数 - -| 参数名称 | 类型 | 描述 | -|:-----|:-----|:-----| -| code | Number | 返回码(200=成功) | -| msg | String | 提示信息 | -| data | Object | 版本信息 | -| data.releaseId | Number | 版本记录 ID | -| data.versionNo | String | 版本号 | -| data.releaseTime | String | 发布时间,格式 yyyy-MM-dd HH:mm:ss | -| data.releaseNotes | String | 更新内容 | -| data.packageOssId | Number | 安装包 OSS 主键 | -| data.packageName | String | 安装包文件名 | -| data.packageSize | Number | 安装包大小(字节) | -| data.packageSizeDisplay | String | 安装包大小展示文案,如 12.50 MB | - -### 成功示例 - -```json -{ - "code": 200, - "msg": "操作成功", - "data": { - "releaseId": "123456", - "versionNo": "1.0.0", - "releaseTime": "2024-01-01 12:00:00", - "releaseNotes": "更新内容", - "packageOssId": "789", - "packageName": "devco-1.0.0.exe", - "packageSize": 52428800, - "packageSizeDisplay": "50.00 MB" - } -} -``` - -### 失败示例 - -```json -{ - "code": 500, - "msg": "错误信息" -} -``` - -## 新建版本 - -- 请求地址:/system/client/software -- 请求方式:POST - -### 请求参数 - -| 参数名称 | 是否必传 | 类型 | 描述 | -|:-----|:-----|:-----|:-----| -| identity | 是 | String | 客户端标识,如 devco | -| state | 是 | String | 版本状态,canary=灰度版、release=正式版 | -| version | 是 | String | 版本号,如 1.0.0 | -| releaseTime | 否 | String | 发布时间,格式 yyyy-MM-dd HH:mm:ss;省略则取当前时间 | -| releaseNotes | 否 | String | 更新日志(富文本 HTML) | -| ossId | 是 | Number | 安装包 OSS ID | - -### 请求示例 - -```bash -curl -X POST {gateway}/system/client/software \ - -H "Content-Type: application/json" \ - -d '{ - "identity": "devco", - "state": "release", - "version": "1.0.0", - "releaseTime": "2024-01-01 12:00:00", - "releaseNotes": "

更新日志

", - "ossId": 789 - }' -``` - -### 响应参数 - -| 参数名称 | 类型 | 描述 | -|:-----|:-----|:-----| -| code | Number | 返回码(200=成功) | -| msg | String | 提示信息 | -| data | Object | 版本信息 | -| data.releaseId | Number | 版本记录 ID | -| data.versionNo | String | 版本号 | -| data.releaseTime | String | 发布时间,格式 yyyy-MM-dd HH:mm:ss | -| data.releaseNotes | String | 更新内容 | -| data.packageOssId | Number | 安装包 OSS 主键 | -| data.packageName | String | 安装包文件名 | -| data.packageSize | Number | 安装包大小(字节) | -| data.packageSizeDisplay | String | 安装包大小展示文案,如 12.50 MB | - -### 成功示例 - -```json -{ - "code": 200, - "msg": "操作成功", - "data": { - "releaseId": "123456", - "versionNo": "1.0.0", - "releaseTime": "2024-01-01 12:00:00", - "releaseNotes": "

更新日志

", - "packageOssId": "789", - "packageName": "devco-1.0.0.exe", - "packageSize": 52428800, - "packageSizeDisplay": "50.00 MB" - } -} -``` - -### 失败示例 - -```json -{ - "code": 500, - "msg": "错误信息" -} -``` - -## 编辑版本信息 - -- 请求地址:/system/client/software/{releaseId} -- 请求方式:PUT - -### 请求参数 - -| 参数名称 | 是否必传 | 类型 | 描述 | -|:-----|:-----|:-----|:-----| -| releaseId | 是 | Number | 版本ID(路径参数) | -| identity | 是 | String | 客户端标识,如 devco | -| state | 是 | String | 版本状态,canary=灰度版、release=正式版 | -| version | 是 | String | 版本号,如 1.0.0 | -| releaseTime | 否 | String | 发布时间,格式 yyyy-MM-dd HH:mm:ss;省略则取当前时间 | -| releaseNotes | 否 | String | 更新日志(富文本 HTML) | -| ossId | 是 | Number | 安装包 OSS ID | - -### 请求示例 - -```bash -curl -X PUT {gateway}/system/client/software/{releaseId} \ - -H "Content-Type: application/json" \ - -d '{ - "identity": "devco", - "state": "release", - "version": "1.0.1", - "releaseTime": "2024-01-02 12:00:00", - "releaseNotes": "

修复bug

", - "ossId": 790 - }' -``` - -### 响应参数 - -| 参数名称 | 类型 | 描述 | -|:-----|:-----|:-----| -| code | Number | 返回码(200=成功) | -| msg | String | 提示信息 | -| data | Object | 版本信息 | -| data.releaseId | Number | 版本记录 ID | -| data.versionNo | String | 版本号 | -| data.releaseTime | String | 发布时间,格式 yyyy-MM-dd HH:mm:ss | -| data.releaseNotes | String | 更新内容 | -| data.packageOssId | Number | 安装包 OSS 主键 | -| data.packageName | String | 安装包文件名 | -| data.packageSize | Number | 安装包大小(字节) | -| data.packageSizeDisplay | String | 安装包大小展示文案,如 12.50 MB | - -### 成功示例 - -```json -{ - "code": 200, - "msg": "操作成功", - "data": { - "releaseId": "123456", - "versionNo": "1.0.1", - "releaseTime": "2024-01-02 12:00:00", - "releaseNotes": "

修复bug

", - "packageOssId": "790", - "packageName": "devco-1.0.1.exe", - "packageSize": 52428800, - "packageSizeDisplay": "50.00 MB" - } -} -``` - -### 失败示例 - -```json -{ - "code": 500, - "msg": "参数[releaseId]不能为空" -} -``` - -## 删除版本 - -- 请求地址:/system/client/software/{releaseId} -- 请求方式:DELETE - -### 请求参数 - -| 参数名称 | 是否必传 | 类型 | 描述 | -|:-----|:-----|:-----|:-----| -| releaseId | 是 | Number | 版本ID(路径参数) | - -### 请求示例 - -```bash -curl -X DELETE {gateway}/system/client/software/{releaseId} -``` - -### 响应参数 - -| 参数名称 | 类型 | 描述 | -|:-----|:-----|:-----| -| code | Number | 返回码(200=成功) | -| msg | String | 提示信息 | -| data | Boolean | 操作是否成功 | - -### 成功示例 - -```json -{ - "code": 200, - "msg": "操作成功", - "data": true -} -``` - -### 失败示例 - -```json -{ - "code": 500, - "msg": "错误信息" -} -``` - -# 客户端软件包测试成员管理 - -以下是关于客户端软件包测试成员管理的API文档。 - -## 查看详情 - -- 请求地址:/system/client/software/canary -- 请求方式:GET - -### 请求参数 - -| 参数名称 | 是否必传 | 类型 | 描述 | -|:-----|:-----|:-----|:-----| -| identity | 是 | String | 客户端标识,如 devco | - -### 请求示例 - -```bash -curl -X GET '{gateway}/system/client/software/canary?identity={identity}' -``` - -### 响应参数 - -| 参数名称 | 类型 | 描述 | -|:-----|:-----|:-----| -| code | Number | 返回码(200=成功) | -| msg | String | 提示信息 | -| data | Object | 灰度配置信息 | -| data.identity | String | 客户端标识 | -| data.deptIds | Array | 部门ID列表 | -| data.userIds | Array | 用户ID列表 | -| data.dept | Array | 部门详情列表 | -| data.dept[].id | Number | 部门ID | -| data.dept[].name | String | 部门名称 | -| data.user | Array | 用户详情列表 | -| data.user[].id | Number | 用户ID | -| data.user[].name | String | 用户名称 | - -### 成功示例 - -```json -{ - "code": 200, - "msg": "操作成功", - "data": { - "identity": "devco", - "deptIds": [1, 2, 3], - "userIds": [100, 200], - "dept": [ - { - "id": 1, - "name": "研发部" - }, - { - "id": 2, - "name": "测试部" - } - ], - "user": [ - { - "id": 100, - "name": "张三" - }, - { - "id": 200, - "name": "李四" - } - ] - } -} -``` - -### 失败示例 - -```json -{ - "code": 500, - "msg": "错误信息" -} -``` - -## 添加用户或部门 - -- 请求地址:/system/client/software/canary -- 请求方式:PUT - -### 请求参数 - -| 参数名称 | 是否必传 | 类型 | 描述 | -|:-----|:-----|:-----|:-----| -| identity | 是 | String | 客户端标识,如 devco | -| ids | 否 | Array | 用户ID或部门ID集合 | -| type | 是 | Number | 类型,1=用户、2=部门 | - -### 请求示例 - -```bash -curl -X PUT {gateway}/system/client/software/canary \ - -H "Content-Type: application/json" \ - -d '{ - "identity": "devco", - "ids": [100, 200], - "type": 1 - }' -``` - -### 响应参数 - -| 参数名称 | 类型 | 描述 | -|:-----|:-----|:-----| -| code | Number | 返回码(200=成功) | -| msg | String | 提示信息 | -| data | Boolean | 操作是否成功 | - -### 成功示例 - -```json -{ - "code": 200, - "msg": "操作成功", - "data": true -} -``` - -### 失败示例 - -```json -{ - "code": 500, - "msg": "错误信息" -} -``` - -## 删除用户或部门 - -- 请求地址:/system/client/software/canary -- 请求方式:DELETE - -### 请求参数 - -| 参数名称 | 是否必传 | 类型 | 描述 | -|:-----|:-----|:-----|:-----| -| identity | 是 | String | 客户端标识,如 devco | -| ids | 否 | Array | 用户ID或部门ID集合 | -| type | 是 | Number | 类型,1=用户、2=部门 | - -### 请求示例 - -```bash -curl -X DELETE {gateway}/system/client/software/canary \ - -H "Content-Type: application/json" \ - -d '{ - "identity": "devco", - "ids": [100], - "type": 1 - }' -``` - -### 响应参数 - -| 参数名称 | 类型 | 描述 | -|:-----|:-----|:-----| -| code | Number | 返回码(200=成功) | -| msg | String | 提示信息 | -| data | Boolean | 操作是否成功 | - -### 成功示例 - -```json -{ - "code": 200, - "msg": "操作成功", - "data": true -} -``` - -### 失败示例 - -```json -{ - "code": 500, - "msg": "错误信息" -} -``` - -# 智能体管理 - -以下是关于智能体管理的API文档。 - -## 禁用或启用智能体 - -- 请求地址:/paw/agents/available -- 请求方式:POST - -### 请求参数 - -| 参数名称 | 是否必传 | 类型 | 描述 | -|:-----|:-----|:-----|:-----| -| agentId | 是 | String | 智能体ID | -| available | 是 | Boolean | true=启用、false=禁用 | - -### 请求示例 - -```bash -curl -X POST {gateway}/paw/agents/available \ - -H "Content-Type: application/json" \ - -d '{ - "agentId": "123456", - "available": true - }' -``` - -### 响应参数 - -| 参数名称 | 类型 | 描述 | -|:-----|:-----|:-----| -| code | Number | 返回码(200=成功) | -| msg | String | 提示信息 | -| data | Boolean | 操作是否成功 | - -### 成功示例 - -```json -{ - "code": 200, - "msg": "操作成功", - "data": true -} -``` - -### 失败示例 - -```json -{ - "code": 500, - "msg": "错误信息" -} -``` - -## 移除智能体(老接口) - -- 请求地址:/paw/agents/{agentId} -- 请求方式:DELETE - -### 请求参数 - -| 参数名称 | 是否必传 | 类型 | 描述 | -|:-----|:-----|:-----|:-----| -| agentId | 是 | String | 智能体ID | - -### 请求示例 - -```bash -curl -X 请求方式:DELETE {gateway}/paw/agents/123456 -``` - -### 响应参数 - -| 参数名称 | 类型 | 描述 | -|:-----|:-----|:-----| -| code | Number | 返回码(200=成功) | -| msg | String | 提示信息 | - -### 成功示例 - -```json -{ - "code": 200, - "msg": "操作成功" -} -``` - -### 失败示例 - -```json -{ - "code": 500, - "msg": "错误信息" -} -``` \ No newline at end of file diff --git a/chat-openapi.md b/chat-openapi.md deleted file mode 100644 index e03a1a1..0000000 --- a/chat-openapi.md +++ /dev/null @@ -1,229 +0,0 @@ -# MIS-Paw 开放 API 使用文档 - -> 面向外部接入系统的开发者。当前提供文件上传和 Agent 对话两个接口。 -> -> API 根地址示例:`https://misagent.lcfuturecenter.com` - -## 1. 快速开始 - -外部系统只需要使用 MIS-Paw 管理页面创建的完整 API Key。API Key 会唯一定位一个 Agent,因此请求中不需要传 `agentId`。 - -对外接口不要求登录态,也不要求 `Authorization`、`Clientid` 或 `Subsystem`。两个接口都必须携带: - -```http -X-Paw-Api-Key: <完整 API Key> -``` - -API Key 必须通过 HTTPS 传输,不要写入日志、前端源码、URL 查询参数或错误信息。管理页面列表中的 Key 可能被掩码显示,调用时请复制完整值。 - -## 2. 接口总览 - -| 方法 | 路径 | 用途 | 请求类型 | 成功响应 | -|---|---|---|---|---| -| `POST` | `/api/files/upload` | 上传 Agent 对话附件 | `multipart/form-data` | JSON | -| `POST` | `/api/shareChat` | 调用 Agent 对话 | `application/json` | SSE | - -网关和服务部署在带有统一前缀的环境时,将前缀拼接到上述路径前。例如实际地址可能是 `/paw/api/shareChat`;请以部署环境提供的 API 根地址为准。 - -## 3. 文件上传:`POST /api/files/upload` - -### 3.1 请求 - -请求头: - -| Header | 必填 | 值 | -|---|---:|---| -| `X-Paw-Api-Key` | 是 | 当前 Agent 的完整 API Key | -| `Content-Type` | 自动 | `multipart/form-data`,由 HTTP 客户端自动生成 boundary | - -表单字段: - -| 字段 | 必填 | 类型 | 说明 | -|---|---:|---|---| -| `file` | 是 | Binary | 要上传的文件 | - -示例: - -```bash -curl --fail-with-body -X POST "https://misagent.lcfuturecenter.com/api/files/upload" \ - -H "X-Paw-Api-Key: <完整 API Key>" \ - -F "file=@./demo.txt" -``` - -不要手动设置 `Content-Type: multipart/form-data`,否则可能缺少 boundary;让 curl、浏览器或 SDK 自动设置。 - -### 3.2 成功响应 - -```http -HTTP/1.1 200 OK -Content-Type: application/json -``` - -```json -{ - "code": 200, - "msg": "操作成功", - "data": { - "url": "/root/output/paw15004/.qwenpaw/workspaces/9U5Y2t5/media/1b3e01157eb74bb39c0329dc47d6235c_demo.txt", - "fileName": "demo.txt", - "fileSize": 84757 - } -} -``` - -`data.url` 是 QwenPaw 当前 Agent Workspace `media` 目录中的文件引用。它是不透明值,调用方必须完整保存并在对话请求中原样传回,不要拼接、截断、URL 解码后重组或自行构造本地路径。 - -文件上传调用不依赖缓存头完成业务处理;部署环境如配置了响应缓存策略,应将该响应设置为 `Cache-Control: no-store`。 - -上传接口不创建 Session,也不返回 `X-Paw-Session-Id`。文件真正被对话使用后,才会按 QwenPaw 原生机制进入聊天文件记录。 - -## 4. Agent 对话:`POST /api/shareChat` - -### 4.1 请求头 - -| Header | 必填 | 说明 | -|---|---:|---| -| `X-Paw-Api-Key` | 是 | 定位 Agent 并完成 API Key 鉴权 | -| `X-Paw-Session-Id` | 否 | 续聊时传上一次响应中的值;首次请求可省略 | -| `Accept` | 否 | 推荐 `text/event-stream`;缺少时默认为 SSE。当前仅支持流式,不支持 `application/json` | -| `Content-Type` | 是 | `application/json` | - -本接口不要求 `Authorization`、`Clientid`、`Subsystem`。不要把 API Key 或 Session ID 放在 URL 查询参数中。 - -### 4.2 请求体 - -```json -{ - "message": "这个文件内容是什么", - "files": [ - { - "url": "/root/output/paw15004/.qwenpaw/workspaces/9U5Y2t5/media/1b3e01157eb74bb39c0329dc47d6235c_demo.txt", - "fileName": "demo.txt", - "fileSize": 84757 - } - ] -} -``` - -字段说明: - -| 字段 | 必填 | 类型 | 说明 | -|---|---:|---|---| -| `message` | 是 | String | 用户消息;去除首尾空白后不能为空,即使只提问文件也必须填写 | -| `files` | 否 | Array | 文件引用列表;不传等同于空数组 | -| `files[].url` | 是(每个文件) | String | `/api/files/upload` 成功响应中的 `data.url`,必须原样传回 | -| `files[].fileName` | 是(每个文件) | String | 上传响应中的 `data.fileName` | -| `files[].fileSize` | 是(每个文件) | Long | 上传响应中的 `data.fileSize`,单位为字节 | - -对外 DTO 不接收 `agentId`、`userId`、`sessionId`、`channel`、`stream` 或 QwenPaw Runtime 私有字段。 - -## 5. 流式对话(SSE) - -### 5.1 首次请求 - -省略 `X-Paw-Session-Id`,服务端会按 QwenPaw Console 规则生成 Session ID,并在响应头返回: - -```bash -curl -N --fail-with-body -X POST "https://misagent.lcfuturecenter.com/api/shareChat" \ - -H "X-Paw-Api-Key: <完整 API Key>" \ - -H "Accept: text/event-stream" \ - -H "Content-Type: application/json" \ - -d '{"message":"你好","files":[]}' -``` - -成功响应头: - -```http -Content-Type: text/event-stream;charset=UTF-8 -Cache-Control: no-cache, no-transform -X-Paw-Session-Id: 1788156264286 -``` - -响应体是现有 QwenPaw Console Chat 的 SSE 事件流,事件顺序和结束语义保持一致。客户端应按标准 SSE 读取 `data:` 事件,不要假设每一帧都是完整的最终答案。 - -### 5.2 续聊 - -保存首次响应的 `X-Paw-Session-Id`,后续请求用同一个 API Key 和同一个 Session ID: - -```bash -curl -N --fail-with-body -X POST "https://misagent.lcfuturecenter.com/api/shareChat" \ - -H "X-Paw-Api-Key: <完整 API Key>" \ - -H "X-Paw-Session-Id: 1788156264286" \ - -H "Accept: text/event-stream" \ - -H "Content-Type: application/json" \ - -d '{"message":"继续说明","files":[]}' -``` - -Session ID 是会话上下文标识,不是 API Key,也不是登录凭证。接入系统应按自己的用户或业务会话保存它;不同 API Key 不要主动共享同一个 Session ID。同一个 Session 同时只能有一个进行中的对话请求,否则可能返回 `409 SESSION_BUSY`。 - -## 6. 错误处理 - -建连前的错误通常返回 MIS 统一 JSON 错误结构: - -```json -{ - "code": 401, - "msg": "API Key 无效或已过期", - "data": null, - "errorCode": "API_KEY_INVALID" -} -``` - -常见状态码: - -| HTTP | 场景 | -|---:|---| -| `400` | `message` 为空、文件元数据缺失或 Session 格式不合法 | -| `401` | 缺少、无效或已过期的 `X-Paw-Api-Key` | -| `403` | API Key 已停用,或文件不属于该 Key 定位的 Agent Workspace | -| `406` | `Accept` 不支持 | -| `409` | 同一个 Agent/Session 已有进行中的 Chat | -| `413` | 文件超过配置的大小限制 | -| `422` | Agent 创建人的模型 Key 不可用 | -| `503` | Agent 或 QwenPaw 实例不可用 | - -如果 SSE 已经开始,之后发生的 Agent 错误仍以 SSE 事件返回,不会中途切换成 JSON。客户端需要同时处理 HTTP 建连错误和 SSE 错误事件。 - -## 7. 文件+对话完整流程 - -1. 使用 `X-Paw-Api-Key` 调用 `/api/files/upload`。 -2. 保存响应中的 `data.url`、`data.fileName`、`data.fileSize`。 -3. 调用 `/api/shareChat`,将这三个值放入 `files`,并填写 `message`。 -4. 保存响应头 `X-Paw-Session-Id`。 -5. 后续续聊时使用同一个 API Key,并回传保存的 Session ID。 - -```bash -# 1. 上传文件 -curl -sS -X POST "https://misagent.lcfuturecenter.com/api/files/upload" \ - -H "X-Paw-Api-Key: <完整 API Key>" \ - -F "file=@./demo.txt" - -# 2. 使用上传返回的 url 对话 -curl -N -X POST "https://misagent.lcfuturecenter.com/api/shareChat" \ - -H "X-Paw-Api-Key: <完整 API Key>" \ - -H "Accept: text/event-stream" \ - -H "Content-Type: application/json" \ - -d '{ - "message": "这个文件内容是什么", - "files": [{ - "url": "<上一步 data.url>", - "fileName": "demo.txt", - "fileSize": 84757 - }] - }' -``` - -## 8. 浏览器跨域调用 - -如果由浏览器直接调用,预检请求不需要 API Key,但实际 `POST` 必须携带。前端需要能够读取 `X-Paw-Session-Id`,服务端跨域配置应允许以下请求头并暴露 Session 响应头: - -```text -Allowed-Headers: Content-Type, Accept, X-Paw-Api-Key, X-Paw-Session-Id -Exposed-Headers: X-Paw-Session-Id, Content-Type, Cache-Control -``` - -不要在浏览器端把完整 API Key 固化到公开前端代码中;更适合由受控的后端接入系统代理调用。 - -## 9. 重试与费用提示 - -一期没有 HTTP 请求级幂等键。客户端在未收到完整响应时重试,可能重新启动一次 Agent 对话并产生新的模型费用;只有同一 Session 尚未结束时,才可能收到 `409 SESSION_BUSY`。请由调用方控制超时、重试次数和同一 Session 的并发请求。 diff --git a/devco-client.md b/devco-client.md deleted file mode 100644 index 2a17c03..0000000 --- a/devco-client.md +++ /dev/null @@ -1,88 +0,0 @@ -# 客户端软件包 - -以下是客户端软件包相关接口的API文档。 - -## 查看最新版本 - -查询指定客户端(`identity`)的最新版本信息,若带 `canary=true` 且当前登录用户在灰度范围内,则查询范围覆盖灰度版,否则仅返回正式版。 - -- 请求地址:/client/software/latest -- 请求方式:GET - -### 请求参数 - -| 参数名称 | 是否必传 | 类型 | 描述 | -|:-----|:-----|:-----|:-----| -| identity | 是 | String | 客户端标识,示例:devco | -| canary | 否 | Boolean | 传true则查询范围覆盖灰度版,否则只查正式版;不传等同于false | - -### 请求示例 - -```bash -curl -X GET {gateway}/client/software/latest?identity=devco&canary=true -``` - -### 响应参数 - -| 参数名称 | 类型 | 描述 | -|:-----|:-----|:-----| -| code | Number | 返回码(200=成功) | -| msg | String | 提示信息 | -| data | Object | 版本信息;无匹配版本时为 null | -| data.releaseId | String | 版本记录 ID(Long 序列化为字符串) | -| data.versionNo | String | 版本号,如 1.0.0 | -| data.releaseTime | String | 发布时间,格式 yyyy-MM-dd HH:mm:ss(GMT+8) | -| data.releaseNotes | String | 更新内容 | -| data.packageOssId | String | 安装包 OSS 主键(Long 序列化为字符串);前端据此请求预签名下载地址 | -| data.packageName | String | 安装包文件名 | -| data.packageSize | Number | 安装包大小(字节) | -| data.packageSizeDisplay | String | 安装包大小展示文案,如 12.50 MB | -| data.state | String | 版本状态:canary=灰度版、release=正式版 | - -### 成功示例 - -```json -{ - "code": 200, - "msg": "操作成功", - "data": { - "releaseId": "1928374655647382", - "versionNo": "1.0.0", - "releaseTime": "2026-09-28 10:00:00", - "releaseNotes": "修复已知问题,优化启动速度", - "packageOssId": "1928374655647383", - "packageName": "devco-1.0.0-setup.exe", - "packageSize": 13107200, - "packageSizeDisplay": "12.50 MB", - "state": "release" - } -} -``` - -### 无版本示例 - -查询范围内没有任何版本时,`data` 为 `null`: - -```json -{ - "code": 200, - "msg": "操作成功", - "data": null -} -``` - -### 失败示例 - -```json -{ - "code": 500, - "msg": "错误信息" -} -``` - -### 备注 - -- 结果按 `releaseTime` 倒序取第一条,即为最新版本。 -- 未登录(`LoginHelper.getLoginUser()` 为 null)时仅返回正式版,忽略 `canary`。 -- `packageName`、`packageSize`、`packageSizeDisplay` 在数据库未记录安装包信息时,会尝试从 OSS 元数据补全;OSS 查询失败时保持为空,不影响接口返回。 -- 下载安装包请调用 `GET /client/software/download/{ossId}`,其中 `ossId` 取 `data.packageOssId`。 diff --git a/harness-api.md b/harness-api.md deleted file mode 100644 index f0a2c74..0000000 --- a/harness-api.md +++ /dev/null @@ -1,594 +0,0 @@ -# SE智能体相关接口 - -以下是对应 `/harness` 路由前缀的 SE 智能体 HTTP 接口文档。 - -## 根据用户意图选子智能体 - -### 基本信息 - -| 项目 | 说明 | -|------|------| -| 接口地址 | `/harness/choose/subagent` | -| 请求方式 | `POST` | -| Content-Type | `application/json` | -| 响应类型 | `text/event-stream` (SSE) | -| 接口描述 | 根据用户意图选择子智能体 | - -### 请求参数 (Request Body) - -| 参数名 | 类型 | 必填 | 说明 | -|--------|------|------|------| -| sessionId | Long | 是 | 会话ID | -| username | String | 是 | 用户名 | -| input | String | 是 | 用户输入内容 | - -#### 请求示例 - -```json -{ - "sessionId": 1001, - "username": "zhangsan", - "input": "帮我查看代码中的空指针异常" -} -``` - -### 响应参数 (Response Body) - -| 参数名 | 类型 | 说明 | -|--------|------|------| -| code | int | 状态码 (200=成功, 500=失败) | -| msg | String | 消息内容 | -| data | Object | 响应数据对象 | -| data.sessionId | String | 会话ID | -| data.username | String | 用户名 | -| data.input | String | 用户输入 | -| data.output | String | 主智能体的输出 | -| data.subAgentId | String | 子智能体ID | - -#### 成功响应示例 - -```json -{ - "code": 200, - "msg": "操作成功", - "data": { - "sessionId": "1001", - "username": "zhangsan", - "input": "帮我查看代码中的空指针异常", - "output": "正在为您分配合适的子智能体...", - "subAgentId": "code-review-agent" - } -} -``` - -#### 失败响应示例 - -```json -{ - "code": 500, - "msg": "参数[sessionId]不能为空", - "data": null -} -``` - ---- - -## 保存子智能体回复 - -### 基本信息 - -| 项目 | 说明 | -|------|------| -| 接口地址 | `/harness/subagent/output` | -| 请求方式 | `POST` | -| Content-Type | `application/json` | -| 响应类型 | `text/event-stream` (SSE) | -| 接口描述 | 保存来自paw的子智能体回复内容 | - -### 请求参数 (Request Body) - -| 参数名 | 类型 | 必填 | 说明 | -|--------|------|------|------| -| sessionId | Long | 是 | 会话ID | -| username | String | 是 | 用户名 | -| subagentOutput | String | 是 | 子智能体回复内容 | -| context | Map | 否 | 自定义扩展数据 | - -#### 请求示例 - -```json -{ - "sessionId": 1001, - "username": "zhangsan", - "subagentOutput": "在第42行发现潜在的空指针异常,建议添加空值检查...", - "context": { - "key1": "xxx", - "key2": "yyy" - } -} -``` - -### 响应参数 (Response Body) - -| 参数名 | 类型 | 说明 | -|--------|------|------| -| code | int | 状态码 (200=成功, 500=失败) | -| msg | String | 消息内容 | -| data | Long | 保存的消息ID | - -#### 成功响应示例 - -```json -{ - "code": 200, - "msg": "操作成功", - "data": 12345 -} -``` - -#### 失败响应示例 - -```json -{ - "code": 500, - "msg": "参数[username]不能为空", - "data": null -} -``` - ---- - -## 通用说明 - -### 状态码说明 - -| 状态码 | 说明 | -|--------|------| -| 200 | 操作成功 | -| 500 | 操作失败 | - -### 错误码说明 - -| 错误信息 | 说明 | -|----------|------| -| 参数[sessionId]不能为空 | sessionId为必填参数 | -| 参数[username]不能为空 | username为必填参数 | -| 参数[input]不能为空 | input为必填参数 | -| 参数[subagentOutput]不能为空 | subagentOutput为必填参数 | -| 操作失败 | 服务器内部错误 | - - -## 开启一个会话窗口 - -- 请求地址:{gateway}/harness/session -- 请求方式:PUT - -### 请求参数 - -| 参数名称 | 是否必传 | 类型 | 描述 | -|:-----|:-----|:-----|:-----| -| username | 是 | String | 用户名称 | - -### 请求示例 - -```bash -curl -X PUT {gateway}/harness/session -H "Content-Type: application/json" -d '{ - "username": "zhangsan" -}' -``` - -### 响应参数 - -| 参数名称 | 类型 | 描述 | -|:-----|:-----|:-----| -| code | Number | 返回码(200=成功) | -| msg | String | 提示信息 | -| data | String | 新开启的会话ID(sessionId) | - -### 成功示例 - -```json -{ - "code": 200, - "msg": "操作成功", - "data": "1872639000000000001" -} -``` - -### 失败示例 - -```json -{ - "code": 500, - "msg": "错误信息" -} -``` - -## 查看聊天记录列表 - -- 请求地址:{gateway}/harness/session/history -- 请求方式:POST - -### 请求参数 - -| 参数名称 | 是否必传 | 类型 | 描述 | -|:-----|:-----|:-----|:-----| -| pageNum | 否 | Number | 页码,默认1 | -| pageSize | 否 | Number | 每页行数,默认20 | -| username | 否 | String | 用户名,不传则从token获取 | -| keywords | 否 | String | 根据用户的问题去搜索 | - -### 请求示例 - -```bash -curl -X POST {gateway}/harness/session/history -H "Content-Type: application/json" -d '{ - "pageNum": 1, - "pageSize": 20, - "username": "zhangsan", - "keywords": "如何配置" -}' -``` - -### 响应参数 - -| 参数名称 | 类型 | 描述 | -|:-----|:-----|:-----| -| total | Number | 总记录数 | -| rows | Array | 会话列表数据 | -| rows.sessionId | String | 会话ID | -| rows.userQuestion | String | 用户的第一个问题 | -| rows.createTime | String | 创建时间(yyyy-MM-dd HH:mm:ss) | -| rows.createAt | String | 创建人 | -| code | Number | 返回码(200=成功) | -| msg | String | 提示信息 | -| extraData | Object | 列表之外的额外数据 | - -### 成功示例 - -```json -{ - "total": 1, - "rows": [ - { - "sessionId": "1872639000000000001", - "userQuestion": "如何配置聊天模型", - "createTime": "2026-09-20 10:30:00", - "createAt": "zhangsan" - } - ], - "code": 200, - "msg": "查询成功", - "extraData": null -} -``` - -### 失败示例 - -```json -{ - "code": 500, - "msg": "错误信息" -} -``` - -## 查看会话聊天记录 - -- 请求地址:{gateway}/harness/session/message/{sessionId} -- 请求方式:GET - -### 请求参数 - -| 参数名称 | 是否必传 | 类型 | 描述 | -|:-----|:-----|:-----|:-----| -| sessionId | 是 | Number | 会话ID | - -### 请求示例 - -```bash -curl -X GET {gateway}/harness/session/message/1872639000000000001 -``` - -### 响应参数 - -| 参数名称 | 类型 | 描述 | -|:-----|:-----|:-----| -| code | Number | 返回码(200=成功) | -| msg | String | 提示信息 | -| data | Array | 聊天消息列表 | -| data.messageId | String | 消息ID | -| data.messageType | String | 消息类型(USER=用户输入,AGENT=智能体输出) | -| data.message | String | 消息内容(markdown格式) | -| data.context | Object | 扩展上下文信息 | -| data.createTime | String | 创建时间(yyyy-MM-dd HH:mm:ss) | - -### 成功示例 - -```json -{ - "code": 200, - "msg": "操作成功", - "data": [ - { - "messageId": "1872639000000001001", - "messageType": "USER", - "message": "你好,请问如何配置聊天模型?", - "context": { - "key1": "xxx", - "key2": "yyy" - }, - "createTime": "2026-09-20 10:30:00" - }, - { - "messageId": "1872639000000001002", - "messageType": "AGENT", - "message": "你好!配置聊天模型可以参考以下步骤:...", - "context": null, - "createTime": "2026-09-20 10:30:05" - } - ] -} -``` - -### 失败示例 - -```json -{ - "code": 500, - "msg": "错误信息" -} -``` - -## 预设的热门问题 - -- 请求地址:{gateway}/harness/hot/question -- 请求方式:GET - -### 请求参数 - -无 - -### 请求示例 - -```bash -curl -X GET {gateway}/harness/hot/question -``` - -### 响应参数 - -| 参数名称 | 类型 | 描述 | -|:-----|:-----|:-----| -| code | Number | 返回码(200=成功) | -| msg | String | 提示信息 | -| data | Array | 热门问题列表 | -| data.questionShortName | String | 热门问题简写 | -| data.questionContent | String | 问题实际内容 | - -### 成功示例 - -```json -{ - "code": 200, - "msg": "操作成功", - "data": [ - { - "questionShortName": "如何配置模型", - "questionContent": "如何为智能体配置聊天模型?" - } - ] -} -``` - -### 失败示例 - -```json -{ - "code": 500, - "msg": "错误信息" -} -``` - -## 预设的子智能体 - -- 请求地址:{gateway}/harness/subagent/config -- 请求方式:GET - -### 请求参数 - -无 - -### 请求示例 - -```bash -curl -X GET {gateway}/harness/subagent/config -``` - -### 响应参数 - -| 参数名称 | 类型 | 描述 | -|:-----|:-----|:-----| -| code | Number | 返回码(200=成功) | -| msg | String | 提示信息 | -| data | Array | 子智能体配置列表 | -| data.name | String | 子智能体名称 | -| data.alias | String | 展示给用户看的别名 | -| data.dataId | String | 如果`added=true`返回用户个人空间的agentId,否则返回需要添加到个人空间的agentId | -| data.added | Boolean | 用户是否添加了这个子智能体 | - - -### 成功示例 - -```json -{ - "code": 200, - "msg": "操作成功", - "data": [ - { - "name": "SE_taskexec", - "alias": "SE任务执行专家", - "dataId": "123456", - "added": true - }, - { - "name": "SE_Debug", - "alias": "SE-issue调试专家", - "dataId": "67890", - "added": false - } - ] -} -``` - -### 失败示例 - -```json -{ - "code": 500, - "msg": "错误信息" -} -``` - -## 保存用户输入的内容 - -- 请求地址:{gateway}/harness/user/input -- 请求方式:POST - -### 请求参数 - -| 参数名称 | 是否必传 | 类型 | 描述 | -|:-----|:-----|:-----|:-----| -| sessionId | 是 | Long | 会话ID | -| username | 是 | String | 用户名 | -| userInput | 是 | String | 用户输入的内容 | - -### 请求示例 - -```bash -curl -X POST {gateway}/harness/user/input -H "Content-Type: application/json" -d '{ - "sessionId": 1872639000000000001, - "username": "zhangsan", - "userInput": "帮我查看代码中的空指针异常" -}' -``` - -### 响应参数 - -| 参数名称 | 类型 | 描述 | -|:-----|:-----|:-----| -| code | Number | 返回码(200=成功) | -| msg | String | 提示信息 | -| data | Long | 保存的消息ID | - -### 成功示例 - -```json -{ - "code": 200, - "msg": "操作成功", - "data": 1872639000000001001 -} -``` - -### 失败示例 - -```json -{ - "code": 500, - "msg": "参数[sessionId]不能为空" -} -``` - -## 重写用户输入 - -- 请求地址:{gateway}/harness/user/input/rewrite -- 请求方式:PUT - -### 请求参数 - -| 参数名称 | 是否必传 | 类型 | 描述 | -|:-----|:-----|:-----|:-----| -| sessionId | 是 | Long | 会话ID | -| username | 是 | String | 用户名 | -| userId | 是 | Long | 用户ID | -| userInput | 是 | String | 用户输入的内容 | - -### 请求示例 - -```bash -curl -X PUT {gateway}/harness/user/input/rewrite -H "Content-Type: application/json" -d '{ - "sessionId": 1872639000000000001, - "username": "zhangsan", - "userId": 1001, - "userInput": "帮我查看代码中的空指针异常" -}' -``` - -### 响应参数 - -| 参数名称 | 类型 | 描述 | -|:-----|:-----|:-----| -| code | Number | 返回码(200=成功) | -| msg | String | 提示信息 | -| data | String | 重写后的用户输入内容 | - -### 成功示例 - -```json -{ - "code": 200, - "msg": "操作成功", - "data": "帮我查看代码中的空指针异常\n\n变量表提示信息:..." -} -``` - -### 失败示例 - -```json -{ - "code": 500, - "msg": "参数[sessionId]不能为空" -} -``` - -## 删除会话 - -- 请求地址:{gateway}/harness/session/{sessionId} -- 请求方式:DELETE - -### 请求参数 - -| 参数名称 | 是否必传 | 类型 | 描述 | -|:-----|:-----|:-----|:-----| -| sessionId | 是 | Long | 会话ID(路径参数) | - -### 请求示例 - -```bash -curl -X DELETE {gateway}/harness/session/1872639000000000001 -``` - -### 响应参数 - -| 参数名称 | 类型 | 描述 | -|:-----|:-----|:-----| -| code | Number | 返回码(200=成功) | -| msg | String | 提示信息 | -| data | Long | 被删除的会话ID | - -### 成功示例 - -```json -{ - "code": 200, - "msg": "操作成功", - "data": 1872639000000000001 -} -``` - -### 失败示例 - -```json -{ - "code": 500, - "msg": "删除失败" -} -``` \ No newline at end of file diff --git a/harness-chat.md b/harness-chat.md deleted file mode 100644 index bd1b643..0000000 --- a/harness-chat.md +++ /dev/null @@ -1,1021 +0,0 @@ -# Harness Chat 接口文档 - -`POST /harness/chat` - -## 1. 接口说明 - -- 路径:`/harness/chat` -- 方法:`POST` -- 内容类型:`application/json` -- 返回类型:`Flux`(**流式响应**,支持 SSE 与 JSON 数组两种方式) -- 功能:向智能体发送一条用户输入,返回一段**细粒度智能体事件流**。调用方按事件类型逐条解析即可渲染「思考中 / 正在调用工具 / 流式输出答案 / 需要人工确认」等 UI 状态。 - -> 源码位置:`mis-common/mis-common-harness/java/com/lcfc/harness/chat/HarnessChatGateway.java#L18-L23` -> -> ```java -> @PostMapping("/chat") -> public Flux chat(@RequestBody AgentChatRequest request) { -> ChatUiChannel channel = HarnessAgent.builder().build().channel(ChatUiChannel.create()); -> SendOptions sendOptions = SendOptions.of(request.getUserId(), request.getSessionId()); -> return channel.sendStream(sendOptions, request.getInput()); -> } -> ``` - -## 2. 请求 - -### 2.1 请求头 - -| Header | 值 | 说明 | -| --- | --- | --- | -| `Content-Type` | `application/json` | 必填 | -| `Accept` | `text/event-stream` 或 `application/json` | 决定响应格式(见 §3) | - -### 2.2 请求体(`AgentChatRequest`) - -| 字段 | 类型 | 必填 | 说明 | -| --- | --- | --- | --- | -| `sessionId` | String | ✅ | 会话 ID;同一用户不同会话相互隔离 | -| `username` | String | ✅ | 用户名;用于智能体命名空间隔离 / 会话路由 | -| `input` | String | ✅ | 用户输入内容 | -| `confirmResults` | Array | ❌| (HITL)当工具需要用户确认时,提交用户确认结果,Agent将继续执行| - -### 2.3 请求示例 - -```json -POST /harness/chat -Host: localhost:8080 -Content-Type: application/json -Accept: text/event-stream - -{ - "sessionId": "1872639000000000001", - "username": "zhangsan", - "input": "你好,帮我查询一下上个月的销售数据并生成报表。", - "confirmResults": [ - { - "confirmed": true, - "toolCall": { - "id": "call_001", - "name": "query_sales_data", - "input": { - "month": "2026-08" - }, - "content": null, - "metadata": {}, - "state": "submitted" - }, - "rules": [ - { - "tool_name": "query_sales_data", - "rule_content": "month=2026-08", - "behavior": "allow", - "source": "userSettings" - }, - { - "tool_name": "export_report", - "rule_content": null, - "behavior": "deny", - "source": "userSettings" - }, - { - "tool_name": "delete_record", - "rule_content": null, - "behavior": "ask", - "source": "userSettings" - }, - { - "tool_name": "send_mail", - "rule_content": "to=*", - "behavior": "passthrough", - "source": "userSettings" - } - ] - } - ] -} -``` - -> ⚠️ 注意:当前实现中 `chatModel` 并未被使用(`HarnessAgent.builder().build()` 未传入模型配置)。如需按请求指定模型,需要扩展 `HarnessChatGateway`。 - -## 3. 响应 - -### 3.1 格式一:SSE(推荐,`Accept: text/event-stream`) - -每发生一个事件,服务端推送一条 `data:`,事件之间以空行分隔: - -``` -data:{"type":"AGENT_START","id":"4f9c1e2d8a7b4c5d9e0f1a2b3c4d5e6f","createdAt":"2026-09-18T02:30:45.123456Z","sessionId":"sess-20260918-001","replyId":"reply-7f3a91","name":"assistant","role":"assistant"} - -data:{"type":"THINKING_BLOCK_START","id":"...","createdAt":"...","replyId":"reply-7f3a91","blockId":"blk-001"} - -data:{"type":"TEXT_BLOCK_DELTA","id":"...","createdAt":"...","replyId":"reply-7f3a91","blockId":"blk-002","delta":"已完成"} -``` - -### 3.2 格式二:JSON 数组(默认 / `Accept: application/json`) - -整个事件流序列化为一个 JSON 数组,随事件产生逐个写出: - -```json -[ - { "type": "AGENT_START", "...": "..." }, - { "type": "THINKING_BLOCK_START", "...": "..." }, - { "type": "TEXT_BLOCK_DELTA", "...": "..." } -] -``` - -### 3.3 HTTP 状态 - -| 状态码 | 说明 | -| --- | --- | -| `200` | 正常,返回事件流 | -| `400` | 校验失败(`sessionId` / `userId` / `input` 为空时抛 `400 Bad Request`) | -| `500` | 智能体执行异常(模型未配置、会话中断等) | - -## 4. 事件通用结构 - -所有事件(`AgentEvent`)都包含以下通用字段,通过 `type` 字段区分具体事件类型: - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `type` | String | **类型判别器**,取值见 §5 | -| `id` | String | 事件唯一 ID(32 位十六进制,无连字符 UUID) | -| `createdAt` | String | 事件创建时间,ISO-8601 格式(如 `2026-09-18T02:30:45.123456Z`) | -| `source` | String | 事件来源路径。顶层智能体事件为 `null`;子智能体转发的事件为 `main/researcher` 形式。**无值时缺省(不输出)** | -| `metadata` | Object | 附加元数据,**空时不输出** | - -仅 `type` / `id` / `createdAt` 必现;其余字段视事件类型而定。以下各事件示例均基于同一会话回环 `"replyId":"reply-7f3a91"`。 - -## 5. AgentEvent 类型详解与数据示例 - -### 5.1 AGENT_START — 智能体开始处理 - -表示一次智能体调用开始。 - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `sessionId` | String | 会话 ID | -| `replyId` | String | 本轮回复 ID,用于关联同一轮事件 | -| `name` | String | 智能体名称 | -| `role` | String | 默认 `"assistant"` | - -```json -{ - "type": "AGENT_START", - "id": "4f9c1e2d8a7b4c5d9e0f1a2b3c4d5e6f", - "createdAt": "2026-09-18T02:30:45.123456Z", - "sessionId": "sess-20260918-001", - "replyId": "reply-7f3a91", - "name": "assistant", - "role": "assistant" -} -``` - -### 5.2 THINKING_BLOCK_START — 思考块开始 - -模型开始推理(ReAct 的 reasoning 阶段)。 - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `replyId` | String | 回复 ID | -| `blockId` | String | 思考块 ID | - -```json -{ - "type": "THINKING_BLOCK_START", - "id": "1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d", - "createdAt": "2026-09-18T02:30:45.200000Z", - "replyId": "reply-7f3a91", - "blockId": "blk-001" -} -``` - -### 5.3 THINKING_BLOCK_DELTA — 思考内容增量 - -逐段推送思考内容。 - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `replyId` | String | 回复 ID | -| `blockId` | String | 思考块 ID | -| `delta` | String | 增量文本 | - -```json -{ - "type": "THINKING_BLOCK_DELTA", - "id": "2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e", - "createdAt": "2026-09-18T02:30:45.210000Z", - "replyId": "reply-7f3a91", - "blockId": "blk-001", - "delta": "用户希望将任务清单整理成 markdown 文件并保存,需要先规划目录结构。" -} -``` - -### 5.4 THINKING_BLOCK_END — 思考块结束 - -```json -{ - "type": "THINKING_BLOCK_END", - "id": "3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f", - "createdAt": "2026-09-18T02:30:45.350000Z", - "replyId": "reply-7f3a91", - "blockId": "blk-001" -} -``` - -### 5.5 MODEL_CALL_START — 模型调用开始 - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `replyId` | String | 回复 ID | - -```json -{ - "type": "MODEL_CALL_START", - "id": "4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f90", - "createdAt": "2026-09-18T02:30:45.180000Z", - "replyId": "reply-7f3a91" -} -``` - -### 5.6 MODEL_CALL_END — 模型调用结束(含 token 用量) - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `replyId` | String | 回复 ID | -| `usage` | Object | token 用量统计 | - -`usage` 结构: - -```json -{ - "type": "MODEL_CALL_END", - "id": "5e6f7a8b9c0d1e2f3a4b5c6d7e8f9001", - "createdAt": "2026-09-18T02:30:45.680000Z", - "replyId": "reply-7f3a91", - "usage": { - "inputTokens": 1250, - "outputTokens": 320, - "cachedTokens": 512, - "time": 0.482, - "totalTokens": 1570 - } -} -``` - -| usage 字段 | 类型 | 说明 | -| --- | --- | --- | -| `inputTokens` | Integer | 输入 token 数(含缓存部分) | -| `outputTokens` | Integer | 输出 token 数 | -| `cachedTokens` | Integer | 命中 prompt 缓存的输入 token 数(来自 inputTokens 的子集) | -| `time` | Number | 本次调用耗时(秒) | -| `totalTokens` | Integer | `inputTokens + outputTokens`(派生字段) | - -### 5.7 TOOL_CALL_START — 工具调用开始 - -模型决定调用某个工具(ReAct 的 acting 阶段)。 - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `replyId` | String | 回复 ID | -| `toolCallId` | String | 工具调用 ID | -| `toolCallName` | String | 工具名 | - -```json -{ - "type": "TOOL_CALL_START", - "id": "6f7a8b9c0d1e2f3a4b5c6d7e8f900112", - "createdAt": "2026-09-18T02:30:45.700000Z", - "replyId": "reply-7f3a91", - "toolCallId": "call_9f2c4d", - "toolCallName": "shell_execute" -} -``` - -### 5.8 TOOL_CALL_DELTA — 工具入参流式增量 - -工具参数以 JSON 字符串形式分片送达。 - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `replyId` | String | 回复 ID | -| `toolCallId` | String | 工具调用 ID | -| `toolCallName` | String | 工具名 | -| `delta` | String | 入参 JSON 片段 | - -```json -{ - "type": "TOOL_CALL_DELTA", - "id": "7a8b9c0d1e2f3a4b5c6d7e8f90011223", - "createdAt": "2026-09-18T02:30:45.720000Z", - "replyId": "reply-7f3a91", - "toolCallId": "call_9f2c4d", - "toolCallName": "shell_execute", - "delta": "{\"command\":\"cat /tasks.json > " -} -``` - -```json -{ - "type": "TOOL_CALL_DELTA", - "id": "8b9c0d1e2f3a4b5c6d7e8f9001122334", - "createdAt": "2026-09-18T02:30:45.730000Z", - "replyId": "reply-7f3a91", - "toolCallId": "call_9f2c4d", - "toolCallName": "shell_execute", - "delta": "\\\"/workspace/tasks.md\"}" -} -``` - -### 5.9 TOOL_CALL_END — 工具调用结束 - -```json -{ - "type": "TOOL_CALL_END", - "id": "9c0d1e2f3a4b5c6d7e8f900112233445", - "createdAt": "2026-09-18T02:30:45.740000Z", - "replyId": "reply-7f3a91", - "toolCallId": "call_9f2c4d", - "toolCallName": "shell_execute" -} -``` - -### 5.10 TOOL_RESULT_START — 工具执行结果开始 - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `replyId` | String | 回复 ID | -| `toolCallId` | String | 工具调用 ID | -| `toolCallName` | String | 工具名 | -| `metadata` | Object | 可选,如携带 `taskId` 等转发元数据(缺省) | - -```json -{ - "type": "TOOL_RESULT_START", - "id": "0d1e2f3a4b5c6d7e8f90011223344556", - "createdAt": "2026-09-18T02:30:46.050000Z", - "replyId": "reply-7f3a91", - "toolCallId": "call_9f2c4d", - "toolCallName": "shell_execute" -} -``` - -### 5.11 TOOL_RESULT_TEXT_DELTA — 工具结果文本增量 - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `replyId` | String | 回复 ID | -| `toolCallId` | String | 工具调用 ID | -| `toolCallName` | String | 工具名 | -| `delta` | String | 结果文本片段 | - -```json -{ - "type": "TOOL_RESULT_TEXT_DELTA", - "id": "1e2f3a4b5c6d7e8f9001122334455667", - "createdAt": "2026-09-18T02:30:46.060000Z", - "replyId": "reply-7f3a91", - "toolCallId": "call_9f2c4d", - "toolCallName": "shell_execute", - "delta": "exit_code=0\n" -} -``` - -```json -{ - "type": "TOOL_RESULT_TEXT_DELTA", - "id": "2f3a4b5c6d7e8f9001122334455667788", - "createdAt": "2026-09-18T02:30:46.070000Z", - "replyId": "reply-7f3a91", - "toolCallId": "call_9f2c4d", - "toolCallName": "shell_execute", - "delta": "任务清单已保存到 /workspace/tasks.md" -} -``` - -### 5.12 TOOL_RESULT_DATA_DELTA — 工具结果二进制数据增量 - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `replyId` | String | 回复 ID | -| `toolCallId` | String | 工具调用 ID | -| `toolCallName` | String | 工具名 | -| `data` | Object | 一个多态 ContentBlock(`type` 判别器),常见为 `data` 类型携带 base64 数据 | - -`data` 的 `type` 取值:`text` / `thinking` / `image` / `audio` / `video` / `tool_use` / `tool_result` / `hint` / `data`。 - -```json -{ - "type": "TOOL_RESULT_DATA_DELTA", - "id": "3a4b5c6d7e8f900112233445566778899", - "createdAt": "2026-09-18T02:30:46.080000Z", - "replyId": "reply-7f3a91", - "toolCallId": "call_9f2c4d", - "toolCallName": "render_chart", - "data": { - "type": "data", - "source": { - "type": "base64", - "media_type": "image/png", - "data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==" - }, - "id": "d4a3b2c1d5e6f7a8b9c0d1e2f3a4b5c6", - "name": "chart.png" - } -} -``` - -> URL 型数据源示例:`"source": { "type": "url", "url": "https://cdn.example.com/tmp/chart.png", "mime_type": "image/png" }` - -### 5.13 TOOL_RESULT_END — 工具结果结束(含执行状态) - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `replyId` | String | 回复 ID | -| `toolCallId` | String | 工具调用 ID | -| `toolCallName` | String | 工具名 | -| `state` | String | 执行结果:`success` / `error` / `interrupted` / `denied` / `running` | - -```json -{ - "type": "TOOL_RESULT_END", - "id": "4b5c6d7e8f90011223344556677889900", - "createdAt": "2026-09-18T02:30:46.150000Z", - "replyId": "reply-7f3a91", - "toolCallId": "call_9f2c4d", - "toolCallName": "shell_execute", - "state": "success" -} -``` - -**失败示例(state = error):** - -```json -{ - "type": "TOOL_RESULT_END", - "id": "5c6d7e8f9001122334455667788990011", - "createdAt": "2026-09-18T02:30:47.200000Z", - "replyId": "reply-7f3a91", - "toolCallId": "call_9f2c4d", - "toolCallName": "shell_execute", - "state": "error" -} -``` - -### 5.14 DATA_BLOCK_START — 二进制数据块开始 - -用于向用户直接推送二进制内容(图片 / 音频 / 视频 / 文件),通常出现在最终答案阶段。 - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `replyId` | String | 回复 ID | -| `blockId` | String | 数据块 ID | - -```json -{ - "type": "DATA_BLOCK_START", - "id": "6d7e8f900112233445566778899001122", - "createdAt": "2026-09-18T02:30:48.000000Z", - "replyId": "reply-7f3a91", - "blockId": "blk-003" -} -``` - -### 5.15 DATA_BLOCK_DELTA — 二进制数据块增量 - -`delta` 为二进制内容的 **base64** 分片。 - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `replyId` | String | 回复 ID | -| `blockId` | String | 数据块 ID | -| `delta` | String | base64 数据分片 | - -```json -{ - "type": "DATA_BLOCK_DELTA", - "id": "7e8f90011223344556677889900112233", - "createdAt": "2026-09-18T02:30:48.010000Z", - "replyId": "reply-7f3a91", - "blockId": "blk-003", - "delta": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==" -} -``` - -### 5.16 DATA_BLOCK_END — 二进制数据块结束 - -```json -{ - "type": "DATA_BLOCK_END", - "id": "8f9001122334455667788990011223344", - "createdAt": "2026-09-18T02:30:48.100000Z", - "replyId": "reply-7f3a91", - "blockId": "blk-003" -} -``` - -### 5.17 TEXT_BLOCK_START — 文本块开始 - -```json -{ - "type": "TEXT_BLOCK_START", - "id": "900112233445566778899001122334455", - "createdAt": "2026-09-18T02:30:47.500000Z", - "replyId": "reply-7f3a91", - "blockId": "blk-002" -} -``` - -### 5.18 TEXT_BLOCK_DELTA — 文本块流式增量(最终答案) - -前端据此逐字渲染智能体回复。 - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `replyId` | String | 回复 ID | -| `blockId` | String | 文本块 ID | -| `delta` | String | 文本增量 | - -```json -{ - "type": "TEXT_BLOCK_DELTA", - "id": "a011223344556677889900112233445566", - "createdAt": "2026-09-18T02:30:47.510000Z", - "replyId": "reply-7f3a91", - "blockId": "blk-002", - "delta": "已完成," -} -``` - -```json -{ - "type": "TEXT_BLOCK_DELTA", - "id": "b112233445566778899001122334455667", - "createdAt": "2026-09-18T02:30:47.520000Z", - "replyId": "reply-7f3a91", - "blockId": "blk-002", - "delta": "任务清单已保存至 /workspace/tasks.md" -} -``` - -### 5.19 TEXT_BLOCK_END — 文本块结束 - -```json -{ - "type": "TEXT_BLOCK_END", - "id": "c223344556677889900112233445566778", - "createdAt": "2026-09-18T02:30:47.600000Z", - "replyId": "reply-7f3a91", - "blockId": "blk-002" -} -``` - -### 5.20 AGENT_RESULT — 智能体最终结果(含完整 Msg) - -在 `AGENT_END` 之前发出,携带本轮最终回复消息 `Msg`。调用方可以从事件流直接取结果,无需另外订阅返回值。 - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `result` | Object | 最终消息体(多态,`role` 为判别器:`USER` / `ASSISTANT` / `SYSTEM` / `TOOL`) | - -`result`(Msg)字段: - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `id` | String | 消息 ID(UUID) | -| `name` | String | 消息发送方名称,可为 `null` | -| `role` | String | 角色:`USER` / `ASSISTANT` / `SYSTEM` / `TOOL` | -| `content` | Array | 内容块数组(多态,`type` 判别器) | -| `metadata` | Object | 元数据,如 `agentscope_generate_reason` | -| `timestamp` | String | 消息时间戳,格式 `yyyy-MM-dd HH:mm:ss.SSS` | -| `usage` | Object | token 用量(同 §5.6),可为 `null` | - -```json -{ - "type": "AGENT_RESULT", - "id": "d33445566778899001122334455667788", - "createdAt": "2026-09-18T02:30:48.200000Z", - "result": { - "id": "550e8400-e29b-41d4-a716-446655440000", - "name": "assistant", - "role": "ASSISTANT", - "content": [ - { - "type": "text", - "text": "已完成,任务清单已保存至 /workspace/tasks.md" - } - ], - "metadata": { - "agentscope_generate_reason": "MODEL_STOP" - }, - "timestamp": "2026-09-18 10:30:48.200", - "usage": { - "inputTokens": 1250, - "outputTokens": 320, - "cachedTokens": 512, - "time": 2.46, - "totalTokens": 1570 - } - } -} -``` - -> 多模态回复的 `content` 举例(图片 + 文本混排): -> ```json -> "content": [ -> { "type": "text", "text": "这是生成的图表:" }, -> { "type": "data", "source": { "type": "url", "url": "https://cdn.example.com/chart.png", "mime_type": "image/png" }, "id": "d4a3b2c1d5e6f7a8b9c0d1e2f3a4b5c6", "name": "chart.png" } -> ] -> ``` - -### 5.21 AGENT_END — 智能体结束处理 - -```json -{ - "type": "AGENT_END", - "id": "e455667788990011223344556677889900", - "createdAt": "2026-09-18T02:30:48.300000Z", - "replyId": "reply-7f3a91" -} -``` - -### 5.22 EXCEED_MAX_ITERS — ReAct 循环超过最大迭代次数 - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `replyId` | String | 回复 ID | -| `maxIters` | Integer | 配置的最大迭代次数 | -| `currentIter` | Integer | 实际到达的迭代次数 | - -```json -{ - "type": "EXCEED_MAX_ITERS", - "id": "f566778899001122334455667788990011", - "createdAt": "2026-09-18T02:30:52.000000Z", - "replyId": "reply-7f3a91", - "maxIters": 10, - "currentIter": 10 -} -``` - -### 5.23 REQUIRE_USER_CONFIRM — 需要用户确认工具调用(HITL 暂停) - -智能体在执行敏感工具前暂停,等待用户逐条确认(前端应弹出授权窗口)。工具调用状态为 `asking`。 - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `replyId` | String | 回复 ID | -| `toolCalls` | Array | 待确认的 `ToolUseBlock` 列表 | - -`ToolUseBlock` 字段:`id`、`name`、`input`(Map)、`content`(流式原始内容,可空)、`metadata`、`state`(`pending` / `asking` / `allowed` / `submitted` / `finished`)。 - -```json -{ - "type": "REQUIRE_USER_CONFIRM", - "id": "6778899001122334455667788990011223", - "createdAt": "2026-09-18T02:30:45.750000Z", - "replyId": "reply-7f3a91", - "toolCalls": [ - { - "id": "call_9f2c4d", - "name": "shell_execute", - "input": { - "command": "rm -rf /workspace/old/" - }, - "content": null, - "metadata": {}, - "state": "asking" - }, - { - "id": "call_5a1b02", - "name": "http_post", - "input": { - "url": "https://api.example.com/orders", - "body": "{\"id\": 10086}" - }, - "content": null, - "metadata": {}, - "state": "asking" - } - ] -} -``` - -### 5.24 USER_CONFIRM_RESULT — 用户确认结果回传 - -用户对 `REQUIRE_USER_CONFIRM` 的响应结果(同一会话的下一轮调用事件流中可能出现)。 - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `replyId` | String | 回复 ID | -| `confirmResults` | Array | `ConfirmResult` 列表 | - -`ConfirmResult` 字段: - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `confirmed` | Boolean | 是否批准 | -| `toolCall` | Object | 对应的 `ToolUseBlock`(用户可修改入参) | -| `rules` | Array | 用户新增的权限规则(允许后续免确认),可为空 | - -```json -{ - "type": "USER_CONFIRM_RESULT", - "id": "7889900112233445566778899001122334", - "createdAt": "2026-09-18T02:31:05.000000Z", - "replyId": "reply-7f3a91", - "confirmResults": [ - { - "confirmed": true, - "toolCall": { - "id": "call_9f2c4d", - "name": "shell_execute", - "input": { - "command": "rm -rf /workspace/old/" - }, - "content": null, - "metadata": {}, - "state": "asking" - }, - "rules": [ - { - "tool_name": "shell_execute", - "rule_content": "rm -rf /workspace/*", - "behavior": "allow", - "source": "userSettings" - } - ] - }, - { - "confirmed": false, - "toolCall": { - "id": "call_5a1b02", - "name": "http_post", - "input": { - "url": "https://api.example.com/orders", - "body": "{\"id\": 10086}" - }, - "content": null, - "metadata": {}, - "state": "asking" - }, - "rules": null - } - ] -} -``` - -### 5.25 ALL_TOOLS_DENIED — 本轮所有工具均被拒绝 - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `deniedToolCalls` | Array | 被拒绝的 `ToolUseBlock` 列表 | - -```json -{ - "type": "ALL_TOOLS_DENIED", - "id": "89900112233445566778899001122334455", - "createdAt": "2026-09-18T02:31:05.100000Z", - "deniedToolCalls": [ - { - "id": "call_5a1b02", - "name": "http_post", - "input": { - "url": "https://api.example.com/orders", - "body": "{\"id\": 10086}" - }, - "content": null, - "metadata": {}, - "state": "asking" - } - ] -} -``` - -### 5.26 REQUIRE_EXTERNAL_EXECUTION — 需要外部(进程外)执行工具 - -工具需由调用方在进程外执行,智能体暂停等待结果。 - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `replyId` | String | 回复 ID | -| `toolCalls` | Array | 待外部执行的 `ToolUseBlock` 列表 | - -```json -{ - "type": "REQUIRE_EXTERNAL_EXECUTION", - "id": "9001122334455667788990011223344556", - "createdAt": "2026-09-18T02:30:45.900000Z", - "replyId": "reply-7f3a91", - "toolCalls": [ - { - "id": "call_0f3e9a", - "name": "human_approval_flow", - "input": { - "title": "发布订单 10086 到生产环境" - }, - "content": null, - "metadata": {}, - "state": "pending" - } - ] -} -``` - -### 5.27 EXTERNAL_EXECUTION_RESULT — 外部执行结果回传 - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `replyId` | String | 回复 ID | -| `toolResults` | Array | `ToolResultBlock` 列表 | - -`ToolResultBlock` 字段:`id`、`name`、`output`(ContentBlock 数组)、`metadata`、`state`(`success` / `error` / `interrupted` / `denied` / `running`)。 - -```json -{ - "type": "EXTERNAL_EXECUTION_RESULT", - "id": "a112233445566778899001122334455667", - "createdAt": "2026-09-18T02:31:20.000000Z", - "replyId": "reply-7f3a91", - "toolResults": [ - { - "id": "call_0f3e9a", - "name": "human_approval_flow", - "output": [ - { - "type": "text", - "text": "审批人张三已批准,订单 10086 已发布。" - } - ], - "metadata": {}, - "state": "success" - } - ] -} -``` - -### 5.28 REQUEST_STOP — 请求暂停执行 - -中间件 / 权限引擎要求智能体在当前步骤结束后暂停(如预算超限、合规审查点)。调用方可在下一轮使用相同 `sessionId` 继续该会话,待执行的工具调用会自动恢复。 - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `reason` | String | 停止原因(人类可读) | -| `generateReason` | String | 停止原因枚举名:`MODEL_STOP` / `TOOL_CALLS` / `STRUCTURED_OUTPUT` / `TOOL_SUSPENDED` / `REASONING_STOP_REQUESTED` / `ACTING_STOP_REQUESTED` / `PERMISSION_ASKING` / `MIDDLEWARE_STOP_REQUESTED` / `ALL_TOOLS_DENIED` / `INTERRUPTED` / `MAX_ITERATIONS`,默认 `MIDDLEWARE_STOP_REQUESTED` | - -```json -{ - "type": "REQUEST_STOP", - "id": "b223344556677889900112233445566778", - "createdAt": "2026-09-18T02:30:49.000000Z", - "reason": "单轮 token 消耗超过预算上限 100K,已暂停" -} -``` - -```json -{ - "type": "REQUEST_STOP", - "id": "c334455667788990011223344556677889", - "createdAt": "2026-09-18T02:30:49.100000Z", - "reason": "权限引擎要求用户确认高风险操作", - "generateReason": "PERMISSION_ASKING" -} -``` - -### 5.29 SUBAGENT_EXPOSED — 子智能体对外暴露 - -通过 `agent_spawn(expose_to_user=true)` 生成的子智能体成为可寻址的独立会话入口,SSE 消费端据此在 UI 渲染新的会话卡片。 - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `subagentId` | String | 子智能体实例 ID | -| `agentId` | String | 子智能体定义 ID | -| `sessionId` | String | 子智能体会话 ID | -| `label` | String | 展示名称 | - -```json -{ - "type": "SUBAGENT_EXPOSED", - "id": "d445566778899001122334455667788990", - "createdAt": "2026-09-18T02:31:02.000000Z", - "subagentId": "sub-0a1b2c3d", - "agentId": "data-analyst", - "sessionId": "sess-sub-88", - "label": "数据分析助手" -} -``` - -### 5.30 HINT_BLOCK — 一次性提示块 - -一次性完整下发(不流式),用途包括团队消息、后台工具结果、用户打断等。 - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `replyId` | String | 回复 ID | -| `blockId` | String | 提示块 ID | -| `hintSource` | String | 来源(团队消息发送者姓名、`system` 或 `null`) | -| `hint` | String | 完整提示内容 | - -```json -{ - "type": "HINT_BLOCK", - "id": "e556677889900112233445566778899001", - "createdAt": "2026-09-18T02:31:03.000000Z", - "replyId": "reply-7f3a91", - "blockId": "blk-hint-01", - "hintSource": "alice", - "hint": "alice 加入了会话,可以开始协作。" -} -``` - -### 5.31 CUSTOM — 自定义扩展事件 - -业务中间件用于推送自有状态(未知 `name` 前端应跳过不报错)。约定 `name`:`state_updated`(任务/权限状态变化)、`team_updated`(团队变更)等。 - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `name` | String | 事件名 | -| `value` | Object | 任意 JSON 负载 | - -```json -{ - "type": "CUSTOM", - "id": "f667788990011223344556677889900112", - "createdAt": "2026-09-18T02:31:04.000000Z", - "name": "task_progress", - "value": { - "taskId": "task-201", - "progress": 66, - "status": "RUNNING", - "detail": "正在生成页面截图" - } -} -``` - -```json -{ - "type": "CUSTOM", - "id": "a778899001122334455667788990011223", - "createdAt": "2026-09-18T02:31:04.500000Z", - "name": "team_updated", - "value": { - "action": "MEMBER_ADDED", - "member": "bob", - "teamId": "team-007" - } -} -``` - -## 6. 典型一轮完整事件流(SSE,按顺序) - -以「用户要求整理任务清单并保存为 markdown」为例(含工具调用): - -```text -data:{"type":"AGENT_START","id":"...","createdAt":"...","sessionId":"sess-20260918-001","replyId":"reply-7f3a91","name":"assistant","role":"assistant"} - -data:{"type":"MODEL_CALL_START","id":"...","createdAt":"...","replyId":"reply-7f3a91"} - -data:{"type":"THINKING_BLOCK_START","id":"...","createdAt":"...","replyId":"reply-7f3a91","blockId":"blk-001"} - -data:{"type":"THINKING_BLOCK_DELTA","id":"...","createdAt":"...","replyId":"reply-7f3a91","blockId":"blk-001","delta":"先读取任务源文件,再生成 markdown"} - -data:{"type":"THINKING_BLOCK_END","id":"...","createdAt":"...","replyId":"reply-7f3a91","blockId":"blk-001"} - -data:{"type":"MODEL_CALL_END","id":"...","createdAt":"...","replyId":"reply-7f3a91","usage":{"inputTokens":520,"outputTokens":80,"cachedTokens":0,"time":0.41,"totalTokens":600}} - -data:{"type":"TOOL_CALL_START","id":"...","createdAt":"...","replyId":"reply-7f3a91","toolCallId":"call_9f2c4d","toolCallName":"shell_execute"} - -data:{"type":"TOOL_CALL_DELTA","id":"...","createdAt":"...","replyId":"reply-7f3a91","toolCallId":"call_9f2c4d","toolCallName":"shell_execute","delta":"{\"command\":\"cat /tasks.json\"}"} - -data:{"type":"TOOL_CALL_END","id":"...","createdAt":"...","replyId":"reply-7f3a91","toolCallId":"call_9f2c4d","toolCallName":"shell_execute"} - -data:{"type":"TOOL_RESULT_START","id":"...","createdAt":"...","replyId":"reply-7f3a91","toolCallId":"call_9f2c4d","toolCallName":"shell_execute"} - -data:{"type":"TOOL_RESULT_TEXT_DELTA","id":"...","createdAt":"...","replyId":"reply-7f3a91","toolCallId":"call_9f2c4d","toolCallName":"shell_execute","delta":"3 个任务待办..."} - -data:{"type":"TOOL_RESULT_END","id":"...","createdAt":"...","replyId":"reply-7f3a91","toolCallId":"call_9f2c4d","toolCallName":"shell_execute","state":"success"} - -data:{"type":"MODEL_CALL_START","id":"...","createdAt":"...","replyId":"reply-7f3a91"} - -data:{"type":"MODEL_CALL_END","id":"...","createdAt":"...","replyId":"reply-7f3a91","usage":{"inputTokens":1600,"outputTokens":330,"cachedTokens":512,"time":1.8,"totalTokens":1930}} - -data:{"type":"TEXT_BLOCK_START","id":"...","createdAt":"...","replyId":"reply-7f3a91","blockId":"blk-002"} - -data:{"type":"TEXT_BLOCK_DELTA","id":"...","createdAt":"...","replyId":"reply-7f3a91","blockId":"blk-002","delta":"已完成,"} - -data:{"type":"TEXT_BLOCK_DELTA","id":"...","createdAt":"...","replyId":"reply-7f3a91","blockId":"blk-002","delta":"任务清单已保存至 /workspace/tasks.md"} - -data:{"type":"TEXT_BLOCK_END","id":"...","createdAt":"...","replyId":"reply-7f3a91","blockId":"blk-002"} - -data:{"type":"AGENT_RESULT","id":"...","createdAt":"...","result":{"id":"550e8400-e29b-41d4-a716-446655440000","name":"assistant","role":"ASSISTANT","content":[{"type":"text","text":"已完成,任务清单已保存至 /workspace/tasks.md"}],"metadata":{"agentscope_generate_reason":"MODEL_STOP"},"timestamp":"2026-09-18 10:30:48.200","usage":{"inputTokens":1600,"outputTokens":330,"cachedTokens":512,"time":1.8,"totalTokens":1930}}} - -data:{"type":"AGENT_END","id":"...","createdAt":"...","replyId":"reply-7f3a91"} -``` - -事件一般顺序:`AGENT_START` → (`MODEL_CALL_*` / `THINKING_BLOCK_*` / `TOOL_CALL_*` / `TOOL_RESULT_*` 可能多轮循环) → `TEXT_BLOCK_*` → `AGENT_RESULT` → `AGENT_END`。涉及 HITL 时会插入 `REQUIRE_USER_CONFIRM`(见 §5.23)。 - -## 7. 注意事项 - -1. **延续会话**:同一 `(userId, sessionId)` 组合的上下文会自动累积;不同会话互不干扰。`REQUEST_STOP` 或 `REQUIRE_USER_CONFIRM` 暂停后,用相同 `sessionId` 再发一次请求即可恢复执行。 -2. **事件 ID**:`id` 为 32 位十六进制(无连字符 UUID),可用于调试与去重;`createdAt` 为 ISO-8601(UTC)。 -3. **未知事件**:前端对 `type: CUSTOM` 中未知的 `name` 应静默跳过;对表外未知 `type` 应尽量容忍(服务端可能升级新增事件)。 -4. **空字段省略**:顶层事件的 `source`、`metadata` 及无值字段在 JSON 中缺省(`NON_NULL` 策略);`Msg` 内部字段(如 `name`、`usage`)则为 `null` 或对象。 \ No newline at end of file diff --git a/harness-properties.md b/harness-properties.md deleted file mode 100644 index 1dd561e..0000000 --- a/harness-properties.md +++ /dev/null @@ -1,362 +0,0 @@ -# AgentProperties 配置文档 - -本文档描述 `AgentProperties` 类及其内部静态类的配置字段。每个字段都通过 `@Schema` 注解提供了描述信息。 - -## 主类:AgentProperties - -| 字段名 | 类型 | 描述 | -|--------|------|------| -| mainAgentSpec | MainAgentSpec | 主智能体规格 | -| workspace | Workspace | 工作区配置 | -| compaction | Compaction | 上下文压缩配置 | -| skillRepository | SkillRepository | SKILL相关配置 | -| a2sMcpProvider | McpProvider | AaaS的MCP供应商配置 | -| mcpServerConfigs | List\ | MCP服务配置列表 | -| permissionContext | PermissionContext | 权限上下文配置 | -| memoryConfig | MemoryConfig | 长期记忆配置 | -| subagentSpec | List\ | 子智能体清单 | - -## 内部类:MainAgentSpec - -主智能体规格配置。 - -| 字段名 | 类型 | 描述 | 默认值 | -|--------|------|------|--------| -| name | String | 智能体名字 | - | -| description | String | 智能体描述 | - | -| systemPrompt | String | 系统提示词 | - | -| chatModel | NewApiModelProperties | 聊天模型 | - | -| enablePlanMode | Boolean | 是否启用计划模式 | - | -| enableShell | Boolean | 是否启用SHELL | - | -| enableAgentTraceLog | Boolean | 是否打印TraceLog | - | -| asyncToolTimeout | int | 异步工具执行超时(单位:秒) | - | -| maxContextTokens | int | 最大上下文(默认:8000) | 8000 | -| maxIter | int | 最大迭代次数(默认:10) | 10 | -| maxRetries | int | 最大重试次数(默认:3) | 3 | - -## 内部类:Workspace - -工作区配置。 - -| 字段名 | 类型 | 描述 | -|--------|------|------| -| stateStoreType | String | 状态存储(mysql/redis) | -| isolationScope | String | 隔离级别 | -| anonymousUserId | String | 当上下文没有用户ID使用的默认值 | - -## 内部类:Compaction - -上下文压缩配置。 - -| 字段名 | 类型 | 描述 | 默认值 | -|--------|------|------|--------| -| triggerMessages | int | 触发压缩的消息数量阈值(0表示不按消息数触发) | 50 | -| triggerTokens | int | 触发压缩的token数量阈值(0表示动态模式:根据模型上下文窗口减去reserved计算) | 0 | -| reserved | int | 预留的token数量(仅动态模式使用) | 20000 | -| keepMessages | int | 压缩后保留的消息数量 | 20 | -| keepTokens | int | 压缩后保留的token数量(-1表示动态模式,0表示使用keepMessages) | -1 | -| keepTokensMin | int | 最小保留token数量(动态模式) | 2000 | -| keepTokensMax | int | 最大保留token数量(动态模式) | 8000 | -| keepTokensRatio | Double | 保留token的比例(动态模式) | 0.25 | -| summaryPrompt | String | 摘要提示词,'default'表示使用默认提示词 | - | -| flushBeforeCompact | Boolean | 压缩前是否刷新消息到存储 | true | -| offloadBeforeCompact | Boolean | 压缩前是否卸载消息到外部存储 | true | -| prune | PruneConfig | 剪枝配置 | - | -| truncate | TruncateArgs | 截断配置 | - | -| model | NewApiModelProperties | 压缩使用的模型,不设置则使用智能体主模型 | - | - -## 内部类:McpProvider - -AaaS的MCP供应商配置。 - -| 字段名 | 类型 | 描述 | 示例 | -|--------|------|------|------| -| apiGateway | String | API网关 | https://misdev.lcfuturecenter.com/prod-api | -| apiQueryMcpServerInfoUri | String | 查询MCP连接信息(批量) | /mcp/server/openapi/list | -| httpClient | HttpClientConfig | HTTP客户端配置 | - | - -## 内部类:McpServerConfig - -MCP服务配置。 - -| 字段名 | 类型 | 描述 | 默认值 | -|--------|------|------|--------| -| serverName | String | MCP服务名称 | - | -| transport | String | 协议(stdio/sse/http) | - | -| enableTools | List\ | 启用的工具列表 | - | -| initializationTimeout | int | 多少秒初始化超时(默认10秒) | 10 | -| timeout | int | 多少秒执行超时(默认600秒) | 600 | - -## 内部类:SkillRepository - -SKILL相关配置。 - -| 字段名 | 类型 | 描述 | -|--------|------|------| -| mysql | MysqlSkillRepository | 从MySQL加载 | -| classPath | ClassPathSkillRepository | 从classpath加载 | -| a2s | A2sSkillRepository | 从AaaS加载 | -| httpClient | HttpClientConfig | HTTP客户端配置 | - -## 内部类:HttpClientConfig - -HTTP客户端配置。 - -| 字段名 | 类型 | 描述 | 示例 | -|--------|------|------|------| -| version | String | HTTP协议版本,仅支持:HTTP/1.1、HTTP/2 | HTTP/1.1 | -| connectTimeout | int | 连接超时(单位:秒) | - | -| requestTimeout | int | 单个请求超时(单位:秒) | - | -| enableRequestLogger | Boolean | 是否开启请求日志打印 | - | -| enableResponseLogger | Boolean | 是否开启响应日志打印(下载或流式传输会忽略掉) | - | -| defaultHeaders | Map\ | 自定义的默认请求头 | - | - -## 内部类:A2sSkillRepository - -从AaaS加载SKILL的配置。 - -| 字段名 | 类型 | 描述 | 示例 | -|--------|------|------|------| -| enable | Boolean | 是否启用 | - | -| directory | String | 从A2s下载到服务器本地的目录 | - | -| apiGateway | String | API网关 | https://misdev.lcfuturecenter.com/prod-api | -| apiDebugSkillInfoUri | String | 查询调试版SKILL信息的URI | /mcp/skill/openapi/debug/{skill_name} | -| apiReleaseSkillInfoUri | String | 查询正式版SKILL信息的URI(支持占位符) | /mcp/skill/openapi/release/{skill_name} | -| apiDownloadSkillUri | String | 下载SKILL的地址(支持占位符) | /resource/oss/download/{oss_id} | -| availableSkills | Set\ | 可用SKILL名称列表 | - | - -## 内部类:ClassPathSkillRepository - -从classpath加载SKILL的配置。 - -| 字段名 | 类型 | 描述 | -|--------|------|------| -| enable | Boolean | 是否启用 | -| directory | String | 目录名称 | - -## 内部类:MysqlSkillRepository - -从MySQL加载SKILL的配置。 - -| 字段名 | 类型 | 描述 | -|--------|------|------| -| enable | Boolean | 是否启用 | -| databaseName | String | 数据库名称 | -| skillsTableName | String | SKILL表名称 | -| resourcesTableName | String | SKILL资源表名称 | -| createIfNotExist | Boolean | 没有表是否框架自行创建表 | -| writeable | Boolean | 平台统一管理 skill 时常用,设置为true后可以从 agent 侧写回,只读分发就设置为false | - -## 内部类:PruneConfig - -剪枝配置。 - -| 字段名 | 类型 | 描述 | 默认值 | -|--------|------|------|--------| -| protectTokens | int | 保护的token数量,剪枝时不会删除这些token | 40000 | -| minimumTokens | int | 最小token数量,剪枝后不会低于此值 | 20000 | -| maxOutputChars | int | 工具输出的最大字符数,超过则截断 | 2000 | -| excludedTools | Set\ | 排除的工具列表,这些工具的输出不会被剪枝 | ["read_file", "memory_search", "memory_get", "session_search"] | - -## 内部类:TruncateArgs - -截断配置。 - -| 字段名 | 类型 | 描述 | 默认值 | -|--------|------|------|--------| -| triggerMessages | int | 触发截断的消息数量阈值 | 25 | -| triggerTokens | int | 触发截断的token数量阈值 | 40000 | -| keepMessages | int | 截断后保留的消息数量 | 20 | -| keepTokens | int | 截断后保留的token数量 | 0 | -| maxArgLength | int | 工具参数的最大长度,超过则截断 | 2000 | -| truncationText | String | 截断时显示的提示文本 | ...(argument truncated) | - -## 内部类:PermissionContext - -权限上下文配置。 - -| 字段名 | 类型 | 描述 | 默认值 | 示例 | -|--------|------|------|--------|------| -| mode | String | 工作区权限上下文模式 | default | default/accept_edits/explore/bypass/dont_ask | -| allow | Set\ | 运行执行的工具列表 | - | - | -| deny | Set\ | 拒绝执行的工具列表 | - | - | -| ask | Set\ | 需要询问用户的工具列表 | - | - | - -## 内部类:MemoryConfig - -长期记忆配置。 - -| 字段名 | 类型 | 描述 | 默认值 | 示例 | -|--------|------|------|--------|------| -| model | NewApiModelProperties | 记忆操作(刷新 + 归纳)专用模型,不设置则使用智能体主模型 | - | - | -| flushPrompt | String | 刷新记忆的提示词,null表示使用默认值 | - | - | -| consolidationPrompt | String | 归纳记忆的提示词,必须包含两个%d占位符(max-tokens, max-chars),null表示使用默认值 | - | - | -| consolidationMaxTokens | int | 归纳时的最大token数 | 4000 | 4000 | -| consolidationMinGap | int | 归纳的最小间隔(单位:分钟) | 30 | 30 | -| dailyFileRetentionDays | int | 每日记忆文件保留天数 | 30 | 30 | -| sessionRetentionDays | int | 会话记忆JSONL日志保留天数 | 30 | 30 | -| flushTrigger | String | 每次调用后flush的触发策略(ALWAYS/NEVER) | ALWAYS | ALWAYS | - -## 内部类:SubagentSpec - -子智能体规格配置。 - -| 字段名 | 类型 | 描述 | 默认值 | -|--------|------|------|--------| -| name | String | 子智能体名称 | - | -| description | String | 子智能体描述 | - | -| systemPrompt | String | 子智能体的系统提示词 | - | -| workspaceMode | String | 工作区模式:SHARED=共享主智能体的工作区,ISOLATED=独立的工作区 | SHARED | -| model | NewApiModelProperties | 子智能体使用的模型,不设置则使用主智能体的模型 | - | -| steps | int | 这个子智能体单次最大迭代次数,不填或者设置0则使用主智能体最大迭代次数的1/2 | 0 | -| mode | String | 默认 subagent,可选:primary/subagent/all;primary 不允许被 spawn | subagent | -| hidden | Boolean | 默认false,设为 true 时不出现在 agent 可见列表(仍可程序化 spawn) | false | - ---- - -## 示例 JSON - -```json -{ - "mainAgentSpec": { - "name": "main-agent", - "description": "主智能体", - "systemPrompt": "你是一个有用的助手。", - "chatModel": { - "model": "gpt-4", - "apiKey": "your-api-key" - }, - "enablePlanMode": true, - "enableShell": false, - "enableAgentTraceLog": true, - "asyncToolTimeout": 30, - "maxContextTokens": 8000, - "maxIter": 10, - "maxRetries": 3 - }, - "workspace": { - "stateStoreType": "mysql", - "isolationScope": "USER", - "anonymousUserId": "anonymous" - }, - "compaction": { - "triggerMessages": 50, - "triggerTokens": 0, - "reserved": 20000, - "keepMessages": 20, - "keepTokens": -1, - "keepTokensMin": 2000, - "keepTokensMax": 8000, - "keepTokensRatio": 0.25, - "summaryPrompt": "default", - "flushBeforeCompact": true, - "offloadBeforeCompact": true, - "prune": { - "protectTokens": 40000, - "minimumTokens": 20000, - "maxOutputChars": 2000, - "excludedTools": ["read_file", "memory_search", "memory_get", "session_search"] - }, - "truncate": { - "triggerMessages": 25, - "triggerTokens": 40000, - "keepMessages": 20, - "keepTokens": 0, - "maxArgLength": 2000, - "truncationText": "...(argument truncated)" - }, - "model": { - "model": "gpt-4", - "apiKey": "your-api-key" - } - }, - "skillRepository": { - "mysql": { - "enable": true, - "databaseName": "skill_db", - "skillsTableName": "skills", - "resourcesTableName": "skill_resources", - "createIfNotExist": true, - "writeable": false - }, - "classPath": { - "enable": true, - "directory": "skills" - }, - "a2s": { - "enable": true, - "directory": "/app/skills", - "apiGateway": "https://misdev.lcfuturecenter.com/prod-api", - "apiDebugSkillInfoUri": "/mcp/skill/openapi/debug/{skill_name}", - "apiReleaseSkillInfoUri": "/mcp/skill/openapi/release/{skill_name}", - "apiDownloadSkillUri": "/resource/oss/download/{oss_id}", - "availableSkills": ["skill1|debug", "skill2|release"] - }, - "httpClient": { - "version": "HTTP/1.1", - "connectTimeout": 10, - "requestTimeout": 30, - "enableRequestLogger": true, - "enableResponseLogger": false, - "defaultHeaders": { - "Authorization": "Bearer token123" - } - } - }, - "a2sMcpProvider": { - "apiGateway": "https://misdev.lcfuturecenter.com/prod-api", - "apiQueryMcpServerInfoUri": "/mcp/server/openapi/list", - "httpClient": { - "version": "HTTP/1.1", - "connectTimeout": 10, - "requestTimeout": 30, - "enableRequestLogger": true, - "enableResponseLogger": false, - "defaultHeaders": {} - } - }, - "mcpServerConfigs": [ - { - "serverName": "weather-server", - "transport": "sse", - "enableTools": ["get_weather", "get_forecast"], - "initializationTimeout": 10, - "timeout": 600 - } - ], - "permissionContext": { - "mode": "default", - "allow": ["read_file", "list_files"], - "deny": ["delete_file"], - "ask": ["write_file"] - }, - "memoryConfig": { - "model": { - "model": "gpt-4", - "apiKey": "your-api-key" - }, - "flushPrompt": "刷新记忆提示词", - "consolidationPrompt": "归纳记忆提示词,最大token数:%d,最大字符数:%d", - "consolidationMaxTokens": 4000, - "consolidationMinGap": 30, - "dailyFileRetentionDays": 30, - "sessionRetentionDays": 30, - "flushTrigger": "ALWAYS" - }, - "subagentSpec": [ - { - "name": "research-agent", - "description": "研究智能体", - "systemPrompt": "你是一个研究助手。", - "workspaceMode": "SHARED", - "model": { - "model": "gpt-4", - "apiKey": "your-api-key" - }, - "steps": 5, - "mode": "subagent", - "hidden": false - } - ] -} -``` \ No newline at end of file diff --git a/mingyan.md b/mingyan.md deleted file mode 100644 index 60a5dcf..0000000 --- a/mingyan.md +++ /dev/null @@ -1,32 +0,0 @@ -执行 stress 测试 - -# 我在 MIS 系统的真实个人信息 - -**请以下面的信息作为我的个人信息**,上下文中若出现其他个人信息,请忽略掉,以此为准。 - - - - 我的用户名 - mingyan.li - - - 我的用户ID - 7 - - - 今天的日期 - 2026-09-29 - - - 我的工号 - H220GEE - - - 当前会话ID - 2104757602742181889 - - - 我的邮箱 - Mingyan.Li@lcfuturecenter.com - - \ No newline at end of file diff --git a/mis-debugging.json b/mis-debugging.json deleted file mode 100644 index d60a9d3..0000000 --- a/mis-debugging.json +++ /dev/null @@ -1,142 +0,0 @@ -{ - "mainAgentSpec": { - "name": "se-agent", - "description": "主智能体", - "systemPrompt": "nacos:se-agent-prompt-main.txt", - "chatModel": { - "model": "Qwen3.6-35B-A3B", - "apiKey": "sk-xxx" - }, - "enablePlanMode": false, - "enableShell": false, - "enableAgentTraceLog": true, - "asyncToolTimeout": 30, - "maxContextTokens": 8000, - "maxIter": 200, - "maxRetries": 3 - }, - "workspace": { - "stateStoreType": "mysql", - "isolationScope": "USER", - "anonymousUserId": "anonymous" - }, - "compaction": { - "triggerMessages": 50, - "triggerTokens": 0, - "reserved": 20000, - "keepMessages": 20, - "keepTokens": -1, - "keepTokensMin": 2000, - "keepTokensMax": 8000, - "keepTokensRatio": 0.25, - "summaryPrompt": "default", - "flushBeforeCompact": true, - "offloadBeforeCompact": true, - "prune": { - "protectTokens": 40000, - "minimumTokens": 20000, - "maxOutputChars": 2000, - "excludedTools": ["read_file", "memory_search", "memory_get", "session_search"] - }, - "truncate": { - "triggerMessages": 25, - "triggerTokens": 40000, - "keepMessages": 20, - "keepTokens": 0, - "maxArgLength": 2000, - "truncationText": "...(argument truncated)" - }, - "model": { - "model": "qwen3.5-122b-a10b-fp8", - "apiKey": "sk-xxx" - } - }, - "skillRepository": { - "mysql": { - "enable": false, - "databaseName": "mis-dubugging", - "skillsTableName": "agent_skill", - "resourcesTableName": "agent_skill_resource", - "createIfNotExist": true, - "writeable": false - }, - "classPath": { - "enable": false, - "directory": "skills" - }, - "a2s": { - "enable": true, - "directory": "a2s-skills", - "apiGateway": "https://misdev.lcfuturecenter.com/prod-api", - "apiDebugSkillInfoUri": "/mcp/skill/openapi/debug/{skill_name}", - "apiReleaseSkillInfoUri": "/mcp/skill/openapi/release/{skill_name}", - "apiDownloadSkillUri": "/resource/oss/download/{oss_id}", - "availableSkills": ["skill1|debug", "skill2|release"] - }, - "httpClient": { - "version": "HTTP/1.1", - "connectTimeout": 10, - "requestTimeout": 30, - "enableRequestLogger": true, - "enableResponseLogger": true, - "defaultHeaders": { - "Authorization": "Bearer token123" - } - } - }, - "a2sMcpProvider": { - "apiGateway": "https://misdev.lcfuturecenter.com/prod-api", - "apiQueryMcpServerInfoUri": "/mcp/server/openapi/list", - "httpClient": { - "version": "HTTP/1.1", - "connectTimeout": 10, - "requestTimeout": 30, - "enableRequestLogger": true, - "enableResponseLogger": false, - "defaultHeaders": {} - } - }, - "mcpServerConfigs": [ - { - "serverName": "weather-server", - "transport": "sse", - "enableTools": ["get_weather", "get_forecast"], - "initializationTimeout": 10, - "timeout": 600 - } - ], - "permissionContext": { - "mode": "default", - "allow": ["read_file", "list_files"], - "deny": ["delete_file"], - "ask": ["write_file"] - }, - "memoryConfig": { - "model": { - "model": "gpt-4", - "apiKey": "your-api-key" - }, - "flushPrompt": "刷新记忆提示词", - "consolidationPrompt": "归纳记忆提示词,最大token数:%d,最大字符数:%d", - "consolidationMaxTokens": 4000, - "consolidationMinGap": 30, - "dailyFileRetentionDays": 30, - "sessionRetentionDays": 30, - "flushTrigger": "ALWAYS" - }, - "subagentSpec": [ - { - "name": "research-agent", - "description": "研究智能体", - "systemPrompt": "你是一个研究助手。", - "workspaceMode": "SHARED", - "model": { - "model": "gpt-4", - "apiKey": "your-api-key" - }, - "steps": 5, - "mode": "subagent", - "hidden": false - } - ] -} \ No newline at end of file diff --git a/se-agent-mcp-tool.md b/se-agent-mcp-tool.md deleted file mode 100644 index 8315462..0000000 --- a/se-agent-mcp-tool.md +++ /dev/null @@ -1,1220 +0,0 @@ -# SE 工作流 MCP 工具 API 文档 - -> **来源**:`docs/task/se工作流mcp工具统计.md`(草稿统计)→ 本文档按 `mis-mcp-server` **源码实现**补全为可调用的 API 文档 -> **覆盖范围**:SE 工作流相关的 **9 个** MCP 工具 -> **生成日期**:2026-09-22 -> **代码基线**:`mis-mcp-server` 分支 `dev` -> -> **一句话定位**:面向「AI 生成 SKILL / Prompt」场景的机器友好型接口文档。每个工具给出**参数表 + 返回 JSON 结构 + 字段语义 + 关联工具**。 - -### 修订记录(2026-09-22) - -编写本文档时发现 **5 处工具描述与实现不符**,已在 `mis-mcp-server` 侧修正(**未改动 `mbx` 下游代码**): - -| 工具 | 原描述问题 | 处置 | -|---|---|---| -| `queryDriverListVersion` | 说「驱动列表唯一标识」「返回 `packageFileUrl` 即可」——实为**版本**标识,且该字段**嵌套**在数组里、未裁剪 | ✅ 改描述 | -| `queryTestUnitListByProjectName` | 说「根据项目名称、**五码**查询」——下游 SQL **未按五码过滤** | ✅ 改描述 + 参数说明 | -| `queryProjectNameList` | 说「获取项目名称列表」——实为**固定最多 2 条** | ✅ 常量 `2` → `100`,并同步描述(**行为变更**) | -| `queryTestPcByUuids` | 未说明在线状态字段名——直觉会取恒为 null 的 `onlineStatus` | ✅ 描述里点明用 `onlineStatusKey` | -| `creatOrSendTask` | 未说明 `other.type` 必填——漏传会下游报错 | ✅ 描述里点明必填项 | - ---- - -## ⚠️ 确信度标记(务必先读) - -本文档所有字段名均来自**源码或真实响应样本**,不使用推测值。为便于区分,全文使用以下标记: - -| 标记 | 含义 | -|---|---| -| ✅ **已确定** | 直接来自 `mis-mcp-server` 源码逻辑、下游实现源码,或真实接口响应样本,字段名与结构可信 | -| ⚠️ **透传** | MCP 层**不裁剪**,原样返回下游响应;字段结构以**下游 MIS/MBX 服务为准**,可能随下游变更 | - -> 无法完全确证的少量细节**不散落在正文里**,统一收在 **§6.5 残留不确定项**。 -> 写 prompt 前建议先扫一遍 **§6.4 高风险陷阱汇总**——那里是「照直觉写就会错」的地方。 - -> **给 AI 生成 prompt 的建议**:引用 ⚠️ 透传 字段时,prompt 里应写成「从返回的 `xxx` 字段读取」而非硬编码整个结构; -> 引用 ✅ 已确定 字段时可以放心直接取值。 - ---- - -## 目录 - -- [1. 工具总览](#1-工具总览) -- [2. 全局约定](#2-全局约定) -- [3. 工具详情](#3-工具详情) - - [3.1 `debuggingProjectQuery`](#31-debuggingprojectquery) - - [3.2 `queryProjectNameList`](#32-queryprojectnamelist) - - [3.3 `queryDriverListNamesByProject`](#33-querydriverlistnamesbyproject) - - [3.4 `queryDriverListVersion`](#34-querydriverlistversion) - - [3.5 `prepareTaskFile`](#35-preparetaskfile) - - [3.6 `generatePreloadUpdateLink`](#36-generatepreloadupdatelink) - - [3.7 `creatOrSendTask`](#37-creatorsendtask) - - [3.8 `queryTestUnitListByProjectName`](#38-querytestunitlistbyprojectname) - - [3.9 `queryTestPcByUuids`](#39-querytestpcbyuuids) -- [4. 典型工作流(编排剧本)](#4-典型工作流编排剧本) -- [5. 生成 SKILL 与 Prompt 的指引](#5-生成-skill-与-prompt-的指引) -- [6. 附录](#6-附录) - - [6.1 MCP 接入信息](#61-mcp-接入信息) - - [6.2 下游接口与白名单对照](#62-下游接口与白名单对照) - - [6.3 易混淆 / 已废弃工具](#63-易混淆--已废弃工具) - - [6.4 高风险陷阱汇总(写 prompt 前必读)](#64-高风险陷阱汇总写-prompt-前必读) - - [6.5 残留不确定项](#65-残留不确定项) - ---- - -## 1. 工具总览 - -### 1.1 速查表 - -| # | MCP 工具名 | 所属服务 | 用途 | 必填参数 | 返回形态 | -|---|---|---|---|---|---| -| 1 | `debuggingProjectQuery` | `mis-mcp-tool-debugging` | 按项目名称/别名/五码查**项目基础信息** | 无(全部可选) | 分页信封 `{code,msg,total,rows[]}` ⚠️ | -| 2 | `queryProjectNameList` | `mis-mcp-tool-driver` | 取 MBX 侧**项目名称 + projectUuid** | 无(`creatorCode` 可选) | 数组 `[{name,projectUuid}]` ✅ | -| 3 | `queryDriverListNamesByProject` | `mis-mcp-tool-driver` | 按项目组/项目取**全部 Driver List Name** | `projectGroupUuid` 或 `projectUuid` | 数组 `[{driverListVersionUuid,driverListName}]` ✅ | -| 4 | `queryDriverListVersion` | `mis-mcp-tool-driver` | 取驱动列表版本的**包下载地址** | `driverListVersionUuid` | 下游对象 ⚠️(含 `packageFileUrl`) | -| 5 | `prepareTaskFile` | `mis-mcp-tool-driver` | 下载文件→重传到文件服务,换**任务下发可用的 fileUuid** | `fileUrl` | 对象 `{fileUuid,fileUrl,fileName,fileExtensionKey}` ✅ | -| 6 | `generatePreloadUpdateLink` | `mis-mcp-tool-vlab` | 生成 VLAB Preload 向导的**更新下载链接** | `project` | 对象(成功/失败两种结构)✅ | -| 7 | `creatOrSendTask` | `mis-mcp-tool-vlab` | **创建或下发测试任务** | `creatorCode`,`requestBodyJson` | 下游对象 ⚠️ / 纯文本提示 ✅ | -| 8 | `queryTestUnitListByProjectName` | `mis-mcp-tool-vlab` | 按项目名+五码查**机器列表** | `projectName`,`modelCode`,`ownerCode` | 下游列表 ⚠️ / 纯文本提示 ✅ | -| 9 | `queryTestPcByUuids` | `mis-mcp-tool-vlab` | 按 UUID 批量查**测试机在线状态** | `testUnitUuids` | 下游列表 ⚠️ | - -> **参数必填标记来自源码**:`@ToolParam` 未写 `required = false` 即为**必填**。 - -### 1.2 数据依赖关系(谁喂谁) - -这是生成 prompt 时最关键的一张图——**ID 都是一跳一跳传递的**: - -``` -① debuggingProjectQuery ──► projectName / projectUuid / modelCode - │ -② queryProjectNameList ──────► projectUuid(MBX 侧)──┐ - │ -③ queryDriverListNamesByProject ◄─────────────────────┘ - │ (需要 projectGroupUuid 或 projectUuid) - └──► driverListVersionUuid - │ -④ queryDriverListVersion ◄──┘ - └──► packageFileUrl - │ -⑤ prepareTaskFile ◄─┘ - └──► fileUuid - │ -⑦ creatOrSendTask ◄──┘ (填入 requestBodyJson.model.children[].documentCopyDTOList[].fileUuid) - -⑥ generatePreloadUpdateLink 独立链路,只需 project 名称(+ 可选 osVer) -⑧ queryTestUnitListByProjectName ──► testUnitUuid[] - │ -⑨ queryTestPcByUuids ◄────────────────────┘ (查在线状态) -``` - -**关键 ID 传递表**: - -| 上游工具 | 产出字段 | 下游工具 | 填入位置 | -|---|---|---|---| -| `queryDriverListNamesByProject` | `driverListVersionUuid` | `queryDriverListVersion` | 入参 `driverListVersionUuid` | -| `queryDriverListVersion` | `driverPackageVersionList[].packageFileUrl` | `prepareTaskFile` | 入参 `fileUrl` | -| `prepareTaskFile` | `fileUuid` | `creatOrSendTask` | `requestBodyJson.model.children[].documentCopyDTOList[].fileUuid` | -| `queryProjectNameList` | `projectUuid` | `queryDriverListNamesByProject` | 入参 `projectUuid` | -| `queryTestUnitListByProjectName` | `testUnitUuid` | `queryTestPcByUuids` | 入参 `testUnitUuids[]` | - -### 1.3 语义说明:两个「项目查询」不重复(用户补充) - -- `debuggingProjectQuery` —— 查的是 **SE 系统同步过来的 project** 信息; -- `queryProjectNameList` —— 查的是 **MBX 系统**的 project 信息; -- **两边的 project 的 `name` 值是对应的**,可互为参照。 - -> AI 写 prompt 时:要「项目基础信息」用 ①;要「能直接喂给 Driver 链路的 `projectUuid`」用 ②。 - ---- - -## 2. 全局约定 - -### 2.1 返回信封与三种裁剪行为 - -MCP 工具**全部返回字符串**(JSON 文本)。脱掉下游信封 `{code, msg, data}` 后,按模块有**三种**不同行为——写 prompt 时必须区分: - -| 行为 | 工具 | 返回内容 | -|---|---|---| -| **A. 全量透传** | `debuggingProjectQuery` | 返回**整个信封** `{code,msg,total,rows[]}`,`rows[]` 内字段**不裁剪** ⚠️ | -| **B. 取 data(分页自动展平)** | `queryDriverListVersion`、`creatOrSendTask`、`queryTestUnitListByProjectName`、`queryTestPcByUuids` | 若 `data` 是对象且含 `records`,**只返回 `records` 数组**;否则返回 `data` 本身;`data` 为空返回 `"[]"` ⚠️ | -| **C. 取 data + 字段裁剪** | `queryProjectNameList`、`queryDriverListNamesByProject`、`prepareTaskFile`、`generatePreloadUpdateLink` | 只返回源码中显式挑出的字段 ✅ | - -> **注意 B 类的空值表现**:`data` 为空时返回字符串 `"[]"`(**空数组**,不是空对象)。 - -### 2.2 分页参数命名不统一(易错点) - -| 服务 | 页码参数 | 每页参数 | 默认值 | -|---|---|---|---| -| `mis-mcp-tool-debugging` | `pageNum` | `pageSize` | 1 / 10 | -| `mis-mcp-tool-driver` | `current` | `size` | 1 / 10(`queryProjectList*` / `queryDriverChidPage` / `queryDriverPackageList` / `queryWu*`)
1 / 5(`queryDriverListPage`) | -| `mis-mcp-tool-vlab` | `current` | `size` | 1 / 10 | - -> **两个工具没有分页参数**(内部固定,调用方无需也无法指定): -> `queryProjectNameList`(固定第 1 页、每页 **100** 条)、`queryDriverListNamesByProject`(自动翻页取全量,每页 100 条)。 - -### 2.3 用户 ID 与鉴权 - -- **两种用户 ID 不能混用**:MCP 工具入参普遍收 **MIS 系统用户 ID**(如 `creatorCode`、`ownerCode`), - 由服务内部通过 `MbxUserIdConverter` 转成 **MBX 用户 ID** 后传给下游(5 分钟本地缓存)。 -- **转换失败有专用提示**:部分工具转换失败时返回**纯文本**而非 JSON,见 §2.4。 -- **鉴权由 MCP 客户端透传**,调用方(LLM 侧)**不需要**在工具参数里传 token; - 凭证走 MCP 请求头 `auth` / `clientid`,由 `MisAuthForestInterceptor` 注入下游。 - -### 2.4 非 JSON 返回(prompt 必须能识别) - -以下情况返回的是**纯文本字符串**,不是 JSON——AI 解析时应先判断首字符: - -| 工具 | 返回文本 | 触发条件 | -|---|---|---| -| `creatOrSendTask` | `请输入当前登录人信息` | `creatorCode` 为空,或 MIS→MBX 用户 ID 转换失败 | -| `queryTestUnitListByProjectName` | `登录人信息转换异常` | `ownerCode` 有值但转换失败 | - -### 2.5 异常的处理方式 - -参数校验失败、下游业务失败时,工具**抛异常**(`IllegalArgumentException` / `RuntimeException`), -由 MCP 协议以错误形式返回,**不会**包装成 JSON。典型触发: - -- `queryDriverListVersion`、`queryTestPcByUuids` 等:必填参数为空(如 `testUnitUuids` 空列表); -- 所有工具:下游返回非 JSON、下游业务码失败(错误信息取下游 `msg`)。 - ---- - -## 3. 工具详情 - -### 3.1 `debuggingProjectQuery` - -**摘要**:根据项目名称、项目别名、项目五码查询项目基础信息,返回项目列表分页数据。 - -| 项 | 值 | -|---|---| -| 所属服务 | `mis-mcp-tool-debugging`(端口 18780,`STATELESS`) | -| Java 方法 | `ProjectMcpService.queryProjectList` | -| MCP 工具名 | `debuggingProjectQuery`(**源码中显式指定**,与 Java 方法名不同,调用时必须用这个名字) | -| 下游接口 | `GET {misApiBaseUrl}/debugging/project`(MIS 平台,网关白名单已放行) | -| 返回裁剪 | **A 类:全量透传**(`rows[]` 内 34 个字段全部返回,不裁剪)⚠️ | - -**参数表** - -| 参数名 | 类型 | 必填 | 默认 | 说明 | 示例 | -|---|---|---|---|---|---| -| `projectName` | String | 否 | — | 项目名称 | `IdeaPad 5 Pro 16ARP8` | -| `projectAlias` | String | 否 | — | 项目别名 | — | -| `modelCode` | String | 否 | — | 项目五码 | `LT4EN` | -| `ppmQuery` | String | 否 | — | 项目负责人名称或参与人 | `san.zhang` | -| `mtCode` | String | 否 | — | 项目四码 | `81S3` | -| `pageSize` | Integer | 否 | `10` | 每页条数 | `10` | -| `pageNum` | Integer | 否 | `1` | 页码 | `1` | - -**返回 JSON 结构** ✅(顶层 5 字段)/ ⚠️(透传,未裁剪) - -```jsonc -{ - "total": 0, // number 总条数 - "rows": [ /* 见下表,Project 实体,34 个字段 */ ], - "code": 200, // number 成功码固定 200 - "msg": "查询成功", // string - "extraData": null // 该接口路径下恒为 null -} -``` - -**`rows[]` 元素字段表**(实体 `com.lcfc.debugging.domain.Project`,**无任何 JSON 重命名注解**) - -| 字段名 | 类型 | 说明 | -|---|---|---| -| `projectUuid` | Long → number/string | 主键。**类型不确定**:雪花 ID 超 2^53-1 时会被序列化成字符串,须按「可能是数字也可能是字符串」处理 | -| `idpProjectUuid` | String | idp 项目管理表主键 | -| `projectName` | String | Project Name 数据 | -| `projectCode` | String | Project code 数据 | -| `projectAlias` | String | 项目别名 | -| `lenovoProductName` | String | 联想产品名称 | -| `issueOwners` | Array\ | Issue Owner 列表,元素为 `{category, component, owner}` | -| `modelCode` | String | 五码信息(BOX Model Code) | -| `mtCode` | String | 四码信息 | -| `finCode` | String | 财务代码 | -| `bu` | String | BU 信息 | -| `developmentType` | String | Development Type | -| `generation` | String | Generation | -| `segment` | String | Segment | -| `pm` | String | PM | -| `ppm` | Array\ | PPM 列表 | -| `pje` | Array\ | PJE 列表 | -| `biosCode` | String | BIOS Code | -| `ddsTime` | String | 日期,格式固定 `yyyy-MM-dd` | -| `pkoTime` | String | 同上 | -| `evtStartTime` / `evtEndTime` | String | 同上 | -| `fvtStartTime` / `fvtEndTime` | String | 同上 | -| `sitStartTime` / `sitEndTime` | String | 同上 | -| `svtStartTime` / `svtEndTime` | String | 同上 | -| `sovpTime` / `ssTime` | String | 同上 | -| `actuaiEopTime` | String | 同上。**字段名拼写就是 `actuaiEopTime`**(非 `actual`),按原样使用 | -| `sort` | Integer | 排序号 | -| `delFlag` | String | 删除标志,查询恒定返回 `"0"` | -| `ppmQuery` | null | **恒为 null**(该字段只用于查询条件,不参与返回取值) | - -**返回示例**(截取) - -```json -{ - "total": 1, - "rows": [ - { - "projectUuid": "2049298006288687105", - "projectName": "IdeaPad 5 Pro 16ARP8", - "projectAlias": "LCP8", - "modelCode": "LT4EN", - "mtCode": "81S3", - "ppm": ["san.zhang"], - "pje": [], - "ddsTime": "2026-03-01", - "delFlag": "0", - "ppmQuery": null - } - ], - "code": 200, - "msg": "查询成功", - "extraData": null -} -``` - -**注意事项** - -- 这是**唯一一个返回「整个信封」**的工具(其余 debugging 工具会裁剪成 `{code,msg,total,rows[]}` 且过滤行内字段)。若 prompt 里要遍历数据,需先取 `rows`。 -- `total` 是**总条数**,不是当前页条数。 -- `projectUuid` 在别的工具里常以字符串形式出现,**做参数传递时按字符串处理最安全**。 -- 查的是 **SE 系统同步过来的项目信息**,与 `queryProjectNameList` 的 MBX 侧数据来源不同,但 `name` 对应(见 §1.3)。 - -**关联工具**:`queryDriverListNamesByProject`(其 `projectUuid` 可来自本工具)、`queryProjectNameList` - ---- - -### 3.2 `queryProjectNameList` - -**摘要**:获取项目名称列表,返回 `name` 与 `projectUuid`。`creatorCode` 有值时只查该用户所涉及的项目。 - -| 项 | 值 | -|---|---| -| 所属服务 | `mis-mcp-tool-driver`(端口 18767,`STATELESS`) | -| Java 方法 | `DriverService.queryProjectNameList` | -| MCP 工具名 | `queryProjectNameList` | -| 下游接口 | `GET {misDriverBusinessBaseUrl}/project/mcpvlabpage`(MBX `mbv-service-business`) | -| 返回裁剪 | **C 类:取 data + 裁剪**,只保留 `name` / `projectUuid` ✅ | - -**参数表** - -| 参数名 | 类型 | 必填 | 默认 | 说明 | -|---|---|---|---|---| -| `creatorCode` | String | 否 | — | 当前登录人 **MIS 系统用户 ID**。有值 → 只查该用户涉及的项目 | - -> **入参规则**(源码 `MbxUserIdConverter`):`creatorCode` 必须是**纯数字**的 MIS 用户 ID; -> 为空、非数字、或查不到映射时,工具**不会**把用户条件传给下游(即退化成「不带用户过滤」查询),**不报错**。 - -**返回 JSON 结构** ✅ - -```jsonc -[ - { - "name": "string", // 项目名称:实际取自下游 portfolioProjectName - "projectUuid": "string" // 项目唯一标识,可直接喂给 queryDriverListNamesByProject - } -] -``` - -> **已核实**:下游 `ProjectPageInfo` **没有 `name` 字段**,所以源码里「`portfolioProjectName` 为空则回退 `name`」的兜底**永远不会触发**。 -> 实际取值路径只有 `portfolioProjectName` 一条;该字段为空的行会被**整条丢弃**(不返回)。 -> 因此 prompt 中应把 `name` 理解为「下游的项目名称(portfolioProjectName)」,不要去找别的名字来源。 - -**返回示例** - -```json -[ - { "name": "IdeaPad 5 Pro 16ARP8", "projectUuid": "018cd84ba0a82b020410bb40a1d85ba5" }, - { "name": "Legion 5 15IRX10", "projectUuid": "000c798c09d537f4f25f5b29046aebd1" } -] -``` - -**注意事项** - -- **本工具固定只取第 1 页、每页 100 条**(源码常量 `PROJECT_NAME_LIST_SIZE = 100`),即**最多返回 100 条项目**,且**没有分页参数**。 - 超过 100 条时**不会自动翻页**;需要按名称检索或取更多项目请用 `debuggingProjectQuery`。 - (该常量原为 `2`,2026-09-22 修正为 `100`。) -- 返回**不含分页信息**,是纯数组。 -- 两个字段都为空的下游记录会被过滤掉。 -- 空结果返回 `"[]"`。 - -**关联工具**:`queryDriverListNamesByProject`(承接 `projectUuid`)、`debuggingProjectQuery`(项目基础信息) - ---- - -### 3.3 `queryDriverListNamesByProject` - -**摘要**:根据项目组唯一标识或项目唯一标识,查询对应的**全部** Driver List Name,返回 `driverListVersionUuid` 与 `driverListName` 集合。 - -| 项 | 值 | -|---|---| -| 所属服务 | `mis-mcp-tool-driver` | -| Java 方法 | `DriverService.queryDriverListNamesByProject` | -| MCP 工具名 | `queryDriverListNamesByProject` | -| 下游接口 | `GET {misDriverBaseUrl}/driverlist/mcpvlabpage`(内部自动翻页,每页 100 条直到取完) | -| 返回裁剪 | **C 类:裁剪并去重** ✅ | - -**参数表** - -| 参数名 | 类型 | 必填 | 默认 | 说明 | 示例 | -|---|---|---|---|---|---| -| `projectGroupUuid` | String | 否 | — | 项目组唯一标识(与 `projectUuid` **至少给一个**) | `d5ac3039abf4c8302cccefc40f7056dd` | -| `projectUuid` | String | 否 | — | 项目唯一标识(与 `projectGroupUuid` **至少给一个**) | `018cd84ba0a82b020410bb40a1d85ba5` | - -**返回 JSON 结构** ✅ - -```jsonc -[ - { - "driverListVersionUuid": "string", // 驱动列表【版本】唯一标识 —— 给 queryDriverListVersion 用 - "driverListName": "string" // 驱动列表名称:实际取自下游 driverListName - } -] -``` - -> **已核实**:源码写的是「优先取 `nameRemark`,为空则回退 `driverListName`」,但下游**分页接口的 SQL 根本没查 `name_remark` 列**, -> 因此 `nameRemark` 在这个链路上**恒为 null**,回退分支**必然生效** —— 返回值里的 `driverListName` 实际就是下游的 `driverListName`。 -> (`nameRemark` 只在单查版本详情、即 §3.4 的返回里才有值。)对调用方而言:**只会拿到一个非空的 `driverListName`,直接用它做筛选即可**。 - -**返回示例** - -```json -[ - { "driverListVersionUuid": "93b947167dad2e8956a70358742f70cc", "driverListName": "MyLNBGroup_Win10 21H2_V02" }, - { "driverListVersionUuid": "c95301ca9485a1bb2102989f91e5eaf9", "driverListName": "MyLNBGroup_Win10 21H2_V01_20260407" } -] -``` - -**注意事项** - -- 返回的是**版本级**标识(`driverListVersionUuid`),**不是**驱动列表级标识;一个驱动列表有多个版本时会有多条。 -- 结果已按 `driverListVersionUuid` **去重**;名称为空、UUID 为空的记录会被跳过。 -- 工具内部会**自动翻页**(`size=100`)取全量,调用方**不需要**传分页参数,也没有分页参数。 -- 返回**不含分页信息**,是纯数组;空结果返回 `"[]"`。 -- 项目组/项目下驱动列表很多时,返回可能较长——prompt 里应引导模型**先按名称筛选**再取版本。 -- ⚠️ **已知下游缺陷**:下游分页接口对「**一个版本都没有的空驱动列表**」会抛数组越界 → 返回 **500**。 - 出现「Driver 接口业务失败」类报错时,除了参数问题,也要考虑该分组下存在空驱动列表这一可能。 - -**关联工具**:`queryDriverListVersion`(承接 `driverListVersionUuid`)、`queryProjectNameList`(提供 `projectUuid`) - ---- - -### 3.4 `queryDriverListVersion` - -**摘要**:根据驱动列表唯一标识查询驱动列表版本信息,用于拿到**驱动包的下载地址**。 - -| 项 | 值 | -|---|---| -| 所属服务 | `mis-mcp-tool-driver` | -| Java 方法 | `DriverService.queryDriverListVersion` | -| MCP 工具名 | `queryDriverListVersion` | -| 下游接口 | `GET {misDriverBaseUrl}/listversion/mcpvlab/{driverListUuid}` | -| 返回裁剪 | **B 类:取 data(未做字段裁剪)** ⚠️ | - -**参数表** - -| 参数名 | 类型 | 必填 | 默认 | 说明 | 示例 | -|---|---|---|---|---|---| -| `driverListVersionUuid` | String | **是** | — | 驱动列表版本唯一标识,来自 `queryDriverListNamesByProject` 的返回 | `93b947167dad2e8956a70358742f70cc` | - -**返回 JSON 结构** ⚠️ **透传(未裁剪)** - -MCP 层**只拆信封**,返回下游 `data` 的**完整内容**(`data` 为分页对象时取 `records`,为空时返回 `[]`)。 -`data` 的结构是 `DriverListVersionVO`: - -```jsonc -{ - "driverListVersionUuid": "string", - "nameRemark": "string", // 本接口有值(与分页列表不同) - "driverListUuid": "string", - "driverListVersion": 0, - "status": null, // 下游未映射,恒 null - "driverListReleaseDate": "yyyy-MM-dd", - "creatorCode": "string", - "modifierCode": "string", - "createTime": "string", - "modifyTime": "string", - "activityStatusKey": "string", - "homesFlag": true, - "driverListName": "string", - "projectGroupUuid": "string", - "projectGroupName": "string", - "spmsProjectName": "string", - "driverListGmStatus": 0, - "driverListStatus": 0, // 0-临时 1-草稿 2-发布 - "changeList": "string", - "remark": "string", - "comment": "string", - "osTypeKeyList": [0], - - // ★★★ 目标产物在这里 ★★★ - "driverPackageVersionList": [ - { - "packageFileUrl": "★★ 驱动包下载地址 —— prepareTaskFile 的 fileUrl 入参", - "...": "DriverPackageVersionVO 其余字段" - } - ], - "solidifiedDriverPackageVersionList": [ /* 结构同上,仅 driverListStatus==2(发布态)时有值 */ ], - - "releaseContactUuidList": ["string"], - "releaseContactList": [ /* DriverContactVO */ ], - "driverPoContactList": [ /* DriverContactVO */ ], - "packageVersionNum": 0, - "bu": 0, - "logoNeeded": [0], - "platform": "string", - "baseIntelBkcVersion": "string", - "specialField": "string" -} -``` - -> ### ⚠️ 最容易踩的坑:`packageFileUrl` **不在顶层** -> -> MCP 实现**不裁剪字段**,`packageFileUrl` 也**不是顶层字段**—— -> 它是嵌套元素 `DriverPackageVersionVO` 的字段,位于: -> -> - `driverPackageVersionList[].packageFileUrl`,或 -> - `solidifiedDriverPackageVersionList[].packageFileUrl`(仅发布态 `driverListStatus == 2` 时有值) -> -> **prompt 必须写成「从 `driverPackageVersionList[].packageFileUrl` 取值」**, -> 若写成「取返回的 `packageFileUrl`」会取到 `undefined`。 -> 建议优先读 `solidifiedDriverPackageVersionList`(发布态更稳定),为空再回退 `driverPackageVersionList`。 -> -> ✅ **2026-09-22 已修正**:本工具的 `description` 原先写「返回 `packageFileUrl` 的下载地址即可」, -> 与实现不符,现已改为明确说明该字段的嵌套位置(见 `DriverService.queryDriverListVersion`)。 - -**注意事项** - -- 入参 `driverListVersionUuid` 填的是**版本 UUID**(照抄 `queryDriverListNamesByProject` 的返回值)。 - MCP 源码内部把它命名成 `driverListUuid` 只是**命名失误**,下游实际按版本 UUID 查询,不影响调用。 -- 拿到的 `packageFileUrl` **不能直接**用于任务下发,必须再过 `prepareTaskFile`(见 §3.5)。 -- 该 URL 形如 `http://<文件服务>/mbvClient/downloadFile?objectName=...&bucketName=driver`,**必须带 `objectName` 与 `bucketName`**。 -- 传错成「驱动列表 UUID」时不会报错,而是 `data` 为 null → 返回 `[]`,需按空结果处理。 - -**关联工具**:`queryDriverListNamesByProject`(上游,提供 `driverListVersionUuid`)、`prepareTaskFile`(下游,消费 `packageFileUrl`) - ---- - -### 3.5 `prepareTaskFile` - -**摘要**:把「文件下载地址」对应的文件**重新上传到文件服务**,返回可用于测试任务下发的文件参数。 - -| 项 | 值 | -|---|---| -| 所属服务 | `mis-mcp-tool-driver` | -| Java 方法 | `DriverService.prepareTaskFile` | -| MCP 工具名 | `prepareTaskFile` | -| 下游接口 | ① `GET {misFileServiceBaseUrl}/mbvClient/downloadFile`(下载,`mbv-service-minio`)
② `POST {misFileServiceBaseUrl}/uploadFileSpecial`(上传到 `document` 桶) | -| 返回裁剪 | **C 类:裁剪** ✅ | - -**参数表** - -| 参数名 | 类型 | 必填 | 默认 | 说明 | 示例 | -|---|---|---|---|---|---| -| `fileUrl` | String | **是** | — | 文件下载地址,来自 `queryDriverListVersion` 返回的 `packageFileUrl` | `http://10.159.41.130:8080/mbvClient/downloadFile?objectName=20260413/16/55/33/xxx.zip&bucketName=driver` | - -> **`fileUrl` 必须带 `objectName` 与 `bucketName` 两个查询参数**,否则工具直接抛错(无法解析文件名/桶名)。 - -**返回 JSON 结构** ✅ - -```jsonc -{ - "fileUuid": "string", // ★ 任务下发要用的文件唯一标识 - "fileUrl": "string", // 上传后文件服务返回的访问地址 - "fileName": "string", // 文件名(取自 objectName 最后一段) - "fileExtensionKey": 0 // 文件扩展名标识;类型不固定(可能是数字/字符串/null),按原样传递即可 -} -``` - -**返回示例** - -```json -{ - "fileUuid": "8f2a1c9e4b7d4a1f9c3e5b6a7d8e9f01", - "fileUrl": "http://10.159.41.130:8080/mbvClient/downloadFile?objectName=document/20260922/xxx.zip&bucketName=document", - "fileName": "xxx.zip", - "fileExtensionKey": 3 -} -``` - -**它在链路中的位置**(**这是本工具存在的唯一理由**) - -``` -queryDriverListVersion → packageFileUrl →【prepareTaskFile】→ fileUuid - → creatOrSendTask 的 - requestBodyJson.model.children[].documentCopyDTOList[].fileUuid -``` - -> 为什么不能直接把 `packageFileUrl` 填进任务下发?因为 `creatOrSendTask` 的 `documentCopyDTOList` **只认 `fileUuid`**, -> 而 driver 桶的文件不落文件信息表、没有 `file_uuid`。重传到 `document` 桶才能换到一个可用的 `fileUuid`。 -> **因此这一步不可省略**,顺序也不能颠倒。 - -**注意事项** - -- ⏱ **耗时较长**:驱动包可能有几百 MB,内部超时为 **10 分钟**。prompt 里应提示用户「这一步较慢,请稍候」。 -- **不校验文件内容**,只做下载 + 上传;下载得到的是「HTTP 200 + 纯文本」形式的错误提示(如「文件不存在」)时会被拦截并报错。 -- 返回的 `fileUrl` 是**上传后**的新地址(`document` 桶),与入参的 `packageFileUrl`(`driver` 桶)**不同**,不要混用。 - -**关联工具**:`queryDriverListVersion`(上游,提供 `fileUrl`)、`creatOrSendTask`(下游,消费 `fileUuid`) - ---- - -### 3.6 `generatePreloadUpdateLink` - -**摘要**:根据项目信息生成 VLAB Preload 向导页面的 **preload 更新下载链接**。 - -| 项 | 值 | -|---|---| -| 所属服务 | `mis-mcp-tool-vlab`(端口 18769,`STREAMABLE`,端点 `/mcp`) | -| Java 方法 | `PreloadService.generatePreloadUpdateLink` | -| MCP 工具名 | `generatePreloadUpdateLink` | -| 下游接口 | `mbv-service-preload`:`/preload/preloadNameList` → `/preload/init` → `/preload/select` → `/preload/getOtherList` → `/preload/preloadVersion` → `/aod` | -| 返回裁剪 | **C 类:自行组装** ✅ | - -**参数表** - -| 参数名 | 类型 | 必填 | 默认 | 说明 | 示例 | -|---|---|---|---|---|---| -| `project` | String | **是** | — | 项目名称,**必须是 Preload 向导页面下拉选项中的值** | `IdeaPad 5 Pro 16ARP8` | -| `osVer` | String | 否 | 下拉列表**第一个**版本 | 操作系统版本,可用**页面展示名**(`description`)或**目录名**(`directory`) | `9.Win11` | - -> 其余页面字段(Location、Preload VER、OS Type、Language、OS Edition、HDD Config、模块穿梭框)**均按页面默认值自动提交**, -> 调用方**无需也无法**指定。 - -**返回 JSON 结构** ✅ —— **成功与失败是两种不同结构,prompt 必须能区分** - -**① 成功** - -```jsonc -{ - "downloadUrl": "string", // ★ 生成的 preload 更新下载链接 - "project": "string", // 实际匹配到的项目名(回显下游下拉里的原值) - "osVer": "string", // 实际匹配到的 OS 版本展示名 - "os": "string", // OS 目录名(directory) - "preloadVersion": "string", // 实际使用的 Preload VER - "locationName": "string" // 实际使用的 Location -} -``` - -**② 失败**(三种触发场景,`msg` 不同,附加字段也不同) - -```jsonc -{ - "success": false, // ★ 失败标志(注意:成功时【没有】success:true) - "msg": "string", // 失败原因 - // 以下附加字段随场景变化: - "project": "string", // 回显入参 - "osVer": "string", // 回显入参(可能为 null) - "os": "string", // 仅「未找到 Preload VER」场景 - "preloadVersion": "string", // 仅「未返回下载地址」场景 - "availableProjects": ["string"], // ★ 仅「Project 不在下拉选项中」场景 - "availableOsVer": ["string"] // ★ 仅「OS VER 不在下拉选项中」场景 -} -``` - -**失败场景对照表** - -| `msg` | 触发条件 | 可用来自纠偏的字段 | -|---|---|---| -| `Project 不在 Preload 向导下拉选项中` | `project` 与下游下拉值**不匹配**(忽略大小写、去空格后仍不匹配) | `availableProjects` —— 全部合法项目名 | -| `OS VER 不在 Preload 向导下拉选项中` | `osVer` 既不是某版本的 `description` 也不是 `directory` | `availableOsVer` —— 全部合法 OS 版本名 | -| `未找到对应的 Preload VER` | 项目+OS 组合下 select 返回空 | `project` / `osVer` / `os` | -| `生成 Preload 更新链接失败,下游未返回下载地址` | 走到 `/aod` 但没拿到地址 | `project` / `osVer` / `preloadVersion` | - -**返回示例** - -```json -{ - "downloadUrl": "http://mbxqas.lcfuturecenter.com/prod-api/preloadService/xxx/download?file=xxx.zip", - "project": "IdeaPad 5 Pro 16ARP8", - "osVer": "9.Win11", - "os": "Win11", - "preloadVersion": "PR9.0.0", - "locationName": "LCFC" -} -``` - -**注意事项** - -- ⚠️ **判成功的正确写法**:检查是否**存在 `downloadUrl`**,或检查 `success === false`。 - **不要**写 `success === true` —— 成功返回里**没有** `success` 字段。 -- `project` / `osVer` 都是**按下游下拉值精确匹配**(忽略大小写与首尾空格),**不是模糊查询**。 - 传错时不会返回空数组,而是返回**失败对象 + 候选列表**——这是自纠偏的关键: - **prompt 应引导模型用 `availableProjects` / `availableOsVer` 重新选取后再重试一次,而不是反复用同一个错值重试。** -- `osVer` 不传时取下拉列表**第一个**版本,与页面默认行为一致。 -- 该工具**会真实生成下载链接**(非只读查询),属于链路中副作用最强的一步。 - -**关联工具**:无上游依赖;项目名可参照 `debuggingProjectQuery` / `queryProjectNameList` 的 `name`(但**必须**用 Preload 页面下拉里的值) - ---- - -### 3.7 `creatOrSendTask` - -**摘要**:创建或下发测试任务。**本工作流中唯一的写操作**。 - -| 项 | 值 | -|---|---| -| 所属服务 | `mis-mcp-tool-vlab` | -| Java 方法 | `TaskService.creatOrSendTask` | -| MCP 工具名 | `creatOrSendTask`(**注意是 `creat` 不是 `create`**) | -| 下游接口 | `POST {misDispatcherBaseUrl}/mcpvlabcreatOrSendTask?fs={fs}&userId={userId}`,请求体为任务 JSON | -| 返回裁剪 | **B 类:取 data(未做字段裁剪)** ⚠️ | - -**参数表** - -| 参数名 | 类型 | 必填 | 默认 | 说明 | -|---|---|---|---|---| -| `creatorCode` | String | **是** | — | 当前登录人 **MIS 系统用户 ID**(纯数字)。服务内部转成 MBX `userId` 传给下游 | -| `requestBodyJson` | String | **是** | — | **任务请求体 JSON 字符串**。结构见下方“请求体”一节 | -| `fs` | Boolean | 否 | `false` | 随请求透传给下游的 `fs` 参数 | - -### 请求体 `requestBodyJson` 结构 ✅(已核实下游 `DispatcherServiceImpl.commonCreateTask`) - -> **`requestBodyJson` 必须是一个 JSON 字符串**(不是对象)。模型调用时需要把整个任务体**序列化成字符串**再作为参数传入。 -> 下游用 Hutool 解析(非强类型 DTO),只有一个字段是硬性必填:**`other.type`**。 - -**顶层结构** - -```jsonc -{ - "base": { /* TestTask —— 任务基本信息 */ }, - "other": { "type": 2 }, // ★ 必填!1=只保存 2=创建并下发 - "rule": { /* TestTaskUnitBinding —— 选机器规则 */ }, - "model": { /* TestModelNode —— 任务步骤树(模型视图时必填) */ }, - "testTaskIssueTypeCode": 1, // 1=模型视图(默认) 2=用例视图 - "testCaseAssociationVersionUuidList": [] // 仅用例视图(2)时必填 -} -``` - -**`base` 常用字段**(`TestTask`) - -| 字段 | 类型 | 说明 | -|---|---|---| -| `testTaskName` | String | 任务名称 | -| `testTaskTypeKey` | Integer | 1=测试任务,2=debug 任务 | -| `projectUuid` | String | 项目唯一标识 | -| `remark` | String | 备注 | -| `scheduleTime` | Date | 定时下发时间(**必须晚于当前时间**,否则报错) | - -> 下发时会被下游**强制覆盖**的字段(传了也不生效):`testTaskCode`(重新生成)、 -> `testModelUuid` / `testModelVersionUuid`、`ownerCode` / `creatorCode` / `operatorCode` / `modifierCode`(一律用 `userId` 覆盖)、 -> `activityStatusKey`、`testTaskStatusKey`、`submitState`。 - -**`other` 字段** - -| 字段 | 类型 | 说明 | -|---|---|---| -| `type` | Integer | **必填**。1=只保存,2=创建并下发。**为 null 会导致下游 NPE(500)** | -| `isClear` | Boolean | 是否清除当前执行任务 | -| `isDevice` | Boolean | — | -| `scheduleTime` | Date | 定时下发时间 | - -**`rule` 常用字段**(`TestTaskUnitBinding`)——「选哪些机器」 - -| 字段 | 类型 | 说明 | -|---|---|---| -| `testTaskUnitBindingRuleKey` | Integer | 绑定规则:1=ssn 2=sku 3=mo 4=model 5=project | -| `bindingRulePriority` | Integer | 优先级 | -| `entityPrimaryKeyList` | Array\ | ★ 选中的机器。**元素是 JSON 字符串,不是裸 UUID**,形如 `"{\"key\":\"\",\"value\":\"<机器名>\"}"` | - -**`model` 关键字段与文件挂载点**(`TestModelNode`,可递归) - -```jsonc -{ - "testModelUuid": "string", - "testModelVersionUuid": "string", - "testModelName": "string", - "nodeSequenceTypeKey": 1, // 1 串行 / 2 并行 - "children": [ - { - "testModelUuid": "string", - "testModelVersionUuid": "string", - "children": [], - - // ★★★ 驱动包文件挂在这里 ★★★ - "documentCopyDTOList": [ - { - "fileUuid": "★ 填 prepareTaskFile 返回的 fileUuid", - "documentName": "string", // 可选 - "documentVersionNo": "string" // 可选 - } - ] - } - ] -} -``` - -> **`documentCopyDTOList` 里下游实际只用 `fileUuid`**(做判重与建文档映射),其余字段可选。 -> 这与 §3.5 的链路说明一致。 - -**返回** ✅ / ⚠️ - -| 形态 | 内容 | 触发条件 | -|---|---|---| -| **纯文本** ✅ | `请输入当前登录人信息` | `creatorCode` 为空,**或** MIS→MBX 用户 ID 转换失败 | -| 异常 | `IllegalArgumentException: 任务请求体 requestBodyJson 不能为空` | `requestBodyJson` 为空 | -| **JSON** ⚠️ | 见下 | 正常调用 / 下游业务失败 | - -**成功返回**(下游 `R.ok(statusMap, "任务下发已提交,正在生成中")`,MCP 取出 `data`) - -```jsonc -{ - "offLineTestUnit": "uuid1,uuid2,", // 离线机器 uuid,逗号拼接、末尾带逗号 - "unWorkingTestUnit": "uuid3,", // 使用中机器 uuid,同上 - "testTaskUuid": "string", // ★ 新建任务唯一标识 - "testTaskCode": "string" // ★ 任务编号 -} -``` - -**失败返回**(MCP 同样按 B 类处理:`data` 为 null 时返回 `[]`) - -| 下游 `msg` | 含义 | -|---|---| -| `参数异常请检查` | ⚠️ 请求体为空。**下游这里返回的是 `code="0"`**,MCP 会当成成功路径处理,返回 `[]` —— 无法只靠 code 区分,需结合 `msg` | -| `任务定时下发时间需在当前时间之后,请重新设置!` | `scheduleTime` 早于当前时间 | -| `该任务含有禁用的用例关联版本,请修改重试!` | 用例关联版本被禁用 | -| `关联版本对应的绑定模型数据为空!` / `testCaseAssociationVersionUuid参数不得为空!` | 用例视图参数缺失 | -| `该任务含有不可用的原子模型,请修改重试!` | ⚠️ 此时下游 `code="26"`,`data` 是**列表** `[{deviceTypeKey, testUnitUuid, testUnitName}]`,MCP 会把该列表返回 | - -**注意事项** - -- ⚠️ **写操作**:会真实创建/下发任务,不可撤销。prompt 中应要求**先展示完整 `requestBodyJson` 给用户确认**再执行。 -- `fileUuid` **必须**来自 `prepareTaskFile`,不能用 `packageFileUrl` 顶替(§3.5)。 -- `creatorCode` 必须是**纯数字**的 MIS 用户 ID;非数字会走到「请输入当前登录人信息」分支,而不是报错——**prompt 需能识别这句纯文本并提示用户提供正确 ID**。 -- `other.type` 忘了传 → 下游 NPE(500),这是最常见的构造错误。 -- `fs=true` 会**跳过「机器未绑定设备类型」校验**并强制下发;默认 `false` 时该校验不过会返回 `code="26"`。 -- 参数名与下游路径都是 `creat...`(少一个 e),拼错会找不到工具。 - -**关联工具**:`prepareTaskFile`(上游,提供 `fileUuid`) - ---- - -### 3.8 `queryTestUnitListByProjectName` - -**摘要**:根据项目名称、五码查询机器列表的数据,按列表分页显示。 - -| 项 | 值 | -|---|---| -| 所属服务 | `mis-mcp-tool-vlab` | -| Java 方法 | `UnitService.queryTestUnitListByProjectName` | -| MCP 工具名 | `queryTestUnitListByProjectName` | -| 下游接口 | `GET {misVlabBaseUrl}/testUnit/qv/mcpvlabqueryTestPcList` | -| 返回裁剪 | **B 类:取 data(未做字段裁剪)** ⚠️ | - -**参数表** - -| 参数名 | 类型 | 必填 | 默认 | 说明 | 示例 | -|---|---|---|---|---|---| -| `projectName` | String | **是** | — | 项目名称 | `TNB Commercial OS Refresh-X_CS24` | -| `modelCode` | String | **是** | — | 五码 | `LT4EN` | -| `ownerCode` | String | **是** | — | 当前用户的 UUID(**MIS 用户 ID**,纯数字) | — | -| `current` | Long | 否 | `1` | 当前页码 | `1` | -| `size` | Long | 否 | `10` | 每页条数 | `10` | - -> **参数名与下游字段名不一致**:工具入参叫 `modelCode`(五码),传给下游时字段名是 **`modelName`**。调用方只需按 `modelCode` 传值。 - -**返回** ✅ / ⚠️ - -| 形态 | 内容 | 触发条件 | -|---|---|---| -| **纯文本** ✅ | `登录人信息转换异常` | `ownerCode` 有值但 MIS→MBX 转换失败 | -| 异常 | `IllegalArgumentException: 项目名称 projectName 不能为空` | `projectName` 为空 | -| **JSON** ⚠️ | 下游 `data`(含 `records` 时只取 `records`;`data` 为空返回 `[]`) | 正常调用 | - -**返回 JSON 结构** ⚠️ 透传(下游 `data` 是 MyBatis-Plus 分页对象,MCP 取出 `records`) - -```jsonc -[ - { - "testUnitUuid": "string", // ★ 测试机唯一标识 —— 给 queryTestPcByUuids 用 - "testUnitName": "string", // 机器名称 - "shippingSn": "string", // 出货流水号 / 机器 SSN - "onlineStatus": 2, // ★ 在线状态:1=离线 2=在线 - "workingStatusKey": 2, // 机器状态:1=闲置中 2=使用中 - "lockStatus": 0, // 锁定状态:0=未锁定 1=已锁定 - "tokenStatus": 0, // 认领状态 - "borrowStatus": 0, // 借用状态 - "isStore": 0, // 是否收藏:0/1 - "projectCode": "string", // 项目编号 - "projectName": "string", // 项目名称 - "projectPhase": "string", // 项目阶段 - "programName": "string", // 项目集名称 - "modelName": "string", // 五码 - "groupName": "string", // 分组名称 - "testUnitGroupUuid": "string", // 分组 uuid - "testUnitTypeKey": 0, // 测试机类型键 / 物料组 - "matterDescription": "string", // 物料描述 - "fgPn": "string", // SKU - "skuShortName": "string", // SKU 别名 - "skuExtensionNo": "string", // SKU 扩展序号 - "mbPn": "string", // 主板料号 - "mbSn": "string", // 主板流水号 - "fgSn": "string", // 整机流水号 - "gerberVersion": "string", // 主板 Gerber 版本 - "ipAddress": "string", // IP - "ipAddressBridge": "string", // 桥接 IP - "ownerCode": "string", // 机器管理员 - "ownerName": "string", // 管理员名称 - "userCode": 0, // 当前使用人编号 - "userName": "string", // 当前使用人名称 - "groupLeaderName": "string", // Smart FAI 组长姓名 - "groupLeaderCode": "string", // Smart FAI 组长工号 - "testUnitSource": "string", // 数据源:1=手工导入 2=开机注册 - "comments": "string", // 备注 - "gmtCreate": "yyyy-MM-dd HH:mm:ss", // 录入时间 - "mbUuid": "string", // 主板 uuid - - // 以下字段恒为 null(下游 SQL 未查出) - "mo": null, - "vncParam": null, - "lcfcUuid": null - } -] -``` - -**关键字段速查** - -| 字段 | 取值 | 说明 | -|---|---|---| -| `testUnitUuid` | — | 传给 `queryTestPcByUuids` | -| `onlineStatus` | `1` 离线 / `2` 在线 | 在线状态 | -| `workingStatusKey` | `1` 闲置中 / `2` 使用中 | 机器状态 | -| `lockStatus` | `0` 未锁定 / `1` 已锁定 | 锁定状态 | - -**注意事项** - -- 三个入参(`projectName` / `modelCode` / `ownerCode`)在源码中**都是必填**。 -- ⚠️ **`ownerCode` 不能留空**:MCP 允许它为空(不报错),但下游会直接返回 - `未获取到用户信息`(`code="1"`)→ MCP 抛异常。**必须传纯数字的 MIS 用户 ID。** -- ⚠️ **`modelCode`(五码)实际不生效**:已核实下游该查询语句的 WHERE 子句里 - **没有 `modelName` 过滤条件**,MCP 传过去的五码被**静默忽略**。 - 即实际过滤条件只有 `projectName`(+ 用户维度)。 - **prompt 不要声称「按五码精确筛选」**;若确需按五码收窄,应在拿到结果后**在模型侧自行过滤** `modelName` 字段。 -- 与已废弃的 `queryTestUnitList` 区分:**按项目查机器用本工具**(见 §6.3)。 - -**关联工具**:`queryTestPcByUuids`(下游,承接 `testUnitUuid`)、`debuggingProjectQuery`(提供 `modelCode` 五码) - ---- - -### 3.9 `queryTestPcByUuids` - -**摘要**:根据测试机 UUID 列表**批量**查询测试机在线状态信息。 - -| 项 | 值 | -|---|---| -| 所属服务 | `mis-mcp-tool-vlab` | -| Java 方法 | `TestUnitQvService.queryTestPcByUuids` | -| MCP 工具名 | `queryTestPcByUuids` | -| 下游接口 | `POST {misVlabBaseUrl}/testUnit/queryTestPcByUuids`,请求体 `{"testUnitUuids": [...]}` | -| 返回裁剪 | **B 类:取 data(未做字段裁剪)** ⚠️ | - -**参数表** - -| 参数名 | 类型 | 必填 | 默认 | 说明 | 示例 | -|---|---|---|---|---|---| -| `testUnitUuids` | Array\ | **是** | — | 测试机 UUID **列表**(**批量传入**,不要循环单传) | `["0062c70e645c4d0a824d8b2c3134015d"]` | - -**返回** ✅ / ⚠️ - -| 形态 | 内容 | 触发条件 | -|---|---|---| -| 异常 | `IllegalArgumentException: testUnitUuids 不能为空` | 入参为空列表或 null | -| **JSON** ⚠️ | 下游 `data` 本身就是一个**数组**(非分页) | 正常调用 | - -**返回 JSON 结构** ⚠️ 透传 - -> 与 §3.8 不同,本接口的 `data` **直接就是数组**(不是分页对象),无需再取 `records`。 - -```jsonc -[ - { - "testUnitUuid": "string", // 机器统一标识码 - "testUnitName": "string", // 机器名称 - "onlineStatusKey": 2, // ★★★ 在线状态:1=离线 2=在线 - "workingStatusKey": 2, // 机器状态:1=空闲 2=使用中 - "ownerCode": 0, // 所有者编号(数字) - "ownerName": "string", // 所有者名称 - "userCode": 0, // 使用者编号(数字) - "sortField": null, // 继承自 SortEntity,非查询用途 - "positiveOrReverse": null, - - // ❌ 陷阱:这个字段名很像在线状态,但本接口恒为 null - "onlineStatus": null, - - // 其余约 50 个字段(projectName / fgSn / lockStatus / gmtCreate …)也会出现,但恒为 null - "projectName": null, - "fgSn": null, - "lockStatus": null - } -] -``` - -> ### ⚠️ 最容易踩的坑:`onlineStatus` 是 null,要用 `onlineStatusKey` -> -> 下游 `Machines` 类里**同时存在**两个长得像在线状态的字段: -> - **`onlineStatusKey`** —— ✅ 本接口真正返回的在线状态(1 离线 / 2 在线) -> - `onlineStatus` —— ❌ 本接口的 SQL **没有查这一列**,恒为 `null` -> -> **prompt 里必须写 `onlineStatusKey`**。若写 `onlineStatus`,会拿到 `null` 并被误判成「离线/未知」。 - -**注意事项** - -- **批量语义**:一次传入多个 UUID,比逐个调用高效——prompt 里应显式要求**合并成一次调用**。 -- UUID 来源:`queryTestUnitListByProjectName` 返回的 `testUnitUuid`。 -- 空数组会**直接抛异常**,不会返回空结果。 -- 返回体很大(每台机器约 50+ 个恒 null 字段),**机器数量多时注意上下文占用**; - 建议 prompt 里只提取 `testUnitUuid` / `testUnitName` / `onlineStatusKey` 三个字段。 - -**关联工具**:`queryTestUnitListByProjectName`(上游,提供 `testUnitUuids`) - ---- - -## 4. 典型工作流(编排剧本) - -> 每条链路都给出**步骤 → 工具 → 参数来源 → 产出**,可直接转成 SKILL 的调用顺序。 - -### 4.1 驱动包下发测试任务(最长链路,5 步) - -| 步骤 | 工具 | 关键参数 | 取值来源 | 产出 | -|---|---|---|---|---| -| 1 | `queryProjectNameList` 或 `debuggingProjectQuery` | `projectName` / `creatorCode` | 用户输入 | `projectUuid` | -| 2 | `queryDriverListNamesByProject` | `projectUuid`(或 `projectGroupUuid`) | 步骤 1 | `driverListVersionUuid`、`driverListName` | -| 3 | `queryDriverListVersion` | `driverListVersionUuid` | 步骤 2 | `driverPackageVersionList[].packageFileUrl`(**非顶层字段**,见 §3.4) | -| 4 | `prepareTaskFile` | `fileUrl` = `packageFileUrl` | 步骤 3 | `fileUuid` ⏱ 耗时较长 | -| 5 | `creatOrSendTask` | `creatorCode`、`requestBodyJson`(含 `fileUuid`) | 步骤 4 + 用户输入 | 任务创建/下发结果 | - -**决策点**(prompt 里必须交代清楚): -- 步骤 2 若匹配到**多个** `driverListName` → **列出让用户选**,不要自选。 -- 步骤 4 耗时可能达数分钟 → 应提示用户。 -- 步骤 5 是**写操作**(会真实创建/下发任务)→ 建议**先展示完整 `requestBodyJson` 给用户确认**再执行。 - -### 4.2 Preload 更新链接(单步 + 自纠偏) - -| 步骤 | 工具 | 参数 | 产出 | -|---|---|---|---| -| 1 | `generatePreloadUpdateLink` | `project`(必填,页面下拉精确值)、`osVer`(可选) | `downloadUrl` | - -**失败分支**:返回 `success: false` 时,用 `availableProjects` / `availableOsVer` 让用户确认后再**重试一次**(见 §3.6)。 - -### 4.3 项目 → 测试机 → 在线状态(3 步) - -| 步骤 | 工具 | 关键参数 | 产出 | -|---|---|---|---| -| 1 | `debuggingProjectQuery` | `projectName` / `modelCode` | 项目信息(含五码 `modelCode`) | -| 2 | `queryTestUnitListByProjectName` | `projectName`、`modelCode`(五码)、`ownerCode` | 机器列表(含 `testUnitUuid`) | -| 3 | `queryTestPcByUuids` | `testUnitUuids` = 步骤 2 的 UUID 数组 | 在线状态 | - -> 步骤 2 的三个参数在源码中**均为必填**(未标 `required = false`)。`ownerCode` 传 MIS 用户 ID。 - ---- - -## 5. 生成 SKILL 与 Prompt 的指引 - -> 本节把上文的结构化信息转成**可直接抄用的模板**。 - -### 5.1 推荐的 SKILL 结构 - -```markdown ---- -name: se-driver-workflow # 建议按业务域命名,见下方 5.1.1 -description: > - 处理 SE 驱动的查询与测试任务下发。当用户提到「驱动列表」「Driver List」 - 「驱动包版本」「下发测试任务」「preload 更新链接」时使用。 - 覆盖 9 个 MCP 工具:项目查询、驱动列表查询、驱动包下载、文件准备、任务下发、 - Preload 链接生成、测试机查询。 ---- - -# 工具调用顺序(严格按此顺序,ID 逐跳传递) -1. queryProjectNameList / debuggingProjectQuery → 拿 projectUuid / 项目信息 -2. queryDriverListNamesByProject → 拿 driverListVersionUuid -3. queryDriverListVersion → 拿 packageFileUrl -4. prepareTaskFile → 拿 fileUuid(耗时较长) -5. creatOrSendTask → 下发任务 - -# 详细参数与返回结构 -见 `references/se工作流mcp工具API文档.md`(按需加载,不要一次性全读) -``` - -**5.1.1 SKILL 拆分建议**:按**链路**而非按工具拆,推荐 3 个: - -| SKILL 名(建议) | 覆盖工具 | 触发场景 | -|---|---|---| -| `se-driver-workflow` | ①~⑤ + ⑦(`debuggingProjectQuery`/`queryProjectNameList`/`queryDriverListNamesByProject`/`queryDriverListVersion`/`prepareTaskFile`/`creatOrSendTask`) | 驱动查询与任务下发 | -| `se-preload-link` | ⑥ `generatePreloadUpdateLink` | 生成 Preload 更新链接 | -| `se-test-unit-query` | ⑧⑨ `queryTestUnitListByProjectName`/`queryTestPcByUuids` | 测试机列表与在线状态 | - -### 5.2 工具 → 自然语言触发词 - -写 SKILL 的 `description` 时直接取用,能显著提高工具被正确选中的概率: - -| 工具 | 用户可能说的话 | -|---|---| -| `debuggingProjectQuery` | 「查一下 XX 项目」「XX 项目的五码/四码/负责人」「项目别名是 XX 的项目」 | -| `queryProjectNameList` | 「有哪些项目」「我能看到哪些项目」「项目名和 projectUuid」 | -| `queryDriverListNamesByProject` | 「XX 项目下的 Driver List」「这个项目组有哪些驱动列表」「驱动列表版本」 | -| `queryDriverListVersion` | 「这个驱动列表的包在哪下载」「驱动包的下载地址」 | -| `prepareTaskFile` | 「准备一下这个文件」「把驱动包传上去」 | -| `generatePreloadUpdateLink` | 「生成 preload 更新链接」「Preload 更新包的下载地址」 | -| `creatOrSendTask` | 「下发测试任务」「创建测试任务」「跑一下这个驱动」 | -| `queryTestUnitListByProjectName` | 「XX 项目有哪些机器」「五码 XX 的测试机」 | -| `queryTestPcByUuids` | 「这几台机器在线吗」「机器在线状态」 | - -### 5.3 编排 Prompt 模板 - -**模板 A:驱动包下发测试任务(最完整链路)** - -```text -目标:把「{项目名}」项目下「{驱动列表名匹配词}」的驱动包,下发测试任务。 - -请严格按顺序执行,每步只用上一步的返回结果,不要跳步或猜 ID: - -1. 调用 queryDriverListNamesByProject,参数 projectUuid = {projectUuid}(若只知道项目名, - 先用 queryProjectNameList 拿 projectUuid)。 - → 从返回数组中选出名称匹配「{驱动列表名匹配词}」的那条,记下它的 driverListVersionUuid。 - → 如果匹配到多条,先列出来问我要哪一个,不要自己选。 - -2. 调用 queryDriverListVersion,参数 driverListVersionUuid = 上一步的值。 - → 从返回中取出 packageFileUrl。 - -3. 调用 prepareTaskFile,参数 fileUrl = 上一步的 packageFileUrl。 - → 这一步会下载并重新上传驱动包,可能耗时数分钟,请告知我在处理中。 - → 取出返回的 fileUuid。 - -4. 调用 creatOrSendTask: - - creatorCode = {当前登录人 MIS 用户 ID} - - requestBodyJson = 见下方模板,把 fileUuid 填入 - model.children[].documentCopyDTOList[].fileUuid - - 执行前把完整 requestBodyJson 展示给我确认。 - -【重要】任何一步失败就停下来报告原因,不要用猜测的参数重试。 -``` - -**模板 B:Preload 更新链接** - -```text -帮我生成「{项目名}」的 preload 更新链接(OS VER 用 {9.Win11 / 不指定})。 - -调用 generatePreloadUpdateLink,参数 project = "{项目名}",osVer = "{osVer}"。 - -判断结果: -- 返回里有 downloadUrl → 成功,把链接给我。 -- 返回里有 "success": false → - · 若带 availableProjects,从里面挑最接近的候选,把候选列表给我确认后再重试一次; - · 若带 availableOsVer,同理。 - · 不要用同一个错值反复重试。 -``` - -**模板 C:测试机在线状态** - -```text -1. 调用 queryTestUnitListByProjectName: - projectName = "{项目名}",modelCode = "{五码}",ownerCode = "{当前登录人 MIS 用户 ID}" - → 从返回里取出各机器的 testUnitUuid。 -2. 调用 queryTestPcByUuids,testUnitUuids = 上一步的 UUID 数组(批量传入,不要一次一个)。 - → 汇总每台机器的在线状态给我。 -``` - -### 5.4 反模式(写 prompt 时明确禁止) - -| ❌ 不要这样写 | ✅ 应该这样写 | 原因 | -|---|---|---| -| 让模型「猜」或「编」`projectUuid` / `driverListVersionUuid` 等 UUID | 强制从上一个工具的返回中取值 | UUID 无法凭空生成,编造必然查不到 | -| 用 `queryProjectNameList` 取超过 100 条项目 | 用 `debuggingProjectQuery` 检索项目 | 前者单页最多 100 条且无分页参数(§3.2) | -| 把 `packageFileUrl` 直接填进 `creatOrSendTask` | 先过 `prepareTaskFile` 换成 `fileUuid` | 任务下发只认 `fileUuid`(§3.5) | -| 写「取返回的 `packageFileUrl`」 | 写「取 `driverPackageVersionList[].packageFileUrl`」 | 它不是顶层字段(§3.4) | -| 用 `onlineStatus` 判断测试机在线状态 | 用 `onlineStatusKey` | `onlineStatus` 恒为 null(§3.9) | -| 声称 `queryTestUnitListByProjectName` 按五码筛选 | 说明只按项目名筛选,五码需自行过滤 | 下游忽略 `modelName`(§3.8) | -| 让模型自行拼 `other.type` 等必填项 | 在 prompt 里给出完整请求体模板 | 漏传必填项会 500(§3.7) | -| 用 `success === true` 判断 Preload 成功 | 判断 `downloadUrl` 是否存在 / `success === false` | 成功返回里没有 `success` 字段(§3.6) | -| 对 `generatePreloadUpdateLink` 传模糊项目名 | 传 Preload 页面下拉里的**精确**值 | 该工具是精确匹配,不匹配会返回失败对象(§3.6) | -| 假设返回一定是 JSON | 先看首字符:`请`/`登` 开头是纯文本提示 | 两个工具会返回**纯文本**(§2.4) | -| 一次性读取整份 API 文档 | 按需加载对应工具小节 | 文档较长,全量加载浪费上下文 | - ---- - -## 6. 附录 - -### 6.1 MCP 接入信息 - -| 服务 | 端口 | `protocol` | 配置来源 | 工具数(本工作流涉及) | -|---|---|---|---|---| -| `mis-mcp-tool-debugging` | 18780 | `STATELESS` | 仓库 `application.yml` | 1 | -| `mis-mcp-tool-driver` | 18767 | `STATELESS` | 仓库 `application.yml` | 4 | -| `mis-mcp-tool-vlab` | 18769 | `STREAMABLE`(`mcp-endpoint: /mcp`) | **Nacos**(仓库内无此配置) | 4 | - -> ⚠️ **鉴权由 MCP 客户端透传**:调用方(LLM 侧)**不需要**把 token 作为工具参数传入。 -> 凭证走 MCP 请求头 `auth` / `clientid`,由服务端 `MisAuthForestInterceptor` 注入下游。 -> 排查「工具连不上」时,别只看仓库代码——`vlab` 的协议配置**不在代码里**,在 Nacos。 - -### 6.2 下游接口与白名单对照 - -下列路径**必须**存在于对应服务的 Nacos `security.oauth2.client.ignore-urls`(MBX 侧)或网关 `ignore.whites`(MIS 侧), -否则工具上线后必然 **401 / 403**。 - -| # | 工具 | 下游路径 | 下游服务 | 白名单位置 | 快照核对 | -|---|---|---|---|---|---| -| 1 | `debuggingProjectQuery` | `/debugging/project` | `mis-debugging` | **MIS 网关** `mis-gateway.yml` → `ignore.whites` | ✅ 已存在 | -| 2 | `queryProjectNameList` | `/project/mcpvlabpage` | `mbv-service-business` | `mbv-service-business-dev.yml` | ✅ 已存在 | -| 3 | `queryDriverListNamesByProject` | `/driverlist/mcpvlabpage` | `mbx-service-driver` | `mbx-service-driver-dev.yml` | ✅ 已存在 | -| 4 | `queryDriverListVersion` | `/listversion/mcpvlab/*` | `mbx-service-driver` | 同上 | ✅ 已存在 | -| 5 | `prepareTaskFile` | `/mbvClient/downloadFile`、`/uploadFileSpecial` | `mbv-service-minio` | `mbv-service-minio-dev.yml` | ✅ 已存在 | -| 6 | `generatePreloadUpdateLink` | `/preload/preloadNameList`、`/preload/init`、`/preload/select`、`/preload/getOtherList`、`/preload/preloadVersion`、`/aod` | `mbv-service-preload` | `mbv-service-preload-dev.yml` | ✅ 已存在(6 条齐全) | -| 7 | `creatOrSendTask` | `/mcpvlabcreatOrSendTask` | `mbv-service-dispatcher` | `mbv-service-dispatcher-dev.yml` | ✅ 已存在 | -| 8 | `queryTestUnitListByProjectName` | `/testUnit/qv/mcpvlabqueryTestPcList` | `mbv-service-business` | `mbv-service-business-dev.yml` | ✅ 已存在 | -| 9 | `queryTestPcByUuids` | `/testUnit/queryTestPcByUuids` | `mbv-service-business` | 同上 | ✅ 已存在 | - -> **路径参数写 `*` 不写 `{}`**(如 `/listversion/mcpvlab/*`)。 -> **本节结论基于本地 Nacos 快照**(`docs/nacos/`),快照是导出副本、**随时可能过期**, -> 上线前请以**远程 Nacos 实际值**为准。快照文件名是 `*-dev.yml` 但装的是 **qas** 环境的值。 - -### 6.3 易混淆 / 已废弃工具 - -| 工具 | 状态 | 说明 | -|---|---|---| -| `queryTestUnitList` | ⚠️ **已废弃**(源码 javadoc 明确标注「废弃」,但 `@Tool` 注解**未摘除**,仍会暴露给模型) | 参数多且语义宽泛,**不要**在新的 SKILL / prompt 里使用;按项目查机器请用 `queryTestUnitListByProjectName`,按 UUID 批量查用 `queryTestPcByUuids` | -| `debuggingProjectQuery` | 命名特殊 | 源码用 `@Tool(name = ...)` 显式指定,**Java 方法名是 `queryProjectList`**,两者不同名;调用时用 `debuggingProjectQuery` | -| `creatOrSendTask` | 拼写特殊 | 是 `creat` 不是 `create`,**必须原样使用** | -| `queryProjectNameList` vs `debuggingProjectQuery` | 数据源不同 | 前者查 MBX 侧,后者查 SE 同步侧;`name` 值对应(§1.3) | - -### 6.4 高风险陷阱汇总(写 prompt 前必读) - -> 以下每一条都来自**源码逐行核对**,都是「照直觉写就会错」的地方。 - -| # | 陷阱 | 正确做法 | 出处 | -|---|---|---|---| -| 1 | 以为 `queryDriverListVersion` 顶层有 `packageFileUrl` | 取 **`driverPackageVersionList[].packageFileUrl`**(或 `solidifiedDriverPackageVersionList[]`) | §3.4 | -| 2 | 用 `onlineStatus` 判断测试机在线状态 | 用 **`onlineStatusKey`**(`onlineStatus` 恒为 null) | §3.9 | -| 3 | 以为 `queryTestUnitListByProjectName` 会按五码筛选 | **`modelCode` 被下游静默忽略**;只按 `projectName` 过滤,需要五码请自行在结果里过滤 `modelName` | §3.8 | -| 4 | 给 `queryTestUnitListByProjectName` 传空 `ownerCode` | **必须传纯数字 MIS 用户 ID**,否则下游报「未获取到用户信息」 | §3.8 | -| 5 | 用 `success === true` 判断 Preload 成功 | 判断 **`downloadUrl` 是否存在** / `success === false`(成功返回里**没有** `success` 字段) | §3.6 | -| 6 | `creatOrSendTask` 漏传 `other.type` | **必须传**(`1` 只保存 / `2` 创建并下发),否则下游 NPE 500 | §3.7 | -| 7 | 把 `creatOrSendTask` 的空请求体当成失败 | 该场景下游返回 **`code="0"` + `msg="参数异常请检查"`**,是**假成功**,需结合 `msg` 判断 | §3.7 | -| 8 | 用 `queryProjectNameList` 拉取超过 100 条项目 | 它**单页最多 100 条且无分页**;项目检索用 `debuggingProjectQuery` | §3.2 | -| 9 | 假设返回值一定是 JSON | 两个工具会返回**纯文本**(`请输入当前登录人信息` / `登录人信息转换异常`) | §2.4 | -| 10 | 把 `packageFileUrl` 直接填进 `creatOrSendTask` | 必须先过 `prepareTaskFile` 换成 `fileUuid` | §3.5 | -| 11 | 把 `creatOrSendTask` 当只读查询 | 它是**写操作**,prompt 应先展示请求体让用户确认 | §3.7 | - -### 6.5 残留不确定项 - -> 以下是本次核对**未能完全确证**的部分,不要在这些细节上做硬编码假设。 - -| # | 事项 | 状态 | 建议 | -|---|---|---|---| -| 1 | `debuggingProjectQuery` 返回的 `projectUuid` 是 number 还是 string | 下游类型为 `Long`,且全局注册了 `BigNumberSerializer`(值超 2^53-1 时输出**字符串**)。源码示例值 `2049298006288687105` 是 19 位雪花 ID → **实际应为字符串**;小 ID 历史数据可能为数字 | 统一**按字符串处理**(比较前归一) | -| 2 | MyBatis-Plus `Page` 序列化出的完整字段集 | 仅实锤 `records` / `total`(前端代码印证);`size`/`current`/`pages`/`orders` 等为框架常规字段,**未从 jar 逐项确认** | 只依赖 `records` / `total` | -| 3 | 下游抛 `RuntimeException`(如「生成任务编号失败」)经全局异常处理后的 JSON 结构 | **未确认** | 按 MCP 抛异常处理即可 | -| 4 | `queryTestUnitListByProjectName` 的 `machineListType` 分支 | MCP 不传该参数,走默认 SQL;另两条分支 SQL 未逐条核对 | 无需关注 | -| 5 | `debuggingProjectQuery` 的 `ppmQuery` 字段 | **已核实**:恒为 `null`(只作查询条件,不进结果映射) | 不要从返回值读它 | -| 6 | 值为 `null` 的字段是否会**整键消失** | **已核对**:下游无 `spring.jackson.*` 配置,MIS 共享配置 `application-common.yml` 未设 `default-property-inclusion` → **null 字段会原样输出** | 字段存在,判空即可 | - -> **另需注意**:`mbv-service-test-unit` 模块里存在一份**同名**的 `/testUnit/queryTestPcByUuids` 实现, -> 但网关 `/business` 前缀落到的是 **`mbv-service-business`**,以本文档结论为准。 - ---- - -**文档结束** · 生成于 2026-09-22 · 基线 `mis-mcp-server@dev` - diff --git a/v260921.md b/v260921.md deleted file mode 100644 index ae5666b..0000000 --- a/v260921.md +++ /dev/null @@ -1,203 +0,0 @@ -# 服务 - -| 服务名称 | 分支 | 描述 | -| --- | --- | --- | -| mis-paw | dev_lab | 用户添加Agent到个人中心(添加次数+1)| -| mis-tool-server | dev_lab | MCP、Skill、Agent 数据统计 | - -## SQL脚本 - -### 新建的表 - -```sql -DROP TABLE `mis-mcp-paw-claw`.`user_resource_operate_record` -DROP TABLE `mis-mcp-paw-claw`.`resource_operate_count`; -DROP TABLE `mis-mcp-paw-claw`.`user_resource_comment`; -DROP TABLE `mis-cloud-claw`.`client_software`; -DROP TABLE `mis-cloud-claw`.`client_software_canary_settings`; -DROP TABLE `mis-paw-claw`.`work_sheet`; -``` - -```sql -CREATE TABLE `mis-mcp-paw-claw`.`resource_operate_count` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT 'id', - `tag` VARCHAR(32) DEFAULT NULL COMMENT '资源类型(agent=智能体、skill=技能、mcp_server=MCP服务)', - `resource_id` VARCHAR(255) DEFAULT NULL COMMENT '资源ID(Agent=智能体ID、Skill=skillId、MCP=mcpServerUuid)', - `like_count` BIGINT DEFAULT '0' COMMENT '点赞次数', - `comment_count` BIGINT DEFAULT '0' COMMENT '评论次数', - `personal_space_add_count` BIGINT DEFAULT '0' COMMENT '被添加到个人中心的次数', - `create_time` DATETIME DEFAULT NULL COMMENT '创建时间', - `update_time` DATETIME DEFAULT NULL COMMENT '最近更新时间', - `create_at` VARCHAR(255) DEFAULT NULL COMMENT '创建人', - `update_at` VARCHAR(255) DEFAULT NULL COMMENT '最近更新人', - `delete_flag` VARCHAR(8) DEFAULT '0' COMMENT '删除标识(0=未删除,2=已删除)', - PRIMARY KEY (`id`), - KEY(`resource_id`), - UNIQUE KEY(`tag`, `resource_id`) -) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = '资源的操作统计'; - -CREATE TABLE `mis-mcp-paw-claw`.`user_resource_comment` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT 'id', - `tag` VARCHAR(32) DEFAULT NULL COMMENT '资源类型(agent=智能体、skill=技能、mcp_server=MCP服务)', - `resource_id` VARCHAR(255) DEFAULT NULL COMMENT '资源ID(Agent=智能体ID、Skill=skillId、MCP=mcpServerUuid)', - `user_id` VARCHAR(255) DEFAULT NULL COMMENT '用户ID', - `comment` VARCHAR(500) DEFAULT NULL COMMENT '评论内容', - `star` INT DEFAULT '0' COMMENT '评分星级(1~5)', - `create_time` DATETIME DEFAULT NULL COMMENT '创建时间', - `update_time` DATETIME DEFAULT NULL COMMENT '最近更新时间', - `create_at` VARCHAR(255) DEFAULT NULL COMMENT '创建人', - `update_at` VARCHAR(255) DEFAULT NULL COMMENT '最近更新人', - `delete_flag` VARCHAR(8) DEFAULT '0' COMMENT '删除标识(0=未删除,2=已删除)', - PRIMARY KEY (`id`), - KEY(`resource_id`), - KEY(`user_id`) -) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = '用户对资源的评论'; - -CREATE TABLE `mis-mcp-paw-claw`.`user_resource_operate_record` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT 'id', - `tag` VARCHAR(32) DEFAULT NULL COMMENT '资源类型(agent=智能体、skill=技能、mcp_server=MCP服务)', - `resource_id` VARCHAR(255) DEFAULT NULL COMMENT '资源ID(Agent=智能体ID、Skill=skillId、MCP=mcpServerUuid)', - `user_id` VARCHAR(255) DEFAULT NULL COMMENT '用户ID', - `click_like` VARCHAR(8) DEFAULT NULL COMMENT '是否点过赞(yes=是、no=否)', - `click_like_time` DATETIME DEFAULT NULL COMMENT '点赞时间', - `withdraw_like` VARCHAR(8) DEFAULT NULL COMMENT '是否取消点赞(yes=是、no=否)', - `withdraw_like_time` DATETIME DEFAULT NULL COMMENT '取消点赞时间', - `create_time` DATETIME DEFAULT NULL COMMENT '创建时间', - `update_time` DATETIME DEFAULT NULL COMMENT '最近更新时间', - `create_at` VARCHAR(255) DEFAULT NULL COMMENT '创建人', - `update_at` VARCHAR(255) DEFAULT NULL COMMENT '最近更新人', - `delete_flag` VARCHAR(8) DEFAULT '0' COMMENT '删除标识(0=未删除,2=已删除)', - PRIMARY KEY (`id`), - KEY(`resource_id`), - UNIQUE KEY(`tag`, `resource_id`, `user_id`) -) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = '用户在个人空间对资源的操作记录'; - -CREATE TABLE `mis-cloud-claw`.`client_software` ( - `id` BIGINT NOT NULL COMMENT 'ID', - `identity` VARCHAR(255) NOT NULL COMMENT '客户端标识', - `state` VARCHAR(50) NOT NULL COMMENT '状态', - `version_no` VARCHAR(50) NOT NULL COMMENT '版本号', - `release_notes` TEXT COMMENT '更新内容', - `release_time` DATETIME COMMENT '发布时间', - `package_oss_id` BIGINT COMMENT '安装包 OSS ID', - `package_name` VARCHAR(255) COMMENT '安装包文件名', - `package_size` BIGINT COMMENT '安装包大小(字节)', - `create_time` DATETIME COMMENT '创建时间', - `update_time` DATETIME COMMENT '最近更新时间', - `create_at` VARCHAR(100) COMMENT '创建人', - `update_at` VARCHAR(100) COMMENT '最近更新人', - `delete_flag` CHAR(1) DEFAULT '0' COMMENT '删除标识:0=未删除(其他数值视为删除)', - PRIMARY KEY (`id`), - KEY idx_identity(`identity`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户端软件表'; - -CREATE TABLE `mis-cloud-claw`.`client_software_canary_settings` ( - `id` BIGINT NOT NULL COMMENT 'ID', - `identity` VARCHAR(255) NOT NULL COMMENT '客户端标识', - `dept_ids` JSON COMMENT '部门ID列表', - `user_ids` JSON COMMENT '用户ID列表', - `create_time` DATETIME COMMENT '创建时间', - `update_time` DATETIME COMMENT '最近更新时间', - `create_at` VARCHAR(100) COMMENT '创建人', - `update_at` VARCHAR(100) COMMENT '最近更新人', - `delete_flag` CHAR(1) DEFAULT '0' COMMENT '删除标识:0=未删除(其他数值视为删除)', - PRIMARY KEY (`id`), - KEY idx_identity(`identity`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户端软件包测试版配置表'; - -CREATE TABLE `mis-paw-claw`.`work_sheet` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT 'ID', - `system_code` VARCHAR(64) NOT NULL COMMENT '系统编码', - `work_code` VARCHAR(512) NOT NULL COMMENT '工单编码', - `current_try_times` INT NOT NULL COMMENT '当前是第几次重试', - `max_try_times` INT NOT NULL COMMENT '最多重试多少次', - `task_id` VARCHAR(512) NOT NULL COMMENT '追踪标识(traceId、业务标识、时间戳等)', - `state` VARCHAR(32) NOT NULL COMMENT '状态:wait-待执行,error-失败,success-成功', - `json_param` JSON NULL COMMENT '请求参数(JSON格式)', - `str_param` VARCHAR(512) NULL COMMENT '请求参数(简单字符串)', - `response_param` LONGTEXT NULL COMMENT '响应参数', - `error` LONGTEXT NULL COMMENT '错误信息', - `create_time` DATETIME NOT NULL COMMENT '创建时间', - `start_time` DATETIME NULL COMMENT '执行开始时间', - `finish_time` DATETIME NULL COMMENT '执行结束时间', - PRIMARY KEY (`id`), - KEY idx_task_id(`task_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='工单表'; -``` - -### 扩字段 - -```sql -ALTER TABLE `mis-paw-claw`.`agent` -ADD COLUMN `available` VARCHAR(8) DEFAULT 'yes' COMMENT '是否可用(yes=启用,no=禁用)'; - -ALTER TABLE `mis-paw-claw`.`agent_skill_mapping` - ADD COLUMN `skill_id` BIGINT NULL COMMENT '技能ID(调试版)' AFTER `agent_id`; - -ALTER TABLE `mis-paw-claw`.`agent_skill_mapping` MODIFY `skill_release_id` BIGINT NULL COMMENT 'tool-server skill_release 主键(正式版)'; -``` - -### 数据初始化 - -```sql --- 初始化智能体被添加次数 -INSERT INTO `mis-mcp-paw-claw`.`resource_operate_count`(`tag`, `resource_id`, `like_count`, `comment_count`, `personal_space_add_count`, `create_time`, `update_time`, `create_at`, `update_at`, `delete_flag`) -VALUES -SELECT 'agent', `parent_agent_id`, 0, 0, count(`agent_id`), now(), now(), 'admin', 'admin', '0' -FROM `mis-paw-claw`.`agent` -WHERE `del_flag` = '0' AND `version_lane` = 'PUBLISHED' -GROUP BY `parent_agent_id`; - --- 初始化MCP被添加次数 -INSERT INTO `mis-mcp-paw-claw`.`resource_operate_count`(`tag`, `resource_id`, `like_count`, `comment_count`, `personal_space_add_count`, `create_time`, `update_time`, `create_at`, `update_at`, `delete_flag`) -VALUES -SELECT 'mcp_server', `mcp_server_uuid`, 0, 0, count(`mcp_square_pull_record_id`), now(), now(), 'admin', 'admin', '0' -FROM `mis-mcp-paw-claw`.`mcp_square_pull_record` -WHERE `use_state` = 3 -GROUP BY `mcp_server_uuid`; - --- 初始化Skill被添加次数 -INSERT INTO `mis-mcp-paw-claw`.`resource_operate_count`(`tag`, `resource_id`, `like_count`, `comment_count`, `personal_space_add_count`, `create_time`, `update_time`, `create_at`, `update_at`, `delete_flag`) -VALUES -SELECT 'skill', `skill_release_id`, 0, 0, count(`skill_square_pull_record_id`), now(), now(), 'admin', 'admin', '0' -FROM `mis-mcp-paw-claw`.`skill_square_pull_record` -WHERE `use_state` = 3 -GROUP BY `skill_release_id`; - --- 初始化 skill_id -UPDATE `mis-paw-claw`.`agent_skill_mapping` AS asm -INNER JOIN `mis-mcp-paw-claw`.`skill_release` AS sr - ON sr.`skill_release_id` = asm.`skill_release_id` -SET asm.`skill_id` = sr.`skill_id` -WHERE sr.`del_flag` = '0' - AND asm.`del_flag` = '0' - AND asm.`skill_release_id` IS NOT NULL - AND sr.`skill_id` IS NOT NULL; -``` - -### 数据迁移 - -```sql -CREATE TABLE `mis-cloud-claw`.`server_client_release` ( - `release_id` BIGINT NOT NULL COMMENT '主键', - `version_no` VARCHAR(64) NOT NULL COMMENT '版本号,如 1.0.0', - `release_time` DATETIME NOT NULL COMMENT '发布时间', - `release_notes` TEXT COMMENT '更新内容', - `download_url` VARCHAR(1024) COMMENT '外部下载地址;上传包时可为空,由 oss 预签名生成', - `package_oss_id` BIGINT COMMENT '客户端安装包 ossId', - `package_name` VARCHAR(255) COMMENT '安装包原始文件名', - `package_size` BIGINT COMMENT '安装包大小(字节)', - `create_by` BIGINT, - `create_dept` BIGINT, - `create_time` DATETIME, - `update_by` BIGINT, - `update_time` DATETIME, - `del_flag` CHAR(1) NOT NULL DEFAULT 0, - PRIMARY KEY (`release_id`), - INDEX `idx_release_time` (`release_time`) -) ENGINE=InnoDB COMMENT='Server客户端版本发布'; - --- 同步版本数据 -INSERT INTO `mis-cloud-claw`.`server_client_release` -SELECT * FROM `mis-paw-claw`.`server_client_release`; -``` \ No newline at end of file diff --git a/v260930.md b/v260930.md deleted file mode 100644 index 98bd7eb..0000000 --- a/v260930.md +++ /dev/null @@ -1,118 +0,0 @@ -# 服务 - -| 服务名称 | 分支 | 描述 | -| --- | --- | --- | -| mis-debugging | qas_liushuang | SE智能体 | - -## 新建的表 - -```sql -CREATE TABLE `work_sheet` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT 'ID', - `system_code` VARCHAR(64) NOT NULL COMMENT '系统编码', - `work_code` VARCHAR(512) NOT NULL COMMENT '工单编码', - `current_try_times` INT NOT NULL COMMENT '当前是第几次重试', - `max_try_times` INT NOT NULL COMMENT '最多重试多少次', - `task_id` VARCHAR(512) NOT NULL COMMENT '追踪标识(traceId、业务标识、时间戳等)', - `state` VARCHAR(32) NOT NULL COMMENT '状态:wait-待执行,error-失败,success-成功', - `json_param` JSON NULL COMMENT '请求参数(JSON格式)', - `str_param` VARCHAR(512) NULL COMMENT '请求参数(简单字符串)', - `response_param` LONGTEXT NULL COMMENT '响应参数', - `error` LONGTEXT NULL COMMENT '错误信息', - `create_time` DATETIME NOT NULL COMMENT '创建时间', - `start_time` DATETIME NULL COMMENT '执行开始时间', - `finish_time` DATETIME NULL COMMENT '执行结束时间', - PRIMARY KEY (`id`), - KEY idx_task_id(`task_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='工单表'; - -CREATE TABLE `se_agent_session` ( - `id` BIGINT NOT NULL COMMENT '主键ID', - `create_time` DATETIME NOT NULL COMMENT '创建时间', - `create_at` VARCHAR(64) NOT NULL COMMENT '创建人', - `del_flag` VARCHAR(1) NOT NULL DEFAULT '0' COMMENT '删除标识 0=未删除 2=已删除', - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='SeAgent会话表'; - -CREATE TABLE `se_agent_chat_message` ( - `id` BIGINT NOT NULL COMMENT '主键ID', - `session_id` BIGINT NOT NULL COMMENT '会话ID', - `message_type` VARCHAR(16) NOT NULL COMMENT '消息类型 USER=用户输入 AGENT=智能体输出', - `message` LONGTEXT NOT NULL COMMENT '消息内容', - `context` JSON NULL COMMENT '扩展上下文信息(JSON)', - `create_time` DATETIME NOT NULL COMMENT '创建时间', - `create_at` VARCHAR(64) NOT NULL COMMENT '创建者', - `del_flag` VARCHAR(1) NOT NULL DEFAULT '0' COMMENT '删除标识 0=未删除 2=已删除', - PRIMARY KEY (`id`), - INDEX `idx_session_id` (`session_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='SeAgent聊天消息表'; -``` - -## Nacos - -- se-agent.yaml -- se-agent-system-prompt.txt - -## 主智能体选子智能体的系统提示词 - -```text -# 角色 - -你叫软件工程师,人们通常称呼你为SE智能体,SE取自"Software Engineer"英文缩写。经过3轮MBTI测试,你的人格类型均为INTJ。 -你最大的优点是沉着、冷静、一丝不苟、循规蹈矩,这也是人们喜欢你的原因。 -你的唯一目标是根据用户的问题,选一个子智能体,输出子智能体的名称。 -当用户的输入不符合任何子智能体的职责时,回复"defaultSubagent"即可。 - -## 输出契约 - -你只需要输出子智能体的名称,你不用过度思考、不用解释原因,仅输出子智能体的名称。 - -## 子智能体 - -|智能体名称|职责| -|---|---| -|SE_Debug|提供相似issue匹配、log解析、DIKW相关建议,在任务执行过程中遇到异常,请由工程师来决定如何执行。| -|SE_Taskexec|提供任务执行相关能力,下发任务到测试机。| -|SE_PPM|提供初始issue分配建议、issue数据统计分析的能力,在任务执行过程中遇到异常,请由工程师来决定如何执行。| -|SE_Dataquery|提供vLAB系统、Driver系统、SE管理系统的数据查询服务| -|SE_KnowledgeSearch|提供笔记本电脑测试、调试的知识问答服务,通过用户提供的简单自然语言描述,快速定位相关知识文档,提供清晰的排查步骤与修复方案等相关知识。| - -## 参考示例 - -|用户的问题|输出| -|执行stress测试|SE_Taskexec| -|提供issue解决建议|SE_Debug| -|提供issue分配建议|SE_PPM| -|查询Debug测试流程|SE_KnowledgeSearch| -|更新Driver|SE_Taskexec| -|执行Preload|SE_Taskexec| -``` - -## 集成Harness(废案) - -### 新建的表 - -从`agentscope-java`源码提取而来。 - -```sql -CREATE TABLE IF NOT EXISTS agent_skill ( - id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - name VARCHAR(255) NOT NULL UNIQUE, - description TEXT NOT NULL, - skill_content LONGTEXT NOT NULL, - source VARCHAR(255) NOT NULL, - metadata_json LONGTEXT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - -CREATE TABLE IF NOT EXISTS agent_skill_resource ( - id BIGINT NOT NULL, - resource_path VARCHAR(500) NOT NULL, - resource_content LONGTEXT NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (id, resource_path), - FOREIGN KEY (id) REFERENCES agent_skill (id) ON DELETE CASCADE -) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -``` \ No newline at end of file