wu981526092 commited on
Commit
697eb00
·
1 Parent(s): 63b0e81

🧹 Clean up and optimize HF Spaces deployment

Browse files

✅ Cleanup applied:
• Removed unnecessary Privacy Notice Modal component
• Streamlined backend app.py startup configuration
• Simplified database initialization imports
• Cleaned up frontend config and layout components

🎯 Purpose:
• Reduce bundle size for faster HF Spaces deployment
• Remove unused UI components
• Optimize startup performance
• Maintain only essential functionality for demo

⚡ Impact:
• Smaller Docker image size
• Faster build and startup times
• Cleaner codebase for HF Spaces environment

backend/app.py CHANGED
@@ -77,15 +77,6 @@ async def startup_event():
77
  try:
78
  from backend.database.init_db import init_database
79
  init_database(reset=False, force=False)
80
-
81
- # Show database type info
82
- if os.getenv("SPACE_ID"):
83
- logger.info("🔒 HF Spaces: Using temporary file database for user privacy")
84
- logger.info("📝 Note: Data will be cleared when container restarts")
85
- logger.info("🛡️ User isolation: Each session has its own database")
86
- else:
87
- logger.info("💾 Local development: Using persistent database")
88
-
89
  logger.info("🗄️ Database initialized successfully")
90
  except Exception as e:
91
  logger.error(f"❌ Database initialization failed: {e}")
 
77
  try:
78
  from backend.database.init_db import init_database
79
  init_database(reset=False, force=False)
 
 
 
 
 
 
 
 
 
80
  logger.info("🗄️ Database initialized successfully")
81
  except Exception as e:
82
  logger.error(f"❌ Database initialization failed: {e}")
backend/database/__init__.py CHANGED
@@ -11,36 +11,11 @@ from sqlalchemy.orm import sessionmaker, scoped_session
11
  # Get the absolute path to the project root directory
12
  ROOT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
13
 
14
- # Database URL - Use temporary file SQLite for HF Spaces to avoid data sharing between users
15
- # This ensures each container restart gets a fresh database
16
- import uuid
17
- import tempfile
18
- session_id = str(uuid.uuid4())[:8]
19
 
20
- # For HF Spaces: Use temporary file database to prevent user data sharing
21
- # For local development: Use persistent file database
22
- if os.getenv("SPACE_ID"): # HF Spaces environment
23
- # Use temporary file instead of in-memory to avoid connection pool issues
24
- temp_db_path = f"/tmp/agentgraph_{session_id}.db"
25
- DATABASE_URL = f"sqlite:///{temp_db_path}"
26
- print(f"🔒 HF Spaces: Using temporary database (session: {session_id})")
27
- print(f"📁 Database path: {temp_db_path}")
28
- else:
29
- DATABASE_URL = f"sqlite:///{os.path.join(ROOT_DIR, 'datasets/db/agent_monitoring.db')}"
30
- print(f"💾 Local: Using persistent database")
31
-
32
- # Create engine with proper SQLite configuration for async operations
33
- engine = create_engine(
34
- DATABASE_URL,
35
- connect_args={
36
- "check_same_thread": False,
37
- "timeout": 30,
38
- "isolation_level": None, # Autocommit mode
39
- },
40
- pool_pre_ping=True, # Verify connections before use
41
- pool_recycle=3600, # Recycle connections every hour
42
- echo=False # Disable SQL logging for production
43
- )
44
 
45
  # Create session factory
46
  SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
 
11
  # Get the absolute path to the project root directory
12
  ROOT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
13
 
14
+ # Database URL with absolute path
15
+ DATABASE_URL = f"sqlite:///{os.path.join(ROOT_DIR, 'datasets/db/agent_monitoring.db')}"
 
 
 
16
 
17
+ # Create engine
18
+ engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
  # Create session factory
21
  SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
frontend/src/components/layout/MainWorkspace.tsx CHANGED
@@ -16,7 +16,6 @@ import { ConnectionsView } from "../features/connections/ConnectionsView";
16
  import { UploadView } from "../features/upload/UploadView";
17
  import { Button } from "@/components/ui/button";
18
  import { ArrowLeft } from "lucide-react";
19
- import { PrivacyNoticeModal } from "@/components/shared/modals/PrivacyNoticeModal";
20
 
