ylib-openclaw-weixin 2.1.7
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 +53 -0
- package/CHANGELOG.zh_CN.md +53 -0
- package/LICENSE +27 -0
- package/README.md +312 -0
- package/README.zh_CN.md +311 -0
- package/index.ts +377 -0
- package/openclaw.plugin.json +12 -0
- package/package.json +59 -0
- package/src/api/api.ts +344 -0
- package/src/api/config-cache.ts +79 -0
- package/src/api/session-guard.ts +58 -0
- package/src/api/types.ts +226 -0
- package/src/auth/accounts.ts +383 -0
- package/src/auth/login-qr.ts +482 -0
- package/src/auth/pairing.ts +120 -0
- package/src/cdn/aes-ecb.ts +21 -0
- package/src/cdn/cdn-upload.ts +87 -0
- package/src/cdn/cdn-url.ts +20 -0
- package/src/cdn/pic-decrypt.ts +101 -0
- package/src/cdn/upload.ts +157 -0
- package/src/channel.ts +569 -0
- package/src/compat.ts +77 -0
- package/src/config/config-schema.ts +42 -0
- package/src/media/media-download.ts +149 -0
- package/src/media/mime.ts +76 -0
- package/src/media/silk-transcode.ts +74 -0
- package/src/messaging/debug-mode.ts +69 -0
- package/src/messaging/endpoint-dispatch.ts +905 -0
- package/src/messaging/error-notice.ts +30 -0
- package/src/messaging/inbound.ts +262 -0
- package/src/messaging/markdown-filter.ts +391 -0
- package/src/messaging/process-message.ts +629 -0
- package/src/messaging/send-media.ts +72 -0
- package/src/messaging/send.ts +241 -0
- package/src/messaging/slash-commands.ts +110 -0
- package/src/monitor/monitor.ts +222 -0
- package/src/runtime.ts +70 -0
- package/src/storage/state-dir.ts +11 -0
- package/src/storage/sync-buf.ts +81 -0
- package/src/util/logger.ts +161 -0
- package/src/util/random.ts +17 -0
- package/src/util/redact.ts +54 -0
- package/src/vendor.d.ts +25 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
[简体中文](CHANGELOG.zh_CN.md)
|
|
4
|
+
|
|
5
|
+
This project follows the [Keep a Changelog](https://keepachangelog.com/) format.
|
|
6
|
+
|
|
7
|
+
## [2.1.7] - 2026-04-07
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **Plugin registration re-entrance:** Lazy-import `monitorWeixinProvider` inside `startAccount` in `channel.ts` to avoid pulling in the monitor → process-message → command-auth chain at plugin registration time, which could re-enter the plugin/provider registry before the account starts.
|
|
12
|
+
- **Initialization side effect:** Lazy-import `resolveSenderCommandAuthorizationWithRuntime` / `resolveDirectDmAuthorizationOutcome` in `process-message.ts` to prevent `ensureContextWindowCacheLoaded` from being triggered during module initialization, which caused `loadOpenClawPlugins` re-entrance.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- **Tool-call outbound path:** `sendWeixinOutbound` now applies `StreamingMarkdownFilter` to the outbound text, consistent with the model-output path in `process-message`.
|
|
17
|
+
|
|
18
|
+
## [2.1.4] - 2026-04-03
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- **QR login:** Remove client-side timeout for `get_bot_qrcode`; the request is no longer aborted on a fixed deadline (server / stack limits still apply).
|
|
23
|
+
|
|
24
|
+
## [2.1.3] - 2026-04-02
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
|
|
28
|
+
- **`StreamingMarkdownFilter`** (`src/messaging/markdown-filter.ts`): outbound text no longer runs through whole-string `markdownToPlainText` stripping; a streaming character filter replaces it, so Markdown goes from **effectively unsupported** to **partially supported**.
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
- **Outbound text path:** `process-message` uses `StreamingMarkdownFilter` (`feed` / `flush`) per deliver chunk instead of `markdownToPlainText`.
|
|
33
|
+
|
|
34
|
+
### Removed
|
|
35
|
+
|
|
36
|
+
- **`markdownToPlainText`** from `src/messaging/send.ts` (and its tests from `send.test.ts`); coverage moves to `markdown-filter.test.ts`.
|
|
37
|
+
|
|
38
|
+
## [2.1.2] - 2026-04-02
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
|
|
42
|
+
- **Config reload after login:** On each successful Weixin login, bump `channels.openclaw-weixin.channelConfigUpdatedAt` (ISO 8601) in `openclaw.json` so the gateway reloads config from disk, instead of writing an empty `accounts: {}` placeholder.
|
|
43
|
+
- **QR login:** Increase client timeout for `get_bot_qrcode` from 5s to 10s.
|
|
44
|
+
- **Docs:** Uninstall instructions now use `openclaw plugins uninstall @tencent-weixin/openclaw-weixin` (aligned with the plugins CLI).
|
|
45
|
+
- **Logging:** `debug-check` log line no longer includes `stateDir` / `OPENCLAW_STATE_DIR`.
|
|
46
|
+
|
|
47
|
+
### Removed
|
|
48
|
+
|
|
49
|
+
- **`openclaw-weixin` CLI subcommands** (`src/weixin-cli.ts` and registration in `index.ts`). Use the host `openclaw plugins uninstall …` flow instead.
|
|
50
|
+
|
|
51
|
+
### Fixed
|
|
52
|
+
|
|
53
|
+
- Resolves the **dangerous code pattern** warning when installing the plugin on **OpenClaw 2026.3.31+** (host plugin install / static checks).
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# 变更日志
|
|
2
|
+
|
|
3
|
+
[English](CHANGELOG.md)
|
|
4
|
+
|
|
5
|
+
本项目遵循 [Keep a Changelog](https://keepachangelog.com/) 格式。
|
|
6
|
+
|
|
7
|
+
## [2.1.7] - 2026-04-07
|
|
8
|
+
|
|
9
|
+
### 修复
|
|
10
|
+
|
|
11
|
+
- **插件注册重入:** `channel.ts` 中将 `monitorWeixinProvider` 改为在 `startAccount` 内部懒加载(`await import(...)`),避免插件注册阶段提前拉取 monitor → process-message → command-auth 依赖链,导致 plugin/provider registry 重入。
|
|
12
|
+
- **初始化副作用:** `process-message.ts` 中将 `resolveSenderCommandAuthorizationWithRuntime` / `resolveDirectDmAuthorizationOutcome` 改为懒加载,避免模块初始化时触发宿主的 `ensureContextWindowCacheLoaded` 副作用,进而导致 `loadOpenClawPlugins` 重入。
|
|
13
|
+
|
|
14
|
+
### 变更
|
|
15
|
+
|
|
16
|
+
- **tool-call 外发路径:** `sendWeixinOutbound` 现在对发送文本应用 `StreamingMarkdownFilter`,与 `process-message` 中的 model-output 路径保持一致。
|
|
17
|
+
|
|
18
|
+
## [2.1.4] - 2026-04-03
|
|
19
|
+
|
|
20
|
+
### 变更
|
|
21
|
+
|
|
22
|
+
- **扫码登录:** 移除 `get_bot_qrcode` 的客户端超时,请求不再因固定时限被 abort(仍受服务端与网络栈限制)。
|
|
23
|
+
|
|
24
|
+
## [2.1.3] - 2026-04-02
|
|
25
|
+
|
|
26
|
+
### 新增
|
|
27
|
+
|
|
28
|
+
- **`StreamingMarkdownFilter`**(`src/messaging/markdown-filter.ts`):外发文本由原先 `markdownToPlainText` 整段剥离 Markdown,改为流式逐字符过滤;**对 Markdown 从完全不支持变为部分支持**。
|
|
29
|
+
|
|
30
|
+
### 变更
|
|
31
|
+
|
|
32
|
+
- **外发文本:** `process-message` 在每次 `deliver` 时用 `StreamingMarkdownFilter`(`feed` / `flush`)处理回复,替代 `markdownToPlainText`。
|
|
33
|
+
|
|
34
|
+
### 移除
|
|
35
|
+
|
|
36
|
+
- 从 `src/messaging/send.ts` 删除 **`markdownToPlainText`**(相关用例从 `send.test.ts` 迁至 `markdown-filter.test.ts`)。
|
|
37
|
+
|
|
38
|
+
## [2.1.2] - 2026-04-02
|
|
39
|
+
|
|
40
|
+
### 变更
|
|
41
|
+
|
|
42
|
+
- **登录后配置刷新:** 每次微信登录成功后,在 `openclaw.json` 中更新 `channels.openclaw-weixin.channelConfigUpdatedAt`(ISO 8601),让网关从磁盘重新加载配置;不再写入空的 `accounts: {}` 占位。
|
|
43
|
+
- **扫码登录:** `get_bot_qrcode` 客户端超时由 5s 调整为 10s。
|
|
44
|
+
- **文档:** 卸载说明改为使用 `openclaw plugins uninstall @tencent-weixin/openclaw-weixin`,与插件 CLI 一致。
|
|
45
|
+
- **日志:** `debug-check` 日志不再输出 `stateDir` / `OPENCLAW_STATE_DIR`。
|
|
46
|
+
|
|
47
|
+
### 移除
|
|
48
|
+
|
|
49
|
+
- **`openclaw-weixin` 子命令**(删除 `src/weixin-cli.ts` 及 `index.ts` 中的注册)。请使用宿主自带的 `openclaw plugins uninstall …` 卸载流程。
|
|
50
|
+
|
|
51
|
+
### 修复
|
|
52
|
+
|
|
53
|
+
- 解决在 **OpenClaw 2026.3.31 及更新版本**上安装插件时出现的 **dangerous code pattern** 提示(宿主插件安装 / 静态检查)。
|
package/LICENSE
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Tencent is pleased to support the open source community by making openclaw-weixin available.
|
|
2
|
+
|
|
3
|
+
Copyright (C) 2026 Tencent. All rights reserved.
|
|
4
|
+
|
|
5
|
+
openclaw-weixin is licensed under the MIT.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
Terms of the MIT:
|
|
9
|
+
--------------------------------------------------------------------
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
11
|
+
a copy of this software and associated documentation files (the
|
|
12
|
+
"Software"), to deal in the Software without restriction, including
|
|
13
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
14
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
15
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
16
|
+
the following conditions:
|
|
17
|
+
|
|
18
|
+
The above copyright notice and this permission notice shall be
|
|
19
|
+
included in all copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
22
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
23
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
24
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
25
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
26
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
27
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
# WeChat
|
|
2
|
+
|
|
3
|
+
[简体中文](./README.zh_CN.md)
|
|
4
|
+
|
|
5
|
+
OpenClaw's WeChat channel plugin, supporting login authorization via QR code scanning.
|
|
6
|
+
|
|
7
|
+
## Compatibility
|
|
8
|
+
|
|
9
|
+
| Plugin Version | OpenClaw Version | npm dist-tag | Status |
|
|
10
|
+
|---------------|------------------------|--------------|-------------|
|
|
11
|
+
| 2.0.x | >=2026.3.22 | `latest` | Active |
|
|
12
|
+
| 1.0.x | >=2026.1.0 <2026.3.22 | `legacy` | Maintenance |
|
|
13
|
+
|
|
14
|
+
> The plugin checks the host version at startup and will refuse to load if the
|
|
15
|
+
> running OpenClaw version is outside the supported range.
|
|
16
|
+
|
|
17
|
+
## Prerequisites
|
|
18
|
+
|
|
19
|
+
[OpenClaw](https://docs.openclaw.ai/install) must be installed (the `openclaw` CLI needs to be available).
|
|
20
|
+
|
|
21
|
+
Check your version: `openclaw --version`
|
|
22
|
+
|
|
23
|
+
## Quick Install
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npx -y @tencent-weixin/openclaw-weixin-cli install
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Manual Installation
|
|
30
|
+
|
|
31
|
+
If the quick install doesn't work, follow these steps manually:
|
|
32
|
+
|
|
33
|
+
### 1. Install the plugin
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
openclaw plugins install "@tencent-weixin/openclaw-weixin"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 2. Enable the plugin
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
openclaw config set plugins.entries.openclaw-weixin.enabled true
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 3. QR code login
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
openclaw channels login --channel openclaw-weixin
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
A QR code will appear in the terminal. Scan it with your phone and confirm the authorization. Once confirmed, the login credentials will be saved locally automatically — no further action is needed.
|
|
52
|
+
|
|
53
|
+
### 4. Restart the gateway
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
openclaw gateway restart
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Adding More WeChat Accounts
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
openclaw channels login --channel openclaw-weixin
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Each QR code login creates a new account entry, supporting multiple WeChat accounts online simultaneously.
|
|
66
|
+
|
|
67
|
+
## Multi-Account Context Isolation
|
|
68
|
+
|
|
69
|
+
By default, DMs can share one session bucket. For **multiple logged-in WeChat accounts**, isolate by account + channel + sender:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
openclaw config set session.dmScope per-account-channel-peer
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Backend API Protocol
|
|
76
|
+
|
|
77
|
+
This plugin communicates with the backend gateway via HTTP JSON API. Developers integrating with their own backend need to implement the following interfaces.
|
|
78
|
+
|
|
79
|
+
All endpoints use `POST` with JSON request and response bodies. Common request headers:
|
|
80
|
+
|
|
81
|
+
| Header | Description |
|
|
82
|
+
|--------|-------------|
|
|
83
|
+
| `Content-Type` | `application/json` |
|
|
84
|
+
| `AuthorizationType` | Fixed value `ilink_bot_token` |
|
|
85
|
+
| `Authorization` | `Bearer <token>` (obtained after login) |
|
|
86
|
+
| `X-WECHAT-UIN` | Base64-encoded random uint32 |
|
|
87
|
+
|
|
88
|
+
### Endpoint List
|
|
89
|
+
|
|
90
|
+
| Endpoint | Path | Description |
|
|
91
|
+
|----------|------|-------------|
|
|
92
|
+
| getUpdates | `getupdates` | Long-poll for new messages |
|
|
93
|
+
| sendMessage | `sendmessage` | Send a message (text/image/video/file) |
|
|
94
|
+
| getUploadUrl | `getuploadurl` | Get CDN upload pre-signed URL |
|
|
95
|
+
| getConfig | `getconfig` | Get account config (typing ticket, etc.) |
|
|
96
|
+
| sendTyping | `sendtyping` | Send/cancel typing status indicator |
|
|
97
|
+
|
|
98
|
+
### getUpdates
|
|
99
|
+
|
|
100
|
+
Long-polling endpoint. The server responds when new messages arrive or on timeout.
|
|
101
|
+
|
|
102
|
+
**Request body:**
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"get_updates_buf": ""
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
| Field | Type | Description |
|
|
111
|
+
|-------|------|-------------|
|
|
112
|
+
| `get_updates_buf` | `string` | Sync cursor from the previous response; empty string for the first request |
|
|
113
|
+
|
|
114
|
+
**Response body:**
|
|
115
|
+
|
|
116
|
+
```json
|
|
117
|
+
{
|
|
118
|
+
"ret": 0,
|
|
119
|
+
"msgs": [...],
|
|
120
|
+
"get_updates_buf": "<new cursor>",
|
|
121
|
+
"longpolling_timeout_ms": 35000
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
| Field | Type | Description |
|
|
126
|
+
|-------|------|-------------|
|
|
127
|
+
| `ret` | `number` | Return code, `0` = success |
|
|
128
|
+
| `errcode` | `number?` | Error code (e.g., `-14` = session timeout) |
|
|
129
|
+
| `errmsg` | `string?` | Error description |
|
|
130
|
+
| `msgs` | `WeixinMessage[]` | Message list (structure below) |
|
|
131
|
+
| `get_updates_buf` | `string` | New sync cursor to pass in the next request |
|
|
132
|
+
| `longpolling_timeout_ms` | `number?` | Server-suggested long-poll timeout for the next request (ms) |
|
|
133
|
+
|
|
134
|
+
### sendMessage
|
|
135
|
+
|
|
136
|
+
Send a message to a user.
|
|
137
|
+
|
|
138
|
+
**Request body:**
|
|
139
|
+
|
|
140
|
+
```json
|
|
141
|
+
{
|
|
142
|
+
"msg": {
|
|
143
|
+
"to_user_id": "<target user ID>",
|
|
144
|
+
"context_token": "<conversation context token>",
|
|
145
|
+
"item_list": [
|
|
146
|
+
{
|
|
147
|
+
"type": 1,
|
|
148
|
+
"text_item": { "text": "Hello" }
|
|
149
|
+
}
|
|
150
|
+
]
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### getUploadUrl
|
|
156
|
+
|
|
157
|
+
Get CDN upload pre-signed parameters. Call this endpoint before uploading a file to obtain `upload_param` and `thumb_upload_param`.
|
|
158
|
+
|
|
159
|
+
**Request body:**
|
|
160
|
+
|
|
161
|
+
```json
|
|
162
|
+
{
|
|
163
|
+
"filekey": "<file identifier>",
|
|
164
|
+
"media_type": 1,
|
|
165
|
+
"to_user_id": "<target user ID>",
|
|
166
|
+
"rawsize": 12345,
|
|
167
|
+
"rawfilemd5": "<plaintext MD5>",
|
|
168
|
+
"filesize": 12352,
|
|
169
|
+
"thumb_rawsize": 1024,
|
|
170
|
+
"thumb_rawfilemd5": "<thumbnail plaintext MD5>",
|
|
171
|
+
"thumb_filesize": 1040
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
| Field | Type | Description |
|
|
176
|
+
|-------|------|-------------|
|
|
177
|
+
| `media_type` | `number` | `1` = IMAGE, `2` = VIDEO, `3` = FILE |
|
|
178
|
+
| `rawsize` | `number` | Original file plaintext size |
|
|
179
|
+
| `rawfilemd5` | `string` | Original file plaintext MD5 |
|
|
180
|
+
| `filesize` | `number` | Ciphertext size after AES-128-ECB encryption |
|
|
181
|
+
| `thumb_rawsize` | `number?` | Thumbnail plaintext size (required for IMAGE/VIDEO) |
|
|
182
|
+
| `thumb_rawfilemd5` | `string?` | Thumbnail plaintext MD5 (required for IMAGE/VIDEO) |
|
|
183
|
+
| `thumb_filesize` | `number?` | Thumbnail ciphertext size (required for IMAGE/VIDEO) |
|
|
184
|
+
|
|
185
|
+
**Response body:**
|
|
186
|
+
|
|
187
|
+
```json
|
|
188
|
+
{
|
|
189
|
+
"upload_param": "<original image upload encrypted parameters>",
|
|
190
|
+
"thumb_upload_param": "<thumbnail upload encrypted parameters>"
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### getConfig
|
|
195
|
+
|
|
196
|
+
Get account configuration, including the typing ticket.
|
|
197
|
+
|
|
198
|
+
**Request body:**
|
|
199
|
+
|
|
200
|
+
```json
|
|
201
|
+
{
|
|
202
|
+
"ilink_user_id": "<user ID>",
|
|
203
|
+
"context_token": "<optional, conversation context token>"
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**Response body:**
|
|
208
|
+
|
|
209
|
+
```json
|
|
210
|
+
{
|
|
211
|
+
"ret": 0,
|
|
212
|
+
"typing_ticket": "<base64-encoded typing ticket>"
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### sendTyping
|
|
217
|
+
|
|
218
|
+
Send or cancel the typing status indicator.
|
|
219
|
+
|
|
220
|
+
**Request body:**
|
|
221
|
+
|
|
222
|
+
```json
|
|
223
|
+
{
|
|
224
|
+
"ilink_user_id": "<user ID>",
|
|
225
|
+
"typing_ticket": "<obtained from getConfig>",
|
|
226
|
+
"status": 1
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
| Field | Type | Description |
|
|
231
|
+
|-------|------|-------------|
|
|
232
|
+
| `status` | `number` | `1` = typing, `2` = cancel typing |
|
|
233
|
+
|
|
234
|
+
### Message Structure
|
|
235
|
+
|
|
236
|
+
#### WeixinMessage
|
|
237
|
+
|
|
238
|
+
| Field | Type | Description |
|
|
239
|
+
|-------|------|-------------|
|
|
240
|
+
| `seq` | `number?` | Message sequence number |
|
|
241
|
+
| `message_id` | `number?` | Unique message ID |
|
|
242
|
+
| `from_user_id` | `string?` | Sender ID |
|
|
243
|
+
| `to_user_id` | `string?` | Receiver ID |
|
|
244
|
+
| `create_time_ms` | `number?` | Creation timestamp (ms) |
|
|
245
|
+
| `session_id` | `string?` | Session ID |
|
|
246
|
+
| `message_type` | `number?` | `1` = USER, `2` = BOT |
|
|
247
|
+
| `message_state` | `number?` | `0` = NEW, `1` = GENERATING, `2` = FINISH |
|
|
248
|
+
| `item_list` | `MessageItem[]?` | Message content list |
|
|
249
|
+
| `context_token` | `string?` | Conversation context token, must be passed back when replying |
|
|
250
|
+
|
|
251
|
+
#### MessageItem
|
|
252
|
+
|
|
253
|
+
| Field | Type | Description |
|
|
254
|
+
|-------|------|-------------|
|
|
255
|
+
| `type` | `number` | `1` TEXT, `2` IMAGE, `3` VOICE, `4` FILE, `5` VIDEO |
|
|
256
|
+
| `text_item` | `{ text: string }?` | Text content |
|
|
257
|
+
| `image_item` | `ImageItem?` | Image (with CDN reference and AES key) |
|
|
258
|
+
| `voice_item` | `VoiceItem?` | Voice (SILK encoded) |
|
|
259
|
+
| `file_item` | `FileItem?` | File attachment |
|
|
260
|
+
| `video_item` | `VideoItem?` | Video |
|
|
261
|
+
| `ref_msg` | `RefMessage?` | Referenced message |
|
|
262
|
+
|
|
263
|
+
#### CDN Media Reference (CDNMedia)
|
|
264
|
+
|
|
265
|
+
All media types (image/voice/file/video) are transferred via CDN using AES-128-ECB encryption:
|
|
266
|
+
|
|
267
|
+
| Field | Type | Description |
|
|
268
|
+
|-------|------|-------------|
|
|
269
|
+
| `encrypt_query_param` | `string?` | Encrypted parameters for CDN download/upload |
|
|
270
|
+
| `aes_key` | `string?` | Base64-encoded AES-128 key |
|
|
271
|
+
|
|
272
|
+
### CDN Upload Flow
|
|
273
|
+
|
|
274
|
+
1. Calculate the file's plaintext size, MD5, and ciphertext size after AES-128-ECB encryption
|
|
275
|
+
2. If a thumbnail is needed (image/video), calculate the thumbnail's plaintext and ciphertext parameters as well
|
|
276
|
+
3. Call `getUploadUrl` to get `upload_param` (and `thumb_upload_param`)
|
|
277
|
+
4. Encrypt the file content with AES-128-ECB and PUT upload to the CDN URL
|
|
278
|
+
5. Encrypt and upload the thumbnail in the same way
|
|
279
|
+
6. Use the returned `encrypt_query_param` to construct a `CDNMedia` reference, include it in the `MessageItem`, and send
|
|
280
|
+
|
|
281
|
+
> For complete type definitions, see [`src/api/types.ts`](src/api/types.ts). For API call implementations, see [`src/api/api.ts`](src/api/api.ts).
|
|
282
|
+
|
|
283
|
+
## Uninstall
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
openclaw plugins uninstall @tencent-weixin/openclaw-weixin
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## Troubleshooting
|
|
290
|
+
|
|
291
|
+
### "requires OpenClaw >=2026.3.22" error
|
|
292
|
+
|
|
293
|
+
Your OpenClaw version is too old for this plugin version. Check with:
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
openclaw --version
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
Install the legacy plugin line instead:
|
|
300
|
+
|
|
301
|
+
```bash
|
|
302
|
+
openclaw plugins install @tencent-weixin/openclaw-weixin@legacy
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Channel shows "OK" but doesn't connect
|
|
306
|
+
|
|
307
|
+
Ensure `plugins.entries.openclaw-weixin.enabled` is `true` in `~/.openclaw/openclaw.json`:
|
|
308
|
+
|
|
309
|
+
```bash
|
|
310
|
+
openclaw config set plugins.entries.openclaw-weixin.enabled true
|
|
311
|
+
openclaw gateway restart
|
|
312
|
+
```
|