forked from kent/consciousness
kill cli/misc.rs
This commit is contained in:
parent
5a832b1d6c
commit
70097fa84b
6 changed files with 157 additions and 162 deletions
|
|
@ -479,3 +479,32 @@ pub fn cmd_export(files: &[String], export_all: bool) -> Result<(), String> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cmd_status() -> Result<(), String> {
|
||||||
|
// TUI moved to consciousness binary (F4 unconscious screen)
|
||||||
|
|
||||||
|
let store = crate::store::Store::load()?;
|
||||||
|
let g = store.build_graph();
|
||||||
|
|
||||||
|
let mut type_counts = std::collections::HashMap::new();
|
||||||
|
for node in store.nodes.values() {
|
||||||
|
*type_counts.entry(format!("{:?}", node.node_type)).or_insert(0usize) += 1;
|
||||||
|
}
|
||||||
|
let mut types: Vec<_> = type_counts.iter().collect();
|
||||||
|
types.sort_by_key(|(_, c)| std::cmp::Reverse(**c));
|
||||||
|
|
||||||
|
println!("Nodes: {} Relations: {}", store.nodes.len(), store.relations.len());
|
||||||
|
print!("Types:");
|
||||||
|
for (t, c) in &types {
|
||||||
|
let label = match t.as_str() {
|
||||||
|
"Semantic" => "semantic",
|
||||||
|
"EpisodicSession" | "EpisodicDaily" | "EpisodicWeekly" | "EpisodicMonthly"
|
||||||
|
=> "episodic",
|
||||||
|
_ => t,
|
||||||
|
};
|
||||||
|
print!(" {}={}", label, c);
|
||||||
|
}
|
||||||
|
println!();
|
||||||
|
println!("Graph edges: {} Communities: {}",
|
||||||
|
g.edge_count(), g.community_count());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
||||||
156
src/cli/misc.rs
156
src/cli/misc.rs
|
|
@ -1,156 +0,0 @@
|
||||||
// cli/misc.rs — misc subcommand handlers
|
|
||||||
|
|
||||||
|
|
||||||
pub fn cmd_search(keys: &[String]) -> Result<(), String> {
|
|
||||||
if keys.is_empty() {
|
|
||||||
return Err("search requires seed keys".into());
|
|
||||||
}
|
|
||||||
let result = crate::mcp_server::memory_rpc(
|
|
||||||
"memory_search",
|
|
||||||
serde_json::json!({"keys": keys}),
|
|
||||||
).map_err(|e| e.to_string())?;
|
|
||||||
print!("{}", result);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn cmd_status() -> Result<(), String> {
|
|
||||||
// TUI moved to consciousness binary (F4 unconscious screen)
|
|
||||||
|
|
||||||
let store = crate::store::Store::load()?;
|
|
||||||
let g = store.build_graph();
|
|
||||||
|
|
||||||
let mut type_counts = std::collections::HashMap::new();
|
|
||||||
for node in store.nodes.values() {
|
|
||||||
*type_counts.entry(format!("{:?}", node.node_type)).or_insert(0usize) += 1;
|
|
||||||
}
|
|
||||||
let mut types: Vec<_> = type_counts.iter().collect();
|
|
||||||
types.sort_by_key(|(_, c)| std::cmp::Reverse(**c));
|
|
||||||
|
|
||||||
println!("Nodes: {} Relations: {}", store.nodes.len(), store.relations.len());
|
|
||||||
print!("Types:");
|
|
||||||
for (t, c) in &types {
|
|
||||||
let label = match t.as_str() {
|
|
||||||
"Semantic" => "semantic",
|
|
||||||
"EpisodicSession" | "EpisodicDaily" | "EpisodicWeekly" | "EpisodicMonthly"
|
|
||||||
=> "episodic",
|
|
||||||
_ => t,
|
|
||||||
};
|
|
||||||
print!(" {}={}", label, c);
|
|
||||||
}
|
|
||||||
println!();
|
|
||||||
println!("Graph edges: {} Communities: {}",
|
|
||||||
g.edge_count(), g.community_count());
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn cmd_query(expr: &[String]) -> Result<(), String> {
|
|
||||||
if expr.is_empty() {
|
|
||||||
return Err("query requires an expression (try: poc-memory query --help)".into());
|
|
||||||
}
|
|
||||||
|
|
||||||
let query_str = expr.join(" ");
|
|
||||||
let result = crate::mcp_server::memory_rpc(
|
|
||||||
"memory_query",
|
|
||||||
serde_json::json!({"query": query_str}),
|
|
||||||
).map_err(|e| e.to_string())?;
|
|
||||||
print!("{}", result);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get group content via RPC (handles daemon or local fallback)
|
|
||||||
pub fn get_group_content(group: &crate::config::ContextGroup, cfg: &crate::config::Config) -> Vec<(String, String)> {
|
|
||||||
match group.source {
|
|
||||||
crate::config::ContextSource::Journal => {
|
|
||||||
// Query for recent journal entries
|
|
||||||
let window: i64 = cfg.journal_days as i64 * 24 * 3600;
|
|
||||||
let query = format!("all | type:episodic | age:<{} | sort:timestamp | limit:{}",
|
|
||||||
window, cfg.journal_max);
|
|
||||||
|
|
||||||
let keys_str = match crate::mcp_server::memory_rpc(
|
|
||||||
"memory_query",
|
|
||||||
serde_json::json!({"query": query}),
|
|
||||||
) {
|
|
||||||
Ok(s) => s,
|
|
||||||
Err(_) => return vec![],
|
|
||||||
};
|
|
||||||
|
|
||||||
// Parse keys (one per line) and render each
|
|
||||||
keys_str.lines()
|
|
||||||
.filter(|k| !k.is_empty() && *k != "no results")
|
|
||||||
.filter_map(|key| {
|
|
||||||
let content = crate::mcp_server::memory_rpc(
|
|
||||||
"memory_render",
|
|
||||||
serde_json::json!({"key": key, "raw": true}),
|
|
||||||
).ok()?;
|
|
||||||
if content.trim().is_empty() { return None; }
|
|
||||||
Some((key.to_string(), content))
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
crate::config::ContextSource::File => {
|
|
||||||
group.keys.iter().filter_map(|key| {
|
|
||||||
let content = std::fs::read_to_string(cfg.identity_dir.join(key)).ok()?;
|
|
||||||
if content.trim().is_empty() { return None; }
|
|
||||||
Some((key.clone(), content.trim().to_string()))
|
|
||||||
}).collect()
|
|
||||||
}
|
|
||||||
crate::config::ContextSource::Store => {
|
|
||||||
group.keys.iter().filter_map(|key| {
|
|
||||||
let content = crate::mcp_server::memory_rpc(
|
|
||||||
"memory_render",
|
|
||||||
serde_json::json!({"key": key, "raw": true}),
|
|
||||||
).ok()?;
|
|
||||||
if content.trim().is_empty() { return None; }
|
|
||||||
Some((key.clone(), content.trim().to_string()))
|
|
||||||
}).collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn cmd_load_context(stats: bool) -> Result<(), String> {
|
|
||||||
let cfg = crate::config::get();
|
|
||||||
|
|
||||||
if stats {
|
|
||||||
let mut total_words = 0;
|
|
||||||
let mut total_entries = 0;
|
|
||||||
println!("{:<25} {:>6} {:>8}", "GROUP", "ITEMS", "WORDS");
|
|
||||||
println!("{}", "-".repeat(42));
|
|
||||||
|
|
||||||
for group in &cfg.context_groups {
|
|
||||||
let entries = get_group_content(group, &cfg);
|
|
||||||
let words: usize = entries.iter()
|
|
||||||
.map(|(_, c)| c.split_whitespace().count())
|
|
||||||
.sum();
|
|
||||||
let count = entries.len();
|
|
||||||
println!("{:<25} {:>6} {:>8}", group.label, count, words);
|
|
||||||
total_words += words;
|
|
||||||
total_entries += count;
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("{}", "-".repeat(42));
|
|
||||||
println!("{:<25} {:>6} {:>8}", "TOTAL", total_entries, total_words);
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("=== MEMORY SYSTEM ({}) ===", cfg.assistant_name);
|
|
||||||
|
|
||||||
for group in &cfg.context_groups {
|
|
||||||
let entries = get_group_content(group, &cfg);
|
|
||||||
if !entries.is_empty() && group.source == crate::config::ContextSource::Journal {
|
|
||||||
println!("--- recent journal entries ({}/{}) ---",
|
|
||||||
entries.len(), cfg.journal_max);
|
|
||||||
}
|
|
||||||
for (key, content) in entries {
|
|
||||||
if group.source == crate::config::ContextSource::Journal {
|
|
||||||
println!("## {}", key);
|
|
||||||
} else {
|
|
||||||
println!("--- {} ({}) ---", key, group.label);
|
|
||||||
}
|
|
||||||
println!("{}\n", content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("=== END MEMORY LOAD ===");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -8,7 +8,6 @@ pub mod node;
|
||||||
pub mod agent;
|
pub mod agent;
|
||||||
pub mod admin;
|
pub mod admin;
|
||||||
pub mod journal;
|
pub mod journal;
|
||||||
pub mod misc;
|
|
||||||
|
|
||||||
/// Exit silently if POC_MEMORY_DRY_RUN=1.
|
/// Exit silently if POC_MEMORY_DRY_RUN=1.
|
||||||
pub fn check_dry_run() {
|
pub fn check_dry_run() {
|
||||||
|
|
|
||||||
123
src/cli/node.rs
123
src/cli/node.rs
|
|
@ -156,3 +156,126 @@ pub fn cmd_edit(key: &[String]) -> Result<(), String> {
|
||||||
println!("{}", result);
|
println!("{}", result);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cmd_search(keys: &[String]) -> Result<(), String> {
|
||||||
|
if keys.is_empty() {
|
||||||
|
return Err("search requires seed keys".into());
|
||||||
|
}
|
||||||
|
let result = crate::mcp_server::memory_rpc(
|
||||||
|
"memory_search",
|
||||||
|
serde_json::json!({"keys": keys}),
|
||||||
|
).map_err(|e| e.to_string())?;
|
||||||
|
print!("{}", result);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cmd_query(expr: &[String]) -> Result<(), String> {
|
||||||
|
if expr.is_empty() {
|
||||||
|
return Err("query requires an expression (try: poc-memory query --help)".into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let query_str = expr.join(" ");
|
||||||
|
let result = crate::mcp_server::memory_rpc(
|
||||||
|
"memory_query",
|
||||||
|
serde_json::json!({"query": query_str}),
|
||||||
|
).map_err(|e| e.to_string())?;
|
||||||
|
print!("{}", result);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get group content via RPC (handles daemon or local fallback)
|
||||||
|
pub fn get_group_content(group: &crate::config::ContextGroup, cfg: &crate::config::Config) -> Vec<(String, String)> {
|
||||||
|
match group.source {
|
||||||
|
crate::config::ContextSource::Journal => {
|
||||||
|
// Query for recent journal entries
|
||||||
|
let window: i64 = cfg.journal_days as i64 * 24 * 3600;
|
||||||
|
let query = format!("all | type:episodic | age:<{} | sort:timestamp | limit:{}",
|
||||||
|
window, cfg.journal_max);
|
||||||
|
|
||||||
|
let keys_str = match crate::mcp_server::memory_rpc(
|
||||||
|
"memory_query",
|
||||||
|
serde_json::json!({"query": query}),
|
||||||
|
) {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(_) => return vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parse keys (one per line) and render each
|
||||||
|
keys_str.lines()
|
||||||
|
.filter(|k| !k.is_empty() && *k != "no results")
|
||||||
|
.filter_map(|key| {
|
||||||
|
let content = crate::mcp_server::memory_rpc(
|
||||||
|
"memory_render",
|
||||||
|
serde_json::json!({"key": key, "raw": true}),
|
||||||
|
).ok()?;
|
||||||
|
if content.trim().is_empty() { return None; }
|
||||||
|
Some((key.to_string(), content))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
crate::config::ContextSource::File => {
|
||||||
|
group.keys.iter().filter_map(|key| {
|
||||||
|
let content = std::fs::read_to_string(cfg.identity_dir.join(key)).ok()?;
|
||||||
|
if content.trim().is_empty() { return None; }
|
||||||
|
Some((key.clone(), content.trim().to_string()))
|
||||||
|
}).collect()
|
||||||
|
}
|
||||||
|
crate::config::ContextSource::Store => {
|
||||||
|
group.keys.iter().filter_map(|key| {
|
||||||
|
let content = crate::mcp_server::memory_rpc(
|
||||||
|
"memory_render",
|
||||||
|
serde_json::json!({"key": key, "raw": true}),
|
||||||
|
).ok()?;
|
||||||
|
if content.trim().is_empty() { return None; }
|
||||||
|
Some((key.clone(), content.trim().to_string()))
|
||||||
|
}).collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cmd_load_context(stats: bool) -> Result<(), String> {
|
||||||
|
let cfg = crate::config::get();
|
||||||
|
|
||||||
|
if stats {
|
||||||
|
let mut total_words = 0;
|
||||||
|
let mut total_entries = 0;
|
||||||
|
println!("{:<25} {:>6} {:>8}", "GROUP", "ITEMS", "WORDS");
|
||||||
|
println!("{}", "-".repeat(42));
|
||||||
|
|
||||||
|
for group in &cfg.context_groups {
|
||||||
|
let entries = get_group_content(group, &cfg);
|
||||||
|
let words: usize = entries.iter()
|
||||||
|
.map(|(_, c)| c.split_whitespace().count())
|
||||||
|
.sum();
|
||||||
|
let count = entries.len();
|
||||||
|
println!("{:<25} {:>6} {:>8}", group.label, count, words);
|
||||||
|
total_words += words;
|
||||||
|
total_entries += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("{}", "-".repeat(42));
|
||||||
|
println!("{:<25} {:>6} {:>8}", "TOTAL", total_entries, total_words);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("=== MEMORY SYSTEM ({}) ===", cfg.assistant_name);
|
||||||
|
|
||||||
|
for group in &cfg.context_groups {
|
||||||
|
let entries = get_group_content(group, &cfg);
|
||||||
|
if !entries.is_empty() && group.source == crate::config::ContextSource::Journal {
|
||||||
|
println!("--- recent journal entries ({}/{}) ---",
|
||||||
|
entries.len(), cfg.journal_max);
|
||||||
|
}
|
||||||
|
for (key, content) in entries {
|
||||||
|
if group.source == crate::config::ContextSource::Journal {
|
||||||
|
println!("## {}", key);
|
||||||
|
} else {
|
||||||
|
println!("--- {} ({}) ---", key, group.label);
|
||||||
|
}
|
||||||
|
println!("{}\n", content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("=== END MEMORY LOAD ===");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -437,15 +437,15 @@ trait Run {
|
||||||
impl Run for Command {
|
impl Run for Command {
|
||||||
fn run(self) -> Result<(), String> {
|
fn run(self) -> Result<(), String> {
|
||||||
match self {
|
match self {
|
||||||
Self::Search { keys } => cli::misc::cmd_search(&keys),
|
Self::Search { keys } => cli::node::cmd_search(&keys),
|
||||||
Self::Render { key } => cli::node::cmd_render(&key),
|
Self::Render { key } => cli::node::cmd_render(&key),
|
||||||
Self::Write { key } => cli::node::cmd_write(&key),
|
Self::Write { key } => cli::node::cmd_write(&key),
|
||||||
Self::Edit { key } => cli::node::cmd_edit(&key),
|
Self::Edit { key } => cli::node::cmd_edit(&key),
|
||||||
Self::History { full, key } => cli::node::cmd_history(&key, full),
|
Self::History { full, key } => cli::node::cmd_history(&key, full),
|
||||||
Self::Tail { n, full, provenance, all_versions }
|
Self::Tail { n, full, provenance, all_versions }
|
||||||
=> cli::journal::cmd_tail(n, full, provenance.as_deref(), !all_versions),
|
=> cli::journal::cmd_tail(n, full, provenance.as_deref(), !all_versions),
|
||||||
Self::Status => cli::misc::cmd_status(),
|
Self::Status => cli::admin::cmd_status(),
|
||||||
Self::Query { expr } => cli::misc::cmd_query(&expr),
|
Self::Query { expr } => cli::node::cmd_query(&expr),
|
||||||
Self::WeightSet { key, weight } => cli::node::cmd_weight_set(&key, weight),
|
Self::WeightSet { key, weight } => cli::node::cmd_weight_set(&key, weight),
|
||||||
Self::Node(sub) => sub.run(),
|
Self::Node(sub) => sub.run(),
|
||||||
Self::Journal(sub) => sub.run(),
|
Self::Journal(sub) => sub.run(),
|
||||||
|
|
@ -518,7 +518,7 @@ impl Run for AdminCmd {
|
||||||
Self::DailyCheck => cli::admin::cmd_daily_check(),
|
Self::DailyCheck => cli::admin::cmd_daily_check(),
|
||||||
Self::Import { files } => cli::admin::cmd_import(&files),
|
Self::Import { files } => cli::admin::cmd_import(&files),
|
||||||
Self::Export { files, all } => cli::admin::cmd_export(&files, all),
|
Self::Export { files, all } => cli::admin::cmd_export(&files, all),
|
||||||
Self::LoadContext { stats } => cli::misc::cmd_load_context(stats),
|
Self::LoadContext { stats } => cli::node::cmd_load_context(stats),
|
||||||
Self::MigrateTranscriptProgress => {
|
Self::MigrateTranscriptProgress => {
|
||||||
let mut store = store::Store::load()?;
|
let mut store = store::Store::load()?;
|
||||||
let count = store.migrate_transcript_progress()?;
|
let count = store.migrate_transcript_progress()?;
|
||||||
|
|
|
||||||
|
|
@ -474,7 +474,7 @@ fn resolve(
|
||||||
let mut keys = Vec::new();
|
let mut keys = Vec::new();
|
||||||
for group in &cfg.context_groups {
|
for group in &cfg.context_groups {
|
||||||
if !group.agent { continue; }
|
if !group.agent { continue; }
|
||||||
let entries = crate::cli::misc::get_group_content(group, &cfg);
|
let entries = crate::cli::node::get_group_content(group, &cfg);
|
||||||
for (key, content) in entries {
|
for (key, content) in entries {
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
writeln!(text, "--- {} ({}) ---", key, group.label).ok();
|
writeln!(text, "--- {} ({}) ---", key, group.label).ok();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue