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