From 9a7e29bdaf363699864cf5383a5e82665b6fcc46 Mon Sep 17 00:00:00 2001 From: "Shibani Basava (from Dev Box)" Date: Wed, 29 Nov 2023 23:30:54 +0000 Subject: [PATCH 1/8] feat: load past 5 conversations --- .../public/svg/chevron-up-icon.svg | 3 + .../public/svg/history-dismiss-icon.svg | 3 + .../public/svg/history-icon.svg | 4 + .../src/components/chat-component.ts | 58 +++++++++----- .../src/components/chat-history-controller.ts | 78 +++++++++++++++++++ .../src/config/global-config.js | 3 + .../src/styles/chat-action-button.ts | 1 + .../src/styles/chat-component.ts | 14 ++++ 8 files changed, 146 insertions(+), 18 deletions(-) create mode 100644 packages/chat-component/public/svg/chevron-up-icon.svg create mode 100644 packages/chat-component/public/svg/history-dismiss-icon.svg create mode 100644 packages/chat-component/public/svg/history-icon.svg create mode 100644 packages/chat-component/src/components/chat-history-controller.ts diff --git a/packages/chat-component/public/svg/chevron-up-icon.svg b/packages/chat-component/public/svg/chevron-up-icon.svg new file mode 100644 index 00000000..549d247a --- /dev/null +++ b/packages/chat-component/public/svg/chevron-up-icon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/chat-component/public/svg/history-dismiss-icon.svg b/packages/chat-component/public/svg/history-dismiss-icon.svg new file mode 100644 index 00000000..b0557768 --- /dev/null +++ b/packages/chat-component/public/svg/history-dismiss-icon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/chat-component/public/svg/history-icon.svg b/packages/chat-component/public/svg/history-icon.svg new file mode 100644 index 00000000..4defb55e --- /dev/null +++ b/packages/chat-component/public/svg/history-icon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/packages/chat-component/src/components/chat-component.ts b/packages/chat-component/src/components/chat-component.ts index 7d877696..b3a8d17a 100644 --- a/packages/chat-component/src/components/chat-component.ts +++ b/packages/chat-component/src/components/chat-component.ts @@ -15,6 +15,7 @@ import iconDelete from '../../public/svg/delete-icon.svg?raw'; import iconCancel from '../../public/svg/cancel-icon.svg?raw'; import iconSend from '../../public/svg/send-icon.svg?raw'; import iconClose from '../../public/svg/close-icon.svg?raw'; +import iconUp from '../../public/svg/chevron-up-icon.svg?raw'; import './loading-indicator.js'; import './voice-input-button.js'; @@ -26,6 +27,7 @@ import './chat-thread-component.js'; import './chat-action-button.js'; import { type TabContent } from './tab-component.js'; import { ChatController } from './chat-controller.js'; +import { ChatHistoryController } from './chat-history-controller.js'; /** * A chat component that allows the user to ask questions and get answers from an API. @@ -78,6 +80,7 @@ export class ChatComponent extends LitElement { isResetInput = false; private chatController = new ChatController(this); + private chatHistoryController = new ChatHistoryController(this); // Is showing thought process panel @state() @@ -155,6 +158,10 @@ export class ChatComponent extends LitElement { stream: this.useStream, }, ); + + if (this.interactionModel === 'chat') { + this.chatHistoryController.saveChatHistory(this.chatThread); + } } // Reset the input field and the current question @@ -173,6 +180,8 @@ export class ChatComponent extends LitElement { this.isDefaultPromptsEnabled = true; this.selectedCitation = undefined; this.chatController.reset(); + // clean up the current session content from the history too + this.chatHistoryController.saveChatHistory(this.chatThread); this.collapseAside(event); this.handleUserChatCancel(event); } @@ -309,6 +318,27 @@ export class ChatComponent extends LitElement { } } + renderChatThread(chatThread: ChatThreadEntry[]) { + return html` + `; + } + // Render the chat component as a web component override render() { return html` @@ -318,6 +348,7 @@ export class ChatComponent extends LitElement { ${this.isChatStarted ? html`
+ ${this.interactionModel === 'chat' ? this.chatHistoryController.renderHistoryButton() : ''}
- - + ${this.chatHistoryController.showChatHistory + ? html`
+ ${this.renderChatThread(this.chatHistoryController.chatHistory)} + +
` + : ''} + ${this.renderChatThread(this.chatThread)} ` : ''} ${this.chatController.isAwaitingResponse diff --git a/packages/chat-component/src/components/chat-history-controller.ts b/packages/chat-component/src/components/chat-history-controller.ts new file mode 100644 index 00000000..a7c39aa7 --- /dev/null +++ b/packages/chat-component/src/components/chat-history-controller.ts @@ -0,0 +1,78 @@ +import { type ReactiveController, type ReactiveControllerHost } from 'lit'; +import { html } from 'lit'; +import { globalConfig } from '../config/global-config.js'; + +import iconHistory from '../../public/svg/history-icon.svg?raw'; +import iconHistoryDismiss from '../../public/svg/history-dismiss-icon.svg?raw'; + +import './chat-action-button.js'; + +export class ChatHistoryController implements ReactiveController { + host: ReactiveControllerHost; + static CHATHISTORY_ID = 'component:chat-history'; + + chatHistory: ChatThreadEntry[] = []; + + private _showChatHistory: boolean = false; + + get showChatHistory() { + return this._showChatHistory; + } + + set showChatHistory(value: boolean) { + this._showChatHistory = value; + this.host.requestUpdate(); + } + + constructor(host: ReactiveControllerHost) { + (this.host = host).addController(this); + } + + hostConnected() { + const chatHistory = localStorage.getItem(ChatHistoryController.CHATHISTORY_ID); + if (chatHistory) { + const history = JSON.parse(chatHistory); + + // find last 5 user messages indexes + const lastUserMessagesIndexes = history + .map((entry, index) => { + if (entry.isUserMessage) { + return index; + } + }) + .filter((index) => index !== undefined) + .slice(-5); + + // trim everything before the first user message + const trimmedHistory = lastUserMessagesIndexes.length === 0 ? history : history.slice(lastUserMessagesIndexes[0]); + + this.chatHistory = trimmedHistory; + } + } + + hostDisconnected() { + // no-op + } + + saveChatHistory(currentChat: ChatThreadEntry[]): void { + const newChatHistory = [...this.chatHistory, ...currentChat]; + localStorage.setItem(ChatHistoryController.CHATHISTORY_ID, JSON.stringify(newChatHistory)); + } + + handleChatHistoryButtonClick(event: Event) { + event.preventDefault(); + this.showChatHistory = !this.showChatHistory; + } + + renderHistoryButton() { + return html` + + + `; + } +} diff --git a/packages/chat-component/src/config/global-config.js b/packages/chat-component/src/config/global-config.js index 32178e4c..304e685a 100644 --- a/packages/chat-component/src/config/global-config.js +++ b/packages/chat-component/src/config/global-config.js @@ -34,6 +34,9 @@ const globalConfig = { SUPPORT_CONTEXT_LABEL: 'Support Context', CITATIONS_LABEL: 'Learn More:', CITATIONS_TAB_LABEL: 'Citations', + SHOW_CHAT_HISTORY_LABEL: 'Show Chat History', + HIDE_CHAT_HISTORY_LABEL: 'Hide Chat History', + CHAT_HISTORY_FOOTER_TEXT: 'Showing past 5 conversations', }; const teaserListTexts = { diff --git a/packages/chat-component/src/styles/chat-action-button.ts b/packages/chat-component/src/styles/chat-action-button.ts index 4c3c6e37..12c883fe 100644 --- a/packages/chat-component/src/styles/chat-action-button.ts +++ b/packages/chat-component/src/styles/chat-action-button.ts @@ -50,6 +50,7 @@ export const styles = css` svg { fill: currentColor; width: 20px; + height: 20px; padding: 3px; } button:hover > span, diff --git a/packages/chat-component/src/styles/chat-component.ts b/packages/chat-component/src/styles/chat-component.ts index 28b0f577..c360b22e 100644 --- a/packages/chat-component/src/styles/chat-component.ts +++ b/packages/chat-component/src/styles/chat-component.ts @@ -260,4 +260,18 @@ export const chatStyle = css` border-radius: 25px; padding: 20px; } + .chat-history__footer { + display: flex; + flex-direction: row; + gap: 10px; + justify-content: space-between; + align-self: center; + padding: 20px; + } + .chat-history__container { + display: flex; + flex-direction: column; + border-bottom: 3px solid var(--light-gray); + margin-bottom: 30px; + } `; From 24a00937ee50cefc83405b127f88b072f2c926ec Mon Sep 17 00:00:00 2001 From: "Shibani Basava (from Dev Box)" Date: Thu, 30 Nov 2023 00:36:20 +0000 Subject: [PATCH 2/8] fix: empty follow up question rendering --- .../src/components/chat-thread-component.ts | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/packages/chat-component/src/components/chat-thread-component.ts b/packages/chat-component/src/components/chat-thread-component.ts index 3d912d4e..faa6a448 100644 --- a/packages/chat-component/src/components/chat-thread-component.ts +++ b/packages/chat-component/src/components/chat-thread-component.ts @@ -177,19 +177,21 @@ export class ChatThreadComponent extends LitElement {
${unsafeSVG(iconQuestion)}
    - ${followupQuestions.map( - (followupQuestion) => html` -
  • - ${followupQuestion} -
  • - `, - )} + ${followupQuestions + .filter((q) => q !== null) + .map( + (followupQuestion) => html` +
  • + ${followupQuestion} +
  • + `, + )}
`; From 071fb380e69ceaa067cd7dd48c9894e968a0f55c Mon Sep 17 00:00:00 2001 From: "Shibani Basava (from Dev Box)" Date: Thu, 30 Nov 2023 03:25:24 +0000 Subject: [PATCH 3/8] fix: pass the chat history in the api call --- .../src/components/chat-component.ts | 23 +++++++++++++++++++ .../src/components/chat-thread-component.ts | 5 ++-- .../chat-component/src/core/http/index.ts | 3 ++- packages/chat-component/src/types.d.ts | 1 + packages/chat-component/src/utils/index.ts | 9 ++++++++ 5 files changed, 37 insertions(+), 4 deletions(-) diff --git a/packages/chat-component/src/components/chat-component.ts b/packages/chat-component/src/components/chat-component.ts index b3a8d17a..a3d77e4f 100644 --- a/packages/chat-component/src/components/chat-component.ts +++ b/packages/chat-component/src/components/chat-component.ts @@ -7,6 +7,7 @@ import { chatHttpOptions, globalConfig, teaserListTexts, requestOptions } from ' import { chatStyle } from '../styles/chat-component.js'; import { unsafeSVG } from 'lit/directives/unsafe-svg.js'; import { produce } from 'immer'; +import { chatEntryToString } from '../utils/index.js'; // TODO: allow host applications to customize these icons @@ -130,6 +131,27 @@ export class ChatComponent extends LitElement { } } + getMessageContext(): Message[] { + if (this.interactionModel === 'ask') { + return []; + } + + const history = [ + ...this.chatThread, + // include the history from the previous session if the user has enabled the chat history + ...(this.chatHistoryController.showChatHistory ? this.chatHistoryController.chatHistory : []), + ]; + + const messages: Message[] = history.map((entry) => { + return { + content: chatEntryToString(entry), + role: entry.isUserMessage ? 'user' : 'assistant', + }; + }); + + return messages; + } + // Handle the click on the chat button and send the question to the API async handleUserChatSubmit(event: Event): Promise { event.preventDefault(); @@ -148,6 +170,7 @@ export class ChatComponent extends LitElement { }, question, type: this.interactionModel, + messages: this.getMessageContext(), }, { // use defaults diff --git a/packages/chat-component/src/components/chat-thread-component.ts b/packages/chat-component/src/components/chat-thread-component.ts index faa6a448..d5a297b5 100644 --- a/packages/chat-component/src/components/chat-thread-component.ts +++ b/packages/chat-component/src/components/chat-thread-component.ts @@ -6,6 +6,7 @@ import { styles } from '../styles/chat-thread-component.js'; import { globalConfig } from '../config/global-config.js'; import { unsafeSVG } from 'lit/directives/unsafe-svg.js'; import { unsafeHTML } from 'lit/directives/unsafe-html.js'; +import { chatEntryToString } from '../utils/index.js'; import iconSuccess from '../../public/svg/success-icon.svg?raw'; import iconCopyToClipboard from '../../public/svg/copy-icon.svg?raw'; @@ -42,9 +43,7 @@ export class ChatThreadComponent extends LitElement { // Copy response to clipboard copyResponseToClipboard(entry: ChatThreadEntry): void { - const response = entry.text - .map((textEntry) => textEntry.value + '\n\n' + textEntry.followingSteps?.map((s) => ' - ' + s).join('\n')) - .join('\n\n'); + const response = chatEntryToString(entry); navigator.clipboard.writeText(response); this.isResponseCopied = true; diff --git a/packages/chat-component/src/core/http/index.ts b/packages/chat-component/src/core/http/index.ts index cb4b1db4..fe8d8831 100644 --- a/packages/chat-component/src/core/http/index.ts +++ b/packages/chat-component/src/core/http/index.ts @@ -1,7 +1,7 @@ import { ChatResponseError } from '../../utils/index.js'; export async function callHttpApi( - { question, type, approach, overrides }: ChatRequestOptions, + { question, type, approach, overrides, messages }: ChatRequestOptions, { method, url, stream, signal }: ChatHttpOptions, ) { return await fetch(`${url}/${type}`, { @@ -12,6 +12,7 @@ export async function callHttpApi( signal, body: JSON.stringify({ messages: [ + ...(messages ?? []), { content: question, role: 'user', diff --git a/packages/chat-component/src/types.d.ts b/packages/chat-component/src/types.d.ts index bb9147da..3aa5ceb2 100644 --- a/packages/chat-component/src/types.d.ts +++ b/packages/chat-component/src/types.d.ts @@ -40,6 +40,7 @@ declare interface ChatRequestOptions { overrides: RequestOverrides; type: string; question: string; + messages?: Message[]; } declare interface RequestOverrides { diff --git a/packages/chat-component/src/utils/index.ts b/packages/chat-component/src/utils/index.ts index 1f53bb3a..015add23 100644 --- a/packages/chat-component/src/utils/index.ts +++ b/packages/chat-component/src/utils/index.ts @@ -77,6 +77,15 @@ export function getTimestamp() { }); } +export function chatEntryToString(entry: ChatThreadEntry) { + const message = entry.text + .map((textEntry) => textEntry.value + '\n\n' + textEntry.followingSteps?.map((s, i) => `${i + 1}.` + s).join('\n')) + .join('\n\n') + .replaceAll(/]*>(.*?)<\/sup>/g, ''); // remove the tags from the message + + return message; +} + // Creates a new chat message error export class ChatResponseError extends Error { code?: number; From 58aae8ab90dac1955e0462de86ca731c97380a7d Mon Sep 17 00:00:00 2001 From: "Shibani Basava (from Dev Box)" Date: Thu, 30 Nov 2023 03:51:37 +0000 Subject: [PATCH 4/8] chore: set max history from global --- .../src/components/chat-component.ts | 15 +++++++++++++-- .../src/components/chat-history-controller.ts | 4 ++-- .../chat-component/src/config/global-config.js | 15 +++++++++++++-- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/packages/chat-component/src/components/chat-component.ts b/packages/chat-component/src/components/chat-component.ts index a3d77e4f..cf56febb 100644 --- a/packages/chat-component/src/components/chat-component.ts +++ b/packages/chat-component/src/components/chat-component.ts @@ -3,7 +3,13 @@ import { LitElement, html } from 'lit'; import DOMPurify from 'dompurify'; import { customElement, property, query, state } from 'lit/decorators.js'; import { unsafeHTML } from 'lit/directives/unsafe-html.js'; -import { chatHttpOptions, globalConfig, teaserListTexts, requestOptions } from '../config/global-config.js'; +import { + chatHttpOptions, + globalConfig, + teaserListTexts, + requestOptions, + MAX_CHAT_HISTORY, +} from '../config/global-config.js'; import { chatStyle } from '../styles/chat-component.js'; import { unsafeSVG } from 'lit/directives/unsafe-svg.js'; import { produce } from 'immer'; @@ -384,7 +390,12 @@ export class ChatComponent extends LitElement { ? html`
${this.renderChatThread(this.chatHistoryController.chatHistory)}
` : ''} diff --git a/packages/chat-component/src/components/chat-history-controller.ts b/packages/chat-component/src/components/chat-history-controller.ts index a7c39aa7..98f38e35 100644 --- a/packages/chat-component/src/components/chat-history-controller.ts +++ b/packages/chat-component/src/components/chat-history-controller.ts @@ -1,6 +1,6 @@ import { type ReactiveController, type ReactiveControllerHost } from 'lit'; import { html } from 'lit'; -import { globalConfig } from '../config/global-config.js'; +import { globalConfig, MAX_CHAT_HISTORY } from '../config/global-config.js'; import iconHistory from '../../public/svg/history-icon.svg?raw'; import iconHistoryDismiss from '../../public/svg/history-dismiss-icon.svg?raw'; @@ -41,7 +41,7 @@ export class ChatHistoryController implements ReactiveController { } }) .filter((index) => index !== undefined) - .slice(-5); + .slice(-MAX_CHAT_HISTORY); // trim everything before the first user message const trimmedHistory = lastUserMessagesIndexes.length === 0 ? history : history.slice(lastUserMessagesIndexes[0]); diff --git a/packages/chat-component/src/config/global-config.js b/packages/chat-component/src/config/global-config.js index 304e685a..017aa5ce 100644 --- a/packages/chat-component/src/config/global-config.js +++ b/packages/chat-component/src/config/global-config.js @@ -36,7 +36,8 @@ const globalConfig = { CITATIONS_TAB_LABEL: 'Citations', SHOW_CHAT_HISTORY_LABEL: 'Show Chat History', HIDE_CHAT_HISTORY_LABEL: 'Hide Chat History', - CHAT_HISTORY_FOOTER_TEXT: 'Showing past 5 conversations', + CHAT_MAX_COUNT_TAG: '{MAX_CHAT_HISTORY}', + CHAT_HISTORY_FOOTER_TEXT: 'Showing past {MAX_CHAT_HISTORY} conversations', }; const teaserListTexts = { @@ -75,6 +76,16 @@ const chatHttpOptions = { stream: true, }; +const MAX_CHAT_HISTORY = 5; + const APPROACH_MODEL = ['rrr', 'rtr']; -export { globalConfig, requestOptions, chatHttpOptions, NEXT_QUESTION_INDICATOR, APPROACH_MODEL, teaserListTexts }; +export { + globalConfig, + requestOptions, + chatHttpOptions, + NEXT_QUESTION_INDICATOR, + APPROACH_MODEL, + teaserListTexts, + MAX_CHAT_HISTORY, +}; From 60e34420f9f6b1c2d523179bb51ce7fa787a073d Mon Sep 17 00:00:00 2001 From: Shibani Basava Date: Thu, 30 Nov 2023 04:05:09 +0000 Subject: [PATCH 5/8] chore: disable chat history button when streaming --- packages/chat-component/src/components/chat-component.ts | 4 +++- .../chat-component/src/components/chat-history-controller.ts | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/chat-component/src/components/chat-component.ts b/packages/chat-component/src/components/chat-component.ts index cf56febb..f503322b 100644 --- a/packages/chat-component/src/components/chat-component.ts +++ b/packages/chat-component/src/components/chat-component.ts @@ -377,7 +377,9 @@ export class ChatComponent extends LitElement { ${this.isChatStarted ? html`
- ${this.interactionModel === 'chat' ? this.chatHistoryController.renderHistoryButton() : ''} + ${this.interactionModel === 'chat' + ? this.chatHistoryController.renderHistoryButton({ disabled: this.isDisabled }) + : ''} From 45979e79cdac4d60bd1b072f8dc92fe95a263439 Mon Sep 17 00:00:00 2001 From: Shibani Basava Date: Thu, 30 Nov 2023 04:55:25 +0000 Subject: [PATCH 6/8] test: add chat history test --- tests/e2e/webapp.spec.ts | 67 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/tests/e2e/webapp.spec.ts b/tests/e2e/webapp.spec.ts index c5919814..a5da2b1a 100644 --- a/tests/e2e/webapp.spec.ts +++ b/tests/e2e/webapp.spec.ts @@ -45,6 +45,9 @@ test.describe('default', () => { await expect(userMessage.nth(0)).toHaveText(firstQuestionText); await expect(defaultQuestions).toHaveCount(0); + + // make sure chat history is available for chat interaction mode + await expect(page.getByTestId('chat-history-button')).toBeVisible(); }); // make sure the response is formatted as list items @@ -108,6 +111,9 @@ test.describe('default', () => { // expect some response await expect(page.locator('.chat__txt--entry')).not.toHaveText(''); await expect(defaultQuestions).toHaveCount(0); + + // make sure chat history is not available for ask interaction mode + await expect(page.getByTestId('chat-history-button')).not.toBeVisible(); }); await test.step('Reset chat', async () => { @@ -132,6 +138,67 @@ test.describe('default', () => { await expect(page.getByTestId('loading-indicator')).toBeVisible(); await expect(page.getByTestId('question-input')).not.toBeEnabled(); }); + + test('chat history', async ({ page }) => { + await page.goto('/'); + await page.getByTestId('default-question').nth(0).click(); + + await page.routeFromHAR('./tests/e2e/hars/default-chat-response-stream.har', { + url: '/chat', + update: false, + updateContent: 'embed', + }); + + await page.getByTestId('submit-question-button').click(); + // wait for the thought process button to be enabled. + await expect(page.getByTestId('chat-show-thought-process')).toBeEnabled({ timeout: 30_000 }); + + await test.step('new chat history', async () => { + await expect(page.locator('.chat-history__container')).not.toBeVisible(); + await expect(page.getByTestId('chat-history-button')).toHaveText('Show Chat History'); + + await page.getByTestId('chat-history-button').click(); + + await expect(page.getByTestId('chat-history-button')).toHaveText('Hide Chat History'); + await expect(page.locator('.chat-history__container')).toBeVisible(); + + // no history in the past yet + const chatHistory = page.locator('.chat-history__container .chat__listItem'); + await expect(chatHistory).toHaveCount(0); + }); + + const currentChat = page.locator('.chat__txt--entry').nth(-1); + const lastChatText = await currentChat.textContent(); + + const currentUserMessage = page.locator('.chat__txt.user-message').nth(-1); + const lastChatUserMessageText = await currentUserMessage.textContent(); + + await test.step('chat history after chat', async () => { + // ask another question to get a new thread + await page.goto('/'); + await page.getByTestId('question-input').fill(`testing chat history`); + + await page.getByTestId('submit-question-button').click(); + // wait for the thought process button to be enabled. + await expect(page.getByTestId('chat-show-thought-process')).toBeEnabled({ timeout: 30_000 }); + + await page.getByTestId('chat-history-button').click(); + + // should show the last two last conversation + const chatHistory = page.locator('.chat-history__container .chat__listItem'); + await expect(chatHistory).toHaveCount(2); + + // check that the last session's chat matches in the one in chat history + // which is different from current session's chat + const previousChatUserMessage = chatHistory.nth(0).locator('.chat__txt.user-message').nth(-1); + await expect(currentUserMessage).not.toHaveText(lastChatUserMessageText); + await expect(previousChatUserMessage).toHaveText(lastChatUserMessageText); + + const previousChatLastItem = chatHistory.nth(-1).locator('.chat__txt--entry').nth(-1); + await expect(currentChat).not.toHaveText(lastChatText); + await expect(previousChatLastItem).toHaveText(lastChatText); + }); + }); }); test.describe('errors', () => { From f44595c2b9f11708a1d235e934e42d8863c04279 Mon Sep 17 00:00:00 2001 From: Shibani Basava Date: Thu, 30 Nov 2023 22:40:50 +0000 Subject: [PATCH 7/8] chore: use base64 strings instead of json strings --- .../src/components/chat-history-controller.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/chat-component/src/components/chat-history-controller.ts b/packages/chat-component/src/components/chat-history-controller.ts index b806c71e..6d0ce32a 100644 --- a/packages/chat-component/src/components/chat-history-controller.ts +++ b/packages/chat-component/src/components/chat-history-controller.ts @@ -31,7 +31,8 @@ export class ChatHistoryController implements ReactiveController { hostConnected() { const chatHistory = localStorage.getItem(ChatHistoryController.CHATHISTORY_ID); if (chatHistory) { - const history = JSON.parse(chatHistory); + // decode base64 string and then parse it + const history = JSON.parse(atob(chatHistory)); // find last 5 user messages indexes const lastUserMessagesIndexes = history @@ -56,7 +57,8 @@ export class ChatHistoryController implements ReactiveController { saveChatHistory(currentChat: ChatThreadEntry[]): void { const newChatHistory = [...this.chatHistory, ...currentChat]; - localStorage.setItem(ChatHistoryController.CHATHISTORY_ID, JSON.stringify(newChatHistory)); + // encode to base64 string and then save it + localStorage.setItem(ChatHistoryController.CHATHISTORY_ID, btoa(JSON.stringify(newChatHistory))); } handleChatHistoryButtonClick(event: Event) { From a7f114e9b8f6fdadc38cf285cbdf5fea1ba3ee4e Mon Sep 17 00:00:00 2001 From: Shibani Basava Date: Thu, 30 Nov 2023 22:46:44 +0000 Subject: [PATCH 8/8] chore: reset field after generate --- packages/chat-component/src/components/chat-component.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/chat-component/src/components/chat-component.ts b/packages/chat-component/src/components/chat-component.ts index f503322b..86d2123f 100644 --- a/packages/chat-component/src/components/chat-component.ts +++ b/packages/chat-component/src/components/chat-component.ts @@ -165,7 +165,6 @@ export class ChatComponent extends LitElement { const question = DOMPurify.sanitize(this.questionInput.value); this.isChatStarted = true; this.isDefaultPromptsEnabled = false; - this.questionInput.value = ''; await this.chatController.generateAnswer( { @@ -191,6 +190,9 @@ export class ChatComponent extends LitElement { if (this.interactionModel === 'chat') { this.chatHistoryController.saveChatHistory(this.chatThread); } + + this.questionInput.value = ''; + this.isResetInput = false; } // Reset the input field and the current question