openclaw-weixin 3.0.2 → 3.1.1

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.
@@ -0,0 +1,347 @@
1
+ # Backend API Protocol
2
+
3
+ [Back to detailed guide](./guide_EN.md) |
4
+ [简体中文](./backend-api.md)
5
+
6
+ This document covers every Weixin backend endpoint used by the plugin for QR
7
+ login, lifecycle notifications, messaging, and media. The two QR login requests
8
+ always use Tencent's fixed service. A backend selected by the account's
9
+ post-login `baseurl` must implement the lifecycle, messaging, and media
10
+ endpoints.
11
+
12
+ QR creation and all post-login endpoints use `POST`; QR status polling uses
13
+ `GET`. All requests include:
14
+
15
+ | Header | Description |
16
+ |--------|-------------|
17
+ | `iLink-App-Id` | Plugin application ID |
18
+ | `iLink-App-ClientVersion` | Plugin version encoded as an unsigned integer |
19
+ | `SKRouteTag` | Optional configured route tag |
20
+
21
+ `POST` requests additionally include `Content-Type: application/json`,
22
+ `AuthorizationType: ilink_bot_token`, and a random base64-encoded
23
+ `X-WECHAT-UIN`. Authenticated post-login requests also include
24
+ `Authorization: Bearer <bot-token>`; QR status `GET` requests do not include
25
+ these `POST`-specific headers.
26
+
27
+ Authenticated post-login `POST` bodies include `base_info`; QR creation does
28
+ not. The message examples below omit it for readability.
29
+
30
+ ```json
31
+ {
32
+ "base_info": {
33
+ "channel_version": "<plugin version>",
34
+ "bot_agent": "OpenClaw"
35
+ }
36
+ }
37
+ ```
38
+
39
+ `bot_agent` is for observability only. Its supported format and configuration
40
+ are documented in the [detailed guide](./guide_EN.md#custom-botagent-optional).
41
+
42
+ ## Endpoint List
43
+
44
+ | Method | Path | Description |
45
+ |--------|------|-------------|
46
+ | `POST` | `/ilink/bot/get_bot_qrcode?bot_type=3` | Create a QR login session |
47
+ | `GET` | `/ilink/bot/get_qrcode_status?qrcode=<opaque-id>` | Poll QR login status; accepts optional `verify_code` |
48
+ | `POST` | `/ilink/bot/msg/notifystart` | Notify backend that the channel started |
49
+ | `POST` | `/ilink/bot/msg/notifystop` | Notify backend that the channel stopped |
50
+ | `POST` | `/ilink/bot/getupdates` | Long-poll for new messages |
51
+ | `POST` | `/ilink/bot/sendmessage` | Send a message (text/image/video/file) |
52
+ | `POST` | `/ilink/bot/getuploadurl` | Get CDN upload pre-signed parameters |
53
+ | `POST` | `/ilink/bot/getconfig` | Get account config (typing ticket, etc.) |
54
+ | `POST` | `/ilink/bot/sendtyping` | Send/cancel typing status |
55
+
56
+ The first two rows describe the fixed QR login service. They are not sent to the
57
+ account's post-login `baseurl`.
58
+
59
+ ## QR Login and Lifecycle
60
+
61
+ Create a QR session with:
62
+
63
+ ```http
64
+ POST /ilink/bot/get_bot_qrcode?bot_type=3
65
+ Content-Type: application/json
66
+ ```
67
+
68
+ ```json
69
+ {
70
+ "local_token_list": []
71
+ }
72
+ ```
73
+
74
+ The response contains an opaque `qrcode` identifier and
75
+ `qrcode_img_content`, the URL rendered as the QR code. Poll
76
+ `GET /ilink/bot/get_qrcode_status?qrcode=<opaque-id>` until it reaches a
77
+ terminal state. The optional `verify_code` query parameter handles verification
78
+ challenges.
79
+
80
+ | Field | Type | Description |
81
+ |-------|------|-------------|
82
+ | `status` | `string` | `wait`, `scaned`, `need_verifycode`, `verify_code_blocked`, `expired`, `scaned_but_redirect`, `binded_redirect`, or `confirmed` |
83
+ | `bot_token` | `string?` | Bot credential returned after confirmation |
84
+ | `ilink_bot_id` | `string?` | Required account ID after confirmation |
85
+ | `baseurl` | `string?` | Account API base URL |
86
+ | `ilink_user_id` | `string?` | ID of the user who scanned the QR code |
87
+ | `redirect_host` | `string?` | New polling host for `scaned_but_redirect` |
88
+
89
+ After authentication, call `/ilink/bot/msg/notifystart` when the channel starts
90
+ and `/ilink/bot/msg/notifystop` when it stops. Both receive the standard
91
+ `base_info` body and return:
92
+
93
+ ```json
94
+ {
95
+ "ret": 0,
96
+ "errmsg": ""
97
+ }
98
+ ```
99
+
100
+ QR identifiers, verification codes, bot tokens, account IDs, user IDs, and
101
+ context tokens are sensitive. Never place real values in logs or examples.
102
+
103
+ ## getUpdates
104
+
105
+ Long-polling endpoint. The server responds when new messages arrive or on
106
+ timeout.
107
+
108
+ **Request body:**
109
+
110
+ ```json
111
+ {
112
+ "get_updates_buf": ""
113
+ }
114
+ ```
115
+
116
+ | Field | Type | Description |
117
+ |-------|------|-------------|
118
+ | `get_updates_buf` | `string` | Sync cursor from the previous response; empty string for the first request |
119
+
120
+ **Response body:**
121
+
122
+ ```json
123
+ {
124
+ "ret": 0,
125
+ "msgs": [],
126
+ "get_updates_buf": "<new cursor>",
127
+ "longpolling_timeout_ms": 35000
128
+ }
129
+ ```
130
+
131
+ | Field | Type | Description |
132
+ |-------|------|-------------|
133
+ | `ret` | `number` | Return code, `0` = success |
134
+ | `errcode` | `number?` | Error code (e.g., `-14` = stale token) |
135
+ | `errmsg` | `string?` | Error description |
136
+ | `msgs` | `WeixinMessage[]` | Message list (structure below) |
137
+ | `get_updates_buf` | `string` | New sync cursor to pass in the next request |
138
+ | `longpolling_timeout_ms` | `number?` | Server-suggested long-poll timeout for the next request (ms) |
139
+
140
+ ## sendMessage
141
+
142
+ Send a message to a user.
143
+
144
+ **Request body:**
145
+
146
+ ```json
147
+ {
148
+ "msg": {
149
+ "to_user_id": "<target user ID>",
150
+ "context_token": "<conversation context token>",
151
+ "item_list": [
152
+ {
153
+ "type": 1,
154
+ "text_item": { "text": "Hello" }
155
+ }
156
+ ]
157
+ }
158
+ }
159
+ ```
160
+
161
+ **Response body:**
162
+
163
+ ```json
164
+ {
165
+ "ret": 0,
166
+ "errmsg": ""
167
+ }
168
+ ```
169
+
170
+ ## getUploadUrl
171
+
172
+ Get CDN upload pre-signed parameters. Call this endpoint before uploading a file
173
+ to obtain `upload_param` and `thumb_upload_param`.
174
+
175
+ **Request body:**
176
+
177
+ ```json
178
+ {
179
+ "filekey": "<file identifier>",
180
+ "media_type": 1,
181
+ "to_user_id": "<target user ID>",
182
+ "rawsize": 12345,
183
+ "rawfilemd5": "<plaintext MD5>",
184
+ "filesize": 12352,
185
+ "no_need_thumb": true,
186
+ "aeskey": "<32-character hex AES key>"
187
+ }
188
+ ```
189
+
190
+ | Field | Type | Description |
191
+ |-------|------|-------------|
192
+ | `filekey` | `string` | Per-upload file identifier |
193
+ | `media_type` | `number` | `1` = IMAGE, `2` = VIDEO, `3` = FILE, `4` = VOICE |
194
+ | `to_user_id` | `string` | Target user ID |
195
+ | `rawsize` | `number` | Original file plaintext size |
196
+ | `rawfilemd5` | `string` | Original file plaintext MD5 |
197
+ | `filesize` | `number` | Ciphertext size after AES-128-ECB encryption |
198
+ | `no_need_thumb` | `boolean?` | Set `true` to omit thumbnail upload parameters |
199
+ | `aeskey` | `string?` | AES-128 key as 32 hexadecimal characters |
200
+ | `thumb_rawsize` | `number?` | Thumbnail plaintext size when a thumbnail is requested |
201
+ | `thumb_rawfilemd5` | `string?` | Thumbnail plaintext MD5 when requested |
202
+ | `thumb_filesize` | `number?` | Thumbnail ciphertext size when requested |
203
+
204
+ **Response body:**
205
+
206
+ ```json
207
+ {
208
+ "upload_param": "<original image upload encrypted parameters>",
209
+ "upload_full_url": "https://cdn.example.test/upload",
210
+ "thumb_upload_param": "<optional thumbnail upload parameters>"
211
+ }
212
+ ```
213
+
214
+ | Field | Type | Description |
215
+ |-------|------|-------------|
216
+ | `upload_param` | `string?` | Parameters used to construct the CDN upload URL |
217
+ | `upload_full_url` | `string?` | Complete CDN upload URL; takes precedence over `upload_param` |
218
+ | `thumb_upload_param` | `string?` | Optional thumbnail upload parameters |
219
+
220
+ ## getConfig
221
+
222
+ Get account configuration, including the typing ticket.
223
+
224
+ **Request body:**
225
+
226
+ ```json
227
+ {
228
+ "ilink_user_id": "<user ID>",
229
+ "context_token": "<optional, conversation context token>"
230
+ }
231
+ ```
232
+
233
+ **Response body:**
234
+
235
+ ```json
236
+ {
237
+ "ret": 0,
238
+ "errmsg": "",
239
+ "typing_ticket": "<base64-encoded typing ticket>"
240
+ }
241
+ ```
242
+
243
+ ## sendTyping
244
+
245
+ Send or cancel the typing status indicator.
246
+
247
+ **Request body:**
248
+
249
+ ```json
250
+ {
251
+ "ilink_user_id": "<user ID>",
252
+ "typing_ticket": "<obtained from getConfig>",
253
+ "status": 1
254
+ }
255
+ ```
256
+
257
+ | Field | Type | Description |
258
+ |-------|------|-------------|
259
+ | `status` | `number` | `1` = typing, `2` = cancel typing |
260
+
261
+ **Response body:**
262
+
263
+ ```json
264
+ {
265
+ "ret": 0,
266
+ "errmsg": ""
267
+ }
268
+ ```
269
+
270
+ ## Message Structure
271
+
272
+ ### WeixinMessage
273
+
274
+ | Field | Type | Description |
275
+ |-------|------|-------------|
276
+ | `seq` | `number?` | Message sequence number |
277
+ | `message_id` | `number?` | Unique message ID |
278
+ | `from_user_id` | `string?` | Sender ID |
279
+ | `to_user_id` | `string?` | Receiver ID |
280
+ | `client_id` | `string?` | Client-generated message ID |
281
+ | `create_time_ms` | `number?` | Creation timestamp (ms) |
282
+ | `update_time_ms` | `number?` | Update timestamp (ms) |
283
+ | `delete_time_ms` | `number?` | Deletion timestamp (ms) |
284
+ | `session_id` | `string?` | Session ID |
285
+ | `group_id` | `string?` | Group ID |
286
+ | `message_type` | `number?` | `1` = USER, `2` = BOT |
287
+ | `message_state` | `number?` | `0` = NEW, `1` = GENERATING, `2` = FINISH |
288
+ | `item_list` | `MessageItem[]?` | Message content list |
289
+ | `context_token` | `string?` | Conversation context token, must be passed back when replying |
290
+ | `run_id` | `string?` | OpenClaw run ID for generated replies |
291
+
292
+ ### MessageItem
293
+
294
+ | Field | Type | Description |
295
+ |-------|------|-------------|
296
+ | `type` | `number` | `1` TEXT, `2` IMAGE, `3` VOICE, `4` FILE, `5` VIDEO, `11` TOOL_CALL_START, `12` TOOL_CALL_RESULT |
297
+ | `create_time_ms` | `number?` | Item creation timestamp |
298
+ | `update_time_ms` | `number?` | Item update timestamp |
299
+ | `is_completed` | `boolean?` | Whether a progress item is complete |
300
+ | `msg_id` | `string?` | Item message ID |
301
+ | `text_item` | `{ text: string }?` | Text content |
302
+ | `image_item` | `ImageItem?` | Image (with CDN reference and AES key) |
303
+ | `voice_item` | `VoiceItem?` | Voice (SILK encoded) |
304
+ | `file_item` | `FileItem?` | File attachment |
305
+ | `video_item` | `VideoItem?` | Video |
306
+ | `ref_msg` | `RefMessage?` | Referenced message |
307
+ | `tool_call_start_item` | `{ tool_name?: string; tool_call_id?: string }?` | Tool invocation metadata |
308
+ | `tool_call_result_item` | `{ tool_name?: string; tool_call_id?: string; status?: string }?` | Tool completion metadata |
309
+
310
+ ### Nested Item Structures
311
+
312
+ | Structure | Fields |
313
+ |-----------|--------|
314
+ | `RefMessage` | `message_item?: MessageItem`, `title?: string` |
315
+ | `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` |
316
+ | `VoiceItem` | `media?: CDNMedia`, `encode_type?: number`, `bits_per_sample?: number`, `sample_rate?: number`, `playtime?: number`, `text?: string` |
317
+ | `FileItem` | `media?: CDNMedia`, `file_name?: string`, `md5?: string`, `len?: string` |
318
+ | `VideoItem` | `media?: CDNMedia`, `video_size?: number`, `play_length?: number`, `video_md5?: string`, `thumb_media?: CDNMedia`, `thumb_size?: number`, `thumb_height?: number`, `thumb_width?: number` |
319
+ | `ToolCallStartItem` | `tool_name?: string`, `tool_call_id?: string` |
320
+ | `ToolCallResultItem` | `tool_name?: string`, `tool_call_id?: string`, `status?: string` |
321
+
322
+ ### CDN Media Reference (CDNMedia)
323
+
324
+ All media types (image/voice/file/video) are transferred via CDN using
325
+ AES-128-ECB encryption:
326
+
327
+ | Field | Type | Description |
328
+ |-------|------|-------------|
329
+ | `encrypt_query_param` | `string?` | Encrypted parameters for CDN download/upload |
330
+ | `aes_key` | `string?` | Base64-encoded AES-128 key |
331
+ | `encrypt_type` | `number?` | Encryption metadata mode |
332
+ | `full_url` | `string?` | Complete download URL returned by the backend |
333
+
334
+ ## CDN Upload Flow
335
+
336
+ 1. Calculate the file's plaintext size, MD5, and ciphertext size after
337
+ AES-128-ECB encryption
338
+ 2. If a thumbnail is needed (image/video), calculate the thumbnail's plaintext
339
+ and ciphertext parameters as well
340
+ 3. Call `getUploadUrl` to get `upload_full_url` or `upload_param` (and optional
341
+ `thumb_upload_param`)
342
+ 4. Encrypt the file content with AES-128-ECB and `POST` it to the CDN URL as
343
+ `application/octet-stream`
344
+ 5. Encrypt and upload the thumbnail in the same way when requested
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
package/docs/guide.md CHANGED
@@ -1,40 +1,35 @@
1
- # Detailed Guide
1
+ # 详细指南
2
2
 
3
- [Back to README](../README_EN.md) | [简体中文](./guide.zh_CN.md)
3
+ [返回 README](../README.md) | [English](./guide_EN.md)
4
4
 
5
- ## Installation Details
5
+ ## 安装说明
6
6
 
7
- ### Package Names and State
7
+ ### 包名与状态兼容性
8
8
 
9
- The npm package, plugin id, and channel id are all `openclaw-weixin`. The
10
- [install command](../README_EN.md#install-or-replace) preserves the existing
11
- `channels.openclaw-weixin`, `plugins.entries.openclaw-weixin`, and
12
- `~/.openclaw/openclaw-weixin/` state paths.
9
+ npm 包、插件 ID 和 channel ID 均为 `openclaw-weixin`。README 中的
10
+ [安装命令](../README.md#connect-wechat)会保留
11
+ `channels.openclaw-weixin`、`plugins.entries.openclaw-weixin` 和
12
+ `~/.openclaw/openclaw-weixin/` 状态路径。
13
13
 
14
- `--force` confirms the npm source and allows OpenClaw to replace a plugin with
15
- the same internal id. OpenClaw rotates backups of its config automatically; do
16
- not copy the entire state directory for this replacement.
14
+ `--force` 允许 OpenClaw 覆盖内部 ID 相同的现有插件安装;它不会改变来源信任或
15
+ 安全策略。OpenClaw 会自动轮换配置备份;此次替换无需复制整个状态目录。
17
16
 
18
- ### Limitations
17
+ ### 安装限制
19
18
 
20
- - Use the CLI for this community npm package. OpenClaw's Control UI does not
21
- install arbitrary npm, git, or local-path plugin sources.
22
- - In Nix mode (`OPENCLAW_NIX_MODE=1`), plugin install, update, uninstall,
23
- enable, and disable commands are intentionally disabled. Add the package and
24
- config to the Nix source, then rebuild instead.
25
- - OpenClaw installs plugin dependencies with lifecycle scripts disabled. This
26
- package therefore ships its compiled `dist/index.js` runtime and does not
27
- build on the user's machine.
19
+ - 此社区 npm 包需通过 CLI 安装;OpenClaw Control UI 不能安装任意 npm、git
20
+ 或本地路径来源的插件。
21
+ - Nix 模式(`OPENCLAW_NIX_MODE=1`)会禁止插件安装、更新、卸载、启用和停用
22
+ 命令;请改动 Nix 配置源后重新构建。
23
+ - OpenClaw 安装插件依赖时会禁用生命周期脚本,因此本包直接携带编译后的
24
+ `dist/index.js`,无需在用户机器上构建。
28
25
 
29
- ## Custom BotAgent (optional)
26
+ ## 自定义 BotAgent(可选)
30
27
 
31
- Every authenticated post-login request to the WeChat backend carries a
32
- self-declared `bot_agent` identifier — analogous to an HTTP `User-Agent` — used
33
- for log attribution and monitoring aggregation. The default is `OpenClaw`.
34
- Declaring your own app name makes it much easier to trace your traffic in
35
- backend logs.
28
+ 登录后的每条鉴权请求会带一个自我声明的 `bot_agent` 字段——类似 HTTP
29
+ `User-Agent`——用于后台日志归因和监控聚合。**默认值为 `OpenClaw`**。声明自己的
30
+ 应用名能让你的流量在后台日志中更容易识别。
36
31
 
37
- Add one line to `openclaw.json`:
32
+ 在 `openclaw.json` 中加一行即可:
38
33
 
39
34
  ```json
40
35
  {
@@ -46,64 +41,59 @@ Add one line to `openclaw.json`:
46
41
  }
47
42
  ```
48
43
 
49
- **Format** (UA-style):
44
+ **格式规范**(UA 风格):
50
45
 
51
- - One or more `Name/Version` tokens, space-separated
52
- - Each token may optionally be followed by ` (comment)`
53
- - ASCII only; total length ≤ 256 bytes
54
- - Invalid tokens are silently dropped during sanitization; falls back to
55
- `OpenClaw` if nothing valid remains
46
+ - 一个或多个 `Name/Version` token,空格分隔
47
+ - 每个 token 可选地跟一个 ` (comment)`
48
+ - 仅允许 ASCII 字符;总长 ≤ 256 字节
49
+ - 不合规的 token 在清洗时静默丢弃;如果最终为空,回退到 `OpenClaw`
56
50
 
57
- Examples that pass through unchanged:
51
+ 可直接使用的示例:
58
52
 
59
53
  - `MyBot/1.2.0`
60
54
  - `MyBot/1.2.0 (region=cn;env=prod)`
61
55
  - `MyBot/1.2.0 LangChain/0.3.5`
62
56
  - `MyBot/1.2.0-rc.1+build.5`
63
57
 
64
- **Note**: `bot_agent` is for observability only — it is not used for
65
- authentication or routing. All registered agents on this plugin instance
66
- currently share the same `botAgent` declaration; per-agent overrides may be
67
- added in a future version if needed.
58
+ **注意**:`bot_agent` 仅用于观测,**不参与鉴权或路由**。当前本插件实例下所有
59
+ 已注册的 agent 共享同一个 `botAgent` 声明;如有需要按 agent 单独标识的场景,
60
+ 可在后续版本扩展配置。
68
61
 
69
- ## Uninstall
62
+ ## 卸载
70
63
 
71
64
  > [!WARNING]
72
- > Do not uninstall when replacing Tencent's package. Use the
73
- > [install command](../README_EN.md#install-or-replace) instead.
65
+ > 替换腾讯版时不要卸载,请使用 README 中的
66
+ > [安装命令](../README.md#connect-wechat)原位替换。
74
67
 
75
- Back up `~/.openclaw/openclaw.json` first if you may want to reinstall: current
76
- OpenClaw versions remove the plugin entry and owned
77
- `channels.openclaw-weixin` configuration during uninstall.
68
+ 如果以后可能重装,请先备份 `~/.openclaw/openclaw.json`:新版 OpenClaw
69
+ 卸载时会删除插件条目及其拥有的 `channels.openclaw-weixin` 配置。
78
70
 
79
71
  ```bash
80
72
  openclaw plugins uninstall openclaw-weixin
81
73
  ```
82
74
 
83
- ## Troubleshooting
75
+ ## 故障排查
84
76
 
85
- ### "requires OpenClaw >=2026.6.1" error
77
+ ### "requires OpenClaw >=2026.6.1" 报错
86
78
 
87
- Your OpenClaw version is too old for this plugin version. Check with:
79
+ 你的 OpenClaw 版本太旧,不兼容当前插件版本。检查版本:
88
80
 
89
81
  ```bash
90
82
  openclaw --version
91
83
  ```
92
84
 
93
- Upgrade OpenClaw before installing this package. The community package does not
94
- publish a legacy compatibility line.
85
+ 请先升级 OpenClaw。社区包不发布旧宿主兼容版本线。
95
86
 
96
- ### Channel shows "OK" but doesn't connect
87
+ ### Channel 显示 "OK" 但未连接
97
88
 
98
- Enable the plugin, reload or restart the actual unit that runs OpenClaw, and
99
- probe the channel again:
89
+ 启用插件,重载或重启实际承载 OpenClaw 的运行单元,然后再次探测:
100
90
 
101
91
  ```bash
102
92
  openclaw plugins enable openclaw-weixin
103
93
  openclaw channels status --probe
104
94
  ```
105
95
 
106
- ## Developer Documentation
96
+ ## 开发者文档
107
97
 
108
- - [Backend API protocol](./backend-api.md)
109
- - [Architecture](./architecture.md)
98
+ - [后端 API 协议](./backend-api.md)
99
+ - [架构说明](./architecture.md)
@@ -0,0 +1,110 @@
1
+ # Detailed Guide
2
+
3
+ [Back to README](../README_EN.md) | [简体中文](./guide.md)
4
+
5
+ ## Installation Details
6
+
7
+ ### Package Names and State
8
+
9
+ The npm package, plugin id, and channel id are all `openclaw-weixin`. The
10
+ [install command](../README_EN.md#connect-wechat) preserves the existing
11
+ `channels.openclaw-weixin`, `plugins.entries.openclaw-weixin`, and
12
+ `~/.openclaw/openclaw-weixin/` state paths.
13
+
14
+ `--force` allows OpenClaw to overwrite an existing plugin installation with the
15
+ same internal id; it does not change source-trust or security policy. OpenClaw
16
+ rotates backups of its config automatically; do not copy the entire state
17
+ directory for this replacement.
18
+
19
+ ### Limitations
20
+
21
+ - Use the CLI for this community npm package. OpenClaw's Control UI does not
22
+ install arbitrary npm, git, or local-path plugin sources.
23
+ - In Nix mode (`OPENCLAW_NIX_MODE=1`), plugin install, update, uninstall,
24
+ enable, and disable commands are intentionally disabled. Add the package and
25
+ config to the Nix source, then rebuild instead.
26
+ - OpenClaw installs plugin dependencies with lifecycle scripts disabled. This
27
+ package therefore ships its compiled `dist/index.js` runtime and does not
28
+ build on the user's machine.
29
+
30
+ ## Custom BotAgent (optional)
31
+
32
+ Every authenticated post-login request to the WeChat backend carries a
33
+ self-declared `bot_agent` identifier — analogous to an HTTP `User-Agent` — used
34
+ for log attribution and monitoring aggregation. The default is `OpenClaw`.
35
+ Declaring your own app name makes it much easier to trace your traffic in
36
+ backend logs.
37
+
38
+ Add one line to `openclaw.json`:
39
+
40
+ ```json
41
+ {
42
+ "channels": {
43
+ "openclaw-weixin": {
44
+ "botAgent": "MyBot/1.2.0"
45
+ }
46
+ }
47
+ }
48
+ ```
49
+
50
+ **Format** (UA-style):
51
+
52
+ - One or more `Name/Version` tokens, space-separated
53
+ - Each token may optionally be followed by ` (comment)`
54
+ - ASCII only; total length ≤ 256 bytes
55
+ - Invalid tokens are silently dropped during sanitization; falls back to
56
+ `OpenClaw` if nothing valid remains
57
+
58
+ Examples that pass through unchanged:
59
+
60
+ - `MyBot/1.2.0`
61
+ - `MyBot/1.2.0 (region=cn;env=prod)`
62
+ - `MyBot/1.2.0 LangChain/0.3.5`
63
+ - `MyBot/1.2.0-rc.1+build.5`
64
+
65
+ **Note**: `bot_agent` is for observability only — it is not used for
66
+ authentication or routing. All registered agents on this plugin instance
67
+ currently share the same `botAgent` declaration; per-agent overrides may be
68
+ added in a future version if needed.
69
+
70
+ ## Uninstall
71
+
72
+ > [!WARNING]
73
+ > Do not uninstall when replacing Tencent's package. Use the
74
+ > [install command](../README_EN.md#connect-wechat) instead.
75
+
76
+ Back up `~/.openclaw/openclaw.json` first if you may want to reinstall: current
77
+ OpenClaw versions remove the plugin entry and owned
78
+ `channels.openclaw-weixin` configuration during uninstall.
79
+
80
+ ```bash
81
+ openclaw plugins uninstall openclaw-weixin
82
+ ```
83
+
84
+ ## Troubleshooting
85
+
86
+ ### "requires OpenClaw >=2026.6.1" error
87
+
88
+ Your OpenClaw version is too old for this plugin version. Check with:
89
+
90
+ ```bash
91
+ openclaw --version
92
+ ```
93
+
94
+ Upgrade OpenClaw before installing this package. The community package does not
95
+ publish a legacy compatibility line.
96
+
97
+ ### Channel shows "OK" but doesn't connect
98
+
99
+ Enable the plugin, reload or restart the actual unit that runs OpenClaw, and
100
+ probe the channel again:
101
+
102
+ ```bash
103
+ openclaw plugins enable openclaw-weixin
104
+ openclaw channels status --probe
105
+ ```
106
+
107
+ ## Developer Documentation
108
+
109
+ - [Backend API protocol](./backend-api_EN.md)
110
+ - [Architecture](./architecture_EN.md)
package/index.ts CHANGED
@@ -7,8 +7,8 @@ import { WeixinConfigSchema } from "./src/config/config-schema.js";
7
7
 
8
8
  export default {
9
9
  id: "openclaw-weixin",
10
- name: "Weixin",
11
- description: "Weixin channel (getUpdates long-poll + sendMessage)",
10
+ name: "WeChat",
11
+ description: "Community-maintained WeChat (Weixin) channel plugin for OpenClaw using the iLink bot API.",
12
12
  configSchema: buildChannelConfigSchema(WeixinConfigSchema),
13
13
  register(api: OpenClawPluginApi) {
14
14
  // Fail-fast: reject incompatible host versions before any side-effects.
@@ -1,6 +1,9 @@
1
1
  {
2
2
  "id": "openclaw-weixin",
3
- "version": "3.0.2",
3
+ "name": "WeChat",
4
+ "description": "Community-maintained WeChat (Weixin) channel plugin for OpenClaw using the iLink bot API.",
5
+ "icon": "https://openclaw-weixin.newfuture.cc/logo.svg",
6
+ "version": "3.1.1",
4
7
  "channels": ["openclaw-weixin"],
5
8
  "channelConfigs": {
6
9
  "openclaw-weixin": {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "openclaw-weixin",
3
- "version": "3.0.2",
4
- "description": "Community-maintained OpenClaw WeChat channel plugin",
3
+ "version": "3.1.1",
4
+ "description": "Community-maintained WeChat (Weixin) channel plugin for OpenClaw using the iLink bot API.",
5
5
  "license": "MIT",
6
6
  "author": "Tencent",
7
7
  "contributors": [
@@ -49,6 +49,7 @@
49
49
  "check:versions": "node scripts/check-versions.mjs",
50
50
  "check:static": "npm run check:versions && npm run check:style && npm run typecheck && npm run typecheck:tests",
51
51
  "check:fast": "npm run check:static && npm run test:unit",
52
+ "audit:all": "npm audit --audit-level=moderate",
52
53
  "audit:deps": "npm audit --omit=dev --omit=peer --audit-level=moderate",
53
54
  "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
54
55
  "build": "npm run clean && tsc",
@@ -67,23 +68,29 @@
67
68
  "openclaw": ">=2026.6.1"
68
69
  },
69
70
  "devDependencies": {
70
- "@biomejs/biome": "2.5.6",
71
+ "@biomejs/biome": "2.5.7",
71
72
  "@types/node": "^26.1.2",
72
73
  "@vitest/coverage-v8": "^4.1.10",
73
74
  "openclaw": "2026.7.1",
74
75
  "silk-wasm": "^3.7.1",
76
+ "tar": "7.5.22",
75
77
  "typescript": "^7.0.2",
76
78
  "vitest": "^4.1.10"
77
79
  },
78
80
  "overrides": {
79
- "@hono/node-server": "2.1.0",
80
- "brace-expansion": "5.0.9",
81
- "fast-uri": "3.1.5",
82
- "hono": "4.13.0",
83
- "protobufjs": "7.6.5",
84
- "tar": "7.5.22"
81
+ "openclaw@2026.7.1": {
82
+ "@hono/node-server": "2.1.0",
83
+ "tar": "7.5.22",
84
+ "undici": "8.9.0"
85
+ }
85
86
  },
86
87
  "openclaw": {
88
+ "compat": {
89
+ "pluginApi": ">=2026.6.1"
90
+ },
91
+ "build": {
92
+ "openclawVersion": "2026.7.1"
93
+ },
87
94
  "extensions": [
88
95
  "./index.ts"
89
96
  ],