diff --git a/apps/desktop/src/renderer/src/App.tsx b/apps/desktop/src/renderer/src/App.tsx
index 73213be93..dc5cf23c4 100644
--- a/apps/desktop/src/renderer/src/App.tsx
+++ b/apps/desktop/src/renderer/src/App.tsx
@@ -5,7 +5,6 @@ import { TooltipProvider } from '@multica/ui/components/ui/tooltip'
import { Toaster } from './components/toaster'
import Layout from './pages/layout'
import HomePage from './pages/home'
-import ChatPage from './pages/chat'
import ProfilePage from './pages/agent/profile'
import SkillsPage from './pages/agent/skills'
import ToolsPage from './pages/agent/tools'
@@ -73,7 +72,7 @@ const router = createHashRouter([
),
},
- { path: 'chat', element: },
+ { path: 'chat', element: null },
{ path: 'agent/profile', element: },
{ path: 'agent/skills', element: },
{ path: 'agent/tools', element: },
diff --git a/apps/desktop/src/renderer/src/components/local-chat.tsx b/apps/desktop/src/renderer/src/components/local-chat.tsx
index 39c6c0b38..0f842a059 100644
--- a/apps/desktop/src/renderer/src/components/local-chat.tsx
+++ b/apps/desktop/src/renderer/src/components/local-chat.tsx
@@ -73,12 +73,13 @@ export function LocalChat({ initialPrompt }: LocalChatProps) {
const currentMeta = current ? providers.find((p) => p.id === current.provider) : null
// Auto-send initial prompt after a short delay
- const hasSentInitialPrompt = useRef(false)
+ const lastPromptRef = useRef(undefined)
useEffect(() => {
- if (!agentId || !initialPrompt || hasSentInitialPrompt.current) return
+ if (!agentId || !initialPrompt) return
+ if (initialPrompt === lastPromptRef.current) return
const timer = setTimeout(() => {
- hasSentInitialPrompt.current = true
+ lastPromptRef.current = initialPrompt
sendMessage(initialPrompt)
// Remove prompt from URL to prevent re-sending on back navigation
navigate('/chat', { replace: true })
diff --git a/apps/desktop/src/renderer/src/pages/layout.tsx b/apps/desktop/src/renderer/src/pages/layout.tsx
index 1651e447a..476f61c73 100644
--- a/apps/desktop/src/renderer/src/pages/layout.tsx
+++ b/apps/desktop/src/renderer/src/pages/layout.tsx
@@ -1,3 +1,4 @@
+import { useState, useEffect } from 'react'
import { Outlet, NavLink, useLocation, useNavigate } from 'react-router-dom'
import { Button } from '@multica/ui/components/ui/button'
import { MulticaIcon } from '@multica/ui/components/multica-icon'
@@ -43,6 +44,7 @@ import {
} from '@multica/ui/components/ui/sidebar'
import { cn } from '@multica/ui/lib/utils'
import { ModeToggle } from '../components/mode-toggle'
+import { LocalChat } from '../components/local-chat'
import { DeviceConfirmDialog } from '../components/device-confirm-dialog'
import { UpdateNotification } from '../components/update-notification'
import { useAuthStore } from '../stores/auth'
@@ -151,8 +153,20 @@ export default function Layout() {
const location = useLocation()
const navigate = useNavigate()
const isAgentActive = location.pathname.startsWith('/agent')
+ const isOnChat = location.pathname === '/chat'
const { user, clearAuth } = useAuthStore()
+ // Lazy mount: only mount Chat on first visit, then keep it mounted forever
+ const [chatMounted, setChatMounted] = useState(false)
+ useEffect(() => {
+ if (isOnChat && !chatMounted) setChatMounted(true)
+ }, [isOnChat, chatMounted])
+
+ // Extract initialPrompt from URL search params when navigating to /chat?prompt=...
+ const initialPrompt = isOnChat
+ ? new URLSearchParams(location.search).get('prompt') ?? undefined
+ : undefined
+
const handleLogout = async () => {
await clearAuth()
navigate('/login')
@@ -285,7 +299,14 @@ export default function Layout() {
-
+
+
+
+ {chatMounted && (
+
+
+
+ )}