From c0c984d82e5334c64cb8322a0e37be5fd76c399a Mon Sep 17 00:00:00 2001 From: Harkamal Randhawa Date: Fri, 10 Apr 2026 07:20:15 -0600 Subject: [PATCH] Fix bot runtime --- .../backend/controller/ChatController.java | 4 +-- .../controller/ChatWebSocketController.java | 2 +- .../backend/service/OpenRouterAiService.java | 35 +++++++++++++++---- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/backend/src/main/java/com/petshop/backend/controller/ChatController.java b/backend/src/main/java/com/petshop/backend/controller/ChatController.java index f5dcb5fc..5c7d87de 100644 --- a/backend/src/main/java/com/petshop/backend/controller/ChatController.java +++ b/backend/src/main/java/com/petshop/backend/controller/ChatController.java @@ -91,7 +91,7 @@ public class ChatController { MessageResponse message = chatService.sendMessage(id, user.getId(), user.getRole(), request); chatRealtimeService.publishMessage(id, message); chatRealtimeService.publishConversationUpdate(id); - openRouterAiService.generateAndSendReply(id); + openRouterAiService.generateAndSendReply(id, message.getId()); return ResponseEntity.status(HttpStatus.CREATED).body(message); } @@ -105,7 +105,7 @@ public class ChatController { MessageResponse message = chatService.sendMessageWithAttachment(id, user.getId(), user.getRole(), file, content); chatRealtimeService.publishMessage(id, message); chatRealtimeService.publishConversationUpdate(id); - openRouterAiService.generateAndSendReply(id); + openRouterAiService.generateAndSendReply(id, message.getId()); return ResponseEntity.status(HttpStatus.CREATED).body(message); } diff --git a/backend/src/main/java/com/petshop/backend/controller/ChatWebSocketController.java b/backend/src/main/java/com/petshop/backend/controller/ChatWebSocketController.java index 36b0469a..4bee487c 100644 --- a/backend/src/main/java/com/petshop/backend/controller/ChatWebSocketController.java +++ b/backend/src/main/java/com/petshop/backend/controller/ChatWebSocketController.java @@ -57,7 +57,7 @@ public class ChatWebSocketController { MessageResponse message = chatService.sendMessage(id, user.getId(), user.getRole(), request); chatRealtimeService.publishMessage(id, message); chatRealtimeService.publishConversationUpdate(id); - openRouterAiService.generateAndSendReply(id); + openRouterAiService.generateAndSendReply(id, message.getId()); } @MessageExceptionHandler({IllegalArgumentException.class, RuntimeException.class}) diff --git a/backend/src/main/java/com/petshop/backend/service/OpenRouterAiService.java b/backend/src/main/java/com/petshop/backend/service/OpenRouterAiService.java index 4d56bdc1..2f093ce4 100644 --- a/backend/src/main/java/com/petshop/backend/service/OpenRouterAiService.java +++ b/backend/src/main/java/com/petshop/backend/service/OpenRouterAiService.java @@ -2,6 +2,7 @@ package com.petshop.backend.service; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.json.JsonMapper; import com.petshop.backend.entity.Conversation; import com.petshop.backend.entity.Message; import com.petshop.backend.entity.User; @@ -45,25 +46,27 @@ public class OpenRouterAiService { ChatService chatService, ChatRealtimeService chatRealtimeService, MessageRepository messageRepository, - UserRepository userRepository, - ObjectMapper objectMapper + UserRepository userRepository ) { this.chatService = chatService; this.chatRealtimeService = chatRealtimeService; this.messageRepository = messageRepository; this.userRepository = userRepository; - this.objectMapper = objectMapper; + this.objectMapper = JsonMapper.builder().findAndAddModules().build(); this.httpClient = HttpClient.newBuilder() .connectTimeout(Duration.ofSeconds(10)) .build(); } - public void generateAndSendReply(Long conversationId) { - CompletableFuture.runAsync(() -> generateReply(conversationId)); + public void generateAndSendReply(Long conversationId, Long triggerMessageId) { + CompletableFuture.runAsync(() -> generateReply(conversationId, triggerMessageId)); } - private void generateReply(Long conversationId) { + private void generateReply(Long conversationId, Long triggerMessageId) { try { + if (triggerMessageId == null) { + return; + } if (apiKey == null || apiKey.isBlank()) { log.debug("Skipping OpenRouter reply for conversation {} because no API key is configured", conversationId); return; @@ -87,12 +90,20 @@ public class OpenRouterAiService { User botUser = userRepository.findByUsername(BOT_USERNAME) .orElseThrow(() -> new IllegalStateException("Bot user not found")); + Message triggerMessage = messageRepository.findById(triggerMessageId).orElse(null); + if (triggerMessage == null || !conversationId.equals(triggerMessage.getConversationId())) { + return; + } + List history = messageRepository.findByConversationIdOrderByTimestampAsc(conversationId); if (history.isEmpty()) { return; } Message lastMessage = history.get(history.size() - 1); + if (!triggerMessageId.equals(lastMessage.getId())) { + return; + } String lastContent = normalizeContent(lastMessage.getContent()); if (lastContent.isBlank()) { return; @@ -146,6 +157,18 @@ public class OpenRouterAiService { return; } + Conversation latestConversation = chatService.getConversationEntity(conversationId); + if (latestConversation.getStatus() == Conversation.ConversationStatus.CLOSED + || latestConversation.getHumanRequestedAt() != null + || latestConversation.getMode() != Conversation.ConversationMode.AUTOMATED) { + return; + } + + List latestHistory = messageRepository.findByConversationIdOrderByTimestampAsc(conversationId); + if (latestHistory.isEmpty() || !triggerMessageId.equals(latestHistory.get(latestHistory.size() - 1).getId())) { + return; + } + var messageResponse = chatService.saveBotMessage(conversationId, replyContent); chatRealtimeService.publishMessage(conversationId, messageResponse); chatRealtimeService.publishConversationUpdate(conversationId);