import type { AgentToolResult } from "@mariozechner/pi-agent-core"; import type { ImageContent } from "@mariozechner/pi-ai"; import { createSubsystemLogger } from "../logging/subsystem.js"; import { canonicalizeBase64 } from "../media/base64.js"; import {
buildImageResizeSideGrid,
getImageMetadata,
IMAGE_REDUCE_QUALITY_STEPS,
resizeToJpeg,
} from "../media/image-ops.js"; import {
DEFAULT_IMAGE_MAX_BYTES,
DEFAULT_IMAGE_MAX_DIMENSION_PX,
type ImageSanitizationLimits,
} from "./image-sanitization.js";
type ToolContentBlock = AgentToolResult<unknown>["content"][number];
type ImageContentBlock = Extract<ToolContentBlock, { type: "image" }>;
type TextContentBlock = Extract<ToolContentBlock, { type: "text" }>;
// Anthropic Messages API limitations (observed in OpenClaw sessions): // - Images over ~2000px per side can fail in multi-image requests. // - Images over 5MB are rejected by the API. // // To keep sessions resilient (and avoid "silent" WhatsApp non-replies), we auto-downscale // and recompress base64 image blocks when they exceed these limits. const MAX_IMAGE_DIMENSION_PX = DEFAULT_IMAGE_MAX_DIMENSION_PX; const MAX_IMAGE_BYTES = DEFAULT_IMAGE_MAX_BYTES; const log = createSubsystemLogger("agents/tool-images");
function isImageBlock(block: unknown): block is ImageContentBlock { if (!block || typeof block !== "object") { returnfalse;
} const rec = block as Record<string, unknown>; return rec.type === "image" && typeof rec.data === "string" && typeof rec.mimeType === "string";
}
function isTextBlock(block: unknown): block is TextContentBlock { if (!block || typeof block !== "object") { returnfalse;
} const rec = block as Record<string, unknown>; return rec.type === "text" && typeof rec.text === "string";
}
function inferMimeTypeFromBase64(base64: string): string | undefined { const trimmed = base64.trim(); if (!trimmed) { return undefined;
} if (trimmed.startsWith("/9j/")) { return"image/jpeg";
} if (trimmed.startsWith("iVBOR")) { return"image/png";
} if (trimmed.startsWith("R0lGOD")) { return"image/gif";
} return undefined;
}
const next = await sanitizeContentBlocksImages(content, label, opts); return { ...result, content: next };
}
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.62Bemerkung:
(vorverarbeitet am 2026-06-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.