import type { ConductorSuccessionService } from "./conductor-succession.js";
import { z } from "zod";
import { moveToSchema } from "./dispatch.js";
import { type HarnessInventory } from "./harnesses.js";
import { type Json, type Provider, type StartingTarget, type Target } from "./protocol.js";
import type { TerminalProvider } from "./terminal.js";
export { moveToSchema };
export type MoveTo = z.infer<typeof moveToSchema>;
export declare const moveRequestSchema: 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>;
    to: z.ZodObject<{
        computer: z.ZodOptional<z.ZodString>;
        harness: z.ZodEnum<{
            claude: "claude";
            codex: "codex";
            copilot: "copilot";
            opencode: "opencode";
        }>;
        account: z.ZodOptional<z.ZodString>;
        model: z.ZodOptional<z.ZodString>;
        effort: z.ZodOptional<z.ZodEnum<{
            high: "high";
            low: "low";
            max: "max";
            medium: "medium";
            minimal: "minimal";
            xhigh: "xhigh";
        }>>;
    }, z.core.$strict>;
    mode: z.ZodDefault<z.ZodEnum<{
        "new-chat": "new-chat";
        replace: "replace";
    }>>;
    id: z.ZodOptional<z.ZodString>;
    handoffTimeoutMs: z.ZodOptional<z.ZodNumber>;
}, z.core.$strict>;
declare const moveRecordSchema: z.ZodObject<{
    id: z.ZodString;
    state: z.ZodEnum<{
        exiting: "exiting";
        failed: "failed";
        "handing-off": "handing-off";
        launching: "launching";
        linking: "linking";
        moved: "moved";
        uncertain: "uncertain";
    }>;
    createdAt: z.ZodString;
    updatedAt: z.ZodString;
    from: 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>;
        account: z.ZodOptional<z.ZodString>;
        label: z.ZodOptional<z.ZodString>;
    }, z.core.$strict>;
    to: z.ZodObject<{
        computer: z.ZodOptional<z.ZodString>;
        harness: z.ZodEnum<{
            claude: "claude";
            codex: "codex";
            copilot: "copilot";
            opencode: "opencode";
        }>;
        account: z.ZodOptional<z.ZodString>;
        model: z.ZodOptional<z.ZodString>;
        effort: z.ZodOptional<z.ZodEnum<{
            high: "high";
            low: "low";
            max: "max";
            medium: "medium";
            minimal: "minimal";
            xhigh: "xhigh";
        }>>;
    }, z.core.$strict>;
    computerFingerprint: z.ZodOptional<z.ZodString>;
    computerId: z.ZodOptional<z.ZodString>;
    accountChoice: z.ZodOptional<z.ZodString>;
    project: z.ZodOptional<z.ZodString>;
    mode: z.ZodOptional<z.ZodEnum<{
        "new-chat": "new-chat";
        replace: "replace";
    }>>;
    modeForced: z.ZodOptional<z.ZodLiteral<"conductor">>;
    handedOffTo: z.ZodOptional<z.ZodObject<{
        computer: z.ZodOptional<z.ZodString>;
        target: z.ZodUnion<readonly [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>, 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";
            }>;
            starting: z.ZodLiteral<true>;
            startingToken: z.ZodString;
        }, z.core.$strip>]>;
    }, z.core.$strict>>;
    handedOffFrom: z.ZodOptional<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>;
        title: z.ZodString;
    }, z.core.$strict>>;
    cwd: z.ZodString;
    dispatch: z.ZodOptional<z.ZodString>;
    workerDispatch: z.ZodOptional<z.ZodString>;
    handoff: z.ZodOptional<z.ZodObject<{
        path: z.ZodString;
        source: z.ZodEnum<{
            agent: "agent";
            fallback: "fallback";
        }>;
        reason: z.ZodOptional<z.ZodString>;
        chars: z.ZodNumber;
    }, z.core.$strict>>;
    exit: z.ZodOptional<z.ZodEnum<{
        clean: "clean";
        interrupted: "interrupted";
        killed: "killed";
    }>>;
    placement: z.ZodOptional<z.ZodEnum<{
        "adjacent-pane": "adjacent-pane";
        peer: "peer";
        "same-pane": "same-pane";
    }>>;
    target: z.ZodOptional<z.ZodUnion<readonly [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>, 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";
        }>;
        starting: z.ZodLiteral<true>;
        startingToken: z.ZodString;
    }, z.core.$strip>]>>;
    paneTarget: 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";
        }>;
    }, z.core.$strip>>;
    linkPending: z.ZodOptional<z.ZodBoolean>;
    notice: z.ZodOptional<z.ZodString>;
    movedAt: z.ZodOptional<z.ZodString>;
    error: z.ZodOptional<z.ZodString>;
    recovery: z.ZodOptional<z.ZodObject<{
        attempts: z.ZodNumber;
        nextAt: z.ZodString;
    }, z.core.$strict>>;
}, z.core.$strict>;
export type MoveRecord = z.infer<typeof moveRecordSchema>;
/** What a dispatching Hook records on its receipt when its worker moved. */
export interface MovedWorker {
    id: string;
    at: string;
    handoff?: string;
    computerFingerprint?: string;
    computerId?: string;
    from: {
        harness: Provider;
        account?: string;
    };
    to: MoveTo;
    target: Target | StartingTarget;
}
export declare function movesRoot(): string;
/** The hand-off sits beside the new agent's brief, in a folder Claude is given read access to. */
export declare const handoffPath: (id: string) => string;
export declare function readMove(id: string): Promise<MoveRecord | undefined>;
/** Recent moves, newest first; old ones are removed on the way. */
export declare function listMoves(now?: number): Promise<MoveRecord[]>;
/** The move that took the agent out of `target`'s pane: a target with a
 * conversation matches only that conversation; a starting one, the pane. */
