mirror of
https://github.com/open-webui/open-webui
synced 2025-06-26 18:26:48 +00:00
Merge remote-tracking branch 'upstream/dev' into feat/oauth
This commit is contained in:
@@ -8,12 +8,15 @@
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
import { getModels as _getModels } from '$lib/apis';
|
||||
import { getOllamaVersion } from '$lib/apis/ollama';
|
||||
import { getPrompts } from '$lib/apis/prompts';
|
||||
|
||||
import { getDocs } from '$lib/apis/documents';
|
||||
import { getAllChatTags } from '$lib/apis/chats';
|
||||
|
||||
import { getPrompts } from '$lib/apis/prompts';
|
||||
import { getDocs } from '$lib/apis/documents';
|
||||
import { getTools } from '$lib/apis/tools';
|
||||
|
||||
import { getBanners } from '$lib/apis/configs';
|
||||
import { getUserSettings } from '$lib/apis/users';
|
||||
|
||||
import {
|
||||
user,
|
||||
showSettings,
|
||||
@@ -24,32 +27,22 @@
|
||||
tags,
|
||||
banners,
|
||||
showChangelog,
|
||||
config
|
||||
config,
|
||||
showCallOverlay,
|
||||
tools
|
||||
} from '$lib/stores';
|
||||
import { REQUIRED_OLLAMA_VERSION, WEBUI_API_BASE_URL } from '$lib/constants';
|
||||
import { compareVersion } from '$lib/utils';
|
||||
|
||||
import SettingsModal from '$lib/components/chat/SettingsModal.svelte';
|
||||
import Sidebar from '$lib/components/layout/Sidebar.svelte';
|
||||
import ShortcutsModal from '$lib/components/chat/ShortcutsModal.svelte';
|
||||
import ChangelogModal from '$lib/components/ChangelogModal.svelte';
|
||||
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
||||
import { getBanners } from '$lib/apis/configs';
|
||||
import { getUserSettings } from '$lib/apis/users';
|
||||
import Help from '$lib/components/layout/Help.svelte';
|
||||
import AccountPending from '$lib/components/layout/Overlay/AccountPending.svelte';
|
||||
import { error } from '@sveltejs/kit';
|
||||
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
let ollamaVersion = '';
|
||||
let loaded = false;
|
||||
let showShortcutsButtonElement: HTMLButtonElement;
|
||||
let DB = null;
|
||||
let localDBChats = [];
|
||||
|
||||
let showShortcuts = false;
|
||||
|
||||
const getModels = async () => {
|
||||
return _getModels(localStorage.token);
|
||||
};
|
||||
@@ -97,6 +90,9 @@
|
||||
(async () => {
|
||||
documents.set(await getDocs(localStorage.token));
|
||||
})(),
|
||||
(async () => {
|
||||
tools.set(await getTools(localStorage.token));
|
||||
})(),
|
||||
(async () => {
|
||||
banners.set(await getBanners(localStorage.token));
|
||||
})(),
|
||||
@@ -181,7 +177,6 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<Help />
|
||||
<SettingsModal bind:show={$showSettings} />
|
||||
<ChangelogModal bind:show={$showChangelog} />
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<script lang="ts">
|
||||
import Chat from '$lib/components/chat/Chat.svelte';
|
||||
import Help from '$lib/components/layout/Help.svelte';
|
||||
</script>
|
||||
|
||||
<Help />
|
||||
<Chat />
|
||||
|
||||
@@ -14,7 +14,11 @@
|
||||
</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class=" flex flex-col w-full min-h-screen max-h-screen">
|
||||
<div
|
||||
class=" flex flex-col w-full min-h-screen max-h-screen {$showSidebar
|
||||
? 'md:max-w-[calc(100%-260px)]'
|
||||
: ''}"
|
||||
>
|
||||
<div class=" px-4 pt-3 mt-0.5 mb-1">
|
||||
<div class=" flex items-center gap-1">
|
||||
<div class="{$showSidebar ? 'md:hidden' : ''} mr-1 self-start flex flex-none items-center">
|
||||
@@ -30,29 +34,29 @@
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex items-center text-xl font-semibold">{$i18n.t('Workspace')}</div>
|
||||
<div class="flex items-center text-xl font-semibold">{$i18n.t('Admin Panel')}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="px-4 my-1">
|
||||
<div class="px-4 my-1">
|
||||
<div
|
||||
class="flex scrollbar-none overflow-x-auto w-fit text-center text-sm font-medium rounded-xl bg-transparent/10 p-1"
|
||||
>
|
||||
<a
|
||||
class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes('/workspace/models')
|
||||
class="min-w-fit rounded-lg p-1.5 px-3 {['/admin', '/admin/'].includes($page.url.pathname)
|
||||
? 'bg-gray-50 dark:bg-gray-850'
|
||||
: ''} transition"
|
||||
href="/workspace/models">{$i18n.t('Models')}</a
|
||||
href="/admin">{$i18n.t('Dashboard')}</a
|
||||
>
|
||||
|
||||
<a
|
||||
class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes('/workspace/prompts')
|
||||
class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes('/admin/settings')
|
||||
? 'bg-gray-50 dark:bg-gray-850'
|
||||
: ''} transition"
|
||||
href="/workspace/prompts">{$i18n.t('Prompts')}</a
|
||||
href="/admin/settings">{$i18n.t('Settings')}</a
|
||||
>
|
||||
|
||||
<a
|
||||
<!-- <a
|
||||
class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes('/workspace/documents')
|
||||
? 'bg-gray-50 dark:bg-gray-850'
|
||||
: ''} transition"
|
||||
@@ -66,9 +70,9 @@
|
||||
? 'bg-gray-50 dark:bg-gray-850'
|
||||
: ''} transition"
|
||||
href="/workspace/playground">{$i18n.t('Playground')}</a
|
||||
>
|
||||
> -->
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
<hr class=" my-2 dark:border-gray-850" />
|
||||
|
||||
|
||||
@@ -11,17 +11,14 @@
|
||||
import { toast } from 'svelte-sonner';
|
||||
|
||||
import { updateUserRole, getUsers, deleteUserById } from '$lib/apis/users';
|
||||
import { getSignUpEnabledStatus, toggleSignUpEnabledStatus } from '$lib/apis/auths';
|
||||
|
||||
import MenuLines from '$lib/components/icons/MenuLines.svelte';
|
||||
|
||||
import EditUserModal from '$lib/components/admin/EditUserModal.svelte';
|
||||
import SettingsModal from '$lib/components/admin/SettingsModal.svelte';
|
||||
import Pagination from '$lib/components/common/Pagination.svelte';
|
||||
import ChatBubbles from '$lib/components/icons/ChatBubbles.svelte';
|
||||
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
||||
import UserChatsModal from '$lib/components/admin/UserChatsModal.svelte';
|
||||
import AddUserModal from '$lib/components/admin/AddUserModal.svelte';
|
||||
import ConfirmDialog from '$lib/components/common/ConfirmDialog.svelte';
|
||||
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
@@ -34,7 +31,7 @@
|
||||
|
||||
let page = 1;
|
||||
|
||||
let showSettingsModal = false;
|
||||
let showDeleteConfirmDialog = false;
|
||||
let showAddUserModal = false;
|
||||
|
||||
let showUserChatsModal = false;
|
||||
@@ -82,6 +79,13 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<ConfirmDialog
|
||||
bind:show={showDeleteConfirmDialog}
|
||||
on:confirm={() => {
|
||||
deleteUserHandler(selectedUser.id);
|
||||
}}
|
||||
/>
|
||||
|
||||
{#key selectedUser}
|
||||
<EditUserModal
|
||||
bind:show={showEditUserModal}
|
||||
@@ -100,7 +104,6 @@
|
||||
}}
|
||||
/>
|
||||
<UserChatsModal bind:show={showUserChatsModal} user={selectedUser} />
|
||||
<SettingsModal bind:show={showSettingsModal} />
|
||||
|
||||
{#if loaded}
|
||||
<div class="mt-0.5 mb-3 gap-1 flex flex-col md:flex-row justify-between">
|
||||
@@ -118,7 +121,7 @@
|
||||
/>
|
||||
|
||||
<div class="flex gap-0.5">
|
||||
<Tooltip content="Add User">
|
||||
<Tooltip content={$i18n.t('Add User')}>
|
||||
<button
|
||||
class=" px-2 py-2 rounded-xl border border-gray-200 dark:border-gray-600 dark:border-0 hover:bg-gray-100 dark:bg-gray-850 dark:hover:bg-gray-800 transition font-medium text-sm flex items-center space-x-1"
|
||||
on:click={() => {
|
||||
@@ -137,28 +140,6 @@
|
||||
</svg>
|
||||
</button>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip content={$i18n.t('Admin Settings')}>
|
||||
<button
|
||||
class=" px-2 py-2 rounded-xl border border-gray-200 dark:border-gray-600 dark:border-0 hover:bg-gray-100 dark:bg-gray-850 dark:hover:bg-gray-800 transition font-medium text-sm flex items-center space-x-1"
|
||||
on:click={() => {
|
||||
showSettingsModal = !showSettingsModal;
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 16 16"
|
||||
fill="currentColor"
|
||||
class="w-4 h-4"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M6.955 1.45A.5.5 0 0 1 7.452 1h1.096a.5.5 0 0 1 .497.45l.17 1.699c.484.12.94.312 1.356.562l1.321-1.081a.5.5 0 0 1 .67.033l.774.775a.5.5 0 0 1 .034.67l-1.08 1.32c.25.417.44.873.561 1.357l1.699.17a.5.5 0 0 1 .45.497v1.096a.5.5 0 0 1-.45.497l-1.699.17c-.12.484-.312.94-.562 1.356l1.082 1.322a.5.5 0 0 1-.034.67l-.774.774a.5.5 0 0 1-.67.033l-1.322-1.08c-.416.25-.872.44-1.356.561l-.17 1.699a.5.5 0 0 1-.497.45H7.452a.5.5 0 0 1-.497-.45l-.17-1.699a4.973 4.973 0 0 1-1.356-.562L4.108 13.37a.5.5 0 0 1-.67-.033l-.774-.775a.5.5 0 0 1-.034-.67l1.08-1.32a4.971 4.971 0 0 1-.561-1.357l-1.699-.17A.5.5 0 0 1 1 8.548V7.452a.5.5 0 0 1 .45-.497l1.699-.17c.12-.484.312-.94.562-1.356L2.629 4.107a.5.5 0 0 1 .034-.67l.774-.774a.5.5 0 0 1 .67-.033L5.43 3.71a4.97 4.97 0 0 1 1.356-.561l.17-1.699ZM6 8c0 .538.212 1.026.558 1.385l.057.057a2 2 0 0 0 2.828-2.828l-.058-.056A2 2 0 0 0 6 8Z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -189,7 +170,7 @@
|
||||
}
|
||||
})
|
||||
.slice((page - 1) * 20, page * 20) as user}
|
||||
<tr class="bg-white border-b dark:bg-gray-900 dark:border-gray-700 text-xs">
|
||||
<tr class="bg-white border-b dark:bg-gray-900 dark:border-gray-850 text-xs">
|
||||
<td class="px-3 py-2 min-w-[7rem] w-28">
|
||||
<button
|
||||
class=" flex items-center gap-2 text-xs px-3 py-0.5 rounded-lg {user.role ===
|
||||
@@ -284,7 +265,8 @@
|
||||
<button
|
||||
class="self-center w-fit text-sm px-2 py-2 hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
|
||||
on:click={async () => {
|
||||
deleteUserHandler(user.id);
|
||||
showDeleteConfirmDialog = true;
|
||||
selectedUser = user;
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
|
||||
5
src/routes/(app)/admin/settings/+page.svelte
Normal file
5
src/routes/(app)/admin/settings/+page.svelte
Normal file
@@ -0,0 +1,5 @@
|
||||
<script>
|
||||
import Settings from '$lib/components/admin/Settings.svelte';
|
||||
</script>
|
||||
|
||||
<Settings />
|
||||
@@ -14,7 +14,11 @@
|
||||
</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class=" flex flex-col w-full min-h-screen max-h-screen">
|
||||
<div
|
||||
class=" flex flex-col w-full min-h-screen max-h-screen {$showSidebar
|
||||
? 'md:max-w-[calc(100%-260px)]'
|
||||
: ''}"
|
||||
>
|
||||
<div class=" px-4 pt-3 mt-0.5 mb-1">
|
||||
<div class=" flex items-center gap-1">
|
||||
<div class="{$showSidebar ? 'md:hidden' : ''} mr-1 self-start flex flex-none items-center">
|
||||
@@ -61,6 +65,15 @@
|
||||
{$i18n.t('Documents')}
|
||||
</a>
|
||||
|
||||
<a
|
||||
class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes('/workspace/tools')
|
||||
? 'bg-gray-50 dark:bg-gray-850'
|
||||
: ''} transition"
|
||||
href="/workspace/tools"
|
||||
>
|
||||
{$i18n.t('Tools')}
|
||||
</a>
|
||||
|
||||
<a
|
||||
class="min-w-fit rounded-lg p-1.5 px-3 {$page.url.pathname.includes('/workspace/playground')
|
||||
? 'bg-gray-50 dark:bg-gray-850'
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { toast } from 'svelte-sonner';
|
||||
import { goto } from '$app/navigation';
|
||||
import { settings, user, config, models } from '$lib/stores';
|
||||
import { settings, user, config, models, tools } from '$lib/stores';
|
||||
|
||||
import { onMount, tick, getContext } from 'svelte';
|
||||
import { addNewModel, getModelById, getModelInfos } from '$lib/apis/models';
|
||||
@@ -11,6 +11,9 @@
|
||||
import AdvancedParams from '$lib/components/chat/Settings/Advanced/AdvancedParams.svelte';
|
||||
import Checkbox from '$lib/components/common/Checkbox.svelte';
|
||||
import Tags from '$lib/components/common/Tags.svelte';
|
||||
import Knowledge from '$lib/components/workspace/Models/Knowledge.svelte';
|
||||
import ToolsSelector from '$lib/components/workspace/Models/ToolsSelector.svelte';
|
||||
import { stringify } from 'postcss';
|
||||
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
@@ -30,11 +33,6 @@
|
||||
let id = '';
|
||||
let name = '';
|
||||
|
||||
let params = {};
|
||||
let capabilities = {
|
||||
vision: true
|
||||
};
|
||||
|
||||
let info = {
|
||||
id: '',
|
||||
base_model_id: null,
|
||||
@@ -53,14 +51,21 @@
|
||||
}
|
||||
};
|
||||
|
||||
let params = {};
|
||||
let capabilities = {
|
||||
vision: true
|
||||
};
|
||||
|
||||
let toolIds = [];
|
||||
let knowledge = [];
|
||||
|
||||
$: if (name) {
|
||||
id = name.replace(/\s+/g, '-').toLowerCase();
|
||||
}
|
||||
|
||||
let baseModel = null;
|
||||
$: {
|
||||
baseModel = $models.find((m) => m.id === info.base_model_id);
|
||||
console.log(baseModel);
|
||||
const addUsage = (base_model_id) => {
|
||||
const baseModel = $models.find((m) => m.id === base_model_id);
|
||||
|
||||
if (baseModel) {
|
||||
if (baseModel.owned_by === 'openai') {
|
||||
capabilities.usage = baseModel.info?.meta?.capabilities?.usage ?? false;
|
||||
@@ -69,7 +74,7 @@
|
||||
}
|
||||
capabilities = capabilities;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const submitHandler = async () => {
|
||||
loading = true;
|
||||
@@ -77,8 +82,24 @@
|
||||
info.id = id;
|
||||
info.name = name;
|
||||
info.meta.capabilities = capabilities;
|
||||
info.params.stop = params.stop ? params.stop.split(',').filter((s) => s.trim()) : null;
|
||||
|
||||
if (knowledge.length > 0) {
|
||||
info.meta.knowledge = knowledge;
|
||||
} else {
|
||||
if (info.meta.knowledge) {
|
||||
delete info.meta.knowledge;
|
||||
}
|
||||
}
|
||||
|
||||
if (toolIds.length > 0) {
|
||||
info.meta.toolIds = toolIds;
|
||||
} else {
|
||||
if (info.meta.toolIds) {
|
||||
delete info.meta.toolIds;
|
||||
}
|
||||
}
|
||||
|
||||
info.params.stop = params.stop ? params.stop.split(',').filter((s) => s.trim()) : null;
|
||||
Object.keys(info.params).forEach((key) => {
|
||||
if (info.params[key] === '' || info.params[key] === null) {
|
||||
delete info.params[key];
|
||||
@@ -124,15 +145,34 @@
|
||||
|
||||
id = model.id;
|
||||
|
||||
if (model.info.base_model_id) {
|
||||
const base_model = $models
|
||||
.filter((m) => !m?.preset)
|
||||
.find((m) =>
|
||||
[model.info.base_model_id, `${model.info.base_model_id}:latest`].includes(m.id)
|
||||
);
|
||||
|
||||
console.log('base_model', base_model);
|
||||
|
||||
if (!base_model) {
|
||||
model.info.base_model_id = null;
|
||||
} else if ($models.find((m) => m.id === `${model.info.base_model_id}:latest`)) {
|
||||
model.info.base_model_id = `${model.info.base_model_id}:latest`;
|
||||
}
|
||||
}
|
||||
|
||||
params = { ...params, ...model?.info?.params };
|
||||
params.stop = params?.stop ? (params?.stop ?? []).join(',') : null;
|
||||
|
||||
capabilities = { ...capabilities, ...(model?.info?.meta?.capabilities ?? {}) };
|
||||
toolIds = model?.info?.meta?.toolIds ?? [];
|
||||
|
||||
info = {
|
||||
...info,
|
||||
...model.info
|
||||
};
|
||||
|
||||
console.log(info);
|
||||
};
|
||||
|
||||
onMount(async () => {
|
||||
@@ -233,7 +273,7 @@
|
||||
<button
|
||||
class="flex space-x-1"
|
||||
on:click={() => {
|
||||
history.back();
|
||||
goto('/workspace/models');
|
||||
}}
|
||||
>
|
||||
<div class=" self-center">
|
||||
@@ -252,7 +292,7 @@
|
||||
</div>
|
||||
<div class=" self-center font-medium text-sm">{$i18n.t('Back')}</div>
|
||||
</button>
|
||||
<!-- <hr class="my-3 dark:border-gray-700" /> -->
|
||||
<!-- <hr class="my-3 dark:border-gray-850" /> -->
|
||||
|
||||
<form
|
||||
class="flex flex-col max-w-2xl mx-auto mt-4 mb-10"
|
||||
@@ -331,6 +371,9 @@
|
||||
class="px-3 py-1.5 text-sm w-full bg-transparent border dark:border-gray-600 outline-none rounded-lg"
|
||||
placeholder="Select a base model (e.g. llama3, gpt-4o)"
|
||||
bind:value={info.base_model_id}
|
||||
on:change={(e) => {
|
||||
addUsage(e.target.value);
|
||||
}}
|
||||
required
|
||||
>
|
||||
<option value={null} class=" text-gray-900">{$i18n.t('Select a base model')}</option>
|
||||
@@ -416,6 +459,7 @@
|
||||
{#if showAdvanced}
|
||||
<div class="my-2">
|
||||
<AdvancedParams
|
||||
admin={true}
|
||||
bind:params
|
||||
on:change={(e) => {
|
||||
info.params = { ...info.params, ...params };
|
||||
@@ -518,6 +562,14 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="my-2">
|
||||
<Knowledge bind:knowledge />
|
||||
</div>
|
||||
|
||||
<div class="my-2">
|
||||
<ToolsSelector bind:selectedToolIds={toolIds} tools={$tools} />
|
||||
</div>
|
||||
|
||||
<div class="my-1">
|
||||
<div class="flex w-full justify-between mb-1">
|
||||
<div class=" self-center text-sm font-semibold">{$i18n.t('Capabilities')}</div>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { onMount, getContext } from 'svelte';
|
||||
import { page } from '$app/stores';
|
||||
import { settings, user, config, models } from '$lib/stores';
|
||||
import { settings, user, config, models, tools } from '$lib/stores';
|
||||
import { splitStream } from '$lib/utils';
|
||||
|
||||
import { getModelInfos, updateModelById } from '$lib/apis/models';
|
||||
@@ -14,6 +14,8 @@
|
||||
import { getModels } from '$lib/apis';
|
||||
import Checkbox from '$lib/components/common/Checkbox.svelte';
|
||||
import Tags from '$lib/components/common/Tags.svelte';
|
||||
import Knowledge from '$lib/components/workspace/Models/Knowledge.svelte';
|
||||
import ToolsSelector from '$lib/components/workspace/Models/ToolsSelector.svelte';
|
||||
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
@@ -54,19 +56,37 @@
|
||||
};
|
||||
|
||||
let params = {};
|
||||
|
||||
let capabilities = {
|
||||
vision: true
|
||||
};
|
||||
|
||||
let knowledge = [];
|
||||
let toolIds = [];
|
||||
|
||||
const updateHandler = async () => {
|
||||
loading = true;
|
||||
|
||||
info.id = id;
|
||||
info.name = name;
|
||||
info.meta.capabilities = capabilities;
|
||||
info.params.stop = params.stop ? params.stop.split(',').filter((s) => s.trim()) : null;
|
||||
|
||||
if (knowledge.length > 0) {
|
||||
info.meta.knowledge = knowledge;
|
||||
} else {
|
||||
if (info.meta.knowledge) {
|
||||
delete info.meta.knowledge;
|
||||
}
|
||||
}
|
||||
|
||||
if (toolIds.length > 0) {
|
||||
info.meta.toolIds = toolIds;
|
||||
} else {
|
||||
if (info.meta.toolIds) {
|
||||
delete info.meta.toolIds;
|
||||
}
|
||||
}
|
||||
|
||||
info.params.stop = params.stop ? params.stop.split(',').filter((s) => s.trim()) : null;
|
||||
Object.keys(info.params).forEach((key) => {
|
||||
if (info.params[key] === '' || info.params[key] === null) {
|
||||
delete info.params[key];
|
||||
@@ -119,6 +139,14 @@
|
||||
)
|
||||
: null;
|
||||
|
||||
if (model?.info?.meta?.knowledge) {
|
||||
knowledge = [...model?.info?.meta?.knowledge];
|
||||
}
|
||||
|
||||
if (model?.info?.meta?.toolIds) {
|
||||
toolIds = [...model?.info?.meta?.toolIds];
|
||||
}
|
||||
|
||||
if (model?.owned_by === 'openai') {
|
||||
capabilities.usage = false;
|
||||
}
|
||||
@@ -126,6 +154,7 @@
|
||||
if (model?.info?.meta?.capabilities) {
|
||||
capabilities = { ...capabilities, ...model?.info?.meta?.capabilities };
|
||||
}
|
||||
|
||||
console.log(model);
|
||||
} else {
|
||||
goto('/workspace/models');
|
||||
@@ -205,7 +234,7 @@
|
||||
<button
|
||||
class="flex space-x-1"
|
||||
on:click={() => {
|
||||
history.back();
|
||||
goto('/workspace/models');
|
||||
}}
|
||||
>
|
||||
<div class=" self-center">
|
||||
@@ -393,6 +422,7 @@
|
||||
{#if showAdvanced}
|
||||
<div class="my-2">
|
||||
<AdvancedParams
|
||||
admin={true}
|
||||
bind:params
|
||||
on:change={(e) => {
|
||||
info.params = { ...info.params, ...params };
|
||||
@@ -405,7 +435,7 @@
|
||||
|
||||
<hr class=" dark:border-gray-850 my-1" />
|
||||
|
||||
<div class="my-1">
|
||||
<div class="my-2">
|
||||
<div class="flex w-full justify-between items-center">
|
||||
<div class="flex w-full justify-between items-center">
|
||||
<div class=" self-center text-sm font-semibold">{$i18n.t('Prompt suggestions')}</div>
|
||||
@@ -495,7 +525,15 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="my-1">
|
||||
<div class="my-2">
|
||||
<Knowledge bind:knowledge />
|
||||
</div>
|
||||
|
||||
<div class="my-2">
|
||||
<ToolsSelector bind:selectedToolIds={toolIds} tools={$tools} />
|
||||
</div>
|
||||
|
||||
<div class="my-2">
|
||||
<div class="flex w-full justify-between mb-1">
|
||||
<div class=" self-center text-sm font-semibold">{$i18n.t('Capabilities')}</div>
|
||||
</div>
|
||||
|
||||
5
src/routes/(app)/workspace/tools/+page.svelte
Normal file
5
src/routes/(app)/workspace/tools/+page.svelte
Normal file
@@ -0,0 +1,5 @@
|
||||
<script>
|
||||
import Tools from '$lib/components/workspace/Tools.svelte';
|
||||
</script>
|
||||
|
||||
<Tools />
|
||||
57
src/routes/(app)/workspace/tools/create/+page.svelte
Normal file
57
src/routes/(app)/workspace/tools/create/+page.svelte
Normal file
@@ -0,0 +1,57 @@
|
||||
<script>
|
||||
import { goto } from '$app/navigation';
|
||||
import { createNewTool, getTools } from '$lib/apis/tools';
|
||||
import ToolkitEditor from '$lib/components/workspace/Tools/ToolkitEditor.svelte';
|
||||
import { tools } from '$lib/stores';
|
||||
import { onMount } from 'svelte';
|
||||
import { toast } from 'svelte-sonner';
|
||||
|
||||
let mounted = false;
|
||||
let clone = false;
|
||||
let tool = null;
|
||||
|
||||
const saveHandler = async (data) => {
|
||||
console.log(data);
|
||||
const res = await createNewTool(localStorage.token, {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
meta: data.meta,
|
||||
content: data.content
|
||||
}).catch((error) => {
|
||||
toast.error(error);
|
||||
return null;
|
||||
});
|
||||
|
||||
if (res) {
|
||||
toast.success('Tool created successfully');
|
||||
tools.set(await getTools(localStorage.token));
|
||||
|
||||
await goto('/workspace/tools');
|
||||
}
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
if (sessionStorage.tool) {
|
||||
tool = JSON.parse(sessionStorage.tool);
|
||||
sessionStorage.removeItem('tool');
|
||||
|
||||
console.log(tool);
|
||||
clone = true;
|
||||
}
|
||||
|
||||
mounted = true;
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if mounted}
|
||||
<ToolkitEditor
|
||||
id={tool?.id ?? ''}
|
||||
name={tool?.name ?? ''}
|
||||
meta={tool?.meta ?? { description: '' }}
|
||||
content={tool?.content ?? ''}
|
||||
{clone}
|
||||
on:save={(e) => {
|
||||
saveHandler(e.detail);
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
66
src/routes/(app)/workspace/tools/edit/+page.svelte
Normal file
66
src/routes/(app)/workspace/tools/edit/+page.svelte
Normal file
@@ -0,0 +1,66 @@
|
||||
<script>
|
||||
import { goto } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import { getToolById, getTools, updateToolById } from '$lib/apis/tools';
|
||||
import Spinner from '$lib/components/common/Spinner.svelte';
|
||||
import ToolkitEditor from '$lib/components/workspace/Tools/ToolkitEditor.svelte';
|
||||
import { tools } from '$lib/stores';
|
||||
import { onMount } from 'svelte';
|
||||
import { toast } from 'svelte-sonner';
|
||||
|
||||
let tool = null;
|
||||
|
||||
const saveHandler = async (data) => {
|
||||
console.log(data);
|
||||
const res = await updateToolById(localStorage.token, tool.id, {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
meta: data.meta,
|
||||
content: data.content
|
||||
}).catch((error) => {
|
||||
toast.error(error);
|
||||
return null;
|
||||
});
|
||||
|
||||
if (res) {
|
||||
toast.success('Tool updated successfully');
|
||||
tools.set(await getTools(localStorage.token));
|
||||
|
||||
// await goto('/workspace/tools');
|
||||
}
|
||||
};
|
||||
|
||||
onMount(async () => {
|
||||
console.log('mounted');
|
||||
const id = $page.url.searchParams.get('id');
|
||||
|
||||
if (id) {
|
||||
tool = await getToolById(localStorage.token, id).catch((error) => {
|
||||
toast.error(error);
|
||||
goto('/workspace/tools');
|
||||
return null;
|
||||
});
|
||||
|
||||
console.log(tool);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if tool}
|
||||
<ToolkitEditor
|
||||
edit={true}
|
||||
id={tool.id}
|
||||
name={tool.name}
|
||||
meta={tool.meta}
|
||||
content={tool.content}
|
||||
on:save={(e) => {
|
||||
saveHandler(e.detail);
|
||||
}}
|
||||
/>
|
||||
{:else}
|
||||
<div class="flex items-center justify-center h-full">
|
||||
<div class=" pb-16">
|
||||
<Spinner />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -1,5 +1,10 @@
|
||||
<script>
|
||||
import { io } from 'socket.io-client';
|
||||
import { spring } from 'svelte/motion';
|
||||
|
||||
let loadingProgress = spring(0, {
|
||||
stiffness: 0.05
|
||||
});
|
||||
|
||||
import { onMount, tick, setContext } from 'svelte';
|
||||
import {
|
||||
@@ -121,8 +126,35 @@
|
||||
|
||||
await tick();
|
||||
|
||||
document.getElementById('splash-screen')?.remove();
|
||||
loaded = true;
|
||||
if (
|
||||
document.documentElement.classList.contains('her') &&
|
||||
document.getElementById('progress-bar')
|
||||
) {
|
||||
loadingProgress.subscribe((value) => {
|
||||
const progressBar = document.getElementById('progress-bar');
|
||||
|
||||
if (progressBar) {
|
||||
progressBar.style.width = `${value}%`;
|
||||
}
|
||||
});
|
||||
|
||||
await loadingProgress.set(100);
|
||||
|
||||
document.getElementById('splash-screen')?.remove();
|
||||
|
||||
const audio = new Audio(`/audio/greeting.mp3`);
|
||||
const playAudio = () => {
|
||||
audio.play();
|
||||
document.removeEventListener('click', playAudio);
|
||||
};
|
||||
|
||||
document.addEventListener('click', playAudio);
|
||||
|
||||
loaded = true;
|
||||
} else {
|
||||
document.getElementById('splash-screen')?.remove();
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', onResize);
|
||||
|
||||
@@ -135,7 +135,7 @@
|
||||
{#if ($config?.features.auth_trusted_header ?? false) || $config?.features.auth === false}
|
||||
<div class=" my-auto pb-10 w-full">
|
||||
<div
|
||||
class="flex items-center justify-center gap-3 text-xl sm:text-2xl text-center font-bold dark:text-gray-200"
|
||||
class="flex items-center justify-center gap-3 text-xl sm:text-2xl text-center font-medium dark:text-gray-200"
|
||||
>
|
||||
<div>
|
||||
{$i18n.t('Signing in')}
|
||||
@@ -157,7 +157,7 @@
|
||||
}}
|
||||
>
|
||||
<div class="mb-1">
|
||||
<div class=" text-2xl font-bold">
|
||||
<div class=" text-2xl font-medium">
|
||||
{mode === 'signin' ? $i18n.t('Sign in') : $i18n.t('Sign up')}
|
||||
{$i18n.t('to')}
|
||||
{$WEBUI_NAME}
|
||||
@@ -176,7 +176,7 @@
|
||||
<div class="flex flex-col mt-4">
|
||||
{#if mode === 'signup'}
|
||||
<div>
|
||||
<div class=" text-sm font-semibold text-left mb-1">{$i18n.t('Name')}</div>
|
||||
<div class=" text-sm font-medium text-left mb-1">{$i18n.t('Name')}</div>
|
||||
<input
|
||||
bind:value={name}
|
||||
type="text"
|
||||
@@ -191,7 +191,7 @@
|
||||
{/if}
|
||||
|
||||
<div class="mb-2">
|
||||
<div class=" text-sm font-semibold text-left mb-1">{$i18n.t('Email')}</div>
|
||||
<div class=" text-sm font-medium text-left mb-1">{$i18n.t('Email')}</div>
|
||||
<input
|
||||
bind:value={email}
|
||||
type="email"
|
||||
@@ -203,7 +203,7 @@
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class=" text-sm font-semibold text-left mb-1">{$i18n.t('Password')}</div>
|
||||
<div class=" text-sm font-medium text-left mb-1">{$i18n.t('Password')}</div>
|
||||
|
||||
<input
|
||||
bind:value={password}
|
||||
@@ -218,7 +218,7 @@
|
||||
|
||||
<div class="mt-5">
|
||||
<button
|
||||
class=" bg-gray-900 hover:bg-gray-800 w-full rounded-2xl text-white font-semibold text-sm py-3 transition"
|
||||
class=" bg-gray-900 hover:bg-gray-800 w-full rounded-2xl text-white font-medium text-sm py-3 transition"
|
||||
type="submit"
|
||||
>
|
||||
{mode === 'signin' ? $i18n.t('Sign in') : $i18n.t('Create Account')}
|
||||
|
||||
Reference in New Issue
Block a user