diff options
Diffstat (limited to 'src/client/views/nodes/chatbot/chatboxcomponents')
| -rw-r--r-- | src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx | 178 | 
1 files changed, 60 insertions, 118 deletions
| diff --git a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx index 076f49831..47d4fb8a7 100644 --- a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx +++ b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx @@ -14,10 +14,9 @@ import OpenAI, { ClientOptions } from 'openai';  import * as React from 'react';  import { v4 as uuidv4 } from 'uuid';  import { ClientUtils } from '../../../../../ClientUtils'; -import { Doc, DocListCast, FieldType, Opt } from '../../../../../fields/Doc'; +import { Doc, DocListCast, Opt } from '../../../../../fields/Doc';  import { DocData, DocViews } from '../../../../../fields/DocSymbols';  import { CsvCast, DocCast, NumCast, PDFCast, RTFCast, StrCast } from '../../../../../fields/Types'; -import { Networking } from '../../../../Network';  import { DocUtils } from '../../../../documents/DocUtils';  import { CollectionViewType, DocumentType } from '../../../../documents/DocumentTypes';  import { Docs, DocumentOptions } from '../../../../documents/Documents'; @@ -33,9 +32,11 @@ import { Vectorstore } from '../vectorstore/Vectorstore';  import './ChatBox.scss';  import MessageComponentBox from './MessageComponent';  import { ProgressBar } from './ProgressBar'; +import { supportedDocumentTypes } from '../tools/CreateDocumentTool';  dotenv.config(); +type parsedDoc = { doc_type: string; id: string; data: unknown; title: string; width: number; height: number; backgroundColor: string };  /**   * ChatBox is the main class responsible for managing the interaction between the user and the assistant,   * handling documents, and integrating with OpenAI for tasks such as document analysis, chat functionality, @@ -399,48 +400,26 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {       * @param id The unique ID for the document.       */      @action -    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; -    // }); +    private createCollectionWithChildren = (data: parsedDoc[], insideCol: boolean): Opt<Doc>[] => +        data.map(doc => this.whichDoc(doc.doc_type, doc.data, { backgroundColor: doc.backgroundColor, _width: doc.width, _height: doc.height }, doc.id, insideCol));      @action -    whichDoc = (doc_type: string, data: unknown, options: DocumentOptions, id: string, insideCol: boolean): Promise<Opt<Doc>> => -        (async () => { +    whichDoc = (doc_type: string, data: unknown, options: DocumentOptions, id: string, insideCol: boolean): Opt<Doc> => { +        const ndoc = (() => {              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 }) => -                        (() => { +                case supportedDocumentTypes.text:       return Docs.Create.TextDocument(data as string, options); +                case supportedDocumentTypes.comparison: return this.createComparison(data as parsedDoc[], options); +                case supportedDocumentTypes.flashcard:  return this.createFlashcard(data as parsedDoc[], options); +                case supportedDocumentTypes.deck:       return this.createDeck(data as parsedDoc[], options); +                case supportedDocumentTypes.image:      return Docs.Create.ImageDocument(data as string, options); +                case supportedDocumentTypes.equation:   return Docs.Create.EquationDocument(data as string, options); +                case supportedDocumentTypes.notetaking: return Docs.Create.NoteTakingDocument([], options); +                case supportedDocumentTypes.web:        return Docs.Create.WebDocument(data as string, { ...options, data_useCors: true }); +                case supportedDocumentTypes.dataviz:    return Docs.Create.DataVizDocument('/users/rz/Downloads/addresses.csv', options); +                case supportedDocumentTypes.collection: { +                    const arr = this.createCollectionWithChildren(data as parsedDoc[], true).filter(d=>d).map(d => d!); +                    const collOpts = {  ...options, _layout_fitWidth: true, _width:300, _height: 300, _freeform_backgroundGrid: true }; +                    return (() => {                              switch (options.type_collection) {                                  case CollectionViewType.Tree:        return Docs.Create.TreeDocument(arr, collOpts);                                  case CollectionViewType.Masonry:     return Docs.Create.MasonryDocument(arr, collOpts); @@ -450,31 +429,26 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {                                  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); +                        })(); +                    } +                // case supportedDocumentTypes.diagram:    return Docs.Create.DiagramDocument(options); +                // case supportedDocumentTypes.audio:      return Docs.Create.AudioDocument(data as string, options); +                // case supportedDocumentTypes.map:        return Docs.Create.MapDocument([], options); +                // case supportedDocumentTypes.button:     return Docs.Create.ButtonDocument(options); +                // case supportedDocumentTypes.script:     return Docs.Create.ScriptingDocument(null, options); +                // case supportedDocumentTypes.chat:       return Docs.Create.ChatDocument(options); +                // case supportedDocumentTypes.trail:      return Docs.Create.PresDocument(options); +                // case supportedDocumentTypes.trail:      return Docs.Create.FreeformDocument([], 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; -        }); +        })(); + +        if (ndoc) { +            ndoc.x = NumCast((options.x as number) ?? 0) + (insideCol ? 0 : NumCast(this.layoutDoc.x) + NumCast(this.layoutDoc.width)) + 100; +            ndoc.y = NumCast(options.y as number) + (insideCol ? 0 : NumCast(this.layoutDoc.y)); +        } +        return ndoc; +    };      /**       * Creates a document in the dashboard. @@ -494,32 +468,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {                  DocumentManager.Instance.showDocument(doc, { willZoomCentered: true }, () => {});              }          }; -        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 -        })(); +        const doc = this.whichDoc(doc_type, data, options, uuidv4(), false);          if (doc) linkAndShowDoc(doc);      }; @@ -531,17 +480,14 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {       * @returns {Doc} A carousel document containing the flashcard deck.       */      @action -    createDeck = (data: string | unknown[], options: DocumentOptions) => { +    createDeck = (data: parsedDoc[], 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); +        if (data.length == 2 && data[0].doc_type == 'text' && data[1].doc_type == 'text') { +            this.createFlashcard(data, options);          } else { -            flashcardArray.forEach(doc => { -                const flashcardDoc = this.createFlashcard(doc, options); +            data.forEach(doc => { +                const flashcardDoc = this.createFlashcard(doc.data as parsedDoc[] | string[], options);                  if (flashcardDoc) flashcardDeck.push(flashcardDoc);              });          } @@ -564,25 +510,21 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {       * @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, -            }; +    createFlashcard = (data: parsedDoc[] | string[], options: DocumentOptions) => { +        const [front, back] = data; -            // Create front and back text documents -            const side1 = Docs.Create.CenteredTextCreator('question', front, sideOptions); -            const side2 = Docs.Create.CenteredTextCreator('answer', back, sideOptions); +        const sideOptions: DocumentOptions = { +            backgroundColor: options.backgroundColor, +            _width: options._width, +            _height: options._height || 300, +        }; -            // Create the flashcard document with both sides -            return Docs.Create.FlashcardDocument('flashcard', side1, side2, sideOptions); -        } +        // Create front and back text documents +        const side1 = typeof front === 'string' ? Docs.Create.CenteredTextCreator('question', front as string, sideOptions) : this.whichDoc(front.doc_type, front.data, options, front.id, false); +        const side2 = typeof back === 'string' ? Docs.Create.CenteredTextCreator('answer', back as string, sideOptions) : this.whichDoc(back.doc_type, back.data, options, back.id, false); + +        // Create the flashcard document with both sides +        return Docs.Create.FlashcardDocument('flashcard', side1, side2, sideOptions);      };      /** @@ -593,10 +535,10 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {       * @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) => +    createComparison = (doc: parsedDoc[], 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 }), +            data_back: Docs.Create.TextDocument(doc[0].data as string, { backgroundColor: doc[0].backgroundColor, _width: doc[0].width, _height: doc[0].height }), +            data_front: Docs.Create.TextDocument(doc[1].data as string, { backgroundColor: doc[1].backgroundColor, _width: doc[1].width, _height: doc[1].height }),              _width: options._width,              _height: options._height || 300,              backgroundColor: options.backgroundColor, | 
