open-dsh-plugins/dsh-open-in-app0

dsh-open-in-app

Open the current workspace folder with an installed application (Finder, Terminal, VS Code, Ghostty, Zed, ...) from the session header of the dsh web UI

AI 분석

核心用途是在 Web UI 中快速调用本地应用打开当前工作区。适合频繁需要在网页聊天与本地编辑器/终端之间切换的 DSH 用户。

패키지
dsh-open-in-app
버전
0.1.2
라이선스
MIT
최근 업데이트
2026. 8. 24.

설치

$npx -p @deepseek-ai/dsh dsh plugin --profile web add github:open-dsh-plugins/dsh-open-in-app

dsh-open-in-app

English | 中文

面向 DeepSeek Harness(dsh)Web UI 的一个插件:在聊天窗口右上角提供一个按钮,用已安装的应用打开当前会话的工作区文件夹。菜单按终端模拟器流行 IDE/编辑器白名单整理,分组为“终端应用”和“编辑器与 IDE”。

仓库:github.com/open-dsh-plugins/dsh-open-in-app

截图

open-in-app 控件位于会话头部工具行(聊天窗口右上角),“Session log”按钮旁边。文件夹按钮一键打开工作区——使用你上次为该工作区选择的应用;下拉箭头打开选择菜单,显示最近使用的应用、系统默认文件夹处理器,以及主机上白名单内的终端和编辑器——每一项都带有应用图标:

open-in-app 选择菜单:最近使用、系统默认、终端应用与编辑器与 IDE

功能

  • 在会话头部工具行(聊天窗口右上角)新增一个 Codex 风格的拆分控件,样式与**“Session log”头部按钮一致的胶囊**(32px 高、1px 边框、18px 圆角、悬停填充),两段之间用细线分隔:
    • 文件夹按钮一键打开工作区——使用你上次为该工作区选择的应用(按 cwd 记录在 localStorage 中,按钮上显示其图标),否则回退到默认编辑器(优先级最高的已安装编辑器——VS Code → Cursor → Windsurf → Zed → IntelliJ IDEA → …——然后是系统默认);
    • 下拉箭头打开菜单,包含置顶的**“最近使用”条目、一个“系统默认应用”条目(内置 host.openPath 行为;macOS 上是 Finder),以及主机上已安装的白名单终端和编辑器,每一项都带有应用图标(从应用包中以 32px 读取,以 data: URL 传递;无法解析图标的仅显示名称)。“系统默认应用”行显示默认文件夹处理器的真实图标**(macOS 是 Finder,Windows 是资源管理器,Linux 是 xdg-mime 默认文件管理器),无法解析时回退为文件夹图标。
  • 从菜单选择应用即可用该应用打开当前工作区文件夹:
平台应用发现打开命令图标
macOS/Applications/System/Applications(+ Utilities)、~/Applications`open -a ""
`通过 sips 将 bundle .icns → 32px PNG;无 icns 的 bundle 用 qlmanage 回退
Windows%ProgramFiles%%ProgramFiles(x86)%%LOCALAPPDATA%\Programs(顶层 *.exe`cmd /c start ""
`通过 PowerShell [System.Drawing.Icon]::ExtractAssociatedIcon 提取内嵌 exe 图标
Linux/usr/share/applications/usr/local/share/applications~/.local/share/applications*.desktop`gtk-launch
(回退到 xdg-open`)freedesktop Icon= 值:绝对路径、hicolor 主题(128→16)、可缩放 svg、pixmaps

白名单

匹配对应用名(macOS 的 .app 基名、Windows 的 .exe 基名、Linux 的 desktop Name)不区分大小写。只有已安装且匹配的应用会出现在菜单中。

终端应用 — Terminal、iTerm2、Ghostty、Warp、Alacritty、kitty、WezTerm、Hyper、Tabby、Rio、Contour、Foot、Tilix、Terminator、Konsole、GNOME Terminal、xterm、mintty、Windows Terminal、PowerShell、Cmder、ConEmu。

