Lightweight multimodal and tool-call value structs matching Imp's adapter vocabulary.
The conversion helpers are deliberately permissive for plain text values and
deliberately strict for Imp's typed structs. A free-form value can be rendered
as text, but a %File{} without file data, identity, or filename is a malformed
attachment and should fail at this boundary instead of becoming provider text.
Typed values are inert: constructing or formatting them never reads the host
filesystem or fetches the network. Use the explicit from_path/1 and
from_url/2 factories when the caller intends those effects.
Summary
Functions
Decodes a single OpenAI-compatible content block or a list of blocks.
Converts a single value or list of values into OpenAI-compatible content blocks.
Decodes a known OpenAI-compatible content block into an Imp content struct.
Converts one Imp content value into an OpenAI-compatible content block.
Functions
Decodes a single OpenAI-compatible content block or a list of blocks.
iex> alias Imp.Adapter.Types
iex> Types.content_from_openai([%{"type" => "text", "text" => "hello"}])
[%Imp.Adapter.Types.Document{text: "hello", metadata: %{}}]
Converts a single value or list of values into OpenAI-compatible content blocks.
iex> alias Imp.Adapter.Types
iex> Types.content_to_openai(["hello", %Types.Document{text: "world"}])
[%{type: "text", text: "hello"}, %{type: "text", text: "world"}]
iex> Imp.Adapter.Types.content_to_openai("hello")
[%{type: "text", text: "hello"}]
Decodes a known OpenAI-compatible content block into an Imp content struct.
Known block types are strict: if a value claims to be an image_url,
input_audio, file, or text block, it must have the expected payload.
Unknown future provider block types pass through unchanged.
iex> alias Imp.Adapter.Types
iex> Types.from_openai(%{"type" => "text", "text" => "notes"})
%Imp.Adapter.Types.Document{text: "notes", metadata: %{}}
iex> future = %{"type" => "provider_future_block", "payload" => %{}}
iex> Imp.Adapter.Types.from_openai(future)
%{"type" => "provider_future_block", "payload" => %{}}
iex> Imp.Adapter.Types.from_openai(%{"type" => "file", "file" => %{}})
** (ArgumentError) OpenAI-compatible content block "file" has malformed payload: %{"file" => %{}, "type" => "file"}
Converts one Imp content value into an OpenAI-compatible content block.
Typed Imp structs are validated strictly. Plain strings and unknown values are still rendered as text, which keeps simple prompts ergonomic while making malformed attachments visible.
iex> alias Imp.Adapter.Types
iex> Types.to_openai(%Types.Image{url: "https://example.com/cat.png"})
%{type: "image_url", image_url: %{url: "https://example.com/cat.png"}}
iex> Imp.Adapter.Types.to_openai("hello")
%{type: "text", text: "hello"}
iex> Imp.Adapter.Types.to_openai(%Imp.Adapter.Types.File{})
** (ArgumentError) Imp.Adapter.Types.File expects binary :url, :data, :file_id, or :filename; got: %Imp.Adapter.Types.File{path: nil, url: nil, data: nil, file_id: nil, filename: nil, mime_type: nil, metadata: %{}}