Fix Bazel support for v8-backed code_mode

This commit is contained in:
pakrym-oai
2026-03-10 09:30:15 -07:00
parent 1746126881
commit 0435efbc2e
9 changed files with 79 additions and 14 deletions

View File

@@ -88,6 +88,14 @@ crate.annotation(
],
)
crate.annotation(
crate = "v8",
patch_args = ["-p1"],
patches = [
"//patches:v8_relative_prebuilt_binding_path.patch",
],
)
inject_repo(crate, "zstd")
bazel_dep(name = "bzip2", version = "1.0.8.bcr.3")

View File

@@ -236,7 +236,7 @@ regex-lite = "0.1.8"
reqwest = "0.12"
rmcp = { version = "0.15.0", default-features = false }
runfiles = { git = "https://github.com/dzbarsky/rules_rust", rev = "b56cbaa8465e74127f1ea216f813cd377295ad81" }
rusty_v8 = { package = "v8", version = "146.4.0" }
v8 = "146.4.0"
rustls = { version = "0.23", default-features = false, features = [
"ring",
"std",

View File

@@ -3,4 +3,5 @@ load("//:defs.bzl", "codex_rust_crate")
codex_rust_crate(
name = "code-mode",
crate_name = "codex_code_mode",
compile_data = ["src/code_mode_bridge.js"],
)

View File

@@ -16,4 +16,4 @@ serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
[target.'cfg(not(all(target_os = "linux", target_env = "musl")))'.dependencies]
rusty_v8 = { workspace = true }
v8 = { workspace = true }

View File

@@ -3,7 +3,6 @@ use std::sync::Once;
use crate::EnabledTool;
use crate::ToolCallHandler;
use rusty_v8 as v8;
use serde_json::Value as JsonValue;
const CODE_MODE_BOOTSTRAP_SOURCE: &str = include_str!("code_mode_bridge.js");
@@ -101,7 +100,11 @@ fn install_tool_call_binding(scope: &mut v8::PinScope<'_, '_>) -> Result<(), Str
}
}
fn run_script(scope: &mut v8::PinScope<'_, '_>, filename: &str, source: &str) -> Result<(), String> {
fn run_script(
scope: &mut v8::PinScope<'_, '_>,
filename: &str,
source: &str,
) -> Result<(), String> {
let scope = pin!(v8::TryCatch::new(scope));
let scope = &mut scope.init();
let source = v8_string(scope, source)?;
@@ -386,7 +389,10 @@ fn wait_for_module_promise(
}
fn read_content_items(scope: &mut v8::PinScope<'_, '_>) -> Result<Vec<JsonValue>, String> {
let source = v8_string(scope, "JSON.stringify(globalThis.__codexContentItems ?? [])")?;
let source = v8_string(
scope,
"JSON.stringify(globalThis.__codexContentItems ?? [])",
)?;
let script = v8::Script::compile(scope, source, None)
.ok_or_else(|| "failed to read code_mode content items".to_string())?;
let value = script
@@ -396,7 +402,8 @@ fn read_content_items(scope: &mut v8::PinScope<'_, '_>) -> Result<Vec<JsonValue>
.to_string(scope)
.ok_or_else(|| "failed to serialize code_mode content items".to_string())?
.to_rust_string_lossy(scope);
serde_json::from_str(&serialized).map_err(|err| format!("invalid code_mode content items: {err}"))
serde_json::from_str(&serialized)
.map_err(|err| format!("invalid code_mode content items: {err}"))
}
fn build_bootstrap_source(enabled_tools: &[EnabledTool]) -> Result<String, String> {
@@ -453,9 +460,7 @@ fn throw_v8_exception<'s, T>(
None
}
fn format_v8_exception(
try_catch: &mut v8::PinnedRef<'_, v8::TryCatch<v8::HandleScope>>,
) -> String {
fn format_v8_exception(try_catch: &mut v8::PinnedRef<'_, v8::TryCatch<v8::HandleScope>>) -> String {
let Some(exception) = try_catch.exception() else {
return "JavaScript execution failed".to_string();
};

View File

@@ -392,8 +392,9 @@ impl Codex {
&& let Some(reason) = codex_code_mode::unsupported_reason()
{
let _ = config.features.disable(Feature::CodeMode);
let message =
format!("Disabled `code_mode` for this session because it is unavailable: {reason}");
let message = format!(
"Disabled `code_mode` for this session because it is unavailable: {reason}"
);
warn!("{message}");
config.startup_warnings.push(message);
}

View File

@@ -11,16 +11,16 @@ use crate::tools::context::SharedTurnDiffTracker;
use crate::tools::context::ToolPayload;
use crate::tools::router::ToolCall;
use crate::tools::router::ToolCallSource;
use codex_code_mode::execute as execute_code_mode;
use codex_code_mode::EnabledTool;
use codex_code_mode::ToolKind as CodeModeToolKind;
use codex_code_mode::execute as execute_code_mode;
use codex_protocol::models::ContentItem;
use codex_protocol::models::FunctionCallOutputBody;
use codex_protocol::models::FunctionCallOutputContentItem;
use codex_protocol::models::FunctionCallOutputPayload;
use codex_protocol::models::ResponseInputItem;
use serde_json::json;
use serde_json::Value as JsonValue;
use serde_json::json;
use tokio::runtime::Handle;
use tokio::runtime::RuntimeFlavor;

View File

@@ -95,7 +95,8 @@ impl ToolsConfig {
session_source,
} = params;
let include_apply_patch_tool = features.enabled(Feature::ApplyPatchFreeform);
let include_code_mode = features.enabled(Feature::CodeMode) && codex_code_mode::is_supported();
let include_code_mode =
features.enabled(Feature::CodeMode) && codex_code_mode::is_supported();
let include_js_repl = features.enabled(Feature::JsRepl);
let include_js_repl_tools_only =
include_js_repl && features.enabled(Feature::JsReplToolsOnly);

View File

@@ -0,0 +1,49 @@
diff --git a/build.rs b/build.rs
--- a/build.rs
+++ b/build.rs
@@ -578,6 +578,16 @@
}
fn static_lib_dir() -> PathBuf {
+ if let Some(out_dir) = env::var_os("OUT_DIR") {
+ let out_dir = PathBuf::from(out_dir);
+ if out_dir
+ .components()
+ .any(|component| component.as_os_str() == "bazel-out")
+ {
+ return out_dir;
+ }
+ }
+
build_dir().join("gn_out").join("obj")
}
@@ -591,6 +601,13 @@
);
let out_dir_abs = cwd.join(out_dir);
+ if out_dir_abs
+ .components()
+ .any(|component| component.as_os_str() == "bazel-out")
+ {
+ return out_dir_abs.parent().unwrap().to_path_buf();
+ }
+
// This would be `target/debug` or `target/release`
out_dir_abs
.parent()
@@ -861,9 +878,13 @@
download_file(&url, &src_binding_path);
}
+ // `src/binding.rs` includes this path directly, so keep it relative to that
+ // source file instead of the build script's synthetic runfiles directory.
+ let include_path = Path::new("..").join("gen").join(name);
+
println!(
"cargo:rustc-env=RUSTY_V8_SRC_BINDING_PATH={}",
- src_binding_path.display()
+ include_path.display()
);
}