export type FrpcDownloadProgress = {
    phase: 'downloading' | 'extracting';
    url?: string;
    bytesReceived?: number;
    totalBytes?: number | null;
    percent?: number | null;
};
export type TunnelStartPhase = 'preparing_frpc' | 'registering' | 'starting_frpc' | 'reconnecting_frpc';
export type TunnelStartProgress = {
    phase: TunnelStartPhase;
    startedAt: string;
    publicUrl?: string | null;
};
export type TunnelRegistration = {
    tunnelId: string;
    tunnelToken: string;
    subdomain: string;
    publicUrl: string;
    frpc: {
        serverAddr: string;
        serverPort: number;
        authToken: string;
        proxyName: string;
    };
    expiresAt: string;
    heartbeatIntervalMs: number;
};
export type PersistedTunnelState = {
    tunnelId: string;
    tunnelToken: string;
    subdomain: string;
    publicUrl: string;
    frpcAuthToken: string;
    registeredAt: string;
    enabled?: boolean;
    /** Saved on register so stop/start can resume without re-registering. */
    frpcServerAddr?: string;
    frpcServerPort?: number;
    proxyName?: string;
    heartbeatIntervalMs?: number;
};
export type TunnelStatus = {
    enabled: boolean;
    state: 'disconnected' | 'connecting' | 'connected' | 'reconnecting' | 'error';
    subdomain: string | null;
    publicUrl: string | null;
    connectedSince: string | null;
    frpcPid: number | null;
    lastHeartbeatAt: string | null;
    lastError: string | null;
    frpcDownload?: FrpcDownloadProgress | null;
    startProgress?: TunnelStartProgress | null;
    config: {
        autoStart: boolean;
        brokerUrl: string;
        transport: {
            tls: 'broker_terminated';
        };
    };
};
export type TunnelQrPayload = {
    qrPayload: string;
    publicUrl: string | null;
    lanUrl: string | null;
    expiresAt?: string;
};
