description: "面向已启动 profile 的插件管理:pluginManager 服务与 plugins Remote,负责安装、启用、停用与重试组合包、编辑用户层的行,并报告每个包的状态。"
English | 中文
dsh-host-plugin-manager 是改变一个运行中 profile 由什么组成的唯一地方。profile launcher 从组合包层与用户补丁文件组合出宿主树,并经 profileRuntime 在运行中重新组合;本服务驱动这一切:在 profile 目录运行 pnpm 安装或移除包,把组合包移入或移出 profile 的层列表并以结果重新组合树,在组合包的行启动失败时重新组合它,向 profile 的全局用户层或某个 agent preset 的用户层添加与移除行,并把 manifest、探针记录与在线树折叠成每个包一份视图。plugins Remote 暴露每一项操作;每次变更之后发出 plugins/changed 事件,安装运行把 pnpm 的输出以 plugins/install-log 流式发出。客户端包通过 api-remotes 装配消费该 Remote。
把这一行挂在宿主组合里插件清单旁边;web 组合包已经这么做了。该行只注入 Loader,并在每次调用时解析 profile runtime,因此不经 profile launcher 启动的组合仍能启动,只是每次调用都回答 plugins/unavailable。
plugins/list 为 profile 知道的每个包返回一份视图:模板组合包与已安装的组合包,以及其他每个已安装的依赖。视图携带 manifest 事实(名字、版本、标题、描述、engines.dsh),这个包是什么(bundle、plugin 或 library),谁提供它(builtin 或 external),它的行何时挂载(boot 或 runtime),是否已安装与已启用,以及折叠出的 status:已启用的组合包按活跃行的多少是 running、partial 或 failed;已安装但不在层列表中的组合包是 disabled;探针拒绝时是 not-enableable 并附原因;在启动时才应用变更的 profile 上 manifest 与在线树不一致时是 restart-required;库或插件模块是 plain,它们被添加进组合而不是被启用。组合包已组合时行来自在线树——阶段、被谁停用,以及隔离行记录的失败——否则来自探针记录,id 保持各自 patch 声明的样子。addable 列出包在 dsh.plugins 里声明的模块,各自带默认配置与探针的判定。
plugins/install 接受一个 pnpm spec——registry 名字、github: 或 git URL、tarball、绝对路径——在 profile 目录运行 pnpm add,记录 pnpm 写进 dependencies 的内容,在子进程里探测每个新包,并让新组合包保持停用,除非调用方要求 enable。pnpm 的输出以带本次 jobId 的 plugins/install-log 分块到达;最后一块携带退出码。非零退出、spawn 失败或超时都以 plugins/install-failed 与日志尾部让调用失败,并把 profile manifest 恢复到运行前的样子。pnpm add 成功还不等于装好了插件:新包既不声明组合包也不声明插件模块,或者是某个行 id 已被已组合层占有的组合包,会再以 pnpm remove 移除并连同原因列在 removed 里;探针拒绝的包保留在原处,由视图说明它为何不能启用。管理器一次只跑一个变更——上一个还在跑时再调用会以 plugins/busy 失败并点名正在进行的操作——并且在有会话运行时拒绝改动 node_modules,报 plugins/agents-running。
plugins/enable 把已安装的组合包放进层列表,并在 live profile 上经 profile runtime 带着它重新组合树。这次重新组合就是 Loader 自己的事务:树拒绝的组合包——boot 阶段而行抛错的组合包——回滚,层列表恢复,调用以点名原因的 plugins/enable-failed 失败,而原本运行的树继续运行。runtime 阶段而行失败的组合包则被隔离:调用成功,视图报告该行的失败,plugins/retry 从头重新组合它。plugins/disable 是反向操作;模板组合包不是依赖,无法停用。在 patchReload 为 startup 的 profile 上,两者只写 manifest 并报告 effect: 'restart'。
plugins/uninstall 在组合包已启用时先停用它,删除每一条点名该包模块的用户层行,运行 pnpm remove,并忘掉探针记录。与 install 一样,它等待运行中的会话:只要有 agent 在运行就报 plugins/agents-running。
plugins/addRow 把一条点名该包某个模块的行——plugin 包的主导出,或某个 dsh.plugins 条目——插入 profile 的全局 cordis.patch.yml(target: { kind: 'global' })或某个 agent preset 的用户层({ kind: 'preset', preset },经 roster 的 overlayPathFor)。行 id 未给出时由包名与子路径派生;已被占用的 id 以 plugins/row-conflict 失败。plugins/removeRow 移除一条插入的行,plugins/setRowDisabled 为任意行写入或移除 disabled: true——只写拒绝,因此组合包自己的 !!js 门被恢复而不是被覆盖。全局层当场在线重新组合;preset 的层在其下一个常驻代际生效。
plugins/dependents 说明停用或移除一个包会搁浅什么:其行提供而包外的行注入的服务,以及点名其模块的用户层行。
| 字段 | 默认值 | 含义 |
|---|---|---|
pnpmCommand |
pnpm |
可执行文件,与 dsh plugin 命令一样经 PATH 解析。 |
installTimeoutMs |
600000 |
单次安装或移除运行的上限。 |
probeTimeoutMs |
20000 |
单次包探测的上限。 |
installLogTailBytes |
16384 |
安装失败时报告多少尾部输出。 |
当管理器的契约还不够时读这些:它驱动的运行时、它编辑的文件,以及渲染它的界面。
无,宿主侧的插件管理器不注册任何面向模型的东西;它组合出的行各自拥有自己做出的注册。
无;本包既不组装也不发送 provider 请求。
这些限制界定管理器不会为客户端做什么。它们是当前包的约束,不是任务清单。
install 做的 pnpm update 改写了文件,但运行中的树在进程重启前一直用旧模块。inject 边,因此 dependents 无法点名只读取该包所注册内容的行。engines.dsh 检查——该范围只被报告,不对运行中的 harness 版本强制执行。