use crate::message::{ConversationMessage, Part, 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));
obj.insert("role".into(), json!(msg.role));
if let Some(model) = &msg.model {
obj.insert("model".into(), json!(model));
}
if let Some(timestamp) = &msg.timestamp {
obj.insert("timestamp".into(), json!(timestamp.to_rfc3339()));
}
let parts: Vec<Value> = msg.parts.iter().map(part).collect();
obj.insert("parts".into(), json!(parts));
Value::Object(obj)
}
fn part(part: &Part) -> Value {
match part {
Part::Text(text) => json!({ "type": "text", "text": text }),
Part::Reasoning(reasoning) => {
let mut obj = Map::new();
obj.insert("type".into(), json!("reasoning"));
obj.insert("text".into(), json!(reasoning.text));
if !reasoning.signature.is_empty() {
obj.insert("signature".into(), json!(reasoning.signature));
}
if reasoning.redacted {
obj.insert("redacted".into(), json!(true));
}
Value::Object(obj)
}
Part::ToolCall(call) => json!({
"type": "toolCall",
"id": call.id,
"name": call.name,
"arguments": call.arguments,
}),
Part::ToolResult(result) => json!({
"type": "toolResult",
"callId": result.call_id,
"toolName": result.tool_name,
"content": result.content,
"isError": result.is_error,
}),
Part::Image(image) => {
let mut obj = Map::new();
obj.insert("type".into(), json!("image"));
obj.insert("mimeType".into(), json!(image.mime_type));
obj.insert("data".into(), json!(image.data));
Value::Object(obj)
}
Part::Bash(bash) => json!({
"type": "bash",
"command": bash.command,
"output": bash.output,
}),
Part::Passthrough(passthrough) => json!({
"type": "passthrough",
"kind": passthrough.kind,
"raw": passthrough.raw,
}),
}
}
#[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)
}