DeepSeek Harness 插件

dsh-custom-context-menu

DSH Web 自定义右键菜单:全局拦截 contextmenu,提供可扩展菜单框架,并内置“打开工作区文件夹”功能(英文原文)

跳到安装方式

来源信息

GitHub 仓库
sulfide2085/dsh-custom-context-menu
最近更新
2026年8月16日
分类
工具与能力
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/sulfide2085/dsh-custom-context-menu
插件名:dsh-custom-context-menu
作者:sulfide2085

检查来源文件

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

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

dsh-custom-context-menu

English · 中文

> DeepSeek Harness(DSH)Web UI 的自定义右键菜单插件:全局接管浏览器右键,提供零依赖的扩展菜单框架,并内置“右键工作区 → 在资源管理器中打开文件夹”。

特性

  • 全局 contextmenu 接管:捕获阶段拦截浏览器右键,输入框/文本域/可编辑元素与菜单自身除外
  • 可扩展 provider:一行 register() 注册菜单项,支持分隔线、分组标题、禁用项、危险项、hint
  • 键盘导航:↑/↓ 循环选择,Enter/Space 触发
  • 智能定位:菜单超右/下边缘自动翻转,并夹紧在视口内
  • 无命中不打扰:没有 provider 命中时放行浏览器原生菜单,不再显示“暂无菜单项”占位
  • 打开工作区文件夹:右键侧边栏工作区行 → 「打开文件夹」→ host 半直接拉起系统文件管理器

- Windows:explorer.exe <path>,路径自动规范化为反斜杠,并通过前台激活 helper 把窗口带到最前 - macOS:open <path> - Linux:xdg-open <path>

  • 失败可见:打开前校验目录存在;路径失效时明确报错,不会假报“已打开文件夹”

安装

本地安装

cd dsh-custom-context-menu
pnpm install
cd ..
dsh plugin --profile web add ./dsh-custom-context-menu

重启 DSH Web 生效。

从 GitHub 安装

dsh plugin --profile web add "https://github.com/sulfide2085/dsh-custom-context-menu.git"

> dsh plugin add 会把包以 link:/Git 依赖方式装进 profile,并把本包 cordis.patch.yml 声明的 bundle 层追加到 dsh.profile.bundles

快速使用:注册菜单项

在浏览器控制台(F12)或其他插件中:

window.dshContextMenu.register((target, event) => {
  const row = target.closest("[data-session-row]");
  if (row === null) return null; // 不处理,交给下一个 provider

  return [
    { type: "label", text: row.dataset.title },
    { label: "复制标题", onClick: () => navigator.clipboard.writeText(row.dataset.title) },
    { type: "separator" },
    { label: "删除会话", danger: true, onClick: () => { /* ... */ } }
  ];
});

菜单项模型

形式说明
"字符串"简写 item,label 即字符串
{ label, onClick?, disabled?, danger?, hint? }常规项;onClick(item, ctx)ctx{ target, x, y }
{ type: "separator" }分隔线(连续分隔线自动压缩,首尾丢弃)
{ type: "label", text }只读分组标题

完整 API(window.dshContextMenu

| 成员 | 说明 | | --- | --- | | register(provider) | 注册 (target, event) => items[] \| null,返回注销函数;多个 provider 依次询问,第一个非空结果胜出 | | setEnabled(bool) / enabled | 全局开关;关闭后完全放行浏览器原生右键菜单 | | open(x, y, items) | 命令式在视口坐标弹菜单(不经过拦截器) | | close() / isOpen / itemCount | 关闭 / 状态查询 | | debug() | 诊断各部件状态,便于排障 |

工作区“打开文件夹”的匹配规则

右键目标向上查找 div[role="treeitem"],三路匹配 ctx.workspaces.list 条目,任一唯一命中即提供菜单项:

1. 行尾省略号按钮的 aria-label 匹配官方 workspace 字典 2. 行内首个文本 span 匹配 workspace title 3. 行内首个文本 span 匹配目录 path 的 basename(title 被重命名时)

> 重名工作区不提供菜单项,避免打开错误目录。

行为约定

  • 输入框 / 文本域 / 可编辑元素右键 → 放行原生菜单(保留复制/粘贴)
  • 自定义菜单自身右键 → 放行(避免关掉又弹)
  • 其余区域且 provider 命中 → preventDefault() + 弹出自定义菜单
  • 无 provider 命中 → 关闭已打开的自定义菜单并放行原生菜单
  • 关闭方式:点击菜单项 / 点击菜单外 / Esc / Tab / 锚点滚出视口 / 窗口缩放或失焦
  • 菜单尾部固定附“打开浏览器菜单”,点击后下一次右键显示浏览器原生菜单(仅一次)

文件结构

文件作用
lib/client.js浏览器半:全局拦截 + 菜单框架 + 工作区 provider(点击调用 folderOpener/open 远程)
lib/index.jshost 半:folderOpener Typert 远程服务(路径校验、平台命令分派、Windows 前台激活)
cordis.patch.ymlbundle patch,安装时自动挂载
test/node:test 单元测试

开发

pnpm install
pnpm test

依赖

  • zod:host 侧 wire schema
  • @deepseek-ai/dsh-typert-protocol:Typert Remote 服务基类
  • @deepseek-ai/cordis:Service 基类(Typert 协议 peer)

浏览器半(lib/client.js)为手写 bundle,零依赖、全部原生 DOM。

限制

  • 菜单项为单层(无子菜单)
  • 工作区匹配依赖 DSH Web 官方 workspace 行结构与 ctx.workspaces 服务
  • 依赖浏览器 contextmenu 事件;Electron/浏览器外壳同样适用

License

MIT