Skip to content

Conversation

@Artuomka
Copy link
Collaborator

No description provided.

…ases

- Introduced UserAiChatEntity and AiChatMessageEntity to manage AI chat sessions and messages.
- Implemented IUserAiChatRepository and IAiChatMessageRepository interfaces for data access.
- Created repository extensions for user AI chat and message functionalities.
- Developed use cases for finding, deleting, and retrieving user AI chats and messages.
- Added UserAiChatController to handle API requests related to user AI chats.
- Updated global database context to include new repositories.
- Created migration to set up database tables and relationships for AI chat entities.
Copilot AI review requested due to automatic review settings January 30, 2026 12:47
@Artuomka Artuomka enabled auto-merge January 30, 2026 12:50
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request implements AI conversation history functionality to enable users to maintain and manage persistent chat sessions with the AI assistant. The feature allows users to continue conversations across multiple requests and manage their chat history.

Changes:

  • Added database tables and entities for storing AI chat conversations and messages with user relationships
  • Implemented CRUD API endpoints for managing AI chats (list, get, delete)
  • Created a new v4 AI request endpoint that saves conversation messages to the database
  • Added comprehensive E2E tests for both SaaS and non-SaaS environments

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
backend/src/migrations/1769759553633-AddChatWithAiAndChatMessageEntities.ts Database migration creating user_ai_chat and ai_chat_message tables with foreign key relationships
backend/src/entities/ai/ai-conversation-history/user-ai-chat/user-ai-chat.entity.ts Entity definition for user AI chat sessions
backend/src/entities/ai/ai-conversation-history/ai-chat-messages/ai-chat-message.entity.ts Entity definition for individual chat messages with role (user/ai/system)
backend/src/entities/ai/ai-conversation-history/user-ai-chat/repository/*.ts Repository interface and implementation for chat CRUD operations
backend/src/entities/ai/ai-conversation-history/ai-chat-messages/repository/*.ts Repository interface and implementation for message operations
backend/src/entities/ai/ai-conversation-history/use-cases/*.ts Use cases for finding and deleting user AI chats
backend/src/entities/ai/ai-conversation-history/user-ai-chat.controller.ts REST controller exposing chat management endpoints
backend/src/entities/ai/use-cases/request-info-from-table-with-ai-v7.use.case.ts New v7 use case integrating conversation history with AI requests
backend/src/entities/ai/user-ai-requests-v2.controller.ts Updated controller with v4 endpoint supporting conversation threads
backend/src/entities/ai/ai.module.ts Module configuration registering new providers and applying authentication middleware
backend/src/entities/user/user.entity.ts Added relationship to user AI chats
backend/src/common/application/global-database-context.ts Added repositories for chat and message entities
backend/src/common/data-injection.tokens.ts Added use case tokens for dependency injection
backend/src/decorators/slug-uuid.decorator.ts Added 'chatId' parameter support
backend/src/exceptions/text/messages.ts Added AI_CHAT_NOT_FOUND error message
backend/test/ava-tests/saas-tests/ai-chat-e2e.test.ts Comprehensive E2E tests for AI chat functionality in SaaS mode
backend/test/ava-tests/non-saas-tests/non-saas-ai-chat-e2e.test.ts Comprehensive E2E tests for AI chat functionality in non-SaaS mode

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +15 to +18
`ALTER TABLE "ai_chat_message" ADD CONSTRAINT "FK_03bc49058afd5262d6a503bf123" FOREIGN KEY ("ai_chat_id") REFERENCES "user_ai_chat"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "user_ai_chat" ADD CONSTRAINT "FK_0f95dbd767d42e637345636cb5d" FOREIGN KEY ("user_id") REFERENCES "user"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

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

The foreign key constraints use "ON DELETE NO ACTION" which is inconsistent with the entity definitions and codebase conventions. Looking at the entity definitions, UserAiChatEntity and AiChatMessageEntity don't specify onDelete options, but similar user-owned entities throughout the codebase (like AiResponsesToUserEntity, UserApiKeyEntity, SignInAuditEntity) use CASCADE deletion. When a user is deleted, their AI chats should also be deleted. Similarly, when a chat is deleted, its messages should be deleted. Change both foreign key constraints to use "ON DELETE CASCADE" to match the expected behavior and prevent orphaned records.

Suggested change
`ALTER TABLE "ai_chat_message" ADD CONSTRAINT "FK_03bc49058afd5262d6a503bf123" FOREIGN KEY ("ai_chat_id") REFERENCES "user_ai_chat"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "user_ai_chat" ADD CONSTRAINT "FK_0f95dbd767d42e637345636cb5d" FOREIGN KEY ("user_id") REFERENCES "user"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
`ALTER TABLE "ai_chat_message" ADD CONSTRAINT "FK_03bc49058afd5262d6a503bf123" FOREIGN KEY ("ai_chat_id") REFERENCES "user_ai_chat"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "user_ai_chat" ADD CONSTRAINT "FK_0f95dbd767d42e637345636cb5d" FOREIGN KEY ("user_id") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,

Copilot uses AI. Check for mistakes.
Comment on lines +87 to +90
await this._dbContext.aiChatMessageRepository.saveMessage(foundUserAiChat.id, user_message, MessageRole.user);

const messages = new MessageBuilder().system(systemPrompt).human(user_message).build();

Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

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

The v7 use case saves conversation messages to the database but does not retrieve and include previous messages when sending requests to the AI. At line 89, it only builds messages with the system prompt and the current user message, completely ignoring the conversation history stored in the database. This defeats the purpose of maintaining conversation history since the AI model won't have context from previous exchanges. To fix this, after retrieving or creating the chat entity, load the existing messages from the database and include them in the MessageBuilder chain before adding the new user message. You should load messages from the aiChatMessageRepository, convert them to the appropriate format for the MessageBuilder, and add them in chronological order.

Suggested change
await this._dbContext.aiChatMessageRepository.saveMessage(foundUserAiChat.id, user_message, MessageRole.user);
const messages = new MessageBuilder().system(systemPrompt).human(user_message).build();
// Load existing conversation history for this chat and build the message list in chronological order.
const previousMessages =
await this._dbContext.aiChatMessageRepository.findMessagesByChatId(foundUserAiChat.id);
// Persist the current user message to the conversation history.
await this._dbContext.aiChatMessageRepository.saveMessage(
foundUserAiChat.id,
user_message,
MessageRole.user,
);
const messageBuilder = new MessageBuilder().system(systemPrompt);
for (const message of previousMessages) {
if (message.role === MessageRole.user) {
messageBuilder.human(message.content);
} else if (message.role === MessageRole.ai) {
messageBuilder.ai(message.content);
}
}
// Append the current user message as the latest turn in the conversation.
const messages = messageBuilder.human(user_message).build();

Copilot uses AI. Check for mistakes.

@ManyToOne(
() => UserEntity,
(user) => user.ai_chats,
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

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

The ManyToOne relationship with UserEntity should specify the onDelete behavior to match the migration and follow codebase conventions. Similar user-owned entities like AiResponsesToUserEntity specify onDelete: 'CASCADE' in their decorators. Add the onDelete option to ensure TypeORM properly handles cascade deletion when generating migrations in the future.

Suggested change
(user) => user.ai_chats,
(user) => user.ai_chats,
{ onDelete: 'CASCADE' },

Copilot uses AI. Check for mistakes.

@ManyToOne(
() => UserAiChatEntity,
(ai_chat) => ai_chat.messages,
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

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

The ManyToOne relationship with UserAiChatEntity should specify the onDelete behavior to ensure messages are deleted when their parent chat is deleted. Add onDelete: 'CASCADE' to the decorator options to match the database migration and maintain referential integrity.

Suggested change
(ai_chat) => ai_chat.messages,
(ai_chat) => ai_chat.messages,
{ onDelete: 'CASCADE' },

Copilot uses AI. Check for mistakes.
throw new NotFoundException(Messages.AI_CHAT_NOT_FOUND);
}

await this._dbContext.aiChatMessageRepository.deleteMessagesForChat(chatId);
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

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

The manual deletion of messages at line 30 is unnecessary if the database foreign key constraint is properly set to CASCADE. Once the migration is fixed to use ON DELETE CASCADE, this explicit deletion can be removed since the database will automatically delete related messages when the chat is deleted. This would simplify the code and ensure atomicity of the deletion operation.

Suggested change
await this._dbContext.aiChatMessageRepository.deleteMessagesForChat(chatId);

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +17
import { MessageRole } from '../../ai-chat-messages/message-role.enum.js';

export class AiChatMessageRO {
id: string;
message: string;
role: MessageRole;
created_at: Date;
}

export class UserAiChatRO {
id: string;
name: string;
created_at: Date;
updated_at: Date;
}

export class UserAiChatWithMessagesRO extends UserAiChatRO {
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

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

The response object classes are missing @ApiProperty decorators which are consistently used throughout the codebase for Swagger documentation. Looking at similar DTOs like FoundUserDto or FoundConnectionPropertiesDs, all properties should have @ApiProperty() decorators to generate proper API documentation. Add these decorators to all properties in AiChatMessageRO, UserAiChatRO, and UserAiChatWithMessagesRO classes.

Suggested change
import { MessageRole } from '../../ai-chat-messages/message-role.enum.js';
export class AiChatMessageRO {
id: string;
message: string;
role: MessageRole;
created_at: Date;
}
export class UserAiChatRO {
id: string;
name: string;
created_at: Date;
updated_at: Date;
}
export class UserAiChatWithMessagesRO extends UserAiChatRO {
import { MessageRole } from '../../ai-chat-messages/message-role.enum.js';
import { ApiProperty } from '@nestjs/swagger';
export class AiChatMessageRO {
@ApiProperty()
id: string;
@ApiProperty()
message: string;
@ApiProperty({ enum: MessageRole })
role: MessageRole;
@ApiProperty()
created_at: Date;
}
export class UserAiChatRO {
@ApiProperty()
id: string;
@ApiProperty()
name: string;
@ApiProperty()
created_at: Date;
@ApiProperty()
updated_at: Date;
}
export class UserAiChatWithMessagesRO extends UserAiChatRO {
@ApiProperty({ type: () => [AiChatMessageRO] })

Copilot uses AI. Check for mistakes.
@Artuomka Artuomka disabled auto-merge January 30, 2026 12:54
@Artuomka Artuomka merged commit ac6643b into main Jan 30, 2026
19 checks passed
@Artuomka Artuomka deleted the backend_ai_conversation_history branch January 30, 2026 13:05
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.

2 participants