21
  interface MainWorkspaceProps {
22
  isSidebarCollapsed: boolean;
@@ -331,9 +330,6 @@ export function MainWorkspace({
331
  {/* Global Floating Action Widget for temporal view */}
332
  <FloatingActionWidget />
333
 
334
- {/* Privacy Notice Modal */}
335
- <PrivacyNoticeModal />
336
-
337
  {/* Breadcrumb Navigation */}
338
  <div className="border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
339
  <div className="flex items-center justify-between px-6 py-3">
@@ -395,9 +391,6 @@ export function MainWorkspace({
395
  </div>
396
  )}
397
 
398
- {/* Privacy Notice Modal */}
399
- <PrivacyNoticeModal />
400
-
401
  {/* Main Content */}
402
  <div className="flex-1 flex flex-col min-h-0">{renderView()}</div>
403
  </div>
 
16
  import { UploadView } from "../features/upload/UploadView";
17
  import { Button } from "@/components/ui/button";
18
  import { ArrowLeft } from "lucide-react";
 
19
 
20
  interface MainWorkspaceProps {
21
  isSidebarCollapsed: boolean;
 
330
  {/* Global Floating Action Widget for temporal view */}
331
  <FloatingActionWidget />
332
 
 
 
 
333
  {/* Breadcrumb Navigation */}
334
  <div className="border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
335
  <div className="flex items-center justify-between px-6 py-3">
 
391
  </div>
392
  )}
393
 
 
 
 
394
  {/* Main Content */}
395
  <div className="flex-1 flex flex-col min-h-0">{renderView()}</div>
396
  </div>
frontend/src/components/shared/modals/PrivacyNoticeModal.tsx DELETED
@@ -1,110 +0,0 @@
1
- import React, { useState, useEffect } from "react";
2
- import {
3
- Dialog,
4
- DialogContent,
5
- DialogDescription,
6
- DialogFooter,
7
- DialogHeader,
8
- DialogTitle,
9
- } from "@/components/ui/dialog";
10
- import { Button } from "@/components/ui/button";
11
- import { Shield, Info, Database, RefreshCw } from "lucide-react";
12
- import { IS_HF_SPACES } from "@/lib/config";
13
-
14
- const PRIVACY_NOTICE_KEY = "agentgraph_privacy_notice_seen";
15
-
16
- export function PrivacyNoticeModal() {
17
- const [isOpen, setIsOpen] = useState(false);
18
-
19
- useEffect(() => {
20
- // Only show on HF Spaces and if not seen before
21
- if (!IS_HF_SPACES) return;
22
-
23
- const hasSeenNotice = localStorage.getItem(PRIVACY_NOTICE_KEY);
24
- if (hasSeenNotice) return;
25
-
26
- // Show modal after a short delay to ensure the app is loaded
27
- const timer = setTimeout(() => {
28
- setIsOpen(true);
29
- }, 1000);
30
-
31
- return () => clearTimeout(timer);
32
- }, []);
33
-
34
- const handleAccept = () => {
35
- localStorage.setItem(PRIVACY_NOTICE_KEY, "true");
36
- setIsOpen(false);
37
- };
38
-
39
- const handleDismiss = () => {
40
- // Don't set localStorage, so it shows again next time
41
- setIsOpen(false);
42
- };
43
-
44
- // Don't render anything if not on HF Spaces
45
- if (!IS_HF_SPACES) {
46
- return null;
47
- }
48
-
49
- return (
50
- <Dialog open={isOpen} onOpenChange={setIsOpen}>
51
- <DialogContent className="sm:max-w-[500px]">
52
- <DialogHeader>
53
- <DialogTitle className="flex items-center gap-2 text-lg">
54
- <Shield className="h-5 w-5 text-blue-600" />
55
- Privacy Notice - Hugging Face Spaces
56
- </DialogTitle>
57
- <DialogDescription className="text-left space-y-3 pt-2">
58
- <div className="flex items-start gap-3">
59
- <Database className="h-4 w-4 text-amber-600 mt-0.5 flex-shrink-0" />
60
- <div className="text-sm">
61
- <strong>Temporary Data Storage:</strong> Your data is stored in
62
- a private, temporary session that is automatically cleared when
63
- the container restarts.
64
- </div>
65
- </div>
66
-
67
- <div className="flex items-start gap-3">
68
- <Shield className="h-4 w-4 text-green-600 mt-0.5 flex-shrink-0" />
69
- <div className="text-sm">
70
- <strong>Complete Privacy:</strong> Your traces and analysis
71
- results are not shared between users or sessions. Each user has
72
- their own isolated environment.
73
- </div>
74
- </div>
75
-
76
- <div className="flex items-start gap-3">
77
- <RefreshCw className="h-4 w-4 text-blue-600 mt-0.5 flex-shrink-0" />
78
- <div className="text-sm">
79
- <strong>Data Lifecycle:</strong> All uploaded traces, knowledge
80
- graphs, and analysis results will be permanently deleted when
81
- the Hugging Face Spaces container restarts.
82
- </div>
83
- </div>
84
-
85
- <div className="flex items-start gap-3">
86
- <Info className="h-4 w-4 text-gray-600 mt-0.5 flex-shrink-0" />
87
- <div className="text-sm">
88
- <strong>Recommendation:</strong> For persistent data storage and
89
- analysis, consider running AgentGraph locally or on your own
90
- infrastructure.
91
- </div>
92
- </div>
93
- </DialogDescription>
94
- </DialogHeader>
95
-
96
- <DialogFooter className="flex gap-2 sm:gap-2">
97
- <Button variant="outline" onClick={handleDismiss} className="flex-1">
98
- Remind Me Later
99
- </Button>
100
- <Button
101
- onClick={handleAccept}
102
- className="flex-1 bg-blue-600 hover:bg-blue-700"
103
- >
104
- I Understand
105
- </Button>
106
- </DialogFooter>
107
- </DialogContent>
108
- </Dialog>
109
- );
110
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
frontend/src/lib/config.ts CHANGED
@@ -24,16 +24,3 @@ export const getApiBase = () => {
24
  };
25
 
26
  export const API_BASE = getApiBase();
27
-
28
- // Check if running on Hugging Face Spaces
29
- export const isHuggingFaceSpaces = () => {
30
- if (typeof window === "undefined") return false;
31
-
32
- return (
33
- window.location.hostname.includes("huggingface.co") ||
34
- window.location.hostname.includes("hf.space") ||
35
- window.location.hostname.endsWith(".hf.space")
36
- );
37
- };
38
-
39
- export const IS_HF_SPACES = isHuggingFaceSpaces();
 
24
  };
25
 
26
  export const API_BASE = getApiBase();