src / models.ts

// src/models.ts
// Модуль для кэширования и управления списком моделей

import { GeneratorController } from "@lmstudio/sdk";
import { fetchModels, filterFreeModels } from "./api";
import { globalConfigSchematics } from "./schema";
import { loadCache, saveCache } from "./file-cache";

// Кэш моделей на уровне модуля
let cachedAllModels: string[] | null = null;
let cachedFreeModels: string[] | null = null;
let loadPromise: Promise<void> | null = null;

/**
 * Загружает и кэширует список моделей из API
 * Сначала проверяет файловый кэш, затем загружает из API
 */
async function loadModels(ctl: GeneratorController): Promise<void> {
  if (loadPromise) {
    return loadPromise;
  }

  loadPromise = (async () => {
    const cache = loadCache();
    if (cache) {
      cachedAllModels = cache.allModels;
      cachedFreeModels = cache.freeModels;
      loadPromise = null;
      return;
    }

    const globalConfig = await ctl.getGlobalPluginConfig(globalConfigSchematics as any);
    const baseUrl = globalConfig.get("baseUrl") || "https://openrouter.ai/api/v1";
    const apiKey = globalConfig.get("apiKey") || "";

    const allModels = await fetchModels(baseUrl, apiKey);

    if (allModels.length > 0) {
      cachedAllModels = allModels;
      cachedFreeModels = filterFreeModels(allModels);
      saveCache(cachedAllModels, cachedFreeModels);
    } else {
      console.warn("[Models] API returned empty list, using fallback");
      cachedAllModels = ["x-ai/grok-4.1-fast:free"];
      cachedFreeModels = ["x-ai/grok-4.1-fast:free"];
    }

    loadPromise = null;
  })();

  return loadPromise;
}

/**
 * Получает список моделей (все или только бесплатные)
 */
export async function getModels(
  ctl: GeneratorController,
  onlyFree: boolean = false
): Promise<string[]> {
  await loadModels(ctl);

  if (onlyFree) {
    return cachedFreeModels || [];
  }

  return cachedAllModels || [];
}

/**
 * Получает первую доступную модель (для fallback)
 */
export async function getFirstModel(
  ctl: GeneratorController,
  onlyFree: boolean = false
): Promise<string> {
  const models = await getModels(ctl, onlyFree);
  return models[0] || "";
}

/**
 * Принудительно перезагружает модели из API (игнорируя кэш)
 */
export async function reloadModels(
  ctl: GeneratorController,
  onlyFree: boolean = false
): Promise<string[]> {
  // Сбрасываем кэш
  cachedAllModels = null;
  cachedFreeModels = null;
  loadPromise = null;
  
  // Загружаем заново
  await loadModels(ctl);
  
  if (onlyFree) {
    return cachedFreeModels || [];
  }
  
  return cachedAllModels || [];
}