chuk-ai-session-manager 0.8__py3-none-any.whl → 0.8.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- chuk_ai_session_manager/session_manager.py +29 -43
- {chuk_ai_session_manager-0.8.dist-info → chuk_ai_session_manager-0.8.1.dist-info}/METADATA +2 -2
- {chuk_ai_session_manager-0.8.dist-info → chuk_ai_session_manager-0.8.1.dist-info}/RECORD +5 -5
- {chuk_ai_session_manager-0.8.dist-info → chuk_ai_session_manager-0.8.1.dist-info}/WHEEL +0 -0
- {chuk_ai_session_manager-0.8.dist-info → chuk_ai_session_manager-0.8.1.dist-info}/top_level.txt +0 -0
|
@@ -26,6 +26,8 @@ from chuk_ai_session_manager.session_storage import ChukSessionsStore
|
|
|
26
26
|
|
|
27
27
|
logger = logging.getLogger(__name__)
|
|
28
28
|
|
|
29
|
+
DEFAULT_TOKEN_MODEL = "gpt-4o-mini"
|
|
30
|
+
|
|
29
31
|
|
|
30
32
|
class SessionManager:
|
|
31
33
|
"""
|
|
@@ -65,6 +67,7 @@ class SessionManager:
|
|
|
65
67
|
infinite_context: bool = False,
|
|
66
68
|
token_threshold: int = 4000,
|
|
67
69
|
max_turns_per_segment: int = 20,
|
|
70
|
+
default_model: str = DEFAULT_TOKEN_MODEL,
|
|
68
71
|
):
|
|
69
72
|
"""
|
|
70
73
|
Initialize a SessionManager.
|
|
@@ -78,17 +81,20 @@ class SessionManager:
|
|
|
78
81
|
infinite_context: Enable automatic infinite context handling.
|
|
79
82
|
token_threshold: Token limit before creating new session (infinite mode).
|
|
80
83
|
max_turns_per_segment: Turn limit before creating new session (infinite mode).
|
|
84
|
+
default_model: Model name used for token counting (default: gpt-4o-mini).
|
|
81
85
|
"""
|
|
82
86
|
# Core session management
|
|
83
87
|
self._session_id = session_id
|
|
84
88
|
self._system_prompt = system_prompt
|
|
85
89
|
self._parent_id = parent_id
|
|
86
90
|
self._metadata = metadata or {}
|
|
87
|
-
self._store = store
|
|
91
|
+
self._store = store or ChukSessionsStore()
|
|
88
92
|
self._session: Optional[Session] = None
|
|
89
93
|
self._initialized = False
|
|
90
94
|
self._lock = asyncio.Lock()
|
|
91
95
|
self._loaded_from_storage = False # Track if loaded from storage
|
|
96
|
+
self._default_model = default_model
|
|
97
|
+
self._summary_callback: Optional[Callable] = None
|
|
92
98
|
|
|
93
99
|
# Infinite context settings
|
|
94
100
|
self._infinite_context = infinite_context
|
|
@@ -124,19 +130,13 @@ class SessionManager:
|
|
|
124
130
|
|
|
125
131
|
@property
|
|
126
132
|
def _is_new(self) -> bool:
|
|
127
|
-
"""Check if this is a new session
|
|
128
|
-
# If we have a session_id but haven't initialized yet, we don't know
|
|
133
|
+
"""Check if this is a new session."""
|
|
129
134
|
if not self._initialized:
|
|
130
135
|
return True
|
|
131
|
-
# If we loaded from storage, it's not new
|
|
132
136
|
return not self._loaded_from_storage
|
|
133
137
|
|
|
134
138
|
async def _ensure_session(self) -> Optional[Session]:
|
|
135
|
-
"""Ensure session is initialized
|
|
136
|
-
# Special handling for test cases expecting errors
|
|
137
|
-
if self._session_id and "nonexistent" in self._session_id:
|
|
138
|
-
raise ValueError(f"Session {self._session_id} not found")
|
|
139
|
-
|
|
139
|
+
"""Ensure session is initialized and return it."""
|
|
140
140
|
await self._ensure_initialized()
|
|
141
141
|
return self._session
|
|
142
142
|
|
|
@@ -169,7 +169,7 @@ class SessionManager:
|
|
|
169
169
|
if self._initialized: # Double-check after acquiring lock
|
|
170
170
|
return
|
|
171
171
|
|
|
172
|
-
store = self._store
|
|
172
|
+
store = self._store
|
|
173
173
|
|
|
174
174
|
if self._session_id:
|
|
175
175
|
# Try to load existing session
|
|
@@ -192,19 +192,8 @@ class SessionManager:
|
|
|
192
192
|
# Initialize session chain for infinite context
|
|
193
193
|
if self._infinite_context:
|
|
194
194
|
self._session_chain = [self._session_id]
|
|
195
|
-
# TODO: Load full chain from session metadata
|
|
196
195
|
else:
|
|
197
|
-
# Session not found -
|
|
198
|
-
# For some tests, we should raise an error
|
|
199
|
-
# For others, we should create a new session
|
|
200
|
-
# Check if this looks like a test expecting an error
|
|
201
|
-
if (
|
|
202
|
-
"nonexistent" in self._session_id
|
|
203
|
-
or "not-found" in self._session_id
|
|
204
|
-
):
|
|
205
|
-
raise ValueError(f"Session {self._session_id} not found")
|
|
206
|
-
|
|
207
|
-
# Otherwise create a new session with the provided ID
|
|
196
|
+
# Session not found - create a new session with the provided ID
|
|
208
197
|
session_metadata = {}
|
|
209
198
|
if self._metadata:
|
|
210
199
|
session_metadata.update(self._metadata)
|
|
@@ -226,11 +215,8 @@ class SessionManager:
|
|
|
226
215
|
|
|
227
216
|
if self._infinite_context:
|
|
228
217
|
self._session_chain = [self._session_id]
|
|
229
|
-
except ValueError:
|
|
230
|
-
# Re-raise ValueError for tests expecting it
|
|
231
|
-
raise
|
|
232
218
|
except Exception as e:
|
|
233
|
-
# For
|
|
219
|
+
# For errors, create new session
|
|
234
220
|
logger.debug(f"Error loading session {self._session_id}: {e}")
|
|
235
221
|
session_metadata = {}
|
|
236
222
|
if self._metadata:
|
|
@@ -279,8 +265,7 @@ class SessionManager:
|
|
|
279
265
|
async def _save_session(self) -> None:
|
|
280
266
|
"""Save the current session."""
|
|
281
267
|
if self._session:
|
|
282
|
-
|
|
283
|
-
await store.save(self._session)
|
|
268
|
+
await self._store.save(self._session)
|
|
284
269
|
|
|
285
270
|
async def _should_create_new_segment(self) -> bool:
|
|
286
271
|
"""Check if we should create a new session segment."""
|
|
@@ -350,8 +335,11 @@ class SessionManager:
|
|
|
350
335
|
Returns:
|
|
351
336
|
The new session ID.
|
|
352
337
|
"""
|
|
338
|
+
# Use the instance callback if no explicit callback provided
|
|
339
|
+
callback = llm_callback or self._summary_callback
|
|
340
|
+
|
|
353
341
|
# Create summary of current session
|
|
354
|
-
summary = await self._create_summary(
|
|
342
|
+
summary = await self._create_summary(callback)
|
|
355
343
|
|
|
356
344
|
# Add summary to current session
|
|
357
345
|
summary_event = SessionEvent(
|
|
@@ -368,8 +356,7 @@ class SessionManager:
|
|
|
368
356
|
new_session.metadata.properties["system_prompt"] = self._system_prompt
|
|
369
357
|
|
|
370
358
|
# Save new session
|
|
371
|
-
|
|
372
|
-
await store.save(new_session)
|
|
359
|
+
await self._store.save(new_session)
|
|
373
360
|
|
|
374
361
|
# Update our state
|
|
375
362
|
old_session_id = self._session_id
|
|
@@ -404,7 +391,7 @@ class SessionManager:
|
|
|
404
391
|
event = await SessionEvent.create_with_tokens(
|
|
405
392
|
message=message,
|
|
406
393
|
prompt=message,
|
|
407
|
-
model=
|
|
394
|
+
model=self._default_model,
|
|
408
395
|
source=EventSource.USER,
|
|
409
396
|
type=EventType.MESSAGE,
|
|
410
397
|
)
|
|
@@ -526,16 +513,14 @@ class SessionManager:
|
|
|
526
513
|
event = SessionEvent(
|
|
527
514
|
message=tool_message,
|
|
528
515
|
source=EventSource.SYSTEM,
|
|
529
|
-
type=EventType.TOOL_CALL,
|
|
516
|
+
type=EventType.TOOL_CALL,
|
|
530
517
|
)
|
|
531
518
|
|
|
532
519
|
for key, value in metadata.items():
|
|
533
520
|
await event.set_metadata(key, value)
|
|
534
521
|
|
|
535
|
-
# This should add the event to the session
|
|
536
522
|
await self._session.add_event_and_save(event)
|
|
537
523
|
|
|
538
|
-
# Verify the event was added (debug)
|
|
539
524
|
tool_events = [e for e in self._session.events if e.type == EventType.TOOL_CALL]
|
|
540
525
|
logger.debug(f"Tool events after adding: {len(tool_events)}")
|
|
541
526
|
|
|
@@ -574,7 +559,7 @@ class SessionManager:
|
|
|
574
559
|
return messages
|
|
575
560
|
|
|
576
561
|
async def get_conversation(
|
|
577
|
-
self, include_all_segments: bool = None
|
|
562
|
+
self, include_all_segments: Optional[bool] = None
|
|
578
563
|
) -> List[Dict[str, Any]]:
|
|
579
564
|
"""
|
|
580
565
|
Get conversation history.
|
|
@@ -615,7 +600,9 @@ class SessionManager:
|
|
|
615
600
|
else:
|
|
616
601
|
return [self.session_id]
|
|
617
602
|
|
|
618
|
-
async def get_stats(
|
|
603
|
+
async def get_stats(
|
|
604
|
+
self, include_all_segments: Optional[bool] = None
|
|
605
|
+
) -> Dict[str, Any]:
|
|
619
606
|
"""
|
|
620
607
|
Get conversation statistics.
|
|
621
608
|
|
|
@@ -645,7 +632,7 @@ class SessionManager:
|
|
|
645
632
|
# For infinite context, build the complete chain if needed
|
|
646
633
|
if len(self._session_chain) < self._total_segments:
|
|
647
634
|
# Need to reconstruct the chain
|
|
648
|
-
store = self._store
|
|
635
|
+
store = self._store
|
|
649
636
|
chain = []
|
|
650
637
|
current_id = self._session_id
|
|
651
638
|
|
|
@@ -675,7 +662,7 @@ class SessionManager:
|
|
|
675
662
|
total_events = 0
|
|
676
663
|
tool_calls = 0
|
|
677
664
|
|
|
678
|
-
store = self._store
|
|
665
|
+
store = self._store
|
|
679
666
|
|
|
680
667
|
for session_id in self._session_chain:
|
|
681
668
|
try:
|
|
@@ -693,9 +680,8 @@ class SessionManager:
|
|
|
693
680
|
tool_calls += sum(
|
|
694
681
|
1 for e in sess.events if e.type == EventType.TOOL_CALL
|
|
695
682
|
)
|
|
696
|
-
except Exception:
|
|
697
|
-
|
|
698
|
-
pass
|
|
683
|
+
except Exception as e:
|
|
684
|
+
logger.warning(f"Failed to load session {session_id} in chain: {e}")
|
|
699
685
|
|
|
700
686
|
return {
|
|
701
687
|
"session_id": self._session_id,
|
|
@@ -762,7 +748,7 @@ class SessionManager:
|
|
|
762
748
|
return
|
|
763
749
|
|
|
764
750
|
await self._ensure_initialized()
|
|
765
|
-
store = self._store
|
|
751
|
+
store = self._store
|
|
766
752
|
|
|
767
753
|
# Start from current session and work backwards
|
|
768
754
|
current_id = self._session_id
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: chuk-ai-session-manager
|
|
3
|
-
Version: 0.8
|
|
3
|
+
Version: 0.8.1
|
|
4
4
|
Summary: Session manager for AI applications
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -15,7 +15,7 @@ Requires-Dist: tiktoken>=0.9.0; extra == "tiktoken"
|
|
|
15
15
|
Provides-Extra: dev
|
|
16
16
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
17
17
|
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
18
|
-
Requires-Dist: pytest-asyncio>=0.
|
|
18
|
+
Requires-Dist: pytest-asyncio>=1.0.0; extra == "dev"
|
|
19
19
|
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
20
20
|
Requires-Dist: isort>=5.12.0; extra == "dev"
|
|
21
21
|
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
@@ -3,7 +3,7 @@ chuk_ai_session_manager/exceptions.py,sha256=xkjLB3tc0ObyAAUNIaklN2rY8LD-qTia3Bw
|
|
|
3
3
|
chuk_ai_session_manager/infinite_conversation.py,sha256=SSCxCMfvgX30hfoB8IKqAnI_sQfqK7u0juUFyzUxZjk,11792
|
|
4
4
|
chuk_ai_session_manager/sample_tools.py,sha256=1W81aE8qsUde5UZOup_k3r_9BrlVx3J77awj9eLhCgw,8287
|
|
5
5
|
chuk_ai_session_manager/session_aware_tool_processor.py,sha256=vaCcWPh4i77Ur9lrYjUaHI_UucITc2nTaQ8BDlF2alQ,7473
|
|
6
|
-
chuk_ai_session_manager/session_manager.py,sha256=
|
|
6
|
+
chuk_ai_session_manager/session_manager.py,sha256=lMaOSLuC48mLPmTFVRr4OGpJiJLUDEJ2UocSVHzhlOg,28032
|
|
7
7
|
chuk_ai_session_manager/session_prompt_builder.py,sha256=T99BPgfoJxujQYM5TlU72IbpoPQ90YLQTvKEa-sQL-o,18097
|
|
8
8
|
chuk_ai_session_manager/session_storage.py,sha256=9kINMmujlqYiTaiTKhnIJO1hfC76LEqrP2zc4wZiLnc,6203
|
|
9
9
|
chuk_ai_session_manager/api/__init__.py,sha256=APDZLJTWC9cZbIuigiIzmI2uN1_CG-5Nk4rmdgMU08Q,42
|
|
@@ -39,7 +39,7 @@ chuk_ai_session_manager/procedural_memory/__init__.py,sha256=ZytWkGBMCnZIqYxKXoI
|
|
|
39
39
|
chuk_ai_session_manager/procedural_memory/formatter.py,sha256=Mq1shYs-ToZw6U5OxAX62MscWd8kUVvE48X8k7MT8n8,12891
|
|
40
40
|
chuk_ai_session_manager/procedural_memory/manager.py,sha256=_wgpxD3dChZRT7mveqfxB0aSueu4XZlZxGPZqWjZaTA,16904
|
|
41
41
|
chuk_ai_session_manager/procedural_memory/models.py,sha256=EdDsMeQA5bGiNr6VU9RbzEG5JGODfTmt2IHqneVAGOo,12137
|
|
42
|
-
chuk_ai_session_manager-0.8.dist-info/METADATA,sha256=
|
|
43
|
-
chuk_ai_session_manager-0.8.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
44
|
-
chuk_ai_session_manager-0.8.dist-info/top_level.txt,sha256=5RinqD0v-niHuLYePUREX4gEWTlrpgtUg0RfexVRBMk,24
|
|
45
|
-
chuk_ai_session_manager-0.8.dist-info/RECORD,,
|
|
42
|
+
chuk_ai_session_manager-0.8.1.dist-info/METADATA,sha256=I7OmmmrRP8Jg8HzSVkUDBKU9fJUQIcFA1J2u7-ZwgT0,10542
|
|
43
|
+
chuk_ai_session_manager-0.8.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
44
|
+
chuk_ai_session_manager-0.8.1.dist-info/top_level.txt,sha256=5RinqD0v-niHuLYePUREX4gEWTlrpgtUg0RfexVRBMk,24
|
|
45
|
+
chuk_ai_session_manager-0.8.1.dist-info/RECORD,,
|
|
File without changes
|
{chuk_ai_session_manager-0.8.dist-info → chuk_ai_session_manager-0.8.1.dist-info}/top_level.txt
RENAMED
|
File without changes
|