use crate::message::{ConversationMessage, MessageKind, SearchHit};
use serde_json::{Map, Value, json};
#[must_use]
pub fn messages(msgs: &[ConversationMessage]) -> Value {
let messages: Vec<Value> = msgs.iter().map(message).collect();
json!({ "messages": messages })
}
fn message(msg: &ConversationMessage) -> Value {
let mut obj = Map::new();
obj.insert("entryId".into(), json!(msg.entry_id));
match &msg.kind {
MessageKind::TextContent(tc) => {
obj.insert("kind".into(), json!("text"));
obj.insert("role".into(), json!(tc.role));
obj.insert("text".into(), json!(tc.text));
}
MessageKind::AssistantResponse(ar) => {
let calls: Vec<Value> = ar
.tool_calls
.iter()
.map(|tc| json!({ "name": tc.name, "arguments": tc.arguments }))
.collect();
obj.insert("kind".into(), json!("assistant"));
obj.insert("thinking".into(), json!(ar.thinking));
obj.insert("text".into(), json!(ar.text));
obj.insert("toolCalls".into(), json!(calls));
}
MessageKind::ToolResultData(tr) => {
obj.insert("kind".into(), json!("toolResult"));
obj.insert("toolName".into(), json!(tr.tool_name));
obj.insert("content".into(), json!(tr.content));
obj.insert("isError".into(), json!(tr.is_error));
}
MessageKind::BashOutput(bo) => {
obj.insert("kind".into(), json!("bash"));
obj.insert("command".into(), json!(bo.command));
obj.insert("output".into(), json!(bo.output));
}
}
Value::Object(obj)
}
#[must_use]
pub fn hits(hits: &[SearchHit]) -> Value {
let hits: Vec<Value> = hits
.iter()
.map(|h| {
json!({
"entryId": h.entry_id,
"score": h.score,
"role": h.role,
"text": h.text,
"files": h.files,
"terms": h.terms,
})
})
.collect();
json!(hits)
}