refac
This commit is contained in:
1 parent
83ec36cd38
commit
fa76764c3b
6 files changed
+149
-22
No files matched your search
@@ -167,6 +167,31 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-2.5 flex w-full justify-between">
|
||||
<div class="self-center text-xs font-medium">
|
||||
{$i18n.t('Web Search Confirmation')}
|
||||
</div>
|
||||
<div class="flex items-center relative">
|
||||
<Tooltip content={$i18n.t('Require users to confirm before using Web Search.')}>
|
||||
<Switch bind:state={webConfig.ENABLE_WEB_SEARCH_CONFIRMATION} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if webConfig.ENABLE_WEB_SEARCH_CONFIRMATION}
|
||||
<div class="mb-2.5">
|
||||
<div class="self-center text-xs font-medium mb-2">
|
||||
{$i18n.t('Web Search Confirmation Content')}
|
||||
</div>
|
||||
<Textarea
|
||||
placeholder={$i18n.t(
|
||||
'Your query will be sent to the configured web search provider.'
|
||||
)}
|
||||
bind:value={webConfig.WEB_SEARCH_CONFIRMATION_CONTENT}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class=" mb-2.5 flex w-full justify-between">
|
||||
<div class=" self-center text-xs font-medium">
|
||||
{$i18n.t('Web Search Engine')}
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
import ChatControls from './ChatControls.svelte';
|
||||
import EventConfirmDialog from '../common/ConfirmDialog.svelte';
|
||||
import DeleteConfirmDialog from '../common/ConfirmDialog.svelte';
|
||||
import WebSearchConfirmDialog from '../common/ConfirmDialog.svelte';
|
||||
import Placeholder from './Placeholder.svelte';
|
||||
import FilesOverlay from './MessageInput/FilesOverlay.svelte';
|
||||
import NotificationToast from '../NotificationToast.svelte';
|
||||
@@ -139,6 +140,7 @@
|
||||
let eventConfirmationInputPlaceholder = '';
|
||||
let eventConfirmationInputValue = '';
|
||||
let eventConfirmationInputType = '';
|
||||
let eventConfirmationInputOptions: ({ label?: string; value: string } | string)[] = [];
|
||||
let eventCallback = null;
|
||||
|
||||
let selectedModels = [''];
|
||||
@@ -158,6 +160,49 @@
|
||||
let imageGenerationEnabled = false;
|
||||
let webSearchEnabled = false;
|
||||
let codeInterpreterEnabled = false;
|
||||
let webSearchActive = false;
|
||||
let showWebSearchConfirm = false;
|
||||
let pendingWebSearchPrompt: string | null = null;
|
||||
let webSearchConfirmed = false;
|
||||
|
||||
$: {
|
||||
const currentModels = atSelectedModel?.id ? [atSelectedModel.id] : selectedModels;
|
||||
const allModelsSupportWebSearch =
|
||||
currentModels.filter(
|
||||
(model) => $models.find((m) => m.id === model)?.info?.meta?.capabilities?.web_search ?? true
|
||||
).length === currentModels.length;
|
||||
|
||||
webSearchActive = Boolean(
|
||||
$config?.features?.enable_web_search &&
|
||||
($user?.role === 'admin' || $user?.permissions?.features?.web_search) &&
|
||||
(webSearchEnabled ||
|
||||
(allModelsSupportWebSearch && ($settings?.webSearch ?? false) === 'always'))
|
||||
);
|
||||
}
|
||||
|
||||
const openWebSearchConfirm = () => {
|
||||
window.setTimeout(() => {
|
||||
showWebSearchConfirm = true;
|
||||
}, 0);
|
||||
};
|
||||
|
||||
const handleWebSearchToggle = (enabled: boolean) => {
|
||||
if (enabled && $config?.features?.enable_web_search_confirmation && !webSearchConfirmed) {
|
||||
webSearchEnabled = false;
|
||||
pendingWebSearchPrompt = null;
|
||||
openWebSearchConfirm();
|
||||
}
|
||||
};
|
||||
|
||||
const resetWebSearchConfirmation = () => {
|
||||
webSearchConfirmed = false;
|
||||
pendingWebSearchPrompt = null;
|
||||
showWebSearchConfirm = false;
|
||||
};
|
||||
|
||||
$: if (!webSearchActive) {
|
||||
resetWebSearchConfirmation();
|
||||
}
|
||||
|
||||
let showCommands = false;
|
||||
|
||||
@@ -671,6 +716,7 @@
|
||||
|
||||
eventConfirmationInput = false;
|
||||
showEventConfirmation = true;
|
||||
eventConfirmationInputOptions = [];
|
||||
|
||||
eventConfirmationTitle = data.title;
|
||||
eventConfirmationMessage = data.message;
|
||||
@@ -698,7 +744,8 @@
|
||||
eventConfirmationMessage = data.message;
|
||||
eventConfirmationInputPlaceholder = data.placeholder;
|
||||
eventConfirmationInputValue = data?.value ?? '';
|
||||
eventConfirmationInputType = data?.type ?? '';
|
||||
eventConfirmationInputType = data?.input?.type ?? data?.type ?? '';
|
||||
eventConfirmationInputOptions = data?.input?.options ?? data?.options ?? [];
|
||||
} else if (type.startsWith('terminal:')) {
|
||||
terminalEventHandler(type, data);
|
||||
} else {
|
||||
@@ -819,11 +866,25 @@
|
||||
} catch {}
|
||||
};
|
||||
|
||||
const handleSocketConnect = async () => {
|
||||
if (!chatIdProp || $temporaryChatEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentMessage = history.currentId ? history.messages[history.currentId] : null;
|
||||
if (currentMessage?.role !== 'assistant' || currentMessage.done) {
|
||||
return;
|
||||
}
|
||||
|
||||
await loadChat();
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
loading = true;
|
||||
console.log('mounted');
|
||||
window.addEventListener('message', onMessageHandler);
|
||||
$socket?.on('events', chatEventHandler);
|
||||
$socket?.on('connect', handleSocketConnect);
|
||||
|
||||
$audioQueue?.destroy();
|
||||
|
||||
@@ -940,6 +1001,7 @@
|
||||
selectedFolderSubscribe();
|
||||
window.removeEventListener('message', onMessageHandler);
|
||||
$socket?.off('events', chatEventHandler);
|
||||
$socket?.off('connect', handleSocketConnect);
|
||||
dismissContextCompactionToast();
|
||||
audioQueueInstance?.destroy();
|
||||
audioQueue.set(null);
|
||||
@@ -1203,6 +1265,7 @@
|
||||
|
||||
const initNewChat = async () => {
|
||||
console.log('initNewChat');
|
||||
resetWebSearchConfirmation();
|
||||
|
||||
// Mark the outgoing chat as read before resetting; in-place created chats
|
||||
// keep chatIdProp undefined, so navigateHandler never marks them read.
|
||||
@@ -2080,6 +2143,16 @@
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
$config?.features?.enable_web_search_confirmation &&
|
||||
webSearchActive &&
|
||||
!webSearchConfirmed
|
||||
) {
|
||||
pendingWebSearchPrompt = userPrompt ?? '';
|
||||
openWebSearchConfirm();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the assistant is still generating the main response
|
||||
// (don't block on background tasks like title gen, follow-ups, tags)
|
||||
const lastMessage = history.currentId ? history.messages[history.currentId] : null;
|
||||
@@ -2278,24 +2351,9 @@
|
||||
($user?.role === 'admin' || $user?.permissions?.features?.code_interpreter)
|
||||
? codeInterpreterEnabled
|
||||
: false,
|
||||
web_search:
|
||||
$config?.features?.enable_web_search &&
|
||||
($user?.role === 'admin' || $user?.permissions?.features?.web_search)
|
||||
? webSearchEnabled
|
||||
: false
|
||||
web_search: webSearchActive
|
||||
};
|
||||
|
||||
const currentModels = atSelectedModel?.id ? [atSelectedModel.id] : selectedModels;
|
||||
if (
|
||||
currentModels.filter(
|
||||
(model) => $models.find((m) => m.id === model)?.info?.meta?.capabilities?.web_search ?? true
|
||||
).length === currentModels.length
|
||||
) {
|
||||
if ($config?.features?.enable_web_search && ($settings?.webSearch ?? false) === 'always') {
|
||||
features = { ...features, web_search: true };
|
||||
}
|
||||
}
|
||||
|
||||
if ($settings?.memory ?? $config?.features?.enable_memories ?? false) {
|
||||
features = { ...features, memory: true };
|
||||
}
|
||||
@@ -2981,6 +3039,18 @@
|
||||
|
||||
let showDeleteConfirm = false;
|
||||
|
||||
const confirmWebSearch = async () => {
|
||||
const userPrompt = pendingWebSearchPrompt;
|
||||
pendingWebSearchPrompt = null;
|
||||
webSearchConfirmed = true;
|
||||
|
||||
if (userPrompt !== null) {
|
||||
await submitHandler(userPrompt);
|
||||
} else {
|
||||
webSearchEnabled = true;
|
||||
}
|
||||
};
|
||||
|
||||
const deleteChatHandler = async (id: string) => {
|
||||
showDeleteConfirm = true;
|
||||
};
|
||||
@@ -3017,6 +3087,23 @@
|
||||
|
||||
<audio id="audioElement" style="display: none;"></audio>
|
||||
|
||||
<WebSearchConfirmDialog
|
||||
bind:show={showWebSearchConfirm}
|
||||
title={$i18n.t('Use Web Search?')}
|
||||
message={($config?.features?.web_search_confirmation_content ?? '').trim() !== ''
|
||||
? ($config?.features?.web_search_confirmation_content ?? '')
|
||||
: $i18n.t('Your query will be sent to the configured web search provider.')}
|
||||
confirmLabel={$i18n.t('Continue')}
|
||||
cancelLabel={$i18n.t('Cancel')}
|
||||
on:confirm={confirmWebSearch}
|
||||
on:cancel={() => {
|
||||
if (pendingWebSearchPrompt === null) {
|
||||
webSearchEnabled = false;
|
||||
}
|
||||
pendingWebSearchPrompt = null;
|
||||
}}
|
||||
/>
|
||||
|
||||
<DeleteConfirmDialog
|
||||
bind:show={showDeleteConfirm}
|
||||
title={$i18n.t('Delete chat?')}
|
||||
@@ -3037,8 +3124,11 @@
|
||||
inputPlaceholder={eventConfirmationInputPlaceholder}
|
||||
inputValue={eventConfirmationInputValue}
|
||||
inputType={eventConfirmationInputType}
|
||||
inputOptions={eventConfirmationInputOptions}
|
||||
on:confirm={(e) => {
|
||||
if (e.detail) {
|
||||
if (eventConfirmationInput) {
|
||||
eventCallback(e.detail);
|
||||
} else if (e.detail) {
|
||||
eventCallback(e.detail);
|
||||
} else {
|
||||
eventCallback(true);
|
||||
@@ -3257,6 +3347,7 @@
|
||||
saveDraft(data, $chatId);
|
||||
}
|
||||
}}
|
||||
onWebSearchToggle={handleWebSearchToggle}
|
||||
on:submit={async (e) => {
|
||||
clearDraft($chatId);
|
||||
if (e.detail || files.length > 0) {
|
||||
@@ -3298,6 +3389,7 @@
|
||||
{createMessagePair}
|
||||
{onSelect}
|
||||
{onUpload}
|
||||
onWebSearchToggle={handleWebSearchToggle}
|
||||
onChange={(data) => {
|
||||
if (!$temporaryChatEnabled) {
|
||||
saveDraft(data);
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
|
||||
export let onUpload: Function = (e) => {};
|
||||
export let onChange: Function = () => {};
|
||||
export let onWebSearchToggle: Function = () => {};
|
||||
|
||||
export let createMessagePair: Function;
|
||||
export let stopResponse: Function;
|
||||
@@ -1763,6 +1764,7 @@
|
||||
bind:webSearchEnabled
|
||||
bind:imageGenerationEnabled
|
||||
bind:codeInterpreterEnabled
|
||||
{onWebSearchToggle}
|
||||
closeOnOutsideClick={integrationsMenuCloseOnOutsideClick}
|
||||
onShowValves={(e) => {
|
||||
const { type, id } = e;
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
|
||||
export let onShowValves: Function;
|
||||
export let onClose: Function;
|
||||
export let onWebSearchToggle: Function = () => {};
|
||||
export let closeOnOutsideClick = true;
|
||||
|
||||
let show = false;
|
||||
@@ -270,9 +271,12 @@
|
||||
<button
|
||||
class="flex w-full justify-between gap-2 items-center px-3 py-1.5 text-sm cursor-pointer rounded-xl hover:bg-gray-50 dark:hover:bg-gray-800/50"
|
||||
aria-pressed={webSearchEnabled}
|
||||
aria-label={webSearchEnabled ? $i18n.t('Disable Web Search') : $i18n.t('Enable Web Search')}
|
||||
aria-label={webSearchEnabled
|
||||
? $i18n.t('Disable Web Search')
|
||||
: $i18n.t('Enable Web Search')}
|
||||
on:click={() => {
|
||||
webSearchEnabled = !webSearchEnabled;
|
||||
onWebSearchToggle(webSearchEnabled);
|
||||
}}
|
||||
>
|
||||
<div class="flex-1 truncate">
|
||||
@@ -303,7 +307,9 @@
|
||||
<button
|
||||
class="flex w-full justify-between gap-2 items-center px-3 py-1.5 text-sm cursor-pointer rounded-xl hover:bg-gray-50 dark:hover:bg-gray-800/50"
|
||||
aria-pressed={imageGenerationEnabled}
|
||||
aria-label={imageGenerationEnabled ? $i18n.t('Disable Image Generation') : $i18n.t('Enable Image Generation')}
|
||||
aria-label={imageGenerationEnabled
|
||||
? $i18n.t('Disable Image Generation')
|
||||
: $i18n.t('Enable Image Generation')}
|
||||
on:click={() => {
|
||||
imageGenerationEnabled = !imageGenerationEnabled;
|
||||
}}
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
export let onUpload: Function = (e) => {};
|
||||
export let onSelect = (e) => {};
|
||||
export let onChange = (e) => {};
|
||||
export let onWebSearchToggle: Function = () => {};
|
||||
|
||||
export let toolServers = [];
|
||||
|
||||
@@ -244,6 +245,7 @@
|
||||
placeholder={$i18n.t('How can I help you today?')}
|
||||
{onChange}
|
||||
{onUpload}
|
||||
{onWebSearchToggle}
|
||||
on:submit={(e) => {
|
||||
dispatch('submit', e.detail);
|
||||
}}
|
||||
|
||||
Reference in new issue
Block a user