dsh-workspace-native-open
dsh plugin for native open workspace / 用于本地打开工作区目录的 dsh 插件
- Stars
- 0
- Language
- TypeScript
- Created
- Aug 28, 2026
- Updated
- Aug 28, 2026
Introduction
dsh-workspace-native-open
DeepSeek Harness (DSH) 的工作区菜单增强插件:通过 loopback 地址访问 Web GUI 时,工作区行的 ⋯ 菜单会增加三个本机动作——在文件资源管理器打开、在终端打开、在 Code 打开(在宿主机器上执行)。
✨ 功能
| 功能 | 说明 |
|---|---|
| 在文件资源管理器打开 | 用系统文件管理器打开工作区目录(explorer.exe / open / xdg-open,含 WSL 路径翻译) |
| 在终端打开 | 在工作区目录打开新终端窗口。Windows:pwsh > powershell(经 where.exe 探测;Windows 10+ 必带 PowerShell);WSL:路径经 wslpath 翻译后交 Windows 控制台打开;其他平台:$TERMINAL > bash |
| 在 Code 打开 | 始终展示——插件从不检测 VS Code 是否安装,点击后直接尝试打开目录,失败静默忽略(按需求)。WSL 下优先用 Linux 侧 code 脚本,不存在才走翻译路径上的 code.cmd |
| 仅 loopback 生效 | 页面地址为 localhost / 127.0.0.1 / ::1 / [::1](以及内建放行的 dsh.localhost)时才出现菜单项;宿主端点同时拒绝 Host 头不在白名单内的请求——远程或反代访问绝不暴露本机动作 |
| 静默运行、按需留痕 | 失败不打扰你,但每次请求、探测结果、spawn 失败原因、launcher 退出码都会以 workspace-native-open 前缀写入 harness 日志便于排查 |
| 路径分隔符安全 | 路径全程以 argv 数组传递(从不拼接 shell 字符串);Windows 下 / 与 \ 均可;PowerShell 单引号字面量保护空格与特殊字符 |
📦 安装
方式 A:直接从 GitHub 安装
dsh plugin --profile web add github:JoeyLearnsToCode/dsh-workspace-native-open
方式 B:本地链接(开发)
dsh plugin --profile web add link:/path/to/dsh-workspace-native-open
方式 C:手动部署
- 让包可被 harness 解析(例如放进
node_modules),并在 profile 的cordis.patch.yml中注册:
- insert:
- id: workspace-native-open
name: 'dsh-workspace-native-open'
- 重启
dsh web
本插件面向 Web profile(
dsh --profile web),依赖dsh-web-appbundle 提供的webServer服务。
🔧 工作原理
单一宿主插件,两部分:
- 宿主侧 —— 在
webServer服务上注册POST /api/plugin/workspace-native-open。处理器拒绝Host头不在 loopback 白名单内的请求,校验 action 白名单、强制 JSON content-type(与/api/*相同的 CSRF 防线),并确认路径是存在的绝对目录后,fire-and-forget 执行本机打开动作。请求体有限长 + 限时(413/408)。 - 客户端侧 —— 订阅
webserver/index-inject事件,向每个index.html注入一段经典 script 与样式。script 只在白名单内的 loopback 域名下激活(与宿主侧同一份名单,构建时内联):捕获工作区 ⋯ 按钮(以aria-label识别——dsh 未给该按钮/菜单任何稳定 id/class/data 属性,CSS Modules 类名带内容哈希)的点击,与紧随其后出现的 portal 菜单做点击因果配对,不做菜单文案扫描。菜单项语言取自<html lang>(dsh 的「语言」设置实时同步),文案构建时内联自package.nls.zh.json/package.nls.en.json,样式复用菜单卡片自身的 CSS 变量。
工作区行 → 路径的映射从行的 aria-label 提取工作区名,与 /api/workspace.list 返回的 title 精确匹配——搜索过滤、增删、重排都不会错位;仅同名工作区或 label 格式变化时才退回 DOM 顺序对齐(ui-workspace 按注册顺序渲染分组,未分组行没有菜单按钮)。
平台要点
- Windows 终端 —— 按
pwsh>powershell顺序探测目标 shell(where.exe取完整路径;Windows 10+ 必带 Windows PowerShell,因此不再保留 cmd 兜底),再由隐藏 launcher 用Start-Process -WorkingDirectory开新窗口。Windows 上控制台程序绝不能带detached: true——DETACHED_PROCESS会让它们静默退出(exit 0 但不执行任何命令)。 - WSL 上的终端与 Code —— 路径先经
wslpath翻译再交给 Windows 侧(WSL 下裸 spawnbash/code没有控制台,窗口不可见);探测名带.exe后缀以确保命中 Windows 侧二进制而非 WSL 内的 Linux PowerShell。Code 优先尝试 Linux 侧code脚本,使 WSL 远程保留原生 WSL 路径。 - Windows Code —— Node ≥ 20.12 拒绝直接 spawn
.cmdshim(CVE-2024-27980 加固),因此code.cmd通过 PowerShell launcher 调用(& 'code.cmd' 'dir'——PowerShell 的 & 自行按 PATH 解析 code.cmd,插件因此从不探测 VS Code 是否安装)。 - 生命周期 —— launcher 执行完即退出,其打开的窗口天然脱离 dsh 进程树,dsh 重启不会连带关闭。
🐛 故障排查
所有决策都会以 workspace-native-open 前缀写入 harness 日志:
- 收到请求 / 执行动作(info)
- 探测结果、spawn 失败原因、launcher 退出码与 stderr(warn)
失败同时镜像到浏览器控制台([dsh-native-open] …),并携带在端点 JSON 响应的 error 字段中。
403 not allowed from this host—— 请求的Host头不在 loopback 白名单内;请通过白名单内域名访问页面,或修改src/index.ts中的LOOPBACK_HOSTNAMES后重新构建。408 body timeout—— 请求体停滞;端点 10 秒后断开连接(超过 64 KB 的请求体返回413)。
📝 已知限制
- 菜单项通过 DOM 观察注入工作区菜单(依赖触发按钮的
aria-label、与 portal 菜单的点击因果配对,以及菜单的 CSS 变量);若点击时无法解析工作区路径,菜单项保持禁用(置灰)。 - 插件为纯宿主实现——无
dsh.clientbundle,也无浏览器资源构建流程。 - 远程 / LAN 访问按设计不展示菜单项,端点同时拒绝白名单外的
Host头;dsh.localhost已内建放行——如需放行其他本地域名,修改src/index.ts中的LOOPBACK_HOSTNAMES后重新构建。 - WSL 上「在终端打开」会在翻译后的
\\wsl$路径打开 Windows 控制台——与资源管理器动作相同的 Windows 桌面交接约定。
🛠 开发
# 修改 src/index.ts 后重新构建 loader 产物
bun run build
src/index.ts—— 插件源码(经dsh.bundle.patch以 dsh bundle 方式加载)。lib/index.js—— 构建出的 ESM 产物,由package.json#main引用。cordis.patch.yml—— 插入workspace-native-open行的 bundle patch。package.nls.zh.json/package.nls.en.json—— 简体中文 / 英文翻译目录(菜单标签与页面匹配字面量),构建时内联进lib/index.js。