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}