mirror of
https://github.com/openai/codex.git
synced 2026-11-08 20:40: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
@@ -76,9 +76,11 @@ pub(crate) struct ExecContext {
|
||||
pub(crate) struct CodeModeService {
|
||||
session: OnceCell<Arc<dyn CodeModeSession>>,
|
||||
session_provider: Arc<dyn CodeModeSessionProvider>,
|
||||
availability: Result<(), String>,
|
||||
dispatch_broker: Arc<CodeModeDispatchBroker>,
|
||||
default_exec_yield_time_override_ms: Option<u64>,
|
||||
shutting_down: AtomicBool,
|
||||
unavailable_warning_emitted: AtomicBool,
|
||||
}
|
||||
|
||||
impl CodeModeService {
|
||||
@@ -87,15 +89,38 @@ impl CodeModeService {
|
||||
features: &Features,
|
||||
) -> Self {
|
||||
let dispatch_broker = Arc::new(CodeModeDispatchBroker::new());
|
||||
let availability = session_provider.availability();
|
||||
Self {
|
||||
session: OnceCell::new(),
|
||||
session_provider,
|
||||
availability,
|
||||
dispatch_broker,
|
||||
default_exec_yield_time_override_ms: default_exec_yield_time_override_ms(features),
|
||||
shutting_down: AtomicBool::new(false),
|
||||
unavailable_warning_emitted: AtomicBool::new(false),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn is_available(&self) -> bool {
|
||||
self.availability.is_ok()
|
||||
}
|
||||
|
||||
pub(crate) fn take_unavailable_warning(&self, tool_mode: ToolMode) -> Option<String> {
|
||||
let error = self.availability.as_ref().err()?;
|
||||
let behavior = match tool_mode {
|
||||
ToolMode::Direct => "Falling back to direct tools",
|
||||
ToolMode::CodeMode | ToolMode::CodeModeOnly => "Code mode will fail closed",
|
||||
};
|
||||
(!self
|
||||
.unavailable_warning_emitted
|
||||
.swap(true, Ordering::Relaxed))
|
||||
.then(|| {
|
||||
format!(
|
||||
"Code Mode is unavailable because {error}. {behavior}; enable `features.code_mode_host` and install `codex-code-mode-host`."
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn session_provider(&self) -> Arc<dyn CodeModeSessionProvider> {
|
||||
Arc::clone(&self.session_provider)
|
||||
}
|
||||
@@ -378,18 +403,10 @@ fn build_freeform_tool_payload(
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::CodeModeService;
|
||||
use super::build_nested_tool_payload;
|
||||
use super::truncate_code_mode_result;
|
||||
use crate::tools::context::ToolPayload;
|
||||
use codex_code_mode::CodeModeToolKind;
|
||||
use codex_code_mode::ExecuteRequest;
|
||||
use codex_code_mode::FunctionCallOutputContentItem as CodeModeOutputContentItem;
|
||||
use codex_code_mode::ProcessOwnedCodeModeSessionProvider;
|
||||
use codex_code_mode::RuntimeResponse;
|
||||
use codex_features::Features;
|
||||
use codex_protocol::models::FunctionCallOutputContentItem;
|
||||
use codex_tools::ToolName;
|
||||
use serde_json::json;
|
||||
@@ -460,40 +477,4 @@ mod tests {
|
||||
}]
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn missing_process_host_falls_back_to_in_process_session() {
|
||||
let service = CodeModeService::new(
|
||||
Arc::new(ProcessOwnedCodeModeSessionProvider::with_host_program(
|
||||
"codex-code-mode-host-does-not-exist".into(),
|
||||
)),
|
||||
&Features::with_defaults(),
|
||||
);
|
||||
|
||||
let response = service
|
||||
.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("missing host should fall back to an in-process session")
|
||||
.initial_response()
|
||||
.await
|
||||
.expect("read fallback response");
|
||||
|
||||
assert_eq!(
|
||||
response,
|
||||
RuntimeResponse::Result {
|
||||
cell_id: codex_code_mode::CellId::new("1".to_string()),
|
||||
content_items: vec![CodeModeOutputContentItem::InputText {
|
||||
text: "fallback".to_string(),
|
||||
}],
|
||||
error_text: None,
|
||||
}
|
||||
);
|
||||
service.shutdown().await.expect("shutdown service");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user