# Project export: Big Daddy

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: UC Berkeley AI Hackathon 2025
- Tagline: A digital agent to monitor your child's online activities.
- Devpost: https://devpost.com/software/big-daddy
- GitHub: https://github.com/whackamadoodle3000/Big-Daddy
- Video: https://www.youtube.com/embed/06fpzJV7ULc?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 3 GitHub contributor(s) — Colin Vu (7 commits), cfitzmaurice6 (7 commits), Pranav Tadepalli (4 commits)

## Devpost submission (written by the team)

### Inspiration

These days, young children often spend hours rotting their brains away on iPads, while parents often have no other option than to give their kids some iPad play time to prevent tantrums. Traditional tools like device parental controls or GoGuardian are often too restrictive or time intensive for the parent, requiring parental interventions when their child gets frustrated with math problems and needs a break from math, or parental intervention when students need to get back on track with their educational activities. We wanted to create an intelligent daddy that acts like a caring tutor, gently guiding students back to productive learning when they get distracted but allowing them to take breaks when they need it. Traditional website blockers are too rigid and frustrating. We envisioned something smarter - an AI that understands context, recognizes when a student is genuinely taking a productive break and provides personalized, encouraging feedback rather than harsh restrictions (but can enforce restrictions when needed). Big Daddy has the potential to alleviate parent load while ensuring children are gaining value from their device use instead of rotting their brain away. The potential positive social impact is enormous.

### What it does

Big Daddy allows students to access the web in the Big Daddy Browser (based on Firefox) while it watches their face and screen. Using GPT4o, it analyzes screenshots of their screen, and using DeepFace's emotion detector, it determines the student's emotional state. It gives live feedback to the students through notifications and by talking to the student with LMNT's voice API, and if necessary, will take control of the browser to make sure students are on appropriate activities given their emotional state and the educational / entertainment level of the activity they are doing. Big Daddy can also give positive feedback when students are doing well on their homework, or can give encouragement and recommend break activities if students are getting frustrated. Big Daddy also has content restrictions for strictly bad content, like violent or sexual websites and will redirect students away from them. Additionally, after a session with Big Daddy enabled, Big Daddy will generate a PDF report for the parent to read through to understand exactly what their children has been up to. Using all the log data it collected, Gemini 2.5 Pro will generate a comprehensive report of child activities.

### Challenges we ran into

Big Daddy uses Selenium Webdriver to control the browser. However, we found that selenium is very slow with chromium based browsers, so we pivoted to Firefox. We had trouble getting the emotion recognition to not have spurious emotions, so we wrote an algorithm to smooth the emotion outputs from the model over time. Getting the agent to work reliably was originally frustrating, but after making the agentic process multi-step and enforcing restrictions in each step, we got better results. For example, we have the LLM generate educational and entertainment scores before it continuous its analysis. Additionally, there are only a fixed amount of actions it can choose from, and it considers how long a student has spent on an activity.

### Accomplishments we're proud of

We are proud of making a functional big daddy in one day!

### What's next

We want to bring Big Daddy to the iPad, as this is where our target audience is. However, our current solution works in schools that use Chromebooks or similar devices, which are very popular in education.

## README (from the GitHub repository)

# 🎓 Smart Student Monitoring System

An AI-powered browser monitoring system that uses **computer vision** and **intelligent analysis** to help students stay focused on their studies. The system analyzes screenshots, browsing patterns, and context to make smart decisions about when and how to intervene.

## 🚀 NEW AI-Enhanced Features

### 🧠 Smart AI Agent
- **Computer Vision Analysis**: AI analyzes screenshots to understand content and student activity
- **Intelligent Decision Making**: Context-aware decisions using GPT-4 Vision
- **Dynamic Timeouts**: AI determines optimal timing for interventions (5-300 seconds)
- **Contextual Messages**: Personalized, age-appropriate messages based on analysis
- **Pattern Recognition**: Learns from browsing history and behavior patterns
- **Progress Reports**: AI-generated summaries of study sessions

### 📸 Screenshot Analysis
The AI analyzes each screenshot to determine:
- **Content Type**: Educational, entertainment, social media, inappropriate, etc.
- **Educational Value**: Scored 0-10 for learning relevance
- **Distraction Level**: Scored 0-10 for how off-task the content is
- **Activity Description**: What the student appears to be doing
- **Focus Indicators**: Signs of concentrated work vs casual browsing

### 🎯 Three-State Decision System
1. **ENCOURAGE** 🎉: Positive reinforcement for good study habits
2. **WARN** ⚠️: Gentle reminders when getting distracted
3. **INTERVENE** 🚨: Redirect to educational content when needed

## 📋 Quick Start

### 1. Install Dependencies
```bash
pip install -r requirements.txt
```

### 2. Set OpenAI API Key
```bash
export OPENAI_API_KEY="your-api-key-here"
```

### 3. Run the Smart Monitoring System
```bash
# Full monitoring with AI analysis
python student_monitor.py

# Test AI analysis on recent activity
python student_monitor.py --test

# Custom intervals
python student_monitor.py --browser-interval 3 --ai-interval 10
```

## 🛠️ Advanced Usage

### Individual Components

#### Smart AI Agent (Standalone)
```bash
# Test mode - analyze recent logs
python ai_agent.py --test

# Continuous monitoring
python ai_agent.py --interval 15
```

