feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
use reqwest::StatusCode;
|
|
|
|
|
|
use serde_json;
|
|
|
|
|
|
use std::io;
|
|
|
|
|
|
use thiserror::Error;
|
|
|
|
|
|
use tokio::task::JoinError;
|
|
|
|
|
|
|
|
|
|
|
|
pub type Result<T> = std::result::Result<T, CodexErr>;
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Error, Debug)]
|
|
|
|
|
|
pub enum SandboxErr {
|
|
|
|
|
|
/// Error from sandbox execution
|
|
|
|
|
|
#[error("sandbox denied exec error, exit code: {0}, stdout: {1}, stderr: {2}")]
|
|
|
|
|
|
Denied(i32, String, String),
|
|
|
|
|
|
|
|
|
|
|
|
/// Error from linux seccomp filter setup
|
|
|
|
|
|
#[cfg(target_os = "linux")]
|
|
|
|
|
|
#[error("seccomp setup error")]
|
|
|
|
|
|
SeccompInstall(#[from] seccompiler::Error),
|
|
|
|
|
|
|
|
|
|
|
|
/// Error from linux seccomp backend
|
|
|
|
|
|
#[cfg(target_os = "linux")]
|
|
|
|
|
|
#[error("seccomp backend error")]
|
|
|
|
|
|
SeccompBackend(#[from] seccompiler::BackendError),
|
|
|
|
|
|
|
2025-04-25 12:56:20 -07:00
|
|
|
|
/// Command timed out
|
|
|
|
|
|
#[error("command timed out")]
|
|
|
|
|
|
Timeout,
|
|
|
|
|
|
|
|
|
|
|
|
/// Command was killed by a signal
|
|
|
|
|
|
#[error("command was killed by a signal")]
|
|
|
|
|
|
Signal(i32),
|
|
|
|
|
|
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
/// Error from linux landlock
|
|
|
|
|
|
#[error("Landlock was not able to fully enforce all sandbox rules")]
|
|
|
|
|
|
LandlockRestrict,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Error, Debug)]
|
|
|
|
|
|
pub enum CodexErr {
|
|
|
|
|
|
/// Returned by ResponsesClient when the SSE stream disconnects or errors out **after** the HTTP
|
|
|
|
|
|
/// handshake has succeeded but **before** it finished emitting `response.completed`.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// The Session loop treats this as a transient error and will automatically retry the turn.
|
|
|
|
|
|
#[error("stream disconnected before completion: {0}")]
|
|
|
|
|
|
Stream(String),
|
|
|
|
|
|
|
|
|
|
|
|
/// Returned by run_command_stream when the spawned child process timed out (10s).
|
|
|
|
|
|
#[error("timeout waiting for child process to exit")]
|
|
|
|
|
|
Timeout,
|
|
|
|
|
|
|
|
|
|
|
|
/// Returned by run_command_stream when the child could not be spawned (its stdout/stderr pipes
|
|
|
|
|
|
/// could not be captured). Analogous to the previous `CodexError::Spawn` variant.
|
|
|
|
|
|
#[error("spawn failed: child stdout/stderr not captured")]
|
|
|
|
|
|
Spawn,
|
|
|
|
|
|
|
|
|
|
|
|
/// Returned by run_command_stream when the user pressed Ctrl‑C (SIGINT). Session uses this to
|
|
|
|
|
|
/// surface a polite FunctionCallOutput back to the model instead of crashing the CLI.
|
2025-05-08 21:46:06 -07:00
|
|
|
|
#[error("interrupted (Ctrl-C)")]
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
Interrupted,
|
|
|
|
|
|
|
|
|
|
|
|
/// Unexpected HTTP status code.
|
|
|
|
|
|
#[error("unexpected status {0}: {1}")]
|
|
|
|
|
|
UnexpectedStatus(StatusCode, String),
|
|
|
|
|
|
|
|
|
|
|
|
/// Retry limit exceeded.
|
|
|
|
|
|
#[error("exceeded retry limit, last status: {0}")]
|
|
|
|
|
|
RetryLimit(StatusCode),
|
|
|
|
|
|
|
|
|
|
|
|
/// Agent loop died unexpectedly
|
|
|
|
|
|
#[error("internal error; agent loop died unexpectedly")]
|
|
|
|
|
|
InternalAgentDied,
|
|
|
|
|
|
|
|
|
|
|
|
/// Sandbox error
|
|
|
|
|
|
#[error("sandbox error: {0}")]
|
|
|
|
|
|
Sandbox(#[from] SandboxErr),
|
|
|
|
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------
|
|
|
|
|
|
// Automatic conversions for common external error types
|
|
|
|
|
|
// -----------------------------------------------------------------
|
|
|
|
|
|
#[error(transparent)]
|
|
|
|
|
|
Io(#[from] io::Error),
|
|
|
|
|
|
|
|
|
|
|
|
#[error(transparent)]
|
|
|
|
|
|
Reqwest(#[from] reqwest::Error),
|
|
|
|
|
|
|
|
|
|
|
|
#[error(transparent)]
|
|
|
|
|
|
Json(#[from] serde_json::Error),
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(target_os = "linux")]
|
|
|
|
|
|
#[error(transparent)]
|
|
|
|
|
|
LandlockRuleset(#[from] landlock::RulesetError),
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(target_os = "linux")]
|
|
|
|
|
|
#[error(transparent)]
|
|
|
|
|
|
LandlockPathFd(#[from] landlock::PathFdError),
|
|
|
|
|
|
|
|
|
|
|
|
#[error(transparent)]
|
|
|
|
|
|
TokioJoin(#[from] JoinError),
|
|
|
|
|
|
|
2025-05-08 21:46:06 -07:00
|
|
|
|
#[error("{0}")]
|
|
|
|
|
|
EnvVar(EnvVarError),
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
|
pub struct EnvVarError {
|
|
|
|
|
|
/// Name of the environment variable that is missing.
|
|
|
|
|
|
pub var: String,
|
|
|
|
|
|
|
|
|
|
|
|
/// Optional instructions to help the user get a valid value for the
|
|
|
|
|
|
/// variable and set it.
|
|
|
|
|
|
pub instructions: Option<String>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl std::fmt::Display for EnvVarError {
|
|
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
|
|
write!(f, "Missing environment variable: `{}`.", self.var)?;
|
|
|
|
|
|
if let Some(instructions) = &self.instructions {
|
|
|
|
|
|
write!(f, " {instructions}")?;
|
|
|
|
|
|
}
|
|
|
|
|
|
Ok(())
|
|
|
|
|
|
}
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl CodexErr {
|
|
|
|
|
|
/// Minimal shim so that existing `e.downcast_ref::<CodexErr>()` checks continue to compile
|
|
|
|
|
|
/// after replacing `anyhow::Error` in the return signature. This mirrors the behavior of
|
|
|
|
|
|
/// `anyhow::Error::downcast_ref` but works directly on our concrete enum.
|
|
|
|
|
|
pub fn downcast_ref<T: std::any::Any>(&self) -> Option<&T> {
|
|
|
|
|
|
(self as &dyn std::any::Any).downcast_ref::<T>()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|