/**
 * HTTP proxy for forwarding requests to the local OpenCode server.
 *
 * Proxies non-local routes (session, permission, provider, global/health)
 * to the OpenCode server running at localhost:4096 with Basic auth.
 */
import { logger } from "../utils/logger.js";
const DEFAULT_TIMEOUT_MS = 30_000;
let currentAuth = null;
/**
 * Set the OpenCode auth credentials for proxying.
 * Called after spawnOpenCode() completes successfully.
 */
export function setOpenCodeAuth(auth) {
    currentAuth = auth;
}
/**
 * Clear the OpenCode auth credentials (e.g., on shutdown).
 */
export function clearOpenCodeAuth() {
    currentAuth = null;
}
/**
 * Get the current OpenCode auth credentials.
 * Returns null if OpenCode is not running.
 */
export function getOpenCodeAuth() {
    return currentAuth;
}
/**
 * Build a full URL from the base URL, path, and optional query parameters.
 */
function buildUrl(baseUrl, path, query) {
    const url = new URL(path, baseUrl);
    if (query) {
        for (const [key, value] of Object.entries(query)) {
            url.searchParams.set(key, value);
        }
    }
    return url.toString();
}
/**
 * Proxy an HTTP request to the OpenCode server.
 *
 * Adds the Basic auth header automatically. Forwards the request method,
 * path, headers, body, and query parameters. Returns the response status,
 * headers, and body.
 *
 * @throws Error with code OPENCODE_UNREACHABLE if OpenCode is not configured
 * @throws Error with code TIMEOUT if the request times out
 */
export async function proxyToOpenCode(request, timeoutMs = DEFAULT_TIMEOUT_MS) {
    if (!currentAuth) {
        throw new Error("OPENCODE_UNREACHABLE");
    }
    const { method, path, headers, body, query } = request;
    const url = buildUrl(currentAuth.baseUrl, path, query);
    const fetchHeaders = {
        Authorization: currentAuth.authHeader,
        ...headers,
    };
    // Set content-type for requests with a body if not already set
    if (body && !fetchHeaders["Content-Type"] && !fetchHeaders["content-type"]) {
        fetchHeaders["Content-Type"] = "application/json";
    }
    logger.debug(`Proxy ${method} ${path} → ${url}`);
    try {
        const response = await fetch(url, {
            method,
            headers: fetchHeaders,
            body: method !== "GET" && method !== "HEAD" ? body : undefined,
            signal: AbortSignal.timeout(timeoutMs),
        });
        // Collect response headers
        const responseHeaders = {};
        response.headers.forEach((value, key) => {
            responseHeaders[key] = value;
        });
        // Read response body as text
        const responseBody = await response.text();
        logger.debug(`Proxy response: ${response.status} (${responseBody.length} bytes)`);
        return {
            status: response.status,
            headers: responseHeaders,
            body: responseBody || undefined,
        };
    }
    catch (err) {
        if (err instanceof DOMException && err.name === "TimeoutError") {
            throw new Error("TIMEOUT");
        }
        if (err instanceof TypeError &&
            (err.message.includes("fetch") || err.message.includes("ECONNREFUSED"))) {
            throw new Error("OPENCODE_UNREACHABLE");
        }
        throw err;
    }
}
//# sourceMappingURL=proxy.js.map