Project

General

Profile

Flow - New Prompt » History » Version 3

Tomislav Pleše, 10/11/2025 08:46 PM

1 1 Tomislav Pleše
# Flow - New Prompt
2 2 Tomislav Pleše
3
4 3 Tomislav Pleše
1. Application Entry Point
5
  main.dart
6
    main() → runApp(MyApp())
7
2. Home Screen Initialization
8
  HomeScreen (StatefulWidget)
9
  Location: lib/screens/home_screen.dart
10
  State Initialization (HomeScreenState.initState())
11
    1. Initialize PromptArgs (empty state)
12
    2. Create BackendService instance
13
    3. Create PointManager(backendService)
14
    4. Create TreeViewManager
15
    5. Create ShardManager(pointManager, backendService)
16
    6. Create ThreadManager(pointManager, shardManager, backendService, threadMap, onMapUpdated)
17
    7. Create ContextManager(threadManager, apiService, threadMap)
18
    8. Create HomeScreenManager(managers..., callbacks...)
19
    9. Initialize UI state variables:
20
      - threadMap: Map<String, Point>
21
      - treeViewList: List<Point>
22
      - loadingExchanges: Set<String>
23
      - isLoading: bool
24
      - errorMessage: String?
25
3. User Input Flow
26
  PromptInputField (StatefulWidget)
27
  Location: lib/ui/widgets/prompt_input_field.dart
28
  User Types Prompt
29
    TextField(controller: _textController)
30
31
    User presses Send button or Enter
32
33
    _handleSendRequest()
34
35
    widget.onPrompt(text) → calls HomeScreen.onPrompt()
36
4. Prompt Processing Flow
37
  HomeScreen.onPrompt(String promptText)
38
  Async method that orchestrates the entire prompt handling
39
    1. Clear error messages (setState)
40
    2. Determine if this is a sub-prompt or regular prompt
41
    3. Create/update PromptArgs:
42
      - For regular prompt: use last Point in treeViewList as parent
43
      - For sub-prompt: use existing promptArgs with shard info
44
    4. Call HomeScreenManager.handlePrompt(...)
45
    5. Clear promptArgs (setState)
46
    6. Handle errors with setState and error display
47
5. Home Screen Manager Processing
48
  HomeScreenManager.handlePrompt(...)
49
  Location: lib/managers/home_screen_manager.dart
50
    1. Validate prompt text (not empty)
51
    2. onLoadingStateChanged(true) → updates UI loading state
52
    3. ThreadManager.updateThreadMap(promptText, promptArgs)
53
      → Returns: Point newPoint
54
    4. Create AiModelProperties (model config)
55
    5. ContextManager.createPromptContext(newPoint)
56
      → Returns: List<RequestMessage> promptContextMessages
57
    6. Track loading state for this exchange:
58
      - Extract exchangeId from newPoint.exchangesList.last
59
      - Add to loadingExchanges set
60
      - updateLoadingExchanges callback → updates HomeScreen state
61
    7. ApiService.sendPromptToAi(pointId, promptContextMessages, aiModelProperties)
62
      → Returns: Point updatedNewPoint (with AI response)
63
    8. Remove exchangeId from loadingExchanges
64
    9. Update threadMap[updatedNewPoint.id] = updatedNewPoint
65
    10. onMapUpdated() callback
66
    11. populateTreeViewList(treeViewList, updateTreeViewList)
67
    12. onClearPromptInput() → clears input field
68
    13. onLoadingStateChanged(false)
69
6. Thread Map Update (Core Logic)
70
  ThreadManager.updateThreadMap(...)
71
  Location: lib/managers/thread_manager.dart
72
    1. PointManager.createNewPoint(promptArgs, promptText)
73
      → Returns: Point newPoint (with prompt, no response yet)
74
75
    2. IF newPoint.id == newPoint.parentPointId:
76
      → Root point: Add to threadMap and return
77
78
    3. ELSE: Get parent point
79
      - IF NOT in threadMap:
80
        → PointManager.getParentPoint(fetchArgs, newPoint.id)
81
        → Cache parent in threadMap
82
      - ELSE:
83
        → Retrieve parent from threadMap
84
85
    4. Decision Branch:
86
      
87
      A. IF promptArgs.isShardChild AND selectedText exists:
88
          **SHARDING FLOW** (Sub-prompt)
89
90
          ShardManager.addShardToParentPoint(newPoint.id, parentPoint, promptArgs)
91
            → Returns: Point updatedParentPoint (with new Shard added)
92
93
          Extract parentShardId from updatedParentPoint.shardsList
94
95
          newPoint.copyWith(parentShardId: parentShardId)
96
97
          Update threadMap with both points
98
99
          onMapUpdated() callback
100
      
101
      B. ELSE:
102
          **REGULAR FLOW** (Continue conversation)
103
104
          PointManager.updateParentPoint(newPoint.id, parentPoint)
105
            → Returns: Point updatedParentPoint (with newPoint.id in pointChildren)
