Skip to main content

synwire_sandbox/plugin/
context.rs

1//! Shared context for sandbox tools that need to spawn processes.
2//!
3//! [`SandboxContext`] bundles the OCI runtime, sandbox configuration, and
4//! process registry into a single shareable handle. Tools that spawn or
5//! interact with sandboxed processes (e.g., `run_command`, `open_shell`)
6//! hold an `Arc<SandboxContext>`.
7
8use std::collections::HashMap;
9use std::sync::Arc;
10
11use tokio::sync::{Mutex, RwLock};
12
13use synwire_core::agents::sandbox::SandboxConfig;
14
15use crate::process_registry::ProcessRegistry;
16use crate::visibility::ProcessVisibilityScope;
17
18use super::expect_engine::{PtyStream, StubProcess};
19
20#[cfg(target_os = "linux")]
21use crate::platform::linux::namespace::NamespaceContainer;
22
23/// An expectrl session wrapping a PTY controller fd from the OCI runtime.
24pub type ExpectSession = expectrl::Session<StubProcess, PtyStream>;
25
26/// Shared context for sandbox LLM tools.
27///
28/// Holds everything needed to spawn sandboxed processes and PTY sessions.
29/// Passed as `Arc<SandboxContext>` to tools like `run_command` and `open_shell`.
30#[derive(Debug)]
31pub struct SandboxContext {
32    /// The sandbox configuration (filesystem rules, security, resources).
33    pub config: SandboxConfig,
34    /// The process registry for this agent.
35    pub registry: Arc<RwLock<ProcessRegistry>>,
36    /// Visibility scope (own + child registries).
37    pub scope: ProcessVisibilityScope,
38    /// The OCI runtime container (Linux only).
39    #[cfg(target_os = "linux")]
40    pub container: NamespaceContainer,
41    /// Active expectrl sessions keyed by session ID.
42    /// Each session wraps a PTY controller fd and provides expect/send/batch.
43    pub(crate) sessions: Mutex<HashMap<String, ExpectSession>>,
44    /// OCI runtime child processes for active shell sessions, keyed by session ID.
45    /// Kept alive alongside the session — dropped when the session is closed.
46    #[cfg(target_os = "linux")]
47    pub(crate) session_children: Mutex<HashMap<String, tokio::process::Child>>,
48}
49
50impl SandboxContext {
51    /// Create a new sandbox context.
52    ///
53    /// # Errors
54    ///
55    /// Returns a [`crate::SandboxError`] if the OCI runtime cannot be found.
56    #[cfg(target_os = "linux")]
57    pub fn new(
58        config: SandboxConfig,
59        registry: Arc<RwLock<ProcessRegistry>>,
60        scope: ProcessVisibilityScope,
61        container: NamespaceContainer,
62    ) -> Self {
63        Self {
64            config,
65            registry,
66            scope,
67            container,
68            sessions: Mutex::new(HashMap::new()),
69            session_children: Mutex::new(HashMap::new()),
70        }
71    }
72}