export interface VerifiedDownloadSpec { readonly url: string; /** Expected byte count (pinned). */ readonly bytes: number; /** Expected lowercase hex sha256 (pinned). */ readonly sha256: string; } export interface VerifiedDownloadOptions { readonly spec: VerifiedDownloadSpec; readonly destPath: string; readonly fetchImpl?: typeof fetch | undefined; readonly timeoutMs?: number | undefined; /** Progress callback (best-effort). */ readonly onProgress?: ((phase: 'skip' | 'download' | 'verify' | 'done', message?: string) => void) | undefined; } export type VerifiedDownloadResult = { readonly ok: true; readonly path: string; readonly bytes: number; readonly skipped: boolean; } | { readonly ok: false; readonly reason: 'download-failed' | 'checksum-mismatch' | 'size-mismatch'; readonly error: string; }; /** * The lowercase hex sha256 of a file, or null when it cannot be read. For * honest "got X, want Y" mismatch reporting; never throws. */ export declare function fileSha256(path: string): string | null; /** True when an existing file already matches the pinned size + checksum. */ export declare function fileMatches(path: string, spec: VerifiedDownloadSpec): boolean; /** * Like {@link fileMatches} but cached by (path, size, mtime): repeated status * polls do not synchronously re-read and re-hash a 63MB model on every call. * A file whose size or mtime changed is re-verified with the full hash, * provisioning decisions (download skip/replace) always use the full hash. */ export declare function fileMatchesCached(path: string, spec: VerifiedDownloadSpec): boolean; /** * Download a component to `destPath` atomically, verifying size + sha256. * Skips (returns skipped:true) when the file already matches, this is what * makes a re-run resumable. Never leaves a partial or unverified file in place. */ export declare function downloadVerifiedFile(options: VerifiedDownloadOptions): Promise; //# sourceMappingURL=download-verified.d.ts.map