@wecom/wecom-openclaw-plugin 2026.3.30 → 2026.3.31-beta.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.
Files changed (99) hide show
  1. package/README.md +251 -4
  2. package/dist/index.d.ts +2 -4
  3. package/dist/index.js +113 -0
  4. package/dist/src/accounts.d.ts +57 -0
  5. package/dist/src/accounts.js +222 -0
  6. package/dist/src/agent/api-client.d.ts +94 -0
  7. package/dist/src/agent/api-client.js +292 -0
  8. package/dist/src/agent/handler.d.ts +63 -0
  9. package/dist/src/agent/handler.js +532 -0
  10. package/dist/src/agent/index.d.ts +5 -0
  11. package/dist/src/agent/index.js +5 -0
  12. package/dist/src/agent/webhook.d.ts +23 -0
  13. package/dist/src/agent/webhook.js +226 -0
  14. package/dist/src/agent/xml.d.ts +21 -0
  15. package/dist/src/agent/xml.js +41 -0
  16. package/dist/src/channel.js +564 -0
  17. package/dist/src/chat-queue.d.ts +31 -0
  18. package/dist/src/chat-queue.js +45 -0
  19. package/dist/src/const.d.ts +46 -0
  20. package/dist/src/const.js +157 -0
  21. package/dist/src/dm-policy.js +84 -0
  22. package/dist/src/group-policy.js +126 -0
  23. package/dist/src/http.d.ts +26 -0
  24. package/dist/src/http.js +93 -0
  25. package/dist/src/interface.d.ts +0 -2
  26. package/dist/src/interface.js +4 -0
  27. package/dist/src/mcp/index.js +6 -0
  28. package/dist/src/mcp/interceptors/biz-error.js +64 -0
  29. package/dist/src/mcp/interceptors/index.js +66 -0
  30. package/dist/src/mcp/interceptors/msg-media.js +133 -0
  31. package/dist/src/mcp/interceptors/smartpage-create.js +132 -0
  32. package/dist/src/mcp/interceptors/smartpage-export.js +87 -0
  33. package/dist/src/mcp/interceptors/types.js +7 -0
  34. package/dist/src/mcp/schema.js +99 -0
  35. package/dist/src/mcp/tool.js +202 -0
  36. package/dist/src/mcp/transport.js +410 -0
  37. package/dist/src/media-handler.js +122 -0
  38. package/dist/src/media-uploader.js +333 -0
  39. package/dist/src/message-parser.js +129 -0
  40. package/dist/src/message-sender.d.ts +18 -0
  41. package/dist/src/message-sender.js +120 -0
  42. package/dist/src/monitor.js +832 -0
  43. package/dist/src/onboarding.js +175 -0
  44. package/dist/src/openclaw-compat.d.ts +49 -0
  45. package/dist/src/openclaw-compat.js +487 -0
  46. package/dist/src/reqid-store.js +83 -0
  47. package/dist/src/runtime.js +10 -0
  48. package/dist/src/shared/command-auth.d.ts +23 -0
  49. package/dist/src/shared/command-auth.js +73 -0
  50. package/dist/src/shared/xml-parser.d.ts +46 -0
  51. package/dist/src/shared/xml-parser.js +210 -0
  52. package/dist/src/state-manager.js +216 -0
  53. package/dist/src/target.d.ts +35 -0
  54. package/dist/src/target.js +67 -0
  55. package/dist/src/template-card-manager.d.ts +55 -0
  56. package/dist/src/template-card-manager.js +205 -0
  57. package/dist/src/template-card-parser.js +647 -0
  58. package/dist/src/timeout.js +36 -0
  59. package/dist/src/types/account.d.ts +29 -0
  60. package/dist/src/types/account.js +4 -0
  61. package/dist/src/types/config.d.ts +80 -0
  62. package/dist/src/types/config.js +7 -0
  63. package/dist/src/types/constants.d.ts +42 -0
  64. package/dist/src/types/constants.js +42 -0
  65. package/dist/src/types/index.d.ts +7 -0
  66. package/dist/src/types/index.js +5 -0
  67. package/dist/src/types/message.d.ts +238 -0
  68. package/dist/src/types/message.js +5 -0
  69. package/dist/src/utils.d.ts +39 -0
  70. package/dist/src/utils.js +70 -0
  71. package/dist/src/version.d.ts +1 -1
  72. package/dist/src/version.js +24 -0
  73. package/dist/src/webhook/command-auth.d.ts +47 -0
  74. package/dist/src/webhook/command-auth.js +96 -0
  75. package/dist/src/webhook/gateway.d.ts +36 -0
  76. package/dist/src/webhook/gateway.js +227 -0
  77. package/dist/src/webhook/handler.d.ts +18 -0
  78. package/dist/src/webhook/handler.js +420 -0
  79. package/dist/src/webhook/helpers.d.ts +156 -0
  80. package/dist/src/webhook/helpers.js +833 -0
  81. package/dist/src/webhook/http.d.ts +26 -0
  82. package/dist/src/webhook/http.js +94 -0
  83. package/dist/src/webhook/index.d.ts +11 -0
  84. package/dist/src/webhook/index.js +14 -0
  85. package/dist/src/webhook/media.d.ts +29 -0
  86. package/dist/src/webhook/media.js +88 -0
  87. package/dist/src/webhook/monitor.d.ts +59 -0
  88. package/dist/src/webhook/monitor.js +1147 -0
  89. package/dist/src/webhook/state.d.ts +220 -0
  90. package/dist/src/webhook/state.js +491 -0
  91. package/dist/src/webhook/target.d.ts +41 -0
  92. package/dist/src/webhook/target.js +132 -0
  93. package/dist/src/webhook/types.d.ts +347 -0
  94. package/dist/src/webhook/types.js +33 -0
  95. package/package.json +15 -7
  96. package/dist/index.cjs.js +0 -4953
  97. package/dist/index.cjs.js.map +0 -1
  98. package/dist/index.esm.js +0 -4926
  99. package/dist/index.esm.js.map +0 -1
