Skip to main content

llmleaf_client/
lib.rs

1//! # llmleaf-client
2//!
3//! Official async Rust SDK for the [llmleaf](https://github.com/codefionn/llmleaf) LLM
4//! proxy. It speaks llmleaf's OpenAI/OpenRouter-shaped JSON over HTTP — the wire is JSON,
5//! never protobuf-binary — and covers every endpoint in `clients/SPEC.md`:
6//!
7//! * chat completions, non-streaming ([`Client::chat`]) and streaming
8//!   ([`Client::chat_stream`], an `impl Stream` of [`ChatCompletionChunk`]s that stops on
9//!   the `[DONE]` sentinel);
10//! * the OpenAI Responses dialect, non-streaming ([`Client::responses`]) and streaming
11//!   ([`Client::responses_stream`], an `impl Stream` of [`ResponsesStreamEvent`]s that ends
12//!   on the terminal `response.completed`/`incomplete`/`failed` event — there is no
13//!   `[DONE]` sentinel);
14//! * embeddings ([`Client::embeddings`], with base64 → float decoding);
15//! * rerank ([`Client::rerank`], scoring documents against a query);
16//! * model catalog ([`Client::list_models`]);
17//! * text-to-speech ([`Client::speech`] → `(bytes, content_type)`) and the voice catalog
18//!   ([`Client::voices`]);
19//! * speech-to-text ([`Client::transcribe`], multipart with the `file` part);
20//! * batches ([`Client::create_batch`], [`Client::get_batch`], [`Client::cancel_batch`],
21//!   [`Client::batch_results`] → an NDJSON stream of [`BatchResultLine`]s).
22//!
23//! ## Codegen
24//!
25//! `build.rs` compiles `proto/llmleaf/v1/llmleaf.proto` with `prost-build` (real codegen,
26//! run every build); the generated messages are exposed under [`pb`]. The public types
27//! (re-exported at the crate root, e.g. [`ChatRequest`]) are hand-written serde structs
28//! that produce the exact OpenAI JSON wire — prost compiles the proto while serde drives
29//! the wire.
30//!
31//! ## Quickstart
32//!
33//! ```no_run
34//! use llmleaf_client::{Client, ChatRequest, ChatMessage};
35//!
36//! # async fn run() -> Result<(), llmleaf_client::Error> {
37//! let client = Client::new("https://gateway.example.com", "sk-...")?;
38//! let resp = client
39//!     .chat(ChatRequest::new(
40//!         "gpt-4o-mini",
41//!         vec![ChatMessage::user("hi")],
42//!     ))
43//!     .await?;
44//! println!("{}", resp.first_text().unwrap_or_default());
45//! # Ok(())
46//! # }
47//! ```
48
49// Public types mirror `proto/llmleaf/v1/llmleaf.proto` field-for-field; the proto and
50// `clients/SPEC.md` are the authoritative documentation for individual fields, so we warn
51// on undocumented top-level items but not on every mirrored struct field.
52#![warn(missing_docs)]
53#![allow(clippy::doc_markdown)]
54
55pub mod pb;
56
57mod client;
58mod error;
59mod stream;
60mod wire;
61
62// The wire-mirror structs document themselves at the type level; their fields map
63// one-to-one onto the proto/SPEC keys, so we don't repeat that prose per field.
64#[allow(missing_docs)]
65mod types;
66
67pub use client::{Client, ClientBuilder};
68pub use error::{Error, Result};
69pub use types::*;