Space Bot commited on
Commit
d43cae3
·
2 Parent(s): ab61283 0850f39

merge upstream

Browse files
.gitignore CHANGED
@@ -308,4 +308,4 @@ cypress/videos
308
  cypress/screenshots
309
  .vscode/settings.json
310
 
311
- webui.db
 
308
  cypress/screenshots
309
  .vscode/settings.json
310
 
311
+ webui.db
backend/open_webui/models/messages.py CHANGED
@@ -189,9 +189,11 @@ class MessageTable:
189
  .all()
190
  )
191
 
192
- return [
193
- MessageModel.model_validate(message) for message in all_messages
194
- ] + [MessageModel.model_validate(message)]
 
 
195
 
196
  def update_message_by_id(
197
  self, id: str, form_data: MessageForm
 
189
  .all()
190
  )
191
 
192
+ # If length of all_messages is less than limit, then add the parent message
193
+ if len(all_messages) < limit:
194
+ all_messages.append(message)
195
+
196
+ return [MessageModel.model_validate(message) for message in all_messages]
197
 
198
  def update_message_by_id(
199
  self, id: str, form_data: MessageForm
backend/open_webui/routers/tasks.py CHANGED
@@ -499,8 +499,8 @@ async def generate_moa_response(
499
  "model": task_model_id,
500
  "messages": [{"role": "user", "content": content}],
501
  "stream": form_data.get("stream", False),
502
- "chat_id": form_data.get("chat_id", None),
503
  "metadata": {
 
504
  "task": str(TASKS.MOA_RESPONSE_GENERATION),
505
  "task_body": form_data,
506
  },
 
499
  "model": task_model_id,
500
  "messages": [{"role": "user", "content": content}],
501
  "stream": form_data.get("stream", False),
 
502
  "metadata": {
503
+ "chat_id": form_data.get("chat_id", None),
504
  "task": str(TASKS.MOA_RESPONSE_GENERATION),
505
  "task_body": form_data,
506
  },
backend/requirements.txt CHANGED
@@ -105,4 +105,4 @@ googleapis-common-protos==1.63.2
105
  ## LDAP
106
  ldap3==2.9.1
107
 
108
- gnupg
 
105
  ## LDAP
106
  ldap3==2.9.1
107
 
108
+ gnupg
src/lib/components/NotificationToast.svelte CHANGED
@@ -12,6 +12,10 @@
12
  export let content: string;
13
 
14
  onMount(() => {
 
 
 
 
15
  if ($settings?.notificationSound ?? true) {
16
  const audio = new Audio(`/audio/notification.mp3`);
17
  audio.play();
 
12
  export let content: string;
13
 
14
  onMount(() => {
15
+ if (!navigator.userActivation.hasBeenActive) {
16
+ return;
17
+ }
18
+
19
  if ($settings?.notificationSound ?? true) {
20
  const audio = new Audio(`/audio/notification.mp3`);
21
  audio.play();
src/lib/components/channel/Messages/Message.svelte CHANGED
@@ -178,7 +178,7 @@
178
  <div class="flex-auto w-0 pl-1">
179
  {#if showUserProfile}
180
  <Name>
181
- <div class=" self-end text-base font-medium">
182
  {message?.user?.name}
183
  </div>
184
 
@@ -189,7 +189,7 @@
189
  <Tooltip
190
  content={dayjs(message.created_at / 1000000).format('dddd, DD MMMM YYYY HH:mm')}
191
  >
192
- {formatDate(message.created_at / 1000000)}
193
  </Tooltip>
194
  </div>
195
  {/if}
 
178
  <div class="flex-auto w-0 pl-1">
179
  {#if showUserProfile}
180
  <Name>
181
+ <div class=" self-end text-base shrink-0 font-medium truncate">
182
  {message?.user?.name}
183
  </div>
184
 
 
189
  <Tooltip
190
  content={dayjs(message.created_at / 1000000).format('dddd, DD MMMM YYYY HH:mm')}
191
  >
192
+ <span class="line-clamp-1">{formatDate(message.created_at / 1000000)}</span>
193
  </Tooltip>
194
  </div>
195
  {/if}
src/lib/components/channel/Messages/Message/ReactionPicker.svelte CHANGED
@@ -61,13 +61,13 @@
61
  );
62
  }
63
  });
64
- // Group emojis into rows of 6
65
  emojiRows = [];
66
  let currentRow = [];
67
  flattenedEmojis.forEach((item) => {
68
  if (item.type === 'emoji') {
69
  currentRow.push(item);
70
- if (currentRow.length === 7) {
71
  emojiRows.push(currentRow);
72
  currentRow = [];
73
  }
@@ -126,7 +126,7 @@
126
  {#if emojiRows.length === 0}
127
  <div class="text-center text-xs text-gray-500 dark:text-gray-400">No results</div>
128
  {:else}
129
- <div class="w-full flex ml-2">
130
  <VirtualList rowHeight={ROW_HEIGHT} items={emojiRows} height={384} let:item>
131
  <div class="w-full">
132
  {#if item.length === 1 && item[0].type === 'group'}
@@ -136,7 +136,7 @@
136
  </div>
137
  {:else}
138
  <!-- Render emojis in a row -->
139
- <div class="flex items-center gap-2 w-full">
140
  {#each item as emojiItem}
141
  <Tooltip
142
  content={emojiItem.shortCodes.map((code) => `:${code}:`).join(', ')}
 
61
  );
62
  }
63
  });
64
+ // Group emojis into rows of 8
65
  emojiRows = [];
66
  let currentRow = [];
67
  flattenedEmojis.forEach((item) => {
68
  if (item.type === 'emoji') {
69
  currentRow.push(item);
70
+ if (currentRow.length === 8) {
71
  emojiRows.push(currentRow);
72
  currentRow = [];
73
  }
 
126
  {#if emojiRows.length === 0}
127
  <div class="text-center text-xs text-gray-500 dark:text-gray-400">No results</div>
128
  {:else}
129
+ <div class="w-full flex ml-0.5">
130
  <VirtualList rowHeight={ROW_HEIGHT} items={emojiRows} height={384} let:item>
131
  <div class="w-full">
132
  {#if item.length === 1 && item[0].type === 'group'}
 
136
  </div>
137
  {:else}
138
  <!-- Render emojis in a row -->
139
+ <div class="flex items-center gap-1.5 w-full">
140
  {#each item as emojiItem}
141
  <Tooltip
142
  content={emojiItem.shortCodes.map((code) => `:${code}:`).join(', ')}
src/lib/components/chat/Messages/ResponseMessage.svelte CHANGED
@@ -489,11 +489,15 @@
489
 
490
  <div class="flex-auto w-0 pl-1">
491
  <Name>
492
- {model?.name ?? message.model}
 
 
 
 
493
 
494
  {#if message.timestamp}
495
  <span
496
- class=" self-center invisible group-hover:visible text-gray-400 text-xs font-medium uppercase ml-0.5 -mt-0.5"
497
  >
498
  {dayjs(message.timestamp * 1000).format($i18n.t('h:mm a'))}
499
  </span>
 
489
 
490
  <div class="flex-auto w-0 pl-1">
491
  <Name>
492
+ <Tooltip content={model?.name ?? message.model} placement="top-start">
493
+ <span class="line-clamp-1">
494
+ {model?.name ?? message.model}
495
+ </span>
496
+ </Tooltip>
497
 
498
  {#if message.timestamp}
499
  <span
500
+ class=" self-center shrink-0 translate-y-0.5 invisible group-hover:visible text-gray-400 text-xs font-medium uppercase ml-0.5 -mt-0.5"
501
  >
502
  {dayjs(message.timestamp * 1000).format($i18n.t('h:mm a'))}
503
  </span>
src/lib/components/layout/Sidebar.svelte CHANGED
@@ -578,82 +578,6 @@
578
  ? 'opacity-20'
579
  : ''}"
580
  >
581
- {#if !search && $pinnedChats.length > 0}
582
- <div class="flex flex-col space-y-1 rounded-xl">
583
- <Folder
584
- className="px-2"
585
- bind:open={showPinnedChat}
586
- on:change={(e) => {
587
- localStorage.setItem('showPinnedChat', e.detail);
588
- console.log(e.detail);
589
- }}
590
- on:import={(e) => {
591
- importChatHandler(e.detail, true);
592
- }}
593
- on:drop={async (e) => {
594
- const { type, id, item } = e.detail;
595
-
596
- if (type === 'chat') {
597
- let chat = await getChatById(localStorage.token, id).catch((error) => {
598
- return null;
599
- });
600
- if (!chat && item) {
601
- chat = await importChat(localStorage.token, item.chat, item?.meta ?? {});
602
- }
603
-
604
- if (chat) {
605
- console.log(chat);
606
- if (chat.folder_id) {
607
- const res = await updateChatFolderIdById(
608
- localStorage.token,
609
- chat.id,
610
- null
611
- ).catch((error) => {
612
- toast.error(error);
613
- return null;
614
- });
615
- }
616
-
617
- if (!chat.pinned) {
618
- const res = await toggleChatPinnedStatusById(localStorage.token, chat.id);
619
- }
620
-
621
- initChatList();
622
- }
623
- }
624
- }}
625
- name={$i18n.t('Pinned')}
626
- >
627
- <div
628
- class="ml-3 pl-1 mt-[1px] flex flex-col overflow-y-auto scrollbar-hidden border-s border-gray-100 dark:border-gray-900"
629
- >
630
- {#each $pinnedChats as chat, idx}
631
- <ChatItem
632
- className=""
633
- id={chat.id}
634
- title={chat.title}
635
- {shiftKey}
636
- selected={selectedChatId === chat.id}
637
- on:select={() => {
638
- selectedChatId = chat.id;
639
- }}
640
- on:unselect={() => {
641
- selectedChatId = null;
642
- }}
643
- on:change={async () => {
644
- initChatList();
645
- }}
646
- on:tag={(e) => {
647
- const { type, name } = e.detail;
648
- tagEventHandler(type, name, chat.id);
649
- }}
650
- />
651
- {/each}
652
- </div>
653
- </Folder>
654
- </div>
655
- {/if}
656
-
657
  {#if $config?.features?.enable_channels && ($user.role === 'admin' || $channels.length > 0) && !search}
658
  <Folder
659
  className="px-2 mt-0.5"
@@ -677,22 +601,6 @@
677
  </Folder>
678
  {/if}
679
 
680
- {#if !search && folders}
681
- <Folders
682
- {folders}
683
- on:import={(e) => {
684
- const { folderId, items } = e.detail;
685
- importChatHandler(items, false, folderId);
686
- }}
687
- on:update={async (e) => {
688
- initChatList();
689
- }}
690
- on:change={async () => {
691
- initChatList();
692
- }}
693
- />
694
- {/if}
695
-
696
  <Folder
697
  collapsible={!search}
698
  className="px-2 mt-0.5"
@@ -750,6 +658,98 @@
750
  <div class="absolute z-40 w-full h-full flex justify-center"></div>
751
  {/if}
752
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
753
  <div class=" flex-1 flex flex-col overflow-y-auto scrollbar-hidden">
754
  <div class="pt-1.5">
755
  {#if $chats}
 
578
  ? 'opacity-20'
579
  : ''}"
580
  >
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
581
  {#if $config?.features?.enable_channels && ($user.role === 'admin' || $channels.length > 0) && !search}
582
  <Folder
583
  className="px-2 mt-0.5"
 
601
  </Folder>
602
  {/if}
603
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
604
  <Folder
605
  collapsible={!search}
606
  className="px-2 mt-0.5"
 
658
  <div class="absolute z-40 w-full h-full flex justify-center"></div>
659
  {/if}
660
 
661
+ {#if !search && $pinnedChats.length > 0}
662
+ <div class="flex flex-col space-y-1 rounded-xl">
663
+ <Folder
664
+ className="px-2"
665
+ bind:open={showPinnedChat}
666
+ on:change={(e) => {
667
+ localStorage.setItem('showPinnedChat', e.detail);
668
+ console.log(e.detail);
669
+ }}
670
+ on:import={(e) => {
671
+ importChatHandler(e.detail, true);
672
+ }}
673
+ on:drop={async (e) => {
674
+ const { type, id, item } = e.detail;
675
+
676
+ if (type === 'chat') {
677
+ let chat = await getChatById(localStorage.token, id).catch((error) => {
678
+ return null;
679
+ });
680
+ if (!chat && item) {
681
+ chat = await importChat(localStorage.token, item.chat, item?.meta ?? {});
682
+ }
683
+
684
+ if (chat) {
685
+ console.log(chat);
686
+ if (chat.folder_id) {
687
+ const res = await updateChatFolderIdById(
688
+ localStorage.token,
689
+ chat.id,
690
+ null
691
+ ).catch((error) => {
692
+ toast.error(error);
693
+ return null;
694
+ });
695
+ }
696
+
697
+ if (!chat.pinned) {
698
+ const res = await toggleChatPinnedStatusById(localStorage.token, chat.id);
699
+ }
700
+
701
+ initChatList();
702
+ }
703
+ }
704
+ }}
705
+ name={$i18n.t('Pinned')}
706
+ >
707
+ <div
708
+ class="ml-3 pl-1 mt-[1px] flex flex-col overflow-y-auto scrollbar-hidden border-s border-gray-100 dark:border-gray-900"
709
+ >
710
+ {#each $pinnedChats as chat, idx}
711
+ <ChatItem
712
+ className=""
713
+ id={chat.id}
714
+ title={chat.title}
715
+ {shiftKey}
716
+ selected={selectedChatId === chat.id}
717
+ on:select={() => {
718
+ selectedChatId = chat.id;
719
+ }}
720
+ on:unselect={() => {
721
+ selectedChatId = null;
722
+ }}
723
+ on:change={async () => {
724
+ initChatList();
725
+ }}
726
+ on:tag={(e) => {
727
+ const { type, name } = e.detail;
728
+ tagEventHandler(type, name, chat.id);
729
+ }}
730
+ />
731
+ {/each}
732
+ </div>
733
+ </Folder>
734
+ </div>
735
+ {/if}
736
+
737
+ {#if !search && folders}
738
+ <Folders
739
+ {folders}
740
+ on:import={(e) => {
741
+ const { folderId, items } = e.detail;
742
+ importChatHandler(items, false, folderId);
743
+ }}
744
+ on:update={async (e) => {
745
+ initChatList();
746
+ }}
747
+ on:change={async () => {
748
+ initChatList();
749
+ }}
750
+ />
751
+ {/if}
752
+
753
  <div class=" flex-1 flex flex-col overflow-y-auto scrollbar-hidden">
754
  <div class="pt-1.5">
755
  {#if $chats}