106
107
          Update threadMap with both points
108
109
          onMapUpdated() callback
110
111
    5. Return newPoint (or updatedNewPoint)
112
7. Tree View Update
113
  HomeScreenManager.populateTreeViewList(...)
114
    TreeViewManager.updateTreeViewList(threadMap, treeViewList)
115
      → Returns: List<Point> newTreeViewList
116
117
    updateTreeViewList callback → updates HomeScreen.treeViewList
118
119
    setState() triggers UI rebuild
120
8. Tree Rendering Flow
121
  TreeSliverThread (StatefulWidget)
122
  Location: lib/ui/widgets/tree_sliver_thread.dart
123
  State Update (_TreeSliverThreadState)
124
    didUpdateWidget(TreeSliverThread oldWidget)
125
126
    IF treeViewList or threadMap changed:
127
128
      _updateTreeList()
129
130
        TreeSliverManager.buildFlatTreeList(threadMap, treeViewList)
131
          → Returns: List<TreeNodeModel> _flatTreeList
132
133
        setState() → triggers rebuild
134
9. Tree Structure Building
135
  TreeSliverManager.buildFlatTreeList(...)
136
  Location: lib/managers/tree_sliver_manager.dart
137
  # This is the core algorithm that creates the tree structure shown in the UI
138
    1. _buildTreeStructure(treeViewList, threadMap)
139
      → Returns: List<TreeNodeModel> treeNodes
140
      
141
      Step A: Create all nodes (First Pass)
142
      ─────────────────────────────────────
143
      FOR EACH Point in treeViewList:
144
        - Get first Exchange
145
        - Check if Point has valid shards:
146
          
147
          IF has valid shards:
148
            → _createShardPointNode(point, exchange, nodeMap, threadMap)
149
              Creates:
150
              ├─ Main prompt node (no response)
151
              ├─ Shard segment nodes (response parts) [stored in nodeMap]
152
              └─ "After" segment if text remains
153
          
154
          ELSE:
155
            → Create regular TreeNodeModel
156
              Contains both prompt and full response
157
      
158
      Step B: Build hierarchy (Second Pass)
159
      ──────────────────────────────────────
160
      FOR EACH Point in treeViewList:
161
        IF Point.parentPointId == Point.id:
162
          → Add as root node
163
          → IF has shards: Add shard segments as siblings
164
        
165
        ELSE:
166
          → Find parent (could be a shard segment)
167
          → Add as child to parent
168
          → Update level (parent.level + 1)
169
          → IF this child has shards: Add child's shard segments as siblings
170
      
171
      Step C: Update hasChildren flags
172
      ──────────────────────────────────
173
174
    2. _flattenNode(node, flatList) [Recursive]
175
      → Flattens tree based on expansion states
176
      → Returns: List<TreeNodeModel> flatList
177
  # Shard Point Node Creation (_createShardPointNode)
178
    1. Create main prompt node (no response content)
179
    2. Filter valid shards (validate anchor positions)
180
    3. Sort shards by start position
181
    4. FOR EACH shard:
182
      - Extract response segment (currentPosition to shard.endPosition)
183
      - Create TreeNodeModel for segment (NodeType.shardResponse)
184
      - Store in nodeMap (NOT added as child of main node)
185
      - FOR EACH child in shard.shardChildren:
186
        → _buildChildNode(childPoint, shardSegment.id, shard.shardId, level=1, ...)
187
        → Add child as child of shard segment
188
        → IF child has shards: Add child's shard segments as siblings
189
      - Update currentPosition
190
    5. Create "after" segment if text remains
191
    6. Return main prompt node
192
10. Tree Item Rendering
193
  TreeSliverThread.build(...)
194
    SliverList.builder(
195
      itemCount: _flatTreeList.length
196
      itemBuilder: (context, index)
197
198
        Get TreeNodeModel node from _flatTreeList[index]
199
200
        Check if node.exchangeId is in loadingExchanges
201
202
        Return TreeSliverItem(node, isLoading, callbacks...)
203
    )
204
11. Individual Tree Item Display
205
  TreeSliverItem (StatelessWidget)
206
  Location: lib/ui/widgets/tree_sliver_item.dart
207
  # Build Method Structure
208
    Container (with left margin based on node.level)
209
210
      Card
211
212
        InkWell (onTap: collapses/expands, selects node)
213
214
          Padding
215
216
            Column:
217
              ├─ IF hasChildren: _buildExpansionHeader()
218
              │    → Shows "Collapse" / "Expand" with icon
219
220
              ├─ IF promptContent != null: _buildPromptSection()
221
              │    → Shows prompt with blue background
222
              │    → Icon: person icon
223
              │    → Label: "You" or "Shard"
224
225
              └─ IF responseContent != null:
226
                  IF isLoading:
227
                    → _buildStatusSection(StatusSectionConfig.loading())
228
                      Shows "Waiting for response..." with spinner
229
                  ELSE:
230
                    → _buildResponseSection()
231
                      Shows response with color based on type:
