Translate ACP messages into the block maps a transcript renders.
This is the module that replaces a hand-written dialect parser, and the reason it lives beside the peer rather than in a view is the point of Fountain's ADR 0014: four proprietary output formats used to be parsed in the render path, where a vendor's point release becomes a rendering bug. The ACP path parses once, in a module with its own tests, and every client reads one parse.
The block shapes are a wire contract, not a choice made here: they are what the transcript renderers already draw, so a client can render an ACP transcript and a legacy one with one code path. The README lists them.
ACP session/update | block |
|---|---|
agent_message_chunk | %{kind: :text} |
agent_thought_chunk | %{kind: :thinking} |
tool_call | %{kind: :tool_use} |
tool_call_update | %{kind: :tool_result} |
user_message_chunk | dropped — we already render the prompt |
plan, available_commands_update | dropped — no equivalent yet |
Chunks are not messages
agent_message_chunk is a chunk: a turn produces many, and each carries a
fragment of text. We emit one :text block per chunk and let the existing
renderer concatenate adjacent ones, which is what it already does for the
legacy stream. Buffering them here would mean holding a turn's whole
assistant message in the peer's memory to produce output that renders
identically.
Tool calls thread on one id
A renderer's tool-pairing pass exists because three of the four legacy
dialects emit a tool call and its result as unrelated top-level events. ACP
threads
them on toolCallId by construction, so the pairing pass gets the ids it
wants for free — we map tool_call → :tool_use with :id and
tool_call_update → :tool_result with :tool_id, and the existing pass
collapses them.
A tool_call_update only becomes a :tool_result once it reports a terminal
status. In-flight updates (pending, in_progress) carry progress, not an
outcome, and turning each one into a result block would render a completed
tool card several times per call.
Summary
Functions
Translate one stored ndjson line into blocks.
Translate the params of one session/update notification.
Functions
Translate one stored ndjson line into blocks.
This is the entry point a render path uses: an owner stores the raw protocol line the peer reported, so what is on disk is what the adapter actually said.
Translate the params of one session/update notification.
The update variant lives under sessionUpdate; everything else in the map is
variant-specific.