DeepSeek Harness 插件:對話內文件右鍵「打開方式」

前言

DeepSeek Harness(DSH)的對話界面裏經常會出現文件鏈接:Markdown 裏的文件引用、@文件 引用、路徑標籤等。在沒有輔助插件時,打開這些文件通常只能用瀏覽器默認行爲或複製路徑後在文件管理器裏手工定位。DSH 插件市場裏已有幾個提供右鍵菜單的插件,但大多隻能調用已註冊文件類型關聯的應用。如果遇到未註冊關聯的程序(例如 Visual Studio),這些插件就無能爲力。

本插件爲 DSH 增加「文件右鍵 → 打開方式」能力。在對話界面右鍵點擊文件,可使用系統默認應用打開、在文件管理器中定位、選擇已註冊的編輯器或終端,以及通過系統「打開方式」對話框選擇未註冊的應用。

插件定位

名稱:dsh-open-any
維護者:xl0223
分類:客戶端
GitHub:https://github.com/xl0223/dsh-open-any
許可證:MIT
DSH 版本要求:≥ 0.2.0-rc.1

插件通過在瀏覽器側識別文件元素並右鍵注入菜單,再通過 Host 側路由調用系統命令,實現跨平臺的文件打開能力。

識別範圍與行爲

插件識別以下元素,通過 title 屬性提取路徑:

  • Markdown 文件鏈接:button.fileLink
  • 輸入框 / 消息裏的 @文件 引用:[data-ref-chip="file"]
  • 路徑標籤:[data-path-label]
  • 其它帶 title 的元素(兜底)

右鍵菜單包含以下選項:

  1. 用 <默認應用> 打開
    使用系統默認關聯程序打開文件。

  2. 在文件資源管理器中打開
    一級菜單項,在文件管理器中定位該文件(Windows 爲「文件資源管理器」,macOS 爲「在訪達中顯示」)。

  3. 打開方式 ▸
    列出本機爲該文件類型註冊過關聯的編輯器 / 終端,帶真實圖標與「(默認)」標記。

  4. 其他應用…(系統對話框)
    喚起 Windows 原生「打開方式」對話框,可選未註冊文件關聯的應用(例如 Visual Studio)。這是本插件獨有的能力。

  5. 複製路徑
    複製文件的絕對路徑。

路徑處理:相對路徑會按當前正在查看的會話的工作目錄補全成絕對路徑。非文件位置右鍵仍彈出瀏覽器原生菜單。

與同類插件的區別

DSH 插件市場裏已有多個提供右鍵菜單的插件,本插件不追求功能最全,而是聚焦兩點:

  1. 「其他應用…(系統對話框)」
    通過 rundll32 shell32.dll,OpenAs_RunDLL 喚起系統選擇器,可打開未註冊關聯的應用。只列 workspacePathApplications 的插件無法覆蓋這類程序。

  2. 不拖垮啓動的工程約束
    Client 插件在 apply 階段不拋異常、不等待服務就緒。DSH 的 web boot 機制會把非 active 條目視爲致命錯誤,本插件爲此採用「服務延遲到事件發生時惰性解析」的設計。

如果需要超鏈接右鍵、另存爲、複製文件內容、文件樹右鍵等能力,建議使用更全面的現有插件。

安裝與啓用

從 GitHub 安裝(推薦)

在 DSH 的「設置 → 插件」或插件管理器的添加框裏填:

github:xl0223/dsh-open-any

或使用 DSH 自帶 CLI(把 <profile> 換成你的 profile 名,例如 desktop):

dsh plugin --profile <profile> add github:xl0223/dsh-open-any

安裝完成後需要重啓 DSH:client bundle 按文件 mtime 生成 rev 並版本化緩存,不重啓不會重載。

本地源碼調試

dsh plugin --profile <profile> add link:C:\path\to\dsh-open-any

修改 src/ 後必須重新運行 node scripts/build.mjs(DSH 加載的是 lib/);修改 lib/client.js 後刷新頁面即可,修改 host 半側需要重啓。

卸載

dsh plugin --profile <profile> remove dsh-open-any

或從 profile 的 package.json 裏刪除 dsh.profile.bundles 與 dependencies 中的 dsh-open-any,然後重啓。

