启动与配置
审计基线 0.1.5-alpha.1 @ 5dda764ed3。
一句话版:
dsh的启动 =app-boot粘合层把「环境 → profile → bundle 层 → 你的 patch 层」组装成一颗配置树,Loader 装载、断言、激活,失败时 fail-loud(dsh:前缀退出)。
dsh web / dsh --profile <name> 都走同一个 boot。理解它,你就知道"改哪层生效、哪层覆盖哪层、配置树怎么查"。
一、启动流程(boot 粘合层)
二、分层环境变量
loadLayeredEnv 的优先级:
继承环境 > 项目 .env > 用户 .env
- 文件里的 bootstrap-only 变量会被拒绝
- 在不替换继承值的前提下物化文件值
三、Profile 机制
| 函数 | 职责 |
|---|---|
resolveProfileDir / initProfile | 定位 / 初始化 $DSH_HOME/profiles/<name> |
readProfileManifest | 读 profile 的 dsh.profile.bundles 列表 |
composeEntries | 把 bundle 层组合成条目 |
loadOptionalPatches | 解析 cordis.patch.yml(顶层 YAML:insert / 覆盖 / !!js) |
watchUserPatches | HMR:patch 变更时事务性重新组合 |
关键细节:
- 内置模板 5 个(首次使用时自动初始化);
tui等需自建目录
| 模板 | dsh.profile.bundles | patchReload |
|---|---|---|
acp | @deepseek-ai/dsh-base + @deepseek-ai/dsh-acp-app | startup |
web | @deepseek-ai/dsh-base + @deepseek-ai/dsh-web-app | live |
headless | @deepseek-ai/dsh-base + @deepseek-ai/dsh-headless | startup |
sdk | @deepseek-ai/dsh-base + @deepseek-ai/dsh-sdk-app | startup |
sdk-minimal | @deepseek-ai/dsh-sdk-minimal | startup |
- 不在上表的自建 profile 默认
patchReload: live;dsh --profile <新名> --from-default-profile <模板>可从模板复制一份新 profile initProfile创建:目录 +package.json(含dsh.profile.bundles与patchReload)+ 注释模板的cordis.patch.yml+pnpm-workspace.yaml(nodeLinker: hoisted)healProfilesModuleFallback维护$DSH_HOME/profiles/node_modules的安装依赖闭包兜底(普通 Node 用 symlink,打包可执行文件用 ESM proxy),让 out-of-tree 插件解析到同一个 cordis;bundle 私有依赖再经 profile 自己的node_modules链接- 家目录级
cordis.patch.yml($DSH_HOME/cordis.patch.yml)越权于 per-profile 层;应用序为 bundle 层 → profile patch → 家目录 patch →--patchoverlay → 遥测开关
对应 插件解剖 的完整 patch 应用序。
四、Fail-loud 行为
当 $DSH_SNAPSHOT === 'replay' 时,resolveConfigPath 把 cordis.yml 换成 cordis.snapshot.yml(快照重放)。加载失败时:
$ dsh web # 插件解析失败时
dsh: plugin tree failed to load: ...
# 或
dsh: fatal load failure: <Error stack>
# 标签前缀固定 dsh:,进程 exit(1),绝不带病运行
两个断言函数的区别:
| 断言 | 检查什么 |
|---|---|
assertEntriesLoaded | 树结算后存在已启用但没有 fiber 的条目 → 抛错 |
assertEntriesActivated | 再等每个已启用配置项激活;错误带原始堆栈 |
五、配置查看:--dump-config
dsh web --dump-config # 渲染当前组合树(带 # == 层来源注释)
dsh web --dump-default-config # 只渲染 bundle 层(不含用户层,也不含 --patch overlay)
dsh web --patch ./extra.yml # 临时叠加一层 patch(可重复,应用在 profile 层之后)
--dump-default-config 是"用户层写坏了"时的恢复诊断:它不解析 cordis.patch.yml。renderConfigDump 用 Loader 自己的解析器离线合成,结果与真实启动一致:这是排查"哪层覆盖了什么"的权威工具。每行的 # == 注释标了它来自哪个层(base / web-app / 你的 profile / --patch 文件)。
六、验证
dsh web --dump-config | head -30 # 看层叠结构与来源注释