1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//! # entelix-memory-openai
//!
//! Concrete [`entelix_memory::Embedder`] implementation backed by
//! OpenAI's `/v1/embeddings` endpoint. Ships the
//! `text-embedding-3-{small,large}` models plus operator-supplied
//! custom model identifiers for forward compatibility.
//!
//! Companion to the trait-only [`entelix_memory`] crate (invariant
//! 13's "trait-only `entelix-memory`" principle): concrete vendor
//! impls live in their own crate so the core memory trait surface
//! ships without pulling `reqwest` + `secrecy` for users who
//! provide their own embedder.
//!
//! ## One-call setup
//!
//! ```ignore
//! use std::sync::Arc;
//! use entelix_core::auth::ApiKeyProvider;
//! use entelix_memory_openai::OpenAiEmbedder;
//!
//! let credentials = Arc::new(ApiKeyProvider::new(
//! "authorization",
//! format!("Bearer {}", std::env::var("OPENAI_API_KEY")?),
//! )?);
//! let embedder = OpenAiEmbedder::small().with_credentials(credentials).build()?;
//! ```
//!
//! ## Invariant alignment
//!
//! - **Invariant 10** — credentials never reach `Tool::execute`. The
//! embedder holds an `Arc<dyn CredentialProvider>` and resolves
//! per-call; no token enters request scope state.
//! - **F10** — `Embedder` is wrapped in `Arc` at the call boundary.
//! Cloning the embedder is cheap (`Arc::clone` of the inner
//! `reqwest::Client` plus a credential handle).
//! - **F4** — `EmbeddingUsage` is populated only on the `Ok` branch
//! of `embed`/`embed_batch`; failed calls produce no phantom
//! token charge in downstream meters.
// `OpenAI` ride through doc strings as the vendor name (not as code
// identifier) frequently — backticking each occurrence noisily.
pub use ;
pub use ;