Skip to main content

rustyclaw_core/runtime/
native.rs

1//! Native runtime implementation.
2//!
3//! Full-access runtime for Mac/Linux/Windows with shell, filesystem, and
4//! long-running process support.
5//!
6//! Adapted from ZeroClaw (MIT OR Apache-2.0 licensed).
7
8use super::traits::RuntimeAdapter;
9use std::path::{Path, PathBuf};
10
11/// Native runtime — full access, runs on Mac/Linux/Windows/Raspberry Pi
12pub struct NativeRuntime;
13
14impl NativeRuntime {
15    pub fn new() -> Self {
16        Self
17    }
18}
19
20impl Default for NativeRuntime {
21    fn default() -> Self {
22        Self::new()
23    }
24}
25
26impl RuntimeAdapter for NativeRuntime {
27    fn name(&self) -> &str {
28        "native"
29    }
30
31    fn has_shell_access(&self) -> bool {
32        true
33    }
34
35    fn has_filesystem_access(&self) -> bool {
36        true
37    }
38
39    fn storage_path(&self) -> PathBuf {
40        directories::UserDirs::new().map_or_else(
41            || PathBuf::from(".rustyclaw"),
42            |u| u.home_dir().join(".rustyclaw"),
43        )
44    }
45
46    fn supports_long_running(&self) -> bool {
47        true
48    }
49
50    fn build_shell_command(
51        &self,
52        command: &str,
53        workspace_dir: &Path,
54    ) -> anyhow::Result<tokio::process::Command> {
55        #[cfg(unix)]
56        {
57            let mut process = tokio::process::Command::new("sh");
58            process.arg("-c").arg(command).current_dir(workspace_dir);
59            Ok(process)
60        }
61        #[cfg(windows)]
62        {
63            let mut process = tokio::process::Command::new("cmd");
64            process.arg("/C").arg(command).current_dir(workspace_dir);
65            Ok(process)
66        }
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73
74    #[test]
75    fn native_name() {
76        assert_eq!(NativeRuntime::new().name(), "native");
77    }
78
79    #[test]
80    fn native_has_shell_access() {
81        assert!(NativeRuntime::new().has_shell_access());
82    }
83
84    #[test]
85    fn native_has_filesystem_access() {
86        assert!(NativeRuntime::new().has_filesystem_access());
87    }
88
89    #[test]
90    fn native_supports_long_running() {
91        assert!(NativeRuntime::new().supports_long_running());
92    }
93
94    #[test]
95    fn native_memory_budget_unlimited() {
96        assert_eq!(NativeRuntime::new().memory_budget(), 0);
97    }
98
99    #[test]
100    fn native_storage_path_contains_rustyclaw() {
101        let path = NativeRuntime::new().storage_path();
102        assert!(path.to_string_lossy().contains("rustyclaw"));
103    }
104
105    #[test]
106    fn native_builds_shell_command() {
107        let cwd = std::env::temp_dir();
108        let command = NativeRuntime::new()
109            .build_shell_command("echo hello", &cwd)
110            .unwrap();
111        let debug = format!("{command:?}");
112        assert!(debug.contains("echo hello"));
113    }
114}