open-webui/src/routes/(app)/+layout.svelte

165 lines
3.6 KiB
Svelte
Raw Normal View History

2023-11-20 01:47:07 +00:00
<script lang="ts">
import { openDB, deleteDB } from 'idb';
2023-11-19 05:41:43 +00:00
import { onMount, tick } from 'svelte';
2023-11-20 01:47:07 +00:00
import { goto } from '$app/navigation';
import { config, user, showSettings, settings, models, db } from '$lib/stores';
import SettingsModal from '$lib/components/chat/SettingsModal.svelte';
import Sidebar from '$lib/components/layout/Sidebar.svelte';
import toast from 'svelte-french-toast';
import { OLLAMA_API_BASE_URL } from '$lib/constants';
2023-11-19 00:47:12 +00:00
2023-11-19 05:41:43 +00:00
let loaded = false;
2023-11-20 01:47:07 +00:00
const getModels = async () => {
let models = [];
const res = await fetch(`${$settings?.API_BASE_URL ?? OLLAMA_API_BASE_URL}/tags`, {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
...($settings.authHeader && { Authorization: $settings.authHeader }),
...($user && { Authorization: `Bearer ${localStorage.token}` })
}
})
.then(async (res) => {
if (!res.ok) throw await res.json();
return res.json();
})
.catch((error) => {
console.log(error);
if ('detail' in error) {
toast.error(error.detail);
} else {
toast.error('Server connection failed');
}
return null;
});
console.log(res);
models.push(...(res?.models ?? []));
// If OpenAI API Key exists
if ($settings.OPENAI_API_KEY) {
// Validate OPENAI_API_KEY
const openaiModelRes = await fetch(`https://api.openai.com/v1/models`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${$settings.OPENAI_API_KEY}`
}
})
.then(async (res) => {
if (!res.ok) throw await res.json();
return res.json();
})
.catch((error) => {
console.log(error);
toast.error(`OpenAI: ${error?.error?.message ?? 'Network Problem'}`);
return null;
});
const openAIModels = openaiModelRes?.data ?? null;
models.push(
...(openAIModels
? [
{ name: 'hr' },
...openAIModels
.map((model) => ({ name: model.id, label: 'OpenAI' }))
.filter((model) => model.name.includes('gpt'))
]
: [])
);
}
return models;
};
const getDB = async () => {
return await openDB('Chats', 1, {
upgrade(db) {
const store = db.createObjectStore('chats', {
keyPath: 'id',
autoIncrement: true
});
store.createIndex('timestamp', 'timestamp');
}
});
};
2023-11-19 05:41:43 +00:00
onMount(async () => {
if ($config && $config.auth && $user === undefined) {
await goto('/auth');
}
2023-11-20 02:00:53 +00:00
await settings.set(JSON.parse(localStorage.getItem('settings') ?? JSON.stringify($settings)));
2023-11-20 01:47:07 +00:00
let _models = await getModels();
await models.set(_models);
let _db = await getDB();
await db.set(_db);
2023-11-19 05:41:43 +00:00
await tick();
loaded = true;
});
2023-11-19 00:47:12 +00:00
</script>
2023-11-19 05:41:43 +00:00
{#if loaded}
2023-11-20 01:47:07 +00:00
<div class="app">
<div
class=" text-gray-700 dark:text-gray-100 bg-white dark:bg-gray-800 min-h-screen overflow-auto flex flex-row"
>
<Sidebar />
<SettingsModal bind:show={$showSettings} />
<slot />
</div>
</div>
2023-11-19 00:47:12 +00:00
{/if}
2023-11-20 01:47:07 +00:00
<style>
.loading {
display: inline-block;
clip-path: inset(0 1ch 0 0);
animation: l 1s steps(3) infinite;
letter-spacing: -0.5px;
}
@keyframes l {
to {
clip-path: inset(0 -1ch 0 0);
}
}
pre[class*='language-'] {
position: relative;
overflow: auto;
/* make space */
margin: 5px 0;
padding: 1.75rem 0 1.75rem 1rem;
border-radius: 10px;
}
pre[class*='language-'] button {
position: absolute;
top: 5px;
right: 5px;
font-size: 0.9rem;
padding: 0.15rem;
background-color: #828282;
border: ridge 1px #7b7b7c;
border-radius: 5px;
text-shadow: #c4c4c4 0 0 2px;
}
pre[class*='language-'] button:hover {
cursor: pointer;
background-color: #bcbabb;
}
</style>