import { Effect, Option } from "effect"; /** * Outcome of a loopback port probe. `unknown` is a real third answer, not a * synonym for `free`. */ export type PortProbe = "listening" | "free" | "unknown"; /** * Whether something accepts TCP connections on the port. Loopback only: a * server may bind wider, but loopback is always reachable when it is up. * * An inconclusive first attempt is retried once, because the usual cause is * our own loop having been blocked past the deadline and by now it is running * again. Only a twice-inconclusive probe reports `unknown`. */ export declare const probePort: (port: number, timeoutMs?: number | undefined) => Effect.Effect; /** * Port-allocation view of the probe: anything but a definitive `free` counts * as taken. Handing out a port we merely failed to read would collide with * whatever is actually on it. */ export declare function portInUse(port: number): Effect.Effect; /** One process holding at least one listening TCP socket. */ export interface ListeningProcess { readonly pid: number; readonly command: string; /** Every port it was seen listening on. */ readonly ports: readonly number[]; } /** * Parse `lsof -Fpcn` LISTEN output into one record per pid. Field lines: * `p` starts a process, `c` names it, and `n` is one * listening socket (`*:4199`, `127.0.0.1:8103`, `[::1]:3000`). */ export declare function parseListeners(out: string): ListeningProcess[]; /** Parse `lsof -a -p -d cwd -Fpn` output into pid to cwd. */ export declare function parseCwdMap(out: string): Map; /** * Path containment with a component boundary, so `/wt/foo` never claims * `/wt/foobar`. A trailing slash on `root` is ignored. */ export declare function isUnderPath(cwd: string, root: string): boolean; /** The raw output of one scan, and whether it actually finished. */ export interface LsofScan { readonly out: string; /** False means the scan did not finish. `out` is then not an answer. */ readonly complete: boolean; } export interface LsofScanOptions { /** Budget for one attempt. The scan gets two attempts. */ readonly timeoutMs?: number; /** Working directory for `lsof`. Defaults to `/`. */ readonly cwd?: string; } /** * Run one `lsof`-style scan and say whether it finished. * * A blown budget is retried once, because the load spikes that cause it are * usually brief. Two blown budgets, or any failure to run the command at all, * resolve to `{ out: "", complete: false }` and log a warning. This never * fails, and it never reports an unfinished scan as an empty world. * * Assumes macOS/BSD `lsof` with `-F` field output. */ export declare const lsofScan: (argv: readonly string[], options?: LsofScanOptions | undefined) => Effect.Effect; /** * Every process holding a listening TCP socket, or `None` when the scan did * not finish. `None` means unknown; an empty array means nothing is listening. * * Assumes macOS/BSD `lsof`: `-nP` suppresses host and port name resolution, * `-Fpcn` selects field output with the pid, command and name fields. */ export declare const listeningProcesses: (options?: LsofScanOptions | undefined) => Effect.Effect, never, never>; /** * The working directory of each of the given pids, or `None` when the scan did * not finish. Pids that no longer exist are simply absent from the map. * * Assumes macOS/BSD `lsof`: `-d cwd` selects the current-directory descriptor. */ export declare const processCwds: (pids: readonly number[], options?: LsofScanOptions | undefined) => Effect.Effect>, never, never>;