DeepSeek Harness 插件

omdsh-editor

Open the current project directory in a native editor from the DeepSeek Harness web GUI: the session header's editor picker, and the host half that finds the installed editors and launches one(英文原文)

跳到安装方式

来源信息

GitHub 仓库
omdsh-plugins/omdsh-editor
最近更新
2026年8月20日
分类
记忆
GitHub stars
0
载体类型
plugin
目录证据
上游声明已找到 dsh.bundle
证据路径
package.json#dsh.bundle
核对版本
0.1.0-rc.8
上游核对日期
2026-08-20

该证据由上游目录提供。本站没有安装、运行或安全审核这个插件。

安装

默认先复制一段 Prompt,让 Agent 读 GitHub 仓库和源码;需要自己装时再切到命令。

复制这段 Prompt,发给 DSH、Codex 或其他 Agent,让它先读 GitHub 仓库和源码。

请先不要安装或执行任何命令。阅读这个插件的 GitHub 仓库、README 和关键源码,然后用清楚、直接的方式回答以下问题,帮助我判断它是否适合我的需求:

1. 这个插件是什么,解决什么问题;
2. 适合哪些用户和典型使用场景;
3. 安装后如何使用,并给出一个最小使用示例;
4. 有哪些已知限制,以及隐私、安全、兼容性或维护风险;
5. 给出“推荐 / 有条件推荐 / 不推荐”的明确建议和理由。

请区分仓库明确说明、根据源码推断和未知信息。证据不足时请明确说明,不要猜测或照抄 README。

GitHub:https://github.com/omdsh-plugins/omdsh-editor
插件名:omdsh-editor
作者:omdsh-plugins

检查来源文件

安装前先看这个插件目录里的 README 和其他文件。

文件资源管理器4 个文件
README.zh.md来源说明 · 只读预览
README 语言

omdsh-editor

English | 中文

用你真正在用的编辑器打开当前项目。DeepSeek Harness 网页界面的会话标题栏右侧多出一个分体控件:按左半边,当前会话的目录就在你上次选的编辑器里打开;按右边的箭头,换一个。

harness 本身没有这个能力,也没有留下能绕过它补上的接缝,所以这个包把两半都带上了——负责查找并启动应用的宿主半边,和负责把它们摆出来的浏览器半边。

┌──────────────────────────────────────────────┬───────────────┐
│  my-project                                  │  ⌗   ⧉   [◧|▾] │  ← 会话标题栏
└──────────────────────────────────────────────┴───────────────┘
                                                        │
                                       ┌────────────────┴──────┐
                                       │ ◧  VS Code            │
                                       │ ◧  Cursor             │
                                       │ ▤  Finder             │
                                       │ ▸  Terminal           │
                                       │ ▸  iTerm2             │
                                       └───────────────────────┘

它提供什么

界面从哪来
会话标题栏右侧的分体编辑器控件conversation.session.header.utilities 里的一个条目——ui-conversation 已经声明好的工具行
GET /omdsh-editor/editors这台主机真正装了哪些应用,以及它的 process.platform——每个候选一次 stat,结果缓存 15 秒
GET /omdsh-editor/icon?id=…每个应用自己的图标,从这台主机上已安装的那份里读出来,按 PNG 提供
POST /omdsh-editor/open启动本身:以会话自己的工作目录为准,交给一个 detach 出去的子进程
记住的那个选择浏览器半边的 localStorage——正是它让控件的左半边能成为一个动词

harness 本身没有任何改动。三条路由挂在 webServer 上的同一次前缀注册里,控件占的座位是本来就发布好的,本包不声明任何自己的 slot——所以移除这一行之后,标题栏就是出厂的样子。

编辑器在哪台机器上打开

运行 runtime 的那台。 项目目录就在那里,"打开这个文件夹"也只在那台机器上有意义,harness 自己的模型本来就把工作放在那里。

由此可以推出:通过网络访问一个 runtime 并按下编辑器,编辑器会在文件旁边启动,而不是在浏览器旁边。插件把这一点挑明,而不是藏起来:在一台什么都没装的主机上,菜单会写明它查找的平台(No editor found on the machine running dsh (linux)),好让你分清"去装个编辑器"和"这个 runtime 不在我桌上"。

