- Home
- Plugin
- Sviluppo e strumenti per plugin
- dsh-service
dsh-service
gehennawu/dsh-service
Pannello operativo DSH Web self-hosted per riavvio e aggiornamento sicuri, diagnostica dello stato, statistiche di utilizzo dei modelli e ricerca della quota dei provider, backup e gestione sessioni, notifiche attività, controlli skill, routing del modello per subagent e manutenzione dei permessi Linux.
Installazione
dsh plugin --profile web add github:gehennawu/dsh-serviceREADME
🛠️ dsh-service
DeepSeek Harness (DSH) Web 服务控制与运维插件
A service-control & operations plugin for DeepSeek Harness (DSH) Web.
功能 • 架构 • 安装 • 自动重启配置 • 平台支持 • 安全设计 • 常见问题 FAQ • 参与贡献 • 许可证
DSH Web 服务控制与运维插件:安全重启、版本管理与一键升级、健康诊断、模型用量统计、额度查询、备份管理、任务通知、技能管理、会话管理与 Linux 文件权限维护。

📑 目录
🚀 功能
设置页「服务控制」面板六页导航:概览 · 模型统计 · 额度查询 · 健康诊断 · 维护 · 配置;其中「维护」聚合 会话管理 · 技能 · 子代理 · 备份维护 · 重启 五个子页,「配置」聚合 功能开关 · 任务通知 · 设置栏标签 三个子页。重启、额度查询、会话管理可另行开启设置页左列快捷入口(默认关闭;技能与子代理的左列入口已撤销)。
「插件 → 插件配置」提供十二个宿主级开关:健康诊断、模型统计、额度查询、备份维护、任务通知、技能管理、子代理模型、会话管理、移动端适配、模型厂家图标、右栏文件编辑、/healthz 探活(除移动端适配外默认开启)。全部热生效:关闭即隐藏界面、停止轮询并让宿主拒绝对应能力;概览与重启固定保留。

概览
- 状态摘要(error → warning → info → normal 聚合,带状态点)→ 可行动项(仅在存在时)→ 版本与运行环境 → 指标格 → 近期报错(仅非空时渲染,默认折叠)
- 状态聚合规则:健康/诊断/备份/统计/额度/重启任一失败即 error;权限异常、非咨询性诊断警告为 warning;可更新、尚无备份为 info(额度窗口高占用只在额度查询页内以进度条呈现;疑似终端手动启动属常驻环境事实,也只在健康诊断检查项与重启/升级确认中呈现——两者都不再进概览提醒)
维护与配置聚合页


- 「维护」集中会话管理、技能、子代理、备份维护与重启;记住最近使用的子页,关闭对应功能后自动回退到仍可用的项目
- 「配置」集中功能开关、任务通知与设置栏标签;开关按功能组展示并热生效,任务通知关闭时保留入口但显示置灰状态,设置栏标签支持对设置弹窗左侧全部导航标签进行手动排序(拖拽/上下箭头换位)与显隐管理,配置持久化到服务端统一配置文件
$DSH_HOME/dsh-service-config.json(多设备同步、启动自动拉取,本地缓存兜底),即时生效(服务控制面板永久锁定显示防锁死);额度卡的排序与显隐走同一份配置(quotaCards区块,进入额度页时拉取) - 插件统一配置文件:各功能的轻量偏好收敛在
$DSH_HOME/dsh-service-config.json单一文件(原子写入、0600),按功能分区块隔离——修改或清除某一区块绝不影响其他区块;大缓存(使用统计索引等)与加密凭据不在此文件内
版本与更新
- 显示当前 DSH 与插件版本,链接 GitHub Releases
- 自动检查 npm 正式版 + 预览版(latest / next 双 tag)
- 「本次更新内容」入口跟在当前版本号之后且常驻:点开读当前这一版的更新说明;有新版本时状态文本「有新版本:x.y.z」整体可点,展开新版的 release 信息。正文一律由宿主从 GitHub Releases API 取回后就地渲染(纯 Markdown,不嵌 iframe、不跳转),带版本号、发布日期与预发布标记;未建 Release 或读取失败各有明确提示;点版本卡以外的任意位置或按 Esc 即关闭。两行的版本号与「本次更新内容」入口按钮按同一套列对齐,版本号右对齐使它与入口按钮的间距固定,与版本号长度无关——长短版本号只把整列一起推宽,不会让某一行错位;窄容器(手机与窄设置面板)沿用同一对齐——版本号吃掉行内余量并右对齐,两行的版本号与入口按钮仍各自同列
- 一键升级,完成后自动重启;未检测到进程管理器时先确认后果,保持运行并提示手动重启
- 升级落地但进程尚未重启期间(手动启动环境尤为常见),版本行改示「已安装 X,重启后生效」并收起升级按钮,重开面板或刷新页面状态依旧;重启进程后恢复常态
安全重启

- 重启前检测活跃 Agent、后台任务与终端,展示清单并要求显式确认
- 对话输入
/restart也可触发;检测到运行中工作时自动拒绝 - 重启后自动探测新进程并刷新页面,60 秒未恢复提供手动刷新;对话里用
/restart触发的重启同样自动刷新(页面加载时记下进程身份,重连后比对instanceId,新进程上线即刷新) - 可开启「设置页左列显示入口」(默认关闭),与「维护 → 重启」子页共用同一确认流程
- 疑似终端手动启动时提示「退出后不会自动拉起」,健康诊断以黄色警示标注
健康诊断

