# dsh-turn-status-text English | [中文](README.md) Replaces the **"Deep diving for 12s ···"** line in the DSH (DeepSeek Harness) chat area with text you write yourself and a colour you pick, from **sidebar → Plugins → select this plugin → configure** — save and it applies immediately, no page reload. | Default | Customised | | --- | --- | | ![Default status line](docs/before.png) | ![Custom status line](docs/after.png) | Both images are real screenshots from the same machine: the left is the deployment as shipped (`深度求索中,用时 6分29秒 ···`), the right swaps the text for `硬邦邦思考中…` and the colour for `#ff5500` (the whale mark on the left and the shimmer on the right change colour with it). Keep `{duration}` in your text and the live elapsed time stays: ![Custom status line keeping the elapsed time](docs/after-duration.png) ## What you can change | What | Details | | --- | --- | | Text | Any text. Include the `{duration}` placeholder to keep the live elapsed time, e.g. `Thinking hard… {duration}` → `Thinking hard… 12s`; without the placeholder the line shows nothing but your text. | | Colour | Type a colour code, `#4d6bfe` or `#abc`. The whole row takes the colour — the text, the whale mark to its left, and the text's shimmer all follow (see below for why). | | Reset to default | One control per field: clear the draft and save, and the text goes back to the copy the deployment ships while the colour goes back to the theme colour. | The Host writes the changes into the current profile's `cordis.patch.yml`, appending a `config:` section to this row (this is what actually lands on disk), so they survive a browser switch and a restart; the plugin makes no network calls and registers nothing the model can see. ```yaml - id: dsh-turn-status-text name: "@dsh-external/dsh-turn-status-text" config: text: 宝宝正在努力思考… {duration} color: "#ff5500" ``` Only the **in-progress line** changes. The `Completed in …` summary after a turn finishes, `Failed`, and the rest stay exactly as shipped. ## Install From GitHub (the repository ships the built `lib/` and **deliberately declares no `prepare` script**, so pnpm will not ask you to approve build permissions): ```bash dsh plugin --profile add github:WONGIII/dsh-turn-status-text ``` From a local checkout: ```bash git clone https://github.com/WONGIII/dsh-turn-status-text.git dsh plugin --profile add ./dsh-turn-status-text ``` On the desktop app you can also paste that GitHub URL straight into the **Plugins** page in the sidebar. > Replace `` with your own profile name (commonly `web` for `dsh web`). > The desktop app's own profile is managed exclusively by the Electron application — the CLI refuses it with > `profile "desktop" is managed exclusively by the Electron application` — so install and uninstall from the sidebar > **Plugins** page there. **DSH has to be restarted once after installing** (`dsh web` or the desktop app). The plugin row is a host-side Loader row, and the browser half is served from it; only a fresh composition of the configuration mounts a new Loader row — refreshing the page is not enough. (The configuration file itself is "live" at runtime, but the settings namespace directory a **new** row depends on only includes it after that recomposition.) Once installed, `@dsh-external/dsh-turn-status-text` shows up in the sidebar under **Plugins → Installed**; expand it to toggle the `dsh-turn-status-text` row on its own. Uninstall: ```bash dsh plugin --profile remove @dsh-external/dsh-turn-status-text ``` ## How to configure **1. Configure it in the Plugins page (recommended)**: **sidebar → Plugins → open this plugin in the list → the configuration section is right under the title** (no need to open 包含的组件) → two inputs: the custom text and the text colour → Save. ![The configuration section on the plugin's own page](docs/plugins-config.png) There is another way in: the same form also lives on the row inside "包含的组件" (click that row's chevron title, the `配置 @dsh-external/dsh-turn-status-text` button). > In 0.2.0-rc the plugin configuration is no longer under "Settings → Plugins → Configurable": that tab and the `settings.plugin.item` slot it dispatched do not exist in the new build. > The Plugins page now collects configuration from two slots, and **each needs a registration before any entry appears**: > - `plugins.bundle.config` (key = the package name) → renders a configuration section under the plugin's own title, which is the screenshot above; > - `plugins.row.config` (key = `#`, i.e. `rowConfigKey()` in `ui-plugin-manager`) → gives that row inside "包含的组件" a page of its own (`configure.has(row)`). > > The values travel over the `configForms` service (`configForms.get(row id)`, guarded by `whileServed`), and the form is the platform's own > `SettingsFormModel` / `SettingsForm` / `SettingsValueField`, so both places look exactly like the settings pages the deployment ships. Both fields are `volatile()` fields on this row's Config, so a save takes effect **immediately — with neither a restart nor a page reload**. **2. Temporary override (DevTools console, current page only, wins over the settings)**: ```js window.__DSH_TURN_STATUS_TEXT__ = 'Thinking hard… {duration}' window.__DSH_TURN_STATUS_COLOR__ = '#ff5500' delete window.__DSH_TURN_STATUS_TEXT__ // drop the text override delete window.__DSH_TURN_STATUS_COLOR__ // drop the colour override ``` Both globals are **read live on every render and on every stylesheet change**, so an edit shows up at once. Precedence: `window override` > `value from settings` > the copy / theme colour the deployment ships. ## How it works ### Text: the dictionaries stay untouched, the `translate` seam is rewritten The in-progress line's copy comes from Chat's dictionary keys: ```js const label = startTime === undefined ? t('chat.deepDiving') // Deep diving : t('chat.deepDivingFor', { duration }) // Deep diving for {duration} ··· ``` The `t` the framework hands every slot component is built by `ctx.locale.bind(ns)` and implemented as `(key, params) => this.translate(ns, key, params)` — **`this.translate` is resolved at call time**. So the plugin installs an own property of the same name on the locale service instance to shadow `translate`: it intercepts exactly these three keys (`chat.deepDiving`, `chat.deepDivingFor`, and `message.turnProcess.deepDivingFor` on 0.1.7), and forwards every other key untouched (`common` fallbacks, parameter interpolation, unknown keys falling back to the key name); uninstalling the plugin restores the original. `{duration}` is filled in by the plugin itself from the elapsed-time string the framework passes; when there is no duration parameter (the key used before the clock starts, for instance) the placeholder is swallowed and doubled spaces are collapsed, so no curly braces ever leak through. ### Colour: one higher-priority rule plus the platform's own colour variables On 0.2.0-rc that line is not flat text but `TextShimmer` (a layer of text swept by a mask): its colour comes from the custom property `--dsw-alias-label-shimmer`, and `.X_running` maps that from `--dsw-alias-label-deep-diving-shimmer`. So **both custom properties are load-bearing in the rule** (not a nicety), while `color` covers the older deployments (where it really was a `currentColor` gradient) and unifies the whale mark along the way. This is the single rule the plugin injects (the selector is written twice = 0,2,0, which outranks the generated class at 0,1,0 no matter which stylesheet comes first): ```css [data-chat-running][data-chat-running]{ color:#ff5500; /* older deployments are coloured by this, and it unifies the whale mark too */ --dsw-alias-label-deep-diving:#ff5500; /* the two variables the deployment uses itself */ --dsw-alias-label-shimmer:#ff5500; } [data-turn-process][data-turn-process]{color:#ff5500} /* the 0.1.7 turn-process row */ ``` The shimmer's geometry, animation and timing all stay exactly as they were; only the colour changes. The row itself is addressed through **attributes** (`data-chat-running` / `data-turn-process`), never through content-hashed class names that move with the build. On older deployments (before 0.1.7) that row is `._turnStatus` with a gradient background, so the plugin discovers the real class name in `document.styleSheets` with `/\.([A-Za-z0-9_-]*_turnStatus)(?![\w-])/` and rebuilds a rule with the same gradient geometry; the `