import { type ArkmeChatRealtimeNotice, type ArkmeChatReceiveHint, type ArkmeChatPolicyUpdatedHint, type ArkmeConversationListPreferenceUpdatedHint } from '../chat-realtime.js'; import type { ArkmeSessionCredentials } from '../keychain-store.js'; import type { ArkmeChatClientEvent, ArkmeChatAttentionSummary, ArkmeChatRealtimeState, ArkmeTimelineItem } from '../types.js'; import { SourceService } from './source-service.js'; import { ServiceRuntime } from './service.js'; import { type ArkmeDesktopNotificationDispatchResult, type ArkmeDesktopNotificationPayload } from './desktop-attention-bridge.js'; export interface ArkmeChatProjectionReader { chatTimelineItems(data: Record, session: ArkmeSessionCredentials, chatSessionUid: string, sourceKind?: 'private_chat' | 'group_chat', bundle?: Record): Promise; } export interface ArkmeNativeAttentionDispatcher { showNotification(payload: ArkmeDesktopNotificationPayload): Promise; applyBadgeSummary(summary: { count: number; revision: number; }): Promise; resetBadgeCount?(): Promise; } type ArkmeMessageNotification = Extract['notification']; export interface PendingChatNotificationHint { hint: ArkmeChatReceiveHint; connectionGeneration: number; attempts: number; receivedAtMillis?: number | undefined; accountUserId?: number | undefined; accountOwnerGeneration?: number | undefined; baselinePassed?: boolean | undefined; resolvedNotification?: ArkmeMessageNotification | undefined; nextAttemptAtMillis?: number | undefined; } export interface PendingChatProjection { latestSequence: number; notificationHints: PendingChatNotificationHint[]; refreshSource?: boolean | undefined; /** A read-cursor change updates directory facts without changing message bodies. */ refreshTimeline?: boolean | undefined; /** Same-sequence content changes need the authoritative preview, not a forward-only tail. */ refreshPreview?: boolean | undefined; accountUserId?: number | undefined; accountOwnerGeneration?: number | undefined; minimumActivityAtMillis?: number | undefined; previewUpdatedAtMillis?: number | undefined; } export declare class ChatRealtimeService { private readonly runtime; private readonly source; private readonly projectionReader; private readonly nativeAttention; teamPublication?: (notice: ArkmeChatRealtimeNotice) => void; directoryInvalidation?: (hint: ArkmeChatPolicyUpdatedHint | ArkmeConversationListPreferenceUpdatedHint) => Promise; directoryAttention?: (retry: boolean) => Promise; directoryBaseline?: () => Promise; private disposed; private readonly chatRealtime; private readonly chatClientListeners; private readonly memberJoinEvents; private readonly pendingChatProjections; private readonly projectionRetryCounts; private readonly localReadCursors; private projectionTimer; private projectionTimerDueAtMillis; private projectionInFlight; private preferredProjectionInFlight; private readonly projectingSessions; private readonly pendingBodyWaiters; private readonly nativeNotificationFlights; private preferredProjection; private readonly projectionRetryAt; private notificationBaselineGeneration; private notificationBaselineUserId; private notificationBaselineOwnerGeneration; private readonly notificationBaselineSequences; private connectionBaselineRetryTimer; private connectionBaselineRetryCount; private chatClientRevision; private attentionSummaryVersion; private attentionSummaryFingerprint; private latestAttentionSummary; private attentionOwnerGeneration; private attentionOwnerUserId; private attentionRefreshInFlight; private attentionRefreshStarted; private attentionRefreshDirty; private attentionRetryTimer; private attentionRetryCount; private attentionStale; private attentionStopped; private realtimeStarted; private attentionController; constructor(runtime: ServiceRuntime, source: SourceService, projectionReader: ArkmeChatProjectionReader, nativeAttention?: ArkmeNativeAttentionDispatcher); reconnect(): void; dispose(): void; offlineContextInvalidation?: () => Promise; selfRoleInvalidation?: () => Promise; startChatRealtime(): () => void; chatRealtimeState(): ArkmeChatRealtimeState; subscribeChatRealtime(listener: (event: ArkmeChatClientEvent) => void): () => void; chatRealtimeInitialEvent(): ArkmeChatClientEvent; handleChatRealtimeNotice(notice: ArkmeChatRealtimeNotice): void; private scheduleMessageNotificationProjection; private handleChatActorHint; private handleTimelineChanged; private handleMemberEvent; /** Suppress only cursor echoes already covered by a local write or its validated ACK. */ beginLocalReadCursor(userId: number, sessionUid: string, sequence: number): (confirmedSequence?: number) => void; private handleReadCursorAdvanced; invalidateOfflineContextProjection(userId: number | undefined, signal?: AbortSignal): Promise; /** Archive changes directory membership, not record content, privacy or calendar. */ invalidateTopicDirectoryProjection(): Promise; invalidateRecordProjection(options?: { contentOnly?: boolean; }): Promise; refreshAttentionSummary(retry?: boolean): Promise; private refreshAttentionSummarySerial; private clearAttentionSummaryRetry; private scheduleAttentionSummaryRetry; private activateAttentionOwner; private clearAttentionOwner; resetAttentionSummary(): void; private invalidateChatPolicyForCurrentSession; /** Browser invalidation only; raw source/Bot caches belong to different projections. */ invalidateConversationListPreferenceForCurrentSession(expectedUserId?: number, hint?: ArkmeConversationListPreferenceUpdatedHint): Promise; private reconcileChatConnectionBaseline; scheduleChatSessionProjection(chatSessionUid: string, latestSequence: number, notificationHint?: PendingChatNotificationHint, refreshTimeline?: boolean, refreshPreview?: boolean, minimumActivityAtMillis?: number, previewUpdatedAtMillis?: number): void; /** Scheduling hint only: a read grants neither activation nor read-ACK authority. */ preferChatProjection(userId: number, sessionUid: string): void; private preferredProjectionUid; private scheduleProjectionFlush; private projectionReadyAt; private canDispatchNativeNotifications; private pendingProjectionRetryDelay; private flushChatSessionProjections; private requeueProjectionFailures; private mergePendingChatProjection; refreshChatSessionProjectionBatch(pending: Array<[string, PendingChatProjection]>, releaseBeforeNativeCompletion?: boolean): Promise>; emitChatClientEvent(event: ArkmeChatClientEvent): void; nextChatClientRevision(): number; } export {}; //# sourceMappingURL=chat-realtime-service.d.ts.map