mirror of
https://github.com/Routstr/routstrd.git
synced 2026-07-30 15:46:14 +00:00
fix: sort model providers by per-token rate and show [Disabled] annotation
getModelProviders was manually iterating getAllCachedModels() and sorting
by max_cost (a per-request ceiling), which didn't match the SDK's actual
routing order (prompt+completion per million tokens). Switch to
providerManager.getProviderPriceRankingForModel({ includeDisabled: true })
so the display order matches real routing. Cross-reference the store's
disabledProviders list to set a per-provider 'disabled' flag, and print
'[Disabled]' next to the URL in the CLI.
This commit is contained in:
@@ -32,5 +32,8 @@ temp/
|
||||
.worktrees/
|
||||
.routstrd/
|
||||
|
||||
# Graphify output
|
||||
graphify-out/
|
||||
|
||||
# Standalone prototype scripts
|
||||
index.ts
|
||||
|
||||
+4
-1
@@ -751,6 +751,7 @@ program
|
||||
context_length?: number;
|
||||
providers: Array<{
|
||||
baseUrl: string;
|
||||
disabled?: boolean;
|
||||
pricing: {
|
||||
prompt: number;
|
||||
completion: number;
|
||||
@@ -777,7 +778,9 @@ program
|
||||
}
|
||||
console.log(`\n Providers (${modelData.providers.length}):`);
|
||||
for (const provider of modelData.providers) {
|
||||
console.log(`\n ${provider.baseUrl}`);
|
||||
console.log(
|
||||
`\n ${provider.baseUrl}${provider.disabled ? " [Disabled]" : ""}`,
|
||||
);
|
||||
console.log(
|
||||
` Prompt: ${(provider.pricing.prompt * 1000000).toFixed(2)} sats/M tokens`,
|
||||
);
|
||||
|
||||
+1
-1
@@ -113,7 +113,7 @@ async function main(): Promise<void> {
|
||||
// Create shared ProviderManager for consistent failure tracking across all requests
|
||||
const providerManager = new ProviderManager(discoveryAdapter, store, daemonSdkLogger);
|
||||
const { ensureProvidersBootstrapped, getRoutstr21Models, getModelProviders, refreshProvidersAndModels } =
|
||||
createModelService(modelManager, store);
|
||||
createModelService(modelManager, providerManager, store);
|
||||
|
||||
const walletClient = await createCocoClient();
|
||||
|
||||
|
||||
+26
-21
@@ -1,9 +1,10 @@
|
||||
import { ModelManager, type SdkStore } from "@routstr/sdk";
|
||||
import { ModelManager, ProviderManager, type SdkStore } from "@routstr/sdk";
|
||||
import type { ExposedModel } from "./types";
|
||||
import { logger } from "../utils/logger";
|
||||
|
||||
export type ModelProviderInfo = {
|
||||
baseUrl: string;
|
||||
disabled: boolean;
|
||||
pricing: {
|
||||
prompt: number;
|
||||
completion: number;
|
||||
@@ -16,7 +17,11 @@ export type ModelWithProviders = ExposedModel & {
|
||||
providers: ModelProviderInfo[];
|
||||
};
|
||||
|
||||
export function createModelService(modelManager: ModelManager, store: SdkStore) {
|
||||
export function createModelService(
|
||||
modelManager: ModelManager,
|
||||
providerManager: ProviderManager,
|
||||
store: SdkStore,
|
||||
) {
|
||||
let providerBootstrapPromise: Promise<void> | null = null;
|
||||
|
||||
const ensureProvidersBootstrapped = (): Promise<void> => {
|
||||
@@ -77,33 +82,33 @@ export function createModelService(modelManager: ModelManager, store: SdkStore)
|
||||
): Promise<ModelWithProviders | null> => {
|
||||
await ensureProvidersBootstrapped();
|
||||
|
||||
const allModels = modelManager.getAllCachedModels();
|
||||
const providers: ModelProviderInfo[] = [];
|
||||
const disabledSet = new Set<string>(store.getState().disabledProviders || []);
|
||||
|
||||
for (const [baseUrl, models] of Object.entries(allModels)) {
|
||||
const model = models.find((m) => m.id === modelId);
|
||||
if (model && model.sats_pricing) {
|
||||
providers.push({
|
||||
baseUrl,
|
||||
pricing: {
|
||||
prompt: model.sats_pricing.prompt,
|
||||
completion: model.sats_pricing.completion,
|
||||
request: model.sats_pricing.request,
|
||||
max_cost: model.sats_pricing.max_cost,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
// Use the SDK ranking (sorted by prompt+completion per million tokens)
|
||||
// so the display order matches real routing. includeDisabled keeps
|
||||
// disabled providers visible so we can annotate them.
|
||||
const ranking = providerManager.getProviderPriceRankingForModel(modelId, {
|
||||
includeDisabled: true,
|
||||
});
|
||||
|
||||
// Sort by max_cost (cheapest first)
|
||||
providers.sort((a, b) => a.pricing.max_cost - b.pricing.max_cost);
|
||||
const providers: ModelProviderInfo[] = ranking.map((entry: any) => ({
|
||||
baseUrl: entry.baseUrl,
|
||||
disabled: disabledSet.has(entry.baseUrl),
|
||||
pricing: {
|
||||
prompt: entry.promptPerMillion / 1_000_000,
|
||||
completion: entry.completionPerMillion / 1_000_000,
|
||||
request: entry.model.sats_pricing?.request ?? 0,
|
||||
max_cost: entry.model.sats_pricing?.max_cost ?? 0,
|
||||
},
|
||||
}));
|
||||
|
||||
if (providers.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get model metadata from first provider that has it
|
||||
// Get model metadata from first (cheapest) provider
|
||||
const cheapest = providers[0]!;
|
||||
const allModels = modelManager.getAllCachedModels();
|
||||
const firstProvider = allModels[cheapest.baseUrl];
|
||||
const modelInfo = firstProvider?.find((m: { id: string }) => m.id === modelId);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user