import type { Context } from '../../api.js'; import type { SlackMessageEvent } from './types.js'; import type { ChannelMeta } from './scope.js'; export interface SlackHistoryPage { messages: SlackMessageEvent[]; next_cursor: string | null; } export type SlackHistoryFetcher = (args: { channelId: string; /** Slack's opaque pagination token. Null on first page of a backfill run. */ cursor: string | null; /** * Incremental-resume bound: skip messages with ts <= oldest. Set from * `slack_cursors.latest_ts` on the FIRST page of a rerun; unused on * subsequent pages within one run (where `cursor` carries us forward). * Distinct from `cursor` because Slack treats `cursor` as opaque token * and `oldest` as a numeric ts — feeding `latest_ts` as `cursor` breaks * against the live API even though it round-trips through test fetchers. */ oldest?: string; }) => Promise; export interface BackfillOpts { teamId: string; channel: ChannelMeta; fetcher: SlackHistoryFetcher; /** Stop after this many messages. Default: unlimited. */ maxMessages?: number; } /** * Page through `conversations.history` via the injected fetcher and ingest each * message. The cursor is persisted to `slack_cursors` after every page so a * crash mid-backfill resumes near where it left off. * * Each ingested message uses a synthesized eventId of the form * `backfill:${teamId}:${channelId}:${ts}`. Reruns dedupe via the * `slack_event_log` PK so calling `backfillChannel` twice is safe. */ export declare function backfillChannel(ctx: Context, opts: BackfillOpts): Promise<{ ingested: number; pages: number; }>; //# sourceMappingURL=backfill.d.ts.map