File size: 10,218 Bytes
41a5ab2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
```mermaid

sequenceDiagram

    participant UI as 🧩 ChatSidebar / ChatScreen

    participant convStore as πŸ—„οΈ conversationsStore

    participant chatStore as πŸ—„οΈ chatStore

    participant DbSvc as βš™οΈ DatabaseService

    participant IDB as πŸ’Ύ IndexedDB



    Note over convStore: State:<br/>conversations: DatabaseConversation[]<br/>activeConversation: DatabaseConversation | null<br/>activeMessages: DatabaseMessage[]<br/>isInitialized: boolean<br/>usedModalities: $derived({vision, audio})



    %% ═══════════════════════════════════════════════════════════════════════════

    Note over UI,IDB: πŸš€ INITIALIZATION

    %% ═══════════════════════════════════════════════════════════════════════════



    Note over convStore: Auto-initialized in constructor (browser only)

    convStore->>convStore: initialize()

    activate convStore

    convStore->>convStore: loadConversations()

    convStore->>DbSvc: getAllConversations()

    DbSvc->>IDB: SELECT * FROM conversations ORDER BY lastModified DESC

    IDB-->>DbSvc: Conversation[]

    DbSvc-->>convStore: conversations

    convStore->>convStore: conversations = $state(data)

    convStore->>convStore: isInitialized = true

    deactivate convStore



    %% ═══════════════════════════════════════════════════════════════════════════

    Note over UI,IDB: βž• CREATE CONVERSATION

    %% ═══════════════════════════════════════════════════════════════════════════



    UI->>convStore: createConversation(name?)

    activate convStore

    convStore->>DbSvc: createConversation(name || "New Chat")

    DbSvc->>IDB: INSERT INTO conversations

    IDB-->>DbSvc: conversation {id, name, lastModified, currNode: ""}

    DbSvc-->>convStore: conversation

    convStore->>convStore: conversations.unshift(conversation)

    convStore->>convStore: activeConversation = $state(conversation)

    convStore->>convStore: activeMessages = $state([])

    deactivate convStore



    %% ═══════════════════════════════════════════════════════════════════════════

    Note over UI,IDB: πŸ“‚ LOAD CONVERSATION

    %% ═══════════════════════════════════════════════════════════════════════════



    UI->>convStore: loadConversation(convId)

    activate convStore

    convStore->>DbSvc: getConversation(convId)

    DbSvc->>IDB: SELECT * FROM conversations WHERE id = ?

    IDB-->>DbSvc: conversation

    convStore->>convStore: activeConversation = $state(conversation)



    convStore->>convStore: refreshActiveMessages()

    convStore->>DbSvc: getConversationMessages(convId)

    DbSvc->>IDB: SELECT * FROM messages WHERE convId = ?

    IDB-->>DbSvc: allMessages[]

    convStore->>convStore: filterByLeafNodeId(allMessages, currNode)

    Note right of convStore: Filter to show only current branch path

    convStore->>convStore: activeMessages = $state(filtered)



    convStore->>chatStore: syncLoadingStateForChat(convId)

    Note right of chatStore: Sync isLoading/currentResponse if streaming

    deactivate convStore



    %% ═══════════════════════════════════════════════════════════════════════════

    Note over UI,IDB: 🌳 MESSAGE BRANCHING MODEL

    %% ═══════════════════════════════════════════════════════════════════════════



    Note over IDB: Message Tree Structure:<br/>- Each message has parent (null for root)<br/>- Each message has children[] array<br/>- Conversation.currNode points to active leaf<br/>- filterByLeafNodeId() traverses from root to currNode



    rect rgb(240, 240, 255)

        Note over convStore: Example Branch Structure:

        Note over convStore: root β†’ user1 β†’ assistant1 β†’ user2 β†’ assistant2a (currNode)<br/>                                    β†˜ assistant2b (alt branch)

    end



    %% ═══════════════════════════════════════════════════════════════════════════

    Note over UI,IDB: ↔️ BRANCH NAVIGATION

    %% ═══════════════════════════════════════════════════════════════════════════



    UI->>convStore: navigateToSibling(msgId, direction)

    activate convStore

    convStore->>convStore: Find message in activeMessages

    convStore->>convStore: Get parent message

    convStore->>convStore: Find sibling in parent.children[]

    convStore->>convStore: findLeafNode(siblingId, allMessages)

    Note right of convStore: Navigate to leaf of sibling branch

    convStore->>convStore: updateCurrentNode(leafId)

    convStore->>DbSvc: updateCurrentNode(convId, leafId)

    DbSvc->>IDB: UPDATE conversations SET currNode = ?

    convStore->>convStore: refreshActiveMessages()

    deactivate convStore



    %% ═══════════════════════════════════════════════════════════════════════════

    Note over UI,IDB: πŸ“ UPDATE CONVERSATION

    %% ═══════════════════════════════════════════════════════════════════════════



    UI->>convStore: updateConversationName(convId, newName)

    activate convStore

    convStore->>DbSvc: updateConversation(convId, {name: newName})

    DbSvc->>IDB: UPDATE conversations SET name = ?

    convStore->>convStore: Update in conversations array

    deactivate convStore



    Note over convStore: Auto-title update (after first response):

    convStore->>convStore: updateConversationTitleWithConfirmation()

    convStore->>convStore: titleUpdateConfirmationCallback?()

    Note right of convStore: Shows dialog if title would change



    %% ═══════════════════════════════════════════════════════════════════════════

    Note over UI,IDB: πŸ—‘οΈ DELETE CONVERSATION

    %% ═══════════════════════════════════════════════════════════════════════════



    UI->>convStore: deleteConversation(convId)

    activate convStore

    convStore->>DbSvc: deleteConversation(convId)

    DbSvc->>IDB: DELETE FROM conversations WHERE id = ?

    DbSvc->>IDB: DELETE FROM messages WHERE convId = ?

    convStore->>convStore: conversations.filter(c => c.id !== convId)

    alt deleted active conversation

        convStore->>convStore: clearActiveConversation()

    end

    deactivate convStore



    %% ═══════════════════════════════════════════════════════════════════════════

    Note over UI,IDB: πŸ“Š MODALITY TRACKING

    %% ═══════════════════════════════════════════════════════════════════════════



    Note over convStore: usedModalities = $derived.by(() => {<br/>  calculateModalitiesFromMessages(activeMessages)<br/>})



    Note over convStore: Scans activeMessages for attachments:<br/>- IMAGE β†’ vision: true<br/>- PDF (processedAsImages) β†’ vision: true<br/>- AUDIO β†’ audio: true



    UI->>convStore: getModalitiesUpToMessage(msgId)

    Note right of convStore: Used for regeneration validation<br/>Only checks messages BEFORE target



    %% ═══════════════════════════════════════════════════════════════════════════

    Note over UI,IDB: πŸ“€ EXPORT / πŸ“₯ IMPORT

    %% ═══════════════════════════════════════════════════════════════════════════



    UI->>convStore: exportAllConversations()

    activate convStore

    convStore->>DbSvc: getAllConversations()

    loop each conversation

        convStore->>DbSvc: getConversationMessages(convId)

    end

    convStore->>convStore: triggerDownload(JSON blob)

    deactivate convStore



    UI->>convStore: importConversations(file)

    activate convStore

    convStore->>convStore: Parse JSON file

    convStore->>DbSvc: importConversations(parsed)

    DbSvc->>IDB: Bulk INSERT conversations + messages

    convStore->>convStore: loadConversations()

    deactivate convStore

```