Asish22 commited on
Commit
4e52e70
Β·
verified Β·
1 Parent(s): 6bdaaac

Deploy Sentinel AI with service fixes

Browse files
Files changed (4) hide show
  1. .gitattributes +3 -1
  2. Dockerfile +10 -5
  3. app.py +15 -9
  4. main.py +38 -15
.gitattributes CHANGED
@@ -17,4 +17,6 @@
17
  *.safetensors filter=lfs diff=lfs merge=lfs -text
18
  *.tar filter=lfs diff=lfs merge=lfs -text
19
  *.zip filter=lfs diff=lfs merge=lfs -text
20
- *.png filter=lfs diff=lfs merge=lfs -text
 
 
 
17
  *.safetensors filter=lfs diff=lfs merge=lfs -text
18
  *.tar filter=lfs diff=lfs merge=lfs -text
19
  *.zip filter=lfs diff=lfs merge=lfs -text
20
+ assets/logo.png filter=lfs diff=lfs merge=lfs -text
21
+ assets/sentinel_logo.png filter=lfs diff=lfs merge=lfs -text
22
+ logo.png filter=lfs diff=lfs merge=lfs -text
Dockerfile CHANGED
@@ -9,21 +9,26 @@ RUN apt-get update && apt-get install -y \
9
 
10
  # Create non-root user (required by HF Spaces)
11
  RUN useradd -m -u 1000 user
12
- ENV HOME=/home/user \
13
- PATH="/home/user/.local/bin:$PATH"
14
 
15
  WORKDIR /app
16
 
17
- # Copy requirements first to leverage Docker cache
18
- COPY --chown=user requirements.txt .
19
  RUN pip install --no-cache-dir -r requirements.txt
20
 
21
  # Copy the entire application
22
- COPY --chown=user . .
 
 
 
23
 
24
  # Switch to non-root user
25
  USER user
26
 
 
 
 
 
27
  # Expose the port Hugging Face expects
28
  EXPOSE 7860
29
 
 
9
 
10
  # Create non-root user (required by HF Spaces)
11
  RUN useradd -m -u 1000 user
 
 
12
 
13
  WORKDIR /app
14
 
15
+ # Copy and install requirements as root (system-wide)
16
+ COPY requirements.txt .
17
  RUN pip install --no-cache-dir -r requirements.txt
18
 
19
  # Copy the entire application
20
+ COPY . .
21
+
22
+ # Make the app directory writable by user (for SQLite DB, logs, JSON files)
23
+ RUN chown -R user:user /app
24
 
25
  # Switch to non-root user
26
  USER user
27
 
28
+ ENV HOME=/home/user \
29
+ PATH="/home/user/.local/bin:$PATH" \
30
+ PYTHONUNBUFFERED=1
31
+
32
  # Expose the port Hugging Face expects
33
  EXPOSE 7860
34
 
app.py CHANGED
@@ -43,7 +43,7 @@ def start_background_services():
43
  start_background_services()
44
 
45
  # --- Helper Functions ---
46
- @st.cache_data(ttl=60)
47
  def check_server_status():
48
  # All services are mounted as sub-apps under the gateway on port 8000
49
  urls = {
@@ -53,12 +53,17 @@ def check_server_status():
53
  "Private DB": "http://127.0.0.1:8000/private/",
54
  }
55
  statuses = {}
56
- with httpx.Client(timeout=3.0) as client:
57
- for name, url in urls.items():
58
- try:
59
- response = client.get(url)
60
- statuses[name] = "βœ… Online" if response.status_code == 200 else "⚠️ Error"
61
- except: statuses[name] = "❌ Offline"
 
 
 
 
 
62
  return statuses
63
 
64
  def load_watchlist():
@@ -345,8 +350,9 @@ def render_analysis():
345
  all_online = all(s == "βœ… Online" for s in server_statuses.values())
346
 
347
  if not all_online:
348
- st.error("SYSTEM HALTED: Core services offline. Check sidebar status.")
349
- else:
 
350
  with st.status("πŸš€ SENTINEL ORCHESTRATOR ENGAGED...", expanded=True) as status:
351
  try:
352
  from agents.orchestrator_v3 import get_orchestrator
 
43
  start_background_services()
44
 
45
  # --- Helper Functions ---
46
+ @st.cache_data(ttl=30)
47
  def check_server_status():
48
  # All services are mounted as sub-apps under the gateway on port 8000
49
  urls = {
 
53
  "Private DB": "http://127.0.0.1:8000/private/",
54
  }
55
  statuses = {}
56
+ try:
57
+ with httpx.Client(timeout=5.0) as client:
58
+ for name, url in urls.items():
59
+ try:
60
+ response = client.get(url)
61
+ statuses[name] = "βœ… Online" if response.status_code == 200 else "⚠️ Error"
62
+ except:
63
+ statuses[name] = "❌ Offline"
64
+ except Exception:
65
+ for name in urls:
66
+ statuses[name] = "❌ Offline"
67
  return statuses
