Compare commits
38 Commits
87ca40fcd7
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| eee6640952 | |||
| 37ebd8715f | |||
| 55d8ed8e28 | |||
| c3dc494f2d | |||
| 3c0a740e91 | |||
| de02fa7817 | |||
| d3215e4fdc | |||
| 0aa670000c | |||
| 304250da43 | |||
| 27e90e99ee | |||
| 205c6870ca | |||
| 0703252426 | |||
| 17ba3dc05b | |||
| 05138c0496 | |||
| 1b365cf7eb | |||
| ece21f7113 | |||
| c1e81b207a | |||
| b4f1e2ce95 | |||
| 2a728f8935 | |||
| 17102203f8 | |||
| 9c36f5f9d5 | |||
| 9d61ae3d4e | |||
| dc8a8e079d | |||
| 8dfb3f20d0 | |||
| 62251ec879 | |||
| cb22feda71 | |||
| 560cd88572 | |||
| 98a80854d7 | |||
| 18f77a28ed | |||
| 460dbf34c7 | |||
| 799eea0698 | |||
| 2f42f825cf | |||
| d3fe5f1dab | |||
| ff62144fcc | |||
| 8ba9d13166 | |||
| 8d060f5c6e | |||
| 73434c778a | |||
| 6fcd9b2cd7 |
+887
@@ -0,0 +1,887 @@
|
||||
# 数据统计
|
||||
|
||||
以下是关于数据统计的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": "<p>更新日志</p>",
|
||||
"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": "<p>更新日志</p>",
|
||||
"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": "<p>修复bug</p>",
|
||||
"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": "<p>修复bug</p>",
|
||||
"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": "错误信息"
|
||||
}
|
||||
```
|
||||
@@ -1,93 +0,0 @@
|
||||
# Intro
|
||||
|
||||
分析 agentscope、agentscope-java 对于容器沙箱的支持。
|
||||
|
||||
## 支持的沙箱类型
|
||||
|
||||
| 沙箱类型 | agentscope | agentscope-java |
|
||||
| --- | --- | --- |
|
||||
| Docker | ✅ `DockerWorkspace` | ✅ `DockerFilesystemSpec` |
|
||||
| Kubernetes | ✅ `K8sWorkspace`| ✅ `KubernetesFilesystemSpec` |
|
||||
| E2B | ✅ `E2BWorkspace` | ✅ `E2bFilesystemSpec` |
|
||||
| Daytona | ✅ `DaytonaWorkspace` | ✅ `DaytonaFilesystemSpec` |
|
||||
| AgentRun | ❌ | ✅ `AgentRunFilesystemSpec` |
|
||||
| OpenSandbox | ✅ `OpenSandboxWorkspace` | ❌ |
|
||||
| Bubblewrap | ✅(依赖操作系统) | ❌ |
|
||||
|
||||
## 架构对比
|
||||
|
||||
### agentscope
|
||||
|
||||
Workspace + Backend + Gateway
|
||||
|
||||
```
|
||||
WorkspaceManager (服务侧缓存 / TTL / IsolationPolicy)
|
||||
│
|
||||
▼
|
||||
SandboxedWorkspaceBase.initialize()
|
||||
├─ _provision_backend() ← Docker/E2B/K8s/Daytona/OpenSandbox 各实现
|
||||
├─ _ensure_workspace_layout() (/workspace、skills、sessions、data、.mcp)
|
||||
└─ _setup_mcp_gateway() ← 容器内 FastAPI MCP Gateway
|
||||
│
|
||||
▼
|
||||
BackendBase (exec_shell / read_file / write_file)
|
||||
└─ 内置工具 Bash/Read/Write/Edit/Grep/Glob 透明落到沙箱内
|
||||
```
|
||||
|
||||
关键设计:通过 MCP 网关收敛文件系统相关 tool 的访问,采用空闲 TTL 驱逐的方案释放沙箱资源。
|
||||
|
||||
### agentscope-java
|
||||
|
||||
Filesystem Spec + SandboxManager
|
||||
|
||||
```
|
||||
HarnessAgent.Builder.filesystem(DockerFilesystemSpec / …)
|
||||
│
|
||||
▼
|
||||
SandboxFilesystemSpec.toSandboxContext(hostWorkspaceRoot)
|
||||
└─ SandboxContext(client, options, snapshotSpec, workspaceSpec, isolationScope)
|
||||
│
|
||||
▼
|
||||
SandboxLifecycleHook
|
||||
PreCall → SandboxManager.acquire → Sandbox.start()
|
||||
PostCall → Sandbox.stop() (tar 快照) → persist state → release
|
||||
│
|
||||
▼
|
||||
SandboxBackedFilesystem + ShellExecuteTool
|
||||
└─ 文件工具 / execute
|
||||
```
|
||||
|
||||
关键设计:在ReAct生命周期内,通过 hook 机制(2.0版本叫中间件)start、stop 沙箱。
|
||||
|
||||
## Docker沙箱双端对照表
|
||||
|
||||
| 对比项 | agentscope | agentscope-java |
|
||||
| --- | --- | --- |
|
||||
| API 形态 | Docker Engine API | CLI |
|
||||
| 保活命令 | `sleep infinity` | `while :; do sleep 3600; done` |
|
||||
| 镜像策略 | all-in-one镜像,自动构建并内容哈希缓存 | 用户指定 |
|
||||
| 默认网络 | Docker 默认| 用户指定 |
|
||||
| 持久化 | Bind-mount(可选) | Tar 快照为主 + 可选 bind-mount |
|
||||
| 生命周期 | Workspace 长生命周期 | 按 Agent `call` 借还 |
|
||||
| MCP | 容器内 Gateway | Harness 侧注册;沙箱只做 FS/Shell |
|
||||
| 资源限制 | 较弱(构造参数少) | memory / cpu / ports / network |
|
||||
| 水平扩展 | 不适合 | 需外置快照/状态存储 |
|
||||
|
||||
### 优点
|
||||
|
||||
- agentscope:
|
||||
- 通过 HTTP API 与 Docker 引擎交互,除了与本机 Docker 引擎交互之外,还可以访问远程服务器上的 Docker 引擎。
|
||||
- 自动构建镜像,且可以随着依赖库的增删不断迭代 Dockerfile。
|
||||
- agentscope-java:
|
||||
- 每次 call 的时候都会在 start/stop/snapshot 生成 tar 包快照。
|
||||
- 隔离级别更贴近多租户场景(SESSION/USER/AGENT/GLOBAL)覆盖多租户常见模型。
|
||||
|
||||
### 弊端
|
||||
|
||||
- agentscope:
|
||||
- 文件沙箱的生命周期过长,强依赖 TTL 清扫。
|
||||
- 工作区没有快照或副本能力,可以自行开发。
|
||||
- agentscope-java:
|
||||
- 随着工作区目录越来越大,会导致快照越来越慢(tar命令)可以自定义这个逻辑规避。
|
||||
- 没有 agentscope 那样不断迭代镜像的能力,需要人工干预(私以为自动迭代沙箱镜像是个伪需求)
|
||||
- 若隔离级别会 session 级别,每个 session 都会被拉起一个容器(要控制一台服务器的会话总数量)
|
||||
@@ -1,66 +1,3 @@
|
||||
# 任务目标
|
||||
|
||||
分析一下"RemoteMcpToolsServiceImpl.java"的"getMisMcpToolMetadata"方法,为什么返回的是一个Empty List。调用的入口是"MisMcpToolMetadataCtl.java"的"doGetMisMcpToolMetadata"方法,传入的mcpServerIds是包含一个数值为2084832591415877633的集合。我在数据库执行SQL:
|
||||
```sql
|
||||
select * from mcp_serve where mcp_server_uuid = 2084832591415877633;
|
||||
```
|
||||
得到如下结果:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"mcp_server_uuid": 2084832591415877633,
|
||||
"mcp_server_source_uuid": 2011699902312255490,
|
||||
"name": "getappliedlist-mingyan-1785897794303",
|
||||
"serve_aliases": "GetAppliedList-Mingyan",
|
||||
"description": "查询GetAppliedList的数据",
|
||||
"service_picture": 0,
|
||||
"mcp_service_type": 3,
|
||||
"workflow": 1,
|
||||
"sort": null,
|
||||
"create_by": 7,
|
||||
"create_time": "2026-08-05 10:43:19",
|
||||
"create_dept": 1889219366819864580,
|
||||
"update_time": "2026-08-05 14:04:48",
|
||||
"update_by": 7,
|
||||
"del_flag": 0,
|
||||
"auth_name": "",
|
||||
"auth": "",
|
||||
"auth_type": 0,
|
||||
"private_flags": 0,
|
||||
"address": null,
|
||||
"mcp_state": 2,
|
||||
"mcp_state_reason": null,
|
||||
"environment": 1,
|
||||
"mcp_file": null,
|
||||
"mcp_param": null,
|
||||
"usage_type": 7
|
||||
}
|
||||
]
|
||||
```
|
||||
继续执行SQL:
|
||||
```sql
|
||||
select * from mcp_tools where mcp_server_uuid = 2084832591415877633;
|
||||
```
|
||||
得到如下结果:
|
||||
```sql
|
||||
[
|
||||
{
|
||||
"tools_uuid": 2084832573384683521,
|
||||
"mcp_server_uuid": 2084832591415877633,
|
||||
"tools_name": "GetAppliedList-Mingyan",
|
||||
"tools_image": 0,
|
||||
"tools_state": 2,
|
||||
"tools_llm_description": "查询GetAppliedList的数据",
|
||||
"tools_state_reason": null,
|
||||
"mcp_access_mode": 1,
|
||||
"sort": null,
|
||||
"create_by": 7,
|
||||
"create_time": "2026-08-05 10:43:14",
|
||||
"create_dept": 1889219366819864580,
|
||||
"update_time": "2026-08-05 14:04:53",
|
||||
"update_by": 7,
|
||||
"del_flag": 0
|
||||
}
|
||||
]
|
||||
```
|
||||
但是我发现doGetMisMcpToolMetadata返回的是1个空的集合,这是为什么?
|
||||
修改E:\gitlab\mis-paw\mis-modules\mis-paw\src\main\java\com\lcfc\mispaw\service\Impl\AgentApprovalServiceImpl.java里面的"assertNoUnpublishedSkillMapping"方法,目前判断agentId关联的skill包含未发布的逻辑有误,应该参考"E:\gitlab\mis-paw\mis-modules\mis-paw\src\main\java\com\lcfc\mispaw\service\Impl\AgentPublishServiceImpl.java"的"submitPublish"方法生成的"AgentConfigSnapshot.java"。
|
||||
+993
@@ -0,0 +1,993 @@
|
||||
# Harness Chat 接口文档
|
||||
|
||||
`POST /harness/chat`
|
||||
|
||||
## 1. 接口说明
|
||||
|
||||
- 路径:`/harness/chat`
|
||||
- 方法:`POST`
|
||||
- 内容类型:`application/json`
|
||||
- 返回类型:`Flux<AgentEvent>`(**流式响应**,支持 SSE 与 JSON 数组两种方式)
|
||||
- 功能:向智能体发送一条用户输入,返回一段**细粒度智能体事件流**。调用方按事件类型逐条解析即可渲染「思考中 / 正在调用工具 / 流式输出答案 / 需要人工确认」等 UI 状态。
|
||||
|
||||
> 源码位置:`mis-common/mis-common-harness/java/com/lcfc/harness/chat/HarnessChatGateway.java#L18-L23`
|
||||
>
|
||||
> ```java
|
||||
> @PostMapping("/chat")
|
||||
> public Flux<AgentEvent> 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;同一用户不同会话相互隔离 |
|
||||
| `userId` | String | ✅ | 用户 ID;用于智能体命名空间隔离 / 会话路由 |
|
||||
| `input` | String | ✅ | 用户输入内容 |
|
||||
| `chatModel` | Object | ❌ | 聊天模型配置(`name`、`stream`、`temperature`) |
|
||||
|
||||
`chatModel` 结构:
|
||||
|
||||
| 字段 | 类型 | 默认值 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `name` | String | - | 模型名称,如 `gpt-oss-120b` |
|
||||
| `stream` | Boolean | `true` | 是否流式 |
|
||||
| `temperature` | Double | `0.2` | 温度 |
|
||||
|
||||
### 2.3 请求示例
|
||||
|
||||
```json
|
||||
POST /harness/chat
|
||||
Host: localhost:8080
|
||||
Content-Type: application/json
|
||||
Accept: text/event-stream
|
||||
|
||||
{
|
||||
"sessionId": "sess-20260918-001",
|
||||
"userId": "user-10001",
|
||||
"input": "帮我梳理今天的任务清单,生成一份 markdown 并保存到工作区",
|
||||
"chatModel": {
|
||||
"name": "gpt-oss-120b",
|
||||
"stream": true,
|
||||
"temperature": 0.2
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> ⚠️ 注意:当前实现中 `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` 或对象。
|
||||
-204
@@ -1,204 +0,0 @@
|
||||
# 内置的安全能力总览
|
||||
|
||||
| 安全能力 | v1.x | v2.x | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| 工具守卫 (Tool Guard) | ✅ | ✅ | 运行时工具调用检测 |
|
||||
| 文件防护 (File Guard) | ✅ | ✅ | 敏感文件/目录访问拒绝列表 |
|
||||
| 技能扫描器 (Skill Scanner) | ✅ | ✅ | 技能启用前安全预检 |
|
||||
| Web 登录认证 | ✅ | ✅ | 控制台可选身份验证 |
|
||||
| 沙箱隔离 (Sandbox) | ❌ | ✅ | **新增**:OS 内核级 Shell 执行隔离 |
|
||||
| 访问策略 (Access Policy) | ❌ | ✅ | **新增**:声明式 allow/deny/ask 策略引擎 |
|
||||
|
||||
## 已经做的安全加固
|
||||
|
||||
- 操作系统层面,已启用 SE Linux 的 Enforcing 模式。其 MAC(Mandatory Access Control)防御机制,可以遏制传统 DAC 机制下被恶意攻击,提权到 root 劫持系统控制权。在 MAC 机制下,权限受限于访问策略,而非文件所有者或用户。即便是 root 权限启动的进程,也必须遵守规则,无法绕过。
|
||||
- QwenPaw Linux 的实例运行在 Docker 容器中而非直接运行在宿主机,通过目录挂载的方式,将运行时生成的文件、数据持久化至宿主机上。宿主机磁盘目录不删除的前提下,容器实例宕机、重启数据不会丢失。
|
||||
|
||||
## 还能做的安全防护
|
||||
|
||||
- 定期备份数据目录:
|
||||
- 方案一、每天定时全量备份数据目录,生成压缩包上传至OSS。
|
||||
- 方案二、将数据目录挂载到NAS [点此查看方案明细](https://git.jkwlstv.cn/doc/container/src/branch/main/nas-to-nfs-linux-docker.md)
|
||||
- 除此之外,还能把 Docker 也启用 SE Linux 更精细的控制文件访问权限。
|
||||
- [点击跳转查看 agentscope、agentscope-java 对于容器沙箱的支持](./agentscope-sandbox.md)
|
||||
|
||||
## 工具守卫 (Tool Guard)
|
||||
|
||||
| Item | 详细说明 |
|
||||
| --- | --- |
|
||||
| 核心作用 | Agent 调用工具**之前**扫描参数,检测危险命令、路径遍历、数据外泄等,阻止恶意操作 |
|
||||
| 主要检测对象 | 重点针对 `execute_shell_command`;结合 YAML 正则规则 + `ShellEvasionGuardian`(引号感知的 Shell 规避分析) |
|
||||
| 检测示例 | `rm -rf /`、SQL 注入片段、命令替换 `$()`/`` ` ``、路径遍历 `../`、`sudo`/`su`、反向 Shell、Fork 炸弹、标志位混淆、Unicode 空白绕过等 |
|
||||
| 严重级别 | CRITICAL / HIGH / MEDIUM / LOW / INFO;CRITICAL/HIGH 在交互环境进入待审批,无会话时记日志(可用 `denied_tools` 强制禁止) |
|
||||
| 守护范围 (`guarded_tools`) | `null`=守护全部内置工具;`[]`=不守护;指定列表=仅守护列出工具 |
|
||||
| 禁止工具 (`denied_tools`) | 无条件阻止,不提供审批 |
|
||||
| 自定义规则 | 支持正则、威胁类别、严重级别、排除模式;类别含 command_injection、data_exfiltration、path_traversal 等 10 类 |
|
||||
| Shell 规避检查 | 7 项独立开关(默认全关):命令替换、混淆标志、反斜杠空白/操作符、换行、注释引号不同步、引号内换行 |
|
||||
| 执行级别 (`approval_level`) | STRICT(全审批)/ SMART(高风险审批)/ AUTO(仅规则命中审批,默认)/ OFF(关闭) |
|
||||
| 控制台 | 设置 → 安全 → 工具防护:启停、守护范围、禁止工具、内置/自定义规则管理;改完立即生效 |
|
||||
| 环境变量 | `QWENPAW_TOOL_GUARD_ENABLED`(优先于配置文件) |
|
||||
|
||||
### 内置 YAML 规则
|
||||
|
||||
| 类别 | 规则 ID | 严重级别 | 检测目标 |
|
||||
| --- | --- | --- | --- |
|
||||
| 命令注入与文件操作 | `TOOL_CMD_DANGEROUS_RM` | HIGH | `rm` 危险删除 |
|
||||
| 命令注入与文件操作 | `TOOL_CMD_DANGEROUS_MV` | HIGH | `mv` 移动/覆盖 |
|
||||
| 命令注入与文件操作 | `TOOL_CMD_UNSAFE_PERMISSIONS` | HIGH | `chmod -R 777`、`chattr` |
|
||||
| 低级别磁盘操作 | `TOOL_CMD_FS_DESTRUCTION` | CRITICAL | `mkfs`、`dd of=/dev/` 等 |
|
||||
| 资源滥用 | `TOOL_CMD_DOS_FORK_BOMB` | CRITICAL | Fork 炸弹、`kill -9 -1` |
|
||||
| 资源滥用 | `TOOL_CMD_SYSTEM_REBOOT` | CRITICAL | `reboot`/`shutdown`/`halt`/`init 0/6` |
|
||||
| 资源滥用 | `TOOL_CMD_SERVICE_RESTART` | HIGH | `systemctl`/`service` 重启停止 |
|
||||
| 资源滥用 | `TOOL_CMD_PROCESS_KILL` | HIGH | `pkill`/`killall`/`kill` |
|
||||
| 代码执行 | `TOOL_CMD_PIPE_TO_SHELL` | CRITICAL | `curl/wget \| bash` |
|
||||
| 代码执行 | `TOOL_CMD_OBFUSCATED_EXEC` | HIGH | `base64 -d \| bash` |
|
||||
| 代码执行 | `TOOL_CMD_IFS_INJECTION` | HIGH | `$IFS` 绕过 |
|
||||
| 代码执行 | `TOOL_CMD_CONTROL_CHARS` | CRITICAL | 不可见控制字符 |
|
||||
| 代码执行 | `TOOL_CMD_UNICODE_WHITESPACE` | HIGH | Unicode 空白绕过 |
|
||||
| 代码执行 | `TOOL_CMD_PROC_ENVIRON` | HIGH | `/proc/*/environ` 读环境 |
|
||||
| 代码执行 | `TOOL_CMD_JQ_SYSTEM` | HIGH | `jq` 中 `system(` |
|
||||
| 代码执行 | `TOOL_CMD_JQ_FILE_FLAGS` | HIGH | `jq` 任意读文件/加载代码 |
|
||||
| 代码执行 | `TOOL_CMD_ZSH_DANGEROUS` | HIGH | zsh 危险内建 |
|
||||
| 权限提升 | `TOOL_CMD_PRIVILEGE_ESCALATION` | CRITICAL | `sudo`/`su`/`doas`/`pkexec` |
|
||||
| 权限提升 | `TOOL_CMD_SYSTEM_TAMPERING` | HIGH | crontab、authorized_keys、sudoers |
|
||||
| 网络滥用 | `TOOL_CMD_REVERSE_SHELL` | CRITICAL | `/dev/tcp`、`nc -e`、`socat EXEC:` |
|
||||
|
||||
### Shell 规避
|
||||
|
||||
严重级别均为 **HIGH**
|
||||
|
||||
| 规则 ID | 说明 |
|
||||
| --- | --- |
|
||||
| `SHELL_EVASION_COMMAND_SUBSTITUTION` | 单引号外的反引号/命令/进程替换 |
|
||||
| `SHELL_EVASION_OBFUSCATED_FLAGS` | ANSI-C/区域化引号、空引号标志技巧 |
|
||||
| `SHELL_EVASION_BACKSLASH_WHITESPACE` | 引号外反斜杠转义空白 |
|
||||
| `SHELL_EVASION_BACKSLASH_OPERATOR` | 引号外反斜杠转义 `;\|&<>` |
|
||||
| `SHELL_EVASION_NEWLINE` | 裸换行/`\r` 拆分命令 |
|
||||
| `SHELL_EVASION_COMMENT_QUOTE_DESYNC` | `#` 注释与引号状态不同步 |
|
||||
| `SHELL_EVASION_QUOTED_NEWLINE` | 引号内换行后接伪注释行 |
|
||||
|
||||
## 文件防护 (File Guard)
|
||||
|
||||
| 能力项 | 详细说明 |
|
||||
| --- | --- |
|
||||
| 核心作用 | 阻止 Agent 工具访问敏感文件和目录;每次工具调用自动扫描路径参数 |
|
||||
| 独立性 | 即使 `tool_guard.enabled=false`,只要 `file_guard.enabled=true` 仍会检查 |
|
||||
| 路径提取策略 | 已知文件工具检查 `file_path`;Shell 从命令串提取(含重定向);其他工具扫描类路径字符串 |
|
||||
| 路径处理 | 相对路径解析、`~` 展开、规范化为绝对路径;以 `/` 结尾的目录递归保护 |
|
||||
| 默认保护 | `{WORKING_DIR}.secret/`(默认 `~/.qwenpaw.secret/`,存 API 密钥与凭据) |
|
||||
| 阻止级别 | 匹配时以 HIGH 级别发现阻止 |
|
||||
| 配置字段 | `enabled`(默认 true)、`sensitive_files`(绝对/相对/`~/`/目录路径) |
|
||||
| 控制台 | 设置 → 安全 → 文件防护:启停、增删保护路径、保存/重置;立即生效 |
|
||||
|
||||
## 技能扫描器 (Skill Scanner)
|
||||
|
||||
| 能力项 | 详细说明 |
|
||||
| --- | --- |
|
||||
| 核心作用 | 技能启用/安装前扫描恶意代码、硬编码密钥、社会工程等威胁 |
|
||||
| 触发时机 | 创建新技能、启用已禁用技能、从 Skill Hub 导入 |
|
||||
| 扫描机制 | YAML 正则签名 + PatternAnalyzer;支持自定义 ScanPolicy |
|
||||
| 智能缓存 | 基于文件 mtime,未变更不重复扫描 |
|
||||
| 超时保护 | 默认 30 秒(可配 5–300 秒) |
|
||||
| 文件安全 | 跳过符号链接、校验路径边界、默认跳过二进制/归档 |
|
||||
| 扫描模式 | **Block** 拦截不可用;**Warn** 警告但可用(默认);**Off** 关闭 |
|
||||
| 配置优先级 | 环境变量 `QWENPAW_SKILL_SCAN_MODE` > 控制台 > `config.json` |
|
||||
| 扫描告警 | 查看详情(文件/行号/模式)、加白名单、删单条/清全部 |
|
||||
| 白名单 | SHA-256 内容哈希版本锁定;文件变更后白名单失效需重扫 |
|
||||
| 内置威胁类别 | command_injection、data_exfiltration、hardcoded_secrets、prompt_injection、social_engineering、supply_chain_attack、obfuscation、resource_abuse、unauthorized_tool_use |
|
||||
| 自定义规则 | YAML 签名(id/category/severity/patterns/exclude_patterns/file_types 等) |
|
||||
| 控制台 | 设置 → 安全 → 技能扫描器;模式与超时改完立即生效 |
|
||||
|
||||
### Web 登录认证
|
||||
|
||||
| 能力项 | 详细说明 |
|
||||
| --- | --- |
|
||||
| 核心作用 | 可选保护控制台,防未授权访问;**默认关闭**,需 `QWENPAW_AUTH_ENABLED=true` |
|
||||
| 账户模式 | 单用户管理员;首次网页注册,或环境变量自动注册(适合 Docker/K8s) |
|
||||
| 令牌 | HMAC-SHA256 签名,有效期 7 天,存 localStorage |
|
||||
| 密码存储 | 加盐 SHA-256,不存明文;`auth.json` 权限 `0o600` |
|
||||
| 本地免认证 | `127.0.0.1` / `::1` 跳过认证;CLI 无需令牌 |
|
||||
| 豁免主机 | `security.allow_no_auth_hosts`(默认 localhost) |
|
||||
| 环境变量 | `QWENPAW_AUTH_ENABLED`(必填启用);`QWENPAW_AUTH_USERNAME` / `QWENPAW_AUTH_PASSWORD`(可选自动注册) |
|
||||
| 运维能力 | `qwenpaw auth reset-password`(轮换签名密钥使所有会话失效);侧边栏退出登录 |
|
||||
| 路由保护 | 仅 `/api/*` 需认证;登录/注册/status/version 与静态资源公开;WebSocket 令牌经查询参数 |
|
||||
|
||||
## 沙箱隔离 (Sandbox)
|
||||
|
||||
**沙箱隔离来自操作系统支持**
|
||||
|
||||
| 能力项 | 详细说明 |
|
||||
| --- | --- |
|
||||
| 核心作用 | 为 Shell 命令提供 **OS 内核级**执行隔离;命令只能访问已声明的文件系统视图 |
|
||||
| 在链路中的位置 | 工具守卫(静态检测)→ 治理引擎(ALLOW/DENY/ASK/SANDBOX_FALLBACK)→ **沙箱隔离(运行时强制)** → 违规检测 |
|
||||
| 与既有层关系 | 即使通过工具守卫与文件防护,沙箱仍从内核层限制白名单外访问 |
|
||||
| 隔离模型 | 默认拒绝 + 白名单:`mounts` 控制可写;`deny_paths` 额外阻止;最小化 `/dev`;Bubblewrap 支持 PID 隔离 |
|
||||
| 配置来源 | 由治理策略引擎自动编译,用户通常无需手写;含 mode、workspace_dir、mounts、deny_paths、allow_read_all、timeout 等 |
|
||||
| 违规处理 | 解析 stderr 模式填充 `sandbox_violation`;记治理日志;可按策略提示审批扩展权限 |
|
||||
|
||||
### 不同平台的沙箱隔离机制
|
||||
|
||||
| 平台 | 后端 | 机制 | 选用条件 |
|
||||
| --- | --- | --- | --- |
|
||||
| macOS | Seatbelt | `sandbox-exec` + S-expression 策略 | PATH 有 `sandbox-exec` |
|
||||
| Linux | Bubblewrap(首选) | Mount/User/PID namespace | `bwrap` + user namespace |
|
||||
| Linux | Landlock(回退) | Landlock LSM(内核 5.13+) | 无 bwrap 时回退 |
|
||||
| Windows | AppContainer | AppContainer + `icacls` ACL | `allow_read_all=False`,Win10+ |
|
||||
| Windows | Restricted_token | 受限令牌 + WFP 防火墙 | `allow_read_all=True`(默认),需管理员 |
|
||||
| 所有 | None | 无隔离直接执行 | 无可用后端时 |
|
||||
|
||||
### 不同隔离机制的能力对比
|
||||
|
||||
| 能力 | Seatbelt | Bubblewrap | Landlock | AppContainer | Restricted_token |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 文件系统(读) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| 文件系统(写) | ✅ | ✅ | ✅ | ✅ | ✅(受限令牌) |
|
||||
| deny_paths 不可见 | ❌(拒绝访问) | ✅(未挂载) | ❌(拒绝访问) | ❌ | ❌ |
|
||||
| PID 命名空间隔离 | ❌ | ✅ | ❌ | ❌ | ❌ |
|
||||
| 最小化 /dev | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| 网络控制 | ✅(允许/拒绝) | 计划中 | ❌ | ✅ | ✅(WFP) |
|
||||
|
||||
最小化 /dev 指的是沙箱里不挂载完整的 /dev 只挂载:
|
||||
|
||||
```text
|
||||
/dev/null
|
||||
/dev/zero
|
||||
/dev/urandom
|
||||
/dev/tty
|
||||
```
|
||||
|
||||
这样命令仍能做重定向、读随机数、写终端等常规操作,但碰不到磁盘分区、真实网卡设备等更危险的节点。
|
||||
|
||||
### 沙箱目前的限制
|
||||
|
||||
| 限制项 | 说明 |
|
||||
| --- | --- |
|
||||
| 网络隔离 | 当前未真正强制;`network_allow` 暂不影响;bubblewrap 网络命名空间已规划 |
|
||||
| 资源限制 | `max_processes` / `max_memory_mb` 字段存在但后端未强制 |
|
||||
| Windows 要求 | 需 Windows 10 build 10240+;AppContainer/Restricted_token 常需管理员权限 |
|
||||
| AppContainer 删文件 | `allow_read_all=False` 时沙箱内可能无法删除工作区文件 |
|
||||
|
||||
## 访问策略 (Access Policy)
|
||||
|
||||
| 能力项 | 详细说明 |
|
||||
| --- | --- |
|
||||
| 核心作用 | 声明式策略引擎:对每次能力调用裁定 **allow / deny / ask** |
|
||||
| 适用范围 | 每个服务客户端独立策略;当前已在 **MCP** 落地,设计可扩展到其他协议 |
|
||||
| 三种效果 | `allow` 立即执行;`deny` 阻止并返回错误;`ask` 挂起等待控制台人工审批 |
|
||||
| 两级粒度 | **客户端级**默认效果;**工具级**可为特定工具覆盖(如禁 `dangerous_tool`) |
|
||||
| 来源感知 | 按 `principal` 匹配来源渠道(console、dingtalk 等)与身份(user 等) |
|
||||
| Subject 模式 | `user:xxx`、`session:xxx`、`channel:xxx`、`*` |
|
||||
| 默认效果 | `default_effect`:无规则匹配时生效,默认 `deny` |
|
||||
| 优先级裁决 | 目标名精确 > 目标类型 > Principal 具体度 > Subject 精确度 > 严格程度(deny > ask > allow) |
|
||||
| 审批流程 | ask 时挂起并出审批卡片(工具/参数/身份/来源/客户端);超时未响应则拒绝 |
|
||||
| 配置位置 | MCP 客户端 YAML 的 `policy` 段;控制台 **智能体 → MCP → 工具&权限** |
|
||||
| 控制台能力 | 设默认效果、客户端级规则、工具级默认与覆盖规则;保存立即生效 |
|
||||
| 注意 | YAML 中高级 subject(如 `user:admin`)会保留但控制台不可编辑,显示为「未管理规则」 |
|
||||
|
||||
### 策略裁决示例
|
||||
|
||||
| 请求场景 | 结果 | 原因 |
|
||||
| --- | --- | --- |
|
||||
| `user:admin` 调用任意工具 | ALLOW | 精确 subject 匹配 |
|
||||
| 任何人调用 `dangerous_tool` | DENY | 精确目标名称优先 |
|
||||
| 控制台用户调用 `safe_tool` | ALLOW | 目标 + principal 双重匹配 |
|
||||
| 钉钉用户调用 `other_tool`(无规则) | ASK | 回落到 `default_effect` |
|
||||
@@ -1,354 +1 @@
|
||||
# AgentScope vs AgentScope-Java:Workspace 文件系统与沙箱集成分析
|
||||
|
||||
> 对比版本:`agentscope` **v2.0.5** · `agentscope-java` **v2.0.0**
|
||||
> 重点:Docker 沙箱;兼顾 Kubernetes / E2B / Daytona / OpenSandbox / AgentRun
|
||||
|
||||
---
|
||||
|
||||
## 1. 结论摘要
|
||||
|
||||
两套框架都把「Agent 读写文件 / 执行命令」从本机磁盘解耦到可替换的隔离后端,但抽象重心不同:
|
||||
|
||||
| 维度 | agentscope (Python) | agentscope-java |
|
||||
| --- | --- | --- |
|
||||
| 核心抽象 | **Workspace**(长期运行的工作区 + 进程内 MCP Gateway) | **Filesystem Spec**(声明式配置)→ 每次 `call` 借出/归还沙箱 |
|
||||
| 生命周期粒度 | Workspace 级:`initialize` → 长期复用 → `close` | Call 级:`PreCall acquire/start` → `PostCall stop(快照)/release` |
|
||||
| Docker 接入方式 | **aiodocker**(Docker Engine HTTP API) | **`docker` CLI**(`ProcessBuilder`,无 docker-java 依赖) |
|
||||
| 持久化主路径 | Bind mount / 云沙箱 pause / K8s PVC | **Workspace tar 快照**(Local/Redis/OSS/…)+ 可选 bind mount |
|
||||
| 分布式能力 | 依赖云沙箱 metadata 重连或 K8s 集群资源 | 依赖 `SandboxStateStore` + 分布式快照后端 |
|
||||
| 独有后端 | OpenSandbox、Bubblewrap | AgentRun(阿里云) |
|
||||
|
||||
**选型直觉:** 需要「常驻工作区 + MCP 网关 + Python Agent 服务」→ agentscope;需要「HarnessAgent 按次隔离、快照跨副本恢复、Java 生态」→ agentscope-java。
|
||||
|
||||
---
|
||||
|
||||
## 2. 总体架构对比
|
||||
|
||||
### 2.1 agentscope:Workspace + Backend + Gateway
|
||||
|
||||
```
|
||||
WorkspaceManager (服务侧缓存 / TTL / IsolationPolicy)
|
||||
│
|
||||
▼
|
||||
SandboxedWorkspaceBase.initialize()
|
||||
├─ _provision_backend() ← Docker/E2B/K8s/Daytona/OpenSandbox 各实现
|
||||
├─ _ensure_workspace_layout() (/workspace、skills、sessions、data、.mcp)
|
||||
└─ _setup_mcp_gateway() ← 容器内 FastAPI MCP Gateway
|
||||
│
|
||||
▼
|
||||
BackendBase (exec_shell / read_file / write_file)
|
||||
└─ 内置工具 Bash/Read/Write/Edit/Grep/Glob 透明落到沙箱内
|
||||
```
|
||||
|
||||
关键设计点:
|
||||
|
||||
1. **模板方法**:子类只实现 `_provision_backend` / `_teardown_backend` / `_bootstrap_commands`。
|
||||
2. **容器内 MCP Gateway**:宿主机通过 `GatewayClient` + `backend.exec_shell` 驱动网关(一般不依赖宿主机到沙箱的端口映射)。
|
||||
3. **WorkspaceManager**:`PER_AGENT` / `PER_SESSION` / `PER_USER`,空闲 TTL 驱逐;云后端可按 metadata/label 跨节点重连。
|
||||
|
||||
### 2.2 agentscope-java:Filesystem Spec + SandboxManager
|
||||
|
||||
```
|
||||
HarnessAgent.Builder.filesystem(DockerFilesystemSpec / …)
|
||||
│
|
||||
▼
|
||||
SandboxFilesystemSpec.toSandboxContext(hostWorkspaceRoot)
|
||||
└─ SandboxContext(client, options, snapshotSpec, workspaceSpec, isolationScope)
|
||||
│
|
||||
▼
|
||||
SandboxLifecycleHook
|
||||
PreCall → SandboxManager.acquire → Sandbox.start() (四分支恢复)
|
||||
PostCall → Sandbox.stop() (tar 快照) → persist state → release
|
||||
│
|
||||
▼
|
||||
SandboxBackedFilesystem + ShellExecuteTool
|
||||
└─ 文件工具 / execute 全部转发到沙箱
|
||||
```
|
||||
|
||||
关键设计点:
|
||||
|
||||
1. **声明式 Spec**:`DockerFilesystemSpec` 等只描述「如何创建」,不是运行时文件系统本身。
|
||||
2. **Call 边界生命周期**:每次推理前后自动 acquire/start/stop,适合多租户按次计费与快照恢复。
|
||||
3. **快照与执行后端正交**:换 Docker/K8s/E2B 不影响 `LocalSnapshotSpec` / `RedisSnapshotSpec` / `OssSnapshotSpec` 的选择。
|
||||
4. **Workspace Projection**:启动时把宿主 `AGENTS.md`、`skills/`、`subagents/`、`knowledge/` 等打 tar 注入沙箱,按内容 SHA-256 增量跳过。
|
||||
|
||||
---
|
||||
|
||||
## 3. Docker 集成深挖(重点)
|
||||
|
||||
### 3.1 agentscope · `DockerWorkspace`
|
||||
|
||||
**源码入口:** `src/agentscope/workspace/_docker/_docker_workspace.py`
|
||||
**配套:** `_docker_backend.py`、`_make_dockerfile.py`
|
||||
|
||||
#### 实现原理
|
||||
|
||||
1. **镜像构建(内容哈希缓存)**
|
||||
- `prepare_build_context()` 渲染 Dockerfile,打包 gateway 脚本、`requirements.txt`、glob helper。
|
||||
- Tag 形如 `agentscope-workspace:<12hex>`,对 Dockerfile + COPY 文件做 SHA-256;本地已有则跳过 build。
|
||||
- 默认基础镜像 `python:3.11-slim`,镜像内预装 gateway venv + agentscope(Docker 路径**不做**首次 bootstrap)。
|
||||
- 可选 `node_version` 从官方 Node slim 镜像拷贝 `node`/`npm`(供 npx MCP)。
|
||||
|
||||
2. **容器启动**
|
||||
- 通过 **aiodocker** `containers.create_or_replace`。
|
||||
- `Cmd: ["sleep", "infinity"]`,工作目录 `/workspace`。
|
||||
- Label:`agentscope.workspace=true`、`agentscope.workspace.id=<id>`。
|
||||
- **Gateway 端口仅容器内监听,不做 host port 映射**;宿主经 `DockerBackend.exec` 访问。
|
||||
|
||||
3. **持久化**
|
||||
- 可选 `host_workdir` bind-mount → `/workspace`(`is_persistent`)。
|
||||
- 无 mount 则为 ephemeral 容器文件系统。
|
||||
- Linux 上 teardown 时尝试 `chown` 把 bind-mount 文件所有权还给宿主用户。
|
||||
|
||||
4. **I/O 原语(`DockerBackend`)**
|
||||
- `exec_shell`:容器 `exec` API,直传 argv(无中间 shell,需要时包 `sh -c`)。
|
||||
- `read_file` / `write_file`:`get_archive` / `put_archive`(tar)。
|
||||
|
||||
5. **服务侧**
|
||||
- `DockerWorkspaceManager`:`basedir` 下为每个 workspace 建宿主目录并 bind-mount;TTL sweeper 回收空闲容器。
|
||||
|
||||
#### 使用限制
|
||||
|
||||
| 限制 | 说明 |
|
||||
| --- | --- |
|
||||
| 依赖 Docker daemon | 需本机/远端可达的 Docker Engine + aiodocker |
|
||||
| 基础镜像须含 `python3` | Gateway 与工具链假设 Python 可用 |
|
||||
| **单节点** | 官方文档明确:Docker/Local/Bubblewrap 不适配水平扩容;跨节点请用 E2B/Daytona/OpenSandbox/K8s |
|
||||
| 首次镜像构建成本 | 缓存未命中时 build 较慢;构建失败需解读 docker stream 日志 |
|
||||
| 无细粒度 CPU/内存 API | 构造参数侧重镜像与环境变量,资源限额不如 Java Spec 直接 |
|
||||
| Linux bind-mount 权限 | 容器内 root 写文件可能留下错误 uid;框架仅在 teardown 做 chown 尽力修复 |
|
||||
|
||||
#### 好处
|
||||
|
||||
- 镜像内预置 gateway,**冷启动无需 apt/uv/pip bootstrap**(对比 E2B/K8s/OpenSandbox)。
|
||||
- 内容哈希镜像缓存,Dockerfile 不变则秒级复用。
|
||||
- Workspace 长期存活,MCP / skills / sessions 与服务模型一致。
|
||||
- Bind-mount 可把工作区落在宿主磁盘,便于调试与备份。
|
||||
- 与 `WorkspaceManager` 隔离策略(PER_AGENT 等)无缝衔接。
|
||||
|
||||
#### 弊端
|
||||
|
||||
- 强依赖本机 Docker,水平扩展与多副本亲和困难。
|
||||
- 常驻 `sleep infinity` 容器占用资源,依赖 TTL 清扫。
|
||||
- Gateway 健康检查失败时排查需看容器内日志路径。
|
||||
- 与 Java 版相比,缺少一等公民的「跨 call tar 快照后端」抽象。
|
||||
|
||||
---
|
||||
|
||||
### 3.2 agentscope-java · `DockerFilesystemSpec` / `DockerSandbox`
|
||||
|
||||
**源码入口:**
|
||||
- Spec:`.../sandbox/impl/docker/DockerFilesystemSpec.java`
|
||||
- 运行时:`DockerSandbox.java`、`DockerSandboxClient.java`
|
||||
|
||||
#### 实现原理
|
||||
|
||||
1. **配置层(Spec)**
|
||||
Fluent API:`image`、`workspaceRoot`(默认 `/workspace`)、`memorySizeBytes`、`cpuCount`、`exposedPorts`、`network`、`environment`、`additionalRunArgs`、`snapshotSpec`、`workspaceSpec`。
|
||||
|
||||
2. **创建与客户端**
|
||||
- `DockerSandboxClient.create(...)` 生成 `DockerSandboxState`(sessionId、镜像、资源参数、快照句柄)。
|
||||
- **不引入 docker-java**:一律 `docker run` / `exec` / `inspect` / `stop` / `rm` CLI。
|
||||
- 要求宿主 `PATH` 上有 `docker`,且 daemon 可达。
|
||||
|
||||
3. **容器命令**
|
||||
```text
|
||||
docker run -d --name agentscope-sandbox-<sessionId>
|
||||
[--memory] [--cpus] [-p] [--network=none|...] [-v bind...]
|
||||
<image> sh -c "while :; do sleep 3600; done"
|
||||
```
|
||||
- 默认 **`--network=none`**(未配置 network 时),比 Python 版更偏「默认断网隔离」。
|
||||
- 支持 `WorkspaceSpec` 中的 `BindMountEntry` → `-v host:container:ro|rw`。
|
||||
- `exec`:`docker exec -w <workspaceRoot> <id> sh -c <command>`。
|
||||
|
||||
4. **工作区 tar 快照**
|
||||
- Persist:`docker exec tar -cf - -C /workspace .`(并对 bind-mount 路径 `--exclude`)。
|
||||
- Hydrate:`docker exec -i tar -xf - -C /workspace`。
|
||||
- `AbstractBaseSandbox` **四分支恢复**:容器是否仍保留目录 × 是否有可恢复快照。
|
||||
|
||||
5. **Call 级编排**
|
||||
- `start()`:确保容器 running → 四分支初始化 → workspace projection。
|
||||
- `stop()`:写快照,**容器可继续跑**。
|
||||
- `shutdown()`:自管容器则 `docker stop` + `docker rm --force`。
|
||||
|
||||
#### 使用限制
|
||||
|
||||
| 限制 | 说明 |
|
||||
| --- | --- |
|
||||
| 依赖 Docker CLI | 无嵌入式 Engine API;Windows/远程 Docker 场景需确保 CLI 行为一致 |
|
||||
| 默认无网络 | `network` 未设时为 `none`;需要拉包/访问外网必须显式配置 |
|
||||
| 镜像需自备 | 不像 Python 那样自动构建含 gateway 的专用镜像;由用户指定(如 `ubuntu:24.04`) |
|
||||
| 输出截断 | stdout/stderr 单流约 512KB 上限 |
|
||||
| 并发语义 | 同一 IsolationScope 并发 call 可起多个容器,stop 时 **last-write-wins** 覆盖快照 |
|
||||
| 多副本 | 本地 Docker + 本地快照会成单点;生产需 Redis/OSS 快照 + 分布式 `AgentStateStore` |
|
||||
| AgentRun/K8s 等扩展 | Docker 在 harness 核心;其它后端在 extension 模块,需单独依赖 |
|
||||
|
||||
#### 好处
|
||||
|
||||
- **零额外 Java Docker 库依赖**,部署简单。
|
||||
- 资源限额(CPU/内存)、端口、网络、额外 run args 一等配置。
|
||||
- 快照体系成熟,可跨 call / 跨副本恢复 `node_modules` 等重状态。
|
||||
- Workspace projection 把静态资产与运行态分离,宿主改 skills 可增量注入。
|
||||
- `IsolationScope`(SESSION/USER/AGENT/GLOBAL)覆盖多租户 SaaS 常见模型。
|
||||
- `executionGuard` 可对 AGENT/GLOBAL 做串行化,缓解快照互踩。
|
||||
|
||||
#### 弊端
|
||||
|
||||
- 每次 call 的 start/stop/snapshot 有固定开销(尤其大工作区 tar)。
|
||||
- CLI 进程模型:高并发时大量 `docker exec` 子进程与线程池开销。
|
||||
- 无内置 MCP Gateway;MCP 走 Harness 侧 `tools.json` 注册,与沙箱内进程模型不同。
|
||||
- 默认断网 + 裸镜像,冷启动后常需 agent 自己装依赖(靠快照摊销)。
|
||||
|
||||
---
|
||||
|
||||
### 3.3 Docker 双端对照表
|
||||
|
||||
| 对比项 | agentscope v2.0.5 | agentscope-java v2.0.0 |
|
||||
| --- | --- | --- |
|
||||
| API 形态 | aiodocker(Engine API) | docker CLI |
|
||||
| 保活命令 | `sleep infinity` | `while :; do sleep 3600; done` |
|
||||
| 镜像策略 | 自动构建并内容哈希缓存 | 用户指定现成镜像 |
|
||||
| 默认网络 | Docker 默认(通常有网) | **`none`** |
|
||||
| 持久化 | Bind-mount(可选) | Tar 快照为主 + 可选 bind-mount |
|
||||
| 生命周期 | Workspace 长生命周期 | 按 Agent `call` 借还 |
|
||||
| MCP | 容器内 Gateway | Harness 侧注册;沙箱只做 FS/Shell |
|
||||
| 资源限制 | 较弱(构造参数少) | memory / cpu / ports / network |
|
||||
| 水平扩展 | 不适合 | 需外置快照/状态存储 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 其它沙箱类型
|
||||
|
||||
### 4.1 支持矩阵
|
||||
|
||||
| 沙箱类型 | agentscope v2.0.5 | agentscope-java v2.0.0 | 共同点 |
|
||||
| --- | --- | --- | --- |
|
||||
| Docker | ✅ `DockerWorkspace` | ✅ `DockerFilesystemSpec`(harness 内置) | 本地隔离、需 Docker |
|
||||
| Kubernetes | ✅ `K8sWorkspace`(Pod + PVC) | ✅ `KubernetesFilesystemSpec`(extension) | 集群级资源、适合生产 K8s |
|
||||
| E2B | ✅ `E2BWorkspace` | ✅ `E2bFilesystemSpec` | 云沙箱 SDK、metadata/API 重连 |
|
||||
| Daytona | ✅ `DaytonaWorkspace` | ✅ `DaytonaFilesystemSpec` | 云沙箱、标签/API 重挂接 |
|
||||
| AgentRun | ❌ 暂未支持 | ✅ `AgentRunFilesystemSpec`(阿里云) | — |
|
||||
| OpenSandbox | ✅ `OpenSandboxWorkspace` | ❌ 暂未支持 | — |
|
||||
| Bubblewrap | ✅(另有 Local) | ❌(有 LocalFilesystemSpec) | Linux 轻量沙箱 / 本机模式 |
|
||||
|
||||
### 4.2 agentscope 各后端要点
|
||||
|
||||
| 后端 | 供给方式 | 持久化 | Teardown | Bootstrap |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| **Docker** | aiodocker 建容器 | Bind-mount 或 ephemeral | kill + delete 容器 | 镜像已含 gateway |
|
||||
| **K8s** | Pod + PVC(`as-ws-{id}`) | PVC 跨 Pod 存活 | 删 Pod,默认可保留 PVC | 首次 apt + uv + gateway |
|
||||
| **E2B** | `AsyncSandbox.create/connect` | pause 保留磁盘 | `pause()` | 首次 bootstrap |
|
||||
| **Daytona** | SDK create / label 查找 | `stop(force=False)` | stop + close client | 首次 bootstrap(路径由 SDK 推导) |
|
||||
| **OpenSandbox** | `Sandbox.create` / resume / connect | `pause()` | pause + close | 首次 bootstrap |
|
||||
|
||||
云后端共性:用 `agentscope.workspace.id`(或等价 metadata/label)索引;Manager 缓存 miss 时可跨服务副本重连——这是文档推荐的**分布式部署**路径。
|
||||
|
||||
### 4.3 agentscope-java 各后端要点
|
||||
|
||||
| 后端 | 模块位置 | 交互方式 | 持久化侧重 |
|
||||
| --- | --- | --- | --- |
|
||||
| **Docker** | harness 核心 | CLI | Tar 快照 + 可选 bind |
|
||||
| **Kubernetes** | extension | fabric8 / Pod 侧 exec+tar(文档侧亦描述 agent-sandbox WarmPool 演进) | 快照 Spec;集群侧还可结合 PVC/模板 |
|
||||
| **E2B** | extension | E2B HTTP + envd;支持 TAR / NATIVE_SNAPSHOT 等持久化模式 | 平台快照或 tar |
|
||||
| **Daytona** | extension | Control Plane HTTP API | 快照 Spec;不应用 host bind-mount(有则 WARN) |
|
||||
| **AgentRun** | extension | 阿里云 AgentRun API;可配 NAS/OSS mount、MCP URL | 云侧空闲超时 + 快照 Spec |
|
||||
|
||||
公共能力均来自 `SandboxFilesystemSpec`:`isolationScope`、`snapshotSpec`、`executionGuard`、`workspaceProjection*`。
|
||||
|
||||
### 4.4 OpenSandbox 补充(仅 Python)
|
||||
|
||||
[OpenSandbox](https://open-sandbox.ai/getting-started) 是通用沙箱平台(Docker/K8s 运行时 + 多语言 SDK)。agentscope 通过官方 `opensandbox` SDK:
|
||||
|
||||
- 按 metadata 过滤 RUNNING/PAUSED 沙箱并 resume/connect;
|
||||
- close 时 **pause** 保文件系统;
|
||||
- 与 E2B 类似走 `_bootstrap_commands` 安装 gateway。
|
||||
|
||||
Java 侧 v2.0.0 **未集成**,若要在 Java 使用需自研 `SandboxClient` 或等待官方 extension。
|
||||
|
||||
---
|
||||
|
||||
## 5. 隔离模型对比
|
||||
|
||||
| | agentscope `IsolationPolicy` | agentscope-java `IsolationScope` |
|
||||
| --- | --- | --- |
|
||||
| 会话级 | `PER_SESSION` | `SESSION`(沙箱默认) |
|
||||
| 用户级 | `PER_USER`(跨 agent 慎用) | `USER`(跨 session 共享记忆/快照) |
|
||||
| Agent 级 | `PER_AGENT`(默认,按 user+agent) | `AGENT`(按 agent 名共享) |
|
||||
| 全局 | 无对等枚举 | `GLOBAL` |
|
||||
| 绑定时机 | Session 创建时写入 `workspace_id` | 每次 call 用 RuntimeContext 算 isolation key |
|
||||
|
||||
Java 另强调:**沙箱模式下的 scope 是「顺序复用 + 快照」,不是同一容器实时共享**;并发需 `executionGuard`。
|
||||
|
||||
---
|
||||
|
||||
## 6. 好处与弊端总览
|
||||
|
||||
### 6.1 agentscope(Python)Workspace 沙箱体系
|
||||
|
||||
**好处**
|
||||
|
||||
- 统一 `SandboxedWorkspaceBase`,后端可插拔,服务侧一行切换 Manager。
|
||||
- MCP Gateway 与文件工具同处沙箱,安全边界清晰。
|
||||
- Docker 镜像预烘焙,稳态性能好;云后端天然支持多副本重连。
|
||||
- OpenSandbox / Bubblewrap 覆盖「自托管云」与「轻量 Linux 沙箱」。
|
||||
|
||||
**弊端**
|
||||
|
||||
- Docker/Local 单节点限制明显。
|
||||
- 非 Docker 后端首次 bootstrap 重(网络、时间、镜像权限)。
|
||||
- 缺少 Java 那种可插拔「快照存储后端」产品化抽象。
|
||||
- 无 AgentRun。
|
||||
|
||||
### 6.2 agentscope-java Harness 沙箱体系
|
||||
|
||||
**好处**
|
||||
|
||||
- Filesystem 三模式(Local / Remote KV / Sandbox)切换不改 Agent 业务代码。
|
||||
- Call 级生命周期 + 多快照后端,适合多租户与水平扩展。
|
||||
- Docker 资源/网络控制细;扩展点(自定义 `SandboxClient`)文档化完整。
|
||||
- AgentRun 对接阿里云;projection 解决静态资产分发。
|
||||
|
||||
**弊端**
|
||||
|
||||
- Docker CLI 与大 tar 快照带来延迟与运维开销。
|
||||
- 默认 `network=none`、裸镜像,开发体验需额外配置。
|
||||
- 并发 last-write-wins 需业务侧理解。
|
||||
- 无 OpenSandbox;MCP 不在沙箱内统一托管(与 Python Gateway 模型不同)。
|
||||
|
||||
---
|
||||
|
||||
## 7. 实践建议
|
||||
|
||||
1. **本地可信开发**
|
||||
- Python:`LocalWorkspace` / `BubblewrapWorkspace`
|
||||
- Java:`LocalFilesystemSpec`(默认)
|
||||
|
||||
2. **单机强隔离、可调试**
|
||||
- 两边都用 **Docker**;Python 适合长期 workspace + MCP;Java 适合按次执行 + 快照实验。
|
||||
|
||||
3. **多副本生产**
|
||||
- Python:E2B / Daytona / OpenSandbox / K8s Manager
|
||||
- Java:任意 `SandboxFilesystemSpec` + **分布式** `snapshotSpec` + `AgentStateStore`(否则 build 会强制提醒单点风险)
|
||||
|
||||
4. **中国云 / AgentRun**
|
||||
- 仅 Java `AgentRunFilesystemSpec`。
|
||||
|
||||
5. **自托管沙箱平台**
|
||||
- 仅 Python `OpenSandboxWorkspace`;需先部署 OpenSandbox Server。
|
||||
|
||||
---
|
||||
|
||||
## 8. 参考链接
|
||||
|
||||
| 资源 | URL |
|
||||
| --- | --- |
|
||||
| agentscope DockerWorkspace | https://github.com/agentscope-ai/agentscope/blob/v2.0.5/src/agentscope/workspace/_docker/_docker_workspace.py |
|
||||
| agentscope Workspace Manager 文档 | https://docs.agentscope.io/versions/2.0.5/zh/deploy/workspace-manager |
|
||||
| agentscope-java DockerFilesystemSpec | https://github.com/agentscope-ai/agentscope-java/blob/v2.0.0/agentscope-harness/src/main/java/io/agentscope/harness/agent/sandbox/impl/docker/DockerFilesystemSpec.java |
|
||||
| agentscope-java Filesystem 文档 | https://java.agentscope.io/v2/zh/docs/harness/filesystem.html |
|
||||
| OpenSandbox 入门 | https://open-sandbox.ai/getting-started |
|
||||
| OpenSandbox GitHub | https://github.com/opensandbox-group/OpenSandbox |
|
||||
|
||||
---
|
||||
|
||||
*报告基于上述版本标签源码与官方文档整理;若文档站点已超前于 tag,以对应 Git tag 源码为准。*
|
||||
123
|
||||
@@ -1 +1,211 @@
|
||||
123
|
||||
# 目录
|
||||
|
||||
- [查智能体用户数](#查智能体用户数)
|
||||
- [查客户端是否登录](#查客户端是否登录)
|
||||
- [查智能体对话日志](#查智能体对话日志)
|
||||
- [查智能体信息](#查智能体信息)
|
||||
- [查智能体使用数据](查智能体使用数据)
|
||||
- [查项目统计数据](#查项目统计数据)
|
||||
- [新增devco账号](#新增devco账号)
|
||||
- [查paw-agent信息](#查paw-agent信息)
|
||||
|
||||
## 查智能体用户数
|
||||
|
||||
```sql
|
||||
select
|
||||
'单智能体' AS agent_type,
|
||||
agent.agent_id,
|
||||
agent.agent_name,
|
||||
IFNULL (aus.user_num, 0) AS user_num
|
||||
from
|
||||
`agent` AS agent
|
||||
left join agent_usage_stats AS aus ON agent.agent_id = aus.agent_id
|
||||
where
|
||||
agent.del_flag = '0'
|
||||
UNION ALL
|
||||
select
|
||||
'多智能体' AS agent_type,
|
||||
ma.agent_id,
|
||||
ma.agent_name,
|
||||
IFNULL (maus.user_num, 0) AS user_num
|
||||
from
|
||||
`multi_agent_main` AS ma
|
||||
left join agent_usage_stats AS maus ON ma.agent_id = maus.agent_id
|
||||
where
|
||||
ma.del_flag = '0';
|
||||
```
|
||||
|
||||
## 查客户端是否登录
|
||||
|
||||
```sql
|
||||
select
|
||||
*
|
||||
from
|
||||
`mis-cloud-claw`.`sys_logininfor`
|
||||
where
|
||||
client_key = (
|
||||
select
|
||||
client_key
|
||||
from
|
||||
`mis-cloud-claw`.`sys_client`
|
||||
where
|
||||
`client_id` = '客户端ID'
|
||||
);
|
||||
```
|
||||
|
||||
## 查智能体对话日志
|
||||
|
||||
1. 查询所有切片号,假设查询出来的`part`是[1,2]
|
||||
|
||||
```sql
|
||||
select part from log_agent_chat where del_flag = '0';
|
||||
```
|
||||
|
||||
2. 根据切片号查询并合并各个切片表的数据
|
||||
|
||||
```sql
|
||||
select * from log_agent_chat_1 where chat_window_id = 会话ID
|
||||
UNION ALL
|
||||
select * from log_agent_chat_2 where chat_window_id = 会话ID
|
||||
```
|
||||
|
||||
## 查智能体信息
|
||||
|
||||
必须提供**智能体ID**,在不明确用户查询的是单智能体还是多智能体时,友好的询问要查询哪种智能体。
|
||||
|
||||
1. 查询单智能体信息
|
||||
|
||||
```sql
|
||||
with agent_info AS (
|
||||
select
|
||||
agent_id,
|
||||
agent_name,
|
||||
system_prompt,
|
||||
`description`,
|
||||
max_messages,
|
||||
max_tokens,
|
||||
kb_uuids,
|
||||
kb_configs,
|
||||
kb_similarity_threshold,
|
||||
kb_top_k,
|
||||
kb_max_recall_toekn,
|
||||
llm_name,
|
||||
long_term_memory,
|
||||
case kb_mode when '1' then '直接检索' when '2' then 'tool检索' else '' end AS kb_mode,
|
||||
case kb_search_type when '0' then '向量检索' when '1' then '混合检索' when '2' then '智能检索' else '' end AS kb_search_type
|
||||
from mis-agent.agent
|
||||
where agent_id = <智能体ID>
|
||||
),
|
||||
agent_skill AS (
|
||||
select
|
||||
<智能体ID> AS agent_id,
|
||||
GROUP_CONCAT(skill_name) AS skill_names
|
||||
from mis-mcp.skill
|
||||
where skill_id in (
|
||||
select skill_id from mis-agent.agent_skill_mapping
|
||||
where agent_id = <智能体ID>
|
||||
)
|
||||
),
|
||||
agent_mcp_tool AS (
|
||||
select
|
||||
<智能体ID> AS agent_id,
|
||||
GROUP_CONCAT(tool_name) AS tool_names
|
||||
from mis-mcp.map_tools
|
||||
where mcp_server_uuid in (
|
||||
select mcp_server_uuid from mis-agent.agent_tool_mapping
|
||||
where relate_agent_id = <智能体ID>
|
||||
)
|
||||
)
|
||||
|
||||
select * from agent_info AS a
|
||||
left join agent_skill AS b on a.agent_id = b.agent_id
|
||||
left join agent_mcp_tool AS c on a.agent_id = c.agent_id
|
||||
```
|
||||
|
||||
2. 查询多智能体信息
|
||||
|
||||
```sql
|
||||
select * from mis-agent.agent_release_info where release_id in (
|
||||
select
|
||||
release_id
|
||||
from mis-agent.multi_agent_sub
|
||||
where main_agent_id = <智能体ID>
|
||||
)
|
||||
```
|
||||
|
||||
## 查智能体使用数据
|
||||
|
||||
必须提供**智能体ID**。
|
||||
|
||||
```sql
|
||||
select * from mis-agent.agent_usage_stats_daily where agent_id = <智能体ID> order by daily desc
|
||||
```
|
||||
|
||||
## 查项目统计数据
|
||||
|
||||
必须提供**项目名称**。
|
||||
|
||||
1. 查询项目注册表,判断是否包含该项目。用户提供的项目名称大概率是模糊的,比如"认证"、"ebiz",要根据语义判断究竟是哪一个,如果猜不准就询问一下用户是哪个。
|
||||
|
||||
```sql
|
||||
select * from mis-agent.project_stats_registry
|
||||
```
|
||||
|
||||
**重要:`project_stats_registry`里的`id`字段,称为项目ID,或者叫project_id,后面的步骤需要用到。**
|
||||
|
||||
2. 查询项目统计数据
|
||||
|
||||
```sql
|
||||
select * from mis-agent.project_data_stats_daily where project_id = <project_id>
|
||||
```
|
||||
|
||||
## 新增devco账号
|
||||
|
||||
用户的输入格式如下。
|
||||
|
||||
```text
|
||||
devco
|
||||
username1
|
||||
username2
|
||||
username3
|
||||
```
|
||||
|
||||
- 在用户的输入中,`devco`是触发d当前技能的关键词。
|
||||
- **从第二行开始,去掉空白行以后,每一个都是用户名。**如果用户提供的用户名存在重复,请忽略大小写保留1个即可。
|
||||
- `client_id`和`state`字段是固定值,用户名对应的是`account`字段。
|
||||
|
||||
**在`mis-dev`资源下的`mis-cloud-paw`库中执行**批量插入sql,示例:
|
||||
|
||||
```sql
|
||||
INSERT INTO external_login_client_account (client_id, account, state) VALUES
|
||||
('226c18408b5705449f37b621a432a6d3', 'username1', 1),
|
||||
('226c18408b5705449f37b621a432a6d3', 'username2', 1),
|
||||
('226c18408b5705449f37b621a432a6d3', 'username3', 1);
|
||||
```
|
||||
|
||||
## 查paw-agent信息
|
||||
|
||||
在`mis-dev`资源下,根据用户名(username)查询paw-agent信息,如果用户没有提供username,友好的提问要查哪个用户的,一个可用的username示例:`Agnes2.wang`。
|
||||
|
||||
1. 根据用户提供的`username`查询`user_id`,只会查出来1行数据,示例:
|
||||
|
||||
```sql
|
||||
select user_id from `mis-cloud-claw`.`sys_user` where user_name = '{username}';
|
||||
```
|
||||
|
||||
2. 根据`user_id`查询agent信息,可能返回多行数据,使用markdown表格的形式展示每一行的数据,示例:
|
||||
|
||||
```sql
|
||||
select
|
||||
agent_id,
|
||||
agent_mode,
|
||||
publish_status,
|
||||
publish_scope,
|
||||
published_at,
|
||||
version_lane,
|
||||
key_scope_default
|
||||
from
|
||||
`mis-paw-claw`.`agent`
|
||||
where
|
||||
create_by = < user_id >;
|
||||
```
|
||||
+203
@@ -0,0 +1,203 @@
|
||||
# 服务
|
||||
|
||||
| 服务名称 | 分支 | 描述 |
|
||||
| --- | --- | --- |
|
||||
| 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`;
|
||||
```
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
# 服务
|
||||
|
||||
| 服务名称 | 分支 | 描述 |
|
||||
| --- | --- | --- |
|
||||
| mis-debugging | qas_liushuang | SE智能体 |
|
||||
|
||||
## 新建的表
|
||||
|
||||
```sql
|
||||
CREATE TABLE `mis-debugging`.`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='工单表':
|
||||
```
|
||||
|
||||
## 集成Harness
|
||||
|
||||
### Nacos
|
||||
|
||||
参见`qas`环境的`se-harness-agent.yml`配置文件。
|
||||
|
||||
### 新建的表
|
||||
|
||||
从`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;
|
||||
```
|
||||
Reference in New Issue
Block a user