/**
 * Custom OpenAI-compatible provider adapter. The base URL is admin-controlled,
 * so it is SSRF-validated and DNS-resolved before any request. Falls back to an
 * empty model list (manual entry in the UI) when the endpoint doesn't support
 * `/models`.
 */
import { assertSafeBaseUrl, extractModelIds, messageFromStatus, openAiChat, statusFromHttp, timedFetch, trimTrailingSlash, } from './http.js';
function headers(ctx) {
    return { authorization: `Bearer ${ctx.apiKey}` };
}
export async function testConnection(ctx) {
    const testedAt = new Date().toISOString();
    if (!ctx.baseUrl) {
        return {
            ok: false,
            status: 'needs_setup',
            message: 'A base URL is required for a custom provider.',
            testedAt,
        };
    }
    try {
        await assertSafeBaseUrl(ctx.baseUrl);
    }
    catch (err) {
        return {
            ok: false,
            status: 'unknown',
            message: err instanceof Error ? err.message : 'Invalid base URL.',
            testedAt,
        };
    }
    if (!ctx.apiKey) {
        return { ok: false, status: 'needs_setup', message: messageFromStatus('needs_setup'), testedAt };
    }
    try {
        const res = await timedFetch(`${trimTrailingSlash(ctx.baseUrl)}/models`, { method: 'GET', headers: headers(ctx) }, ctx);
        // A 404 likely means the endpoint doesn't implement /models; the connection
        // itself may still be usable with a manually-entered model id.
        if (res.status === 404) {
            return {
                ok: true,
                status: 'connected',
                message: 'Connected. This endpoint does not list models; enter a model id manually.',
                testedAt,
            };
        }
        const status = statusFromHttp(res.status);
        return { ok: status === 'connected', status, message: messageFromStatus(status), testedAt };
    }
    catch {
        return {
            ok: false,
            status: 'provider_down',
            message: messageFromStatus('provider_down'),
            testedAt,
        };
    }
}
export async function listModels(ctx) {
    if (!ctx.baseUrl)
        return [];
    await assertSafeBaseUrl(ctx.baseUrl);
    const res = await timedFetch(`${trimTrailingSlash(ctx.baseUrl)}/models`, { method: 'GET', headers: headers(ctx) }, ctx);
    if (res.status === 404)
        return [];
    if (!res.ok)
        throw new Error(`Custom provider model listing failed (${res.status})`);
    return extractModelIds(await res.json());
}
export async function generateText(ctx, opts) {
    if (!ctx.baseUrl)
        throw new Error('A base URL is required for a custom provider.');
    await assertSafeBaseUrl(ctx.baseUrl);
    return openAiChat(ctx.baseUrl, { authorization: `Bearer ${ctx.apiKey}` }, ctx, opts);
}
//# sourceMappingURL=custom.js.map