68
 
69
  def load_watchlist():
 
350
  all_online = all(s == "βœ… Online" for s in server_statuses.values())
351
 
352
  if not all_online:
353
+ st.warning("⚠️ Some core services are still starting up. Analysis may have limited data. Proceeding anyway...")
354
+
355
+ if True: # Always allow analysis to proceed
356
  with st.status("πŸš€ SENTINEL ORCHESTRATOR ENGAGED...", expanded=True) as status:
357
  try:
358
  from agents.orchestrator_v3 import get_orchestrator
main.py CHANGED
@@ -3,38 +3,61 @@ import sys
3
  import os
4
  import time
5
  import signal
 
6
 
7
  def cleanup(signum, frame):
8
- print("Stopping services...")
9
- # Add cleanup logic here if needed
10
  sys.exit(0)
11
 
12
  signal.signal(signal.SIGINT, cleanup)
13
  signal.signal(signal.SIGTERM, cleanup)
14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  def main():
16
- print("πŸš€ Starting Sentinel Monolith...")
17
 
18
  # 1. Start the MCP Gateway (which now includes all microservices)
19
- # running on port 8000
20
  gateway_cmd = [sys.executable, "mcp_gateway.py"]
21
- gateway_process = subprocess.Popen(gateway_cmd, cwd=os.getcwd())
22
- print(f"βœ… Gateway started (PID: {gateway_process.pid})")
 
 
 
 
 
23
 
24
  # 2. Start the Monitor (runs in background loop)
25
- # Using the same interpreter
26
  monitor_cmd = [sys.executable, "monitor.py"]
27
- monitor_process = subprocess.Popen(monitor_cmd, cwd=os.getcwd())
28
- print(f"βœ… Monitor started (PID: {monitor_process.pid})")
 
 
 
 
 
29
 
30
- # Give backend a moment to initialize
31
- time.sleep(5)
32
 
33
- # 3. Start Streamlit (Frontend)
34
- # This commands blocks until Streamlit exits
35
- print("βœ… Starting Streamlit on port 7860...")
36
  streamlit_cmd = [
37
- "streamlit", "run", "app.py",
38
  "--server.port", "7860",
39
  "--server.address", "0.0.0.0",
40
  "--server.headless", "true",
 
3
  import os
4
  import time
5
  import signal
6
+ import httpx
7
 
8
  def cleanup(signum, frame):
9
+ print("Stopping services...", flush=True)
 
10
  sys.exit(0)
11
 
12
  signal.signal(signal.SIGINT, cleanup)
13
  signal.signal(signal.SIGTERM, cleanup)
14
 
15
+ def wait_for_gateway(url="http://127.0.0.1:8000/", timeout=60, interval=2):
16
+ """Wait until the MCP Gateway is responding before starting Streamlit."""
17
+ print(f"⏳ Waiting for Gateway at {url} (timeout={timeout}s)...", flush=True)
18
+ start = time.time()
19
+ while time.time() - start < timeout:
20
+ try:
21
+ resp = httpx.get(url, timeout=3.0)
22
+ if resp.status_code == 200:
23
+ print("βœ… Gateway is healthy!", flush=True)
24
+ return True
25
+ except Exception:
26
+ pass
27
+ time.sleep(interval)
28
+ print("⚠️ Gateway did not respond in time. Starting Streamlit anyway...", flush=True)
29
+ return False
30
+
31
  def main():
32
+ print("πŸš€ Starting Sentinel Monolith...", flush=True)
33
 
34
  # 1. Start the MCP Gateway (which now includes all microservices)
 
35
  gateway_cmd = [sys.executable, "mcp_gateway.py"]
36
+ gateway_process = subprocess.Popen(
37
+ gateway_cmd,
38
+ cwd=os.getcwd(),
39
+ stdout=sys.stdout,
40
+ stderr=sys.stderr,
41
+ )
42
+ print(f"βœ… Gateway started (PID: {gateway_process.pid})", flush=True)
43
 
44
  # 2. Start the Monitor (runs in background loop)
 
45
  monitor_cmd = [sys.executable, "monitor.py"]
46
+ monitor_process = subprocess.Popen(
47
+ monitor_cmd,
48
+ cwd=os.getcwd(),
49
+ stdout=sys.stdout,
50
+ stderr=sys.stderr,
51
+ )
52
+ print(f"βœ… Monitor started (PID: {monitor_process.pid})", flush=True)
53
 
54
+ # 3. Wait for gateway to be healthy before starting Streamlit
55
+ wait_for_gateway()
56
 
57
+ # 4. Start Streamlit (Frontend)
58
+ print("βœ… Starting Streamlit on port 7860...", flush=True)
 
59
  streamlit_cmd = [
60
+ sys.executable, "-m", "streamlit", "run", "app.py",
61
  "--server.port", "7860",
62
  "--server.address", "0.0.0.0",
63
  "--server.headless", "true",