/** * Cron scheduler — runs scheduled tasks at specified intervals. * Jobs are stored in the cron_jobs DB table and executed by sending prompts * to the agent via the pipeline. */ import type Database from "better-sqlite3"; import { type ChatAccessContext } from "./access.js"; /** 把 cron 表达式转成人类可读频率描述(用于卡片标题);无法识别时原样返回。 * 展示一律按当前展示时区。旧任务的钟点数字可能按当时机器时区写入,换算后再显示。 */ export declare function describeCronExpr(expr: string, sourceTz?: string, displayTz?: string): string; /** Cron 任务触发节奏描述:表达式优先;一次性任务显示本地时间。 */ export declare function describeCronSchedule(expr: string | null, runAt: string | null, timezone?: string): string; /** 把相对间隔(秒)转成 cron 表达式;秒级或无法整分/整时/整天表达时返回 undefined。 */ export declare function everyToCronExpr(seconds: number): string | undefined; export declare const MAX_ACTIVE_CRON_JOBS_PER_CHAT = 20; export declare const DEFAULT_MAX_CONCURRENT_CRON_RUNS = 4; export declare const CRON_FAILURE_LIMIT = 3; export interface CronJob { id: number; chatId: string; threadId: string | null; replyToMsgId: string | null; creatorUserId: string; cronExpr: string | null; runAt: string | null; prompt: string; description: string; maxTimes: number | null; untilTime: string | null; runCount: number; status: string; lastRunAt: string | null; timezone: string; claimedAt: string | null; claimToken: string | null; lastError: string | null; consecutiveFailures: number; } export type CronExecutor = (chatId: string, userId: string, prompt: string, description: string, cronJobId: number, claimToken: string, threadId?: string) => Promise; export type CronFailureReporter = (chatId: string, description: string, error: string, paused: boolean, threadId?: string, replyToMsgId?: string) => Promise | void; export interface CronSchedulerOptions { maxConcurrent?: number; reportFailure?: CronFailureReporter; } export declare class CronScheduler { private db; private executor; private timer; private running; /** 当前 tick 的 Promise;stop() 等待它结束,保证 cron_jobs 更新在 DB 关闭前完成。 */ private currentTick; private stopping; private readonly maxConcurrent; private readonly reportFailure?; constructor(db: Database.Database, executor: CronExecutor, options?: CronSchedulerOptions); start(): void; /** 停止调度并等待当前 tick 结束(tick 内会更新 cron_jobs,必须在 DB 关闭前完成)。 */ stop(): Promise; private tick; private executeClaimedJob; } /** Restore claims left behind by a stopped process. Recurring jobs keep the claim minute * in last_run_at, so they do not repeat within that minute after restart. */ export declare function recoverInterruptedCronJobs(db: Database.Database): number; /** Select and atomically claim every job due at this instant. */ export declare function claimDueCronJobs(db: Database.Database, now?: Date): CronJob[]; /** Add a cron job */ export declare function addCronJob(db: Database.Database, opts: { chatId: string; threadId?: string; replyToMsgId?: string; creatorUserId: string; cronExpr?: string; runAt?: string; prompt: string; description?: string; maxTimes?: number; untilTime?: string; timeZone?: string; }): number; /** Validate the five-field Cron subset implemented by matchesCron(). */ export declare function validateCronExpression(expression: string): void; /** List active cron jobs for a chat */ export declare function listCronJobs(db: Database.Database, chatId?: string, threadId?: string): Array; /** List active cron jobs visible from the current access context */ export declare function listCronJobsForAccess(db: Database.Database, options: ChatAccessContext & { targetChatId?: string; }): Array; /** Cancel a cron job. Keep the row for audit/history and invalidate any active claim. */ export declare function deleteCronJob(db: Database.Database, id: number): boolean; /** Delete a cron job after checking chat visibility and creator ownership. */ export declare function deleteCronJobForAccess(db: Database.Database, id: number, ctx: ChatAccessContext & { userId?: string; }): CronJob & { createdAt: string; } | undefined; /** Get a cron job by ID */ export declare function getCronJob(db: Database.Database, id: number): (CronJob & { createdAt: string; }) | undefined; /** * Simple cron expression matcher. * Supports: minute hour day month weekday * Each field: number, *, or comma-separated values */ export declare function matchesCron(expr: string, date: Date, timeZone: string): boolean; /** Normalize datetime string: replace 'T' separator with space for consistent comparison */ export declare function normalizeDatetime(s: string): string; /** Convert pre-v16 cron timestamps, which were stored as local wall-clock text, to UTC once. */ export declare function migrateLegacyCronTimezones(db: Database.Database, timeZone?: string): number;