* webui: load the model selected via ?model= Opening the WebUI with ?model= selects the model but doesn't load it. The load only starts when you send your first message, so you wait for it then. This loads it as soon as the page opens, while you're still typing your prompt. It's what the model dropdown already does, and it isn't awaited, so the UI still works while the model loads. This is the path the Llama macOS app uses to open the WebUI, so it's a common way in. * webui: gate the load behind ?load=true Loading on landing is opt-in, so a plain ?model= link behaves as before and doesn't allocate memory on its own. * webui: name the chat URL params Collects the query params the chat routes read into a URL_PARAMS constant, instead of repeating the literals across three files. NEW_CHAT_PARAM folds into it.
104 lines
3.0 KiB
Svelte
104 lines
3.0 KiB
Svelte
<script lang="ts">
|
|
import { DialogModelNotAvailable } from '$lib/components/app';
|
|
import { chatStore } from '$lib/stores/chat.svelte';
|
|
import { conversationsStore, isConversationsInitialized } from '$lib/stores/conversations.svelte';
|
|
import { modelsStore, modelOptions } from '$lib/stores/models.svelte';
|
|
import { isRouterMode } from '$lib/stores/server.svelte';
|
|
import { onMount } from 'svelte';
|
|
import { page } from '$app/state';
|
|
import { replaceState } from '$app/navigation';
|
|
import { APP_NAME, URL_PARAMS } from '$lib/constants';
|
|
|
|
let qParam = $derived(page.url.searchParams.get(URL_PARAMS.QUERY));
|
|
let modelParam = $derived(page.url.searchParams.get(URL_PARAMS.MODEL));
|
|
let newChatParam = $derived(page.url.searchParams.get(URL_PARAMS.NEW_CHAT));
|
|
let loadParam = $derived(page.url.searchParams.get(URL_PARAMS.LOAD));
|
|
|
|
// Dialog state for model not available error
|
|
let showModelNotAvailable = $state(false);
|
|
let requestedModelName = $state('');
|
|
let availableModelNames = $derived(modelOptions().map((m) => m.model));
|
|
|
|
/**
|
|
* Clear URL params after message is sent to prevent re-sending on refresh
|
|
*/
|
|
function clearUrlParams() {
|
|
const url = new URL(page.url);
|
|
|
|
url.searchParams.delete(URL_PARAMS.QUERY);
|
|
url.searchParams.delete(URL_PARAMS.MODEL);
|
|
url.searchParams.delete(URL_PARAMS.LOAD);
|
|
url.searchParams.delete(URL_PARAMS.NEW_CHAT);
|
|
|
|
replaceState(url.toString(), {});
|
|
}
|
|
|
|
async function handleUrlParams() {
|
|
await modelsStore.fetch();
|
|
|
|
if (modelParam) {
|
|
const model = modelsStore.findModelByName(modelParam);
|
|
|
|
if (model) {
|
|
try {
|
|
await modelsStore.selectModelById(model.id);
|
|
|
|
// with ?load=true, start loading right away so the model is ready sooner;
|
|
// not awaited, so the UI stays usable during the load
|
|
if (loadParam === 'true' && isRouterMode() && !modelsStore.isModelLoaded(model.id)) {
|
|
modelsStore
|
|
.loadModel(model.id)
|
|
.catch((error) => console.error('Failed to load model:', error));
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to select model:', error);
|
|
requestedModelName = modelParam;
|
|
showModelNotAvailable = true;
|
|
|
|
return;
|
|
}
|
|
} else {
|
|
requestedModelName = modelParam;
|
|
showModelNotAvailable = true;
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Handle ?q= parameter - create new conversation and send message
|
|
if (qParam !== null) {
|
|
await conversationsStore.createConversation();
|
|
clearUrlParams();
|
|
} else if (modelParam || newChatParam === 'true') {
|
|
clearUrlParams();
|
|
}
|
|
}
|
|
|
|
onMount(async () => {
|
|
if (!isConversationsInitialized()) {
|
|
await conversationsStore.initialize();
|
|
}
|
|
|
|
conversationsStore.clearActiveConversation();
|
|
chatStore.clearUIState();
|
|
|
|
await modelsStore.fetch();
|
|
|
|
if (qParam !== null || modelParam !== null || newChatParam === 'true') {
|
|
await handleUrlParams();
|
|
}
|
|
|
|
await modelsStore.ensureFirstModelSelected();
|
|
});
|
|
</script>
|
|
|
|
<svelte:head>
|
|
<title>{APP_NAME}</title>
|
|
</svelte:head>
|
|
|
|
<DialogModelNotAvailable
|
|
bind:open={showModelNotAvailable}
|
|
modelName={requestedModelName}
|
|
availableModels={availableModelNames}
|
|
/>
|