feat: export core Hermes skills

This commit is contained in:
2026-07-15 02:45:56 +00:00
parent a028b63eda
commit 54711fee2a
308 changed files with 41310 additions and 1 deletions
@@ -0,0 +1,88 @@
# 飞书群发消息 + @人(已验证配方 2026-06-16)
目标:把消息发到**正确的飞书群**并 **@ 正确的人**,一次做对。依赖 `lark-cli`(lark-im 技能)。
## 步骤
### 1. 找出 bot 实际所在的群(不要猜 chat_id)
```bash
cd ~ && lark-cli im +chat-list --as bot
```
返回每个群的 `chat_id``name``description``owner_id`。挑出你和目标人**共处**的那个群。
- 本环境已知群:"Doro, Maggie, 魏玮"(描述"小Maggie工作群")= `oc_a927f86118216c36cb9394b0e95f2a11`
- 若有多个候选群,按成员和描述确认,仍不确定就问用户,别赌。
### 2. @人的格式(两种已验证写法,均触发真实可点击 @ + 通知)
- **text 模式**:`--msg-type text`,content 形如 `{"text":"<at>…</at> 正文"}`,@ 标签 `<at user_id="ou_xxx">显示名</at>`(用 **open_id**;嵌进 JSON 字符串时内层引号按 JSON 规则转义)。@所有人 `<at user_id="all"></at>`
- **post 模式**(多行/结构化汇报推荐,2026-06-16 已验证):post JSON 里 @ 用 at 元素 `{"tag":"at","user_id":"ou_xxx"}`,与文本元素 `{"tag":"text","text":"…"}` **同行**拼接,配 `--msg-type post`。结构:
`{"zh_cn":{"content":[[{"tag":"at","user_id":"ou_757f053c9d7aff6c73b18aa60c337756"},{"tag":"text","text":" 进展汇报…"}],[{"tag":"text","text":"第二行"}]]}}`
- **不要用 `--markdown`** 发 @:会强制转 post 且 @ 处理不可靠,用显式 post JSON 自己控制。
### 3. 先 dry-run 验证 payload
```bash
lark-cli im +messages-send --chat-id oc_xxx --as bot \
--content '{"text":"<at user_id=\"ou_757f053c9d7aff6c73b18aa60c337756\">Doro</at> 正文…"}' \
--msg-type text --dry-run
```
检查 body 里 chat_id、msg_type、@标签是否正确
### 4. 去掉 --dry-run 正式发送
成功返回 `message_id` + `create_time`。把 message_id 和**北京时间**报给用户便于核对。
## 发送前如何核实「这个 open_id 确实是目标本人」
@错人是红线。理想是查通讯录,但本 bot **常缺 contact / chat 读权限**,按可靠性从高到低:
1. **gateway.log 取地面真值(最可靠,无需任何 scope)**——平台事件原始数据,比 API、比记忆都硬:
```bash
grep "oc_<群id>" ~/.hermes/logs/gateway.log | grep -oE "ou_[a-z0-9]{20,}" | sort | uniq -c | sort -rn
```
再看「当前这条消息」的入站行确认发送者:
```bash
grep "inbound message: platform=feishu" ~/.hermes/logs/gateway.log | tail
# → user=ou_xxx chat=oc_xxx msg='…' 即是谁在这个群说了这句话
```
把刚收到那句话的 `user=ou_xxx` 与已知映射比对,一致才发。
2. **已知 open_id 映射**(下方表 + memory),ID 没映射到人 → 先问不猜。
3. **通讯录 API(常被 scope 挡)**:`lark-cli contact +get-user --user-id ou_xxx --user-id-type open_id --as user`。本环境 2026-06-16 报缺 `contact:user.basic_profile:readonly`;`im chat.members get` 也缺 `im:chat.members:read` 等。缺权限是**正常状态**,别卡在这里——退回方法 1。
## 已知 open_id(核对身份用,新增/纠正后同步到 memory)
- Doro = `ou_757f053c9d7aff6c73b18aa60c337756`(与 bot 私聊 chat=`oc_9292e11bd98ddb5a69ea2c2da10d4f12`)
- Scott(魏玮) = `ou_04fade9a9335c09ad09846da2051b3c0`
## 注意
- `--as bot`:消息以应用 bot 名义发出,bot 必须已在目标群里。
- lark-cli 是 API 工具,不是消息网关;bot 身份不代理用户(Scott 已纠正)。
- 终端里 lark-cli 输出常带 HTTPS_PROXY 的 WARN 和版本更新 notice,是噪音,不影响结果;可 `grep -v "WARN\|proxy"` 过滤。
## 发文件附件到群里(md/pdf/docx 报告,已验证)
要把一份**文件**(错误分析 md、合同 docx、报告 pdf)发到群里,用 `--file`。常见组合:**先发文件附件,再发一条 @某人 的 post 说明**(文件本身不能 @ 人,说明消息负责 @)。
```bash
# 先发文件(--file 接 cwd 相对路径),成功返回 message_id 并打印 "uploading file: xxx"
cd ~/lark_send_tmp && lark-cli im +messages-send \
--chat-id oc_a927f86118216c36cb9394b0e95f2a11 \
--as bot --file "./报告.md" \
--dry-run 2>&1 | grep -v "WARN\|proxy" # 先 dry-run,确认后去掉 --dry-run
# 再发 @某人 的 post 说明(见上「@人的格式」post 模式),把文件背景+要点写清楚
```
### ⚠️ 关键坑:`--file` 只接 cwd 相对路径,绝对路径被拒
lark-cli 安全限制:`--file`(及 `--image`/`--video`/`--audio`)**拒绝绝对路径**(如 `/tmp/x.md`),路径解析 `..`/symlink 后必须仍在 cwd 内。
**解法**:把文件复制到干净工作目录,`cd` 进去用 `./文件名` 发:
```bash
mkdir -p ~/lark_send_tmp && cp "/tmp/报告.md" ~/lark_send_tmp/
cd ~/lark_send_tmp && lark-cli im +messages-send --chat-id oc_xxx --as bot --file "./报告.md"
rm -rf ~/lark_send_tmp # 发完清理
```
- 本地文件 lark-cli 会**先自动上传**再发 file 消息,无需手动 `images.create`/拿 file_key。
- dry-run 时 file_key 显示占位符 `file_dryrun_upload` 是正常的,正式发送才真上传。
- 同理发图片用 `--image ./x.png`,视频 `--video ./x.mp4 --video-cover ./cover.png`。
## 已知群与人 ID(核对身份用)
| 对象 | ID |
|------|-----|
| 飞书工作群"Doro, Maggie, 魏玮"(小Maggie工作群) | `oc_a927f86118216c36cb9394b0e95f2a11` |
| Doro | `ou_757f053c9d7aff6c73b18aa60c337756`(私聊 chat `oc_9292e11bd98ddb5a69ea2c2da10d4f12`,别和群混) |
| Scott / 魏玮 | `ou_04fade9a9335c09ad09846da2051b3c0` |
| @所有人 | `all` |