@yanhaidao/wecom 2.3.160 → 2.3.190

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 (49) hide show
  1. package/README.md +294 -379
  2. package/SKILLS_CAL.md +895 -0
  3. package/SKILLS_DOC.md +2288 -0
  4. package/changelog/v2.3.18.md +22 -0
  5. package/changelog/v2.3.19.md +73 -0
  6. package/index.ts +39 -3
  7. package/package.json +2 -3
  8. package/src/agent/handler.event-filter.test.ts +11 -0
  9. package/src/agent/handler.ts +732 -643
  10. package/src/app/account-runtime.ts +46 -20
  11. package/src/app/index.ts +20 -1
  12. package/src/capability/bot/stream-orchestrator.ts +1 -1
  13. package/src/capability/calendar/SKILLS_CHECKLIST.md +251 -0
  14. package/src/capability/calendar/client.ts +815 -0
  15. package/src/capability/calendar/index.ts +3 -0
  16. package/src/capability/calendar/schema.ts +417 -0
  17. package/src/capability/calendar/tool.ts +417 -0
  18. package/src/capability/calendar/types.ts +309 -0
  19. package/src/capability/doc/client.ts +788 -64
  20. package/src/capability/doc/schema.ts +419 -318
  21. package/src/capability/doc/tool.ts +1517 -1178
  22. package/src/capability/doc/types.ts +130 -14
  23. package/src/capability/mcp/index.ts +10 -0
  24. package/src/capability/mcp/schema.ts +107 -0
  25. package/src/capability/mcp/tool.ts +170 -0
  26. package/src/capability/mcp/transport.ts +394 -0
  27. package/src/channel.ts +70 -28
  28. package/src/config/index.ts +7 -1
  29. package/src/config/media.test.ts +113 -0
  30. package/src/config/media.ts +133 -6
  31. package/src/config/schema.ts +74 -102
  32. package/src/outbound.test.ts +250 -15
  33. package/src/outbound.ts +155 -30
  34. package/src/runtime/reply-orchestrator.test.ts +35 -2
  35. package/src/runtime/reply-orchestrator.ts +14 -2
  36. package/src/runtime/routing-bridge.test.ts +115 -0
  37. package/src/runtime/routing-bridge.ts +26 -1
  38. package/src/runtime/session-manager.ts +20 -6
  39. package/src/runtime/source-registry.ts +165 -0
  40. package/src/transport/bot-webhook/inbound-normalizer.ts +4 -4
  41. package/src/transport/bot-ws/media.test.ts +44 -0
  42. package/src/transport/bot-ws/media.ts +272 -0
  43. package/src/transport/bot-ws/reply.test.ts +216 -18
  44. package/src/transport/bot-ws/reply.ts +116 -21
  45. package/src/transport/bot-ws/sdk-adapter.test.ts +64 -1
  46. package/src/transport/bot-ws/sdk-adapter.ts +89 -12
  47. package/src/types/config.ts +3 -0
  48. package/.claude/settings.local.json +0 -11
  49. package/docs/update-content-fix.md +0 -135
