dsh-chat-ctxmenu

uitested: passnpmMIT

Right-click menu for DeepSeek Harness conversation content: copy the selection or the whole message, copy message images and the preview lightbox to the clipboard as PNG (or save them), open file paths (absolute, relative to the session working directory, or ~/), reveal them in the file manager, ope

下载量 / Downloads
790
依赖体积 / node_modules
0.08 MB
测试时间 / Tested
2026-11-07
DSH 版本 / Version
0.2.2-rc.1

Install

dsh plugin --profile web add dsh-chat-ctxmenu

Sandbox test results

StageResult
1 install✓
2 list✓
3 mount✓
4 boot—

Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).

README

dsh-chat-ctxmenu — 对话右键菜单(官方菜单增强)

给 DeepSeek Harness 的对话区右键加只有它才能提供的能力,其余右键交给 DSH 官方菜单。

从 2.0.0 起,本插件不再绘制自己的菜单:DSH 0.2.2 的官方右键菜单框架(@deepseek-ai/dsh-client-ui-context-menu)负责手势、视口定位、键盘导航、图标与提示,本插件只向官方菜单贡献条目,并为官方没有接管的正文手势提供一层兜底。兜底由三个 document 监听组成:contextmenu 捕获阶段的纯计数器(只让仍在等待 Host 的旧兜底失效,绝不 preventDefault、绝不打开菜单)、keydown 捕获阶段的键盘失效器(官方 ContextMenu / Shift+F10 只在 keydown 里 preventDefault,不派发 contextmenu),以及 contextmenu 冒泡阶段处理器(官方已处理时让位)。

  • 手势 hook 归官方:右键/键盘触发元素的绑定、视口定位、键盘导航、图标与提示都由官方 @deepseek-ai/dsh-client-ui-context-menu 负责;触发点分布在 ui-chat、ui-tool、ui-reference、ui-sidebar-files、ui-workspace、ui-sidebar-right 等包,菜单条目由 ui-open-in-app、ui-file-actions、ui-workspace 及本插件贡献。本插件不绘制菜单。
  • 本插件只贡献官方没有的条目(官方按 target kind 分发,所以 file/directory 条目同样会出现在工作区文件树等官方 file/directory 目标上,属于增量而非接管):
  • 文件:复制相对路径、用其他应用打开 ▸(系统为该文件注册的应用列表 + Windows「选择其他程序…」);
  • 目录:复制相对路径;
  • 图片:复制图片链接(仅 http(s) 来源);
  • 正文纯文本:复制选中内容、复制整条消息(插件自定义的 chatMessage 目标)。
  • 正文里的路径识别仍然保留:右键落在正文里的 src/app.ts、./dist/x.js、~/…、UNC、驱动器路径、path:line:col、代码块里的裸文件名时,先由 Host 校验存在性,再交给官方文件菜单打开(因此打开/显示/复制路径仍走官方实现);正文里的 http(s) URL 交给官方链接菜单。

菜单内容(2.0.0)

右键位置 · 谁提供 · 菜单项

正文纯文本 / 工具结果 · 本插件 · 复制选中内容(有选区时)· 复制整条消息

正文里的路径 token(经 Host 校验存在) · 本插件识别 → 官方菜单 · 在侧边栏打开 · 在浮窗中打开 · 在文件夹显示 · 使用默认应用打开 · 复制文件路径 · 复制相对路径 · 用其他应用打开 ▸

Markdown 文件 / 引用 chip / 工具文件控件 · 官方触发/渲染 · 官方文件条目 + 本插件的复制相对路径、用其他应用打开 ▸

链接(Markdown / 正文 URL) · 官方 · 在侧边栏打开 · 外部浏览器打开 · 复制链接地址

图片(消息图片、原图预览) · 官方 + 本插件 · 复制图片 · 下载 · 另存为 · 在文件夹显示 · 复制图片链接

工作区行 · 官方 · 官方工作区条目(重命名 / 删除 / 在文件夹显示等);本插件不注册 workspace 目标

