This commit is contained in:
Timothy Jaeryang Baek
2026-03-22 06:14:05 -05:00
parent 6a004205d8
commit d784eb1e9b
2 changed files with 63 additions and 57 deletions
+60 -57
View File
@@ -45,7 +45,8 @@
showEmbeds, showEmbeds,
selectedTerminalId, selectedTerminalId,
showFileNavPath, showFileNavPath,
showFileNavDir showFileNavDir,
chatRequestQueues
} from '$lib/stores'; } from '$lib/stores';
import { WEBUI_API_BASE_URL } from '$lib/constants'; import { WEBUI_API_BASE_URL } from '$lib/constants';
@@ -170,8 +171,7 @@
let files = []; let files = [];
let params = {}; let params = {};
// Message queue for storing messages while generating
let messageQueue: { id: string; prompt: string; files: any[] }[] = [];
$: if (chatIdProp) { $: if (chatIdProp) {
navigateHandler(); navigateHandler();
@@ -180,16 +180,10 @@
const navigateHandler = async () => { const navigateHandler = async () => {
loading = true; loading = true;
// Save current queue to sessionStorage before navigating away
if (messageQueue.length > 0 && $chatId) {
sessionStorage.setItem(`chat-queue-${$chatId}`, JSON.stringify(messageQueue));
}
prompt = ''; prompt = '';
messageInput?.setText(''); messageInput?.setText('');
files = []; files = [];
messageQueue = [];
selectedToolIds = []; selectedToolIds = [];
selectedFilterIds = []; selectedFilterIds = [];
webSearchEnabled = false; webSearchEnabled = false;
@@ -206,28 +200,11 @@
await tick(); await tick();
// Restore queue from sessionStorage // Process any queued requests if the chat is idle
const storedQueueData = sessionStorage.getItem(`chat-queue-${chatIdProp}`); const lastMessage = history.currentId ? history.messages[history.currentId] : null;
if (storedQueueData) { const isIdle = !lastMessage || lastMessage.role !== 'assistant' || lastMessage.done;
try { if (isIdle) {
const restoredQueue = JSON.parse(storedQueueData); await processNextInQueue(chatIdProp);
if (restoredQueue.length > 0) {
sessionStorage.removeItem(`chat-queue-${chatIdProp}`);
// Check if there are pending tasks (still generating)
const hasPendingTask = taskIds !== null && taskIds.length > 0;
if (!hasPendingTask) {
// No pending tasks - process the queue
files = restoredQueue.flatMap((m) => m.files);
await tick();
const combinedPrompt = restoredQueue.map((m) => m.prompt).join('\n\n');
await submitPrompt(combinedPrompt);
} else {
// Has pending tasks - show as queued (chatCompletedHandler will process)
messageQueue = restoredQueue;
}
}
} catch (e) {}
} }
if (storageChatInput) { if (storageChatInput) {
@@ -444,6 +421,7 @@
for (const messageId of history.messages[message.parentId].childrenIds) { for (const messageId of history.messages[message.parentId].childrenIds) {
history.messages[messageId].done = true; history.messages[messageId].done = true;
} }
await processNextInQueue($chatId);
} else { } else {
message.done = true; message.done = true;
} }
@@ -562,6 +540,9 @@
history.messages[event.message_id] = message; history.messages[event.message_id] = message;
} }
} else {
// Non-active chat completion: queue stays in the global store.
// navigateHandler will process it when the user returns to that chat.
} }
}; };
@@ -1155,7 +1136,6 @@
chatFiles = []; chatFiles = [];
params = {}; params = {};
taskIds = null; taskIds = null;
messageQueue = [];
if ($page.url.searchParams.get('youtube')) { if ($page.url.searchParams.get('youtube')) {
await uploadWeb(`https://www.youtube.com/watch?v=${$page.url.searchParams.get('youtube')}`); await uploadWeb(`https://www.youtube.com/watch?v=${$page.url.searchParams.get('youtube')}`);
@@ -1307,6 +1287,24 @@
}); });
} }
}; };
const processNextInQueue = async (targetChatId: string) => {
const queue = $chatRequestQueues[targetChatId];
if (!queue || queue.length === 0) return;
const combinedPrompt = queue.map((m) => m.prompt).join('\n\n');
const combinedFiles = queue.flatMap((m) => m.files);
chatRequestQueues.update((q) => {
const { [targetChatId]: _, ...rest } = q;
return rest;
});
files = combinedFiles;
await tick();
await submitPrompt(combinedPrompt);
};
const chatCompletedHandler = async (_chatId, modelId, responseMessageId, messages) => { const chatCompletedHandler = async (_chatId, modelId, responseMessageId, messages) => {
const res = await chatCompleted(localStorage.token, { const res = await chatCompleted(localStorage.token, {
model: modelId, model: modelId,
@@ -1716,16 +1714,8 @@
createMessagesList(history, message.id) createMessagesList(history, message.id)
); );
// Process message queue immediately after main response finishes // Process next queued request if any
if (messageQueue.length > 0) { await processNextInQueue(chatId);
const combinedPrompt = messageQueue.map((m) => m.prompt).join('\n\n');
const combinedFiles = messageQueue.flatMap((m) => m.files);
messageQueue = [];
files = combinedFiles;
await tick();
await submitPrompt(combinedPrompt);
}
} }
console.log(data); console.log(data);
@@ -1789,16 +1779,15 @@
if (isGenerating) { if (isGenerating) {
if ($settings?.enableMessageQueue ?? true) { if ($settings?.enableMessageQueue ?? true) {
// Queue the message // Enqueue the request
const _files = structuredClone(files); const _files = structuredClone(files);
messageQueue = [ chatRequestQueues.update((q) => ({
...messageQueue, ...q,
{ [$chatId]: [
id: uuidv4(), ...(q[$chatId] ?? []),
prompt: userPrompt, { id: uuidv4(), prompt: userPrompt, files: _files }
files: _files ]
} }));
];
// Clear input // Clear input
messageInput?.setText(''); messageInput?.setText('');
prompt = ''; prompt = '';
@@ -2392,6 +2381,8 @@
generationController?.abort(); generationController?.abort();
generationController = null; generationController = null;
} }
await processNextInQueue($chatId);
}; };
const submitMessage = async (parentId, prompt) => { const submitMessage = async (parentId, prompt) => {
@@ -2845,12 +2836,16 @@
{stopResponse} {stopResponse}
{createMessagePair} {createMessagePair}
{onUpload} {onUpload}
{messageQueue} messageQueue={$chatRequestQueues[$chatId] ?? []}
onQueueSendNow={async (id) => { onQueueSendNow={async (id) => {
const item = messageQueue.find((m) => m.id === id); const queue = $chatRequestQueues[$chatId] ?? [];
const item = queue.find((m) => m.id === id);
if (item) { if (item) {
// Remove from queue // Remove from queue
messageQueue = messageQueue.filter((m) => m.id !== id); chatRequestQueues.update((q) => ({
...q,
[$chatId]: queue.filter((m) => m.id !== id)
}));
// Stop current generation first // Stop current generation first
await stopResponse(); await stopResponse();
await tick(); await tick();
@@ -2861,17 +2856,25 @@
} }
}} }}
onQueueEdit={(id) => { onQueueEdit={(id) => {
const item = messageQueue.find((m) => m.id === id); const queue = $chatRequestQueues[$chatId] ?? [];
const item = queue.find((m) => m.id === id);
if (item) { if (item) {
// Remove from queue // Remove from queue
messageQueue = messageQueue.filter((m) => m.id !== id); chatRequestQueues.update((q) => ({
...q,
[$chatId]: queue.filter((m) => m.id !== id)
}));
// Set files and restore prompt to input // Set files and restore prompt to input
files = item.files; files = item.files;
messageInput?.setText(item.prompt); messageInput?.setText(item.prompt);
} }
}} }}
onQueueDelete={(id) => { onQueueDelete={(id) => {
messageQueue = messageQueue.filter((m) => m.id !== id); const queue = $chatRequestQueues[$chatId] ?? [];
chatRequestQueues.update((q) => ({
...q,
[$chatId]: queue.filter((m) => m.id !== id)
}));
}} }}
onChange={(data) => { onChange={(data) => {
if (!$temporaryChatEnabled) { if (!$temporaryChatEnabled) {
+3
View File
@@ -80,6 +80,9 @@ export const banners: Writable<Banner[]> = writable([]);
export const settings: Writable<Settings> = writable({}); export const settings: Writable<Settings> = writable({});
export const audioQueue = writable<AudioQueue | null>(null); export const audioQueue = writable<AudioQueue | null>(null);
export const chatRequestQueues: Writable<
Record<string, { id: string; prompt: string; files: any[] }[]>
> = writable({});
export const sidebarWidth = writable(260); export const sidebarWidth = writable(260);