1use thiserror::Error;
4
5#[derive(Debug, Clone, Error)]
14pub enum LlmError {
15 #[error("LLM transport failed{}: {message}", status.map(|c| format!(" (HTTP {c})")).unwrap_or_default())]
19 Transport {
20 status: Option<u16>,
21 message: String,
22 },
23
24 #[error("LLM response was unparseable: {0}")]
26 Unparseable(String),
27
28 #[error("{message}")]
33 ModelStopped { finish: String, message: String },
34
35 #[error("LLM not configured: {0}")]
37 NotConfigured(String),
38
39 #[error("LLM backend {kind}: {message}")]
41 Backend {
42 kind: BackendErrorKind,
43 message: String,
44 },
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq)]
49pub enum BackendErrorKind {
50 Contract,
51 Authentication,
52 UsageLimit,
53 Request,
54 UnknownExit,
55}
56
57impl std::fmt::Display for BackendErrorKind {
58 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59 f.write_str(match self {
60 Self::Contract => "contract failure",
61 Self::Authentication => "authentication failure",
62 Self::UsageLimit => "usage limit",
63 Self::Request => "request rejection",
64 Self::UnknownExit => "failure",
65 })
66 }
67}
68
69impl BackendErrorKind {
70 pub fn as_str(self) -> &'static str {
72 match self {
73 Self::Contract => "contract",
74 Self::Authentication => "authentication",
75 Self::UsageLimit => "usage_limit",
76 Self::Request => "request",
77 Self::UnknownExit => "unknown_exit",
78 }
79 }
80}
81
82impl LlmError {
83 pub fn status(&self) -> Option<u16> {
85 match self {
86 Self::Transport { status, .. } => *status,
87 Self::Unparseable(_)
88 | Self::ModelStopped { .. }
89 | Self::NotConfigured(_)
90 | Self::Backend { .. } => None,
91 }
92 }
93}