/** Root for downloaded media. Always resolved absolute so the safety check
 *  `path.startsWith(MEDIA_ROOT)` is robust. Override via env for tests.
 *
 *  Bug fix (2026-05-23): two `.test.ts` files in different platform
 *  adapters each set `process.env.IMHUB_MEDIA_ROOT` to their own tmp dir
 *  before dynamically importing media-download.js. Under bun's shared
 *  test-process module cache the first import wins and the second test
 *  reads the wrong root. Fix: read env at every call site via
 *  `getMediaRoot()` rather than at module-eval time. `MEDIA_ROOT` is
 *  kept as a backwards-compatible alias that reflects the value at
 *  import time — production reads happen post-startup so the env is
 *  stable anyway. */
export declare function getMediaRoot(): string;
export declare const MEDIA_ROOT: string;
/** Hard upper bound on a single download. Telegram photo max is ~10 MB and
 *  document max is 50 MB on the bot API; we cap at 20 MB so a runaway upload
 *  can't fill the disk. */
export declare const MAX_BYTES: number;
/** Default cleanup TTL — 7 days. Long enough that a multi-day conversation
 *  can re-reference an image, short enough that the directory doesn't grow
 *  without bound. Override via env for ops. */
export declare const DEFAULT_TTL_MS: number;
export interface DownloadParams {
    /** TG file URL — must be on api.telegram.org. */
    url: string;
    /** Destination folder under MEDIA_ROOT, typically `${platform}/${chatId}`. */
    subdir: string;
    /** Filename (no path components). */
    filename: string;
}
export interface DownloadResult {
    path: string;
    bytes: number;
}
/**
 * Download `url` and write it to `<MEDIA_ROOT>/<subdir>/<filename>`. Returns
 * the absolute path on success. Errors out (and writes nothing) on:
 *   - non-https or non-telegram host
 *   - HTTP non-2xx
 *   - body larger than MAX_BYTES
 *   - destination resolves outside MEDIA_ROOT (path-injection guard)
 *
 * Best-effort cleanup: if write fails partway through, the partial file is
 * removed so a half-saved image never reaches the agent.
 */
export declare function downloadToMediaRoot(params: DownloadParams): Promise<DownloadResult>;
/**
 * Spawn curl to fetch `url` directly to `outPath`. Resolves on exit code 0,
 * rejects with an Error containing curl's stderr on any other exit. Hard
 * timeout 60 s so a hung connection can't wedge the calling handler.
 *
 * Exposed only inside this module — callers stick to {@link downloadToMediaRoot}.
 */
export declare function buildCurlArgs(url: string, outPath: string): string[];
/**
 * Walk MEDIA_ROOT recursively, removing regular files older than `maxAgeMs`.
 * Empty directories are also pruned. Errors on a single file are logged and
 * ignored — cleanup must never block the IM pipeline.
 */
export declare function cleanupOldMedia(maxAgeMs?: number): Promise<{
    deleted: number;
    kept: number;
}>;
/**
 * Pick a filename extension from a TG `file_path` (e.g. "photos/file_123.jpg")
 * or a mime-type like "image/png". Falls back to "bin" so we always have an
 * extension on disk for easier debugging.
 */
export declare function pickExtension(filePath: string | undefined, mime: string | undefined): string;
//# sourceMappingURL=media-download.d.ts.map