Bundle
dsh-prevent-scd
DSH 防猝死小卫士 — a playful rest-reminder pet plugin for DeepSeek Harness: detects late-night or prolonged continuous human operation and blocks the UI with a cute nurse-cat until you agree to rest. 检测深夜或连续数小时有人工操作的 DSH 会话,放出宠物捣乱并提醒休息。
- Source
- Codingendless
- stars
- 2 stars
- License
- MIT
- Updated
- Updated 13 days ago
Readme
# dsh-prevent-scd — DSH 防猝死小卫士 🐱
> **English** · [中文](#中文文档)
**dsh-prevent-scd** is a playful rest-reminder pet plugin for the [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH) web UI — like ChatGPT's pet, it comes out and **causes trouble** to make you take a break.
It watches for **traces of human operation** in DSH sessions and nags you when:
- you have been working **continuously for hours** (default 3 h, any configurable), or
- it is **late night** (default 23:00–06:00, configurable) and you are still operating.
A cute hand-drawn **nurse-cat** (inline SVG, zero external assets) lives in the composer strip, turns worried when you approach the limit, then **blocks the whole screen** with a bouncing sign — **「⛔ 睡觉!」 at night / 「⛔ 走走!」 by day** — intercepting Enter, until you choose the matching action (**“OK, I'll sleep”** at night / **“I'll go for a walk”** by day, quiet for 2 h) or snooze for 15 more minutes.
### Highlights
- Host half (Node): listens to `session/event` real `user/message`s (plugin-injected / replay events do not count), maintains continuous-work timing.
- Browser half (Web): persistent status line + companion **moe pop-up** (once you've been continuously working for each multiple of `moeIntervalMinutes`, the cat pops into the bottom-right corner to say hi — click to dismiss, never blocks) + full-screen mischief overlay, five SVG poses (napping / worried / blocking-sleep / blocking-walk / relieved farewell), CSS animations (breathing, tail wag, shake, floating Zzz).
- Scene-aware copy: **late night → go to sleep**, **daytime long work → go for a walk** — the messages, title, buttons and the sign all match the trigger.
- Every threshold is configurable: `maxWorkMinutes`, `idleBreakMinutes` (a no-op gap longer than this resets the clock, default 30 min), late-night window, cooldown, snooze.
- State persists to `$DSH_HOME/prevent-scd/state.json`, surviving `dsh` restarts.
- No external assets, no network calls, works offline. 18 unit/integration/smoke tests.
### Quick install
```powershell
dsh plugin --profile web add -w "path/to/dsh-prevent-scd"
# restart the dsh web service to activate
```
Override config in the profile's `cordis.patch.yml` (hot-reloaded, no restart needed):
```yaml
- id: prevent-scd
config:
maxWorkMinutes: 120
idleBreakMinutes: 20
lateNightStart: '23:00'
lateNightEnd: '06:00'
```
### HTTP surface
- `GET /prevent-scd/state.json` — state snapshot (browser polls every 15 s)
- `POST /prevent-scd/ack` — `{ "kind": "rest" | "snooze" }` user response
### License
MIT
---
# 中文文档
一个 DSH(DeepSeek Harness)Web 插件:检测「深夜 + 有人工操作」或「连续数小时有人工操作」,
放出宠物跳出来**捣乱**,提醒你休息——像 ChatGPT 的宠物一样。
- 宿主半边(Node):监听 `session/event` 的真实用户消息(`user/message`,`source.kind === 'user'`,
且为 `append` 进入日志的事件;插件注入/历史回放不算人工操作),维护连续计时;
- 浏览器半边(Web):输入框下方常驻一行状态小字;卫士猫每隔 45 分钟(可配置)在右下角
**冒出来卖个萌**说句话(点一下就关,不挡工作);休息时间到后宠物占满全屏捣乱
(挡住界面、拦截回车),给你「去休息 / 再干 N 分钟」两个出口。
## 规则(全部可配置)
| 配置 | 默认 | 说明 |
|---|---|---|
| `maxWorkMinutes` | 180 | 连续工作上限(分钟),达到后宠物出来捣乱 |
| `warnAtMinutes` | 150 | 提前提醒:连续时长到达该值先小声提醒 |
| `idleBreakMinutes` | 30 | 无操作多久算中断:超过该时长连续计时清零 |
| `moeIntervalMinutes` | 45 | 陪伴卖萌:卫士猫每连续工作满该分钟数,在右下角冒出来卖萌一次(0 = 关闭) |
| `moeDurationSeconds` | 6 | 卖萌卡片停留时长(秒),点一下可提前关闭 |
| `lateNightStart` | `23:00` | 深夜窗口开始(`HH:MM`,支持跨零点) |
| `lateNightEnd` | `06:00` | 深夜窗口结束 |
| `recentActivityMinutes` | 20 | 深夜判定「人在」的操作窗口:超过该时长无操作不打扰 |
| `lateNightMinWorkMinutes` | 0 | 深夜触发所需的最少连续工作分钟(0 = 深夜有操作即提醒) |
| `restCooldownMinutes` | 120 | 点「我去休息」后的安静时长 |
| `snoozeMinutes` | 15 | 点「再干 N 分钟」的延时时长 |
| `evaluateIntervalSeconds` | 30 | 宿主侧评估间隔(浏览器侧轮询固定 15 秒) |
| `persist` | true | 计时状态持久化(重启 dsh 不丢) |
| `statePath` | `''` | 状态文件路径;留空 = `$DSH_HOME/prevent-scd/state.json` |
「连续」的定义:任一无操作间隔超过 `idleBreakMinutes`(默认 30 分钟)即视为中断,
连续计时清零,下次操作重新起算。
## 安装
```powershell
# 在你的 profile 里安装(示例:web)
dsh plugin --profile web add -w "D:\projects\vibe\dshp\dsh-prevent‑scd"
```
然后**重启 dsh web 服务**生效(profile bundle 列表变更需要重启;运行中的实例不受影响)。
> 注意:pnpm 对 `link:` 依赖不安装传递依赖,`@deepseek-ai/cordis` /
> `@deepseek-ai/schemastery` 通过本机共享的 `D:\projects\vibe\dshp\node_modules` 解析
> (与同目录的 dsh-liang-rheostat 插件同一约定)。换机器部署时,先在插件目录
> 执行 `pnpm install` 或把这两个依赖装到可达的 node_modules。
## 配置
在 profile 的 `cordis.patch.yml` 里按行 id 覆盖(最后写入者胜,保存即热生效):
```yaml
- id: prevent-scd
config:
maxWorkMinutes: 120 # 2 小时就提醒
idleBreakMinutes: 20 # 20 分钟无操作算中断
lateNightStart: '22:30' # 22:30 到次日 6:30 算深夜
lateNightEnd: '06:30'
snoozeMinutes: 10
```
或直接改 bundle 里的默认值(`cordis.patch.yml` 中该行的 `config`)。
## 卸载
```powershell
dsh plugin --profile web remove dsh-prevent-scd
# 并删除 profile package.json 的 dsh.profile.bundles 里的 dsh-prevent-scd(如果 pnpm remove 没自动清)
```
删除 `$DSH_HOME/prevent-scd/` 可清掉计时状态。
## 内部结构
```
cordis.patch.yml bundle patch:插入 prevent-scd 一行(dsh.client 双面包)
lib/index.js 宿主插件:session/event 监听、/prevent-scd/* HTTP 端点、持久化
lib/tracker.js 纯逻辑规则引擎(无 cordis 依赖,可独立测试)
lib/client.js 浏览器 bundle:状态条 + 全屏宠物拦截(手写 ModuleLoader 格式)
宠物为内嵌 SVG 矢量插画(渐变毛色/高光/护士帽+爱心主题,
打盹/担忧/拦路(深夜睡觉版/白天走走版)/放行,零外部资源)
tools/render-pets.mjs 开发工具:把四个宠物 SVG 渲染成 PNG 并做结构分析
test/ node:test 单元/集成/冒烟测试
```
- `GET /prevent-scd/state.json` — 状态快照(浏览器每 15 秒轮询)
- `POST /prevent-scd/ack` — `{ "kind": "rest" | "snooze" }` 用户回应
改宠物美术:`lib/client.js` 里的 `PET_SLEEP / PET_WORRY / PET_ANGRY_SLEEP /
PET_ANGRY_MOVE / PET_HAPPY` 五个 SVG 字符串,改完用 `node tools/render-pets.mjs tools/art`
渲染预览,再刷新浏览器即可(客户端 bundle 是运行时从插件目录读取的,无需重启 dsh)。
## 测试
```powershell
pnpm test # 或 node --test-force-exit test/tracker.test.js 等
```
## License
MIT
Install
dsh plugin --profile web add github:Codingendless/dsh-prevent-scd
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-prevent-scd from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.