/** * Passive update notifier (change: add-zero-interaction-onboarding). * * Best-practice, npm/gh/brew-style: a cached, non-blocking, fail-silent check * against the npm registry that tells a human "a newer openlore is available" * on stderr — never blocks a command, never prints in CI or non-interactive * contexts, and is silenceable. The actual upgrade is a separate explicit step * (`openlore update`); this module only *notifies*. * * Design rules (so it can never harm the hot path): * - Reads a cached result and prints synchronously (instant); a stale cache is * refreshed in the background and is NOT awaited, so no command ever waits on * the network for the notifier. * - Suppressed unless stderr is a TTY (keeps agent/MCP/hook output clean), and * in CI, and when OPENLORE_NO_UPDATE_NOTIFIER / NO_UPDATE_NOTIFIER is set. * - Every network and disk operation is wrapped to never throw. * - 100% deterministic given an injected fetcher/clock — no LLM, no new runtime * dependency (uses global fetch + node:fs/os). */ /** Published package name on npm. */ export declare const PACKAGE_NAME = "openlore"; /** dist-tag endpoint returning the latest published version as JSON. */ export declare const REGISTRY_LATEST_URL = "https://registry.npmjs.org/openlore/latest"; /** How long a cached check stays fresh before a background refresh. */ export declare const CHECK_INTERVAL_MS: number; /** Network budget for the background refresh. */ export declare const FETCH_TIMEOUT_MS = 2000; /** Default cache file: ~/.openlore/update-check.json (per the repo cache convention). */ export declare function defaultCacheFile(): string; export interface UpdateCache { /** Latest version seen at the last successful check. */ latest: string; /** Epoch ms of the last check attempt. */ checkedAt: number; } export interface NotifyOptions { /** Override the cache file (tests). */ cacheFile?: string; /** Override the environment (tests). Defaults to process.env. */ env?: NodeJS.ProcessEnv; /** Where the banner is written. Defaults to process.stderr. */ stream?: { write(s: string): void; isTTY?: boolean; }; /** Clock injection (tests). Defaults to Date.now. */ now?: () => number; /** Network fetcher injection (tests). Defaults to global fetch. */ fetcher?: (url: string, init?: { signal?: AbortSignal; }) => Promise<{ ok: boolean; json(): Promise; }>; /** Force the TTY decision (tests). */ isTTY?: boolean; } /** * True when `latest` is strictly newer than `current` by semver core * (major.minor.patch). Prerelease tags are ignored — a stable release is the * only thing we nudge a user toward. Returns false on any unparseable input. */ export declare function isNewer(current: string, latest: string): boolean; /** Fetch the latest published version, or null on any failure (never throws). */ export declare function fetchLatestVersion(opts?: NotifyOptions): Promise; /** Refresh the cache from the network. Fail-silent; safe to fire-and-forget. */ export declare function refreshCache(opts?: NotifyOptions): Promise; /** The boxed banner shown to a human on stderr. */ export declare function formatBanner(current: string, latest: string): string; /** * Print an update banner if a newer version is cached, then refresh a stale * cache in the background (NOT awaited). Returns true if a banner was printed. * * Suppressed entirely (returns false, no network) when: a silencing env var is * set, CI is detected, or stderr is not a TTY — so agents, MCP servers, hooks, * and pipelines never see it. */ export declare function notifyIfUpdateAvailable(current: string, opts?: NotifyOptions): boolean; //# sourceMappingURL=update-notifier.d.ts.map