1```mermaid
2sequenceDiagram
3 participant UI as ๐งฉ ChatForm / ChatMessage
4 participant chatStore as ๐๏ธ chatStore
5 participant convStore as ๐๏ธ conversationsStore
6 participant settingsStore as ๐๏ธ settingsStore
7 participant ChatSvc as โ๏ธ ChatService
8 participant DbSvc as โ๏ธ DatabaseService
9 participant API as ๐ /v1/chat/completions
10
11 Note over chatStore: State:<br/>isLoading, currentResponse<br/>errorDialogState, activeProcessingState<br/>chatLoadingStates (Map)<br/>chatStreamingStates (Map)<br/>abortControllers (Map)<br/>processingStates (Map)
12
13 %% โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
14 Note over UI,API: ๐ฌ SEND MESSAGE
15 %% โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
16
17 UI->>chatStore: sendMessage(content, extras)
18 activate chatStore
19
20 chatStore->>chatStore: setChatLoading(convId, true)
21 chatStore->>chatStore: clearChatStreaming(convId)
22
23 alt no active conversation
24 chatStore->>convStore: createConversation()
25 Note over convStore: โ see conversations-flow.mmd
26 end
27
28 chatStore->>chatStore: addMessage("user", content, extras)
29 chatStore->>DbSvc: createMessageBranch(userMsg, parentId)
30 chatStore->>convStore: addMessageToActive(userMsg)
31 chatStore->>convStore: updateCurrentNode(userMsg.id)
32
33 chatStore->>chatStore: createAssistantMessage(userMsg.id)
34 chatStore->>DbSvc: createMessageBranch(assistantMsg, userMsg.id)
35 chatStore->>convStore: addMessageToActive(assistantMsg)
36
37 chatStore->>chatStore: streamChatCompletion(messages, assistantMsg)
38 deactivate chatStore
39
40 %% โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
41 Note over UI,API: ๐ STREAMING
42 %% โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
43
44 activate chatStore
45 chatStore->>chatStore: startStreaming()
46 Note right of chatStore: isStreamingActive = true
47
48 chatStore->>chatStore: setActiveProcessingConversation(convId)
49 chatStore->>chatStore: getOrCreateAbortController(convId)
50 Note right of chatStore: abortControllers.set(convId, new AbortController())
51
52 chatStore->>chatStore: getApiOptions()
53 Note right of chatStore: Merge from settingsStore.config:<br/>temperature, max_tokens, top_p, etc.
54
55 chatStore->>ChatSvc: sendMessage(messages, options, signal)
56 activate ChatSvc
57
58 ChatSvc->>ChatSvc: convertMessageToChatData(messages)
59 Note right of ChatSvc: DatabaseMessage[] โ ApiChatMessageData[]<br/>Process attachments (images, PDFs, audio)
60
61 ChatSvc->>API: POST /v1/chat/completions
62 Note right of API: {messages, model?, stream: true, ...params}
63
64 loop SSE chunks
65 API-->>ChatSvc: data: {"choices":[{"delta":{...}}]}
66 ChatSvc->>ChatSvc: parseSSEChunk(line)
67
68 alt content chunk
69 ChatSvc-->>chatStore: onChunk(content)
70 chatStore->>chatStore: setChatStreaming(convId, response, msgId)
71 Note right of chatStore: currentResponse = $state(accumulated)
72 chatStore->>convStore: updateMessageAtIndex(idx, {content})
73 end
74
75 alt reasoning chunk
76 ChatSvc-->>chatStore: onReasoningChunk(reasoning)
77 chatStore->>convStore: updateMessageAtIndex(idx, {thinking})
78 end
79
80 alt tool_calls chunk
81 ChatSvc-->>chatStore: onToolCallChunk(toolCalls)
82 chatStore->>convStore: updateMessageAtIndex(idx, {toolCalls})
83 end
84
85 alt model info
86 ChatSvc-->>chatStore: onModel(modelName)
87 chatStore->>chatStore: recordModel(modelName)
88 chatStore->>DbSvc: updateMessage(msgId, {model})
89 end
90
91 alt timings (during stream)
92 ChatSvc-->>chatStore: onTimings(timings, promptProgress)
93 chatStore->>chatStore: updateProcessingStateFromTimings()
94 end
95
96 chatStore-->>UI: reactive $state update
97 end
98
99 API-->>ChatSvc: data: [DONE]
100 ChatSvc-->>chatStore: onComplete(content, reasoning, timings, toolCalls)
101 deactivate ChatSvc
102
103 chatStore->>chatStore: stopStreaming()
104 chatStore->>DbSvc: updateMessage(msgId, {content, timings, model})
105 chatStore->>convStore: updateCurrentNode(msgId)
106 chatStore->>chatStore: setChatLoading(convId, false)
107 chatStore->>chatStore: clearChatStreaming(convId)
108 chatStore->>chatStore: clearProcessingState(convId)
109 deactivate chatStore
110
111 %% โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
112 Note over UI,API: โน๏ธ STOP GENERATION
113 %% โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
114
115 UI->>chatStore: stopGeneration()
116 activate chatStore
117 chatStore->>chatStore: savePartialResponseIfNeeded(convId)
118 Note right of chatStore: Save currentResponse to DB if non-empty
119 chatStore->>chatStore: abortControllers.get(convId).abort()
120 Note right of chatStore: fetch throws AbortError โ caught by isAbortError()
121 chatStore->>chatStore: stopStreaming()
122 chatStore->>chatStore: setChatLoading(convId, false)
123 chatStore->>chatStore: clearChatStreaming(convId)
124 chatStore->>chatStore: clearProcessingState(convId)
125 deactivate chatStore
126
127 %% โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
128 Note over UI,API: ๐ REGENERATE
129 %% โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
130
131 UI->>chatStore: regenerateMessageWithBranching(msgId, model?)
132 activate chatStore
133 chatStore->>convStore: findMessageIndex(msgId)
134 chatStore->>chatStore: Get parent of target message
135 chatStore->>chatStore: createAssistantMessage(parentId)
136 chatStore->>DbSvc: createMessageBranch(newAssistantMsg, parentId)
137 chatStore->>convStore: refreshActiveMessages()
138 Note right of chatStore: Same streaming flow
139 chatStore->>chatStore: streamChatCompletion(...)
140 deactivate chatStore
141
142 %% โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
143 Note over UI,API: โก๏ธ CONTINUE
144 %% โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
145
146 UI->>chatStore: continueAssistantMessage(msgId)
147 activate chatStore
148 chatStore->>chatStore: Get existing content from message
149 chatStore->>chatStore: streamChatCompletion(..., existingContent)
150 Note right of chatStore: Appends to existing message content
151 deactivate chatStore
152
153 %% โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
154 Note over UI,API: โ๏ธ EDIT USER MESSAGE
155 %% โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
156
157 UI->>chatStore: editUserMessagePreserveResponses(msgId, newContent)
158 activate chatStore
159 chatStore->>chatStore: Get parent of target message
160 chatStore->>DbSvc: createMessageBranch(editedMsg, parentId)
161 chatStore->>convStore: refreshActiveMessages()
162 Note right of chatStore: Creates new branch, original preserved
163 deactivate chatStore
164
165 %% โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
166 Note over UI,API: โ ERROR HANDLING
167 %% โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
168
169 Note over chatStore: On stream error (non-abort):
170 chatStore->>chatStore: showErrorDialog(type, message)
171 Note right of chatStore: errorDialogState = {type: 'timeout'|'server', message}
172 chatStore->>convStore: removeMessageAtIndex(failedMsgIdx)
173 chatStore->>DbSvc: deleteMessage(failedMsgId)
174```