Refactor: Fix clippy warnings and introduce AppError

This commit is contained in:
Riz Ashraf committed 2026-09-30 20:43:28 +01:00
1 parent 3add6c3d31
commit 4e1a633dbd
13 files changed
+129 -103

No files matched your search

+3 -5
View File
@@ -19,9 +19,9 @@ pub fn spawn_watcher(state: Arc<MemoryState>) {
continue;
}
if let Ok(_clip) = tokio::task::spawn_blocking(|| Clipboard::new_attempts(3)).await.unwrap() {
if let Ok(text) = get_clipboard::<String, _>(formats::Unicode) {
if text != last_text && !text.trim().is_empty() {
if let Ok(_clip) = tokio::task::spawn_blocking(|| Clipboard::new_attempts(3)).await.unwrap()
&& let Ok(text) = get_clipboard::<String, _>(formats::Unicode)
&& text != last_text && !text.trim().is_empty() {
last_text = text.clone();
let note = StickyNote {
@@ -40,8 +40,6 @@ pub fn spawn_watcher(state: Arc<MemoryState>) {
// We use rebuild_index to index the new sticky note
state.rebuild_index().await;
}
}
}
}
});
}
+17 -1
View File
@@ -6,6 +6,8 @@ use axum::{
use serde_json::json;
use thiserror::Error;
pub type Result<T> = std::result::Result<T, AppError>;
#[derive(Error, Debug)]
pub enum AppError {
#[error("Not Found: {0}")]
@@ -19,6 +21,18 @@ pub enum AppError {
#[error("Bad Request: {0}")]
BadRequest(String),
#[error("Serialization Error: {0}")]
JsonError(#[from] serde_json::Error),
#[error("I/O Error: {0}")]
IoError(#[from] std::io::Error),
}
impl From<AppError> for String {
fn from(err: AppError) -> String {
err.to_string()
}
}
impl IntoResponse for AppError {
@@ -26,8 +40,10 @@ impl IntoResponse for AppError {
let (status, error_message) = match &self {
AppError::NotFound(msg) => (StatusCode::NOT_FOUND, msg.clone()),
AppError::Forbidden(msg) => (StatusCode::FORBIDDEN, msg.clone()),
AppError::Internal(msg) => (StatusCode::INTERNAL_SERVER_ERROR, msg.clone()),
AppError::BadRequest(msg) => (StatusCode::BAD_REQUEST, msg.clone()),
AppError::Internal(msg) => (StatusCode::INTERNAL_SERVER_ERROR, msg.clone()),
AppError::JsonError(e) => (StatusCode::INTERNAL_SERVER_ERROR, format!("JSON Error: {}", e)),
AppError::IoError(e) => (StatusCode::INTERNAL_SERVER_ERROR, format!("I/O Error: {}", e)),
};
let body = Json(json!({
+2 -8
View File
@@ -55,13 +55,7 @@ impl McpTool for ReadFileSkeletonHandler {
fn extract_skeleton(node: Node, code: &str, out: &mut String, depth: usize) {
let kind = node.kind();
let is_structural = match kind {
"use_declaration" | "import_statement" | "import_from_statement" => true,
"struct_item" | "enum_item" | "trait_item" | "impl_item" => true,
"function_item" | "function_declaration" | "function_definition" | "method_definition" => true,
"interface_declaration" | "type_alias_declaration" | "class_declaration" | "class_definition" => true,
_ => false,
};
let is_structural = matches!(kind, "use_declaration" | "import_statement" | "import_from_statement" | "struct_item" | "enum_item" | "trait_item" | "impl_item" | "function_item" | "function_declaration" | "function_definition" | "method_definition" | "interface_declaration" | "type_alias_declaration" | "class_declaration" | "class_definition");
if is_structural {
let indent = " ".repeat(depth);
@@ -84,7 +78,7 @@ impl McpTool for ReadFileSkeletonHandler {
}
out.push_str(&indent);
out.push_str(&signature.trim());
out.push_str(signature.trim());
out.push('\n');
} else if node.is_named() {
let mut cursor = node.walk();
+2 -3
View File
@@ -27,11 +27,10 @@ impl McpTool for GetActiveWorktreeContextHandler {
let repo = git2::Repository::discover(&cwd).map_err(|e| format!("Not in a git repository: {}", e))?;
let mut branch_name = String::new();
if let Ok(head) = repo.head() {
if let Some(name) = head.shorthand() {
if let Ok(head) = repo.head()
&& let Some(name) = head.shorthand() {
branch_name = name.to_string();
}
}
let mut opts = git2::DiffOptions::new();
let mut diff = None;
+2 -2
View File
@@ -409,7 +409,7 @@ impl McpTool for OmniSearchHandler {
));
}
};
println!("OMNI SEARCH MATCHES: {:?}", matches);
// tracing::info!("OMNI SEARCH MATCHES: {:?}", matches);
let q = req.query.clone();
let query_emb = crate::embedding::generate_embedding_async(q.clone()).await.unwrap_or_default();
@@ -846,7 +846,7 @@ mod tests {
.execute(json!({"query": "Omni"}), state.clone())
.await
.unwrap();
println!("OMNI RES: {}", omni_res);
// tracing::info!("OMNI RES: {}", omni_res);
assert!(
omni_res.contains("omni-1"),
"omni search should return results containing the task id"
+17 -26
View File
@@ -32,25 +32,21 @@ impl McpTool for WriteClipboardHandler {
let mut msgs = Vec::new();
// Handle clipboard_win formats (text, html, files)
if tool_args.text.is_some() || tool_args.html.is_some() || tool_args.files.is_some() {
if let Ok(_clip) = Clipboard::new_attempts(3) {
if let Some(text) = &tool_args.text {
if clipboard_win::set_clipboard_string(text).is_ok() {
if (tool_args.text.is_some() || tool_args.html.is_some() || tool_args.files.is_some())
&& let Ok(_clip) = Clipboard::new_attempts(3) {
if let Some(text) = &tool_args.text
&& clipboard_win::set_clipboard_string(text).is_ok() {
msgs.push("Wrote text");
}
}
if let Some(html) = &tool_args.html {
if formats::Html::new().unwrap().write_clipboard(html).is_ok() {
if let Some(html) = &tool_args.html
&& formats::Html::new().unwrap().write_clipboard(html).is_ok() {
msgs.push("Wrote HTML");
}
}
if let Some(files) = &tool_args.files {
if raw::set_file_list(files).is_ok() {
if let Some(files) = &tool_args.files
&& raw::set_file_list(files).is_ok() {
msgs.push("Wrote FileList");
}
}
}
}
// Handle arboard for image
if let Some(image_path) = &tool_args.image_path {
@@ -106,26 +102,23 @@ impl McpTool for ReadClipboardHandler {
let mut out = serde_json::Map::new();
if let Ok(_clip) = Clipboard::new_attempts(3) {
if let Ok(text) = get_clipboard::<String, _>(formats::Unicode) {
if !text.trim().is_empty() {
if let Ok(text) = get_clipboard::<String, _>(formats::Unicode)
&& !text.trim().is_empty() {
out.insert("text".into(), json!(text));
}
}
if let Ok(html) = get_clipboard::<String, _>(formats::Html::new().unwrap()) {
if !html.trim().is_empty() {
if let Ok(html) = get_clipboard::<String, _>(formats::Html::new().unwrap())
&& !html.trim().is_empty() {
out.insert("html".into(), json!(html));
}
}
if let Ok(files) = get_clipboard::<Vec<String>, _>(formats::FileList) {
if !files.is_empty() {
if let Ok(files) = get_clipboard::<Vec<String>, _>(formats::FileList)
&& !files.is_empty() {
out.insert("files".into(), json!(files));
}
}
}
if let Ok(mut clipboard) = arboard::Clipboard::new() {
if let Ok(image_data) = clipboard.get_image() {
if let Some(img) = ImageBuffer::<image::Rgba<u8>, _>::from_raw(
if let Ok(mut clipboard) = arboard::Clipboard::new()
&& let Ok(image_data) = clipboard.get_image()
&& let Some(img) = ImageBuffer::<image::Rgba<u8>, _>::from_raw(
image_data.width as u32,
image_data.height as u32,
image_data.bytes.into_owned(),
@@ -152,8 +145,6 @@ impl McpTool for ReadClipboardHandler {
out.insert("image_path".into(), json!(file_path.to_string_lossy().to_string()));
}
}
}
}
Ok(Value::Object(out))
})
+3 -3
View File
@@ -22,7 +22,7 @@ pub async fn start_background_indexer(state: Arc<MemoryState>) {
for result in walker {
match result {
Ok(entry) => {
if entry.file_type().map_or(false, |ft| ft.is_file()) {
if entry.file_type().is_some_and(|ft| ft.is_file()) {
let path = entry.path().to_path_buf();
let ext = path.extension().and_then(|e| e.to_str()).unwrap_or("");
if ["rs", "ts", "js", "jsx", "tsx", "py", "java", "c", "cpp", "go"].contains(&ext) {
@@ -98,7 +98,7 @@ pub async fn start_background_indexer(state: Arc<MemoryState>) {
});
}
fn extract_chunks(node: Node, code: &str, chunks: &mut Vec<(String, String, String)>, ext: &str) {
fn extract_chunks(node: Node, code: &str, chunks: &mut Vec<(String, String, String)>, _ext: &str) {
let kind = node.kind();
let is_structural = matches!(
kind,
@@ -128,7 +128,7 @@ fn extract_chunks(node: Node, code: &str, chunks: &mut Vec<(String, String, Stri
} else {
let mut cursor = node.walk();
for child in node.named_children(&mut cursor) {
extract_chunks(child, code, chunks, ext);
extract_chunks(child, code, chunks, _ext);
}
}
}
+4 -4
View File
@@ -258,7 +258,7 @@ impl MemoryIndex {
}
pub fn add_task_sync(&self, t: &Task) {
println!("add_task_sync called for task: {}", t.id);
// println!("add_task_sync called for task: {}", t.id);
if let Ok(writer) = self.writer.lock() {
let _res = writer.add_document(doc!(
self.id_field => t.id.as_str(),
@@ -267,12 +267,12 @@ impl MemoryIndex {
self.type_field => "task",
self.namespace_field => "global"
));
println!("Writer add_document returned id/result");
// println!("Writer add_document returned id/result");
self.needs_commit
.store(true, std::sync::atomic::Ordering::SeqCst);
println!("Needs_commit set to true in add_task_sync");
// println!("Needs_commit set to true in add_task_sync");
} else {
println!("Failed to acquire writer lock in add_task_sync");
// println!("Failed to acquire writer lock in add_task_sync");
}
}
+10 -7
View File
@@ -1,6 +1,7 @@
use crate::models::*;
use crate::search::MemoryIndex;
use crate::store::Store;
use crate::vector_db::VectorDB;
use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::{Arc, RwLock};
@@ -17,6 +18,7 @@ pub struct MemoryState {
pub clipboard_watch_mode: tokio::sync::RwLock<bool>,
pub graph: Store<KnowledgeGraph>,
pub search_index: RwLock<MemoryIndex>,
pub vector_db: tokio::sync::RwLock<Option<VectorDB>>,
pub ledger: Store<Vec<CodeChange>>,
pub sticky: Store<Vec<StickyNote>>,
pub tasks: Store<Vec<Task>>,
@@ -63,6 +65,7 @@ impl MemoryState {
std::process::exit(1);
}
}),
vector_db: tokio::sync::RwLock::new(None),
ledger: Store::new("audit_ledger", db.clone()),
sticky: Store::new("sticky_notes", db.clone()),
tasks: Store::new("tasks", db.clone()),
@@ -144,7 +147,7 @@ impl MemoryState {
let snippets = self.snippets.read_with(|s| s.clone());
let adrs = self.adrs.read_with(|a| a.clone());
println!(
tracing::info!(
"rebuild_index: found {} entities, {} tasks",
entities.len(),
tasks.len()
@@ -152,7 +155,7 @@ impl MemoryState {
let idx_clone = idx.clone();
tokio::task::spawn_blocking(move || {
println!("spawn_blocking started in rebuild_index");
// tracing::info!("spawn_blocking started in rebuild_index");
for e in entities {
idx_clone.add_entity_sync(&e);
}
@@ -222,13 +225,13 @@ mod tests {
let idx = arc_state.search_index.read().unwrap();
// Force reload reader to ensure it sees the commit made by rebuild_index
idx.reader.reload().unwrap();
println!(
"Index reader doc count: {}",
idx.reader.searcher().num_docs()
);
// tracing::info!(
// "Index reader doc count: {}",
// idx.reader.searcher().num_docs()
// );
let all_docs = idx.search("Test", None).expect("Search failed");
println!("All docs for 'Test': {:?}", all_docs);
// tracing::info!("All docs for 'Test': {:?}", all_docs);
// Verify the task added synchronously is actually searchable
let results = idx.search("Test", None).expect("Search failed");
+1 -1
View File
@@ -3,7 +3,7 @@ use qdrant_client::Qdrant;
use std::sync::Arc;
use std::error::Error;
use uuid::Uuid;
use tracing::{info, error};
use tracing::info;
use serde::{Deserialize, Serialize};
#[derive(Clone)]