兼容性

  • DSH 版本:0.2.0-rc.2 上完成真機驗證(菜單、應用列表、打開、文案)。
  • DSH 0.2.1-rc.2:已靜態確認模塊基座表,未做真機重驗。
  • 平臺:Host 側使用 rundll32 / explorer / open / xdg-open,三平臺均有實現,但只在 Windows 11 上實測過。
  • Node:構建需要 Node ≥ 20;運行時只用 DSH 自帶能力。

開發與驗證

構建與驗證命令(在插件根目錄執行):

node scripts/build.mjs                                                  # 語法 + 契約校驗 → lib/
node --test scripts/verify-client.test.mjs scripts/verify-host.test.mjs  # 離線單測
node tools/check-host-contract.mjs                                      # 與真實 app.asar 的模塊/路由契約
node tools/probe-open-in-app.mjs                                        # 真機探測:本機會列出哪些應用

一條命令跑全部:npm run check。

驗證報告(基於 README 提供的實測結果):

  • 平臺:Windows 11;DSH D:\Ai_Agent\DeepSeek Harness(0.2.0-rc.2 真機 / 0.2.1-rc.2 靜態)。
  • 構建:成功生成 lib/client.js 和 lib/index.js。
  • 離線單測:30 / 30 通過。
  • 宿主契約:檢查通過,所有 require 與導出名均存在。
  • 真機驗證:右鍵文件 → 菜單彈出 → 應用列表來自本機 → 選擇應用後文件被打開;「其他應用…」喚起 Windows 原生選擇器。

已知限制

  • 0.2.1-rc.2 未真機重驗,僅靜態確認模塊基座表。
  • 「其他應用…」僅 Windows 實現(OpenAs_RunDLL);macOS / Linux 會返回 501。
  • 圖片類 Markdown 鏈接(有縮略圖浮層、無 title)不命中。
  • 只複製絕對路徑,沒有相對路徑 / 文件名 / 文件內容 / 另存爲。
  • 不處理超鏈接、不處理文件樹(側邊欄)內的右鍵。
  • 未做 canOpenWorkspacePath 預檢:文件不在工作區時,菜單仍會彈出、操作會失敗並提示。

踩坑記錄

  1. client 插件的 apply 絕不能拋異常,也不能等任何服務。
    DSH 的 web boot 把非 active 條目當致命錯誤。靜態 inject 會讓 fiber 永遠 pending;apply 裏同步調用 ctx.effect(...) + locale.register(...) 拋錯會讓 fiber failed,導致整個 GUI 打不開。正確姿勢是:factory 先掛一個 no-op exports.apply,真實實現包在 try 裏;apply 只做 DOM/React,服務延遲到事件發生時惰性讀取。

  2. ctx.inject 要一個一個注。
    把多個服務一次性交給一個 ctx.inject,只要有一個名字對不上就會永遠不回調,整條鏈路靜默失效。改成每個服務一條 ctx.inject([name], cb) 後立刻正常。

  3. locale.bind(ns)(key) 未命中時會原樣返回 key。
    必須判斷返回值 !== key 再採用,否則裸 key 會顯示到菜單裏。

  4. GUI 頁面的 origin 是 dsh-app://app,不是 http://127.0.0.1:<port>。
    瀏覽器側對相對路徑的 fetch 不一定到 host 路由,排查時以 host 半側寫盤的證據爲準。

  5. Host 側路徑必須先是絕對路徑。
    它用 path.resolve 按進程 cwd 解析,相對路徑要在瀏覽器側按會話 cwd 補全。

適用場景與注意

本插件適合需要在 DSH 對話界面中快速打開文件、定位文件位置、或使用未註冊關聯應用的場景。插件以當前 DSH 進程的權限運行,安裝前建議檢查源碼與許可證。

小結

本插件爲 DSH 增加了一個實用的右鍵菜單能力,特別在於支持通過系統對話框打開未註冊關聯的應用。如果你正在使用 DSH 進行智能體開發或日常對話,並經常需要處理本地文件,這個插件可以作爲工具鏈的一部分。

插件主頁與源碼:https://github.com/xl0223/dsh-open-any

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