/**
 * Aggregated cross-deployment roster (HUB side): the hub's own local bots
 * ([[team-roster]]) merged with every member deployment's advertised bots
 * ([[federation-store]]), each tagged with the deployment it belongs to so the
 * UI can group by deployment (local first, then remote by name).
 *
 * Pure read from `{dataDir}` files — testable, no Lark API.
 */
import { type LiveBot } from './team-roster.js';
/** A federated deployment is considered stale (likely offline) if it hasn't
 *  synced within this window — its bots are flagged so the UI can de-emphasize them. */
export declare const FEDERATION_STALE_MS: number;
export interface AggregatedRosterBot {
    larkAppId: string;
    name: string;
    cliId: string;
    capability: string | null;
    hasTeamRole: boolean;
    /** Tenant-stable bot id (kept now so P2 拉群 by union_id needs no schema change). */
    botUnionId?: string;
    /** Owner (person) of this bot — union_id is tenant-stable, used to pull the
     *  owner into a federated group regardless of app scope. */
    owner?: {
        unionId?: string;
        name?: string;
    };
    deployment: {
        id: string;
        name: string;
        local: boolean;
        stale: boolean;
    };
}
export interface AggregatedDeployment {
    id: string;
    name: string;
    local: boolean;
    botCount: number;
    lastSeenAt?: number;
    /** true when a remote deployment hasn't synced within FEDERATION_STALE_MS. */
    stale: boolean;
}
export interface AggregatedRoster {
    team: {
        id: string;
        name: string;
        memberCount: number;
    };
    deployments: AggregatedDeployment[];
    bots: AggregatedRosterBot[];
}
/** Hub's local bots + all member deployments' bots, tagged + grouped by deployment. */
export declare function buildFederatedRoster(dataDir: string, teamId?: string, configOrder?: string[], now?: number, liveBots?: LiveBot[]): AggregatedRoster;
//# sourceMappingURL=federation-roster.d.ts.map