dsh-web-plugin-manager 功能参考(工作区文档)
August 15, 2026 · View on GitHub
README 只保留功能速览;本文件存放功能与限制的细致说明,供开发与排障查阅。
查看
- 四源合并:include 树稳定行(
EntryOptions.id,官方语义稳定,Loader 挂载 id 每次随机,patch 定位必须用它)+dsh.profile.bundles层栈 +package.json依赖 +cordis.patch.ymlinsert 行 - 非运行 profile 显示离线合成条目(官方 in-box 包 base/web-app/headless 不标记为已安装)
- 已安装但未挂载的依赖:官方 CLI/pnpm 手动安装的非 bundle 插件只写依赖、不写挂载行(从未被加载)——list() 合成为
unmounted条目,目录页显示「未挂载」标签与「挂载」按钮,一键补写 managed insert 行(运行中 profile 实时生效)
实时启停
- 受控编辑 profile 的
cordis.patch.yml:# dsh-plugin-manager:managed:start/end标记块,行级操作、原子写入(tmp + rename),保留用户内容,可逆可审阅 - 变更先经 loader include 条目直接应用(
entry.update,与平台 watchUserPatches 同通道)再写文件——绕开平台 watcher 死锁(HMR 卸载等待自身 disposables 循环等待),实时生效、零重启 - 插件自有的 patch 文件 watcher:手动编辑持续实时生效,不依赖 HMR 生命周期
- 5s 超时兜底;跨 profile 隔离(仅作用于运行中宿主 profile)
- 随机行(无显式 id 的挂载行)不可经此启停——id 每次挂载变化
安装
- 调用官方
dsh pluginCLI(pnpm reconcile),保护 in-box bundles(base/web-app/headless 从dsh.profile.bundles恢复) - 非 bundle 插件自动写 managed insert 行并实时挂载;bundle 插件进入层栈,重启后加载
- git 源自动 clone 进
$DSH_HOME/plugin-manager-src缓存;已发布 npm 的包优先走 npm 安装(npm-first) - 安装即质量门(见下),任何问题自动回滚,profile 保持可启动
- 行 id 冲突预检:slugify 后的行 id 与既有行(insert 行同名不同包、用户顶层行)冲突时拒绝安装并回滚——避免 loader 拒绝整棵树
质量门(安装时)
- 扫描整条加载链(入口 + 相对 import 可达文件,BFS 有界)的 import,对照声明依赖 + 平台白名单
- 白名单:
@deepseek-ai/dsh-client-*/cordis-plugin-*前缀族 + cordis / react 等 loader 提供项 - 覆盖副作用导入、re-export、动态 import、minified 形态;
import type不误报 - 声明了但未安装的依赖同样拦截;bundle 插件
cordis.patch.yml行名逐一校验 - 官方包只能 peerDependencies:普通
dependencies命中安装兜底闭包的@deepseek-ai/*一律拦截回滚——普通依赖会在 profile 内装出第二份官方拷贝,loader 最近优先解析劫持官方行,模块身份(unique symbol/class)分裂导致Cannot read properties of undefined (reading 'prepare')类运行时故障;写peerDependencies即可(autoInstallPeers: false下经共享兜底目录解析,全 profile 共享一份)
更新
- npm 包对比 registry dist-tag
latest;git 缓存源(link: 路径是 git 仓库)git fetch对比远端 HEAD(@{u} 回退 FETCH_HEAD);git URL 源ls-remote对比安装 commit(gitHead) - 可更新卡片淡绿边框,更新按钮在删除左侧(仅检测到更新可点),详情显示当前/最新版本
- 更新动作:npm
@latest重装 / git 缓存 fetch+reset 后重跑官方 add / git URL 源重解析,均带质量门与回滚 - 边界:本地目录安装(非 git)无上游可比,报告"不可检测";git URL 源需要 manifest 记录安装 commit(gitHead)
健康检查(src/analyze.ts,离线引擎)
- 依赖图:全包 entry imports → providers(含 pnpm symlink、exports 子路径)→ 包间依赖边;拓扑排序输出(加载顺序提示,cordis 激活本身是服务可用性驱动)
- 缺失依赖(imports 无提供者且未声明)、被禁用依赖、循环依赖(DFS)、重复 patch 行 id
- 同名注册冲突(确定性 fail-loud 故障):服务名(new Service/ctx.provide)、工具名(ctx.tools.register)、prompt section 名(ctx.systemPrompt.section)、web 路由路径(ctx.webServer.register)——源码正则扫描,动态注册(字符串拼接的名字)检测不到
- peerDependencies 版本满足性(简化 semver:
^/~/>=/<=/>/</精确/星号),含经共享 fallback 解析的官方核心包 - 官方包重复安装(official-duplicate):
@deepseek-ai/*同时存在于 profile node_modules 与安装兜底目录 → 报肇事插件(哪个依赖引入的)与修复指引 - 运行时诊断(宿主):pending 注入根因(静态 inject 声明 vs 活跃服务表)、fiber 加载失败原因(
_error) - 作用效果冲突(语义冲突)不在静态检测范围:两个插件做相反的事(互相矛盾的 prompt 指导、竞争同一事件流)没有同名可查,只能靠运行时观察尽力而为
环境管理
- 设置 → 插件 → 环境:启动/停止(终端或后台)、复制/转移插件(按记录源重装)、创建/重命名/删除 profile
- 官方 profile(web/headless)只读,不可管理
市场
- 数据源:awesome-dsh-plugins 结构化 catalog(catalog/plugins/*.json + tombstones)+ PLUGINS.md 双源合并,互补不互斥;GitHub API 补星数/更新时间;24h 缓存,空结果不写正缓存
- 已安装条目按 npm 包名 / manifest repository / git 缓存源 owner-repo 三重匹配显示「已安装」徽标并禁用安装按钮
- 网络健壮性:每请求 15s 超时(AbortSignal.timeout);支持
HTTP_PROXY/HTTPS_PROXY/NO_PROXY(undici ProxyAgent——Node 全局 fetch 会丢弃 dispatcher 选项,市场请求必须走 undici 自身 fetch);失败原因负缓存 5 分钟(marketplace-failure.json,避免每次进页重跑全量 GitHub 往返);双源全挂且无缓存时空列表直接显示失败原因 - GitHub API 未认证限流 60/h:403/429 停止富化(星数降级用上次快照元数据),列表本身不受影响;raw 兜底源可达时列表保持非空
- 系统代理/规则模式加速器对 Node 进程无效(undici 不读系统代理)——市场为空且此类加速器用户,把代理地址写进环境变量,或改 TUN/全局模式
agent 工具与安装守卫
plugin_status/plugin_install/plugin_uninstall/plugin_toggle(目标 profile 由配置profile指定,默认web);依赖注入避免循环导入- 安装守卫(
src/guard.ts):tools.guard拒绝 bash/run_code 中裸dsh plugin add/remove/update与指向 profile 目录的pnpm add/remove(只读 verb list/status/dump-config/help 放行),拒绝原因直接给模型指路plugin_*工具与dshpm;systemPrompt.section(order 300)常驻提示同一规则 - 守卫只拦 agent 工具调用,拦不住用户在终端手工执行裸命令
CLI(dshpm)
- bin 随插件安装进入 profile 的 node_modules;也可
node <profile>/node_modules/dsh-web-plugin-manager/dist/cli.js直接调用;--home指定 DSH_HOME - 所有变更走与 Web UI 完全相同的受保护链路:pnpm add/remove(官方 CLI)→ 质量门 → 自动回滚 → 安装后分析 → insert 行维护;ctx 可空:无宿主进程时跳过 live 应用,文件级操作与 Web UI 一致
- 命令:
dshpm install <source>:npm 名 / github:user/repo / git URL / tarball / 本地路径dshpm remove <name>:insert 行 + 包依赖一并清理(含 node_modules)dshpm mount <name>:补挂载官方 CLI 手动安装的未挂载依赖dshpm list:bundle 层栈 / 已装包 / insert 行dshpm analyze:健康检查全文输出,有问题退出码 1
架构模块
- Host:
src/index.ts——PluginManagerService(ctx.pluginManager)+/api2/plugin-manager/*REST(webServer.register) - 实时应用:
src/live.ts;分析引擎:src/analyze.ts(与质量门共享扫描器,永不漂移);Patch 编辑:src/patch.ts(YAML 陷阱:@包名引号、空数组文档[]、纯注释文件恢复模板);网络助手:src/net.ts(超时 + 代理);Agent 工具:src/tools.ts;守卫与提示:src/guard.ts;CLI:src/cli.ts - Client:
src/client/——settings.plugins.tab(all 遮蔽官方只读列表 + manager + environments)+settings.section(marketplace);同源 fetch 调 REST(不走 Typert Remote)
已知限制明细
- 禁用被依赖的条目可能导致 profile 启动失败(官方 fail-loud 设计);恢复:手动编辑该 profile 的
cordis.patch.yml删除 managed 块 - 安装来自 git 的 bundle 需要用户在终端放行
pnpm allowBuilds(命令输出会回显) - git 子包安装:多包仓库用
#路径:<dir>约定指定子目录(#ref是 git ref) - 质量门可能误伤:未声明运行时依赖的插件会被拦截回滚(保守策略);若插件确实由 Loader/host 提供该模块,需在 manifest 声明或加入白名单
- 市场条目来源于 awesome 目录,个别仓库可能已删除/私有(安装时报
Repository not found) - nvm 用户注意:子进程命令(dsh/npm/pnpm/git)解析按「运行中 node 目录 → PATH → $NVM_DIR」兜底,并把命中的工具目录注入子进程与终端窗口的 PATH——宿主进程不在 nvm 激活的 shell 中启动(桌面启动器/服务/nohup)也能工作;仅当 dsh 完全未安装时才需要从 nvm 激活的终端启动