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
//! LLM client and JSON extraction.
//!
//! Split by concern rather than by phase:
//!
//! - [`json_parsing`] turns whatever the model returned into a `serde_json::Value`.
//! Tolerant of fences, prose, trailing commas and truncated output, in that
//! order, first success wins.
//! - [`client`] wraps `open-agent-sdk`. The request itself - streaming,
//! transport retry, and parse retry.
//! - [`cache`] is the on-disk response cache. Content-addressed keys (not
//! git-aware), infallible reads, oldest-first eviction.
//! - [`concurrency`] is the bounded in-flight limiter. Deliberately just a
//! `Semaphore`; the rate-limit machinery the Python carried is gone (see
//! the module doc for the four reasons).
//! - [`models`] asks an endpoint which models it serves, for `drep init`.
//! - [`quirks`] answers what one *model* accepts - `temperature` and its
//! output ceiling - which no endpoint's listing carries.
//! - [`chain`] is the ordered list of providers with failover. It owns the
//! loop, so the cache key is recomputed per provider and the answer is
//! filed under the key of whoever gave it.
//!
//! `chain::ProviderChain::complete_json` is the boundary the analyzer calls;
//! `client::LlmClient::complete_json` is the single-provider request beneath
//! it. It
//! returns the `Extracted` from `json_parsing`, never the raw text, so a
//! truncated response stays a type the caller can pattern-match on rather
//! than a log line to grep for.