from __future__ import annotations import base64 from typing import Any, Iterable def _data_uri_from(value: Any) -> str | None: """Convert raw slide/image representations into a data URI string. This accepts several shapes that can appear in MCP tool responses: - plain bytes - dicts or objects with ``data``/``mimeType`` fields - already-encoded ``data:...`` URIs """ if not value: return None if isinstance(value, str): if value.startswith("data:"): return value return None if isinstance(value, bytes): b64 = base64.b64encode(value).decode("ascii") return f"data:image/png;base64,{b64}" # Handle ImageContent-like objects or dicts data = getattr(value, "data", None) mime = getattr(value, "mimeType", None) or getattr(value, "mime_type", None) if isinstance(value, dict): data = value.get("data", data) mime = value.get("mimeType") or value.get("mime_type") or mime if data is None: return None if isinstance(data, bytes): b64 = base64.b64encode(data).decode("ascii") else: if isinstance(data, str) and data.startswith("data:"): return data if not isinstance(data, str): return None b64 = data if not mime: mime = "image/png" return f"data:{mime};base64,{b64}" def normalize_slide_entries(slides_result: Any) -> list[dict]: """Return a list of slide dicts with `image_data_uri` populated.""" if not isinstance(slides_result, dict): return [] candidates: Iterable[Any] | None = slides_result.get("slides") if isinstance(candidates, dict): candidates = candidates.get("slides") elif candidates is None: maybe_nested = slides_result.get("result") if isinstance(maybe_nested, dict): candidates = maybe_nested.get("slides") if isinstance(candidates, dict): candidates = candidates.get("slides") if not isinstance(candidates, list): return [] normalized: list[dict] = [] for idx, raw in enumerate(candidates): entry: dict | None = None if isinstance(raw, dict): entry = dict(raw) data_uri = entry.get("image_data_uri") if not data_uri: for key in ("image", "image_content", "content"): if key in entry: data_uri = _data_uri_from(entry[key]) if data_uri: entry["image_data_uri"] = data_uri break entry.setdefault("index", idx) else: data_uri = _data_uri_from(raw) if data_uri: entry = {"index": idx, "image_data_uri": data_uri} if entry and entry.get("image_data_uri"): normalized.append(entry) return normalized __all__ = ["normalize_slide_entries"]