DSH-better-sidebar

1.9kStar126Fork89Issue3Watching

为 DSH 提供类 VS Code 的右侧栏+底部双工作台:文件编辑、真实终端、Git、嵌入浏览器与后台任务;按会话隔离,并向其他插件开放页面与文件预览器注册。

语言
TypeScript
License
MIT
分支
main
deepseekdeepseek-harnessdshdsh-better-sidebardsh-pluginsidebar

安装

$ dsh plugin --profile web add github:omdsh-dev/DSH-better-sidebar

在终端中运行以上命令,通过 dsh CLI 安装此插件。可在右上角切换 Profile。 第一次用 dsh?看这篇新手教程

一句话定位

为 DeepSeek Harness (DSH) 的 Web 端提供一个 VS Code 风格的右侧栏 + 底部面板双工作台,自带文件浏览/编辑、真实终端、Git 面板、内嵌浏览器与后台任务视图,按会话隔离,并把 ctx.betterSidebar 服务开放给其他插件注册新页面与文件预览器。

核心能力

  • 浏览与编辑会话工作区内的文件:可缩进的目录树(含软链接识别、失效链接标红)+ CodeMirror 编辑器,支持 14+ 语言的语法高亮、搜索替换、撤销重做;可直接预览图片 / PDF / Markdown / HTML(沙箱 iframe),Office 需安装推荐插件
  • 在侧边栏运行真实终端:xterm.js 渲染 + node-pty 后端 shell,断线重连会回放上次 transcript;切换标签页或刷新页面 shell 不退出
  • 暂存 / 提交 / 还原 / 检出 / 历史与差异查看(diff 走专属 diff tab),支持 cherry-pick / revert
  • 内嵌浏览器:以独立 tab 多开网页,内容走沙箱 iframe;外部链接可按协议拦截到侧边栏(HTTP 默认开,HTTPS 默认关)
  • 后台任务面板:子代理拓扑 + 后台任务的退出码、实时输出与强制终止
  • ctx.betterSidebar 服务开放给任意第三方插件,通过 registerTab / registerFileViewer 挂入新的侧边栏页面和文件类型预览器,能力与内置功能对等

