daemon status: add in-flight tasks, recent completions, and node history command
Show running/pending tasks with elapsed time, progress, and last 3 output lines. Show last 20 completed/failed jobs from daemon log. Both displayed before the existing grouped task view. Add 'poc-memory history KEY' command that replays the append-only node log to show all versions of a key with version number, weight, timestamp, and content preview. Useful for auditing what modified a node.
This commit is contained in:
parent
f4c4e1bb39
commit
851fc0d417
2 changed files with 134 additions and 0 deletions
52
src/main.rs
52
src/main.rs
|
|
@ -107,6 +107,7 @@ fn main() {
|
|||
"journal-ts-migrate" => cmd_journal_ts_migrate(),
|
||||
"load-context" => cmd_load_context(&args[2..]),
|
||||
"render" => cmd_render(&args[2..]),
|
||||
"history" => cmd_history(&args[2..]),
|
||||
"write" => cmd_write(&args[2..]),
|
||||
"import" => cmd_import(&args[2..]),
|
||||
"export" => cmd_export(&args[2..]),
|
||||
|
|
@ -1547,6 +1548,57 @@ fn cmd_render(args: &[String]) -> Result<(), String> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn cmd_history(args: &[String]) -> Result<(), String> {
|
||||
if args.is_empty() {
|
||||
return Err("Usage: poc-memory history KEY".into());
|
||||
}
|
||||
let key = args.join(" ");
|
||||
|
||||
// Replay the node log, collecting all versions of this key
|
||||
let path = store::nodes_path();
|
||||
if !path.exists() {
|
||||
return Err("No node log found".into());
|
||||
}
|
||||
|
||||
use std::io::BufReader;
|
||||
let file = std::fs::File::open(&path)
|
||||
.map_err(|e| format!("open {}: {}", path.display(), e))?;
|
||||
let mut reader = BufReader::new(file);
|
||||
|
||||
let mut versions: Vec<store::Node> = Vec::new();
|
||||
while let Ok(msg) = capnp::serialize::read_message(&mut reader, capnp::message::ReaderOptions::new()) {
|
||||
let log = msg.get_root::<poc_memory::memory_capnp::node_log::Reader>()
|
||||
.map_err(|e| format!("read log: {}", e))?;
|
||||
for node_reader in log.get_nodes()
|
||||
.map_err(|e| format!("get nodes: {}", e))? {
|
||||
let node = store::Node::from_capnp(node_reader)?;
|
||||
if node.key == key {
|
||||
versions.push(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if versions.is_empty() {
|
||||
return Err(format!("No history found for '{}'", key));
|
||||
}
|
||||
|
||||
eprintln!("{} versions of '{}':\n", versions.len(), key);
|
||||
for (i, node) in versions.iter().enumerate() {
|
||||
let preview: String = node.content.chars().take(200).collect();
|
||||
let preview = preview.replace('\n', "\\n");
|
||||
eprintln!(" v{} (w={:.3}, {}): {}",
|
||||
node.version, node.weight, node.timestamp, preview);
|
||||
}
|
||||
|
||||
// Show latest full content
|
||||
if let Some(latest) = versions.last() {
|
||||
eprintln!("\n--- Latest content (v{}) ---", latest.version);
|
||||
print!("{}", latest.content);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn cmd_write(args: &[String]) -> Result<(), String> {
|
||||
if args.is_empty() {
|
||||
return Err("Usage: poc-memory write KEY < content\n\
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue