dsh-tool-gateway:把 DSH 工具目錄收成 find_tools / call_tool / call_tools

前言

在 DSH 裏接 MCP、裝插件、換 preset 之後,註冊表裏的工具會越來越多。模型側往往只能看到一份被截斷或精簡後的工具表:表一長就容易挑錯工具;表被截斷時,沒出現在表裏的工具容易被忽略,模型會反覆用幾個熟面孔湊合。

另外,工具定義通常排在每次請求的最前部。工具表一變,整段前綴緩存就會失效,帶來重新計費和首字延遲變長——而工具表又恰恰是最容易變動的一塊。

下面介紹社區插件 dsh-tool-gateway(維護者 leolee9086),它把模型可見的工具表收成少量「元工具」,其餘工具仍可通過元工具調用,並配套會話開關、工具箱面板、工具組與硬禁用名單。分類爲工作流;倉庫當前星標爲 0。目錄頁:https://www.skillhub.cn/plugins/leolee9086/dsh-tool-gateway,源碼:https://github.com/leolee9086/dsh-tool-gateway。

這是什麼

dsh-tool-gateway 掛在 DSH profile 層(根作用域),對 preset 與會話施加同一套網關邏輯(會話級總開關除外)。它做兩件事:

  1. 可見性:在裝配系統提示時過濾 assembled.tools,讓模型可見的工具表主要是 find_tools、call_tool,以及在條件滿足時的 call_tools。
  2. 執行守衛:拒絕模型對其它工具的直接調用;通過 call_tool(帶 parent 的子分發)發起的調用仍走 ctx.tools.execute(),審批、守衛、沙箱與會話日誌與直接調用一致。

因此,長列表不再堆在模型眼前,而是先 find_tools 查、再 call_tool 調;裝插件或改面板開關時,模型可見的工具表字節可以保持不變,變的只是檢索索引與守衛判定。

三個元工具

工具 作用 何時用
find_tools 按名字、描述、中文或拼音檢索,返回完整參數 schema 不知道有什麼工具,或不清楚參數怎麼寫
call_tool 調用單個工具,參數爲 {tool_name, arguments} 一次調一個
call_tools 用一段 TypeScript 程序批量調用 連續調多個,中間結果不必進對話

find_tools 的結果按 token 估算收縮(默認預算 10000,可配置);單個 schema 不截斷。被截斷時可用返回的 offset 繼續查同一查詢。普通查詢不會列出會話裏關掉的工具;要用 find_tools({scope: "disabled"}) 查看關着的工具——該路徑每次需審批,在 danger-full-access 下會直接拒絕。

call_tools 在 DSH PTC 運行時中執行模型寫的程序,程序內僅可調用 tools.find_tools({query}) 與 tools.call_tool({tool_name, arguments});只有 return 的值回到對話。參數與輸出對齊官方 PTC 的 run_code(含 description 必填、結構化輸出與 CodeRunFailedError),但 SDK 聲明只保留上述兩條,避免把整份註冊表再餵給模型。

何時不掛 call_tools:

  • 已開啓 PTC 模式(mode: 'ptc' 或 'both'),且可見集裏已有 run_code。
  • 部署未提供 ctx.ptcRuntime。

檢測按會話進行;讀不出時保守地不掛載 call_tools。

會話開關、工具箱與工具組

會話級總開關

Web 會話標題欄有「工具箱 開 / 工具箱 關」chip,控制當前會話是否施加網關約束,默認開。狀態持久在 $DSH_HOME/storages/tool_gateway/sessions;子代理跟隨父會話。關閉後模型看到完整工具表,可直接調用任意工具;執行守衛立即生效,工具表與提示段落在下一輪請求生效。切換時會通過 agent.inject() 注入一條用戶可見通知。無 webServer 的 headless 部署不掛界面,開關固定爲默認「開」。

工具箱面板

右側欄「工具」面板列出該會話可見的全部工具(含被網關收起來的)。單工具三態:未設置(跟隨組默認)、顯式開、顯式關。關掉後從 find_tools 結果消失,直接調用會被守衛拒絕;三個元工具不可關。面板改動同樣會通知模型。網關開啓時,開關只改目錄索引與守衛,不用 restrict() 改可見工具表,以免破壞前綴緩存。

工具組

註冊方可聲明一批工具默認關着,避免一次註冊幾百個工具時面板爆滿。示例(摘自 README):

const gateway = ctx.get('toolGateway')
if (gateway !== undefined) {
  const group = gateway.registerGroup({
    id: 'siyuan-http',
    title: '思源 HTTP 端點',
    origin: 'dsh-plugin-siyuan',
    defaultEnabled: false,
  })
  ctx.effect(() => () => group.dispose(), 'siyuan: gateway group')
  for (const tool of tools) {
    ctx.tools.register(tool)
    group.add(tool.name)
  }
}

未安裝網關時 ctx.get('toolGateway') 爲 undefined,插件應照常註冊工具,只是沒有「默認關着」語義。

硬禁用名單

部分工具在任何會話、任何路徑(含 call_tool 子分發)都不允許執行。默認禁用 ask_user_question。配置 ban: { deny: [] } 表示顯式清空禁用列表;完全不寫 deny 才使用默認名單。配置項中的名字在面板裏也不可切換。

安裝與啓用

插件以當前 DSH 進程權限運行,安裝前請自行查看源碼與 MIT 許可證。要求 Node >=22.19.0。

dsh plugin --profile web add github:leolee9086/dsh-tool-gateway#v0.3.0

安裝會依據包內 dsh.bundle.patch 追加到 dsh.profile.bundles,無需手工改 profile 的 cordis.patch.yml。倉庫提交的是 lib/ 產物,從 git 安裝不需要 pnpm 構建授權。重啓 DSH 生效,不需要改 preset。

典型用法(模型側)

網關開啓且會話約束爲「開」時,模型側流程可以概括爲:

  1. 用 find_tools 按任務關鍵詞檢索,必要時用 offset 翻頁,拿到目標工具的完整 schema。
  2. 用 call_tool 傳入 tool_name 與 arguments 執行。
  3. 若需連續多步且中間結果不必進上下文,在 PTC 可用且未與官方 run_code 衝突時,用 call_tools 寫短程序,內部只調用 tools.find_tools 與 tools.call_tool。

人在 Web 界面可通過標題欄 chip 關閉單會話約束,或在工具箱面板按工具/按組開關;需要看被關工具時用 find_tools({scope: "disabled"})(受審批策略約束)。

適用場景與注意

適合: 工具數量多、經常接 MCP 或熱插拔插件,希望模型「先查再調」、並穩定前綴緩存的 DSH 用戶;插件作者希望大批量工具默認關着、由用戶按需打開。

注意:

  • 插件版本以安裝標籤爲準(資料中爲 v0.3.0);鎖版本可把 #v0.3.0 換成 commit sha。
  • 硬禁用與 danger-full-access 下對 scope: "disabled" 的限制屬於安全設計,部署時需理解審批服務行爲。
  • 社區目錄 SkillHub 與 DeepSeek / 幻方無官方從屬關係;DSH 生態是「一切皆插件」,本文事實均來自上述倉庫 README 與 package.json。

結尾

dsh-tool-gateway 用可見性過濾加執行守衛,把工具入口收成檢索與調用元工具,並用面板與工具組管理「誰能被查到、誰能被執行」,同時儘量保持模型可見工具表穩定。進一步瞭解請見目錄頁 https://www.skillhub.cn/plugins/leolee9086/dsh-tool-gateway 與 GitHub https://github.com/leolee9086/dsh-tool-gateway。

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

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

小夜