feat(server): persist activity history on the server and expose it to the dashboard UI via /api/activity instead of relying on fragile localStorage

This commit is contained in:
Riz Ashraf committed 2026-09-21 18:01:21 +01:00
1 parent bf7bf48163
commit ae0ea9ab22
4 files changed
+83 -41

No files matched your search

+31 -24
View File
@@ -225,6 +225,23 @@ async fn run_server(state: Arc<MemoryState>) -> Result<(), Box<dyn std::error::E
next_id: AtomicUsize::new(1),
});
let app_state_clone = Arc::clone(&app_state);
let mut rx = state.activity_tx.subscribe();
tokio::spawn(async move {
while let Ok(msg) = rx.recv().await {
let senders: Vec<_> = app_state_clone
.clients
.read()
.unwrap_or_else(|e| e.into_inner())
.values()
.cloned()
.collect();
for client_tx in senders {
let _ = client_tx.try_send(msg.clone());
}
}
});
let app = Router::new()
.route(
"/api/version",
@@ -350,6 +367,18 @@ async fn run_server(state: Arc<MemoryState>) -> Result<(), Box<dyn std::error::E
}
}),
)
.route(
"/api/activity",
get({
let state_clone = app_state.handler.state.clone();
move || async move {
let activities = state_clone.recent_activities.read_with(|a| {
a.iter().cloned().collect::<Vec<_>>()
});
axum::Json(serde_json::json!(activities))
}
}),
)
.route(
"/api/stats",
get({
@@ -491,30 +520,7 @@ async fn handle_socket(socket: WebSocket, state: Arc<AppState>, client_type: Str
.and_then(|p| p.get("name"))
.and_then(|n| n.as_str())
.unwrap_or("unknown_tool");
let activity_msg = format!("Agent executed tool: {}", name);
let event = serde_json::json!({
"type": "activity",
"data": activity_msg
});
let senders: Vec<_> = state_clone
.clients
.read()
.unwrap_or_else(|e| e.into_inner())
.iter()
.filter_map(|(id, tx)| {
if id != &session_id_clone {
Some(tx.clone())
} else {
None
}
})
.collect();
for client_tx in senders {
let _ = client_tx.try_send(event.to_string());
}
handler.state.broadcast_activity(&format!("Agent executed tool: {}", name));
}
} // End if proxy
@@ -840,6 +846,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
tech_debts: Store::new("tech_debts", db.clone()),
gates: Store::new("gates", db.clone()),
context_workspaces: Store::new("context_workspaces", db.clone()),
recent_activities: Store::new("recent_activities", db.clone()),
activity_tx: tokio::sync::broadcast::channel(100).0,
});