From 517a3cd90bb968314b1d0da336c286bf608e9b02 Mon Sep 17 00:00:00 2001 From: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Wed, 12 Aug 2026 06:33:35 +0200 Subject: [PATCH] Fix assistant-first provider history Omit orphaned leading assistant messages from model history so Claude-compatible providers receive a user-first conversation. Add regression coverage for the initial UI greeting path. --- helpers/history.py | 2 ++ helpers/history.py.dox.md | 1 + tests/test_history.py | 14 ++++++++++++++ 3 files changed, 17 insertions(+) create mode 100644 tests/test_history.py diff --git a/helpers/history.py b/helpers/history.py index f0ee4c0df..a52263812 100644 --- a/helpers/history.py +++ b/helpers/history.py @@ -724,6 +724,8 @@ def output_langchain(messages: list[OutputMessage]): result.append(HumanMessage(content)) # type: ignore # ensure message type alternation result = group_messages_abab(result) + while result and isinstance(result[0], AIMessage): + result.pop(0) return result diff --git a/helpers/history.py.dox.md b/helpers/history.py.dox.md index 7f00f5075..59593e253 100644 --- a/helpers/history.py.dox.md +++ b/helpers/history.py.dox.md @@ -80,6 +80,7 @@ - Update this file whenever public functions, classes, persistence behavior, path/security assumptions, side effects, or cross-module contracts change. - `clear_responses_provider_state(agent)` removes the active provider continuation IDs after local history rewrites while preserving stored response ID lists for later cleanup. - `Message.from_dict()` normalizes legacy AI Responses metadata through `LLMResult.metadata()` so loaded chats shed transient payloads while unrelated metadata and non-AI tool-result inputs remain intact. +- `output_langchain()` removes leading assistant messages after grouping so provider histories always begin with a user turn; the WebUI greeting remains persisted and displayed but is not sent as an orphaned assistant message. - Observed side-effect areas: filesystem writes, filesystem deletion, model calls, plugin state, settings/state persistence, secret handling. - Imported dependency areas include: `abc`, `asyncio`, `collections`, `collections.abc`, `enum`, `helpers`, `json`, `langchain_core.messages`, `math`, `plugins._model_config.helpers.model_config`, `typing`, `uuid`. diff --git a/tests/test_history.py b/tests/test_history.py new file mode 100644 index 000000000..6357f6315 --- /dev/null +++ b/tests/test_history.py @@ -0,0 +1,14 @@ +from helpers.history import output_langchain +from langchain_core.messages import AIMessage, HumanMessage + + +def test_output_langchain_omits_leading_assistant_messages(): + messages = output_langchain( + [ + {"ai": True, "content": "Welcome"}, + {"ai": False, "content": "Hello"}, + {"ai": True, "content": "Hi"}, + ] + ) + + assert messages == [HumanMessage("Hello"), AIMessage("Hi")]