import { EventEmitter } from 'events';
/**
 * Interface for remote server connection configuration
 */
export interface RemoteConnectionConfig {
    host: string;
    port: number;
    username: string;
    password?: string;
    privateKey?: string;
    passphrase?: string;
    name?: string;
    useSudo?: boolean;
}
/**
 * Type for remote command execution results
 */
export interface CommandResult {
    stdout: string;
    stderr: string;
    code: number | null;
}
/**
 * Class to manage SSH connections to remote servers
 */
export declare class RemoteConnection extends EventEmitter {
    private client;
    private config;
    private _isConnected;
    isPM2Installed: boolean;
    name: string;
    host: string;
    port: number;
    username: string;
    get hasPassword(): boolean;
    get hasPrivateKey(): boolean;
    get hasPassphrase(): boolean;
    get secureConfig(): RemoteConnectionConfig;
    getFullConfig(): RemoteConnectionConfig;
    constructor(config: RemoteConnectionConfig);
    /**
     * Check if the connection is active
     */
    isConnected(): boolean;
    /**
     * Connect to the remote server
     */ connect(): Promise<void>;
    /**
     * Disconnect from the remote server
     */
    disconnect(): Promise<void>; /**
     * Execute a command on the remote server
     * @param command The command to execute
     * @param forceSudo Whether to force using sudo for this specific command
     */
    executeCommand(command: string, forceSudo?: boolean): Promise<CommandResult>;
    /**
     * Stream a remote file directly into an HTTP response without buffering.
     *
     * Strategy (tried in order):
     *   1. SFTP createReadStream  — best; handles large files, uses file-transfer protocol
     *   2. exec `cat <file>`      — current SSH user, direct pipe to response
     *   3. exec `sudo -S cat`     — password-based sudo (when password auth is configured)
     *   4. exec `sudo cat`        — NOPASSWD sudo (key-based auth where sudo needs no password)
     */
    private static readonly SHELL_UNSAFE;
    private static validateRemotePath;
    streamFileToResponse(remotePath: string, res: import('express').Response, fileName: string): Promise<void>;
    /**
     * Stream a remote .gz file to an HTTP response, decompressing it on the fly.
     * Uses SFTP + local zlib.createGunzip() pipeline — no server-side buffering.
     * Falls back to exec `zcat` if SFTP is unavailable.
     */
    streamGzFileToResponse(remotePath: string, res: import('express').Response, fileName: string): Promise<void>;
    /**
     * Check if PM2 is installed on the remote server
     * Uses multiple detection methods for better reliability
     */
    checkPM2Installation(): Promise<boolean>;
    /**
     * Ordered list of command builders tried when resolving the pm2 binary.
     * The index of the first successful builder is cached so that subsequent
     * calls (including streaming commands) reuse the same invocation.
     */
    private static readonly PM2_BUILDERS;
    /** Index into PM2_BUILDERS of the invocation that actually works on this host. -1 = not yet resolved. */
    private resolvedBuilderIndex;
    /**
     * Execute a PM2 command with proper PATH handling.
     * The first successful invocation is cached so later calls (and streaming
     * commands) reuse the same shell/binary path without re-probing.
     */
    executePM2Command(pm2Args: string): Promise<CommandResult>;
    /**
     * Build a pm2 command string using the already-resolved invocation pattern.
     * Falls back to bash -li -c if the resolver has not yet run.
     * Use this when you need the raw command string for a streaming shell exec.
     */
    buildPM2StreamCommand(pm2Args: string): string;
    /**
     * Get PM2 processes from the remote server
     */
    getPM2Processes(): Promise<any[]>;
    /**
     * Format memory size to human readable format
     */
    private formatMemory;
    /**
     * Format uptime to human readable format
     */ private formatUptime;
    /**
     * Start a PM2 process
     */
    startPM2Process(processName: string): Promise<CommandResult>;
    /**
     * Stop a PM2 process
     */
    stopPM2Process(processName: string): Promise<CommandResult>;
    /**
     * Restart a PM2 process
     */
    restartPM2Process(processName: string): Promise<CommandResult>;
    /**
     * Delete a PM2 process
     */
    deletePM2Process(processName: string): Promise<CommandResult>;
    /**
     * Install PM2 on the remote server
     */
    installPM2(): Promise<CommandResult>;
    /**
     * Get system information from the remote server
     */
    getSystemInfo(): Promise<any>;
    /**
     * Get logs for a PM2 process
     */
    getPM2Logs(processName: string, lines?: number): Promise<CommandResult>; /**
     * Create a streaming log connection for a command
     */
    createLogStream(command: string, useSudo?: boolean): Promise<EventEmitter>;
}
/**
 * Interface for saved connection configuration
 */
export interface SavedConnectionConfig extends RemoteConnectionConfig {
    id: string;
}
/**
 * Connection manager to handle multiple remote connections
 */
export declare class RemoteConnectionManager {
    private connections;
    private configFilePath;
    constructor();
    /**
     * Create a new remote connection
     * @param config Connection configuration
     * @returns The connection ID
     */
    createConnection(config: RemoteConnectionConfig): string;
    /**
     * Update an existing remote connection
     * @param connectionId The connection ID
     * @param config New connection configuration
     * @returns True if the connection was updated, false if it didn't exist
     */
    updateConnection(connectionId: string, config: RemoteConnectionConfig): Promise<boolean>;
    /**
     * Get a connection by ID
     * @param connectionId The connection ID
     */
    getConnection(connectionId: string): RemoteConnection | undefined;
    /**
     * Close a connection by ID (disconnect but keep the configuration)
     * @param connectionId The connection ID
     */
    closeConnection(connectionId: string): Promise<boolean>;
    /**
     * Close all connections
     */ closeAllConnections(): Promise<void>;
    /**
     * Get all connections
     * @returns Map of all connections
     */
    getAllConnections(): Map<string, RemoteConnection>;
    /**
   * Delete a connection by ID
   * @param connectionId The connection ID
   * @returns True if the connection was deleted, false if it didn't exist
   */
    deleteConnection(connectionId: string): boolean;
    /**
     * Load connection configurations from disk
     */
    private loadConnectionsFromDisk;
    /**
   * Save connection configurations to disk
   */
    private saveConnectionsToDisk;
}
export declare const remoteConnectionManager: RemoteConnectionManager;
