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.
This commit is contained in:
Alessandro 2026-08-12 06:33:35 +02:00
parent 4e4add524f
commit 517a3cd90b
3 changed files with 17 additions and 0 deletions

View file

@ -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

View file

@ -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`.

14
tests/test_history.py Normal file
View file

@ -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")]