dsh-super-injector

127Star17Fork20Issue2Watching

DSH 生态的"模组注入器":免重启把任意本地插件包加载到运行中的 web,含热重载/自重载/一键卸载/路由自愈/侧挂区与设置页插件管理 UI。

语言
TypeScript
分支
main
dshdsh-plugin

安装

$ dsh plugin --profile web add github:yjh051108/dsh-super-injector

在终端中运行以上命令,通过 dsh CLI 安装此插件。可在右上角切换 Profile。 第一次用 dsh?看这篇新手教程

一句话定位

DSH(DeepSeek Harness)的运行时"模组注入器":装好它之后,对 agent 说一句话就能把任意本地插件包免重启加载到运行中的 web,并把整套开发闭环——热重载、自重载、一键卸载、路由自愈、侧挂测试区——一并交付,省掉反复重启和改配置。

核心能力

  • 运行时注入任意本地插件包:把插件目录链接到 profile 的 node_modules,再用 loader.create 装配,不动 patch/package.json,免重启立刻生效(含 host 工具 + client UI)
  • 整包热重载:改代码 → build → 1.5 秒内自动监听文件指纹变化触发重载,或显式调用 dev_reload_package;失败自动回滚保留旧版
  • 一键卸载 + 路由自愈:卸 loader entry、清注入清单、删 junction、清 webserver 路由残留,全部免重启
  • 双路径安装 + 启动自动恢复:既可运行时注入(开发态)也可走 profile bundles(重启后由官方接管);注入清单持久化,重启后自动归位
  • 插件生产线脚手架:内置四种形态骨架(工具包 / 守护循环 / UI 面板 / 混合),含构建脚本、peerDependencies 范围声明、ctx.effect 资源注册规范
  • 设置页插件管理 UI:客户端新增"插件"设置页,可视化浏览已注入插件、一键卸载、拖入文件夹走"内化"(新建 agent 会话让 AI 把内容变成插件)

技术实现

  • 语言: TypeScript(ESM、NodeNext)
  • 关键依赖: @deepseek-ai/dsh-tools(peer,工具注册)、cordis(peer,DI/fiber)、schemastery(peer,Config Schema);运行时还用到 node:fs / node:path / node:os / node:child_process
  • 架构模式: 自带一个 cordis 引导器 entry(通过 cordis.patch.ymlinsert 注入),注册 16 个 dev_* 工具(host 层) + 一个 settings.section 客户端 UI;host 与 client 各自走独立 build(tsc + tsdown)
  • 入口文件: src/index.ts:570apply(ctx, config)),客户端入口 src/client/index.ts:54

适用场景

  • 想在 DSH 上快速试用或迭代自己的插件包,但又不想每次重启 web(debug 时频繁重启尤其痛苦)
  • 需要让 AI agent 自己决定"装/卸/换"插件的运行时管理面——官方装配机制只覆盖"装什么",而"装完之后怎么改"留白
  • 多人/多环境的 DSH 部署里,需要在不碰官方 profile 配置的前提下注入第三方插件

前置依赖与兼容性

依赖最低版本说明
DSH(@deepseek-ai/dsh-tools)>=0.0.1-rc <2peerDependencies 范围声明,DSH 0.1.0-rc.6 已实测通过,升级不需改插件
cordis>=4.0.0-rc <5peerDependencies 范围声明
schemastery^3.18.0peerDependencies
Node未声明devDependencies 用 @types/node ^24.13.3;运行依赖与 DSH 宿主 Node 版本一致即可
平台macOS / Windows / LinuxWindows 用 NTFS junction,其他系统用软链;Windows 需要 Git Bash 或 WSL 运行 bash 构建脚本
原生模块仅用 node:fs / node:path / node:os / node:child_process / node:url
外置工具bash + node + npm仅在使用 dev_scaffold_plugin / dev_build_plugin 脚手架工具链时需要;纯注入/卸载不需要 bash

安装方式

dsh plugin --profile web add github:yjh051108/dsh-super-injector

配置项

配置类型说明默认值
registryFilestring注入清单持久化文件路径;记录已注入的插件包目录与时间,重启后按此自动恢复~/.dsh/super-injector/registry.jsonDSH_HOME 优先于 homedir()
profileNodeModulesstringprofile 的 node_modules 路径;junction 链接目标,DSH loader 据此解析包~/.dsh/profiles/web/node_modules
autoRestoreboolean启动时是否自动恢复注入清单(重新链接并装配所有已注入的包)true
intervalMsnumberwatch 自动轮询检测产物指纹的间隔毫秒;构建产物整批写入,间隔天然合并抖动1500
watchesarray自定义监听目录与匹配子串,每条形如 {dir, match};loadCache key 是 realpath URL,按目录名子串匹配[]

