Files
qqbot/skills/qqbot-cron/SKILL.md
rianli a3e87f2f37 feat(qqbot): 定时提醒技能与主动消息系统
**新增提醒技能**
- 新增 skills/qqbot-cron/SKILL.md 定时提醒技能定义
- 支持一次性提醒(--at)和周期性提醒(--cron)
- 支持设置、查询、取消提醒操作

**主动消息系统**
- 新增 src/proactive.ts 主动消息发送模块
- 新增 src/known-users.ts 已知用户管理
- 新增 src/session-store.ts 会话存储
- 支持主动向用户/群组发送消息

**工具脚本**
- 新增 scripts/proactive-api-server.ts 主动消息API服务
2026-02-02 20:31:14 +08:00

476 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: qqbot-cron
description: QQ Bot 智能提醒技能。支持一次性提醒、周期性任务、自动降级确保送达。可设置、查询、取消提醒。
metadata: {"clawdbot":{"emoji":"⏰","requires":{"channels":["qqbot"]}}}
---
# QQ Bot 智能提醒
让 AI 帮用户设置、管理定时提醒,支持私聊和群聊。
---
## 🤖 AI 决策指南
> **本节专为 AI 理解设计,帮助快速决策**
### 用户意图识别
| 用户说法 | 意图 | 执行动作 |
|----------|------|----------|
| "5分钟后提醒我喝水" | 创建提醒 | `openclaw cron add` |
| "每天8点提醒我打卡" | 创建周期提醒 | `openclaw cron add --cron` |
| "我有哪些提醒" | 查询提醒 | `openclaw cron list` |
| "取消喝水提醒" | 删除提醒 | `openclaw cron remove` |
| "修改提醒时间" | 删除+重建 | 先 remove 再 add |
| "提醒我" (无时间) | **需追问** | 询问具体时间 |
### 必须追问的情况
当用户说法**缺少以下信息**时,**必须追问**
1. **没有时间**"提醒我喝水" → 询问"请问什么时候提醒你?"
2. **时间模糊**"晚点提醒我" → 询问"具体几点呢?"
3. **周期不明**"定期提醒我" → 询问"多久一次?每天?每周?"
### 无需追问可直接执行
| 用户说法 | 理解为 |
|----------|--------|
| "5分钟后" | `--at 5m` |
| "半小时后" | `--at 30m` |
| "1小时后" | `--at 1h` |
| "明天早上8点" | `--at 2026-02-02T08:00:00+08:00` |
| "每天早上8点" | `--cron "0 8 * * *"` |
| "工作日9点" | `--cron "0 9 * * 1-5"` |
---
## 📋 命令速查
### 创建提醒(完整模板)
```bash
openclaw cron add \
--name "{任务名}" \
--at "{时间}" \
--session isolated \
--system-event '{"type":"reminder","user_openid":"{openid}","user_name":"{用户名称}","original_message_id":"{message_id}","reminder_content":"{提醒内容}","created_at":"{当前时间ISO格式}"}' \
--message "{消息内容}" \
--deliver \
--channel qqbot \
--to "{openid}" \
--delete-after-run
```
> 💡 **`--system-event` 说明**:用于存储用户上下文信息,提醒触发时 AI 可以获取这些信息来提供更个性化的提醒。
> ⚠️ **注意**`cron add` 命令不支持 `--reply-to` 参数。提醒消息将作为主动消息直接发送给用户。
### 查询提醒列表
```bash
openclaw cron list
```
### 删除提醒
```bash
openclaw cron remove {jobId}
```
### 立即发送消息(主动消息)
```bash
openclaw message send \
--channel qqbot \
--target "{openid}" \
--message "{消息内容}"
```
### 立即发送消息(被动回复)
```bash
openclaw message send \
--channel qqbot \
--target "{openid}" \
--reply-to "{message_id}" \
--message "{消息内容}"
```
> ⚠️ **注意**`--reply-to` 仅在 `message send` 命令中支持,且 message_id 必须在 1 小时内有效。定时提醒不支持被动回复。
---
## 💬 用户交互模板
> **创建提醒后,必须给用户反馈确认**
### 创建成功反馈
**一次性提醒**
```
✅ 提醒已设置!
📝 内容:{提醒内容}
⏰ 时间:{具体时间}
到时候我会准时提醒你~
```
**周期提醒**
```
✅ 周期提醒已设置!
📝 内容:{提醒内容}
🔄 周期:{周期描述,如"每天早上8:00"}
提醒会持续生效,说"取消xx提醒"可停止~
```
### 查询提醒反馈
```
📋 你当前的提醒:
1. ⏰ 喝水提醒 - 5分钟后 (一次性)
2. 🔄 打卡提醒 - 每天08:00 (周期)
3. 🔄 日报提醒 - 工作日18:00 (周期)
说"取消xx提醒"可删除~
```
### 无提醒时反馈
```
📋 你当前没有设置任何提醒
说"5分钟后提醒我xxx"可创建提醒~
```
### 删除成功反馈
```
✅ 已取消"{提醒名称}"提醒
```
---
## ⏱️ 时间格式
### 相对时间(--at
> ⚠️ **不要加 + 号!** 用 `5m` 而不是 `+5m`
| 用户说法 | 参数值 |
|----------|--------|
| 5分钟后 | `5m` |
| 半小时后 | `30m` |
| 1小时后 | `1h` |
| 2小时后 | `2h` |
| 明天这时候 | `24h` |
### 绝对时间(--at
| 用户说法 | 参数值 |
|----------|--------|
| 今天下午3点 | `2026-02-01T15:00:00+08:00` |
| 明天早上8点 | `2026-02-02T08:00:00+08:00` |
| 2月14日中午 | `2026-02-14T12:00:00+08:00` |
### Cron 表达式(--cron
| 用户说法 | Cron 表达式 | 必须加 `--tz "Asia/Shanghai"` |
|----------|-------------|------------------------------|
| 每天早上8点 | `0 8 * * *` | ✅ |
| 每天晚上10点 | `0 22 * * *` | ✅ |
| 每个工作日早上9点 | `0 9 * * 1-5` | ✅ |
| 每周一早上9点 | `0 9 * * 1` | ✅ |
| 每周末上午10点 | `0 10 * * 0,6` | ✅ |
| 每小时整点 | `0 * * * *` | ✅ |
---
## 📌 参数说明
### 必填参数
| 参数 | 说明 | 示例 |
|------|------|------|
| `--name` | 任务名,含用户标识 | `"喝水提醒-小明"` |
| `--at` / `--cron` | 触发时间(二选一) | `5m` / `0 8 * * *` |
| `--session isolated` | 隔离会话 | 固定值 |
| `--message` | 消息内容,**不能为空** | `"💧 该喝水啦!"` |
| `--deliver` | 启用投递 | 固定值 |
| `--channel qqbot` | QQ 渠道 | 固定值 |
| `--to` | 接收者 openid | 从系统消息获取 |
### 推荐参数(用于存储用户上下文)
| 参数 | 说明 | 何时使用 |
|------|------|----------|
| `--system-event` | 用户上下文 JSON | **建议所有任务都使用** |
| `--delete-after-run` | 执行后删除 | **一次性任务必须** |
| `--tz "Asia/Shanghai"` | 时区 | **周期任务必须** |
### --system-event 字段说明
`--system-event` 用于存储提醒的上下文信息,格式为 JSON
```json
{
"type": "reminder",
"user_openid": "用户的openid",
"user_name": "用户名称(如有)",
"original_message_id": "创建提醒时的message_id",
"reminder_content": "提醒内容摘要",
"created_at": "创建时间ISO格式"
}
```
| 字段 | 说明 | 来源 |
|------|------|------|
| `type` | 事件类型,固定为 `"reminder"` | 固定值 |
| `user_openid` | 用户 openid | 从系统消息获取 |
| `user_name` | 用户名称 | 从系统消息获取(如有) |
| `original_message_id` | 创建时的消息 ID | 从系统消息获取 |
| `reminder_content` | 提醒内容摘要 | AI 根据用户请求生成 |
| `created_at` | 提醒创建时间 | 当前时间 ISO 格式 |
> 💡 **为什么需要 `--system-event`**
> - 提醒触发时AI 可以获取完整的用户上下文
> - 便于追踪提醒来源和调试
> - 为未来可能的功能扩展预留信息
---
## 🎯 使用场景示例
### 场景1一次性提醒
**用户**: 5分钟后提醒我喝水
**AI 执行**:
```bash
openclaw cron add \
--name "喝水提醒-用户" \
--at "5m" \
--session isolated \
--system-event '{"type":"reminder","user_openid":"{openid}","original_message_id":"{message_id}","reminder_content":"喝水","created_at":"2026-02-01T16:50:00+08:00"}' \
--message "💧 该喝水啦这是你5分钟前设置的提醒~" \
--deliver \
--channel qqbot \
--to "{openid}" \
--delete-after-run
```
**AI 回复**:
```
✅ 提醒已设置!
📝 内容:喝水
⏰ 时间5分钟后
到时候我会准时提醒你~
```
---
### 场景2每日周期提醒
**用户**: 每天早上8点提醒我打卡
**AI 执行**:
```bash
openclaw cron add \
--name "打卡提醒-用户" \
--cron "0 8 * * *" \
--tz "Asia/Shanghai" \
--session isolated \
--system-event '{"type":"reminder","user_openid":"{openid}","original_message_id":"{message_id}","reminder_content":"打卡","created_at":"2026-02-01T16:50:00+08:00"}' \
--message "🌅 早上好!记得打卡签到~" \
--deliver \
--channel qqbot \
--to "{openid}"
```
**AI 回复**:
```
✅ 周期提醒已设置!
📝 内容:打卡
🔄 周期:每天早上 8:00
提醒会持续生效,说"取消打卡提醒"可停止~
```
> 💡 周期任务**不加** `--delete-after-run`
---
### 场景3工作日提醒
**用户**: 工作日下午6点提醒我写日报
**AI 执行**:
```bash
openclaw cron add \
--name "日报提醒-用户" \
--cron "0 18 * * 1-5" \
--tz "Asia/Shanghai" \
--session isolated \
--system-event '{"type":"reminder","user_openid":"{openid}","original_message_id":"{message_id}","reminder_content":"写日报","created_at":"2026-02-01T16:50:00+08:00"}' \
--message "📝 今天的日报别忘了提交!" \
--deliver \
--channel qqbot \
--to "{openid}"
```
---
### 场景4群组提醒
**用户**(群聊): 每天早上9点提醒大家站会
**AI 执行**:
```bash
openclaw cron add \
--name "站会提醒-群" \
--cron "0 9 * * 1-5" \
--tz "Asia/Shanghai" \
--session isolated \
--system-event '{"type":"reminder","user_openid":"group:{group_openid}","original_message_id":"{message_id}","reminder_content":"站会","created_at":"2026-02-01T16:50:00+08:00"}' \
--message "📢 各位同事9点站会时间到请准时参加~" \
--deliver \
--channel qqbot \
--to "group:{group_openid}"
```
> 💡 群组使用 `group:{group_openid}` 格式
---
### 场景5查询提醒
**用户**: 我有哪些提醒?
**AI 执行**:
```bash
openclaw cron list
```
**AI 回复**(根据返回结果组织):
```
📋 你当前的提醒:
1. ⏰ 喝水提醒 - 3分钟后 (一次性)
2. 🔄 打卡提醒 - 每天08:00 (周期)
说"取消xx提醒"可删除~
```
---
### 场景6取消提醒
**用户**: 取消打卡提醒
**AI 执行**:
1. 先执行 `openclaw cron list` 找到对应任务 ID
2. 执行 `openclaw cron remove {jobId}`
**AI 回复**:
```
✅ 已取消"打卡提醒"
```
---
## ⚙️ 消息发送说明
### 定时提醒cron add
定时提醒**只能发送主动消息**,因为:
- 提醒执行时,原始 message_id 通常已超过 1 小时有效期
- `openclaw cron add` 命令不支持 `--reply-to` 参数
```
┌─────────────────────┐
│ 定时任务触发 │
└──────────┬──────────┘
┌─────────────────────┐
│ AI 通过 system-event │
│ 获取用户上下文信息 │
└──────────┬──────────┘
┌─────────────────────┐
│ 发送主动消息到用户 │
│ --channel qqbot │
│ --to {openid} │
└──────────┬──────────┘
✅ 用户收到提醒
```
### 即时回复message send
即时消息发送支持被动回复(如果 message_id 有效):
```
┌─────────────────────┐
│ 发送即时消息 │
└──────────┬──────────┘
┌──────────────────────────────┐
│ 有 --reply-to 且 message_id │
│ 在 1 小时内有效? │
└──────────────────────────────┘
↓ ↓
是 否
↓ ↓
┌───────────────┐ ┌─────────────────┐
│ 被动消息回复 │ │ 发送主动消息 │
│ (引用原消息) │ │ (直接发送) │
└───────────────┘ └─────────────────┘
```
---
## ⚠️ 重要限制
| 限制 | 说明 |
|------|------|
| **message_id 有效期** | 1 小时内有效,超时自动降级 |
| **回复次数限制** | 同一 message_id 最多回复 4 次 |
| **主动消息限制** | 只能发给与机器人交互过的用户 |
| **消息内容** | `--message` 不能为空 |
---
## 📝 消息模板
| 场景 | 模板 | Emoji |
|------|------|-------|
| 喝水 | 该喝水啦! | 💧 🚰 |
| 打卡 | 早上好!记得打卡~ | 🌅 ✅ |
| 会议 | xx会议马上开始 | 📅 👥 |
| 休息 | 该休息一下了~ | 😴 💤 |
| 日报 | 今日日报别忘了~ | 📝 ✍️ |
| 运动 | 该运动了! | 🏃 💪 |
| 吃药 | 记得按时吃药~ | 💊 🏥 |
| 生日 | 今天是xx的生日 | 🎂 🎉 |
---
## 🔧 用户标识
| 类型 | 格式 | 来源 |
|------|------|------|
| 用户 openid | `B3EA9A1d-2D3c-5CBD-...` | 系统消息自动提供 |
| 群组 openid | `group:FeC1ADaf-...` | 系统消息自动提供 |
| message_id | `ROBOT1.0_xxx` | 系统消息自动提供 |
> 💡 这些信息在系统消息中格式如:
> - `当前用户 openid: B3EA9A1d-...`
> - `当前消息 message_id: ROBOT1.0_...`