oxmux: Add model registry listing#44
Conversation
Greptile SummaryThis PR adds a headless
Confidence Score: 4/5Safe to merge with low risk; the registry is headless and does not touch existing routing or proxy paths. The core logic is well-structured and thoroughly tested. One completeness gap exists in listing_state_for: when the availability snapshot reports Degraded, static provider.degraded_reasons and account.degraded_reasons are not merged into the resulting ModelListingState::Degraded.reasons, potentially hiding relevant context from listing consumers. The existing test sets up exactly this combination but only checks the variant, not the reasons list. The listing_state_for function in crates/oxmux/src/model_registry.rs and the corresponding test in crates/oxmux/tests/model_registry.rs for the availability-degraded + static-degraded combination.
|
| Filename | Overview |
|---|---|
| crates/oxmux/src/model_registry.rs | New headless model registry module; core logic is sound. One completeness gap: static provider/account degraded reasons are not merged into the Degraded listing state when the availability snapshot is also Degraded. |
| crates/oxmux/src/oxmux.rs | Adds model_registry module declaration and re-exports all new public types; straightforward facade update. |
| crates/oxmux/tests/model_registry.rs | Comprehensive integration tests for registry construction, filters, aliases, forks, and availability metadata; one test exercises combined static+dynamic degraded reasons but does not assert the merged reasons list. |
| crates/oxmux/tests/dependency_boundary.rs | Adds a source-text scan confirming model_registry.rs carries no app-shell or runtime imports; straightforward boundary guard. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
RP[RoutingPolicy\nroutes + aliases]
VFC[ValidatedFileConfiguration\nrouting_default_groups]
PS[ProviderSummary\ncapabilities + accounts]
RAS[RoutingAvailabilitySnapshot\noptional]
RP --> FP[from_policy_with_availability]
VFC --> FF[from_file_configuration_with_availability]
PS --> FP
PS --> FF
RAS -->|optional| FP
RAS -->|optional| FF
FP --> MR[ModelRegistry\nentries: Vec]
FF --> MR
MR --> AE[all_entries]
MR --> VE[visible_entries\nAvailable or Degraded]
MR --> DE[disabled_entries\nDisabled / RoutingIneligible / UnknownProvider / UnknownAccount]
MR --> GE[degraded_entries\nDegraded]
MR --> OAI[open_ai_model_list\nOpenAiModelListProjection]
MR --> MRE[ModelRegistryEntry\nidentity + alias + fork + candidates]
MRE --> MRC[ModelRegistryCandidate\nnative_target + applicability + capabilities + listing_state]
MRC --> LS{listing_state_for}
LS -->|provider missing| UP[UnknownProvider]
LS -->|account missing| UA[UnknownAccount]
LS -->|routing_eligible=false| RI[RoutingIneligible]
LS -->|availability Unavailable/Exhausted| DIS[Disabled]
LS -->|availability Degraded| DG[Degraded]
LS -->|static reasons empty| AV[Available]
LS -->|static reasons present| DG
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
crates/oxmux/src/model_registry.rs:660-665
**Static degraded reasons silently dropped when availability is `Degraded`**
When the availability snapshot reports `RoutingAvailabilityState::Degraded`, `listing_state_for` creates a `ModelListingState::Degraded` with only the availability-derived reason, discarding any static `provider.degraded_reasons` or `account.degraded_reasons` that were set on the provider summary. By contrast, when the snapshot reports `Available`, the code correctly calls `degraded_or_available`, which merges both static layers.
This means a provider that has both a static quota-pressure warning (in `provider.degraded_reasons`) and a live-degraded signal from the snapshot will expose only the live reason. The test in `availability_metadata_marks_disabled_and_degraded_without_selecting_route` exercises this exact combination (`account.with_degraded("account", "reduced quota")` + `Degraded { "limited capacity" }`), but only asserts the variant, not the reasons list, so the gap is not caught.
Reviews (2): Last reviewed commit: "oxmux: Fix model registry account applic..." | Re-trigger Greptile
🔗 Linked Issue
Closes #26
✅ Type of Change
📝 Summary
oxmuxmodel registry API for typed model identities, aliases, forks, provider/account applicability, capabilities, and disabled/degraded/unknown listing states.📐 OpenSpec Evidence
openspec/changes/add-oxmux-model-registry-listingoxmuxas the shared headless owner for model registry/listing semantics while keepingoxidemux, GPUI, provider SDKs, OAuth, credential storage, live provider discovery, and outbound network behavior out of scope.📖 Documentation Checklist
README.md,CONTRIBUTING.md, or OpenSpec docs when needed.CHANGELOG.mdfor notable user-facing, compatibility, security, or workflow changes, or explained why it was not applicable.✔️ Contributor Checklist
.env.examplefile if environment variables are needed and ensured no secrets are committed.oxmuxshared-core andoxidemuxplatform-shell boundary, or documented the OpenSpec-approved reason for changing it.mise run cilocally, or explained why it was not applicable.mise run securitylocally for dependency policy and vulnerability changes, or explained why it was not applicable.mise run hk-check, or explained why they were not applicable.mise run cicovered formatting, checking, clippy, tests, and docs for this code-only change.💬 Additional Comments
Verification run locally:
openspec validate add-oxmux-model-registry-listing --strictcargo fmt --all --checkcargo test -p oxmuxmise run ciRelease Notes:
Need help on this PR? Tag
@codesmithwith what you need.