export declare const MAX_PENDING_PER_USER = 50;
export declare const MIN_FUTURE_MS: number;
export declare const MAX_FUTURE_MS: number;
export declare const MAX_TEXT_LEN = 1000;
export type ReminderStatus = 'pending' | 'firing' | 'fired' | 'cancelled' | 'failed';
export type PromptMode = 'literal' | 'llm';
export interface Reminder {
    id: number;
    fire_at: string;
    text: string;
    platform: string;
    channel_id: string;
    thread_id: string;
    user_id: string;
    status: ReminderStatus;
    created_at: string;
    fired_at: string | null;
    error: string | null;
    source: string;
    parent_id: number | null;
    recurrence: string | null;
    last_fired_at: string | null;
    /** 'llm' = at fire time, treat `text` as a prompt and ask the active
     *  agent to compose the actual delivery. 'literal' = deliver `text` as-is. */
    prompt_mode: PromptMode;
}
export interface CreateReminderInput {
    fireAt: Date;
    text: string;
    platform: string;
    channelId: string;
    threadId: string;
    userId: string;
    source?: 'slash' | 'mcp' | 'api';
    parentId?: number;
    /** Recurrence spec: `every:5m` / `daily:HH:MM` / `weekly:1,3,5:HH:MM`.
     *  When set, the row stays `pending` after each fire and `fire_at` is rolled
     *  forward to the next occurrence. Cancel via /remind cancel <id>. */
    recurrence?: string;
    /** Default 'llm'. Set 'literal' to bypass LLM polish and deliver text as-is. */
    promptMode?: PromptMode;
}
export interface OwnerOpts {
    /** When set, list/get/cancel/snooze only see rows where user_id matches
     *  OR is empty (legacy/system rows). Same model as schedule.ts. */
    creatorId?: string;
}
export declare class ReminderError extends Error {
    code: string;
    constructor(code: string, msg: string);
}
/** "2m" / "90s" / "3h" / "1d" → milliseconds. Rejects 0/negative/non-int. */
export declare function parseDuration(s: string): number | null;
/** "18:30" → today's 18:30 if still in the future, else tomorrow's 18:30.
 *  Uses server TZ (override at process level via TZ=… env). */
export declare function parseClock(s: string, now?: Date): Date | null;
/** ISO-ish absolute datetime "2026-05-09T20:00" / "2026-05-09T20:00:00Z" etc.
 *  Trailing seconds and timezone suffix are optional. */
export declare function parseISO(s: string): Date | null;
/** Unified parser tried in order: duration → clock → ISO. */
export declare function parseWhen(s: string, now?: Date): {
    ok: true;
    fireAt: Date;
} | {
    ok: false;
    reason: string;
};
/**
 * Consume a time-expression prefix from the head of `s`, supporting Chinese
 * (no-separator allowed: "40秒喝水" / "下午6点下班") and English/ISO formats.
 * Returns { fireAt, rest } on success, null when nothing matches.
 *
 * This is the main entry point used by the /remind slash handler so users
 * don't need to remember strict syntax.
 */
export declare function parseWhenPrefix(s: string, now?: Date): {
    fireAt: Date;
    rest: string;
} | null;
export declare const MIN_RECURRENCE_INTERVAL_MS: number;
/** Validate a recurrence spec string. Returns true if parseable. */
export declare function isValidRecurrence(spec: string): boolean;
/**
 * Compute the next fire time for a recurring reminder.
 *
 * `anchor` is the previous fire_at (for `every:` we step forward from there;
 * if we missed cycles while offline, we fast-forward past `now`). For clock-
 * based recurrences (daily/weekly) anchor is ignored — we always pick the
 * next future slot from `now`.
 *
 * Returns null if the spec is malformed or has no satisfiable next slot.
 */
export declare function computeNext(spec: string, anchor: Date, now: Date): Date | null;
/** Human-readable recurrence label for /remind list. */
export declare function describeRecurrence(spec: string): string;
/**
 * Consume a recurrence prefix from the head of `s`. Supports:
 *
 *   每5分钟 / 每隔5分钟 / 每2小时 / 每30秒（拒绝, 不做亚分钟级）
 *   每天早上8点 / 每日下午6点半 / 每天8:30
 *   每周一8点 / 每周一三五9点 / 每周末10点 / 每个工作日9点
 *   every 5m / every 1h
 *
 * Returns `{ recurrence, fireAt, rest }` where `fireAt` is the FIRST occurrence
 * (≥ now). `null` when no recurrence pattern matched.
 */
export declare function parseRecurrencePrefix(s: string, now?: Date): {
    recurrence: string;
    fireAt: Date;
    rest: string;
} | null;
export declare function createReminder(input: CreateReminderInput): number;
export declare function listReminders(opts?: OwnerOpts & {
    status?: ReminderStatus;
    limit?: number;
}): Reminder[];
export declare function getReminder(id: number, opts?: OwnerOpts): Reminder | null;
export declare function cancelReminder(id: number, opts?: OwnerOpts): boolean;
export declare function clearReminders(opts: {
    creatorId: string;
}): number;
/** Snooze an existing reminder by `deltaMs`: clones the row's text and target
 *  thread to a new pending row, then marks the original 'cancelled' (if still
 *  pending) or just chains parent_id (if already fired). Returns new id. */
export declare function snoozeReminder(id: number, deltaMs: number, opts?: OwnerOpts): number;
/** Bind (or rebind) an email address to an IM user. Returns the bound email. */
export declare function bindEmail(platform: string, userId: string, email: string): string;
/** Look up the bound email for an IM user, or null. */
export declare function getBoundEmail(platform: string, userId: string): string | null;
/** Remove the binding for an IM user. Returns true if a row was deleted. */
export declare function unbindEmail(platform: string, userId: string): boolean;
/**
 * Render a compact "background context" block listing the user's pending
 * reminders for the current platform. Used by router.ts to prepend to the
 * agent prompt so the agent has live visibility into the user's queue —
 * lets it answer "what reminders do I have?" without an extra
 * list_reminders tool call, and avoids creating duplicates.
 *
 * Empty string when nothing pending — caller should noop.
 *
 * Cost: ~80-200 tokens per message when populated. Bounded to 5 reminders.
 */
export declare function buildContextSnippet(platform: string, userId: string): string;
/** Whether the LLM intent detector should run for this user's non-slash
 *  messages. Default on (no row = enabled). DB-unavailable also returns
 *  true so users on bun/fail-soft don't lose the feature silently. */
export declare function isAiwatchEnabled(platform: string, userId: string): boolean;
/** Set the aiwatch enabled flag. UPSERT semantics. Returns the new value. */
export declare function setAiwatchEnabled(platform: string, userId: string, enabled: boolean): boolean;
/** Move a failed/cancelled reminder back to pending with a fresh fireAt
 *  (now + MIN_FUTURE_MS). Owner-scoped. Returns true on success. */
export declare function retryReminder(id: number, opts?: OwnerOpts): boolean;
/** Run a single tick. Exposed for tests so they can advance the clock manually. */
export declare function tick(now?: Date): Promise<number>;
/** Start the periodic ticker. Idempotent. */
export declare function startReminderEngine(): void;
export declare function stopReminderEngine(): void;
export declare function closeReminderDb(): void;
//# sourceMappingURL=reminders.d.ts.map