先给结论:DeepSeek Harness(DSH)那句「一切皆插件」,不是口号,而是一个有十年积累、有论文、有形式化证明的
插件运行时 撑起来的。这个运行时叫 Cordis,DSH 把它以「vendor」的方式(源码级拷贝)嵌进仓库,
改名成 @deepseek-ai/cordis,版本 4.0.0-rc.7。它要解决的是插件系统里一个最反直觉的难题——
「加载」容易,「卸载」才是地狱:绝大多数插件框架能让插件挂上功能,却没法在不重启宿主的情况下把它干干净净地摘掉。
Cordis 用两个概念回答了这个问题,而这两个概念,正好对应了任务里那句「可逆效应」与「反应式余效应」。
本文所有事实截至 2026 年 8 月 14 日,以 DSH 官方仓库(deepseek-ai/deepseek-harness)的
docs/cordis-primer.md、docs/architecture.md、四个 preset 的配置文件与 Cordis 论文为准。
先说清本文的事实纪律,因为它直接决定「哪些是白纸黑字、哪些只能算推断」。这一篇里:
已确认(仓库原文)的,是 Cordis 的五个核心概念、effect/disposer/fiber 的生命周期语义、DSH 的
profile/bundle/patch 分层、核心包的 ctx 键、四个 preset 的 preset.yml 与
agent.cordis.yml 逐行内容;来自论文但需说明口径的,是「可逆效应 / 反应式余效应」这组术语的
精确定义(它们出自《A Programming Paradigm for Spatiotemporal Composability》这篇预印本,由北京大学与 DeepSeek-AI Harness
团队合作,草稿日期 2026 年 8 月 13 日,约 88 页);明确标注存疑的,会在正文里点名。
本站一贯的写法是:宁可写「存疑」,也不为了顺口而编一个看起来很专业的细节。
目录
一、为什么「一切皆插件」值得再往下一层
上一篇文章里,我们给「一切皆插件」下的定义是:DSH 里模型适配器、工具注册表、会话日志、沙箱、存储、调度、UI、甚至 agent loop 本身,全都是挂在 Cordis 上的插件,扩展它的方式不是改源码,而是「把新插件挂到别的插件旁边」。这个判断是对的,但它只回答了 「是什么」,没回答「凭什么」。一个很自然的追问是:凭什么插件可以互相替换、可以热拔插、可以按依赖自动排序? 如果只是「把代码拆成一堆模块然后逐个 require」,那它跟十年前就有的插件系统没有任何区别,DeepSeek 也没必要把 Cordis 单独拎出来强调。
答案在于,Cordis 提供的不是「模块化」,而是 「可组合性(composability)」——而且是分两个正交维度的: 时间维(一个组件被拔掉之后,它留下的所有痕迹都能被精确撤销)与 空间维(一个组件缺它依赖的东西时, 会安静地停着,等依赖就绪才活过来)。把这两个维度做扎实,DSH 才敢让「模型」这种东西也变成一个可替换插件——你可以在同一套会话、工具、 权限体系里换掉模型适配器,而不用重启、不用重建上下文。这是它和 Claude Code / Codex 那种「模型与产品垂直整合」路线最本质的分野。
二、Cordis 是什么:血统、论文与「被 vendor 进 DSH」
先纠正一个可能的误读:Cordis 不是 DeepSeek 为了 DSH 临时造的轮子。它的作者是 shigma,即开源跨平台聊天机器人框架 Koishi(名字取自东方 Project 角色,GitHub 约 6000 Star)的作者。Cordis 作为 Koishi 的底层已经 在生产环境跑了约四年,被 4000 多个社区插件在真实场景里反复验证过;Koishi 跑的是 Cordis v3,而 DSH 这次开发者预览 用的是 Cordis v4,恰恰和那篇论文同一天公开。换句话说,DeepSeek 选它,是选了一个「被真实用户群殴过四年」的框架, 而不是实验室里的一个 prototype——这一点官方和论文都反复强调,作为「Cordis 久经考验」的证据。
那篇论文叫 A Programming Paradigm for Spatiotemporal Composability(《一套处理时空可组合性的编程范式》)。它要回答的核心 问题是:现代插件系统大多「不能真正拔插件」。论文里点名了 VSCode——插件市场排名前 100 的扩展里,有 87 个包含无法在 运行时单独卸载、必须重启扩展宿主的可执行代码。对一个「自进化」的 AI agent harness 来说,这个痛点被放大了:agent 可能会在运行时自己 生成、安装、替换它自己的工具,而重启会毁掉已经积累的上下文与缓存。Cordis 就是冲这个来的。
再看 DSH 是怎么「拿到」Cordis 的——这点很能说明 DeepSeek 的态度。DSH 没有通过 npm 依赖 Cordis,而是把 Cordis 及其基础库
(cosmokit、schemastery、loader、include、group、timer、hmr 等)源码级 vendor 进自己的 monorepo,统一改名到
@deepseek-ai 作用域(cordis → @deepseek-ai/cordis,@cordisjs/plugin-* →
@deepseek-ai/cordis-plugin-*)。官方的理由写得很直白:「让 harness 完全拥有自己的框架层——可审计、可打补丁、可锁定版本」。
vendor 目录里还维护了一份「本地修改日志」,逐条记录了它对上游 Cordis 做了什么改动,例如对 fiber 生命周期做了三处「重入式卸载」的加固、
让 Loader/Include 的配置热更新变成事务性的。这层「连框架层都要攥在自己手里」的姿态,跟 DeepSeek 一贯「先自己跑起来再外发」的风格是一致的。
三、Cordis 的五个核心概念
Cordis 官方 primer(docs/cordis-primer.md)把它的设计浓缩成五句话。这五句话是理解后面所有机制的地基,值得逐条展开,
因为它们分别对应了「怎么装」「怎么找」「怎么等」「怎么喊」「怎么撤」五个动作。
- 插件是实现 Service 的对象。它可以是一个带可选
inject和apply(ctx)字段的函数, 也可以是一个Service子类,其生命周期由 Cordis 挂载进当前上下文。注意「对象/函数」这个形态——它没有规定插件必须继承什么基类, 所以一个插件既可以是 YAML 配置里的一行,也可以是代码里随手写的一个函数。 - 上下文(Context)是服务的容器。一个服务占据一个稳定的
ctx.<key>槽位,比如ctx.tools、ctx.llm、ctx.sessions;其他插件通过 key 去找服务,而不是 import 某个具体实现。 这正是「模型可替换」的根基——消费方只知道「有个ctx.llm」,不知道也不在乎它背后是 DeepSeek 还是 OpenAI。 - 通过
inject声明服务依赖。一个插件声明自己需要哪些服务后,会一直等到这些服务就绪才启动。 于是「加载顺序」这件事不再靠人肉编排启动序列,而是靠依赖关系自己表达出来。这条直接通往第四节要讲的「反应式余效应」。 - 类型化事件用于通信。服务通过 TypeScript 的声明合并(declaration merging)注册事件名,然后以
emit(观察)、waterfall(包装/瀑布式)、parallel(并行扇出)、serial(按序) 四种模式分发。事件是扩展点,也是 DSH「事件就是扩展点」这句话的技术来源。 - 注册是可逆的副作用(reversible effects)。提示词片段、工具 schema、适配器、提供方、监听器,都通过
ctx.effect()或ctx.on()安装,reload 和 teardown 时会按预期撤销。这一条是整个框架的「灵魂」, 下面两节专门拆它。
四、两个关键术语:可逆效应 与 反应式余效应
这里要做一个术语纠偏——因为这两个词在中文语境里很容易被译得似是而非,而它们恰恰是 Cordis 论文最核心的贡献。任务里写的 「可逆效应与反应式余效应」,对应到论文的英文原词,分别是:
| 中文 | 英文原词 | 解决的问题 |
|---|---|---|
| 可逆效应 | Revertible Effects | 时间维可组合性(Temporal Composability) |
| 反应式余效应 | Reactive Coeffects | 空间维可组合性(Spatial Composability) |
先说 可逆效应(Revertible Effects)。论文把它定义得很严格:每一次对上下文的变换,都必须携带一个 显式的逆函数(inverse),由运行时跟踪;卸载一个插件时,运行时按注册顺序的逆序执行这条 「撤销链(undo chain)」,把系统精确恢复到它加载之前的状态。用代码里更接地气的话说,就是每个注册都要返回一个 disposer(资源释放函数),框架在卸载时替你把它跑一遍。注意「可逆」这个词不是修辞——它是论文给出的、有操作语义支撑的 承诺:系统状态是「加载/卸载顺序无关」的(论文证明了 confluence 性质,即最终状态不依赖加载卸载的先后)。
再来看更有意思的 反应式余效应(Reactive Coeffects)。这里最容易翻错:它不是「reactive effects(反应式效应)」,
而是 coeffect(余效应/协效应)——类型论里「effect system(效应系统)」的对偶概念。效应系统关心「这段代码会产生什么副作用」,
而 coeffect 系统关心的是反过来的那一面:「这段代码需要从环境里得到什么」。映射到 Cordis:一个组件声明它所需的依赖
(比如一个聊天插件需要「消息适配器」和「数据库」),在依赖全部满足之前,它保持 INACTIVE(未激活) 状态;一旦依赖就绪,
它的生命周期(activate / deactivate / neutral)就由环境变化来反应式地驱动。这就是「反应式」三个字的来历,也是第四节里
inject 声明的理论基础。
论文的巧思在于,它把这两个原本分属两套理论的东西,统一进同一个 「上下文类型(context type)」,形成所谓的 「上下文范式(context paradigm)」。整篇论文给出一套 10 条规则的操作语义,并证明了四条元性质:保真(preservation)、全局时空可组合性、 进展(progress)与合流(confluence)。对这些术语,本文只做转述,不做二次演绎——它们属于那篇 88 页预印本的形式化部分,普通读者只需记住 一句话:Cordis 是「卸载可彻底撤销」与「依赖就绪才激活」这两件事同时成立的一套机制。
五、Effect 的机械细节:disposer、fiber 与逆序释放
落到代码层面,这套理论长什么样?Cordis 官方教程第 2 章(docs/cordis-tutorial/02-lifecycle-and-effects.md)给了最直白的
回答:一个插件可能因为「改配置、热重载、显式释放、或所需服务消失」而被卸载;凡是通过 Cordis API 建立的注册,都是 effect,
会在所属插件卸载时被撤销;而那些 Cordis 管不到的资源(定时器、连接、文件 watcher),你必须自己用 ctx.effect() 包起来,
并返回一个 disposer。核心代码长这样:
ctx.effect(() => {
const timer = setInterval(() => console.log('tick'), 200)
return () => { // ← 这就是 disposer
clearInterval(timer)
console.log('cleaned up')
}
})
这段代码揭示了 effect 模型的两个关键动作:effect 主体在加载期间运行,它返回的 disposer 在卸载期间运行;对于生命周期与
插件一致的资源,你永远不需要自己调用 disposer——框架会在卸载时替你跑。而且,内置的注册 API 本身就已经是 effect 了:
ctx.on(event, listener) 的监听器会在卸载时自动移除,ctx.plugin(child) 的子插件会随父插件一起释放,
服务注册(比如 ctx.tools.register(...))返回的 disposer 也会自动挂到调用插件身上。所以真正需要你手写 ctx.effect()
的场景,其实很少——大多数时候你只是「注册」,撤销是免费的。
这里藏着一个容易踩坑的顺序细节,官方专门用黑体强调过:disposer 按注册顺序的逆序启动,但多个异步 disposer 会并发运行。 如果你的拆除步骤必须严格按顺序执行,就得把它们放进同一个 disposer,在里面逐个 await。这条规则背后是「撤销链」的语义: 后注册的先拆,像叠起来的一摞盘子,从最上面开始拿——这也正是「可逆」在工程上的落点。
再往下,是 fiber 这个概念。每一个已加载的插件实例都拥有一个 fiber(运行时句柄),它在下面这个状态机里流转:
PENDING → LOADING → ACTIVE → UNLOADING → DISPOSED
↘ FAILED - PENDING:已声明,但它
inject的服务还没就绪——这就是「反应式余效应」在运行时最直观的表现:插件在等依赖。 - LOADING / ACTIVE:
apply正在跑 / 已经跑完。 - FAILED:
apply或配置校验抛了异常。 - UNLOADING / DISPOSED:disposer 正在跑 / 一切已拆除。
官方教程还点了一句很实用的诊断经验:如果你发现某个插件「没输出」,答案十有八九是它卡在 PENDING——它在等一个永远没出现的依赖。
而 fiber.dispose() 会等该插件所有清理工作(包括异步 disposer)都完成后才结束,并递归卸载它挂载的所有子插件。这两点加起来,
就是「随时拔插件」这件事的完整闭环:加载是声明式的等待,卸载是递归的、逆序的、可等待的。
六、DSH 如何把 Cordis 用起来:插件树、seam 与「无特权内核」
有了上面的地基,再看 DSH 的架构文档(docs/architecture.md),很多东西就顺了。它开篇第一句就是:Cordis 是 dsh 底层的框架,
「插件向共享上下文贡献服务、类型化事件和可逆的副作用」,产品的每一部分都是插件——模型适配器、工具注册表、会话日志、以及 agent loop 本身,
所以每一部分都能从配置替换。不存在需要打补丁的特权内核:扩展 dsh 的方式,就是「把插件挂到其他插件旁边」。
一个正在运行的 dsh,是一棵 插件树(plugin tree),由启动时按序叠加的各层组合而成:
| 概念 | 作用 |
|---|---|
| Profile | 放在 Harness home 里的具名组装,列出要叠放的 bundle、存放树外插件、保存用户自己的 cordis.patch.yml;web 和 headless 是出厂模板 |
| Bundle(组合包) | Cordis 配置项 + 挂载代码的分发格式,上层总是可以 patch 覆盖它 |
| dsh-base | 每个 profile 的第一层:模型适配器、工具、持久化、沙箱与审批策略、设置、凭据、遥测 |
| patch 层 | profile 的 patch → home 级 patch → 任意 --patch overlay,按序叠加 |
分层按这个顺序应用在空条目列表之上:先按 profile 列出的顺序应用每个 bundle,然后是 profile 的 cordis.patch.yml,然后是 home 级的,
最后是任意 --patch overlay。一条 patch 按 id 定位某个条目、替换它的整个 config,或插入新条目。你可以用
dsh --profile web --dump-config 直接打印你机器上实际启动的配置树——它打印出的任何条目,都可以被你自己 patch 替换。这就是
「可组合」在用户侧的样子:不是「改源码」,而是「叠一层补丁」。
核心包通过向这棵树贡献服务(ctx 键)来工作,架构文档给了一张表:
| 包 | 职责 | ctx 键 |
|---|---|---|
| core/session | 仅追加的 SessionEvent 日志与内存存储 | ctx.sessions |
| core/system-prompt | 提示词片段与工具 schema 的组装 | ctx.systemPrompt |
| core/tools | 作用域化的工具注册表 + 带把关的执行流水线 | ctx.tools |
| core/agent | Agent 接口、活跃 agent 注册表与 agent/* 事件 | ctx.agents |
| core/agent-loop | 实现 Agent 接口的默认驱动器 | ctx.agentLoop |
| llm/llm | 消息与流式词汇表、以及适配器 seam | ctx.llm |
这张表里最值得琢磨的是 seam(接缝) 这个词。DSH 给 seam 下的定义是「一种可替换能力」,包含三种角色:
Service Definition(声明接口、拥有自己的 ctx.<key> 和词汇类型)、一个或多个
Service Provider(实现它)、以及一个或多个注入该服务的 Consumer(通常是面向模型的工具)。
拿 packages/shell 举例:dsh-shell 是 Service Definition,dsh-bash-local /
dsh-bash-sandbox 是提供方,dsh-tool-bash 是 Consumer。文件系统与进程提供方共享同一个「执行世界」,
于是把它们的 seam 指向一个远程沙箱,也就把 Bash、PTY、LSP 一并搬了过去——不用给每个提供方写专门的 fork。
这正是「替换一个提供方就能改变整个产品」的机制,也解释了为什么 DSH 能轻描淡写地说「模型也是插件」。
事件也是分三类的,架构文档强调「事件就是扩展点」:会话事件是追加进日志、通过 session/event 广播的持久事实;
Agent 事件(agent/*)携带活跃 Agent,用于观察/拦截正在跑的任务;能力事件则无需 import 循环
就能给 fs/*、tools/*、telemetry/* 这些 seam 挂策略和适配器。还有一条不变量反复被强调:
「模型可见 ⇔ 已记录」——凡是最终进入模型请求的内容,都必须能从会话日志里重建出来,且由一条运行时断言强制保证。上下文压缩用的是
replacement 事件,原始历史永不删除。这条不变量的意义在于:它让「可逆」不止作用于插件装配,也作用于 agent 的每一步行为——调试、审计、回放,共用同一份事件流。
七、四种运行模式深挖:标准 / PTC(Code) / 极简 / 创造
有了 Cordis 这套「一切皆插件」的底座,「运行模式」这件事就变得很自然了:模式不是硬编码的分支,而是四种出厂预设(agent preset)。
上一篇文章把 preset 定义为「一个会话的 Agent 所运行的插件组装」,这一篇直接挖到仓库里每个 preset 的配置文件
(apps/cli/config/agent-presets/*/preset.yml 和 agent.cordis.yml),看它们到底「开」了什么、「关」了什么。
先给一张总表,再逐个拆。
| 目录名 | 中文显示名 | 说明(preset.yml 原文) |
|---|---|---|
standard | 标准模式 | 功能完整的编码 Agent,支持文件编辑、Shell、文件与网页检索、Skills、计划、目标、子代理和工作流。 |
code | PTC 模式 | 具备标准模式的全部能力,并通过 Code Mode SDK 呈现工具,让模型用一个 TypeScript 程序组合多步操作。 |
minimal | 极简模式 | 仅提供持久 bash 与 str_replace_editor 的双工具编码 Agent。 |
cordis | 创造模式 | 用于创建自定义 Agent preset:具备标准模式的全部能力,并提供运行时检查、插件实验和 preset 创作指导。 |
注意一个很容易被忽略、但信息量很大的细节:这四个预设的目录名是 standard / code /
minimal / cordis,而中文显示名分别是「标准 / PTC / 极简 / 创造」。也就是说,「PTC」是中文界面的显示名,
它的目录 id 是 code、英文机制名是 Code Mode;官方没有展开「PTC」这个缩写本身(仓库里找不到全称),
所以本文只描述它的机制、不为这个缩写编一个全称。同理,「创造模式」的目录 id 是 cordis——它直接以框架命名,这个命名本身就是线索。
标准模式(standard):一个「挂载一次、多次加入」的完整编码 Agent
标准模式的 agent.cordis.yml 开头注释写着:它是「完整编码 Agent,每个进程挂载一次」。这个「挂载一次」不是随便说的——
它是一个 standing scope(常驻作用域),roster 把它挂载一次,之后每个命名它的会话都通过 scope 父级关系
加入,于是这里注册的工具和提示词片段覆盖每一个加入的 agent,而会话自己的状态仍按 Session/Agent 隔离在各个插件内部。这背后正是第三节那个
scope 原语:一项贡献要么是「全局的」(对所有 agent 可见),要么是「带作用域的」(恰好归属一个 scope key)。
它开的东西,从配置行里能数出来:bash / pwsh 两个 shell 工具、文件系统(fs + fs-search)、后台任务、Skills、目标(goal)、计划模式
(plan-mode)、上下文压缩(compaction)、子代理与工作流(subagent / subagent_fork / workflow / ralph)、ask_user、todo、web 搜索。
还有两个被 disabled: true 关掉的行特别值得注意:tool-subagent-codex 和 tool-subagent-claude-code。
也就是说,DSH 出厂就内置了「把某个子代理委托给 Codex / Claude Code 去跑」的产品提供方,但默认是关的;你复制一份 preset、
去掉对应行的 disabled,就能只对你这个 agent 开放「子代理外包给别的产品」的能力。这是「一切皆插件」最具体的注脚:连「外包给竞品」
都是一个可以开关的插件行。
PTC / Code 模式(code):让模型写一个 TypeScript 程序,把 N 次往返压成 1 次
Code 模式是四个里最「机制导向」的一个。它的 agent.cordis.yml 开头写得很清楚:标准模式里的一切都原样保留,唯一新增的是一个
tool-presentation 行(@deepseek-ai/dsh-agent-tool-presentation,mode: code)。它的效果是:
模型不再「一次工具调用做一个动作」,而是针对生成的 SDK 写一个 TypeScript 程序,由 run_code 执行——
于是原本需要五次往返的操作序列,被压成一次。
这里有个非常「Cordis」的细节值得单独说:配置注释强调,注册表本身留在 host 平面——agent loop 的调度器、API proxy 的 presenter 才是它的消费方;这个 preset 拥有的只是「这个 agent 独享的注册表呈现方式」。原生会话和它并排跑在同一个进程里,各自看到 自己的工具目录。换句话说,Code 模式没有改变「能力」,它改变的是「能力的呈现」——把 N 个细粒度工具调用,重新呈现为一个「可编程组合」的接口。 这跟 Claude Code 里模型逐条调用工具、Codex 里模型写脚本的思路都有交集,但 DSH 把它做成了 preset 的一个开关,而不是产品的固有形态。
极简模式(minimal):只有两个工具,专门用来「公平地测模型」
极简模式是信息密度最高的一个,因为它的存在理由跟「产品好用」无关,而跟「基准测试是否公平」有关。它的注释第一句:
a fixed-prompt, two-tool coding-agent composition——固定提示词、双工具编码 Agent 组装。它的 persona 就是
完整的系统提示词(complete: true),全局身份、Web 指引、工具说明以及之后任何组装监听器都不能再往里加提示词;
运行时上下文快照被抑制(includeRuntimeContext: false);模型只能组合两个工具:持久 bash 和
str_replace_editor;没有上下文压缩(compaction 缺席)。
为什么这个组合是「基准测试」用的?因为当你在比较两个模型的 Agent 能力时,任何「提示词工程差异」「工具丰富度差异」「压缩策略差异」都会成为 混淆变量。极简模式把这些变量全部钉死:同样的两句话提示词、同样的两个工具、同样的无压缩上下文——剩下的差异,就只能归因于模型本身。 上一篇文章提过「正式版 DeepSeek-V4-Flash 使用 DeepSeek Harness 极简模式作为框架进行测试」,现在能看得更透:DeepSeek 用它来保证 自家 Agent 跑分里「执行环境」这个变量是受控的——尽管这也意味着,官方跑分衡量的始终是「模型在这个受控环境里的表现」,而非纯模型能力。 这一点,本站此前已经提醒过要「存疑但转述」,这一篇从机制上补全了「为什么」。
创造模式(cordis):一个能读写自己运行时的 Agent
创造模式是四个里最激进、也最「自指」的一个。它的 agent.cordis.yml 注释第一句:the standard coding agent, plus the
ability to read and write the runtime it is running in——标准编码 Agent,加上「读写它自己运行所在的运行时」的能力。它存在的目的,
官方写得直白:让一个人可以要求一个 agent 去创作另一个 agent。标准模式的一切原样保留,新增的是:一套自指的 Cordis 工具集
(dsh-tool-cordis,其中 cordis_mount 会把模型写的 JavaScript 对着活着的运行时求值)、一个教
「composition 创作」的 skill(editing-cordis-compositions),以及一个解释「两个平面」的 persona。
「两个平面」这个说法值得展开,因为它其实是整个 DSH 架构的关键心智模型:HOST 平面持有注册表本身和一切跨会话共享的东西
——持久化、沙箱与审批栈、模型路由、子代理注册表及其后端;AGENT PRESET 平面持有一个会话向这些注册表贡献的东西——它的工具、
它的 persona、它的提示词片段。一条「发布服务」的插件行属于 host 平面,或者放在一个 isolate realm 里(当这个 preset 真正拥有该服务、
且没有别人读它时)。这个「哪一行该放哪个平面」的区分,就是那个 skill 要教给模型的东西。
更要命的是安全边界。创造模式的配置头用大写 TRUST 标注了一条警告:cordis_mount 会对着活着的运行时求值模型写的 JavaScript,
而这个 agent 写出来的 composition 会成为其他会话挂载的 preset——「把跑在这个 preset 上的会话当作 shell 权限对待」。
换句话说,创造模式不是一个沙箱,它是一个信任边界。在一个刚发布的 v0.1 里,允许模型在受控条件下改动自己的运行时装配,
这确实很激进,也正是「Agent 即基础设施」这条思路的自然延伸;官方同时明确警告后续会有破坏性变更,生产使用需谨慎。
八、结论:这到底意味着什么
把这四个模式和 Cordis 的机制拼在一起,DSH 的完整图景就清晰了:它不是一个「带插件系统的 Agent 产品」,而是一个「用插件系统组装 Agent 产品的运行时」。标准 / PTC / 极简 / 创造,本质是同一套 Cordis 装配的四种不同「预设」——标准是完整形态,PTC 换了工具呈现方式, 极简把变量钉死用于测模型,创造干脆把「改运行时」本身做成一个工具。四种模式的差异,全部落在「哪些插件行被开/被关/被换」上,没有一行是硬编码的分支。
落到「这对本站读者意味着什么」,有三点最实际。第一,模型是插件、是 seam,意味着你完全可以把 DSH 的 ctx.llm
指向国内中转站的 OpenAI 兼容端点,用 DeepSeek V4 Pro / V4 Flash 驱动它——这跟上一篇的 DEEPSEEK_BASE_URL / Web UI /
settings.yaml 接入方法是同一件事,只是现在你知道了它为什么能这么顺:因为你换的不是「模型」这个硬编码,而是一个可逆注册的适配器插件。
第二,极简模式是官方跑分的「受控变量」,所以看到「DeepSeek 碾压某某」的标题时,记得先问一句:是在哪个模式、哪个 harness 下测的。
第三,创造模式是信任边界而非沙箱,v0.1 阶段别让它在有真实凭证的生产环境里乱跑。
最后补一句诚实的边界:Cordis 论文里那套「可逆效应 / 反应式余效应」的形式化定义,本文是从论文与官方 primer 转述的,并非本站的独立形式化复验;
DSH 对 Cordis 做的本地改动(fiber 加固、事务性热更新等)来自 vendor 目录的「本地修改日志」,属于官方自述口径。这两处都值得读者在深入时
回原仓库核对原文。除此之外,本文关于四个 preset 的描述,均直接取自仓库内 preset.yml 与 agent.cordis.yml 的原文与注释,
可以放心作为「当前版本的事实」。
合在一起看,这意味着
- 想理解「DSH 凭什么敢让一切皆插件」 → 答案在 Cordis 的「可逆效应(Revertible Effects,时间维)+ 反应式余效应(Reactive Coeffects,空间维)」:注册带 disposer、卸载按逆序撤销、依赖就绪才激活。
- 想看「模型如何变成可替换插件」 → 关键在
ctx.llm这个 seam(Service Definition + Provider + Consumer),以及 profile/bundle/patch 的分层组合。 - 四种模式 → standard(完整)、code/PTC(Code Mode:模型写 TypeScript 程序)、minimal(双工具、固定提示词,测模型用)、cordis/创造(读写运行时,信任边界)。
- 两个提醒 → 官方 Agent 跑分含「极简模式」这个受控环境变量,需等第三方复测;创造模式是信任边界而非沙箱,v0.1 有破坏性变更风险。