diff --git a/surfsense_web/app/dashboard/[search_space_id]/client-layout.tsx b/surfsense_web/app/dashboard/[search_space_id]/client-layout.tsx
index bfe8599f6..284c1ebc0 100644
--- a/surfsense_web/app/dashboard/[search_space_id]/client-layout.tsx
+++ b/surfsense_web/app/dashboard/[search_space_id]/client-layout.tsx
@@ -265,7 +265,7 @@ export function DashboardClientLayout({
-
{children}
+ {children}
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 00514facb..e18629b92 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
@@ -626,11 +626,11 @@ export default function NewChatPage() {
-
-
-
-
-
+
+ }
+ />
);
diff --git a/surfsense_web/components/assistant-ui/thread.tsx b/surfsense_web/components/assistant-ui/thread.tsx
index 33d6a0cad..9596f4fe0 100644
--- a/surfsense_web/components/assistant-ui/thread.tsx
+++ b/surfsense_web/components/assistant-ui/thread.tsx
@@ -8,7 +8,6 @@ import {
ThreadPrimitive,
useAssistantState,
useMessage,
- useThreadViewport,
} from "@assistant-ui/react";
import { useAtomValue } from "jotai";
import {
@@ -69,6 +68,8 @@ import { cn } from "@/lib/utils";
*/
interface ThreadProps {
messageThinkingSteps?: Map
;
+ /** Optional header component to render at the top of the viewport (sticky) */
+ header?: React.ReactNode;
}
// Context to pass thinking steps to AssistantMessage
@@ -212,71 +213,21 @@ const ThinkingStepsDisplay: FC<{ steps: ThinkingStep[]; isThreadRunning?: boolea
);
};
-/**
- * Component that handles auto-scroll when thinking steps update.
- * Uses useThreadViewport to scroll to bottom when thinking steps change,
- * ensuring the user always sees the latest content during streaming.
- */
-const ThinkingStepsScrollHandler: FC = () => {
- const thinkingStepsMap = useContext(ThinkingStepsContext);
- const viewport = useThreadViewport();
- const isRunning = useAssistantState(({ thread }) => thread.isRunning);
- // Track the serialized state to detect any changes
- const prevStateRef = useRef("");
-
- useEffect(() => {
- // Only act during streaming
- if (!isRunning) {
- prevStateRef.current = "";
- return;
- }
-
- // Serialize the thinking steps state to detect any changes
- // This catches new steps, status changes, and item additions
- let stateString = "";
- thinkingStepsMap.forEach((steps, msgId) => {
- steps.forEach((step) => {
- stateString += `${msgId}:${step.id}:${step.status}:${step.items?.length || 0};`;
- });
- });
-
- // If state changed at all during streaming, scroll
- if (stateString !== prevStateRef.current && stateString !== "") {
- prevStateRef.current = stateString;
-
- // Multiple attempts to ensure scroll happens after DOM updates
- const scrollAttempt = () => {
- try {
- viewport.scrollToBottom();
- } catch (e) {
- // Ignore errors - viewport might not be ready
- }
- };
-
- // Delayed attempts to handle async DOM updates
- requestAnimationFrame(scrollAttempt);
- setTimeout(scrollAttempt, 100);
- }
- }, [thinkingStepsMap, viewport, isRunning]);
-
- return null; // This component doesn't render anything
-};
-
-export const Thread: FC = ({ messageThinkingSteps = new Map() }) => {
+export const Thread: FC = ({ messageThinkingSteps = new Map(), header }) => {
return (
- {/* Auto-scroll handler for thinking steps - must be inside Viewport */}
-
+ {/* Optional sticky header for model selector etc. */}
+ {header && {header}
}
thread.isEmpty}>
diff --git a/surfsense_web/components/new-chat/chat-header.tsx b/surfsense_web/components/new-chat/chat-header.tsx
index ef1533e23..34b2cc814 100644
--- a/surfsense_web/components/new-chat/chat-header.tsx
+++ b/surfsense_web/components/new-chat/chat-header.tsx
@@ -47,12 +47,7 @@ export function ChatHeader({ searchSpaceId }: ChatHeaderProps) {
return (
<>
- {/* Header Bar */}
-
-
-
-
- {/* Config Sidebar */}
+
@@ -206,11 +207,14 @@ export function ModelSelector({ onEdit, onAddNew, className }: ModelSelectorProp
-
+
{/* Switching overlay */}
{isSwitching && (
@@ -221,8 +225,7 @@ export function ModelSelector({ onEdit, onAddNew, className }: ModelSelectorProp
)}
-
-
+
0 && filteredUserConfigs.length > 0 && (
-
+
)}
{/* User Configs Section */}
@@ -362,7 +365,7 @@ export function ModelSelector({ onEdit, onAddNew, className }: ModelSelectorProp
)}
{/* Add New Config Button */}
-
+