Back to home@JoeyLearnsToCode

dsh-workspace-native-open

dsh plugin for native open workspace / 用于本地打开工作区目录的 dsh 插件

Stars
0
Language
TypeScript
Created
Aug 28, 2026
Updated
Aug 28, 2026
GitHub repo

Introduction

dsh-workspace-native-open

DeepSeek Harness (DSH) 的工作区菜单增强插件:通过 loopback 地址访问 Web GUI 时,工作区行的 ⋯ 菜单会增加三个本机动作——在文件资源管理器打开在终端打开在 Code 打开(在宿主机器上执行)。

English

✨ 功能

功能说明
在文件资源管理器打开用系统文件管理器打开工作区目录(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:手动部署

  1. 让包可被 harness 解析(例如放进 node_modules),并在 profile 的 cordis.patch.yml 中注册:
- insert:
    - id: workspace-native-open
      name: 'dsh-workspace-native-open'
  1. 重启 dsh web

本插件面向 Web profile(dsh --profile web),依赖 dsh-web-app bundle 提供的 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 下裸 spawn bash/code 没有控制台,窗口不可见);探测名带 .exe 后缀以确保命中 Windows 侧二进制而非 WSL 内的 Linux PowerShell。Code 优先尝试 Linux 侧 code 脚本,使 WSL 远程保留原生 WSL 路径。
  • Windows Code —— Node ≥ 20.12 拒绝直接 spawn .cmd shim(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.client bundle,也无浏览器资源构建流程。
  • 远程 / 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

📄 许可证

MIT