Overview
The engine/handlers.py module provides helper functions for broadcasting state updates and chat history to WebSocket clients. These functions are used throughout the engine to keep the TUI synchronized with backend state changes.
Functions
broadcast_sync_state
Sends current engine state to a WebSocket client, synchronizing all available worlds, characters, models, sessions, and active selections.
async def broadcast_sync_state ( ws : WebSocket) -> None
FastAPI WebSocket connection to send state to
Behavior:
Retrieves the 15 most recent sessions from the database
Formats session data with world, character, and title preview
Sends a sync_state event containing:
Active model, world, character, session IDs
Available worlds, characters, models, rules
Active rules
Recent sessions list
Source: engine/handlers.py:9-32
async def broadcast_sync_state ( ws : WebSocket):
recent_sessions = [
{ "id" : s.id, "name" : f "[ { s.world_id } ] { s.character_id } : { s.title[: 30 ] } " }
for s in session_manager.list_recent( 15 )
]
await ws.send_text(
build_ws_payload(
"sync_state" ,
"State synchronized" ,
{
"model" : state. CURRENT_MODEL ,
"model_confirmed" : state. MODEL_CONFIRMED ,
"world_id" : state. ACTIVE_WORLD_ID ,
"character_id" : state. ACTIVE_CHARACTER_ID ,
"session_id" : state. ACTIVE_SESSION_ID ,
"available_worlds" : state.available_worlds,
"available_characters" : state.available_characters,
"available_models" : state. AVAILABLE_MODELS ,
"available_rules" : state.available_rules,
"active_rules" : state. ACTIVE_RULES ,
"available_sessions" : recent_sessions,
},
)
)
WebSocket Message:
{
"event" : "sync_state" ,
"payload" : {
"content" : "State synchronized" ,
"metadata" : {
"model" : "google/gemini-2.0-pro-exp-02-05:free" ,
"model_confirmed" : true ,
"world_id" : "fantasy_world" ,
"character_id" : "elara" ,
"session_id" : "a1b2c3d4e5f6" ,
"available_worlds" : [
{ "id" : "fantasy_world" , "name" : "High Fantasy Realm" }
],
"available_characters" : [
{ "id" : "elara" , "name" : "Elara the Brave" }
],
"available_models" : [ ... ],
"available_rules" : [ ... ],
"active_rules" : [ "gritty" ],
"available_sessions" : [
{ "id" : "a1b2c3d4e5f6" , "name" : "[fantasy_world] elara: Exploring the ruins" }
]
}
}
}
Used By:
engine/main.py - Initial connection handshake
engine/commands.py - After world/character/session/rules changes
send_chat_history
Retrieves and sends the complete message history for a character’s session.
async def send_chat_history ( ws : WebSocket, char_id : str , session_id : str ) -> None
FastAPI WebSocket connection
Character ID to fetch messages for
Session ID to fetch messages for
Behavior:
Queries the database for all messages in the session
Converts messages to {role, content} format
Sends a chat_history event with the message array
Source: engine/handlers.py:35-46
async def send_chat_history ( ws : WebSocket, char_id : str , session_id : str ):
messages = msg_manager.get_messages(char_id, session_id)
history = [{ "role" : m.role, "content" : m.content} for m in messages]
await ws.send_text(
json.dumps(
{
"event" : "chat_history" ,
"payload" : { "content" : "" , "metadata" : { "history" : history}},
}
)
)
WebSocket Message:
{
"event" : "chat_history" ,
"payload" : {
"content" : "" ,
"metadata" : {
"history" : [
{ "role" : "assistant" , "content" : "Welcome to the realm..." },
{ "role" : "user" , "content" : "I look around carefully." },
{ "role" : "assistant" , "content" : "You see ancient ruins..." }
]
}
}
}
Used By:
/session continue command - Loads history when resuming a session
Usage Example
from fastapi import WebSocket
from engine.handlers import broadcast_sync_state, send_chat_history
import engine.state as state
# After a command that changes state
async def handle_world_select ( ws : WebSocket, world_id : str ):
state. ACTIVE_WORLD_ID = world_id
state.save_state()
# Notify client of state change
await broadcast_sync_state(ws)
# When continuing a session
async def continue_session ( ws : WebSocket, session_id : str ):
sess = session_manager.get_session(session_id)
if sess:
state. ACTIVE_SESSION_ID = sess.id
state. ACTIVE_WORLD_ID = sess.world_id
state. ACTIVE_CHARACTER_ID = sess.character_id
# Load history first
await send_chat_history(ws, sess.character_id, sess.id)
# Then sync state
await broadcast_sync_state(ws)
Dependencies
fastapi.WebSocket - WebSocket connection type
engine.database.msg_manager - Message retrieval
engine.database.session_manager - Session retrieval
engine.utils.build_ws_payload - JSON payload builder
engine.state - Global state variables
WebSocket Protocol Message format specification
State Management Global state variables
Commands Command handlers that use these functions
Utils WebSocket payload builder