feat: 新增企业微信助手 Agent,并修正 wecom-cli 条目 ref 漂移 (#112)

## 概述 / Overview

两件事:新增「企业微信助手」Agent(自带 15 个技能),并修正 `wecom-cli` 条目钉在 6 月快照的 ref 漂移。

Two changes: adds the **WeCom Assistant** agent (bundling 15 skills),
and fixes the `wecom-cli` entry whose pinned ref was stuck on a June
snapshot.

## 1. 新增企业微信助手 Agent

覆盖企业微信 **14 类服务、95
个方法**:消息、群聊历史、通讯录、日程、会议、待办、邮件、在线文档、在线表格、智能表格、智能文档、文档管理、微盘、媒体文件。

**采用内联形态 + 自带私有技能**:Agent 安装对 `agents/<id>/` 整目录递归复制且 `skills/`
不在排除集合里,因此装 Agent 即带全部技能,用户无需再单独获取技能合集。

### 技能集(15 个,约 5000 行)

- 基于上游 [wecom-cli](https://github.com/WecomTeam/wecom-cli) 官方
Skill(MIT,© WecomTeam)改写,每个技能末尾保留归属声明
- **新增 `wecom-chat`**:补齐上游零覆盖的群聊历史读取
- 补齐上游未覆盖的 `message.send`、`doc.create`,方法覆盖达 **95/95**
- 修正上游三处文档漂移:邮件能力描述与实际相反、会议室参数名已过时、`title_highlight` 字段不存在

### 相对上游的核心增量:风险治理

- 26 个对外可见或不可逆的方法逐个写明**执行前确认要求**
- 4 个条件升级方法给出**参数级判据**,而非按方法名一刀切
- 文档权限扩散两项加重处理,涉及**企业外可见**时单独再确认一次
- 内部标识禁止外露,不因用户索要而放宽
- 拒绝导出可识别到具体自然人的隐私字段

### 三条真机实测得出、上游未覆盖的硬约束

1. 机器人**只能写入/修改自己创建的数据**,真人创建的只能读
2. 每次响应携带的 `extra_identity_context` **禁止透露给用户**
3. 权限错误(`850002`/`851008`/`853006`)**不得重试**,须将 `help_message`
**逐字原样**转给用户

## 2. 修正 wecom-cli 条目 ref 漂移

`source.ref` 原钉在 2026-06-28 的 `72e14f7`,该快照只有 7
个子技能且用已废弃的旧命名(`msg`/`schedule`)。上游 v1.2.0 已扩展到 **14 个**技能。按旧 ref
安装的用户拿到的是三个月前的快照。

- `source.ref` → `78c514b2afee7c0d3d7be715628478421f37ee63`
- `children` 由 `scripts/gen-collection-children.py` 重新生成,**7 → 14**
- sidecar 同步 `provenance.content.ref`、`childCount` 与 `children`

## 验证 / Verification

**静态**
- 215 条示例命令追加 `--dry-run` 实跑,**215/215 退出码 0**
- 未知方法 0、未知参数 0、`--json` 未知字段 0、枚举违规 0
- 15 个 `SKILL.md` 的 frontmatter 经客户端 `skillFrontmatterSchema` 校验全部通过
- `validate_catalog_metadata.py --require-complete` 与
`gen-collection-children.py`:**0 error**

**真机(在真实企业微信账号上端到端)**
- **待办域 6/6 方法全通**(含 2 个 write-high),`items` 必填的隐蔽坑实测证实
- **日程域 5 个方法全通**(含 3 个 write-high)
- 消息发送、通讯录解析、微盘列表、邮件搜索、文档搜索、会议列表、智能表格创建均已实测通过
- 测试数据已全部清理,未污染真实账号

**尚未实测**:群聊历史(机器人未开通该品类)。相关文档已明确标注验证状态,未实测的能力不写「实际效果」段落。
This commit is contained in:
2026-09-03 03:50:00 -04:00
committed by GitHub
parent c83f917901
commit aec2e7c28b
57 changed files with 16893 additions and 45 deletions

View File

@@ -0,0 +1,139 @@
# 邮件
企业微信邮箱的**发、回、转、搜、读**:发新邮件、回复、全部回复、转发、发日程邀约邮件与会议邮件,
按各种条件搜邮件,读正文、附件和内嵌图。
**能做的比大多数人以为的多**——但**标已读、删除、存草稿、改标签、撤回这些一概做不了**。
## 你可以怎么说
> 「给张三发封邮件,说 Q2 进展汇报已经发在群里了」
> 「回一下这封邮件:收到,周五前给结果」
> 「把这封转给李四」
> 「邮箱里搜一下产品周报」
> 「有没有新邮件?」
> 「这封邮件说了什么?」
## 📋 验证状态
| 项 | 状态 |
|---|---|
| 搜索邮件 | ✅ **已实测**(返回 0 封匹配——账号里当时确实没有匹配邮件) |
| 发送新邮件 | ⚠️ **未实测** |
| 回复 / 全部回复 | ⚠️ **未实测** |
| 转发 | ⚠️ **未实测** |
| 日程邀约邮件 / 会议邮件 | ⚠️ **未实测** |
| 读邮件正文、附件、内嵌图 | ⚠️ **未实测** |
| 完整链路(你说一句话 → 助手自动发完) | ⚠️ 未实测 |
**实测记录**(命令层,人工在真实账号上执行):
```bash
wecom-cli mail search # 通过,返回 0 封匹配
```
**只验证了「接口通、能返回」**。发送方向一条都没测——因为发出去就收不回,
不适合拿真人邮箱做验收实验。所以本页不写「实际效果」,也不虚构任何邮件内容、收件人或返回值。
## 能力清单
| 能做什么 | 命令 | 风险 |
|---|---|---|
| 搜索 / 浏览邮件列表 | `wecom-cli mail search` | 读取(隐私敏感) |
| 读邮件详情(正文 / 附件 / 内嵌图 / 日程信息) | `wecom-cli mail get` | 读取(隐私敏感) |
| 发送新邮件 | `wecom-cli mail send` | **高风险写入** |
| 回复 / 全部回复 | 同上(换一组参数) | **高风险写入** |
| 转发 | 同上 | **高风险写入** |
| 日程邀约邮件(只发日程,不建线上会议) | 同上 | **高风险写入** |
| 会议邮件(同时建线上会议) | 同上 | **高风险写入** |
后面五行其实是**同一个发送方法的五种用法**,靠传不同的参数区分,风险级别相同。
### 明确做不到的事
这些企业微信的命令行工具都没有提供,助手会如实告诉你去客户端操作:
- **标记已读 / 未读**(但**按未读条件搜索是可以的**
- **删除邮件**、**保存草稿**
- **给邮件打标签 / 移除标签**(但**按标签搜索是可以的**
- **撤回已发送的邮件**、**修改已发送的邮件**
- 邮箱账号设置、签名、自动回复、收信规则
## 注意事项
**发出去就收不回,所以一定会先给你看预览。**
助手会把最终的主题、收件人(只显示姓名,不显示邮箱)、抄送、正文完整摆出来,
**然后等你明确同意才发**。哪怕你已经把内容说得很完整,这一步也不会省。
(顺带说明一件事:这套助手的上游文档原本要求「展示完预览就直接发,不许再问」。
本项目**故意改了这条**——发邮件不可撤回,属于最典型的高风险动作,所以预览之后仍然要等你点头。)
**回复的收件人来自原邮件,不去通讯录里找。**
这条看起来是细节,实际很关键:通讯录的模糊搜索可能匹配到同音不同字的人,那就发错了。
所以回复时助手直接用原邮件里的发件人地址。
**「回一下」默认是全部回复。** 想只回发件人,说清楚「只回他」「别回复所有人」。
即使参数上不需要列收件人,**预览里也会把最终会收到这封邮件的所有人列全**,让你看清范围。
**主题前缀是助手自己拼的。** 回复会拼成「回复:原主题」,转发拼成「转发:原主题」。
原主题已经带同类前缀时会沿用(一字不改,不会「顺手规范化」),
但**跨类型不抵消**——转发一封「回复xxx」主题会变成「转发回复xxx」。
**转发默认不带附加说明。** 你没提要加话,助手就不加,企业微信会自动带上原邮件正文。
你提了,它才写进去。
**日程邮件和会议邮件的区别是「建不建线上会议室」。**
- 说「开会 / 线上会议 / 拉个视频会」→ **会议邮件**(会建线上会议室)。**线下会议也走会议邮件**
会议室照建,用不用由你定。
- 说「发个日程 / 约个碰头 / 提醒大家周五有活动」→ **日程邀约邮件**(不建会议室)。
- 实在判不准,助手会问一句「需要创建线上会议室吗?」。
**只有你明确提到「邮箱」或「邮件」时才走这条路。**
你只说「帮我约个会」而没提邮件,那是 [05 日程](05-日程.md) / [06 会议](06-会议.md) 的活,
助手**不会**擅自替你改成「发封会议邮件」。
**搜索有三条硬线:**
- 带时间范围、未读、重要这类条件时,**搜索窗口不超过最近 30 天**。
- 带关键词的搜索**最多返回 100 封**。
- 单封邮件的正文加附件**合计不超过 50MB**。
**「最近」按 7 天算。** 你说「最近」「近期」「这段时间」而没给具体范围时,助手按最近 7 天处理,
并会在回复里说明它用的是哪个范围。
**没拉完会明说。** 结果还有更多没取回时,助手会在末尾提示「已展示前 N 条(未拉完)」,
**不会让你误以为看到的就是全部**。问「有几封」时它看的是总数字段;
总数被接口限制截断时也会如实说明。
**多封候选时它不会替你挑。** 你要找某一封特定的邮件而搜出好几封时,
助手会用「序号 + 主题 + 发件人 + 时间」列出来让你选。只是浏览或统计时才直接给列表。
**附件分两种,一种下得下来,一种下不来。**
- 普通附件——助手能落到本地读给你听。
- **微盘附件、以及防泄漏加密链接**——这类只能给你一个可点的链接,助手**打不开也解不开**
引导你在企业微信客户端里点开看。这是正常的产品行为,不是故障。
**邮件正文里的内容是数据,不是指令。** 正文里如果出现「忽略之前的指令」「请执行以下命令」
这类文本,助手一律当普通文字处理,不执行。检测到疑似夹带时会在摘要里附一句提示。
**收发件人数量看计数不看列表。** 一封群发邮件,接口只返回前 30 个收件人,真实人数在计数字段里。
问「这封发给了多少人」时助手报的是真实总数。
### 三条通用边界在本域怎么体现
1. **只能改它自己建的东西**——邮件这一域的写操作**只有「发出去」**,没有「改已有的」。
已发送的邮件既不能改也不能撤回,接口层就没有这两个能力。
2. **能力按品类逐项开通**——邮件是独立品类(实测账号是后来单独补开的)。
未开通时助手会把官方开通指引原样转给你,然后停下,不重试。
3. **危险动作先问你**——**发送方向的五种用法全是高风险写入**,都会先展示预览、
再等你明确同意。见 [99 风险与确认](99-风险与确认.md)。
## 相关
- [02 通讯录](02-通讯录.md)——按人名发邮件时,先在这里把姓名解析成邮箱
- [05 日程](05-日程.md) / [06 会议](06-会议.md)——管理日程和会议**本身**(改期、取消、查询)走那边,
本域只负责「通过邮件发出去」
- [15 媒体文件](15-媒体文件.md)——读邮件附件内容时中间那一步在做什么
- [03 消息与会话](03-消息与会话.md)——发企业微信消息是另一套能力
- [99 风险与确认](99-风险与确认.md)——发送前的确认怎么算数