+
+ {selectedCompanyId && activeConversationId && (
+ <>
+ {/* Bookmarks toggle */}
+
+ {/* Export buttons */}
+
+ >
+ )}
{selectedCompanyId && (
+ {/* Bookmarks panel (shown when toggled) */}
+ {bookmarksOpen && selectedCompanyId && (
+
+
+
+ )}
+
+ {/* Branch selector */}
+ {activeConversationId && branches.length > 0 && (
+
+ )}
+
{/* Message area */}
{activeConversationId ? (
@@ -204,6 +335,8 @@ export function ChatPanel() {
onRetry={handleRetry}
onHandoff={handleHandoff}
agentMap={agentMap}
+ onBookmark={handleBookmark}
+ bookmarkedMessageIds={bookmarkedMessageIds}
/>
) : (
@@ -230,6 +363,14 @@ export function ChatPanel() {
+
+ {/* Search dialog */}
+
);
}
diff --git a/ui/src/components/CommandPalette.tsx b/ui/src/components/CommandPalette.tsx
index 9d84be52..ed1c66cd 100644
--- a/ui/src/components/CommandPalette.tsx
+++ b/ui/src/components/CommandPalette.tsx
@@ -28,6 +28,7 @@ import {
History,
SquarePen,
Plus,
+ Search,
} from "lucide-react";
import { Identity } from "./Identity";
import { agentUrl, projectUrl } from "../lib/utils";
@@ -114,6 +115,16 @@ export function CommandPalette() {
No results found.
+ {
+ window.dispatchEvent(new CustomEvent("nexus:open-chat-search"));
+ setOpen(false);
+ }}
+ >
+
+ Search chat messages
+
{
setOpen(false);
diff --git a/ui/src/context/ChatPanelContext.tsx b/ui/src/context/ChatPanelContext.tsx
index 7ce3bdb3..bf3eed0c 100644
--- a/ui/src/context/ChatPanelContext.tsx
+++ b/ui/src/context/ChatPanelContext.tsx
@@ -5,9 +5,11 @@ const STORAGE_KEY = "nexus:chat-panel-open";
interface ChatPanelContextValue {
chatOpen: boolean;
activeConversationId: string | null;
+ scrollToMessageId: string | null;
setChatOpen: (open: boolean) => void;
toggleChat: () => void;
setActiveConversationId: (id: string | null) => void;
+ setScrollToMessageId: (id: string | null) => void;
}
const ChatPanelContext = createContext(null);
@@ -32,6 +34,7 @@ function writePreference(open: boolean) {
export function ChatPanelProvider({ children }: { children: ReactNode }) {
const [chatOpen, setChatOpenState] = useState(readPreference);
const [activeConversationId, setActiveConversationId] = useState(null);
+ const [scrollToMessageId, setScrollToMessageId] = useState(null);
const setChatOpen = useCallback((open: boolean) => {
setChatOpenState(open);
@@ -48,7 +51,7 @@ export function ChatPanelProvider({ children }: { children: ReactNode }) {
return (
{children}