编辑器与 IDE — Visual Studio Code、Cursor、Windsurf、Zed、Xcode、Android Studio、IntelliJ IDEA、PyCharm、WebStorm、GoLand、CLion、PhpStorm、RubyMine、Rider、DataGrip、DataSpell、RustRover、Fleet、Aqua、Visual Studio、Eclipse、NetBeans、Sublime Text、Nova、BBEdit、TextMate、CodeRunner、MacVim、Neovide、Emacs、Lite XL、HBuilderX。

要增删条目,编辑 lib/apps.js 中的 WHITELIST 数组——每个条目为 { id, category, match, exact? },其中 id 是规范显示名(也是原生打开命令必须能找到的名称),match 别名做子串匹配,exact 别名做全名匹配(用于诸如 code 这类会误匹配 CodeRunner 的短名称)。Windows JetBrains 启动器(idea64pycharm64 等)与 Code.exe 已通过别名覆盖。

架构

  • 宿主端lib/index.js):一个 Cordis 插件,注册一个 Typert Remote 服务 openInApp(通过 Typert Gateway 的 source-mode 回退发现——无需生成 TYPERT manifest):
    • openInApp/listApps{ apps, defaultIcon? }:白名单内已安装应用(含展示图标)以及默认文件夹处理器的图标
    • openInApp/openWith(path, appId) → 用指定应用打开文件夹
    • openInApp/openDefault(path) → 用系统默认方式打开文件夹
    • openInApp/openDefaultEditor(path) → 用默认编辑器打开文件夹(见 lib/apps.js 中的 EDITOR_PRIORITY
  • 图标lib/icons.js):为每个应用以及系统默认文件夹处理器(Finder / Explorer / xdg-mime 默认)解析一个 data:image/* 图标,按平台尽力而为(见上表),按源路径 + mtime 缓存,使重复打开菜单开销很低;失败时缓存为“无”,绝不报错。在 macOS 上,与应用同名的 icns 优先于文件类型 icns(Zed.app 中的 Zed.icns 优先于 Document.icns)。枚举的 source 路径作为不可枚举属性(lib/apps.js)携带,因此 JSON 传输永远不会看到它。
  • 客户端lib/client.js):一个 dsh.client web 模块,通过 ctx.remote.$mount(...) 挂载 Remote 端点,并注册 conversation.session.header.utilities 条目 open-in-app。挂载运行在声明了 remote 的嵌套插件 fiber 中:api-gateway 将每个命名空间注册为点分隔的 cordis 服务(remote.openInApp),一个既挂载又注入自身命名空间的 fiber 会导致加载器死锁。因此消费方通过文档化的非严格 store 访问(ctx.reflect.get("remote.openInApp", false))读取该命名空间。
  • Bundlecordis.patch.yml):一行加载器记录激活宿主端;profile 工具将其作为 profile bundle 引入。

安装

安装已发布到 npm 的包(需该包已发布到 npm registry):

dsh plugin --profile web add dsh-open-in-app

或在包含本仓库本地克隆的目录下执行:

git clone https://github.com/open-dsh-plugins/dsh-open-in-app.git
cd dsh-open-in-app
dsh plugin --profile web add .

然后重启 web 应用(dsh web)——加载器与客户端模块图在启动时组合,新增插件没有热重载。重启后,文件夹按钮会出现在会话标题旁,菜单会显示已安装的应用。

安全说明

  • Remote 端点不在特权方法列表中,因此它们与其余 /api 面处于同一浏览器信任边界之后(仅限 loopback / 已配置的可信主机)。
  • 打开路径会在宿主机上派生原生进程。文件夹路径来自会话自身的 cwd,即该 agent 正在操作的目录。
  • 图标解析仅读取枚举的应用路径(标准应用根目录)以及 freedesktop 图标主题目录;缓冲区上限为 256 KB,原生转换(sipsqlmanage、PowerShell)带有可选的 abort 信号。
  • 命令失败(open 退出码、应用缺失)会以菜单中的错误行呈现,而不是抛异常。

开发

  • lib/apps.jslib/icons.js 是纯 Node(无 dsh 导入)——可独立测试(node -e 'import("./lib/icons.js").then(m => m.listAppsWithIcons()).then(console.log)')。
  • 客户端 bundle 必须保持自包含:它只依赖平台种子词(reactreact/jsx-runtime@deepseek-ai/dsh-client-ui-primitives)。
  • 无需重建:没有构建步骤——lib/ 原样发布。