Menghuan1918 260e3b8d6b docs: one-shot install prompt for DSH; platform support notes
- README leads with a self-contained prompt the user pastes into DSH:
  clone URL, build, profile registration, cordis mount row, restart
- manual install/update section kept as the no-prompt alternative
- platform support section documents win32/linux/macOS adaptation and
  the node-pty build-tool requirements
2026-08-09 22:07:03 +08:00
2026-08-08 00:04:01 +08:00

dsh-better-sidebar

DeepSeek Harness Web GUI 的 VSCode 风格右侧侧边栏插件 —— 文件管理、编辑预览、真实终端、Git 面板,一个面板全部搞定。

image image

🚀 一键安装(把提示词发给 DSH)

把下面提示词整段发给 DSH,它会自动完成克隆、构建、注册与安装(前置条件:已安装 DSH 且 dsh web 可运行,Node.js ≥ 20、pnpm ≥ 10):

请帮我把 dsh-better-sidebar 插件安装到我的 web profile(插件 = VSCode 风格右侧侧边栏,仓库 https://github.com/dsh-external/DSH-better-sidebar):

1. 克隆并构建:
   git clone https://github.com/dsh-external/DSH-better-sidebar.git ~/Code/DSH-better-sidebar
   cd ~/Code/DSH-better-sidebar && pnpm install && pnpm build
   (若 pnpm install 因 @deepseek-ai/* 的 link: 依赖解析失败,说明 DSH 源码 checkout 不在 ~/.dsh/source/current —— 停下来告诉我,不要继续)
2. 注册到 web profile:
   a. 编辑 ~/.dsh/profiles/web/package.json,在 dependencies 中加入 "dsh-better-sidebar": "link:<第 1 步克隆目录的绝对路径>"
   b. 编辑 ~/.dsh/profiles/web/cordis.patch.yml,追加挂载行:
      - insert:
          - id: better-sidebar
            name: 'dsh-better-sidebar'
3. 在 ~/.dsh/profiles/web 目录执行 pnpm install
4. 全部完成后告诉我,我重启 DSH 并硬刷新(Cmd/Ctrl+Shift+R)验证

安装 = 把插件登记进 web profile 的依赖清单(等价于 dsh plugin --profile web add link:<路径>)+ 一行 cordis 挂载行,与 portal 无关——portal 只指侧边栏面板在页面上的渲染方式(见下文规范符合性)。

为什么用它

  • ⚡ 工作流不断档:编辑文件、跑终端、看 Git 状态、拖 Tab 分栏对比,全在对话旁边完成,无需切窗口
  • 🧠 按会话记忆与隔离:每个 conversation 拥有独立的布局、分栏、Tab 与目录展开状态,切换会话即切换整套工作台
  • 🎨 与 GUI 浑然一体:完全复用 DSH 主题变量与官方组件,明暗主题自适应,观感就是原生的

✨ 功能一览

🗂️ 文件资源管理器

  • 懒加载目录树,根目录 = 当前会话工作目录(cwd);目录优先、隐藏文件变暗、每层 1000 项上限
  • 点击文件在侧边栏打开编辑器;刷新按钮重载
  • 悬浮行尾 @文件 按钮:一键把 @相对路径 追加到输入框草稿(如 @src/main.ts),引用文件不再手打路径
  • 右键行 → 复制相对地址 / 复制绝对地址,复制成功行内短暂显示"已复制"

📝 文件编辑与预览

  • CodeMirror 6:自动换行 + 按扩展名语法高亮(js/ts/jsx/tsx、json、python、html、css、xml、yaml、sql、java、c/c++、rust、go、php、shell、toml、nginx、dockerfile、properties…)
  • 脏点标记 + Ctrl/Cmd+S 保存(原子写入);512KB 截断横幅、二进制文件提示
  • 图片直接预览;Markdown 预览/编辑切换,预览实时渲染未保存草稿
  • 切换 Tab 不卸载:编辑器保留草稿与撤销栈

💻 终端

  • xterm.js + node-pty 真实 shell,每会话最多 3 个
  • Tab 打开期间一直保活:切换 Tab/分栏、切换会话(30 秒内返回)、刷新页面都重连到同一个 shell 进程并回放转录
  • 真正关闭 Tab 立即释放配额;连续失败停止重连并显示原因与重试按钮

🌿 Git 面板

  • status 暂存/未暂存分组、按文件 diff(HEAD vs 工作区/暂存区)、stage/unstage(单个与全部)、commit、分支切换、提交历史

🧩 VSCode 式分栏工作台

  • 拖 Tab 到分栏边缘(左/右/上/下)即拆分新分栏,拖到中间合并,拖到另一个 Tab 上插入其前
  • 分隔线拖拽调整比例;面板宽度从左侧缘拖拽;折叠滑出隐藏 + 全屏展开

📑 Tab 栏

  • Tab 与 + 菜单均带类型图标(文件夹 / 分支 / 终端 / 代码文件)
  • + 菜单新建 Explorer / Git / 终端(终端受 3 个上限约束);中键点击关闭 Tab
  • 空分栏显示可打开类型卡片,点击即开

🔁 会话隔离与状态自愈

  • 布局/分栏/Tab/目录展开按会话持久化(localStorage),切换会话即切换整套状态
  • 陈旧状态自动净化:结构校验、宽度钳制视口、损坏的重复 id 自动重新编号——刷新后分栏与新生成的 id 永不冲突,不会出现"文件开进两个分栏"
  • 侧边栏占用布局(挤窄对话列而非悬浮遮挡,动画过渡)
  • 拦截对话"产出文件"行:点击改为在侧边栏打开,而不是系统默认程序

🎨 界面风格

  • 行/按钮/间距/动效对齐应用自身组件:34px 圆角树行、28px 圆形图标按钮、挂载淡入
  • 键盘焦点可见(focus-visible 环)、prefers-reduced-motion 下关闭全部动画

⌨️ 快捷键速查

操作 按键
保存编辑 Ctrl/Cmd + S
Git 提交 Ctrl + Enter
关闭 Tab 鼠标中键
拆分分栏 拖 Tab 到分栏边缘
合并分栏 拖 Tab 到分栏中间
引用文件到输入框 悬浮行尾 @文件 按钮
复制文件路径 右键行 → 复制相对/绝对地址

🧰 手动安装与更新

不想用提示词时,也可以手动完成(等价于上面提示词的步骤):

前置条件

  • 已安装 DSH(dsh web 可运行),Node.js ≥ 20、pnpm ≥ 10
  • 构建/类型检查需要 DSH 源码 checkout 位于 ~/.dsh/source/current(devDependencies 中的 @deepseek-ai/* 以 link: 指向它;若 checkout 在其他路径,修改 package.json 中对应的 link: 路径)。运行期不依赖该 checkout——@deepseek-ai/* 声明在 peerDependencies,由 web profile 提供

1. 克隆、安装、构建

git clone https://github.com/dsh-external/DSH-better-sidebar.git
cd DSH-better-sidebar
pnpm install
pnpm build        # 产物: lib/index.js + lib/invariant.js (host) + lib/client.js (client) + lib/types/*.d.ts

运行期依赖(cordis、react、@deepseek-ai/dsh-client-* 等)按官方插件清单规范声明在 peerDependencies——web profile 已内置全部 peer 依赖,安装本插件无需额外装包;dependencies 只保留插件自有的运行时依赖(node-pty、ws、xterm、CodeMirror、schemastery 等)。

2. 注册到 web profile

dsh plugin --profile web add link:/绝对路径/DSH-better-sidebar

(等价于手动把 "dsh-better-sidebar": "link:<绝对路径>" 写入 ~/.dsh/profiles/web/package.json 的 dependencies 并 pnpm install。)

然后编辑 ~/.dsh/profiles/web/cordis.patch.yml,追加插件挂载行(dsh plugin 只管理依赖清单,不写挂载行):

- insert:
    - id: better-sidebar
      name: 'dsh-better-sidebar'

3. 重启 DSH 并刷新页面

重启 DSH(你的 dsh web 启动方式),浏览器硬刷新(Cmd/Ctrl+Shift+R)后,右侧出现侧边栏即安装成功。

更新

pnpm build            # 产物: lib/index.js + lib/invariant.js (host) + lib/client.js (client) + lib/types
  • 只改了 client 代码(src/client/*)→ 硬刷新页面即可(bundle 由服务器按请求读取)
  • 改了 host 代码(src/index.ts、src/config.ts 等)→ 重启 DSH + 硬刷新

link: 引用无需重新 install。

🛠️ 开发

pnpm typecheck   # tsc --noEmit
pnpm test        # vitest(单元 + 冒烟 + 插件形态 guard:真实 git/fs/node-pty 交互)
pnpm build       # rm -rf lib && tsc(声明) + tsdown → lib/index.js + lib/invariant.js + lib/client.js + lib/types
pnpm watch       # tsdown --watch(client bundle 热重建)

规范符合性

插件按 DSH 官方插件规范组织(参考 dsh-external/turtle-ui 与 mainline packages/client/AGENTS.md)。安装通道与渲染方式是两个独立概念:安装始终走 profile 清单协议(dsh plugin / cordis.yml 行,见一键安装);下面的 portal 条目只描述面板在页面上的渲染方式。

  • 插件形态:export const name / inject / Config / apply,无 default 导出;tests/plugin-shape.spec.ts 通过 Loader.unwrapExports 守卫该形态
  • 清单:types + exports(. / ./invariant / ./client / ./src/* / ./package.json)、dshClient(platform: 'web' + 信息性 inject 边)、peerDependencies、engines、files 产物明细、prepare(消费者侧 tsdown,git 安装可用)
  • client 契约:仅导出 apply/inject(+ 类型);store 为 createSidebarStore() 工厂,实例归 apply 所有;src/invariant.ts 伴生;client bundle 复刻官方 preset(externals = 平台模块表 + runtime/client 豁免、纯度门、CSS Modules 内联)
  • 已知偏差:侧边栏面板经 portal(document.body + createRoot)挂载而非 slot——官方 slot 系统的 'root' 由 ui-layout 独占声明,重复声明 fail loud,外部插件无整面板 slot 可用;与 shell 的集成点(conversation.chat.turnTail)走官方 chain-slot 机制

🏗️ 架构

一个 npm 包,host/client 双半结构(与 DSH monorepo 内 client 包同构):

半 入口 职责
host src/index.ts → lib/index.js cordis 插件(Config 为 schemastery schema,可调 readLimit/mediaLimit/listLimit/terminalsPerSession/reconnectGraceMs):/sidebar/api/* JSON API、/sidebar/file 媒体路由、/sidebar/ws/terminal WebSocket;fs / git / pty 服务
invariant src/invariant.ts → lib/invariant.js 包属 invariant 伴生(注册包名,无运行时断言)
client src/client/index.tsx → lib/client.js 浏览器 bundle(__ModuleLoader__.load 闭包工厂):portal 侧边栏 + 各视图 + turnTail 拦截
  • 所有 API 携带 sessionId;cwd 权威值取自会话 header,会话未附加(页面加载竞态)时回退客户端摘要 cwd,再回退进程 cwd;终端按 ${sessionId}:${tabId} 键控,重连时若权威 cwd 变化则重启 shell 到正确目录
  • 路由与 /api 同款信任围栏(Host 头 loopback / connection.trustedHosts,src/trust-fence.ts,拷贝自 @deepseek-ai/dsh-client-connection,BSD-3-Clause)
  • client 状态按会话持久化到 localStorage(dsh-sidebar:v1:<sessionId>),读取时结构校验 + 宽度钳制视口 + 重复 id 重新编号
  • client bundle externals 仅模块表词条(react/cordis/ui-primitives 等),xterm/CodeMirror 等全部内联

🔐 安全边界

  • 路由受 Host 头信任围栏保护(与 /api 一致;0.0.0.0 部署时由 dsh web 启动器动态派生的 LAN IP 列表生效)
  • fs.write 仅文本写入、原子替换(临时文件 + rename);/sidebar/file 仅限会话 cwd 内的媒体文件
  • 提交/分支操作仅调用 git CLI,绝不设置 git 身份

⚠️ 已知限制(v1 非目标)

  • Git 无 push/pull/fetch;无文件 watcher(手动刷新)
  • 工具行内的文件打开按钮(核心代码)不可拦截,仅"产出文件"行被接管
  • 终端 Tab 拖拽到另一分栏时会重挂载(shell 重开);切换 Tab / 切换会话(30 秒内返回)/ 刷新页面不会

🖥️ 平台支持

代码按 Windows / Linux / macOS 三平台适配(macOS 为日常验证平台;Windows/Linux 的平台分支经单元测试覆盖,建议真机冒烟):

  • 路径处理全部走 node:path 平台 API(列表拼接、resolve);媒体路由的前缀检查与相对路径投影容忍混合分隔符,Windows 上大小写不敏感
  • Windows 上终端 shell 为 powershell.exe;node-pty 的 spawn-helper 修复(pnpm 剥执行位)自动跳过 Windows
  • node-pty 安装优先下载预编译二进制(prebuild.js,需网络),失败则源码编译——Windows 需 Visual Studio Build Tools,Linux 需 make/g++/python3,macOS 需 Xcode Command Line Tools;pnpm-workspace.yaml 已声明 allowBuilds: node-pty: true
  • git 操作仅依赖 git 在 PATH(Windows 需 Git for Windows)
S
Description
WorkBuddy/Tutti-style right sidebar enhancement for DeepSeek Harness: Tasks / Agents / Profile tabs, configurable display name (default apes--sidebar, preset feyOS). Built on dsh-better-sidebar.
Readme MIT
6.6 MiB
Languages
TypeScript 93.5%
CSS 4%
Shell 1.6%
JavaScript 0.5%
PowerShell 0.4%