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//! * embeddings ([`Client::embeddings`], with base64 → float decoding);
11//! * model catalog ([`Client::list_models`]);
12//! * text-to-speech ([`Client::speech`] → `(bytes, content_type)`) and the voice catalog
13//! ([`Client::voices`]);
14//! * speech-to-text ([`Client::transcribe`], multipart with the `file` part);
15//! * batches ([`Client::create_batch`], [`Client::get_batch`], [`Client::cancel_batch`],
16//! [`Client::batch_results`] → an NDJSON stream of [`BatchResultLine`]s).
17//!
18//! ## Codegen
19//!
20//! `build.rs` compiles `proto/llmleaf/v1/llmleaf.proto` with `prost-build` (real codegen,
21//! run every build); the generated messages are exposed under [`pb`]. The public types
22//! (re-exported at the crate root, e.g. [`ChatRequest`]) are hand-written serde structs
23//! that produce the exact OpenAI JSON wire — prost compiles the proto while serde drives
24//! the wire.
25//!
26//! ## Quickstart
27//!
28//! ```no_run
29//! use llmleaf_client::{Client, ChatRequest, ChatMessage};
30//!
31//! # async fn run() -> Result<(), llmleaf_client::Error> {
32//! let client = Client::new("https://gateway.example.com", "sk-...")?;
33//! let resp = client
34//! .chat(ChatRequest::new(
35//! "gpt-4o-mini",
36//! vec![ChatMessage::user("hi")],
37//! ))
38//! .await?;
39//! println!("{}", resp.first_text().unwrap_or_default());
40//! # Ok(())
41//! # }
42//! ```
43
44// Public types mirror `proto/llmleaf/v1/llmleaf.proto` field-for-field; the proto and
45// `clients/SPEC.md` are the authoritative documentation for individual fields, so we warn
46// on undocumented top-level items but not on every mirrored struct field.
47#![warn(missing_docs)]
48#![allow(clippy::doc_markdown)]
49
50pub mod pb;
51
52mod client;
53mod error;
54mod stream;
55mod wire;
56
57// The wire-mirror structs document themselves at the type level; their fields map
58// one-to-one onto the proto/SPEC keys, so we don't repeat that prose per field.
59#[allow(missing_docs)]
60mod types;
61
62pub use client::{Client, ClientBuilder};
63pub use error::{Error, Result};
64pub use types::*;