Преглед на файлове

Merge branch 'dev' into remove-ollama

Timothy Jaeryang Baek преди 9 месеца
родител
ревизия
670f28d694

+ 2 - 0
.github/ISSUE_TEMPLATE/bug_report.md

@@ -29,9 +29,11 @@ assignees: ''
 - [ ] I have provided the exact steps to reproduce the bug in the "Steps to Reproduce" section below.
 
 ## Expected Behavior:
+
 [Describe what you expected to happen.]
 
 ## Actual Behavior:
+
 [Describe what actually happened.]
 
 ## Description

+ 22 - 0
CHANGELOG.md

@@ -5,6 +5,28 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## [0.3.12] - 2024-08-07
+
+### Added
+
+- **🔄 Sidebar Infinite Scroll**: Added an infinite scroll feature in the sidebar for more efficient chat navigation, reducing load times and enhancing user experience.
+- **🚀 Enhanced Markdown Rendering**: Support for rendering all code blocks and making images clickable for preview; codespan styling is also enhanced to improve readability and user interaction.
+- **🔒 Admin Shared Chat Visibility**: Admins no longer have default visibility over shared chats when ENABLE_ADMIN_CHAT_ACCESS is set to false, tightening security and privacy settings for users.
+- **🌍 Language Updates**: Added Malay (Bahasa Malaysia) translation and updated Catalan and Traditional Chinese translations to improve accessibility for more users.
+
+### Fixed
+
+- **📊 Markdown Rendering Issues**: Resolved issues with markdown rendering to ensure consistent and correct display across components.
+- **🛠️ Styling Issues**: Multiple fixes applied to styling throughout the application, improving the overall visual experience and interface consistency.
+- **🗃️ Modal Handling**: Fixed an issue where modals were not closing correctly in various model chat scenarios, enhancing usability and interface reliability.
+- **📄 Missing OpenAI Usage Information**: Resolved issues where usage statistics for OpenAI services were not being correctly displayed, ensuring users have access to crucial data for managing and monitoring their API consumption.
+- **🔧 Non-Streaming Support for Functions Plugin**: Fixed a functionality issue with the Functions plugin where non-streaming operations were not functioning as intended, restoring full capabilities for async and sync integration within the platform.
+- **🔄 Environment Variable Type Correction (COMFYUI_FLUX_FP8_CLIP)**: Corrected the data type of the 'COMFYUI_FLUX_FP8_CLIP' environment variable from string to boolean, ensuring environment settings apply correctly and enhance configuration management.
+
+### Changed
+
+- **🔧 Backend Dependency Updates**: Updated several backend dependencies such as boto3, pypdf, python-pptx, validators, and black, ensuring up-to-date security and performance optimizations.
+
 ## [0.3.11] - 2024-08-02
 
 ### Added

+ 4 - 2
backend/apps/openai/main.py

@@ -359,8 +359,10 @@ async def generate_chat_completion(
 ):
     idx = 0
     payload = {**form_data}
-    payload.pop("metadata", None)
-
+    
+    if "metadata" in payload:
+        del payload["metadata"]
+        
     model_id = form_data.get("model")
     model_info = Models.get_model_by_id(model_id)
 

+ 2 - 0
backend/apps/webui/main.py

@@ -46,6 +46,7 @@ from config import (
     AppConfig,
     OAUTH_USERNAME_CLAIM,
     OAUTH_PICTURE_CLAIM,
+    OAUTH_EMAIL_CLAIM,
 )
 
 from apps.socket.main import get_event_call, get_event_emitter
@@ -84,6 +85,7 @@ app.state.config.ENABLE_COMMUNITY_SHARING = ENABLE_COMMUNITY_SHARING
 
 app.state.config.OAUTH_USERNAME_CLAIM = OAUTH_USERNAME_CLAIM
 app.state.config.OAUTH_PICTURE_CLAIM = OAUTH_PICTURE_CLAIM
+app.state.config.OAUTH_EMAIL_CLAIM = OAUTH_EMAIL_CLAIM
 
 app.state.MODELS = {}
 app.state.TOOLS = {}

+ 6 - 0
backend/config.py

@@ -433,6 +433,12 @@ OAUTH_PICTURE_CLAIM = PersistentConfig(
     os.environ.get("OAUTH_PICTURE_CLAIM", "picture"),
 )
 
