mirror of
https://github.com/open-webui/open-webui.git
synced 2026-03-09 07:18:29 -05:00
refac
This commit is contained in:
@@ -4,6 +4,7 @@ from typing import Optional
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
from open_webui.internal.db import Base, JSONField, get_db, get_db_context
|
||||
from open_webui.utils.misc import sanitize_metadata
|
||||
from pydantic import BaseModel, ConfigDict, model_validator
|
||||
from sqlalchemy import BigInteger, Column, String, Text, JSON
|
||||
|
||||
@@ -127,9 +128,16 @@ class FilesTable:
|
||||
self, user_id: str, form_data: FileForm, db: Optional[Session] = None
|
||||
) -> Optional[FileModel]:
|
||||
with get_db_context(db) as db:
|
||||
file_data = form_data.model_dump()
|
||||
|
||||
# Sanitize meta to remove non-JSON-serializable objects
|
||||
# (e.g. callable tool functions, MCP client instances from middleware)
|
||||
if file_data.get("meta"):
|
||||
file_data["meta"] = sanitize_metadata(file_data["meta"])
|
||||
|
||||
file = FileModel(
|
||||
**{
|
||||
**form_data.model_dump(),
|
||||
**file_data,
|
||||
"user_id": user_id,
|
||||
"created_at": int(time.time()),
|
||||
"updated_at": int(time.time()),
|
||||
|
||||
@@ -566,6 +566,51 @@ def sanitize_data_for_db(obj):
|
||||
return obj
|
||||
|
||||
|
||||
def sanitize_metadata(metadata: dict) -> dict:
|
||||
"""
|
||||
Return a JSON-safe copy of a metadata dict for database storage.
|
||||
|
||||
The middleware metadata accumulates non-serializable Python objects
|
||||
(e.g. callable tool functions, MCP client instances) that cause
|
||||
PostgreSQL JSON inserts to fail. This helper strips those out while
|
||||
preserving the primitive data needed for file-to-chat linking.
|
||||
"""
|
||||
if not isinstance(metadata, dict):
|
||||
return metadata
|
||||
|
||||
def _sanitize(obj):
|
||||
if isinstance(obj, (str, int, float, bool, type(None))):
|
||||
return obj
|
||||
if isinstance(obj, dict):
|
||||
return {
|
||||
k: _sanitize(v)
|
||||
for k, v in obj.items()
|
||||
if not callable(v) and _is_serializable(v)
|
||||
}
|
||||
if isinstance(obj, list):
|
||||
return [_sanitize(v) for v in obj if not callable(v) and _is_serializable(v)]
|
||||
if callable(obj):
|
||||
return None
|
||||
# Last resort: try to see if it's serializable
|
||||
try:
|
||||
json.dumps(obj)
|
||||
return obj
|
||||
except (TypeError, ValueError):
|
||||
return None
|
||||
|
||||
def _is_serializable(obj):
|
||||
"""Quick check whether a value can survive JSON serialization."""
|
||||
if isinstance(obj, (str, int, float, bool, type(None), dict, list)):
|
||||
return True
|
||||
try:
|
||||
json.dumps(obj)
|
||||
return True
|
||||
except (TypeError, ValueError):
|
||||
return False
|
||||
|
||||
return _sanitize(metadata)
|
||||
|
||||
|
||||
def extract_folders_after_data_docs(path):
|
||||
# Convert the path to a Path object if it's not already
|
||||
path = Path(path)
|
||||
|
||||
Reference in New Issue
Block a user