Add setTimeout support to code mode (#16153)

The implementation is less than ideal - it starts a thread per timer. A
better approach might be to switch to tokio and use their timer
imlementation.
This commit is contained in:
pakrym-oai
2026-04-06 17:46:28 -07:00
committed by GitHub
Unverified
parent 1f2411629f
commit 0de7662dab
6 changed files with 261 additions and 1 deletions
+24 -1
View File
@@ -1,6 +1,7 @@
mod callbacks;
mod globals;
mod module_loader;
mod timers;
mod value;
use std::collections::HashMap;
@@ -75,6 +76,7 @@ pub(crate) enum TurnMessage {
pub(crate) enum RuntimeCommand {
ToolResponse { id: String, result: JsonValue },
ToolError { id: String, error_text: String },
TimeoutFired { id: u64 },
Terminate,
}
@@ -103,6 +105,7 @@ pub(crate) fn spawn_runtime(
event_tx: mpsc::UnboundedSender<RuntimeEvent>,
) -> Result<(std_mpsc::Sender<RuntimeCommand>, v8::IsolateHandle), String> {
let (command_tx, command_rx) = std_mpsc::channel();
let runtime_command_tx = command_tx.clone();
let (isolate_handle_tx, isolate_handle_rx) = std_mpsc::sync_channel(1);
let enabled_tools = request
.enabled_tools
@@ -117,7 +120,13 @@ pub(crate) fn spawn_runtime(
};
thread::spawn(move || {
run_runtime(config, event_tx, command_rx, isolate_handle_tx);
run_runtime(
config,
event_tx,
command_rx,
isolate_handle_tx,
runtime_command_tx,
);
});
let isolate_handle = isolate_handle_rx
@@ -137,10 +146,13 @@ struct RuntimeConfig {
pub(super) struct RuntimeState {
event_tx: mpsc::UnboundedSender<RuntimeEvent>,
pending_tool_calls: HashMap<String, v8::Global<v8::PromiseResolver>>,
pending_timeouts: HashMap<u64, timers::ScheduledTimeout>,
stored_values: HashMap<String, JsonValue>,
enabled_tools: Vec<EnabledToolMetadata>,
next_tool_call_id: u64,
next_timeout_id: u64,
tool_call_id: String,
runtime_command_tx: std_mpsc::Sender<RuntimeCommand>,
exit_requested: bool,
}
@@ -168,6 +180,7 @@ fn run_runtime(
event_tx: mpsc::UnboundedSender<RuntimeEvent>,
command_rx: std_mpsc::Receiver<RuntimeCommand>,
isolate_handle_tx: std_mpsc::SyncSender<v8::IsolateHandle>,
runtime_command_tx: std_mpsc::Sender<RuntimeCommand>,
) {
initialize_v8();
@@ -185,10 +198,13 @@ fn run_runtime(
scope.set_slot(RuntimeState {
event_tx: event_tx.clone(),
pending_tool_calls: HashMap::new(),
pending_timeouts: HashMap::new(),
stored_values: config.stored_values,
enabled_tools: config.enabled_tools,
next_tool_call_id: 1,
next_timeout_id: 1,
tool_call_id: config.tool_call_id,
runtime_command_tx,
exit_requested: false,
});
@@ -223,6 +239,7 @@ fn run_runtime(
let Ok(command) = command_rx.recv() else {
break;
};
match command {
RuntimeCommand::Terminate => break,
RuntimeCommand::ToolResponse { id, result } => {
@@ -241,6 +258,12 @@ fn run_runtime(
return;
}
}
RuntimeCommand::TimeoutFired { id } => {
if let Err(runtime_error) = timers::invoke_timeout_callback(scope, id) {
capture_scope_send_error(scope, &event_tx, Some(runtime_error));
return;
}
}
}
scope.perform_microtask_checkpoint();