use crate::conversation::Message;
use crate::error::KowalskiError;
use async_trait::async_trait;
use futures::stream::Stream;
use std::pin::Pin;
pub type TokenStream<'a> = Pin<Box<dyn Stream<Item = Result<String, KowalskiError>> + Send + 'a>>;
#[async_trait]
pub trait LLMProvider: Send + Sync {
async fn chat(&self, model: &str, messages: &[Message]) -> Result<String, KowalskiError>;
async fn embed(&self, text: &str) -> Result<Vec<f32>, KowalskiError>;
fn supports_streaming(&self) -> bool;
fn chat_stream(&self, model: &str, messages: Vec<Message>) -> TokenStream<'_>;
}
pub fn chat_stream_single_chunk<'a>(
llm: &'a (dyn LLMProvider + 'a),
model: &'a str,
messages: Vec<Message>,
) -> TokenStream<'a> {
Box::pin(async_stream::stream! {
match llm.chat(model, &messages).await {
Ok(t) if !t.is_empty() => yield Ok(t),
Ok(_) => {}
Err(e) => yield Err(e),
}
})
}