feat(routing): native provider priority with automatic fallback#1220
feat(routing): native provider priority with automatic fallback#1220wayfind wants to merge 3 commits intorouter-for-me:mainfrom
Conversation
When multiple providers support the same model, prefer the provider whose name matches the model's prefix. This enables zero-config native-first routing with automatic fallback. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Summary of ChangesHello @wayfind, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request refines the model provider selection mechanism to move beyond simple alphabetical sorting. By introducing a rule that prioritizes providers whose names are prefixes of the model ID, the system now makes more intuitive and effective choices, aligning with common model naming conventions and enhancing the reliability of provider interactions, particularly for fallback strategies. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a useful feature to prioritize native providers when multiple providers are available for a model. The implementation is straightforward and correctly modifies the sorting logic to prefer providers whose names are prefixes of the model ID. I have one suggestion for a minor performance optimization to avoid repeated work inside the sort closure. Overall, this is a solid improvement.
internal/registry/model_registry.go
Outdated
| modelLower := strings.ToLower(modelID) | ||
| iMatch := strings.HasPrefix(modelLower, strings.ToLower(providers[i].name)) | ||
| jMatch := strings.HasPrefix(modelLower, strings.ToLower(providers[j].name)) |
There was a problem hiding this comment.
To improve performance, consider moving the strings.ToLower(modelID) call outside the sort closure, as it's a repeated calculation on a constant value. The closure can be called O(N log N) times.
Similarly, strings.ToLower(providers[i].name) is also repeatedly calculated. This could be optimized by pre-calculating lowercase provider names when building the providers slice.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 551656f922
ℹ️ 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".
internal/registry/model_registry.go
Outdated
| sort.Slice(providers, func(i, j int) bool { | ||
| // Native provider priority: provider name matching model prefix comes first. | ||
| // e.g., "claude-haiku-*" prefers "claude" provider over "antigravity". | ||
| modelLower := strings.ToLower(modelID) | ||
| iMatch := strings.HasPrefix(modelLower, strings.ToLower(providers[i].name)) |
There was a problem hiding this comment.
Ensure native-priority affects actual routing
This new prefix-based sort won’t change which provider actually executes requests because the runtime selection path ignores provider ordering: GetProviderName feeds the list into coreauth.Manager, but normalizeProviders just lowercases/dedupes and pickNextMixed builds a set of providers and lets the selector choose any candidate (sdk/cliproxy/auth/conductor.go:1010-1027, 1563-1571). In scenarios with multiple providers (e.g., both "claude" and an alias provider for a claude-* model), the routing will still pick any available auth, so the intended “native provider first” behavior won’t be honored except in logs. If you want native preference to affect real routing, the ordering needs to be passed into the selector or enforced before candidate selection.
Useful? React with 👍 / 👎.
Pre-calculate lowercase strings outside sort closure to avoid O(N log N) repeated calls: - Move strings.ToLower(modelID) before sort - Store nameLower in providerCount struct Addresses review feedback from Gemini Code Assist. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
Thanks for the review feedback @gemini-code-assist! The performance optimization has been addressed in commit
This avoids O(N log N) repeated string operations during sorting. |
|
Thanks for the update, @wayfind! I appreciate you addressing the performance optimization by pre-calculating |
The previous GetModelProviders sorting was ineffective because pickNextMixed converted the provider list to a set, losing order. Now iterate by provider order when building candidates, ensuring native providers (e.g., "claude" for claude-* models) are selected before alias-mapped providers. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
@chatgpt-codex-connector Great catch! You were absolutely right. Problem identified: Fixed in commit // Before: providers → set (order lost) → iterate m.auths
// After: providers → preserve order → iterate by provider priority
for _, providerKey := range normalizedProviders {
for _, candidate := range m.auths {
if candidate.Provider == providerKey {
candidates = append(candidates, candidate)
}
}
}Now native providers (e.g., "claude" for 👍 for the thorough analysis! |
|
To use Codex here, create an environment for this repo. |
|
No plan to support this. |
Problem
When multiple providers support the same model (e.g., native
claudeand alias-mappedantigravityboth provideclaude-haiku-4-5), the system had no preference mechanism. Users expected native providers to be used first, with automatic fallback to alternatives when quota is exceeded.Solution
Two coordinated changes that work together:
1. Registry: Native provider priority sorting
File:
internal/registry/model_registry.goGetModelProviders()now returns providers sorted by native affinity:2. Conductor: Preserve provider order in selection
File:
sdk/cliproxy/auth/conductor.gopickNextMixed()now iterates by provider order instead of converting to an unordered set:Why Both Changes Are Needed
pickNextMixedset conversionBehavior
Example
Request for
claude-3-5-haiku-20241022:claudeprovider firstantigravity