dsh
OpenPetsHQ/openpets将 DeepSeek Harness 的生命周期状态、错误与审批请求,桥接到本地运行的 OpenPets 桌面伙伴。
A DeepSeek Harness (dsh) plugin that posts a hot-news or reminder card directly into the conversation stream while the agent is thinking for a long time. Low-frequency, never intrusive.
assistant/message directly into the session log (session.append + surfaceOp:'append'), rendered as a card in the conversation stream with a clickable link. If a source fails, it silently degrades — never blocks the conversation.gap_feed_reminder_add tool to save it. Due reminders are prioritized over news.gap-feed form automatically from a schema: configure limits, manage reminders (CRUD / enable / done).model source (kind/provider/model) from existing session messages, so the session loads fine after a restart (a forged source is rejected by SessionPersistence validation).dsh plugin --profile web add dsh-gap-feed
Restart dsh web (or just refresh the page).
Published on npm as
dsh-gap-feed— the market prefers prebuilt npm tarballs (noallowBuildsapproval needed).
All of the following must hold:
enabled is true;minThinkSeconds (default 20s) without idling — detected by polling the agent registry, so it's robust to event timing;cooldownMinutes (default 15) since the last injection;maxPerHour (default 4) injections in the last hour.Otherwise it stays silent and does nothing.
Say something with a time + a task, for example:
The model parses it into text (the task) + dueAt (unix ms timestamp, default = now + 1h) and saves it. Parse failures return a friendly error without blocking the conversation. Due reminders are shown before news on the next injection.
The dsh settings page automatically renders the gap-feed namespace form. Changes take effect immediately and survive restarts.
| Key | Type | Default | Description |
|---|---|---|---|
enabled | boolean | true | Master switch |
minThinkSeconds | number | 20 | Only inject after this many seconds of continuous thinking |
cooldownMinutes | number | 15 | Minimum gap between injections (minutes) — the core rate limiter |
maxPerHour | number | 4 | Per-hour injection cap (safety net) |
blacklist | string[] | [] | Title blacklist words; a matching title is filtered out |
Defaults live in DEFAULT_CONFIG in src/types.ts.
$DSH_HOME/profiles/<profile>/data/gap-feed/reminders.json
DSH_HOME defaults to ~/.dsh;id / text / dueAt / done / enabled / createdAt; missing dirs are created, and read/write failures or corrupt JSON silently fall back to in-memory state — never throws.npm install # dev deps
npm test # vitest: 67 unit + contract tests
npm run typecheck # tsc --noEmit
npm run build # tsc -> dist/ (prepack runs it automatically)
Layering discipline: pure-function layers (decision.ts, picker.ts) have zero dsh dependency and full branch coverage; side-effect layers (news.ts network, reminders.ts file I/O) are mockable via the Source interface; the wiring layer (index.ts) only connects the runtime.
-352) on datacenter IPs; it degrades silently — other sources are unaffected.MIT