Skip to content

Commit e4eedd6

Browse files
ccongercodex
andauthored
Code mode on v8 (#15276)
Moves Code Mode to a new crate with no dependencies on codex. This create encodes the code mode semantics that we want for lifetime, mounting, tool calling. The model-facing surface is mostly unchanged. `exec` still runs raw JavaScript, `wait` still resumes or terminates a `cell_id`, nested tools are still available through `tools.*`, and helpers like `text`, `image`, `store`, `load`, `notify`, `yield_control`, and `exit` still exist. The major change is underneath that surface: - Old code mode was an external Node runtime. - New code mode is an in-process V8 runtime embedded directly in Rust. - Old code mode managed cells inside a long-lived Node runner process. - New code mode manages cells in Rust, with one V8 runtime thread per active `exec`. - Old code mode used JSON protocol messages over child stdin/stdout plus Node worker-thread messages. - New code mode uses Rust channels and direct V8 callbacks/events. This PR also fixes the two migration regressions that fell out of that substrate change: - `wait { terminate: true }` now waits for the V8 runtime to actually stop before reporting termination. - synchronous top-level `exit()` now succeeds again instead of surfacing as a script error. --- - `core/src/tools/code_mode/*` is now mostly an adapter layer for the public `exec` / `wait` tools. - `code-mode/src/service.rs` owns cell sessions and async control flow in Rust. - `code-mode/src/runtime/*.rs` owns the embedded V8 isolate and JavaScript execution. - each `exec` spawns a dedicated runtime thread plus a Rust session-control task. - helper globals are installed directly into the V8 context instead of being injected through a source prelude. - helper modules like `tools.js` and `@openai/code_mode` are synthesized through V8 module resolution callbacks in Rust. --- Also added a benchmark for showing the speed of init and use of a code mode env: ``` $ cargo bench -p codex-code-mode --bench exec_overhead -- --samples 30 --warm-iterations 25 --tool-counts 0,32,128 Finished [`bench` profile [optimized]](https://doc.rust-lang.org/cargo/reference/profiles.html#default-profiles) target(s) in 0.18s Running benches/exec_overhead.rs (target/release/deps/exec_overhead-008c440d800545ae) exec_overhead: samples=30, warm_iterations=25, tool_counts=[0, 32, 128] scenario tools samples warmups iters mean/exec p95/exec rssΔ p50 rssΔ max cold_exec 0 30 0 1 1.13ms 1.20ms 8.05MiB 8.06MiB warm_exec 0 30 1 25 473.43us 512.49us 912.00KiB 1.33MiB cold_exec 32 30 0 1 1.03ms 1.15ms 8.08MiB 8.11MiB warm_exec 32 30 1 25 509.73us 545.76us 960.00KiB 1.30MiB cold_exec 128 30 0 1 1.14ms 1.19ms 8.30MiB 8.34MiB warm_exec 128 30 1 25 575.08us 591.03us 736.00KiB 864.00KiB memory uses a fresh-process max RSS delta for each scenario ``` --------- Co-authored-by: Codex <noreply@openai.com>
1 parent ec32866 commit e4eedd6

31 files changed

+2728
-2263
lines changed

codex-rs/Cargo.lock

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

codex-rs/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ members = [
1313
"feedback",
1414
"features",
1515
"codex-backend-openapi-models",
16+
"code-mode",
1617
"cloud-requirements",
1718
"cloud-tasks",
1819
"cloud-tasks-client",
@@ -91,6 +92,7 @@ app_test_support = { path = "app-server/tests/common" }
9192
codex-ansi-escape = { path = "ansi-escape" }
9293
codex-api = { path = "codex-api" }
9394
codex-artifacts = { path = "artifacts" }
95+
codex-code-mode = { path = "code-mode" }
9496
codex-package-manager = { path = "package-manager" }
9597
codex-app-server = { path = "app-server" }
9698
codex-app-server-client = { path = "app-server-client" }
@@ -374,7 +376,7 @@ ignored = [
374376
"openssl-sys",
375377
"codex-utils-readiness",
376378
"codex-secrets",
377-
"codex-v8-poc"
379+
"codex-v8-poc",
378380
]
379381

380382
[profile.release]

codex-rs/code-mode/BUILD.bazel

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
load("//:defs.bzl", "codex_rust_crate")
2+
3+
codex_rust_crate(
4+
name = "code-mode",
5+
crate_name = "codex_code_mode",
6+
)

codex-rs/code-mode/Cargo.toml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
[package]
2+
edition.workspace = true
3+
license.workspace = true
4+
name = "codex-code-mode"
5+
version.workspace = true
6+
7+
[lib]
8+
doctest = false
9+
name = "codex_code_mode"
10+
path = "src/lib.rs"
11+
12+
[lints]
13+
workspace = true
14+
15+
[dependencies]
16+
async-trait = { workspace = true }
17+
serde = { workspace = true, features = ["derive"] }
18+
serde_json = { workspace = true }
19+
tokio = { workspace = true, features = ["macros", "rt", "sync", "time"] }
20+
tokio-util = { workspace = true, features = ["rt"] }
21+
tracing = { workspace = true }
22+
v8 = { workspace = true }
23+
24+
[dev-dependencies]
25+
pretty_assertions = { workspace = true }

0 commit comments

Comments
 (0)