Skip to content

Commit 80ce1af

Browse files
committed
fix: provider alias mapping for pricing and always show provider icon
- Add shared provider-aliases utility (gemini↔google, qwen↔alibaba) used by both available-models endpoint and tier auto-assignment - Provider icon on tier cards now always shows by falling back to PROVIDERS model list when pricing API data is unavailable
1 parent dc15305 commit 80ce1af

File tree

4 files changed

+45
-12
lines changed

4 files changed

+45
-12
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* Maps between frontend provider IDs and pricing-DB provider names.
3+
* E.g. the user connects "gemini" but pricing rows use "Google".
4+
*/
5+
const ALIASES: Record<string, string[]> = {
6+
gemini: ['google'],
7+
google: ['gemini'],
8+
qwen: ['alibaba'],
9+
alibaba: ['qwen'],
10+
moonshot: ['moonshot'],
11+
};
12+
13+
/** Expand a set of provider names to include known aliases. */
14+
export function expandProviderNames(names: Iterable<string>): Set<string> {
15+
const expanded = new Set<string>();
16+
for (const name of names) {
17+
const lower = name.toLowerCase();
18+
expanded.add(lower);
19+
for (const alias of ALIASES[lower] ?? []) {
20+
expanded.add(alias);
21+
}
22+
}
23+
return expanded;
24+
}

packages/backend/src/routing/routing.controller.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { CurrentUser } from '../auth/current-user.decorator';
1111
import { AuthUser } from '../auth/auth.instance';
1212
import { RoutingService } from './routing.service';
1313
import { ModelPricingCacheService } from '../model-prices/model-pricing-cache.service';
14+
import { expandProviderNames } from './provider-aliases';
1415

1516
@Controller('api/v1/routing')
1617
export class RoutingController {
@@ -97,10 +98,8 @@ export class RoutingController {
9798
@Get('available-models')
9899
async getAvailableModels(@CurrentUser() user: AuthUser) {
99100
const providers = await this.routingService.getProviders(user.id);
100-
const activeProviders = new Set(
101-
providers
102-
.filter((p) => p.is_active)
103-
.map((p) => p.provider.toLowerCase()),
101+
const activeProviders = expandProviderNames(
102+
providers.filter((p) => p.is_active).map((p) => p.provider),
104103
);
105104

106105
const models = this.pricingCache.getAll();

packages/backend/src/routing/tier-auto-assign.service.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { UserProvider } from '../entities/user-provider.entity';
66
import { TierAssignment } from '../entities/tier-assignment.entity';
77
import { ModelPricing } from '../entities/model-pricing.entity';
88
import { randomUUID } from 'crypto';
9+
import { expandProviderNames } from './provider-aliases';
910

1011
const TIERS = ['simple', 'standard', 'complex', 'reasoning'] as const;
1112
type Tier = (typeof TIERS)[number];
@@ -31,11 +32,13 @@ export class TierAutoAssignService {
3132
const providers = await this.providerRepo.find({
3233
where: { user_id: userId, is_active: true },
3334
});
34-
const activeProviderNames = providers.map((p) => p.provider);
35+
const activeProviders = expandProviderNames(
36+
providers.map((p) => p.provider),
37+
);
3538

3639
const allModels = this.pricingCache.getAll();
3740
const available = allModels.filter((m) =>
38-
activeProviderNames.includes(m.provider.toLowerCase()),
41+
activeProviders.has(m.provider.toLowerCase()),
3942
);
4043

4144
for (const tier of TIERS) {

packages/frontend/src/pages/Routing.tsx

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,19 @@ function resolveProviderId(dbProvider: string): string | undefined {
3939
return PROVIDERS.find((p) => p.id === key || p.id === alias || p.name.toLowerCase() === key)?.id;
4040
}
4141

42-
/** Find the provider id (lowercase) for a model_name from available models */
43-
function providerIdForModel(model: string, models: AvailableModel[]): string | undefined {
44-
const m = models.find((x) => x.model_name === model)
45-
?? models.find((x) => x.model_name.startsWith(model + "-"));
46-
if (!m) return undefined;
47-
return resolveProviderId(m.provider);
42+
/** Find the provider id for a model — checks pricing API first, then PROVIDERS list */
43+
function providerIdForModel(model: string, apiModels: AvailableModel[]): string | undefined {
44+
// Try pricing API data
45+
const m = apiModels.find((x) => x.model_name === model)
46+
?? apiModels.find((x) => x.model_name.startsWith(model + "-"));
47+
if (m) return resolveProviderId(m.provider);
48+
// Fallback: search PROVIDERS model lists by value
49+
for (const prov of PROVIDERS) {
50+
if (prov.models.some((pm) => pm.value === model || model.startsWith(pm.value + "-") || pm.value.startsWith(model + "-"))) {
51+
return prov.id;
52+
}
53+
}
54+
return undefined;
4855
}
4956

5057
const Routing: Component = () => {

0 commit comments

Comments
 (0)