import type { MessengerAdapter, MessageContext } from '../../../core/types.js';
import type { Credentials } from './ilink-types.js';
export declare class ILinkWeChatAdapter implements MessengerAdapter {
    readonly name = "wechat-ilink";
    private client;
    private messageHandler?;
    private isRunning;
    private pollState;
    private contextTokens;
    private typingTickets;
    private processedMessages;
    constructor();
    start(): Promise<void>;
    stop(): Promise<void>;
    onMessage(handler: (ctx: MessageContext) => Promise<void>): void;
    sendMessage(threadId: string, text: string): Promise<void>;
    /** Drop the cached + persisted context-token for a user. Called when
     *  wechat rejects a send with INVALID_PARAMS so the next inbound
     *  message rebuilds the cache from the fresh polling token. */
    private invalidateContextToken;
    sendTyping(threadId: string, isTyping: boolean): Promise<void>;
    /**
     * Start QR code login flow
     * Returns QR code URL and token for polling
     */
    startQRLogin(): Promise<{
        qrUrl: string;
        qrToken: string;
    }>;
    /**
     * Single-shot QR status check, intended for the web settings page
     * which polls on its own cadence rather than holding a 2-minute
     * long-poll. On 'confirmed' the credentials are persisted to disk
     * exactly the same way `waitForQRLogin` does, so the caller doesn't
     * need to know about the credentials-file layout.
     */
    pollQRLogin(qrToken: string): Promise<{
        status: 'wait' | 'scaned' | 'confirmed' | 'expired' | string;
        credentials?: {
            accountId?: string;
            userId?: string;
        };
    }>;
    /**
     * Poll QR code status until confirmed or expired
     */
    waitForQRLogin(qrToken: string, onStatus?: (status: string) => void): Promise<Credentials | null>;
    private startPolling;
    private pollLoop;
    /**
     * Attempt to recover from SESSION_EXPIRED. Tries a fresh getUpdates
     * up to 3 times with linear backoff so a single network blip during
     * recovery doesn't tear down the whole adapter (W-3).
     */
    private tryRefreshSession;
    /**
     * Periodic keep-alive: probe getconfig instead of getUpdates so we don't
     * race the polling loop on the same long-poll cursor (W-1).
     */
    private sendHeartbeat;
    private handleIncomingMessage;
    /**
     * Extract displayable text content from a single message item. Text items
     * return their text directly; media items are downloaded and surfaced as
     * path markers that downstream agents can read.
     */
    private extractItemContent;
    private handleImageItem;
    private handleVoiceItem;
    private handleFileItem;
    private handleVideoItem;
    private getContextToken;
    private setContextToken;
    private cleanupProcessedMessages;
    /**
     * L14: drop expired context-token entries. The original implementation
     * only removed an entry on read (`getContextToken` checked TTL), so a
     * userId that messaged once and never came back left its row in the
     * Map indefinitely. Called from the polling loop at the same cadence
     * as cleanupProcessedMessages so memory stays bounded under big group
     * sizes / churning user populations.
     */
    private cleanupExpiredContextTokens;
    private loadCredentials;
    private saveCredentials;
    private splitMessage;
}
export declare const ilinkWeChatAdapter: ILinkWeChatAdapter;
//# sourceMappingURL=ilink-adapter.d.ts.map