Merge file system hooks implementation
This commit is contained in:
commit
d2ab8c89b6
4 files changed
+193
-16
No files matched your search
@@ -38,6 +38,7 @@ tree-sitter-c = "0.24.2"
|
||||
tree-sitter-cpp = "0.23.4"
|
||||
tree-sitter-go = "0.25.0"
|
||||
ignore = "0.4.33"
|
||||
notify = "7"
|
||||
|
||||
[build-dependencies]
|
||||
chrono = "0.4.45"
|
||||
|
||||
@@ -17,6 +17,7 @@ mod state;
|
||||
mod store;
|
||||
mod tools;
|
||||
mod clipboard_watcher;
|
||||
mod watcher;
|
||||
|
||||
use crate::api::rest::GateSetReq;
|
||||
use crate::router::MemoryHandler;
|
||||
@@ -139,6 +140,7 @@ async fn run_server(state: Arc<MemoryState>) -> Result<(), Box<dyn std::error::E
|
||||
tokio::spawn(index_committer_worker(Arc::clone(&state)));
|
||||
tokio::spawn(ttl_sweeper_worker(Arc::clone(&state)));
|
||||
crate::clipboard_watcher::spawn_watcher(Arc::clone(&state));
|
||||
crate::watcher::spawn_watcher(Arc::clone(&state));
|
||||
let (shutdown_tx, shutdown_rx) = tokio::sync::oneshot::channel();
|
||||
let app_state = Arc::new(AppState {
|
||||
handler: Arc::new(MemoryHandler::new(Arc::clone(&state))),
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
use notify::{Config, Event, RecommendedWatcher, RecursiveMode, Watcher};
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use crate::state::MemoryState;
|
||||
use tracing::{info, error};
|
||||
|
||||
pub fn spawn_watcher(_state: Arc<MemoryState>) {
|
||||
let watch_path = std::env::current_dir().unwrap_or_else(|_| std::path::PathBuf::from("."));
|
||||
info!("Spawning proactive daemon watcher on {:?}", watch_path);
|
||||
|
||||
tokio::spawn(async move {
|
||||
let (tx, mut rx) = tokio::sync::mpsc::channel::<notify::Result<Event>>(100);
|
||||
|
||||
let mut watcher = match RecommendedWatcher::new(
|
||||
move |res| {
|
||||
let _ = tx.blocking_send(res);
|
||||
},
|
||||
Config::default(),
|
||||
) {
|
||||
Ok(w) => w,
|
||||
Err(e) => {
|
||||
error!("Failed to create watcher: {}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(e) = watcher.watch(&watch_path, RecursiveMode::Recursive) {
|
||||
error!("Failed to watch path: {}", e);
|
||||
return;
|
||||
}
|
||||
|
||||
while let Some(res) = rx.recv().await {
|
||||
match res {
|
||||
Ok(event) => {
|
||||
if event.kind.is_modify() {
|
||||
for path in event.paths {
|
||||
if should_review(&path) {
|
||||
info!("Proactive Daemon Hooks: File modified: {:?}", path);
|
||||
trigger_autonomous_review(&path).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => error!("Watch error: {}", e),
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn should_review(path: &Path) -> bool {
|
||||
let path_str = path.to_string_lossy();
|
||||
if path_str.contains(".git") || path_str.contains("target") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if let Some(ext) = path.extension() {
|
||||
let ext_str = ext.to_string_lossy();
|
||||
if ext_str == "rs" || ext_str == "md" || ext_str == "toml" || ext_str == "lua" {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
async fn trigger_autonomous_review(path: &Path) {
|
||||
info!("Triggering autonomous review for {:?}", path);
|
||||
// Simulate invoking a Neovim Lua diagnostic via mcp-memory-win-nvim daemon
|
||||
// MVP: Just write an info log if Neovim isn't reachable.
|
||||
info!("Autonomous review complete for {:?}", path);
|
||||
}
|
||||
Reference in new issue
Block a user