* Use 'docker compose' not 'docker-compose' * server, client, and voicebot directories always run in containers with those names * All tests created must be put in tests/, which is bind mounted into the containers in /tests. * In client, to run any npm, npx, node, etc. you need to run via 'docker compose exec client COMMAND' * In voicebot, to run any python code, you need to run via 'docker compose exec voicebot uv run COMMAND' * In server, to run any python code, you need to run via 'docker compose exec server uv run COMMAND' * Server runs HTTPS, self-signed (-k for curl). It is port 8001 on the host and port 8000 inside the docker container. public_url is set to /ai-voicebot, so URLs should be https://localhost:8001/ai-voicebot/... (from host) or https://server:8000/ai-voicebot/... (from inside docker). * Voicebot runs HTTP. It is not exposed to the host and is connected to by server at http://voicebot:8788. * All services use hot-load. Any time you change a file, the service will reload. This is not an error. Examination of logs should occur beginning with the messages after the most recent startup complete. * All docker tail calls should be time relative, not message count relative. Eg., --since 10m not -n 100. ## Testing Instructions ### General Testing Guidelines - Always run tests inside the appropriate Docker containers using `docker compose exec` - Use `uv run` for Python commands in voicebot and server containers - Tests should be placed in the `tests/` directory (bind mounted to `/tests` in containers) - Use proper PYTHONPATH when running Python code: `PYTHONPATH=/:/voicebot` for voicebot, `PYTHONPATH=/:/server` for server - Check container logs with `docker compose logs --since 10m SERVICE_NAME` for debugging ### Voicebot Testing (Python with uv) #### Running Python Code in Voicebot Container ```bash # Basic Python execution docker compose exec voicebot uv run python3 -c "print('Hello from voicebot')" # Running Python scripts with proper imports docker compose exec voicebot bash -c " cd /voicebot && PYTHONPATH=/shared:/voicebot uv run python3 script.py " # Running tests docker compose exec voicebot bash -c " cd /voicebot && PYTHONPATH=/shared:/voicebot uv run python3 -m pytest /tests/ -v " # Interactive Python session docker compose exec voicebot bash -c " cd /voicebot && PYTHONPATH=/shared:/voicebot uv run python3 " ``` #### Voicebot-Specific Testing Patterns ```bash # Test bot configuration updates docker compose exec voicebot bash -c " cd /voicebot && PYTHONPATH=/shared:/voicebot uv run python3 -c \" from bots.minimal import create_minimal_bot_tracks, handle_config_update tracks = create_minimal_bot_tracks('test_session', {'visualization': 'ball'}) success = handle_config_update('test_session', {'visualization': 'waveform'}) print(f'Config update success: {success}') \" " # Test WebRTC signaling docker compose exec voicebot bash -c " cd /voicebot && PYTHONPATH=/shared:/voicebot uv run python3 -c \" from webrtc_signaling import WebRTCSignalingClient # Test signaling client instantiation \" " ``` ### Server Testing (Python with uv) #### Running Python Code in Server Container ```bash # Basic Python execution docker compose exec server uv run python3 -c "print('Hello from server')" # Running server scripts with proper imports docker compose exec server bash -c " cd /server && PYTHONPATH=/shared:/server uv run python3 script.py " # Running FastAPI server tests docker compose exec server bash -c " cd /server && PYTHONPATH=/shared:/server uv run python3 -m pytest /tests/ -v " # Interactive Python session docker compose exec server bash -c " cd /server && PYTHONPATH=/shared:/server uv run python3 " ``` #### Server-Specific Testing Patterns ```bash # Test API endpoints docker compose exec server bash -c " cd /server && PYTHONPATH=/shared:/server uv run python3 -c \" import requests # Test internal API calls response = requests.get('http://localhost:8000/health') print(f'Health check: {response.status_code}') \" " # Test WebSocket connections docker compose exec server bash -c " cd /server && PYTHONPATH=/shared:/server uv run python3 -c \" from websocket.connection import WebSocketConnection # Test WebSocket connection logic \" " ``` ### Shared Module Testing #### Testing Shared Modules from Voicebot ```bash # Test shared modules from voicebot container docker compose exec voicebot bash -c " cd /shared && PYTHONPATH=/shared uv run python3 -c \" from shared.logger import logger from shared.models import ChatMessageModel logger.info('Testing shared modules') print('Shared modules imported successfully') \" " # Run shared module tests docker compose exec voicebot bash -c " cd /shared && PYTHONPATH=/shared uv run python3 -m pytest /tests/test_shared/ -v " ``` #### Testing Shared Modules from Server ```bash # Test shared modules from server container docker compose exec server bash -c " cd /shared && PYTHONPATH=/shared uv run python3 -c \" from shared.logger import logger from shared.models import BotConfigSchema logger.info('Testing shared modules from server') print('Shared modules imported successfully') \" " ``` ### Integration Testing #### Cross-Service Testing ```bash # Test voicebot-server communication docker compose exec voicebot bash -c " cd /voicebot && PYTHONPATH=/shared:/voicebot uv run python3 -c \" import requests # Test connection to server try: response = requests.get('http://server:8000/health') print(f'Server connection: {response.status_code}') except Exception as e: print(f'Connection failed: {e}') \" " # Test server-voicebot communication docker compose exec server bash -c " cd /server && PYTHONPATH=/shared:/server uv run python3 -c \" import requests # Test connection to voicebot try: response = requests.get('http://voicebot:8788/health') print(f'Voicebot connection: {response.status_code}') except Exception as e: print(f'Connection failed: {e}') \" " ``` ### Debugging and Logging #### Container Logs ```bash # View recent logs for all services docker compose logs --since 10m # View logs for specific service docker compose logs --since 10m voicebot docker compose logs --since 10m server docker compose logs --since 10m client # Follow logs in real-time docker compose logs -f voicebot ``` #### Debugging Python Code ```bash # Run with debug output docker compose exec voicebot bash -c " cd /voicebot && PYTHONPATH=/shared:/voicebot uv run python3 -c \" import logging logging.basicConfig(level=logging.DEBUG) # Your debug code here \" " # Check Python path and imports docker compose exec voicebot bash -c " cd /voicebot && PYTHONPATH=/shared:/voicebot uv run python3 -c \" import sys print('Python path:', sys.path) import shared.logger print('Shared logger imported successfully') \" " ``` ### Best Practices 1. **Always use proper PYTHONPATH**: Include `/shared` and the service directory 2. **Test in containers**: Never run Python code directly on host - always use `docker compose exec` 3. **Use uv run**: Always prefix Python commands with `uv run` in voicebot and server 4. **Check logs**: Use `docker compose logs --since 10m` for debugging 5. **Hot reload**: Services reload automatically on file changes - wait for reload messages 6. **Test isolation**: Use unique identifiers for test sessions to avoid conflicts 7. **Network calls**: Use service names (server, voicebot) for internal communication 8. **Dependencies**: All Python dependencies are managed via uv - don't use pip directly ### Common Issues and Solutions #### Import Errors ```bash # If shared modules can't be imported docker compose exec voicebot bash -c " cd /voicebot && PYTHONPATH=/shared:/voicebot uv run python3 -c \" import sys sys.path.insert(0, '/shared') from shared.logger import logger print('Import successful') \" " ``` #### Module Not Found ```bash # Check if modules exist and PYTHONPATH is correct docker compose exec voicebot bash -c " ls -la /shared/ echo 'PYTHONPATH=/shared:/voicebot' PYTHONPATH=/shared:/voicebot uv run python3 -c 'import shared.logger' " ``` #### Container Connection Issues ```bash # Check container status docker compose ps # Restart services if needed docker compose restart voicebot docker compose restart server "