mirror of
https://github.com/open-webui/open-webui
synced 2025-04-16 05:22:46 +00:00
refac
This commit is contained in:
parent
153413dc54
commit
8daa549146
@ -685,13 +685,13 @@ Path(CACHE_DIR).mkdir(parents=True, exist_ok=True)
|
|||||||
|
|
||||||
|
|
||||||
####################################
|
####################################
|
||||||
# DIRECT API
|
# DIRECT CONNECTIONS
|
||||||
####################################
|
####################################
|
||||||
|
|
||||||
ENABLE_DIRECT_API = PersistentConfig(
|
ENABLE_DIRECT_CONNECTIONS = PersistentConfig(
|
||||||
"ENABLE_DIRECT_API",
|
"ENABLE_DIRECT_CONNECTIONS",
|
||||||
"direct.enable",
|
"direct.enable",
|
||||||
os.environ.get("ENABLE_DIRECT_API", "True").lower() == "true",
|
os.environ.get("ENABLE_DIRECT_CONNECTIONS", "True").lower() == "true",
|
||||||
)
|
)
|
||||||
|
|
||||||
####################################
|
####################################
|
||||||
|
@ -97,8 +97,8 @@ from open_webui.config import (
|
|||||||
OPENAI_API_BASE_URLS,
|
OPENAI_API_BASE_URLS,
|
||||||
OPENAI_API_KEYS,
|
OPENAI_API_KEYS,
|
||||||
OPENAI_API_CONFIGS,
|
OPENAI_API_CONFIGS,
|
||||||
# Direct API
|
# Direct Connections
|
||||||
ENABLE_DIRECT_API,
|
ENABLE_DIRECT_CONNECTIONS,
|
||||||
# Code Interpreter
|
# Code Interpreter
|
||||||
ENABLE_CODE_INTERPRETER,
|
ENABLE_CODE_INTERPRETER,
|
||||||
CODE_INTERPRETER_ENGINE,
|
CODE_INTERPRETER_ENGINE,
|
||||||
@ -407,11 +407,11 @@ app.state.OPENAI_MODELS = {}
|
|||||||
|
|
||||||
########################################
|
########################################
|
||||||
#
|
#
|
||||||
# DIRECT API
|
# DIRECT CONNECTIONS
|
||||||
#
|
#
|
||||||
########################################
|
########################################
|
||||||
|
|
||||||
app.state.config.ENABLE_DIRECT_API = ENABLE_DIRECT_API
|
app.state.config.ENABLE_DIRECT_CONNECTIONS = ENABLE_DIRECT_CONNECTIONS
|
||||||
|
|
||||||
########################################
|
########################################
|
||||||
#
|
#
|
||||||
@ -1056,7 +1056,7 @@ async def get_app_config(request: Request):
|
|||||||
"enable_websocket": ENABLE_WEBSOCKET_SUPPORT,
|
"enable_websocket": ENABLE_WEBSOCKET_SUPPORT,
|
||||||
**(
|
**(
|
||||||
{
|
{
|
||||||
"enable_direct_api": app.state.config.ENABLE_DIRECT_API,
|
"enable_direct_connections": app.state.config.ENABLE_DIRECT_CONNECTIONS,
|
||||||
"enable_channels": app.state.config.ENABLE_CHANNELS,
|
"enable_channels": app.state.config.ENABLE_CHANNELS,
|
||||||
"enable_web_search": app.state.config.ENABLE_RAG_WEB_SEARCH,
|
"enable_web_search": app.state.config.ENABLE_RAG_WEB_SEARCH,
|
||||||
"enable_code_interpreter": app.state.config.ENABLE_CODE_INTERPRETER,
|
"enable_code_interpreter": app.state.config.ENABLE_CODE_INTERPRETER,
|
||||||
|
@ -37,28 +37,30 @@ async def export_config(user=Depends(get_admin_user)):
|
|||||||
|
|
||||||
|
|
||||||
############################
|
############################
|
||||||
# Direct API Config
|
# Direct Connections Config
|
||||||
############################
|
############################
|
||||||
|
|
||||||
|
|
||||||
class DirectAPIConfigForm(BaseModel):
|
class DirectAPIConfigForm(BaseModel):
|
||||||
ENABLE_DIRECT_API: bool
|
ENABLE_DIRECT_CONNECTIONS: bool
|
||||||
|
|
||||||
|
|
||||||
@router.get("/direct_api", response_model=DirectAPIConfigForm)
|
@router.get("/direct_connections", response_model=DirectAPIConfigForm)
|
||||||
async def get_direct_api_config(request: Request, user=Depends(get_admin_user)):
|
async def get_direct_connections_config(request: Request, user=Depends(get_admin_user)):
|
||||||
return {
|
return {
|
||||||
"ENABLE_DIRECT_API": request.app.state.config.ENABLE_DIRECT_API,
|
"ENABLE_DIRECT_CONNECTIONS": request.app.state.config.ENABLE_DIRECT_CONNECTIONS,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@router.post("/direct_api", response_model=DirectAPIConfigForm)
|
@router.post("/direct_connections", response_model=DirectAPIConfigForm)
|
||||||
async def set_direct_api_config(
|
async def set_direct_connections_config(
|
||||||
request: Request, form_data: DirectAPIConfigForm, user=Depends(get_admin_user)
|
request: Request, form_data: DirectAPIConfigForm, user=Depends(get_admin_user)
|
||||||
):
|
):
|
||||||
request.app.state.config.ENABLE_DIRECT_API = form_data.ENABLE_DIRECT_API
|
request.app.state.config.ENABLE_DIRECT_CONNECTIONS = (
|
||||||
|
form_data.ENABLE_DIRECT_CONNECTIONS
|
||||||
|
)
|
||||||
return {
|
return {
|
||||||
"ENABLE_DIRECT_API": request.app.state.config.ENABLE_DIRECT_API,
|
"ENABLE_DIRECT_CONNECTIONS": request.app.state.config.ENABLE_DIRECT_CONNECTIONS,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,10 +58,10 @@ export const exportConfig = async (token: string) => {
|
|||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getDirectApiConfig = async (token: string) => {
|
export const getDirectConnectionsConfig = async (token: string) => {
|
||||||
let error = null;
|
let error = null;
|
||||||
|
|
||||||
const res = await fetch(`${WEBUI_API_BASE_URL}/configs/direct_api`, {
|
const res = await fetch(`${WEBUI_API_BASE_URL}/configs/direct_connections`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@ -85,10 +85,10 @@ export const getDirectApiConfig = async (token: string) => {
|
|||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const setDirectApiConfig = async (token: string, config: object) => {
|
export const setDirectConnectionsConfig = async (token: string, config: object) => {
|
||||||
let error = null;
|
let error = null;
|
||||||
|
|
||||||
const res = await fetch(`${WEBUI_API_BASE_URL}/configs/direct_api`, {
|
const res = await fetch(`${WEBUI_API_BASE_URL}/configs/direct_connections`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
import { getOllamaConfig, updateOllamaConfig } from '$lib/apis/ollama';
|
import { getOllamaConfig, updateOllamaConfig } from '$lib/apis/ollama';
|
||||||
import { getOpenAIConfig, updateOpenAIConfig, getOpenAIModels } from '$lib/apis/openai';
|
import { getOpenAIConfig, updateOpenAIConfig, getOpenAIModels } from '$lib/apis/openai';
|
||||||
import { getModels as _getModels } from '$lib/apis';
|
import { getModels as _getModels } from '$lib/apis';
|
||||||
import { getDirectApiConfig, setDirectApiConfig } from '$lib/apis/configs';
|
import { getDirectConnectionsConfig, setDirectConnectionsConfig } from '$lib/apis/configs';
|
||||||
|
|
||||||
import { models, user } from '$lib/stores';
|
import { models, user } from '$lib/stores';
|
||||||
|
|
||||||
@ -17,7 +17,7 @@
|
|||||||
import Plus from '$lib/components/icons/Plus.svelte';
|
import Plus from '$lib/components/icons/Plus.svelte';
|
||||||
|
|
||||||
import OpenAIConnection from './Connections/OpenAIConnection.svelte';
|
import OpenAIConnection from './Connections/OpenAIConnection.svelte';
|
||||||
import AddConnectionModal from './Connections/AddConnectionModal.svelte';
|
import AddConnectionModal from '$lib/components/AddConnectionModal.svelte';
|
||||||
import OllamaConnection from './Connections/OllamaConnection.svelte';
|
import OllamaConnection from './Connections/OllamaConnection.svelte';
|
||||||
|
|
||||||
const i18n = getContext('i18n');
|
const i18n = getContext('i18n');
|
||||||
@ -38,7 +38,7 @@
|
|||||||
let ENABLE_OPENAI_API: null | boolean = null;
|
let ENABLE_OPENAI_API: null | boolean = null;
|
||||||
let ENABLE_OLLAMA_API: null | boolean = null;
|
let ENABLE_OLLAMA_API: null | boolean = null;
|
||||||
|
|
||||||
let directApiConfig = null;
|
let directConnectionsConfig = null;
|
||||||
|
|
||||||
let pipelineUrls = {};
|
let pipelineUrls = {};
|
||||||
let showAddOpenAIConnectionModal = false;
|
let showAddOpenAIConnectionModal = false;
|
||||||
@ -101,13 +101,15 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateDirectAPIHandler = async () => {
|
const updateDirectConnectionsHandler = async () => {
|
||||||
const res = await setDirectApiConfig(localStorage.token, directApiConfig).catch((error) => {
|
const res = await setDirectConnectionsConfig(localStorage.token, directConnectionsConfig).catch(
|
||||||
toast.error(`${error}`);
|
(error) => {
|
||||||
});
|
toast.error(`${error}`);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
toast.success($i18n.t('Direct API settings updated'));
|
toast.success($i18n.t('Direct Connections settings updated'));
|
||||||
await models.set(await getModels());
|
await models.set(await getModels());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -143,7 +145,7 @@
|
|||||||
openaiConfig = await getOpenAIConfig(localStorage.token);
|
openaiConfig = await getOpenAIConfig(localStorage.token);
|
||||||
})(),
|
})(),
|
||||||
(async () => {
|
(async () => {
|
||||||
directApiConfig = await getDirectApiConfig(localStorage.token);
|
directConnectionsConfig = await getDirectConnectionsConfig(localStorage.token);
|
||||||
})()
|
})()
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -191,7 +193,7 @@
|
|||||||
const submitHandler = async () => {
|
const submitHandler = async () => {
|
||||||
updateOpenAIHandler();
|
updateOpenAIHandler();
|
||||||
updateOllamaHandler();
|
updateOllamaHandler();
|
||||||
updateDirectAPIHandler();
|
updateDirectConnectionsHandler();
|
||||||
|
|
||||||
dispatch('save');
|
dispatch('save');
|
||||||
};
|
};
|
||||||
@ -210,7 +212,7 @@
|
|||||||
|
|
||||||
<form class="flex flex-col h-full justify-between text-sm" on:submit|preventDefault={submitHandler}>
|
<form class="flex flex-col h-full justify-between text-sm" on:submit|preventDefault={submitHandler}>
|
||||||
<div class=" overflow-y-scroll scrollbar-hidden h-full">
|
<div class=" overflow-y-scroll scrollbar-hidden h-full">
|
||||||
{#if ENABLE_OPENAI_API !== null && ENABLE_OLLAMA_API !== null && directApiConfig !== null}
|
{#if ENABLE_OPENAI_API !== null && ENABLE_OLLAMA_API !== null && directConnectionsConfig !== null}
|
||||||
<div class="my-2">
|
<div class="my-2">
|
||||||
<div class="mt-2 space-y-2 pr-1.5">
|
<div class="mt-2 space-y-2 pr-1.5">
|
||||||
<div class="flex justify-between items-center text-sm">
|
<div class="flex justify-between items-center text-sm">
|
||||||
@ -356,14 +358,14 @@
|
|||||||
|
|
||||||
<div class="pr-1.5 my-2">
|
<div class="pr-1.5 my-2">
|
||||||
<div class="flex justify-between items-center text-sm">
|
<div class="flex justify-between items-center text-sm">
|
||||||
<div class=" font-medium">{$i18n.t('Direct API')}</div>
|
<div class=" font-medium">{$i18n.t('Direct Connections')}</div>
|
||||||
|
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="">
|
<div class="">
|
||||||
<Switch
|
<Switch
|
||||||
bind:state={directApiConfig.ENABLE_DIRECT_API}
|
bind:state={directConnectionsConfig.ENABLE_DIRECT_CONNECTIONS}
|
||||||
on:change={async () => {
|
on:change={async () => {
|
||||||
updateDirectAPIHandler();
|
updateDirectConnectionsHandler();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -372,7 +374,9 @@
|
|||||||
|
|
||||||
<div class="mt-1.5">
|
<div class="mt-1.5">
|
||||||
<div class="text-xs text-gray-500">
|
<div class="text-xs text-gray-500">
|
||||||
{$i18n.t('Direct API allows users to use the models directly from their browser.')}
|
{$i18n.t(
|
||||||
|
'Direct Connections allow users to connect to their own OpenAI compatible API endpoints.'
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
||||||
import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
|
import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
|
||||||
import AddConnectionModal from './AddConnectionModal.svelte';
|
import AddConnectionModal from '$lib/components/AddConnectionModal.svelte';
|
||||||
|
|
||||||
import Cog6 from '$lib/components/icons/Cog6.svelte';
|
import Cog6 from '$lib/components/icons/Cog6.svelte';
|
||||||
import Wrench from '$lib/components/icons/Wrench.svelte';
|
import Wrench from '$lib/components/icons/Wrench.svelte';
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
||||||
import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
|
import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
|
||||||
import Cog6 from '$lib/components/icons/Cog6.svelte';
|
import Cog6 from '$lib/components/icons/Cog6.svelte';
|
||||||
import AddConnectionModal from './AddConnectionModal.svelte';
|
import AddConnectionModal from '$lib/components/AddConnectionModal.svelte';
|
||||||
|
|
||||||
import { connect } from 'socket.io-client';
|
import { connect } from 'socket.io-client';
|
||||||
|
|
||||||
export let onDelete = () => {};
|
export let onDelete = () => {};
|
||||||
|
114
src/lib/components/chat/Settings/Connections.svelte
Normal file
114
src/lib/components/chat/Settings/Connections.svelte
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { toast } from 'svelte-sonner';
|
||||||
|
import { createEventDispatcher, onMount, getContext, tick } from 'svelte';
|
||||||
|
import { getModels as _getModels } from '$lib/apis';
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
const i18n = getContext('i18n');
|
||||||
|
|
||||||
|
import { models, user } from '$lib/stores';
|
||||||
|
|
||||||
|
import Switch from '$lib/components/common/Switch.svelte';
|
||||||
|
import Spinner from '$lib/components/common/Spinner.svelte';
|
||||||
|
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
||||||
|
import Plus from '$lib/components/icons/Plus.svelte';
|
||||||
|
import Connection from './Connections/Connection.svelte';
|
||||||
|
|
||||||
|
const getModels = async () => {
|
||||||
|
const models = await _getModels(localStorage.token);
|
||||||
|
return models;
|
||||||
|
};
|
||||||
|
|
||||||
|
let config = null;
|
||||||
|
|
||||||
|
let showConnectionModal = false;
|
||||||
|
|
||||||
|
onMount(async () => {});
|
||||||
|
|
||||||
|
const submitHandler = async () => {};
|
||||||
|
const updateHandler = async () => {};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- <AddConnectionModal
|
||||||
|
bind:show={showConnectionModal}
|
||||||
|
onSubmit={addConnectionHandler}
|
||||||
|
/> -->
|
||||||
|
|
||||||
|
<form class="flex flex-col h-full justify-between text-sm" on:submit|preventDefault={submitHandler}>
|
||||||
|
<div class=" overflow-y-scroll scrollbar-hidden h-full">
|
||||||
|
<div class="my-2">
|
||||||
|
<div class="space-y-2 pr-1.5">
|
||||||
|
<div class="flex justify-between items-center text-sm">
|
||||||
|
<div class=" font-medium">{$i18n.t('Direct Connections')}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-1.5">
|
||||||
|
<div class="text-xs text-gray-500">
|
||||||
|
{$i18n.t('Connect to your own OpenAI compatible API endpoints.')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if false}
|
||||||
|
<hr class=" border-gray-50 dark:border-gray-850" />
|
||||||
|
|
||||||
|
<div class="">
|
||||||
|
<div class="flex justify-between items-center">
|
||||||
|
<div class="font-medium">{$i18n.t('Manage Connections')}</div>
|
||||||
|
|
||||||
|
<Tooltip content={$i18n.t(`Add Connection`)}>
|
||||||
|
<button
|
||||||
|
class="px-1"
|
||||||
|
on:click={() => {
|
||||||
|
showConnectionModal = true;
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<Plus />
|
||||||
|
</button>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col gap-1.5 mt-1.5">
|
||||||
|
{#each config?.OPENAI_API_BASE_URLS ?? [] as url, idx}
|
||||||
|
<Connection
|
||||||
|
bind:url
|
||||||
|
bind:key={config.OPENAI_API_KEYS[idx]}
|
||||||
|
bind:config={config.OPENAI_API_CONFIGS[idx]}
|
||||||
|
onSubmit={() => {
|
||||||
|
updateHandler();
|
||||||
|
}}
|
||||||
|
onDelete={() => {
|
||||||
|
config.OPENAI_API_BASE_URLS = config.OPENAI_API_BASE_URLS.filter(
|
||||||
|
(url, urlIdx) => idx !== urlIdx
|
||||||
|
);
|
||||||
|
config.OPENAI_API_KEYS = config.OPENAI_API_KEYS.filter(
|
||||||
|
(key, keyIdx) => idx !== keyIdx
|
||||||
|
);
|
||||||
|
|
||||||
|
let newConfig = {};
|
||||||
|
config.OPENAI_API_BASE_URLS.forEach((url, newIdx) => {
|
||||||
|
newConfig[newIdx] =
|
||||||
|
config.OPENAI_API_CONFIGS[newIdx < idx ? newIdx : newIdx + 1];
|
||||||
|
});
|
||||||
|
config.OPENAI_API_CONFIGS = newConfig;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr class=" border-gray-50 dark:border-gray-850" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-end pt-3 text-sm font-medium">
|
||||||
|
<button
|
||||||
|
class="px-3.5 py-1.5 text-sm font-medium bg-black hover:bg-gray-900 text-white dark:bg-white dark:text-black dark:hover:bg-gray-100 transition rounded-full"
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
{$i18n.t('Save')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
106
src/lib/components/chat/Settings/Connections/Connection.svelte
Normal file
106
src/lib/components/chat/Settings/Connections/Connection.svelte
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { getContext, tick } from 'svelte';
|
||||||
|
const i18n = getContext('i18n');
|
||||||
|
|
||||||
|
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
||||||
|
import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
|
||||||
|
import Cog6 from '$lib/components/icons/Cog6.svelte';
|
||||||
|
import AddConnectionModal from '$lib/components/AddConnectionModal.svelte';
|
||||||
|
|
||||||
|
export let onDelete = () => {};
|
||||||
|
export let onSubmit = () => {};
|
||||||
|
|
||||||
|
export let pipeline = false;
|
||||||
|
|
||||||
|
export let url = '';
|
||||||
|
export let key = '';
|
||||||
|
export let config = {};
|
||||||
|
|
||||||
|
let showConfigModal = false;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<AddConnectionModal
|
||||||
|
edit
|
||||||
|
bind:show={showConfigModal}
|
||||||
|
connection={{
|
||||||
|
url,
|
||||||
|
key,
|
||||||
|
config
|
||||||
|
}}
|
||||||
|
{onDelete}
|
||||||
|
onSubmit={(connection) => {
|
||||||
|
url = connection.url;
|
||||||
|
key = connection.key;
|
||||||
|
config = connection.config;
|
||||||
|
onSubmit(connection);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="flex w-full gap-2 items-center">
|
||||||
|
<Tooltip
|
||||||
|
className="w-full relative"
|
||||||
|
content={$i18n.t(`WebUI will make requests to "{{url}}/chat/completions"`, {
|
||||||
|
url
|
||||||
|
})}
|
||||||
|
placement="top-start"
|
||||||
|
>
|
||||||
|
{#if !(config?.enable ?? true)}
|
||||||
|
<div
|
||||||
|
class="absolute top-0 bottom-0 left-0 right-0 opacity-60 bg-white dark:bg-gray-900 z-10"
|
||||||
|
></div>
|
||||||
|
{/if}
|
||||||
|
<div class="flex w-full">
|
||||||
|
<div class="flex-1 relative">
|
||||||
|
<input
|
||||||
|
class=" outline-none w-full bg-transparent {pipeline ? 'pr-8' : ''}"
|
||||||
|
placeholder={$i18n.t('API Base URL')}
|
||||||
|
bind:value={url}
|
||||||
|
autocomplete="off"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{#if pipeline}
|
||||||
|
<div class=" absolute top-0.5 right-2.5">
|
||||||
|
<Tooltip content="Pipelines">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
class="size-4"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M11.644 1.59a.75.75 0 0 1 .712 0l9.75 5.25a.75.75 0 0 1 0 1.32l-9.75 5.25a.75.75 0 0 1-.712 0l-9.75-5.25a.75.75 0 0 1 0-1.32l9.75-5.25Z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m3.265 10.602 7.668 4.129a2.25 2.25 0 0 0 2.134 0l7.668-4.13 1.37.739a.75.75 0 0 1 0 1.32l-9.75 5.25a.75.75 0 0 1-.71 0l-9.75-5.25a.75.75 0 0 1 0-1.32l1.37-.738Z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m10.933 19.231-7.668-4.13-1.37.739a.75.75 0 0 0 0 1.32l9.75 5.25c.221.12.489.12.71 0l9.75-5.25a.75.75 0 0 0 0-1.32l-1.37-.738-7.668 4.13a2.25 2.25 0 0 1-2.134-.001Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<SensitiveInput
|
||||||
|
inputClassName=" outline-none bg-transparent w-full"
|
||||||
|
placeholder={$i18n.t('API Key')}
|
||||||
|
bind:value={key}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
<div class="flex gap-1">
|
||||||
|
<Tooltip content={$i18n.t('Configure')} className="self-start">
|
||||||
|
<button
|
||||||
|
class="self-center p-1 bg-transparent hover:bg-gray-100 dark:bg-gray-900 dark:hover:bg-gray-850 rounded-lg transition"
|
||||||
|
on:click={() => {
|
||||||
|
showConfigModal = true;
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<Cog6 />
|
||||||
|
</button>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { getContext, tick } from 'svelte';
|
import { getContext, tick } from 'svelte';
|
||||||
import { toast } from 'svelte-sonner';
|
import { toast } from 'svelte-sonner';
|
||||||
import { models, settings, user } from '$lib/stores';
|
import { config, models, settings, user } from '$lib/stores';
|
||||||
import { updateUserSettings } from '$lib/apis/users';
|
import { updateUserSettings } from '$lib/apis/users';
|
||||||
import { getModels as _getModels } from '$lib/apis';
|
import { getModels as _getModels } from '$lib/apis';
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
@ -17,6 +17,7 @@
|
|||||||
import Personalization from './Settings/Personalization.svelte';
|
import Personalization from './Settings/Personalization.svelte';
|
||||||
import SearchInput from '../layout/Sidebar/SearchInput.svelte';
|
import SearchInput from '../layout/Sidebar/SearchInput.svelte';
|
||||||
import Search from '../icons/Search.svelte';
|
import Search from '../icons/Search.svelte';
|
||||||
|
import Connections from './Settings/Connections.svelte';
|
||||||
|
|
||||||
const i18n = getContext('i18n');
|
const i18n = getContext('i18n');
|
||||||
|
|
||||||
@ -122,6 +123,11 @@
|
|||||||
'alwaysonwebsearch'
|
'alwaysonwebsearch'
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'connections',
|
||||||
|
title: 'Connections',
|
||||||
|
keywords: []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'personalization',
|
id: 'personalization',
|
||||||
title: 'Personalization',
|
title: 'Personalization',
|
||||||
@ -447,6 +453,32 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class=" self-center">{$i18n.t('Interface')}</div>
|
<div class=" self-center">{$i18n.t('Interface')}</div>
|
||||||
</button>
|
</button>
|
||||||
|
{:else if tabId === 'connections'}
|
||||||
|
{#if $user.role === 'admin' || ($user.role === 'user' && $config?.features?.enable_direct_connections)}
|
||||||
|
<button
|
||||||
|
class="px-0.5 py-1 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
|
||||||
|
'connections'
|
||||||
|
? ''
|
||||||
|
: ' text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'}"
|
||||||
|
on:click={() => {
|
||||||
|
selectedTab = 'connections';
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div class=" self-center mr-2">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
fill="currentColor"
|
||||||
|
class="w-4 h-4"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M1 9.5A3.5 3.5 0 0 0 4.5 13H12a3 3 0 0 0 .917-5.857 2.503 2.503 0 0 0-3.198-3.019 3.5 3.5 0 0 0-6.628 2.171A3.5 3.5 0 0 0 1 9.5Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class=" self-center">{$i18n.t('Connections')}</div>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
{:else if tabId === 'personalization'}
|
{:else if tabId === 'personalization'}
|
||||||
<button
|
<button
|
||||||
class="px-0.5 py-1 min-w-fit rounded-lg flex-1 md:flex-none flex text-left transition {selectedTab ===
|
class="px-0.5 py-1 min-w-fit rounded-lg flex-1 md:flex-none flex text-left transition {selectedTab ===
|
||||||
@ -620,6 +652,13 @@
|
|||||||
toast.success($i18n.t('Settings saved successfully!'));
|
toast.success($i18n.t('Settings saved successfully!'));
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
{:else if selectedTab === 'connections'}
|
||||||
|
<Connections
|
||||||
|
{saveSettings}
|
||||||
|
on:save={() => {
|
||||||
|
toast.success($i18n.t('Settings saved successfully!'));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
{:else if selectedTab === 'personalization'}
|
{:else if selectedTab === 'personalization'}
|
||||||
<Personalization
|
<Personalization
|
||||||
{saveSettings}
|
{saveSettings}
|
||||||
|
Loading…
Reference in New Issue
Block a user