- Home
- Plugins
- UI Enhancements
- dsh-pet-progress
dsh-pet-progress
elefseus/dsh-pet-progress
Folds the durable todo and goal events the dsh pet ignores into a percentage bubble on the pet, and falls back to a one-line activity summary for a session that never wrote a todo list. Requires the dsh web pet plugin (@linxin666/dsh-pet >= 0.4.0).
Install
dsh plugin --profile web add github:elefseus/dsh-pet-progressREADME
dsh-pet-progress
English · 中文说明
A progress bar for your desktop pet.
The dsh web pet shows what the agent is doing right now — thinking, calling a tool, done. It has no way to show how much of a long task is finished, so a task that is 90% done looks exactly like one that just started.
This plugin fixes that. It reads the todo lists and goals your agent already writes to the session, and folds them into a percentage bubble on the pet. A session that never writes a todo list isn't left blank either — there the bubble falls back to a plain line saying what is happening right now.
Install
One command, using the plugin's full GitHub URL:
dsh plugin add https://github.com/Elefseus/dsh-pet-progress
This requires the dsh web pet to be installed. If it is missing, the plugin stays loaded but publishes nothing — you'll see a note in the dsh log rather than a crash.
Restart DSH afterwards — bundles are read only at startup, so the plugin won't mount until you do. The bubble then appears on its own the next time your agent writes a todo list or starts a goal; there is nothing to switch on.
For a named profile, use dsh plugin --profile <name> add ….
What you'll see
A small bubble above the pet, updated whenever the todo list or the goal changes:
| Situation | Bubble |
|---|---|
| Todo list, one task in progress | 3/7 · 43% titled with that task |
| Todo list, several tasks in progress | 3/7 · 43%, naming them — up to three, +N for the rest |
| All todos done | 任务全部完成 in green — a moment, gone after about 10 seconds |
| Long-lived goal with no todos | 2/8 轮 — the goal's round budget |
| Goal finished | 目标完成 in green — also a moment |
| Goal blocked | The block reason, in place of progress |
| No todo list and no goal | A plain line with no percentage — what the model is thinking (正在思考), the words it is writing (最近输出), or what the tool it just called is for (当前过程) |
A standing bubble fades out about 30 seconds after the last progress update, so a finished turn doesn't leave a stale percentage on screen; it comes back by itself if the work resumes. A moment — a finished list or a finished goal — is announced once and never renewed, so it clears itself instead of sitting there; it also keeps the bubble for those ten seconds, because the agent usually starts talking again immediately and would otherwise replace it before you read it.
Several sessions can be open at once — the most recently active one owns the bubble.
Checking the full list
The bubble is one line, so there's a button for the rest: click 进度 on the pet panel and the complete todo list is written to the dsh log.
Good to know
- It never over-reports. A todo whose status the plugin doesn't recognise counts as not done. If every entry in a write is unreadable, the plugin treats it as "no information" and keeps what it had.
- It won't guess. It names the tasks that are actually in progress — up to
three, each trimmed to 32 characters, with
+Nwhen more are running. It never picks one of several and pretends that one is the work. - It reads, it doesn't judge. A percentage comes from the todo lists and goals your agent writes; the plugin never infers progress from how long something has been running. Without either, it shows the plain activity line instead of a number.
- It says what is happening, not just which phase. With no task list it
follows the model's own words as they stream — the thinking first, then the
answer, newest words only, since those are the ones that say what is going on
now — and it names what a tool call is for (
正在调用 pwsh:npm test,正在调用 read:progress.ts), not only that a tool is running.
Requirements
| DSH | >=0.1.7-rc.1 |
@linxin666/dsh-pet | >=0.4.0 (peer) |
| Node | ^22.19.0 || >=24.0.0 |
The plugin binds to the pet's plugin-seam contract (announce,
registerPanelAction, and the session/event channel); an older pet does not
expose all three.
Configuration
apply(ctx, { enabled?: boolean, heartbeatMs?: number })
With enabled: false nothing mounts. heartbeatMs defaults to 10000.
Using it from code
The plugin is host-only (no client bundle). The pet service is available as
ctx.pet, and the same three seams the pet publishes are what this plugin uses:
| Seam | Used for |
|---|---|
ctx.on('session/event', …) | Reading todo/write, goal/change, and the turn/step/tool/message events behind the activity line |
ctx.pet.announce(…) | Publishing the progress bubble |
ctx.pet.registerPanelAction(…) | The 进度 panel button |
Adjust PROGRESS_TTL_MS and MAX_TRACKED_SESSIONS in
src/progress.ts to change the fade-out and how many sessions
are tracked at once.
Development
src/*.ts is the source of truth; lib/ is committed build output, because the
cordis loader does no transpilation. After editing src/, rebuild and commit
lib/ with it — CI fails if the two drift apart.
node build.mjs # rebuild lib/ from src/
node --test src/*.test.ts # 76 tests, node:test only
To work on the code, skip installing and point the profile at your checkout:
// ~/.dsh/profiles/<profile>/package.json
{
"dependencies": { "dsh-pet-progress": "file:<absolute path to this directory>" },
"dsh": { "profile": { "bundles": ["…existing…", "dsh-pet-progress"] } }
}
A bundles entry alone is not enough — the package must also be a dependency.
If the path contains non-ASCII characters, write it as a file:// URL. Restart
the app afterwards.
Node is pinned in package.json engines and exercised in CI at 22.19.0 and
24.x.
dsh plugin --profile desktop up dsh-pet-progress # update to latest default branch
dsh plugin --profile desktop add "<repo>#<tag>" # pin a tag instead (reproducible)
More
- Design notes — why the plugin is built this way: the event gap it fills, why it's a sibling rather than a patch, what it reports, and the two non-obvious details (deferred mounting, and an announcement slot with no retract).
MIT
Related plugins
dsh-web (dsh-task-board)
zhu1090093659/dsh-web
dsh-web (dsh-web-all)
zhu1090093659/dsh-web
dsh-web-ui (dsh-task-board)
zhu1090093659/dsh-web-ui
dsh-web-ui (dsh-web-ui-all)
zhu1090093659/dsh-web-ui