forked from kent/consciousness
Fix agent provenance and add store activity for unconscious agents
- Remove bogus "agent:" prefix from provenance - just use agent name - Add history field to UnconsciousSnapshot - Update snapshots() to fetch store activity via recent_by_provenance - Fix TUI to display store activity for both agent types Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
parent
d2dbdedc8f
commit
e9e7458013
5 changed files with 66 additions and 32 deletions
|
|
@ -380,7 +380,13 @@ impl Mind {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn unconscious_snapshots(&self) -> Vec<UnconsciousSnapshot> {
|
pub async fn unconscious_snapshots(&self) -> Vec<UnconsciousSnapshot> {
|
||||||
self.unconscious.lock().await.snapshots()
|
let unc = self.unconscious.lock().await;
|
||||||
|
let store = crate::store::Store::cached().await.ok();
|
||||||
|
let store_guard = match &store {
|
||||||
|
Some(s) => Some(s.lock().await),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
unc.snapshots(store_guard.as_deref())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn init(&self) {
|
pub async fn init(&self) {
|
||||||
|
|
|
||||||
|
|
@ -456,10 +456,8 @@ impl Subconscious {
|
||||||
|
|
||||||
pub fn snapshots(&self, store: Option<&crate::store::Store>) -> Vec<SubconsciousSnapshot> {
|
pub fn snapshots(&self, store: Option<&crate::store::Store>) -> Vec<SubconsciousSnapshot> {
|
||||||
self.agents.iter().map(|s| {
|
self.agents.iter().map(|s| {
|
||||||
let history = store.map(|st| {
|
let history = store.map(|st| st.recent_by_provenance(&s.name, 30))
|
||||||
let prov = format!("agent:{}", s.name);
|
.unwrap_or_default();
|
||||||
st.recent_by_provenance(&prov, 30)
|
|
||||||
}).unwrap_or_default();
|
|
||||||
s.snapshot(&self.state, history)
|
s.snapshot(&self.state, history)
|
||||||
}).collect()
|
}).collect()
|
||||||
}
|
}
|
||||||
|
|
@ -595,10 +593,9 @@ impl Subconscious {
|
||||||
dbglog!("[subconscious] triggering {}", auto.name);
|
dbglog!("[subconscious] triggering {}", auto.name);
|
||||||
|
|
||||||
let forked = agent.fork(auto.tools.clone()).await;
|
let forked = agent.fork(auto.tools.clone()).await;
|
||||||
let prov = format!("agent:{}", auto.name);
|
|
||||||
{
|
{
|
||||||
let mut st = forked.state.lock().await;
|
let mut st = forked.state.lock().await;
|
||||||
st.provenance = prov.clone();
|
st.provenance = auto.name.clone();
|
||||||
// Surface agent gets near-interactive priority;
|
// Surface agent gets near-interactive priority;
|
||||||
// other subconscious agents get lower priority.
|
// other subconscious agents get lower priority.
|
||||||
st.priority = Some(if auto.name == "surface" { 1 } else { 2 });
|
st.priority = Some(if auto.name == "surface" { 1 } else { 2 });
|
||||||
|
|
@ -611,7 +608,7 @@ impl Subconscious {
|
||||||
let keys = memory_keys.clone();
|
let keys = memory_keys.clone();
|
||||||
let st = self.state.clone();
|
let st = self.state.clone();
|
||||||
let recent: Vec<String> = store_guard.as_ref()
|
let recent: Vec<String> = store_guard.as_ref()
|
||||||
.map(|s| s.recent_by_provenance(&prov, 50)
|
.map(|s| s.recent_by_provenance(&auto.name, 50)
|
||||||
.into_iter().map(|(k, _)| k).collect())
|
.into_iter().map(|(k, _)| k).collect())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,8 @@ pub struct UnconsciousSnapshot {
|
||||||
pub last_run_secs_ago: Option<f64>,
|
pub last_run_secs_ago: Option<f64>,
|
||||||
pub agent: Option<std::sync::Arc<crate::agent::Agent>>,
|
pub agent: Option<std::sync::Arc<crate::agent::Agent>>,
|
||||||
pub last_stats: Option<RunStats>,
|
pub last_stats: Option<RunStats>,
|
||||||
|
/// Recent store activity for this agent: (key, timestamp), newest first.
|
||||||
|
pub history: Vec<(String, i64)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Unconscious {
|
pub struct Unconscious {
|
||||||
|
|
@ -138,15 +140,20 @@ impl Unconscious {
|
||||||
save_enabled_config(&map);
|
save_enabled_config(&map);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn snapshots(&self) -> Vec<UnconsciousSnapshot> {
|
pub fn snapshots(&self, store: Option<&crate::store::Store>) -> Vec<UnconsciousSnapshot> {
|
||||||
self.agents.iter().map(|a| UnconsciousSnapshot {
|
self.agents.iter().map(|a| {
|
||||||
name: a.name.clone(),
|
let history = store.map(|st| st.recent_by_provenance(&a.name, 30))
|
||||||
running: a.is_running(),
|
.unwrap_or_default();
|
||||||
enabled: a.enabled,
|
UnconsciousSnapshot {
|
||||||
runs: a.runs,
|
name: a.name.clone(),
|
||||||
last_run_secs_ago: a.last_run.map(|t| t.elapsed().as_secs_f64()),
|
running: a.is_running(),
|
||||||
agent: a.agent.clone(),
|
enabled: a.enabled,
|
||||||
last_stats: a.last_stats.clone(),
|
runs: a.runs,
|
||||||
|
last_run_secs_ago: a.last_run.map(|t| t.elapsed().as_secs_f64()),
|
||||||
|
agent: a.agent.clone(),
|
||||||
|
last_stats: a.last_stats.clone(),
|
||||||
|
history,
|
||||||
|
}
|
||||||
}).collect()
|
}).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -285,7 +292,7 @@ impl Unconscious {
|
||||||
).await;
|
).await;
|
||||||
{
|
{
|
||||||
let mut st = agent.state.lock().await;
|
let mut st = agent.state.lock().await;
|
||||||
st.provenance = format!("unconscious:{}", auto.name);
|
st.provenance = auto.name.clone();
|
||||||
st.priority = Some(10);
|
st.priority = Some(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -404,7 +404,12 @@ async fn run(
|
||||||
unc.toggle(name).await;
|
unc.toggle(name).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
app.unconscious_state = unc.snapshots();
|
let store = crate::store::Store::cached().await.ok();
|
||||||
|
let store_guard = match &store {
|
||||||
|
Some(s) => Some(s.lock().await),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
app.unconscious_state = unc.snapshots(store_guard.as_deref());
|
||||||
app.graph_health = unc.graph_health.clone();
|
app.graph_health = unc.graph_health.clone();
|
||||||
app.mind_state = Some(mind.shared.lock().unwrap().clone());
|
app.mind_state = Some(mind.shared.lock().unwrap().clone());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -160,6 +160,21 @@ impl SubconsciousScreen {
|
||||||
app.unconscious_state.get(unc_idx)?.agent.clone()
|
app.unconscious_state.get(unc_idx)?.agent.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get store activity history for the selected agent.
|
||||||
|
fn selected_history<'a>(&self, app: &'a App) -> &'a [(String, i64)] {
|
||||||
|
let idx = self.selected();
|
||||||
|
let sub_count = app.agent_state.len();
|
||||||
|
if idx < sub_count {
|
||||||
|
return app.agent_state.get(idx)
|
||||||
|
.map(|s| s.history.as_slice())
|
||||||
|
.unwrap_or(&[]);
|
||||||
|
}
|
||||||
|
idx.checked_sub(sub_count + 1)
|
||||||
|
.and_then(|i| app.unconscious_state.get(i))
|
||||||
|
.map(|s| s.history.as_slice())
|
||||||
|
.unwrap_or(&[])
|
||||||
|
}
|
||||||
|
|
||||||
fn output_sections(&self, app: &App) -> Vec<SectionView> {
|
fn output_sections(&self, app: &App) -> Vec<SectionView> {
|
||||||
let snap = match app.agent_state.get(self.selected()) {
|
let snap = match app.agent_state.get(self.selected()) {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
|
|
@ -306,23 +321,27 @@ impl SubconsciousScreen {
|
||||||
let key_style = Style::default().fg(Color::Yellow);
|
let key_style = Style::default().fg(Color::Yellow);
|
||||||
|
|
||||||
let mut lines: Vec<Line> = Vec::new();
|
let mut lines: Vec<Line> = Vec::new();
|
||||||
let mut title = "memory store activity".to_string();
|
|
||||||
|
|
||||||
if let Some(snap) = app.agent_state.get(self.selected()) {
|
let name = self.selected_agent_name(app);
|
||||||
let short_name = snap.name.strip_prefix("subconscious-").unwrap_or(&snap.name);
|
let short_name = name.as_ref()
|
||||||
title = format!("{} store activity", short_name);
|
.map(|n| n.strip_prefix("subconscious-").unwrap_or(n))
|
||||||
|
.unwrap_or("—");
|
||||||
|
let title = format!("{} store activity", short_name);
|
||||||
|
|
||||||
if snap.history.is_empty() {
|
let history = self.selected_history(app);
|
||||||
lines.push(Line::styled(" (no store activity)", dim));
|
if history.is_empty() {
|
||||||
} else {
|
lines.push(Line::styled(" (no store activity)", dim));
|
||||||
for (key, ts) in &snap.history {
|
} else {
|
||||||
lines.push(Line::from(vec![
|
for (key, ts) in history {
|
||||||
Span::styled(format!(" {:>6} ", format_ts_age(*ts)), dim),
|
lines.push(Line::from(vec![
|
||||||
Span::styled(key.as_str(), key_style),
|
Span::styled(format!(" {:>6} ", format_ts_age(*ts)), dim),
|
||||||
]));
|
Span::styled(key.as_str(), key_style),
|
||||||
}
|
]));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walked state (subconscious only)
|
||||||
|
if let Some(snap) = app.agent_state.get(self.selected()) {
|
||||||
if let Some(walked_str) = snap.state.get("walked") {
|
if let Some(walked_str) = snap.state.get("walked") {
|
||||||
let walked: Vec<&str> = walked_str.lines()
|
let walked: Vec<&str> = walked_str.lines()
|
||||||
.map(|l| l.trim()).filter(|l| !l.is_empty()).collect();
|
.map(|l| l.trim()).filter(|l| !l.is_empty()).collect();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue