"use strict";
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2024-2026 Gracker (Chris)
// This file is part of SmartPerfetto. See LICENSE for details.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.assertAnalysisRuntimeReady = assertAnalysisRuntimeReady;
exports.collectDoctorReport = collectDoctorReport;
exports.isClaudeSdkBinaryUsable = isClaudeSdkBinaryUsable;
const fs = __importStar(require("fs"));
const child_process_1 = require("child_process");
const runtimeSelection_1 = require("../../agentRuntime/runtimeSelection");
const claudeConfig_1 = require("../../agentv3/claudeConfig");
const openAiConfig_1 = require("../../agentOpenAI/openAiConfig");
const workingTraceProcessor_1 = require("../../services/workingTraceProcessor");
const providerManager_1 = require("../../services/providerManager");
const androidCapture_1 = require("./androidCapture");
const captureTools_1 = require("./captureTools");
function providerIdFor(selection) {
    return selection.source === 'provider' ? selection.providerId ?? null : null;
}
function assertAnalysisRuntimeReady(options = {}) {
    const selection = (0, runtimeSelection_1.resolveAgentRuntimeSelection)(options.providerId, options.runtimeOverride);
    const providerId = providerIdFor(selection);
    if (selection.kind === 'openai-agents-sdk') {
        const diagnostics = (0, openAiConfig_1.getOpenAIRuntimeDiagnostics)(providerId);
        if (!(0, openAiConfig_1.hasOpenAICredentials)(providerId)) {
            throw new Error([
                'OpenAI runtime is selected but no usable OpenAI-compatible credentials were found.',
                'Set OPENAI_API_KEY, configure an active OpenAI/Ollama provider, or use a localhost OpenAI-compatible endpoint.',
                'Run `smp doctor --format text` for the resolved runtime and provider details.',
            ].join(' '));
        }
        return { selection, diagnostics };
    }
    const diagnostics = (0, claudeConfig_1.getClaudeRuntimeDiagnostics)(providerId);
    if (!isClaudeSdkBinaryUsable(diagnostics.sdkBinary)) {
        throw new Error([
            'Claude Agent SDK runtime is selected but its native binary is not executable.',
            diagnostics.sdkBinary?.chosenPath
                ? `Resolved binary: ${diagnostics.sdkBinary.chosenPath}`
                : 'No SDK native binary was resolved.',
            'Reinstall backend dependencies, or set CLAUDE_BINARY_PATH to an executable Claude Agent SDK binary.',
        ].join(' '));
    }
    // Claude Agent SDK can use API/proxy credentials, Bedrock/Vertex env, or a
    // local Claude Code login. Do not reject the local-auth fallback here; the SDK
    // will surface a precise auth error if the local account is unavailable.
    return { selection, diagnostics };
}
function collectDoctorReport(cliHome) {
    const selection = (0, runtimeSelection_1.resolveAgentRuntimeSelection)();
    const providerId = providerIdFor(selection);
    const runtimeDiagnostics = selection.kind === 'openai-agents-sdk'
        ? (0, openAiConfig_1.getOpenAIRuntimeDiagnostics)(providerId)
        : (0, claudeConfig_1.getClaudeRuntimeDiagnostics)(providerId);
    const traceProcessorPath = (0, workingTraceProcessor_1.getTraceProcessorPath)();
    const traceProcessorExists = fs.existsSync(traceProcessorPath);
    const traceProcessorExecutable = traceProcessorExists && isExecutable(traceProcessorPath);
    const adb = (0, captureTools_1.resolveAdbTool)();
    const tracebox = (0, captureTools_1.resolveTraceboxTool)();
    const adbDevices = collectAdbDevices(adb);
    const providerSvc = (0, providerManager_1.getProviderService)();
    const providers = providerSvc.list();
    const active = providers.find((p) => p.isActive);
    const nodeMajor = Number.parseInt(process.version.replace(/^v/, '').split('.')[0] || '0', 10);
    const checks = [
        {
            name: 'node',
            ok: nodeMajor >= 24 && nodeMajor < 25,
            status: nodeMajor >= 24 && nodeMajor < 25 ? 'ok' : 'error',
            message: `Node.js ${process.version} (expected >=24 <25)`,
        },
        {
            name: 'runtime',
            ok: runtimeDiagnostics.configured || selection.kind === 'claude-agent-sdk',
            status: runtimeDiagnostics.configured
                ? 'ok'
                : selection.kind === 'claude-agent-sdk'
                    ? 'warn'
                    : 'error',
            message: runtimeDiagnostics.configured
                ? `${selection.kind} credentials/configuration detected`
                : selection.kind === 'claude-agent-sdk'
                    ? 'Claude SDK has no explicit credentials; local Claude login fallback will be used if available'
                    : 'OpenAI runtime needs OPENAI_API_KEY or a localhost/OpenAI-compatible provider',
            details: {
                source: selection.source,
                providerId: selection.providerId,
                providerName: selection.providerName,
            },
        },
        ...(selection.kind === 'claude-agent-sdk'
            ? [buildClaudeSdkBinaryCheck(runtimeDiagnostics.sdkBinary)]
            : []),
        {
            name: 'trace_processor_shell',
            ok: traceProcessorExists && traceProcessorExecutable,
            status: traceProcessorExists && traceProcessorExecutable ? 'ok' : 'warn',
            message: traceProcessorExists
                ? traceProcessorExecutable
                    ? 'trace_processor_shell is present and executable'
                    : 'trace_processor_shell exists but is not executable'
                : 'trace_processor_shell is missing; CLI will download the pinned binary on first trace command',
            details: { path: traceProcessorPath },
        },
        {
            name: 'adb',
            ok: adb.exists && adb.executable,
            status: adb.exists && adb.executable ? 'ok' : 'warn',
            message: adb.exists && adb.executable
                ? `adb is available (${adb.source})`
                : 'adb is not available; Android capture needs ADB_PATH, bundled adb, or adb on PATH',
            details: { path: adb.path, source: adb.source, devices: adbDevices.readyCount },
        },
        {
            name: 'tracebox',
            ok: tracebox.exists && tracebox.executable,
            status: tracebox.exists && tracebox.executable ? 'ok' : 'warn',
            message: tracebox.exists && tracebox.executable
                ? `tracebox is available for sideload capture (${tracebox.source})`
                : 'tracebox is not bundled; sideload capture requires --tracebox or an approved packaged binary',
            details: { path: tracebox.path, source: tracebox.source },
        },
    ];
    return {
        ok: checks.every((c) => c.status !== 'error'),
        generatedAt: new Date().toISOString(),
        node: {
            version: process.version,
            expected: '>=24.0.0 <25.0.0',
            ok: nodeMajor >= 24 && nodeMajor < 25,
        },
        cliHome,
        runtime: selection,
        runtimeDiagnostics,
        traceProcessor: {
            path: traceProcessorPath,
            exists: traceProcessorExists,
            executable: traceProcessorExecutable,
        },
        captureTools: {
            adb,
            tracebox,
            devices: adbDevices,
        },
        providers: {
            count: providers.length,
            ...(active ? { active: { id: active.id, name: active.name, type: active.type } } : {}),
        },
        checks,
    };
}
function collectAdbDevices(adb) {
    if (!adb.exists || !adb.executable) {
        return { count: 0, readyCount: 0, serials: [] };
    }
    const result = (0, child_process_1.spawnSync)(adb.path, ['devices', '-l'], {
        encoding: 'utf-8',
        timeout: 5000,
    });
    if (result.error || result.status !== 0) {
        return { count: 0, readyCount: 0, serials: [] };
    }
    const devices = (0, androidCapture_1.parseAdbDevices)(`${result.stdout ?? ''}\n${result.stderr ?? ''}`);
    const ready = devices.filter((device) => device.state === 'device');
    return {
        count: devices.length,
        readyCount: ready.length,
        serials: ready.map((device) => device.serial),
    };
}
function isExecutable(filePath) {
    try {
        fs.accessSync(filePath, fs.constants.X_OK);
        return true;
    }
    catch {
        return false;
    }
}
function isClaudeSdkBinaryUsable(sdkBinary) {
    if (!sdkBinary?.chosenPath || sdkBinary.source === 'none')
        return false;
    return isExecutable(sdkBinary.chosenPath);
}
function buildClaudeSdkBinaryCheck(sdkBinary) {
    const usable = isClaudeSdkBinaryUsable(sdkBinary);
    return {
        name: 'claude_sdk_binary',
        ok: usable,
        status: usable ? 'ok' : 'error',
        message: usable
            ? 'Claude Agent SDK native binary is present and executable'
            : 'Claude Agent SDK native binary is missing or not executable',
        details: {
            path: sdkBinary?.chosenPath ?? null,
            source: sdkBinary?.source ?? 'none',
            detectedPlatformKey: sdkBinary?.detectedPlatformKey ?? null,
            fallbackUsed: sdkBinary?.fallbackUsed ?? false,
        },
    };
}
//# sourceMappingURL=runtimeGuard.js.map