博客

Eva-CLI 的模块划分边界

Eva-CLI 如何把架构决策落实为 Rust crate 边界、依赖方向、运行时交接和受控副作用归属。

发布: 分类: 运行时

Eva-CLI 的模块划分不是给 crate 起名字。它真正要固定的是架构边界:权力归属在哪里,副作用在哪里发生,热更新 Agent 行为如何演进,同时又不把运行时变成一个没有结构的脚本宿主。

简短结论是:Rust 托管可信运行时边界,Lua 承载可替换业务行为,EventBus 与 Scheduler 负责协作,Adapter 和服务 crate 负责副作用,eva-runtime 是唯一组合具体实现的位置。

Eva-CLI 模块划分总览图,展示 CLI、runtime、核心契约、事件路由、Agent、Lua host、adapter、memory、storage、discovery、lifecycle 与 observability 边界。
模块图表达的是稳定职责边界,不是临时实施阶段。

先划职责,再排目录

推荐的 workspace 使用 crate 承载稳定职责域,crate 内部再用 module 组织实现细节。这个区别很重要:目录结构可以较低成本调整,职责边界一旦被错误依赖穿透,后续修复成本会高很多。

第一条规则是底层 crate 不反向依赖应用组合根。eva-coreeva-eventbuseva-schedulereva-agenteva-lua-hosteva-adaptereva-storage 和服务 crate 都应保持可独立测试。eva-runtime 负责装配它们,但不能把自身泄漏回这些模块。

核心依赖方向

依赖方向应把契约留在中心,把具体 transport 留在边缘。核心类型、Topic 规则、结构化错误、权限形状和观测字段可以向内共享。provider 协议、shell 执行、MCP transport、HTTP、硬件 I/O 和 release mutation 必须藏在 adapter 或服务边界之后。

Eva-CLI 模块依赖规则图,展示核心契约、runtime 组合根,以及 adapter、service、Lua host、storage、policy、discovery、lifecycle 和 observability 的受控依赖方向。
依赖方向是模块方案真正的约束手段。
边界 负责 不负责
eva-core Event、Topic、ID、schema 形态契约、通用错误形态。 运行时编排、文件系统访问、provider 协议、策略决策。
eva-eventbuseva-scheduler 发布订阅、投递、路由规则、队列、死信。 业务决策、Lua 执行、外部 capability 调用。
eva-agenteva-lua-host Agent 生命周期、私有 inbox、沙箱 Lua state、受控 host API。 原始 shell、原始网络、密钥、设备句柄、release pointer mutation。
eva-adapter 与服务 crate capability、provider 路由、副作用边界、storage、memory、discovery、lifecycle。 未经校验的 Lua 权力,或跨模块共享的隐式全局状态。

运行时交接必须显式

好的模块边界会在运行时交接上显形。用户输入通过 ingress surface 进入并变成 typed Event。EventBus 持久化并发布事件。Scheduler 决定投递。AgentRuntime 隔离每个 Agent inbox。Lua 通过窄 host context 处理业务逻辑。AdapterRouter 和服务 crate 只有在 schema 与 policy 校验通过后才执行副作用。

Eva-CLI 运行时模块流图,展示 ingress 到 EventBus、Scheduler、AgentRuntime、Lua Host、Tool Layer、AdapterRouter、外部 provider、服务模块、storage、lifecycle 与 observability 的交接。
运行时流程把副作用留在 Lua 之外,并让每次交接可观测。

横切规则

有些规则不属于单个 crate,但每个 crate 都必须保留。跨模块错误需要稳定字段,例如 kindmessageretryableprovider_code 和 correlation 标识。权限只能沿着 system policy、manifest permissions、user/session policy、request constraints、effective permissions 逐层收紧。状态归属也必须显式:Agent 局部状态归 Agent 与 Lua generation,业务持久状态归 storage 与 memory,事件恢复状态归 EventBus,Adapter 运行状态归 Adapter,generation 状态归 lifecycle。

基础契约
  -> 事件与路由内核
  -> 隔离的 Agent 与 Lua 执行边界
  -> 受控 capability 与 Adapter 边界
  -> Discovery 与 Runtime services
  -> CLI、Supervisor 和运维工作流

为什么这会影响实现

Eva-CLI 后续会接入 Skills、MCP、外部 Agent、记忆、硬件、备份、Release Snapshot 和进程 generation 切换。每个功能都天然想直接拿到某种强权力。模块划分的价值就是把这些权力保持在可审查路径上:Discovery 可以发现候选,Policy 可以授权,Adapter 可以执行,Observability 可以记录,Runtime 可以组合,而 Lua 或 Scheduler 不会变成隐藏系统 API。

完整技术方案见 模块划分方案