ai-agent 0.13.4

Idiomatic agent sdk inspired by the claude code source leak
Documentation
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tokio::sync::RwLock;

#[derive(Debug, Clone)]
pub struct SSHSessionManager {
    sessions: Arc<RwLock<std::collections::HashMap<String, SSHSession>>>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SSHSession {
    pub session_id: String,
    pub host: String,
    pub user: String,
    pub port: u16,
    pub created_at: i64,
    pub last_active: i64,
    pub status: SessionStatus,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum SessionStatus {
    Connecting,
    Connected,
    Disconnected,
    Error,
}

impl SSHSessionManager {
    pub fn new() -> Self {
        Self {
            sessions: Arc::new(RwLock::new(std::collections::HashMap::new())),
        }
    }

    pub async fn create_session(&self, host: &str, user: &str, port: u16) -> SSHSession {
        let session_id = uuid::Uuid::new_v4().to_string();
        let session = SSHSession {
            session_id: session_id.clone(),
            host: host.to_string(),
            user: user.to_string(),
            port,
            created_at: chrono::Utc::now().timestamp_millis(),
            last_active: chrono::Utc::now().timestamp_millis(),
            status: SessionStatus::Connecting,
        };

        let mut sessions = self.sessions.write().await;
        sessions.insert(session_id, session.clone());
        session
    }

    pub async fn get_session(&self, session_id: &str) -> Option<SSHSession> {
        let sessions = self.sessions.read().await;
        sessions.get(session_id).cloned()
    }

    pub async fn remove_session(&self, session_id: &str) -> Option<SSHSession> {
        let mut sessions = self.sessions.write().await;
        sessions.remove(session_id)
    }

    pub async fn list_sessions(&self) -> Vec<SSHSession> {
        let sessions = self.sessions.read().await;
        sessions.values().cloned().collect()
    }

    pub async fn update_status(&self, session_id: &str, status: SessionStatus) {
        let mut sessions = self.sessions.write().await;
        if let Some(session) = sessions.get_mut(session_id) {
            session.status = status;
            session.last_active = chrono::Utc::now().timestamp_millis();
        }
    }
}

impl Default for SSHSessionManager {
    fn default() -> Self {
        Self::new()
    }
}