Spaces:
Running
Running
Update app/app.py
Browse files- app/app.py +59 -110
app/app.py
CHANGED
|
@@ -56,10 +56,10 @@ logger_providers = logging.getLogger('providers')
|
|
| 56 |
logger_models = logging.getLogger('models')
|
| 57 |
logger_db_sync = logging.getLogger('db_sync')
|
| 58 |
# =============================================================================
|
| 59 |
-
# Quart app instance
|
| 60 |
# =============================================================================
|
| 61 |
-
app = Quart(__name__)
|
| 62 |
-
START_TIME = datetime.utcnow()
|
| 63 |
# =============================================================================
|
| 64 |
# Quart Routes
|
| 65 |
# =============================================================================
|
|
@@ -75,104 +75,43 @@ START_TIME = datetime.utcnow()
|
|
| 75 |
# "service": "Universal MCP Hub",
|
| 76 |
# "uptime_seconds": int(uptime.total_seconds()),
|
| 77 |
# })
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
uptime_s = int(uptime.total_seconds())
|
| 83 |
-
|
| 84 |
-
accept = request.headers.get("Accept", "")
|
| 85 |
-
if "text/html" not in accept:
|
| 86 |
-
return jsonify({"status": "running", "service": "Universal MCP Hub", "uptime_seconds": uptime_s})
|
| 87 |
-
|
| 88 |
-
html = f"""<!DOCTYPE html>
|
| 89 |
<html lang="en">
|
| 90 |
<head>
|
| 91 |
<meta charset="UTF-8">
|
| 92 |
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 93 |
<title>Universal MCP Hub</title>
|
| 94 |
<style>
|
| 95 |
-
*
|
| 96 |
-
body
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
.
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
margin-bottom: 1.5rem;
|
| 119 |
-
padding-bottom: 1.5rem;
|
| 120 |
-
border-bottom: 1px solid #21262d;
|
| 121 |
-
}}
|
| 122 |
-
.dot {{
|
| 123 |
-
width: 10px; height: 10px;
|
| 124 |
-
border-radius: 50%;
|
| 125 |
-
background: #3fb950;
|
| 126 |
-
box-shadow: 0 0 8px #3fb95080;
|
| 127 |
-
flex-shrink: 0;
|
| 128 |
-
}}
|
| 129 |
-
h1 {{ font-size: 1.1rem; font-weight: 600; color: #f0f6fc; }}
|
| 130 |
-
.badge {{
|
| 131 |
-
margin-left: auto;
|
| 132 |
-
font-size: 0.7rem;
|
| 133 |
-
background: #1f6feb30;
|
| 134 |
-
color: #58a6ff;
|
| 135 |
-
border: 1px solid #1f6feb;
|
| 136 |
-
border-radius: 20px;
|
| 137 |
-
padding: 2px 10px;
|
| 138 |
-
}}
|
| 139 |
-
.stats {{
|
| 140 |
-
display: grid;
|
| 141 |
-
grid-template-columns: 1fr 1fr;
|
| 142 |
-
gap: 12px;
|
| 143 |
-
margin-bottom: 1.5rem;
|
| 144 |
-
}}
|
| 145 |
-
.stat {{
|
| 146 |
-
background: #0d1117;
|
| 147 |
-
border: 1px solid #21262d;
|
| 148 |
-
border-radius: 8px;
|
| 149 |
-
padding: 0.75rem 1rem;
|
| 150 |
-
}}
|
| 151 |
-
.stat-label {{ font-size: 0.7rem; color: #8b949e; margin-bottom: 4px; }}
|
| 152 |
-
.stat-value {{ font-size: 1rem; color: #f0f6fc; font-weight: 500; }}
|
| 153 |
-
.stat-value.green {{ color: #3fb950; }}
|
| 154 |
-
.links {{
|
| 155 |
-
display: flex;
|
| 156 |
-
flex-direction: column;
|
| 157 |
-
gap: 8px;
|
| 158 |
-
}}
|
| 159 |
-
.link {{
|
| 160 |
-
display: flex;
|
| 161 |
-
align-items: center;
|
| 162 |
-
gap: 10px;
|
| 163 |
-
padding: 0.6rem 0.9rem;
|
| 164 |
-
background: #0d1117;
|
| 165 |
-
border: 1px solid #21262d;
|
| 166 |
-
border-radius: 8px;
|
| 167 |
-
color: #8b949e;
|
| 168 |
-
text-decoration: none;
|
| 169 |
-
font-size: 0.82rem;
|
| 170 |
-
transition: border-color 0.15s, color 0.15s;
|
| 171 |
-
}}
|
| 172 |
-
.link:hover {{ border-color: #58a6ff; color: #58a6ff; }}
|
| 173 |
-
.link svg {{ flex-shrink: 0; opacity: 0.7; }}
|
| 174 |
-
.link span {{ flex: 1; }}
|
| 175 |
-
.link .arrow {{ font-size: 0.75rem; opacity: 0.4; }}
|
| 176 |
</style>
|
| 177 |
</head>
|
| 178 |
<body>
|
|
@@ -189,32 +128,42 @@ async def health_check():
|
|
| 189 |
</div>
|
| 190 |
<div class="stat">
|
| 191 |
<div class="stat-label">uptime</div>
|
| 192 |
-
<div class="stat-value">
|
| 193 |
</div>
|
| 194 |
</div>
|
| 195 |
<div class="links">
|
| 196 |
-
<a class="link" href="https://huggingface.co/spaces/codey-lab/Multi-LLM-API-Gateway
|
| 197 |
-
<
|
| 198 |
-
<span>HuggingFace Space</span>
|
| 199 |
-
<span class="arrow">↗</span>
|
| 200 |
-
</a>
|
| 201 |
-
<a class="link" href="https://github.com/VolkanSah/Multi-LLM-API-Gateway/" target="_blank">
|
| 202 |
-
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0 0 24 12c0-6.63-5.37-12-12-12z"/></svg>
|
| 203 |
-
<span>GitHub Repository</span>
|
| 204 |
-
<span class="arrow">↗</span>
|
| 205 |
</a>
|
| 206 |
-
<a class="link" href="/
|
| 207 |
-
<
|
| 208 |
-
<span>API Docs</span>
|
| 209 |
-
<span class="arrow">↗</span>
|
| 210 |
</a>
|
| 211 |
</div>
|
| 212 |
</div>
|
| 213 |
</body>
|
| 214 |
</html>"""
|
| 215 |
-
return html, 200, {"Content-Type": "text/html"}
|
| 216 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 217 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 218 |
|
| 219 |
# end health check
|
| 220 |
|
|
|
|
| 56 |
logger_models = logging.getLogger('models')
|
| 57 |
logger_db_sync = logging.getLogger('db_sync')
|
| 58 |
# =============================================================================
|
| 59 |
+
# Quart app instance OLD
|
| 60 |
# =============================================================================
|
| 61 |
+
# app = Quart(__name__)
|
| 62 |
+
#START_TIME = datetime.utcnow()
|
| 63 |
# =============================================================================
|
| 64 |
# Quart Routes
|
| 65 |
# =============================================================================
|
|
|
|
| 75 |
# "service": "Universal MCP Hub",
|
| 76 |
# "uptime_seconds": int(uptime.total_seconds()),
|
| 77 |
# })
|
| 78 |
+
# =============================================================================
|
| 79 |
+
# Quart app instance (NEW)
|
| 80 |
+
# =============================================================================
|
| 81 |
+
app = Quart(__name__)
|
| 82 |
+
START_TIME = datetime.utcnow()
|
| 83 |
|
| 84 |
+
# Health check page — plain string, kein f-string, kein Klammer-Chaos
|
| 85 |
+
_HEALTH_HTML = """\
|
| 86 |
+
<!DOCTYPE html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
<html lang="en">
|
| 88 |
<head>
|
| 89 |
<meta charset="UTF-8">
|
|
|
|
| 90 |
<title>Universal MCP Hub</title>
|
| 91 |
<style>
|
| 92 |
+
*{box-sizing:border-box;margin:0;padding:0}
|
| 93 |
+
body{font-family:ui-monospace,monospace;background:#0d1117;color:#c9d1d9;
|
| 94 |
+
min-height:100vh;display:flex;align-items:center;justify-content:center;padding:2rem}
|
| 95 |
+
.card{background:#161b22;border:1px solid #30363d;border-radius:12px;
|
| 96 |
+
padding:2rem 2.5rem;max-width:480px;width:100%}
|
| 97 |
+
.header{display:flex;align-items:center;gap:12px;margin-bottom:1.5rem;
|
| 98 |
+
padding-bottom:1.5rem;border-bottom:1px solid #21262d}
|
| 99 |
+
.dot{width:10px;height:10px;border-radius:50%;background:#3fb950;flex-shrink:0}
|
| 100 |
+
h1{font-size:1.1rem;font-weight:600;color:#f0f6fc}
|
| 101 |
+
.badge{margin-left:auto;font-size:.7rem;background:#1f6feb30;color:#58a6ff;
|
| 102 |
+
border:1px solid #1f6feb;border-radius:20px;padding:2px 10px}
|
| 103 |
+
.stats{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:1.5rem}
|
| 104 |
+
.stat{background:#0d1117;border:1px solid #21262d;border-radius:8px;padding:.75rem 1rem}
|
| 105 |
+
.stat-label{font-size:.7rem;color:#8b949e;margin-bottom:4px}
|
| 106 |
+
.stat-value{font-size:1rem;color:#f0f6fc;font-weight:500}
|
| 107 |
+
.green{color:#3fb950}
|
| 108 |
+
.links{display:flex;flex-direction:column;gap:8px}
|
| 109 |
+
.link{display:flex;align-items:center;gap:10px;padding:.6rem .9rem;
|
| 110 |
+
background:#0d1117;border:1px solid #21262d;border-radius:8px;
|
| 111 |
+
color:#8b949e;text-decoration:none;font-size:.82rem;
|
| 112 |
+
transition:border-color .15s,color .15s}
|
| 113 |
+
.link:hover{border-color:#58a6ff;color:#58a6ff}
|
| 114 |
+
.arrow{font-size:.75rem;opacity:.4}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 115 |
</style>
|
| 116 |
</head>
|
| 117 |
<body>
|
|
|
|
| 128 |
</div>
|
| 129 |
<div class="stat">
|
| 130 |
<div class="stat-label">uptime</div>
|
| 131 |
+
<div class="stat-value">__UPTIME__s</div>
|
| 132 |
</div>
|
| 133 |
</div>
|
| 134 |
<div class="links">
|
| 135 |
+
<a class="link" href="https://huggingface.co/spaces/codey-lab/Multi-LLM-API-Gateway" target="_blank">
|
| 136 |
+
<span>HuggingFace Space</span><span class="arrow">↗</span>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 137 |
</a>
|
| 138 |
+
<a class="link" href="https://github.com/VolkanSah/Multi-LLM-API-Gateway" target="_blank">
|
| 139 |
+
<span>GitHub Repository</span><span class="arrow">↗</span>
|
|
|
|
|
|
|
| 140 |
</a>
|
| 141 |
</div>
|
| 142 |
</div>
|
| 143 |
</body>
|
| 144 |
</html>"""
|
|
|
|
| 145 |
|
| 146 |
+
# =============================================================================
|
| 147 |
+
# Quart Routes
|
| 148 |
+
# =============================================================================
|
| 149 |
+
@app.route("/", methods=["GET"])
|
| 150 |
+
async def health_check():
|
| 151 |
+
"""
|
| 152 |
+
Health check endpoint.
|
| 153 |
+
Used by HuggingFace Spaces and monitoring systems to verify the app is running.
|
| 154 |
+
"""
|
| 155 |
+
uptime = datetime.utcnow() - START_TIME
|
| 156 |
+
uptime_s = int(uptime.total_seconds())
|
| 157 |
|
| 158 |
+
if "text/html" not in request.headers.get("Accept", ""):
|
| 159 |
+
return jsonify({
|
| 160 |
+
"status": "running",
|
| 161 |
+
"service": "Universal MCP Hub",
|
| 162 |
+
"uptime_seconds": uptime_s,
|
| 163 |
+
})
|
| 164 |
+
|
| 165 |
+
html = _HEALTH_HTML.replace("__UPTIME__", str(uptime_s))
|
| 166 |
+
return html, 200, {"Content-Type": "text/html"}
|
| 167 |
|
| 168 |
# end health check
|
| 169 |
|