import { type ExecFileSyncOptions } from 'child_process';
export interface DaemonUpgradeHelperPayload {
    packageName: string;
    targetVersion: string;
    parentPid: number;
    restartArgv: string[];
    cwd?: string;
    sessionHostAppName?: string;
}
export interface CurrentGlobalInstallSurface {
    npmExecutable: string;
    npmArgsPrefix?: string[];
    packageRoot: string | null;
    installPrefix: string | null;
    execOptions?: NpmExecOptions;
}
export interface PinnedGlobalInstallCommand {
    command: string;
    args: string[];
    surface: CurrentGlobalInstallSurface;
    execOptions: NpmExecOptions;
}
export type NpmExecOptions = {
    shell: boolean;
    windowsHide?: boolean;
};
export declare function resolveCurrentGlobalInstallSurface(options: {
    packageName: string;
    currentCliPath?: string;
    nodeExecutable?: string;
    platform?: NodeJS.Platform;
}): CurrentGlobalInstallSurface;
export declare function buildPinnedGlobalInstallCommand(options: {
    packageName: string;
    targetVersion: string;
    currentCliPath?: string;
    nodeExecutable?: string;
    platform?: NodeJS.Platform;
}): PinnedGlobalInstallCommand;
export declare function getNpmExecOptions(platform?: NodeJS.Platform): NpmExecOptions;
export declare function execNpmCommandSync(args: string[], options?: ExecFileSyncOptions, surface?: Pick<CurrentGlobalInstallSurface, 'npmExecutable' | 'npmArgsPrefix' | 'execOptions'>): Buffer | string;
export declare function stopSessionHostProcesses(appName: string): Promise<void>;
/**
 * Enumerate processes that have a locked native addon (conpty.node /
 * ghostty-vt.dll) of *this* install memory-mapped.
 *
 * `stopSessionHostProcesses()` only knows the single managed session-host pid, so
 * any *foreign* holder — e.g. an orphaned `pty_*probe*.cjs` left in `%TEMP%` — is
 * invisible to it and keeps the addon locked through every install retry, dooming
 * the upgrade with EBUSY. This scans by the module's full path so we only ever
 * target a holder of the exact `packageRoot` being replaced (never an unrelated
 * install's copy). Windows-only — these locks don't exist on POSIX.
 */
export declare function listForeignNativeAddonHolders(packageRoot: string | null | undefined): Array<{
    pid: number;
    commandLine: string | null;
}>;
/**
 * Terminate every foreign process holding this install's native addon mapped,
 * then wait for each to actually exit so the mapping is released before npm
 * copies the file into its staging dir. Returns what it found/killed so the
 * caller can surface an actionable recovery message on failure.
 */
export declare function stopForeignNativeAddonHolders(packageRoot: string | null | undefined, options?: {
    parentPid?: number;
}): Promise<Array<{
    pid: number;
    commandLine: string | null;
    killed: boolean;
}>>;
/**
 * Best-effort removal of a leftover npm staging entry.
 *
 * A stale staging dir can hold a locked native binary — e.g. `ghostty-vt.dll`
 * from `@adhdev/ghostty-vt-node` still mapped by a lingering session-host
 * process — which makes `rmSync` throw `EPERM` on Windows. Staging cleanup is
 * only housekeeping: the leftover is inert and npm creates its own fresh
 * staging dir for the real install, so a lock on an old leftover must NOT abort
 * the upgrade. Log and continue instead of letting the error propagate.
 */
export declare function safeRemoveStaleEntry(target: string, label: string): void;
export declare function cleanupStaleGlobalInstallDirs(pkgName: string, surface: CurrentGlobalInstallSurface): void;
export declare function spawnDetachedDaemonUpgradeHelper(payload: DaemonUpgradeHelperPayload): void;
export declare function maybeRunDaemonUpgradeHelperFromEnv(): Promise<boolean>;
