@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
JavaScript
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,
},
};
};
}