AcpBackend
An AcpAgent as a chat provider: each conversation is one ACP session, each turn one session/prompt.
The session id is kept in the reply's Message.metadata under acp; the next turn continues that session (the agent keeps the history), so only the new user message is sent. A conversation whose session is gone and cannot be loaded starts a new one with the earlier turns as context.
Mapping (ACP session/update): agent_message_chunk → text (images → files, resource links → sources), agent_thought_chunk → reasoning, tool_call / tool_call_update → tool calls (title as the title, kind as the name, content — text, diffs, terminals — as the output, rawInput as the input), plan → the plan data part. session/request_permission asks approver: approve picks the agent's allow-once option (allow-always when the user said to remember), deny its reject-once option (ACP answers carry an option id only, so the UI offers no reason or edits). Stopping the turn sends session/cancel.
Functions
Replays message's turn from the agent's own record of the session: ACP session/load streams the session back as session/updates, and the turn's updates go through the same mapping as a live turn. ACP updates carry no timestamps, so they play at a steady pace (speed 2 is twice as fast). Null when message did not come from an ACP session; the flow fails if the agent cannot load it.