goosedump 0.6.1

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

use serde_json::Value as JsonValue;

#[derive(Debug, Clone)]
pub struct ConversationMessage {
    pub entry_id: String,
    pub kind: MessageKind,
}

impl ConversationMessage {
    #[must_use]
    pub fn new(entry_id: impl Into<String>, kind: MessageKind) -> Self {
        Self {
            entry_id: entry_id.into(),
            kind,
        }
    }

    /// The conversational role (`user`/`assistant`) this message carries.
    #[must_use]
    pub fn role(&self) -> &str {
        match &self.kind {
            MessageKind::TextContent(tc) => tc.role.as_str(),
            MessageKind::AssistantResponse(_) => "assistant",
            MessageKind::ToolResultData(_) | MessageKind::BashOutput(_) => "user",
        }
    }
}

#[derive(Debug, Clone)]
pub enum MessageKind {
    TextContent(TextContent),
    AssistantResponse(AssistantResponse),
    ToolResultData(ToolResultData),
    BashOutput(BashOutput),
}

#[derive(Debug, Clone)]
pub struct TextContent {
    pub role: String,
    pub text: String,
}

#[derive(Debug, Clone)]
pub struct AssistantResponse {
    pub thinking: Vec<String>,
    pub tool_calls: Vec<ToolCall>,
    pub text: String,
}

#[derive(Debug, Clone)]
pub struct ToolResultData {
    /// Correlation id of the call this result answers (provider `tool_use_id`
    /// / `call_id`); empty when the source format does not address results by
    /// id. Lets renderers re-pair a result with its originating call.
    pub call_id: String,
    pub tool_name: String,
    pub content: String,
    pub is_error: bool,
}

#[derive(Debug, Clone)]
pub struct BashOutput {
    pub command: String,
    pub output: String,
}

#[derive(Debug, Clone)]
pub struct ToolCall {
    /// Provider call id (`tool_use.id` / `call_id`); empty when the source
    /// format does not assign one. Lets renderers correlate a later tool
    /// result back to this call.
    pub id: String,
    pub name: String,
    pub arguments: JsonValue,
}

#[derive(Debug, Clone)]
pub struct Entry {
    pub id: String,
    pub parent_id: String,
}

#[derive(Debug, Clone)]
pub struct Context {
    pub entries: Vec<Entry>,
    pub messages: Vec<ConversationMessage>,
    /// Working directory recorded in the session, when the source format
    /// carries one. Re-emitted by renderers whose native format has a `cwd`
    /// slot (e.g. the Pi/Codex session header).
    pub cwd: Option<String>,
}

#[derive(Debug, Clone)]
pub struct ContextListing {
    pub id: String,
    pub detail: String,
}

/// A listing paired with the provider it was discovered under, so that
/// aggregated `list` output can be tagged as `<provider>:<id>`.
#[derive(Debug, Clone)]
pub struct TaggedListing {
    pub provider: &'static str,
    pub listing: ContextListing,
}