mirror of
https://github.com/openai/codex.git
synced 2026-11-07 20:30:33 +00:00
Run code mode exclusively through the standalone host (#36217)
## What changed - Move the V8 implementation into a dedicated `codex-code-mode-runtime` crate used by `codex-code-mode-host`, removing the embedded runtime fallback from the Codex process. - Resolve the host executable from the active installation layout and check its availability before selecting tools. - Fall back to direct tools with a one-time warning when optional code mode is unavailable. Keep `code_mode_only` and `disable_in_process_fallback` configurations fail-closed. ## Testing - Cover host discovery for standalone and package layouts, including missing hosts and symlinks. - Verify direct-tool fallback, one-time warnings, and fail-closed code-mode-only behavior. GitOrigin-RevId: 5aa3c6f1db148b2231fc24089a2ee0e2b00dbddb
This commit is contained in:
committed by
copyberry
parent
acd540f158
commit
97576b1794
@@ -33,67 +33,18 @@ use super::ProcessOwnedCodeModeSession;
|
||||
use super::ProcessOwnedCodeModeSessionProvider;
|
||||
use super::WebSocketCodeModeSessionProvider;
|
||||
use super::connection::ConnectionError;
|
||||
use super::resolve_host_program;
|
||||
use crate::NoopCodeModeSessionDelegate;
|
||||
|
||||
#[test]
|
||||
fn provider_reuses_its_live_process_host() {
|
||||
let provider = ProcessOwnedCodeModeSessionProvider::default();
|
||||
|
||||
let first = provider.process_host().expect("owned process host");
|
||||
let second = provider.process_host().expect("owned process host");
|
||||
let first = provider.process_host();
|
||||
let second = provider.process_host();
|
||||
|
||||
assert!(Arc::ptr_eq(&first, &second));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn host_program_override_takes_precedence() {
|
||||
assert_eq!(
|
||||
resolve_host_program(
|
||||
Some("custom-code-mode-host".into()),
|
||||
Ok(PathBuf::from("/opt/codex/bin/codex")),
|
||||
),
|
||||
PathBuf::from("custom-code-mode-host")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn host_program_is_next_to_the_main_executable_even_when_missing() {
|
||||
let executable_name = if cfg!(windows) {
|
||||
"codex-code-mode-host.exe"
|
||||
} else {
|
||||
"codex-code-mode-host"
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
resolve_host_program(
|
||||
/*override_path*/ None,
|
||||
Ok(PathBuf::from("/opt/codex/bin/codex")),
|
||||
),
|
||||
PathBuf::from("/opt/codex/bin").join(executable_name)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn host_program_falls_back_to_its_name_when_main_executable_is_unknown() {
|
||||
let executable_name = if cfg!(windows) {
|
||||
"codex-code-mode-host.exe"
|
||||
} else {
|
||||
"codex-code-mode-host"
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
resolve_host_program(
|
||||
/*override_path*/ None,
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::NotFound,
|
||||
"missing executable"
|
||||
)),
|
||||
),
|
||||
PathBuf::from(executable_name)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn missing_host_error_limits_the_displayed_path_to_512_bytes() {
|
||||
let executable = "codex-code-mode-host-does-not-exist";
|
||||
@@ -129,42 +80,6 @@ fn missing_host_error_preserves_utf8_boundaries_when_truncating_the_path() {
|
||||
assert!(displayed_path.len() <= 512);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn provider_falls_back_to_in_process_session_when_host_is_missing() {
|
||||
let provider = ProcessOwnedCodeModeSessionProvider::with_host_program(
|
||||
"codex-code-mode-host-does-not-exist".into(),
|
||||
);
|
||||
|
||||
let session = provider
|
||||
.create_session(Arc::new(NoopCodeModeSessionDelegate))
|
||||
.await
|
||||
.expect("missing host should fall back to an in-process session");
|
||||
let response = session
|
||||
.execute(ExecuteRequest {
|
||||
tool_call_id: "call-1".to_string(),
|
||||
enabled_tools: Vec::new(),
|
||||
source: "text('fallback')".to_string(),
|
||||
yield_time_ms: None,
|
||||
max_output_tokens: None,
|
||||
})
|
||||
.await
|
||||
.expect("execute fallback session")
|
||||
.initial_response()
|
||||
.await
|
||||
.expect("read fallback response");
|
||||
|
||||
assert_eq!(
|
||||
response,
|
||||
RuntimeResponse::Result {
|
||||
cell_id: codex_code_mode_protocol::CellId::new("1".to_string()),
|
||||
content_items: vec![FunctionCallOutputContentItem::InputText {
|
||||
text: "fallback".to_string(),
|
||||
}],
|
||||
error_text: None,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn websocket_provider_executes_over_shared_connector() {
|
||||
let listener = TcpListener::bind("127.0.0.1:0")
|
||||
@@ -310,20 +225,18 @@ async fn websocket_provider_executes_over_shared_connector() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn provider_returns_missing_host_error_when_in_process_fallback_is_disabled() {
|
||||
async fn provider_returns_missing_host_error() {
|
||||
let provider = ProcessOwnedCodeModeSessionProvider::with_host_program(
|
||||
"codex-code-mode-host-does-not-exist".into(),
|
||||
)
|
||||
.without_in_process_fallback();
|
||||
);
|
||||
|
||||
let error = provider
|
||||
.create_session(Arc::new(NoopCodeModeSessionDelegate))
|
||||
.await
|
||||
.err()
|
||||
.expect("missing host should fail when in-process fallback is disabled");
|
||||
.expect("missing host should fail");
|
||||
|
||||
assert!(error.contains("failed to spawn code-mode host codex-code-mode-host-does-not-exist"));
|
||||
assert!(provider.process_host().is_some());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
Reference in New Issue
Block a user