use std::sync::Arc;
use serde::Serialize;
use tokio::sync::RwLock;
use synwire_core::agents::agent_node::Agent;
use synwire_core::agents::sandbox::SandboxConfig;
use synwire_sandbox::plugin::process_plugin::ProcessPlugin;
use synwire_sandbox::process_registry::ProcessRegistry;
use synwire_sandbox::visibility::ProcessVisibilityScope;
pub use synwire_sandbox::{
CapturedOutput, OutputMode, ProcessCapture, ProcessRecord, ProcessStatus,
};
#[derive(Debug, Clone)]
pub struct SandboxHandle {
pub registry: Arc<RwLock<ProcessRegistry>>,
pub scope: ProcessVisibilityScope,
}
pub trait SandboxedAgent<O: Serialize + Send + Sync + 'static> {
fn with_sandbox(self, config: SandboxConfig) -> (Self, SandboxHandle)
where
Self: Sized;
fn with_sandbox_limit(self, config: SandboxConfig, max_tracked: usize) -> (Self, SandboxHandle)
where
Self: Sized;
}
impl<O: Serialize + Send + Sync + 'static> SandboxedAgent<O> for Agent<O> {
fn with_sandbox(self, config: SandboxConfig) -> (Self, SandboxHandle) {
self.with_sandbox_limit(config, 256)
}
fn with_sandbox_limit(
self,
config: SandboxConfig,
max_tracked: usize,
) -> (Self, SandboxHandle) {
let registry = Arc::new(RwLock::new(ProcessRegistry::new(Some(max_tracked))));
let scope = ProcessVisibilityScope::new(Arc::clone(®istry));
let handle = SandboxHandle {
registry: Arc::clone(®istry),
scope: scope.clone(),
};
let plugin = try_full_plugin(config.clone(), registry, scope);
let agent = self.plugin(plugin).sandbox(config);
(agent, handle)
}
}
fn try_full_plugin(
config: SandboxConfig,
registry: Arc<RwLock<ProcessRegistry>>,
scope: ProcessVisibilityScope,
) -> ProcessPlugin {
#[cfg(target_os = "linux")]
{
use synwire_sandbox::platform::linux::namespace::NamespaceContainer;
use synwire_sandbox::plugin::context::SandboxContext;
match NamespaceContainer::new() {
Ok(container) => {
let ctx = Arc::new(SandboxContext::new(config, registry, scope, container));
return ProcessPlugin::with_context(ctx);
}
Err(e) => {
tracing::warn!(
"OCI runtime not found ({e}), sandbox tools will be management-only \
(no run_command/open_shell)"
);
}
}
}
#[cfg(not(target_os = "linux"))]
let _ = config;
ProcessPlugin::with_scope(scope)
}