import { SkillSelectionError, type SelectionCacheOptions } from "./selection-cache.js"; import { type SessionReconciliationOptions } from "./session-reconciliation.js"; /** The longest an expired-pin prompt waits for its background renewal. */ export declare const BACKGROUND_RENEWAL_WAIT_MS = 3000; /** A lock older than this belongs to no live worker (the worker's own budget plus margin). */ export declare const BACKGROUND_RENEWAL_LOCK_TTL_MS: number; /** A failed attempt for the same pin is reported again, not retried, within these windows. */ export declare const EXPIRED_RENEWAL_RETRY_MS = 30000; export declare const AHEAD_RENEWAL_RETRY_MS: number; export type BackgroundRenewalMode = "expired" | "ahead"; export type BackgroundRenewalStatus = "running" | "renewed" | "migrated" | "unchanged" | "failed"; export interface BackgroundRenewalState { schemaVersion: 1; kind: "session-pin-background-renewal"; sessionId: string; profileId: string; operationId: string; /** verifiedAt of the exact pin this attempt renews. */ pinVerifiedAt: string; mode: BackgroundRenewalMode; status: BackgroundRenewalStatus; startedAt: string; finishedAt?: string; workerPid?: number; code?: string; migrationTimeout?: true; /** No worker could be started; such a record never delays the next attempt. */ notStarted?: true; /** * The exact request this attempt answers: the receipt bytes, mode, * migration setting and prompt directory. A recorded failure is reused only * for the same request; any change (a rewritten receipt, migration turned * on, another directory) asks again at once. */ requestDigest?: string; } export interface BackgroundRenewalRequest { sessionId: string; profileId: string; pinVerifiedAt: string; mode: BackgroundRenewalMode; /** SHA-256 of the exact receipt bytes this request read. */ receiptSha256: string; /** Expired pins only: the managed hook's automatic migration of a refused renewal. */ migrate?: boolean; /** The prompt's directory, which migration requires (project locks keep the refusal). */ projectDir?: string; } export interface BackgroundRenewalOptions extends SelectionCacheOptions { /** * Tests replace the detached worker; production spawns `skills sessions * renew-background`. `notStarted` is called if the worker fails to start * after this returns (an asynchronous spawn error such as EAGAIN). */ spawnWorker?: (args: string[], notStarted: () => void) => void; } /** The identity of one renewal request; equal digests ask the authority the same question. */ export declare function backgroundRenewalRequestDigest(request: BackgroundRenewalRequest): string; /** * The last recorded attempt for this session, or null when absent or not * exact. Only validated fields are returned; anything else in the file is * dropped, so no unvalidated value reaches a caller's output. */ export declare function readBackgroundRenewalState(sessionId: string, options?: SelectionCacheOptions): BackgroundRenewalState | null; export type BackgroundRenewalStart = /** `operationId` names the attempt to wait for, when its lock is readable. */ { status: "started" | "running"; operationId?: string; } /** `notStarted`: no worker could be started, so the caller may renew inline instead. */ | { status: "failed"; state: BackgroundRenewalState; notStarted?: true; }; /** * Start the session's background renewal unless one is running, or report a * recent failure of the same pin without starting another. */ export declare function startBackgroundRenewal(request: BackgroundRenewalRequest, options?: BackgroundRenewalOptions): BackgroundRenewalStart; export type BackgroundRenewalWait = { status: "running" | "changed"; } | { status: Exclude; state: BackgroundRenewalState; }; /** * Wait up to waitMs for the attempt renewing this exact pin to finish, or for * the session receipt to stop holding that pin. With an operation id, only * that attempt's outcome counts. */ export declare function awaitBackgroundRenewal(sessionId: string, pinVerifiedAt: string, waitMs: number, options?: SelectionCacheOptions, operationId?: string): Promise; export interface BackgroundRenewalRun { status: BackgroundRenewalStatus | "superseded"; code?: string; } /** * The worker: renew (or, for an expired pin with migration on, migrate) one * session pin with the background budget, record the outcome, release the lock. */ export declare function runBackgroundRenewal(sessionId: string, profileId: string, operationId: string, request: { migrate?: boolean; projectDir?: string; }, options?: SessionReconciliationOptions): Promise; /** * An expired pin whose background renewal is still running. It keeps the * renewal timeout's code (fixed codes cross the hook boundary) and a fixed * marker so the hook can say the renewal continues instead of restarting. */ export declare class SessionRenewalInBackground extends SkillSelectionError { readonly renewal: "background"; constructor(); } /** The recorded failure of a background attempt, as the error the inline renewal would have raised. */ export declare function backgroundRenewalError(state: BackgroundRenewalState): SkillSelectionError; /** The pin's age class, from its verifiedAt; null when it is neither due nor expired. */ export declare function renewalModeFor(verifiedAt: string, now: number): BackgroundRenewalMode | null;