From 3374b21a7d50b0bd17c5c6782b1f23e5af01a40c Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Tue, 25 Aug 2026 14:39:25 -0400 Subject: [PATCH] refac --- src/lib/components/chat/Chat.svelte | 122 +++++++++++------- src/lib/components/chat/MessageInput.svelte | 5 +- .../chat/MessageInput/IntegrationsMenu.svelte | 4 +- src/lib/components/chat/Placeholder.svelte | 2 + 4 files changed, 79 insertions(+), 54 deletions(-) diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index 024aad1893..5df9cd1de2 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -312,9 +312,9 @@ $: contextUsage = getContextUsage() ?? (contextCompactionEnabled ? serverContextUsage : null); $: embeddedHeaderTitle = embeddedTitle || $chatTitle || $i18n.t('Chat'); - let selectedToolIds = []; - let selectedSkillIds = []; - let selectedFilterIds = []; + let selectedToolIds: string[] = []; + let selectedSkillIds: string[] = []; + let selectedFilterIds: string[] = []; let pendingOAuthTools = []; let imageGenerationEnabled = false; @@ -408,7 +408,7 @@ // Chat Input let prompt = ''; let chatFiles = []; - let files = []; + let files: any[] = []; let params = {}; let chatVariables = {}; let showChatVariablesModal = false; @@ -737,6 +737,31 @@ }); }; + const restoreChatInput = async (storageChatInput: string | null) => { + if (!storageChatInput || $temporaryChatEnabled) { + return false; + } + + try { + const input = JSON.parse(storageChatInput); + prompt = input.prompt ?? ''; + messageInput?.setText(prompt); + files = input.files ?? []; + selectedToolIds = input.selectedToolIds ?? []; + selectedSkillIds = input.selectedSkillIds ?? []; + selectedFilterIds = input.selectedFilterIds ?? []; + webSearchEnabled = input.webSearchEnabled ?? false; + imageGenerationEnabled = input.imageGenerationEnabled ?? false; + codeInterpreterEnabled = input.codeInterpreterEnabled ?? false; + if (input.toolApprovalMode) { + await handleToolApprovalModeChange(input.toolApprovalMode); + } + return true; + } catch (e) { + return false; + } + }; + const withSelectedText = (text: string) => embedded && selectedText?.trim() ? `${text}\n\nSelected note text for replace_note_content operations:\n${selectedText.trim()}` @@ -820,25 +845,7 @@ await processNextInQueue(chatIdProp); } - if (storageChatInput) { - try { - const input = JSON.parse(storageChatInput); - - if (!$temporaryChatEnabled) { - messageInput?.setText(input.prompt); - files = input.files; - selectedToolIds = input.selectedToolIds; - selectedSkillIds = input.selectedSkillIds ?? []; - selectedFilterIds = input.selectedFilterIds; - webSearchEnabled = input.webSearchEnabled; - imageGenerationEnabled = input.imageGenerationEnabled; - codeInterpreterEnabled = input.codeInterpreterEnabled; - if (input.toolApprovalMode) { - handleToolApprovalModeChange(input.toolApprovalMode); - } - } - } catch (e) {} - } else { + if (!(await restoreChatInput(storageChatInput))) { await setDefaults(); } @@ -941,9 +948,7 @@ return; } - saveSessionSelectedModels(); - await tick(); - initiateOAuthRedirect(nextTool); + await oauthRedirectHandler(nextTool); }; const resetInput = async () => { @@ -1590,23 +1595,7 @@ imageGenerationEnabled = false; codeInterpreterEnabled = false; - try { - const input = JSON.parse(storageChatInput); - - if (!$temporaryChatEnabled) { - messageInput?.setText(input.prompt); - files = input.files; - selectedToolIds = input.selectedToolIds; - selectedSkillIds = input.selectedSkillIds ?? []; - selectedFilterIds = input.selectedFilterIds; - webSearchEnabled = input.webSearchEnabled; - imageGenerationEnabled = input.imageGenerationEnabled; - codeInterpreterEnabled = input.codeInterpreterEnabled; - if (input.toolApprovalMode) { - handleToolApprovalModeChange(input.toolApprovalMode); - } - } - } catch (e) {} + await restoreChatInput(storageChatInput); } messageInput?.focus({ preventScroll: true }); @@ -2125,6 +2114,7 @@ autoScroll = true; await resetInput(); + await restoreChatInput(sessionStorage.getItem('chat-input')); await chatId.set(''); await chatTitle.set(''); @@ -4007,23 +3997,52 @@ const MAX_DRAFT_LENGTH = 5000; let saveDraftTimeout: ReturnType | null = null; - const saveDraft = async (draft: any, chatId: string | null = null) => { + const getChatInputDraft = () => ({ + prompt, + files: files + .filter((file) => file.type !== 'image') + .map((file) => ({ + ...file, + user: undefined, + access_grants: undefined + })), + selectedToolIds, + selectedSkillIds, + selectedFilterIds, + imageGenerationEnabled, + webSearchEnabled, + codeInterpreterEnabled, + toolApprovalMode + }); + + const saveDraft = async (draft: any, chatId: string | null = null, debounce = true) => { if (saveDraftTimeout) { clearTimeout(saveDraftTimeout); } if (draft.prompt !== null && draft.prompt.length < MAX_DRAFT_LENGTH) { - saveDraftTimeout = setTimeout(async () => { - await sessionStorage.setItem( - `chat-input${chatId ? `-${chatId}` : ''}`, - JSON.stringify(draft) - ); - }, 500); + const key = `chat-input${chatId ? `-${chatId}` : ''}`; + const write = () => sessionStorage.setItem(key, JSON.stringify(draft)); + if (debounce) { + saveDraftTimeout = setTimeout(write, 500); + } else { + write(); + } } else { sessionStorage.removeItem(`chat-input${chatId ? `-${chatId}` : ''}`); } }; + const oauthRedirectHandler = async (tool: { + id: string; + serverId: string; + authType?: string | null; + }) => { + saveSessionSelectedModels(); + await saveDraft(getChatInputDraft(), null, false); + initiateOAuthRedirect(tool); + }; + const clearDraft = async (chatId: string | null = null) => { if (saveDraftTimeout) { clearTimeout(saveDraftTimeout); @@ -4406,6 +4425,7 @@ bind:imageGenerationEnabled bind:codeInterpreterEnabled {pendingOAuthTools} + {oauthRedirectHandler} bind:webSearchEnabled bind:atSelectedModel bind:showCommands @@ -4497,6 +4517,7 @@ bind:imageGenerationEnabled bind:codeInterpreterEnabled {pendingOAuthTools} + {oauthRedirectHandler} bind:webSearchEnabled bind:atSelectedModel bind:showCommands @@ -4557,6 +4578,7 @@ {toolApprovalMode} onToolApprovalModeChange={handleToolApprovalModeChange} {pendingOAuthTools} + {oauthRedirectHandler} {stopResponse} {createMessagePair} {onSelect} diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index 336a10ed47..bb65768366 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -67,7 +67,6 @@ import { getSessionUser } from '$lib/apis/auths'; import { WEBUI_BASE_URL, WEBUI_API_BASE_URL, PASTED_TEXT_CHARACTER_LIMIT } from '$lib/constants'; - import { initiateOAuthRedirect } from '$lib/apis/configs'; import { matchKeybinding, Shortcut } from '$lib/shortcuts'; import { createNoteHandler } from '../notes/utils'; @@ -193,6 +192,7 @@ export let onToolApprovalModeChange: Function = () => {}; export let pendingOAuthTools = []; + export let oauthRedirectHandler: Function = () => {}; let showTerminalMenu = false; @@ -2259,6 +2259,7 @@ bind:webSearchEnabled bind:imageGenerationEnabled bind:codeInterpreterEnabled + {oauthRedirectHandler} {onWebSearchToggle} closeOnOutsideClick={integrationsMenuCloseOnOutsideClick} onShowValves={(e) => { @@ -2478,7 +2479,7 @@