diff --git a/packages/app/src/agent-stream/presentation.test.ts b/packages/app/src/agent-stream/presentation.test.ts index 786cd5192b..5e625a9028 100644 --- a/packages/app/src/agent-stream/presentation.test.ts +++ b/packages/app/src/agent-stream/presentation.test.ts @@ -210,6 +210,17 @@ describe("stream presentation through installed plugins", () => { expect(result.head).toMatchObject([{ text: "```ts\nconst a = 1;\n\nconst b = 2;" }]); }); + // Codex streams a line break and the next line's indent as their own chunks. + it("keeps a line break when a chunk ends in the next line's indent", () => { + const harness = streamHarness(); + harness.send(assistant("```mermaid\nflowchart TD\n A[Start] --> B[Review]\n")); + harness.send(assistant(" ")); + const result = harness.send(assistant(" B --> C[Finish]\n```")); + expect(result.head).toMatchObject([ + { text: "```mermaid\nflowchart TD\n A[Start] --> B[Review]\n B --> C[Finish]\n```" }, + ]); + }); + // One rendering path: a fetched message is the same block group as a streamed one, // which is what lets find, scroll-to-message and history reveal address it by id. // A link reference definition stays with the paragraph that uses it, so the split diff --git a/packages/app/src/agent-stream/presentation.ts b/packages/app/src/agent-stream/presentation.ts index 0e83a0f50c..8300996348 100644 --- a/packages/app/src/agent-stream/presentation.ts +++ b/packages/app/src/agent-stream/presentation.ts @@ -112,8 +112,10 @@ export function createStreamPresentation() { const index = prefix.length + offset; let blockText = text; if (offset === textBlocks.length - 1) { - const trailingNewlines = /\n+$/.exec(item.text)?.[0] ?? ""; - blockText += trailingNewlines; + // The split drops trailing blank lines, including a line break followed only + // by the next line's indent. Keep them so the next append continues that line. + const trailingBlankLines = /\n\s*$/.exec(item.text)?.[0] ?? ""; + blockText += trailingBlankLines; } const existing = previous?.[index]; const id = `${item.id}:block:${index}`;