Meowrium/dsh-copy-file-path

dsh-copy-file-path

dsh plugin: adds 复制相对路径 / 复制绝对路径 (copy relative / absolute path) to the delivered-file card menu of the DeepSeek Harness web UI. / dsh Web 交付文件卡片菜单增加复制相对路径与复制绝对路径。

待分类clipboarddeepseek-harnessdsh

dsh-copy-file-path

English README

给 DeepSeek Harness(dsh)Web 前端的交付文件卡片菜单加上「复制相对路径」和「复制绝对路径」两项。

每轮对话结束时,dsh 会把该轮交付的文件显示成卡片。卡片上有一个「打开」按钮,以及一个「⋯」菜单,里面只有「用默认应用打开」和「在文件资源管理器中显示」(Linux 上是「打开所在文件夹」)。本插件在这个菜单末尾追加两项:

菜单项复制的内容
复制相对路径相对当前会话工作区的路径
复制绝对路径主机上的绝对路径

点击即复制到剪贴板,并弹出一个短提示显示复制了什么。

⋯  ┌──────────────────────────┐
   │ ↗  用默认应用打开         │  ← dsh-client-ui-deliverables 自带
   │ ▤  在文件资源管理器中显示 │
   │ ⧉  复制相对路径           │  ← 本插件
   │ ⧉  复制绝对路径           │  ← 本插件
   └──────────────────────────┘

安装

dsh plugin --profile web add github:Meowrium/dsh-copy-file-path

装完重启 dsh web,并硬刷新页面(Ctrl+Shift+R)——宿主在启动时装配 bundle,浏览器端需要重建客户端模块。

为什么非得写插件

那两行菜单是 @deepseek-ai/dsh-client-ui-deliverables 里硬编码的 items 数组,由 @deepseek-ai/dsh-client-ui-primitives 的 Menu 渲染(一个 role="menu" 的列表,portal 到 document.body)。既没有 slot、注册表或钩子可以插行,想 shadow 就得把整张卡片重写一遍。

所以本插件走DOM 后处理这条路(和 dsh-mermaid 同一套办法):不改内核、不猴补 React 内部。它盯着那个 portal,当某张交付卡片的箭头处于展开态(aria-expanded="true")时,克隆最后一行、改标签、换成复制图标、接管点击。注入的行是纯 DOM:点击处理器会 stopPropagation,React 根节点根本看不到这个事件;菜单则通过与「点击别处」完全相同的 outside-pointerdown 路径关闭。

两个路径从哪来

不猜、不改写,两个值都取自 dsh 自己手里已有的东西:

取值来源
绝对路径卡片预览按钮的 title,也就是 dsh 自己解析并打开的那个路径(resolveWorkspacePath(cwd, file.path))。逐字复制,分隔符不动。
相对路径该轮向 present 工具声明的路径,从卡片自身的 aria-label 里取回({路径} 的更多文件操作 / More file actions for {路径})。若当初声明的就是绝对路径,则按工作区根重新计算。
工作区根由上面这一对(绝对、声明)反推,构造上精确;客户端会话状态(sessions.list)只是兜底,用于标签里没有声明路径的卡片。

某个值拿不到时,对应的那一行直接不出现——绝不给一个错的路径。

兼容性

  • 适用于带交付文件卡片的 dsh Web 界面。实测环境:0.1.6-alpha.1 / Windows;更早版本线未验(bundle 形态与 0.1.5 线相同,但没实测过)。
  • 零运行时依赖。浏览器半只用 DOM,外加可选的 locale、sessions 两个客户端服务:inject 为空,即使这两个服务缺失插件照样加载——标签回退英文、工作区根从卡片自身推导。

测试

两个用例都不需要 dsh 实例:

node test/paths.test.mjs        # 路径纯函数的 35 条断言

test/fixture.html 复刻了交付卡片与 primitives 菜单 portal(结构逐条读自 0.1.6-alpha.1 的发布代码),用桩模块加载器载入 lib/client.js,在真实浏览器里跑 23 条检查:注入与标签语言、两个复制值、菜单关闭、事件不外泄进 React 容器、负控(无关菜单不注入)、幂等、以及完整卸载。用浏览器打开该文件即可,结果渲染在页面上,同时写进 document.title。

已知边界

  • 只覆盖交付文件卡片的菜单。「本轮文件改动」胶囊与侧边栏文件树本身没有菜单,因此不受影响也没有增强。
  • 那个菜单属于内置组件:将来 dsh 若改动卡片结构,本插件可能需要同步更新。检测不到时它选择不注入,而不是把两项塞进一个无关的菜单。
  • 只复制文本:不读文件、不打开文件、不外发,完全没有宿主侧访问(host 半是刻意留空的)。

卸载

dsh plugin --profile web remove dsh-copy-file-path

许可

MIT