From f525c49267ec092217d75e9ad403e7e50adebc28 Mon Sep 17 00:00:00 2001 From: ZyGuo Date: Tue, 16 Jun 2026 13:06:36 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20iframe=E5=A2=9E=E5=8A=A0=E6=99=BA?= =?UTF-8?q?=E8=83=BD=E4=BD=93=E9=80=89=E6=8B=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend-web/src/pages/IframeChatPage.tsx | 180 ++++++++++++++++++---- 1 file changed, 152 insertions(+), 28 deletions(-) diff --git a/frontend-web/src/pages/IframeChatPage.tsx b/frontend-web/src/pages/IframeChatPage.tsx index 9cb2861a..f9983498 100644 --- a/frontend-web/src/pages/IframeChatPage.tsx +++ b/frontend-web/src/pages/IframeChatPage.tsx @@ -1,10 +1,18 @@ "use client"; +import { + BookMarkedIcon, + BrainCircuitIcon, + CheckIcon, + FileTextIcon, + GraduationCapIcon, +} from "lucide-react"; import { useRouter } from "next/navigation"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { type PromptInputMessage } from "@/components/ai-elements/prompt-input"; import { useArtifacts } from "@/components/workspace/artifacts"; +import { AgentSelector } from "@/components/workspace/agents/agent-selector"; import { ChatBox, useSpecificChatMode, @@ -12,18 +20,23 @@ import { } from "@/components/workspace/chats"; import { MessageList, - MESSAGE_LIST_DEFAULT_PADDING_BOTTOM, - MESSAGE_LIST_FOLLOWUPS_EXTRA_PADDING_BOTTOM, } from "@/components/workspace/messages"; import { ThreadContext } from "@/components/workspace/messages/context"; import { TodoList } from "@/components/workspace/todo-list"; +import { Button } from "@/components/ui/button"; +import { useAgentSelector } from "@/core/agents"; import { getAccessToken } from "@/core/auth"; import { useI18n } from "@/core/i18n/hooks"; import { useModels } from "@/core/models/hooks"; import { useNotification } from "@/core/notification/hooks"; import { useRouteBase } from "@/core/route-base"; -import { useThreadSettings } from "@/core/settings"; -import { usePromptPrefixSettings } from "@/core/system-settings/hooks"; +import { + getLastAgentId, + isThreadRagModeLocked, + saveLastAgentId, + useLocalSettings, + useThreadSettings, +} from "@/core/settings"; import { useThreadStream } from "@/core/threads/hooks"; import { textOfMessage } from "@/core/threads/utils"; import { env } from "@/env"; @@ -81,16 +94,16 @@ export default function IframeChatPage() { const routeBase = useRouteBase(); const router = useRouter(); const { t } = useI18n(); - const [showFollowups, setShowFollowups] = useState(false); const [hasStartedConversation, setHasStartedConversation] = useState(false); const { threadId, setThreadId, isNewThread, setIsNewThread, isMock } = useThreadChat(); - const [settings] = useThreadSettings(threadId); + const [settings, setSettings] = useThreadSettings(threadId); + const [localSettings, setLocalSettings] = useLocalSettings(); const [mounted, setMounted] = useState(false); const { tokenUsageEnabled } = useModels(); - const { data: promptPrefixSettings } = usePromptPrefixSettings(); - const [promptPrefixOn, setPromptPrefixOn] = useState(false); const [selectedAgentId, setSelectedAgentId] = useState(null); + const { agents: selectorAgents, isLoading: selectorLoading } = + useAgentSelector(); const pendingRequestIdRef = useRef(null); const { selectedArtifact } = useArtifacts(); useSpecificChatMode(); @@ -124,11 +137,19 @@ export default function IframeChatPage() { useEffect(() => { if (isNewThread) { setHasStartedConversation(false); - setPromptPrefixOn(false); - setSelectedAgentId(null); + setSelectedAgentId(getLastAgentId()); } }, [isNewThread, threadId]); + useEffect(() => { + if (selectorLoading || !selectedAgentId) { + return; + } + if (!selectorAgents.some((agent) => agent.id === selectedAgentId)) { + setSelectedAgentId(null); + } + }, [selectedAgentId, selectorAgents, selectorLoading]); + const { showNotification } = useNotification(); const [thread, sendMessage, isUploading] = useThreadStream({ @@ -207,20 +228,12 @@ export default function IframeChatPage() { return; } - const shouldApplyPrefix = - isNewThread && - !hasStartedConversation && - promptPrefixOn && - promptPrefixSettings?.enabled === true; setHasStartedConversation(true); window.dispatchEvent( new CustomEvent("workspace:sandbox-resume-autoscroll"), ); const extraContext: Record = {}; - if (shouldApplyPrefix) { - extraContext.prompt_prefix_enabled = true; - } if (settings.context.writing_mode && writingArtifactPath) { extraContext.writing_artifact_path = writingArtifactPath; } @@ -238,8 +251,6 @@ export default function IframeChatPage() { [ hasStartedConversation, isNewThread, - promptPrefixOn, - promptPrefixSettings, router, selectedAgentId, sendMessage, @@ -257,6 +268,45 @@ export default function IframeChatPage() { [sendMessage, threadId], ); + const handleAgentChange = useCallback((agentId: string | null) => { + setSelectedAgentId(agentId); + saveLastAgentId(agentId); + }, []); + + const ragModeLocked = isThreadRagModeLocked(threadId); + const ragModeEnabled = + localSettings.display.ragModeEnabled || ragModeLocked; + const proModeEnabled = settings.context.mode === "pro"; + + const toggleWritingMode = useCallback(() => { + setSettings("context", { + writing_mode: !settings.context.writing_mode, + }); + }, [setSettings, settings.context.writing_mode]); + + const toggleMemoryInjection = useCallback(() => { + setSettings("context", { + memory_injection_enabled: + !(settings.context.memory_injection_enabled ?? true), + }); + }, [setSettings, settings.context.memory_injection_enabled]); + + const toggleRagMode = useCallback(() => { + if (ragModeLocked) { + return; + } + setLocalSettings("display", { + ragModeEnabled: !ragModeEnabled, + }); + }, [ragModeEnabled, ragModeLocked, setLocalSettings]); + + const toggleProMode = useCallback(() => { + setSettings("context", { + mode: proModeEnabled ? "flash" : "pro", + reasoning_effort: proModeEnabled ? "minimal" : "medium", + }); + }, [proModeEnabled, setSettings]); + const handleInterrupt = useCallback( async (message: BrainyChatInterruptMessage) => { const targetRequestId = message.payload?.requestId?.trim(); @@ -318,11 +368,47 @@ export default function IframeChatPage() { }; }, [handleInterrupt, handleSubmit]); - const messageListPaddingBottom = showFollowups - ? MESSAGE_LIST_DEFAULT_PADDING_BOTTOM + - MESSAGE_LIST_FOLLOWUPS_EXTRA_PADDING_BOTTOM - : undefined; const isLandingState = isNewThread && !hasStartedConversation; + const bottomBarHeightClass = "pb-28"; + const modeButtons = [ + { + key: "writing", + label: "写作", + icon: FileTextIcon, + active: !!settings.context.writing_mode, + onClick: toggleWritingMode, + activeClassName: + "border-amber-300 bg-amber-50 text-amber-700 hover:bg-amber-100", + }, + { + key: "memory", + label: "记忆", + icon: BrainCircuitIcon, + active: settings.context.memory_injection_enabled ?? true, + onClick: toggleMemoryInjection, + activeClassName: + "border-blue-300 bg-blue-50 text-blue-700 hover:bg-blue-100", + }, + { + key: "references", + label: "参考文献", + icon: BookMarkedIcon, + active: ragModeEnabled, + onClick: toggleRagMode, + disabled: ragModeLocked, + activeClassName: + "border-emerald-300 bg-emerald-50 text-emerald-700 hover:bg-emerald-100", + }, + { + key: "pro", + label: "专业问答", + icon: GraduationCapIcon, + active: proModeEnabled, + onClick: toggleProMode, + activeClassName: + "border-violet-300 bg-violet-50 text-violet-700 hover:bg-violet-100", + }, + ] as const; return ( @@ -350,24 +436,30 @@ export default function IframeChatPage() { */}
-
+
{!isLandingState && ( )}
-
+
你好
+
+ +
)} {env.NEXT_PUBLIC_STATIC_WEBSITE_ONLY === "true" && ( @@ -396,6 +495,31 @@ export default function IframeChatPage() { )}
+
+
+ {modeButtons.map((button) => { + const Icon = button.icon; + return ( + + ); + })} +
+
From f6809349d2db01e7eb5e93cc13ae42d490d9eeab Mon Sep 17 00:00:00 2001 From: xuhd Date: Tue, 16 Jun 2026 17:26:13 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E6=9D=A5=E6=BA=90=E4=B8=8A=E4=BC=A0?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E6=A0=B7=E5=BC=8F=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../assistant-ui/document-upload-popup.tsx | 454 +++++++++++++----- frontend-web/src/components/ui/checkbox.tsx | 46 ++ frontend-web/src/styles/globals.css | 48 ++ 3 files changed, 438 insertions(+), 110 deletions(-) create mode 100644 frontend-web/src/components/ui/checkbox.tsx diff --git a/frontend-web/src/components/assistant-ui/document-upload-popup.tsx b/frontend-web/src/components/assistant-ui/document-upload-popup.tsx index 240b93f5..98fcdbe4 100644 --- a/frontend-web/src/components/assistant-ui/document-upload-popup.tsx +++ b/frontend-web/src/components/assistant-ui/document-upload-popup.tsx @@ -27,6 +27,7 @@ import { Button } from "@/components/ui/button"; import { toast } from "sonner"; import { getStoredAuth } from "@/core/auth"; import { queryClient } from "@/components/query-client-provider"; +import { Checkbox } from "@/components/ui/checkbox"; import Empty from "./empty"; import { NetworkActor } from "./network-actor"; @@ -693,169 +694,402 @@ const DocumentUploadPopupContent: FC<{ {/* A系统基因库 */} {activeTab === "A" && (
-
- {searchTypes.map((option) => ( -
searchTypeChange(option.value)} - > - {option.label} -
- ))} -
+ {false && ( +
+
+