use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::PathBuf;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RegisteredAgent {
pub name: String,
pub path: PathBuf,
pub contract: AgentContract,
pub registered_at: String, }
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum AgentContract {
NativeRust,
Process,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct Registry {
pub agents: HashMap<String, RegisteredAgent>,
}
impl Registry {
pub fn new() -> Self {
Self::default()
}
pub fn load_from(artifact_root: &std::path::Path) -> anyhow::Result<Self> {
let registry_path = artifact_root.join("registry.json");
if !registry_path.exists() {
return Ok(Self::default());
}
let content = std::fs::read_to_string(registry_path)?;
let reg: Registry = serde_json::from_str(&content)?;
Ok(reg)
}
pub fn save_to(&self, artifact_root: &std::path::Path) -> anyhow::Result<()> {
let registry_path = artifact_root.join("registry.json");
if let Some(parent) = registry_path.parent() {
std::fs::create_dir_all(parent)?;
}
let content = serde_json::to_string_pretty(self)?;
std::fs::write(registry_path, content)?;
Ok(())
}
pub fn register(&mut self, agent: RegisteredAgent) {
self.agents.insert(agent.name.clone(), agent);
}
pub fn get(&self, name: &str) -> Option<&RegisteredAgent> {
self.agents.get(name)
}
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::tempdir;
#[test]
fn test_registry_save_load_roundtrip() {
let dir = tempdir().unwrap();
let root = dir.path();
let mut reg = Registry::new();
reg.register(RegisteredAgent {
name: "test-agent".to_string(),
path: PathBuf::from("/tmp/test"),
contract: AgentContract::NativeRust,
registered_at: "123".to_string(),
});
reg.save_to(root).unwrap();
let loaded = Registry::load_from(root).unwrap();
assert_eq!(loaded.agents.len(), 1);
assert_eq!(
loaded.get("test-agent").unwrap().contract,
AgentContract::NativeRust
);
}
}