goosedump 0.6.6

Coding agent context data browser
// SPDX-License-Identifier: LGPL-2.1-or-later
// Copyright (C) Jarkko Sakkinen 2026

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)
}