import type { ProviderAccount, ProviderVendorInfo } from '@/lib/providers'; import type { ProductModelRef } from '@/types/coding-conversation'; export interface CodingModelOption { key: string; accountId: string; modelId: string; label: string; } export function codingModelKey(model: Pick): string { return JSON.stringify([model.accountId, model.modelId]); } export function parseCodingModelKey(key: string): Pick | null { try { const value = JSON.parse(key) as unknown; if (!Array.isArray(value) || value.length !== 2) return null; const [accountId, modelId] = value; if (typeof accountId !== 'string' || !accountId.trim() || typeof modelId !== 'string' || !modelId.trim()) return null; return { accountId: accountId.trim(), modelId: modelId.trim() }; } catch { return null; } } export function buildCodingModelOptions( accounts: ProviderAccount[], vendors: ProviderVendorInfo[], ): CodingModelOption[] { const vendorNames = new Map(vendors.map((vendor) => [vendor.id, vendor.name])); const seen = new Set(); const options: CodingModelOption[] = []; for (const account of accounts) { if (!account.enabled) continue; const modelIds = [ account.model, ...(account.fallbackModels ?? []), ...(account.metadata?.customModels ?? []), ]; for (const value of modelIds) { const modelId = value?.trim(); if (!modelId) continue; const key = codingModelKey({ accountId: account.id, modelId }); if (seen.has(key)) continue; seen.add(key); const vendor = vendorNames.get(account.vendorId); options.push({ key, accountId: account.id, modelId, label: `${account.label}${vendor && vendor !== account.label ? ` ยท ${vendor}` : ''} / ${modelId}`, }); } } return options; }