dsh-pet 的宿主半侧向 DSH 自己的 Web 服务注册了一条前缀路由 /dsh-pet-7340,浏览器端、
桌面端、设置页与第三方插件全都访问同一份实现。本文只做功能预览(接口名 + 一句话),
完整契约——参数、响应体、字段含义、错误码与示例——见根目录的 openapi.yaml。
- 基址:
http://127.0.0.1:<port>/dsh-pet-7340,<port>是 DSH Web 服务实际监听的端口 - 只监听 127.0.0.1,且没有鉴权:任何能访问本机该端口的进程都能调用,请勿转发到公网
| 接口 | 功能 |
|---|---|
GET /dsh-pet-7340/state |
轮询唯一数据源:所有状态位都在这里;带 ?since=&timeout= 可长轮询 |
GET /dsh-pet-7340/config |
读合并后的成品配置(内置默认 + 用户层,字段已填满) |
GET /dsh-pet-7340/config/meta |
配置文件路径、日志文件路径、各类数据落盘位置、卸载该用哪个 profile |
GET /dsh-pet-7340/models |
可用服务商与模型清单(与 DSH 自己的模型选择器同源) |
GET /dsh-pet-7340/chat?pet= |
读某只桌宠最近的对话记忆窗口;带 ?rounds= 可指定本次读取的轮数(0–200,不传用配置的 chatMemoryRounds) |
GET /dsh-pet-7340/pose?pet= |
读桌面端宠物的实况(位置 + 朝向);网页端用客户端服务 petApi7340,不走这条路 |
| 接口 | 功能 |
|---|---|
POST /dsh-pet-7340/lock?pet= |
占用锁:联动演出期间独占这只宠物(除持锁者外全静音);lockId 给了=续期、没给=新建,回 lockId + expiresAt |
POST /dsh-pet-7340/lock/release?pet= |
释放占用:lockId=持锁者收工 / force=用户接管(渲染端上报,第三方不用调) |
锁占用期间,桌宠完全静止:它自己不动、也不弹气泡——余额、碎碎念、工作状态这些全都让路。
标了「(需锁)」的接口,第三方调用时必须带上 ?lock=<lockId>。锁就是给第三方用的:带上它,
才能保证这段时间归你控制,不被别的插件、也不被桌宠自己的事件打断。没带 → lock-required;
编号不对 → lock-lost(附 cause:过期 / 已释放 / 被用户抢走)。
两条边界:
- 没有锁时:不传
?lock=一切照旧;传了?lock=说明你以为自己还持有 → 回lock-lost,cause告诉你锁是怎么没的(过期 / 已释放 / 被用户抢走); - 用户优先:用户拖一下宠物、或把它隐藏 / 关闭,锁会立刻被撤掉。
/whisper、/balance、/chat是用户自己点的入口(右键菜单 / 斜杠命令),占用期间照常可用。
| 接口 | 功能 |
|---|---|
POST /dsh-pet-7340/whisper?pet= |
让桌宠生成一句碎碎念(走当前模型);响应带 text(配图时另有 image),同时照旧写进气泡 |
POST /dsh-pet-7340/broadcast?pet= |
第三方投喂(需锁):把外部给定的文本写进气泡(不生成,只搬运);配图(image 池内名 / url 自带地址)、时长、动画联动可选 |
POST /dsh-pet-7340/bubble/clear?pet= |
清空气泡(需锁):提前收起说话气泡(只动气泡,不动动画) |
POST /dsh-pet-7340/chat?pet= |
对桌宠说一句话并生成回复,同时写入对话记忆;响应带 text(配图时另有 image),同时照旧写进气泡。可选 attachment(mediaType + base64)随本轮送一张图:图片记进记忆(存附件引用,不存本体),但只影响这一轮、不进气泡;不传时行为与旧版逐字一致 |
DELETE /dsh-pet-7340/chat?pet= |
删除对话记忆:带 ?ts=(可重复,取自 GET /chat 的 messages[].ts)只删这些轮——一轮两条共享 ts,成对删;不带 ts 清空整只。响应 { ok: true, removed },删空后不留空对象 |
GET /dsh-pet-7340/chat/memory |
列出已删宠物残留的对话历史(宠物删了但历史还在,GET /chat 读不到);只给条数与最后时间 |
DELETE /dsh-pet-7340/chat/memory |
一次清空这些残留历史 |
POST /dsh-pet-7340/balance |
立即刷新一次余额(可见效果同样是弹气泡 + 档位动画) |
| 接口 | 功能 |
|---|---|
POST /dsh-pet-7340/anim?pet= |
点播动画(需锁):播池内名字(同右键「动作」菜单)或第三方自带的 url;facing 可选指定朝向(left/right,不传则不动朝向);回 playbackId |
GET /dsh-pet-7340/playback/{id} |
播放回执:查那次点播的真实状态;带 ?wait=&timeout= 可挂起等待 |
POST /dsh-pet-7340/playback/{id}/report |
渲染端上报播放状态(内部通道,第三方不用调) |
POST /dsh-pet-7340/pose/report?pet= |
桌面渲染端上报实况(内部通道,第三方不用调) |
POST /dsh-pet-7340/position?pet= |
位置控制(需锁):挪到归一化坐标,mode = 直接/弹簧/直线;不碰动画。额外回夹取后的 x/y |
POST /dsh-pet-7340/throw?pet= |
原生抛掷(需锁):给桌宠一个初速度让它飞出去(angle 度、power 倍率) |
| 接口 | 功能 |
|---|---|
PUT /dsh-pet-7340/config |
保存用户层配置(白名单重建,用户手写的精调字段会保留) |
POST /dsh-pet-7340/config |
用内置默认整份覆盖用户配置,即「恢复默认」 |
POST /dsh-pet-7340/pet-display |
改单只宠物的显示位置(web / desktop / both / none),只传 { id, display } |
POST /dsh-pet-7340/pet-config |
按种类写回全部实例({ entry, pets },entry = pet/<名>-config.json 的前缀);白名单重建,顶层动画池与人设保留 |
POST /dsh-pet-7340/reload |
重载桌面端(重启桌面宠物进程,按最新配置重建窗口) |
| 接口 | 功能 |
|---|---|
POST /dsh-pet-7340/menu/item |
注册菜单项(该 owner 的菜单项整体覆盖):{ owner, labels: ["弹弓","钓鱼"], target?: "web"|"desktop"|"both" },target 不写 = 两端都显示 |
DELETE /dsh-pet-7340/menu/item?owner= |
清除菜单项(该 owner 的全部项,幂等):回 { ok: true, removed: 2 } |
GET /dsh-pet-7340/menu/events?owner=&wait= |
查询触发(读取即清空,wait = 长轮询毫秒数):回 { 弹弓: "main", 钓鱼: null } |
POST /dsh-pet-7340/menu/click |
渲染端上报点击(内部通道,第三方不用调) |
第三方菜单项统一收在右键菜单的**「更多」**下;只有一项时不显示 owner 那层。
| 接口 | 功能 |
|---|---|
GET /dsh-pet-7340/thumb/{petId}/{file} |
动画素材(.webm / .mov,按宠物归属) |
GET /dsh-pet-7340/font/{file} |
字体文件 |
GET /dsh-pet-7340/pic/{file} |
通知图标(pic/)与表情包(pic/memes/{素材根}/,按宠物归属) |
GET /dsh-pet-7340/attachment?id= |
取图:把对话记忆里 image.attachmentId(sha256:…)换回图片 |
GET /dsh-pet-7340/logo |
插件 logo(assets/logo.png),对话面板拿它当宠物头像 |
| 接口 | 功能 |
|---|---|
POST /dsh-pet-7340/work-status |
外部写入工作状态:{ state, task? },固定外部槽,最后写入者生效 |
DELETE /dsh-pet-7340/work-status |
清空外部槽回空闲(幂等,204) |
| 接口 | 功能 |
|---|---|
POST /dsh-pet-7340/voice/speak |
合成并返回 mp3:{ text, voice?, rate? };同一输入命中缓存,队列最多排 3 个 |
GET /dsh-pet-7340/voice/voices |
可用音色列表;前端拿它渲染选择器,不要硬编码 id |
GET /state 是所有状态位的唯一出口,结构固定:
每个 {…} 是一个叶子 { counter, data }:counter 变了就表示它更新了(唯一判据)。
长轮询:?since=<上次的顶层 counter>&timeout=<ms>(成对必填,上限 10s)。有字段改变就
立刻返回,否则一直挂到 timeout 到点;返回体与不带参数时一样。
前端在每个需要的地方各存一份 counter:首拉只记基线不渲染,之后一样就不渲染、不一样就
渲染并更新——据此判断变了没有、要不要触发。
不启动 DSH 时,同一份 /dsh-pet-7340 契约由本机服务提供,另外多出三个挂在服务根上的端点
(不在 /dsh-pet-7340 前缀下):
| 接口 | 功能 |
|---|---|
GET /、GET /health |
服务与插件信息:名称、插件根与版本、监听端口、已运行秒数 |
POST /shutdown |
优雅停机:释放插件注册的 effect(停止桌面助手、清掉周期定时器)后关闭服务,进程退出码 0 |
/dsh-pet-7340 下的端点形状不变,但三个依赖 DSH 的接口明确降级(结构化失败,不假装成功):
POST /whisper、POST /chat 回 reason: 'provider-missing',POST /balance 回 reason: 'unsupported'。
CORDIS.md—— 对外 Cordis 服务(客户端半侧,页面内ctx.get(),不走网络)openapi.yaml—— 完整契约(OpenAPI 3.1,可直接导入 Swagger UI / Postman)tools/api-tester.html—— 桌宠控制台:扮演第三方消费方的示例页面, 可直观试用上述接口(用node tools/api-tester.cjs启动,它会带上本地代理解决跨域)
{ "counter": 1755000000007, // 整份 S 的版本号 = 最后一次写入的编号(顶层,不是叶子) "sections": { // 全局段:所有端共享一份 "balance": {…}, "workStatus": {…}, "notify": {…}, "config": {…} }, "pets": { // 每只宠物各自一份;键是宠物 id(可含点号,勿切分) "main": { "say": {…}, "anim": {…}, "position": {…}, "throw": {…}, "lock": {…} } } }