/** * What the store found on disk, and therefore how the poller must start. * * - `resume` , a valid cursor; continue exactly where the last run stopped. * - `fresh` , no cursor file at all (first run, or the surface was just * enabled). Start with NO offset so Telegram hands over its * retained backlog. This is deliberate: a user who sends /start * before the daemon is running must still be answered, which is * precisely the case that made the missing ingress path visible. * - `skip-ahead`, the cursor file existed but was torn or implausible. We * cannot know which updates were already dispatched, so the * poller jumps to the newest update instead of replaying. * Rationale: replaying spawns duplicate agents that do real work * on the user's machine and send duplicate messages, whereas * skipping loses at most the messages sent since the crash, * which the user can see went unanswered and can resend. * Duplicated autonomous work is the worse failure. */ export type TelegramOffsetStart = { readonly mode: 'resume'; readonly offset: number; } | { readonly mode: 'fresh'; } | { readonly mode: 'skip-ahead'; readonly reason: string; }; export declare class TelegramOffsetStore { private readonly filePath; constructor(filePath: string); /** * Read the cursor and decide how to start. Never throws: a store that cannot * be read must degrade to a stated recovery mode, not stop ingress. */ load(): TelegramOffsetStart; /** * Persist the cursor. Called after a batch is fully processed, so an update * is only confirmed once the work it triggered has been handed off, a crash * mid-batch replays that batch rather than losing it. */ save(offset: number): void; /** Remove the cursor entirely, used when the surface is reconfigured. */ clear(): void; /** Delete an unusable cursor file and report why, so it cannot fail every boot. */ private sweep; } //# sourceMappingURL=offset-store.d.ts.map