Load conversation history from disk. Returns empty list if stale or missing.
(project_dir: str = None, path: str = None, max_age_hours: int = 2)
| 65 | warning(f"Could not save session: {e}") |
| 66 | |
| 67 | def load_session(project_dir: str = None, path: str = None, max_age_hours: int = 2) -> list: |
| 68 | """Load conversation history from disk. Returns empty list if stale or missing.""" |
| 69 | if path: |
| 70 | path = Path(path) |
| 71 | else: |
| 72 | path = _session_path(project_dir) |
| 73 | if not path.exists(): |
| 74 | return [] |
| 75 | try: |
| 76 | data = json.loads(path.read_text(encoding="utf-8")) |
| 77 | # Skip stale sessions — old context causes the model to |
| 78 | # repeat previous responses instead of following new instructions |
| 79 | saved_at_str = data.get("saved_at", "") |
| 80 | if saved_at_str: |
| 81 | try: |
| 82 | saved_at_dt = datetime.fromisoformat(saved_at_str) |
| 83 | age_hours = (datetime.now() - saved_at_dt).total_seconds() / 3600 |
| 84 | if age_hours > max_age_hours: |
| 85 | info(f"Session expired ({age_hours:.0f}h old). Starting fresh.") |
| 86 | return [] |
| 87 | except (ValueError, TypeError): |
| 88 | pass |
| 89 | history = data.get("history", []) |
| 90 | saved_at = saved_at_str[:16].replace("T", " ") if saved_at_str else "unknown" |
| 91 | turns = data.get("turns", len(history) // 2) |
| 92 | info(f"Resumed session: {turns} turns from {saved_at}") |
| 93 | return history |
| 94 | except Exception as e: |
| 95 | warning(f"Could not load session: {e}") |
| 96 | return [] |
| 97 | |
| 98 | def clear_session(project_dir: str = None): |
| 99 | """Delete saved session for current project.""" |