Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 38 additions & 36 deletions backend/routes/config_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,42 +74,44 @@ async def get_config(
# Get RAG data sources for the user (feature-gated MCP-backed discovery)
rag_data_sources = []
rag_servers = []
try:
if app_settings.feature_rag_mcp_enabled:
rag_mcp = app_factory.get_rag_mcp_service()
rag_data_sources = await rag_mcp.discover_data_sources(
current_user, user_compliance_level=compliance_level
)
rag_servers = await rag_mcp.discover_servers(
current_user, user_compliance_level=compliance_level
)
else:
rag_client = app_factory.get_rag_client()
# rag_client.discover_data_sources now returns List[DataSource] objects
data_source_objects = await rag_client.discover_data_sources(current_user)
# Convert to list of names (strings) for the 'data_sources' field (backward compatibility)
rag_data_sources = [ds.name for ds in data_source_objects]
# Populate rag_servers with the mock data in the expected format for the UI
rag_servers = [
{
"server": "rag_mock",
"displayName": "RAG Mock Data",
"icon": "database",
"complianceLevel": "Public", # Default compliance for the mock server itself
"sources": [
{
"id": ds.name,
"name": ds.name,
"authRequired": True,
"selected": False,
"complianceLevel": ds.compliance_level,
}
for ds in data_source_objects
],
}
]
except Exception as e:
logger.warning(f"Error resolving RAG data sources: {e}")
# Only attempt RAG discovery if RAG feature is enabled
if app_settings.feature_rag_enabled:
try:
if app_settings.feature_rag_mcp_enabled:
rag_mcp = app_factory.get_rag_mcp_service()
rag_data_sources = await rag_mcp.discover_data_sources(
current_user, user_compliance_level=compliance_level
)
rag_servers = await rag_mcp.discover_servers(
current_user, user_compliance_level=compliance_level
)
else:
rag_client = app_factory.get_rag_client()
# rag_client.discover_data_sources now returns List[DataSource] objects
data_source_objects = await rag_client.discover_data_sources(current_user)
# Convert to list of names (strings) for the 'data_sources' field (backward compatibility)
rag_data_sources = [ds.name for ds in data_source_objects]
# Populate rag_servers with the mock data in the expected format for the UI
rag_servers = [
{
"server": "rag_mock",
"displayName": "RAG Mock Data",
"icon": "database",
"complianceLevel": "Public", # Default compliance for the mock server itself
"sources": [
{
"id": ds.name,
"name": ds.name,
"authRequired": True,
"selected": False,
"complianceLevel": ds.compliance_level,
}
for ds in data_source_objects
],
}
]
except Exception as e:
logger.warning(f"Error resolving RAG data sources: {e}")

# Check if tools are enabled
tools_info = []
Expand Down
43 changes: 43 additions & 0 deletions backend/tests/test_routes_config_smoke.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from unittest.mock import patch, MagicMock, AsyncMock

from starlette.testclient import TestClient

from infrastructure.app_factory import app_factory
from main import app


Expand All @@ -14,3 +17,43 @@ def test_config_endpoint_smoke(monkeypatch):
assert "tools" in data
assert "prompts" in data
assert "data_sources" in data


def test_rag_discovery_skipped_when_feature_disabled(monkeypatch):
Copy link

Copilot AI Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The monkeypatch parameter is declared but never used in the test function. Remove it or use it to set environment variables instead of directly mutating the config_manager settings. Other tests in the codebase use monkeypatch.setenv() to modify configuration (see test_core_auth.py line 11).

Copilot uses AI. Check for mistakes.
"""Verify RAG discovery is not attempted when feature_rag_enabled is False."""
# Create mock rag_client to track if discover_data_sources is called
mock_rag_client = MagicMock()
mock_rag_client.discover_data_sources = AsyncMock(return_value=[])

# Create mock rag_mcp_service
mock_rag_mcp = MagicMock()
mock_rag_mcp.discover_data_sources = AsyncMock(return_value=[])
mock_rag_mcp.discover_servers = AsyncMock(return_value=[])

# Patch the app_factory methods
with patch.object(app_factory, 'get_rag_client', return_value=mock_rag_client):
with patch.object(app_factory, 'get_rag_mcp_service', return_value=mock_rag_mcp):
# Ensure RAG feature is disabled
config_manager = app_factory.get_config_manager()
original_setting = config_manager.app_settings.feature_rag_enabled
config_manager.app_settings.feature_rag_enabled = False

try:
client = TestClient(app)
resp = client.get("/api/config", headers={"X-User-Email": "test@test.com"})
assert resp.status_code == 200

# Verify RAG discovery was NOT called when feature is disabled
mock_rag_client.discover_data_sources.assert_not_called()
mock_rag_mcp.discover_data_sources.assert_not_called()
mock_rag_mcp.discover_servers.assert_not_called()

# Verify response still has data_sources field (just empty)
data = resp.json()
assert "data_sources" in data
assert data["data_sources"] == []
assert "rag_servers" in data
assert data["rag_servers"] == []
finally:
# Restore original setting
config_manager.app_settings.feature_rag_enabled = original_setting
Loading