export declare function moveFrom(records: readonly MoveRecord[], target: {
    server: string;
    pane: string;
    source: string;
    session?: string;
}): MoveRecord | undefined;
/** Conversation-bound annotations shared by tab and pane overview rows. */
export declare function moveSessionFields(records: readonly MoveRecord[], target: Target, title?: string): Json;
/** The receipt fields for a finished move. */
export declare function movedWorker(record: MoveRecord): MovedWorker | undefined;
/** A harness as people name it, with its account and model: "Claude (work, opus)". */
export declare function harnessName(to: {
    harness: string;
    account?: string;
    model?: string;
    effort?: string;
}): string;
/** What the moving agent is asked to write. */
export declare function handoffRequest(id: string, to: MoveTo, mode?: "replace" | "new-chat"): string;
/** The hand-off between the markers in the agent's replies after the request,
 * or undefined while its end marker has not arrived. Code fences around the
 * block are dropped. */
export declare function extractHandoff(replies: readonly string[], id: string): string | undefined;
/** One message from a conversation's tail. */
export interface TailEntry {
    role: "owner" | "agent";
    text: string;
}
/** The owner's prompts and the agent's replies in a transcript's lines, oldest first. */
export declare function conversationEntries(lines: readonly string[], source: Provider): TailEntry[];
/** The agent's replies after the move's request: the request names the move, so an older hand-off never counts. */
export declare function repliesAfterRequest(entries: readonly TailEntry[], id: string): string[];
/** What `git` shows in the checkout at the move. */
export interface GitState {
    root: string;
    branch?: string;
    head?: string;
    upstream?: string;
    ahead?: number;
    behind?: number;
    /** `git status --porcelain` lines: every change, tracked or not. */
    changes: string[];
}
export declare function readGitState(directory: string): Promise<GitState | undefined>;
/** The commands of every process below `pids` (the agent's own children), not the agent itself. */
export declare function processesBelow(pids: readonly number[]): Promise<string[]>;
/** What Phren itself saw at the move, appended to every hand-off. */
export declare function observedState(git: GitState | undefined, processes: readonly string[], processCommands?: boolean): string;
/** A hand-off built without the agent: the conversation's tail, the original brief and the git state. */
export declare function fallbackHandoff(input: {
    reason: string;
    from: string;
    entries: readonly TailEntry[];
    original?: string;
    dispatch?: string;
    label?: string;
}): string;
/** The hand-off file: who moved where and when, the body, then what Phren saw. */
export declare function handoffDocument(record: MoveRecord, body: string, observed: string, at: string, conductor?: boolean): string;
/** The new agent's first prompt: the whole hand-off when it fits the brief, else where to read it. */
export declare function continuePrompt(document: string, file: string): string;
export interface MoverDeps {
    succession?: ConductorSuccessionService;
    snapshot: (server: string) => Promise<Json>;
    /** The conversation the pane runs now. */
    identity: (server: string, pane: Json) => Promise<string | undefined>;
    terminal: Pick<TerminalProvider, "prompt" | "sendKeys" | "processes" | "closePane">;
    /** The `hand_off` delivery path: queued while the agent is busy. */
    deliver: (target: Target, text: string, deliveryId: string) => Promise<Json>;
    /** Starts the new agent (`startSession`), in `into` when given. */
    launch: (server: string, data: Json, options: {
        into?: {
            workspaceId: string;
            tabId: string;
            paneId: string;
        };
        dispatchId?: string;
    }) => Promise<Json>;
    inventory: () => Promise<HarnessInventory | undefined>;
    /** The conversation's transcript lines, its tail is enough. */
    transcript: (target: Target) => Promise<string[]>;
    git?: (directory: string) => Promise<GitState | undefined>;
    processesBelow?: (pids: readonly number[]) => Promise<string[]>;
    /** The Claude account the pane runs under, when known. */
    paneAccount?: (server: string, pane: Json) => string | undefined;
    /** The dispatch the pane's agent was launched for. */
    paneDispatch?: (server: string, pane: Json) => Promise<string | undefined>;
    /** The text of a brief this computer wrote. */
    brief?: (id: string) => Promise<string | undefined>;
    /** Whether the pane holds this computer's conductor. */
    isConductor?: (server: string, pane: Json) => Promise<boolean>;
    /** Herdr gives a pane its variables only when it is created; tmux sets them on every start. */
    envAtStart?: (server: string) => boolean;
    /** Cleanup after the old agent exited (a Codex pane's app-server). */
    afterExit?: (server: string, pane: string) => Promise<void>;
    kill?: (pid: number, signal: NodeJS.Signals) => void;
    now?: () => number;
    sleep?: (ms: number) => Promise<void>;
    pollMs?: number;
    /** How long a clean exit, then an interrupt, may take before the agent counts as hung. */
    exitMs?: number;
}
/** Runs moves on the computer that runs the session. A move outlives the
 * request that started it (the Hook answers in seconds); its record says where it is. */
