UNPKG

@plteam/chat-ui

Version:

CUI Kit is a free and open-source library for creating AI assistant chat interfaces, built with React, Material UI, and TypeScript

131 lines (128 loc) 4.71 kB
import { MessageModel, ChatMessageOwner } from './MessageModel'; import moment from 'moment'; import { v4 as uuid, v4 as uuidv4 } from 'uuid'; import { ThreadMessages } from './ThreadMessages'; import { ObservableReactValue } from '../utils/observers/ObservableReactValue'; import { randomId } from '../utils/numberUtils/randomInt'; export class ThreadModel { streamMessage; /*@observable.shallow private readonly _messages: ChatMessage[] = [];*/ viewerUniqueKey = uuid(); messages = new ThreadMessages(); observableTitle = new ObservableReactValue(''); isTyping = new ObservableReactValue(false); isLoadingAttachments = new ObservableReactValue([]); isEmpty = new ObservableReactValue(false); tool = new ObservableReactValue(undefined); aiModel = new ObservableReactValue(undefined); helloMessage = new MessageModel({ id: 'helloMessage' + randomId(), content: '', role: ChatMessageOwner.ASSISTANT, time: 0 }); /** * We can pass threads with empty history to improve performance * When opening such a thread, we need to call the getFullThread method to load the history */ isLoadingFullData = new ObservableReactValue(true); scrollY = -1; // private _threadCreating?: ApiMethodPromise<{ thread: DD }>; // диалог уже создан на сервере, но пользователь ещё не отправил ни одного сообщения. // Установим этот ID сразу после отправки сообщения // private potentialId?: IdType; pinnedAt = new ObservableReactValue(null); timestamp; _data; constructor(data, streamMessage) { this.streamMessage = streamMessage; this._data = data; this.observableTitle.value = data.title; this.aiModel.value = data.aiModel; this.pinnedAt.value = data.pinnedAt ?? null; if (data.messages?.find((m) => m.role === ChatMessageOwner.ASSISTANT && m.initialStatus)) { this.isTyping.value = true; } /*if (!_data.messages.find(v => !!v.parentId)) { const newMessages: DD['messages'] = []; let parentId: IdType | undefined = undefined; _data.messages.forEach(v => { newMessages.push({ ...v, parentId, }); if (v.role === ChatMessageOwner.USER) { parentId = v.id; } }); _data.messages = newMessages }*/ this.messages.allMessages.value = data.messages?.map(v => new MessageModel(v)) ?? []; this.isEmpty.value = !!data.isNew; if (!!data.messages?.length || data.isNew) { this.isLoadingFullData.value = false; } this.timestamp = new ObservableReactValue(moment(data.date).unix()); } get id() { return this._data.id; } set id(value) { this._data.id = value; } get time() { return this.timestamp.value ?? 0; } get title() { return this.observableTitle.value; } set title(value) { this.observableTitle.value = value; } get date() { return this._data.date; } get isNew() { return this._data.isNew; } get messagesArray() { return this.messages.allMessagesArray; } get data() { return this._data; } setFullData = (threadData) => { this.messages.allMessages.value = threadData.messages?.map(v => new MessageModel(v)) ?? []; this.isLoadingFullData.value = false; }; static createEmptyData = () => { return ({ id: 'NEW_THREAD_' + randomId(), title: 'New thread', date: (new Date()).toISOString(), messages: [], isNew: true, }); }; _createPair = (content, parentMessage) => { const userMessage = new MessageModel({ id: uuidv4(), content, role: ChatMessageOwner.USER, time: moment().unix(), parentId: parentMessage?.id, }); const assistantMessage = new MessageModel({ id: 'NEW_MESSAGE_' + randomId(), content: '', role: ChatMessageOwner.ASSISTANT, // должно быть больше для правильной сортировки time: moment().unix() + 1, parentId: userMessage.id, }); return { userMessage, assistantMessage, }; }; }