diff --git a/src/agent/api/mod.rs b/src/agent/api/mod.rs index b70140d..b199bd2 100644 --- a/src/agent/api/mod.rs +++ b/src/agent/api/mod.rs @@ -57,6 +57,7 @@ pub enum StreamEvent { Error(String), } +#[derive(Clone)] pub struct ApiClient { client: Client, api_key: String, diff --git a/src/agent/runner.rs b/src/agent/runner.rs index 50f63b6..992e6bb 100644 --- a/src/agent/runner.rs +++ b/src/agent/runner.rs @@ -76,6 +76,10 @@ pub struct Agent { session_id: String, /// Agent orchestration state (surface-observe, journal, reflect). pub agent_cycles: crate::subconscious::subconscious::AgentCycleState, + /// Latest memory importance scores from training scorer. + pub memory_scores: Option, + /// Whether a /score task is currently running. + pub scoring_in_flight: bool, } fn render_journal(entries: &[journal::JournalEntry]) -> String { @@ -125,6 +129,8 @@ impl Agent { prompt_file, session_id, agent_cycles, + memory_scores: None, + scoring_in_flight: false, }; agent.load_startup_journal(); @@ -670,8 +676,16 @@ impl Agent { _ => unreachable!(), }; let text = entry.message().content_text(); + let score = self.memory_scores.as_ref() + .and_then(|s| s.memory_weights.iter() + .find(|(k, _)| k == key) + .map(|(_, v)| *v)); + let label = match score { + Some(v) => format!("{} (importance: {:.1})", key, v), + None => key.to_string(), + }; ContextSection { - name: key.to_string(), + name: label, tokens: count(text), content: String::new(), children: Vec::new(), @@ -970,6 +984,10 @@ impl Agent { } /// Mutable access to conversation entries (for /retry). + pub fn client_clone(&self) -> ApiClient { + self.client.clone() + } + pub fn entries_mut(&mut self) -> &mut Vec { &mut self.context.entries } diff --git a/src/agent/types.rs b/src/agent/types.rs index 53f6db4..a963556 100644 --- a/src/agent/types.rs +++ b/src/agent/types.rs @@ -397,6 +397,7 @@ impl ConversationEntry { } } +#[derive(Clone)] pub struct ContextState { pub system_prompt: String, pub personality: Vec<(String, String)>, diff --git a/src/bin/poc-agent.rs b/src/bin/poc-agent.rs index 6e7f5d8..0497ce4 100644 --- a/src/bin/poc-agent.rs +++ b/src/bin/poc-agent.rs @@ -354,6 +354,7 @@ impl Session { ("/save", "Save session to disk"), ("/retry", "Re-run last turn"), ("/model", "Show/switch model (/model )"), + ("/score", "Score memory importance"), ("/dmn", "Show DMN state"), ("/sleep", "Put DMN to sleep"), ("/wake", "Wake DMN to foraging"), @@ -422,6 +423,46 @@ impl Session { } Command::Handled } + "/score" => { + { + let agent = self.agent.lock().await; + if agent.scoring_in_flight { + let _ = self.ui_tx.send(UiMessage::Info( + "(scoring already in progress)".into() + )); + return Command::Handled; + } + } + self.agent.lock().await.scoring_in_flight = true; + let agent = self.agent.clone(); + let ui_tx = self.ui_tx.clone(); + tokio::spawn(async move { + let (context, client) = { + let agent = agent.lock().await; + (agent.context.clone(), agent.client_clone()) + }; + let result = poc_memory::thought::training::score_memories( + &context, &client, &ui_tx, + ).await; + let mut agent = agent.lock().await; + agent.scoring_in_flight = false; + match result { + Ok(scores) => { + let _ = ui_tx.send(UiMessage::Info(format!( + "[memory scoring complete: {} memories scored]", + scores.memory_keys.len(), + ))); + agent.memory_scores = Some(scores); + } + Err(e) => { + let _ = ui_tx.send(UiMessage::Info(format!( + "[memory scoring failed: {:#}]", e, + ))); + } + } + }); + Command::Handled + } "/dmn" => { let _ = self .ui_tx diff --git a/src/subconscious/daemon.rs b/src/subconscious/daemon.rs index 146dd96..e6c1d37 100644 --- a/src/subconscious/daemon.rs +++ b/src/subconscious/daemon.rs @@ -13,7 +13,6 @@ // Phase 2 will inline job logic; Phase 3 integrates into poc-agent. use jobkit::{Choir, ExecutionContext, TaskError, TaskInfo, TaskStatus}; -use std::collections::{HashMap, HashSet}; use std::fs; use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex}; diff --git a/src/subconscious/knowledge.rs b/src/subconscious/knowledge.rs index 8b093ba..8f1f7ac 100644 --- a/src/subconscious/knowledge.rs +++ b/src/subconscious/knowledge.rs @@ -102,7 +102,7 @@ pub fn run_and_apply_excluded( log: &(dyn Fn(&str) + Sync), exclude: &std::collections::HashSet, ) -> Result<(), String> { - let result = run_one_agent_excluded(store, agent_name, batch_size, llm_tag, log, exclude)?; + let _result = run_one_agent_excluded(store, agent_name, batch_size, llm_tag, log, exclude)?; Ok(()) } diff --git a/src/thought/training.rs b/src/thought/training.rs index 35f1d27..e1fdfec 100644 --- a/src/thought/training.rs +++ b/src/thought/training.rs @@ -89,7 +89,7 @@ pub async fn score_memories( // Compute per-response divergence let mut row = Vec::new(); - for (resp_idx, (base_lps, without_lps)) in baseline.iter().zip(without.iter()).enumerate() { + for (_resp_idx, (base_lps, without_lps)) in baseline.iter().zip(without.iter()).enumerate() { // Sum of logprob drops across tokens in this response // Positive = memory helped (logprob was higher with it) let divergence: f64 = base_lps.iter().zip(without_lps.iter())