import { type ResourceRegistry } from "./utils.js"; export type WarmTaskKind = "driver-install" | "browser-install" | "device-boot" | "wda-check" | "session-probe" | "chromedriver-prefetch"; export type WarmOutcome = "warmed" | "skipped" | "failed"; export type WarmTask = { name: string; kind: WarmTaskKind; exclusiveResources: string[]; payload: Record; }; export type WarmTaskResult = { name: string; kind: WarmTaskKind; outcome: WarmOutcome; durationMs: number; note?: string; }; export type WarmReport = { durationMs: number; tasks: WarmTaskResult[]; }; export declare const WARM_POOL_LIMIT = 4; export declare const RUNTIME_INSTALL_RESOURCE = "runtime-install"; /** * The single identity a warm device task is deduped, named, and * tag-serialized by. It mirrors how the acquisition planners converge on a * device: a NAMED descriptor always resolves to that registry name (whatever * its other fields say), so two same-named descriptors are one device even * when their osVersions differ — a second boot task would just registry-hit * and block a warm worker on the full boot. Unnamed (default) descriptors * resolve by deviceType + osVersion, so those fields distinguish devices. */ export declare function deviceIdentity(platform: string, desc: { name?: string; deviceType?: string; osVersion?: string; } | undefined): string; export declare function deviceResourceTag(platform: string, desc: { name?: string; deviceType?: string; osVersion?: string; } | undefined): string; /** * Re-wrap the named effect functions on an acquire-deps object so the first * invocation of any of them fires `signal` — the boot-initiation hook * raceBootInitiation races against. Shared by the android (createAvd/boot) * and ios (create/boot) device-boot bodies so the initiation contract lives * in one place. */ export declare function wrapInitiationEffects>(deps: T, keys: (keyof T)[], signal: () => void): T; export type WarmPlanDeps = { isBrowserRequired(args: { test: any; }): boolean; isAppDriverRequired(args: { test: any; }): boolean; isMobileTargetPlatform(platform: unknown): "android" | "ios" | null; getDefaultBrowser(args: { runnerDetails: any; }): any; requiredBrowserAssets(name: string | undefined): unknown[]; collectDeviceDescriptors(context: any): any[]; normalizeDeviceDescriptor(args: { contextDevice?: any; stepDevice?: any; platform: "android" | "ios"; }): any; mobileBrowserGate(args: { platform: "android" | "ios"; browser?: any; hasBrowserStep: boolean; hasAppStep: boolean; }): { action: "proceed"; browserName: string | null; } | { action: "skip"; level: "warning"; reason: string; } | { action: "fail"; reason: string; }; contextRequirementsSkipMessage(args: { context: any; }): string | null; appDriverPlatforms: Record; }; /** * Derive the warm tasks a run needs from its sizing jobs (flat + routed). * Pure: no I/O of its own, and — unlike selectWarmUpTargets — it never * writes defaults onto the job contexts; effective platform/browser are * computed locally so planning leaves the jobs byte-identical for the * execution paths that own those mutations. * * Derivation is strictly "what the run's own paths would JIT-provision": * a pure-web run plans only the browser installs (and, at limit > 1 with a * pool, the session probe) that today's pre-pass already performs; mobile * and app contexts add their driver installs, device boots, WDA check, and * chromedriver prefetch. Anything the run's own gates would refuse before * provisioning — an unmet `requires` gate, an ios context off darwin, a * windows app context off windows, a mobile context the browser gate * skips/fails — is not planned, mirroring the per-context gates. */ export declare function planWarmTasks({ sizingJobs, runnerDetails, limit, hasAppiumPool, deps, }: { sizingJobs: any[]; runnerDetails: any; limit: number; hasAppiumPool: boolean; deps: WarmPlanDeps; }): WarmTask[]; /** * Run planned warm tasks through the run's resource registry, bounded by * WARM_POOL_LIMIT. Best-effort by contract: a task that throws is recorded * as failed and logged as a warning — the returned promise never rejects, * and nothing here can gate the run. */ export declare function executeWarmTasks({ tasks, registry, runTask, log, now, }: { tasks: WarmTask[]; registry: ResourceRegistry; runTask: (task: WarmTask) => Promise<{ outcome: WarmOutcome; note?: string; }>; log: (level: string, message: string) => void; now?: () => number; }): Promise; /** * Resolve a device-boot task at boot INITIATION rather than boot completion: * warm's job is to start the clock early, not to block on it — the first * consuming context awaits the registry entry's `ready` promise exactly * where it does today. * * `startAcquire` receives a `signalInitiated` callback the caller wires into * the acquire deps' create/boot effects (wrapInitiationEffects). * acquireDevice/acquireSimulator invoke those effects synchronously inside * the ready-promise body and then synchronously register the * `bootedByUs: true` placeholder before any microtask runs — so by the time * the race resolves on the signal, the registry entry (with its in-flight * `ready`) is already visible to consumers. Fast paths (registry hit, * reuse-running, plan skip) never signal and settle through the acquire * promise itself. * * The catch is chained onto the acquire promise BEFORE the race, so a boot * that fails after the task already resolved can never surface as an * unhandled rejection; `onError` is the caller's warn hook. acquire deletes * its registry placeholder on failure, so a consuming context retries fresh. */ export declare function raceBootInitiation({ startAcquire, onError, }: { startAcquire: (signalInitiated: () => void) => Promise<{ entry?: any; skip?: string; }>; onError: (error: unknown) => void; }): Promise<{ outcome: WarmOutcome; note?: string; }>; //# sourceMappingURL=warmPhase.d.ts.map