/**
 * Dynamic Gemini model discovery with caching.
 *
 * Fetches available models from the Gemini API and categorizes them by
 * capability. Results are cached in memory and refreshed periodically.
 */
import { GoogleGenAI } from "@google/genai";
import { logger } from "./logger.js";
/** Cache TTL: 1 hour. */
const CACHE_TTL_MS = 60 * 60 * 1000;
let cache;
/**
 * Infer the primary capability of a model based on its ID and supportedActions.
 * Returns undefined if the model isn't useful for our tool.
 */
function inferCapability(modelId, supportedActions) {
    const id = modelId.toLowerCase();
    const actions = supportedActions.map((a) => a.toLowerCase());
    // TTS models
    if (id.includes("tts"))
        return "tts";
    // Music models (Lyria family)
    if (id.includes("lyria"))
        return "music";
    // Video generation models (Veo family)
    if (id.includes("veo"))
        return "video_generation";
    // Image generation — models with "image" in the name that support generateContent
    if (id.includes("image") &&
        (actions.includes("generatecontent") || actions.includes("generate_content"))) {
        return "image_generation";
    }
    // General text/multimodal models (gemini family, not specialized)
    if (id.startsWith("gemini") && !id.includes("embedding")) {
        if (actions.includes("generatecontent") || actions.includes("generate_content")) {
            return "text";
        }
    }
    return undefined;
}
/**
 * Fetch all available models from the Gemini API and categorize them.
 */
async function fetchModels(apiKey) {
    const ai = new GoogleGenAI({ apiKey });
    const models = [];
    try {
        const pager = await ai.models.list({ config: { pageSize: 100, queryBase: true } });
        // Collect all pages
        let page = pager.page;
        while (page.length > 0) {
            for (const m of page) {
                const id = m.name?.replace(/^models\//, "") ?? "";
                const actions = m.supportedActions ?? [];
                const capability = inferCapability(id, actions);
                if (capability) {
                    models.push({
                        id,
                        displayName: m.displayName ?? id,
                        supportedActions: actions,
                        capability,
                    });
                }
            }
            // Try next page
            const hasNext = pager.hasNextPage();
            if (!hasNext)
                break;
            await pager.nextPage();
            page = pager.page;
        }
    }
    catch (err) {
        logger.err(`[gemini-models] Failed to fetch model list: ${err instanceof Error ? err.message : String(err)}`);
    }
    return models;
}
/**
 * Get categorized Gemini models, using cache when fresh.
 * Returns empty array if the API call fails and no cache exists.
 */
export async function getGeminiModels(apiKey) {
    if (cache && Date.now() - cache.fetchedAt < CACHE_TTL_MS) {
        return cache.models;
    }
    const models = await fetchModels(apiKey);
    if (models.length > 0) {
        cache = { models, fetchedAt: Date.now() };
        logger.system(`[gemini-models] Cached ${models.length} models`);
    }
    return cache?.models ?? [];
}
/**
 * Get all models for a specific capability, sorted by ID descending
 * (newer versions typically have higher version numbers).
 */
export async function getModelsForCapability(apiKey, capability) {
    const models = await getGeminiModels(apiKey);
    return models
        .filter((m) => m.capability === capability)
        .sort((a, b) => b.id.localeCompare(a.id));
}
/**
 * Build a human-readable summary of available models, grouped by capability.
 * Used to dynamically populate the tool description.
 */
export function formatModelList(models) {
    const grouped = new Map();
    for (const m of models) {
        const list = grouped.get(m.capability) ?? [];
        list.push(m);
        grouped.set(m.capability, list);
    }
    const labels = {
        image_generation: "Image Generation",
        music: "Music Generation",
        text: "Text / Multimodal",
        video_generation: "Video Generation",
        tts: "Text-to-Speech",
    };
    const lines = [];
    for (const [cap, label] of Object.entries(labels)) {
        const list = grouped.get(cap);
        if (list && list.length > 0) {
            lines.push(`${label}: ${list.map((m) => m.id).join(", ")}`);
        }
    }
    return lines.join("\n");
}
/** Clear the cache (for testing). */
export function clearModelCache() {
    cache = undefined;
}
//# sourceMappingURL=gemini-models.js.map