feat(agent): implement streamdown for real-time message rendering in chat

This commit is contained in:
HouYunFei
2026-07-09 17:16:35 +08:00
parent 25e1d173e8
commit 864ce4101a
7 changed files with 22 additions and 24 deletions
+2 -1
View File
@@ -35,6 +35,7 @@
"react-router": "^7.12.0",
"react-router-dom": "^7.12.0",
"shadcn": "^4.7.0",
"streamdown": "^2.5.0",
"tailwind-merge": "^3.6.0",
"tailwindcss": "^4",
"tw-animate-css": "^1.4.0",
@@ -42,11 +43,11 @@
},
"devDependencies": {
"@tailwindcss/postcss": "^4",
"@vitejs/plugin-react": "^5.2.0",
"@types/file-saver": "^2.0.7",
"@types/node": "^20",
"@types/react": "19.1.12",
"@types/react-dom": "19.1.9",
"@vitejs/plugin-react": "^5.2.0",
"prettier": "^3.8.3",
"typescript": "^5",
"vite": "^7.3.0"
@@ -1,6 +1,7 @@
import { useEffect, useRef, useState, type ReactNode } from "react";
import { Button, Tooltip } from "antd";
import { ArrowUp, CheckCircle2, CircleAlert, ImagePlus, LoaderCircle, Square, UserRound, Wrench, X, XCircle } from "lucide-react";
import { Streamdown } from "streamdown";
import { isPlainEnterKey } from "@/lib/keyboard-event";
import { canvasThemes } from "@/lib/canvas-theme";
@@ -15,6 +16,8 @@ export type CanvasAgentChatMessage = {
meta?: string;
detail?: unknown;
attachments?: CanvasAgentChatAttachment[];
/** Present while the message is actively streaming; cleared on completion. */
streamId?: string;
};
const WORKING_TEXT = "working...";
@@ -46,7 +49,11 @@ export function AgentChatMessage({ item, theme, user, onRejectTool, onApproveToo
<div className={`flex items-start gap-3 ${isUser ? "justify-end" : "justify-start"}`}>
{!isUser ? <AgentAvatar theme={theme} /> : null}
<div className={`min-w-0 max-w-[82%] text-sm leading-6 ${isUser ? "text-right" : "text-left"}`} style={{ color }}>
<div className="whitespace-pre-wrap break-words text-left">{item.text}</div>
{isUser ? (
<div className="whitespace-pre-wrap break-words text-left">{item.text}</div>
) : (
<Streamdown animated isAnimating={!!item.streamId}>{item.text}</Streamdown>
)}
{item.attachments?.length ? <AgentMessageAttachments attachments={item.attachments} /> : null}
{item.meta ? <div className="mt-1 text-[11px] opacity-45">{item.meta}</div> : null}
</div>
+1
View File
@@ -1,6 +1,7 @@
import React from "react";
import { createRoot } from "react-dom/client";
import "antd/dist/reset.css";
import "streamdown/styles.css";
import "./styles/globals.css";
import { RouterProvider } from "react-router-dom";
+1
View File
@@ -1,5 +1,6 @@
@import "tailwindcss";
@import "tw-animate-css";
@source "../../../node_modules/streamdown/dist/*.js";
@import "shadcn/tailwind.css";
@custom-variant dark (&:is(.dark *));