AkurAI Build
Menu

Public repository / master

AkurAI-Framework / crates/llm/src/error.rs

Latest change a81af83654d182e3becb8e2beaed6d61a3bd8e6b - feat(llm): streaming OpenAI-compatible client + /api/assistant SSE endpoint by Ólafur Búi Ólafsson

//! Errors for the streaming chat client.
//!
//! Every failure mode of the plain-HTTP round-trip maps to a distinct,
//! non-panicking variant so callers (the CLI's `/api/assistant` relay) can
//! surface a precise `error` SSE event instead of crashing the connection.

use std::fmt;

/// A failure while streaming a chat completion from an OpenAI-compatible
/// endpoint.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum LlmError {
    /// The endpoint string couldn't be parsed into `host[:port]`.
    InvalidEndpoint(String),
    /// An `https://` URL was supplied. std has no TLS; terminate TLS at the
    /// edge (Caddy/nginx) and point this client at the plain-HTTP origin.
    TlsUnsupported(String),
    /// TCP connect failed (e.g. connection refused, DNS failure, host down).
    Connect(String),
    /// The socket read timed out before the next event arrived.
    Timeout,
    /// A lower-level I/O error during send/receive.
    Io(String),
    /// The server replied with a non-2xx status. Carries the code and a short
    /// snippet of the body for diagnosis.
    HttpStatus { code: u16, snippet: String },
    /// The response was missing, truncated, or had no status line.
    ShortResponse,
    /// A `data:` SSE payload was not valid `chat.completion.chunk` JSON.
    MalformedChunk(String),
}

impl fmt::Display for LlmError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            LlmError::InvalidEndpoint(s) => write!(f, "invalid endpoint: {s}"),
            LlmError::TlsUnsupported(s) => write!(
                f,
                "TLS is not supported (std has no TLS); use a plain http:// origin, not {s}"
            ),
            LlmError::Connect(s) => write!(f, "could not connect: {s}"),
            LlmError::Timeout => write!(f, "read timed out"),
            LlmError::Io(s) => write!(f, "I/O error: {s}"),
            LlmError::HttpStatus { code, snippet } => {
                write!(f, "LLM endpoint returned HTTP {code}: {snippet}")
            }
            LlmError::ShortResponse => write!(f, "empty or truncated HTTP response"),
            LlmError::MalformedChunk(s) => write!(f, "malformed SSE chunk: {s}"),
        }
    }
}

impl std::error::Error for LlmError {}