dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
把侧栏底部的账号头像移出,支持四种位置(含零高度的品牌行内嵌)、三档高度(最小仅头像)、可调间距,并在插件页提供设置卡;其他插件的底栏小组件保持原位贴底。
English | 中文
Moves the left sidebar's account avatar (which is also the Settings launcher) out of the bottom strip, so the session list gains the space back. Placement, height and spacing are adjustable from a card on the Plugins page; inline brand row costs zero vertical space.
Tested against DeepSeek Harness 0.2.1-rc.2 (desktop, Windows).DSH pins a footer at the bottom of the left sidebar: the account row (头像 + 账号名) sits next to sidebar.footer.action, where plugins such as dsh-cost-meter mount their own widgets.
This plugin moves only the account row:
display: contents, so its two children join the sidebar's flex column; theaccount row is then reordered while _footerActions keeps its default order and stays pinned at the bottom. (Moving the whole footer would drag other plugins' widgets along — that was a real bug in 0.2.1.)
brand row** (Windows desktop; position: absolute at the free right end, zero vertical cost).
shrinks the avatar to 20px).
inline placement temporarily returns to a normal 28px row under the brand row: an absolutely positioned row has no width to give the pill, so it would otherwise be drawn underneath the avatar. The avatar goes back to the corner as soon as the pill disappears.
Changes apply immediately — the browser half subscribes to the settings document and rewrites the stylesheet. Settings persist in the profile's cordis.patch.yml.
Setting · Values · Default Enabled · on / off · on Position · top / below brand / below New Session / inline brand row · top Height · full 44 / compact 32 / avatar only 28 · full 44 Spacing below · 0–24 px · 4 Restore defaults · button · —
dsh plugin add dsh-avatar-topRestart DSH once after installing (the client bundle and package metadata are read at host start). Then open Plugins → dsh-avatar-top to configure it.
Git install works too, e.g. dsh plugin add git+https://github.com//dsh-avatar-top.
Self-check: the plugin serves its current stylesheet at /dsh-avatar-top.css (public, read-only), so a wrong layout can be diagnosed without a session:
http://127.0.0.1:<dsh-port>/dsh-avatar-top.cssThe Host contributes one structured style row through webserver/index-inject:
ctx.on('webserver/index-inject', (table) => {
table.push({ kind: 'style', text: cssFor(readOptions(config)) })
})Both shells render that row:
Shell · Where the page comes from · How the row arrives Browser / dsh web · the SPA dist server answers the index over HTTP · renderIndex() renders the rows into the HTML Desktop app · Electron serves dsh-web-frontend/dist/index.html itself over its dsh-app:// scheme · the Host's injection table is handed to the page over IPC after startup; the page-side interpreter appends style rows to ``
ctx.webServer.tapIndex() would only cover the HTTP shell; the desktop window never calls it.
The desktop snapshot is taken at Host start, so the browser half also applies the stylesheet live (``, appended after the boot row, so it wins) and the boot row only prevents a flash on first paint.
The sidebar is a flex column; placement is pure order, and selectors key off the stable CSS-module class-name suffixes (_root, _footArea, _settingsArea, _trigger, _label, _avatar, _logoRow, _newSession, _panelList) rather than the per-build hash prefix.
html:not([data-platform='darwin']) [class*='_root']:not([class*='_collapsed']) > [class*='_footArea'] {
display: contents;
}
… > [class*='_footArea'] > [class*='_settingsArea'] {
order: -1;
margin-bottom: 4px;
}:not([data-platform='darwin'])).display:none there anyway).inlineBrand lifts the button out of the flow (top: 8px; right: 12px; z-index: 3) and forcesthe avatar-only shape. On non-Windows shells it falls back to top. While the update pill exists (:has([class*='_indicator'])) the row returns to position: static; order: -3, i.e. a normal 28px row under the brand row.
[class*='_trigger']:not([class*='_triggerRow']):not([class*='_triggerLabel']). A bare [class*='_trigger'] also matches _triggerRow — the flex row holding the account button, the connection indicator and the update pill — which collapsed the row to 28px and drew the pill underneath the avatar (0.3.0 bug). The row itself only gets flex-wrap: wrap, so a pill that cannot fit wraps instead of being pushed out of the sidebar.
Config declares four volatile() fields (user settings, not deployment config), so the Host serves the avatar-top namespace (the loader row id). The browser half binds it through ctx.configForms.get('avatar-top'), writes through config.set() / config.unset() (which reach remote.settings.mutate), and registers its card into the plugins.bundle.config keyed slot under the package name.
sidebar.settings (instead ofsidebar.footer.action) would ride along; no shipped plugin does that today.
positioning or moves it out of the column, the rules become no-ops (no errors, no misplacement).
inlineBrand needs the Windows titlebar (html[data-windows-titlebar]), where the collapsetoggle lives in the native titlebar. Elsewhere it falls back to the top placement.
npm install # @deepseek-ai/schemastery, for the tests' host-side import
node --check lib/index.js
node --check lib/client.js
npm testThe smoke test covers the schema defaults and rejections, volatile-ref and plain-value inputs, the full placement × height × spacing matrix, row de-duplication, the diagnostics route, a regression assertion that _footerActions is never reordered (so cost meters and friends stay at the bottom), and byte-equality of the two CSS generators across 120 option combinations.
lib/client.js is a hand-written bundle in the DSH client-module format (window.__ModuleLoader__.load); it has no build step.
MIT