fix: resolve mapped model ids in model list and per-model views

The SDK now ranks/aggregates providers serving canonical models under
mapped variant ids or aliases (e.g. z-ai-glm-5-3, claude-opus-5-5), but
the daemon still matched exact ids in two places, causing
'Model not found' when the cheapest provider only knew a variant id:

- getModelProviders metadata lookup: use findModelForId; prefer metadata
  from a provider serving the canonical id natively, fall back to the
  cheapest mapped provider. Return the requested canonical id.
- getCachedModels aggregation: group best-priced models by
  canonicalIdForModel so variants fold into one entry.

Verified live: claude-opus-5.5 now merges 13 providers (cypherpunk #1
enabled at ~2562 sats/M), glm-5.3 shows cypherpunk via z-ai-glm-5-3.
This commit is contained in:
redshift
2026-09-24 20:46:47 +05:30
parent ee6fcc479a
commit 1fc85054b4
+34 -7
View File
@@ -1,4 +1,11 @@
import { ModelManager, ProviderManager, type SdkStore } from "@routstr/sdk";
import {
canonicalIdForModel,
findModelForId,
ModelManager,
ProviderManager,
type Model,
type SdkStore,
} from "@routstr/sdk";
import type { ExposedModel } from "./types";
import { logger } from "../utils/logger";
@@ -66,13 +73,16 @@ export function createModelService(
for (const model of models as PricedModel[]) {
if (!model.sats_pricing) continue;
const existing = bestById.get(model.id);
// Group by canonical id so providers serving the same model under a
// mapped variant id or alias fold into one aggregate entry.
const canonicalId = canonicalIdForModel(model as Model);
const existing = bestById.get(canonicalId);
if (
!existing ||
(model.sats_pricing.completion ?? 0) <
(existing.sats_pricing?.completion ?? 0)
) {
bestById.set(model.id, model);
bestById.set(canonicalId, model);
}
}
}
@@ -201,18 +211,35 @@ export function createModelService(
return null;
}
// Get model metadata from first (cheapest) provider
// Get model metadata. Prefer a provider that serves the requested
// canonical id natively (nicest name/description); fall back to the
// cheapest provider matched through the SDK's model mappings, since it
// may only know the model under a mapped variant id or alias.
const cheapest = providers[0]!;
const allModels = modelManager.getAllCachedModels();
const firstProvider = allModels[cheapest.baseUrl];
const modelInfo = firstProvider?.find((m: { id: string }) => m.id === modelId);
let modelInfo: Model | undefined;
for (const p of providers) {
const exact = (allModels[p.baseUrl] as Model[] | undefined)?.find(
(m) => m.id === modelId,
);
if (exact) {
modelInfo = exact;
break;
}
}
if (!modelInfo) {
const firstProvider = allModels[cheapest.baseUrl];
modelInfo = firstProvider
? findModelForId(firstProvider as Model[], modelId)
: undefined;
}
if (!modelInfo) {
return null;
}
return {
id: modelInfo.id,
id: modelId,
name: modelInfo.name,
description: modelInfo.description,
context_length: modelInfo.context_length,