技术实现

  • 语言: TypeScript(ESM);前端用 React 18,后端用 Node 20+,同时为 host 和 client 两个 half 打包
  • 关键依赖: node-pty(真实终端 shell);@xterm/xterm + @xterm/addon-fit(终端前端);@codemirror/*(代码编辑器全家桶);ws + rxjs + schemastery(终端 WebSocket、状态响应式、设置 schema 校验)
  • 架构模式: 双半宿主插件(dual-half)。host half(src/index.ts)注册 /sidebar/api/* JSON 接口、/sidebar/file 媒体、/sidebar/html 沙箱预览、/sidebar/ws/terminal 终端 WebSocket、/sidebar/ws/agent-terminals 推送,全部走和 /api 同源的 Host-header trust fence;client half(src/client/index.tsx)用 ctx.provide('betterSidebar', service) 把注册表服务暴露给所有挂载顺序在后的插件
  • 入口文件: host src/index.ts(导出 apply / Config / Context),client src/client/index.tsx(导出 apply / inject),挂载声明在 cordis.patch.yml + package.json#dsh.bundle.patch

适用场景

当 DSH 用户需要在浏览器内"看见并操作"AI 协作产生的项目文件——比如手动修改一段代码、跑几个 shell 命令查看中间产物、对比两次修改的差异——而不想离开 DSH 切去 VS Code 或系统终端。另一个典型场景是插件作者要为自己的插件添加专属侧边栏页面和文件预览器,DSH-better-sidebar 提供注册表服务让插件之间水平扩展,免去重复造一套面板、tab 栏、分栏、终端与状态管理。

前置依赖与兼容性

依赖最低版本说明
DeepSeek Harness (DSH)0.1.0-rc.6全部 @deepseek-ai/dsh-*@deepseek-ai/cordis 均锁在 ^0.1.0-rc.6,pre-release dist-tag 需对齐(见 package.json 84-104 行)
Node.js>=20engines.node 字段声明(package.json:39-41
平台macOS / Windows / LinuxmacOS 由 CI 每日验证,Linux/Windows 由单元测试覆盖;node-pty 优先用预编译二进制,否则需在本机准备构建工具链(macOS Xcode CLT / Linux make+g+++python3 / Windows VS Build Tools)
原生模块node-pty ^1.1.0仅终端功能依赖;缺失时插件其余能力照常可用(0.12.3 引入的懒加载 + 降级,见 issue #140)
代码包pnpm >=10pnpm 11 默认拦截 build 脚本;首次装需要在 ~/.dsh/profiles/webpnpm approve-builds --all 放行 node-pty

安装方式

dsh plugin --profile web add github:omdsh-dev/DSH-better-sidebar

配置项

本插件分两类配置:宿主管道配置(写在 ~/.dsh/profiles/web/cordis.patch.yml,少改),以及用户偏好(在 DSH 设置页 → 侧边栏卡片,多改)。

宿主管道配置(defaults of Config schema)

配置类型说明默认值
readLimitnumber单文件文本读取字节上限(超出标记为截断)524288 (512 KB)
mediaLimitnumber图片/PDF/HTML 预览的最大字节数20971520 (20 MB)
listLimitnumber文件树单层目录最多列出的行数1000
terminalsPerSessionnumber单个会话最多同时打开多少个 UI 终端3
reconnectGraceMsnumber终端 WebSocket 断线后保留 shell 进程的宽限时长(ms),方便刷新/切 tab 后无感重连30000
shellstringUI 终端与 agent 终端统一使用的 shell(绝对路径或可执行名);空 = 自动探测(POSIX 用 $SHELL/登录 shell,Windows 依次探测 pwsh → PowerShell 5.1)""

用户偏好(在 DSH 设置 → 侧边栏卡片)

偏好类型说明默认值
openByDefaultboolean新建会话时是否默认展开侧边栏false
defaultWidthPercentnumber (20–60)侧边栏宽度占窗口的百分比35
autoOpenSubagentboolean当前会话派生子代理时是否自动展开侧边栏并跳到子代理页true
autoOpenJobsboolean新增后台任务时是否自动展开侧边栏并跳到任务页true
agentTerminalToolsboolean是否给模型注入 terminal_create/list/send/read/wait_for/resize/signal/close 这些工具;关闭时已创建的 agent 终端一并释放false
bottomPanelAutoTerminalboolean当前会话首次展开底部面板时是否顺便开一个终端 tabtrue
terminalFontFamilystring终端字体栈,留空跟随主题(--ds-font-family-code""
terminalFontSizenumber (9–32)终端字号(px)13
interceptOpenPathboolean聊天里点文件路径(工具行、生成文件、文本引用)时是否拦截到侧边栏编辑器(与编辑器自身的总开关同时开启才生效)true
editorExplorerboolean编辑器是否合并模式(顶部路径输入框 + 可停靠树面板);关闭时回到老的独立编辑器true
titleBarCompatboolean顶部预留原生标题栏空间的兼容模式(仅 Windows 无边框窗口需要)false
titleBarStripPxnumber (0–120)上述兼容模式预留的高度40
htmlViewerNoSandboxbooleanHTML 预览是否取消沙箱(不推荐,仅用于完全可信本地内容)false
htmlViewerDefaultUnsafebooleanHTML 预览默认就是无沙箱状态(每页可用顶部状态行一键恢复)false
browserNoSandboxboolean浏览器 tab 是否取消沙箱(不推荐,仅用于完全可信站点)false
browserInterceptLinksboolean是否把 GUI 内的外链点击拦截到侧边栏(总闸)true
browserInterceptHttpbooleanHTTP 外链默认拦截到侧边栏true
browserInterceptHttpsbooleanHTTPS 外链默认拦截到侧边栏(多数 HTTPS 站拒绝 iframe,默认关闭)false
tabsEnabledobject按 tab id 单独禁用(如 {"editor": false}),缺省 = 启用{}
viewersEnabledobject按 file viewer id 单独禁用(如 {"code": false}),缺省 = 启用{}
pluginSettingsobject各第三方插件自有的设置 blob(key = 描述符 id,给 settings.pluginToggles 用){}

常见问题

Q: 安装后页面上出现两个侧边栏怎么办?

A: 这说明同时走了两条挂载通道(npm bundle + 手写 patch),或在切到 bundle 通道前没清掉手写的挂载行。删除 ~/.dsh/profiles/web/cordis.patch.yml 里的手写 - insert: ... better-sidebar ... 行,让 npm 通道独占即可(README_EN.md:117-119)。

Q: 终端提示"node-pty failed to load"或终端根本打不开怎么办?

A: 这是 node-pty 没正确加载。0.12.3 之后(issue #140)插件不会因此崩溃:UI 终端 tab 会显示一条可复制的修复命令、agent 终端工具会被自动跳过。你只需在 ~/.dsh/profiles/web 里跑 pnpm approve-builds --all && pnpm rebuild node-pty,重启 DSH,回到终端 tab 点"Retry"。

Q: 它要求什么 Node 与 DSH 版本?为什么我换 Node 老版本就装不上?

A: 强约束:engines.node: ">=20";所有 @deepseek-ai/dsh-*@deepseek-ai/cordis 都被锁在 ^0.1.0-rc.6package.json:84-104)。升 DSH 或 Node 后遇到装载失败,先核对发行 dist-tag 与 lockfile 是否同步。

Q: 别的插件怎么向它注册新页面和文件预览器?

A: 在你的插件 client half 用 ctx.betterSidebar.registerTab({...}) / registerFileViewer({...})——和内置 6 tabs + 6 viewers 走的是同一套 API。务必用 ctx.effect(() => register(...)) 包一层,disposer 由 Cordis 在 HMR 时自动调用,避免反复装载报"already registered"。全文指南见仓库 AGENTS.md / docs/external-plugin-guide.md

Q: 浏览 / 编辑 / 终端的数据存在哪?会话之间会不会串?

A: 布局、tab 列表、面板几何等 UI 状态存在浏览器 localStorage 并以 sessionId 隔离;宿主侧的文件读写、Git 操作、终端进程、媒体/HTML 预览路径全部限定在当前会话的 cwd 下,不会越界读其他会话的工作区。卸载插件会清掉 UI 状态,磁盘上的项目文件与 .git 完全不受影响。

Q: 我能完全卸载吗?

A: 能。~/.dsh/profiles/web/package.json 的 dependencies 里去掉 "dsh-better-sidebar" 行,pnpm install 后重启 dsh web,硬刷新浏览器即可。该插件不写入 home 目录、不依赖后台进程,没有"残留物"。

Q: 内嵌浏览器能登录 GitHub 之类的站点吗?

A: 浏览器与 HTML 预览默认跑在沙箱里(opaque-origin iframe,allow-same-origin 关闭),无法承载第三方 cookie / 登录态,需要登录的站点会自动开系统浏览器;站点被 X-Frame-Options 或 CSP frame-ancestors 拒绝嵌入时,侧边栏会显示原因并提供"在浏览器打开"按钮。需要登录的站可以在设置里临时关掉沙箱,但这样浏览内容会获得与 GUI 同源的权限,仅在可信站点上用。

Q: 移动端能用吗?

A: 右侧栏在窄屏(<768px)下会自动合并为全宽抽屉,照常能用;底部面板在窄屏不可用,浏览器面板里的 tab 会被并入右栏一次;切回宽屏后这些 tab 不会自动回到右栏,需要手动拖回。这是 README 已记录的已知行为。

上手难度

入门 — 单条 dsh plugin add + 硬刷新即可用;想要的就是右侧栏 + 文件编辑 + 内置终端/HTTP 外链浏览。再往深一点调的是:在设置里挑选要启用的预览器、调整面板宽度、决定 agent 终端工具是否注入、决定 HTML/浏览器沙箱是否取消等。

已知问题与限制

  • Git 没有 push/pull/fetch:内置 Git 面板覆盖 status / diff / stage / commit / branch / checkout / log / cherry-pick / revert / discard / show;push/pull/fetch 需要装推荐插件 dsh-git-remotes
  • 没有文件 watcher:文件树不会自动刷新,需要手动点刷新按钮
  • 工具行内联"打开文件"按钮无法被拦截:只有经过 ctx.workspaces.openPath 的路径(即"在生成文件"、文本引用等)会被 interceptOpenPath 拦截
  • 把终端 tab 拖到别的 pane 时会重启:跨 pane 移动 terminal tab 会重新挂载(remount),shell 进程不跨 pane 保留
  • Office 三件套预览已迁到推荐插件:0.12 起 .docx/.xlsx/.pptx 不再内置,需安装"Add Plugins"弹窗里的 Office 预览插件;没装时这些文件会落到下载按钮或代码兜底
  • 浏览器沙箱无登录态 + 部分站拒绝嵌入:需要登录的页面请在浏览器里完成;拒绝嵌入的站会在侧边栏给"在浏览器打开"
  • HTML 预览只显示已保存的文件:未保存的编辑器修改不会反映到预览
  • 移动端无底部面板:宽 <768px 时底部面板不可用,tab 会并入右栏一次;切回宽屏后这些 tab 不会自动回到右栏(README 已记录,README_EN.md:226)
  • node-pty 加载失败已降级(issue #140):终端 tab 会显示修复 banner,agent 终端工具自动跳过,插件其余功能不受影响
  • 双重挂载会得到两个侧边栏:同时启用 npm bundle + 手写 patch(或同时挂 npm bundle + plugin-registry)必须保留一条通道;详情见上文"常见问题"
  • 透明/玻璃质感皮肤的处理(issue #90):终端与编辑器面板会主动回退到不透明底色,避免文字叠在皮肤画上滚动;非面板表面仍跟随主题