dsh-sidebar-restart

DSH PLUGIN会话与消息

仓库 DONGBIN007/dsh-sidebar-restart

会话与消息 L5 · 运行验证通过 安全审查:低风险 可信度:金 可安装插件
安装这个插件

dsh-sidebar-restart 是 DONGBIN007 维护的 会话与消息 类 DSH 可安装插件, 仓库为 DONGBIN007/dsh-sidebar-restart,许可证 MIT。 下面按「装什么、怎么装、验没验过、跑起来要注意什么」逐项列出。

一句话选型结论

按资料字段整理

dsh-sidebar-restart 是会话与消息类的 DSH 可安装插件,验证等级 L5 · 运行验证通过,安全审查为低风险,有可直接复制的安装命令。验证通过不等于安全:插件会读写文件、执行命令或联网,装前先到仓库确认它做了什么;涉及密钥或系统权限的,建议先在隔离环境试装。

分类会话与消息 收录类型可安装插件 验证等级L5 · 运行验证通过 安全审查低风险
验证等级 L5 L5 · 运行验证通过
GitHub 星标 0 复刻 0 · 未关闭 issue 0
最近更新 2026-10-18 创建于 2026-10-16
README 12.1 KB 正文体量,越大说明说明书写得越细

安装

可安装插件
在 DSH 里执行,装完用 dsh plugin list 确认已挂上;标了 L4 / L5 的命令已在沙盒里真实跑通
dsh plugin --profile web add github:DONGBIN007/dsh-sidebar-restart
  1. 1
    确认版本与运行环境

    仓库没有标注兼容版本与 Node.js 要求,先确认你的 DSH 版本能装,再继续。

  2. 2
    执行安装命令

    在 DSH 里执行上面的命令;多包仓库要注意区分具体子包名,别装错包。

  3. 3
    确认已挂载

    用 dsh plugin list 查看列表里是否出现这个插件,出现即挂载成功。

  4. 4
    试跑并检查权限

    加载后跑一个最小用例,确认它能正常工作;同时看它申请了哪些文件、命令或网络权限。

兼容 DSH 版本未标注版本不匹配时安装会报错
Node.js 要求未标注来自仓库 package.json 的 engines 字段
前置依赖无需要同时安装的同级依赖
npm 包名未发布到 npm可用 npm view 查看包信息

能做什么

会话与消息
字段来自项目仓库与公开索引,中文说明由本站标注

上游标签

cordis-plugindeepseek-harnessdshdsh-plugin

验证等级与安全审查

L5 · 运行验证通过
自动化流程结论,不是人工审核
验证等级L5 · 运行验证通过在 dsh 沙盒中完成安装与运行冒烟——装得上、跑得起来
安全审查低风险静态分析结论,未标注不代表已通过审查
仓库健康度活跃按仓库活跃度与最近更新时间给出
可信度金综合仓库活跃度与验证结果

选择建议

装之前先看这几条
按条目字段给出的判断,不替你决定用不用

值得选的地方

  • 验证等级 L5:安装和运行都在沙盒里跑通过,装完能直接用的概率高。
  • 静态安全审查为低风险,没有发现明显可疑行为。
  • 有可直接复制的安装命令,不用自己翻文档找入口。

先想清楚的地方

  • 没有声明 Node.js 版本要求,版本不匹配可能装不上。
  • 验证通过不等于安全:插件会读写文件、执行命令或联网,装前先到仓库确认它做了什么。

更适合

  • 需要在会话与消息场景里给 DSH 补能力的人。
  • 想装完就能用、不想自己排依赖的人。
  • 能接受在本地装依赖、愿意自己确认权限的人。

不太适合

  • 只使用 DSH 官方内置能力、不接受第三方插件的人。

同类对比

6 个同类
同分类里挑最接近的几条,字段以各自详情页为准
插件验证等级安全审查星标兼容版本安装命令
dsh-sidebar-restart当前 L5 · 运行验证通过 低风险 0 未标注 有
dsh-desktop L3 · 安装规范通过 低风险 3.0 万 未标注 无
openpets L4 · 沙盒安装通过 低风险 1,274 未标注 有
deeptide L4 · 沙盒安装通过 低风险 1,104 0.1.1-rc.2 有
jingyun-dsh L3 · 安装规范通过 低风险 1,004 未标注 有
study-mate 未做沙盒验证 未标注 856 未标注 无

