registry: high-level ModelRouter (workload-tier routing layer)#54
Conversation
Add `registry::router` — the declarative workload-tier layer over the named
model registry, and the crate-owned home for the projection hosts have
re-implemented by hand (OpenHuman's RouterProvider + routes.rs): map named tiers
(chat-v1, reasoning-v1, vision-v1, ...) onto concrete registered models with
per-tier capability gates and ordered same-family fallback chains.
- `WorkloadRoute` — one tier: alias -> model, optional CapabilitySet gate,
ordered sibling fallback aliases. Pure metadata (names a model, owns none).
- `ModelRouter` — insertion-ordered route table + optional default. Answers the
three questions turn assembly needs: target_model(alias), fallback_policy(alias)
([alias, fallbacks...] leading with the primary so FallbackPolicy::next_after
yields the alternate), required_capabilities(alias). Infallible last-write-wins
builder (with_route/with_default) + duplicate-rejecting register().
Holds no models and drives no I/O — cheap cloneable policy read while wiring a
registry + RunPolicy, so *what routes where* stays decoupled from *how a model is
built*. Fills the long-declared ComponentKind::Router. Foundation for issue #4249
Phase 3 (RouterProvider -> crate ModelRegistry route-projection).
Exported from registry::{ModelRouter, WorkloadRoute} + crate root. Module README
under src/registry/router/. 9 unit tests + 1 doctest; fmt + clippy clean.
Claude-Session: https://claude.ai/code/session_01U8NDGbt9tKj443VquzycLB
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 32 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9d6026f714
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let mut chain = Vec::with_capacity(route.fallbacks.len() + 1); | ||
| chain.push(route.alias.clone()); | ||
| chain.extend(route.fallbacks.iter().cloned()); |
There was a problem hiding this comment.
Build fallback chains from target model names
When a route maps an alias to a different model (for example WorkloadRoute::new("chat-v1", "gpt-4.1-mini")), callers following this API use target_model("chat-v1") for the request model, so the agent loop's fallback cursor is the resolved target model name. This policy starts with route.alias and copies fallback aliases, so FallbackPolicy::next_after(&cursor) will not find the current model and no fallback is selected. Resolve the primary and fallback aliases to their route.model values, or keep dispatch consistently on aliases, before constructing the policy.
Useful? React with 👍 / 👎.
What
Adds
registry::router— a high-levelModelRouter: the declarativeworkload-tier layer over the named model registry, filling the long-declared
ComponentKind::Router.Where
CapabilityRegistryresolves a model by name and the agent loop failsover across a
FallbackPolicy, neither owns the policy that maps a host'sworkload tiers (
chat-v1,reasoning-v1,vision-v1, …) onto concretemodels, plus the per-tier capability gates and same-family fallback ordering.
Hosts have re-implemented that projection by hand (OpenHuman's
RouterProviderroutes.rs).ModelRouteris the crate-owned home for it.Surface
WorkloadRoute— one tier:alias → model, optionalCapabilitySetgate, ordered sibling fallback aliases. Pure metadata (names a model, owns
none); serde-friendly (skips empty
requires/fallbacks).ModelRouter— insertion-ordered route table + optional default alias.Answers the three questions turn assembly needs:
target_model(alias)→ registered model namefallback_policy(alias)→[alias, fallbacks…](leads with the primary soFallbackPolicy::next_afteryields the alternate;Nonewhen no alternates)required_capabilities(alias)→ gate to stamp on requests (None= ungated)with_route/with_default, plusduplicate-rejecting
register.Holds no models, drives no I/O — cheap cloneable policy read while wiring a
registry +
RunPolicy, keeping what routes where decoupled from how a modelis built.
Why
Foundation for issue #4249 Phase 3 (RouterProvider → crate
ModelRegistryroute-projection): a host declares its tier table once and hands it over, instead
of open-coding alias resolution + fallback ordering + capability gating at the
turn-assembly boundary.
Tests / checks
cargo fmt --check,cargo clippy --lib -- -D warnings, 9 unit tests + 1doctest, full
registry::suite (30) green. No behavior change to existingsurfaces — purely additive.
https://claude.ai/code/session_01U8NDGbt9tKj443VquzycLB