5aed7b6a3d291f4b1fe0f6f1e328a06a3de11be3
Every frontend spelled the same recipes in its own backend assembly, and rhema-code spelled them three times: deepseek is the generic adapter at DeepSeek's endpoint, zai is the Anthropic adapter at Z.ai's route under bearer auth, each keyed kind takes its own adapter — with the DeepSeek endpoint a string literal in three crates and the zai recipe hand-rolled in each. The construction could not centralize while the model catalog lived on inherent adapter methods: claw's AnyProvider enum existed to box listings a trait object could not reach, and code holding only a provider name had to construct concrete types to list models at all. rhema-provider gains the ModelListing seam, implemented by every adapter, so the catalog is reachable through a trait object. A new rhema-provider-registry owns the wiring: build() takes a rhema-config PROVIDERS spelling plus whatever the caller resolved — a key, the llama.cpp server address, a stored route override, blank reading as unset — and returns the turn provider and the catalog listing. What stays with the frontend is policy: credential resolution, the retry wrapper, the default model. The base constants and the named zai route constructor stay on the adapters they describe. claw's AnyProvider died with its last reason to exist, ACP no longer defaults an unknown catalog kind to google's, and adding a provider is now adapter plus one registry row instead of three frontend edits that had already drifted apart.
Languages
Rust
74.9%
Kotlin
13.8%
Vue
7.1%
TypeScript
3%
Dockerfile
0.5%
Other
0.6%