description: "面向 dsh profile 的插件管理:dsh plugin 命令与 Web 宿主共用的安装器,以及在已启动 profile 上启用、停用、重试、编辑用户层的行并报告每个包的管理器。"
English | 中文
dsh-plugin-manager 通过 CLI 与 Web 宿主安装包并管理它们声明的插件行。安装读取元信息,不执行模块。管理器启停整份组合包层,编辑全局或预设用户 patch,重试失败并报告当前运行问题。失败携带 plugins/* 错误码;Host 适配器 通过 Remote 暴露这些操作。
用 profile 目录、安装锚点(dsh 应用的 package.json)、一个回答 profile 已组合层列表的 loadProfile、工具边界、pnpm 输出的去处,以及是否让 pnpm 上色,构造 PluginInstaller,然后 add(spec) 或 remove(name):
import { loadProfile } from '@deepseek-ai/dsh-app-boot'
import { PluginInstaller } from '@deepseek-ai/dsh-plugin-manager'
declare const profileDir: string
declare const installAnchor: string
const installer = new PluginInstaller({
profileDir, profileName: 'web', installAnchor,
loadProfile: () => loadProfile('dsh', 'web', installAnchor, undefined, { userLayer: false }),
config: { pnpmCommand: 'pnpm', installTimeoutMs: 600_000, installLogTailBytes: 16_384 },
installLog: (chunk) => process.stdout.write(chunk.text),
color: process.stdout.isTTY,
})
const outcome = await installer.add('@acme/dsh-sql-tool')
console.log(outcome.installed, outcome.removed)
add 在 profile 中执行 pnpm,核对 dependencies,并按当前行归属静态检查新组合包声明。冲突组合包会被移除并给出原因;未声明或声明不可读的包保持已安装。新组合包保持禁用,除非调用方启用。pnpm 执行失败会恢复运行前的 manifest,并通过 plugins/install-failed 报告日志尾部。
在 Cordis 上下文之上构造 PluginManager,并交给它按调用读取所需之物的读取器——profile runtime、preset roster 的层、运行中的 agent 数——这样一个后来才有或始终没有其中之一的组合在调用时得到回答,而不是在挂载时:
import type { Context } from '@deepseek-ai/cordis'
import type {} from '@deepseek-ai/dsh-agent'
import type {} from '@deepseek-ai/dsh-agent-presets'
import type {} from '@deepseek-ai/dsh-app-boot'
import { PluginManager, type PluginToolingConfig } from '@deepseek-ai/dsh-plugin-manager'
declare const ctx: Context
declare const config: PluginToolingConfig
const manager = new PluginManager(ctx, {
config,
runtime: () => ctx.get('profileRuntime'),
presets: () => ctx.get('agentPresets'),
runningAgents: () => (ctx.get('agents')?.list() ?? []).filter(agent => agent.status === 'running').length,
})
console.log(await manager.list())
list 报告包身份、bundle / plugin / unknown 分类、trust、stage、安装与启用状态。运行行携带实际阶段与失败;禁用组合包显示静态 patch 声明。addable 只来自 dsh.plugins,包括表示主入口的 . 和声明的默认配置。行更新失败后,活跃实例可能保留先前配置。包的 issues 还报告其 patch 覆盖的失败行,但不转移这些行的归属。
enable 选择整份组合包层,并在实时 profile 中重组。逐行失败保留启用选择与成功的其他行;结果报告 issues,列表可显示 partial 或 failed。准备失败会撤销启用选择,并抛出 plugins/enable-failed。disable 移除整层,包括覆盖。retry 先禁用并等待清理,再启用。仅启动时生效的 profile 报告 effect: restart。uninstall 禁用组合包、删除用户插入的引用、执行 pnpm remove。
addRow 将显式声明的 dsh.plugins 模块写入 profile 的全局 cordis.patch.yml 或预设用户层。它保留声明的默认配置,检查目标行 id,不在挂载前 import。removeRow 删除用户插入。setRowDisabled 写入或删除 disabled: true,保留组合包自己的条件。全局编辑在实时 profile 中立即重组;预设编辑应用于后续代际。dependents 报告注入依赖方与用户层模块引用。
管理器一次只跑一个变更——上一个还在跑时再调用会以 plugins/busy 失败并点名正在进行的操作——add 与 uninstall 在有会话运行时拒绝改动 node_modules,报 plugins/agents-running。每次变更之后在上下文上发出 plugins/changed 事件,安装运行把 pnpm 的输出以 plugins/install-log 分块发出,每块都写明所跑的命令行与所在的 profile 目录,开了颜色时还带着 pnpm 的 SGR 转义。
每次拒绝或失败都是一个 PluginOperationError,带稳定的 code 与按码定型的 details:plugins/unavailable(没有 profile runtime,或 preset 目标没有 roster)、plugins/not-installed、plugins/not-enableable、plugins/enable-failed、plugins/install-failed、plugins/row-conflict、plugins/busy、plugins/agents-running,以及请求点名了 profile 没有的东西时的 plugins/bad-request。pluginOperationFailureOf 把捕获到的值收窄为按码区分的联合。
当管理器的契约还不够时读这些:它驱动的运行时、它编辑的文件,以及调用它的表面。
plugins Remote。dsh plugin 命令。无,插件管理不注册任何面向模型的东西;它组合出的行各自拥有自己做出的注册。
无;本包既不组装也不发送 provider 请求。
这些限制界定管理器不会为调用方做什么。它们是当前包的约束,不是任务清单。
add 做的 pnpm update 改写了文件,但运行中的树在进程重启前一直用旧模块。inject 边,因此 dependents 无法点名只读取该包所注册内容的行。engines.dsh 检查——该范围只被报告,不对运行中的 harness 版本强制执行。