diff --git a/surfsense_backend/app/agents/new_chat/system_prompt.py b/surfsense_backend/app/agents/new_chat/system_prompt.py index 274896229..cff13e8c6 100644 --- a/surfsense_backend/app/agents/new_chat/system_prompt.py +++ b/surfsense_backend/app/agents/new_chat/system_prompt.py @@ -566,7 +566,7 @@ DISABLED TOOLS (by user): The following tools are available in SurfSense but have been disabled by the user for this session: {disabled_list}. You do NOT have access to these tools and MUST NOT claim you can use them. If the user asks about a capability provided by a disabled tool, let them know the relevant tool -is currently disabled and they can re-enable it from the tools menu (wrench icon) in the composer toolbar. +is currently disabled and they can re-enable it. """) parts.append("\n\n") diff --git a/surfsense_web/app/dashboard/[search_space_id]/new-chat/[[...chat_id]]/page.tsx b/surfsense_web/app/dashboard/[search_space_id]/new-chat/[[...chat_id]]/page.tsx index 8e877b99c..7a046bc9a 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/new-chat/[[...chat_id]]/page.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/new-chat/[[...chat_id]]/page.tsx @@ -1596,7 +1596,7 @@ export default function NewChatPage() { // Show loading state only when loading an existing thread if (isInitializing) { return ( -
+
{/* User message */}
@@ -1624,7 +1624,7 @@ export default function NewChatPage() {
{/* Input bar */} -
+
diff --git a/surfsense_web/app/globals.css b/surfsense_web/app/globals.css index 1f44ead92..087c5b676 100644 --- a/surfsense_web/app/globals.css +++ b/surfsense_web/app/globals.css @@ -47,6 +47,7 @@ --sidebar-accent-foreground: oklch(0.205 0 0); --sidebar-border: oklch(0.922 0 0); --sidebar-ring: oklch(0.708 0 0); + --main-panel: oklch(1 0 0); --syntax-bg: #f5f5f5; --brand: oklch(0.623 0.214 259.815); --highlight: oklch(0.852 0.199 91.936); @@ -85,6 +86,7 @@ --sidebar-accent-foreground: oklch(0.985 0 0); --sidebar-border: oklch(0.269 0 0); --sidebar-ring: oklch(0.439 0 0); + --main-panel: oklch(0.18 0 0); --syntax-bg: #1e1e1e; --brand: oklch(0.707 0.165 254.624); --highlight: oklch(0.852 0.199 91.936); @@ -115,6 +117,7 @@ --color-chart-3: var(--chart-3); --color-chart-4: var(--chart-4); --color-chart-5: var(--chart-5); + --color-main-panel: var(--main-panel); --radius-sm: calc(var(--radius) - 4px); --radius-md: calc(var(--radius) - 2px); --radius-lg: var(--radius); diff --git a/surfsense_web/components/assistant-ui/thread-scroll-to-bottom.tsx b/surfsense_web/components/assistant-ui/thread-scroll-to-bottom.tsx index 79fee1850..394ba5d79 100644 --- a/surfsense_web/components/assistant-ui/thread-scroll-to-bottom.tsx +++ b/surfsense_web/components/assistant-ui/thread-scroll-to-bottom.tsx @@ -9,7 +9,7 @@ export const ThreadScrollToBottom: FC = () => { diff --git a/surfsense_web/components/assistant-ui/thread.tsx b/surfsense_web/components/assistant-ui/thread.tsx index b7a5bcf0e..f5118c683 100644 --- a/surfsense_web/components/assistant-ui/thread.tsx +++ b/surfsense_web/components/assistant-ui/thread.tsx @@ -19,6 +19,7 @@ import { ChevronRightIcon, CopyIcon, DownloadIcon, + Globe, Plus, RefreshCwIcon, Settings2, @@ -27,13 +28,13 @@ import { Upload, X, } from "lucide-react"; +import { AnimatePresence, motion } from "motion/react"; import { useParams } from "next/navigation"; import { type FC, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react"; import { createPortal } from "react-dom"; import { agentToolsAtom, disabledToolsAtom, - enabledToolCountAtom, hydrateDisabledToolsAtom, toggleToolAtom, } from "@/atoms/agent-tools/agent-tools.atoms"; @@ -118,7 +119,7 @@ export const Thread: FC = ({ messageThinkingSteps = new Map() }) => const ThreadContent: FC = () => { return ( { /> @@ -161,7 +162,7 @@ const ThreadScrollToBottom: FC = () => { @@ -232,7 +233,7 @@ const ThreadWelcome: FC = () => {
{/* Greeting positioned above the composer */}
-

{greeting}

+

{greeting}

{/* Composer - top edge fixed, expands downward only */}
@@ -589,7 +590,17 @@ const ComposerAction: FC = ({ isBlockedByOtherUser = false const disabledTools = useAtomValue(disabledToolsAtom); const toggleTool = useSetAtom(toggleToolAtom); const hydrateDisabled = useSetAtom(hydrateDisabledToolsAtom); - const enabledCount = useAtomValue(enabledToolCountAtom); + + const hasWebSearchTool = agentTools?.some((t) => t.name === "web_search") ?? false; + const isWebSearchEnabled = hasWebSearchTool && !disabledTools.includes("web_search"); + const filteredTools = useMemo( + () => agentTools?.filter((t) => t.name !== "web_search"), + [agentTools] + ); + const filteredEnabledCount = useMemo(() => { + if (!filteredTools) return 0; + return filteredTools.length - disabledTools.filter((d) => filteredTools.some((t) => t.name === d)).length; + }, [filteredTools, disabledTools]); useEffect(() => { hydrateDisabled(); @@ -642,11 +653,11 @@ const ComposerAction: FC = ({ isBlockedByOtherUser = false
Agent Tools - {enabledCount}/{agentTools?.length ?? 0} enabled + {filteredEnabledCount}/{filteredTools?.length ?? 0} enabled
- {agentTools?.map((tool) => { + {filteredTools?.map((tool) => { const isDisabled = disabledTools.includes(tool.name); return (
= ({ isBlockedByOtherUser = false
); })} - {!agentTools?.length && ( + {!filteredTools?.length && (
Loading tools...
@@ -707,7 +718,7 @@ const ComposerAction: FC = ({ isBlockedByOtherUser = false
Agent Tools - {enabledCount}/{agentTools?.length ?? 0} enabled + {filteredEnabledCount}/{filteredTools?.length ?? 0} enabled
= ({ isBlockedByOtherUser = false WebkitMaskImage: `linear-gradient(to bottom, ${toolsScrollPos === "top" ? "black" : "transparent"}, black 16px, black calc(100% - 16px), ${toolsScrollPos === "bottom" ? "black" : "transparent"})`, }} > - {agentTools?.map((tool) => { + {filteredTools?.map((tool) => { const isDisabled = disabledTools.includes(tool.name); const row = (
@@ -741,7 +752,7 @@ const ComposerAction: FC = ({ isBlockedByOtherUser = false ); })} - {!agentTools?.length && ( + {!filteredTools?.length && (
Loading tools...
@@ -750,6 +761,39 @@ const ComposerAction: FC = ({ isBlockedByOtherUser = false )} + {hasWebSearchTool && ( + + )} {sidebarDocs.length > 0 && (