chore: update Codex::spawn() to return a struct instead of a tuple

This commit is contained in:
Michael Bolin
2025-07-24 14:49:55 -07:00
parent 508abbe990
commit a7638d9b31
7 changed files with 36 additions and 11 deletions

View File

@@ -4,6 +4,7 @@ use std::sync::Arc;
use clap::Parser;
use codex_common::CliConfigOverrides;
use codex_core::Codex;
use codex_core::CodexConversation;
use codex_core::config::Config;
use codex_core::config::ConfigOverrides;
use codex_core::protocol::Submission;
@@ -35,7 +36,7 @@ pub async fn run_main(opts: ProtoCli) -> anyhow::Result<()> {
let config = Config::load_with_cli_overrides(overrides_vec, ConfigOverrides::default())?;
let ctrl_c = notify_on_sigint();
let (codex, _init_id, _session_id) = Codex::spawn(config, ctrl_c.clone()).await?;
let CodexConversation { codex, .. } = Codex::spawn(config, ctrl_c.clone()).await?;
let codex = Arc::new(codex);
// Task that reads JSON lines from stdin and forwards to Submission Queue

View File

@@ -96,11 +96,22 @@ pub struct Codex {
rx_event: Receiver<Event>,
}
/// Wrapper returned by [`Codex::spawn`] containing the spawned [`Codex`],
/// the submission id for the initial `ConfigureSession` request and the
/// unique session id.
pub struct CodexConversation {
pub codex: Codex,
pub init_id: String,
pub session_id: Uuid,
}
impl Codex {
/// Spawn a new [`Codex`] and initialize the session. Returns the instance
/// of `Codex` and the ID of the `SessionInitialized` event that was
/// submitted to start the session.
pub async fn spawn(config: Config, ctrl_c: Arc<Notify>) -> CodexResult<(Codex, String, Uuid)> {
/// Spawn a new [`Codex`] and initialize the session.
///
/// Returns a [`CodexConversation`] containing the [`Codex`] instance,
/// the submission id of the initial `ConfigureSession` request and the
/// unique session id.
pub async fn spawn(config: Config, ctrl_c: Arc<Notify>) -> CodexResult<CodexConversation> {
// experimental resume path (undocumented)
let resume_path = config.experimental_resume.clone();
info!("resume_path: {resume_path:?}");
@@ -138,7 +149,11 @@ impl Codex {
};
let init_id = codex.submit(configure_session).await?;
Ok((codex, init_id, session_id))
Ok(CodexConversation {
codex,
init_id,
session_id,
})
}
/// Submit the `op` wrapped in a `Submission` with a unique ID.

View File

@@ -1,6 +1,7 @@
use std::sync::Arc;
use crate::Codex;
use crate::CodexConversation;
use crate::config::Config;
use crate::protocol::Event;
use crate::protocol::EventMsg;
@@ -15,7 +16,11 @@ use uuid::Uuid;
/// that callers can surface the information to the UI.
pub async fn init_codex(config: Config) -> anyhow::Result<(Codex, Event, Arc<Notify>, Uuid)> {
let ctrl_c = notify_on_sigint();
let (codex, init_id, session_id) = Codex::spawn(config, ctrl_c.clone()).await?;
let CodexConversation {
codex,
init_id,
session_id,
} = Codex::spawn(config, ctrl_c.clone()).await?;
// The first event must be `SessionInitialized`. Validate and forward it to
// the caller so that they can display it in the conversation history.

View File

@@ -11,6 +11,7 @@ mod client;
mod client_common;
pub mod codex;
pub use codex::Codex;
pub use codex::CodexConversation;
pub mod codex_wrapper;
pub mod config;
pub mod config_profile;

View File

@@ -1,4 +1,5 @@
use codex_core::Codex;
use codex_core::CodexConversation;
use codex_core::ModelProviderInfo;
use codex_core::exec::CODEX_SANDBOX_NETWORK_DISABLED_ENV_VAR;
use codex_core::protocol::EventMsg;
@@ -72,7 +73,7 @@ async fn includes_session_id_and_model_headers_in_request() {
let mut config = load_default_config_for_test(&codex_home);
config.model_provider = model_provider;
let ctrl_c = std::sync::Arc::new(tokio::sync::Notify::new());
let (codex, _init_id, _session_id) = Codex::spawn(config, ctrl_c.clone()).await.unwrap();
let CodexConversation { codex, .. } = Codex::spawn(config, ctrl_c.clone()).await.unwrap();
codex
.submit(Op::UserInput {
@@ -148,7 +149,7 @@ async fn includes_base_instructions_override_in_request() {
config.model_provider = model_provider;
let ctrl_c = std::sync::Arc::new(tokio::sync::Notify::new());
let (codex, ..) = Codex::spawn(config, ctrl_c.clone()).await.unwrap();
let CodexConversation { codex, .. } = Codex::spawn(config, ctrl_c.clone()).await.unwrap();
codex
.submit(Op::UserInput {

View File

@@ -20,6 +20,7 @@
use std::time::Duration;
use codex_core::Codex;
use codex_core::CodexConversation;
use codex_core::error::CodexErr;
use codex_core::protocol::AgentMessageEvent;
use codex_core::protocol::ErrorEvent;
@@ -48,7 +49,7 @@ async fn spawn_codex() -> Result<Codex, CodexErr> {
let mut config = load_default_config_for_test(&codex_home);
config.model_provider.request_max_retries = Some(2);
config.model_provider.stream_max_retries = Some(2);
let (agent, _init_id, _session_id) =
let CodexConversation { codex: agent, .. } =
Codex::spawn(config, std::sync::Arc::new(Notify::new())).await?;
Ok(agent)

View File

@@ -4,6 +4,7 @@
use std::time::Duration;
use codex_core::Codex;
use codex_core::CodexConversation;
use codex_core::ModelProviderInfo;
use codex_core::exec::CODEX_SANDBOX_NETWORK_DISABLED_ENV_VAR;
use codex_core::protocol::EventMsg;
@@ -94,7 +95,7 @@ async fn retries_on_early_close() {
let codex_home = TempDir::new().unwrap();
let mut config = load_default_config_for_test(&codex_home);
config.model_provider = model_provider;
let (codex, _init_id, _session_id) = Codex::spawn(config, ctrl_c).await.unwrap();
let CodexConversation { codex, .. } = Codex::spawn(config, ctrl_c).await.unwrap();
codex
.submit(Op::UserInput {