"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OpenRouterClient = void 0;
exports.createOpenRouterClient = createOpenRouterClient;
const undici_1 = require("undici");
const logger_js_1 = require("../../utils/logger.js");
const config_js_1 = require("../../utils/config.js");
const logger = (0, logger_js_1.createModuleLogger)('openrouter-client');
const OPENROUTER_BASE_URL = 'https://openrouter.ai/api/v1';
const DEFAULT_MODEL = 'google/gemini-3.1-flash-lite-preview';
const DEFAULT_MAX_TOKENS = 500;
const DEFAULT_TEMPERATURE = 0.8;
const MAX_RETRIES = 3;
const INITIAL_BACKOFF_MS = 1000;
class OpenRouterClient {
    apiKey;
    initialBackoffMs;
    constructor(apiKey, options) {
        this.apiKey = apiKey || '';
        this.initialBackoffMs = options?.initialBackoffMs ?? INITIAL_BACKOFF_MS;
    }
    async chatCompletion(messages, options) {
        const body = {
            model: DEFAULT_MODEL,
            messages,
            temperature: clampTemperature(options?.temperature ?? DEFAULT_TEMPERATURE),
            max_tokens: options?.max_tokens ?? DEFAULT_MAX_TOKENS,
            ...(options?.top_p !== undefined && { top_p: options.top_p }),
        };
        return this.sendRequest(body);
    }
    async chatCompletionWithVision(messages, options) {
        // Vision requests use the same endpoint; the multimodal content
        // is encoded inside the message content array.
        return this.chatCompletion(messages, options);
    }
    async sendRequest(body) {
        let lastError;
        for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
            try {
                logger.debug({ attempt, model: body.model }, 'Sending chat completion request');
                const response = await (0, undici_1.fetch)(`${OPENROUTER_BASE_URL}/chat/completions`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                        Authorization: `Bearer ${this.apiKey}`,
                    },
                    body: JSON.stringify(body),
                });
                if (!response.ok) {
                    const errorText = await response.text();
                    const err = new Error(`OpenRouter API error: ${response.status} ${response.statusText} - ${errorText}`);
                    logger.warn({ status: response.status, attempt, errorText }, 'API request failed');
                    // Don't retry on client errors (4xx) except 429 (rate limit)
                    if (response.status >= 400 && response.status < 500 && response.status !== 429) {
                        throw err;
                    }
                    lastError = err;
                }
                else {
                    const data = (await response.json());
                    logger.debug({ id: data.id, usage: data.usage }, 'Chat completion successful');
                    return data;
                }
            }
            catch (error) {
                if (lastError === undefined || lastError !== error) {
                    lastError = error instanceof Error ? error : new Error(String(error));
                }
                // If it's a non-retryable client error, throw immediately
                if (lastError.message.includes('OpenRouter API error: 4') && !lastError.message.includes('429')) {
                    throw lastError;
                }
                logger.warn({ attempt, error: lastError.message }, 'Request attempt failed');
            }
            // Only sleep between retries, not after the last attempt
            if (attempt < MAX_RETRIES) {
                const backoff = this.initialBackoffMs * Math.pow(2, attempt - 1);
                logger.debug({ backoff, attempt }, 'Waiting before retry');
                await sleep(backoff);
            }
        }
        logger.error({ error: lastError?.message }, 'All retry attempts exhausted');
        throw lastError ?? new Error('OpenRouter request failed after all retries');
    }
}
exports.OpenRouterClient = OpenRouterClient;
function clampTemperature(value) {
    return Math.min(0.9, Math.max(0.7, value));
}
function sleep(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms));
}
function createOpenRouterClient() {
    return new OpenRouterClient(config_js_1.config.openrouterApiKey);
}
//# sourceMappingURL=client.js.map