Skip to main content

construct/runtime/
native.rs

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