diff --git a/codex-rs/code-mode-runtime/src/runtime/globals.rs b/codex-rs/code-mode-runtime/src/runtime/globals.rs index 4ce226f68c..1c39bb4317 100644 --- a/codex-rs/code-mode-runtime/src/runtime/globals.rs +++ b/codex-rs/code-mode-runtime/src/runtime/globals.rs @@ -1,4 +1,3 @@ -use super::RuntimeState; use super::callbacks::audio_callback; use super::callbacks::clear_timeout_callback; use super::callbacks::exit_callback; @@ -11,16 +10,20 @@ use super::callbacks::store_callback; use super::callbacks::text_callback; use super::callbacks::tool_callback; use super::callbacks::yield_control_callback; +use codex_code_mode_protocol::EnabledToolMetadata; -pub(super) fn install_globals(scope: &mut v8::PinScope<'_, '_>) -> Result<(), String> { +pub(super) fn install_globals( + scope: &mut v8::PinScope<'_, '_>, + enabled_tools: &[EnabledToolMetadata], +) -> Result<(), String> { let global = scope.get_current_context().global(scope); delete_global(scope, global, "console")?; delete_global(scope, global, "Atomics")?; delete_global(scope, global, "SharedArrayBuffer")?; delete_global(scope, global, "WebAssembly")?; - let tools = build_tools_object(scope)?; - let all_tools = build_all_tools_value(scope)?; + let tools = build_tools_object(scope, enabled_tools)?; + let all_tools = build_all_tools_value(scope, enabled_tools)?; let clear_timeout = helper_function(scope, "clearTimeout", clear_timeout_callback)?; let set_timeout = helper_function(scope, "setTimeout", set_timeout_callback)?; let text = helper_function(scope, "text", text_callback)?; @@ -57,12 +60,9 @@ pub(super) fn install_globals(scope: &mut v8::PinScope<'_, '_>) -> Result<(), St fn build_tools_object<'s>( scope: &mut v8::PinScope<'s, '_>, + enabled_tools: &[EnabledToolMetadata], ) -> Result, String> { let tools = v8::Object::new(scope); - let enabled_tools = scope - .get_slot::() - .map(|state| state.enabled_tools.clone()) - .unwrap_or_default(); for (tool_index, tool) in enabled_tools.iter().enumerate() { let name = v8::String::new(scope, &tool.global_name) @@ -75,11 +75,8 @@ fn build_tools_object<'s>( fn build_all_tools_value<'s>( scope: &mut v8::PinScope<'s, '_>, + enabled_tools: &[EnabledToolMetadata], ) -> Result, String> { - let enabled_tools = scope - .get_slot::() - .map(|state| state.enabled_tools.clone()) - .unwrap_or_default(); let array = v8::Array::new(scope, enabled_tools.len() as i32); let name_key = v8::String::new(scope, "name") .ok_or_else(|| "failed to allocate ALL_TOOLS name key".to_string())?; diff --git a/codex-rs/code-mode-runtime/src/runtime/mod.rs b/codex-rs/code-mode-runtime/src/runtime/mod.rs index bdb667d943..ae587c0233 100644 --- a/codex-rs/code-mode-runtime/src/runtime/mod.rs +++ b/codex-rs/code-mode-runtime/src/runtime/mod.rs @@ -16,7 +16,7 @@ use codex_code_mode_protocol::CodeModeToolKind; use codex_code_mode_protocol::EnabledToolMetadata; use codex_code_mode_protocol::ExecuteRequest; use codex_code_mode_protocol::FunctionCallOutputContentItem; -use codex_code_mode_protocol::enabled_tool_metadata; +use codex_code_mode_protocol::normalize_code_mode_identifier; use codex_protocol::ToolName; use serde_json::Value as JsonValue; use tokio::sync::mpsc; @@ -94,8 +94,13 @@ pub(crate) fn spawn_runtime( let (isolate_handle_tx, isolate_handle_rx) = std_mpsc::sync_channel(1); let enabled_tools = request .enabled_tools - .iter() - .map(enabled_tool_metadata) + .into_iter() + .map(|definition| EnabledToolMetadata { + global_name: normalize_code_mode_identifier(&definition.name), + tool_name: definition.tool_name, + description: definition.description, + kind: definition.kind, + }) .collect::>(); let config = RuntimeConfig { tool_call_id: request.tool_call_id, @@ -147,13 +152,19 @@ struct RuntimeConfig { stored_values: HashMap>, } +// Callback indices refer to this cell's original catalog for its entire lifetime. +struct ToolCallbackMetadata { + tool_name: ToolName, + kind: CodeModeToolKind, +} + pub(super) struct RuntimeState { event_tx: mpsc::UnboundedSender, pending_tool_calls: HashMap>, pending_timeouts: HashMap, stored_values: HashMap>, stored_value_writes: HashMap>, - enabled_tools: Vec, + enabled_tools: Vec, next_tool_call_id: u64, next_timeout_id: u64, tool_call_id: String, @@ -189,13 +200,25 @@ fn run_runtime( let context = v8::Context::new(scope, Default::default()); let scope = &mut v8::ContextScope::new(scope, context); + if let Err(error_text) = globals::install_globals(scope, &config.enabled_tools) { + send_result(&event_tx, HashMap::new(), Some(error_text)); + return; + } + scope.set_slot(RuntimeState { event_tx: event_tx.clone(), pending_tool_calls: HashMap::new(), pending_timeouts: HashMap::new(), stored_values: config.stored_values, stored_value_writes: HashMap::new(), - enabled_tools: config.enabled_tools, + enabled_tools: config + .enabled_tools + .into_iter() + .map(|tool| ToolCallbackMetadata { + tool_name: tool.tool_name, + kind: tool.kind, + }) + .collect(), next_tool_call_id: 1, next_timeout_id: 1, tool_call_id: config.tool_call_id, @@ -203,11 +226,6 @@ fn run_runtime( exit_requested: false, }); - if let Err(error_text) = globals::install_globals(scope) { - send_result(&event_tx, HashMap::new(), Some(error_text)); - return; - } - let _ = event_tx.send(RuntimeEvent::Started); let pending_promise = match module_loader::evaluate_main_module(scope, &config.source) { diff --git a/codex-rs/ext/extension-api/tests/registry.rs b/codex-rs/ext/extension-api/tests/registry.rs index 90c6bad8b9..818ac8b80f 100644 --- a/codex-rs/ext/extension-api/tests/registry.rs +++ b/codex-rs/ext/extension-api/tests/registry.rs @@ -77,6 +77,7 @@ fn mcp_context_preserves_selected_executor_order_and_unavailability() { environment_id: "starting-primary".to_owned(), cwd: PathUri::parse("file:///workspace").expect("workspace URI"), workspace_roots: Vec::new(), + selected_capability_roots: Default::default(), config: EnvironmentConfigState::Pending, selected_capability_roots: Default::default(), }, @@ -84,6 +85,7 @@ fn mcp_context_preserves_selected_executor_order_and_unavailability() { environment_id: "ready-secondary".to_owned(), cwd: PathUri::parse("file:///other").expect("workspace URI"), workspace_roots: Vec::new(), + selected_capability_roots: Default::default(), config: EnvironmentConfigState::FromThread, selected_capability_roots: Default::default(), },