前言¶
DeepSeek Harness(DSH)里不少第三方插件通过 webServer.tapIndex(html => html) 向页面注入 <script>、<style> 等标记。在 dsh web 或 Host 自行渲染 index.html 的路径上,这套机制工作正常;官方桌面版却加载内置 SPA(dsh-app://app/),只消费 Host 经 IPC 上报的结构化注入行(webserver/index-inject),不会执行 renderIndex() 里的 tapIndex 变换。结果是插件在列表里显示已启用、加载也无报错,但注入的资源从未出现在页面里。下面介绍社区插件 dsh-index-tap-bridge 如何在不改目标插件源码的前提下,把 tapIndex 桥接到桌面外壳能识别的注入通道。
这是什么¶
dsh-index-tap-bridge(GitHub:VCPr0j3k7/dsh-index-tap-bridge)由维护者 VCPr0j3k7 发布,分类为客户端插件,当前版本 0.1.0,许可证 MIT。它以独立 bundle 形式装入 DSH profile,在 webserver/index-inject 事件触发时读取已注册的 indexTaps,把变换产生的新增 HTML 标记翻译成结构化注入行,再 push 进注入表,使依赖 tapIndex 的第三方插件在官方 Harness 桌面版中同样生效。
问题背景与两条注入通道¶
@deepseek-ai/dsh-host-webserver 向 index.html 提供两条通道:
| 通道 | 主要使用者 | 官方桌面版 |
|---|---|---|
结构化注入行(webserver/index-inject 事件) |
官方插件(如 dsh-client-modules) |
生效 |
索引变换(tapIndex(html => html)) |
大量第三方插件 | 不生效 |
桌面版不渲染 Host 的 index.html:窗口加载外壳内置 SPA;Host 启动后仅上报一次 collectIndexInjections() 的结果。tapIndex 只在 renderIndex() 内执行,而桌面版不会走该路径。官方源码将 applyIndexTaps() 描述为 “the escape hatch for markup no IndexInjection row expresses”——桥接插件正是把 escape hatch 里的产出转写为 IndexInjection 行能表达的形式。
核心功能¶
- 透明兼容:目标插件仍调用
tapIndex(),变换保留在indexTaps中;浏览器与dsh web经renderIndex()的行为不变。 - 翻译注入:在桌面外壳场景下,对每个 tap 作用于最小骨架 HTML,提取新增标记,按规则映射为
script-src、script、style、html等kind,并按kind与载荷去重。 - 条件启用:默认根据
process.argv是否包含dsh-desktop-host判断是否启用桥接,避免在自包含外壳(仍走renderIndex())上重复注入。 - Bundle 集成:通过
dsh.bundle.patch(cordis.patch.yml)挂入 profile;dsh plugin安装后会运行reconcilePlugins()自动维护dsh.profile.bundles。
翻译规则摘要(完整表见仓库 README):
| 原始标记 | 翻译结果 |
|---|---|
<script src="U"> |
{ kind: 'script-src', src: 'U' } |
<script>内联</script> |
{ kind: 'script', text, placement } |
<style>…</style> |
{ kind: 'style', text } |
<link>、div 等 |
{ kind: 'html', placement, html } |
桌面前端对 html 行使用 insertAdjacentHTML(),经此插入的 <script> 不会执行,因此 <script> 必须单独映射,不能由 html 行承载。
环境要求¶
| 项 | 要求 |
|---|---|
| Node.js | ^22.19.0 \|\| >=24 |
| DeepSeek Harness | 已在官方桌面版 0.1.7-rc.2 上验证 |
安装与启用¶
插件以 DSH profile 为单位安装。Web 侧常用 web profile(DSH 首次运行自动创建);官方 Harness 桌面版使用 desktop profile。
装入 web profile:
dsh plugin --profile web add github:VCPr0j3k7/dsh-index-tap-bridge
桌面版:
dsh plugin --profile desktop add github:VCPr0j3k7/dsh-index-tap-bridge
无需手改 dsh.profile.bundles。确认已登记:
dsh --profile web --dump-config
输出中应包含 index-tap-bridge。安装完成后需重启目标 harness;桌面版在启动时加载插件,运行中的实例不会热更新。
排障时可覆盖启用逻辑:
| 环境变量 | 取值 | 作用 |
|---|---|---|
DSH_INDEX_TAP_BRIDGE |
on |
强制启用 |
DSH_INDEX_TAP_BRIDGE |
off |
强制关闭 |
卸载¶
dsh plugin --profile desktop rm dsh-index-tap-bridge
reconcilePlugins() 会同步清理 bundle 条目;若有残留可手动删除对应项。卸载后同样需要重启 harness。
典型验证方式¶
仓库提供不依赖 DSH 运行时的逻辑自检:
npm test
test/check.mjs 覆盖翻译分支、空载荷丢弃、顺序保持、不可翻译标记上报及桌面外壳判定;README 记载当前 23/23 通过。
端到端:安装并重启桌面版后,原先不显示挂件的 tapIndex 插件应开始工作;若插件有日志,可看到其注入资源被请求。
适用场景与注意¶
适合谁:已在 DSH 中启用依赖 tapIndex 的第三方插件,且主要使用官方桌面外壳的开发者。
权限与安全:插件随当前 DSH 进程以相同权限运行。安装前请阅读 GitHub 仓库 源码与 MIT 许可证,自行评估是否纳入 profile。
已知限制(摘自 README):
- 仅翻译新增标记;若 tap 修改已有 DOM 片段,无法翻译,会通过
console.warn列出。 - 官方若变更
indexTaps字段名,桥接可能静默失效(有Array.isArray守卫)。 <canvas>等需「替换节点」语义的标记不会强行译为html行。- 桌面版插件库开关可能重写
dsh.profile.bundles(sanitizeProfile);桥接突然失效时,先检查 bundle 中是否仍有该条目。
DSH 生态强调「一切皆插件」;社区目录 SkillHub 插件页 为独立站点,与 DeepSeek / 幻方无官方从属关系。
结尾¶
dsh-index-tap-bridge 解决的是官方桌面版与 tapIndex 注入路径脱节的问题:在 Host 仍注册 tap 的前提下,于 index-inject 时刻把新增标记翻译成外壳能应用的注入行。若你的插件列表正常但页面脚本从未加载,可先为 desktop profile 安装本桥接并重启,再对照 README 中的限制排查未翻译的标记。
- 目录页:https://www.skillhub.cn/plugins/VCPr0j3k7/dsh-index-tap-bridge
- GitHub:https://github.com/VCPr0j3k7/dsh-index-tap-bridge