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}