Vai al contenuto principale
L

dsh-declutter-ui

lg320531124/dsh-declutter-ui

Three client-only fixes for the web UI: unfolds the session list past its 5-row fold, collapses long tool-call runs behind one toggle, and restores the mobile sidebar drawer above its own mask.

Installazione

dsh plugin --profile web add github:lg320531124/dsh-declutter-ui

README

dsh-declutter-ui

Three quality-of-life fixes for the DeepSeek Harness web UI, in one small client-side plugin. No server code, no network calls, no telemetry — it only touches the DOM of the page you are already looking at.

给 DeepSeek Harness 网页版做的三处「界面清爽化」修正,一个纯前端插件,不联网、不上报。


What it fixes

1. The session list no longer hides everything after 5 items

The workspace sidebar renders each group with SESSION_WATERMARK_BASE = 5 rows and folds the rest behind a 展开其余 N 个会话 button. That number is a hard-coded constant, the visible count lives in component state, and the folded rows are never mounted — so you cannot scroll to them and no setting exposes the count.

This plugin clicks the toggle programmatically until the group is fully shown.

click 1  "展开其余 10 个会话"  aria-expanded=false   12 -> 17 rows
click 2  "展开其余 5 个会话"   aria-expanded=false   17 -> 22 rows
click 3  "收起"                aria-expanded=true     22 -> 12 rows  <- collapses again

The button never unmounts — once the group is fully visible it becomes the collapse action. A naive "click until it disappears" loop therefore oscillates forever. The safe rule (implemented here) is: click only while the label still starts with 展开其余 and aria-expanded is "false".

2. Long tool-call runs collapse behind one toggle

An agent turn can easily emit 100+ tool rows. Each one is a 30px single-line summary, so a long answer becomes a wall of 执行了命令 / 读取 … noise you have to scroll past.

A 显示工具调用 N / 折叠工具调用 N pill is injected inline into the view-tab strip (对话 轨迹 上下文 … ⋯), not as a floating overlay. One click hides the whole run; the state is remembered in localStorage.

Fold state is display-only — it never changes what is sent to the model and never saves tokens.

3. The mobile sidebar drawer actually appears

On narrow viewports (< 1024px) the layout collapses the sidebar to an icon rail, and the ☰ button opens it as an overlay drawer. On the builds tested, the drawer does open (sidebarCol goes from x: -280 to x: 0) but stays at z-index: 0 while the backdrop mask sits at z-index: 70 with backdrop-filter: blur(28px) — so all you see is a blurred grey sheet and the sidebar looks broken.

The framework CSS is supposed to promote the drawer to z-index: 71 / position: absolute, but that rule did not apply on the tested build. This plugin injects the missing rule.


Install

dsh plugin --profile web add dsh-declutter-ui

Then add it to your profile's bundle list so the patch layer is applied — in ~/.dsh/profiles/<profile>/package.json:

{
  "dsh": {
    "profile": {
      "bundles": [
        "…",
        "dsh-declutter-ui"
      ]
    }
  }
}

Restart dsh web once (the profile bundle list is read at startup; the client half itself hot-reloads on refresh).

Uninstall

dsh plugin --profile web remove dsh-declutter-ui

Remove the entry from dsh.profile.bundles and restart dsh web.


Compatibility

Verified by unpacking the npm tarballs of the upstream UI packages and grepping for the DOM contract tokens this plugin relies on:

TokenOwning package0.2.0-rc.20.2.1-rc.50.2.2-rc.1
flowItemdsh-client-ui-chat141518
viewTabsdsh-client-ui-conversation599
sidebarColdsh-client-ui-layout171729
data-disclosure-rowdsh-client-ui-workflow-run111
overflow:dsh-client-ui-workspace181819

All five tokens survive across those three releases. That proves the tokens were not renamed — it does not prove the DOM structure around them is unchanged.

Tested manually on: DSH 0.2.2-rc.1, web profile, Windows 11, Chromium.

Failure mode

Everything degrades silently. If a selector stops matching, the corresponding fix simply does nothing — no console error, no broken page. If you upgrade DSH and a feature goes quiet, that is why.

Hashed CSS-module prefixes (pI_x6G_, wSkVaW_, …) change on every build. This plugin deliberately matches only the readable suffix via [class*="sidebarCol"] style selectors, so prefix churn is harmless.


Design notes

  • Client-only. lib/index.js exports an empty apply() so the Loader mounts the package; all behaviour lives in lib/client.js, declared through package.json → dsh.client.
  • Self-healing mount. React re-renders replace the injected button node, so the plugin re-checks after DOM mutations (400ms throttle) and re-mounts if it was removed. If the tab strip disappears entirely it falls back to a fixed top-right overlay.
  • No timers left behind. Every listener, MutationObserver and <style> node is registered through ctx.effect(...) so a plugin reload cleans up.

License

MIT

Plugin correlati