dsh-mobile-upgrade
Verifieddsh-mobile-upgrade ยท v0.8.11 ยท SySL-1.0 ยท Web UI
Mobile UI fixes for the DeepSeek Harness web profile: a restart row, input-modality switches, a narrow-screen drawer and settings tabs, a full-width model menu, a stuck/failed request watch surfaced in the connection card, a scrollable question region, a
Install
dsh plugin add dsh-mobile-upgrade Confirm the layer applied with dsh --profile default --dump-config โ see the install guide.
Source
Tags
Creators
Readme
dsh-mobile-upgrade
English | ็ฎไฝไธญๆ | ็น้ซไธญๆ | ๆฅๆฌ่ช | ํ๊ตญ์ด | Espaรฑol | Franรงais | Deutsch | ะ ัััะบะธะน
Mobile quality-of-life fixes for the DeepSeek Harness (dsh) web profile, shipped as a single plugin. Almost everything renders through the host's own slots and state signals โ no layout takeover, no DOM polling of chat content. A few overlays are fixed-position plain DOM on purpose โ the bottom-left connection chip/card, the self-update banner, the shared toast: they must stay alive exactly while the host's own React tree is frozen.
What you get
- Restart row โ a "Restart service" entry in Settings โ General. Confirms first, restarts the
dshprocess, and reloads the page automatically once the service answers again. - Input-modality switches โ text/image checkboxes on every model row of the native provider editor, writing the model's
inputarray into the active profile's settings document (with a 0600 backup next to it). Catalog models without a user-customised route show the switches read-only with the defaulttextvalue (dsh 0.2'sllm.listProviderscarries no model list, so the effective catalog cannot refine them). - Narrow-screen drawer โ below 1024px the collapsed sidebar parks fully off-screen, replaced by the plugin's own floating button: a plain-DOM 56px round translucent element that is not the sidebar (the old chip was the sidebar itself, resized โ broken by host rebuilds and skin restyles), with its own icon โ the host's whale cloned and stripped of styling hooks โ at a size pinned against any skin. Tapping it chases the host rail to expand and slides the full-height sidebar in from the button's side as soon as the expanded rail mounts; the button fades out while the drawer stands, and a close tap (scrim, session row, header toggle) slides it back out in the same frame. The panel's width never changes, the transform-only slide cannot freeze halfway; the open drawer still paints an opaque surface from the theme's own sidebar tokens that a glass skin cannot turn transparent. The button stays draggable to either edge; the drawer opens from the side it is attached to.
- Narrow settings tabs โ below 700px the settings dialog's side navigation becomes a row of horizontally scrollable tabs.
- Full-width model menu โ below 700px the composer's model menu re-anchors to exactly the phone width (12px margins) instead of landing past the screen edge, while the host keeps owning the vertical placement above the trigger.
- Scrollable question card โ below 1024px a pending question can no longer bury its own choices: the question is capped into its own scroll region, so a long question scrolls in place while the option list below keeps whatever room is left and the options, the submit row and the minimize/close buttons stay on screen and reachable. A short question is untouched, and the card still hugs its content.
- Details-overlay settle โ the fullscreen tool-details overlay whose close control is inert in the current host is not rendered on narrow screens, so it cannot trap the chat.
- Storm-safe reactivity โ the drawer/menu observers and the settings poller react to a burst of streaming messages at a capped rate and back off while the host is unreachable, a rail remount during a reconnect keeps the drawer state instead of flapping it, and drawer close taps retry through a remount instead of landing on a stale toggle: many sessions streaming at once no longer freeze input or twitch the sidebar into unclickability, whether it is open or closed.
- Subagent-catalog guard โ the host serves the subagent catalog by enumerating the whole session corpus per request (~1s on a long history), and its client asks on every selection, chip hover, and membership event. The plugin wraps that refresh: a parent with no children in the live session list is never asked, a parent is re-asked at most once per 2.5s, and refresh starts are spaced apart โ a subagent fan-out no longer starves the host with full-corpus scans.
- Click-to-open lineage chips โ on desktop the subagent chips ("N subagents" and the subagent title switcher) open on hover only in the current host; a click does nothing. The plugin translates a click on a chip into the hover event pair the host already understands, so clicking toggles the tree open/closed (ancestor crumbs keep their navigate-on-click).
- Narrow-header collector โ below 1024px the session header's chips (lineage, jobs, preset) are wider than the phone and hover-only. They fold into one pill (
โก title ยท N agents ยท M jobs); tapping it opens a full-width sheet with the session lineage (each ancestor tappable, each with its descendant count), the subagent tree rooted at the family root โ rows render from the live session list, branches fetch their catalog on demand through the guarded refresh โ and this session's background jobs. On desktop nothing changes. - Session-list render throttle โ the host pushes a whole-value projection frame for every projection change of every attached session, and a running subagent's timing view changes on every committed event, so a busy background fleet streams 50-150 frames/s into the page. Each frame used to re-render the whole session list (one rebuild walks every summary plus an O(nยฒ) cache sweep โ measured as most of the main-thread time, freezing the page until reload). The plugin coalesces those re-renders onto an adaptive trailing interval while the values keep flowing into the per-session stores unchanged, so background streaming no longer freezes the page โ on any session, new or old.
- Connection card โ the host's bottom-left connection control reacts to a click with nothing observable: the retry it requests dives back into the same wedged transport, the recovery pill is an unclickable div on a timer, and the narrow rail/drawer sidebar never renders it at all. This plugin anchors the status with a plain-DOM chip at the bottom-left corner (alive even while the host's React tree is frozen) and pops a semi-persistent card above it: the card stays while the pointer is inside it, auto-dismisses otherwise, and carries the two actions that actually work โ an immediate reconnect through the connection service and a full manual page refresh. Stuck or failed
/api/requests surface in the same place: a badge and count on the chip, a request list plus a liveness probe inside the card โ nothing warns beside the composer's controls any more, no matter how many requests hang or fail. - Self-update โ the client bundle is served immutable per revision, so a phone tab can keep running an older build for days. The page compares the revision it booted with against the one the server publishes now and reloads itself once the page has been idle (never while a draft is being typed), or offers a tappable banner.
- Per-feature toggles โ the plugin installs a
dsh-mobile-upgradesection in Settings โ Plugins with a switch per feature.
Screenshots
The floating button, the session drawer, the narrow-screen settings tabs and the narrow-header collector (annotated):
![]() |
![]() |
![]() |
![]() |
Install
dsh plugin --profile web add dsh-mobile-upgrade
Restart dsh web, then open the web profile on your phone: the restart row sits in Settings โ General and the feature toggles in Settings โ Plugins โ dsh-mobile-upgrade. Attachments come from the host's own composer attachment system.
Requires dsh 0.2.0-rc.2 or newer (the host's built-in attachment system replaced this plugin's upload feature).
Configuration
The plugin's settings card lists one switch per feature (see Feature toggles); restartEnabled also gates the restart route:
| Key | Default | Meaning |
|---|---|---|
restartEnabled |
true |
Offer the restart row and its route |
Feature toggles
Every feature above can be switched in Settings โ Plugins โ dsh-mobile-upgrade (effective on the next page load), or overridden per device with a localStorage key โ mfx-restart, mfx-settle, mfx-drawer, mfx-settings, mfx-modality, mfx-menus, mfx-net, mfx-questions, mfx-selfupdate, mfx-agents, mfx-header, mfx-listthrottle, mfx-conn โ where the value "0" turns a feature off.
Limitations
- The client hooks specific host UI elements by their hashed CSS class names (menu, drawer toggle, provider editor, session-header chips). A host build that renames them degrades individual features until this plugin catches up; everything else keeps working. The question card's question region is found through the card's own
data-question-keyhook instead, so a host rebuild that merely rehashes its CSS modules keeps it working. - The header collector and the lineage click shim ride the host's own data (the live session list and its subagent catalogs); they add no requests beyond the guarded branch fetches, and a tap on a row whose mode is still loading completes on its own once that catalog lands.
- Input-modality switches can only patch provider routes you have customised yourself; catalog-only routes are read-only by design, because fabricating a catalog section collapses the model directory.
Security notes
The plugin's HTTP routes (restart, settings editing) perform no authentication of their own โ they trust the dsh web surface they are loaded into. Put the deployment behind whatever gate protects the rest of the UI (reverse-proxy auth, loopback binding) before exposing it beyond localhost.
Community Links
- Linux.Do โ A community for sharing and discussing technology.
License
Distributed under the Synthetic Source License (SySL), Version 1.0.
NOTICE: This software includes code generated by artificial intelligence. See the LICENSE file for the Synthetic Source License terms, including model disclosure requirements.