232
                      - Green for AI Assistant
233
                      - Yellow for Shard Segments
234
  # Content Section Rendering (_buildContentSection)
235
    Container (colored background)
236
237
      Column:
238
        ├─ Row (icon + label)
239
        └─ _buildSelectableText(content)
240
241
            SelectableText with custom context menu
242
243
              IF text selected:
244
                → Custom menu includes "Sub-prompt" option
245
                → _handleSubPrompt(selectedText, selection)
246
                  ├─ Copy text to clipboard
247
                  ├─ Create PromptArgs with shard info
248
                  ├─ Call prepareSubPromptInput callback
249
                  └─ Updates HomeScreen state
250
12. Sub-Prompt Preparation
251
  HomeScreen.prepareSubPromptInput(PromptArgs promptArgs)
252
    1. Validate selectedText
253
    2. setState:
254
      - Clear errorMessage
255
      - Update this.promptArgs with new values:
256
        * currentPointId
257
        * isShardChild = true
258
        * selectedText, startPosition, endPosition
259
    3. Show SnackBar: "Text copied to input..."
260
    4. Post frame callback:
261
      - PromptInputFieldKey.currentState.setText(selectedText)
262
      - PromptInputFieldKey.currentState.focusInput()
263
13. Node Selection
264
  HomeScreen.onNodeSelected(String currentPointId)
265
    1. setState:
266
      - Update promptArgs with selected node's pointId
267
      - Set isShardChild = false (continuing from this point)
268
    2. Focus input field for user to type next prompt
269
14. Data Models
270
  # Point Model (lib/models/point.dart)
271
    Point:
272
      - id: String
273
      - parentPointId: String
274
      - pointChildren: List<String>
275
      - parentShardId: String?
276
      - shardsList: List<Shard>
277
      - exchangesList: List<Exchange>
278
      - metadata: Metadata?
279
280
    Shard:
281
      - shardId: String
282
      - shardChildren: List<String>
283
      - anchor: Anchor (startPosition, endPosition, selectedText)
284
285
    Exchange:
286
      - exchangeId: String
287
      - prompt: Prompt (model, promptMessage, maxTokens)
288
      - response: Response? (with choices containing message content)
289
  # TreeNodeModel (lib/models/tree_node_model.dart)
290
    TreeNodeModel:
291
      - id: String (unique identifier for display)
292
      - pointId: String (actual Point.id)
293
      - parentId: String?
294
      - parentShardId: String?
295
      - exchangeId: String?
296
      - shardId: String?
297
      - level: int (indentation level)
298
      - isExpanded: bool
299
      - hasChildren: bool
300
      - promptContent: String?
301
      - responseContent: String?
302
      - promptRole: String?
303
      - responseRole: String?
304
      - nodeType: NodeType (exchange, shard, shardResponse)
305
      - children: List<TreeNodeModel>
306
      - shardStartPosition: int?
307
      - shardEndPosition: int?
308
      - choiceIndex: int?
309
15. Complete Flow Summary for Screenshot Example
310
  Scenario: "What's Earth?" conversation
311
    1. User types "What's Earth?" → HomeScreen.onPrompt()
312
313
    2. HomeScreenManager.handlePrompt()
314
315
    3. ThreadManager.updateThreadMap() → Creates Point T001
316
317
    4. ApiService.sendPromptToAi() → Returns response "Third planet from the Sun"
318
319
    5. TreeViewManager.updateTreeViewList() → [T001]
320
321
    6. TreeSliverManager.buildFlatTreeList()
322
      → Creates TreeNodeModel for T001 (prompt + response)
323
324
    7. TreeSliverThread renders TreeSliverItem
325
      → Shows blue "You" box: "What's Earth?"
326
      → Shows green "AI Assistant" box: "Third planet from the Sun"
327
328
    8. User selects "Sun" text → Right-click → "Sub-prompt"
329
330
    9. HomeScreen.prepareSubPromptInput()
331
      → Sets promptArgs with shard info
332
      → Fills input field with "Sun - what's this?"
333
334
    10. User types sub-prompt → HomeScreen.onPrompt()
335
336
    11. ThreadManager.updateThreadMap() with isShardChild=true
337
338
    12. ShardManager.addShardToParentPoint()
339
        → Creates Shard S01 in Point T001
340
        → Creates new Point T002 (parentShardId = S01)
341
342
    13. TreeSliverManager rebuilds tree:
343
        Point T001 now split into:
344
        ├─ Prompt: "What's Earth?"
345
        ├─ Response segment: "Third planet from the "
346
        ├─ Shard segment (with children):
347
        │  ├─ "Sun"
348
        │  └─ Child: T002
349
        │      ├─ Prompt: "Sun - what's this?"
350
        │      └─ Response: "The star" + "A luminous sphere" + "of plasma..."
351
        └─ After segment: " [remaining text]"
352
353
    14. Each subsequent sub-prompt repeats steps 8-13,
354
        creating nested tree structure as shown in screenshot