diff --git a/astrbot/core/provider/sources/anthropic_source.py b/astrbot/core/provider/sources/anthropic_source.py index 27cc459622..f4e425e3eb 100644 --- a/astrbot/core/provider/sources/anthropic_source.py +++ b/astrbot/core/provider/sources/anthropic_source.py @@ -540,11 +540,11 @@ async def _query( ) llm_response = LLMResponse(role="assistant") + completion_text_parts: list[str] = [] for content_block in completion.content: if content_block.type == "text": - completion_text = str(content_block.text).strip() - llm_response.completion_text = completion_text + completion_text_parts.append(str(content_block.text)) if content_block.type == "thinking": reasoning_content = str(content_block.thinking).strip() @@ -556,6 +556,7 @@ async def _query( llm_response.tools_call_name.append(content_block.name) llm_response.tools_call_ids.append(content_block.id) + llm_response.completion_text = "".join(completion_text_parts).strip() llm_response.id = completion.id llm_response.usage = self._extract_usage(completion.usage) diff --git a/tests/test_anthropic_kimi_code_provider.py b/tests/test_anthropic_kimi_code_provider.py index 0dc33f58ba..42e8855249 100644 --- a/tests/test_anthropic_kimi_code_provider.py +++ b/tests/test_anthropic_kimi_code_provider.py @@ -736,6 +736,40 @@ async def fake_create(**kwargs): assert llm_response.usage.output == 0 +@pytest.mark.asyncio +async def test_query_accumulates_multiple_text_blocks(monkeypatch): + """A Message with more than one text content block (e.g. Citations API + output) must concatenate every block, not keep only the last one.""" + provider = _setup_provider_with_mock_client(monkeypatch) + + class _FakeMessageBlock: + def __init__(self, text: str): + self.type = "text" + self.text = text + + class _FakeMessage: + def __init__(self): + self.id = "msg_multi_block" + self.content = [ + _FakeMessageBlock("First block: the important part."), + _FakeMessageBlock("Second block: a trailing citation note."), + ] + self.stop_reason = "end_turn" + self.usage = None + + async def fake_create(**kwargs): + return _FakeMessage() + + monkeypatch.setattr(anthropic_source, "Message", _FakeMessage) + provider.client.messages.create = fake_create + + llm_response = await provider.text_chat(prompt="test") + + assert llm_response.completion_text == ( + "First block: the important part.Second block: a trailing citation note." + ) + + @pytest.mark.asyncio async def test_tool_choice_auto_converts_to_dict(monkeypatch): """tool_choice='auto' 应转换为 {'type': 'auto'}"""