From 1c5bce92cb8497a67abbfc02e9f805277ad1ee24 Mon Sep 17 00:00:00 2001 From: bergeouss Date: Sun, 3 May 2026 18:28:24 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20add=20gateway=20status=20card=20to=20Se?= =?UTF-8?q?ttings=20=E2=86=92=20System=20(#1457)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/routes.py | 37 +++++++++++++++++++++++++++++++++++++ static/index.html | 6 ++++++ static/panels.js | 24 +++++++++++++++++++++++- 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/api/routes.py b/api/routes.py index 8f6a88ed..8c4f177b 100644 --- a/api/routes.py +++ b/api/routes.py @@ -2181,6 +2181,43 @@ def handle_get(handler, parsed) -> bool: {"name": get_active_profile_name(), "path": str(get_active_hermes_home())}, ) + # ── Gateway Status (GET) ── + if parsed.path == "/api/gateway/status": + import datetime + identity_map = _load_gateway_session_identity_map() + sessions_path = _gateway_session_metadata_path() + running = bool(identity_map) + platforms_set: set[str] = set() + for meta in identity_map.values(): + raw = meta.get("raw_source") or meta.get("platform") or "" + norm = _normalize_messaging_source(raw) + if norm: + platforms_set.add(norm) + _PLATFORM_LABELS = { + "telegram": "Telegram", + "discord": "Discord", + "slack": "Slack", + "web": "Web", + "api": "API", + } + platforms = sorted( + [{"name": p, "label": _PLATFORM_LABELS.get(p, p.title())} for p in platforms_set], + key=lambda x: x["label"], + ) + last_active = "" + if running and sessions_path.exists(): + try: + mtime = sessions_path.stat().st_mtime + last_active = datetime.datetime.fromtimestamp(mtime).isoformat() + except Exception: + pass + return j(handler, { + "running": running, + "platforms": platforms, + "last_active": last_active, + "session_count": len(identity_map), + }) + # ── MCP Servers (GET) ── if parsed.path == "/api/mcp/servers": return _handle_mcp_servers_list(handler) diff --git a/static/index.html b/static/index.html index 287f5ba1..a875d87c 100644 --- a/static/index.html +++ b/static/index.html @@ -931,6 +931,12 @@ + +
+ +
Status of the Hermes gateway (Telegram, Discord, Slack, etc.)
+
Loading…
+
diff --git a/static/panels.js b/static/panels.js index f633a7f4..eaf4ab2e 100644 --- a/static/panels.js +++ b/static/panels.js @@ -3840,11 +3840,33 @@ async function deleteMcpServer(name){ else{showToast((r&&r.error)||t('mcp_delete_failed'));} }).catch(()=>{showToast(t('mcp_delete_failed'));}); } +function loadGatewayStatus(){ + const card=$('gatewayStatusCard'); + if(!card) return; + api('/api/gateway/status').then(r=>{ + if(!r) return; + if(!r.running){ + card.innerHTML=`
Gateway not running
`; + return; + } + const platformIcons={telegram:'💬',discord:'🎮',slack:'📝',web:'🌐',api:'🔌'}; + let badges=''; + if(r.platforms&&r.platforms.length){ + badges=r.platforms.map(p=>{ + const icon=platformIcons[p.name]||'📡'; + return `${icon} ${esc(p.label)}`; + }).join(' '); + } + const lastActive=r.last_active?`Last active: ${esc(new Date(r.last_active).toLocaleString())}`:''; + const sessionInfo=r.session_count?`${r.session_count} session${r.session_count!==1?'s':''}`:''; + card.innerHTML=`
Running
${badges?`
${badges}
`:''}
${sessionInfo}${lastActive}
`; + }).catch(()=>{card.innerHTML=`
Failed to load gateway status
`}); +} // Load MCP servers when system settings tab opens const _origSwitchSettings=switchSettingsSection; switchSettingsSection=function(name){ _origSwitchSettings(name); - if(name==='system') loadMcpServers(); + if(name==='system'){loadMcpServers();loadGatewayStatus();} }; // ── Checkpoints / Rollback ──────────────────────────────────────────────────