Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions external_plugins/wechat-connector/.zcode-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "wechat-connector",
"description": "Send notifications to WeCom (WeChat Work) group robots via the official webhook API — outbound text and markdown group notifications from ZCode.",
"description_i18n": {
"en": "Send notifications to WeCom (WeChat Work) group robots via the official webhook API — outbound text and markdown group notifications from ZCode.",
"zh-CN": "通过企业微信群机器人官方 webhook 接口发送群通知:支持文本与 Markdown 消息、多渠道配置与频控处理。"
},
"version": "0.1.0",
"author": {
"name": "zhaohongjun20-creator",
"url": "https://github.com/zhaohongjun20-creator"
},
"license": "MIT",
"keywords": ["wechat", "wecom", "webhook", "notification", "group-robot", "qyapi"],
"skills": "./skills"
}
112 changes: 112 additions & 0 deletions external_plugins/wechat-connector/DESIGN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# wechat-connector 微信接入插件 · 设计草案 v0.2

日期:2026-11-01 | 状态:v0.2 —— M1 已实现并实测通过(errcode 0);M2 规划中

## 1. 目标与范围

让 ZCode 通过**微信官方接口**收发消息:

| 能力 | 方向 | 通道 | 版本 |
|---|---|---|---|
| 群通知(文本 / Markdown) | 出站 | 企业微信群机器人 webhook | M1 |
| 对话机器人 | 双向 | 微信公众号(开发用测试号) | M2 |
| 图片 / 模板卡片、多群多渠道 | — | 同上 | M3 |

**明确不做**:个人微信客户端自动化 / 协议机器人——违反微信使用条款、有封号风险,不碰。

## 2. 总体架构

```
ZCode 会话
│ skills(纯指令文档,教 agent 怎么做)
│ ├─ wechat-send:发通知(curl → 机器人 webhook)
│ └─ wechat-bot:收发对话(读 mailbox → 生成回复 → curl 客服接口)
│
├──(M2 起)gateway:常驻小服务(Node,无重依赖)
│ 微信服务器 → HTTP 回调 → 验签 → 追加 mailbox/inbox.jsonl → 立即回空串
│
├──(M2 起)responder:回复引擎,可插拔
│ A. zcode-session:ZCode 定时任务读 mailbox,用当前会话模型生成回复(能调全部工具)
│ B. llm-api:常驻脚本轮询 mailbox,直接调 OpenAI 兼容接口生成回复(默认 DeepSeek)
│
└── 运行时数据 ~/.zcode/wechat/
config.json(多个 webhook 渠道、appid/secret/token)
mailbox/inbox.jsonl(网关写,ZCode 读)
mailbox/seen.json(MsgId 去重)
```

设计原则:**先零依赖,后加组件**。

- M1 不需要任何常驻进程:skill 教 agent 用 `curl` 直接调 webhook,密钥从环境变量读。
- M2 才引入 gateway + mailbox;收发用 Read/curl 即可完成,先不写 MCP server,等工具面变大后再封装成 MCP(留作演进项)。

## 3. 接口约定

**出站(企业微信 webhook)**

- `POST https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=XXX`
- msgtype:`text`(支持 @mention)/ `markdown` / `image`(base64+md5)/ 模板卡片
- 频控:每机器人 20 条/分钟,超出时排队或合并;失败退避重试 3 次

**入站(公众号回调,gateway 暴露)**

- `GET /wechat/callback`:微信验证,echostr 原样返回
- `POST /wechat/callback`:验签 `sha1(sort(token, timestamp, nonce))`,解析 XML 得 FromUser / Content / MsgId
- 收到即回空串(规避 5 秒被动回复超时与重推),消息落 mailbox 异步处理
- 回复走客服接口 `POST message/custom/send`(测试号无 48h 窗口限制)

**回复引擎(M2,可插拔)**

- 方案 A `zcode-session`:定时自动化(如每 2 分钟)拉 mailbox,ZCode 用当前模型生成并发出回复——能查文件、跑命令,适合"半自动助理";依赖 ZCode 会话在跑。
- 方案 B `llm-api`(默认先做):独立 responder 脚本常驻轮询 mailbox,直接调 OpenAI 兼容接口生成并回复。默认接 DeepSeek:`base_url=https://api.deepseek.com`、`model=deepseek-chat`、密钥 `DEEPSEEK_API_KEY`;换其他模型只改 base_url/model 两个变量。7×24 无人值守,成本最低。

