Bundle
dsh-better
Better DSH: archived-session management, task-stop desktop notifications, an update checker, model routing (keyword rules + allowlist-gated model_route), multi-task scheduled triggers (interval heartbeats & fixed-time tasks), and a DeepSeek-style message scroll nav for the dsh web GUI
- Source
- wackyju2-beep
- stars
- 4 stars
- License
- MIT
- Updated
- Updated 1 hour ago
Readme
# dsh-better
> **Unofficial community plugin.** Not affiliated with DeepSeek. 非官方社区插件,与 DeepSeek 官方无关。依靠AI生产的代码。
更好的 DSH —— 一个符合 DeepSeek Harness 插件标准的双半部插件(host + browser),为 dsh Web GUI 补上几件顺手的小工具:归档会话管理、系统级任务通知、版本检查、模型路由、多任务定时调度(心跳/定点)、仿 DeepSeek 官网的消息滚动导航。所有能力都在「设置 → 更好的 DSH」下,随装随用。
中文 · [English](README.en.md)
本插件已上架 [dsh-market](https://github.com/dsh-market/dsh-market),可以在市场插件里发现并下载。
## 安装
已发布到 npm,终端里一条命令即可装入你的 DSH:
```bash
dsh plugin --profile web add dsh-better
```
安装后重启 DSH 生效,设置页出现「更好的 DSH」入口。
## 功能
设置 → 更好的 DSH:
- **已归档会话** —— 列出所有已归档对话(标题线索、工作目录、归档时间、本地日志状态),可复原回原工作区原位置接着聊,也可连同本地日志彻底删除;
- **任务通知** —— 网页保持打开时,任务停止即弹出系统原生通知(Windows Toast / macOS / Linux 桌面通知):Agent 提问或给出选项、任务完成、任务出错三种时机各自可开关;
- **检查更新** —— 对比本机 dsh 与 GitHub Releases 最新发布(完整 semver 规则),一键复制全套更新命令,也可在源码目录弹出独立终端窗口供你粘贴执行;
- **模型路由** —— 关键词规则按顺序匹配用户消息,首个命中即把会话切到指定提供方 / 模型 / 推理强度;可选开启 `model_route` 工具让智能体在对话中自主切换(设计移植自 [dsh-model-router](https://github.com/superboy911/dsh-model-router),按需裁剪);
- **定时任务** —— 多任务调度:可建任意多个**间隔心跳**(每 N 分钟注入,类 OpenClaw)与**定点触发**(每天/每周几/每月几号 HH:mm)任务,每条任务独立的名称、开关、时间、提示语与目标;目标可选主工作区根(内部巡检)或任意会话。全部运行在 **dsh 后端进程**中——**无需保持网页打开**;
- **侧边滚动栏** —— 1:1 复刻 [chat.deepseek.com](https://chat.deepseek.com) 的滚动导航:每条你发出的消息对应一根刻度线,悬浮预览、点击直达,配色可在设置页自定义。**默认关闭**;开启后会替代官方内置的轮次导航,关闭即原样还原。
所有配置改动实时生效,无需重启。
## 实现方式
标准双半部插件:**宿主半部**运行在 Node 后端进程内,注册一组仅回环可达的 `/api/dsh-better/*` exact API 路由;**浏览器半部**按页加载,向设置页注入界面与交互,经由上述路由与宿主通信。
对 dsh 运行时的依赖全部在运行期解析:dsh-better 经符号链接目录加载,无法静态 `import "@deepseek-ai/*"`,宿主半部以启动入口为锚点解析所需宿主模块(与运行实例同一份构建产物),缺哪一块就单独降级对应功能并给出警告,绝不拖垮后端启动。
三层安全栅栏:只接受回环连接;校验 `Host` 头(防 DNS 重绑定);POST 强制声明 `application/json`——跨站"简单请求"无法伪造该头,而这些路由也永不应答 CORS 预检,跨站伪造页面动不了你的存档。
### 已归档会话
- 复原/删除通过开放的工作区持久层直接落盘。归档从不改动工作区记账,所以复原即还原:把会话从全局归档集移除,回到原工作区的原位置;
- 删除会清掉本地 `.jsonl` 会话日志,并从工作区记录与归档集中一并移除;正在直播的会话拒绝删除(`session-live`);
- 所有变更直接写持久化的 workspace 域,浏览器经由网关现有的 `domain/changed` 转发即时收敛——所有打开着的页面无需手动刷新。
### 任务通知
- 由标准浏览器 Notification API 实现,跨平台通用(Windows Toast / macOS 通知中心 / Linux freedesktop 桌面通知,带 DeepSeek 鲸鱼图标);关闭网页后通知自然停止,这是该 API 的固有边界;
- 通知引擎以**可逆方式**包装会话运行时的两个帧入口来观察事件流:只旁路观察、绝不改动分发;插件停用时逐个还原被包装的原型方法并清空内部状态(包装器自带标记,防止重复启用后叠层),不留任何残留观察者;
- 提问挂起期间死掉的会话不再永久吞掉完成通知(挂起登记随新运行自动清理);子代理子会话默认不重复提醒;
- 授权状态、启用开关与三类时机开关保存在浏览器本地(localStorage)。
### 检查更新
- **目录发现链**(结果在进程内缓存):`DSH_BETTER_REPO_ROOT` 环境变量显式指定 → 从启动入口(`argv[1]`)与工作目录向上查找最近的 `@deepseek-ai/dsh` package.json(源码运行与打包安装都能命中)→ node 可执行文件旁的 pnpm 全局 store → 约定路径扫描 `<盘符>:\.dsh\deepseek-harness`。路径含 node_modules 判为「发行包安装」,apps/cli 布局判为「源码构建」;盘扫与 pnpm 探测是 Windows 特有,unix 上静默跳过;
- **取版本三级源**,任一可用即成功:`/releases/latest`(该端点排除预发布——上游 release 全是预发布时恒 404,属预期)→ `/releases` 列表取首个非草稿(失败重试 1 次)→ `github.com/<repo>/releases.atom` 订阅源(与前两者不同主机,api.github.com 整体故障时的独立通路,重试 1 次)。单请求超时 9 秒;成功缓存 5 分钟;24 小时内有过成功值时,全源失败兜底展示旧值并带「缓存数据(可能过期)」徽章——陈旧数据优于白屏报错;
- 检查更新移出共享串行队列,带并发去重与失败缓存:GitHub 抽风时面板照常能用,也不阻塞其余功能;
- 版本比较遵循完整 semver 规则(`0.1.1-rc.2 < 0.1.1`、数字预发布标识符按数值比较),比较器单独导出供测试;
- **弹终端**:Windows 经 `cmd /d /s /c start` 为内层 cmd 分配全新控制台——绕开 `detached: true` 等价 `DETACHED_PROCESS`、控制台程序不分配任何控制台的坑;macOS `open -a Terminal`;Linux 依次尝试 x-terminal-emulator / gnome-terminal / konsole / xfce4-terminal,以 250ms error-race 区分「缺程序」与真实启动,迟发 error 挂 no-op 监听防止拖崩后端。窗口完全独立于后端生命周期,不受其管理或终止,命令由你自己粘贴执行,插件绝不代输。
### 模型路由
- 引擎的规则匹配、目标校验等纯函数部分与原版 [dsh-model-router](https://github.com/superboy911/dsh-model-router) 逐行同源;配置持久化在独立 settings 命名空间 `better-model-router`(刻意区别于原版插件,二者可以共存);
- 规则按顺序匹配用户消息文本,**命中即停;未命中不改动会话**。写入会话前先对 DSH 实时注册表精确校验(提供方须已激活、模型须可解析、推理强度须被支持),校验失败不写会话;休眠目标可保存但不会执行;
- 子代理会话默认不应用会话头选择,引擎会惰性安装官方选择装配,让关键词规则在子代理第一条请求即生效;
- 可选 `model_route` 工具(默认关闭):开启后智能体可在对话中自主切换当前会话模型,但只能切到白名单里逐条精确列出的组合,每次执行仍经实时精确校验;开启但白名单为空时不注册任何工具;聊天流中有对应的路由卡片;
- 只读路由移出共享串行队列、规则目标并行校验、上游请求带超时上限,打开路由页不会拖慢其余功能;保存走版本号乐观锁,配置被其他窗口改动时明确提示冲突。
### 定时任务(多任务调度)
一个页面管理任意多条任务(上限 20),每条任务都有独立的名称、开关、类型、时间、提示语与目标,共用一套投递路径。**调度器完全运行在 dsh 后端进程里——网页关掉照常触发**:
- **两种类型**:「间隔心跳」每 N 分钟(最小 5,默认 60)注入一次,开启即从当前时刻起算间隔;「定点触发」每天 / 每周几 / 每月几号的 HH:mm 触发(本地时区,同一分钟不重复);某月缺少对应日期(如 2 月 30 日)自动跳过、不会顺延到下月 2 日;
- **新建 / 删除**:保存与触发按钮旁的「新建任务」一键追加,每条任务卡内有「触发一次」做端到端验证(未启用也可手动触发)与两段式确认的删除;
- **目标两种**:「主工作区根(内部巡检)」= 向该工作区下最近活跃的会话注入(一次最多 5 个;全部离线时自动唤醒最近的一个);「指定会话」= 只注入该会话。目标会话不在内存时(后端刚重启、网页没开过它),通过官方 `sessionController` 的标准恢复路径**冷恢复**后注入——与你在网页里点开它再发消息完全等价,代价是被唤醒的会话会常驻内存;
- **提示语**支持 `{time}` 占位符(注入时替换为当前时间),留空使用默认巡检提示语;消息以插件来源注入,与官方 schedule 提醒同一套机制;
- 定点时间用「时/分」两个下拉选择,会话目标下拉默认显示**对话标题**(与归档会话页同源,带短代号后缀),一键切换为路径+代号紧凑模式;所有下拉均为 dsh 原生 Menu 样式,深浅色主题自适应;
- 页面内可看每条任务的下次触发倒计时、共享的最近 20 次运行记录(任务名、注入结果、失败原因);
- 触发会消耗 token:被注入的会话会真的跑一轮模型调用,请按需设置间隔。
实现上的三个要点:
- **配置与迁移**:任务表整体存于独立 settings 命名空间 `better-scheduler`(`{ version: 2, tasks: […] }`,上限 20 条),保存走版本号乐观锁,被其他窗口改动时明确提示冲突;宿主以 `scope.watch` 订阅变更,保存后逐任务即时重新武装,无需重启。旧的单任务配置(独立的心跳/定点条目)读取时自动迁移为任务列表——已配置的延续原计时状态,从未配置过的安装迁为空表;
- **调度核心**:一个分钟级 tick 每分钟对账全部任务;每条任务一份独立台账(上次运行、下次触发、定点分钟去重 key),仅在任务首次出现或「关 → 开」时重置计时基准——编辑名称/提示语/目标不会重启节奏,删除任务时其台账随之清理。「每 N 分钟从开启时刻起算」「同一分钟不重复」「缺日期自动跳过」全部由这份台账推导,不依赖网页保持打开,也不依赖系统 cron;
- **投递路径**:所有任务共用一条投递链路——按目标解析出会话后,经官方 `sessionController.resolveAgent` 取回代理(目标不在内存则走标准冷恢复),再以 `agent.followup` 注入用户消息;主工作区根目标按 cwd 匹配活跃 root 会话(上限 5)逐一投递。网页上的「触发一次」走的就是这条链路,等于对生产投递做端到端演练。
### 侧边滚动栏
> **官方已有内置替代(v0.4.1 起本功能默认关闭)**:dsh 0.1.2-alpha.1 起官方自带了「轮次导航」(会话右侧的回合刻度条)。本功能转为可选增强——默认关闭,保持官方原样;**开启开关即为全局接管**:所有会话中的官方轮次导航一律隐藏,与本功能刻度条当屏是否显示无关(某会话刻度不足两条或消息尚未载入时只是本功能刻度条暂不出现,官方导航依然保持隐藏);关闭开关则全部会话立即还原官方导航。开关实时生效,无需刷新页面。跳转默认与官方轮次导航同一套语义(瞬时定位写入,配合官方的滚动台账,不会被流式输出拽回);设置页另有「平滑滚动跳转」可选开关,打开后恢复旧版的平滑滑动+心跳守卫机制(流式输出期间偶尔需要多滑一两次才能到位)。
- 从 chat.deepseek.com 的生产样式表逆向其滚动导航的类名与布局,1:1 复刻为毛玻璃胶囊轨道;
- 刻度直接从会话快照派生:`user` / `steering`(运行中插话)聊天节点各对应一根刻度,以稳定锚点 key 对齐到渲染出的消息行;
- 一条长生命周期的监听器维护全部 DOM 派生状态:滚动监听以捕获阶段委托一次性绑定(任何元素的滚动都能到达这里,会话中途换上新滚动容器也会在第一次滚动时自动重定向),`ResizeObserver` 跟随布局变化;当前浏览位置的判定在每次滚动时同步计算——刻意不用 rAF,后台标签页里 rAF 冻结会让高亮刻度滞留旧位置;
- 点击刻度把会话滚动容器瞬时滚到对应消息行——与官方轮次导航同一套机制(单次 scrollTop 写入,官方滚动台账将其识别为程序写入而非读者输入,从而自行解除底部跟随);旧版的 5 秒心跳重申守卫随官方滚动系统重写一并退役;
- 对官方轮次导航的隐藏不依赖任何构建期类名(官方类名是 CSS Modules 哈希),只认官方滚动容器内的 `nav` 元素;插件自己的导航带专属标记,绝不会被误伤;
- 主题色用 CSS `light-dark()` 自动跟随浅色/深色;自定义配色保存在浏览器本地(localStorage),改动即时生效。
界面上我们有点小骄傲:**全程沿用 dsh 原版的设计语言**——颜色、圆角、间距、字体一律取自当前主题的语义变量,不引入任何第三方样式。无论你换到哪个主题,它都像原生自带的功能页一样自然融入。
## 问题反馈
遇到任何问题——安装失败、界面异常、通知不响、路由不生效……或者有任何功能建议——都欢迎到 [Issues](https://github.com/wackyju2-beep/dsh-better/issues) 提出,多多益善。描述越具体(DSH 版本、操作系统、复现步骤),修复越快。
## 兼容性说明
**在官方宿主更新到正式版之前,本插件只适配 DSH `0.1.2-rc.1` 这一个版本**(含以此自报版本号的 post-rc.1 master 构建)。`package.json` 的 `engines.dsh` 已按精确版本钉死,dshmarket 会对其它宿主版本显示不兼容。`0.1.3` 起的 alpha 实测存在会话历史无法显示等严重问题,升级宿主请等官方正式版。
Install
dsh plugin --profile web add github:wackyju2-beep/dsh-better
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-better from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.