use crate::message::{ConversationMessage, MessageKind, SearchHit, TaggedListing};
use serde_json::{Map, Value, json};
#[must_use]
pub fn to_string(value: &Value) -> String {
serde_json::to_string_pretty(value).expect("serialize json value")
}
#[must_use]
pub fn listings(contexts: &[TaggedListing]) -> Value {
let sessions: Vec<Value> = contexts
.iter()
.map(|t| {
json!({
"provider": t.provider,
"id": t.listing.id,
"tag": format!("{}:{}", t.provider, t.listing.id),
"detail": t.listing.detail,
"path": t.listing.path.as_ref().map(|p| p.display().to_string()),
})
})
.collect();
json!({ "sessions": sessions })
}
#[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)
}