仓库档案

会话与消息
字段来自项目仓库与公开索引,中文说明由本站标注
作者 / 维护方DONGBIN007仓库 dsh-sidebar-restart · 默认分支 main
分类会话与消息client
收录类型可安装插件声明了 dsh.bundle、可用 dsh plugin add 安装的条目
开发语言未标注仓库主语言
许可证MIT商用或二次分发前请确认条款原文
星标 / 复刻 / issue0 / 0 / 0收录时的数值,非实时
创建 / 更新2026-10-16 · 2026-10-18最后推送 2026-10-18
本站收录2026-10-30首次进入本站目录的时间

README 全文

12.1 KB
作者原文,中文版优先;只做安全转义,不改内容

dsh-sidebar-restart

One row in the sidebar foot, beside the settings gear: restarts the DSH desktop
app in a single click, instead of quitting from the tray and relaunching by hand.

Install

dsh plugin --profile desktop add dsh-sidebar-restart   # once it is on npm

or straight from the repository:

dsh plugin --profile desktop add github:DONGBIN007/dsh-sidebar-restart

Then restart the app once by hand so the plugin loads — which is the last time you
have to do that, since this button is what you use from then on.

Desktop only. On a plain dsh web profile the row renders disabled and says
why; there is no desktop process to replace there. If you wanted the Web server
restarted, that is a different plugin
(dsh-restart-button).

What it does, in one line

Adds a Restart row to the desktop app's sidebar foot beside Settings. Clicking
it asks the Host to restart; a detached helper kills the Electron main process and
the Host by PID, waits until both are gone, starts the app again, and the tab
reloads itself once the replacement answers with a new boot id — so a plugin you
installed a moment ago is actually running afterwards.

What it looks like

Desktop app (wide sidebar) Mobile drawer

Both follow the host's own rule rather than a breakpoint of mine: the label appears
exactly where the host shows one for the gear, i.e. when the sidebar is wide. In the
narrow 56px rail the row stays icon-only and keeps the gear's 36×36 target.

The control is a copy of the gear row next door

The seat is sidebar.footer.action — "optional actions beside Settings at the
sidebar foot". The shipped sidebar renders it as footerActions, a flex row that
footArea lays out above settingsArea (the gear row). So in the plain host
footer this control sits directly above the gear.

It is deliberately styled as the gear's twin, with every value read from the
shipped .wCInkW_trigger (ui-settings-general) and the seat's own sibling
.dsh-mobile-control__trigger, which agree:

Property Value Why
colour --dsw-alias-label-primary the gear uses the primary label colour; a secondary-coloured icon beside it is a visible mismatch
height 42px the footer row height both host controls use
padding 0 10px 0 8px, gap 8px the gear's own padding and icon/label gap
radius --dsw-radius-md the gear's radius, not the small one
label 14px / 22px, font: inherit the gear label's typography
row box calc(100% + 4px), margin 4px -2px the gear's row is .wCInkW_triggerRow{width:calc(100% + 4px);margin:4px -2px} — it bleeds 2px past the column on each side, so its content begins at parentLeft − 2 + 8 = +6. Without the same bleed this row's icon and label sit 2px to the right of the gear's, and the two never line up. This button is its own row, so it carries both the bleed and the padding.

Verified on a real phone screenshot (1216×2640, so ≈3.5 device px per CSS px),
measuring the dark ink of each row directly:

row, on the device icon ink left label ink left icon ink row centre
before the bleed: 重启 73 157 50 2356.5
before the bleed: 设置 67 150 48 2531.5
after the bleed: 重启 66 150 50 —
after the bleed: 设置 67 150 48 —

So the old geometry sat +6 device px (≈2 CSS px) right of the gear — the 2px the
CSS predicted — and the shipped geometry lands within 1 device px on the icon and
exactly 0 on the label. The two row centres are 175 device px apart, which is
175 / 3.5 = 50.0 CSS px — precisely the designed 21 + 4 + 4 + 21.

The orange line is the gear's own icon left edge. Before, the ↻ icon and the 重启
label both sit to its right; after, they land on it.

The equivalent check against the host's shipped CSS in a controlled 340px column
gives the same result to the hundredth:

