16
16
17
17
18
18
class AdvancedSQLiteSession (SQLiteSession ):
19
- """Enhanced SQLite session with turn tracking, soft deletion, and usage analytics.
19
+ """Enhanced SQLite session with conversation branching and usage analytics.
20
20
21
21
Features:
22
- - Turn-based conversation management with soft delete/reactivate
22
+ - Conversation branching from any user message
23
+ - Independent branch management with turn tracking
23
24
- Detailed usage tracking per turn with token breakdowns
24
25
- Message structure metadata and tool usage statistics
25
26
"""
26
27
27
- ACTIVE = 1 # Message is active and visible in conversation
28
- INACTIVE = 0 # Message is soft-deleted (hidden but preserved)
29
-
30
28
def __init__ (
31
29
self ,
32
30
* ,
@@ -96,7 +94,6 @@ def _init_structure_tables(self):
96
94
CREATE INDEX IF NOT EXISTS idx_structure_turn
97
95
ON message_structure(session_id, branch_id, user_turn_number)
98
96
""" )
99
- # Compound index for optimal performance on get_items queries
100
97
conn .execute ("""
101
98
CREATE INDEX IF NOT EXISTS idx_structure_branch_seq
102
99
ON message_structure(session_id, branch_id, sequence_number)
@@ -375,15 +372,13 @@ def _is_user_message(self, item: TResponseInputItem) -> bool:
375
372
async def get_items (
376
373
self ,
377
374
limit : int | None = None ,
378
- include_inactive : bool = False ,
379
375
branch_id : str | None = None ,
380
376
) -> list [TResponseInputItem ]:
381
- """Get items from current or specified branch, optionally including soft-deleted ones ."""
377
+ """Get items from current or specified branch."""
382
378
if branch_id is None :
383
379
branch_id = self ._current_branch_id
384
380
385
- if include_inactive :
386
- # Get all items (active and inactive) for this branch
381
+ # Get all items for this branch
387
382
def _get_all_items_sync ():
388
383
conn = self ._get_connection ()
389
384
with self ._lock if self ._is_memory_db else threading .Lock ():
@@ -427,12 +422,11 @@ def _get_all_items_sync():
427
422
428
423
return await asyncio .to_thread (_get_all_items_sync )
429
424
430
- # Filter to only active items in this branch
431
- def _get_active_items_sync ():
425
+ def _get_items_sync ():
432
426
conn = self ._get_connection ()
433
427
with self ._lock if self ._is_memory_db else threading .Lock ():
434
428
with closing (conn .cursor ()) as cursor :
435
- # Get active message IDs in correct order for this branch
429
+ # Get message IDs in correct order for this branch
436
430
if limit is None :
437
431
cursor .execute (
438
432
"""
@@ -470,7 +464,7 @@ def _get_active_items_sync():
470
464
continue
471
465
return items
472
466
473
- return await asyncio .to_thread (_get_active_items_sync )
467
+ return await asyncio .to_thread (_get_items_sync )
474
468
475
469
async def _copy_messages_to_new_branch (self , new_branch_id : str , from_turn_number : int ) -> None :
476
470
"""Copy messages before the branch point to the new branch."""
@@ -562,7 +556,7 @@ async def create_branch_from_turn(
562
556
The branch_id of the newly created branch
563
557
564
558
Raises:
565
- ValueError: If turn doesn't exist, isn't active, or doesn't contain a user message
559
+ ValueError: If turn doesn't exist or doesn't contain a user message
566
560
"""
567
561
import time
568
562
@@ -576,14 +570,15 @@ def _validate_turn():
576
570
FROM message_structure ms
577
571
JOIN agent_messages am ON ms.message_id = am.id
578
572
WHERE ms.session_id = ? AND ms.branch_id = ?
579
- AND ms.branch_turn_number = ? AND ms.message_type = 'user' """ ,
573
+ AND ms.branch_turn_number = ? AND ms.message_type = 'user'
574
+ """ ,
580
575
(self .session_id , self ._current_branch_id , turn_number ),
581
576
)
582
577
583
578
result = cursor .fetchone ()
584
579
if not result :
585
580
raise ValueError (
586
- f"Turn { turn_number } does not contain an active user message "
581
+ f"Turn { turn_number } does not contain a user message "
587
582
f"in branch '{ self ._current_branch_id } '"
588
583
)
589
584
@@ -862,9 +857,9 @@ async def list_branches(self) -> list[dict[str, Any]]:
862
857
Returns:
863
858
List of dicts with branch info: {
864
859
'branch_id': str, # Branch identifier
865
- 'message_count': int, # Number of active messages in branch
860
+ 'message_count': int, # Number of messages in branch
866
861
'user_turns': int, # Number of user turns in branch
867
- 'is_current': bool, # Whether this is the current active branch
862
+ 'is_current': bool, # Whether this is the current branch
868
863
'created_at': str # When the branch was first created
869
864
}
870
865
"""
@@ -880,7 +875,8 @@ def _list_branches_sync():
880
875
COUNT(CASE WHEN ms.message_type = 'user' THEN 1 END) as user_turns,
881
876
MIN(ms.created_at) as created_at
882
877
FROM message_structure ms
883
- WHERE ms.session_id = ? GROUP BY ms.branch_id
878
+ WHERE ms.session_id = ?
879
+ GROUP BY ms.branch_id
884
880
ORDER BY created_at
885
881
""" ,
886
882
(self .session_id ,),
0 commit comments