pub mod inspector;
pub mod profiler;
pub mod remote;
pub mod tracer;
pub use inspector::{InspectionQuery, InspectionResult, StateInspector};
pub use profiler::{AllocationRecord, MemoryProfiler, MemorySnapshot, ProfilingReport};
pub use remote::{DebugCommand, DebugSession, DebuggerConfig, RemoteDebugger};
pub use tracer::{ExecutionTracer, TraceEvent, TraceFilter, TraceRecorder};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DebugContext {
pub agent_id: [u8; 16],
pub session_id: [u8; 16],
pub enabled: bool,
pub breakpoints: Vec<Breakpoint>,
pub watches: Vec<WatchExpression>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Breakpoint {
pub id: u64,
pub location: String,
pub condition: Option<String>,
pub hit_count: u64,
pub enabled: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WatchExpression {
pub id: u64,
pub expression: String,
pub last_value: Option<String>,
}
impl DebugContext {
pub fn new(agent_id: [u8; 16]) -> Self {
use rand::Rng;
let mut rng = rand::rng();
let mut session_id = [0u8; 16];
rng.fill(&mut session_id);
Self {
agent_id,
session_id,
enabled: false,
breakpoints: Vec::new(),
watches: Vec::new(),
}
}
pub fn enable(&mut self) {
self.enabled = true;
}
pub fn disable(&mut self) {
self.enabled = false;
}
pub fn add_breakpoint(&mut self, location: String, condition: Option<String>) -> u64 {
let id = self.breakpoints.len() as u64;
self.breakpoints.push(Breakpoint {
id,
location,
condition,
hit_count: 0,
enabled: true,
});
id
}
pub fn remove_breakpoint(&mut self, id: u64) -> bool {
if let Some(pos) = self.breakpoints.iter().position(|b| b.id == id) {
self.breakpoints.remove(pos);
true
} else {
false
}
}
pub fn add_watch(&mut self, expression: String) -> u64 {
let id = self.watches.len() as u64;
self.watches.push(WatchExpression {
id,
expression,
last_value: None,
});
id
}
pub fn remove_watch(&mut self, id: u64) -> bool {
if let Some(pos) = self.watches.iter().position(|w| w.id == id) {
self.watches.remove(pos);
true
} else {
false
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_debug_context_creation() {
let agent_id = [1u8; 16];
let context = DebugContext::new(agent_id);
assert_eq!(context.agent_id, agent_id);
assert!(!context.enabled);
assert!(context.breakpoints.is_empty());
assert!(context.watches.is_empty());
}
#[test]
fn test_debug_context_enable_disable() {
let agent_id = [1u8; 16];
let mut context = DebugContext::new(agent_id);
assert!(!context.enabled);
context.enable();
assert!(context.enabled);
context.disable();
assert!(!context.enabled);
}
#[test]
fn test_debug_context_breakpoints() {
let agent_id = [1u8; 16];
let mut context = DebugContext::new(agent_id);
let bp_id = context.add_breakpoint("main".to_string(), None);
assert_eq!(context.breakpoints.len(), 1);
let removed = context.remove_breakpoint(bp_id);
assert!(removed);
assert_eq!(context.breakpoints.len(), 0);
}
#[test]
fn test_debug_context_watches() {
let agent_id = [1u8; 16];
let mut context = DebugContext::new(agent_id);
let watch_id = context.add_watch("variable_x".to_string());
assert_eq!(context.watches.len(), 1);
let removed = context.remove_watch(watch_id);
assert!(removed);
assert_eq!(context.watches.len(), 0);
}
}