dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
为侧边栏「工作区文件」树添加自定义右键菜单:新建文件夹、重命名、在文件管理器中显示、浏览器打开、VS Code 打开、复制路径、流式 ZIP 下载、删除。
为 DeepSeek Harness Web 客户端侧边栏的「工作区文件」树添加自定义右键菜单,替代浏览器默认菜单。 纯前端 + Host 路由实现,无第三方依赖、无构建步骤。项目名为
dsh-menu,后续可在此基础上扩展更多菜单。
已发布到 npm,一行命令装好(装完重启宿主进程 + 浏览器硬刷新):
dsh plugin --profile web add dsh-menu
| 深色模式 | 浅色模式 |
|---|---|
![]() | ![]() |
右键「工作区文件」中的任意行 → 自定义菜单(新建文件夹 / 重命名 / 在文件管理器中显示 / 在浏览器中打开 / 在 VS Code 中打开 / 复制文件路径 / 下载文件夹 / 删除)
右键「工作区文件」任意文件 / 文件夹行,弹出自定义菜单(顺序即菜单顺序):
| # | 菜单项 | 说明 |
|---|---|---|
| 1 | 新建文件夹 | 内联输入框;目录行在其内部创建,文件行在其父目录创建 |
| 2 | 重命名 | 内联输入框,可编辑当前文件名 |
| 3 | 在文件管理器中显示 | 调用官方 remote 服务,在资源管理器中定位该文件 |
| 4 | 在浏览器中打开 | 文件原样返回内容;目录渲染为可浏览的 HTML 列表 |
| 5 | 在 VS Code 中打开 | 自动解析本机 VS Code 并打开文件/目录 |
| 6 | 复制文件路径 | 复制工作区路径到剪贴板 |
| 7 | 下载文件夹 / 下载文件 | 目录打包为流式 ZIP 下载;文件直接下载 |
| 8 | 删除(红色) | 危险项红色标注,点击后二次确认 |
backdrop-filter: blur(18px) saturate(140%)Enter 提交、Esc 取消Esc、滚动、窗口缩放都会自动关闭菜单zh / en 两套文案,跟随界面语言dsh-menu/
├── index.js # Host 半区:全部文件系统操作路由(约 743 行)
├── client.js # Client 半区:右键菜单 UI(约 680 行)
├── package.json # 包元信息 + dsh.bundle / dsh.client 声明
├── cordis.patch.yml # 把插件并入 Harness profile 的补丁
├── screenshot-dark.png # 深色模式效果图
├── screenshot-light.png # 浅色模式效果图
└── README.md # 本文档
client.js)在文档捕获阶段拦截 contextmenu 事件,命中 [data-files-entry] 树行后 preventDefault 掉浏览器默认菜单,改弹自定义菜单(挂载在 shell.overlay 槽位,是一个独立 overlay 组件)。index.js)通过 connection.fetch.register 注册一组 /api/workspace-files-menu/* 路由,所有文件系统操作(重命名 / 建目录 / 删除 / 打开 / 下载)都由 Host 执行,Client 只发 JSON。React.useSyncExternalStore,样式只用官方主题 CSS token(--dsw-alias-*)。remote.session.openWorkspacePath({ action: "reveal" }),其余操作走自建路由。错误响应统一为 { ok: false, error: { code, message } }。
| 路由 | 方法 | 参数 | 行为 |
|---|---|---|---|
/api/workspace-files-menu/rename | POST | { sessionId, path, name } | 重命名文件或目录(仅改名,不移动) |
/api/workspace-files-menu/mkdir | POST | { sessionId, path, name } | 在 path(必须是目录)内新建文件夹 |
/api/workspace-files-menu/delete | POST | { sessionId, path } | 删除文件或目录(递归) |
/api/workspace-files-menu/open-app | POST | { sessionId, path, app: "vscode" } | 在外部应用中打开;当前支持 vscode |
/api/workspace-files-menu/open | GET | ?sessionId=&path= | 浏览器打开:文件返回内容,目录返回 HTML 列表 |
/api/workspace-files-menu/download | GET | ?sessionId=&path= | 文件直接下载;目录流式打包 ZIP 下载 |
主要状态码:200 成功;400 非法参数 / 非法文件名 / 父级不是目录;403 目标在工作区之外(含删除根、越界穿越);404 目标不存在;409 重名冲突(rename 到已存在名 / 已存在同名新目录)。
前置:已部署并运行 DeepSeek Harness(含 Web GUI);宿主进程可直接运行 Node.js 与 pnpm。
dsh plugin --profile web add dsh-menu
dsh plugin --profile web add github:tangu2023/dsh-menu
D:\plugins\dsh-menu),无需构建。cordis.patch.yml(把 dsh-menu 插入当前 profile)。Ctrl+Shift+R)加载 Client 半区。说明:
cordis.patch.yml是唯一要求的配置文件,请勿手工修改 profile 下的package.json/cordis.patch.yml,统一由插件管理器写入。本插件零依赖、无构建步骤,所以 git 安装不需要任何 build 授权。
卸载:
dsh plugin --profile web remove dsh-menu(或插件管理器中禁用后移除)。若 pnpm 提示新包保护(
minimumReleaseAge),dsh plugin add会自动把dsh-menu加入 profile 的minimumReleaseAgeExclude,无需手动处理。
在侧边栏「工作区文件」树中右键任意文件或文件夹行即可弹出菜单;「新建文件夹 / 重命名」为内联输入,「删除」需二次确认,其余操作即时执行并 toast 反馈。
sessionWorkspaceRoot),再对目标做双向往返路径校验(processPathFromHostPath → fs.resolve → processPath)与严格前缀边界检查(防 D:/workspace2 这类前缀穿透),任何越界请求返回 403。403。400;重名返回 409;路径按 normalize 后仅以名称参与拼接,杜绝路径穿越。/open 返回的任何 text/html 都会附加 Content-Security-Policy: sandbox,防止工作区内 HTML 以 GUI 同源权限执行。Readable.from + Readable.toWeb 背压),手写 ZIP 写入器(UTF-8 文件名、CRC32、data descriptor),零依赖。node --check index.js / node --check client.js。index.js):需要重启 DSH 宿主进程(看门狗会自动拉起)。client.js):浏览器硬刷新即可(Host 按请求从磁盘读取 client 模块并自带版本缓存破击,无需重启)。curl -X POST http://127.0.0.1:12012/api/workspace-files-menu/rename \
-H "Content-Type: application/json" \
-d '{"sessionId":"<会话ID>","path":"D:/workspace/a.txt","name":"b.txt"}'
| 现象 | 处理 |
|---|---|
| 右键仍是浏览器默认菜单 | 浏览器硬刷新;确认 shell.overlay 槽位存在 workspace-files-menu 占用 |
| Host 路由 500 / 404 | 插件是 enable 状态但模块未重载 → 重启 DSH 宿主进程 |
| 「在浏览器中打开」403 | 目标不在当前会话工作区内 |
| 重命名报「已存在」 | 目标名已占用(409),换名即可 |
下载中文名文件报 500 | 已在 1.0.0 修复(RFC 6266 响应头编码);旧版本请升级 |
安装 bundle 报 'pnpm' 不是内部或外部命令 | 宿主进程找不到 pnpm → 执行 npm i -g pnpm,或在宿主工作目录放一个 pnpm.cmd shim 指向全局 pnpm |
shell.overlay 槽位:右键菜单的宿主容器data-files-entry / data-files-path--dsw-alias-*(缺失时样式降级,功能不受影响)dsh-api-session-controller / dsh-api-remotes / dsh-client-ui-sidebar-rightremote.session.openWorkspacePath({ action: "reveal" })(用于「在文件管理器中显示」)/api/workspace-files-menu/* 命名空间,不会与其它插件撞名。workspace-files-menu 追加占用(槽位 id 与包名无关,短 id 便于在检查工具里辨认),不替换、不修改任何已有条目。[data-files-entry] 且能解析出会话时接管;其它区域(含其它插件的面板)保持浏览器默认菜单。contextmenu,两者可能各弹一个菜单(当前未发现此类插件)。wfm- 前缀,<style> 带 data-plugin 标记,便于定位与移除。window.__ModuleLoader__.load 注册自身模块)。node:fs/promises、node:stream、node:child_process),无第三方依赖、无编译步骤。pnpm(见上方常见问题)。PATH 中的 code 命令推导真实 Code.exe,并回退常见安装目录(%LOCALAPPDATA%\Programs、Program Files (x86)、Program Files);已实测 D:\Program Files\Microsoft VS Code。/Applications、/usr/bin/code、/usr/local/bin/code 等;其余路由(下载 / 浏览器打开 / ZIP 打包)跨平台通用。| 渠道 | 地址 | 状态 |
|---|---|---|
| npm | dsh-menu | ✅ 已发布 |
| GitHub | tangu2023/dsh-menu | ✅ 公开,MIT |
| 插件索引 | GitHub topic dsh-plugin | ✅ 已打标(索引站按此 topic 定期同步) |
| 社区清单 | awesome-dsh-plugin PR #6885 | ⏳ 已提交,等待维护者合并 |
合并后即可在 DSH 设置面板内的 dsh-market 插件市场中搜到并一键安装。
minimumReleaseAge)说明。500;现按 RFC 6266 输出 filename + filename*=UTF-8''…。MIT © 2025