use super::super::{Agent, Channel};
use super::background::{ErlTaskArgs, erl_reflection_task};
impl<C: Channel> Agent<C> {
pub(crate) async fn build_erl_heuristics_prompt(&self) -> String {
let Some(config) = self.learning_engine.config.as_ref() else {
return String::new();
};
if !config.erl_enabled {
return String::new();
}
let Some(memory) = &self.memory_state.persistence.memory else {
return String::new();
};
let mut sections = String::new();
for skill_name in &self.skill_state.active_skill_names {
let heuristics = match memory
.sqlite()
.load_skill_heuristics(
skill_name,
config.erl_min_confidence,
config.erl_max_heuristics_per_skill,
)
.await
{
Ok(rows) => rows,
Err(e) => {
tracing::warn!("ERL: load_skill_heuristics failed for {skill_name}: {e:#}");
continue;
}
};
if heuristics.is_empty() {
continue;
}
let texts: Vec<String> = heuristics.into_iter().map(|(_, text, _, _)| text).collect();
let section = zeph_skills::erl::format_heuristics_section(&texts);
if !section.is_empty() {
sections.push_str("\n\n<!-- ERL heuristics for skill: ");
sections.push_str(skill_name);
sections.push_str(" -->\n");
sections.push_str(§ion);
}
}
sections
}
pub(crate) fn spawn_erl_reflection(&mut self, skill_name: &str) {
let Some(config) = self.learning_engine.config.as_ref() else {
return;
};
if !config.erl_enabled {
return;
}
let tool_names = self.extract_last_turn_tool_names();
if tool_names.is_empty() {
return;
}
let Some(memory) = self.memory_state.persistence.memory.clone() else {
return;
};
let task_summary = self
.msg
.messages
.iter()
.rev()
.find(|m| m.role == super::super::Role::User)
.map(|m| m.content.chars().take(512).collect::<String>())
.unwrap_or_default();
let status_tx = self.session.status_tx.clone();
if let Some(ref tx) = self.session.status_tx {
let _ = tx.send("Reflecting on experience…".to_string());
}
let args = ErlTaskArgs {
provider: self.resolve_background_provider(config.erl_extract_provider.as_str()),
memory,
skill_name: skill_name.to_string(),
task_summary,
tool_calls_str: tool_names.join(", "),
dedup_threshold: config.erl_dedup_threshold,
status_tx,
};
self.try_spawn_learning_task(erl_reflection_task(args));
}
}