fix(nodes): Fix Swapper models and DAGI Router agents display for NODE2
- Fix get_node_endpoints to correctly determine URLs for NODE2 (localhost instead of Docker service names) - Fix swapper detail endpoint to return fallback data instead of 404 when metrics not found - This allows UI to show pending state instead of error for NODE2 Fixes: - Swapper Service models not showing for NODE2 - DAGI Router agents not showing for NODE2
This commit is contained in:
@@ -59,7 +59,11 @@ from models_city import (
|
||||
CreateAgentRequest,
|
||||
CreateAgentResponse,
|
||||
DeleteAgentResponse,
|
||||
CreateMicrodaoRoomRequest
|
||||
CreateMicrodaoRoomRequest,
|
||||
MicrodaoActivity,
|
||||
CreateMicrodaoActivity,
|
||||
MicrodaoStats,
|
||||
MicrodaoDashboard
|
||||
)
|
||||
import repo_city
|
||||
from common.redis_client import PresenceRedis, get_redis
|
||||
@@ -4384,12 +4388,21 @@ async def get_node_swapper_detail(node_id: str):
|
||||
"""
|
||||
Get detailed Swapper Service status for a node.
|
||||
Used by Node Cabinet to show loaded models and health.
|
||||
Returns fallback data if metrics not found (instead of 404).
|
||||
"""
|
||||
try:
|
||||
# Fetch from node_cache
|
||||
metrics = await repo_city.get_node_metrics(node_id)
|
||||
if not metrics:
|
||||
raise HTTPException(status_code=404, detail="Node not found")
|
||||
# Return fallback instead of 404 - allows UI to show pending state
|
||||
logger.info(f"Swapper metrics not found for {node_id}, returning fallback")
|
||||
return NodeSwapperDetail(
|
||||
node_id=node_id,
|
||||
healthy=False,
|
||||
models_loaded=0,
|
||||
models_total=0,
|
||||
models=[]
|
||||
)
|
||||
|
||||
# Parse swapper state (stored as JSONB)
|
||||
state = metrics.get("swapper_state") or {}
|
||||
@@ -4724,3 +4737,77 @@ async def trigger_node_self_healing(node_id: str):
|
||||
)
|
||||
|
||||
raise HTTPException(status_code=500, detail=f"Self-healing failed: {e}")
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# MicroDAO Dashboard & Activity
|
||||
# =============================================================================
|
||||
|
||||
@router.get("/microdao/{slug}/dashboard", response_model=MicrodaoDashboard)
|
||||
async def api_get_microdao_dashboard(slug: str):
|
||||
"""Отримати повний дашборд для MicroDAO"""
|
||||
try:
|
||||
dashboard = await repo_city.get_microdao_dashboard(slug)
|
||||
return dashboard
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=404, detail=str(e))
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to get microdao dashboard for {slug}: {e}")
|
||||
raise HTTPException(status_code=500, detail="Failed to load dashboard")
|
||||
|
||||
|
||||
@router.get("/microdao/{slug}/activity", response_model=List[MicrodaoActivity])
|
||||
async def api_list_microdao_activity(slug: str, limit: int = Query(20, ge=1, le=100)):
|
||||
"""Отримати список активності MicroDAO"""
|
||||
try:
|
||||
activity = await repo_city.get_microdao_activity(slug, limit=limit)
|
||||
# Конвертувати dict в MicrodaoActivity
|
||||
result = []
|
||||
for act in activity:
|
||||
result.append({
|
||||
"id": str(act["id"]),
|
||||
"microdao_slug": act["microdao_slug"],
|
||||
"kind": act["kind"],
|
||||
"title": act.get("title"),
|
||||
"body": act["body"],
|
||||
"author_agent_id": str(act["author_agent_id"]) if act.get("author_agent_id") else None,
|
||||
"author_name": act.get("author_name"),
|
||||
"created_at": act["created_at"]
|
||||
})
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to get microdao activity for {slug}: {e}")
|
||||
raise HTTPException(status_code=500, detail="Failed to load activity")
|
||||
|
||||
|
||||
@router.post("/microdao/{slug}/activity", response_model=MicrodaoActivity, status_code=201)
|
||||
async def api_create_microdao_activity(
|
||||
slug: str,
|
||||
payload: CreateMicrodaoActivity
|
||||
):
|
||||
"""Створити новий запис активності для MicroDAO"""
|
||||
try:
|
||||
activity = await repo_city.create_microdao_activity(
|
||||
slug=slug,
|
||||
kind=payload.kind,
|
||||
body=payload.body,
|
||||
title=payload.title,
|
||||
author_agent_id=str(payload.author_agent_id) if payload.author_agent_id else None,
|
||||
author_name=payload.author_name
|
||||
)
|
||||
# Конвертувати dict в MicrodaoActivity
|
||||
return {
|
||||
"id": str(activity["id"]),
|
||||
"microdao_slug": activity["microdao_slug"],
|
||||
"kind": activity["kind"],
|
||||
"title": activity.get("title"),
|
||||
"body": activity["body"],
|
||||
"author_agent_id": str(activity["author_agent_id"]) if activity.get("author_agent_id") else None,
|
||||
"author_name": activity.get("author_name"),
|
||||
"created_at": activity["created_at"]
|
||||
}
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=404, detail=str(e))
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to create microdao activity for {slug}: {e}")
|
||||
raise HTTPException(status_code=500, detail="Failed to create activity")
|
||||
|
||||
Reference in New Issue
Block a user