Author: Danny Milosavljevic Date: 2026-07-11 License: ASL2.0 Subject: Disable V8 support in codex-code-mode. The V8 engine is only needed for actually executing JavaScript in the code-mode sandbox. Upstream's code-mode crate depends on v8 and deno_core_icudata unconditionally, and the V8 build downloads a large prebuilt archive at build time. Gate the V8-backed implementation behind a disabled "v8-runtime" feature, remove the unvendored V8 dependencies, and provide stub session providers. diff --git a/codex-rs/code-mode/Cargo.toml b/codex-rs/code-mode/Cargo.toml index 011fee6..4242afb 100644 --- a/codex-rs/code-mode/Cargo.toml +++ b/codex-rs/code-mode/Cargo.toml @@ -10,7 +10,9 @@ name = "codex_code_mode" path = "src/lib.rs" [features] -sandbox = ["v8/v8_enable_sandbox"] +default = [] +v8-runtime = [] +sandbox = [] [lints] workspace = true @@ -18,13 +20,11 @@ workspace = true [dependencies] codex-code-mode-protocol = { workspace = true } codex-protocol = { workspace = true } -deno_core_icudata = { workspace = true } futures = { workspace = true } serde_json = { workspace = true } tokio = { workspace = true, features = ["io-util", "macros", "process", "rt", "sync", "time"] } tokio-util = { workspace = true, features = ["rt"] } tracing = { workspace = true } -v8 = { workspace = true } [dev-dependencies] pretty_assertions = { workspace = true } diff --git a/codex-rs/code-mode/src/lib.rs b/codex-rs/code-mode/src/lib.rs index 6d332bf..b161369 100644 --- a/codex-rs/code-mode/src/lib.rs +++ b/codex-rs/code-mode/src/lib.rs @@ -1,17 +1,254 @@ +#[cfg(feature = "v8-runtime")] mod cell_actor; +#[cfg(feature = "v8-runtime")] mod remote_session; +#[cfg(feature = "v8-runtime")] mod runtime; +#[cfg(feature = "v8-runtime")] mod service; +#[cfg(feature = "v8-runtime")] mod session_runtime; +#[cfg(feature = "v8-runtime")] mod v8_init; +#[cfg(feature = "v8-runtime")] pub(crate) type TaskFailureHandler = std::sync::Arc; pub use codex_code_mode_protocol::*; +#[cfg(feature = "v8-runtime")] pub use remote_session::ProcessOwnedCodeModeSession; +#[cfg(feature = "v8-runtime")] pub use remote_session::ProcessOwnedCodeModeSessionProvider; +#[cfg(feature = "v8-runtime")] pub use service::InProcessCodeModeSession; +#[cfg(feature = "v8-runtime")] pub use service::InProcessCodeModeSessionProvider; +#[cfg(feature = "v8-runtime")] pub use service::NoopCodeModeSessionDelegate; +#[cfg(feature = "v8-runtime")] pub use v8_init::V8JitMode; +#[cfg(feature = "v8-runtime")] pub use v8_init::initialize_v8; + +// Stubs used when the v8-runtime feature is disabled. Consumers that only +// touch the protocol types can build without pulling in v8. Calling +// execute/wait/terminate on a stub session returns an error. +#[cfg(not(feature = "v8-runtime"))] +mod stub { + use std::path::PathBuf; + use std::sync::Arc; + + use codex_code_mode_protocol::{ + CellId, CodeModeSession, CodeModeSessionDelegate, CodeModeSessionProvider, + CodeModeSessionProviderFuture, CodeModeSessionResultFuture, ExecuteRequest, StartedCell, + WaitOutcome, WaitRequest, + }; + + const DISABLED: &str = "code mode is disabled (built without v8-runtime)"; + + pub struct NoopCodeModeSessionDelegate; + + impl CodeModeSessionDelegate for NoopCodeModeSessionDelegate { + fn invoke_tool<'a>( + &'a self, + _invocation: codex_code_mode_protocol::CodeModeNestedToolCall, + _cancellation_token: tokio_util::sync::CancellationToken, + ) -> codex_code_mode_protocol::ToolInvocationFuture<'a> { + Box::pin(async { Err(DISABLED.into()) }) + } + + fn notify<'a>( + &'a self, + _call_id: String, + _cell_id: CellId, + _text: String, + _cancellation_token: tokio_util::sync::CancellationToken, + ) -> codex_code_mode_protocol::NotificationFuture<'a> { + Box::pin(async { Ok(()) }) + } + + fn cell_closed(&self, _cell_id: &CellId) {} + } + + #[derive(Default)] + pub struct InProcessCodeModeSessionProvider; + + impl CodeModeSessionProvider for InProcessCodeModeSessionProvider { + fn create_session<'a>( + &'a self, + _delegate: Arc, + ) -> CodeModeSessionProviderFuture<'a> { + Box::pin(async { + let session: Arc = Arc::new(InProcessCodeModeSession); + Ok(session) + }) + } + } + + pub struct InProcessCodeModeSession; + + impl InProcessCodeModeSession { + pub fn new() -> Self { + Self + } + + pub fn with_delegate(_delegate: Arc) -> Self { + Self + } + + pub fn with_delegate_and_task_failure_handler( + _delegate: Arc, + _task_failure_handler: Arc, + ) -> Self { + Self + } + + pub async fn execute(&self, _request: ExecuteRequest) -> Result { + Err(DISABLED.into()) + } + + pub async fn wait(&self, _request: WaitRequest) -> Result { + Err(DISABLED.into()) + } + + pub async fn terminate(&self, _cell_id: CellId) -> Result { + Err(DISABLED.into()) + } + + pub async fn shutdown(&self) -> Result<(), String> { + Ok(()) + } + } + + impl Default for InProcessCodeModeSession { + fn default() -> Self { + Self::new() + } + } + + impl CodeModeSession for InProcessCodeModeSession { + fn execute<'a>( + &'a self, + request: ExecuteRequest, + ) -> CodeModeSessionResultFuture<'a, StartedCell> { + Box::pin(InProcessCodeModeSession::execute(self, request)) + } + + fn wait<'a>( + &'a self, + request: WaitRequest, + ) -> CodeModeSessionResultFuture<'a, WaitOutcome> { + Box::pin(InProcessCodeModeSession::wait(self, request)) + } + + fn terminate<'a>( + &'a self, + cell_id: CellId, + ) -> CodeModeSessionResultFuture<'a, WaitOutcome> { + Box::pin(InProcessCodeModeSession::terminate(self, cell_id)) + } + + fn shutdown<'a>(&'a self) -> CodeModeSessionResultFuture<'a, ()> { + Box::pin(InProcessCodeModeSession::shutdown(self)) + } + } + + #[derive(Default)] + pub struct ProcessOwnedCodeModeSessionProvider; + + impl ProcessOwnedCodeModeSessionProvider { + pub fn with_host_program(_host_program: PathBuf) -> Self { + Self + } + } + + impl CodeModeSessionProvider for ProcessOwnedCodeModeSessionProvider { + fn create_session<'a>( + &'a self, + _delegate: Arc, + ) -> CodeModeSessionProviderFuture<'a> { + Box::pin(async { + let session: Arc = Arc::new(ProcessOwnedCodeModeSession); + Ok(session) + }) + } + } + + pub struct ProcessOwnedCodeModeSession; + + impl ProcessOwnedCodeModeSession { + pub fn new() -> Self { + Self + } + + pub async fn execute(&self, _request: ExecuteRequest) -> Result { + Err(DISABLED.into()) + } + + pub async fn wait(&self, _request: WaitRequest) -> Result { + Err(DISABLED.into()) + } + + pub async fn terminate(&self, _cell_id: CellId) -> Result { + Err(DISABLED.into()) + } + + pub async fn shutdown(&self) -> Result<(), String> { + Ok(()) + } + } + + impl Default for ProcessOwnedCodeModeSession { + fn default() -> Self { + Self::new() + } + } + + impl CodeModeSession for ProcessOwnedCodeModeSession { + fn execute<'a>( + &'a self, + request: ExecuteRequest, + ) -> CodeModeSessionResultFuture<'a, StartedCell> { + Box::pin(ProcessOwnedCodeModeSession::execute(self, request)) + } + + fn wait<'a>( + &'a self, + request: WaitRequest, + ) -> CodeModeSessionResultFuture<'a, WaitOutcome> { + Box::pin(ProcessOwnedCodeModeSession::wait(self, request)) + } + + fn terminate<'a>( + &'a self, + cell_id: CellId, + ) -> CodeModeSessionResultFuture<'a, WaitOutcome> { + Box::pin(ProcessOwnedCodeModeSession::terminate(self, cell_id)) + } + + fn shutdown<'a>(&'a self) -> CodeModeSessionResultFuture<'a, ()> { + Box::pin(ProcessOwnedCodeModeSession::shutdown(self)) + } + } + + pub enum V8JitMode { + Enabled, + Disabled, + } + + impl V8JitMode { + pub fn as_str(&self) -> &'static str { + match self { + Self::Enabled => "enabled", + Self::Disabled => "disabled", + } + } + } + + pub fn initialize_v8(_jit_mode: V8JitMode) -> Result<(), String> { + Err(DISABLED.into()) + } +} + +#[cfg(not(feature = "v8-runtime"))] +pub use stub::*;