Commit graph

4938 commits

Author SHA1 Message Date
Bryan Helmkamp
3a998196ff
Answer catalog questions with the lithos catalog queries
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>
2026-09-10 09:26:40 -06:00
Bryan Helmkamp
3510d5081d
Implement the lithos CredentialProvider trait directly
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>
2026-09-10 09:16:39 -06:00
Bryan Helmkamp
6eb9ee8cd9
Pin lithos-llm at the Rust boundary revision
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>
2026-09-10 09:09:21 -06:00
Bryan Helmkamp
1bb387a0e5
Merge pull request #847 from fabro-sh/lithos-llm-migration
Replace fabro-llm internals and fabro-model with lithos-llm
2026-09-10 08:09:19 -06:00
Bryan Helmkamp
7ef09968f2
Document the catalog overlay without the metadata.fabro namespace
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>
2026-09-09 23:26:48 -06:00
Bryan Helmkamp
b82b3dd48e
Use the lithos control enum API instead of local spellings
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>
2026-09-09 23:23:49 -06:00
Bryan Helmkamp
2a2fc41807
Read catalog policy from lithos core fields and metadata.agent
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>
2026-09-09 23:20:12 -06:00
Bryan Helmkamp
6dfc96d3fd
Resolve provider secrets through lithos conventional credentials
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>
2026-09-09 23:00:08 -06:00
Bryan Helmkamp
0319b24585
Name fabro as the application on the model client
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>
2026-09-09 22:42:00 -06:00
Bryan Helmkamp
df5c9d2c57
Drop FabroResolver in favor of the lithos resolver
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>
2026-09-09 22:41:47 -06:00
Bryan Helmkamp
7d5f33ab16
Add the gpt6 agent profile kind
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>
2026-09-09 22:37:28 -06:00
Bryan Helmkamp
f2695b96c7
Pin lithos-llm at the catalog convergence revision
lithos-llm 38ccb14 moves the catalog policy Fabro carried under
metadata.fabro into core fields (enabled, stands_in_for, api_key_url,
family, cutoffs, estimated_output_tps, small_default, probe), ships the
openai-codex provider, reads the shared metadata.agent namespace, and
derives conventional secret names for operator-defined providers.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-09 22:11:21 -06:00
Bryan Helmkamp
6c1dc96af6
Stop Debug-formatting credentials in fabro-auth resolve tests
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>
2026-09-09 19:09:22 -06:00
Bryan Helmkamp
5f49cdf9da
Delete fabro-model and document the lithos catalog overlay
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>
2026-09-09 17:26:57 -06:00
Bryan Helmkamp
75e5f34c0d
Expose lithos request and response shapes through the API, server, CLI, and web
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>
2026-09-09 17:26:57 -06:00
Bryan Helmkamp
82bcafcfca
Port fabro-workflow, hooks, validate, and store to the lithos types
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>
2026-09-09 17:26:57 -06:00
Bryan Helmkamp
e557774b0b
Rebuild fabro-llm on lithos-llm and adopt its stream contract in fabro-agent
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>
2026-09-09 17:26:57 -06:00
Bryan Helmkamp
f37151ed46
Adopt lithos vocabulary in fabro-types, fabro-auth, and fabro-config
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>
2026-09-09 17:26:57 -06:00
Bryan Helmkamp
580bb85f5b
Depend on lithos-llm and the published twin-openai crate
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>
2026-09-09 17:26:57 -06:00
fabro-releases[bot]
2f326a13c4 Bump version to 0.348.0-nightly.0
Some checks failed
Rust / Format (push) Has been cancelled
Rust / Clippy (push) Has been cancelled
Rust / Generated Docs (push) Has been cancelled
Rust / Test (Linux) (push) Has been cancelled
Rust / Test (macOS) (push) Has been cancelled
2026-09-06 09:29:10 +00:00
Bryan Helmkamp
5d290a609b
Merge pull request #844 from fabro-sh/remove/expired-secret-migrations
Some checks are pending
Rust / Format (push) Waiting to run
Rust / Clippy (push) Waiting to run
Rust / Generated Docs (push) Waiting to run
Rust / Test (Linux) (push) Waiting to run
Rust / Test (macOS) (push) Waiting to run
Remove expired startup secret migrations
2026-09-05 14:33:28 -04:00
Bryan Helmkamp
b6482910e5
Remove expired startup secret migrations 2026-09-05 14:05:48 -04:00
Bryan Helmkamp
e5e63c9646
Merge pull request #842 from fabro-sh/fix/replay-conclusion-summaries
Rebuild conclusion stage summaries from run events
2026-09-05 12:05:21 -04:00
Bryan Helmkamp
6cf027282f
Update inspect snapshots for projected conclusion stages 2026-09-05 11:53:44 -04:00
Bryan Helmkamp
a7ed03e175
Rebuild conclusion stage summaries from run events 2026-09-05 11:44:23 -04:00
fabro-releases[bot]
efa0d16588 Bump version to 0.347.0-nightly.0 2026-09-05 09:31:42 +00:00
Scott Werner
5b44e25c7c
Merge pull request #841 from fabro-sh/codex/runnable-startup-reconciliation
Some checks failed
Rust / Clippy (push) Waiting to run
Rust / Generated Docs (push) Waiting to run
Rust / Test (Linux) (push) Waiting to run
Rust / Test (macOS) (push) Waiting to run
Rust / Format (push) Waiting to run
TypeScript / Typecheck (push) Has been cancelled
TypeScript / Test (push) Has been cancelled
TypeScript / Build (push) Has been cancelled
Reconcile runnable runs after server restart
2026-09-04 17:07:23 -04:00
Scott Werner
a712aa4dab Reconcile runnable runs after server restart 2026-09-04 14:15:58 -04:00
Scott Werner
ab7cbeb4ae
Merge pull request #839 from fabro-sh/codex/remove-playground
Remove unsupported workflow playground
2026-09-04 11:18:00 -04:00
Scott Werner
8c0702bfac Remove obsolete playground API route assertion 2026-09-04 10:27:18 -04:00
Scott Werner
7e6bbb243d Remove obsolete playground browser route assertion 2026-09-04 10:13:16 -04:00
Scott Werner
209f45b967
Merge pull request #840 from fabro-sh/cli-missing-default-environment-error
Report available environments when default is missing
2026-09-04 10:09:28 -04:00
fabro-releases[bot]
86101748da Bump version to 0.346.0-nightly.0 2026-09-04 09:35:05 +00:00
Scott Werner
a00b95abe0 Report available environments when default is missing
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>
2026-09-03 12:56:47 -04:00
Scott Werner
f52f2a1edb
Merge pull request #838 from fabro-sh/codex/persist-pre-start-worker-failures
Persist pre-start worker failures
2026-09-03 12:48:39 -04:00
Scott Werner
bdb7b29877
Merge pull request #837 from fabro-sh/codex/reject-local-auto-pr-admission
Reject automatic pull requests for Local runs
2026-09-03 12:40:01 -04:00
Scott Werner
f1b569d9e6 Remove unsupported workflow playground 2026-09-03 12:04:35 -04:00
Scott Werner
c437dc012d Simplify pre-start worker failure handling
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>
2026-09-03 11:45:47 -04:00
Scott Werner
c5010c0b33 Simplify the Local pull-request admission check
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>
2026-09-03 11:43:29 -04:00
Scott Werner
a2002175e1
Merge pull request #835 from fabro-sh/codex/projected-run-cleanup
Move run projection replay into the summary store
2026-09-03 11:40:45 -04:00
fabro-releases[bot]
a468125ab3 Bump version to 0.345.0-nightly.0 2026-09-03 09:33:32 +00:00
Scott Werner
54666632c8 Persist pre-start worker failures 2026-09-02 17:29:41 -04:00
Scott Werner
cd20e453ec Use a compatible environment in pull request settings test 2026-09-02 17:24:22 -04:00
Scott Werner
18cb752b61 Reject automatic pull requests for Local runs 2026-09-02 17:15:52 -04:00
Scott Werner
0f1e5e1c9c Centralize run projection replay on ProjectedRun
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>
2026-09-02 16:33:14 -04:00
Scott Werner
efcf8a0d93
Merge pull request #831 from fabro-sh/codex/cli-run-intent-producer
Create CLI runs from immutable workflow intents
2026-09-02 15:45:21 -04:00
Scott Werner
49fb160108 Use async reads during CLI intent preparation 2026-09-02 13:44:33 -04:00
Scott Werner
2360e8046b Move run projection replay into the summary store 2026-09-02 13:32:43 -04:00
Scott Werner
7c23e08868
Merge pull request #833 from fabro-sh/codex/lazy-run-projections
Load inactive run projections on demand
2026-09-02 13:06:04 -04:00
Scott Werner
e3cbc31ca1 Harden CLI run target identity 2026-09-02 12:59:04 -04:00