refactor: consolidate nvim crates, extract server library, and update workspace dependencies

This commit is contained in:
Riz Ashraf committed 2026-10-04 01:42:59 +01:00
1 parent a083719cf1
commit 533adfd41b
53 files changed
+5967 -1230

No files matched your search

+252 -8
View File
@@ -120,8 +120,20 @@ pub fn create_router(app_state: Arc<AppState>) -> Router {
}
tracing::info!(
"Received shutdown request via /shutdown endpoint. Initiating graceful shutdown."
"Received shutdown request via /shutdown endpoint. Creating session checkpoint and initiating graceful shutdown."
);
let mem_state = state.handler.state.clone();
let now = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap_or_default().as_secs();
let memo = crate::models::HandoffMemo {
id: format!("chk_shutdown_{}", now),
author: "ShutdownHook".to_string(),
content: format!("Automatic session checkpoint triggered on graceful server shutdown at epoch {}", now),
expires_at: None,
namespace: "global".to_string(),
timestamp: now,
};
mem_state.telemetry.handoff_memos.modify(|m| m.push(memo));
if let Some(tx) = state.shutdown_tx.lock().unwrap().take() {
let _ = tx.send(());
}
@@ -389,15 +401,14 @@ mod tests {
use crate::router::MemoryHandler;
use crate::state::MemoryState;
use axum::body::Body;
use axum::http::Request;
use axum::http::{Request, StatusCode};
use std::collections::HashMap;
use std::sync::RwLock;
use std::sync::atomic::AtomicUsize;
use tempfile::tempdir;
use tower::ServiceExt;
#[tokio::test]
async fn test_create_router_health() {
async fn setup_app() -> (axum::Router, Arc<AppState>, tempfile::TempDir) {
let dir = tempdir().unwrap();
let state = Arc::new(MemoryState::new(dir.path().to_str().unwrap()));
let (shutdown_tx, _) = tokio::sync::oneshot::channel();
@@ -408,16 +419,249 @@ mod tests {
shutdown_tx: std::sync::Mutex::new(Some(shutdown_tx)),
});
let app = create_router(app_state);
let app = create_router(app_state.clone());
(app, app_state, dir)
}
#[tokio::test]
async fn test_create_router_health() {
let (app, _, _dir) = setup_app().await;
// Test health endpoint
let request = Request::builder()
.uri("/health")
.body(Body::empty())
.unwrap();
let response = app.oneshot(request).await.unwrap();
assert_eq!(response.status(), 200);
assert_eq!(response.status(), StatusCode::OK);
}
#[tokio::test]
async fn test_ping_endpoint() {
let (app, _, _dir) = setup_app().await;
let request = Request::builder()
.uri("/ping")
.body(Body::empty())
.unwrap();
let response = app.oneshot(request).await.unwrap();
assert_eq!(response.status(), StatusCode::OK);
}
#[tokio::test]
async fn test_version_endpoint() {
let (app, _, _dir) = setup_app().await;
let request = Request::builder()
.uri("/api/version")
.body(Body::empty())
.unwrap();
let response = app.oneshot(request).await.unwrap();
assert_eq!(response.status(), StatusCode::OK);
}
#[tokio::test]
async fn test_metrics_endpoint() {
let (app, _, _dir) = setup_app().await;
let request = Request::builder()
.uri("/metrics")
.body(Body::empty())
.unwrap();
let response = app.oneshot(request).await.unwrap();
assert_eq!(response.status(), StatusCode::OK);
}
#[tokio::test]
async fn test_activity_endpoint() {
let (app, _, _dir) = setup_app().await;
let request = Request::builder()
.uri("/api/activity")
.body(Body::empty())
.unwrap();
let response = app.oneshot(request).await.unwrap();
assert_eq!(response.status(), StatusCode::OK);
}
#[tokio::test]
async fn test_nvim_telemetry_endpoint() {
let (app, _, _dir) = setup_app().await;
let body_json = serde_json::json!({
"session_id": "test_session",
"event": "BufEnter",
"file": "test.rs"
});
let request = Request::builder()
.method("POST")
.uri("/nvim/telemetry")
.header("content-type", "application/json")
.body(Body::from(body_json.to_string()))
.unwrap();
let response = app.oneshot(request).await.unwrap();
assert_eq!(response.status(), StatusCode::OK);
}
#[tokio::test]
async fn test_terminal_history_endpoint() {
let (app, _, _dir) = setup_app().await;
let request = Request::builder()
.uri("/api/terminal/history")
.body(Body::empty())
.unwrap();
let response = app.oneshot(request).await.unwrap();
assert_eq!(response.status(), StatusCode::OK);
}
#[tokio::test]
async fn test_terminal_telemetry_endpoint() {
let (app, _, _dir) = setup_app().await;
let body_json = serde_json::json!({
"command": "cargo build",
"exit_code": 0,
"cwd": "/tmp",
"os": "windows",
"timestamp": 1234567890
});
let request = Request::builder()
.method("POST")
.uri("/terminal/telemetry")
.header("content-type", "application/json")
.body(Body::from(body_json.to_string()))
.unwrap();
let response = app.oneshot(request).await.unwrap();
assert_eq!(response.status(), StatusCode::OK);
}
#[tokio::test]
async fn test_post_event_endpoint() {
let (app, _, _dir) = setup_app().await;
let body_json = serde_json::json!({
"topic": "test_topic",
"session_id": "s123",
"payload": { "key": "value" }
});
let request = Request::builder()
.method("POST")
.uri("/events")
.header("content-type", "application/json")
.body(Body::from(body_json.to_string()))
.unwrap();
let response = app.oneshot(request).await.unwrap();
assert_eq!(response.status(), StatusCode::OK);
}
#[tokio::test]
async fn test_gate_verify_endpoint() {
let (app, _, _dir) = setup_app().await;
let request = Request::builder()
.uri("/gate/verify?action=deploy&target=prod")
.body(Body::empty())
.unwrap();
let response = app.oneshot(request).await.unwrap();
assert_eq!(response.status(), StatusCode::NOT_FOUND);
}
#[tokio::test]
async fn test_gate_set_and_verify_success() {
let (app, app_state, _dir) = setup_app().await;
let set_req = Request::builder()
.method("POST")
.uri("/gate/set")
.header("content-type", "application/json")
.body(Body::from(serde_json::json!({
"action": "deploy",
"target": "prod",
"authorize": true,
"reason": "Tests passed"
}).to_string()))
.unwrap();
let response = app.oneshot(set_req).await.unwrap();
assert_eq!(response.status(), StatusCode::OK);
let app2 = create_router(app_state);
let verify_req = Request::builder()
.uri("/gate/verify?action=deploy&target=prod")
.body(Body::empty())
.unwrap();
let verify_resp = app2.oneshot(verify_req).await.unwrap();
assert_eq!(verify_resp.status(), StatusCode::OK);
}
#[tokio::test]
async fn test_all_rest_endpoints_comprehensive() {
let (_app, app_state, _dir) = setup_app().await;
let endpoints = vec![
"/",
"/api/graph",
"/api/tasks",
"/api/sticky",
"/api/search?q=test",
"/api/tech_debts",
"/api/adrs",
"/api/context_workspaces",
"/api/handoff_memos",
"/api/milestones",
"/api/snippets",
"/api/pr_checklists",
"/api/error_fixes",
"/api/stats",
];
for ep in endpoints {
let app_inst = create_router(app_state.clone());
let req = Request::builder()
.uri(ep)
.body(Body::empty())
.unwrap();
let resp = app_inst.oneshot(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::OK, "Failed endpoint: {}", ep);
}
// Test task completion endpoint
let app_task = create_router(app_state.clone());
let complete_req = Request::builder()
.method("POST")
.uri("/api/tasks/task_123/complete")
.body(Body::empty())
.unwrap();
let complete_resp = app_task.oneshot(complete_req).await.unwrap();
assert_eq!(complete_resp.status(), StatusCode::OK);
// Test /shutdown unauthorized without token
let app_shut = create_router(app_state.clone());
let shut_req = Request::builder()
.method("POST")
.uri("/shutdown")
.body(Body::empty())
.unwrap();
let shut_resp = app_shut.oneshot(shut_req).await.unwrap();
assert_eq!(shut_resp.status(), StatusCode::UNAUTHORIZED);
}
}
// Force recompile
+1 -8
View File
@@ -104,14 +104,7 @@ pub async fn terminal_telemetry_handler(
state
.handler
.state
.telemetry
.terminal_history
.modify(|history| {
history.push_front(payload.clone());
if history.len() > 100 {
history.pop_back();
}
});
.record_terminal_history(payload.clone());
let ws_msg = serde_json::json!({
"type": "terminal_telemetry",