跳到主要内容
路径文档

启动与配置

一句话版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)
watchUserPatchesHMR:patch 变更时事务性重新组合

关键细节:

  • 内置模板只有 webheadless(自动初始化,默认挂 @deepseek-ai/dsh-base);tui 等需自建目录
  • initProfile 创建:目录 + package.json(含 dsh.profile.bundles)+ 空 cordis.patch.yml + pnpm-workspace.yaml
  • healProfilesModuleFallback 维护 $DSH_HOME/profiles/node_modules 扁平 symlink 兜底,让 out-of-tree 插件解析到同一个 cordis
  • 家目录级 cordis.patch.yml($DSH_HOME/cordis.patch.yml)越权于 per-profile 层

对应 插件解剖 的完整 patch 应用序。

四、Fail-loud 行为

$DSH_SNAPSHOT === 'replay' 时,resolveConfigPathcordis.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 层(无用户层)

renderConfigDump 用 Loader 自己的解析器离线合成,结果与真实启动一致:这是排查"哪层覆盖了什么"的权威工具。每行的 # == 注释标了它来自哪个层(base / web-app / 你的 profile)。

六、验证

dsh web --dump-config | head -30 # 看层叠结构与来源注释

下一步