diff --git a/bin_replace.pdb b/bin_replace.pdb deleted file mode 100644 index 5bc2bb2..0000000 Binary files a/bin_replace.pdb and /dev/null differ diff --git a/check_output.txt b/check_output.txt deleted file mode 100644 index 5636012..0000000 --- a/check_output.txt +++ /dev/null @@ -1 +0,0 @@ - Finished `dev` profile [unoptimized + debuginfo] target(s) in 14.64s diff --git a/clippy_output.txt b/clippy_output.txt deleted file mode 100644 index 098ea08..0000000 --- a/clippy_output.txt +++ /dev/null @@ -1,312 +0,0 @@ - Blocking waiting for file lock on package cache - Blocking waiting for file lock on package cache - Compiling proc-macro2 v1.0.107 - Compiling quote v1.0.47 - Compiling unicode-ident v1.0.24 - Compiling getrandom v0.4.3 - Compiling serde_core v1.0.229 - Checking windows-link v0.2.1 - Compiling cfg-if v1.0.4 - Compiling shlex v2.0.1 - Compiling find-msvc-tools v0.1.12 - Checking smallvec v1.16.0 - Checking stable_deref_trait v1.2.1 - Checking windows-sys v0.61.2 - Checking pin-project-lite v0.2.17 - Checking futures-core v0.3.34 - Checking memchr v2.8.3 - Checking itoa v1.0.18 - Compiling serde v1.0.229 - Checking bytes v1.12.1 - Checking once_cell v1.21.4 - Checking futures-sink v0.3.34 - Compiling parking_lot_core v0.9.12 - Checking scopeguard v1.2.0 - Checking slab v0.4.12 - Checking mio v1.2.3 - Checking socket2 v0.6.5 - Checking log v0.4.34 - Checking futures-channel v0.3.34 - Compiling version_check v0.9.5 - Compiling jobserver v0.1.35 - Checking lock_api v0.4.14 - Compiling zmij v1.0.23 - Checking futures-task v0.3.34 - Checking futures-io v0.3.34 - Compiling num-conv v0.2.2 - Compiling time-core v0.1.9 - Compiling cc v1.4.5 - Compiling autocfg v1.5.1 - Checking deranged v0.5.8 - Checking http v1.5.0 - Checking tracing-core v0.1.36 - Compiling syn v3.0.5 - Compiling syn v2.0.119 - Checking percent-encoding v2.3.2 - Checking litemap v0.8.3 - Compiling time-macros v0.2.32 - Checking writeable v0.6.4 - Checking powerfmt v0.2.0 - Checking equivalent v1.0.2 - Checking parking_lot v0.12.5 - Checking utf8_iter v1.0.4 - Compiling icu_normalizer_data v2.3.0 - Compiling icu_properties_data v2.3.0 - Checking fnv v1.0.7 - Compiling serde_json v1.0.151 - Checking http-body v1.1.0 - Checking hashbrown v0.17.1 - Compiling httparse v1.10.1 - Checking base64 v0.22.1 - Compiling synstructure v0.13.2 - Checking tower-service v0.3.3 - Compiling ring v0.17.14 - Compiling num-traits v0.2.19 - Checking indexmap v2.14.2 - Checking time v0.3.55 - Checking try-lock v0.2.5 - Compiling serde_derive v1.0.229 - Compiling zerovec-derive v0.11.6 - Compiling tokio-macros v2.7.2 - Compiling zerofrom-derive v0.1.7 - Compiling yoke-derive v0.8.2 - Compiling displaydoc v0.2.7 - Compiling futures-macro v0.3.34 - Compiling tracing-attributes v0.1.31 - Compiling zeroize_derive v1.5.0 - Checking tokio v1.53.1 - Compiling libc v0.2.189 - Checking atomic-waker v1.1.2 - Checking futures-util v0.3.34 - Checking subtle v2.6.1 - Checking zerofrom v0.1.8 - Checking want v0.3.1 - Checking zeroize v1.9.0 - Checking tracing v0.1.44 - Checking form_urlencoded v1.2.2 - Checking yoke v0.8.3 - Checking getrandom v0.2.17 - Checking httpdate v1.0.3 - Checking untrusted v0.9.0 - Checking rustls-pki-types v1.15.1 - Compiling generic-array v0.14.7 - Checking sync_wrapper v1.0.2 - Checking tower-layer v0.3.3 - Checking tokio-util v0.7.19 - Checking zerovec v0.11.8 - Checking zerotrie v0.2.5 - Compiling rustls v0.23.44 - Compiling pkg-config v0.3.34 - Checking ipnet v2.12.2 - Compiling async-trait v0.1.92 - Compiling cmake v0.1.58 - Compiling cookie v0.18.2 - Checking h2 v0.4.19 - Checking tinystr v0.8.4 - Checking potential_utf v0.1.6 - Compiling dunce v1.0.5 - Checking mime v0.3.17 - Compiling zstd-sys v2.1.0+zstd.1.5.7 - Compiling unicase v2.9.0 - Checking icu_locale_core v2.3.0 - Compiling thiserror v2.0.20 - Checking icu_collections v2.3.0 - Compiling fs_extra v1.3.0 - Compiling crossbeam-utils v0.8.23 - Checking typenum v1.20.1 - Compiling mime_guess v2.0.5 - Checking hyper v1.11.1 - Checking tower v0.5.3 - Checking rustls-webpki v0.103.15 - Checking icu_provider v2.3.1 - Compiling thiserror-impl v2.0.20 - Compiling aws-lc-sys v0.45.0 - Checking http-body-util v0.1.5 - Checking icu_normalizer v2.3.0 - Checking icu_properties v2.3.0 - Checking hyper-util v0.1.20 - Compiling litrs v1.0.0 - Checking ryu v1.0.23 - Checking psl-types v2.0.11 - Checking either v1.18.0 - Compiling crunchy v0.2.4 - Checking idna_adapter v1.2.2 - Checking serde_urlencoded v0.7.1 - Compiling document-features v0.2.12 - Checking idna v1.1.0 - Checking webpki-roots v1.0.9 - Compiling ident_case v1.0.1 - Checking tokio-rustls v0.26.5 - Checking byteorder v1.5.0 - Checking url v2.5.8 - Checking publicsuffix v2.3.0 - Checking bitflags v2.13.1 - Compiling crossbeam-epoch v0.9.21 - Compiling windows_x86_64_msvc v0.52.6 - Compiling zstd-safe v7.3.0 - Checking regex-syntax v0.8.11 - Compiling strsim v0.11.1 - Checking hyper-rustls v0.27.9 - Checking cookie_store v0.22.1 - Checking tower-http v0.6.11 - Compiling darling_core v0.24.1 - Checking block-buffer v0.10.4 - Checking crypto-common v0.1.7 - Checking num-integer v0.1.47 - Checking ownedbytes v0.9.0 - Compiling crossbeam-deque v0.8.8 - Compiling typeid v1.0.3 - Checking once_cell_polyfill v1.70.2 - Compiling aws-lc-rs v1.18.1 - Checking utf8parse v0.2.2 - Compiling prettyplease v0.3.0 - Checking anstyle v1.0.14 - Checking tantivy-common v0.11.0 - Checking anstyle-parse v1.0.0 - Compiling darling_macro v0.24.1 - Checking anstyle-wincon v3.0.11 - Checking num-bigint v0.4.8 - Checking digest v0.10.7 - Checking reqwest v0.12.28 - Checking bitpacking v0.9.3 - Checking futures-executor v0.3.34 - Compiling fs-err v3.3.1 - Checking anstyle-query v1.1.5 - Compiling rayon-core v1.13.0 - Checking colorchoice v1.0.5 - Checking is_terminal_polyfill v1.70.2 - Checking utf8-ranges v1.0.5 - Compiling rustversion v1.0.23 - Checking untrusted v0.7.1 - Compiling erased-serde v0.4.10 - Checking futures v0.3.34 - Checking tantivy-bitpacker v0.10.0 - Checking anstream v1.0.0 - Checking zstd v0.13.3 - Checking tantivy-fst v0.5.0 - Checking simple_asn1 v0.6.4 - Checking windows-targets v0.52.6 - Compiling darling v0.24.1 - Checking uuid v1.26.0 - Checking itertools v0.14.0 - Checking tokio-stream v0.1.19 - Checking rust-mcp-schema v2.0.0 - Checking pem v3.0.6 - Compiling crc32fast v1.5.1 - Checking minimal-lexical v0.2.1 - Checking signature v2.2.0 - Checking murmurhash32 v0.3.1 - Checking clap_lex v1.1.0 - Compiling heck v0.5.0 - Checking cpufeatures v0.2.17 - Checking allocator-api2 v0.2.21 - Checking foldhash v0.2.0 - Compiling typetag v0.2.23 - Compiling winapi v0.3.9 - Checking nom v7.1.3 - Checking tantivy-stacker v0.7.0 - Checking sha2 v0.10.9 - Compiling clap_derive v4.6.4 - Checking tantivy-sstable v0.7.0 - Checking hashbrown v0.16.1 - Checking clap_builder v4.6.6 - Compiling rust-mcp-macros v2.0.0 - Compiling bon-macros v3.10.1 - Checking rust-mcp-transport v2.0.0 - Checking windows-sys v0.59.0 - Checking hmac v0.12.1 - Checking regex-automata v0.4.18 - Checking axum-core v0.5.6 - Checking ordered-float v5.5.0 - Compiling typetag-impl v0.2.23 - Checking serde_path_to_error v0.1.20 - Checking fastrand v2.5.0 - Checking inventory v0.3.24 - Checking downcast-rs v2.0.2 - Checking matchit v0.8.4 - Checking fastdivide v0.4.2 - Checking option-ext v0.2.0 - Checking base64 v0.23.1 - Checking fs4 v0.13.1 - Checking arc-swap v1.9.2 - Checking tantivy-columnar v0.7.0 - Checking dirs-sys v0.5.0 - Checking tempfile v3.27.0 - Checking clap v4.6.6 - Checking regex v1.13.1 - Checking tantivy-query-grammar v0.26.0 - Checking axum v0.8.9 - Checking rayon v1.12.0 - Checking axum-server v0.8.0 - Checking lru v0.16.4 - Checking crossbeam-channel v0.5.17 - Checking rust-stemmers v1.2.0 - Checking sketches-ddsketch v0.4.1 - Checking tantivy-tokenizer-api v0.7.0 - Checking measure_time v0.9.0 - Checking aho-corasick v1.1.5 - Checking htmlescape v0.3.1 - Checking lz4_flex v0.13.1 - Checking bon v3.10.1 - Checking memmap2 v0.9.11 - Checking datasketches v0.2.0 - Checking levenshtein_automata v0.2.1 - Checking rustc-hash v2.1.3 - Checking oneshot v0.1.13 - Checking census v0.4.2 - Checking dirs v6.0.0 - Checking glob v0.3.4 - Checking mcp-memory-stub v0.1.0 (C:\Users\reazul.ashraf\workspace\rust\mcp-memory\stub) - Checking tantivy v0.26.1 -warning: this can be `std::io::Error::other(_)` - --> stub\src\main.rs:76:72 - | -76 | let stream = resp.bytes_stream().map(|res| res.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#io_other_error - = note: `#[warn(clippy::io_other_error)]` on by default -help: use `std::io::Error::other` - | -76 - let stream = resp.bytes_stream().map(|res| res.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))); -76 + let stream = resp.bytes_stream().map(|res| res.map_err(|e| std::io::Error::other(e))); - | - -warning: stripping a prefix manually - --> stub\src\main.rs:93:40 - | -93 | println!("{}", &trimmed[6..]); - | ^^^^^^^^^^^^^ - | -note: the prefix was tested here - --> stub\src\main.rs:91:24 - | -91 | } else if trimmed.starts_with("data: ") { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#manual_strip - = note: `#[warn(clippy::manual_strip)]` on by default -help: try using the `strip_prefix` method - | -91 ~ } else if let Some() = trimmed.strip_prefix("data: ") { -92 | if is_message { -93 ~ println!("{}", ); -94 | is_message = false; -95 | } else if is_endpoint { -96 ~ let ep = ; - | - -warning: redundant pattern matching - --> stub\src\main.rs:117:16 - | -117 | if let Err(_) = std::net::TcpStream::connect(cli.target.replace("http://", "").replace("https://", "")) { - | ^^^^^^ - | - = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#redundant_pattern_matching - = note: `#[warn(clippy::redundant_pattern_matching)]` on by default -help: consider using `is_err()` - | -117 - if let Err(_) = std::net::TcpStream::connect(cli.target.replace("http://", "").replace("https://", "")) { -117 + if std::net::TcpStream::connect(cli.target.replace("http://", "").replace("https://", "")).is_err() { - | - -warning: `mcp-memory-stub` (bin "mcp-memory-stub") generated 3 warnings (run `cargo clippy --fix --bin "mcp-memory-stub" -p mcp-memory-stub -- ` to apply 2 suggestions) diff --git a/dedup.py b/dedup.py deleted file mode 100644 index 1f72adf..0000000 --- a/dedup.py +++ /dev/null @@ -1,14 +0,0 @@ -import re - -with open("server/src/handlers.rs", "r", encoding="utf-8") as f: - text = f.read() - -pattern = r'"(list_milestones|list_pinned_files|read_handoff_memos)" => \{\s*let req = parse_tool!\(args, id, ([a-zA-Z]+)\);\s*let mut [a-zA-Z_]+ = self\.state\.([a-zA-Z_]+)\.read\(\);\s*if let Some\(ns\) = req\.namespace \{\s*[a-zA-Z_]+\.retain\(\|.\| \w+\.namespace == ns\);\s*\}\s*let data = serde_json::to_string\(&[a-zA-Z_]+\)\.unwrap_or_default\(\);\s*Ok\(data\.to_string\(\)\)\s*\}' - -def repl(m): - return f'"{m.group(1)}" => handle_list_with_namespace!(self, {m.group(3)}, {m.group(2)}, args, id),' - -new_text = re.sub(pattern, repl, text) - -with open("server/src/handlers.rs", "w", encoding="utf-8") as f: - f.write(new_text) diff --git a/dedup2.py b/dedup2.py deleted file mode 100644 index 7128092..0000000 --- a/dedup2.py +++ /dev/null @@ -1,14 +0,0 @@ -import re - -with open("server/src/handlers.rs", "r", encoding="utf-8") as f: - text = f.read() - -pattern = r'"([a-zA-Z_]+)" => \{\s*(?:let req = parse_tool!\(args, id, ([a-zA-Z]+)\);\s*)?let data = serde_json::to_string\(&self\.state\.([a-zA-Z_]+)\.read\(\)\)\s*\.unwrap_or_else\(\|_\| "\[\]"\.to_string\(\)\);\s*Ok\(data\.to_string\(\)\)\s*\}' - -def repl(m): - return f'"{m.group(1)}" => {{\n let data = serde_json::to_string(&self.state.{m.group(3)}.read()).unwrap_or_else(|_| "[]".to_string());\n Ok(data)\n}},' - -new_text = re.sub(pattern, repl, text) - -with open("server/src/handlers.rs", "w", encoding="utf-8") as f: - f.write(new_text) diff --git a/fix_warnings.py b/fix_warnings.py deleted file mode 100644 index 218b70c..0000000 --- a/fix_warnings.py +++ /dev/null @@ -1,40 +0,0 @@ -import re - -# 1. Fix stub/src/main.rs -stub_path = r'C:\Users\reazul.ashraf\workspace\rust\mcp-memory\stub\src\main.rs' -with open(stub_path, 'r', encoding='utf-8') as f: - content = f.read() -content = content.replace('use tokio::io::AsyncBufReadExt;\n', '') -with open(stub_path, 'w', encoding='utf-8') as f: - f.write(content) - -# 2. Fix nvim-core/src/lib.rs -nvim_path = r'C:\Users\reazul.ashraf\workspace\rust\mcp-memory\nvim-core\src\lib.rs' -with open(nvim_path, 'r', encoding='utf-8') as f: - content = f.read() -content = content.replace( - 'use tokio::io::{AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader};', - 'use tokio::io::{AsyncReadExt, AsyncWriteExt};' -) -with open(nvim_path, 'w', encoding='utf-8') as f: - f.write(content) - -# 3. Fix server/src/store.rs -store_path = r'C:\Users\reazul.ashraf\workspace\rust\mcp-memory\server\src\store.rs' -with open(store_path, 'r', encoding='utf-8') as f: - content = f.read() - -inspect_method = """ pub fn inspect(&self, f: F) -> R - where - F: FnOnce(&T) -> R, - { - let lock = self.cache.read().unwrap(); - f(&lock) - } - -""" -content = content.replace(inspect_method, "") -with open(store_path, 'w', encoding='utf-8') as f: - f.write(content) - -print("Warnings fixed!") diff --git a/patch_nvim.py b/patch_nvim.py deleted file mode 100644 index 64a3aa8..0000000 --- a/patch_nvim.py +++ /dev/null @@ -1,168 +0,0 @@ -import re -import sys - -with open('C:\\Users\\reazul.ashraf\\workspace\\rust\\mcp-memory\\nvim-core\\src\\lib.rs', 'r', encoding='utf-8') as f: - content = f.read() - -start_pattern = r'#\[cfg\(windows\)\]\nasync fn call_nvim' -end_pattern = r'async fn send_nvim_command' - -start_idx = re.search(start_pattern, content).start() -end_idx = re.search(end_pattern, content).start() - -new_code = """use std::sync::LazyLock; -use std::sync::Arc; -use tokio::sync::{Mutex, mpsc, oneshot}; -use std::collections::HashMap; -use tokio::io::{AsyncReadExt, AsyncWriteExt}; - -pub struct NvimRequest { - pub msgid_str: String, - pub req: rmpv::Value, - pub reply: oneshot::Sender>, -} - -static NVIM_CONN: LazyLock>>>> = LazyLock::new(|| Arc::new(Mutex::new(None))); - -async fn get_nvim_connection() -> Result, String> { - let mut conn_lock = NVIM_CONN.lock().await; - if let Some(sender) = conn_lock.as_ref() { - if !sender.is_closed() { - return Ok(sender.clone()); - } - } - - tracing::info!("Establishing new persistent connection to Neovim"); - let socket_path = get_socket_path().await?; - - #[cfg(windows)] - let stream = { - use tokio::net::windows::named_pipe::ClientOptions; - ClientOptions::new().open(&socket_path).map_err(|e| e.to_string())? - }; - - #[cfg(unix)] - let stream = { - use tokio::net::UnixStream; - UnixStream::connect(socket_path).await.map_err(|e| e.to_string())? - }; - - let (mut read_half, mut write_half) = tokio::io::split(stream); - let (tx, mut rx) = mpsc::channel::(32); - let pending_requests: Arc>>>> = Arc::new(Mutex::new(HashMap::new())); - - // Write task - let pending_clone = Arc::clone(&pending_requests); - tokio::spawn(async move { - while let Some(req) = rx.recv().await { - let mut buf = Vec::new(); - if let Err(e) = rmpv::encode::write_value(&mut buf, &req.req) { - let _ = req.reply.send(Err(e.to_string())); - continue; - } - - pending_clone.lock().await.insert(req.msgid_str.clone(), req.reply); - - if write_half.write_all(&buf).await.is_err() { - tracing::error!("Failed to write to Neovim socket"); - break; - } - } - }); - - // Read task - let pending_clone2 = Arc::clone(&pending_requests); - tokio::spawn(async move { - let mut resp_buf = Vec::new(); - let mut chunk = vec![0u8; 8192]; - let mut offset = 0; - - loop { - let mut cursor = std::io::Cursor::new(&resp_buf[offset..]); - match rmpv::decode::read_value(&mut cursor) { - Ok(val) => { - offset += cursor.position() as usize; - - if let rmpv::Value::Array(ref arr) = val { - if arr.len() >= 4 && arr[0] == rmpv::Value::Integer(1.into()) { - let msgid = &arr[1]; - let msgid_str = format!("{:?}", msgid); - - if let Some(reply_sender) = pending_clone2.lock().await.remove(&msgid_str) { - let _ = reply_sender.send(Ok(val)); - } - } - } - // Trim buffer if it gets too large - if offset > 1024 * 1024 { - resp_buf.drain(..offset); - offset = 0; - } - continue; - } - Err(_) => { - if offset > 0 { - resp_buf.drain(..offset); - offset = 0; - } - - let read_future = read_half.read(&mut chunk); - match tokio::time::timeout(tokio::time::Duration::from_secs(60), read_future).await { - Ok(Ok(n)) if n > 0 => { - resp_buf.extend_from_slice(&chunk[..n]); - } - _ => { - tracing::error!("Neovim socket read loop closed or timeout"); - break; - } - } - } - } - } - - // Cleanup pending requests on disconnect - let mut pending = pending_clone2.lock().await; - for (_, sender) in pending.drain() { - let _ = sender.send(Err("Connection closed".to_string())); - } - }); - - *conn_lock = Some(tx.clone()); - Ok(tx) -} - -async fn call_nvim(req: rmpv::Value) -> Result { - let msgid = if let rmpv::Value::Array(ref arr) = req { - if arr.len() > 1 { - arr[1].clone() - } else { - rmpv::Value::Nil - } - } else { - rmpv::Value::Nil - }; - - let msgid_str = format!("{:?}", msgid); - let tx = get_nvim_connection().await?; - let (reply_tx, reply_rx) = oneshot::channel(); - - tx.send(NvimRequest { - msgid_str, - req, - reply: reply_tx, - }).await.map_err(|_| "Failed to send request to Neovim connection manager")?; - - match tokio::time::timeout(tokio::time::Duration::from_secs(10), reply_rx).await { - Ok(Ok(res)) => res, - Ok(Err(_)) => Err("Response channel dropped".to_string()), - Err(_) => Err("Timeout waiting for Neovim response".to_string()), - } -} - -""" - -new_content = content[:start_idx] + new_code + content[end_idx:] -with open('C:\\Users\\reazul.ashraf\\workspace\\rust\\mcp-memory\\nvim-core\\src\\lib.rs', 'w', encoding='utf-8') as f: - f.write(new_content) - -print("Patched!") diff --git a/patch_nvim_macro.py b/patch_nvim_macro.py deleted file mode 100644 index 1da0e4a..0000000 --- a/patch_nvim_macro.py +++ /dev/null @@ -1,40 +0,0 @@ -import re -import sys - -with open('C:\\Users\\reazul.ashraf\\workspace\\rust\\mcp-memory\\nvim-core\\src\\lib.rs', 'r', encoding='utf-8') as f: - content = f.read() - -macro_def = """ -macro_rules! send_text_result { - ($id:expr, $text:expr) => { - send_response(JsonRpcResponse { - jsonrpc: "2.0".to_string(), - id: $id, - result: Some(json!({ - "content": [{"type": "text", "text": $text}] - })), - error: None, - }).await; - }; -} -""" - -if "macro_rules! send_text_result" not in content: - idx = content.find("pub async fn run_mcp_loop") - content = content[:idx] + macro_def + "\n" + content[idx:] - -# Find tools/call block -tools_call_idx = content.find('"tools/call" => {') -if tools_call_idx != -1: - block = content[tools_call_idx:] - - # Replace the verbose blocks - pattern = r'send_response\(JsonRpcResponse \{\s*jsonrpc: "2\.0"\.to_string\(\),\s*id,\s*result: Some\(json!\(\{\s*"content": \[\{"type": "text", "text": (.*?)\}\]\s*\}\)\),\s*error: None,\s*\}\)\s*\.await;' - - new_block = re.sub(pattern, r'send_text_result!(id.clone(), \1);', block) - - content = content[:tools_call_idx] + new_block - -with open('C:\\Users\\reazul.ashraf\\workspace\\rust\\mcp-memory\\nvim-core\\src\\lib.rs', 'w', encoding='utf-8') as f: - f.write(content) -print("Patched nvim macro") diff --git a/patch_stub.py b/patch_stub.py deleted file mode 100644 index 7b3de08..0000000 --- a/patch_stub.py +++ /dev/null @@ -1,15 +0,0 @@ -import re -import sys - -with open('C:\\Users\\reazul.ashraf\\workspace\\rust\\mcp-memory\\stub\\src\\main.rs', 'r', encoding='utf-8') as f: - content = f.read() - -start1 = r'let mut log_prefix = String::from\("Message"\);\n\s*if let Ok\(v\) = serde_json::from_str::\(&msg\) \{[\s\S]*?log_prefix = format!\("Response id=\{\}", res_id\);\n\s*\}\n\s*\}' -content = re.sub(start1, r'let log_prefix = logger::extract_log_prefix(&msg, false);', content) - -start2 = r'let mut log_prefix = String::from\("Message"\);\n\s*if let Ok\(v\) = serde_json::from_str::\(&text\) \{[\s\S]*?log_prefix = format!\("Response id=\{\} \[Error: \{\}\]", id, is_error\);\n\s*\}' -content = re.sub(start2, r'let log_prefix = logger::extract_log_prefix(&text, true);', content) - -with open('C:\\Users\\reazul.ashraf\\workspace\\rust\\mcp-memory\\stub\\src\\main.rs', 'w', encoding='utf-8') as f: - f.write(content) -print("Patched stub") diff --git a/patch_tests.py b/patch_tests.py deleted file mode 100644 index 72f921f..0000000 --- a/patch_tests.py +++ /dev/null @@ -1,12 +0,0 @@ -import re - -with open('C:\\Users\\reazul.ashraf\\workspace\\rust\\mcp-memory\\nvim-core\\src\\lib.rs', 'r', encoding='utf-8') as f: - content = f.read() - -content = content.replace('read_message(&mut reader)', 'mcp_stdio::read_mcp_message(&mut reader)') -content = content.replace('let req = mcp_stdio::read_mcp_message(&mut reader).await.unwrap();', 'let raw = mcp_stdio::read_mcp_message(&mut reader).await.unwrap();\n let req: JsonRpcRequest = serde_json::from_str(&raw).unwrap();') -content = content.replace('let req = mcp_stdio::read_mcp_message(&mut reader).await;', 'let req = mcp_stdio::read_mcp_message(&mut reader).await;') - -with open('C:\\Users\\reazul.ashraf\\workspace\\rust\\mcp-memory\\nvim-core\\src\\lib.rs', 'w', encoding='utf-8') as f: - f.write(content) -print("Patched tests") diff --git a/server/fix_descriptions.py b/server/fix_descriptions.py deleted file mode 100644 index 7d2e1a1..0000000 --- a/server/fix_descriptions.py +++ /dev/null @@ -1,24 +0,0 @@ -import re - -with open(r'C:\Users\reazul.ashraf\workspace\rust\mcp-memory\server\src\handlers.rs', 'r', encoding='utf-8') as f: - content = f.read() - -content = content.replace( - 'crate::mcp::tool_def::(\n "generate_standup_report",\n "",\n )', - 'crate::mcp::tool_def::(\n "generate_standup_report",\n "Generate a standup report summarizing recent work, blockers, and next steps.",\n )' -) - -content = content.replace( - 'crate::mcp::tool_def::(\n "get_environment_details",\n "",\n )', - 'crate::mcp::tool_def::(\n "get_environment_details",\n "Get detailed information about a specific deployment environment.",\n )' -) - -content = content.replace( - 'crate::mcp::tool_def::(\n "list_context_workspaces",\n "",\n )', - 'crate::mcp::tool_def::(\n "list_context_workspaces",\n "List all saved context workspaces.",\n )' -) - -with open(r'C:\Users\reazul.ashraf\workspace\rust\mcp-memory\server\src\handlers.rs', 'w', encoding='utf-8') as f: - f.write(content) - -print("Descriptions fixed.") diff --git a/server/src/bake_nvim_safeguards.py b/server/src/bake_nvim_safeguards.py deleted file mode 100644 index 79afbee..0000000 --- a/server/src/bake_nvim_safeguards.py +++ /dev/null @@ -1,62 +0,0 @@ -import os -import re - -def bake_nvim_safeguards(): - filepath = 'nvim-core/src/lib.rs' - with open(filepath, 'r', encoding='utf-8') as f: - content = f.read() - - # 1. We're going to inject an AST-level safeguard inside "nvim_execute_lua" - # Find the execute_lua block - target = """ "nvim_execute_lua" => { - if let Some(code) = args.get("code").and_then(|v| v.as_str()) { - match execute_nvim_lua(code).await {""" - - safeguarded = """ "nvim_execute_lua" => { - if let Some(code) = args.get("code").and_then(|v| v.as_str()) { - // BAKE IN: Block interactive prompts that cause server deadlocks - let lower_code = code.to_lowercase(); - if lower_code.contains("vim.fn.input") || lower_code.contains("vim.ui.select") || lower_code.contains("vim.fn.confirm") || lower_code.contains("vim.ui.input") { - send_error(id, -32600, "CRITICAL ERROR: Interactive Lua functions (input, select, confirm) are strictly forbidden via MCP as they will hang the headless server.").await; - return; - } - // Block the 'c' confirm flag in vim.cmd substitutions - if (code.contains("vim.cmd") || code.contains("vim.api.nvim_command")) && code.contains("%s") && code.contains("c") { - // A rough heuristic to block `%s/foo/bar/gc` - if regex::Regex::new(r"%s.*/.*c").unwrap().is_match(code) { - send_error(id, -32600, "CRITICAL ERROR: The 'c' (confirm) flag in Neovim substitutions is strictly forbidden via MCP as it triggers an interactive prompt that hangs the headless server. Use '/ge' instead.").await; - return; - } - } - - match execute_nvim_lua(code).await {""" - - if target in content: - # Also need to add regex as a dependency or just use basic string matching. - # Let's just use basic string matching for the %s block to avoid adding the regex crate to nvim-core if not present - - safeguarded_no_regex = """ "nvim_execute_lua" => { - if let Some(code) = args.get("code").and_then(|v| v.as_str()) { - // BAKE IN: Block interactive prompts that cause server deadlocks - let lower_code = code.to_lowercase(); - if lower_code.contains("vim.fn.input") || lower_code.contains("vim.ui.select") || lower_code.contains("vim.fn.confirm") || lower_code.contains("vim.ui.input") { - send_error(id, -32600, "CRITICAL ERROR: Interactive Lua functions (input, select, confirm) are strictly forbidden via MCP as they will hang the headless server.").await; - return; - } - // Block the 'c' confirm flag in vim.cmd substitutions - if (code.contains("vim.cmd") || code.contains("vim.api.nvim_command")) && code.contains("%s") && (code.contains("gc'") || code.contains('gc"') || code.contains("gc\\n") || code.contains("c'") || code.contains('c"')) { - send_error(id, -32600, "CRITICAL ERROR: The 'c' (confirm) flag in Neovim substitutions is strictly forbidden via MCP as it triggers an interactive prompt that hangs the headless server. Use '/g' or '/ge' instead.").await; - return; - } - - match execute_nvim_lua(code).await {""" - - content = content.replace(target, safeguarded_no_regex) - print("Baked safeguards into nvim_execute_lua") - - with open(filepath, 'w', encoding='utf-8') as f: - f.write(content) - else: - print("Could not find nvim_execute_lua block") - -bake_nvim_safeguards() diff --git a/server/src/bin_replace2.py b/server/src/bin_replace2.py deleted file mode 100644 index 020118a..0000000 --- a/server/src/bin_replace2.py +++ /dev/null @@ -1,150 +0,0 @@ -import os - -def rewrite_graph(): - with open('server/src/handlers_v2/graph.rs', 'r', encoding='utf-8') as f: - content = f.read() - - old_block = """ let mut included: HashSet<&str> = HashSet::new(); - let mut to_draw = Vec::new(); - - state.read_graph(|full| { - for (name, e) in &full.entities { - if let Some(ns) = &req.namespace - && e.namespace != *ns - { - continue; - } - if query.is_empty() - || contains_ignore_ascii_case(name, &query) - || contains_ignore_ascii_case(&e.entity_type, &query) - { - included.insert(name.as_str()); - } - } - - for r in &full.relations { - if let Some(ns) = &req.namespace - && r.namespace != *ns - { - continue; - } - if query.is_empty() || included.contains(r.from.as_str()) || included.contains(r.to.as_str()) { - included.insert(r.from.as_str()); - included.insert(r.to.as_str()); - to_draw.push(r.clone()); - } - } - }); - use std::fmt::Write; - let mut output = String::with_capacity(included.len() * 40 + to_draw.len() * 60); - output.push_str("graph TD;\\n"); - - let sanitize = |s: &str, id_mode: bool| -> String { - let mut out = String::with_capacity(s.len()); - for c in s.chars() { - if c != '"' && c != '(' && c != ')' { - if id_mode && (c == ' ' || c == '-' || c == '.') { - out.push('_'); - } else { - out.push(c); - } - } - } - out - }; - - for name in &included { - let _ = writeln!( - output, - " id_{}[\\"{}\\"];", - sanitize(name, true), - sanitize(name, false) - ); - } - for r in to_draw { - let _ = writeln!( - output, - " id_{}-->|\\"{}\\"|id_{};", - sanitize(&r.from, true), - r.relation_type.replace("\\"", ""), - sanitize(&r.to, true) - ); - }""" - - new_block = """ use std::fmt::Write; - let mut output = state.read_graph(|full| { - let mut included: HashSet<&str> = HashSet::new(); - let mut to_draw = Vec::new(); - - for (name, e) in &full.entities { - if let Some(ns) = &req.namespace - && e.namespace != *ns - { - continue; - } - if query.is_empty() - || contains_ignore_ascii_case(name, &query) - || contains_ignore_ascii_case(&e.entity_type, &query) - { - included.insert(name.as_str()); - } - } - - for r in &full.relations { - if let Some(ns) = &req.namespace - && r.namespace != *ns - { - continue; - } - if query.is_empty() || included.contains(r.from.as_str()) || included.contains(r.to.as_str()) { - included.insert(r.from.as_str()); - included.insert(r.to.as_str()); - to_draw.push(r.clone()); - } - } - - let mut out = String::with_capacity(included.len() * 40 + to_draw.len() * 60); - out.push_str("graph TD;\\n"); - - let sanitize = |s: &str, id_mode: bool| -> String { - let mut o = String::with_capacity(s.len()); - for c in s.chars() { - if c != '"' && c != '(' && c != ')' { - if id_mode && (c == ' ' || c == '-' || c == '.') { - o.push('_'); - } else { - o.push(c); - } - } - } - o - }; - - for name in &included { - let _ = writeln!( - out, - " id_{}[\\"{}\\"];", - sanitize(name, true), - sanitize(name, false) - ); - } - for r in to_draw { - let _ = writeln!( - out, - " id_{}-->|\\"{}\\"|id_{};", - sanitize(&r.from, true), - r.relation_type.replace("\\"", ""), - sanitize(&r.to, true) - ); - } - out - });""" - - if old_block in content: - with open('server/src/handlers_v2/graph.rs', 'w', encoding='utf-8') as f: - f.write(content.replace(old_block, new_block)) - print("Replaced visualize_graph") - else: - print("Could not find old block") - -rewrite_graph() diff --git a/server/src/bin_test.rs b/server/src/bin_test.rs deleted file mode 100644 index 8538587..0000000 --- a/server/src/bin_test.rs +++ /dev/null @@ -1,10 +0,0 @@ -use rmcp::model::{InitializeResult, ServerCapabilities}; - -fn main() { - let init = InitializeResult::new(ServerCapabilities::builder().enable_tools().build()) - .with_server_info(rmcp::model::Implementation::new( - "gemini-mcp-memory", - "3.0.0", - )); - println!("{}", serde_json::to_string_pretty(&init).unwrap()); -} diff --git a/server/src/fix_env_ws.py b/server/src/fix_env_ws.py deleted file mode 100644 index 2adb226..0000000 --- a/server/src/fix_env_ws.py +++ /dev/null @@ -1,61 +0,0 @@ -import os - -def fix_env_and_workspaces(): - filepath = 'server/src/handlers_v2/env.rs' - with open(filepath, 'r', encoding='utf-8') as f: - content = f.read() - - old_env = """ let fps = state.env_fingerprints.read(); - if let Some(fp) = fps.get(&req.namespace) {""" - - new_env = """ let data = state.env_fingerprints.read_with(|fps| { - fps.get(&req.namespace).cloned() - }); - if let Some(fp) = data {""" - - if old_env in content: - content = content.replace(old_env, new_env) - print('Replaced env read') - else: - print('Could not find old_env') - - with open(filepath, 'w', encoding='utf-8') as f: - f.write(content) - - filepath = 'server/src/handlers_v2/workspaces.rs' - with open(filepath, 'r', encoding='utf-8') as f: - content = f.read() - - old_ws = """ let query = req.query.to_lowercase(); - let snippets = state.snippets.read(); - let mut results = Vec::new(); - for s in snippets { - if contains_ignore_ascii_case(&s.name, &query) - || contains_ignore_ascii_case(&s.description, &query) - || contains_ignore_ascii_case(&s.language, &query) - { - results.push(s); - } - } - let data = serde_json::to_string(&results).unwrap_or_default();""" - - new_ws = """ let query = req.query.to_lowercase(); - let data = state.snippets.read_with(|snippets| { - let results: Vec<_> = snippets.iter().filter(|s| { - contains_ignore_ascii_case(&s.name, &query) - || contains_ignore_ascii_case(&s.description, &query) - || contains_ignore_ascii_case(&s.language, &query) - }).cloned().collect(); - serde_json::to_string(&results).unwrap_or_default() - });""" - - if old_ws in content: - content = content.replace(old_ws, new_ws) - print('Replaced workspaces read') - else: - print('Could not find old_ws') - - with open(filepath, 'w', encoding='utf-8') as f: - f.write(content) - -fix_env_and_workspaces() diff --git a/server/src/fix_main.py b/server/src/fix_main.py deleted file mode 100644 index bd9df6f..0000000 --- a/server/src/fix_main.py +++ /dev/null @@ -1,60 +0,0 @@ -import os - -def fix_main_stats(): - filepath = 'server/src/main.rs' - with open(filepath, 'r', encoding='utf-8') as f: - content = f.read() - - old_stats = """ let (entities, relations) = { - let graph = state_clone.get_full_graph(); - (graph.entities.len(), graph.relations.len()) - }; - let tasks = state_clone.tasks.read().len(); - let snippets = state_clone.snippets.read().len(); - let tech_debts = state_clone.tech_debts.read().len(); - let adrs = state_clone.adrs.read().len(); - - let ledger = state_clone.ledger.read().len(); - let sticky = state_clone.sticky.read().len(); - let error_fixes = state_clone.error_fixes.read().len(); - let pinned_files = state_clone.pinned_files.read().len(); - let session_summaries = state_clone.session_summaries.read().len(); - let handoff_memos = state_clone.handoff_memos.read().len(); - let env_fingerprints = state_clone.env_fingerprints.read().len(); - let env_requirements = state_clone.env_requirements.read().len(); - let milestones = state_clone.milestones.read().len(); - let environments = state_clone.environments.read().len(); - let pr_checklists = state_clone.pr_checklists.read().len(); - let gates = state_clone.gates.read().len(); - let context_workspaces = state_clone.context_workspaces.read().len();""" - - new_stats = """ let (entities, relations) = state_clone.read_graph(|g| (g.entities.len(), g.relations.len())); - let tasks = state_clone.tasks.read_with(|items| items.len()); - let snippets = state_clone.snippets.read_with(|items| items.len()); - let tech_debts = state_clone.tech_debts.read_with(|items| items.len()); - let adrs = state_clone.adrs.read_with(|items| items.len()); - - let ledger = state_clone.ledger.read_with(|items| items.len()); - let sticky = state_clone.sticky.read_with(|items| items.len()); - let error_fixes = state_clone.error_fixes.read_with(|items| items.len()); - let pinned_files = state_clone.pinned_files.read_with(|items| items.len()); - let session_summaries = state_clone.session_summaries.read_with(|items| items.len()); - let handoff_memos = state_clone.handoff_memos.read_with(|items| items.len()); - let env_fingerprints = state_clone.env_fingerprints.read_with(|items| items.len()); - let env_requirements = state_clone.env_requirements.read_with(|items| items.len()); - let milestones = state_clone.milestones.read_with(|items| items.len()); - let environments = state_clone.environments.read_with(|items| items.len()); - let pr_checklists = state_clone.pr_checklists.read_with(|items| items.len()); - let gates = state_clone.gates.read_with(|items| items.len()); - let context_workspaces = state_clone.context_workspaces.read_with(|items| items.len());""" - - if old_stats in content: - content = content.replace(old_stats, new_stats) - print('Replaced stats reads') - else: - print('Could not find old_stats') - - with open(filepath, 'w', encoding='utf-8') as f: - f.write(content) - -fix_main_stats() diff --git a/server/src/fix_meta.py b/server/src/fix_meta.py deleted file mode 100644 index 0c23291..0000000 --- a/server/src/fix_meta.py +++ /dev/null @@ -1,111 +0,0 @@ -import os - -def fix_meta(): - filepath = 'server/src/handlers_v2/meta.rs' - with open(filepath, 'r', encoding='utf-8') as f: - content = f.read() - - old_omni = """ let q = req.query.to_lowercase(); - let tech_debts: Vec<_> = state - .tech_debts - .read() - .into_iter() - .filter(|d| { - req.namespace.as_ref().is_none_or(|ns| d.namespace == *ns) - && (contains_ignore_ascii_case(&d.description, &q) - || contains_ignore_ascii_case(&d.ideal_solution, &q)) - }) - .collect(); - let memos: Vec<_> = state - .handoff_memos - .read() - .into_iter() - .filter(|m| { - req.namespace.as_ref().is_none_or(|ns| m.namespace == *ns) - && contains_ignore_ascii_case(&m.content, &q) - }) - .collect(); - let error_fixes: Vec<_> = state - .error_fixes - .read() - .into_iter() - .filter(|f| { - contains_ignore_ascii_case(&f.signature, &q) - || contains_ignore_ascii_case(&f.solution, &q) - }) - .collect();""" - - new_omni = """ let q = req.query.to_lowercase(); - let tech_debts = state.tech_debts.read_with(|debts| { - debts.iter().filter(|d| { - req.namespace.as_ref().is_none_or(|ns| d.namespace == *ns) - && (contains_ignore_ascii_case(&d.description, &q) - || contains_ignore_ascii_case(&d.ideal_solution, &q)) - }).cloned().collect::>() - }); - let memos = state.handoff_memos.read_with(|memos| { - memos.iter().filter(|m| { - req.namespace.as_ref().is_none_or(|ns| m.namespace == *ns) - && contains_ignore_ascii_case(&m.content, &q) - }).cloned().collect::>() - }); - let error_fixes = state.error_fixes.read_with(|fixes| { - fixes.iter().filter(|f| { - contains_ignore_ascii_case(&f.signature, &q) - || contains_ignore_ascii_case(&f.solution, &q) - }).cloned().collect::>() - });""" - - if old_omni in content: - content = content.replace(old_omni, new_omni) - print('Replaced omni_search vecs') - else: - print('Could not find old_omni') - - old_health = """ let active_tasks = state - .tasks - .read() - .into_iter() - .filter(|t| t.status != "done") - .count(); - let unresolved_debt = state - .tech_debts - .read() - .into_iter() - .filter(|d| d.namespace == req.namespace && !d.is_resolved) - .count(); - let unread_memos = state - .handoff_memos - .read() - .into_iter() - .filter(|m| m.namespace == req.namespace) - .count(); - let active_milestones = state - .milestones - .read() - .into_iter() - .filter(|m| m.namespace == req.namespace && m.status != "done") - .count(); - let remaining_checklists = state - .pr_checklists - .read() - .into_iter() - .filter(|c| c.namespace == req.namespace) - .count();""" - - new_health = """ let active_tasks = state.tasks.read_with(|tasks| tasks.iter().filter(|t| t.status != "done").count()); - let unresolved_debt = state.tech_debts.read_with(|debts| debts.iter().filter(|d| d.namespace == req.namespace && !d.is_resolved).count()); - let unread_memos = state.handoff_memos.read_with(|memos| memos.iter().filter(|m| m.namespace == req.namespace).count()); - let active_milestones = state.milestones.read_with(|milestones| milestones.iter().filter(|m| m.namespace == req.namespace && m.status != "done").count()); - let remaining_checklists = state.pr_checklists.read_with(|checklists| checklists.iter().filter(|c| c.namespace == req.namespace).count());""" - - if old_health in content: - content = content.replace(old_health, new_health) - print('Replaced health counters') - else: - print('Could not find old_health') - - with open(filepath, 'w', encoding='utf-8') as f: - f.write(content) - -fix_meta() diff --git a/server/src/fix_msgid.py b/server/src/fix_msgid.py deleted file mode 100644 index 92b0966..0000000 --- a/server/src/fix_msgid.py +++ /dev/null @@ -1,44 +0,0 @@ -import os -import re - -def fix_nvim_msgid(): - filepath = 'nvim-core/src/lib.rs' - with open(filepath, 'r', encoding='utf-8') as f: - content = f.read() - - # Add atomic import and static var if not exists - if 'static NEXT_MSGID' not in content: - atomic_def = "use std::sync::atomic::{AtomicU64, Ordering};\nstatic NEXT_MSGID: AtomicU64 = AtomicU64::new(1);\n" - # Find NVIM_CONN - conn_idx = content.find('static NVIM_CONN') - if conn_idx != -1: - content = content[:conn_idx] + atomic_def + content[conn_idx:] - - # Replace all hardcoded msgid - # e.g., RmpValue::Integer(1.into()), // msgid - # with: let msgid = NEXT_MSGID.fetch_add(1, Ordering::SeqCst); ... RmpValue::Integer(msgid.into()), - - # We need to insert `let msgid = NEXT_MSGID.fetch_add(1, Ordering::SeqCst);` before `let req = RmpValue::Array(vec![` - - # We will use regex to find the blocks - funcs = [ - ('send_nvim_command', '1'), - ('get_nvim_active_buffer', '2'), - ('get_nvim_cursor', '3'), - ('get_nvim_visual_selection', '4'), - ('set_nvim_diagnostics', '5'), - ('execute_nvim_lua', '6'), - ] - - for func, old_id in funcs: - pattern = rf"let req = RmpValue::Array\(vec!\[\s*RmpValue::Integer\(0\.into\(\)\),\s*RmpValue::Integer\({old_id}\.into\(\)\), // msgid" - replacement = f"let msgid = NEXT_MSGID.fetch_add(1, Ordering::SeqCst);\n let req = RmpValue::Array(vec![\n RmpValue::Integer(0.into()),\n RmpValue::Integer(msgid.into()), // msgid" - - content = re.sub(pattern, replacement, content) - - with open(filepath, 'w', encoding='utf-8') as f: - f.write(content) - - print('Fixed msgid allocations') - -fix_nvim_msgid() diff --git a/server/src/fix_notes.py b/server/src/fix_notes.py deleted file mode 100644 index d6439c8..0000000 --- a/server/src/fix_notes.py +++ /dev/null @@ -1,40 +0,0 @@ -import os - -def fix_notes(): - filepath = 'server/src/handlers_v2/notes.rs' - with open(filepath, 'r', encoding='utf-8') as f: - content = f.read() - - old_standup = """ let tasks = state - .tasks - .read() - .into_iter() - .filter(|t| t.updated_at >= cutoff) - .collect::>(); - let changes = state - .ledger - .read() - .into_iter() - .filter(|c| c.timestamp >= cutoff) - .collect::>(); - let summaries = state - .session_summaries - .read() - .into_iter() - .filter(|s| s.namespace == req.namespace && s.timestamp >= cutoff) - .collect::>();""" - - new_standup = """ let tasks = state.tasks.read_with(|items| items.iter().filter(|t| t.updated_at >= cutoff).cloned().collect::>()); - let changes = state.ledger.read_with(|items| items.iter().filter(|c| c.timestamp >= cutoff).cloned().collect::>()); - let summaries = state.session_summaries.read_with(|items| items.iter().filter(|s| s.namespace == req.namespace && s.timestamp >= cutoff).cloned().collect::>());""" - - if old_standup in content: - content = content.replace(old_standup, new_standup) - print('Replaced standup in notes.rs') - else: - print('Could not find old_standup in notes.rs') - - with open(filepath, 'w', encoding='utf-8') as f: - f.write(content) - -fix_notes() diff --git a/server/src/fix_stub.py b/server/src/fix_stub.py deleted file mode 100644 index 9a8bc8d..0000000 --- a/server/src/fix_stub.py +++ /dev/null @@ -1,66 +0,0 @@ -import os - -def fix_stub_leaks(): - filepath = 'stub/src/main.rs' - with open(filepath, 'r', encoding='utf-8') as f: - content = f.read() - - # 1. Fix connect_async to handle shutdown and timeout - old_connect = """ match tokio_tungstenite::connect_async(request).await {""" - new_connect = """ let connect_result = tokio::select! { - _ = shutdown_rx.recv() => { - tracing::info!("Shutdown received during connect"); - break; - } - res = tokio::time::timeout( - tokio::time::Duration::from_secs(5), - tokio_tungstenite::connect_async(request) - ) => res, - }; - - match connect_result { - Ok(Ok((ws_stream, _))) => {""" - - if old_connect in content: - content = content.replace(old_connect, new_connect) - print("Replaced connect_async") - - # Fix Err block to match the new match structure - old_err = """ Err(e) => { - tracing::error!("Failed to connect via WSS: {}", e); - tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; - }""" - new_err = """ Ok(Err(e)) => { - tracing::error!("Failed to connect via WSS: {}", e); - tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; - } - Err(_) => { - tracing::error!("Connection attempt timed out"); - tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; - }""" - - if old_err in content: - content = content.replace(old_err, new_err) - print("Replaced Err branch") - - # 2. Fix the break in send_task that exits the stub instead of reconnecting - old_select_send = """ _ = &mut send_task => { - tracing::error!("Send task exited"); - tokio::time::sleep(tokio::time::Duration::from_millis(50)).await; - recv_task.abort(); - break; - }""" - new_select_send = """ _ = &mut send_task => { - tracing::error!("Send task exited"); - tokio::time::sleep(tokio::time::Duration::from_millis(50)).await; - recv_task.abort(); - }""" - - if old_select_send in content: - content = content.replace(old_select_send, new_select_send) - print("Replaced select send_task") - - with open(filepath, 'w', encoding='utf-8') as f: - f.write(content) - -fix_stub_leaks() diff --git a/server/src/handlers.rs b/server/src/handlers.rs deleted file mode 100644 index 72b02be..0000000 --- a/server/src/handlers.rs +++ /dev/null @@ -1,197 +0,0 @@ -use crate::router::McpTool; -use crate::state::MemoryState; -use std::sync::Arc; - -pub struct MemoryHandler { - pub state: Arc, - pub tools: std::collections::HashMap>, -} - -impl MemoryHandler { - pub fn new(state: Arc) -> Self { - let mut tools: std::collections::HashMap> = - std::collections::HashMap::new(); - - macro_rules! register { - ($module:ident::$handler:ident) => { - let h = crate::handlers_v2::$module::$handler; - tools.insert(h.name().to_string(), Box::new(h)); - }; - } - - register!(graph::QueryGraphPathHandler); - register!(graph::CreateEntitiesHandler); - register!(graph::CreateRelationsHandler); - register!(graph::AddObservationsHandler); - register!(graph::DeleteEntitiesHandler); - register!(graph::DeleteObservationsHandler); - register!(graph::DeleteRelationsHandler); - register!(graph::ReadGraphHandler); - register!(graph::SearchNodesHandler); - register!(graph::OpenNodesHandler); - register!(graph::VisualizeGraphHandler); - register!(graph::CondenseEntityHandler); - register!(graph::MergeEntitiesHandler); - register!(graph::FindOrphansHandler); - - register!(tasks::AddTaskHandler); - register!(tasks::DeleteTaskHandler); - register!(tasks::UpdateTaskStatusHandler); - register!(tasks::ListActiveTasksHandler); - register!(tasks::SetAcceptanceCriteriaHandler); - register!(tasks::VerifyAcceptanceCriteriaHandler); - register!(tasks::AddMilestoneHandler); - register!(tasks::UpdateMilestoneHandler); - register!(tasks::ListMilestonesHandler); - - register!(notes::AddStickyNoteHandler); - register!(notes::ReadStickyNotesHandler); - register!(notes::DeleteStickyNoteHandler); - register!(notes::ClearStickyNotesHandler); - register!(notes::LeaveHandoffMemoHandler); - register!(notes::ReadHandoffMemosHandler); - register!(notes::ClearHandoffMemosHandler); - register!(notes::AddSessionSummaryHandler); - register!(notes::GenerateStandupReportHandler); - - register!(meta::LogDecisionHandler); - register!(meta::QueryDecisionsHandler); - register!(meta::LogErrorFixHandler); - register!(meta::SearchErrorFixesHandler); - register!(meta::LogCodeChangeHandler); - register!(meta::QueryRecentChangesHandler); - register!(meta::LearnPreferenceHandler); - register!(meta::ReadPreferencesHandler); - register!(meta::LogTechDebtHandler); - register!(meta::ResolveTechDebtHandler); - register!(meta::ListTechDebtHandler); - register!(meta::OmniSearchHandler); - register!(meta::GetProjectHealthHandler); - - register!(env::UpdateEnvFingerprintHandler); - register!(env::ReadEnvFingerprintHandler); - register!(env::LogEnvRequirementHandler); - register!(env::RegisterEnvironmentHandler); - register!(env::GetEnvironmentDetailsHandler); - - register!(workspaces::PinFileHandler); - register!(workspaces::UnpinFileHandler); - register!(workspaces::ListPinnedFilesHandler); - register!(workspaces::StoreSnippetHandler); - register!(workspaces::SearchSnippetsHandler); - register!(workspaces::DeleteSnippetHandler); - register!(workspaces::SaveContextWorkspaceHandler); - register!(workspaces::LoadContextWorkspaceHandler); - register!(workspaces::ListContextWorkspacesHandler); - register!(workspaces::AddPrChecklistItemHandler); - register!(workspaces::GetPrChecklistHandler); - register!(workspaces::ClearPrChecklistHandler); - - Self { state, tools } - } - - pub async fn handle_request(&self, req: serde_json::Value) -> Option { - let id = req.get("id").cloned().unwrap_or(serde_json::Value::Null); - let id_clone = id.clone(); - let method = req.get("method").and_then(|m| m.as_str()).unwrap_or(""); - - match method { - "server/discover" => { - let payload = serde_json::json!({ - "resultType": "complete", - "ttlMs": 0, - "cacheScope": "public", - "supportedVersions": ["2026-07-28", "2025-11-25", "2025-06-18", "2025-03-26", "2024-11-05"], - "capabilities": { - "tools": serde_json::json!({}) - }, - "_meta": { - "io.modelcontextprotocol/serverInfo": { - "name": "gemini-mcp-memory", - "version": "3.0.0" - } - } - }); - Some(crate::mcp::success(id, payload)) - } - "initialize" => { - let init = rmcp::model::InitializeResult::new( - rmcp::model::ServerCapabilities::builder() - .enable_tools() - .build(), - ) - .with_server_info(rmcp::model::Implementation::new( - "gemini-mcp-memory", - "3.0.0", - )); - Some(crate::mcp::success( - id, - serde_json::to_value(&init).unwrap_or_default(), - )) - } - "notifications/initialized" => None, - "tools/list" => { - let mut tools: Vec = - self.tools.values().map(|t| t.schema()).collect(); - tools.sort_by_key(|t| { - t.get("name") - .and_then(|n| n.as_str()) - .unwrap_or("") - .to_string() - }); - Some(crate::mcp::success( - id, - serde_json::json!({ "tools": tools }), - )) - } - "tools/call" => { - let params = req.get("params").unwrap_or(&serde_json::Value::Null); - let name = params.get("name").and_then(|n| n.as_str()).unwrap_or(""); - let args = params - .get("arguments") - .cloned() - .unwrap_or(serde_json::Value::Object(Default::default())); - - self.state - .broadcast_activity(&format!("Agent executed tool: {}", name)); - - let result: Result = if let Some(tool) = self.tools.get(name) { - tool.execute(args, self.state.clone()).await - } else { - Err(format!("Unknown tool: {}", name)) - }; - - match result { - Ok(text) => { - let payload = serde_json::json!({ - "content": [{"type": "text", "text": text}], - "isError": false - }); - Some(crate::mcp::success(id_clone, payload)) - } - Err(e) => { - tracing::error!("Tool {} failed: {}", name, e); - let payload = serde_json::json!({ - "content": [{"type": "text", "text": e}], - "isError": true - }); - Some(crate::mcp::success(id_clone, payload)) - } - } - } - m if m.starts_with("notifications/") => None, - "ping" => Some(crate::mcp::success(id, serde_json::json!({}))), - _ => { - if id.is_null() { - None - } else { - Some(crate::mcp::error( - id, - -32601, - &format!("Method {} not found", method), - )) - } - } - } - } -} diff --git a/server/src/refactor.py b/server/src/refactor.py deleted file mode 100644 index 03915c6..0000000 --- a/server/src/refactor.py +++ /dev/null @@ -1,173 +0,0 @@ -import os -import re - -GROUPS = { - "graph": [ - "query_graph_path", "create_entities", "create_relations", "add_observations", - "delete_entities", "delete_observations", "delete_relations", "read_graph", - "search_nodes", "open_nodes", "visualize_graph", "condense_entity", - "merge_entities", "find_orphans" - ], - "tasks": [ - "add_task", "delete_task", "update_task_status", "list_active_tasks", - "set_acceptance_criteria", "verify_acceptance_criteria", - "add_milestone", "update_milestone", "list_milestones" - ], - "notes": [ - "add_sticky_note", "read_sticky_notes", "delete_sticky_note", "clear_sticky_notes", - "leave_handoff_memo", "read_handoff_memos", "clear_handoff_memos", - "add_session_summary", "generate_standup_report" - ], - "meta": [ - "log_decision", "query_decisions", "log_error_fix", "search_error_fixes", - "log_code_change", "query_recent_changes", "learn_preference", "read_preferences", - "log_tech_debt", "resolve_tech_debt", "list_tech_debt", "omni_search", "get_project_health" - ], - "env": [ - "update_env_fingerprint", "read_env_fingerprint", "log_env_requirement", - "register_environment", "get_environment_details" - ], - "workspaces": [ - "pin_file", "unpin_file", "list_pinned_files", "store_snippet", "search_snippets", - "delete_snippet", "save_context_workspace", "load_context_workspace", - "list_context_workspaces", "add_pr_checklist_item", "get_pr_checklist", "clear_pr_checklist" - ] -} - -def to_camel_case(snake_str): - components = snake_str.split('_') - return "".join(x.title() for x in components) - -def parse_rust_match(file_path): - with open(file_path, "r", encoding="utf-8") as f: - lines = f.readlines() - - start_idx = -1 - for i, line in enumerate(lines): - if "let result: Result = match name {" in line: - start_idx = i - break - - if start_idx == -1: - return {} - - brace_depth = 1 - i = start_idx + 1 - - tools = {} - current_tool = None - current_body = [] - - while i < len(lines): - line = lines[i] - - if brace_depth == 1 and "=>" in line and '"' in line: - parts = line.strip().split('"') - if len(parts) >= 3: - tool_name = parts[1] - current_tool = tool_name - current_body = [] - # Don't add the "name" => { line - - if current_tool is not None and not (brace_depth == 1 and "=>" in line and '"' in line): - # check if this line closes the block - next_depth = brace_depth + line.count('{') - line.count('}') - if next_depth == 1 and current_tool is not None: - # This is the closing brace - tools[current_tool] = "".join(current_body) - current_tool = None - else: - current_body.append(line) - - brace_depth += line.count('{') - brace_depth -= line.count('}') - - if brace_depth == 0: - break - - i += 1 - - return tools - -def transform_body(body): - # Transform parse_tool! - body = re.sub( - r'let req = parse_tool!\(args, id, ([^)]+)\);', - r'let req: \1 = serde_json::from_value(args).map_err(|e| e.to_string())?;', - body - ) - # Transform handle_list_with_namespace! - def repl_handle_list(m): - store = m.group(1) - tool_type = m.group(2) - return f""" - let req: {tool_type} = serde_json::from_value(args).map_err(|e| e.to_string())?; - let mut items = state.{store}.read(); - if let Some(ns) = req.namespace {{ - items.retain(|i| i.namespace == ns); - }} - let data = serde_json::to_string(&items).unwrap_or_default(); - return Ok(data.to_string()); - """ - body = re.sub( - r'return handle_list_with_namespace!\(self, ([^,]+), ([^,]+), args, id\);', - repl_handle_list, - body - ) - - # Replace self.state with state - body = body.replace("self.state.", "state.") - - return body - - -tools = parse_rust_match("server/src/handlers.rs") - -for group, tool_names in GROUPS.items(): - file_path = f"server/src/handlers_v2/{group}.rs" - with open(file_path, "w", encoding="utf-8") as f: - f.write("use crate::router::McpTool;\n") - f.write("use crate::state::MemoryState;\n") - f.write("use crate::tools::*;\n") - f.write("use async_trait::async_trait;\n") - f.write("use serde_json::Value;\n") - f.write("use std::sync::Arc;\n") - f.write("use std::time::{SystemTime, UNIX_EPOCH};\n\n") - - for name in tool_names: - if name not in tools: - continue - - body = tools[name] - # special case for query_graph_path which we already wrote properly? - # actually we will just overwrite it with the transformed body - body = transform_body(body) - - struct_name = to_camel_case(name) + "Handler" - tool_type = to_camel_case(name) + "Tool" - - f.write(f"pub struct {struct_name};\n\n") - f.write(f"#[async_trait]\n") - f.write(f"impl McpTool for {struct_name} {{\n") - f.write(f" fn name(&self) -> &'static str {{\n") - f.write(f' "{name}"\n') - f.write(f" }}\n\n") - f.write(f" fn schema(&self) -> Value {{\n") - # For schema description we can just put a generic one or extract it. - # I will use a generic one for now, or you can extract it from tools/list. - f.write(f' crate::mcp::tool_def::<{tool_type}>(\n') - f.write(f' "{name}",\n') - f.write(f' "Execute {name}",\n') - f.write(f' )\n') - f.write(f" }}\n\n") - f.write(f" async fn execute(&self, args: Value, state: Arc) -> Result {{\n") - f.write(body) - f.write(f" }}\n") - f.write(f"}}\n\n") - -print("Generated handlers_v2 modules") - -# generate mod.rs -with open("server/src/handlers_v2/mod.rs", "w", encoding="utf-8") as f: - for group in GROUPS.keys(): - f.write(f"pub mod {group};\n") diff --git a/server/src/refactor.rs b/server/src/refactor.rs deleted file mode 100644 index 16f1b56..0000000 --- a/server/src/refactor.rs +++ /dev/null @@ -1,11 +0,0 @@ -use std::fs; -use std::io::Write; - -fn main() { - let content = fs::read_to_string("server/src/handlers.rs").unwrap(); - println!("Read {} bytes", content.len()); - // Find the match name { block - let match_start = content.find("match name {").unwrap(); - // naive extraction - println!("Found match block at {}", match_start); -} diff --git a/server/src/refactor_router.py b/server/src/refactor_router.py deleted file mode 100644 index c48ca5f..0000000 --- a/server/src/refactor_router.py +++ /dev/null @@ -1,82 +0,0 @@ -import re -import os - -with open("server/src/handlers.rs", "r", encoding="utf-8") as f: - lines = f.readlines() - -list_start = -1 -for i, line in enumerate(lines): - if '"tools/list" => {' in line: - list_start = i - break - -# Find end of tools/call -call_start = -1 -for i in range(list_start, len(lines)): - if '"tools/call" => {' in line: - call_start = i - break - -# Find end of tools/call -# Match brace depth from call_start -brace_depth = 1 -call_end = -1 -for i in range(call_start + 1, len(lines)): - brace_depth += lines[i].count('{') - brace_depth -= lines[i].count('}') - if brace_depth == 0: - call_end = i - break - -# replacement block -replacement = """ "tools/list" => { - let mut tools: Vec = self.tools.values().map(|t| t.schema()).collect(); - tools.sort_by_key(|t| t.get("name").and_then(|n| n.as_str()).unwrap_or("").to_string()); - Some(crate::mcp::success( - id, - serde_json::json!({ "tools": tools }), - )) - } - "tools/call" => { - let params = req.get("params").unwrap_or(&serde_json::Value::Null); - let name = params.get("name").and_then(|n| n.as_str()).unwrap_or(""); - let args = params - .get("arguments") - .cloned() - .unwrap_or(serde_json::Value::Object(Default::default())); - - self.state - .broadcast_activity(&format!("Agent executed tool: {}", name)); - - let result: Result = if let Some(tool) = self.tools.get(name) { - tool.execute(args, self.state.clone()).await - } else { - Err(format!("Unknown tool: {}", name)) - }; - - match result { - Ok(text) => { - let payload = serde_json::json!({ - "content": [{"type": "text", "text": text}], - "isError": false - }); - Some(crate::mcp::success(id_clone, payload)) - } - Err(e) => { - tracing::error!("Tool {} failed: {}", name, e); - let payload = serde_json::json!({ - "content": [{"type": "text", "text": e}], - "isError": true - }); - Some(crate::mcp::success(id_clone, payload)) - } - } - } -""" - -new_lines = lines[:list_start] + [replacement] + lines[call_end+1:] - -with open("server/src/handlers.rs", "w", encoding="utf-8") as f: - f.writelines(new_lines) - -print("tools/list and tools/call replaced.") diff --git a/server/src/refactor_wire.py b/server/src/refactor_wire.py deleted file mode 100644 index fc77d3e..0000000 --- a/server/src/refactor_wire.py +++ /dev/null @@ -1,106 +0,0 @@ -import re -import os - -with open("server/src/handlers.rs", "r", encoding="utf-8") as f: - content = f.read() - -# Replace MemoryHandler struct -struct_pattern = r'pub struct MemoryHandler \{\s*pub state: Arc,\s*\}' - -new_struct = """use crate::router::McpTool; - -pub struct MemoryHandler { - pub state: Arc, - pub tools: std::collections::HashMap>, -} - -impl MemoryHandler { - pub fn new(state: Arc) -> Self { - let mut tools: std::collections::HashMap> = std::collections::HashMap::new(); - - macro_rules! register { - ($module:ident::$handler:ident) => { - let h = crate::handlers_v2::$module::$handler; - tools.insert(h.name().to_string(), Box::new(h)); - }; - } - - register!(graph::QueryGraphPathHandler); - register!(graph::CreateEntitiesHandler); - register!(graph::CreateRelationsHandler); - register!(graph::AddObservationsHandler); - register!(graph::DeleteEntitiesHandler); - register!(graph::DeleteObservationsHandler); - register!(graph::DeleteRelationsHandler); - register!(graph::ReadGraphHandler); - register!(graph::SearchNodesHandler); - register!(graph::OpenNodesHandler); - register!(graph::VisualizeGraphHandler); - register!(graph::CondenseEntityHandler); - register!(graph::MergeEntitiesHandler); - register!(graph::FindOrphansHandler); - - register!(tasks::AddTaskHandler); - register!(tasks::DeleteTaskHandler); - register!(tasks::UpdateTaskStatusHandler); - register!(tasks::ListActiveTasksHandler); - register!(tasks::SetAcceptanceCriteriaHandler); - register!(tasks::VerifyAcceptanceCriteriaHandler); - register!(tasks::AddMilestoneHandler); - register!(tasks::UpdateMilestoneHandler); - register!(tasks::ListMilestonesHandler); - - register!(notes::AddStickyNoteHandler); - register!(notes::ReadStickyNotesHandler); - register!(notes::DeleteStickyNoteHandler); - register!(notes::ClearStickyNotesHandler); - register!(notes::LeaveHandoffMemoHandler); - register!(notes::ReadHandoffMemosHandler); - register!(notes::ClearHandoffMemosHandler); - register!(notes::AddSessionSummaryHandler); - register!(notes::GenerateStandupReportHandler); - - register!(meta::LogDecisionHandler); - register!(meta::QueryDecisionsHandler); - register!(meta::LogErrorFixHandler); - register!(meta::SearchErrorFixesHandler); - register!(meta::LogCodeChangeHandler); - register!(meta::QueryRecentChangesHandler); - register!(meta::LearnPreferenceHandler); - register!(meta::ReadPreferencesHandler); - register!(meta::LogTechDebtHandler); - register!(meta::ResolveTechDebtHandler); - register!(meta::ListTechDebtHandler); - register!(meta::OmniSearchHandler); - register!(meta::GetProjectHealthHandler); - - register!(env::UpdateEnvFingerprintHandler); - register!(env::ReadEnvFingerprintHandler); - register!(env::LogEnvRequirementHandler); - register!(env::RegisterEnvironmentHandler); - register!(env::GetEnvironmentDetailsHandler); - - register!(workspaces::PinFileHandler); - register!(workspaces::UnpinFileHandler); - register!(workspaces::ListPinnedFilesHandler); - register!(workspaces::StoreSnippetHandler); - register!(workspaces::SearchSnippetsHandler); - register!(workspaces::DeleteSnippetHandler); - register!(workspaces::SaveContextWorkspaceHandler); - register!(workspaces::LoadContextWorkspaceHandler); - register!(workspaces::ListContextWorkspacesHandler); - register!(workspaces::AddPrChecklistItemHandler); - register!(workspaces::GetPrChecklistHandler); - register!(workspaces::ClearPrChecklistHandler); - - Self { state, tools } - } -""" - -content = re.sub(struct_pattern, new_struct, content) -content = content.replace("impl MemoryHandler {\n pub async fn handle_request", " pub async fn handle_request") - -with open("server/src/handlers.rs", "w", encoding="utf-8") as f: - f.write(content) - -print("MemoryHandler struct updated.") diff --git a/server/src/tools_patch.rs b/server/src/tools_patch.rs deleted file mode 100644 index 3ff7bf1..0000000 --- a/server/src/tools_patch.rs +++ /dev/null @@ -1,45 +0,0 @@ -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; - -/// Create new entities in the knowledge graph. -#[derive(Debug, Deserialize, Serialize, JsonSchema)] -pub struct CreateEntitiesTool { - pub entities: Vec, -} - -/// Create new relations between entities in the knowledge graph. -#[derive(Debug, Deserialize, Serialize, JsonSchema)] -pub struct CreateRelationsTool { - pub relations: Vec, -} - -#[derive(Debug, Deserialize, Serialize, JsonSchema)] -pub struct ObservationInput { - #[serde(rename = "entityName")] - pub entity_name: String, - pub contents: Vec, -} - -/// Add new observations to existing entities in the knowledge graph. -#[derive(Debug, Deserialize, Serialize, JsonSchema)] -pub struct AddObservationsTool { - pub observations: Vec, -} - -/// Define a strict checklist of acceptance criteria for a given task or feature before starting work. -#[derive(Debug, Deserialize, Serialize, JsonSchema)] -pub struct SetAcceptanceCriteriaTool { - /// The name or title of the task/feature being worked on. - pub task_title: String, - /// An array of specific, undeniable conditions that must be proven before claiming success. - pub criteria: Vec, -} - -/// Mark a previously defined acceptance criteria as met by providing cryptographic-like proof (logs, output, diffs). -#[derive(Debug, Deserialize, Serialize, JsonSchema)] -pub struct VerifyAcceptanceCriteriaTool { - /// The exact text of the criteria being met. - pub criteria: String, - /// The undeniable proof (e.g., test logs, terminal output, git diff) that proves the criteria is met. - pub proof: String, -} diff --git a/server/update_win_config.py b/server/update_win_config.py deleted file mode 100644 index 09522fd..0000000 --- a/server/update_win_config.py +++ /dev/null @@ -1,37 +0,0 @@ -import json -import os - -eager_tools = [ - "log_code_change", - "log_error_fix", - "log_tech_debt", - "omni_search", - "create_entities", - "learn_preference", - "list_active_tasks", - "add_task", - "set_acceptance_criteria", - "verify_acceptance_criteria", - "update_task_status", - "list_pinned_files", - "pin_file", - "unpin_file", - "get_project_health", - "list_tech_debt", - "resolve_tech_debt" -] - -# Update Windows config -win_config_path = r'C:\Users\reazul.ashraf\.gemini\config\mcp_config.json' -with open(win_config_path, 'r', encoding='utf-8') as f: - win_data = json.load(f) - -win_data['mcpServers']['mcp-memory']['eagerTools'] = eager_tools -if 'args' in win_data['mcpServers']['mcp-memory']: - # Ensure args are empty as we removed --target earlier - win_data['mcpServers']['mcp-memory']['args'] = [] - -with open(win_config_path, 'w', encoding='utf-8') as f: - json.dump(win_data, f, indent=2) - -print("Updated Windows config") diff --git a/temp.lua b/temp.lua deleted file mode 100644 index 1c0cdb9..0000000 --- a/temp.lua +++ /dev/null @@ -1,27 +0,0 @@ -local buf = vim.fn.bufnr('server/src/search.rs') -if buf == -1 then - vim.cmd('e server/src/search.rs') - buf = vim.api.nvim_get_current_buf() -end - -vim.api.nvim_buf_set_lines(buf, 216, 222, false, { - ' &self,', - ' entities: &[Entity],', - ' tasks: &[Task],', - ' snippets: &[Snippet],', - ' adrs: &[Adr],' -}) - --- We need to change the loop variables inside the task from values to clones if they are passed as slices --- Actually we can just clone the slice data before moving it into spawn_blocking -vim.api.nvim_buf_set_lines(buf, 222, 223, false, { - ' ) -> tokio::task::JoinHandle> {', - ' let entities = entities.to_vec();', - ' let tasks = tasks.to_vec();', - ' let snippets = snippets.to_vec();', - ' let adrs = adrs.to_vec();' -}) - -vim.cmd('write') -require('notify')('Updated search index_batch signature', 'info', { title = 'Antigravity' }) -return 'ok' diff --git a/temp_execute.lua b/temp_execute.lua deleted file mode 100644 index d428b35..0000000 --- a/temp_execute.lua +++ /dev/null @@ -1,28 +0,0 @@ -local buf = vim.fn.bufnr('server/src/search.rs') -if buf == -1 then - vim.cmd('e server/src/search.rs') - buf = vim.api.nvim_get_current_buf() -end - -vim.api.nvim_buf_set_lines(buf, 216, 222, false, { - ' &self,', - ' entities: &[Entity],', - ' tasks: &[Task],', - ' snippets: &[Snippet],', - ' adrs: &[Adr],' -}) - --- We need to change the loop variables inside the task from values to clones if they are passed as slices --- Actually we can just clone the slice data before moving it into spawn_blocking -vim.api.nvim_buf_set_lines(buf, 222, 223, false, { - ' ) -> tokio::task::JoinHandle> {', - ' let entities = entities.to_vec();', - ' let tasks = tasks.to_vec();', - ' let snippets = snippets.to_vec();', - ' let adrs = adrs.to_vec();' -}) - -vim.cmd('write') -require('notify')('Updated search index_batch signature', 'info', { title = 'Antigravity' }) -return 'ok' - diff --git a/temp_read.lua b/temp_read.lua deleted file mode 100644 index d3f0030..0000000 --- a/temp_read.lua +++ /dev/null @@ -1,2 +0,0 @@ -local code = vim.fn.readfile('temp.lua') -return table.concat(code, '\n') diff --git a/temp_setup.lua b/temp_setup.lua deleted file mode 100644 index e671585..0000000 --- a/temp_setup.lua +++ /dev/null @@ -1,6 +0,0 @@ -local buf = vim.fn.bufnr('server/src/handlers_v2/graph.rs') -if buf == -1 then - vim.cmd('e server/src/handlers_v2/graph.rs') - buf = vim.api.nvim_get_current_buf() -end -return vim.api.nvim_buf_get_name(buf) diff --git a/update_main.patch b/update_main.patch deleted file mode 100644 index 93a0bef..0000000 --- a/update_main.patch +++ /dev/null @@ -1,25 +0,0 @@ ---- server/src/main.rs -+++ server/src/main.rs -@@ -225,6 +225,20 @@ - next_id: AtomicUsize::new(1), - }); - -+ let app_state_clone = Arc::clone(&app_state); -+ let mut rx = state.activity_tx.subscribe(); -+ tokio::spawn(async move { -+ while let Ok(msg) = rx.recv().await { -+ let senders: Vec<_> = app_state_clone -+ .clients -+ .read() -+ .unwrap_or_else(|e| e.into_inner()) -+ .values() -+ .cloned() -+ .collect(); -+ for client_tx in senders { -+ let _ = client_tx.try_send(msg.clone()); -+ } -+ } -+ }); -+ - let app = Router::new() - .route(