桌宠-奶娃小时候(dsh-desktop-pet-naiwa):一个把 Agent 进度、Token 估算和真实余额放进 Windows 桌面的 DSH 插件

前言

在 DSH 里跑 Agent,多数时间你盯着的是 Web GUI:任务跑到哪一步、这一步调用了什么工具、今天烧了多少 Token,都需要切回页面看。网页窗口也没法做一个始终浮在桌面、点击可交互的角色。dsh-desktop-pet-naiwa 是 Night-maze 维护的一个 Windows 客户端插件,做的事是把这些信息投影到一个透明、无边框、置顶的原生窗口里,同时让这个窗口可以单击互动、长按拖拽、贴边半隐藏,并支持把文件拖进去移动到回收站。

下面介绍这个插件:先讲它为什么必须拆成两层,再讲功能、安装命令和可用配置。

这是什么东西

一句话定位:基于 DeepSeek Harness 插件机制的 Windows 桌面宠物(桌宠),维护者 Night-maze,分类为客户端,许可证 MIT,GitHub 仓库创建于 2026-11-05,当前星标 0。npm 包名 dsh-desktop-pet-naiwa,版本 1.0.0。

它解决的问题:Agent 运行时状态在原生桌面上缺席。现有的 DSH client plugin 只能渲染 Web GUI 内的 React 界面,不能创建任意 OS 窗口。

为什么要 Host 插件加 WPF 子进程

DSH 的 client plugin 跑在浏览器 sandbox 里,没有创建原生窗口的权限。要做出透明、无边框、置顶、可拖拽的窗口,必须有一个独立的原生进程。插件因此拆成两层:

  • Host 插件 lib/index.js(Cordis bundle),订阅 session/event,维护按天回填的 Token 账本,读取真实余额,并负责拉起和守护子进程;
  • WPF 子进程 pet/DesktopPet.ps1 + DesktopPet.cs,自己画窗口、做手势和动画;
  • 两者之间通过 127.0.0.1 loopback 上的 newline-delimited JSON 通信,并带随机 token 鉴权。

职责也有明确边界:Host 不把 Token、余额、进度写死;WPF 子进程不访问网络、不读 DSH 内部状态,只消费宿主发来的 JSON。

核心功能

Agent 进度投影

按事件投影:turn/start 表示任务开始,step/start 和 tool/call 提供进度,assistant/message 与 assistant/attempt 提供 Token 用量,turn/end 给出完成、失败或取消,agent/error 作为失败兜底。

默认显示不确定进度条加「第 N 步 · 工具名」文本。插件明确不使用编造的 0–100% 数字,避免出现一个看着像进度、其实没有依据的百分比。

Token 花费估算与真实余额

「今日花费」是真实 Token 用量 × 公开列表单价,UI 里用 ≈ 标注,这是估算值。利用率账本按 sessionId:seq 去重;同一个 turn/step 的成功消息会替换失败的 attempt;llm/retry-started 之后允许重试 attempt 再次计入。启动时从 ctx.sessionPersistence 回填当天数据。

「余额」来自 ctx.deepseekAccount.getBalance,是平台钱包的真实值,不估算、不伪造。读取失败时保留上一次的值并标记为 stale,刷新带指数退避,绝不用 0 冒充。

价格默认内置 deepseek-flash、deepseek-v4-pro 的 CNY/USD 公开列表价,并区分峰时(北京时间工作日 9–12、14–18)与非峰时。没有配单价的模型只显示 Token,不计金额。

交互行为

  • 单击:按权重随机选一条 interactions 配置,内置 6 种(blink、jump、shake、heart、random line、dance),可配权重、动画、台词和对应精灵。
  • 长按提起:按下后超过 longPressMs(默认 450ms)算提起,之后是钟摆/弹簧拖拽,松手自然落回。
  • 贴边半隐藏:拖到屏幕边缘释放后,按当前显示器 WorkingArea 和 edgeThreshold 判断方向,滑到只露 edgeVisibleRatio;鼠标移入滑出,移出延迟滑回。
  • 点击穿透:WM_NCHITTEST 按当前精灵 alpha 判断,透明像素返回 HTTRANSPARENT,不挡住桌面其他操作。

拖拽文件到回收站

通过 IFileOperation 加 FOF_ALLOWUNDO | FOFX_RECYCLEONDELETE 实现,强制「回收或失败」,没有 File.Delete / Directory.Delete 回退。路径受限:盘符根、系统目录、符号链接/目录联接、无权限、文件被占用、跨盘或网络回收失败,都会保留原文件并弹出明确错误。AppContainer 或低完整性进程会被拒绝执行。

客户端侧

client 侧注册侧边栏 🐾 桌宠 入口和设置页,可调缩放、音量、统计显示、长按/拖拽阈值,并支持刷新统计、重启、显示/隐藏。设置写入数据目录 ui-config.json,覆盖 profile 同名字段;删掉该文件并重启插件可恢复 profile 配置。

安装与启用

前置:Windows 10/11,系统自带 Windows PowerShell 5.1 和 .NET Framework 4.x(WPF 组件)。不需要额外 npm 依赖,Host 只用 Node 内置模块。插件声明基于 DSH 0.2.1-rc.5 的 Cordis 插件/服务 API。

