| import type { ProviderModelEntry } from "../types.js"; |
|
|
| function asRecord(value: unknown): Record<string, unknown> | null { |
| if (!value || typeof value !== "object" || Array.isArray(value)) return null; |
| return value as Record<string, unknown>; |
| } |
|
|
| export function normalizeBaseUrl(value: string): string { |
| return value.trim().replace(/\/+$/, ""); |
| } |
|
|
| export function toModelCatalog(rawEntries: unknown[]): ProviderModelEntry[] { |
| const deduped = new Map<string, ProviderModelEntry>(); |
|
|
| 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<Response>, |
| 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 }; |
|
|