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,127 @@
# 日程
把「什么时候、和谁、在哪儿」落到企业微信日历上:约日程、看安排、找大家都有空的时间、订会议室、改期、取消。
它管的是**不带会议号和入会链接**的安排——包括纯线下的面对面碰头,也包括订了会议室的线下会。
要的是带入会链接的在线会议,见 [06 会议](06-会议.md)。
## 你可以怎么说
> 「我明天有什么安排?」
> 「约个日程:周三下午 2 点产品评审,叫上张三和李四」
> 「项目评审是什么时候?」
> 「把周四那个会挪到下午 4 点」
> 「张三和李四这周什么时候都有空?」
> 「订个会议室16 楼的,能坐 6 个人」
## 📋 验证状态
| 项 | 状态 |
|---|---|
| 创建日程 | ✅ **已实测** |
| 查看日程列表 | ✅ **已实测** |
| 按标识取日程详情 | ✅ **已实测** |
| 改期(更新日程) | ✅ **已实测** |
| 取消日程 | ✅ **已实测** |
| 查多人共同空闲时段 | ⚠️ **未实测** |
| 查办公楼清单 / 查会议室可订性 / 订会议室 | ⚠️ **未实测** |
| 完整链路(你说一句话 → 助手自动约完) | ⚠️ 未实测 |
**实测记录**(命令层,人工在真实账号上执行):
一条完整的生命周期跑通了 5 个方法——
```
schedules create → schedules list → schedules get
→ schedules update15:00 改到 16:00
→ schedules cancel取消后列表归零
```
取消后复核,日程列表数量归 0`schedule_list_count: 0`),测试数据已清理干净。
其中 `update``cancel` 都属于高风险写入,实测时是明确知情后执行的。
**另有一条界面内的行为实测**(不是命令层):让助手「帮我约个会」时,它触发的消歧问句
**逐字正确**——`需要创建日程还是会议?(请回复:日程 / 会议)`
这一条是修复了一个缺陷之后复测通过的,见下方「注意事项」。
## 能力清单
| 能做什么 | 命令 | 风险 |
|---|---|---|
| 查某段时间的日程列表 | `wecom-cli calendar schedules list` | 读取 |
| 按关键词 / 组织人 / 参与人搜日程 | `wecom-cli calendar schedules search` | 读取 |
| 按标识批量取日程详情 | `wecom-cli calendar schedules get` | 读取 |
| 查多人共同空闲时段 | `wecom-cli calendar schedules free list` | 读取 |
| 查企业办公楼清单 | `wecom-cli meeting rooms buildings list` | 读取 |
| 查会议室这个时段空不空 | `wecom-cli meeting rooms search` | 读取 |
| 创建日程(可邀请参与人、可占会议室) | `wecom-cli calendar schedules create` | **高风险写入** |
| 更新日程(改时间 / 地点 / 人 / 会议室) | `wecom-cli calendar schedules update` | **高风险写入** |
| 取消(删除)日程 | `wecom-cli calendar schedules cancel` | **高风险写入** |
三个写方法都会**通知到别人**:建带参与人的日程会给对方发邀请、对方日历上立刻多出这条;
改期会通知全体参与人,被移除的人会直接失去这条日程;取消会通知所有人**且无法撤回**。
所以每一个执行前都会复述并等你同意。
## 注意事项
**日程和会议的区别只有一条:有没有会议号和入会链接。**
有的是「会议」,没有的是「日程」——**订了会议室的纯线下会也算日程**。
- **创建**时,你只说「开个会」而没说清是哪种,助手会**逐字问你一句固定的话**
`需要创建日程还是会议?(请回复:日程 / 会议)`
这句话的措辞是钉死的,不会被改写成「线上还是线下」「视频会议还是普通日程」之类的变体——
因为下游是按「日程」/「会议」这两个词匹配你的回复的。
**注意**:「在 1605 开会」「订个会议室开会」这种**只给了地点**的说法**也不算说清楚**
它还是会问——会议室里同样可能要远程接入。
- **查询**时它**不会问**这一句。你说「最近有什么会」,它会**日程和会议两边都查**,再合并给你,
末尾汇总「共 N 场,其中会议 X 场、日程 Y 场」。
**改约永远是「改」,不是「先取消再新建」。**
即使你说的是「把周四那个会取消,改约到周五」,助手也会走「更新」这条路。
原因很实在:**会议链接重建不出来**——一旦拆成取消 + 新建,参与人手里的旧入会链接会全部作废,
而新建的纯日程根本生成不了新链接。这条禁令没有例外。
**会议室查询归日程,不归会议——这一点反直觉。**
虽然命令看起来是「会议」开头的,但查办公楼、查会议室、订会议室这几件事都由日程这一域负责。
[06 会议](06-会议.md) 要订会议室时,会反过来调用这边。你不需要记这个,说「订个会议室」就行。
**会议室只写进「地点」等于没订。**
助手会真正去查这个时段这间会议室空不空拿到真实的会议室再占用而不是把「1605 会议室」
当成一行文字塞进地点字段。**订房是创建的前置阻塞项**——提到了会议室却没订上,
它不会「先把日程建了回头补会议室」。
指定的会议室查无此室或已被占用时,助手会**先告诉你**,哪怕只有一个替代候选也要你确认,
**不会静默换一间**。另外,会议室被占用时企业微信**不会告诉你被谁占了**,助手也就不会编。
**多人时会先查冲突再让你拍板。** 约多人日程时助手会先查共同空闲时段,把冲突摆给你看,
由你决定是按这个时间硬约还是换一个。它不会替你做这个决定。
注意共同空闲查询的窗口**不超过 24 小时**,而且**早于当前时刻的部分会被自动截断**——
所以「昨天大家什么时候有空」永远查不出东西。
**周期性(重复)日程完全不支持。** 创建、修改、取消重复日程都做不了,助手会直接告诉你要去
企业微信客户端操作,**不会用「建多条单次日程」「逐场修改」这类变通蒙混过去**。
**接受 / 拒绝日程邀请RSVP也不支持**,得你自己在客户端点,或者私信发起人。
**时间要给具体的。** 助手向你确认时间时,候选一定是**精确到分钟的具体时刻**(「明天 14:00」「周六 10:30」
不会给「上午」「下班前」这类模糊选项。你只给了开始时间没给结束时间时,它按 1 小时算,不追问。
**查询窗口有边界。** 日程列表能查的是当前时刻前后各 30 天,超出部分企业微信直接不返回(不是报错)。
超范围时助手会请你给一个更短的范围,**不会自行截断后假装查全了**。
### 三条通用边界在本域怎么体现
1. **只能改它自己建的东西**——**这一条在日程上最容易撞到**。你自己在企业微信里建的那条日程,
助手**改不了也取消不了**。它不会预先拦你,而是直接去执行,拿到权限错误后如实告诉你,
并建议你联系创建人或自己在客户端改。
2. **能力按品类逐项开通**——日程与会议室是独立品类。未开通时助手会把官方开通指引原样转给你,
然后停下,不重试。
3. **危险动作先问你**——建、改、取消三个动作**全是高风险写入**,每次都会复述
「主题、时间、涉及哪些人、能否撤回」并等你明确同意。见 [99 风险与确认](99-风险与确认.md)。
## 相关
- [06 会议](06-会议.md)——要入会链接和会议号的在线会议
- [02 通讯录](02-通讯录.md)——拉人进日程前先在这里把人名解析出来
- [07 待办](07-待办.md)——「记一件要做的事」而不是「占一段时间」时用它
- [08 邮件](08-邮件.md)——**通过邮件**发日程邀约是另一条路(只有你明确提到「邮件」时才走那边)
- [99 风险与确认](99-风险与确认.md)——三个写方法的确认规则