+OAUTH_EMAIL_CLAIM = PersistentConfig(
+    "OAUTH_EMAIL_CLAIM",
+    "oauth.oidc.email_claim",
+    os.environ.get("OAUTH_EMAIL_CLAIM", "email"),
+)
+
 
 def load_oauth_providers():
     OAUTH_PROVIDERS.clear()

+ 2 - 1
backend/main.py

@@ -2158,7 +2158,8 @@ async def oauth_callback(provider: str, request: Request, response: Response):
         log.warning(f"OAuth callback failed, sub is missing: {user_data}")
         raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED)
     provider_sub = f"{provider}@{sub}"
-    email = user_data.get("email", "").lower()
+    email_claim = webui_app.state.config.OAUTH_EMAIL_CLAIM
+    email = user_data.get(email_claim, "").lower()
     # We currently mandate that email addresses are provided
     if not email:
         log.warning(f"OAuth callback failed, email is missing: {user_data}")

+ 2 - 1
docs/SECURITY.md

@@ -32,4 +32,5 @@ We regularly audit our internal processes and system architecture for vulnerabil
 For immediate concerns or detailed reports that meet our guidelines, please create an issue in our [issue tracker](/open-webui/open-webui/issues) or contact us on [Discord](https://discord.gg/5rJgQTnV4s).
 
 ---
-_Last updated on **2024-08-06**._
+
+_Last updated on **2024-08-06**._

Файловите разлики са ограничени, защото са твърде много
+ 235 - 278
package-lock.json


+ 21 - 16
package.json

@@ -1,6 +1,6 @@
 {
 	"name": "open-webui",
-	"version": "0.3.11",
+	"version": "0.3.12",
 	"private": true,
 	"scripts": {
 		"dev": "npm run pyodide:fetch && vite dev --host",
@@ -20,30 +20,31 @@
 		"pyodide:fetch": "node scripts/prepare-pyodide.js"
 	},
 	"devDependencies": {
-		"@sveltejs/adapter-auto": "^2.0.0",
-		"@sveltejs/adapter-static": "^2.0.3",
-		"@sveltejs/kit": "^1.30.0",
-		"@tailwindcss/typography": "^0.5.10",
+		"@sveltejs/adapter-auto": "3.2.2",
+		"@sveltejs/adapter-static": "^3.0.2",
+		"@sveltejs/kit": "^2.5.20",
+		"@sveltejs/vite-plugin-svelte": "^3.1.1",
+		"@tailwindcss/typography": "^0.5.13",
 		"@types/bun": "latest",
 		"@typescript-eslint/eslint-plugin": "^6.17.0",
 		"@typescript-eslint/parser": "^6.17.0",
 		"autoprefixer": "^10.4.16",
 		"cypress": "^13.8.1",
 		"eslint": "^8.56.0",
-		"eslint-config-prettier": "^8.5.0",
-		"eslint-plugin-cypress": "^3.0.2",
-		"eslint-plugin-svelte": "^2.30.0",
-		"i18next-parser": "^8.13.0",
+		"eslint-config-prettier": "^9.1.0",
+		"eslint-plugin-cypress": "^3.4.0",
+		"eslint-plugin-svelte": "^2.43.0",
+		"i18next-parser": "^9.0.1",
 		"postcss": "^8.4.31",
-		"prettier": "^2.8.0",
-		"prettier-plugin-svelte": "^2.10.1",
-		"svelte": "^4.0.5",
-		"svelte-check": "^3.4.3",
+		"prettier": "^3.3.3",
+		"prettier-plugin-svelte": "^3.2.6",
+		"svelte": "^4.2.18",
+		"svelte-check": "^3.8.5",
 		"svelte-confetti": "^1.3.2",
 		"tailwindcss": "^3.3.3",
 		"tslib": "^2.4.1",
-		"typescript": "^5.0.0",
-		"vite": "^4.4.2",
+		"typescript": "^5.5.4",
+		"vite": "^5.3.5",
 		"vitest": "^1.6.0"
 	},
 	"type": "module",
@@ -52,7 +53,7 @@
 		"@codemirror/lang-python": "^6.1.6",
 		"@codemirror/theme-one-dark": "^6.1.2",
 		"@pyscript/core": "^0.4.32",
-		"@sveltejs/adapter-node": "^1.3.1",
+		"@sveltejs/adapter-node": "^2.0.0",
 		"async": "^3.2.5",
 		"bits-ui": "^0.19.7",
 		"codemirror": "^6.0.1",
@@ -77,5 +78,9 @@
 		"tippy.js": "^6.3.7",
 		"turndown": "^7.2.0",
 		"uuid": "^9.0.1"
+	},
+	"engines": {
+		"node": ">=18.13.0 <=21.x.x",
+		"npm": ">=6.0.0"
 	}
 }

