File size: 5,304 Bytes
5da61b4 831f161 b7b2c8c 64d3841 4606755 f02ffb2 4606755 cd5cd0c 992a8de 4606755 992a8de cad3e14 0fcf19a 831f161 82fcab7 2e28042 831f161 b7b2c8c 992a8de b7b2c8c ed27197 b7b2c8c 41f29a4 5c9a37f 992a8de 5c9a37f 992a8de cad3e14 992a8de 82fcab7 f02ffb2 2cb745f 82fcab7 64d3841 4e58dda 2cb745f cd6894d 992a8de 82fcab7 2606dde cf7ac8d 2606dde ce2231f 2606dde ce2231f 2606dde 12c3a5a 2606dde cd6894d 0e5c445 41f29a4 2606dde b7b2c8c fa3b3b4 992a8de fa3b3b4 992a8de 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 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
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,
SERPSTACK_API_KEY,
MESSAGES_BEFORE_LOGIN,
YDC_API_KEY,
USE_LOCAL_WEBSEARCH,
ENABLE_ASSISTANTS,
} from "$env/static/private";
import { ObjectId } from "mongodb";
import type { ConvSidebar } from "$lib/types/ConvSidebar";
export const load: LayoutServerLoad = async ({ locals, depends }) => {
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.assistants?.map((el) => el.toString())?.includes(settings?.activeModel)
) {
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 collections.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;
const enableAssistants = ENABLE_ASSISTANTS === "true";
const assistantActive = !models.map(({ id }) => id).includes(settings?.activeModel ?? "");
const assistant = assistantActive
? JSON.parse(
JSON.stringify(
await collections.assistants.findOne({
_id: new ObjectId(settings?.activeModel),
})
)
)
: null;
const conversations = await collections.conversations
.find(authCondition(locals))
.sort({ updatedAt: -1 })
.project<
Pick<Conversation, "title" | "model" | "_id" | "updatedAt" | "createdAt" | "assistantId">
>({
title: 1,
model: 1,
_id: 1,
updatedAt: 1,
createdAt: 1,
assistantId: 1,
})
.toArray();
const assistantIds = conversations
.map((conv) => conv.assistantId)
.filter((el) => !!el) as ObjectId[];
const assistants = await collections.assistants.find({ _id: { $in: assistantIds } }).toArray();
return {
conversations: conversations.map((conv) => {
if (settings?.hideEmojiOnSidebar) {
conv.title = conv.title.replace(/\p{Emoji}/gu, "");
}
// remove invalid unicode and trim whitespaces
conv.title = conv.title.replace(/\uFFFD/gu, "").trimStart();
return {
id: conv._id.toString(),
title: conv.title,
model: conv.model ?? defaultModel,
updatedAt: conv.updatedAt,
assistantId: conv.assistantId?.toString(),
avatarHash:
conv.assistantId &&
assistants.find((a) => a._id.toString() === conv.assistantId?.toString())?.avatar,
};
}) satisfies ConvSidebar[],
settings: {
searchEnabled: !!(
SERPAPI_KEY ||
SERPER_API_KEY ||
SERPSTACK_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 ?? {},
assistants: settings?.assistants?.map((el) => el.toString()) ?? [],
},
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 && {
id: locals.user._id.toString(),
username: locals.user.username,
avatarUrl: locals.user.avatarUrl,
email: locals.user.email,
},
assistant,
enableAssistants,
loginRequired,
loginEnabled: requiresUser,
guestMode: requiresUser && messagesBeforeLogin > 0,
};
};
|