From 3c92e871568a45980087da5a2e221afe39d5b17d Mon Sep 17 00:00:00 2001 From: ZyGuo Date: Tue, 2 Jun 2026 16:24:01 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=A0=87=E9=A2=98=E5=8E=BB=E9=99=A4?= =?UTF-8?q?=E7=89=B9=E6=AE=8Atag?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/workspace/thread-title.tsx | 54 ++++++++++--------- frontend-web/src/core/threads/utils.ts | 12 +++++ 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/frontend-web/src/components/workspace/thread-title.tsx b/frontend-web/src/components/workspace/thread-title.tsx index a5d86205..d001ca07 100644 --- a/frontend-web/src/components/workspace/thread-title.tsx +++ b/frontend-web/src/components/workspace/thread-title.tsx @@ -1,9 +1,10 @@ import type { BaseStream } from "@langchain/langgraph-sdk"; -import { useEffect } from "react"; - -import { useI18n } from "@/core/i18n/hooks"; -import type { AgentThreadState } from "@/core/threads"; -import { desensitize } from "@/lib/desensitize"; +import { useEffect } from "react"; + +import { useI18n } from "@/core/i18n/hooks"; +import type { AgentThreadState } from "@/core/threads"; +import { sanitizeThreadTitleForDisplay } from "@/core/threads/utils"; +import { desensitize } from "@/lib/desensitize"; import { useThreadChat } from "./chats"; import { FlipDisplay } from "./flip-display"; @@ -16,16 +17,18 @@ export function ThreadTitle({ threadId: string; thread: BaseStream; }) { - const { t } = useI18n(); - const { isNewThread } = useThreadChat(); - useEffect(() => { - let _title = t.pages.untitled; - - if (thread.values?.title) { - _title = thread.values.title; - } else if (isNewThread) { - _title = t.pages.newChat; - } + const { t } = useI18n(); + const { isNewThread } = useThreadChat(); + const displayTitle = sanitizeThreadTitleForDisplay(thread.values?.title); + + useEffect(() => { + let _title = t.pages.untitled; + + if (thread.values?.title) { + _title = displayTitle; + } else if (isNewThread) { + _title = t.pages.newChat; + } if (thread.isThreadLoading) { document.title = `Loading... - ${t.pages.appName}`; } else { @@ -35,17 +38,18 @@ export function ThreadTitle({ isNewThread, t.pages.newChat, t.pages.untitled, - t.pages.appName, - thread.isThreadLoading, - thread.values, - ]); + t.pages.appName, + thread.isThreadLoading, + thread.values, + displayTitle, + ]); if (!thread.values?.title) { return null; } - return ( - - {desensitize(thread.values.title ?? "Untitled")} - - ); -} + return ( + + {desensitize(displayTitle)} + + ); +} diff --git a/frontend-web/src/core/threads/utils.ts b/frontend-web/src/core/threads/utils.ts index 8877eda3..cf25b7b7 100644 --- a/frontend-web/src/core/threads/utils.ts +++ b/frontend-web/src/core/threads/utils.ts @@ -65,3 +65,15 @@ export function textOfMessage(message: Message) { export function titleOfThread(thread: AgentThread) { return thread.values?.title ?? "Untitled"; } + +export function sanitizeThreadTitleForDisplay(title: string | null | undefined) { + if (!title) return "Untitled"; + + const cleaned = title + .replace(/<\/?[^>\n]+>/g, " ") + .replace(/<[^>\n]*$/g, " ") + .replace(/\s+/g, " ") + .trim(); + + return cleaned || "Untitled"; +}