Coverage for src / lexigram / contracts / ai / multimodal.py: 0%

23 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-08-15 18:57 +0800

1"""Typed multimodal message content parts for cross-client LLM messaging.""" 

2 

3from __future__ import annotations 

4 

5from dataclasses import dataclass, field 

6from typing import Literal, TypeAlias 

7 

8 

9@dataclass(frozen=True) 

10class TextPart: 

11 """A plain-text content part in a multimodal message. 

12 

13 Attributes: 

14 text: The text content. 

15 type: Discriminator field, always ``"text"``. 

16 """ 

17 

18 text: str 

19 type: Literal["text"] = field(default="text", init=False) 

20 

21 

22@dataclass(frozen=True) 

23class ImageUrlPart: 

24 """An image specified by URL in a multimodal message. 

25 

26 The framework passes the URL through to providers that support it 

27 natively (OpenAI, Anthropic, Gemini). For providers that require 

28 base64 (Ollama, Bedrock), the client fetches and converts. 

29 

30 Attributes: 

31 url: Public or data-URI URL of the image. 

32 detail: OpenAI vision detail level (``"auto"``, ``"low"``, ``"high"``). 

33 type: Discriminator field, always ``"image_url"``. 

34 """ 

35 

36 url: str 

37 detail: Literal["auto", "low", "high"] = "auto" 

38 type: Literal["image_url"] = field(default="image_url", init=False) 

39 

40 

41@dataclass(frozen=True) 

42class ImageBase64Part: 

43 """An image pre-encoded as base64 in a multimodal message. 

44 

45 Attributes: 

46 data: Raw base64-encoded bytes (no ``data:`` prefix). 

47 media_type: MIME type, e.g. ``"image/jpeg"``. 

48 detail: OpenAI vision detail level, or ``""`` when the source 

49 carries none (e.g. Claude-sourced images). 

50 type: Discriminator field, always ``"image_base64"``. 

51 """ 

52 

53 data: str 

54 media_type: str 

55 detail: str = "" 

56 type: Literal["image_base64"] = field(default="image_base64", init=False) 

57 

58 

59ContentPart: TypeAlias = TextPart | ImageUrlPart | ImageBase64Part 

60"""Union of all supported content part types.""" 

61 

62MessageContent: TypeAlias = str | list[ContentPart] 

63"""Content field type for ``ChatMessage``. 

64 

65Either a plain string (backward-compatible) or a list of typed parts 

66for multimodal messages. 

67""" 

68 

69 

70__all__ = [ 

71 "ContentPart", 

72 "ImageBase64Part", 

73 "ImageUrlPart", 

74 "MessageContent", 

75 "TextPart", 

76]