Render assistant streams as Markdown

This commit is contained in:
murashit 2026-05-21 15:44:17 +09:00
parent d4d8022b64
commit 8d587b0927
4 changed files with 13 additions and 4 deletions

View file

@ -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,
},
];
}

View file

@ -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);

View file

@ -171,6 +171,14 @@ describe("thread item conversion preserves app-server semantics", () => {
expect(normalizeProposedPlanMarkdown("<proposed_plan>\n## Summary\n- Ship it\n</proposed_plan>")).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", "<proposed_plan>\n# Plan");
const updated = appendPlanDelta(items, "p1", "t1", "\n</proposed_plan>");

View file

@ -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<ServerNotification, { method: "item/agentMessage/delta" }>);
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", () => {