Skip to content

Commit

Permalink
Merge branch 'main' into feat(settings)/conv_deletion_refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
nsarrazin authored Feb 11, 2025
2 parents 497acab + 87872cd commit f18d65e
Show file tree
Hide file tree
Showing 10 changed files with 177 additions and 114 deletions.
20 changes: 16 additions & 4 deletions scripts/updateLocalEnv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,29 @@ const prod = JSON.parse(JSON.stringify(yaml.load(file)));
const vars = prod.envVars as Record<string, string>;

let PUBLIC_CONFIG = "";
Object.entries(vars).forEach(([key, value]) => {
PUBLIC_CONFIG += `${key}=\`${value}\`\n`;
});

Object.entries(vars)
// filter keys used in prod with the proxy
.filter(([key]) => !["XFF_DEPTH", "ADDRESS_HEADER"].includes(key))
.forEach(([key, value]) => {
PUBLIC_CONFIG += `${key}=\`${value}\`\n`;
});

const SECRET_CONFIG =
(fs.existsSync(".env.SECRET_CONFIG")
? fs.readFileSync(".env.SECRET_CONFIG", "utf8")
: process.env.SECRET_CONFIG) ?? "";

// Prepend the content of the env variable SECRET_CONFIG
const full_config = `${PUBLIC_CONFIG}\n${SECRET_CONFIG}`;
let full_config = `${PUBLIC_CONFIG}\n${SECRET_CONFIG}`;

// replace the internal proxy url with the public endpoint
full_config = full_config.replaceAll(
"https://proxy.serverless.api-inference.huggingface.tech",
"https://api-inference.huggingface.co"
);

console.log(full_config);

// Write full_config to .env.local
fs.writeFileSync(".env.local", full_config);
8 changes: 6 additions & 2 deletions src/lib/components/Modal.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import { createEventDispatcher, onDestroy, onMount } from "svelte";
import { cubicOut } from "svelte/easing";
import { fade } from "svelte/transition";
import { fade, fly } from "svelte/transition";
import Portal from "./Portal.svelte";
import { browser } from "$app/environment";
Expand Down Expand Up @@ -63,7 +63,11 @@
tabindex="-1"
bind:this={modalEl}
onkeydown={handleKeydown}
class="max-h-[90dvh] overflow-y-auto overflow-x-hidden rounded-2xl bg-white shadow-2xl outline-none sm:-mt-10 {width}"
in:fly={{ y: 100 }}
class={[
"max-h-[90dvh] overflow-y-auto overflow-x-hidden rounded-2xl bg-white shadow-2xl outline-none sm:-mt-10",
width,
]}
>
{@render children?.()}
</div>
Expand Down
42 changes: 42 additions & 0 deletions src/lib/components/OverloadedModal.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<script lang="ts">
import { goto } from "$app/navigation";
import { base } from "$app/paths";
import { page } from "$app/state";
import IconDazzled from "./icons/IconDazzled.svelte";
import Modal from "./Modal.svelte";
let { onClose }: { onClose: () => void } = $props();
</script>

<Modal on:close={onClose}>
<div
class="from-primary-500/40 via-primary-500/10 to-primary-500/0 flex w-full flex-col items-center gap-3 bg-gradient-to-b px-5 pb-4 pt-9 text-center sm:px-6"
>
<div class="flex flex-wrap items-center gap-2">
<IconDazzled classNames="text-3xl mx-auto" />
<h2 class="flex flex-wrap items-center text-lg font-semibold text-gray-800">
This model is currently overloaded.
</h2>
</div>

<p class="text-sm text-gray-500">
Please try again later or consider using a different model. We currently have {page.data
.models.length} models available.
</p>

