|
11 | 11 | sessions where context compaction or summarization may silently change the |
12 | 12 | agent's behavior. |
13 | 13 |
|
| 14 | +Because a short fresh session will not reliably trigger compaction on demand, |
| 15 | +the default runnable demo below uses a simulated token-usage boundary while the |
| 16 | +live integration helpers keep the exact public SDK wiring you would use in a |
| 17 | +real session. |
| 18 | +
|
14 | 19 | Reference: https://github.com/anthropics/claude-agent-sdk-python/issues/772 |
15 | 20 | """ |
16 | 21 |
|
17 | 22 | import asyncio |
18 | 23 | import json |
19 | 24 | import math |
| 25 | +import os |
20 | 26 | import re |
21 | 27 | import time |
22 | 28 | from collections import Counter |
@@ -263,7 +269,45 @@ async def run_monitored_turn( |
263 | 269 | return monitor.record_turn(" ".join(text_parts), total_tokens) |
264 | 270 |
|
265 | 271 |
|
266 | | -async def main() -> None: |
| 272 | +def run_simulated_boundary_demo() -> None: |
| 273 | + """Run a deterministic boundary demo using the same scoring logic.""" |
| 274 | + monitor = SessionMonitor( |
| 275 | + compaction_drop_ratio=0.20, |
| 276 | + drift_threshold=0.30, |
| 277 | + log_path=None, |
| 278 | + ) |
| 279 | + |
| 280 | + synthetic_turns = [ |
| 281 | + ( |
| 282 | + "Use jwt validation with bcrypt hashes, redis-backed sessions, and " |
| 283 | + "foreign_key-safe migrations for the auth schema.", |
| 284 | + 1200, |
| 285 | + ), |
| 286 | + ( |
| 287 | + "Keep jwt auth, bcrypt password storage, and redis session checks " |
| 288 | + "intact while you add the profile endpoint.", |
| 289 | + 1480, |
| 290 | + ), |
| 291 | + ( |
| 292 | + "Add PATCH /profile rate limiting with concise validation and 429 " |
| 293 | + "responses. Focus on the endpoint only.", |
| 294 | + 860, |
| 295 | + ), |
| 296 | + ] |
| 297 | + |
| 298 | + print("=== Deterministic session boundary demo ===") |
| 299 | + print("This uses simulated token snapshots so the monitor always shows a boundary event.\n") |
| 300 | + for text, total_tokens in synthetic_turns: |
| 301 | + event = monitor.record_turn(text, total_tokens) |
| 302 | + if event: |
| 303 | + print(json.dumps(event, indent=2)) |
| 304 | + |
| 305 | + print("\n=== Session summary ===") |
| 306 | + print(json.dumps(monitor.summary(), indent=2)) |
| 307 | + |
| 308 | + |
| 309 | +async def run_live_demo() -> None: |
| 310 | + """Optional live SDK demo using the same monitor.""" |
267 | 311 | monitor = SessionMonitor( |
268 | 312 | compaction_drop_ratio=0.20, |
269 | 313 | drift_threshold=0.30, |
@@ -302,5 +346,15 @@ async def main() -> None: |
302 | 346 | print("plus get_context_usage() as the compaction-boundary heuristic.") |
303 | 347 |
|
304 | 348 |
|
| 349 | +async def main() -> None: |
| 350 | + run_simulated_boundary_demo() |
| 351 | + |
| 352 | + if os.getenv("CLAUDE_SESSION_MONITOR_LIVE") == "1": |
| 353 | + print("\n=== Live SDK session demo ===") |
| 354 | + await run_live_demo() |
| 355 | + else: |
| 356 | + print("\nSet CLAUDE_SESSION_MONITOR_LIVE=1 to also run the live SDK session demo.") |
| 357 | + |
| 358 | + |
305 | 359 | if __name__ == "__main__": |
306 | 360 | asyncio.run(main()) |
0 commit comments