mirror of
https://github.com/open-webui/open-webui.git
synced 2026-10-06 02:48:04 +00:00
fix: address 4th review - don't clear normalized parent, guard malformed node
- Dual-write sends parent_id only when parentId is known; parent_id=None
would wipe a correct parent link on the normalized row from a stale
embedded snapshot (the inverse of last round's repair gap).
- Treat a non-dict existing node as the synthesis path instead of letting
{**existing} TypeError, consistent with the container guard.
- build_assistant_message_update: structural keys last so callers can't
override id/role.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b7bd853e38
commit
466883ad18
2 changed files with 14 additions and 11 deletions
|
|
@ -584,13 +584,15 @@ class ChatTable:
|
|||
return node
|
||||
|
||||
existing = messages.get(message_id)
|
||||
if existing is not None:
|
||||
if isinstance(existing, dict):
|
||||
# {**existing, **message}: omitted keys keep existing, explicit
|
||||
# values (incl. parentId=None, childrenIds=[]) win.
|
||||
messages[message_id] = enforce_node_invariants({**existing, **message})
|
||||
else:
|
||||
# Node missing: a concurrent whole-chat write likely dropped the
|
||||
# placeholder. Warn only when the payload is itself partial.
|
||||
if existing is not None:
|
||||
log.warning(f'upsert: discarding malformed existing node {message_id}')
|
||||
# Node missing/unusable: a concurrent whole-chat write likely
|
||||
# dropped the placeholder. Warn only when the payload is partial.
|
||||
is_partial = not all(k in message for k in ('id', 'parentId', 'childrenIds', 'role'))
|
||||
if is_partial:
|
||||
log.warning(
|
||||
|
|
@ -623,16 +625,18 @@ class ChatTable:
|
|||
|
||||
chat['history'] = history
|
||||
|
||||
# Dual-write to chat_message table. Alias camelCase parentId to
|
||||
# snake_case so the normalized row's parent link is repaired too
|
||||
# (callee gates its update on 'parent_id').
|
||||
# Send parent_id only when known; parent_id=None would clear a real
|
||||
# link on the normalized row from a possibly-stale snapshot.
|
||||
node = history['messages'][message_id]
|
||||
cm_data = {**node}
|
||||
if node.get('parentId') is not None:
|
||||
cm_data['parent_id'] = node['parentId']
|
||||
try:
|
||||
await ChatMessages.upsert_message(
|
||||
message_id=message_id,
|
||||
chat_id=id,
|
||||
user_id=user_id,
|
||||
data={**node, 'parent_id': node.get('parentId')},
|
||||
data=cm_data,
|
||||
)
|
||||
except Exception as e:
|
||||
log.warning(f'Failed to write to chat_message table: {e}')
|
||||
|
|
|
|||
|
|
@ -3583,13 +3583,12 @@ async def streaming_chat_response_handler(response, ctx):
|
|||
model_id = form_data.get('model', '')
|
||||
|
||||
def build_assistant_message_update(**fields):
|
||||
# Only placeholder-repair fields, and each only when authoritative,
|
||||
# so the upsert merge can't clobber an existing node (chats.py
|
||||
# synthesizes what's missing).
|
||||
# Placeholder-repair fields only, each when authoritative;
|
||||
# structural keys last so callers can't override them.
|
||||
update = {
|
||||
**fields,
|
||||
'id': metadata['message_id'],
|
||||
'role': 'assistant',
|
||||
**fields,
|
||||
}
|
||||
if model_id:
|
||||
update['model'] = model_id
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue