import type { ConfigManager } from '../config/manager.js'; /** One announce-once line a surface renders verbatim. */ export interface FeatureAnnouncement { readonly id: string; readonly text: string; } /** A fired announcement awaiting delivery to a rendering surface. */ export interface PendingFeatureAnnouncement { readonly id: string; readonly text: string; readonly at: number; } /** * Persisted announce-once bookkeeping under the control-plane config * directory, so an announcement made by any process of this install is made * exactly once, PLUS a pending-delivery queue: an announcement recorded with * text waits here until a rendering surface drains it (the daemon folds the * queue into the explicitly-consuming /status receipts read), so * announce-once lines reach surfaces instead of dead-ending in the log. * * File format: `{ announced: { id -> timestamp }, pending: [{id,text,at}] }`. * The legacy format (a plain id->timestamp map) reads as announced-with- * nothing-pending, old installs never re-announce. */ export declare class FeatureAnnouncementStore { private readonly path; constructor(path: string); private read; private persist; has(id: string): boolean; /** * Record an announcement; returns true only on the FIRST record (the caller * announces), false when it was already made (the caller stays silent). * With `text`, the first record also enqueues the line for surface delivery * (see drainPending), so the announcement reaches a rendering surface, not * only the log. */ record(id: string, text?: string): boolean; /** * The fired-but-undelivered announcements, cleared on read: exactly-once * delivery to the first draining reader (the daemon's explicitly-consuming * /status receipts read), mirroring the daemon receipt contract. */ drainPending(): PendingFeatureAnnouncement[]; } /** The store file location for an install (control-plane config directory). */ export declare function featureAnnouncementsPath(configManager: Pick): string; /** The web surface's reachable URL from its settings. */ export declare function resolveWebSurfaceUrl(configManager: Pick): string; export declare const WEB_SURFACE_ANNOUNCEMENT_ID = "web-surface-url"; export declare const SANDBOX_CONTAINED_ANNOUNCEMENT_ID = "exec-sandbox-contained"; /** The one-time contained-exec line, verbatim. */ export declare const SANDBOX_CONTAINED_ANNOUNCEMENT_TEXT = "commands now run contained; escalations will ask"; /** * Collect the announce-once lines due at daemon start. Each returned line is * recorded in the store as announced, the caller renders every returned * line (daemon-start log, footer, ...), exactly once per install. */ export declare function collectStartupAnnouncements(deps: { readonly configManager: Pick; readonly store: Pick; }): FeatureAnnouncement[]; /** The automation empty state a surface renders while no routines exist. */ export interface AutomationEmptyState { readonly title: string; readonly body: string; } /** * Automation's how-to-create-your-first-routine empty state: present while * automation is enabled and has zero routines, absent otherwise. Persistent * state (not once-only), it disappears by itself when the first routine * exists, so nothing default-on ever needs a setup step to be honest. */ export declare function buildAutomationEmptyState(input: { readonly enabled: boolean; readonly routineCount: number; }): AutomationEmptyState | null; /** * The exec sandbox's first-contained-run announcer: call it on every * sandboxed command execution; the FIRST call per install announces once via * `onAnnounce` and every later call is silent. */ export declare function createSandboxContainmentAnnouncer(store: Pick, onAnnounce: (announcement: FeatureAnnouncement) => void): () => void; //# sourceMappingURL=feature-announcements.d.ts.map