mirror of
https://github.com/samvallad33/vestige.git
synced 2026-07-04 22:02:14 +02:00
feat: live memory materialization — nodes spawn in 3D graph in real-time
When memories are created, promoted, deleted, or dreamed via MCP tools, the 3D graph now shows spectacular live animations: - Rainbow particle burst + elastic scale-up on MemoryCreated - Ripple wave cascading to nearby nodes - Green pulse + node growth on MemoryPromoted - Implosion + dissolution on MemoryDeleted - Edge growth animation on ConnectionDiscovered - Purple cascade on DreamStarted/DreamProgress/DreamCompleted - FIFO eviction at 50 live nodes to guard performance Also: graph center defaults to most-connected node, legacy HTML redirects to SvelteKit dashboard, CSS height chain fix in layout. Testing: 150 unit tests (vitest), 11 e2e tests (Playwright with MCP Streamable HTTP client), 22 proof screenshots. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
816b577f69
commit
9bdcc69ce3
76 changed files with 5915 additions and 332 deletions
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "vestige-core"
|
||||
version = "2.0.2"
|
||||
version = "2.0.3"
|
||||
edition = "2024"
|
||||
rust-version = "1.91"
|
||||
authors = ["Vestige Team"]
|
||||
|
|
|
|||
|
|
@ -3532,6 +3532,21 @@ impl Storage {
|
|||
Ok(result)
|
||||
}
|
||||
|
||||
/// Get the memory with the most connections (best center node for graph visualization)
|
||||
pub fn get_most_connected_memory(&self) -> Result<Option<String>> {
|
||||
let reader = self.reader.lock()
|
||||
.map_err(|_| StorageError::Init("Reader lock poisoned".into()))?;
|
||||
let mut stmt = reader.prepare(
|
||||
"SELECT id, COUNT(*) as cnt FROM (
|
||||
SELECT source_id as id FROM memory_connections
|
||||
UNION ALL
|
||||
SELECT target_id as id FROM memory_connections
|
||||
) GROUP BY id ORDER BY cnt DESC LIMIT 1"
|
||||
)?;
|
||||
let result = stmt.query_row([], |row| row.get::<_, String>(0)).optional()?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// Get memories with their connection data for graph visualization
|
||||
pub fn get_memory_subgraph(&self, center_id: &str, depth: u32, max_nodes: usize) -> Result<(Vec<KnowledgeNode>, Vec<ConnectionRecord>)> {
|
||||
let mut visited_ids: std::collections::HashSet<String> = std::collections::HashSet::new();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "vestige-mcp"
|
||||
version = "2.0.2"
|
||||
version = "2.0.3"
|
||||
edition = "2024"
|
||||
description = "Cognitive memory MCP server for Claude - FSRS-6, spreading activation, synaptic tagging, 3D dashboard, and 130 years of memory research"
|
||||
authors = ["samvallad33"]
|
||||
|
|
@ -32,7 +32,7 @@ path = "src/bin/cli.rs"
|
|||
# ============================================================================
|
||||
# Includes: FSRS-6, spreading activation, synaptic tagging, hippocampal indexing,
|
||||
# memory states, context memory, importance signals, dreams, and more
|
||||
vestige-core = { version = "2.0.2", path = "../vestige-core", default-features = false, features = ["bundled-sqlite"] }
|
||||
vestige-core = { version = "2.0.3", path = "../vestige-core", default-features = false, features = ["bundled-sqlite"] }
|
||||
|
||||
# ============================================================================
|
||||
# MCP Server Dependencies
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use axum::extract::{Path, Query, State};
|
||||
use axum::http::StatusCode;
|
||||
use axum::response::{Html, Json};
|
||||
use axum::response::{Json, Redirect};
|
||||
use chrono::{Duration, Utc};
|
||||
use serde::Deserialize;
|
||||
use serde_json::Value;
|
||||
|
|
@ -12,9 +12,9 @@ use serde_json::Value;
|
|||
use super::events::VestigeEvent;
|
||||
use super::state::AppState;
|
||||
|
||||
/// Serve the dashboard HTML
|
||||
pub async fn serve_dashboard() -> Html<&'static str> {
|
||||
Html(include_str!("../dashboard.html"))
|
||||
/// Redirect root to the SvelteKit dashboard
|
||||
pub async fn serve_dashboard() -> Redirect {
|
||||
Redirect::permanent("/dashboard")
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
|
|
@ -328,9 +328,9 @@ pub async fn health_check(
|
|||
// MEMORY GRAPH
|
||||
// ============================================================================
|
||||
|
||||
/// Serve the memory graph visualization HTML
|
||||
pub async fn serve_graph() -> Html<&'static str> {
|
||||
Html(include_str!("../graph.html"))
|
||||
/// Redirect legacy graph to SvelteKit dashboard graph page
|
||||
pub async fn serve_graph() -> Redirect {
|
||||
Redirect::permanent("/dashboard/graph")
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
|
|
@ -360,13 +360,21 @@ pub async fn get_graph(
|
|||
.map(|n| n.id.clone())
|
||||
.ok_or(StatusCode::NOT_FOUND)?
|
||||
} else {
|
||||
// Default: most recent memory
|
||||
let recent = state.storage
|
||||
.get_all_nodes(1, 0)
|
||||
// Default: most connected memory (for a rich initial graph)
|
||||
let most_connected = state.storage
|
||||
.get_most_connected_memory()
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||
recent.first()
|
||||
.map(|n| n.id.clone())
|
||||
.ok_or(StatusCode::NOT_FOUND)?
|
||||
if let Some(id) = most_connected {
|
||||
id
|
||||
} else {
|
||||
// Fallback: most recent memory
|
||||
let recent = state.storage
|
||||
.get_all_nodes(1, 0)
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||
recent.first()
|
||||
.map(|n| n.id.clone())
|
||||
.ok_or(StatusCode::NOT_FOUND)?
|
||||
}
|
||||
};
|
||||
|
||||
// Get subgraph
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue