fix: Persist login credentials for stable device ID
- Save user_id/device_id/access_token to crypto store on first login - restore_login() on subsequent starts (no new device each restart) - Enables proper Olm session persistence across restarts CF-1147 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
33
bot.py
33
bot.py
@@ -1,4 +1,5 @@
|
||||
import os
|
||||
import json
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
@@ -27,6 +28,7 @@ LK_KEY = os.environ["LIVEKIT_API_KEY"]
|
||||
LK_SECRET = os.environ["LIVEKIT_API_SECRET"]
|
||||
AGENT_NAME = os.environ.get("AGENT_NAME", "matrix-ai")
|
||||
STORE_PATH = os.environ.get("CRYPTO_STORE_PATH", "/data/crypto_store")
|
||||
CREDS_FILE = os.path.join(STORE_PATH, "credentials.json")
|
||||
|
||||
|
||||
class Bot:
|
||||
@@ -47,13 +49,31 @@ class Bot:
|
||||
self.dispatched_rooms = set()
|
||||
|
||||
async def start(self):
|
||||
# Restore existing session or create new one
|
||||
if os.path.exists(CREDS_FILE):
|
||||
with open(CREDS_FILE) as f:
|
||||
creds = json.load(f)
|
||||
self.client.restore_login(
|
||||
user_id=creds["user_id"],
|
||||
device_id=creds["device_id"],
|
||||
access_token=creds["access_token"],
|
||||
)
|
||||
self.client.load_store()
|
||||
logger.info("Restored session as %s (device %s)", creds["user_id"], creds["device_id"])
|
||||
else:
|
||||
resp = await self.client.login(BOT_PASS, device_name="ai-voice-bot")
|
||||
if not isinstance(resp, LoginResponse):
|
||||
logger.error("Login failed: %s", resp)
|
||||
return
|
||||
logger.info("Logged in as %s (device %s)", resp.user_id, resp.device_id)
|
||||
# Persist credentials for next restart
|
||||
with open(CREDS_FILE, "w") as f:
|
||||
json.dump({
|
||||
"user_id": resp.user_id,
|
||||
"device_id": resp.device_id,
|
||||
"access_token": resp.access_token,
|
||||
}, f)
|
||||
logger.info("Logged in as %s (device %s) — credentials saved", resp.user_id, resp.device_id)
|
||||
|
||||
# Trust our own device keys
|
||||
if self.client.should_upload_keys:
|
||||
await self.client.keys_upload()
|
||||
|
||||
@@ -74,7 +94,6 @@ class Bot:
|
||||
logger.info("Invited to %s", room.room_id)
|
||||
await self.client.join(room.room_id)
|
||||
|
||||
# LiveKit room name = Matrix room ID (Element Call convention)
|
||||
lk_room_name = room.room_id
|
||||
try:
|
||||
await self.lkapi.agent_dispatch.create_dispatch(
|
||||
@@ -90,17 +109,17 @@ class Bot:
|
||||
|
||||
async def on_sync(self, response: SyncResponse):
|
||||
"""After each sync, trust all devices in our rooms."""
|
||||
for user_id in self.client.device_store.users:
|
||||
for user_id in list(self.client.device_store.users):
|
||||
for device in self.client.device_store.active_user_devices(user_id):
|
||||
if not device.verified:
|
||||
self.client.verify_device(device)
|
||||
logger.info("Auto-trusted device %s of %s", device.device_id, user_id)
|
||||
|
||||
async def on_megolm(self, room, event: MegolmEvent):
|
||||
"""Handle undecryptable messages by requesting keys."""
|
||||
"""Log undecryptable messages."""
|
||||
logger.warning(
|
||||
"Can't decrypt event %s in %s from %s (session %s)",
|
||||
event.event_id, room.room_id, event.sender, event.session_id,
|
||||
"Undecryptable event %s in %s from %s",
|
||||
event.event_id, room.room_id, event.sender,
|
||||
)
|
||||
|
||||
async def on_key_verification(self, event):
|
||||
|
||||
Reference in New Issue
Block a user