1use std::collections::BTreeMap;
2
3use runifold_core::RetrySafety;
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6use thiserror::Error;
7
8#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
10#[non_exhaustive]
11pub enum ModelErrorKind {
12 InvalidRequest,
14 UnsupportedFeature,
16 Transport,
18 Protocol,
20 StreamState,
22 MalformedToolArguments,
24 Provider,
26 Cancelled,
28 DeadlineExceeded,
30}
31
32#[derive(Clone, Debug, Deserialize, Error, PartialEq, Serialize)]
34#[error("{kind:?}: {message}")]
35pub struct ModelError {
36 pub kind: ModelErrorKind,
38 pub message: String,
40 pub provider: Option<String>,
42 pub retry_safety: RetrySafety,
44 pub metadata: BTreeMap<String, Value>,
46}
47
48impl ModelError {
49 pub const fn diagnostic_code(&self) -> &'static str {
54 match self.kind {
55 ModelErrorKind::InvalidRequest => "RF-PROVIDER-001",
56 ModelErrorKind::UnsupportedFeature => "RF-PROVIDER-002",
57 ModelErrorKind::Transport => "RF-PROVIDER-003",
58 ModelErrorKind::Protocol => "RF-PROVIDER-004",
59 ModelErrorKind::StreamState => "RF-PROVIDER-005",
60 ModelErrorKind::MalformedToolArguments => "RF-PROVIDER-006",
61 ModelErrorKind::Provider => "RF-PROVIDER-007",
62 ModelErrorKind::Cancelled => "RF-PROVIDER-008",
63 ModelErrorKind::DeadlineExceeded => "RF-PROVIDER-009",
64 }
65 }
66
67 pub fn local(kind: ModelErrorKind, message: impl Into<String>) -> Self {
69 Self {
70 kind,
71 message: message.into(),
72 provider: None,
73 retry_safety: RetrySafety::Unknown,
74 metadata: BTreeMap::new(),
75 }
76 }
77}