@@ -0,0 +1,22 @@
1
+ # OpenClaw WeCom 插件 v2.3.18 变更简报
2
+
3
+ > [!TIP]
4
+ > **企业微信面向中小企业的新能力开放版本**:`v2.3.18` 重点完善了 `wecom` 插件在 Bot WebSocket 场景下的能力层。现在,面向 5 人及以下小企业,OpenClaw 已支持以用户个人身份在企业微信内使用文档读写、日程读写、会议读写、待办读写、通讯录查询等能力。同时,本次也补齐了 Bot WS 媒体发送、建立了 Bot 与 Agent 双平面路由,并修复了企业微信里容易卡在“正在思考...”不结束的问题。
5
+
6
+ ## 2026-03-18(v2.3.18)
7
+ - 【中小企业能力开放】🚀 **[重大更新]** 面向 5 人及以下小企业,OpenClaw 在企业微信内正式开放以用户个人身份使用的协作能力入口。现在,大模型可以在具备相应授权的前提下,调用企业微信文档读写、日程读写、会议读写、待办读写以及通讯录查询等能力,把原本分散在多个协作入口中的企业操作集中到同一条智能对话链路中。
8
+ - 【新增 Bot WS MCP 工具层】新增 `wecom_mcp` 工具,将企业微信 Bot WS 能力以挂载式能力层接入 `wecom` 插件。现在 Bot 侧可以按业务类别动态获取 MCP 配置,并把企业微信开放的能力暴露给大模型调用。
9
+ - 【建立 Bot / Agent 双平面路由】新增基于会话来源的能力分流。Bot WS 会话优先使用 `wecom_mcp`;Agent 回调会话继续保留原生 `wecom_doc`、`wecom_calendar` 工具链,避免不同能力面互相干扰。
10
+ - 【多账号能力隔离加强】MCP 相关缓存和状态改为按 `accountId + category` 隔离。在多账号矩阵下,同一类能力不会再共用同一份 Bot 侧配置,减少串账号、串上下文、串连接状态的问题。
11
+ - 【补齐 Bot WS 命令与媒体链】扩展 Bot WS 运行时接口,除了主动文本发送外,现在还支持命令桥接、连接状态探测和媒体发送。Bot WebSocket 会话下的图片、文件回复不再必须依赖 Agent API 补送。
12
+ - 【新增媒体发送提示注入】在企业微信 Bot WS 会话里定向注入 `MEDIA:` 使用提示,帮助模型更稳定地触发图片和文件回复,同时避免把这类提示扩散到非 WeCom 或 Agent 会话。
13
+ - 【修复回复流不收口问题】**[重要修复]** 处理 Bot WS 回复时,带媒体的中间块不再错误中断文本发送。现在文本会先正常下发,媒体在结束阶段继续处理;如果上游没有显式 final,系统也会自动补一个收口帧,避免企业微信里长期停留在“正在思考...”。
14
+ - 【欢迎语路径提速】`enter_chat` 欢迎事件在配置静态欢迎语时改为直发,不再额外启动完整推理流程。首次进入会话时的响应更直接,链路也更短。
15
+ - 【运行时日志增强】新增更细的派发与投递日志,包括 `dispatch-start`、`dispatch-done`、`dispatch-fail`、`deliver-start`、`deliver-done`。现在排查问题时可以更快区分是模型处理慢、回复已被企微确认、MCP 类别未开通,还是本地媒体路径被限制拦截。
16
+ - 【能力边界提示更明确】当企业微信后台只开放部分能力时,插件会更明确地把限制反馈给用户和日志。例如只开通文档类能力时,待办、会议、日程类请求会直接提示当前账号尚未开放对应能力,而不是表现成模糊失败。
17
+
18
+ ## 升级提示
19
+ - 执行 `openclaw plugins update wecom` 即可升级到 `v2.3.18`。
20
+ - 本次版本是企业微信能力面的重要开放版本,尤其适合希望在企业微信内直接完成文档、日程、会议、待办与通讯录协作的小型团队。
21
+ - 如果你之前在企业微信 Bot WS 会话里只看到反复“正在思考...”、最终不出结果,本次升级后应已修复。
22
+ - 如果你希望在企业微信里直接使用会议、待办、日程等 Bot 侧能力,请同时确认企业微信后台已经为当前 Bot 开通相应业务类别;插件侧已经具备调用链,但实际可用范围仍以企业微信侧授权为准。
@@ -0,0 +1,73 @@
1
+ # OpenClaw WeCom 插件 v2.3.19 变更简报
2
+
3
+ > [!TIP]
4
+ > `v2.3.19` 主要修了四件和真实使用强相关的问题:第一,本机图片/文件终于能更自然地发出去,不再默认只认 OpenClaw 自己目录里的文件;第二,走 Bot WebSocket 时,`dynamicAgents` 也会真正生效,不会再出现“同样开了动态路由,但 WS 会话还是串到主 Agent”这种割裂行为;第三,媒体大小上限开始统一跟随 OpenClaw 标准配置 `mediaMaxMb`,不再是 WeCom 插件自己一套、OpenClaw 主配置又是一套;第四,Bot WS 对话里的图片/文件现在会尽量留在当前 Bot WS 对话里发送,不再静默切到 Agent 私聊链路。
5
+
6
+ ## 2026-03-19(v2.3.19)
7
+ - 【修复 WS 不走 dynamicAgents】**[重要修复]** 之前 `dynamicAgents` 只在旧消息链路上生效,新的 Bot WebSocket 统一运行时没有把这层路由覆盖带进去。结果就是,同样一份配置,在 Webhook 或 Agent 路径上能按“每个用户 / 每个群”隔离会话,但走 WS 时却可能重新落回主 Agent。现在 WS 运行时也会执行同样的动态路由逻辑,单聊、群聊的隔离行为终于统一了。
8
+ - 【修正 Bot WS 对话里的媒体回落策略】**[重要修复]** 如果当前消息本来就在 Bot WS 对话流里,图片/文件发送现在会优先并固定留在同一个 Bot WS 会话内处理。一旦已经尝试过 WS 发送,就不再静默回落到 Agent 私聊链路,避免用户明明在一个 Bot 对话里操作,结果媒体却从另一个 Agent 会话发出来。这个调整只针对 Bot WS,对 Bot Webhook 模式没有影响。
9
+ - 【统一媒体大小配置到 OpenClaw 标准】之前 WeCom 插件内部主要认自己的 `channels.wecom.media.maxBytes`,而不是 OpenClaw 通用的 `mediaMaxMb`。这会带来一个很直接的问题:你明明已经在 OpenClaw 里把媒体大小放宽了,WeCom 这边却还像没看见一样。现在插件会优先读取 `channels.wecom.mediaMaxMb`,并支持 `channels.wecom.accounts.<accountId>.mediaMaxMb` 做账号级覆盖;旧的 `channels.wecom.media.maxBytes` 仍然保留兼容,但只作为历史配置兜底。
10
+ - 【补齐 Bot WS 媒体发送链路的大小透传】Bot WS 在读取本地文件、下载远程媒体并上传到企业微信前,现在会真正带上解析后的 `mediaMaxMb` 上限,而不是继续走内部固定值。换句话说,媒体大小限制终于从“写在配置里”和“运行时真的执行”两边对齐了。
11
+ - 【放宽本地文件默认可发送目录】之前本地媒体白名单更偏向 OpenClaw 自己的状态目录,所以像 `~/Downloads/01.png` 这种很自然的用户文件路径,虽然文件确实存在,也会被当成“不允许发送”。现在插件默认额外放行常见用户目录:`~/Desktop`、`~/Documents`、`~/Downloads`、`~/Movies`、`~/Pictures`。对普通用户来说,这意味着“桌面、下载、图片目录里的文件”现在默认就更符合直觉地可发送了。
12
+ - 【支持继续追加自定义本地媒体目录】除了默认目录外,现在仍然可以通过 `channels.wecom.media.localRoots` 继续追加共享盘、挂载盘、业务导出目录等自定义路径。这里的设计原则很简单:默认给出大多数人会用到的目录,但不假设所有企业的数据都在同一个地方。
13
+ - 【文案与排障提示同步更新】当媒体太大或解密失败时,提示语现在会直接指向 `channels.wecom.mediaMaxMb` 这套推荐配置,避免用户继续被旧的 `media.maxBytes` 误导。
14
+
15
+ ## 这次改动背后的最小理解模型
16
+
17
+ 把这次版本理解成四句话就够了:
18
+
19
+ 1. **会话该隔离的,要真的隔离。**
20
+ 你开了 `dynamicAgents`,系统就应该不管走 Webhook、Agent Callback 还是 Bot WS,都稳定地把“不同用户 / 不同群”落到不同会话上,而不是不同链路表现不一致。
21
+
22
+ 2. **从哪个对话开始,就该尽量在哪个对话里发回去。**
23
+ 如果用户是在 Bot WS 对话里让系统发图,那么结果也应该优先回到这个 Bot WS 对话,而不是悄悄切到 Agent 私聊。否则用户看到的“会话边界”和系统内部实际走的链路会分裂。
24
+
25
+ 3. **配置写在哪里,运行时就该认哪里。**
26
+ OpenClaw 既然已经把媒体大小的标准字段定成 `mediaMaxMb`,WeCom 插件就不该再偷偷主要走自己那套 `media.maxBytes`。统一之后,用户只需要记住一套规则。
27
+
28
+ 4. **用户的文件,默认应该在用户常用目录里。**
29
+ 大多数人发文件,不会先把图拷进 `.openclaw/media`,而是直接从下载目录、桌面、图片目录发。默认路径如果违背这个常识,系统虽然“安全”,但体验是不成立的。
30
+
31
+ ## 推荐配置
32
+
33
+ ```json
34
+ {
35
+ "channels": {
36
+ "wecom": {
37
+ "mediaMaxMb": 50,
38
+ "media": {
39
+ "tempDir": "/tmp/openclaw-wecom-media",
40
+ "localRoots": [
41
+ "/srv/company-share",
42
+ "/data/reports"
43
+ ]
44
+ },
45
+ "dynamicAgents": {
46
+ "enabled": true,
47
+ "dmCreateAgent": true,
48
+ "groupEnabled": true,
49
+ "adminUsers": ["your-admin-userid"]
50
+ }
51
+ }
52
+ }
53
+ }
54
+ ```
55
+
56
+ ## 升级后你应该感受到的变化
57
+
58
+ - 从 `Downloads`、`Desktop` 这类常见目录直接发图、发文件,更容易一次成功。
59
+ - 同样开启 `dynamicAgents` 的前提下,Bot WS 会话也会像其他链路一样稳定隔离,不再更容易串上下文。
60
+ - 如果当前就是 Bot WS 对话流,发图、发文件会优先留在这个对话里处理,不会再更容易“跳”到 Agent 私聊。
61
+ - 调整 `mediaMaxMb` 后,WeCom 插件的上传 / 解密 / 读取链路会真正跟着变化,而不是“配置改了,行为没改”。
62
+
63
+ ## 仍然需要知道的边界
64
+
65
+ - `mediaMaxMb` 控制的是 OpenClaw 这边愿意读取和处理多大的媒体,不代表企业微信协议本身没有限制。
66
+ - 企业微信自身的媒体限制仍然存在,例如图片 / 视频超过 10MB、语音超过 2MB、文件超过 20MB 时,最终行为仍受企业微信接口约束。
67
+ - 旧配置 `channels.wecom.media.maxBytes` 目前还兼容,但新配置建议统一迁移到 `channels.wecom.mediaMaxMb`。
68
+
69
+ ## 升级提示
70
+
71
+ - 执行 `openclaw plugins update wecom` 即可升级到 `v2.3.19`。
72
+ - 如果你之前遇到“WS 开了 dynamicAgents 但还是串到主 Agent”“明明在 Bot WS 对话里发图,结果却从 Agent 私聊发出来”,或“明明改了媒体大小配置却没有生效”,这一版就是针对这些问题的直接修复。
73
+ - 如果你的文件仍然不在默认目录内,例如 NAS、共享盘或业务导出盘,请继续在 `channels.wecom.media.localRoots` 中追加对应路径。
package/index.ts CHANGED
@@ -3,11 +3,28 @@
3
3
  */
