From d52b4da7f0d2784246f6cc77c90bdad9a95ce09a Mon Sep 17 00:00:00 2001 From: panyehong <2655992392@qq.com> Date: Wed, 6 May 2026 10:48:13 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=90=9B=20Bugfix:=20Fixed=20the=20issu?= =?UTF-8?q?e=20of=20conversation=20history=20not=20being=20saved=20correct?= =?UTF-8?q?ly.=20[Specification=20Detail]=201.=20For=20Pydantic=20data=20t?= =?UTF-8?q?ypes,=20directly=20use=20item.role=20to=20retrieve=20them.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../conversation_management_service.py | 4 +- .../test_conversation_management_service.py | 37 ++++++++++++++++++- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/backend/services/conversation_management_service.py b/backend/services/conversation_management_service.py index 1a66901f8..d5d4a85a4 100644 --- a/backend/services/conversation_management_service.py +++ b/backend/services/conversation_management_service.py @@ -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"]) 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) @@ -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: diff --git a/test/backend/services/test_conversation_management_service.py b/test/backend/services/test_conversation_management_service.py index 1b720f7c1..5bedbc6d8 100644 --- a/test/backend/services/test_conversation_management_service.py +++ b/test/backend/services/test_conversation_management_service.py @@ -81,7 +81,11 @@ def render(self, ctx): 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 @@ -115,6 +119,17 @@ def model_dump(self): # 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: {} @@ -148,6 +163,26 @@ def __exit__(self, exc_type, exc, tb): 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 +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 From 8ff3350eac8fd362295977bf34f15104d3c9e8de Mon Sep 17 00:00:00 2001 From: panyehong <2655992392@qq.com> Date: Wed, 6 May 2026 11:13:41 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=90=9B=20Bugfix:=20Fixed=20the=20issu?= =?UTF-8?q?e=20of=20conversation=20history=20not=20being=20saved=20correct?= =?UTF-8?q?ly.=20[Specification=20Detail]=201.=20Fix=20test=20cases.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/backend/services/test_agent_version_service.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/test/backend/services/test_agent_version_service.py b/test/backend/services/test_agent_version_service.py index 167997853..27177e812 100644 --- a/test/backend/services/test_agent_version_service.py +++ b/test/backend/services/test_agent_version_service.py @@ -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) @@ -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): @@ -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",