Skip to main content

omni_dev/claude/
ai.rs

1//! AI client trait and metadata definitions.
2
3pub mod bedrock;
4pub mod claude;
5pub mod openai;
6
7use std::future::Future;
8use std::pin::Pin;
9use std::time::Duration;
10
11use anyhow::Result;
12
13/// HTTP request timeout for AI API calls.
14///
15/// Set to 5 minutes to accommodate large prompts and long model responses
16/// (up to 64k output tokens) while preventing indefinite hangs.
17pub(crate) const REQUEST_TIMEOUT: Duration = Duration::from_secs(300);
18
19/// Metadata about an AI client implementation.
20#[derive(Clone, Debug)]
21pub struct AiClientMetadata {
22    /// Service provider name.
23    pub provider: String,
24    /// Model identifier.
25    pub model: String,
26    /// Maximum context length supported.
27    pub max_context_length: usize,
28    /// Maximum token response length supported.
29    pub max_response_length: usize,
30    /// Active beta header, if any: (key, value).
31    pub active_beta: Option<(String, String)>,
32}
33
34/// Prompt formatting families for AI providers.
35///
36/// Determines provider-specific prompt behaviour (e.g., how template
37/// instructions are phrased). Parse once at the boundary via
38/// [`AiClientMetadata::prompt_style`] and match on the enum downstream.
39#[derive(Clone, Copy, Debug, PartialEq, Eq)]
40pub enum PromptStyle {
41    /// Claude models handle "literal template" instructions correctly.
42    Claude,
43    /// OpenAI-compatible models (OpenAI, Ollama) need different formatting.
44    OpenAi,
45}
46
47impl AiClientMetadata {
48    /// Derives the prompt style from the provider name.
49    #[must_use]
50    pub fn prompt_style(&self) -> PromptStyle {
51        let p = self.provider.to_lowercase();
52        if p.contains("openai") || p.contains("ollama") {
53            PromptStyle::OpenAi
54        } else {
55            PromptStyle::Claude
56        }
57    }
58}
59
60/// Trait for AI service clients.
61pub trait AiClient: Send + Sync {
62    /// Sends a request to the AI service and returns the raw response.
63    fn send_request<'a>(
64        &'a self,
65        system_prompt: &'a str,
66        user_prompt: &'a str,
67    ) -> Pin<Box<dyn Future<Output = Result<String>> + Send + 'a>>;
68
69    /// Returns metadata about the AI client implementation.
70    fn get_metadata(&self) -> AiClientMetadata;
71}