diff --git a/astrbot/core/provider/sources/gemini_source.py b/astrbot/core/provider/sources/gemini_source.py index abf7bb7cf8..992c4e6b9b 100644 --- a/astrbot/core/provider/sources/gemini_source.py +++ b/astrbot/core/provider/sources/gemini_source.py @@ -428,7 +428,7 @@ def append_or_extend( append_or_extend(gemini_contents, parts, types.UserContent) if gemini_contents and isinstance(gemini_contents[0], types.ModelContent): - gemini_contents.pop() + gemini_contents.pop(0) return gemini_contents diff --git a/tests/test_gemini_source.py b/tests/test_gemini_source.py index 9294ea46b2..7b47bcb5e1 100644 --- a/tests/test_gemini_source.py +++ b/tests/test_gemini_source.py @@ -2,13 +2,74 @@ import httpx import pytest +from google.genai import types -from astrbot.core.exceptions import EmptyModelOutputError import astrbot.core.provider.sources.request_retry as request_retry +from astrbot.core.exceptions import EmptyModelOutputError from astrbot.core.provider.entities import LLMResponse from astrbot.core.provider.sources.gemini_source import ProviderGoogleGenAI +def test_gemini_prepare_conversation_removes_leading_model_content(): + provider = ProviderGoogleGenAI.__new__(ProviderGoogleGenAI) + + contents = provider._prepare_conversation( + { + "messages": [ + {"role": "assistant", "content": "stale assistant turn"}, + {"role": "user", "content": "current user turn"}, + ] + } + ) + + assert len(contents) == 1 + assert isinstance(contents[0], types.UserContent) + assert contents[0].parts is not None + assert contents[0].parts[-1].text == "current user turn" + + +def test_gemini_prepare_conversation_keeps_normal_user_first_history(): + provider = ProviderGoogleGenAI.__new__(ProviderGoogleGenAI) + + contents = provider._prepare_conversation( + { + "messages": [ + {"role": "user", "content": "first user turn"}, + {"role": "assistant", "content": "assistant turn"}, + {"role": "user", "content": "current user turn"}, + ] + } + ) + + assert [type(content) for content in contents] == [ + types.UserContent, + types.ModelContent, + types.UserContent, + ] + assert contents[-1].parts is not None + assert contents[-1].parts[-1].text == "current user turn" + + +def test_gemini_prepare_conversation_preserves_user_model_history(): + provider = ProviderGoogleGenAI.__new__(ProviderGoogleGenAI) + + contents = provider._prepare_conversation( + { + "messages": [ + {"role": "user", "content": "user turn"}, + {"role": "assistant", "content": "assistant turn"}, + ] + } + ) + + assert [type(content) for content in contents] == [ + types.UserContent, + types.ModelContent, + ] + assert contents[-1].parts is not None + assert contents[-1].parts[-1].text == "assistant turn" + + def test_gemini_empty_output_raises_empty_model_output_error(): llm_response = LLMResponse(role="assistant")