Module Injector for DSH ecosystem: Load any local plugin into a running web without restart, featuring hot reload, self-reload, one-click uninstall, route self-healing, and plugin management UI for side panels and settings pages.
$ dsh plugin --profile web add github:yjh051108/dsh-super-injectorRun the command above in your terminal to install this plugin via the dsh CLI. You can switch Profile in the top-right corner. New to dsh? Read the beginner tutorial
DSH (DeepSeek Harness) runtime "module injector": once installed, you can tell the agent to load any local plugin package into the running web without restart, and deliver the entire development loop—hot reload, self-reload, one-click uninstall, route self-healing, sidebar test area—all at once, eliminating repeated restarts and config changes.
dev_reload_package; failures auto-rollback to preserve the old version@deepseek-ai/dsh-tools (peer, tool registration), cordis (peer, DI/fiber), schemastery (peer, Config Schema); runtime also uses node:fs / node:path / node:os / node:child_processinsert in cordis.patch.yml), registering 16 dev_* tools (host layer) + one settings.section client UI; host and client each have independent builds (tsc + tsdown)src/index.ts:570 (apply(ctx, config)), client entry src/client/index.ts:54| Dependency | Min Version | Notes |
|---|---|---|
| DSH (@deepseek-ai/dsh-tools) | >=0.0.1-rc <2 | peerDependencies range declaration, DSH 0.1.0-rc.6 tested, no plugin changes needed on upgrade |
| cordis | >=4.0.0-rc <5 | peerDependencies range declaration |
| schemastery | ^3.18.0 | peerDependencies |
| Node | Not declared | devDependencies use @types/node ^24.13.3; runtime depends on DSH host Node version |
| Platform | macOS / Windows / Linux | Windows uses NTFS junction, other systems use symlinks; Windows needs Git Bash or WSL to run bash build scripts |
| Native modules | None | Only uses node:fs / node:path / node:os / node:child_process / node:url |
| External tools | bash + node + npm | Only needed when using dev_scaffold_plugin / dev_build_plugin scaffold toolchain; pure injection/uninstall doesn't need bash |
dsh plugin --profile web add github:yjh051108/dsh-super-injector
| Config | Type | Description | Default |
|---|---|---|---|
registryFile | string | Injection list persistence file path; records injected plugin package directories and timestamps, auto-restores after restart | ~/.dsh/super-injector/registry.json (DSH_HOME takes precedence over homedir()) |
profileNodeModules | string | Profile's node_modules path; junction link target, DSH loader resolves packages based on this | ~/.dsh/profiles/web/node_modules |
autoRestore | boolean | Whether to auto-restore injection list on startup (re-link and assemble all injected packages) | true |
intervalMs | number | Watch polling interval in ms for detecting build artifact fingerprints; build artifacts are written in batches, interval naturally merges jitter | 1500 |
watches | array | Custom watch directories and match substrings, each format {dir, match}; loadCache key is realpath URL, matched by directory name substring | [] |
Q: Can't see dev_ tools after installation. What should I do?*
A: First confirm the injector has taken effect through official assembly path (dsh plugin --profile web add or cordis.patch.yml), then restart the corresponding web profile. Ask the agent for dev_plugin_status—if dsh-super-injector is not in the list, it's likely installed to a non-running profile.
Q: Injecting a UI-type plugin reports "client ✗". How to debug?
A: If the plugin doesn't declare dsh.client.platform, it shows "skipped", which is expected. If it shows "registration failed", it means lib/client.js is missing or the client bundle isn't a tsdown output; you need to npm run build:client to build the client bundle separately. The injector will automatically block injection in this case.
Q: dev_reload_package reports "reload target hits injector itself" and gets rejected?
A: The injector refuses self-destruction via normal paths—you must use dev_reload_package with a match string containing dsh-super-injector (goes to self-reload branch), and the interval between two self-reloads must be ≥10 seconds, otherwise it gets throttled.
Q: Web reports "duplicate loader entry id" crash. How to fix?
A: Run node scripts/fix-patch.mjs in the extraction directory (or use dev_fix_patch in a running environment), which deduplicates by ID and auto-backs up the original file; dsh loader strictly requires only one entry per ID.
Q: Build reports "can't find bash" on Windows or WSL errors?
A: The injector actively rejects WSL's System32\bash.exe (which fails when System32 takes priority in PATH). You need to install Git for Windows or PortableGit and add Git\bin to PATH; Windows uses NTFS junction instead of symlinks.
Q: Are injected plugins still there after restart?
A: Yes. The injection list persists to ~/.dsh/super-injector/registry.json. On next assembly, autoRestore is enabled by default, automatically re-injects each package from the list; sidebar-to-main tools are also persisted in staging.json.
Q: How to completely uninstall the injector?
A: dsh plugin --profile web remove @yjh051108/dsh-super-injector, then clean up related entries in cordis.patch.yml (keep single top-level array), delete profile node_modules links, optionally delete ~/.dsh/super-injector/ directory; after restart, dev_* tools disappearing means uninstall is complete.
Q: Can scaffold-generated skeletons be injected directly?
A: Yes, but you need to first dev_build_plugin under DSH_CHECKOUT environment to build lib/; skeletons already enforce ctx.effect registration specs and peerDependencies range declarations. Client-type skeletons also validate slots.register against legitimate slot names.
Advanced—it's not just installing a plugin, but bringing in a complete set of runtime management surfaces outside the official assembly mechanism; you need to understand junctions, loader.create, cordis fiber, and schema injection to read the source code; regular users only need to follow README/INSTALL to complete installation and self-check.
dev_reload_package with match string containing dsh-super-injector; watch auto-reload won't trigger self-reload (prevents injector permanent absence during unattended operation)~/.dsh/super-injector/self-reload.json for cross-instance persistenceinject = ['slots'] and slots.register name must fall within known whitelist (conversation.view / settings.section / settings.plugin.item etc. 11 slots), otherwise injection is blockeddsh.client.platform but missing lib/client.js or artifact isn't tsdown output (missing __ModuleLoader__ marker) → block; src/ newer than lib/ → warning without blockcordis.patch.yml on Windows may contain UTF-8 BOM, injector actively checks for BOM and rejectsDSH_HOME environment variable differs from web process's homedir() (e.g., service account), path derivation will be completely off—DSH_HOME is authoritativeSystem32\bash.exe takes priority in PATH, injector actively detects and rejects; need Git for Windows / PortableGitdev_self_test) temp directory is fixed at super-injector/selftest-runner under DSH_HOME; directory name/path changes will trigger old tsx cache hits causing reload failure0.1.0 may fail to install when DSH upgrades🎉 v0.3.0 重大声明(2026-08-14)
从经验补丁到源码契约——注入器完成规范重构。
本版本按 docs/SPEC.md(基于 DSH 0.1.0-rc.6 源码语义推导的 设计契约)重构自重载为官方 REPLACE 结构:工具只排程、绝不亲自自杀; reboot 走
entry._dispose(官方_disposing豁免)+ 失败自动 rollback。 从此注入器的一切行为都有源码依据,不再依赖经验补丁。里程碑回顾:
- 三轮零上下文 subagent 评测:9/10 → 9.5/10 → 10/10
- 作死压力测试:连环自杀/坏语法/悬空 junction/循环注入卸载——零崩溃零残留
- 云源自举:下载 release 副本 → 装配 → 注入器从云端副本运行(自检 8/8)
- 免杀进程恢复:失败 → touch patch(include.refresh 进程内重装配)→ 6 秒复活
- DSH 正式版兼容:0.1.0-rc.6 一行不改直接运行(peerDeps 范围声明实证)
哲学不变:一切皆插件——注入器是 DSH 生态的运行时注入标准层, 让"插件想长成什么样就长成什么样"。
DSH 生态的 BepInEx 式模组注入入口:运行时把任意本地插件包注入运行中的 web, 不碰 patch / package.json / bundles 列表、不重启进程。注入即完整生效(host 工具 + client UI)。
灵感:官方装配机制(profile bundle / repository-plugin)是唯一的"官方入口",就像游戏 只有启动器能装模组。本插件打破这一点——引导器走官方入口装一次,之后万物皆可运行时注入。
从 Releases 下载
dsh-external-dsh-super-injector-0.0.1.tgz,解压得到插件目录(含 lib/ 与 cordis.patch.yml),然后:
# 官方装配(重启后由 bundles 接管,生产态)
dsh plugin --profile web add <解压目录>
# 或运行时注入(免重启,开发态;需任一环境已常驻注入器)
# 对 AI 说:dev_inject_plugin <解压目录>
dsh plugin --profile web add github:yjh051108/dsh-super-injector
在 ~/.dsh/profiles/web/cordis.patch.yml 添加:
- insert:
- id: dsh-super-injector
name: '@yjh051108/dsh-super-injector'
config: {}
引导器常驻后,任意超级模组随取随用,无需再碰官方配置。
@deepseek-ai/dsh-tools: >=0.0.1-rc <2、cordis: >=4.0.0-rc <5)——DSH 升级不报废。webServer(原 httpServer)、compaction(原 compact)。dev_reload_package 整包重载(清缓存 → 重新 import → 重建 fiber,失败回滚保留旧代);注入器自身也支持自重载(自杀 → 全局定时器重建)dev_stage_promote 一键转正;staging 落盘,自重载/重启后转正工具自动恢复dev_uninject_plugin fiber 全清理(工具/监听/路由/client 表)→ 清注入清单 → 删 junction,免重启dev_clear_routes 直捣 webserver 内部路由表,热重载残留的孤儿路由免重启清除~/.dsh/super-injector/registry.json),web 重启后自动归位host ✓ / client ✓ 双验证;dev_plugin_status 含操作成功率统计hasActiveEntry 权威防重 + 失败残留缓存自动清理 + 残留 entry 自动清理| dsh-evolve | dsh-super-injector | |
|---|---|---|
| 形态 | 创造模式:agent 现场写单文件插件源码(~/.dsh/evolve/<name>.mjs)热挂载 | 手术台:注入开发者预构建的完整插件包(package.json + lib/) |
| 适用 | agent 随对话长出小工具(记账/天气/周报) | 装/换成品模组、自主开发闭环(写 → build → 注入 → 热重载) |
| 联动 | evolve 长出的源码可升级为完整包,再走注入器上膛 | 注入后可被 dev_reload_package 热重载 |
官方对插件体系的方向(2026-07 agent notes):
翻译:官方钦定"装什么"(bundle / repository + 配置),但"装完之后怎么改"——热重载、侧挂测试、一键转正、卸载、失败自愈——是官方留白。这一整块运行时管理面,由本插件吃下。
| 生态入口 | 层 | 一句话分工 |
|---|---|---|
| 官方 bundle / repository | 装配层 | 唯一官方入口,配置即状态 |
| plugin-registry | 官方薄控制台 | 官方格式插件管理与开发引导 |
| marisa | agent 面工具链 | 临时插件 → 持久化插件的固化桥 |
| mygo | 受管对象层 | 插件生命周期对象化(锁定/启停/依赖图) |
| dsh-evolve | 创造模式 | agent 现场长出单文件能力 |
| dsh-super-injector | 运行时手术台 | 开发闭环全家桶:注入 / 热重载 / 侧挂转正 / 卸载 / 路由自愈 / UI 联动 |
设计原则:
dev_install_package 落 profile bundles(重启后由官方接管,生产态)——注入清单只是运行时恢复缓存,不是第二安装数据库;目标:成为官方装配机制之下、生态事实标准的运行时管理层——"启动器装模组"只是起点,注入器让 DSH 拥有"万物可注入、注入可回滚、改完即生效"的 Mod 级体验。
| 工具 | 说明 |
|---|---|
dev_inject_plugin | 运行时注入本地插件包(junction 链接 + loader.create,hasActiveEntry 防重) |
dev_uninject_plugin | 一键卸载注入模组(fiber dispose 全清理;bundle 插件自动写 disabled 阻断自装配) |
dev_injected_list | 列出注入清单 |
dev_install_package | 热装配本地 bundle 插件(profile package.json + junction + loader.create,重启后由 bundles 列表正常装配) |
dev_reload_package | 整包热重载(清缓存 → 重新 import → 重建 fiber,失败回滚保留旧代;含自重载) |
dev_plugin_status | 已装配插件清单、fiber 状态与操作成功率统计 |
dev_clear_routes | webserver 路由残留自愈(按 path 前缀删除孤儿路由) |
dev_stage_add | 开发侧挂:测试工具挂后侧(不进 tools schema,缓存零污染) |
dev_stage_call | 调用侧挂工具测试 |
dev_stage_list | 列出侧挂工具(含转正状态) |
dev_stage_promote | 一键转正:侧挂工具挂前侧正式注册(唯一一次缓存刷新) |
dev_stage_demote | 撤回/注销侧挂或已转正工具 |
哲学:插件想长成什么样就能长成什么样——工具包 / 守护循环(timer+LLM 自主 agent loop)/ UI 面板 / 混合形态,同一注入通道;注入即完整生效(host+UI)、可热重载与自重载、卸载即净;插件自身的提示词/工具/循环皆可自我优化(改 → build → 重载闭环)。建新插件优先克隆/借鉴/重构生态已有资源(dsh-external 仓库、已注入插件、官方 packages 模式),不重复造轮子。
# 1. 生成骨架(toolkit / daemon-loop / ui-panel / hybrid)
# 对 AI 说:dev_scaffold_plugin {"dir": "D:/dev/my-plugin", "name": "my-plugin", "form": "daemon-loop", "description": "..."}
# 2. 构建打包(探测 DSH_CHECKOUT → tsc host → tsdown client(如声明)→ npm pack → tgz)
# 对 AI 说:dev_build_plugin {"dir": "D:/dev/my-plugin"}
# 3. 发布(gh release create v<version> + tgz)
# 对 AI 说:dev_release_plugin {"dir": "D:/dev/my-plugin", "version": "0.1.0"}
# 注入即活:dev_inject_plugin {"dir": "D:/dev/my-plugin"}
# 改代码 → build → 自动 watch ~1.5s 重载(或 dev_reload_package)
import type { Context } from 'cordis'
import type LlmService from '@deepseek-ai/dsh-llm'
import { createUserMessage, ReasoningEffortId } from '@deepseek-ai/dsh-llm'
type AppContext = Context & { llm: LlmService; setInterval(fn: () => void, ms: number): any }
export const name = 'my-daemon'
export const inject = ['timer', 'llm']
export function apply(ctx: AppContext): void {
let route: { provider: string; model: string } | null = null
ctx.on('llm/stream', (options, next) => { route = { provider: options.provider, model: options.model }; return next() })
ctx.setInterval(() => {
void (async () => {
if (!route) return
const stream = ctx.llm.stream({
provider: route.provider, model: route.model,
system: '判断是否需要人工介入,直接输出结论',
messages: [createUserMessage({ source: { kind: 'user' }, content: [{ type: 'text', text: '检查事项...' }] })],
reasoningEffort: ReasoningEffortId('off'), maxTokens: 200,
})
for await (const chunk of stream) { /* 决策 → 行动 */ }
})().catch(() => {})
}, 60_000)
}
规范铁律(注入器实测沉淀):
ctx.effect(工具/路由/监听)——热重载/卸载才能自动清理,否则僵尸残留(注入器自己踩过)>=0.0.1-rc <2、>=4.0.0-rc <5)——不硬编码版本,DSH 升级不报废dev_self_test,确保注入/重载/自重载/预检/卸载全链路不退化tool/call 后恢复全部——首轮请求结构决定整条会话的策略轨迹,锚定训练对齐的窄工具面再放开,能力不损。实现:system-prompt/assemble Waterfall 过滤器(骨架已自带,见 dev_scaffold_plugin)为什么:DeepSeek V4 Pro 的行为策略在首轮请求处被「完整 system prompt + 工具 schema 分布」强条件化。同题同环境:minimal(2 工具)99/96,standard(25 工具)91,两阶段锚定 98/99——先窄后宽,能力与完整工具面兼得。微探针证明起作用的是可调用的 schema 面(action space),不是看见工具名文本;工具目录只变化一次(首↔次请求之间有一次前缀缓存变化,首轮无缓存 prefill 最贵)。
怎么做(骨架自带,三步启用):
dev_scaffold_plugin 生成的 toolkit 骨架 apply() 末尾有注释好的锚定块;inject 数组加 'systemPrompt',把 MINE 换成你的工具名集合、CORE 换成首轮要保留的核心工具;验证:导出 session JSONL 看 request/header——第一份只含核心工具,首次工具调用后的下一份变更 header 含完整目录,此后保持。
| 机制 | 实测 | 落地 |
|---|---|---|
| 首轮锚定(窄工具面) | Project2 98/99 | tool-bootstrap 过滤器(骨架自带) |
| 近距离引导(用户消息后注入) | 零衰减(远距离同指令加速衰减) | 插件监听 session/event → inbox.append 固定引导 |
| 弱域内路由(模糊任务交模型自分类) | 区分度 +5~5.7,按模型选 persona | weak 模式(dev_router_mode weak) |
| deep-guide(分类+深度思考+commit) | 路由 96% + 收敛 100% + 反稀释 | 近距离固定引导文本 |
| 单任务三锚(回顾+收敛+反跑题) | 完成率 0%→100% | persona 静态锚 |
| plan-mode section 保留 | 失忆修复(v6) | applyPersona 只换 persona section |
完整实现与复现探针:dsh-router-standard(v0.1.0,含论文与 P1-P23 全数据)。
参考与致谢:本引导中的「首轮锚定」机制与统计证据,参考了 xiaobright 的开源工作——
dsh-anchored-standard(MIT,
两阶段锚定 preset 与 tool-bootstrap.mjs 实现,Project2 实测 98/99,首轮 2 工具 → 首次
工具调用后恢复 25 项完整 Standard 工具)与
modeltest(V4.1b 评测套件:同环境对照
minimal 99/96 vs standard 91 vs 两阶段 98/99、触发机制微探针、轨迹统计)。骨架中的锚定
实现即该 preset 过滤器的插件级移植(只裁剪本插件工具)。
装模组:拿到插件包(package.json + lib/ 产物)→ 对 AI 说 dev_inject_plugin(参数 = 插件包绝对路径)→ 当场生效(下一 step 工具可见)。
开发迭代:改代码 → build → 自动 watch 约 1.5 秒自动重载(或 dev_reload_package)→ 验证 → 稳定后 dev_stage_promote 一键转正。
卸载:dev_uninject_plugin(参数 = 包名子串)→ 工具/监听/路由/client 表全清,免重启。
~/.dsh/profiles/web/node_modules(loader 标准解析路径);ctx.loader.create({ name, config }) 运行时装配(完整 ctx);~/.dsh/super-injector/registry.json),重启后自动恢复注入;client-modules.processOne),浏览器端 bundle rev 联动更新。lib/ 里 import '@deepseek-ai/dsh-tools' 等从包自身 node_modules 解析——照 build.sh 建 junction 到 checkout 包(如 node_modules/@deepseek-ai/dsh-tools → <checkout>/packages/core/tools);bash scripts/build.sh(tsc),client 侧 npm run build:client(tsdown,产物 lib/client.js)——注入插件要出 UI 必须两步都构建;purgeCache 清理;ctx.effect:reloadPackage 重建失败若报 duplicate / already registered,说明资源是裸注册——挂 ctx.effect 后热重载才能正确清理重建;client-modules.processOne 对 entry.options.name 精确匹配,传短名会静默注册失败;仓库:https://github.com/yjh051108/dsh-super-injector Release:https://github.com/yjh051108/dsh-super-injector/releases