aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx')
-rw-r--r--src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx402
1 files changed, 273 insertions, 129 deletions
diff --git a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
index 3ef6bdd8b..076f49831 100644
--- a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
+++ b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
@@ -14,12 +14,12 @@ import OpenAI, { ClientOptions } from 'openai';
import * as React from 'react';
import { v4 as uuidv4 } from 'uuid';
import { ClientUtils } from '../../../../../ClientUtils';
-import { Doc, DocListCast } from '../../../../../fields/Doc';
+import { Doc, DocListCast, FieldType, Opt } from '../../../../../fields/Doc';
import { DocData, DocViews } from '../../../../../fields/DocSymbols';
-import { CsvCast, DocCast, PDFCast, RTFCast, StrCast } from '../../../../../fields/Types';
+import { CsvCast, DocCast, NumCast, PDFCast, RTFCast, StrCast } from '../../../../../fields/Types';
import { Networking } from '../../../../Network';
import { DocUtils } from '../../../../documents/DocUtils';
-import { DocumentType } from '../../../../documents/DocumentTypes';
+import { CollectionViewType, DocumentType } from '../../../../documents/DocumentTypes';
import { Docs, DocumentOptions } from '../../../../documents/Documents';
import { DocumentManager } from '../../../../util/DocumentManager';
import { LinkManager } from '../../../../util/LinkManager';
@@ -33,7 +33,6 @@ import { Vectorstore } from '../vectorstore/Vectorstore';
import './ChatBox.scss';
import MessageComponentBox from './MessageComponent';
import { ProgressBar } from './ProgressBar';
-import { RichTextField } from '../../../../../fields/RichTextField';
dotenv.config();
@@ -45,17 +44,17 @@ dotenv.config();
@observer
export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
// MobX observable properties to track UI state and data
- @observable history: AssistantMessage[] = [];
- @observable.deep current_message: AssistantMessage | undefined = undefined;
- @observable isLoading: boolean = false;
- @observable uploadProgress: number = 0;
- @observable currentStep: string = '';
- @observable expandedScratchpadIndex: number | null = null;
- @observable inputValue: string = '';
- @observable private linked_docs_to_add: ObservableSet = observable.set();
- @observable private linked_csv_files: { filename: string; id: string; text: string }[] = [];
- @observable private isUploadingDocs: boolean = false;
- @observable private citationPopup: { text: string; visible: boolean } = { text: '', visible: false };
+ @observable private _history: AssistantMessage[] = [];
+ @observable.deep private _current_message: AssistantMessage | undefined = undefined;
+ @observable private _isLoading: boolean = false;
+ @observable private _uploadProgress: number = 0;
+ @observable private _currentStep: string = '';
+ @observable private _expandedScratchpadIndex: number | null = null;
+ @observable private _inputValue: string = '';
+ @observable private _linked_docs_to_add: ObservableSet = observable.set();
+ @observable private _linked_csv_files: { filename: string; id: string; text: string }[] = [];
+ @observable private _isUploadingDocs: boolean = false;
+ @observable private _citationPopup: { text: string; visible: boolean } = { text: '', visible: false };
// Private properties for managing OpenAI API, vector store, agent, and UI elements
private openai: OpenAI;
@@ -96,7 +95,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
// Reaction to update dataDoc when chat history changes
reaction(
() =>
- this.history.map((msg: AssistantMessage) => ({
+ this._history.map((msg: AssistantMessage) => ({
role: msg.role,
content: msg.content,
follow_up_questions: msg.follow_up_questions,
@@ -115,20 +114,20 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
*/
@action
addDocToVectorstore = async (newLinkedDoc: Doc) => {
- this.uploadProgress = 0;
- this.currentStep = 'Initializing...';
- this.isUploadingDocs = true;
+ this._uploadProgress = 0;
+ this._currentStep = 'Initializing...';
+ this._isUploadingDocs = true;
try {
// Add the document to the vectorstore
await this.vectorstore.addAIDoc(newLinkedDoc, this.updateProgress);
} catch (error) {
console.error('Error uploading document:', error);
- this.currentStep = 'Error during upload';
+ this._currentStep = 'Error during upload';
} finally {
- this.isUploadingDocs = false;
- this.uploadProgress = 0;
- this.currentStep = '';
+ this._isUploadingDocs = false;
+ this._uploadProgress = 0;
+ this._currentStep = '';
}
};
@@ -139,8 +138,8 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
*/
@action
updateProgress = (progress: number, step: string) => {
- this.uploadProgress = progress;
- this.currentStep = step;
+ this._uploadProgress = progress;
+ this._currentStep = step;
};
/**
@@ -177,7 +176,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
const csvId = id ?? uuidv4();
// Add CSV details to linked files
- this.linked_csv_files.push({
+ this._linked_csv_files.push({
filename: CsvCast(newLinkedDoc.data).url.pathname,
id: csvId,
text: csvData,
@@ -199,7 +198,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
*/
@action
toggleToolLogs = (index: number) => {
- this.expandedScratchpadIndex = this.expandedScratchpadIndex === index ? null : index;
+ this._expandedScratchpadIndex = this._expandedScratchpadIndex === index ? null : index;
};
/**
@@ -258,7 +257,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@action
askGPT = async (event: React.FormEvent): Promise<void> => {
event.preventDefault();
- this.inputValue = '';
+ this._inputValue = '';
// Extract the user's message
const textInput = (event.currentTarget as HTMLFormElement).elements.namedItem('messageInput') as HTMLInputElement;
@@ -268,13 +267,13 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
try {
textInput.value = '';
// Add the user's message to the history
- this.history.push({
+ this._history.push({
role: ASSISTANT_ROLE.USER,
content: [{ index: 0, type: TEXT_TYPE.NORMAL, text: trimmedText, citation_ids: null }],
processing_info: [],
});
- this.isLoading = true;
- this.current_message = {
+ this._isLoading = true;
+ this._current_message = {
role: ASSISTANT_ROLE.ASSISTANT,
content: [],
citations: [],
@@ -284,9 +283,9 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
// Define callbacks for real-time processing updates
const onProcessingUpdate = (processingUpdate: ProcessingInfo[]) => {
runInAction(() => {
- if (this.current_message) {
- this.current_message = {
- ...this.current_message,
+ if (this._current_message) {
+ this._current_message = {
+ ...this._current_message,
processing_info: processingUpdate,
};
}
@@ -296,9 +295,9 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
const onAnswerUpdate = (answerUpdate: string) => {
runInAction(() => {
- if (this.current_message) {
- this.current_message = {
- ...this.current_message,
+ if (this._current_message) {
+ this._current_message = {
+ ...this._current_message,
content: [{ text: answerUpdate, type: TEXT_TYPE.NORMAL, index: 0, citation_ids: [] }],
};
}
@@ -310,22 +309,24 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
// Update the history with the final assistant message
runInAction(() => {
- if (this.current_message) {
- this.history.push({ ...finalMessage });
- this.current_message = undefined;
- this.dataDoc.data = JSON.stringify(this.history);
+ if (this._current_message) {
+ this._history.push({ ...finalMessage });
+ this._current_message = undefined;
+ this.dataDoc.data = JSON.stringify(this._history);
}
});
} catch (err) {
console.error('Error:', err);
// Handle error in processing
- this.history.push({
+ this._history.push({
role: ASSISTANT_ROLE.ASSISTANT,
content: [{ index: 0, type: TEXT_TYPE.ERROR, text: 'Sorry, I encountered an error while processing your request.', citation_ids: null }],
processing_info: [],
});
} finally {
- this.isLoading = false;
+ runInAction(() => {
+ this._isLoading = false;
+ });
this.scrollToBottom();
}
}
@@ -339,8 +340,8 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
*/
@action
updateMessageCitations = (index: number, citations: Citation[]) => {
- if (this.history[index]) {
- this.history[index].citations = citations;
+ if (this._history[index]) {
+ this._history[index].citations = citations;
}
};
@@ -381,17 +382,14 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
* @param data The CSV data content.
*/
@action
- createCSVInDash = async (url: string, title: string, id: string, data: string) => {
- const doc = DocCast(await DocUtils.DocumentFromType('csv', url, { title: title, text: RTFCast(data) }));
-
- const linkDoc = Docs.Create.LinkDocument(this.Document, doc);
- LinkManager.Instance.addLink(linkDoc);
-
- doc && this._props.addDocument?.(doc);
- await DocumentManager.Instance.showDocument(doc, { willZoomCentered: true }, () => {});
-
- this.addCSVForAnalysis(doc, id);
- };
+ createCSVInDash = (url: string, title: string, id: string, data: string) =>
+ DocUtils.DocumentFromType('csv', url, { title: title, text: RTFCast(data) }).then(doc => {
+ if (doc) {
+ LinkManager.Instance.addLink(Docs.Create.LinkDocument(this.Document, doc));
+ this._props.addDocument?.(doc);
+ DocumentManager.Instance.showDocument(doc, { willZoomCentered: true }, () => {}).then(() => this.addCSVForAnalysis(doc, id));
+ }
+ });
/**
* Creates a text document in the dashboard and adds it for analysis.
@@ -401,68 +399,216 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
* @param id The unique ID for the document.
*/
@action
- createDocInDash = async (doc_type: string, data: string | undefined, options: DocumentOptions, id: string) => {
- let doc;
-
- switch (doc_type.toLowerCase()) {
- case 'text':
- doc = Docs.Create.TextDocument(data || '', options);
- break;
- case 'image':
- doc = Docs.Create.ImageDocument(data || '', options);
- break;
- case 'pdf':
- doc = Docs.Create.PdfDocument(data || '', options);
- break;
- case 'video':
- doc = Docs.Create.VideoDocument(data || '', options);
- break;
- case 'audio':
- doc = Docs.Create.AudioDocument(data || '', options);
- break;
- case 'web':
- doc = Docs.Create.WebDocument(data || '', options);
- break;
- case 'equation':
- doc = Docs.Create.EquationDocument(data || '', options);
- break;
- case 'functionplot':
- case 'function_plot':
- doc = Docs.Create.FunctionPlotDocument([], options);
- break;
- case 'dataviz':
- case 'data_viz': {
- const { fileUrl, id } = await Networking.PostToServer('/createCSV', {
- filename: (options.title as string).replace(/\s+/g, '') + '.csv',
- data: data,
- });
- doc = Docs.Create.DataVizDocument(fileUrl, { ...options, text: RTFCast(data) });
- this.addCSVForAnalysis(doc, id);
- break;
+ private createCollectionWithChildren = (data: { doc_type: string; id: string; data: any; title: string; width: number; height: number; backgroundColor: string }[], insideCol: boolean): Promise<Doc[]> =>
+ Promise.all(
+ data.map(doc =>
+ doc.doc_type !== 'collection' // Handle non-collection documents
+ ? this.whichDoc(doc.doc_type, doc.data, { backgroundColor: doc.backgroundColor, _width: doc.width, _height: doc.height }, doc.id, insideCol)
+ : this.createCollectionWithChildren(doc.data, true).then(nestedDocs =>
+ Docs.Create.FreeformDocument(nestedDocs, {
+ title: doc.title,
+ backgroundColor: doc.backgroundColor,
+ _width: doc.width,
+ _height: doc.height,
+ _layout_fitWidth: true,
+ _freeform_backgroundGrid: true,
+ })
+ )
+ ) // prettier-ignore
+ ).then(childDocs => childDocs.filter(doc => doc).map(doc => doc!));
+ // .then(nestedResults => {
+ // // Flatten any nested arrays from recursive collection calls
+ // const childDocs = nestedResults.flat() as Doc[];
+ // childDocs.forEach(doc => {
+ // console.log(DocCast(doc));
+ // console.log(DocCast(doc)[DocData].data);
+ // console.log(DocCast(doc)[DocData].data);
+ // });
+ // return childDocs;
+ // });
+
+ @action
+ whichDoc = (doc_type: string, data: unknown, options: DocumentOptions, id: string, insideCol: boolean): Promise<Opt<Doc>> =>
+ (async () => {
+ switch (doc_type) {
+ case 'text': return Docs.Create.TextDocument(data as string, options);
+ case 'flashcard': return this.createFlashcard(data as string[], options);
+ case 'deck': return this.createDeck(data as string, options);
+ case 'image': return Docs.Create.ImageDocument(data as string, options);
+ case 'equation': return Docs.Create.EquationDocument(data as string, options);
+ case 'noteboard': return Docs.Create.NoteTakingDocument([], options);
+ case 'simulation': return Docs.Create.SimulationDocument(options);
+ case 'collection': return this.createCollectionWithChildren(data as { doc_type: string; id: string; data: any; title: string; width: number; height: number; backgroundColor: string }[] , true).
+ then((arr, collOpts = { ...options, _layout_fitWidth: true, _freeform_backgroundGrid: true }) =>
+ (() => {
+ switch (options.type_collection) {
+ case CollectionViewType.Tree: return Docs.Create.TreeDocument(arr, collOpts);
+ case CollectionViewType.Masonry: return Docs.Create.MasonryDocument(arr, collOpts);
+ case CollectionViewType.Card: return Docs.Create.CardDeckDocument(arr, collOpts);
+ case CollectionViewType.Carousel: return Docs.Create.CarouselDocument(arr, collOpts);
+ case CollectionViewType.Carousel3D: return Docs.Create.Carousel3DDocument(arr, collOpts);
+ case CollectionViewType.Multicolumn: return Docs.Create.CarouselDocument(arr, collOpts);
+ default: return Docs.Create.FreeformDocument(arr, collOpts);
+ }
+ })()
+ );
+ case 'web': return Docs.Create.WebDocument(data as string, { ...options, data_useCors: true });
+ case 'comparison': return this.createComparison(data as {left: {width:number ,height: number, backgroundColor: string, data: string}, right: {width:number ,height: number, backgroundColor: string, data: string}}, options);
+ case 'diagram': return Docs.Create.DiagramDocument(options);
+ case 'audio': return Docs.Create.AudioDocument(data as string, options);
+ case 'map': return Docs.Create.MapDocument([], options);
+ case 'screengrab': return Docs.Create.ScreenshotDocument(options);
+ case 'webcam': return Docs.Create.WebCamDocument('', options);
+ case 'button': return Docs.Create.ButtonDocument(options);
+ case 'script': return Docs.Create.ScriptingDocument(null, options);
+ case 'dataviz': return Docs.Create.DataVizDocument('/users/rz/Downloads/addresses.csv', options);
+ case 'chat': return Docs.Create.ChatDocument(options);
+ case 'trail': return Docs.Create.PresDocument(options);
+ case 'tab': return Docs.Create.FreeformDocument([], options);
+ case 'slide': return Docs.Create.TreeDocument([], options);
+ default: return Docs.Create.TextDocument(data as string, options);
+ } // prettier-ignore
+ })().then(doc => {
+ if (doc) {
+ doc.x = NumCast((options.x as number) ?? 0) + (insideCol ? 0 : NumCast(this.layoutDoc.x) + NumCast(this.layoutDoc.width)) + 100;
+ doc.y = NumCast(options.y as number) + (insideCol ? 0 : NumCast(this.layoutDoc.y));
+ }
+ return doc;
+ });
+
+ /**
+ * Creates a document in the dashboard.
+ *
+ * @param {string} doc_type - The type of document to create.
+ * @param {string} data - The data used to generate the document.
+ * @param {DocumentOptions} options - Configuration options for the document.
+ * @param {string} id - Unique identifier for the document.
+ * @returns {Promise<void>} A promise that resolves once the document is created and displayed.
+ */
+ @action
+ createDocInDash = (doc_type: string, data: unknown, options: DocumentOptions /*, id: string */) => {
+ const linkAndShowDoc = (doc: Opt<Doc>) => {
+ if (doc) {
+ LinkManager.Instance.addLink(Docs.Create.LinkDocument(this.Document, doc));
+ this._props.addDocument?.(doc);
+ DocumentManager.Instance.showDocument(doc, { willZoomCentered: true }, () => {});
}
- case 'chat':
- doc = Docs.Create.ChatDocument(options);
- break;
- // Add more cases for other document types
- default:
- console.error('Unknown or unsupported document type:', doc_type);
- return;
+ };
+ const doc = (() => {
+ switch (doc_type.toLowerCase()) {
+ case 'flashcard': return this.createFlashcard(data as string[], options);
+ case 'text': return Docs.Create.TextDocument(data as string || '', options);
+ case 'image': return Docs.Create.ImageDocument(data as string || '', options);
+ case 'pdf': return Docs.Create.PdfDocument(data as string || '', options);
+ case 'video': return Docs.Create.VideoDocument(data as string || '', options);
+ case 'audio': return Docs.Create.AudioDocument(data as string || '', options);
+ case 'web': return Docs.Create.WebDocument(data as string || '', options);
+ case 'equation': return Docs.Create.EquationDocument(data as string || '', options);
+ case 'chat': return Docs.Create.ChatDocument(options);
+ case 'functionplot': return Docs.Create.FunctionPlotDocument([], options);
+ case 'dataviz': Networking.PostToServer('/createCSV', {
+ filename: (options.title as string).replace(/\s+/g, '') + '.csv',
+ data: data,
+ })?.then(({ fileUrl, id }) => {
+ const vdoc = Docs.Create.DataVizDocument(fileUrl, { ...options, text: RTFCast(data as FieldType) });
+ this.addCSVForAnalysis(vdoc, id);
+ linkAndShowDoc(vdoc);
+ });
+ return undefined;
+ // Add more cases for other document types
+ default: console.error('Unknown or unsupported document type:', doc_type);
+ return undefined;
+ } // prettier-ignore
+ })();
+ if (doc) linkAndShowDoc(doc);
+ };
+
+ /**
+ * Creates a deck of flashcards.
+ *
+ * @param {any} data - The data used to generate the flashcards. Can be a string or an object.
+ * @param {DocumentOptions} options - Configuration options for the flashcard deck.
+ * @returns {Doc} A carousel document containing the flashcard deck.
+ */
+ @action
+ createDeck = (data: string | unknown[], options: DocumentOptions) => {
+ const flashcardDeck: Doc[] = [];
+ // Parse `data` only if it’s a string
+ const deckData = typeof data === 'string' ? (JSON.parse(data) as unknown) : data;
+ const flashcardArray = Array.isArray(deckData) ? deckData : Object.values(deckData as object);
+ // Process each flashcard document in the `deckData` array
+ if (flashcardArray.length == 2 && flashcardArray[0].doc_type == 'text' && flashcardArray[1].doc_type == 'text') {
+ this.createFlashcard(flashcardArray as string[], options);
+ } else {
+ flashcardArray.forEach(doc => {
+ const flashcardDoc = this.createFlashcard(doc, options);
+ if (flashcardDoc) flashcardDeck.push(flashcardDoc);
+ });
}
- const linkDoc = Docs.Create.LinkDocument(this.Document, doc);
- LinkManager.Instance.addLink(linkDoc);
- doc && this._props.addDocument?.(doc);
- await DocumentManager.Instance.showDocument(doc, { willZoomCentered: true }, () => {});
+ // Create a carousel to contain the flashcard deck
+ return Docs.Create.CarouselDocument(flashcardDeck, {
+ title: options.title || 'Flashcard Deck',
+ _width: options._width || 300,
+ _height: options._height || 300,
+ _layout_fitWidth: false,
+ _layout_autoHeight: true,
+ });
+ };
+
+ /**
+ * Creates a single flashcard document.
+ *
+ * @param {any} data - The data used to generate the flashcard. Can be a string or an object.
+ * @param {any} options - Configuration options for the flashcard.
+ * @returns {Doc | undefined} The created flashcard document, or undefined if the flashcard cannot be created.
+ */
+ @action
+ createFlashcard = (data: string[], options: DocumentOptions) => {
+ const deckData = typeof data === 'string' ? JSON.parse(data) : data;
+ const flashcardArray = Array.isArray(deckData) ? deckData : (Object.values(deckData)[2] as string[]);
+ const [front, back] = flashcardArray;
+
+ if (typeof front === 'string' && typeof back === 'string') {
+ const sideOptions: DocumentOptions = {
+ backgroundColor: options.backgroundColor,
+ _width: options._width,
+ _height: options._height || 300,
+ };
+
+ // Create front and back text documents
+ const side1 = Docs.Create.CenteredTextCreator('question', front, sideOptions);
+ const side2 = Docs.Create.CenteredTextCreator('answer', back, sideOptions);
+
+ // Create the flashcard document with both sides
+ return Docs.Create.FlashcardDocument('flashcard', side1, side2, sideOptions);
+ }
};
/**
+ * Creates a comparison document.
+ *
+ * @param {any} doc - The document data containing left and right components for comparison.
+ * @param {any} options - Configuration options for the comparison document.
+ * @returns {Doc} The created comparison document.
+ */
+ @action
+ createComparison = (doc: { left: { width: number; height: number; backgroundColor: string; data: string }; right: { width: number; height: number; backgroundColor: string; data: string } }, options: DocumentOptions) =>
+ Docs.Create.ComparisonDocument(options.title as string, {
+ data_back: Docs.Create.TextDocument(doc.left.data, { backgroundColor: doc.left.backgroundColor, _width: doc.left.width, _height: doc.left.height }),
+ data_front: Docs.Create.TextDocument(doc.right.data, { backgroundColor: doc.right.backgroundColor, _width: doc.right.width, _height: doc.right.height }),
+ _width: options._width,
+ _height: options._height || 300,
+ backgroundColor: options.backgroundColor,
+ });
+
+ /**
* Event handler to manage citations click in the message components.
* @param citation The citation object clicked by the user.
*/
@action
handleCitationClick = (citation: Citation) => {
const currentLinkedDocs: Doc[] = this.linkedDocs;
-
const chunkId = citation.chunk_id;
// Loop through the linked documents to find the matching chunk and handle its display
@@ -497,8 +643,8 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
}
break;
case CHUNK_TYPE.TEXT:
- this.citationPopup = { text: citation.direct_text ?? 'No text available', visible: true };
- setTimeout(() => (this.citationPopup.visible = false), 3000); // Hide after 3 seconds
+ this._citationPopup = { text: citation.direct_text ?? 'No text available', visible: true };
+ setTimeout(() => (this._citationPopup.visible = false), 3000); // Hide after 3 seconds
DocumentManager.Instance.showDocument(doc, { willZoomCentered: true }, () => {
const firstView = Array.from(doc[DocViews])[0] as DocumentView;
@@ -566,7 +712,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
try {
const storedHistory = JSON.parse(StrCast(this.dataDoc.data));
runInAction(() => {
- this.history.push(
+ this._history.push(
...storedHistory.map((msg: AssistantMessage) => ({
role: msg.role,
content: msg.content,
@@ -581,7 +727,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
} else {
// Default welcome message
runInAction(() => {
- this.history.push({
+ this._history.push({
role: ASSISTANT_ROLE.ASSISTANT,
content: [
{
@@ -605,11 +751,11 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
.filter(d => d);
return linkedDocs;
},
- linked => linked.forEach(doc => this.linked_docs_to_add.add(doc))
+ linked => linked.forEach(doc => this._linked_docs_to_add.add(doc))
);
// Observe changes to linked documents and handle document addition
- observe(this.linked_docs_to_add, change => {
+ observe(this._linked_docs_to_add, change => {
if (change.type === 'add') {
if (PDFCast(change.newValue.data)) {
this.addDocToVectorstore(change.newValue);
@@ -682,18 +828,16 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
/**
* Getter that retrieves all linked CSV files for analysis.
*/
- @computed
- get linkedCSVs(): { filename: string; id: string; text: string }[] {
- return this.linked_csv_files;
+ @computed get linkedCSVs(): { filename: string; id: string; text: string }[] {
+ return this._linked_csv_files;
}
/**
* Getter that formats the entire chat history as a string for the agent's system message.
*/
- @computed
- get formattedHistory(): string {
+ @computed get formattedHistory(): string {
let history = '<chat_history>\n';
- for (const message of this.history) {
+ for (const message of this._history) {
history += `<${message.role}>${message.content.map(content => content.text).join(' ')}`;
if (message.loop_summary) {
history += `<loop_summary>${message.loop_summary}</loop_summary>`;
@@ -729,7 +873,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
*/
@action
handleFollowUpClick = (question: string) => {
- this.inputValue = question;
+ this._inputValue = question;
};
/**
@@ -738,11 +882,11 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
render() {
return (
<div className="chat-box">
- {this.isUploadingDocs && (
+ {this._isUploadingDocs && (
<div className="uploading-overlay">
<div className="progress-container">
<ProgressBar />
- <div className="step-name">{this.currentStep}</div>
+ <div className="step-name">{this._currentStep}</div>
</div>
</div>
)}
@@ -750,18 +894,18 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
<h2>{this.userName()}&apos;s AI Assistant</h2>
</div>
<div className="chat-messages" ref={this.messagesRef}>
- {this.history.map((message, index) => (
+ {this._history.map((message, index) => (
<MessageComponentBox key={index} message={message} onFollowUpClick={this.handleFollowUpClick} onCitationClick={this.handleCitationClick} updateMessageCitations={this.updateMessageCitations} />
))}
- {this.current_message && (
- <MessageComponentBox key={this.history.length} message={this.current_message} onFollowUpClick={this.handleFollowUpClick} onCitationClick={this.handleCitationClick} updateMessageCitations={this.updateMessageCitations} />
+ {this._current_message && (
+ <MessageComponentBox key={this._history.length} message={this._current_message} onFollowUpClick={this.handleFollowUpClick} onCitationClick={this.handleCitationClick} updateMessageCitations={this.updateMessageCitations} />
)}
</div>
<form onSubmit={this.askGPT} className="chat-input">
- <input type="text" name="messageInput" autoComplete="off" placeholder="Type your message here..." value={this.inputValue} onChange={e => (this.inputValue = e.target.value)} disabled={this.isLoading} />
- <button className="submit-button" type="submit" disabled={this.isLoading || !this.inputValue.trim()}>
- {this.isLoading ? (
+ <input type="text" name="messageInput" autoComplete="off" placeholder="Type your message here..." value={this._inputValue} onChange={action(e => (this._inputValue = e.target.value))} disabled={this._isLoading} />
+ <button className="submit-button" type="submit" disabled={this._isLoading || !this._inputValue.trim()}>
+ {this._isLoading ? (
<div className="spinner"></div>
) : (
<svg viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" strokeWidth="2" fill="none" strokeLinecap="round" strokeLinejoin="round">
@@ -772,10 +916,10 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
</button>
</form>
{/* Popup for citation */}
- {this.citationPopup.visible && (
+ {this._citationPopup.visible && (
<div className="citation-popup">
<p>
- <strong>Text from your document: </strong> {this.citationPopup.text}
+ <strong>Text from your document: </strong> {this._citationPopup.text}
</p>
</div>
)}