#!/usr/bin/env node
"use strict";
/**
 * Headless executor for Claude CLI delegation
 * Spawns claude with -p flag for single-turn execution
 */
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 (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.HeadlessExecutor = void 0;
const child_process_1 = require("child_process");
const path = __importStar(require("path"));
const process_utils_1 = require("../utils/process-utils");
const fs = __importStar(require("fs"));
const session_manager_1 = require("./session-manager");
const settings_parser_1 = require("./settings-parser");
const ui_1 = require("../utils/ui");
const stream_parser_1 = require("./executor/stream-parser");
const result_aggregator_1 = require("./executor/result-aggregator");
const config_manager_1 = require("../utils/config-manager");
const profile_compat_1 = require("../utils/profile-compat");
const shell_executor_1 = require("../utils/shell-executor");
const openai_compat_launch_settings_1 = require("../utils/openai-compat-launch-settings");
const profile_continuity_inheritance_1 = require("../auth/profile-continuity-inheritance");
const image_analysis_1 = require("../utils/image-analysis");
const hooks_1 = require("../utils/hooks");
const image_analyzer_profile_hook_injector_1 = require("../utils/hooks/image-analyzer-profile-hook-injector");
const services_1 = require("../api/services");
const cliproxy_1 = require("../cliproxy");
const port_manager_1 = require("../cliproxy/config/port-manager");
const proxy_1 = require("../proxy");
const websearch_manager_1 = require("../utils/websearch-manager");
const config_loader_facade_1 = require("../config/config-loader-facade");
/**
 * Headless executor for Claude CLI delegation
 */
class HeadlessExecutor {
    /**
     * Execute task via headless Claude CLI
     * @param profile - Profile name (glm, km, custom)
     * @param enhancedPrompt - Enhanced prompt with context
     * @param options - Execution options
     * @returns execution result
     */
    static async execute(profile, enhancedPrompt, options = {}) {
        const { cwd = process.cwd(), timeout = 600000, // 10 minutes default
        permissionMode = 'acceptEdits', resumeSession = false, sessionId = null, maxTurns, fallbackModel, agents, betas, extraArgs = [], } = options;
        // Validate permission mode
        this._validatePermissionMode(permissionMode);
        // Initialize session manager
        const sessionMgr = new session_manager_1.SessionManager();
        // Detect Claude CLI path
        const claudeCli = this._detectClaudeCli();
        if (!claudeCli) {
            throw new Error('Claude CLI not found in PATH. Install from: https://docs.claude.com/en/docs/claude-code/installation');
        }
        // Get settings path for profile (supports compatibility aliases like km -> kimi)
        const ccsDir = (0, config_loader_facade_1.getCcsDir)();
        const settingsCandidates = (0, profile_compat_1.getProfileLookupCandidates)(profile).map((candidate) => path.join(ccsDir, `${candidate}.settings.json`));
        const settingsPath = settingsCandidates.find((candidatePath) => fs.existsSync(candidatePath));
        const primarySettingsPath = path.join(ccsDir, `${profile}.settings.json`);
        // Validate settings file exists
        if (!settingsPath) {
            throw new Error(`Settings file not found: ${primarySettingsPath}\nProfile "${profile}" may not be configured.`);
        }
        const continuityInheritance = await (0, profile_continuity_inheritance_1.resolveProfileContinuityInheritance)({
            profileName: profile,
            profileType: 'settings',
            target: 'claude',
        });
        const inheritedClaudeConfigDir = continuityInheritance.claudeConfigDir;
        if (continuityInheritance.sourceAccount && process.env.CCS_DEBUG) {
            console.error((0, ui_1.info)(`Continuity inheritance active: profile "${profile}" -> account "${continuityInheritance.sourceAccount}"`));
        }
        (0, websearch_manager_1.ensureWebSearchMcpOrThrow)();
        const imageAnalysisMcpReady = (0, image_analysis_1.ensureImageAnalysisMcpOrThrow)();
        (0, websearch_manager_1.syncWebSearchMcpToConfigDir)(inheritedClaudeConfigDir);
        (0, image_analysis_1.syncImageAnalysisMcpToConfigDir)(inheritedClaudeConfigDir);
        const settings = (0, config_loader_facade_1.loadSettings)(settingsPath);
        const globalEnvConfig = (0, config_loader_facade_1.getGlobalEnvConfig)();
        const globalEnv = globalEnvConfig.enabled ? globalEnvConfig.env : {};
        const settingsEnv = settings.env || {};
        const openAICompatProfile = (0, proxy_1.resolveOpenAICompatProfileConfig)(profile, settingsPath, settingsEnv);
        const cliproxyBridge = (0, services_1.resolveCliproxyBridgeMetadata)(settings);
        let imageAnalysisFallbackHookReady;
        if (imageAnalysisMcpReady) {
            (0, image_analyzer_profile_hook_injector_1.removeImageAnalysisProfileHook)(profile, settingsPath);
        }
        else {
            imageAnalysisFallbackHookReady = (0, hooks_1.prepareImageAnalysisFallbackHook)();
            (0, image_analyzer_profile_hook_injector_1.ensureProfileHooks)({
                profileName: profile,
                profileType: 'settings',
                settingsPath,
                settings,
                cliproxyBridge,
                sharedHookInstalled: imageAnalysisFallbackHookReady,
            });
        }
        const imageAnalysisStatus = await (0, hooks_1.resolveImageAnalysisRuntimeStatus)({
            profileName: profile,
            profileType: 'settings',
            settings,
            cliproxyBridge,
            sharedHookInstalled: imageAnalysisFallbackHookReady,
        });
        const runtimeConnection = (0, hooks_1.resolveImageAnalysisRuntimeConnection)();
        let imageAnalysisEnv = (0, hooks_1.getImageAnalysisHookEnv)({
            profileName: profile,
            profileType: 'settings',
            settings,
            cliproxyBridge,
        });
        imageAnalysisEnv = (0, hooks_1.applyImageAnalysisRuntimeOverrides)(imageAnalysisEnv, {
            backendId: imageAnalysisStatus.backendId,
            model: imageAnalysisStatus.model,
            runtimePath: imageAnalysisStatus.runtimePath,
            baseUrl: runtimeConnection.baseUrl,
            apiKey: runtimeConnection.apiKey,
            allowSelfSigned: runtimeConnection.allowSelfSigned,
        });
        imageAnalysisEnv = {
            ...imageAnalysisEnv,
            CCS_IMAGE_ANALYSIS_SKIP_HOOK: imageAnalysisMcpReady ? '1' : '0',
        };
        const imageAnalysisProvider = imageAnalysisEnv['CCS_CURRENT_PROVIDER'];
        if (imageAnalysisEnv['CCS_IMAGE_ANALYSIS_SKIP'] !== '1' &&
            imageAnalysisProvider &&
            imageAnalysisStatus.effectiveRuntimeMode === 'native-read') {
            console.error((0, ui_1.info)(`${imageAnalysisStatus.effectiveRuntimeReason || `Image analysis via ${imageAnalysisProvider} is unavailable.`} This delegation will use native Read.`));
            imageAnalysisEnv = {
                ...imageAnalysisEnv,
                CCS_CURRENT_PROVIDER: '',
                CCS_IMAGE_ANALYSIS_SKIP: '1',
            };
        }
        else if (imageAnalysisEnv['CCS_IMAGE_ANALYSIS_SKIP'] !== '1' &&
            imageAnalysisProvider &&
            imageAnalysisStatus.proxyReadiness === 'stopped') {
            const ensureServiceResult = await (0, cliproxy_1.ensureCliproxyService)((0, port_manager_1.resolveLifecyclePort)(), false);
            if (!ensureServiceResult.started) {
                console.error((0, ui_1.warn)(`Image analysis via ${imageAnalysisProvider} is unavailable because CCS could not start the local CLIProxy service. This delegation will use native Read.`));
                imageAnalysisEnv = {
                    ...imageAnalysisEnv,
                    CCS_CURRENT_PROVIDER: '',
                    CCS_IMAGE_ANALYSIS_SKIP: '1',
                };
            }
        }
        let runtimeEnvVars = {
            ...(0, shell_executor_1.stripAnthropicRoutingEnv)({ ...globalEnv, ...settingsEnv }, settingsEnv),
            ...(inheritedClaudeConfigDir ? { CLAUDE_CONFIG_DIR: inheritedClaudeConfigDir } : {}),
            CCS_PROFILE_TYPE: 'settings',
            CCS_STRIP_INHERITED_ANTHROPIC_ENV: '1',
        };
        if (openAICompatProfile) {
            const proxyStart = await (0, proxy_1.startOpenAICompatProxy)(openAICompatProfile, {
                insecure: openAICompatProfile.insecure,
            });
            if (!proxyStart.success) {
                throw new Error(proxyStart.error || 'Failed to start local OpenAI-compatible proxy');
            }
            runtimeEnvVars = {
                ...runtimeEnvVars,
                ...(0, proxy_1.buildOpenAICompatProxyEnv)(openAICompatProfile, proxyStart.port, proxyStart.authToken || '', inheritedClaudeConfigDir),
            };
            delete runtimeEnvVars.ANTHROPIC_API_KEY;
        }
        // Smart slash command detection and preservation
        const processedPrompt = this._processSlashCommand(enhancedPrompt);
        const launchSettings = openAICompatProfile
            ? (0, openai_compat_launch_settings_1.createOpenAICompatLaunchSettings)(settingsPath, settings)
            : { settingsPath, cleanup: () => { } };
        // Prepare arguments
        const args = ['-p', processedPrompt, '--settings', launchSettings.settingsPath];
        // Always use stream-json for real-time progress visibility
        args.push('--output-format', 'stream-json', '--verbose');
        // Add permission mode
        if (permissionMode && permissionMode !== 'default') {
            if (permissionMode === 'bypassPermissions') {
                args.push('--dangerously-skip-permissions');
                if (process.env.CCS_DEBUG) {
                    console.warn((0, ui_1.warn)('WARNING: Using --dangerously-skip-permissions mode'));
                }
            }
            else {
                args.push('--permission-mode', permissionMode);
            }
        }
        // Add resume flag for multi-turn sessions
        if (resumeSession) {
            const lastSession = sessionMgr.getLastSession(profile);
            if (lastSession) {
                args.push('--resume', lastSession.sessionId);
                if (process.env.CCS_DEBUG) {
                    const cost = lastSession.totalCost?.toFixed(4) || '0.0000';
                    console.error((0, ui_1.info)(`Resuming session: ${lastSession.sessionId} ($${cost})`));
                }
            }
            else if (sessionId) {
                args.push('--resume', sessionId);
            }
            else {
                console.warn((0, ui_1.warn)('No previous session found, starting new session'));
            }
        }
        else if (sessionId) {
            args.push('--resume', sessionId);
        }
        // Add tool restrictions from settings
        const toolRestrictions = settings_parser_1.SettingsParser.parseToolRestrictions(cwd);
        if (toolRestrictions.allowedTools.length > 0) {
            args.push('--allowedTools', ...toolRestrictions.allowedTools);
        }
        if (toolRestrictions.disallowedTools.length > 0) {
            args.push('--disallowedTools', toolRestrictions.disallowedTools.join(','));
        }
        // Claude Code CLI passthrough flags (explicit, validated)
        // Use undefined checks (not truthy) to allow empty strings if ever valid
        if (maxTurns !== undefined && maxTurns > 0) {
            args.push('--max-turns', String(maxTurns));
        }
        if (fallbackModel !== undefined && fallbackModel) {
            args.push('--fallback-model', fallbackModel);
        }
        if (agents !== undefined && agents) {
            args.push('--agents', agents);
        }
        if (betas !== undefined && betas) {
            args.push('--betas', betas);
        }
        // Passthrough extra args (catch-all for new/unknown flags)
        // Filter out duplicates of explicitly handled flags
        if (extraArgs.length > 0) {
            const explicitFlags = new Set(['--max-turns', '--fallback-model', '--agents', '--betas']);
            const filteredExtras = [];
            for (let i = 0; i < extraArgs.length; i++) {
                if (explicitFlags.has(extraArgs[i])) {
                    // Skip this flag and its value (next element)
                    if (i + 1 < extraArgs.length && !extraArgs[i + 1].startsWith('-')) {
                        i++; // Skip value too
                    }
                    continue;
                }
                filteredExtras.push(extraArgs[i]);
            }
            if (filteredExtras.length > 0) {
                args.push(...filteredExtras);
            }
        }
        const imageAnalysisArgs = imageAnalysisMcpReady
            ? (0, image_analysis_1.appendThirdPartyImageAnalysisToolArgs)(args)
            : args;
        const launchArgs = (0, websearch_manager_1.appendThirdPartyWebSearchToolArgs)(imageAnalysisArgs);
        const traceEnv = (0, websearch_manager_1.createWebSearchTraceContext)({
            launcher: 'delegation.headless-executor',
            args: launchArgs,
            cwd,
            profile,
            profileType: 'settings',
            settingsPath,
            claudeConfigDir: inheritedClaudeConfigDir,
        });
        if (process.env.CCS_DEBUG) {
            console.error((0, ui_1.info)(`Claude CLI args: ${launchArgs.join(' ')}`));
        }
        // Initialize UI before spawning
        await ui_1.ui.init();
        // Execute with spawn
        return this._spawnAndExecute(claudeCli, launchArgs, {
            cwd,
            profile,
            timeout,
            resumeSession,
            sessionId,
            sessionMgr,
            claudeConfigDir: inheritedClaudeConfigDir,
            imageAnalysisEnv,
            runtimeEnvVars,
            traceEnv,
            launchCleanup: launchSettings.cleanup,
        });
    }
    /**
     * Spawn Claude CLI and handle execution
     */
    static _spawnAndExecute(claudeCli, args, ctx) {
        const { cwd, profile, timeout, resumeSession, sessionId, sessionMgr, claudeConfigDir, imageAnalysisEnv = {}, runtimeEnvVars = {}, traceEnv = {}, launchCleanup = () => { }, } = ctx;
        return new Promise((resolve, reject) => {
            const startTime = Date.now();
            const showProgress = !process.env.CCS_QUIET;
            const streamBuffer = new stream_parser_1.StreamBuffer();
            if (showProgress) {
                const modelName = (0, config_manager_1.getModelDisplayName)(profile);
                console.error(ui_1.ui.info(`Delegating to ${modelName}...`));
            }
            // Strip Claude Code nested session guard env var to allow CCS delegation
            // (Claude Code v2.1.39+ sets CLAUDECODE to detect nested sessions)
            const cleanEnv = (0, shell_executor_1.stripClaudeCodeEnv)({
                ...(0, shell_executor_1.stripAnthropicRoutingEnv)(process.env),
                ...(0, shell_executor_1.getClaudeLaunchEnvOverrides)(),
                ...(0, websearch_manager_1.getWebSearchHookEnv)(),
                ...runtimeEnvVars,
                ...imageAnalysisEnv,
                ...traceEnv,
                ...(claudeConfigDir ? { CLAUDE_CONFIG_DIR: claudeConfigDir } : {}),
                CCS_PROFILE_TYPE: 'settings',
            });
            const proc = (0, child_process_1.spawn)(claudeCli, args, {
                cwd,
                stdio: ['ignore', 'pipe', 'pipe'],
                timeout,
                env: cleanEnv,
            });
            let stdout = '';
            let stderr = '';
            let progressInterval;
            const messages = [];
            let timedOut = false;
            let cleanedUp = false;
            const cleanupLaunchArtifacts = () => {
                if (cleanedUp) {
                    return;
                }
                cleanedUp = true;
                launchCleanup();
            };
            // Setup signal handlers for cleanup
            const cleanupHandler = () => {
                if (proc.exitCode === null) {
                    (0, process_utils_1.killWithEscalation)(proc, 2000);
                }
            };
            process.once('SIGINT', cleanupHandler);
            process.once('SIGTERM', cleanupHandler);
            const removeSignalHandlers = () => {
                process.removeListener('SIGINT', cleanupHandler);
                process.removeListener('SIGTERM', cleanupHandler);
            };
            proc.on('close', removeSignalHandlers);
            proc.on('error', removeSignalHandlers);
            // Progress indicator
            if (showProgress) {
                progressInterval = setInterval(() => {
                    const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
                    process.stderr.write(`${ui_1.ui.info(`Still running... ${elapsed}s elapsed`)}\r`);
                }, 5000);
            }
            // Capture stdout (stream-json format)
            proc.stdout?.on('data', (data) => {
                const dataStr = data.toString();
                stdout += dataStr;
                const parsedMessages = streamBuffer.parseChunk(dataStr);
                for (const msg of parsedMessages) {
                    messages.push(msg);
                    // Show real-time tool use
                    if (showProgress && msg.type === 'assistant') {
                        const toolUses = msg.message?.content?.filter((c) => c.type === 'tool_use') || [];
                        for (const tool of toolUses) {
                            process.stderr.write('\r\x1b[K');
                            const toolInput = tool.input || {};
                            const verboseMsg = (0, stream_parser_1.formatToolVerbose)(tool.name || 'Unknown', toolInput);
                            process.stderr.write(`${verboseMsg}\n`);
                        }
                    }
                }
            });
            // Stream stderr in real-time
            proc.stderr?.on('data', (data) => {
                const stderrText = data.toString();
                stderr += stderrText;
                if (showProgress) {
                    if (progressInterval)
                        process.stderr.write('\r\x1b[K');
                    process.stderr.write(stderrText);
                }
            });
            // Handle completion
            proc.on('close', (exitCode) => {
                cleanupLaunchArtifacts();
                const duration = Date.now() - startTime;
                if (progressInterval) {
                    clearInterval(progressInterval);
                    process.stderr.write('\r\x1b[K');
                }
                if (showProgress) {
                    const durationSec = (duration / 1000).toFixed(1);
                    console.error(timedOut
                        ? ui_1.ui.warn(`Timed out after ${durationSec}s`)
                        : ui_1.ui.info(`Completed in ${durationSec}s`));
                    console.error('');
                }
                const result = (0, result_aggregator_1.buildExecutionResult)({
                    exitCode: exitCode || 0,
                    stdout,
                    stderr,
                    cwd,
                    profile,
                    duration,
                    timedOut,
                    messages,
                });
                const launchId = traceEnv.CCS_WEBSEARCH_TRACE_LAUNCH_ID;
                if (launchId) {
                    const launchTraceRecords = (0, websearch_manager_1.readWebSearchTraceRecords)(launchId, {
                        ...process.env,
                        ...traceEnv,
                        CCS_PROFILE_TYPE: 'settings',
                    });
                    const mcpSessionSummary = [...launchTraceRecords]
                        .reverse()
                        .find((record) => record.event === 'mcp_session_summary');
                    const providerSuccess = [...launchTraceRecords]
                        .reverse()
                        .find((record) => record.event === 'websearch_provider_success');
                    const exposed = mcpSessionSummary?.exposed === true;
                    const calledWebSearch = result.toolUsageSummary?.calledWebSearch === true;
                    const fallbackToolsUsed = result.toolUsageSummary?.fallbackToolsUsed || [];
                    (0, websearch_manager_1.appendWebSearchTrace)('headless_websearch_summary', {
                        profile,
                        sessionId: result.sessionId || null,
                        calledWebSearch,
                        fallbackToolsUsed,
                        providerUsed: typeof providerSuccess?.providerName === 'string'
                            ? providerSuccess.providerName
                            : null,
                        exposed,
                        likelyBypassed: exposed && !calledWebSearch
                            ? fallbackToolsUsed.length > 0
                                ? true
                                : 'unknown'
                            : false,
                    }, {
                        ...process.env,
                        ...traceEnv,
                        CCS_PROFILE_TYPE: 'settings',
                    });
                }
                // Store session
                if (result.sessionId) {
                    if (resumeSession || sessionId) {
                        sessionMgr.updateSession(profile, result.sessionId, { totalCost: result.totalCost });
                    }
                    else {
                        sessionMgr.storeSession(profile, {
                            sessionId: result.sessionId,
                            totalCost: result.totalCost,
                            cwd,
                        });
                    }
                    if (Math.random() < 0.1)
                        sessionMgr.cleanupExpired();
                }
                resolve(result);
            });
            // Handle errors
            proc.on('error', (error) => {
                cleanupLaunchArtifacts();
                if (progressInterval)
                    clearInterval(progressInterval);
                reject(new Error(`Failed to execute Claude CLI: ${error.message}`));
            });
            // Handle timeout
            if (timeout > 0) {
                const timeoutHandle = setTimeout(() => {
                    if (proc.exitCode === null) {
                        timedOut = true;
                        if (progressInterval) {
                            clearInterval(progressInterval);
                            process.stderr.write('\r\x1b[K');
                        }
                        // Longer grace period for timeout (vs 2s for SIGINT) since delegated sessions may need time to flush output
                        (0, process_utils_1.killWithEscalation)(proc, 10000);
                    }
                }, timeout);
                proc.on('close', () => clearTimeout(timeoutHandle));
            }
        });
    }
    /** Validate permission mode */
    static _validatePermissionMode(mode) {
        const VALID_MODES = ['default', 'plan', 'acceptEdits', 'bypassPermissions'];
        if (!VALID_MODES.includes(mode)) {
            throw new Error(`Invalid permission mode: "${mode}". Valid modes: ${VALID_MODES.join(', ')}`);
        }
    }
    /** Detect Claude CLI executable */
    static _detectClaudeCli() {
        if (process.env.CCS_CLAUDE_PATH)
            return process.env.CCS_CLAUDE_PATH;
        const { execSync } = require('child_process');
        try {
            return execSync('command -v claude', { encoding: 'utf8' }).trim();
        }
        catch {
            return null;
        }
    }
    /** Execute with retry logic */
    static async executeWithRetry(profile, enhancedPrompt, options = {}) {
        const { maxRetries = 2, ...execOptions } = options;
        let lastError;
        for (let attempt = 0; attempt <= maxRetries; attempt++) {
            try {
                const result = await this.execute(profile, enhancedPrompt, execOptions);
                if (result.success)
                    return result;
                if (attempt < maxRetries) {
                    console.error((0, ui_1.warn)(`Attempt ${attempt + 1} failed, retrying...`));
                    await this._sleep(1000 * (attempt + 1));
                    continue;
                }
                return result;
            }
            catch (error) {
                lastError = error;
                if (attempt < maxRetries) {
                    console.error((0, ui_1.warn)(`Attempt ${attempt + 1} errored, retrying...`));
                    await this._sleep(1000 * (attempt + 1));
                }
            }
        }
        throw lastError || new Error('Execution failed after all retry attempts');
    }
    /** Sleep utility for retry backoff */
    static _sleep(ms) {
        return new Promise((resolve) => setTimeout(resolve, ms));
    }
    /** Process prompt to detect and preserve slash commands */
    static _processSlashCommand(prompt) {
        const trimmed = prompt.trim();
        // Case 1: Already starts with slash command
        if (trimmed.match(/^\/[\w:-]+(\s|$)/))
            return prompt;
        // Case 2: Find slash command embedded in text
        const embeddedSlash = trimmed.match(/(?:^|[^\w/])(\/[\w:-]+)(\s+[\s\S]*)?$/);
        if (embeddedSlash) {
            const command = embeddedSlash[1];
            const args = (embeddedSlash[2] || '').trim();
            const matchIndex = embeddedSlash.index || 0;
            const matchStart = matchIndex + (embeddedSlash[0][0] === '/' ? 0 : 1);
            const beforeCommand = trimmed.substring(0, matchStart).trim();
            if (beforeCommand && args)
                return `${command} ${args}\n\nContext: ${beforeCommand}`;
            if (beforeCommand)
                return `${command}\n\nContext: ${beforeCommand}`;
            return args ? `${command} ${args}` : command;
        }
        return prompt;
    }
    /** Test if profile is executable */
    static async testProfile(profile) {
        try {
            const result = await this.execute(profile, 'Say "test successful"', { timeout: 10000 });
            return result.success;
        }
        catch {
            return false;
        }
    }
}
exports.HeadlessExecutor = HeadlessExecutor;
//# sourceMappingURL=headless-executor.js.map