Skip to content

Cloud Tasks

源码版本rust-v0.145.0

codex cloud は prompt を OpenAI クラウドに投げて走らせるサブコマンドだ:ローカルではモデルを呼ばず、Agent ループも回さず、タスクの提出、状態のポーリング、diff の取得、パッチの適用だけを担う。cloud-tasks は TUI + CLI の入口で、cloud-tasks-clientCloudBackend trait + HTTP 実装を提供し、cloud-tasks-mock-client が debug モードに偽バックエンドを差し込み、backend-client は下層の HTTP(他の backend API にも再利用される)。Model Provider のローカル推論とは異なり——こちらでは「モデル推論」はクラウドのコンテナ内で起きる。

責務

  1. タスク提出:run_exec_command が prompt + git ref + environment id をパッケージして POST /wham/tasks(または /api/codex/tasks)に送り、task id を返す (codex-rs/cloud-tasks/src/lib.rs:161-184)。
  2. リスト/詳細/差分:run_list_commandrun_status_commandrun_diff_command の三つの CLI サブコマンドがそれぞれ list_tasks / get_task_summary / get_task_diff に対応する (codex-rs/cloud-tasks/src/cli.rs:16-27)。
  3. パッチ適用:apply_task は dry-run preflight を走らせてから実際に apply する。diff_override でユーザが best-of-N のうちの一回を選べる (codex-rs/cloud-tasks-client/src/http.rs:99-121)。
  4. trait 抽象:CloudBackend がバックエンドとの全やり取りを trait に集約し、debug build は MockClient、release は HttpClient に進む (codex-rs/cloud-tasks-client/src/api.rs:136-176)。
  5. バックエンド初期化:init_backend が base URL、UA、auth provider、ChatGPT-Account-Id を組み立て、CODEX_CLOUD_TASKS_BASE_URL に従い WHAM / Codex API のパススタイルを切り替える (codex-rs/cloud-tasks/src/lib.rs:43-107)。

設計動機

core に詰め込むのではなく独立 crate にしたのは、このパスがAgent メインループを走らせないからだ。core の client はモデルに stream リクエストを送り、SSE をパースし、turn state を管理する。cloud task は「長いタスクをクラウドに提出し、非同期で結果を待つ」。両者の並発モデルは全く異なる:前者は長接続 stream、後者は poll + 取得。CloudBackend trait が存在するのは、TUI を debug build で走らせるためだ——init_backendCODEX_CLOUD_TASKS_MODE=mock を検出したら直接 MockClient に切り替え、ローカルで ChatGPT バックエンドに接続せずに UI 状態機械を调试できる。HttpClient は内部で backend-client::Client を再利用し、HTTP をもう一つ作らない。backend-api の認証ヘッダ、Cloudflare cookie store、パススタイル(wham vs codex-api)などのロジックが他の backend API 呼び出しと一致するからだ。

best-of-N はこのパスの特色だ:create_taskattempts: usize(1-4)を受け付け、クラウドは複数 attempt を走らせる。list_sibling_attempts がそれらを全部引き戻し、ApplyCommand はユーザが --attempt N で特定の結果を選べるようにする。diff_override フィールドは apply_task_preflightapply_task を貫き、apply 段階で diff を再取得せず、ユーザが選んだものを使う。

主要ファイル

codex-rs/cloud-tasks/src/lib.rs:735-744run_main。サブコマンドディスパッチ + TUI モード起動入口。codex-rs/cloud-tasks/src/lib.rs:43-107BackendContextinit_backend。環境変数で mock / http を決め、auth を組み立てる。codex-rs/cloud-tasks/src/cli.rs:29-50ExecCommand--env--attempts--branch の三つのコア引数を定義。codex-rs/cloud-tasks-client/src/api.rs:136-176CloudBackend trait。11 個のメソッドが list / get / apply / create をカバー。codex-rs/cloud-tasks-client/src/http.rs:25-63HttpClientbackend-client::Client を包み、CloudBackend を実装。codex-rs/backend-client/src/client.rs:451-482create_task の base client での実装。JSON から task id を抽出。codex-rs/cloud-tasks-mock-client/src/mock.rs:163-189MockClient が trait を実装し、内部の mock データ生成関数に転送。

ファクトリ init_backend は debug build で環境変数を検査し、mock か本物の HTTP かを決める:

