Skip to content

Commit fa9c1c7

Browse files
committed
Resolved merge conflicts from pull
2 parents 713069a + cb4f674 commit fa9c1c7

13 files changed

Lines changed: 359 additions & 179 deletions

File tree

eslint.config.js

Lines changed: 46 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,48 @@
1-
import { FlatCompat } from "@eslint/eslintrc";
2-
import tseslint from "typescript-eslint";
1+
// import { FlatCompat } from "@eslint/eslintrc";
2+
// import tseslint from "typescript-eslint";
33

4-
const compat = new FlatCompat({
5-
baseDirectory: import.meta.dirname,
6-
});
4+
// const compat = new FlatCompat({
5+
// baseDirectory: import.meta.dirname,
6+
// });
77

8-
export default tseslint.config(
9-
{
10-
ignores: [".next"],
11-
},
12-
...compat.extends("next/core-web-vitals"),
13-
{
14-
files: ["**/*.ts", "**/*.tsx"],
15-
extends: [
16-
...tseslint.configs.recommended,
17-
...tseslint.configs.recommendedTypeChecked,
18-
...tseslint.configs.stylisticTypeChecked,
19-
],
20-
rules: {
21-
"@typescript-eslint/array-type": "off",
22-
"@typescript-eslint/consistent-type-definitions": "off",
23-
"@typescript-eslint/consistent-type-imports": [
24-
"warn",
25-
{ prefer: "type-imports", fixStyle: "inline-type-imports" },
26-
],
27-
"@typescript-eslint/no-unused-vars": [
28-
"warn",
29-
{ argsIgnorePattern: "^_" },
30-
],
31-
"@typescript-eslint/require-await": "off",
32-
"@typescript-eslint/no-misused-promises": [
33-
"error",
34-
{ checksVoidReturn: { attributes: false } },
35-
],
36-
},
37-
},
38-
{
39-
linterOptions: {
40-
reportUnusedDisableDirectives: true,
41-
},
42-
languageOptions: {
43-
parserOptions: {
44-
projectService: true,
45-
},
46-
},
47-
},
48-
);
8+
// export default tseslint.config(
9+
// {
10+
// ignores: [".next"],
11+
// },
12+
// ...compat.extends("next/core-web-vitals"),
13+
// {
14+
// files: ["**/*.ts", "**/*.tsx"],
15+
// extends: [
16+
// ...tseslint.configs.recommended,
17+
// ...tseslint.configs.recommendedTypeChecked,
18+
// ...tseslint.configs.stylisticTypeChecked,
19+
// ],
20+
// rules: {
21+
// "@typescript-eslint/array-type": "off",
22+
// "@typescript-eslint/consistent-type-definitions": "off",
23+
// "@typescript-eslint/consistent-type-imports": [
24+
// "warn",
25+
// { prefer: "type-imports", fixStyle: "inline-type-imports" },
26+
// ],
27+
// "@typescript-eslint/no-unused-vars": [
28+
// "warn",
29+
// { argsIgnorePattern: "^_" },
30+
// ],
31+
// "@typescript-eslint/require-await": "off",
32+
// "@typescript-eslint/no-misused-promises": [
33+
// "error",
34+
// { checksVoidReturn: { attributes: false } },
35+
// ],
36+
// },
37+
// },
38+
// {
39+
// linterOptions: {
40+
// reportUnusedDisableDirectives: true,
41+
// },
42+
// languageOptions: {
43+
// parserOptions: {
44+
// projectService: true,
45+
// },
46+
// },
47+
// },
48+
// );
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
Warnings:
3+
4+
- A unique constraint covering the columns `[userId]` on the table `Subscription` will be added. If there are existing duplicate values, this will fail.
5+
- Changed the type of `role` on the `Message` table. No cast exists, the column would be dropped and recreated, which cannot be done if there is data, since the column is required.
6+
7+
*/
8+
-- CreateEnum
9+
CREATE TYPE "MessageRole" AS ENUM ('USER', 'ASSISTANT');
10+
11+
-- AlterTable
12+
ALTER TABLE "Message" DROP COLUMN "role",
13+
ADD COLUMN "role" "MessageRole" NOT NULL;
14+
15+
-- CreateIndex
16+
CREATE UNIQUE INDEX "Subscription_userId_key" ON "Subscription"("userId");

