import { z } from "zod";
import { type Json, type Target } from "./protocol.js";
export declare const queuedHandOffSchema: z.ZodObject<{
    target: z.ZodObject<{
        server: z.ZodString;
        workspace: z.ZodString;
        tab: z.ZodString;
        pane: z.ZodString;
        source: z.ZodEnum<{
            claude: "claude";
            codex: "codex";
            copilot: "copilot";
            opencode: "opencode";
            phren: "phren";
        }>;
        session: z.ZodUnion<readonly [z.ZodString, z.ZodString]>;
    }, z.core.$strip>;
    text: z.ZodString;
    deliveryId: z.ZodOptional<z.ZodString>;
    origin: z.ZodOptional<z.ZodObject<{
        server: z.ZodString;
        workspace: z.ZodString;
        tab: z.ZodString;
        pane: z.ZodString;
        source: z.ZodEnum<{
            claude: "claude";
            codex: "codex";
            copilot: "copilot";
            opencode: "opencode";
            phren: "phren";
        }>;
        session: z.ZodUnion<readonly [z.ZodString, z.ZodString]>;
    }, z.core.$strip>>;
    originComputer: z.ZodOptional<z.ZodString>;
}, z.core.$strict>;
export interface QueueOptions {
    validate: (target: Target) => Promise<Json>;
    send: (target: Target, text: string, deliveryId: string, typing: () => Promise<void>) => Promise<Json>;
    notify?: (target: Target, text: string, deliveryId: string, computer: string) => Promise<Json>;
    now?: () => number;
    root?: string;
}
/** Settled rows (and notice tombstones) are kept this long, so a late retry of
 * an old delivery id still replays instead of typing again. */
export declare const HAND_OFF_RETENTION_MS: number;
/** At most this many rows stay on disk; the oldest settled rows go first. */
export declare const HAND_OFF_MAX_ROWS = 512;
/** A durable outbox on the receiving Hook. Persist 'attempting' before input,
 * so a crash in the input/ack gap recovers as uncertain, never as a retry.
 * Tombstones are retained for HAND_OFF_RETENTION_MS, so a retried delivery id
 * replays instead of typing a second time; a queued or attempting row is never
 * pruned. The sweep runs on enqueue and at most daily from tick(). */
export declare class HandOffQueue {
    private options;
    private pending;
    private root;
    private now;
    private lastPrune;
    private ticking?;
    constructor(options: QueueOptions);
    private serial;
    private file;
    private save;
    private read;
    private rows;
    /** Drops settled rows past retention, then the oldest settled rows over the
     * cap (those still owing their sender a notice last). Returns what is kept. */
    private prune;
    private reply;
    enqueue(input: unknown): Promise<Json>;
    status(id: string, target: Target): Promise<Json>;
    private attempt;
    /** Coalesced: the Hook calls this every 5 s whether or not the last tick
     * finished, and queuing each behind the lock would hold every enqueue and
     * status behind a backlog that grows faster than a slow tick drains it. */
    tick(): Promise<void>;
    private sweep;
    private noticeId;
    /** Hold enqueues and delivery while the Hook validates and closes a worker.
     * A new hand-off cannot be accepted between the pending check and closure. */
    whenNoPending(target: Target, close: () => Promise<Json>): Promise<Json>;
    hasPending(target: Target): Promise<boolean>;
}
