fix: surface attached chat references in <attached_files> (#28788)

A chat attached via the "+" menu or dropped from the sidebar references an
existing chat by id and carries no url. add_file_context() filtered on
`file.get('url')`, so the reference was dropped from <attached_files>
entirely and the model was never told it existed.

When the RAG file-context path is enabled the chat content still reaches
the model as <source> context, which masked this. With file_context
disabled that path is skipped, and get_attached_knowledge() only promotes
collection/note items into <attached_knowledge> - so an attached chat was
visible in the UI but invisible to the model, which then reported having
no chat attachments despite having a view_chat tool available.

Keep chat references and emit their id so the model can resolve them with
view_chat. The url attribute is now conditional, since a chat has none;
the id guard it replaces was dead once the filter guarantees a url or a
chat id.

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Classic298 2026-08-19 20:15:22 +02:00 committed by GitHub
parent ebd4d9c6cc
commit 2e7df54673
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1613,11 +1613,10 @@ async def add_file_context(messages: list, chat_id: str, user) -> list:
stored_messages = get_message_list(history.get('messages', {}), history.get('currentId'))
def format_file_tag(file):
file_id = file.get('id') or file.get('url')
attrs = f'type="{file.get("type", "file")}"'
if file_id:
attrs += f' id="{file_id}"'
attrs += f' url="{file["url"]}"'
# Every file reaching here has a url or a chat id, so id is always set.
attrs = f'type="{file.get("type", "file")}" id="{file.get("id") or file.get("url")}"'
if file.get('url'):
attrs += f' url="{file["url"]}"'
if file.get('content_type'):
attrs += f' content_type="{file["content_type"]}"'
if file.get('name'):
@ -1634,15 +1633,17 @@ async def add_file_context(messages: list, chat_id: str, user) -> list:
stored_user_messages = [m for m in stored_messages if m.get('role') == 'user']
for message, stored_message in zip(user_messages, stored_user_messages):
files_with_urls = [
# Chat references carry no url - they are addressed by id via view_chat.
attached_files = [
file
for file in stored_message.get('files', [])
if file.get('url') and not file.get('url').startswith('data:')
if (file.get('url') and not file.get('url').startswith('data:'))
or (file.get('type') == 'chat' and file.get('id'))
]
if not files_with_urls:
if not attached_files:
continue
file_tags = [format_file_tag(file) for file in files_with_urls]
file_tags = [format_file_tag(file) for file in attached_files]
file_context = '<attached_files>\n' + '\n'.join(file_tags) + '\n</attached_files>\n\n'
content = message.get('content', '')