Skip to content

Commit e0fd220

Browse files
feat(chat): persist conversation history with session switching
Add ChatSession and PersistedChatMessage ObjectBox entities and regenerate schema bindings. Persist user/assistant messages, restore latest session on launch, and add history bottom sheet + New Chat flow. Harden edge cases with guarded storage reads, one-time persistence warning, duplicate-save guard, and query.remove() cascade deletion.
1 parent 2b3319f commit e0fd220

6 files changed

Lines changed: 688 additions & 14 deletions

File tree

lib/models/chat_session.dart

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import 'package:objectbox/objectbox.dart';
2+
3+
/// A persisted chat conversation.
4+
@Entity()
5+
class ChatSession {
6+
@Id()
7+
int id;
8+
9+
/// Auto-generated from the first user message.
10+
String title;
11+
12+
@Property(type: PropertyType.date)
13+
DateTime createdAt;
14+
15+
@Property(type: PropertyType.date)
16+
DateTime lastMessageAt;
17+
18+
ChatSession({
19+
this.id = 0,
20+
required this.title,
21+
DateTime? createdAt,
22+
DateTime? lastMessageAt,
23+
}) : createdAt = createdAt ?? DateTime.now(),
24+
lastMessageAt = lastMessageAt ?? DateTime.now();
25+
}
26+
27+
/// A single persisted message belonging to a [ChatSession].
28+
@Entity()
29+
class PersistedChatMessage {
30+
@Id()
31+
int id;
32+
33+
final session = ToOne<ChatSession>();
34+
35+
String content;
36+
37+
/// 0=user, 1=assistant, 2=system (mapped from ChatRole.index).
38+
int roleIndex;
39+
40+
@Property(type: PropertyType.date)
41+
DateTime timestamp;
42+
43+
bool isError;
44+
45+
PersistedChatMessage({
46+
this.id = 0,
47+
required this.content,
48+
required this.roleIndex,
49+
DateTime? timestamp,
50+
this.isError = false,
51+
}) : timestamp = timestamp ?? DateTime.now();
52+
}

lib/models/models.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ export 'patient.dart';
22
export 'lab_report.dart';
33
export 'biomarker_result.dart';
44
export 'chat_message.dart';
5+
export 'chat_session.dart';
56
export 'model_info.dart';

lib/objectbox-model.json

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,10 +194,81 @@
194194
}
195195
],
196196
"relations": []
197+
},
198+
{
199+
"id": "4:542975154161431803",
200+
"lastPropertyId": "4:4126270972844958425",
201+
"name": "ChatSession",
202+
"properties": [
203+
{
204+
"id": "1:3079507420252501277",
205+
"name": "id",
206+
"type": 6,
207+
"flags": 1
208+
},
209+
{
210+
"id": "2:7755307406885512726",
211+
"name": "title",
212+
"type": 9
213+
},
214+
{
215+
"id": "3:1585498312990007282",
216+
"name": "createdAt",
217+
"type": 10
218+
},
219+
{
220+
"id": "4:4126270972844958425",
221+
"name": "lastMessageAt",
222+
"type": 10
223+
}
224+
],
225+
"relations": []
226+
},
227+
{
228+
"id": "5:1397208082251365964",
229+
"lastPropertyId": "6:5450536964930078917",
230+
"name": "PersistedChatMessage",
231+
"properties": [
232+
{
233+
"id": "1:2957032474519806104",
234+
"name": "id",
235+
"type": 6,
236+
"flags": 1
237+
},
238+
{
239+
"id": "2:4019668193248367598",
240+
"name": "sessionId",
241+
"indexId": "5:2477129363995053950",
242+
"type": 11,
243+
"flags": 520,
244+
"relationTarget": "ChatSession"
245+
},
246+
{
247+
"id": "3:6374967230335097998",
248+
"name": "content",
249+
"type": 9
250+
},
251+
{
252+
"id": "4:2972012503306002202",
253+
"name": "roleIndex",
254+
"type": 6
255+
},
256+
{
257+
"id": "5:2296869470696146310",
258+
"name": "timestamp",
259+
"type": 10
260+
},
261+
{
262+
"id": "6:5450536964930078917",
263+
"name": "isError",
264+
"type": 1
265+
}
266+
],
267+
"relations": []
197268
}
198269
],
199-
"lastEntityId": "3:3215559289155237862",
200-
"lastIndexId": "4:2507639558608191303",
270+
"lastEntityId": "5:1397208082251365964",
271+
"lastIndexId": "5:2477129363995053950",
201272
"lastRelationId": "0:0",
202273
"lastSequenceId": "0:0",
203274
"modelVersion": 5,

0 commit comments

Comments
 (0)