use std::net::SocketAddr;
use std::path::PathBuf;
use std::time::Duration;
use crate::KitError;
#[derive(Clone, Debug)]
pub struct CodexConfig {
mode: CodexMode,
}
#[derive(Clone, Debug)]
pub(crate) enum CodexMode {
Spawn {
startup_timeout: Duration,
request_timeout: Duration,
},
Tcp {
address: SocketAddr,
connect_timeout: Duration,
request_timeout: Duration,
},
Unix {
path: PathBuf,
connect_timeout: Duration,
request_timeout: Duration,
},
}
impl CodexConfig {
pub fn spawn(startup_timeout: Duration, request_timeout: Duration) -> Result<Self, KitError> {
Self::validate_timeout("Codex startup timeout", startup_timeout)?;
Self::validate_timeout("Codex request timeout", request_timeout)?;
Ok(Self {
mode: CodexMode::Spawn {
startup_timeout,
request_timeout,
},
})
}
pub fn tcp(
address: SocketAddr,
connect_timeout: Duration,
request_timeout: Duration,
) -> Result<Self, KitError> {
if address.port() == 0 {
return Err(KitError::invalid_config(
"Codex TCP address must use a nonzero port",
));
}
Self::validate_timeout("Codex connect timeout", connect_timeout)?;
Self::validate_timeout("Codex request timeout", request_timeout)?;
Ok(Self {
mode: CodexMode::Tcp {
address,
connect_timeout,
request_timeout,
},
})
}
pub fn unix(
path: PathBuf,
connect_timeout: Duration,
request_timeout: Duration,
) -> Result<Self, KitError> {
if path.as_os_str().is_empty() {
return Err(KitError::invalid_config(
"Codex Unix socket path must not be empty",
));
}
Self::validate_timeout("Codex connect timeout", connect_timeout)?;
Self::validate_timeout("Codex request timeout", request_timeout)?;
Ok(Self {
mode: CodexMode::Unix {
path,
connect_timeout,
request_timeout,
},
})
}
pub(crate) fn mode(&self) -> &CodexMode {
&self.mode
}
pub(crate) fn validate(&self) -> Result<(), KitError> {
match &self.mode {
CodexMode::Spawn {
startup_timeout,
request_timeout,
} => {
Self::validate_timeout("Codex startup timeout", *startup_timeout)?;
Self::validate_timeout("Codex request timeout", *request_timeout)
}
CodexMode::Tcp {
address,
connect_timeout,
request_timeout,
} => {
if address.port() == 0 {
return Err(KitError::invalid_config(
"Codex TCP address must use a nonzero port",
));
}
Self::validate_timeout("Codex connect timeout", *connect_timeout)?;
Self::validate_timeout("Codex request timeout", *request_timeout)
}
CodexMode::Unix {
path,
connect_timeout,
request_timeout,
} => {
if path.as_os_str().is_empty() {
return Err(KitError::invalid_config(
"Codex Unix socket path must not be empty",
));
}
Self::validate_timeout("Codex connect timeout", *connect_timeout)?;
Self::validate_timeout("Codex request timeout", *request_timeout)
}
}
}
fn validate_timeout(label: &str, timeout: Duration) -> Result<(), KitError> {
if timeout.is_zero() {
return Err(KitError::invalid_config(format!(
"{label} must be greater than zero"
)));
}
Ok(())
}
}
impl CodexMode {
pub(crate) fn request_timeout(&self) -> Duration {
match self {
Self::Spawn {
request_timeout, ..
}
| Self::Tcp {
request_timeout, ..
}
| Self::Unix {
request_timeout, ..
} => *request_timeout,
}
}
}