/** * In-memory notification queue for server → TUI push. * * The queue is the durable at-least-once buffer; live WebSocket sinks are only * a low-latency delivery path. A notification is pruned only after the TUI acks * it with the highest id it handled. */ export interface RpcNotification { id: number; type: string; payload: Record; sessionId?: string; } export interface NotificationSink { /** The TUI session that the sink's socket authenticated for. */ sessionId?: string; /** Deliver one queued notification over the live socket. */ send: (notification: RpcNotification) => void; } export interface StatusChangeSink { /** The TUI session that the sink's socket authenticated for. */ sessionId?: string; /** Deliver a lightweight status invalidation over the live socket. */ send: (event: RpcStatusChange) => void; } export interface RpcStatusChange { sessionId?: string; } /** Register a live TUI notification sink. Returns an unregister function. */ export declare function registerNotificationSink(sink: NotificationSink): () => void; /** Register a live TUI status-invalidation sink. Returns an unregister function. */ export declare function registerStatusChangeSink(sink: StatusChangeSink): () => void; /** Push a notification for the TUI. Fans out to live sinks and keeps the queue. */ export declare function pushNotification(type: string, payload: Record, sessionId?: string): void; /** Push a lightweight status invalidation to matching live TUI sockets. */ export declare function pushStatusChange(sessionId?: string): void; /** Return pending notifications after acking the client's last received id. * * Session scoping: when `sessionId` is provided, only notifications tagged for * that session (or session-less/global ones) are returned and pruned — a * notification tagged for a DIFFERENT session is never handed to this client * and is never pruned by this client's ack. This matters because the in-memory * queue is per-process but a TUI can end up draining a process that also serves * OTHER sessions: e.g. opening OpenCode Desktop on the same project starts a * newer RPC server that the TUI's port discovery (newest-pid-wins) then selects, * so a Desktop-session dialog action would otherwise surface in an unrelated * TUI session. Each client also tracks its own `lastReceivedId`, so a global * watermark prune would let session A's ack drop session B's still-unseen * notification — scoping the prune to the acking session prevents that too. * * Delivery is at-least-once (non-destructive return + prune-on-ack): a returned * notification stays queued until a later call acks it via a higher * `lastReceivedId`, so a dropped WS socket re-delivers the backlog on reconnect * (the client sends its `lastReceivedId` in the hello). */ export declare function drainNotifications(lastReceivedId?: number, sessionId?: string): RpcNotification[]; /** Whether a TUI client is connected via a live notification socket. */ export declare function isTuiConnected(sessionId?: string): boolean; export declare function __resetRpcNotificationsForTest(): void; //# sourceMappingURL=rpc-notifications.d.ts.map