#!/usr/bin/env node
/**
 * Фоновый процесс после `cursorconnect start`: держит bridge, чинит CDP если Cursor
 * открыли без --remote-debugging-port=9222, idle npm update.
 * Не launchd — завершается при cursorconnect stop.
 */
import { readFileSync } from 'fs';
import { ensureConnectCdpReady, isBridgeRunning, isCursorRunning, startBridge, stopBridgeProcess, } from './launch.js';
import { SUPERVISOR_ENV_FILE } from './paths.js';
import { maybeIdleAutoUpdate } from './idle-auto-update.js';
const WATCH_MS = 15_000;
const CDP_RECOVERY_COOLDOWN_MS = 45_000;
function sleep(ms) {
    return new Promise((r) => setTimeout(r, ms));
}
function loadSupervisorConfig() {
    try {
        const raw = readFileSync(SUPERVISOR_ENV_FILE, 'utf-8');
        const j = JSON.parse(raw);
        if (!j.env || typeof j.env !== 'object')
            return null;
        return { env: j.env, argv: Array.isArray(j.argv) ? j.argv : [] };
    }
    catch {
        return null;
    }
}
async function bridgeNeedsCdpRecovery() {
    if (!isCursorRunning())
        return false;
    try {
        const res = await fetch('http://127.0.0.1:3847/health', {
            signal: AbortSignal.timeout(3_000),
        });
        if (!res.ok)
            return isCursorRunning();
        const j = (await res.json());
        return !j.cdp;
    }
    catch {
        return isCursorRunning();
    }
}
async function main() {
    const cfg = loadSupervisorConfig();
    if (!cfg) {
        process.exit(0);
    }
    const { env, argv } = cfg;
    const cdpUrl = env.CDP_URL ?? 'http://127.0.0.1:9222';
    const relayUrl = (env.RELAY_URL ?? '').replace(/\/$/, '');
    let lastCdpRecoveryAt = 0;
    let lastIdleUpdateCheck = Date.now();
    const syncBridge = async () => {
        if (isBridgeRunning()) {
            stopBridgeProcess();
        }
        startBridge(env);
    };
    const bootBridge = async () => {
        if (isBridgeRunning()) {
            const needs = await bridgeNeedsCdpRecovery();
            if (!needs)
                return;
        }
        await ensureConnectCdpReady({
            cdpUrl,
            noRestartCursor: false,
            syncBridge,
            waitBridgeMs: 35_000,
        });
    };
    await bootBridge();
    for (;;) {
        await sleep(WATCH_MS);
        if (!isBridgeRunning()) {
            await bootBridge();
            continue;
        }
        if (await bridgeNeedsCdpRecovery()) {
            const now = Date.now();
            if (now - lastCdpRecoveryAt >= CDP_RECOVERY_COOLDOWN_MS) {
                lastCdpRecoveryAt = now;
                await ensureConnectCdpReady({
                    cdpUrl,
                    noRestartCursor: false,
                    restartCursor: true,
                    syncBridge,
                    waitBridgeMs: 35_000,
                });
            }
        }
        if (relayUrl &&
            Date.now() - lastIdleUpdateCheck >= idleUpdateCheckMsFromEnv()) {
            lastIdleUpdateCheck = Date.now();
            await maybeIdleAutoUpdate(relayUrl, argv, env);
        }
    }
}
function idleUpdateCheckMsFromEnv() {
    const n = Number.parseInt(process.env.CURSORCONNECT_IDLE_UPDATE_CHECK_MS ?? '', 10);
    return Number.isFinite(n) && n > 0 ? n : 60_000;
}
main().catch((e) => {
    console.error('[cursorconnect] supervisor:', e);
    process.exit(1);
});