export declare class SessionMover {
    private readonly deps;
    private readonly cancelled;
    private readonly admissions;
    private readonly running;
    constructor(deps: MoverDeps);
    private get now();
    private sleep;
    private get poll();
    /** Checks the move can happen, records it and starts it. Refuses before anything is typed. */
    start(input: unknown, caller?: {
        owner?: boolean;
    }): Promise<MoveRecord>;
    private admit;
    /** For tests: the move under way in a pane, until it settles. */
    settled(server: string, pane: string): Promise<void> | undefined;
    private update;
    private run;
    abort(id: string): Promise<MoveRecord>;
    private assertNotAborted;
    private continueOnPeer;
    /** Startup and tick recovery reuse the receiving Hook's durable move id.
     * No fresh id, brief or pane is created after an uncertain launch. */
    reconcile(): Promise<void>;
    /** An ordinary move never acquires permission to stop a conductor merely
     * because the owner promoted its source while the hand-off was running. */
    private checkPromotion;
    /** Uses the same durable prompt path as the hand-off and its first brief. */
    private conductorNotice;
    /** The agent's own hand-off, or why there is none. Fails only when the session itself went away. */
    private askForHandoff;
    private fallback;
    /** Ends the old agent with its own exit command; an interrupt, then a kill, only when it hangs. */
    private exit;
    /** Starts the target in the old pane when its shell has what the target needs, else in a new tab beside it. */
    private relaunch;
    /** New chats remain open as linking while the harness establishes its conversation. */
    private newTarget;
}
/** The last `bytes` of a transcript as lines, the first (cut) one dropped. */
export declare function transcriptTail(file: string, bytes?: number): Promise<string[]>;
