mirror of
https://github.com/samvallad33/vestige.git
synced 2026-05-08 23:32:37 +02:00
feat: Vestige v1.3.0 — importance scoring, session checkpoints, duplicate detection
3 new MCP tools (16 → 19 total): - importance_score: 4-channel neuroscience importance scoring (novelty/arousal/reward/attention) - session_checkpoint: batch smart_ingest up to 20 items with PE Gating - find_duplicates: cosine similarity clustering with union-find for dedup CLI: vestige ingest command for memory ingestion via command line Core: made get_node_embedding public, added get_all_embeddings for dedup scanning Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
5cca386d6b
commit
04a3062328
9 changed files with 848 additions and 5 deletions
|
|
@ -94,6 +94,21 @@ enum Commands {
|
|||
#[arg(long)]
|
||||
no_open: bool,
|
||||
},
|
||||
|
||||
/// Ingest a memory (routes through Prediction Error Gating)
|
||||
Ingest {
|
||||
/// Content to remember
|
||||
content: String,
|
||||
/// Tags (comma-separated)
|
||||
#[arg(long)]
|
||||
tags: Option<String>,
|
||||
/// Node type (fact, concept, event, person, place, note, pattern, decision)
|
||||
#[arg(long, default_value = "fact")]
|
||||
node_type: String,
|
||||
/// Source reference
|
||||
#[arg(long)]
|
||||
source: Option<String>,
|
||||
},
|
||||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
|
|
@ -118,6 +133,12 @@ fn main() -> anyhow::Result<()> {
|
|||
yes,
|
||||
} => run_gc(min_retention, max_age_days, dry_run, yes),
|
||||
Commands::Dashboard { port, no_open } => run_dashboard(port, !no_open),
|
||||
Commands::Ingest {
|
||||
content,
|
||||
tags,
|
||||
node_type,
|
||||
source,
|
||||
} => run_ingest(content, tags, node_type, source),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -842,6 +863,83 @@ fn run_gc(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Ingest a memory via CLI (routes through smart_ingest / PE Gating)
|
||||
fn run_ingest(
|
||||
content: String,
|
||||
tags: Option<String>,
|
||||
node_type: String,
|
||||
source: Option<String>,
|
||||
) -> anyhow::Result<()> {
|
||||
if content.trim().is_empty() {
|
||||
anyhow::bail!("Content cannot be empty");
|
||||
}
|
||||
|
||||
let tag_list: Vec<String> = tags
|
||||
.as_deref()
|
||||
.map(|t| {
|
||||
t.split(',')
|
||||
.map(|s| s.trim().to_string())
|
||||
.filter(|s| !s.is_empty())
|
||||
.collect()
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
let input = IngestInput {
|
||||
content: content.clone(),
|
||||
node_type,
|
||||
source,
|
||||
sentiment_score: 0.0,
|
||||
sentiment_magnitude: 0.0,
|
||||
tags: tag_list,
|
||||
valid_from: None,
|
||||
valid_until: None,
|
||||
};
|
||||
|
||||
let mut storage = Storage::new(None)?;
|
||||
|
||||
// Try smart_ingest (PE Gating) if available, otherwise regular ingest
|
||||
#[cfg(all(feature = "embeddings", feature = "vector-search"))]
|
||||
{
|
||||
let result = storage.smart_ingest(input)?;
|
||||
println!("{}", "=== Vestige Ingest ===".cyan().bold());
|
||||
println!();
|
||||
println!("{}: {}", "Decision".white().bold(), result.decision.green());
|
||||
println!("{}: {}", "Node ID".white().bold(), result.node.id);
|
||||
if let Some(sim) = result.similarity {
|
||||
println!("{}: {:.3}", "Similarity".white().bold(), sim);
|
||||
}
|
||||
if let Some(pe) = result.prediction_error {
|
||||
println!("{}: {:.3}", "Prediction Error".white().bold(), pe);
|
||||
}
|
||||
println!("{}: {}", "Reason".white().bold(), result.reason);
|
||||
println!();
|
||||
println!(
|
||||
"{}",
|
||||
format!("Memory {} ({})", result.decision, truncate(&content, 60))
|
||||
.green()
|
||||
.bold()
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(not(all(feature = "embeddings", feature = "vector-search")))]
|
||||
{
|
||||
let node = storage.ingest(input)?;
|
||||
println!("{}", "=== Vestige Ingest ===".cyan().bold());
|
||||
println!();
|
||||
println!("{}: create", "Decision".white().bold());
|
||||
println!("{}: {}", "Node ID".white().bold(), node.id);
|
||||
println!();
|
||||
println!(
|
||||
"{}",
|
||||
format!("Memory created ({})", truncate(&content, 60))
|
||||
.green()
|
||||
.bold()
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Run the dashboard web server
|
||||
fn run_dashboard(port: u16, open_browser: bool) -> anyhow::Result<()> {
|
||||
println!("{}", "=== Vestige Dashboard ===".cyan().bold());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue