import { models as codexFallbackModels } from "@zmeel/adapter-codex-local";
import { readConfigFile } from "../config-file.js";
const OPENAI_MODELS_ENDPOINT = "https://api.openai.com/v1/models";
const OPENAI_MODELS_TIMEOUT_MS = 5000;
const OPENAI_MODELS_CACHE_TTL_MS = 60_000;
let cached = null;
function fingerprint(apiKey) {
    return `${apiKey.length}:${apiKey.slice(-6)}`;
}
function dedupeModels(models) {
    const seen = new Set();
    const deduped = [];
    for (const model of models) {
        const id = model.id.trim();
        if (!id || seen.has(id))
            continue;
        seen.add(id);
        deduped.push({ id, label: model.label.trim() || id });
    }
    return deduped;
}
function mergedWithFallback(models) {
    return dedupeModels([
        ...models,
        ...codexFallbackModels,
    ]).sort((a, b) => a.id.localeCompare(b.id, "en", { numeric: true, sensitivity: "base" }));
}
function resolveOpenAiApiKey() {
    const envKey = process.env.OPENAI_API_KEY?.trim();
    if (envKey)
        return envKey;
    const config = readConfigFile();
    if (config?.llm?.provider !== "openai")
        return null;
    const configKey = config.llm.apiKey?.trim();
    return configKey && configKey.length > 0 ? configKey : null;
}
async function fetchOpenAiModels(apiKey) {
    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), OPENAI_MODELS_TIMEOUT_MS);
    try {
        const response = await fetch(OPENAI_MODELS_ENDPOINT, {
            headers: {
                Authorization: `Bearer ${apiKey}`,
            },
            signal: controller.signal,
        });
        if (!response.ok)
            return [];
        const payload = (await response.json());
        const data = Array.isArray(payload.data) ? payload.data : [];
        const models = [];
        for (const item of data) {
            if (typeof item !== "object" || item === null)
                continue;
            const id = item.id;
            if (typeof id !== "string" || id.trim().length === 0)
                continue;
            models.push({ id, label: id });
        }
        return dedupeModels(models);
    }
    catch {
        return [];
    }
    finally {
        clearTimeout(timeout);
    }
}
export async function listCodexModels() {
    const apiKey = resolveOpenAiApiKey();
    const fallback = dedupeModels(codexFallbackModels);
    if (!apiKey)
        return fallback;
    const now = Date.now();
    const keyFingerprint = fingerprint(apiKey);
    if (cached && cached.keyFingerprint === keyFingerprint && cached.expiresAt > now) {
        return cached.models;
    }
    const fetched = await fetchOpenAiModels(apiKey);
    if (fetched.length > 0) {
        const merged = mergedWithFallback(fetched);
        cached = {
            keyFingerprint,
            expiresAt: now + OPENAI_MODELS_CACHE_TTL_MS,
            models: merged,
        };
        return merged;
    }
    if (cached && cached.keyFingerprint === keyFingerprint && cached.models.length > 0) {
        return cached.models;
    }
    return fallback;
}
export function resetCodexModelsCacheForTests() {
    cached = null;
}
//# sourceMappingURL=codex-models.js.map