组合包 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。