export interface RelayInfo { /** The relay's localhost HTTP/WS port (OS-assigned per preview run). */ relayPort: number; /** The public preview URL, for display. */ url: string; /** The preview process pid, so a stale file can be detected. */ pid: number; /** WS/HTTP path prefix routed to the relay (default /__harness). */ harnessPath: string; /** * When the session's hard maximum lifetime expires, ISO8601. * * A live marker proves the LOCAL relay is up; it does not prove the tunnel * URL still resolves — a session can be superseded from another machine or * hit its hard max while this process sits idle. Carrying the expiry lets a * re-run say "this link is still good until X" instead of printing a URL it * only assumes is live. Optional: markers written by an older CLI lack it. */ expiresAt?: string; } export declare function relayInfoPath(cwd: string): string; /** * The directory a marker for this tree lives in: the binding's directory when * there is one, else the cwd unchanged. * * A preview is one per WORKING TREE, and a binding is found by walking up from * the cwd — so `apps/web/` and the repo root are the same tree and must find the * same marker. Anchoring on the raw cwd instead made them two, and a second * `vincentt preview` from the repo root minted a second live session for a * project that already had one (the server could not supersede it either: its * tree key is derived from the same path). */ export declare function relayInfoDir(cwd: string): Promise; export declare function writeRelayInfo(cwd: string, info: RelayInfo): Promise; /** Reads the marker for the TREE containing cwd, not only the folder itself. */ export declare function readRelayInfo(cwd: string): Promise; export declare function clearRelayInfo(cwd: string): Promise; /** * isProcessAlive is a NECESSARY but NOT SUFFICIENT check. * * `kill(pid, 0)` proves SOME process holds that pid, never that it is ours: pids * are recycled, and after a reboot the number in a stale marker routinely * belongs to something else entirely. It is kept as the cheap first gate — it * rules out the common case (a killed CLI) with no I/O — and the relay probe * below is what actually proves identity. */ export declare function isProcessAlive(pid: number): boolean; /** * isRelayResponding asks the recorded port whether OUR relay is behind it. * * This is the check that makes a recycled pid harmless: a `/query` that answers * with a RelayResult-shaped body could only have come from a relay this CLI * started. A stranger on that port answers something else, or nothing, and the * marker is correctly judged stale. * * A short timeout, because this runs on the startup path of a command a creator * runs fifty times a day, and the fallback (mint a preview) is what they asked * for anyway. */ export declare function isRelayResponding(port: number, timeoutMs?: number, fetchImpl?: typeof fetch): Promise; /** * readLivePreview returns the marker ONLY when it still describes a preview that * is genuinely running, and CLEARS it otherwise. * * The marker is proof that a preview was STARTED, never that one is RUNNING: a * crashed CLI, a `kill -9`, or a reboot all leave it behind. Trusting it * unvalidated let `vincentt preview` short-circuit into "attaching…" followed by * "the preview is no longer running", and exit — no mint, no session, and the * creator's only recourse was deleting a dotfile they do not know exists. A * marker that cannot be validated is not a marker. * * Clearing on the stale path is what stops the dead end from recurring on the * next run. */ export declare function readLivePreview(cwd: string, deps?: { processAlive?: (pid: number) => boolean; relayResponding?: (port: number) => Promise; }): Promise;