import { type FocusRow } from '../canvas/index.js'; export type { FocusRow }; export { splitWindow, breakPane, selectLayout, selectPane, focusWindow, selectWindow, switchClient, openNodeWindow, ensureSession, paneLocation, paneExists, paneRunning, paneCurrentPath, currentTmux, inTmux, paneOfNode, installTmuxBindings, installTmuxBindings as installMenuBinding, setPaneOption, getPaneOption, piCommand, shellQuote, respawnPaneSync, closePane, displayPopup, windowOfPane, renameWindow, paneOfWindow, windowAlive, listLivePanes, } from './tmux.js'; export type { RespawnPaneOpts, TmuxInstalledPair, TmuxInstallDiagnostic, TmuxInstallResult } from './tmux.js'; /** The viewer a node has on screen, or null. UNIQUE(node_id) ⇒ at most one. */ export declare function focusOf(nodeId: string): FocusRow | null; /** Does this node have a live viewer on screen? */ export declare function isFocused(nodeId: string): boolean; /** The viewer realized by a given pane (`%id`), or null. */ export declare function focusByPane(pane: string): FocusRow | null; /** The set of node ids that currently have a live viewer. */ export declare function focusedNodes(): Set; /** Every live viewer row (GC'ing any whose pane has gone). */ export declare function listFocuses(): FocusRow[]; /** A reviver: ensure a node's broker ENGINE is alive (idempotent → reviveNode → * headlessBrokerHost.launch). Injected so placement.ts need not import revive.ts * (which imports placement.ts — a cycle). */ export type Reviver = (nodeId: string) => { launch?: { exited: Promise<{ code: number | null; signal: NodeJS.Signals | null; }>; }; } | void; /** Result of a focus op. `inPlace` = navigated to an existing viewer (no new * pane); false = a fresh viewer pane was opened/moved. `revived` = this call * had to (re)launch the broker engine. */ export interface FocusResult { focused: boolean; session: string | null; inPlace: boolean; revived: boolean; } /** Register a `crtr surface attach` VIEWER pane as the node's one viewer focus row. * UNIQUE(node_id) ⇒ one viewer per node: returns * the existing row (no insert) when the pane or the node is already registered. * `window` is accepted for the call contract (spawn passes it) but not stored — * the focuses table keys on pane + session only. The attach client self-tags the * pane `@crtr_node` on connect, so `nodeInPane` resolves it either way. */ export declare function registerViewerFocus(nodeId: string, pane: string, session: string | null, window: string | null): FocusRow | null; /** Open a surface-attach viewer for `nodeId` and register its viewer focus row — * the shared opener used by `focus` (a split beside the caller) and by a --root * spawn (a fresh window in the caller's current session). Wraps `ensureSession` * + `openNodeWindow`/`splitWindow` + `registerViewerFocus`. The attach client * connects to the node's `view.sock` and renders/drives the live broker engine * — it NEVER launches the engine (the one-writer invariant; the caller ensures * the broker is alive first). Returns the registered viewer row, or null if tmux * refused. * - default → a fresh WINDOW in `session` (the --root spawn-viewer path). * - `besidePane` → a SPLIT beside that pane in its own session (the focus * open-beside-the-caller path); `session` is then only a fallback. */ export declare function openViewerWindow(nodeId: string, session: string, opts?: { name?: string; cwd?: string; besidePane?: string; waitForBroker?: boolean; }): FocusRow | null; export declare function focus(nodeId: string, opts: { pane?: string; newPane?: boolean; inPlace?: boolean; revive: Reviver; }): Promise; /** Tear a node off its viewer (close/reset/cancel teardown). The broker engine * is killed by its own host teardown over view.sock — this only closes the * on-screen viewer: kill its pane (the window collapses once its last pane goes) * and drop its registry row. Best-effort tmux; the DB write always lands. No-op * when the node has no viewer. */ export declare function tearDownNode(nodeId: string, keepPane?: string): void; /** Detach a node from the foreground (the `node lifecycle demote --detach` / Alt+C → D * half). Every node is a headless broker — the only thing on screen is its * surface-attach viewer pane — so "detach" means STOP FOREGROUNDING it: close the * viewer pane (and drop its row) and leave the broker engine running untouched, * reconnectable by a later `focus`. `pane` is the authoritative pane the caller * acts on (the Alt+C menu's `#{pane_id}`); falls back to the node's registered * viewer pane. No-op (false) when there is no live viewer pane to close. */ export declare function detachToBackground(nodeId: string, pane?: string): boolean; /** Reap `nodeId` IFF it is an empty shell (see {@link isEmptyNode}): tear down its * broker engine, close any viewer, and hard-delete its row (edges cascade) + dir. * The user closing or detaching from a node that never said anything wants it * GONE, not parked as a canceled husk — except an OPEN managed worktree keeps * its node identity so the worktree remains owned and can later be closed. * Returns true when it reaped. No-op (false) on a node that produced output, * is mid-first-turn, owns an open managed worktree, or no longer exists. */ export declare function reapIfEmpty(nodeId: string, keepPane?: string): boolean; /** Sweep the whole canvas for empty shells and reap them — the bulk cleanup * behind `crtr canvas prune --empty`, for the husks that accumulated before * close/detach learned to reap. Skips: the caller ($CRTR_NODE_ID), nodes * mid-first-turn, and any node with a LIVE broker (pi_pid alive) — a running * engine is the daemon's domain and may have output not yet persisted, so bulk * GC never kills one (the per-action {@link reapIfEmpty} does, since the user * explicitly closed/detached that node). `dryRun` reports candidates without * deleting. Returns the reaped (or, under dryRun, reapable) node ids. */ export declare function reapEmptyNodes(opts?: { dryRun?: boolean; }): string[];