diff --git a/frontend/src/api/gateway.ts b/frontend/src/api/gateway.ts index e803ffda..a88fdc72 100644 --- a/frontend/src/api/gateway.ts +++ b/frontend/src/api/gateway.ts @@ -134,9 +134,22 @@ export const gatewayApi = { }); }, - /// Fetch pipeline status from all registered projects. - getAllProjectsPipeline(): Promise { - return gatewayRequest("/api/gateway/pipeline"); + /// Fetch pipeline status from all registered projects via the pipeline.get read-RPC. + async getAllProjectsPipeline(): Promise { + const res = await fetch("/mcp", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "pipeline.get", params: {} }), + }); + if (!res.ok) { + const text = await res.text(); + throw new Error(text || `Request failed (${res.status})`); + } + const rpc = await res.json() as { result?: AllProjectsPipeline; error?: { message: string } }; + if (rpc.error) { + throw new Error(rpc.error.message); + } + return rpc.result!; }, /// Switch the active project. diff --git a/server/src/gateway.rs b/server/src/gateway.rs index 3a67d447..0b99d617 100644 --- a/server/src/gateway.rs +++ b/server/src/gateway.rs @@ -27,10 +27,6 @@ pub fn build_gateway_route(state_arc: Arc) -> impl poem::Endpoint .at("/bot-config", poem::get(gateway_bot_config_page_handler)) .at("/api/gateway", poem::get(gateway_api_handler)) .at("/api/gateway/switch", poem::post(gateway_switch_handler)) - .at( - "/api/gateway/pipeline", - poem::get(gateway_all_pipeline_handler), - ) .at( "/api/gateway/projects", poem::post(gateway_add_project_handler), diff --git a/server/src/http/gateway/mcp.rs b/server/src/http/gateway/mcp.rs index cd8fc136..5f6d92e2 100644 --- a/server/src/http/gateway/mcp.rs +++ b/server/src/http/gateway/mcp.rs @@ -143,6 +143,7 @@ pub async fn gateway_mcp_post_handler( Ok(resp) => to_json_response(resp), Err(e) => to_json_response(JsonRpcResponse::error(rpc.id, -32603, e)), }, + "pipeline.get" => to_json_response(handle_pipeline_get(&state, rpc.id).await), "tools/call" => { let tool_name = rpc .params @@ -424,3 +425,21 @@ async fn handle_aggregate_pipeline_status_tool( }), ) } + +/// Handle the `pipeline.get` read-RPC — returns the same shape as the old +/// `GET /api/gateway/pipeline` endpoint: `{ "active": "...", "projects": {...} }`. +async fn handle_pipeline_get(state: &GatewayState, id: Option) -> JsonRpcResponse { + let project_urls: BTreeMap = state + .projects + .read() + .await + .iter() + .map(|(n, e)| (n.clone(), e.url.clone())) + .collect(); + + let results = + gateway::io::fetch_all_project_pipeline_statuses(&project_urls, &state.client).await; + let active = state.active_project.read().await.clone(); + + JsonRpcResponse::success(id, json!({ "active": active, "projects": results })) +} diff --git a/server/src/http/gateway/mod.rs b/server/src/http/gateway/mod.rs index 4d8e5034..ee52a946 100644 --- a/server/src/http/gateway/mod.rs +++ b/server/src/http/gateway/mod.rs @@ -16,8 +16,8 @@ mod websocket; pub use mcp::{gateway_mcp_get_handler, gateway_mcp_post_handler}; pub use rest::{ - gateway_add_project_handler, gateway_all_pipeline_handler, gateway_api_handler, - gateway_assign_agent_handler, gateway_bot_config_get_handler, gateway_bot_config_page_handler, + gateway_add_project_handler, gateway_api_handler, gateway_assign_agent_handler, + gateway_bot_config_get_handler, gateway_bot_config_page_handler, gateway_bot_config_save_handler, gateway_generate_token_handler, gateway_list_agents_handler, gateway_mode_handler, gateway_remove_project_handler, gateway_switch_handler, }; diff --git a/server/src/http/gateway/rest.rs b/server/src/http/gateway/rest.rs index 8d35ae4b..d7e2dac8 100644 --- a/server/src/http/gateway/rest.rs +++ b/server/src/http/gateway/rest.rs @@ -1,4 +1,4 @@ -//! REST HTTP handlers for the gateway: agents, projects, bot configuration, and pipeline. +//! REST HTTP handlers for the gateway: agents, projects, and bot configuration. use crate::service::gateway::{self, GatewayState}; use poem::handler; @@ -8,7 +8,6 @@ use poem::web::{Data, Json}; use poem::{Body, Response}; use serde::{Deserialize, Serialize}; use serde_json::{Value, json}; -use std::collections::BTreeMap; use std::sync::Arc; // ── Agent REST handlers ─────────────────────────────────────────────────────── @@ -257,28 +256,6 @@ pub async fn gateway_bot_config_save_handler( } } -/// `GET /api/gateway/pipeline` — fetch pipeline status from all registered projects. -#[handler] -pub async fn gateway_all_pipeline_handler(state: Data<&Arc>) -> Response { - let project_urls: BTreeMap = state - .projects - .read() - .await - .iter() - .map(|(n, e)| (n.clone(), e.url.clone())) - .collect(); - - let results = - gateway::io::fetch_all_project_pipeline_statuses(&project_urls, &state.client).await; - - let active = state.active_project.read().await.clone(); - let body = json!({ "active": active, "projects": results }); - Response::builder() - .status(StatusCode::OK) - .header("Content-Type", "application/json") - .body(Body::from(serde_json::to_vec(&body).unwrap_or_default())) -} - // ── Bot config page ─────────────────────────────────────────────────────────── /// Self-contained HTML page for bot configuration.