import { readFileSync } from 'node:fs';
import * as tls from 'node:tls';
import { Agent, EnvHttpProxyAgent } from 'undici';
const proxyAgents = new Map();
const directAgents = new Map();
function getProxyUrl() {
    return (process.env.https_proxy ||
        process.env.HTTPS_PROXY ||
        process.env.http_proxy ||
        process.env.HTTP_PROXY);
}
function getExtraCaCertificates() {
    const path = process.env.NODE_EXTRA_CA_CERTS;
    if (!path) {
        return [];
    }
    try {
        return [readFileSync(path, 'utf-8')];
    }
    catch {
        return [];
    }
}
function getCaCertificates(options) {
    const extra = getExtraCaCertificates();
    if (!options.includeSystem && extra.length === 0) {
        return undefined;
    }
    const readCaCertificates = tls.getCACertificates;
    if (!readCaCertificates) {
        return extra.length > 0 ? [...new Set(extra)] : undefined;
    }
    const certificates = [
        ...readCaCertificates('default'),
        ...(options.includeSystem ? readCaCertificates('system') : []),
        ...extra
    ].filter((certificate) => certificate.trim().length > 0);
    const uniqueCertificates = [...new Set(certificates)];
    return uniqueCertificates.length > 0 ? uniqueCertificates : undefined;
}
function shouldBypassProxy(input) {
    const noProxy = process.env.no_proxy || process.env.NO_PROXY;
    if (!noProxy)
        return false;
    if (noProxy.trim() === '*')
        return true;
    let url;
    try {
        url = new URL(input instanceof Request ? input.url : String(input));
    }
    catch {
        return false;
    }
    const hostname = url.hostname.toLowerCase();
    const port = url.port || (url.protocol === 'https:' ? '443' : '80');
    const hostWithPort = `${hostname}:${port}`;
    const entries = noProxy
        .split(/[,\s]+/)
        .map((entry) => entry.trim().toLowerCase())
        .filter(Boolean);
    return entries.some((entry) => {
        if (entry.includes(':')) {
            return hostWithPort === entry;
        }
        if (entry.startsWith('.')) {
            return hostname === entry.slice(1) || hostname.endsWith(entry);
        }
        return hostname === entry;
    });
}
function getProxyDispatcher(input) {
    const proxyUrl = getProxyUrl();
    const bypassProxy = !proxyUrl || shouldBypassProxy(input);
    const ca = getCaCertificates({ includeSystem: !bypassProxy });
    const caKey = `${ca?.length ?? 0}:${process.env.NODE_EXTRA_CA_CERTS ?? ''}`;
    if (bypassProxy) {
        if (!ca) {
            return undefined;
        }
        let agent = directAgents.get(caKey);
        if (!agent) {
            agent = new Agent({
                connect: { ca }
            });
            directAgents.set(caKey, agent);
        }
        return agent;
    }
    const proxyKey = `${proxyUrl}:${caKey}`;
    let agent = proxyAgents.get(proxyKey);
    if (!agent) {
        agent = new EnvHttpProxyAgent({
            httpProxy: proxyUrl,
            httpsProxy: proxyUrl,
            noProxy: process.env.no_proxy || process.env.NO_PROXY,
            ...(ca
                ? {
                    connect: { ca },
                    requestTls: { ca }
                }
                : {})
        });
        proxyAgents.set(proxyKey, agent);
    }
    return agent;
}
export function withHostedMcpProxyFetchOptions(input, init) {
    const dispatcher = getProxyDispatcher(input);
    if (!dispatcher) {
        return init;
    }
    return {
        ...init,
        dispatcher
    };
}
export const hostedMcpFetch = async (input, init) => fetch(input, withHostedMcpProxyFetchOptions(input, init));
//# sourceMappingURL=proxy-fetch.js.map