把它做进 Electron 外壳会让这个能力只属于打包后的应用,而终端里的 dsh web 同样需要它。

它能打开哪些应用

类别应用
编辑器VS Code、VS Code Insiders、Cursor、Windsurf、Zed、Sublime Text、IntelliJ IDEA、PyCharm、WebStorm、Xcode
文件Finder、文件资源管理器、File Manager(xdg-open
终端Terminal、iTerm2、Warp、Ghostty、WezTerm、kitty、Alacritty

只列出这台主机真正装了的那些。探测就是每个候选一次 stat,仅此而已——没有 mdfind,不读注册表,不起子进程——所以整轮扫描只要几毫秒,菜单是一个直接展开的列表,而不是一个要等的对话框。结果缓存 15 秒,短到在 harness 运行期间装的编辑器不用重启就会出现。

表里没有的应用是看不见的。加一个是 [src/catalog.ts](src/catalog.ts) 里的十来行,或者插件配置里的一项 editors——后者会整体替换出厂的表,见[怎么配置它](#怎么配置它)。

一个应用是怎么被找到和启动的

每一行按优先顺序列出它可能存在的几种形态,第一个命中的既决定了"装了",也决定了怎么启动。

探测方式查找位置启动方式
mac-appmacOS 标准应用目录,含 ~/Applicationsopen -a <bundle> <dir>
windows-exe%LOCALAPPDATA% / %ProgramFiles% 下的固定路径可执行文件加目录参数
path-binPATH(Windows 上带 .exe/.cmd/.bat/.com可执行文件加目录参数

优先 bundle 而不是命令行 shim,因为在一个从未执行过用户 profile 的 GUI 会话里,PATH 上可能什么都没有,而 bundle 仍在。用 open -a 而不是直接执行 bundle 里的可执行文件,因为只有 Launch Services 能激活已经在运行的实例,也只有它能把参数送进去——Terminal 会在该目录起一个 shell、Finder 会定位到该目录,靠的也是它。

有四个终端(Ghostty、WezTerm、kitty、Alacritty)只按命令行形态收录。它们的工作目录是一个 flag 而不是一份"文档",而 open -a 没法把 flag 传给已在运行的实例;如果给它们加 bundle 探测,那一行会亮起来,点开却是错误的目录——这比这一行干脆不出现更糟。

子进程会 detach 到自己的进程组,流关闭,然后 unref,所以退出 harness——或者桌面外壳按自己的内存策略重启一次——不会关掉你正在敲字的窗口。

怎么配置它

这个插件不注册 settings 命名空间,所以它在插件中心里的那张卡片——那里按 package.jsondsh.plughub 元数据显示为 External Editor(外部编辑器)——没有表单,而且会老实写明它没有可配置项。用起来本来也没有什么要调的:装了哪些应用是主机的回答,左半边开哪一个则是上次按下时记住的。

它确实接受组装层的配置,要写在 profile 的 cordis.patch.yml 里那一行 bundle 上:

- id: editor
  name: '@omdsh-plugins/omdsh-editor'
  config:
    editors:                                  # 整体替换出厂的表
      - id: nvim
        label: Neovim
        kind: terminal                        # code | terminal | files
        accent: '#57a143'
        probes:
          - { kind: path-bin, bin: nvim }     # mac-app | path-bin | windows-exe
    detectionTtlMs: 60000                     # 默认 15000

editors 是整张表,不是往表里追加:只写一行就意味着只提供这一个应用,所以想加一个应用的部署,通常会先把 [src/catalog.ts](src/catalog.ts) 里出厂的那份抄过来。把工作目录写成 flag 的启动器可以再给一项 args['--working-directory={dir}']);不写就是把目录直接接在后面,这也正是每个编辑器的命令行 shim 本来的行为。

detectionTtlMs 是一轮探测的新鲜期。默认值短到在 harness 运行期间装的编辑器不用重启就会出现,一般没有理由去改它。

路由

三条都挂在 /omdsh-editor 下,并且通过 ctx.effect 注册,所以卸载插件就会移除它们。

路由作用
GET /omdsh-editor/editors这台主机有哪些应用,以及它的 process.platform
GET /omdsh-editor/icon?id=…某个应用自己的图标,PNG
POST /omdsh-editor/open在某个会话的目录上启动其中一个

目录由宿主说了算。 一次 open 请求指名一个会话;会话自身的工作目录是权威来源,浏览器发来的 cwd 只在会话没有目录时才作参考。无论走哪条路,结果都必须是绝对路径,而且在启动任何东西之前必须仍然是一个目录。这里刻意没有 process.cwd() 兜底:因为这个会话没有目录,就去打开 harness 恰好启动时所在的那个目录,那是意外,不是兜底。

每条路由都会通过与 /api 网关完全相同的浏览器信任检查([src/trust-fence.ts](src/trust-fence.ts))——Host 头指向我们,加上同源的浏览器标记。一条能启动本机应用的路由,必须与 /api 一样可达,而且不能比它更可达。

这个控件

conversation.session.header.utilities 里的一个条目,这是 ui-conversation 已经声明好的右对齐工具行。本包不声明任何自己的 slot,所以移除它之后标题栏就是出厂的样子。

分体是设计本身。左半边是动词——常见情形就是"用我的编辑器打开我的项目",它应该只花一次点击、不需要做选择。右半边是选择器,只在第一次以及想换一个的时候需要。选择记在 localStorage 里,这是左半边能成为一个动词的唯一原因。

图标是真的

每一行都用产品自己的图标绘制,所以六行排在一起,能像 Dock 那样一眼分辨开。

不附带、不重绘。字节来自这台主机上已安装的那份应用:Contents/Resources/*.icns,由 bundle 自己的 Info.plist 指名,在本地渲染——和系统"打开方式"菜单做的是同一件事。在包里附带十几个厂商的 logo 是授权问题;读取用户自己装的那份不是。

提取是纯 Node,不用 sips、不起子进程:.icns 是一个扁平的 type-length-value 容器,现代的每一个都把大尺寸变体存成内嵌 PNG,所以取图标就是一次扫描加一次切片。实际提供的是宽度不小于 64px 的最小变体,几 KB,在 2× 下清晰。

三种情况会让某一行没有真图标——应用不是 macOS bundle 的主机、用编译后的 asset catalog 而非 .icns 的 bundle、以及 Resources 里一堆 .icns 但认不出哪个是应用自己的。三种都回退到该类别的字形,染上产品主色,仍然足以分辨。catalog 响应里带 icon: boolean,所以选择器只会去请求确实存在的图标;即便如此 <img> 出错时也会自己回退。

安装

npx @omdsh-plugins/omdsh-plughub add omdsh-editor

这就是插件中心的安装器,只是入 口从按钮换成了 argv。它从这套集合的 registry 里解析出这个插件、从它的 GitHub 仓库装上,并把那条 pnpm 构建白名单写好——裸的 dsh plugin add github:… 会把这一步留给你,而那条记录里带着 pnpm 解析出来的 commit,只能从报错里抄,事先 写不出来。

dsh plugin --profile web add @omdsh-plugins/omdsh-editor 现在还不是那条命令:这个 包不在 npm 上,pnpm 会回 ERR_PNPM_FETCH_404。同一次安装也可以是一个按钮—— 只要 profile 里已经有插件中心,它就在设置 → 插件 → 插件中心里这个插件的卡片 上。

dsh plugin --profile <名字> <参数…> 是一层很薄的 pnpm 转发,在 profile 目录(~/.dsh/profiles/web,或 $DSH_HOME/profiles/web)里执行。pnpm 收什么它就收什么,之后再把 dsh.profile.bundles 与实际安装状态对齐。

或者从一份 checkout 安装,改这个插件本身时要的就是这种:

pnpm install && pnpm run build                 # 必须先有 lib/;按路径安装不会执行 prepare
dsh plugin --profile web add "$PWD"

相对路径会以你执行 dsh 时所在的目录为锚。两种写法都会让 profile 清单多出这条依赖,并把 @omdsh-plugins/omdsh-editor 追加到 dsh.profile.bundles,于是 [cordis.patch.yml](cordis.patch.yml) 会在 @deepseek-ai/dsh-base@deepseek-ai/dsh-web-app 之后生效。harness 的目录树保持出厂原样。

重启 runtime 才会生效(重跑 dsh web,或退出并重开桌面应用)。移除也是同一种写法:

dsh plugin --profile web remove @omdsh-plugins/omdsh-editor

这会同时带走 bundle 行、路由和这个控件,会话标题栏回到出厂的样子。

按路径安装记的是 link:,也就是说 pnpm 既不构建这个包也不装它的依赖——这两件在这里都不要紧,因为 node 半边只 import Node 内置模块,浏览器半边把 clsx 打进了 bundle。但它确实意味着:改完源码,重新构建得自己跑。

没有"缺了就不工作"的伙伴插件。 两半 inject 的每一个服务都是 profile 已经组合好的 harness 服务——宿主侧是 webServersessionswebRuntime,浏览器侧是 slotslocale——所以不必再装这个集合里的任何别的插件,别的插件也不会改变它的行为。webRuntime 来自 web 形态的 bundle,所以这一行属于 web profile:信任围栏要比对的那份清单就在它上面,而一个没有网页服务器的形态,本来也没有浏览器可服务。

命令

pnpm install
pnpm run build       # tsc 产出 lib/types,tsdown 打包两半
pnpm run typecheck   # 源码与测试
pnpm run test        # vitest

提交的 manifest 固定指向已发布的 harness,所以裸 clone 自己就能安装和构建。要改成对着同级的 checkout 构建:

pnpm run harness:local ../../deepseek-harness   # 那个 checkout 需要先构建过
pnpm install
pnpm run harness:npm                            # 提交前务必执行 —— link: 是某一台机器的目录布局
pnpm run check:harness-pin

只跑 node 的用例在裸 clone + 固定版本下都能过。三个浏览器用例需要那份 checkout:harness 已发布的浏览器包只提供测试运行器无法 import 的 loader bundle,所以在固定版本下它们会解析到 [tests/registry-mode-guard.ts](tests/registry-mode-guard.ts),并带着一条说明原因的报错失败。

已知限制

  • 编辑器来自一张表。 装了冷门工具的主机看到的列表会比实际短。"这台机器上存在哪些编辑器"本身不是一个有答案的问题;逃生舱是 editors 配置。
  • 成功只意味着进程起来了。 子进程 detach 之后没有退出码可等,所以编辑器起来之后自己拒绝了目录,这件事不会报回来。spawn 观察窗口是 150ms——长到 Node 来得及送达一次 ENOENT,短到在界面上看不出来。
  • 记住的选择是按浏览器而不是按用户。 它存在 localStorage 里,所以换一个浏览器会重新从列表第一个开始。
  • Xcode 拿到的是目录而不是工程。 这一行做的就是 open -a Xcode <dir>;不是工程或 workspace 的目录,会以 Xcode 自己的文件夹视图打开。
  • Windows 探测只覆盖默认安装位置。 装在别处的编辑器,只有 shim 落在 PATH 上时才找得到。
  • 图标只支持 macOS。 Windows 需要解析 PE 资源,Linux 需要 .desktop 加图标主题查找,两者都没做,所以那些主机拿到的是类别字形。图标存在编译后的 Assets.car 里的 bundle 也会回退——要读它就得带一个 asset catalog 解码器。
  • 只解析 XML 形式的 Info.plist 二进制的不解码,改用应用自己的名字去找图标——实际上每个这样的 bundle 都是这么命名的(Xcode 就是)。如果某个二进制 plist 的 bundle 给图标起了别的名字,那一行就回退到字形。
  • 没有端到端覆盖。 跑通真实链路需要一个窗口会话和一个装好的编辑器;现有用例覆盖了探测、每条路由与每种拒绝、针对真实进程的启动契约(detach、shell: false、正确的工作目录),以及浏览器半边的状态机与渲染。