This commit is contained in:
Timothy Jaeryang Baek committed 2026-07-15 18:03:36 -04:00
1 parent ba067258de
commit 933ab1e1cd
25 files changed
+239 -210

No files matched your search

+2 -2
View File
@@ -61,7 +61,7 @@
const inputClass = const inputClass =
'rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 py-1.5 text-gray-700 outline-hidden transition-colors placeholder:text-gray-300 focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:placeholder:text-gray-700 dark:focus:border-blue-500'; 'rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 py-1.5 text-gray-700 outline-hidden transition-colors placeholder:text-gray-300 focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:placeholder:text-gray-700 dark:focus:border-blue-500';
const selectClass = const selectClass =
'rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 py-1.5 text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500'; 'rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 pe-8 py-1.5 text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500';
const verifyOllamaHandler = async () => { const verifyOllamaHandler = async () => {
// remove trailing slash from url // remove trailing slash from url
@@ -384,7 +384,7 @@
<div class="flex-shrink-0 self-start"> <div class="flex-shrink-0 self-start">
<select <select
id="select-bearer-or-session" id="select-bearer-or-session"
class={`w-full text-sm pr-5 ${selectClass}`} class={`w-full text-sm ${selectClass}`}
bind:value={auth_type} bind:value={auth_type}
> >
<option value="none">{$i18n.t('None')}</option> <option value="none">{$i18n.t('None')}</option>
@@ -62,7 +62,7 @@
const inputClass = const inputClass =
'rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 py-1.5 text-gray-700 outline-hidden transition-colors placeholder:text-gray-300 focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:placeholder:text-gray-700 dark:focus:border-blue-500'; 'rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 py-1.5 text-gray-700 outline-hidden transition-colors placeholder:text-gray-300 focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:placeholder:text-gray-700 dark:focus:border-blue-500';
const selectClass = const selectClass =
'rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 py-1.5 text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500'; 'rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 pe-8 py-1.5 text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500';
const stringifyJson = (value: object | null | undefined) => { const stringifyJson = (value: object | null | undefined) => {
return JSON.stringify(value && Object.keys(value).length ? value : {}, null, 2); return JSON.stringify(value && Object.keys(value).length ? value : {}, null, 2);
@@ -601,10 +601,7 @@
</div> </div>
<div class="flex gap-2"> <div class="flex gap-2">
<div class="flex-shrink-0 self-start"> <div class="flex-shrink-0 self-start">
<select <select class={`w-full text-sm ${selectClass}`} bind:value={policyStorage}>
class={`w-full text-sm pr-5 ${selectClass}`}
bind:value={policyStorage}
>
<option value="ephemeral">{$i18n.t('Ephemeral')}</option> <option value="ephemeral">{$i18n.t('Ephemeral')}</option>
<option value="persistent">{$i18n.t('Persistent')}</option> <option value="persistent">{$i18n.t('Persistent')}</option>
</select> </select>
@@ -816,7 +813,7 @@
<div class="flex gap-2"> <div class="flex gap-2">
<div class="flex-shrink-0 self-start"> <div class="flex-shrink-0 self-start">
<select class={`w-full text-sm pr-5 ${selectClass}`} bind:value={auth_type}> <select class={`w-full text-sm ${selectClass}`} bind:value={auth_type}>
<option value="none">{$i18n.t('None')}</option> <option value="none">{$i18n.t('None')}</option>
<option value="bearer">{$i18n.t('Bearer')}</option> <option value="bearer">{$i18n.t('Bearer')}</option>
{#if !direct} {#if !direct}
+4 -4
View File
@@ -72,7 +72,7 @@
const inputClass = const inputClass =
'rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 py-1.5 text-gray-700 outline-hidden transition-colors placeholder:text-gray-300 focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:placeholder:text-gray-700 dark:focus:border-blue-500'; 'rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 py-1.5 text-gray-700 outline-hidden transition-colors placeholder:text-gray-300 focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:placeholder:text-gray-700 dark:focus:border-blue-500';
const selectClass = const selectClass =
'rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 py-1.5 text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500'; 'rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 pe-8 py-1.5 text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500';
const registerOAuthClientHandler = async () => { const registerOAuthClientHandler = async () => {
if (url === '') { if (url === '') {
@@ -694,7 +694,7 @@
<div class="flex-shrink-0 self-start"> <div class="flex-shrink-0 self-start">
<select <select
id="select-bearer-or-session" id="select-bearer-or-session"
class={`w-full text-sm pr-5 ${selectClass}`} class={`w-full text-sm ${selectClass}`}
bind:value={auth_type} bind:value={auth_type}
> >
<option value="none">{$i18n.t('None')}</option> <option value="none">{$i18n.t('None')}</option>
@@ -812,7 +812,7 @@
<div class="flex-shrink-0 self-start"> <div class="flex-shrink-0 self-start">
<select <select
id="select-bearer-or-session" id="select-bearer-or-session"
class={`w-full text-sm pr-5 ${selectClass}`} class={`w-full text-sm ${selectClass}`}
bind:value={spec_type} bind:value={spec_type}
> >
<option value="url">{$i18n.t('URL')}</option> <option value="url">{$i18n.t('URL')}</option>
@@ -894,7 +894,7 @@
<div class="flex flex-1 items-center"> <div class="flex flex-1 items-center">
<select <select
id="oauth-resource-parameter" id="oauth-resource-parameter"
class={`w-full text-sm pr-5 ${selectClass}`} class={`w-full text-sm ${selectClass}`}
bind:value={oauthResourceParameter} bind:value={oauthResourceParameter}
> >
<option value="auto">{$i18n.t('Automatic')}</option> <option value="auto">{$i18n.t('Automatic')}</option>
@@ -267,7 +267,7 @@
</div> </div>
<div class="flex items-center relative"> <div class="flex items-center relative">
<select <select
class="cursor-pointer w-fit pr-8 rounded-lg px-2 p-1 text-xs bg-transparent outline-hidden text-right" class="cursor-pointer w-fit pr-8 rounded-lg px-2 p-1 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
bind:value={STT_ENGINE} bind:value={STT_ENGINE}
placeholder={$i18n.t('Select an engine')} placeholder={$i18n.t('Select an engine')}
> >
@@ -285,7 +285,7 @@
<div> <div>
<div class="mt-1 flex gap-2 mb-1"> <div class="mt-1 flex gap-2 mb-1">
<input <input
class="flex-1 w-full bg-transparent outline-hidden" class="flex-1 w-full border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('API Base URL')} placeholder={$i18n.t('API Base URL')}
bind:value={STT_OPENAI_API_BASE_URL} bind:value={STT_OPENAI_API_BASE_URL}
required required
@@ -301,7 +301,7 @@
</div> </div>
<div class="flex items-center relative"> <div class="flex items-center relative">
<select <select
class="cursor-pointer w-fit pr-8 rounded-lg px-2 p-1 text-xs bg-transparent outline-hidden text-right" class="cursor-pointer w-fit pr-8 rounded-lg px-2 p-1 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
bind:value={STT_OPENAI_API_REQUEST_FORMAT} bind:value={STT_OPENAI_API_REQUEST_FORMAT}
> >
<option value="multipart">{$i18n.t('Multipart Upload')}</option> <option value="multipart">{$i18n.t('Multipart Upload')}</option>
@@ -434,7 +434,7 @@
<div> <div>
<div class="mt-1 flex gap-2 mb-1"> <div class="mt-1 flex gap-2 mb-1">
<input <input
class="flex-1 w-full bg-transparent outline-hidden" class="flex-1 w-full border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('API Base URL')} placeholder={$i18n.t('API Base URL')}
bind:value={STT_MISTRAL_API_BASE_URL} bind:value={STT_MISTRAL_API_BASE_URL}
required required
@@ -563,7 +563,7 @@
</div> </div>
<div class="flex items-center relative"> <div class="flex items-center relative">
<select <select
class="w-fit pr-8 cursor-pointer rounded-lg px-2 p-1 text-xs bg-transparent outline-hidden text-right" class="w-fit pr-8 cursor-pointer rounded-lg px-2 p-1 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
bind:value={TTS_ENGINE} bind:value={TTS_ENGINE}
placeholder={$i18n.t('Select a mode')} placeholder={$i18n.t('Select a mode')}
on:change={async (e) => { on:change={async (e) => {
@@ -597,7 +597,7 @@
<div> <div>
<div class="mt-1 flex gap-2 mb-1"> <div class="mt-1 flex gap-2 mb-1">
<input <input
class="flex-1 w-full bg-transparent outline-hidden" class="flex-1 w-full border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('API Base URL')} placeholder={$i18n.t('API Base URL')}
bind:value={TTS_OPENAI_API_BASE_URL} bind:value={TTS_OPENAI_API_BASE_URL}
required required
@@ -652,7 +652,7 @@
<div> <div>
<div class="mt-1 flex gap-2 mb-1"> <div class="mt-1 flex gap-2 mb-1">
<input <input
class="flex-1 w-full bg-transparent outline-hidden" class="flex-1 w-full border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('API Base URL')} placeholder={$i18n.t('API Base URL')}
bind:value={TTS_MISTRAL_API_BASE_URL} bind:value={TTS_MISTRAL_API_BASE_URL}
required required
@@ -913,7 +913,7 @@
</div> </div>
<div class="flex items-center relative"> <div class="flex items-center relative">
<select <select
class="w-fit pr-8 cursor-pointer rounded-lg px-2 p-1 text-xs bg-transparent outline-hidden text-right" class="w-fit pr-8 cursor-pointer rounded-lg px-2 p-1 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
aria-label={$i18n.t('Select how to split message text for TTS requests')} aria-label={$i18n.t('Select how to split message text for TTS requests')}
bind:value={TTS_SPLIT_ON} bind:value={TTS_SPLIT_ON}
> >
@@ -50,7 +50,7 @@
const textareaClass = const textareaClass =
'w-full rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 py-1.5 text-xs text-gray-700 outline-hidden transition-colors placeholder:text-gray-300 focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:placeholder:text-gray-700 dark:focus:border-blue-500'; 'w-full rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 py-1.5 text-xs text-gray-700 outline-hidden transition-colors placeholder:text-gray-300 focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:placeholder:text-gray-700 dark:focus:border-blue-500';
const selectClass = const selectClass =
'cursor-pointer bg-transparent text-xs text-gray-600 outline-hidden dark:text-gray-400'; 'h-7 rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 pe-8 text-xs text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500';
const updateLdapServerHandler = async () => { const updateLdapServerHandler = async () => {
await updateLdapConfig(localStorage.token, ENABLE_LDAP); await updateLdapConfig(localStorage.token, ENABLE_LDAP);
@@ -25,7 +25,7 @@
const inlineInputClass = const inlineInputClass =
'w-fit h-7 rounded-lg border border-transparent bg-transparent px-2 text-xs text-gray-600 outline-hidden transition-colors hover:bg-black/5 focus:border-blue-400 dark:text-gray-400 dark:hover:bg-white/5 dark:focus:border-blue-500'; 'w-fit h-7 rounded-lg border border-transparent bg-transparent px-2 text-xs text-gray-600 outline-hidden transition-colors hover:bg-black/5 focus:border-blue-400 dark:text-gray-400 dark:hover:bg-white/5 dark:focus:border-blue-500';
const selectClass = const selectClass =
'cursor-pointer bg-transparent text-xs text-gray-600 outline-hidden dark:text-gray-400'; 'h-7 rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 pe-8 text-xs text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500';
const submitHandler = async () => { const submitHandler = async () => {
const res = await setCodeExecutionConfig(localStorage.token, config); const res = await setCodeExecutionConfig(localStorage.token, config);
@@ -387,7 +387,7 @@
</div> </div>
<div class=""> <div class="">
<select <select
class="w-fit pr-8 rounded-lg px-2 text-xs bg-transparent outline-hidden text-right" class="w-fit pr-8 rounded-lg px-2 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
bind:value={RAGConfig.CONTENT_EXTRACTION_ENGINE} bind:value={RAGConfig.CONTENT_EXTRACTION_ENGINE}
> >
<option value="">{$i18n.t('Default')}</option> <option value="">{$i18n.t('Default')}</option>
@@ -429,7 +429,7 @@
</div> </div>
<div class=""> <div class="">
<select <select
class="w-fit pr-8 rounded-lg px-2 text-xs bg-transparent outline-hidden text-right" class="w-fit pr-8 rounded-lg px-2 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
bind:value={RAGConfig.PDF_LOADER_MODE} bind:value={RAGConfig.PDF_LOADER_MODE}
> >
<option value="page">{$i18n.t('Page')}</option> <option value="page">{$i18n.t('Page')}</option>
@@ -448,7 +448,7 @@
className="w-full" className="w-full"
> >
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('Enter Datalab Marker API Base URL')} placeholder={$i18n.t('Enter Datalab Marker API Base URL')}
bind:value={RAGConfig.DATALAB_MARKER_API_BASE_URL} bind:value={RAGConfig.DATALAB_MARKER_API_BASE_URL}
/> />
@@ -601,7 +601,7 @@
</div> </div>
<div class=""> <div class="">
<select <select
class="w-fit pr-8 rounded-lg px-2 text-xs bg-transparent outline-hidden text-right" class="w-fit pr-8 rounded-lg px-2 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
bind:value={RAGConfig.DATALAB_MARKER_OUTPUT_FORMAT} bind:value={RAGConfig.DATALAB_MARKER_OUTPUT_FORMAT}
> >
<option value="markdown">{$i18n.t('Markdown')}</option> <option value="markdown">{$i18n.t('Markdown')}</option>
@@ -614,7 +614,7 @@
<div class="my-0.5 flex flex-col gap-2 pr-2"> <div class="my-0.5 flex flex-col gap-2 pr-2">
<div class="flex gap-2"> <div class="flex gap-2">
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('Enter External Document Loader URL')} placeholder={$i18n.t('Enter External Document Loader URL')}
bind:value={RAGConfig.EXTERNAL_DOCUMENT_LOADER_URL} bind:value={RAGConfig.EXTERNAL_DOCUMENT_LOADER_URL}
/> />
@@ -688,7 +688,7 @@
<div class="flex w-full mt-1"> <div class="flex w-full mt-1">
<div class="flex-1 mr-2"> <div class="flex-1 mr-2">
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('Enter Tika Server URL')} placeholder={$i18n.t('Enter Tika Server URL')}
bind:value={RAGConfig.TIKA_SERVER_URL} bind:value={RAGConfig.TIKA_SERVER_URL}
/> />
@@ -697,7 +697,7 @@
{:else if RAGConfig.CONTENT_EXTRACTION_ENGINE === 'docling'} {:else if RAGConfig.CONTENT_EXTRACTION_ENGINE === 'docling'}
<div class="my-0.5 flex gap-2 pr-2"> <div class="my-0.5 flex gap-2 pr-2">
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('Enter Docling Server URL')} placeholder={$i18n.t('Enter Docling Server URL')}
bind:value={RAGConfig.DOCLING_SERVER_URL} bind:value={RAGConfig.DOCLING_SERVER_URL}
/> />
@@ -726,7 +726,7 @@
{:else if RAGConfig.CONTENT_EXTRACTION_ENGINE === 'document_intelligence'} {:else if RAGConfig.CONTENT_EXTRACTION_ENGINE === 'document_intelligence'}
<div class="my-0.5 flex gap-2 pr-2"> <div class="my-0.5 flex gap-2 pr-2">
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('Enter Document Intelligence Endpoint')} placeholder={$i18n.t('Enter Document Intelligence Endpoint')}
bind:value={RAGConfig.DOCUMENT_INTELLIGENCE_ENDPOINT} bind:value={RAGConfig.DOCUMENT_INTELLIGENCE_ENDPOINT}
/> />
@@ -743,7 +743,7 @@
<div class="flex w-full"> <div class="flex w-full">
<div class="flex-1 mr-2"> <div class="flex-1 mr-2">
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('Enter Document Intelligence Model')} placeholder={$i18n.t('Enter Document Intelligence Model')}
bind:value={RAGConfig.DOCUMENT_INTELLIGENCE_MODEL} bind:value={RAGConfig.DOCUMENT_INTELLIGENCE_MODEL}
/> />
@@ -753,7 +753,7 @@
{:else if RAGConfig.CONTENT_EXTRACTION_ENGINE === 'mistral_ocr'} {:else if RAGConfig.CONTENT_EXTRACTION_ENGINE === 'mistral_ocr'}
<div class="my-0.5 flex gap-2 pr-2"> <div class="my-0.5 flex gap-2 pr-2">
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('Enter Mistral API Base URL')} placeholder={$i18n.t('Enter Mistral API Base URL')}
bind:value={RAGConfig.MISTRAL_OCR_API_BASE_URL} bind:value={RAGConfig.MISTRAL_OCR_API_BASE_URL}
/> />
@@ -780,7 +780,7 @@
{:else if RAGConfig.CONTENT_EXTRACTION_ENGINE === 'paddleocr_vl'} {:else if RAGConfig.CONTENT_EXTRACTION_ENGINE === 'paddleocr_vl'}
<div class="my-0.5 flex gap-2 pr-2"> <div class="my-0.5 flex gap-2 pr-2">
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('Enter PaddleOCR-vl API Base URL')} placeholder={$i18n.t('Enter PaddleOCR-vl API Base URL')}
bind:value={RAGConfig.PADDLEOCR_VL_BASE_URL} bind:value={RAGConfig.PADDLEOCR_VL_BASE_URL}
/> />
@@ -798,7 +798,7 @@
{$i18n.t('API Mode')} {$i18n.t('API Mode')}
</div> </div>
<select <select
class="w-fit pr-8 rounded-lg px-2 text-xs bg-transparent outline-hidden" class="w-fit pr-8 rounded-lg px-2 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
bind:value={RAGConfig.MINERU_API_MODE} bind:value={RAGConfig.MINERU_API_MODE}
on:change={() => { on:change={() => {
// Auto-update URL when switching modes if it's empty or matches the opposite mode's default // Auto-update URL when switching modes if it's empty or matches the opposite mode's default
@@ -825,7 +825,7 @@
<!-- API URL --> <!-- API URL -->
<div class="flex w-full mt-2"> <div class="flex w-full mt-2">
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={RAGConfig.MINERU_API_MODE === 'cloud' placeholder={RAGConfig.MINERU_API_MODE === 'cloud'
? $i18n.t('https://mineru.net/api/v4') ? $i18n.t('https://mineru.net/api/v4')
: $i18n.t('http://localhost:8000')} : $i18n.t('http://localhost:8000')}
@@ -846,7 +846,7 @@
{$i18n.t('API Timeout')} {$i18n.t('API Timeout')}
</div> </div>
<input <input
class="w-16 text-xs bg-transparent outline-hidden text-right" class="w-16 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
type="number" type="number"
min="1" min="1"
bind:value={RAGConfig.MINERU_API_TIMEOUT} bind:value={RAGConfig.MINERU_API_TIMEOUT}
@@ -890,7 +890,7 @@
</Tooltip> </Tooltip>
</div> </div>
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('pdf, docx, pptx, xlsx')} placeholder={$i18n.t('pdf, docx, pptx, xlsx')}
bind:value={RAGConfig.MINERU_FILE_EXTENSIONS} bind:value={RAGConfig.MINERU_FILE_EXTENSIONS}
/> />
@@ -926,7 +926,7 @@
</div> </div>
<div class="flex items-center relative"> <div class="flex items-center relative">
<select <select
class="w-fit pr-8 rounded-lg px-2 text-xs bg-transparent outline-hidden text-right" class="w-fit pr-8 rounded-lg px-2 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
bind:value={RAGConfig.TEXT_SPLITTER} bind:value={RAGConfig.TEXT_SPLITTER}
> >
<option value="">{$i18n.t('Default')} ({$i18n.t('Character')})</option> <option value="">{$i18n.t('Default')} ({$i18n.t('Character')})</option>
@@ -1056,7 +1056,7 @@
</div> </div>
<div class="flex items-center relative"> <div class="flex items-center relative">
<select <select
class="w-fit pr-8 rounded-lg px-2 p-1 text-xs bg-transparent outline-hidden text-right" class="w-fit pr-8 rounded-lg px-2 p-1 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
bind:value={RAG_EMBEDDING_ENGINE} bind:value={RAG_EMBEDDING_ENGINE}
placeholder={$i18n.t('Select an embedding model engine')} placeholder={$i18n.t('Select an embedding model engine')}
on:change={(e) => { on:change={(e) => {
@@ -1082,7 +1082,7 @@
{#if RAG_EMBEDDING_ENGINE === 'openai'} {#if RAG_EMBEDDING_ENGINE === 'openai'}
<div class="my-0.5 flex gap-2 pr-2"> <div class="my-0.5 flex gap-2 pr-2">
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('API Base URL')} placeholder={$i18n.t('API Base URL')}
bind:value={OpenAIUrl} bind:value={OpenAIUrl}
required required
@@ -1097,7 +1097,7 @@
{:else if RAG_EMBEDDING_ENGINE === 'ollama'} {:else if RAG_EMBEDDING_ENGINE === 'ollama'}
<div class="my-0.5 flex gap-2 pr-2"> <div class="my-0.5 flex gap-2 pr-2">
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('API Base URL')} placeholder={$i18n.t('API Base URL')}
bind:value={OllamaUrl} bind:value={OllamaUrl}
required required
@@ -1113,7 +1113,7 @@
<div class="my-0.5 flex flex-col gap-2 pr-2 w-full"> <div class="my-0.5 flex flex-col gap-2 pr-2 w-full">
<div class="flex gap-2"> <div class="flex gap-2">
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('API Base URL')} placeholder={$i18n.t('API Base URL')}
bind:value={AzureOpenAIUrl} bind:value={AzureOpenAIUrl}
required required
@@ -1122,7 +1122,7 @@
</div> </div>
<div class="flex gap-2"> <div class="flex gap-2">
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('Version')} placeholder={$i18n.t('Version')}
bind:value={AzureOpenAIVersion} bind:value={AzureOpenAIVersion}
required required
@@ -1142,7 +1142,7 @@
<div class="flex w-full"> <div class="flex w-full">
<div class="flex-1 mr-2"> <div class="flex-1 mr-2">
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
bind:value={RAG_EMBEDDING_MODEL} bind:value={RAG_EMBEDDING_MODEL}
placeholder={$i18n.t('Set embedding model')} placeholder={$i18n.t('Set embedding model')}
required required
@@ -1153,7 +1153,7 @@
<div class="flex w-full"> <div class="flex w-full">
<div class="flex-1 mr-2"> <div class="flex-1 mr-2">
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('Set embedding model (e.g. {{model}})', { placeholder={$i18n.t('Set embedding model (e.g. {{model}})', {
model: RAG_EMBEDDING_MODEL.slice(-40) model: RAG_EMBEDDING_MODEL.slice(-40)
})} })}
@@ -1318,7 +1318,7 @@
</div> </div>
<div class="flex items-center relative"> <div class="flex items-center relative">
<select <select
class="w-fit pr-8 rounded-lg px-2 p-1 text-xs bg-transparent outline-hidden text-right" class="w-fit pr-8 rounded-lg px-2 p-1 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
bind:value={RAGConfig.RAG_RERANKING_ENGINE} bind:value={RAGConfig.RAG_RERANKING_ENGINE}
placeholder={$i18n.t('Select a reranking model engine')} placeholder={$i18n.t('Select a reranking model engine')}
on:change={(e) => { on:change={(e) => {
@@ -1338,7 +1338,7 @@
{#if RAGConfig.RAG_RERANKING_ENGINE === 'external'} {#if RAGConfig.RAG_RERANKING_ENGINE === 'external'}
<div class="my-0.5 flex gap-2 pr-2"> <div class="my-0.5 flex gap-2 pr-2">
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('API Base URL')} placeholder={$i18n.t('API Base URL')}
bind:value={RAGConfig.RAG_EXTERNAL_RERANKER_URL} bind:value={RAGConfig.RAG_EXTERNAL_RERANKER_URL}
required required
@@ -1362,7 +1362,7 @@
<div class="flex w-full"> <div class="flex w-full">
<div class="flex-1 mr-2"> <div class="flex-1 mr-2">
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('Set reranking model (e.g. {{model}})', { placeholder={$i18n.t('Set reranking model (e.g. {{model}})', {
model: 'BAAI/bge-reranker-v2-m3' model: 'BAAI/bge-reranker-v2-m3'
})} })}
@@ -1397,7 +1397,7 @@
</div> </div>
<div class="flex items-center relative"> <div class="flex items-center relative">
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
type="number" type="number"
placeholder={$i18n.t('Enter Top K')} placeholder={$i18n.t('Enter Top K')}
bind:value={RAGConfig.TOP_K} bind:value={RAGConfig.TOP_K}
@@ -1414,7 +1414,7 @@
</div> </div>
<div class="flex items-center relative"> <div class="flex items-center relative">
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
type="number" type="number"
placeholder={$i18n.t('Enter Top K Reranker')} placeholder={$i18n.t('Enter Top K Reranker')}
bind:value={RAGConfig.TOP_K_RERANKER} bind:value={RAGConfig.TOP_K_RERANKER}
@@ -1433,7 +1433,7 @@
</div> </div>
<div class="flex items-center relative"> <div class="flex items-center relative">
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
type="number" type="number"
step="0.01" step="0.01"
placeholder={$i18n.t('Enter Score')} placeholder={$i18n.t('Enter Score')}
@@ -1572,7 +1572,7 @@
placement="top-start" placement="top-start"
> >
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
type="text" type="text"
placeholder={$i18n.t('e.g. pdf, docx, txt')} placeholder={$i18n.t('e.g. pdf, docx, txt')}
bind:value={RAGConfig.ALLOWED_FILE_EXTENSIONS} bind:value={RAGConfig.ALLOWED_FILE_EXTENSIONS}
@@ -1594,7 +1594,7 @@
placement="top-start" placement="top-start"
> >
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
type="number" type="number"
placeholder={$i18n.t('Leave empty for unlimited')} placeholder={$i18n.t('Leave empty for unlimited')}
bind:value={RAGConfig.FILE_MAX_SIZE} bind:value={RAGConfig.FILE_MAX_SIZE}
@@ -1617,7 +1617,7 @@
placement="top-start" placement="top-start"
> >
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
type="number" type="number"
placeholder={$i18n.t('Leave empty for unlimited')} placeholder={$i18n.t('Leave empty for unlimited')}
bind:value={RAGConfig.FILE_MAX_COUNT} bind:value={RAGConfig.FILE_MAX_COUNT}
@@ -1640,7 +1640,7 @@
placement="top-start" placement="top-start"
> >
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
type="number" type="number"
placeholder={$i18n.t('Leave empty for no compression')} placeholder={$i18n.t('Leave empty for no compression')}
bind:value={RAGConfig.FILE_IMAGE_COMPRESSION_WIDTH} bind:value={RAGConfig.FILE_IMAGE_COMPRESSION_WIDTH}
@@ -1663,7 +1663,7 @@
placement="top-start" placement="top-start"
> >
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
type="number" type="number"
placeholder={$i18n.t('Leave empty for no compression')} placeholder={$i18n.t('Leave empty for no compression')}
bind:value={RAGConfig.FILE_IMAGE_COMPRESSION_HEIGHT} bind:value={RAGConfig.FILE_IMAGE_COMPRESSION_HEIGHT}
@@ -350,7 +350,7 @@
<div class="flex items-center"> <div class="flex items-center">
<select <select
class="w-full py-1 text-sm rounded-lg bg-transparent {selectedModelId class="w-full rounded-lg border border-gray-100/50 !bg-gray-50/40 px-2 py-1.5 text-sm text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500 {selectedModelId
? '' ? ''
: 'text-gray-500'} placeholder:text-gray-300 dark:placeholder:text-gray-700 outline-hidden" : 'text-gray-500'} placeholder:text-gray-300 dark:placeholder:text-gray-700 outline-hidden"
bind:value={selectedModelId} bind:value={selectedModelId}
@@ -455,7 +455,7 @@
{$i18n.t('Send events for')} {$i18n.t('Send events for')}
</div> </div>
<select <select
class="text-xs bg-transparent outline-hidden text-gray-700 dark:text-gray-300" class="rounded-lg border border-gray-100/50 !bg-gray-50/40 px-2 py-1.5 text-xs text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500"
bind:value={targetMode} bind:value={targetMode}
> >
<option value="all">{$i18n.t('All users and system events')}</option> <option value="all">{$i18n.t('All users and system events')}</option>
@@ -460,7 +460,7 @@
<div class="flex flex-1 items-center"> <div class="flex flex-1 items-center">
<select <select
id="external-source-provider" id="external-source-provider"
class="w-full text-sm bg-transparent outline-hidden" class="w-full rounded-lg border border-gray-100/50 !bg-gray-50/40 px-2 py-1.5 text-sm text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500"
bind:value={sourceForm.provider} bind:value={sourceForm.provider}
on:change={updateProvider} on:change={updateProvider}
> >
+21 -21
View File
@@ -325,7 +325,7 @@
<Tooltip content={$i18n.t('Enter Model ID')} placement="top-start"> <Tooltip content={$i18n.t('Enter Model ID')} placement="top-start">
<input <input
list="model-list" list="model-list"
class=" text-right text-xs bg-transparent outline-hidden max-w-full w-52" class=" text-right text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 max-w-full w-52"
bind:value={config.IMAGE_GENERATION_MODEL} bind:value={config.IMAGE_GENERATION_MODEL}
placeholder={$i18n.t('Select a model')} placeholder={$i18n.t('Select a model')}
required required
@@ -350,7 +350,7 @@
<Tooltip content={$i18n.t('Enter Image Size (e.g. 512x512)')} placement="top-start"> <Tooltip content={$i18n.t('Enter Image Size (e.g. 512x512)')} placement="top-start">
<input <input
class=" text-right text-xs bg-transparent outline-hidden max-w-full w-52" class=" text-right text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 max-w-full w-52"
placeholder={$i18n.t('Enter Image Size (e.g. 512x512)')} placeholder={$i18n.t('Enter Image Size (e.g. 512x512)')}
bind:value={config.IMAGE_SIZE} bind:value={config.IMAGE_SIZE}
/> />
@@ -372,7 +372,7 @@
placement="top-start" placement="top-start"
> >
<input <input
class=" text-right text-xs bg-transparent outline-hidden" class=" text-right text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('Enter Number of Steps (e.g. 50)')} placeholder={$i18n.t('Enter Number of Steps (e.g. 50)')}
bind:value={config.IMAGE_STEPS} bind:value={config.IMAGE_STEPS}
required required
@@ -404,7 +404,7 @@
</div> </div>
<select <select
class="w-fit pr-8 cursor-pointer rounded-lg px-2 text-xs bg-transparent outline-hidden text-right" class="w-fit pr-8 cursor-pointer rounded-lg px-2 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
bind:value={config.IMAGE_GENERATION_ENGINE} bind:value={config.IMAGE_GENERATION_ENGINE}
placeholder={$i18n.t('Select Engine')} placeholder={$i18n.t('Select Engine')}
> >
@@ -428,7 +428,7 @@
<div class="flex w-full"> <div class="flex w-full">
<div class="flex-1"> <div class="flex-1">
<input <input
class="w-full text-xs bg-transparent outline-hidden text-right" class="w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
placeholder={$i18n.t('API Base URL')} placeholder={$i18n.t('API Base URL')}
bind:value={config.IMAGES_OPENAI_API_BASE_URL} bind:value={config.IMAGES_OPENAI_API_BASE_URL}
/> />
@@ -469,7 +469,7 @@
<div class="flex w-full"> <div class="flex w-full">
<div class="flex-1"> <div class="flex-1">
<input <input
class="w-full text-xs bg-transparent outline-hidden text-right" class="w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
placeholder={$i18n.t('API Version')} placeholder={$i18n.t('API Version')}
bind:value={config.IMAGES_OPENAI_API_VERSION} bind:value={config.IMAGES_OPENAI_API_VERSION}
/> />
@@ -509,7 +509,7 @@
<div class="flex w-full"> <div class="flex w-full">
<div class="flex-1 mr-2"> <div class="flex-1 mr-2">
<input <input
class="w-full text-xs bg-transparent outline-hidden text-right" class="w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
placeholder={$i18n.t('Enter URL (e.g. http://127.0.0.1:7860/)')} placeholder={$i18n.t('Enter URL (e.g. http://127.0.0.1:7860/)')}
bind:value={config.AUTOMATIC1111_BASE_URL} bind:value={config.AUTOMATIC1111_BASE_URL}
/> />
@@ -623,7 +623,7 @@
<div class="flex w-full"> <div class="flex w-full">
<div class="flex-1 mr-2"> <div class="flex-1 mr-2">
<input <input
class="w-full text-xs bg-transparent outline-hidden text-right" class="w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
placeholder={$i18n.t('Enter URL (e.g. http://127.0.0.1:7860/)')} placeholder={$i18n.t('Enter URL (e.g. http://127.0.0.1:7860/)')}
bind:value={config.COMFYUI_BASE_URL} bind:value={config.COMFYUI_BASE_URL}
/> />
@@ -786,7 +786,7 @@
<div class=""> <div class="">
<Tooltip content={$i18n.t('Input Key (e.g. text, unet_name, steps)')}> <Tooltip content={$i18n.t('Input Key (e.g. text, unet_name, steps)')}>
<input <input
class="py-1 w-24 text-xs bg-transparent outline-hidden" class="py-1 w-24 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('Key')} placeholder={$i18n.t('Key')}
bind:value={node.key} bind:value={node.key}
required required
@@ -802,7 +802,7 @@
placement="top-start" placement="top-start"
> >
<input <input
class="w-full py-1 text-xs bg-transparent outline-hidden" class="w-full py-1 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('Node Ids')} placeholder={$i18n.t('Node Ids')}
bind:value={node.node_ids} bind:value={node.node_ids}
/> />
@@ -830,7 +830,7 @@
<div class="flex w-full"> <div class="flex w-full">
<div class="flex-1"> <div class="flex-1">
<input <input
class="w-full text-xs bg-transparent outline-hidden text-right" class="w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
placeholder={$i18n.t('API Base URL')} placeholder={$i18n.t('API Base URL')}
bind:value={config.IMAGES_GEMINI_API_BASE_URL} bind:value={config.IMAGES_GEMINI_API_BASE_URL}
/> />
@@ -869,7 +869,7 @@
</div> </div>
<select <select
class="w-fit pr-8 cursor-pointer rounded-lg px-2 text-xs bg-transparent outline-hidden text-right" class="w-fit pr-8 cursor-pointer rounded-lg px-2 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
bind:value={config.IMAGES_GEMINI_ENDPOINT_METHOD} bind:value={config.IMAGES_GEMINI_ENDPOINT_METHOD}
placeholder={$i18n.t('Select Method')} placeholder={$i18n.t('Select Method')}
> >
@@ -910,7 +910,7 @@
<Tooltip content={$i18n.t('Enter Model ID')} placement="top-start"> <Tooltip content={$i18n.t('Enter Model ID')} placement="top-start">
<input <input
list="model-list" list="model-list"
class="text-right text-xs bg-transparent outline-hidden max-w-full w-52" class="text-right text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 max-w-full w-52"
bind:value={config.IMAGE_EDIT_MODEL} bind:value={config.IMAGE_EDIT_MODEL}
placeholder={$i18n.t('Select a model')} placeholder={$i18n.t('Select a model')}
/> />
@@ -934,7 +934,7 @@
<Tooltip content={$i18n.t('Enter Image Size (e.g. 512x512)')} placement="top-start"> <Tooltip content={$i18n.t('Enter Image Size (e.g. 512x512)')} placement="top-start">
<input <input
class="text-right text-xs bg-transparent outline-hidden max-w-full w-52" class="text-right text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 max-w-full w-52"
placeholder={$i18n.t('Enter Image Size (e.g. 512x512)')} placeholder={$i18n.t('Enter Image Size (e.g. 512x512)')}
bind:value={config.IMAGE_EDIT_SIZE} bind:value={config.IMAGE_EDIT_SIZE}
/> />
@@ -952,7 +952,7 @@
</div> </div>
<select <select
class="w-fit pr-8 cursor-pointer rounded-lg px-2 text-xs bg-transparent outline-hidden text-right" class="w-fit pr-8 cursor-pointer rounded-lg px-2 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
bind:value={config.IMAGE_EDIT_ENGINE} bind:value={config.IMAGE_EDIT_ENGINE}
placeholder={$i18n.t('Select Engine')} placeholder={$i18n.t('Select Engine')}
> >
@@ -975,7 +975,7 @@
<div class="flex w-full"> <div class="flex w-full">
<div class="flex-1"> <div class="flex-1">
<input <input
class="w-full text-xs bg-transparent outline-hidden text-right" class="w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
placeholder={$i18n.t('API Base URL')} placeholder={$i18n.t('API Base URL')}
bind:value={config.IMAGES_EDIT_OPENAI_API_BASE_URL} bind:value={config.IMAGES_EDIT_OPENAI_API_BASE_URL}
/> />
@@ -1016,7 +1016,7 @@
<div class="flex w-full"> <div class="flex w-full">
<div class="flex-1"> <div class="flex-1">
<input <input
class="w-full text-xs bg-transparent outline-hidden text-right" class="w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
placeholder={$i18n.t('API Version')} placeholder={$i18n.t('API Version')}
bind:value={config.IMAGES_EDIT_OPENAI_API_VERSION} bind:value={config.IMAGES_EDIT_OPENAI_API_VERSION}
/> />
@@ -1036,7 +1036,7 @@
<div class="flex w-full"> <div class="flex w-full">
<div class="flex-1 mr-2"> <div class="flex-1 mr-2">
<input <input
class="w-full text-xs bg-transparent outline-hidden text-right" class="w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
placeholder={$i18n.t('Enter URL (e.g. http://127.0.0.1:7860/)')} placeholder={$i18n.t('Enter URL (e.g. http://127.0.0.1:7860/)')}
bind:value={config.IMAGES_EDIT_COMFYUI_BASE_URL} bind:value={config.IMAGES_EDIT_COMFYUI_BASE_URL}
/> />
@@ -1191,7 +1191,7 @@
<div class=""> <div class="">
<Tooltip content={$i18n.t('Input Key (e.g. text, unet_name, steps)')}> <Tooltip content={$i18n.t('Input Key (e.g. text, unet_name, steps)')}>
<input <input
class="py-1 w-24 text-xs bg-transparent outline-hidden" class="py-1 w-24 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('Key')} placeholder={$i18n.t('Key')}
bind:value={node.key} bind:value={node.key}
required required
@@ -1207,7 +1207,7 @@
placement="top-start" placement="top-start"
> >
<input <input
class="w-full py-1 text-xs bg-transparent outline-hidden" class="w-full py-1 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('Node Ids')} placeholder={$i18n.t('Node Ids')}
bind:value={node.node_ids} bind:value={node.node_ids}
/> />
@@ -1235,7 +1235,7 @@
<div class="flex w-full"> <div class="flex w-full">
<div class="flex-1"> <div class="flex-1">
<input <input
class="w-full text-xs bg-transparent outline-hidden text-right" class="w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
placeholder={$i18n.t('API Base URL')} placeholder={$i18n.t('API Base URL')}
bind:value={config.IMAGES_EDIT_GEMINI_API_BASE_URL} bind:value={config.IMAGES_EDIT_GEMINI_API_BASE_URL}
/> />
@@ -60,7 +60,7 @@
<div class="flex flex-row flex-1 gap-2 items-start"> <div class="flex flex-row flex-1 gap-2 items-start">
<select <select
class="w-fit capitalize rounded-xl text-xs bg-transparent outline-hidden pl-1 pr-5" class="w-fit capitalize rounded-xl text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 pl-1 pr-5"
bind:value={banner.type} bind:value={banner.type}
required required
> >
@@ -72,7 +72,7 @@
</select> </select>
<Textarea <Textarea
className="mr-2 text-xs w-full bg-transparent outline-hidden resize-none" className="mr-2 text-xs w-full border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 resize-none"
placeholder={$i18n.t('Content')} placeholder={$i18n.t('Content')}
bind:value={banner.content} bind:value={banner.content}
maxSize={100} maxSize={100}
@@ -12,7 +12,7 @@
{#if ollamaConfig} {#if ollamaConfig}
<div class="flex-1 mb-2.5 pr-1.5 rounded-lg bg-gray-50 dark:text-gray-300 dark:bg-gray-850"> <div class="flex-1 mb-2.5 pr-1.5 rounded-lg bg-gray-50 dark:text-gray-300 dark:bg-gray-850">
<select <select
class="w-full py-2 px-4 text-sm outline-hidden bg-transparent" class="w-full py-2 px-4 text-sm outline-hidden border border-gray-100/50 !bg-gray-50/40 dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
bind:value={selectedUrlIdx} bind:value={selectedUrlIdx}
placeholder={$i18n.t('Select an Ollama instance')} placeholder={$i18n.t('Select an Ollama instance')}
> >
@@ -812,7 +812,7 @@
class="flex-1 mr-2 pr-1.5 rounded-lg bg-gray-50 dark:text-gray-300 dark:bg-gray-850" class="flex-1 mr-2 pr-1.5 rounded-lg bg-gray-50 dark:text-gray-300 dark:bg-gray-850"
> >
<select <select
class="w-full py-2 px-4 text-sm outline-hidden bg-transparent" class="w-full py-2 px-4 text-sm outline-hidden border border-gray-100/50 !bg-gray-50/40 dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
bind:value={deleteModelTag} bind:value={deleteModelTag}
placeholder={$i18n.t('Select a model')} placeholder={$i18n.t('Select a model')}
> >
@@ -41,7 +41,7 @@
<div class="flex items-center -mr-1"> <div class="flex items-center -mr-1">
<select <select
class="w-full py-1 text-sm rounded-lg bg-transparent {selectedModelId class="w-full py-1 text-sm rounded-lg border border-gray-100/50 !bg-gray-50/40 dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 {selectedModelId
? '' ? ''
: 'text-gray-500'} placeholder:text-gray-300 dark:placeholder:text-gray-700 outline-hidden" : 'text-gray-500'} placeholder:text-gray-300 dark:placeholder:text-gray-700 outline-hidden"
bind:value={selectedModelId} bind:value={selectedModelId}
@@ -43,7 +43,7 @@
const inputClass = const inputClass =
'w-full h-7 rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 text-xs text-gray-700 outline-hidden transition-colors placeholder:text-gray-300 focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:placeholder:text-gray-700 dark:focus:border-blue-500'; 'w-full h-7 rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 text-xs text-gray-700 outline-hidden transition-colors placeholder:text-gray-300 focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:placeholder:text-gray-700 dark:focus:border-blue-500';
const selectClass = const selectClass =
'w-full h-7 rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 text-xs text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500'; 'w-full h-7 rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 pe-8 text-xs text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500';
const actionButtonClass = const actionButtonClass =
'rounded-lg px-2 py-1 text-xs text-gray-500 transition-colors hover:bg-black/5 hover:text-gray-900 disabled:opacity-50 dark:text-gray-500 dark:hover:bg-white/5 dark:hover:text-white'; 'rounded-lg px-2 py-1 text-xs text-gray-500 transition-colors hover:bg-black/5 hover:text-gray-900 disabled:opacity-50 dark:text-gray-500 dark:hover:bg-white/5 dark:hover:text-white';
const iconButtonClass = const iconButtonClass =
@@ -199,7 +199,7 @@
</div> </div>
<div class="flex items-center relative"> <div class="flex items-center relative">
<select <select
class="w-fit pr-8 rounded-lg px-2 p-1 text-xs bg-transparent outline-hidden text-right" class="w-fit pr-8 rounded-lg px-2 p-1 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
bind:value={webConfig.WEB_SEARCH_ENGINE} bind:value={webConfig.WEB_SEARCH_ENGINE}
placeholder={$i18n.t('Select a engine')} placeholder={$i18n.t('Select a engine')}
required required
@@ -1152,7 +1152,7 @@
</div> </div>
<div class="flex items-center relative"> <div class="flex items-center relative">
<select <select
class="w-fit pr-8 rounded-lg px-2 p-1 text-xs bg-transparent outline-hidden text-right" class="w-fit pr-8 rounded-lg px-2 p-1 text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 text-right"
bind:value={webConfig.WEB_LOADER_ENGINE} bind:value={webConfig.WEB_LOADER_ENGINE}
placeholder={$i18n.t('Select a engine')} placeholder={$i18n.t('Select a engine')}
> >
@@ -1171,7 +1171,7 @@
</div> </div>
<div class="flex items-center relative"> <div class="flex items-center relative">
<input <input
class="flex-1 w-full text-xs bg-transparent outline-hidden" class="flex-1 w-full text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
placeholder={$i18n.t('Timeout')} placeholder={$i18n.t('Timeout')}
bind:value={webConfig.WEB_LOADER_TIMEOUT} bind:value={webConfig.WEB_LOADER_TIMEOUT}
/> />
@@ -1386,7 +1386,7 @@
</div> </div>
<div class="flex items-center relative"> <div class="flex items-center relative">
<input <input
class="flex-1 w-full rounded-lg text-xs bg-transparent outline-hidden" class="flex-1 w-full rounded-lg text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
type="text" type="text"
placeholder={$i18n.t('Enter language codes')} placeholder={$i18n.t('Enter language codes')}
bind:value={webConfig.YOUTUBE_LOADER_LANGUAGE} bind:value={webConfig.YOUTUBE_LOADER_LANGUAGE}
@@ -1401,7 +1401,7 @@
</div> </div>
<div class="flex items-center relative"> <div class="flex items-center relative">
<input <input
class="flex-1 w-full rounded-lg text-xs bg-transparent outline-hidden" class="flex-1 w-full rounded-lg text-xs border border-gray-100/50 !bg-gray-50/40 outline-hidden dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300"
type="text" type="text"
placeholder={$i18n.t('Enter proxy URL (e.g. https://user:password@host:port)')} placeholder={$i18n.t('Enter proxy URL (e.g. https://user:password@host:port)')}
bind:value={webConfig.YOUTUBE_LOADER_PROXY_URL} bind:value={webConfig.YOUTUBE_LOADER_PROXY_URL}
@@ -17,6 +17,7 @@
import UserProfileImage from './Account/UserProfileImage.svelte'; import UserProfileImage from './Account/UserProfileImage.svelte';
import UserSettingField from './UserSettingField.svelte'; import UserSettingField from './UserSettingField.svelte';
import UserSettingRow from './UserSettingRow.svelte'; import UserSettingRow from './UserSettingRow.svelte';
import UserSettingSelect from './UserSettingSelect.svelte';
import UserSettingSection from './UserSettingSection.svelte'; import UserSettingSection from './UserSettingSection.svelte';
const i18n = getContext('i18n'); const i18n = getContext('i18n');
@@ -171,10 +172,10 @@
label={$i18n.t('Gender')} label={$i18n.t('Gender')}
description={$i18n.t('Choose the gender value stored on your profile.')} description={$i18n.t('Choose the gender value stored on your profile.')}
> >
<select <UserSettingSelect
class={inputClass} className="w-full"
bind:value={_gender} bind:value={_gender}
aria-label={$i18n.t('Gender')} ariaLabel={$i18n.t('Gender')}
on:change={(e) => { on:change={(e) => {
console.log(_gender); console.log(_gender);
@@ -190,7 +191,7 @@
<option value="male">{$i18n.t('Male')}</option> <option value="male">{$i18n.t('Male')}</option>
<option value="female">{$i18n.t('Female')}</option> <option value="female">{$i18n.t('Female')}</option>
<option value="custom">{$i18n.t('Custom')}</option> <option value="custom">{$i18n.t('Custom')}</option>
</select> </UserSettingSelect>
{#if _gender === 'custom'} {#if _gender === 'custom'}
<input <input
+12 -16
View File
@@ -10,6 +10,7 @@
import Tooltip from '$lib/components/common/Tooltip.svelte'; import Tooltip from '$lib/components/common/Tooltip.svelte';
import UserSettingField from './UserSettingField.svelte'; import UserSettingField from './UserSettingField.svelte';
import UserSettingRow from './UserSettingRow.svelte'; import UserSettingRow from './UserSettingRow.svelte';
import UserSettingSelect from './UserSettingSelect.svelte';
import UserSettingSection from './UserSettingSection.svelte'; import UserSettingSection from './UserSettingSection.svelte';
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
@@ -40,8 +41,6 @@
let playbackRate = 1; let playbackRate = 1;
const inputClass = const inputClass =
'h-7 w-full rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 text-xs text-gray-700 outline-hidden transition-colors placeholder:text-gray-300 focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:placeholder:text-gray-700 dark:focus:border-blue-500'; 'h-7 w-full rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 text-xs text-gray-700 outline-hidden transition-colors placeholder:text-gray-300 focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:placeholder:text-gray-700 dark:focus:border-blue-500';
const selectClass =
'h-7 w-fit min-w-28 rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 text-right text-xs text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500';
const actionButtonClass = const actionButtonClass =
'text-xs text-gray-500 transition-colors hover:text-gray-900 dark:text-gray-500 dark:hover:text-white'; 'text-xs text-gray-500 transition-colors hover:text-gray-900 dark:text-gray-500 dark:hover:text-white';
@@ -193,15 +192,14 @@
label={$i18n.t('Speech-to-Text Engine')} label={$i18n.t('Speech-to-Text Engine')}
description={$i18n.t('Choose the engine used to transcribe voice input.')} description={$i18n.t('Choose the engine used to transcribe voice input.')}
> >
<select <UserSettingSelect
class={selectClass}
bind:value={STTEngine} bind:value={STTEngine}
aria-label={$i18n.t('Speech-to-Text Engine')} ariaLabel={$i18n.t('Speech-to-Text Engine')}
placeholder={$i18n.t('Select an engine')} placeholder={$i18n.t('Select an engine')}
> >
<option value="">{$i18n.t('Default')}</option> <option value="">{$i18n.t('Default')}</option>
<option value="web">{$i18n.t('Web API')}</option> <option value="web">{$i18n.t('Web API')}</option>
</select> </UserSettingSelect>
</UserSettingRow> </UserSettingRow>
<UserSettingRow <UserSettingRow
@@ -252,15 +250,14 @@
label={$i18n.t('Text-to-Speech Engine')} label={$i18n.t('Text-to-Speech Engine')}
description={$i18n.t('Choose the engine used to read assistant responses aloud.')} description={$i18n.t('Choose the engine used to read assistant responses aloud.')}
> >
<select <UserSettingSelect
class={selectClass}
bind:value={TTSEngine} bind:value={TTSEngine}
aria-label={$i18n.t('Text-to-Speech Engine')} ariaLabel={$i18n.t('Text-to-Speech Engine')}
placeholder={$i18n.t('Select an engine')} placeholder={$i18n.t('Select an engine')}
> >
<option value="">{$i18n.t('Default')}</option> <option value="">{$i18n.t('Default')}</option>
<option value="browser-kokoro">{$i18n.t('Kokoro.js (Browser)')}</option> <option value="browser-kokoro">{$i18n.t('Kokoro.js (Browser)')}</option>
</select> </UserSettingSelect>
</UserSettingRow> </UserSettingRow>
{#if TTSEngine === 'browser-kokoro'} {#if TTSEngine === 'browser-kokoro'}
@@ -268,10 +265,9 @@
label={$i18n.t('Kokoro.js Dtype')} label={$i18n.t('Kokoro.js Dtype')}
description={$i18n.t('Select the local model precision used by Kokoro.js.')} description={$i18n.t('Select the local model precision used by Kokoro.js.')}
> >
<select <UserSettingSelect
class={selectClass}
bind:value={TTSEngineConfig.dtype} bind:value={TTSEngineConfig.dtype}
aria-label={$i18n.t('Kokoro.js Dtype')} ariaLabel={$i18n.t('Kokoro.js Dtype')}
placeholder={$i18n.t('Select dtype')} placeholder={$i18n.t('Select dtype')}
> >
<option value="" disabled selected>{$i18n.t('Select dtype')}</option> <option value="" disabled selected>{$i18n.t('Select dtype')}</option>
@@ -279,7 +275,7 @@
<option value="fp16">fp16</option> <option value="fp16">fp16</option>
<option value="q8">q8</option> <option value="q8">q8</option>
<option value="q4">q4</option> <option value="q4">q4</option>
</select> </UserSettingSelect>
</UserSettingRow> </UserSettingRow>
{/if} {/if}
@@ -364,7 +360,7 @@
label={$i18n.t('Set Voice')} label={$i18n.t('Set Voice')}
description={$i18n.t('Choose the browser voice used for speech output.')} description={$i18n.t('Choose the browser voice used for speech output.')}
> >
<select class={inputClass} bind:value={voice} aria-label={$i18n.t('Voice')}> <UserSettingSelect className="w-full" bind:value={voice} ariaLabel={$i18n.t('Voice')}>
<option value="" selected={voice !== ''}>{$i18n.t('Default')}</option> <option value="" selected={voice !== ''}>{$i18n.t('Default')}</option>
{#each voices.filter((v) => nonLocalVoices || v.localService === true) as _voice} {#each voices.filter((v) => nonLocalVoices || v.localService === true) as _voice}
<option <option
@@ -373,7 +369,7 @@
selected={voice === _voice.name}>{_voice.name}</option selected={voice === _voice.name}>{_voice.name}</option
> >
{/each} {/each}
</select> </UserSettingSelect>
</UserSettingField> </UserSettingField>
<UserSettingRow <UserSettingRow
label={$i18n.t('Allow non-local voices')} label={$i18n.t('Allow non-local voices')}
@@ -13,6 +13,7 @@
import UserSettingField from './UserSettingField.svelte'; import UserSettingField from './UserSettingField.svelte';
import UserSettingRow from './UserSettingRow.svelte'; import UserSettingRow from './UserSettingRow.svelte';
import UserSettingSection from './UserSettingSection.svelte'; import UserSettingSection from './UserSettingSection.svelte';
import UserSettingSelect from './UserSettingSelect.svelte';
export let saveSettings: Function; export let saveSettings: Function;
export let getModels: Function; export let getModels: Function;
@@ -29,8 +30,6 @@
const systemPromptTextareaClass = const systemPromptTextareaClass =
'w-full resize-y rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 py-1.5 text-xs text-gray-700 outline-hidden transition-colors placeholder:text-gray-300 focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:placeholder:text-gray-700 dark:focus:border-blue-500'; 'w-full resize-y rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 py-1.5 text-xs text-gray-700 outline-hidden transition-colors placeholder:text-gray-300 focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:placeholder:text-gray-700 dark:focus:border-blue-500';
const selectClass =
'h-7 w-fit min-w-28 rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 text-right text-xs text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500';
const actionButtonClass = const actionButtonClass =
'text-xs text-gray-500 transition-colors hover:text-gray-900 dark:text-gray-500 dark:hover:text-white'; 'text-xs text-gray-500 transition-colors hover:text-gray-900 dark:text-gray-500 dark:hover:text-white';
@@ -224,9 +223,9 @@
label={$i18n.t('Theme')} label={$i18n.t('Theme')}
description={$i18n.t('Choose the color theme used by the interface.')} description={$i18n.t('Choose the color theme used by the interface.')}
> >
<select <UserSettingSelect
class={selectClass}
bind:value={selectedTheme} bind:value={selectedTheme}
ariaLabel={$i18n.t('Theme')}
placeholder={$i18n.t('Select a theme')} placeholder={$i18n.t('Select a theme')}
on:change={() => themeChangeHandler(selectedTheme)} on:change={() => themeChangeHandler(selectedTheme)}
> >
@@ -237,16 +236,17 @@
{#if $config?.features?.enable_easter_eggs} {#if $config?.features?.enable_easter_eggs}
<option value="her">🌷 Her</option> <option value="her">🌷 Her</option>
{/if} {/if}
</select> </UserSettingSelect>
</UserSettingRow> </UserSettingRow>
<UserSettingRow <UserSettingRow
label={$i18n.t('Language')} label={$i18n.t('Language')}
description={$i18n.t('Choose the language used for interface text.')} description={$i18n.t('Choose the language used for interface text.')}
> >
<select <UserSettingSelect
class={selectClass}
bind:value={lang} bind:value={lang}
ariaLabel={$i18n.t('Language')}
className="w-48"
placeholder={$i18n.t('Select a language')} placeholder={$i18n.t('Select a language')}
on:change={(e) => { on:change={(e) => {
changeLanguage(lang); changeLanguage(lang);
@@ -255,7 +255,7 @@
{#each languages as language} {#each languages as language}
<option value={language['code']}>{language['title']}</option> <option value={language['code']}>{language['title']}</option>
{/each} {/each}
</select> </UserSettingSelect>
</UserSettingRow> </UserSettingRow>
{#if $i18n.language === 'en-US' && !($config?.license_metadata ?? false)} {#if $i18n.language === 'en-US' && !($config?.license_metadata ?? false)}
<div class="-mt-1 text-[0.6875rem] text-gray-400 dark:text-gray-600"> <div class="-mt-1 text-[0.6875rem] text-gray-400 dark:text-gray-600">
@@ -16,7 +16,9 @@
import UserSettingSection from './UserSettingSection.svelte'; import UserSettingSection from './UserSettingSection.svelte';
import ChevronDown from '$lib/components/icons/ChevronDown.svelte'; import ChevronDown from '$lib/components/icons/ChevronDown.svelte';
import Plus from '$lib/components/icons/Plus.svelte'; import Plus from '$lib/components/icons/Plus.svelte';
import Search from '$lib/components/icons/Search.svelte';
import Trash from '$lib/components/icons/Trash.svelte'; import Trash from '$lib/components/icons/Trash.svelte';
import XMark from '$lib/components/icons/XMark.svelte';
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
@@ -34,8 +36,6 @@
let showClearConfirmDialog = false; let showClearConfirmDialog = false;
let showDeleteConfirm = false; let showDeleteConfirm = false;
let query = ''; let query = '';
const inputClass =
'h-7 w-full rounded-lg border border-gray-100/50 bg-gray-50/40 px-2 text-xs text-gray-700 outline-hidden transition-colors placeholder:text-gray-300 focus:border-blue-400 dark:border-white/[0.04] dark:bg-white/[0.03] dark:text-gray-300 dark:placeholder:text-gray-700 dark:focus:border-blue-500';
const actionButtonClass = const actionButtonClass =
'shrink-0 text-xs text-gray-500 transition-colors hover:text-gray-900 dark:text-gray-500 dark:hover:text-white'; 'shrink-0 text-xs text-gray-500 transition-colors hover:text-gray-900 dark:text-gray-500 dark:hover:text-white';
@@ -145,54 +145,13 @@
{#if enableMemory} {#if enableMemory}
<div> <div>
<div class="mb-2 flex items-center justify-between"> <div class="mb-1 flex items-center">
<div class="text-xs text-gray-600 dark:text-gray-400"> <div class="text-xs text-gray-600 dark:text-gray-400">
{$i18n.t('Saved Memories')} {$i18n.t('Saved Memories')}
{#if !loadingMemories} {#if !loadingMemories}
<span class="ml-1 text-gray-400 dark:text-gray-600">{memories.length}</span> <span class="ml-1 text-gray-400 dark:text-gray-600">{memories.length}</span>
{/if} {/if}
</div> </div>
<Dropdown align="end">
<Tooltip content={$i18n.t('Actions')}>
<button
class="flex h-7 items-center gap-1.5 rounded-lg bg-transparent px-1.5 text-xs text-gray-500 transition-colors hover:text-gray-900 dark:text-gray-500 dark:hover:text-white"
type="button"
>
<span>{$i18n.t('Actions')}</span>
<ChevronDown className="size-3" strokeWidth="2.5" />
</button>
</Tooltip>
<div slot="content">
<DropdownMenu className="w-[170px] shadow-sm">
<button
class="flex h-[1.6875rem] w-full cursor-pointer select-none items-center gap-2 rounded-lg bg-transparent px-2 text-xs hover:text-gray-900 disabled:cursor-default disabled:opacity-30 dark:hover:text-gray-100"
disabled={loadingMemories}
type="button"
on:click={() => {
selectedMemory = null;
showMemoryModal = true;
}}
>
<Plus className="size-3.5 shrink-0" strokeWidth="1.5" />
<div class="min-w-0 flex-1 truncate text-left">{$i18n.t('Add Memory')}</div>
</button>
<button
class="flex h-[1.6875rem] w-full cursor-pointer select-none items-center gap-2 rounded-lg bg-transparent px-2 text-xs hover:text-gray-900 disabled:cursor-default disabled:opacity-30 dark:hover:text-gray-100"
disabled={loadingMemories || memories.length === 0}
type="button"
on:click={() => {
showClearConfirmDialog = true;
}}
>
<Trash className="size-3.5 shrink-0" strokeWidth="1.5" />
<div class="min-w-0 flex-1 truncate text-left">{$i18n.t('Clear memory')}</div>
</button>
</DropdownMenu>
</div>
</Dropdown>
</div> </div>
{#if loadingMemories} {#if loadingMemories}
@@ -200,28 +159,76 @@
<Spinner className="size-4" /> <Spinner className="size-4" />
</div> </div>
{:else} {:else}
{#if memories.length > 0} <div class="mb-2 flex min-w-0 items-center justify-between gap-3">
<div class="mb-2 flex items-center gap-2"> {#if memories.length > 0}
<input <div class="flex min-w-0 flex-1 items-center gap-2">
class={inputClass} <Search className="size-3.5 shrink-0 text-gray-400 dark:text-gray-600" />
bind:value={query} <input
placeholder={$i18n.t('Search Memories')} data-settings-search
maxlength="500" class="min-w-0 flex-1 bg-transparent py-0.5 text-xs text-gray-700 outline-hidden placeholder:text-gray-300 dark:text-gray-300 dark:placeholder:text-gray-700"
/> bind:value={query}
placeholder={$i18n.t('Search Memories')}
maxlength="500"
/>
{#if query}
<div class="shrink-0">
<button
class="rounded-lg p-0.5 text-gray-400 transition-colors hover:text-gray-700 dark:text-gray-600 dark:hover:text-gray-300"
type="button"
aria-label={$i18n.t('Clear search')}
on:click={() => {
query = '';
}}
>
<XMark className="size-3" strokeWidth="2" />
</button>
</div>
{/if}
</div>
{:else}
<div class="min-w-0 flex-1"></div>
{/if}
{#if query} <Dropdown align="end">
<Tooltip content={$i18n.t('Actions')}>
<button <button
class="flex h-7 items-center gap-1.5 rounded-lg bg-transparent px-1.5 text-xs text-gray-500 transition-colors hover:text-gray-900 dark:text-gray-500 dark:hover:text-white"
type="button" type="button"
class={actionButtonClass}
on:click={() => {
query = '';
}}
> >
{$i18n.t('Clear')} <span>{$i18n.t('Actions')}</span>
<ChevronDown className="size-3" strokeWidth="2.5" />
</button> </button>
{/if} </Tooltip>
</div>
{/if} <div slot="content">
<DropdownMenu className="w-[170px] shadow-sm">
<button
class="flex h-[1.6875rem] w-full cursor-pointer select-none items-center gap-2 rounded-lg bg-transparent px-2 text-xs hover:text-gray-900 disabled:cursor-default disabled:opacity-30 dark:hover:text-gray-100"
type="button"
on:click={() => {
selectedMemory = null;
showMemoryModal = true;
}}
>
<Plus className="size-3.5 shrink-0" strokeWidth="1.5" />
<div class="min-w-0 flex-1 truncate text-left">{$i18n.t('Add Memory')}</div>
</button>
<button
class="flex h-[1.6875rem] w-full cursor-pointer select-none items-center gap-2 rounded-lg bg-transparent px-2 text-xs hover:text-gray-900 disabled:cursor-default disabled:opacity-30 dark:hover:text-gray-100"
disabled={memories.length === 0}
type="button"
on:click={() => {
showClearConfirmDialog = true;
}}
>
<Trash className="size-3.5 shrink-0" strokeWidth="1.5" />
<div class="min-w-0 flex-1 truncate text-left">{$i18n.t('Clear memory')}</div>
</button>
</DropdownMenu>
</div>
</Dropdown>
</div>
{#if sortedMemories.length === 0} {#if sortedMemories.length === 0}
<div class="min-h-16 text-[0.6875rem] text-gray-400 dark:text-gray-600"> <div class="min-h-16 text-[0.6875rem] text-gray-400 dark:text-gray-600">
@@ -0,0 +1,19 @@
<script lang="ts">
export let value = '';
export let ariaLabel = '';
export let placeholder = '';
export let className = 'w-fit min-w-32';
export let selectClassName = '';
</script>
<div class="relative inline-flex {className}">
<select
bind:value
aria-label={ariaLabel || undefined}
title={placeholder || undefined}
class="h-7 w-full truncate rounded-lg border border-gray-100/50 !bg-gray-50/40 ps-2.5 pe-9 text-left text-xs text-gray-700 outline-hidden transition-colors focus:border-blue-400 dark:border-white/[0.04] dark:!bg-white/[0.03] dark:text-gray-300 dark:focus:border-blue-500 {selectClassName}"
on:change
>
<slot />
</select>
</div>
@@ -308,7 +308,7 @@
<Modal size="lg" bind:show={showEditModal}> <Modal size="lg" bind:show={showEditModal}>
<div class="px-4 pt-3 pb-4"> <div class="px-4 pt-3 pb-4">
<div class="flex justify-between items-center mb-2 dark:text-gray-100"> <div class="flex justify-between items-center mb-2 dark:text-gray-100">
<div class="text-sm font-medium">{$i18n.t('Edit Prompt')}</div> <div class="text-xs">{$i18n.t('Edit Prompt')}</div>
<button <button
class="rounded-lg p-1 text-gray-500 transition hover:bg-gray-50 hover:text-gray-700 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-gray-200" class="rounded-lg p-1 text-gray-500 transition hover:bg-gray-50 hover:text-gray-700 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-gray-200"
aria-label={$i18n.t('Close')} aria-label={$i18n.t('Close')}
@@ -326,7 +326,7 @@
<div class="mt-1"> <div class="mt-1">
<Textarea <Textarea
className="text-sm w-full bg-transparent outline-hidden overflow-y-hidden resize-none" className="text-xs w-full bg-transparent outline-hidden overflow-y-hidden resize-none"
placeholder={$i18n.t('Write a summary in 50 words that summarizes {{topic}}.')} placeholder={$i18n.t('Write a summary in 50 words that summarizes {{topic}}.')}
bind:value={content} bind:value={content}
aria-label={$i18n.t('Prompt Content')} aria-label={$i18n.t('Prompt Content')}
@@ -340,7 +340,7 @@
<div class="text-gray-500 text-xs">{$i18n.t('Commit Message')} ({$i18n.t('optional')})</div> <div class="text-gray-500 text-xs">{$i18n.t('Commit Message')} ({$i18n.t('optional')})</div>
<div class="mt-1"> <div class="mt-1">
<input <input
class="text-sm w-full bg-transparent outline-hidden" class="w-full bg-transparent text-xs outline-hidden"
placeholder={$i18n.t('Describe what changed...')} placeholder={$i18n.t('Describe what changed...')}
aria-label={$i18n.t('Commit Message')} aria-label={$i18n.t('Commit Message')}
bind:value={commitMessage} bind:value={commitMessage}
@@ -355,13 +355,13 @@
bind:checked={isProduction} bind:checked={isProduction}
class="w-4 h-4 rounded border-gray-300 dark:border-gray-600" class="w-4 h-4 rounded border-gray-300 dark:border-gray-600"
/> />
<span class="text-sm text-gray-700 dark:text-gray-300" <span class="text-xs text-gray-700 dark:text-gray-300"
>{$i18n.t('Set as Production')}</span >{$i18n.t('Set as Production')}</span
> >
</label> </label>
<div> <div>
<button <button
class="text-sm px-4 py-2 transition rounded-full {loading class="px-3 py-1.5 text-xs transition rounded-full {loading
? 'cursor-not-allowed bg-gray-200 text-gray-500 dark:bg-gray-700 dark:text-gray-400' ? 'cursor-not-allowed bg-gray-200 text-gray-500 dark:bg-gray-700 dark:text-gray-400'
: 'bg-black hover:bg-gray-900 text-white dark:bg-white dark:hover:bg-gray-100 dark:text-black'} flex justify-center" : 'bg-black hover:bg-gray-900 text-white dark:bg-white dark:hover:bg-gray-100 dark:text-black'} flex justify-center"
type="submit" type="submit"
@@ -387,14 +387,14 @@
<div class="flex items-start justify-between gap-4 shrink-0"> <div class="flex items-start justify-between gap-4 shrink-0">
<div class="min-w-0 flex-1"> <div class="min-w-0 flex-1">
<input <input
class="text-2xl w-full bg-transparent outline-hidden" class="w-full bg-transparent text-sm outline-hidden"
placeholder={$i18n.t('Prompt Name')} placeholder={$i18n.t('Prompt Name')}
bind:value={name} bind:value={name}
on:input={debouncedSaveMetadata} on:input={debouncedSaveMetadata}
{disabled} {disabled}
/> />
<div class="flex items-center gap-0.5 text-sm text-gray-500 w-full flex-1"> <div class="flex w-full flex-1 items-center gap-0.5 text-xs text-gray-500">
<span>/</span> <span>/</span>
<input <input
class="bg-transparent outline-hidden" class="bg-transparent outline-hidden"
@@ -410,13 +410,13 @@
<div class="flex items-center gap-2 shrink-0 justify-end"> <div class="flex items-center gap-2 shrink-0 justify-end">
{#if !disabled} {#if !disabled}
<button <button
class="px-4 py-1 text-sm font-normal bg-black text-white dark:bg-white dark:text-black rounded-full hover:opacity-90 transition shadow-xs" class="flex shrink-0 items-center rounded-lg bg-gray-50 px-2 py-1 text-xs text-gray-900 ring-1 ring-gray-200 transition hover:bg-gray-100 dark:bg-gray-850 dark:text-gray-100 dark:ring-gray-800 dark:hover:bg-gray-800"
on:click={() => (showEditModal = true)} on:click={() => (showEditModal = true)}
> >
{$i18n.t('Edit')} {$i18n.t('Edit')}
</button> </button>
<AccessButton on:click={() => (showAccessControlModal = true)} /> <AccessButton on:click={() => (showAccessControlModal = true)} />
{:else} {:else}
<span class="text-xs text-gray-500 bg-gray-100 dark:bg-gray-800 px-2 py-1 rounded-full" <span class="text-xs text-gray-500 bg-gray-100 dark:bg-gray-800 px-2 py-1 rounded-full"
>{$i18n.t('Read Only')}</span >{$i18n.t('Read Only')}</span
@@ -424,7 +424,7 @@
{/if} {/if}
</div> </div>
<div class="mt-1.5"> <div>
<Tooltip content={$i18n.t('Click to copy ID')}> <Tooltip content={$i18n.t('Click to copy ID')}>
<button <button
class="text-xs text-gray-500 font-mono px-2 py-1 rounded-lg cursor-pointer hover:underline transition" class="text-xs text-gray-500 font-mono px-2 py-1 rounded-lg cursor-pointer hover:underline transition"
@@ -458,9 +458,9 @@
</div> </div>
</div> </div>
<div class="flex flex-col md:flex-row gap-4 flex-1 overflow-hidden pb-6"> <div class="flex flex-1 flex-col gap-3 overflow-hidden pb-4 md:flex-row">
<!-- Desktop History Sidebar --> <!-- Desktop History Sidebar -->
<div class="hidden md:flex md:flex-col w-72 shrink-0 overflow-hidden"> <div class="hidden w-64 shrink-0 overflow-hidden md:flex md:flex-col">
<div class="flex-1 overflow-y-auto"> <div class="flex-1 overflow-y-auto">
{@render historySection()} {@render historySection()}
</div> </div>
@@ -474,9 +474,7 @@
{$i18n.t('Prompt Content')} {$i18n.t('Prompt Content')}
</div> </div>
{#if selectedHistoryEntry} {#if selectedHistoryEntry}
<span <span class="px-1 font-mono text-xs text-gray-500">
class="text-xs text-gray-500 font-mono bg-gray-100 dark:bg-gray-800 px-1.5 rounded"
>
{selectedHistoryEntry.id.slice(0, 7)} {selectedHistoryEntry.id.slice(0, 7)}
</span> </span>
{/if} {/if}
@@ -519,9 +517,7 @@
</button> </button>
</div> </div>
<!-- Scrollable content --> <!-- Scrollable content -->
<div <div class="h-full overflow-y-auto rounded-lg bg-transparent px-1 py-1">
class="bg-gray-50 dark:bg-gray-900 rounded-xl px-4 py-3 border border-gray-100/50 dark:border-gray-850/50 h-full overflow-y-auto"
>
<pre class="text-xs whitespace-pre-wrap font-mono pr-8">{selectedHistoryEntry?.snapshot <pre class="text-xs whitespace-pre-wrap font-mono pr-8">{selectedHistoryEntry?.snapshot
?.content || content}</pre> ?.content || content}</pre>
</div> </div>
@@ -534,7 +530,7 @@
<div class="w-full max-h-full {modal ? 'h-full flex flex-col' : ''}"> <div class="w-full max-h-full {modal ? 'h-full flex flex-col' : ''}">
{#if modal} {#if modal}
<div class="flex justify-between items-center dark:text-gray-100 px-5 pt-4 pb-2"> <div class="flex justify-between items-center dark:text-gray-100 px-5 pt-4 pb-2">
<h3 class="text-base font-normal">{$i18n.t('Create Prompt')}</h3> <h3 class="text-sm">{$i18n.t('Create Prompt')}</h3>
<button <button
class="self-center shrink-0 ml-2" class="self-center shrink-0 ml-2"
aria-label={$i18n.t('Close')} aria-label={$i18n.t('Close')}
@@ -560,7 +556,7 @@
<div class="flex flex-col w-full"> <div class="flex flex-col w-full">
<div class="flex items-center"> <div class="flex items-center">
<input <input
class="{modal ? 'text-base' : 'text-2xl'} w-full bg-transparent outline-hidden" class="w-full bg-transparent text-sm outline-hidden"
placeholder={$i18n.t('Name')} placeholder={$i18n.t('Name')}
bind:value={name} bind:value={name}
required required
@@ -568,7 +564,7 @@
<div class="self-center shrink-0"> <div class="self-center shrink-0">
<AccessButton on:click={() => (showAccessControlModal = true)} /> <AccessButton on:click={() => (showAccessControlModal = true)} />
</div> </div>
</div> </div>
<div class="flex gap-0.5 items-center text-xs text-gray-500"> <div class="flex gap-0.5 items-center text-xs text-gray-500">
<div>/</div> <div>/</div>
<input <input
@@ -601,14 +597,14 @@
<div class={modal ? 'mt-1 flex-1 min-h-0 flex flex-col' : 'mt-1'}> <div class={modal ? 'mt-1 flex-1 min-h-0 flex flex-col' : 'mt-1'}>
{#if modal} {#if modal}
<textarea <textarea
class="text-sm w-full flex-1 min-h-0 bg-transparent outline-hidden resize-none" class="w-full flex-1 min-h-0 resize-none bg-transparent text-xs outline-hidden"
placeholder={$i18n.t('Write a summary in 50 words that summarizes {{topic}}.')} placeholder={$i18n.t('Write a summary in 50 words that summarizes {{topic}}.')}
bind:value={content} bind:value={content}
required required
></textarea> ></textarea>
{:else} {:else}
<Textarea <Textarea
className="text-sm w-full bg-transparent outline-hidden overflow-y-hidden resize-none" className="text-xs w-full bg-transparent outline-hidden overflow-y-hidden resize-none"
placeholder={$i18n.t('Write a summary in 50 words that summarizes {{topic}}.')} placeholder={$i18n.t('Write a summary in 50 words that summarizes {{topic}}.')}
bind:value={content} bind:value={content}
rows={6} rows={6}
@@ -640,8 +636,8 @@
<button <button
class="{modal class="{modal
? 'px-3.5 py-1.5 text-sm rounded-full w-fit' ? 'px-3.5 py-1.5 text-xs rounded-full w-fit'
: 'text-sm w-full lg:w-fit px-4 py-2 rounded-xl'} transition bg-black hover:bg-gray-900 text-white dark:bg-white dark:hover:bg-gray-100 dark:text-black flex justify-center" : 'text-xs w-full lg:w-fit px-4 py-2 rounded-xl'} transition bg-black hover:bg-gray-900 text-white dark:bg-white dark:hover:bg-gray-100 dark:text-black flex justify-center"
type="submit" type="submit"
disabled={loading} disabled={loading}
> >
@@ -669,10 +665,10 @@
<div class="flex"> <div class="flex">
<!-- Content --> <!-- Content -->
<button <button
class="flex-1 text-left px-3.5 py-2 mb-1 rounded-2xl transition group class="mb-0.5 flex-1 rounded-lg px-2 py-1.5 text-left transition group
{selectedHistoryEntry?.id === entry.id {selectedHistoryEntry?.id === entry.id
? 'bg-gray-100/50 dark:bg-gray-850/50' ? 'bg-gray-50/60 dark:bg-white/[0.03]'
: 'hover:bg-gray-100/50 dark:hover:bg-gray-850/50'}" : 'hover:bg-gray-50/60 dark:hover:bg-white/[0.03]'}"
on:click={() => (selectedHistoryEntry = entry)} on:click={() => (selectedHistoryEntry = entry)}
> >
<!-- Commit Message --> <!-- Commit Message -->
@@ -100,5 +100,11 @@
</script> </script>
{#key model} {#key model}
<ModelEditor {model} {onSubmit} /> <ModelEditor
{model}
{onSubmit}
onBack={async () => {
await goto('/workspace/models');
}}
/>
{/key} {/key}
@@ -52,5 +52,12 @@
</script> </script>
{#if model} {#if model}
<ModelEditor edit={true} {model} {onSubmit} /> <ModelEditor
edit={true}
{model}
{onSubmit}
onBack={async () => {
await goto('/workspace/models');
}}
/>
{/if} {/if}