File size: 5,006 Bytes
9564069 972bdb5 a44a6ec 0ef8cba 402ce00 3578090 9564069 506c5f2 9564069 0e5f52f 0ef8cba 0e5f52f 29ee1c2 93cbd1b 0e5f52f dc06ee7 3578090 506c5f2 5611aed 402ce00 9564069 3578090 402ce00 9564069 3578090 402ce00 a845c0d 9564069 a845c0d 9564069 402ce00 9564069 a845c0d 9564069 a845c0d 9564069 a845c0d 9564069 507cacb 9564069 a845c0d 507cacb a845c0d 9564069 a845c0d 9564069 a845c0d 9564069 5856d68 29ee1c2 0ef8cba 402ce00 0ef8cba 402ce00 0ef8cba dc06ee7 5856d68 a44a6ec 132f86c a44a6ec 132f86c a44a6ec 132f86c a44a6ec 132f86c a44a6ec 132f86c a44a6ec 132f86c a44a6ec 402ce00 a44a6ec dc06ee7 93e01b6 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
import { useState, useCallback, useEffect, useRef } from 'react'
import ThemeProvider from '@/components/ThemeProvider'
import TabVisibilityProvider from '@/contexts/TabVisibilityProvider'
import ApiKeyAlert from '@/components/ApiKeyAlert'
import StatusIndicator from '@/components/status/StatusIndicator'
import { healthCheckInterval } from '@/lib/constants'
import { useBackendState, useAuthStore } from '@/stores/state'
import { useSettingsStore } from '@/stores/settings'
import { getAuthStatus } from '@/api/lightrag'
import SiteHeader from '@/features/SiteHeader'
import { InvalidApiKeyError, RequireApiKeError } from '@/api/lightrag'
import GraphViewer from '@/features/GraphViewer'
import DocumentManager from '@/features/DocumentManager'
import RetrievalTesting from '@/features/RetrievalTesting'
import ApiSite from '@/features/ApiSite'
import { Tabs, TabsContent } from '@/components/ui/Tabs'
function App() {
const message = useBackendState.use.message()
const enableHealthCheck = useSettingsStore.use.enableHealthCheck()
const currentTab = useSettingsStore.use.currentTab()
const [apiKeyAlertOpen, setApiKeyAlertOpen] = useState(false)
const versionCheckRef = useRef(false); // Prevent duplicate calls in Vite dev mode
const handleApiKeyAlertOpenChange = useCallback((open: boolean) => {
setApiKeyAlertOpen(open)
if (!open) {
useBackendState.getState().clear()
}
}, [])
// Health check - can be disabled
useEffect(() => {
// Only execute if health check is enabled and ApiKeyAlert is closed
if (!enableHealthCheck || apiKeyAlertOpen) return;
// Health check function
const performHealthCheck = async () => {
await useBackendState.getState().check();
};
// Set interval for periodic execution
const interval = setInterval(performHealthCheck, healthCheckInterval * 1000);
return () => clearInterval(interval);
}, [enableHealthCheck, apiKeyAlertOpen]);
// Version check - independent and executed only once
useEffect(() => {
const checkVersion = async () => {
// Prevent duplicate calls in Vite dev mode
if (versionCheckRef.current) return;
versionCheckRef.current = true;
// Check if version info was already obtained in login page
const versionCheckedFromLogin = sessionStorage.getItem('VERSION_CHECKED_FROM_LOGIN') === 'true';
if (versionCheckedFromLogin) return;
// Get version info
const token = localStorage.getItem('LIGHTRAG-API-TOKEN');
if (!token) return;
try {
const status = await getAuthStatus();
if (status.core_version || status.api_version) {
const isGuestMode = status.auth_mode === 'disabled' || useAuthStore.getState().isGuestMode;
// Update version info while maintaining login state
useAuthStore.getState().login(
token,
isGuestMode,
status.core_version,
status.api_version
);
// Set flag to indicate version info has been checked
sessionStorage.setItem('VERSION_CHECKED_FROM_LOGIN', 'true');
}
} catch (error) {
console.error('Failed to get version info:', error);
}
};
// Execute version check
checkVersion();
}, []); // Empty dependency array ensures it only runs once on mount
const handleTabChange = useCallback(
(tab: string) => useSettingsStore.getState().setCurrentTab(tab as any),
[]
)
useEffect(() => {
if (message) {
if (message.includes(InvalidApiKeyError) || message.includes(RequireApiKeError)) {
setApiKeyAlertOpen(true)
}
}
}, [message])
return (
<ThemeProvider>
<TabVisibilityProvider>
<main className="flex h-screen w-screen overflow-hidden">
<Tabs
defaultValue={currentTab}
className="!m-0 flex grow flex-col !p-0 overflow-hidden"
onValueChange={handleTabChange}
>
<SiteHeader />
<div className="relative grow">
<TabsContent value="documents" className="absolute top-0 right-0 bottom-0 left-0 overflow-auto">
<DocumentManager />
</TabsContent>
<TabsContent value="knowledge-graph" className="absolute top-0 right-0 bottom-0 left-0 overflow-hidden">
<GraphViewer />
</TabsContent>
<TabsContent value="retrieval" className="absolute top-0 right-0 bottom-0 left-0 overflow-hidden">
<RetrievalTesting />
</TabsContent>
<TabsContent value="api" className="absolute top-0 right-0 bottom-0 left-0 overflow-hidden">
<ApiSite />
</TabsContent>
</div>
</Tabs>
{enableHealthCheck && <StatusIndicator />}
<ApiKeyAlert open={apiKeyAlertOpen} onOpenChange={handleApiKeyAlertOpenChange} />
</main>
</TabVisibilityProvider>
</ThemeProvider>
)
}
export default App
|