diff --git a/auto-analyst-backend/Dockerfile b/auto-analyst-backend/Dockerfile index 480e44ca..d373f797 100644 --- a/auto-analyst-backend/Dockerfile +++ b/auto-analyst-backend/Dockerfile @@ -10,4 +10,11 @@ COPY --chown=user ./requirements.txt requirements.txt RUN pip install --no-cache-dir --upgrade -r requirements.txt COPY --chown=user . /app -CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"] \ No newline at end of file + +# Make entrypoint script executable +USER root +RUN chmod +x /app/entrypoint.sh +USER user + +# Use the entrypoint script instead of directly running uvicorn +CMD ["/app/entrypoint.sh"] \ No newline at end of file diff --git a/auto-analyst-backend/Housing.xlsx b/auto-analyst-backend/Housing.xlsx deleted file mode 100644 index 86b99de3..00000000 Binary files a/auto-analyst-backend/Housing.xlsx and /dev/null differ diff --git a/auto-analyst-backend/chat_database.db b/auto-analyst-backend/chat_database.db index 022a896b..f991a3aa 100644 --- a/auto-analyst-backend/chat_database.db +++ b/auto-analyst-backend/chat_database.db @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b74d10d11586da55532cda065ffa649d4cde09dbf9874c90ac275f1921d685da -size 110592 +oid sha256:576d57c765fb2c0c432f9381bcf1c4abfd679be4bb986453757b253ec053cc0a +size 69632 diff --git a/auto-analyst-backend/cleaned_property_data.csv b/auto-analyst-backend/cleaned_property_data.csv deleted file mode 100644 index 494c9709..00000000 --- a/auto-analyst-backend/cleaned_property_data.csv +++ /dev/null @@ -1,3 +0,0 @@ -price,area,bedrooms,bathrooms,stories,mainroad,guestroom,basement,hotwaterheating,airconditioning,parking,prefarea,furnishingstatus_semi-furnished,normalized_price,normalized_area -13300000,7420,4,2,3,1,1,0,0,1,2,0,True,0.7071067811865476,-0.7071067811865476 -12250000,8960,4,4,4,1,0,1,1,1,3,1,False,-0.7071067811865476,0.7071067811865476 diff --git a/auto-analyst-backend/entrypoint.sh b/auto-analyst-backend/entrypoint.sh new file mode 100644 index 00000000..8e82044f --- /dev/null +++ b/auto-analyst-backend/entrypoint.sh @@ -0,0 +1,89 @@ +#!/bin/bash + +# Entrypoint script for Auto-Analyst backend +# This script safely initializes the database and starts the application +# SAFE for PostgreSQL/RDS - only modifies SQLite databases + +set -e # Exit on any error + +echo "๐Ÿš€ Starting Auto-Analyst Backend..." + +# Function to run safe database initialization +init_production_database() { + echo "๐Ÿ”ง Running SAFE database initialization..." + + # Run the safe initialization script + python scripts/init_production_db.py + + # Don't fail if database initialization has issues - let app try to start + if [ $? -eq 0 ]; then + echo "โœ… Database initialization completed successfully" + else + echo "โš ๏ธ Database initialization had issues, but continuing..." + echo "๐Ÿ“‹ App will start but some features may not work properly" + fi +} + +# Function to verify basic app imports work +verify_app_imports() { + echo "๐Ÿ” Verifying application imports..." + python -c " +try: + from app import app + print('โœ… Main application imports successful') +except Exception as e: + print(f'โŒ Application import failed: {e}') + exit(1) +" || { + echo "โŒ Critical application import failure - cannot start" + exit 1 +} +} + +# Function to verify database connectivity (non-failing) +verify_database_connectivity() { + echo "๐Ÿ”— Testing database connectivity..." + python -c " +try: + from src.db.init_db import get_session, is_postgres_db + from src.db.schemas.models import AgentTemplate + + db_type = 'PostgreSQL/RDS' if is_postgres_db() else 'SQLite' + print(f'๐Ÿ—„๏ธ Database type: {db_type}') + + session = get_session() + + # Try to query templates if table exists + try: + template_count = session.query(AgentTemplate).count() + print(f'โœ… Database connected. Found {template_count} templates.') + except Exception as table_error: + print(f'โš ๏ธ Database connected but template table issue: {table_error}') + print('๐Ÿ“‹ Template functionality may not work') + finally: + session.close() + +except Exception as e: + print(f'โš ๏ธ Database connectivity issue: {e}') + print('๐Ÿ“‹ App will start but database features may not work') +" + # Don't exit on database connectivity issues - let app try to start +} + +# Main startup sequence +echo "๐Ÿ”ง Initializing production environment..." + +# Verify critical imports first +verify_app_imports + +# Initialize database safely (won't modify RDS) +init_production_database + +# Test database connectivity (non-failing) +verify_database_connectivity + +echo "๐ŸŽฏ Starting FastAPI application..." +echo "๐ŸŒ Application will be available on port 7860" + +# Start the FastAPI application +exec uvicorn app:app --host 0.0.0.0 --port 7860 \ No newline at end of file diff --git a/auto-analyst-backend/property_price_vs_area.png b/auto-analyst-backend/property_price_vs_area.png deleted file mode 100644 index c0188730..00000000 --- a/auto-analyst-backend/property_price_vs_area.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:14c495d58d3fddbe3e6623dbcd569a3b96c467a57b9ac98a3d4e22439abb153d -size 427665 diff --git a/auto-analyst-backend/scripts/init_production_db.py b/auto-analyst-backend/scripts/init_production_db.py new file mode 100644 index 00000000..04cf0912 --- /dev/null +++ b/auto-analyst-backend/scripts/init_production_db.py @@ -0,0 +1,191 @@ +#!/usr/bin/env python3 +""" +Production database initialization script. +This ensures templates are populated properly and verifies database health. +SAFE for PostgreSQL/RDS - only creates tables on SQLite databases. +""" + +import sys +import os +import logging +from datetime import datetime, UTC + +# Add the project root to the Python path +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +from src.db.init_db import init_db, session_factory, engine, is_postgres_db +from src.db.schemas.models import Base, AgentTemplate, UserTemplatePreference +from scripts.populate_agent_templates import populate_templates +from sqlalchemy import inspect, text +from src.utils.logger import Logger + +logger = Logger("init_production_db", see_time=True, console_log=True) + +def get_database_type(): + """Get the database type (sqlite or postgresql).""" + try: + if is_postgres_db(): + return "postgresql" + else: + return "sqlite" + except Exception as e: + logger.log_message(f"Error determining database type: {e}", logging.ERROR) + return "unknown" + +def check_table_exists(table_name: str) -> bool: + """Check if a table exists in the database.""" + try: + inspector = inspect(engine) + tables = inspector.get_table_names() + return table_name in tables + except Exception as e: + logger.log_message(f"Error checking table existence: {e}", logging.ERROR) + return False + +def verify_database_schema(): + """Verify that all required tables exist. Only create tables on SQLite.""" + db_type = get_database_type() + logger.log_message(f"๐Ÿ” Verifying database schema for {db_type.upper()} database...", logging.INFO) + + required_tables = [ + 'users', 'chats', 'messages', 'model_usage', 'code_executions', + 'message_feedback', 'deep_analysis_reports', 'agent_templates', + 'user_template_preferences' + ] + + missing_tables = [] + existing_tables = [] + + for table in required_tables: + if not check_table_exists(table): + missing_tables.append(table) + logger.log_message(f"โŒ Missing table: {table}", logging.WARNING) + else: + existing_tables.append(table) + logger.log_message(f"โœ… Table exists: {table}", logging.INFO) + + if missing_tables: + if db_type == "sqlite": + logger.log_message(f"๐Ÿ”ง Creating missing tables on SQLite: {missing_tables}", logging.INFO) + try: + # Safe to create tables on SQLite + Base.metadata.create_all(engine) + logger.log_message("โœ… All tables created successfully on SQLite", logging.INFO) + except Exception as e: + logger.log_message(f"โŒ Failed to create tables: {e}", logging.ERROR) + raise + else: + # PostgreSQL/RDS - DO NOT create tables automatically + logger.log_message(f"โš ๏ธ WARNING: Missing tables detected in {db_type.upper()} database: {missing_tables}", logging.WARNING) + logger.log_message("๐Ÿ›ก๏ธ SAFETY: Not creating tables automatically on PostgreSQL/RDS", logging.INFO) + logger.log_message("๐Ÿ“‹ Please ensure these tables exist in your RDS database:", logging.INFO) + for table in missing_tables: + logger.log_message(f" - {table}", logging.INFO) + + # Continue without failing - the app might still work with existing tables + if 'agent_templates' in missing_tables or 'user_template_preferences' in missing_tables: + logger.log_message("โš ๏ธ Template functionality may not work without agent_templates and user_template_preferences tables", logging.WARNING) + else: + logger.log_message(f"โœ… All required tables exist in {db_type.upper()} database", logging.INFO) + +def verify_template_data(): + """Verify that agent templates are populated. Safe for all database types.""" + logger.log_message("๐Ÿ“‹ Verifying template data...", logging.INFO) + + session = session_factory() + try: + # Check if agent_templates table exists before querying + if not check_table_exists('agent_templates'): + logger.log_message("โš ๏ธ agent_templates table does not exist, skipping template verification", logging.WARNING) + return + + template_count = session.query(AgentTemplate).filter(AgentTemplate.is_active == True).count() + logger.log_message(f"๐Ÿ“Š Found {template_count} active templates", logging.INFO) + + if template_count == 0: + logger.log_message("๐Ÿ”ง No templates found, populating...", logging.INFO) + try: + populate_templates() + + # Verify population worked + new_count = session.query(AgentTemplate).filter(AgentTemplate.is_active == True).count() + logger.log_message(f"โœ… Templates populated. Total active templates: {new_count}", logging.INFO) + except Exception as e: + logger.log_message(f"โŒ Template population failed: {e}", logging.ERROR) + logger.log_message("โš ๏ธ App will continue but template functionality may not work", logging.WARNING) + else: + logger.log_message("โœ… Templates already populated", logging.INFO) + + except Exception as e: + logger.log_message(f"โŒ Error verifying templates: {e}", logging.ERROR) + logger.log_message("โš ๏ธ Template verification failed, but app will continue", logging.WARNING) + finally: + session.close() + +def test_template_api_functionality(): + """Test that template-related database operations work. Safe for all database types.""" + logger.log_message("๐Ÿงช Testing template API functionality...", logging.INFO) + + session = session_factory() + try: + # Check if agent_templates table exists before testing + if not check_table_exists('agent_templates'): + logger.log_message("โš ๏ธ agent_templates table does not exist, skipping API test", logging.WARNING) + return + + # Test basic template query + templates = session.query(AgentTemplate).filter(AgentTemplate.is_active == True).limit(5).all() + logger.log_message(f"โœ… Successfully queried {len(templates)} templates", logging.INFO) + + if templates: + sample_template = templates[0] + logger.log_message(f"๐Ÿ“„ Sample template: {sample_template.template_name} - {sample_template.display_name}", logging.INFO) + else: + logger.log_message("๐Ÿ“ญ No templates found in database", logging.INFO) + + except Exception as e: + logger.log_message(f"โŒ Template API test failed: {e}", logging.ERROR) + logger.log_message("โš ๏ธ Template API may not work properly", logging.WARNING) + finally: + session.close() + +def run_safe_initialization(): + """Run safe database initialization that respects production databases.""" + db_type = get_database_type() + logger.log_message(f"๐Ÿš€ Starting SAFE database initialization for {db_type.upper()}...", logging.INFO) + + if db_type == "postgresql": + logger.log_message("๐Ÿ›ก๏ธ PostgreSQL/RDS detected - running in SAFE mode", logging.INFO) + logger.log_message("๐Ÿ“‹ Will only verify schema and populate templates", logging.INFO) + elif db_type == "sqlite": + logger.log_message("๐Ÿ’ฝ SQLite detected - full initialization mode", logging.INFO) + + try: + # Step 1: Initialize database (safe for all types) + logger.log_message("Step 1: Basic database initialization", logging.INFO) + if db_type == "sqlite": + init_db() # Only run full init on SQLite + else: + logger.log_message("Skipping init_db() for PostgreSQL (safety)", logging.INFO) + + # Step 2: Verify schema (safe - only creates tables on SQLite) + logger.log_message("Step 2: Schema verification", logging.INFO) + verify_database_schema() + + # Step 3: Verify template data (safe for all types) + logger.log_message("Step 3: Template data verification", logging.INFO) + verify_template_data() + + # Step 4: Test functionality (safe for all types) + logger.log_message("Step 4: Functionality testing", logging.INFO) + test_template_api_functionality() + + logger.log_message(f"๐ŸŽ‰ Safe database initialization completed for {db_type.upper()}!", logging.INFO) + + except Exception as e: + logger.log_message(f"๐Ÿ’ฅ Database initialization failed: {e}", logging.ERROR) + logger.log_message("โš ๏ธ App may still start but some features might not work", logging.WARNING) + # Don't raise - let the app try to start anyway + +if __name__ == "__main__": + run_safe_initialization() \ No newline at end of file diff --git a/auto-analyst-frontend/components/custom-templates/TemplateCard.tsx b/auto-analyst-frontend/components/custom-templates/TemplateCard.tsx index e191b4b7..0b3e6b34 100644 --- a/auto-analyst-frontend/components/custom-templates/TemplateCard.tsx +++ b/auto-analyst-frontend/components/custom-templates/TemplateCard.tsx @@ -1,7 +1,6 @@ import React from 'react' import { motion } from 'framer-motion' -import { Sparkles, Lock, TrendingUp } from 'lucide-react' -import { Switch } from '../ui/switch' +import { Sparkles, Lock, TrendingUp, Check } from 'lucide-react' import { Badge } from '../ui/badge' import { TemplateAgent, TemplatePreference } from './types' @@ -24,9 +23,9 @@ export default function TemplateCard({ // Premium-only templates are only toggleable by premium users (hasAccess = true for premium) const canToggle = hasAccess - const handleToggle = (checked: boolean) => { + const handleClick = () => { if (canToggle) { - onToggleChange(template.template_id, checked) + onToggleChange(template.template_id, !isEnabled) } } @@ -106,15 +105,20 @@ export default function TemplateCard({ - {/* Toggle switch */} + {/* Checkmark selector */}
- + className={`w-6 h-6 rounded-md border-2 flex items-center justify-center transition-all duration-200 ${ + isEnabled + ? 'bg-[#FF7F7F] border-[#FF7F7F] text-white' + : 'border-gray-300 hover:border-[#FF7F7F] bg-white' + } ${!canToggle ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer hover:scale-105'}`} + > + {isEnabled && } +