Introduce an `LlmProvider` trait (the engine<->LLM seam, sibling to the
`Backend` harness<->engine trait) so inference can route to providers
beyond the Bifrost gateway. Two impls behind it:
- `BifrostClient` - existing OpenAI-compatible gateway (default).
- `OpenAiOAuthProvider` - rides the Codex CLI's ChatGPT login
(`~/.codex/auth.json`) and drives `chatgpt.com/backend-api/codex/responses`
(Responses API) with no API key. Self-refreshes the token (single-flight,
write-back, CLI re-read fallback) and translates the engine's OpenAI-chat
request to/from the Responses API + SSE accumulation.
Selected via `[bifrost] provider` ("bifrost" | "openai-oauth"). The engine
keeps speaking the existing ChatCompletionRequest/CompletionResult/
InferenceStrain currency, so all six inference call-sites are unchanged -
only the field type flips to `Arc<dyn LlmProvider>`.
Model ids are translated at the provider boundary (oauth/catalog.rs::resolve):
Bifrost-namespaced ids (`openai/...`, `-precision`) map onto served ChatGPT
models; `-fast` -> priority service tier.
Verified live to the wire level: builds+links, server boots in oauth mode
(reads the Codex token), and chatgpt.com accepts the request (auth, endpoint,
headers, payload all valid). The SSE->CompletionResult accumulation is NOT yet
verified against a successful completion (blocked by a subscription usage limit
at test time) - needs one live turn to confirm end-to-end.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
10 lines
418 B
Rust
10 lines
418 B
Rust
//! Riding the Codex CLI's ChatGPT OAuth login.
|
|
//!
|
|
//! Souveraine does not run its own ChatGPT login flow — it reads the token the
|
|
//! Codex CLI already minted (`~/.codex/auth.json`), refreshes it against
|
|
//! OpenAI's token endpoint when it ages out, and writes the rotated token back
|
|
//! so the two stay in sync. The same "ride the CLI" move OpenClaw makes.
|
|
|
|
pub mod catalog;
|
|
pub mod codex_creds;
|
|
pub mod refresh;
|