split out src/mind

This commit is contained in:
Kent Overstreet 2026-04-04 02:46:32 -04:00
parent ce04568454
commit 79e384f005
21 changed files with 1865 additions and 2175 deletions

View file

@ -288,6 +288,79 @@ pub async fn score_memory(
Ok(divs.iter().sum())
}
// ── Background memory scoring ───────────────────────────────────
/// Incrementally score memories through the conversation.
///
/// Walks memory entries in conversation order starting from `cursor`.
/// For each memory with a full WINDOW after it, calls score_memory()
/// and yields the result. Stops at the first memory that doesn't have
/// enough messages yet — the conversation needs to grow before we can
/// score it.
///
/// Returns the updated cursor (entry index to resume from next time)
/// and the scores for each memory that was scored this round.
pub async fn score_memories_incremental(
context: &ContextState,
cursor: usize,
client: &ApiClient,
ui_tx: &UiSender,
) -> anyhow::Result<(usize, Vec<(String, f64)>)> {
const WINDOW: usize = 50;
// Collect unique memory keys with their first position, starting from cursor
let mut seen = std::collections::HashSet::new();
let mut to_score: Vec<(usize, String)> = Vec::new();
for (i, entry) in context.entries.iter().enumerate().skip(cursor) {
if let ConversationEntry::Memory { key, .. } = entry {
if seen.insert(key.clone()) {
to_score.push((i, key.clone()));
}
}
}
let http = http_client();
let mut new_cursor = cursor;
let mut results = Vec::new();
for (pos, key) in &to_score {
let end = pos + WINDOW;
// Not enough conversation after this memory yet — stop here
if end > context.entries.len() {
break;
}
// Need at least one assistant response in the window
let range = *pos..end;
if !context.entries[range.clone()].iter().any(|e| e.message().role == Role::Assistant) {
new_cursor = end;
continue;
}
let _ = ui_tx.send(UiMessage::Activity(format!("scoring memory: {}...", key)));
match score_divergence(&http, client, context, range, Filter::SkipKey(key)).await {
Ok((divs, _)) => {
let importance: f64 = divs.iter().sum();
let _ = ui_tx.send(UiMessage::Debug(format!(
"[scoring] {} → {:.2}", key, importance,
)));
results.push((key.clone(), importance));
}
Err(e) => {
let _ = ui_tx.send(UiMessage::Debug(format!(
"[scoring] {} FAILED: {:#}", key, e,
)));
}
}
new_cursor = end;
}
let _ = ui_tx.send(UiMessage::Activity(String::new()));
Ok((new_cursor, results))
}
// ── Fine-tuning scoring ─────────────────────────────────────────
/// Score which recent responses are candidates for fine-tuning.