Bring back disclaimer modal & updates to guest mode (#526)
Browse files* Changes to modal on login:
- Ethics modal on page load
- Login modal pop up for guest mode later
- Change message limit to be 5 messages across all conversations
* fix login button width
* tweak modals
* Update src/routes/+layout.server.ts
Co-authored-by: Mishig <mishig.davaadorj@coloradocollege.edu>
* Fix linting
---------
Co-authored-by: Victor Mustar <victor.mustar@gmail.com>
Co-authored-by: Mishig <mishig.davaadorj@coloradocollege.edu>
- .env.template +1 -1
- src/lib/components/DisclaimerModal.svelte +72 -0
- src/lib/components/LoginModal.svelte +14 -29
- src/lib/components/NavMenu.svelte +1 -1
- src/lib/components/chat/ChatWindow.svelte +23 -6
- src/routes/+layout.server.ts +23 -2
- src/routes/+layout.svelte +3 -14
- src/routes/conversation/[id]/+page.svelte +0 -9
- src/routes/conversation/[id]/+server.ts +18 -3
.env.template
CHANGED
@@ -142,7 +142,7 @@ PUBLIC_APP_DATA_SHARING=1
|
|
142 |
PUBLIC_APP_DISCLAIMER=1
|
143 |
|
144 |
RATE_LIMIT=16
|
145 |
-
MESSAGES_BEFORE_LOGIN=
|
146 |
|
147 |
PUBLIC_GOOGLE_ANALYTICS_ID=G-8Q63TH4CSL
|
148 |
|
|
|
142 |
PUBLIC_APP_DISCLAIMER=1
|
143 |
|
144 |
RATE_LIMIT=16
|
145 |
+
MESSAGES_BEFORE_LOGIN=5# how many messages a user can send in a conversation before having to login. set to 0 to force login right away
|
146 |
|
147 |
PUBLIC_GOOGLE_ANALYTICS_ID=G-8Q63TH4CSL
|
148 |
|
src/lib/components/DisclaimerModal.svelte
ADDED
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<script lang="ts">
|
2 |
+
import { base } from "$app/paths";
|
3 |
+
import { page } from "$app/stores";
|
4 |
+
import { PUBLIC_APP_DESCRIPTION, PUBLIC_APP_NAME } from "$env/static/public";
|
5 |
+
import LogoHuggingFaceBorderless from "$lib/components/icons/LogoHuggingFaceBorderless.svelte";
|
6 |
+
import Modal from "$lib/components/Modal.svelte";
|
7 |
+
import type { LayoutData } from "../../routes/$types";
|
8 |
+
import Logo from "./icons/Logo.svelte";
|
9 |
+
|
10 |
+
export let settings: LayoutData["settings"];
|
11 |
+
</script>
|
12 |
+
|
13 |
+
<Modal>
|
14 |
+
<div
|
15 |
+
class="flex w-full flex-col items-center gap-6 bg-gradient-to-b from-primary-500/40 via-primary-500/10 to-primary-500/0 px-5 pb-8 pt-9 text-center sm:px-6"
|
16 |
+
>
|
17 |
+
<h2 class="flex items-center text-2xl font-semibold text-gray-800">
|
18 |
+
<Logo classNames="mr-1" />
|
19 |
+
{PUBLIC_APP_NAME}
|
20 |
+
</h2>
|
21 |
+
|
22 |
+
<p class="text-lg font-semibold leading-snug text-gray-800" style="text-wrap: balance;">
|
23 |
+
{PUBLIC_APP_DESCRIPTION}
|
24 |
+
</p>
|
25 |
+
|
26 |
+
<p class="text-sm text-gray-500">
|
27 |
+
Disclaimer: AI is an area of active research with known problems such as biased generation and
|
28 |
+
misinformation. Do not use this application for high-stakes decisions or advice.
|
29 |
+
</p>
|
30 |
+
|
31 |
+
<div class="flex w-full flex-col items-center gap-2">
|
32 |
+
{#if $page.data.guestMode || !$page.data.loginEnabled}
|
33 |
+
<form action="{base}/settings" target="_parent" method="POST" class="w-full">
|
34 |
+
<input type="hidden" name="ethicsModalAccepted" value={true} />
|
35 |
+
{#each Object.entries(settings).filter(([k]) => !(k === "customPrompts")) as [key, val]}
|
36 |
+
<input type="hidden" name={key} value={val} />
|
37 |
+
{/each}
|
38 |
+
<input
|
39 |
+
type="hidden"
|
40 |
+
name="customPrompts"
|
41 |
+
value={JSON.stringify(settings.customPrompts)}
|
42 |
+
/>
|
43 |
+
<button
|
44 |
+
type="submit"
|
45 |
+
class="w-full justify-center rounded-full border-2 border-gray-300 bg-black px-5 py-2 text-lg font-semibold text-gray-100 transition-colors hover:bg-gray-100"
|
46 |
+
class:bg-white={$page.data.loginEnabled}
|
47 |
+
class:text-gray-800={$page.data.loginEnabled}
|
48 |
+
>
|
49 |
+
{#if $page.data.loginEnabled}
|
50 |
+
Try as guest
|
51 |
+
{:else}
|
52 |
+
Start chatting
|
53 |
+
{/if}
|
54 |
+
</button>
|
55 |
+
</form>
|
56 |
+
{/if}
|
57 |
+
{#if $page.data.loginEnabled}
|
58 |
+
<form action="{base}/login" target="_parent" method="POST" class="w-full">
|
59 |
+
<button
|
60 |
+
type="submit"
|
61 |
+
class="flex w-full items-center justify-center whitespace-nowrap rounded-full border-2 border-black bg-black px-5 py-2 text-lg font-semibold text-gray-100 transition-colors hover:bg-gray-900"
|
62 |
+
>
|
63 |
+
Sign in
|
64 |
+
{#if PUBLIC_APP_NAME === "HuggingChat"}
|
65 |
+
with <LogoHuggingFaceBorderless classNames="text-xl mr-1 ml-1.5 flex-none" /> Hugging Face
|
66 |
+
{/if}
|
67 |
+
</button>
|
68 |
+
</form>
|
69 |
+
{/if}
|
70 |
+
</div>
|
71 |
+
</div>
|
72 |
+
</Modal>
|
src/lib/components/LoginModal.svelte
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<script lang="ts">
|
2 |
import { base } from "$app/paths";
|
3 |
import { page } from "$app/stores";
|
4 |
-
import {
|
5 |
import LogoHuggingFaceBorderless from "$lib/components/icons/LogoHuggingFaceBorderless.svelte";
|
6 |
import Modal from "$lib/components/Modal.svelte";
|
7 |
import type { LayoutData } from "../../routes/$types";
|
@@ -9,47 +9,32 @@
|
|
9 |
export let settings: LayoutData["settings"];
|
10 |
</script>
|
11 |
|
12 |
-
<Modal>
|
13 |
<div
|
14 |
-
class="flex w-full flex-col items-center gap-6 bg-gradient-to-
|
15 |
>
|
16 |
<h2 class="flex items-center text-2xl font-semibold text-gray-800">
|
17 |
<Logo classNames="mr-1" />
|
18 |
{PUBLIC_APP_NAME}
|
19 |
-
<div
|
20 |
-
class="ml-3 flex h-6 items-center rounded-lg border border-gray-100 bg-gray-50 px-2 text-base text-gray-400"
|
21 |
-
>
|
22 |
-
v{PUBLIC_VERSION}
|
23 |
-
</div>
|
24 |
</h2>
|
25 |
-
|
26 |
-
|
27 |
-
class="px-4 text-lg font-semibold leading-snug text-gray-800 sm:px-12"
|
28 |
-
style="text-wrap: balance;"
|
29 |
-
>
|
30 |
-
Please Sign in with Hugging Face to continue
|
31 |
-
</p>
|
32 |
-
{/if}
|
33 |
-
<p class="text-base text-gray-800">
|
34 |
-
Disclaimer: AI is an area of active research with known problems such as biased generation and
|
35 |
-
misinformation. Do not use this application for high-stakes decisions or advice.
|
36 |
</p>
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
{/if}
|
43 |
<form
|
44 |
-
action="{base}/{$page.data.
|
45 |
target="_parent"
|
46 |
method="POST"
|
47 |
class="flex w-full flex-col items-center gap-2"
|
48 |
>
|
49 |
-
{#if $page.data.
|
50 |
<button
|
51 |
type="submit"
|
52 |
-
class="
|
53 |
>
|
54 |
Sign in
|
55 |
{#if PUBLIC_APP_NAME === "HuggingChat"}
|
@@ -63,7 +48,7 @@
|
|
63 |
{/each}
|
64 |
<button
|
65 |
type="submit"
|
66 |
-
class="
|
67 |
>
|
68 |
Start chatting
|
69 |
</button>
|
|
|
1 |
<script lang="ts">
|
2 |
import { base } from "$app/paths";
|
3 |
import { page } from "$app/stores";
|
4 |
+
import { PUBLIC_APP_DESCRIPTION, PUBLIC_APP_NAME } from "$env/static/public";
|
5 |
import LogoHuggingFaceBorderless from "$lib/components/icons/LogoHuggingFaceBorderless.svelte";
|
6 |
import Modal from "$lib/components/Modal.svelte";
|
7 |
import type { LayoutData } from "../../routes/$types";
|
|
|
9 |
export let settings: LayoutData["settings"];
|
10 |
</script>
|
11 |
|
12 |
+
<Modal on:close>
|
13 |
<div
|
14 |
+
class="flex w-full flex-col items-center gap-6 bg-gradient-to-b from-primary-500/40 via-primary-500/10 to-primary-500/0 px-5 pb-8 pt-9 text-center"
|
15 |
>
|
16 |
<h2 class="flex items-center text-2xl font-semibold text-gray-800">
|
17 |
<Logo classNames="mr-1" />
|
18 |
{PUBLIC_APP_NAME}
|
|
|
|
|
|
|
|
|
|
|
19 |
</h2>
|
20 |
+
<p class="text-lg font-semibold leading-snug text-gray-800" style="text-wrap: balance;">
|
21 |
+
{PUBLIC_APP_DESCRIPTION}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
</p>
|
23 |
+
<p class="rounded-xl border bg-white/80 p-2 text-base text-gray-800">
|
24 |
+
You have reached the guest message limit, please Sign In with your Hugging Face account to
|
25 |
+
continue.
|
26 |
+
</p>
|
27 |
+
|
|
|
28 |
<form
|
29 |
+
action="{base}/{$page.data.loginRequired ? 'login' : 'settings'}"
|
30 |
target="_parent"
|
31 |
method="POST"
|
32 |
class="flex w-full flex-col items-center gap-2"
|
33 |
>
|
34 |
+
{#if $page.data.loginRequired}
|
35 |
<button
|
36 |
type="submit"
|
37 |
+
class="flex w-full items-center justify-center whitespace-nowrap rounded-full bg-black px-5 py-2 text-center text-lg font-semibold text-gray-100 transition-colors hover:bg-gray-900"
|
38 |
>
|
39 |
Sign in
|
40 |
{#if PUBLIC_APP_NAME === "HuggingChat"}
|
|
|
48 |
{/each}
|
49 |
<button
|
50 |
type="submit"
|
51 |
+
class="flex w-full items-center justify-center whitespace-nowrap rounded-full border-2 border-black bg-black px-5 py-2 text-lg font-semibold text-gray-100 transition-colors hover:bg-gray-900"
|
52 |
>
|
53 |
Start chatting
|
54 |
</button>
|
src/lib/components/NavMenu.svelte
CHANGED
@@ -67,7 +67,7 @@
|
|
67 |
<form action="{base}/login" method="POST" target="_parent">
|
68 |
<button
|
69 |
type="submit"
|
70 |
-
class="flex h-9 flex-none items-center gap-1.5 rounded-lg pl-3 pr-2 text-gray-500 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-700"
|
71 |
>
|
72 |
Login
|
73 |
</button>
|
|
|
67 |
<form action="{base}/login" method="POST" target="_parent">
|
68 |
<button
|
69 |
type="submit"
|
70 |
+
class="flex h-9 w-full flex-none items-center gap-1.5 rounded-lg pl-3 pr-2 text-gray-500 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-700"
|
71 |
>
|
72 |
Login
|
73 |
</button>
|
src/lib/components/chat/ChatWindow.svelte
CHANGED
@@ -15,6 +15,8 @@
|
|
15 |
import WebSearchToggle from "../WebSearchToggle.svelte";
|
16 |
import LoginModal from "../LoginModal.svelte";
|
17 |
import type { WebSearchUpdate } from "$lib/types/MessageUpdate";
|
|
|
|
|
18 |
|
19 |
export let messages: Message[] = [];
|
20 |
export let loading = false;
|
@@ -26,7 +28,6 @@
|
|
26 |
export let webSearchMessages: WebSearchUpdate[] = [];
|
27 |
export let preprompt: string | undefined = undefined;
|
28 |
|
29 |
-
export let loginRequired = false;
|
30 |
$: isReadOnly = !models.some((model) => model.id === currentModel.id);
|
31 |
|
32 |
let loginModalOpen = false;
|
@@ -47,8 +48,15 @@
|
|
47 |
</script>
|
48 |
|
49 |
<div class="relative min-h-0 min-w-0">
|
50 |
-
{#if
|
51 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
{/if}
|
53 |
<ChatMessages
|
54 |
{loading}
|
@@ -61,7 +69,13 @@
|
|
61 |
isAuthor={!shared}
|
62 |
{webSearchMessages}
|
63 |
{preprompt}
|
64 |
-
on:message
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
on:vote
|
66 |
on:retry={(ev) => {
|
67 |
if (!loading) dispatch("retry", ev.detail);
|
@@ -91,8 +105,11 @@
|
|
91 |
placeholder="Ask anything"
|
92 |
bind:value={message}
|
93 |
on:submit={handleSubmit}
|
94 |
-
on:keypress={() => {
|
95 |
-
if (loginRequired)
|
|
|
|
|
|
|
96 |
}}
|
97 |
maxRows={4}
|
98 |
disabled={isReadOnly}
|
|
|
15 |
import WebSearchToggle from "../WebSearchToggle.svelte";
|
16 |
import LoginModal from "../LoginModal.svelte";
|
17 |
import type { WebSearchUpdate } from "$lib/types/MessageUpdate";
|
18 |
+
import { page } from "$app/stores";
|
19 |
+
import DisclaimerModal from "../DisclaimerModal.svelte";
|
20 |
|
21 |
export let messages: Message[] = [];
|
22 |
export let loading = false;
|
|
|
28 |
export let webSearchMessages: WebSearchUpdate[] = [];
|
29 |
export let preprompt: string | undefined = undefined;
|
30 |
|
|
|
31 |
$: isReadOnly = !models.some((model) => model.id === currentModel.id);
|
32 |
|
33 |
let loginModalOpen = false;
|
|
|
48 |
</script>
|
49 |
|
50 |
<div class="relative min-h-0 min-w-0">
|
51 |
+
{#if !settings.ethicsModalAcceptedAt}
|
52 |
+
<DisclaimerModal {settings} />
|
53 |
+
{:else if loginModalOpen}
|
54 |
+
<LoginModal
|
55 |
+
{settings}
|
56 |
+
on:close={() => {
|
57 |
+
loginModalOpen = false;
|
58 |
+
}}
|
59 |
+
/>
|
60 |
{/if}
|
61 |
<ChatMessages
|
62 |
{loading}
|
|
|
69 |
isAuthor={!shared}
|
70 |
{webSearchMessages}
|
71 |
{preprompt}
|
72 |
+
on:message={(ev) => {
|
73 |
+
if ($page.data.loginRequired) {
|
74 |
+
loginModalOpen = true;
|
75 |
+
} else {
|
76 |
+
dispatch("message", ev.detail);
|
77 |
+
}
|
78 |
+
}}
|
79 |
on:vote
|
80 |
on:retry={(ev) => {
|
81 |
if (!loading) dispatch("retry", ev.detail);
|
|
|
105 |
placeholder="Ask anything"
|
106 |
bind:value={message}
|
107 |
on:submit={handleSubmit}
|
108 |
+
on:keypress={(ev) => {
|
109 |
+
if ($page.data.loginRequired) {
|
110 |
+
ev.preventDefault();
|
111 |
+
loginModalOpen = true;
|
112 |
+
}
|
113 |
}}
|
114 |
maxRows={4}
|
115 |
disabled={isReadOnly}
|
src/routes/+layout.server.ts
CHANGED
@@ -38,6 +38,26 @@ export const load: LayoutServerLoad = async ({ locals, depends, url }) => {
|
|
38 |
});
|
39 |
}
|
40 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
return {
|
42 |
conversations: await conversations
|
43 |
.find(authCondition(locals))
|
@@ -83,7 +103,8 @@ export const load: LayoutServerLoad = async ({ locals, depends, url }) => {
|
|
83 |
avatarUrl: locals.user.avatarUrl,
|
84 |
email: locals.user.email,
|
85 |
},
|
86 |
-
|
87 |
-
|
|
|
88 |
};
|
89 |
};
|
|
|
38 |
});
|
39 |
}
|
40 |
|
41 |
+
// get the number of messages where `from === "assistant"` across all conversations.
|
42 |
+
const totalMessages =
|
43 |
+
(
|
44 |
+
await conversations
|
45 |
+
.aggregate([
|
46 |
+
{ $match: authCondition(locals) },
|
47 |
+
{ $project: { messages: 1 } },
|
48 |
+
{ $unwind: "$messages" },
|
49 |
+
{ $match: { "messages.from": "assistant" } },
|
50 |
+
{ $count: "messages" },
|
51 |
+
])
|
52 |
+
.toArray()
|
53 |
+
)[0]?.messages ?? 0;
|
54 |
+
|
55 |
+
const messagesBeforeLogin = MESSAGES_BEFORE_LOGIN ? parseInt(MESSAGES_BEFORE_LOGIN) : 0;
|
56 |
+
|
57 |
+
const userHasExceededMessages = messagesBeforeLogin > 0 && totalMessages > messagesBeforeLogin;
|
58 |
+
|
59 |
+
const loginRequired = requiresUser && !locals.user && userHasExceededMessages;
|
60 |
+
|
61 |
return {
|
62 |
conversations: await conversations
|
63 |
.find(authCondition(locals))
|
|
|
103 |
avatarUrl: locals.user.avatarUrl,
|
104 |
email: locals.user.email,
|
105 |
},
|
106 |
+
loginRequired,
|
107 |
+
loginEnabled: requiresUser,
|
108 |
+
guestMode: requiresUser && messagesBeforeLogin > 0,
|
109 |
};
|
110 |
};
|
src/routes/+layout.svelte
CHANGED
@@ -4,7 +4,7 @@
|
|
4 |
import { page } from "$app/stores";
|
5 |
import "../styles/main.css";
|
6 |
import { base } from "$app/paths";
|
7 |
-
import { PUBLIC_ORIGIN
|
8 |
|
9 |
import { shareConversation } from "$lib/shareConversation";
|
10 |
import { UrlDependency } from "$lib/types/UrlDependency";
|
@@ -14,7 +14,6 @@
|
|
14 |
import NavMenu from "$lib/components/NavMenu.svelte";
|
15 |
import Toast from "$lib/components/Toast.svelte";
|
16 |
import SettingsModal from "$lib/components/SettingsModal.svelte";
|
17 |
-
import LoginModal from "$lib/components/LoginModal.svelte";
|
18 |
import { PUBLIC_APP_ASSETS, PUBLIC_APP_NAME } from "$env/static/public";
|
19 |
import titleUpdate from "$lib/stores/titleUpdate";
|
20 |
|
@@ -94,13 +93,6 @@
|
|
94 |
|
95 |
$: if ($error) onError();
|
96 |
|
97 |
-
const requiresLogin =
|
98 |
-
!$page.error &&
|
99 |
-
!$page.route.id?.startsWith("/r/") &&
|
100 |
-
(data.requiresLogin
|
101 |
-
? !data.user
|
102 |
-
: !data.settings.ethicsModalAcceptedAt && !!PUBLIC_APP_DISCLAIMER);
|
103 |
-
|
104 |
$: if ($titleUpdate) {
|
105 |
const convIdx = data.conversations.findIndex(({ id }) => id === $titleUpdate?.convId);
|
106 |
|
@@ -157,7 +149,7 @@
|
|
157 |
<NavMenu
|
158 |
conversations={data.conversations}
|
159 |
user={data.user}
|
160 |
-
canLogin={data.user === undefined && data.
|
161 |
on:shareConversation={(ev) => shareConversation(ev.detail.id, ev.detail.title)}
|
162 |
on:deleteConversation={(ev) => deleteConversation(ev.detail)}
|
163 |
on:clickSettings={() => (isSettingsOpen = true)}
|
@@ -168,7 +160,7 @@
|
|
168 |
<NavMenu
|
169 |
conversations={data.conversations}
|
170 |
user={data.user}
|
171 |
-
canLogin={data.user === undefined && data.
|
172 |
on:shareConversation={(ev) => shareConversation(ev.detail.id, ev.detail.title)}
|
173 |
on:deleteConversation={(ev) => deleteConversation(ev.detail)}
|
174 |
on:clickSettings={() => (isSettingsOpen = true)}
|
@@ -185,8 +177,5 @@
|
|
185 |
models={data.models}
|
186 |
/>
|
187 |
{/if}
|
188 |
-
{#if requiresLogin && data.messagesBeforeLogin === 0}
|
189 |
-
<LoginModal settings={data.settings} />
|
190 |
-
{/if}
|
191 |
<slot />
|
192 |
</div>
|
|
|
4 |
import { page } from "$app/stores";
|
5 |
import "../styles/main.css";
|
6 |
import { base } from "$app/paths";
|
7 |
+
import { PUBLIC_ORIGIN } from "$env/static/public";
|
8 |
|
9 |
import { shareConversation } from "$lib/shareConversation";
|
10 |
import { UrlDependency } from "$lib/types/UrlDependency";
|
|
|
14 |
import NavMenu from "$lib/components/NavMenu.svelte";
|
15 |
import Toast from "$lib/components/Toast.svelte";
|
16 |
import SettingsModal from "$lib/components/SettingsModal.svelte";
|
|
|
17 |
import { PUBLIC_APP_ASSETS, PUBLIC_APP_NAME } from "$env/static/public";
|
18 |
import titleUpdate from "$lib/stores/titleUpdate";
|
19 |
|
|
|
93 |
|
94 |
$: if ($error) onError();
|
95 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
$: if ($titleUpdate) {
|
97 |
const convIdx = data.conversations.findIndex(({ id }) => id === $titleUpdate?.convId);
|
98 |
|
|
|
149 |
<NavMenu
|
150 |
conversations={data.conversations}
|
151 |
user={data.user}
|
152 |
+
canLogin={data.user === undefined && data.loginEnabled}
|
153 |
on:shareConversation={(ev) => shareConversation(ev.detail.id, ev.detail.title)}
|
154 |
on:deleteConversation={(ev) => deleteConversation(ev.detail)}
|
155 |
on:clickSettings={() => (isSettingsOpen = true)}
|
|
|
160 |
<NavMenu
|
161 |
conversations={data.conversations}
|
162 |
user={data.user}
|
163 |
+
canLogin={data.user === undefined && data.loginEnabled}
|
164 |
on:shareConversation={(ev) => shareConversation(ev.detail.id, ev.detail.title)}
|
165 |
on:deleteConversation={(ev) => deleteConversation(ev.detail)}
|
166 |
on:clickSettings={() => (isSettingsOpen = true)}
|
|
|
177 |
models={data.models}
|
178 |
/>
|
179 |
{/if}
|
|
|
|
|
|
|
180 |
<slot />
|
181 |
</div>
|
src/routes/conversation/[id]/+page.svelte
CHANGED
@@ -12,7 +12,6 @@
|
|
12 |
import { findCurrentModel } from "$lib/utils/models";
|
13 |
import { webSearchParameters } from "$lib/stores/webSearchParameters";
|
14 |
import type { Message } from "$lib/types/Message";
|
15 |
-
import { PUBLIC_APP_DISCLAIMER } from "$env/static/public";
|
16 |
import type { MessageUpdate, WebSearchUpdate } from "$lib/types/MessageUpdate";
|
17 |
import titleUpdate from "$lib/stores/titleUpdate";
|
18 |
|
@@ -32,7 +31,6 @@
|
|
32 |
|
33 |
let loading = false;
|
34 |
let pending = false;
|
35 |
-
let loginRequired = false;
|
36 |
|
37 |
async function convFromShared() {
|
38 |
try {
|
@@ -266,12 +264,6 @@
|
|
266 |
|
267 |
$: $page.params.id, (isAborted = true);
|
268 |
$: title = data.conversations.find((conv) => conv.id === $page.params.id)?.title ?? data.title;
|
269 |
-
|
270 |
-
$: loginRequired =
|
271 |
-
(data.requiresLogin
|
272 |
-
? !data.user
|
273 |
-
: !data.settings.ethicsModalAcceptedAt && !!PUBLIC_APP_DISCLAIMER) &&
|
274 |
-
messages.length >= data.messagesBeforeLogin;
|
275 |
</script>
|
276 |
|
277 |
<svelte:head>
|
@@ -299,5 +291,4 @@
|
|
299 |
models={data.models}
|
300 |
currentModel={findCurrentModel([...data.models, ...data.oldModels], data.model)}
|
301 |
settings={data.settings}
|
302 |
-
{loginRequired}
|
303 |
/>
|
|
|
12 |
import { findCurrentModel } from "$lib/utils/models";
|
13 |
import { webSearchParameters } from "$lib/stores/webSearchParameters";
|
14 |
import type { Message } from "$lib/types/Message";
|
|
|
15 |
import type { MessageUpdate, WebSearchUpdate } from "$lib/types/MessageUpdate";
|
16 |
import titleUpdate from "$lib/stores/titleUpdate";
|
17 |
|
|
|
31 |
|
32 |
let loading = false;
|
33 |
let pending = false;
|
|
|
34 |
|
35 |
async function convFromShared() {
|
36 |
try {
|
|
|
264 |
|
265 |
$: $page.params.id, (isAborted = true);
|
266 |
$: title = data.conversations.find((conv) => conv.id === $page.params.id)?.title ?? data.title;
|
|
|
|
|
|
|
|
|
|
|
|
|
267 |
</script>
|
268 |
|
269 |
<svelte:head>
|
|
|
291 |
models={data.models}
|
292 |
currentModel={findCurrentModel([...data.models, ...data.oldModels], data.model)}
|
293 |
settings={data.settings}
|
|
|
294 |
/>
|
src/routes/conversation/[id]/+server.ts
CHANGED
@@ -49,13 +49,28 @@ export async function POST({ request, fetch, locals, params, getClientAddress })
|
|
49 |
ip: getClientAddress(),
|
50 |
});
|
51 |
|
52 |
-
//
|
53 |
if (
|
54 |
!locals.user?._id &&
|
55 |
requiresUser &&
|
56 |
-
|
57 |
) {
|
58 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
}
|
60 |
|
61 |
// check if the user is rate limited
|
|
|
49 |
ip: getClientAddress(),
|
50 |
});
|
51 |
|
52 |
+
// guest mode check
|
53 |
if (
|
54 |
!locals.user?._id &&
|
55 |
requiresUser &&
|
56 |
+
(MESSAGES_BEFORE_LOGIN ? parseInt(MESSAGES_BEFORE_LOGIN) : 0) > 0
|
57 |
) {
|
58 |
+
const totalMessages =
|
59 |
+
(
|
60 |
+
await collections.conversations
|
61 |
+
.aggregate([
|
62 |
+
{ $match: authCondition(locals) },
|
63 |
+
{ $project: { messages: 1 } },
|
64 |
+
{ $unwind: "$messages" },
|
65 |
+
{ $match: { "messages.from": "assistant" } },
|
66 |
+
{ $count: "messages" },
|
67 |
+
])
|
68 |
+
.toArray()
|
69 |
+
)[0]?.messages ?? 0;
|
70 |
+
|
71 |
+
if (totalMessages > parseInt(MESSAGES_BEFORE_LOGIN)) {
|
72 |
+
throw error(429, "Exceeded number of messages before login");
|
73 |
+
}
|
74 |
}
|
75 |
|
76 |
// check if the user is rate limited
|