/**
 * `agents sessions focus [id]` — take me to a live session, however it's reachable.
 *
 * Same detection as `go`, but where `go` *refuses* an un-attachable session,
 * `focus` **opens a new tab and resumes it** — locally, or on the remote over SSH
 * (via the terminal launch engine's `openSurfaces`, `host` = the peer). So:
 *   - in tmux (local/remote)   -> attach the live pane (join it, no fork)
 *   - in Ghostty               -> focus its tab
 *   - headless / plain / etc.  -> new tab + `resume` (a copy if it's mid-run — the
 *                                  original keeps going; a clean continue if it's idle)
 *
 * NOTE: joining a live process without forking is only possible via tmux — that's
 * why `--tmux`-wrapped launches are worth it for sessions you'll want back live.
 */
import type { Command } from 'commander';
import { probeAttachRail, type AttachRailLiveness, type UnreachableFallback } from './go.js';
import { type ActiveSession } from '../lib/session/active.js';
import { type SessionMeta } from '../lib/session/types.js';
export { looksLikeTmuxAlias, resolveTmuxAliasState, shouldAttachLocalTmuxAliasBeforeFleet, type TmuxAliasState } from '../lib/session/local-tmux-attach.js';
import { type LiveStatusFilter } from './sessions.js';
import { openSurfaces, type Backend } from '../lib/terminal/index.js';
/** Options for `sessions focus` — device scope + the `--active` live-state filters. */
export interface FocusOptions {
    /**
     * Resolve the target from the launcher's AGENT_LAUNCH_ID instead of a session
     * id (RUSH-3125).
     *
     * A `--device` launcher mints this id BEFORE it opens the connection and
     * forwards it, so it is the one handle that is still known after the link
     * dies. A session id is not: only Claude is handed one up front, and every
     * other harness's real id had to be read back off the peer — over the very
     * link that just dropped — which is why a blink left a Grok or Codex tab with
     * nothing to reconnect to. The lookup runs HERE, on the box that owns the hook
     * records, so it needs no network at the moment it is needed most.
     */
    launchId?: string;
    local?: boolean;
    attachOnly?: boolean;
    device?: string[];
    active?: boolean;
    agent?: string;
    claude?: boolean;
    codex?: boolean;
    kimi?: boolean;
    antigravity?: boolean;
    grok?: boolean;
    opencode?: boolean;
    all?: boolean;
    teams?: boolean;
    inTeam?: string;
    routine?: boolean;
    project?: string;
    skill?: string;
    plugin?: string;
    since?: string;
    until?: string;
    limit?: string;
    bookmarks?: boolean;
    unmanaged?: boolean;
    sort?: string;
    working?: boolean;
    idle?: boolean;
    waiting?: boolean;
    orphan?: boolean;
    orphaned?: boolean;
    crashed?: boolean;
    closed?: boolean;
    abandoned?: boolean;
    queued?: boolean;
    unknown?: boolean;
    reconnectReattach?: boolean;
}
/** Commander gives overlapping `sessions` flags to the parent command, even
 * when they appear after `focus`. Fold only values explicitly provided there
 * into the child options; child defaults (limit/sort) otherwise stay intact. */
export declare function inheritFocusOptions(child: FocusOptions, parent?: Command): FocusOptions;
/** Collect device targets from `--device`; repeatable. Returns a host list. */
export declare function mergeFocusHosts(opts: FocusOptions): string[];
/** Picker header that reflects the active filter + device, e.g. "Focus orphaned sessions on yosemite-s0:". */
export declare function focusHeader(statuses: LiveStatusFilter[], hosts: string[]): string;
export declare function registerFocusCommand(program: Command): void;
/**
 * Which fallback fires when a session has no attach rail. `--attach-only` (the old
 * `go`) refuses; the default opens a new tab and resumes a copy. Pure so it's testable
 * without touching `jumpTo`'s side effects.
 */
