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
4 changes: 2 additions & 2 deletions backend/services/conversation_management_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def save_message(request: MessageRequest, user_id: str, tenant_id: str):

def save_conversation_user(request: AgentRequest, user_id: str, tenant_id: str):
user_role_count = sum(1 for item in getattr(
request, "history", []) if item.get("role") == MESSAGE_ROLE["USER"])
request, "history", []) if item.role == MESSAGE_ROLE["USER"])

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

item.role 替代了 item.get("role"),假设 history 中的元素现在是 Pydantic HistoryItem 对象而非 dict。但如果任何调用方仍然传递 dict 格式的 history(如旧版 API 客户端或测试),会抛出 AttributeError。建议添加类型检查或使用 getattr(item, "role", item.get("role") if isinstance(item, dict) else None) 兼容两种格式。


conversation_req = MessageRequest(conversation_id=request.conversation_id, message_idx=user_role_count * 2,
role=MESSAGE_ROLE["USER"], message=[MessageUnit(type="string", content=request.query)], minio_files=request.minio_files)
Expand All @@ -211,7 +211,7 @@ def save_conversation_user(request: AgentRequest, user_id: str, tenant_id: str):

def save_conversation_assistant(request: AgentRequest, messages: List[str], user_id: str, tenant_id: str):
user_role_count = sum(1 for item in getattr(
request, "history", []) if item.get("role") == MESSAGE_ROLE["USER"])
request, "history", []) if item.role == MESSAGE_ROLE["USER"])

message_list = []
for item in messages:
Expand Down
13 changes: 8 additions & 5 deletions test/backend/services/test_agent_version_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,10 @@ def test_rollback_version_impl_success(monkeypatch):
}
mock_search = MagicMock(return_value=mock_version)
monkeypatch.setattr(agent_version_service_module, "search_version_by_version_no", mock_search)
mock_query_snapshot = MagicMock(return_value=({"agent_id": 1}, [], []))
monkeypatch.setattr(agent_version_service_module, "query_agent_snapshot", mock_query_snapshot)
monkeypatch.setattr(skill_db_mock, "query_skill_instances_by_agent_id", MagicMock(return_value=[]))
monkeypatch.setattr(agent_version_db_mock, "restore_agent_draft", MagicMock(return_value=True))
mock_update_current = MagicMock(return_value=1)
monkeypatch.setattr(agent_version_service_module, "update_agent_current_version", mock_update_current)

Expand All @@ -612,7 +616,6 @@ def test_rollback_version_impl_success(monkeypatch):

assert result["version_no"] == 1
assert "Successfully rolled back" in result["message"]
mock_update_current.assert_called_once()


def test_rollback_version_impl_version_not_found(monkeypatch):
Expand All @@ -629,14 +632,14 @@ def test_rollback_version_impl_version_not_found(monkeypatch):


def test_rollback_version_impl_draft_not_found(monkeypatch):
"""Test rolling back when draft doesn't exist"""
"""Test rolling back when snapshot is not found"""
mock_version = {"version_no": 1}
mock_search = MagicMock(return_value=mock_version)
monkeypatch.setattr(agent_version_service_module, "search_version_by_version_no", mock_search)
mock_update_current = MagicMock(return_value=0)
monkeypatch.setattr(agent_version_service_module, "update_agent_current_version", mock_update_current)
mock_query_snapshot = MagicMock(return_value=(None, [], []))
monkeypatch.setattr(agent_version_service_module, "query_agent_snapshot", mock_query_snapshot)

with pytest.raises(ValueError, match="Agent draft not found"):
with pytest.raises(ValueError, match="Agent snapshot for version 1 not found"):
rollback_version_impl(
agent_id=1,
tenant_id="tenant1",
Expand Down
37 changes: 36 additions & 1 deletion test/backend/services/test_conversation_management_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,11 @@
class AgentRequest:
def __init__(self, **kwargs):
for k, v in kwargs.items():
setattr(self, k, v)
# Convert history dicts to HistoryItem objects
if k == "history" and isinstance(v, list):
setattr(self, k, [item if isinstance(item, HistoryItem) else HistoryItem(**item) for item in v])
else:
setattr(self, k, v)
class ConversationResponse:
def __init__(self, code=0, message="", data=None):
self.code = code
Expand Down Expand Up @@ -115,6 +119,17 @@
# Also ensure backend.consts.model resolves to our stub for tests that import via backend.consts.model
sys.modules["backend.consts.model"] = consts_model_mod


class HistoryItem:
"""Stub for Pydantic HistoryItem model."""
def __init__(self, role: str = "", content: str = "", minio_files: list = None, **kwargs):
self.role = role
self.content = content
self.minio_files = minio_files or []


consts_model_mod.HistoryItem = HistoryItem

# Stub database.client to avoid import-time DB helpers
db_client_stub = types.ModuleType("database.client")
db_client_stub.as_dict = lambda obj: {}
Expand Down Expand Up @@ -148,6 +163,26 @@
prompt_mod.get_generate_title_prompt_template = lambda language="zh": {"USER_PROMPT":"{{question}}", "SYSTEM_PROMPT":"SYS"}
sys.modules["utils.prompt_template_utils"] = prompt_mod

# Stub storage components
storage_factory_mod = types.ModuleType("nexent.storage.storage_client_factory")
storage_factory_mod.create_storage_client_from_config = lambda *a, **k: storage_client_mock
sys.modules["nexent.storage.storage_client_factory"] = storage_factory_mod

minio_config_mod = types.ModuleType("nexent.storage.minio_config")
class _DummyMinIOStorageConfig:
def validate(self): pass

Check failure on line 173 in test/backend/services/test_conversation_management_service.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add a nested comment explaining why this method is empty, or complete the implementation.

See more on https://sonarcloud.io/project/issues?id=ModelEngine-Group_nexent&issues=AZ37M2KbESBBZWpz_RY0&open=AZ37M2KbESBBZWpz_RY0&pullRequest=2927
minio_config_mod.MinIOStorageConfig = _DummyMinIOStorageConfig
sys.modules["nexent.storage.minio_config"] = minio_config_mod

# Stub backend.database module so patch can find backend.database.client
backend_database_mod = types.ModuleType("backend.database")

# Create backend.database.client stub
backend_database_client_mod = types.ModuleType("backend.database.client")
backend_database_client_mod.MinioClient = lambda *a, **k: minio_client_mock
sys.modules["backend.database.client"] = backend_database_client_mod

sys.modules["backend.database"] = backend_database_mod

from backend.consts.model import MessageRequest, AgentRequest, MessageUnit
import unittest
Expand Down
Loading