+ 1 - 1
pyproject.toml

@@ -38,7 +38,7 @@ dependencies = [
 
     "openai",
     "anthropic",
-    "google-generativeai==0.5.4",
+    "google-generativeai==0.7.2",
     "tiktoken",
 
     "langchain==0.2.11",

+ 9 - 8
requirements-dev.lock

@@ -57,13 +57,13 @@ beautifulsoup4==4.12.3
     # via unstructured
 bidict==0.23.1
     # via python-socketio
-black==24.4.2
+black==24.8.0
     # via open-webui
 blinker==1.8.2
     # via flask
-boto3==1.34.110
+boto3==1.34.153
     # via open-webui
-botocore==1.34.110
+botocore==1.34.155
     # via boto3
     # via s3transfer
 build==1.2.1
@@ -179,7 +179,7 @@ frozenlist==1.4.1
 fsspec==2024.3.1
     # via huggingface-hub
     # via torch
-google-ai-generativelanguage==0.6.4
+google-ai-generativelanguage==0.6.6
     # via google-generativeai
 google-api-core==2.19.0
     # via google-ai-generativelanguage
@@ -196,7 +196,7 @@ google-auth==2.29.0
     # via kubernetes
 google-auth-httplib2==0.2.0
     # via google-api-python-client
-google-generativeai==0.5.4
+google-generativeai==0.7.2
     # via open-webui
 googleapis-common-protos==1.63.0
     # via google-api-core
@@ -502,7 +502,7 @@ pypandoc==1.13
 pyparsing==2.4.7
     # via httplib2
     # via oletools
-pypdf==4.2.0
+pypdf==4.3.1
     # via open-webui
     # via unstructured-client
 pypika==0.48.9
@@ -533,7 +533,7 @@ python-magic==0.4.27
 python-multipart==0.0.9
     # via fastapi
     # via open-webui
-python-pptx==0.6.23
+python-pptx==1.0.0
     # via open-webui
 python-socketio==5.11.3
     # via open-webui
@@ -684,6 +684,7 @@ typing-extensions==4.11.0
     # via opentelemetry-sdk
     # via pydantic
     # via pydantic-core
+    # via python-pptx
     # via sqlalchemy
     # via torch
     # via typer
@@ -718,7 +719,7 @@ uvicorn==0.22.0
     # via open-webui
 uvloop==0.19.0
     # via uvicorn
-validators==0.28.1
+validators==0.33.0
     # via open-webui
 watchfiles==0.21.0
     # via uvicorn

+ 9 - 8
requirements.lock

@@ -57,13 +57,13 @@ beautifulsoup4==4.12.3
     # via unstructured
 bidict==0.23.1
     # via python-socketio
-black==24.4.2
+black==24.8.0
     # via open-webui
 blinker==1.8.2
     # via flask
-boto3==1.34.110
+boto3==1.34.153
     # via open-webui
-botocore==1.34.110
+botocore==1.34.155
     # via boto3
     # via s3transfer
 build==1.2.1
@@ -179,7 +179,7 @@ frozenlist==1.4.1
 fsspec==2024.3.1
     # via huggingface-hub
     # via torch
-google-ai-generativelanguage==0.6.4
+google-ai-generativelanguage==0.6.6
     # via google-generativeai
 google-api-core==2.19.0
     # via google-ai-generativelanguage
@@ -196,7 +196,7 @@ google-auth==2.29.0
     # via kubernetes
 google-auth-httplib2==0.2.0
     # via google-api-python-client
-google-generativeai==0.5.4
+google-generativeai==0.7.2
     # via open-webui
 googleapis-common-protos==1.63.0
     # via google-api-core
@@ -502,7 +502,7 @@ pypandoc==1.13
 pyparsing==2.4.7
     # via httplib2
     # via oletools
-pypdf==4.2.0
+pypdf==4.3.1
     # via open-webui
     # via unstructured-client
 pypika==0.48.9
@@ -533,7 +533,7 @@ python-magic==0.4.27
 python-multipart==0.0.9
     # via fastapi
     # via open-webui
-python-pptx==0.6.23
+python-pptx==1.0.0
     # via open-webui
 python-socketio==5.11.3
     # via open-webui
@@ -684,6 +684,7 @@ typing-extensions==4.11.0
     # via opentelemetry-sdk
     # via pydantic
     # via pydantic-core
+    # via python-pptx
     # via sqlalchemy
     # via torch
     # via typer
@@ -718,7 +719,7 @@ uvicorn==0.22.0
     # via open-webui
 uvloop==0.19.0
     # via uvicorn
-validators==0.28.1
+validators==0.33.0
     # via open-webui
 watchfiles==0.21.0
     # via uvicorn

+ 1 - 0
src/lib/apis/index.ts

@@ -69,6 +69,7 @@ type ChatCompletedForm = {
 	model: string;
 	messages: string[];
 	chat_id: string;
+	session_id: string;
 };
 
 export const chatCompleted = async (token: string, body: ChatCompletedForm) => {

+ 30 - 30
src/lib/components/chat/Messages/CompareMessages.svelte

@@ -118,47 +118,47 @@
 								currentMessageId = message.id;
 								let messageId = message.id;
 								console.log(messageId);
-
 								//
 								let messageChildrenIds = history.messages[messageId].childrenIds;
 								while (messageChildrenIds.length !== 0) {
 									messageId = messageChildrenIds.at(-1);
 									messageChildrenIds = history.messages[messageId].childrenIds;
 								}
-
 								history.currentId = messageId;
 								dispatch('change');
 							}
 						}}
 					>
