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

108 lines (107 loc) 4.53 kB
import { ChatMessageOwner } from './MessageModel'; import { MessageText } from './MessageText'; export class MessageSender { content; userMessage; assistantMessage; thread; constructor(content, userMessage, assistantMessage, thread) { this.content = content; this.userMessage = userMessage; this.assistantMessage = assistantMessage; this.thread = thread; } _finished = false; setText = (text) => { if (!this._finished) { this.changeTypingStatus(true); } this.assistantMessage.text = text; }; pushChunk = (chunk) => { if (!this.assistantMessage.text) { // The first text chunk clears any waiting-status (host-set or default "thinking") // and ends the reasoning-streaming phase. if (this.assistantMessage.status.value !== '') { this.assistantMessage.status.value = ''; } this.assistantMessage.reasoningManager.isStreaming.value = false; } this.assistantMessage.text += chunk; }; setStatus = (status) => { this.assistantMessage.status.value = status; }; changeTypingStatus = (status) => { if (status !== this.assistantMessage.typing.value) { this.assistantMessage.typing.value = status; if (!status) { this._finished = true; } } }; updateCurrentTextIndex = () => { this.assistantMessage.texts.value = [ ...this.assistantMessage.texts.value, new MessageText(''), ]; }; getUserParams = (resolver, getInternalMessage) => { const message = this.assistantMessage; const internalUserMessage = getInternalMessage(this.userMessage); const content = this.content; let attachments = []; if (Array.isArray(content)) { attachments = content.filter(v => v.type !== 'text'); } return { content: this.content, attachments, history: this.thread.messages.currentMessages.value.map(getInternalMessage), message: internalUserMessage, assistantMessage: getInternalMessage(message), toolType: this.thread.tool.value, aiModel: this.thread.aiModel.value, pushChunk: this.pushChunk, setText: this.setText, setStatus: this.setStatus, onFinish: () => { this.changeTypingStatus(false); resolver({ message: internalUserMessage }); message.reasoningManager.updateTimeSec(); message.reasoningManager.isStreaming.value = false; this.thread.isTyping.value = false; this.setStatus(''); if (message.data.role === ChatMessageOwner.ASSISTANT) { message.data.initialStatus = undefined; } message.data.content = message.texts.value.map((v) => ({ type: 'text', text: v.text, })); }, reasoning: { pushChunk: (chunk) => { if (message.reasoningManager.text.value === '' && message.status.value !== '') { // The first reasoning chunk clears any waiting-status too. message.status.value = ''; } message.reasoningManager.isStreaming.value = true; message.reasoningManager.pushChunk(chunk); }, setFull: message.reasoningManager.setText, setTitle: message.reasoningManager.setUserHeader, setTimeSec: message.reasoningManager.setUserTimeSec, setViewType: message.reasoningManager.setUserViewType, unlockAutoManagement: message.reasoningManager.unlockAutoManagment, }, actions: { updateThreadId: (newId) => this.thread.id = newId, updateThreadTitle: (newTitle) => this.thread.observableTitle.value = newTitle, updateUserMessageId: (newId) => this.userMessage.data.id = newId, updateAssistantMessageId: (newId) => message.data.id = newId, updateCurrentTextIndex: this.updateCurrentTextIndex, }, }; }; }