use super::{openai_wire, CompletionRequest, CompletionResponse, Provider};
use crate::error::{Error, Result};
const ENDPOINT: &str = "https://openrouter.ai/api/v1/chat/completions";
pub struct OpenRouter {
client: reqwest::Client,
api_key: String,
model: String,
}
impl OpenRouter {
pub fn new(api_key: impl Into<String>, model: impl Into<String>) -> Self {
Self {
client: reqwest::Client::new(),
api_key: api_key.into(),
model: model.into(),
}
}
pub fn from_env() -> Result<Self> {
let api_key = std::env::var("OPENROUTER_API_KEY")
.map_err(|_| Error::Config("OPENROUTER_API_KEY is not set".into()))?;
let model = std::env::var("OPENROUTER_MODEL")
.map_err(|_| Error::Config("OPENROUTER_MODEL is not set".into()))?;
Ok(Self::new(api_key, model))
}
}
impl Provider for OpenRouter {
fn name(&self) -> &str {
"openrouter"
}
async fn complete(&self, request: CompletionRequest) -> Result<CompletionResponse> {
let resp = self
.client
.post(ENDPOINT)
.bearer_auth(&self.api_key)
.json(&openai_wire::body(&self.model, &request))
.send()
.await
.map_err(|e| Error::Provider(e.to_string()))?;
if !resp.status().is_success() {
let status = resp.status();
let detail = resp.text().await.unwrap_or_default();
return Err(Error::Provider(format!("HTTP {status}: {detail}")));
}
openai_wire::parse_stream(resp).await
}
}