Spaces:
Running
Running
| import { writable, derived } from "svelte/store"; | |
| import { type ChatMessage, type MessageSegment } from "../models/chat-data"; | |
| interface SimpleChatState { | |
| messages: ChatMessage[]; | |
| connected: boolean; | |
| processing: boolean; | |
| error: string | null; | |
| typingIndicator: boolean; | |
| } | |
| function createChatStore() { | |
| const initialState: SimpleChatState = { | |
| messages: [], | |
| connected: false, | |
| processing: false, | |
| error: null, | |
| typingIndicator: false, | |
| }; | |
| const { subscribe, update } = writable<SimpleChatState>(initialState); | |
| return { | |
| subscribe, | |
| setConnected(connected: boolean) { | |
| update((state) => ({ ...state, connected })); | |
| }, | |
| setProcessing(processing: boolean) { | |
| update((state) => ({ ...state, processing })); | |
| }, | |
| setError(error: string | null) { | |
| update((state) => ({ ...state, error })); | |
| }, | |
| addMessage(message: ChatMessage) { | |
| update((state) => ({ | |
| ...state, | |
| messages: [...state.messages, message], | |
| })); | |
| }, | |
| appendToLastMessage(content: string) { | |
| update((state) => { | |
| if (state.messages.length === 0) return state; | |
| const messages = [...state.messages]; | |
| const lastMessage = messages[messages.length - 1]; | |
| messages[messages.length - 1] = { | |
| ...lastMessage, | |
| content: lastMessage.content + content, | |
| }; | |
| return { ...state, messages }; | |
| }); | |
| }, | |
| setLastMessageContent(content: string) { | |
| update((state) => { | |
| if (state.messages.length === 0) return state; | |
| const messages = [...state.messages]; | |
| const lastMessage = messages[messages.length - 1]; | |
| messages[messages.length - 1] = { | |
| ...lastMessage, | |
| content, | |
| }; | |
| return { ...state, messages }; | |
| }); | |
| }, | |
| setLastMessageSegments(segments: MessageSegment[]) { | |
| update((state) => { | |
| if (state.messages.length === 0) return state; | |
| const messages = [...state.messages]; | |
| const lastMessage = messages[messages.length - 1]; | |
| messages[messages.length - 1] = { | |
| ...lastMessage, | |
| segments, | |
| }; | |
| return { ...state, messages }; | |
| }); | |
| }, | |
| clearMessages() { | |
| update((state) => ({ | |
| ...state, | |
| messages: [], | |
| error: null, | |
| })); | |
| }, | |
| setTypingIndicator(typingIndicator: boolean) { | |
| update((state) => ({ ...state, typingIndicator })); | |
| }, | |
| }; | |
| } | |
| export const chatStore = createChatStore(); | |
| export const isProcessing = derived(chatStore, ($chat) => $chat.processing); | |
| export const isConnected = derived(chatStore, ($chat) => $chat.connected); | |
| export const messages = derived(chatStore, ($chat) => $chat.messages); | |
| export const error = derived(chatStore, ($chat) => $chat.error); | |
| export const typingIndicator = derived( | |
| chatStore, | |
| ($chat) => $chat.typingIndicator, | |
| ); | |