diff --git a/src/lib/components/EditConversationModal.svelte b/src/lib/components/EditConversationModal.svelte index 54badb0f34e..d421d54737f 100644 --- a/src/lib/components/EditConversationModal.svelte +++ b/src/lib/components/EditConversationModal.svelte @@ -11,10 +11,10 @@ let { open = false, title = "", onclose, onsave }: Props = $props(); - let newTitle = $state(title); + let newTitle = $state(""); let inputEl: HTMLInputElement | undefined = $state(); - $effect(() => { + $effect.pre(() => { // keep local input in sync if parent changes title while open if (open) { newTitle = title; diff --git a/src/lib/components/NavConversationItem.svelte b/src/lib/components/NavConversationItem.svelte index 45b519eeed9..2cb7fbf6ae1 100644 --- a/src/lib/components/NavConversationItem.svelte +++ b/src/lib/components/NavConversationItem.svelte @@ -66,7 +66,6 @@ }} > {#if inlineEditing} - { if (messages.length > prevMessageCount) { diff --git a/src/lib/components/chat/MarkdownRenderer.svelte b/src/lib/components/chat/MarkdownRenderer.svelte index 7c7d4ee13cc..f4bc1b6c774 100644 --- a/src/lib/components/chat/MarkdownRenderer.svelte +++ b/src/lib/components/chat/MarkdownRenderer.svelte @@ -15,21 +15,22 @@ let { content, sources = [], loading = false }: Props = $props(); - let blocks: BlockToken[] = $state(processBlocksSync(content, sources)); + // Sync-computed blocks used as fallback and for SSR (where effects don't run) + let syncBlocks = $derived(processBlocksSync(content, sources)); + let workerBlocks: BlockToken[] | null = $state(null); + let blocks = $derived(workerBlocks ?? syncBlocks); + let worker: Worker | null = null; let latestRequestId = 0; function handleBlocks(result: BlockToken[], requestId: number) { if (requestId !== latestRequestId) return; - blocks = result; + workerBlocks = result; updateDebouncer.endRender(); } $effect(() => { - if (!browser) { - blocks = processBlocksSync(content, sources); - return; - } + if (!browser) return; const requestId = ++latestRequestId; @@ -42,7 +43,6 @@ (async () => { updateDebouncer.startRender(); const processed = await processBlocks(content, sources); - // Only apply if this is still the latest request handleBlocks(processed, requestId); })(); }); diff --git a/src/lib/components/chat/ModelSwitch.svelte b/src/lib/components/chat/ModelSwitch.svelte index 46863f47068..e02743b198d 100644 --- a/src/lib/components/chat/ModelSwitch.svelte +++ b/src/lib/components/chat/ModelSwitch.svelte @@ -11,9 +11,13 @@ let { models, currentModel }: Props = $props(); - let selectedModelId = $state( - models.map((m) => m.id).includes(currentModel.id) ? currentModel.id : models[0].id - ); + let selectedModelId = $state(""); + + $effect.pre(() => { + selectedModelId = models.map((m) => m.id).includes(currentModel.id) + ? currentModel.id + : models[0].id; + }); async function handleModelChange() { if (!page.params.id) return; diff --git a/src/lib/components/mcp/AddServerForm.svelte b/src/lib/components/mcp/AddServerForm.svelte index 96a389b5202..a5bc035d5bf 100644 --- a/src/lib/components/mcp/AddServerForm.svelte +++ b/src/lib/components/mcp/AddServerForm.svelte @@ -29,9 +29,15 @@ submitLabel = "Add Server", }: Props = $props(); - let name = $state(initialName); - let url = $state(initialUrl); - let headers = $state(initialHeaders.length > 0 ? [...initialHeaders] : []); + let name = $state(""); + let url = $state(""); + let headers = $state([]); + + $effect.pre(() => { + name = initialName; + url = initialUrl; + headers = initialHeaders.length > 0 ? [...initialHeaders] : []; + }); let showHeaderValues = $state>({}); let error = $state(null); diff --git a/src/lib/components/players/AudioPlayer.svelte b/src/lib/components/players/AudioPlayer.svelte index e95baf2411f..8883c25c438 100644 --- a/src/lib/components/players/AudioPlayer.svelte +++ b/src/lib/components/players/AudioPlayer.svelte @@ -65,6 +65,12 @@ {format(time)}
{ paused = true; }} diff --git a/src/lib/migrations/routines/09-delete-empty-conversations.spec.ts b/src/lib/migrations/routines/09-delete-empty-conversations.spec.ts index 427fb0a67d0..b4a147f942e 100644 --- a/src/lib/migrations/routines/09-delete-empty-conversations.spec.ts +++ b/src/lib/migrations/routines/09-delete-empty-conversations.spec.ts @@ -4,7 +4,7 @@ import type { Conversation } from "$lib/types/Conversation"; import { ObjectId } from "mongodb"; import { deleteConversations } from "./09-delete-empty-conversations"; import { afterAll, afterEach, beforeAll, describe, expect, test } from "vitest"; -import { collections } from "$lib/server/database"; +import { collections, ready } from "$lib/server/database"; type Message = Conversation["messages"][number]; @@ -190,25 +190,26 @@ describe.sequential("Deleting discarded conversations", async () => { expect(result).toBe(10010); }); -}); -beforeAll(async () => { - await collections.users.insertOne(userData); - await collections.sessions.insertOne(sessionForUser); -}, 20000); + beforeAll(async () => { + await ready; + await collections.users.insertOne(userData); + await collections.sessions.insertOne(sessionForUser); + }, 20000); -afterAll(async () => { - await collections.users.deleteOne({ - _id: userData._id, - }); - await collections.sessions.deleteOne({ - _id: sessionForUser._id, + afterAll(async () => { + await collections.users.deleteOne({ + _id: userData._id, + }); + await collections.sessions.deleteOne({ + _id: sessionForUser._id, + }); + await collections.conversations.deleteMany({}); }); - await collections.conversations.deleteMany({}); -}); -afterEach(async () => { - await collections.conversations.deleteMany({ - _id: { $in: [conversationBase._id] }, + afterEach(async () => { + await collections.conversations.deleteMany({ + _id: { $in: [conversationBase._id] }, + }); }); });