dsh-web-icon-indicator
Browser tab favicon reflects the current DSH session state — idle / running / asking / done — so you can see at a glance whether a session needs your attention, even when the tab is in the background.
States
| State | Preview | Visual · Icon | Animation |
|---|---|---|---|
idle |
Original DeepSeek whale (default favicon) | — | |
running |
Yellow whale | Static | |
asking |
Yellow ⇄ red | 400 ms blink | |
done |
Green whale | Static for 5 s, then back to idle |
The four SVG icons live in icons/ beside the package. Edit them to match your brand; the plugin re-reads them on every request, so any change is live as soon as the browser tab polls again.
Install
This is a standard DSH bundle plugin. Install it into the web profile (the GUI/TUI profiles pick it up automatically through the cordis patch layer).
From npm (recommended — published as dsh-web-icon-indicator@0.1.0):
dsh plugin --profile web add dsh-web-icon-indicator
From the Git source:
dsh plugin --profile web add github:waknow/dsh-web-icon-indicator
Or from a local directory / tarball:
dsh plugin --profile web add <path-or-tarball>
Or drop the directory into ~/.dsh/profiles/web/node_modules/<name>/ and ship a cordis.patch.yml that matches the one shipped here.
Configure
All keys are optional; defaults shown.
| Key | Default | Meaning |
|---|---|---|
iconsDir |
<package>/icons/ |
Directory of the four *.svg files |
statusPath |
/dsh-web-icon-status.json |
JSON status endpoint |
iconPathPrefix |
/dsh-web-icon-indicator |
URL prefix the four SVGs are served under |
askingHoldMs |
3500 |
Minimum visibility of the asking icon |
askingBlinkMs |
400 |
Yellow/red blink interval |
doneHoldMs |
5000 |
Time the done icon stays |
Override from your composition row:
- id: dsh-web-icon-indicator
name: 'dsh-web-icon-indicator'
config:
askingBlinkMs: 320
doneHoldMs: 4000
How it works
- Host-only plugin: registers three routes on the existing
webServer(status JSON,/dsh-web-icon-indicator/*.svg, and onetapIndexto inject a small browser script into every servedindex.html). - Status is aggregated across live
agents.list()with priorityasking > running > done > idle. The aggregation runs areconcile()step on every request to detect running → idle transitions, becauseagent/status's idle delivery is not guaranteed at turn end. ask_user_questiontool calls (viatools/pre-execute/tools/result) flip the session intoaskingwith a configurable minimum-hold so the icon stays visible even when the user answers immediately.- Permission / sandbox-interception waits are also surfaced as
asking: when the agent hits a sandbox denial and escalates (sandbox_permissions+justification), or any other tool asks for approval, the approval service appends anapproval/askedsession event and blocks the agent until you decide. The plugin watchessession/event(with an authoritative fold over the live session log as a fallback) and pins the session into the blinkingaskingstate for that whole wait, clearing it onapproval/decided. - The browser script polls
/dsh-web-icon-status.jsononce a second and sets<link rel="icon">'shrefto adata:image/svg+xml,…URI. Browsers don't play SVG favicon CSS animations, so the four icons are static SVGs and theaskingblink is driven by the script swapping between yellow and red frames everyaskingBlinkMs.
Caveats
- Favicon SVG CSS animations do not run inside the browser's tab UI — the four shipped icons are static for that reason. Open the SVG files directly in a viewer to see the full design.
- The plugin runs in the host plane; it must be mounted into a profile's composition, not a session-scoped agent preset.
- File reads go through the
fsservice with the configurediconsDirascwd. Make sure that path is readable under your deployment's sandbox policy.
License
MIT
No comments yet. Be the first to write one.