import type Database from 'better-sqlite3';
export type OutboxStatus = 'pending' | 'delivered' | 'giving_up';
export type OutboxKind = 'text' | 'card' | 'typing';
export type OutboxPriority = 'high' | 'normal';
export interface OutboxRow {
    id: number;
    job_id: number | null;
    thread_key: string;
    platform: string;
    channel_id: string;
    thread_id: string;
    payload: string;
    kind: OutboxKind;
    priority: OutboxPriority;
    status: OutboxStatus;
    attempts: number;
    last_attempt_at: string | null;
    last_error: string | null;
    delivered_at: string | null;
    next_attempt_at: string | null;
    created_at: string;
}
export interface EnqueueOpts {
    threadKey: string;
    platform: string;
    channelId: string;
    threadId: string;
    /** For text/card: serialized payload (text body or JSON of card). For typing: unused, pass ''. */
    payload: string;
    kind: OutboxKind;
    priority?: OutboxPriority;
    jobId?: number | null;
}
export declare const MAX_ATTEMPTS: 6;
/** Stop the retention sweep (graceful shutdown / tests). */
export declare function stopOutboxRetentionSweep(): void;
/** Close the underlying SQLite handle. Called by cli.ts on graceful shutdown. */
export declare function closeOutboxDb(): void;
/** Insert a new pending row. Returns the row id, or -1 if the DB is broken
 *  (caller should fall back to direct send).
 *
 *  R13 B5 — outbound text payloads are scrubbed for secret-shaped
 *  substrings before insert. Defense-in-depth tail behind B1's hard
 *  denylist: if an agent dumps a token / private key / .env block
 *  via a path the denylist missed, the scrubber catches it on the
 *  way out. The scrubbed payload is what hits SQLite + the wire;
 *  the original never persists. */
export declare function enqueue(opts: EnqueueOpts): number;
/** Pick up to `limit` pending rows whose next_attempt_at is now-or-past,
 *  highest priority first. Worker calls this on each tick. */
export declare function pickPending(limit?: number): OutboxRow[];
/** Mark a row delivered. */
export declare function markDelivered(id: number): void;
/** Record a failed attempt. If attempts have exhausted the backoff schedule
 *  the row transitions to 'giving_up' (and no longer drains). Otherwise it
 *  stays 'pending' with next_attempt_at = now + backoff. */
export declare function markFailed(id: number, error: string): {
    gaveUp: boolean;
    attempts: number;
};
/** Get one row by id. */
export declare function getOutbox(id: number): OutboxRow | null;
/** List rows in 'giving_up' or 'pending' state for /outbox command. */
export declare function listOutbox(opts?: {
    status?: OutboxStatus;
    limit?: number;
    threadKey?: string;
}): OutboxRow[];
/** Aggregate counts for /outbox status. */
export declare function getOutboxStats(): Record<OutboxStatus, number>;
/** Resurrect a 'giving_up' row back to 'pending' so the worker tries again.
 *  Resets attempts to 0 so the full backoff ladder applies again. */
export declare function retryGivingUp(id: number): boolean;
/** Prune delivered + giving_up rows older than the retention window. */
export declare function pruneOldOutbox(d?: Database.Database): number;
/** Test hook: wipe everything. Only safe in unit tests. */
export declare function _resetOutboxForTests(): void;
//# sourceMappingURL=outbox.d.ts.map