Skip to main content

pi_ai/
lib.rs

1//! `pi-ai` — Unified multi-provider LLM API.
2//!
3//! Rust port of the TypeScript package `@earendil-works/pi-ai`. The original
4//! project supports many providers; this port focuses on the two most common
5//! agent backends: Anthropic Messages and OpenAI Chat Completions. Both share
6//! the same `Message`/`Tool`/`AssistantMessageEvent` types so the agent loop
7//! is provider-agnostic.
8
9pub mod error;
10pub mod providers;
11pub mod retry;
12pub mod stream;
13pub mod types;
14
15pub use error::{Error, Result};
16pub use providers::{
17    anthropic::AnthropicProvider, google::GoogleProvider, openai::OpenAiProvider, Provider,
18};
19pub use stream::AssistantMessageEventStream;
20pub use types::{
21    now_ms, AssistantMessage, AssistantMessageEvent, Content, Context, Message, Model, StopReason,
22    StreamOptions, ThinkingLevel, Tool, ToolResultMessage, Usage,
23};
24
25/// Entry point that mirrors `streamSimple()` in pi-ai TS: pick the provider
26/// implementation from `model.api` and return a stream of message events.
27///
28/// `openai-completions` covers OpenAI and every OpenAI-compatible passthrough
29/// (OpenRouter, Together, Groq, Cerebras, DeepSeek, Fireworks, xAI, etc.) —
30/// just set `Model::base_url` (or `StreamOptions::base_url`) accordingly.
31pub async fn stream_simple(
32    model: &Model,
33    context: &Context,
34    options: &StreamOptions,
35) -> Result<AssistantMessageEventStream> {
36    match model.api.as_str() {
37        "anthropic-messages" => {
38            AnthropicProvider::new()
39                .stream(model, context, options)
40                .await
41        }
42        "openai-completions" => OpenAiProvider::new().stream(model, context, options).await,
43        "google-generative-ai" => GoogleProvider::new().stream(model, context, options).await,
44        other => Err(Error::UnsupportedProvider(other.into())),
45    }
46}