diff --git a/ee/app/assets/javascripts/ai/components/ai_genie_chat_message.vue b/ee/app/assets/javascripts/ai/components/ai_genie_chat_message.vue
index c2ec668cdd85b7904f5f46f5d1fafeca07170c12..d7da37abb4507014473ea2f7b0c6907afafc30b5 100644
--- a/ee/app/assets/javascripts/ai/components/ai_genie_chat_message.vue
+++ b/ee/app/assets/javascripts/ai/components/ai_genie_chat_message.vue
@@ -5,8 +5,17 @@ import SafeHtml from '~/vue_shared/directives/safe_html';
 import { renderGFM } from '~/behaviors/markdown/render_gfm';
 import { GENIE_CHAT_MODEL_ROLES } from '../constants';
 
+const concatIndicesUntilEmpty = (arr) => {
+  const start = arr.findIndex((el) => el);
+  if (start === -1 || start !== 1) return ''; // If there are no non-empty elements
+
+  const end = arr.slice(start).findIndex((el) => !el);
+  return end > 0 ? arr.slice(start, end).join('') : arr.slice(start).join('');
+};
+
 export default {
   name: 'AiGenieChatMessage',
+  messageChunks: [],
   directives: {
     SafeHtml,
   },
@@ -26,16 +35,34 @@ export default {
       messageContent: renderMarkdown(this.message.content || this.message.errors[0]),
     };
   },
