Skip to content

Chat history#441

Merged
elie222 merged 10 commits intomainfrom
feat/chat
May 22, 2025
Merged

Chat history#441
elie222 merged 10 commits intomainfrom
feat/chat

Conversation

@elie222
Copy link
Owner

@elie222 elie222 commented May 21, 2025

Summary by CodeRabbit

  • New Features

    • Introduced persistent chat history with the ability to fetch, view, and select previous conversations.
    • Added chat history dropdown for seamless navigation between chats.
    • Enabled dynamic loading of chat messages based on selected chat ID.
    • Added API endpoints to retrieve chats and individual chat messages securely.
  • Improvements

    • Enhanced chat input and UI to support optional chat IDs and dynamic initial message loading.
    • Improved error handling with detailed notifications.
    • Updated UI text and styling for better readability and consistency.
    • Added client-side fetching of pending rules to conditionally display relevant UI tabs.
  • Chores

    • Updated database schema with new tables for chats and chat messages, including relations and indexes.
    • Refined AI assistant chat processing to support persistent message storage and richer completion callbacks.
    • Introduced new React hooks to encapsulate chat and chat message data fetching.

@vercel
Copy link

vercel bot commented May 21, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
inbox-zero ✅ Ready (Inspect) Visit Preview May 22, 2025 4:03pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 21, 2025

Walkthrough

The changes introduce persistent chat functionality with chat history, message storage, and retrieval. New Prisma models and migrations add Chat and ChatMessage tables. API endpoints for chat creation, retrieval, and listing are implemented. The chat UI is refactored to support chat history selection and dynamic message loading. Supporting hooks and type updates are included.

Changes

File(s) / Path(s) Change Summary
apps/web/prisma/schema.prisma
apps/web/prisma/migrations/20250521104911_chat/migration.sql
apps/web/prisma/migrations/20250521132820_message_parts/migration.sql
Added Chat and ChatMessage models and relations to Prisma schema; created migration scripts to add these tables and later modify ChatMessage by replacing content with a JSON parts column.
apps/web/app/api/chat/route.ts Refactored chat API to accept structured input, validate with Zod, persist chat and messages, enforce authorization, and handle chat state with database integration. Added helpers for chat creation, message saving, and retrieval.
apps/web/app/api/chats/route.ts
apps/web/app/api/chats/[chatId]/route.ts
Added new API endpoints: one to fetch all chats for an email account, another to fetch a specific chat with messages. Both enforce authentication and return typed responses.
apps/web/utils/ai/assistant/chat.ts
apps/web/utils/llms/index.ts
Updated AI chat processing and streaming logic to use new Message[] types, richer result objects, and an onFinish callback for post-processing and result handling.
apps/web/app/api/ai/summarise/controller.ts Adjusted summarization logic to use the new result object format from the streaming function, passing only the result text to the summary-saving function.
apps/web/components/assistant-chat/chat.tsx Refactored chat UI to use chat ID from URL, fetch initial messages via hook, and support chat history selection through a dropdown. Updated props and error handling. Added helper to convert chat data to UI messages.
apps/web/components/assistant-chat/multimodal-input.tsx Made chatId prop optional in the input component and updated callback dependencies accordingly.
apps/web/app/(app)/[emailAccountId]/assistant/page.tsx Simplified Chat component usage by removing explicit id and initialMessages props.
apps/web/app/(app)/[emailAccountId]/automation/AssistantTabs.tsx Added client-side fetching of pending rules status and conditional rendering of "Pending" tab based on this status; minor UI text adjustment and padding added.
apps/web/hooks/useChats.ts Added a new hook to fetch chat list conditionally using SWR.
apps/web/hooks/useChatMessages.ts Added a new hook to fetch messages for a specific chat using SWR.
apps/web/app/api/rules/pending/route.ts Added new API endpoint to fetch pending rules status for an email account, returning a boolean indicating presence of pending non-automated rules.
apps/web/components/assistant-chat/multimodal-input.tsx Changed chatId prop from required to optional and updated callback dependencies.
apps/web/utils/ai/assistant/chat.ts Updated aiProcessAssistantChat function signature to accept new Message[] type and an onFinish callback for post-processing. Removed legacy commented code.
apps/web/utils/llms/index.ts Modified chatCompletionStream to accept new Message[] type and richer onFinish callback with full result object; added streaming transformation option.
apps/web/app/api/ai/summarise/controller.ts Adjusted summarization callback to extract and pass only text from the new result object.
.cursor/rules/get-api-route.mdc Updated example code to replace withAuth middleware with withEmailAccount for authentication and error handling.
apps/web/app/(app)/[emailAccountId]/automation/page.tsx Removed unused imports; no logic changes.
apps/web/app/api/chats/route.ts Added GET handler to fetch all chats for authenticated email account.
apps/web/app/api/chats/[chatId]/route.ts Added GET handler to fetch a specific chat and its messages for authenticated email account.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ChatUI
    participant useChatMessages / useChats
    participant API
    participant DB

    User->>ChatUI: Opens Assistant page
    ChatUI->>useChats: Optionally fetch chat list
    useChats->>API: GET /api/chats
    API->>DB: Query chats by emailAccountId
    DB-->>API: Return chat list
    API-->>useChats: Respond with chats
    useChats-->>ChatUI: Provide chat list

    User->>ChatUI: Selects a chat from history
    ChatUI->>useChatMessages: Fetch messages for chatId
    useChatMessages->>API: GET /api/chats/{chatId}
    API->>DB: Query chat and messages
    DB-->>API: Return chat with messages
    API-->>useChatMessages: Respond with chat data
    useChatMessages-->>ChatUI: Provide messages

    User->>ChatUI: Sends new message
    ChatUI->>API: POST /api/chat (chatId + message)
    API->>DB: Fetch or create chat, save user message
    API->>AI: Process chat with messages
    AI-->>API: Return assistant response
    API->>DB: Save assistant message
    API-->>ChatUI: Stream assistant response