-						<ResponseMessage
-							message={groupedMessages[model].messages[groupedMessagesIdx[model]]}
-							siblings={groupedMessages[model].messages.map((m) => m.id)}
-							isLastMessage={true}
-							{updateChatMessages}
-							{confirmEditResponseMessage}
-							showPreviousMessage={() => showPreviousMessage(model)}
-							showNextMessage={() => showNextMessage(model)}
-							{readOnly}
-							{rateMessage}
-							{copyToClipboard}
-							{continueGeneration}
-							regenerateResponse={async (message) => {
-								regenerateResponse(message);
-								await tick();
-								groupedMessagesIdx[model] = groupedMessages[model].messages.length - 1;
-							}}
-							on:save={async (e) => {
-								console.log('save', e);
-
-								const message = e.detail;
-								history.messages[message.id] = message;
-								await updateChatById(localStorage.token, chatId, {
-									messages: messages,
-									history: history
-								});
-							}}
-						/>
+						{#key history.currentId}
+							<ResponseMessage
+								message={groupedMessages[model].messages[groupedMessagesIdx[model]]}
+								siblings={groupedMessages[model].messages.map((m) => m.id)}
+								isLastMessage={true}
+								{updateChatMessages}
+								{confirmEditResponseMessage}
+								showPreviousMessage={() => showPreviousMessage(model)}
+								showNextMessage={() => showNextMessage(model)}
+								{readOnly}
+								{rateMessage}
+								{copyToClipboard}
+								{continueGeneration}
+								regenerateResponse={async (message) => {
+									regenerateResponse(message);
+									await tick();
+									groupedMessagesIdx[model] = groupedMessages[model].messages.length - 1;
+								}}
+								on:save={async (e) => {
+									console.log('save', e);
+
+									const message = e.detail;
+									history.messages[message.id] = message;
+									await updateChatById(localStorage.token, chatId, {
+										messages: messages,
+										history: history
+									});
+								}}
+							/>
+						{/key}
 					</div>
 				{/if}
 			{/each}

+ 0 - 85
src/lib/components/chat/Messages/MarkdownTokens.svelte

@@ -125,91 +125,6 @@
 					code={revertSanitizedResponseContent(token?.text ?? '')}
 				/>
 			{/if}
-			<!-- {:else if token.type === 'heading'}
-		<svelte:element this={headerComponent(token.depth)}>
-			<MarkdownInlineTokens id={`${id}-${tokenIdx}-h`} tokens={token.tokens} />
-		</svelte:element>
-	{:else if token.type === 'hr'}
-		<hr />
-	{:else if token.type === 'blockquote'}
-		<blockquote>
-			<svelte:self id={`${id}-${tokenIdx}`} tokens={token.tokens} />
-		</blockquote>
-	{:else if token.type === 'html'}
-		{@html token.text}
-	{:else if token.type === 'paragraph'}
-		<p>
-			<MarkdownInlineTokens id={`${id}-${tokenIdx}-p`} tokens={token.tokens ?? []} />
-		</p>
-	{:else if token.type === 'list'}
-		{#if token.ordered}
-			<ol start={token.start || 1}>
-				{#each token.items as item, itemIdx}
-					<li>
-						<svelte:self
-							id={`${id}-${tokenIdx}-${itemIdx}`}
-							tokens={item.tokens}
-							top={token.loose}
-						/>
-					</li>
-				{/each}
-			</ol>
-		{:else}
-			<ul>
-				{#each token.items as item, itemIdx}
-					<li>
-						<svelte:self
-							id={`${id}-${tokenIdx}-${itemIdx}`}
-							tokens={item.tokens}
-							top={token.loose}
-						/>
-					</li>
-				{/each}
-			</ul>
-		{/if}
-	{:else if token.type === 'table'}
-		<table>
-			<thead>
-				<tr>
-					{#each token.header as header, headerIdx}
-						<th style={token.align[headerIdx] ? '' : `text-align: ${token.align[headerIdx]}`}>
-							<MarkdownInlineTokens
-								id={`${id}-${tokenIdx}-header-${headerIdx}`}
-								tokens={header.tokens}
-							/>
-						</th>
-					{/each}
-				</tr>
-			</thead>
-			<tbody>
-				{#each token.rows as row, rowIdx}
-					<tr>
-						{#each row ?? [] as cell, cellIdx}
-							<td style={token.align[cellIdx] ? '' : `text-align: ${token.align[cellIdx]}`}>
-								<MarkdownInlineTokens
-									id={`${id}-${tokenIdx}-row-${rowIdx}-${cellIdx}`}
-									tokens={cell.tokens}
-								/>
-							</td>
-						{/each}
-					</tr>
-				{/each}
-			</tbody>
-		</table>
-	{:else if token.type === 'text'} -->
-			<!-- {#if top}
-			<p>
-				{#if token.tokens}
-					<MarkdownInlineTokens id={`${id}-${tokenIdx}-t`} tokens={token.tokens} />
-				{:else}
-					{unescapeHtml(token.text)}
-				{/if}
-			</p>
-		{:else if token.tokens}
-			<MarkdownInlineTokens id={`${id}-${tokenIdx}-p`} tokens={token.tokens ?? []} />
-		{:else}
-			{unescapeHtml(token.text)}
-		{/if} -->
 		{:else}
 			{@html marked.parse(token.raw, {
 				...defaults,

+ 19 - 0
src/routes/+layout.svelte

@@ -111,6 +111,10 @@
 
 			if ($config) {
 				const _socket = io(`${WEBUI_BASE_URL}` || undefined, {
+					reconnection: true,
+					reconnectionDelay: 1000,
+					reconnectionDelayMax: 5000,
+					randomizationFactor: 0.5,
 					path: '/ws/socket.io',
 					auth: { token: localStorage.token }
 				});
@@ -119,6 +123,21 @@
 					console.log('connected');
 				});
 
+				_socket.on('reconnect_attempt', (attempt) => {
+					console.log('reconnect_attempt', attempt);
+				});
+
+				_socket.on('reconnect_failed', () => {
+					console.log('reconnect_failed');
+				});
+
+				_socket.on('disconnect', (reason, details) => {
+					console.log(`Socket ${socket.id} disconnected due to ${reason}`);
+					if (details) {
+						console.log('Additional details:', details);
+					}
+				});
+
 				await socket.set(_socket);
 
 				_socket.on('user-count', (data) => {

+ 1 - 1
svelte.config.js

@@ -1,5 +1,5 @@
 import adapter from '@sveltejs/adapter-static';
-import { vitePreprocess } from '@sveltejs/kit/vite';
+import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
 
 /** @type {import('@sveltejs/kit').Config} */
 const config = {

Някои файлове не бяха показани, защото твърде много файлове са промени