// image-fetch — fetch a remote image URL and return it as a vision-capable
// content block the calling model can see.
//
// Why this exists: the listing-curator specialist writes one :ImageObject per
// Listing image, each carrying a vision-LLM `description` and a closed-set
// `tags` array. The curator's model has vision, but its tool palette only
// reads local files (Read) and text URLs (WebFetch). Neither can deliver
// remote image bytes as a vision input. This tool closes that gap with the
// smallest possible surface: one URL → base64 image content block.
//
// Out of scope: caching, persistence, transformation, OCR, EPC PDFs.
// Guards: image/* content types only, 10 MB byte cap, 30 s timeout.
const MAX_BYTES = 10 * 1024 * 1024;
const TIMEOUT_MS = 30_000;
/**
 * Fetch a remote image URL, validate it is an image of acceptable size,
 * and return the base64-encoded bytes ready for MCP content-block return.
 */
export async function fetchImageAsContent(url) {
    if (!/^https?:\/\//i.test(url)) {
        return { ok: false, reason: `URL must be http or https — got "${url.slice(0, 40)}"` };
    }
    const controller = new AbortController();
    const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
    try {
        const res = await fetch(url, { signal: controller.signal, redirect: "follow" });
        if (!res.ok) {
            return { ok: false, reason: `HTTP ${res.status} ${res.statusText}` };
        }
        const contentType = res.headers.get("content-type") ?? "";
        if (!contentType.startsWith("image/")) {
            return { ok: false, reason: `content-type "${contentType}" is not image/*` };
        }
        const declaredLength = Number(res.headers.get("content-length"));
        if (Number.isFinite(declaredLength) && declaredLength > MAX_BYTES) {
            return {
                ok: false,
                reason: `image is ${declaredLength} bytes; max ${MAX_BYTES}`,
            };
        }
        const buffer = await res.arrayBuffer();
        if (buffer.byteLength > MAX_BYTES) {
            return {
                ok: false,
                reason: `image is ${buffer.byteLength} bytes; max ${MAX_BYTES}`,
            };
        }
        // Strip parameters (e.g. "image/jpeg; charset=binary") — the MCP image
        // content block expects a bare mime type.
        const mimeType = contentType.split(";")[0].trim();
        const base64 = Buffer.from(buffer).toString("base64");
        return { ok: true, mimeType, base64, bytes: buffer.byteLength };
    }
    catch (err) {
        if (err instanceof Error && err.name === "AbortError") {
            return { ok: false, reason: `fetch timed out after ${TIMEOUT_MS} ms` };
        }
        return { ok: false, reason: err instanceof Error ? err.message : String(err) };
    }
    finally {
        clearTimeout(timer);
    }
}
//# sourceMappingURL=image-fetch.js.map