// Author: Simon-Pierre Boucher // Contact: contact@spboucher.ai // Project: chat.spboucher.ai import { orGet } from "./client"; import { parseModelsResponse, type ORModelRaw } from "./schemas"; import { deriveCapabilities } from "./capabilities"; import { derivePricing } from "./pricing"; import type { ModelDefinition } from "./types"; /** Provider is the human-readable prefix of the display name ("Anthropic: Claude ..."), never parsed from the ID for behavior. */ function deriveProvider(raw: ORModelRaw): string | undefined { const name = raw.name ?? ""; const colon = name.indexOf(":"); if (colon > 0) return name.slice(0, colon).trim(); const slash = raw.id.indexOf("/"); if (slash > 0) return raw.id.slice(0, slash); return undefined; } function displayName(raw: ORModelRaw): string { const name = raw.name ?? raw.id; const colon = name.indexOf(":"); return colon > 0 ? name.slice(colon + 1).trim() : name; } export function normalizeModel(raw: ORModelRaw): ModelDefinition { return { id: raw.id, name: displayName(raw), provider: deriveProvider(raw), description: raw.description, contextLength: raw.context_length ?? raw.top_provider?.context_length, pricing: derivePricing(raw), capabilities: deriveCapabilities(raw), metadata: { architecture: raw.architecture?.modality, tokenizer: raw.architecture?.tokenizer, createdAt: raw.created, raw, }, }; } /** Fetch and normalize the full OpenRouter model catalog. */ export async function fetchModels(signal?: AbortSignal): Promise { const json = await orGet("/models", signal); return parseModelsResponse(json).map(normalizeModel); }