<div class="flex w-full flex-col items-center gap-4 pt-4">
<button
onclick={() => (onClose(), goto(`${base}/models`))}
class="flex w-full flex-wrap 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"
>
See all available models
</button>
<button
onclick={onClose}
class="flex w-fit flex-wrap items-center justify-center whitespace-nowrap px-2 py-1 text-gray-600 transition-colors hover:text-gray-900"
>
Close
</button>
</div>
</div>
</Modal>
30 changes: 13 additions & 17 deletions src/lib/components/ScrollToBottomBtn.svelte
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
<script lang="ts">
import { run } from "svelte/legacy";
import { fade } from "svelte/transition";
import { onDestroy } from "svelte";
import IconChevron from "./icons/IconChevron.svelte";
let visible = $state(false);
interface Props {
scrollNode: HTMLElement;
class?: string;
}
let { scrollNode, class: className = "" }: Props = $props();
let visible = $state(false);
let observer: ResizeObserver | null = $state(null);
function updateVisibility() {
Expand All @@ -24,20 +22,18 @@
observer?.disconnect();
scrollNode?.removeEventListener("scroll", updateVisibility);
}
onDestroy(destroy);
run(() => {
if (scrollNode) {
destroy();
if (window.ResizeObserver) {
observer = new ResizeObserver(() => {
updateVisibility();
});
observer.observe(scrollNode);
const cleanup = $effect.root(() => {
$effect(() => {
if (scrollNode) {
if (window.ResizeObserver) {
observer = new ResizeObserver(() => updateVisibility());
observer.observe(scrollNode);
cleanup();
}
scrollNode?.addEventListener("scroll", updateVisibility);
}
scrollNode.addEventListener("scroll", updateVisibility);
}
});
return () => destroy();
});
</script>

Expand Down
20 changes: 11 additions & 9 deletions src/lib/components/Toast.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts">
import { fade } from "svelte/transition";
import Portal from "./Portal.svelte";
import IconDazzled from "$lib/components/icons/IconDazzled.svelte";
interface Props {
Expand All @@ -10,14 +10,16 @@
let { message = "" }: Props = $props();
</script>

<div
transition:fade|global={{ duration: 300 }}
class="pointer-events-none fixed right-0 top-12 z-20 bg-gradient-to-bl from-red-500/20 via-red-500/0 to-red-500/0 pb-36 pl-36 pr-2 pt-2 md:top-0 md:pr-8 md:pt-5"
>
<Portal>
<div
class="pointer-events-auto flex items-center rounded-full bg-white/90 px-3 py-1 shadow-sm dark:bg-gray-900/80"
transition:fade|global={{ duration: 300 }}
class="pointer-events-none fixed right-0 top-12 z-50 bg-gradient-to-bl from-red-500/20 via-red-500/0 to-red-500/0 pb-36 pl-36 pr-2 pt-2 md:top-0 md:pr-8 md:pt-5"
>
<IconDazzled classNames="text-2xl mr-2" />
<h2 class="max-w-2xl font-semibold">{message}</h2>
<div
class="pointer-events-auto flex items-center rounded-full bg-white/90 px-3 py-1 shadow-sm dark:bg-gray-900/80"
>
<IconDazzled classNames="text-2xl mr-2" />
<h2 class="max-w-2xl font-semibold text-gray-800 dark:text-gray-200">{message}</h2>
</div>
</div>
</div>
</Portal>
36 changes: 22 additions & 14 deletions src/lib/components/chat/Alternatives.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
import CarbonChevronLeft from "~icons/carbon/chevron-left";
import CarbonChevronRight from "~icons/carbon/chevron-right";
import { enhance } from "$app/forms";
import { createEventDispatcher } from "svelte";
import { base } from "$app/paths";
import { page } from "$app/state";
import { error } from "$lib/stores/errors";
import { invalidate } from "$app/navigation";
import { UrlDependency } from "$lib/types/UrlDependency";
interface Props {
message: Message;
Expand Down Expand Up @@ -45,22 +49,26 @@
>
<CarbonChevronRight class="text-sm" />
</button>
{#if !loading && message.children}<form
method="POST"
action="?/deleteBranch"
{#if !loading && message.children}
<button
class="hidden group-hover/navbranch:block"
use:enhance={({ cancel }) => {
if (!confirm("Are you sure you want to delete this branch?")) {
cancel();
}
onclick={() => {
fetch(`${base}/api/conversation/${page.params.id}/message/${message.id}`, {
method: "DELETE",
}).then(async (r) => {
if (r.ok) {
await invalidate(UrlDependency.Conversation);
} else {
$error = (await r.json()).message;
}
});
}}
>
<input name="messageId" value={message.id} type="hidden" />
<button
<div
class="flex items-center justify-center text-xs text-gray-400 hover:text-gray-800 dark:text-gray-500 dark:hover:text-gray-200"
type="submit"
><CarbonTrashCan />
</button>
</form>
>
<CarbonTrashCan />
</div>
</button>
{/if}
</div>
11 changes: 11 additions & 0 deletions src/routes/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import ExpandNavigation from "$lib/components/ExpandNavigation.svelte";
import { loginModalOpen } from "$lib/stores/loginModal";
import LoginModal from "$lib/components/LoginModal.svelte";
import OverloadedModal from "$lib/components/OverloadedModal.svelte";
import { isHuggingChat } from "$lib/utils/isHuggingChat";
let { data = $bindable(), children } = $props();
Expand All @@ -34,6 +36,8 @@
let isNavOpen = $state(false);
let isNavCollapsed = $state(false);
let overloadedModalOpen = $state(false);
let errorToastTimeout: ReturnType<typeof setTimeout>;
let currentError: string | undefined = $state();
Expand All @@ -47,6 +51,9 @@
currentError = $error;
if (currentError === "Model is overloaded") {
overloadedModalOpen = true;
}
errorToastTimeout = setTimeout(() => {
$error = undefined;
currentError = undefined;
Expand Down Expand Up @@ -235,6 +242,10 @@
/>
{/if}

{#if overloadedModalOpen && isHuggingChat}
<OverloadedModal onClose={() => (overloadedModalOpen = false)} />
{/if}

<div
class="fixed grid h-full w-screen grid-cols-1 grid-rows-[auto,1fr] overflow-hidden text-smd {!isNavCollapsed
? 'md:grid-cols-[290px,1fr]'
Expand Down
42 changes: 42 additions & 0 deletions src/routes/api/conversation/[id]/message/[messageId]/+server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { authCondition } from "$lib/server/auth";
import { collections } from "$lib/server/database";
import { error } from "@sveltejs/kit";
import { ObjectId } from "mongodb";

export async function DELETE({ locals, params }) {
const messageId = params.messageId;

if (!messageId || typeof messageId !== "string") {
error(400, "Invalid message id");
}

const conversation = await collections.conversations.findOne({
...authCondition(locals),
_id: new ObjectId(params.id),
});

if (!conversation) {
error(404, "Conversation not found");
}

const filteredMessages = conversation.messages
.filter(
(message) =>
// not the message AND the message is not in ancestors
!(message.id === messageId) && message.ancestors && !message.ancestors.includes(messageId)
)
.map((message) => {
// remove the message from children if it's there
if (message.children && message.children.includes(messageId)) {
message.children = message.children.filter((child) => child !== messageId);
}
return message;
});

await collections.conversations.updateOne(
{ _id: conversation._id, ...authCondition(locals) },
{ $set: { messages: filteredMessages } }
);

return new Response();
}
41 changes: 0 additions & 41 deletions src/routes/conversation/[id]/+page.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,44 +66,3 @@ export const load = async ({ params, depends, locals }) => {
shared,
};
};

export const actions = {
deleteBranch: async ({ request, locals, params }) => {
const data = await request.formData();
const messageId = data.get("messageId");

if (!messageId || typeof messageId !== "string") {
error(400, "Invalid message id");
}

const conversation = await collections.conversations.findOne({
...authCondition(locals),
_id: new ObjectId(params.id),
});

if (!conversation) {
error(404, "Conversation not found");
}

const filteredMessages = conversation.messages
.filter(
(message) =>
// not the message AND the message is not in ancestors
!(message.id === messageId) && message.ancestors && !message.ancestors.includes(messageId)
)
.map((message) => {
// remove the message from children if it's there
if (message.children && message.children.includes(messageId)) {
message.children = message.children.filter((child) => child !== messageId);
}
return message;
});

await collections.conversations.updateOne(
{ _id: conversation._id, ...authCondition(locals) },
{ $set: { messages: filteredMessages } }
);

return { from: "deleteBranch", ok: true };
},
};
Loading

0 comments on commit f18d65e

Please sign in to comment.