/** * CloudOutboxStore — reads and trims the durable `cloud_outbox` that the * `chat_messages` triggers fill, keeps the uploader's `cloud_sync_state`, and * pages history for the first-sign-in backfill * (specs/unified-conversations-cloud-store.md §A.4, §B.3, §B.4). * * The outbox is on disk, so a machine that is offline or signed out loses * nothing: rows wait until the uploader drains them. * * @module services/chat-v2/sqlite/cloud-outbox.store */ import type { ChatChannelType, ChatContentType, ChatSenderType } from '../types.js'; import type { ChatDatabase } from './chat-db.js'; /** One outbox row. */ export interface OutboxEntry { seq: number; messageId: string; op: 'upsert' | 'delete'; enqueuedAt: number; } /** Attachment metadata (never the bytes — owner decision O4). */ export interface UploadAttachmentRow { kind: string; mimeType: string; sizeBytes: number; originalName: string | null; } /** A message with everything the uploader sends about it. */ export interface UploadMessageRow { rowid: number; id: string; channelId: string; senderType: ChatSenderType; senderId: string; content: string; contentType: ChatContentType; createdAt: number; metadata: string | null; mentions: string | null; threadId: string | null; source: string | null; direction: string | null; senderKind: string | null; agentSession: string | null; extRef: string | null; cloudSync: number | null; channelName: string; channelType: ChatChannelType; /** First member of a huddle — the agent a message addressed to nobody in particular is filed under. */ leadMember: string | null; attachments: UploadAttachmentRow[]; } /** Position in `created_at ASC, rowid ASC` order. */ export interface BackfillCursor { createdAt: number; rowid: number; } /** SQLite-backed outbox + sync-state store. */ export declare class CloudOutboxStore { private readonly db; constructor(db: ChatDatabase); /** * The oldest outbox rows, in upload order. * * @param limit - Maximum rows * @returns Rows ordered by `seq` */ peek(limit: number): OutboxEntry[]; /** * Remove every outbox row up to and including `seq` (Cloud has them). * * @param seq - Highest acknowledged outbox seq * @returns Rows removed */ ackThrough(seq: number): number; /** @returns Number of rows waiting in the outbox */ count(): number; /** Empty the outbox (account switch / sign-out: the backfill re-sends the window). */ clear(): void; /** * Keep the outbox bounded while nothing drains it: drop rows older than * `olderThanMs`, then the oldest beyond `maxRows`. * * @param options.maxRows - Row cap * @param options.olderThanMs - Drop rows enqueued before this epoch ms * @returns Rows dropped (a history gap on Cloud when > 0) */ trim(options: { maxRows: number; olderThanMs: number; }): number; /** * Load messages by id, with their channel and attachment metadata. * * @param ids - Message ids * @returns Map of id → row (ids with no row — deleted since — are absent) */ getMessages(ids: readonly string[]): Map; /** * One page of syncable history for the backfill, oldest first. * * @param sinceMs - Only rows created at/after this epoch ms (the plan window) * @param after - Resume after this position (exclusive), or null to start * @param limit - Page size * @returns Rows in `created_at, rowid` order */ backfillPage(sinceMs: number, after: BackfillCursor | null, limit: number): UploadMessageRow[]; /** * Read a sync-state value. * * @param key - State key * @returns The value, or null */ getState(key: string): string | null; /** * Write (or with `null`, remove) a sync-state value. * * @param key - State key * @param value - Value, or null to delete */ setState(key: string, value: string | null): void; /** * Remove every sync-state value except the ones listed. * * @param keep - Keys to preserve */ clearState(keep?: readonly string[]): void; /** * Attach attachment metadata and map to the camel-case row shape. * * @param rows - Raw rows * @returns Upload rows */ private withAttachments; } //# sourceMappingURL=cloud-outbox.store.d.ts.map