Skip to content

Conversation

@Artuomka
Copy link
Collaborator

No description provided.

Copilot AI review requested due to automatic review settings January 30, 2026 15:52
@Artuomka Artuomka enabled auto-merge January 30, 2026 15:52
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

Adds automatic chat naming for new AI conversations and tightens AI JSON-output handling to reduce parsing failures.

Changes:

  • Generate a chat title on first user message for newly created AI chats and persist it.
  • Extend IUserAiChatRepository with updateChatName and implement it in the repository extension.
  • Strengthen the AI prompt guidance and post-processing for JSON responses (remove comments / trailing commas).

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
backend/src/entities/ai/use-cases/request-info-from-table-with-ai-v7.use.case.ts Triggers background chat-title generation for new chats and updates the persisted chat name.
backend/src/entities/ai/ai.service.ts Updates the LLM prompt to emphasize strict JSON-only output with no comments.
backend/src/entities/ai/ai-conversation-history/user-ai-chat/repository/user-ai-chat-repository.interface.ts Adds updateChatName to the repository interface.
backend/src/entities/ai/ai-conversation-history/user-ai-chat/repository/user-ai-chat-repository.extension.ts Implements updateChatName via a TypeORM update query.
backend/src/ai-core/tools/query-validators.ts Expands AI JSON cleaning to strip comment syntax and trailing commas before parsing.

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

Comment on lines +92 to +94
this.generateAndUpdateChatName(foundUserAiChat.id, user_message).catch((error) => {
Sentry.captureException(error);
});
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.

generateAndUpdateChatName() already catches and reports errors internally, so the additional .catch(...) here will never run and makes the async fire-and-forget behavior harder to reason about. Either remove the outer .catch and explicitly mark the call as fire-and-forget (e.g., void ...), or remove the internal try/catch and handle errors only at the call site (but avoid double-reporting).

Suggested change
this.generateAndUpdateChatName(foundUserAiChat.id, user_message).catch((error) => {
Sentry.captureException(error);
});
void this.generateAndUpdateChatName(foundUserAiChat.id, user_message);

Copilot uses AI. Check for mistakes.
findChatByIdAndUserId(chatId: string, userId: string): Promise<UserAiChatEntity | null>;
findChatWithMessagesByIdAndUserId(chatId: string, userId: string): Promise<UserAiChatEntity | null>;
createChatForUser(userId: string, name?: string): Promise<UserAiChatEntity>;
updateChatName(chatId: string, name: string): Promise<void>;
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.

updateChatName is defined without a userId parameter, unlike the other repository methods that scope operations by chatId + userId. To avoid accidental cross-tenant updates, consider changing this API to updateChatName(chatId: string, userId: string, name: string) (or similar) so implementations can enforce ownership at the data layer.

Suggested change
updateChatName(chatId: string, name: string): Promise<void>;
updateChatName(chatId: string, userId: string, name: string): Promise<void>;

Copilot uses AI. Check for mistakes.
Comment on lines +36 to +40
async updateChatName(chatId: string, name: string): Promise<void> {
await this.createQueryBuilder()
.update(UserAiChatEntity)
.set({ name })
.where('id = :chatId', { 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.

This update query scopes only by id. Since chats are user-owned (and other repo methods require userId), this should also include user_id = :userId (and accept userId as a parameter) to prevent updating another user's chat if a UUID is ever reused/leaked/passed incorrectly.

Suggested change
async updateChatName(chatId: string, name: string): Promise<void> {
await this.createQueryBuilder()
.update(UserAiChatEntity)
.set({ name })
.where('id = :chatId', { chatId })
async updateChatName(chatId: string, userId: string, name: string): Promise<void> {
await this.createQueryBuilder()
.update(UserAiChatEntity)
.set({ name })
.where('id = :chatId AND user_id = :userId', { chatId, userId })

Copilot uses AI. Check for mistakes.
Comment on lines +112 to +114
cleanedResponse = cleanedResponse.replace(/^\s*\/\/.*$/gm, '');
cleanedResponse = cleanedResponse.replace(/\/\*[\s\S]*?\*\//g, '');
cleanedResponse = cleanedResponse.replace(/,(\s*[}\]])/g, '$1');
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 block-comment stripping regex (/\/\*[\s\S]*?\*\//g) will also remove /* ... */ sequences that appear inside valid JSON string values, mutating otherwise-correct AI responses (e.g., a description containing those characters). Consider using a comment-tolerant parser (e.g., JSON5) or implementing a small scanner that removes comments only when not inside quoted strings.

Copilot uses AI. Check for mistakes.
@Artuomka Artuomka merged commit 66adf95 into main Jan 30, 2026
25 checks passed
@Artuomka Artuomka deleted the backend_ai_conversation_history branch January 30, 2026 16:00
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