/** * The operator's intended runtime posture. * * - `running` — discover candidates, screen them, send outbound messages and * automate replies. * - `scan` — keep conversations in sync (chat refresh, reply detection, * response checking) but send nothing and start no new outreach. Actionable * replies are surfaced as backlog for a human instead of being answered. * - `stopped` — everything halts. * * `scan` differs from `browser.dryRun`: dry run still discovers and screens * candidates (and pays for the AI screening), it just suppresses the send. */ export type BotMode = 'running' | 'scan' | 'stopped'; export const BOT_MODES: readonly BotMode[] = ['running', 'scan', 'stopped']; export function isBotMode(value: unknown): value is BotMode { return typeof value === 'string' && (BOT_MODES as readonly string[]).includes(value); } /** Falls back to `stopped` so an unreadable persisted value never auto-sends. */ export function parseBotMode(value: unknown, fallback: BotMode = 'stopped'): BotMode { return isBotMode(value) ? value : fallback; } /** Outbound messages and automated replies. */ export function allowsSending(mode: BotMode): boolean { return mode === 'running'; } /** Subreddit scanning, AI screening and candidate dispatch. */ export function allowsDiscovery(mode: BotMode): boolean { return mode === 'running'; } /** Chat refresh, reply detection and response checking. */ export function allowsConversationSync(mode: BotMode): boolean { return mode === 'running' || mode === 'scan'; } export function describeBotMode(mode: BotMode): string { switch (mode) { case 'running': return 'Running'; case 'scan': return 'Scanning'; case 'stopped': return 'Stopped'; } }