课程总纲 / 阶段 1 · 理念
L04

核心理念一:一切皆插件

dsh 最重要的设计决策,以及它带来的三个直接好处。

预计阅读 20 分钟难度 ★★☆☆☆这是 L19 讲稿的第一张图

一、两种世界观Two Worldviews

传统框架:核心 + 扩展点

  • 特权核心塞满内置功能
  • 扩展 = 核心预留的"插座",位置数量固定
  • 想换内置功能?改核心源码,或祈祷它留了口子
  • 越成功越臃肿,"牵一发动全身"

dsh:一切皆插件(微内核)

  • 核心只剩最小调度机制
  • 连模型适配器、工具注册表、会话日志、agent 循环本身都是插件
  • 扩展 = 在别的插件旁边再挂一个你的插件
  • 任何部分都能从配置替换,没有谁动不得

传统框架像精装房:装修队留了几个插座,你只能在那儿插。dsh 像毛坯 + 标准化构件:墙都能拆,因为每面墙都是同样规格的挂件。

最有说服力的证据:驱动整个智能体的 agent-loop(循环本身)也是普通插件,挂在 packages/core/agent-loop/,可被配置替换——循环之上没有任何特权代码。

二、好处一:没有特权核心No Privileged Core

扩展 dsh 的方式永远只有一种:挂插件,不存在"内置的改不了"——换权限策略、换模型、换持久化后端,都是挂一个自己的插件。官方文档原话:"There is no privileged core to patch"——没有一个需要打补丁的特权核心

三、好处二:注册即效果Registration is an Effect

registrations are effects —— 一切注册都是"可撤销的效果"。

插件注册的每样东西——工具、事件监听器、提示词段落、定时器——都通过 ctx.effect()ctx.on() 安装,自动附带"卸载逻辑",卸载时按相反顺序干净消失。

export function apply(ctx: Context) {
  // 传统写法:注册了就收不回来,卸载后监听器还挂着(内存泄漏/重复触发)
  setInterval(heartbeat, 5000)

  // dsh 写法:卸载时 clearInterval 自动执行
  ctx.effect(() => {
    const timer = setInterval(heartbeat, 5000)
    return () => clearInterval(timer)  // ← 卸载时自动调用
  })
}

像酒店房卡:入住(注册)拿房卡,退房(卸载)房间自动恢复原状——不用挨个把家具搬回去。

四、好处三:热重载HMR

前两个好处叠加得到 HMR(热重载):改插件代码不用重启进程。

保存代码my-plugin.ts 改动
旧插件卸载注册全部自动撤销
新插件挂载重新注册
进程不重启会话状态不丢

别的框架很难做到——注册是"泼出去的水"(无撤销逻辑),卸载必留幽灵监听器;注册即效果让"拔插件"变安全,这是"一切皆插件"的隐藏红利。

五、配套纪律:改插件,不改循环Plugins, not Loop Changes

新行为挂在已有扩展点上(事件、服务),不改 agent-loop 本身。官方规定:改 agent-loop 必须同步更新架构文档——这条高门槛让循环保持极简稳定,复杂度全外移到插件层。写插件也一样:先找扩展点,找不到再考虑别的

这让 dsh 成为"反向依赖"系统:循环不知道插件的存在,插件却知道循环的一切扩展点——耦合方向决定可演化性。

微内核 microkernel
只保留最小调度核心、一切功能皆可插拔模块的架构。
注册即效果
每次注册自带撤销逻辑,卸载时逆序回收。
HMR 热重载
改代码不重启进程,插件自动换新。
扩展点 extension point
官方文档化的挂载位置:事件、服务、注册表。
✏️ 动手练习
  1. 打开 docs/architecture.zh.md 的"Where new behavior goes"表,挑 3 行没见过的机制抄下来(后续课程的地图)。
  2. 用"酒店房卡"和"精装房 vs 毛坯房"两个比喻,向自己复述"注册即效果"和"没有特权核心"。
📝 自测(点击展开答案)
1. "一切皆插件"最极端的证据?
agent-loop——驱动智能体的循环本身也是插件(packages/core/agent-loop/),可整体替换;循环之上没有特权代码。
2. 为什么 dsh 的 HMR 能干净工作?
注册即效果:所有注册经 ctx.effect()/ctx.on() 安装、自带撤销逻辑,卸载时逆序回收。传统框架注册无撤销路径,卸载必留残留。
3. 加新行为的正确思路顺序?
先查"Where new behavior goes"表找扩展点,做成插件挂上去;改 agent-loop 是最后手段(还触发架构文档更新义务)。
4. "耦合方向决定可演化性"指什么?
循环不 import 任何插件,插件却知道循环的全部扩展点;增删插件循环零改动,系统可无限演化。
权威出处:docs/architecture.zh.md(Cordis 节) · extension-cookbook.zh.md · cordis-primer.zh.md