@nkj/dsh-ui-pet
A canvas pet for the DeepSeek Harness web GUI. It follows the pointer and is styled as a subtle background decoration in the shell.overlay layer: position:fixed (no layout impact), fully click-through (pointer-events:none), a low z-index (below other overlay entries and dialogs), and < 1 opacity so the page content shows through — visible without covering or blocking the real UI. v1 is presentation-only (pointer follow) with a procedurally-drawn vector mascot; a later version reacts to session / agent activity.
How it plugs in
The package is a dsh bundle (dsh.bundle → cordis.patch.yml) that is also a client plugin (dsh.client). Installing it into a profile with dsh plugin --profile web add <pkg> auto-registers it (the CLI reconciles installed dependencies that declare dsh.bundle into dsh.profile.bundles), then the client module system serves /plugins/@nkj/dsh-ui-pet/client.js on the next boot. No manual cordis.yml edit.
Built-in dev loop
# once: install build deps
pnpm install
# build both artifacts (lib/index.js host half + lib/client.js browser bundle)
pnpm run build
# iterate: rebuild the browser bundle on source change (the dsh host stat-polls
# the served bundle and broadcasts a reload, so the browser refreshes on write)
pnpm exec tsdown --watch
Verify locally (before publishing)
dsh plugin --profile web add /absolute/path/to/dsh-ui-pet
pnpm dsh web # bind http://127.0.0.1:3080
In the browser at http://127.0.0.1:3080, confirm:
- In the tree —
dsh --profile web --dump-config contains the ui-pet row.
- Bundle served — DevTools → Network shows
/plugins/@nkj/dsh-ui-pet/client.js (200); or curl http://127.0.0.1:3080/plugins/@nkj/dsh-ui-pet/client.js.
- Rendered, and visible — DevTools → Elements: the
<canvas> is inside the shell.overlay layer, position:fixed, pointer-events:none, low z-index, and opacity < 1. Move the pointer; the pet follows it, and the page content remains visible through the semi-transparent pet (it never blocks or covers the UI).
- Behavior — move the pointer; the pet follows it. The overlay does not block clicks (the layer and canvas are
pointer-events:none).
While SPRITE is empty in src/client/sprite.ts, the pet draws a colorful placeholder blob, so step 4 is verifiable without any asset.
Publish
pnpm run build
npm pack # confirm lib/, cordis.patch.yml, and src are in the tarball
npm publish --access public
After publishing, a user installs it with:
dsh plugin --profile web add @nkj/dsh-ui-pet
Customizing the pet
Model Experience
None. The pet manages browser-only presentation; nothing reaches a model request.
KV Cache effect
None; this package neither assembles nor sends a provider request.
Target version
Runtime-compatible with dsh 0.1.1-rc.2 (the web profile). The host dsh install supplies the runtime react, @deepseek-ai/cordis, and the slots service.
The published package is intentionally build-dependency-free: the source uses no @deepseek-ai/* imports (the DSH-specific types are left structural/untyped), so the standalone build needs only react + tsdown + typescript. The DSH integration is by convention: apply receives a ctx with a slots service, and the bundle is the standard window.__ModuleLoader__.load closure factory.
Known Limitations and Deferred Work
- v1 is pointer-follow only. Reacting to session / agent streaming (the asset/activity animation) is deferred: the pet can read the active session through the standing runtime hooks the
shell.overlay slot provides.
- The pet lives in the
shell.overlay floating layer, so it paints above the app content (it is deliberately semi-transparent and small so it does not obscure it). Rendering it genuinely behind the content is impossible from a plugin without DSH source changes: the conversation/details/sidebar surfaces are opaque and would fully cover a behind-content canvas.
- The
ctx / slot types are structural and untyped to keep the standalone build self-contained. When developing inside the dsh monorepo, restore the real ClientContext / PropsRuntime<'shell.overlay'> types for full checking.
- The bundle format (closure factory + React externalization) is reproduced from the dsh
clientBundle preset; iterate against a live dsh web to confirm exact output.