- Home
- Plugins
- Workflow & Automation
- dsh-whale-waker
dsh-whale-waker
ztan4706/dsh-whale-waker
Per-target scheduled wake-ups for a DSH workspace: interval, quiet hours, daily cap and a prompt per target; each wake-up waits for the turn it started and records the outcome, and a turn that never finished is not counted as done.
Install
dsh plugin --profile web add github:ztan4706/dsh-whale-wakerREADME
Whale Waker
Scheduled wake-ups for the residents of a workspace. Each target — a "whale" — gets its own interval, quiet hours, daily cap, prompt and deny-list. Every wake-up reuses the same session, gathers what changed since last time, and sends one short prompt.
- Package:
dsh-whale-waker - Version: 0.4.1
- License: MIT
- Author: Bao · E-1021
Why: an agent that only exists while you type is a tool. An agent that wakes on its own, reads what changed, and decides to do one small thing — that is closer to a resident. This plugin is the clock for that.
Install
dsh plugin --profile <your-profile> add dsh-whale-waker
From a local checkout:
git clone https://github.com/ztan4706/dsh-whale-waker.git
dsh plugin --profile <profile> add link:/absolute/path/dsh-whale-waker
Or install the directory through plugin_manager's install_bundle in the app.
Restart DSH afterwards — plugin modules are cached by URL.
The settings page shows up in Settings → Whale Waker right after that.
Configure
Settings live in dsh-whale-waker.json:
$DSH_PROFILE_DIR/dsh-whale-waker.jsonby default,- or
config.configPathfrom the row config.
The page edits the file for you; the scheduler re-reads it when the mtime changes (checked every five minutes).
{
"targets": [
{
"id": "echo",
"name": "Echo",
"workspace": "D:\\rooms\\echo",
"provider": "",
"model": "",
"enabled": true,
"intervalMinutes": 95,
"minGapMinutes": 45,
"startHour": 9,
"endHour": 23,
"maxPerDay": 6,
"prompt": "(Scheduled wake-up.)\n\n{material}\n\nMove one thing forward, or answer \"nothing this round\"."
}
]
}
| Field | Meaning |
|---|---|
id | Target name; also the session id (walk-<id>) and the log tag. |
workspace | The room this whale lives in. Files changed here become material. Required: empty means no wake-up happens (no-workspace). |
provider / model | Optional. Empty means "use this DSH's default model", so the plugin does not assume a vendor. A provider this host does not serve is logged and skipped as provider-not-configured instead of failing inside agent creation. |
ollamaBase | Endpoint used only to pre-warm an ollama* provider. Default http://127.0.0.1:11434, 15 s timeout, and a failure never blocks the wake-up. |
intervalMinutes | How often it may wake on its own (5–2880). |
minGapMinutes | Minimum gap between two wake-ups (0–1440). |
startHour / endHour | Quiet hours: outside this window nothing fires (0–24). |
maxPerDay | Hard daily cap (0–48). 0 means never wake on its own. |
dryRun | Collect material and log it, but do not open a session. |
watch | Extra directories whose fresh files are listed as material. |
stateSection | Heading in STATE.md whose bullets are quoted (default ## In progress). |
denyTools | Tool names removed from that whale's wake session (e.g. another agent's private tools). |
activeWindowMinutes | After a human actually talks in that workspace, the timer stays quiet this long (default 10; 0 disables). Manual wake-ups ignore it. |
prompt | Template; {material} is replaced. |
name | Display name used in the session title (defaults to id). |
sessionTitle | Title template for the wake session; {name} is replaced (default Wake · {name}). |
State (last wake, today's count) is persisted to dsh-whale-waker-state.json next to
the config, so restarting DSH does not re-fire everybody.
Language
The settings page follows the DSH locale by default, and can be switched per plugin without touching the rest of the UI:
{ "ui": { "language": "zh-TW" } }
Supported values: auto (follow DSH), en, zh-CN, zh-TW. The selector sits
near the top of the page; the choice is written to the same config file.
While you are talking to it
A wake-up never joins your live chat: it opens (or resumes) its own session,
walk-<id>, in that workspace. So the honest answer to "would it start walking
while I am mid-conversation?" is yes, unless something stops it.
So something stops it. The plugin watches agent/inbox/claimed for messages a
human actually typed (its own injected prompts and walk-* sessions are ignored).
If the workspace saw one within activeWindowMinutes (default 10), the timer wake
is skipped and logged as user-active. The next tick, five minutes later, tries
again.
What this does not do:
- It does not interrupt a wake-up already running.
- It does not persist: after a restart the activity map is empty until the next
message.
minGapMinutesis the backstop for that window. - It does not block manual wake-ups (
wake_whale, or the page's "Wake once") — those are explicit intent and passforce.
Workspace path
The address under each target is editable: type a folder and press Apply. The host validates it (absolute, existing, a directory), stores the canonical spelling, and — when no workspace owns that folder — creates one titled after the last folder segment. That is what puts the wake session in its own sidebar group instead of "Ungrouped"; a typo is rejected with the reason instead of being saved.
Changing the path also changes the session id (walk-<id>-<workspace fingerprint>),
so the next wake opens a fresh session in the new room; the old one is left as
history.
Restart notice
The plugin compares the version on disk with the version the running process loaded. When they differ — the usual case right after an upgrade — the page shows a banner:
The package on disk is v0.0.2, but this process is still running v0.0.1. Restart DSH to load the new code.
That is deliberate: DSH caches plugin modules by URL, so "installed" and "running" can disagree, and silently pretending otherwise wastes an afternoon. Any plugin that changes something a restart is required for should say so, in the UI and in the log, instead of leaving the user to guess.
Tool
wake_whale — wake one target for a single turn.
wake_whale({})lists targets, their next-eligible state and today's count.wake_whale({ id: "echo", reason: "..." })wakes that target once, bypassing the schedule but still respecting "already running".
What a wake-up does
- Collects material: files changed in the workspace since the last wake, plus
watchdirectories, plus thestateSectionbullets ofSTATE.md. - Mounts an agent preset so the session has real tools (without one, a wake session
cannot even read its own
STATE.md). - Reuses
walk-<id>-<workspace fingerprint>— created the first time, resumed afterwards. The fingerprint changes with the workspace path, so a moved room gets a fresh session instead of resuming one that still points at the old path. - Attaches that session to the workspace group that matches its cwd.
- Sends the prompt and waits for the turn to actually end (claim →
turn/end). The session stays alive afterwards, so the conversation remains visible in that workspace. - Names the session from
sessionTitle(defaultWake · {name}), because the automatic titler ignores prompts that a plugin injects and would otherwise leave it "Untitled" in the sidebar.
Everything is logged to dsh-whale-waker.log next to the config, including the material
that was handed over — so "why did it say that" is answerable afterwards.
Limits (honest)
- The scheduler checks every five minutes, so a wake can drift by up to five minutes.
- Wake sessions run with the provider/model you configure; a slow local model can take a while to warm up (the plugin pre-warms Ollama, 3-minute timeout).
- Only one wake per target at a time.
- No UI to add targets — edit the JSON (or the page fields of existing targets).
License
MIT · Bao · E-1021
Related plugins
webnovel-writer
lingfengqaq/webnovel-writer
loopx (dsh-loopx-plugin)
loopx-project/loopx
ouroboros (dsh-plugin)
q00/ouroboros
loopx (dsh-loopx-plugin)
huangruiteng/loopx