/**
 * Cloud Client Service
 *
 * Singleton service responsible for all interactions with CrewlyAI Cloud.
 * Handles authentication, premium template fetching, and subscription
 * status synchronization.
 *
 * Premium templates are loaded into memory only — never written to disk
 * to prevent IP leakage.
 *
 * @module services/cloud/cloud-client.service
 */
import { type CloudTier, type CloudConnectionStatus } from '../../constants.js';
/**
 * Persisted cloud config stored at ~/.crewly/cloud/config.json.
 * Enables auto-reconnect on backend restart.
 */
export interface PersistedCloudConfig {
    cloudUrl: string;
    token: string;
    tier: string;
    connectedAt: string;
    /** Refresh token for auto-renewing expired access tokens */
    refreshToken?: string;
    /**
     * Relay-signed access JWT (distinct from the access `token`). Persisted so
     * the BrowserProxy can re-register on backend restart without waiting for a
     * fresh validate round-trip. Never the Google/Supabase token — see the
     * RELAY-TOKEN-TYPE invariant in the long-term browser-relay fix design.
     */
    relayToken?: string;
}
/**
 * Decode the `exp` (expiry, seconds since epoch) claim from a JWT without
 * verifying its signature. Returns null when the token is malformed or has
 * no `exp`. Used to schedule proactive relay-token refresh before expiry so
 * a continuously-open relay socket never carries an expired token.
 *
 * @param token - JWT string (may be null)
 * @returns The `exp` claim in seconds, or null when unavailable
 */
export declare function decodeJwtExp(token: string | null): number | null;
/** Summary of a premium template returned by the cloud listing endpoint. */
export interface CloudTemplateSummary {
    /** Unique template identifier */
    id: string;
    /** Human-readable template name */
    name: string;
    /** Short description */
    description: string;
    /** Minimum subscription tier required */
    requiredTier: CloudTier;
    /** Category tag (e.g. "dev-team", "marketing") */
    category: string;
}
/** Full detail for a single premium template (in-memory only). */
export interface CloudTemplateDetail {
    /** Unique template identifier */
    id: string;
    /** Human-readable template name */
    name: string;
    /** Full description */
    description: string;
    /** Minimum subscription tier required */
    requiredTier: CloudTier;
    /** Category tag */
    category: string;
    /** Team member role definitions */
    roles: Array<{
        role: string;
        prompt: string;
    }>;
    /** Task orchestration config */
    orchestration: Record<string, unknown>;
}
/** A relay device returned by the Cloud devices API. */
export interface CloudRelayDevice {
    /** Device/session ID */
    sessionId: string;
    /** Device role */
    role: 'orchestrator' | 'agent';
    /** Device state */
    state: 'waiting' | 'paired' | 'disconnected';
    /** Paired peer device ID */
    pairedWith: string | null;
    /** ISO registration timestamp */
    registeredAt: string;
    /** ISO last heartbeat timestamp */
    lastHeartbeatAt: string;
    /** Human-readable device name (legacy field) */
    name?: string;
    /** Human-readable device name returned by Cloud API */
    deviceName?: string;
    /** Unique device identifier */
    deviceId?: string;
}
/** Current cloud connection state exposed by getStatus(). */
export interface CloudStatus {
    /** Whether the client is currently connected */
    connectionStatus: CloudConnectionStatus;
    /** Cloud API base URL (set after connect) */
    cloudUrl: string | null;
    /** Current subscription tier */
    tier: CloudTier;
    /** ISO timestamp of last successful sync */
    lastSyncAt: string | null;
}
/**
 * CloudClientService singleton.
 *
 * Manages the lifecycle of the connection between a local Crewly instance
 * and CrewlyAI Cloud. All cloud API calls are made via native fetch with
 * bearer-token authentication.
 */
