lib/planck/ai/message.ex

defmodule Planck.AI.Message do
  @moduledoc """
  A single conversation turn with a role and a list of typed content parts.

  Content is always a list of tagged tuples, mirroring the Anthropic API's
  multi-part message format. An assistant message may contain both text and
  tool calls interleaved.

  ## Content part types

  - `{:text, text}` — plain text
  - `{:image, data, mime_type}` — binary image data with MIME type
  - `{:image_url, url}` — image referenced by URL
  - `{:file, data, mime_type}` — binary file/document (PDF, etc.)
  - `{:video_url, url}` — video referenced by URL (Google Gemini only)
  - `{:tool_call, id, name, args}` — a tool call emitted by the model
  - `{:tool_result, id, result}` — the result of executing a tool call
  - `{:thinking, text}` — extended thinking / reasoning block

  ## Examples

      iex> %Planck.AI.Message{
      ...>   role: :user,
      ...>   content: [{:text, "What is the weather in Lisbon?"}]
      ...> }

  """

  @type role :: :user | :assistant | :tool_result

  @type content_part ::
          {:text, String.t()}
          | {:image, binary(), String.t()}
          | {:image_url, String.t()}
          | {:file, binary(), String.t()}
          | {:video_url, String.t()}
          | {:tool_call, String.t(), String.t(), map()}
          | {:tool_result, String.t(), term()}
          | {:thinking, String.t()}

  @type t :: %__MODULE__{
          role: role(),
          content: [content_part()]
        }

  defstruct [:role, content: []]
end