AI Analysis and Content Strategy fixes. Enhanced Strategy Routes refactoring.

This commit is contained in:
ajaysi
2026-01-10 19:32:50 +05:30
parent 0b63ae7fc1
commit 8193cdba67
298 changed files with 45678 additions and 10952 deletions

View File

@@ -0,0 +1,106 @@
"""
Database Migration Script: Add actual_provider_name column to api_usage_logs table
This script adds the actual_provider_name column to track real providers
(WaveSpeed, Google, HuggingFace, etc.) instead of just generic enum values.
"""
import sys
import os
# Add parent directory to path - handle both direct execution and module import
script_dir = os.path.dirname(os.path.abspath(__file__))
parent_dir = os.path.dirname(script_dir)
if parent_dir not in sys.path:
sys.path.insert(0, parent_dir)
from sqlalchemy import text
from services.database import get_db
from loguru import logger
def add_actual_provider_name_column():
"""Add actual_provider_name column to api_usage_logs table if it doesn't exist."""
db = next(get_db())
try:
# Check if column already exists (SQLite compatible)
try:
result = db.execute(text("PRAGMA table_info(api_usage_logs)"))
columns = [row[1] for row in result.fetchall()]
column_exists = 'actual_provider_name' in columns
if column_exists:
logger.info("Column 'actual_provider_name' already exists in api_usage_logs table")
return
except Exception as e:
# If PRAGMA fails, try MySQL/PostgreSQL approach
try:
result = db.execute(text("""
SELECT COUNT(*) as count
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'api_usage_logs'
AND COLUMN_NAME = 'actual_provider_name'
"""))
column_exists = result.fetchone()[0] > 0
if column_exists:
logger.info("Column 'actual_provider_name' already exists in api_usage_logs table")
return
except:
# Column check failed, try to add anyway (will fail if exists)
pass
# Add the column
logger.info("Adding 'actual_provider_name' column to api_usage_logs table...")
try:
db.execute(text("""
ALTER TABLE api_usage_logs
ADD COLUMN actual_provider_name VARCHAR(50) NULL
"""))
db.commit()
logger.success("Successfully added 'actual_provider_name' column to api_usage_logs table")
except Exception as alter_error:
# Column might already exist, check again
if 'duplicate' in str(alter_error).lower() or 'already exists' in str(alter_error).lower():
logger.info("Column 'actual_provider_name' already exists (detected during ALTER)")
db.rollback()
return
raise
# Optionally, backfill existing records with detected provider names
logger.info("Backfilling existing records with detected provider names...")
from services.subscription.provider_detection import detect_actual_provider
from models.subscription_models import APIUsageLog, APIProvider
# Get all records without actual_provider_name
logs = db.query(APIUsageLog).filter(
APIUsageLog.actual_provider_name.is_(None)
).all()
updated_count = 0
for log in logs:
try:
actual_provider = detect_actual_provider(
provider_enum=log.provider,
model_name=log.model_used,
endpoint=log.endpoint
)
log.actual_provider_name = actual_provider
updated_count += 1
except Exception as e:
logger.warning(f"Failed to detect provider for log {log.id}: {e}")
db.commit()
logger.success(f"Backfilled {updated_count} existing records with actual provider names")
except Exception as e:
db.rollback()
logger.error(f"Error adding actual_provider_name column: {e}")
raise
finally:
db.close()
if __name__ == "__main__":
logger.info("Starting migration: Add actual_provider_name column")
add_actual_provider_name_column()
logger.info("Migration completed successfully")

View File

