适用版本:ChengOS v0.1.0+ | 最后核对:2026-08-12 | 来源:
crates/cheng-engine/src/lib.rs、crates/cheng-engine/src/dag、crates/cheng-engine/src/executor/task_scheduler.rs、crates/cheng-core/src/types.rs
引擎建立在一条明确的设计原则之上:静态在左,动态在右;状态兜底,调度闭环。 规划只做一次,离线且无副作用;调度在运行时进行;而持久化的状态机是让整套机制可恢复(而不仅仅是快)的关键。
两个阶段
静态阶段(离线、纯函数) 动态阶段(运行时)
┌──────────────────────┐ ┌──────────────────────┐
│ DAG 规划器 │ │ 任务调度器 │
│ ├─ 分层执行计划 │ │ ├─ spawn 任务 │
│ ├─ 拓扑排序 │ │ ├─ 控制并发 │
│ └─ 阶段选择器 │ │ └─ 回写结果 │
└──────────┬───────────┘ └──────────┬───────────┘
▼ ▼
┌──────────────────────┐ 节点完成 ┌──────────────────────┐
│ 执行队列 │◄───────────────│ 事件 │
│ (缓冲就绪节点) │ └──────────────────────┘
└──────────┬───────────┘
▼
┌──────────────────────┐
│ 状态机(兜底) │
└──────────────────────┘
静态那一半是纯函数式且无状态的——它只分析结构并产出执行计划,不产生任何副作用。正因如此,图校验才足够廉价,可以在每次执行前都跑一遍,而且无需数据库就能测试。
静态分析
- 构建图。 节点和连线变成邻接表形式的 DAG。
- 校验。 拒绝成环、悬空连线和无法满足的必需输入。一张不可能成功的图会在此刻被拒绝,而不是运行到一半才失败。
- 拓扑排序。 用 Kahn 算法得出一个合法顺序。
- 分层成阶段。 彼此之间没有依赖的节点落入同一阶段,这使它们有资格并发运行。
- 选择就绪节点。 阶段选择器识别出依赖已满足的节点。
因为执行计划是推导出来的而非存储的,所以修改工作流绝不会留下过期的计划。
运行时调度
调度器把每个就绪节点作为一个异步 Tokio 任务 spawn 出去,并用信号量限制并发。
| 设置 | 默认值 |
|---|---|
| 最大并发 | CPU 核数 × 3 |
| 任务超时 | 启用,300 秒(5 分钟) |
并发数刻意高于核心数,因为多数节点是 I/O 密集的——在等待模型 API、HTTP 调用或数据库。按核心数设置会让机器在任务等待网络时空转。
这个循环是闭合的:某个节点完成会发布完成事件,队列重新评估哪些节点刚变为就绪,调度器再把它们 spawn 出去。这里没有轮询,也没有固定的逐阶段栅栏——一个节点在它自己的依赖被满足的那一刻就运行,而不是等整个阶段都结束。
状态
执行状态是持久化的,而不仅仅保存在内存中,这正是「状态兜底」的含义:一次执行可以被检视、恢复,或在进程重启后被找回。
执行状态——pending、running、paused、waiting_for_review、completed、failed、cancelled、timeout。后四个是终态。
节点状态——waiting、ready、running、completed、failed、skipped。节点自身不持有状态;运行进行中时状态记录在执行记录里。
waiting_for_review 值得留意:它在某个工具返回 requires_review: true 时进入,并持久地挂起执行直到决策到来。由于审批总线是一个内存中的广播通道,决策还会同时记录在审批上下文上——否则一个在无人订阅时发布的决策就会永久丢失。
值与流式传输
数据以 NodeValue 形式流动,这是一个包含 file 和 stream 情况的带标签联合类型。正是「流」让模型节点能在 token 抵达时就把它们传给下游,而不必缓冲整段响应;而「文件」让大体积负载以引用方式传递。
节点有三种实现形态:TypedNode(同步、类型安全,用于纯计算)、AsyncTypedNode(异步,用于 I/O 密集或依赖上下文的工作),以及更底层的、接受原始 map 的 AsyncNode。
事件
每次生命周期状态转换都会发布一个事件,并通过 WebSocket 抵达客户端:EXECUTION_START、EXECUTION_PROGRESS、NODE_COMPLETE、NODE_FAILED、EXECUTION_STATE_CHANGED,以及终态的 EXECUTION_COMPLETE / EXECUTION_FAILED / EXECUTION_CANCELLED。流式节点额外发出 NODE_STREAM_*;智能体额外发出迭代、工具和轮次事件。参见 WebSocket API。
容器与循环
在普通 DAG 之外,引擎还支持容器节点——子流程、批量子流程和循环——它们包含各自的子图。这些会经过独立的分析阶段,并发出 CONTAINER_STARTED / CONTAINER_COMPLETED 与 LOOP_ITERATION_* 事件,因此一批 100 个条目是逐次可观测的,而不是一个不透明的节点。
失败、重试与取消
节点失败默认会使整次执行失败。POST /executions/:id/cancel 把活跃运行转为 cancelled;引擎也支持从失败点重试一次失败的执行,这会产生一个新的执行 id,而不是修改旧记录——失败的那次运行会作为证据完整保留。
下一步
- 测试与调试——在编辑器中观察这一切。
- WebSocket API——直接消费事件流。
- 执行失败排查——诊断一次糟糕的运行。

暂无评论内容