dsh-service
gehennawu/dsh-service
Panneau d'opérations Web DSH auto-hébergé pour un redémarrage et une mise à niveau en toute sécurité, des diagnostics d'intégrité, des statistiques d'utilisation du modèle et la recherche de quotas de fournisseur, la gestion des sauvegardes et des sessions, les notifications de tâches, les contrôles de compétences, le routage du modèle de sous-agent et la maintenance des autorisations Linux.
Installer
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「发布」一节。
📄 许可证
Plugins associés
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