openclaw-weixin 3.0.2 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/CHANGELOG_EN.md +25 -0
- package/README.md +101 -50
- package/README_EN.md +113 -57
- package/dist/src/auth/accounts.js +313 -18
- package/dist/src/auth/accounts.js.map +1 -1
- package/dist/src/channel.js +106 -49
- package/dist/src/channel.js.map +1 -1
- package/dist/src/messaging/inbound.js +13 -8
- package/dist/src/messaging/inbound.js.map +1 -1
- package/dist/src/messaging/process-message.js +3 -2
- package/dist/src/messaging/process-message.js.map +1 -1
- package/dist/src/monitor/monitor.js +2 -0
- package/dist/src/monitor/monitor.js.map +1 -1
- package/docs/architecture.md +95 -103
- package/docs/architecture_EN.md +136 -0
- package/docs/backend-api.md +187 -196
- package/docs/backend-api_EN.md +347 -0
- package/docs/guide.md +45 -55
- package/docs/guide_EN.md +110 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +7 -7
- package/docs/backend-api.zh_CN.md +0 -338
- package/docs/guide.zh_CN.md +0 -99
package/docs/backend-api.md
CHANGED
|
@@ -1,64 +1,60 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 后端 API 协议
|
|
2
2
|
|
|
3
|
-
[
|
|
4
|
-
[简体中文](./backend-api.zh_CN.md)
|
|
3
|
+
[返回详细指南](./guide.md) | [English](./backend-api_EN.md)
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
post-login `baseurl` must implement the lifecycle, messaging, and media
|
|
10
|
-
endpoints.
|
|
5
|
+
本文档覆盖插件用于扫码登录、生命周期通知、消息和媒体的全部微信后端接口。两个扫码
|
|
6
|
+
登录请求始终使用腾讯固定服务;账号登录后 `baseurl` 指定的后端需要实现生命周期、
|
|
7
|
+
消息和媒体接口。
|
|
11
8
|
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
二维码创建和登录后的接口使用 `POST`;二维码状态轮询使用 `GET`。所有 API
|
|
10
|
+
请求均携带:
|
|
14
11
|
|
|
15
|
-
| Header |
|
|
16
|
-
|
|
17
|
-
| `iLink-App-Id` |
|
|
18
|
-
| `iLink-App-ClientVersion` |
|
|
19
|
-
| `SKRouteTag` |
|
|
12
|
+
| Header | 说明 |
|
|
13
|
+
|--------|------|
|
|
14
|
+
| `iLink-App-Id` | 插件应用 ID |
|
|
15
|
+
| `iLink-App-ClientVersion` | 编码为无符号整数的插件版本 |
|
|
16
|
+
| `SKRouteTag` | 可选的配置路由标签 |
|
|
20
17
|
|
|
21
|
-
`POST`
|
|
22
|
-
`AuthorizationType: ilink_bot_token
|
|
23
|
-
`X-WECHAT-UIN
|
|
24
|
-
`Authorization: Bearer <bot-token
|
|
25
|
-
|
|
18
|
+
`POST` 请求还会携带 `Content-Type: application/json`、
|
|
19
|
+
`AuthorizationType: ilink_bot_token` 和随机 uint32 的 base64 编码
|
|
20
|
+
`X-WECHAT-UIN`。登录后的鉴权请求还会携带
|
|
21
|
+
`Authorization: Bearer <bot-token>`;二维码状态 `GET` 请求不携带这些 `POST`
|
|
22
|
+
专用请求头。
|
|
26
23
|
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
登录后的 `POST` 请求体包含 `base_info`,二维码创建请求则不包含。下方消息示例
|
|
25
|
+
为简洁起见将其省略。
|
|
29
26
|
|
|
30
27
|
```json
|
|
31
28
|
{
|
|
32
29
|
"base_info": {
|
|
33
|
-
"channel_version": "
|
|
30
|
+
"channel_version": "<插件版本>",
|
|
34
31
|
"bot_agent": "OpenClaw"
|
|
35
32
|
}
|
|
36
33
|
}
|
|
37
34
|
```
|
|
38
35
|
|
|
39
|
-
`bot_agent`
|
|
40
|
-
|
|
36
|
+
`bot_agent` 仅用于观测,其格式和配置方式见
|
|
37
|
+
[详细指南](./guide.md#自定义-botagent可选)。
|
|
41
38
|
|
|
42
|
-
##
|
|
39
|
+
## 接口列表
|
|
43
40
|
|
|
44
|
-
|
|
|
45
|
-
|
|
46
|
-
| `POST` | `/ilink/bot/get_bot_qrcode?bot_type=3` |
|
|
47
|
-
| `GET` | `/ilink/bot/get_qrcode_status?qrcode=<opaque-id>` |
|
|
48
|
-
| `POST` | `/ilink/bot/msg/notifystart` |
|
|
49
|
-
| `POST` | `/ilink/bot/msg/notifystop` |
|
|
50
|
-
| `POST` | `/ilink/bot/getupdates` |
|
|
51
|
-
| `POST` | `/ilink/bot/sendmessage` |
|
|
52
|
-
| `POST` | `/ilink/bot/getuploadurl` |
|
|
53
|
-
| `POST` | `/ilink/bot/getconfig` |
|
|
54
|
-
| `POST` | `/ilink/bot/sendtyping` |
|
|
41
|
+
| 方法 | 路径 | 说明 |
|
|
42
|
+
|------|------|------|
|
|
43
|
+
| `POST` | `/ilink/bot/get_bot_qrcode?bot_type=3` | 创建扫码登录会话 |
|
|
44
|
+
| `GET` | `/ilink/bot/get_qrcode_status?qrcode=<opaque-id>` | 轮询扫码状态;可选传入 `verify_code` |
|
|
45
|
+
| `POST` | `/ilink/bot/msg/notifystart` | 通知后端 channel 已启动 |
|
|
46
|
+
| `POST` | `/ilink/bot/msg/notifystop` | 通知后端 channel 已停止 |
|
|
47
|
+
| `POST` | `/ilink/bot/getupdates` | 长轮询获取新消息 |
|
|
48
|
+
| `POST` | `/ilink/bot/sendmessage` | 发送消息(文本/图片/视频/文件) |
|
|
49
|
+
| `POST` | `/ilink/bot/getuploadurl` | 获取 CDN 上传预签名参数 |
|
|
50
|
+
| `POST` | `/ilink/bot/getconfig` | 获取账号配置(typing ticket 等) |
|
|
51
|
+
| `POST` | `/ilink/bot/sendtyping` | 发送或取消输入状态 |
|
|
55
52
|
|
|
56
|
-
|
|
57
|
-
account's post-login `baseurl`.
|
|
53
|
+
前两行描述固定的扫码登录服务,不会发送到账号登录后的 `baseurl`。
|
|
58
54
|
|
|
59
|
-
##
|
|
55
|
+
## 扫码登录与生命周期
|
|
60
56
|
|
|
61
|
-
|
|
57
|
+
创建扫码会话:
|
|
62
58
|
|
|
63
59
|
```http
|
|
64
60
|
POST /ilink/bot/get_bot_qrcode?bot_type=3
|
|
@@ -71,24 +67,23 @@ Content-Type: application/json
|
|
|
71
67
|
}
|
|
72
68
|
```
|
|
73
69
|
|
|
74
|
-
|
|
75
|
-
`qrcode_img_content
|
|
76
|
-
`GET /ilink/bot/get_qrcode_status?qrcode=<opaque-id
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
| `
|
|
83
|
-
| `
|
|
84
|
-
| `
|
|
85
|
-
| `
|
|
86
|
-
| `
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
`base_info` body and return:
|
|
70
|
+
响应包含不透明的 `qrcode` 标识,以及用于生成二维码的 URL
|
|
71
|
+
`qrcode_img_content`。随后轮询
|
|
72
|
+
`GET /ilink/bot/get_qrcode_status?qrcode=<opaque-id>`,直到进入终止状态。遇到
|
|
73
|
+
验证挑战时,可通过 `verify_code` 查询参数提交验证码。
|
|
74
|
+
|
|
75
|
+
| 字段 | 类型 | 说明 |
|
|
76
|
+
|------|------|------|
|
|
77
|
+
| `status` | `string` | `wait`、`scaned`、`need_verifycode`、`verify_code_blocked`、`expired`、`scaned_but_redirect`、`binded_redirect` 或 `confirmed` |
|
|
78
|
+
| `bot_token` | `string?` | 确认后返回的 bot 凭据 |
|
|
79
|
+
| `ilink_bot_id` | `string?` | 确认后必需的账号 ID |
|
|
80
|
+
| `baseurl` | `string?` | 账号 API 基础 URL |
|
|
81
|
+
| `ilink_user_id` | `string?` | 扫码用户 ID |
|
|
82
|
+
| `redirect_host` | `string?` | `scaned_but_redirect` 返回的新轮询主机 |
|
|
83
|
+
|
|
84
|
+
鉴权完成后,channel 启动时调用 `/ilink/bot/msg/notifystart`,停止时调用
|
|
85
|
+
`/ilink/bot/msg/notifystop`。两者均接收标准 `base_info` 请求体,并返回
|
|
86
|
+
以下结构:
|
|
92
87
|
|
|
93
88
|
```json
|
|
94
89
|
{
|
|
@@ -97,15 +92,14 @@ and `/ilink/bot/msg/notifystop` when it stops. Both receive the standard
|
|
|
97
92
|
}
|
|
98
93
|
```
|
|
99
94
|
|
|
100
|
-
|
|
101
|
-
|
|
95
|
+
二维码标识、验证码、bot token、账号 ID、用户 ID 和 context token 均属敏感
|
|
96
|
+
信息,不要在日志或示例中写入真实值。
|
|
102
97
|
|
|
103
98
|
## getUpdates
|
|
104
99
|
|
|
105
|
-
|
|
106
|
-
timeout.
|
|
100
|
+
长轮询接口。服务端在有新消息或超时后返回。
|
|
107
101
|
|
|
108
|
-
|
|
102
|
+
**请求体:**
|
|
109
103
|
|
|
110
104
|
```json
|
|
111
105
|
{
|
|
@@ -113,52 +107,52 @@ timeout.
|
|
|
113
107
|
}
|
|
114
108
|
```
|
|
115
109
|
|
|
116
|
-
|
|
|
117
|
-
|
|
118
|
-
| `get_updates_buf` | `string` |
|
|
110
|
+
| 字段 | 类型 | 说明 |
|
|
111
|
+
|------|------|------|
|
|
112
|
+
| `get_updates_buf` | `string` | 上次响应返回的同步游标,首次请求传空字符串 |
|
|
119
113
|
|
|
120
|
-
|
|
114
|
+
**响应体:**
|
|
121
115
|
|
|
122
116
|
```json
|
|
123
117
|
{
|
|
124
118
|
"ret": 0,
|
|
125
119
|
"msgs": [],
|
|
126
|
-
"get_updates_buf": "
|
|
120
|
+
"get_updates_buf": "<新游标>",
|
|
127
121
|
"longpolling_timeout_ms": 35000
|
|
128
122
|
}
|
|
129
123
|
```
|
|
130
124
|
|
|
131
|
-
|
|
|
132
|
-
|
|
133
|
-
| `ret` | `number` |
|
|
134
|
-
| `errcode` | `number?` |
|
|
135
|
-
| `errmsg` | `string?` |
|
|
136
|
-
| `msgs` | `WeixinMessage[]` |
|
|
137
|
-
| `get_updates_buf` | `string` |
|
|
138
|
-
| `longpolling_timeout_ms` | `number?` |
|
|
125
|
+
| 字段 | 类型 | 说明 |
|
|
126
|
+
|------|------|------|
|
|
127
|
+
| `ret` | `number` | 返回码,`0` = 成功 |
|
|
128
|
+
| `errcode` | `number?` | 错误码(如 `-14` = token 失效) |
|
|
129
|
+
| `errmsg` | `string?` | 错误描述 |
|
|
130
|
+
| `msgs` | `WeixinMessage[]` | 消息列表(结构见下方) |
|
|
131
|
+
| `get_updates_buf` | `string` | 新的同步游标,下次请求时回传 |
|
|
132
|
+
| `longpolling_timeout_ms` | `number?` | 服务端建议的下次长轮询超时(ms) |
|
|
139
133
|
|
|
140
134
|
## sendMessage
|
|
141
135
|
|
|
142
|
-
|
|
136
|
+
发送一条消息给用户。
|
|
143
137
|
|
|
144
|
-
|
|
138
|
+
**请求体:**
|
|
145
139
|
|
|
146
140
|
```json
|
|
147
141
|
{
|
|
148
142
|
"msg": {
|
|
149
|
-
"to_user_id": "
|
|
150
|
-
"context_token": "
|
|
143
|
+
"to_user_id": "<目标用户 ID>",
|
|
144
|
+
"context_token": "<会话上下文令牌>",
|
|
151
145
|
"item_list": [
|
|
152
146
|
{
|
|
153
147
|
"type": 1,
|
|
154
|
-
"text_item": { "text": "
|
|
148
|
+
"text_item": { "text": "你好" }
|
|
155
149
|
}
|
|
156
150
|
]
|
|
157
151
|
}
|
|
158
152
|
}
|
|
159
153
|
```
|
|
160
154
|
|
|
161
|
-
|
|
155
|
+
**响应体:**
|
|
162
156
|
|
|
163
157
|
```json
|
|
164
158
|
{
|
|
@@ -169,96 +163,96 @@ Send a message to a user.
|
|
|
169
163
|
|
|
170
164
|
## getUploadUrl
|
|
171
165
|
|
|
172
|
-
|
|
173
|
-
|
|
166
|
+
获取 CDN 上传预签名参数。上传文件前需先调用此接口获取 `upload_param` 和
|
|
167
|
+
`thumb_upload_param`。
|
|
174
168
|
|
|
175
|
-
|
|
169
|
+
**请求体:**
|
|
176
170
|
|
|
177
171
|
```json
|
|
178
172
|
{
|
|
179
|
-
"filekey": "
|
|
173
|
+
"filekey": "<文件标识>",
|
|
180
174
|
"media_type": 1,
|
|
181
|
-
"to_user_id": "
|
|
175
|
+
"to_user_id": "<目标用户 ID>",
|
|
182
176
|
"rawsize": 12345,
|
|
183
|
-
"rawfilemd5": "
|
|
177
|
+
"rawfilemd5": "<明文 MD5>",
|
|
184
178
|
"filesize": 12352,
|
|
185
179
|
"no_need_thumb": true,
|
|
186
|
-
"aeskey": "<32
|
|
180
|
+
"aeskey": "<32 位十六进制 AES 密钥>"
|
|
187
181
|
}
|
|
188
182
|
```
|
|
189
183
|
|
|
190
|
-
|
|
|
191
|
-
|
|
192
|
-
| `filekey` | `string` |
|
|
193
|
-
| `media_type` | `number` | `1` = IMAGE
|
|
194
|
-
| `to_user_id` | `string` |
|
|
195
|
-
| `rawsize` | `number` |
|
|
196
|
-
| `rawfilemd5` | `string` |
|
|
197
|
-
| `filesize` | `number` |
|
|
198
|
-
| `no_need_thumb` | `boolean?` |
|
|
199
|
-
| `aeskey` | `string?` | AES-128
|
|
200
|
-
| `thumb_rawsize` | `number?` |
|
|
201
|
-
| `thumb_rawfilemd5` | `string?` |
|
|
202
|
-
| `thumb_filesize` | `number?` |
|
|
203
|
-
|
|
204
|
-
|
|
184
|
+
| 字段 | 类型 | 说明 |
|
|
185
|
+
|------|------|------|
|
|
186
|
+
| `filekey` | `string` | 本次上传的文件标识 |
|
|
187
|
+
| `media_type` | `number` | `1` = IMAGE、`2` = VIDEO、`3` = FILE、`4` = VOICE |
|
|
188
|
+
| `to_user_id` | `string` | 目标用户 ID |
|
|
189
|
+
| `rawsize` | `number` | 原文件明文大小 |
|
|
190
|
+
| `rawfilemd5` | `string` | 原文件明文 MD5 |
|
|
191
|
+
| `filesize` | `number` | AES-128-ECB 加密后的密文大小 |
|
|
192
|
+
| `no_need_thumb` | `boolean?` | 设为 `true` 时不请求缩略图上传参数 |
|
|
193
|
+
| `aeskey` | `string?` | 32 位十六进制 AES-128 密钥 |
|
|
194
|
+
| `thumb_rawsize` | `number?` | 请求缩略图时的明文大小 |
|
|
195
|
+
| `thumb_rawfilemd5` | `string?` | 请求缩略图时的明文 MD5 |
|
|
196
|
+
| `thumb_filesize` | `number?` | 请求缩略图时的密文大小 |
|
|
197
|
+
|
|
198
|
+
**响应体:**
|
|
205
199
|
|
|
206
200
|
```json
|
|
207
201
|
{
|
|
208
|
-
"upload_param": "
|
|
202
|
+
"upload_param": "<原图上传加密参数>",
|
|
209
203
|
"upload_full_url": "https://cdn.example.test/upload",
|
|
210
|
-
"thumb_upload_param": "
|
|
204
|
+
"thumb_upload_param": "<可选的缩略图上传参数>"
|
|
211
205
|
}
|
|
212
206
|
```
|
|
213
207
|
|
|
214
|
-
|
|
|
215
|
-
|
|
216
|
-
| `upload_param` | `string?` |
|
|
217
|
-
| `upload_full_url` | `string?` |
|
|
218
|
-
| `thumb_upload_param` | `string?` |
|
|
208
|
+
| 字段 | 类型 | 说明 |
|
|
209
|
+
|------|------|------|
|
|
210
|
+
| `upload_param` | `string?` | 用于构造 CDN 上传 URL 的参数 |
|
|
211
|
+
| `upload_full_url` | `string?` | 完整 CDN 上传 URL;优先于 `upload_param` |
|
|
212
|
+
| `thumb_upload_param` | `string?` | 可选的缩略图上传参数 |
|
|
219
213
|
|
|
220
214
|
## getConfig
|
|
221
215
|
|
|
222
|
-
|
|
216
|
+
获取账号配置,包括 typing ticket。
|
|
223
217
|
|
|
224
|
-
|
|
218
|
+
**请求体:**
|
|
225
219
|
|
|
226
220
|
```json
|
|
227
221
|
{
|
|
228
|
-
"ilink_user_id": "
|
|
229
|
-
"context_token": "
|
|
222
|
+
"ilink_user_id": "<用户 ID>",
|
|
223
|
+
"context_token": "<可选,会话上下文令牌>"
|
|
230
224
|
}
|
|
231
225
|
```
|
|
232
226
|
|
|
233
|
-
|
|
227
|
+
**响应体:**
|
|
234
228
|
|
|
235
229
|
```json
|
|
236
230
|
{
|
|
237
231
|
"ret": 0,
|
|
238
232
|
"errmsg": "",
|
|
239
|
-
"typing_ticket": "<base64
|
|
233
|
+
"typing_ticket": "<base64 编码的 typing ticket>"
|
|
240
234
|
}
|
|
241
235
|
```
|
|
242
236
|
|
|
243
237
|
## sendTyping
|
|
244
238
|
|
|
245
|
-
|
|
239
|
+
发送或取消输入状态指示。
|
|
246
240
|
|
|
247
|
-
|
|
241
|
+
**请求体:**
|
|
248
242
|
|
|
249
243
|
```json
|
|
250
244
|
{
|
|
251
|
-
"ilink_user_id": "
|
|
252
|
-
"typing_ticket": "
|
|
245
|
+
"ilink_user_id": "<用户 ID>",
|
|
246
|
+
"typing_ticket": "<从 getConfig 获取>",
|
|
253
247
|
"status": 1
|
|
254
248
|
}
|
|
255
249
|
```
|
|
256
250
|
|
|
257
|
-
|
|
|
258
|
-
|
|
259
|
-
| `status` | `number` | `1` =
|
|
251
|
+
| 字段 | 类型 | 说明 |
|
|
252
|
+
|------|------|------|
|
|
253
|
+
| `status` | `number` | `1` = 正在输入,`2` = 取消输入 |
|
|
260
254
|
|
|
261
|
-
|
|
255
|
+
**响应体:**
|
|
262
256
|
|
|
263
257
|
```json
|
|
264
258
|
{
|
|
@@ -267,81 +261,78 @@ Send or cancel the typing status indicator.
|
|
|
267
261
|
}
|
|
268
262
|
```
|
|
269
263
|
|
|
270
|
-
##
|
|
264
|
+
## 消息结构
|
|
271
265
|
|
|
272
266
|
### WeixinMessage
|
|
273
267
|
|
|
274
|
-
|
|
|
275
|
-
|
|
276
|
-
| `seq` | `number?` |
|
|
277
|
-
| `message_id` | `number?` |
|
|
278
|
-
| `from_user_id` | `string?` |
|
|
279
|
-
| `to_user_id` | `string?` |
|
|
280
|
-
| `client_id` | `string?` |
|
|
281
|
-
| `create_time_ms` | `number?` |
|
|
282
|
-
| `update_time_ms` | `number?` |
|
|
283
|
-
| `delete_time_ms` | `number?` |
|
|
284
|
-
| `session_id` | `string?` |
|
|
285
|
-
| `group_id` | `string?` |
|
|
268
|
+
| 字段 | 类型 | 说明 |
|
|
269
|
+
|------|------|------|
|
|
270
|
+
| `seq` | `number?` | 消息序列号 |
|
|
271
|
+
| `message_id` | `number?` | 消息唯一 ID |
|
|
272
|
+
| `from_user_id` | `string?` | 发送者 ID |
|
|
273
|
+
| `to_user_id` | `string?` | 接收者 ID |
|
|
274
|
+
| `client_id` | `string?` | 客户端生成的消息 ID |
|
|
275
|
+
| `create_time_ms` | `number?` | 创建时间戳(ms) |
|
|
276
|
+
| `update_time_ms` | `number?` | 更新时间戳(ms) |
|
|
277
|
+
| `delete_time_ms` | `number?` | 删除时间戳(ms) |
|
|
278
|
+
| `session_id` | `string?` | 会话 ID |
|
|
279
|
+
| `group_id` | `string?` | 群组 ID |
|
|
286
280
|
| `message_type` | `number?` | `1` = USER, `2` = BOT |
|
|
287
281
|
| `message_state` | `number?` | `0` = NEW, `1` = GENERATING, `2` = FINISH |
|
|
288
|
-
| `item_list` | `MessageItem[]?` |
|
|
289
|
-
| `context_token` | `string?` |
|
|
290
|
-
| `run_id` | `string?` | OpenClaw run ID
|
|
282
|
+
| `item_list` | `MessageItem[]?` | 消息内容列表 |
|
|
283
|
+
| `context_token` | `string?` | 会话上下文令牌,回复时需回传 |
|
|
284
|
+
| `run_id` | `string?` | 生成回复对应的 OpenClaw run ID |
|
|
291
285
|
|
|
292
286
|
### MessageItem
|
|
293
287
|
|
|
294
|
-
|
|
|
295
|
-
|
|
296
|
-
| `type` | `number` | `1` TEXT
|
|
297
|
-
| `create_time_ms` | `number?` |
|
|
298
|
-
| `update_time_ms` | `number?` |
|
|
299
|
-
| `is_completed` | `boolean?` |
|
|
300
|
-
| `msg_id` | `string?` |
|
|
301
|
-
| `text_item` | `{ text: string }?` |
|
|
302
|
-
| `image_item` | `ImageItem?` |
|
|
303
|
-
| `voice_item` | `VoiceItem?` |
|
|
304
|
-
| `file_item` | `FileItem?` |
|
|
305
|
-
| `video_item` | `VideoItem?` |
|
|
306
|
-
| `ref_msg` | `RefMessage?` |
|
|
307
|
-
| `tool_call_start_item` | `{ tool_name?: string; tool_call_id?: string }?` |
|
|
308
|
-
| `tool_call_result_item` | `{ tool_name?: string; tool_call_id?: string; status?: string }?` |
|
|
309
|
-
|
|
310
|
-
###
|
|
311
|
-
|
|
312
|
-
|
|
|
313
|
-
|
|
314
|
-
| `RefMessage` | `message_item?: MessageItem
|
|
315
|
-
| `ImageItem` | `media?: CDNMedia
|
|
316
|
-
| `VoiceItem` | `media?: CDNMedia
|
|
317
|
-
| `FileItem` | `media?: CDNMedia
|
|
318
|
-
| `VideoItem` | `media?: CDNMedia
|
|
319
|
-
| `ToolCallStartItem` | `tool_name?: string
|
|
320
|
-
| `ToolCallResultItem` | `tool_name?: string
|
|
321
|
-
|
|
322
|
-
### CDN
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
| `
|
|
330
|
-
| `
|
|
331
|
-
| `
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
`
|
|
344
|
-
|
|
345
|
-
6. Read `x-encrypted-param` from the CDN response and use it as
|
|
346
|
-
`encrypt_query_param` in the `CDNMedia` reference
|
|
347
|
-
7. Include the reference in the `MessageItem` and send
|
|
288
|
+
| 字段 | 类型 | 说明 |
|
|
289
|
+
|------|------|------|
|
|
290
|
+
| `type` | `number` | `1` TEXT、`2` IMAGE、`3` VOICE、`4` FILE、`5` VIDEO、`11` TOOL_CALL_START、`12` TOOL_CALL_RESULT |
|
|
291
|
+
| `create_time_ms` | `number?` | 条目创建时间戳 |
|
|
292
|
+
| `update_time_ms` | `number?` | 条目更新时间戳 |
|
|
293
|
+
| `is_completed` | `boolean?` | 进度条目是否完成 |
|
|
294
|
+
| `msg_id` | `string?` | 条目消息 ID |
|
|
295
|
+
| `text_item` | `{ text: string }?` | 文本内容 |
|
|
296
|
+
| `image_item` | `ImageItem?` | 图片(含 CDN 引用和 AES 密钥) |
|
|
297
|
+
| `voice_item` | `VoiceItem?` | 语音(SILK 编码) |
|
|
298
|
+
| `file_item` | `FileItem?` | 文件附件 |
|
|
299
|
+
| `video_item` | `VideoItem?` | 视频 |
|
|
300
|
+
| `ref_msg` | `RefMessage?` | 引用消息 |
|
|
301
|
+
| `tool_call_start_item` | `{ tool_name?: string; tool_call_id?: string }?` | 工具调用信息 |
|
|
302
|
+
| `tool_call_result_item` | `{ tool_name?: string; tool_call_id?: string; status?: string }?` | 工具完成信息 |
|
|
303
|
+
|
|
304
|
+
### 嵌套条目结构
|
|
305
|
+
|
|
306
|
+
| 结构 | 字段 |
|
|
307
|
+
|------|------|
|
|
308
|
+
| `RefMessage` | `message_item?: MessageItem`、`title?: string` |
|
|
309
|
+
| `ImageItem` | `media?: CDNMedia`、`thumb_media?: CDNMedia`、`aeskey?: string`、`url?: string`、`mid_size?: number`、`thumb_size?: number`、`thumb_height?: number`、`thumb_width?: number`、`hd_size?: number` |
|
|
310
|
+
| `VoiceItem` | `media?: CDNMedia`、`encode_type?: number`、`bits_per_sample?: number`、`sample_rate?: number`、`playtime?: number`、`text?: string` |
|
|
311
|
+
| `FileItem` | `media?: CDNMedia`、`file_name?: string`、`md5?: string`、`len?: string` |
|
|
312
|
+
| `VideoItem` | `media?: CDNMedia`、`video_size?: number`、`play_length?: number`、`video_md5?: string`、`thumb_media?: CDNMedia`、`thumb_size?: number`、`thumb_height?: number`、`thumb_width?: number` |
|
|
313
|
+
| `ToolCallStartItem` | `tool_name?: string`、`tool_call_id?: string` |
|
|
314
|
+
| `ToolCallResultItem` | `tool_name?: string`、`tool_call_id?: string`、`status?: string` |
|
|
315
|
+
|
|
316
|
+
### CDN 媒体引用 (CDNMedia)
|
|
317
|
+
|
|
318
|
+
所有媒体类型(图片/语音/文件/视频)通过 CDN 传输,使用 AES-128-ECB 加密:
|
|
319
|
+
|
|
320
|
+
| 字段 | 类型 | 说明 |
|
|
321
|
+
|------|------|------|
|
|
322
|
+
| `encrypt_query_param` | `string?` | CDN 下载/上传的加密参数 |
|
|
323
|
+
| `aes_key` | `string?` | base64 编码的 AES-128 密钥 |
|
|
324
|
+
| `encrypt_type` | `number?` | 加密元数据模式 |
|
|
325
|
+
| `full_url` | `string?` | 后端返回的完整下载 URL |
|
|
326
|
+
|
|
327
|
+
## CDN 上传流程
|
|
328
|
+
|
|
329
|
+
1. 计算文件明文大小、MD5,以及 AES-128-ECB 加密后的密文大小
|
|
330
|
+
2. 如需缩略图(图片/视频),同样计算缩略图的明文和密文参数
|
|
331
|
+
3. 调用 `getUploadUrl` 获取 `upload_full_url` 或 `upload_param`(以及可选的
|
|
332
|
+
`thumb_upload_param`)
|
|
333
|
+
4. 使用 AES-128-ECB 加密文件内容,以 `application/octet-stream` 通过 `POST`
|
|
334
|
+
上传到 CDN URL
|
|
335
|
+
5. 需要缩略图时,同理加密并上传
|
|
336
|
+
6. 从 CDN 响应读取 `x-encrypted-param`,作为 `CDNMedia` 引用中的
|
|
337
|
+
`encrypt_query_param`
|
|
338
|
+
7. 将引用放入 `MessageItem` 后发送
|