Forked from will-lms/openai-compat-endpoint
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 || [];
}