- 106 动画 + 2366 表情包 + 语义标签 - 三层记忆 / 心情系统 / 9 可配置插件 / 10 技能 - DeepSeek 对话直连 + MCP/HTTP 接入 + 接入文档 - 动画随机链 + 物理引擎 + 贴边碰撞校准 - 大资源(动画webp/表情图)由 scripts/ 再生成,不入库
13 KiB
桌宠推送接入文档(workbuddy / DeepSeek 等)
桌宠在设备本机开了一个 HTTP 服务,任何 App 只要拿到授权码就能向它推送任务通知。
- 地址:
http://127.0.0.1:7350 - 授权码:在桌宠面板「接入 → 推送授权」里查看/复制/生成(可多个、可单独吊销)
- 鉴权:写请求必须带
X-Pet-Token: <码>(也支持?token=<码>) - 只读接口
GET /api/state、GET /api/health无需授权
调用方 App 需允许明文 HTTP:
android:usesCleartextTraffic="true", 或 network-security-config 放行127.0.0.1。
接口一览
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/health |
应用信息、动画数、authRequired、端点清单 |
| GET | /api/state |
当前动画、气泡、朝向 |
| POST | /api/task |
任务状态通知(推荐) |
| POST | /api/notify |
通用通知(按 level 或 state) |
| POST | /api/anim |
点播任意动画(中文名) |
| POST | /api/broadcast |
只说一句话,不改动画 |
| POST | /api/clear |
清空气泡 |
POST /api/task
{ "state": "working", "text": "正在生成周报…", "durationMs": 8000, "meme": "m09" }
state → 动画映射:
| state | 动画 |
|---|---|
start / thinking |
工作状态-思考冒泡 |
working |
工作状态-忙碌点按 |
result |
工作状态-清点归档 |
waiting |
工作状态-原地踱步张望 |
done / success |
工作状态-雀跃庆祝 |
error / failed |
工作状态-垂头叹气冒汗 |
POST /api/notify
{ "level": "error", "text": "构建失败", "durationMs": 10000, "meme": "m24" }
level 可选:info result working waiting success error。
durationMs 期间宠物会保持这个动作,随机动画链不会覆盖。
meme 可选,取值 m01~m27(气泡里的表情包,见面板动作页预览)。
调用示例
curl
TOKEN=2caa9cb98fea488e
curl -X POST http://127.0.0.1:7350/api/task \
-H 'Content-Type: application/json' \
-H "X-Pet-Token: $TOKEN" \
-d '{"state":"working","text":"正在生成周报…"}'
Kotlin(无第三方依赖)
import org.json.JSONObject
import java.net.HttpURLConnection
import java.net.URL
fun pushToPet(token: String, state: String, text: String, durationMs: Long = 8000) {
Thread {
runCatching {
val conn = (URL("http://127.0.0.1:7350/api/task").openConnection() as HttpURLConnection)
conn.requestMethod = "POST"
conn.doOutput = true
conn.connectTimeout = 2000
conn.readTimeout = 2000
conn.setRequestProperty("Content-Type", "application/json")
conn.setRequestProperty("X-Pet-Token", token)
val body = JSONObject()
.put("state", state)
.put("text", text)
.put("durationMs", durationMs)
.toString()
conn.outputStream.use { it.write(body.toByteArray()) }
conn.responseCode // 200 = 成功,401 = 授权码不对
conn.disconnect()
}
}.start()
}
// 用法
pushToPet(token = "2caa9cb98fea488e", state = "working", text = "正在整理对话…")
pushToPet(token = "2caa9cb98fea488e", state = "done", text = "整理完成 ✅")
pushToPet(token = "2caa9cb98fea488e", state = "error", text = "请求失败:超时")
JavaScript / Node(workbuddy 若是前端/Node)
async function pushToPet(token, state, text, durationMs = 8000) {
const res = await fetch('http://127.0.0.1:7350/api/task', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-Pet-Token': token },
body: JSON.stringify({ state, text, durationMs })
});
if (!res.ok) console.warn('pet push failed', res.status, await res.text());
}
排错
| 现象 | 原因 |
|---|---|
401 unauthorized |
授权码不对 / 该应用被删除 / 面板里授权已关闭 |
| 连接被拒绝 | 桌宠没在运行(服务随宠物存活) |
404 not-found |
路径写错(注意是 /api/task 不是 /task) |
| 调用成功但没反应 | 宠物面板「外观 → 距离/透明度」设得太小看不见;或气泡已超时消失 |
cleartext not permitted |
调用方 App 没开明文 HTTP |
行为约定
- 通知展示时长内(
durationMs)随机动画链暂停,保证通知动作完整播完。 - 同一时刻只有一条气泡,后到的覆盖前面的。
- 桌宠本身不存储通知历史(当前版本),错过了就没了。
语义标签(AI 调用推荐方式)
每个动作和表情包都带内部标签。AI 不必记中文名,按语义调用即可。
标签表
| 标签 | 含义 | 典型动作 / 表情包 |
|---|---|---|
work workstatus |
工作状态 | 思考冒泡 / 忙碌点按 / 清点归档 / 踱步张望 / 雀跃庆祝 / 垂头叹气冒汗 |
thinking working result waiting success error |
六档细分 | 对应上面六种工作状态 |
happy celebrate praise |
开心/庆祝/夸奖 | 雀跃庆祝、开心跃动、厉害了我的鲸、可爱 |
sad error fail |
沮丧/出错 | 垂头叹气冒汗、死掉了、完蛋了把黄油删了 |
busy stress |
忙碌/压力 | 忙碌点按、压力一只大肥鱼、大烧货 |
eat food |
吃东西 | 吃什么分类全部(12 个) |
play fun |
玩耍/搞笑 | 玩耍分类(27 个)+ Ciallo、就骚了怎么滴吧 |
rest sleep lazy |
休息/摸鱼 | 待机呼吸、小憩沉眠、哈欠连天、深度睡眠 |
festival season |
节日/时令 | 时节分类(21 个:春节/中秋/圣诞/万圣…) |
money token need |
余额/token | 余额动画 6 档、token给妈妈保管、鱼片有资源吗 |
warn urgent alert |
预警/紧急 | 大的要来啦、大的药来了、电死你 |
greet wave hello |
打招呼 | 元气挥手、Ciallo |
shy surprise angry tsundere |
情绪 | 害羞惊讶、傲娇生气 |
drag click move turn idle look walk picked |
交互池 | 拖拽悬空、点击回应、移动走路、转向张望、待机 |
text talk whisper |
文字/说话 | 文字分类 2 个、碎碎念 3 个 |
category + 分类名 |
分类归属 | 小动作 / 玩耍 / 吃什么 / 时节 / 文字 |
新增 / 增强的接口
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/catalog |
返回全部动作与表情包及其标签(免授权) |
| POST | /api/meme |
`{tag |
| POST | /api/anim |
现在支持 {tag:"play"} 按标签点播 |
| POST | /api/task /api/notify |
新增 withMeme:true 或 memeTag:"success" 自动配图 |
典型用法
# 开始干活:播「忙碌点按」+ 自动配工作风表情包
curl -X POST http://127.0.0.1:7350/api/task \
-H 'Content-Type: application/json' -H 'X-Pet-Token: 你的授权码' \
-d '{"state":"working","text":"正在生成周报…","withMeme":true}'
# 干完了:播「雀跃庆祝」+ 夸奖表情包
curl -X POST http://127.0.0.1:7350/api/task \
-H 'Content-Type: application/json' -H 'X-Pet-Token: 你的授权码' \
-d '{"state":"done","text":"周报已生成 ✅","memeTag":"praise"}'
# 出错了
curl -X POST http://127.0.0.1:7350/api/task \
-H 'Content-Type: application/json' -H 'X-Pet-Token: 你的授权码' \
-d '{"state":"error","text":"构建失败","withMeme":true}'
# 随手玩一下
curl -X POST http://127.0.0.1:7350/api/anim -H 'Content-Type: application/json' \
-H 'X-Pet-Token: 你的授权码' -d '{"tag":"play"}'
curl -X POST http://127.0.0.1:7350/api/meme -H 'Content-Type: application/json' \
-H 'X-Pet-Token: 你的授权码' -d '{"tag":"fun"}'
# 让 AI 自己发现可用标签
curl http://127.0.0.1:7350/api/catalog
自动配图规则
withMeme:true 时会按状态自动挑标签:
done/success → success,praise;error → error,fail;working → working,busy;
waiting → warn;start/thinking → working,busy。
表情包标签(随图入库)
表情包最终以 config.json 里每条的 tags 为准(官方 27 张 + 动画帧生成 24 张 + 梗鲸档案馆收录)。
常用梗图情绪标签:angry sad happy praise thinking fun confused complain
love money waiting greet eat work error rest。
GET /api/catalog返回每张表情包的tagsPOST /api/meme {"tag":"..."}按标签随机弹一张POST /api/task {"state":"working","withMeme":true}按状态自动配图- 应用内长按表情包可隐藏(写进
pet_prefs.hidden_memes)
动作节奏与随机
| 接口 | 说明 |
|---|---|
POST /api/settings {"chainGapSeconds":8,"idleAfterSeconds":120} |
切换间隔(0–60s)、空闲回待机(0=关闭,最多 3600s) |
POST /api/anim {"random":true} |
随机播一个动作(排除事件池) |
POST /api/anim {"idle":true} |
回到待机动作(待机池) |
GET /api/health |
返回 memes / tags / catalog / docs* 等入口 |
应用内也有:设置 → 动作(切换间隔、空闲回待机、随机播一个动作、回到待机)。
推送与动作节奏
推送(/api/task、/api/notify、/api/anim、/api/meme、/api/broadcast)现在也纳入动作节奏循环:
- 推送的动画会完整播放(占满其时长)
- 之后额外等待「切换间隔」(
chainGapSeconds)才继续随机动作链 - 推送会重置「空闲回待机」计时(视为有活动)
- 多次推送连续到达时,以最后一条的时长重新排程
扩展能力:技能 / 插件 / MCP
技能(Skills)
声明式动作序列,一次调用播一串。
| 接口 | 说明 |
|---|---|
GET /api/skills |
列出内置技能 |
POST /api/skill {"id":"work_done"} |
执行;可带 text 覆盖首个气泡文字 |
内置:work_start 开工 · work_done 收工 · work_error 出错了 · slack 摸鱼 · meal 干饭 · greet 打招呼 · sleep 睡觉 · report 汇报。
应用内:动作页顶部「技能」卡片点一下即触发。
插件(JS)
| 接口 | 说明 |
|---|---|
POST /api/plugin {"id":"x","code":"..."} |
安装/覆盖插件(存 App 私有目录) |
GET /api/plugins |
已装插件列表 |
POST /api/plugin/remove {"id":"x"} |
卸载 |
GET /api/plugins.js |
合并后的插件代码(宠物 WebView 自动加载) |
插件运行在宠物 WebView 里,可用桥接 Pet:
Pet.say(text, ms)、Pet.notify(state, text, withMeme)、Pet.anim({tag}|{name}|{random:true})、
Pet.meme({tag}|{name})、Pet.skill(id)、Pet.status()、Pet.on(evt, fn)。
示例插件:{"id":"clock","code":"setInterval(function(){Pet.say('整点啦~')},3600000)"}
MCP(Model Context Protocol)
本机 MCP Server:POST http://127.0.0.1:7350/mcp?token=授权码(JSON-RPC 2.0)
initialize→ protocolVersion2024-11-05tools/list→pet_statuspet_saypet_notifypet_playpet_memepet_skillpet_catalogtools/call→{name, arguments},返回content[0].text(JSON 字符串)
curl -X POST 'http://127.0.0.1:7350/mcp?token=你的授权码' \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"pet_notify","arguments":{"state":"working","text":"MCP 调用测试","withMeme":true}}}'
内置插件(首启自动安装)
| id | 名称 | 行为 |
|---|---|---|
greet_daily |
时段问候 | 早/中/下午/晚各问候一次(按天去重) |
water_reminder |
喝水提醒 | 每小时一句补水提醒 |
sit_reminder |
久坐提醒 | 每 45 分钟提醒起身 |
clock_chime |
整点报时 | 整点轻声报时 |
tap_counter |
戳戳吐槽 | 连戳 5 次吐槽一句 |
random_meme |
随机表情包 | 每 2 小时随机弹一张 |
全部 23:00–07:00 静默。设置 → 内置插件 可逐个开关;GET /api/plugins 查已装列表。
技能新增:hydrate 喝水 · stretch 伸懒腰(共 10 个)。
新增内置插件(v2)
| id | 名称 | 行为 |
|---|---|---|
fish_memory |
鱼的记忆 | 七秒记忆梗:约 25 分钟一次有 35% 概率忘事;被戳 12% 概率问「刚才说什么来着」 |
fish_mood |
鱼的心情 | 心情值 0–100,戳+4、被甩-1,按小时自然衰减;每 90 分钟按心情说一句并配 happy/sad 动作 |
proactive_talk |
主动搭话 | 40–80 分钟随机主动说一句(关心/闲聊/白米饭),夜间静默 |
插件配置(v3)
内置插件支持参数配置:设置 → 扩展 → 插件 → 点某个插件 → 滑条/开关 → 保存(自动按新配置重装)。
存储:pet_prefs.plugin_cfg_<id>(JSON),安装时以 var CFG = {...}; 注入代码前缀。
| 插件 | 可调参数 |
|---|---|
| 时段问候 | 夜间免打扰、启动延迟(0–60s) |
| 喝水提醒 / 久坐提醒 | 提醒间隔(15–240 / 15–180 分钟)、夜间免打扰 |
| 整点报时 | 只报 7–23 点 |
| 戳戳吐槽 | 每戳几次吐槽(2–20) |
| 随机表情包 | 间隔(30–480 分钟)、夜间免打扰 |
| 鱼的记忆 | 间隔(10–120 分钟)、触发概率(0–100%)、被戳概率 |
| 鱼的心情 | 表达间隔(30–240 分钟)、被戳加点(0–20)、初始心情 |
| 主动搭话 | 最短/最长间隔(分钟)、夜间免打扰 |
自定义插件同样能用 CFG:安装时把常量写成 var CFG = {...} 前缀即可。