use std::sync::Arc;
use serde::{Deserialize, Serialize};
use tokio::sync::RwLock;
use synwire_core::agents::plugin::{Plugin, PluginStateKey};
use synwire_core::tools::Tool;
use crate::plugin::command_tools::{
OpenShellTool, RunCommandTool, ShellBatchTool, ShellExpectCasesTool, ShellExpectTool,
ShellReadTool, ShellSignalTool, ShellWriteTool,
};
use crate::plugin::context::SandboxContext;
use crate::plugin::tools::{
KillProcessTool, ListProcessesTool, ProcessStatsTool, ReadProcessOutputTool, WaitForProcessTool,
};
use crate::process_registry::ProcessRegistry;
use crate::visibility::ProcessVisibilityScope;
#[derive(Debug)]
pub struct ProcessPluginState {
pub registry: Arc<RwLock<ProcessRegistry>>,
}
impl Serialize for ProcessPluginState {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
use serde::ser::SerializeMap;
let mut map = serializer.serialize_map(Some(1))?;
map.serialize_entry("active", &true)?;
map.end()
}
}
impl<'de> Deserialize<'de> for ProcessPluginState {
fn deserialize<D: serde::Deserializer<'de>>(_deserializer: D) -> Result<Self, D::Error> {
Ok(Self {
registry: Arc::new(RwLock::new(ProcessRegistry::new(None))),
})
}
}
pub struct ProcessPluginKey;
impl PluginStateKey for ProcessPluginKey {
type State = ProcessPluginState;
const KEY: &'static str = "synwire.process";
}
pub struct ProcessPlugin {
tools: Vec<Arc<dyn Tool>>,
}
impl ProcessPlugin {
#[must_use]
pub fn new(registry: Arc<RwLock<ProcessRegistry>>) -> Self {
Self::with_scope(ProcessVisibilityScope::new(registry))
}
#[must_use]
pub fn with_scope(scope: ProcessVisibilityScope) -> Self {
let tools: Vec<Arc<dyn Tool>> = vec![
Arc::new(ListProcessesTool::new(scope.clone())),
Arc::new(KillProcessTool::new(scope.clone())),
Arc::new(ProcessStatsTool::new(scope.clone())),
Arc::new(WaitForProcessTool::new(scope.clone())),
Arc::new(ReadProcessOutputTool::new(scope)),
];
Self { tools }
}
#[must_use]
pub fn with_context(ctx: Arc<SandboxContext>) -> Self {
let scope = ctx.scope.clone();
let mut tools: Vec<Arc<dyn Tool>> = vec![
Arc::new(ListProcessesTool::new(scope.clone())),
Arc::new(KillProcessTool::new(scope.clone())),
Arc::new(ProcessStatsTool::new(scope.clone())),
Arc::new(WaitForProcessTool::new(scope.clone())),
Arc::new(ReadProcessOutputTool::new(scope)),
Arc::new(RunCommandTool::new(Arc::clone(&ctx))),
Arc::new(OpenShellTool::new(Arc::clone(&ctx))),
Arc::new(ShellWriteTool::new(Arc::clone(&ctx))),
Arc::new(ShellReadTool::new(Arc::clone(&ctx))),
Arc::new(ShellExpectTool::new(Arc::clone(&ctx))),
Arc::new(ShellExpectCasesTool::new(Arc::clone(&ctx))),
Arc::new(ShellBatchTool::new(Arc::clone(&ctx))),
Arc::new(ShellSignalTool::new(ctx)),
];
tools.sort_by(|a, b| a.name().cmp(b.name()));
Self { tools }
}
}
impl Plugin for ProcessPlugin {
fn name(&self) -> &'static str {
"synwire-process"
}
fn tools(&self) -> Vec<Arc<dyn Tool>> {
self.tools.clone()
}
}