import type { ProviderModelEntry } from "../types.js"; function asRecord(value: unknown): Record | null { if (!value || typeof value !== "object" || Array.isArray(value)) return null; return value as Record; } export function normalizeBaseUrl(value: string): string { return value.trim().replace(/\/+$/, ""); } export function toModelCatalog(rawEntries: unknown[]): ProviderModelEntry[] { const deduped = new Map(); for (const rawEntry of rawEntries) { const record = asRecord(rawEntry); const id = typeof record?.id === "string" ? record.id.trim() : ""; if (!id || deduped.has(id)) continue; const label = typeof record?.name === "string" && record.name.trim().length > 0 ? record.name.trim() : id; deduped.set(id, { id, label, raw: record ?? null, }); } return Array.from(deduped.values()).sort((left, right) => left.id.localeCompare(right.id)); } export async function fetchOpenAiModelCatalog( fetchImpl: (url: string, init?: RequestInit) => Promise, input: { baseUrl: string; apiKey: string }, ): Promise<{ baseUrl: string; modelCatalog: ProviderModelEntry[] }> { const baseUrl = normalizeBaseUrl(input.baseUrl); const response = await fetchImpl(`${baseUrl}/models`, { headers: { Authorization: `Bearer ${input.apiKey}`, }, }); if (!response.ok) { throw new Error(`Failed to fetch models (${response.status})`); } const body = await response.json() as { data?: unknown[] }; return { baseUrl, modelCatalog: toModelCatalog(Array.isArray(body.data) ? body.data : []), }; } export { asRecord };