diff --git a/backend/open_webui/main.py b/backend/open_webui/main.py index f350b80a8..48e6268b5 100644 --- a/backend/open_webui/main.py +++ b/backend/open_webui/main.py @@ -951,7 +951,7 @@ async def get_app_config(request: Request): }, "google_drive": { "client_id": GOOGLE_DRIVE_CLIENT_ID.value, - "api_key": GOOGLE_DRIVE_API_KEY.value + "api_key": GOOGLE_DRIVE_API_KEY.value, }, **( { diff --git a/backend/open_webui/routers/knowledge.py b/backend/open_webui/routers/knowledge.py index 0dff2bc02..04ebcf507 100644 --- a/backend/open_webui/routers/knowledge.py +++ b/backend/open_webui/routers/knowledge.py @@ -11,7 +11,12 @@ from open_webui.models.knowledge import ( ) from open_webui.models.files import Files, FileModel from open_webui.retrieval.vector.connector import VECTOR_DB_CLIENT -from open_webui.routers.retrieval import process_file, ProcessFileForm, process_files_batch, BatchProcessFilesForm +from open_webui.routers.retrieval import ( + process_file, + ProcessFileForm, + process_files_batch, + BatchProcessFilesForm, +) from open_webui.constants import ERROR_MESSAGES @@ -519,6 +524,7 @@ async def reset_knowledge_by_id(id: str, user=Depends(get_verified_user)): # AddFilesToKnowledge ############################ + @router.post("/{id}/files/batch/add", response_model=Optional[KnowledgeFilesResponse]) def add_files_to_knowledge_batch( id: str, @@ -555,27 +561,25 @@ def add_files_to_knowledge_batch( # Process files try: - result = process_files_batch(BatchProcessFilesForm( - files=files, - collection_name=id - )) - except Exception as e: - log.error(f"add_files_to_knowledge_batch: Exception occurred: {e}", exc_info=True) - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail=str(e) + result = process_files_batch( + BatchProcessFilesForm(files=files, collection_name=id) ) - + except Exception as e: + log.error( + f"add_files_to_knowledge_batch: Exception occurred: {e}", exc_info=True + ) + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) + # Add successful files to knowledge base data = knowledge.data or {} existing_file_ids = data.get("file_ids", []) - + # Only add files that were successfully processed successful_file_ids = [r.file_id for r in result.results if r.status == "completed"] for file_id in successful_file_ids: if file_id not in existing_file_ids: existing_file_ids.append(file_id) - + data["file_ids"] = existing_file_ids knowledge = Knowledges.update_knowledge_data_by_id(id=id, data=data) @@ -587,11 +591,10 @@ def add_files_to_knowledge_batch( files=Files.get_files_by_ids(existing_file_ids), warnings={ "message": "Some files failed to process", - "errors": error_details - } + "errors": error_details, + }, ) return KnowledgeFilesResponse( - **knowledge.model_dump(), - files=Files.get_files_by_ids(existing_file_ids) + **knowledge.model_dump(), files=Files.get_files_by_ids(existing_file_ids) ) diff --git a/backend/open_webui/static/swagger-ui/swagger-ui-bundle.js b/backend/open_webui/static/swagger-ui/swagger-ui-bundle.js index b2e982f1d..dcd1c5313 100644 --- a/backend/open_webui/static/swagger-ui/swagger-ui-bundle.js +++ b/backend/open_webui/static/swagger-ui/swagger-ui-bundle.js @@ -37007,16 +37007,14 @@ Pe.createElement('span', { className: 'brace-close' }, '}') ), pe.size - ? pe - .entrySeq() - .map(([s, o]) => - Pe.createElement(xe, { - key: `${s}-${o}`, - propKey: s, - propVal: o, - propClass: 'property' - }) - ) + ? pe.entrySeq().map(([s, o]) => + Pe.createElement(xe, { + key: `${s}-${o}`, + propKey: s, + propVal: o, + propClass: 'property' + }) + ) : null ); } @@ -37167,16 +37165,14 @@ ) : null, C && z.size - ? z - .entrySeq() - .map(([s, o]) => - Pe.createElement(le, { - key: `${s}-${o}`, - propKey: s, - propVal: o, - propClass: rs - }) - ) + ? z.entrySeq().map(([s, o]) => + Pe.createElement(le, { + key: `${s}-${o}`, + propKey: s, + propVal: o, + propClass: rs + }) + ) : null, U ? Pe.createElement(ie, { source: U }) : null, Z && @@ -57290,20 +57286,18 @@ Pe.createElement( 'div', { className: 'modal-ux-content' }, - x - .valueSeq() - .map((x, j) => - Pe.createElement(C, { - key: j, - AST: w, - definitions: x, - getComponent: i, - errSelectors: u, - authSelectors: s, - authActions: o, - specSelectors: _ - }) - ) + x.valueSeq().map((x, j) => + Pe.createElement(C, { + key: j, + AST: w, + definitions: x, + getComponent: i, + errSelectors: u, + authSelectors: s, + authActions: o, + specSelectors: _ + }) + ) ) ) ) diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index 36430ed44..51fbf5804 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -630,7 +630,6 @@ ); } }} - onClose={async () => { await tick(); diff --git a/src/lib/components/chat/MessageInput/InputMenu.svelte b/src/lib/components/chat/MessageInput/InputMenu.svelte index ce72cf24f..299ebb6e3 100644 --- a/src/lib/components/chat/MessageInput/InputMenu.svelte +++ b/src/lib/components/chat/MessageInput/InputMenu.svelte @@ -161,12 +161,30 @@ }} > - - - - - - + + + + + +
{$i18n.t('Google Drive')}
diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index 6dbd90bb9..6621db8a4 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -552,31 +552,33 @@ export const removeEmojis = (str: string) => { }; export const removeFormattings = (str: string) => { - return str - // Block elements (remove completely) - .replace(/(```[\s\S]*?```)/g, '') // Code blocks - .replace(/^\|.*\|$/gm, '') // Tables - // Inline elements (preserve content) - .replace(/(?:\*\*|__)(.*?)(?:\*\*|__)/g, '$1') // Bold - .replace(/(?:[*_])(.*?)(?:[*_])/g, '$1') // Italic - .replace(/~~(.*?)~~/g, '$1') // Strikethrough - .replace(/`([^`]+)`/g, '$1') // Inline code - - // Links and images - .replace(/!?\[([^\]]*)\](?:\([^)]+\)|\[[^\]]*\])/g, '$1') // Links & images - .replace(/^\[[^\]]+\]:\s*.*$/gm, '') // Reference definitions - - // Block formatting - .replace(/^#{1,6}\s+/gm, '') // Headers - .replace(/^\s*[-*+]\s+/gm, '') // Lists - .replace(/^\s*(?:\d+\.)\s+/gm, '') // Numbered lists - .replace(/^\s*>[> ]*/gm, '') // Blockquotes - .replace(/^\s*:\s+/gm, '') // Definition lists - - // Cleanup - .replace(/\[\^[^\]]*\]/g, '') // Footnotes - .replace(/[-*_~]/g, '') // Remaining markers - .replace(/\n{2,}/g, '\n') // Multiple newlines + return ( + str + // Block elements (remove completely) + .replace(/(```[\s\S]*?```)/g, '') // Code blocks + .replace(/^\|.*\|$/gm, '') // Tables + // Inline elements (preserve content) + .replace(/(?:\*\*|__)(.*?)(?:\*\*|__)/g, '$1') // Bold + .replace(/(?:[*_])(.*?)(?:[*_])/g, '$1') // Italic + .replace(/~~(.*?)~~/g, '$1') // Strikethrough + .replace(/`([^`]+)`/g, '$1') // Inline code + + // Links and images + .replace(/!?\[([^\]]*)\](?:\([^)]+\)|\[[^\]]*\])/g, '$1') // Links & images + .replace(/^\[[^\]]+\]:\s*.*$/gm, '') // Reference definitions + + // Block formatting + .replace(/^#{1,6}\s+/gm, '') // Headers + .replace(/^\s*[-*+]\s+/gm, '') // Lists + .replace(/^\s*(?:\d+\.)\s+/gm, '') // Numbered lists + .replace(/^\s*>[> ]*/gm, '') // Blockquotes + .replace(/^\s*:\s+/gm, '') // Definition lists + + // Cleanup + .replace(/\[\^[^\]]*\]/g, '') // Footnotes + .replace(/[-*_~]/g, '') // Remaining markers + .replace(/\n{2,}/g, '\n') + ); // Multiple newlines }; export const cleanText = (content: string) => {