01Virex/dsh-status-rotator

01Virex/dsh-status-rotator

把 dsh 回合状态行换成 1059 条中英文案的轮播:打字机输出、流动彩虹渐变、弹幕、12 个可开关的主题词库包、实时占位符与标签页标题轮换。两个 star 包默认关闭;星标者包每位星标者一条文案,由工作流每周刷新。

UI 增强dsh

dsh-status-rotator

Give DSH's running status your own voice: custom phrases, typewriter output, day/night gradients, danmaku and an optional animated whale tail. Ships 1379 phrases, 14 theme packs; choose which packs to enable.

English | 中文 · Effects · Install · Reference · Changelog

A DeepSeek Harness (DSH) client plugin that replaces Deep diving... / 深度求索中... with editable phrases while preserving the host's elapsed-time clock.

Effect preview

Status text and light/dark gradients

Phrase rotation · Typewriter · Light/dark gradients · Official whale-tail sway. Captured from the actual plugin in a minimal DSH host, using sample phrases and an enlarged status row. Static preview.

Whale-tail animations

Reading left to right, top to bottom: Official sway → Flipping tail → Sway → Twist. Official sway uses its recommended 4-second cycle; the other three use 0.5 cycles/s. The icon containers stay fixed while the contours deform. Static comparison.

These actions ship in v0.35.0. Under Appearance → Whale tail, enable both Keep the whale tail and Tail motion, then choose the flipping tail, 24-frame sway, 36-frame twist, 150-frame official original sway, or random switching. Existing configurations without animation keep the flipping tail.

Choice · Behavior Official sway · 150-frame action, recommended speed one cycle every 4 seconds Flipping tail / Sway / Twist · Fixed speed or estimated tok/s; default level 3 tops out at 1.5 cycles/s Random switching · Select an action pool shared by timed switching and optional tool-call triggers

Speed presets have 2–5 levels; custom tok/s maximums range from 1–10 cycles/s. The official action keeps its recommended speed unless you disable that option.

Speed settings, action pools and tool-call triggers.

Appearance themes and danmaku

Classic / Neon / Terminal / Candy / Glitch set the font, glow, animation and gradient together. Pick a theme, then adjust its individual options. Theme parameters.

Danmaku supports scrolling, top and bottom placement. Optional hover-pause, click-to-copy, phase colors and adaptive density are available in Settings. This is a captured frame with enlarged text and higher opacity for readability. Danmaku parameters.

Installation

Install from npm through the Desktop plugin manager, or use dsh plugin add for Web. Restart the corresponding host after the first install.

Desktop npm walkthrough

DSH Desktop can install directly from npm without cloning this repository. The screenshots below show DSH Desktop 0.2.0-rc.2 with a Chinese interface; layouts may differ between host versions.

  1. Open DSH Desktop, select Plugins (插件) in the sidebar, then click Add plugin (添加插件) at the top right.
  2. Enter this in the Package name or address (包名或地址) field:
dsh-status-rotator

Choose an Install source (安装源) suitable for your network. The screenshot uses the Mainland China mirror. Click Install (安装); Desktop downloads the npm package and registers the plugin.

  1. Wait for installation to finish. Find dsh-status-rotator under Installed (已安装) and confirm that its enable switch is on. Follow any restart prompt; if the settings page has not appeared, fully exit Desktop, including its tray process, and reopen it.
  2. Open the account menu at the bottom left, then Settings → Status Texts (设置 → 状态文案). Choose packs or edit phrases. For tail motion, enable Keep the whale tail and Tail motion under Appearance → Whale tail. Settings save automatically; start a new turn to see the status line.

Install the npm package from the command line

dsh plugin --profile desktop add dsh-status-rotator

Restart DSH Desktop afterward. Desktop uses the desktop profile; if your terminal cannot find dsh, use the Desktop installation dialog above.

Quick start

For Web, run:

dsh plugin --profile web add dsh-status-rotator

Restart dsh web, then open Settings → Status Texts and start a turn. For Desktop, use the npm walkthrough above or its command-line alternative. Later settings changes save and apply automatically; restart the corresponding host after upgrading plugin code.

The whale tail and tail motion start off; enable them under Appearance → Whale tail. Danmaku starts on and can be disabled under Appearance → Danmaku.

Other installation methods and first-run behavior

Option A: dsh plugin add (recommended)

