diff --git a/src/display/stream-updates.ts b/src/display/stream-updates.ts index 277c4b76..8f306064 100644 --- a/src/display/stream-updates.ts +++ b/src/display/stream-updates.ts @@ -37,7 +37,7 @@ export function appendAssistantDelta(items: DisplayItem[], itemId: string, turnI text: `${item.text}${delta}`, copyText: `${item.text}${delta}`, turnId: item.turnId ?? turnId, - markdown: false, + markdown: true, } : item, ); @@ -52,7 +52,7 @@ export function appendAssistantDelta(items: DisplayItem[], itemId: string, turnI copyText: delta, turnId, itemId, - markdown: false, + markdown: true, }, ]; } diff --git a/src/panel/message-renderer.ts b/src/panel/message-renderer.ts index 484fbc4f..433cc1d0 100644 --- a/src/panel/message-renderer.ts +++ b/src/panel/message-renderer.ts @@ -89,6 +89,7 @@ export class PanelMessageRenderer { private renderMarkdownMessage(parent: HTMLElement, text: string): void { const sourcePath = this.options.app.workspace.getActiveFile()?.path ?? ""; void MarkdownRenderer.render(this.options.app, text, parent, sourcePath, this.options.owner).then(() => { + if (!parent.isConnected) return; this.bindRenderedWikiLinks(parent, sourcePath); this.bindRenderedMarkdownFileLinks(parent, sourcePath); notifyMessageContentRendered(parent); diff --git a/tests/display/display-model.test.ts b/tests/display/display-model.test.ts index 7f3a3aeb..20c82c1e 100644 --- a/tests/display/display-model.test.ts +++ b/tests/display/display-model.test.ts @@ -171,6 +171,14 @@ describe("thread item conversion preserves app-server semantics", () => { expect(normalizeProposedPlanMarkdown("\n## Summary\n- Ship it\n")).toBe("## Summary\n- Ship it"); }); + it("streams assistant deltas as markdown", () => { + const items = appendAssistantDelta([], "a1", "t1", "**Hello**"); + const updated = appendAssistantDelta(items, "a1", "t1", "\n\n- world"); + expect(updated).toMatchObject([ + { id: "a1", kind: "message", role: "assistant", text: "**Hello**\n\n- world", copyText: "**Hello**\n\n- world", markdown: true }, + ]); + }); + it("streams plan deltas as plain assistant text until completion", () => { const items = appendPlanDelta([], "p1", "t1", "\n# Plan"); const updated = appendPlanDelta(items, "p1", "t1", "\n"); diff --git a/tests/panel/panel-controller.test.ts b/tests/panel/panel-controller.test.ts index dd356442..837cb718 100644 --- a/tests/panel/panel-controller.test.ts +++ b/tests/panel/panel-controller.test.ts @@ -53,7 +53,7 @@ describe("PanelController", () => { expect(state.displayItems).toEqual([]); }); - it("applies matching streaming deltas as lightweight assistant text", () => { + it("applies matching streaming deltas as assistant markdown", () => { const state = createPanelState(); state.activeThreadId = "thread-active"; state.activeTurnId = "turn-active"; @@ -64,7 +64,7 @@ describe("PanelController", () => { params: { threadId: "thread-active", turnId: "turn-active", itemId: "a1", delta: "hello" }, } satisfies Extract); - expect(state.displayItems).toMatchObject([{ id: "a1", text: "hello", markdown: false }]); + expect(state.displayItems).toMatchObject([{ id: "a1", text: "hello", markdown: true }]); }); it("marks active reasoning completed when assistant text starts", () => {