Back to home

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:

  • Manifestpet.json (legacy avatar.json also accepted) with id, displayName, description, spritesheetPath (default spritesheet.webp), frame (default 192×208, 8 columns × 9 rows), and animations (frames sprite indices, fps default 8, loop default true, fallback default idle). spriteVersionNumber: 2 (the Codex app sheet format) widens the default grid to 11 rows; other unknown fields such as kind are 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 to idle after their duration, and a missing state track falls back to idle — 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-pets cache.
  • Local pets$DSH_HOME/pets/<id>/ (writable; the import target).
  • Codex-home pets~/.codex/pets/<id>/ and legacy ~/.codex/avatars/<id>/ (CODEX_HOME respected), 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 own spritesheetPath and 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-pet directory (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 overlayshell.overlay entry pet: the sprite plays running while the current session runs, waiting when an interaction (approval, question, plan review) blocks it, review for a few seconds after a running→idle edge, and idle otherwise, 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 through running to 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 name plus 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 inject hooks compartment, so no component carries subscription machinery.
  • Settings pagesettings.section entry pet: catalog browsing with static previews, size options (小/中/大 = 94/117/150 px target sprite heights), .codex-pet directory 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 useSessions feed (running bit, pending interaction, and the running→idle edge), so a per-turn error has no dedicated failed animation 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-pet folder 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-leveldsh plugin --profile <name> remove dsh-codex-compatible-pet removes 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).