-  mounted() {
-    this.hydrateContentWithGFM();
-  },
-  methods: {
-    isAssistantMessage(message) {
-      return message.role.toLowerCase() === GENIE_CHAT_MODEL_ROLES.assistant;
+  computed: {
+    isAssistantMessage() {
+      return this.message.role.toLowerCase() === GENIE_CHAT_MODEL_ROLES.assistant;
     },
-    isUserMessage(message) {
-      return message.role.toLowerCase() === GENIE_CHAT_MODEL_ROLES.user;
+    isUserMessage() {
+      return this.message.role.toLowerCase() === GENIE_CHAT_MODEL_ROLES.user;
     },
+  },
+  watch: {
+    message: {
+      handler() {
+        const { chunkId, content, errors } = this.message;
+        if (!chunkId) {
+          this.$options.messageChunks = [];
+          this.messageContent = renderMarkdown(content || errors[0]);
+          this.hydrateContentWithGFM();
+        } else {
+          this.$options.messageChunks[chunkId] = content;
+          this.messageContent = renderMarkdown(
+            concatIndicesUntilEmpty(this.$options.messageChunks),
+          );
+        }
+      },
+      immediate: true,
+      deep: true,
+    },
+  },
+  methods: {
     async hydrateContentWithGFM() {
       const textToConvert = this.message.content || this.message.errors[0];
       if (textToConvert) {
@@ -51,17 +78,13 @@ export default {
   <div
     class="gl-py-3 gl-mb-4 gl-px-4 gl-rounded-lg gl-line-height-20 gl-word-break-word ai-genie-chat-message"
     :class="{
-      'gl-ml-auto gl-bg-blue-100 gl-text-blue-900 gl-rounded-bottom-right-none': isUserMessage(
-        message,
-      ),
-      'gl-rounded-bottom-left-none gl-text-gray-900 gl-bg-white gl-border-1 gl-border-solid gl-border-gray-50': isAssistantMessage(
-        message,
-      ),
+      'gl-ml-auto gl-bg-blue-100 gl-text-blue-900 gl-rounded-bottom-right-none': isUserMessage,
+      'gl-rounded-bottom-left-none gl-text-gray-900 gl-bg-white gl-border-1 gl-border-solid gl-border-gray-50': isAssistantMessage,
     }"
   >
     <div ref="content" v-safe-html="messageContent"></div>
     <slot
-      v-if="isAssistantMessage(message)"
+      v-if="isAssistantMessage"
       name="feedback"
       :prompt-location="promptLocation"
       :message="message"
diff --git a/ee/app/assets/javascripts/ai/graphql/chat.mutation.graphql b/ee/app/assets/javascripts/ai/graphql/chat.mutation.graphql
index c26d8270de374eb739b8d6cd706e301060e6ee21..6ae83926f55f2f726e309b9d5ab7645b0c4a4b11 100644
--- a/ee/app/assets/javascripts/ai/graphql/chat.mutation.graphql
+++ b/ee/app/assets/javascripts/ai/graphql/chat.mutation.graphql
@@ -1,5 +1,10 @@
-mutation chat($question: String!, $resourceId: AiModelID!) {
-  aiAction(input: { chat: { resourceId: $resourceId, content: $question } }) {
+mutation chat($question: String!, $resourceId: AiModelID!, $clientSubscriptionId: String) {
+  aiAction(
+    input: {
+      chat: { resourceId: $resourceId, content: $question }
+      clientSubscriptionId: $clientSubscriptionId
+    }
+  ) {
     requestId
     errors
   }
diff --git a/ee/app/assets/javascripts/ai/tanuki_bot/components/app.vue b/ee/app/assets/javascripts/ai/tanuki_bot/components/app.vue
index 5dea45dc3129d11b725cde4d1bfbb9e7b502cc75..3313956bff8b3dd2576d0c90147ac4f5e5aa3e30 100644
--- a/ee/app/assets/javascripts/ai/tanuki_bot/components/app.vue
+++ b/ee/app/assets/javascripts/ai/tanuki_bot/components/app.vue
@@ -2,6 +2,7 @@
 import { GlIcon, GlLink } from '@gitlab/ui';
 // eslint-disable-next-line no-restricted-imports
 import { mapActions, mapState } from 'vuex';
+import { v4 as uuidv4 } from 'uuid';
 import { __, s__, n__ } from '~/locale';
 import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
 import { helpCenterState } from '~/super_sidebar/constants';
@@ -75,6 +76,24 @@ export default {
           });
         },
       },
+      aiCompletionResponseStream: {
+        query: aiResponseSubscription,
+        variables() {
+          return {
+            userId: this.userId,
+            resourceId: this.resourceId || this.userId,
+            clientSubscriptionId: this.clientSubscriptionId,
+          };
+        },
+        result({ data }) {
+          this.addDuoChatMessage(data?.aiCompletionResponse);
+        },
+        error(err) {
+          this.addDuoChatMessage({
+            errors: [err],
+          });
+        },
+      },
     },
     aiMessages: {
       query: getAiMessages,
@@ -93,6 +112,7 @@ export default {
   data() {
     return {
       helpCenterState,
+      clientSubscriptionId: uuidv4(),
     };
   },
   computed: {
@@ -111,6 +131,7 @@ export default {
           variables: {
             question,
             resourceId: this.resourceId || this.userId,
+            clientSubscriptionId: this.clientSubscriptionId,
           },
         })
         .then(({ data: { aiAction = {} } = {} }) => {
diff --git a/ee/app/assets/javascripts/ai/tanuki_bot/store/actions.js b/ee/app/assets/javascripts/ai/tanuki_bot/store/actions.js
index 0ca11f6cae4d79ea78ff1cfa143f9321a5b79599..22febc767f58c51efffa7bc9eb5f5411a3f480fb 100644
--- a/ee/app/assets/javascripts/ai/tanuki_bot/store/actions.js
+++ b/ee/app/assets/javascripts/ai/tanuki_bot/store/actions.js
@@ -20,6 +20,17 @@ export const addDuoChatMessage = async ({ commit }, messageData = { content: ''
     let parsedResponse;
     try {
       parsedResponse = JSON.parse(msgContent);
+
+      // JSON.parse does not throw when parsing Strings that are coerced to primary data types, like Number or Boolean.
+      // JSON.parse("1") would return 1 (Number), same as JSON.parse("false"), which returns false (Boolean).
+      // We therefore check if the parsed response is really an Object.
+      // This will be solved with https://gitlab.com/gitlab-org/gitlab/-/issues/423315 when we no longer receive
+      // potential JSON as a string.
+      if (typeof parsedResponse !== 'object') {
+        parsedResponse = {
+          content: msgContent,
+        };
+      }
     } catch {
       parsedResponse = { content: msgContent };
     }
diff --git a/ee/app/assets/javascripts/ai/tanuki_bot/store/mutations.js b/ee/app/assets/javascripts/ai/tanuki_bot/store/mutations.js
index 5067667532b10c9e60ffc0f2ab7f7800450ebed9..b96cbf1919b5f2c77777d1bf3f2e9fda085eb2dd 100644
--- a/ee/app/assets/javascripts/ai/tanuki_bot/store/mutations.js
+++ b/ee/app/assets/javascripts/ai/tanuki_bot/store/mutations.js
@@ -8,23 +8,39 @@ export default {
       if (newMessageData.role.toLowerCase() === GENIE_CHAT_MODEL_ROLES.system) {
         return;
       }
-      const index = state.messages.findIndex((msg) => msg.requestId === newMessageData.requestId);
-      const hasMsgWithRequestId = index > -1;
-      const msgWithRequestId = hasMsgWithRequestId && state.messages[index];
       let isLastMessage = false;
 
-      if (hasMsgWithRequestId) {
-        if (msgWithRequestId.role.toLowerCase() === newMessageData.role.toLowerCase()) {
-          // We update the existing message object instead of pushing a new one
-          state.messages[index] = {
-            ...msgWithRequestId,
-            ...newMessageData,
-          };
-        } else {
-          // We add the new ASSISTANT message
-          isLastMessage = index === state.messages.length - 1;
-          state.messages.splice(index + 1, 0, newMessageData);
-        }
+      const getExistingMesagesIndex = (role) =>
+        state.messages.findIndex(
+          (msg) => msg.requestId === newMessageData.requestId && msg.role.toLowerCase() === role,
+        );
+      const userMessageWithRequestIdIndex = getExistingMesagesIndex(GENIE_CHAT_MODEL_ROLES.user);
+      const assistantMessageWithRequestIdIndex = getExistingMesagesIndex(
+        GENIE_CHAT_MODEL_ROLES.assistant,
+      );
+      const assistantMessageExists = assistantMessageWithRequestIdIndex > -1;
+      const userMessageExists = userMessageWithRequestIdIndex > -1;
+
+      const isUserMesasge = newMessageData.role.toLowerCase() === GENIE_CHAT_MODEL_ROLES.user;
+      const isAssistantMessage =
+        newMessageData.role.toLowerCase() === GENIE_CHAT_MODEL_ROLES.assistant;
+
+      if (assistantMessageExists && isAssistantMessage) {
+        // We update the existing ASSISTANT message object instead of pushing a new one
+        state.messages.splice(assistantMessageWithRequestIdIndex, 1, {
+          ...state.messages[assistantMessageWithRequestIdIndex],
+          ...newMessageData,
+        });
+      } else if (userMessageExists && isUserMesasge) {
+        // We update the existing USER message object instead of pushing a new one
+        state.messages.splice(userMessageWithRequestIdIndex, 1, {
+          ...state.messages[userMessageWithRequestIdIndex],
+          ...newMessageData,
+        });
+      } else if (userMessageExists && isAssistantMessage) {
+        // We add the new ASSISTANT message
+        isLastMessage = userMessageWithRequestIdIndex === state.messages.length - 1;
+        state.messages.splice(userMessageWithRequestIdIndex + 1, 0, newMessageData);
       } else {
         // It's the new message, so just push it to the end of the Array
         state.messages.push(newMessageData);
diff --git a/ee/app/assets/javascripts/graphql_shared/subscriptions/ai_completion_response.subscription.graphql b/ee/app/assets/javascripts/graphql_shared/subscriptions/ai_completion_response.subscription.graphql
index c4603081e01c45bc1db60f27663d1b0ca7e9530d..02c8b0cbe81642056c427309ba8f1cc8866240d6 100644
--- a/ee/app/assets/javascripts/graphql_shared/subscriptions/ai_completion_response.subscription.graphql
+++ b/ee/app/assets/javascripts/graphql_shared/subscriptions/ai_completion_response.subscription.graphql
@@ -1,10 +1,19 @@
-subscription aiCompletionResponse($userId: UserID, $resourceId: AiModelID!) {
-  aiCompletionResponse(userId: $userId, resourceId: $resourceId) {
+subscription aiCompletionResponse(
+  $userId: UserID
+  $resourceId: AiModelID!
+  $clientSubscriptionId: String
+) {
+  aiCompletionResponse(
+    userId: $userId
+    resourceId: $resourceId
+    clientSubscriptionId: $clientSubscriptionId
+  ) {
     requestId
     responseBody
     errors
     role
     timestamp
     type
+    chunkId
   }
 }
diff --git a/ee/spec/frontend/ai/components/ai_genie_chat_message_spec.js b/ee/spec/frontend/ai/components/ai_genie_chat_message_spec.js
index 39fa7bcda54eb8c053985bf0645e5c44f9792ffa..e45c26b30003bdab116d1c3e88dfc66d43f5a621 100644
--- a/ee/spec/frontend/ai/components/ai_genie_chat_message_spec.js
+++ b/ee/spec/frontend/ai/components/ai_genie_chat_message_spec.js
@@ -1,3 +1,4 @@
+import { nextTick } from 'vue';
 import waitForPromises from 'helpers/wait_for_promises';
 import AiGenieChatMessage from 'ee/ai/components/ai_genie_chat_message.vue';
 import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
@@ -10,6 +11,8 @@ jest.mock('~/rest_api');
 describe('AiGenieChatMessage', () => {
   let wrapper;
 
+  const findContent = () => wrapper.findComponent({ ref: 'content' });
+
   const createComponent = ({
     propsData = { message: MOCK_USER_MESSAGE },
     scopedSlots = {},
@@ -95,4 +98,155 @@ describe('AiGenieChatMessage', () => {
       });
     });
   });
+
+  describe('message output', () => {
+    it('hydrates the message with GLFM when mounting the component', () => {
+      createComponent();
+      expect(getMarkdown).toHaveBeenCalledWith({ text: MOCK_USER_MESSAGE.content, gfm: true });
+    });
+
+    it('listens to the message changes', async () => {
+      const newContent = 'new foo content';
+      createComponent();
+      // setProps is justified here because we are testing the component's
+      // reactive behavior which consistutes an exception
+      // See https://docs.gitlab.com/ee/development/fe_guide/style/vue.html#setting-component-state
+      wrapper.setProps({
+        message: {
+          ...MOCK_USER_MESSAGE,
+          content: newContent,
+        },
+      });
+      await nextTick();
+      expect(findContent().text()).not.toContain(MOCK_USER_MESSAGE.content);
+      expect(findContent().text()).toContain(newContent);
+    });
+  });
+
+  describe('updates to the message', () => {
+    const content1 = 'chunk #1';
+    const content2 = ' chunk #2';
+    const content3 = ' chunk #3';
+    const chunk1 = {
+      ...MOCK_USER_MESSAGE,
+      content: content1,
+      chunkId: 1,
+    };
+    const chunk2 = {
+      ...MOCK_USER_MESSAGE,
+      content: content2,
+      chunkId: 2,
+    };
+    const chunk3 = {
+      ...MOCK_USER_MESSAGE,
+      content: content3,
+      chunkId: 3,
+    };
+
+    beforeEach(() => {
+      createComponent();
+    });
+
+    it('does not fail if the message has no chunkId', async () => {
+      // setProps is justified here because we are testing the component's
+      // reactive behavior which consistutes an exception
+      // See https://docs.gitlab.com/ee/development/fe_guide/style/vue.html#setting-component-state
+      wrapper.setProps({
+        message: {
+          ...MOCK_USER_MESSAGE,
+          content: content1,
+        },
+      });
+      await nextTick();
+      expect(findContent().text()).toBe(content1);
+    });
+
+    it('renders chunks correctly when the chunks arrive out of order', async () => {
+      // setProps is justified here because we are testing the component's
+      // reactive behavior which consistutes an exception
+      // See https://docs.gitlab.com/ee/development/fe_guide/style/vue.html#setting-component-state
+      wrapper.setProps({
+        message: chunk2,
+      });
+      await nextTick();
+      expect(findContent().text()).toBe('');
+
+      wrapper.setProps({
+        message: chunk1,
+      });
+      await nextTick();
+      expect(findContent().text()).toBe(content1 + content2);
+
+      wrapper.setProps({
+        message: chunk3,
+      });
+      await nextTick();
+      expect(findContent().text()).toBe(content1 + content2 + content3);
+    });
+
+    it('renders the chunks as they arrive', async () => {
+      const consolidatedContent = content1 + content2;
+
+      // setProps is justified here because we are testing the component's
+      // reactive behavior which consistutes an exception
+      // See https://docs.gitlab.com/ee/development/fe_guide/style/vue.html#setting-component-state
+      wrapper.setProps({
+        message: chunk1,
+      });
+      await nextTick();
+      expect(findContent().text()).toBe(content1);
+
+      wrapper.setProps({
+        message: chunk2,
+      });
+      await nextTick();
+      expect(findContent().text()).toBe(consolidatedContent);
+    });
+
+    it('treats the initial message content as chunk if message has chunkId', async () => {
+      createComponent({
+        propsData: {
+          message: chunk1,
+        },
+      });
+      expect(findContent().text()).toBe(content1);
+
+      // setProps is justified here because we are testing the component's
+      // reactive behavior which consistutes an exception
+      // See https://docs.gitlab.com/ee/development/fe_guide/style/vue.html#setting-component-state
+      wrapper.setProps({
+        message: chunk2,
+      });
+      await nextTick();
+      expect(findContent().text()).toBe(content1 + content2);
+    });
+
+    it('hydrates the message with GLFM when the updated message is not a chunk', async () => {
+      createComponent({
+        propsData: {
+          message: chunk1,
+        },
+      });
+      getMarkdown.mockClear();
+      expect(getMarkdown).not.toHaveBeenCalled();
+
+      // setProps is justified here because we are testing the component's
+      // reactive behavior which consistutes an exception
+      // See https://docs.gitlab.com/ee/development/fe_guide/style/vue.html#setting-component-state
+      wrapper.setProps({
+        message: chunk2,
+      });
+      await nextTick();
+      expect(getMarkdown).not.toHaveBeenCalled();
+
+      wrapper.setProps({
+        message: {
+          ...chunk3,
+          chunkId: null,
+        },
+      });
+      await nextTick();
+      expect(getMarkdown).toHaveBeenCalledWith({ text: content3, gfm: true });
+    });
+  });
 });
diff --git a/ee/spec/frontend/ai/components/generate_test_file_drawer_spec.js b/ee/spec/frontend/ai/components/generate_test_file_drawer_spec.js
index 69ce0d0159f65335eb8ad62b08e61ea7c605098c..d38bd4c94087150f1ba16c88b0282993ca72baf5 100644
--- a/ee/spec/frontend/ai/components/generate_test_file_drawer_spec.js
+++ b/ee/spec/frontend/ai/components/generate_test_file_drawer_spec.js
@@ -36,6 +36,7 @@ const subscriptionResponsePartial = {
   role: GENIE_CHAT_MODEL_ROLES.assistant,
   timestamp: '2021-05-26T14:00:00.000Z',
   type: null,
+  chunkId: null,
 };
 
 describe('Generate test file drawer component', () => {
diff --git a/ee/spec/frontend/ai/tanuki_bot/components/app_spec.js b/ee/spec/frontend/ai/tanuki_bot/components/app_spec.js
index 8f0081b6a464f8ba12177873965422f56d5f926a..fa725e463a42c626ba30280fb5f2bb1e87424e29 100644
--- a/ee/spec/frontend/ai/tanuki_bot/components/app_spec.js
+++ b/ee/spec/frontend/ai/tanuki_bot/components/app_spec.js
@@ -1,5 +1,6 @@
 import { GlSprintf } from '@gitlab/ui';
 import Vue, { nextTick } from 'vue';
+import { v4 as uuidv4 } from 'uuid';
 // eslint-disable-next-line no-restricted-imports
 import Vuex from 'vuex';
 import VueApollo from 'vue-apollo';
@@ -34,6 +35,7 @@ Vue.use(Vuex);
 Vue.use(VueApollo);
 
 jest.mock('~/rest_api');
+jest.mock('uuid');
 
 describe('GitLab Duo Chat', () => {
   let wrapper;
@@ -90,9 +92,16 @@ describe('GitLab Duo Chat', () => {
   const findAllUserFeedback = () => wrapper.findAllComponents(UserFeedback);
 
   beforeEach(() => {
+    uuidv4.mockImplementation(() => '123');
     getMarkdown.mockImplementation(({ text }) => Promise.resolve({ data: { html: text } }));
   });
 
+  it('generates unique `clientSubscriptionId` using v4', () => {
+    createComponent();
+    expect(uuidv4).toHaveBeenCalled();
+    expect(wrapper.vm.clientSubscriptionId).toBe('123');
+  });
+
   describe('rendering', () => {
     beforeEach(() => {
       createComponent();
@@ -192,6 +201,7 @@ describe('GitLab Duo Chat', () => {
             expect(expectedMutation).toHaveBeenCalledWith({
               resourceId: expectedResourceId,
               question: MOCK_USER_MESSAGE.msg,
+              clientSubscriptionId: '123',
             });
           },
         );
diff --git a/ee/spec/frontend/ai/tanuki_bot/mock_data.js b/ee/spec/frontend/ai/tanuki_bot/mock_data.js
index 02721baaea3746231f5cc255b3baffdc4fda1f9d..07c54970cf8f51f115e254ee694a8a64ae35e682 100644
--- a/ee/spec/frontend/ai/tanuki_bot/mock_data.js
+++ b/ee/spec/frontend/ai/tanuki_bot/mock_data.js
@@ -50,6 +50,7 @@ export const GENERATE_MOCK_TANUKI_RES = (body = JSON.stringify(MOCK_TANUKI_MESSA
         role: MOCK_TANUKI_MESSAGE.role,
         timestamp: '2021-04-21T12:00:00.000Z',
         type: null,
+        chunkId: null,
       },
     },
   };
diff --git a/ee/spec/frontend/ai/tanuki_bot/store/actions_spec.js b/ee/spec/frontend/ai/tanuki_bot/store/actions_spec.js
index b7d906c9d47702e0787f3cbf9e5477c3cc0814bd..d2f593182d2820f041a814cce2f6b97ed98747ca 100644
--- a/ee/spec/frontend/ai/tanuki_bot/store/actions_spec.js
+++ b/ee/spec/frontend/ai/tanuki_bot/store/actions_spec.js
@@ -67,6 +67,34 @@ describe('TanukiBot Store Actions', () => {
           expectedMutations: [],
         });
       });
+
+      it('should commit the correct mutation for a number as content', () => {
+        return testAction({
+          action: actions.addDuoChatMessage,
+          payload: { responseBody: '1', role: GENIE_CHAT_MODEL_ROLES.assistant },
+          state,
+          expectedMutations: [
+            {
+              type: types.ADD_MESSAGE,
+              payload: { content: '1', role: GENIE_CHAT_MODEL_ROLES.assistant },
+            },
+          ],
+        });
+      });
+
+      it('should commit the correct mutation for a boolean as content', () => {
+        return testAction({
+          action: actions.addDuoChatMessage,
+          payload: { responseBody: 'true', role: GENIE_CHAT_MODEL_ROLES.assistant },
+          state,
+          expectedMutations: [
+            {
+              type: types.ADD_MESSAGE,
+              payload: { content: 'true', role: GENIE_CHAT_MODEL_ROLES.assistant },
+            },
+          ],
+        });
+      });
     });
 
     describe('with error', () => {
diff --git a/ee/spec/frontend/ai/tanuki_bot/store/mutations_spec.js b/ee/spec/frontend/ai/tanuki_bot/store/mutations_spec.js
index 4ce5a00d8f6d1e4e792db6ba71a36252c6c5d767..b147bc7a3f95d4d57ab377ca5f7231f0d66578bc 100644
--- a/ee/spec/frontend/ai/tanuki_bot/store/mutations_spec.js
+++ b/ee/spec/frontend/ai/tanuki_bot/store/mutations_spec.js
@@ -43,8 +43,37 @@ describe('GitLab Duo Chat Store Mutations', () => {
     });
 
     describe('when there is a message with the same requestId', () => {
+      const updatedContent = 'Updated content';
+      it('updates the correct message based on the role', () => {
+        state.messages.push(
+          {
+            ...MOCK_USER_MESSAGE,
+            requestId,
+          },
+          {
+            ...MOCK_TANUKI_MESSAGE,
+            requestId,
+          },
+        );
+        mutations[types.ADD_MESSAGE](state, {
+          requestId,
+          role: MOCK_TANUKI_MESSAGE.role,
+          content: updatedContent,
+        });
+        expect(state.messages.length).toBe(2);
+        expect(state.messages).toStrictEqual([
+          {
+            ...MOCK_USER_MESSAGE,
+            requestId,
+          },
+          {
+            ...MOCK_TANUKI_MESSAGE,
+            requestId,
+            content: updatedContent,
+          },
+        ]);
+      });
       describe('when the message is of the same role', () => {
-        const updatedContent = 'Updated content';
         it('updates the message object if it is of exactly the same role', () => {
           state.messages.push({ ...MOCK_USER_MESSAGE, requestId });
           mutations[types.ADD_MESSAGE](state, {
diff --git a/ee/spec/frontend/batch_comments/components/summarize_my_review_spec.js b/ee/spec/frontend/batch_comments/components/summarize_my_review_spec.js
index 34720039495395c7273cc208973cde307225715d..c0bc9219dba4f09723844c60ac5be56bbbd36f4b 100644
--- a/ee/spec/frontend/batch_comments/components/summarize_my_review_spec.js
+++ b/ee/spec/frontend/batch_comments/components/summarize_my_review_spec.js
@@ -36,6 +36,7 @@ const subscriptionResponsePartial = {
   role: GENIE_CHAT_MODEL_ROLES.assistant,
   timestamp: '2021-05-26T14:00:00.000Z',
   type: null,
+  chunkId: null,
 };
 
 const findButton = () => wrapper.findByTestId('mutation-trigger');
diff --git a/ee/spec/frontend/vue_merge_request_widget/components/ai_commit_message_spec.js b/ee/spec/frontend/vue_merge_request_widget/components/ai_commit_message_spec.js
index 16b93373a409580f962c78303d701ea2cf33419e..de5b7dff5d3686266a96b3d5903a3aa3013e34c9 100644
--- a/ee/spec/frontend/vue_merge_request_widget/components/ai_commit_message_spec.js
+++ b/ee/spec/frontend/vue_merge_request_widget/components/ai_commit_message_spec.js
@@ -23,6 +23,7 @@ describe('Ai Commit Message component', () => {
     role: GENIE_CHAT_MODEL_ROLES.assistant,
     timestamp: '2021-05-26T14:00:00.000Z',
     type: null,
+    chunkId: null,
   };
 
   const createComponent = () => {
diff --git a/ee/spec/frontend/vulnerabilities/explain_vulnerability/explain_vulnerability_drawer_spec.js b/ee/spec/frontend/vulnerabilities/explain_vulnerability/explain_vulnerability_drawer_spec.js
index 3dde2d44f1b672ce7683d7724638db5f15bf9064..ab06a55f4abdb960964e9ade98b93aba4150417c 100644
--- a/ee/spec/frontend/vulnerabilities/explain_vulnerability/explain_vulnerability_drawer_spec.js
+++ b/ee/spec/frontend/vulnerabilities/explain_vulnerability/explain_vulnerability_drawer_spec.js
@@ -31,6 +31,7 @@ const SUBSCRIPTION_RESPONSE = {
   role: 'assistant',
   timestamp: '2021-05-26T14:00:00.000Z',
   type: null,
+  chunkId: null,
 };
 const SUBSCRIPTION_ERROR_RESPONSE = { ...SUBSCRIPTION_RESPONSE, errors: ['subscription error'] };