常见问题

Q: 装好之后看不到 dev_ 工具怎么办?*

A: 先确认注入器已通过官方装配路径(dsh plugin --profile web addcordis.patch.yml)生效、对应 web profile 已重启,再对 agent 说 dev_plugin_status——若列表里没有 dsh-super-injector,多半是装到了非运行 profile。

Q: 注入一个 UI 形态插件报 "client ✗" 怎么排查?

A: 若插件本来就没声明 dsh.client.platform,会显示"跳过",这是预期。若显示"注册失败",说明缺 lib/client.js 或 client bundle 不是 tsdown 产物;需要 npm run build:client 单独构建 client bundle,注入器会在注入前自动阻断。

Q: dev_reload_package 报"重载目标命中注入器自身"被拒绝?

A: 注入器拒绝普通路径下的自毁——必须用 dev_reload_package 匹配名中带 dsh-super-injector(走自重载分支),且两次自重载间隔必须 ≥10 秒,否则会被节流拦下。

Q: web 启动报 "duplicate loader entry id" 崩溃怎么修?

A: 在解压目录里跑 node scripts/fix-patch.mjs(或在已起的环境里用 dev_fix_patch),按 id 去重并自动备份原文件;dsh loader 严格要求同 id 仅一条。

Q: Windows 上构建报 "找不到 bash" 或 WSL 报错?

A: 注入器主动拒绝 WSL 的 System32\bash.exe(System32 抢先 PATH 时会启动失败),需要装 Git for Windows / PortableGit 并把 Git\bin 加到 PATH;Windows 链接用 NTFS junction 而非符号链接。

Q: 注入的插件重启后还在吗?

A: 在。注入清单持久化到 ~/.dsh/super-injector/registry.json,下次装配时 autoRestore 默认开启,自动按清单逐个重新注入;侧挂转正的工具也持久化在 staging.json

Q: 怎么彻底卸载注入器?

A: dsh plugin --profile web remove @yjh051108/dsh-super-injector,再清理 cordis.patch.yml 里相关条目(保持单一顶层数组)、删 profile node_modules 链接、可选删 ~/.dsh/super-injector/ 目录;重启后 dev_* 工具消失即卸载完成。

Q: scaffold 出来的骨架能直接注入吗?

A: 可以,但需要先 dev_build_pluginDSH_CHECKOUT 环境下构建出 lib/;骨架已强制 ctx.effect 注册规范与 peerDependencies 范围声明,client 形态还会校验 slots.register 的合法 slot 名。

上手难度

进阶 — 不只是装一个插件,而是把官方装配机制之外的一整套运行时管理面带进来;要理解 junction、loader.create、cordis fiber 与 schema 注入才能读懂源码;普通用户只需按 README/INSTALL 走完安装与自检即可用。

已知问题与限制

  • 自重载必须显式调用 dev_reload_package 且匹配串含 dsh-super-injector;watch 自动重载不会触发自重载(防无人值守时注入器永久缺席)
  • 自重载最小间隔 10 秒(防连环自杀),节流时间戳落盘到 ~/.dsh/super-injector/self-reload.json 以跨实例持久
  • client 形态插件必须声明 inject = ['slots']slots.register 的 name 落在已知白名单(conversation.view / settings.section / settings.plugin.item 等 11 个),否则注入会被阻断
  • 注入前会校验构建产物新鲜度:声明了 dsh.client.platform 但缺 lib/client.js 或产物非 tsdown 输出(缺 __ModuleLoader__ 标记)→ 阻断;src/lib/ 新 → 警告不阻断
  • Windows 上 PowerShell 编辑过的 cordis.patch.yml 可能含 UTF-8 BOM,注入器主动检查 BOM 并拒绝
  • DSH_HOME 环境变量与 web 进程的 homedir() 不一致(如服务账户)时,路径推导会全部错位——以 DSH_HOME 为权威
  • WSL 安装但未配分发版时,System32\bash.exe 抢先 PATH,注入器主动探测并拒绝,需用 Git for Windows / PortableGit
  • 测试插件(dev_self_test)的临时目录固定在 DSH_HOME 下的 super-injector/selftest-runner,目录名/路径变化会触发 tsx 旧缓存命中导致重载失败
  • peerDependencies 范围声明是脚手架的强制约束(不硬编码版本),下游插件作者若改用 0.1.0 这种精确版本,可能因 DSH 升级而装不上
dsh-super-injector — DeepSeek Harness 插件 | deepseek-plugin.org