use crate::llm::actions::protocol_trait::ActionResult;
use anyhow::{Context, Result};
use serde_json::json;
use std::collections::HashMap;
use tracing::debug;
#[derive(Debug)]
pub struct HttpResponseData {
pub status: u16,
pub headers: HashMap<String, String>,
pub body: String,
}
pub fn execute_http_response_action(action: serde_json::Value) -> Result<ActionResult> {
let status_value = action
.get("status")
.context("Missing 'status' parameter (HTTP status code, e.g. 200)")?;
let status = match status_value {
serde_json::Value::Number(n) => n.as_u64(),
serde_json::Value::String(s) => s.trim().parse::<u64>().ok(),
_ => None,
}
.filter(|s| (100..=599).contains(s))
.with_context(|| {
format!(
"Invalid 'status' parameter {}: expected an HTTP status code between 100 and 599",
status_value
)
})? as u16;
let headers = action
.get("headers")
.and_then(|v| v.as_object())
.map(|obj| {
obj.iter()
.filter_map(|(k, v)| match v {
serde_json::Value::Null => None,
serde_json::Value::String(s) => Some((k.clone(), s.clone())),
other => Some((k.clone(), other.to_string())),
})
.collect::<HashMap<String, String>>()
})
.unwrap_or_default();
let body = match action.get("body") {
None | Some(serde_json::Value::Null) => String::new(),
Some(serde_json::Value::String(s)) => s.clone(),
Some(other) => {
debug!(
"HTTP response body was not a string; serializing {} to JSON text",
other
);
other.to_string()
}
};
let response_data = json!({
"status": status,
"headers": headers,
"body": body
});
Ok(ActionResult::Output(
serde_json::to_vec(&response_data).context("Failed to serialize HTTP response")?,
))
}