diff --git a/nextcloud_mcp_server/app.py b/nextcloud_mcp_server/app.py index c8909f7..ecf6504 100644 --- a/nextcloud_mcp_server/app.py +++ b/nextcloud_mcp_server/app.py @@ -1410,6 +1410,7 @@ def get_app(transport: str = "sse", enabled_apps: list[str] | None = None): from nextcloud_mcp_server.auth.userinfo_routes import ( revoke_session, user_info_html, + vector_sync_status_fragment, ) from nextcloud_mcp_server.auth.webhook_routes import ( disable_webhook_preset, @@ -1424,6 +1425,12 @@ def get_app(transport: str = "sse", enabled_apps: list[str] | None = None): Route( "/revoke", revoke_session, methods=["POST"], name="revoke_session_endpoint" ), # /app/revoke → revoke_session + # Vector sync status fragment (htmx polling) + Route( + "/vector-sync/status", + vector_sync_status_fragment, + methods=["GET"], + ), # /app/vector-sync/status # Webhook management routes (admin-only) Route("/webhooks", webhook_management_pane, methods=["GET"]), # /app/webhooks Route( diff --git a/nextcloud_mcp_server/auth/userinfo_routes.py b/nextcloud_mcp_server/auth/userinfo_routes.py index 0aff68e..8d19fa1 100644 --- a/nextcloud_mcp_server/auth/userinfo_routes.py +++ b/nextcloud_mcp_server/auth/userinfo_routes.py @@ -139,6 +139,72 @@ async def _get_processing_status(request: Request) -> dict[str, Any] | None: return None +@requires("authenticated", redirect="oauth_login") +async def vector_sync_status_fragment(request: Request) -> HTMLResponse: + """Vector sync status fragment endpoint - returns HTML fragment with current status. + + This endpoint is polled by htmx to provide real-time updates of vector sync processing + status without requiring a full page refresh. + + Requires authentication via session cookie (redirects to oauth_login route if not authenticated). + + Args: + request: Starlette request object + + Returns: + HTML response with vector sync status table fragment + """ + processing_status = await _get_processing_status(request) + + # If vector sync is disabled or unavailable, return empty fragment + if not processing_status: + return HTMLResponse( + """ +
Vector sync not available
+| Indexed Documents | +{indexed_count_str} | +
| Pending Documents | +{pending_count_str} | +
| Status | +{status_badge} | +
| Indexed Documents | -{indexed_count_str} | -
| Pending Documents | -{pending_count_str} | -
| Status | -{status_badge} | -
Loading vector sync status...
+