package/README.md CHANGED
@@ -19,7 +19,7 @@
19
19
 
20
20
  **WeCom channel plugin for [OpenClaw](https://github.com/openclaw)** — by the Tencent WeCom team.
21
21
 
22
- > A bot plugin powered by WeCom AI Bot WebSocket persistent connections. Supports direct messages & group chats, streaming replies, and proactive messaging.
22
+ > A channel plugin powered by WeCom. Supports **Bot mode** (WebSocket long-polling) and **Agent mode** (HTTP webhook with XML encrypted callbacks). Direct messages, group chats, streaming replies, and proactive messaging.
23
23
 
24
24
  ---
25
25
 
@@ -28,13 +28,15 @@
28
28
 
29
29
  ## ✨ Features
30
30
 
31
- - 🔗 WebSocket persistent connection for stable communication
31
+ - 🔗 **Dual-mode**: Bot (WebSocket) and Agent (HTTP webhook) can run independently or together
32
32
  - 💬 Supports both direct messages (DM) and group chat
33
33
  - 📤 Proactive messaging to specific users or groups
34
34
  - 🖼️ Receives and processes image and file messages with automatic downloading
35
- - ⏳ Streaming replies with "thinking" placeholder messages
35
+ - ⏳ Streaming replies with "thinking" placeholder messages (Bot mode)
36
+ - 🔐 Agent mode: AES-256-CBC encrypted XML callbacks with SHA1 signature verification
36
37
  - 📝 Markdown formatting support for replies
37
38
  - 🔒 Built-in access control: DM Policy (pairing / open / allowlist / disabled) and Group Policy (open / allowlist / disabled)
39
+ - 👥 Multi-account support: run multiple WeCom accounts with independent bot/agent configs
38
40
  - ⚡ Auto heartbeat keep-alive and reconnection (up to 100 reconnect attempts)
39
41
  - 🧙 Interactive CLI setup wizard
40
42
 
@@ -89,7 +91,16 @@ openclaw config set channels.wecom.enabled true
89
91
  openclaw gateway restart
90
92
  ```
91
93
 
92
- ### Configuration Reference
94
+ ### Mode Overview
95
+
96
+ The plugin supports two connection modes that can be used independently or together:
97
+
98
+ | Mode | Connection | Message Format | Use Case |
99
+ |------|-----------|---------------|----------|
100
+ | **Bot** (智能体) | WebSocket long-polling | JSON | Quick setup, streaming replies |
101
+ | **Agent** (自建应用) | HTTP webhook callbacks | XML | Enterprise apps, API-driven messaging |
102
+
103
+ ### Bot Mode Configuration
93
104
 
94
105
  | Config Path | Description | Options | Default |
95
106
  |---|---|---|---|
@@ -103,6 +114,141 @@ openclaw gateway restart
103
114
  | `channels.wecom.groupAllowFrom` | Group allowlist (group IDs) | — | `[]` |
104
115
  | `channels.wecom.sendThinkingMessage` | Send "thinking" placeholder | `true` / `false` | `true` |
105
116
 
117
+ ### Agent Mode Configuration
118
+
119
+ Agent mode uses HTTP webhook callbacks with XML encrypted messages. You need to configure the callback URL in the WeCom admin console under "API Receive" settings.
120
+
121
+ #### Prerequisites
122
+
123
+ 1. Create a self-built app in [WeCom Admin Console](https://work.weixin.qq.com/wework_admin/frame#apps)
124
+ 2. In the app settings, go to "API Receive" (API接收) and configure:
125
+ - **URL**: `https://<your-gateway-host>/plugins/wecom/agent` (or `/plugins/wecom/agent/<accountId>` for multi-account)
126
+ - **Token**: auto-generated or custom
127
+ - **EncodingAESKey**: auto-generated or custom
128
+ 3. Note down the **CorpID**, **CorpSecret**, **Token**, and **EncodingAESKey**
129
+
130
+ #### Quick Setup
131
+
132
+ ```shell
133
+ openclaw config set channels.wecom.agent.corpId <YOUR_CORP_ID>
134
+ openclaw config set channels.wecom.agent.corpSecret <YOUR_CORP_SECRET>
135
+ openclaw config set channels.wecom.agent.agentId <YOUR_AGENT_ID>
136
+ openclaw config set channels.wecom.agent.token <YOUR_CALLBACK_TOKEN>
137
+ openclaw config set channels.wecom.agent.encodingAESKey <YOUR_ENCODING_AES_KEY>
138
+ openclaw config set channels.wecom.enabled true
139
+ openclaw gateway restart
140
+ ```
141
+
142
+ #### JSON Configuration
143
+
144
+ ```json
145
+ {
146
+ "channels": {
147
+ "wecom": {
148
+ "enabled": true,
149
+ "agent": {
150
+ "corpId": "ww1234567890abcdef",
151
+ "corpSecret": "your-corp-secret",
152
+ "agentId": 1000002,
153
+ "token": "your-callback-token",
154
+ "encodingAESKey": "your-encoding-aes-key-43-chars"
155
+ }
156
+ }
157
+ }
158
+ }
159
+ ```
160
+
161
+ #### Agent Config Reference
162
+
163
+ | Config Path | Description | Required |
164
+ |---|---|---|
165
+ | `channels.wecom.agent.corpId` | Enterprise Corp ID | Yes |
166
+ | `channels.wecom.agent.corpSecret` | App secret | Yes |
167
+ | `channels.wecom.agent.agentId` | App agent ID | No (needed for proactive messaging) |
168
+ | `channels.wecom.agent.token` | Callback verification token | Yes |
169
+ | `channels.wecom.agent.encodingAESKey` | Callback encryption key (43 chars) | Yes |
170
+
171
+ #### Webhook Paths
172
+
173
+ | Path | Description |
174
+ |---|---|
175
+ | `/plugins/wecom/agent` | Recommended path (single account) |
176
+ | `/plugins/wecom/agent/<accountId>` | Multi-account path |
177
+ | `/wecom/agent` | Legacy compatible path |
178
+
179
+ ### Outbound Delivery (Bot WS → Agent HTTP Fallback)
180
+
181
+ The plugin uses a **Bot-first, Agent-fallback** strategy for outbound message delivery:
182
+
183
+ 1. **Bot WebSocket available** → send via WS (supports markdown, streaming)
184
+ 2. **Bot WS unavailable** → automatically fallback to **Agent HTTP API** (`cgi-bin/message/send`)
185
+
186
+ This means:
187
+ - **Agent-only accounts** (no Bot configured) can still send proactive messages, cron deliveries, and broadcasts
188
+ - **Target formats** like `party:1`, `tag:Ops`, `user:zhangsan` are fully supported in both paths
189
+ - No manual switching needed — the plugin handles fallback transparently
190
+
191
+ ### Using Both Modes Together
192
+
193
+ Bot and Agent can run simultaneously on the same account. Bot handles WebSocket streaming; Agent handles HTTP webhook callbacks with API-driven replies.
194
+
195
+ ```json
196
+ {
197
+ "channels": {
198
+ "wecom": {
199
+ "enabled": true,
200
+ "botId": "your-bot-id",
201
+ "secret": "your-bot-secret",
202
+ "agent": {
203
+ "corpId": "ww1234567890abcdef",
204
+ "corpSecret": "your-corp-secret",
205
+ "agentId": 1000002,
206
+ "token": "your-callback-token",
207
+ "encodingAESKey": "your-encoding-aes-key-43-chars"
208
+ }
209
+ }
210
+ }
211
+ }
212
+ ```
213
+
214
+ ### Multi-Account Configuration
215
+
216
+ Use `accounts` to configure multiple WeCom accounts, each with optional bot and/or agent sub-configs:
217
+
218
+ ```json
219
+ {
220
+ "channels": {
221
+ "wecom": {
222
+ "enabled": true,
223
+ "accounts": {
224
+ "main": {
225
+ "bot": {
226
+ "botId": "bot-id-1",
227
+ "secret": "secret-1"
228
+ },
229
+ "agent": {
230
+ "corpId": "ww1234567890abcdef",
231
+ "corpSecret": "secret-a",
232
+ "agentId": 1000002,
233
+ "token": "token-a",
234
+ "encodingAESKey": "aes-key-a"
235
+ }
236
+ },
237
+ "support": {
238
+ "agent": {
239
+ "corpId": "ww1234567890abcdef",
240
+ "corpSecret": "secret-b",
241
+ "agentId": 1000003,
242
+ "token": "token-b",
243
+ "encodingAESKey": "aes-key-b"
244
+ }
245
+ }
246
+ }
247
+ }
248
+ }
249
+ }
250
+ ```
251
+
106
252
  ---
107
253
 
108
254
  ## 🔒 Access Control
@@ -198,6 +344,107 @@ In addition to the group allowlist, you can restrict which members within a grou
198
344
 
199
345
  ---
200
346
 
347
+ ## ⏰ Cronjob (Scheduled Tasks)
348
+
349
+ The plugin supports scheduled message delivery via OpenClaw's built-in Cron service. Cron jobs run through the **Agent outbound** channel, so Agent mode must be configured.
350
+
351
+ ### Target Formats
352
+
353
+ The `delivery.to` field supports the following target formats:
354
+
355
+ | Format | Target | Example |
356
+ |--------|--------|---------|
357
+ | `party:<id>` | Department (all members) | `party:1` (root dept = all employees) |
358
+ | `dept:<id>` | Department (alias) | `dept:5` |
359
+ | `tag:<id>` | Tag group | `tag:Ops` |
360
+ | `user:<id>` | Specific user | `user:zhangsan` |
361
+ | `group:<id>` | External group chat | `group:wr123abc` |
362
+ | `chat:<id>` | Group chat (alias) | `chat:wc456def` |
363
+ | Pure number | Auto-detected as department | `1` → `party:1` |
364
+ | `wr...` / `wc...` | Auto-detected as group chat | `wr123` → `chatid` |
365
+ | Other string | Auto-detected as user | `zhangsan` → `touser` |
366
+
367
+ ### Method 1: CLI (Recommended — takes effect immediately)
368
+
369
+ ```shell
370
+ openclaw cron add \
371
+ --name "daily-report" \
372
+ --agent main \
373
+ --cron "0 9 * * 1-5" \
374
+ --message "Good morning! Here is your daily briefing." \
375
+ --deliver \
376
+ --delivery-channel wecom \
377
+ --delivery-to "party:1"
378
+ ```
379
+
380
+ Common CLI commands:
381
+
382
+ ```shell
383
+ openclaw cron list # List all cron jobs
384
+ openclaw cron enable <id> # Enable a job
385
+ openclaw cron disable <id> # Disable a job
386
+ openclaw cron remove <id> # Remove a job
387
+ openclaw cron run <id> # Manually trigger a job
388
+ ```
389
+
390
+ ### Method 2: Edit `jobs.json` (requires gateway restart)
391
+
392
+ File path: `~/.openclaw/cron/jobs.json`
393
+
394
+ ```json
395
+ {
396
+ "version": 1,
397
+ "jobs": [
398
+ {
399
+ "id": "daily-report",
400
+ "name": "Daily Report",
401
+ "agentId": "main",
402
+ "enabled": true,
403
+ "schedule": { "kind": "cron", "expr": "0 9 * * 1-5", "tz": "Asia/Shanghai" },
404
+ "sessionTarget": "isolated",
405
+ "wakeMode": "now",
406
+ "payload": {
407
+ "kind": "agentTurn",
408
+ "message": "Generate today's briefing and send it.",
409
+ "deliver": true,
410
+ "channel": "wecom",
411
+ "to": "party:1"
412
+ },
413
+ "delivery": {
414
+ "mode": "announce",
415
+ "channel": "wecom",
416
+ "to": "party:1",
417
+ "accountId": "main"
418
+ },
419
+ "state": {}
420
+ }
421
+ ]
422
+ }
423
+ ```
424
+
425
+ After editing, restart the gateway:
426
+
427
+ ```shell
428
+ openclaw gateway restart
429
+ ```
430
+
431
+ ### Method 3: Create via chat (takes effect immediately)
432
+
433
+ You can ask the AI agent directly in a WeCom conversation:
434
+
435
+ > "Create a scheduled task: send a daily briefing to the entire company at 9am every weekday"
436
+
437
+ The agent will call the Cron API to create the job — no restart needed.
438
+
439
+ ### Notes
440
+
441
+ - Cron jobs use the **Agent outbound** path — Agent mode (`corpId` / `corpSecret` / `agentId`) must be configured.
442
+ - The server IP must be in the WeCom trusted IP allowlist, or configure `egressProxyUrl` for a fixed egress proxy.
443
+ - Jobs created via CLI or chat API take effect immediately. Manual edits to `jobs.json` require `openclaw gateway restart`.
444
+ - For multi-account setups, set `delivery.accountId` to the target account (e.g. `"main"`, `"support"`).
445
+
446
+ ---
447
+
201
448
  ## 📦 Update
202
449
 
203
450
  ```shell
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
- import { OpenClawPluginApi } from 'openclaw/plugin-sdk/core';
2
-
1
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core";
3
2
  declare const plugin: {
4
3
  id: string;
5
4
  name: string;
@@ -7,5 +6,4 @@ declare const plugin: {
7
6
  configSchema: Record<string, unknown>;
8
7
  register(api: OpenClawPluginApi): void;
9
8
  };
10
-
11
- export { plugin as default };
9
+ export default plugin;
package/dist/index.js ADDED
@@ -0,0 +1,113 @@
1
+ import { emptyPluginConfigSchema } from "./src/openclaw-compat.js";
2
+ import { wecomPlugin } from "./src/channel.js";
3
+ import { createWeComMcpTool } from "./src/mcp/index.js";
4
+ import { setWeComRuntime } from "./src/runtime.js";
5
+ import { CHANNEL_ID, WEBHOOK_PATHS } from "./src/const.js";
6
+ import { handleWecomAgentWebhookRequest } from "./src/agent/webhook.js";
7
+ import { handleWecomWebhookRequest } from "./src/webhook/index.js";
8
+ // ============================================================================
9
+ // 需要自动注入 tools.alsoAllow 的工具名列表
10
+ // ============================================================================
11
+ const REQUIRED_ALSO_ALLOW_TOOLS = ["wecom_mcp"];
12
+ /**
13
+ * 确保 tools.alsoAllow 中包含插件所需的工具名。
14
+ *
15
+ * 逻辑:
16
+ * 1. 读取当前配置
17
+ * 2. 检查 tools.alsoAllow 中是否已包含所需工具
18
+ * 3. 如有缺失,合并写入配置文件
19
+ *
20
+ * 幂等操作——重复调用不会产生副作用。
21
+ * 若 tools.allow 已显式设置(与 alsoAllow 互斥),则跳过注入并打印提示。
22
+ */
23
+ async function ensureToolsAlsoAllow(api) {
24
+ try {
25
+ const cfg = api.runtime.config.loadConfig();
26
+ const tools = cfg.tools ?? {};
27
+ // 如果用户显式配置了 tools.allow(全量白名单),则 alsoAllow 与之互斥,
28
+ // 此时不应自动追加 alsoAllow,避免产生校验冲突
29
+ if (tools.allow && tools.allow.length > 0) {
30
+ const missing = REQUIRED_ALSO_ALLOW_TOOLS.filter((t) => !tools.allow.includes(t));
31
+ if (missing.length > 0) {
32
+ console.warn(`[wecom] tools.allow 已显式设置,无法自动注入 alsoAllow。` +
33
+ `请手动将 ${JSON.stringify(missing)} 加入 tools.allow。`);
34
+ }
35
+ return;
36
+ }
37
+ const existing = tools.alsoAllow ?? [];
38
+ const missing = REQUIRED_ALSO_ALLOW_TOOLS.filter((t) => !existing.includes(t));
39
+ if (missing.length === 0) {
40
+ // 所有工具已在白名单中,无需操作
41
+ return;
42
+ }
43
+ const merged = [...existing, ...missing];
44
+ const nextConfig = {
45
+ ...cfg,
46
+ tools: {
47
+ ...tools,
48
+ alsoAllow: merged,
49
+ },
50
+ };
51
+ await api.runtime.config.writeConfigFile(nextConfig);
52
+ console.log(`[wecom] 已自动将 ${JSON.stringify(missing)} 加入 tools.alsoAllow`);
53
+ }
54
+ catch (err) {
55
+ // 配置写入失败不应阻断 Gateway 启动
56
+ console.error(`[wecom] 自动注入 tools.alsoAllow 失败:`, err instanceof Error ? err.message : String(err));
57
+ }
58
+ }
59
+ const plugin = {
60
+ id: "wecom-openclaw-plugin",
61
+ name: "企业微信",
62
+ description: "企业微信 OpenClaw 插件",
63
+ configSchema: emptyPluginConfigSchema(),
64
+ register(api) {
65
+ setWeComRuntime(api.runtime);
66
+ api.registerChannel({ plugin: wecomPlugin });
67
+ // 注册 wecom_mcp:通过 HTTP 直接调用企业微信 MCP Server
68
+ api.registerTool(createWeComMcpTool(), { name: "wecom_mcp" });
69
+ // 注册 Agent 模式 HTTP 路由(prefix match 覆盖带 accountId 的子路径)
70
+ api.registerHttpRoute({
71
+ path: WEBHOOK_PATHS.AGENT_PLUGIN,
72
+ handler: handleWecomAgentWebhookRequest,
73
+ auth: "plugin",
74
+ match: "prefix",
75
+ });
76
+ api.registerHttpRoute({
77
+ path: WEBHOOK_PATHS.AGENT,
78
+ handler: handleWecomAgentWebhookRequest,
79
+ auth: "plugin",
80
+ match: "prefix",
81
+ });
82
+ // ── 注册 bot Webhook HTTP 路由 ────────────────────────────────────────
83
+ // 前缀匹配模式,同时覆盖 /plugins/wecom 和 /wecom 路径
84
+ const webhookRoutes = [WEBHOOK_PATHS.BOT_PLUGIN, WEBHOOK_PATHS.BOT_ALT, WEBHOOK_PATHS.BOT];
85
+ for (const routePath of webhookRoutes) {
86
+ api.registerHttpRoute({
87
+ path: routePath,
88
+ handler: handleWecomWebhookRequest,
89
+ auth: "plugin",
90
+ match: "prefix",
91
+ });
92
+ }
93
+ // ── Gateway 启动时自动确保 tools.alsoAllow 包含 wecom_mcp ──────────
94
+ // 在 gateway_start 阶段检测并写入,保证插件安装/更新后首次启动即生效
95
+ // api.on("gateway_start", async () => {
96
+ // await ensureToolsAlsoAllow(api);
97
+ // });
98
+ // 注入媒体发送指令和文件大小限制提示词(仅对企业微信 channel 生效)
99
+ api.on("before_prompt_build", (_event, ctx) => {
100
+ // 只在企业微信 channel 的会话中注入,避免影响其他 channel 插件
101
+ if (ctx?.channelId !== CHANNEL_ID) {
102
+ return;
103
+ }
104
+ return {
105
+ appendSystemContext: [
106
+ "重要:涉及发送图片/视频/语音/文件给用户时,请务必使用 `MEDIA:` 指令。详见 wecom-send-media 这个 skill(技能)。",
107
+ "重要:当需要向用户发送结构化卡片消息(如通知、投票、按钮选择等)时,请在回复中直接输出 JSON 代码块(```json ... ```),其中 card_type 字段标明卡片类型。详见 wecom-send-template-card 技能。"
108
+ ].join("\n"),
109
+ };
110
+ });
111
+ },
112
+ };
113
+ export default plugin;
@@ -0,0 +1,57 @@
1
+ import type { OpenClawConfig } from "openclaw/plugin-sdk";
2
+ import type { WeComConfig, WeComAccountConfig, ResolvedWeComAccount } from "./utils.js";
3
+ /**
4
+ * 企业微信多账号配置结构(扩展 WeComConfig)
5
+ */
6
+ export interface WeComMultiAccountConfig extends WeComConfig {
7
+ /** 默认账号 ID */
8
+ defaultAccount?: string;
9
+ /** 多账号配置 */
10
+ accounts?: Record<string, WeComAccountConfig>;
11
+ }
12
+ /**
13
+ * 判断是否为多账号模式(即配置中存在 accounts 字段)。
14
+ * 用于区分单账号/多账号模式的分支判断,替代 `accountId === DEFAULT_ACCOUNT_ID` 的不可靠判断。
15
+ */
16
+ export declare function hasMultiAccounts(cfg: OpenClawConfig): boolean;
17
+ /**
18
+ * 列出所有企业微信账号 ID。
19
+ * 如果没有 accounts 字段,返回 [DEFAULT_ACCOUNT_ID] 以向后兼容。
20
+ */
21
+ export declare function listWeComAccountIds(cfg: OpenClawConfig): string[];
22
+ /**
23
+ * 解析默认账号 ID。
24
+ *
25
+ * 优先级:
26
+ * 1. 显式设置的 defaultAccount
27
+ * 2. 包含 DEFAULT_ACCOUNT_ID 的账号列表
28
+ * 3. 字母序第一个账号
29
+ */
30
+ export declare function resolveDefaultWeComAccountId(cfg: OpenClawConfig): string;
31
+ /**
32
+ * 解析单个企业微信账号的完整配置。
33
+ *
34
+ * 支持:
35
+ * - 显式指定 accountId → 使用该 accountId
36
+ * - 未指定 → 使用默认账号
37
+ * - 单账号模式(无 accounts 字段) → 直接读取顶层配置
38
+ */
39
+ export declare function resolveWeComAccountMulti(params: {
40
+ cfg: OpenClawConfig;
41
+ accountId?: string | null;
42
+ }): ResolvedWeComAccount;
43
+ /**
44
+ * 列出所有已启用且已配置凭据的账号。
45
+ */
46
+ export declare function listEnabledWeComAccounts(cfg: OpenClawConfig): ResolvedWeComAccount[];
47
+ /**
48
+ * 写入企业微信账户配置(自动区分单账号/多账号模式)。
49
+ *
50
+ * - 单账号模式(无 accounts 字段):写入顶层 channels.wecom
51
+ * - 多账号模式:写入 channels.wecom.accounts[accountId]
52
+ *
53
+ * @param cfg 当前全局配置
54
+ * @param updates 要写入的部分配置字段
55
+ * @param accountId 目标账号 ID(默认写入默认账号)
56
+ */
57
+ export declare function setWeComAccountMulti(cfg: OpenClawConfig, updates: Partial<WeComConfig>, accountId?: string): OpenClawConfig;