export declare class CloudClientService {
    private static instance;
    private readonly logger;
    /** Cloud API base URL (e.g. "https://api.crewlyai.com") */
    private cloudUrl;
    /** Bearer token obtained during connect() */
    private token;
    /** Refresh token for auto-renewing expired access tokens */
    private refreshToken;
    /** Current connection status */
    private connectionStatus;
    /** Subscription tier reported by cloud */
    private tier;
    /** Timestamp of the most recent successful cloud API call */
    private lastSyncAt;
    /** Timer for proactive token refresh (fires 5 min before expiry) */
    private refreshTimer;
    /** Guard to prevent concurrent refresh attempts */
    private refreshInProgress;
    /** Callbacks invoked when the access token is refreshed */
    private tokenRefreshCallbacks;
    /**
     * Relay-signed access JWT used by BrowserProxyService to register with the
     * Cloud Relay as role 'agent'. First-class, stored credential — distinct
     * from the access `token` and decoupled from socket lifetime. NEVER the
     * Google/Supabase access token (RELAY-TOKEN-TYPE invariant).
     */
    private relayToken;
    /** Parsed `exp` (seconds) of {@link relayToken}, for proactive refresh. */
    private relayTokenExp;
    /** Timer for proactive relay-token refresh (fires SKEW before exp). */
    private relayRefreshTimer;
    /** Callbacks invoked when the relay token is refreshed (distinct channel). */
    private relayTokenRefreshCallbacks;
    private constructor();
    /**
     * Get the singleton instance.
     *
     * @returns CloudClientService instance
     */
    static getInstance(): CloudClientService;
    /**
     * Reset the singleton (for testing).
     */
    static resetInstance(): void;
    /**
     * Connect to CrewlyAI Cloud by verifying the provided token.
     *
     * Calls the cloud auth endpoint to validate credentials and retrieve
     * the subscription tier. On success the service transitions to
     * "connected" status.
     *
     * @param cloudUrl - Base URL of the CrewlyAI Cloud API
     * @param token - Authentication token (API key or JWT)
     * @returns Object with connection result
     * @throws Error when the auth request fails or token is invalid
     *
     * @example
     * ```ts
     * const client = CloudClientService.getInstance();
     * await client.connect('https://api.crewlyai.com', 'sk-abc123');
     * ```
     */
    connect(cloudUrl: string, token: string, refreshToken?: string): Promise<{
        success: boolean;
        tier: CloudTier;
    }>;
    /**
     * Connect using a locally verified JWT (no remote API call needed).
     *
     * Used when the JWT was issued by this same instance or the JWT secret
     * is shared between OSS and Cloud. Avoids the round-trip to the cloud
     * auth endpoint.
     *
     * @param cloudUrl - Base URL of the CrewlyAI Cloud API
     * @param token - JWT access token (already verified locally)
     * @param tier - Subscription tier extracted from the JWT payload
     * @param refreshToken - Optional refresh token for auto-renewal
     */
    connectLocal(cloudUrl: string, token: string, tier: CloudTier, refreshToken?: string): void;
    /**
     * Disconnect from CrewlyAI Cloud.
     *
     * Clears stored credentials and resets the connection state.
     */
    disconnect(): void;
    /**
     * Path to the persisted cloud config file.
     */
    static getConfigPath(): string;
    /**
     * Load persisted cloud config from disk.
     * Returns null if file doesn't exist or is invalid.
     */
    loadPersistedConfig(): Promise<PersistedCloudConfig | null>;
    /**
     * Persist current cloud connection config to disk for auto-reconnect.
     */
    private persistConfig;
    /**
     * Remove persisted cloud config from disk (on disconnect).
     */
    private removePersistedConfig;
    /**
     * Fetch the list of premium templates available on CrewlyAI Cloud.
     *
     * Requires an active cloud connection.
     *
     * @returns Array of template summaries
     * @throws Error when not connected or fetch fails
     *
     * @example
     * ```ts
     * const templates = await client.getTemplates();
     * console.log(templates.map(t => t.name));
     * ```
     */
    getTemplates(): Promise<CloudTemplateSummary[]>;
    /**
     * Fetch full detail for a single premium template.
     *
     * The returned data is held in memory only and must never be
     * persisted to disk.
     *
     * @param id - Template identifier
     * @returns Template detail object
     * @throws Error when not connected, template not found, or fetch fails
     *
     * @example
     * ```ts
     * const detail = await client.getTemplateDetail('tpl-tiktok-ops');
     * ```
     */
    getTemplateDetail(id: string): Promise<CloudTemplateDetail>;
    /**
     * Get the stored cloud API base URL (set during connect).
     *
     * @returns Cloud URL or null if not connected
     */
    getCloudUrl(): string | null;
    /**
     * Get the current cloud connection status and subscription tier.
     *
     * @returns Current status snapshot
     */
    getStatus(): CloudStatus;
    /**
     * Check whether the client is currently connected to cloud.
     *
     * @returns true if connected
     */
    isConnected(): boolean;
    /**
     * Check whether the cloud token has expired (401/403 from cloud API).
     *
     * @returns true if the token has expired
     */
    isTokenExpired(): boolean;
    /**
     * Get the current subscription tier.
     *
     * @returns Current tier value
     */
    getTier(): CloudTier;
    /**
     * Fetch the list of devices registered to this user from Cloud.
     *
     * Proxies GET /api/v1/relay/devices on crewlyai.com and returns
     * the device list for the authenticated user.
     *
     * @returns Array of cloud relay devices
     * @throws Error when not connected or fetch fails
     */
    fetchCloudDevices(): Promise<CloudRelayDevice[]>;
    /**
     * Set the refresh token for auto-renewal.
     *
     * Called by the connect controller after OAuth login provides a refresh token.
     *
     * @param refreshToken - Refresh token string
     */
    setRefreshToken(refreshToken: string): void;
    /**
     * Get the current access token (for CloudSyncService token updates).
     *
     * @returns Current access token or null
     */
    getToken(): string | null;
    /**
     * Register a callback to be invoked whenever the access token is refreshed.
     * Used by BrowserProxyService to update its relay auth token in real-time.
     *
     * @param callback - Function receiving the new access token string
     */
    onTokenRefresh(callback: (newToken: string) => void): void;
    /**
     * Get the current relay-signed token (for BrowserProxyService registration).
     *
     * This is DISTINCT from {@link getToken} (the access/HTTP token). The
     * BrowserProxy must register with the relay token, never the access token —
     * see the RELAY-TOKEN-TYPE invariant. Returns null until a relay token has
     * been minted by the Cloud validate/refresh endpoint.
     *
     * @returns Current relay token or null
     */
    getRelayToken(): string | null;
    /**
     * Register a callback invoked whenever the relay token is refreshed.
     *
     * Distinct subscription channel from {@link onTokenRefresh}: subscribers
     * here (BrowserProxyService) receive the relay-signed token, never the
     * access token. Decoupling the channels prevents the proxy from ever being
     * fed the wrong token type on refresh.
     *
     * @param callback - Function receiving the new relay token string
     */
    onRelayTokenRefresh(callback: (newRelayToken: string) => void): void;
    /**
     * Store a freshly-minted relay token as a first-class credential, parse its
     * expiry, schedule proactive refresh, persist it, and notify subscribers.
     *
     * Centralizes relay-token handling so every code path that obtains one
     * (connect, refresh, validate) treats it identically. Persistence is
     * fire-and-forget; a persist failure must not break the refresh chain.
     *
     * @param relayToken - The relay-signed access JWT from Cloud
     */
    private storeRelayToken;
    /**
     * Attempt to refresh the access token using the stored refresh token.
     *
     * Issues a new access token locally (since both access and refresh tokens
     * are signed with the same HMAC secret on this OSS instance).
     *
     * @returns true if refresh succeeded, false if no refresh token or refresh failed
     */
    tryRefreshToken(): Promise<boolean>;
    /**
     * Schedule a proactive token refresh 5 minutes before expiry.
     *
     * Parses the JWT `exp` claim and sets a timer. If the token has
     * less than 5 minutes remaining, refreshes immediately.
     *
     * @param token - JWT access token to extract expiry from
     */
    private scheduleTokenRefresh;
    /**
     * Schedule a proactive relay-token refresh `RELAY_REFRESH_SKEW_S` seconds
     * before the relay token's real `exp`.
     *
     * The relay token (~60min TTL) is decoupled from the access token, so it
     * needs its own refresh schedule. When the timer fires it calls
     * {@link fetchRelayTokenFromValidate}, which re-mints a relay token and
     * stores it (re-arming this timer). This keeps a continuously-open relay
     * socket from ever carrying an expired token — the DURABLE-CREDENTIAL
     * invariant. Driven by the JWT `exp` claim, not a wall-clock heuristic.
     */
    private scheduleRelayTokenRefresh;
    /**
     * Fetch relay token by calling Cloud validate endpoint.
     * Used after connectLocal() to get a Cloud-signed relay JWT
     * without blocking the connection flow.
     *
     * @returns Promise that resolves when relay token is fetched (or skipped)
     */
    private fetchRelayTokenFromValidate;
    /**
     * Throw if the client is not in a connected state.
     *
     * @throws Error when not connected
     */
    private ensureConnected;
    /**
     * Build the standard authorization headers for cloud API requests.
     *
     * @returns Headers object with Authorization and Content-Type
     */
    private authHeaders;
    /**
     * Check if an HTTP status code indicates an authentication/authorization failure.
     *
     * @param status - HTTP status code
     * @returns true if the status is 401 or 403
     */
    private isAuthError;
    /**
     * Handle a 401/403 response from the cloud API by transitioning
     * the connection status to TOKEN_EXPIRED. This signals the frontend
     * to show a reconnect prompt instead of a raw error.
     *
     * @param context - Description of the failed operation (for logging)
     * @param status - HTTP status code from the cloud API
     */
    private handleAuthFailure;
}
//# sourceMappingURL=cloud-client.service.d.ts.map