contacts: extract into standalone skill, add himalaya wrapper for all email sends

Refactors the contacts system from being embedded in cal_tool.py into a
standalone contacts skill that serves as the single source of truth for
recipient validation across all outbound email paths.

- New skills/contacts/ skill: list, add, delete, resolve commands
- New skills/himalaya/scripts/himalaya.sh wrapper: validates To/Cc/Bcc
  recipients against contacts for message send, template send, and
  message write commands; passes everything else through unchanged
- cal_tool.py now delegates to contacts.py resolve instead of inline logic
- TOOLS.md updated: agent should use himalaya wrapper, not raw himalaya
This commit is contained in:
Yanxin Lu
2026-03-31 11:12:08 -07:00
parent cd1ee050ed
commit f05a84d8ca
10 changed files with 703 additions and 314 deletions

View File

@@ -28,21 +28,44 @@ Skills define _how_ tools work. This file is for _your_ specifics — the stuff
**本地配置:**
- 二进制:`~/.local/bin/himalaya`
- **安全包装器**`~/.openclaw/workspace/skills/himalaya/scripts/himalaya.sh`(验证收件人)
- 配置:`~/.config/himalaya/config.toml`
- 文档:`~/.openclaw/workspace/skills/himalaya/SKILL.md`
**核心用法:**
**重要:发送邮件时必须使用包装器,不要直接调用 himalaya**
```bash
himalaya envelope list --page-size 20 # 列出邮件
himalaya message read <id> # 读取邮件
himalaya message delete <id> # 删除邮件
himalaya message write # 写新邮件(交互式
HIMALAYA=~/.openclaw/workspace/skills/himalaya/scripts/himalaya.sh
$HIMALAYA envelope list --page-size 20 # 列出邮件(直接透传)
$HIMALAYA message read <id> # 读取邮件(直接透传
$HIMALAYA message delete <id> # 删除邮件(直接透传)
cat msg.txt | $HIMALAYA template send # 发送邮件(校验收件人)
```
**邮件发送规则:**
- **所有发送命令通过包装器**,自动校验收件人在通讯录中
- **youlu@luyanxin.com → mail@luyx.org**: 直接发送,无需确认(用户 SimpleLogin 别名)
- 其他所有对外邮件: 仍需确认
### 通讯录contacts
**目录**: `~/.openclaw/workspace/skills/contacts/`
**数据**: `~/.openclaw/workspace/contacts/default/`vCard .vcf 文件CardDAV 同步)
```bash
CONTACTS=~/.openclaw/workspace/skills/contacts/scripts/contacts.sh
$CONTACTS list # 列出所有联系人
$CONTACTS add --name "小橘子" --email "x@y.com" --type work # 添加联系人
$CONTACTS delete --name "小橘子" # 删除联系人
$CONTACTS resolve "小橘子:work" # 解析为邮箱地址
```
**安全规则**:
- **添加联系人和发送邮件是独立操作**,不要在同一次请求中先 add 再 send
- 所有邮件发送himalaya 和日历邀请)都会校验收件人在通讯录中
### 🌐 网页操作 - 工具选择决策表
| 场景 | 首选 | 次选 |
@@ -105,19 +128,13 @@ agent-browser close
**目录**: `~/.openclaw/workspace/skills/calendar/`
**默认发件人**: youlu@luyanxin.com
**默认时区**: America/Los_Angeles
**日历数据**: `~/.openclaw/workspace/calendars/home/`(事件)、`calendars/tasks/`(待办)`contacts/default/`(通讯录)
**日历数据**: `~/.openclaw/workspace/calendars/home/`(事件)、`calendars/tasks/`(待办)
**运行方式**: `uv run`(依赖 `icalendar` 库)
**核心用法**:
```bash
SKILL_DIR=~/.openclaw/workspace/skills/calendar
# 通讯录管理send 命令会校验收件人必须在通讯录中)
$SKILL_DIR/scripts/calendar.sh contact list
$SKILL_DIR/scripts/calendar.sh contact add --name "小橘子" --email "Erica.Jiang@anderson.ucla.edu" --type work
$SKILL_DIR/scripts/calendar.sh contact add --name "小橘子" --email "xueweijiang0313@gmail.com" --type home
$SKILL_DIR/scripts/calendar.sh contact delete --name "小橘子"
# 发送日历邀请(--to 用通讯录名称,不要直接写邮箱地址)
$SKILL_DIR/scripts/calendar.sh send \
--to "小橘子:work" \
@@ -154,7 +171,7 @@ $SKILL_DIR/scripts/calendar.sh todo delete --match "报销"
$SKILL_DIR/scripts/calendar.sh todo check # 每日摘要cron
```
**支持操作**: 通讯录 (`contact list/add/delete`)、发送邀请 (`send`)、接受/拒绝/暂定 (`reply`)、事件管理 (`event list/delete --date/--all`)、待办管理 (`todo add/list/edit/complete/delete/check`)
**支持操作**: 发送邀请 (`send`)、接受/拒绝/暂定 (`reply`)、事件管理 (`event list/delete --date/--all`)、待办管理 (`todo add/list/edit/complete/delete/check`)
**依赖**: himalaya邮件、vdirsyncerCalDAV 同步、khal查看日历、todoman待办管理
**同步**: 发送/回复/待办变更后自动 `vdirsyncer sync`,心跳也会定期同步
**注意**: 发送日历邀请属于对外邮件,需先确认