module

Smith::Media

What a file is, decided from its bytes.

An extension is a claim, not a fact: a screenshot saved as .txt is still a PNG, and a text file named .png is still text. Sending the second one as an image is a provider error the user cannot act on, so the signature decides and the name is only ever shown.

Constants

DEFAULT_MAX_BYTES = (3 * 1024) * 1024

Base64 inflates by a third, and the result is not sent once: it goes into the session file and back out in every later request of the session. 3 MB before encoding is around 4 MB on the wire, per turn.

GIF = Format.new("image/gif", Kind::Image)
JPEG = Format.new("image/jpeg", Kind::Image)
PDF = Format.new("application/pdf", Kind::Document)
PNG = Format.new("image/png", Kind::Image)
SNIFF_BYTES = 12

How much of a file has to be read to recognise it. WebP needs twelve bytes — RIFF at 0, WEBP at 8 — and that is the longest signature here.

WEBP = Format.new("image/webp", Kind::Image)

Class methods

detect(bytes : Bytes) : Format | Nil

nil for anything not recognised. Deliberately not a guess: an unknown binary is refused rather than labelled application/octet-stream and sent in the hope that the provider works it out.

Source
detect_file(path : String) : Format | Nil

Reads only the signature, so deciding what a file is never costs the price of loading it.

Source
from_base64(data : String) : Attachment | Nil

Takes any integer so a caller with a File.size — a UInt64 — does not have to narrow it first and risk wrapping a genuinely huge file into a small number. An attachment from something that arrived already encoded — an MCP server's image content block, which carries base64 and a mimeType.

The mime type is not consulted. A server claims a type in a field, and a claim about a file is not the file: the same rule that decides an @-mention and a read_file decides here, from the bytes. nil when the payload is not base64 at all, or not a format smith attaches.

Source
human_size(bytes : Int) : String
Source
read(path : String) : Attachment | Nil

nil when the file is not a format smith attaches. The size limit is the caller's to enforce — it is the caller that knows how to report a skip.

Source

Nested types