import { z } from 'zod'; /** The registry filename for a dev server listening on `port`. */ export declare function devServerRegistryFileName(port: number): string; /** * The port from a registry filename, or null when the name is not one. * * Strict about the whole shape, because the daemon's own `daemon-.json` sits in the same * directory: reading one of those as a dev server would report the daemon as an instrumented app, * which is the precise false green this signal exists to prevent. */ export declare function devServerRegistryPort(fileName: string): number | null; /** One dev server's entry: enough to name it, reach it, and prove it is still alive. */ export declare const DevServerEntrySchema: z.ZodObject<{ port: z.ZodNumber; pid: z.ZodNumber; /** The project directory the dev server is serving — how a monorepo tells its apps apart. */ root: z.ZodString; /** Where the app is actually served, as the dev server itself reports it. Never assembled here. */ url: z.ZodString; /** * The SDK version in the bundle, so a skew can be named rather than guessed at. * * Optional, and ABSENT rather than empty when it cannot be resolved. `""` reads as "the version is * empty"; a missing field reads as "not known", which is the true statement — and the difference * matters to the one reader who exists for this field, a skew diagnosis. */ sdkVersion: z.ZodOptional; startedAt: z.ZodNumber; /** * Optional because an app can be running before `init` has ever named it — which is exactly the * state this signal has to be able to describe. */ projectId: z.ZodOptional; }, "strip", z.ZodTypeAny, { url: string; port: number; pid: number; startedAt: number; root: string; projectId?: string | undefined; sdkVersion?: string | undefined; }, { url: string; port: number; pid: number; startedAt: number; root: string; projectId?: string | undefined; sdkVersion?: string | undefined; }>; export type DevServerEntry = z.infer; /** * The entries whose process is still running, lowest port first. * * Liveness is checked rather than trusted for the same reason the daemon registry checks it: a dev * server killed with SIGKILL runs no cleanup, so its file outlives it. A stale entry read as live is * worse than no entry at all — it reports a running, instrumented app over a dead port, and sends * the reader to look at their browser instead of at their terminal. * * Pure, so both the CLI and the plugins share one rule and it is testable without real processes. */ /** * The live entries that belong to THIS project. * * Scoping is the difference between a diagnosis and a wrong answer. The registry is machine-wide — * one directory holds every app on the box — so unscoped, "a dev server is running" is satisfied by * somebody else's app, another package in the same monorepo, or yesterday's terminal, and `init` * for app A hands the user app B's URL: confident, specific, and about the wrong project. * * Two ways to belong, because both are true and neither covers the other: * * - the projectId matches, which is exact and survives a moved directory * - the entry's root is the directory being set up, or inside it, which is what makes `init` at a * monorepo root see the apps underneath it — they genuinely are its apps * * With neither known nothing matches, and the caller gets the same less specific answer it had * before. That is the conservative direction on purpose: a missed match costs one vaguer sentence, * a wrong match sends somebody to another team's app. */ export declare function devServersForProject(entries: readonly DevServerEntry[], scope: { projectId?: string | undefined; root?: string | undefined; }): DevServerEntry[]; export declare function liveDevServers(entries: readonly DevServerEntry[], isAlive: (pid: number) => boolean): DevServerEntry[];