prisma/schema.prisma

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ model Message {
102102
chatId String
103103
chat Chat @relation(fields: [chatId], references: [id], onDelete: Cascade)
104104
content String
105-
role String
105+
role MessageRole
106106
createdAt DateTime @default(now())
107107
updatedAt DateTime @updatedAt
108108
@@index([chatId])
@@ -125,4 +125,9 @@ enum TransactionStatus {
125125
PENDING
126126
SUCCESS
127127
FAILED
128+
}
129+
130+
enum MessageRole {
131+
USER
132+
ASSISTANT
128133
}

src/actions/fetchUser.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,21 @@ export async function FetchUser() {
77
return null
88
}
99
const user = await db.user.findUnique({
10-
where: { id: session.user.id }
10+
where: { id: session.user.id, },
11+
select: {
12+
name: true,
13+
email: true,
14+
image: true,
15+
nickname: true,
16+
about: true,
17+
whatDoYouDo: true,
18+
customTraits: true,
19+
subscription: {
20+
select: {
21+
plan: true,
22+
}
23+
}
24+
}
1125
})
1226

1327
return user

src/actions/saveChat.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export async function saveChat(messages: Message[]) {
5757
id: message.id,
5858
chatId: chat.id,
5959
content: message.content,
60-
role: message.role,
60+
role: message.role === "user" ? "USER" : "ASSISTANT",
6161
},
6262
});
6363
}

src/app/(app)/ask/layout.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,17 @@ import { SelectTheme } from "@/components/ui/theme-toggler";
88
import { UIStructure } from "@/components/ui/ui-structure";
99
import { SlidersHorizontalIcon } from "@phosphor-icons/react/dist/ssr";
1010
import Link from "next/link";
11+
import { TRPCReactProvider } from "@/trpc/react";
1112

