use std::collections::HashMap;
use serde_json::Value;
use lc_chains::base::{BaseChain, ChainError, ChainResult};
use crate::protocol::A2AMessage;
pub(crate) fn extract_message(params: &Value) -> A2AMessage {
match params.get("message") {
Some(msg_val) => serde_json::from_value(msg_val.clone()).unwrap_or_else(|_| {
let content = extract_content_text(msg_val.get("content"));
if content.is_empty() {
log::warn!(
"tasks/send: message content is not a plain string and yielded no text; \
role={:?} content={:?}",
msg_val.get("role"),
msg_val.get("content")
);
}
A2AMessage::new(
msg_val
.get("role")
.and_then(Value::as_str)
.unwrap_or("user"),
content,
)
}),
None => A2AMessage::user(params.to_string()),
}
}
pub(crate) fn extract_content_text(content: Option<&Value>) -> String {
match content {
None => String::new(),
Some(Value::String(s)) => s.clone(),
Some(Value::Object(map)) => map
.get("text")
.or_else(|| map.get("content"))
.and_then(Value::as_str)
.map(str::to_string)
.unwrap_or_else(|| serde_json::to_string(map).unwrap_or_default()),
Some(v) => serde_json::to_string(v).unwrap_or_default(),
}
}
pub(crate) fn build_chain_input_from_history(
history: &[A2AMessage],
chain: &dyn BaseChain,
) -> HashMap<String, Value> {
let content = if history.len() == 1 {
history[0].content.clone()
} else {
history
.iter()
.map(|m| format!("{}: {}", m.role, m.content))
.collect::<Vec<_>>()
.join("\n")
};
build_chain_input(&content, chain)
}
pub(crate) fn build_chain_input(content: &str, chain: &dyn BaseChain) -> HashMap<String, Value> {
let mut map = HashMap::new();
let input_keys = chain.input_keys();
if let Some(first_key) = input_keys.first() {
map.insert(first_key.to_string(), Value::String(content.to_string()));
} else {
map.insert("input".to_string(), Value::String(content.to_string()));
}
map
}
pub(crate) fn extract_output(result: &ChainResult) -> String {
result
.values()
.next()
.and_then(|v| v.as_str())
.unwrap_or("")
.to_string()
}
pub(crate) fn is_input_required(e: &ChainError) -> bool {
matches!(e, ChainError::MissingInput(_) | ChainError::InputError(_))
}