mod config;
mod context_learner;
mod continuum_memory;
mod reconfigurator;
mod self_modifier;
pub use config::KaneruConfig;
pub use context_learner::ContextLearner;
pub use continuum_memory::ContinuumMemory;
pub use reconfigurator::{AutoReconfigurator, NodeConfig};
pub use self_modifier::{BehaviorRule, SafetyBounds, SelfModifier};
use crate::error::AiResult;
use crate::types::ResourceCategory;
use parking_lot::RwLock;
use std::sync::Arc;
use tracing::{debug, info};
pub struct KaneruAgent {
memory: Arc<RwLock<ContinuumMemory>>,
modifier: Arc<RwLock<SelfModifier>>,
context_learner: Arc<RwLock<ContextLearner>>,
reconfigurator: Arc<RwLock<AutoReconfigurator>>,
config: KaneruConfig,
state: AgentState,
}
impl KaneruAgent {
pub fn new(config: KaneruConfig) -> Self {
Self {
memory: Arc::new(RwLock::new(ContinuumMemory::new(config.memory_dim))),
modifier: Arc::new(RwLock::new(SelfModifier::new(&config))),
context_learner: Arc::new(RwLock::new(ContextLearner::new(config.context_capacity))),
reconfigurator: Arc::new(RwLock::new(AutoReconfigurator::new())),
config,
state: AgentState::default(),
}
}
pub fn process_experience(&mut self, experience: &Experience) -> AiResult<ExperienceResult> {
debug!(experience_type = ?experience.experience_type, "Processing experience");
{
let mut mem = self.memory.write();
mem.store(experience);
}
{
let mut cl = self.context_learner.write();
cl.learn(&Context {
data: experience.data.clone(),
timestamp: experience.timestamp,
relevance: 1.0,
});
}
let modification_applied = if self.config.self_modification_enabled {
let mut modifier = self.modifier.write();
let outcome = Outcome {
success: experience.success,
reward: experience.reward,
};
modifier.evolve(&outcome)
} else {
false
};
self.state.experiences_processed += 1;
if modification_applied {
self.state.modifications_applied += 1;
}
Ok(ExperienceResult {
stored: true,
modification_applied,
current_rules: self.get_behavior_rules().len(),
})
}
pub fn query(&self, query: &Query) -> QueryResult {
let memory_result = {
let mem = self.memory.read();
mem.retrieve(query)
};
let contexts = {
let cl = self.context_learner.read();
cl.query_with_context(query)
};
QueryResult {
memory_matches: memory_result,
relevant_contexts: contexts,
}
}
pub fn check_reconfiguration(&mut self, resources: &Resources) -> ReconfigResult {
let category = resources.category();
let result = {
let mut reconf = self.reconfigurator.write();
reconf.reconfigure(category)
};
if let ReconfigResult::Changed(ref new_config) = result {
info!(
mode = ?new_config.mode,
"Kaneru Agent reconfigured"
);
self.apply_node_config(new_config);
}
result
}
pub fn get_behavior_rules(&self) -> Vec<BehaviorRule> {
let modifier = self.modifier.read();
modifier.get_rules()
}
pub fn stats(&self) -> AgentStats {
let mem = self.memory.read();
let cl = self.context_learner.read();
let modifier = self.modifier.read();
AgentStats {
state: self.state.clone(),
memory_size: mem.len(),
context_size: cl.len(),
rule_count: modifier.rule_count(),
safety_violations: modifier.safety_violation_count(),
}
}
fn apply_node_config(&mut self, config: &NodeConfig) {
if config.mode == PowerMode::Critical {
let mut mem = self.memory.write();
mem.compress();
}
}
}
#[derive(Debug, Clone)]
pub struct Experience {
pub id: [u8; 32],
pub experience_type: ExperienceType,
pub data: Vec<u8>,
pub timestamp: u64,
pub success: bool,
pub reward: f32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ExperienceType {
Validation,
Network,
Storage,
Consensus,
}
#[derive(Debug, Clone)]
pub struct Query {
pub data: Vec<u8>,
pub limit: usize,
}
#[derive(Debug, Clone)]
pub struct Outcome {
pub success: bool,
pub reward: f32,
}
#[derive(Debug, Clone)]
pub struct Context {
pub data: Vec<u8>,
pub timestamp: u64,
pub relevance: f32,
}
#[derive(Debug, Clone)]
pub struct Resources {
pub memory_available: usize,
pub cpu_usage: f32,
pub battery_level: Option<f32>,
}
impl Resources {
pub fn category(&self) -> ResourceCategory {
if let Some(battery) = self.battery_level {
if battery < 0.1 {
return ResourceCategory::Critical;
}
if battery < 0.3 {
return ResourceCategory::Limited;
}
}
if self.memory_available < 10 * 1024 * 1024 {
return ResourceCategory::Critical;
}
if self.memory_available < 100 * 1024 * 1024 {
return ResourceCategory::Limited;
}
if self.cpu_usage > 0.9 {
return ResourceCategory::Limited;
}
if self.memory_available > 1024 * 1024 * 1024 {
return ResourceCategory::Abundant;
}
ResourceCategory::Normal
}
}
#[derive(Debug, Clone, Default)]
pub struct AgentState {
pub experiences_processed: u64,
pub modifications_applied: u64,
}
#[derive(Debug, Clone)]
pub struct ExperienceResult {
pub stored: bool,
pub modification_applied: bool,
pub current_rules: usize,
}
#[derive(Debug, Clone)]
pub struct QueryResult {
pub memory_matches: Vec<MemoryResult>,
pub relevant_contexts: Vec<Context>,
}
#[derive(Debug, Clone)]
pub struct MemoryResult {
pub id: [u8; 32],
pub similarity: f32,
pub data: Vec<u8>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PowerMode {
Full,
Balanced,
Low,
Critical,
}
#[derive(Debug, Clone)]
pub enum ReconfigResult {
NoChange,
Changed(NodeConfig),
}
#[derive(Debug, Clone)]
pub struct AgentStats {
pub state: AgentState,
pub memory_size: usize,
pub context_size: usize,
pub rule_count: usize,
pub safety_violations: usize,
}
#[cfg(test)]
mod tests {
use super::*;
fn make_experience(id: u8) -> Experience {
Experience {
id: [id; 32],
experience_type: ExperienceType::Validation,
data: vec![id; 10],
timestamp: 1702656000000,
success: true,
reward: 0.5,
}
}
#[test]
fn test_kaneru_agent_basic() {
let config = KaneruConfig::default();
let mut agent = KaneruAgent::new(config);
let exp = make_experience(1);
let result = agent.process_experience(&exp).unwrap();
assert!(result.stored);
}
#[test]
fn test_kaneru_agent_query() {
let config = KaneruConfig::default();
let mut agent = KaneruAgent::new(config);
for i in 0..5 {
let exp = make_experience(i);
agent.process_experience(&exp).unwrap();
}
let query = Query {
data: vec![2; 10],
limit: 3,
};
let result = agent.query(&query);
assert!(result.relevant_contexts.len() > 0 || result.memory_matches.len() >= 0);
}
#[test]
fn test_resource_categorization() {
let abundant = Resources {
memory_available: 2 * 1024 * 1024 * 1024, cpu_usage: 0.3,
battery_level: Some(0.9),
};
assert_eq!(abundant.category(), ResourceCategory::Abundant);
let critical = Resources {
memory_available: 5 * 1024 * 1024, cpu_usage: 0.9,
battery_level: Some(0.05),
};
assert_eq!(critical.category(), ResourceCategory::Critical);
}
#[test]
fn test_reconfiguration() {
let config = KaneruConfig::default();
let mut agent = KaneruAgent::new(config);
let resources = Resources {
memory_available: 5 * 1024 * 1024, cpu_usage: 0.9,
battery_level: Some(0.05),
};
let result = agent.check_reconfiguration(&resources);
matches!(result, ReconfigResult::Changed(_));
}
}