Extension of ChatGPT only plugin to support private ai services.

- Creation of ai-code-review plugin.
 - Initial changes to this project will include renaming of the plugin
to ai-code-review, along with its assets.
 - The new plugin version resides in plugins/ai-code-review and was
 performed to allow Open Source contributions, without impacting chatGPT specific development.
 - Items that overlap will be renamed from chatGPTXXX to chatAIXXX.
Configuration will be renamed where it can be from gptModel / gptToken to aiToken etc. as it is applicable to more than just chatGPT.
 - Creation of new aiType member to allow the switching between different
authorization headers, and API endpoints easily.

- Adding plugin-repo-mvn jenkins build file, so it should build
 master for the submitted changes, and a verifier branch for code reviews.

Testing:
aiType=ollama
aiModel=qwen2.5-coder

OLLAMA working with several models, current suggestion is
to use the qwen-coder model ( note use the 7b model as the
1.5b currently doesn't correctly use tools support ).
The current prereq for the models is that
they support "tools" so that the format_replies tool call
can be made which returns the replies object in JSON matching
the supplied schema, without this it would require much more
parsing to change the response markdown->json on the response.

- Added a new quick start, for Ollama using a docker setup.  This will provide a local AI service instance using docker, running with the correct example model to begin testing.

- Added tests covering new configuration elements, and exposed some
 of the keys to the mocking to ensure they use the same altered names.

TODO:
 - Check what changes are required for Stateful OLLAMA reviews,
 it would appear the /assistants/v2 api from chatGPT is in beta
so this area will need reworked as its not openAI compliant yet.
 - AzureOpenAI has not been tested - WIP.
   - Auth header coded - using api-key.
   - API item called: apiversion needs to be passed as part of the endpoint string currently but should be a seperate configuration option and added as a query param.  e.g. https://{endpoint}/openai/deployments/{deployment-id}/completions?api-version=2024-06-01

Change-Id: Ic3ddeff429fcb4786eea1ed346eafd76dd6d0976
diff --git a/README.md b/README.md
index c8659b1..5a15bcf 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,23 @@
-# ChatGPT Code Review Gerrit Plugin
+# AI Code Review Gerrit Plugin
+
+## Starting Point
+This plugin has been based on the initial chatGPT plugin available on github: [chatgpt-code-review-gerrit-plugin](https://github.com/amarula/chatgpt-code-review-gerrit-plugin/)
+
+A full history of the previous plugin is in the branch: gerrithub-chatgpt-code-review/main.
+
+The requirement of the updated plugin was to abstract the chatGPT specific nature of the plugin and to provide a more
+generic naming point, and set of configuration and API naming that used the openAPI specification that is
+common between chatGPT and other private AI service providers.
 
 ## Features
 
-This plugin allows you to use ChatGPT for code review in Gerrit conveniently. After submitting a Patch Set, OpenAI will
-provide review feedback in the form of comments and, optionally, a vote.
-You can continue to ask ChatGPT by @{gerritUserName} or @{gerritEmailAddress} (provided that `gerritEmailAddress` is in
+This plugin allows you to use different AI Chat services, e.g. ChatGPT or OLLAMA for code review in Gerrit conveniently.
+After submitting a Patch Set, OpenAI will provide review feedback in the form of comments and, optionally, a vote.
+You can continue to ask the AI Chat by @{gerritUserName} or @{gerritEmailAddress} (provided that `gerritEmailAddress` is in
 the form "gerritUserName@<any_email_domain>") in the comments to further guide it in generating more targeted review
 comments.
-Reviews can be also triggered by directing a comment with the `/review` command to ChatGPT.
+Reviews can be also triggered by directing a comment with the `/review` command which will be interpretted and sent on by
+the plugin.
 
 ## Getting Started
 
@@ -24,26 +34,44 @@
 
 2. **Install:** Upload the compiled jar file to the `$gerrit_site/plugins` directory.
 
-3. **Configure:** First, you need to create a ChatGPT user in Gerrit.
+3. **Configure:** First, you need to create an AI Code Review user in Gerrit.
    Then, set up the basic parameters in your `$gerrit_site/etc/gerrit.config` file under the section
 
-   `[plugin "chatgpt-code-review-gerrit-plugin"]`:
+   `[plugin "ai-code-review"]`:
 
-- `gptToken`: OpenAI GPT token.
-- `gerritUserName`: Gerrit username of ChatGPT user.
+- `aiToken`: Authentication token, for aiType selected (Default: chatGPT bearer token).
+- `gerritUserName`: Gerrit username of AI Code Review user.
 - `globalEnable`: Default value is false. The plugin will only review specified repositories. If set to true, the plugin
    will by default review all pull requests.
 
-   For enhanced security, consider storing sensitive information like gptToken in a secure location
+   For enhanced security, consider storing sensitive information like aiToken in a secure location
    or file. Detailed instructions on how to do this will be provided later in this document.
 
 4. **Verify:** After restarting Gerrit, you can see the following information in Gerrit's logs:
 
    ```bash
-   INFO com.google.gerrit.server.plugins.PluginLoader : Loaded plugin chatgpt-code-review-gerrit-plugin, version ...
+   INFO com.google.gerrit.server.plugins.PluginLoader : Loaded plugin ai-code-review, version ...
    ```
 
-   You can also check the status of the chatgpt-code-review-gerrit-plugin on Gerrit's plugin page as Enabled.
+   You can also check the status of the ai-code-review on Gerrit's plugin page as Enabled.
+
+## Setup of a local ollama AI service.
+
+If you wish to test a local installation of 'Ollama' llm, then you can follow the instructions on the 
+ollama site directly, or the [official docker image](https://hub.docker.com/r/ollama/ollama) instructions.
+Using the docker instructions allows you to start various different models, and you can start and stop the
+image as much as you need to and the manifest data is associated with the container, so only when it is finally
+deleted with it remove the volume associated with that image.
+This allows you to clean up all the associated test images very easily with one command.
+
+``` docker run -d -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama ```
+
+You can then attach to this running ollama service and run any model/manifest you wish.
+
+``` docker exec -it ollama ollama run qwen2.5-coder ```
+
+
+
 
 ## Usage Examples
 
@@ -56,14 +84,15 @@
 **NOTE**: Voting is disabled by default. To use this feature, it needs to be activated either across all projects or on
 a per-project basis via the `enabledVoting` configuration option, as described below.
 
-### ChatGPT Score Adjustment Following User Interaction
+### AI Code Review Score Adjustment Following User Interaction
 
-In the example below, ChatGPT initially posits a potential unintended behavior in the code, assigning a "-1" score.
+In the example below, the AI Chat initially posits a potential unintended behavior in the code, assigning a "-1" score.
 Upon receiving clarification, it resets the score to "0".
 
 ![Example of Dialogue](images/chatgpt_changed_mind.png?raw=true)
 
-More examples of ChatGPT's code reviews and inline discussions are available at
+More examples of ChatGPT's use within code reviews and inline discussions based on the origin ChatGPT
+version of this plugin are available at
 https://wiki.amarulasolutions.com/opensource/products/chatgpt-gerrit.html
 
 ## Configuration Parameters
@@ -77,25 +106,41 @@
 as follows:
 
 ```
-[plugin "chatgpt-code-review-gerrit-plugin"]
+[plugin "ai-code-review"]
     # Required parameters
-    gptToken = {gptToken}
+    aiToken = {aiToken}
     ...
 
     # Optional parameters
-    gptModel = {gptModel}
-    gptSystemPrompt = {gptSystemPrompt}
+    aiType = {aiType}
+    aiModel = {aiModel}
+    aiSystemPrompt = {aiSystemPrompt}
+    ...
+```
+
+Note aiType is only optional as by default the system will assume an aiType of chatGPT
+so as to maintain compatibility with the previous chat-gpt version of the plugin.
+If you require a different service, update the optional parameters such as `aiType`.
+
+### Example Configuration for OLLAMA
+
+```
+[plugin "ai-code-review"]
+    # Required parameters
+    aiType = OLLAMA
+    aiModel = qwen2.5-coder
+    aiDomain = http://localhost:11434/
     ...
 ```
 
 #### Secure Configuration
 
-It is highly recommended to store sensitive information such as `gptToken` in the `secure.config`
+It is highly recommended to store sensitive information such as `aiToken` in the `secure.config`
 file. Please edit the file at $gerrit_site/etc/`secure.config` and include the following details:
 
 ```
-[plugin "chatgpt-code-review-gerrit-plugin"]
-    gptToken = {gptToken}
+[plugin "ai-code-review"]
+    aiToken = {aiToken}
 ```
 
 If you wish to encrypt the information within the `secure.config` file, you can refer
@@ -106,21 +151,21 @@
 To add the following content, please edit the `project.config` file in `refs/meta/config`:
 
 ```
-[plugin "chatgpt-code-review-gerrit-plugin"]
+[plugin "ai-code-review"]
     # Required parameters
     gerritUserName = {gerritUserName}
     ...
 
     # Optional parameters
-    gptModel = {gptModel}
-    gptSystemPrompt = {gptSystemPrompt}
+    aiModel = {aiModel}
+    aiSystemPrompt = {aiSystemPrompt}
     ...
 ```
 
 #### Secure Configuration
 
 Please ensure **strict control over the access permissions of `refs/meta/config`** since sensitive information such as
-`gptToken` is configured in the `project.config` file within `refs/meta/config`.
+`aiToken` is configured in the `project.config` file within `refs/meta/config`.
 
 ## Stateful and Stateless modes
 
@@ -151,24 +196,34 @@
 
 ### Optional Parameters
 
-- `gptMode`: Select whether requests are processed in Stateless or Stateful mode. For backward compatibility, the
+- `aiMode`: Select whether requests are processed in Stateless or Stateful mode. For backward compatibility, the
 default value is `stateless`. To enable Stateful mode, set this parameter to `stateful`.
-- `gptModel`: The default model is `gpt-4o`. You can also configure it to `gpt-3.5-turbo` or `gpt-4-turbo`.
-- `gptDomain`: The default ChatGPT domain is `https://api.openai.com`.
-- `gptSystemPrompt`: You can modify the default system prompt ("Act as a PatchSet Reviewer") to your preferred prompt.
-- `gptReviewTemperature`: Specifies the temperature setting for ChatGPT when reviewing a Patch Set, with a default
+- `aiModel`: The default model is `gpt-4o`. You can also configure it to `gpt-3.5-turbo` or `gpt-4-turbo`.
+- `aiDomain`: The default if not specified is the ChatGPT domain `https://api.openai.com`.
+This correlates with the `aiType` field which defaults to CHATGPT if not specified.
+- `aiSystemPrompt`: You can modify the default system prompt ("Act as a PatchSet Reviewer") to your preferred prompt.
+- `aiReviewTemperature`: Specifies the temperature setting for ChatGPT when reviewing a Patch Set, with a default
   setting of 0.2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more
   focused and deterministic.
-- `gptCommentTemperature`: Specifies the temperature setting for ChatGPT when replying to a comment, with a default
+- `aiCommentTemperature`: Specifies the temperature setting for ChatGPT when replying to a comment, with a default
   setting of 1.0.
-- `gptReviewPatchSet`: Set to true by default. When switched to false, it disables the automatic review of Patch Sets as
+- `aiReviewPatchSet`: Set to true by default. When switched to false, it disables the automatic review of Patch Sets as
   they are created or updated.
-- `gptReviewCommitMessages`: The default value is true. When enabled, this option also verifies if the commit message
+- `aiReviewCommitMessages`: The default value is true. When enabled, this option also verifies if the commit message
   matches with the content of the Change Set.
 - `gptFullFileReview`: Enabled by default. Activating this option sends both unchanged lines and changes to ChatGPT for
   review, offering additional context information. Deactivating it (set to false) results in only the changed lines
   being submitted for review.
-- `gptStreamOutput`: The default value is false. Whether the response is expected in stream output mode or not.
+- `aiStreamOutput`: The default value is false. Whether the response is expected in stream output mode or not.
+- `aiType`: Allows the selection of different ai chat services the current list is ChatGPT, Ollama, AzureOpenAI and Generic.
+    For compatibility the default is ChatGPT when not specified.  Note: Gemeric is used to allow the specification of new
+    uri endpoints, and different authorization headers to allow new service testing more quickly.
+  - `aiAuthHeaderName`: When using the GENERIC aiType, you can specify any authorization header, which can allow you to test
+non bearer token authorization e.g. api-key used for AZUREOpenAI.
+  - `aiChatEndpoint`: When using the GENERIC aiType, you can specify any endpoint you wish
+  to test a different ai service, or new API.  e.g. /api/someapi.  Although it is best
+  to ensure the API is compatible with the openAPI specification or additional response parsing will be
+  needed to correctly read the data into the new API data structures. 
 - `maxReviewLines`: The default value is 1000. This sets a limit on the number of lines of code included in the review.
 - `maxReviewFileSize`: Set with a default value of 10000, this parameter establishes a cap on the file size that can be
   included in reviews.
@@ -198,7 +253,7 @@
   specified below. Turning off this option (false) allows the display of comments ChatGPT marks as irrelevant.
 - `filterCommentsRelevanceThreshold`: When `filterRelevantComments` is enabled, any review comment assigned a relevance
   score by ChatGPT below this threshold will not be shown. The default threshold is set at 0.6.
-- `gptRelevanceRules`: This option allows customization of the rules ChatGPT uses to determine the relevance of a task.
+- `aiRelevanceRules`: This option allows customization of the rules ChatGPT uses to determine the relevance of a task.
 - `patchSetCommentsAsResolved`: Initially set to false, this option leaves ChatGPT's Patch Set comments as unresolved,
   inviting further discussion. If activated, it marks ChatGPT's Patch Set comments as resolved.
 - `inlineCommentsAsResolved`: Initially set to false, this option leaves ChatGPT's inline comments as unresolved,
@@ -274,7 +329,7 @@
 - `/configure --<CONFIG_KEY_1>=<CONFIG_VALUE_1> [... --<CONFIG_KEY_N>=<CONFIG_VALUE_N>]` assigns new values to one or
   more configuration keys.
 
-  **NOTE**: Values that include spaces, such as `gptSystemPrompt`, must be enclosed in double quotes.
+  **NOTE**: Values that include spaces, such as `aiSystemPrompt`, must be enclosed in double quotes.
 
 #### Command Options
 
diff --git a/gerrit.config b/gerrit.config
index 80787ac..93c3cac 100644
--- a/gerrit.config
+++ b/gerrit.config
@@ -1,6 +1,6 @@
-[plugin "chatgpt-code-review-gerrit-plugin"]
-	gptToken = <CHATGPT_API_TOKEN>
-	gptModel = gpt-4
-	gptStreamOutput = false
+[plugin "ai-code-review"]
+	aiToken = <CHATGPT_API_TOKEN>
+	aiModel = gpt-4
+	aiStreamOutput = false
 	gerritUserName = <GERRIT_USER_NAME>
 	globalEnable = true
diff --git a/pom.xml b/pom.xml
index 1febf56..a3bcf09 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,21 +5,17 @@
     <modelVersion>4.0.0</modelVersion>
 
     <groupId>com.googlesource.gerrit.plugins</groupId>
-    <artifactId>chatgpt-code-review-gerrit-plugin</artifactId>
+    <artifactId>ai-code-review</artifactId>
     <packaging>jar</packaging>
-    <version>3.0.0</version>
+    <version>4.0.0</version>
     <properties>
         <Gerrit-ApiType>plugin</Gerrit-ApiType>
-        <Gerrit-ApiVersion>3.10.0-rc3</Gerrit-ApiVersion>
+        <!-- Default the gerrit-api version to the lowest version that uses JDK17 by default, the same as this project.
+        because we can't run on JDK11, but equally we wish to support as many gerrit versions for this plugin as possible, this doesn't mean this wont run
+         on later versions, it just allows it to be backward compatible back to this min version ( unless we actually need to use a feature from a later API spec -->
+        <Gerrit-ApiVersion>3.7.9</Gerrit-ApiVersion>
         <maven.test.skip>false</maven.test.skip>
     </properties>
-    <distributionManagement>
-        <repository>
-            <id>github</id>
-            <name>GitHub Amarula Maven Packages</name>
-            <url>https://maven.pkg.github.com/amarula/chatgpt-code-review-gerrit-plugin</url>
-        </repository>
-    </distributionManagement>
     <build>
         <plugins>
             <plugin>
@@ -29,15 +25,13 @@
                 <configuration>
                     <archive>
                         <manifestEntries>
-                            <Gerrit-PluginName>chatgpt-code-review-gerrit-plugin</Gerrit-PluginName>
-                            <Gerrit-Module>com.googlesource.gerrit.plugins.chatgpt.Module</Gerrit-Module>
+                            <Gerrit-PluginName>ai-code-review</Gerrit-PluginName>
+                            <Gerrit-Module>com.googlesource.gerrit.plugins.aicodereview.Module</Gerrit-Module>
 
-                            <Implementation-Vendor>Amarula</Implementation-Vendor>
-                            <Implementation-URL>
-                                https://github.com/amarula/chatgpt-code-review-gerrit-plugin
-                            </Implementation-URL>
+                            <Implementation-Vendor>OpenSource Gerrit Plugin</Implementation-Vendor>
+                            <Implementation-URL>https://gerrit.googlesource.com/plugins/ai-code-review</Implementation-URL>
 
-                            <Implementation-Title>ChatGPT Code Review Gerrit Plugin</Implementation-Title>
+                            <Implementation-Title>AI Code Review Gerrit Plugin</Implementation-Title>
                             <Implementation-Version>${project.version}</Implementation-Version>
 
                             <Gerrit-ApiType>${Gerrit-ApiType}</Gerrit-ApiType>
@@ -84,11 +78,11 @@
                             <relocations>
                                 <relocation>
                                     <pattern>okhttp3</pattern>
-                                    <shadedPattern>com.googlesource.gerrit.plugins.chatgpt.okhttp3</shadedPattern>
+                                    <shadedPattern>com.googlesource.gerrit.plugins.aicodereview.okhttp3</shadedPattern>
                                 </relocation>
                                 <relocation>
                                     <pattern>okio</pattern>
-                                    <shadedPattern>com.googlesource.gerrit.plugins.chatgpt.okio</shadedPattern>
+                                    <shadedPattern>com.googlesource.gerrit.plugins.aicodereview.okio</shadedPattern>
                                 </relocation>
                             </relocations>
                             <filters>
@@ -107,11 +101,11 @@
                             <transformers>
                                 <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                     <manifestEntries>
-                                        <Gerrit-PluginName>chatgpt-code-review-gerrit-plugin</Gerrit-PluginName>
-                                        <Gerrit-Module>com.googlesource.gerrit.plugins.chatgpt.Module</Gerrit-Module>
-                                        <Implementation-Vendor>Amarula</Implementation-Vendor>
-                                        <Implementation-URL>https://github.com/amarula/chatgpt-code-review-gerrit-plugin</Implementation-URL>
-                                        <Implementation-Title>ChatGPT Code Review Gerrit Plugin</Implementation-Title>
+                                        <Gerrit-PluginName>ai-code-review</Gerrit-PluginName>
+                                        <Gerrit-Module>com.googlesource.gerrit.plugins.aicodereview.Module</Gerrit-Module>
+                                        <Implementation-Vendor>OpenSource Gerrit Plugin</Implementation-Vendor>
+                                        <Implementation-URL>https://gerrit.googlesource.com/plugins/ai-code-review</Implementation-URL>
+                                        <Implementation-Title>AI Code Review Gerrit Plugin</Implementation-Title>
                                         <Implementation-Version>${project.version}</Implementation-Version>
                                         <Gerrit-ApiType>${Gerrit-ApiType}</Gerrit-ApiType>
                                         <Gerrit-ApiVersion>${Gerrit-ApiVersion}</Gerrit-ApiVersion>
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/Module.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/Module.java
similarity index 76%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/Module.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/Module.java
index 39227f0..9a4f4f9 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/Module.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/Module.java
@@ -1,9 +1,9 @@
-package com.googlesource.gerrit.plugins.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview;
 
 import com.google.gerrit.server.events.EventListener;
 import com.google.inject.AbstractModule;
 import com.google.inject.multibindings.Multibinder;
-import com.googlesource.gerrit.plugins.chatgpt.listener.GerritListener;
+import com.googlesource.gerrit.plugins.aicodereview.listener.GerritListener;
 
 public class Module extends AbstractModule {
     @Override
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/PatchSetReviewer.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/PatchSetReviewer.java
similarity index 72%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/PatchSetReviewer.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/PatchSetReviewer.java
index 28b7040..7bcea8f 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/PatchSetReviewer.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/PatchSetReviewer.java
@@ -1,23 +1,23 @@
-package com.googlesource.gerrit.plugins.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview;
 
 import com.google.inject.Inject;
 import com.google.inject.Provider;
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.data.ChangeSetDataHandler;
-import com.googlesource.gerrit.plugins.chatgpt.interfaces.mode.common.client.api.chatgpt.IChatGptClient;
-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.client.api.gerrit.GerritClient;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritClientReview;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.messages.DebugCodeBlocksReview;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.patch.comment.GerritCommentRange;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptReplyItem;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptResponseContent;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritCodeRange;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritComment;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.review.ReviewBatch;
-import com.googlesource.gerrit.plugins.chatgpt.settings.Settings;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.data.ChangeSetDataHandler;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.common.client.api.openapi.ChatAIClient;
+import com.googlesource.gerrit.plugins.aicodereview.localization.Localizer;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritClient;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritClientReview;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.messages.DebugCodeBlocksReview;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.patch.comment.GerritCommentRange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatReplyItem;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatResponseContent;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritCodeRange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritComment;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.review.ReviewBatch;
+import com.googlesource.gerrit.plugins.aicodereview.settings.Settings;
 import lombok.Getter;
 import lombok.extern.slf4j.Slf4j;
 
@@ -33,7 +33,7 @@
     private final ChangeSetData changeSetData;
     private final Provider<GerritClientReview> clientReviewProvider;
     @Getter
-    private final IChatGptClient chatGptClient;
+    private final ChatAIClient chatGptClient;
     private final Localizer localizer;
     private final DebugCodeBlocksReview debugCodeBlocksReview;
 
@@ -48,7 +48,7 @@
             Configuration config,
             ChangeSetData changeSetData,
             Provider<GerritClientReview> clientReviewProvider,
-            IChatGptClient chatGptClient,
+            ChatAIClient chatGptClient,
             Localizer localizer
     ) {
         this.config = config;
@@ -66,14 +66,14 @@
         commentProperties = gerritClient.getClientData(change).getCommentProperties();
         gerritCommentRange = new GerritCommentRange(gerritClient, change);
         String patchSet = gerritClient.getPatchSet(change);
-        if (patchSet.isEmpty() && config.getGptMode() == Settings.Modes.stateless) {
+        if (patchSet.isEmpty() && config.getAIMode() == Settings.Modes.stateless) {
             log.info("No file to review has been found in the PatchSet");
             return;
         }
         ChangeSetDataHandler.update(config, change, gerritClient, changeSetData, localizer);
 
-        if (changeSetData.shouldRequestChatGptReview()) {
-            ChatGptResponseContent reviewReply = getReviewReply(change, patchSet);
+        if (changeSetData.shouldRequestAICodeReview()) {
+            AIChatResponseContent reviewReply = getReviewReply(change, patchSet);
             log.debug("ChatGPT response: {}", reviewReply);
 
             retrieveReviewBatches(reviewReply, change);
@@ -99,7 +99,7 @@
         }
     }
 
-    private void setPatchSetReviewBatchMap(ReviewBatch batchMap, ChatGptReplyItem replyItem) {
+    private void setPatchSetReviewBatchMap(ReviewBatch batchMap, AIChatReplyItem replyItem) {
         Optional<GerritCodeRange> optGerritCommentRange = gerritCommentRange.getGerritCommentRange(replyItem);
         if (optGerritCommentRange.isPresent()) {
             GerritCodeRange gerritCodeRange = optGerritCommentRange.get();
@@ -109,12 +109,12 @@
         }
     }
 
-    private void retrieveReviewBatches(ChatGptResponseContent reviewReply, GerritChange change) {
+    private void retrieveReviewBatches(AIChatResponseContent reviewReply, GerritChange change) {
         if (reviewReply.getMessageContent() != null && !reviewReply.getMessageContent().isEmpty()) {
             reviewBatches.add(new ReviewBatch(reviewReply.getMessageContent()));
             return;
         }
-        for (ChatGptReplyItem replyItem : reviewReply.getReplies()) {
+        for (AIChatReplyItem replyItem : reviewReply.getReplies()) {
             String reply = replyItem.getReply();
             Integer score = replyItem.getScore();
             boolean isNotNegative = isNotNegativeReply(score);
@@ -141,11 +141,11 @@
         }
     }
 
-    private ChatGptResponseContent getReviewReply(GerritChange change, String patchSet) throws Exception {
+    private AIChatResponseContent getReviewReply(GerritChange change, String patchSet) throws Exception {
         List<String> patchLines = Arrays.asList(patchSet.split("\n"));
         if (patchLines.size() > config.getMaxReviewLines()) {
             log.warn("Patch set too large. Skipping review. changeId: {}", change.getFullChangeId());
-            return new ChatGptResponseContent(String.format(SPLIT_REVIEW_MSG, config.getMaxReviewLines()));
+            return new AIChatResponseContent(String.format(SPLIT_REVIEW_MSG, config.getMaxReviewLines()));
         }
 
         return chatGptClient.ask(changeSetData, change, patchSet);
@@ -168,7 +168,7 @@
                 score >= config.getFilterCommentsBelowScore();
     }
 
-    private boolean isIrrelevantReply(ChatGptReplyItem replyItem) {
+    private boolean isIrrelevantReply(AIChatReplyItem replyItem) {
         return config.getFilterRelevantComments() &&
                 replyItem.getRelevance() != null &&
                 replyItem.getRelevance() < config.getFilterCommentsRelevanceThreshold();
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/config/ConfigCreator.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/config/ConfigCreator.java
similarity index 88%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/config/ConfigCreator.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/config/ConfigCreator.java
index 9cebdde..fc22c23 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/config/ConfigCreator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/config/ConfigCreator.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.config;
+package com.googlesource.gerrit.plugins.aicodereview.config;
 
 import com.google.gerrit.entities.Account;
 import com.google.gerrit.entities.Change;
@@ -13,7 +13,7 @@
 import com.google.gerrit.server.util.OneOffRequestContext;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandlerBaseProvider;
+import com.googlesource.gerrit.plugins.aicodereview.data.PluginDataHandlerBaseProvider;
 import lombok.NonNull;
 import lombok.extern.slf4j.Slf4j;
 import org.eclipse.jgit.lib.Config;
@@ -23,7 +23,7 @@
 import java.util.Optional;
 import java.util.Set;
 
-import static com.googlesource.gerrit.plugins.chatgpt.config.DynamicConfiguration.KEY_DYNAMIC_CONFIG;
+import static com.googlesource.gerrit.plugins.aicodereview.config.DynamicConfiguration.KEY_DYNAMIC_CONFIG;
 
 @Singleton
 @Slf4j
@@ -71,10 +71,10 @@
             log.info("DynamicConfig found for change '{}': {}", changeKey, dynamicConfig);
             projectConfig = updateDynamicConfig(projectConfig, pluginName, dynamicConfig);
         }
-        Optional<AccountState> gptAccount = getAccount(globalConfig);
-        String email = gptAccount.map(a -> a.account().preferredEmail()).orElse("");
+        Optional<AccountState> codeReviewAccount = getAccount(globalConfig);
+        String email = codeReviewAccount.map(a -> a.account().preferredEmail()).orElse("");
         Account.Id accountId =
-            gptAccount
+            codeReviewAccount
                 .map(a -> a.account().id())
                 .orElseThrow(
                     () ->
@@ -86,8 +86,8 @@
     }
 
     private Optional<AccountState> getAccount(PluginConfig globalConfig) {
-        String gptUser = globalConfig.getString(Configuration.KEY_GERRIT_USERNAME);
-        return accountCache.getByUsername(gptUser);
+        String codeReviewUser = globalConfig.getString(Configuration.KEY_GERRIT_USERNAME);
+        return accountCache.getByUsername(codeReviewUser);
     }
 
     private PluginConfig updateDynamicConfig(
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/config/Configuration.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/config/Configuration.java
similarity index 67%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/config/Configuration.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/config/Configuration.java
index 0a26d62..c79a24b 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/config/Configuration.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/config/Configuration.java
@@ -1,5 +1,7 @@
-package com.googlesource.gerrit.plugins.chatgpt.config;
+package com.googlesource.gerrit.plugins.aicodereview.config;
 
+import com.google.common.base.Strings;
+import com.google.common.net.HttpHeaders;
 import com.google.gerrit.entities.Account;
 import com.google.gerrit.extensions.api.GerritApi;
 import com.google.gerrit.server.config.PluginConfig;
@@ -8,11 +10,16 @@
 
 import lombok.Getter;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.http.NameValuePair;
+import org.apache.http.message.BasicNameValuePair;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.*;
 import java.util.regex.Pattern;
 
-import static com.googlesource.gerrit.plugins.chatgpt.settings.Settings.Modes;
+import static com.googlesource.gerrit.plugins.aicodereview.settings.Settings.Modes;
+import static com.googlesource.gerrit.plugins.aicodereview.settings.Settings.AIType;
+
 
 @Slf4j
 public class Configuration {
@@ -24,11 +31,13 @@
 
     // Default Config values
     public static final String OPENAI_DOMAIN = "https://api.openai.com";
-    public static final String DEFAULT_GPT_MODEL = "gpt-4o";
-    public static final double DEFAULT_GPT_REVIEW_TEMPERATURE = 0.2;
-    public static final double DEFAULT_GPT_COMMENT_TEMPERATURE = 1.0;
+    public static final String DEFAULT_CHATGPT_MODEL = "gpt-4o";
+    public static final String DEFAULT_OPENAI_MODEL = "qwen2.5-coder";
 
-    private static final String DEFAULT_GPT_MODE = "stateless";
+    public static final double DEFAULT_AI_CHAT_REVIEW_TEMPERATURE = 0.2;
+    public static final double DEFAULT_AI_CHAT_COMMENT_TEMPERATURE = 1.0;
+
+    private static final String DEFAULT_AI_MODE = "stateless";
     private static final boolean DEFAULT_REVIEW_PATCH_SET = true;
     private static final boolean DEFAULT_REVIEW_COMMIT_MESSAGES = true;
     private static final boolean DEFAULT_FULL_FILE_REVIEW = true;
@@ -82,26 +91,31 @@
     private static final boolean DEFAULT_INLINE_COMMENTS_AS_RESOLVED = false;
     private static final boolean DEFAULT_PATCH_SET_COMMENTS_AS_RESOLVED = false;
     private static final boolean DEFAULT_IGNORE_OUTDATED_INLINE_COMMENTS = false;
-    private static final boolean DEFAULT_IGNORE_RESOLVED_CHAT_GPT_COMMENTS = true;
+    private static final boolean DEFAULT_IGNORE_RESOLVED_AI_CHAT_COMMENTS = true;
     private static final boolean DEFAULT_FORCE_CREATE_ASSISTANT = false;
     private static final boolean DEFAULT_ENABLE_MESSAGE_DEBUGGING = false;
 
+    public static final String AUTH_HEADER_API_KEY = "api-key";
+
     // Config setting keys
-    public static final String KEY_GPT_SYSTEM_PROMPT = "gptSystemPrompt";
-    public static final String KEY_GPT_RELEVANCE_RULES = "gptRelevanceRules";
-    public static final String KEY_GPT_REVIEW_TEMPERATURE = "gptReviewTemperature";
-    public static final String KEY_GPT_COMMENT_TEMPERATURE = "gptCommentTemperature";
+    public static final String KEY_AI_SYSTEM_PROMPT = "aiSystemPrompt";
+    public static final String KEY_AI_RELEVANCE_RULES = "aiRelevanceRules";
+    public static final String KEY_AI_REVIEW_TEMPERATURE = "aiReviewTemperature";
+    public static final String KEY_AI_COMMENT_TEMPERATURE = "aiCommentTemperature";
     public static final String KEY_VOTING_MIN_SCORE = "votingMinScore";
     public static final String KEY_VOTING_MAX_SCORE = "votingMaxScore";
     public static final String KEY_GERRIT_USERNAME = "gerritUserName";
 
-    private static final String KEY_GPT_TOKEN = "gptToken";
-    private static final String KEY_GPT_DOMAIN = "gptDomain";
-    private static final String KEY_GPT_MODEL = "gptModel";
-    private static final String KEY_STREAM_OUTPUT = "gptStreamOutput";
-    private static final String KEY_GPT_MODE = "gptMode";
-    private static final String KEY_REVIEW_COMMIT_MESSAGES = "gptReviewCommitMessages";
-    private static final String KEY_REVIEW_PATCH_SET = "gptReviewPatchSet";
+    public static final String KEY_AI_TYPE = "aiType";
+    public static final String KEY_AI_TOKEN = "aiToken";
+    public static final String KEY_AI_DOMAIN = "aiDomain";
+    public static final String KEY_AI_CHAT_ENDPOINT = "aiChatEndpoint";
+    public static final String KEY_AI_AUTH_HEADER_NAME = "aiAuthHeaderName";
+    private static final String KEY_AI_MODEL = "aiModel";
+    public static final String KEY_STREAM_OUTPUT = "aiStreamOutput";
+    private static final String KEY_AI_MODE = "aiMode";
+    private static final String KEY_REVIEW_COMMIT_MESSAGES = "aiReviewCommitMessages";
+    private static final String KEY_REVIEW_PATCH_SET = "aiReviewPatchSet";
     private static final String KEY_FULL_FILE_REVIEW = "gptFullFileReview";
     private static final String KEY_PROJECT_ENABLE = "isEnabled";
     private static final String KEY_GLOBAL_ENABLE = "globalEnable";
@@ -123,7 +137,7 @@
     private static final String KEY_INLINE_COMMENTS_AS_RESOLVED = "inlineCommentsAsResolved";
     private static final String KEY_PATCH_SET_COMMENTS_AS_RESOLVED = "patchSetCommentsAsResolved";
     private static final String KEY_IGNORE_OUTDATED_INLINE_COMMENTS = "ignoreOutdatedInlineComments";
-    private static final String KEY_IGNORE_RESOLVED_CHAT_GPT_COMMENTS = "ignoreResolvedChatGptComments";
+    private static final String KEY_IGNORE_RESOLVED_AI_CHAT_COMMENTS = "ignoreResolvedChatGptComments";
     private static final String KEY_FORCE_CREATE_ASSISTANT = "forceCreateAssistant";
     private static final String KEY_ENABLE_MESSAGE_DEBUGGING = "enableMessageDebugging";
 
@@ -153,36 +167,64 @@
       return context.openAs(userId);
     }
 
-    public String getGptToken() {
-        return getValidatedOrThrow(KEY_GPT_TOKEN);
+    public String getAIToken() {
+        // The Aitoken isn't required for all aiTypes.
+
+        return getValidatedOrThrow(KEY_AI_TOKEN);
     }
 
     public String getGerritUserName() {
         return getValidatedOrThrow(KEY_GERRIT_USERNAME);
     }
 
-    public String getGptDomain() {
-        return getString(KEY_GPT_DOMAIN, OPENAI_DOMAIN);
+    public String getAIDomain() {
+        // AiDomain is not a required field UNLESS we are using OLLAMA which is a local / private based
+        // instance by its very nature. it makes more sense to enforce that it is a required field for when
+        // aiType==ollama.
+        String aiDomain = getAIType() == AIType.OLLAMA ?
+                getValidatedOrThrow(KEY_AI_DOMAIN) :
+                getString(KEY_AI_DOMAIN, OPENAI_DOMAIN);
+
+        // trim end slash, so putting endpoint urls together is easier.
+        return aiDomain.endsWith("/") ?
+                aiDomain.substring(0, aiDomain.length() - 1) : aiDomain;
     }
 
-    public String getGptModel() {
-        return getString(KEY_GPT_MODEL, DEFAULT_GPT_MODEL);
+    public String getAIModel() {
+        // default to the chatGPT model if nothing is specified, excecpt if we are using
+        // an openAI compliant service like OLLAMA, then we use its appropriate default.
+        return getString(KEY_AI_MODEL,
+                getAIType() == AIType.OLLAMA ? DEFAULT_OPENAI_MODEL : DEFAULT_CHATGPT_MODEL);
     }
 
-    public boolean getGptReviewPatchSet() {
+    public boolean getAIReviewPatchSet() {
         return getBoolean(KEY_REVIEW_PATCH_SET, DEFAULT_REVIEW_PATCH_SET);
     }
 
-    public Modes getGptMode() {
-        String mode = getString(KEY_GPT_MODE, DEFAULT_GPT_MODE);
-        try {
-            return Enum.valueOf(Modes.class, mode);
-        } catch (IllegalArgumentException e) {
-            throw new RuntimeException("Illegal mode: " + mode, e);
-        }
+    public Modes getAIMode() {
+        String mode = getString(KEY_AI_MODE, DEFAULT_AI_MODE);
+        return getValueAsEnum(Modes.class, mode);
+    }
+    public AIType getAIType(){
+        // return default type of CHATGPT if no value has been specified.
+        // Leaving the default behaviour of this plugin as it was historically.
+        String aiType = getString(KEY_AI_TYPE, "CHATGPT");
+        // for ease of use with enum, use toUpper, so we can always be case-sensitive on compares.
+        return getValueAsEnum( AIType.class, aiType.toUpperCase());
     }
 
-    public boolean getGptReviewCommitMessages() {
+    public String getChatEndpoint(){
+        // optional, and only used when combined with the "GENERIC" aiType, for testing
+        // of new or not yet supported ai frameworks.
+        return getString(KEY_AI_CHAT_ENDPOINT, "");
+    }
+    public String getAuthHeaderName(){
+        // optional, and only used when combined with the "GENERIC" aiType, for testing
+        // of new or not yet supported ai frameworks.
+        return getString(KEY_AI_AUTH_HEADER_NAME, "");
+    }
+
+    public boolean getAIReviewCommitMessages() {
         return getBoolean(KEY_REVIEW_COMMIT_MESSAGES, DEFAULT_REVIEW_COMMIT_MESSAGES);
     }
 
@@ -190,7 +232,7 @@
         return getBoolean(KEY_FULL_FILE_REVIEW, DEFAULT_FULL_FILE_REVIEW);
     }
 
-    public boolean getGptStreamOutput() {
+    public boolean getAIStreamOutput() {
         return getBoolean(KEY_STREAM_OUTPUT, DEFAULT_STREAM_OUTPUT);
     }
 
@@ -282,8 +324,8 @@
         return getBoolean(KEY_PATCH_SET_COMMENTS_AS_RESOLVED, DEFAULT_PATCH_SET_COMMENTS_AS_RESOLVED);
     }
 
-    public boolean getIgnoreResolvedChatGptComments() {
-        return getBoolean(KEY_IGNORE_RESOLVED_CHAT_GPT_COMMENTS, DEFAULT_IGNORE_RESOLVED_CHAT_GPT_COMMENTS);
+    public boolean getIgnoreResolvedAIChatComments() {
+        return getBoolean(KEY_IGNORE_RESOLVED_AI_CHAT_COMMENTS, DEFAULT_IGNORE_RESOLVED_AI_CHAT_COMMENTS);
     }
 
     public boolean getForceCreateAssistant() {
@@ -298,6 +340,26 @@
         return getBoolean(KEY_IGNORE_OUTDATED_INLINE_COMMENTS, DEFAULT_IGNORE_OUTDATED_INLINE_COMMENTS);
     }
 
+
+    public NameValuePair getAuthorizationHeaderInfo() {
+        switch (getAIType()) {
+            case AZUREOPENAI:
+                return new BasicNameValuePair(AUTH_HEADER_API_KEY, getAIToken());
+            case OLLAMA:
+            case GENERIC:
+                // by default no auth header is required for ollama so return null for no auth.
+                // But if they wish to add some auth requirements, maybe for hosted setup,
+                // then allow the header to be generically specified, same as the GENERIC configuration.
+                return !Strings.isNullOrEmpty(getAuthHeaderName()) ?
+                        new BasicNameValuePair(getAuthHeaderName(), getAIToken()) : null;
+            case CHATGPT:
+            default:
+                // by default, or for chatGpt use bearer token, if someone is adding a new aiType, it can fall
+                // into this block - or they will need to extend the cases above.
+                return new BasicNameValuePair(HttpHeaders.AUTHORIZATION, "Bearer " + getAIToken());
+        }
+    }
+
     public String getString(String key, String defaultValue) {
         String value = projectConfig.getString(key);
         if (value != null) {
@@ -340,6 +402,15 @@
         return Double.parseDouble(getString(key, String.valueOf(defaultValue)));
     }
 
+    @NotNull
+    private static <T extends Enum<T>> T getValueAsEnum(Class<T> enumClass, String value) {
+        try {
+            return Enum.valueOf(enumClass, value);
+        } catch (IllegalArgumentException e) {
+            throw new RuntimeException(String.format("Illegal value: %s for enum class: %s", value, enumClass), e);
+        }
+    }
+
     private List<String> splitConfig(String value) {
         Pattern separator=Pattern.compile("\\s*,\\s*");
         return Arrays.asList(separator.split(value));
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/config/DynamicConfiguration.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/config/DynamicConfiguration.java
similarity index 87%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/config/DynamicConfiguration.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/config/DynamicConfiguration.java
index 6062c90..398da82 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/config/DynamicConfiguration.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/config/DynamicConfiguration.java
@@ -1,7 +1,7 @@
-package com.googlesource.gerrit.plugins.chatgpt.config;
+package com.googlesource.gerrit.plugins.aicodereview.config;
 
-import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandler;
-import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandlerProvider;
+import com.googlesource.gerrit.plugins.aicodereview.data.PluginDataHandler;
+import com.googlesource.gerrit.plugins.aicodereview.data.PluginDataHandlerProvider;
 import lombok.Getter;
 import lombok.extern.slf4j.Slf4j;
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/data/ChangeSetDataHandler.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/data/ChangeSetDataHandler.java
similarity index 63%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/data/ChangeSetDataHandler.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/data/ChangeSetDataHandler.java
index 8cf9875..af6bb68 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/data/ChangeSetDataHandler.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/data/ChangeSetDataHandler.java
@@ -1,13 +1,13 @@
-package com.googlesource.gerrit.plugins.chatgpt.data;
+package com.googlesource.gerrit.plugins.aicodereview.data;
 
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-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.client.api.gerrit.GerritClient;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.prompt.ChatGptDataPrompt;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritPermittedVotingRange;
-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.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.localization.Localizer;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritClient;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.prompt.AIChatDataPrompt;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritPermittedVotingRange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.GerritClientData;
 import lombok.extern.slf4j.Slf4j;
 
 import java.util.HashSet;
@@ -22,7 +22,7 @@
             Localizer localizer
     ) {
         GerritClientData gerritClientData = gerritClient.getClientData(change);
-        ChatGptDataPrompt chatGptDataPrompt = new ChatGptDataPrompt(
+        AIChatDataPrompt AIChatDataPrompt = new AIChatDataPrompt(
                 config,
                 changeSetData,
                 change,
@@ -32,7 +32,7 @@
         changeSetData.setCommentPropertiesSize(gerritClientData.getCommentProperties().size());
         changeSetData.setDirectives(new HashSet<>());
         changeSetData.setReviewSystemMessage(null);
-        changeSetData.setGptDataPrompt(chatGptDataPrompt.buildPrompt());
+        changeSetData.setReviewAIDataPrompt(AIChatDataPrompt.buildPrompt());
         if (config.isVotingEnabled() && !change.getIsCommentEvent()) {
             GerritPermittedVotingRange permittedVotingRange = gerritClient.getPermittedVotingRange(change);
             if (permittedVotingRange != null) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/data/ChangeSetDataProvider.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/data/ChangeSetDataProvider.java
similarity index 74%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/data/ChangeSetDataProvider.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/data/ChangeSetDataProvider.java
index 6f3ac7c..616aec4 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/data/ChangeSetDataProvider.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/data/ChangeSetDataProvider.java
@@ -1,10 +1,10 @@
-package com.googlesource.gerrit.plugins.chatgpt.data;
+package com.googlesource.gerrit.plugins.aicodereview.data;
 
 import com.google.gerrit.server.account.AccountCache;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
 
 public class ChangeSetDataProvider implements Provider<ChangeSetData> {
     private final int gptAccountId;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/data/PluginDataHandler.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/data/PluginDataHandler.java
similarity index 94%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/data/PluginDataHandler.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/data/PluginDataHandler.java
index cf390e4..59e6474 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/data/PluginDataHandler.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/data/PluginDataHandler.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.data;
+package com.googlesource.gerrit.plugins.aicodereview.data;
 
 import com.google.gson.reflect.TypeToken;
 import com.google.inject.Inject;
@@ -11,7 +11,7 @@
 import java.util.Map;
 import java.util.Properties;
 
-import static com.googlesource.gerrit.plugins.chatgpt.utils.GsonUtils.getGson;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.GsonUtils.getGson;
 
 @Singleton
 public class PluginDataHandler {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/data/PluginDataHandlerBaseProvider.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/data/PluginDataHandlerBaseProvider.java
similarity index 93%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/data/PluginDataHandlerBaseProvider.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/data/PluginDataHandlerBaseProvider.java
index 15344a9..7d4ca18 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/data/PluginDataHandlerBaseProvider.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/data/PluginDataHandlerBaseProvider.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.data;
+package com.googlesource.gerrit.plugins.aicodereview.data;
 
 import com.google.inject.Inject;
 import com.google.inject.Provider;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/data/PluginDataHandlerProvider.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/data/PluginDataHandlerProvider.java
similarity index 83%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/data/PluginDataHandlerProvider.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/data/PluginDataHandlerProvider.java
index a21c74b..7c7d855 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/data/PluginDataHandlerProvider.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/data/PluginDataHandlerProvider.java
@@ -1,13 +1,13 @@
-package com.googlesource.gerrit.plugins.chatgpt.data;
+package com.googlesource.gerrit.plugins.aicodereview.data;
 
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
 
 import java.nio.file.Path;
 
-import static com.googlesource.gerrit.plugins.chatgpt.utils.FileUtils.sanitizeFilename;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.FileUtils.sanitizeFilename;
 
 @Singleton
 public class PluginDataHandlerProvider extends PluginDataHandlerBaseProvider implements Provider<PluginDataHandler> {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/interfaces/listener/IEventHandlerType.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/interfaces/listener/IEventHandlerType.java
similarity index 73%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/interfaces/listener/IEventHandlerType.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/interfaces/listener/IEventHandlerType.java
index 829900f..dac591c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/interfaces/listener/IEventHandlerType.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/interfaces/listener/IEventHandlerType.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.interfaces.listener;
+package com.googlesource.gerrit.plugins.aicodereview.interfaces.listener;
 
 public interface IEventHandlerType {
     enum PreprocessResult {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/interfaces/mode/common/client/api/gerrit/GerritClientPatchSet.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/interfaces/mode/common/client/api/gerrit/GerritClientPatchSet.java
new file mode 100644
index 0000000..d265c97
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/interfaces/mode/common/client/api/gerrit/GerritClientPatchSet.java
@@ -0,0 +1,17 @@
+package com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.common.client.api.gerrit;
+
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.patch.diff.FileDiffProcessed;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+
+import java.util.HashMap;
+
+public interface GerritClientPatchSet {
+    String getPatchSet(ChangeSetData changeSetData, GerritChange gerritChange) throws Exception;
+    boolean isDisabledUser(String authorUsername);
+    boolean isDisabledTopic(String topic);
+    void retrieveRevisionBase(GerritChange change);
+    Integer getNotNullAccountId(String authorUsername);
+    HashMap<String, FileDiffProcessed> getFileDiffsProcessed();
+    Integer getRevisionBase();
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/interfaces/mode/common/client/api/openapi/ChatAIClient.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/interfaces/mode/common/client/api/openapi/ChatAIClient.java
new file mode 100644
index 0000000..e70b2d3
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/interfaces/mode/common/client/api/openapi/ChatAIClient.java
@@ -0,0 +1,11 @@
+package com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.common.client.api.openapi;
+
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatResponseContent;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+
+public interface ChatAIClient {
+    AIChatResponseContent ask(ChangeSetData changeSetData, GerritChange change, String patchSet)
+            throws Exception;
+    String getRequestBody();
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/interfaces/mode/common/client/prompt/ChatAIDataPrompt.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/interfaces/mode/common/client/prompt/ChatAIDataPrompt.java
new file mode 100644
index 0000000..0869ad9
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/interfaces/mode/common/client/prompt/ChatAIDataPrompt.java
@@ -0,0 +1,12 @@
+package com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.common.client.prompt;
+
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatMessageItem;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritComment;
+
+import java.util.List;
+
+public interface ChatAIDataPrompt {
+    void addMessageItem(int i);
+    List<GerritComment> getCommentProperties();
+    List<AIChatMessageItem> getMessageItems();
+}
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/aicodereview/interfaces/mode/stateful/client/prompt/ChatGptPromptStateful.java
similarity index 63%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/interfaces/mode/stateful/client/prompt/IChatGptPromptStateful.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/interfaces/mode/stateful/client/prompt/ChatGptPromptStateful.java
index 76820d9..087a9e9 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/interfaces/mode/stateful/client/prompt/IChatGptPromptStateful.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/interfaces/mode/stateful/client/prompt/ChatGptPromptStateful.java
@@ -1,12 +1,12 @@
-package com.googlesource.gerrit.plugins.chatgpt.interfaces.mode.stateful.client.prompt;
+package com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.stateful.client.prompt;
 
 import java.util.List;
 
-public interface IChatGptPromptStateful {
+public interface ChatGptPromptStateful {
     void addGptAssistantInstructions(List<String> instructions);
     String getDefaultGptAssistantDescription();
     String getDefaultGptAssistantInstructions();
     String getDefaultGptThreadReviewMessage(String patchSet);
-    String getGptRequestDataPrompt();
+    String getAIRequestDataPrompt();
     void setCommentEvent(boolean isCommentEvent);
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerExecutor.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/listener/EventHandlerExecutor.java
similarity index 90%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerExecutor.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/listener/EventHandlerExecutor.java
index 4cce7cd..2d0cf62 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerExecutor.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/listener/EventHandlerExecutor.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.listener;
+package com.googlesource.gerrit.plugins.aicodereview.listener;
 
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.server.config.PluginConfigFactory;
@@ -7,7 +7,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import com.google.inject.Injector;
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
 import lombok.extern.slf4j.Slf4j;
 
 import java.util.concurrent.ScheduledExecutorService;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTask.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/listener/EventHandlerTask.java
similarity index 87%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTask.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/listener/EventHandlerTask.java
index 2faacfb..2e5931e 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTask.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/listener/EventHandlerTask.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.listener;
+package com.googlesource.gerrit.plugins.aicodereview.listener;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Splitter;
@@ -7,14 +7,14 @@
 import com.google.gerrit.server.events.CommentAddedEvent;
 import com.google.gerrit.server.events.PatchSetCreatedEvent;
 import com.google.inject.Inject;
-import com.googlesource.gerrit.plugins.chatgpt.PatchSetReviewer;
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandlerProvider;
-import com.googlesource.gerrit.plugins.chatgpt.interfaces.listener.IEventHandlerType;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritClient;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.git.GitRepoFiles;
+import com.googlesource.gerrit.plugins.aicodereview.PatchSetReviewer;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.data.PluginDataHandlerProvider;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.listener.IEventHandlerType;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritClient;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.git.GitRepoFiles;
 import lombok.extern.slf4j.Slf4j;
 
 import java.util.List;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/listener/EventHandlerTypeChangeMerged.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/listener/EventHandlerTypeChangeMerged.java
new file mode 100644
index 0000000..1e4af18
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/listener/EventHandlerTypeChangeMerged.java
@@ -0,0 +1,53 @@
+package com.googlesource.gerrit.plugins.aicodereview.listener;
+
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.data.PluginDataHandlerProvider;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.listener.IEventHandlerType;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.chatgpt.ChatGptAssistant;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.git.GitRepoFiles;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class EventHandlerTypeChangeMerged implements IEventHandlerType {
+    private final Configuration config;
+    private final ChangeSetData changeSetData;
+    private final GerritChange change;
+    private final GitRepoFiles gitRepoFiles;
+    private final PluginDataHandlerProvider pluginDataHandlerProvider;
+
+    EventHandlerTypeChangeMerged(
+            Configuration config,
+            ChangeSetData changeSetData,
+            GerritChange change,
+            GitRepoFiles gitRepoFiles,
+            PluginDataHandlerProvider pluginDataHandlerProvider
+    ) {
+        this.config = config;
+        this.changeSetData = changeSetData;
+        this.change = change;
+        this.gitRepoFiles = gitRepoFiles;
+        this.pluginDataHandlerProvider = pluginDataHandlerProvider;
+    }
+
+    @Override
+    public PreprocessResult preprocessEvent() {
+        return PreprocessResult.OK;
+    }
+
+    @Override
+    public void processEvent() {
+        // TODO: Should we be firing assistant based stateful request items when the aiMode is stateless?
+        // This is extra paid for requests which aren't required if using GPT.
+        ChatGptAssistant chatGptAssistant = new ChatGptAssistant(
+                config,
+                changeSetData,
+                change,
+                gitRepoFiles,
+                pluginDataHandlerProvider
+        );
+        chatGptAssistant.flushAssistantIds();
+        chatGptAssistant.createVectorStore();
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTypeCommentAdded.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/listener/EventHandlerTypeCommentAdded.java
similarity index 70%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTypeCommentAdded.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/listener/EventHandlerTypeCommentAdded.java
index ec730b7..6d25df4 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTypeCommentAdded.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/listener/EventHandlerTypeCommentAdded.java
@@ -1,10 +1,10 @@
-package com.googlesource.gerrit.plugins.chatgpt.listener;
+package com.googlesource.gerrit.plugins.aicodereview.listener;
 
-import com.googlesource.gerrit.plugins.chatgpt.PatchSetReviewer;
-import com.googlesource.gerrit.plugins.chatgpt.interfaces.listener.IEventHandlerType;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritClient;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.PatchSetReviewer;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.listener.IEventHandlerType;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritClient;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
 import lombok.extern.slf4j.Slf4j;
 
 @Slf4j
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTypePatchSetReview.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/listener/EventHandlerTypePatchSetReview.java
similarity index 81%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTypePatchSetReview.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/listener/EventHandlerTypePatchSetReview.java
index d372f9e..d1ecbd4 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTypePatchSetReview.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/listener/EventHandlerTypePatchSetReview.java
@@ -1,13 +1,13 @@
-package com.googlesource.gerrit.plugins.chatgpt.listener;
+package com.googlesource.gerrit.plugins.aicodereview.listener;
 
 import com.google.gerrit.extensions.client.ChangeKind;
 import com.google.gerrit.server.data.PatchSetAttribute;
-import com.googlesource.gerrit.plugins.chatgpt.PatchSetReviewer;
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.interfaces.listener.IEventHandlerType;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritClient;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.PatchSetReviewer;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.listener.IEventHandlerType;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritClient;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
 import lombok.extern.slf4j.Slf4j;
 
 import java.util.Optional;
@@ -53,7 +53,7 @@
     }
 
     private boolean isPatchSetReviewEnabled(GerritChange change) {
-        if (!config.getGptReviewPatchSet()) {
+        if (!config.getAIReviewPatchSet()) {
             log.debug("Disabled review function for created or updated PatchSets.");
             return false;
         }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/listener/GerritEventContextModule.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/listener/GerritEventContextModule.java
new file mode 100644
index 0000000..423a09f
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/listener/GerritEventContextModule.java
@@ -0,0 +1,54 @@
+package com.googlesource.gerrit.plugins.aicodereview.listener;
+
+import com.google.gerrit.extensions.config.FactoryModule;
+import com.google.gerrit.server.events.Event;
+import com.google.inject.Singleton;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.data.ChangeSetDataProvider;
+import com.googlesource.gerrit.plugins.aicodereview.data.PluginDataHandler;
+import com.googlesource.gerrit.plugins.aicodereview.data.PluginDataHandlerProvider;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.common.client.api.openapi.ChatAIClient;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.common.client.api.gerrit.GerritClientPatchSet;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.chatai.AIChatClientStateful;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.gerrit.GerritClientPatchSetStateful;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateless.client.api.chatai.AIChatClientStateless;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateless.client.api.gerrit.GerritClientPatchSetStateless;
+
+import static com.google.inject.Scopes.SINGLETON;
+
+public class GerritEventContextModule extends FactoryModule {
+    private final Event event;
+    private final Configuration config;
+
+    public GerritEventContextModule(Configuration config, Event event) {
+        this.event = event;
+        this.config = config;
+    }
+
+    @Override
+    protected void configure() {
+        bind(ChatAIClient.class).to(getChatAIMode());
+        bind(GerritClientPatchSet.class).to(getClientPatchSet());
+
+        bind(Configuration.class).toInstance(config);
+        bind(GerritChange.class).toInstance(new GerritChange(event));
+        bind(ChangeSetData.class).toProvider(ChangeSetDataProvider.class).in(SINGLETON);
+        bind(PluginDataHandler.class).toProvider(PluginDataHandlerProvider.class).in(Singleton.class);
+    }
+
+    private Class<? extends ChatAIClient> getChatAIMode() {
+        return switch (config.getAIMode()){
+            case stateful -> AIChatClientStateful.class;
+            case stateless -> AIChatClientStateless.class;
+        };
+    }
+
+    private Class<? extends GerritClientPatchSet> getClientPatchSet() {
+        return switch (config.getAIMode()){
+            case stateful -> GerritClientPatchSetStateful.class;
+            case stateless -> GerritClientPatchSetStateless.class;
+        };
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/GerritListener.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/listener/GerritListener.java
similarity index 85%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/GerritListener.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/listener/GerritListener.java
index 82d4cbd..0bf3e21 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/GerritListener.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/listener/GerritListener.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.listener;
+package com.googlesource.gerrit.plugins.aicodereview.listener;
 
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.entities.Change;
@@ -7,13 +7,13 @@
 import com.google.gerrit.server.events.*;
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.inject.Inject;
-import com.googlesource.gerrit.plugins.chatgpt.config.ConfigCreator;
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.config.ConfigCreator;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
 import lombok.extern.slf4j.Slf4j;
 
 import java.util.Objects;
 
-import static com.googlesource.gerrit.plugins.chatgpt.listener.EventHandlerTask.EVENT_CLASS_MAP;
+import static com.googlesource.gerrit.plugins.aicodereview.listener.EventHandlerTask.EVENT_CLASS_MAP;
 
 @Slf4j
 public class GerritListener implements EventListener {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/localization/Localizer.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/localization/Localizer.java
similarity index 76%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/localization/Localizer.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/localization/Localizer.java
index dcf068b..6786836 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/localization/Localizer.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/localization/Localizer.java
@@ -1,7 +1,7 @@
-package com.googlesource.gerrit.plugins.chatgpt.localization;
+package com.googlesource.gerrit.plugins.aicodereview.localization;
 
 import com.google.inject.Inject;
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
 import lombok.extern.slf4j.Slf4j;
 
 import java.util.ResourceBundle;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/ClientBase.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/ClientBase.java
new file mode 100644
index 0000000..479be40
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/ClientBase.java
@@ -0,0 +1,11 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client;
+
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+
+public abstract class ClientBase {
+    protected Configuration config;
+
+    public ClientBase(Configuration config) {
+        this.config = config;
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritChange.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritChange.java
similarity index 96%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritChange.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritChange.java
index ab18d97..803c069 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritChange.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritChange.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit;
 
 import com.google.gerrit.entities.BranchNameKey;
 import com.google.gerrit.entities.Change;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClient.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritClient.java
similarity index 82%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClient.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritClient.java
index e5b8548..b2fda14 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClient.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritClient.java
@@ -1,10 +1,10 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit;
 
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.patch.diff.FileDiffProcessed;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritPermittedVotingRange;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.GerritClientData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.patch.diff.FileDiffProcessed;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritPermittedVotingRange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.GerritClientData;
 import lombok.extern.slf4j.Slf4j;
 
 import java.util.HashMap;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientAccount.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritClientAccount.java
similarity index 95%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientAccount.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritClientAccount.java
index 01dab3b..25532c4 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientAccount.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritClientAccount.java
@@ -1,9 +1,9 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit;
 
 import com.google.gerrit.extensions.common.GroupInfo;
 import com.google.gerrit.server.account.AccountCache;
 import com.google.gerrit.server.util.ManualRequestContext;
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
 import lombok.extern.slf4j.Slf4j;
 
 import static java.util.stream.Collectors.toList;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritClientBase.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritClientBase.java
new file mode 100644
index 0000000..0c5ed8e
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritClientBase.java
@@ -0,0 +1,20 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit;
+
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.ClientBase;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.patch.diff.FileDiffProcessed;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.HashMap;
+
+
+@Slf4j
+public abstract class GerritClientBase extends ClientBase {
+    @Getter
+    protected HashMap<String, FileDiffProcessed> fileDiffsProcessed = new HashMap<>();
+
+    public GerritClientBase(Configuration config) {
+        super(config);
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientComments.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritClientComments.java
similarity index 86%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientComments.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritClientComments.java
index 1aa9c70..3c65805 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientComments.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritClientComments.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.gerrit.extensions.common.CommentInfo;
@@ -6,14 +6,14 @@
 import com.google.gerrit.server.events.CommentAddedEvent;
 import com.google.gerrit.server.util.ManualRequestContext;
 import com.google.inject.Inject;
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandlerProvider;
-import com.googlesource.gerrit.plugins.chatgpt.localization.Localizer;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.messages.ClientMessage;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritCodeRange;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritComment;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.CommentData;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.data.PluginDataHandlerProvider;
+import com.googlesource.gerrit.plugins.aicodereview.localization.Localizer;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.messages.ClientMessage;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritCodeRange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritComment;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.CommentData;
 import lombok.Getter;
 import lombok.extern.slf4j.Slf4j;
 
@@ -21,10 +21,10 @@
 
 import java.util.*;
 
-import static com.googlesource.gerrit.plugins.chatgpt.utils.TimeUtils.getTimeStamp;
-import static com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritClientDetail.toAuthor;
-import static com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritClientDetail.toDateString;
-import static com.googlesource.gerrit.plugins.chatgpt.settings.Settings.GERRIT_PATCH_SET_FILENAME;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.TimeUtils.getTimeStamp;
+import static com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritClientDetail.toAuthor;
+import static com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritClientDetail.toDateString;
+import static com.googlesource.gerrit.plugins.aicodereview.settings.Settings.GERRIT_PATCH_SET_FILENAME;
 
 @Slf4j
 public class GerritClientComments extends GerritClientAccount {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientDetail.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritClientDetail.java
similarity index 89%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientDetail.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritClientDetail.java
index 7bda0e3..7d2630a 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientDetail.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritClientDetail.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit;
 
 import com.google.gerrit.entities.LabelId;
 import com.google.gerrit.extensions.common.AccountInfo;
@@ -7,11 +7,11 @@
 import com.google.gerrit.extensions.common.ChangeMessageInfo;
 import com.google.gerrit.extensions.common.LabelInfo;
 import com.google.gerrit.server.util.ManualRequestContext;
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritComment;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritPatchSetDetail;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritPermittedVotingRange;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritComment;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritPatchSetDetail;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritPermittedVotingRange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
 import lombok.extern.slf4j.Slf4j;
 
 import static java.util.Collections.emptyList;
@@ -53,12 +53,12 @@
         loadPatchSetDetail(change);
         List<GerritPatchSetDetail.Permission> permissions = gerritPatchSetDetail.getLabels().getCodeReview().getAll();
         if (permissions == null) {
-            log.debug("No limitations on the ChatGPT voting range were detected");
+            log.debug("No limitations on the AICodeReview voting range were detected");
             return null;
         }
         for (GerritPatchSetDetail.Permission permission : permissions) {
             if (permission.getAccountId() == gptAccountId) {
-                log.debug("PatchSet voting range detected for ChatGPT user: {}", permission.getPermittedVotingRange());
+                log.debug("PatchSet voting range detected for AICodeReview user: {}", permission.getPermittedVotingRange());
                 return permission.getPermittedVotingRange();
             }
         }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientFacade.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritClientFacade.java
similarity index 75%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientFacade.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritClientFacade.java
index 651cc22..0278794 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientFacade.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritClientFacade.java
@@ -1,13 +1,13 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.inject.Inject;
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.interfaces.mode.common.client.api.gerrit.IGerritClientPatchSet;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.patch.diff.FileDiffProcessed;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritPermittedVotingRange;
-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.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.common.client.api.gerrit.GerritClientPatchSet;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.patch.diff.FileDiffProcessed;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritPermittedVotingRange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.GerritClientData;
 import lombok.extern.slf4j.Slf4j;
 
 import java.util.HashMap;
@@ -17,7 +17,7 @@
     private final ChangeSetData changeSetData;
     private final GerritClientDetail gerritClientDetail;
     private final GerritClientComments gerritClientComments;
-    private final IGerritClientPatchSet gerritClientPatchSet;
+    private final GerritClientPatchSet gerritClientPatchSet;
 
     @VisibleForTesting
     @Inject
@@ -25,7 +25,7 @@
             Configuration config,
             ChangeSetData changeSetData,
             GerritClientComments gerritClientComments,
-            IGerritClientPatchSet gerritClientPatchSet) {
+            GerritClientPatchSet gerritClientPatchSet) {
         gerritClientDetail = new GerritClientDetail(config, changeSetData);
         this.gerritClientPatchSet = gerritClientPatchSet;
         this.changeSetData = changeSetData;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientPatchSet.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritClientPatchSet.java
similarity index 86%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientPatchSet.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritClientPatchSet.java
index 9ff6046..2450da0 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientPatchSet.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritClientPatchSet.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -9,17 +9,17 @@
 import com.google.gerrit.extensions.common.DiffInfo;
 import com.google.gerrit.server.account.AccountCache;
 import com.google.gerrit.server.util.ManualRequestContext;
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.patch.diff.FileDiffProcessed;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritFileDiff;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritPatchSetFileDiff;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritReviewFileDiff;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.patch.diff.FileDiffProcessed;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritFileDiff;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritPatchSetFileDiff;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritReviewFileDiff;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
 import lombok.Getter;
 import lombok.extern.slf4j.Slf4j;
 
-import static com.googlesource.gerrit.plugins.chatgpt.utils.FileUtils.matchesExtensionList;
-import static com.googlesource.gerrit.plugins.chatgpt.utils.GsonUtils.getNoEscapedGson;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.FileUtils.matchesExtensionList;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.GsonUtils.getNoEscapedGson;
 import static java.util.stream.Collectors.toList;
 
 @Slf4j
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientReview.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritClientReview.java
similarity index 85%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientReview.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritClientReview.java
index 46af398..60e5c99 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientReview.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/gerrit/GerritClientReview.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Strings;
@@ -10,13 +10,13 @@
 import com.google.gerrit.server.account.AccountCache;
 import com.google.gerrit.server.util.ManualRequestContext;
 import com.google.inject.Inject;
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.config.DynamicConfiguration;
-import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandlerProvider;
-import com.googlesource.gerrit.plugins.chatgpt.localization.Localizer;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.messages.DebugCodeBlocksDynamicSettings;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.review.ReviewBatch;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.config.DynamicConfiguration;
+import com.googlesource.gerrit.plugins.aicodereview.data.PluginDataHandlerProvider;
+import com.googlesource.gerrit.plugins.aicodereview.localization.Localizer;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.messages.DebugCodeBlocksDynamicSettings;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.review.ReviewBatch;
 import lombok.extern.slf4j.Slf4j;
 
 import java.util.ArrayList;
@@ -25,8 +25,8 @@
 import java.util.Map;
 import java.util.Optional;
 
-import static com.googlesource.gerrit.plugins.chatgpt.mode.common.client.prompt.MessageSanitizer.sanitizeChatGptMessage;
-import static com.googlesource.gerrit.plugins.chatgpt.utils.TextUtils.joinWithDoubleNewLine;
+import static com.googlesource.gerrit.plugins.aicodereview.mode.common.client.prompt.MessageSanitizer.sanitizeAIChatMessage;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.TextUtils.joinWithDoubleNewLine;
 
 @Slf4j
 public class GerritClientReview extends GerritClientAccount {
@@ -90,7 +90,7 @@
         if (changeSetData.getReviewSystemMessage() != null) {
             systemMessage = changeSetData.getReviewSystemMessage();
         }
-        else if (!changeSetData.shouldHideChatGptReview()) {
+        else if (!changeSetData.shouldHideAICodeReview()) {
             comments = getReviewComments(reviewBatches);
             if (reviewScore != null) {
                 reviewInput.label(LabelId.CODE_REVIEW, reviewScore);
@@ -120,7 +120,7 @@
     private Map<String, List<CommentInput>> getReviewComments(List<ReviewBatch> reviewBatches) {
         Map<String, List<CommentInput>> comments = new HashMap<>();
         for (ReviewBatch reviewBatch : reviewBatches) {
-            String message = sanitizeChatGptMessage(reviewBatch.getContent());
+            String message = sanitizeAIChatMessage(reviewBatch.getContent());
             if (message.trim().isEmpty()) {
                 log.info("Empty message from review not submitted.");
                 continue;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/openai/AIChatClient.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/openai/AIChatClient.java
new file mode 100644
index 0000000..d4540cd
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/openai/AIChatClient.java
@@ -0,0 +1,102 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.openai;
+
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.ClientBase;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.*;
+
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.BufferedReader;
+import java.io.StringReader;
+import java.util.List;
+import java.util.Optional;
+
+import static com.googlesource.gerrit.plugins.aicodereview.utils.GsonUtils.getGson;
+
+@Slf4j
+abstract public class AIChatClient extends ClientBase {
+    protected boolean isCommentEvent = false;
+    @Getter
+    protected String requestBody;
+
+    public AIChatClient(Configuration config) {
+        super(config);
+    }
+
+    protected AIChatResponseContent extractContent(Configuration config, String body) throws Exception {
+        if (config.getAIStreamOutput() && !isCommentEvent) {
+            StringBuilder finalContent = new StringBuilder();
+            try (BufferedReader reader = new BufferedReader(new StringReader(body))) {
+                String line;
+                while ((line = reader.readLine()) != null) {
+                    extractContentFromLine(line).ifPresent(finalContent::append);
+                }
+            }
+            return convertResponseContentFromJson(finalContent.toString());
+        }
+        else {
+            AIChatResponseUnstreamed AIChatResponseUnstreamed =
+                    getGson().fromJson(body, AIChatResponseUnstreamed.class);
+            return getResponseContent(AIChatResponseUnstreamed.getChoices().get(0).getMessage().getToolCalls());
+        }
+    }
+
+    protected boolean validateResponse(AIChatResponseContent AIChatResponseContent, String changeId, int attemptInd) {
+        String returnedChangeId = AIChatResponseContent.getChangeId();
+        // A response is considered valid if either no changeId is returned or the changeId returned matches the one
+        // provided in the request
+        boolean isValidated = returnedChangeId == null || changeId.equals(returnedChangeId);
+        if (!isValidated) {
+            log.error("ChangedId mismatch error (attempt #{}).\nExpected value: {}\nReturned value: {}", attemptInd,
+                    changeId, returnedChangeId);
+        }
+        return isValidated;
+    }
+
+    protected AIChatResponseContent getResponseContent(List<AIChatToolCall> toolCalls) {
+        if (toolCalls.size() > 1) {
+            return mergeToolCalls(toolCalls);
+        } else {
+            return getArgumentAsResponse(toolCalls, 0);
+        }
+    }
+
+    protected Optional<String> extractContentFromLine(String line) {
+        String dataPrefix = "data: {\"id\"";
+
+        if (!line.startsWith(dataPrefix)) {
+            return Optional.empty();
+        }
+        AIChatResponseStreamed AIChatResponseStreamed =
+                getGson().fromJson(line.substring("data: ".length()), AIChatResponseStreamed.class);
+        AIChatResponseMessage delta = AIChatResponseStreamed.getChoices().get(0).getDelta();
+        if (delta == null || delta.getToolCalls() == null) {
+            return Optional.empty();
+        }
+        String content = getArgumentAsString(delta.getToolCalls(), 0);
+        return Optional.ofNullable(content);
+    }
+
+    private AIChatResponseContent convertResponseContentFromJson(String content) {
+        return getGson().fromJson(content, AIChatResponseContent.class);
+    }
+
+    private String getArgumentAsString(List<AIChatToolCall> toolCalls, int ind) {
+        return toolCalls.get(ind).getFunction().getArguments();
+    }
+
+    private AIChatResponseContent getArgumentAsResponse(List<AIChatToolCall> toolCalls, int ind) {
+        return convertResponseContentFromJson(getArgumentAsString(toolCalls, ind));
+    }
+
+    private AIChatResponseContent mergeToolCalls(List<AIChatToolCall> toolCalls) {
+        AIChatResponseContent responseContent = getArgumentAsResponse(toolCalls, 0);
+        for (int ind = 1; ind < toolCalls.size(); ind++) {
+            responseContent.getReplies().addAll(
+                    getArgumentAsResponse(toolCalls, ind).getReplies()
+            );
+        }
+        return responseContent;
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/openai/AIChatParameters.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/openai/AIChatParameters.java
new file mode 100644
index 0000000..1f4ad44
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/openai/AIChatParameters.java
@@ -0,0 +1,38 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.openai;
+
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.ClientBase;
+
+import java.util.concurrent.ThreadLocalRandom;
+
+public class AIChatParameters extends ClientBase {
+    private static boolean isCommentEvent;
+
+    public AIChatParameters(Configuration config, boolean isCommentEvent) {
+        super(config);
+        AIChatParameters.isCommentEvent = isCommentEvent;
+    }
+
+    public double getGptTemperature() {
+        if (isCommentEvent) {
+            return retrieveTemperature(Configuration.KEY_AI_COMMENT_TEMPERATURE,
+                    Configuration.DEFAULT_AI_CHAT_COMMENT_TEMPERATURE);
+        }
+       else {
+            return retrieveTemperature(Configuration.KEY_AI_REVIEW_TEMPERATURE,
+                    Configuration.DEFAULT_AI_CHAT_REVIEW_TEMPERATURE);
+        }
+    }
+
+    public boolean getStreamOutput() {
+        return config.getAIStreamOutput() && !isCommentEvent;
+    }
+
+    public int getRandomSeed() {
+        return ThreadLocalRandom.current().nextInt();
+    }
+
+    private Double retrieveTemperature(String temperatureKey, Double defaultTemperature) {
+        return Double.parseDouble(config.getString(temperatureKey, String.valueOf(defaultTemperature)));
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/openai/AIChatTools.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/openai/AIChatTools.java
new file mode 100644
index 0000000..6a74adb
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/api/openai/AIChatTools.java
@@ -0,0 +1,32 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.openai;
+
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatTool;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatToolChoice;
+import com.googlesource.gerrit.plugins.aicodereview.utils.FileUtils;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import static com.googlesource.gerrit.plugins.aicodereview.utils.GsonUtils.getGson;
+
+public class AIChatTools {
+    public static AIChatTool retrieveFormatRepliesTool() {
+        AIChatTool tools;
+        try (InputStreamReader reader = FileUtils.getInputStreamReader("config/formatRepliesTool.json")) {
+            tools = getGson().fromJson(reader, AIChatTool.class);
+        } catch (IOException e) {
+            throw new RuntimeException("Failed to load data for ChatGPT `format_replies` tool", e);
+        }
+        return tools;
+    }
+
+    public static AIChatToolChoice retrieveFormatRepliesToolChoice() {
+        AIChatToolChoice toolChoice;
+        try (InputStreamReader reader = FileUtils.getInputStreamReader("config/formatRepliesToolChoice.json")) {
+            toolChoice = getGson().fromJson(reader, AIChatToolChoice.class);
+        } catch (IOException e) {
+            throw new RuntimeException("Failed to load data for ChatGPT `format_replies` tool choice", e);
+        }
+        return toolChoice;
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/commands/ClientCommands.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/commands/ClientCommands.java
similarity index 91%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/commands/ClientCommands.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/commands/ClientCommands.java
index 38619d6..11b6e89 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/commands/ClientCommands.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/commands/ClientCommands.java
@@ -1,12 +1,12 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.commands;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.commands;
 
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.config.DynamicConfiguration;
-import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandlerProvider;
-import com.googlesource.gerrit.plugins.chatgpt.localization.Localizer;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.ClientBase;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.prompt.Directives;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.config.DynamicConfiguration;
+import com.googlesource.gerrit.plugins.aicodereview.data.PluginDataHandlerProvider;
+import com.googlesource.gerrit.plugins.aicodereview.localization.Localizer;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.ClientBase;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.prompt.Directives;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
 import lombok.Getter;
 import lombok.extern.slf4j.Slf4j;
 
@@ -126,7 +126,7 @@
             }
             else if (command == CommandSet.CONFIGURE) {
                 if (config.getEnableMessageDebugging()) {
-                    changeSetData.setHideChatGptReview(true);
+                    changeSetData.setHideAICodeReview(true);
                     dynamicConfiguration.updateConfiguration(modifiedDynamicConfig, shouldResetDynamicConfig);
                 }
                 else {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/http/HttpClient.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/http/HttpClient.java
similarity index 63%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/http/HttpClient.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/http/HttpClient.java
index ad537a6..6d87ae8 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/http/HttpClient.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/http/HttpClient.java
@@ -1,12 +1,14 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.http;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.http;
 
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
 import lombok.extern.slf4j.Slf4j;
 import okhttp3.*;
+import org.apache.http.NameValuePair;
 
 import java.io.IOException;
 import java.util.Map;
 
-import static com.googlesource.gerrit.plugins.chatgpt.utils.GsonUtils.getGson;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.GsonUtils.getGson;
 
 @Slf4j
 public class HttpClient {
@@ -28,12 +30,16 @@
         return null;
     }
 
-    public Request createRequest(String uri, String bearer, RequestBody body, Map<String, String> additionalHeaders) {
+    public Request createRequest(String uri, Configuration configuration, RequestBody body, Map<String, String> additionalHeaders) {
         // If body is null, a GET request is initiated. Otherwise, a POST request is sent with the specified body.
         Request.Builder builder = new Request.Builder()
-                .url(uri)
-                .header("Authorization", "Bearer " + bearer);
+                .url(uri);
 
+        // depending on the aiType, add appropriate authorization header ( if required ).
+        NameValuePair authHeader = configuration.getAuthorizationHeaderInfo();
+        if (authHeader != null) {
+            builder.header(authHeader.getName(), authHeader.getValue());
+        }
         if (body != null) {
             builder.post(body);
         }
@@ -48,17 +54,17 @@
         return builder.build();
     }
 
-    public Request createRequestFromJson(String uri, String bearer, Object requestObject,
+    public Request createRequestFromJson(String uri, Configuration configuration, Object requestObject,
                                          Map<String, String> additionalHeaders) {
         if (requestObject != null) {
             String bodyJson = getGson().toJson(requestObject);
             log.debug("Request body: {}", bodyJson);
             RequestBody body = RequestBody.create(bodyJson, MediaType.get("application/json"));
 
-            return createRequest(uri, bearer, body, additionalHeaders);
+            return createRequest(uri, configuration, body, additionalHeaders);
         }
         else {
-            return createRequest(uri, bearer, null, additionalHeaders);
+            return createRequest(uri, configuration, null, additionalHeaders);
         }
     }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/http/HttpClientWithRetry.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/http/HttpClientWithRetry.java
similarity index 95%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/http/HttpClientWithRetry.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/http/HttpClientWithRetry.java
index 52288c6..af6334d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/http/HttpClientWithRetry.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/http/HttpClientWithRetry.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.http;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.http;
 
 import com.github.rholder.retry.*;
 import com.google.inject.Singleton;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/messages/ClientMessage.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/messages/ClientMessage.java
similarity index 85%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/messages/ClientMessage.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/messages/ClientMessage.java
index dd4f130..689c64d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/messages/ClientMessage.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/messages/ClientMessage.java
@@ -1,11 +1,11 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.messages;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.messages;
 
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandlerProvider;
-import com.googlesource.gerrit.plugins.chatgpt.localization.Localizer;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.ClientBase;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.commands.ClientCommands;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.data.PluginDataHandlerProvider;
+import com.googlesource.gerrit.plugins.aicodereview.localization.Localizer;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.ClientBase;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.commands.ClientCommands;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
 import lombok.Getter;
 import lombok.extern.slf4j.Slf4j;
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/messages/DebugCodeBlocks.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/messages/DebugCodeBlocks.java
similarity index 85%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/messages/DebugCodeBlocks.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/messages/DebugCodeBlocks.java
index 4cb2491..8894a33 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/messages/DebugCodeBlocks.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/messages/DebugCodeBlocks.java
@@ -1,11 +1,11 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.messages;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.messages;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import static com.googlesource.gerrit.plugins.chatgpt.utils.TextUtils.*;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.TextUtils.*;
 
 public class DebugCodeBlocks {
     protected final String commentOpening;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/messages/DebugCodeBlocksDynamicSettings.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/messages/DebugCodeBlocksDynamicSettings.java
similarity index 64%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/messages/DebugCodeBlocksDynamicSettings.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/messages/DebugCodeBlocksDynamicSettings.java
index cb3829c..0c57376 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/messages/DebugCodeBlocksDynamicSettings.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/messages/DebugCodeBlocksDynamicSettings.java
@@ -1,11 +1,11 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.messages;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.messages;
 
-import com.googlesource.gerrit.plugins.chatgpt.localization.Localizer;
+import com.googlesource.gerrit.plugins.aicodereview.localization.Localizer;
 
 import java.util.List;
 import java.util.Map;
 
-import static com.googlesource.gerrit.plugins.chatgpt.utils.TextUtils.prettyStringifyMap;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.TextUtils.prettyStringifyMap;
 
 public class DebugCodeBlocksDynamicSettings extends DebugCodeBlocks {
     public DebugCodeBlocksDynamicSettings(Localizer localizer) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/messages/DebugCodeBlocksReview.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/messages/DebugCodeBlocksReview.java
new file mode 100644
index 0000000..2832cb2
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/messages/DebugCodeBlocksReview.java
@@ -0,0 +1,23 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.messages;
+
+import com.googlesource.gerrit.plugins.aicodereview.localization.Localizer;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatReplyItem;
+
+import java.util.List;
+
+import static com.googlesource.gerrit.plugins.aicodereview.utils.TextUtils.prettyStringifyObject;
+
+public class DebugCodeBlocksReview extends DebugCodeBlocks {
+    private static final String HIDDEN_REPLY = "hidden: %s";
+
+    public DebugCodeBlocksReview(Localizer localizer) {
+        super(localizer.getText("message.debugging.review.title"));
+    }
+
+    public String getDebugCodeBlock(AIChatReplyItem replyItem, boolean isHidden) {
+        return super.getDebugCodeBlock(List.of(
+                String.format(HIDDEN_REPLY, isHidden),
+                prettyStringifyObject(replyItem)
+        ));
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/patch/code/CodeFinder.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/patch/code/CodeFinder.java
similarity index 91%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/patch/code/CodeFinder.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/patch/code/CodeFinder.java
index e4dca8a..e02a899 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/patch/code/CodeFinder.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/patch/code/CodeFinder.java
@@ -1,9 +1,9 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.patch.code;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.patch.code;
 
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptReplyItem;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritCodeRange;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.patch.code.CodeFinderDiff;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.patch.diff.DiffContent;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatReplyItem;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritCodeRange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.patch.code.CodeFinderDiff;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.patch.diff.DiffContent;
 import lombok.extern.slf4j.Slf4j;
 
 import java.lang.reflect.Field;
@@ -35,7 +35,7 @@
         PLACEHOLDER_REGEX = "(?:" + randomPlaceholder + ")+";
     }
 
-    public GerritCodeRange findCommentedCode(ChatGptReplyItem replyItem, int commentedLine) {
+    public GerritCodeRange findCommentedCode(AIChatReplyItem replyItem, int commentedLine) {
         this.commentedLine = commentedLine;
         updateCodePattern(replyItem);
         currentCodeRange = null;
@@ -58,7 +58,7 @@
         return closestCodeRange;
     }
 
-    private void updateCodePattern(ChatGptReplyItem replyItem) {
+    private void updateCodePattern(AIChatReplyItem replyItem) {
         String commentedCode = replyItem.getCodeSnippet()
                 .replaceAll(BEGINNING_DIFF_REGEX, "")
                 .replaceAll(ENDING_ELLIPSIS_REGEX, "")
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/patch/code/InlineCode.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/patch/code/InlineCode.java
similarity index 80%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/patch/code/InlineCode.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/patch/code/InlineCode.java
index b9ebb8c..4fa8382 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/patch/code/InlineCode.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/patch/code/InlineCode.java
@@ -1,16 +1,16 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.patch.code;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.patch.code;
 
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.patch.diff.FileDiffProcessed;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptReplyItem;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritCodeRange;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritComment;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.patch.diff.FileDiffProcessed;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatReplyItem;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritCodeRange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritComment;
 import lombok.extern.slf4j.Slf4j;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
 
-import static com.googlesource.gerrit.plugins.chatgpt.utils.TextUtils.joinWithNewLine;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.TextUtils.joinWithNewLine;
 
 @Slf4j
 public class InlineCode {
@@ -37,7 +37,7 @@
         }
     }
 
-    public Optional<GerritCodeRange> findCommentRange(ChatGptReplyItem replyItem) {
+    public Optional<GerritCodeRange> findCommentRange(AIChatReplyItem replyItem) {
         int commentedLine;
         try {
             commentedLine = replyItem.getLineNumber();
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/patch/comment/GerritCommentRange.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/patch/comment/GerritCommentRange.java
similarity index 64%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/patch/comment/GerritCommentRange.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/patch/comment/GerritCommentRange.java
index ddd91c7..01c92c0 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/patch/comment/GerritCommentRange.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/patch/comment/GerritCommentRange.java
@@ -1,11 +1,11 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.patch.comment;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.patch.comment;
 
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritClient;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.patch.code.InlineCode;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.patch.diff.FileDiffProcessed;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptReplyItem;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritCodeRange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritClient;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.patch.code.InlineCode;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.patch.diff.FileDiffProcessed;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatReplyItem;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritCodeRange;
 import lombok.extern.slf4j.Slf4j;
 
 import java.util.HashMap;
@@ -19,7 +19,7 @@
         fileDiffsProcessed = gerritClient.getFileDiffsProcessed(change);
     }
 
-    public Optional<GerritCodeRange> getGerritCommentRange(ChatGptReplyItem replyItem) {
+    public Optional<GerritCodeRange> getGerritCommentRange(AIChatReplyItem replyItem) {
         Optional<GerritCodeRange> gerritCommentRange = Optional.empty();
         String filename = replyItem.getFilename();
         if (filename == null || filename.equals("/COMMIT_MSG")) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/patch/diff/FileDiffProcessed.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/patch/diff/FileDiffProcessed.java
similarity index 89%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/patch/diff/FileDiffProcessed.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/patch/diff/FileDiffProcessed.java
index 37c48b0..8fa74bc 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/patch/diff/FileDiffProcessed.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/patch/diff/FileDiffProcessed.java
@@ -1,10 +1,10 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.patch.diff;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.patch.diff;
 
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritPatchSetFileDiff;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.patch.code.CodeFinderDiff;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.patch.diff.DiffContent;
-import com.googlesource.gerrit.plugins.chatgpt.settings.Settings;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritPatchSetFileDiff;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.patch.code.CodeFinderDiff;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.patch.diff.DiffContent;
+import com.googlesource.gerrit.plugins.aicodereview.settings.Settings;
 import lombok.Getter;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.RandomStringUtils;
@@ -14,7 +14,7 @@
 import java.util.List;
 import java.util.TreeMap;
 
-import static com.googlesource.gerrit.plugins.chatgpt.utils.TextUtils.joinWithNewLine;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.TextUtils.joinWithNewLine;
 
 @Slf4j
 public class FileDiffProcessed {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/AIChatComment.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/AIChatComment.java
new file mode 100644
index 0000000..be5ef0b
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/AIChatComment.java
@@ -0,0 +1,38 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.prompt;
+
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.localization.Localizer;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.ClientBase;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.messages.ClientMessage;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritComment;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class AIChatComment extends ClientBase {
+    protected ClientMessage commentMessage;
+
+    private final ChangeSetData changeSetData;
+    private final Localizer localizer;
+
+    public AIChatComment(Configuration config, ChangeSetData changeSetData, Localizer localizer) {
+        super(config);
+        this.changeSetData = changeSetData;
+        this.localizer = localizer;
+    }
+
+    protected String getCleanedMessage(GerritComment commentProperty) {
+        commentMessage = new ClientMessage(config, changeSetData, commentProperty.getMessage(), localizer);
+        if (isFromAssistant(commentProperty)) {
+            commentMessage.removeDebugCodeBlocksReview().removeDebugCodeBlocksDynamicSettings();
+        }
+        else {
+            commentMessage.removeMentions().parseRemoveCommands();
+        }
+        return commentMessage.removeHeadings().getMessage();
+    }
+
+    protected boolean isFromAssistant(GerritComment commentProperty) {
+        return commentProperty.getAuthor().getAccountId() == changeSetData.getGptAccountId();
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/AIChatDataPrompt.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/AIChatDataPrompt.java
new file mode 100644
index 0000000..928e385
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/AIChatDataPrompt.java
@@ -0,0 +1,43 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.prompt;
+
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.common.client.prompt.ChatAIDataPrompt;
+import com.googlesource.gerrit.plugins.aicodereview.localization.Localizer;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatMessageItem;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.GerritClientData;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.List;
+
+import static com.googlesource.gerrit.plugins.aicodereview.utils.GsonUtils.getGson;
+
+@Slf4j
+public class AIChatDataPrompt {
+    private final ChatAIDataPrompt aiChatDataPromptHandler;
+
+    public AIChatDataPrompt(
+            Configuration config,
+            ChangeSetData changeSetData,
+            GerritChange change,
+            GerritClientData gerritClientData,
+            Localizer localizer
+    ) {
+        aiChatDataPromptHandler = AIChatPromptFactory.getChatGptDataPrompt(
+                config,
+                changeSetData,
+                change,
+                gerritClientData,
+                localizer
+        );
+    }
+
+    public String buildPrompt() {
+        for (int i = 0; i < aiChatDataPromptHandler.getCommentProperties().size(); i++) {
+            aiChatDataPromptHandler.addMessageItem(i);
+        }
+        List<AIChatMessageItem> messageItems = aiChatDataPromptHandler.getMessageItems();
+        return messageItems.isEmpty() ? "" : getGson().toJson(messageItems);
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/AIChatDataPromptBase.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/AIChatDataPromptBase.java
new file mode 100644
index 0000000..6ef3bf2
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/AIChatDataPromptBase.java
@@ -0,0 +1,71 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.prompt;
+
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.common.client.prompt.ChatAIDataPrompt;
+import com.googlesource.gerrit.plugins.aicodereview.localization.Localizer;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.patch.code.InlineCode;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.patch.diff.FileDiffProcessed;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatMessageItem;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatRequestMessage;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritComment;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.CommentData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.GerritClientData;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+@Slf4j
+public abstract class AIChatDataPromptBase implements ChatAIDataPrompt {
+    protected final GerritClientData gerritClientData;
+    protected final HashMap<String, FileDiffProcessed> fileDiffsProcessed;
+    protected final CommentData commentData;
+    @Getter
+    protected final List<AIChatMessageItem> messageItems;
+
+    protected AIChatHistory aiChatHistory;
+    @Getter
+    protected List<GerritComment> commentProperties;
+
+    public AIChatDataPromptBase(
+            Configuration config,
+            ChangeSetData changeSetData,
+            GerritClientData gerritClientData,
+            Localizer localizer
+    ) {
+        this.gerritClientData = gerritClientData;
+        fileDiffsProcessed = gerritClientData.getFileDiffsProcessed();
+        commentData = gerritClientData.getCommentData();
+        aiChatHistory = new AIChatHistory(config, changeSetData, gerritClientData, localizer);
+        messageItems = new ArrayList<>();
+    }
+
+    public abstract void addMessageItem(int i);
+
+    protected AIChatMessageItem getMessageItem(int i) {
+        AIChatMessageItem messageItem = new AIChatMessageItem();
+        GerritComment commentProperty = commentProperties.get(i);
+        if (commentProperty.getLine() != null || commentProperty.getRange() != null) {
+            String filename = commentProperty.getFilename();
+            FileDiffProcessed fileDiffProcessed = fileDiffsProcessed.get(filename);
+            if (fileDiffProcessed == null) {
+                return messageItem;
+            }
+            InlineCode inlineCode = new InlineCode(fileDiffProcessed);
+            messageItem.setFilename(filename);
+            messageItem.setLineNumber(commentProperty.getLine());
+            messageItem.setCodeSnippet(inlineCode.getInlineCode(commentProperty));
+        }
+
+        return messageItem;
+    }
+
+    protected void setHistory(AIChatMessageItem messageItem, List<AIChatRequestMessage> messageHistory) {
+        if (!messageHistory.isEmpty()) {
+            messageItem.setHistory(messageHistory);
+        }
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/AIChatDataPromptRequests.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/AIChatDataPromptRequests.java
new file mode 100644
index 0000000..708aa3a
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/AIChatDataPromptRequests.java
@@ -0,0 +1,54 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.prompt;
+
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.localization.Localizer;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatMessageItem;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatRequestMessage;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.GerritClientData;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.List;
+
+import static com.googlesource.gerrit.plugins.aicodereview.settings.Settings.OPEN_AI_CHAT_ROLE_USER;
+
+@Slf4j
+public class AIChatDataPromptRequests extends AIChatDataPromptBase {
+    protected AIChatMessageItem messageItem;
+    protected List<AIChatRequestMessage> messageHistory;
+
+    public AIChatDataPromptRequests(
+            Configuration config,
+            ChangeSetData changeSetData,
+            GerritClientData gerritClientData,
+            Localizer localizer
+    ) {
+        super(config, changeSetData, gerritClientData, localizer);
+        commentProperties = commentData.getCommentProperties();
+    }
+
+    public void addMessageItem(int i) {
+        AIChatMessageItem messageItem = getMessageItem(i);
+        messageItem.setId(i);
+        messageItems.add(messageItem);
+    }
+
+    protected AIChatMessageItem getMessageItem(int i) {
+        messageItem = super.getMessageItem(i);
+        messageHistory = aiChatHistory.retrieveHistory(commentProperties.get(i));
+        AIChatRequestMessage request = extractLastUserMessageFromHistory();
+        messageItem.setRequest(request.getContent());
+
+        return messageItem;
+    }
+
+    private AIChatRequestMessage extractLastUserMessageFromHistory() {
+        for (int i = messageHistory.size() - 1; i >= 0; i--) {
+            if (OPEN_AI_CHAT_ROLE_USER.equals(messageHistory.get(i).getRole())) {
+                return messageHistory.remove(i);
+            }
+        }
+        throw new RuntimeException("Error extracting request from message history: no user message found in " +
+                messageHistory);
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/AIChatDataPromptReview.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/AIChatDataPromptReview.java
new file mode 100644
index 0000000..f49663f
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/AIChatDataPromptReview.java
@@ -0,0 +1,42 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.prompt;
+
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.common.client.prompt.ChatAIDataPrompt;
+import com.googlesource.gerrit.plugins.aicodereview.localization.Localizer;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatMessageItem;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatRequestMessage;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.GerritClientData;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Slf4j
+public class AIChatDataPromptReview extends AIChatDataPromptBase implements ChatAIDataPrompt {
+    public AIChatDataPromptReview(
+            Configuration config,
+            ChangeSetData changeSetData,
+            GerritClientData gerritClientData,
+            Localizer localizer
+    ) {
+        super(config, changeSetData, gerritClientData, localizer);
+        commentProperties = new ArrayList<>(commentData.getCommentMap().values());
+    }
+
+    public void addMessageItem(int i) {
+        AIChatMessageItem messageItem = getMessageItem(i);
+        if (messageItem.getHistory() != null) {
+            messageItems.add(messageItem);
+        }
+    }
+
+    protected AIChatMessageItem getMessageItem(int i) {
+        AIChatMessageItem messageItem = super.getMessageItem(i);
+        List<AIChatRequestMessage> messageHistory = aiChatHistory.retrieveHistory(commentProperties.get(i),
+                true);
+        setHistory(messageItem, messageHistory);
+
+        return messageItem;
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptPrompt.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/AIChatGptPrompt.java
similarity index 62%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptPrompt.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/AIChatGptPrompt.java
index ab9efb5..d3d2a51 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptPrompt.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/AIChatGptPrompt.java
@@ -1,8 +1,8 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.prompt;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.prompt;
 
 import com.google.gson.reflect.TypeToken;
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.utils.FileUtils;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.utils.FileUtils;
 import lombok.Setter;
 import lombok.extern.slf4j.Slf4j;
 
@@ -12,11 +12,11 @@
 import java.util.*;
 import java.util.stream.Collectors;
 
-import static com.googlesource.gerrit.plugins.chatgpt.utils.GsonUtils.getGson;
-import static com.googlesource.gerrit.plugins.chatgpt.utils.TextUtils.*;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.GsonUtils.getGson;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.TextUtils.*;
 
 @Slf4j
-public class ChatGptPrompt {
+public class AIChatGptPrompt {
     // Reply attributes
     public static final String ATTRIBUTE_ID = "id";
     public static final String ATTRIBUTE_REPLY = "reply";
@@ -33,53 +33,53 @@
     ));
 
     // Prompt constants loaded from JSON file
-    public static String DEFAULT_GPT_SYSTEM_PROMPT;
-    public static String DEFAULT_GPT_REVIEW_PROMPT_DIRECTIVES;
-    public static String DEFAULT_GPT_PROMPT_FORCE_JSON_FORMAT;
-    public static String DEFAULT_GPT_REPLIES_PROMPT_SPECS;
-    public static String DEFAULT_GPT_REPLIES_PROMPT_INLINE;
-    public static String DEFAULT_GPT_REPLIES_PROMPT_ENFORCE_RESPONSE_CHECK;
-    public static String DEFAULT_GPT_REQUEST_PROMPT_DIFF;
-    public static String DEFAULT_GPT_REQUEST_PROMPT_REQUESTS;
-    public static String DEFAULT_GPT_REVIEW_PROMPT_COMMIT_MESSAGES;
-    public static String DEFAULT_GPT_RELEVANCE_RULES;
-    public static String DEFAULT_GPT_HOW_TO_FIND_COMMIT_MESSAGE;
-    public static Map<String, String> DEFAULT_GPT_REPLIES_ATTRIBUTES;
+    public static String DEFAULT_AI_CHAT_SYSTEM_PROMPT;
+    public static String DEFAULT_AI_CHAT_REVIEW_PROMPT_DIRECTIVES;
+    public static String DEFAULT_AI_CHAT_PROMPT_FORCE_JSON_FORMAT;
+    public static String DEFAULT_AI_CHAT_REPLIES_PROMPT_SPECS;
+    public static String DEFAULT_AI_CHAT_REPLIES_PROMPT_INLINE;
+    public static String DEFAULT_AI_CHAT_REPLIES_PROMPT_ENFORCE_RESPONSE_CHECK;
+    public static String DEFAULT_AI_CHAT_REQUEST_PROMPT_DIFF;
+    public static String DEFAULT_AI_CHAT_REQUEST_PROMPT_REQUESTS;
+    public static String DEFAULT_AI_CHAT_REVIEW_PROMPT_COMMIT_MESSAGES;
+    public static String DEFAULT_AI_CHAT_RELEVANCE_RULES;
+    public static String DEFAULT_AI_CHAT_HOW_TO_FIND_COMMIT_MESSAGE;
+    public static Map<String, String> DEFAULT_AI_CHAT_REPLIES_ATTRIBUTES;
 
     protected final Configuration config;
 
     @Setter
     protected boolean isCommentEvent;
 
-    public ChatGptPrompt(Configuration config) {
+    public AIChatGptPrompt(Configuration config) {
+        this(config, false);
+    }
+
+    public AIChatGptPrompt(Configuration config, boolean isCommentEvent) {
         this.config = config;
+        this.isCommentEvent = isCommentEvent;
         // Avoid repeated loading of prompt constants
-        if (DEFAULT_GPT_SYSTEM_PROMPT == null) {
+        if (DEFAULT_AI_CHAT_SYSTEM_PROMPT == null) {
             loadDefaultPrompts("prompts");
         }
     }
 
-    public ChatGptPrompt(Configuration config, boolean isCommentEvent) {
-        this(config);
-        this.isCommentEvent = isCommentEvent;
-    }
-
     public static String getCommentRequestPrompt(int commentPropertiesSize) {
         return joinWithSpace(new ArrayList<>(List.of(
-                DEFAULT_GPT_PROMPT_FORCE_JSON_FORMAT,
+                DEFAULT_AI_CHAT_PROMPT_FORCE_JSON_FORMAT,
                 buildFieldSpecifications(REQUEST_REPLY_ATTRIBUTES),
-                DEFAULT_GPT_REPLIES_PROMPT_INLINE,
-                String.format(DEFAULT_GPT_REPLIES_PROMPT_ENFORCE_RESPONSE_CHECK, commentPropertiesSize)
+                DEFAULT_AI_CHAT_REPLIES_PROMPT_INLINE,
+                String.format(DEFAULT_AI_CHAT_REPLIES_PROMPT_ENFORCE_RESPONSE_CHECK, commentPropertiesSize)
         )));
     }
 
     public static String getReviewPromptCommitMessages() {
-        return String.format(DEFAULT_GPT_REVIEW_PROMPT_COMMIT_MESSAGES, DEFAULT_GPT_HOW_TO_FIND_COMMIT_MESSAGE);
+        return String.format(DEFAULT_AI_CHAT_REVIEW_PROMPT_COMMIT_MESSAGES, DEFAULT_AI_CHAT_HOW_TO_FIND_COMMIT_MESSAGE);
     }
 
     protected void loadDefaultPrompts(String promptFilename) {
         String promptFile = String.format("config/%s.json", promptFilename);
-        Class<? extends ChatGptPrompt> me = this.getClass();
+        Class<? extends AIChatGptPrompt> me = this.getClass();
         try (InputStreamReader reader = FileUtils.getInputStreamReader(promptFile)) {
             Map<String, Object> values = getGson().fromJson(reader, new TypeToken<Map<String, Object>>(){}.getType());
             for (Map.Entry<String, Object> entry : values.entrySet()) {
@@ -96,12 +96,12 @@
             throw new RuntimeException("Failed to load prompts", e);
         }
         // Keep the given order of attributes
-        DEFAULT_GPT_REPLIES_ATTRIBUTES = new LinkedHashMap<>(DEFAULT_GPT_REPLIES_ATTRIBUTES);
+        DEFAULT_AI_CHAT_REPLIES_ATTRIBUTES = new LinkedHashMap<>(DEFAULT_AI_CHAT_REPLIES_ATTRIBUTES);
     }
 
     protected static String buildFieldSpecifications(List<String> filterFields) {
         Set<String> orderedFilterFields = new LinkedHashSet<>(filterFields);
-        Map<String, String> attributes = DEFAULT_GPT_REPLIES_ATTRIBUTES.entrySet().stream()
+        Map<String, String> attributes = DEFAULT_AI_CHAT_REPLIES_ATTRIBUTES.entrySet().stream()
                 .filter(entry -> orderedFilterFields.contains(entry.getKey()))
                 .collect(Collectors.toMap(
                         entry -> INLINE_CODE_DELIMITER + entry.getKey() + INLINE_CODE_DELIMITER,
@@ -113,7 +113,7 @@
                 .map(entry -> entry.getKey() + SPACE + entry.getValue())
                 .collect(Collectors.toList());
 
-        return String.format(DEFAULT_GPT_REPLIES_PROMPT_SPECS,
+        return String.format(DEFAULT_AI_CHAT_REPLIES_PROMPT_SPECS,
                 joinWithComma(attributes.keySet()),
                 joinWithSemicolon(fieldDescription)
         );
@@ -128,24 +128,24 @@
             attributes.remove(ATTRIBUTE_SCORE);
         }
         updateRelevanceDescription();
-        return buildFieldSpecifications(attributes) + SPACE + DEFAULT_GPT_REPLIES_PROMPT_INLINE;
+        return buildFieldSpecifications(attributes) + SPACE + DEFAULT_AI_CHAT_REPLIES_PROMPT_INLINE;
     }
 
     private void updateScoreDescription() {
-        String scoreDescription = DEFAULT_GPT_REPLIES_ATTRIBUTES.get(ATTRIBUTE_SCORE);
+        String scoreDescription = DEFAULT_AI_CHAT_REPLIES_ATTRIBUTES.get(ATTRIBUTE_SCORE);
         if (scoreDescription.contains("%d")) {
             scoreDescription = String.format(scoreDescription, config.getVotingMinScore(), config.getVotingMaxScore());
-            DEFAULT_GPT_REPLIES_ATTRIBUTES.put(ATTRIBUTE_SCORE, scoreDescription);
+            DEFAULT_AI_CHAT_REPLIES_ATTRIBUTES.put(ATTRIBUTE_SCORE, scoreDescription);
         }
     }
 
     private void updateRelevanceDescription() {
-        String relevanceDescription = DEFAULT_GPT_REPLIES_ATTRIBUTES.get(ATTRIBUTE_RELEVANCE);
+        String relevanceDescription = DEFAULT_AI_CHAT_REPLIES_ATTRIBUTES.get(ATTRIBUTE_RELEVANCE);
         if (relevanceDescription.contains("%s")) {
-            String defaultGptRelevanceRules = config.getString(Configuration.KEY_GPT_RELEVANCE_RULES,
-                    DEFAULT_GPT_RELEVANCE_RULES);
-            relevanceDescription = String.format(relevanceDescription, defaultGptRelevanceRules);
-            DEFAULT_GPT_REPLIES_ATTRIBUTES.put(ATTRIBUTE_RELEVANCE, relevanceDescription);
+            String defaultAIRelevanceRules = config.getString(Configuration.KEY_AI_RELEVANCE_RULES,
+                    DEFAULT_AI_CHAT_RELEVANCE_RULES);
+            relevanceDescription = String.format(relevanceDescription, defaultAIRelevanceRules);
+            DEFAULT_AI_CHAT_REPLIES_ATTRIBUTES.put(ATTRIBUTE_RELEVANCE, relevanceDescription);
         }
     }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptHistory.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/AIChatHistory.java
similarity index 73%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptHistory.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/AIChatHistory.java
index 1bf8c3a..f48462c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptHistory.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/AIChatHistory.java
@@ -1,13 +1,13 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.prompt;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.prompt;
 
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.localization.Localizer;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptRequestMessage;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritComment;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.CommentData;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.GerritClientData;
-import com.googlesource.gerrit.plugins.chatgpt.settings.Settings;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.localization.Localizer;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatRequestMessage;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritComment;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.CommentData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.GerritClientData;
+import com.googlesource.gerrit.plugins.aicodereview.settings.Settings;
 import lombok.extern.slf4j.Slf4j;
 
 import java.util.*;
@@ -15,7 +15,7 @@
 import java.util.stream.Stream;
 
 @Slf4j
-public class ChatGptHistory extends ChatGptComment {
+public class AIChatHistory extends AIChatComment {
     private final Set<String> messagesExcludedFromHistory;
     private final HashMap<String, GerritComment> commentMap;
     private final HashMap<String, GerritComment> patchSetCommentMap;
@@ -25,7 +25,7 @@
 
     private boolean filterActive;
 
-    public ChatGptHistory(
+    public AIChatHistory(
             Configuration config,
             ChangeSetData changeSetData,
             GerritClientData gerritClientData,
@@ -44,7 +44,7 @@
         patchSetCommentAdded = new HashSet<>();
     }
 
-    public List<ChatGptRequestMessage> retrieveHistory(GerritComment commentProperty, boolean filterActive) {
+    public List<AIChatRequestMessage> retrieveHistory(GerritComment commentProperty, boolean filterActive) {
         this.filterActive = filterActive;
         if (commentProperty.isPatchSetComment()) {
             return retrievePatchSetMessageHistory();
@@ -54,7 +54,7 @@
         }
     }
 
-    public List<ChatGptRequestMessage> retrieveHistory(GerritComment commentProperty) {
+    public List<AIChatRequestMessage> retrieveHistory(GerritComment commentProperty) {
         return retrieveHistory(commentProperty, false);
     }
 
@@ -86,11 +86,11 @@
     }
 
     private String getRoleFromComment(GerritComment currentComment) {
-        return isFromAssistant(currentComment) ? Settings.CHAT_GPT_ROLE_ASSISTANT : Settings.CHAT_GPT_ROLE_USER;
+        return isFromAssistant(currentComment) ? Settings.OPEN_AI_CHAT_ROLE_ASSISTANT : Settings.OPEN_AI_CHAT_ROLE_USER;
     }
 
-    private List<ChatGptRequestMessage> retrieveMessageHistory(GerritComment currentComment) {
-        List<ChatGptRequestMessage> messageHistory = new ArrayList<>();
+    private List<AIChatRequestMessage> retrieveMessageHistory(GerritComment currentComment) {
+        List<AIChatRequestMessage> messageHistory = new ArrayList<>();
         while (currentComment != null) {
             addMessageToHistory(messageHistory, currentComment);
             currentComment = commentMap.get(currentComment.getInReplyTo());
@@ -101,8 +101,8 @@
         return messageHistory;
     }
 
-    private List<ChatGptRequestMessage> retrievePatchSetMessageHistory() {
-        List<ChatGptRequestMessage> messageHistory = new ArrayList<>();
+    private List<AIChatRequestMessage> retrievePatchSetMessageHistory() {
+        List<AIChatRequestMessage> messageHistory = new ArrayList<>();
         for (GerritComment patchSetComment : patchSetComments) {
             if (patchSetComment.isAutogenerated()) {
                 continue;
@@ -119,12 +119,12 @@
     }
 
     private boolean isInactiveComment(GerritComment comment) {
-        return config.getIgnoreResolvedChatGptComments() && isFromAssistant(comment) && comment.isResolved() ||
+        return config.getIgnoreResolvedAIChatComments() && isFromAssistant(comment) && comment.isResolved() ||
                 config.getIgnoreOutdatedInlineComments() && comment.getOneBasedPatchSet() != revisionBase &&
                         !comment.isPatchSetComment();
     }
 
-    private void addMessageToHistory(List<ChatGptRequestMessage> messageHistory, GerritComment comment) {
+    private void addMessageToHistory(List<AIChatRequestMessage> messageHistory, GerritComment comment) {
         String messageContent = getCleanedMessage(comment);
         boolean shouldNotProcessComment = messageContent.isEmpty() ||
                 messagesExcludedFromHistory.contains(messageContent) ||
@@ -139,7 +139,7 @@
             commentMessage.processHistoryCommand();
             return;
         }
-        ChatGptRequestMessage message = ChatGptRequestMessage.builder()
+        AIChatRequestMessage message = AIChatRequestMessage.builder()
                 .role(getRoleFromComment(comment))
                 .content(messageContent)
                 .build();
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/AIChatPromptFactory.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/AIChatPromptFactory.java
new file mode 100644
index 0000000..1d294a0
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/AIChatPromptFactory.java
@@ -0,0 +1,54 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.prompt;
+
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.common.client.prompt.ChatAIDataPrompt;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.stateful.client.prompt.ChatGptPromptStateful;
+import com.googlesource.gerrit.plugins.aicodereview.localization.Localizer;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.GerritClientData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.prompt.AIChatDataPromptRequestsStateful;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.prompt.AIChatGptPromptStatefulRequests;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.prompt.AIChatGptPromptStatefulReview;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateless.client.prompt.AIChatDataPromptRequestsStateless;
+import com.googlesource.gerrit.plugins.aicodereview.settings.Settings;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class AIChatPromptFactory {
+
+    public static ChatGptPromptStateful getAIChatPromptStateful(
+            Configuration config,
+            ChangeSetData changeSetData,
+            GerritChange change
+    ) {
+        if (change.getIsCommentEvent()) {
+            log.info("AIChatPromptFactory: Returned AIChatGptPromptStatefulRequests");
+            return new AIChatGptPromptStatefulRequests(config, changeSetData, change);
+        } else {
+            log.info("AIChatPromptFactory: Returned AIChatGptPromptStatefulReview");
+            return new AIChatGptPromptStatefulReview(config, changeSetData, change);
+        }
+    }
+
+    public static ChatAIDataPrompt getChatGptDataPrompt(
+            Configuration config,
+            ChangeSetData changeSetData,
+            GerritChange change,
+            GerritClientData gerritClientData,
+            Localizer localizer
+    ) {
+        if (change.getIsCommentEvent()) {
+            if ((config.getAIMode() == Settings.Modes.stateless)) {
+                log.info("AIChatPromptFactory: Returned AIChatDataPromptRequestsStateless");
+                return new AIChatDataPromptRequestsStateless(config, changeSetData, gerritClientData, localizer);
+            } else {
+                log.info("AIChatPromptFactory: Returned AIChatDataPromptRequestsStateful");
+                return new AIChatDataPromptRequestsStateful(config, changeSetData, gerritClientData, localizer);
+            }
+        } else {
+            log.info("AIChatPromptFactory: Returned AIChatDataPromptReview");
+            return new AIChatDataPromptReview(config, changeSetData, gerritClientData, localizer);
+        }
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/Directives.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/Directives.java
similarity index 74%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/Directives.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/Directives.java
index 6cdeb98..ea1a6ed 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/Directives.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/Directives.java
@@ -1,6 +1,6 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.prompt;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.prompt;
 
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
 
 public class Directives {
     private final ChangeSetData changeSetData;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/MessageSanitizer.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/MessageSanitizer.java
similarity index 90%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/MessageSanitizer.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/MessageSanitizer.java
index 41f1a59..7bf49d2 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/MessageSanitizer.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/client/prompt/MessageSanitizer.java
@@ -1,16 +1,16 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.prompt;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.client.prompt;
 
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import static com.googlesource.gerrit.plugins.chatgpt.utils.TextUtils.*;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.TextUtils.*;
 
 public class MessageSanitizer {
     private static final Pattern SANITIZE_BOLD_REGEX = Pattern.compile("(\\*{1,2}|(?<!\\w)_{1,2})(.+?)\\1",
             Pattern.DOTALL);
     private static final Pattern SANITIZE_NUM_REGEX = Pattern.compile("^(\\s*)(#+)(?=\\s)", Pattern.MULTILINE);
 
-    public static String sanitizeChatGptMessage(String message) {
+    public static String sanitizeAIChatMessage(String message) {
         // Sanitize code blocks (delimited by CODE_DELIMITER) by stripping out the language for syntax highlighting and
         // ensuring that is preceded by two "\n" chars. Additionally, sanitize the content outside these blocks.
         return parseOutOfDelimiters(message, "\\s*" + CODE_DELIMITER + "\\w*\\s*",
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/gerrit/GerritCodeRange.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/gerrit/GerritCodeRange.java
similarity index 83%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/gerrit/GerritCodeRange.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/gerrit/GerritCodeRange.java
index ca6d6b8..6917006 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/gerrit/GerritCodeRange.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/gerrit/GerritCodeRange.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit;
 
 import com.google.gson.annotations.SerializedName;
 import lombok.Builder;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/gerrit/GerritComment.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/gerrit/GerritComment.java
similarity index 91%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/gerrit/GerritComment.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/gerrit/GerritComment.java
index 4c68ef0..defea13 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/gerrit/GerritComment.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/gerrit/GerritComment.java
@@ -1,7 +1,7 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit;
 
 import com.google.gson.annotations.SerializedName;
-import com.googlesource.gerrit.plugins.chatgpt.settings.Settings;
+import com.googlesource.gerrit.plugins.aicodereview.settings.Settings;
 import lombok.Data;
 
 @Data
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/gerrit/GerritFileDiff.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/gerrit/GerritFileDiff.java
similarity index 81%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/gerrit/GerritFileDiff.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/gerrit/GerritFileDiff.java
index 174809a..4daf319 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/gerrit/GerritFileDiff.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/gerrit/GerritFileDiff.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit;
 
 import com.google.gson.annotations.SerializedName;
 import lombok.Data;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/gerrit/GerritPatchSetDetail.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/gerrit/GerritPatchSetDetail.java
similarity index 91%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/gerrit/GerritPatchSetDetail.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/gerrit/GerritPatchSetDetail.java
index 6e26f82..d33a02d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/gerrit/GerritPatchSetDetail.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/gerrit/GerritPatchSetDetail.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit;
 
 import com.google.gson.annotations.SerializedName;
 import lombok.Data;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/gerrit/GerritPatchSetFileDiff.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/gerrit/GerritPatchSetFileDiff.java
similarity index 81%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/gerrit/GerritPatchSetFileDiff.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/gerrit/GerritPatchSetFileDiff.java
index 4a1d126..27d4873 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/gerrit/GerritPatchSetFileDiff.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/gerrit/GerritPatchSetFileDiff.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit;
 
 import lombok.Data;
 import lombok.EqualsAndHashCode;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/gerrit/GerritPermittedVotingRange.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/gerrit/GerritPermittedVotingRange.java
new file mode 100644
index 0000000..1220941
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/gerrit/GerritPermittedVotingRange.java
@@ -0,0 +1,9 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit;
+
+import lombok.Data;
+
+@Data
+public class GerritPermittedVotingRange {
+    private int min;
+    private int max;
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/gerrit/GerritReview.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/gerrit/GerritReview.java
similarity index 84%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/gerrit/GerritReview.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/gerrit/GerritReview.java
index 63788e2..8a6bfb9 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/gerrit/GerritReview.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/gerrit/GerritReview.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit;
 
 import com.google.gson.annotations.SerializedName;
 import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/gerrit/GerritReviewFileDiff.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/gerrit/GerritReviewFileDiff.java
similarity index 66%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/gerrit/GerritReviewFileDiff.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/gerrit/GerritReviewFileDiff.java
index 4e2debd..7e8c81b 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/gerrit/GerritReviewFileDiff.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/gerrit/GerritReviewFileDiff.java
@@ -1,6 +1,6 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit;
 
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.patch.diff.DiffContent;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.patch.diff.DiffContent;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatDialogueItem.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatDialogueItem.java
new file mode 100644
index 0000000..338a70f
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatDialogueItem.java
@@ -0,0 +1,11 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai;
+
+import lombok.Data;
+
+@Data
+public abstract class AIChatDialogueItem {
+    protected Integer id;
+    protected String filename;
+    protected Integer lineNumber;
+    protected String codeSnippet;
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatMessageItem.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatMessageItem.java
new file mode 100644
index 0000000..031bc73
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatMessageItem.java
@@ -0,0 +1,13 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.List;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class AIChatMessageItem extends AIChatDialogueItem {
+    private String request;
+    private List<AIChatRequestMessage> history;
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptReplyItem.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatReplyItem.java
similarity index 63%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptReplyItem.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatReplyItem.java
index bb91382..eef7929 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptReplyItem.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatReplyItem.java
@@ -1,11 +1,11 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai;
 
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 
 @EqualsAndHashCode(callSuper = true)
 @Data
-public class ChatGptReplyItem extends ChatGptDialogueItem {
+public class AIChatReplyItem extends AIChatDialogueItem {
     private String reply;
     private Integer score;
     private Double relevance;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptRequestMessage.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatRequestMessage.java
similarity index 61%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptRequestMessage.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatRequestMessage.java
index 1e20263..f476d15 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptRequestMessage.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatRequestMessage.java
@@ -1,11 +1,11 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai;
 
 import lombok.Builder;
 import lombok.Data;
 
 @Data
 @Builder
-public class ChatGptRequestMessage {
+public class AIChatRequestMessage {
     private String role;
     private String content;
     // PatchSet changeId passed in the request
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatResponseContent.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatResponseContent.java
new file mode 100644
index 0000000..90a425e
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatResponseContent.java
@@ -0,0 +1,16 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai;
+
+import lombok.Data;
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+
+import java.util.List;
+
+@Data
+@RequiredArgsConstructor
+public class AIChatResponseContent {
+    private List<AIChatReplyItem> replies;
+    private String changeId;
+    @NonNull
+    private String messageContent;
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptResponseMessage.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatResponseMessage.java
similarity index 70%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptResponseMessage.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatResponseMessage.java
index b9e169c..f2c85f9 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptResponseMessage.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatResponseMessage.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai;
 
 import com.google.gson.annotations.SerializedName;
 import lombok.Data;
@@ -6,11 +6,11 @@
 import java.util.List;
 
 @Data
-public class ChatGptResponseMessage {
+public class AIChatResponseMessage {
     private String role;
     private String type;
     @SerializedName("tool_calls")
-    private List<ChatGptToolCall> toolCalls;
+    private List<AIChatToolCall> toolCalls;
     @SerializedName("message_creation")
     private MessageCreation messageCreation;
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptResponseStreamed.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatResponseStreamed.java
similarity index 63%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptResponseStreamed.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatResponseStreamed.java
index bb9ca0b..81960c3 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptResponseStreamed.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatResponseStreamed.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai;
 
 import com.google.gson.annotations.SerializedName;
 import lombok.Data;
@@ -6,12 +6,12 @@
 import java.util.List;
 
 @Data
-public class ChatGptResponseStreamed {
+public class AIChatResponseStreamed {
     private List<Choice> choices;
 
     @Data
     public static class Choice {
-        protected ChatGptResponseMessage delta;
+        protected AIChatResponseMessage delta;
         protected int index;
         @SerializedName("finish_reason")
         protected String finishReason;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatResponseUnstreamed.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatResponseUnstreamed.java
new file mode 100644
index 0000000..bc590e2
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatResponseUnstreamed.java
@@ -0,0 +1,15 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class AIChatResponseUnstreamed {
+    private List<MessageChoice> choices;
+
+    @Data
+    public static class MessageChoice {
+        private AIChatResponseMessage message;
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptTool.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatTool.java
similarity index 94%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptTool.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatTool.java
index 2b501b3..176e29c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptTool.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatTool.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai;
 
 import lombok.Data;
 import lombok.NonNull;
@@ -8,7 +8,7 @@
 
 @RequiredArgsConstructor
 @Data
-public class ChatGptTool {
+public class AIChatTool {
     @NonNull
     private String type;
     private Function function;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptToolCall.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatToolCall.java
similarity index 66%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptToolCall.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatToolCall.java
index b1325ca..605015f 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptToolCall.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatToolCall.java
@@ -1,9 +1,9 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai;
 
 import lombok.Data;
 
 @Data
-public class ChatGptToolCall {
+public class AIChatToolCall {
     private String id;
     private String type;
     private Function function;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatToolChoice.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatToolChoice.java
new file mode 100644
index 0000000..1ba0478
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/api/openai/AIChatToolChoice.java
@@ -0,0 +1,14 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai;
+
+import lombok.Data;
+
+@Data
+public class AIChatToolChoice {
+    private String type;
+    private Function function;
+
+    @Data
+    public static class Function {
+        private String name;
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/data/ChangeSetData.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/data/ChangeSetData.java
similarity index 66%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/data/ChangeSetData.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/data/ChangeSetData.java
index 060f38e..5b5fa4f 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/data/ChangeSetData.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/data/ChangeSetData.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data;
 
 import lombok.Data;
 import lombok.NonNull;
@@ -14,7 +14,7 @@
 public class ChangeSetData {
     @NonNull
     private Integer gptAccountId;
-    private String gptDataPrompt;
+    private String reviewAIDataPrompt;
     private Integer commentPropertiesSize;
     @NonNull
     private Integer votingMinScore;
@@ -26,15 +26,15 @@
     private Boolean forcedReviewLastPatchSet = false;
     private Boolean replyFilterEnabled = true;
     private Boolean debugReviewMode = false;
-    private Boolean hideChatGptReview = false;
+    private Boolean hideAICodeReview = false;
     private Set<String> directives = new HashSet<>();
     private String reviewSystemMessage;
 
-    public Boolean shouldHideChatGptReview() {
-        return hideChatGptReview && !forcedReview;
+    public Boolean shouldHideAICodeReview() {
+        return hideAICodeReview && !forcedReview;
     }
 
-    public Boolean shouldRequestChatGptReview() {
-        return reviewSystemMessage == null && !shouldHideChatGptReview();
+    public Boolean shouldRequestAICodeReview() {
+        return reviewSystemMessage == null && !shouldHideAICodeReview();
     }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/data/CommentData.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/data/CommentData.java
similarity index 65%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/data/CommentData.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/data/CommentData.java
index a43d8b9..b7085ab 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/data/CommentData.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/data/CommentData.java
@@ -1,6 +1,6 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data;
 
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritComment;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritComment;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/data/GerritClientData.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/data/GerritClientData.java
similarity index 66%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/data/GerritClientData.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/data/GerritClientData.java
index 232935b..8dfa887 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/data/GerritClientData.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/data/GerritClientData.java
@@ -1,7 +1,7 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data;
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data;
 
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.patch.diff.FileDiffProcessed;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritComment;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.patch.diff.FileDiffProcessed;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritComment;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/patch/code/CodeFinderDiff.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/patch/code/CodeFinderDiff.java
new file mode 100644
index 0000000..cd826d1
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/patch/code/CodeFinderDiff.java
@@ -0,0 +1,14 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.patch.code;
+
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.patch.diff.DiffContent;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+import java.util.TreeMap;
+
+@AllArgsConstructor
+@Data
+public class CodeFinderDiff {
+    private DiffContent content;
+    private TreeMap<Integer, Integer> charToLineMap;
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/patch/diff/DiffContent.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/patch/diff/DiffContent.java
new file mode 100644
index 0000000..620acc9
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/patch/diff/DiffContent.java
@@ -0,0 +1,10 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.patch.diff;
+
+import lombok.Data;
+
+@Data
+public class DiffContent {
+    public String a;
+    public String b;
+    public String ab;
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/review/ReviewBatch.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/review/ReviewBatch.java
new file mode 100644
index 0000000..cb1f356
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/common/model/review/ReviewBatch.java
@@ -0,0 +1,23 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.common.model.review;
+
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.gerrit.GerritCodeRange;
+import lombok.Data;
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+
+import static com.googlesource.gerrit.plugins.aicodereview.settings.Settings.GERRIT_PATCH_SET_FILENAME;
+
+@Data
+@RequiredArgsConstructor
+public class ReviewBatch {
+    private String id;
+    @NonNull
+    private String content;
+    private String filename;
+    private Integer line;
+    private GerritCodeRange range;
+
+    public String getFilename() {
+        return filename == null ? GERRIT_PATCH_SET_FILENAME : filename;
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/UriResourceLocatorStateful.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/UriResourceLocatorStateful.java
similarity index 94%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/UriResourceLocatorStateful.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/UriResourceLocatorStateful.java
index a0265a2..4525c25 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/UriResourceLocatorStateful.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/UriResourceLocatorStateful.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api;
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api;
 
 public class UriResourceLocatorStateful {
     private static final String VERSION_URI = "/v1";
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/chatai/AIChatClientStateful.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/chatai/AIChatClientStateful.java
new file mode 100644
index 0000000..9c586fe
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/chatai/AIChatClientStateful.java
@@ -0,0 +1,109 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.chatai;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.data.PluginDataHandlerProvider;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.common.client.api.openapi.ChatAIClient;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.openai.AIChatClient;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatResponseContent;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.chatgpt.ChatGptRun;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.chatgpt.ChatGptThread;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.chatgpt.ChatGptThreadMessage;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.git.GitRepoFiles;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.model.api.chatgpt.ChatGptThreadMessageResponse;
+import lombok.extern.slf4j.Slf4j;
+
+import static com.googlesource.gerrit.plugins.aicodereview.utils.GsonUtils.getGson;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.JsonTextUtils.isJsonString;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.JsonTextUtils.unwrapJsonCode;
+
+@Slf4j
+@Singleton
+public class AIChatClientStateful extends AIChatClient implements ChatAIClient {
+    private static final String TYPE_MESSAGE_CREATION = "message_creation";
+    private static final String TYPE_TOOL_CALLS = "tool_calls";
+
+    private final GitRepoFiles gitRepoFiles;
+    private final PluginDataHandlerProvider pluginDataHandlerProvider;
+
+    @VisibleForTesting
+    @Inject
+    public AIChatClientStateful(
+            Configuration config,
+            GitRepoFiles gitRepoFiles,
+            PluginDataHandlerProvider pluginDataHandlerProvider
+    ) {
+        super(config);
+        this.gitRepoFiles = gitRepoFiles;
+        this.pluginDataHandlerProvider = pluginDataHandlerProvider;
+    }
+
+    public AIChatResponseContent ask(ChangeSetData changeSetData, GerritChange change, String patchSet) {
+        isCommentEvent = change.getIsCommentEvent();
+        String changeId = change.getFullChangeId();
+        log.info("Processing STATEFUL ChatGPT Request with changeId: {}, Patch Set: {}", changeId, patchSet);
+
+        ChatGptThread chatGptThread = new ChatGptThread(config, pluginDataHandlerProvider);
+        String threadId = chatGptThread.createThread();
+
+        ChatGptThreadMessage chatGptThreadMessage = new ChatGptThreadMessage(
+                threadId,
+                config,
+                changeSetData,
+                change,
+                patchSet
+        );
+        chatGptThreadMessage.addMessage();
+
+        ChatGptRun chatGptRun = new ChatGptRun(
+                threadId,
+                config,
+                changeSetData,
+                change,
+                gitRepoFiles,
+                pluginDataHandlerProvider
+        );
+        chatGptRun.createRun();
+        chatGptRun.pollRunStep();
+        // Attribute `requestBody` is valued for testing purposes
+        requestBody = chatGptThreadMessage.getAddMessageRequestBody();
+        log.debug("ChatGPT request body: {}", requestBody);
+
+        AIChatResponseContent AIChatResponseContent = getResponseContentStateful(threadId, chatGptRun);
+        chatGptRun.cancelRun();
+
+        return AIChatResponseContent;
+    }
+
+    private AIChatResponseContent getResponseContentStateful(String threadId, ChatGptRun chatGptRun) {
+        return switch (chatGptRun.getFirstStepDetails().getType()) {
+            case TYPE_MESSAGE_CREATION -> retrieveThreadMessage(threadId, chatGptRun);
+            case TYPE_TOOL_CALLS -> getResponseContent(chatGptRun.getFirstStepToolCalls());
+            default -> throw new IllegalStateException("Unexpected Step Type in stateful ChatGpt response: " +
+                    chatGptRun);
+        };
+    }
+
+    private AIChatResponseContent retrieveThreadMessage(String threadId, ChatGptRun chatGptRun) {
+        ChatGptThreadMessage chatGptThreadMessage = new ChatGptThreadMessage(threadId, config);
+        ChatGptThreadMessageResponse threadMessageResponse = chatGptThreadMessage.retrieveMessage(
+                chatGptRun.getFirstStepDetails().getMessageCreation().getMessageId()
+        );
+        String responseText = threadMessageResponse.getContent().get(0).getText().getValue();
+        if (responseText == null) {
+            throw new RuntimeException("ChatGPT thread message response content is null");
+        }
+        if (isJsonString(responseText)) {
+            return extractResponseContent(responseText);
+        }
+        return new AIChatResponseContent(responseText);
+    }
+
+    private AIChatResponseContent extractResponseContent(String responseText) {
+        return getGson().fromJson(unwrapJsonCode(responseText), AIChatResponseContent.class);
+    }
+}
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/aicodereview/mode/stateful/client/api/chatgpt/ChatGptAssistant.java
similarity index 66%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptAssistant.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/chatgpt/ChatGptAssistant.java
index 2c87ba0..7f99dff 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/aicodereview/mode/stateful/client/api/chatgpt/ChatGptAssistant.java
@@ -1,20 +1,20 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.chatgpt;
 
-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;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptTool;
-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.ChatGptPromptStatefulBase;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.model.api.chatgpt.*;
-import com.googlesource.gerrit.plugins.chatgpt.utils.HashUtils;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.data.PluginDataHandler;
+import com.googlesource.gerrit.plugins.aicodereview.data.PluginDataHandlerProvider;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.stateful.client.prompt.ChatGptPromptStateful;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.ClientBase;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.openai.AIChatParameters;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.openai.AIChatTools;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatTool;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.UriResourceLocatorStateful;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.git.GitRepoFiles;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.prompt.AIChatGptPromptStatefulBase;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.model.api.chatgpt.*;
+import com.googlesource.gerrit.plugins.aicodereview.utils.HashUtils;
 import lombok.extern.slf4j.Slf4j;
 import okhttp3.Request;
 
@@ -23,11 +23,11 @@
 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;
-import static com.googlesource.gerrit.plugins.chatgpt.utils.GsonUtils.getGson;
+import static com.googlesource.gerrit.plugins.aicodereview.mode.common.client.prompt.AIChatPromptFactory.getAIChatPromptStateful;
+import static com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.chatgpt.ChatGptVectorStore.KEY_VECTOR_STORE_ID;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.FileUtils.createTempFileWithContent;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.FileUtils.sanitizeFilename;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.GsonUtils.getGson;
 
 @Slf4j
 public class ChatGptAssistant extends ClientBase {
@@ -117,11 +117,11 @@
     }
 
     private Request createRequest(String vectorStoreId) {
-        URI uri = URI.create(config.getGptDomain() + UriResourceLocatorStateful.assistantCreateUri());
+        URI uri = URI.create(config.getAIDomain() + UriResourceLocatorStateful.assistantCreateUri());
         log.debug("ChatGPT Create Assistant request URI: {}", uri);
-        ChatGptTool[] tools = new ChatGptTool[] {
-                new ChatGptTool("file_search"),
-                ChatGptTools.retrieveFormatRepliesTool()
+        AIChatTool[] tools = new AIChatTool[] {
+                new AIChatTool("file_search"),
+                AIChatTools.retrieveFormatRepliesTool()
         };
         ChatGptToolResources toolResources = new ChatGptToolResources(
                 new ChatGptToolResources.VectorStoreIds(
@@ -129,7 +129,7 @@
                 )
         );
         ChatGptCreateAssistantRequestBody requestBody = ChatGptCreateAssistantRequestBody.builder()
-                .name(ChatGptPromptStatefulBase.DEFAULT_GPT_ASSISTANT_NAME)
+                .name(AIChatGptPromptStatefulBase.DEFAULT_AI_CHAT_ASSISTANT_NAME)
                 .description(description)
                 .instructions(instructions)
                 .model(model)
@@ -139,17 +139,17 @@
                 .build();
         log.debug("ChatGPT Create Assistant request body: {}", requestBody);
 
-        return httpClient.createRequestFromJson(uri.toString(), config.getGptToken(), requestBody);
+        return httpClient.createRequestFromJson(uri.toString(), config, requestBody);
     }
 
     private void setupAssistantParameters() {
-        IChatGptPromptStateful chatGptPromptStateful = getChatGptPromptStateful(config, changeSetData, change);
-        ChatGptParameters chatGptParameters = new ChatGptParameters(config, change.getIsCommentEvent());
+        ChatGptPromptStateful chatGptPromptStateful = getAIChatPromptStateful(config, changeSetData, change);
+        AIChatParameters AIChatParameters = new AIChatParameters(config, change.getIsCommentEvent());
 
         description = chatGptPromptStateful.getDefaultGptAssistantDescription();
         instructions = chatGptPromptStateful.getDefaultGptAssistantInstructions();
-        model = config.getGptModel();
-        temperature = chatGptParameters.getGptTemperature();
+        model = config.getAIModel();
+        temperature = AIChatParameters.getGptTemperature();
     }
 
     private String calculateAssistantIdHashKey() {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/chatgpt/ChatGptFiles.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/chatgpt/ChatGptFiles.java
new file mode 100644
index 0000000..22d1787
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/chatgpt/ChatGptFiles.java
@@ -0,0 +1,49 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.chatgpt;
+
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.ClientBase;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.http.HttpClient;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.UriResourceLocatorStateful;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.model.api.chatgpt.ChatGptFilesResponse;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.*;
+import org.apache.http.NameValuePair;
+
+import java.io.File;
+import java.net.URI;
+import java.nio.file.Path;
+
+import static com.googlesource.gerrit.plugins.aicodereview.utils.GsonUtils.getGson;
+
+@Slf4j
+public class ChatGptFiles extends ClientBase {
+    private final HttpClient httpClient = new HttpClient();
+
+    public ChatGptFiles(Configuration config) {
+        super(config);
+    }
+
+    public ChatGptFilesResponse uploadFiles(Path repoPath) {
+        Request request = createUploadFileRequest(repoPath);
+        log.debug("ChatGPT Upload Files request: {}", request);
+
+        String response = httpClient.execute(request);
+        log.debug("ChatGPT Upload Files response: {}", response);
+
+        return getGson().fromJson(response, ChatGptFilesResponse.class);
+    }
+
+    private Request createUploadFileRequest(Path repoPath) {
+        URI uri = URI.create(config.getAIDomain() + UriResourceLocatorStateful.filesCreateUri());
+        log.debug("ChatGPT Upload Files request URI: {}", uri);
+        File file = repoPath.toFile();
+        RequestBody requestBody = new MultipartBody.Builder()
+                .setType(MultipartBody.FORM)
+                .addFormDataPart("purpose", "assistants")
+                .addFormDataPart("file", file.getName(),
+                        RequestBody.create(file, MediaType.parse("application/json")))
+                .build();
+
+        return httpClient.createRequest(uri.toString(), config, requestBody, null);
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/chatgpt/ChatGptHttpClient.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/chatgpt/ChatGptHttpClient.java
new file mode 100644
index 0000000..2ccc552
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/chatgpt/ChatGptHttpClient.java
@@ -0,0 +1,15 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.chatgpt;
+
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.http.HttpClient;
+import okhttp3.Request;
+
+import java.util.Map;
+
+public class ChatGptHttpClient extends HttpClient {
+    private static final Map<String, String> BETA_VERSION_HEADER = Map.of("OpenAI-Beta", "assistants=v2");
+
+    public Request createRequestFromJson(String uri, Configuration configuration, Object requestObject) {
+        return createRequestFromJson(uri, configuration, requestObject, BETA_VERSION_HEADER);
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptRun.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/chatgpt/ChatGptRun.java
similarity index 77%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptRun.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/chatgpt/ChatGptRun.java
index 02c9b99..3325105 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptRun.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/chatgpt/ChatGptRun.java
@@ -1,23 +1,23 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.chatgpt;
 
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandlerProvider;
-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.ChatGptResponseMessage;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptToolCall;
-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.model.api.chatgpt.*;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.data.PluginDataHandlerProvider;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.ClientBase;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatResponseMessage;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatToolCall;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.UriResourceLocatorStateful;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.git.GitRepoFiles;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.model.api.chatgpt.*;
 import lombok.extern.slf4j.Slf4j;
 import okhttp3.Request;
 
 import java.net.URI;
 import java.util.*;
 
-import static com.googlesource.gerrit.plugins.chatgpt.utils.GsonUtils.getGson;
-import static com.googlesource.gerrit.plugins.chatgpt.utils.ThreadUtils.threadSleep;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.GsonUtils.getGson;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.ThreadUtils.threadSleep;
 
 @Slf4j
 public class ChatGptRun extends ClientBase {
@@ -95,11 +95,11 @@
         }
     }
 
-    public ChatGptResponseMessage getFirstStepDetails() {
+    public AIChatResponseMessage getFirstStepDetails() {
         return getFirstStep().getStepDetails();
     }
 
-    public List<ChatGptToolCall> getFirstStepToolCalls() {
+    public List<AIChatToolCall> getFirstStepToolCalls() {
         return getFirstStepDetails().getToolCalls();
     }
 
@@ -141,17 +141,17 @@
     }
 
     private Request runCreateRequest() {
-        URI uri = URI.create(config.getGptDomain() + UriResourceLocatorStateful.runsUri(threadId));
+        URI uri = URI.create(config.getAIDomain() + UriResourceLocatorStateful.runsUri(threadId));
         log.debug("ChatGPT Create Run request URI: {}", uri);
         ChatGptCreateRunRequest requestBody = ChatGptCreateRunRequest.builder()
                 .assistantId(assistantId)
                 .build();
 
-        return httpClient.createRequestFromJson(uri.toString(), config.getGptToken(), requestBody);
+        return httpClient.createRequestFromJson(uri.toString(), config, requestBody);
     }
 
     private Request getPollRequest() {
-        URI uri = URI.create(config.getGptDomain()
+        URI uri = URI.create(config.getAIDomain()
                 + UriResourceLocatorStateful.runRetrieveUri(threadId, runResponse.getId()));
         log.debug("ChatGPT Poll Run request URI: {}", uri);
 
@@ -159,7 +159,7 @@
     }
 
     private Request getStepsRequest() {
-        URI uri = URI.create(config.getGptDomain()
+        URI uri = URI.create(config.getAIDomain()
                 + UriResourceLocatorStateful.runStepsUri(threadId, runResponse.getId()));
         log.debug("ChatGPT Run Steps request URI: {}", uri);
 
@@ -167,14 +167,14 @@
     }
 
     private Request getCancelRequest() {
-        URI uri = URI.create(config.getGptDomain()
+        URI uri = URI.create(config.getAIDomain()
                 + UriResourceLocatorStateful.runCancelUri(threadId, runResponse.getId()));
         log.debug("ChatGPT Run Cancel request URI: {}", uri);
 
-        return httpClient.createRequestFromJson(uri.toString(), config.getGptToken(), new Object());
+        return httpClient.createRequestFromJson(uri.toString(), config, new Object());
     }
 
     private Request getRunPollRequest(URI uri) {
-        return httpClient.createRequestFromJson(uri.toString(), config.getGptToken(), null);
+        return httpClient.createRequestFromJson(uri.toString(), config, null);
     }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptThread.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/chatgpt/ChatGptThread.java
similarity index 66%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptThread.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/chatgpt/ChatGptThread.java
index 413bf98..c8740ca 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptThread.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/chatgpt/ChatGptThread.java
@@ -1,16 +1,16 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.chatgpt;
 
-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.mode.stateful.client.api.UriResourceLocatorStateful;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.model.api.chatgpt.ChatGptResponse;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.data.PluginDataHandler;
+import com.googlesource.gerrit.plugins.aicodereview.data.PluginDataHandlerProvider;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.UriResourceLocatorStateful;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.model.api.chatgpt.ChatGptResponse;
 import lombok.extern.slf4j.Slf4j;
 import okhttp3.Request;
 
 import java.net.URI;
 
-import static com.googlesource.gerrit.plugins.chatgpt.utils.GsonUtils.getGson;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.GsonUtils.getGson;
 
 @Slf4j
 public class ChatGptThread {
@@ -46,9 +46,9 @@
     }
 
     private Request createThreadRequest() {
-        URI uri = URI.create(config.getGptDomain() + UriResourceLocatorStateful.threadsUri());
+        URI uri = URI.create(config.getAIDomain() + UriResourceLocatorStateful.threadsUri());
         log.debug("ChatGPT Create Thread request URI: {}", uri);
 
-        return httpClient.createRequestFromJson(uri.toString(), config.getGptToken(), new Object());
+        return httpClient.createRequestFromJson(uri.toString(), config, new Object());
     }
 }
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/aicodereview/mode/stateful/client/api/chatgpt/ChatGptThreadMessage.java
similarity index 60%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptThreadMessage.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/chatgpt/ChatGptThreadMessage.java
index 9d961ac..fbfd3a6 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/aicodereview/mode/stateful/client/api/chatgpt/ChatGptThreadMessage.java
@@ -1,21 +1,21 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview.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.model.api.chatgpt.ChatGptResponse;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.model.api.chatgpt.ChatGptThreadMessageResponse;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.stateful.client.prompt.ChatGptPromptStateful;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.ClientBase;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatRequestMessage;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.UriResourceLocatorStateful;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.model.api.chatgpt.ChatGptResponse;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.model.api.chatgpt.ChatGptThreadMessageResponse;
 import lombok.extern.slf4j.Slf4j;
 import okhttp3.Request;
 
 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;
+import static com.googlesource.gerrit.plugins.aicodereview.mode.common.client.prompt.AIChatPromptFactory.getAIChatPromptStateful;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.GsonUtils.getGson;
 
 @Slf4j
 public class ChatGptThreadMessage extends ClientBase {
@@ -25,7 +25,7 @@
     private ChangeSetData changeSetData;
     private GerritChange change;
     private String patchSet;
-    private ChatGptRequestMessage addMessageRequestBody;
+    private AIChatRequestMessage addMessageRequestBody;
 
     public ChatGptThreadMessage(String threadId, Configuration config) {
         super(config);
@@ -69,23 +69,23 @@
     }
 
     private Request createRetrieveMessageRequest(String messageId) {
-        URI uri = URI.create(config.getGptDomain() +
+        URI uri = URI.create(config.getAIDomain() +
                 UriResourceLocatorStateful.threadMessageRetrieveUri(threadId, messageId));
         log.debug("ChatGPT Retrieve Thread Message request URI: {}", uri);
 
-        return httpClient.createRequestFromJson(uri.toString(), config.getGptToken(), null);
+        return httpClient.createRequestFromJson(uri.toString(), config, null);
     }
 
     private Request addMessageRequest() {
-        URI uri = URI.create(config.getGptDomain() + UriResourceLocatorStateful.threadMessagesUri(threadId));
+        URI uri = URI.create(config.getAIDomain() + UriResourceLocatorStateful.threadMessagesUri(threadId));
         log.debug("ChatGPT Add Message request URI: {}", uri);
-        IChatGptPromptStateful chatGptPromptStateful = getChatGptPromptStateful(config, changeSetData, change);
-        addMessageRequestBody = ChatGptRequestMessage.builder()
+        ChatGptPromptStateful chatGptPromptStateful = getAIChatPromptStateful(config, changeSetData, change);
+        addMessageRequestBody = AIChatRequestMessage.builder()
                 .role("user")
                 .content(chatGptPromptStateful.getDefaultGptThreadReviewMessage(patchSet))
                 .build();
         log.debug("ChatGPT Add Message request body: {}", addMessageRequestBody);
 
-        return httpClient.createRequestFromJson(uri.toString(), config.getGptToken(), addMessageRequestBody);
+        return httpClient.createRequestFromJson(uri.toString(), config, addMessageRequestBody);
     }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptVectorStore.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/chatgpt/ChatGptVectorStore.java
similarity index 66%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptVectorStore.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/chatgpt/ChatGptVectorStore.java
index 5f9d51d..a4be290 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptVectorStore.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/chatgpt/ChatGptVectorStore.java
@@ -1,16 +1,16 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.chatgpt;
 
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-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.stateful.client.api.UriResourceLocatorStateful;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.model.api.chatgpt.*;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.ClientBase;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.UriResourceLocatorStateful;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.model.api.chatgpt.*;
 import lombok.extern.slf4j.Slf4j;
 import okhttp3.Request;
 
 import java.net.URI;
 
-import static com.googlesource.gerrit.plugins.chatgpt.utils.GsonUtils.getGson;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.GsonUtils.getGson;
 
 @Slf4j
 public class ChatGptVectorStore extends ClientBase {
@@ -37,7 +37,7 @@
     }
 
     private Request vectorStoreCreateRequest() {
-        URI uri = URI.create(config.getGptDomain() + UriResourceLocatorStateful.vectorStoreCreateUri());
+        URI uri = URI.create(config.getAIDomain() + UriResourceLocatorStateful.vectorStoreCreateUri());
         log.debug("ChatGPT Create Vector Store request URI: {}", uri);
 
         ChatGptCreateVectorStoreRequest requestBody = ChatGptCreateVectorStoreRequest.builder()
@@ -46,6 +46,6 @@
                 .build();
 
         log.debug("ChatGPT Create Vector Store request body: {}", requestBody);
-        return httpClient.createRequestFromJson(uri.toString(), config.getGptToken(), requestBody);
+        return httpClient.createRequestFromJson(uri.toString(), config, requestBody);
     }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/gerrit/GerritClientPatchSetHelper.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/gerrit/GerritClientPatchSetHelper.java
similarity index 81%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/gerrit/GerritClientPatchSetHelper.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/gerrit/GerritClientPatchSetHelper.java
index 93e6e6c..87d0184 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/gerrit/GerritClientPatchSetHelper.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/gerrit/GerritClientPatchSetHelper.java
@@ -1,6 +1,6 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.gerrit;
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.gerrit;
 
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
 import lombok.extern.slf4j.Slf4j;
 
 import java.util.ArrayList;
@@ -8,8 +8,8 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import static com.googlesource.gerrit.plugins.chatgpt.settings.Settings.COMMIT_MESSAGE_FILTER_OUT_PREFIXES;
-import static com.googlesource.gerrit.plugins.chatgpt.settings.Settings.GERRIT_COMMIT_MESSAGE_PREFIX;
+import static com.googlesource.gerrit.plugins.aicodereview.settings.Settings.COMMIT_MESSAGE_FILTER_OUT_PREFIXES;
+import static com.googlesource.gerrit.plugins.aicodereview.settings.Settings.GERRIT_COMMIT_MESSAGE_PREFIX;
 
 @Slf4j
 public class GerritClientPatchSetHelper {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/gerrit/GerritClientPatchSetStateful.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/gerrit/GerritClientPatchSetStateful.java
similarity index 68%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/gerrit/GerritClientPatchSetStateful.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/gerrit/GerritClientPatchSetStateful.java
index f233dfd..13af663 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/gerrit/GerritClientPatchSetStateful.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/gerrit/GerritClientPatchSetStateful.java
@@ -1,22 +1,21 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.gerrit;
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.gerrit;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.gerrit.server.account.AccountCache;
 import com.google.gerrit.server.util.ManualRequestContext;
 import com.google.inject.Inject;
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.interfaces.mode.common.client.api.gerrit.IGerritClientPatchSet;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritClientPatchSet;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.common.client.api.gerrit.GerritClientPatchSet;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
 import lombok.extern.slf4j.Slf4j;
 
 import java.util.List;
 
-import static com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.gerrit.GerritClientPatchSetHelper.*;
+import static com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.gerrit.GerritClientPatchSetHelper.*;
 
 @Slf4j
-public class GerritClientPatchSetStateful extends GerritClientPatchSet implements IGerritClientPatchSet {
+public class GerritClientPatchSetStateful extends com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritClientPatchSet implements GerritClientPatchSet {
     private GerritChange change;
 
     @VisibleForTesting
@@ -55,7 +54,7 @@
     }
 
     private String filterPatch(String formattedPatch) {
-        if (config.getGptReviewCommitMessages()) {
+        if (config.getAIReviewCommitMessages()) {
             return filterPatchWithCommitMessage(formattedPatch);
         }
         else {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/git/GitRepoFiles.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/git/GitRepoFiles.java
similarity index 87%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/git/GitRepoFiles.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/git/GitRepoFiles.java
index d518049..b618a43 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/git/GitRepoFiles.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/api/git/GitRepoFiles.java
@@ -1,7 +1,7 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.git;
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.git;
 
-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.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
 import lombok.extern.slf4j.Slf4j;
 import org.eclipse.jgit.api.errors.GitAPIException;
 import org.eclipse.jgit.lib.*;
@@ -18,8 +18,8 @@
 import java.util.List;
 import java.util.Map;
 
-import static com.googlesource.gerrit.plugins.chatgpt.utils.FileUtils.matchesExtensionList;
-import static com.googlesource.gerrit.plugins.chatgpt.utils.GsonUtils.getGson;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.FileUtils.matchesExtensionList;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.GsonUtils.getGson;
 
 @Slf4j
 public class GitRepoFiles {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/prompt/AIChatDataPromptRequestsStateful.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/prompt/AIChatDataPromptRequestsStateful.java
new file mode 100644
index 0000000..25b4353
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/prompt/AIChatDataPromptRequestsStateful.java
@@ -0,0 +1,19 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.prompt;
+
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.common.client.prompt.ChatAIDataPrompt;
+import com.googlesource.gerrit.plugins.aicodereview.localization.Localizer;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.prompt.AIChatDataPromptRequests;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.GerritClientData;
+
+public class AIChatDataPromptRequestsStateful extends AIChatDataPromptRequests implements ChatAIDataPrompt {
+    public AIChatDataPromptRequestsStateful(
+            Configuration config,
+            ChangeSetData changeSetData,
+            GerritClientData gerritClientData,
+            Localizer localizer
+    ) {
+        super(config, changeSetData, gerritClientData, localizer);
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/prompt/AIChatGptPromptStatefulBase.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/prompt/AIChatGptPromptStatefulBase.java
new file mode 100644
index 0000000..d1df98b
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/prompt/AIChatGptPromptStatefulBase.java
@@ -0,0 +1,65 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.prompt;
+
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.stateful.client.prompt.ChatGptPromptStateful;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.prompt.AIChatGptPrompt;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.googlesource.gerrit.plugins.aicodereview.utils.TextUtils.*;
+
+@Slf4j
+public abstract class AIChatGptPromptStatefulBase extends AIChatGptPrompt implements ChatGptPromptStateful {
+    public static String DEFAULT_AI_CHAT_ASSISTANT_NAME;
+    public static String DEFAULT_AI_CHAT_ASSISTANT_DESCRIPTION;
+    public static String DEFAULT_AI_CHAT_ASSISTANT_INSTRUCTIONS;
+    public static String DEFAULT_AI_CHAT_MESSAGE_REVIEW;
+
+    protected final ChangeSetData changeSetData;
+
+    private final GerritChange change;
+
+    public AIChatGptPromptStatefulBase(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_AI_CHAT_ASSISTANT_NAME == null) {
+            loadDefaultPrompts("promptsStateful");
+        }
+    }
+
+    public String getDefaultGptAssistantDescription() {
+        return String.format(DEFAULT_AI_CHAT_ASSISTANT_DESCRIPTION, change.getProjectName());
+    }
+
+    public abstract void addGptAssistantInstructions(List<String> instructions);
+
+    public abstract String getAIRequestDataPrompt();
+
+    public String getDefaultGptAssistantInstructions() {
+        List<String> instructions = new ArrayList<>(List.of(
+                DEFAULT_AI_CHAT_SYSTEM_PROMPT + DOT,
+                String.format(DEFAULT_AI_CHAT_ASSISTANT_INSTRUCTIONS, change.getProjectName())
+        ));
+        addGptAssistantInstructions(instructions);
+
+        return joinWithSpace(instructions);
+    }
+
+    public String getDefaultGptThreadReviewMessage(String patchSet) {
+        String gptRequestDataPrompt = getAIRequestDataPrompt();
+        if (gptRequestDataPrompt != null && !gptRequestDataPrompt.isEmpty()) {
+            log.debug("Request User Prompt retrieved: {}", gptRequestDataPrompt);
+            return gptRequestDataPrompt;
+        }
+        else {
+            return String.format(DEFAULT_AI_CHAT_MESSAGE_REVIEW, patchSet);
+        }
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/prompt/AIChatGptPromptStatefulRequests.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/prompt/AIChatGptPromptStatefulRequests.java
new file mode 100644
index 0000000..9ccbbbd
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/prompt/AIChatGptPromptStatefulRequests.java
@@ -0,0 +1,35 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.prompt;
+
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.stateful.client.prompt.ChatGptPromptStateful;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.List;
+
+@Slf4j
+public class AIChatGptPromptStatefulRequests extends AIChatGptPromptStatefulBase implements ChatGptPromptStateful {
+    public static String DEFAULT_AI_CHAT_ASSISTANT_INSTRUCTIONS_REQUESTS;
+
+    public AIChatGptPromptStatefulRequests(Configuration config, ChangeSetData changeSetData, GerritChange change) {
+        super(config, changeSetData, change);
+        if (DEFAULT_AI_CHAT_ASSISTANT_INSTRUCTIONS_REQUESTS == null) {
+            loadDefaultPrompts("promptsStatefulRequests");
+        }
+    }
+
+    @Override
+    public void addGptAssistantInstructions(List<String> instructions) {
+       instructions.addAll(List.of(
+                DEFAULT_AI_CHAT_ASSISTANT_INSTRUCTIONS_REQUESTS,
+               getCommentRequestPrompt(changeSetData.getCommentPropertiesSize())
+        ));
+    }
+
+    @Override
+    public String getAIRequestDataPrompt() {
+        if (changeSetData == null ) return null;
+        return changeSetData.getReviewAIDataPrompt();
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/prompt/AIChatGptPromptStatefulReview.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/prompt/AIChatGptPromptStatefulReview.java
new file mode 100644
index 0000000..8f006d6
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/client/prompt/AIChatGptPromptStatefulReview.java
@@ -0,0 +1,55 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.prompt;
+
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.stateful.client.prompt.ChatGptPromptStateful;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.googlesource.gerrit.plugins.aicodereview.utils.TextUtils.*;
+
+@Slf4j
+public class AIChatGptPromptStatefulReview extends AIChatGptPromptStatefulBase implements ChatGptPromptStateful {
+    private static final String RULE_NUMBER_PREFIX = "RULE #";
+
+    public static String DEFAULT_AI_CHAT_ASSISTANT_INSTRUCTIONS_REVIEW;
+    public static String DEFAULT_AI_CHAT_ASSISTANT_INSTRUCTIONS_DONT_GUESS_CODE;
+    public static String DEFAULT_AI_CHAT_ASSISTANT_INSTRUCTIONS_HISTORY;
+
+    public AIChatGptPromptStatefulReview(Configuration config, ChangeSetData changeSetData, GerritChange change) {
+        super(config, changeSetData, change);
+        if (DEFAULT_AI_CHAT_ASSISTANT_INSTRUCTIONS_REVIEW == null) {
+            loadDefaultPrompts("promptsStatefulReview");
+        }
+    }
+
+    @Override
+    public void addGptAssistantInstructions(List<String> instructions) {
+        instructions.addAll(List.of(
+                getGptAssistantInstructionsReview(),
+                getPatchSetReviewPrompt()
+        ));
+        if (config.getAIReviewCommitMessages()) {
+            instructions.add(getReviewPromptCommitMessages());
+        }
+    }
+
+    @Override
+    public String getAIRequestDataPrompt() {
+        return null;
+    }
+
+    private String getGptAssistantInstructionsReview() {
+        return String.format(DEFAULT_AI_CHAT_ASSISTANT_INSTRUCTIONS_REVIEW, joinWithNewLine(getNumberedList(
+                new ArrayList<>(List.of(
+                        DEFAULT_AI_CHAT_PROMPT_FORCE_JSON_FORMAT,
+                        DEFAULT_AI_CHAT_ASSISTANT_INSTRUCTIONS_DONT_GUESS_CODE,
+                        DEFAULT_AI_CHAT_ASSISTANT_INSTRUCTIONS_HISTORY
+                )),
+                RULE_NUMBER_PREFIX, COLON_SPACE
+        )));
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptCreateAssistantRequestBody.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptCreateAssistantRequestBody.java
similarity index 65%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptCreateAssistantRequestBody.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptCreateAssistantRequestBody.java
index 6e85320..94c0df4 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptCreateAssistantRequestBody.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptCreateAssistantRequestBody.java
@@ -1,7 +1,7 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.model.api.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateful.model.api.chatgpt;
 
 import com.google.gson.annotations.SerializedName;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptTool;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatTool;
 import lombok.Builder;
 import lombok.Data;
 
@@ -13,7 +13,7 @@
     private String instructions;
     private String model;
     private Double temperature;
-    private ChatGptTool[] tools;
+    private AIChatTool[] tools;
     @SerializedName("tool_resources")
     private ChatGptToolResources toolResources;
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptCreateRunRequest.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptCreateRunRequest.java
similarity index 71%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptCreateRunRequest.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptCreateRunRequest.java
index bd3f7eb..0a0aae0 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptCreateRunRequest.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptCreateRunRequest.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.model.api.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateful.model.api.chatgpt;
 
 import com.google.gson.annotations.SerializedName;
 import lombok.Builder;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptCreateVectorStoreRequest.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptCreateVectorStoreRequest.java
similarity index 74%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptCreateVectorStoreRequest.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptCreateVectorStoreRequest.java
index aae613f..b755054 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptCreateVectorStoreRequest.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptCreateVectorStoreRequest.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.model.api.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateful.model.api.chatgpt;
 
 import com.google.gson.annotations.SerializedName;
 import lombok.Builder;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptFilesResponse.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptFilesResponse.java
similarity index 68%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptFilesResponse.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptFilesResponse.java
index e06838b..88d2cb6 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptFilesResponse.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptFilesResponse.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.model.api.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateful.model.api.chatgpt;
 
 import lombok.Data;
 import lombok.EqualsAndHashCode;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptListResponse.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptListResponse.java
similarity index 65%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptListResponse.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptListResponse.java
index 0c0ccd4..14363a7 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptListResponse.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptListResponse.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.model.api.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateful.model.api.chatgpt;
 
 import lombok.Data;
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptResponse.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptResponse.java
similarity index 61%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptResponse.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptResponse.java
index 7501d96..84d5ae5 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptResponse.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptResponse.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.model.api.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateful.model.api.chatgpt;
 
 import lombok.Data;
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptRunStepsResponse.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptRunStepsResponse.java
new file mode 100644
index 0000000..b70847a
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptRunStepsResponse.java
@@ -0,0 +1,13 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateful.model.api.chatgpt;
+
+import com.google.gson.annotations.SerializedName;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatResponseMessage;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class ChatGptRunStepsResponse extends ChatGptResponse {
+    @SerializedName("step_details")
+    private AIChatResponseMessage stepDetails;
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptThreadMessageResponse.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptThreadMessageResponse.java
similarity index 83%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptThreadMessageResponse.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptThreadMessageResponse.java
index 5f063ea..6c61254 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptThreadMessageResponse.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptThreadMessageResponse.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.model.api.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateful.model.api.chatgpt;
 
 import lombok.Data;
 import lombok.EqualsAndHashCode;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptToolResources.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptToolResources.java
similarity index 82%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptToolResources.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptToolResources.java
index 66bd3db..fcf268c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptToolResources.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateful/model/api/chatgpt/ChatGptToolResources.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.model.api.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateful.model.api.chatgpt;
 
 import com.google.gson.annotations.SerializedName;
 import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateless/client/api/UriResourceLocatorStateless.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateless/client/api/UriResourceLocatorStateless.java
new file mode 100644
index 0000000..1475dfc
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateless/client/api/UriResourceLocatorStateless.java
@@ -0,0 +1,44 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateless.client.api;
+
+
+import com.google.common.base.Strings;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+
+public class UriResourceLocatorStateless {
+
+    public static String getChatResourceUri(Configuration configuration) {
+        // different resource Uri endpoints exist for each aiType we support.
+        // some have backward compatible endpoints, but some do not.  This abstracts the knowledge
+        // of which to call for which aiType set in the configuration settings.
+        switch (configuration.getAIType()) {
+            case CHATGPT:
+            // ollama has an OpenAI compatible completions URI endpoint now,
+            // use so that the tools_calls format is used for returned data by default saving
+            // on loads more code changes in the response parsing.
+            case OLLAMA:
+                return chatCompletionsUri();
+
+            case AZUREOPENAI:
+                // TODO: add the endpoint information here, along with the additional query param with the version
+                // info - for testing use generic for now, but we will want to add the additional version info as another
+                // config element and then append the 2 together here.
+                throw new UnsupportedOperationException("AzureOpenAi endpoint not yet supported.");
+            case GENERIC:
+                // generic ai development will require you to override the endpoint if it doesn't support the existing
+                // chatCompletionsUri.. Usually you will provide the optional chatEndpoint configuration option.
+                final String chatEndpoint = configuration.getChatEndpoint();
+                // fallback onto chatCompletions api if nothing has been specified.
+                return Strings.isNullOrEmpty(chatEndpoint) ? chatCompletionsUri() : chatEndpoint;
+            default:
+                throw new UnsupportedOperationException("Unsupported aiType, chat resource endpoint not yet described.");
+        }
+    }
+
+    public static String chatCompletionsUri() {
+        return "/v1/chat/completions";
+    }
+
+    public static String ollamaChatUri() {
+        return "/api/chat";
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateless/client/api/chatai/AIChatClientStateless.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateless/client/api/chatai/AIChatClientStateless.java
new file mode 100644
index 0000000..36adbe5
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateless/client/api/chatai/AIChatClientStateless.java
@@ -0,0 +1,117 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateless.client.api.chatai;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.net.HttpHeaders;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.common.client.api.openapi.ChatAIClient;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.openai.AIChatClient;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.openai.AIChatParameters;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.openai.AIChatTools;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.http.HttpClientWithRetry;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.*;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateless.client.api.UriResourceLocatorStateless;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateless.client.prompt.AIChatPromptStateless;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateless.model.api.chatgpt.ChatGptCompletionRequest;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.NameValuePair;
+import org.apache.http.entity.ContentType;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.util.List;
+
+import static com.googlesource.gerrit.plugins.aicodereview.utils.GsonUtils.getNoEscapedGson;
+
+@Slf4j
+@Singleton
+public class AIChatClientStateless extends AIChatClient implements ChatAIClient {
+    private static final int REVIEW_ATTEMPT_LIMIT = 3;
+
+    private final HttpClientWithRetry httpClientWithRetry = new HttpClientWithRetry();
+
+    @VisibleForTesting
+    @Inject
+    public AIChatClientStateless(Configuration config) {
+        super(config);
+    }
+
+    public AIChatResponseContent ask(ChangeSetData changeSetData, GerritChange change, String patchSet)
+            throws Exception {
+        isCommentEvent = change.getIsCommentEvent();
+        String changeId = change.getFullChangeId();
+        log.info("Processing STATELESS ChatGPT Request with changeId: {}, Patch Set: {}", changeId, patchSet);
+        for (int attemptInd = 0; attemptInd < REVIEW_ATTEMPT_LIMIT; attemptInd++) {
+            HttpRequest request = createRequest(config, changeSetData, patchSet);
+            log.debug("ChatGPT request: {}", request.toString());
+
+            HttpResponse<String> response = httpClientWithRetry.execute(request);
+
+            String body = response.body();
+            log.debug("ChatGPT response body: {}", body);
+            if (body == null) {
+                throw new IOException("ChatGPT response body is null");
+            }
+
+            AIChatResponseContent contentExtracted = extractContent(config, body);
+            if (validateResponse(contentExtracted, changeId, attemptInd)) {
+                return contentExtracted;
+            }
+        }
+        throw new RuntimeException("Failed to receive valid ChatGPT response");
+    }
+
+    protected HttpRequest createRequest(Configuration config, ChangeSetData changeSetData, String patchSet) {
+        URI uri = URI.create(config.getAIDomain() + UriResourceLocatorStateless.getChatResourceUri(config));
+        log.debug("AIChat request URI: {}", uri);
+        requestBody = createRequestBody(config, changeSetData, patchSet);
+        log.debug("AIChat request body: {}", requestBody);
+
+        HttpRequest.Builder builder = HttpRequest.newBuilder()
+                .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
+                .uri(uri)
+                .POST(HttpRequest.BodyPublishers.ofString(requestBody));
+
+        // depending on the aiType, add appropriate authorization header ( if required ).
+        NameValuePair authHeader = config.getAuthorizationHeaderInfo();
+        if (authHeader != null) {
+            builder.header(authHeader.getName(), authHeader.getValue());
+        }
+        return builder.build();
+    }
+
+    private String createRequestBody(Configuration config, ChangeSetData changeSetData, String patchSet) {
+        AIChatPromptStateless AIChatPromptStateless = new AIChatPromptStateless(config, isCommentEvent);
+        AIChatRequestMessage systemMessage = AIChatRequestMessage.builder()
+                .role("system")
+                .content(AIChatPromptStateless.getAISystemPrompt())
+                .build();
+        AIChatRequestMessage userMessage = AIChatRequestMessage.builder()
+                .role("user")
+                .content(AIChatPromptStateless.getGptUserPrompt(changeSetData, patchSet))
+                .build();
+
+        AIChatParameters AIChatParameters = new AIChatParameters(config, isCommentEvent);
+        AIChatTool[] tools = new AIChatTool[]{
+                AIChatTools.retrieveFormatRepliesTool()
+        };
+        ChatGptCompletionRequest chatGptCompletionRequest = ChatGptCompletionRequest.builder()
+                .model(config.getAIModel())
+                .messages(List.of(systemMessage, userMessage))
+                .temperature(AIChatParameters.getGptTemperature())
+                .stream(AIChatParameters.getStreamOutput())
+                // Seed value is Utilized to prevent ChatGPT from mixing up separate API calls that occur in close
+                // temporal proximity.
+                .seed(AIChatParameters.getRandomSeed())
+                .tools(tools)
+                .toolChoice(AIChatTools.retrieveFormatRepliesToolChoice())
+                .build();
+
+        return getNoEscapedGson().toJson(chatGptCompletionRequest);
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateless/client/api/gerrit/GerritClientPatchSetStateless.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateless/client/api/gerrit/GerritClientPatchSetStateless.java
similarity index 80%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateless/client/api/gerrit/GerritClientPatchSetStateless.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateless/client/api/gerrit/GerritClientPatchSetStateless.java
index 0ecdaa4..ad8e28c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateless/client/api/gerrit/GerritClientPatchSetStateless.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateless/client/api/gerrit/GerritClientPatchSetStateless.java
@@ -1,15 +1,14 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateless.client.api.gerrit;
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateless.client.api.gerrit;
 
 import com.google.inject.Inject;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.gerrit.extensions.common.FileInfo;
 import com.google.gerrit.server.account.AccountCache;
 import com.google.gerrit.server.util.ManualRequestContext;
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.interfaces.mode.common.client.api.gerrit.IGerritClientPatchSet;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritClientPatchSet;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.common.client.api.gerrit.GerritClientPatchSet;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
 import lombok.extern.slf4j.Slf4j;
 
 import static java.util.stream.Collectors.toList;
@@ -18,7 +17,7 @@
 import java.util.Map;
 
 @Slf4j
-public class GerritClientPatchSetStateless extends GerritClientPatchSet implements IGerritClientPatchSet {
+public class GerritClientPatchSetStateless extends com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritClientPatchSet implements GerritClientPatchSet {
     @VisibleForTesting
     @Inject
     public GerritClientPatchSetStateless(Configuration config, AccountCache accountCache) {
@@ -54,7 +53,7 @@
                 .filter(
                     fileEntry -> {
                       String filename = fileEntry.getKey();
-                      if (!filename.equals("/COMMIT_MSG") || config.getGptReviewCommitMessages()) {
+                      if (!filename.equals("/COMMIT_MSG") || config.getAIReviewCommitMessages()) {
                         if (fileEntry.getValue().size > config.getMaxReviewFileSize()) {
                           log.info(
                               "File '{}' not reviewed because its size exceeds the fixed maximum allowable size.",
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateless/client/prompt/AIChatDataPromptRequestsStateless.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateless/client/prompt/AIChatDataPromptRequestsStateless.java
new file mode 100644
index 0000000..2011a3f
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateless/client/prompt/AIChatDataPromptRequestsStateless.java
@@ -0,0 +1,29 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateless.client.prompt;
+
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.common.client.prompt.ChatAIDataPrompt;
+import com.googlesource.gerrit.plugins.aicodereview.localization.Localizer;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.prompt.AIChatDataPromptRequests;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatMessageItem;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.GerritClientData;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class AIChatDataPromptRequestsStateless extends AIChatDataPromptRequests implements ChatAIDataPrompt {
+    public AIChatDataPromptRequestsStateless(
+            Configuration config,
+            ChangeSetData changeSetData,
+            GerritClientData gerritClientData,
+            Localizer localizer
+    ) {
+        super(config, changeSetData, gerritClientData, localizer);
+    }
+
+    protected AIChatMessageItem getMessageItem(int i) {
+        super.getMessageItem(i);
+        setHistory(messageItem, messageHistory);
+
+        return messageItem;
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateless/client/prompt/AIChatPromptStateless.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateless/client/prompt/AIChatPromptStateless.java
new file mode 100644
index 0000000..e07ac2b
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateless/client/prompt/AIChatPromptStateless.java
@@ -0,0 +1,103 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateless.client.prompt;
+
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.prompt.AIChatGptPrompt;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static com.googlesource.gerrit.plugins.aicodereview.utils.TextUtils.*;
+
+@Slf4j
+public class AIChatPromptStateless extends AIChatGptPrompt {
+    public static String DEFAULT_AI_CHAT_SYSTEM_PROMPT_INPUT_DESCRIPTION;
+    public static String DEFAULT_AI_CHAT_SYSTEM_PROMPT_INPUT_DESCRIPTION_REVIEW;
+    public static String DEFAULT_AI_CHAT_REVIEW_PROMPT;
+    public static String DEFAULT_AI_CHAT_REVIEW_PROMPT_REVIEW;
+    public static String DEFAULT_AI_CHAT_REVIEW_PROMPT_MESSAGE_HISTORY;
+    public static String DEFAULT_AI_CHAT_REVIEW_PROMPT_DIFF;
+
+    public AIChatPromptStateless(Configuration config) {
+        super(config);
+        loadStatelessPrompts();
+    }
+
+    public AIChatPromptStateless(Configuration config, boolean isCommentEvent) {
+        super(config, isCommentEvent);
+        loadStatelessPrompts();
+    }
+
+    public static String getDefaultGptReviewSystemPrompt() {
+        return joinWithSpace(new ArrayList<>(List.of(
+                DEFAULT_AI_CHAT_SYSTEM_PROMPT + DOT,
+                DEFAULT_AI_CHAT_SYSTEM_PROMPT_INPUT_DESCRIPTION,
+                DEFAULT_AI_CHAT_SYSTEM_PROMPT_INPUT_DESCRIPTION_REVIEW
+        )));
+    }
+
+    public String getAISystemPrompt() {
+        List<String> prompt = new ArrayList<>(Arrays.asList(
+                config.getString(Configuration.KEY_AI_SYSTEM_PROMPT, DEFAULT_AI_CHAT_SYSTEM_PROMPT) + DOT,
+                AIChatPromptStateless.DEFAULT_AI_CHAT_SYSTEM_PROMPT_INPUT_DESCRIPTION
+        ));
+        if (!isCommentEvent) {
+            prompt.add(AIChatPromptStateless.DEFAULT_AI_CHAT_SYSTEM_PROMPT_INPUT_DESCRIPTION_REVIEW);
+        }
+        return joinWithSpace(prompt);
+    }
+
+    public String getGptUserPrompt(ChangeSetData changeSetData, String patchSet) {
+        List<String> prompt = new ArrayList<>();
+        String gptRequestDataPrompt = changeSetData.getReviewAIDataPrompt();
+        boolean isValidRequestDataPrompt = gptRequestDataPrompt != null && !gptRequestDataPrompt.isEmpty();
+        if (isCommentEvent && isValidRequestDataPrompt) {
+            log.debug("Request User Prompt retrieved: {}", gptRequestDataPrompt);
+            prompt.addAll(Arrays.asList(
+                    DEFAULT_AI_CHAT_REQUEST_PROMPT_DIFF,
+                    patchSet,
+                    DEFAULT_AI_CHAT_REQUEST_PROMPT_REQUESTS,
+                    gptRequestDataPrompt,
+                    getCommentRequestPrompt(changeSetData.getCommentPropertiesSize())
+            ));
+        }
+        else {
+            prompt.add(AIChatPromptStateless.DEFAULT_AI_CHAT_REVIEW_PROMPT);
+            prompt.addAll(getReviewSteps());
+            prompt.add(AIChatPromptStateless.DEFAULT_AI_CHAT_REVIEW_PROMPT_DIFF);
+            prompt.add(patchSet);
+            if (isValidRequestDataPrompt) {
+                prompt.add(AIChatPromptStateless.DEFAULT_AI_CHAT_REVIEW_PROMPT_MESSAGE_HISTORY);
+                prompt.add(gptRequestDataPrompt);
+            }
+            if (!changeSetData.getDirectives().isEmpty()) {
+                prompt.add(DEFAULT_AI_CHAT_REVIEW_PROMPT_DIRECTIVES);
+                prompt.add(getNumberedListString(new ArrayList<>(changeSetData.getDirectives()), null, null));
+            }
+        }
+        return joinWithNewLine(prompt);
+    }
+
+    private void loadStatelessPrompts() {
+        // Avoid repeated loading of prompt constants
+        if (DEFAULT_AI_CHAT_SYSTEM_PROMPT_INPUT_DESCRIPTION == null) {
+            loadDefaultPrompts("promptsStateless");
+        }
+    }
+
+    private List<String> getReviewSteps() {
+        List<String> steps = new ArrayList<>(List.of(
+                joinWithSpace(new ArrayList<>(List.of(
+                        DEFAULT_AI_CHAT_REVIEW_PROMPT_REVIEW,
+                        DEFAULT_AI_CHAT_PROMPT_FORCE_JSON_FORMAT,
+                        getPatchSetReviewPrompt()
+                )))
+        ));
+        if (config.getAIReviewCommitMessages()) {
+            steps.add(getReviewPromptCommitMessages());
+        }
+        return steps;
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateless/model/api/chatgpt/ChatGptCompletionRequest.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateless/model/api/chatgpt/ChatGptCompletionRequest.java
new file mode 100644
index 0000000..a65e0a9
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/mode/stateless/model/api/chatgpt/ChatGptCompletionRequest.java
@@ -0,0 +1,23 @@
+package com.googlesource.gerrit.plugins.aicodereview.mode.stateless.model.api.chatgpt;
+
+import com.google.gson.annotations.SerializedName;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatRequestMessage;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatTool;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatToolChoice;
+import lombok.Builder;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@Builder
+public class ChatGptCompletionRequest {
+    private String model;
+    private boolean stream;
+    private double temperature;
+    private int seed;
+    private List<AIChatRequestMessage> messages;
+    private AIChatTool[] tools;
+    @SerializedName("tool_choice")
+    private AIChatToolChoice toolChoice;
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/aicodereview/settings/Settings.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/settings/Settings.java
new file mode 100644
index 0000000..00dc4c5
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/settings/Settings.java
@@ -0,0 +1,36 @@
+package com.googlesource.gerrit.plugins.aicodereview.settings;
+
+import java.util.Map;
+
+public class Settings {
+    public static final String GERRIT_PATCH_SET_FILENAME = "/PATCHSET_LEVEL";
+    public static final String GERRIT_DEFAULT_MESSAGE_DONE = "Done";
+    public static final String GERRIT_AUTOGENERATED_PREFIX = "autogenerated:";
+    public static final Map<String , String> COMMIT_MESSAGE_FILTER_OUT_PREFIXES = Map.of(
+            "PARENT","Parent:",
+            "AUTHOR","Author:",
+            "AUTHOR_DATE", "AuthorDate:",
+            "COMMIT","Commit:",
+            "COMMIT_DATE", "CommitDate:",
+            "CHANGE_ID", "Change-Id:"
+    );
+    public static final String GERRIT_COMMIT_MESSAGE_PREFIX = "Subject: ";
+
+    public static final String OPEN_AI_CHAT_ROLE_USER = "user";
+    public static final String OPEN_AI_CHAT_ROLE_ASSISTANT = "assistant";
+
+    public enum Modes {
+        stateless,
+        stateful
+    }
+
+    public enum AIType {
+        CHATGPT,
+        OLLAMA,
+        AZUREOPENAI,
+
+        // used for testing new endpoints and ai services not yet in the supported list, but you can specify the
+        // endpoint, the authorization header information, and the prompt to quickly prove out a new aiType.
+        GENERIC;
+    }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/utils/FileUtils.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/utils/FileUtils.java
similarity index 95%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/utils/FileUtils.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/utils/FileUtils.java
index e37c4bd..bad1db3 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/utils/FileUtils.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/utils/FileUtils.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.utils;
+package com.googlesource.gerrit.plugins.aicodereview.utils;
 
 import java.io.IOException;
 import java.io.InputStreamReader;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/utils/GsonUtils.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/utils/GsonUtils.java
similarity index 83%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/utils/GsonUtils.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/utils/GsonUtils.java
index 9598a7d..82d665c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/utils/GsonUtils.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/utils/GsonUtils.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.utils;
+package com.googlesource.gerrit.plugins.aicodereview.utils;
 
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/utils/HashUtils.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/utils/HashUtils.java
similarity index 95%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/utils/HashUtils.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/utils/HashUtils.java
index 7e9840c..4c09f76 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/utils/HashUtils.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/utils/HashUtils.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.utils;
+package com.googlesource.gerrit.plugins.aicodereview.utils;
 
 import java.nio.charset.StandardCharsets;
 import java.security.MessageDigest;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/utils/JsonTextUtils.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/utils/JsonTextUtils.java
similarity index 91%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/utils/JsonTextUtils.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/utils/JsonTextUtils.java
index e03ca7b..d1b35a8 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/utils/JsonTextUtils.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/utils/JsonTextUtils.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.utils;
+package com.googlesource.gerrit.plugins.aicodereview.utils;
 
 import lombok.extern.slf4j.Slf4j;
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/utils/StringUtils.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/utils/StringUtils.java
similarity index 91%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/utils/StringUtils.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/utils/StringUtils.java
index 11edecf..dd7a9c0 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/utils/StringUtils.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/utils/StringUtils.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.utils;
+package com.googlesource.gerrit.plugins.aicodereview.utils;
 
 import lombok.extern.slf4j.Slf4j;
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/utils/TextUtils.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/utils/TextUtils.java
similarity index 98%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/utils/TextUtils.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/utils/TextUtils.java
index e4f41e8..f70b4a4 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/utils/TextUtils.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/utils/TextUtils.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.utils;
+package com.googlesource.gerrit.plugins.aicodereview.utils;
 
 import lombok.extern.slf4j.Slf4j;
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/utils/ThreadUtils.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/utils/ThreadUtils.java
similarity index 83%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/utils/ThreadUtils.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/utils/ThreadUtils.java
index f452649..6ee8aac 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/utils/ThreadUtils.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/utils/ThreadUtils.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.utils;
+package com.googlesource.gerrit.plugins.aicodereview.utils;
 
 public class ThreadUtils {
     public static void threadSleep(long millis) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/utils/TimeUtils.java b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/utils/TimeUtils.java
similarity index 88%
rename from src/main/java/com/googlesource/gerrit/plugins/chatgpt/utils/TimeUtils.java
rename to src/main/java/com/googlesource/gerrit/plugins/aicodereview/utils/TimeUtils.java
index 623f6fe..8d7b0c5 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/utils/TimeUtils.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/aicodereview/utils/TimeUtils.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt.utils;
+package com.googlesource.gerrit.plugins.aicodereview.utils;
 
 import java.time.LocalDateTime;
 import java.time.ZoneOffset;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/interfaces/mode/common/client/api/chatgpt/IChatGptClient.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/interfaces/mode/common/client/api/chatgpt/IChatGptClient.java
deleted file mode 100644
index d6803b4..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/interfaces/mode/common/client/api/chatgpt/IChatGptClient.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.interfaces.mode.common.client.api.chatgpt;
-
-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.model.api.chatgpt.ChatGptResponseContent;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
-
-public interface IChatGptClient {
-    ChatGptResponseContent ask(ChangeSetData changeSetData, GerritChange change, String patchSet)
-            throws Exception;
-    String getRequestBody();
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/interfaces/mode/common/client/api/gerrit/IGerritClientPatchSet.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/interfaces/mode/common/client/api/gerrit/IGerritClientPatchSet.java
deleted file mode 100644
index d4fe8f7..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/interfaces/mode/common/client/api/gerrit/IGerritClientPatchSet.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.interfaces.mode.common.client.api.gerrit;
-
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.patch.diff.FileDiffProcessed;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
-
-import java.util.HashMap;
-
-public interface IGerritClientPatchSet {
-    String getPatchSet(ChangeSetData changeSetData, GerritChange gerritChange) throws Exception;
-    boolean isDisabledUser(String authorUsername);
-    boolean isDisabledTopic(String topic);
-    void retrieveRevisionBase(GerritChange change);
-    Integer getNotNullAccountId(String authorUsername);
-    HashMap<String, FileDiffProcessed> getFileDiffsProcessed();
-    Integer getRevisionBase();
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/interfaces/mode/common/client/prompt/IChatGptDataPrompt.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/interfaces/mode/common/client/prompt/IChatGptDataPrompt.java
deleted file mode 100644
index d226c5b..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/interfaces/mode/common/client/prompt/IChatGptDataPrompt.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.interfaces.mode.common.client.prompt;
-
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptMessageItem;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritComment;
-
-import java.util.List;
-
-public interface IChatGptDataPrompt {
-    void addMessageItem(int i);
-    List<GerritComment> getCommentProperties();
-    List<ChatGptMessageItem> getMessageItems();
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTypeChangeMerged.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTypeChangeMerged.java
deleted file mode 100644
index 8b82e56..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/EventHandlerTypeChangeMerged.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.listener;
-
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandlerProvider;
-import com.googlesource.gerrit.plugins.chatgpt.interfaces.listener.IEventHandlerType;
-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.stateful.client.api.chatgpt.ChatGptAssistant;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.git.GitRepoFiles;
-import lombok.extern.slf4j.Slf4j;
-
-@Slf4j
-public class EventHandlerTypeChangeMerged implements IEventHandlerType {
-    private final Configuration config;
-    private final ChangeSetData changeSetData;
-    private final GerritChange change;
-    private final GitRepoFiles gitRepoFiles;
-    private final PluginDataHandlerProvider pluginDataHandlerProvider;
-
-    EventHandlerTypeChangeMerged(
-            Configuration config,
-            ChangeSetData changeSetData,
-            GerritChange change,
-            GitRepoFiles gitRepoFiles,
-            PluginDataHandlerProvider pluginDataHandlerProvider
-    ) {
-        this.config = config;
-        this.changeSetData = changeSetData;
-        this.change = change;
-        this.gitRepoFiles = gitRepoFiles;
-        this.pluginDataHandlerProvider = pluginDataHandlerProvider;
-    }
-
-    @Override
-    public PreprocessResult preprocessEvent() {
-        return PreprocessResult.OK;
-    }
-
-    @Override
-    public void processEvent() {
-        ChatGptAssistant chatGptAssistant = new ChatGptAssistant(
-                config,
-                changeSetData,
-                change,
-                gitRepoFiles,
-                pluginDataHandlerProvider
-        );
-        chatGptAssistant.flushAssistantIds();
-        chatGptAssistant.createVectorStore();
-    }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/GerritEventContextModule.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/GerritEventContextModule.java
deleted file mode 100644
index 5d143b4..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/listener/GerritEventContextModule.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.listener;
-
-import com.google.gerrit.extensions.config.FactoryModule;
-import com.google.gerrit.server.events.Event;
-import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.data.ChangeSetDataProvider;
-import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandler;
-import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandlerProvider;
-import com.googlesource.gerrit.plugins.chatgpt.interfaces.mode.common.client.api.chatgpt.IChatGptClient;
-import com.googlesource.gerrit.plugins.chatgpt.interfaces.mode.common.client.api.gerrit.IGerritClientPatchSet;
-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.stateful.client.api.chatgpt.ChatGptClientStateful;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.gerrit.GerritClientPatchSetStateful;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateless.client.api.chatgpt.ChatGptClientStateless;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateless.client.api.gerrit.GerritClientPatchSetStateless;
-
-import static com.google.inject.Scopes.SINGLETON;
-
-public class GerritEventContextModule extends FactoryModule {
-    private final Event event;
-    private final Configuration config;
-
-    public GerritEventContextModule(Configuration config, Event event) {
-        this.event = event;
-        this.config = config;
-    }
-
-    @Override
-    protected void configure() {
-        bind(IChatGptClient.class).to(getChatGptMode());
-        bind(IGerritClientPatchSet.class).to(getClientPatchSet());
-
-        bind(Configuration.class).toInstance(config);
-        bind(GerritChange.class).toInstance(new GerritChange(event));
-        bind(ChangeSetData.class).toProvider(ChangeSetDataProvider.class).in(SINGLETON);
-        bind(PluginDataHandler.class).toProvider(PluginDataHandlerProvider.class).in(Singleton.class);
-    }
-
-    private Class<? extends IChatGptClient> getChatGptMode() {
-        return switch (config.getGptMode()){
-            case stateful -> ChatGptClientStateful.class;
-            case stateless -> ChatGptClientStateless.class;
-        };
-    }
-
-    private Class<? extends IGerritClientPatchSet> getClientPatchSet() {
-        return switch (config.getGptMode()){
-            case stateful -> GerritClientPatchSetStateful.class;
-            case stateless -> GerritClientPatchSetStateless.class;
-        };
-    }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/ClientBase.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/ClientBase.java
deleted file mode 100644
index edb6bb7..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/ClientBase.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client;
-
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-
-public abstract class ClientBase {
-    protected Configuration config;
-
-    public ClientBase(Configuration config) {
-        this.config = config;
-    }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/chatgpt/ChatGptClient.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/chatgpt/ChatGptClient.java
deleted file mode 100644
index f6e10fb..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/chatgpt/ChatGptClient.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.chatgpt;
-
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.ClientBase;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.*;
-
-import lombok.Getter;
-import lombok.extern.slf4j.Slf4j;
-
-import java.io.BufferedReader;
-import java.io.StringReader;
-import java.util.List;
-import java.util.Optional;
-
-import static com.googlesource.gerrit.plugins.chatgpt.utils.GsonUtils.getGson;
-
-@Slf4j
-abstract public class ChatGptClient extends ClientBase {
-    protected boolean isCommentEvent = false;
-    @Getter
-    protected String requestBody;
-
-    public ChatGptClient(Configuration config) {
-        super(config);
-    }
-
-    protected ChatGptResponseContent extractContent(Configuration config, String body) throws Exception {
-        if (config.getGptStreamOutput() && !isCommentEvent) {
-            StringBuilder finalContent = new StringBuilder();
-            try (BufferedReader reader = new BufferedReader(new StringReader(body))) {
-                String line;
-                while ((line = reader.readLine()) != null) {
-                    extractContentFromLine(line).ifPresent(finalContent::append);
-                }
-            }
-            return convertResponseContentFromJson(finalContent.toString());
-        }
-        else {
-            ChatGptResponseUnstreamed chatGptResponseUnstreamed =
-                    getGson().fromJson(body, ChatGptResponseUnstreamed.class);
-            return getResponseContent(chatGptResponseUnstreamed.getChoices().get(0).getMessage().getToolCalls());
-        }
-    }
-
-    protected boolean validateResponse(ChatGptResponseContent chatGptResponseContent, String changeId, int attemptInd) {
-        String returnedChangeId = chatGptResponseContent.getChangeId();
-        // A response is considered valid if either no changeId is returned or the changeId returned matches the one
-        // provided in the request
-        boolean isValidated = returnedChangeId == null || changeId.equals(returnedChangeId);
-        if (!isValidated) {
-            log.error("ChangedId mismatch error (attempt #{}).\nExpected value: {}\nReturned value: {}", attemptInd,
-                    changeId, returnedChangeId);
-        }
-        return isValidated;
-    }
-
-    protected ChatGptResponseContent getResponseContent(List<ChatGptToolCall> toolCalls) {
-        if (toolCalls.size() > 1) {
-            return mergeToolCalls(toolCalls);
-        } else {
-            return getArgumentAsResponse(toolCalls, 0);
-        }
-    }
-
-    protected Optional<String> extractContentFromLine(String line) {
-        String dataPrefix = "data: {\"id\"";
-
-        if (!line.startsWith(dataPrefix)) {
-            return Optional.empty();
-        }
-        ChatGptResponseStreamed chatGptResponseStreamed =
-                getGson().fromJson(line.substring("data: ".length()), ChatGptResponseStreamed.class);
-        ChatGptResponseMessage delta = chatGptResponseStreamed.getChoices().get(0).getDelta();
-        if (delta == null || delta.getToolCalls() == null) {
-            return Optional.empty();
-        }
-        String content = getArgumentAsString(delta.getToolCalls(), 0);
-        return Optional.ofNullable(content);
-    }
-
-    private ChatGptResponseContent convertResponseContentFromJson(String content) {
-        return getGson().fromJson(content, ChatGptResponseContent.class);
-    }
-
-    private String getArgumentAsString(List<ChatGptToolCall> toolCalls, int ind) {
-        return toolCalls.get(ind).getFunction().getArguments();
-    }
-
-    private ChatGptResponseContent getArgumentAsResponse(List<ChatGptToolCall> toolCalls, int ind) {
-        return convertResponseContentFromJson(getArgumentAsString(toolCalls, ind));
-    }
-
-    private ChatGptResponseContent mergeToolCalls(List<ChatGptToolCall> toolCalls) {
-        ChatGptResponseContent responseContent = getArgumentAsResponse(toolCalls, 0);
-        for (int ind = 1; ind < toolCalls.size(); ind++) {
-            responseContent.getReplies().addAll(
-                    getArgumentAsResponse(toolCalls, ind).getReplies()
-            );
-        }
-        return responseContent;
-    }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/chatgpt/ChatGptParameters.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/chatgpt/ChatGptParameters.java
deleted file mode 100644
index c73dcb1..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/chatgpt/ChatGptParameters.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.chatgpt;
-
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.ClientBase;
-
-import java.util.concurrent.ThreadLocalRandom;
-
-public class ChatGptParameters extends ClientBase {
-    private static boolean isCommentEvent;
-
-    public ChatGptParameters(Configuration config, boolean isCommentEvent) {
-        super(config);
-        ChatGptParameters.isCommentEvent = isCommentEvent;
-    }
-
-    public double getGptTemperature() {
-        if (isCommentEvent) {
-            return retrieveTemperature(Configuration.KEY_GPT_COMMENT_TEMPERATURE,
-                    Configuration.DEFAULT_GPT_COMMENT_TEMPERATURE);
-        }
-       else {
-            return retrieveTemperature(Configuration.KEY_GPT_REVIEW_TEMPERATURE,
-                    Configuration.DEFAULT_GPT_REVIEW_TEMPERATURE);
-        }
-    }
-
-    public boolean getStreamOutput() {
-        return config.getGptStreamOutput() && !isCommentEvent;
-    }
-
-    public int getRandomSeed() {
-        return ThreadLocalRandom.current().nextInt();
-    }
-
-    private Double retrieveTemperature(String temperatureKey, Double defaultTemperature) {
-        return Double.parseDouble(config.getString(temperatureKey, String.valueOf(defaultTemperature)));
-    }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/chatgpt/ChatGptTools.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/chatgpt/ChatGptTools.java
deleted file mode 100644
index b41cf1d..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/chatgpt/ChatGptTools.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.chatgpt;
-
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptTool;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptToolChoice;
-import com.googlesource.gerrit.plugins.chatgpt.utils.FileUtils;
-
-import java.io.IOException;
-import java.io.InputStreamReader;
-
-import static com.googlesource.gerrit.plugins.chatgpt.utils.GsonUtils.getGson;
-
-public class ChatGptTools {
-    public static ChatGptTool retrieveFormatRepliesTool() {
-        ChatGptTool tools;
-        try (InputStreamReader reader = FileUtils.getInputStreamReader("config/formatRepliesTool.json")) {
-            tools = getGson().fromJson(reader, ChatGptTool.class);
-        } catch (IOException e) {
-            throw new RuntimeException("Failed to load data for ChatGPT `format_replies` tool", e);
-        }
-        return tools;
-    }
-
-    public static ChatGptToolChoice retrieveFormatRepliesToolChoice() {
-        ChatGptToolChoice toolChoice;
-        try (InputStreamReader reader = FileUtils.getInputStreamReader("config/formatRepliesToolChoice.json")) {
-            toolChoice = getGson().fromJson(reader, ChatGptToolChoice.class);
-        } catch (IOException e) {
-            throw new RuntimeException("Failed to load data for ChatGPT `format_replies` tool choice", e);
-        }
-        return toolChoice;
-    }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientBase.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientBase.java
deleted file mode 100644
index f0896e5..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientBase.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit;
-
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.ClientBase;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.patch.diff.FileDiffProcessed;
-import lombok.Getter;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.HashMap;
-
-
-@Slf4j
-public abstract class GerritClientBase extends ClientBase {
-    @Getter
-    protected HashMap<String, FileDiffProcessed> fileDiffsProcessed = new HashMap<>();
-
-    public GerritClientBase(Configuration config) {
-        super(config);
-    }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/messages/DebugCodeBlocksReview.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/messages/DebugCodeBlocksReview.java
deleted file mode 100644
index 2c2f607..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/messages/DebugCodeBlocksReview.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.messages;
-
-import com.googlesource.gerrit.plugins.chatgpt.localization.Localizer;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptReplyItem;
-
-import java.util.List;
-
-import static com.googlesource.gerrit.plugins.chatgpt.utils.TextUtils.prettyStringifyObject;
-
-public class DebugCodeBlocksReview extends DebugCodeBlocks {
-    private static final String HIDDEN_REPLY = "hidden: %s";
-
-    public DebugCodeBlocksReview(Localizer localizer) {
-        super(localizer.getText("message.debugging.review.title"));
-    }
-
-    public String getDebugCodeBlock(ChatGptReplyItem replyItem, boolean isHidden) {
-        return super.getDebugCodeBlock(List.of(
-                String.format(HIDDEN_REPLY, isHidden),
-                prettyStringifyObject(replyItem)
-        ));
-    }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptComment.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptComment.java
deleted file mode 100644
index ebddc85..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptComment.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.prompt;
-
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.localization.Localizer;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.ClientBase;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.messages.ClientMessage;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritComment;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
-import lombok.extern.slf4j.Slf4j;
-
-@Slf4j
-public class ChatGptComment extends ClientBase {
-    protected ClientMessage commentMessage;
-
-    private final ChangeSetData changeSetData;
-    private final Localizer localizer;
-
-    public ChatGptComment(Configuration config, ChangeSetData changeSetData, Localizer localizer) {
-        super(config);
-        this.changeSetData = changeSetData;
-        this.localizer = localizer;
-    }
-
-    protected String getCleanedMessage(GerritComment commentProperty) {
-        commentMessage = new ClientMessage(config, changeSetData, commentProperty.getMessage(), localizer);
-        if (isFromAssistant(commentProperty)) {
-            commentMessage.removeDebugCodeBlocksReview().removeDebugCodeBlocksDynamicSettings();
-        }
-        else {
-            commentMessage.removeMentions().parseRemoveCommands();
-        }
-        return commentMessage.removeHeadings().getMessage();
-    }
-
-    protected boolean isFromAssistant(GerritComment commentProperty) {
-        return commentProperty.getAuthor().getAccountId() == changeSetData.getGptAccountId();
-    }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptDataPrompt.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptDataPrompt.java
deleted file mode 100644
index 48d8b99..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptDataPrompt.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.prompt;
-
-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.localization.Localizer;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptMessageItem;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.GerritClientData;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.List;
-
-import static com.googlesource.gerrit.plugins.chatgpt.utils.GsonUtils.getGson;
-
-@Slf4j
-public class ChatGptDataPrompt {
-    private final IChatGptDataPrompt chatGptDataPromptHandler;
-
-    public ChatGptDataPrompt(
-            Configuration config,
-            ChangeSetData changeSetData,
-            GerritChange change,
-            GerritClientData gerritClientData,
-            Localizer localizer
-    ) {
-        chatGptDataPromptHandler = ChatGptPromptFactory.getChatGptDataPrompt(
-                config,
-                changeSetData,
-                change,
-                gerritClientData,
-                localizer
-        );
-    }
-
-    public String buildPrompt() {
-        for (int i = 0; i < chatGptDataPromptHandler.getCommentProperties().size(); i++) {
-            chatGptDataPromptHandler.addMessageItem(i);
-        }
-        List<ChatGptMessageItem> messageItems = chatGptDataPromptHandler.getMessageItems();
-        return messageItems.isEmpty() ? "" : getGson().toJson(messageItems);
-    }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptDataPromptBase.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptDataPromptBase.java
deleted file mode 100644
index c080bc2..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptDataPromptBase.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.prompt;
-
-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.localization.Localizer;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.patch.code.InlineCode;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.patch.diff.FileDiffProcessed;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptMessageItem;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptRequestMessage;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritComment;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.CommentData;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.GerritClientData;
-import lombok.Getter;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-@Slf4j
-public abstract class ChatGptDataPromptBase implements IChatGptDataPrompt {
-    protected final GerritClientData gerritClientData;
-    protected final HashMap<String, FileDiffProcessed> fileDiffsProcessed;
-    protected final CommentData commentData;
-    @Getter
-    protected final List<ChatGptMessageItem> messageItems;
-
-    protected ChatGptHistory gptMessageHistory;
-    @Getter
-    protected List<GerritComment> commentProperties;
-
-    public ChatGptDataPromptBase(
-            Configuration config,
-            ChangeSetData changeSetData,
-            GerritClientData gerritClientData,
-            Localizer localizer
-    ) {
-        this.gerritClientData = gerritClientData;
-        fileDiffsProcessed = gerritClientData.getFileDiffsProcessed();
-        commentData = gerritClientData.getCommentData();
-        gptMessageHistory = new ChatGptHistory(config, changeSetData, gerritClientData, localizer);
-        messageItems = new ArrayList<>();
-    }
-
-    public abstract void addMessageItem(int i);
-
-    protected ChatGptMessageItem getMessageItem(int i) {
-        ChatGptMessageItem messageItem = new ChatGptMessageItem();
-        GerritComment commentProperty = commentProperties.get(i);
-        if (commentProperty.getLine() != null || commentProperty.getRange() != null) {
-            String filename = commentProperty.getFilename();
-            FileDiffProcessed fileDiffProcessed = fileDiffsProcessed.get(filename);
-            if (fileDiffProcessed == null) {
-                return messageItem;
-            }
-            InlineCode inlineCode = new InlineCode(fileDiffProcessed);
-            messageItem.setFilename(filename);
-            messageItem.setLineNumber(commentProperty.getLine());
-            messageItem.setCodeSnippet(inlineCode.getInlineCode(commentProperty));
-        }
-
-        return messageItem;
-    }
-
-    protected void setHistory(ChatGptMessageItem messageItem, List<ChatGptRequestMessage> messageHistory) {
-        if (!messageHistory.isEmpty()) {
-            messageItem.setHistory(messageHistory);
-        }
-    }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptDataPromptRequests.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptDataPromptRequests.java
deleted file mode 100644
index 11fd9c9..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptDataPromptRequests.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.prompt;
-
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.localization.Localizer;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptMessageItem;
-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.common.model.data.GerritClientData;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.List;
-
-import static com.googlesource.gerrit.plugins.chatgpt.settings.Settings.CHAT_GPT_ROLE_USER;
-
-@Slf4j
-public class ChatGptDataPromptRequests extends ChatGptDataPromptBase {
-    protected ChatGptMessageItem messageItem;
-    protected List<ChatGptRequestMessage> messageHistory;
-
-    public ChatGptDataPromptRequests(
-            Configuration config,
-            ChangeSetData changeSetData,
-            GerritClientData gerritClientData,
-            Localizer localizer
-    ) {
-        super(config, changeSetData, gerritClientData, localizer);
-        commentProperties = commentData.getCommentProperties();
-    }
-
-    public void addMessageItem(int i) {
-        ChatGptMessageItem messageItem = getMessageItem(i);
-        messageItem.setId(i);
-        messageItems.add(messageItem);
-    }
-
-    protected ChatGptMessageItem getMessageItem(int i) {
-        messageItem = super.getMessageItem(i);
-        messageHistory = gptMessageHistory.retrieveHistory(commentProperties.get(i));
-        ChatGptRequestMessage request = extractLastUserMessageFromHistory();
-        messageItem.setRequest(request.getContent());
-
-        return messageItem;
-    }
-
-    private ChatGptRequestMessage extractLastUserMessageFromHistory() {
-        for (int i = messageHistory.size() - 1; i >= 0; i--) {
-            if (CHAT_GPT_ROLE_USER.equals(messageHistory.get(i).getRole())) {
-                return messageHistory.remove(i);
-            }
-        }
-        throw new RuntimeException("Error extracting request from message history: no user message found in " +
-                messageHistory);
-    }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptDataPromptReview.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptDataPromptReview.java
deleted file mode 100644
index 7b06465..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptDataPromptReview.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.prompt;
-
-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.localization.Localizer;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptMessageItem;
-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.common.model.data.GerritClientData;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@Slf4j
-public class ChatGptDataPromptReview extends ChatGptDataPromptBase implements IChatGptDataPrompt {
-    public ChatGptDataPromptReview(
-            Configuration config,
-            ChangeSetData changeSetData,
-            GerritClientData gerritClientData,
-            Localizer localizer
-    ) {
-        super(config, changeSetData, gerritClientData, localizer);
-        commentProperties = new ArrayList<>(commentData.getCommentMap().values());
-    }
-
-    public void addMessageItem(int i) {
-        ChatGptMessageItem messageItem = getMessageItem(i);
-        if (messageItem.getHistory() != null) {
-            messageItems.add(messageItem);
-        }
-    }
-
-    protected ChatGptMessageItem getMessageItem(int i) {
-        ChatGptMessageItem messageItem = super.getMessageItem(i);
-        List<ChatGptRequestMessage> messageHistory = gptMessageHistory.retrieveHistory(commentProperties.get(i),
-                true);
-        setHistory(messageItem, messageHistory);
-
-        return messageItem;
-    }
-}
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
deleted file mode 100644
index e6cfb24..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/prompt/ChatGptPromptFactory.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.prompt;
-
-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;
-
-@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,
-            GerritChange change,
-            GerritClientData gerritClientData,
-            Localizer localizer
-    ) {
-        if (change.getIsCommentEvent()) {
-            if ((config.getGptMode() == Settings.Modes.stateless)) {
-                log.info("ChatGptPromptFactory: Returned ChatGptDataPromptRequestsStateless");
-                return new ChatGptDataPromptRequestsStateless(config, changeSetData, gerritClientData, localizer);
-            } else {
-                log.info("ChatGptPromptFactory: Returned ChatGptDataPromptRequestsStateful");
-                return new ChatGptDataPromptRequestsStateful(config, changeSetData, gerritClientData, localizer);
-            }
-        } else {
-            log.info("ChatGptPromptFactory: Returned ChatGptDataPromptReview");
-            return new ChatGptDataPromptReview(config, changeSetData, gerritClientData, localizer);
-        }
-    }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptDialogueItem.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptDialogueItem.java
deleted file mode 100644
index e4e75fe..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptDialogueItem.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt;
-
-import lombok.Data;
-
-@Data
-public abstract class ChatGptDialogueItem {
-    protected Integer id;
-    protected String filename;
-    protected Integer lineNumber;
-    protected String codeSnippet;
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptMessageItem.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptMessageItem.java
deleted file mode 100644
index 2307ce1..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptMessageItem.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt;
-
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import java.util.List;
-
-@EqualsAndHashCode(callSuper = true)
-@Data
-public class ChatGptMessageItem extends ChatGptDialogueItem {
-    private String request;
-    private List<ChatGptRequestMessage> history;
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptResponseContent.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptResponseContent.java
deleted file mode 100644
index 7529395..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptResponseContent.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt;
-
-import lombok.Data;
-import lombok.NonNull;
-import lombok.RequiredArgsConstructor;
-
-import java.util.List;
-
-@Data
-@RequiredArgsConstructor
-public class ChatGptResponseContent {
-    private List<ChatGptReplyItem> replies;
-    private String changeId;
-    @NonNull
-    private String messageContent;
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptResponseUnstreamed.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptResponseUnstreamed.java
deleted file mode 100644
index b3139b8..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptResponseUnstreamed.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt;
-
-import lombok.Data;
-
-import java.util.List;
-
-@Data
-public class ChatGptResponseUnstreamed {
-    private List<MessageChoice> choices;
-
-    @Data
-    public static class MessageChoice {
-        private ChatGptResponseMessage message;
-    }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptToolChoice.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptToolChoice.java
deleted file mode 100644
index 066c228..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/chatgpt/ChatGptToolChoice.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt;
-
-import lombok.Data;
-
-@Data
-public class ChatGptToolChoice {
-    private String type;
-    private Function function;
-
-    @Data
-    public static class Function {
-        private String name;
-    }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/gerrit/GerritPermittedVotingRange.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/gerrit/GerritPermittedVotingRange.java
deleted file mode 100644
index f617d3e..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/api/gerrit/GerritPermittedVotingRange.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit;
-
-import lombok.Data;
-
-@Data
-public class GerritPermittedVotingRange {
-    private int min;
-    private int max;
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/patch/code/CodeFinderDiff.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/patch/code/CodeFinderDiff.java
deleted file mode 100644
index 089f5f8..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/patch/code/CodeFinderDiff.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.patch.code;
-
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.patch.diff.DiffContent;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-
-import java.util.TreeMap;
-
-@AllArgsConstructor
-@Data
-public class CodeFinderDiff {
-    private DiffContent content;
-    private TreeMap<Integer, Integer> charToLineMap;
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/patch/diff/DiffContent.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/patch/diff/DiffContent.java
deleted file mode 100644
index db30603..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/patch/diff/DiffContent.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.patch.diff;
-
-import lombok.Data;
-
-@Data
-public class DiffContent {
-    public String a;
-    public String b;
-    public String ab;
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/review/ReviewBatch.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/review/ReviewBatch.java
deleted file mode 100644
index 73196d5..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/model/review/ReviewBatch.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.common.model.review;
-
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritCodeRange;
-import lombok.Data;
-import lombok.NonNull;
-import lombok.RequiredArgsConstructor;
-
-import static com.googlesource.gerrit.plugins.chatgpt.settings.Settings.GERRIT_PATCH_SET_FILENAME;
-
-@Data
-@RequiredArgsConstructor
-public class ReviewBatch {
-    private String id;
-    @NonNull
-    private String content;
-    private String filename;
-    private Integer line;
-    private GerritCodeRange range;
-
-    public String getFilename() {
-        return filename == null ? GERRIT_PATCH_SET_FILENAME : filename;
-    }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptClientStateful.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptClientStateful.java
deleted file mode 100644
index e38af1c..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptClientStateful.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.chatgpt;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandlerProvider;
-import com.googlesource.gerrit.plugins.chatgpt.interfaces.mode.common.client.api.chatgpt.IChatGptClient;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.chatgpt.ChatGptClient;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptResponseContent;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.git.GitRepoFiles;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.model.api.chatgpt.ChatGptThreadMessageResponse;
-import lombok.extern.slf4j.Slf4j;
-
-import static com.googlesource.gerrit.plugins.chatgpt.utils.GsonUtils.getGson;
-import static com.googlesource.gerrit.plugins.chatgpt.utils.JsonTextUtils.isJsonString;
-import static com.googlesource.gerrit.plugins.chatgpt.utils.JsonTextUtils.unwrapJsonCode;
-
-@Slf4j
-@Singleton
-public class ChatGptClientStateful extends ChatGptClient implements IChatGptClient {
-    private static final String TYPE_MESSAGE_CREATION = "message_creation";
-    private static final String TYPE_TOOL_CALLS = "tool_calls";
-
-    private final GitRepoFiles gitRepoFiles;
-    private final PluginDataHandlerProvider pluginDataHandlerProvider;
-
-    @VisibleForTesting
-    @Inject
-    public ChatGptClientStateful(
-            Configuration config,
-            GitRepoFiles gitRepoFiles,
-            PluginDataHandlerProvider pluginDataHandlerProvider
-    ) {
-        super(config);
-        this.gitRepoFiles = gitRepoFiles;
-        this.pluginDataHandlerProvider = pluginDataHandlerProvider;
-    }
-
-    public ChatGptResponseContent ask(ChangeSetData changeSetData, GerritChange change, String patchSet) {
-        isCommentEvent = change.getIsCommentEvent();
-        String changeId = change.getFullChangeId();
-        log.info("Processing STATEFUL ChatGPT Request with changeId: {}, Patch Set: {}", changeId, patchSet);
-
-        ChatGptThread chatGptThread = new ChatGptThread(config, pluginDataHandlerProvider);
-        String threadId = chatGptThread.createThread();
-
-        ChatGptThreadMessage chatGptThreadMessage = new ChatGptThreadMessage(
-                threadId,
-                config,
-                changeSetData,
-                change,
-                patchSet
-        );
-        chatGptThreadMessage.addMessage();
-
-        ChatGptRun chatGptRun = new ChatGptRun(
-                threadId,
-                config,
-                changeSetData,
-                change,
-                gitRepoFiles,
-                pluginDataHandlerProvider
-        );
-        chatGptRun.createRun();
-        chatGptRun.pollRunStep();
-        // Attribute `requestBody` is valued for testing purposes
-        requestBody = chatGptThreadMessage.getAddMessageRequestBody();
-        log.debug("ChatGPT request body: {}", requestBody);
-
-        ChatGptResponseContent chatGptResponseContent = getResponseContentStateful(threadId, chatGptRun);
-        chatGptRun.cancelRun();
-
-        return chatGptResponseContent;
-    }
-
-    private ChatGptResponseContent getResponseContentStateful(String threadId, ChatGptRun chatGptRun) {
-        return switch (chatGptRun.getFirstStepDetails().getType()) {
-            case TYPE_MESSAGE_CREATION -> retrieveThreadMessage(threadId, chatGptRun);
-            case TYPE_TOOL_CALLS -> getResponseContent(chatGptRun.getFirstStepToolCalls());
-            default -> throw new IllegalStateException("Unexpected Step Type in stateful ChatGpt response: " +
-                    chatGptRun);
-        };
-    }
-
-    private ChatGptResponseContent retrieveThreadMessage(String threadId, ChatGptRun chatGptRun) {
-        ChatGptThreadMessage chatGptThreadMessage = new ChatGptThreadMessage(threadId, config);
-        ChatGptThreadMessageResponse threadMessageResponse = chatGptThreadMessage.retrieveMessage(
-                chatGptRun.getFirstStepDetails().getMessageCreation().getMessageId()
-        );
-        String responseText = threadMessageResponse.getContent().get(0).getText().getValue();
-        if (responseText == null) {
-            throw new RuntimeException("ChatGPT thread message response content is null");
-        }
-        if (isJsonString(responseText)) {
-            return extractResponseContent(responseText);
-        }
-        return new ChatGptResponseContent(responseText);
-    }
-
-    private ChatGptResponseContent extractResponseContent(String responseText) {
-        return getGson().fromJson(unwrapJsonCode(responseText), ChatGptResponseContent.class);
-    }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptFiles.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptFiles.java
deleted file mode 100644
index 4923503..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptFiles.java
+++ /dev/null
@@ -1,48 +0,0 @@
-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.mode.common.client.ClientBase;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.http.HttpClient;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.UriResourceLocatorStateful;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.model.api.chatgpt.ChatGptFilesResponse;
-import lombok.extern.slf4j.Slf4j;
-import okhttp3.*;
-
-import java.io.File;
-import java.net.URI;
-import java.nio.file.Path;
-
-import static com.googlesource.gerrit.plugins.chatgpt.utils.GsonUtils.getGson;
-
-@Slf4j
-public class ChatGptFiles extends ClientBase {
-    private final HttpClient httpClient = new HttpClient();
-
-    public ChatGptFiles(Configuration config) {
-        super(config);
-    }
-
-    public ChatGptFilesResponse uploadFiles(Path repoPath) {
-        Request request = createUploadFileRequest(repoPath);
-        log.debug("ChatGPT Upload Files request: {}", request);
-
-        String response = httpClient.execute(request);
-        log.debug("ChatGPT Upload Files response: {}", response);
-
-        return getGson().fromJson(response, ChatGptFilesResponse.class);
-    }
-
-    private Request createUploadFileRequest(Path repoPath) {
-        URI uri = URI.create(config.getGptDomain() + UriResourceLocatorStateful.filesCreateUri());
-        log.debug("ChatGPT Upload Files request URI: {}", uri);
-        File file = repoPath.toFile();
-        RequestBody requestBody = new MultipartBody.Builder()
-                .setType(MultipartBody.FORM)
-                .addFormDataPart("purpose", "assistants")
-                .addFormDataPart("file", file.getName(),
-                        RequestBody.create(file, MediaType.parse("application/json")))
-                .build();
-
-        return httpClient.createRequest(uri.toString(), config.getGptToken(), requestBody, null);
-    }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptHttpClient.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptHttpClient.java
deleted file mode 100644
index 86d4f11..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/api/chatgpt/ChatGptHttpClient.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.chatgpt;
-
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.http.HttpClient;
-import okhttp3.Request;
-
-import java.util.Map;
-
-public class ChatGptHttpClient extends HttpClient {
-    private static final Map<String, String> BETA_VERSION_HEADER = Map.of("OpenAI-Beta", "assistants=v2");
-
-    public Request createRequestFromJson(String uri, String bearer, Object requestObject) {
-        return createRequestFromJson(uri, bearer, requestObject, BETA_VERSION_HEADER);
-    }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/prompt/ChatGptDataPromptRequestsStateful.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/prompt/ChatGptDataPromptRequestsStateful.java
deleted file mode 100644
index 5c2e390..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/prompt/ChatGptDataPromptRequestsStateful.java
+++ /dev/null
@@ -1,19 +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.interfaces.mode.common.client.prompt.IChatGptDataPrompt;
-import com.googlesource.gerrit.plugins.chatgpt.localization.Localizer;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.prompt.ChatGptDataPromptRequests;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.GerritClientData;
-
-public class ChatGptDataPromptRequestsStateful extends ChatGptDataPromptRequests implements IChatGptDataPrompt {
-    public ChatGptDataPromptRequestsStateful(
-            Configuration config,
-            ChangeSetData changeSetData,
-            GerritClientData gerritClientData,
-            Localizer localizer
-    ) {
-        super(config, changeSetData, gerritClientData, localizer);
-    }
-}
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
deleted file mode 100644
index bb39d01..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/prompt/ChatGptPromptStatefulBase.java
+++ /dev/null
@@ -1,65 +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.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
deleted file mode 100644
index e92629a..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/prompt/ChatGptPromptStatefulRequests.java
+++ /dev/null
@@ -1,35 +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.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
deleted file mode 100644
index 389e5e6..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/client/prompt/ChatGptPromptStatefulReview.java
+++ /dev/null
@@ -1,55 +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.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/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptRunStepsResponse.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptRunStepsResponse.java
deleted file mode 100644
index d951b1d..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateful/model/api/chatgpt/ChatGptRunStepsResponse.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateful.model.api.chatgpt;
-
-import com.google.gson.annotations.SerializedName;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptResponseMessage;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-@EqualsAndHashCode(callSuper = true)
-@Data
-public class ChatGptRunStepsResponse extends ChatGptResponse {
-    @SerializedName("step_details")
-    private ChatGptResponseMessage stepDetails;
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateless/client/api/UriResourceLocatorStateless.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateless/client/api/UriResourceLocatorStateless.java
deleted file mode 100644
index a09cd28..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateless/client/api/UriResourceLocatorStateless.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateless.client.api;
-
-
-public class UriResourceLocatorStateless {
-    public static String chatCompletionsUri() {
-        return "/v1/chat/completions";
-    }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateless/client/api/chatgpt/ChatGptClientStateless.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateless/client/api/chatgpt/ChatGptClientStateless.java
deleted file mode 100644
index dd47726..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateless/client/api/chatgpt/ChatGptClientStateless.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateless.client.api.chatgpt;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.net.HttpHeaders;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.interfaces.mode.common.client.api.chatgpt.IChatGptClient;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.chatgpt.ChatGptClient;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.chatgpt.ChatGptParameters;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.chatgpt.ChatGptTools;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.http.HttpClientWithRetry;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.*;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateless.client.api.UriResourceLocatorStateless;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateless.client.prompt.ChatGptPromptStateless;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateless.model.api.chatgpt.ChatGptCompletionRequest;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.http.entity.ContentType;
-
-import java.io.IOException;
-import java.net.URI;
-import java.net.http.HttpRequest;
-import java.net.http.HttpResponse;
-import java.util.List;
-
-import static com.googlesource.gerrit.plugins.chatgpt.utils.GsonUtils.getNoEscapedGson;
-
-@Slf4j
-@Singleton
-public class ChatGptClientStateless extends ChatGptClient implements IChatGptClient {
-    private static final int REVIEW_ATTEMPT_LIMIT = 3;
-
-    private final HttpClientWithRetry httpClientWithRetry = new HttpClientWithRetry();
-
-    @VisibleForTesting
-    @Inject
-    public ChatGptClientStateless(Configuration config) {
-        super(config);
-    }
-
-    public ChatGptResponseContent ask(ChangeSetData changeSetData, GerritChange change, String patchSet)
-            throws Exception {
-        isCommentEvent = change.getIsCommentEvent();
-        String changeId = change.getFullChangeId();
-        log.info("Processing STATELESS ChatGPT Request with changeId: {}, Patch Set: {}", changeId, patchSet);
-        for (int attemptInd = 0; attemptInd < REVIEW_ATTEMPT_LIMIT; attemptInd++) {
-            HttpRequest request = createRequest(config, changeSetData, patchSet);
-            log.debug("ChatGPT request: {}", request.toString());
-
-            HttpResponse<String> response = httpClientWithRetry.execute(request);
-
-            String body = response.body();
-            log.debug("ChatGPT response body: {}", body);
-            if (body == null) {
-                throw new IOException("ChatGPT response body is null");
-            }
-
-            ChatGptResponseContent contentExtracted = extractContent(config, body);
-            if (validateResponse(contentExtracted, changeId, attemptInd)) {
-                return contentExtracted;
-            }
-        }
-        throw new RuntimeException("Failed to receive valid ChatGPT response");
-    }
-
-    protected HttpRequest createRequest(Configuration config, ChangeSetData changeSetData, String patchSet) {
-        URI uri = URI.create(config.getGptDomain() + UriResourceLocatorStateless.chatCompletionsUri());
-        log.debug("ChatGPT request URI: {}", uri);
-        requestBody = createRequestBody(config, changeSetData, patchSet);
-        log.debug("ChatGPT request body: {}", requestBody);
-
-        return HttpRequest.newBuilder()
-                .header(HttpHeaders.AUTHORIZATION, "Bearer " + config.getGptToken())
-                .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
-                .uri(uri)
-                .POST(HttpRequest.BodyPublishers.ofString(requestBody))
-                .build();
-    }
-
-    private String createRequestBody(Configuration config, ChangeSetData changeSetData, String patchSet) {
-        ChatGptPromptStateless chatGptPromptStateless = new ChatGptPromptStateless(config, isCommentEvent);
-        ChatGptRequestMessage systemMessage = ChatGptRequestMessage.builder()
-                .role("system")
-                .content(chatGptPromptStateless.getGptSystemPrompt())
-                .build();
-        ChatGptRequestMessage userMessage = ChatGptRequestMessage.builder()
-                .role("user")
-                .content(chatGptPromptStateless.getGptUserPrompt(changeSetData, patchSet))
-                .build();
-
-        ChatGptParameters chatGptParameters = new ChatGptParameters(config, isCommentEvent);
-        ChatGptTool[] tools = new ChatGptTool[] {
-                ChatGptTools.retrieveFormatRepliesTool()
-        };
-        ChatGptCompletionRequest chatGptCompletionRequest = ChatGptCompletionRequest.builder()
-                .model(config.getGptModel())
-                .messages(List.of(systemMessage, userMessage))
-                .temperature(chatGptParameters.getGptTemperature())
-                .stream(chatGptParameters.getStreamOutput())
-                // Seed value is Utilized to prevent ChatGPT from mixing up separate API calls that occur in close
-                // temporal proximity.
-                .seed(chatGptParameters.getRandomSeed())
-                .tools(tools)
-                .toolChoice(ChatGptTools.retrieveFormatRepliesToolChoice())
-                .build();
-
-        return getNoEscapedGson().toJson(chatGptCompletionRequest);
-    }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateless/client/prompt/ChatGptDataPromptRequestsStateless.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateless/client/prompt/ChatGptDataPromptRequestsStateless.java
deleted file mode 100644
index 8682352..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateless/client/prompt/ChatGptDataPromptRequestsStateless.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateless.client.prompt;
-
-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.localization.Localizer;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.prompt.ChatGptDataPromptRequests;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptMessageItem;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.GerritClientData;
-import lombok.extern.slf4j.Slf4j;
-
-@Slf4j
-public class ChatGptDataPromptRequestsStateless extends ChatGptDataPromptRequests implements IChatGptDataPrompt {
-    public ChatGptDataPromptRequestsStateless(
-            Configuration config,
-            ChangeSetData changeSetData,
-            GerritClientData gerritClientData,
-            Localizer localizer
-    ) {
-        super(config, changeSetData, gerritClientData, localizer);
-    }
-
-    protected ChatGptMessageItem getMessageItem(int i) {
-        super.getMessageItem(i);
-        setHistory(messageItem, messageHistory);
-
-        return messageItem;
-    }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateless/client/prompt/ChatGptPromptStateless.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateless/client/prompt/ChatGptPromptStateless.java
deleted file mode 100644
index 7ed6f94..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateless/client/prompt/ChatGptPromptStateless.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateless.client.prompt;
-
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-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.Arrays;
-import java.util.List;
-
-import static com.googlesource.gerrit.plugins.chatgpt.utils.TextUtils.*;
-
-@Slf4j
-public class ChatGptPromptStateless extends ChatGptPrompt {
-    public static String DEFAULT_GPT_SYSTEM_PROMPT_INPUT_DESCRIPTION;
-    public static String DEFAULT_GPT_SYSTEM_PROMPT_INPUT_DESCRIPTION_REVIEW;
-    public static String DEFAULT_GPT_REVIEW_PROMPT;
-    public static String DEFAULT_GPT_REVIEW_PROMPT_REVIEW;
-    public static String DEFAULT_GPT_REVIEW_PROMPT_MESSAGE_HISTORY;
-    public static String DEFAULT_GPT_REVIEW_PROMPT_DIFF;
-
-    public ChatGptPromptStateless(Configuration config) {
-        super(config);
-        loadStatelessPrompts();
-    }
-
-    public ChatGptPromptStateless(Configuration config, boolean isCommentEvent) {
-        super(config, isCommentEvent);
-        loadStatelessPrompts();
-    }
-
-    public static String getDefaultGptReviewSystemPrompt() {
-        return joinWithSpace(new ArrayList<>(List.of(
-                DEFAULT_GPT_SYSTEM_PROMPT + DOT,
-                DEFAULT_GPT_SYSTEM_PROMPT_INPUT_DESCRIPTION,
-                DEFAULT_GPT_SYSTEM_PROMPT_INPUT_DESCRIPTION_REVIEW
-        )));
-    }
-
-    public String getGptSystemPrompt() {
-        List<String> prompt = new ArrayList<>(Arrays.asList(
-                config.getString(Configuration.KEY_GPT_SYSTEM_PROMPT, DEFAULT_GPT_SYSTEM_PROMPT) + DOT,
-                ChatGptPromptStateless.DEFAULT_GPT_SYSTEM_PROMPT_INPUT_DESCRIPTION
-        ));
-        if (!isCommentEvent) {
-            prompt.add(ChatGptPromptStateless.DEFAULT_GPT_SYSTEM_PROMPT_INPUT_DESCRIPTION_REVIEW);
-        }
-        return joinWithSpace(prompt);
-    }
-
-    public String getGptUserPrompt(ChangeSetData changeSetData, String patchSet) {
-        List<String> prompt = new ArrayList<>();
-        String gptRequestDataPrompt = changeSetData.getGptDataPrompt();
-        boolean isValidRequestDataPrompt = gptRequestDataPrompt != null && !gptRequestDataPrompt.isEmpty();
-        if (isCommentEvent && isValidRequestDataPrompt) {
-            log.debug("Request User Prompt retrieved: {}", gptRequestDataPrompt);
-            prompt.addAll(Arrays.asList(
-                    DEFAULT_GPT_REQUEST_PROMPT_DIFF,
-                    patchSet,
-                    DEFAULT_GPT_REQUEST_PROMPT_REQUESTS,
-                    gptRequestDataPrompt,
-                    getCommentRequestPrompt(changeSetData.getCommentPropertiesSize())
-            ));
-        }
-        else {
-            prompt.add(ChatGptPromptStateless.DEFAULT_GPT_REVIEW_PROMPT);
-            prompt.addAll(getReviewSteps());
-            prompt.add(ChatGptPromptStateless.DEFAULT_GPT_REVIEW_PROMPT_DIFF);
-            prompt.add(patchSet);
-            if (isValidRequestDataPrompt) {
-                prompt.add(ChatGptPromptStateless.DEFAULT_GPT_REVIEW_PROMPT_MESSAGE_HISTORY);
-                prompt.add(gptRequestDataPrompt);
-            }
-            if (!changeSetData.getDirectives().isEmpty()) {
-                prompt.add(DEFAULT_GPT_REVIEW_PROMPT_DIRECTIVES);
-                prompt.add(getNumberedListString(new ArrayList<>(changeSetData.getDirectives()), null, null));
-            }
-        }
-        return joinWithNewLine(prompt);
-    }
-
-    private void loadStatelessPrompts() {
-        // Avoid repeated loading of prompt constants
-        if (DEFAULT_GPT_SYSTEM_PROMPT_INPUT_DESCRIPTION == null) {
-            loadDefaultPrompts("promptsStateless");
-        }
-    }
-
-    private List<String> getReviewSteps() {
-        List<String> steps = new ArrayList<>(List.of(
-                joinWithSpace(new ArrayList<>(List.of(
-                        DEFAULT_GPT_REVIEW_PROMPT_REVIEW,
-                        DEFAULT_GPT_PROMPT_FORCE_JSON_FORMAT,
-                        getPatchSetReviewPrompt()
-                )))
-        ));
-        if (config.getGptReviewCommitMessages()) {
-            steps.add(getReviewPromptCommitMessages());
-        }
-        return steps;
-    }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateless/model/api/chatgpt/ChatGptCompletionRequest.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateless/model/api/chatgpt/ChatGptCompletionRequest.java
deleted file mode 100644
index 82e9e90..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/stateless/model/api/chatgpt/ChatGptCompletionRequest.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.mode.stateless.model.api.chatgpt;
-
-import com.google.gson.annotations.SerializedName;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptRequestMessage;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptTool;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptToolChoice;
-import lombok.Builder;
-import lombok.Data;
-
-import java.util.List;
-
-@Data
-@Builder
-public class ChatGptCompletionRequest {
-    private String model;
-    private boolean stream;
-    private double temperature;
-    private int seed;
-    private List<ChatGptRequestMessage> messages;
-    private ChatGptTool[] tools;
-    @SerializedName("tool_choice")
-    private ChatGptToolChoice toolChoice;
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/settings/Settings.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/settings/Settings.java
deleted file mode 100644
index 90c91fe..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/settings/Settings.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.settings;
-
-import java.util.Map;
-
-public class Settings {
-    public static final String GERRIT_PATCH_SET_FILENAME = "/PATCHSET_LEVEL";
-    public static final String GERRIT_DEFAULT_MESSAGE_DONE = "Done";
-    public static final String GERRIT_AUTOGENERATED_PREFIX = "autogenerated:";
-    public static final Map<String , String> COMMIT_MESSAGE_FILTER_OUT_PREFIXES = Map.of(
-            "PARENT","Parent:",
-            "AUTHOR","Author:",
-            "AUTHOR_DATE", "AuthorDate:",
-            "COMMIT","Commit:",
-            "COMMIT_DATE", "CommitDate:",
-            "CHANGE_ID", "Change-Id:"
-    );
-    public static final String GERRIT_COMMIT_MESSAGE_PREFIX = "Subject: ";
-
-    public static final String CHAT_GPT_ROLE_USER = "user";
-    public static final String CHAT_GPT_ROLE_ASSISTANT = "assistant";
-
-    public enum Modes {
-        stateless,
-        stateful
-    }
-}
diff --git a/src/main/resources/config/prompts.json b/src/main/resources/config/prompts.json
index aa976f1..c88eacf 100644
--- a/src/main/resources/config/prompts.json
+++ b/src/main/resources/config/prompts.json
@@ -1,14 +1,14 @@
 {
-  "DEFAULT_GPT_SYSTEM_PROMPT": "Act as a PatchSet Reviewer",
-  "DEFAULT_GPT_REVIEW_PROMPT_DIRECTIVES": "Here are the Directives:",
-  "DEFAULT_GPT_REVIEW_PROMPT_COMMIT_MESSAGES": "You MUST review the commit message of the PatchSet and provide your feedback in an additional reply. The commit message is provided in %s. Ensure that the commit message accurately and succinctly describes the changes made, and verify if it matches the nature and scope of the changes in the PatchSet. If your feedback on the commit message is negative, you are required to supply an example of commit message that meets these criteria. For instance, if your comment is \"The commit message lacks detail\", you should follow up with \"A clearer commit message would be '...'\".",
-  "DEFAULT_GPT_REQUEST_PROMPT_DIFF": "I have some requests about the following PatchSet Diff:",
-  "DEFAULT_GPT_REQUEST_PROMPT_REQUESTS": "My requests are given in a JSON-formatted array, where each element includes the compulsory field `request`, the field `history` with any prior exchanged messages, and, for inline code comments, the fields `filename`, `lineNumber`, and `codeSnippet`:",
-  "DEFAULT_GPT_PROMPT_FORCE_JSON_FORMAT": "You MUST provide your entire response as a JSON object; no other formats, such as plain text lists of suggestions, will be considered acceptable. Each reply must be formatted as an individual answer object within an array in the key `replies` of the response object, as defined in the tools function named `format_replies`.",
-  "DEFAULT_GPT_REPLIES_PROMPT_SPECS": "The answer object includes the string attributes %s, with the following specifications: %s.",
-  "DEFAULT_GPT_REPLIES_PROMPT_INLINE": "For replies that are specific to a certain part of the code, the object must additionally include the keys `filename`, `lineNumber`, and `codeSnippet` to precisely identify the relevant code section.",
-  "DEFAULT_GPT_REPLIES_PROMPT_ENFORCE_RESPONSE_CHECK": "Make sure that the array in `replies` contains exactly %d element(s), one for each request.",
-  "DEFAULT_GPT_REPLIES_ATTRIBUTES": {
+  "DEFAULT_AI_CHAT_SYSTEM_PROMPT": "Act as a PatchSet Reviewer",
+  "DEFAULT_AI_CHAT_REVIEW_PROMPT_DIRECTIVES": "Here are the Directives:",
+  "DEFAULT_AI_CHAT_REVIEW_PROMPT_COMMIT_MESSAGES": "You MUST review the commit message of the PatchSet and provide your feedback in an additional reply. The commit message is provided in %s. Ensure that the commit message accurately and succinctly describes the changes made, and verify if it matches the nature and scope of the changes in the PatchSet. If your feedback on the commit message is negative, you are required to supply an example of commit message that meets these criteria. For instance, if your comment is \"The commit message lacks detail\", you should follow up with \"A clearer commit message would be '...'\".",
+  "DEFAULT_AI_CHAT_REQUEST_PROMPT_DIFF": "I have some requests about the following PatchSet Diff:",
+  "DEFAULT_AI_CHAT_REQUEST_PROMPT_REQUESTS": "My requests are given in a JSON-formatted array, where each element includes the compulsory field `request`, the field `history` with any prior exchanged messages, and, for inline code comments, the fields `filename`, `lineNumber`, and `codeSnippet`:",
+  "DEFAULT_AI_CHAT_PROMPT_FORCE_JSON_FORMAT": "You MUST provide your entire response as a JSON object; no other formats, such as plain text lists of suggestions, will be considered acceptable. Each reply must be formatted as an individual answer object within an array in the key `replies` of the response object, as defined in the tools function named `format_replies`.",
+  "DEFAULT_AI_CHAT_REPLIES_PROMPT_SPECS": "The answer object includes the string attributes %s, with the following specifications: %s.",
+  "DEFAULT_AI_CHAT_REPLIES_PROMPT_INLINE": "For replies that are specific to a certain part of the code, the object must additionally include the keys `filename`, `lineNumber`, and `codeSnippet` to precisely identify the relevant code section.",
+  "DEFAULT_AI_CHAT_REPLIES_PROMPT_ENFORCE_RESPONSE_CHECK": "Make sure that the array in `replies` contains exactly %d element(s), one for each request.",
+  "DEFAULT_AI_CHAT_REPLIES_ATTRIBUTES": {
     "reply": "contains the text of the insight",
     "id": "corresponds to the `id` value from the related request in the request JSON array",
     "score": "represents a rating (an integer from %d to %d) attributed to the change being addressed in your reply, based on the reply content",
@@ -17,5 +17,5 @@
     "repeated": "is marked true if any message in the history either contains the same core message as the `reply` or addresses the same code snippet, and is marked false otherwise",
     "conflicting": "is marked true if either of these conditions is met: 1. issuing the reply goes against one of the Directives, or 2. any message in the history, identified by the 'assistant' role, is in conflict with the reply"
   },
-  "DEFAULT_GPT_RELEVANCE_RULES": "lower values for improvement suggestions, commit messages not providing details on the testing or verification process, and missing documentation or testing of functionalities; for code issues, set `relevance` in direct relation to the issue's severity; for commit messages that do not thoroughly describe the changes, adjust `relevance` based on the significance of the unexplained aspects"
+  "DEFAULT_AI_CHAT_RELEVANCE_RULES": "lower values for improvement suggestions, commit messages not providing details on the testing or verification process, and missing documentation or testing of functionalities; for code issues, set `relevance` in direct relation to the issue's severity; for commit messages that do not thoroughly describe the changes, adjust `relevance` based on the significance of the unexplained aspects"
 }
diff --git a/src/main/resources/config/promptsStateful.json b/src/main/resources/config/promptsStateful.json
index c774b91..af3e691 100644
--- a/src/main/resources/config/promptsStateful.json
+++ b/src/main/resources/config/promptsStateful.json
@@ -1,7 +1,7 @@
 {
-  "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_MESSAGE_REVIEW": "Review the following Patch Set: ```%s```",
-  "DEFAULT_GPT_HOW_TO_FIND_COMMIT_MESSAGE": "the \"Subject:\" entry of the Patch Set"
+  "DEFAULT_AI_CHAT_ASSISTANT_NAME": "PatchSet Reviewer",
+  "DEFAULT_AI_CHAT_ASSISTANT_DESCRIPTION": "PatchSet Reviewer for project %s.",
+  "DEFAULT_AI_CHAT_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_AI_CHAT_MESSAGE_REVIEW": "Review the following Patch Set: ```%s```",
+  "DEFAULT_AI_CHAT_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
index 832612d..f176162 100644
--- a/src/main/resources/config/promptsStatefulRequests.json
+++ b/src/main/resources/config/promptsStatefulRequests.json
@@ -1,3 +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."
+  "DEFAULT_AI_CHAT_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
index cf8d7f9..0601286 100644
--- a/src/main/resources/config/promptsStatefulReview.json
+++ b/src/main/resources/config/promptsStatefulReview.json
@@ -1,5 +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."
+  "DEFAULT_AI_CHAT_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_AI_CHAT_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_AI_CHAT_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/main/resources/config/promptsStateless.json b/src/main/resources/config/promptsStateless.json
index 06110a8..5018709 100644
--- a/src/main/resources/config/promptsStateless.json
+++ b/src/main/resources/config/promptsStateless.json
@@ -1,9 +1,9 @@
 {
-  "DEFAULT_GPT_SYSTEM_PROMPT_INPUT_DESCRIPTION": "I will provide you with PatchSet Diffs for various files in a JSON format. Each changed file's content will be detailed in the \"content\" field of the JSON object. In this \"content\", the \"a\" items are the lines removed, the \"b\" items are the lines added, and the \"ab\" items are the unchanged lines. In your response, avoid explicitly referring to the \"a\", \"b\", and other fields from the JSON object. Instead, use more intuitive terms like \"new lines\" for additions, \"removed lines\" for deletions, and \"unchanged lines\" for the parts that haven't been altered.",
-  "DEFAULT_GPT_SYSTEM_PROMPT_INPUT_DESCRIPTION_REVIEW": "Also, I will supply the history of messages exchanged related to the PatchSet.",
-  "DEFAULT_GPT_REVIEW_PROMPT": "To conduct your review, follow these steps in the given order:",
-  "DEFAULT_GPT_REVIEW_PROMPT_REVIEW": "Begin with examining the PatchSet Diff, focusing exclusively on the \"a\" and \"b\" items, and using the \"ab\" items solely as context to understand the changes better. Provide insights on any potential issues you foresee and suggestions for improvements if necessary, with each insight articulated as a separate reply. Concentrate exclusively on spotting and rectifying issues; avoid mentioning any positive elements. For instance, instead of saying \"this is good, but that needs improvement\", simply state \"that needs improvement\".",
-  "DEFAULT_GPT_REVIEW_PROMPT_DIFF": "Here are the PatchSet Diffs:",
-  "DEFAULT_GPT_REVIEW_PROMPT_MESSAGE_HISTORY": "Here are the message histories:",
-  "DEFAULT_GPT_HOW_TO_FIND_COMMIT_MESSAGE": "the \"content\" field of \"/COMMIT_MSG\" in the same way as the file changes"
+  "DEFAULT_AI_CHAT_SYSTEM_PROMPT_INPUT_DESCRIPTION": "I will provide you with PatchSet Diffs for various files in a JSON format. Each changed file's content will be detailed in the \"content\" field of the JSON object. In this \"content\", the \"a\" items are the lines removed, the \"b\" items are the lines added, and the \"ab\" items are the unchanged lines. In your response, avoid explicitly referring to the \"a\", \"b\", and other fields from the JSON object. Instead, use more intuitive terms like \"new lines\" for additions, \"removed lines\" for deletions, and \"unchanged lines\" for the parts that haven't been altered.",
+  "DEFAULT_AI_CHAT_SYSTEM_PROMPT_INPUT_DESCRIPTION_REVIEW": "Also, I will supply the history of messages exchanged related to the PatchSet.",
+  "DEFAULT_AI_CHAT_REVIEW_PROMPT": "To conduct your review, follow these steps in the given order:",
+  "DEFAULT_AI_CHAT_REVIEW_PROMPT_REVIEW": "Begin with examining the PatchSet Diff, focusing exclusively on the \"a\" and \"b\" items, and using the \"ab\" items solely as context to understand the changes better. Provide insights on any potential issues you foresee and suggestions for improvements if necessary, with each insight articulated as a separate reply. Concentrate exclusively on spotting and rectifying issues; avoid mentioning any positive elements. For instance, instead of saying \"this is good, but that needs improvement\", simply state \"that needs improvement\".",
+  "DEFAULT_AI_CHAT_REVIEW_PROMPT_DIFF": "Here are the PatchSet Diffs:",
+  "DEFAULT_AI_CHAT_REVIEW_PROMPT_MESSAGE_HISTORY": "Here are the message histories:",
+  "DEFAULT_AI_CHAT_HOW_TO_FIND_COMMIT_MESSAGE": "the \"content\" field of \"/COMMIT_MSG\" in the same way as the file changes"
 }
diff --git a/src/main/resources/documentation/about.md b/src/main/resources/documentation/about.md
index 670caa2..13d5dbd 100644
--- a/src/main/resources/documentation/about.md
+++ b/src/main/resources/documentation/about.md
@@ -1 +1 @@
-This plugin can send patches to GPT for code review.
\ No newline at end of file
+This plugin can send patch information to AI services for code review.
\ No newline at end of file
diff --git a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewStatefulTest.java b/src/test/java/com/googlesource/gerrit/plugins/aicodereview/AIChatReviewStatefulTest.java
similarity index 77%
rename from src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewStatefulTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/aicodereview/AIChatReviewStatefulTest.java
index 91e40a3..b31b9f7 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewStatefulTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/aicodereview/AIChatReviewStatefulTest.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview;
 
 import com.github.tomakehurst.wiremock.client.WireMock;
 import com.google.common.net.HttpHeaders;
@@ -7,14 +7,14 @@
 import com.google.gerrit.extensions.common.DiffInfo;
 import com.google.gerrit.extensions.restapi.BinaryResult;
 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.model.api.chatgpt.ChatGptListResponse;
-import com.googlesource.gerrit.plugins.chatgpt.settings.Settings.Modes;
-import com.googlesource.gerrit.plugins.chatgpt.utils.ThreadUtils;
+import com.googlesource.gerrit.plugins.aicodereview.data.PluginDataHandler;
+import com.googlesource.gerrit.plugins.aicodereview.data.PluginDataHandlerProvider;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.stateful.client.prompt.ChatGptPromptStateful;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatResponseContent;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.UriResourceLocatorStateful;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.model.api.chatgpt.ChatGptListResponse;
+import com.googlesource.gerrit.plugins.aicodereview.settings.Settings.Modes;
+import com.googlesource.gerrit.plugins.aicodereview.utils.ThreadUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.http.entity.ContentType;
 import org.junit.Assert;
@@ -29,32 +29,32 @@
 import java.io.ByteArrayInputStream;
 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;
-import static com.googlesource.gerrit.plugins.chatgpt.utils.GsonUtils.getGson;
+import static com.googlesource.gerrit.plugins.aicodereview.listener.EventHandlerTask.SupportedEvents;
+import static com.googlesource.gerrit.plugins.aicodereview.mode.common.client.prompt.AIChatPromptFactory.getAIChatPromptStateful;
+import static com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.chatgpt.ChatGptRun.COMPLETED_STATUS;
+import static com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.chatgpt.ChatGptVectorStore.KEY_VECTOR_STORE_ID;
+import static com.googlesource.gerrit.plugins.aicodereview.settings.Settings.GERRIT_PATCH_SET_FILENAME;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.GsonUtils.getGson;
 import static java.net.HttpURLConnection.HTTP_OK;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.*;
 
 @Slf4j
 @RunWith(MockitoJUnitRunner.class)
-public class ChatGptReviewStatefulTest extends ChatGptReviewTestBase {
-    private static final String CHAT_GPT_FILE_ID = "file-TEST_FILE_ID";
-    private static final String CHAT_GPT_VECTOR_ID = "file-TEST_VECTOR_ID";
-    private static final String CHAT_GPT_ASSISTANT_ID = "asst_TEST_ASSISTANT_ID";
-    private static final String CHAT_GPT_THREAD_ID = "thread_TEST_THREAD_ID";
-    private static final String CHAT_GPT_MESSAGE_ID = "msg_TEST_MESSAGE_ID";
-    private static final String CHAT_GPT_RUN_ID = "run_TEST_RUN_ID";
+public class AIChatReviewStatefulTest extends AIChatReviewTestBase {
+    private static final String AI_CHAT_FILE_ID = "file-TEST_FILE_ID";
+    private static final String AI_CHAT_VECTOR_ID = "file-TEST_VECTOR_ID";
+    private static final String AI_CHAT_ASSISTANT_ID = "asst_TEST_ASSISTANT_ID";
+    private static final String AI_CHAT_THREAD_ID = "thread_TEST_THREAD_ID";
+    private static final String AI_CHAT_MESSAGE_ID = "msg_TEST_MESSAGE_ID";
+    private static final String AI_CHAT_RUN_ID = "run_TEST_RUN_ID";
 
     private String formattedPatchContent;
-    private IChatGptPromptStateful chatGptPromptStateful;
+    private ChatGptPromptStateful chatGptPromptStateful;
     private String requestContent;
     private PluginDataHandler projectHandler;
 
-    public ChatGptReviewStatefulTest() {
+    public AIChatReviewStatefulTest() {
         MockitoAnnotations.openMocks(this);
     }
 
@@ -62,7 +62,7 @@
         super.initGlobalAndProjectConfig();
 
         // Mock the Global Config values that differ from the ones provided by Default
-        when(globalConfig.getString(Mockito.eq("gptMode"), Mockito.anyString()))
+        when(globalConfig.getString(Mockito.eq("aiMode"), Mockito.anyString()))
                 .thenReturn(Modes.stateful.name());
 
         setupPluginData();
@@ -78,7 +78,7 @@
         super.initTest();
 
         // Load the prompts
-        chatGptPromptStateful = getChatGptPromptStateful(config, changeSetData, getGerritChange());
+        chatGptPromptStateful = getAIChatPromptStateful(config, changeSetData, getGerritChange());
     }
 
     protected void setupMockRequests() throws RestApiException {
@@ -89,56 +89,56 @@
         when(gitRepoFiles.getGitRepoFiles(any(), any())).thenReturn(repoJson);
 
         // Mock the behavior of the ChatGPT create-file request
-        WireMock.stubFor(WireMock.post(WireMock.urlEqualTo(URI.create(config.getGptDomain()
+        WireMock.stubFor(WireMock.post(WireMock.urlEqualTo(URI.create(config.getAIDomain()
                         + UriResourceLocatorStateful.filesCreateUri()).getPath()))
                 .willReturn(WireMock.aResponse()
                         .withStatus(HTTP_OK)
                         .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
-                        .withBody("{\"id\": " + CHAT_GPT_FILE_ID + "}")));
+                        .withBody("{\"id\": " + AI_CHAT_FILE_ID + "}")));
 
         // Mock the behavior of the ChatGPT create-vector-store request
-        WireMock.stubFor(WireMock.post(WireMock.urlEqualTo(URI.create(config.getGptDomain()
+        WireMock.stubFor(WireMock.post(WireMock.urlEqualTo(URI.create(config.getAIDomain()
                         + UriResourceLocatorStateful.vectorStoreCreateUri()).getPath()))
                 .willReturn(WireMock.aResponse()
                         .withStatus(HTTP_OK)
                         .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
-                        .withBody("{\"id\": " + CHAT_GPT_VECTOR_ID + "}")));
+                        .withBody("{\"id\": " + AI_CHAT_VECTOR_ID + "}")));
 
         // Mock the behavior of the ChatGPT create-assistant request
-        WireMock.stubFor(WireMock.post(WireMock.urlEqualTo(URI.create(config.getGptDomain()
+        WireMock.stubFor(WireMock.post(WireMock.urlEqualTo(URI.create(config.getAIDomain()
                         + UriResourceLocatorStateful.assistantCreateUri()).getPath()))
                 .willReturn(WireMock.aResponse()
                         .withStatus(HTTP_OK)
                         .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
-                        .withBody("{\"id\": " + CHAT_GPT_ASSISTANT_ID + "}")));
+                        .withBody("{\"id\": " + AI_CHAT_ASSISTANT_ID + "}")));
 
         // Mock the behavior of the ChatGPT create-thread request
-        WireMock.stubFor(WireMock.post(WireMock.urlEqualTo(URI.create(config.getGptDomain()
+        WireMock.stubFor(WireMock.post(WireMock.urlEqualTo(URI.create(config.getAIDomain()
                         + UriResourceLocatorStateful.threadsUri()).getPath()))
                 .willReturn(WireMock.aResponse()
                         .withStatus(HTTP_OK)
                         .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
-                        .withBody("{\"id\": " + CHAT_GPT_THREAD_ID + "}")));
+                        .withBody("{\"id\": " + AI_CHAT_THREAD_ID + "}")));
 
         // Mock the behavior of the ChatGPT add-message-to-thread request
-        WireMock.stubFor(WireMock.post(WireMock.urlEqualTo(URI.create(config.getGptDomain()
-                        + UriResourceLocatorStateful.threadMessagesUri(CHAT_GPT_THREAD_ID)).getPath()))
+        WireMock.stubFor(WireMock.post(WireMock.urlEqualTo(URI.create(config.getAIDomain()
+                        + UriResourceLocatorStateful.threadMessagesUri(AI_CHAT_THREAD_ID)).getPath()))
                 .willReturn(WireMock.aResponse()
                         .withStatus(HTTP_OK)
                         .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
-                        .withBody("{\"id\": " + CHAT_GPT_MESSAGE_ID + "}")));
+                        .withBody("{\"id\": " + AI_CHAT_MESSAGE_ID + "}")));
 
         // Mock the behavior of the ChatGPT create-run request
-        WireMock.stubFor(WireMock.post(WireMock.urlEqualTo(URI.create(config.getGptDomain()
-                        + UriResourceLocatorStateful.runsUri(CHAT_GPT_THREAD_ID)).getPath()))
+        WireMock.stubFor(WireMock.post(WireMock.urlEqualTo(URI.create(config.getAIDomain()
+                        + UriResourceLocatorStateful.runsUri(AI_CHAT_THREAD_ID)).getPath()))
                 .willReturn(WireMock.aResponse()
                         .withStatus(HTTP_OK)
                         .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
-                        .withBody("{\"id\": " + CHAT_GPT_RUN_ID + "}")));
+                        .withBody("{\"id\": " + AI_CHAT_RUN_ID + "}")));
 
         // Mock the behavior of the ChatGPT retrieve-run request
-        WireMock.stubFor(WireMock.post(WireMock.urlEqualTo(URI.create(config.getGptDomain()
-                        + UriResourceLocatorStateful.runRetrieveUri(CHAT_GPT_THREAD_ID, CHAT_GPT_RUN_ID)).getPath()))
+        WireMock.stubFor(WireMock.post(WireMock.urlEqualTo(URI.create(config.getAIDomain()
+                        + UriResourceLocatorStateful.runRetrieveUri(AI_CHAT_THREAD_ID, AI_CHAT_RUN_ID)).getPath()))
                 .willReturn(WireMock.aResponse()
                         .withStatus(HTTP_OK)
                         .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
@@ -163,7 +163,7 @@
     protected void initComparisonContent() {
         super.initComparisonContent();
 
-        promptTagComments = readTestFile("__files/stateful/chatGptPromptTagRequests.json");
+        promptTagComments = readTestFile("__files/stateful/aiChatPromptTagRequests.json");
     }
 
     protected ArgumentCaptor<ReviewInput> testRequestSent() throws RestApiException {
@@ -176,7 +176,7 @@
         ChatGptListResponse responseContent = getGson().fromJson(readTestFile(responseFile), ChatGptListResponse.class);
         String reviewJsonResponse = responseContent.getData().get(0).getStepDetails().getToolCalls().get(tollCallId)
                 .getFunction().getArguments();
-        return getGson().fromJson(reviewJsonResponse, ChatGptResponseContent.class).getReplies().get(0).getReply();
+        return getGson().fromJson(reviewJsonResponse, AIChatResponseContent.class).getReplies().get(0).getReply();
     }
 
     private String getCapturedMessage(ArgumentCaptor<ReviewInput> captor, String filename) {
@@ -185,8 +185,8 @@
 
     private void mockRetrieveRunSteps(String bodyFile) {
         // Mock the behavior of the ChatGPT retrieve-run-steps request
-        WireMock.stubFor(WireMock.get(WireMock.urlEqualTo(URI.create(config.getGptDomain()
-                        + UriResourceLocatorStateful.runStepsUri(CHAT_GPT_THREAD_ID, CHAT_GPT_RUN_ID)).getPath()))
+        WireMock.stubFor(WireMock.get(WireMock.urlEqualTo(URI.create(config.getAIDomain()
+                        + UriResourceLocatorStateful.runStepsUri(AI_CHAT_THREAD_ID, AI_CHAT_RUN_ID)).getPath()))
                 .willReturn(WireMock.aResponse()
                         .withStatus(HTTP_OK)
                         .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
@@ -255,8 +255,8 @@
 
         chatGptPromptStateful.setCommentEvent(true);
         mockRetrieveRunSteps("chatGptResponseRequestMessageStateful.json");
-        WireMock.stubFor(WireMock.get(WireMock.urlEqualTo(URI.create(config.getGptDomain()
-                        + UriResourceLocatorStateful.threadMessageRetrieveUri(CHAT_GPT_THREAD_ID, CHAT_GPT_MESSAGE_ID)).getPath()))
+        WireMock.stubFor(WireMock.get(WireMock.urlEqualTo(URI.create(config.getAIDomain()
+                        + UriResourceLocatorStateful.threadMessageRetrieveUri(AI_CHAT_THREAD_ID, AI_CHAT_MESSAGE_ID)).getPath()))
                 .willReturn(WireMock.aResponse()
                         .withStatus(HTTP_OK)
                         .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
@@ -275,8 +275,8 @@
 
         chatGptPromptStateful.setCommentEvent(true);
         mockRetrieveRunSteps("chatGptResponseRequestMessageStateful.json");
-        WireMock.stubFor(WireMock.get(WireMock.urlEqualTo(URI.create(config.getGptDomain()
-                        + UriResourceLocatorStateful.threadMessageRetrieveUri(CHAT_GPT_THREAD_ID, CHAT_GPT_MESSAGE_ID)).getPath()))
+        WireMock.stubFor(WireMock.get(WireMock.urlEqualTo(URI.create(config.getAIDomain()
+                        + UriResourceLocatorStateful.threadMessageRetrieveUri(AI_CHAT_THREAD_ID, AI_CHAT_MESSAGE_ID)).getPath()))
                 .willReturn(WireMock.aResponse()
                         .withStatus(HTTP_OK)
                         .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
@@ -294,6 +294,6 @@
         projectHandler.removeValue(KEY_VECTOR_STORE_ID);
         handleEventBasedOnType(SupportedEvents.CHANGE_MERGED);
 
-        Assert.assertEquals(CHAT_GPT_VECTOR_ID, projectHandler.getValue(KEY_VECTOR_STORE_ID));
+        Assert.assertEquals(AI_CHAT_VECTOR_ID, projectHandler.getValue(KEY_VECTOR_STORE_ID));
     }
 }
diff --git a/src/test/java/com/googlesource/gerrit/plugins/aicodereview/AIChatReviewStatelessTest.java b/src/test/java/com/googlesource/gerrit/plugins/aicodereview/AIChatReviewStatelessTest.java
new file mode 100644
index 0000000..d25c9c9
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/aicodereview/AIChatReviewStatelessTest.java
@@ -0,0 +1,259 @@
+package com.googlesource.gerrit.plugins.aicodereview;
+
+import com.github.tomakehurst.wiremock.client.WireMock;
+import com.google.common.net.HttpHeaders;
+import com.google.gson.JsonArray;
+import com.googlesource.gerrit.plugins.aicodereview.listener.EventHandlerTask;
+import com.google.gerrit.extensions.api.changes.FileApi;
+import com.google.gerrit.extensions.api.changes.ReviewInput;
+import com.google.gerrit.extensions.common.DiffInfo;
+import com.google.gerrit.extensions.common.FileInfo;
+import com.google.gerrit.extensions.restapi.RestApiException;
+import com.google.gerrit.json.OutputFormat;
+import com.google.gson.Gson;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateless.client.api.UriResourceLocatorStateless;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateless.client.prompt.AIChatPromptStateless;
+import com.googlesource.gerrit.plugins.aicodereview.settings.Settings;
+import lombok.extern.slf4j.Slf4j;
+
+import org.apache.commons.lang3.reflect.TypeLiteral;
+import org.apache.http.entity.ContentType;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.net.URI;
+import java.util.Arrays;
+import java.util.Map;
+
+import static com.googlesource.gerrit.plugins.aicodereview.config.Configuration.*;
+import static com.googlesource.gerrit.plugins.aicodereview.listener.EventHandlerTask.SupportedEvents;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.TextUtils.joinWithNewLine;
+import static java.net.HttpURLConnection.HTTP_OK;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@Slf4j
+@RunWith(MockitoJUnitRunner.class)
+public class AIChatReviewStatelessTest extends AIChatReviewTestBase {
+    private ReviewInput expectedResponseStreamed;
+    private String expectedSystemPromptReview;
+    private String promptTagReview;
+    private String diffContent;
+    private ReviewInput gerritPatchSetReview;
+    private JsonArray prompts;
+
+    private AIChatPromptStateless AIChatPromptStateless;
+
+    protected void initConfig() {
+        super.initGlobalAndProjectConfig();
+
+        when(globalConfig.getBoolean(Mockito.eq(KEY_STREAM_OUTPUT), Mockito.anyBoolean()))
+                .thenReturn(GPT_STREAM_OUTPUT);
+        when(globalConfig.getBoolean(Mockito.eq("aiReviewCommitMessages"), Mockito.anyBoolean()))
+                .thenReturn(true);
+
+        super.initConfig();
+
+        // Load the prompts
+        AIChatPromptStateless = new AIChatPromptStateless(config);
+    }
+
+    protected void setupMockRequests() throws RestApiException {
+        super.setupMockRequests();
+
+        // Mock the behavior of the gerritPatchSetFiles request
+        Map<String, FileInfo> files = readTestFileToType(
+                "__files/stateless/gerritPatchSetFiles.json",
+                new TypeLiteral<Map<String, FileInfo>>() {}.getType()
+        );
+        when(revisionApiMock.files(0)).thenReturn(files);
+
+        // Mock the behavior of the gerritPatchSet diff requests
+        FileApi commitMsgFileMock = mock(FileApi.class);
+        when(revisionApiMock.file("/COMMIT_MSG")).thenReturn(commitMsgFileMock);
+        DiffInfo commitMsgFileDiff = readTestFileToClass("__files/stateless/gerritPatchSetDiffCommitMsg.json", DiffInfo.class);
+        when(commitMsgFileMock.diff(0)).thenReturn(commitMsgFileDiff);
+        FileApi testFileMock = mock(FileApi.class);
+        when(revisionApiMock.file("test_file.py")).thenReturn(testFileMock);
+        DiffInfo testFileDiff = readTestFileToClass("__files/stateless/gerritPatchSetDiffTestFile.json", DiffInfo.class);
+        when(testFileMock.diff(0)).thenReturn(testFileDiff);
+
+        // Mock the behavior of the askGpt request
+        WireMock.stubFor(WireMock.post(WireMock.urlEqualTo(URI.create(config.getAIDomain()
+                        + UriResourceLocatorStateless.chatCompletionsUri()).getPath()))
+                .willReturn(WireMock.aResponse()
+                        .withStatus(HTTP_OK)
+                        .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
+                        .withBodyFile("aiChatResponseStreamed.txt")));
+    }
+
+    protected void initComparisonContent() {
+        super.initComparisonContent();
+
+        diffContent = readTestFile("reducePatchSet/patchSetDiffOutput.json");
+        gerritPatchSetReview = readTestFileToClass("__files/stateless/gerritPatchSetReview.json", ReviewInput.class);
+        expectedResponseStreamed = readTestFileToClass("__files/stateless/aiChatExpectedResponseStreamed.json", ReviewInput.class);
+        promptTagReview = readTestFile("__files/stateless/aiChatPromptTagReview.json");
+        promptTagComments = readTestFile("__files/stateless/aiChatPromptTagRequests.json");
+        expectedSystemPromptReview = AIChatPromptStateless.getDefaultGptReviewSystemPrompt();
+    }
+
+    protected ArgumentCaptor<ReviewInput> testRequestSent() throws RestApiException {
+        ArgumentCaptor<ReviewInput> reviewInputCaptor = super.testRequestSent();
+        prompts = gptRequestBody.get("messages").getAsJsonArray();
+        return reviewInputCaptor;
+    }
+
+    private String getReviewUserPrompt() {
+        return joinWithNewLine(Arrays.asList(
+                AIChatPromptStateless.DEFAULT_AI_CHAT_REVIEW_PROMPT,
+                AIChatPromptStateless.DEFAULT_AI_CHAT_REVIEW_PROMPT_REVIEW + " " +
+                        AIChatPromptStateless.DEFAULT_AI_CHAT_PROMPT_FORCE_JSON_FORMAT + " " +
+                        AIChatPromptStateless.getPatchSetReviewPrompt(),
+                AIChatPromptStateless.getReviewPromptCommitMessages(),
+                AIChatPromptStateless.DEFAULT_AI_CHAT_REVIEW_PROMPT_DIFF,
+                diffContent,
+                AIChatPromptStateless.DEFAULT_AI_CHAT_REVIEW_PROMPT_MESSAGE_HISTORY,
+                promptTagReview
+        ));
+    }
+
+    @Test
+    public void patchSetCreatedOrUpdatedStreamed() throws Exception {
+        String reviewUserPrompt = getReviewUserPrompt();
+        AIChatPromptStateless.setCommentEvent(false);
+
+        handleEventBasedOnType(SupportedEvents.PATCH_SET_CREATED);
+
+        ArgumentCaptor<ReviewInput> captor = testRequestSent();
+        String systemPrompt = prompts.get(0).getAsJsonObject().get("content").getAsString();
+        Assert.assertEquals(expectedSystemPromptReview, systemPrompt);
+        String userPrompt = prompts.get(1).getAsJsonObject().get("content").getAsString();
+        Assert.assertEquals(reviewUserPrompt, userPrompt);
+
+        Gson gson = OutputFormat.JSON_COMPACT.newGson();
+        Assert.assertEquals(gson.toJson(expectedResponseStreamed), gson.toJson(captor.getAllValues().get(0)));
+    }
+
+    @Test
+    public void patchSetCreatedOrUpdatedUnstreamed() throws Exception {
+        when(globalConfig.getBoolean(Mockito.eq("aiStreamOutput"), Mockito.anyBoolean()))
+                .thenReturn(false);
+        when(globalConfig.getBoolean(Mockito.eq("enabledVoting"), Mockito.anyBoolean()))
+                .thenReturn(true);
+
+        String reviewUserPrompt = getReviewUserPrompt();
+        AIChatPromptStateless.setCommentEvent(false);
+        WireMock.stubFor(WireMock.post(WireMock.urlEqualTo(URI.create(config.getAIDomain()
+                        + UriResourceLocatorStateless.chatCompletionsUri()).getPath()))
+                .willReturn(WireMock.aResponse()
+                        .withStatus(HTTP_OK)
+                        .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
+                        .withBodyFile("aiChatResponseReview.json")));
+
+        handleEventBasedOnType(SupportedEvents.PATCH_SET_CREATED);
+
+        ArgumentCaptor<ReviewInput> captor = testRequestSent();
+        String userPrompt = prompts.get(1).getAsJsonObject().get("content").getAsString();
+        Assert.assertEquals(reviewUserPrompt, userPrompt);
+
+        Gson gson = OutputFormat.JSON_COMPACT.newGson();
+        Assert.assertEquals(gson.toJson(gerritPatchSetReview), gson.toJson(captor.getAllValues().get(0)));
+    }
+
+    @Test
+    public void patchSetDisableUserGroup() {
+        when(globalConfig.getString(Mockito.eq("disabledGroups"), Mockito.anyString()))
+                .thenReturn(GERRIT_USER_GROUP);
+
+        Assert.assertEquals(EventHandlerTask.Result.NOT_SUPPORTED, handleEventBasedOnType(SupportedEvents.PATCH_SET_CREATED));
+    }
+
+    @Test
+    public void gptMentionedInComment() throws RestApiException {
+        when(config.getGerritUserName()).thenReturn(GERRIT_GPT_USERNAME);
+        AIChatPromptStateless.setCommentEvent(true);
+        WireMock.stubFor(WireMock.post(WireMock.urlEqualTo(URI.create(config.getAIDomain()
+                        + UriResourceLocatorStateless.chatCompletionsUri()).getPath()))
+                .willReturn(WireMock.aResponse()
+                        .withStatus(HTTP_OK)
+                        .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
+                        .withBodyFile("aiChatResponseRequestStateless.json")));
+
+        handleEventBasedOnType(SupportedEvents.COMMENT_ADDED);
+        int commentPropertiesSize = gerritClient.getClientData(getGerritChange()).getCommentProperties().size();
+
+        String commentUserPrompt = joinWithNewLine(Arrays.asList(
+                AIChatPromptStateless.DEFAULT_AI_CHAT_REQUEST_PROMPT_DIFF,
+                diffContent,
+                AIChatPromptStateless.DEFAULT_AI_CHAT_REQUEST_PROMPT_REQUESTS,
+                readTestFile("__files/stateless/aiChatExpectedRequestMessage.json"),
+                AIChatPromptStateless.getCommentRequestPrompt(commentPropertiesSize)
+        ));
+        testRequestSent();
+        String userPrompt = prompts.get(1).getAsJsonObject().get("content").getAsString();
+        Assert.assertEquals(commentUserPrompt, userPrompt);
+    }
+
+    @Test
+    public void testAITypeValidOptions(){
+        when(globalConfig.getString(Mockito.eq("aiType"), Mockito.anyString()))
+                .thenReturn("CHATGPT");
+
+        // check default for aiType is chatGPT.
+        Assert.assertEquals(config.getAIType(), Settings.AIType.CHATGPT);
+
+        when(globalConfig.getString(Mockito.eq("aiType"), Mockito.anyString()))
+                .thenReturn("OLLAMA");
+
+        Assert.assertEquals(config.getAIType(), Settings.AIType.OLLAMA);
+    }
+
+    @Test
+    public void testAITypeControlsEndpoint(){
+        when(globalConfig.getString(Mockito.eq("aiType"), Mockito.anyString()))
+                .thenReturn("CHATGPT");
+
+        // check default for aiType is chatGPT.
+        Assert.assertEquals(config.getChatEndpoint(), "");
+        Assert.assertEquals(UriResourceLocatorStateless.chatCompletionsUri(),
+                UriResourceLocatorStateless.getChatResourceUri(config));
+
+        // swap it to ollama, check we still get the chatCompletionsUri, as its the openai
+        // compat endpoint we use.
+        when(globalConfig.getString(Mockito.eq("aiType"), Mockito.anyString()))
+                .thenReturn("OLLAMA");
+        Assert.assertEquals(UriResourceLocatorStateless.chatCompletionsUri(),
+                UriResourceLocatorStateless.getChatResourceUri(config));
+
+        // finally change to GENERIC, and check that we can specify any endpoint
+        when(globalConfig.getString(Mockito.eq(KEY_AI_TYPE), Mockito.anyString()))
+                .thenReturn("GENERIC");
+
+        final String expectedValueForEndpoint = "/someendpoint/someapi/chat";
+        when(globalConfig.getString(Mockito.eq(KEY_AI_CHAT_ENDPOINT), Mockito.anyString()))
+                .thenReturn(expectedValueForEndpoint);
+        Assert.assertEquals(expectedValueForEndpoint,
+                UriResourceLocatorStateless.getChatResourceUri(config));
+    }
+
+    @Test
+    public void testAITypeControlsAuthHeader(){
+        when(globalConfig.getString(Mockito.eq("aiType"), Mockito.anyString()))
+                .thenReturn("CHATGPT");
+
+        // check default for aiType is chatGPT.
+        Assert.assertEquals("Authorization", config.getAuthorizationHeaderInfo().getName());
+        Assert.assertEquals("Bearer " + config.getAIToken(), config.getAuthorizationHeaderInfo().getValue());
+
+        // swap it to ollama, check we still get the chatCompletionsUri, as its the openai
+        // compat endpoint we use.
+        when(globalConfig.getString(Mockito.eq("aiType"), Mockito.anyString()))
+                .thenReturn("OLLAMA");
+        Assert.assertNull("No expected value for auth header for ollama",  config.getAuthorizationHeaderInfo());
+    }
+}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewTestBase.java b/src/test/java/com/googlesource/gerrit/plugins/aicodereview/AIChatReviewTestBase.java
similarity index 84%
rename from src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewTestBase.java
rename to src/test/java/com/googlesource/gerrit/plugins/aicodereview/AIChatReviewTestBase.java
index f664bf9..1d81253 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewTestBase.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/aicodereview/AIChatReviewTestBase.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview;
 
 import com.github.tomakehurst.wiremock.junit.WireMockRule;
 import com.google.gerrit.entities.Account;
@@ -25,24 +25,24 @@
 import com.google.inject.Guice;
 import com.google.inject.TypeLiteral;
 import com.google.inject.util.Providers;
-import com.googlesource.gerrit.plugins.chatgpt.config.ConfigCreator;
-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.common.client.api.chatgpt.IChatGptClient;
-import com.googlesource.gerrit.plugins.chatgpt.interfaces.mode.common.client.api.gerrit.IGerritClientPatchSet;
-import com.googlesource.gerrit.plugins.chatgpt.listener.EventHandlerTask;
-import com.googlesource.gerrit.plugins.chatgpt.localization.Localizer;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritClient;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritClientComments;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritClientFacade;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritClientReview;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.chatgpt.ChatGptClientStateful;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.gerrit.GerritClientPatchSetStateful;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateful.client.api.git.GitRepoFiles;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateless.client.api.chatgpt.ChatGptClientStateless;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateless.client.api.gerrit.GerritClientPatchSetStateless;
+import com.googlesource.gerrit.plugins.aicodereview.config.ConfigCreator;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.data.PluginDataHandler;
+import com.googlesource.gerrit.plugins.aicodereview.data.PluginDataHandlerProvider;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.common.client.api.openapi.ChatAIClient;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.common.client.api.gerrit.GerritClientPatchSet;
+import com.googlesource.gerrit.plugins.aicodereview.listener.EventHandlerTask;
+import com.googlesource.gerrit.plugins.aicodereview.localization.Localizer;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritClient;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritClientComments;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritClientFacade;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritClientReview;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.chatai.AIChatClientStateful;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.gerrit.GerritClientPatchSetStateful;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateful.client.api.git.GitRepoFiles;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateless.client.api.chatai.AIChatClientStateless;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateless.client.api.gerrit.GerritClientPatchSetStateless;
 import lombok.NonNull;
 import org.junit.Before;
 import org.junit.Rule;
@@ -64,23 +64,23 @@
 import java.util.function.Consumer;
 
 import static com.google.gerrit.extensions.client.ChangeKind.REWORK;
-import static com.googlesource.gerrit.plugins.chatgpt.listener.EventHandlerTask.EVENT_CLASS_MAP;
-import static com.googlesource.gerrit.plugins.chatgpt.utils.GsonUtils.getGson;
+import static com.googlesource.gerrit.plugins.aicodereview.listener.EventHandlerTask.EVENT_CLASS_MAP;
+import static com.googlesource.gerrit.plugins.aicodereview.utils.GsonUtils.getGson;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-public class ChatGptReviewTestBase extends ChatGptTestBase {
+public class AIChatReviewTestBase extends AIChatTestBase {
     protected static final Path basePath = Paths.get("src/test/resources");
-    protected static final int GERRIT_GPT_ACCOUNT_ID = 1000000;
-    protected static final String GERRIT_GPT_USERNAME = "gpt";
-    protected static final int GERRIT_USER_ACCOUNT_ID = 1000001;
+    public static final int GERRIT_GPT_ACCOUNT_ID = 1000000;
+    public static final String GERRIT_GPT_USERNAME = "gpt";
+    public static final int GERRIT_USER_ACCOUNT_ID = 1000001;
     protected static final String GERRIT_USER_ACCOUNT_NAME = "Test";
     protected static final String GERRIT_USER_ACCOUNT_EMAIL = "test@example.com";
     protected static final String GERRIT_USER_USERNAME = "test";
     protected static final String GERRIT_USER_GROUP = "Test";
-    protected static final String GPT_TOKEN = "tk-test";
+    protected static final String AI_TOKEN = "tk-test";
     protected static final String GPT_DOMAIN = "http://localhost:9527";
     protected static final boolean GPT_STREAM_OUTPUT = true;
     protected static final long TEST_TIMESTAMP = 1699270812;
@@ -142,7 +142,7 @@
         };
 
         // Mock the Global Config values not provided by Default
-        when(globalConfig.getString("gptToken")).thenReturn(GPT_TOKEN);
+        when(globalConfig.getString("aiToken")).thenReturn(AI_TOKEN);
 
         // Mock the Global Config values to the Defaults passed as second arguments of the `get*` methods.
         when(globalConfig.getString(Mockito.anyString(), Mockito.anyString())).thenAnswer(returnDefaultArgument);
@@ -150,7 +150,7 @@
         when(globalConfig.getBoolean(Mockito.anyString(), Mockito.anyBoolean())).thenAnswer(returnDefaultArgument);
 
         // Mock the Global Config values that differ from the ones provided by Default
-        when(globalConfig.getString(Mockito.eq("gptDomain"), Mockito.anyString()))
+        when(globalConfig.getString(Mockito.eq("aiDomain"), Mockito.anyString()))
                 .thenReturn(GPT_DOMAIN);
         when(globalConfig.getString("gerritUserName")).thenReturn(GERRIT_GPT_USERNAME);
 
@@ -387,15 +387,15 @@
         return accountCache;
     }
 
-    private IChatGptClient getChatGptClient() {
-        return switch (config.getGptMode()) {
-            case stateful -> new ChatGptClientStateful(config, gitRepoFiles, pluginDataHandlerProvider);
-            case stateless -> new ChatGptClientStateless(config);
+    private ChatAIClient getChatGptClient() {
+        return switch (config.getAIMode()) {
+            case stateful -> new AIChatClientStateful(config, gitRepoFiles, pluginDataHandlerProvider);
+            case stateless -> new AIChatClientStateless(config);
         };
     }
 
-    private IGerritClientPatchSet getGerritClientPatchSet() {
-        return switch (config.getGptMode()) {
+    private GerritClientPatchSet getGerritClientPatchSet() {
+        return switch (config.getAIMode()) {
             case stateful -> new GerritClientPatchSetStateful(config, accountCacheMock);
             case stateless -> new GerritClientPatchSetStateless(config, accountCacheMock);
         };
diff --git a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptTestBase.java b/src/test/java/com/googlesource/gerrit/plugins/aicodereview/AIChatTestBase.java
similarity index 79%
rename from src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptTestBase.java
rename to src/test/java/com/googlesource/gerrit/plugins/aicodereview/AIChatTestBase.java
index d04186d..7e6aff2 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptTestBase.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/aicodereview/AIChatTestBase.java
@@ -1,9 +1,9 @@
-package com.googlesource.gerrit.plugins.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview;
 
 import com.google.gerrit.entities.BranchNameKey;
 import com.google.gerrit.entities.Change;
 import com.google.gerrit.entities.Project;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
 import org.junit.Rule;
 import org.junit.rules.TemporaryFolder;
 import org.mockito.Mock;
@@ -12,7 +12,7 @@
 
 import static org.mockito.Mockito.when;
 
-public class ChatGptTestBase {
+public class AIChatTestBase {
     protected static final Project.NameKey PROJECT_NAME = Project.NameKey.parse("myProject");
     protected static final Change.Key CHANGE_ID = Change.Key.parse("myChangeId");
     protected static final BranchNameKey BRANCH_NAME = BranchNameKey.create(PROJECT_NAME, "myBranchName");
@@ -34,6 +34,6 @@
     }
 
     protected GerritChange getGerritChange() {
-        return new GerritChange(ChatGptTestBase.PROJECT_NAME, ChatGptTestBase.BRANCH_NAME, ChatGptTestBase.CHANGE_ID);
+        return new GerritChange(AIChatTestBase.PROJECT_NAME, AIChatTestBase.BRANCH_NAME, AIChatTestBase.CHANGE_ID);
     }
 }
diff --git a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/PluginDataTest.java b/src/test/java/com/googlesource/gerrit/plugins/aicodereview/PluginDataTest.java
similarity index 89%
rename from src/test/java/com/googlesource/gerrit/plugins/chatgpt/PluginDataTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/aicodereview/PluginDataTest.java
index f6e6f83..5fee984 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/PluginDataTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/aicodereview/PluginDataTest.java
@@ -1,19 +1,19 @@
-package com.googlesource.gerrit.plugins.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview;
 
 import static org.junit.Assert.*;
 import static org.mockito.Mockito.when;
 
 import java.nio.file.Files;
 
-import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandler;
-import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandlerProvider;
+import com.googlesource.gerrit.plugins.aicodereview.data.PluginDataHandler;
+import com.googlesource.gerrit.plugins.aicodereview.data.PluginDataHandlerProvider;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.junit.MockitoJUnitRunner;
 
 @RunWith(MockitoJUnitRunner.class)
-public class PluginDataTest extends ChatGptTestBase {
+public class PluginDataTest extends AIChatTestBase {
 
     @Before
     public void setUp() {
diff --git a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/TemporaryFileTest.java b/src/test/java/com/googlesource/gerrit/plugins/aicodereview/TemporaryFileTest.java
similarity index 87%
rename from src/test/java/com/googlesource/gerrit/plugins/chatgpt/TemporaryFileTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/aicodereview/TemporaryFileTest.java
index 1ba3f63..30be370 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/TemporaryFileTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/aicodereview/TemporaryFileTest.java
@@ -1,4 +1,4 @@
-package com.googlesource.gerrit.plugins.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview;
 
 import static org.junit.Assert.*;
 
@@ -6,7 +6,7 @@
 import java.nio.file.Files;
 import java.nio.file.Path;
 
-import com.googlesource.gerrit.plugins.chatgpt.utils.FileUtils;
+import com.googlesource.gerrit.plugins.aicodereview.utils.FileUtils;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
diff --git a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/TestGerritEventContextModule.java b/src/test/java/com/googlesource/gerrit/plugins/aicodereview/TestGerritEventContextModule.java
similarity index 71%
rename from src/test/java/com/googlesource/gerrit/plugins/chatgpt/TestGerritEventContextModule.java
rename to src/test/java/com/googlesource/gerrit/plugins/aicodereview/TestGerritEventContextModule.java
index 7506e9a..47dd921 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/TestGerritEventContextModule.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/aicodereview/TestGerritEventContextModule.java
@@ -1,10 +1,10 @@
-package com.googlesource.gerrit.plugins.chatgpt;
+package com.googlesource.gerrit.plugins.aicodereview;
 
 import com.google.gerrit.extensions.annotations.PluginData;
 import com.google.gerrit.server.events.Event;
 import com.google.inject.Provides;
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.listener.GerritEventContextModule;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.listener.GerritEventContextModule;
 
 import java.nio.file.Path;
 import java.nio.file.Paths;
diff --git a/src/test/java/com/googlesource/gerrit/plugins/aicodereview/integration/CodeReviewPluginIT.java b/src/test/java/com/googlesource/gerrit/plugins/aicodereview/integration/CodeReviewPluginIT.java
new file mode 100644
index 0000000..f196ce4
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/aicodereview/integration/CodeReviewPluginIT.java
@@ -0,0 +1,84 @@
+package com.googlesource.gerrit.plugins.aicodereview.integration;
+
+import com.google.gerrit.server.account.AccountCache;
+import com.googlesource.gerrit.plugins.aicodereview.config.Configuration;
+import com.googlesource.gerrit.plugins.aicodereview.data.PluginDataHandlerProvider;
+import com.googlesource.gerrit.plugins.aicodereview.interfaces.mode.common.client.api.openapi.ChatAIClient;
+import com.googlesource.gerrit.plugins.aicodereview.localization.Localizer;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritChange;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritClient;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.client.api.gerrit.GerritClientReview;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.api.openai.AIChatResponseContent;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.data.ChangeSetData;
+import com.googlesource.gerrit.plugins.aicodereview.mode.common.model.review.ReviewBatch;
+import com.googlesource.gerrit.plugins.aicodereview.mode.stateless.client.prompt.AIChatPromptStateless;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static junit.framework.TestCase.assertNotNull;
+import static org.mockito.Mockito.when;
+
+@Ignore("This test suite is designed to demonstrate how to test the Gerrit and GPT interfaces in a real environment. " +
+        "It is not intended to be executed during the regular build process")
+@Slf4j
+@RunWith(MockitoJUnitRunner.class)
+public class CodeReviewPluginIT {
+    @Mock
+    private Configuration config;
+
+    @Mock
+    protected PluginDataHandlerProvider pluginDataHandlerProvider;
+
+    @InjectMocks
+    private GerritClient gerritClient;
+
+    @InjectMocks
+    private ChatAIClient chatGptClient;
+
+    @InjectMocks
+    private AccountCache accountCache;
+
+    @Test
+    public void sayHelloToGPT() throws Exception {
+        ChangeSetData changeSetData = new ChangeSetData(1, config.getVotingMinScore(), config.getMaxReviewFileSize());
+        AIChatPromptStateless AIChatPromptStateless = new AIChatPromptStateless(config, true);
+        when(config.getAIDomain()).thenReturn(Configuration.OPENAI_DOMAIN);
+        when(config.getAIToken()).thenReturn("Your GPT token");
+        when(config.getAIModel()).thenReturn(Configuration.DEFAULT_CHATGPT_MODEL);
+        when(AIChatPromptStateless.getAISystemPrompt()).thenReturn(AIChatPromptStateless.DEFAULT_AI_CHAT_SYSTEM_PROMPT);
+
+        AIChatResponseContent answer = chatGptClient.ask(changeSetData, new GerritChange(""), "hello");
+        log.info("answer: {}", answer);
+        assertNotNull(answer);
+    }
+
+    @Test
+    public void getPatchSet() throws Exception {
+        when(config.getGerritUserName()).thenReturn("Your Gerrit username");
+
+        String patchSet = gerritClient.getPatchSet("${changeId}");
+        log.info("patchSet: {}", patchSet);
+        assertNotNull(patchSet);
+    }
+
+    @Test
+    public void setReview() throws Exception {
+        ChangeSetData changeSetData = new ChangeSetData(1, config.getVotingMinScore(), config.getMaxReviewFileSize());
+        Localizer localizer = new Localizer(config);
+        when(config.getGerritUserName()).thenReturn("Your Gerrit username");
+
+        List<ReviewBatch> reviewBatches = new ArrayList<>();
+        reviewBatches.add(new ReviewBatch("message"));
+
+        GerritClientReview gerritClientReview = new GerritClientReview(config, accountCache, pluginDataHandlerProvider, localizer);
+        gerritClientReview.setReview(new GerritChange("Your changeId"), reviewBatches, changeSetData);
+    }
+}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewStatelessTest.java b/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewStatelessTest.java
deleted file mode 100644
index 2ff1254..0000000
--- a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewStatelessTest.java
+++ /dev/null
@@ -1,199 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt;
-
-import com.github.tomakehurst.wiremock.client.WireMock;
-import com.google.common.net.HttpHeaders;
-import com.google.gson.JsonArray;
-import com.googlesource.gerrit.plugins.chatgpt.listener.EventHandlerTask;
-import com.google.gerrit.extensions.api.changes.FileApi;
-import com.google.gerrit.extensions.api.changes.ReviewInput;
-import com.google.gerrit.extensions.common.DiffInfo;
-import com.google.gerrit.extensions.common.FileInfo;
-import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.json.OutputFormat;
-import com.google.gson.Gson;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateless.client.api.UriResourceLocatorStateless;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateless.client.prompt.ChatGptPromptStateless;
-import lombok.extern.slf4j.Slf4j;
-
-import org.apache.commons.lang3.reflect.TypeLiteral;
-import org.apache.http.entity.ContentType;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mockito;
-import org.mockito.junit.MockitoJUnitRunner;
-
-import java.net.URI;
-import java.util.Arrays;
-import java.util.Map;
-
-import static com.googlesource.gerrit.plugins.chatgpt.listener.EventHandlerTask.SupportedEvents;
-import static com.googlesource.gerrit.plugins.chatgpt.utils.TextUtils.joinWithNewLine;
-import static java.net.HttpURLConnection.HTTP_OK;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-@Slf4j
-@RunWith(MockitoJUnitRunner.class)
-public class ChatGptReviewStatelessTest extends ChatGptReviewTestBase {
-    private ReviewInput expectedResponseStreamed;
-    private String expectedSystemPromptReview;
-    private String promptTagReview;
-    private String diffContent;
-    private ReviewInput gerritPatchSetReview;
-    private JsonArray prompts;
-
-    private ChatGptPromptStateless chatGptPromptStateless;
-
-    protected void initConfig() {
-        super.initGlobalAndProjectConfig();
-
-        when(globalConfig.getBoolean(Mockito.eq("gptStreamOutput"), Mockito.anyBoolean()))
-                .thenReturn(GPT_STREAM_OUTPUT);
-        when(globalConfig.getBoolean(Mockito.eq("gptReviewCommitMessages"), Mockito.anyBoolean()))
-                .thenReturn(true);
-
-        super.initConfig();
-
-        // Load the prompts
-        chatGptPromptStateless = new ChatGptPromptStateless(config);
-    }
-
-    protected void setupMockRequests() throws RestApiException {
-        super.setupMockRequests();
-
-        // Mock the behavior of the gerritPatchSetFiles request
-        Map<String, FileInfo> files = readTestFileToType(
-                "__files/stateless/gerritPatchSetFiles.json",
-                new TypeLiteral<Map<String, FileInfo>>() {}.getType()
-        );
-        when(revisionApiMock.files(0)).thenReturn(files);
-
-        // Mock the behavior of the gerritPatchSet diff requests
-        FileApi commitMsgFileMock = mock(FileApi.class);
-        when(revisionApiMock.file("/COMMIT_MSG")).thenReturn(commitMsgFileMock);
-        DiffInfo commitMsgFileDiff = readTestFileToClass("__files/stateless/gerritPatchSetDiffCommitMsg.json", DiffInfo.class);
-        when(commitMsgFileMock.diff(0)).thenReturn(commitMsgFileDiff);
-        FileApi testFileMock = mock(FileApi.class);
-        when(revisionApiMock.file("test_file.py")).thenReturn(testFileMock);
-        DiffInfo testFileDiff = readTestFileToClass("__files/stateless/gerritPatchSetDiffTestFile.json", DiffInfo.class);
-        when(testFileMock.diff(0)).thenReturn(testFileDiff);
-
-        // Mock the behavior of the askGpt request
-        WireMock.stubFor(WireMock.post(WireMock.urlEqualTo(URI.create(config.getGptDomain()
-                        + UriResourceLocatorStateless.chatCompletionsUri()).getPath()))
-                .willReturn(WireMock.aResponse()
-                        .withStatus(HTTP_OK)
-                        .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
-                        .withBodyFile("chatGptResponseStreamed.txt")));
-    }
-
-    protected void initComparisonContent() {
-        super.initComparisonContent();
-
-        diffContent = readTestFile("reducePatchSet/patchSetDiffOutput.json");
-        gerritPatchSetReview = readTestFileToClass("__files/stateless/gerritPatchSetReview.json", ReviewInput.class);
-        expectedResponseStreamed = readTestFileToClass("__files/stateless/chatGptExpectedResponseStreamed.json", ReviewInput.class);
-        promptTagReview = readTestFile("__files/stateless/chatGptPromptTagReview.json");
-        promptTagComments = readTestFile("__files/stateless/chatGptPromptTagRequests.json");
-        expectedSystemPromptReview = ChatGptPromptStateless.getDefaultGptReviewSystemPrompt();
-    }
-
-    protected ArgumentCaptor<ReviewInput> testRequestSent() throws RestApiException {
-        ArgumentCaptor<ReviewInput> reviewInputCaptor = super.testRequestSent();
-        prompts = gptRequestBody.get("messages").getAsJsonArray();
-        return reviewInputCaptor;
-    }
-
-    private String getReviewUserPrompt() {
-        return joinWithNewLine(Arrays.asList(
-                ChatGptPromptStateless.DEFAULT_GPT_REVIEW_PROMPT,
-                ChatGptPromptStateless.DEFAULT_GPT_REVIEW_PROMPT_REVIEW + " " +
-                        ChatGptPromptStateless.DEFAULT_GPT_PROMPT_FORCE_JSON_FORMAT + " " +
-                        chatGptPromptStateless.getPatchSetReviewPrompt(),
-                ChatGptPromptStateless.getReviewPromptCommitMessages(),
-                ChatGptPromptStateless.DEFAULT_GPT_REVIEW_PROMPT_DIFF,
-                diffContent,
-                ChatGptPromptStateless.DEFAULT_GPT_REVIEW_PROMPT_MESSAGE_HISTORY,
-                promptTagReview
-        ));
-    }
-
-    @Test
-    public void patchSetCreatedOrUpdatedStreamed() throws Exception {
-        String reviewUserPrompt = getReviewUserPrompt();
-        chatGptPromptStateless.setCommentEvent(false);
-
-        handleEventBasedOnType(SupportedEvents.PATCH_SET_CREATED);
-
-        ArgumentCaptor<ReviewInput> captor = testRequestSent();
-        String systemPrompt = prompts.get(0).getAsJsonObject().get("content").getAsString();
-        Assert.assertEquals(expectedSystemPromptReview, systemPrompt);
-        String userPrompt = prompts.get(1).getAsJsonObject().get("content").getAsString();
-        Assert.assertEquals(reviewUserPrompt, userPrompt);
-
-        Gson gson = OutputFormat.JSON_COMPACT.newGson();
-        Assert.assertEquals(gson.toJson(expectedResponseStreamed), gson.toJson(captor.getAllValues().get(0)));
-    }
-
-    @Test
-    public void patchSetCreatedOrUpdatedUnstreamed() throws Exception {
-        when(globalConfig.getBoolean(Mockito.eq("gptStreamOutput"), Mockito.anyBoolean()))
-                .thenReturn(false);
-        when(globalConfig.getBoolean(Mockito.eq("enabledVoting"), Mockito.anyBoolean()))
-                .thenReturn(true);
-
-        String reviewUserPrompt = getReviewUserPrompt();
-        chatGptPromptStateless.setCommentEvent(false);
-        WireMock.stubFor(WireMock.post(WireMock.urlEqualTo(URI.create(config.getGptDomain()
-                        + UriResourceLocatorStateless.chatCompletionsUri()).getPath()))
-                .willReturn(WireMock.aResponse()
-                        .withStatus(HTTP_OK)
-                        .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
-                        .withBodyFile("chatGptResponseReview.json")));
-
-        handleEventBasedOnType(SupportedEvents.PATCH_SET_CREATED);
-
-        ArgumentCaptor<ReviewInput> captor = testRequestSent();
-        String userPrompt = prompts.get(1).getAsJsonObject().get("content").getAsString();
-        Assert.assertEquals(reviewUserPrompt, userPrompt);
-
-        Gson gson = OutputFormat.JSON_COMPACT.newGson();
-        Assert.assertEquals(gson.toJson(gerritPatchSetReview), gson.toJson(captor.getAllValues().get(0)));
-    }
-
-    @Test
-    public void patchSetDisableUserGroup() {
-        when(globalConfig.getString(Mockito.eq("disabledGroups"), Mockito.anyString()))
-                .thenReturn(GERRIT_USER_GROUP);
-
-        Assert.assertEquals(EventHandlerTask.Result.NOT_SUPPORTED, handleEventBasedOnType(SupportedEvents.PATCH_SET_CREATED));
-    }
-
-    @Test
-    public void gptMentionedInComment() throws RestApiException {
-        when(config.getGerritUserName()).thenReturn(GERRIT_GPT_USERNAME);
-        chatGptPromptStateless.setCommentEvent(true);
-        WireMock.stubFor(WireMock.post(WireMock.urlEqualTo(URI.create(config.getGptDomain()
-                        + UriResourceLocatorStateless.chatCompletionsUri()).getPath()))
-                .willReturn(WireMock.aResponse()
-                        .withStatus(HTTP_OK)
-                        .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
-                        .withBodyFile("chatGptResponseRequestStateless.json")));
-
-        handleEventBasedOnType(SupportedEvents.COMMENT_ADDED);
-        int commentPropertiesSize = gerritClient.getClientData(getGerritChange()).getCommentProperties().size();
-
-        String commentUserPrompt = joinWithNewLine(Arrays.asList(
-                ChatGptPromptStateless.DEFAULT_GPT_REQUEST_PROMPT_DIFF,
-                diffContent,
-                ChatGptPromptStateless.DEFAULT_GPT_REQUEST_PROMPT_REQUESTS,
-                readTestFile("__files/stateless/chatGptExpectedRequestMessage.json"),
-                ChatGptPromptStateless.getCommentRequestPrompt(commentPropertiesSize)
-        ));
-        testRequestSent();
-        String userPrompt = prompts.get(1).getAsJsonObject().get("content").getAsString();
-        Assert.assertEquals(commentUserPrompt, userPrompt);
-    }
-}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/integration/CodeReviewPluginIT.java b/src/test/java/com/googlesource/gerrit/plugins/chatgpt/integration/CodeReviewPluginIT.java
deleted file mode 100644
index 220e993..0000000
--- a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/integration/CodeReviewPluginIT.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package com.googlesource.gerrit.plugins.chatgpt.integration;
-
-import com.google.gerrit.server.account.AccountCache;
-import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.data.PluginDataHandlerProvider;
-import com.googlesource.gerrit.plugins.chatgpt.interfaces.mode.common.client.api.chatgpt.IChatGptClient;
-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.client.api.gerrit.GerritClient;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritClientReview;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.chatgpt.ChatGptResponseContent;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.review.ReviewBatch;
-import com.googlesource.gerrit.plugins.chatgpt.mode.stateless.client.prompt.ChatGptPromptStateless;
-import lombok.extern.slf4j.Slf4j;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnitRunner;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static junit.framework.TestCase.assertNotNull;
-import static org.mockito.Mockito.when;
-
-@Ignore("This test suite is designed to demonstrate how to test the Gerrit and GPT interfaces in a real environment. " +
-        "It is not intended to be executed during the regular build process")
-@Slf4j
-@RunWith(MockitoJUnitRunner.class)
-public class CodeReviewPluginIT {
-    @Mock
-    private Configuration config;
-
-    @Mock
-    protected PluginDataHandlerProvider pluginDataHandlerProvider;
-
-    @InjectMocks
-    private GerritClient gerritClient;
-
-    @InjectMocks
-    private IChatGptClient chatGptClient;
-
-    @InjectMocks
-    private AccountCache accountCache;
-
-    @Test
-    public void sayHelloToGPT() throws Exception {
-        ChangeSetData changeSetData = new ChangeSetData(1, config.getVotingMinScore(), config.getMaxReviewFileSize());
-        ChatGptPromptStateless chatGptPromptStateless = new ChatGptPromptStateless(config, true);
-        when(config.getGptDomain()).thenReturn(Configuration.OPENAI_DOMAIN);
-        when(config.getGptToken()).thenReturn("Your GPT token");
-        when(config.getGptModel()).thenReturn(Configuration.DEFAULT_GPT_MODEL);
-        when(chatGptPromptStateless.getGptSystemPrompt()).thenReturn(ChatGptPromptStateless.DEFAULT_GPT_SYSTEM_PROMPT);
-
-        ChatGptResponseContent answer = chatGptClient.ask(changeSetData, new GerritChange(""), "hello");
-        log.info("answer: {}", answer);
-        assertNotNull(answer);
-    }
-
-    @Test
-    public void getPatchSet() throws Exception {
-        when(config.getGerritUserName()).thenReturn("Your Gerrit username");
-
-        String patchSet = gerritClient.getPatchSet("${changeId}");
-        log.info("patchSet: {}", patchSet);
-        assertNotNull(patchSet);
-    }
-
-    @Test
-    public void setReview() throws Exception {
-        ChangeSetData changeSetData = new ChangeSetData(1, config.getVotingMinScore(), config.getMaxReviewFileSize());
-        Localizer localizer = new Localizer(config);
-        when(config.getGerritUserName()).thenReturn("Your Gerrit username");
-
-        List<ReviewBatch> reviewBatches = new ArrayList<>();
-        reviewBatches.add(new ReviewBatch("message"));
-
-        GerritClientReview gerritClientReview = new GerritClientReview(config, accountCache, pluginDataHandlerProvider, localizer);
-        gerritClientReview.setReview(new GerritChange("Your changeId"), reviewBatches, changeSetData);
-    }
-}
diff --git a/src/test/resources/__files/chatGptResponseRequestStateless.json b/src/test/resources/__files/aiChatResponseRequestStateless.json
similarity index 100%
rename from src/test/resources/__files/chatGptResponseRequestStateless.json
rename to src/test/resources/__files/aiChatResponseRequestStateless.json
diff --git a/src/test/resources/__files/chatGptResponseReview.json b/src/test/resources/__files/aiChatResponseReview.json
similarity index 100%
rename from src/test/resources/__files/chatGptResponseReview.json
rename to src/test/resources/__files/aiChatResponseReview.json
diff --git a/src/test/resources/__files/chatGptResponseStreamed.txt b/src/test/resources/__files/aiChatResponseStreamed.txt
similarity index 100%
rename from src/test/resources/__files/chatGptResponseStreamed.txt
rename to src/test/resources/__files/aiChatResponseStreamed.txt
diff --git a/src/test/resources/__files/stateful/chatGptPromptTagRequests.json b/src/test/resources/__files/stateful/aiChatPromptTagRequests.json
similarity index 100%
rename from src/test/resources/__files/stateful/chatGptPromptTagRequests.json
rename to src/test/resources/__files/stateful/aiChatPromptTagRequests.json
diff --git a/src/test/resources/__files/stateless/chatGptExpectedRequestMessage.json b/src/test/resources/__files/stateless/aiChatExpectedRequestMessage.json
similarity index 100%
rename from src/test/resources/__files/stateless/chatGptExpectedRequestMessage.json
rename to src/test/resources/__files/stateless/aiChatExpectedRequestMessage.json
diff --git a/src/test/resources/__files/stateless/chatGptExpectedResponseStreamed.json b/src/test/resources/__files/stateless/aiChatExpectedResponseStreamed.json
similarity index 100%
rename from src/test/resources/__files/stateless/chatGptExpectedResponseStreamed.json
rename to src/test/resources/__files/stateless/aiChatExpectedResponseStreamed.json
diff --git a/src/test/resources/__files/stateless/chatGptPromptTagRequests.json b/src/test/resources/__files/stateless/aiChatPromptTagRequests.json
similarity index 100%
rename from src/test/resources/__files/stateless/chatGptPromptTagRequests.json
rename to src/test/resources/__files/stateless/aiChatPromptTagRequests.json
diff --git a/src/test/resources/__files/stateless/chatGptPromptTagReview.json b/src/test/resources/__files/stateless/aiChatPromptTagReview.json
similarity index 100%
rename from src/test/resources/__files/stateless/chatGptPromptTagReview.json
rename to src/test/resources/__files/stateless/aiChatPromptTagReview.json