deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
PROJECT README
Long-task audio reminder for DeepSeek Harness — a short "beep" when a sub-agent finishes, a clear "ding" when the whole turn is done and you should come back. Pure browser-side; works with any AI provider.
DSH(DeepSeek Harness)长任务完成提醒:你发出消息不响;子任务(子代理)完成响一声"嘟";整轮任务跑完、该回来操作了,响一声"叮"(附带可选标题闪动 / TTS 播报)。纯浏览器端做提醒,和你用哪家 AI 模型无关。
subagent, subagent_fork, etc.) settling; plays a short beep per completion, with an automatic merge window for rapid consecutive ones.speechSynthesis (off by default) with customizable template — use {time} as a placeholder for the actual duration.dsh plugin add dsh-plugin-task-notify
Restart dsh web and the settings card appears under Settings → Plugins.
lib/ artifacts):pnpm install && pnpm build
The
lib/directory ships pre-built; only rebuild after modifyingsrc/.
<dsh-home>/profiles/web/node_modules/dsh-plugin-task-notify/
cordis.patch.yml entry to the profile (the inject: [settings] line is required):- insert:
- id: task-notify
name: dsh-plugin-task-notify
inject: [settings]
config:
enabled: true
thresholdMinutes: 5
⚠️ The
inject: [settings]line is critical. Without it the cordis loader never waits for the settings service, so the host half'sapply()runs but the namespace never registers — and the settings card silently does not appear. See Troubleshooting below.
| Field | Meaning | Default |
|---|---|---|
enabled |
Master switch | true |
thresholdMinutes |
Turn-end ding threshold (minutes) | 5 |
subReminderEnabled |
Sub-task beep switch | true |
mergeMs |
Consecutive sub-task merge window (ms) | 500 |
masterVolume |
Ding volume, 0..1 | 0.6 |
subVolume |
Beep volume, 0..1 | 0.5 |
ttsEnabled |
TTS readout (default off) | false |
ttsTemplate |
TTS template, {time} = actual duration |
任务完成,用时约 {time} 分钟 |
titleFlash |
Title-bar flash on turn end | true |
globalSessions |
Monitor all sessions | true |
batchSingleBeep |
Single beep per turn for all sub-tasks | false |
runningCalls → short beep. Merge window deduplicates rapid completions; batchSingleBeep makes one beep per whole turn.{time} replaced by actual duration).0.1.0-rc.8 client contract (same baseline as dsh-plugin-agent-workflow).sessions.list, running, runningCalls) and standard settings slots.inject() snapshot forever).0.1.2-rc.1 snapshot-shape fix (2026-09): the client notifier previously read snap.runningCalls / snap.turnTimings as flat fields, but on 0.1.2-rc.1 SessionSnapshot only exposes running (running-call tree / turn timings moved into the chat view views.get('chat')?.legacy). Reading the flat field threw TypeError: items is not iterable inside walk → every SessionTracker.adopt() died → trackers= 0 and the whole notifier was silent, with the error repeating on every sync. Fix: added runningCallsOf() / turnTimingsOf() adapters that read views.get('chat')?.legacy?.runningCalls first, fall back to the flat field, and degrade to empty on absence; walk now guards Array.isArray. On 0.1.2-rc.1 the turn-end "叮" works (it only needs running); the sub-agent "嘟" is a silent no-op there because the running-call tree is not reachable through sessions without the chat-view service.Card shows stale values right after Save (controls look like they "did not work" even though the settings file actually updated):
The DSH slot renderer caches each slot entry's inject() result per registration (dsh-client-ui-renderer cachedRootInject, a WeakMap keyed by the entry). The settings card therefore receives whatever the inject closure returned on first render, forever. The 0.2.0 card was injected a one-shot value snapshot, so after Save (which writes via the live scope.set) the card fell back to the frozen snapshot and displayed the pre-save state. Fix (0.2.1): the inject closure hands the card the live bound settings scope instead of a snapshot; the card subscribes to it (scope.subscribe + scope.getSnapshot().value) and re-reads after every settled write, so Save updates the card without a reload.
Settings card does not appear even though the plugin shows as mounted and active in the plugin list:
The cordis loader reads inject from the patch line only, not from the plugin module's export const inject. If the patch line omits inject: [settings], the host half's apply() runs but any async delay (like installSettingsSection) never fires — the settings namespace is never registered, and the card never appears. Fix: add inject: [settings] to the patch line and use synchronous ctx.settings.register() in apply().
MIT © DearMrChai
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。