fabro-llm's catalog module held some 250 lines of listing and picking
helpers over lithos data: enabled and listed providers, model lookup by
id, alias, or wire id, matches ranked as the resolver ranks, default and
probe models, the small utility model across ready providers, the nearest
model on another provider, and cost by handle. lithos-llm now answers all
of those on `Catalog` and `CatalogProvider` through `Offering`, so the
helpers and the `ModelEntry` wrapper go.
What stays in Fabro's catalog module is its own: building the catalog from
the operator overlay, and reading the agent harness and
`reasoning_by_default` from the shared `metadata.agent` namespace. The
passthrough selection policy in `selection.rs` keeps its rules and calls
lithos for the lookups.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
fabro-auth defined its own `CredentialSource` trait beside the lithos
`CredentialProvider`, with a parallel `ResolveError` and an adapter between
them, because lithos had no way to ask which providers a store can serve
right now. It does now: `credentials::readiness`, `ClientBuilder::build_ready`,
and `CredentialError::Unusable`.
- The vault, SQL vault, API-key, and extra-headers stores implement
`CredentialProvider` directly. Material that is present but unusable (an
expired token with no refresh, a wrong-typed vault entry, a header secret
that did not resolve, a store read failure) is `CredentialError::Unusable`
with the operator-facing reason; its `Display` replaces
`auth_issue_message`. `is_configured` is the cheap presence check.
- `fabro_llm::build_client` calls `build_ready`; `FabroClient::auth_issues`
carries `CredentialError`. `fabro_llm::configured_providers` replaces the
per-store `configured_providers` method.
- `CredentialSource`, `ResolvedCredentials`, `lithos_credentials`,
`ResolveError`, and `auth_issue_message` are deleted. Twenty files that
held `Arc<dyn CredentialSource>` hold `Arc<dyn CredentialProvider>`.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
lithos-llm ba2f418 adds provider readiness, catalog queries, error policy
predicates, one-call structured output, local-file inlining, the reasoning
normalizer, the nearest supported effort, and built-in provider ids. Every
addition is additive, so this pin changes nothing yet; the commits that
follow adopt each one and delete Fabro's copy.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The `[llm]` reference now describes `enabled`, `api_key_url`,
`stands_in_for`, `small_default`, `probe`, `family`, and the cutoffs as
lithos fields, the coding harness under `metadata.agent`, and the secret
names lithos derives for operator-defined providers. Secret-bearing
headers go in `default_headers` as `{{ secrets.NAME }}` tokens. The
integration guides enable a provider with `enabled = true` on its table.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
lithos-llm now exposes `ReasoningEffort::ALL`, `Speed::ALL`, `as_str`,
`Display`, and `FromStr` on its request-control enums. Fabro's
`controls` module kept parallel name tables and parsers for them; only
the nearest-supported-effort rule is Fabro's own, so that is what stays.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Fabro's policy layer restated the lithos built-ins under `metadata.fabro`:
enabled flags, credentials, display facts, probe and small-default roles,
and agent profiles. lithos-llm now carries every one of those as a core
field or under the shared `metadata.agent` namespace, so the layer and its
typed view go:
- Delete `fabro-policy.toml` and `FABRO_POLICY_TOML`. The catalog is the
lithos built-ins plus the operator's `[llm]` overlay, nothing between.
- Delete `fabro_types::catalog_policy`. `enabled`, `stands_in_for`,
`api_key_url`, `family`, the cutoffs, `estimated_output_tps`,
`small_default`, and `probe` are read from lithos accessors; the agent
profile and `reasoning_by_default` come from `metadata.agent`, which
Pebble reads too.
- `catalog::provider`, `enabled_providers`, and `listed_providers` return
the lithos `CatalogProvider` directly; `ModelEntry` loses its policy
field and gains `agent_profile()`.
- Test fixtures move `[providers.x.metadata.fabro] enabled = true` onto
the provider table, drop `credentials` lists in favor of the secret name
lithos derives from the provider id, and spell `agent_profile` as
`metadata.agent.profile`.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
lithos-llm now owns which named secrets each provider reads and how they
shape into its auth scheme, including a derived `<PROVIDER>_API_KEY` for
operator-defined providers. Fabro's job shrinks to supplying the store:
`VaultCredentialSource` hands lithos a lookup that reads the process
environment, then the vault, under the same conventional names.
What Fabro still adds on top: the Codex OAuth credential in the vault,
refreshed and persisted when it expires; `{{ secrets.NAME }}` tokens in a
provider's `default_headers`, resolved against the vault and re-sent as
credential headers; and OpenAI organization and project headers from the
environment.
Deleted with the `metadata.fabro.credentials` list: `CredentialRef`,
`CredentialResolver`, `EnvCredentialSource` (now
`VaultCredentialSource::environment_only`), and the `env_var_names` /
`expected_vault_secret_name` helpers, replaced by `secret_names` and
`expected_secret_name` over the lithos table. `openai-codex` joins the
first-party provider id constants.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
lithos-llm sends the application name as the codex `originator` header,
so the OpenAI Codex deployment can tell which harness a request came from.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
lithos-llm now owns `enabled` and `stands_in_for` as core provider
fields, and its `CatalogResolver` refuses disabled providers and reroutes
a request to the provider standing in for an unavailable one. Fabro's
resolver re-implemented both from `metadata.fabro`, so it goes.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
lithos ships `metadata.agent.profile = "gpt6"` on the GPT-6 Astra row.
Fabro runs it on the GPT-5.6 harness: the same Codex core tool set,
memory filenames, question tool, and command timeout. The shared
`uses_codex_core_tools` predicate replaces the `== Gpt56` checks so the
two kinds cannot drift apart.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Three test panics printed the resolved `Credentials` value with `{:?}`.
The lithos credential types redact secrets in their Debug output, but
CodeQL's cleartext-logging rule cannot see that and flagged each site.
The variant name is enough to diagnose a failing test, so drop the value.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
fabro-model's ids and billing rollup now live in fabro-types, and its
pricing, catalog, provider TOMLs, and legacy index are replaced by the
lithos built-in catalog plus the Fabro policy layer.
Regenerate the configuration reference for the `[llm]` overlay and
`metadata.fabro`, and rewrite the SDK, models, and integration docs for
the lithos provider and model shapes.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The OpenAPI spec adopts the lithos request, response, content part,
tool, usage, and cost schemas. The completions endpoint returns the
lithos `Response` JSON verbatim and SSE carries lithos `StreamEvent`s
verbatim. The models and providers endpoints serve the fabro-types
catalog views, and the install and model-test flows probe providers
through fabro-llm.
The CLI builds its catalog from the operator overlay, drives `fabro exec`
through the server gateway adapter, and parses reasoning effort with the
shared controls. The web app reads content parts as lithos-tagged
objects. The TypeScript client is regenerated.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Workflow LLM handlers build lithos requests, bill from lithos usage and
cost, and classify failures from lithos `ErrorKind`. Model resolution and
fallback use the fabro-llm selection and catalog helpers. Validation
rules read the lithos catalog, and store fixtures use the new
`BilledModelUsage` shape.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
fabro-llm is now a thin integration crate: catalog construction from the
lithos built-ins, the Fabro policy layer, and operator overlays; client
construction from catalog plus credentials; a Fabro `ModelResolver` that
enforces `metadata.fabro` policy; model selection; a server gateway
adapter; attachment inlining middleware; reasoning normalization;
one-shot structured output; probe wiring; and catalog API views. The
in-house codecs, transports, providers, tool loop, retry, cost, and
token-count code are deleted along with the wire snapshots that covered
them.
fabro-agent consumes lithos `StreamEvent`s and `Response`s directly.
Retry is split: lithos's retry middleware handles failures before any
visible output, and the agent replays the turn after.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
fabro-types re-exports the lithos request, response, content, tool, and
stream types and absorbs the identifiers, billing rollup, provider ids,
controls, catalog API views, and Fabro catalog policy (`metadata.fabro`)
that lived in fabro-model. Stored and wire formats use the lithos serde
shapes directly with no compatibility shims.
fabro-auth becomes a lithos `CredentialProvider`: `CredentialSource`
resolves credentials per catalog provider, with env, vault, SQL vault,
extra-headers, and API-key sources.
fabro-config's `[llm]` settings become an opaque TOML overlay layer
(`LlmLayer`) that is applied on top of the lithos built-ins and the Fabro
policy layer.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Add lithos-llm as a pinned git dependency and replace the in-repo
`test/twin/openai` crate with the published `twins` revision that
lithos-llm verifies its codecs against. Move the Fabro policy overlay
(`fabro-policy.toml`) into fabro-llm so Fabro owns its own catalog
policy layer.
Drop the twin-openai nextest overrides and CI package filter now that the
crate is no longer a workspace member.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
When `fabro run` or `fabro create` omits `--environment` and the server
has no environment named `default`, the CLI previously failed with only
"could not retrieve environment `default`". It now lists the server's
environment catalog in the error so the user can pass an explicit
`--environment <id>` or create the missing `default` entry. Explicit
`--environment` lookups keep their existing not-found message.
Adds `Client::list_environments` to fabro-client for the catalog read.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Move the "which failures can happen before Starting" classification onto
FailureReason as an exhaustive predicate and use it for every
Runnable -> Failed transition, replacing the hand-maintained allowlist.
Give the pending-cancel precedence rule a single owner shared by the
worker launch and worker exit paths.
Test cleanups: share the Notify wait loop, server record fixture, and
post-failure assertions; simplify the pre-start test runtime's hold
flag; and parameterize the slate run.failed payload helper.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Use the shared clone-based provider predicate and rely on the settings
resolver dropping disabled pull-request settings instead of re-checking
the enabled flag. List the new intent-lane error code in the OpenAPI
description, trim the acceptance tests to what they actually prove, and
fold the docs note into the existing requirements sentence.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Move ProjectedRun next to EventProjectionCache in run_state, since the
summary store both produces and consumes it, and give it a replay
constructor that owns the events-to-head derivation. load_projection now
returns RunNotFound directly instead of erasing it to None and having
callers rebuild it; load_run_projection is the single Option translation
point. install_in_memory_state reuses the existing From impl, and the
commit path passes its Arc through instead of unwrapping and
reallocating it.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>