/** * Devices (`nexus_devices`) — every machine that runs CLEO against this * global store, keyed by the stable `/device-id` (T9321) that * `nexus_project_locations.device_id` already carries (T12469). Resolving a * location's device id against this table answers "which machine, which OS, * which CLEO version, and when did it last check in". * * The CLI calls {@link recordDeviceHeartbeat} on start. It is throttled to at * most one write per {@link DEVICE_HEARTBEAT_INTERVAL_MS} per device: one * primary-key read decides, and only a stale or absent row costs a single * primary-key upsert. The upsert repeats the staleness test in its `WHERE`, so * concurrent CLI starts cannot both write inside one interval. * * @task T12510 * @epic T12496 */ import type { NexusDeviceRecord } from '@cleocode/contracts'; import type { NodeSQLiteDatabase } from 'drizzle-orm/node-sqlite'; /** Minimum interval between two heartbeat writes for one device. */ export declare const DEVICE_HEARTBEAT_INTERVAL_MS = 60000; /** Registry handle subset the device functions need. */ export type DeviceStoreHandle = Pick; /** Descriptive facts about the device sending a heartbeat. */ export interface DeviceFacts { /** Stable device id. Defaults to {@link currentDeviceId}. */ deviceId?: string; /** Hostname. Defaults to `os.hostname()`. */ hostname?: string; /** OS. Defaults to `process.platform`. */ os?: string; /** Architecture. Defaults to `process.arch`. */ arch?: string; /** CLEO version. Defaults to the installed package version. */ cleoVersion?: string; } /** What {@link recordDeviceHeartbeat} did. */ export type DeviceHeartbeatOutcome = 'written' | 'throttled'; /** * Upsert this device's `nexus_devices` row unless it was written within the * last {@link DEVICE_HEARTBEAT_INTERVAL_MS}. * * Cost: one primary-key read; when stale, one primary-key upsert. Descriptive * facts (hostname, version) are resolved only when a write happens. * * @param db - Global registry handle (`getNexusRegistryDb`). * @param now - Heartbeat instant. Defaults to the current time. * @param facts - Overrides for the recorded device facts (tests). * @returns `written` when the row was inserted or refreshed, else `throttled`. * @example * ```ts * await recordDeviceHeartbeat(await getNexusRegistryDb(getCleoHome())); * ``` */ export declare function recordDeviceHeartbeat(db: DeviceStoreHandle, now?: Date, facts?: DeviceFacts): Promise; /** * List every known device, most recent heartbeat first. * * @param db - Global registry handle (`getNexusRegistryDb`). * @returns Device records; `current` marks this device. * @example * ```ts * const all = listNexusDevices(await getNexusRegistryDb(getCleoHome())); * ``` */ export declare function listNexusDevices(db: DeviceStoreHandle): NexusDeviceRecord[]; /** Filename in `` whose mtime records the last heartbeat attempt. */ export declare const DEVICE_HEARTBEAT_STAMP = "device-heartbeat.stamp"; /** What {@link heartbeatThisDevice} did. */ export type DeviceStartupHeartbeatOutcome = DeviceHeartbeatOutcome | 'disabled' | 'shutting-down' | 'no-store'; /** * CLI-start heartbeat: record this device in the global store at most once * per {@link DEVICE_HEARTBEAT_INTERVAL_MS}. * * A stamp file's mtime is checked first, so a start inside the interval costs * one `stat` and never opens the database. Past the interval it opens the * global registry (only if it already exists — a heartbeat never creates the * store) and calls {@link recordDeviceHeartbeat}, whose own primary-key check * and guarded upsert keep concurrent starts to a single write. * * Callers MUST treat every error as non-fatal; the CLI swallows it. * * @param options - `cleoHome` and `now` overrides (tests). * @returns What happened. * @example * ```ts * try { await heartbeatThisDevice(); } catch { // never fail the command } * ``` */ export declare function heartbeatThisDevice(options?: { cleoHome?: string; now?: Date; }): Promise; //# sourceMappingURL=devices.d.ts.map