huskies: merge 921
This commit is contained in:
@@ -215,6 +215,82 @@ pub async fn fetch_all_project_pipeline_statuses(
|
||||
join_all(futures).await.into_iter().collect()
|
||||
}
|
||||
|
||||
/// Fetch pipeline items for a single project URL.
|
||||
///
|
||||
/// Returns `{ "active": [...], "backlog_count": N }` preserving individual
|
||||
/// story items so the gateway UI can render them. On error returns
|
||||
/// `{ "error": "..." }`. This is distinct from
|
||||
/// `fetch_one_project_pipeline_status` which discards items and returns
|
||||
/// aggregated counts.
|
||||
pub async fn fetch_one_project_pipeline_items(url: &str, client: &Client) -> Value {
|
||||
let mcp_url = format!("{}/mcp", url.trim_end_matches('/'));
|
||||
let rpc_body = json!({
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"method": "tools/call",
|
||||
"params": {
|
||||
"name": "get_pipeline_status",
|
||||
"arguments": {}
|
||||
}
|
||||
});
|
||||
|
||||
match client.post(&mcp_url).json(&rpc_body).send().await {
|
||||
Ok(resp) => match resp.json::<Value>().await {
|
||||
Ok(upstream) => {
|
||||
if let Some(text) = upstream
|
||||
.get("result")
|
||||
.and_then(|r| r.get("content"))
|
||||
.and_then(|c| c.get(0))
|
||||
.and_then(|c| c.get("text"))
|
||||
.and_then(|t| t.as_str())
|
||||
{
|
||||
match serde_json::from_str::<Value>(text) {
|
||||
Ok(pipeline) => {
|
||||
let active = pipeline.get("active").cloned().unwrap_or(json!([]));
|
||||
let backlog_count = pipeline
|
||||
.get("backlog_count")
|
||||
.and_then(|n| n.as_u64())
|
||||
.unwrap_or(0);
|
||||
json!({ "active": active, "backlog_count": backlog_count })
|
||||
}
|
||||
Err(_) => json!({ "error": "invalid pipeline JSON" }),
|
||||
}
|
||||
} else {
|
||||
json!({ "error": "unexpected response shape" })
|
||||
}
|
||||
}
|
||||
Err(e) => json!({ "error": format!("invalid response: {e}") }),
|
||||
},
|
||||
Err(e) => json!({ "error": format!("unreachable: {e}") }),
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetch pipeline items from every registered project URL in parallel.
|
||||
///
|
||||
/// Returns per-project `{ "active": [...], "backlog_count": N }` objects
|
||||
/// suitable for the gateway web UI.
|
||||
pub async fn fetch_all_project_pipeline_items(
|
||||
project_urls: &BTreeMap<String, String>,
|
||||
client: &Client,
|
||||
) -> BTreeMap<String, Value> {
|
||||
use futures::future::join_all;
|
||||
|
||||
let futures: Vec<_> = project_urls
|
||||
.iter()
|
||||
.map(|(name, url)| {
|
||||
let name = name.clone();
|
||||
let url = url.clone();
|
||||
let client = client.clone();
|
||||
async move {
|
||||
let result = fetch_one_project_pipeline_items(&url, &client).await;
|
||||
(name, result)
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
join_all(futures).await.into_iter().collect()
|
||||
}
|
||||
|
||||
/// Fetch the pipeline status from a single project for the `gateway_status` tool.
|
||||
pub async fn fetch_pipeline_status_for_project(
|
||||
client: &Client,
|
||||
|
||||
Reference in New Issue
Block a user