refac
This commit is contained in:
1 parent
cf887b68ea
commit
73421c5b42
8 files changed
+103
-21
No files matched your search
@@ -920,6 +920,47 @@ export const cloneChatById = async (token: string, id: string, title?: string) =
|
|||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const forkChatById = async (token: string, id: string, messageId?: string | null) => {
|
||||||
|
let error = null;
|
||||||
|
|
||||||
|
const res = await fetch(`${WEBUI_API_BASE_URL}/chats/${id}/fork`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
...(token && { authorization: `Bearer ${token}` })
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
message_id: messageId ?? null
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(async (res) => {
|
||||||
|
if (!res.ok) throw await res.json();
|
||||||
|
return res.json();
|
||||||
|
})
|
||||||
|
.then((json) => {
|
||||||
|
return json;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
error = err;
|
||||||
|
|
||||||
|
if ('detail' in err) {
|
||||||
|
error = err.detail;
|
||||||
|
} else {
|
||||||
|
error = err;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error(err);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
export const cloneSharedChatById = async (token: string, id: string) => {
|
export const cloneSharedChatById = async (token: string, id: string) => {
|
||||||
let error = null;
|
let error = null;
|
||||||
|
|
||||||
|
|||||||
@@ -70,10 +70,10 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
archiveChatById,
|
archiveChatById,
|
||||||
cloneChatById,
|
|
||||||
compactChatById,
|
compactChatById,
|
||||||
createNewChat,
|
createNewChat,
|
||||||
deleteChatById,
|
deleteChatById,
|
||||||
|
forkChatById,
|
||||||
getAllTags,
|
getAllTags,
|
||||||
getChatById,
|
getChatById,
|
||||||
getTagsById,
|
getTagsById,
|
||||||
@@ -1884,6 +1884,9 @@
|
|||||||
(chatContent?.history ?? undefined) !== undefined
|
(chatContent?.history ?? undefined) !== undefined
|
||||||
? chatContent.history
|
? chatContent.history
|
||||||
: convertMessagesToHistory(chatContent.messages);
|
: convertMessagesToHistory(chatContent.messages);
|
||||||
|
if (chat?.current_message_id && history?.messages?.[chat.current_message_id]) {
|
||||||
|
history.currentId = chat.current_message_id;
|
||||||
|
}
|
||||||
|
|
||||||
// Sanitize history: repair orphaned references and structurally-malformed
|
// Sanitize history: repair orphaned references and structurally-malformed
|
||||||
// nodes from failed regenerations (#24424, #24157, #20474)
|
// nodes from failed regenerations (#24424, #24157, #20474)
|
||||||
@@ -2466,7 +2469,7 @@
|
|||||||
document.getElementById('chat-input')?.focus();
|
document.getElementById('chat-input')?.focus();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleForkChat = async () => {
|
const handleForkChat = async (messageId: string | null = null) => {
|
||||||
if (!$chatId || !history?.currentId) {
|
if (!$chatId || !history?.currentId) {
|
||||||
toast.message($i18n.t('No chat to fork'));
|
toast.message($i18n.t('No chat to fork'));
|
||||||
return;
|
return;
|
||||||
@@ -2489,13 +2492,7 @@
|
|||||||
const toastId = toast.loading($i18n.t('Forking chat...'));
|
const toastId = toast.loading($i18n.t('Forking chat...'));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await cloneChatById(
|
const result = await forkChatById(localStorage.token, $chatId, messageId ?? history.currentId);
|
||||||
localStorage.token,
|
|
||||||
$chatId,
|
|
||||||
$i18n.t('Clone of {{TITLE}}', {
|
|
||||||
TITLE: $chatTitle || 'Chat'
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
if (result?.id) {
|
if (result?.id) {
|
||||||
if (!embedded) {
|
if (!embedded) {
|
||||||
@@ -3725,6 +3722,7 @@
|
|||||||
{mergeResponses}
|
{mergeResponses}
|
||||||
{chatActionHandler}
|
{chatActionHandler}
|
||||||
{addMessages}
|
{addMessages}
|
||||||
|
forkHandler={generating || taskIds?.length ? null : handleForkChat}
|
||||||
topPadding={!embedded}
|
topPadding={!embedded}
|
||||||
bottomPadding={files.length > 0}
|
bottomPadding={files.length > 0}
|
||||||
{onSelect}
|
{onSelect}
|
||||||
|
|||||||
@@ -183,10 +183,10 @@
|
|||||||
</button>
|
</button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
{:else if item.data.id === 'fork'}
|
{:else if item.data.id === 'fork'}
|
||||||
<Tooltip content="Clone this chat into a new copy." placement="top">
|
<Tooltip content="Fork the current chat branch into a new chat." placement="top">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
aria-label="Fork: clone this chat into a new copy."
|
aria-label="Fork: fork the current chat branch into a new chat."
|
||||||
class="slash-command-row flex items-center gap-2 w-full h-6 px-2 rounded-xl text-xs text-left transition-colors duration-75
|
class="slash-command-row flex items-center gap-2 w-full h-6 px-2 rounded-xl text-xs text-left transition-colors duration-75
|
||||||
{commandIdx === selectedIdx ? 'app-interactive-active' : ''} disabled:opacity-50"
|
{commandIdx === selectedIdx ? 'app-interactive-active' : ''} disabled:opacity-50"
|
||||||
disabled={forkDisabled}
|
disabled={forkDisabled}
|
||||||
@@ -222,7 +222,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<span class="flex-1 min-w-0 flex items-baseline gap-1.5 overflow-hidden">
|
<span class="flex-1 min-w-0 flex items-baseline gap-1.5 overflow-hidden">
|
||||||
<span class="truncate">Fork</span>
|
<span class="truncate">Fork</span>
|
||||||
<span class="app-muted text-[0.625rem] truncate shrink-0">Clone chat</span>
|
<span class="app-muted text-[0.625rem] truncate shrink-0">Current branch</span>
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
export let showMessage: Function = () => {};
|
export let showMessage: Function = () => {};
|
||||||
export let submitMessage: Function = () => {};
|
export let submitMessage: Function = () => {};
|
||||||
export let addMessages: Function = () => {};
|
export let addMessages: Function = () => {};
|
||||||
|
export let forkHandler: Function | null = null;
|
||||||
|
|
||||||
export let readOnly = false;
|
export let readOnly = false;
|
||||||
export let editCodeBlock = true;
|
export let editCodeBlock = true;
|
||||||
@@ -539,6 +540,7 @@
|
|||||||
{continueResponse}
|
{continueResponse}
|
||||||
{mergeResponses}
|
{mergeResponses}
|
||||||
{addMessages}
|
{addMessages}
|
||||||
|
{forkHandler}
|
||||||
{triggerScroll}
|
{triggerScroll}
|
||||||
{readOnly}
|
{readOnly}
|
||||||
{editCodeBlock}
|
{editCodeBlock}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
export let mergeResponses;
|
export let mergeResponses;
|
||||||
|
|
||||||
export let addMessages;
|
export let addMessages;
|
||||||
|
export let forkHandler: Function | null = null;
|
||||||
export let triggerScroll;
|
export let triggerScroll;
|
||||||
export let readOnly = false;
|
export let readOnly = false;
|
||||||
export let editCodeBlock = true;
|
export let editCodeBlock = true;
|
||||||
@@ -97,6 +98,7 @@
|
|||||||
{continueResponse}
|
{continueResponse}
|
||||||
{regenerateResponse}
|
{regenerateResponse}
|
||||||
{addMessages}
|
{addMessages}
|
||||||
|
{forkHandler}
|
||||||
{readOnly}
|
{readOnly}
|
||||||
{editCodeBlock}
|
{editCodeBlock}
|
||||||
{topPadding}
|
{topPadding}
|
||||||
@@ -122,6 +124,7 @@
|
|||||||
{mergeResponses}
|
{mergeResponses}
|
||||||
{triggerScroll}
|
{triggerScroll}
|
||||||
{addMessages}
|
{addMessages}
|
||||||
|
{forkHandler}
|
||||||
{readOnly}
|
{readOnly}
|
||||||
{editCodeBlock}
|
{editCodeBlock}
|
||||||
{topPadding}
|
{topPadding}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
export let mergeResponses: Function;
|
export let mergeResponses: Function;
|
||||||
|
|
||||||
export let addMessages: Function;
|
export let addMessages: Function;
|
||||||
|
export let forkHandler: Function | null = null;
|
||||||
|
|
||||||
export let triggerScroll: Function;
|
export let triggerScroll: Function;
|
||||||
|
|
||||||
@@ -319,6 +320,7 @@
|
|||||||
groupedMessageIds[selectedModelIdx].messageIds.length - 1;
|
groupedMessageIds[selectedModelIdx].messageIds.length - 1;
|
||||||
}}
|
}}
|
||||||
{addMessages}
|
{addMessages}
|
||||||
|
{forkHandler}
|
||||||
{readOnly}
|
{readOnly}
|
||||||
{topPadding}
|
{topPadding}
|
||||||
{onInsertToNote}
|
{onInsertToNote}
|
||||||
@@ -376,6 +378,7 @@
|
|||||||
groupedMessageIds[modelIdx].messageIds.length - 1;
|
groupedMessageIds[modelIdx].messageIds.length - 1;
|
||||||
}}
|
}}
|
||||||
{addMessages}
|
{addMessages}
|
||||||
|
{forkHandler}
|
||||||
{readOnly}
|
{readOnly}
|
||||||
{editCodeBlock}
|
{editCodeBlock}
|
||||||
{topPadding}
|
{topPadding}
|
||||||
|
|||||||
@@ -159,6 +159,7 @@
|
|||||||
export let submitMessage: Function;
|
export let submitMessage: Function;
|
||||||
export let continueResponse: Function;
|
export let continueResponse: Function;
|
||||||
export let regenerateResponse: Function;
|
export let regenerateResponse: Function;
|
||||||
|
export let forkHandler: Function | null = null;
|
||||||
|
|
||||||
export let addMessages: Function;
|
export let addMessages: Function;
|
||||||
|
|
||||||
@@ -1054,6 +1055,37 @@
|
|||||||
</button>
|
</button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
|
{#if message.done && !readOnly && forkHandler}
|
||||||
|
<Tooltip content="Fork chat" placement="bottom">
|
||||||
|
<button
|
||||||
|
aria-label="Fork chat"
|
||||||
|
class="{isLastMessage || ($settings?.highContrastMode ?? false)
|
||||||
|
? 'visible'
|
||||||
|
: 'invisible group-hover:visible'} p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg dark:hover:text-white hover:text-black transition"
|
||||||
|
on:click={() => {
|
||||||
|
forkHandler?.(message.id);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
class="w-4 h-4"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="1.8"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<path d="M4 12H9" />
|
||||||
|
<path d="M9 12C12.5 12 12.5 7 16 7H20" />
|
||||||
|
<path d="M17 4L20 7L17 10" />
|
||||||
|
<path d="M9 12C12.5 12 12.5 17 16 17H20" />
|
||||||
|
<path d="M17 14L20 17L17 20" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</Tooltip>
|
||||||
|
{/if}
|
||||||
|
|
||||||
{#if onInsertToNote && visibleResponseContent}
|
{#if onInsertToNote && visibleResponseContent}
|
||||||
<Tooltip content={$i18n.t('Insert into note')} placement="bottom">
|
<Tooltip content={$i18n.t('Insert into note')} placement="bottom">
|
||||||
<button
|
<button
|
||||||
|
|||||||
+12
-9
@@ -203,25 +203,28 @@ export const convertMessagesToHistory = (messages) => {
|
|||||||
let messageId = null;
|
let messageId = null;
|
||||||
|
|
||||||
for (const message of messages) {
|
for (const message of messages) {
|
||||||
messageId = uuidv4();
|
messageId = message?.id ?? uuidv4();
|
||||||
|
const parentId = message?.parentId ?? parentMessageId;
|
||||||
if (parentMessageId !== null) {
|
|
||||||
history.messages[parentMessageId].childrenIds = [
|
|
||||||
...history.messages[parentMessageId].childrenIds,
|
|
||||||
messageId
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
history.messages[messageId] = {
|
history.messages[messageId] = {
|
||||||
...message,
|
...message,
|
||||||
id: messageId,
|
id: messageId,
|
||||||
parentId: parentMessageId,
|
parentId,
|
||||||
childrenIds: []
|
childrenIds: []
|
||||||
};
|
};
|
||||||
|
|
||||||
parentMessageId = messageId;
|
parentMessageId = messageId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const message of Object.values(history.messages)) {
|
||||||
|
if (message.parentId && history.messages[message.parentId]) {
|
||||||
|
history.messages[message.parentId].childrenIds = [
|
||||||
|
...history.messages[message.parentId].childrenIds,
|
||||||
|
message.id
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
history.currentId = messageId;
|
history.currentId = messageId;
|
||||||
return history;
|
return history;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in new issue
Block a user