- 运行时间、内存、会话数、活跃 Agent 与后台任务;「进程与运行环境」卡显示平台、架构与 Node 版本
- 完整诊断:会话存储、工作区注册表、备份目录、tar 可用性、文件权限、运行环境、Node 版本与使用统计索引——两行检查清单(检查名+状态点 / 详情),异常行局部淡染强调、正常行低对比
- 使用统计索引:报出已索引会话数、索引更新时间与未能索引的会话数(单会话折读失败会让用量静默少算)。失败会话按「部分成功」处理,记提示而非警告,不点亮警告状态、不进概览可行动项;尚未建立索引(还没打开过模型统计页)记信息级;「模型统计」开关关闭时整项不检查(宿主在该状态下本就不刷新索引,报了只会是陈旧误导)
- 通知权限:诊断页在宿主检查项之后追加一行浏览器侧检查——系统通知被拒绝或尚未授权都意味着「通知不会响」,并给出恢复入口;浏览器不支持时记信息级。该行只留在诊断页内,不进概览可行动项、不点亮标签 ⚠(是否用通知是用户选择),「任务通知」开关关闭时整行不渲染
- 插件健康检查:只检查异常(官方插件页已有完整清单与开关,这里不做重复清单)——插件失败或依赖未就绪时检查项报错/警告,刚启动的 pending/loading 有短暂宽限;已释放或未知状态显式标为信息级,不误报为警告。检查清单下方列出异常插件(名称、已脱敏且限长的错误、缺失依赖);失败插件可两段式确认后重新加载(只作用于宿主已确认失败的条目);手动停用的插件(无论内置还是自定义)一律不算异常
- 文件权限深检与修复(两段式确认)收敛在默认折叠的「权限与修复」区(有异常时按钮显示计数)
- 疑似手动启动 → 黄色警示「重启无保障」;无备份属信息级提示,不点亮 ⚠
模型统计

- 近 7 天输入 / 输出 / 缓存 token 堆叠柱图,按项目筛选、悬停显示精确值;图例与刷新统一收进统计区头部行,图表带可访问的文本摘要。悬浮提示为七行:日期 + 输入/输出/缓存命中三项明细,再追加 token 总量、成功模型步骤、缓存命中率;命中率取宿主按当日桶加权的值(比率不跨桶相加)
- 模型明细横条,列表头部「今日 / 近 7 天 / 累计」切换
- 卡片最下方日用量热力日历:覆盖索引内全部日期(上限 20 周、起点对齐周一),四档强度按单日峰值分位、悬停看当日明细;随项目筛选联动。主图只画近 7 天,这里补上长期视图
- 热力块右上角可切到**「小时」打卡图**:7 行(周一–周日)× 24 列(0–23 时),格 = 该时段累计 token,回答「几点最忙」;同一批小时桶换个维度折出,不新增持久化字段。方格布局为星期标签与间距预留宽度,窄屏在块内横向滚动
- 已统计的用量永久保留:删除会话或删除项目文件夹都不会扣减历史,总量与热力图始终是「索引建立以来的完整历史」;索引版本升级先保留旧摘要,可读取的会话仅在完整重建成功后替换,失败时保留历史并重试
- 项目文件夹已删除时,该项目不再出现在项目筛选入口里,但它贡献的用量仍计入「全部」总量、日期桶与模型明细
- 最近 48 小时模型 / 工具报错统计(默认折叠、仅非空渲染)
- 提供方未上报 token 用量的步骤不纳入统计
- 单个会话无法读取、迁移或解析时继续统计其他会话,显示全项目成功/跳过数量与可展开的会话 ID、错误类别及安全摘要;失败会话有旧缓存时保留并标明过期,首次失败不计入,下次刷新重试。只有服务不可用、列表读取或索引写入失败等全局错误才让整次刷新失败。该提示可关闭(关闭后记入本地存储),且只静音同一批失败——出现新的跳过会话或错误类别变化时会再次提示,不会一次关闭就永久盖住新问题
额度查询
- 供应商卡片保留既有窗口展示(标签+百分比 / 独立进度条 / 重置倒计时);配置(凭据填写、类型切换、手动重置录入)默认折叠,按卡展开