The plugin's package.json declares a dsh.bundle.patch manifest, so it is recognized automatically after install — no extra flags needed. The command syntax is dsh plugin --profile add (e.g. --profile web):

  • From npm (easiest): dsh plugin --profile web add dsh-status-rotator ← always installs the latest release
  • For DSH Desktop: dsh plugin --profile desktop add dsh-status-rotator (the desktop build's profile is desktop)
  • From a clone: dsh plugin --profile web add ./dsh-status-rotator
  • From a release package: download dsh-status-rotator-.zip from the Release page (it contains a ready-to-use plugin directory with config.json — not an npm tarball), unzip it, then dsh plugin --profile web add /path/to/dsh-status-rotator.

Manual installation

Option B: manual install

  1. Put this project directory under your profile's node_modules (default C:\Users\.dsh\profiles\node_modules\dsh-status-rotator);
  2. Insert the following into the profile's cordis.patch.yml:
- insert:
       - id: status-rotator
         name: dsh-status-rotator
  1. Run node gen-config.cjs to initialize the local config.json (copied from config.example.json);
  2. Restart dsh web and hard-refresh the browser with Ctrl+F5.

First run

On first start the plugin serves, in order: your saved settings ($DSH_HOME/status-rotator/config.json) → the package config.json → config.example.json (what an npm install has: all 1379 default phrases live inside it, see Phrase Bank). Two more layers join in: the auto-updated bank (every 6 hours, see Auto-updating the bank) and the optional external bank ($DSH_HOME/status-rotator/phrases.json, highest priority, see Hot-reloadable external bank). Edit files directly (hot-reloaded while a page is open) or use the Settings → Status Texts page of DSH.

Host version details and isolated testing

Status line as of dsh 0.1.7: the host moved it into the turn's fold header button[data-turn-process] (Deep diving for 12s), which scrolls out of view in a long turn. The plugin moves the line back above the input box, styled like dsh ≤0.1.6's .turnStatus (26px, shimmer, 13px clock) and pinned with the composer; the header copy is hidden and returns when the turn ends. Duration and phase come from reading the header label (never writing into it). On 0.1.6 and older the role="status" line already sits there and behaves as before.
Status line as of dsh 0.2.0: while a turn runs the host no longer keeps the text inside the fold header — it renders a separate row in the conversation flow, div[data-chat-running] (hidden announcement + divider + DeepSeek whale-tail icon + shimmer text), and button[data-turn-process] now only renders once the turn is closed. The plugin gained a matching host path: it adopts that row (writes its phrase into it, hides the host's own shimmer text, still reads the duration from the host text) with the same position and look, and leaves the screen-reader announcement untouched. `whaleTail` (off by default) keeps the whale tail in that row, next to the plugin's phrase, and animates it with the rainbow-gradient palette. The separate tail-wagging switch can follow tok/s or use a fixed speed; enabling that switch explicitly opts in to the wag.
Starting an isolated test instance (without touching your daily profile): install a dsh version into a temp dir and boot a profile with its own DSH_HOME — DSH_HOME=/tmp/dsh-test node /tmp/dsh-test/node_modules/.bin/dsh test020 --from-default-profile web --no-open --port 3081, then dsh plugin --profile test020 add . That instance's config store, bank and settings live inside its own DSH_HOME, so your daily instance is untouched.
Never a blank line: config.labelSource (default "phrases") decides the text; with an empty bank the plugin's line falls back to the host text instead of rendering an empty row. Set it to "host" to drop rotation and get the verbatim 0.1.6 .turnStatus look (weight 500, inline-flex, 26px, shimmer, clock after 15s).

Feature Overview

What to customize · What you can do Status text · Rotate by thinking, running and long-task phases; typewriter output, weighted picks and an anti-repeat shuffle bag Phrase content · Toggle and edit packs; use conditions, live placeholders and Chinese/English text Appearance · Light/dark gradients, appearance themes, danmaku with optional hover-pause and click-to-copy, and whale-tail motion Daily workflow · Schedule presets by weekday and time; optionally rotate the browser tab title Saving and updates · Store settings outside the package; hot-apply config changes and report conflicting settings-page writes Plugin integration · Register packs, placeholders and dynamic phrases, or send danmaku through ctx.statusRotator

Next step · Go to Choose content and appearance · Settings · Phrase bank · Whale tail Write your own phrases · Packs · Conditions · Placeholders Manage files and bank updates · Configuration · Installation Contribute or develop · Phrase submissions · Extension API · Testing

Settings Page

Open Settings → Status Texts. Content, Appearance, Behavior and Automation organize the controls; changes save automatically.

Controls and save behavior

Open Settings in the bottom-left of DSH and a new Status Texts page appears in the navigation. The page is split into four tabs and follows the official plugin settings-page spec (760px column, the same tab / field / input language):

Content

  • Edit target — one selector covering the base library, any preset (preset:) and any phrase pack (pack:); saving writes to that target. A target that no longer exists (preset or pack deleted) falls back to the base library;
  • 中文 / English tabs, each with three text boxes for thinking / running / long, one phrase per line, blank lines ignored; a line text | weight sets that phrase's weight; each phase shows its phrase count;
  • Pack toggles — ten theme packs ship enabled; community, ads and both star packs ship disabled;
  • Presets — pick a preset, New to create one, edit its name inline (stored per editing language), Delete to remove it (schedule rules referencing it go with it), and "Set active" to write activePreset.

Appearance

  • Font weight, shared by the status line and danmaku;
  • Rainbow gradient: enable toggle, palette mode (follow the interface light/dark, or force day/night), flow direction (right-to-left / left-to-right), separate day + night color sequences, flow speed;
  • Danmaku: enable toggle, spawn interval, cross duration, random font-size range, rainbow mode + palette, opacity, max concurrent bullets, layer z-index and phrase scope.

Behavior

  • Rotation interval, typewriter speed, long-task threshold, auto-reload interval, placeholder refresh interval, weighted-random toggle.

Automation

  • Schedule editor: add/remove weekday + time-window rules that switch presets automatically; the currently effective preset (schedule included) is shown live.

Across the page:

  • Changes save themselves: toggles and selects write immediately, text/number fields 400ms after you stop typing (a preset rename on blur) — no save button, and only a failed write turns the toolbar red;
  • Every write PUTs the full JSON to /plugins/dsh-status-rotator/config.json; the node half validates and writes it back atomically, and open pages hot-apply it — invalid content returns 400 and shows an error instead of corrupting the file;
  • Switching the edit target or hitting Reload flushes drafts first (nothing is silently dropped); numeric fields are validated as you type with a Reset action when a value differs from its default; the footer links back to the source repo.

After upgrading to a version with the settings page, restart dsh web once (so the node half registers the write endpoint); everything after that can be done from the page.

Whale-tail settings

Speed settings, random switching and tool-call triggers

Recommended official speed. officialRecommendedSpeed defaults to true. Official sway uses 0.25 cycles/s (one cycle every 4 seconds) in fixed, tok/s, random and tool-triggered playback. Other actions restore the user’s speed automatically. Turn this switch off to apply the common speed settings to official sway too.

Speed levels. Levels 2–5 are speed presets with maximums of 1.0 / 1.5 / 2.0 / 2.5 cycles/s: higher levels move faster at high output rates. For other actions, every level has a minimum of 1 cycle/s; level 3 uses 1.00 / 1.25 / 1.50. Selecting a level restores its maximum. Editing a level’s maximum shows Custom rather than mislabeling it as a preset. Continuous mode retains its own maximum. Boundaries have a deadband of about 4.8 tok/s on each side. Explicit maximums in old configurations remain effective and show Custom when they do not match a preset.

Random mode requests a switch every 4–8 seconds, choosing a different action only from randomActions. It waits for the current loop junction and uses six contour bridge frames. A single selected action keeps playing without redundant transitions. Tool-call triggers use the same pool. All four actions share speed and gradient settings. Hidden pages pause playback; turn end, disabling or unloading releases contours and listeners.

Speed changes preserve animation progress to avoid jumping frames. Rebuilt host icons recover the current action, speed, and gradient; random mode also retains its switching schedule. These ideas were inspired by dsh-whale-sway; see the adaptation notes.

Rebuilt icons restore their within-cycle progress. A six-frame bridge already in flight also resumes its original target and progress. Temporary icon gaps retain a playback snapshot until the row is released, without holding the old DOM nodes.

Tool-call triggers: enable “Randomly switch on tool calls” in the same settings group. It defaults to off with a 35% chance, configurable from 0–100%. Each new tool/call in the current session is checked once; history, paging, repeated notifications, and streamed arguments do not trigger it. Hits switch to a different action at the junction through six bridge frames; consecutive hits share one pending request. This works with fixed actions and timed random mode. A tool-triggered replacement of a fixed action remains until another trigger, an action selection change, or disabling this option. Disabling it restores the selected action at a junction. Hosts without the event source simply skip this feature.

"whaleTail": true,
"whaleTailMotion": {
    "enabled": true,
    "animation": "random",
    "toolSwitchEnabled": true,
    "toolSwitchChance": 0.35,
    "mode": "tps",
    "fixedSpeed": 1.5,
    "tpsTiers": 3,
    "officialRecommendedSpeed": true,
    "randomActions": ["wag", "official"]
}

For local development, open the action preview to try all actions, random switching, and fixed speed using the actual plugin. Run npm test, npm run test:browser:turn-process, and npm run test:browser:settings to check configuration, bridges, speed, persistence, and cleanup.

The preview also has a “Simulate a tool call” button. Select a fixed action and set the chance to 100% to inspect tool-triggered switches, then use 0% as a no-trigger comparison.

Below the tool-trigger controls, connection status and live counts show new calls, probability hits, and switches started. Counts begin when the plugin connects to the current session; history is not replayed. New hosts use the main conversation's data-conversation-session, including when the right sidebar is closed. Delayed or replaced bindings are retried. Hits while the page is hidden stay queued and play at a junction after the page becomes visible.

Pending requests belong to the current session: calls arriving before the icon still undergo the probability check and are consumed when the icon appears. Same-session reconnects retain the tool-selected action and pending requests. Ending the corresponding turn, disabling the feature, changing logical sessions, or unloading clears the queue so requests cannot leak into a later turn.

How It Works