Bundle
dsh-codex-compatible-pet
Codex-compatible desktop pet for the DeepSeek Harness web GUI: animated pets that follow the agent state
- Source
- youzhoujiMrLiu
- stars
- 1 stars
- License
- MIT
- Updated
- Updated 5 days ago
Readme
# dsh-codex-compatible-pet English | [中文](README.zh.md) 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` (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 overlay** — `shell.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 page** — `settings.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: ```text 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-level** — `dsh 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).
Install
dsh plugin --profile web add github:youzhoujiMrLiu/dsh-codex-compatible-pet
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-codex-compatible-pet from the hub
- This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.