(options: GetModelsOptions)
| 242 | * @returns The models from the cache or the fetched models. |
| 243 | */ |
| 244 | export const getModels = async (options: GetModelsOptions): Promise<ModelRecord> => { |
| 245 | const { provider } = options |
| 246 | const cacheKey = getCacheKey(options) |
| 247 | |
| 248 | const shouldSkipCache = isAuthScopedProvider(provider) |
| 249 | |
| 250 | let models = shouldSkipCache ? undefined : getModelsFromCache(options) |
| 251 | |
| 252 | if (models) { |
| 253 | return models |
| 254 | } |
| 255 | |
| 256 | try { |
| 257 | models = await fetchModelsFromProvider(options) |
| 258 | const modelCount = Object.keys(models).length |
| 259 | |
| 260 | // Only cache non-empty results so a failed API response doesn't get persisted |
| 261 | // as if the provider had no models. Auth-scoped providers skip caching entirely. |
| 262 | if (modelCount > 0 && !shouldSkipCache) { |
| 263 | memoryCache.set(cacheKey, models) |
| 264 | |
| 265 | await writeModels(cacheKey, models).catch((err) => |
| 266 | console.error(`[MODEL_CACHE] Error writing ${cacheKey} models to file cache:`, err), |
| 267 | ) |
| 268 | } else if (modelCount === 0) { |
| 269 | TelemetryService.instance.captureEvent(TelemetryEventName.MODEL_CACHE_EMPTY_RESPONSE, { |
| 270 | provider, |
| 271 | context: "getModels", |
| 272 | hasExistingCache: false, |
| 273 | }) |
| 274 | } |
| 275 | |
| 276 | return models |
| 277 | } catch (error) { |
| 278 | // Log the error and re-throw it so the caller can handle it (e.g., show a UI message). |
| 279 | console.error(`[getModels] Failed to fetch models in modelCache for ${provider}:`, error) |
| 280 | |
| 281 | throw error // Re-throw the original error to be handled by the caller. |
| 282 | } |
| 283 | } |
| 284 | |
| 285 | /** |
| 286 | * Force-refresh models from API, bypassing cache. |
no test coverage detected