Loading

Possibly related PRs

  • Filter by rule on history and pending tabs #302: Adds rule filtering and query parameter management for history and pending tabs in automation UI, related to pending rules handling and UI components, complementing the client-side pending rules fetching and conditional rendering introduced here.

Poem

🐇
A warren of chats now saved with care,
Messages stored, histories to share.
Dropdowns let you hop through time,
With Prisma fields both neat and prime.
The rabbit’s proud of all this lore—
Persistent chat, and so much more!
🥕

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

apps/web/app/(app)/[emailAccountId]/assistant/page.tsx

Oops! Something went wrong! :(

ESLint: 9.24.0

ESLint couldn't find an eslint.config.(js|mjs|cjs) file.

From ESLint v9.0.0, the default configuration file is now eslint.config.js.
If you are using a .eslintrc.* file, please follow the migration guide
to update your configuration file to the new format:

https://eslint.org/docs/latest/use/configure/migration-guide

If you still have problems after following the migration guide, please stop by
https://eslint.org/chat/help to chat with the team.

apps/web/app/(app)/[emailAccountId]/automation/AssistantTabs.tsx

Oops! Something went wrong! :(

ESLint: 9.24.0

ESLint couldn't find an eslint.config.(js|mjs|cjs) file.

From ESLint v9.0.0, the default configuration file is now eslint.config.js.
If you are using a .eslintrc.* file, please follow the migration guide
to update your configuration file to the new format:

https://eslint.org/docs/latest/use/configure/migration-guide

If you still have problems after following the migration guide, please stop by
https://eslint.org/chat/help to chat with the team.

apps/web/app/api/rules/pending/route.ts

Oops! Something went wrong! :(

ESLint: 9.24.0

ESLint couldn't find an eslint.config.(js|mjs|cjs) file.

From ESLint v9.0.0, the default configuration file is now eslint.config.js.
If you are using a .eslintrc.* file, please follow the migration guide
to update your configuration file to the new format:

https://eslint.org/docs/latest/use/configure/migration-guide

If you still have problems after following the migration guide, please stop by
https://eslint.org/chat/help to chat with the team.

Note

⚡️ AI Code Reviews for VS Code, Cursor, Windsurf

CodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback.
Learn more here.


Note

⚡️ Faster reviews with caching

CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 30th. To opt out, configure Review - Disable Cache at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the Data Retention setting under your Organization Settings.
Enjoy the performance boost—your workflow just got faster.

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (7)
apps/web/app/api/chats/route.ts (1)

13-20: Consider adding pagination for chat listing

The implementation for fetching chats is clean and follows good practices, ordering by most recent first. However, as users accumulate more chats over time, this endpoint might return a large payload.

Consider adding pagination to handle potentially large numbers of chat sessions:

- async function getChats({ emailAccountId }: { emailAccountId: string }) {
+ async function getChats({ emailAccountId, page = 1, limit = 20 }: { emailAccountId: string, page?: number, limit?: number }) {
  const chats = await prisma.chat.findMany({
    where: { emailAccountId },
    orderBy: { updatedAt: "desc" },
+   skip: (page - 1) * limit,
+   take: limit,
  });

-  return { chats };
+  return { chats, page, limit };
}
apps/web/components/assistant-chat/chat.tsx (2)

169-223: Well-implemented chat history dropdown with good UX patterns.

The ChatHistoryDropdown component is well-structured and follows good practices:

  • Lazy loading of chats only when the user interacts with the dropdown
  • Proper handling of loading and error states
  • Clean implementation of chat selection via URL query parameters

Consider adding a refresh mechanism for when new chats are created:

function ChatHistoryDropdown() {
  const [_chatId, setChatId] = useQueryState("chatId");
  const [shouldLoadChats, setShouldLoadChats] = useState(false);
-  const { data, error, isLoading } = useChats(shouldLoadChats);
+  const { data, error, isLoading, mutate } = useChats(shouldLoadChats);

  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <Button
          variant="ghost"
          size="icon"
-          onMouseEnter={() => setShouldLoadChats(true)}
+          onMouseEnter={() => {
+            setShouldLoadChats(true);
+            mutate(); // Refresh chat list when dropdown is opened
+          }}
        >

204-214: Enhance date formatting for better readability.

The current date formatting uses the browser's default locale settings, which may not be consistent across all users.

Consider using a more structured date format or a relative time format for better readability:

{data.chats.map((chatItem) => (
  <DropdownMenuItem
    key={chatItem.id}
    onSelect={() => {
      setChatId(chatItem.id);
    }}
  >
-    {`Chat from ${new Date(chatItem.createdAt).toLocaleString()}`}
+    {`Chat from ${new Date(chatItem.createdAt).toLocaleDateString()} at ${new Date(chatItem.createdAt).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}`}
  </DropdownMenuItem>
))}

Or consider using a relative time format like "2 hours ago" for better user experience.

apps/web/app/api/chats/[chatId]/route.ts (1)

29-51: Well-implemented database query with security constraints.

The getChat function:

  • Properly restricts access by checking both chatId and emailAccountId
  • Orders messages chronologically
  • Uses appropriate Prisma query structure

Consider adding pagination for messages to handle potentially large chat histories:

async function getChat({
  chatId,
  emailAccountId,
+  limit = 100,
+  offset = 0,
}: {
  chatId: string;
  emailAccountId: string;
+  limit?: number;
+  offset?: number;
}) {
  const chat = await prisma.chat.findUnique({
    where: {
      id: chatId,
      emailAccountId,
    },
    include: {
      messages: {
        orderBy: {
          createdAt: "asc",
        },
+       take: limit,
+       skip: offset,
      },
    },
  });

  return chat;
}
apps/web/prisma/schema.prisma (1)

581-595: ChatMessage model with proper structure and indexing.

The ChatMessage model is well-structured but could benefit from some enhancements:

Consider using an enum for the role field to restrict it to valid values:

+enum ChatMessageRole {
+  USER
+  ASSISTANT
+  SYSTEM
+}

model ChatMessage {
  id        String   @id @default(cuid())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

-  role    String
+  role    ChatMessageRole
  content String
  // attachments Json? // For storing message attachments if any
  // metadata    Json? // For any additional metadata, like tool calls

  chatId String
  chat   Chat   @relation(fields: [chatId], references: [id], onDelete: Cascade)

  @@index([chatId])
}
apps/web/app/api/chat/route.ts (2)

98-110: Order loaded messages to preserve chronology

findUnique({ include: { messages: true } }) returns messages in unspecified order.
Sorting prevents inconsistent conversation state:

 include: { 
-  messages: true 
+  messages: { orderBy: { createdAt: "asc" } } 
 },

174-180: convertDbRoleToSdkRole lacks a mapping for "tool"

saveChatMessages may persist "tool" roles, but the converter defaults them to "assistant".
Add explicit handling or filter such messages out.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between a9de5ad and 73de091.

📒 Files selected for processing (11)
  • apps/web/app/(app)/[emailAccountId]/automation/AssistantTabs.tsx (1 hunks)
  • apps/web/app/api/chat/route.ts (2 hunks)
  • apps/web/app/api/chats/[chatId]/route.ts (1 hunks)
  • apps/web/app/api/chats/route.ts (1 hunks)
  • apps/web/components/assistant-chat/chat.tsx (4 hunks)
  • apps/web/hooks/useChat.ts (1 hunks)
  • apps/web/hooks/useChats.ts (1 hunks)
  • apps/web/prisma/migrations/20250521104911_chat/migration.sql (1 hunks)
  • apps/web/prisma/schema.prisma (3 hunks)
  • apps/web/utils/ai/assistant/chat.ts (3 hunks)
  • apps/web/utils/llms/index.ts (4 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (5)
apps/web/hooks/useChats.ts (1)
apps/web/app/api/chats/route.ts (1)
  • GetChatsResponse (5-5)
apps/web/hooks/useChat.ts (1)
apps/web/app/api/chats/[chatId]/route.ts (1)
  • GetChatResponse (5-5)
apps/web/components/assistant-chat/chat.tsx (1)
apps/web/hooks/useChats.ts (1)
  • useChats (4-6)
apps/web/app/api/chats/route.ts (2)
apps/web/app/api/chats/[chatId]/route.ts (1)
  • GET (7-27)
apps/web/utils/middleware.ts (1)
  • withEmailAccount (190-194)
apps/web/app/api/chats/[chatId]/route.ts (2)
apps/web/app/api/chats/route.ts (1)
  • GET (7-11)
apps/web/utils/middleware.ts (1)
  • withEmailAccount (190-194)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Static Code Analysis Js
  • GitHub Check: Jit Security
🔇 Additional comments (14)
apps/web/app/(app)/[emailAccountId]/automation/AssistantTabs.tsx (1)

60-62: Clean text improvement in UI messaging

The removal of the possessive pronoun "your" from the instructional text makes the message more generic and consistent with the application's overall tone.

apps/web/hooks/useChats.ts (1)

1-6: Well-structured hook for fetching chats

Nice implementation of a custom hook that follows React best practices with SWR. The conditional fetching pattern with the shouldFetch parameter gives components control over when to load data.

apps/web/hooks/useChat.ts (1)

1-6: Clean implementation of single chat fetching hook

This hook follows the same good patterns as useChats, providing a consistent API for fetching a single chat by ID. The conditional fetch when chatId is undefined is handled properly.

apps/web/app/api/chats/route.ts (1)

1-11: Secure API route with proper authentication

The route handler is correctly wrapped with withEmailAccount middleware to ensure proper authentication and authorization. The implementation extracts the email account ID from the request auth context and uses it to fetch only the chats that belong to the authenticated user.

apps/web/utils/llms/index.ts (4)

12-13: Import additions for enhanced streaming capabilities.

The addition of smoothStream and updated Message type imports support the new word-level chunking feature and updated message handling.


174-175: Enhanced callback interface with additional result data.

The onFinish callback signature now includes the full result object, providing more context to callback handlers.


204-205: Updated callback invocation with result parameter.

The onFinish callback now receives both the completed text and the full result object.


169-170:

Details

❓ Verification inconclusive

Updated message type from CoreMessage to Message.

Changing the parameter type from CoreMessage[] to Message[] aligns with the updated requirements for chat message handling.

Verify that all places using this function have been updated to work with the new Message type:


🏁 Script executed:

#!/bin/bash
# Find all usages of chatCompletionStream function to check type compatibility
rg --type=typescript "chatCompletionStream" -A 5 -B 5

Length of output: 88


Let's broaden the search to all TypeScript files and drop the unrecognized type filter:


🏁 Script executed:

#!/bin/bash
# Find all usages of chatCompletionStream across .ts/.tsx files
rg "chatCompletionStream" -A 5 -B 5 --glob "*.ts" --glob "*.tsx"

Length of output: 5218


Please verify all chatCompletionStream call sites for the new Message[] type

The parameter has been updated from CoreMessage[] to Message[] in
apps/web/utils/llms/index.ts. Ensure each usage is still type-safe:

• apps/web/utils/ai/assistant/chat.ts
– passes messages; confirm that the local messages variable is declared as Message[] (not CoreMessage[]).
• apps/web/app/api/ai/summarise/controller.ts
– uses prompt only (no messages, which is optional).
• apps/web/app/api/ai/compose-autocomplete/route.ts
– uses prompt only (no messages, which is optional).

apps/web/app/api/chats/[chatId]/route.ts (1)

1-27: Well-structured API route with proper authentication and error handling.

The GET handler is implemented with good practices:

  • Uses authentication middleware to ensure the request is authorized
  • Validates required parameters
  • Returns appropriate error responses
  • Uses clean response formatting
apps/web/prisma/schema.prisma (3)

569-579: Well-designed Chat model with appropriate relationships.

The Chat model follows good database design principles:

  • Contains standard fields (id, timestamps)
  • Establishes proper relationship with EmailAccount
  • Includes cascade delete for proper cleanup
  • Has appropriate indexing for performance

587-590: Commented fields suggest planned future enhancements.

The commented out fields for attachments and metadata indicate preparation for future features.

It might be worth tracking these as future tasks. Do you have a roadmap or ticket for implementing these features?


124-124: Added Chat relation to EmailAccount model.

The relationship between EmailAccount and Chat is properly established.

apps/web/app/api/chat/route.ts (2)

84-92: Await message-saving to ensure durability

The HTTP response is returned immediately; if saveChatMessages fails, the client receives a 200 anyway.

-onFinish: (messages: any) => {
-  saveChatMessages({ … });
-},
+onFinish: async (messages) => {
+  const ok = await saveChatMessages({ … });
+  if (!ok) logger.error("Message persistence failed", { chatId: chat.id });
+},

47-55: ⚠️ Potential issue

Use success flag from safeParse for reliable validation

safeParse returns { success, data, error }. If parsing fails, data is undefined; accessing it later will throw.

-const { data, error } = assistantInputSchema.safeParse(json);
-if (error)
+const parse = assistantInputSchema.safeParse(json);
+if (!parse.success)
   return NextResponse.json({ error: error.message }, { status: 400 });
-const { data } = parse;     // guaranteed to exist

Likely an incorrect or invalid review comment.

Comment on lines +12 to +21
CREATE TABLE "ChatMessage" (
"id" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"role" TEXT NOT NULL,
"content" TEXT NOT NULL,
"chatId" TEXT NOT NULL,

CONSTRAINT "ChatMessage_pkey" PRIMARY KEY ("id")
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Schema is missing attachments / metadata columns used by the code

saveChatMessages() inserts attachments and metadata, but the table definition lacks them, causing runtime failures (Unknown arg attachments …).

   "content" TEXT NOT NULL,
   "chatId" TEXT NOT NULL,
+  "attachments" JSONB,
+  "metadata" JSONB,

Add the columns (or drop the fields in the write-path) and create matching Prisma model attributes.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
CREATE TABLE "ChatMessage" (
"id" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"role" TEXT NOT NULL,
"content" TEXT NOT NULL,
"chatId" TEXT NOT NULL,
CONSTRAINT "ChatMessage_pkey" PRIMARY KEY ("id")
);
CREATE TABLE "ChatMessage" (
"id" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"role" TEXT NOT NULL,
"content" TEXT NOT NULL,
"chatId" TEXT NOT NULL,
"attachments" JSONB,
"metadata" JSONB,
CONSTRAINT "ChatMessage_pkey" PRIMARY KEY ("id")
);
🤖 Prompt for AI Agents
In apps/web/prisma/migrations/20250521104911_chat/migration.sql around lines 12
to 21, the ChatMessage table is missing the attachments and metadata columns
that the code expects when calling saveChatMessages(), causing runtime errors.
Add appropriate columns for attachments and metadata to the table schema,
ensuring their data types match the expected structure (e.g., JSON or TEXT).
Also, update the corresponding Prisma model to include these fields so the
schema and code remain consistent.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (5)
apps/web/app/api/chat/route.ts (5)

82-82: Replace as any type cast with proper typing

Using as any bypasses TypeScript's type checking. This could lead to runtime errors if the structure of dbMsg.parts doesn't match what's expected.

-      parts: dbMsg.parts as any,
+      parts: dbMsg.parts as Prisma.JsonValue,

95-97: Consider handling attachments consistently

The code contains commented-out attachment handling. Either implement the feature fully or remove the commented code to avoid confusion.


104-109: Validate array is not empty before using at(-1)

The getTrailingMessageId function checks if the trailing message exists but the current code assumes there's at least one assistant message in the filtered array. Consider adding a check.

-      const assistantId = getTrailingMessageId({
-        messages: response.messages.filter(
-          (message: { role: string }) => message.role === "assistant",
-        ),
-      });
+      const assistantMessages = response.messages.filter(
+        (message: { role: string }) => message.role === "assistant",
+      );
+      
+      if (assistantMessages.length === 0) {
+        throw new Error("No assistant messages found in response!");
+      }
+      
+      const assistantId = getTrailingMessageId({
+        messages: assistantMessages,
+      });

123-126: Simplify nullable JSON handling

The conditional check and explicit use of Prisma.JsonNull appears unnecessarily complex for handling message parts.

-        parts: assistantMessage.parts
-          ? (assistantMessage.parts as Prisma.InputJsonValue)
-          : Prisma.JsonNull,
+        parts: assistantMessage.parts || [],

135-147: Enhance error handling in createNewChat

The function currently logs the error but doesn't provide specific details about what went wrong. Consider adding more specific error handling.

async function createNewChat(emailAccountId: string) {
  try {
    const newChat = await prisma.chat.create({
      data: { emailAccountId },
      include: { messages: true },
    });
    logger.info("New chat created", { chatId: newChat.id, emailAccountId });
    return newChat;
  } catch (error) {
-    logger.error("Failed to create new chat", { error, emailAccountId });
+    if (error instanceof Prisma.PrismaClientKnownRequestError) {
+      logger.error("Database error creating chat", { 
+        code: error.code,
+        meta: error.meta,
+        emailAccountId 
+      });
+    } else {
+      logger.error("Failed to create new chat", { 
+        error: error instanceof Error ? error.message : String(error), 
+        emailAccountId 
+      });
+    }
    return undefined;
  }
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 73de091 and 1945481.

📒 Files selected for processing (6)
  • apps/web/app/api/ai/summarise/controller.ts (1 hunks)
  • apps/web/app/api/chat/route.ts (2 hunks)
  • apps/web/prisma/migrations/20250521132820_message_parts/migration.sql (1 hunks)
  • apps/web/prisma/schema.prisma (3 hunks)
  • apps/web/utils/ai/assistant/chat.ts (3 hunks)
  • apps/web/utils/llms/index.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/web/prisma/schema.prisma
  • apps/web/utils/llms/index.ts
  • apps/web/utils/ai/assistant/chat.ts
🔇 Additional comments (6)
apps/web/app/api/ai/summarise/controller.ts (1)

27-28: Good adaptation to the new API signature.

The change correctly updates the onFinish callback to work with the new richer result object structure, extracting just the text content that's needed for the summary storage. This aligns well with the PR's chat history implementation while maintaining the original functionality.

apps/web/prisma/migrations/20250521132820_message_parts/migration.sql (1)

1-11: Schema migration removes content column and adds JSON parts field

This migration updates the ChatMessage table to use a more structured format, replacing the plain text content column with a structured parts JSON field. The migration explicitly warns about data loss and requirements.

A few considerations:

  1. Ensure you have a data migration strategy if this is applied to a production database with existing chat messages
  2. Consider adding a default empty JSON array ('[]') to make the migration more robust when applied to non-empty tables
apps/web/app/api/chat/route.ts (4)

161-176: LGTM: Role conversion function is well-implemented

The convertDbRoleToSdkRole function correctly handles role mapping without case conversion issues, addressing a previous concern with role conversion.


20-43: Schema validation is thorough

The input validation schema is well-defined with proper constraints on text length and structure. Good job implementing proper validation.


58-74: Strong security with chat ownership verification

Excellent implementation of authorization checks to ensure users can only access their own chats.


103-129: Well-structured callback for saving assistant messages

The onFinish callback effectively handles saving assistant messages after processing completes, ensuring message persistence.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/web/components/assistant-chat/multimodal-input.tsx (1)

100-100: Consider documenting the history manipulation approach.

The commented-out history manipulation code suggests there may be a new approach to URL management for chats. Consider adding a comment explaining the new approach or why this functionality was removed, to help future developers understand the design decision.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1945481 and 25e3930.

📒 Files selected for processing (5)
  • apps/web/app/(app)/[emailAccountId]/assistant/page.tsx (1 hunks)
  • apps/web/app/api/chat/route.ts (2 hunks)
  • apps/web/components/assistant-chat/chat.tsx (8 hunks)
  • apps/web/components/assistant-chat/multimodal-input.tsx (2 hunks)
  • apps/web/hooks/useChats.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • apps/web/app/(app)/[emailAccountId]/assistant/page.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/web/hooks/useChats.ts
  • apps/web/components/assistant-chat/chat.tsx
  • apps/web/app/api/chat/route.ts
🔇 Additional comments (2)
apps/web/components/assistant-chat/multimodal-input.tsx (2)

36-36: Good change making chatId optional.

Making the chatId prop optional is a good decision that aligns with the broader application changes for persistent chat support. This change allows the component to function properly whether or not a chat is currently selected, supporting the dynamic chat loading and selection functionality introduced in this PR.


110-110: Correctly updated dependency array.

The dependency array update is consistent with making chatId optional. Removing chatId from the dependencies prevents unnecessary re-renders when the chat ID changes and properly reflects that the callback no longer uses this value internally.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/web/hooks/useChatMessages.ts (1)

4-6: Consider adding revalidation options for improved user experience.

While the current implementation is solid, you might want to consider adding revalidation options to control refetching behavior:

export function useChatMessages(chatId?: string) {
-  return useSWR<GetChatResponse>(chatId ? `/api/chats/${chatId}` : null);
+  return useSWR<GetChatResponse>(
+    chatId ? `/api/chats/${chatId}` : null,
+    {
+      revalidateOnFocus: false, // Prevent refetching when tab regains focus
+      dedupingInterval: 10000, // Reduce duplicate requests
+    }
+  );
}

This would improve performance by reducing unnecessary refetches, especially important for chat applications where constant refetching might not be desired.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9f1f99e and b1eb0ec.

📒 Files selected for processing (4)
  • apps/web/app/(app)/[emailAccountId]/assistant/page.tsx (2 hunks)
  • apps/web/app/(app)/[emailAccountId]/automation/AssistantTabs.tsx (1 hunks)
  • apps/web/components/assistant-chat/chat.tsx (8 hunks)
  • apps/web/hooks/useChatMessages.ts (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • apps/web/app/(app)/[emailAccountId]/assistant/page.tsx
  • apps/web/app/(app)/[emailAccountId]/automation/AssistantTabs.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/components/assistant-chat/chat.tsx
🧰 Additional context used
🧬 Code Graph Analysis (1)
apps/web/hooks/useChatMessages.ts (1)
apps/web/app/api/chats/[chatId]/route.ts (1)
  • GetChatResponse (5-5)
🔇 Additional comments (1)
apps/web/hooks/useChatMessages.ts (1)

1-6: Well-implemented hook for chat message retrieval.

This hook is clean, focused, and follows SWR patterns correctly. It conditionally fetches chat data only when a valid chatId is provided, which prevents unnecessary API calls. The explicit typing with GetChatResponse ensures type safety throughout the application.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/web/app/api/rules/pending/route.ts (1)

16-22: Consider adding an index to optimize this query.

The database query is well-structured, using findFirst with minimal field selection for better performance. For frequently accessed routes, consider adding a database index on emailAccountId and automate fields if not already present.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b1eb0ec and 132bdf9.

📒 Files selected for processing (6)
  • .cursor/rules/get-api-route.mdc (2 hunks)
  • .cursor/rules/memory.mdc (0 hunks)
  • apps/web/app/(app)/[emailAccountId]/assistant/page.tsx (1 hunks)
  • apps/web/app/(app)/[emailAccountId]/automation/AssistantTabs.tsx (5 hunks)
  • apps/web/app/(app)/[emailAccountId]/automation/page.tsx (0 hunks)
  • apps/web/app/api/rules/pending/route.ts (1 hunks)
💤 Files with no reviewable changes (2)
  • apps/web/app/(app)/[emailAccountId]/automation/page.tsx
  • .cursor/rules/memory.mdc
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/web/app/(app)/[emailAccountId]/assistant/page.tsx
  • apps/web/app/(app)/[emailAccountId]/automation/AssistantTabs.tsx
🧰 Additional context used
🧬 Code Graph Analysis (1)
apps/web/app/api/rules/pending/route.ts (1)
apps/web/utils/middleware.ts (2)
  • withEmailAccount (190-194)
  • RequestWithEmailAccount (28-34)
🔇 Additional comments (3)
apps/web/app/api/rules/pending/route.ts (1)

10-14: LGTM! Proper use of authentication middleware.

The API route correctly uses the withEmailAccount middleware to ensure authenticated access and extract the current email account ID. This approach aligns with the updated guidelines in .cursor/rules/get-api-route.mdc.

.cursor/rules/get-api-route.mdc (2)

21-21: LGTM! Updated example with appropriate middleware.

The example code now correctly demonstrates the use of withEmailAccount instead of withAuth, which is consistent with the new API routes being implemented in the codebase.


41-44: LGTM! Clear explanation of middleware options.

The updated guidelines provide a clear distinction between withAuth and withEmailAccount, helping developers choose the appropriate middleware based on whether they need user-level or email account-level context. This aligns well with the implementation in apps/web/app/api/rules/pending/route.ts.

@elie222 elie222 merged commit c6722b9 into main May 22, 2025
6 of 7 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Jul 24, 2025
@elie222 elie222 deleted the feat/chat branch December 18, 2025 23:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Comments