| import os |
| import sys |
| from dotenv import load_dotenv |
|
|
| load_dotenv(override=True) |
|
|
| |
| from src.crew import build_crew |
|
|
|
|
| def validate_cv_path(cv_path: str) -> str: |
| """Validate the CV file path exists and is a supported format.""" |
| if not cv_path: |
| print("β CV path cannot be empty.") |
| sys.exit(1) |
|
|
| if not os.path.isfile(cv_path): |
| print(f"β File not found: {cv_path}") |
| sys.exit(1) |
|
|
| if not cv_path.lower().endswith((".pdf", ".docx")): |
| print(f"β Unsupported file format. Only .pdf and .docx are supported.") |
| sys.exit(1) |
|
|
| return cv_path |
|
|
|
|
| def validate_not_empty(value: str, field_name: str) -> str: |
| """Ensure a required input is not empty.""" |
| if not value: |
| print(f"β {field_name} cannot be empty.") |
| sys.exit(1) |
| return value |
|
|
|
|
| def validate_env(): |
| missing = [k for k in ("GROQ_API_KEY", "SERPER_API_KEY") if not os.getenv(k)] |
| if missing: |
| for key in missing: |
| print(f"β Missing required environment variable: {key}") |
| print(" Set them in your .env file (see .env.example).") |
| sys.exit(1) |
|
|
|
|
| def run(): |
| validate_env() |
|
|
| print("\nπ Job Application Intelligence Agent\n") |
| print("=" * 40) |
|
|
| cv_path = input("Enter path to your CV (PDF/DOCX): ").strip() |
| cv_path = validate_cv_path(cv_path) |
|
|
| jd_source = input("Enter LinkedIn job URL or paste JD text: ").strip() |
| jd_source = validate_not_empty(jd_source, "Job description source") |
|
|
| company_name = input("Enter company name: ").strip() |
| company_name = validate_not_empty(company_name, "Company name") |
|
|
| city = input("Enter company city: ").strip() |
| city = validate_not_empty(city, "City") |
|
|
| crew = build_crew( |
| cv_path=cv_path, |
| jd_source=jd_source, |
| company_name=company_name, |
| city=city |
| ) |
|
|
| print("\nβ³ Starting analysis...\n") |
|
|
| try: |
| result = crew.kickoff() |
| print("\nβ
Done! Here's your full report:\n") |
|
|
| |
| sections = [ |
| ("π SKILL GAP ANALYSIS", 3), |
| ("βοΈ CV OPTIMIZATION SUGGESTIONS", 4), |
| ("π¨ OUTREACH MESSAGES", 5), |
| ] |
| outputs = result.tasks_output or [] |
| for title, idx in sections: |
| if idx < len(outputs): |
| print("\n" + "=" * 60) |
| print(f" {title}") |
| print("=" * 60) |
| print(outputs[idx].raw) |
|
|
| return result |
| except Exception as e: |
| error_msg = str(e) |
|
|
| if "rate_limit" in error_msg.lower() or "ratelimit" in error_msg.lower(): |
| print("\n" + "=" * 50) |
| print("β RATE LIMIT ERROR") |
| print("=" * 50) |
| print("The Groq API token limit was exceeded.") |
| print("Options:") |
| print(" 1. Wait 15-20 minutes and try again") |
| print(" 2. Upgrade to Groq Dev Tier at https://console.groq.com/settings/billing") |
| print(" 3. Paste the JD text directly instead of a URL (uses fewer tokens)") |
| print("=" * 50 + "\n") |
| else: |
| print("\n" + "=" * 50) |
| print("β PIPELINE ERROR") |
| print("=" * 50) |
| print(f"Something went wrong: {error_msg[:300]}") |
| print("=" * 50 + "\n") |
|
|
| return None |
|
|
|
|
| if __name__ == "__main__": |
| run() |
|
|