跳到主内容

组合包 bundle 与 profile:两个 manifest

dsh.bundle 与 ~/.dsh/profiles/*.json 双 manifest 各管什么、如何隔离 web/tui/headless 三套工作区、profile 切换的边界。

约 7 分钟读完

读完这篇你会

  • 理解 DSH 的「组合包 + Profile」双 manifest 是怎么协同的
  • 知道一个 plugin 同时进多个 Profile 时会发生什么
  • dsh --profile X plugin add 隔离不同工作区的插件集合

适用版本

Compatible with: dsh 0.1.1-rc.2(基于官方 apps/cli/README + docs/user/develop/basic/ 整理)

两层 manifest 各管什么

DSH 用两层 manifest 表达「这个插件怎么被加载 + 这个 Profile 加载哪些插件」:

文件位置内容谁来读
dsh.bundle仓库根插件元数据(name / version / entry / services / patches)CLI 安装时一次性解析
~/.dsh/profiles/<name>.json用户工作区启用哪些 bundle + 加载顺序 + 启动参数Web/CLI 每次启动

这两层不互相替代:bundle 描述「这个仓库是 DSH 插件」,profile 描述「我今天要用哪些插件组合」。同一个 bundle 可以进多个 profile,每个 profile 加载同一份 bundle 时是独立副本(Cordis 的 dispose 机制),互不污染。

三个常见 Profile 配方

  • web(默认):跑 Web GUI,所有能进浏览器的插件都启用(视觉增强、上下文仪表盘、皮肤、桌宠)
  • tui:跑终端 UI(dsh-tianshu-tui / dsh-TUI),TUI 专属插件 + 不需要 GUI 的工具类
  • headless:纯 CLI 调用,没有 UI;只装最小依赖(搜索、记忆、上下文)

切换 profile:

dsh --profile web plugin add @liustack/modlens
dsh --profile tui plugin add @omdsh-dev/dsh-mnemon

两个 profile 各自维护插件列表,互不影响。

Profile 隔离的边界

  • 共享:模型 API Key、license cache、GitHub API token(全局配置)
  • 隔离:插件列表、enable/disable 状态、profile 级 config(如 cordis.services
  • 不共享:临时缓存(web 的 IndexedDB / tui 的 PTY 历史),profile 切换时各自保留

故障排查

  • 「装了 plugin 但 profile 里看不到」:多半是装到了别的 profile,用 dsh --profile X plugin ls 核对
  • 「profile 启动报错」dsh --profile X --dump-config 输出实际加载清单
  • 「两个 profile 互相串数据」:检查 ~/.dsh/profiles/ 下是否有同名 profile 互相覆盖;profile 名应是 kebab-case,不要带空格

FAQ

Profile 文件可以直接编辑吗?

可以,路径 ~/.dsh/profiles/<name>.json。CLI 也会写,但手改后再用 CLI 操作会自动覆盖——编辑前最好备份。

一个 bundle 能强制只在某个 profile 加载吗?

不能。bundle 本身不感知 profile;只能靠 CLI 调用时显式指定 profile,或者在 plugin 的 apply(ctx) 里运行时判断 ctx.config.profile。