02 — 分层设计:核心 Crate 职责
Workspace 成员(如何读 Cargo.toml)
codex-rs/Cargo.toml 的 [workspace] members 列表即 官方划分的模块边界。可按「用户可见产物」反向映射 crate:
| 用户可见 | 主要 crate |
|---|---|
codex 主程序 | cli |
| 交互终端 | tui |
codex exec / 非交互 | exec |
codex app-server | app-server、app-server-protocol、app-server-client |
codex mcp-server | mcp-server(与 protocol 类型共用) |
| 业务逻辑库 | core |
| 类型与序列化 | protocol |
此外还有大量 竖切能力 crate:apply-patch、sandboxing、linux-sandbox、exec-server、execpolicy、skills、hooks、file-search、otel 等,体现 把 codex-core 变瘦 的演进方向(见根目录 AGENTS.md:「resist adding code to codex-core」)。
codex-core:#![deny(clippy::print_stdout, clippy::print_stderr)]
codex-rs/core/src/lib.rs 在 crate 根上 禁止 标准输出/错误:
- 原因:库代码若直接打印,会破坏 exec 的 JSONL 模式(stdout 必须是纯 JSON 行)、破坏 TUI 画面,且难以测试与归因。
- 实践:用户可见输出走 TUI、tracing,或由上层 CLI 明确处理。
这是典型的 「库与二进制 IO 契约」 设计,可联系:Node 里 library 不应 console.log、浏览器 SDK 不应直接操作 document。
codex-protocol:Op 与 Event 的「单一事实来源」
Op 定义在 codex-rs/protocol/src/protocol.rs,表示 提交给会话的操作(用户回合、中断、shutdown、实时对话等)。使用 #[serde(tag = "type", rename_all = "snake_case")] 与 #[non_exhaustive]:
- tagged enum:序列化稳定、跨语言易对齐。
- non_exhaustive:允许后续加 variant 而不破坏下游穷尽匹配(Rust 侧强制有
_分支或升级)。
codex-app-server-protocol:v2 API 规范
AGENTS.md 规定:新 API 只加在 v2,命名用 *Params / *Response / *Notification,wire 上 camelCase(配置类除外 mirror config.toml)。
这与前端 OpenAPI / GraphQL schema 演进 规则一致:老客户端继续用 v1,新能力走 v2。
依赖方向(简述)
理想依赖图(简化):
cli / exec / tui → core, app-server-client, protocol
app-server → core, app-server-protocol
core → protocol, 各 *-utils, apply-patch, sandboxing, ...
protocol → 尽量少禁止:protocol 依赖 core(避免循环、保持类型层纯净)。
小结(一句话)
Codex 用 protocol 定契约、core 做状态机与安全落地、多 UI crate 复用同一核心,并通过 独立 crate 拆沙箱/补丁/策略,控制
codex-core体积与编译耦合。