@tencent-connect/openclaw-qqbot 1.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +393 -0
- package/README.zh.md +390 -0
- package/bin/qqbot-cli.js +243 -0
- package/clawdbot.plugin.json +16 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +22 -0
- package/dist/src/api.d.ts +138 -0
- package/dist/src/api.js +523 -0
- package/dist/src/channel.d.ts +3 -0
- package/dist/src/channel.js +337 -0
- package/dist/src/config.d.ts +25 -0
- package/dist/src/config.js +156 -0
- package/dist/src/gateway.d.ts +18 -0
- package/dist/src/gateway.js +2315 -0
- package/dist/src/image-server.d.ts +62 -0
- package/dist/src/image-server.js +401 -0
- package/dist/src/known-users.d.ts +100 -0
- package/dist/src/known-users.js +263 -0
- package/dist/src/onboarding.d.ts +10 -0
- package/dist/src/onboarding.js +203 -0
- package/dist/src/outbound.d.ts +150 -0
- package/dist/src/outbound.js +1175 -0
- package/dist/src/proactive.d.ts +170 -0
- package/dist/src/proactive.js +399 -0
- package/dist/src/runtime.d.ts +3 -0
- package/dist/src/runtime.js +10 -0
- package/dist/src/session-store.d.ts +52 -0
- package/dist/src/session-store.js +254 -0
- package/dist/src/types.d.ts +145 -0
- package/dist/src/types.js +1 -0
- package/dist/src/utils/audio-convert.d.ts +73 -0
- package/dist/src/utils/audio-convert.js +645 -0
- package/dist/src/utils/file-utils.d.ts +46 -0
- package/dist/src/utils/file-utils.js +107 -0
- package/dist/src/utils/image-size.d.ts +51 -0
- package/dist/src/utils/image-size.js +234 -0
- package/dist/src/utils/media-tags.d.ts +14 -0
- package/dist/src/utils/media-tags.js +120 -0
- package/dist/src/utils/payload.d.ts +112 -0
- package/dist/src/utils/payload.js +186 -0
- package/dist/src/utils/platform.d.ts +126 -0
- package/dist/src/utils/platform.js +358 -0
- package/dist/src/utils/upload-cache.d.ts +34 -0
- package/dist/src/utils/upload-cache.js +93 -0
- package/index.ts +27 -0
- package/moltbot.plugin.json +16 -0
- package/node_modules/@eshaz/web-worker/LICENSE +201 -0
- package/node_modules/@eshaz/web-worker/README.md +134 -0
- package/node_modules/@eshaz/web-worker/browser.js +17 -0
- package/node_modules/@eshaz/web-worker/cjs/browser.js +16 -0
- package/node_modules/@eshaz/web-worker/cjs/node.js +219 -0
- package/node_modules/@eshaz/web-worker/index.d.ts +4 -0
- package/node_modules/@eshaz/web-worker/node.js +223 -0
- package/node_modules/@eshaz/web-worker/package.json +54 -0
- package/node_modules/@wasm-audio-decoders/common/index.js +5 -0
- package/node_modules/@wasm-audio-decoders/common/package.json +36 -0
- package/node_modules/@wasm-audio-decoders/common/src/WASMAudioDecoderCommon.js +231 -0
- package/node_modules/@wasm-audio-decoders/common/src/WASMAudioDecoderWorker.js +129 -0
- package/node_modules/@wasm-audio-decoders/common/src/puff/README +67 -0
- package/node_modules/@wasm-audio-decoders/common/src/puff/build_puff.js +31 -0
- package/node_modules/@wasm-audio-decoders/common/src/puff/puff.c +863 -0
- package/node_modules/@wasm-audio-decoders/common/src/puff/puff.h +35 -0
- package/node_modules/@wasm-audio-decoders/common/src/utilities.js +3 -0
- package/node_modules/@wasm-audio-decoders/common/types.d.ts +7 -0
- package/node_modules/mpg123-decoder/README.md +265 -0
- package/node_modules/mpg123-decoder/dist/mpg123-decoder.min.js +185 -0
- package/node_modules/mpg123-decoder/dist/mpg123-decoder.min.js.map +1 -0
- package/node_modules/mpg123-decoder/index.js +8 -0
- package/node_modules/mpg123-decoder/package.json +58 -0
- package/node_modules/mpg123-decoder/src/EmscriptenWasm.js +464 -0
- package/node_modules/mpg123-decoder/src/MPEGDecoder.js +200 -0
- package/node_modules/mpg123-decoder/src/MPEGDecoderWebWorker.js +21 -0
- package/node_modules/mpg123-decoder/types.d.ts +30 -0
- package/node_modules/silk-wasm/LICENSE +21 -0
- package/node_modules/silk-wasm/README.md +85 -0
- package/node_modules/silk-wasm/lib/index.cjs +16 -0
- package/node_modules/silk-wasm/lib/index.d.ts +70 -0
- package/node_modules/silk-wasm/lib/index.mjs +16 -0
- package/node_modules/silk-wasm/lib/silk.wasm +0 -0
- package/node_modules/silk-wasm/lib/utils.d.ts +4 -0
- package/node_modules/silk-wasm/package.json +39 -0
- package/node_modules/simple-yenc/.github/FUNDING.yml +1 -0
- package/node_modules/simple-yenc/.prettierignore +1 -0
- package/node_modules/simple-yenc/LICENSE +7 -0
- package/node_modules/simple-yenc/README.md +163 -0
- package/node_modules/simple-yenc/dist/esm.js +1 -0
- package/node_modules/simple-yenc/dist/index.js +1 -0
- package/node_modules/simple-yenc/package.json +50 -0
- package/node_modules/simple-yenc/rollup.config.js +27 -0
- package/node_modules/simple-yenc/src/simple-yenc.js +302 -0
- package/node_modules/ws/LICENSE +20 -0
- package/node_modules/ws/README.md +548 -0
- package/node_modules/ws/browser.js +8 -0
- package/node_modules/ws/index.js +13 -0
- package/node_modules/ws/lib/buffer-util.js +131 -0
- package/node_modules/ws/lib/constants.js +19 -0
- package/node_modules/ws/lib/event-target.js +292 -0
- package/node_modules/ws/lib/extension.js +203 -0
- package/node_modules/ws/lib/limiter.js +55 -0
- package/node_modules/ws/lib/permessage-deflate.js +528 -0
- package/node_modules/ws/lib/receiver.js +706 -0
- package/node_modules/ws/lib/sender.js +602 -0
- package/node_modules/ws/lib/stream.js +161 -0
- package/node_modules/ws/lib/subprotocol.js +62 -0
- package/node_modules/ws/lib/validation.js +152 -0
- package/node_modules/ws/lib/websocket-server.js +554 -0
- package/node_modules/ws/lib/websocket.js +1393 -0
- package/node_modules/ws/package.json +69 -0
- package/node_modules/ws/wrapper.mjs +8 -0
- package/openclaw.plugin.json +16 -0
- package/package.json +76 -0
- package/scripts/proactive-api-server.ts +356 -0
- package/scripts/pull-latest.sh +316 -0
- package/scripts/send-proactive.ts +273 -0
- package/scripts/set-markdown.sh +156 -0
- package/scripts/upgrade-and-run.sh +525 -0
- package/scripts/upgrade.sh +127 -0
- package/skills/qqbot-cron/SKILL.md +513 -0
- package/skills/qqbot-media/SKILL.md +194 -0
- package/src/api.ts +704 -0
- package/src/channel.ts +368 -0
- package/src/config.ts +182 -0
- package/src/gateway.ts +2459 -0
- package/src/image-server.ts +474 -0
- package/src/known-users.ts +353 -0
- package/src/onboarding.ts +274 -0
- package/src/openclaw-plugin-sdk.d.ts +483 -0
- package/src/outbound.ts +1301 -0
- package/src/proactive.ts +530 -0
- package/src/runtime.ts +14 -0
- package/src/session-store.ts +303 -0
- package/src/types.ts +153 -0
- package/src/utils/audio-convert.ts +738 -0
- package/src/utils/file-utils.ts +122 -0
- package/src/utils/image-size.ts +266 -0
- package/src/utils/media-tags.ts +134 -0
- package/src/utils/payload.ts +265 -0
- package/src/utils/platform.ts +404 -0
- package/src/utils/upload-cache.ts +128 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# QQBot 插件升级脚本
|
|
3
|
+
# 用于清理旧版本插件并重新安装
|
|
4
|
+
# 兼容 clawdbot 和 openclaw 两种安装
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
echo "=== QQBot 插件升级脚本 ==="
|
|
9
|
+
|
|
10
|
+
# 检测使用的是 clawdbot 还是 openclaw
|
|
11
|
+
detect_installation() {
|
|
12
|
+
if [ -d "$HOME/.clawdbot" ]; then
|
|
13
|
+
echo "clawdbot"
|
|
14
|
+
elif [ -d "$HOME/.openclaw" ]; then
|
|
15
|
+
echo "openclaw"
|
|
16
|
+
else
|
|
17
|
+
echo ""
|
|
18
|
+
fi
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
# 可能的扩展目录名(原仓库 qqbot + 本仓库框架推断名 openclaw-qq)
|
|
22
|
+
EXTENSION_DIRS=("qqbot" "openclaw-qq" "openclaw-qqbot")
|
|
23
|
+
|
|
24
|
+
# 清理指定目录的函数
|
|
25
|
+
cleanup_installation() {
|
|
26
|
+
local APP_NAME="$1"
|
|
27
|
+
local APP_DIR="$HOME/.$APP_NAME"
|
|
28
|
+
local CONFIG_FILE="$APP_DIR/$APP_NAME.json"
|
|
29
|
+
|
|
30
|
+
echo ""
|
|
31
|
+
echo ">>> 处理 $APP_NAME 安装..."
|
|
32
|
+
|
|
33
|
+
# 1. 删除所有可能的旧扩展目录
|
|
34
|
+
for dir_name in "${EXTENSION_DIRS[@]}"; do
|
|
35
|
+
local ext_dir="$APP_DIR/extensions/$dir_name"
|
|
36
|
+
if [ -d "$ext_dir" ]; then
|
|
37
|
+
echo "删除旧版本插件: $ext_dir"
|
|
38
|
+
rm -rf "$ext_dir"
|
|
39
|
+
fi
|
|
40
|
+
done
|
|
41
|
+
|
|
42
|
+
# 2. 清理配置文件中所有可能的插件 ID 相关字段
|
|
43
|
+
if [ -f "$CONFIG_FILE" ]; then
|
|
44
|
+
echo "清理配置文件中的插件字段..."
|
|
45
|
+
|
|
46
|
+
# 使用 node 处理 JSON(比 jq 更可靠处理复杂结构)
|
|
47
|
+
node -e "
|
|
48
|
+
const fs = require('fs');
|
|
49
|
+
const config = JSON.parse(fs.readFileSync('$CONFIG_FILE', 'utf8'));
|
|
50
|
+
const ids = ['qqbot', 'openclaw-qq', '@sliverp/qqbot', '@tencent-connect/qqbot', '@tencent-connect/openclaw-qq', '@tencent-connect/openclaw-qqbot', 'openclaw-qqbot'];
|
|
51
|
+
|
|
52
|
+
for (const id of ids) {
|
|
53
|
+
// 删除 channels.<id>
|
|
54
|
+
if (config.channels && config.channels[id]) {
|
|
55
|
+
delete config.channels[id];
|
|
56
|
+
console.log(' - 已删除 channels.' + id);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 删除 plugins.entries.<id>
|
|
60
|
+
if (config.plugins && config.plugins.entries && config.plugins.entries[id]) {
|
|
61
|
+
delete config.plugins.entries[id];
|
|
62
|
+
console.log(' - 已删除 plugins.entries.' + id);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// 删除 plugins.installs.<id>
|
|
66
|
+
if (config.plugins && config.plugins.installs && config.plugins.installs[id]) {
|
|
67
|
+
delete config.plugins.installs[id];
|
|
68
|
+
console.log(' - 已删除 plugins.installs.' + id);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// 删除 plugins.allow 中的 <id>
|
|
72
|
+
if (config.plugins && Array.isArray(config.plugins.allow)) {
|
|
73
|
+
const before = config.plugins.allow.length;
|
|
74
|
+
config.plugins.allow = config.plugins.allow.filter((x) => x !== id);
|
|
75
|
+
if (config.plugins.allow.length !== before) {
|
|
76
|
+
console.log(' - 已删除 plugins.allow 项: ' + id);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
fs.writeFileSync('$CONFIG_FILE', JSON.stringify(config, null, 2));
|
|
82
|
+
console.log('配置文件已更新');
|
|
83
|
+
"
|
|
84
|
+
else
|
|
85
|
+
echo "未找到配置文件: $CONFIG_FILE"
|
|
86
|
+
fi
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
# 检测并处理所有可能的安装
|
|
90
|
+
FOUND_INSTALLATION=""
|
|
91
|
+
|
|
92
|
+
# 检查 clawdbot
|
|
93
|
+
if [ -d "$HOME/.clawdbot" ]; then
|
|
94
|
+
cleanup_installation "clawdbot"
|
|
95
|
+
FOUND_INSTALLATION="clawdbot"
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
# 检查 openclaw
|
|
99
|
+
if [ -d "$HOME/.openclaw" ]; then
|
|
100
|
+
cleanup_installation "openclaw"
|
|
101
|
+
FOUND_INSTALLATION="openclaw"
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
# 检查 moltbot
|
|
105
|
+
if [ -d "$HOME/.moltbot" ]; then
|
|
106
|
+
cleanup_installation "moltbot"
|
|
107
|
+
FOUND_INSTALLATION="moltbot"
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
# 如果都没找到
|
|
111
|
+
if [ -z "$FOUND_INSTALLATION" ]; then
|
|
112
|
+
echo "未找到 clawdbot / openclaw / moltbot 安装目录"
|
|
113
|
+
echo "请确认已安装其中之一"
|
|
114
|
+
exit 1
|
|
115
|
+
fi
|
|
116
|
+
|
|
117
|
+
# 使用检测到的安装类型作为命令
|
|
118
|
+
CMD="$FOUND_INSTALLATION"
|
|
119
|
+
|
|
120
|
+
echo ""
|
|
121
|
+
echo "=== 清理完成 ==="
|
|
122
|
+
echo ""
|
|
123
|
+
echo "接下来请执行以下命令重新安装插件:"
|
|
124
|
+
echo " cd /path/to/openclaw-qqbot"
|
|
125
|
+
echo " $CMD plugins install ."
|
|
126
|
+
echo " $CMD channels add --channel qqbot --token \"AppID:AppSecret\""
|
|
127
|
+
echo " $CMD gateway restart"
|
|
@@ -0,0 +1,513 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: qqbot-cron
|
|
3
|
+
description: QQBot 定时提醒技能。支持一次性和周期性提醒的创建、查询、取消。当通过 QQ 通道通信且涉及提醒/定时任务时使用此技能。
|
|
4
|
+
metadata: {"openclaw":{"emoji":"⏰","requires":{"config":["channels.qqbot"]}}}
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# QQ Bot 智能提醒
|
|
8
|
+
|
|
9
|
+
让 AI 帮用户设置、管理定时提醒,支持私聊和群聊。
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## ⛔ 最重要的一条规则(读三遍)
|
|
14
|
+
|
|
15
|
+
> **调用 cron 工具时,payload.kind 必须是 `"agentTurn"`。绝对不能用 `"systemEvent"`!**
|
|
16
|
+
>
|
|
17
|
+
> `systemEvent` 只会在 AI 会话里插入一条文本,用户根本收不到 QQ 消息。
|
|
18
|
+
> 只有 `agentTurn` + `deliver: true` + `channel: "qqbot"` + `to` 才能真正把消息发到 QQ。
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 🤖 AI 决策指南
|
|
23
|
+
|
|
24
|
+
### 时间确认规则
|
|
25
|
+
|
|
26
|
+
> 设置提醒前,先确认当前系统时间(查看上下文中的时间信息,或执行 `date`)。
|
|
27
|
+
> 纯相对时间("5分钟后"、"1小时后")可以跳过确认,直接算 `Date.now() + 延迟毫秒`。
|
|
28
|
+
|
|
29
|
+
### 用户意图识别
|
|
30
|
+
|
|
31
|
+
| 用户说法 | 意图 | cron 工具 action |
|
|
32
|
+
|----------|------|------------------|
|
|
33
|
+
| "5分钟后提醒我喝水" | 创建一次性提醒 | `add`(schedule.kind=at) |
|
|
34
|
+
| "每天8点提醒我打卡" | 创建周期提醒 | `add`(schedule.kind=cron) |
|
|
35
|
+
| "我有哪些提醒" | 查询 | `list` |
|
|
36
|
+
| "取消喝水提醒" | 删除 | `remove` |
|
|
37
|
+
| "修改提醒时间" | 删除+重建 | `remove` → `add` |
|
|
38
|
+
| "提醒我" (无时间) | **需追问** | 询问具体时间 |
|
|
39
|
+
|
|
40
|
+
### 必须追问的情况
|
|
41
|
+
|
|
42
|
+
1. **没有时间**:"提醒我喝水" → "请问什么时候提醒你?"
|
|
43
|
+
2. **时间模糊**:"晚点提醒我" → "具体几点呢?"
|
|
44
|
+
3. **周期不明**:"定期提醒我" → "多久一次?每天?每周?"
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 📋 创建提醒(最重要)
|
|
49
|
+
|
|
50
|
+
### 🚨🚨🚨 工具调用参数模板(AI 必须严格遵循)
|
|
51
|
+
|
|
52
|
+
> **AI 调用 cron 工具时,传的是 JSON 参数,不是 CLI 命令。以下是唯一正确的 JSON 格式:**
|
|
53
|
+
|
|
54
|
+
**一次性提醒(N 分钟后)**:
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"action": "add",
|
|
58
|
+
"job": {
|
|
59
|
+
"name": "{任务名}",
|
|
60
|
+
"schedule": {
|
|
61
|
+
"kind": "at",
|
|
62
|
+
"atMs": {当前时间戳毫秒 + N分钟*60000}
|
|
63
|
+
},
|
|
64
|
+
"sessionTarget": "isolated",
|
|
65
|
+
"wakeMode": "now",
|
|
66
|
+
"deleteAfterRun": true,
|
|
67
|
+
"payload": {
|
|
68
|
+
"kind": "agentTurn",
|
|
69
|
+
"message": "你是一个暖心的提醒助手。请用温暖、有趣的方式提醒用户:{提醒内容}。要求:(1) 不要回复HEARTBEAT_OK (2) 不要解释你是谁 (3) 直接输出一条暖心的提醒消息 (4) 可以加一句简短的鸡汤或关怀的话 (5) 控制在2-3句话以内 (6) 用emoji点缀",
|
|
70
|
+
"deliver": true,
|
|
71
|
+
"channel": "qqbot",
|
|
72
|
+
"to": "{openid}"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**周期提醒(每天/每周)**:
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"action": "add",
|
|
82
|
+
"job": {
|
|
83
|
+
"name": "{任务名}",
|
|
84
|
+
"schedule": {
|
|
85
|
+
"kind": "cron",
|
|
86
|
+
"expr": "0 8 * * *",
|
|
87
|
+
"tz": "Asia/Shanghai"
|
|
88
|
+
},
|
|
89
|
+
"sessionTarget": "isolated",
|
|
90
|
+
"wakeMode": "now",
|
|
91
|
+
"payload": {
|
|
92
|
+
"kind": "agentTurn",
|
|
93
|
+
"message": "你是一个暖心的提醒助手。请用温暖、有趣的方式提醒用户:{提醒内容}。要求:(1) 不要回复HEARTBEAT_OK (2) 不要解释你是谁 (3) 直接输出一条暖心的提醒消息 (4) 可以加一句简短的鸡汤或关怀的话 (5) 控制在2-3句话以内 (6) 用emoji点缀",
|
|
94
|
+
"deliver": true,
|
|
95
|
+
"channel": "qqbot",
|
|
96
|
+
"to": "{openid}"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
> 🚨 **绝对不可更改的 5 个字段**(改了提醒就废了):
|
|
103
|
+
> 1. `payload.kind` 必须是 `"agentTurn"` — ❌ 绝对不能用 `"systemEvent"`
|
|
104
|
+
> 2. `payload.deliver` 必须是 `true`
|
|
105
|
+
> 3. `payload.channel` 必须是 `"qqbot"`
|
|
106
|
+
> 4. `payload.to` 必须是用户的 openid
|
|
107
|
+
> 5. `sessionTarget` 必须是 `"isolated"`
|
|
108
|
+
>
|
|
109
|
+
> 🚫 **`payload.kind: "systemEvent"` 只会在 AI 会话中注入文本,不会发送 QQ 消息给用户!**
|
|
110
|
+
>
|
|
111
|
+
> ⚠️ **`schedule.atMs` 必须是绝对毫秒时间戳**(如 `1770733800000`),不支持相对时间字符串如 `"5m"`!
|
|
112
|
+
> 需要自行计算:`当前时间戳 + 延迟毫秒数`。例如 5 分钟后 = `Date.now() + 5 * 60 * 1000`。
|
|
113
|
+
|
|
114
|
+
### 查询提醒
|
|
115
|
+
|
|
116
|
+
使用 cron 工具 `action: "list"` 查询。
|
|
117
|
+
|
|
118
|
+
### 删除提醒
|
|
119
|
+
|
|
120
|
+
使用 cron 工具 `action: "remove"` + `jobId`。
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## 💬 用户交互模板
|
|
125
|
+
|
|
126
|
+
> **创建提醒后的反馈要简洁友好,不要啰嗦**
|
|
127
|
+
|
|
128
|
+
### 创建成功反馈(推荐简洁版)
|
|
129
|
+
|
|
130
|
+
**一次性提醒**:
|
|
131
|
+
```
|
|
132
|
+
⏰ 好的,{时间}后提醒你{提醒内容}~
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**周期提醒**:
|
|
136
|
+
```
|
|
137
|
+
⏰ 收到,{周期描述}提醒你{提醒内容}~
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### 查询提醒反馈
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
📋 你的提醒:
|
|
144
|
+
|
|
145
|
+
1. ⏰ {提醒名} - {时间}
|
|
146
|
+
2. 🔄 {提醒名} - {周期}
|
|
147
|
+
|
|
148
|
+
说"取消xx提醒"可删除~
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### 无提醒时反馈
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
📋 目前没有提醒哦~
|
|
155
|
+
|
|
156
|
+
说"5分钟后提醒我xxx"试试?
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### 删除成功反馈
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
✅ 已取消"{提醒名称}"
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## ⏱️ 时间格式
|
|
168
|
+
|
|
169
|
+
### 一次性提醒(schedule.kind = "at")
|
|
170
|
+
|
|
171
|
+
> ⚠️ `schedule.atMs` 只接受**绝对毫秒时间戳**,需要自己计算!
|
|
172
|
+
|
|
173
|
+
| 用户说法 | 计算方式 |
|
|
174
|
+
|----------|----------|
|
|
175
|
+
| 5分钟后 | `Date.now() + 5 * 60 * 1000` |
|
|
176
|
+
| 半小时后 | `Date.now() + 30 * 60 * 1000` |
|
|
177
|
+
| 1小时后 | `Date.now() + 60 * 60 * 1000` |
|
|
178
|
+
| 明天早上8点 | 先确认当前日期,计算目标时间的毫秒时间戳 |
|
|
179
|
+
|
|
180
|
+
### 周期提醒(schedule.kind = "cron")
|
|
181
|
+
|
|
182
|
+
> 必须加 `"tz": "Asia/Shanghai"`
|
|
183
|
+
|
|
184
|
+
| 用户说法 | schedule.expr |
|
|
185
|
+
|----------|---------------|
|
|
186
|
+
| 每天早上8点 | `"0 8 * * *"` |
|
|
187
|
+
| 每天晚上10点 | `"0 22 * * *"` |
|
|
188
|
+
| 每个工作日早上9点 | `"0 9 * * 1-5"` |
|
|
189
|
+
| 每周一早上9点 | `"0 9 * * 1"` |
|
|
190
|
+
| 每周末上午10点 | `"0 10 * * 0,6"` |
|
|
191
|
+
| 每小时整点 | `"0 * * * *"` |
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## 📌 参数说明
|
|
196
|
+
|
|
197
|
+
### 工具调用 job 对象必填字段
|
|
198
|
+
|
|
199
|
+
| 字段 | 说明 | 示例 |
|
|
200
|
+
|------|------|------|
|
|
201
|
+
| `job.name` | 任务名 | `"喝水提醒"` |
|
|
202
|
+
| `job.schedule.kind` | `"at"` 或 `"cron"` | `"at"` |
|
|
203
|
+
| `job.schedule.atMs` | **绝对毫秒时间戳**(不支持 `"5m"`!) | `1770734100000` |
|
|
204
|
+
| `job.sessionTarget` | 必须 `"isolated"` | `"isolated"` |
|
|
205
|
+
| `job.wakeMode` | 推荐 `"now"` | `"now"` |
|
|
206
|
+
| `job.payload.kind` | 必须 `"agentTurn"`(❌ 不能用 `"systemEvent"`) | `"agentTurn"` |
|
|
207
|
+
| `job.payload.message` | 以 `[直接输出]` 开头 | `"[直接输出] 💧 喝水时间到!"` |
|
|
208
|
+
| `job.payload.deliver` | 必须 `true` | `true` |
|
|
209
|
+
| `job.payload.channel` | 必须 `"qqbot"` | `"qqbot"` |
|
|
210
|
+
| `job.payload.to` | 用户 openid | 从系统消息获取 |
|
|
211
|
+
| `job.deleteAfterRun` | 一次性任务必须 `true` | `true` |
|
|
212
|
+
|
|
213
|
+
### payload.message 暖心提醒模板
|
|
214
|
+
|
|
215
|
+
> 💡 **`payload.message` 是一个 prompt,告诉 AI 以暖心方式生成提醒**。每次触发时 AI 会自由发挥,生成不重复的、有温度的提醒消息。
|
|
216
|
+
|
|
217
|
+
**统一模板**(把 `{提醒内容}` 替换成具体事项):
|
|
218
|
+
```
|
|
219
|
+
你是一个暖心的提醒助手。请用温暖、有趣的方式提醒用户:{提醒内容}。要求:(1) 不要回复HEARTBEAT_OK (2) 不要解释你是谁 (3) 直接输出一条暖心的提醒消息 (4) 可以加一句简短的鸡汤或关怀的话 (5) 控制在2-3句话以内 (6) 用emoji点缀
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**效果举例**(每次触发内容都不同):
|
|
223
|
+
- 喝水提醒 → `💧 嘿,该喝水啦~身体是革命的本钱,水是身体的燃料!`
|
|
224
|
+
- 开会提醒 → `📅 会议时间到~带上你的好想法,闪亮登场吧!`
|
|
225
|
+
- 吃饭提醒 → `🍜 干饭时间到!再忙也要好好吃饭,你值得被善待~`
|
|
226
|
+
- 打卡提醒 → `🌅 新的一天,记得打卡哦~每一天都是新的开始!`
|
|
227
|
+
|
|
228
|
+
**为什么用 prompt 而不是固定文本?**
|
|
229
|
+
- 固定文本太死板,每次都一样,像机器人
|
|
230
|
+
- 用 prompt 让 AI 自由发挥,每次提醒都暖心且不重复
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## 🎯 使用场景示例
|
|
235
|
+
|
|
236
|
+
### 场景1:一次性提醒
|
|
237
|
+
|
|
238
|
+
**用户**: 5分钟后提醒我喝水
|
|
239
|
+
|
|
240
|
+
**AI 调用 cron 工具**(假设当前时间戳为 1770734000000):
|
|
241
|
+
```json
|
|
242
|
+
{
|
|
243
|
+
"action": "add",
|
|
244
|
+
"job": {
|
|
245
|
+
"name": "喝水提醒",
|
|
246
|
+
"schedule": { "kind": "at", "atMs": 1770734300000 },
|
|
247
|
+
"sessionTarget": "isolated",
|
|
248
|
+
"wakeMode": "now",
|
|
249
|
+
"deleteAfterRun": true,
|
|
250
|
+
"payload": {
|
|
251
|
+
"kind": "agentTurn",
|
|
252
|
+
"message": "你是一个暖心的提醒助手。请用温暖、有趣的方式提醒用户:该喝水了。要求:(1) 不要回复HEARTBEAT_OK (2) 不要解释你是谁 (3) 直接输出一条暖心的提醒消息 (4) 可以加一句简短的鸡汤或关怀的话 (5) 控制在2-3句话以内 (6) 用emoji点缀",
|
|
253
|
+
"deliver": true,
|
|
254
|
+
"channel": "qqbot",
|
|
255
|
+
"to": "{openid}"
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
> `atMs` = 当前时间戳 + 5 * 60 * 1000 = 1770734000000 + 300000 = 1770734300000
|
|
261
|
+
|
|
262
|
+
**AI 回复**: `⏰ 好的,5分钟后提醒你喝水~`
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
### 场景2:每日周期提醒
|
|
267
|
+
|
|
268
|
+
**用户**: 每天早上8点提醒我打卡
|
|
269
|
+
|
|
270
|
+
**AI 调用 cron 工具**:
|
|
271
|
+
```json
|
|
272
|
+
{
|
|
273
|
+
"action": "add",
|
|
274
|
+
"job": {
|
|
275
|
+
"name": "打卡提醒",
|
|
276
|
+
"schedule": { "kind": "cron", "expr": "0 8 * * *", "tz": "Asia/Shanghai" },
|
|
277
|
+
"sessionTarget": "isolated",
|
|
278
|
+
"wakeMode": "now",
|
|
279
|
+
"payload": {
|
|
280
|
+
"kind": "agentTurn",
|
|
281
|
+
"message": "[直接输出] 🌅 打卡时间到!",
|
|
282
|
+
"deliver": true,
|
|
283
|
+
"channel": "qqbot",
|
|
284
|
+
"to": "{openid}"
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
> 周期任务**不加** `deleteAfterRun`
|
|
290
|
+
|
|
291
|
+
**AI 回复**: `⏰ 收到,每天早上8点提醒你打卡~`
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
### 场景3:工作日提醒
|
|
296
|
+
|
|
297
|
+
**用户**: 工作日下午6点提醒我写日报
|
|
298
|
+
|
|
299
|
+
**AI 调用 cron 工具**:
|
|
300
|
+
```json
|
|
301
|
+
{
|
|
302
|
+
"action": "add",
|
|
303
|
+
"job": {
|
|
304
|
+
"name": "日报提醒",
|
|
305
|
+
"schedule": { "kind": "cron", "expr": "0 18 * * 1-5", "tz": "Asia/Shanghai" },
|
|
306
|
+
"sessionTarget": "isolated",
|
|
307
|
+
"wakeMode": "now",
|
|
308
|
+
"payload": {
|
|
309
|
+
"kind": "agentTurn",
|
|
310
|
+
"message": "你是一个暖心的提醒助手。请用温暖、有趣的方式提醒用户:该写日报了。要求:(1) 不要回复HEARTBEAT_OK (2) 不要解释你是谁 (3) 直接输出一条暖心的提醒消息 (4) 可以加一句简短的鸡汤或关怀的话 (5) 控制在2-3句话以内 (6) 用emoji点缀",
|
|
311
|
+
"deliver": true,
|
|
312
|
+
"channel": "qqbot",
|
|
313
|
+
"to": "{openid}"
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
**AI 回复**: `⏰ 收到,工作日下午6点提醒你写日报~`
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
### 场景4:会议提醒
|
|
324
|
+
|
|
325
|
+
**用户**: 3分钟后提醒我开会
|
|
326
|
+
|
|
327
|
+
**AI 调用 cron 工具**(假设当前时间戳为 1770734000000):
|
|
328
|
+
```json
|
|
329
|
+
{
|
|
330
|
+
"action": "add",
|
|
331
|
+
"job": {
|
|
332
|
+
"name": "开会提醒",
|
|
333
|
+
"schedule": { "kind": "at", "atMs": 1770734180000 },
|
|
334
|
+
"sessionTarget": "isolated",
|
|
335
|
+
"wakeMode": "now",
|
|
336
|
+
"deleteAfterRun": true,
|
|
337
|
+
"payload": {
|
|
338
|
+
"kind": "agentTurn",
|
|
339
|
+
"message": "[直接输出] 📅 开会时间到!",
|
|
340
|
+
"deliver": true,
|
|
341
|
+
"channel": "qqbot",
|
|
342
|
+
"to": "{openid}"
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
> `atMs` = 当前时间戳 + 3 * 60 * 1000
|
|
348
|
+
|
|
349
|
+
**AI 回复**: `⏰ 好的,3分钟后提醒你开会~`
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
### 场景5:群组提醒
|
|
354
|
+
|
|
355
|
+
**用户**(群聊): 每天早上9点提醒大家站会
|
|
356
|
+
|
|
357
|
+
**AI 调用 cron 工具**:
|
|
358
|
+
```json
|
|
359
|
+
{
|
|
360
|
+
"action": "add",
|
|
361
|
+
"job": {
|
|
362
|
+
"name": "站会提醒",
|
|
363
|
+
"schedule": { "kind": "cron", "expr": "0 9 * * 1-5", "tz": "Asia/Shanghai" },
|
|
364
|
+
"sessionTarget": "isolated",
|
|
365
|
+
"wakeMode": "now",
|
|
366
|
+
"payload": {
|
|
367
|
+
"kind": "agentTurn",
|
|
368
|
+
"message": "你是一个暖心的提醒助手。请用温暖、有趣的方式提醒用户:站会时间到了。要求:(1) 不要回复HEARTBEAT_OK (2) 不要解释你是谁 (3) 直接输出一条暖心的提醒消息 (4) 可以加一句简短的鸡汤或关怀的话 (5) 控制在2-3句话以内 (6) 用emoji点缀",
|
|
369
|
+
"deliver": true,
|
|
370
|
+
"channel": "qqbot",
|
|
371
|
+
"to": "group:{group_openid}"
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
```
|
|
376
|
+
> 群组使用 `"group:{group_openid}"` 格式
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
### 场景6:查询提醒
|
|
381
|
+
|
|
382
|
+
**用户**: 我有哪些提醒?
|
|
383
|
+
|
|
384
|
+
**AI 调用 cron 工具**:`{ "action": "list" }`
|
|
385
|
+
|
|
386
|
+
**AI 回复**(根据返回结果):
|
|
387
|
+
```
|
|
388
|
+
📋 你的提醒:
|
|
389
|
+
|
|
390
|
+
1. ⏰ 喝水提醒 - 3分钟后
|
|
391
|
+
2. 🔄 打卡提醒 - 每天08:00
|
|
392
|
+
|
|
393
|
+
说"取消xx提醒"可删除~
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
### 场景7:取消提醒
|
|
399
|
+
|
|
400
|
+
**用户**: 取消打卡提醒
|
|
401
|
+
|
|
402
|
+
**AI 执行**:
|
|
403
|
+
1. 先用 `{ "action": "list" }` 找到对应任务 ID
|
|
404
|
+
2. 再用 `{ "action": "remove", "jobId": "{id}" }` 删除
|
|
405
|
+
|
|
406
|
+
**AI 回复**:
|
|
407
|
+
```
|
|
408
|
+
✅ 已取消"打卡提醒"
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
## ⚙️ 消息发送说明
|
|
414
|
+
|
|
415
|
+
### 定时提醒(cron add)
|
|
416
|
+
|
|
417
|
+
定时提醒**只能发送主动消息**,因为:
|
|
418
|
+
- 提醒执行时,原始 message_id 通常已超过 1 小时有效期
|
|
419
|
+
|
|
420
|
+
```
|
|
421
|
+
┌─────────────────────┐
|
|
422
|
+
│ 定时任务触发 │
|
|
423
|
+
└──────────┬──────────┘
|
|
424
|
+
↓
|
|
425
|
+
┌─────────────────────┐
|
|
426
|
+
│ AI 通过 agentTurn │
|
|
427
|
+
│ 在隔离会话中执行 │
|
|
428
|
+
└──────────┬──────────┘
|
|
429
|
+
↓
|
|
430
|
+
┌─────────────────────┐
|
|
431
|
+
│ deliver=true 投递 │
|
|
432
|
+
│ channel="qqbot" │
|
|
433
|
+
│ to="{openid}" │
|
|
434
|
+
└──────────┬──────────┘
|
|
435
|
+
↓
|
|
436
|
+
✅ 用户收到提醒
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
### 即时回复
|
|
440
|
+
|
|
441
|
+
即时消息发送支持被动回复(如果 message_id 有效):
|
|
442
|
+
|
|
443
|
+
```
|
|
444
|
+
┌─────────────────────┐
|
|
445
|
+
│ 发送即时消息 │
|
|
446
|
+
└──────────┬──────────┘
|
|
447
|
+
↓
|
|
448
|
+
┌──────────────────────────────┐
|
|
449
|
+
│ message_id 在 1 小时内有效? │
|
|
450
|
+
└──────────────────────────────┘
|
|
451
|
+
↓ ↓
|
|
452
|
+
是 否
|
|
453
|
+
↓ ↓
|
|
454
|
+
┌───────────────┐ ┌─────────────────┐
|
|
455
|
+
│ 被动消息回复 │ │ 发送主动消息 │
|
|
456
|
+
│ (引用原消息) │ │ (直接发送) │
|
|
457
|
+
└───────────────┘ └─────────────────┘
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
---
|
|
461
|
+
|
|
462
|
+
## ⚠️ 重要限制
|
|
463
|
+
|
|
464
|
+
| 限制 | 说明 |
|
|
465
|
+
|------|------|
|
|
466
|
+
| **message_id 有效期** | 1 小时内有效,超时自动降级 |
|
|
467
|
+
| **回复次数限制** | 同一 message_id 最多回复 4 次 |
|
|
468
|
+
| **主动消息权限** | ⚠️ **QQ 机器人需要申请主动消息权限**,否则定时提醒会发送失败 |
|
|
469
|
+
| **主动消息限制** | 只能发给与机器人交互过的用户(24小时内) |
|
|
470
|
+
| **消息内容** | `payload.message` 不能为空 |
|
|
471
|
+
|
|
472
|
+
### ⚠️ 主动消息权限说明
|
|
473
|
+
|
|
474
|
+
定时提醒功能依赖**主动消息能力**,但 QQ 官方默认**不授予**此权限。
|
|
475
|
+
|
|
476
|
+
**常见错误**:
|
|
477
|
+
- 错误码 `40034102`:"主动消息失败, 无权限"
|
|
478
|
+
- 这表示机器人没有主动消息权限
|
|
479
|
+
|
|
480
|
+
**解决方案**:
|
|
481
|
+
1. 登录 [QQ 开放平台](https://q.qq.com/)
|
|
482
|
+
2. 进入机器人开发-沙箱管理,消息列表配置中添加自己。
|
|
483
|
+
|
|
484
|
+
> 💡 **临时替代方案**:在没有主动消息权限前,可以让用户使用"回复"方式获得即时提醒,而非定时提醒。
|
|
485
|
+
|
|
486
|
+
---
|
|
487
|
+
|
|
488
|
+
## 📝 消息模板
|
|
489
|
+
|
|
490
|
+
| 场景 | 触发时输出 | Emoji |
|
|
491
|
+
|------|------------|-------|
|
|
492
|
+
| 喝水 | 喝水时间到啦! | 💧 🚰 |
|
|
493
|
+
| 打卡 | 早上好,打卡时间到! | 🌅 ✅ |
|
|
494
|
+
| 会议 | 开会时间到! | 📅 👥 |
|
|
495
|
+
| 休息 | 该休息一下了~ | 😴 💤 |
|
|
496
|
+
| 日报 | 下班前别忘了写日报哦~ | 📝 ✍️ |
|
|
497
|
+
| 运动 | 运动时间到! | 🏃 💪 |
|
|
498
|
+
| 吃药 | 该吃药了~ | 💊 🏥 |
|
|
499
|
+
| 生日 | 今天是xx的生日! | 🎂 🎉 |
|
|
500
|
+
|
|
501
|
+
---
|
|
502
|
+
|
|
503
|
+
## 🔧 用户标识
|
|
504
|
+
|
|
505
|
+
| 类型 | 格式 | 来源 |
|
|
506
|
+
|------|------|------|
|
|
507
|
+
| 用户 openid | `B3EA9A1d-2D3c-5CBD-...` | 系统消息自动提供 |
|
|
508
|
+
| 群组 openid | `group:FeC1ADaf-...` | 系统消息自动提供 |
|
|
509
|
+
| message_id | `ROBOT1.0_xxx` | 系统消息自动提供 |
|
|
510
|
+
|
|
511
|
+
> 💡 这些信息在系统消息中格式如:
|
|
512
|
+
> - `当前用户 openid: B3EA9A1d-...`
|
|
513
|
+
> - `当前消息 message_id: ROBOT1.0_...`
|