Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/(auth)/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export default function Page() {

const { update: updateSession } = useSession();

// biome-ignore lint/correctness/useExhaustiveDependencies: fix infinite loop on login
useEffect(() => {
if (state.status === "failed") {
toast({
Expand Down
1 change: 1 addition & 0 deletions app/(auth)/register/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export default function Page() {

const { update: updateSession } = useSession();

// biome-ignore lint/correctness/useExhaustiveDependencies: fix infinite loop on register
useEffect(() => {
if (state.status === "user_exists") {
toast({ type: "error", description: "Account already exists!" });
Expand Down
2 changes: 1 addition & 1 deletion app/(chat)/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import { generateText, type UIMessage } from "ai";
import { cookies } from "next/headers";
import type { VisibilityType } from "@/components/visibility-selector";
import { myProvider } from "@/lib/ai/providers";
import { titlePrompt } from "@/lib/ai/prompts";
import { myProvider } from "@/lib/ai/providers";
import {
deleteMessagesByChatIdAfterTimestamp,
getMessageById,
Expand Down
2 changes: 1 addition & 1 deletion app/(chat)/api/history/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { NextRequest } from "next/server";
import { auth } from "@/app/(auth)/auth";
import { getChatsByUserId, deleteAllChatsByUserId } from "@/lib/db/queries";
import { deleteAllChatsByUserId, getChatsByUserId } from "@/lib/db/queries";
import { ChatSDKError } from "@/lib/errors";

export async function GET(request: NextRequest) {
Expand Down
6 changes: 3 additions & 3 deletions app/globals.css
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
@import "tailwindcss";

/* Add KaTeX CSS for math rendering */
@import "katex/dist/katex.min.css";

/* include utility classes in streamdown */
@source '../node_modules/streamdown/dist/index.js';

/* Add KaTeX CSS for math rendering */
@import 'katex/dist/katex.min.css';

/* custom variant for setting dark mode programmatically */
@custom-variant dark (&:is(.dark, .dark *));

Expand Down
16 changes: 11 additions & 5 deletions components/app-sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import { toast } from "sonner";
import { useSWRConfig } from "swr";
import { unstable_serialize } from "swr/infinite";
import { PlusIcon, TrashIcon } from "@/components/icons";
import { SidebarHistory, getChatHistoryPaginationKey } from "@/components/sidebar-history";
import {
getChatHistoryPaginationKey,
SidebarHistory,
} from "@/components/sidebar-history";
import { SidebarUserNav } from "@/components/sidebar-user-nav";
import { Button } from "@/components/ui/button";
import {
Expand All @@ -19,7 +22,6 @@ import {
SidebarMenu,
useSidebar,
} from "@/components/ui/sidebar";
import { Tooltip, TooltipContent, TooltipTrigger } from "./ui/tooltip";
import {
AlertDialog,
AlertDialogAction,
Expand All @@ -30,6 +32,7 @@ import {
AlertDialogHeader,
AlertDialogTitle,
} from "./ui/alert-dialog";
import { Tooltip, TooltipContent, TooltipTrigger } from "./ui/tooltip";

export function AppSidebar({ user }: { user: User | undefined }) {
const router = useRouter();
Expand Down Expand Up @@ -118,13 +121,16 @@ export function AppSidebar({ user }: { user: User | undefined }) {
<SidebarFooter>{user && <SidebarUserNav user={user} />}</SidebarFooter>
</Sidebar>

<AlertDialog onOpenChange={setShowDeleteAllDialog} open={showDeleteAllDialog}>
<AlertDialog
onOpenChange={setShowDeleteAllDialog}
open={showDeleteAllDialog}
>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Delete all chats?</AlertDialogTitle>
<AlertDialogDescription>
This action cannot be undone. This will permanently delete all your
chats and remove them from our servers.
This action cannot be undone. This will permanently delete all
your chats and remove them from our servers.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
Expand Down
6 changes: 3 additions & 3 deletions components/data-stream-handler.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"use client";

import { useEffect, useRef } from "react";
import { useEffect } from "react";
import { initialArtifactData, useArtifact } from "@/hooks/use-artifact";
import { artifactDefinitions } from "./artifact";
import { useDataStream } from "./data-stream-provider";

export function DataStreamHandler() {
const { dataStream,setDataStream } = useDataStream();
const { dataStream, setDataStream } = useDataStream();

const { artifact, setArtifact, setMetadata } = useArtifact();

Expand Down Expand Up @@ -77,7 +77,7 @@ export function DataStreamHandler() {
}
});
}
}, [dataStream, setArtifact, setMetadata, artifact]);
}, [dataStream, setArtifact, setMetadata, artifact, setDataStream]);

return null;
}
2 changes: 1 addition & 1 deletion components/elements/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export const Context = ({ className, usage, ...props }: ContextProps) => {
className={cn(
"inline-flex select-none items-center gap-1 rounded-md text-sm",
"cursor-pointer bg-background text-foreground",
"focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 outline-none ring-offset-background",
"outline-none ring-offset-background focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
className
)}
type="button"
Expand Down
5 changes: 1 addition & 4 deletions components/message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -328,12 +328,9 @@ export const ThinkingMessage = () => {
</div>

<div className="flex w-full flex-col gap-2 md:gap-4">
<div className="p-0 text-muted-foreground text-sm">
Thinking...
</div>
<div className="p-0 text-muted-foreground text-sm">Thinking...</div>
</div>
</div>
</motion.div>
);
};

42 changes: 25 additions & 17 deletions components/multimodal-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -231,59 +231,67 @@ function PureMultimodalInput({
},
[setAttachments, uploadFile]
);

const handlePaste = useCallback(
async (event: ClipboardEvent) => {
const items = event.clipboardData?.items;
if (!items) return;
if (!items) {
return;
}

const imageItems = Array.from(items).filter((item) =>
item.type.startsWith('image/'),
item.type.startsWith("image/")
);

if (imageItems.length === 0) return;
if (imageItems.length === 0) {
return;
}

// Prevent default paste behavior for images
event.preventDefault();

setUploadQueue((prev) => [...prev, 'Pasted image']);
setUploadQueue((prev) => [...prev, "Pasted image"]);

try {
const uploadPromises = imageItems.map(async (item) => {
const file = item.getAsFile();
if (!file) return;
return uploadFile(file);
if (!file) {
return;
}
return await uploadFile(file);
});

const uploadedAttachments = await Promise.all(uploadPromises);
const successfullyUploadedAttachments = uploadedAttachments.filter(
(attachment) =>
attachment !== undefined &&
attachment.url !== undefined &&
attachment.contentType !== undefined,
attachment.contentType !== undefined
);

setAttachments((curr) => [
...curr,
...(successfullyUploadedAttachments as Attachment[]),
]);
} catch (error) {
console.error('Error uploading pasted images:', error);
toast.error('Failed to upload pasted image(s)');
console.error("Error uploading pasted images:", error);
toast.error("Failed to upload pasted image(s)");
} finally {
setUploadQueue([]);
}
},
[setAttachments],
[setAttachments, uploadFile]
);

// Add paste event listener to textarea
useEffect(() => {
const textarea = textareaRef.current;
if (!textarea) return;
if (!textarea) {
return;
}

textarea.addEventListener('paste', handlePaste);
return () => textarea.removeEventListener('paste', handlePaste);
textarea.addEventListener("paste", handlePaste);
return () => textarea.removeEventListener("paste", handlePaste);
}, [handlePaste]);

return (
Expand Down Expand Up @@ -367,7 +375,7 @@ function PureMultimodalInput({
/>{" "}
<Context {...contextProps} />
</div>
<PromptInputToolbar className="!border-top-0 border-t-0! p-0 shadow-none dark:border-0 dark:border-transparent!">
<PromptInputToolbar className="border-top-0! border-t-0! p-0 shadow-none dark:border-0 dark:border-transparent!">
<PromptInputTools className="gap-0 sm:gap-0.5">
<AttachmentsButton
fileInputRef={fileInputRef}
Expand All @@ -385,9 +393,9 @@ function PureMultimodalInput({
) : (
<PromptInputSubmit
className="size-8 rounded-full bg-primary text-primary-foreground transition-colors duration-200 hover:bg-primary/90 disabled:bg-muted disabled:text-muted-foreground"
data-testid="send-button"
disabled={!input.trim() || uploadQueue.length > 0}
status={status}
data-testid="send-button"
>
<ArrowUpIcon size={14} />
</PromptInputSubmit>
Expand Down Expand Up @@ -482,7 +490,7 @@ function PureModelSelectorCompact({
value={selectedModel?.name}
>
<Trigger asChild>
<Button variant="ghost" className="h-8 px-2">
<Button className="h-8 px-2" variant="ghost">
<CpuIcon size={16} />
<span className="hidden font-medium text-xs sm:block">
{selectedModel?.name}
Expand Down
6 changes: 3 additions & 3 deletions components/preview-attachment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ export const PreviewAttachment = ({

{isUploading && (
<div
className="absolute inset-0 flex items-center justify-center bg-black/50"
data-testid="input-attachment-loader"
>
className="absolute inset-0 flex items-center justify-center bg-black/50"
data-testid="input-attachment-loader"
>
<Loader size={16} />
</div>
)}
Expand Down
Loading