推荐方式是用 bundle 安装。先在 DSH Web GUI 打开 Plugins,执行:

dsh plugin --profile desktop add dsh-desktop-pet-naiwa

或者指向本地源码目录:

dsh plugin --profile desktop add link:F:\path\to\dsh-desktop-pet-naiwa

package.json 里已经声明了 bundle patch 和 client 注入:

"dsh": {
  "bundle": { "patch": "./cordis.patch.yml" },
  "client": { "platform": "web", "inject": ["..."] }
}

接下来的步骤:

  1. 在 Plugins 页面把「桌宠-奶娃小时候」这个 bundle 打开,或把它加入 profile 的 dsh.profile.bundles。
  2. 移除任何指向绝对路径的开发行,避免同一插件加载两次。
  3. 刷新 DSH 页面,侧边栏应出现 🐾 桌宠。若没有,重启 DSH 一次,让 client graph 重新扫描 dsh.client。

另有一种开发行方式,只在 %USERPROFILE%\.dsh\profiles\<profile>\cordis.patch.yml 追加绝对路径条目。它没有 bundle 身份,Plugins 页面没有开关,也没有 client 设置页,只适合临时调试,日常应删掉。

配置

完整字段和注释见仓库的 config.example.yml。常用项:

字段 默认 说明
enabled true 插件总开关
imagePath '' 单张自定义形象;留空用内置 12 精灵
spriteDir / soundDir 内置 assets 相对插件目录或绝对路径
scale 1.0 整体缩放 0.5–2,窗口、UI、形象一起缩放
volume 0.7 音效音量 0–1
topmost true 置顶
avoidFullscreen true 全屏应用时隐藏
statsDisplay always always / hover / off
longPressMs 450 长按提起阈值
dragStartPx 10 拖拽启动阈值
edgeThreshold 24 贴边触发距离(物理像素)
edgeVisibleRatio 0.38 半隐藏后可见比例
currency auto CNY / USD / auto(跟钱包)
costPrecision 4 花费小数位
balanceRefreshMs 60000 余额刷新,最小 30s,失败指数退避到 5min
statsRefreshMs 30000 统计推送间隔
pricing 公开价表 峰时、节假日、模型单价(每百万 Token)
interactions 6 种 单击随机互动的权重/动画/台词/精灵
protectPaths 系统目录 拒绝回收的路径前缀
backfill 开启 启动回填的数量/字节/超时上限

pricing.holidays 默认是空数组:中国法定节假日每年变化,插件不内置易过期日历;需要精确峰谷账单就手动填 YYYY-MM-DD。

配置里的数组是整体替换,不是逐项合并。单击是从 interactions 里抽一条,再用该条的 sprite 指定显示哪张图(文件名去掉 .png)。想保留哪几条就全部列出来,未列出的不会再出现。

数据与日志

默认目录 $DSH_HOME/storages/desktop-pet/:

文件 说明
pet-config.json Host 写给 WPF 的合并配置
usage.json 今日 + 最近 14 天 Token 账本,含模型、时间、四个桶
host.log Host 插件诊断
pet.log WPF / 启动器诊断
launcher.log 启动器编译与启动诊断
window.json 上次窗口位置,用于多显示器恢复

日志可能轮转为 pet.log.old.<timestamp>,插件不会删除用户文件。

测试与验证

node test/run-tests.mjs          # host 单元测试
node test/mock-host.mjs          # 真实 WPF + mock Cordis 集成
powershell -STA -File scripts/demo.ps1

回收站那条测试必须在普通用户进程里跑,不能在 DSH workspace sandbox 里:

powershell -STA -File scripts/test-recycle.ps1

适用场景与注意

适合在 Windows 上跑 DSH Agent 的开发者:希望进度和成本留在桌面上可见,同时接受一个常驻子进程。全屏演示场景下 avoidFullscreen 会把它藏起来,不会打断展示。

几点需要留意:

  • 插件以当前 dsh 进程权限运行。它确实会调用平台余额接口,并在收到文件拖入时操作回收站,所以安装前应先审一遍源码,确认 ctx.deepseekAccount.getBalance 调用和 IFileOperation 调用符合你的预期。许可证是 MIT,来源是 npm 包和 GitHub 仓库。
  • 唯一会删除文件的路径是 Shell 回收 API。如果 Shell 无法回收,操作直接失败,原文件保留,没有永久删除的回退。
  • 「今日花费」只是估算,金额按公开列表价算,不等于已结算金额。
  • 进度条刻意不显示百分比,如果需要确切的数字,仍应回到 Web GUI 或日志里看。

结论

这个插件把 Agent 运行时状态从 Web 页面搬到了原生窗口,关键取舍是:用估算值标花费、用真实值标余额、用不确定进度条代替伪造百分比。两层结构(Host 插件 + WPF 子进程)是它绕开 client plugin sandbox 限制的方式,也是安装和排障时需要看清的地方。

目录页:https://www.skillhub.cn/plugins/Night-maze/dsh-desktop-pet-naiwa
仓库:https://github.com/Night-maze/dsh-desktop-pet-naiwa
npm:https://www.npmjs.com/package/dsh-desktop-pet-naiwa

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