/**
 * Proxy lifecycle manager.
 *
 * The only stateful piece of the sandbox: holds the long-lived
 * HTTP + SOCKS5 proxy servers and their Unix socket paths.
 *
 * Config resolution and command wrapping are pure functions —
 * the caller composes them with the proxy handle.
 */
import { startNetworkProxy } from './network/index.js';
export class ProxyManager {
    handle = null;
    startup = null;
    configKey = null;
    /** Socket paths for the current proxy (undefined if not started). */
    get httpSocketPath() {
        return this.handle?.httpSocketPath;
    }
    get socksSocketPath() {
        return this.handle?.socksSocketPath;
    }
    /**
     * Start the network proxy. Reuses the existing proxy when the effective
     * config is unchanged, otherwise restarts it with the new config.
     */
    async start(distro, allowedDomains, callbacks) {
        const configKey = JSON.stringify({
            distro,
            allowedDomains: [...allowedDomains].sort()
        });
        if (this.startup && this.configKey === configKey)
            return this.startup;
        if (this.startup) {
            this.stop();
        }
        this.configKey = configKey;
        this.startup = this._start(distro, allowedDomains, callbacks);
        this.startup.catch(() => {
            this.startup = null;
            this.configKey = null;
        });
        return this.startup;
    }
    async _start(distro, allowedDomains, callbacks) {
        this.handle = await startNetworkProxy({
            distro,
            allowedDomains,
            onDomainCheck: callbacks.onDomainCheck
        });
    }
    /**
     * Wait for the proxy to be ready.
     * If the proxy was never started, resolves immediately.
     * If the proxy failed to start, resolves (caller should have
     * handled the error via the start() promise and fallen back).
     */
    async ensureReady() {
        if (!this.startup)
            return;
        try {
            await this.startup;
        }
        catch {
            // The caller that initiated start() owns error handling
            // (e.g. falling back to networkMode 'none'). By the time
            // ensureReady() is called, the fallback should already be in place.
        }
    }
    /** Stop all proxy servers and bridges. */
    stop() {
        if (this.handle) {
            this.handle.stop();
            this.handle = null;
        }
        this.startup = null;
        this.configKey = null;
    }
}
//# sourceMappingURL=manager.js.map