mielin-cells 0.1.0-rc.1

Agent SDK providing agent lifecycle management, policy execution, and inter-agent communication
Documentation
//! Remote debugging support

use crate::CellError;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DebuggerConfig {
    pub listen_address: String,
    pub port: u16,
    pub max_sessions: usize,
    pub session_timeout_secs: u64,
}

impl Default for DebuggerConfig {
    fn default() -> Self {
        Self {
            listen_address: "127.0.0.1".to_string(),
            port: 9229,
            max_sessions: 10,
            session_timeout_secs: 3600,
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum DebugCommand {
    Pause,
    Resume,
    StepOver,
    StepInto,
    StepOut,
    SetBreakpoint { location: String },
    RemoveBreakpoint { id: u64 },
    Evaluate { expression: String },
    GetStackFrame,
    GetVariables,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DebugSession {
    pub session_id: [u8; 16],
    pub agent_id: [u8; 16],
    pub created_at: u64,
    pub last_activity: u64,
    pub paused: bool,
}

#[derive(Debug)]
pub struct RemoteDebugger {
    #[allow(dead_code)]
    config: DebuggerConfig,
    sessions: HashMap<[u8; 16], DebugSession>,
}

impl RemoteDebugger {
    pub fn new(config: DebuggerConfig) -> Self {
        Self {
            config,
            sessions: HashMap::new(),
        }
    }

    pub fn create_session(&mut self, agent_id: [u8; 16]) -> Result<[u8; 16], CellError> {
        use rand::Rng;
        let mut rng = rand::rng();
        let mut session_id = [0u8; 16];
        rng.fill(&mut session_id);

        let now = std::time::SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH)
            .map_err(|_| CellError::InvalidState("Time error".to_string()))?
            .as_secs();

        self.sessions.insert(
            session_id,
            DebugSession {
                session_id,
                agent_id,
                created_at: now,
                last_activity: now,
                paused: false,
            },
        );

        Ok(session_id)
    }

    pub fn close_session(&mut self, session_id: &[u8; 16]) -> bool {
        self.sessions.remove(session_id).is_some()
    }

    pub fn get_session(&self, session_id: &[u8; 16]) -> Option<&DebugSession> {
        self.sessions.get(session_id)
    }

    pub fn handle_command(
        &mut self,
        session_id: &[u8; 16],
        _command: &DebugCommand,
    ) -> Result<String, CellError> {
        if let Some(session) = self.sessions.get_mut(session_id) {
            let now = std::time::SystemTime::now()
                .duration_since(std::time::UNIX_EPOCH)
                .map_err(|_| CellError::InvalidState("Time error".to_string()))?
                .as_secs();
            session.last_activity = now;
            Ok("Command executed".to_string())
        } else {
            Err(CellError::InvalidState("Session not found".to_string()))
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_remote_debugger() {
        let config = DebuggerConfig::default();
        let mut debugger = RemoteDebugger::new(config);

        let agent_id = [1u8; 16];
        let session_id = debugger.create_session(agent_id).expect("Failed");

        assert!(debugger.get_session(&session_id).is_some());

        let closed = debugger.close_session(&session_id);
        assert!(closed);
    }
}