Session Lifecycle¶
Overview¶
voice-agent maintains one Claude session per Telegram chat. Sessions track working directory, message count, and pending permissions.
Session States¶
stateDiagram-v2
[*] --> NoSession
NoSession --> Active: First message or "continue"
Active --> Active: prompt/command
Active --> Reset: "new session"
Reset --> Active: automatic
Persisted sessions survive bot restarts. Say "continue" to resume previous context.
Session Data¶
Each session stores:
@dataclass
class Session:
chat_id: int # Telegram chat ID
cwd: str # Working directory
created_at: datetime # Session start time
message_count: int # Messages exchanged
permission_handler: PermissionHandler
process: subprocess.Popen | None
claude_session_id: str | None # For resuming Claude context
Persistence¶
Sessions are persisted to JSON via SessionStorage:
@dataclass
class StoredSession:
chat_id: int
cwd: str
created_at: str # ISO format
message_count: int
claude_session_id: str | None
On startup, the bot restores all persisted sessions.
Creating Sessions¶
Sessions are created on-demand when the first message arrives:
def get_or_create(self, chat_id: int, cwd: str | None = None) -> Session:
if chat_id not in self.sessions:
session = Session(
chat_id=chat_id,
cwd=cwd or self.default_cwd,
)
self.sessions[chat_id] = session
return self.sessions[chat_id]
Resetting Sessions¶
Say "new session" to reset:
def create_new(self, chat_id: int, cwd: str | None = None) -> Session:
# Clean up old session
if chat_id in self.sessions:
old = self.sessions[chat_id]
if old.process:
old.process.terminate()
# Create fresh session
session = Session(chat_id=chat_id, cwd=cwd or self.default_cwd)
self.sessions[chat_id] = session
return session
Changing Working Directory¶
Say "work on PROJECT" to switch directories:
def set_cwd(self, chat_id: int, cwd: str) -> Session:
session = self.get_or_create(chat_id)
session.cwd = cwd
return session
Session Status¶
Say "status" to see:
Working directory: /code/project
Messages: 15
Age: 1h 23m
Pending approval: Write file: /tmp/test.txt
Persistence and Resume¶
Sessions are now persisted to sessions.json (configurable via SESSION_STORAGE_PATH):
- Sessions survive bot restarts
claude_session_idenables resuming Claude context- Say "continue" to resume with full conversation history
# Resume uses --resume flag
cmd = ["claude", "--print", "--dangerously-skip-permissions"]
if session.claude_session_id:
cmd.extend(["--resume", session.claude_session_id])
cmd.append(prompt)
Memory Management¶
For long-running deployments, consider:
- Periodic cleanup of old sessions from storage
- Maximum session age limits
- Session count limits per user