File size: 3,267 Bytes
4ae4ae8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
"""Session state management for REFRAME — all persisted via gr.BrowserState."""

from __future__ import annotations

import json
import uuid
from dataclasses import asdict, dataclass, field
from datetime import datetime


@dataclass
class ThoughtCard:
    id: str = field(default_factory=lambda: str(uuid.uuid4())[:8])
    date: str = field(default_factory=lambda: datetime.now().strftime("%Y-%m-%d"))
    situation: str = ""
    automatic_thought: str = ""
    distortions: list[str] = field(default_factory=list)
    evidence_for: list[str] = field(default_factory=list)
    evidence_against: list[str] = field(default_factory=list)
    balanced_thought: str = ""
    emotion_before: tuple[str, int] = ("", 0)
    emotion_after: tuple[str, int] = ("", 0)


@dataclass
class Experiment:
    description: str = ""
    set_date: str = field(default_factory=lambda: datetime.now().strftime("%Y-%m-%d"))
    status: str = "pending"  # pending | completed | skipped
    outcome: str = ""
    insight: str = ""


@dataclass
class SessionState:
    session_count: int = 0
    cards: list[dict] = field(default_factory=list)
    experiments: list[dict] = field(default_factory=list)
    distortion_counts: dict[str, int] = field(default_factory=dict)
    mood_log: list[tuple[str, int]] = field(default_factory=list)
    last_summary: str = ""
    days_since_last: int = 0
    mood_trend: str = ""
    conversation_summaries: list[str] = field(default_factory=list)


def serialize_session(state: SessionState) -> str:
    """Serialize session to JSON string for BrowserState."""
    return json.dumps(asdict(state))


def deserialize_session(data: str | None) -> SessionState:
    """Deserialize session from BrowserState JSON string."""
    if not data:
        return SessionState()
    try:
        d = json.loads(data) if isinstance(data, str) else data
        return SessionState(**d)
    except (json.JSONDecodeError, TypeError):
        return SessionState()


def save_card(state: SessionState, card: ThoughtCard) -> SessionState:
    """Save a completed thought card to session."""
    state.cards.append(asdict(card))
    # Update distortion counts
    for d in card.distortions:
        state.distortion_counts[d] = state.distortion_counts.get(d, 0) + 1
    # Cap at max
    from config import MAX_CARDS
    if len(state.cards) > MAX_CARDS:
        state.cards = state.cards[-MAX_CARDS:]
    return state


def save_experiment(state: SessionState, experiment: Experiment) -> SessionState:
    """Save a behavioral experiment to session."""
    state.experiments.append(asdict(experiment))
    return state


def start_new_session(state: SessionState) -> SessionState:
    """Increment session count and calculate days since last."""
    state.session_count += 1
    return state


def get_session_context(state: SessionState) -> dict:
    """Get session data formatted for prompt injection."""
    return {
        "session_count": state.session_count,
        "cards": state.cards,
        "card_count": len(state.cards),
        "experiments": state.experiments,
        "distortion_counts": state.distortion_counts,
        "last_summary": state.last_summary,
        "days_since_last": state.days_since_last,
        "mood_trend": state.mood_trend,
    }