diff --git a/.gitignore b/.gitignore index 345bc6a..52e9ea4 100644 --- a/.gitignore +++ b/.gitignore @@ -32,5 +32,8 @@ temp/ .worktrees/ .routstrd/ +# Graphify output +graphify-out/ + # Standalone prototype scripts index.ts diff --git a/src/cli.ts b/src/cli.ts index 7f58af5..c6124d8 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -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`, ); diff --git a/src/daemon/index.ts b/src/daemon/index.ts index 91ca8c1..0dcf6d3 100644 --- a/src/daemon/index.ts +++ b/src/daemon/index.ts @@ -113,7 +113,7 @@ async function main(): Promise { // 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(); diff --git a/src/daemon/models.ts b/src/daemon/models.ts index 702dd18..2099396 100644 --- a/src/daemon/models.ts +++ b/src/daemon/models.ts @@ -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 | null = null; const ensureProvidersBootstrapped = (): Promise => { @@ -77,33 +82,33 @@ export function createModelService(modelManager: ModelManager, store: SdkStore) ): Promise => { await ensureProvidersBootstrapped(); - const allModels = modelManager.getAllCachedModels(); - const providers: ModelProviderInfo[] = []; + const disabledSet = new Set(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);