# whale-girl

> A whale girl desktop pet floats in the bottom right corner of the DSH webpage. It accompanies tasks and conversations, accumulating experience and memories. Users can feed, play with, and drag the pet.

## Metadata

- Author: [@vlln](https://github.com/vlln)
- Repo: <https://github.com/vlln/whale-girl.git>
- GitHub: [vlln/whale-girl](https://github.com/vlln/whale-girl)
- Stars: 252
- Language: JavaScript
- License: [MIT](https://spdx.org/licenses/MIT.html)
- Topics: `deepseek-harness`, `dsh`, `dsh-plugin`, `dsh-repository-plugin`, `pet`
- Forks: 15
- Open Issues: 3
- Last push: 2026-08-19T21:18:20.000Z
- Added: 2026-08-13T00:00:00.000Z

## Install

```bash
dsh plugin --profile web add github:vlln/whale-girl
```

## Wiki

## At a Glance
A whale-girl desk pet hovers in the bottom-right corner of the DSH Web GUI, accompanying you through completing tasks, meetings, accumulating seniority, and creating shared memories. It's a lightweight companionship plugin in the "QQ Pet" style, driven by accumulation rather than cultivation pressure.

## Core Capabilities
- **Floating Window Rendering**: Displays a draggable character in the bottom-right corner of the DSH web page, supporting click interaction menus (feed/play/switch character)
- **State Machine Driven**: Automatically switches between 15 state animations (idle, nap, welcome, celebrate, scared, disappointed, thinking, waiting, walking, etc.) based on events like tasks/sessions/idle
- **Seniority Accumulation**: Complete tasks +10 XP, new session +5 XP, active companionship time accumulates; zero negative feedback (failures only count, no point deduction)
- **Titles & Memories**: Unlock titles automatically upon reaching milestones; cumulative shared events between you and the pet are written into a memoir
- **Experience Layer Hot-Reload**: Pet size, transparency, wandering interval, idle time before napping, interaction reply text, etc. take effect without restart after modifying `settings.yaml`
- **Multi-Character Switching**: Built-in multiple character assets (each character must provide all 15 states), menu supports cyclic switching or persistent selection via localStorage

## Technical Implementation
- **Language**: JavaScript (Node half) + ES Modules; client bundle packaged with esbuild
- **Key Dependencies**: schemastery (config schema), esbuild (build client bundle); no other runtime third-party dependencies
- **Architecture Pattern**: Official bundle plugin format — repository root `package.json` declares `dsh.bundle.patch` + `dsh.client.platform=web`; Node half is a complete Cordis plugin (depends on `jobs`/`agents`/`sessions`/`settings`/`webServer`), client mounted via `__ModuleLoader__` kernel
- **Entry Files**: `lib/index.mjs` (Node half) + `lib/client/index.mjs` (client source; product `lib/client.js` generated by `scripts/build-client.mjs`)

## Use Cases
For people who use DSH for long periods running tasks or sessions, wanting a moving "companion" at their workstation to relieve monotony. The pet provides real feedback to task/session events (celebrates upon completion, accompanies during thinking, naps when idle), better demonstrating a "working together" atmosphere compared to purely decorative add-ons. Also suitable for users wanting to experience the QQ pet nostalgia, and as a reference for official bundle plugin development patterns.

## Prerequisites & Compatibility
| Dependency | Min Version | Description |
|---|---|---|
| DSH | Not declared | Official bundle plugin, does not declare engines in package.json; requires DSH supporting bundle format (profile web management) |
| Node | Not declared | Source uses ES Modules and top-level await; runtime provided by host |
| Platform | Cross-platform | Node half cross-platform; asset path sanitization handles Windows backslash traversal |
| Native modules | None | Pure JS dependency only on `schemastery`, no native binding introduced |

## Installation
```bash
dsh plugin --profile web add github:vlln/whale-girl
```

## Configuration Options
| Config | Type | Description | Default |
|---|---|---|---|
| `enabled` | Boolean | Master switch for web pet rendering; recommend setting to false when desktop companion is running to avoid dual pets | true |
| `size` | Number (64–160) | Pet display size (pixels) | 110 |
| `opacity` | Number (0.2–1) | Normal transparency (interaction has separate 0.25 temporary low transparency, not in this config) | 1 |
| `walk.enabled` | Boolean | Whether to allow pet to periodically auto-wander | true |
| `walk.minWaitMs` / `maxWaitMs` | Number (0–300000) | Random wait bounds between two wanders (ms) | 18000 / 40000 |
| `walk.minMs` / `maxMs` | Number (0–60000) | Single wander duration bounds (ms) | 3000 / 6000 |
| `walk.speedPxPerSec` | Number (10–300) | Wander speed (pixels/sec) | 45 |
| `sleepAfterMs` | Number (5000–600000) | Idle duration before entering nap state (ms) | 60000 |
| `pollMs` | Number (1000–30000) | State polling interval (ms) | 3000 |
| `bubbleMs` | Number (500–10000) | Interaction reply bubble display duration (ms) | 2500 |
| `welcomeMs` / `celebrateMs` | Number (0–30000) | Welcome/celebrate state window duration (ms) | 6000 / 6000 |
| `errorMs` / `disappointedMs` | Number (0–15000) | Scared/disappointed state window duration (ms) | 4000 / 6000 |
| `replies.feed` / `replies.play` | String array | Reply text pools for feed/play interactions (custom additions allowed) | Built-in 3 sentences each |

> The semantic layer (XP thresholds/level curves/title sets/memory limits) is not in the schema and cannot be overridden in configuration.

## FAQ

**Q: Why don't I see the pet after installation?**

A: Bundle plugins are synthesized when DSH starts, so you need to restart DSH Web after installation. On first install, you'll also enter the onboarding guide page where the pet is hidden by default; it appears after completing the guide.

**Q: Can it run simultaneously with the desktop companion?**

A: Yes. When running the desktop companion under `desktop/`, the web pet will automatically hide via presence heartbeat (restores after companion exits or crashes with 45s TTL expiration). If you don't want dual-display, set `whale-girl.enabled` to false in `settings.yaml` to disable the web pet.

**Q: Can I adjust seniority/titles/level curves?**

A: No. These are code-level sealed semantic layer constants (XP formula `50·L·(L−1)/2`, title sets, memory limits, etc.), schema intentionally doesn't expose them, guarded by the gate so config surface cannot reference them — only the visual/timing parameters in the experience layer table above are adjustable.

**Q: Where is data stored? Will it be lost on uninstall?**

A: State file is written to `<DSH_HOME>/data/whale-girl/state.json`, **not in the plugin directory**, so uninstalling the plugin won't delete seniority or memories; they continue accumulating after reinstallation.

**Q: Updates didn't take effect, what to do?**

A: Most changes (config surface, client behavior) require refreshing the page or restarting DSH Web to take effect; after modifying Node half source code, you must restart web because ESM secondary import to the same URL returns the old module.

**Q: How to add custom characters?**

A: Provide 15-state sprite sheets and manifest entries according to the asset full contract in `docs/adding-a-character.md` and `docs/sprites-spec.md`; character id limited to `[a-z0-9-]` (must be URL-path safe), locally run `node scripts/gates/verify-assets.mjs` for acceptance verification before plugin release.

## Difficulty Level
Beginner — install with one command to use; all experience layer parameters have defaults; enter advanced level only when wanting to customize characters or participate in development (requires understanding schemastery, Cordis plugin structure, and sprite asset specifications).

## Known Issues & Limitations
- After bundle format initial release, plugin path/export name cannot be renamed (public ref consumed), changing structure breaks installed environments
- Character id allows only `[a-z0-9-]` characters (URL path injection defense), naming needs attention
- Desktop companion is not within `dsh plugin` installation scope; requires self `npm install` + starting Tauri/headless engine in `desktop/` subdirectory
- After modifying Node half source code, ESM cache causes disable/enable to not take effect, must restart DSH Web (`plugin tree failed to load` is a clear signal of this issue)
- Although config modifications support hot-reload, initial injection still depends on synthesis at host startup; changing schema field names/defaults requires restart for old settings to re-normalize

---

This document is auto-generated by [deepseek-plugin.org](https://deepseek-plugin.org). HTML page: [whale-girl](https://deepseek-plugin.org/plugins/vlln/whale-girl)
Wiki generated by AI (model: `MiniMax-M2.5`)
