File size: 3,593 Bytes
8aab1a5
98051f8
 
 
5d291ff
ef7aeda
01b06a3
5d291ff
 
e5f4e9a
 
4ae2179
df3243b
 
 
 
8aab1a5
 
949cae0
 
5d291ff
01b06a3
df3243b
c202241
4ae2179
c202241
8aab1a5
 
feb88db
e5f4e9a
0c6af63
feb88db
 
 
 
 
 
e5f4e9a
feb88db
 
8aab1a5
 
45dbaaf
6a0861b
0c6af63
45dbaaf
 
5d291ff
949cae0
df3243b
 
 
 
 
 
 
22d10ff
 
df3243b
 
 
 
 
 
 
 
 
 
 
 
 
 
638f450
4ae2179
770735d
 
 
 
 
 
e5f4e9a
770735d
 
c51ecfb
770735d
8aab1a5
df3243b
 
 
 
 
8aab1a5
c51ecfb
f16c630
 
 
0c6af63
f16c630
949cae0
0c6af63
8aab1a5
45dbaaf
6a0861b
45dbaaf
 
8aab1a5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<script lang="ts">
	import type { Message } from "$lib/types/Message";
	import { snapScrollToBottom } from "$lib/actions/snapScrollToBottom";
	import ScrollToBottomBtn from "$lib/components/ScrollToBottomBtn.svelte";
	import { tick } from "svelte";
	import { randomUUID } from "$lib/utils/randomUuid";
	import type { Model } from "$lib/types/Model";
	import ChatIntroduction from "./ChatIntroduction.svelte";
	import ChatMessage from "./ChatMessage.svelte";
	import type { WebSearchUpdate } from "$lib/types/MessageUpdate";
	import { browser } from "$app/environment";
	import SystemPromptModal from "../SystemPromptModal.svelte";
	import type { Assistant } from "$lib/types/Assistant";
	import AssistantIntroduction from "./AssistantIntroduction.svelte";
	import { page } from "$app/stores";
	import { base } from "$app/paths";

	export let messages: Message[];
	export let loading: boolean;
	export let pending: boolean;
	export let isAuthor: boolean;
	export let currentModel: Model;
	export let assistant: Assistant | undefined;
	export let models: Model[];
	export let preprompt: string | undefined;
	export let readOnly: boolean;

	let chatContainer: HTMLElement;

	export let webSearchMessages: WebSearchUpdate[] = [];

	async function scrollToBottom() {
		await tick();
		chatContainer.scrollTop = chatContainer.scrollHeight;
	}

	// If last message is from user, scroll to bottom
	$: if (browser && messages[messages.length - 1]?.from === "user") {
		scrollToBottom();
	}
</script>

<div
	class="scrollbar-custom mr-1 h-full overflow-y-auto"
	use:snapScrollToBottom={messages.length ? [...messages, ...webSearchMessages] : false}
	bind:this={chatContainer}
>
	<div class="mx-auto flex h-full max-w-3xl flex-col gap-6 px-5 pt-6 sm:gap-8 xl:max-w-4xl">
		{#each messages as message, i}
			{#if i === 0 && $page.data?.assistant}
				<a
					class="mx-auto flex items-center gap-1.5 rounded-full border border-gray-100 bg-gray-50 py-1 pl-1 pr-3 text-sm text-gray-800 hover:bg-gray-100 dark:border-gray-800 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700"
					href="{base}/settings/assistants/{$page.data.assistant._id}"
				>
					{#if $page.data?.assistant.avatar}
						<img
							src="{base}/settings/assistants/{$page.data?.assistant._id.toString()}/avatar.jpg?hash=${$page
								.data.assistant.avatar}"
							alt="Avatar"
							class="size-5 rounded-full object-cover"
						/>
					{:else}
						<div
							class="flex size-6 items-center justify-center rounded-full bg-gray-300 font-bold uppercase text-gray-500"
						>
							{$page.data?.assistant.name[0]}
						</div>
					{/if}

					{$page.data.assistant.name}
				</a>
			{:else if i === 0 && preprompt && preprompt != currentModel.preprompt}
				<SystemPromptModal preprompt={preprompt ?? ""} />
			{/if}
			<ChatMessage
				loading={loading && i === messages.length - 1}
				{message}
				{isAuthor}
				{readOnly}
				model={currentModel}
				webSearchMessages={i === messages.length - 1 ? webSearchMessages : []}
				on:retry
				on:vote
				on:continue
			/>
		{:else}
			{#if !assistant}
				<ChatIntroduction {models} {currentModel} on:message />
			{:else}
				<AssistantIntroduction {assistant} on:message />
			{/if}
		{/each}
		{#if pending && messages[messages.length - 1]?.from === "user"}
			<ChatMessage
				message={{ from: "assistant", content: "", id: randomUUID() }}
				model={currentModel}
				{webSearchMessages}
			/>
		{/if}
		<div class="h-44 flex-none" />
	</div>
	<ScrollToBottomBtn
		class="bottom-36 right-4 max-md:hidden lg:right-10"
		scrollNode={chatContainer}
	/>
</div>