工作区文件树 · 官方触发/渲染 · 官方文件/目录条目 + 本插件的复制相对路径、用其他应用打开 ▸(同 file/directory 目标,属增量)

  • 目录(folder)目前只有官方「在文件夹显示 / 复制文件夹路径」与本插件「复制相对路径」;「使用默认应用打开 / 用其他应用打开 / 在侧边栏打开 / 在浮窗中打开」是文件专属条目(以上为中文界面实际文案)。
  • 用其他应用打开 ▸ 的应用 id 必须先出现在系统的「打开方式」注册列表里;未注册的 id 一律拒绝(防止伪造请求拉起任意程序)。Windows 上对「已注册、且 id 就是 exe 路径」的应用直接 spawn(exe, [file])——Harness 原生 IHandler::Invoke 对多数 Win32 处理器无效;UWP/AUMID 等非 exe id 仍走原生通道。选择前会校验注册关系,直接启动失败时再回退原生通道并回报具体错误。

实现方式

Client(浏览器)
  ctx.contextMenus.register  ── 向官方目标贡献条目
      file      → 复制相对路径、用其他应用打开 ▸(Host RPC: apps/openWith/openWithDialog)
      directory → 复制相对路径
      image     → 复制图片链接
      chatMessage(插件自定义目标)→ 复制选中内容 / 复制整条消息
  document 'contextmenu'(捕获阶段,纯计数器)
      任意新手势(右键)→ 让仍在等 Host 的旧兜底失效
  document 'keydown'(捕获阶段,键盘失效器)
      ContextMenu / Shift+F10 → 让仍在等 Host 的旧兜底失效
  document 'contextmenu'(冒泡阶段,兜底)
      官方已处理(event.defaultPrevented)→ 让位
      非对话正文 / 输入框 / 工作区           → 让位
      光标下的 URL                          → 官方 url 菜单(优先于同块路径)
      正文路径 token → Host resolve 校验 → 官方 file/directory 菜单
      其余正文       → chatMessage 菜单
Host(Node,仅保留官方菜单拿不到的能力)
  resolve  → fs.resolve + stat/lstat(相对路径按会话 cwd,~ 展开)
  apps     → sessionController.workspacePathApplications
  openWith / openWithDialog → 原生授权通道 + Windows 直接 spawn 兜底
  status   → 诊断

安全边界:

  • 两个路由只接受 loopback 对端;带 Origin 时必须与 Harness 自身 origin 同源(未知 origin 直接拒绝)。
  • 不做文件写入、不读文件内容:只做存在性校验与系统打开。
  • 路径来自用户右键的文本,必须通过 Host fs 校验存在才会交给官方文件菜单;用其他应用打开 只接受系统已注册为该文件打开方式的应用 id。

环境要求

  • DSH >= 0.2.2-rc.1 < 0.3.0(engines.dsh)。0.2.2 是本插件依赖官方 contextMenus 服务的最低版本;在 0.2.1 及更早版本上插件不会被加载。

安装

从 npm 安装

截至本分支,npm latest 仍是 1.0.3(自绘菜单,需要 DSH 0.2.1)。2.0.0 尚未发布;发布后再用下面的命令,或显式 dsh-chat-ctxmenu@2.0.0。在此之前请用本地目录 / tarball 安装。
dsh plugin --profile desktop add dsh-chat-ctxmenu@2.0.0

或在会话中让 agent 执行:

plugin_manager action=install_bundle target=dsh-chat-ctxmenu

从本地目录 / tarball 安装

dsh plugin --profile desktop add <本目录绝对路径>
# 或
dsh plugin --profile desktop add ./dsh-chat-ctxmenu-2.0.0.tgz   # npm pack 的输出

在 DSH 会话中让 agent 执行(bundle 目录为本仓库):

plugin_manager action=install_bundle target=<本目录绝对路径>

安装后 Host 侧热加载;浏览器端刷新页面后生效(client 半在页面引导时加载)。