4
4
  import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
5
5
  import { emptyPluginConfigSchema } from "openclaw/plugin-sdk";
6
-
6
+ import { registerWecomCalendarTools } from "./src/capability/calendar/tool.js";
7
+ import { registerWecomDocTools } from "./src/capability/doc/tool.js";
8
+ import { createWeComMcpToolFactory } from "./src/capability/mcp/index.js";
9
+ import { wecomPlugin } from "./src/channel.js";
7
10
  import { handleWecomWebhookRequest } from "./src/monitor.js";
8
11
  import { setWecomRuntime } from "./src/runtime.js";
9
- import { wecomPlugin } from "./src/channel.js";
10
- import { registerWecomDocTools } from "./src/capability/doc/tool.js";
12
+ import { isWecomBotWsSource } from "./src/runtime/source-registry.js";
13
+
14
+ const WECOM_BOT_WS_MEDIA_GUIDANCE = [
15
+ "【WeCom Bot WS 媒体发送】",
16
+ "当前会话支持企业微信 Bot WS 媒体发送。",
17
+ "当你需要发送图片、文件、视频或语音时,必须在回复中单独一行使用 MEDIA: 指令,后面跟本地文件路径。",
18
+ "格式:MEDIA: /文件的绝对路径",
19
+ "示例:",
20
+ " MEDIA: ~/.openclaw/output.png",
21
+ " MEDIA: ~/.openclaw/report.pdf",
22
+ "注意事项:",
23
+ "- MEDIA: 必须单独成行并以 MEDIA: 开头",
24
+ "- 建议优先使用本地可访问路径,而不是远程 URL",
25
+ "- 图片和视频超过 10MB、语音超过 2MB、文件超过 20MB 时可能会降级或发送失败",
26
+ "- 语音消息仅原生支持 AMR;其他音频格式会按文件发送",
27
+ ].join("\n");
11
28
 