**配置优先级**:环境变量 > `config.json`。
`WECHAT_WEBHOOK_URL`、`WECHAT_APPID` / `WECHAT_SECRET` / `WECHAT_TOKEN` / `WECHAT_ENCODING_AES_KEY`、`DEEPSEEK_API_KEY`(M2 方案 B)。
密钥永不写入插件源码、不进 git。

## 4. 插件目录结构(按 ZCode 插件规范)

```
plugins/
marketplace.json # 本地测试市场
wechat-connector/
.zcode-plugin/plugin.json # name: wechat-connector, version 0.1.0
skills/wechat-send/SKILL.md
skills/wechat-bot/SKILL.md # M2
gateway/index.mjs + package.json # M2
DESIGN.md / README.md
```

manifest 只声明真实存在的组件(M1 仅 `"skills": "./skills"`),M2 起再按需加 `"mcpServers"`。

## 5. 里程碑与验收

| 里程碑 | 内容 | 验收标准(代表性用例) |
|---|---|---|
| M1 出站通知 | wechat-send skill + 配置模板 + 冒烟脚本 | 对 ZCode 说"往研发群发:今晚 8 点发布"→ 群里收到该消息 |
| M2 双向对话 | gateway + mailbox + wechat-bot skill + responder(默认 DeepSeek 方案 B) | 给测试号发"你好"→ 1 分钟内收到机器人回复 |
| M3 增强 | 图片/卡片消息、多群渠道管理、消息日志查询 | 另行评审 |

回复引擎方案 A 由 ZCode 定时自动化驱动(每 2 分钟处理一次新消息),平时也可以手动说一句"看看微信";方案 B 由 responder 自己轮询,完全不依赖 ZCode 在线。

## 6. 安全与合规

- 回调验签,可选 AES 加密模式;验签失败一律 403
- MsgId 去重,防微信重推导致重复回复
- webhook URL 视同密码,不入库不入 git
- 频控 + 退避重试,防止刷屏被封 webhook
- 全程走官方 API,无逆向协议、无第三方机器人框架

## 7. 风险与限制

- 公众号被动回复有 5 秒超时 → 已用"回空 + 异步 mailbox"模式规避
- 测试号回调需要公网可达的 80/443 → 本地开发用内网穿透(cpolar / ngrok / frp),或直接部署到云服务器
- 未认证订阅号的客服接口有 48 小时会话窗口限制 → 先在测试号上开发,不受此限
- 企业微信 webhook 每机器人 20 条/分钟,大量通知需合并发送

## 8. 设计决策记录(已确认)

1. 通道:企业微信群机器人(出站,M1)+ 公众号(双向,M2);个人微信客户端自动化永不支持。
2. 架构:M1 零依赖(skill + curl);M2 起引入 gateway(Node)+ 本地信箱;回复引擎可插拔(A:ZCode 会话 / B:OpenAI 兼容 API,默认 DeepSeek)。
3. 实现语言:Node/JavaScript(gateway 与未来 MCP),skill 为纯 Markdown。
4. M2 的 gateway 部署位置:待定(本地 + 内网穿透,或云服务器)。
21 changes: 21 additions & 0 deletions external_plugins/wechat-connector/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 zhaohongjun20-creator

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
82 changes: 82 additions & 0 deletions external_plugins/wechat-connector/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# wechat-connector — WeChat Connector for ZCode

A ZCode plugin that sends notifications to WeCom (WeChat Work / 企业微信) group robots through Tencent's **official webhook API**. No reverse-engineered protocols and no client automation — just an HTTPS call to the group robot webhook you create in your own group, so there is no account-ban risk from unofficial clients.

[中文说明](README_CN.md)

## Features

- Send **text** and **Markdown** messages to one or more WeCom groups
- Multi-channel configuration: several groups / webhook URLs as named channels
- Rate-limit aware: 20 messages/minute per robot, with retry guidance built into the skill
- Official API only, zero background services for outbound notifications (a single `curl` call)
- Ships as a ZCode skill (`wechat-send`), so any ZCode session can use it once installed

## Install

**Option A — from the official community marketplace (recommended after review):**
add the `zcode-plugins-official` marketplace in your ZCode client, then install *WeChat Connector (微信接入)*.

**Option B — from this repository:**
add this repository as a plugin marketplace in your ZCode client (if your version supports git sources), or clone it and add the local directory:

```bash
git clone https://github.com/zhaohongjun20-creator/wechat-connector.git
# then in ZCode: Plugin Marketplace → Add → Add Plugin Marketplace → select the cloned folder
```

## Configuration

