Source code for ralph.mcp.multimodal.resources

"""URI builder/parser and session-scoped manifest for ralph://media resources.

The manifest tracks every resource_reference artifact emitted during a session
so they can be listed via resources/list and retrieved via resources/read.
"""

from __future__ import annotations

import hashlib
import re
import uuid
from dataclasses import dataclass, field

from ralph.mcp.multimodal._manifest_entry import ManifestEntry
from ralph.mcp.multimodal._media_entry_extras import MediaEntryExtras
from ralph.mcp.multimodal._media_source import MediaSource

_RALPH_MEDIA_PREFIX = "ralph://media/"
_URI_PATTERN = re.compile(
    r"^ralph://media/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$"
)

MEDIA_URI_TEMPLATE = "ralph://media/{artifact_id}"


[docs] def build_media_uri(artifact_id: str) -> str: """Build a ralph://media/{artifact_id} URI.""" return f"{_RALPH_MEDIA_PREFIX}{artifact_id}"
[docs] def parse_media_uri(uri: str) -> str | None: """Parse a ralph://media/{artifact_id} URI and return artifact_id, or None.""" m = _URI_PATTERN.match(uri) if m is None: return None return m.group(1)
[docs] def new_artifact_id() -> str: """Generate a new random artifact UUID.""" return str(uuid.uuid4())
[docs] def build_media_identity( *, modality: str, mime_type: str, title: str, source: MediaSource | None = None, ) -> str: """Build a stable identity for deduping repeated live artifacts.""" src = source or MediaSource() if src.source_uri: return f"source-uri:{modality}:{src.source_uri}" if src.source_path: return f"source-path:{modality}:{src.source_path}" if src.raw_bytes is not None: digest = hashlib.sha256(src.raw_bytes).hexdigest() return f"payload:{modality}:{mime_type}:{title}:{digest}" return f"artifact:{modality}:{mime_type}:{title}"
[docs] @dataclass class MediaManifest: """Session-scoped manifest of all multimodal resource references.""" _entries: dict[str, ManifestEntry] = field(default_factory=dict) _identity_index: dict[str, str] = field(default_factory=dict)
[docs] def add( self, *, title: str, mime_type: str, modality: str, raw_bytes: bytes, extras: MediaEntryExtras | None = None, ) -> ManifestEntry: """Add or replace an artifact and return its manifest entry.""" xt = extras or MediaEntryExtras() resolved_identity = xt.identity_key or build_media_identity( modality=modality, mime_type=mime_type, title=title, source=MediaSource( source_path=xt.source_path, source_uri=xt.source_uri, raw_bytes=raw_bytes, ), ) artifact_id = self._identity_index.get(resolved_identity, new_artifact_id()) uri = build_media_uri(artifact_id) entry = ManifestEntry( artifact_id=artifact_id, uri=uri, mime_type=mime_type, title=title, modality=modality, identity_key=resolved_identity, cache_path=xt.cache_path, source_path=xt.source_path, source_uri=xt.source_uri, _raw_bytes=raw_bytes, _byte_loader=xt.byte_loader, ) self._entries[artifact_id] = entry self._identity_index[resolved_identity] = artifact_id return entry
[docs] def get(self, artifact_id: str) -> ManifestEntry | None: """Retrieve a manifest entry by artifact_id, or None if not found.""" return self._entries.get(artifact_id)
[docs] def list_entries(self) -> list[ManifestEntry]: """Return all manifest entries in insertion order.""" return list(self._entries.values())
[docs] def is_empty(self) -> bool: """Return True if no artifacts have been stored.""" return not self._entries
__all__ = [ "MEDIA_URI_TEMPLATE", "ManifestEntry", "MediaEntryExtras", "MediaManifest", "MediaSource", "build_media_identity", "build_media_uri", "new_artifact_id", "parse_media_uri", ]