chore: fix formatting and clippy lints
This commit is contained in:
1 parent
8952bd5399
commit
9d9e959744
35 files changed
+1091
-582
No files matched your search
@@ -191,11 +191,10 @@ pub fn html_to_markdown(html: &str) -> String {
|
||||
out.push_str("* ");
|
||||
}
|
||||
}
|
||||
"/li" => {
|
||||
if !in_cell {
|
||||
"/li"
|
||||
if !in_cell => {
|
||||
out.push('\n');
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
} else if c == '&' {
|
||||
@@ -298,38 +297,46 @@ pub async fn ensure_ocr_engine() -> Option<&'static OcrEngine> {
|
||||
if let Some(engine) = OCR_ENGINE.get() {
|
||||
return Some(engine);
|
||||
}
|
||||
|
||||
|
||||
let cache_dir = dirs::home_dir()?.join(".gemini/mcp_memory/models");
|
||||
let _ = std::fs::create_dir_all(&cache_dir);
|
||||
|
||||
|
||||
let det_path = cache_dir.join("text-detection.rten");
|
||||
if !det_path.exists() || std::fs::metadata(&det_path).map(|m| m.len()).unwrap_or(0) < 100_000 {
|
||||
match reqwest::get("https://ocrs-models.s3-accelerate.amazonaws.com/text-detection.rten").await {
|
||||
match reqwest::get("https://ocrs-models.s3-accelerate.amazonaws.com/text-detection.rten")
|
||||
.await
|
||||
{
|
||||
Ok(resp) => {
|
||||
if let Ok(bytes) = resp.bytes().await {
|
||||
if let Err(e) = std::fs::write(&det_path, &bytes) {
|
||||
tracing::error!("Failed to write text-detection.rten to disk: {}", e);
|
||||
}
|
||||
} else {
|
||||
tracing::error!("Failed to read bytes from text-detection.rten download response");
|
||||
tracing::error!(
|
||||
"Failed to read bytes from text-detection.rten download response"
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
Err(e) => tracing::error!("Failed to download text-detection.rten: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let rec_path = cache_dir.join("text-recognition.rten");
|
||||
if !rec_path.exists() || std::fs::metadata(&rec_path).map(|m| m.len()).unwrap_or(0) < 100_000 {
|
||||
match reqwest::get("https://ocrs-models.s3-accelerate.amazonaws.com/text-recognition.rten").await {
|
||||
match reqwest::get("https://ocrs-models.s3-accelerate.amazonaws.com/text-recognition.rten")
|
||||
.await
|
||||
{
|
||||
Ok(resp) => {
|
||||
if let Ok(bytes) = resp.bytes().await {
|
||||
if let Err(e) = std::fs::write(&rec_path, &bytes) {
|
||||
tracing::error!("Failed to write text-recognition.rten to disk: {}", e);
|
||||
}
|
||||
} else {
|
||||
tracing::error!("Failed to read bytes from text-recognition.rten download response");
|
||||
tracing::error!(
|
||||
"Failed to read bytes from text-recognition.rten download response"
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
Err(e) => tracing::error!("Failed to download text-recognition.rten: {}", e),
|
||||
}
|
||||
}
|
||||
@@ -350,10 +357,7 @@ pub async fn ensure_ocr_engine() -> Option<&'static OcrEngine> {
|
||||
|
||||
pub fn perform_ocrs_ocr(engine: &OcrEngine, img: &image::DynamicImage) -> Option<String> {
|
||||
let rgb_img = img.to_rgb8();
|
||||
let img_source = ocrs::ImageSource::from_bytes(
|
||||
rgb_img.as_raw(),
|
||||
rgb_img.dimensions(),
|
||||
).ok()?;
|
||||
let img_source = ocrs::ImageSource::from_bytes(rgb_img.as_raw(), rgb_img.dimensions()).ok()?;
|
||||
|
||||
let ocr_input = engine.prepare_input(img_source).ok()?;
|
||||
let word_rects = engine.detect_words(&ocr_input).ok()?;
|
||||
@@ -365,7 +369,7 @@ pub fn perform_ocrs_ocr(engine: &OcrEngine, img: &image::DynamicImage) -> Option
|
||||
out.push_str(&text.to_string());
|
||||
out.push('\n');
|
||||
}
|
||||
|
||||
|
||||
let trimmed = out.trim();
|
||||
if trimmed.is_empty() {
|
||||
None
|
||||
@@ -482,23 +486,22 @@ pub async fn process_clipboard_snapshot(state: Arc<MemoryState>) {
|
||||
|
||||
if let Some(engine) = ensure_ocr_engine().await {
|
||||
let img_clone = img.clone();
|
||||
ocr_text_opt = tokio::task::spawn_blocking(move || {
|
||||
perform_ocrs_ocr(engine, &img_clone)
|
||||
})
|
||||
.await
|
||||
.ok()
|
||||
.flatten();
|
||||
ocr_text_opt =
|
||||
tokio::task::spawn_blocking(move || perform_ocrs_ocr(engine, &img_clone))
|
||||
.await
|
||||
.ok()
|
||||
.flatten();
|
||||
}
|
||||
|
||||
let mut cache = state.clipboard_cache.write().await;
|
||||
|
||||
|
||||
// Check if this is an identical image captured rapidly
|
||||
let is_duplicate = if let Some(ref prev) = cache.last_image {
|
||||
prev.width == w && prev.height == h && prev.size_bytes == size_bytes
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
|
||||
if !is_duplicate {
|
||||
// Index OCR text into Tantivy for omni_search
|
||||
if let Some(ref text) = ocr_text_opt {
|
||||
@@ -563,11 +566,10 @@ pub async fn process_clipboard_snapshot(state: Arc<MemoryState>) {
|
||||
};
|
||||
|
||||
let mut cache = state.clipboard_cache.write().await;
|
||||
if let Some(ref prev) = cache.last_text {
|
||||
if prev.text == cached.text {
|
||||
if let Some(ref prev) = cache.last_text
|
||||
&& prev.text == cached.text {
|
||||
return;
|
||||
}
|
||||
}
|
||||
cache.last_text = Some(cached.clone());
|
||||
cache
|
||||
.history
|
||||
@@ -669,7 +671,7 @@ pub fn spawn_clipboard_listener(state: Arc<MemoryState>) {
|
||||
tokio::spawn(async move {
|
||||
while let Some(()) = rx.recv().await {
|
||||
tokio::time::sleep(tokio::time::Duration::from_millis(150)).await;
|
||||
while let Ok(_) = rx.try_recv() {}
|
||||
while rx.try_recv().is_ok() {}
|
||||
|
||||
process_clipboard_snapshot(Arc::clone(&state)).await;
|
||||
}
|
||||
@@ -843,8 +845,8 @@ impl McpTool for ClipboardHandler {
|
||||
ClipboardAction::Read => {
|
||||
let engine = ensure_ocr_engine().await;
|
||||
|
||||
let out =
|
||||
tokio::task::spawn_blocking(move || -> crate::error::Result<serde_json::Map<String, Value>> {
|
||||
let out = tokio::task::spawn_blocking(
|
||||
move || -> crate::error::Result<serde_json::Map<String, Value>> {
|
||||
let mut out = serde_json::Map::new();
|
||||
|
||||
if let Some(text) = get_native_clipboard_text() {
|
||||
@@ -860,8 +862,19 @@ impl McpTool for ClipboardHandler {
|
||||
let rgb_img = img.into_rgb8();
|
||||
|
||||
let mut jpeg_bytes = std::io::Cursor::new(Vec::new());
|
||||
let mut encoder = image::codecs::jpeg::JpegEncoder::new_with_quality(&mut jpeg_bytes, 88);
|
||||
if encoder.encode(&rgb_img, rgb_img.width(), rgb_img.height(), image::ExtendedColorType::Rgb8).is_ok() {
|
||||
let mut encoder = image::codecs::jpeg::JpegEncoder::new_with_quality(
|
||||
&mut jpeg_bytes,
|
||||
88,
|
||||
);
|
||||
if encoder
|
||||
.encode(
|
||||
&rgb_img,
|
||||
rgb_img.width(),
|
||||
rgb_img.height(),
|
||||
image::ExtendedColorType::Rgb8,
|
||||
)
|
||||
.is_ok()
|
||||
{
|
||||
let bytes = jpeg_bytes.into_inner();
|
||||
|
||||
let cache_dir = dirs::home_dir()
|
||||
@@ -876,17 +889,20 @@ impl McpTool for ClipboardHandler {
|
||||
out.insert("image_path_wsl".into(), json!(wsl_path));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(eng) = engine {
|
||||
if let Some(ocr_text) = perform_ocrs_ocr(eng, &dynamic_img) {
|
||||
out.insert("image_analysis".to_string(), json!(ocr_text.trim()));
|
||||
|
||||
if let Some(eng) = engine
|
||||
&& let Some(ocr_text) = perform_ocrs_ocr(eng, &dynamic_img) {
|
||||
out.insert(
|
||||
"image_analysis".to_string(),
|
||||
json!(ocr_text.trim()),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(out)
|
||||
})
|
||||
.await
|
||||
.map_err(|e| crate::error::AppError::Internal(format!("Task panic: {}", e)))??;
|
||||
},
|
||||
)
|
||||
.await
|
||||
.map_err(|e| crate::error::AppError::Internal(format!("Task panic: {}", e)))??;
|
||||
|
||||
state.record_activity("clipboard", "Read contents from OS clipboard", None);
|
||||
Ok::<String, crate::error::AppError>(serde_json::to_string_pretty(&Value::Object(
|
||||
|
||||
Reference in new issue
Block a user