Skip to content

非交互模式 — 练习

练习 1:使用 Exec 模式执行指令

尝试使用 codex exec 命令执行一个简单的代码生成任务,观察输出格式。

参考答案

使用 codex exec "创建一个 hello world Python 程序" 执行,流程如下:

  1. CLI 解析exec::run_main() 解析 Cli 参数,command 字段为 "创建一个 hello world Python 程序"

  2. 初始化:加载配置、认证,创建 in-process app-server client

  3. 执行:构造 InitialOperation::UserTurn { items, output_schema: None },提交到 thread

  4. 事件流(JSON 模式 --experimental-json):

    json
    {"type": "TurnStartedEvent", "thread_id": "..."}
    {"type": "AgentMessageItem", "content": "我来为你创建一个 hello world 程序"}
    {"type": "CommandExecutionItem", "command": "echo 'print(\"hello world\")' > hello.py", "stdout": "", "exit_code": 0}
    {"type": "FileChangeItem", "path": "hello.py", "change": "created"}
    {"type": "TurnCompletedEvent", "usage": {"input_tokens": 1234, "output_tokens": 567}}
  5. 退出:turn 完成后,程序以 CodexStatus::Success 退出,退出码 0

文本模式下的输出是彩色的人类可读格式,包含相同的操作信息但以更友好的方式呈现。

练习 2:分析 Exec 模式执行流程

追踪 Exec 模式从接收指令到输出结果的完整执行流程。

参考答案

Exec 模式的完整执行流程(exec/src/lib.rs):

  1. run_main(cli, paths) — 主入口:

    • 解析 CLI 参数(Cli struct)
    • 确定 codex_home 和配置路径
    • 加载 ConfigCloudConfigBundle
  2. 初始化 App Server

    • 创建 ExecRunArgs,包含 in_process_start_args
    • 启动 in-process app-server client(无需外部守护进程)
    • 初始化 StateDbHandle 用于状态持久化
  3. 解析 Prompt

    • command 字段获取命令行 prompt
    • command 为空,从 stdin 读取
    • 构造 InitialOperation::UserTurn { items, output_schema }
  4. 启动/恢复 Thread

    • 新建 thread:调用 app-server 的 start_thread 请求
    • 恢复 thread:使用 --resume 参数指定 thread ID
  5. 事件循环EventProcessor):

    • rx_event 接收 Event
    • 根据事件类型映射为 ThreadEvent
    • JSON 模式:每个事件序列化为一行 JSON
    • 文本模式:格式化为人类可读的彩色文本
  6. 交互请求处理

    • 所有 ServerRequest 自动生成拒绝响应
    • 不等待用户输入,保持无交互执行
  7. 终止

    • Turn 完成或失败后退出事件循环
    • 返回 CodexStatus(Success/Failed)
    • 清理资源(关闭连接、释放 state_db)

练习 3:对比 TUI 和 Exec 的安全策略

对比两种模式下的沙箱策略和权限差异。

参考答案

TUI 和 Exec 模式共享同一套沙箱基础设施(SandboxManagerExecPolicy),但安全策略的应用方式有显著差异:

共同基础

  • 两者都使用 SandboxManager::transform() 包装命令执行
  • 都通过 ExecPolicy::check() 评估命令权限
  • 都在沙箱环境中执行(Landlock/Seatbelt

关键差异

安全维度TUI 模式Exec 模式
审批处理用户实时审批/拒绝所有请求自动拒绝
权限提升用户可临时授权无法提升权限
ExecPolicyAllow + Prompt 都可执行仅 Allow 可执行
沙箱配置标准配置可配置更严格
失败处理用户可重试/调整直接失败退出
网络策略用户可审批网络请求遵循预配置规则

Exec 模式的安全含义

  • 由于所有交互请求自动拒绝,只有 Decision::Allow 的命令能成功执行
  • 这意味着 Exec 模式的 ExecPolicy 必须预先配置好所有需要的命令权限
  • 不适合需要高权限操作的场景(如系统包安装、全局配置修改)
  • 最适合预定义任务(如代码生成、测试运行、文件操作)

最佳实践

  • 为 Exec 模式配置专门的 ExecPolicy profile,只允许必要的命令
  • 使用 output_schema_path 约束输出结构,减少意外行为
  • 在 CI/CD 中使用最小权限原则配置沙箱

拓展挑战

  • 分析 EventProcessorWithJsonOutput 的 JSON 序列化实现
  • 阅读 ExecRunArgs 的所有字段,理解每个参数的作用
  • 追踪 --resume 模式下 thread 恢复的完整流程
  • 分析 CodexStatus 的所有变体和对应的退出码