import { type Computer } from "./computer-identity.js";
import { type HookPeer } from "./peers.js";
import { type Json } from "./protocol.js";
import type { SetName } from "./conductor-role.js";
/**
 * Linked computer sets (docs/conductor-sets.md). A link runs both ways when
 * each computer's hooks.yaml lists the other; a set is the computers joined by
 * such links. This Hook sees its set from itself and one hop: each peer
 * answers `GET /v1/conductor` with its live conductor, its own peers, whether
 * it lists the caller back and the set name it holds. A set has one conductor.
 */
type Ask = (peer: HookPeer, route: string, data?: Json, timeout?: number) => Promise<Json>;
/** What this computer tells a peer about itself, so the peer can say whether it links back. */
export interface Caller {
    name: string;
    hostKey?: string;
}
export declare function localCaller(): Promise<Caller>;
export declare function callerQuery(caller: Caller): string;
/** One peer's answer to `GET /v1/conductor`, or why it gave none. */
export type PeerAnswer = {
    peer: HookPeer;
} & ({
    ok: true;
    id?: string;
    names: string[];
    conductor?: Json;
    /** Its hooks.yaml names; absent from a Hook older than sets. */
    peers?: string[];
    /** Whether it lists this computer back; absent when its Hook cannot say. */
    knowsCaller?: boolean;
    set?: SetName;
} | {
    ok: false;
    error: string;
    code?: string;
    /** Its conductor module is off, so it cannot run a conductor. */
    disabled?: boolean;
});
export declare function askPeers(peers: readonly HookPeer[], caller: Caller, ask?: Ask): Promise<PeerAnswer[]>;
export interface GroupConductor {
    /** A live conductor on a member of this computer's set. */
    found?: {
        computer: string;
        target?: Json;
    };
    /** Members that could not say, so a conductor there cannot be ruled out. */
    unchecked: {
        computer: string;
        error: string;
        code?: string;
    }[];
}
/** The names members report that are neither this computer nor one of its
 * peers: computers in the set that this Hook cannot ask directly. */
export declare function indirectMembers(answers: readonly PeerAnswer[], localNames: readonly string[]): string[];
export declare const linkHint: (name: string) => string;
export declare const oneWayHint: (name: string) => string;
/** One conductor per set: a live conductor on any member, and the members that could not say. */
export declare function setConductor(answers: readonly PeerAnswer[], localNames: readonly string[]): GroupConductor;
export declare function groupConductor(peers: readonly HookPeer[], localNames: readonly string[], ask?: Ask, caller?: Caller): Promise<GroupConductor>;
export interface SetComputer {
    name: string;
    id?: string;
    local?: true;
    /** Whether its Hook answered just now; absent when this Hook cannot ask it. */
    reachable?: boolean;
    link: "self" | "two-way" | "one-way" | "indirect" | "unknown";
    conductor?: Json;
    error?: string;
    code?: string;
    hint?: string;
}
export interface ComputerSet {
    id: string;
    name?: string;
    namedAt?: string;
    /** This computer's own set. */
    local: boolean;
    computers: SetComputer[];
    /** The set's conductor; with `conductors` above 1, the first of several. */
    conductor?: {
        computer: string;
        target?: Json;
    };
    conductors: number;
}
/**
 * Every set this Hook can see: its own (itself, its two-way and not yet known
 * peers, and computers they link that this Hook does not), then one set per
 * one-way peer. `unlinked` are computers the store knows with no link here.
 */
export declare function buildSets(input: {
    local: {
        name: string;
        id?: string;
        conductor?: Json;
        set?: SetName;
        names: readonly string[];
    };
    answers: readonly PeerAnswer[];
    computers: readonly Computer[];
    /** Identity rows from peers, used only to recognize names in their set reports. */
    reportedComputers?: readonly Pick<Computer, "id" | "name" | "aliases">[];
}): {
    sets: ComputerSet[];
    unlinked: Computer[];
};
export {};