检查:

GET /dsh-chat-ctxmenu/status                 # Host 半:应返回 ok:true,rev=5
浏览器 DevTools → Network 过滤 dsh-chat-ctxmenu/client.js   # Client 半:应能看到被加载

shell.overlay 里的 context-menu 是官方浮层,只能证明官方框架在、不能证明本插件客户端已加载。

卸载:plugin_manager action=remove_bundle target=dsh-chat-ctxmenu。

RPC 路由

路由 · 方法 · 说明

/dsh-chat-ctxmenu/rpc · POST · {action, args};动作:resolve apps openWith openWithDialog status

/dsh-chat-ctxmenu/status · GET · 诊断:平台、原生通道是否可用、canOpen、rev;?probe=<path>&cwd=<dir> 可验证路径解析

2.0.0 移除了 open / reveal / openUrl:这些能力由官方菜单承担,本插件不再提供第二条打开通道。

升级说明(1.x → 2.x)

  • 自绘菜单、图片复制/另存为、链接打开/复制、打开/显示/复制路径的自有实现均已移除,改由 DSH 0.2.2 官方右键菜单提供;本插件保留官方没有的条目(见上表)。原先在每个菜单里都会出现的「复制选中内容 / 复制整条消息」现在只出现在正文纯文本菜单(chatMessage 目标)——文件、链接、图片的官方菜单不再有这两项。
  • 插件版本提升到 2.0.0,engines.dsh 收紧到 >=0.2.2-rc.1 <0.3.0:仍在 0.2.1 的机器请显式装回 1.0.3:
  dsh plugin --profile desktop add dsh-chat-ctxmenu@1.0.3
  • 目录(folder)不再有独立的「打开」条目:官方对目录只提供「在文件夹显示」(explorer /select,<目录>,即打开父目录并选中该目录)与「复制文件夹路径」,本插件补充「复制相对路径」。
  • 设置项无变化;没有持久化数据。

已知限制

  • 依赖对话节点带 data-chat-flow-kind 标记(官方 Chat 视图仍在用);若未来 DSH 改动该标记,正文兜底会静默不触发(不会误弹)。
  • 官方菜单的「复制路径」复制绝对路径;「复制相对路径」是本插件补充的独立条目,仅当目标位于会话工作区内时出现。
  • 正文里的裸文件名(如「改一下 index.js」)只会在会话工作目录下确实存在同名文件时出现文件菜单——刻意避免误判。
  • 一次右键客户端最多提交 6 个候选路径(Host 单次上限 8),取第一个真实存在的;同一文本块出现多个候选时只接受唯一的绝对路径,避免「点 A 打开 B」。
  • 未加引号、含空格的 Windows 路径会同时提交「截断版 + 扩展版」两个候选,由 Host 取存在的那个。
  • 用其他应用打开 ▸ 的子项在官方菜单打开前异步读取(受官方 resolutionTimeoutMs 限制,默认 1s);读取超时会被官方丢弃并显示失败提示,应用列表读取失败时该条目直接不出现(不弹空菜单)。
  • 官方按 target kind 分发,因此本插件的「复制相对路径 / 用其他应用打开 ▸」也会出现在工作区文件树的 file/directory 菜单里(官方触发、官方渲染,本插件只是增量条目);打开这类菜单同样会等一次 apps 查询,受上面 1s 预算影响。
  • 本插件只在对话正文内做手势兜底;工作区行、工作区文件树、会话行等区域的右键触发完全由官方决定,插件不注册这些目标。
  • 复制选中内容 / 复制整条消息 / 复制相对路径 优先走 navigator.clipboard;在非安全上下文(如 http 远程访问)会被浏览器拒绝,此时退回旧版使用的 document.execCommand('copy') 后备路径。

…(truncated)

Rendered from the README published on npm. Formatted only, not edited.

Versions

Published on npm::5,最后更新 2026-11-06

Links

GitHub · Homepage · npm

Same category