File size: 3,593 Bytes
1b66f8d
5da61b4
 
 
5b779a6
4a6603b
2606dde
5b779a6
 
e943a05
 
af58e08
992a8de
 
 
 
1b66f8d
 
3aa8136
 
5b779a6
2606dde
992a8de
b7b2c8c
af58e08
b7b2c8c
1b66f8d
 
77c7055
e943a05
0c4cf03
77c7055
 
 
 
 
 
e943a05
77c7055
 
1b66f8d
 
0714764
b2387f6
0c4cf03
0714764
 
5b779a6
3aa8136
992a8de
 
 
 
 
 
 
91ec91f
 
992a8de
 
 
 
 
 
 
 
 
 
 
 
 
 
2da78f5
af58e08
6434339
 
 
 
 
 
e943a05
6434339
 
77399ca
6434339
1b66f8d
992a8de
 
 
 
 
1b66f8d
77399ca
ad6275a
 
 
0c4cf03
ad6275a
3aa8136
0c4cf03
1b66f8d
0714764
b2387f6
0714764
 
1b66f8d
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>