diff --git a/apps/x/apps/renderer/src/App.tsx b/apps/x/apps/renderer/src/App.tsx
index 150cd2ce..2ae02677 100644
--- a/apps/x/apps/renderer/src/App.tsx
+++ b/apps/x/apps/renderer/src/App.tsx
@@ -6,7 +6,7 @@ import type { LanguageModelUsage, ToolUIPart } from 'ai';
import './App.css'
import z from 'zod';
import { Button } from './components/ui/button';
-import { CheckIcon, LoaderIcon, ArrowUp, PanelLeftIcon, PanelRightIcon, Square, X } from 'lucide-react';
+import { CheckIcon, LoaderIcon, ArrowUp, PanelLeftIcon, PanelRightIcon, Square, X, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react';
import { cn } from '@/lib/utils';
import { MarkdownEditor } from './components/markdown-editor';
import { ChatInputBar } from './components/chat-button';
@@ -446,8 +446,33 @@ function ChatInputWithMentions({
)
}
-/** Traffic light placeholders + toggle button, fixed next to macOS traffic lights */
-function FixedSidebarToggle() {
+/** A snapshot of which view the user is on */
+type ViewState =
+ | { type: 'chat'; runId: string | null }
+ | { type: 'file'; path: string }
+ | { type: 'graph' }
+ | { type: 'task'; name: string }
+
+function viewStatesEqual(a: ViewState, b: ViewState): boolean {
+ if (a.type !== b.type) return false
+ if (a.type === 'chat' && b.type === 'chat') return a.runId === b.runId
+ if (a.type === 'file' && b.type === 'file') return a.path === b.path
+ if (a.type === 'task' && b.type === 'task') return a.name === b.name
+ return true // both graph
+}
+
+/** Traffic light placeholders + toggle button + back/forward nav, fixed next to macOS traffic lights */
+function FixedSidebarToggle({
+ onNavigateBack,
+ onNavigateForward,
+ canNavigateBack,
+ canNavigateForward,
+}: {
+ onNavigateBack: () => void
+ onNavigateForward: () => void
+ canNavigateBack: boolean
+ canNavigateForward: boolean
+}) {
const { toggleSidebar } = useSidebar()
return (
@@ -466,6 +491,25 @@ function FixedSidebarToggle() {
>
+ {/* Back / Forward navigation */}
+
+
)
}
@@ -489,8 +533,6 @@ function ContentHeader({ children }: { children: React.ReactNode }) {
function App() {
// File browser state (for Knowledge section)
const [selectedPath, setSelectedPath] = useState(null)
- const [fileHistoryBack, setFileHistoryBack] = useState([])
- const [fileHistoryForward, setFileHistoryForward] = useState([])
const [fileContent, setFileContent] = useState('')
const [editorContent, setEditorContent] = useState('')
const [tree, setTree] = useState([])
@@ -506,6 +548,16 @@ function App() {
const [graphError, setGraphError] = useState(null)
const [isChatSidebarOpen, setIsChatSidebarOpen] = useState(true)
+ // Keep the latest selected path in a ref (avoids stale async updates when switching rapidly)
+ const selectedPathRef = useRef(null)
+ const editorPathRef = useRef(null)
+ const fileLoadRequestIdRef = useRef(0)
+ const initialContentByPathRef = useRef