diff --git a/backend/open_webui/routers/files.py b/backend/open_webui/routers/files.py
index 0a2b4ac97f..e63a93a9c4 100644
--- a/backend/open_webui/routers/files.py
+++ b/backend/open_webui/routers/files.py
@@ -129,13 +129,16 @@ def upload_file(
id = str(uuid.uuid4())
name = filename
filename = f"{id}_{filename}"
- tags = {
- "OpenWebUI-User-Email": user.email,
- "OpenWebUI-User-Id": user.id,
- "OpenWebUI-User-Name": user.name,
- "OpenWebUI-File-Id": id,
- }
- contents, file_path = Storage.upload_file(file.file, filename, tags)
+ contents, file_path = Storage.upload_file(
+ file.file,
+ filename,
+ {
+ "OpenWebUI-User-Email": user.email,
+ "OpenWebUI-User-Id": user.id,
+ "OpenWebUI-User-Name": user.name,
+ "OpenWebUI-File-Id": id,
+ },
+ )
file_item = Files.insert_new_file(
user.id,
diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte
index 98a492ccfc..c2a5361578 100644
--- a/src/lib/components/chat/Chat.svelte
+++ b/src/lib/components/chat/Chat.svelte
@@ -2196,6 +2196,42 @@
shareEnabled={!!history.currentId}
{initNewChat}
showBanners={!showCommands}
+ onSaveTempChat={async () => {
+ try {
+ if (!history?.currentId || !Object.keys(history.messages).length) {
+ toast.error($i18n.t('No conversation to save'));
+ return;
+ }
+ const messages = createMessagesList(history, history.currentId);
+ const title =
+ messages.find((m) => m.role === 'user')?.content ?? $i18n.t('New Chat');
+
+ const savedChat = await createNewChat(
+ localStorage.token,
+ {
+ id: uuidv4(),
+ title: title.length > 50 ? `${title.slice(0, 50)}...` : title,
+ models: selectedModels,
+ history: history,
+ messages: messages,
+ timestamp: Date.now()
+ },
+ null
+ );
+
+ if (savedChat) {
+ temporaryChatEnabled.set(false);
+ chatId.set(savedChat.id);
+ chats.set(await getChatList(localStorage.token, $currentChatPage));
+
+ await goto(`/c/${savedChat.id}`);
+ toast.success($i18n.t('Conversation saved successfully'));
+ }
+ } catch (error) {
+ console.error('Error saving conversation:', error);
+ toast.error($i18n.t('Failed to save conversation'));
+ }
+ }}
/>
diff --git a/src/lib/components/chat/Navbar.svelte b/src/lib/components/chat/Navbar.svelte
index 7012583aea..5c48fd90fb 100644
--- a/src/lib/components/chat/Navbar.svelte
+++ b/src/lib/components/chat/Navbar.svelte
@@ -18,6 +18,7 @@
import { slide } from 'svelte/transition';
import { page } from '$app/stores';
+ import { goto } from '$app/navigation';
import ShareChatModal from '../chat/ShareChatModal.svelte';
import ModelSelector from '../chat/ModelSelector.svelte';
@@ -34,7 +35,7 @@
import ChatBubbleDottedChecked from '../icons/ChatBubbleDottedChecked.svelte';
import EllipsisHorizontal from '../icons/EllipsisHorizontal.svelte';
- import { goto } from '$app/navigation';
+ import ChatPlus from '../icons/ChatPlus.svelte';
const i18n = getContext('i18n');
@@ -48,6 +49,8 @@
export let showModelSelector = true;
export let showBanners = true;
+ export let onSaveTempChat: () => {};
+
let closedBannerIds = [];
let showShareChatModal = false;
@@ -105,31 +108,47 @@
- {#if !chat?.id && ($user?.role === 'user' ? ($user?.permissions?.chat?.temporary ?? true) && !($user?.permissions?.chat?.temporary_enforced ?? false) : true)}
-
-
-
+ {#if $user?.role === 'user' ? ($user?.permissions?.chat?.temporary ?? true) && !($user?.permissions?.chat?.temporary_enforced ?? false) : true}
+ {#if !chat?.id}
+
+
+
+ {:else if $temporaryChatEnabled}
+
+
+
+ {/if}
{/if}
{#if shareEnabled && chat && (chat.id || $temporaryChatEnabled)}
diff --git a/src/lib/components/icons/ChatPlus.svelte b/src/lib/components/icons/ChatPlus.svelte
new file mode 100644
index 0000000000..4d669500e7
--- /dev/null
+++ b/src/lib/components/icons/ChatPlus.svelte
@@ -0,0 +1,19 @@
+
+
+