用户旅程

从用户视角看,Codex 是一个聊天式 coding agent;从源码看,它是一条跨越 UI、协议、线程、turn、模型、工具和持久化的流水线。

用户旅程

1. 入口收集输入

TUI 侧的输入逻辑分布在 codex-rs/tui/src/chatwidget/input_*slash_dispatch.rsturn_runtime.rs 等模块。CLI/app-server 入口也会把请求转换成 protocol 层的 Op

关键点是:用户输入不会直接调用模型,而是封装成 Submission

  • Submission 带唯一 id,用于关联后续事件。
  • Op 表示用户动作,例如用户消息、配置更新、审批响应、interrupt、compact 等。
  • 客户端通过事件流消费 EventMsg,而不是同步等待一个字符串。

源码入口:codex-rs/protocol/src/protocol.rs

2. Thread 接收提交

CodexThread 是 thread 级别的双向消息管道。它暴露:

  • submit:提交普通 Op
  • submit_with_trace:携带 W3C trace。
  • steer_input:向当前 active turn 注入用户输入。
  • inject_if_running:扩展向正在运行的 turn 注入 model-visible item。
  • try_start_turn_if_idle:扩展在空闲时启动自动 turn,例如 /goal 续跑。

源码入口:codex-rs/core/src/codex_thread.rs

3. Session 选择任务类型

Session 内部不是只有“普通对话”。codex-rs/core/src/tasks 里把任务拆成不同 SessionTask

  • RegularTask:普通用户 turn。
  • CompactTask:手动压缩。
  • ReviewTask:review 相关流程。
  • UserShellTask:用户直接触发的 shell 流程。

RegularTask 会先发 TurnStartedEvent,再调用 run_turn。如果 turn 结束后队列还有 pending input,它会再次进入 run_turn,从而支持模型运行期间用户继续输入。

源码入口:codex-rs/core/src/tasks/regular.rs

4. Agent Loop 处理模型输出

run_turn 的循环大致是:

  1. 运行 pre-sampling compact。
  2. 记录上下文更新,并构建 skills/plugins 注入项。
  3. 运行 session start hook 和 pending input hook。
  4. 克隆历史并转换成模型输入。
  5. 发起 Responses API 请求。
  6. 如果模型输出工具调用,调度工具并把结果写回历史。
  7. 如果还需要 follow-up 或有 pending input,继续下一轮采样。
  8. 如果没有 follow-up,运行 stop hook 和 after-agent hook,结束 turn。

源码入口:codex-rs/core/src/session/turn.rs

5. 结果回到 UI

模型消息、reasoning delta、工具开始/结束、审批请求、警告、错误、token usage、goal updated 等都通过 EventMsg 返回。UI 层只需要根据事件更新视图,不需要知道核心 loop 的所有细节。

这个事件化设计也让 app-server、TUI、CLI 和测试可以复用同一套核心能力。