arct_ai/
types.rs

1//! Common types for AI interactions
2
3use serde::{Deserialize, Serialize};
4use thiserror::Error;
5
6/// Result type for AI operations
7pub type AIResult<T> = Result<T, AIError>;
8
9/// AI-specific errors
10#[derive(Debug, Error)]
11pub enum AIError {
12    #[error("API error: {0}")]
13    ApiError(String),
14
15    #[error("Configuration error: {0}")]
16    ConfigError(String),
17
18    #[error("Network error: {0}")]
19    NetworkError(#[from] reqwest::Error),
20
21    #[error("Rate limit exceeded")]
22    RateLimitExceeded,
23
24    #[error("Invalid API key")]
25    InvalidApiKey,
26
27    #[error("Model not available: {0}")]
28    ModelNotAvailable(String),
29
30    #[error("Unknown error: {0}")]
31    Unknown(String),
32}
33
34/// AI provider configuration
35#[derive(Debug, Clone, Serialize, Deserialize)]
36pub enum AIConfig {
37    /// Anthropic (Claude) provider
38    Anthropic {
39        api_key: String,
40        model: String,
41    },
42
43    /// OpenAI (GPT) provider
44    OpenAI {
45        api_key: String,
46        model: String,
47    },
48
49    /// Local LLM (Ollama, LM Studio, etc.)
50    Local {
51        endpoint: String,
52        model: Option<String>,
53    },
54
55    /// Arc Academy managed service
56    Managed {
57        auth_token: String,
58    },
59
60    /// Claude Code CLI (for Max subscribers)
61    ClaudeCLI {
62        model: Option<String>,
63    },
64
65    /// AI disabled
66    Disabled,
67}
68
69impl Default for AIConfig {
70    fn default() -> Self {
71        Self::Disabled
72    }
73}
74
75/// Chat message role
76#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
77#[serde(rename_all = "lowercase")]
78pub enum Role {
79    System,
80    User,
81    Assistant,
82}
83
84/// A chat message
85#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct Message {
87    pub role: Role,
88    pub content: String,
89}
90
91impl Message {
92    pub fn system(content: impl Into<String>) -> Self {
93        Self {
94            role: Role::System,
95            content: content.into(),
96        }
97    }
98
99    pub fn user(content: impl Into<String>) -> Self {
100        Self {
101            role: Role::User,
102            content: content.into(),
103        }
104    }
105
106    pub fn assistant(content: impl Into<String>) -> Self {
107        Self {
108            role: Role::Assistant,
109            content: content.into(),
110        }
111    }
112}
113
114/// Options for AI completion
115#[derive(Debug, Clone, Serialize, Deserialize)]
116pub struct CompletionOptions {
117    pub temperature: f32,
118    pub max_tokens: usize,
119    pub stream: bool,
120}
121
122impl Default for CompletionOptions {
123    fn default() -> Self {
124        Self {
125            temperature: 0.7,
126            max_tokens: 1000,
127            stream: false,
128        }
129    }
130}