UNPKG

@lobehub/chat

Version:

Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.

220 lines (181 loc) 5.53 kB
import isEqual from 'fast-deep-equal'; import { produce } from 'immer'; import { ChatMessage, ChatMessageExtra, ChatPluginPayload, ChatToolPayload, CreateMessageParams, } from '@/types/message'; import { merge } from '@/utils/merge'; interface UpdateMessages { id: string; type: 'updateMessage'; value: Partial<ChatMessage>; } interface CreateMessage { id: string; type: 'createMessage'; value: CreateMessageParams; } interface DeleteMessage { id: string; type: 'deleteMessage'; } interface DeleteMessages { ids: string[]; type: 'deleteMessages'; } interface UpdatePluginState { id: string; key: string; type: 'updatePluginState'; value: any; } interface UpdateMessagePlugin { id: string; type: 'updateMessagePlugin'; value: Partial<ChatPluginPayload>; } interface UpdateMessageTools { id: string; tool_call_id: string; type: 'updateMessageTools'; value: Partial<ChatPluginPayload>; } interface AddMessageTool { id: string; type: 'addMessageTool'; value: ChatToolPayload; } interface DeleteMessageTool { id: string; tool_call_id: string; type: 'deleteMessageTool'; } interface UpdateMessageExtra { id: string; key: string; type: 'updateMessageExtra'; value: any; } export type MessageDispatch = | CreateMessage | UpdateMessages | UpdatePluginState | UpdateMessageExtra | DeleteMessage | UpdateMessagePlugin | UpdateMessageTools | AddMessageTool | DeleteMessageTool | DeleteMessages; export const messagesReducer = (state: ChatMessage[], payload: MessageDispatch): ChatMessage[] => { switch (payload.type) { case 'updateMessage': { return produce(state, (draftState) => { const { id, value } = payload; const index = draftState.findIndex((i) => i.id === id); if (index < 0) return; draftState[index] = merge(draftState[index], { ...value, updatedAt: Date.now() }); }); } case 'updateMessageExtra': { return produce(state, (draftState) => { const { id, key, value } = payload; const message = draftState.find((i) => i.id === id); if (!message) return; if (!message.extra) { message.extra = { [key]: value } as ChatMessageExtra; } else { message.extra[key as keyof ChatMessageExtra] = value; } message.updatedAt = Date.now(); }); } case 'updatePluginState': { return produce(state, (draftState) => { const { id, key, value } = payload; const message = draftState.find((i) => i.id === id); if (!message) return; let newState; if (!message.pluginState) { newState = { [key]: value } as any; } else { newState = merge(message.pluginState, { [key]: value }); } if (isEqual(message.pluginState, newState)) return; message.pluginState = newState; message.updatedAt = Date.now(); }); } case 'updateMessagePlugin': { return produce(state, (draftState) => { const { id, value } = payload; const message = draftState.find((i) => i.id === id); if (!message || message.role !== 'tool') return; message.plugin = merge(message.plugin, value); message.updatedAt = Date.now(); }); } case 'addMessageTool': { return produce(state, (draftState) => { const { id, value } = payload; const message = draftState.find((i) => i.id === id); if (!message || message.role !== 'assistant') return; if (!message.tools) { message.tools = [value]; } else { const index = message.tools.findIndex((tool) => tool.id === value.id); if (index > 0) return; message.tools.push(value); } message.updatedAt = Date.now(); }); } case 'deleteMessageTool': { return produce(state, (draftState) => { const { id, tool_call_id } = payload; const message = draftState.find((i) => i.id === id); if (!message || message.role !== 'assistant' || !message.tools) return; message.tools = message.tools.filter((tool) => tool.id !== tool_call_id); message.updatedAt = Date.now(); }); } case 'updateMessageTools': { return produce(state, (draftState) => { const { id, value, tool_call_id } = payload; const message = draftState.find((i) => i.id === id); if (!message || message.role !== 'assistant' || !message.tools) return; const index = message.tools.findIndex((tool) => tool.id === tool_call_id); if (index < 0) return; message.tools[index] = merge(message.tools[index], value); message.updatedAt = Date.now(); }); } case 'createMessage': { return produce(state, (draftState) => { const { value, id } = payload; draftState.push({ ...value, createdAt: Date.now(), id, meta: {}, updatedAt: Date.now() }); }); } case 'deleteMessage': { return produce(state, (draft) => { const { id } = payload; const index = draft.findIndex((m) => m.id === id); if (index >= 0) draft.splice(index, 1); }); } case 'deleteMessages': { return produce(state, (draft) => { const { ids } = payload; return draft.filter((item) => { return !ids.includes(item.id); }); }); } default: { throw new Error('暂未实现的 type,请检查 reducer'); } } };