ACP: agent_message_chunk carries no messageId, and session_info_update floods the stream — markdown breaks in JetBrains clients #1667
Closed
AndriyPytel
started this conversation in
Bug reports
Replies: 1 comment
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Symptom
In JetBrains WebStorm 2026.2 (external ACP agent
acp.prime-agent), assistant markdown renders with random line breaks mid-word and mid-sentence, and markdown tables never render as tables. It gets much worse when parallel RLM subagents are running.Evidence
Measured from the IDE's own ACP log
~/Library/Logs/JetBrains/<IDE>/acp/acp.log, one 5.7 MB session:SessionInfoUpdateAgentMessageChunkAgentThoughtChunkToolCall+ToolCallUpdateAgentMessageChunk(content=Text(...), messageId=null).AgentMessageChunkpairs have another update injected between them, almost alwaysSessionInfoUpdate.SessionInfoUpdatenotifications are byte-identical duplicates of the previous one, up to 30 per second. Payload is_meta["ai.primeintellect.prime-agent"].subagents[...]status/token telemetry.prime-agent --mode acpshows chunk boundaries land mid-word (...ne|ensions for heavy work,...typin|g with implicit coercion). Concatenated the text is a perfectly valid markdown table.Analysis
ACP v1
ContentChunkalready has an optionalmessageId: "All chunks belonging to the same message share the same messageId. A change in messageId indicates a new message has started." prime-agent leaves it null (packages/coding-agent/src/modes/acp/acp-events.ts,assistantDeltaUpdates). A client that cannot group chunks starts a new markdown block whenever any other update interleaves, so a table split across an interleave never parses. Zed hit the same class of bug from the client side and fixed it by merging chunks by messageId (zed#62631 / #62672). JetBrains has it open as LLM-25940 ("Tables are not rendered") and JUNIE-3777 ("ACP omits newlines in some agent messages").Proposal
messageIdon everyagent_message_chunkandagent_thought_chunk, stable per assistant message, new id per message. Pure v1, no protocol bump, no latency cost.session_info_update: skip payloads identical to the last one sent, and rate-limit subagent telemetry (~500 ms). 13,693 -> ~600 notifications.agent_messageupsert with the samemessageIdand the full content at end of message. v2 semantics say that content replaces everything accumulated for that messageId, which gives a clean re-render of the finished markdown without waiting to stream it.Questions
All reactions