@@ -0,0 +1,148 @@
"""
Database Migration Script for Research Projects
Creates the research_projects table for cross-device project persistence.
"""
import sys
import os
from pathlib import Path
# Add the backend directory to Python path
backend_dir = Path(__file__).parent.parent
sys.path.insert(0, str(backend_dir))
from sqlalchemy import create_engine, text
from loguru import logger
import traceback
# Import models - ResearchProject uses SubscriptionBase
from models.subscription_models import Base as SubscriptionBase
from models.research_models import ResearchProject
from services.database import DATABASE_URL
def create_research_tables():
"""Create research-related tables."""
try:
# Create engine
engine = create_engine(DATABASE_URL, echo=False)
# Create all tables (ResearchProject uses SubscriptionBase, so it will be created)
logger.info("Creating research projects tables...")
SubscriptionBase.metadata.create_all(bind=engine)
logger.info("✅ Research tables created successfully")
# Verify table was created
display_setup_summary(engine)
except Exception as e:
logger.error(f"❌ Error creating research tables: {e}")
logger.error(traceback.format_exc())
raise
def display_setup_summary(engine):
"""Display a summary of the created tables."""
try:
with engine.connect() as conn:
logger.info("\n" + "="*60)
logger.info("RESEARCH PROJECTS SETUP SUMMARY")
logger.info("="*60)
# Check if table exists (SQLite)
check_query = text("""
SELECT name FROM sqlite_master
WHERE type='table' AND name='research_projects'
""")
result = conn.execute(check_query)
table_exists = result.fetchone()
if table_exists:
logger.info("✅ Table 'research_projects' created successfully")
# Get table schema
schema_query = text("""
SELECT sql FROM sqlite_master
WHERE type='table' AND name='research_projects'
""")
result = conn.execute(schema_query)
schema = result.fetchone()
if schema:
logger.info("\n📋 Table Schema:")
logger.info(schema[0])
# Check indexes
indexes_query = text("""
SELECT name FROM sqlite_master
WHERE type='index' AND tbl_name='research_projects'
""")
result = conn.execute(indexes_query)
indexes = result.fetchall()
if indexes:
logger.info(f"\n📊 Indexes ({len(indexes)}):")
for idx in indexes:
logger.info(f"{idx[0]}")
else:
logger.warning("⚠️ Table 'research_projects' not found after creation")
logger.info("\n" + "="*60)
logger.info("NEXT STEPS:")
logger.info("="*60)
logger.info("1. The research_projects table is ready for use")
logger.info("2. Projects will automatically save to database after intent analysis")
logger.info("3. Users can resume projects from any device")
logger.info("4. Use the 'My Projects' button to view saved projects")
logger.info("="*60)
except Exception as e:
logger.error(f"Error displaying summary: {e}")
def check_existing_table(engine):
"""Check if research_projects table already exists."""
try:
with engine.connect() as conn:
check_query = text("""
SELECT name FROM sqlite_master
WHERE type='table' AND name='research_projects'
""")
result = conn.execute(check_query)
table_exists = result.fetchone()
if table_exists:
logger.info(" Table 'research_projects' already exists")
logger.info(" Running migration will ensure schema is up to date...")
return True
return False
except Exception as e:
logger.error(f"Error checking existing table: {e}")
return False
if __name__ == "__main__":
logger.info("🚀 Starting research projects database migration...")
try:
# Create engine to check existing table
engine = create_engine(DATABASE_URL, echo=False)
# Check existing table
table_exists = check_existing_table(engine)
# Create tables (idempotent - won't recreate if exists)
create_research_tables()
logger.info("✅ Migration completed successfully!")
except KeyboardInterrupt:
logger.info("Migration cancelled by user")
sys.exit(0)
except Exception as e:
logger.error(f"❌ Migration failed: {e}")
traceback.print_exc()
sys.exit(1)

View File

@@ -134,7 +134,7 @@ def display_setup_summary(engine):
logger.info("NEXT STEPS:")
logger.info("="*60)
logger.info("1. Update your FastAPI app to include subscription routes:")
logger.info(" from api.subscription_api import router as subscription_router")
logger.info(" from api.subscription import router as subscription_router")
logger.info(" app.include_router(subscription_router)")
logger.info("\n2. Update database service to include subscription models:")
logger.info(" Add SubscriptionBase.metadata.create_all(bind=engine) to init_database()")

View File

@@ -0,0 +1,72 @@
"""
Update Basic Tier Limits and OSS Model Pricing
Updates existing subscription plans and pricing without recreating tables.
"""
import sys
import os
from pathlib import Path
# Add the backend directory to Python path
backend_dir = Path(__file__).parent.parent
sys.path.insert(0, str(backend_dir))
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from loguru import logger
import traceback
from services.database import DATABASE_URL
from services.subscription.pricing_service import PricingService
def update_pricing_and_plans():
"""Update pricing and plans without recreating tables."""
try:
# Create engine
engine = create_engine(DATABASE_URL, echo=False)
# Create session
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
db = SessionLocal()
try:
# Initialize pricing and plans (will update existing)
pricing_service = PricingService(db)
logger.info("🔄 Updating default API pricing (including OSS models)...")
pricing_service.initialize_default_pricing()
logger.info("✅ Default API pricing updated")
logger.info("🔄 Updating default subscription plans (Basic tier limits)...")
pricing_service.initialize_default_plans()
logger.info("✅ Default subscription plans updated")
logger.info("🎉 Pricing and plans update completed successfully!")
except Exception as e:
logger.error(f"❌ Error updating pricing/plans: {e}")
logger.error(traceback.format_exc())
db.rollback()
raise
finally:
db.close()
except Exception as e:
logger.error(f"❌ Error: {e}")
logger.error(traceback.format_exc())
raise
if __name__ == "__main__":
logger.info("🚀 Updating Basic Tier Limits and OSS Model Pricing...")
try:
update_pricing_and_plans()
logger.info("✅ Update completed successfully!")
except KeyboardInterrupt:
logger.info("Update cancelled by user")
sys.exit(0)
except Exception as e:
logger.error(f"❌ Update failed: {e}")
sys.exit(1)