Refactor code for prompt specialization

The ChatGptPromptStateful class has been restructured into an abstract
base class, ChatGptPromptStatefulBase, with two specialized subclasses:
ChatGptPromptStatefulReview for Patch Set review instructions, and
ChatGptPromptStatefulRequests for handling replies to comment requests.
Furthermore, general stateful prompt items remain in
`promptsStateful.json`, while specialized resources for reviews and
requests have been segregated into `promptsStatefulReview.json` and
`promptsStatefulRequests.json` respectively.
This restructuring enhances code maintainability and prepares for
further prompt specialization.

Change-Id: I5d92d403a59df712acb74a534f230ce04e33ddba
Signed-off-by: Patrizio <patrizio.gelosi@amarulasolutions.com>
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/interfaces/mode/stateful/client/prompt/IChatGptPromptStateful.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/interfaces/mode/stateful/client/prompt/IChatGptPromptStateful.java
new file mode 100644
index 0000000..76820d9
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/interfaces/mode/stateful/client/prompt/IChatGptPromptStateful.java
@@ -0,0 +1,12 @@
+package com.googlesource.gerrit.plugins.chatgpt.interfaces.mode.stateful.client.prompt;
+
+import java.util.List;
+
+public interface IChatGptPromptStateful {
+    void addGptAssistantInstructions(List<String> instructions);
+    String getDefaultGptAssistantDescription();
+    String getDefaultGptAssistantInstructions();
+    String getDefaultGptThreadReviewMessage(String patchSet);
+    String getGptRequestDataPrompt();
+    void setCommentEvent(boolean isCommentEvent);
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptPromptFactory.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptPromptFactory.java
index a7653e7..e6cfb24 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptPromptFactory.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptPromptFactory.java
@@ -2,11 +2,14 @@
 
 import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
 import com.googlesource.gerrit.plugins.chatgpt.interfaces.mode.common.client.prompt.IChatGptDataPrompt;
+import com.googlesource.gerrit.plugins.chatgpt.interfaces.mode.stateful.client.prompt.IChatGptPromptStateful;
 import com.googlesource.gerrit.plugins.chatgpt.localization.Localizer;
 import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
 import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
 import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.GerritClientData;
 import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.prompt.ChatGptDataPromptRequestsStateful;
+import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.prompt.ChatGptPromptStatefulRequests;
+import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.prompt.ChatGptPromptStatefulReview;
 import com.googlesource.gerrit.plugins.chatgpt.mode.stateless.client.prompt.ChatGptDataPromptRequestsStateless;
 import com.googlesource.gerrit.plugins.chatgpt.settings.Settings;
 import lombok.extern.slf4j.Slf4j;
@@ -14,6 +17,20 @@
 @Slf4j
 public class ChatGptPromptFactory {
 
+    public static IChatGptPromptStateful getChatGptPromptStateful(
+            Configuration config,
+            ChangeSetData changeSetData,
+            GerritChange change
+    ) {
+        if (change.getIsCommentEvent()) {
+            log.info("ChatGptPromptFactory: Returned ChatGptPromptStatefulRequests");
+            return new ChatGptPromptStatefulRequests(config, changeSetData, change);
+        } else {
+            log.info("ChatGptPromptFactory: Returned ChatGptPromptStatefulReview");
+            return new ChatGptPromptStatefulReview(config, changeSetData, change);
+        }
+    }
+
     public static IChatGptDataPrompt getChatGptDataPrompt(
             Configuration config,
             ChangeSetData changeSetData,
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptAssistant.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptAssistant.java
index 1092a8b..2c87ba0 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptAssistant.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptAssistant.java
@@ -3,6 +3,7 @@
 import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
 import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandler;
 import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandlerProvider;
+import com.googlesource.gerrit.plugins.chatgpt.interfaces.mode.stateful.client.prompt.IChatGptPromptStateful;
 import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.ClientBase;
 import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.chatgpt.ChatGptParameters;
 import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.chatgpt.ChatGptTools;
@@ -11,7 +12,7 @@
 import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
 import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.UriResourceLocatorStateful;
 import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.git.GitRepoFiles;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.prompt.ChatGptPromptStateful;
+import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.prompt.ChatGptPromptStatefulBase;
 import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.model.api.chatgpt.*;
 import com.googlesource.gerrit.plugins.chatgpt.utils.HashUtils;
 import lombok.extern.slf4j.Slf4j;
@@ -22,6 +23,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import static com.googlesource.gerrit.plugins.chatgpt.mode.common.client.prompt.ChatGptPromptFactory.getChatGptPromptStateful;
 import static com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.chatgpt.ChatGptVectorStore.KEY_VECTOR_STORE_ID;
 import static com.googlesource.gerrit.plugins.chatgpt.utils.FileUtils.createTempFileWithContent;
 import static com.googlesource.gerrit.plugins.chatgpt.utils.FileUtils.sanitizeFilename;
@@ -127,7 +129,7 @@
                 )
         );
         ChatGptCreateAssistantRequestBody requestBody = ChatGptCreateAssistantRequestBody.builder()
-                .name(ChatGptPromptStateful.DEFAULT_GPT_ASSISTANT_NAME)
+                .name(ChatGptPromptStatefulBase.DEFAULT_GPT_ASSISTANT_NAME)
                 .description(description)
                 .instructions(instructions)
                 .model(model)
@@ -141,7 +143,7 @@
     }
 
     private void setupAssistantParameters() {
-        ChatGptPromptStateful chatGptPromptStateful = new ChatGptPromptStateful(config, changeSetData, change);
+        IChatGptPromptStateful chatGptPromptStateful = getChatGptPromptStateful(config, changeSetData, change);
         ChatGptParameters chatGptParameters = new ChatGptParameters(config, change.getIsCommentEvent());
 
         description = chatGptPromptStateful.getDefaultGptAssistantDescription();
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptThreadMessage.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptThreadMessage.java
index 06c9171..9d961ac 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptThreadMessage.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptThreadMessage.java
@@ -1,12 +1,12 @@
 package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.chatgpt;
 
 import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
+import com.googlesource.gerrit.plugins.chatgpt.interfaces.mode.stateful.client.prompt.IChatGptPromptStateful;
 import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.ClientBase;
 import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
 import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptRequestMessage;
 import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
 import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.UriResourceLocatorStateful;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.prompt.ChatGptPromptStateful;
 import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.model.api.chatgpt.ChatGptResponse;
 import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.model.api.chatgpt.ChatGptThreadMessageResponse;
 import lombok.extern.slf4j.Slf4j;
@@ -14,6 +14,7 @@
 
 import java.net.URI;
 
+import static com.googlesource.gerrit.plugins.chatgpt.mode.common.client.prompt.ChatGptPromptFactory.getChatGptPromptStateful;
 import static com.googlesource.gerrit.plugins.chatgpt.utils.GsonUtils.getGson;
 
 @Slf4j
@@ -78,7 +79,7 @@
     private Request addMessageRequest() {
         URI uri = URI.create(config.getGptDomain() + UriResourceLocatorStateful.threadMessagesUri(threadId));
         log.debug("ChatGPT Add Message request URI: {}", uri);
-        ChatGptPromptStateful chatGptPromptStateful = new ChatGptPromptStateful(config, changeSetData, change);
+        IChatGptPromptStateful chatGptPromptStateful = getChatGptPromptStateful(config, changeSetData, change);
         addMessageRequestBody = ChatGptRequestMessage.builder()
                 .role("user")
                 .content(chatGptPromptStateful.getDefaultGptThreadReviewMessage(patchSet))
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/prompt/ChatGptPromptStateful.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/prompt/ChatGptPromptStateful.java
deleted file mode 100644
index 9791ab2..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/prompt/ChatGptPromptStateful.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.prompt;
-
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.prompt.ChatGptPrompt;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static com.googlesource.gerrit.plugins.chatgpt.utils.TextUtils.*;
-
-
-@Slf4j
-public class ChatGptPromptStateful extends ChatGptPrompt {
-    private static final String RULE_NUMBER_PREFIX = "RULE #";
-
-    public static String DEFAULT_GPT_ASSISTANT_NAME;
-    public static String DEFAULT_GPT_ASSISTANT_DESCRIPTION;
-    public static String DEFAULT_GPT_ASSISTANT_INSTRUCTIONS;
-    public static String DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_REVIEW;
-    public static String DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_REQUESTS;
-    public static String DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_DONT_GUESS_CODE;
-    public static String DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_HISTORY;
-    public static String DEFAULT_GPT_MESSAGE_REVIEW;
-
-    private final ChangeSetData changeSetData;
-    private final GerritChange change;
-
-    public ChatGptPromptStateful(Configuration config, ChangeSetData changeSetData, GerritChange change) {
-        super(config);
-        this.changeSetData = changeSetData;
-        this.change = change;
-        this.isCommentEvent = change.getIsCommentEvent();
-        // Avoid repeated loading of prompt constants
-        if (DEFAULT_GPT_ASSISTANT_NAME == null) {
-            loadDefaultPrompts("promptsStateful");
-        }
-    }
-
-    public String getDefaultGptAssistantDescription() {
-        return String.format(DEFAULT_GPT_ASSISTANT_DESCRIPTION, change.getProjectName());
-    }
-
-    public String getDefaultGptAssistantInstructions() {
-        List<String> instructions = new ArrayList<>(List.of(
-                DEFAULT_GPT_SYSTEM_PROMPT + DOT,
-                String.format(DEFAULT_GPT_ASSISTANT_INSTRUCTIONS, change.getProjectName())
-        ));
-        if (change.getIsCommentEvent()) {
-            instructions.addAll(List.of(
-                    DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_REQUESTS,
-                    getCommentRequestPrompt(changeSetData.getCommentPropertiesSize())
-            ));
-        }
-        else {
-            instructions.addAll(List.of(
-                    getGptAssistantInstructionsReview(),
-                    getPatchSetReviewPrompt()
-            ));
-            if (config.getGptReviewCommitMessages()) {
-                instructions.add(getReviewPromptCommitMessages());
-            }
-        }
-        return joinWithSpace(instructions);
-    }
-
-    public String getDefaultGptThreadReviewMessage(String patchSet) {
-        String gptRequestDataPrompt = getGptRequestDataPrompt();
-        if (gptRequestDataPrompt != null && !gptRequestDataPrompt.isEmpty()) {
-            log.debug("Request User Prompt retrieved: {}", gptRequestDataPrompt);
-            return gptRequestDataPrompt;
-        }
-        else {
-            return String.format(DEFAULT_GPT_MESSAGE_REVIEW, patchSet);
-        }
-    }
-
-    private String getGptRequestDataPrompt() {
-        if (changeSetData == null || !isCommentEvent) return null;
-        return changeSetData.getGptDataPrompt();
-    }
-
-    private String getGptAssistantInstructionsReview() {
-        return String.format(DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_REVIEW, joinWithNewLine(getNumberedList(
-                new ArrayList<>(List.of(
-                        DEFAULT_GPT_PROMPT_FORCE_JSON_FORMAT,
-                        DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_DONT_GUESS_CODE,
-                        DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_HISTORY
-                )),
-                RULE_NUMBER_PREFIX, COLON_SPACE
-        )));
-    }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/prompt/ChatGptPromptStatefulBase.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/prompt/ChatGptPromptStatefulBase.java
new file mode 100644
index 0000000..bb39d01
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/prompt/ChatGptPromptStatefulBase.java
@@ -0,0 +1,65 @@
+package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.prompt;
+
+import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
+import com.googlesource.gerrit.plugins.chatgpt.interfaces.mode.stateful.client.prompt.IChatGptPromptStateful;
+import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.prompt.ChatGptPrompt;
+import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.googlesource.gerrit.plugins.chatgpt.utils.TextUtils.*;
+
+@Slf4j
+public abstract class ChatGptPromptStatefulBase extends ChatGptPrompt implements IChatGptPromptStateful {
+    public static String DEFAULT_GPT_ASSISTANT_NAME;
+    public static String DEFAULT_GPT_ASSISTANT_DESCRIPTION;
+    public static String DEFAULT_GPT_ASSISTANT_INSTRUCTIONS;
+    public static String DEFAULT_GPT_MESSAGE_REVIEW;
+
+    protected final ChangeSetData changeSetData;
+
+    private final GerritChange change;
+
+    public ChatGptPromptStatefulBase(Configuration config, ChangeSetData changeSetData, GerritChange change) {
+        super(config);
+        this.changeSetData = changeSetData;
+        this.change = change;
+        this.isCommentEvent = change.getIsCommentEvent();
+        // Avoid repeated loading of prompt constants
+        if (DEFAULT_GPT_ASSISTANT_NAME == null) {
+            loadDefaultPrompts("promptsStateful");
+        }
+    }
+
+    public String getDefaultGptAssistantDescription() {
+        return String.format(DEFAULT_GPT_ASSISTANT_DESCRIPTION, change.getProjectName());
+    }
+
+    public abstract void addGptAssistantInstructions(List<String> instructions);
+
+    public abstract String getGptRequestDataPrompt();
+
+    public String getDefaultGptAssistantInstructions() {
+        List<String> instructions = new ArrayList<>(List.of(
+                DEFAULT_GPT_SYSTEM_PROMPT + DOT,
+                String.format(DEFAULT_GPT_ASSISTANT_INSTRUCTIONS, change.getProjectName())
+        ));
+        addGptAssistantInstructions(instructions);
+
+        return joinWithSpace(instructions);
+    }
+
+    public String getDefaultGptThreadReviewMessage(String patchSet) {
+        String gptRequestDataPrompt = getGptRequestDataPrompt();
+        if (gptRequestDataPrompt != null && !gptRequestDataPrompt.isEmpty()) {
+            log.debug("Request User Prompt retrieved: {}", gptRequestDataPrompt);
+            return gptRequestDataPrompt;
+        }
+        else {
+            return String.format(DEFAULT_GPT_MESSAGE_REVIEW, patchSet);
+        }
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/prompt/ChatGptPromptStatefulRequests.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/prompt/ChatGptPromptStatefulRequests.java
new file mode 100644
index 0000000..e92629a
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/prompt/ChatGptPromptStatefulRequests.java
@@ -0,0 +1,35 @@
+package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.prompt;
+
+import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
+import com.googlesource.gerrit.plugins.chatgpt.interfaces.mode.stateful.client.prompt.IChatGptPromptStateful;
+import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.List;
+
+@Slf4j
+public class ChatGptPromptStatefulRequests extends ChatGptPromptStatefulBase implements IChatGptPromptStateful {
+    public static String DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_REQUESTS;
+
+    public ChatGptPromptStatefulRequests(Configuration config, ChangeSetData changeSetData, GerritChange change) {
+        super(config, changeSetData, change);
+        if (DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_REQUESTS == null) {
+            loadDefaultPrompts("promptsStatefulRequests");
+        }
+    }
+
+    @Override
+    public void addGptAssistantInstructions(List<String> instructions) {
+       instructions.addAll(List.of(
+                DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_REQUESTS,
+               getCommentRequestPrompt(changeSetData.getCommentPropertiesSize())
+        ));
+    }
+
+    @Override
+    public String getGptRequestDataPrompt() {
+        if (changeSetData == null ) return null;
+        return changeSetData.getGptDataPrompt();
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/prompt/ChatGptPromptStatefulReview.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/prompt/ChatGptPromptStatefulReview.java
new file mode 100644
index 0000000..389e5e6
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/prompt/ChatGptPromptStatefulReview.java
@@ -0,0 +1,55 @@
+package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.prompt;
+
+import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
+import com.googlesource.gerrit.plugins.chatgpt.interfaces.mode.stateful.client.prompt.IChatGptPromptStateful;
+import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.googlesource.gerrit.plugins.chatgpt.utils.TextUtils.*;
+
+@Slf4j
+public class ChatGptPromptStatefulReview extends ChatGptPromptStatefulBase implements IChatGptPromptStateful {
+    private static final String RULE_NUMBER_PREFIX = "RULE #";
+
+    public static String DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_REVIEW;
+    public static String DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_DONT_GUESS_CODE;
+    public static String DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_HISTORY;
+
+    public ChatGptPromptStatefulReview(Configuration config, ChangeSetData changeSetData, GerritChange change) {
+        super(config, changeSetData, change);
+        if (DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_REVIEW == null) {
+            loadDefaultPrompts("promptsStatefulReview");
+        }
+    }
+
+    @Override
+    public void addGptAssistantInstructions(List<String> instructions) {
+        instructions.addAll(List.of(
+                getGptAssistantInstructionsReview(),
+                getPatchSetReviewPrompt()
+        ));
+        if (config.getGptReviewCommitMessages()) {
+            instructions.add(getReviewPromptCommitMessages());
+        }
+    }
+
+    @Override
+    public String getGptRequestDataPrompt() {
+        return null;
+    }
+
+    private String getGptAssistantInstructionsReview() {
+        return String.format(DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_REVIEW, joinWithNewLine(getNumberedList(
+                new ArrayList<>(List.of(
+                        DEFAULT_GPT_PROMPT_FORCE_JSON_FORMAT,
+                        DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_DONT_GUESS_CODE,
+                        DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_HISTORY
+                )),
+                RULE_NUMBER_PREFIX, COLON_SPACE
+        )));
+    }
+}
diff --git a/src/main/resources/config/promptsStateful.json b/src/main/resources/config/promptsStateful.json
index 7f0e584..c774b91 100644
--- a/src/main/resources/config/promptsStateful.json
+++ b/src/main/resources/config/promptsStateful.json
@@ -2,10 +2,6 @@
   "DEFAULT_GPT_ASSISTANT_NAME": "PatchSet Reviewer",
   "DEFAULT_GPT_ASSISTANT_DESCRIPTION": "PatchSet Reviewer for project %s.",
   "DEFAULT_GPT_ASSISTANT_INSTRUCTIONS": "The project file uploaded as JSON object includes the source files for the `%s` project. The JSON object structure uses the file paths (from the project's root) as keys, and the corresponding file contents (stored as arrays of lines) as their values. This arrangement ensures that the line number for any given line of content is equal to its array index plus one.",
-  "DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_REVIEW": "You will receive a patch in the standard git format-patch format. Your tasks include: 1. applying this patch to the corresponding existing files, and 2. conducting a review of the patch. While reviewing the patch, you MUST strictly adhere to each of the following rules; failure to do so will make your response invalid.\n%s\nHere are other guidelines for reviewing the patch: A. Identify any potential problems and offer suggestions for enhancements, presenting each point as a separate reply; B. Focus solely on identifying and suggesting solutions for issues; refrain from highlighting any positive aspects; C. Only evaluate the code that has been modified in the patch; refrain from reviewing any other parts of the project's code that were not changed.",
-  "DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_REQUESTS": "You will receive a prompt request regarding the codebase files and/or one or more patches applied to these files. You are required to respond to the prompt, which may involve providing information, completing a task, answering a query, or making specified modifications. If you need or are requested to access any file from codebase, you will extract it from the project file uploaded. Additionally, you MUST take into account of the messages previously exchanged in the thread in your responses. For example, if you discover something in your previous answers that is relevant to the current response but was not initially identified, you must use this information in your answer.",
-  "DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_DONT_GUESS_CODE": "NEVER attempt to speculate about code that isn't explicitly included in the patch itself. You must locate all referenced code within the project's codebase. If certain code cannot be found, it indicates a potential error. For example, if a patch modifies a function call without changing the function's signature, you should verify compatibility with the existing signature in the codebase. If you cannot find the function's signature in the codebase, you must conclude that the function is not defined and raise a warning accordingly.",
-  "DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_HISTORY": "You MUST take into account of the messages previously exchanged in the thread for your review. For instance, if you uncover new information relevant to the review that was not identified in your initial assessment, you must incorporate this information to update your review.",
   "DEFAULT_GPT_MESSAGE_REVIEW": "Review the following Patch Set: ```%s```",
   "DEFAULT_GPT_HOW_TO_FIND_COMMIT_MESSAGE": "the \"Subject:\" entry of the Patch Set"
 }
diff --git a/src/main/resources/config/promptsStatefulRequests.json b/src/main/resources/config/promptsStatefulRequests.json
new file mode 100644
index 0000000..832612d
--- /dev/null
+++ b/src/main/resources/config/promptsStatefulRequests.json
@@ -0,0 +1,3 @@
+{
+  "DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_REQUESTS": "You will receive a prompt request regarding the codebase files and/or one or more patches applied to these files. You are required to respond to the prompt, which may involve providing information, completing a task, answering a query, or making specified modifications. If you need or are requested to access any file from codebase, you will extract it from the project file uploaded. Additionally, you MUST take into account of the messages previously exchanged in the thread in your responses. For example, if you discover something in your previous answers that is relevant to the current response but was not initially identified, you must use this information in your answer."
+}
diff --git a/src/main/resources/config/promptsStatefulReview.json b/src/main/resources/config/promptsStatefulReview.json
new file mode 100644
index 0000000..cf8d7f9
--- /dev/null
+++ b/src/main/resources/config/promptsStatefulReview.json
@@ -0,0 +1,5 @@
+{
+  "DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_REVIEW": "You will receive a patch in the standard git format-patch format. Your tasks include: 1. applying this patch to the corresponding existing files, and 2. conducting a review of the patch. While reviewing the patch, you MUST strictly adhere to each of the following rules; failure to do so will make your response invalid.\n%s\nHere are other guidelines for reviewing the patch: A. Identify any potential problems and offer suggestions for enhancements, presenting each point as a separate reply; B. Focus solely on identifying and suggesting solutions for issues; refrain from highlighting any positive aspects; C. Only evaluate the code that has been modified in the patch; refrain from reviewing any other parts of the project's code that were not changed.",
+  "DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_DONT_GUESS_CODE": "NEVER attempt to speculate about code that isn't explicitly included in the patch itself. You must locate all referenced code within the project's codebase. If certain code cannot be found, it indicates a potential error. For example, if a patch modifies a function call without changing the function's signature, you should verify compatibility with the existing signature in the codebase. If you cannot find the function's signature in the codebase, you must conclude that the function is not defined and raise a warning accordingly.",
+  "DEFAULT_GPT_ASSISTANT_INSTRUCTIONS_HISTORY": "You MUST take into account of the messages previously exchanged in the thread for your review. For instance, if you uncover new information relevant to the review that was not identified in your initial assessment, you must incorporate this information to update your review."
+}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewStatefulTest.java b/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewStatefulTest.java
index cae1e16..91e40a3 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewStatefulTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewStatefulTest.java
@@ -9,9 +9,9 @@
 import com.google.gerrit.extensions.restapi.RestApiException;
 import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandler;
 import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandlerProvider;
+import com.googlesource.gerrit.plugins.chatgpt.interfaces.mode.stateful.client.prompt.IChatGptPromptStateful;
 import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptResponseContent;
 import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.UriResourceLocatorStateful;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.prompt.ChatGptPromptStateful;
 import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.model.api.chatgpt.ChatGptListResponse;
 import com.googlesource.gerrit.plugins.chatgpt.settings.Settings.Modes;
 import com.googlesource.gerrit.plugins.chatgpt.utils.ThreadUtils;
@@ -30,6 +30,7 @@
 import java.net.URI;
 
 import static com.googlesource.gerrit.plugins.chatgpt.listener.EventHandlerTask.SupportedEvents;
+import static com.googlesource.gerrit.plugins.chatgpt.mode.common.client.prompt.ChatGptPromptFactory.getChatGptPromptStateful;
 import static com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.chatgpt.ChatGptRun.COMPLETED_STATUS;
 import static com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.chatgpt.ChatGptVectorStore.KEY_VECTOR_STORE_ID;
 import static com.googlesource.gerrit.plugins.chatgpt.settings.Settings.GERRIT_PATCH_SET_FILENAME;
@@ -49,7 +50,7 @@
     private static final String CHAT_GPT_RUN_ID = "run_TEST_RUN_ID";
 
     private String formattedPatchContent;
-    private ChatGptPromptStateful chatGptPromptStateful;
+    private IChatGptPromptStateful chatGptPromptStateful;
     private String requestContent;
     private PluginDataHandler projectHandler;
 
@@ -77,7 +78,7 @@
         super.initTest();
 
         // Load the prompts
-        chatGptPromptStateful = new ChatGptPromptStateful(config, changeSetData, getGerritChange());
+        chatGptPromptStateful = getChatGptPromptStateful(config, changeSetData, getGerritChange());
     }
 
     protected void setupMockRequests() throws RestApiException {