use std::io::{BufRead, Write};
use std::sync::{Arc, Mutex};
use std::time::Duration;
use serde_json::{Value, json};
use crate::manager::registry::TerminalRegistry;
use super::tools;
use super::types::{JsonRpcRequest, JsonRpcResponse};
pub fn run_stdio_server() {
let registry = Arc::new(Mutex::new(TerminalRegistry::default()));
let tick_registry = Arc::clone(®istry);
std::thread::spawn(move || loop {
std::thread::sleep(Duration::from_millis(10));
if let Ok(mut reg) = tick_registry.try_lock() {
reg.tick_all();
}
});
let stdin = std::io::stdin();
let stdout = std::io::stdout();
let mut stdout = stdout.lock();
for line in stdin.lock().lines() {
let line = match line {
Ok(l) => l,
Err(_) => break,
};
if line.trim().is_empty() {
continue;
}
let request: JsonRpcRequest = match serde_json::from_str(&line) {
Ok(r) => r,
Err(e) => {
let resp = JsonRpcResponse::error(None, -32700, format!("Parse error: {}", e));
let _ = writeln!(stdout, "{}", serde_json::to_string(&resp).unwrap());
let _ = stdout.flush();
continue;
}
};
let response = handle_request(®istry, &request);
if let Some(resp) = response {
let _ = writeln!(stdout, "{}", serde_json::to_string(&resp).unwrap());
let _ = stdout.flush();
}
}
}
fn handle_request(
registry: &Arc<Mutex<TerminalRegistry>>,
request: &JsonRpcRequest,
) -> Option<JsonRpcResponse> {
match request.method.as_str() {
"initialize" => {
let result = json!({
"protocolVersion": "2024-11-05",
"capabilities": { "tools": {} },
"serverInfo": { "name": "npcterm39", "version": "1.1.0" }
});
Some(JsonRpcResponse::success(request.id.clone(), result))
}
"notifications/initialized" => None,
"tools/list" => {
let tool_defs = tools::tool_definitions();
Some(JsonRpcResponse::success(request.id.clone(), json!({ "tools": tool_defs })))
}
"tools/call" => {
let tool_name = request.params.get("name").and_then(|v| v.as_str()).unwrap_or("");
let args = request.params.get("arguments").cloned().unwrap_or(Value::Object(Default::default()));
let mut reg = registry.lock().unwrap();
let result = tools::handle_tool_call(&mut reg, tool_name, &args);
Some(JsonRpcResponse::success(
request.id.clone(),
serde_json::to_value(&result).unwrap(),
))
}
"ping" => Some(JsonRpcResponse::success(request.id.clone(), json!({}))),
_ => {
if request.id.is_some() {
Some(JsonRpcResponse::error(
request.id.clone(),
-32601,
format!("Method not found: {}", request.method),
))
} else {
None
}
}
}
}