use super::RuntimeState;use super::callbacks::clear_timeout_callback;use super::callbacks::exit_callback;use super::callbacks::generated_image_callback;use super::callbacks::image_callback;use super::callbacks::load_callback;use super::callbacks::notify_callback;use super::callbacks::set_timeout_callback;use super::callbacks::store_callback;use super::callbacks::text_callback;use super::callbacks::tool_callback;use super::callbacks::yield_control_callback;pub(super) fn install_globals(scope: &mut v8::PinScope<'_, '_>) -> 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 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)?; let image = helper_function(scope, "image", image_callback)?; let generated_image = helper_function(scope, "generatedImage", generated_image_callback)?; let store = helper_function(scope, "store", store_callback)?; let load = helper_function(scope, "load", load_callback)?; let notify = helper_function(scope, "notify", notify_callback)?; let yield_control = helper_function(scope, "yield_control", yield_control_callback)?; let exit = helper_function(scope, "exit", exit_callback)?; set_global(scope, global, "tools", tools.into())?; set_global(scope, global, "ALL_TOOLS", all_tools)?; set_global(scope, global, "clearTimeout", clear_timeout.into())?; set_global(scope, global, "setTimeout", set_timeout.into())?; set_global(scope, global, "text", text.into())?; set_global(scope, global, "image", image.into())?; set_global(scope, global, "generatedImage", generated_image.into())?; set_global(scope, global, "store", store.into())?; set_global(scope, global, "load", load.into())?; set_global(scope, global, "notify", notify.into())?; set_global(scope, global, "yield_control", yield_control.into())?; set_global(scope, global, "exit", exit.into())?; Ok(())}fn build_tools_object<'s>( scope: &mut v8::PinScope<'s, '_>,) -> Result<v8::Local<'s, v8::Object>, String> { let tools = v8::Object::new(scope); let enabled_tools = scope .get_slot::<RuntimeState>() .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) .ok_or_else(|| "failed to allocate tool name".to_string())?; let function = tool_function(scope, tool_index)?; tools.set(scope, name.into(), function.into()); } Ok(tools)}fn build_all_tools_value<'s>( scope: &mut v8::PinScope<'s, '_>,) -> Result<v8::Local<'s, v8::Value>, String> { let enabled_tools = scope .get_slot::<RuntimeState>() .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())?; let description_key = v8::String::new(scope, "description") .ok_or_else(|| "failed to allocate ALL_TOOLS description key".to_string())?; for (index, tool) in enabled_tools.iter().enumerate() { let item = v8::Object::new(scope); let name = v8::String::new(scope, &tool.global_name) .ok_or_else(|| "failed to allocate ALL_TOOLS name".to_string())?; let description = v8::String::new(scope, &tool.description) .ok_or_else(|| "failed to allocate ALL_TOOLS description".to_string())?; if item.set(scope, name_key.into(), name.into()) != Some(true) { return Err("failed to set ALL_TOOLS name".to_string()); } if item.set(scope, description_key.into(), description.into()) != Some(true) { return Err("failed to set ALL_TOOLS description".to_string()); } if array.set_index(scope, index as u32, item.into()) != Some(true) { return Err("failed to append ALL_TOOLS metadata".to_string()); } } Ok(array.into())}fn helper_function<'s, F>( scope: &mut v8::PinScope<'s, '_>, name: &str, callback: F,) -> Result<v8::Local<'s, v8::Function>, String>where F: v8::MapFnTo<v8::FunctionCallback>,{ let name = v8::String::new(scope, name).ok_or_else(|| "failed to allocate helper name".to_string())?; let template = v8::FunctionTemplate::builder(callback) .data(name.into()) .build(scope); template .get_function(scope) .ok_or_else(|| "failed to create helper function".to_string())}fn tool_function<'s>( scope: &mut v8::PinScope<'s, '_>, tool_index: usize,) -> Result<v8::Local<'s, v8::Function>, String> { let data = v8::String::new(scope, &tool_index.to_string()) .ok_or_else(|| "failed to allocate tool callback data".to_string())?; let template = v8::FunctionTemplate::builder(tool_callback) .data(data.into()) .build(scope); template .get_function(scope) .ok_or_else(|| "failed to create tool function".to_string())}fn set_global<'s>( scope: &mut v8::PinScope<'s, '_>, global: v8::Local<'s, v8::Object>, name: &str, value: v8::Local<'s, v8::Value>,) -> Result<(), String> { let key = v8::String::new(scope, name) .ok_or_else(|| format!("failed to allocate global `{name}`"))?; if global.set(scope, key.into(), value) == Some(true) { Ok(()) } else { Err(format!("failed to set global `{name}`")) }}fn delete_global<'s>( scope: &mut v8::PinScope<'s, '_>, global: v8::Local<'s, v8::Object>, name: &str,) -> Result<(), String> { let key = v8::String::new(scope, name) .ok_or_else(|| format!("failed to allocate global `{name}`"))?; if global.delete(scope, key.into()) == Some(true) { Ok(()) } else { Err(format!("failed to remove global `{name}`")) }}