/** A restartable browser target. `bundleId` is the macOS CFBundleIdentifier — * the single source of truth we quit + relaunch by (no process-name guessing). * `openArgs` are passed to `open -b --args …` on relaunch (e.g. Chromium's * `--restore-last-session` to force tab restore). */ export interface BrowserTarget { bundleId: string; label: string; /** Extra argv forwarded on relaunch (Chromium restore flag, etc.). */ openArgs?: string[]; /** false ⇒ never offered on the card (config can disable a default). */ enabled?: boolean; } /** Config entry shape (all optional except bundleId) — merged over the defaults * by bundleId. Kept separate from {@link BrowserTarget} so config validation is * explicit and forgiving of missing fields. */ export interface BrowserTargetConfig { bundleId?: unknown; label?: unknown; openArgs?: unknown; enabled?: unknown; } /** Built-in defaults. Chromium browsers get `--restore-last-session` so a bounce * reopens the exact tabs; Arc restores its own state on launch. Order here is * the display order on the card. NOT exhaustive by design — extend via config. */ export declare const DEFAULT_BROWSER_TARGETS: readonly BrowserTarget[]; /** * Merge a config `browserRestartTargets` list over {@link DEFAULT_BROWSER_TARGETS}: * - a config entry whose bundleId matches a default OVERRIDES its label/openArgs/ * enabled (only the fields actually present); * - a config entry with a new bundleId is APPENDED (so new browsers need no code); * - the result drops anything with `enabled === false`. * Pure: no I/O. Invalid/garbage entries (missing/blank bundleId) are ignored so a * hand-edited config can't crash the resolver. When `raw` is undefined/empty the * built-in defaults are returned unchanged. */ export declare function resolveBrowserTargets(raw: unknown): BrowserTarget[]; /** Card button label, e.g. `♻️ 重启 Arc · 6.2 GB`. Memory is optional (unknown * ⇒ omit the suffix). Pure. */ export declare function formatBrowserLabel(label: string, memMB?: number): string; /** A running browser found on the host, with its aggregate RSS in MB. */ export interface RunningBrowser { bundleId: string; label: string; memMB: number; openArgs?: string[]; } /** * Probe the host for which of `targets` are installed AND currently holding * memory, returning them (in `targets` order) with aggregate RSS in MB. A * browser that's installed but not running contributes nothing (no button). * * Memory is summed over every process whose command line lives under the app's * bundle path (helper renderers, GPU process, …) — matched by RESOLVED app path, * not a fuzzy name, so "Google Chrome" can't accidentally match "Chrome" text * elsewhere. Impure (mdfind + ps). Best-effort: a probe failure yields []. */ export declare function detectRunningBrowsers(targets: BrowserTarget[], deps?: { /** injectable for tests; defaults to the real ps. */ psList?: () => Promise; /** injectable for tests; defaults to the real Spotlight lookup. */ appPathFor?: (bundleId: string) => Promise; /** override the platform gate in tests. */ platform?: NodeJS.Platform; }): Promise; /** Result of a restart attempt. `relaunched` is best-effort — a failure to * reopen still counts the quit as done (memory was freed) but is reported. */ export interface RestartResult { ok: boolean; quit: boolean; relaunched: boolean; error?: string; } /** * Restart a browser by bundle id: graceful `quit` via AppleScript, poll until * its processes are gone, then relaunch with `open -b ` (+ openArgs). Never * SIGKILLs — a browser refusing to quit (unsaved prompt) is left alone and * reported rather than force-killed under the user. Impure. `sleep`/`now`/`run` * are injectable so the polling loop is unit-testable without real timers. */ export declare function restartBrowser(target: { bundleId: string; openArgs?: string[]; }, opts?: { run?: (file: string, args: string[]) => Promise<{ stdout: string; }>; isRunning?: (bundleId: string) => Promise; sleep?: (ms: number) => Promise; now?: () => number; quitTimeoutMs?: number; /** inject the resolved bundle path (tests); defaults to a Spotlight lookup. */ appPath?: string; appPathFor?: (bundleId: string) => Promise; }): Promise; /** * True when a `ps` command line's EXECUTABLE belongs to the app at `appPath`. * * A `ps` line is ` `; the executable is argv0 at the very start. * We anchor on that left boundary — the command (after trimming leading spaces) * must BEGIN with `appPath` — instead of scanning for the path anywhere in the * line. This is deliberately stricter than a substring/right-boundary match: * - a backup copy launched from elsewhere, e.g. `/Volumes/Backup/…/Arc.app/…`, * does NOT start with `/Applications/Arc.app` → excluded; * - `/Applications/Arc.app-copy/…` is not under `/Applications/Arc.app/` → excluded; * - the path appearing as an unrelated ARGUMENT, e.g. * `/usr/bin/open -b x /Applications/Arc.app`, is not argv0 → excluded. * Bundle-internal helpers (`/Contents/Frameworks/…`) start with `/`, so * they match. Prefix-matching (not whitespace-splitting) also tolerates spaces in * the app path itself (e.g. `/Applications/Google Chrome.app`). Pure. */ export declare function commandInApp(command: string, appPath: string): boolean; //# sourceMappingURL=browser-restart.d.ts.map