feat(milestones): add POST /api/milestones endpoint and resolve collapsible_if warnings (TD-fc685b13-d9c2-4a57-ac4d-5228a71a2ec0)

This commit is contained in:
Riz Ashraf committed 2026-10-07 19:32:11 +01:00
1 parent 8f924b793a
commit d792b50343
6 files changed
+41 -25

No files matched your search

+1 -1
View File
@@ -102,7 +102,7 @@ build-nvim:
# Stage updated server binary, perform graceful shutdown, and auto-restart (skips if binary is unchanged)
deploy-server:
@Write-Host "Deploying Windows Server (Staged Hot-Swap)..." -ForegroundColor Cyan
-& { $src = "target\release\mcp-memory-server.exe"; $targets = @("$env:USERPROFILE\.local\bin\mcp-memory-server.exe", "$env:USERPROFILE\.cargo\bin\mcp-memory-server.exe"); $srcHash = if (Test-Path $src) { (Get-FileHash $src -Algorithm SHA256).Hash } else { $null }; $updated = $false; foreach ($target in $targets) { $parent = Split-Path $target; if (Test-Path $parent) { if ((Test-Path $target) -and $srcHash -and ((Get-FileHash $target -Algorithm SHA256).Hash -eq $srcHash)) { Write-Host "Skipping copy to $target (identical checksum)." -ForegroundColor Yellow } else { if (Test-Path $target) { $bak = "$target.old.$([guid]::NewGuid().ToString().Substring(0,8))"; Move-Item -Force $target $bak -ErrorAction SilentlyContinue }; Copy-Item -Force $src $target; Get-ChildItem "$parent\mcp-memory-server.exe.old.*" -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue; Write-Host "Copied updated binary to $target" -ForegroundColor Green; $updated = $true } } }; if ($updated -or -not (Get-NetTCPConnection -LocalPort 3000 -State Listen -ErrorAction SilentlyContinue)) { just stop; just start } else { Write-Host "Server binary unchanged and server is running. Skipping restart." -ForegroundColor Green } }
-& { $src = "target\release\mcp-memory-server.exe"; $targets = @("$env:USERPROFILE\.local\bin\mcp-memory-server.exe", "$env:USERPROFILE\.cargo\bin\mcp-memory-server.exe", "$env:USERPROFILE\.gemini\antigravity-cli\mcp\mcp-memory\mcp-memory.exe"); $srcHash = if (Test-Path $src) { (Get-FileHash $src -Algorithm SHA256).Hash } else { $null }; $updated = $false; foreach ($target in $targets) { $parent = Split-Path $target; if (Test-Path $parent) { if ((Test-Path $target) -and $srcHash -and ((Get-FileHash $target -Algorithm SHA256).Hash -eq $srcHash)) { Write-Host "Skipping copy to $target (identical checksum)." -ForegroundColor Yellow } else { if (Test-Path $target) { $bak = "$target.old.$([guid]::NewGuid().ToString().Substring(0,8))"; Move-Item -Force $target $bak -ErrorAction SilentlyContinue }; Copy-Item -Force $src $target; Get-ChildItem "$parent\mcp-memory-server.exe.old.*" -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue; Write-Host "Copied updated binary to $target" -ForegroundColor Green; $updated = $true } } }; if ($updated -or -not (Get-NetTCPConnection -LocalPort 3000 -State Listen -ErrorAction SilentlyContinue)) { just stop; just start } else { Write-Host "Server binary unchanged and server is running. Skipping restart." -ForegroundColor Green } }
# Deploy Windows-native stub binary (skips if identical checksum)
deploy-stub-win:
+19
View File
@@ -355,6 +355,25 @@ pub fn create_router(app_state: Arc<AppState>) -> Router {
let json = state_clone.project.milestones.read_with(|items| serde_json::to_string(items).unwrap_or_else(|_| "[]".to_string()));
([(axum::http::header::CONTENT_TYPE, "application/json")], json)
}
})
.post({
let state_clone = app_state.handler.state.clone();
move |axum::Json(payload): axum::Json<serde_json::Value>| async move {
use crate::router::McpTool;
let handler = crate::handlers::tasks::MilestonesHandler;
match handler.execute(payload, state_clone).await {
Ok(msg) => (
axum::http::StatusCode::OK,
axum::Json(serde_json::json!({ "status": "success", "message": msg })),
)
.into_response(),
Err(e) => (
axum::http::StatusCode::BAD_REQUEST,
axum::Json(serde_json::json!({ "status": "error", "message": e.to_string() })),
)
.into_response(),
}
}
}),
)
.route(
+3
View File
@@ -484,6 +484,9 @@ impl McpTool for MilestonesHandler {
}
if let Some(task_ids) = &req.task_ids {
m.task_ids = task_ids.clone();
if let Some(deliverables) = &req.deliverables {
m.deliverables = deliverables.clone();
}
}
found = true;
break;
+9 -11
View File
@@ -11,13 +11,12 @@ use std::sync::Arc;
pub fn get_native_clipboard_text() -> Option<String> {
for _ in 0..3 {
if let Ok(mut clipboard) = arboard::Clipboard::new() {
if let Ok(text) = clipboard.get_text() {
if !text.trim().is_empty() {
if let Ok(mut clipboard) = arboard::Clipboard::new()
&& let Ok(text) = clipboard.get_text()
&& !text.trim().is_empty()
{
return Some(text);
}
}
}
std::thread::sleep(std::time::Duration::from_millis(20));
}
None
@@ -71,17 +70,16 @@ pub fn get_native_clipboard_image() -> Option<image::DynamicImage> {
return Some(img);
}
for _ in 0..3 {
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(),
) {
)
{
return Some(image::DynamicImage::ImageRgba8(img));
}
}
}
std::thread::sleep(std::time::Duration::from_millis(20));
}
None
+6 -10
View File
@@ -56,11 +56,11 @@ pub fn spawn_watcher(state: Arc<MemoryState>) {
for path in event.paths {
if should_review(&path) {
// 250ms debouncing window per file path
if let Some(last) = last_processed.get(&path) {
if now.duration_since(*last) < std::time::Duration::from_millis(250) {
if let Some(last) = last_processed.get(&path)
&& now.duration_since(*last) < std::time::Duration::from_millis(250)
{
continue;
}
}
last_processed.insert(path.clone(), now);
info!("Proactive Daemon Hooks: File modified: {:?}", path);
@@ -83,13 +83,9 @@ fn should_review(path: &Path) -> bool {
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
path.extension()
.and_then(|ext| ext.to_str())
.is_some_and(|ext| matches!(ext, "rs" | "md" | "toml" | "lua"))
}
async fn trigger_autonomous_review(path: &Path, state: Arc<MemoryState>) {
+3 -3
View File
@@ -40,7 +40,7 @@ async fn test_stub_connection_refused() {
.spawn()
.expect("Failed to execute stub");
let res = tokio::time::timeout(Duration::from_secs(5), child.wait()).await;
let res = tokio::time::timeout(Duration::from_secs(15), child.wait()).await;
let elapsed = start.elapsed();
assert!(
@@ -71,7 +71,7 @@ async fn test_stub_handles_eof_cleanly() {
} // stdin dropped here
let start = Instant::now();
let res = tokio::time::timeout(Duration::from_secs(5), child.wait()).await;
let res = tokio::time::timeout(Duration::from_secs(15), child.wait()).await;
let elapsed = start.elapsed();
assert!(res.is_ok(), "Stub hung after EOF! Took {elapsed:?}");
@@ -102,7 +102,7 @@ async fn test_stub_sse_fallback_failure() {
.spawn()
.expect("Failed to execute stub");
let res = tokio::time::timeout(Duration::from_secs(5), child.wait()).await;
let res = tokio::time::timeout(Duration::from_secs(15), child.wait()).await;
let elapsed = start.elapsed();
assert!(