Skip to content
dsh.fish
Bundle

dsh-client-open-in-vscode

Click a file path in the chat UI to open it in the running VS Code window owning the matching workspace; Edit/Write rows open a diff of that exact change (webview-safe host route behind the loopback/Origin trust fence).

Source
quei4r
License
MIT
Updated
Updated 6 days ago

Readme

# dsh-client-open-in-vscode

中文 | [English](README.en.md)

DeepSeek Harness(DSH)Web 界面的插件:**点击聊天 UI 里的文件路径,在已打开的、工作区匹配的 VS Code 窗口中打开该文件**。

## 功能

捕获阶段拦截以下元素的点击:

| UI 元素 | 识别方式 |
|---------|---------|
| 工具卡片路径(Write/Edit/Read 等) | `button.*_fileLink`,文本即路径(可为工作区相对路径,按当前会话 cwd 补全) |
| 「产物」chips | `[data-produced-files-row] button[title]` |
| 正文里的文件提及链接 | `title` 为绝对路径的 a/button/[role=link] |

命中后 `POST /plugin-open-in-vscode` → 宿主执行 `code --goto --reuse-window <path>`,VS Code 内部按工作区归属路由窗口并提到前台。

**Edit/Write 行为(v0.6)**:点击文件变更行(Edit/Write 等)的路径时,打开**那次编辑的全文件 diff**。原理是 `git apply` 的逆向:行数据自带该次编辑的前后片段(改动 ± 上下文行),把片段拼回完整文件即得两版全文——先试**磁盘当前文件**(覆盖未提交与已提交的编辑,已提交的文件本身就含改后文本),再试 **git HEAD 版本**(覆盖工作区已被还原/改写的编辑);任一基底含片段且唯一命中即重建成功,展示仍走标准 `code --diff`。重建不出(后续提交改写了同一区域)时回退显示行内片段 diff;**运行中/失败**的调用因改动尚未落盘也走片段预览。临时文件 10 分钟后清理;无 diff 数据的行(Read/Bash 等)仍为直接打开。

> 历史编辑也能正确显示:已提交的编辑从提交内容里重建(v0.5 的 HEAD-vs-工作区方案对已提交编辑会显示"无更改",已废弃)。多窗口时 diff 两侧均为临时文件,窗口路由回落到同 authority 的**最近活跃窗口**。

多窗口时的路由规则(VS Code 窗口管理器行为):先按 remote authority 过滤候选窗口(只考虑连接到同一主机/本地的窗口),再看**文件的绝对路径落在哪个已打开工作区文件夹内**——多根 workspace 按根目录声明顺序取第一个命中,多个单文件夹窗口都包含该文件时取**路径最深**的那个;都不命中时回退到同 authority 的**最近活跃窗口**。会话 cwd 只用于把相对路径补全成绝对路径,不参与窗口匹配。

- **Alt+点击**:绕过拦截,走产品原逻辑
- 操作后页面底部有 toast 反馈(成功/失败)

## 安全

路由与框架 `/api` 同款信任闸门:Host 必须是 loopback(防 DNS rebinding)、`Sec-Fetch-Site: cross-site` 拒绝、携带 `Origin` 时必须与 Host 一致(防网页 drive-by POST)。也就是说**其它网站无法借你的浏览器触发本机 VS Code 打开文件**;路径仅接受绝对路径且不经 shell(`execFile` 参数数组)。

## 为什么不用 `vscode://file/...`

v0.1 用锚点跳转 `vscode://` 协议 —— 在真实浏览器里没问题,但 DSH GUI 常跑在 **VS Code webview** 里,webview 导航到该协议会**直接黑屏**。v0.2 起改为宿主侧 `code --goto`,webview 安全。

## 安装

假设 `DSH_HOME` 为 `~/.dsh`(默认值):

1. 复制包到 web profile 的 node_modules:

   ```bash
   cp -r dsh-client-open-in-vscode ~/.dsh/profiles/web/node_modules/
   ```

2. 编辑 `~/.dsh/profiles/web/cordis.patch.yml`,加入:

   ```yaml
   - insert:
       - id: ui-open-in-vscode
         name: dsh-client-open-in-vscode
   ```

3. 重启 `dsh web`(本插件的 Host 半需要在启动时注册 HTTP 路由,仅刷新页面不够)。

验证组合(可选):

```bash
dsh --profile web --dump-config | grep ui-open-in-vscode
```

## 要求

- 系统 PATH 里有 `code` CLI(VS Code 标准安装自带)
- 桌面会话(X11/Wayland),宿主进程能拉起 GUI 窗口

## 卸载

1. 从 `cordis.patch.yml` 删除该 `- insert:` 段;
2. 删除 `~/.dsh/profiles/web/node_modules/dsh-client-open-in-vscode`;
3. 重启 `dsh web`。

## 文件说明

| 文件 | 说明 |
|------|------|
| `index.js` | Host 半:注册 `POST /plugin-open-in-vscode` 路由(loopback/Origin 信任闸门),`execFile('code', ['--goto','--reuse-window', path])` |
| `client.js` | 浏览器半:点击拦截 + fetch POST + toast(`window.__ModuleLoader__` 格式) |
| `cordis.patch.yml` | 插件插入配置(`dsh plugin add` / 市场安装所需) |
| `package.json` | 包清单,含 `dsh.bundle` + `dsh.client.platform: "web"` 声明 |

兼容性:随 `@deepseek-ai/dsh` 0.1.0-rc.6 的 web profile 测试通过。产品 DOM 的 class/hash 若在新版本变动,`client.js` 里 `targetPath()` 的选择器需要跟进调整。

Install

dsh plugin --profile web add github:quei4r/dsh-client-open-in-vscode

Profile: web

  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source