Semantic agent chat model.
Describes the agent conversation view: visibility, runtime status, the active model name and thinking level, the prompt buffer plus its cell-grid metadata (cursor, vim mode, line counts), an optional prompt completion popup, an optional pending approval banner, an optional help overlay, and the list of conversation messages with their stable BEAM-assigned IDs.
This is pure data with domain fields and core types only. It does not
reference any product module; the editor builder pre-resolves every agent
struct into the core views defined here before putting them on the model. The
GUI adapter
(Minga.Frontend.Adapter.GUI.AgentChatEncoder) owns the wire encoding. A
hidden panel is just %AgentChat{visible?: false}; the encoder derives a
change-detection fingerprint with :erlang.phash2/1, so no sentinel is needed.
Messages
messages is a list of {id, body} tuples where id is a stable uint32 the
GUI uses as a persistent identity. body is one of the resolved core message
forms produced by the editor builder:
{:user, text}/{:user, text, attachments}{:assistant, text}{:styled_assistant, styled_lines}{:thinking, text, collapsed?}{:tool_call, %AgentChat.ToolCallView{}}{:styled_tool_call, %AgentChat.ToolCallView{}, styled_lines}{:approval_tool_call, %AgentChat.ApprovalView{}}{:system, text, level}{:usage, %AgentChat.Usage{}}
Bare body tuples (without an id wrapper) are also accepted and encode with
ID 0, matching the historical wire behaviour.
Summary
Types
A message with its stable GUI identity, or a bare body that encodes with ID 0.
A conversation message body.
A line of styled runs.
A styled text run: {text, fg_rgb, bg_rgb, flags} or with a trailing url.
Types
@type message() :: {pos_integer(), message_body()} | message_body()
A message with its stable GUI identity, or a bare body that encodes with ID 0.
@type message_body() :: {:user, String.t()} | {:user, String.t(), term()} | {:assistant, String.t()} | {:styled_assistant, [styled_line()]} | {:thinking, String.t(), boolean()} | {:tool_call, Minga.RenderModel.UI.AgentChat.ToolCallView.t()} | {:styled_tool_call, Minga.RenderModel.UI.AgentChat.ToolCallView.t(), [styled_line()]} | {:approval_tool_call, Minga.RenderModel.UI.AgentChat.ApprovalView.t()} | {:system, String.t(), atom()} | {:usage, Minga.RenderModel.UI.AgentChat.Usage.t()}
A conversation message body.
@type styled_line() :: [styled_run()]
A line of styled runs.
@type styled_run() :: {String.t(), non_neg_integer(), non_neg_integer(), non_neg_integer()} | {String.t(), non_neg_integer(), non_neg_integer(), non_neg_integer(), String.t()}
A styled text run: {text, fg_rgb, bg_rgb, flags} or with a trailing url.
@type t() :: %Minga.RenderModel.UI.AgentChat{ help_groups: [{String.t(), [{String.t(), String.t()}]}], help_visible?: boolean(), messages: [message()], model_name: String.t(), pending_approval: Minga.RenderModel.UI.AgentChat.PendingApproval.t() | nil, prompt: String.t(), prompt_completion: Minga.RenderModel.UI.AgentChat.PromptCompletion.t() | nil, prompt_cursor_col: non_neg_integer(), prompt_cursor_line: non_neg_integer(), prompt_line_count: non_neg_integer(), prompt_vim_mode: atom() | nil, prompt_visible_rows: non_neg_integer(), status: atom(), thinking_level: String.t(), visible?: boolean() }