mirror of
https://github.com/open-webui/open-webui.git
synced 2026-10-02 02:12:25 +00:00
refac: share one guarded helper for chat branch descent (#30070)
The branch navigation handlers each carried their own copy of the loop that walks a message's childrenIds down to the deepest child, eleven copies in total across the single-response view, the multi-response view and Chat.svelte. They now call one getDeepestChildId helper in the frontend utils, which tracks the ids it has already visited and stops when one repeats, the same way the message list build already does. The helper also absorbs the "start from the last root message" fallback that two of the call sites repeated inline, so every site is now a single call.
This commit is contained in:
parent
d9c8de9c39
commit
befdd86eb1
4 changed files with 41 additions and 98 deletions
|
|
@ -57,6 +57,7 @@
|
|||
copyToClipboard,
|
||||
getMessageContentParts,
|
||||
createMessagesList,
|
||||
getDeepestChildId,
|
||||
sanitizeHistory,
|
||||
getPromptVariables,
|
||||
processDetails,
|
||||
|
|
@ -1119,21 +1120,7 @@
|
|||
const _chatId = JSON.parse(JSON.stringify($chatId));
|
||||
let _messageId = JSON.parse(JSON.stringify(message.id));
|
||||
|
||||
let messageChildrenIds = [];
|
||||
if (_messageId === null) {
|
||||
messageChildrenIds = Object.keys(history.messages).filter(
|
||||
(id) => history.messages[id].parentId === null
|
||||
);
|
||||
} else {
|
||||
messageChildrenIds = history.messages[_messageId].childrenIds;
|
||||
}
|
||||
|
||||
while (messageChildrenIds.length !== 0) {
|
||||
_messageId = messageChildrenIds.at(-1);
|
||||
messageChildrenIds = history.messages[_messageId].childrenIds;
|
||||
}
|
||||
|
||||
history.currentId = _messageId;
|
||||
history.currentId = getDeepestChildId(history, _messageId);
|
||||
|
||||
await tick();
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import { toast } from 'svelte-sonner';
|
||||
import { deleteChatMessageById, updateChatById } from '$lib/apis/chats';
|
||||
import { copyToClipboard, extractCurlyBraceWords } from '$lib/utils';
|
||||
import { copyToClipboard, extractCurlyBraceWords, getDeepestChildId } from '$lib/utils';
|
||||
|
||||
import Message from './Messages/Message.svelte';
|
||||
import Loader from '../common/Loader.svelte';
|
||||
|
|
@ -214,14 +214,7 @@
|
|||
|
||||
// If we're navigating to a different message
|
||||
if (message.id !== messageId) {
|
||||
// Drill down to the deepest child of that branch
|
||||
let messageChildrenIds = history.messages[messageId].childrenIds;
|
||||
while (messageChildrenIds.length !== 0) {
|
||||
messageId = messageChildrenIds.at(-1);
|
||||
messageChildrenIds = history.messages[messageId].childrenIds;
|
||||
}
|
||||
|
||||
history.currentId = messageId;
|
||||
history.currentId = getDeepestChildId(history, messageId);
|
||||
}
|
||||
|
||||
await tick();
|
||||
|
|
@ -247,14 +240,7 @@
|
|||
];
|
||||
|
||||
if (message.id !== messageId) {
|
||||
let messageChildrenIds = history.messages[messageId].childrenIds;
|
||||
|
||||
while (messageChildrenIds.length !== 0) {
|
||||
messageId = messageChildrenIds.at(-1);
|
||||
messageChildrenIds = history.messages[messageId].childrenIds;
|
||||
}
|
||||
|
||||
history.currentId = messageId;
|
||||
history.currentId = getDeepestChildId(history, messageId);
|
||||
}
|
||||
} else {
|
||||
let childrenIds = Object.values(history.messages)
|
||||
|
|
@ -263,14 +249,7 @@
|
|||
let messageId = childrenIds[Math.max(childrenIds.indexOf(message.id) - 1, 0)];
|
||||
|
||||
if (message.id !== messageId) {
|
||||
let messageChildrenIds = history.messages[messageId].childrenIds;
|
||||
|
||||
while (messageChildrenIds.length !== 0) {
|
||||
messageId = messageChildrenIds.at(-1);
|
||||
messageChildrenIds = history.messages[messageId].childrenIds;
|
||||
}
|
||||
|
||||
history.currentId = messageId;
|
||||
history.currentId = getDeepestChildId(history, messageId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -299,14 +278,7 @@
|
|||
];
|
||||
|
||||
if (message.id !== messageId) {
|
||||
let messageChildrenIds = history.messages[messageId].childrenIds;
|
||||
|
||||
while (messageChildrenIds.length !== 0) {
|
||||
messageId = messageChildrenIds.at(-1);
|
||||
messageChildrenIds = history.messages[messageId].childrenIds;
|
||||
}
|
||||
|
||||
history.currentId = messageId;
|
||||
history.currentId = getDeepestChildId(history, messageId);
|
||||
}
|
||||
} else {
|
||||
let childrenIds = Object.values(history.messages)
|
||||
|
|
@ -316,14 +288,7 @@
|
|||
childrenIds[Math.min(childrenIds.indexOf(message.id) + 1, childrenIds.length - 1)];
|
||||
|
||||
if (message.id !== messageId) {
|
||||
let messageChildrenIds = history.messages[messageId].childrenIds;
|
||||
|
||||
while (messageChildrenIds.length !== 0) {
|
||||
messageId = messageChildrenIds.at(-1);
|
||||
messageChildrenIds = history.messages[messageId].childrenIds;
|
||||
}
|
||||
|
||||
history.currentId = messageId;
|
||||
history.currentId = getDeepestChildId(history, messageId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -480,16 +445,7 @@
|
|||
delete history.messages[id];
|
||||
});
|
||||
|
||||
let nextMessageId = parentMessageId;
|
||||
let nextChildrenIds =
|
||||
nextMessageId === null
|
||||
? Object.keys(history.messages).filter((id) => history.messages[id].parentId === null)
|
||||
: (history.messages[nextMessageId]?.childrenIds ?? []);
|
||||
while (nextChildrenIds.length > 0) {
|
||||
nextMessageId = nextChildrenIds.at(-1);
|
||||
nextChildrenIds = history.messages[nextMessageId]?.childrenIds ?? [];
|
||||
}
|
||||
history.currentId = nextMessageId;
|
||||
history.currentId = getDeepestChildId(history, parentMessageId);
|
||||
history = history;
|
||||
|
||||
if (!$temporaryChatEnabled) {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,11 @@
|
|||
import ProfileImage from './ProfileImage.svelte';
|
||||
import { WEBUI_BASE_URL } from '$lib/constants';
|
||||
import equal from 'fast-deep-equal';
|
||||
import { formatMessageTimestamp, formatMessageTimestampFull } from '$lib/utils';
|
||||
import {
|
||||
formatMessageTimestamp,
|
||||
formatMessageTimestampFull,
|
||||
getDeepestChildId
|
||||
} from '$lib/utils';
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
export let chatId;
|
||||
|
|
@ -88,15 +92,8 @@
|
|||
let messageId = groupedMessageIds[modelIdx].messageIds[groupedMessageIdsIdx[modelIdx]];
|
||||
console.log(messageId);
|
||||
|
||||
// Traverse the branch to find the deepest child message
|
||||
let messageChildrenIds = history.messages[messageId].childrenIds;
|
||||
while (messageChildrenIds.length !== 0) {
|
||||
messageId = messageChildrenIds.at(-1);
|
||||
messageChildrenIds = history.messages[messageId].childrenIds;
|
||||
}
|
||||
|
||||
// Update the current message ID in history
|
||||
history.currentId = messageId;
|
||||
history.currentId = getDeepestChildId(history, messageId);
|
||||
|
||||
// Await UI updates
|
||||
await tick();
|
||||
|
|
@ -112,14 +109,7 @@
|
|||
let messageId = groupedMessageIds[modelIdx].messageIds[groupedMessageIdsIdx[modelIdx]];
|
||||
console.log(messageId);
|
||||
|
||||
let messageChildrenIds = history.messages[messageId].childrenIds;
|
||||
|
||||
while (messageChildrenIds.length !== 0) {
|
||||
messageId = messageChildrenIds.at(-1);
|
||||
messageChildrenIds = history.messages[messageId].childrenIds;
|
||||
}
|
||||
|
||||
history.currentId = messageId;
|
||||
history.currentId = getDeepestChildId(history, messageId);
|
||||
|
||||
await tick();
|
||||
await updateChat();
|
||||
|
|
@ -135,14 +125,7 @@
|
|||
let messageId = groupedMessageIds[modelIdx].messageIds[groupedMessageIdsIdx[modelIdx]];
|
||||
console.log(messageId);
|
||||
|
||||
let messageChildrenIds = history.messages[messageId].childrenIds;
|
||||
|
||||
while (messageChildrenIds.length !== 0) {
|
||||
messageId = messageChildrenIds.at(-1);
|
||||
messageChildrenIds = history.messages[messageId].childrenIds;
|
||||
}
|
||||
|
||||
history.currentId = messageId;
|
||||
history.currentId = getDeepestChildId(history, messageId);
|
||||
|
||||
await tick();
|
||||
await updateChat();
|
||||
|
|
@ -209,13 +192,7 @@
|
|||
|
||||
const onGroupClick = async (_messageId, modelIdx) => {
|
||||
if (messageId != _messageId) {
|
||||
let currentMessageId = _messageId;
|
||||
let messageChildrenIds = history.messages[currentMessageId].childrenIds;
|
||||
while (messageChildrenIds.length !== 0) {
|
||||
currentMessageId = messageChildrenIds.at(-1);
|
||||
messageChildrenIds = history.messages[currentMessageId].childrenIds;
|
||||
}
|
||||
history.currentId = currentMessageId;
|
||||
history.currentId = getDeepestChildId(history, _messageId);
|
||||
selectedModelIdx = modelIdx;
|
||||
|
||||
// await tick();
|
||||
|
|
|
|||
|
|
@ -1433,6 +1433,29 @@ export const createMessagesList = (history, messageId) => {
|
|||
return list.reverse();
|
||||
};
|
||||
|
||||
export const getDeepestChildId = (history, messageId) => {
|
||||
let deepestId = messageId;
|
||||
const visitedMessageIds = new Set([deepestId]);
|
||||
let childrenIds =
|
||||
deepestId === null
|
||||
? Object.keys(history.messages).filter((id) => history.messages[id].parentId === null)
|
||||
: (history.messages[deepestId]?.childrenIds ?? []);
|
||||
|
||||
while (childrenIds.length !== 0) {
|
||||
const childId = childrenIds.at(-1);
|
||||
if (visitedMessageIds.has(childId)) {
|
||||
console.warn('Circular dependency detected in message history', childId);
|
||||
break;
|
||||
}
|
||||
|
||||
visitedMessageIds.add(childId);
|
||||
deepestId = childId;
|
||||
childrenIds = history.messages[deepestId]?.childrenIds ?? [];
|
||||
}
|
||||
|
||||
return deepestId;
|
||||
};
|
||||
|
||||
const toTokenCount = (value: unknown) => {
|
||||
const parsed = Number(value || 0);
|
||||
return Number.isFinite(parsed) ? Math.trunc(parsed) : 0;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue