"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.probeCursorRuntime = void 0;
const cursor_auth_1 = require("./cursor-auth");
const cursor_daemon_1 = require("./cursor-daemon");
const cursor_models_1 = require("./cursor-models");
const PROBE_PROMPT = 'Reply with OK only.';
const PROBE_TIMEOUT_MS = 15000;
const PROBE_SUCCESS_PATTERN = /^ok[.!]?$/i;
function isDaemonReachabilityError(error) {
    if (!(error instanceof Error))
        return false;
    const message = error.message.toLowerCase();
    if (message.includes('fetch failed') ||
        message.includes('econnrefused') ||
        message.includes('econnreset') ||
        message.includes('socket hang up') ||
        message.includes('connection refused')) {
        return true;
    }
    const cause = error.cause;
    if (!cause || typeof cause !== 'object' || !('code' in cause)) {
        return false;
    }
    const code = String(cause.code ?? '').toUpperCase();
    return ['ECONNREFUSED', 'ECONNRESET', 'ECONNABORTED', 'EPIPE', 'UND_ERR_SOCKET'].includes(code);
}
function parseProbeError(text) {
    try {
        const parsed = JSON.parse(text);
        if (parsed.error?.message) {
            return {
                errorType: parsed.error.type ?? null,
                message: parsed.error.message,
            };
        }
        if (parsed.type === 'error') {
            return {
                errorType: null,
                message: text,
            };
        }
    }
    catch {
        // fall through to raw text
    }
    return {
        errorType: null,
        message: text || 'Unknown probe failure',
    };
}
function parseProbeSuccess(text) {
    try {
        const parsed = JSON.parse(text);
        if (parsed.error?.message) {
            return { ok: false, message: parsed.error.message };
        }
        const content = parsed.choices?.[0]?.message?.content;
        if (typeof content !== 'string' || !content.trim()) {
            return { ok: false, message: 'Probe response was missing assistant content.' };
        }
        return {
            ok: PROBE_SUCCESS_PATTERN.test(content.trim()),
            message: PROBE_SUCCESS_PATTERN.test(content.trim())
                ? 'Live probe succeeded.'
                : `Probe returned unexpected assistant content: ${content.trim()}`,
        };
    }
    catch {
        return { ok: false, message: 'Probe response was not valid JSON.' };
    }
}
async function probeCursorRuntime(config) {
    const startedAt = Date.now();
    if (!config.enabled) {
        return {
            ok: false,
            stage: 'config',
            status: 400,
            duration_ms: Date.now() - startedAt,
            message: 'Cursor integration is disabled.',
            error_type: 'configuration_error',
        };
    }
    const authStatus = (0, cursor_auth_1.checkAuthStatus)();
    if (!authStatus.authenticated || !authStatus.credentials) {
        return {
            ok: false,
            stage: 'auth',
            status: 401,
            duration_ms: Date.now() - startedAt,
            message: 'Cursor credentials not found. Run `ccs legacy cursor auth` first.',
            error_type: 'authentication_error',
        };
    }
    if (authStatus.expired) {
        return {
            ok: false,
            stage: 'auth',
            status: 401,
            duration_ms: Date.now() - startedAt,
            message: 'Cursor credentials expired. Run `ccs legacy cursor auth` again.',
            error_type: 'authentication_error',
        };
    }
    let daemonRunning = await (0, cursor_daemon_1.isDaemonRunning)(config.port);
    if (!daemonRunning && config.auto_start) {
        const startResult = await (0, cursor_daemon_1.startDaemon)({
            port: config.port,
            ghost_mode: config.ghost_mode,
        });
        if (!startResult.success) {
            daemonRunning = await (0, cursor_daemon_1.isDaemonRunning)(config.port);
        }
        else {
            daemonRunning = true;
        }
        if (!daemonRunning) {
            return {
                ok: false,
                stage: 'daemon',
                status: 503,
                duration_ms: Date.now() - startedAt,
                message: startResult.error || 'Failed to start Cursor daemon for live probe.',
                error_type: 'daemon_start_failed',
            };
        }
    }
    if (!daemonRunning) {
        return {
            ok: false,
            stage: 'daemon',
            status: 503,
            duration_ms: Date.now() - startedAt,
            message: 'Cursor daemon is not running. Start it with `ccs legacy cursor start` or enable auto_start.',
            error_type: 'daemon_not_running',
        };
    }
    try {
        const credentials = {
            accessToken: authStatus.credentials.accessToken,
            machineId: authStatus.credentials.machineId,
            ghostMode: config.ghost_mode,
        };
        const availableModels = await (0, cursor_models_1.getModelsForDaemon)({ credentials });
        const model = (0, cursor_models_1.resolveCursorRequestModel)(config.model, availableModels);
        const abortController = new AbortController();
        const timeout = setTimeout(() => abortController.abort(), PROBE_TIMEOUT_MS);
        try {
            const response = await fetch(`http://127.0.0.1:${config.port}/v1/chat/completions`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    model,
                    max_tokens: 8,
                    messages: [{ role: 'user', content: PROBE_PROMPT }],
                }),
                signal: abortController.signal,
            });
            const text = await response.text();
            const duration = Date.now() - startedAt;
            if (!response.ok) {
                const error = parseProbeError(text);
                return {
                    ok: false,
                    stage: 'runtime',
                    status: response.status,
                    duration_ms: duration,
                    model,
                    error_type: error.errorType,
                    message: error.message,
                };
            }
            const success = parseProbeSuccess(text);
            return {
                ok: success.ok,
                stage: 'runtime',
                status: success.ok ? response.status : 502,
                duration_ms: duration,
                model,
                error_type: success.ok ? null : 'probe_validation_failed',
                message: success.message,
            };
        }
        finally {
            clearTimeout(timeout);
        }
    }
    catch (error) {
        const daemonReachabilityError = isDaemonReachabilityError(error);
        return {
            ok: false,
            stage: error instanceof Error && error.name === 'AbortError'
                ? 'runtime'
                : daemonReachabilityError
                    ? 'daemon'
                    : 'runtime',
            status: error instanceof Error && error.name === 'AbortError'
                ? 504
                : daemonReachabilityError
                    ? 503
                    : 500,
            duration_ms: Date.now() - startedAt,
            error_type: error instanceof Error && error.name === 'AbortError'
                ? 'probe_timeout'
                : daemonReachabilityError
                    ? 'daemon_unreachable'
                    : 'runtime_error',
            message: error instanceof Error && error.name === 'AbortError'
                ? `Live probe timed out after ${PROBE_TIMEOUT_MS}ms.`
                : daemonReachabilityError
                    ? 'Cursor daemon became unreachable during the live probe. Start it again and retry.'
                    : error instanceof Error
                        ? error.message
                        : 'Unknown runtime probe failure.',
        };
    }
}
exports.probeCursorRuntime = probeCursorRuntime;
//# sourceMappingURL=cursor-runtime-probe.js.map