dsh-plugin-open-with
Đã xác minhdsh-plugin-open-with · v2.0.0 · MIT · Giao diện web
Capsule split-button in the dsh web conversation header: open the workspace in VS Code, terminal, or file explorer — extensible to more launchers.
Cài đặt
dsh plugin add dsh-plugin-open-with Xác nhận layer đã áp bằng dsh --profile default --dump-config — xem hướng dẫn cài plugin.
Mã nguồn
Thẻ
Tác giả
Readme
dsh-plugin-open-with
打开方式 · 胶囊拆分按钮
在 DeepSeek Harness Web 会话头部添加胶囊拆分按钮,一键在当前工作区打开 VS Code、终端(CMD / PowerShell)和文件资源管理器。
🖼 效果图 · 🧩 功能 · 🚀 安装 · 🔒 安全模型 · 🚧 已知限制 · 🏗 构建与扩展 · 🤝 贡献 · 📜 License
🖼 效果图


🧩 功能
- 💊 胶囊拆分按钮:左半边执行当前选择的启动器;右半边下拉菜单列出全部启动器,点击即切换并立即启动。
- 🪧 默认启动器:VS Code、CMD、PowerShell、文件资源管理器。它们只是预置的自定义项——毫无特权,同样可以被改、隐藏、删除。
- ⚡ 设置即改即生效:设置页每次保存后,host 归一化后的文档通过进程内广播推给胶囊按钮,菜单即时重渲染。无需等点开下拉;展开菜单时仍会补读一次,仅作为兜底(如直接手改 settings.json)。
- ⚙️ 设置页面:在 DSH 设置面板中注入「Open With」配置区域,支持:
- 统一的项目管理:所有启动器都是平等的普通项,支持统一的添加 / 编辑 / 删除 / 拖拽排序 / 可见性控制。预设项不过是最初写入的那批,编辑与删除同样开放,下拉菜单与设置页所见即所得。
- 当前项选择:点击卡片切换当前启动器,胶囊按钮同步更新。
- 按钮位置可切换:胶囊按钮可注入会话标题旁(
actions)或右侧工具区(utilities),保存后立即迁移槽位。 - 按钮顺序可调:同一槽位内按 order 值升序排列,数值越小越靠前(官方「在应用中打开」为 -10),保存后立即重排。
- 传递会话目录:每项可选是否把会话工作区目录作为参数传给启动器(默认传递)。
- 一键恢复默认:把启动项列表还原为内置四项(两步确认;只动列表,不重置按钮位置与顺序)。
- 接管内置按钮:通过本插件自己的 bundle 补丁,声明式关闭 DSH 内置的
open-in-app(Host 与 Client 两半同进同退),会话头部不会出现两个打开按钮。补丁层随插件加载、也随插件消失 —— 卸载后内置按钮自动恢复,本插件从不改动 profile 的cordis.patch.yml。 - 图标自动更新:图标从本地可执行文件按需提取;编辑路径后,带修订号的 URL 主动破除浏览器缓存,图标随之更换。
- 持久化存储:设置自动保存到
profile/<mode>/open-with/settings.json,重启后保持。
- 🌍 中英双语 UI:跟随 DSH 客户端全局 locale 自动切换。
🚀 安装
方式一:从 npm 安装(推荐)
已发布到 npm:dsh-plugin-open-with(当前最新 2.0.0)。在终端执行:
# 安装
dsh --profile web plugin add dsh-plugin-open-with
# 验证安装版本
dsh --profile web plugin list
# 卸载
dsh --profile web plugin remove dsh-plugin-open-with
方式二:从仓库安装(开发 / 调试)
git clone https://github.com/hyrinx/dsh-plugin-open-with.git
cd dsh-plugin-open-with
npm install
npm run build
dsh --profile web plugin add "link:$($PWD.Path)"
重启 dsh web 生效。后续修改源码只需重新 npm run build + 刷新浏览器。
🔒 安全模型
本插件会在 DSH 宿主端启动外部程序,安全措施如下:
- WebServer 路由 + 连接信任栅栏:host 端在
ctx.webServer注册 settings / icon / open / log 四条路由;每条都先经ctx.connection.requestRejection校验 Host / Origin,抵御 DNS rebinding 与跨站调用。请求体限 64 KiB 且必须是 JSON。 - 开放 item 模型,逐项校验:启动目标为设置文档中的普通项 id,Wire 端校验 id 必须真实存在;路径必须是可执行文件存在的绝对目录路径,杜绝任意可执行文件注入。
- 版本化图标寻址:图标路由按 id + 修订号寻址,浏览器无法命中过期字节;取不到图标时返回 404 且前端留空位,不展示误导性兜底图。
- 双半一致、可回退的接管:内置
open-in-app的 Host / Client 是一对,由本插件的 bundle 补丁按 id 一并关闭,避免只留一半的残缺形态;该补丁不属于 profile 配置,卸载即自动恢复。
🚧 已知限制
- 仅支持 Windows:macOS / Linux 适配需要社区贡献。
- 必须通过本机浏览器回环访问(
localhost/127.0.0.1)。 - VS Code 需要先把
code命令加入 PATH:首次运行时 host 用 PATH 解析预设项为绝对路径并写入配置;若命令不在 PATH,该项会保留裸名,需在设置页改填完整.exe路径。 - 终端使用系统自带 cmd.exe / powershell.exe:自定义启动器支持任意
.exe绝对路径。 - 图标从本地可执行文件按需提取:由 host 端用 PowerShell 的
ExtractAssociatedIcon取图标并缓存;取不到时图标位置留空,不显示占位图。
🏗 构建与扩展
npm install
npm run build # 先清 lib,再 tsdown 出主/客两端 bundle,tsc 出 lib/types/*.d.ts
npm run clean # 只删 lib(改过 src 文件结构后 build 会自己调它)
npm run typecheck # tsc -p tsconfig.json --noEmit
npm pack # 发布前预览 tarball 内容
npm publish --access public
目录结构(双半包:一个 host 半 + 一个 dsh.client 浏览器半):
dsh-plugin-open-with/
├── src/
│ ├── index.ts host 半入口:四条 webServer 路由 + connection 信任栅栏
│ ├── shared.ts 两半共享的路由、协议、设置模型与归一化
│ ├── storage.ts settings.json 原子读写 + profile 路径解析
│ ├── logger.ts host.log 落盘
│ ├── launch.ts 各启动器的 spawn 配方与可执行文件解析
│ ├── icons.ts 从可执行文件提取图标
│ └── client/ 浏览器半
│ ├── index.ts 入口:挂载按钮、注入设置页、注册词典
│ ├── OpenWithButton.tsx 胶囊拆分按钮
│ ├── OpenWithSettings.tsx 设置面板(添加/编辑表单、拖拽排序、可见性)
│ ├── ItemIcon.tsx 两个界面共用的行内图标
│ ├── settings-events.ts 设置变更进程内广播(按钮即时刷新 + 图标破缓存)
│ ├── controller.ts 浏览器 → host 的 RPC 载体
│ └── locales.ts 中英双语词典
├── locale/ 插件展示元数据(DSH 插件管理页的标题与描述来源)
├── lib/ 构建产物,勿手改(index.js / client.js / types/)
├── cordis.patch.yml bundle 补丁:插入本插件,并按 id 关掉内置 open-in-app
├── tsdown.config.ts 双配置:host 出 ESM,client 出 ModuleLoader 闭包工厂
└── tsconfig.json 只出声明(emitDeclarationOnly → lib/types/)
模型核心:所有启动器都是同一个 OpenWithItem(id / name / path / passCwd),没有预设与自定义的区分。默认项(DEFAULT_ITEMS)仅在设置文档不存在时作为种子写入,host 逐项把裸命令解析为绝对路径后落盘;此后每项就是普通项,可改名、改路径、隐藏、删除。要使一项不可被删除,并不存在这种情况——设计上所有项一律平等。
lib/ 与 package.json#exports 的子路径一一对应:. → lib/index.js、./client → lib/client.js、./locale/*.json → locale/*.json。展示名与描述只来自 locale/*.json 的 meta(package.json 的 name / description 仅作 fallback),locale/en.json 是 DSH 的发现基线,缺了整包元数据就不生效。
如何新增一个启动器:
- UI 方式(推荐,无需改代码):设置页 → Open With → 「+ Add」,填写名称与可执行文件绝对路径;支持拖拽排序与可见性控制。
- 代码方式(想作为默认项内置):修改
src/shared.ts的DEFAULT_ITEMS数组即可——因为所有项本就统一,新增默认项只需补一条{ id, name, path, passCwd },无需改动类型或启动分发。首次写入时 host 会解析并落盘。
🤝 贡献
欢迎以下方向的 PR:
- 🍎🐧 macOS / Linux 平台适配:实现各平台的 shell、文件管理器启动与图标提取。
- 🖥 更多 IDE 启动器:JetBrains 全家桶、Sublime Text、Neovide、Cursor、Windsurf……
- 💻 更多终端候选:Windows Terminal (
wt)、PowerShell 7 (pwsh)、Git Bash、Alacritty、WezTerm…… - ⚙️ 设置页增强:导入/导出配置、批量操作
- 🎨 UI 反馈:为启动过程加入进行中 / 成功 / 失败的可视状态
提 PR 前请确保:
npm run typecheck # 通过
npm run build # 通过
npm pack # 无 WARN / error