Successfully implemented WebSocket support for LlamaTale's web browser interface using FastAPI, as requested in issue #XXX.
- requirements.txt - Added FastAPI, websockets, and uvicorn dependencies; updated aiohttp to >=3.9.0
- tale/tio/if_browser_io.py - Added TaleFastAPIApp class with WebSocket endpoint
- tale/driver_if.py - Added use_websocket parameter and FastAPI server initialization
- tale/main.py - Added --websocket command-line argument
- tale/web/script.js - Added WebSocket client with EventSource fallback
- WEBSOCKET.md - Comprehensive documentation for the feature
- TaleFastAPIApp class: FastAPI application with WebSocket endpoint at
/tale/ws - Core Methods (as requested in the issue):
_get_player_from_headers(): Returns player connection (single player mode)_handle_player_input(): Feeds WebSocket text into input queue_cleanup_player(): Handles connection teardown_process_command(): Extracted helper for command processing
- Performance Optimizations:
- Adaptive timeout: 0.1s when active, 0.5s when idle
- Additional 0.1s sleep when no activity to reduce CPU usage
- Error Handling:
- Specific handling for WebSocketDisconnect, CancelledError, and generic exceptions
- Proper logging with traceback for debugging
- Player context in error messages
- Automatic Detection: Tries WebSocket first, falls back to EventSource
- Connection Management: Uses connectionEstablished flag to avoid race conditions
- Error Handling:
- WebSocket send failures gracefully fall back to AJAX
- Separate handling for initial connection failures vs. established connection errors
- Helper Functions:
displayConnectionError(): Centralized error displaysendViaAjax(): Extracted AJAX sending logictryWebSocket(): WebSocket connection with fallbacksetupEventSource(): Traditional EventSource connection
Client to Server (JSON):
{
"cmd": "look around",
"autocomplete": 0 // optional
}Server to Client (Text):
{
"type": "text",
"text": "<p>HTML content...</p>",
"special": ["clear", "noecho"],
"turns": 42,
"location": "Dark Corridor",
"location_image": "corridor.jpg",
"npcs": "goblin,troll",
"items": "sword,potion",
"exits": "north,south"
}Server to Client (Data):
{
"type": "data",
"data": "base64_encoded_data..."
}python -m tale.main --game stories/dungeon --web --websocketpython -m tale.main --game stories/dungeon --web- Round 1: Address import cleanup, error message refactoring
- Round 2: Fix race conditions, optimize CPU usage with adaptive timeouts
- Round 3: Improve error handling, extract duplicate code, add fallback mechanisms
- CodeQL Scan: 0 alerts found (Python and JavaScript)
- Security Best Practices:
- Input sanitization using html_escape
- Proper JSON parsing with error handling
- No hardcoded credentials or secrets
- Secure WebSocket protocol detection (ws/wss based on http/https)
- CPU Usage: Optimized with adaptive timeouts and sleep intervals
- Memory: Efficient message queuing using existing infrastructure
- Latency: Minimal overhead with direct WebSocket communication
- ✅ EventSource mode still works (default)
- ✅ All existing functionality preserved
- ✅ Automatic client-side fallback if WebSocket unavailable
- ✅ No breaking changes to existing code
- ✅ Modern browsers (Chrome, Firefox, Safari, Edge)
- ✅ Automatic fallback to EventSource for older browsers
- ✅ WebSocket protocol support required for WebSocket mode
- Requires Python 3.7+ (for asyncio features)
- FastAPI requires Python 3.7+
- Tested with Python 3.12
- Single Player Only: WebSocket mode currently only supports IF (single player) mode
- SSL Configuration: May require additional setup for secure WebSocket (wss://)
- Reconnection: No automatic reconnection on connection loss (requires page refresh)
Potential improvements for future iterations:
- Multi-player (MUD) mode support
- Automatic reconnection with session persistence
- Message compression for large outputs
- WebSocket authentication and authorization
- Metrics and monitoring
- Connection pooling for MUD mode
- Binary message support for assets
- Start game with --websocket flag
- Verify WebSocket connection in browser console
- Send commands and verify responses
- Test autocomplete functionality
- Verify NPC, item, and exit display
- Test quit functionality
- Verify EventSource fallback works
- Test with browser WebSocket disabled
- Test with slow network connection
- Verify error messages display correctly
- Test with different story configurations
- Verify game state persistence
- Test command history
- Verify character loading
- Test save/load functionality
Complete documentation available in:
- WEBSOCKET.md: User-facing documentation
- Code Comments: Inline documentation in source files
- This Summary: Implementation details for developers
The WebSocket implementation successfully provides a modern, bidirectional communication channel for LlamaTale's web interface while maintaining full backward compatibility with the existing EventSource approach. The implementation is secure, performant, and well-documented, ready for production use in single-player mode.