The webhook URL is treated as a secret. It is read from (in priority order):

1. Environment variable `WECHAT_WEBHOOK_URL`
2. Config file `~/.zcode/wechat/config.json` (Windows: `C:\Users\<you>\.zcode\wechat\config.json`):

```json
{
"default_channel": "default",
"channels": {
"default": { "webhook": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=***" }
}
}
```

Ask the agent to "send to channel XX" and it matches the key under `channels`.

### Create a group robot (mobile app is enough)

WeCom group chat → top-right "…" → **Group robots (群机器人) → Add robot** → copy the webhook URL. The robot must stay in the group; if it is removed, the webhook is invalidated and the API returns `errcode 93000`.

## Usage

After installing, say to ZCode:

> Send to the WeCom group: release tonight at 8 PM

The agent resolves the webhook, posts the message, and reports the API result (`errcode 0` means delivered).

## Side effects & security

This section discloses everything the plugin touches, as required for community plugins:

- **Network access**: the skill sends HTTPS `POST` requests to `https://qyapi.weixin.qq.com` (Tencent's official endpoint) containing the webhook URL and the message content.
- **Command execution**: the skill instructs the agent to run `curl` for the HTTP call.
- **File writes**: message payloads are written as temporary JSON files in the system temp directory.
- **Credentials**: webhook URLs (and future API tokens) live only in `~/.zcode/wechat/config.json` or environment variables on your machine. They are never committed to the plugin source, and are sent nowhere except Tencent's API endpoint.
- **No** MCP server, **no** hooks, **no** third-party code or assets.

## How it works

The plugin ships one skill, `skills/wechat-send/SKILL.md`. It documents the official webhook message format (text / markdown / image, mention lists, rate limits, error codes) and instructs the agent to resolve the webhook from config, write a UTF-8 JSON payload (avoiding Windows codepage issues), post it with `curl --data-binary`, and verify the `errcode` in the response.

## Roadmap

- **M1 (shipped)**: outbound group notifications via WeCom group robot webhook
- **M2 (planned)**: two-way conversation via a WeChat Official Account (test account for development) + pluggable reply engine — option A: ZCode session as the brain; option B: any OpenAI-compatible API (default target: DeepSeek)
- **M3 (planned)**: rich messages (images / template cards), channel management, message log queries

Design details: [DESIGN.md](DESIGN.md) (in Chinese).

## License

[MIT](LICENSE)
80 changes: 80 additions & 0 deletions external_plugins/wechat-connector/README_CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# wechat-connector — ZCode 微信接入插件

通过企业微信群机器人**官方 webhook 接口**发送群通知的 ZCode 插件。不碰逆向协议、不做客户端自动化——只是向你自己在群里创建的群机器人发一条 HTTPS 请求,没有封号风险。

[English](README.md)

## 功能

- 向一个或多个企业微信群发送**文本**和 **Markdown** 消息
- 多渠道配置:多个群 / webhook 地址以命名渠道管理
- 频控感知:每个机器人 20 条/分钟,skill 内置退避重试指引
- 全程官方 API,出站通知零常驻服务(一次 `curl` 调用)
- 以 ZCode skill(`wechat-send`)形式提供,安装后任何 ZCode 会话都能用

## 安装

**方式 A —— 官方社区市场(评审通过后推荐):** 在 ZCode 客户端添加 `zcode-plugins-official` 市场,安装"微信接入(WeChat Connector)"。

**方式 B —— 从本仓库安装:** 若你的客户端版本支持 git 源,直接把本仓库添加为插件市场;或先克隆再添加本地目录:

```bash
git clone https://github.com/zhaohongjun20-creator/wechat-connector.git
# 然后在 ZCode:插件市场 → 添加 → 添加插件市场 → 选择克隆出的文件夹
```

## 配置

webhook 地址视同密码,按以下优先级读取:

1. 环境变量 `WECHAT_WEBHOOK_URL`
2. 配置文件 `~/.zcode/wechat/config.json`(Windows:`C:\Users\<用户名>\.zcode\wechat\config.json`):

```json
{
"default_channel": "default",
"channels": {
"default": { "webhook": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=***" }
}
}
```

对 agent 说"发到 XX 群",会按渠道名匹配 `channels` 下的键。

### 创建群机器人(手机版即可)

企业微信群聊 → 右上角"…" → **群机器人 → 添加机器人** → 复制 webhook 地址。机器人必须留在群里;一旦被移出,webhook 立即失效(接口返回 `errcode 93000`)。

## 用法

安装后对 ZCode 说:

> 往企业微信群发:今晚 8 点发布

agent 会解析 webhook、发送消息并回报接口结果(`errcode 0` 即送达)。

## 副作用与安全声明

按社区插件要求,完整披露本插件的一切外部影响:

- **网络访问**:skill 会向 `https://qyapi.weixin.qq.com`(腾讯官方接口)发起 HTTPS `POST`,内容为 webhook 地址与消息文本。
- **命令执行**:skill 指示 agent 运行 `curl` 完成 HTTP 调用。
- **文件写入**:消息 payload 以临时 JSON 文件写入系统临时目录。
- **凭据**:webhook 地址(以及后续的 API token)只保存在本机 `~/.zcode/wechat/config.json` 或环境变量中,绝不写入插件源码,除腾讯接口外不发送到任何地方。
- **没有** MCP 服务、**没有** hooks、**没有**第三方代码或素材。

## 工作原理

插件只包含一个 skill:`skills/wechat-send/SKILL.md`。其中记录了官方 webhook 的消息格式(text / markdown / image、@提及、频控、错误码),并指示 agent:从配置解析 webhook → 以 UTF-8 写出 JSON payload(规避 Windows 代码页问题)→ 用 `curl --data-binary` 发送 → 校验响应中的 `errcode`。

## 路线图

- **M1(已交付)**:企业微信群机器人出站通知
- **M2(规划中)**:公众号双向对话 + 可插拔回复引擎(方案 A:ZCode 会话当大脑;方案 B:任意 OpenAI 兼容接口,默认 DeepSeek)
- **M3(规划中)**:富消息(图片 / 模板卡片)、渠道管理、消息日志查询

设计细节见 [DESIGN.md](DESIGN.md)。

## 许可证

[MIT](LICENSE)
66 changes: 66 additions & 0 deletions external_plugins/wechat-connector/skills/wechat-send/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
name: wechat-send
description: Send text or markdown notifications to a WeCom (企业微信) group robot via official webhook API. Use when the user asks to send a message / notice / notification to a WeCom group, 企业微信群, 群通知, or 企业微信机器人.
---

# wechat-send — 企业微信群机器人通知

通过企业微信群机器人 webhook 发送群通知,全程走官方 API,无需任何常驻服务。

## 1. 取 webhook 地址

按优先级:

1. 环境变量 `WECHAT_WEBHOOK_URL`;
2. 配置文件 `~/.zcode/wechat/config.json`(Windows 下通常是 `C:\Users\<用户名>\.zcode\wechat\config.json`),结构:

```json
{
"default_channel": "default",
"channels": {
"default": { "webhook": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=***" }
}
}
```

用户说"发到 XX 群"时,按渠道名匹配 `channels` 的键;未指明则用 `default_channel`。

**安全**:webhook URL 视同密码——不要在回复中原样展示 key,不要写入任何会提交到仓库的文件。

## 2. 发送(Windows / Git Bash 编码注意)

不要把含中文的 JSON 直接放进 curl 命令行参数(Windows 代码页会破坏 UTF-8)。先用 Write 工具把 payload 写成 UTF-8 临时文件,再发送:

文本消息(临时文件,如 `$TMP/wechat-payload.json`):

```json
{"msgtype": "text", "text": {"content": "今晚 8 点发布"}}
```

Markdown 消息:

```json
{"msgtype": "markdown", "markdown": {"content": "## 发布通知\n今晚 **8 点** 发布,请留意"}}
```

发送:

```bash
curl -sS -X POST -H "Content-Type: application/json" \
--data-binary @"$TMP/wechat-payload.json" \
"$WEBHOOK"
```

注意必须用 `--data-binary`(不要用 `-d`,它会剥掉换行);Git Bash 下路径用正斜杠。

**校验**:响应为 `{"errcode": 0, "errmsg": "ok"}` 才算成功。`errcode` 非 0 时:
- `45009`(接口超频):等 30 秒重试一次;
- `93000` 或 invalid webhook:提示用户检查 webhook 地址是否失效(机器人被移除会失效);
- 其他错误:把 errcode/errmsg 原样报告给用户。

## 3. 限制与礼仪

- 每个机器人 **20 条/分钟**:多条内容尽量合并为一条;确实要分批时每条间隔 3 秒以上。
- 单条 text / markdown 内容上限 4096 字节(UTF-8),超长先分段。
- 除非用户明确要求,不要用 `"mentioned_list": ["@all"]`。
- 这是群通知通道,不是个人聊天,不要用来做对话轮询。
Loading