1213
export default function ChatLayout({
1314
children,
1415
}: {
1516
children: React.ReactNode;
1617
}) {
18+
1719
return (
1820
<>
21+
<TRPCReactProvider>
1922
<UIStructure />
2023
<SidebarInset className="!h-svh p-2">
2124
<div className="bg-muted/80 relative h-full max-h-svh w-full rounded-xl p-4">
@@ -34,8 +37,9 @@ export default function ChatLayout({
3437
<div className="mx-auto flex max-h-fit w-full max-w-3xl overflow-y-hidden">
3538
{children}
3639
</div>
37-
</div>
38-
</SidebarInset>
40+
</div>
41+
</SidebarInset>
42+
</TRPCReactProvider>
3943
</>
4044
);
4145
}

src/app/(app)/settings/subscription/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export default async function SubscriptionPage() {
5050
whatDoYouDo={user?.whatDoYouDo as string}
5151
customTraits={user?.customTraits as string[]}
5252
about={user?.about as string}
53-
plan={user?.plan as string}
53+
plan={user?.subscription?.plan as string}
5454
/>
5555

5656
{/* Message Usage */}

src/app/_components/Chat.tsx

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,13 @@ import { Textarea } from "@/components/ui/textarea";
66
import { Button } from "@/components/ui/button";
77
import { MicrophoneIcon } from "@phosphor-icons/react";
88
import { useParams } from "next/navigation";
9-
import {
10-
Select,
11-
SelectContent,
12-
SelectGroup,
13-
SelectItem,
14-
SelectLabel,
15-
SelectTrigger,
16-
SelectValue,
17-
} from "@/components/ui/select";
9+
1810
import { SpinnerGapIcon } from "@phosphor-icons/react/dist/ssr";
1911
import ReactMarkdown from "react-markdown";
2012
import SyntaxHighlighter from "react-syntax-highlighter";
21-
import { vs2015 } from "react-syntax-highlighter/dist/esm/styles/hljs";
2213
import remarkGfm from "remark-gfm";
2314
import { Geist_Mono } from "next/font/google";
2415
import { cn } from "@/lib/utils";
25-
import { api } from "@/trpc/react";
2616
import { ModelSelector } from "@/components/ui/model-selector";
2717
import { DEFAULT_MODEL_ID } from "@/models/constants";
2818

@@ -58,12 +48,6 @@ const Chat = () => {
5848
scrollToBottom();
5949
}, [messages]);
6050

61-
const saveChat = api.chat.createChat.useMutation({
62-
onError: (error) => {
63-
console.error("Error saving chat:", error);
64-
},
65-
});
66-
6751
const processStream = async (response: Response, userMessage: string) => {
6852
if (!response.ok) {
6953
console.error("Error from API:", response.statusText);
@@ -147,10 +131,6 @@ const Chat = () => {
147131
}
148132

149133
console.log("Saving chat to database:", userMessage, accumulatedContent);
150-
saveChat.mutate({
151-
message: userMessage,
152-
model: model,
153-
});
154134
} catch (error) {
155135
console.error("Error processing stream:", error);
156136
} finally {

src/app/_components/post.tsx

Lines changed: 0 additions & 25 deletions
This file was deleted.

src/app/api/ask/route.ts

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { env } from "@/env";
22
import { auth } from "@/server/auth";
33
import { fetchChatCompletion } from "@/models/service";
44
import { DEFAULT_MODEL_ID, getModelById } from "@/models/constants";
5-
5+
import { db } from "@/server/db";
66
interface ChatMessage {
77
role: "user" | "assistant" | "system";
88
content: string;
@@ -11,6 +11,7 @@ interface ChatMessage {
1111
interface TypeGPTPayload {
1212
messages: ChatMessage[];
1313
model?: string;
14+
chatId: string;
1415
}
1516

1617
interface TypeGPTErrorResponse {
@@ -30,9 +31,18 @@ export async function POST(req: Request): Promise<Response> {
3031
return new Response("Unauthorized", { status: 401 });
3132
}
3233

33-
const { messages, model = DEFAULT_MODEL_ID } =
34+
const { messages, model = DEFAULT_MODEL_ID, chatId } =
3435
(await req.json()) as TypeGPTPayload;
3536

37+
// Save user message
38+
await db.message.create({
39+
data: {
40+
chatId,
41+
content: messages[messages.length - 1]?.content ?? "",
42+
role: "USER",
43+
},
44+
});
45+
3646
const modelInfo = getModelById(model);
3747
if (!modelInfo) {
3848
return new Response(
@@ -50,6 +60,8 @@ export async function POST(req: Request): Promise<Response> {
5060
const writer = writable.getWriter();
5161

5262
void (async () => {
63+
let accumulatedContent = "";
64+
5365
try {
5466
const response = await fetchChatCompletion({
5567
modelId: model,
@@ -89,11 +101,53 @@ export async function POST(req: Request): Promise<Response> {
89101
const { done, value } = await reader.read();
90102

91103
if (done) {
104+
// Save AI message to database after stream completes
105+
if (accumulatedContent.trim()) {
106+
await db.message.create({
107+
data: {
108+
chatId,
109+
content: accumulatedContent,
110+
role: "ASSISTANT",
111+
},
112+
});
113+
}
114+
92115
await writer.write(encoder.encode("data: [DONE]\n\n"));
93116
await writer.close();
94117
break;
95118
}
96119

120+
// Accumulate content for database storage
121+
const chunk = new TextDecoder().decode(value);
122+
const lines = chunk.split("\n");
123+
124+
for (const line of lines) {
125+
if (line.trim() === "") continue;
126+
127+
if (line.startsWith("data: ")) {
128+
const data = line.substring(6);
129+
130+
if (data === "[DONE]") continue;
131+
132+
try {
133+
const parsedData = JSON.parse(data) as {
134+
choices?: Array<{
135+
delta?: {
136+
content?: string;
137+
};
138+
}>;
139+
};
140+
141+
const content = parsedData.choices?.[0]?.delta?.content;
142+
if (content) {
143+
accumulatedContent += content;
144+
}
145+
} catch (e) {
146+
// Ignore parsing errors for non-JSON lines
147+
}
148+
}
149+
}
150+
97151
await writer.write(value);
98152
}
99153
} catch (error) {
@@ -112,7 +166,6 @@ export async function POST(req: Request): Promise<Response> {
112166
}
113167
})();
114168

115-
116169
return new Response(readable, { headers });
117170
} catch (error) {
118171
console.error("Error in chat API:", error);

0 commit comments

Comments
 (0)