#### Browser Monitor (Standalone)
```bash
# Basic monitoring
python browser_monitor_fixed.py

# Custom settings
python browser_monitor_fixed.py --interval 3 --url https://www.khanacademy.org
```

### Command Line Options

#### Student Monitor
```bash
python student_monitor.py [OPTIONS]

Options:
  --headless              Run browser in headless mode
  --api-key KEY          OpenAI API key
  --browser-interval N   Browser monitoring interval (default: 5s)
  --ai-interval N        AI analysis interval (default: 15s)
  --test                 Run AI test analysis only
```

#### AI Agent
```bash
python ai_agent.py [OPTIONS]

Options:
  --api-key KEY          OpenAI API key
  --interval N           Analysis interval (default: 10s)
  --test                 Analyze recent logs only
```

## 🔍 How It Works

### 1. Browser Monitoring
- Captures screenshots every 5 seconds
- Logs URL, title, search queries, and page content
- Tracks navigation and tab management
- Handles context recovery for stability

### 2. AI Analysis Pipeline
```
Screenshot → Computer Vision → Pattern Analysis → Decision Making → Action
     ↓              ↓               ↓              ↓           ↓
  Base64 Encode → GPT-4 Vision → Browsing History → Context AI → Intervention
```

### 3. Intelligent Decision Process
The AI considers:
- **Current Content**: What's on screen right now
- **Time on Site**: How long student has been on current page
- **Browsing Patterns**: Recent navigation behavior
- **Focus Score**: Calculated from site switches and content types
- **Educational Ratio**: Proportion of educational vs distracting content
- **Previous Interventions**: Avoids being too pushy

### 4. Dynamic Actions
- **Smart Timeouts**: AI determines wait times based on urgency
- **Contextual Messages**: Personalized based on student's activity
- **Educational Alternatives**: AI suggests relevant learning resources
- **Progressive Intervention**: Escalates from encouragement to redirection

## 📊 Data Collection

### Browser Activity (`logs.csv`)
- Timestamp and URL
- Page title and screenshot path
- OCR text extraction
- Search queries and page content
- Tab count and navigation events

### AI Analysis (`ai_analysis.csv`)
- AI decisions and reasoning
- Screenshot analysis results
- Browsing pattern metrics
- Timeout and urgency levels
- Intervention success rates

## 🎨 AI Analysis Examples

### Screenshot Analysis Output
```json
{
  "content_type": "educational",
  "educational_value": 9,
  "distraction_level": 1,
  "description": "Student working on Khan Academy math problems",
  "specific_activity": "solving algebra equations",
  "focus_indicators": "concentrated work pattern"
}
```

### Pattern Analysis Output
```json
{
  "pattern": "focused_study",
  "trend": "improving",
  "focus_score": 8.5,
  "educational_ratio": 0.85,
  "site_switches": 2,
  "unique_sites": 3
}
```

### AI Decision Output
```json
{
  "recommendation": "encourage",
  "timeout": 120,
  "message": "Excellent work on those math problems! You've been focused for 15 minutes.",
  "reasoning": "High educational value and sustained focus detected",
  "urgency": "low"
}
```

## 🔧 Configuration

### Monitoring Intervals
- **Browser Monitoring**: 3-10 seconds (default: 5s)
- **AI Analysis**: 10-30 seconds (default: 15s)
- **Screenshot Capture**: Every browser log event
- **Pattern Analysis**: Rolling 10-minute window

### AI Model Settings
- **Vision Model**: GPT-4 Vision Preview
- **Text Model**: GPT-3.5 Turbo (fallback)
- **Temperature**: 0.7 (balanced creativity/consistency)
- **Max Tokens**: 1000 per analysis

### Timeout Ranges
- **Encourage**: 30-300 seconds
- **Warn**: 10-120 seconds
- **Intervene**: 5-30 seconds (immediate for inappropriate content)

## 🛡️ Safety Features

### Content Filtering
- Real-time inappropriate content detection
- Immediate intervention for harmful material
- Age-appropriate messaging and alternatives
- Comprehensive keyword filtering

### Privacy Protection
- Local data storage only
- Optional headless mode
- No data transmitted except to OpenAI API
- Screenshots stored locally with automatic cleanup

### Error Handling
- Graceful browser context recovery
- Fallback decision making if AI fails
- Automatic retry mechanisms
- Comprehensive error logging

## 🎯 Use Cases

### For Students
- **Study Session Monitoring**: Stay focused during homework time
- **Distraction Management**: Gentle reminders to get back on track
- **Learning Reinforcement**: Positive feedback for good study habits
- **Progress Tracking**: AI-generated study session reports

### For Parents/Educators
- **Activity Oversight**: Monitor student computer usage
- **Learning Analytics**: Understand study patterns and effectiveness
- **Intervention Logs**: Review when and why interventions occurred
- **Progress Reports**: AI-generated summaries of student focus

### For Researchers
- **Behavior Analysis**: Study patterns in student computer usage
- **AI Decision Making**: Research intelligent tutoring systems
- **Computer Vision**: Analyze educational content recognition
- **Learning Analytics**: Understand digital learning behaviors

## 📈 Performance Metrics

### AI Accuracy
- **Content Classification**: ~90% accuracy on educational vs distracting content
- **Inappropriate Detection**: 99%+ accuracy with immediate intervention
- **Focus Assessment**: Correlates well with manual observation
- **Message Relevance**: Contextually appropriate 95%+ of the time