row icon left label left
the gear 5.67 29.67
this button, before the bleed 7.67 (+2.00) 31.67 (+2.00)
this button, after the bleed 5.67 (0.00) 29.67 (0.00)

One residual is not a CSS mismatch and is deliberately left alone: on the device
the ↻ ink is 50px against the gear's 48px. Both icons are the host's own primitives at
the host's own wide ? 16 : 18, drawn on the same 16px box with the same 1.3 stroke —
a near-full circle simply carries more ink than a compact gear. Making the two inks
match would mean drawing the shipped artwork below the size the host asks for, which
is the one thing this row must not do.

The label follows the host's own wide convention — no invented breakpoint.
The gear's TriggerContent renders wide ? + label :,
and dsh-mobile, the seat's other occupant, does wide ? : undefined.

The two icons can never disagree, because both seats are handed the same
wide. In the shipped sidebar there is one source:

const wide = windowsTitlebar ? !collapsed : !collapsed || !settled;
renderSlot("sidebar.footer.action", { wide })   // this plugin
renderSlot("sidebar.settings",      { wide })   // the gear

and the gear forwards it unchanged to settings.trigger. So this plugin's
wide ? 16 : 18 is the gear's wide ? 16 : 18, by construction.

The registered component must forward the seat's props. One that takes no
parameters drops wide, and the control then stays in its icon-only shape in every
state while still rendering "fine" — a defect invisible in review and obvious on a
phone. That is exactly what the first mobile screenshot showed: a bare icon in the
open wide drawer, above a labelled 设置. test/client.test.mjs now pins the
forwarding, and the check was confirmed by reintroducing the bug and watching it
fail rather than trusting a green run.

  • Wide column (desktop sidebar; also the mobile drawer while it is open):
    icon + the word 重启 / Restart, in the gear's font and colour.
  • Collapsed 56px rail: 36×36, icon grown to 18px, no label — the gear's rail
    state. Note this is the one place the two host references differ, and the gear
    wins: .wCInkW_trigger.wCInkW_rail keeps --dsw-radius-md (12px), while
    dsh-mobile's .is-rail swaps to border-radius: 50%. A circle beside a
    rounded square reads as a different control family, so this plugin uses the
    gear's rounded square.

On mobile specifically (dsh-mobile, overlay breakpoint (max-width:720px), the
drawer is min(88vw, 340px)): the mobile bundle's !important rules target the
composer, the settings options page and sidebar row menus — none of them
touch sidebar.footer.action or the gear, and mobile defines no icon-size
variable. It only reads the host sidebar's own _collapsed class to decide
whether the drawer is open. So the two icons stay in step by construction, not by
a mobile-specific override.

Two skins/layouts are served by the same code, with no branching: with a skin that
folds the footer into the account popover (for example dsh-claude-style's
collapseFooter, on by default), the skin hoists this same entry into its menu and
renders it as a menu row — where the identical icon still reads as part of the set.

The glyph is the shipped IconRefreshOutlineArtwork from
@deepseek-ai/dsh-client-ui-primitives, copied rather than imported (a plain-JS
bundle may not load a Harness Client package, and importing one is what the plugin
rules forbid). Same 16×16 box, same 1.3 medium stroke, same currentColor and
default caps, so it reads as part of the host's own icon set.

Why the restart works this way

The obvious implementation is not available, and each dead end was verified
against the installed build rather than assumed:

  • The button cannot go inside the account menu. Its items (settings,
    contact, signout) are a hard-coded array in
    @deepseek-ai/dsh-client-ui-settings-account; the menu exposes no plugin seat.
  • There is no restart API for plugins. window.dshDesktop exposes only
    browser, deviceInfo, keyboard, shortcuts and updates; none of the 25
    dsh-desktop:* IPC channels restarts anything. The Host is a plain Node child
    of the Electron main process (ELECTRON_RUN_AS_NODE=1), so it cannot call
    app.relaunch(). The built-in "Restart App and Host" menu item exists but is
    gated on !app.isPackaged, so a released build never shows it.
  • Closing the window does not quit. window.on('close') hides to the tray.
    Launching the app again is also a no-op: the single-instance lock turns the
    second launch into "focus the existing window".

So the restart is an out-of-process handoff: the Host answers 202, then a
detached helper kills the Electron main process and the Host by PID, waits
until both are really gone (which is what keeps the relaunch from being demoted
by the single-instance lock), and starts the application again with the Node-mode
marker removed.

