/**
 * Message Service
 *
 * SQLite-backed persistence for both folder-scoped and workspace-scoped
 * messaging. Database lives at .studiograph/messages.db inside the workspace.
 * Follows the AuthService pattern (WAL mode, table creation on init).
 *
 * Scope model:
 *   - messages.folder = '<name>' → folder-scoped (team chat within a folder)
 *   - messages.folder = NULL     → workspace-scoped (shared home chat)
 *
 * Read receipts are split across two tables (folder vs. workspace) because
 * the folder read_receipts PK is (user_id, folder); allowing NULL there
 * would break uniqueness semantics.
 */
export interface FolderMessage {
    id: number;
    /** Folder name, or null for workspace-scoped messages (shared home chat). */
    folder: string | null;
    userId: number;
    userDisplayName: string;
    role: 'user' | 'agent';
    content: string;
    createdAt: string;
    replyToId: number | null;
}
export interface MsgNotification {
    id: number;
    userId: number;
    /** Folder name, or null for workspace-scoped mentions. */
    folder: string | null;
    messageId: number;
    mentionerName: string;
    messagePreview: string;
    read: boolean;
    createdAt: string;
}
/**
 * Format a list of messages as a readable transcript for an LLM prompt.
 * Messages are sorted oldest-first for natural conversation flow.
 *
 * @param messages   Messages to format.
 * @param showScope  If true, annotate each line with the folder/workspace scope.
 *                   Use when the transcript may mix scopes (e.g. cross-folder search).
 *                   Default false — heartbeat and per-scope callers should leave this off.
 */
export declare function formatTranscript(messages: FolderMessage[], showScope?: boolean): string;
export declare class MessageService {
    private db;
    constructor(workspacePath: string);
    /** Post a new message to a folder thread. */
    postMessage(folder: string, userId: number, displayName: string, role: 'user' | 'agent', content: string, replyToId?: number): FolderMessage;
    /** Get messages for a folder with cursor-based pagination (newest first). */
    getMessages(folder: string, opts?: {
        before?: number;
        limit?: number;
    }): FolderMessage[];
    /** Search messages by keyword, optionally scoped to a folder. */
    searchMessages(query: string, opts?: {
        folder?: string;
        folders?: string[];
        limit?: number;
    }): FolderMessage[];
    /** Mark messages as read up to a given message ID (UPSERT). */
    markRead(userId: number, folder: string, messageId: number): void;
    /** Get unread message counts for a user across multiple folders. */
    getUnreadCounts(userId: number, folders: string[]): Record<string, number>;
    /** Update a message's content (used to mark capture items as done). */
    updateMessageContent(id: number, content: string): void;
    /** Get a single message by ID. */
    getMessageById(id: number): FolderMessage | null;
    /** Get the latest message ID for a folder (for markRead on load). */
    getLatestMessageId(folder: string): number | null;
    /** Update the mentions JSON array on a message (called after mention detection). */
    setMentions(messageId: number, userIds: number[]): void;
    /** Post a new message to the workspace-wide chat. */
    postWorkspaceMessage(userId: number, displayName: string, role: 'user' | 'agent', content: string, replyToId?: number): FolderMessage;
    /** Get workspace-wide messages with cursor-based pagination (newest first). */
    getWorkspaceMessages(opts?: {
        before?: number;
        limit?: number;
    }): FolderMessage[];
    /** Mark workspace messages as read up to a given message ID (UPSERT). */
    markWorkspaceRead(userId: number, messageId: number): void;
    /** Count unread workspace messages for a user. */
    getWorkspaceUnreadCount(userId: number): number;
    /** Latest workspace message ID (for mark-read on load). */
    getLatestWorkspaceMessageId(): number | null;
    /**
     * Create a mention notification.
     * @param folder folder name, or `null` for workspace-wide mentions.
     */
    createNotification(userId: number, folder: string | null, messageId: number, mentionerName: string, messagePreview: string): number;
    getNotifications(userId: number, opts?: {
        unreadOnly?: boolean;
        limit?: number;
    }): MsgNotification[];
    getUnreadNotificationCount(userId: number): number;
    markNotificationRead(notificationId: number, userId: number): void;
    markAllNotificationsRead(userId: number): void;
    /** Get the last-analyzed message ID for a scope, or 0 if never analyzed. */
    getAnalysisMarker(scopeKey: string): number;
    /** Set the last-analyzed message ID for a scope (UPSERT, monotonic). */
    setAnalysisMarker(scopeKey: string, messageId: number): void;
    close(): void;
    private ensureGitignore;
    private toNotification;
    private toMessage;
}
