MingruiZhang commited on
Commit
76fdff4
1 Parent(s): 2189691
.env.example ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # You must first activate a Billing Account here: https://platform.openai.com/account/billing/overview
2
+ # Then get your OpenAI API Key here: https://platform.openai.com/account/api-keys
3
+ OPENAI_API_KEY=XXXXXXXX
4
+
5
+ # Generate a random secret: https://generate-secret.vercel.app/32 or `openssl rand -base64 32`
6
+ AUTH_SECRET=XXXXXXXX
7
+ # Create a GitHub OAuth app here: https://github.com/settings/applications/new
8
+ # For info on authorization callback URL visit here: https://authjs.dev/reference/core/providers_github#callback-url
9
+ AUTH_GITHUB_ID=XXXXXXXX
10
+ AUTH_GITHUB_SECRET=XXXXXXXX
11
+ # Support OAuth login on preview deployments, see: https://authjs.dev/guides/basics/deployment#securing-a-preview-deployment
12
+ # Set the following only when deployed. In this example, we can reuse the same OAuth app, but if you are storing users, we recommend using a different OAuth app for development/production so that you don't mix your test and production user base.
13
+ # AUTH_REDIRECT_PROXY_URL=https://YOURAPP.vercel.app/api/auth
14
+
15
+ # Instructions to create kv database here: https://vercel.com/docs/storage/vercel-kv/quickstart and
16
+ KV_URL=XXXXXXXX
17
+ KV_REST_API_URL=XXXXXXXX
18
+ KV_REST_API_TOKEN=XXXXXXXX
19
+ KV_REST_API_READ_ONLY_TOKEN=XXXXXXXX
20
+
.eslintrc.json ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "$schema": "https://json.schemastore.org/eslintrc",
3
+ "root": true,
4
+ "extends": [
5
+ "next/core-web-vitals",
6
+ "prettier",
7
+ "plugin:tailwindcss/recommended"
8
+ ],
9
+ "plugins": ["tailwindcss"],
10
+ "rules": {
11
+ "tailwindcss/no-custom-classname": "off",
12
+ "tailwindcss/classnames-order": "off"
13
+ },
14
+ "settings": {
15
+ "tailwindcss": {
16
+ "callees": ["cn", "cva"],
17
+ "config": "tailwind.config.js"
18
+ }
19
+ },
20
+ "overrides": [
21
+ {
22
+ "files": ["*.ts", "*.tsx"],
23
+ "parser": "@typescript-eslint/parser"
24
+ }
25
+ ]
26
+ }
.gitignore ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2
+
3
+ # dependencies
4
+ node_modules
5
+ .pnp
6
+ .pnp.js
7
+
8
+ # testing
9
+ coverage
10
+
11
+ # next.js
12
+ .next/
13
+ out/
14
+ build
15
+
16
+ # misc
17
+ .DS_Store
18
+ *.pem
19
+
20
+ # debug
21
+ npm-debug.log*
22
+ yarn-debug.log*
23
+ yarn-error.log*
24
+ .pnpm-debug.log*
25
+
26
+ # local env files
27
+ .env.local
28
+ .env.development.local
29
+ .env.test.local
30
+ .env.production.local
31
+
32
+ # turbo
33
+ .turbo
34
+
35
+ .env
36
+ .vercel
37
+ .vscode
38
+ .env*.local
app/(chat)/chat/[id]/page.tsx ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { type Metadata } from 'next'
2
+ import { notFound, redirect } from 'next/navigation'
3
+
4
+ import { auth } from '@/auth'
5
+ import { getChat } from '@/app/actions'
6
+ import { Chat } from '@/components/chat'
7
+
8
+ export interface ChatPageProps {
9
+ params: {
10
+ id: string
11
+ }
12
+ }
13
+
14
+ export async function generateMetadata({
15
+ params
16
+ }: ChatPageProps): Promise<Metadata> {
17
+ const session = await auth()
18
+
19
+ if (!session?.user) {
20
+ return {}
21
+ }
22
+
23
+ const chat = await getChat(params.id, session.user.id)
24
+ return {
25
+ title: chat?.title.toString().slice(0, 50) ?? 'Chat'
26
+ }
27
+ }
28
+
29
+ export default async function ChatPage({ params }: ChatPageProps) {
30
+ const session = await auth()
31
+
32
+ if (!session?.user) {
33
+ redirect(`/sign-in?next=/chat/${params.id}`)
34
+ }
35
+
36
+ const chat = await getChat(params.id, session.user.id)
37
+
38
+ if (!chat) {
39
+ notFound()
40
+ }
41
+
42
+ if (chat?.userId !== session?.user?.id) {
43
+ notFound()
44
+ }
45
+
46
+ return <Chat id={chat.id} initialMessages={chat.messages} />
47
+ }
app/(chat)/layout.tsx ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { SidebarDesktop } from '@/components/sidebar-desktop'
2
+
3
+ interface ChatLayoutProps {
4
+ children: React.ReactNode
5
+ }
6
+
7
+ export default async function ChatLayout({ children }: ChatLayoutProps) {
8
+ return (
9
+ <div className="relative flex h-[calc(100vh_-_theme(spacing.16))] overflow-hidden">
10
+ <SidebarDesktop />
11
+ <div className="group w-full overflow-auto pl-0 animate-in duration-300 ease-in-out peer-[[data-state=open]]:lg:pl-[250px] peer-[[data-state=open]]:xl:pl-[300px]">
12
+ {children}
13
+ </div>
14
+ </div>
15
+ )
16
+ }
app/(chat)/page.tsx ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ import { nanoid } from '@/lib/utils'
2
+ import { Chat } from '@/components/chat'
3
+
4
+ export default function IndexPage() {
5
+ const id = nanoid()
6
+
7
+ return <Chat id={id} />
8
+ }
app/api/auth/[...nextauth]/route.ts ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ export { GET, POST } from '@/auth'
2
+ export const runtime = 'edge'
app/globals.css ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ @layer base {
6
+ :root {
7
+ --background: 0 0% 100%;
8
+ --foreground: 240 10% 3.9%;
9
+
10
+ --muted: 240 4.8% 95.9%;
11
+ --muted-foreground: 240 3.8% 46.1%;
12
+
13
+ --popover: 0 0% 100%;
14
+ --popover-foreground: 240 10% 3.9%;
15
+
16
+ --card: 0 0% 100%;
17
+ --card-foreground: 240 10% 3.9%;
18
+
19
+ --border: 240 5.9% 90%;
20
+ --input: 240 5.9% 90%;
21
+
22
+ --primary: 240 5.9% 10%;
23
+ --primary-foreground: 0 0% 98%;
24
+
25
+ --secondary: 240 4.8% 95.9%;
26
+ --secondary-foreground: 240 5.9% 10%;
27
+
28
+ --accent: 240 4.8% 95.9%;
29
+ --accent-foreground: ;
30
+
31
+ --destructive: 0 84.2% 60.2%;
32
+ --destructive-foreground: 0 0% 98%;
33
+
34
+ --ring: 240 5% 64.9%;
35
+
36
+ --radius: 0.5rem;
37
+ }
38
+
39
+ .dark {
40
+ --background: 240 10% 3.9%;
41
+ --foreground: 0 0% 98%;
42
+
43
+ --muted: 240 3.7% 15.9%;
44
+ --muted-foreground: 240 5% 64.9%;
45
+
46
+ --popover: 240 10% 3.9%;
47
+ --popover-foreground: 0 0% 98%;
48
+
49
+ --card: 240 10% 3.9%;
50
+ --card-foreground: 0 0% 98%;
51
+
52
+ --border: 240 3.7% 15.9%;
53
+ --input: 240 3.7% 15.9%;
54
+
55
+ --primary: 0 0% 98%;
56
+ --primary-foreground: 240 5.9% 10%;
57
+
58
+ --secondary: 240 3.7% 15.9%;
59
+ --secondary-foreground: 0 0% 98%;
60
+
61
+ --accent: 240 3.7% 15.9%;
62
+ --accent-foreground: ;
63
+
64
+ --destructive: 0 62.8% 30.6%;
65
+ --destructive-foreground: 0 85.7% 97.3%;
66
+
67
+ --ring: 240 3.7% 15.9%;
68
+ }
69
+ }
70
+
71
+ @layer base {
72
+ * {
73
+ @apply border-border;
74
+ }
75
+ body {
76
+ @apply bg-background text-foreground;
77
+ }
78
+ }
app/share/[id]/page.tsx ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // import { type Metadata } from 'next'
2
+ // import { notFound } from 'next/navigation'
3
+
4
+ // import { formatDate } from '@/lib/utils'
5
+ // import { getSharedChat } from '@/app/actions'
6
+ // import { ChatList } from '@/components/chat-list'
7
+
8
+ // interface SharePageProps {
9
+ // params: {
10
+ // id: string
11
+ // }
12
+ // }
13
+
14
+ // export async function generateMetadata({
15
+ // params
16
+ // }: SharePageProps): Promise<Metadata> {
17
+ // const chat = await getSharedChat(params.id)
18
+
19
+ // return {
20
+ // title: chat?.title.slice(0, 50) ?? 'Chat'
21
+ // }
22
+ // }
23
+
24
+ // export default async function SharePage({ params }: SharePageProps) {
25
+ // const chat = await getSharedChat(params.id)
26
+
27
+ // if (!chat || !chat?.sharePath) {
28
+ // notFound()
29
+ // }
30
+
31
+ // return (
32
+ // <>
33
+ // <div className="flex-1 space-y-6">
34
+ // <div className="px-4 py-6 border-b bg-background md:px-6 md:py-8">
35
+ // <div className="max-w-2xl mx-auto md:px-6">
36
+ // <div className="space-y-1 md:-mx-8">
37
+ // <h1 className="text-2xl font-bold">{chat.title}</h1>
38
+ // <div className="text-sm text-muted-foreground">
39
+ // {formatDate(chat.createdAt)} · {chat.messages.length} messages
40
+ // </div>
41
+ // </div>
42
+ // </div>
43
+ // </div>
44
+ // <ChatList messages={chat.messages} />
45
+ // </div>
46
+ // </>
47
+ // )
48
+ // }
app/sign-in/page.tsx ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { auth } from '@/auth'
2
+ import { LoginButton } from '@/components/login-button'
3
+ import { redirect } from 'next/navigation'
4
+
5
+ export default async function SignInPage() {
6
+ const session = await auth()
7
+ // redirect to home if user is already logged in
8
+ if (session?.user) {
9
+ redirect('/')
10
+ }
11
+
12
+ return (
13
+ <div className="flex h-[calc(100vh-theme(spacing.16))] items-center justify-center py-10">
14
+ <LoginButton />
15
+ </div>
16
+ )
17
+ }
yarn.lock ADDED
The diff for this file is too large to render. See raw diff