From 008c03c2bbe2cefa9cc6fb35ed0a736d67b2d422 Mon Sep 17 00:00:00 2001 From: CREDO23 Date: Thu, 13 Aug 2026 15:54:15 +0200 Subject: [PATCH] fix(knowledge-store): read the commit subject out of content blocks A reasoning model replies with a list of blocks rather than a string, so stringifying it wrote the model's entire thinking into the revision's commit message. Reuse the existing extractor, which keeps text and drops reasoning. --- .../commit_message.py | 8 +++++--- .../unit/middleware/test_commit_message.py | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/surfsense_backend/app/agents/chat/multi_agent_chat/main_agent/middleware/knowledge_store_persistence/commit_message.py b/surfsense_backend/app/agents/chat/multi_agent_chat/main_agent/middleware/knowledge_store_persistence/commit_message.py index 4dd442b42..ed6897f39 100644 --- a/surfsense_backend/app/agents/chat/multi_agent_chat/main_agent/middleware/knowledge_store_persistence/commit_message.py +++ b/surfsense_backend/app/agents/chat/multi_agent_chat/main_agent/middleware/knowledge_store_persistence/commit_message.py @@ -7,6 +7,8 @@ import logging from collections.abc import Iterable, Mapping from typing import Any +from app.tasks.chat.llm_history_normalizer import assistant_content_to_llm_text + logger = logging.getLogger(__name__) _SYSTEM_PROMPT = ( @@ -71,9 +73,9 @@ async def generate_commit_message( ), timeout=_GENERATION_TIMEOUT_SECONDS, ) - content = getattr(reply, "content", "") - if not isinstance(content, str): - content = str(content) + # A reasoning model answers in content blocks, so the subject has to be + # read out of them: ``str()`` on the list commits the model's thinking. + content = assistant_content_to_llm_text(getattr(reply, "content", "")) subject = content.strip().splitlines()[0].strip() if content.strip() else "" if subject: return subject diff --git a/surfsense_backend/tests/unit/middleware/test_commit_message.py b/surfsense_backend/tests/unit/middleware/test_commit_message.py index 6f133fabe..4745dcd4d 100644 --- a/surfsense_backend/tests/unit/middleware/test_commit_message.py +++ b/surfsense_backend/tests/unit/middleware/test_commit_message.py @@ -50,6 +50,25 @@ async def test_uses_the_models_reply_as_subject(): assert message == "docs: add meeting notes" +async def test_a_reasoning_models_thinking_never_reaches_the_subject(): + """Reasoning models answer in blocks; the shape below is a real reply.""" + + class _ReasoningModel: + async def ainvoke(self, _input, config=None, **kwargs): + return SimpleNamespace( + content=[ + {"type": "thinking", "thinking": "**Inferring commit message**"}, + {"type": "thinking", "thinking": " the user wants a leaf image"}, + "docs: add simple green leaf image prompt", + ] + ) + + message = await generate_commit_message( + _ReasoningModel(), writes={"documents/leaf.md": b"# Leaf"}, removes=[] + ) + assert message == "docs: add simple green leaf image prompt" + + async def test_falls_back_deterministically_when_the_model_fails(): message = await generate_commit_message( _BrokenModel(),