zeroclaw/src/agent/loop_/context.rs
2026-02-28 15:00:27 -05:00

83 lines
2.5 KiB
Rust

use crate::memory::{self, Memory};
use std::fmt::Write;
/// Build context preamble by searching memory for relevant entries.
/// Entries with a hybrid score below `min_relevance_score` are dropped to
/// prevent unrelated memories from bleeding into the conversation.
pub(super) async fn build_context(
mem: &dyn Memory,
user_msg: &str,
min_relevance_score: f64,
session_id: Option<&str>,
) -> String {
let mut context = String::new();
// Pull relevant memories for this message
if let Ok(entries) = mem.recall(user_msg, 5, session_id).await {
let relevant: Vec<_> = entries
.iter()
.filter(|e| match e.score {
Some(score) => score >= min_relevance_score,
None => true,
})
.collect();
if !relevant.is_empty() {
context.push_str("[Memory context]\n");
for entry in &relevant {
if memory::is_assistant_autosave_key(&entry.key) {
continue;
}
let _ = writeln!(context, "- {}: {}", entry.key, entry.content);
}
if context == "[Memory context]\n" {
context.clear();
} else {
context.push('\n');
}
}
}
context
}
/// Build hardware datasheet context from RAG when peripherals are enabled.
/// Includes pin-alias lookup (e.g. "red_led" → 13) when query matches, plus retrieved chunks.
pub(super) fn build_hardware_context(
rag: &crate::rag::HardwareRag,
user_msg: &str,
boards: &[String],
chunk_limit: usize,
) -> String {
if rag.is_empty() || boards.is_empty() {
return String::new();
}
let mut context = String::new();
// Pin aliases: when user says "red led", inject "red_led: 13" for matching boards
let pin_ctx = rag.pin_alias_context(user_msg, boards);
if !pin_ctx.is_empty() {
context.push_str(&pin_ctx);
}
let chunks = rag.retrieve(user_msg, boards, chunk_limit);
if chunks.is_empty() && pin_ctx.is_empty() {
return String::new();
}
if !chunks.is_empty() {
context.push_str("[Hardware documentation]\n");
}
for chunk in chunks {
let board_tag = chunk.board.as_deref().unwrap_or("generic");
let _ = writeln!(
context,
"--- {} ({}) ---\n{}\n",
chunk.source, board_tag, chunk.content
);
}
context.push('\n');
context
}