import type { CronConfig } from "../../config/types.cron.js";
import type { HeartbeatRunResult } from "../../infra/heartbeat-wake.js";
import type { CronGraphNodeHandlerParams, CronGraphNodeHandlerResult, CronTaskGraphContextItem } from "../graph-context.js";
import type { CronTaskRunQueueSummary } from "../task-run-queue.js";
import type { CronDeliveryStatus, CronJob, CronJobCreate, CronJobPatch, CronTaskAccessBlock, CronRunOutcome, CronRunStatus, CronRunTelemetry, CronStoreFile } from "../types.js";
export type CronEvent = {
    jobId: string;
    action: "added" | "updated" | "removed" | "started" | "finished" | "blocked";
    runAtMs?: number;
    durationMs?: number;
    status?: CronRunStatus;
    error?: string;
    summary?: string;
    delivered?: boolean;
    deliveryStatus?: CronDeliveryStatus;
    deliveryError?: string;
    sessionId?: string;
    sessionKey?: string;
    nextRunAtMs?: number;
} & CronRunTelemetry;
export type Logger = {
    debug: (obj: unknown, msg?: string) => void;
    info: (obj: unknown, msg?: string) => void;
    warn: (obj: unknown, msg?: string) => void;
    error: (obj: unknown, msg?: string) => void;
};
export type CronServiceDeps = {
    nowMs?: () => number;
    log: Logger;
    storePath: string;
    cronEnabled: boolean;
    /** CronConfig for session retention settings. */
    cronConfig?: CronConfig;
    /** Default agent id for jobs without an agent id. */
    defaultAgentId?: string;
    /** Resolve session store path for a given agent id. */
    resolveSessionStorePath?: (agentId?: string) => string;
    /** Path to the session store (sessions.json) for reaper use. */
    sessionStorePath?: string;
    enqueueSystemEvent: (text: string, opts?: {
        agentId?: string;
        sessionKey?: string;
        contextKey?: string;
    }) => void;
    requestHeartbeatNow: (opts?: {
        reason?: string;
        agentId?: string;
        sessionKey?: string;
    }) => void;
    runHeartbeatOnce?: (opts?: {
        reason?: string;
        agentId?: string;
        sessionKey?: string;
    }) => Promise<HeartbeatRunResult>;
    /**
     * WakeMode=now: max time to wait for runHeartbeatOnce to stop returning
     * { status:"skipped", reason:"requests-in-flight" } before falling back to
     * requestHeartbeatNow.
     */
    wakeNowHeartbeatBusyMaxWaitMs?: number;
    /** WakeMode=now: delay between runHeartbeatOnce retries while busy. */
    wakeNowHeartbeatBusyRetryDelayMs?: number;
    runIsolatedAgentJob: (params: {
        job: CronJob;
        message: string;
        abortSignal?: AbortSignal;
        graphContext?: CronTaskGraphContextItem[];
        /**
         * When true, execution should produce a replayable result but leave
         * outbound channel delivery to the durable queue's `deliver` step.
         */
        deferDelivery?: boolean;
    }) => Promise<{
        summary?: string;
        /** Last non-empty agent text output (not truncated). */
        outputText?: string;
        /**
         * `true` when the isolated run already delivered its output to the target
         * channel (including matching messaging-tool sends). See:
         * https://github.com/fased-ai/fased/issues/15692
         */
        delivered?: boolean;
        /**
         * `true` when announce/direct delivery was attempted for this run, even
         * if the final per-message ack status is uncertain.
         */
        deliveryAttempted?: boolean;
    } & CronRunOutcome & CronRunTelemetry>;
    runGraphNodeHandler?: (params: CronGraphNodeHandlerParams) => Promise<CronGraphNodeHandlerResult>;
    deliverIsolatedAgentJobResult?: (params: {
        job: CronJob;
        runId: string;
        result: CronRunOutcome & CronRunTelemetry & {
            delivered?: boolean;
            deliveryAttempted?: boolean;
        };
        abortSignal?: AbortSignal;
    }) => Promise<{
        delivered?: boolean;
        deliveryAttempted?: boolean;
    } & CronRunOutcome & CronRunTelemetry>;
    preflightJobAccess?: (job: CronJob) => CronTaskAccessBlock | undefined;
    onEvent?: (evt: CronEvent) => void;
};
export type CronServiceDepsInternal = Omit<CronServiceDeps, "nowMs"> & {
    nowMs: () => number;
};
export type CronServiceState = {
    deps: CronServiceDepsInternal;
    store: CronStoreFile | null;
    timer: NodeJS.Timeout | null;
    activeRunAbortControllers: Map<string, AbortController>;
    running: boolean;
    op: Promise<unknown>;
    warnedDisabled: boolean;
    storeLoadedAtMs: number | null;
    storeFileMtimeMs: number | null;
};
export declare function createCronServiceState(deps: CronServiceDeps): CronServiceState;
export type CronRunMode = "due" | "force";
export type CronWakeMode = "now" | "next-heartbeat";
export type CronStatusSummary = {
    enabled: boolean;
    storePath: string;
    jobs: number;
    nextWakeAtMs: number | null;
    queue: CronTaskRunQueueSummary;
};
export type CronRunResult = {
    ok: true;
    ran: true;
} | {
    ok: true;
    ran: false;
    reason: "not-due";
} | {
    ok: true;
    ran: false;
    reason: "already-running";
} | {
    ok: false;
};
export type CronRemoveResult = {
    ok: true;
    removed: boolean;
} | {
    ok: false;
    removed: false;
};
export type CronAddResult = CronJob;
export type CronUpdateResult = CronJob;
export type CronListResult = CronJob[];
export type CronAddInput = CronJobCreate;
export type CronUpdateInput = CronJobPatch;
