oxi-tui 0.61.0

Terminal UI widgets and theme system for oxi, built on ratatui
Documentation
//! Core types for the chat widget.

// ── Types ──────────────────────────────────────────────────────────────

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ToolCallStatus {
    Requested,
    Executing,
    Done,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MessageRole {
    User,
    Assistant,
    System,
}

/// Severity tag for advisor (read-only reviewer) notes that surface in the
/// chat transcript as a persistent card. Presentation-layer mirror of
/// `oxi_agent::advisor::AdvisorSeverity`; the conversion happens at the
/// boundary in `oxi-cli/src/tui/handlers.rs` so `oxi-tui` keeps its
/// "no oxi-* deps" rule (see AGENTS.md).
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum AdvisorSeverity {
    /// Non-urgent cleanup / refactor / missed opportunity.
    #[default]
    Nit,
    /// Agent may be going off-track or missed something material.
    Concern,
    /// Stop and reconsider.
    Blocker,
}

impl AdvisorSeverity {
    /// Short uppercase label rendered on the card (e.g. `[NIT]`).
    #[must_use]
    pub const fn label(self) -> &'static str {
        match self {
            AdvisorSeverity::Nit => "NIT",
            AdvisorSeverity::Concern => "CONCERN",
            AdvisorSeverity::Blocker => "BLOCKER",
        }
    }
}

#[derive(Debug, Clone)]
pub enum ContentBlock {
    Text {
        content: String,
    },
    Thinking {
        content: String,
        collapsed: bool,
    },
    ToolCall {
        id: String,
        name: String,
        arguments: String,
        result: Option<(String, bool)>,
        status: ToolCallStatus,
        /// Formatted execution duration (e.g. "1.2s").
        duration: Option<String>,
    },
    ToolResult {
        tool_name: String,
        content: String,
        is_error: bool,
    },
    Error {
        title: String,
        message: String,
        retryable: bool,
    },
    Image {
        mime_type: String,
        base64_data: String,
    },
    /// Welcome dashboard panel with environment info.
    Dashboard {
        info: crate::widgets::chat::DashboardInfo,
    },
    /// Read-only advisor note surfaced as a severity-colored card.
    /// Persistent transcript line for aside/preserve channel advice.
    Advisory {
        body: String,
        severity: AdvisorSeverity,
        timestamp_ms: u64,
    },
}

#[derive(Debug, Clone)]
pub struct ChatMessage {
    pub role: MessageRole,
    pub content_blocks: Vec<ContentBlock>,
    pub timestamp: i64,
}

#[derive(Debug, Clone)]
pub struct StreamingState {
    pub message: ChatMessage,
}