use serde_json::Value;
pub(super) fn forward_to_http(
method: reqwest::Method,
url: &str,
body: Option<&Value>,
extra_headers: &[(&str, String)],
) -> Result<Value, String> {
let client = reqwest::blocking::Client::builder()
.timeout(std::time::Duration::from_secs(15))
.build()
.map_err(|e| format!("federation_forward: build client: {e}"))?;
let mut req = client.request(method, url);
for (k, v) in extra_headers {
req = req.header(*k, v);
}
if let Some(b) = body {
req = req.json(b);
}
let resp = req
.send()
.map_err(|e| format!("federation_forward: POST {url}: {e}"))?;
let status = resp.status();
let text = resp
.text()
.map_err(|e| format!("federation_forward: read body from {url}: {e}"))?;
if !status.is_success() {
return Err(format!(
"federation_forward: {url} returned {status}: {text}"
));
}
serde_json::from_str::<Value>(&text)
.map_err(|e| format!("federation_forward: parse body from {url}: {e} (raw: {text})"))
}
pub(super) fn forward_store_to_http(
forward_url: &str,
params: &Value,
mcp_client: Option<&str>,
) -> Result<Value, String> {
let url = format!("{}/api/v1/memories", forward_url.trim_end_matches('/'));
let explicit_agent_id = params["agent_id"]
.as_str()
.or_else(|| params["metadata"]["agent_id"].as_str());
let agent_id = crate::identity::resolve_agent_id(explicit_agent_id, mcp_client)
.map_err(|e| e.to_string())?;
let body = params.clone();
let headers: &[(&str, String)] = &[(crate::HEADER_AGENT_ID, agent_id)];
forward_to_http(reqwest::Method::POST, &url, Some(&body), headers)
}