export declare function selectFallback(attachOnly: boolean | undefined): UnreachableFallback;
export declare function focusAction(id: string | undefined, opts: FocusOptions): Promise<void>;
/** A retained pane is not attachable merely because tmux can still display it. */
export declare function isAttachableLiveSession(session: ActiveSession): boolean;
/**
 * Collapse rows that are the SAME logical session.
 *
 * A transcript syncs across the fleet, so one session appears once per machine
 * holding a copy. SES-IF-2a: "Synced copies sharing the same full id MUST count
 * as one logical session." `fleetCandidatesByQuery` already groups this way, but
 * this path filtered raw rows instead — so `focus <full-uuid>` answered
 * "is ambiguous (2 sessions). Use more of the id." with no longer id to give.
 * Measured on zion: one of the two rows had no transcript at all
 * ("Session transcript not available (file no longer exists). Path: ").
 */
export declare function dedupeSessionsByLogicalId(rows: SessionMeta[], self?: string): SessionMeta[];
/**
 * The session to focus once an id/identity selector has resolved across the
 * fleet. Prefer the already-gathered candidate-pool row (it carries the live
 * status collected for the picker), but fall back to the resolver's own metadata
 * when the resolved session is not in the filtered pool — a peer-owned, older, or
 * other-project session that the display filters excluded. Returning the resolved
 * session there (instead of rejecting it) is what lets `focus <id>` reach a
 * peer-owned session without `--device`, matching `resume`/`preview`.
 */
export declare function focusTargetForResolved(poolMatch: SessionMeta | undefined, resolved: SessionMeta): SessionMeta;
export declare function focusResolvedSession(meta: SessionMeta, liveById: Map<string, ActiveSession>, self: string, fallback: UnreachableFallback, attachOnly: boolean, reconnectReattach?: boolean): Promise<void>;
/** Focus one row selected by the shared session browser through the same
 * attach/recover decision as `agents sessions focus <id>`. */
export declare function focusSelectedSession(meta: SessionMeta, active: ActiveSession | undefined, self: string): Promise<void>;
/**
 * How a single selected live session opens in its new tab.
 *  - `attach` — a live tmux pane joined in the tab (a second client, no fork),
 *    local (`sh -c`) or remote (`ssh -tt`). tmux is the only rail that can be
 *    *joined* without forking (see the file header).
 *  - `resume` — no attach rail, so resume a copy in the tab (the original keeps
 *    running); never a silent drop.
 *  - `skip` — not resumable AND no rail: reported, not dropped.
 */
export type FocusSurfacePlan = {
    kind: 'attach';
    command: string[];
    note: string;
} | {
    kind: 'resume';
    command: string[];
    note: string;
} | {
    kind: 'skip';
    note: string;
};
/**
 * Shell that resolves a tmux pane to its session and attaches it — the exact form
 * `jumpTo` uses, minus the pre-select-window nicety, so a batch tab joins the live
 * session (a second client) without forking. Reused for local and (wrapped in ssh)
 * remote panes.
 */
export declare function tmuxAttachScript(mux: {
    socket?: string;
    pane: string;
}): string;
/**
 * Decide how one live session opens as a tab. Pure over the session + a
 * `resumeCommandFor` resolver (injected so the local version-pinned resume command
 * and the tests stay decoupled from `discoverSessions`).
 */
export declare function planFocusSurface(s: ActiveSession, self: string, resumeCommandFor: (s: ActiveSession) => string[] | null, rail?: AttachRailLiveness): FocusSurfacePlan;
/** The engine seam — real `openSurfaces`, overridable in tests to assert the tab requests. */
export type OpenSurfacesFn = typeof openSurfaces;
/** Test seams for `openFocusTabs`: inject the engine boundary + force a backend. */
export interface OpenFocusTabsDeps {
    open?: OpenSurfacesFn;
    /** Skip `resolveBackend` (which needs a live terminal) when set — tests pass 'tmux'. */
    backend?: Backend | 'inplace';
    /** Rich rows selected by the shared browser pipeline (including remote history). */
    metas?: SessionMeta[];
    /** Liveness boundary; production probes tmux, tests exercise planning deterministically. */
    probe?: typeof probeAttachRail;
    /** Strict focus mode: open living attach rails only; never recover a copy. */
    attachOnly?: boolean;
}
/**
 * Open each selected live session as a tab: attach its live pane where one exists,
 * else resume a copy. Reuses `resume`'s backend resolution + flood guard.
 */
export declare function openFocusTabs(targets: ActiveSession[], self: string, deps?: OpenFocusTabsDeps): Promise<void>;
/** Minimal SessionMeta for a live session, enough for `buildResumeCommand` + placement. */
export declare function metaFromActive(s: ActiveSession): SessionMeta;
