huskies: merge 899
This commit is contained in:
@@ -203,14 +203,11 @@ pub async fn gateway_mcp_post_handler(
|
||||
}
|
||||
|
||||
/// Proxy a request to the active project and format the response.
|
||||
///
|
||||
/// Prefers the live sled-uplink WebSocket when one is attached (story 899
|
||||
/// AC 2); falls back to the legacy HTTP proxy otherwise.
|
||||
async fn proxy_and_respond(state: &GatewayState, bytes: &[u8], id: Option<Value>) -> Response {
|
||||
let url = match state.active_url().await {
|
||||
Ok(u) => u,
|
||||
Err(e) => {
|
||||
return to_json_response(JsonRpcResponse::error(id, -32603, e.to_string()));
|
||||
}
|
||||
};
|
||||
match gateway::io::proxy_mcp_call(&state.client, &url, bytes).await {
|
||||
match state.proxy_active_mcp(bytes).await {
|
||||
Ok(resp_body) => Response::builder()
|
||||
.status(StatusCode::OK)
|
||||
.header("Content-Type", "application/json")
|
||||
@@ -316,13 +313,23 @@ fn handle_initialize(id: Option<Value>) -> JsonRpcResponse {
|
||||
}
|
||||
|
||||
/// Fetch tools/list from the active project and merge in gateway tools.
|
||||
///
|
||||
/// Routes via the sled-uplink WS when one is attached (story 899 AC 2);
|
||||
/// falls back to HTTP otherwise.
|
||||
async fn handle_tools_list(
|
||||
state: &GatewayState,
|
||||
id: Option<Value>,
|
||||
) -> Result<JsonRpcResponse, String> {
|
||||
let url = state.active_url().await.map_err(|e| e.to_string())?;
|
||||
|
||||
let resp_json = gateway::io::fetch_tools_list(&state.client, &url).await?;
|
||||
let rpc_body = json!({
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"method": "tools/list",
|
||||
"params": {}
|
||||
});
|
||||
let bytes = serde_json::to_vec(&rpc_body).map_err(|e| e.to_string())?;
|
||||
let resp_bytes = state.proxy_active_mcp(&bytes).await?;
|
||||
let resp_json: Value =
|
||||
serde_json::from_slice(&resp_bytes).map_err(|e| format!("invalid tools/list JSON: {e}"))?;
|
||||
|
||||
let mut tools: Vec<Value> = resp_json
|
||||
.get("result")
|
||||
@@ -414,21 +421,36 @@ async fn handle_gateway_status_tool(state: &GatewayState, id: Option<Value>) ->
|
||||
async fn handle_gateway_health_tool(state: &GatewayState, id: Option<Value>) -> JsonRpcResponse {
|
||||
let mut results = BTreeMap::new();
|
||||
|
||||
let project_entries: Vec<(String, String)> = state
|
||||
// Build the project list, preferring the WS-uplink heartbeat as the
|
||||
// source of truth for liveness (story 899 AC 3). HTTP polls are used
|
||||
// only as a fallback when no live sled is connected.
|
||||
let project_names: Vec<(String, Option<String>)> = state
|
||||
.projects
|
||||
.read()
|
||||
.await
|
||||
.iter()
|
||||
.map(|(n, e)| (n.clone(), e.url.clone()))
|
||||
.collect();
|
||||
for (name, url) in &project_entries {
|
||||
let status = match gateway::io::check_project_health(&state.client, url).await {
|
||||
Ok(true) => "healthy".to_string(),
|
||||
Ok(false) => "unhealthy".to_string(),
|
||||
Err(e) => e,
|
||||
let sled_conns = state.sled_connections.read().await;
|
||||
for (name, url_opt) in &project_names {
|
||||
let status = if let Some(conn) = sled_conns.get(name) {
|
||||
if conn.is_alive(crate::service::gateway::HEARTBEAT_MAX_AGE_MS) {
|
||||
"healthy (ws)".to_string()
|
||||
} else {
|
||||
"stale (ws heartbeat overdue)".to_string()
|
||||
}
|
||||
} else if let Some(url) = url_opt {
|
||||
match gateway::io::check_project_health(&state.client, url).await {
|
||||
Ok(true) => "healthy".to_string(),
|
||||
Ok(false) => "unhealthy".to_string(),
|
||||
Err(e) => e,
|
||||
}
|
||||
} else {
|
||||
"no uplink and no url configured".to_string()
|
||||
};
|
||||
results.insert(name.clone(), status);
|
||||
}
|
||||
drop(sled_conns);
|
||||
|
||||
let active = state.active_project.read().await.clone();
|
||||
JsonRpcResponse::success(
|
||||
@@ -512,7 +534,7 @@ async fn handle_aggregate_pipeline_status_tool(
|
||||
.read()
|
||||
.await
|
||||
.iter()
|
||||
.map(|(name, entry)| (name.clone(), entry.url.clone()))
|
||||
.filter_map(|(name, entry)| entry.url.as_ref().map(|u| (name.clone(), u.clone())))
|
||||
.collect();
|
||||
|
||||
let statuses =
|
||||
@@ -656,7 +678,7 @@ async fn handle_pipeline_get(state: &GatewayState, id: Option<Value>) -> JsonRpc
|
||||
.read()
|
||||
.await
|
||||
.iter()
|
||||
.map(|(n, e)| (n.clone(), e.url.clone()))
|
||||
.filter_map(|(n, e)| e.url.as_ref().map(|u| (n.clone(), u.clone())))
|
||||
.collect();
|
||||
|
||||
let results = gateway::io::fetch_all_project_pipeline_items(&project_urls, &state.client).await;
|
||||
|
||||
Reference in New Issue
Block a user