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
55
56
57
58
59
60
61
62
63
64
65
66
// SPDX-License-Identifier: Apache-2.0
//! Production [`LlmClient`](solo_core::LlmClient) backends.
//!
//! Solo's stub LLM lives in `solo_steward::test_support` (deterministic,
//! no-network). This module is the production side: real backends that
//! talk to hosted or local models via HTTP / FFI / candle.
//!
//! v0.2.0 shipped **Anthropic Claude** ([`AnthropicClient`]). v0.3
//! adds **OpenAI Chat Completions** ([`OpenAIClient`]) as a sibling
//! — same `LlmClient` trait, different wire format. Future backends:
//!
//! - **candle-Qwen3-Coder local** — offline default per ADR-0002.
//! ~30 GB weights, GPU detection, download flow. Likely lands as
//! a sibling crate (`solo-llm-candle`?) given the ramp.
//!
//! All backends implement `solo_core::LlmClient` so the
//! `solo_steward::Steward` interactions stay backend-agnostic.
//!
//! ## Selection precedence
//!
//! When more than one backend's env var is set, the CLI's startup
//! glue ([`crate::llm`] consumers in `solo-cli`) prefers
//! Anthropic over OpenAI. Setting `OPENAI_API_KEY` only takes
//! effect when `ANTHROPIC_API_KEY` is unset/empty. This keeps the
//! v0.2 default behavior stable for users who already had
//! Anthropic configured before upgrading.
pub use ;
pub use ;
pub use ;
pub use RetryConfig;
use Arc;
use ;
/// Build an [`LlmClient`] from environment variables, applying the
/// precedence documented at the module level: **Anthropic first**,
/// then **OpenAI**, then `None`.
///
/// Returns:
///
/// - `Ok(Some(client))` if either provider's env var is set.
/// - `Ok(None)` if neither is set/non-empty (caller proceeds
/// without a Steward — clustering-only consolidation).
/// - `Err(_)` if an env var is set but the HTTP client can't be
/// built (rare — TLS init failure).
///
/// Single source of truth — both `solo daemon` (consolidate timer)
/// and one-shot CLI flows use this helper, so the selection rule
/// stays identical across surfaces.