What the tab does while that happens

The page cannot be told "restart finished" by a connection that is being torn
down, so after the 202 it polls the status route and compares the boot id.
A different boot id means the new process is answering, and the tab then calls
location.reload(). That reload is the point of the whole feature: it is what puts
the browser on the newly installed bundle instead of leaving it on the old code —
and it is why the progress dialog is dismissable (Escape, the scrim, or its
button) rather than a modal trap if the handoff never lands. The poll is read-only
and stops after POLL_LIMIT attempts, handing the UI back.

Endpoints

Both are same-origin, loopback-only.

Route Method Purpose
/dsh-desktop-restart/status GET boot id, PIDs, and whether a restart is possible here (with the reason when it is not)
/dsh-desktop-restart/restart POST performs the restart; answers 202 before the app is killed

POST refuses any request that carries a forwarding header, does not come from
loopback, has an Origin that disagrees with Host, or is not
application/json (a cross-site page cannot send that content type without a
preflight this server does not answer). A single-flight latch makes a second
click during a restart a no-op instead of a second application.

Settings

Key Default Meaning
handoffDelayMs 400 How long the helper waits before killing, so the 202 reaches the browser.

Logs

Each restart writes dsh-desktop-restart-.log to the system temp
directory; the path is shown in the progress dialog and returned by the 202.

Limits

  • It is a hard restart. It does not run the shell's quit inspection, and
    running tasks are interrupted — which is why the button confirms first.
  • Freshly installed bundles may still need one manual restart to load. After
    that, this button is the way to restart.
  • If a future DSH release changes the process model, the plugin degrades to a
    disabled button with a stated reason rather than damaging the app.

Development

node --check index.js && node --check client.js
npm test

test/client.test.mjs pins the parts of the client half that are invisible until
they are wrong: that it loads React and no Harness package, that the glyph is the
official artwork rather than a redraw, that the control matches the gear row's
colour/metrics/typography, that the label follows the host's wide convention,
that every visible colour is a theme token, and that its only mutation is the JSON
restart POST.

常见问题

6 问
答案由本站依据条目字段整理,不引用上游原文
dsh-sidebar-restart 怎么安装?

在 DSH 里执行 `dsh plugin --profile web add github:DONGBIN007/dsh-sidebar-restart` 即可。

dsh-sidebar-restart 的验证等级是什么意思?

L5 · 运行验证通过。在 dsh 沙盒中完成安装与运行冒烟——装得上、跑得起来

dsh-sidebar-restart 安全吗?

低风险。

dsh-sidebar-restart 装之前要先确认什么?

先看它会读写哪些文件、执行哪些命令、连接哪些网络地址;验证等级只说明装得上、跑得起来,不等于安全。涉及密钥或系统权限的,建议先在隔离环境试装。

dsh-sidebar-restart 用的是什么许可证?

上游标注为 MIT。商用或二次分发前请到仓库确认许可证原文。

这条记录的数据可靠吗?

本站按仓库名去重后合并整理,字段以作者仓库与 npm 元数据为准;安装命令、仓库地址与 README 保持原文,带 L4 / L5 标记的安装命令已在隔离沙盒里真实跑通。

会话与消息
按星标排序,可作替代方案

dsh-desktop

dsh-desktop

为 DeepSeek Harness (DSH) 插件生态打造的现代化桌面端解决方案。万物皆「插件」,桌面本身也是「插件」。

L3 · 安装规范通过 3.0 万 星

openpets

openpets

L4 · 沙盒安装通过 1,274 星

deeptide

deeptide

L4 · 沙盒安装通过 1,104 星

jingyun-dsh

jingyun-dsh

井云 DSH 客户端插件,为 DeepSeek Harness 注入会员登录、订阅支付、算力管控与应用市场,让智能体和技能快速变成可交易商品

L3 · 安装规范通过 1,004 星

study-mate

study-mate

StudyMate 是 DSH 的「学习模式」预设与技能包,为数学、计算机科目定制学习路线、讲解课件与练习评估,跨科目共享记忆。

未标注验证等级 856 星

插件的元信息来自作者仓库;分类、验证等级与安全结论的中文说明为中文整理,最近核验 —。