Skip to content

Commit a2eebc0

Browse files
authored
Merge pull request #31 from ikuzweelisa/new-ui
Improvements
2 parents c13c9cb + 190960b commit a2eebc0

File tree

104 files changed

+4552
-3732
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

104 files changed

+4552
-3732
lines changed

.eslintrc.json

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

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
{
2-
"typescript.tsdk": "node_modules/typescript/lib"
2+
"typescript.tsdk": "node_modules/typescript/lib",
3+
"typescript.experimental.useTsgo": true
34
}

GEMINI.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
This is a Next.js application that provides a chat interface for interacting with an AI. It uses a variety of modern web technologies to provide a feature-rich experience.
66

7-
The project is a "Code Copilot" chat bot. It allows users to generate responses, copy messages, regenerate messages, save and retrieve chats from a database, and upload attachments.
7+
The project is a " Chat" chat bot. It allows users to generate responses, copy messages, regenerate messages, save and retrieve chats from a database, and upload attachments.
88

99
## Building and Running
1010

@@ -38,7 +38,7 @@ To get started with this project, you'll need to have Node.js and pnpm installed
3838

3939
### Other useful commands:
4040

41-
* `pnpm run lint`: Lint the code.
41+
* `pnpm run lint`: Lint the .
4242
* `pnpm run typecheck`: Run the TypeScript compiler to check for type errors.
4343
* `pnpm run db:push`: Push database schema changes.
4444
* `pnpm run db:generate`: Generate database migration files.
@@ -52,5 +52,5 @@ To get started with this project, you'll need to have Node.js and pnpm installed
5252
* **Database:** The project uses a PostgreSQL database with [Drizzle ORM](https://orm.drizzle.team/). The database schema is defined in `lib/drizzle/schema.ts`.
5353
* **Styling:** The project uses [Tailwind CSS](https://tailwindcss.com/) for styling.
5454
* **UI Components:** The project uses [Radix UI](https://www.radix-ui.com/) and custom components for the user interface.
55-
* **Linting and Formatting:** The project uses [ESLint](https://eslint.org/) for linting and [Prettier](https://prettier.io/) for code formatting.
55+
* **Linting and Formatting:** The project uses [ESLint](https://eslint.org/) for linting and [Prettier](https://prettier.io/) for formatting.
5656
* **Type Checking:** The project uses [TypeScript](https://www.typescriptlang.org/) for static type checking.

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
## Code Copilot
1+
##
22

3-
Code Copilot Chat bot
3+
Chat Chat bot
44

55
> Some Features may not work or Contain bugs.
66
>
@@ -19,7 +19,7 @@ Code Copilot Chat bot
1919
- [x] Update Chat from database
2020
- [x] Show Chat History
2121
- [ ] Canvas Feature
22-
- [ ] Run code using web container
22+
- [ ] Run using web container
2323

2424
## Technologies
2525

app/(home)/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { SidebarProvider, SidebarTrigger } from "~/components/ui/sidebar";
55
export default function Layout({ children }: { children: React.ReactNode }) {
66
return (
77
<div className="h-0">
8-
<SidebarProvider defaultOpen={false}>
8+
<SidebarProvider>
99
<Navbar />
1010
<main className=" w-full h-screen overflow-hidden bg-muted/50">
1111
<SidebarTrigger />

app/(home)/settings/page.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import React from "react";
2+
import { Settings } from "~/components/settings";
3+
4+
export default function page() {
5+
return <Settings />;
6+
}

app/api/auth/[...auth]/route.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { toNextJsHandler } from "better-auth/next-js";
2+
import { auth } from "~/lib/auth";
3+
4+
export const { POST, GET } = toNextJsHandler(auth);

app/api/auth/[...nextauth]/route.ts

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

app/api/chat/[id]/stream/route.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { UI_MESSAGE_STREAM_HEADERS } from "ai";
2+
import { after } from "next/server";
3+
import { createResumableStreamContext } from "resumable-stream/ioredis";
4+
import { getChatById } from "~/lib/server";
5+
6+
export async function GET(
7+
_: Request,
8+
{ params }: { params: Promise<{ id: string }> }
9+
) {
10+
const { id } = await params;
11+
const chat = await getChatById(id);
12+
if (!chat || chat.activeStreamId == null) {
13+
// no content response when there is no active stream
14+
return new Response(null, { status: 204 });
15+
}
16+
const streamContext = createResumableStreamContext({
17+
waitUntil: after,
18+
});
19+
20+
return new Response(
21+
await streamContext.resumeExistingStream(chat.activeStreamId),
22+
{ headers: UI_MESSAGE_STREAM_HEADERS }
23+
);
24+
}

app/api/chat/route.ts

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,84 @@
1-
import { NextRequest } from "next/server";
1+
import type { NextRequest } from "next/server";
22
import { systemPrompt } from "~/lib/ai/prompt";
33
import { chatSchema } from "./schema";
44
import { models } from "~/lib/ai/models";
5-
import { convertToModelMessages, streamText } from "ai";
6-
import { saveChatData } from "~/lib/server";
5+
import { convertToModelMessages, generateId, streamText } from "ai";
6+
import { getChatById, saveChatData } from "~/lib/server";
77
import { cookies } from "next/headers";
8+
import { after } from "next/server";
9+
import { createResumableStreamContext } from "resumable-stream/ioredis";
10+
import { generateMessageId } from "~/lib/ai/utis";
811

912
export async function POST(request: NextRequest) {
10-
const parsedBody = chatSchema.parse(await request.json());
11-
const { id, messages } = parsedBody;
13+
const body = await request.json();
14+
const parsedBody = chatSchema.parse(body);
15+
16+
const { id, message, trigger, messageId } = parsedBody;
1217
const cookieStore = await cookies();
1318
const modelId = cookieStore.get("model.id")?.value;
14-
const model = models.find((m) => m.id === Number(modelId)) ?? models[0];
19+
const model = models.find((m) => m.id === modelId) ?? models[0];
20+
const chat = await getChatById(id);
21+
let messages = chat?.messages ?? [];
22+
if (trigger === "submit-message") {
23+
messages = [...messages, message];
24+
}
25+
if (trigger === "regenerate-message") {
26+
const messageIndex =
27+
messageId == null
28+
? messages.length - 1
29+
: messages.findIndex((message) => message.id === messageId);
30+
31+
if (messageIndex === -1) {
32+
throw new Error(`message ${messageId} not found`);
33+
}
34+
35+
// set the messages to the message before the assistant message
36+
messages = messages.slice(
37+
0,
38+
messages[messageIndex].role === "assistant"
39+
? messageIndex
40+
: messageIndex + 1
41+
);
42+
}
1543
const coreMessage = convertToModelMessages(messages);
44+
45+
await saveChatData({
46+
id: id,
47+
messages: messages,
48+
streamId: null,
49+
});
1650
const result = streamText({
1751
model: model.model,
1852
messages: coreMessage,
1953
system: systemPrompt,
2054
});
55+
2156
return result.toUIMessageStreamResponse({
22-
async onFinish({ messages, responseMessage }) {
23-
await saveChatData(id, [...messages, responseMessage]);
57+
generateMessageId: generateMessageId,
58+
originalMessages: messages,
59+
messageMetadata: ({ part }) => {
60+
if (part.type === "start") {
61+
return {
62+
createdAt: Date.now(),
63+
model: model.name,
64+
};
65+
}
66+
if (part.type === "finish") {
67+
return {
68+
totalTokens: part.totalUsage.totalTokens,
69+
};
70+
}
71+
},
72+
onFinish: async ({ messages }) => {
73+
//generete title when model is done
74+
await saveChatData({ id, messages, streamId: null, genTittle: true });
75+
},
76+
async consumeSseStream({ stream }) {
77+
const streamId = generateId();
78+
const streamContext = createResumableStreamContext({ waitUntil: after });
79+
await streamContext.createNewResumableStream(streamId, () => stream);
80+
// Update the chat with the active stream ID
81+
await saveChatData({ id, streamId: streamId });
2482
},
2583
});
2684
}

0 commit comments

Comments
 (0)