Skip to main content

oratos_generate/llm/
mod.rs

1//! LLM provider abstraction (v0.3 foundation).
2
3use anyhow::Result;
4
5/// Optional LLM backend for captioning, alt-text review, and summaries.
6pub trait LlmProvider: Send + Sync {
7    fn id(&self) -> &'static str;
8
9    /// Complete a prompt and return model text (no streaming in v0.3 preview).
10    fn complete(&self, prompt: &str) -> Result<String>;
11}
12
13/// Configuration for an LLM provider (stored in future `oratos.toml` `[llm]` section).
14#[derive(Debug, Clone)]
15pub struct LlmProviderConfig {
16    pub provider: String,
17    pub base_url: Option<String>,
18    pub model: Option<String>,
19    pub api_key_env: Option<String>,
20}
21
22/// Placeholder OpenAI-compatible provider (not wired to CLI in v0.3 preview).
23pub struct OpenAiCompatibleProvider {
24    pub base_url: String,
25    pub model: String,
26}
27
28impl LlmProvider for OpenAiCompatibleProvider {
29    fn id(&self) -> &'static str {
30        "openai-compatible"
31    }
32
33    fn complete(&self, _prompt: &str) -> Result<String> {
34        anyhow::bail!("LLM provider support is preview-only in v0.3; configure in a future release")
35    }
36}
37
38/// Placeholder Ollama provider.
39pub struct OllamaProvider {
40    pub base_url: String,
41    pub model: String,
42}
43
44impl LlmProvider for OllamaProvider {
45    fn id(&self) -> &'static str {
46        "ollama"
47    }
48
49    fn complete(&self, _prompt: &str) -> Result<String> {
50        anyhow::bail!("Ollama provider is preview-only in v0.3")
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57
58    #[test]
59    fn provider_ids_and_preview_errors() {
60        let openai = OpenAiCompatibleProvider {
61            base_url: "http://localhost".into(),
62            model: "gpt".into(),
63        };
64        assert_eq!(openai.id(), "openai-compatible");
65        assert!(openai.complete("hi").is_err());
66
67        let ollama = OllamaProvider {
68            base_url: "http://localhost:11434".into(),
69            model: "llama".into(),
70        };
71        assert_eq!(ollama.id(), "ollama");
72        assert!(ollama.complete("hi").is_err());
73    }
74}