diff --git a/frontend-web/src/components/workspace/input-box.tsx b/frontend-web/src/components/workspace/input-box.tsx index 5af2eab9..ed83b077 100644 --- a/frontend-web/src/components/workspace/input-box.tsx +++ b/frontend-web/src/components/workspace/input-box.tsx @@ -514,6 +514,7 @@ export function InputBox({ )} +
)} + diff --git a/frontend-web/src/components/workspace/messages/message-group.tsx b/frontend-web/src/components/workspace/messages/message-group.tsx index cf820620..88704d11 100644 --- a/frontend-web/src/components/workspace/messages/message-group.tsx +++ b/frontend-web/src/components/workspace/messages/message-group.tsx @@ -1,6 +1,7 @@ import type { Message } from "@langchain/langgraph-sdk"; import { BookOpenTextIcon, + ChevronDownIcon, ChevronUp, FolderOpenIcon, GlobeIcon, @@ -23,6 +24,18 @@ import { } from "@/components/ai-elements/chain-of-thought"; import { CodeBlock } from "@/components/ai-elements/code-block"; import { Button } from "@/components/ui/button"; +import { + Collapsible, + CollapsibleContent, + CollapsibleTrigger, +} from "@/components/ui/collapsible"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; import { useI18n } from "@/core/i18n/hooks"; import { extractReasoningContentFromMessage, @@ -208,19 +221,10 @@ function ToolCall({ if (typeof args.query === "string") { label = t.toolCalls.searchOnWebFor(args.query); } + const items = normalizeSearchResults(result); return ( - {Array.isArray(result) && ( - - {result.map((item) => ( - - - {item.title} - - - ))} - - )} + {items.length > 0 && } ); } else if (name === "image_search") { @@ -496,3 +500,117 @@ function convertToSteps(messages: Message[]): CoTStep[] { } return steps; } + +type WebSearchItem = { + title?: string; + url?: string; + snippet?: string; + content?: string; + published_date?: string; + publishedDate?: string; + date?: string; +}; + +function normalizeSearchResults( + result: string | Record | undefined, +): WebSearchItem[] { + if (Array.isArray(result)) { + return result as WebSearchItem[]; + } + if (result && typeof result === "object") { + const nested = (result as { results?: unknown }).results; + if (Array.isArray(nested)) { + return nested as WebSearchItem[]; + } + } + return []; +} + +function WebSearchResultsList({ results }: { results: WebSearchItem[] }) { + const [open, setOpen] = useState(false); + return ( + + + + {results.length} 条检索结果 + + + {results.map((item, idx) => ( + + ))} + + + ); +} + +function SearchResultCard({ item }: { item: WebSearchItem }) { + const [open, setOpen] = useState(false); + const content = item.snippet ?? item.content; + const date = item.published_date ?? item.publishedDate ?? item.date; + let source: string | undefined; + if (item.url) { + try { + source = new URL(item.url).hostname.replace(/^www\./, ""); + } catch { + source = undefined; + } + } + return ( + <> + + + + + + {item.title ?? "检索结果"} + + {(source || date) && ( + + {source && {source}} + {source && date && ·} + {date && {date}} + + )} + + {content && ( +
+ {content} +
+ )} + {item.url && ( +
+ {item.url} +
+ )} +
+
+ + ); +} diff --git a/frontend-web/src/components/workspace/workspace-nav-chat-list.tsx b/frontend-web/src/components/workspace/workspace-nav-chat-list.tsx index eaff53d7..b413fe74 100644 --- a/frontend-web/src/components/workspace/workspace-nav-chat-list.tsx +++ b/frontend-web/src/components/workspace/workspace-nav-chat-list.tsx @@ -21,11 +21,11 @@ const NAV_ITEM_CLASS = "data-[active=true]:bg-white data-[active=true]:text-foreground data-[active=true]:shadow-[0_1px_2px_rgba(15,23,42,0.06),0_1px_3px_rgba(15,23,42,0.04)] " + "dark:data-[active=true]:bg-slate-700/80 dark:data-[active=true]:text-slate-100 dark:data-[active=true]:shadow-none"; -// 「新对话」专属:始终主色 chip,让它在导航里更显眼 +// 「新对话」专属:默认仅主色文字/图标(显眼但不是选中态),命中 /chats/new 时才上主色底 const NEW_CHAT_CLASS = - "rounded-xl h-9 px-3 bg-primary/10 text-primary hover:bg-primary/15 hover:text-primary " + + "rounded-xl h-9 px-3 text-primary transition-colors hover:bg-primary/10 hover:text-primary " + "data-[active=true]:bg-primary/15 data-[active=true]:text-primary data-[active=true]:shadow-none " + - "dark:bg-primary/15 dark:text-primary-foreground dark:hover:bg-primary/25 dark:data-[active=true]:bg-primary/25"; + "dark:text-primary-foreground dark:hover:bg-primary/15 dark:data-[active=true]:bg-primary/25"; export function WorkspaceNavChatList() { const { t } = useI18n(); diff --git a/frontend-web/src/pages/ChatPage.tsx b/frontend-web/src/pages/ChatPage.tsx index a5a583b6..cdc49a87 100644 --- a/frontend-web/src/pages/ChatPage.tsx +++ b/frontend-web/src/pages/ChatPage.tsx @@ -236,12 +236,7 @@ export default function ChatPage() { /> )} {mounted ? ( -
+