youzhoujiMrLiu
dsh-codex-compatible-pet
Codex-compatible desktop pet for the DeepSeek Harness web GUI: animated pets that follow the agent state|兼容 Codex 格式的 DSH 桌面宠物:随智能体状态变化的动画宠物
- Stars
- 0
- Language
- TypeScript
- Created
- Aug 16, 2026
- Updated
- Aug 16, 2026
Introduction
dsh-codex-compatible-pet
English | 中文
Desktop pet plugin: a codex-compatible animated pet that lives at the bottom-right of the Web GUI and follows the agent state. It is a dual-face client plugin — the node half serves pet files over HTTP, the browser half renders the sprite and the settings page.
Pet model (codex compatibility)
The pet model is ported from codex-rs (tui/src/pets/model.rs), so existing codex pets work unchanged:
- Manifest —
pet.json(legacyavatar.jsonalso accepted) withid,displayName,description,spritesheetPath(defaultspritesheet.webp),frame(default 192×208, 8 columns × 9 rows), andanimations(framessprite indices,fpsdefault 8,loopdefault true,fallbackdefaultidle).spriteVersionNumber: 2(the Codex app sheet format) widens the default grid to 11 rows; other unknown fields such askindare ignored exactly like the codex parser ignores them. - Animation math — row-major sprite grids; pets on the default frame spec without custom tracks (built-ins, and standard 8×9 or version-2 8×11 sheets) play the full codex state table (
running,waiting,review,failed, …), while custom grids or custom tracks keep the codex idle-only rule — the Codex app behavior, which keeps standard sheets animating instead of motionless. Loop tracks use the prefix-then-loop timing, one-shot tracks fall back toidleafter their duration, and a missing state track falls back toidle— all identical to codex ambient playback.
Pet sources
- Built-in pets — the codex catalog (Codex, Dewey, Fireball, Rocky, Seedy, Stacky, BSOD, Null Signal) proxied from the public Codex pets CDN through the host with a validating
$DSH_HOME/cache/dsh-petscache. - Local pets —
$DSH_HOME/pets/<id>/(writable; the import target). - Codex-home pets —
~/.codex/pets/<id>/and legacy~/.codex/avatars/<id>/(CODEX_HOMErespected), scanned read-only so pets installed for Codex appear automatically.
Host half (routes under /dsh-pet)
GET /dsh-pet/list— built-in catalog plus directory pets (broken manifests stay listed as disabled rows).GET /dsh-pet/manifest/<source>/<id>— a pet's raw manifest JSON.GET /dsh-pet/asset/<source>/<id>/<name>— a pet's spritesheet; the name must be the manifest's ownspritesheetPathand stays inside the pet directory.GET /dsh-pet/builtin/<file>— CDN proxy over a filename whitelist with a 4 MB cap and WebP validation.POST /dsh-pet/import— imports a browser-picked.codex-petdirectory (manifest plus base64 spritesheet); the frame grid must cover the WebP canvas exactly (the codex validation), and the write is staged then renamed.
Every route sits behind a browser trust fence (loopback plus configured trustedHosts), the same shape as the /api fence. Ids and asset names are pattern-restricted, so path traversal is rejected at the route layer.
Browser half
- Ambient overlay —
shell.overlayentrypet: the sprite playsrunningwhile the current session runs,waitingwhen an interaction (approval, question, plan review) blocks it,reviewfor a few seconds after a running→idle edge, andidleotherwise, with a status bubble (思考中 / 等待确认 / 已完成). Clicking the pet plays the first available interaction track (wave,bounce,jumping,waving); dragging it with the mouse moves it anywhere and plays the direction-matched run animation (running-right/running-left, falling back throughrunningto the status track) — a 4 px threshold separates drags from clicks, and the position persists in the store. Reduced-motion users see a static first frame. - Hover detail card — hovering the pet shows what the agent is doing right now, codex-style and truncated: the latest user prompt as a larger bold title, the running tool call (
tool nameplus a compact args head), the head of the latest assistant output (streaming text preferred), and the pending interaction kind. Long text keeps its head and ends with a trailing ellipsis. The facts derive from the object layer — the sessions list plus the current session binding — as one bare observable delivered through the injecthookscompartment, so no component carries subscription machinery. - Settings page —
settings.sectionentrypet: catalog browsing with static previews, size options (小/中/大 = 94/117/150 px target sprite heights),.codex-petdirectory import, and the disable control. - Persistence — the selection, size, and drag offset live in the framework store engine under
dsh.pet(localStorage).
Install
This package is a dsh bundle: its dsh.bundle manifest inserts the ui-pet row into any profile that lists the package, and its dsh.client manifest plus lib/client.js carry the browser half for the Web GUI.
The easiest install is to let an agent do it — DeepSeek Harness itself, or any agent with terminal access to a machine that has the dsh CLI and can reach this repository. Paste this prompt:
Install the dsh-codex-compatible-pet plugin from https://github.com/youzhoujiMrLiu/dsh-codex-compatible-pet for me.
1. Run `dsh plugin add github:youzhoujiMrLiu/dsh-codex-compatible-pet` (add `--profile <name>` to target a specific profile).
2. pnpm ≥10 refuses git-dependency build scripts on the first attempt: copy the package key it prints into the profile's `pnpm-workspace.yaml` `allowBuilds` block and re-run the add.
3. Verify the row `ui-pet` shows up in the profile composition (`dsh --profile <name> --dump-config`) or on the Web GUI's Plugins page.
4. In the Web GUI, refresh the page — the pet appears at the bottom-right and a Pet page appears under Settings. After any server restart, refresh again.
Trust note: a git install runs this package's `prepare` build on the installing machine; pin a commit (`github:youzhoujiMrLiu/dsh-codex-compatible-pet#<sha>`) if you want a fixed revision.
Under the hood the agent runs the ordinary git-install path: prepare builds lib/ from src/ after the install and is self-contained — it assumes no monorepo checkout.
Model Experience
None, as the plugin changes browser presentation only and registers no prompt, tool, schema, session event, or provider request.
KV Cache effect
None; this package neither assembles nor sends a provider request.
Known Limitations and Deferred Work
- Status source is the session list — the pet derives its status from the standard
useSessionsfeed (running bit, pending interaction, and the running→idle edge), so a per-turn error has no dedicatedfailedanimation yet; failed turns fall back to the review reminder and idle. The detail card's activity text does come from the current session's conversation window. - Built-ins need the first download — a built-in pet fetches its spritesheet from the Codex CDN on first selection and shows nothing until that download completes.
- Import is the only write path — dropping a
.codex-petfolder into$DSH_HOME/pets/<id>/by hand also works, but there is no in-app re-scan button beyond reopening the settings page. - Uninstall is composition-level —
dsh plugin --profile <name> remove dsh-codex-compatible-petremoves both the dependency and the inserted layer; there is no runtime toggle. A row inserted by a user-installed bundle does not yet appear under the Custom plugins tab (that classification currently recognizes user patch layers only).