Skip to main content

sage_runtime/tools/
mod.rs

1//! RFC-0011: Tool implementations for Sage agents.
2//!
3//! This module provides the built-in tools that agents can use via
4//! `use ToolName` declarations and `ToolName.method()` calls.
5//!
6//! # WASM Compatibility
7//!
8//! - `HttpClient`: Works on both native and WASM (reqwest has a Fetch backend)
9//! - `DatabaseClient`: Native only (requires SQLx)
10//! - `FsClient`: Native only (requires filesystem access)
11//! - `ShellClient`: Native only (requires process spawning)
12
13#[cfg(not(target_arch = "wasm32"))]
14mod database;
15#[cfg(not(target_arch = "wasm32"))]
16mod filesystem;
17mod http;
18#[cfg(not(target_arch = "wasm32"))]
19mod shell;
20
21#[cfg(not(target_arch = "wasm32"))]
22pub use database::{DatabaseClient, DbRow};
23#[cfg(not(target_arch = "wasm32"))]
24pub use filesystem::FsClient;
25pub use http::{HttpClient, HttpResponse};
26#[cfg(not(target_arch = "wasm32"))]
27pub use shell::{ShellClient, ShellResult};
28
29// ---------------------------------------------------------------------------
30// WASM stubs for native-only tools
31// ---------------------------------------------------------------------------
32// These provide the same types so generated code compiles, but return errors
33// at runtime if invoked in the browser.
34
35#[cfg(target_arch = "wasm32")]
36mod wasm_stubs {
37    use crate::error::{SageError, SageResult};
38
39    /// A row returned from a database query.
40    #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
41    pub struct DbRow {
42        pub columns: Vec<String>,
43        pub values: Vec<String>,
44    }
45
46    /// Database client stub for WASM (not supported).
47    #[derive(Debug, Clone)]
48    pub struct DatabaseClient;
49
50    impl DatabaseClient {
51        pub fn new() -> Self {
52            Self
53        }
54
55        pub fn from_env() -> Self {
56            Self
57        }
58
59        pub async fn query(&self, _sql: String) -> SageResult<Vec<DbRow>> {
60            Err(SageError::Tool(
61                "Database tool is not available in the WASM target".to_string(),
62            ))
63        }
64
65        pub async fn execute(&self, _sql: String) -> SageResult<i64> {
66            Err(SageError::Tool(
67                "Database tool is not available in the WASM target".to_string(),
68            ))
69        }
70    }
71
72    impl Default for DatabaseClient {
73        fn default() -> Self {
74            Self::new()
75        }
76    }
77
78    /// FileSystem client stub for WASM (not supported).
79    #[derive(Debug, Clone)]
80    pub struct FsClient;
81
82    impl FsClient {
83        pub fn new() -> Self {
84            Self
85        }
86
87        pub fn from_env() -> Self {
88            Self
89        }
90
91        pub async fn read(&self, _path: String) -> SageResult<String> {
92            Err(SageError::Tool(
93                "Fs tool is not available in the WASM target".to_string(),
94            ))
95        }
96
97        pub async fn write(&self, _path: String, _content: String) -> SageResult<()> {
98            Err(SageError::Tool(
99                "Fs tool is not available in the WASM target".to_string(),
100            ))
101        }
102
103        pub async fn list(&self, _path: String) -> SageResult<Vec<String>> {
104            Err(SageError::Tool(
105                "Fs tool is not available in the WASM target".to_string(),
106            ))
107        }
108
109        pub async fn exists(&self, _path: String) -> SageResult<bool> {
110            Err(SageError::Tool(
111                "Fs tool is not available in the WASM target".to_string(),
112            ))
113        }
114    }
115
116    impl Default for FsClient {
117        fn default() -> Self {
118            Self::new()
119        }
120    }
121
122    /// Result of running a shell command.
123    #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
124    pub struct ShellResult {
125        pub exit_code: i64,
126        pub stdout: String,
127        pub stderr: String,
128    }
129
130    /// Shell client stub for WASM (not supported).
131    #[derive(Debug, Clone, Default)]
132    pub struct ShellClient;
133
134    impl ShellClient {
135        pub fn new() -> Self {
136            Self
137        }
138
139        pub fn from_env() -> Self {
140            Self
141        }
142
143        pub async fn run(&self, _command: String) -> SageResult<ShellResult> {
144            Err(SageError::Tool(
145                "Shell tool is not available in the WASM target".to_string(),
146            ))
147        }
148    }
149}
150
151#[cfg(target_arch = "wasm32")]
152pub use wasm_stubs::{DatabaseClient, DbRow, FsClient, ShellClient, ShellResult};