This commit is contained in:
Timothy Jaeryang Baek
2025-12-21 17:04:39 +04:00
parent 4fd790f7dd
commit 7746e9f4b8
8 changed files with 94 additions and 103 deletions

View File

@@ -53,7 +53,8 @@
getPromptVariables,
processDetails,
removeAllDetails,
getCodeBlockContents
getCodeBlockContents,
isYoutubeUrl
} from '$lib/utils';
import { AudioQueue } from '$lib/utils/audio';
@@ -773,69 +774,61 @@
}
};
const uploadWeb = async (url) => {
console.log(url);
const fileItem = {
type: 'text',
name: url,
collection_name: '',
status: 'uploading',
url: url,
error: ''
};
try {
files = [...files, fileItem];
const res = await processWeb(localStorage.token, '', url);
if (res) {
fileItem.status = 'uploaded';
fileItem.collection_name = res.collection_name;
fileItem.file = {
...res.file,
...fileItem.file
};
files = files;
}
} catch (e) {
// Remove the failed doc from the files array
files = files.filter((f) => f.name !== url);
toast.error(JSON.stringify(e));
const uploadWeb = async (urls) => {
if (!Array.isArray(urls)) {
urls = [urls];
}
};
const uploadYoutubeTranscription = async (url) => {
console.log(url);
// deduplicate URLs
urls = [...new Set(urls)];
const fileItem = {
// Create file items first
const fileItems = urls.map((url) => ({
type: 'text',
name: url,
collection_name: '',
status: 'uploading',
context: 'full',
url: url,
url,
error: ''
};
}));
try {
files = [...files, fileItem];
const res = await processYoutubeVideo(localStorage.token, url);
// Display all items at once
files = [...files, ...fileItems];
if (res) {
fileItem.status = 'uploaded';
fileItem.collection_name = res.collection_name;
fileItem.file = {
...res.file,
...fileItem.file
};
files = files;
// Process sequentially (NOT parallel)
for (const fileItem of fileItems) {
try {
const res = isYoutubeUrl(fileItem.url)
? await processYoutubeVideo(localStorage.token, fileItem.url)
: await processWeb(localStorage.token, '', fileItem.url);
if (res) {
fileItem.status = 'uploaded';
fileItem.collection_name = res.collection_name;
fileItem.file = {
...res.file,
...fileItem.file
};
}
} catch (e) {
fileItem.status = 'error';
fileItem.error = String(e);
toast.error(`${e}`);
}
} catch (e) {
// Remove the failed doc from the files array
files = files.filter((f) => f.name !== url);
toast.error(`${e}`);
// Force UI reactivity after each file finishes
files = [...files];
}
};
const onUpload = async (event) => {
const { type, data } = event;
if (type === 'google-drive') {
await uploadGoogleDriveFile(data);
} else if (type === 'web') {
await uploadWeb(data);
}
};
@@ -1010,9 +1003,7 @@
params = {};
if ($page.url.searchParams.get('youtube')) {
uploadYoutubeTranscription(
`https://www.youtube.com/watch?v=${$page.url.searchParams.get('youtube')}`
);
await uploadWeb(`https://www.youtube.com/watch?v=${$page.url.searchParams.get('youtube')}`);
}
if ($page.url.searchParams.get('load-url')) {
@@ -2532,22 +2523,12 @@
{generating}
{stopResponse}
{createMessagePair}
{onUpload}
onChange={(data) => {
if (!$temporaryChatEnabled) {
saveDraft(data, $chatId);
}
}}
on:upload={async (e) => {
const { type, data } = e.detail;
if (type === 'web') {
await uploadWeb(data);
} else if (type === 'youtube') {
await uploadYoutubeTranscription(data);
} else if (type === 'google-drive') {
await uploadGoogleDriveFile(data);
}
}}
on:submit={async (e) => {
clearDraft();
if (e.detail || files.length > 0) {
@@ -2584,20 +2565,12 @@
{stopResponse}
{createMessagePair}
{onSelect}
{onUpload}
onChange={(data) => {
if (!$temporaryChatEnabled) {
saveDraft(data);
}
}}
on:upload={async (e) => {
const { type, data } = e.detail;
if (type === 'web') {
await uploadWeb(data);
} else if (type === 'youtube') {
await uploadYoutubeTranscription(data);
}
}}
on:submit={async (e) => {
clearDraft();
if (e.detail || files.length > 0) {

View File

@@ -94,6 +94,7 @@
const i18n = getContext('i18n');
export let onChange: Function = () => {};
export let createMessagePair: Function;
export let stopResponse: Function;
@@ -848,7 +849,7 @@
}
];
} else {
dispatch('upload', e);
onUpload(e);
}
}
})
@@ -883,7 +884,7 @@
}
];
} else {
dispatch('upload', e);
onUpload(e);
}
}
})
@@ -918,7 +919,7 @@
}
];
} else {
dispatch('upload', e);
onUpload(e);
}
}
})
@@ -1487,9 +1488,7 @@
console.error('OneDrive Error:', error);
}
}}
onUpload={async (e) => {
dispatch('upload', e);
}}
{onUpload}
onClose={async () => {
await tick();

View File

@@ -7,7 +7,7 @@
import Modal from '$lib/components/common/Modal.svelte';
import XMark from '$lib/components/icons/XMark.svelte';
import { isValidHttpUrl, isYoutubeUrl } from '$lib/utils';
import { isValidHttpUrl } from '$lib/utils';
export let show = false;
export let onSubmit: (e) => void;
@@ -15,17 +15,20 @@
let url = '';
const submitHandler = () => {
if (isValidHttpUrl(url)) {
onSubmit({
type: isYoutubeUrl(url) ? 'youtube' : 'web',
data: url
});
const urls = url
.split('\n')
.map((u) => u.trim())
.filter((u) => u !== '')
.filter((u) => isValidHttpUrl(u));
show = false;
url = '';
} else {
if (urls.length === 0) {
toast.error($i18n.t('Please enter a valid URL.'));
return;
}
onSubmit({ type: 'web', data: urls });
show = false;
url = '';
};
</script>
@@ -57,15 +60,16 @@
<label
for="webpage-url"
class={`text-xs ${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100' : 'text-gray-500'}`}
>{$i18n.t('Webpage URL')}</label
>{$i18n.t('Webpage URLs')}</label
>
</div>
<input
<textarea
id="webpage-url"
class={`w-full flex-1 text-sm bg-transparent ${($settings?.highContrastMode ?? false) ? 'placeholder:text-gray-700 dark:placeholder:text-gray-100' : 'outline-hidden placeholder:text-gray-300 dark:placeholder:text-gray-700'}`}
type="text"
bind:value={url}
rows="3"
placeholder={'https://example.com'}
autocomplete="off"
required

View File

@@ -110,13 +110,6 @@
type: 'file',
data: data
});
} else if (type === 'youtube') {
insertTextHandler('');
onUpload({
type: 'youtube',
data: data
});
} else if (type === 'web') {
insertTextHandler('');

View File

@@ -216,7 +216,7 @@
on:click={() => {
if (isValidHttpUrl(query)) {
onSelect({
type: 'youtube',
type: 'web',
data: query
});
} else {

View File

@@ -54,6 +54,7 @@
export let codeInterpreterEnabled = false;
export let webSearchEnabled = false;
export let onUpload: Function = (e) => {};
export let onSelect = (e) => {};
export let onChange = (e) => {};
@@ -216,9 +217,7 @@
{createMessagePair}
placeholder={$i18n.t('How can I help you today?')}
{onChange}
on:upload={(e) => {
dispatch('upload', e.detail);
}}
{onUpload}
on:submit={(e) => {
dispatch('submit', e.detail);
}}

View File

@@ -51,13 +51,16 @@
import FilesOverlay from '$lib/components/chat/MessageInput/FilesOverlay.svelte';
import DropdownOptions from '$lib/components/common/DropdownOptions.svelte';
import Pagination from '$lib/components/common/Pagination.svelte';
import AttachWebpageModal from '$lib/components/chat/MessageInput/AttachWebpageModal.svelte';
let largeScreen = true;
let pane;
let showSidepanel = true;
let showAddWebpageModal = false;
let showAddTextContentModal = false;
let showSyncConfirmModal = false;
let showAccessControlModal = false;
@@ -696,6 +699,13 @@
}}
/>
<AttachWebpageModal
bind:show={showAddWebpageModal}
onSubmit={async (data) => {
console.log(data);
}}
/>
<AddTextContentModal
bind:show={showAddTextContentModal}
on:submit={(e) => {
@@ -829,6 +839,8 @@
onUpload={(data) => {
if (data.type === 'directory') {
uploadDirectoryHandler();
} else if (data.type === 'web') {
showAddWebpageModal = true;
} else if (data.type === 'text') {
showAddTextContentModal = true;
} else {

View File

@@ -10,6 +10,7 @@
import BarsArrowUp from '$lib/components/icons/BarsArrowUp.svelte';
import FolderOpen from '$lib/components/icons/FolderOpen.svelte';
import ArrowPath from '$lib/components/icons/ArrowPath.svelte';
import GlobeAlt from '$lib/components/icons/GlobeAlt.svelte';
const i18n = getContext('i18n');
@@ -96,6 +97,16 @@
</DropdownMenu.Item>
</Tooltip>
<DropdownMenu.Item
class="flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl"
on:click={() => {
onUpload({ type: 'web' });
}}
>
<GlobeAlt strokeWidth="2" />
<div class="flex items-center">{$i18n.t('Add webpage')}</div>
</DropdownMenu.Item>
<DropdownMenu.Item
class="flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl"
on:click={() => {