openfunctions_rs/runtime/mod.rs
1//! Runtime for executing tools and agent functions.
2//!
3//! This module provides the `Runtime`, which is responsible for safely
4//! executing tools in a sandboxed environment. It manages the execution
5//! lifecycle, including setting up the environment, invoking the tool,
6//! and capturing the results.
7
8use crate::core::{Config, Registry, Tool};
9use crate::models::{ExecutionResult, FunctionCall};
10use anyhow::Result;
11use tracing::info;
12
13pub mod environment;
14pub mod executor;
15pub mod sandbox;
16
17pub use environment::Environment;
18pub use executor::Executor;
19pub use sandbox::Sandbox;
20
21/// The runtime for executing tools.
22///
23/// The `Runtime` orchestrates the execution of tools, using an `Executor`
24/// to run the tool's code in a controlled `Sandbox` with a prepared
25/// `Environment`.
26pub struct Runtime {
27 #[allow(dead_code)]
28 config: Config,
29 // TODO: executor: executor::Executor,
30}
31
32impl Runtime {
33 /// Creates a new `Runtime` with the given configuration.
34 pub fn new(config: Config) -> Self {
35 Self {
36 config,
37 // TODO: executor: executor::Executor::new(&config.runtime),
38 }
39 }
40
41 /// Executes a tool with the given arguments.
42 ///
43 /// # Arguments
44 /// * `tool` - The tool to execute.
45 /// * `args` - The arguments for the tool, as a JSON value.
46 pub async fn execute_tool(
47 &self,
48 tool: &Tool,
49 args: serde_json::Value,
50 ) -> Result<ExecutionResult> {
51 info!(tool = %tool.name, args = ?args, "Executing tool");
52 // TODO: Implement the full execution logic.
53 // This will involve:
54 // 1. Creating an environment for the execution.
55 // 2. Preparing the arguments.
56 // 3. Using the executor to run the tool in a sandbox.
57 // 4. Capturing and returning the ExecutionResult.
58
59 let start_time = std::time::Instant::now();
60
61 Ok(ExecutionResult {
62 success: true,
63 output: "Executing tool... (not yet implemented)".to_string(),
64 error: None,
65 duration: start_time.elapsed(),
66 metadata: std::collections::HashMap::new(),
67 })
68 }
69
70 /// Executes a function call request.
71 ///
72 /// This is a convenience method that looks up the tool in the registry
73 /// and then calls `execute_tool`.
74 ///
75 /// # Arguments
76 /// * `call` - The `FunctionCall` request.
77 /// * `registry` - The `Registry` to look up the tool in.
78 pub async fn execute_function_call(
79 &self,
80 call: &FunctionCall,
81 registry: &Registry,
82 ) -> Result<ExecutionResult> {
83 info!(function_name = %call.name, "Executing function call");
84 let tool = registry
85 .get_tool(&call.name)
86 .ok_or_else(|| anyhow::anyhow!("Tool not found: {}", call.name))?;
87
88 self.execute_tool(tool, call.arguments.clone()).await
89 }
90}