refac
This commit is contained in:
1 parent
e8d55c0a8b
commit
5cdcdbaeec
53 files changed
+7829
-7954
No files matched your search
@@ -7,7 +7,8 @@ from typing import Optional
|
||||
import aiohttp
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request
|
||||
from mcp.shared.auth import OAuthMetadata
|
||||
from open_webui.config import BannerModel, async_save_config, get_config, save_config
|
||||
from open_webui.config import BannerModel
|
||||
from open_webui.models.config import Config
|
||||
from open_webui.env import AIOHTTP_CLIENT_SESSION_SSL, AIOHTTP_CLIENT_TIMEOUT
|
||||
from open_webui.models.oauth_sessions import OAuthSessions
|
||||
from open_webui.utils.auth import get_admin_user, get_verified_user
|
||||
@@ -34,6 +35,44 @@ router = APIRouter()
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
CONNECTIONS_CONFIG_KEYS = {
|
||||
'ENABLE_DIRECT_CONNECTIONS': 'direct.enable',
|
||||
'ENABLE_BASE_MODELS_CACHE': 'models.base_models_cache',
|
||||
}
|
||||
CODE_EXECUTION_CONFIG_KEYS = {
|
||||
'ENABLE_CODE_EXECUTION': 'code_execution.enable',
|
||||
'CODE_EXECUTION_ENGINE': 'code_execution.engine',
|
||||
'CODE_EXECUTION_JUPYTER_URL': 'code_execution.jupyter.url',
|
||||
'CODE_EXECUTION_JUPYTER_AUTH': 'code_execution.jupyter.auth',
|
||||
'CODE_EXECUTION_JUPYTER_AUTH_TOKEN': 'code_execution.jupyter.auth_token',
|
||||
'CODE_EXECUTION_JUPYTER_AUTH_PASSWORD': 'code_execution.jupyter.auth_password',
|
||||
'CODE_EXECUTION_JUPYTER_TIMEOUT': 'code_execution.jupyter.timeout',
|
||||
'ENABLE_CODE_INTERPRETER': 'code_interpreter.enable',
|
||||
'CODE_INTERPRETER_ENGINE': 'code_interpreter.engine',
|
||||
'CODE_INTERPRETER_PROMPT_TEMPLATE': 'code_interpreter.prompt_template',
|
||||
'CODE_INTERPRETER_JUPYTER_URL': 'code_interpreter.jupyter.url',
|
||||
'CODE_INTERPRETER_JUPYTER_AUTH': 'code_interpreter.jupyter.auth',
|
||||
'CODE_INTERPRETER_JUPYTER_AUTH_TOKEN': 'code_interpreter.jupyter.auth_token',
|
||||
'CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD': 'code_interpreter.jupyter.auth_password',
|
||||
'CODE_INTERPRETER_JUPYTER_TIMEOUT': 'code_interpreter.jupyter.timeout',
|
||||
}
|
||||
MODELS_CONFIG_KEYS = {
|
||||
'DEFAULT_MODELS': 'ui.default_models',
|
||||
'DEFAULT_PINNED_MODELS': 'ui.default_pinned_models',
|
||||
'MODEL_ORDER_LIST': 'ui.model_order_list',
|
||||
'DEFAULT_MODEL_METADATA': 'models.default_metadata',
|
||||
'DEFAULT_MODEL_PARAMS': 'models.default_params',
|
||||
}
|
||||
|
||||
|
||||
async def get_config_values(key_map: dict[str, str]) -> dict:
|
||||
values = await Config.get_many(*key_map.values())
|
||||
return {field: values[storage_key] for field, storage_key in key_map.items() if storage_key in values}
|
||||
|
||||
|
||||
def config_updates(data: dict, key_map: dict[str, str]) -> dict:
|
||||
return {key_map[field]: value for field, value in data.items() if field in key_map}
|
||||
|
||||
|
||||
############################
|
||||
# ImportConfig
|
||||
@@ -48,9 +87,8 @@ class ImportConfigForm(BaseModel):
|
||||
|
||||
@router.post('/import', response_model=dict)
|
||||
async def import_config(request: Request, form_data: ImportConfigForm, user=Depends(get_admin_user)):
|
||||
await async_save_config(form_data.config)
|
||||
request.app.state.config._sync_to_redis()
|
||||
return get_config()
|
||||
await Config.upsert(form_data.config)
|
||||
return await Config.get_all()
|
||||
|
||||
|
||||
############################
|
||||
@@ -60,7 +98,12 @@ async def import_config(request: Request, form_data: ImportConfigForm, user=Depe
|
||||
|
||||
@router.get('/export', response_model=dict)
|
||||
async def export_config(user=Depends(get_admin_user)):
|
||||
return get_config()
|
||||
return await Config.get_all()
|
||||
|
||||
|
||||
@router.get('/namespace/{namespace}', response_model=dict)
|
||||
async def get_config_namespace(namespace: str, user=Depends(get_admin_user)):
|
||||
return await Config.get_namespace(namespace)
|
||||
|
||||
|
||||
############################
|
||||
@@ -75,10 +118,7 @@ class ConnectionsConfigForm(BaseModel):
|
||||
|
||||
@router.get('/connections', response_model=ConnectionsConfigForm)
|
||||
async def get_connections_config(request: Request, user=Depends(get_admin_user)):
|
||||
return {
|
||||
'ENABLE_DIRECT_CONNECTIONS': request.app.state.config.ENABLE_DIRECT_CONNECTIONS,
|
||||
'ENABLE_BASE_MODELS_CACHE': request.app.state.config.ENABLE_BASE_MODELS_CACHE,
|
||||
}
|
||||
return await get_config_values(CONNECTIONS_CONFIG_KEYS)
|
||||
|
||||
|
||||
@router.post('/connections', response_model=ConnectionsConfigForm)
|
||||
@@ -87,13 +127,8 @@ async def set_connections_config(
|
||||
form_data: ConnectionsConfigForm,
|
||||
user=Depends(get_admin_user),
|
||||
):
|
||||
request.app.state.config.ENABLE_DIRECT_CONNECTIONS = form_data.ENABLE_DIRECT_CONNECTIONS
|
||||
request.app.state.config.ENABLE_BASE_MODELS_CACHE = form_data.ENABLE_BASE_MODELS_CACHE
|
||||
|
||||
return {
|
||||
'ENABLE_DIRECT_CONNECTIONS': request.app.state.config.ENABLE_DIRECT_CONNECTIONS,
|
||||
'ENABLE_BASE_MODELS_CACHE': request.app.state.config.ENABLE_BASE_MODELS_CACHE,
|
||||
}
|
||||
await Config.upsert(config_updates(form_data.model_dump(), CONNECTIONS_CONFIG_KEYS))
|
||||
return await get_config_values(CONNECTIONS_CONFIG_KEYS)
|
||||
|
||||
|
||||
class OAuthClientRegistrationForm(BaseModel):
|
||||
@@ -167,9 +202,7 @@ class ToolServersConfigForm(BaseModel):
|
||||
|
||||
@router.get('/tool_servers', response_model=ToolServersConfigForm)
|
||||
async def get_tool_servers_config(request: Request, user=Depends(get_admin_user)):
|
||||
return {
|
||||
'TOOL_SERVER_CONNECTIONS': request.app.state.config.TOOL_SERVER_CONNECTIONS,
|
||||
}
|
||||
return {'TOOL_SERVER_CONNECTIONS': await Config.get('tool_server.connections')}
|
||||
|
||||
|
||||
@router.post('/tool_servers', response_model=ToolServersConfigForm)
|
||||
@@ -178,7 +211,8 @@ async def set_tool_servers_config(
|
||||
form_data: ToolServersConfigForm,
|
||||
user=Depends(get_admin_user),
|
||||
):
|
||||
for connection in request.app.state.config.TOOL_SERVER_CONNECTIONS:
|
||||
existing_connections = await Config.get('tool_server.connections', []) or []
|
||||
for connection in existing_connections:
|
||||
server_type = connection.get('type', 'openapi')
|
||||
auth_type = connection.get('auth_type', 'none')
|
||||
|
||||
@@ -193,13 +227,12 @@ async def set_tool_servers_config(
|
||||
pass
|
||||
|
||||
# Set new tool server connections
|
||||
request.app.state.config.TOOL_SERVER_CONNECTIONS = [
|
||||
connection.model_dump() for connection in form_data.TOOL_SERVER_CONNECTIONS
|
||||
]
|
||||
connections = [connection.model_dump() for connection in form_data.TOOL_SERVER_CONNECTIONS]
|
||||
await Config.upsert({'tool_server.connections': connections})
|
||||
|
||||
await set_tool_servers(request)
|
||||
|
||||
for connection in request.app.state.config.TOOL_SERVER_CONNECTIONS:
|
||||
for connection in connections:
|
||||
server_type = connection.get('type', 'openapi')
|
||||
if server_type == 'mcp':
|
||||
server_id = connection.get('info', {}).get('id')
|
||||
@@ -216,9 +249,7 @@ async def set_tool_servers_config(
|
||||
log.debug(f'Failed to add OAuth client for MCP tool server: {e}')
|
||||
continue
|
||||
|
||||
return {
|
||||
'TOOL_SERVER_CONNECTIONS': request.app.state.config.TOOL_SERVER_CONNECTIONS,
|
||||
}
|
||||
return {'TOOL_SERVER_CONNECTIONS': connections}
|
||||
|
||||
|
||||
class TerminalServerConnection(BaseModel):
|
||||
@@ -249,9 +280,7 @@ class TerminalServersConfigForm(BaseModel):
|
||||
|
||||
@router.get('/terminal_servers')
|
||||
async def get_terminal_servers_config(request: Request, user=Depends(get_admin_user)):
|
||||
return {
|
||||
'TERMINAL_SERVER_CONNECTIONS': request.app.state.config.TERMINAL_SERVER_CONNECTIONS,
|
||||
}
|
||||
return {'TERMINAL_SERVER_CONNECTIONS': await Config.get('terminal_server.connections')}
|
||||
|
||||
|
||||
@router.post('/terminal_servers')
|
||||
@@ -260,15 +289,12 @@ async def set_terminal_servers_config(
|
||||
form_data: TerminalServersConfigForm,
|
||||
user=Depends(get_admin_user),
|
||||
):
|
||||
request.app.state.config.TERMINAL_SERVER_CONNECTIONS = [
|
||||
connection.model_dump() for connection in form_data.TERMINAL_SERVER_CONNECTIONS
|
||||
]
|
||||
connections = [connection.model_dump() for connection in form_data.TERMINAL_SERVER_CONNECTIONS]
|
||||
await Config.upsert({'terminal_server.connections': connections})
|
||||
|
||||
await set_terminal_servers(request)
|
||||
|
||||
return {
|
||||
'TERMINAL_SERVER_CONNECTIONS': request.app.state.config.TERMINAL_SERVER_CONNECTIONS,
|
||||
}
|
||||
return {'TERMINAL_SERVER_CONNECTIONS': connections}
|
||||
|
||||
|
||||
@router.post('/terminal_servers/verify')
|
||||
@@ -518,67 +544,15 @@ class CodeInterpreterConfigForm(BaseModel):
|
||||
|
||||
@router.get('/code_execution', response_model=CodeInterpreterConfigForm)
|
||||
async def get_code_execution_config(request: Request, user=Depends(get_admin_user)):
|
||||
return {
|
||||
'ENABLE_CODE_EXECUTION': request.app.state.config.ENABLE_CODE_EXECUTION,
|
||||
'CODE_EXECUTION_ENGINE': request.app.state.config.CODE_EXECUTION_ENGINE,
|
||||
'CODE_EXECUTION_JUPYTER_URL': request.app.state.config.CODE_EXECUTION_JUPYTER_URL,
|
||||
'CODE_EXECUTION_JUPYTER_AUTH': request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH,
|
||||
'CODE_EXECUTION_JUPYTER_AUTH_TOKEN': request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH_TOKEN,
|
||||
'CODE_EXECUTION_JUPYTER_AUTH_PASSWORD': request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH_PASSWORD,
|
||||
'CODE_EXECUTION_JUPYTER_TIMEOUT': request.app.state.config.CODE_EXECUTION_JUPYTER_TIMEOUT,
|
||||
'ENABLE_CODE_INTERPRETER': request.app.state.config.ENABLE_CODE_INTERPRETER,
|
||||
'CODE_INTERPRETER_ENGINE': request.app.state.config.CODE_INTERPRETER_ENGINE,
|
||||
'CODE_INTERPRETER_PROMPT_TEMPLATE': request.app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE,
|
||||
'CODE_INTERPRETER_JUPYTER_URL': request.app.state.config.CODE_INTERPRETER_JUPYTER_URL,
|
||||
'CODE_INTERPRETER_JUPYTER_AUTH': request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH,
|
||||
'CODE_INTERPRETER_JUPYTER_AUTH_TOKEN': request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_TOKEN,
|
||||
'CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD': request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD,
|
||||
'CODE_INTERPRETER_JUPYTER_TIMEOUT': request.app.state.config.CODE_INTERPRETER_JUPYTER_TIMEOUT,
|
||||
}
|
||||
return await get_config_values(CODE_EXECUTION_CONFIG_KEYS)
|
||||
|
||||
|
||||
@router.post('/code_execution', response_model=CodeInterpreterConfigForm)
|
||||
async def set_code_execution_config(
|
||||
request: Request, form_data: CodeInterpreterConfigForm, user=Depends(get_admin_user)
|
||||
):
|
||||
request.app.state.config.ENABLE_CODE_EXECUTION = form_data.ENABLE_CODE_EXECUTION
|
||||
|
||||
request.app.state.config.CODE_EXECUTION_ENGINE = form_data.CODE_EXECUTION_ENGINE
|
||||
request.app.state.config.CODE_EXECUTION_JUPYTER_URL = form_data.CODE_EXECUTION_JUPYTER_URL
|
||||
request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH = form_data.CODE_EXECUTION_JUPYTER_AUTH
|
||||
request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH_TOKEN = form_data.CODE_EXECUTION_JUPYTER_AUTH_TOKEN
|
||||
request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH_PASSWORD = form_data.CODE_EXECUTION_JUPYTER_AUTH_PASSWORD
|
||||
request.app.state.config.CODE_EXECUTION_JUPYTER_TIMEOUT = form_data.CODE_EXECUTION_JUPYTER_TIMEOUT
|
||||
|
||||
request.app.state.config.ENABLE_CODE_INTERPRETER = form_data.ENABLE_CODE_INTERPRETER
|
||||
request.app.state.config.CODE_INTERPRETER_ENGINE = form_data.CODE_INTERPRETER_ENGINE
|
||||
request.app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE = form_data.CODE_INTERPRETER_PROMPT_TEMPLATE
|
||||
|
||||
request.app.state.config.CODE_INTERPRETER_JUPYTER_URL = form_data.CODE_INTERPRETER_JUPYTER_URL
|
||||
|
||||
request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH = form_data.CODE_INTERPRETER_JUPYTER_AUTH
|
||||
|
||||
request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_TOKEN = form_data.CODE_INTERPRETER_JUPYTER_AUTH_TOKEN
|
||||
request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD = form_data.CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD
|
||||
request.app.state.config.CODE_INTERPRETER_JUPYTER_TIMEOUT = form_data.CODE_INTERPRETER_JUPYTER_TIMEOUT
|
||||
|
||||
return {
|
||||
'ENABLE_CODE_EXECUTION': request.app.state.config.ENABLE_CODE_EXECUTION,
|
||||
'CODE_EXECUTION_ENGINE': request.app.state.config.CODE_EXECUTION_ENGINE,
|
||||
'CODE_EXECUTION_JUPYTER_URL': request.app.state.config.CODE_EXECUTION_JUPYTER_URL,
|
||||
'CODE_EXECUTION_JUPYTER_AUTH': request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH,
|
||||
'CODE_EXECUTION_JUPYTER_AUTH_TOKEN': request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH_TOKEN,
|
||||
'CODE_EXECUTION_JUPYTER_AUTH_PASSWORD': request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH_PASSWORD,
|
||||
'CODE_EXECUTION_JUPYTER_TIMEOUT': request.app.state.config.CODE_EXECUTION_JUPYTER_TIMEOUT,
|
||||
'ENABLE_CODE_INTERPRETER': request.app.state.config.ENABLE_CODE_INTERPRETER,
|
||||
'CODE_INTERPRETER_ENGINE': request.app.state.config.CODE_INTERPRETER_ENGINE,
|
||||
'CODE_INTERPRETER_PROMPT_TEMPLATE': request.app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE,
|
||||
'CODE_INTERPRETER_JUPYTER_URL': request.app.state.config.CODE_INTERPRETER_JUPYTER_URL,
|
||||
'CODE_INTERPRETER_JUPYTER_AUTH': request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH,
|
||||
'CODE_INTERPRETER_JUPYTER_AUTH_TOKEN': request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_TOKEN,
|
||||
'CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD': request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD,
|
||||
'CODE_INTERPRETER_JUPYTER_TIMEOUT': request.app.state.config.CODE_INTERPRETER_JUPYTER_TIMEOUT,
|
||||
}
|
||||
await Config.upsert(config_updates(form_data.model_dump(), CODE_EXECUTION_CONFIG_KEYS))
|
||||
return await get_config_values(CODE_EXECUTION_CONFIG_KEYS)
|
||||
|
||||
|
||||
############################
|
||||
@@ -595,35 +569,19 @@ class ModelsConfigForm(BaseModel):
|
||||
@router.get('/models/defaults')
|
||||
async def get_models_defaults(request: Request, user=Depends(get_verified_user)):
|
||||
return {
|
||||
'DEFAULT_MODEL_METADATA': request.app.state.config.DEFAULT_MODEL_METADATA,
|
||||
'DEFAULT_MODEL_METADATA': await Config.get('models.default_metadata'),
|
||||
}
|
||||
|
||||
|
||||
@router.get('/models', response_model=ModelsConfigForm)
|
||||
async def get_models_config(request: Request, user=Depends(get_admin_user)):
|
||||
return {
|
||||
'DEFAULT_MODELS': request.app.state.config.DEFAULT_MODELS,
|
||||
'DEFAULT_PINNED_MODELS': request.app.state.config.DEFAULT_PINNED_MODELS,
|
||||
'MODEL_ORDER_LIST': request.app.state.config.MODEL_ORDER_LIST,
|
||||
'DEFAULT_MODEL_METADATA': request.app.state.config.DEFAULT_MODEL_METADATA,
|
||||
'DEFAULT_MODEL_PARAMS': request.app.state.config.DEFAULT_MODEL_PARAMS,
|
||||
}
|
||||
return await get_config_values(MODELS_CONFIG_KEYS)
|
||||
|
||||
|
||||
@router.post('/models', response_model=ModelsConfigForm)
|
||||
async def set_models_config(request: Request, form_data: ModelsConfigForm, user=Depends(get_admin_user)):
|
||||
request.app.state.config.DEFAULT_MODELS = form_data.DEFAULT_MODELS
|
||||
request.app.state.config.DEFAULT_PINNED_MODELS = form_data.DEFAULT_PINNED_MODELS
|
||||
request.app.state.config.MODEL_ORDER_LIST = form_data.MODEL_ORDER_LIST
|
||||
request.app.state.config.DEFAULT_MODEL_METADATA = form_data.DEFAULT_MODEL_METADATA
|
||||
request.app.state.config.DEFAULT_MODEL_PARAMS = form_data.DEFAULT_MODEL_PARAMS
|
||||
return {
|
||||
'DEFAULT_MODELS': request.app.state.config.DEFAULT_MODELS,
|
||||
'DEFAULT_PINNED_MODELS': request.app.state.config.DEFAULT_PINNED_MODELS,
|
||||
'MODEL_ORDER_LIST': request.app.state.config.MODEL_ORDER_LIST,
|
||||
'DEFAULT_MODEL_METADATA': request.app.state.config.DEFAULT_MODEL_METADATA,
|
||||
'DEFAULT_MODEL_PARAMS': request.app.state.config.DEFAULT_MODEL_PARAMS,
|
||||
}
|
||||
await Config.upsert(config_updates(form_data.model_dump(), MODELS_CONFIG_KEYS))
|
||||
return await get_config_values(MODELS_CONFIG_KEYS)
|
||||
|
||||
|
||||
class PromptSuggestion(BaseModel):
|
||||
@@ -642,8 +600,8 @@ async def set_default_suggestions(
|
||||
user=Depends(get_admin_user),
|
||||
):
|
||||
data = form_data.model_dump()
|
||||
request.app.state.config.DEFAULT_PROMPT_SUGGESTIONS = data['suggestions']
|
||||
return request.app.state.config.DEFAULT_PROMPT_SUGGESTIONS
|
||||
await Config.upsert({'ui.prompt_suggestions': data['suggestions']})
|
||||
return await Config.get('ui.prompt_suggestions')
|
||||
|
||||
|
||||
############################
|
||||
@@ -662,8 +620,8 @@ async def set_banners(
|
||||
user=Depends(get_admin_user),
|
||||
):
|
||||
data = form_data.model_dump()
|
||||
request.app.state.config.BANNERS = data['banners']
|
||||
return request.app.state.config.BANNERS
|
||||
await Config.upsert({'ui.banners': data['banners']})
|
||||
return await Config.get('ui.banners')
|
||||
|
||||
|
||||
@router.get('/banners', response_model=list[BannerModel])
|
||||
@@ -671,4 +629,4 @@ async def get_banners(
|
||||
request: Request,
|
||||
user=Depends(get_verified_user),
|
||||
):
|
||||
return request.app.state.config.BANNERS
|
||||
return await Config.get('ui.banners')
|
||||
Reference in new issue
Block a user