[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"similar-sunnoy--openclaw-plugin-wecom":3,"tool-sunnoy--openclaw-plugin-wecom":61},[4,17,27,36,44,53],{"id":5,"name":6,"github_repo":7,"description_zh":8,"stars":9,"difficulty_score":10,"last_commit_at":11,"category_tags":12,"status":16},1381,"everything-claude-code","affaan-m\u002Feverything-claude-code","everything-claude-code 是一套专为 AI 编程助手（如 Claude Code、Codex、Cursor 等）打造的高性能优化系统。它不仅仅是一组配置文件，而是一个经过长期实战打磨的完整框架，旨在解决 AI 代理在实际开发中面临的效率低下、记忆丢失、安全隐患及缺乏持续学习能力等核心痛点。\n\n通过引入技能模块化、直觉增强、记忆持久化机制以及内置的安全扫描功能，everything-claude-code 能显著提升 AI 在复杂任务中的表现，帮助开发者构建更稳定、更智能的生产级 AI 代理。其独特的“研究优先”开发理念和针对 Token 消耗的优化策略，使得模型响应更快、成本更低，同时有效防御潜在的攻击向量。\n\n这套工具特别适合软件开发者、AI 研究人员以及希望深度定制 AI 工作流的技术团队使用。无论您是在构建大型代码库，还是需要 AI 协助进行安全审计与自动化测试，everything-claude-code 都能提供强大的底层支持。作为一个曾荣获 Anthropic 黑客大奖的开源项目，它融合了多语言支持与丰富的实战钩子（hooks），让 AI 真正成长为懂上",158594,2,"2026-04-16T23:34:05",[13,14,15],"开发框架","Agent","语言模型","ready",{"id":18,"name":19,"github_repo":20,"description_zh":21,"stars":22,"difficulty_score":23,"last_commit_at":24,"category_tags":25,"status":16},8272,"opencode","anomalyco\u002Fopencode","OpenCode 是一款开源的 AI 编程助手（Coding Agent），旨在像一位智能搭档一样融入您的开发流程。它不仅仅是一个代码补全插件，而是一个能够理解项目上下文、自主规划任务并执行复杂编码操作的智能体。无论是生成全新功能、重构现有代码，还是排查难以定位的 Bug，OpenCode 都能通过自然语言交互高效完成，显著减少开发者在重复性劳动和上下文切换上的时间消耗。\n\n这款工具专为软件开发者、工程师及技术研究人员设计，特别适合希望利用大模型能力来提升编码效率、加速原型开发或处理遗留代码维护的专业人群。其核心亮点在于完全开源的架构，这意味着用户可以审查代码逻辑、自定义行为策略，甚至私有化部署以保障数据安全，彻底打破了传统闭源 AI 助手的“黑盒”限制。\n\n在技术体验上，OpenCode 提供了灵活的终端界面（Terminal UI）和正在测试中的桌面应用程序，支持 macOS、Windows 及 Linux 全平台。它兼容多种包管理工具，安装便捷，并能无缝集成到现有的开发环境中。无论您是追求极致控制权的资深极客，还是渴望提升产出的独立开发者，OpenCode 都提供了一个透明、可信",144296,1,"2026-04-16T14:50:03",[14,26],"插件",{"id":28,"name":29,"github_repo":30,"description_zh":31,"stars":32,"difficulty_score":10,"last_commit_at":33,"category_tags":34,"status":16},6121,"gemini-cli","google-gemini\u002Fgemini-cli","gemini-cli 是一款由谷歌推出的开源 AI 命令行工具，它将强大的 Gemini 大模型能力直接集成到用户的终端环境中。对于习惯在命令行工作的开发者而言，它提供了一条从输入提示词到获取模型响应的最短路径，无需切换窗口即可享受智能辅助。\n\n这款工具主要解决了开发过程中频繁上下文切换的痛点，让用户能在熟悉的终端界面内直接完成代码理解、生成、调试以及自动化运维任务。无论是查询大型代码库、根据草图生成应用，还是执行复杂的 Git 操作，gemini-cli 都能通过自然语言指令高效处理。\n\n它特别适合广大软件工程师、DevOps 人员及技术研究人员使用。其核心亮点包括支持高达 100 万 token 的超长上下文窗口，具备出色的逻辑推理能力；内置 Google 搜索、文件操作及 Shell 命令执行等实用工具；更独特的是，它支持 MCP（模型上下文协议），允许用户灵活扩展自定义集成，连接如图像生成等外部能力。此外，个人谷歌账号即可享受免费的额度支持，且项目基于 Apache 2.0 协议完全开源，是提升终端工作效率的理想助手。",100752,"2026-04-10T01:20:03",[26,14,35,13],"图像",{"id":37,"name":38,"github_repo":39,"description_zh":40,"stars":41,"difficulty_score":10,"last_commit_at":42,"category_tags":43,"status":16},4721,"markitdown","microsoft\u002Fmarkitdown","MarkItDown 是一款由微软 AutoGen 团队打造的轻量级 Python 工具，专为将各类文件高效转换为 Markdown 格式而设计。它支持 PDF、Word、Excel、PPT、图片（含 OCR）、音频（含语音转录）、HTML 乃至 YouTube 链接等多种格式的解析，能够精准提取文档中的标题、列表、表格和链接等关键结构信息。\n\n在人工智能应用日益普及的今天，大语言模型（LLM）虽擅长处理文本，却难以直接读取复杂的二进制办公文档。MarkItDown 恰好解决了这一痛点，它将非结构化或半结构化的文件转化为模型“原生理解”且 Token 效率极高的 Markdown 格式，成为连接本地文件与 AI 分析 pipeline 的理想桥梁。此外，它还提供了 MCP（模型上下文协议）服务器，可无缝集成到 Claude Desktop 等 LLM 应用中。\n\n这款工具特别适合开发者、数据科学家及 AI 研究人员使用，尤其是那些需要构建文档检索增强生成（RAG）系统、进行批量文本分析或希望让 AI 助手直接“阅读”本地文件的用户。虽然生成的内容也具备一定可读性，但其核心优势在于为机器",93400,"2026-04-06T19:52:38",[26,13],{"id":45,"name":46,"github_repo":47,"description_zh":48,"stars":49,"difficulty_score":50,"last_commit_at":51,"category_tags":52,"status":16},4487,"LLMs-from-scratch","rasbt\u002FLLMs-from-scratch","LLMs-from-scratch 是一个基于 PyTorch 的开源教育项目，旨在引导用户从零开始一步步构建一个类似 ChatGPT 的大型语言模型（LLM）。它不仅是同名技术著作的官方代码库，更提供了一套完整的实践方案，涵盖模型开发、预训练及微调的全过程。\n\n该项目主要解决了大模型领域“黑盒化”的学习痛点。许多开发者虽能调用现成模型，却难以深入理解其内部架构与训练机制。通过亲手编写每一行核心代码，用户能够透彻掌握 Transformer 架构、注意力机制等关键原理，从而真正理解大模型是如何“思考”的。此外，项目还包含了加载大型预训练权重进行微调的代码，帮助用户将理论知识延伸至实际应用。\n\nLLMs-from-scratch 特别适合希望深入底层原理的 AI 开发者、研究人员以及计算机专业的学生。对于不满足于仅使用 API，而是渴望探究模型构建细节的技术人员而言，这是极佳的学习资源。其独特的技术亮点在于“循序渐进”的教学设计：将复杂的系统工程拆解为清晰的步骤，配合详细的图表与示例，让构建一个虽小但功能完备的大模型变得触手可及。无论你是想夯实理论基础，还是为未来研发更大规模的模型做准备",90106,3,"2026-04-06T11:19:32",[15,35,14,13],{"id":54,"name":55,"github_repo":56,"description_zh":57,"stars":58,"difficulty_score":10,"last_commit_at":59,"category_tags":60,"status":16},3704,"NextChat","ChatGPTNextWeb\u002FNextChat","NextChat 是一款轻量且极速的 AI 助手，旨在为用户提供流畅、跨平台的大模型交互体验。它完美解决了用户在多设备间切换时难以保持对话连续性，以及面对众多 AI 模型不知如何统一管理的痛点。无论是日常办公、学习辅助还是创意激发，NextChat 都能让用户随时随地通过网页、iOS、Android、Windows、MacOS 或 Linux 端无缝接入智能服务。\n\n这款工具非常适合普通用户、学生、职场人士以及需要私有化部署的企业团队使用。对于开发者而言，它也提供了便捷的自托管方案，支持一键部署到 Vercel 或 Zeabur 等平台。\n\nNextChat 的核心亮点在于其广泛的模型兼容性，原生支持 Claude、DeepSeek、GPT-4 及 Gemini Pro 等主流大模型，让用户在一个界面即可自由切换不同 AI 能力。此外，它还率先支持 MCP（Model Context Protocol）协议，增强了上下文处理能力。针对企业用户，NextChat 提供专业版解决方案，具备品牌定制、细粒度权限控制、内部知识库整合及安全审计等功能，满足公司对数据隐私和个性化管理的高标准要求。",87618,"2026-04-05T07:20:52",[13,15],{"id":62,"github_repo":63,"name":64,"description_en":65,"description_zh":66,"ai_summary_zh":66,"readme_en":67,"readme_zh":68,"quickstart_zh":69,"use_case_zh":70,"hero_image_url":71,"owner_login":72,"owner_name":73,"owner_avatar_url":74,"owner_bio":75,"owner_company":76,"owner_location":76,"owner_email":76,"owner_twitter":76,"owner_website":77,"owner_url":78,"languages":79,"stars":84,"forks":85,"last_commit_at":86,"license":87,"difficulty_score":10,"env_os":88,"env_gpu":89,"env_ram":88,"env_deps":90,"category_tags":97,"github_topics":98,"view_count":10,"oss_zip_url":76,"oss_zip_packed_at":76,"status":16,"created_at":109,"updated_at":110,"faqs":111,"releases":147},8333,"sunnoy\u002Fopenclaw-plugin-wecom","openclaw-plugin-wecom","企业微信 AI 机器人插件 - Enterprise WeChat (WeCom) AI Bot plugin for OpenClaw. 支持流式输出、动态 Agent 管理、群聊集成、指令白名单等功能。","openclaw-plugin-wecom 是一款专为 OpenClaw 框架打造的企业微信（WeCom）增强插件，旨在让 AI 机器人更深度、灵活地融入企业办公场景。它解决了官方插件在多账号管理、动态会话隔离及高级消息交互方面的局限，帮助团队构建更稳健的企业级 AI 应用。\n\n该工具特别适合需要定制企业微信 AI 助手的开发者和技术团队使用。其核心亮点在于支持 WebSocket 长连接与流式输出，确保对话响应实时流畅；同时提供动态 Agent 路由功能，可按用户或群组自动隔离会话与工作区，实现精细化的权限管理。此外，它还具备指令白名单、运行时配额感知、自建应用主动推送（支持文本、图片、文件）以及消息去重等高级特性，有效防止资源滥用并提升系统稳定性。对于从传统 HTTP 回调模式迁移的用户，openclaw-plugin-wecom 提供了平滑的过渡方案，仅需配置 BotID 和密钥即可启用现代化的长连接模式，大幅降低了运维复杂度。无论是构建内部客服机器人还是团队协作助手，它都能提供强大的底层支撑。","# OpenClaw 企业微信（WeCom）增强插件\n\n[![npm](https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fv\u002F@sunnoy\u002Fwecom)](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@sunnoy\u002Fwecom)\n[![license](https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fl\u002F@sunnoy\u002Fwecom)](LICENSE)\n\n`@sunnoy\u002Fwecom` 是 [OpenClaw](https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw) 企业微信渠道的**社区增强插件**，基于官方 [`@wecom\u002Fwecom-openclaw-plugin`](https:\u002F\u002Fgithub.com\u002FWecomTeam\u002Fwecom-openclaw-plugin) 的 WebSocket 长连接骨架，提供多账号管理、动态 Agent 隔离、Agent API \u002F Webhook 增强出站、指令白名单、配额感知等企业级特性。\n\n底层 SDK：[`@wecom\u002Faibot-node-sdk`](https:\u002F\u002Fgithub.com\u002FWecomTeam\u002Faibot-node-sdk) — 企业微信智能机器人 Node.js SDK。\n\n> **⚠️ 从 HTTP 回调迁移到长连接：** 2.0 版本完全采用企业微信 [AI 机器人 WebSocket 长连接模式](https:\u002F\u002Fopen.work.weixin.qq.com\u002Fhelp2\u002Fpc\u002Fcat?doc_id=21657)。如果你之前使用 HTTP 回调（Token + EncodingAESKey + 回调 URL），需要在企业微信管理后台将机器人切换到长连接模式，然后删除旧的回调配置。切换后只需 `botId` 和 `secret` 即可接入。\n\n> **2.1 新增：** 在 WS 长连接之外，2.1 版本新增了企业微信**自建应用\"接收消息\"HTTP 回调**作为可选入站通道。在 `channels.wecom.agent` 下配置 `callback.token`、`callback.encodingAESKey`、`callback.path` 即可同时启用，与 WS 通道并行运行，互不影响。\n\n## 相比官方插件的增强特性\n\n下表列出了本插件相比 [官方 WeCom OpenClaw 插件](https:\u002F\u002Fgithub.com\u002FWecomTeam\u002Fwecom-openclaw-plugin)（[npm](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@wecom\u002Fwecom-openclaw-plugin)）额外提供的能力：\n\n| 特性 | 官方插件 | 本插件 |\n| --- | :---: | :---: |\n| WebSocket 长连接 + 流式回复 | ✅ | ✅ |\n| 私聊 \u002F 群聊接收 | ✅ | ✅ |\n| DM 准入策略（pairing \u002F open \u002F allowlist \u002F disabled） | ✅ | ✅ |\n| 群聊准入策略（open \u002F allowlist \u002F disabled） | ✅ | ✅ |\n| 按群配置发送者白名单 | ✅ | ✅ |\n| 思考占位（`\u003Cthink>` 占位符） | ✅ | ✅ |\n| CLI 交互式配置向导 | ✅ | ✅ |\n| **多账号管理**（多 Bot 独立配置、共享字段继承） | ❌ | ✅ |\n| **动态 Agent 路由**（按用户 \u002F 群自动隔离会话与工作区） | ❌ | ✅ |\n| **Workspace 模板**（自动为新 Agent 复制 AGENTS.md 等引导文件） | ❌ | ✅ |\n| **Agent API 增强出站**（自建应用主动发送文本、图片、文件） | ❌ | ✅ |\n| **部门 \u002F 标签目标发送**（`party:` \u002F `tag:` 寻址） | ❌ | ✅ |\n| **Webhook Bot 群通知**（命名 webhook 映射，markdown \u002F 图片 \u002F 文件） | ❌ | ✅ |\n| **指令白名单**（限制普通用户可执行的 slash 命令） | ❌ | ✅ |\n| **管理员绕过**（命令白名单 + 动态 Agent 路由） | ❌ | ✅ |\n| **运行时配额感知**（被动回复 24h 窗口 + 主动发送额度追踪与告警） | ❌ | ✅ |\n| **Pending Reply 重试**（WS 断连后自动通过 Agent API 补发未送达回复） | ❌ | ✅ |\n| **Reasoning 流式节流**（800ms 节流防止 SDK 队列溢出） | ❌ | ✅ |\n| **`\u003Cthink>` 标签规范化**（兼容 `\u003Cthinking>` \u002F `\u003Cthought>` 等变体） | ❌ | ✅ |\n| **Reply 媒体指令解析**（自动提取 LLM 输出中的 `MEDIA:` \u002F `FILE:` 路径） | ❌ | ✅ |\n| **出站代理**（`network.egressProxyUrl`） | ❌ | ✅ |\n| **自定义 API 基础地址**（`network.apiBaseUrl` \u002F `WECOM_API_BASE_URL`） | ❌ | ✅ |\n| **Bindings 路由**（固定绑定企业微信账号到指定 Agent） | ❌ | ✅ |\n| **消息去重**（reqId + msgId 去重，防止重复处理） | ❌ | ✅ |\n| **入站图文混排**（`mixed` 消息拆解为文本 + 图片） | ❌ | ✅ |\n| **入站语音转写**（`voice.content` 自动提取） | ❌ | ✅ |\n| **入站引用消息**（`quote` 上下文透传） | ❌ | ✅ |\n| **自建应用回调入站**（HTTP 回调作为独立入站通道，与 WS 并行） | ❌ | ✅ |\n| **Agent API Markdown 回复**（回调入站回复默认 markdown 格式） | ❌ | ✅ |\n| **入站\u002F出站信息日志**（WS \u002F CB 收发日志，便于追踪消息流） | ❌ | ✅ |\n\n## 目录\n\n- [相比官方插件的增强特性](#相比官方插件的增强特性)\n- [前置要求](#前置要求)\n- [安装](#安装)\n- [从 HTTP 回调迁移](#从-http-回调迁移)\n- [运行测试](#运行测试)\n- [配置](#配置)\n- [私聊与群聊准入策略](#私聊与群聊准入策略)\n- [企业微信侧配置](#企业微信侧配置)\n- [消息能力与投递策略](#消息能力与投递策略)\n- [动态 Agent 与路由](#动态-agent-与路由)\n- [自建应用回调入站](#自建应用回调入站)\n- [常见问题](#常见问题)\n- [项目结构](#项目结构)\n- [自定义 Skills 配合沙箱使用实践](#自定义-skills-配合沙箱使用实践)\n- [相关链接](#相关链接)\n- [贡献与协议](#贡献与协议)\n\n## 前置要求\n\n- 已安装 [OpenClaw](https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw) `2026.3.23-2+`\n- 企业微信管理后台权限，可创建 AI 机器人或自建应用\n- **机器人已切换到长连接模式**（参考[官方文档](https:\u002F\u002Fopen.work.weixin.qq.com\u002Fhelp2\u002Fpc\u002Fcat?doc_id=21657)）\n- 运行 OpenClaw 的机器可以出站访问：\n  - `wss:\u002F\u002Fopenws.work.weixin.qq.com`\n  - `https:\u002F\u002Fqyapi.weixin.qq.com`（启用 Agent \u002F Webhook 时）\n\nBot 主链路不需要企业微信反向访问你的 HTTP 回调地址。\n\n## 安装\n\n```bash\nopenclaw plugins install @sunnoy\u002Fwecom\n```\n\n> **3.0 兼容性说明：** 从 `3.0.0` 开始，本插件仅支持 OpenClaw `2026.3.23-2+`。旧版 OpenClaw 请继续使用 `2.x`。\n\n> **从官方插件迁移：** 如果之前使用 `openclaw plugins install @wecom\u002Fwecom-openclaw-plugin`，请先卸载官方插件再安装本插件。`channels.wecom` 配置字段兼容，无需修改。\n\n## 从 HTTP 回调迁移\n\n如果之前使用 HTTP 回调模式（Token + EncodingAESKey + 回调 URL），迁移步骤如下：\n\n1. **企业微信后台**：进入「应用管理」→「智能机器人」，将机器人切换到长连接模式（参考[官方文档](https:\u002F\u002Fopen.work.weixin.qq.com\u002Fhelp2\u002Fpc\u002Fcat?doc_id=21657)）\n2. **记录凭证**：切换后获取新的 `BotId` 和 `Secret`\n3. **更新配置**：在 `~\u002F.openclaw\u002Fopenclaw.json` 中：\n   - 设置 `channels.wecom.botId` 和 `channels.wecom.secret`\n   - 删除旧的 `token`、`encodingAesKey`、回调 URL 相关配置\n4. **安装插件**：`openclaw plugins install @sunnoy\u002Fwecom`\n5. **重启 Gateway**：`openclaw gateway restart`\n\n迁移后不再需要公网可达的 HTTP 回调地址，插件会主动连接企业微信 WebSocket。\n\n## 运行测试\n\n```bash\nnpm test\n```\n\n## 配置\n\n### 单账号示例\n\n在 `~\u002F.openclaw\u002Fopenclaw.json` 中添加：\n\n```json\n{\n  \"plugins\": {\n    \"entries\": {\n      \"wecom\": {\n        \"enabled\": true\n      }\n    }\n  },\n  \"channels\": {\n    \"wecom\": {\n      \"enabled\": true,\n      \"botId\": \"aibxxxxxxxxxxxxxxxx\",\n      \"secret\": \"xxxxxxxxxxxxxxxx\",\n      \"welcomeMessage\": \"你好，我是 AI 助手。\",\n      \"sendThinkingMessage\": true,\n      \"dmPolicy\": \"pairing\",\n      \"allowFrom\": [],\n      \"groupPolicy\": \"open\",\n      \"groupAllowFrom\": [],\n      \"adminUsers\": [\"admin-userid\"],\n      \"commands\": {\n        \"enabled\": true,\n        \"allowlist\": [\"\u002Fnew\", \"\u002Fcompact\", \"\u002Fhelp\", \"\u002Fstatus\"]\n      },\n      \"dynamicAgents\": {\n        \"enabled\": true,\n        \"adminBypass\": false\n      },\n      \"dm\": {\n        \"createAgentOnFirstMessage\": true\n      },\n      \"groupChat\": {\n        \"enabled\": true,\n        \"requireMention\": true,\n        \"mentionPatterns\": [\"@\"]\n      },\n      \"workspaceTemplate\": \"\u002Fpath\u002Fto\u002Ftemplate-dir\",\n      \"mediaLocalRoots\": [\"\u002Ftmp\u002Fopenclaw\"],\n      \"agent\": {\n        \"corpId\": \"wwxxxxxxxxxxxxxxxx\",\n        \"corpSecret\": \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n        \"agentId\": 1000002\n      },\n      \"webhooks\": {\n        \"ops\": \"https:\u002F\u002Fqyapi.weixin.qq.com\u002Fcgi-bin\u002Fwebhook\u002Fsend?key=xxx\",\n        \"dev\": \"yyy\"\n      },\n      \"network\": {\n        \"egressProxyUrl\": \"http:\u002F\u002Fproxy.internal:8080\",\n        \"apiBaseUrl\": \"https:\u002F\u002Fqyapi.weixin.qq.com\"\n      }\n    }\n  }\n}\n```\n\n`webhooks` 的 value 既可以是完整 URL，也可以只写群机器人的 `key`。\n\n### 核心配置\n\n| 配置项 | 类型 | 必填 | 说明 |\n| --- | --- | --- | --- |\n| `plugins.entries.wecom.enabled` | boolean | 是 | 启用插件 |\n| `channels.wecom.enabled` | boolean | 否 | 渠道开关 |\n| `channels.wecom.botId` | string | 是 | 企业微信 AI 机器人 Bot ID |\n| `channels.wecom.secret` | string | 是 | 企业微信 AI 机器人 Secret |\n| `channels.wecom.websocketUrl` | string | 否 | WS 地址，默认 `wss:\u002F\u002Fopenws.work.weixin.qq.com` |\n| `channels.wecom.sendThinkingMessage` | boolean | 否 | 是否先发送 `\u003Cthink>\u003C\u002Fthink>` 占位，默认 `true` |\n| `channels.wecom.welcomeMessage` | string | 否 | 进入会话欢迎语（非空时固定使用该字符串） |\n| `channels.wecom.welcomeMessagesFile` | string | 否 | 欢迎语列表文件路径。支持：`{ \"messages\": [ ... ] }` 或顶层数组；每条欢迎语可为**一行一个字符串的数组**（推荐，易读），或单条字符串（可含 `\\\\n`）。相对路径基于 OpenClaw 状态目录（`~\u002F.openclaw` 或 `OPENCLAW_STATE_DIR`）。未设置 `welcomeMessage` 时从该文件随机选取；**修改文件后无需重启服务**（按 mtime 自动重读） |\n| `channels.wecom.adminUsers` | string[] | 否 | 管理员用户 ID，可绕过命令白名单 |\n| `channels.wecom.defaultAccount` | string | 否 | 多账号模式默认账号 |\n\n### 准入与安全配置\n\n| 配置项 | 类型 | 必填 | 说明 |\n| --- | --- | --- | --- |\n| `channels.wecom.dmPolicy` | string | 否 | `pairing`、`allowlist`、`open`、`disabled`，默认 `pairing` |\n| `channels.wecom.allowFrom` | string[] | 否 | 私聊 allowlist |\n| `channels.wecom.groupPolicy` | string | 否 | `open`、`allowlist`、`disabled`，默认 `open` |\n| `channels.wecom.groupAllowFrom` | string[] | 否 | 允许触发的群聊 ID 列表 |\n| `channels.wecom.groups` | object | 否 | 按群覆盖配置，可为某个群单独设置 `allowFrom` |\n| `channels.wecom.commands.enabled` | boolean | 否 | 是否启用命令白名单，默认 `true` |\n| `channels.wecom.commands.allowlist` | string[] | 否 | 普通用户允许执行的命令 |\n\n### 路由与工作区配置\n\n| 配置项 | 类型 | 必填 | 说明 |\n| --- | --- | --- | --- |\n| `channels.wecom.dynamicAgents.enabled` | boolean | 否 | 是否启用动态 Agent，默认 `true` |\n| `channels.wecom.dynamicAgents.adminBypass` | boolean | 否 | 管理员是否绕过动态 Agent，默认 `false` |\n| `channels.wecom.dm.createAgentOnFirstMessage` | boolean | 否 | 私聊是否按用户建独立 Agent，默认 `true` |\n| `channels.wecom.groupChat.enabled` | boolean | 否 | 是否启用群聊处理，默认 `true` |\n| `channels.wecom.groupChat.requireMention` | boolean | 否 | 群聊是否要求 @ 才响应，默认 `true` |\n| `channels.wecom.groupChat.mentionPatterns` | string[] | 否 | 群聊触发前缀，默认 `[\"@\"]` |\n| `channels.wecom.workspaceTemplate` | string | 否 | 动态 Agent 工作区模板目录 |\n| `channels.wecom.mediaLocalRoots` | string[] | 否 | 额外允许被动回复读取的宿主机目录列表。用于放行 `MEDIA:\u002Fabs\u002Fpath` 或 `FILE:\u002Fabs\u002Fpath` 指向的本地文件；默认只允许当前 Agent workspace 和浏览器产物目录。注意：浏览器工具返回的宿主机路径在 block reply 阶段仍可能被 core sandbox 校验拦下，建议先用 `stage_browser_media` 复制到 `\u002Fworkspace\u002F...` 后再回复。多账号模式下也可配置在 `channels.wecom.\u003CaccountId>.mediaLocalRoots`。修改后需重启 Gateway 生效 |\n\n### 增强出站配置\n\n| 配置项 | 类型 | 必填 | 说明 |\n| --- | --- | --- | --- |\n| `channels.wecom.agent.corpId` | string | 否 | 自建应用 CorpID |\n| `channels.wecom.agent.corpSecret` | string | 否 | 自建应用 Secret |\n| `channels.wecom.agent.agentId` | number | 否 | 自建应用 AgentId |\n| `channels.wecom.agent.replyFormat` | string | 否 | 回调入站回复格式，`\"markdown\"`（默认）或 `\"text\"` |\n| `channels.wecom.agent.callback.token` | string | 否 | 回调验签 Token |\n| `channels.wecom.agent.callback.encodingAESKey` | string | 否 | 回调消息解密密钥（43 位） |\n| `channels.wecom.agent.callback.path` | string | 否 | 回调 HTTP 路由路径，如 `\"\u002Fwebhooks\u002Fapp\"` |\n| `channels.wecom.webhooks` | object | 否 | 群机器人 webhook 映射 |\n| `channels.wecom.network.egressProxyUrl` | string | 否 | Agent \u002F Webhook 出站代理 |\n| `channels.wecom.network.apiBaseUrl` | string | 否 | 企业微信 API 基础地址覆盖，默认官方地址 |\n\nAgent 增强出站不需要 `token`、`encodingAesKey`、回调 URL；只有需要同时启用**回调入站**时才需配置 `agent.callback.*`。\n\n### 多账号示例\n\n```json\n{\n  \"channels\": {\n    \"wecom\": {\n      \"defaultAccount\": \"open\",\n      \"adminUsers\": [\"admin-userid\"],\n      \"commands\": {\n        \"enabled\": true,\n        \"allowlist\": [\"\u002Fnew\", \"\u002Fcompact\", \"\u002Fhelp\", \"\u002Fstatus\"]\n      },\n      \"open\": {\n        \"botId\": \"aib-open-xxx\",\n        \"secret\": \"secret-open-xxx\",\n        \"dmPolicy\": \"open\"\n      },\n      \"support\": {\n        \"botId\": \"aib-support-xxx\",\n        \"secret\": \"secret-support-xxx\",\n        \"dmPolicy\": \"pairing\",\n        \"mediaLocalRoots\": [\"\u002Ftmp\u002Fopenclaw\"],\n        \"agent\": {\n          \"corpId\": \"wwxxxxxxxxxxxxxxxx\",\n          \"corpSecret\": \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n          \"agentId\": 1000002\n        },\n        \"webhooks\": {\n          \"ops\": \"https:\u002F\u002Fqyapi.weixin.qq.com\u002Fcgi-bin\u002Fwebhook\u002Fsend?key=xxx\"\n        }\n      }\n    }\n  }\n}\n```\n\n多账号模式下：\n\n- 顶层共享字段会合并到各账号\n- `channels.wecom.\u003CaccountId>` 是每个账号自己的覆盖项\n- 动态 Agent ID 会自动带账号前缀\n- 旧的 v1 `token` \u002F `encodingAesKey` 字段不再使用\n\n## 私聊与群聊准入策略\n\n### 私聊 `dmPolicy`\n\n| 值 | 含义 |\n| --- | --- |\n| `pairing` | 默认模式。陌生用户首次私聊会收到配对码，管理员执行 `openclaw pairing approve wecom \u003Ccode>` 后放行 |\n| `allowlist` | 只允许 `allowFrom` 中的用户私聊，不自动发配对码 |\n| `open` | 允许所有能私聊机器人的企业微信成员直接进入会话 |\n| `disabled` | 禁用私聊 |\n\n`open` 的含义就是：如果机器人可见范围允许，企业内任何能私聊到这个 Bot 的成员都可以直接使用。\n\n### 群聊策略\n\n| 配置 | 说明 |\n| --- | --- |\n| `groupPolicy: \"open\"` | 所有群可触发 |\n| `groupPolicy: \"allowlist\"` + `groupAllowFrom` | 只允许指定群 |\n| `groupPolicy: \"disabled\"` | 禁用群聊 |\n| `groupChat.requireMention` | 群聊是否必须 @ 才触发 |\n| `groups.\u003CchatId>.allowFrom` | 某个群里仅允许指定成员触发 |\n\n## 企业微信侧配置\n\n### 1. 创建 AI 机器人（Bot 主链路）\n\n这是 v2 的主接入方式，使用 WebSocket 长连接。\n\n1. 登录[企业微信管理后台](https:\u002F\u002Fwork.weixin.qq.com\u002Fwework_admin\u002Fframe)\n2. 进入「应用管理」→「智能机器人」\n3. 创建机器人，选择长连接模式（参考[官方文档](https:\u002F\u002Fopen.work.weixin.qq.com\u002Fhelp2\u002Fpc\u002Fcat?doc_id=21657)）\n4. 创建完成后记录 `BotId` 和 `Secret`\n5. 填入 OpenClaw 配置的 `channels.wecom.botId` 和 `channels.wecom.secret`\n6. 启动 OpenClaw，插件会主动连接官方 WebSocket\n\n长连接模式下不需要配置 HTTP 回调 URL、Token、EncodingAESKey。\n\n### 2. 创建自建应用（Agent 增强出站 + 可选回调入站）\n\n自建应用承担两个可选职责：\n\n**增强出站**（主动推送消息）：\n- 主动给用户 \u002F 群 \u002F 部门 \u002F 标签发消息\n- 上传图片和文件\n- 当 WS 断连时作为回复后备通道\n\n**回调入站**（可选，与 WS 并行）：\n- 企业微信将用户消息以 HTTP POST 推送到你的服务器\n- 适合需要独立入站 URL 或不方便使用 WS 长连接的场景\n\n创建步骤：\n\n1. 在企业微信后台创建自建应用\n2. 记录 `CorpID`、`AgentId`、`Secret`\n3. 填入配置：\n   - `channels.wecom.agent.corpId`\n   - `channels.wecom.agent.agentId`\n   - `channels.wecom.agent.corpSecret`\n4. **仅启用回调入站时**，额外在应用的「接收消息」中配置回调 URL，并填入对应的 `agent.callback.*` 配置（见[自建应用回调入站](#自建应用回调入站)）\n\n### 3. 配置群机器人（Webhook 增强出站，可选）\n\nWebhook 只负责群通知。\n\n1. 在目标群添加群机器人\n2. 复制 webhook URL 或 key\n3. 配置到 `channels.wecom.webhooks`\n4. 发送目标使用 `webhook:\u003Cname>`\n\n## 消息能力与投递策略\n\n### 能力矩阵\n\n| 能力 | Bot（WS） | Agent API | Webhook |\n| --- | :---: | :---: | :---: |\n| 私聊接收 | ✅ | ✅（回调入站） | — |\n| 群聊接收（可配置 @ 触发） | ✅ | ✅（回调入站） | — |\n| 被动流式回复 | ✅ | — | — |\n| 被动最终帧图片 | ✅ | ✅ | ✅ |\n| 主动发送文本 | ✅ | ✅ | ✅ |\n| 主动发送图片 \u002F 文件 | — | ✅ | ✅ |\n| 发送到部门 \u002F 标签 | — | ✅ | — |\n| 思考过程 `\u003Cthink>` | ✅ | — | — |\n| 欢迎语 | ✅ | — | — |\n| WS 断连补发 | — | ✅ | — |\n\n### 入站消息\n\n| 类型 | 说明 |\n| --- | --- |\n| `text` | 文本消息 |\n| `image` | 图片（AES 加密下载 + 解密） |\n| `voice` | 语音（自动提取转写文本 `voice.content`） |\n| `file` | 文件（AES 加密下载 + 解密） |\n| `mixed` | 图文混排（自动拆解为文本 + 图片） |\n| `quote` | 引用消息（上下文透传） |\n\n### 被动回复\n\n被动回复统一走 WebSocket `replyStream`：\n\n- 文本内容支持 Markdown\n- `\u003Cthinking>`、`\u003Cthought>` 等变体会被规范化为 `\u003Cthink>`\n- 可先发送 `\u003Cthink>\u003C\u002Fthink>` 占位（配置 `sendThinkingMessage`）\n- 思考流式更新采用 800ms 节流，防止 SDK 队列溢出\n- 最终回复 `finish=true` 时可附带图片 `msg_item`\n- 若最终回复包含 WS 不支持的媒体（文件等），会先文本提示再通过 Agent API 补发\n\n本插件会自动解析模型输出中的 `MEDIA:` \u002F `FILE:` 指令，并在回复完成后上传对应文件：\n\n- 图片使用 `MEDIA:\u002Fabs\u002Fpath`\n- PDF、音频、视频、压缩包、Office 文档等非图片文件使用 `FILE:\u002Fabs\u002Fpath`\n- 沙箱内当前工作区文件可直接写成 `MEDIA:\u002Fworkspace\u002F...` 或 `FILE:\u002Fworkspace\u002F...`\n- 浏览器生成的文件默认允许从 OpenClaw 状态目录下的浏览器媒体目录读取，但如果浏览器工具返回的是宿主机绝对路径，先调用 `stage_browser_media`，再使用它返回的 `MEDIA:\u002Fworkspace\u002F...` 或 `FILE:\u002Fworkspace\u002F...`\n- 宿主机其他目录默认不放行；如果需要回复 `\u002Ftmp\u002Fopenclaw\u002Freport.pdf` 这类文件，请把其父目录加入 `channels.wecom.mediaLocalRoots`，多账号模式可配在 `channels.wecom.\u003CaccountId>.mediaLocalRoots`\n- 更新 `mediaLocalRoots` 后需重启 Gateway 生效\n\n### 主动发送与后备策略\n\n主动发送分层：\n\n1. 普通文本优先走 WS `sendMessage`\n2. 目标为 `webhook:\u003Cname>` 时走 Webhook\n3. 目标为用户 \u002F 群 \u002F 部门 \u002F 标签，且配置了 Agent 时走 Agent API\n4. 发送图片 \u002F 文件时，WS 侧给出文本提示，媒体交给 Agent \u002F Webhook 通道\n5. 未配置 Agent \u002F Webhook 时，只保留 WS 文本提示\n\n### WS 断连自动重试\n\n当 WS 断连导致最终回复发送失败时：\n\n1. 插件自动将未送达回复加入 pending 队列（TTL 5 分钟，最多 50 条）\n2. WS 重连并认证成功后，自动通过 Agent API 补发所有 pending 回复\n3. 过期条目自动丢弃，不会无限积压\n\n### 运行时配额感知\n\n插件做本地近似记账，并把状态暴露到账号 snapshot \u002F status：\n\n- 连接占线：同一个 `botId` 被其他实例接管时，标记 `displaced`\n- 24h 被动回复窗口：按会话追踪 reply quota（限额 30，告警 24）\n- 每会话每日主动发送额度：按会话追踪 active send quota（限额 10，告警 8）\n- 接近上限或触顶时输出 warning\n\n当前策略是\"感知 + 告警\"，不做硬阻断。\n\n### 支持的目标格式\n\n| 格式 | 示例 | 说明 |\n| --- | --- | --- |\n| `wecom:\u003CuserId>` | `wecom:zhangsan` | 发给企业微信用户 |\n| `group:\u003CchatId>` | `group:wr123456` | 发给群聊 |\n| `party:\u003Cid>` | `party:2` | 发给部门 |\n| `tag:\u003Cname>` | `tag:Developers` | 发给标签 |\n| `webhook:\u003Cname>` | `webhook:ops` | 发给 webhook 群 |\n| `\u003CchatId>` | `wr123456` | 直接写群 ID 也可识别 |\n\n## 动态 Agent 与路由\n\n### 动态 Agent\n\n默认路由规则：\n\n- 私聊：`wecom-dm-\u003CuserId>`\n- 群聊：`wecom-group-\u003CchatId>`\n- 多账号私聊：`wecom-\u003CaccountId>-dm-\u003CuserId>`\n- 多账号群聊：`wecom-\u003CaccountId>-group-\u003CchatId>`\n\n好处：\n\n- 每个用户 \u002F 群聊独立上下文\n- 每个动态 Agent 独立工作区\n- 可以按账号进一步隔离\n\n### Workspace 模板\n\n`workspaceTemplate` 目录中的模板文件会在动态 Agent 首次创建时复制到工作区：\n\n- `AGENTS.md`、`BOOTSTRAP.md`、`CLAUDE.md`、`SOUL.md`、`TOOLS.md`、`IDENTITY.md`、`USER.md`、`HEARTBEAT.md`、`system-prompt.md`\n\n插件会在工作区里写入 `.openclaw\u002Fwecom-template-state.json` 记录首次模板同步状态。已有 state 的工作区后续只补缺，不覆盖已有文件。\n\n`BOOTSTRAP.md` 只会在工作区还没有 `memory\u002F` 或 `MEMORY.md` 时参与同步；一旦工作区已经出现记忆痕迹，插件就不再回种 bootstrap，避免打断已完成 onboarding 的会话。\n\n历史工作区如果还没有 state，插件会先补写 state，再按“只补缺、不覆盖”处理，避免存量工作区被重新整批同步。\n\n### Bindings\n\n如果 OpenClaw 配置了 `bindings`，则优先按 binding 路由，不会被动态 Agent 覆盖。\n\n## 自建应用回调入站\n\n自建应用的「接收消息」HTTP 回调可作为额外的入站通道，与 WS 长连接并行运行，互不干扰。适合已有自建应用的场景，或需要独立回调 URL 的情况。\n\n### 配置\n\n在 `channels.wecom.agent` 下增加 `callback` 子对象：\n\n```json\n{\n  \"channels\": {\n    \"wecom\": {\n      \"botId\": \"aib-xxx\",\n      \"secret\": \"bot-secret-xxx\",\n      \"agent\": {\n        \"corpId\": \"wwxxxxxxxxxxxx\",\n        \"corpSecret\": \"app-secret-xxx\",\n        \"agentId\": 1000002,\n        \"replyFormat\": \"markdown\",\n        \"callback\": {\n          \"token\": \"YourToken\",\n          \"encodingAESKey\": \"43位密钥\",\n          \"path\": \"\u002Fwebhooks\u002Fapp\"\n        }\n      }\n    }\n  }\n}\n```\n\n| 字段 | 说明 |\n| --- | --- |\n| `agent.callback.token` | 企业微信「接收消息」里配置的 Token |\n| `agent.callback.encodingAESKey` | 43 位 EncodingAESKey |\n| `agent.callback.path` | Gateway 监听的 HTTP 路径，需与企业微信后台填写的 URL 一致 |\n| `agent.replyFormat` | 回复格式，`\"markdown\"`（默认）或 `\"text\"` |\n\n### 企业微信侧配置\n\n1. 进入自建应用 → 「接收消息」\n2. 填写 URL：`https:\u002F\u002F\u003Cyour-gateway-host>:\u003Cport>\u003Cpath>`（例如 `https:\u002F\u002Fexample.com:18789\u002Fwebhooks\u002Fapp`）\n3. 填写 Token 和 EncodingAESKey（与配置保持一致）\n4. 点击「保存」，企业微信将发送 GET 请求验证（gateway 会自动回复 echostr）\n5. 验证通过后，用户发给自建应用的消息将通过 HTTP POST 推送到 gateway\n\n### 支持的消息类型\n\n| 类型 | 说明 |\n| --- | --- |\n| `text` | 文本消息 |\n| `image` | 图片（通过 Agent API 下载） |\n| `voice` | 语音文件 |\n| `file` | 文件 |\n| `video` | 视频文件 |\n\n事件类消息（关注、进入会话等）会被静默忽略。\n\n## 常见问题\n\n### Q: 2.0 和之前最大的区别是什么？\n\n2.0 完全采用 WebSocket 长连接，不再使用 HTTP 回调。需要在企业微信后台将机器人切换到[长连接模式](https:\u002F\u002Fopen.work.weixin.qq.com\u002Fhelp2\u002Fpc\u002Fcat?doc_id=21657)。\n\n### Q: 3.0 为什么不能再装在旧 OpenClaw 上？\n\n3.0 开始直接适配 OpenClaw `2026.3.23-2+` 的新版 plugin SDK 导出和媒体\u002Fruntime 约定，旧版 core 缺少这些接口。旧环境请固定使用 `2.x`。\n\n### Q: 之前用的官方插件 `@wecom\u002Fwecom-openclaw-plugin`，怎么迁移？\n\n```bash\n# 卸载官方插件\nopenclaw plugins uninstall wecom-openclaw-plugin\n# 安装本插件\nopenclaw plugins install @sunnoy\u002Fwecom\n# 重启\nopenclaw gateway restart\n```\n\n`channels.wecom` 配置字段兼容，无需修改。\n\n### Q: `dmPolicy: \"open\"` 是不是企业里任何人都能私聊？\n\n是。前提是该成员对这个机器人可见，并且能在企业微信里私聊到它。\n\n### Q: `pairing` 模式怎么放行用户？\n\n用户第一次私聊会收到配对码。管理员执行：\n\n```bash\nopenclaw pairing approve wecom \u003Ccode>\n```\n\n### Q: Agent 还需要配置 `token` \u002F `encodingAesKey` 吗？\n\n不需要。Agent 只做增强出站，保留 `corpId`、`corpSecret`、`agentId` 即可。\n\n### Q: 入站图片还依赖全局 `EncodingAESKey` 吗？\n\n不依赖。WS 消息体里的图片 \u002F 文件自带独立 `aeskey`，插件按 `image.aeskey` 或 `file.aeskey` 下载与解密。\n\n### Q: 收到 `disconnected_event` 是什么情况？\n\n通常表示同一个 `botId` 被另一个实例接管了。企业微信同一时刻只允许一个活跃长连接。\n\n### Q: 什么时候会走 Agent 或 Webhook？\n\n- `webhook:\u003Cname>` 目标固定走 Webhook\n- 发送部门 \u002F 标签 \u002F 媒体消息时优先走 Agent\n- WS 断连后的 pending 回复通过 Agent API 补发\n- WS 文本主动发送失败时，尝试回退到 Agent\n\n### Q: 回复本地文件时提示“没有权限访问路径”怎么办？\n\n先确认文件路径是否在允许目录里：\n\n- 当前 Agent 工作区文件默认允许，可直接用 `FILE:\u002Fworkspace\u002F...` 或 `MEDIA:\u002Fworkspace\u002F...`\n- 浏览器生成的文件默认允许，但浏览器工具返回的宿主机路径建议先用 `stage_browser_media` 转成 `\u002Fworkspace\u002F...`\n- 宿主机其他目录需要把父目录加入 `channels.wecom.mediaLocalRoots`\n- 多账号模式如果只想对某个账号生效，可配置 `channels.wecom.\u003CaccountId>.mediaLocalRoots`\n\n例如：\n\n```json\n{\n  \"channels\": {\n    \"wecom\": {\n      \"mediaLocalRoots\": [\"\u002Ftmp\u002Fopenclaw\"]\n    }\n  }\n}\n```\n\n修改后重启 Gateway。`v2.2.1+` 已支持把 `mediaLocalRoots` 并入被动回复文件允许目录。\n\n### Q: `60020 not allow to access from your ip` 是什么问题？\n\n企业微信自建应用 API 的可信 IP 限制。把当前服务器出口 IP 加入企业微信应用的可信 IP 白名单即可。\n\n## 项目结构\n\n```text\nopenclaw-plugin-wecom\u002F\n├── index.js                      # 插件入口、生命周期、onboarding\n├── dynamic-agent.js              # 动态 Agent 路由判断\n├── image-processor.js            # 图片格式检测、MD5、Base64\n├── logger.js                     # 结构化日志\n├── think-parser.js               # \u003Cthink> 标签规范化\n├── utils.js                      # 工具函数\n├── openclaw.plugin.json          # 插件元数据\n├── wecom\u002F\n│   ├── accounts.js               # 多账号管理与配置继承\n│   ├── agent-api.js              # Agent API（Token、发送、上传）\n│   ├── allow-from.js             # allowlist 规范化与匹配\n│   ├── callback-crypto.js        # 回调 AES 解密与签名验证\n│   ├── callback-inbound.js       # 自建应用回调入站处理\n│   ├── callback-media.js         # 回调媒体下载\n│   ├── channel-plugin.js         # 核心通道（sendNotice \u002F sendMedia）\n│   ├── commands.js               # 指令白名单与命令拦截\n│   ├── constants.js              # 常量定义\n│   ├── dm-policy.js              # 私聊准入策略\n│   ├── group-policy.js           # 群聊准入策略\n│   ├── http.js                   # HTTP 请求 + 代理\n│   ├── onboarding.js             # CLI 交互式配置向导\n│   ├── runtime-telemetry.js      # 运行时配额追踪\n│   ├── sandbox.js                # 沙箱集成\n│   ├── state.js                  # 插件状态管理\n│   ├── target.js                 # 目标解析（user \u002F group \u002F party \u002F tag \u002F webhook）\n│   ├── webhook-bot.js            # Webhook Bot 发送\n│   ├── workspace-template.js     # 工作区模板同步\n│   ├── ws-monitor.js             # WS 消息处理、流式回复、节流、重试\n│   └── ws-state.js               # WS 状态 + pending reply 队列\n└── tests\u002F\n    ├── accounts-reserved-keys.test.js\n    ├── api-base-url.test.js\n    ├── callback-crypto.test.js\n    ├── callback-inbound.test.js\n    ├── channel-plugin.media-type.test.js\n    ├── channel-plugin.notice.test.js\n    ├── dynamic-agent.test.js\n    ├── image-processor.test.js\n    ├── issue-fixes.test.js\n    ├── reply-media-directive.test.js\n    ├── runtime-telemetry.test.js\n    ├── target.test.js\n    ├── think-parser.test.js\n    ├── workspace-template.test.js\n    ├── ws-monitor.quote-mixed.test.js\n    └── ws.e2e.test.js\n```\n\n## 自定义 Skills 配合沙箱使用实践\n\nOpenClaw 支持自定义 Skills 并通过沙箱（Docker）隔离执行，下面保留一份生产环境常见配置示例：\n\n```json\n{\n  \"agents\": {\n    \"defaults\": {\n      \"sandbox\": {\n        \"mode\": \"all\",\n        \"workspaceAccess\": \"rw\",\n        \"scope\": \"agent\",\n        \"docker\": {\n          \"image\": \"your-registry.com\u002Fopenclaw-agent:v2026.x.x\",\n          \"readOnlyRoot\": false,\n          \"network\": \"bridge\",\n          \"extraHosts\": [\n            \"your-domain.internal:xxx.xxx.xxx.xxx\"\n          ],\n          \"binds\": [\n            \"\u002Fpath\u002Fto\u002Fskills:\u002Fworkspace\u002Fskills:ro\"\n          ],\n          \"dangerouslyAllowReservedContainerTargets\": true,\n          \"dangerouslyAllowExternalBindSources\": true\n        },\n        \"prune\": {\n          \"idleHours\": 87600,\n          \"maxAgeDays\": 3650\n        }\n      }\n    }\n  },\n  \"skills\": {\n    \"allowBundled\": [\"_none_\"],\n    \"load\": {\n      \"extraDirs\": [\"\u002Fpath\u002Fto\u002Fskills\"],\n      \"watch\": true,\n      \"watchDebounceMs\": 250\n    }\n  }\n}\n```\n\n关键点：\n\n- `sandbox.mode: \"all\"` 表示所有操作都走沙箱\n- `sandbox.workspaceAccess: \"rw\"` 允许 Agent 读写工作区\n- `sandbox.scope: \"agent\"` 表示每个 Agent 独立沙箱\n- `sandbox.docker.binds` 可把宿主机技能目录映射到容器内 `\u002Fworkspace\u002Fskills`\n- `skills.load.extraDirs` 用于声明自定义 Skills 加载目录\n- `skills.load.watch` 改动 Skill 后自动热加载\n\n## 相关链接\n\n- [OpenClaw](https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw) — 开源 AI Agent 运行时\n- [官方 WeCom OpenClaw 插件](https:\u002F\u002Fgithub.com\u002FWecomTeam\u002Fwecom-openclaw-plugin)（[npm](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@wecom\u002Fwecom-openclaw-plugin)）\n- [`@wecom\u002Faibot-node-sdk`](https:\u002F\u002Fgithub.com\u002FWecomTeam\u002Faibot-node-sdk) — 企业微信智能机器人 Node.js SDK\n- [企业微信 AI 机器人官方文档](https:\u002F\u002Fopen.work.weixin.qq.com\u002Fhelp2\u002Fpc\u002Fcat?doc_id=21657)\n\n## 贡献与协议\n\n- 贡献说明见 `CONTRIBUTING.md`\n- 许可证为 `ISC`\n","# OpenClaw 企业微信（WeCom）增强插件\n\n[![npm](https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fv\u002F@sunnoy\u002Fwecom)](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@sunnoy\u002Fwecom)\n[![license](https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fl\u002F@sunnoy\u002Fwecom)](LICENSE)\n\n`@sunnoy\u002Fwecom` 是 [OpenClaw](https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw) 企业微信渠道的**社区增强插件**，基于官方 [`@wecom\u002Fwecom-openclaw-plugin`](https:\u002F\u002Fgithub.com\u002FWecomTeam\u002Fwecom-openclaw-plugin) 的 WebSocket 长连接骨架，提供多账号管理、动态 Agent 隔离、Agent API \u002F Webhook 增强出站、指令白名单、配额感知等企业级特性。\n\n底层 SDK：[`@wecom\u002Faibot-node-sdk`](https:\u002F\u002Fgithub.com\u002FWecomTeam\u002Faibot-node-sdk) — 企业微信智能机器人 Node.js SDK。\n\n> **⚠️ 从 HTTP 回调迁移到长连接：** 2.0 版本完全采用企业微信 [AI 机器人 WebSocket 长连接模式](https:\u002F\u002Fopen.work.weixin.qq.com\u002Fhelp2\u002Fpc\u002Fcat?doc_id=21657)。如果你之前使用 HTTP 回调（Token + EncodingAESKey + 回调 URL），需要在企业微信管理后台将机器人切换到长连接模式，然后删除旧的回调配置。切换后只需 `botId` 和 `secret` 即可接入。\n\n> **2.1 新增：** 在 WS 长连接之外，2.1 版本新增了企业微信**自建应用\"接收消息\"HTTP 回调**作为可选入站通道。在 `channels.wecom.agent` 下配置 `callback.token`、`callback.encodingAESKey`、`callback.path` 即可同时启用，与 WS 通道并行运行，互不影响。\n\n## 相比官方插件的增强特性\n\n下表列出了本插件相比 [官方 WeCom OpenClaw 插件](https:\u002F\u002Fgithub.com\u002FWecomTeam\u002Fwecom-openclaw-plugin)（[npm](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@wecom\u002Fwecom-openclaw-plugin)）额外提供的能力：\n\n| 特性 | 官方插件 | 本插件 |\n| --- | :---: | :---: |\n| WebSocket 长连接 + 流式回复 | ✅ | ✅ |\n| 私聊 \u002F 群聊接收 | ✅ | ✅ |\n| DM 准入策略（pairing \u002F open \u002F allowlist \u002F disabled） | ✅ | ✅ |\n| 群聊准入策略（open \u002F allowlist \u002F disabled） | ✅ | ✅ |\n| 按群配置发送者白名单 | ✅ | ✅ |\n| 思考占位（`\u003Cthink>` 占位符） | ✅ | ✅ |\n| CLI 交互式配置向导 | ✅ | ✅ |\n| **多账号管理**（多 Bot 独立配置、共享字段继承） | ❌ | ✅ |\n| **动态 Agent 路由**（按用户 \u002F 群自动隔离会话与工作区） | ❌ | ✅ |\n| **Workspace 模板**（自动为新 Agent 复制 AGENTS.md 等引导文件） | ❌ | ✅ |\n| **Agent API 增强出站**（自建应用主动发送文本、图片、文件） | ❌ | ✅ |\n| **部门 \u002F 标签目标发送**（`party:` \u002F `tag:` 寻址） | ❌ | ✅ |\n| **Webhook Bot 群通知**（命名 webhook 映射，markdown \u002F 图片 \u002F 文件） | ❌ | ✅ |\n| **指令白名单**（限制普通用户可执行的 slash 命令） | ❌ | ✅ |\n| **管理员绕过**（命令白名单 + 动态 Agent 路由） | ❌ | ✅ |\n| **运行时配额感知**（被动回复 24h 窗口 + 主动发送额度追踪与告警） | ❌ | ✅ |\n| **Pending Reply 重试**（WS 断连后自动通过 Agent API 补发未送达回复） | ❌ | ✅ |\n| **Reasoning 流式节流**（800ms 节流防止 SDK 队列溢出） | ❌ | ✅ |\n| **`\u003Cthink>` 标签规范化**（兼容 `\u003Cthinking>` \u002F `\u003Cthought>` 等变体） | ❌ | ✅ |\n| **Reply 媒体指令解析**（自动提取 LLM 输出中的 `MEDIA:` \u002F `FILE:` 路径） | ❌ | ✅ |\n| **出站代理**（`network.egressProxyUrl`） | ❌ | ✅ |\n| **自定义 API 基础地址**（`network.apiBaseUrl` \u002F `WECOM_API_BASE_URL`） | ❌ | ✅ |\n| **Bindings 路由**（固定绑定企业微信账号到指定 Agent） | ❌ | ✅ |\n| **消息去重**（reqId + msgId 去重，防止重复处理） | ❌ | ✅ |\n| **入站图文混排**（`mixed` 消息拆解为文本 + 图片） | ❌ | ✅ |\n| **入站语音转写**（`voice.content` 自动提取） | ❌ | ✅ |\n| **入站引用消息**（`quote` 上下文透传） | ❌ | ✅ |\n| **自建应用回调入站**（HTTP 回调作为独立入站通道，与 WS 并行） | ❌ | ✅ |\n| **Agent API Markdown 回复**（回调入站回复默认 markdown 格式） | ❌ | ✅ |\n| **入站\u002F出站信息日志**（WS \u002F CB 收发日志，便于追踪消息流） | ❌ | ✅ |\n\n## 目录\n\n- [相比官方插件的增强特性](#相比官方插件的增强特性)\n- [前置要求](#前置要求)\n- [安装](#安装)\n- [从 HTTP 回调迁移](#从-http-回调迁移)\n- [运行测试](#运行测试)\n- [配置](#配置)\n- [私聊与群聊准入策略](#私聊与群聊准入策略)\n- [企业微信侧配置](#企业微信侧配置)\n- [消息能力与投递策略](#消息能力与投递策略)\n- [动态 Agent 与路由](#动态-agent-与路由)\n- [自建应用回调入站](#自建应用回调入站)\n- [常见问题](#常见问题)\n- [项目结构](#项目结构)\n- [自定义 Skills 配合沙箱使用实践](#自定义-skills-配合沙箱使用实践)\n- [相关链接](#相关链接)\n- [贡献与协议](#贡献与协议)\n\n## 前置要求\n\n- 已安装 [OpenClaw](https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw) `2026.3.23-2+`\n- 企业微信管理后台权限，可创建 AI 机器人或自建应用\n- **机器人已切换到长连接模式**（参考[官方文档](https:\u002F\u002Fopen.work.weixin.qq.com\u002Fhelp2\u002Fpc\u002Fcat?doc_id=21657)）\n- 运行 OpenClaw 的机器可以出站访问：\n  - `wss:\u002F\u002Fopenws.work.weixin.qq.com`\n  - `https:\u002F\u002Fqyapi.weixin.qq.com`（启用 Agent \u002F Webhook 时）\n\nBot 主链路不需要企业微信反向访问你的 HTTP 回调地址。\n\n## 安装\n\n```bash\nopenclaw plugins install @sunnoy\u002Fwecom\n```\n\n> **3.0 兼容性说明：** 从 `3.0.0` 开始，本插件仅支持 OpenClaw `2026.3.23-2+`. 旧版 OpenClaw 请继续使用 `2.x`.\n\n> **从官方插件迁移：** 如果之前使用 `openclaw plugins install @wecom\u002Fwecom-openclaw-plugin`，请先卸载官方插件再安装本插件。`channels.wecom` 配置字段兼容，无需修改。\n\n## 从 HTTP 回调迁移\n\n如果之前使用 HTTP 回调模式（Token + EncodingAESKey + 回调 URL），迁移步骤如下：\n\n1. **企业微信后台**：进入「应用管理」→「智能机器人」，将机器人切换到长连接模式（参考[官方文档](https:\u002F\u002Fopen.work.weixin.qq.com\u002Fhelp2\u002Fpc\u002Fcat?doc_id=21657)）\n2. **记录凭证**：切换后获取新的 `BotId` 和 `Secret`\n3. **更新配置**：在 `~\u002F.openclaw\u002Fopenclaw.json` 中：\n   - 设置 `channels.wecom.botId` 和 `channels.wecom.secret`\n   - 删除旧的 `token`、`encodingAesKey`、回调 URL 相关配置\n4. **安装插件**：`openclaw plugins install @sunnoy\u002Fwecom`\n5. **重启 Gateway**：`openclaw gateway restart`\n\n迁移后不再需要公网可达的 HTTP 回调地址，插件会主动连接企业微信 WebSocket。\n\n## 运行测试\n\n```bash\nnpm test\n```\n\n## 配置\n\n### 单账号示例\n\n在 `~\u002F.openclaw\u002Fopenclaw.json` 中添加：\n\n```json\n{\n  \"plugins\": {\n    \"entries\": {\n      \"wecom\": {\n        \"enabled\": true\n      }\n    }\n  },\n  \"channels\": {\n    \"wecom\": {\n      \"enabled\": true,\n      \"botId\": \"aibxxxxxxxxxxxxxxxx\",\n      \"secret\": \"xxxxxxxxxxxxxxxx\",\n      \"welcomeMessage\": \"你好，我是 AI 助手。\",\n      \"sendThinkingMessage\": true,\n      \"dmPolicy\": \"pairing\",\n      \"allowFrom\": [],\n      \"groupPolicy\": \"open\",\n      \"groupAllowFrom\": [],\n      \"adminUsers\": [\"admin-userid\"],\n      \"commands\": {\n        \"enabled\": true,\n        \"allowlist\": [\"\u002Fnew\", \"\u002Fcompact\", \"\u002Fhelp\", \"\u002Fstatus\"]\n      },\n      \"dynamicAgents\": {\n        \"enabled\": true,\n        \"adminBypass\": false\n      },\n      \"dm\": {\n        \"createAgentOnFirstMessage\": true\n      },\n      \"groupChat\": {\n        \"enabled\": true,\n        \"requireMention\": true,\n        \"mentionPatterns\": [\"@\"]\n      },\n      \"workspaceTemplate\": \"\u002Fpath\u002Fto\u002Ftemplate-dir\",\n      \"mediaLocalRoots\": [\"\u002Ftmp\u002Fopenclaw\"],\n      \"agent\": {\n        \"corpId\": \"wwxxxxxxxxxxxxxxxx\",\n        \"corpSecret\": \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n        \"agentId\": 1000002\n      },\n      \"webhooks\": {\n        \"ops\": \"https:\u002F\u002Fqyapi.weixin.qq.com\u002Fcgi-bin\u002Fwebhook\u002Fsend?key=xxx\",\n        \"dev\": \"yyy\"\n      },\n      \"network\": {\n        \"egressProxyUrl\": \"http:\u002F\u002Fproxy.internal:8080\",\n        \"apiBaseUrl\": \"https:\u002F\u002Fqyapi.weixin.qq.com\"\n      }\n    }\n  }\n}\n```\n\n`webhooks` 的 value 既可以是完整 URL，也可以只写群机器人的 `key`.\n\n### 核心配置\n\n| 配置项 | 类型 | 必填 | 说明 |\n| --- | --- | --- | --- |\n| `plugins.entries.wecom.enabled` | boolean | 是 | 启用插件 |\n| `channels.wecom.enabled` | boolean | 否 | 游道开关 |\n| `channels.wecom.botId` | string | 是 | 企业微信 AI 机器人 Bot ID |\n| `channels.wecom.secret` | string | 是 | 企业微信 AI 机器人 Secret |\n| `channels.wecom.websocketUrl` | string | 否 | WS 地址，默认 `wss:\u002F\u002Fopenws.work.weixin.qq.com` |\n| `channels.wecom.sendThinkingMessage` | boolean | 否 | 是否先发送 `\u003C\u003Cthink>>` 占位，默认 `true` |\n| `channels.wecom.welcomeMessage` | string | 否 | 进入会话欢迎语（非空时固定使用该字符串） |\n| `channels.wecom.welcomeMessagesFile` | string | 否 | 欢迎语列表文件路径。支持：`{ \"messages\": [ ... ] }` 或顶层数组；每条欢迎语可为**一行一个字符串的数组**（推荐，易读），或单条字符串（可含 `\\\\n`）。相对路径基于 OpenClaw 状态目录（`~\u002F.openclaw` 或 `OPENCLAW_STATE_DIR`）。未设置 `welcomeMessage` 时从该文件随机选取；**修改文件后无需重启服务**（按 mtime 自动重读） |\n| `channels.wecom.adminUsers` | string[] | 否 | 管理员用户 ID，可绕过命令白名单 |\n| `channels.wecom.defaultAccount` | string | 否 | 多账号模式默认账号 |\n\n### 准入与安全配置\n\n| 配置项 | 类型 | 必填 | 说明 |\n| --- | --- | --- | --- |\n| `channels.wecom.dmPolicy` | string | 否 | `pairing`、`allowlist`、`open`、`disabled`，默认 `pairing` |\n| `channels.wecom.allowFrom` | string[] | 否 | 私聊 allowlist |\n| `channels.wecom.groupPolicy` | string | 否 | `open`、`allowlist`、`disabled`，默认 `open` |\n| `channels.wecom.groupAllowFrom` | string[] | 否 | 允许触发的群聊 ID 列表 |\n| `channels.wecom.groups` | object | 否 | 按群覆盖配置，可为某个群单独设置 `allowFrom` |\n| `channels.wecom.commands.enabled` | boolean | 否 | 是否启用命令白名单，默认 `true` |\n| `channels.wecom.commands.allowlist` | string[] | 否 | 普通用户允许执行的命令 |\n\n### 路由与工作区配置\n\n| 配置项 | 类型 | 必填 | 说明 |\n| --- | --- | --- | --- |\n| `channels.wecom.dynamicAgents.enabled` | boolean | 否 | 是否启用动态 Agent，默认 `true` |\n| `channels.wecom.dynamicAgents.adminBypass` | boolean | 否 | 管理员是否绕过动态 Agent，默认 `false` |\n| `channels.wecom.dm.createAgentOnFirstMessage` | boolean | 否 | 私聊是否按用户建独立 Agent，默认 `true` |\n| `channels.wecom.groupChat.enabled` | boolean | 否 | 是否启用群聊处理，默认 `true` |\n| `channels.wecom.groupChat.requireMention` | boolean | 否 | 群聊是否要求 @ 才响应，默认 `true` |\n| `channels.wecom.groupChat.mentionPatterns` | string[] | 否 | 群聊触发前缀，默认 `[\"@\"]` |\n| `channels.wecom.workspaceTemplate` | string | 否 | 动态 Agent 工作区模板目录 |\n| `channels.wecom.mediaLocalRoots` | string[] | 否 | 额外允许被动回复读取的宿主机目录列表。用于放行 `MEDIA:\u002Fabs\u002Fpath` 或 `FILE:\u002Fabs\u002Fpath` 指向的本地文件；默认只允许当前 Agent workspace 和浏览器产物目录。注意：浏览器工具返回的宿主机路径在 block reply 阶段仍可能被 core sandbox 校验拦下，建议先用 `stage_browser_media` 复制到 `\u002Fworkspace\u002F...` 后再回复。多账号模式下也可配置在 `channels.wecom.\u003CaccountId>.mediaLocalRoots`。修改后需重启 Gateway 生效 |\n\n### 增强出站配置\n\n| 配置项 | 类型 | 必填 | 说明 |\n| --- | --- | --- | --- |\n| `channels.wecom.agent.corpId` | string | 否 | 自建应用 CorpID |\n| `channels.wecom.agent.corpSecret` | string | 否 | 自建应用 Secret |\n| `channels.wecom.agent.agentId` | number | 否 | 自建应用 AgentId |\n| `channels.wecom.agent.replyFormat` | string | 否 | 回调入站回复格式，`\"markdown\"`（默认）或 `\"text\"` |\n| `channels.wecom.agent.callback.token` | string | 否 | 回调验签 Token |\n| `channels.wecom.agent.callback.encodingAESKey` | string | 否 | 回调消息解密密钥（43 位） |\n| `channels.wecom.agent.callback.path` | string | 否 | 回调 HTTP 路由路径，如 `\"\u002Fwebhooks\u002Fapp\"` |\n| `channels.wecom.webhooks` | object | 否 | 群机器人 webhook 映射 |\n| `channels.wecom.network.egressProxyUrl` | string | 否 | Agent \u002F Webhook 出站代理 |\n| `channels.wecom.network.apiBaseUrl` | string | 否 | 企业微信 API 基础地址覆盖，默认官方地址 |\n\nAgent 增强出站不需要 `token`、`encodingAesKey`、回调 URL；只有需要同时启用**回调入站**时才需配置 `agent.callback.*`。\n\n### 多账号示例\n\n```json\n{\n  \"channels\": {\n    \"wecom\": {\n      \"defaultAccount\": \"open\",\n      \"adminUsers\": [\"admin-userid\"],\n      \"commands\": {\n        \"enabled\": true,\n        \"allowlist\": [\"\u002Fnew\", \"\u002Fcompact\", \"\u002Fhelp\", \"\u002Fstatus\"]\n      },\n      \"open\": {\n        \"botId\": \"aib-open-xxx\",\n        \"secret\": \"secret-open-xxx\",\n        \"dmPolicy\": \"open\"\n      },\n      \"support\": {\n        \"botId\": \"aib-support-xxx\",\n        \"secret\": \"secret-support-xxx\",\n        \"dmPolicy\": \"pairing\",\n        \"mediaLocalRoots\": [\"\u002Ftmp\u002Fopenclaw\"],\n        \"agent\": {\n          \"corpId\": \"wwxxxxxxxxxxxxxxxx\",\n          \"corpSecret\": \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n          \"agentId\": 1000002\n        },\n        \"webhooks\": {\n          \"ops\": \"https:\u002F\u002Fqyapi.weixin.qq.com\u002Fcgi-bin\u002Fwebhook\u002Fsend?key=xxx\"\n        }\n      }\n    }\n  }\n}\n```\n\n多账号模式下：\n\n- 顶层共享字段会合并到各账号\n- `channels.wecom.\u003CaccountId>` 是每个账号自己的覆盖项\n- 动态 Agent ID 会自动带账号前缀\n- 旧的 v1 `token` \u002F `encodingAesKey` 字段不再使用。\n\n## 私聊与群聊准入策略\n\n### 私聊 `dmPolicy`\n\n| 值 | 含义 |\n| --- | --- |\n| `pairing` | 默认模式。陌生用户首次私聊会收到配对码，管理员执行 `openclaw pairing approve wecom \u003Ccode>` 后放行 |\n| `allowlist` | 只允许 `allowFrom` 中的用户私聊，不自动发配对码 |\n| `open` | 允许所有能私聊机器人的企业微信成员直接进入会话 |\n| `disabled` | 禁用私聊 |\n\n`open` 的含义就是：如果机器人可见范围允许，企业内任何能私聊到这个 Bot 的成员都可以直接使用。\n\n### 群聊策略\n\n| 配置 | 说明 |\n| --- | --- |\n| `groupPolicy: \"open\"` | 所有群可触发 |\n| `groupPolicy: \"allowlist\"` + `groupAllowFrom` | 只允许指定群 |\n| `groupPolicy: \"disabled\"` | 禁用群聊 |\n| `groupChat.requireMention` | 群聊是否必须 @ 才触发 |\n| `groups.\u003CchatId>.allowFrom` | 某个群里仅允许指定成员触发 |\n\n## 企业微信侧配置\n\n### 1. 创建 AI 机器人（Bot 主链路）\n\n这是 v2 的主接入方式，使用 WebSocket 长连接。\n\n1. 登录[企业微信管理后台](https:\u002F\u002Fwork.weixin.qq.com\u002Fwework_admin\u002Fframe)\n2. 进入「应用管理」→「智能机器人」\n3. 创建机器人，选择长连接模式（参考[官方文档](https:\u002F\u002Fopen.work.weixin.qq.com\u002Fhelp2\u002Fpc\u002Fcat?doc_id=21657)）\n4. 创建完成后记录 `BotId` 和 `Secret`\n5. 填入 OpenClaw 配置的 `channels.wecom.botId` 和 `channels.wecom.secret`\n6. 启动 OpenClaw，插件会主动连接官方 WebSocket\n\n长连接模式下不需要配置 HTTP 回调 URL、Token、EncodingAESKey。\n\n### 2. 创建自建应用（Agent 增强出站 + 可选回调入站）\n\n自建应用承担两个可选职责：\n\n**增强出站**（主动推送消息）：\n- 主动给用户 \u002F 群 \u002F 部门 \u002F 标签发消息\n- 上传图片和文件\n- 当 WS 断连时作为回复后备通道\n\n**回调入站**（可选，与 WS 并行）：\n- 企业微信将用户消息以 HTTP POST 推送到你的服务器\n- 适合需要独立入站 URL 或不方便使用 WS 长连接的场景\n\n创建步骤：\n\n1. 在企业微信后台创建自建应用\n2. 记录 `CorpID`、`AgentId`、`Secret`\n3. 填入配置：\n   - `channels.wecom.agent.corpId`\n   - `channels.wecom.agent.agentId`\n   - `channels.wecom.agent.corpSecret`\n4. **仅启用回调入站时**，额外在应用的「接收消息」中配置回调 URL，并填入对应的 `agent.callback.*` 配置（见[自建应用回调入站](#自建应用回调入站)）\n\n### 3. 配置群机器人（Webhook 增强出站，可选）\n\nWebhook 只负责群通知。\n\n1. 在目标群添加群机器人\n2. 复制 webhook URL 或 key\n3. 配置到 `channels.wecom.webhooks`\n4. 发送目标使用 `webhook:\u003Cname>`\n\n## 消息能力与投递策略\n\n### 能力矩阵\n\n| 能力 | Bot（WS） | Agent API | Webhook |\n| --- | :---: | :---: | :---: |\n| 私聊接收 | ✅ | ✅（回调入站） | — |\n| 群聊接收（可配置 @ 触发） | ✅ | ✅（回调入站） | — |\n| 被动流式回复 | ✅ | — | — |\n| 被动最终帧图片 | ✅ | ✅ | ✅ |\n| 主动发送文本 | ✅ | ✅ | ✅ |\n| 主动发送图片 \u002F 文件 | — | ✅ | ✅ |\n| 发送到部门 \u002F 标签 | — | ✅ | — |\n| 思考过程 `\u003Cthink>` | ✅ | — | — |\n| 欢迎语 | ✅ | — | — |\n| WS 断连补发 | — | ✅ | — |\n\n### 入站消息\n\n| 类型 | 说明 |\n| --- | --- |\n| `text` | 文本消息 |\n| `image` | 图片（AES 加密下载 + 解密） |\n| `voice` | 语音（自动提取转写文本 `voice.content`） |\n| `file` | 文件（AES 加密下载 + 解密） |\n| `mixed` | 图文混排（自动拆解为文本 + 图片） |\n| `quote` | 引用消息（上下文透传） |\n\n### 被动回复\n\n被动回复统一走 WebSocket `replyStream`：\n\n- 文本内容支持 Markdown\n- `\u003Cthinking>`、`\u003Cthought>` 等变体会被规范化为 `\u003Cthink>`\n- 可先发送 `\u003Cthink>\u003C\u002Fthink>` 占位（配置 `sendThinkingMessage`）\n- 思考流式更新采用 800ms 节流，防止 SDK 队列溢出\n- 最终回复 `finish=true` 时可附带图片 `msg_item`\n- 若最终回复包含 WS 不支持的媒体（文件等），会先文本提示再通过 Agent API 补发\n\n本插件会自动解析模型输出中的 `MEDIA:` \u002F `FILE:` 指令，并在回复完成后上传对应文件：\n\n- 图片使用 `MEDIA:\u002Fabs\u002Fpath`\n- PDF、音频、视频、压缩包、Office 文档等非图片文件使用 `FILE:\u002Fabs\u002Fpath`\n- 沙箱内当前工作区文件可直接写成 `MEDIA:\u002Fworkspace\u002F...` 或 `FILE:\u002Fworkspace\u002F...`\n- 浏览器生成的文件默认允许从 OpenClaw 状态目录下的浏览器媒体目录读取，但如果浏览器工具返回的是宿主机绝对路径，先调用 `stage_browser_media`，再使用它返回的 `MEDIA:\u002Fworkspace\u002F...` 或 `FILE:\u002Fworkspace\u002F...`\n- 宿主机其他目录默认不放行；如果需要回复 `\u002Ftmp\u002Fopenclaw\u002Freport.pdf` 这类文件，请把其父目录加入 `channels.wecom.mediaLocalRoots`，多账号模式可配在 `channels.wecom.\u003CaccountId>.mediaLocalRoots`\n- 更新 `mediaLocalRoots` 后需重启 Gateway 生效。\n\n### 主动发送与后备策略\n\n主动发送分层：\n\n1. 普通文本优先走 WS `sendMessage`\n2. 目标为 `webhook:\u003Cname>` 时走 Webhook\n3. 目标为用户 \u002F 群 \u002F 部门 \u002F 标签，且配置了 Agent 时走 Agent API\n4. 发送图片 \u002F 文件时，WS 侧给出文本提示，媒体交给 Agent \u002F Webhook 通道\n5. 未配置 Agent \u002F Webhook 时，只保留 WS 文本提示。\n\n### WS 断连自动重试\n\n当 WS 断连导致最终回复发送失败时：\n\n1. 插件自动将未送达回复加入 pending 队列（TTL 5 分钟，最多 50 条）\n2. WS 重连并认证成功后，自动通过 Agent API 补发所有 pending 回复\n3. 过期条目自动丢弃，不会无限积压\n\n### 运行时配额感知\n\n插件会进行本地近似记账，并将状态暴露到账号快照\u002F状态中：\n\n- 连接占线：当同一个 `botId` 被其他实例接管时，标记为 `displaced`。\n- 24小时被动回复窗口：按会话追踪回复配额（限额30，告警24）。\n- 每会话每日主动发送额度：按会话追踪主动发送配额（限额10，告警8）。\n- 当接近上限或达到上限时，输出警告信息。\n\n当前策略是“感知+告警”，不会进行硬性阻断。\n\n### 支持的目标格式\n\n| 格式 | 示例 | 说明 |\n| --- | --- | --- |\n| `wecom:\u003CuserId>` | `wecom:zhangsan` | 发送给企业微信用户 |\n| `group:\u003CchatId>` | `group:wr123456` | 发送给群聊 |\n| `party:\u003Cid>` | `party:2` | 发送给部门 |\n| `tag:\u003Cname>` | `tag:Developers` | 发送给标签 |\n| `webhook:\u003Cname>` | `webhook:ops` | 发送给 webhook 群 |\n| `\u003CchatId>` | `wr123456` | 直接写群ID也可识别 |\n\n## 动态 Agent 与路由\n\n### 动态 Agent\n\n默认路由规则：\n\n- 私聊：`wecom-dm-\u003CuserId>`\n- 群聊：`wecom-group-\u003CchatId>`\n- 多账号私聊：`wecom-\u003CaccountId>-dm-\u003CuserId>`\n- 多账号群聊：`wecom-\u003CaccountId>-group-\u003CchatId>`\n\n好处：\n\n- 每个用户\u002F群聊拥有独立的上下文。\n- 每个动态 Agent 拥有独立的工作区。\n- 可以按账号进一步隔离。\n\n### Workspace 模板\n\n在 `workspaceTemplate` 目录中的模板文件会在动态 Agent 首次创建时复制到工作区：\n\n- `AGENTS.md`、`BOOTSTRAP.md`、`CLAUDE.md`、`SOUL.md`、`TOOLS.md`、`IDENTITY.md`、`USER.md`、`HEARTBEAT.md`、`system-prompt.md`\n\n插件会在工作区里写入 `.openclaw\u002Fwecom-template-state.json` 文件，记录首次模板同步状态。已有状态的工作区后续只补缺，不覆盖已有文件。\n\n`BOOTSTRAP.md` 只会在工作区还没有 `memory\u002F` 或 `MEMORY.md` 时参与同步；一旦工作区已经出现记忆痕迹，插件就不再回种 bootstrap，避免打断已完成 onboarding 的会话。\n\n历史工作区如果还没有 state，插件会先补写 state，再按“只补缺、不覆盖”处理，避免存量工作区被重新整批同步。\n\n### Bindings\n\n如果 OpenClaw 配置了 `bindings`，则优先按 binding 路由，不会被动态 Agent 覆盖。\n\n## 自建应用回调入站\n\n自建应用的「接收消息」HTTP 回调可作为额外的入站通道，与 WS 长连接并行运行，互不干扰。适合已有自建应用的场景，或需要独立回调 URL 的情况。\n\n### 配置\n\n在 `channels.wecom.agent` 下增加 `callback` 子对象：\n\n```json\n{\n  \"channels\": {\n    \"wecom\": {\n      \"botId\": \"aib-xxx\",\n      \"secret\": \"bot-secret-xxx\",\n      \"agent\": {\n        \"corpId\": \"wwxxxxxxxxxxxx\",\n        \"corpSecret\": \"app-secret-xxx\",\n        \"agentId\": 1000002,\n        \"replyFormat\": \"markdown\",\n        \"callback\": {\n          \"token\": \"YourToken\",\n          \"encodingAESKey\": \"43位密钥\",\n          \"path\": \"\u002Fwebhooks\u002Fapp\"\n        }\n      }\n    }\n  }\n}\n```\n\n| 字段 | 说明 |\n| --- | --- |\n| `agent.callback.token` | 企业微信「接收消息」里配置的 Token |\n| `agent.callback.encodingAESKey` | 43位 EncodingAESKey |\n| `agent.callback.path` | Gateway监听的HTTP路径，需与企业微信后台填写的URL一致 |\n| `agent.replyFormat` | 回复格式，`\"markdown\"`（默认）或 `\"text\"` |\n\n### 企业微信侧配置\n\n1. 进入自建应用 → 「接收消息」\n2. 填写URL：`https:\u002F\u002F\u003Cyour-gateway-host>:\u003Cport>\u003Cpath>`（例如 `https:\u002F\u002Fexample.com:18789\u002Fwebhooks\u002Fapp`）\n3. 填写Token和EncodingAESKey（与配置保持一致）\n4. 点击「保存」，企业微信将发送GET请求验证（gateway会自动回复echostr）\n5. 验证通过后，用户发给自建应用的消息将通过HTTP POST推送到gateway。\n\n### 支持的消息类型\n\n| 类型 | 说明 |\n| --- | --- |\n| `text` | 文本消息 |\n| `image` | 图片（通过Agent API下载） |\n| `voice` | 语音文件 |\n| `file` | 文件 |\n| `video` | 视频文件 |\n\n事件类消息（关注、进入会话等）会被静默忽略。\n\n## 常见问题\n\n### Q: 2.0和之前最大的区别是什么？\n\n2.0完全采用WebSocket长连接，不再使用HTTP回调。需要在企业微信后台将机器人切换到[长连接模式](https:\u002F\u002Fopen.work.weixin.qq.com\u002Fhelp2\u002Fpc\u002Fcat?doc_id=21657)。\n\n### Q: 3.0为什么不能再装在旧OpenClaw上？\n\n3.0开始直接适配OpenClaw `2026.3.23-2+`的新版plugin SDK导出和媒体\u002Fruntime约定，旧版core缺少这些接口。旧环境请固定使用`2.x`。\n\n### Q: 之前用的官方插件`@wecom\u002Fwecom-openclaw-plugin`，怎么迁移？\n\n```bash\n# 卸载官方插件\nopenclaw plugins uninstall wecom-openclaw-plugin\n# 安装本插件\nopenclaw plugins install @sunnoy\u002Fwecom\n# 重启\nopenclaw gateway restart\n```\n\n`channels.wecom`配置字段兼容，无需修改。\n\n### Q: `dmPolicy: \"open\"`是不是企业里任何人都能私聊？\n\n是。前提是该成员对这个机器人可见，并且能在企业微信里私聊到它。\n\n### Q: `pairing`模式怎么放行用户？\n\n用户第一次私聊会收到配对码。管理员执行：\n\n```bash\nopenclaw pairing approve wecom \u003Ccode>\n```\n\n### Q: Agent还需要配置`token`\u002F`encodingAesKey`吗？\n\n不需要。Agent只做增强出站，保留`corpId`、`corpSecret`、`agentId`即可。\n\n### Q: 入站图片还依赖全局`EncodingAESKey`吗？\n\n不依赖。WS消息体里的图片\u002F文件自带独立`aeskey`，插件按`image.aeskey`或`file.aeskey`下载与解密。\n\n### Q: 收到`disconnected_event`是什么情况？\n\n通常表示同一个`botId`被另一个实例接管了。企业微信同一时刻只允许一个活跃长连接。\n\n### Q: 什么时候会走Agent或Webhook？\n\n- `webhook:\u003Cname>`目标固定走Webhook。\n- 发送部门\u002F标签\u002F媒体消息时优先走Agent。\n- WS断连后的pending回复通过Agent API补发。\n- WS文本主动发送失败时，尝试回退到Agent。\n\n### Q: 回复本地文件时提示“没有权限访问路径”怎么办？\n\n先确认文件路径是否在允许目录里：\n\n- 当前Agent工作区文件默认允许，可直接用`FILE:\u002Fworkspace\u002F...`或`MEDIA:\u002Fworkspace\u002F...`。\n- 浏览器生成的文件默认允许，但浏览器工具返回的宿主机路径建议先用`stage_browser_media`转成`\u002Fworkspace\u002F...`。\n- 宿主机其他目录需要把父目录加入`channels.wecom.mediaLocalRoots`。\n- 多账号模式如果只想对某个账号生效，可配置`channels.wecom.\u003CaccountId>.mediaLocalRoots`。\n\n例如：\n\n```json\n{\n  \"channels\": {\n    \"wecom\": {\n      \"mediaLocalRoots\": [\"\u002Ftmp\u002Fopenclaw\"]\n    }\n  }\n}\n```\n\n修改后重启Gateway。`v2.2.1+`已支持把`mediaLocalRoots`并入被动回复文件允许目录。\n\n### Q: `60020 not allow to access from your ip`是什么问题？\n\n企业微信自建应用API的可信IP限制。把当前服务器出口IP加入企业微信应用的可信IP白名单即可。\n\n## 项目结构\n\n```text\nopenclaw-plugin-wecom\u002F\n├── index.js                      # 插件入口、生命周期、onboarding\n├── dynamic-agent.js              # 动态Agent路由判断\n├── image-processor.js            # 图片格式检测、MD5、Base64\n├── logger.js                     # 结构化日志\n├── think-parser.js               # \u003Cthink>标签规范化\n├── utils.js                      # 工具函数\n├── openclaw.plugin.json          # 插件元数据\n├── wecom\u002F\n│   ├── accounts.js               # 多账号管理与配置继承\n│   ├── agent-api.js              # Agent API（Token、发送、上传）\n│   ├── allow-from.js             # allowlist规范化与匹配\n│   ├── callback-crypto.js        # 回调AES解密与签名验证\n│   ├── callback-inbound.js       # 自建应用回调入站处理\n│   ├── callback-media.js         # 回调媒体下载\n│   ├── channel-plugin.js         # 核心通道（sendNotice\u002FsendMedia）\n│   ├── commands.js               # 指令白名单与命令拦截\n│   ├── constants.js              # 常量定义\n│   ├── dm-policy.js              # 私聊准入策略\n│   ├── group-policy.js           # 群聊准入策略\n│   ├── http.js                   # HTTP请求+代理\n│   ├── onboarding.js             # CLI交互式配置向导\n│   ├── runtime-telemetry.js      # 运行时配额追踪\n│   ├── sandbox.js                # 沙箱集成\n│   ├── state.js                  # 插件状态管理\n│   ├── target.js                 # 目标解析（user\u002Fgroup\u002Fparty\u002Ftag\u002Fwebhook）\n│   ├── webhook-bot.js            # WebhookBot发送\n│   ├── workspace-template.js     # 工作区模板同步\n│   ├── ws-monitor.js             # WS消息处理、流式回复、节流、重试\n│   └── ws-state.js               # WS状态+pending reply队列\n└── tests\u002F\n    ├── accounts-reserved-keys.test.js\n    ├── api-base-url.test.js\n    ├── callback-crypto.test.js\n    ├── callback-inbound.test.js\n    ├── channel-plugin.media-type.test.js\n    ├── channel-plugin.notice.test.js\n    ├── dynamic-agent.test.js\n    ├── image-processor.test.js\n    ├── issue-fixes.test.js\n    ├── reply-media-directive.test.js\n    ├── runtime-telemetry.test.js\n    ├── target.test.js\n    ├── think-parser.test.js\n    ├── workspace-template.test.js\n    ├── ws-monitor.quote-mixed.test.js\n    └── ws.e2e.test.js\n```\n\n## 自定义 Skills 配合沙箱使用实践\n\nOpenClaw 支持自定义 Skills 并通过沙箱（Docker）隔离执行，下面保留一份生产环境常见配置示例：\n\n```json\n{\n  \"agents\": {\n    \"defaults\": {\n      \"sandbox\": {\n        \"mode\": \"all\",\n        \"workspaceAccess\": \"rw\",\n        \"scope\": \"agent\",\n        \"docker\": {\n          \"image\": \"your-registry.com\u002Fopenclaw-agent:v2026.x.x\",\n          \"readOnlyRoot\": false,\n          \"network\": \"bridge\",\n          \"extraHosts\": [\n            \"your-domain.internal:xxx.xxx.xxx.xxx\"\n          ],\n          \"binds\": [\n            \"\u002Fpath\u002Fto\u002Fskills:\u002Fworkspace\u002Fskills:ro\"\n          ],\n          \"dangerouslyAllowReservedContainerTargets\": true,\n          \"dangerouslyAllowExternalBindSources\": true\n        },\n        \"prune\": {\n          \"idleHours\": 87600,\n          \"maxAgeDays\": 3650\n        }\n      }\n    }\n  },\n  \"skills\": {\n    \"allowBundled\": [\"_none_\"],\n    \"load\": {\n      \"extraDirs\": [\"\u002Fpath\u002Fto\u002Fskills\"],\n      \"watch\": true,\n      \"watchDebounceMs\": 250\n    }\n  }\n}\n```\n\n关键点：\n\n- `sandbox.mode: \"all\"` 表示所有操作都走沙箱\n- `sandbox.workspaceAccess: \"rw\"` 允许 Agent 读写工作区\n- `sandbox.scope: \"agent\"` 表示每个 Agent 独立沙箱\n- `sandbox.docker.binds` 可把宿主机技能目录映射到容器内 `\u002Fworkspace\u002Fskills`\n- `skills.load.extraDirs` 用于声明自定义 Skills 加载目录\n- `skills.load.watch` 改动 Skill 后自动热加载\n\n## 相关链接\n\n- [OpenClaw](https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw) — 开源 AI Agent 运行时\n- [官方 WeCom OpenClaw 插件](https:\u002F\u002Fgithub.com\u002FWecomTeam\u002Fwecom-openclaw-plugin)（[npm](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@wecom\u002Fwecom-openclaw-plugin)）\n- [`@wecom\u002Faibot-node-sdk`](https:\u002F\u002Fgithub.com\u002FWecomTeam\u002Faibot-node-sdk) — 企业微信智能机器人 Node.js SDK\n- [企业微信 AI 机器人官方文档](https:\u002F\u002Fopen.work.weixin.qq.com\u002Fhelp2\u002Fpc\u002Fcat?doc_id=21657)\n\n## 贡献与协议\n\n- 贡献说明见 `CONTRIBUTING.md`\n- 许可证为 `ISC`","# OpenClaw 企业微信增强插件快速上手指南\n\n`@sunnoy\u002Fwecom` 是 OpenClaw 的企业微信（WeCom）社区增强插件，支持 WebSocket 长连接、多账号管理、动态 Agent 隔离及企业级消息投递能力。\n\n## 1. 环境准备\n\n在开始之前，请确保满足以下前置条件：\n\n*   **OpenClaw 版本**：已安装 `2026.3.23-2` 或更高版本。\n    ```bash\n    openclaw --version\n    ```\n*   **企业微信权限**：拥有企业微信管理后台权限，可创建\"AI 机器人”或“自建应用”。\n*   **网络要求**：运行 OpenClaw 的服务器需能出站访问以下地址：\n    *   `wss:\u002F\u002Fopenws.work.weixin.qq.com` (WebSocket 长连接)\n    *   `https:\u002F\u002Fqyapi.weixin.qq.com` (Agent API \u002F Webhook)\n*   **模式切换**：若之前使用 HTTP 回调模式，需在企微后台将机器人切换至**长连接模式**，并记录新的 `BotId` 和 `Secret`。\n\n## 2. 安装步骤\n\n### 卸载旧插件（如已安装官方插件）\n如果你之前安装了官方插件 `@wecom\u002Fwecom-openclaw-plugin`，请先卸载：\n```bash\nopenclaw plugins uninstall @wecom\u002Fwecom-openclaw-plugin\n```\n\n### 安装增强插件\n执行以下命令安装本插件：\n```bash\nopenclaw plugins install @sunnoy\u002Fwecom\n```\n\n> **注意**：从 v3.0.0 起，本插件仅支持 OpenClaw `2026.3.23-2+`。\n\n## 3. 基本使用\n\n### 第一步：配置凭证\n编辑 OpenClaw 配置文件 `~\u002F.openclaw\u002Fopenclaw.json`，填入企业微信机器人的 `botId` 和 `secret`。\n\n**单账号最小化配置示例：**\n```json\n{\n  \"plugins\": {\n    \"entries\": {\n      \"wecom\": {\n        \"enabled\": true\n      }\n    }\n  },\n  \"channels\": {\n    \"wecom\": {\n      \"enabled\": true,\n      \"botId\": \"aibxxxxxxxxxxxxxxxx\",\n      \"secret\": \"xxxxxxxxxxxxxxxx\",\n      \"dmPolicy\": \"pairing\",\n      \"groupPolicy\": \"open\"\n    }\n  }\n}\n```\n\n*   `botId`: 企业微信 AI 机器人 ID。\n*   `secret`: 企业微信 AI 机器人密钥。\n*   `dmPolicy`: 私聊策略（`pairing` 为配对模式，`open` 为全员开放）。\n*   `groupPolicy`: 群聊策略（`open` 为允许所有群，`disabled` 为禁用）。\n\n### 第二步：启动服务\n保存配置后，重启 OpenClaw 网关以加载插件：\n```bash\nopenclaw gateway restart\n```\n\n### 第三步：验证连接\n1.  **私聊测试**：在企业微信中向机器人发送消息。\n    *   若配置为 `pairing` 模式，首次聊天会收到配对码，需管理员在终端执行 `openclaw pairing approve wecom \u003Ccode>` 放行。\n    *   若配置为 `open` 模式，可直接对话。\n2.  **群聊测试**：在允许的群聊中提及机器人（默认需 `@`），观察是否收到回复。\n\n### 进阶：启用主动推送（可选）\n如需支持主动发送图片、文件或向部门\u002F标签发消息，需在配置中添加自建应用信息：\n\n```json\n\"channels\": {\n  \"wecom\": {\n    \u002F\u002F ... 基础配置\n    \"agent\": {\n      \"corpId\": \"wwxxxxxxxxxxxxxxxx\",\n      \"corpSecret\": \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n      \"agentId\": 1000002\n    }\n  }\n}\n```\n配置完成后重启网关，插件将自动具备增强出站能力。","某中型互联网公司的运维团队希望将内部 AI 助手集成到企业微信群聊中，用于实时响应故障报警并自动执行排查指令，同时确保只有授权人员能触发高危操作。\n\n### 没有 openclaw-plugin-wecom 时\n- **会话混乱难隔离**：多个业务群的请求混杂在同一个 Agent 中，上下文互相干扰，导致 AI 经常“张冠李戴”，无法区分不同项目的故障现场。\n- **权限管控缺失**：缺乏指令白名单机制，任何群成员都能发送 `\u002Frestart-server` 等高危命令，存在严重的安全隐患。\n- **消息触达受限**：仅能被动回复群内消息，无法主动向特定部门或标签组推送紧急告警，且不支持流式输出，长文本生成时用户等待体验极差。\n- **运维黑盒无追踪**：缺少详细的收发日志与配额感知，消息丢失后无法重试，也无法监控机器人是否因达到 24 小时被动回复限制而停摆。\n\n### 使用 openclaw-plugin-wecom 后\n- **动态路由隔离**：利用动态 Agent 管理功能，自动按群组隔离会话工作区，确保每个项目的故障排查上下文独立且精准。\n- **细粒度权限控制**：通过指令白名单与管理者绕过机制，仅允许运维组长执行高危 Slash 命令，普通员工仅限查询类操作，筑牢安全防线。\n- **主动通知与流畅交互**：支持基于部门\u002F标签的主动消息推送，结合流式输出与思考占位符，让长报告生成过程透明流畅，显著提升响应体验。\n- **高可靠可观测**：内置配额实时监控与断连自动重试机制，配合完整的出入站日志，确保关键告警必达，运维状态全程可视。\n\nopenclaw-plugin-wecom 将原本松散脆弱的群聊机器人升级为具备企业级隔离、安全管控与高可用性的智能运维中枢。","https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fsunnoy_openclaw-plugin-wecom_af97f022.png","sunnoy","Hui Liu","https:\u002F\u002Foss.gittoolsai.com\u002Favatars\u002Fsunnoy_ff1ef1fa.jpg","love open",null,"https:\u002F\u002Fwww.li-rui.top\u002F","https:\u002F\u002Fgithub.com\u002Fsunnoy",[80],{"name":81,"color":82,"percentage":83},"JavaScript","#f1e05a",100,676,82,"2026-04-16T07:00:48","ISC","未说明","不需要 GPU",{"notes":91,"python":92,"dependencies":93},"该工具是 OpenClaw 的 Node.js 插件，非 Python 项目。运行需安装 Node.js 环境及 OpenClaw (版本 2026.3.23-2+)。必须拥有企业微信管理后台权限以创建 AI 机器人或自建应用。网络方面，运行机器需能出站访问企业微信 WebSocket (wss:\u002F\u002Fopenws.work.weixin.qq.com) 及 API (https:\u002F\u002Fqyapi.weixin.qq.com)。v2.0+ 版本主要采用 WebSocket 长连接模式，不再强制要求公网 HTTP 回调地址（除非使用可选的自建应用回调入站功能）。","不适用 (基于 Node.js)",[94,95,96],"@sunnoy\u002Fwecom","@wecom\u002Faibot-node-sdk","OpenClaw (>=2026.3.23-2)",[15,26],[99,100,101,102,103,104,105,106,107,108],"ai-bot","chatbot","enterprise-wechat","nodejs","openclaw","plugin","streaming","typescript","wechat","wecom","2026-03-27T02:49:30.150509","2026-04-17T09:54:33.409946",[112,117,122,127,132,137,142],{"id":113,"question_zh":114,"answer_zh":115,"source_url":116},37278,"配置企业微信消息接收时，为什么一直提示“接口回调验证失败”或返回 HTML 页面？","这是因为 OpenClaw 3.2 版本移除了旧的 API，导致 WeCom 插件的 webhook 路径未被正确注册，请求被 SPA 拦截返回了 HTML。此外，旧版本的兼容方案可能触发了 gateway 的 Bearer-token 鉴权拦截。\n\n**解决方案：**\n请升级插件至 v1.6.0 或更高版本，该版本使用 `api.registerHttpRoute({auth: \"plugin\", match: \"prefix\"})` 跳过 gateway 鉴权，让插件自行处理签名验证。\n\n**升级命令：**\n```bash\nopenclaw extension install @sunnoy\u002Fwecom@1.6.0\n```\n⚠️ **注意：** v1.6.0 要求 OpenClaw 版本为 2026.3.2 或更高。","https:\u002F\u002Fgithub.com\u002Fsunnoy\u002Fopenclaw-plugin-wecom\u002Fissues\u002F61",{"id":118,"question_zh":119,"answer_zh":120,"source_url":121},37279,"启动时报错提示缺少 'wxwork' 插件或 'plugin id mismatch'，应该如何配置？","这是因为配置文件中的插件 ID 填写错误。应该使用完整的插件 ID `openclaw-plugin-wecom`，而不是 channel ID `wecom`。\n\n**正确的配置示例 (`openclaw.json`)：**\n```json\n{\n  \"plugins\": {\n    \"deny\": [\"wecom\"],\n    \"entries\": {\n      \"openclaw-plugin-wecom\": { \"enabled\": true }\n    }\n  }\n}\n```\n请确保更新插件到最新版本：\n```bash\nnpm install openclaw-plugin-wecom@latest\n# 或\nopenclaw plugins update openclaw-plugin-wecom\n```","https:\u002F\u002Fgithub.com\u002Fsunnoy\u002Fopenclaw-plugin-wecom\u002Fissues\u002F1",{"id":123,"question_zh":124,"answer_zh":125,"source_url":126},37280,"企业微信 Bot 发送消息时报错 \"Failed to parse request body as JSON\" 且内容以 `\u003Cxml>` 开头，是什么原因？","这通常是因为在企业微信后台创建机器人时选错了模式。插件需要的是支持 XML 加密回调的模式，而不是普通的文本机器人。\n\n**解决方法：**\n请在企业微信后台按照以下路径重新创建机器人：\n“安全与管理” -> “管理工具” -> “创建机器人” -> 滑动到底部选择 **“API 模式创建”**。\n不要选择普通的群机器人模式。","https:\u002F\u002Fgithub.com\u002Fsunnoy\u002Fopenclaw-plugin-wecom\u002Fissues\u002F24",{"id":128,"question_zh":129,"answer_zh":130,"source_url":131},37281,"Agent 可以聊天但无法执行工具（如创建文件、获取磁盘空间），报错 \"Unknown target\" 或权限错误，如何解决？","这是 OpenClaw 2026.3.2 版本调整了 tools 权限模型导致的。默认配置下，tool profile 可能不包含完整的 messaging 权限，导致 AI 无法解析发送目标。\n\n**解决方案：**\n在 `.openclaw.json` 配置文件中显式设置 tools profile 为 \"full\"：\n```json\n{\n  \"tools\": {\n    \"profile\": \"full\"\n  }\n}\n```\n保存后重启服务即可。","https:\u002F\u002Fgithub.com\u002Fsunnoy\u002Fopenclaw-plugin-wecom\u002Fissues\u002F86",{"id":133,"question_zh":134,"answer_zh":135,"source_url":136},37282,"Windows 服务器上 Agent 无法发送图片，报错路径解析错误，如何处理？","这是一个已知问题。在 Windows 上运行时，本地路径会被解析为反斜杠格式（如 `\\this\\is\\a\\path`），而处理逻辑期望正斜杠格式，导致判断中断。\n\n**解决方案：**\n请升级到包含此修复的最新版本插件。维护者已提交 PR 修复了路径分隔符的处理逻辑，新版本已能正确兼容 Windows 路径格式。","https:\u002F\u002Fgithub.com\u002Fsunnoy\u002Fopenclaw-plugin-wecom\u002Fissues\u002F97",{"id":138,"question_zh":139,"answer_zh":140,"source_url":141},37283,"更新版本后自建应用回调失效，日志中没有 `[CB:` 相关记录且返回 404，如何排查？","如果网关日志中没有 `[CB] Registering callback endpoint...` 的记录，说明回调路由根本没有注册成功。这通常是因为配置项缺失或拼写错误。\n\n**排查步骤：**\n1. 检查配置中是否完整包含了以下三个非空值：\n   - `channels.wecom.agent.callback.token`\n   - `channels.wecom.agent.callback.encodingAESKey`\n   - `channels.wecom.agent.corpId`\n2. **常见错误：** 检查大小写，例如 `encodingAESKey` 容易被误写为 `.encodingAesKey`（注意 'S' 的大小写）。\n只有当这三个字段都正确配置时，插件才会注册回调路由。","https:\u002F\u002Fgithub.com\u002Fsunnoy\u002Fopenclaw-plugin-wecom\u002Fissues\u002F102",{"id":143,"question_zh":144,"answer_zh":145,"source_url":146},37284,"社区版插件 (@sunnoy\u002Fwecom) 与企业微信官方插件有什么区别？","本插件 (`@sunnoy\u002Fwecom`) 定位为官方插件的社区增强版。它在官方功能基础上提供了更多的增强特性。\n具体差异对比表可以在 v2.0.0 版本的 README 文档中找到。用户可以根据需求选择使用官方插件或功能更丰富的社区增强版插件。","https:\u002F\u002Fgithub.com\u002Fsunnoy\u002Fopenclaw-plugin-wecom\u002Fissues\u002F92",[148,153,158,163,168,173,178,183,188,193,198,203,208,213,218,223,228,233,238,243],{"id":149,"version":150,"summary_zh":151,"released_at":152},297836,"v3.0.1","与 [v3.0.0](https:\u002F\u002Fgithub.com\u002Fsunnoy\u002Fopenclaw-plugin-wecom\u002Freleases\u002Ftag\u002Fv3.0.0) 相比的变更摘要。\n\n### 修复\n\n- **WeCom `\u002Fworkspace\u002F...` 宿主路径解析对齐新版 OpenClaw**: 将 `ws-monitor` 和动态 agent workspace 模板的路径计算方式调整为优先读取 `agents.defaults.workspace` 或 `agents.list[].workspace`，非默认 agent 不再错误地回退到 `~\u002F.openclaw\u002Fworkspace-\u003CagentId>`，从而修复了新版多 agent workspace 根目录迁移后 `FILE:\u002Fworkspace\u002F...` \u002F `MEDIA:\u002Fworkspace\u002F...` 文件发送失败的问题。\n- **回复文件发送引导强化**: WeCom 回复引导明确要求将 `MEDIA:` \u002F `FILE:` 指令置于 `\u003Cfinal>` 标签内，并补充说明浏览器媒体必须先执行 `stage_browser_media` 再进行回复，以减少因模型误回宿主路径或将指令写在标签外而导致的静默丢失问题。\n\n### 测试\n\n- 扩展 `tests\u002Freply-media-directive.test.js`，覆盖当 `agents.defaults.workspace` 作为非默认 agent workspace 基座时的 `\u002Fworkspace\u002F...` 解析逻辑。\n- 扩展 `tests\u002Fworkspace-template.test.js`，覆盖动态 agent workspace 路径计算与模板种子对新版 workspace 根目录的兼容性测试。","2026-04-08T03:24:15",{"id":154,"version":155,"summary_zh":156,"released_at":157},297837,"v3.0.0","## 重大变更\n\n- 仅支持 OpenClaw `2026.3.23-2+`\n- `peerDependencies.openclaw` 限制为 `^2026.3.23-2`\n- 切换到新版 SDK 导出路径：`plugin-sdk\u002Fstatus-helpers`、`plugin-sdk\u002Fcore`、`plugin-sdk\u002Fmedia-runtime`\n- 不再兼容旧版 core 的媒体 \u002F 状态目录兼容分支；旧环境请继续使用 `2.x`\n\n## 亮点\n\n- 新增 WeCom 主动跨会话 sender 协议：`message.send` \u002F `message.sendAttachment` 会自动注入 `[[sender:...]]`，出站时转成可见发送者前缀\n- 增强目标寻址：支持将纯中文姓名转成拼音 userId，并结合已存在的动态 DM Agent 自动补全目标 userId\n- 子 Agent 投递钩子适配新版 OpenClaw 事件系统\n- WS 主动发送统一走 Markdown 载荷\n- 补回被动回复本地媒体的允许目录校验，防止越权读取路径\n\n## 验证\n\n- `npm test`\n","2026-03-24T08:42:05",{"id":159,"version":160,"summary_zh":161,"released_at":162},297838,"v2.4.0","## v2.4.0 (2026-03-23)\n\n### 功能\n\n- **MCP 按需架构重构**: 移除 `mcp-config.js` 持久化模块，改为通过 WS 客户端按需获取 MCP 配置并内存缓存，消除文件系统路径依赖（#132, #141）\n- **MCP `msg` 类别支持**: `wecom_mcp` 新增消息类 MCP 调用，配套 `wecom-msg` 和 `wecom-send-media` 技能\n- **MCP 企业规模限制说明**: tool description 和错误消息中明确标注企微官方策略——>10 人企业仅支持 `doc` 类别，\u003C=10 人小团队支持全部类别\n- **回调入站媒体下载兼容**: `downloadCallbackMedia` 改用 `core.media` 运行时\n- **image_studio 回复规范**: WS 回复引导中增加不重复输出图片 URL 的约束\n\n### 修复\n\n- **仅回调账户启动修复 (#137)**: `startAccount` 跳过无 WS 凭据的回调专用账户的 WS 监控，防止网关重启循环崩溃\n- **动态 Agent 配置写入安全检查 (#136)**: `ensureDynamicAgentListed` 写入前验证内存配置含 `channels` 段，防止不完整快照覆盖用户配置文件\n- **`replyFormat: \"text\"` 全路径生效 (#139)**: `sendViaAgent` 传递 `format` 参数，`sendViaWebhook` 根据配置选择 `webhookSendText` \u002F `webhookSendMarkdown`，个人微信端不再显示\"暂不支持此消息类型\"\n- **MCP 不支持类别错误增强 (#140)**: 返回企业规模限制说明 + 更明确的停止重试指令\n\n### 升级\n\n```bash\nopenclaw extensions upgrade wecom\n```\n\n**完整变更日志**: https:\u002F\u002Fgithub.com\u002Fsunnoy\u002Fopenclaw-plugin-wecom\u002Fcompare\u002Fv2.3.0...v2.4.0","2026-03-23T08:28:50",{"id":164,"version":165,"summary_zh":166,"released_at":167},297839,"v2.3.0","## 相对于 v2.2.1\n\n### 功能\n- **welcomeMessagesFile**：JSON 外链欢迎语列表，支持热重载，无需重启网关\n- **image_studio**：可选通义\u002F万相生图工具（需配置 qwenImageTools）\n- **子 Agent 投递公告**（WS 模式，#133）\n\n### 修复\n- 动态 Agent 继承与 session key 问题（#125）\n- 被动回复媒体文件路径错误及空 @ 问题（#120）\n- 电话号码误识别为部门 ID 的问题（#124）\n\n详情请参阅 [CHANGELOG.md](https:\u002F\u002Fgithub.com\u002Fsunnoy\u002Fopenclaw-plugin-wecom\u002Fblob\u002Fv2.3.0\u002FCHANGELOG.md)。","2026-03-20T01:49:48",{"id":169,"version":170,"summary_zh":171,"released_at":172},297840,"v2.2.1","## 变更内容\n* 修复：防止手机号被误识别为部门ID，由 @yangsjt 在 https:\u002F\u002Fgithub.com\u002Fsunnoy\u002Fopenclaw-plugin-wecom\u002Fpull\u002F124 中完成\n* 尊重回复消息的媒体资源路径，并跳过空的群聊提及，由 @00010110 在 https:\u002F\u002Fgithub.com\u002Fsunnoy\u002Fopenclaw-plugin-wecom\u002Fpull\u002F120 中完成\n\n## 新贡献者\n* @00010110 在 https:\u002F\u002Fgithub.com\u002Fsunnoy\u002Fopenclaw-plugin-wecom\u002Fpull\u002F120 中完成了首次贡献\n\n**完整变更日志**：https:\u002F\u002Fgithub.com\u002Fsunnoy\u002Fopenclaw-plugin-wecom\u002Fcompare\u002Fv2.2.0...v2.2.1","2026-03-18T08:12:19",{"id":174,"version":175,"summary_zh":176,"released_at":177},297841,"v2.2.0","**完整更新日志**: https:\u002F\u002Fgithub.com\u002Fsunnoy\u002Fopenclaw-plugin-wecom\u002Fcompare\u002Fv2.1.0...v2.2.0","2026-03-15T03:34:35",{"id":179,"version":180,"summary_zh":181,"released_at":182},297842,"v2.1.0","## 功能特性\n\n- **自建应用 Agent 回调入站通道**: 支持企业微信自建应用以 HTTP 回调模式接收消息，作为独立的入站渠道。只需在 `agent.callback` 配置中设置 `token`、`encodingAESKey` 和 `path` 即可启用；路由会自动注册，并与 WS 通道并行运行。\n- **Agent API 回复支持 Markdown**: `agentSendText` 新增 `format` 参数（`\"text\"` | `\"markdown\"`），回调入站回复默认为 `\"markdown\"`；可通过 `agent.replyFormat` 配置项进行覆盖。\n- **入站\u002F出站信息日志**: 提供三条 INFO 级别日志：WS 入站 `[WS:account] ← inbound`、CB 入站 `[CB:account] ← inbound`、CB 出站 `[CB:account] → outbound`，便于在网关日志中追踪消息流。","2026-03-11T09:43:36",{"id":184,"version":185,"summary_zh":186,"released_at":187},297843,"v2.0.2","## 2.0.2 (2026-03-11)\n\n### 修复\n\n- **字段值中的 `@` 被误删**: 修复了企业微信群消息中\n\n### 测试\n\n- 新增群聊回归测试，\n- 新增 `extractGroupMessageContent()` 单元测试，验证提及信息的去除与字段值中 `@` 标记的保留可以同时成立。\n","2026-03-11T07:51:26",{"id":189,"version":190,"summary_zh":191,"released_at":192},297844,"v2.0.1","### 修复\n\n- **动态 Agent 配置持久化**: 将 `ensureDynamicAgentListed` 改为直接写入已变更的内存配置（与 `logoutAccount` 保持一致），修复了因 `loadConfig()` 在 gateway 运行时返回相同内存快照而导致写入被跳过的问题。现在，新的动态 Agent 会正确持久化到磁盘配置文件。\n- **Main Agent 心跳丢失**: 在初始化 `agents.list` 时，为 main 条目添加 `heartbeat: {}`，以防止动态 Agent 注册后 main 的心跳调度被意外排除（基于 `hasExplicitHeartbeatAgents` 逻辑）。\n\n### 备注\n\n- **SDK 100 条队列限制**: 企业微信 `@wecom\u002Faibot-node-sdk` 对每个 `reqId` 的回复队列上限为 100 条（`maxReplyQueueSize=100`），超出后会直接 reject。官方插件未进行任何流控处理，完全依赖 core 的缓冲分发器自然控制频率。本插件由于额外支持 reasoning stream，中间消息量更大，因此保留了 `MAX_INTERMEDIATE_STREAM_MESSAGES=85` 上限加上 800ms 时间节流的双重防护措施。","2026-03-10T12:07:31",{"id":194,"version":195,"summary_zh":196,"released_at":197},297845,"v2.0.0","## ⚠️ 注意\n\n本次 v2.0.0 为大版本重写，由于时间紧迫，测试覆盖尚不完全，欢迎大家测试并反馈问题！\n\n如遇到问题请在 [Issues](https:\u002F\u002Fgithub.com\u002Fsunnoy\u002Fopenclaw-plugin-wecom\u002Fissues) 中报告。\n\n## Breaking Changes\n\n- **移除 HTTP 回调模式**，全面切换至 WebSocket 长连接（需配合企微 AI 助理 WebSocket 模式）\n- 删除 `crypto.js`、`webhook.js`、`stream-manager.js` 及相关 HTTP handler 模块\n- OpenClaw 2026.3.8 兼容基础测试通过\n\n## New Features\n\n- 🔌 **多账号 WebSocket 并行连接** — 支持同时连接多个企微 AI 助理，自动重连 + 指数退避\n- 🤖 **动态 Agent 选择** — 按关键词\u002F正则\u002F默认规则路由消息到不同 Agent\n- 🔄 **Agent API 回调兜底** — WebSocket 断连时自动降级到 Agent API 投递消息\n- 📦 **待发送消息队列** — WS 断连期间缓存未发送消息，重连后自动投递（5 分钟 TTL）\n- ⏱️ **推理流 800ms 节流** — 防止 SDK 100 条队列溢出导致 thinking 内容丢失\n- 👥 **群聊 @机器人 支持** — 群消息策略（仅响应 @bot 的消息）\n- 🎙️ **语音消息识别** — 自动将语音转文字后发送给 Agent\n- 🖼️ **图片消息发送** — 通过 Agent API media_id 发送图片\n- 📊 **运行时遥测** — 连接状态、消息计数、错误统计\n- 🏖️ **沙箱隔离** — 账号级状态隔离\n- 📋 **入职引导** — 新用户自动引导流程\n\n## Refactor\n\n- 按职责拆分模块：`ws-monitor`、`ws-state`、`dm-policy`、`group-policy`、`onboarding`、`sandbox`、`runtime-telemetry`\n- `constants.js` 统一管理所有配置常量\n- 测试套件重写，覆盖新模块（113\u002F116 tests passing）\n\n## 安装 \u002F 升级\n\n```bash\nopenclaw plugins install @sunnoy\u002Fwecom\n```\n\n## 迁移指南\n\n从 v1.x HTTP 回调迁移到 v2.0 WebSocket 长连接，请参考 [README 运维迁移指南](https:\u002F\u002Fgithub.com\u002Fsunnoy\u002Fopenclaw-plugin-wecom#从-http-回调迁移到-websocket-长连接)。","2026-03-10T09:31:33",{"id":199,"version":200,"summary_zh":201,"released_at":202},297846,"v1.9.0","## What's New\n\n### Features\n- **Bindings 路由** (#85): 支持通过 OpenClaw `bindings` 配置将不同 WeCom 账户绑定到不同 Agent，显式 binding 优先于动态 Agent 路由\n- **deliveryMode: \"direct\"**: 对齐上游插件标准，声明直接投递模式\n- **emptyPluginConfigSchema()**: plugin-level configSchema 改用上游推荐的 safeParse 格式\n\n### Fixes\n- **Agent API 长文本截断** (#84): 新增 `splitTextByByteLimit()` 按 WeCom 2048 字节限制自动分段，优先在换行处断开\n- **XML body 误发检测** (#83): Bot webhook 收到 XML 请求时返回 400 并提示使用 Agent 回调地址\n- **消除顶层副作用**: `setInterval` 从模块顶层移入 `register()` 函数\n\n### Closed Issues\n- #78 bot 模式下，无法配置\n- #81 插件地址访问不到\n- #83 1.6.2 是不是没有调整到位\n- #84 Agent 长文本截断 \u002F 项目拆分讨论\n- #85 如何匹配多 agents 路由\n\n### Upgrade\n\n```bash\nopenclaw plugins install @sunnoy\u002Fwecom@1.9.0\n```\n\n**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fsunnoy\u002Fopenclaw-plugin-wecom\u002Fcompare\u002Fv1.8.0...v1.9.0","2026-03-06T12:59:46",{"id":204,"version":205,"summary_zh":206,"released_at":207},297847,"v1.8.0","## What's Changed\n\n### Bug Fixes\n\n- **#81 — 插件地址访问不到 (webhook path redirects to chat UI)**\n  `wecomHttpHandler` 在没有匹配的 webhook target 时不再返回 `false`（导致 OpenClaw 3.x SPA catch-all 接管 webhook 路径），改为返回 `404` + 正确的 HTTP 响应。\n\n- **#79 — Agent 模式 egressProxyUrl 代理不生效**\n  - 新增 `network.apiBaseUrl` 配置项和 `WECOM_API_BASE_URL` 环境变量，允许覆盖硬编码的 `qyapi.weixin.qq.com` 端点，支持反向代理\u002FAPI 网关方案。\n  - 修复字典模式下 `network`、`commands`、`dynamicAgents` 等顶层配置键被误识别为 account ID 的问题。\n  - 当配置了代理但 `undici` 不可用时，输出 ERROR 级别日志（之前静默回退到无代理模式）。\n\n- **#78 — Bot 模式无法配置**\n  放宽 plugin-level `configSchema` 和 `openclaw.plugin.json` 的 `additionalProperties` 为 `true`，防止 OpenClaw 3.2 配置验证拒绝合法属性。\n\n### New Configuration\n\n```yaml\nchannels:\n  wecom:\n    network:\n      # 覆盖微信 API 地址（适用于反向代理\u002FAPI 网关方案）\n      apiBaseUrl: \"https:\u002F\u002Fyour-proxy-gateway.example.com\"\n      # HTTP 代理（需要安装 undici）\n      egressProxyUrl: \"http:\u002F\u002Fproxy:8080\"\n```\n\n或通过环境变量：\n```\nWECOM_API_BASE_URL=https:\u002F\u002Fyour-proxy-gateway.example.com\nWECOM_EGRESS_PROXY_URL=http:\u002F\u002Fproxy:8080\n```\n\n### Test Coverage\n- 新增 `http-handler.test.js` — webhook handler 无 target 时的响应\n- 新增 `accounts-reserved-keys.test.js` — 字典模式 RESERVED_KEYS 覆盖\n- 新增 `api-base-url.test.js` — apiBaseUrl 配置覆盖\n- 新增 `proxy-route-fixes.e2e.test.js` — 远程 E2E 验证\n\n**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fsunnoy\u002Fopenclaw-plugin-wecom\u002Fcompare\u002Fv1.7.0...v1.8.0","2026-03-06T03:40:01",{"id":209,"version":210,"summary_zh":211,"released_at":212},297848,"v1.7.1","### Fixes\n\n- **Fix message truncation during tool calls (#73)**: Move `mainResponseDone` flag from deliver callback to after `dispatchDone`, preventing the 30s idle timeout from closing the stream while LLM is still executing tools","2026-03-05T11:05:34",{"id":214,"version":215,"summary_zh":216,"released_at":217},297849,"v1.7.0","## Features\n\n- **Thinking mode support**: Parse `\u003Cthink>` \u002F `\u003Cthinking>` \u002F `\u003Cthought>` tags from LLM output and display reasoning in WeCom's collapsible `thinking_content` field\n- **Passive reply thinking UI**: First sync response shows thinking mode UI immediately via `thinking_content` field\n- **Markdown fallback**: response_url fallback now sends `msgtype: \"markdown\"` instead of `text` for richer formatting\n\n## Fixes\n\n- **Stream routing**: Fix concurrent message race by checking `ctxStream.finished` before reusing async-context stream; fall back to latest recoverable stream\n- **Agent inbound whitelist**: Filter non-message event types (subscribe\u002Funsubscribe etc.) to prevent them from triggering LLM replies\n- **MEDIA regex**: Match only line-start `^MEDIA:` directives to align with upstream OpenClaw behavior\n- **Grace timer**: Reduce post-dispatch grace timer from 3000ms to 200ms for faster stream finalization\n- **Remove auto-detect \u002Fworkspace\u002F paths**: Remove overly aggressive workspace path auto-detection in outbound delivery; rely on upstream MEDIA directives and payload.mediaUrls instead\n\n## Docs\n\n- Add table of contents navigation to README\n- Add streaming capabilities documentation (Markdown, thinking mode, images)\n- Add CHANGELOG.md\n\n## Install\n\n```bash\nnpm install @sunnoy\u002Fwecom@1.7.0\n```\n","2026-03-05T09:42:29",{"id":219,"version":220,"summary_zh":221,"released_at":222},297850,"v1.6.2","## 变更范围\n本次发布覆盖 **`v1.6.0` → `v1.6.2`** 的全部变更。\n\n## 主要更新\n- 新增 `dynamicAgents.adminBypass`（默认 `false`）\n  - 管理员默认仅绕过指令白名单\n  - 可按需开启“管理员跳过动态 Agent 路由”（对应 #47）\n- 修复应用模式（Agent-only 账号）错误注册 Bot webhook 路径的问题（对应 #68）\n- 支持账号级 `workspaceTemplate` 覆盖全局模板目录\n- 新增并完善动态 Agent 路由相关测试\n\n## 安全修复\n- 修复 `\u002Fworkspace\u002F...` 文件路径自动发送链路中的路径穿越风险\n  - 拒绝 `..` 越界路径，确保文件读取仅限当前 Agent workspace\n  - 覆盖 `MEDIA:`、`payload.mediaUrl(s)`、自动路径检测三条发送路径\n\n## 提交记录（v1.6.0..v1.6.2）\n- `36aab25` fix: guard \u002Fworkspace path traversal in outbound delivery\n- `2cee5fc` release: v1.6.1 - admin bypass option and wecom routing fixes\n\n## 升级\n```bash\nopenclaw plugins install @sunnoy\u002Fwecom@1.6.2\n```\n","2026-03-05T03:11:59",{"id":224,"version":225,"summary_zh":226,"released_at":227},297851,"v1.6.0","## Breaking Change\n\n- **Requires OpenClaw 2026.3.2+** — drops backward compatibility with older versions.\n\n## Fixes\n\n- **Fix webhook callback verification failing after OpenClaw 3.2 upgrade** (Closes #61, Closes #65)\n  - OpenClaw 3.2 removed `api.registerHttpHandler()`; now uses `api.registerHttpRoute({auth: \"plugin\", match: \"prefix\"})`.\n  - `auth: \"plugin\"` bypasses gateway Bearer-token auth so WeCom `msg_signature` verification works correctly.\n  - Removes per-account `registerPluginHttpRoute` calls from `startAccount()` (no longer needed).\n  - Fixes webhook callbacks returning HTML (SPA catch-all) instead of decrypted echostr.\n\n## Upgrade\n\n```bash\nopenclaw extension install @sunnoy\u002Fwecom@1.6.0\n```\n\nThen restart the OpenClaw gateway.\n","2026-03-04T11:44:14",{"id":229,"version":230,"summary_zh":231,"released_at":232},297852,"v1.5.1","## v1.5.1\n\n新版本已修复（与已关闭 issue 对应）：\n\n- 兼容 OpenClaw 2026.3.2 路由注册变化（`registerPluginHttpRoute` \u002F 旧接口兼容）\n- Agent 模式补齐媒体出站（图片\u002F文件）\n- 增加 WeCom 外发代理支持（`channels.wecom.network.egressProxyUrl` \u002F `WECOM_EGRESS_PROXY_URL`）\n- 修复\u002F增强回调与流式处理相关逻辑\n- 增加相关单测与远程 E2E 用例\n\nnpm: `@sunnoy\u002Fwecom@1.5.1`","2026-03-04T09:53:18",{"id":234,"version":235,"summary_zh":236,"released_at":237},297853,"v1.5.0","## Changes\n\n- **媒体类型自动识别**: 新增 `resolveAgentMediaTypeFromFilename`，根据文件扩展名自动判断上传类型为 `image` 或 `file`，替换原先 Agent API 中硬编码的 `\"image\"` 类型，支持非图片文件通过私信正常投递\n- **流恢复增强**: 新增 `resolveRecoverableStream`，通过 `lastStreamByKey` 在异步上下文丢失时兜底恢复 stream，自动清除 `thinking...` 占位符并向用户发送文件投递提示\n\n## Fixes\n\n- 外部 URL 下载失败时抛出明确错误（`download media failed: \u003Cstatus>`）\n- fallback filename 从 `image.png` 修正为 `file`，避免误导文件名\n\n## Tests\n\n- 新增 `tests\u002Fchannel-plugin.media-type.test.js` 覆盖媒体类型识别逻辑\n","2026-03-03T03:08:08",{"id":239,"version":240,"summary_zh":241,"released_at":242},297854,"v1.4.1","### Bug Fixes\n\n- **智能解密媒体文件** — Bot 模式下文件不再损坏 (#44)\n  - 新增 magic-byte 签名检测 (PDF\u002FZIP\u002FJPG\u002FPNG 等 14 种格式)\n  - `smartDecrypt()`: 已是明文则跳过 AES-256-CBC 解密\n  - Agent 模式 (加密) 和 Bot 模式 (明文) 均可正确处理\n\n- **引用消息上下文注入** (#53)\n  - 群聊中引用消息的内容以 `> ...` 格式注入 rawBody，LLM 可感知引用上下文","2026-03-02T09:17:58",{"id":244,"version":245,"summary_zh":246,"released_at":247},297855,"v1.4.0","## 🎉 新功能\n\n### 多账号支持（Multi-Bot）\n\n现在可以在一个 OpenClaw 实例中接入多个企业微信机器人，每个机器人独立配置、互不干扰。\n\n```json\n{\n  \"channels\": {\n    \"wecom\": {\n      \"bot1\": {\n        \"token\": \"Bot1 Token\",\n        \"encodingAesKey\": \"...\",\n        \"agent\": { \"corpId\": \"...\", \"corpSecret\": \"...\", \"agentId\": 1000001 }\n      },\n      \"bot2\": {\n        \"token\": \"Bot2 Token\",\n        \"encodingAesKey\": \"...\",\n        \"agent\": { \"corpId\": \"...\", \"corpSecret\": \"...\", \"agentId\": 1000002 }\n      }\n    }\n  }\n}\n```\n\n**特性：**\n- 字典式配置：`channels.wecom` 下每个 key 即为一个账号\n- 完全向后兼容：旧的单账号配置无需修改，自动识别为 `default` 账号\n- 独立路由：每个账号自动分配独立的 Webhook 路径（`\u002Fwebhooks\u002Fwecom\u002F{accountId}`）\n- Agent 隔离：动态 Agent ID 按账号命名空间隔离\n- 冲突检测：启动时自动检测重复 Token \u002F Agent ID\n\n### 其他改进\n- 文件发送：LLM 生成的文件自动通过 Agent DM 发送\n- 沙箱路径解析：`\u002Fworkspace\u002F` 路径自动映射到宿主机\n- 流式响应修复：双信号关闭机制防止流永不结束\n- 小文件处理：\u003C 5 字节文件以文本形式内联发送\n\nCloses #45","2026-03-02T09:01:20"]