### System Performance
- **Browser Monitoring**: <1% CPU overhead
- **AI Analysis**: 2-5 seconds per analysis
- **Screenshot Processing**: 1-2 seconds average
- **Memory Usage**: <200MB typical

## 🔮 Future Enhancements

### Planned Features
- **Multi-Student Support**: Monitor multiple students simultaneously
- **Learning Objectives**: Align interventions with s

[README truncated for size]

## Detected evidence (automated analysis)

Indexed codebase: 17 recognized source files, 210 KB.
- LangChain (technology) — detected in the code
- OpenAI (technology) — detected in the code
- Python (language) — detected in the code
- TensorFlow (technology) — detected in the code
- Google Gemini (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (27 of 27)

```
.gitignore
agent_logs.csv
ai_agent.py
ai_analysis.csv
browser_launcher.py
browser_monitor_fixed.py
browser_monitor.py
config.py
debug_lmnt.py
emotion_detection/.gitignore
emotion_detection/debug_emotion_detector.py
emotion_detection/requirements.txt
emotionLog.txt
example_demo.py
example_usage.py
format.jsonl
generate_report.py
logs.csv
main_ui.py
parent_report.txt
README.md
report_logger.py
requirements.txt
setup_env.py
student_monitor.py
test_intervention_speech.py
test_speech.py
```

### Dependencies

- emotion_detection/requirements.txt: deepface@>=0.0.75, matplotlib@>=3.5.0, mediapipe@==0.10.13, numpy@>=1.21.0, opencv-python@>=4.8.0, Pillow@>=9.0.0, tensorflow@>=2.13.0
- requirements.txt: duckduckgo-search@==3.9.6, fpdf2@==2.7.8, google-genai@>=1.0.0, langchain@>=0.2.0, langchain-community@>=0.0.10, langchain-openai@>=0.1.0, lmnt@==0.1.0, Markdown@==3.6, numpy@==1.26.2, openai@>=1.3.7, pandas@==2.1.3, Pillow@==10.0.1, pytesseract@==0.3.10, python-dotenv@==1.0.0, requests@==2.31.0, selenium@==4.15.2, webdriver-manager@==4.0.1

### Recent commits (newest first)

- committing whatever is currently working
- Final changes for speed
- no env
- Adding final functionality changes
- Test commit
- Update generate_report.py
- Merge pull request #2 from whackamadoodle3000/cfitzmaurice6-patch-1
- Add files via upload
- Delete screen.py
- Delete cache.py
- Delete emotion.py
- Adding Colin changes
- Add files via upload
- Merge pull request #1 from whackamadoodle3000/colin-branch
- lol
- Adding emotion detection
- Update logs.csv
- Create screenshot_1750549715.png
- v1

## Key source files (fetched from GitHub, selected and truncated for size)

### requirements.txt

```
# Web browser automation
selenium==4.15.2
webdriver-manager==4.0.1

# Image processing and OCR
Pillow==10.0.1
pytesseract==0.3.10

# AI and Language Models
openai>=1.3.7
langchain>=0.2.0
langchain-openai>=0.1.0
langchain-community>=0.0.10
duckduckgo-search==3.9.6
google-genai>=1.0.0

# Data processing
pandas==2.1.3
numpy==1.26.2

# Speech synthesis
lmnt==0.1.0

# Utilities
python-dotenv==1.0.0
requests==2.31.0

# PDF Generation
fpdf2==2.7.8
Markdown==3.6

# Base64 encoding (built-in, but listing for reference)
# base64 - built into Python

# JSON handling (built-in)
# json - built into Python

# Threading and datetime (built-in)
# threading, datetime - built into Python 
```

### emotion_detection/requirements.txt

```
opencv-python>=4.8.0
mediapipe==0.10.13
tensorflow>=2.13.0
numpy>=1.21.0
Pillow>=9.0.0
matplotlib>=3.5.0
deepface>=0.0.75 
```

### config.py

```python
#!/usr/bin/env python3
"""
Configuration file for Smart Student Monitor
Loads settings from environment variables or provides defaults
"""

import os
from dotenv import load_dotenv

# Load environment variables from .env file if it exists
load_dotenv()

# OpenAI Configuration
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY", "")

# Gemini API Key for reporting
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY", "")

# LMNT Configuration (speech synthesis)
LMNT_API_KEY = os.getenv("LMNT_API_KEY", "ak_GkxGopYg9FwhJaQkJ9huMC")

# Monitoring Intervals
BROWSER_INTERVAL = int(os.getenv("BROWSER_INTERVAL", "5"))
AI_INTERVAL = int(os.getenv("AI_INTERVAL", "8"))

# Speech Configuration
SPEECH_ENABLED = os.getenv("SPEECH_ENABLED", "true").lower() == "true"
SPEECH_COOLDOWN = int(os.getenv("SPEECH_COOLDOWN", "120"))

# Browser Configuration
HEADLESS_MODE = os.getenv("HEADLESS_MODE", "false").lower() == "true"

# File Paths
SCREENSHOTS_DIR = "screenshots"
LOGS_FILE = "logs.csv"
AI_ANALYSIS_FILE = "ai_analysis.csv"

# AI Model Configuration
DEFAULT_MODEL = "gpt-4o"
FAST_MODEL = "gpt-3.5-turbo"
TEMPERATURE = 0.3
MAX_TOKENS = 500

def validate_config():
    """Validate that required configuration is present"""
    if not OPENAI_API_KEY:
        print("⚠️ Warning: OPENAI_API_KEY not set")
        print("   Create a .env file with your OpenAI API key:")
        print("   OPENAI_API_KEY=your-api-key-here")
        return False
    return True

def get_config_summary():
    """Get a summary of current configuration"""
    return {
        "openai_api_key": "Set" if OPENAI_API_KEY else "Not Set",
        "gemini_api_key": "Set" if GEMINI_API_KEY else "Not Set",
        "lmnt_api_key": "Set" if LMNT_API_KEY else "Using Default",
        "browser_interval": BROWSER_INTERVAL,
        "ai_interval": AI_INTERVAL,
        "speech_enabled": SPEECH_ENABLED,
        "headless_mode": HEADLESS_MODE
    }
```

### debug_lmnt.py

```python
#!/usr/bin/env python3
"""
Debug script to understand LMNT API response format
"""

import asyncio
import os
from lmnt.api import Speech

async def debug_lmnt():
    """Debug LMNT API response format"""
    try:
        print("🧪 Debugging LMNT API response format...")
        
        # Set API key
        api_key = os.getenv('LMNT_API_KEY') or "ak_GkxGopYg9FwhJaQkJ9huMC"
        
        async with Speech(api_key=api_key) as speech:
            synthesis = await speech.synthesize('Hello world.', 'leah')
            
            print(f"✅ Synthesis completed")
            print(f"📊 Synthesis type: {type(synthesis)}")
            print(f"📊 Synthesis keys: {synthesis.keys() if hasattr(synthesis, 'keys') else 'No keys'}")
            print(f"📊 Synthesis dir: {dir(synthesis)}")
            
            # Try different ways to access audio data
            if hasattr(synthesis, 'audio'):
                print(f"✅ Found synthesis.audio: {type(synthesis.audio)}")
                audio_data = synthesis.audio
            elif 'audio' in synthesis:
                print(f"✅ Found synthesis['audio']: {type(synthesis['audio'])}")
                audio_data = synthesis['audio']
            else:
                print(f"❌ Could not find audio data in synthesis")
                print(f"📊 Full synthesis object: {synthesis}")
                return
            
            print(f"✅ Audio data type: {type(audio_data)}")
            print(f"✅ Audio data length: {len(audio_data)} bytes")
            
            # Save test file
            with open('debug_test.mp3', 'wb') as f:
                f.write(audio_data)
            print("✅ Test audio saved as debug_test.mp3")
            
    except Exception as e:
        print(f"❌ Debug failed: {e}")
        import traceback
        traceback.print_exc()

if __name__ == "__main__":
    asyncio.run(debug_lmnt()) 
```

### example_usage.py

```python
#!/usr/bin/env python3
"""
Example usage of the BrowserLauncher class
"""

from browser_launcher import BrowserLauncher
import time

def example_chrome_usage():
    """Example of using Chrome browser"""
    print("=== Chrome Browser Example ===")
    launcher = BrowserLauncher()
    
    # Launch Chrome and open Google
    if launcher.launch_chrome(start_url="https://www.google.com"):
        print("Chrome launched successfully!")
        
        # Wait a bit
        time.sleep(3)
        
        # Navigate to another site
        launcher.navigate_to("https://www.github.com")
        print("Navigated to GitHub")
        
        # Keep the browser open for 10 seconds
        time.sleep(10)
        
        # Close the browser
        launcher.close_browser()
    else:
        print("Failed to launch Chrome")

def example_firefox_usage():
    """Example of using Firefox browser"""
    print("\n=== Firefox Browser Example ===")
    launcher = BrowserLauncher()
    
    # Launch Firefox and open YouTube
    if launcher.launch_firefox(start_url="https://www.youtube.com"):
        print("Firefox launched successfully!")
        
        # Keep the browser open for 15 seconds
        time.sleep(15)
        
        # Close the browser
        launcher.close_browser()
    else:
        print("Failed to launch Firefox")

def example_interactive_session():
    """Example of an interactive browser session"""
    print("\n=== Interactive Browser Session ===")
    launcher = BrowserLauncher()
    
    # Launch Chrome
    if launcher.launch_chrome(start_url="https://www.google.com"):
        print("Chrome launched! You can now interact with the browser.")
        print("The browser will stay open until you close it manually.")
        print("Or press Ctrl+C in this terminal to close the script.")
        
        # Keep the browser open indefinitely
        launcher.keep_alive()
    else:
        print("Failed to launch Chrome")

if __name__ == "__main__":
    print("Browser Launcher Examples")
    print("Choose an example to run:")
    print("1. Chrome example (auto-close after 10 seconds)")
    print("2. Firefox example (auto-close after 15 seconds)")
    print("3. Interactive Chrome session (keep open until manual close)")
    
    try:
        choice = input("Enter your choice (1-3): ").strip()
        
        if choice == "1":
            example_chrome_usage()
        elif choice == "2":
            example_firefox_usage()
        elif choice == "3":
            example_interactive_session()
        else:
            print("Invalid choice. Running Chrome example...")
            example_chrome_usage()
            
    except KeyboardInterrupt:
        print("\nExiting...")
    except Exception as e:
        print(f"Error: {e}") 
```

### test_speech.py

```python
#!/usr/bin/env python3
"""
Test script for speech synthesis and audio playback
"""

import asyncio
import sys
import os
from ai_agent import SmartStudentAIAgent

# Test LMNT SDK directly
try:
    from lmnt.api import Speech
    LMNT_AVAILABLE = True
except ImportError:
    LMNT_AVAILABLE = False

async def test_lmnt_direct():
    """Test LMNT SDK directly"""
    if not LMNT_AVAILABLE:
        print("⚠️ LMNT SDK not available for direct testing")
        return False
    
    try:
        print("🧪 Testing LMNT SDK directly...")
        
        # Set API key
        api_key = os.getenv('LMNT_API_KEY') or "ak_GkxGopYg9FwhJaQkJ9huMC"
        
        async with Speech(api_key=api_key) as speech:
            synthesis = await speech.synthesize('Hello! This is a direct LMNT test.', 'lily')
            
            # Handle different possible response formats
            if hasattr(synthesis, 'audio'):
                audio_data = synthesis.audio
            elif isinstance(synthesis, dict) and 'audio' in synthesis:
                audio_data = synthesis['audio']
            else:
                # Try to access as bytes directly
                audio_data = synthesis
            
            print(f"✅ Direct LMNT synthesis successful ({len(audio_data)} bytes)")
            
            # Save test file
            with open('lmnt_test.mp3', 'wb') as f:
                f.write(audio_data)
            print("✅ Test audio saved as lmnt_test.mp3")
            return True
            
    except Exception as e:
        print(f"❌ Direct LMNT test failed: {e}")
        return False

async def test_speech():
    """Test speech synthesis and playback"""
    print("🎤 Testing Speech Synthesis System...")
    
    try:
        # Initialize AI agent
        agent = SmartStudentAIAgent()
        
        # Test messages
        test_messages = [
            "Hello! This is a test of the speech system.",
            "Great job staying focused on your studies!",
            "Let's get back to productive learning activities."
        ]
        
        for i, message in enumerate(test_messages, 1):
            print(f"\n🗣️ Test {i}: {message}")
            
            # Test synthesis
            audio_data = await agent.synthesize_speech(message)
            if audio_data:
                print(f"✅ Speech synthesized successfully ({len(audio_data)} bytes)")
                
                # Test playback
                success = agent.play_speech(audio_data)
                if success:
                    print("✅ Audio playback successful")
                else:
                    print("❌ Audio playback failed")
            else:
                print("❌ Speech synthesis failed")
            
            # Wait between tests
            if i < len(test_messages):
                print("⏳ Waiting 2 seconds...")
                await asyncio.sleep(2)
        
        print("\n🎉 Speech test completed!")
        
    except Exception as e:
        print(f"❌ Test error: {e}")

def main():
    """Main test function"""
    print("🧪 Speech System Test")
    print("=" * 30)
    
    # Check if API key is available
    if not os.getenv("OPENAI_API_KEY"):
        print("⚠️ Warning: No OpenAI API key found")
        print("Speech synthesis will use fallback methods only")
    
    async def run_all_tests():
        # Test LMNT directly first
        await test_lmnt_direct()
        print("\n" + "="*30 + "\n")
        
        # Test through AI agent
        await test_speech()
    
    # Run async tests
    asyncio.run(run_all_tests())

if __name__ == "__main__":
    main() 
```

### setup_env.py

```python
#!/usr/bin/env python3
"""
Setup script for Smart Student Monitor
Helps users create their .env file with API keys
"""

import os
import sys

def create_env_file():
    """Create a .env file with user input"""
    print("🎓 Smart Student Monitor - Environment Setup")
    print("=" * 50)
    
    # Check if .env already exists
    if os.path.exists('.env'):
        print("⚠️ .env file already exists!")
        response = input("Do you want to overwrite it? (y/N): ").lower()
        if response != 'y':
            print("Setup cancelled.")
            return
    
    print("\n📝 Let's set up your configuration:")
    
    # Get OpenAI API key
    print("\n🔑 OpenAI API Key:")
    print("   Get your API key from: https://platform.openai.com/api-keys")
    openai_key = input("   Enter your OpenAI API key: ").strip()
    
    if not openai_key:
        print("❌ OpenAI API key is required!")
        return
    
    # Get LMNT API key (optional)
    print("\n🗣️ LMNT API Key (optional):")
    print("   Get your API key from: https://lmnt.com/")
    print("   Leave blank to use default")
    lmnt_key = input("   Enter your LMNT API key: ").strip()
    
    # Get monitoring intervals
    print("\n⏱️ Monitoring Intervals:")
    browser_interval = input("   Browser monitoring interval (default: 5): ").strip() or "5"
    ai_interval = input("   AI analysis interval (default: 15): ").strip() or "15"
    
    # Get other settings
    print("\n⚙️ Other Settings:")
    speech_enabled = input("   Enable speech feedback? (Y/n): ").lower() != 'n'
    headless_mode = input("   Run in headless mode? (y/N): ").lower() == 'y'
    
    # Create .env content
    env_content = f"""# OpenAI API Configuration
OPENAI_API_KEY={openai_key}

# LMNT API Configuration (optional - uses default if not set)
LMNT_API_KEY={lmnt_key or "ak_GkxGopYg9FwhJaQkJ9huMC"}

# Monitoring Configuration
BROWSER_INTERVAL={browser_interval}
AI_INTERVAL={ai_interval}

# Speech Configuration
SPEECH_ENABLED={'true' if speech_enabled else 'false'}
SPEECH_COOLDOWN=120

# Browser Configuration
HEADLESS_MODE={'true' if headless_mode else 'false'}
"""
    
    # Write .env file
    try:
        with open('.env', 'w') as f:
            f.write(env_content)
        
        print(f"\n✅ .env file created successfully!")
        print(f"📁 Location: {os.path.abspath('.env')}")
        
        # Test configuration
        print("\n🧪 Testing configuration...")
        try:
            from config import validate_config, get_config_summary
            if validate_config():
                print("✅ Configuration is valid!")
                print("\n📋 Current settings:")
                config_summary = get_config_summary()
                for key, value in config_summary.items():
                    print(f"   • {key}: {value}")
            else:
                print("❌ Configuration validation failed!")
        except Exception as e:
            print(f"⚠️ Could not validate configuration: {e}")
        
        print(f"\n🚀 You're ready to run the Smart Student Monitor!")
        print(f"   Run: python main_ui.py")
        print(f"   Or: python student_monitor.py")
        
    except Exception as e:
        print(f"❌ Error creating .env file: {e}")

def main():
    """Main function"""
    if len(sys.argv) > 1 and sys.argv[1] == '--help':
        print("Smart Student Monitor Environment Setup")
        print("Usage: python setup_env.py")
        print("\nThis script will help you create a .env file with your API keys and settings.")
        return
    
    create_env_file()

if __name__ == "__main__":
    main() 
```

### example_demo.py

```python
#!/usr/bin/env python3
"""
Example Demo - Student Monitoring System
Demonstrates how to use the browser monitor and AI agent
"""

import time
import threading
from browser_monitor import BrowserMonitor
from ai_agent import StudentAIAgent


def demo_basic_monitoring():
    """Demo basic browser monitoring"""
    print("=== Basic Browser Monitoring Demo ===")
    
    monitor = BrowserMonitor(headless=False)
    
    try:
        # Launch browser
        if monitor.launch_firefox(start_url="https://www.google.com"):
            print("Browser launched! You can now browse normally.")
            print("The system will log your activity every 5 seconds.")
            print("Press Ctrl+C to stop.")
            
            # Start monitoring
            monitor.start_monitoring(interval=5)
            
    except KeyboardInterrupt:
        print("\nDemo stopped by user.")
    finally:
        monitor.close_browser()


def demo_ai_agent():
    """Demo AI agent functionality"""
    print("\n=== AI Agent Demo ===")
    print("Note: This demo requires OpenAI API key.")
    print("Set OPENAI_API_KEY environment variable or pass --api-key")
    
    try:
        agent = StudentAIAgent()
        
        # Simulate some activity analysis
        print("AI Agent initialized successfully!")
        print("The agent will analyze browser activity and take appropriate actions.")
        print("Press Ctrl+C to stop.")
        
        agent.run_agent_loop(interval=30)
        
    except Exception as e:
        print(f"Error: {e}")
        print("Make sure you have set the OPENAI_API_KEY environment variable.")


def demo_combined_system():
    """Demo the combined monitoring and AI agent system"""
    print("\n=== Combined System Demo ===")
    print("This runs both browser monitoring and AI agent together.")
    print("Note: Requires OpenAI API key.")
    
    try:
        from student_monitor import StudentMonitor
        
        monitor = StudentMonitor(headless=False)
        
        print("Starting combined system...")
        monitor.start_monitoring(
            start_url="https://www.google.com",
            monitor_interval=5,
            agent_interval=30
        )
        
    except Exception as e:
        print(f"Error: {e}")
        print("Make sure you have set the OPENAI_API_KEY environment variable.")


def demo_browser_controls():
    """Demo browser control functions"""
    print("\n=== Browser Controls Demo ===")
    
    monitor = BrowserMonitor(headless=False)
    
    try:
        if monitor.launch_firefox(start_url="https://www.google.com"):
            print("Browser launched! Demonstrating controls...")
            
            # Wait a bit
            time.sleep(3)
            
            # Show notification
            monitor.show_notification("Hello! This is a test notification.", duration=5)
            time.sleep(2)
            
            # Open new tab
            monitor.open_new_tab("https://www.github.com")
            time.sleep(3)
            
            # Show another notification
            monitor.show_notification("Opened GitHub in new tab!", duration=5)
            time.sleep(3)
            
            # Close current tab
            monitor.close_current_tab()
            time.sleep(2)
            
            # Show final notification
            monitor.show_notification("Demo completed! Browser will close in 5 seconds.", duration=5)
            time.sleep(5)
            
    except KeyboardInterrupt:
        print("\nDemo stopped by user.")
    finally:
        monitor.close_browser()


def main():
    print("Student Monitoring System - Demo")
    print("Choose a demo to run:")
    print("1. Basic browser monitoring")
    print("2. AI agent (requires OpenAI API key)")
    print("3. Combined system (requires OpenAI API key)")
    print("4. Browser controls demo")
    print("5. Exit")
    
    try:
        choice = input("\nEnter your choice (1-5): ").strip()
        
        if choice == "1":
            demo_basic_monitoring()
        elif choice == "2":
            demo_ai_agent()
        elif choice == "3":
            demo_combined_system()
        elif choice == "4":
            demo_browser_controls()
        elif choice == "5":
            print("Exiting...")
        else:
            print("Invalid choice. Running basic monitoring demo...")
            demo_basic_monitoring()
            
    except KeyboardInterrupt:
        print("\nExiting...")
    except Exception as e:
        print(f"Error: {e}")


if __name__ == "__main__":
    main() 
```

### test_intervention_speech.py

```python
#!/usr/bin/env python3
"""
Test script for intervention speech feedback
Demonstrates how the AI speaks when performing serious interventions
"""

import asyncio
import sys
import os
from ai_agent import SmartStudentAIAgent

async def test_intervention_speech():
    """Test speech feedback for different types of interventions"""
    print("🎤 Testing Intervention Speech Feedback...")
    
    try:
        # Initialize AI agent
        agent = SmartStudentAIAgent()
        
        # Test scenarios with different urgency levels
        test_scenarios = [
            {
                "name": "🚨 High Urgency - Inappropriate Content",
                "analysis": {
                    'recommendation': 'intervene',
                    'current_url': 'https://tinder.com',
                    'time_on_site': 120,
                    'message': 'Inappropriate content detected. Redirecting to educational resources.',
                    'reasoning': 'inappropriate domain "tinder.com" detected',
                    'urgency': 'high',
                    'pattern_analysis': {'focus_score': 3}
                }
            },
            {
                "name": "⚠️ Medium Urgency - Long Distraction",
                "analysis": {
                    'recommendation': 'intervene',
                    'current_url': 'https://youtube.com/watch?v=funny_video',
                    'time_on_site': 450,  # 7.5 minutes
                    'message': 'Extended time on distracting content. Redirecting to educational resources.',
                    'reasoning': 'Extended time on distracting site',
                    'urgency': 'medium',
                    'pattern_analysis': {'focus_score': 4}
                }
            },
            {
                "name": "🎉 Encouragement - Educational Content",
                "analysis": {
                    'recommendation': 'encourage',
                    'current_url': 'https://khanacademy.org/math',
                    'time_on_site': 300,
                    'message': 'Great job staying focused on your studies!',
                    'reasoning': 'Educational site detected',
                    'urgency': 'low',
                    'pattern_analysis': {'focus_score': 8}
                }
            }
        ]
        
        for i, scenario in enumerate(test_scenarios, 1):
            print(f"\n{'='*50}")
            print(f"🧪 Test {i}: {scenario['name']}")
            print(f"{'='*50}")
            
            analysis = scenario['analysis']
            
            # Show scenario details
            print(f"📍 URL: {analysis['current_url']}")
            print(f"⏱️ Time on site: {analysis['time_on_site']/60:.1f} minutes")
            print(f"🎯 Recommendation: {analysis['recommendation']}")
            print(f"⚡ Urgency: {analysis['urgency']}")
            print(f"🔍 Reasoning: {analysis['reasoning']}")
            
            # Test if speech should be given
            should_speak = agent.should_give_speech_feedback(analysis)
            print(f"🗣️ Should give speech: {'YES' if should_speak else 'NO'}")
            
            if should_speak:
                # Generate speech message
                speech_message = agent.generate_speech_message(analysis)
                print(f"💬 Generated speech: \"{speech_message}\"")
                
                # Test speech synthesis (but don't play to avoid spam)
                print("🎤 Testing speech synthesis...")
                audio_data = await agent.synthesize_speech(speech_message)
                if audio_data:
                    print(f"✅ Speech synthesized successfully ({len(audio_data)} bytes)")
                else:
                    print("❌ Speech synthesis failed")
            
            # Wait between tests
            if i < len(test_scenarios):
                print("\n⏳ Waiting 3 seconds before next test...")
                await asyncio.sleep(3)
        
        print(f"\n🎉 All intervention speech tests completed!")
        print(f"\n💡 Key Features Demonstrated:")
        print(f"• 🚨 High urgency interventions ALWAYS get speech feedback")
        print(f"• 💬 AI generates contextual, caring messages")
        print(f"• 🎯 Different message styles for different intervention types")
        print(f"• 🗣️ Explains the reasoning and suggests alternatives")
        
    except Exception as e:
        print(f"❌ Test error: {e}")

def main():
    """Main test function"""
    print("🧪 Intervention Speech Feedback Test")
    print("=" * 40)
    print("This test demonstrates how the AI provides")
    print("detailed speech feedback for interventions,")
    print("especially serious ones involving inappropriate content.")
    print()
    
    # Run async test
    asyncio.run(test_intervention_speech())

if __name__ == "__main__":
    main() 
```

### report_logger.py

```python
# import time, base64, json
# from datetime import datetime, timezone
# # call into existing tools:
# from cache import langchain_cache
# from screen import capture_screenshot
# from emotion import get_latest_emotion

# LOG_PATH = "format.jsonl"
# INTERVAL_SECONDS = 86400  # change to whatever sec

# def log_snapshot():
#     ts = datetime.now(timezone.utc).isoformat()
#     events = langchain_cache.load_memory_variables({})
#     img_bytes = capture_screenshot()
#     img_b64   = base64.b64encode(img_bytes).decode("utf-8")
#     emo_data  = get_latest_emotion()
#     record = {
#         "timestamp":   ts,
#         "chain_events": events,
#         "screenshot":  img_b64,
#         "emotion":     emo_data
#     }
#     with open(LOG_PATH, "a") as f:
#         f.write(json.dumps(record) + "\n")
#     print(f"[{ts}] logged.")

# if __name__ == "__main__":
#     log_snapshot()           # do one immediately
#     while True:
#         time.sleep(INTERVAL_SECONDS)
#         log_snapshot()

# import time
# import base64
# import json
# import os
# from datetime import datetime, timezone
# from cache import langchain_cache
# from screen import capture_screenshot
# from emotion import get_latest_emotion

# # Path to append snapshots
# LOG_PATH = os.getenv("LOG_PATH", "format.jsonl")
# # Interval between snapshots (seconds)
# INTERVAL_SECONDS = int(os.getenv("INTERVAL_SECONDS", 86400))

# def log_snapshot():
#     ts = datetime.now(timezone.utc).replace(microsecond=0).isoformat() + "Z"
#     # langchain_cache.load_memory_variables returns a dict, often with 'history'
#     mem = langchain_cache.load_memory_variables({})
#     events = mem.get("history", []) if isinstance(mem, dict) else []
#     img_b64 = base64.b64encode(capture_screenshot()).decode("utf-8")
#     emo_data = get_latest_emotion()

#     record = {
#         "timestamp":    ts,
#         "chain_events": events,
#         "screenshot":   img_b64,
#         "emotion":      emo_data
#     }

#     # Ensure log file exists\ n    os.makedirs(os.path.dirname(LOG_PATH) or ".", exist_ok=True)
#     with open(LOG_PATH, "a", encoding="utf-8") as f:
#         f.write(json.dumps(record) + "\n")

#     print(f"[{ts}] Logged snapshot to {LOG_PATH}")

# if __name__ == "__main__":
#     try:
#         log_snapshot()  # initial run
#         while True:
#             time.sleep(INTERVAL_SECONDS)
#             log_snapshot()
#     except KeyboardInterrupt:
#         print("Shutting down logger.")

import csv
import json
import os
import glob
from datetime import datetime

AGENT_LOGS    = "agent_logs.csv"
EMOTION_LOG   = "emotionLog.txt"
SCREENSHOT_DIR= "screenshots"
OUTPUT_JSONL  = "format.jsonl"
KEYS = ["angry", "disgust", "fear", "happy", "sad", "surprise", "neutral"]

def load_emotions():
    """
    Parse emotionLog.txt, return a dict mapping datetime → {emotion: value, …}
    """
    emo_map = {}
    with open(EMOTION_LOG, encoding="utf-8") as f:
        for line in f:
            line = line.strip()
            if not line:
                continue
            parts = line.split()
            # first two tokens are date and time
            ts_str = " ".join(parts[:2])
            dt = datetime.strptime(ts_str, "%Y-%m-%d %H:%M:%S")
            # remaining tokens are k:v
            emo = {k: 0.0 for k in KEYS}
            for kv in parts[2:]:
                if ":" not in kv:
                    continue
                k, v = kv.split(":", 1)
                try:
                    emo[k] = float(v)
                except ValueError:
                    pass
            emo_map[dt] = emo
    return emo_map

def find_screenshot(dt: datetime) -> str | None:
    """
    Given a datetime, look for screenshots/screenshot_<epoch>.png
    Fallback to any file with that epoch prefix.
    """
    epoch = int(dt.timestamp())
    base = f"screenshot_{epoch}.png"
    path = os.path.join(SCREENSHOT_DIR, base)
    if os.path.exists(path):
        return base
    # fallback: any file starting with screenshot_<epoch>
    matches = glob.glob(os.path.join(SCREENSHOT_DIR, f"screenshot_{epoch}*.png"))
    if matches:
        return os.path.basename(matches[0])
    return None

def build_jsonl():
    emotions = load_emotions()
    # open CSV and JSONL
    with open(AGENT_LOGS, newline="", encoding="utf-8") as csvf, \
         open(OUTPUT_JSONL, "w", encoding="utf-8") as out:

        reader = csv.DictReader(csvf)
        for row in reader:
            dt = datetime.strptime(row["timestamp"], "%Y-%m-%d %H:%M:%S")
            
            emo = emotions.get(dt, {})

            # find the screenshot filename
            shot = find_screenshot(dt)

            # build one JSON object per line, in the same order as your CSV
            record = {
                "timestamp":          row["timestamp"],
                "current_url":        row.get("current_url", ""),
                "site_category":      row.get("site_category", ""),
                "time_on_site":       float(row.get("time_on_site", 0) or 0),
                "recommendation":     row.get("recommendation", ""),
                "message":            row.get("message", ""),
                "encouragement_count":int(row.get("encouragement_count", 0) or 0),
                "warning_count":      int(row.get("warning_count", 0) or 0),
                "intervention_count": int(row.get("intervention_count", 0) or 0),
                "screenshot":         shot,
                "emotion":            emo
            }

            out.write(json.dumps(record) + "\n")
            print(f"Wrote JSONL for {row['timestamp']} → screenshot={shot}, emotion_keys={list(emo)}")

if __name__ == "__main__":
    os.makedirs(SCREENSHOT_DIR, exist_ok=True)
    build_jsonl()
```

[7 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]