use std::sync::Arc;
use axum::Router;
use axum::extract::State;
use axum::http::StatusCode;
use axum::response::Json;
use axum::routing::get;
use serde::{Deserialize, Serialize};
use crate::agent::approval::ApproveMode;
use crate::lsp::client::known_servers;
use super::state::AppState;
pub fn router() -> Router<Arc<AppState>> {
Router::new()
.route("/api/sidebar", get(sidebar_info))
.route("/api/approve-mode", get(get_approve_mode))
.route("/api/approve-mode", axum::routing::patch(set_approve_mode))
}
#[derive(Serialize)]
struct McpServerInfo {
name: String,
available: bool,
}
#[derive(Serialize)]
struct LspServerInfo {
name: String,
available: bool,
}
#[derive(Serialize)]
struct SidebarResponse {
mcp_servers: Vec<McpServerInfo>,
lsp_servers: Vec<LspServerInfo>,
}
async fn sidebar_info(State(state): State<Arc<AppState>>) -> Json<SidebarResponse> {
let working_dir = state.working_dir().await;
let mcp_servers = crate::mcp::config::load_mcp_status(&working_dir)
.into_iter()
.map(|s| McpServerInfo {
available: matches!(s.status, crate::mcp::config::McpStatus::Available),
name: s.name,
})
.collect();
let lsp_servers = known_servers()
.into_iter()
.filter(|s| {
std::process::Command::new("which")
.arg(&s.command)
.output()
.map(|o| o.status.success())
.unwrap_or(false)
})
.map(|s| LspServerInfo {
name: s.command.clone(),
available: true,
})
.collect();
Json(SidebarResponse {
mcp_servers,
lsp_servers,
})
}
#[derive(Serialize)]
struct ApproveModeResponse {
mode: String,
}
async fn get_approve_mode(State(state): State<Arc<AppState>>) -> Json<ApproveModeResponse> {
Json(ApproveModeResponse {
mode: state.approve_mode.get().to_string(),
})
}
#[derive(Deserialize)]
struct SetApproveModeRequest {
mode: String,
}
async fn set_approve_mode(
State(state): State<Arc<AppState>>,
Json(req): Json<SetApproveModeRequest>,
) -> Result<Json<ApproveModeResponse>, (StatusCode, String)> {
let mode = req.mode.parse::<ApproveMode>().map_err(|_| {
(
StatusCode::BAD_REQUEST,
format!("Invalid mode '{}'. Use: yolo, auto, manual", req.mode),
)
})?;
state.approve_mode.set(mode);
Ok(Json(ApproveModeResponse {
mode: state.approve_mode.get().to_string(),
}))
}