组合与热重载(HMR):导入新模块,回卷旧 Fiber,再激活替换
理解稳定 id、配置组和 Cordis HMR 的卸载—重载流程,并学会定位始终停在 PENDING 的插件。
HMR 的真实流程:保存文件 → 导入替换模块 → 旧插件卸载并回卷 effect → 注册替换 → 依赖满足后激活。
如果只把 HMR 理解成“重新 import”,就会漏掉最重要的部分:旧实例必须先失去所有运行时副作用。
01 / 配置项是可比较的运行时节点
配置项可以带稳定身份:
- id: logger
name: '@deepseek-ai/cordis-plugin-logger-console'
- id: timer
name: '@deepseek-ai/cordis-plugin-timer'
- id: hmr
name: '@deepseek-ai/cordis-plugin-hmr'
config:
root: ['.']
- id: hello
name: './hello.ts'id 让 Loader 在 cordis.yml 改动后区分保留、卸载和重新配置的行。没有 id 的行每次读取都可能得到新身份,从而被当作先删后加。
group 可以让一组配置作为单元装卸,isolate 可以让组拥有独立的服务实例。
这个 HMR 示例还依赖 timer 服务,并需要 Node 的 loader 内部接口;它是服务端 Node HMR,不等同于浏览器端的 client-plugin HMR。
02 / HMR 先导入替换,再卸载旧实例
@deepseek-ai/cordis-plugin-hmr 监视文件变化:
- 文件保存后,HMR 判断变化属于配置、插件模块还是框架外部文件。
- 对于插件模块变化,HMR 先导入替换模块。
- 需要重载的旧 runtime 被卸载,所有 effect 先回卷。
- 替换模块随后注册并运行
apply。 - 如果它依赖的服务尚未就绪,新 Fiber 会停在
PENDING,而不是半启动。
外部或框架文件不是单个插件的重载单位;这类变化会让 Loader 退出,由宿主重新启动。
因此修改 hello.ts 可以看到旧输出停止,新输出出现;修改配置则由 Loader 按 id 进行局部更新。
03 / 为什么 HMR 也可能“没反应”
有两类问题要分开:
- 路径或包名拼写错误属于解析问题,先检查
name和日志。 - 依赖没有 provider 时属于合法的
PENDING,插件不会输出,也不会抛异常。
可以通过注册表观察 Pending Fiber:
import { FiberState } from '@deepseek-ai/cordis'
for (const runtime of ctx.registry.values()) {
for (const fiber of runtime.fibers) {
if (fiber.state === FiberState.PENDING) {
console.log(fiber.name + ' is PENDING')
}
}
}04 / HMR 的安全边界
HMR 只能可靠地撤销已经注册为 effect 的资源。事件监听器、服务注册和子插件由 Cordis 管理;自建定时器、连接和 watcher 必须在 ctx.effect() 中返回 disposer。
如果资源逃离 Fiber,重复保存文件就可能留下重复监听器或旧连接。所谓“热重载安全”,首先是所有权清晰,其次才是 watcher 是否能检测到文件。
05 / DSH 为什么把 HMR 放进基础组合
dsh-base 的配置中包含 timer 与 HMR 插件,profile 在此基础上继续叠加模型、工具、会话和 Agent 能力。修改插件时,运行中的 dsh 可以沿用同一套卸载—重载语义,而不是为每个能力写一套刷新逻辑。
headless 和 web overlay 会禁用服务器 HMR;浏览器端的 client-plugin HMR 是独立链路,不能用这套 Node watcher 的行为推断它。
下一步
更多文章
生命周期与 effect:让 Cordis 注册可以回卷
跟随 Fiber 从 PENDING 到 DISPOSED,理解 effect、disposer 与 HMR 如何共同管理插件副作用。
inject:让依赖决定加载顺序,而不是 YAML 行号
理解 Cordis 的 PENDING、依赖跟踪和可选服务探测,解释为什么 provider 更换会自动带动 consumer。
Cordis 在 DeepSeek Harness 里:一切皆插件如何落地
从 dsh-base、Context 服务、事件域和工具流水线出发,理解 Cordis 如何组织一个可替换的 Agent 运行时。
邮件列表
加入我们的社区
订阅邮件列表,及时获取最新消息和更新