Persist device details by hostname and enhance UI

This commit is contained in:
2025-08-13 00:37:43 -06:00
parent f1fe831911
commit 10c024ddd7
6 changed files with 936 additions and 4 deletions

View File

@@ -14,6 +14,7 @@ import os # To Read Production ReactJS Server Folder
import json # For reading workflow JSON files
import shutil # For moving workflow files and folders
from typing import List, Dict
import sqlite3
# Borealis Python API Endpoints
from Python_API_Endpoints.ocr_engines import run_ocr_on_base64
@@ -380,6 +381,23 @@ registered_agents: Dict[str, Dict] = {}
agent_configurations: Dict[str, Dict] = {}
latest_images: Dict[str, Dict] = {}
# Device database initialization
DB_PATH = os.path.abspath(
os.path.join(os.path.dirname(__file__), "..", "..", "Databases", "devices.db")
)
os.makedirs(os.path.dirname(DB_PATH), exist_ok=True)
def init_db():
conn = sqlite3.connect(DB_PATH)
cur = conn.cursor()
cur.execute(
"CREATE TABLE IF NOT EXISTS device_details (hostname TEXT PRIMARY KEY, description TEXT, details TEXT)"
)
conn.commit()
conn.close()
init_db()
@app.route("/api/agents")
def get_agents():
"""
@@ -388,6 +406,79 @@ def get_agents():
return jsonify(registered_agents)
@app.route("/api/agent/details", methods=["POST"])
def save_agent_details():
data = request.get_json(silent=True) or {}
hostname = data.get("hostname")
details = data.get("details")
if not hostname and isinstance(details, dict):
hostname = details.get("summary", {}).get("hostname")
if not hostname or not isinstance(details, dict):
return jsonify({"error": "invalid payload"}), 400
try:
conn = sqlite3.connect(DB_PATH)
cur = conn.cursor()
cur.execute(
"SELECT description FROM device_details WHERE hostname = ?",
(hostname,),
)
row = cur.fetchone()
description = row[0] if row else ""
cur.execute(
"REPLACE INTO device_details (hostname, description, details) VALUES (?, ?, ?)",
(hostname, description, json.dumps(details)),
)
conn.commit()
conn.close()
return jsonify({"status": "ok"})
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route("/api/device/details/<hostname>", methods=["GET"])
def get_device_details(hostname: str):
try:
conn = sqlite3.connect(DB_PATH)
cur = conn.cursor()
cur.execute(
"SELECT details, description FROM device_details WHERE hostname = ?",
(hostname,),
)
row = cur.fetchone()
conn.close()
if row:
try:
details = json.loads(row[0])
except Exception:
details = {}
description = row[1] if len(row) > 1 else ""
if description:
details.setdefault("summary", {})["description"] = description
return jsonify(details)
except Exception:
pass
return jsonify({})
@app.route("/api/device/description/<hostname>", methods=["POST"])
def set_device_description(hostname: str):
data = request.get_json(silent=True) or {}
description = (data.get("description") or "").strip()
try:
conn = sqlite3.connect(DB_PATH)
cur = conn.cursor()
cur.execute(
"INSERT INTO device_details(hostname, description, details) VALUES (?, ?, COALESCE((SELECT details FROM device_details WHERE hostname = ?), '{}')) "
"ON CONFLICT(hostname) DO UPDATE SET description=excluded.description",
(hostname, description, hostname),
)
conn.commit()
conn.close()
return jsonify({"status": "ok"})
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route("/api/agent/<agent_id>", methods=["DELETE"])
def delete_agent(agent_id: str):
"""Remove an agent from the in-memory registry."""