export interface RemoteAgentsJsonOptions<T> {
    args: string[];
    noFanoutEnv: string;
    hosts?: string[];
    parse: (stdout: string, machine: string) => T[] | RemoteAgentsJsonParseResult<T>;
    /**
     * Suppress the per-device "unreachable — skipped" stderr line. The skipped
     * names still come back in {@link RemoteAgentsJsonResult.skipped}, so a caller
     * that fans out by DEFAULT can report them once, compactly, instead of
     * printing a line per offline box above its output. Never a silent drop.
     */
    quiet?: boolean;
    /** Per-peer deadline. Long-running maintenance commands override 12 seconds. */
    timeoutMs?: number;
    /**
     * Opt-in early-exit for a globally-unique lookup (a full session UUID). When a
     * peer returns an item that satisfies {@link isDefinitive}, the fan-out
     * resolves immediately and SIGTERMs every still-outstanding peer instead of
     * waiting for the slowest one to hit {@link REMOTE_TIMEOUT_MS}.
     *
     * OMITTED BY DEFAULT — tool-search, program-count, and the default session
     * listing keep the all-settle behavior (ambiguity, or a label/prefix conflict,
     * is only known once every peer has answered). Only the full-UUID resolve path
     * opts in, since only a UUID guarantees the first hit is the only hit.
     */
    earlyExit?: {
        isDefinitive: (item: T, machine: string) => boolean;
    };
}
/**
 * The SSH boundary as a swappable dependency so the fan-out logic is testable
 * without a live tailnet. Production wires this to the real {@link sshCapture}.
 */
export type SshCaptureFn = (target: string, remoteCmd: string, opts: {
    timeoutMs: number;
    signal?: AbortSignal;
    extraSshArgs?: string[];
}) => Promise<{
    code: number | null;
    stdout: string;
}>;
export interface GatherRemoteAgentsJsonDeps {
    capture?: SshCaptureFn;
}
export interface RemoteAgentsJsonParseResult<T> {
    items: T[];
    valid: boolean;
}
export interface RemoteAgentsJsonResult<T> {
    items: T[];
    deviceCount: number;
    /** Devices that were dialed but answered with an error / no CLI / a timeout. */
    skipped: string[];
    /** Devices that exited successfully but returned invalid JSON for this command. */
    parseFailed: string[];
    /** Whether automatic target discovery failed before any peer could be dialed. */
    discoveryFailed: boolean;
}
export declare function normalizeRemoteAgentsJsonParse<T>(parsed: T[] | RemoteAgentsJsonParseResult<T>): RemoteAgentsJsonParseResult<T>;
export declare function parseRemoteAgentsJsonPayload<T>(stdout: string, machine: string, parse: RemoteAgentsJsonOptions<T>['parse']): {
    items: T[];
    parseFailed: boolean;
};
/** Build the command one peer runs, with a guard that prevents recursive fan-out. */
export declare function remoteAgentsJsonCommand(args: string[], noFanoutEnv: string, os?: string): string;
/**
 * The subset of a spawned `ssh` child this capture loop drives. Structural so a
 * unit test can feed synthetic `data`/`close` events through a fake without a
 * live SSH connection.
 */
export interface CapturableChild {
    stdout: {
        on(event: 'data', listener: (chunk: Buffer) => void): unknown;
    } | null;
    on(event: 'error' | 'close', listener: (arg?: number | null) => void): unknown;
    kill(signal?: NodeJS.Signals): unknown;
}
/**
 * Stream one child's stdout into memory under a hard per-peer byte ceiling.
 *
 * A cross-machine fan-out awaits every peer's capture under one `Promise.all`,
 * so an unbounded buffer means a single runaway peer (a corrupt or
 * pathologically large payload) exhausts the caller's heap and takes the whole
 * sweep down — RUSH-2065. Once the accumulated bytes would exceed
 * {@link REMOTE_STDOUT_MAX_BYTES}, the child is SIGKILLed and the capture settles
 * as `code: null` (unreachable) rather than trust a truncated body. A definitive
 * early-exit `signal` SIGTERMs the child the same way, and the timer is the
 * per-peer deadline.
 */
export declare function captureBoundedStdout(child: CapturableChild, { timeoutMs, signal }: {
    timeoutMs: number;
    signal?: AbortSignal;
}): Promise<{
    code: number | null;
    stdout: string;
}>;
/** Query explicit hosts, or every registered online peer when hosts is omitted. */
export declare function gatherRemoteAgentsJson<T>(options: RemoteAgentsJsonOptions<T>, deps?: GatherRemoteAgentsJsonDeps): Promise<RemoteAgentsJsonResult<T>>;