12
29
  const plugin = {
13
30
  id: "wecom",
@@ -37,6 +54,25 @@ const plugin = {
37
54
 
38
55
  // Register WeCom Doc Tools
39
56
  registerWecomDocTools(api);
57
+ registerWecomCalendarTools(api);
58
+ api.registerTool(createWeComMcpToolFactory(), { name: "wecom_mcp" });
59
+
60
+ api.on("before_prompt_build", (_event, ctx) => {
61
+ if (ctx.channelId !== "wecom") {
62
+ return;
63
+ }
64
+ if (
65
+ !isWecomBotWsSource({
66
+ sessionKey: ctx.sessionKey,
67
+ sessionId: ctx.sessionId,
68
+ })
69
+ ) {
70
+ return;
71
+ }
72
+ return {
73
+ appendSystemContext: WECOM_BOT_WS_MEDIA_GUIDANCE,
74
+ };
75
+ });
40
76
  },
41
77
  };
42
78
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yanhaidao/wecom",
3
- "version": "2.3.160",
3
+ "version": "2.3.190",
4
4
  "type": "module",
5
5
  "description": "OpenClaw 企业微信(WeCom)插件,默认 Bot WebSocket,支持加密媒体解密、Agent 主动发消息与多账号接入",
6
6
  "repository": {
@@ -42,8 +42,7 @@
42
42
  "dependencies": {
43
43
  "@wecom/aibot-node-sdk": "^1.0.0",
44
44
  "fast-xml-parser": "5.3.4",
45
- "undici": "^7.20.0",
46
- "zod": "^4.3.6"
45
+ "undici": "^7.20.0"
47
46
  },
48
47
  "peerDependencies": {
49
48
  "openclaw": ">=2026.2.24"
@@ -49,6 +49,17 @@ describe("shouldProcessAgentInboundMessage", () => {
49
49
  expect(missingSender.reason).toBe("missing_sender");
50
50
  });
51
51
 
52
+
53
+ it("allows group chat messages when sender id is missing", () => {
54
+ const groupWithoutSender = shouldProcessAgentInboundMessage({
55
+ msgType: "file",
56
+ fromUser: " ",
57
+ chatId: "wrbchat_123",
58
+ });
59
+ expect(groupWithoutSender.shouldProcess).toBe(true);
60
+ expect(groupWithoutSender.reason).toBe("missing_sender_but_group_chat");
61
+ });
62
+
52
63
  it("allows normal user text message processing", () => {
53
64
  const normalMessage = shouldProcessAgentInboundMessage({
54
65
  msgType: "text",