中文 | English
whale-girl
A desktop pet in the DSH Web GUI (QQ-pet style)
A persistent companion floating bottom-right: draggable, feedable, playable —
completed tasks, sessions, and companionship time accrue into seniority levels,
titles, and memories.
Installation
Official bundle plugin (dsh.bundle + dsh.client in root package.json), managed via the official profile:
dsh plugin --profile web add "github:vlln/whale-girl#main" # single-line git source (build artifacts committed)
# or npm source (npm 上的版本可能落后于 main,以 git 源为准): dsh plugin --profile web add whale-girl@0.2.0
# or local directory: dsh plugin --profile web add <path-to-whale-girl>
Restart web after installing (bundle layers compose at startup); the pet appears bottom-right: click for its menu (🍗 feed / 🎾 play), drag to move, hover for the status bar (seniority level / task count / recent shared memories). Hidden on onboarding pages.
Update via dsh plugin --profile web update whale-girl (or switch the git ref), then restart.
Usage
| You / event |
Pet behavior |
| Drag the pet |
Stretched diagonally (drag) |
| Menu 🍗 feed / 🎾 play |
Chomping / ball toss (eat/play) → joy (joy) |
| Idle ≥60s |
Naps (sleep); wakes on interaction (wake) |
| Task done / level-up / title / round done |
Cheers (celebrate) |
| Task failed / request error |
Startled (error) → disappointed (disappointed) |
| New session |
Waves welcome (welcome) |
| Session running / thinking |
Pensive company (think, occasional working) |
| Awaiting approval |
Expectant waiting (wait) |
| Periodic wandering |
Walking (walk) |
| Default |
Idle standby (idle, random blinks / turns) |
Full state machine (priorities / transitions / triggers): docs/state-machine.md.
Desktop Companion (Optional)
desktop/ is a standalone companion app (Node engine + Tauri shell, zero runtime deps) that keeps the whale girl resident on your OS desktop. Not installed via dsh plugin — enable it yourself:
# Prereqs: Node ≥18; the rendering shell needs Rust (cargo)
npm install -g whale-girl-desktop # npm install (engine + Tauri shell source included)
whale-girl-desktop --headless # headless: presence heartbeat + state polling + SSE
cd "$(npm root -g)/whale-girl-desktop/src-tauri" && cargo build --release # first build ~5-15 min; artifact target/release/whale-girl-desktop (~12MB)
./target/release/whale-girl-desktop # transparent always-on-top desktop pet (defaults to local DSH on 3080)
# WHALE_GIRL_BASE_URL=http://IP:PORT points at a non-local DSH
# or from source: cd desktop && npm install && cd src-tauri && cargo build --release
- Uses whale-girl's public endpoints (
/state, /events, /presence, /interact, /config, /assets) without touching the plugin; the in-page pet hides while it runs (presence contract) and returns after exit/crash (TTL 45s).
- Shell: Tauri v2 (recommended, ~12MB); legacy Electron shell kept (
npm i -D electron).
- Design & contracts:
desktop/DESIGN.md, desktop/BUILD-RUN.md.
State Preview
| State |
Trigger |
Preview |
idle |
Default standby |
 |
working |
Random work spell while session thinks |
 |
celebrate |
Task done / level-up / title / round done |
 |
error |
Task failed / request error |
 |
disappointed |
Brief dejection after failure |
 |
joy |
Happy after feeding / playing |
 |
eat |
Click to feed |
 |
play |
Click to play |
 |
drag |
While dragging |
 |
walk |
Periodic wandering |
 |
sleep |
Idle ≥60s |
 |
wake |
Wake-up transition |
 |
welcome |
New session |
 |
think |
Company while session thinks |
 |
wait |
Awaiting approval |
 |
Configuration
Plugins → Installed → whale-girl bundle page (config card): the high-frequency subset — show on page, size, opacity, wandering, sleep delay, and the feed/play reply pools (one per line). Changes apply immediately, no restart (a switch writes on click; numbers and reply pools write on blur or Enter).
The card's first row is an update row: it checks the source once on mount (git installs by commit, registry installs by version) and shows the verdict plus the installed short commit; a newer revision turns the button into "Update to …". An update only rewrites the profile's dependencies and lockfile — the entry's config: (size, opacity, reply copy) and every other patch entry stay untouched, and the enabled state is preserved. It reinstalls through DSH's profile package manager — first the exact revision just checked, then the line the profile records (a branch or tag keeps tracking it) — and reports the host's outcome: hot-applied, restart DeepSeek Harness to apply, overridden, or failed (with the host's error code). Version and source already appear in the bundle page's source section, so the row does not repeat them. A local-path install (dsh plugin add <dir>) that is a git checkout declaring a repository follows that repository's default branch; otherwise, or without a package manager, the row only says no source can be checked.
The full option list lives in the plugin entry's config in the profile patch (<dshHome>/profiles/<profile>/cordis.patch.yml); a whale-girl: section in <dshHome>/settings.yaml is imported into that entry once:
whale-girl:
enabled: true # web render toggle (false disables the in-page pet while a desktop companion runs)
size: 110 # pet size px (64–160)
opacity: 1 # default opacity (0.2–1)
walk:
enabled: true # wandering toggle
sleepAfterMs: 60000
Full option list and why the semantic layer (XP / titles) is sealed: lib/src/config.mjs. Not configurable (changing XP / title thresholds would break the accumulation ledger).
Characters
🎭 "Switch Character" cycles characters (or set whale-girl:character in localStorage); the button is greyed out when the manifest has a single character ("No other characters available"). Every character ships all 15 states (full contract: docs/sprites-spec.md); new characters: docs/adding-a-character.md.
Reference Implementation
whale-girl is a complete bundle plugin format exemplar (dsh.bundle + cordis.patch.yml + lib/, evolving with the official mechanism) — model new plugins on it:
- Structure:
lib/ (entry / logic / client / assets) separate from docs, decisions, scripts — root AGENTS.md
- Conventions: gates (
scripts/gates/run.mjs) + decision records + full asset contracts; guidance: plugin-registry's make-dsh-plugin skill, cookbook, gotchas
Contributing
Issues and suggestions welcome — your feedback shapes the pet's next steps:
- 🐛 Bug: file an issue with repro steps, browser & dsh versions; console errors for client issues
- 💡 Feature ideas: see docs/state-machine.md and docs/growth-system.md, describe the expected effect
- 🎨 New characters: docs/adding-a-character.md §quick guide — read-only contract, 15 sheets + manifest entries, validated by
verify-assets
- 🔧 Code: every non-trivial change needs a decision record (
decisions/), gate self-checks, single-purpose commits (docs/AGENTS.md, root AGENTS.md)
Acknowledgements
Character by ZipZipPipe (the "Whale Girl" sticker character); sprites generated from their design.
License
MIT License