diff --git a/src/backend/agents/__init__.py b/src/backend/agents/__init__.py index d7d89a7..03280b1 100644 --- a/src/backend/agents/__init__.py +++ b/src/backend/agents/__init__.py @@ -1,16 +1,7 @@ from __future__ import annotations import traceback -from pydantic import BaseModel, Field from typing import ( - Literal, - get_args, - List, - AsyncGenerator, - TYPE_CHECKING, - Optional, - ClassVar, - Any, TypeAlias, Dict, Tuple, diff --git a/src/backend/agents/base.py b/src/backend/agents/base.py index 7e3c8e3..21119f4 100644 --- a/src/backend/agents/base.py +++ b/src/backend/agents/base.py @@ -5,51 +5,41 @@ from typing import ( get_args, List, AsyncGenerator, - TYPE_CHECKING, Optional, ClassVar, Any, - TypeAlias, - Dict, - Tuple, ) -import json import time -import inspect import re from abc import ABC -import asyncio from datetime import datetime, UTC from prometheus_client import Counter, Summary, CollectorRegistry # type: ignore import numpy as np # type: ignore import json_extractor as json_extractor from pydantic import BaseModel, Field, model_validator # type: ignore from uuid import uuid4 -from typing import List, Optional, Generator, ClassVar, Any, Dict, TYPE_CHECKING, Literal +from typing import List, Optional, ClassVar, Any, Literal -from datetime import datetime, date, UTC -from typing_extensions import Annotated, Union +from datetime import datetime, UTC import numpy as np # type: ignore from uuid import uuid4 from prometheus_client import CollectorRegistry, Counter # type: ignore -import traceback import os -import json import re from pathlib import Path from rag import start_file_watcher, ChromaDBFileWatcher import defines from logger import logger -from models import (Tunables, CandidateQuestion, ChatMessageUser, ChatMessage, RagEntry, ChatMessageMetaData, ApiStatusType, Candidate, ChatContextType) +from models import (Tunables, ChatMessageUser, ChatMessage, RagEntry, ChatMessageMetaData, ApiStatusType, Candidate, ChatContextType) import utils.llm_proxy as llm_manager from database.manager import RedisDatabase from models import ChromaDBGetResponse from utils.metrics import Metrics -from models import ( ApiActivityType, ApiMessage, ChatMessageError, ChatMessageRagSearch, ChatMessageStatus, ChatMessageStreaming, LLMMessage, ChatQuery, ChatMessage, ChatOptions, ChatMessageUser, Tunables, ApiMessageType, ChatSenderType, ApiStatusType, ChatMessageMetaData, Candidate) +from models import ( ApiActivityType, ApiMessage, ChatMessageError, ChatMessageRagSearch, ChatMessageStatus, ChatMessageStreaming, LLMMessage, ChatMessage, ChatOptions, ChatMessageUser, Tunables, ApiStatusType, ChatMessageMetaData, Candidate) from logger import logger import defines from .registry import agent_registry @@ -64,7 +54,6 @@ class CandidateEntity(Candidate): async def cleanup(self): """Cleanup resources associated with this entity""" - pass # Internal instance members CandidateEntity__agents: List[Agent] = [] diff --git a/src/backend/agents/candidate_chat.py b/src/backend/agents/candidate_chat.py index bfdc2b8..41faaf4 100644 --- a/src/backend/agents/candidate_chat.py +++ b/src/backend/agents/candidate_chat.py @@ -1,13 +1,11 @@ from __future__ import annotations from typing import Literal, AsyncGenerator, ClassVar, Optional, Any -from datetime import datetime -import inspect from .base import Agent, agent_registry from logger import logger from .registry import agent_registry -from models import ( ApiMessage, ChatMessageError, ChatMessageStatus, ChatMessageStreaming, ChatQuery, ChatMessage, Tunables, ApiStatusType, ChatMessageUser, Candidate) +from models import ( ApiMessage, Tunables, ApiStatusType) system_message = f""" diff --git a/src/backend/agents/general.py b/src/backend/agents/general.py index 308de40..ddb50a1 100644 --- a/src/backend/agents/general.py +++ b/src/backend/agents/general.py @@ -1,13 +1,10 @@ from __future__ import annotations -from typing import Literal, AsyncGenerator, ClassVar, Optional, Any +from typing import Literal, ClassVar from datetime import datetime -import inspect from .base import Agent, agent_registry -from logger import logger from .registry import agent_registry -from models import ( ChatQuery, ChatMessage, Tunables, ApiStatusType) system_message = f""" Launched on {datetime.now().isoformat()}. diff --git a/src/backend/agents/generate_image.py b/src/backend/agents/generate_image.py index b68eafa..2f58091 100644 --- a/src/backend/agents/generate_image.py +++ b/src/backend/agents/generate_image.py @@ -1,6 +1,4 @@ from __future__ import annotations -from datetime import UTC, datetime -from pydantic import model_validator, Field, BaseModel from typing import ( Dict, Literal, @@ -12,25 +10,17 @@ from typing import ( Optional # override ) # NOTE: You must import Optional for late binding to work -import inspect import random -import re -import json -import asyncio import time -import asyncio import time import os -import hashlib -from .base import Agent, agent_registry, LLMMessage -from models import ActivityType, ApiActivityType, Candidate, ChatMessage, ChatMessageError, ChatMessageMetaData, ApiMessageType, ChatMessageStatus, ChatMessageStreaming, ChatMessageUser, ChatOptions, ChatSenderType, ApiStatusType, Tunables -import helpers.model_cast as model_cast +from .base import Agent, agent_registry +from models import ApiActivityType, ChatMessage, ChatMessageError, ChatMessageStatus, ChatMessageStreaming, ApiStatusType, Tunables from logger import logger import defines import backstory_traceback as traceback -from image_generator.image_model_cache import ImageModelCache from image_generator.profile_image import generate_image, ImageRequest seed = int(time.time()) diff --git a/src/backend/agents/generate_persona.py b/src/backend/agents/generate_persona.py index 7d5f1d1..0cf2684 100644 --- a/src/backend/agents/generate_persona.py +++ b/src/backend/agents/generate_persona.py @@ -1,5 +1,4 @@ from __future__ import annotations -from datetime import UTC, datetime from pydantic import model_validator, Field, BaseModel # type: ignore from typing import ( Dict, @@ -13,20 +12,17 @@ from typing import ( Optional # override ) # NOTE: You must import Optional for late binding to work -import inspect import random import re import json -import asyncio import time -import asyncio import time import os import random from names_dataset import NameDataset, NameWrapper # type: ignore -from .base import Agent, agent_registry, LLMMessage -from models import ApiActivityType, Candidate, ChatMessage, ChatMessageError, ChatMessageMetaData, ApiMessageType, ChatMessageStatus, ChatMessageStreaming, ChatMessageUser, ChatOptions, ChatSenderType, ApiStatusType, Tunables +from .base import Agent, agent_registry +from models import ApiActivityType, ChatMessage, ChatMessageError, ApiMessageType, ChatMessageStatus, ChatMessageStreaming, ApiStatusType, Tunables from logger import logger import defines import backstory_traceback as traceback diff --git a/src/backend/agents/generate_resume.py b/src/backend/agents/generate_resume.py index bb12ca9..213c3f4 100644 --- a/src/backend/agents/generate_resume.py +++ b/src/backend/agents/generate_resume.py @@ -10,18 +10,12 @@ from typing import ( Optional # override ) # NOTE: You must import Optional for late binding to work -import inspect -import re import json -import traceback -import asyncio -import time -import asyncio import numpy as np # type: ignore from logger import logger from .base import Agent, agent_registry -from models import (ApiActivityType, ApiMessage, ApiStatusType, Candidate, ChatMessage, ChatMessageError, ChatMessageResume, ChatMessageStatus, JobRequirements, JobRequirementsMessage, SkillAssessment, SkillStrength, Tunables) +from models import (ApiActivityType, ApiMessage, ApiStatusType, ChatMessage, ChatMessageError, ChatMessageResume, ChatMessageStatus, SkillAssessment, SkillStrength) class GenerateResume(Agent): agent_type: Literal["generate_resume"] = "generate_resume" # type: ignore diff --git a/src/backend/agents/job_requirements.py b/src/backend/agents/job_requirements.py index 9f02325..6044af9 100644 --- a/src/backend/agents/job_requirements.py +++ b/src/backend/agents/job_requirements.py @@ -11,17 +11,12 @@ from typing import ( # override ) # NOTE: You must import Optional for late binding to work import inspect -import re import json -import asyncio -import time -import asyncio import numpy as np # type: ignore -from .base import Agent, agent_registry, LLMMessage -from models import ApiActivityType, ApiMessage, Candidate, ChatMessage, ChatMessageError, ChatMessageMetaData, ApiMessageType, ChatMessageStatus, ChatMessageStreaming, ChatMessageUser, ChatOptions, ChatSenderType, ApiStatusType, Job, JobRequirements, JobRequirementsMessage, Tunables +from .base import Agent, agent_registry +from models import ApiActivityType, ApiMessage, ChatMessage, ChatMessageError, ChatMessageStatus, ChatMessageStreaming, ApiStatusType, Job, JobRequirements, JobRequirementsMessage, Tunables from logger import logger -import defines import backstory_traceback as traceback class JobRequirementsAgent(Agent): diff --git a/src/backend/agents/rag_search.py b/src/backend/agents/rag_search.py index 8431218..8fe27eb 100644 --- a/src/backend/agents/rag_search.py +++ b/src/backend/agents/rag_search.py @@ -1,13 +1,11 @@ from __future__ import annotations -from typing import Literal, AsyncGenerator, ClassVar, Optional, Any, List -from datetime import datetime, UTC -import inspect +from typing import Literal, AsyncGenerator, ClassVar, Optional, Any from .base import Agent, agent_registry from logger import logger from .registry import agent_registry -from models import ( ApiMessage, ChatMessage, ChromaDBGetResponse, ApiStatusType, ChatMessage, ChatMessageError, ChatMessageRagSearch, ChatMessageStatus, ChatMessageStreaming, ChatOptions, ApiMessageType, ChatSenderType, ApiStatusType, ChatMessageMetaData, Candidate, Tunables ) +from models import ( ApiMessage, ApiStatusType, ChatMessageError, ChatMessageRagSearch, ApiStatusType, Tunables ) class Chat(Agent): """ diff --git a/src/backend/agents/skill_match.py b/src/backend/agents/skill_match.py index e03030f..0a21c05 100644 --- a/src/backend/agents/skill_match.py +++ b/src/backend/agents/skill_match.py @@ -10,20 +10,13 @@ from typing import ( Optional # override ) # NOTE: You must import Optional for late binding to work -import inspect -import re import json -import asyncio -import time -import asyncio import numpy as np # type: ignore -from .base import Agent, agent_registry, LLMMessage -from models import (ApiMessage, Candidate, ChatMessage, ChatMessageError, ChatMessageMetaData, ApiMessageType, ChatMessageRagSearch, -ChatMessageSkillAssessment, ChatMessageStatus, ChatMessageStreaming, ChatMessageUser, ChatOptions, -ChatSenderType, ApiStatusType, EvidenceDetail, SkillAssessment, Tunables) +from .base import Agent, agent_registry +from models import (ApiMessage, ChatMessage, ChatMessageError, ChatMessageRagSearch, ChatMessageSkillAssessment, ApiStatusType, EvidenceDetail, +SkillAssessment, Tunables) from logger import logger -import defines import backstory_traceback as traceback class SkillMatchAgent(Agent): diff --git a/src/backend/auth_utils.py b/src/backend/auth_utils.py deleted file mode 100644 index 0a31dac..0000000 --- a/src/backend/auth_utils.py +++ /dev/null @@ -1,275 +0,0 @@ -# auth_utils.py -""" -Secure Authentication Utilities -Provides password hashing, verification, and security features -""" - -import traceback -import bcrypt -import secrets -import logging -from datetime import datetime, timezone, timedelta -from typing import Dict, Any, Optional, Tuple -from pydantic import BaseModel - -logger = logging.getLogger(__name__) - -class PasswordSecurity: - """Handles password hashing and verification using bcrypt""" - - @staticmethod - def hash_password(password: str) -> Tuple[str, str]: - """ - Hash a password with a random salt using bcrypt - - Args: - password: Plain text password - - Returns: - Tuple of (password_hash, salt) both as strings - """ - # Generate a random salt - salt = bcrypt.gensalt() - - # Hash the password - password_hash = bcrypt.hashpw(password.encode('utf-8'), salt) - - return password_hash.decode('utf-8'), salt.decode('utf-8') - - @staticmethod - def verify_password(password: str, password_hash: str) -> bool: - """ - Verify a password against its hash - - Args: - password: Plain text password to verify - password_hash: Stored password hash - - Returns: - True if password matches, False otherwise - """ - try: - return bcrypt.checkpw( - password.encode('utf-8'), - password_hash.encode('utf-8') - ) - except Exception as e: - logger.error(f"Password verification error: {e}") - return False - - @staticmethod - def generate_secure_token(length: int = 32) -> str: - """Generate a cryptographically secure random token""" - return secrets.token_urlsafe(length) - -class AuthenticationRecord(BaseModel): - """Authentication record for storing user credentials""" - user_id: str - password_hash: str - salt: str - refresh_tokens: list = [] - reset_password_token: Optional[str] = None - reset_password_expiry: Optional[datetime] = None - last_password_change: datetime - mfa_enabled: bool = False - mfa_method: Optional[str] = None - mfa_secret: Optional[str] = None - login_attempts: int = 0 - locked_until: Optional[datetime] = None - - class Config: - json_encoders = { - datetime: lambda v: v.isoformat() if v else None - } - -class SecurityConfig: - """Security configuration constants""" - MAX_LOGIN_ATTEMPTS = 5 - ACCOUNT_LOCKOUT_DURATION_MINUTES = 15 - PASSWORD_MIN_LENGTH = 8 - TOKEN_EXPIRY_HOURS = 24 - REFRESH_TOKEN_EXPIRY_DAYS = 30 - -class AuthenticationManager: - """Manages authentication operations with security features""" - - def __init__(self, database): - self.database = database - self.password_security = PasswordSecurity() - - async def create_user_authentication(self, user_id: str, password: str) -> AuthenticationRecord: - """ - Create authentication record for a new user - - Args: - user_id: Unique user identifier - password: Plain text password - - Returns: - AuthenticationRecord object - """ - if len(password) < SecurityConfig.PASSWORD_MIN_LENGTH: - raise ValueError(f"Password must be at least {SecurityConfig.PASSWORD_MIN_LENGTH} characters long") - - # Hash the password - password_hash, salt = self.password_security.hash_password(password) - - # Create authentication record - auth_record = AuthenticationRecord( - user_id=user_id, - password_hash=password_hash, - salt=salt, - last_password_change=datetime.now(timezone.utc), - login_attempts=0 - ) - - # Store in database - await self.database.set_authentication(user_id, auth_record.model_dump()) - - logger.info(f"🔐 Created authentication record for user {user_id}") - return auth_record - - async def verify_user_credentials(self, login: str, password: str) -> Tuple[bool, Optional[Dict[str, Any]], Optional[str]]: - """ - Verify user credentials with security checks - - Args: - login: Email or username - password: Plain text password - - Returns: - Tuple of (is_valid, user_data, error_message) - """ - try: - # Get user data - user_data = await self.database.get_user(login) - if not user_data: - logger.warning(f"⚠️ Login attempt with non-existent user: {login}") - return False, None, "Invalid credentials" - - # Get authentication record - auth_record = await self.database.get_authentication(user_data["id"]) - if not auth_record: - logger.error(f"❌ No authentication record found for user {user_data['id']}") - return False, None, "Authentication record not found" - - auth_data = AuthenticationRecord.model_validate(auth_record) - - # Check if account is locked - if auth_data.locked_until and auth_data.locked_until > datetime.now(timezone.utc): - time_until_unlock = auth_data.locked_until - datetime.now(timezone.utc) - # Convert time_until_unlock to minutes:seconds format - total_seconds = time_until_unlock.total_seconds() - minutes = int(total_seconds // 60) - seconds = int(total_seconds % 60) - time_until_unlock_str = f"{minutes}m {seconds}s" - logger.warning(f"🔒 Account is locked for user {login} for another {time_until_unlock_str}.") - return False, None, f"Account is temporarily locked due to too many failed attempts. Retry after {time_until_unlock_str}" - - # Verify password - if not self.password_security.verify_password(password, auth_data.password_hash): - # Increment failed attempts - auth_data.login_attempts += 1 - - # Lock account if too many attempts - if auth_data.login_attempts >= SecurityConfig.MAX_LOGIN_ATTEMPTS: - auth_data.locked_until = datetime.now(timezone.utc) + timedelta( - minutes=SecurityConfig.ACCOUNT_LOCKOUT_DURATION_MINUTES - ) - logger.warning(f"🔒 Account locked for user {login} after {auth_data.login_attempts} failed attempts") - - # Update authentication record - await self.database.set_authentication(user_data["id"], auth_data.model_dump()) - - logger.warning(f"⚠️ Invalid password for user {login} (attempt {auth_data.login_attempts})") - return False, None, "Invalid credentials" - - # Reset failed attempts on successful login - if auth_data.login_attempts > 0: - auth_data.login_attempts = 0 - auth_data.locked_until = None - await self.database.set_authentication(user_data["id"], auth_data.model_dump()) - - logger.info(f"✅ Successful authentication for user {login}") - return True, user_data, None - - except Exception as e: - logger.error(traceback.format_exc()) - logger.error(f"❌ Authentication error for user {login}: {e}") - return False, None, "Authentication failed" - - async def check_user_exists(self, email: str, username: str | None = None) -> Tuple[bool, Optional[str]]: - """ - Check if a user already exists with the given email or username - - Args: - email: Email address to check - username: Username to check (optional) - - Returns: - Tuple of (exists, conflict_field) - """ - try: - # Check email - existing_user = await self.database.get_user(email) - if existing_user: - return True, "email" - - # Check username if provided - if username: - existing_user = await self.database.get_user(username) - if existing_user: - return True, "username" - - return False, None - - except Exception as e: - logger.error(f"❌ Error checking user existence: {e}") - # In case of error, assume user doesn't exist to avoid blocking creation - return False, None - - async def update_last_login(self, user_id: str): - """Update user's last login timestamp""" - try: - user_data = await self.database.get_user_by_id(user_id) - if user_data: - user_data["lastLogin"] = datetime.now(timezone.utc).isoformat() - await self.database.set_user_by_id(user_id, user_data) - except Exception as e: - logger.error(f"❌ Error updating last login for user {user_id}: {e}") - -# Utility functions for common operations -def validate_password_strength(password: str) -> Tuple[bool, list]: - """ - Validate password strength - - Args: - password: Password to validate - - Returns: - Tuple of (is_valid, list_of_issues) - """ - issues = [] - - if len(password) < SecurityConfig.PASSWORD_MIN_LENGTH: - issues.append(f"Password must be at least {SecurityConfig.PASSWORD_MIN_LENGTH} characters long") - - if not any(c.isupper() for c in password): - issues.append("Password must contain at least one uppercase letter") - - if not any(c.islower() for c in password): - issues.append("Password must contain at least one lowercase letter") - - if not any(c.isdigit() for c in password): - issues.append("Password must contain at least one digit") - - # Check for special characters - special_chars = "!@#$%^&*()_+-=[]{}|;:,.<>?" - if not any(c in special_chars for c in password): - issues.append("Password must contain at least one special character") - - return len(issues) == 0, issues - -def sanitize_login_input(login: str) -> str: - """Sanitize login input (email or username)""" - return login.strip().lower() if login else "" \ No newline at end of file diff --git a/src/backend/database/manager.py b/src/backend/database/manager.py index ad0ebda..de1bc13 100644 --- a/src/backend/database/manager.py +++ b/src/backend/database/manager.py @@ -1,17 +1,14 @@ -from pydantic import BaseModel, ConfigDict, Field from redis.asyncio import (Redis, ConnectionPool) -from typing import Any, Optional, Dict, List, Optional, TypeGuard, Union +from typing import Optional, Optional import json import logging import os -from datetime import datetime, timezone, UTC, timedelta +from datetime import datetime, UTC import asyncio from models import ( # User models Candidate, Employer, BaseUser, EvidenceDetail, Guest, Authentication, AuthResponse, SkillAssessment, ) -import backstory_traceback as traceback -from .constants import KEY_PREFIXES from .core import RedisDatabase logger = logging.getLogger(__name__) diff --git a/src/backend/database/mixins/ai.py b/src/backend/database/mixins/ai.py index 0589e40..1511342 100644 --- a/src/backend/database/mixins/ai.py +++ b/src/backend/database/mixins/ai.py @@ -1,7 +1,5 @@ -from datetime import UTC, datetime, timedelta, timezone import logging -import json -from typing import List, Optional, Any, Dict, TYPE_CHECKING, Self +from typing import Optional, Any, Dict from .protocols import DatabaseProtocol diff --git a/src/backend/database/mixins/analytics.py b/src/backend/database/mixins/analytics.py index 9b23a8a..99d37f2 100644 --- a/src/backend/database/mixins/analytics.py +++ b/src/backend/database/mixins/analytics.py @@ -1,10 +1,9 @@ import logging -from typing import Any, Dict, TYPE_CHECKING +from typing import TYPE_CHECKING if TYPE_CHECKING: - from .protocols import DatabaseProtocol + pass -from ..constants import KEY_PREFIXES logger = logging.getLogger(__name__) diff --git a/src/backend/database/mixins/auth.py b/src/backend/database/mixins/auth.py index cf6fd48..c8c0dd5 100644 --- a/src/backend/database/mixins/auth.py +++ b/src/backend/database/mixins/auth.py @@ -1,11 +1,10 @@ from datetime import datetime, timedelta, timezone import json import logging -from typing import Any, Dict, TYPE_CHECKING, List, Optional +from typing import Any, Dict, List, Optional from .protocols import DatabaseProtocol -from ..constants import KEY_PREFIXES logger = logging.getLogger(__name__) diff --git a/src/backend/database/mixins/base.py b/src/backend/database/mixins/base.py index 41bd32b..dbde059 100644 --- a/src/backend/database/mixins/base.py +++ b/src/backend/database/mixins/base.py @@ -1,7 +1,6 @@ -from datetime import UTC, datetime import json import logging -from typing import Any, Dict, TYPE_CHECKING, Optional +from typing import Any, Dict, TYPE_CHECKING from .protocols import DatabaseProtocol @@ -9,7 +8,7 @@ from ..constants import KEY_PREFIXES logger = logging.getLogger(__name__) if TYPE_CHECKING: - from ..core import RedisDatabase + pass class BaseMixin(DatabaseProtocol): """Base mixin with core Redis operations and utilities""" diff --git a/src/backend/database/mixins/chat.py b/src/backend/database/mixins/chat.py index 0ee95c2..08a0bee 100644 --- a/src/backend/database/mixins/chat.py +++ b/src/backend/database/mixins/chat.py @@ -1,6 +1,6 @@ from datetime import datetime, UTC, timedelta import logging -from typing import Any, Dict, TYPE_CHECKING, List, Optional +from typing import Any, Dict, List, Optional from .protocols import DatabaseProtocol diff --git a/src/backend/database/mixins/document.py b/src/backend/database/mixins/document.py index 04f90c8..d9fd83a 100644 --- a/src/backend/database/mixins/document.py +++ b/src/backend/database/mixins/document.py @@ -1,6 +1,6 @@ from datetime import UTC, datetime import logging -from typing import Any, Dict, TYPE_CHECKING, List, Optional +from typing import Any, Dict, List, Optional from .protocols import DatabaseProtocol from ..constants import KEY_PREFIXES diff --git a/src/backend/database/mixins/job.py b/src/backend/database/mixins/job.py index 39fea6a..a5a9161 100644 --- a/src/backend/database/mixins/job.py +++ b/src/backend/database/mixins/job.py @@ -1,6 +1,6 @@ -from datetime import datetime, UTC, timedelta +from datetime import datetime, UTC import logging -from typing import Any, Dict, TYPE_CHECKING, List, Optional +from typing import Any, Dict, List, Optional from .protocols import DatabaseProtocol diff --git a/src/backend/database/mixins/protocols.py b/src/backend/database/mixins/protocols.py index 06774e7..9b98468 100644 --- a/src/backend/database/mixins/protocols.py +++ b/src/backend/database/mixins/protocols.py @@ -3,7 +3,7 @@ from typing import Any, Dict, List, Optional, Protocol, TYPE_CHECKING from redis.asyncio import Redis if TYPE_CHECKING: - from database.core import RedisDatabase + pass from models import SkillAssessment diff --git a/src/backend/database/mixins/resume.py b/src/backend/database/mixins/resume.py index 472cbf9..cb0f6c7 100644 --- a/src/backend/database/mixins/resume.py +++ b/src/backend/database/mixins/resume.py @@ -1,6 +1,6 @@ from datetime import UTC, datetime import logging -from typing import Any, Dict, TYPE_CHECKING, List, Optional +from typing import Any, Dict, List, Optional from .protocols import DatabaseProtocol from ..constants import KEY_PREFIXES diff --git a/src/backend/database/mixins/skill.py b/src/backend/database/mixins/skill.py index 8850910..84b105b 100644 --- a/src/backend/database/mixins/skill.py +++ b/src/backend/database/mixins/skill.py @@ -1,11 +1,10 @@ import json import logging -from typing import Any, Dict, TYPE_CHECKING, Optional +from typing import Optional from models import SkillAssessment from .protocols import DatabaseProtocol -from ..constants import KEY_PREFIXES logger = logging.getLogger(__name__) diff --git a/src/backend/database/mixins/user.py b/src/backend/database/mixins/user.py index 372c281..0c8fbbc 100644 --- a/src/backend/database/mixins/user.py +++ b/src/backend/database/mixins/user.py @@ -1,7 +1,7 @@ from datetime import UTC, datetime, timedelta, timezone import logging import json -from typing import List, Optional, Any, Dict, TYPE_CHECKING, Self +from typing import List, Optional, Any, Dict, Self from .protocols import DatabaseProtocol diff --git a/src/backend/device_manager.py b/src/backend/device_manager.py index df17624..7895cb5 100644 --- a/src/backend/device_manager.py +++ b/src/backend/device_manager.py @@ -1,4 +1,4 @@ -from fastapi import FastAPI, HTTPException, Depends, Query, Path, Body, status, APIRouter, Request, BackgroundTasks +from fastapi import Request from database.manager import RedisDatabase import hashlib from logger import logger diff --git a/src/backend/entities/entity_manager.py b/src/backend/entities/entity_manager.py index e9195bb..0ee8836 100644 --- a/src/backend/entities/entity_manager.py +++ b/src/backend/entities/entity_manager.py @@ -1,9 +1,7 @@ -from __future__ import annotations import asyncio -from uuid import uuid4 import weakref from datetime import datetime, timedelta -from typing import Dict, Optional, Any +from typing import Dict, Optional from contextlib import asynccontextmanager from pydantic import BaseModel, Field # type: ignore @@ -46,7 +44,7 @@ class EntityManager(BaseModel): self._prometheus_collector = prometheus_collector self._database = database - async def get_entity(self, candidate: Candidate) -> CandidateEntity: + async def get_entity(self, candidate: "Candidate") -> CandidateEntity: """Get or create CandidateEntity with proper reference tracking""" # Check if entity exists and is still valid diff --git a/src/backend/focused_test.py b/src/backend/focused_test.py index 20abd28..20fa68b 100644 --- a/src/backend/focused_test.py +++ b/src/backend/focused_test.py @@ -8,7 +8,7 @@ import sys from datetime import datetime from models import ( UserStatus, UserType, SkillLevel, EmploymentType, - Candidate, Employer, Location, Skill, AIModelType + Candidate, Employer, Location, Skill ) diff --git a/src/backend/generate_types.py b/src/backend/generate_types.py index 991e057..27755dc 100644 --- a/src/backend/generate_types.py +++ b/src/backend/generate_types.py @@ -458,7 +458,6 @@ def is_field_optional(field_info: Any, field_type: Any, debug: bool = False) -> except: if debug: print(f" └─ is_required() failed") - pass # Check the 'required' attribute (Pydantic v1 style) if hasattr(field_info, 'required'): diff --git a/src/backend/helpers/check_serializable.py b/src/backend/helpers/check_serializable.py index 0cad6a1..5f6ff86 100644 --- a/src/backend/helpers/check_serializable.py +++ b/src/backend/helpers/check_serializable.py @@ -1,4 +1,4 @@ -from pydantic import BaseModel, Field +from pydantic import BaseModel import json from typing import Any, List, Set diff --git a/src/backend/image_generator/profile_image.py b/src/backend/image_generator/profile_image.py index 2d2aae7..699cd31 100644 --- a/src/backend/image_generator/profile_image.py +++ b/src/backend/image_generator/profile_image.py @@ -1,22 +1,13 @@ from __future__ import annotations -from datetime import UTC, datetime -from pydantic import BaseModel, Field -from typing import Dict, Literal, Any, AsyncGenerator, Optional -import inspect -import random -import re -import json +from pydantic import BaseModel +from typing import Any, AsyncGenerator import traceback import asyncio import time import os -import gc -import tempfile import uuid -import torch import asyncio import time -import json from typing import AsyncGenerator from threading import Thread import queue @@ -24,7 +15,7 @@ import uuid from .image_model_cache import ImageModelCache -from models import ApiActivityType, ApiStatusType, Candidate, ChatMessage, ChatMessageError, ChatMessageMetaData, ChatMessageStatus, ChatMessageUser, ChatOptions, ChatSenderType +from models import ApiActivityType, ApiStatusType, ChatMessage, ChatMessageError, ChatMessageStatus from logger import logger from image_generator.image_model_cache import ImageModelCache diff --git a/src/backend/main.py b/src/backend/main.py index 015b1e6..bdb8b19 100644 --- a/src/backend/main.py +++ b/src/backend/main.py @@ -1,81 +1,37 @@ -import hashlib -import time -import traceback -from fastapi import FastAPI, HTTPException, Depends, Query, Path, Body, status, APIRouter, Request, BackgroundTasks, File, UploadFile, Form +from fastapi import FastAPI, Depends, APIRouter, Request from fastapi.middleware.cors import CORSMiddleware -from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials from fastapi.exceptions import RequestValidationError -from fastapi.responses import JSONResponse, StreamingResponse, FileResponse -from fastapi.staticfiles import StaticFiles +from fastapi.responses import JSONResponse, FileResponse from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY -from functools import wraps -from typing import Callable, Any, Optional -from utils.rate_limiter import RateLimiter, RateLimitResult - -import schedule +from typing import Optional import os -import shutil -from enum import Enum -import uuid import defines -import pathlib - -from markitdown import MarkItDown, StreamInfo -import io import uvicorn -from typing import List, Optional, Dict, Any -from datetime import datetime, timedelta, UTC -import uuid -import jwt -import os +from datetime import datetime from contextlib import asynccontextmanager -import redis.asyncio as redis import re -import asyncio import signal import json -import uuid -import logging -from datetime import datetime, timezone, timedelta -from typing import Dict, Any, Optional -from pydantic import BaseModel, EmailStr, field_validator, ValidationError # Prometheus -from prometheus_client import Summary from prometheus_fastapi_instrumentator import Instrumentator -from prometheus_client import CollectorRegistry, Counter -import secrets -import os +from prometheus_client import CollectorRegistry import backstory_traceback -from background_tasks import BackgroundTaskManager # ============================= # Import custom modules # ============================= -from auth_utils import ( - AuthenticationManager, - validate_password_strength, - sanitize_login_input, - SecurityConfig -) -import helpers.model_cast as model_cast -import defines from logger import logger -from database.manager import RedisDatabase, redis_manager, DatabaseManager -import entities -from email_service import VerificationEmailRateLimiter, email_service -from device_manager import DeviceManager -import agents from entities.entity_manager import entity_manager +from database.manager import redis_manager, DatabaseManager +from background_tasks import BackgroundTaskManager # ============================= # Import utilities # ============================= from utils.dependencies import get_database, set_db_manager -from utils.responses import create_success_response, create_error_response -from utils.helpers import filter_and_paginate # ============================= # Import route modules @@ -93,35 +49,6 @@ from routes import ( users, ) -# ============================= -# Import Pydantic models -# ============================= -from models import ( - # API - MOCK_UUID, ApiActivityType, ChatMessageError, ChatMessageResume, ChatMessageSkillAssessment, ChatMessageStatus, ChatMessageStreaming, ChatMessageUser, DocumentMessage, DocumentOptions, Job, JobRequirements, JobRequirementsMessage, LoginRequest, CreateCandidateRequest, CreateEmployerRequest, - - # User models - Candidate, Employer, BaseUserWithType, BaseUser, Guest, Authentication, AuthResponse, CandidateAI, - - # Job models - JobApplication, ApplicationStatus, - - # Chat models - ChatSession, ChatMessage, ChatContext, ChatQuery, ApiStatusType, ChatSenderType, ApiMessageType, ChatContextType, - ChatMessageRagSearch, - - # Document models - Document, DocumentType, DocumentListResponse, DocumentUpdateRequest, DocumentContentResponse, - - # Supporting models - Location, MFARequest, MFAData, MFARequestResponse, MFAVerifyRequest, RagContentMetadata, RagContentResponse, ResendVerificationRequest, Resume, ResumeMessage, Skill, SkillAssessment, SystemInfo, UserType, WorkExperience, Education, - - # Email - EmailVerificationRequest -) - - -# Initialize FastAPI app # ============================ # Startup Event # ============================ diff --git a/src/backend/models.py b/src/backend/models.py index be7277d..494c10a 100644 --- a/src/backend/models.py +++ b/src/backend/models.py @@ -1,14 +1,11 @@ -from typing import List, Dict, Optional, Any, Union, Literal, TypeVar, Generic, Annotated +from typing import List, Dict, Optional, Any, Union, Literal, TypeVar, Annotated from pydantic import BaseModel, Field, EmailStr, HttpUrl, model_validator, field_validator, ConfigDict -from pydantic.types import constr, conint -from datetime import datetime, date, UTC +from datetime import datetime, UTC from enum import Enum import uuid -from auth_utils import ( - AuthenticationManager, +from utils.auth_utils import ( validate_password_strength, sanitize_login_input, - SecurityConfig ) import defines @@ -823,7 +820,6 @@ class GuestConversionRequest(BaseModel): @field_validator('password') def validate_password_strength(cls, v): # Import here to avoid circular imports - from auth_utils import validate_password_strength is_valid, issues = validate_password_strength(v) if not is_valid: raise ValueError('; '.join(issues)) diff --git a/src/backend/rag/markdown_chunker.py b/src/backend/rag/markdown_chunker.py index 18595e0..b5c2e3d 100644 --- a/src/backend/rag/markdown_chunker.py +++ b/src/backend/rag/markdown_chunker.py @@ -1,10 +1,9 @@ from __future__ import annotations -from typing import List, Dict, Any, Optional, TypedDict, Tuple +from typing import List, Dict, Any, Optional, TypedDict from markdown_it import MarkdownIt from markdown_it.tree import SyntaxTreeNode import traceback import logging -import json import defines diff --git a/src/backend/rag/rag.py b/src/backend/rag/rag.py index 574a605..4f21272 100644 --- a/src/backend/rag/rag.py +++ b/src/backend/rag/rag.py @@ -1,10 +1,9 @@ from __future__ import annotations from pydantic import BaseModel, field_serializer, field_validator, model_validator, Field # type: ignore -from typing import List, Optional, Dict, Any, Union +from typing import List, Optional, Dict, Any import os import glob from pathlib import Path -import time import hashlib import asyncio import logging diff --git a/src/backend/routes/admin.py b/src/backend/routes/admin.py index 24d3c72..52b13a8 100644 --- a/src/backend/routes/admin.py +++ b/src/backend/routes/admin.py @@ -2,16 +2,11 @@ Chat routes """ import json -import jwt -import secrets -import uuid -from datetime import datetime, timedelta, timezone, UTC -from typing import (Optional, List, Dict, Any) +from datetime import datetime, timezone, UTC from fastapi import ( - APIRouter, HTTPException, Depends, Body, Request, BackgroundTasks, - FastAPI, HTTPException, Depends, Query, Path, Body, status, - APIRouter, Request, BackgroundTasks, File, UploadFile, Form + APIRouter, HTTPException, Depends, Body, Request, HTTPException, + Depends, Query, Path, Body, APIRouter, Request ) from fastapi.responses import JSONResponse diff --git a/src/backend/routes/auth.py b/src/backend/routes/auth.py index 4974843..312d4f4 100644 --- a/src/backend/routes/auth.py +++ b/src/backend/routes/auth.py @@ -7,13 +7,12 @@ import secrets import uuid import os from datetime import datetime, timedelta, timezone, UTC -from typing import Any, Dict, Optional +from typing import Any, Dict -from fastapi import APIRouter, HTTPException, Depends, Body, Request, BackgroundTasks +from fastapi import APIRouter, Depends, Body, Request, BackgroundTasks from fastapi.responses import JSONResponse from pydantic import BaseModel, EmailStr, ValidationError, field_validator -from auth_utils import AuthenticationManager, SecurityConfig import backstory_traceback as backstory_traceback from utils.rate_limiter import RateLimiter from database.manager import RedisDatabase, redis_manager @@ -21,23 +20,19 @@ from device_manager import DeviceManager from email_service import VerificationEmailRateLimiter, email_service from logger import logger from models import ( - LoginRequest, CreateCandidateRequest, CreateEmployerRequest, - Candidate, Employer, Guest, AuthResponse, - MFARequest, MFAData, MFAVerifyRequest, - EmailVerificationRequest, ResendVerificationRequest, + LoginRequest, CreateCandidateRequest, Candidate, + Employer, Guest, AuthResponse, MFARequest, + MFAData, MFAVerifyRequest, ResendVerificationRequest, MFARequestResponse, MFARequestResponse ) from utils.dependencies import ( - get_current_admin, get_database, get_current_user, get_current_user_or_guest, - create_access_token, verify_token_with_blacklist + get_current_admin, get_database, get_current_user, create_access_token ) from utils.responses import create_success_response, create_error_response from utils.rate_limiter import get_rate_limiter -from auth_utils import ( - AuthenticationManager, +from utils.auth_utils import ( + AuthenticationManager, SecurityConfig, validate_password_strength, - sanitize_login_input, - SecurityConfig ) # Create router for authentication endpoints diff --git a/src/backend/routes/candidates.py b/src/backend/routes/candidates.py index bd9aaca..985464e 100644 --- a/src/backend/routes/candidates.py +++ b/src/backend/routes/candidates.py @@ -5,43 +5,38 @@ import json import pathlib import re import shutil -import jwt import secrets import uuid import os -from datetime import datetime, timedelta, timezone, UTC +from datetime import datetime, timezone, UTC from typing import Any, Dict, List, Optional -from fastapi import APIRouter, File, Form, HTTPException, Depends, Body, Path, Query, Request, BackgroundTasks, UploadFile +from fastapi import APIRouter, File, Form, Depends, Body, Path, Query, BackgroundTasks, UploadFile from fastapi.responses import FileResponse, JSONResponse, StreamingResponse -from pydantic import BaseModel, ValidationError +from pydantic import ValidationError -from auth_utils import AuthenticationManager, SecurityConfig import backstory_traceback as backstory_traceback from agents.generate_resume import GenerateResume import agents.base as agents -from utils.rate_limiter import RateLimiter, rate_limited +from utils.rate_limiter import rate_limited from utils.helpers import filter_and_paginate, get_document_type_from_filename, get_skill_cache_key, get_requirements_list -from database.manager import RedisDatabase, redis_manager -from device_manager import DeviceManager -from email_service import VerificationEmailRateLimiter, email_service +from database.manager import RedisDatabase +from email_service import email_service from logger import logger from models import ( - MOCK_UUID, ApiActivityType, ApiMessageType, ApiStatusType, CandidateAI, ChatContextType, ChatMessageError, ChatMessageRagSearch, ChatMessageResume, ChatMessageSkillAssessment, ChatMessageStatus, ChatMessageStreaming, ChatMessageUser, ChatSession, Document, DocumentContentResponse, DocumentListResponse, DocumentMessage, DocumentOptions, DocumentType, DocumentUpdateRequest, Job, JobRequirements, LoginRequest, CreateCandidateRequest, CreateEmployerRequest, - Candidate, Employer, Guest, AuthResponse, - MFARequest, MFAData, MFAVerifyRequest, - EmailVerificationRequest, RAGDocumentRequest, RagContentMetadata, RagContentResponse, ResendVerificationRequest, - MFARequestResponse, MFARequestResponse, SkillAssessment, UserType + MOCK_UUID, ApiActivityType, ApiMessageType, ApiStatusType, CandidateAI, ChatContextType, ChatMessageError, ChatMessageRagSearch, ChatMessageResume, ChatMessageSkillAssessment, ChatMessageStatus, ChatMessageStreaming, ChatMessageUser, ChatSession, Document, DocumentContentResponse, DocumentListResponse, DocumentMessage, DocumentOptions, DocumentType, DocumentUpdateRequest, Job, JobRequirements, CreateCandidateRequest, Candidate, RAGDocumentRequest, + RagContentMetadata, RagContentResponse, SkillAssessment, UserType ) from utils.dependencies import ( get_current_admin, get_database, get_current_user, get_current_user_or_guest, - create_access_token, verify_token_with_blacklist, prometheus_collector + prometheus_collector ) from utils.rate_limiter import rate_limited from utils.responses import create_paginated_response, create_success_response, create_error_response import utils.llm_proxy as llm_manager import entities.entity_manager as entities import defines +from utils.auth_utils import AuthenticationManager # Create router for authentication endpoints router = APIRouter(prefix="/candidates", tags=["candidates"]) diff --git a/src/backend/routes/chat.py b/src/backend/routes/chat.py index 9cf614d..da7f220 100644 --- a/src/backend/routes/chat.py +++ b/src/backend/routes/chat.py @@ -2,29 +2,21 @@ Chat routes """ import json -import jwt -import secrets import uuid -from datetime import datetime, timedelta, timezone, UTC -from typing import (Optional, List, Dict, Any) +from datetime import datetime, UTC +from typing import (Dict, Any) from fastapi import ( - APIRouter, HTTPException, Depends, Body, Request, BackgroundTasks, - FastAPI, HTTPException, Depends, Query, Path, Body, status, - APIRouter, Request, BackgroundTasks, File, UploadFile, Form + APIRouter, Depends, Body, Depends, Query, Path, + Body, APIRouter ) from fastapi.responses import JSONResponse -from pydantic import ValidationError -from auth_utils import AuthenticationManager, SecurityConfig -from database.manager import RedisDatabase, redis_manager -from device_manager import DeviceManager -from email_service import email_service +from database.manager import RedisDatabase from logger import logger from utils.dependencies import ( - get_database, get_current_user, get_current_user_or_guest, - create_access_token, verify_token_with_blacklist + get_database, get_current_user, get_current_user_or_guest ) from utils.responses import ( create_success_response, create_error_response, create_paginated_response diff --git a/src/backend/routes/debug.py b/src/backend/routes/debug.py index 4285ba7..286719c 100644 --- a/src/backend/routes/debug.py +++ b/src/backend/routes/debug.py @@ -4,36 +4,15 @@ Debugging Endpoints import json from datetime import datetime, UTC -from fastapi import APIRouter, Depends, Body, Path +from fastapi import APIRouter, Depends, Path from fastapi.responses import JSONResponse -from pydantic import BaseModel, EmailStr, ValidationError, field_validator -from auth_utils import AuthenticationManager, SecurityConfig -import backstory_traceback as backstory_traceback -from utils.rate_limiter import RateLimiter -from database.manager import RedisDatabase, redis_manager -from device_manager import DeviceManager -from email_service import VerificationEmailRateLimiter, email_service +from database.manager import RedisDatabase from logger import logger -from models import ( - LoginRequest, CreateCandidateRequest, CreateEmployerRequest, - Candidate, Employer, Guest, AuthResponse, - MFARequest, MFAData, MFAVerifyRequest, - EmailVerificationRequest, ResendVerificationRequest, - MFARequestResponse, MFARequestResponse -) from utils.dependencies import ( - get_current_admin, get_database, get_current_user, get_current_user_or_guest, - create_access_token, verify_token_with_blacklist + get_current_admin, get_database ) from utils.responses import create_success_response, create_error_response -from utils.rate_limiter import get_rate_limiter -from auth_utils import ( - AuthenticationManager, - validate_password_strength, - sanitize_login_input, - SecurityConfig -) # Create router for authentication endpoints router = APIRouter(prefix="/auth", tags=["authentication"]) diff --git a/src/backend/routes/employers.py b/src/backend/routes/employers.py index c2f7395..c5529ae 100644 --- a/src/backend/routes/employers.py +++ b/src/backend/routes/employers.py @@ -1,43 +1,24 @@ """ Employer Routes """ -import asyncio -import io -import json -import pathlib -import re -import shutil -import jwt import secrets import uuid -import os -from datetime import datetime, timedelta, timezone, UTC -from typing import Any, Dict, List, Optional +from datetime import datetime, timezone -from fastapi import APIRouter, File, Form, HTTPException, Depends, Body, Path, Query, Request, BackgroundTasks, UploadFile -from fastapi.responses import FileResponse, JSONResponse, StreamingResponse -from markitdown import MarkItDown, StreamInfo -from pydantic import BaseModel, ValidationError +from fastapi import APIRouter, Depends, BackgroundTasks +from fastapi.responses import JSONResponse -from auth_utils import AuthenticationManager -from utils.helpers import create_job_from_content, filter_and_paginate, get_document_type_from_filename, get_skill_cache_key, get_requirements_list -from database.manager import RedisDatabase, redis_manager +from database.manager import RedisDatabase from logger import logger from models import ( - MOCK_UUID, ApiActivityType, ApiMessageType, ApiStatusType, CandidateAI, ChatContextType, ChatMessage, ChatMessageError, ChatMessageRagSearch, ChatMessageResume, ChatMessageSkillAssessment, ChatMessageStatus, ChatMessageStreaming, ChatMessageUser, ChatSession, Document, DocumentContentResponse, DocumentListResponse, DocumentMessage, DocumentOptions, DocumentType, DocumentUpdateRequest, Job, JobRequirements, JobRequirementsMessage, LoginRequest, CreateCandidateRequest, CreateEmployerRequest, - Candidate, Employer, Guest, AuthResponse, - MFARequest, MFAData, MFAVerifyRequest, - EmailVerificationRequest, RAGDocumentRequest, RagContentMetadata, RagContentResponse, ResendVerificationRequest, - MFARequestResponse, MFARequestResponse, Resume, ResumeMessage, SkillAssessment, UserType + CreateEmployerRequest ) from utils.dependencies import ( - get_current_admin, get_database, get_current_user, get_current_user_or_guest, - create_access_token, verify_token_with_blacklist, prometheus_collector + get_database ) -from utils.responses import create_paginated_response, create_success_response, create_error_response -import utils.llm_proxy as llm_manager -import entities.entity_manager as entities +from utils.responses import create_success_response, create_error_response from email_service import email_service +from utils.auth_utils import AuthenticationManager # Create router for job endpoints router = APIRouter(prefix="/employers", tags=["employers"]) diff --git a/src/backend/routes/jobs.py b/src/backend/routes/jobs.py index 9d6187e..3d80160 100644 --- a/src/backend/routes/jobs.py +++ b/src/backend/routes/jobs.py @@ -6,35 +6,25 @@ import io import json import pathlib import re -import shutil -import jwt -import secrets import uuid -import os -from datetime import datetime, timedelta, timezone, UTC -from typing import Any, Dict, List, Optional +from datetime import datetime, UTC +from typing import Any, Dict, Optional -from fastapi import APIRouter, File, Form, HTTPException, Depends, Body, Path, Query, Request, BackgroundTasks, UploadFile -from fastapi.responses import FileResponse, JSONResponse, StreamingResponse +from fastapi import APIRouter, File, Depends, Body, Path, Query, UploadFile +from fastapi.responses import JSONResponse, StreamingResponse from markitdown import MarkItDown, StreamInfo import backstory_traceback as backstory_traceback import defines -from agents.generate_resume import GenerateResume from agents.base import CandidateEntity -from utils.helpers import create_job_from_content, filter_and_paginate, get_document_type_from_filename, get_skill_cache_key, get_requirements_list -from database.manager import RedisDatabase, redis_manager +from utils.helpers import create_job_from_content, filter_and_paginate, get_document_type_from_filename +from database.manager import RedisDatabase from logger import logger from models import ( - MOCK_UUID, ApiActivityType, ApiMessageType, ApiStatusType, CandidateAI, ChatContextType, ChatMessage, ChatMessageError, ChatMessageRagSearch, ChatMessageResume, ChatMessageSkillAssessment, ChatMessageStatus, ChatMessageStreaming, ChatMessageUser, ChatSession, Document, DocumentContentResponse, DocumentListResponse, DocumentMessage, DocumentOptions, DocumentType, DocumentUpdateRequest, Job, JobRequirements, JobRequirementsMessage, LoginRequest, CreateCandidateRequest, CreateEmployerRequest, - Candidate, Employer, Guest, AuthResponse, - MFARequest, MFAData, MFAVerifyRequest, - EmailVerificationRequest, RAGDocumentRequest, RagContentMetadata, RagContentResponse, ResendVerificationRequest, - MFARequestResponse, MFARequestResponse, Resume, ResumeMessage, SkillAssessment, UserType + MOCK_UUID, ApiActivityType, ApiStatusType, ChatContextType, ChatMessage, ChatMessageError, ChatMessageStatus, DocumentType, Job, JobRequirementsMessage, Candidate, Employer ) from utils.dependencies import ( - get_current_admin, get_database, get_current_user, get_current_user_or_guest, - create_access_token, verify_token_with_blacklist, prometheus_collector + get_current_admin, get_database, get_current_user ) from utils.responses import create_paginated_response, create_success_response, create_error_response import utils.llm_proxy as llm_manager diff --git a/src/backend/routes/resumes.py b/src/backend/routes/resumes.py index 0ce1403..9b0220c 100644 --- a/src/backend/routes/resumes.py +++ b/src/backend/routes/resumes.py @@ -2,38 +2,22 @@ Resume Routes """ import json -import pathlib -import re -import shutil -import jwt -import secrets -import uuid -import os -from datetime import datetime, timedelta, timezone, UTC -from typing import Any, Dict, List, Optional +from datetime import datetime, UTC +from typing import List -from fastapi import APIRouter, File, Form, HTTPException, Depends, Body, Path, Query, Request, BackgroundTasks, UploadFile -from fastapi.responses import FileResponse, JSONResponse, StreamingResponse -from pydantic import BaseModel, ValidationError +from fastapi import APIRouter, HTTPException, Depends, Body, Path, Query +from fastapi.responses import StreamingResponse import backstory_traceback as backstory_traceback -from utils.helpers import filter_and_paginate, get_document_type_from_filename, get_skill_cache_key, get_requirements_list -from database.manager import RedisDatabase, redis_manager +from database.manager import RedisDatabase from logger import logger from models import ( - MOCK_UUID, ApiActivityType, ApiMessageType, ApiStatusType, CandidateAI, ChatContextType, ChatMessageError, ChatMessageRagSearch, ChatMessageResume, ChatMessageSkillAssessment, ChatMessageStatus, ChatMessageStreaming, ChatMessageUser, ChatSession, Document, DocumentContentResponse, DocumentListResponse, DocumentMessage, DocumentOptions, DocumentType, DocumentUpdateRequest, Job, JobRequirements, LoginRequest, CreateCandidateRequest, CreateEmployerRequest, - Candidate, Employer, Guest, AuthResponse, - MFARequest, MFAData, MFAVerifyRequest, - EmailVerificationRequest, RAGDocumentRequest, RagContentMetadata, RagContentResponse, ResendVerificationRequest, - MFARequestResponse, MFARequestResponse, Resume, ResumeMessage, SkillAssessment, UserType + MOCK_UUID, ChatMessageError, Job, Candidate, Resume, ResumeMessage ) from utils.dependencies import ( - get_current_admin, get_database, get_current_user, get_current_user_or_guest, - create_access_token, verify_token_with_blacklist, prometheus_collector + get_database, get_current_user ) -from utils.responses import create_paginated_response, create_success_response, create_error_response -import utils.llm_proxy as llm_manager -from utils.rate_limiter import get_rate_limiter +from utils.responses import create_success_response # Create router for authentication endpoints router = APIRouter(prefix="/resumes", tags=["resumes"]) diff --git a/src/backend/routes/system.py b/src/backend/routes/system.py index 5b2f473..b13eb0e 100644 --- a/src/backend/routes/system.py +++ b/src/backend/routes/system.py @@ -1,39 +1,11 @@ """ Health/system routes """ -import json -from datetime import datetime, UTC -from fastapi import APIRouter, Depends, Body, HTTPException, Path, Request -from fastapi.responses import JSONResponse -from pydantic import BaseModel, EmailStr, ValidationError, field_validator +from fastapi import APIRouter, Depends, HTTPException, Request -from auth_utils import AuthenticationManager, SecurityConfig -import backstory_traceback as backstory_traceback -from utils.rate_limiter import RateLimiter -from database.manager import RedisDatabase, redis_manager, Redis -from device_manager import DeviceManager -from email_service import VerificationEmailRateLimiter, email_service -from logger import logger -from models import ( - LoginRequest, CreateCandidateRequest, CreateEmployerRequest, - Candidate, Employer, Guest, AuthResponse, - MFARequest, MFAData, MFAVerifyRequest, - EmailVerificationRequest, ResendVerificationRequest, - MFARequestResponse, MFARequestResponse -) -from utils.dependencies import ( - get_current_admin, get_database, get_current_user, get_current_user_or_guest, - create_access_token, verify_token_with_blacklist -) -from utils.responses import create_success_response, create_error_response -from utils.rate_limiter import get_rate_limiter -from auth_utils import ( - AuthenticationManager, - validate_password_strength, - sanitize_login_input, - SecurityConfig -) +from database.manager import redis_manager, Redis +from utils.responses import create_success_response # Create router for authentication endpoints router = APIRouter(prefix="/system", tags=["system"]) diff --git a/src/backend/routes/users.py b/src/backend/routes/users.py index 29ce87c..aca453b 100644 --- a/src/backend/routes/users.py +++ b/src/backend/routes/users.py @@ -1,38 +1,19 @@ """ Job Routes """ -import io -import json -import pathlib -import re -import shutil -import jwt -import secrets -import uuid -import os -from datetime import datetime, timedelta, timezone, UTC -from typing import Any, Dict, List, Optional -from fastapi import APIRouter, File, Form, HTTPException, Depends, Body, Path, Query, Request, BackgroundTasks, UploadFile -from fastapi.responses import FileResponse, JSONResponse, StreamingResponse +from fastapi import APIRouter, Depends, Path +from fastapi.responses import JSONResponse -from database.manager import RedisDatabase, redis_manager -from device_manager import DeviceManager -from email_service import VerificationEmailRateLimiter, email_service +from database.manager import RedisDatabase from logger import logger from models import ( - MOCK_UUID, ApiActivityType, ApiMessageType, ApiStatusType, BaseUserWithType, CandidateAI, ChatContextType, ChatMessageError, ChatMessageRagSearch, ChatMessageResume, ChatMessageSkillAssessment, ChatMessageStatus, ChatMessageStreaming, ChatMessageUser, ChatSession, Document, DocumentContentResponse, DocumentListResponse, DocumentMessage, DocumentOptions, DocumentType, DocumentUpdateRequest, Job, JobRequirements, LoginRequest, CreateCandidateRequest, CreateEmployerRequest, - Candidate, Employer, Guest, AuthResponse, - MFARequest, MFAData, MFAVerifyRequest, - EmailVerificationRequest, RAGDocumentRequest, RagContentMetadata, RagContentResponse, ResendVerificationRequest, - MFARequestResponse, MFARequestResponse, Resume, ResumeMessage, SkillAssessment, UserType + BaseUserWithType ) from utils.dependencies import ( - get_current_admin, get_database, get_current_user, get_current_user_or_guest, - create_access_token, verify_token_with_blacklist, prometheus_collector + get_database ) -from utils.rate_limiter import get_rate_limiter -from utils.responses import create_paginated_response, create_success_response, create_error_response +from utils.responses import create_success_response, create_error_response # Create router for job endpoints router = APIRouter(prefix="/users", tags=["users"]) diff --git a/src/backend/tools/basetools.py b/src/backend/tools/basetools.py index d90360c..04170b5 100644 --- a/src/backend/tools/basetools.py +++ b/src/backend/tools/basetools.py @@ -1,11 +1,10 @@ import os -from pydantic import BaseModel, Field, model_validator -from typing import List, Optional, Generator, ClassVar, Any, Dict +from pydantic import BaseModel +from typing import List, Optional, Any, Dict from datetime import datetime from typing import ( Any, ) -from typing_extensions import Annotated from bs4 import BeautifulSoup diff --git a/src/backend/utils/__init__.py b/src/backend/utils/__init__.py index 7752e2e..7fde0bd 100644 --- a/src/backend/utils/__init__.py +++ b/src/backend/utils/__init__.py @@ -1,54 +1,3 @@ """ Utils package - Utility functions and dependencies -""" - -# Import commonly used utilities for easy access -from .dependencies import ( - get_database, - get_current_user, - get_current_user_or_guest, - get_current_admin, - create_access_token, - verify_token_with_blacklist -) - -from .responses import ( - create_success_response, - create_error_response, - create_paginated_response -) - -from .helpers import ( - filter_and_paginate, - stream_agent_response, - get_candidate_files_dir, - get_document_type_from_filename, - get_skill_cache_key -) - -from .rate_limiter import ( - get_rate_limiter -) - -__all__ = [ - # Dependencies - "get_database", - "get_current_user", - "get_current_user_or_guest", - "get_current_admin", - "get_rate_limiter", - "create_access_token", - "verify_token_with_blacklist", - - # Responses - "create_success_response", - "create_error_response", - "create_paginated_response", - - # Helpers - "filter_and_paginate", - "stream_agent_response", - "get_candidate_files_dir", - "get_document_type_from_filename", - "get_skill_cache_key" -] \ No newline at end of file +""" \ No newline at end of file diff --git a/src/backend/utils/auth_utils.py b/src/backend/utils/auth_utils.py index 0a31dac..d2aa785 100644 --- a/src/backend/utils/auth_utils.py +++ b/src/backend/utils/auth_utils.py @@ -3,7 +3,7 @@ Secure Authentication Utilities Provides password hashing, verification, and security features """ - +from __future__ import annotations import traceback import bcrypt import secrets diff --git a/src/backend/utils/dependencies.py b/src/backend/utils/dependencies.py index 4941f8a..a72de8b 100644 --- a/src/backend/utils/dependencies.py +++ b/src/backend/utils/dependencies.py @@ -4,7 +4,7 @@ Shared dependencies for FastAPI routes from __future__ import annotations import jwt import os -from datetime import datetime, timedelta, timezone, UTC +from datetime import datetime, timedelta, UTC from typing import Optional from fastapi import HTTPException, Depends diff --git a/src/backend/utils/helpers.py b/src/backend/utils/helpers.py index a58ed93..ae573b8 100644 --- a/src/backend/utils/helpers.py +++ b/src/backend/utils/helpers.py @@ -4,7 +4,6 @@ Helper functions shared across routes import asyncio import hashlib import json -import os import pathlib from datetime import datetime, UTC from typing import Any, Dict, List, Optional, Tuple @@ -108,7 +107,6 @@ async def stream_agent_response(chat_agent, user_message, chat_session_data=None final_message = None import utils.llm_proxy as llm_manager - import agents async for generated_message in chat_agent.generate( llm=llm_manager.get_llm(), @@ -203,7 +201,7 @@ def get_skill_cache_key(candidate_id: str, skill: str) -> str: async def reformat_as_markdown(database, candidate_entity, content: str): """Reformat content as markdown using AI agent""" - from models import ChatContextType, MOCK_UUID, ApiStatusType, ChatMessageError, ChatMessageStatus, ApiActivityType, ChatMessage + from models import ChatContextType, MOCK_UUID, ChatMessageError, ChatMessageStatus, ApiActivityType, ChatMessage import utils.llm_proxy as llm_manager chat_agent = candidate_entity.get_or_create_agent(agent_type=ChatContextType.JOB_REQUIREMENTS) diff --git a/src/backend/utils/llm_proxy.py b/src/backend/utils/llm_proxy.py index b756c0b..f783b09 100644 --- a/src/backend/utils/llm_proxy.py +++ b/src/backend/utils/llm_proxy.py @@ -3,7 +3,6 @@ from typing import Dict, List, Any, AsyncGenerator, Optional, Union from pydantic import BaseModel, Field from enum import Enum import asyncio -import json from dataclasses import dataclass import os import defines @@ -145,7 +144,6 @@ class BaseLLMAdapter(ABC): **kwargs ) -> Union[ChatResponse, AsyncGenerator[ChatResponse, None]]: """Send chat messages and get response""" - pass @abstractmethod async def generate( @@ -156,7 +154,6 @@ class BaseLLMAdapter(ABC): **kwargs ) -> Union[ChatResponse, AsyncGenerator[ChatResponse, None]]: """Generate text from prompt""" - pass @abstractmethod async def embeddings( @@ -166,12 +163,10 @@ class BaseLLMAdapter(ABC): **kwargs ) -> EmbeddingResponse: """Generate embeddings for input text(s)""" - pass @abstractmethod async def list_models(self) -> List[str]: """List available models""" - pass class OllamaAdapter(BaseLLMAdapter): """Adapter for Ollama with enhanced statistics""" diff --git a/src/backend/utils/rate_limiter.py b/src/backend/utils/rate_limiter.py index eee96a2..267698b 100644 --- a/src/backend/utils/rate_limiter.py +++ b/src/backend/utils/rate_limiter.py @@ -3,10 +3,8 @@ Rate limiting utilities for guest and authenticated users """ from __future__ import annotations from functools import wraps -import json -import time from datetime import datetime, timedelta, UTC -from typing import Callable, Dict, Optional, Tuple, Any +from typing import Callable, Dict, Optional, Any from fastapi import Depends, HTTPException, Request from pydantic import BaseModel # type: ignore from database.manager import RedisDatabase