- 卡片分区展示各供应商:窗口百分比、独立进度条、重置时间;支持强制刷新与官网用量页链接
- 卡片排序与显隐:额度页「调整排序与显隐」展开管理列表,可拖拽或点 ↑↓ 调整卡片顺序,开关可隐藏不常用卡片(隐藏只影响展示,不影响查询);配置与设置栏标签同源,写入服务端统一配置文件
$DSH_HOME/dsh-service-config.json的quotaCards区块(多设备同步、本地缓存兜底,区块间互不影响) - 对话输入框额度圆环:跟随当前会话模型所属供应商,显示最紧预算窗口用量(<80% 绿、≥80% 黄);点击弹出详情面板,窄屏自动切换为居中浮层
- 内置适配:
| 供应商 | 数据来源 |
|---|---|
| DeepSeek 开放平台 | 官方余额 + 峰谷时段提示(忙/闲色带、换挡倒计时;高峰=周一至周五 09:00–12:00、14:00–18:00 UTC+8,不含中国法定节假日,周末与法定节假日全天空闲) |
| 智谱 GLM Coding Plan | 官方端点:5 小时滚动 / 每周 / MCP 月度三窗口 + 峰谷时段提示(忙/闲色带、换挡倒计时;高峰=周一至周五 14:00–18:00 UTC+8) |
| OpenCode Go | {baseURL}/usage(内置渠道未写 baseURL 时用注册表默认端点 https://opencode.ai/zen/go/v1) |
| OpenRouter | credits 已用百分比 |
| Kimi / 硅基流动 | 人民币余额 |
| StepFun 余额 | 官方 GET /v1/accounts(API key,com/ai 双域) |
| StepFun Step Plan | 控制台 BFF 订阅额度(Oasis-Token 登录令牌;5 小时/周窗口与 Credit 月池自动识别) |
| 小米 MiMo Token Plan | 控制台同源套餐额度(网页登录态 Cookie) |
| Command Code(command-goat) | 官方账号额度面 api.commandcode.ai/alpha/*(同 key 复用:余额 + 本周期花费 + 套餐 + 5 小时/周窗口) |
| CLIProxyAPI 部署 | 各 OAuth 上游账号官方剩余额度 |
- 凭据写入 DSH 凭据库(
$DSH_HOME/.credentials.yaml,热生效):普通适配填 API key,CLIProxyAPI 填管理密钥,小米填控制台 Cookie,StepFun Step Plan 填控制台令牌(Oasis-Token,Oasis-Webid由令牌自动派生无需手填);Command Code 额度面与推理面同一把 key,无需另配 - 防风控:结果缓存 60 秒、失败指数退避(30 秒 ×2、封顶 15 分钟);查询为纯手动——打开额度页/展开圆环/点刷新才拉取,客户端不排任何周期轮询(上游节流仍全部在宿主侧)
- CLIProxyAPI 某账号实时查询失败时,回退显示其上次缓存的快照窗口并标注「缓存」徽标;重置时间已过的快照窗口(快照描述的窗口已结束)直接丢弃,避免「额度停在昨天」的错觉
- 失败原因如实呈现:卡片与圆环显示「错误文案(HTTP 状态 · 失败端点 · 失败账号 · 上游原话)· 下次自动重试时刻」——错 key、欠费、限流、路径变更各有各的上游原话与状态码,不再只有一个笼统提示;上游 401/403 判为「凭据被上游拒绝」,卡片同时保留凭据填写入口;HTTP 200 业务信封里的错误码同样定族——鉴权失败判凭据被拒(保留填写入口)、套餐到期判无生效订阅、上游自身故障判「上游服务故障」,不再一律报「响应格式异常」
- API key 只在宿主进程内解析,浏览器仅收到归一化窗口数据;未适配的供应商绝不发起请求
备份管理

-
备份记录列表为两行轻行(文件名主行 + 体积 · 时间次行,分隔线布局;会话管理列表同款)
-
创建会话、配置与插件 profile 清单的
.tar.gz归档;会话经持久化层稳定快照(活跃 agent 写入不再导致失败),创建过程以单条连续进度条分阶段显示(复制/打包/校验/发布,带步骤号 1/4–4/4,复制阶段为真实百分比) -
备份时版本信息:归档文件名带备份那一刻的 DSH 版本(
dsh-backup-YYYYMMDD-HHmmss-dsh0.1.7-rc.1.tar.gz),归档内另有meta/backup.json记录 DSH 版本、插件版本与创建时刻;面板行内与恢复预检都显示该版本,便于判断这份快照出自哪个版本(跨版本降级恢复读不动新格式会话)。旧版本插件所出的归档没有版本段,列表照常显示、恢复照常进行,只是不显示版本行;导入同时接受带版本段与不带版本段两种文件名 -
导出下载 / 导入上传 / 删除(两段式确认);不限份数、不自动清理;导入归档必须先通过与恢复相同的完整性检查
-
完整性检查:恢复前校验 gzip/tar、路径与条目类型,只接受
sessions、三份允许配置、profiles/<name>/package.json与meta/backup.json;拒绝越界路径、链接、特殊文件、未知内容、损坏归档与非法 profile 清单 -
恢复预检:先生成 5 分钟有效的一次性计划,展示会话整体替换、配置覆盖/移除和 profile manifest 覆盖清单;最终确认前再次校验归档 SHA-256 与当前目标指纹,发生漂移则拒绝执行
-
恢复提交使用事务日志和回滚目录:会话整体替换,配置按快照精确替换,profile 只更新 package.json 并保留 node_modules/凭据/附件;成功后托管环境自动重启,手动启动环境提示用户手动重启
技能管理

- 按 自动加载 / 仅手动调用 / 完全停用 三区展示本地技能;同名遮蔽与被遮蔽副本均有标注,内置目录只读
- 条目默认全部折叠成一行(名称 + 来源/只读/已注释徽标);顶部按钮对当前可见条目一键「全部展开 / 全部折叠」,点单条名称行可独立开合;无效条目的 ⚠ 与一键修复折叠态也保留
- 双开关直接改写 SKILL.md frontmatter(
disable-model-invocation/user-invocable),约 200ms 热生效 - 带 camelCase 旧版键的条目会被官方解析器剔除:⚠ 提示 + 一键修复
- ✨ AI 补全说明:选模型生成描述草稿(跟随界面语言),确认后存入插件侧车索引——绝不改写 SKILL.md;支持一键批量补全(宿主后台运行、可取消)。已注释技能会在计划中单列,经「确认强制补全」二次确认后才会被覆盖(不再是一旦注释就永远无法再次补全);补全日志时间按本机时区显示
子代理模型

- 三种模式:初始(不干预)/ 跟随主模型(取主对话最近一次实际使用的 provider/model)/ 自定义(固定到所选模型)
- 派生请求自带 provider/model 时始终优先,绝不覆盖预设钉死
- 自定义模式可选思考等级:仅当所选的 exact provider/model 由适配器声明了可选等级时才显示下拉;留空表示「使用目标模型默认」,由适配器在请求时物化默认值
- 该字段来自适配器 metadata(
reasoning.efforts[].id),等级 ID 对宿主不透明;无等级声明的模型禁用下拉并提示 - inherit / follow / 功能开关关闭 均不注入任何 provider、model 或思考等级;显式指定 provider/model 的子代理不受影响
- 模式切换保留配置:已保存的自定义模型(含思考等级)与回退列表在三种模式间切换时不会被清除——模式只决定是否生效,切回「自定义」无需重新选择(供应商/模型已不在运行时清单时自动回落到清单首项)
- 进入无位移:本页以最近一次成功读取的配置作为首帧缓存,进入即直接落在真实模式上,不会先显示「初始」再跳到「自定义」;首次安装或换浏览器(无缓存)时先显示一行「读取配置…」
- 回退模型(按顺序):跟随与自定义模式都可配置回退列表——第一路由不可用时(渠道已卸载、额度查询判定其不可服务)依次尝试后续模型;全部不可用则回落原生继承,不让派生失败。回退条目与主路由同一道白名单校验,思考等级逐条可选
- 对话页可见性:输入框下方常驻一行本会话子代理实际使用的模型,如
子代理:cpa/gpt-5.6-luna (xhigh) · opencode-go/deepseek-v4-flash (max)——含回退命中、显式路由与继承来源,可直接核对自定义路由是否生效。行挂官方conversation.composer.dock槽位,独占官方统计行的下一行、不与统计胶囊/上下文圆环同行挤占;20s 刷新,不依赖回合数据(会话发生 compaction 折叠工具调用也照常显示),由宿主派发记录兜底,任何视图都能看到;可在 维护 → 子代理 页用独立开关关闭。记录存宿主内存(页面刷新不丢、进程重启即清),官方「指派子代理模型」开关关闭与否都不影响本功能 - 配置存
$DSH_HOME/dsh-service-subagent-route.json(原子写入、0600),可一键重置
任务通知

- 主会话完成一轮任务、或会话需要授权 / 审阅计划 / 回答问题时发送浏览器通知;子代理完成任务不发送完成通知;点击通知聚焦页面
- 子代理触发授权 / 审阅计划 / 回答问题时仍发送浏览器通知
- 四档独立开关:总开关、任务完成、授权与提问、输入框铃铛显隐
- 对话栏铃铛一键开关总通知;所有开关刷新后保持
会话管理

- 查看:统一列表展示会话(运行中 / 冷会话 / 已归档),行内标状态徽章、工作区、事件数、文件体积;列表支持按创建时间正/倒序、按标题排序或按项目分区显示(每个工作区一个分区头:路径 + 会话数,同项目内最新在前;分区默认折叠,点击分区头展开 / 收起);默认停在「仅归档」视图,全部 / 仅归档 / 已删除三个筛选各自首次按需向宿主拉取对应子集并缓存(模块级缓存:切换筛选零请求、关掉面板再打开秒显缓存 + 后台静默刷新一次保鲜,页面刷新才清零),「刷新」按钮可强制重拉当前视图;普通列表提供「批量选择」按钮,进入后可直接点击整条会话(无需精确点复选框)进行选择 / 取消选择,也可一键全选 / 取消全选当前筛选结果,选中行以左侧品牌色标记而不改变背景;工具栏按资格显示可执行数量并支持批量导出 / 归档 / 删除(切换筛选、搜索或进入详情会自动退出批量态);文件体积不随列表下发、行内按需懒加载(模块级 + 宿主进程内存双层缓存:刷新浏览器 / 重开面板直接复用,删除时失效);进详情记住列表滚动位置,返回列表原地不动(沿用官方面板滚动容器,详情期间切筛选 / 改搜索则放弃恢复);详情按事件卡片分页浏览(宿主单槽位快照缓存:翻页/重进详情零重复读取,live 会话 30 秒内保鲜),正文按官方 Markdown 富文本渲染(复用平台官方渲染器
MarkdownText,与聊天界面观感一致:代码块/列表/表格/数学公式、默认拒原始 HTML 与危险链接;老版本 DSH 未提供该渲染器时自动回落纯文本),连续系统事件与工具消息各自默认折叠为计数块(工具消息 =tool/call、tool/result等tool/*事件,以及通篇只有工具调用的 assistant 消息——这类消息占真实长会话的多数,工具参数不会再铺满详情页),点击折叠行展开明细、再点收起;搜索命中落在折叠块内时该块自动展开并保持命中高亮 - 子代理识别:派生的子代理会话行内标「子代理」徽章(判定取自官方会话头字段:
origin=subagent产品分类为准,delegationDepth派生深度兜底老日志;仅parentSession的普通 fork 血统不算子代理);搜索行「仅子代理」复选框聚焦(与「仅搜归档」同行同款控件;正交于全部 / 仅归档叠加过滤,已删除视图不显示、切换视图时状态保留),批量选择态提供「选中子代理」一键把当前可见的子代理会话并入选择集(不清既有选择;视图里没有子代理行时该按钮隐藏),配合批量归档 / 删除快速清理;老版本插件宿主不下发该标志时列表照常,勾选筛选会明示「宿主较旧、未携带子代理标志」而非留一份无解释的空列表 - 导出:一键或批量下载官方完整 ZIP(每个会话一个 ZIP,含子代理与附件),复用官方导出链路,宿主不自己拼包
- 归档与恢复:单项或批量归档非运行中会话,归档后从官方侧栏隐藏;DSH ≥0.1.6 宿主支持单项或批量恢复(取消归档),老版本 DSH 保持单向归档提示
- 内容搜索:对话全文语义搜索(大小写不敏感、空白灵活),跨会话命中列表(匹配文本高亮;多命中显示 seq 位置芯片、可一键直达)→ 命中窗口视图:打开即以命中 seq 为中心展示上下文窗口(命中前后各 15 条事件;命中行标「命中」徽章高亮、自动滚动定位并闪烁 2 秒),支持上一个 / 下一个命中翻跳与导航条 seq 芯片直达(参考 dsh-session-kb 的 Locate 交互);窗口可继续加载后续事件;可限定仅搜归档区
- 删除:仅已归档会话可删除,且执行前再次拒绝运行中的会话;两段式确认先展示会话 id / 标题 / 工作区 / 文件体积,删除记录先原子落盘、再移除日志目录;已删除记录在「已删除」筛选下可见,支持单条清除或批量多选 / 全选清除(两段式确认,永久从记录中移除);删除成功后即时同步官方侧(补发官方会话移除事件、清掉归档集合里的死 id),官方侧栏与「已归档会话」设置页无需刷新浏览器即反映最新状态
- 入口:「维护」页子标签「会话管理」(默认开),设置页左列入口可选(默认关)
- 删除记录存
$DSH_HOME/dsh-service-sessions-deleted.json(原子写入、0600,仅标题/时间,不含内容、不可恢复)
移动端适配

- 默认关闭;仅在视口 <1024px(手机竖屏 / 窄窗口)生效,桌面完全无感
- 侧栏变抽屉、详情列移动端隐藏(对齐官方窄屏语义)、模态变全屏面板、设置左列导航变顶部横滑
- 官方插件面板页(「插件」)顶部手机端不折行:标题+简介与「刷新/添加插件」放不下时工具栏整体落到第二行右缘,简介与按钮文案各自单行;同时修掉抽屉钮让位内边距连带改写该页头部纵向/右侧内边距的旧写法(曾把「安装、启用和配置插件」挤成两行、「添加插件」按钮内文案折两行溢出胶囊)
- 模型选择按钮自适应零截断与思考程度常驻:放宽官方 45cqw 硬限宽,使测宽基于真实无损文字;空间充裕时完整显示「厂家图标 + 模型全名 + 思考程度」(零截断),空间吃紧时(小屏手机、长模型名或被其他插件占用工具栏)模型全名自动收缩为紧凑态,但思考程度(如 High / Low)与厂家图标永远保持显示([厂家图标] High ▾),无思考程度的模型则收成 45px 纯图标钮,全程单行不折行、不截断文字;移动端模型选择弹窗隐藏「搜索模型…」行,防止 autoFocus 强行唤起软键盘遮挡面板,模型列表直接展示更清爽
- 统计条(输入框下方「轮/步/tok/s | tok/缓存命中」)在手机上保持一行、居中且不歪:收紧这一行自身的左右内边距(官方 32px→2px)与列间距换出可用宽度,两枚统计交给官方
justify-content居中排开——≥~420px 视口零截断,更窄视口按比例各让一点(远少于官方的固定截断),不换行、不横向滚动;同时兼容老版本 DSH(0.1.5-rc.2 上这条行是整行宽,早期实现的子项flex-grow会把两枚统计整组推到左边,现已改为不生长)(桌面不受影响) - 会话顶栏手机端重排(≤560px):标题行只留标题 + 模式芯片(芯片右靠贴住「…」钮,标题基本完整可见),「N 个子代理」与「N 个后台任务运行中」两枚计数芯片泊到「对话/轨迹」标签行右缘成一对(标签间距 36→20,点芯片本体仍开各自菜单);官方 crumbs 放不下时的拦腰硬裁彻底消除,561px 以上与桌面保持官方原布局。DSH 0.1.7-rc.1 起官方给模式芯片加了
@container (width<=540px)隐藏(容器是标题行,约合 606px 视口),手机上曾整片消失——本插件在整个移动端带内覆盖回可见(390px 以上标题仍完整不裁,仅 320~375px 档标题略带省略号) - Agent Team 弹窗手机端不越屏(<1024px):官方 Agent Team 面板自带左锚(
left:0),挂在头部右侧动作槽上会整体右移出屏(实测 3201023px 越出 112352px)。移动端把会话头部设为定位上下文、面板改右锚 16px 并按100vw − 32px封顶,两缘各留 16px;桌面 ≥1024px 官方几何逐字不变 - 滑动沉浸:会话内下滑自动收起头部、左上角抽屉图标与输入框全屏阅读(左上角抽屉图标与右上角右侧栏展开按钮同步上滑淡出,收起时让出输入框占位,正文真正铺满整屏;回显时若仍停在会话末尾会自动对齐到底),上滑 / 点「回到底部」浮钮 / 聚焦输入框即恢复(无额外悬浮钮);已经停在会话末尾时往回一点即回显(不再等满阈值),点回底后停留位置会补一次贴底对齐;流式贴底、锚点跳转等程序化滚动绝不误触发
- 滑动开合抽屉:双抽屉关闭时,横移主导的右滑任意位置打开侧栏抽屉、左滑任意位置打开官方右侧栏(DSH 0.1.5+,未就绪时该方向无效);开启后反向横滑任意位置关闭;从屏幕边缘起滑额外享有浏览器手势接管的补完加成,编辑器等真横滚区内的滑动不误触发
- 「回到底部」浮钮右移贴边(不再空出大片右侧留白);其上方新增同款圆形上箭头(全平台生效,不含移动端),点击逐条跳转上一条用户回复、可连续向上回溯,目标在未加载历史时会自动点「加载更早」补齐,跳到最顶部后按钮自动隐藏、下滑即复现
- 大 JSON 响应透明压缩(≥4KB 按
Accept-Encoding自动 gzip/brotli),长会话历史首屏提速 - 自动补
viewport-fit=cover避让刘海、禁双击缩放、输入框 ≥16px 防 iOS 聚焦放大 ?dshsvc-mobile-debug=1显示浮动诊断条(仅调试)
模型厂家图标
- 输入框里那颗模型按钮会显示当前渠道的厂家图标:宽屏(>480px)加在模型名前面;手机上(≤480px,官方把名称收成图标的形态)替换掉官方那枚通用图标
- 没适配的渠道保持官方默认图标不变(宽屏不加、手机照旧显示官方图标),不会出现空缺或错图
- 覆盖 pi-ai 内置 40 个 provider 中的 38 个(
ant-ling、radius无对应品牌图形,走默认图标),并补充 ollama、vLLM、LM Studio、Perplexity、Cohere、火山引擎、豆包、混元、元宝、阶跃、商汤、百川、零一万物、Fal、Replicate、Midjourney 等常用渠道,共 62 张图形 / 76 条渠道映射;区域与计费变体(如xiaomi-token-plan-*、qwen-token-plan-*)共用同一品牌图形 - 自定义渠道名按前缀/别名自动识别:
opencode-goo→ opencode、openrouter-f→ openrouter、zai-coding-cn→ 智谱、xiaomi-token-plan-cn→ 小米、command-goat→ Command Code 等 - 识别不到时按余额查询的手动适配兜底:某个渠道名既不在内置表、也不符合前缀规则时,如果你在余额查询里把它手动适配成了某个类型(如
cpa→ CLIProxyAPI,或任意中转 → OpenRouter / 智谱 / Command Code / StepFun 等),就显示该类型的厂家图标;适配类型一改图标立即跟着换,撤销适配立即回落官方默认图标。两个前提:只有手动适配算数(仅由 baseURL 自动推断出来的类型不算),且名字能识别时以名字为准(叫openrouter-f的渠道即使另外适配成别的类型,也仍显示 OpenRouter 标) - CLIProxyAPI 图标按需出现:手绘的「内凹菱形 + 镜像漩涡」品牌标只在你在余额查询里把某个渠道手动适配成 CLIProxyAPI 后才显示在模型按钮上(渠道名不限,叫
cpa还是自定义名都一样);它就是上面那条兜底规则的一个实例,撤销适配立即回落官方默认图标 - 余额查询的渠道卡片同样带图标:已适配卡片的渠道名前显示同一套厂家小图标(14px;彩色档原样上品牌色、单色档跟随主题文字色)。上面那条「按手动适配兜底」的规则在这里同样生效——卡片区正是你做适配的地方,改完适配立即出现/换标
- 模型选择弹窗的分组标题同样带图标:点开模型按钮 → 「模型」二级列表后,每个厂家/渠道商分组名前面也显示同一枚图标(13px,与 12px 的分组标题同量级)。同一套解析与兜底规则,未识别的渠道分组保持官方标题原样、不加图标
- 浅色 / 深色都清晰:品牌色对浅底与深底两侧对比度都达标才保留原色,否则自动改用跟随主题文字色的单色版——不会出现深色模式下「黑图标糊在黑底上」或浅色模式下近乎隐形
- 零运行期网络请求:图标在构建期内联进客户端产物,离线可用、不影响 CSP,也不向第三方暴露你的渠道名称
- 图标尺寸与输入框旁的额度圆环一致(生成期把每个图标的 viewBox 收紧到真实绘制范围并正方形化,所以各品牌「看起来一样大」,不会有的满格有的缩成一团)
- 开关在 插件 → 插件配置 → 交互(默认开,热生效)
- 图标来自 MIT 许可的 LobeHub Icons(版本钉死
@1.95.0);小米图标取自 CC0 的 Simple Icons 纯 mi 标(LobeHub 那份是「Xiaomi / MIMO」两行文字组合标,15px 下糊成一团)。品牌图形版权归各厂商,正式对外使用前请查阅对应厂商的品牌条款 - 全部图标可在一页里查看:图标目录——62 张图形、76 条渠道映射、匹配规则与深浅色对照;离线单文件,与构建期内联进客户端的数据同源生成
右栏文件编辑
- 官方右侧栏的文件预览头部右上角多一个「编辑」按钮(紧邻渲染器名),点一下就进编辑模式:等宽编辑器,带脏标记、
Ctrl/Cmd + S保存、「重新加载」「撤销保存」,以及一键「预览」返回官方渲染器 - 另外两条等价入口:原来的渲染器下拉里选「编辑」,以及右键标签 → ⋯ 菜单 →「编辑」(后者走官方菜单座、不做任何 DOM 注入,是头部按钮失效时的兜底路径);处于编辑档位时头部按钮自动收起,不会重复
- 不改变官方渲染器的默认地位:
.md、.js等官方有专属渲染器的后缀默认仍是官方预览(Markdown / 代码…);只有官方没有专属渲染器、本来落到「纯文本」的后缀(如.txt、.log、.conf)才默认进编辑器。官方预览未挂载(旧版 DSH)时整块静默不出现 - 写盘走会话自己的文件服务与沙箱策略:浏览器只送
dsh-resource://file/session/<会话>/<路径>资源地址,会话与工作区根由宿主解析,不接受自由路径;保存携带读取时的版本号,磁盘已被 Agent 或其他窗口改过就拒绝覆盖,由你选「重新加载(丢弃修改)」或「用我的内容覆盖」;只读沙箱会话只能预览 - 保存不中断输入:保存期间仍可继续编辑,响应只确认本次提交的内容,后续输入保留为「未保存」;状态区分「保存中 / 未保存 / 已保存」。冲突出现后仍可修改,覆盖保存使用编辑器里的最新草稿
- 离开前保护草稿:通过编辑器自己的「预览」「重新加载」按钮离开或重读时,若有未保存内容先显示内联确认,可取消继续编辑;「撤销保存」也先确认,且保留版本守卫,不静默覆盖磁盘上的新改动
- 单文件上限 2 MiB(超过只读);会话未激活或沙箱策略服务不可用时不可编辑(仍可使用官方预览)
- 首版不做:语法高亮、多光标、查找替换(插件半没有打包器,借不到编辑器组件),关闭标签不弹未保存确认
- 开关在 插件 → 插件配置 → 交互(默认开,热生效)
外部探活
GET/HEAD /healthz返回空 200,其他方法返回 405- 适合 Uptime Kuma、Docker、Kubernetes 等外部监控
🏗️ 架构
插件是 Cordis 双半结构:Host 端(index.js) 承担一切能力与数据访问,Client 端(client.js) 只在浏览器渲染界面;两侧经 Typert JSON-RPC 通信,通道为单层绝对路径 /dsh-service,authority 一律 loopback。
flowchart TB
subgraph Client["🌐 Client 浏览器端 (client.js)"]
UI["设置页「服务控制」面板(六页导航 + 快捷入口)<br/>额度圆环 · 通知铃铛 · 移动端适配"]
end
subgraph Host["⚙️ Host 服务端 (index.js)"]
RPC["Loopback RPC · /dsh-service<br/>version / check-update / restart / quota / skills / backup"]
SPAWN["受控 spawn<br/>chmod / chown / npm 升级"]
end
subgraph DSH["🚀 DSH 核心运行时(只读消费)"]
CORE["agents · jobs · terminals · sessions<br/>sessionQuery · skills · credentials"]
WEB["webServer 路由<br/>GET/HEAD /healthz"]
end
subgraph OS["💾 宿主机与外部"]
PM["进程管理器<br/>Docker / systemd / pm2"]
FS["$DSH_HOME<br/>配置 / 备份 / 凭据 / 技能索引"]
REG["npm registry"]
QUOTA["上游额度 API"]
end
UI -- "Typert JSON-RPC(loopback)" --> RPC
RPC --> CORE
RPC --> SPAWN
RPC --> REG
RPC --> QUOTA
RPC -- "process.exit(42)" --> PM
SPAWN --> FS
MON["外部监控<br/>Uptime Kuma / Docker / K8s"] -- "GET /healthz" --> WEB
关键契约:
- 仅 loopback:能力只经
/dsh-serviceloopback channel 暴露;webServer 路由只返回不含信息量的状态码 - 重启 =
process.exit(42):插件只发退出信号,由外层进程管理器拉起;没有管理器时重启无保障 - 零输入拼接:浏览器侧不接受 URL / 包名 / 命令 / 路径,命令全部走宿主侧白名单
- 凭据不出宿主:API key 只在宿主进程内解析,浏览器只收到归一化窗口数据
⚡ 安装
方式一:DSH 插件管理页(图形界面,推荐)
- 打开左侧边栏的「插件」页。
- 点右上角的「+ 添加插件」按钮。
- 在弹窗里按来源三选一填写(同一个输入框接受三种形式,底部提示会随填写内容变化):
- npm 包名(推荐):
@gehennawu/dsh-service; - GitHub 仓库地址:
https://github.com/gehennawu/dsh-service(公开仓库,无需令牌;github:gehennawu/dsh-service简写同样可用); - 本地插件目录:本机上的绝对路径,例如
/path/to/dsh-service(自研或已下载的插件)。
- npm 包名(推荐):
- 「安装源」按网络情况选择:默认「npm 官方源」;国内网络拉取受限时可选「中国大陆镜像源」(影响走包名安装时的拉取源,GitHub 地址与本地目录不受其影响)。
- 点「安装」,等待官方把包装进当前 profile(弹窗底部会给出进度与结果)。
- 装好后本插件出现在「已安装」分组里。宿主半要等 DSH 进程重启才生效,客户端半刷新页面即生效。
- 在 Web 上:用本插件的「服务控制 → 重启」,或在对话里发
/restart; - 在 DSH Desktop 上:请退出应用后重新打开(桌面端由应用自身托管进程,本插件不会自行退出)。
- 在 Web 上:用本插件的「服务控制 → 重启」,或在对话里发
提示:三种形式都走官方安装链路,无需手动改 profile 文件;图形界面填 GitHub 地址与命令行
github:前缀等价。
方式二:命令行
| 方式 | 命令 |
|---|---|
| npm(推荐) | dsh plugin --profile web add @gehennawu/dsh-service |
| GitHub | dsh plugin --profile web add github:gehennawu/dsh-service |
| 本地开发 | dsh plugin --profile web add link:/path/to/dsh-service |
命令行走 npm / pnpm 的默认源;需要镜像时,请先按 npm / pnpm 的常规做法把 registry 指到镜像站,再执行上面的命令。
安装或更新后重启 DSH Web:
dsh web
打开 DSH Web 设置页,进入服务控制。
🔄 自动重启配置
插件只发送退出信号,不负责拉起进程;没有进程管理器时重启会直接停止 DSH Web。
插件以被动信号(环境变量、/.dockerenv、/proc/1/cgroup、终端 TTY)判断进程管理器:检测到 Docker/systemd/pm2/supervisord/Kubernetes 时照常自动重启;都没有且 stdin/stdout 为交互终端时视为「疑似手动启动」——健康诊断黄色标注、一键升级改为保持运行并提示手动重启。启发式无法覆盖输出重定向、NSSM/WinSW 等场景,可用 DSH_SERVICE_RUNTIME_ENV=managed|manual|desktop 显式声明。
Docker Compose
services:
dsh:
restart: unless-stopped
systemd
[Service]
ExecStart=/usr/local/bin/dsh web --host 127.0.0.1
Restart=on-failure
RestartSec=2
pm2
pm2 start "dsh web --host 127.0.0.1" --name dsh-web
🖥️ 平台支持
| 环境 | 插件功能 | 重启后自动拉起 | 验证状态 |
|---|---|---|---|
| Linux + Docker Compose | 支持 | 配置 restart policy 后支持 | 已验证 |
| Linux + systemd / pm2 | 预期支持 | 由进程管理器负责 | 未单独验证 |
| macOS / Windows + pm2 等 | 代码未限制 | 由进程管理器负责 | 未验证 |
| DSH Desktop(Windows,Electron) | 支持 | 由桌面应用负责 | 已验证(2026-09-28 真机) |
| DSH Desktop(macOS / Linux,Electron) | 代码未限制 | 由桌面应用负责 | 未验证 |
直接运行 dsh web | 支持 | 不支持 | 预期行为 |
运行要求:Node.js >=22,DSH Web 能加载 Host 与 Client 两半插件。更新检查需访问 registry.npmjs.org;网络失败不影响其他功能。
DSH 适配口径:已适配 DSH 0.2.1-alpha.1——会话格式 V4(V3 日志首读时由官方迁移为 session.v4.jsonl.zstd 代际文件,旧 session.v3.jsonl.zstd 按格式目录策略保留;详情视图自动归档系统事件)、SettingsForms 配置面(插件配置改由 Profile 的 cordis.patch.yml 承载,热更新走 loader/volatile-update;旧的 settings.register 在 0.1.5/0.1.6 上仍是权威来源,装在同一宿主上两者互不串台)、会话格式 V3 既有适配全部保留(system/message 入史、sessionPersistence handle 化、官方右栏、turn-process 对象化)、移动端底行触发钮双哈希兼容、子代理回合尾模型行 list 槽位自适应兼容、plugins.bundle.config 槽位注入、会话详情打开接入 uiWorkspace 降级链路。旧版 DSH(>=0.1.1-rc.2)保持兼容。支持区间扩展到 0.2.1-alpha.1(engines.dsh 上界 <0.2.1-alpha.2);0.2.1-alpha.1 源码级、npm 产物级(按 rolldown //#region 切片做逐源模块 sha256)与真机挂载审查(266 commits)确认:20 条既有接缝 17 条区域级逐字节相同、3 条均不触及本插件契约,9 个 slot key、25 个主题令牌、插件使用的 35 项官方 data-* 零丢失,宿主 RPC / webServer / 设置面 / persistence / session-format 产物逐字节全等;官方本版移除运行时 invariant 机制(各包 ./invariant 导出 38→0、dsh-invariants 包退役)本插件零引用,并修复了「启停插件误删其它插件样式」。唯一展示面破坏已双模式适配:官方把 composer 统计行拆成 activity/usage 两个 dock 条目并删除行根类 .root,移动端规则除保留旧锚 [class*="bOPqQW_root"](老宿主命中)外,新增官方新钩子 [data-composer-stat] 的同形约束与 ≤375px 字号阶梯(新宿主命中);0.2.0-rc.2 轮的模型弹窗分组标题 MenuGroup 双选适配继续有效,Client Inspect 挂起缺陷自 0.2.0-rc.2 起保持修复。rc.1 起新增的插件版本兼容门禁只读取 peerDependencies(本插件无该声明,不受门禁约束),并已在 DSH 0.2.1-alpha.1 真机挂载运行。设置面、persistence/布局 seam 均按运行时能力探测走双形态,旧宿主上针对新结构的适配项天然不生效(纯展示,无功能损失)。注意:升级后写入的会话日志无法被旧版 DSH 读取,备份不可跨版本降级恢复。插件市场按 package.json 的 engines.dsh 区间判定兼容性(该字段是唯一的支持口径声明)。
DSH 桌面端(DSH Desktop / Electron)口径:桌面端复用同一份 Web 前端与同一张客户端插件图(platform: web),插件照常加载,绝大多数功能原样可用;语义不同的只有「重启」与「一键升级」。宿主由桌面应用托管,重启一律不再 process.exit(42)(桌面壳把任何非 0 退出判为 Host 崩溃,会弹原生「启动失败」对话框且不会自动重拉,官方也没有可编程重启 RPC)——「重启」按钮、对话里的 /restart 与备份恢复后的重启统一改为提示「请在桌面端退出应用后重新打开」;一键升级在桌面端置灰并指向应用自带的插件管理页(桌面端 CLI 不能启动/改写 profiles/desktop,升级端点直接短路返回 desktop-managed-upgrade,不产生任何 subprocess);健康诊断的「运行环境」行显示「由桌面端托管(Electron)」。判据是宿主进程内的 process.versions.electron(Windows 桌面版真机实测 44.0.0,同进程 ELECTRON_RUN_AS_NODE=1、stdin/stdout 均非 TTY);非 Electron 的桌面封装可用 DSH_SERVICE_RUNTIME_ENV=desktop 显式声明。任务通知在桌面端可用(权限 granted,真机已收到系统通知);唯一的边界是点击通知唤不回窗口(桌面端关窗=隐藏窗口,dshDesktop 无窗口 API,请用托盘唤回)。macOS / Linux 桌面端未验证。
🔒 安全设计
| 领域 | 边界 |
|---|---|
| 输入 | 浏览器不能传入 URL、包名、命令或文件路径。唯一例外:右栏文件编辑只接受 dsh-resource://file/session/<会话>/<路径> 资源地址(逐段解码、拒绝其他形态),会话与工作区根一律宿主侧解析,写盘再经会话沙箱策略围栏 |
| 网络 | 更新检查只访问固定 npm registry 地址 |
| RPC | 仅接受 loopback 调用,数据不出本机 |
| 数据 | 用量索引不保存消息、Prompt、工具参数或凭据;API key 只在宿主进程内使用 |
| 操作 | 破坏性操作(重启、删除、修复权限)均需两段式确认 |
| 凭据 | 写入 DSH 凭据库($DSH_HOME/.credentials.yaml),只发往固定端点 |
❓ 常见问题 FAQ
重启后没有自动起来?
插件只发送退出信号,重新拉起由进程管理器负责(见「自动重启配置」)。面板标注「疑似手动启动」时,直接运行 dsh web 的终端进程会被退出;请改用 Docker Compose / systemd / pm2 托管。
健康诊断里的黄色「重启无保障」警告是什么?
这是「疑似终端手动启动」的检测结果,说明当前没有检测到进程管理器。若实际由 NSSM/WinSW 或输出重定向等场景托管,可用 DSH_SERVICE_RUNTIME_ENV=managed 显式声明消除。
桌面端(DSH Desktop)收不到任务通知?
先确认两件事:① 「配置 → 通知」里的通知总开关必须真正打开——它默认关闭,只有点过「开启通知」且系统授予权限后才会置为开启(若只看到「开启通知」按钮,说明权限还没授予);② 会话必须真的从「运行中」变为结束,且不是子代理会话。系统通知在桌面端本身是可用的:Windows「设置 → 系统 → 通知」里会为应用建立一条 electron.app.DeepSeek Harness 记录(真机实测会弹出「任务完成」通知)。唯一已知边界是点击通知不会把窗口唤回——桌面端关窗=隐藏窗口,当前桌面桥面没有窗口显示 API,请用系统托盘唤回窗口。
额度卡片显示「凭据未配置」?
点击卡片上的内联表单写入凭据:普通适配填 API key,CLIProxyAPI 填管理密钥(不是代理 key),小米 Token Plan 填控制台 Cookie。写入 DSH 凭据库后自动强制刷新;被进程环境变量遮蔽时宿主会拒绝写入,需改环境变量本身。
Command Code 卡片显示「凭据被上游拒绝」?
推理面和额度面共用同一把 key(user_* 前缀,Studio 的 API keys 页生成)。卡片显示该错误说明 key 被上游判为无效:到 commandcode.ai 的 Studio 重新生成或复制 key,点卡片「填写 API 密钥」粘贴即可。若渠道 baseURL 指向的是自建中转而非 api.commandcode.ai,额度面仍固定查官方账号面——中转 key 查不到官方额度。
小米卡片显示「凭据被上游拒绝」?
网页登录态过期了。重新登录 platform.xiaomimimo.com,从任意 /api/v1/tokenPlan/ 请求复制 Cookie: 头,点卡片「填写控制台 Cookie」重新粘贴。
StepFun Step Plan 卡片显示「凭据未配置」?
Step Plan 订阅没有 API-key 形态的查询接口,需要网页登录态令牌。登录 platform.stepfun.com,按 F12 打开开发者工具 → Application → Cookies → platform.stepfun.com,复制 Oasis-Token 的完整值(形如 xxx...yyy,两个小圆点分隔是令牌格式本身的一部分,不要拆分),点卡片「填写控制台令牌(Oasis-Token)」粘贴即可;Oasis-Webid 由宿主从令牌自动派生,无需手填。
StepFun Step Plan 卡片显示「凭据被上游拒绝」?
令牌过期了(官方常见报错 oasis-token is embezzled 即令牌与 web_id 不匹配)。重新登录 platform.stepfun.com 后从 Cookies 复制新的 Oasis-Token 完整值再粘贴;从控制台复制时若自带 Oasis-Token= 或 Cookie: 前缀会被自动剥离,不影响。
恢复备份会怎样?
先做完整性检查并展示恢复预检计划,再由用户最终确认。提交前宿主会复检备份 SHA-256、当前目标指纹与运行中工作;任何变化都会中止,不会部分覆盖或重启。提交成功后会话目录整体替换,允许的配置文件按快照精确替换,profile 只覆盖 package.json(node_modules、凭据、附件不动)。受 Docker/systemd/pm2 等托管时自动重启;疑似终端手动启动时显示手动重启指引。删除备份同样需要两段式确认。
技能开关为什么置灰不可点?
该技能来自内置(bundled)只读目录。只有 project-* 与 user-* 来源的技能支持双向开关。
保存技能开关提示「技能文件刚刚发生变化」?
并发保护生效:SKILL.md 刚被外部编辑器改动(版本比对失败)。点击「刷新」获取最新状态后重试即可。
更新检查失败会影响其他功能吗?
不会。更新检查只是访问 npm registry 的只读请求,失败静默忽略,其余功能不受影响。
🤝 参与贡献
欢迎提交 Issue 与 Pull Request。开发路线与技术约定见仓库内 AGENTS.md;发布规范见 AGENTS.md「发布」一节。
📄 许可证
Plugin correlati
deepseek-harness
deepseek-ai/deepseek-harness
dsh-web (dsh-plugin-manager)
zhu1090093659/dsh-web
dsh-web
zhu1090093659/dsh-web
dsh-web-ui (dsh-plugin-manager)
zhu1090093659/dsh-web-ui