rust
// cloud-tasks/src/lib.rs:43-60 — 后端选择
async fn init_backend(user_agent_suffix: &str) -> anyhow::Result<BackendContext> {
    #[cfg(debug_assertions)]
    let use_mock = matches!(
        std::env::var("CODEX_CLOUD_TASKS_MODE").ok().as_deref(),
        Some("mock") | Some("MOCK")
    );
    let base_url = std::env::var("CODEX_CLOUD_TASKS_BASE_URL")
        .unwrap_or_else(|_| "https://chatgpt.com/backend-api".to_string());
    #[cfg(debug_assertions)]
    if use_mock {
        return Ok(BackendContext {
            backend: Arc::new(codex_cloud_tasks_mock_client::MockClient),
            base_url,
        });
    }

CloudBackend trait は CloudBackendFuture で戻り型を boxed future に統一し、mock と http の実装が同じシグネチャを共有する:

rust
// cloud-tasks-client/src/api.rs:136-176 — 后端抽象
pub trait CloudBackend: Send + Sync {
    fn list_tasks<'a>(
        &'a self,
        env: Option<&'a str>,
        limit: Option<i64>,
        cursor: Option<&'a str>,
    ) -> CloudBackendFuture<'a, TaskListPage>;
    fn get_task_summary(&self, id: TaskId) -> CloudBackendFuture<'_, TaskSummary>;
    fn get_task_diff(&self, id: TaskId) -> CloudBackendFuture<'_, Option<String>>;
    // ...messages / sibling attempts / apply preflight / apply / create
    fn create_task<'a>(
        &'a self,
        env_id: &'a str,
        prompt: &'a str,
        git_ref: &'a str,
        qa_mode: bool,
        best_of_n: usize,
    ) -> CloudBackendFuture<'a, CreatedTask>;
}

create_task は base client で POST し、JSON から task id を抽出する(task.id を優先し、顶层 id にフォールバック):

rust
// backend-client/src/client.rs:451-482 — POST /wham/tasks 并提取 task id
pub async fn create_task(&self, request_body: serde_json::Value) -> Result<String> {
    let url = match self.path_style {
        PathStyle::CodexApi => format!("{}/api/codex/tasks", self.base_url),
        PathStyle::ChatGptApi => format!("{}/wham/tasks", self.base_url),
    };
    // ...发请求,解析 body
    match serde_json::from_str::<serde_json::Value>(&body) {
        Ok(v) => {
            if let Some(id) = v.get("task").and_then(|t| t.get("id")).and_then(|s| s.as_str()) {
                Ok(id.to_string())
            } else if let Some(id) = v.get("id").and_then(|s| s.as_str()) {
                Ok(id.to_string())
            } else {
                anyhow::bail!("POST {url} succeeded but no task id found; ...");
            }
        }
        Err(e) => anyhow::bail!("Decode error for {url}: {e}; ..."),
    }
}

データフロー

境界と失敗

  • 未ログインは直接退出:init_backendauth が None または uses_codex_backend() が false の場合、process::exit(1) する (codex-rs/cloud-tasks/src/lib.rs:76-95)。
  • パススタイルは base URL で決まる:https://chatgpt.com/backend-api は WHAM(/wham/tasks)に進み、それ以外は Codex API(/api/codex/tasks)に進む。PathStyle::from_base_url が判定する (codex-rs/backend-client/src/client.rs:151-177)。
  • attempts 範囲は制限される:parse_attempts は 1-4 を強制し、バックエンドの best-of-N 上限と一致させる (codex-rs/cloud-tasks/src/cli.rs:52-61)。
  • apply 失敗時の終了コードは非 0:run_apply_commandApplyStatus を検査し、Success でなければ process::exit(1) してスクリプト連鎖を便利にする (codex-rs/cloud-tasks/src/lib.rs:589-608)。
  • create_task id は二種 JSON に対応:task.id と顶层 id を両方受け付け、バックエンドごとに返却構造が異なるのを吸収する (codex-rs/backend-client/src/client.rs:464-481)。

まとめ

Cloud Tasks は「提出、照会、適用」の三ステップを CloudBackend trait に圧縮し、HTTP と mock が同じ trait を実装する。これにより TUI はローカルでバックエンドなしで调试できる。下層 HTTP は backend-client::Client を再利用し、Model Provider と認証・パススタイル判定を共有する。クラウドタスク自身の設定(許可される environment、enterprise ポリシー)は 設定システム 内の cloud config bundle が提供し、起動時に取得して適用する。