export declare const PID_FILE: string;
export declare const LOG_FILE: string;
export type ServiceMode = 'systemd' | 'background' | 'foreground' | 'none';
export interface ServiceState {
    mode: ServiceMode;
    pid: number | null;
    /** Approximate uptime in seconds — from systemd timestamp or proc start time. */
    uptimeSec?: number;
    /** Raw `systemctl is-active` value when mode === 'systemd'. R14 — we
     *  return mode='systemd' as soon as the unit is enabled, even when
     *  state is `activating` / `failed` / `inactive`, so callers that
     *  care about the difference can inspect this field. Undefined for
     *  other modes. */
    active?: string;
}
/** Format seconds as e.g. "2h 15m" / "3d 4h" / "45s". */
export declare function formatUptime(sec: number): string;
/** Look up the running mode + pid. Order matters: systemd wins, then bg
 *  pid-file, then a foreground pgrep match. Returns `{mode:'none', pid:null}`
 *  when nothing is running. */
export declare function detectService(): ServiceState;
/**
 * Spawn Agim detached with stdio redirected to ~/.im-hub/im-hub.log.
 * Writes the pid to PID_FILE so subsequent `status` / `stop` find it.
 *
 * Cross-platform: setsid → new session, no controlling tty, parent can exit.
 * On macOS where setsid isn't always reliable, fall through to a plain
 * detached spawn (child still gets stdio: 'ignore' / 'pipe' redirected to
 * the log file, which is enough to survive the parent).
 */
export declare function spawnBackground(executable: string, args?: string[]): {
    pid: number;
};
/** Stop whichever instance is running. Returns the mode that was stopped
 *  (or 'none' when there was nothing to do). */
export declare function stopService(): Promise<{
    mode: ServiceMode;
    pid: number | null;
}>;
/** Get the configured web bind+port from `<AGIM_HOME>/config.json` —
 *  used by `status` to print the URL. Returns null when config is
 *  absent / unparseable. */
export declare function readWebEndpoint(): {
    bind: string;
    port: number;
} | null;
/** R14 — find every agim/im-hub-pro process running on this host.
 *  Includes pids from background spawns AND systemd-spawned children
 *  that may have escaped the cgroup (the failure mode that motivated
 *  R14: a dbus-run-session wrapper detaches its children from
 *  systemd's control group, leaving the old agim alive after
 *  `systemctl stop` "succeeds").
 *
 *  R15 — argv-strict matching. Pre-R15 this used `pgrep -af "agim start"`
 *  which matched any process whose cmdline contained the substring
 *  "agim start" anywhere — meaning a `bash -c 'echo "agim start"'` test
 *  helper got SIGTERM'd by the reap path. Now we read /proc/<pid>/cmdline
 *  directly and require:
 *    - argv[0] basename is a node-like interpreter (node / bun)
 *    - argv[1] basename is an agim entry script (agim / im-hub-pro / cli.js)
 *    - argv[2] is the literal string 'start'
 *  This is impossible for a shell to satisfy — shells have argv[0]=bash.
 *
 *  Non-Linux (darwin / windows) falls back to the legacy pgrep behavior;
 *  /proc isn't available there, and those platforms aren't the R14
 *  motivating case (server-side cgroup escapes need systemd + Linux). */
export declare function findAgimProcesses(): number[];
/** R14 — SIGTERM then SIGKILL any agim process not in the excludeSet.
 *  Used by the web restart handler to clear stray instances that
 *  escaped systemd's cgroup before invoking `systemctl restart` (the
 *  cgroup-kill on stop will then have nothing left to fail on, and
 *  the new MainPID gets a clean port).
 *
 *  Returns the pids actually reaped (signalled + confirmed dead).
 *  Best-effort: a pid we can't signal (permissions, already exited)
 *  is silently dropped — caller is interested in "what we killed",
 *  not in surfacing failures the OS already handled. */
export declare function reapStrayAgimProcesses(opts?: {
    excludePids?: number[];
    sigtermTimeoutMs?: number;
}): Promise<{
    reaped: number[];
    survived: number[];
}>;
//# sourceMappingURL=service.d.ts.map