"""
Bot runner for local development.
This script is called as a subprocess by the local FastAPI server.
It reads configuration from command line arguments and starts the bot.
"""
import argparse
import asyncio
import json
import os
import sys
from loguru import logger
# Add parent directory (project root) to Python path for imports
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from bot_config import BotConfig
def parse_args():
"""Parse command line arguments."""
parser = argparse.ArgumentParser(description="Pipecat bot runner")
parser.add_argument("--session-id", required=True, help="Session ID for the bot")
parser.add_argument("--room-url", required=True, help="Daily room URL")
parser.add_argument("--token", required=True, help="Daily room token")
# Bot data can be provided as JSON string or file
bot_data_group = parser.add_mutually_exclusive_group(required=True)
bot_data_group.add_argument("--bot-data", help="JSON bot configuration data")
bot_data_group.add_argument(
"--bot-config-file", help="Path to JSON bot configuration file"
)
parser.add_argument("--bot-name", default="bot", help="Bot name")
parser.add_argument("--recording-dir", default="/tmp", help="Recording directory")
parser.add_argument(
"--local-recording", action="store_true", help="Enable local recording"
)
parser.add_argument(
"--disable-rtvi",
action="store_true",
help="Disable RTVI processor and observer",
)
return parser.parse_args()
async def main():
"""Main entry point for the bot runner."""
try:
# Parse command line arguments
args = parse_args()
# Parse and validate bot data
try:
if args.bot_data:
raw_bot_data = json.loads(args.bot_data)
elif args.bot_config_file:
with open(args.bot_config_file, "r") as f:
raw_bot_data = json.load(f)
logger.info(f"📄 Loaded bot config from file: {args.bot_config_file}")
else:
logger.error("❌ No bot data provided")
sys.exit(1)
except FileNotFoundError as e:
logger.error(f"❌ Bot config file not found: {e}")
sys.exit(1)
except json.JSONDecodeError as e:
logger.error(f"❌ Failed to parse bot data JSON: {e}")
sys.exit(1)
except ValueError as e:
logger.error(f"❌ Invalid bot data format: {e}")
sys.exit(1)
except Exception as e:
logger.error(f"❌ Failed to validate bot data: {e}")
sys.exit(1)
# Create bot config
config = BotConfig(
session_id=args.session_id,
room_url=args.room_url,
token=args.token,
bot_data=raw_bot_data,
bot_name=args.bot_name,
recording_dir=args.recording_dir,
local_recording=args.local_recording,
rtvi_enabled=not args.disable_rtvi,
)
logger.info(f"🤖 Starting bot runner for session: {config.session_id}")
logger.info(f"🏠 Room URL: {config.room_url}")
logger.info(f"📋 Bot name: {config.bot_name}")
# Import and run the bot
from bot import main as bot_main
await bot_main(config)
except KeyboardInterrupt:
logger.info("🛑 Bot runner interrupted by user")
if __name__ == "__main__":
# Configure logging
logger.remove() # Remove default handler
logger.add(
sys.stdout,
format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | bot | {message}",
level="INFO",
)
# Run the bot
asyncio.run(main())