File size: 3,926 Bytes
5da61b4
 
 
831f161
b7b2c8c
64d3841
 
4606755
 
 
 
 
cd5cd0c
4606755
cad3e14
0fcf19a
cad3e14
831f161
82fcab7
2e28042
831f161
b7b2c8c
 
 
ed27197
 
 
b7b2c8c
 
41f29a4
 
 
 
 
 
 
 
 
 
 
5c9a37f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cad3e14
 
2e28042
cad3e14
2606dde
cad3e14
2606dde
cad3e14
 
5da61b4
cad3e14
2606dde
 
4e58dda
2606dde
332d815
2606dde
5da61b4
82fcab7
2cb745f
 
82fcab7
64d3841
4e58dda
2cb745f
 
 
cd6894d
82fcab7
2606dde
cf7ac8d
2606dde
 
ce2231f
2606dde
ce2231f
2606dde
12c3a5a
2606dde
 
cd6894d
0e5c445
41f29a4
2606dde
b7b2c8c
fa3b3b4
 
 
 
 
5c9a37f
 
 
cad3e14
 
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
108
109
110
111
112
113
114
115
116
import type { LayoutServerLoad } from "./$types";
import { collections } from "$lib/server/database";
import type { Conversation } from "$lib/types/Conversation";
import { UrlDependency } from "$lib/types/UrlDependency";
import { defaultModel, models, oldModels, validateModel } from "$lib/server/models";
import { authCondition, requiresUser } from "$lib/server/auth";
import { DEFAULT_SETTINGS } from "$lib/types/Settings";
import {
	SERPAPI_KEY,
	SERPER_API_KEY,
	MESSAGES_BEFORE_LOGIN,
	YDC_API_KEY,
	USE_LOCAL_WEBSEARCH,
} from "$env/static/private";

export const load: LayoutServerLoad = async ({ locals, depends }) => {
	const { conversations } = collections;
	depends(UrlDependency.ConversationList);

	const settings = await collections.settings.findOne(authCondition(locals));

	// If the active model in settings is not valid, set it to the default model. This can happen if model was disabled.
	if (settings && !validateModel(models).safeParse(settings?.activeModel).success) {
		settings.activeModel = defaultModel.id;
		await collections.settings.updateOne(authCondition(locals), {
			$set: { activeModel: defaultModel.id },
		});
	}

	// if the model is unlisted, set the active model to the default model
	if (
		settings?.activeModel &&
		models.find((m) => m.id === settings?.activeModel)?.unlisted === true
	) {
		settings.activeModel = defaultModel.id;
		await collections.settings.updateOne(authCondition(locals), {
			$set: { activeModel: defaultModel.id },
		});
	}

	// get the number of messages where `from === "assistant"` across all conversations.
	const totalMessages =
		(
			await conversations
				.aggregate([
					{ $match: authCondition(locals) },
					{ $project: { messages: 1 } },
					{ $unwind: "$messages" },
					{ $match: { "messages.from": "assistant" } },
					{ $count: "messages" },
				])
				.toArray()
		)[0]?.messages ?? 0;

	const messagesBeforeLogin = MESSAGES_BEFORE_LOGIN ? parseInt(MESSAGES_BEFORE_LOGIN) : 0;

	const userHasExceededMessages = messagesBeforeLogin > 0 && totalMessages > messagesBeforeLogin;

	const loginRequired = requiresUser && !locals.user && userHasExceededMessages;

	return {
		conversations: await conversations
			.find(authCondition(locals))
			.sort({ updatedAt: -1 })
			.project<Pick<Conversation, "title" | "model" | "_id" | "updatedAt" | "createdAt">>({
				title: 1,
				model: 1,
				_id: 1,
				updatedAt: 1,
				createdAt: 1,
			})
			.map((conv) => ({
				id: conv._id.toString(),
				title: settings?.hideEmojiOnSidebar ? conv.title.replace(/\p{Emoji}/gu, "") : conv.title,
				model: conv.model ?? defaultModel,
				updatedAt: conv.updatedAt,
			}))
			.toArray(),
		settings: {
			searchEnabled: !!(SERPAPI_KEY || SERPER_API_KEY || YDC_API_KEY || USE_LOCAL_WEBSEARCH),
			ethicsModalAccepted: !!settings?.ethicsModalAcceptedAt,
			ethicsModalAcceptedAt: settings?.ethicsModalAcceptedAt ?? null,
			activeModel: settings?.activeModel ?? DEFAULT_SETTINGS.activeModel,
			hideEmojiOnSidebar: settings?.hideEmojiOnSidebar ?? false,
			shareConversationsWithModelAuthors:
				settings?.shareConversationsWithModelAuthors ??
				DEFAULT_SETTINGS.shareConversationsWithModelAuthors,
			customPrompts: settings?.customPrompts ?? {},
		},
		models: models.map((model) => ({
			id: model.id,
			name: model.name,
			websiteUrl: model.websiteUrl,
			modelUrl: model.modelUrl,
			datasetName: model.datasetName,
			datasetUrl: model.datasetUrl,
			displayName: model.displayName,
			description: model.description,
			promptExamples: model.promptExamples,
			parameters: model.parameters,
			preprompt: model.preprompt,
			multimodal: model.multimodal,
			unlisted: model.unlisted,
		})),
		oldModels,
		user: locals.user && {
			username: locals.user.username,
			avatarUrl: locals.user.avatarUrl,
			email: locals.user.email,
		},
		loginRequired,
		loginEnabled: requiresUser,
		guestMode: requiresUser && messagesBeforeLogin > 0,
	};
};