jobagent 1.0.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. jobagent-1.0.5/LICENSE +21 -0
  2. jobagent-1.0.5/MANIFEST.in +25 -0
  3. jobagent-1.0.5/PKG-INFO +198 -0
  4. jobagent-1.0.5/README.md +160 -0
  5. jobagent-1.0.5/agents/__init__.py +10 -0
  6. jobagent-1.0.5/agents/form_agent.py +327 -0
  7. jobagent-1.0.5/agents/fsm_runner.py +534 -0
  8. jobagent-1.0.5/agents/job_evaluator.py +271 -0
  9. jobagent-1.0.5/apply_jobs.py +532 -0
  10. jobagent-1.0.5/automation/__init__.py +1 -0
  11. jobagent-1.0.5/automation/pages/__init__.py +13 -0
  12. jobagent-1.0.5/automation/pages/base_page.py +95 -0
  13. jobagent-1.0.5/automation/pages/easy_apply_modal.py +549 -0
  14. jobagent-1.0.5/automation/pages/job_details_page.py +164 -0
  15. jobagent-1.0.5/automation/pages/job_search_page.py +185 -0
  16. jobagent-1.0.5/automation/pages/login_page.py +213 -0
  17. jobagent-1.0.5/automation/pages/naukri_page.py +326 -0
  18. jobagent-1.0.5/config/__init__.py +1 -0
  19. jobagent-1.0.5/config/candidate_profile.template.json +37 -0
  20. jobagent-1.0.5/config/settings.py +70 -0
  21. jobagent-1.0.5/jobagent.egg-info/PKG-INFO +198 -0
  22. jobagent-1.0.5/jobagent.egg-info/SOURCES.txt +44 -0
  23. jobagent-1.0.5/jobagent.egg-info/dependency_links.txt +1 -0
  24. jobagent-1.0.5/jobagent.egg-info/entry_points.txt +2 -0
  25. jobagent-1.0.5/jobagent.egg-info/requires.txt +18 -0
  26. jobagent-1.0.5/jobagent.egg-info/top_level.txt +7 -0
  27. jobagent-1.0.5/main.py +248 -0
  28. jobagent-1.0.5/models/__init__.py +23 -0
  29. jobagent-1.0.5/models/application.py +27 -0
  30. jobagent-1.0.5/models/evaluation.py +31 -0
  31. jobagent-1.0.5/models/form.py +37 -0
  32. jobagent-1.0.5/models/job.py +23 -0
  33. jobagent-1.0.5/models/profile.py +29 -0
  34. jobagent-1.0.5/pyproject.toml +68 -0
  35. jobagent-1.0.5/requirements.txt +10 -0
  36. jobagent-1.0.5/services/__init__.py +11 -0
  37. jobagent-1.0.5/services/chat_agent.py +768 -0
  38. jobagent-1.0.5/services/db_service.py +247 -0
  39. jobagent-1.0.5/services/llm_service.py +568 -0
  40. jobagent-1.0.5/services/memory_service.py +124 -0
  41. jobagent-1.0.5/services/profile_loader.py +169 -0
  42. jobagent-1.0.5/services/resume_reviewer.py +147 -0
  43. jobagent-1.0.5/services/resume_service.py +118 -0
  44. jobagent-1.0.5/services/setup_service.py +825 -0
  45. jobagent-1.0.5/setup.cfg +4 -0
  46. jobagent-1.0.5/setup.py +4 -0
jobagent-1.0.5/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Yaswanth Asapu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,25 @@
1
+ include README.md
2
+ include LICENSE
3
+ include requirements.txt
4
+ include pyproject.toml
5
+ include config/candidate_profile.template.json
6
+
7
+ # Exclude sensitive, local-only, and private data
8
+ exclude .env
9
+ exclude .env.*
10
+ exclude applications.db
11
+ exclude sharepoint_screen.png
12
+ exclude AmazonCartMobileApp
13
+ exclude jobagent.bat
14
+ exclude jobagent.ps1
15
+ exclude config/candidate_profile.json
16
+ exclude config/agent_memory.json
17
+ exclude config/resume.pdf
18
+
19
+ recursive-exclude .browser_context *
20
+ recursive-exclude screenshots *
21
+ recursive-exclude tests *
22
+ recursive-exclude .pytest_cache *
23
+ recursive-exclude desktopapplication *
24
+ recursive-exclude * __pycache__
25
+ recursive-exclude * *.py[co]
@@ -0,0 +1,198 @@
1
+ Metadata-Version: 2.4
2
+ Name: jobagent
3
+ Version: 1.0.5
4
+ Summary: Autonomous Multi-Platform AI Job Application Agent for LinkedIn and Naukri
5
+ Author-email: Yaswanth Asapu <yaswanth901@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/yaswanth901/jobagent
8
+ Keywords: job-application,job-agent,linkedin,naukri,automation,playwright,ai,gemini
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: End Users/Desktop
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Office/Business
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: playwright>=1.40.0
22
+ Requires-Dist: pydantic>=2.5.0
23
+ Requires-Dist: pydantic-settings>=2.0.0
24
+ Requires-Dist: rich>=13.0.0
25
+ Requires-Dist: SQLAlchemy>=2.0.0
26
+ Requires-Dist: aiosqlite>=0.19.0
27
+ Requires-Dist: httpx>=0.25.0
28
+ Requires-Dist: python-dotenv>=1.0.0
29
+ Requires-Dist: reportlab>=4.0.0
30
+ Requires-Dist: pypdf>=3.0.0
31
+ Requires-Dist: google-genai>=0.1.0
32
+ Provides-Extra: openai
33
+ Requires-Dist: openai>=1.0.0; extra == "openai"
34
+ Provides-Extra: all
35
+ Requires-Dist: google-genai>=0.1.0; extra == "all"
36
+ Requires-Dist: openai>=1.0.0; extra == "all"
37
+ Dynamic: license-file
38
+
39
+ # Hybrid Browser AI Agent for LinkedIn Easy Apply
40
+
41
+ A Python-based browser automation AI agent built with **Playwright**, a **Finite State Machine (FSM)**, **Page Object Model (POM)**, and an **LLM-driven Semantic Matching & Form Interpretation Engine** with a strict **Human-in-the-Loop (HITL)** approval gate.
42
+
43
+ ---
44
+
45
+ ## Architecture Overview
46
+
47
+ ```
48
+ d:\Gravity\
49
+ ├── config/
50
+ │ ├── candidate_profile.json # Single source of truth for candidate data
51
+ │ └── settings.py # Pydantic BaseSettings (.env loader)
52
+ ├── models/
53
+ │ ├── profile.py # Pydantic models for Candidate Profile
54
+ │ ├── job.py # JobCardSummary and JobDetails schemas
55
+ │ ├── evaluation.py # MatchBreakdown and JobEvaluationResult schemas
56
+ │ ├── form.py # FormField, FormStep, ApplicationSummary schemas
57
+ │ └── application.py # Database ApplicationRecord and Status
58
+ ├── services/
59
+ │ ├── profile_loader.py # Profile reader & dynamic field calculation
60
+ │ ├── db_service.py # SQLite/PostgreSQL persistence & deduplication
61
+ │ ├── llm_service.py # Multi-backend LLM client & NLP heuristic engine
62
+ │ └── resume_service.py # Resume path manager & reportlab PDF generator
63
+ ├── automation/
64
+ │ └── pages/
65
+ │ ├── base_page.py # Playwright POM base with anti-detection & typing jitter
66
+ │ ├── login_page.py # Auth state verification & manual checkpoint polling
67
+ │ ├── job_search_page.py # Easy Apply search navigation & job card extraction
68
+ │ ├── job_details_page.py # Description extraction & Easy Apply launcher
69
+ │ └── easy_apply_modal.py # Modal step traversal, dynamic filling, review
70
+ ├── agents/
71
+ │ ├── job_evaluator.py # LLM semantic fit scorer & experience analysis
72
+ │ ├── form_agent.py # Dynamic form question interpreter & HITL routing
73
+ │ └── fsm_runner.py # Finite State Machine orchestrator
74
+ ├── tests/ # Pytest automated test suite
75
+ ├── main.py # Rich CLI runner & dashboard
76
+ ├── requirements.txt # Python dependencies
77
+ └── .env.example # Example environment variables
78
+ ```
79
+
80
+ ---
81
+
82
+ ## Finite State Machine (FSM) Lifecycle
83
+
84
+ ```mermaid
85
+ stateDiagram-v2
86
+ [*] --> INIT
87
+ INIT --> LAUNCH_BROWSER: Load profile & init database
88
+ LAUNCH_BROWSER --> CHECK_LOGIN: Launch persistent Chromium context
89
+ CHECK_LOGIN --> CHECK_LOGIN: Pause & wait if CAPTCHA / 2FA / Login needed
90
+ CHECK_LOGIN --> SEARCH_JOBS: Authenticated
91
+ SEARCH_JOBS --> EXTRACT_CARDS: Search with f_AL=true (Easy Apply)
92
+ EXTRACT_CARDS --> EVALUATE_FIT: Filter out applied jobs
93
+ EVALUATE_FIT --> NEXT_JOB: Score < min_score OR Experience Reject
94
+ EVALUATE_FIT --> FILL_FORM: Score >= min_score -> Launch Modal
95
+ FILL_FORM --> AWAIT_APPROVAL: Reached final review step
96
+ AWAIT_APPROVAL --> SUBMIT: User Approved [y]
97
+ AWAIT_APPROVAL --> NEXT_JOB: User Skipped [n]
98
+ SUBMIT --> TRACK: Click submit
99
+ TRACK --> NEXT_JOB: Persist to applications.db
100
+ NEXT_JOB --> EXTRACT_CARDS: Next unapplied card
101
+ NEXT_JOB --> [*]: Max jobs reached or finished
102
+ ```
103
+
104
+ ---
105
+
106
+ ## Key Features & Adherence to Requirements
107
+
108
+ 1. **Finite State Machine & Page Object Model**:
109
+ - Clean separation between Playwright UI interactions (`automation/pages/`), agent decision logic (`agents/`), data storage (`services/`), and schema contracts (`models/`).
110
+
111
+ 2. **Stealth & Persistent Browser Context**:
112
+ - Uses Chromium in non-headless mode by default (`HEADLESS=false`).
113
+ - Uses persistent profile directory (`.browser_context/`) to preserve cookies, sessions, and tokens.
114
+ - **Zero Credential Storage**: LinkedIn passwords are never stored in code, `.env`, or logs.
115
+ - **No Automated Solvers**: If LinkedIn prompts with 2FA, OTP, or CAPTCHA, the agent halts, prints an alert to the terminal, and waits for manual completion in the open browser before resuming.
116
+
117
+ 3. **Candidate Profile as Single Source of Truth**:
118
+ - Located at `config/candidate_profile.json`.
119
+ - All downstream calculations (compensation, experience years, notice period, skill lookups) dynamically read from this profile without hardcoded values.
120
+
121
+ 4. **Semantic LLM Fit Scoring**:
122
+ - Evaluates:
123
+ - **Experience Match**: Candidate has 4 years; if job asks for 5–8 years, score is downgraded proportionally; if >8 years or Director/Lead, hard rejection.
124
+ - **Skill Match**: Semantic clustering recognizing synonyms (e.g. RestAssured/Postman <-> API testing, Selenium/Playwright <-> Web automation).
125
+ - **Role Match**: Checks relevance against preferred roles (QA Automation Engineer, SDET, etc.).
126
+ - Skips postings when `overall_score < minimum_match_score` (70%).
127
+
128
+ 5. **Dynamic Form Filling**:
129
+ - Maps standard personal details, current/expected CTC, 60 days notice period, and skill-specific experience years.
130
+ - Handles dropdowns, radio groups, and file uploads.
131
+ - Flags sensitive/ambiguous declarations (clearance, disability, citizenship) for explicit HITL prompt.
132
+
133
+ 6. **Human-in-the-Loop (HITL) Gate**:
134
+ - Pauses on the final review step of the modal.
135
+ - Renders a Rich summary table (Job Title, Company, Match Score, File Uploaded).
136
+ - Requires explicit user approval (`[y] Approve & Submit / [n] Skip / [q] Quit`) before clicking the submit button.
137
+
138
+ 7. **Application Tracking & Deduplication**:
139
+ - Async SQLite database (`applications.db`) with an `applications` table.
140
+ - Queries by `job_id` or `job_url` + `company` before opening any job card to avoid duplicates.
141
+
142
+ ---
143
+
144
+ ## Installation & Setup
145
+
146
+ 1. **Install Dependencies**:
147
+ ```bash
148
+ pip install -r requirements.txt
149
+ ```
150
+
151
+ 2. **Initialize Playwright Browser**:
152
+ ```bash
153
+ playwright install chromium
154
+ ```
155
+
156
+ 3. **Configure Environment (Optional)**:
157
+ ```bash
158
+ cp .env.example .env
159
+ ```
160
+ Add your `OPENAI_API_KEY` or `GEMINI_API_KEY` if you want live cloud LLM reasoning. If left empty, the built-in deterministic NLP extraction and semantic scoring engine will run offline automatically.
161
+
162
+ ---
163
+
164
+ ## Usage Guide
165
+
166
+ ### 1. Dry Run (Recommended for testing without submitting)
167
+ Simulates the workflow, extracts cards, computes fit scores, fills forms up to the final review step, and tests the HITL prompt without submitting:
168
+ ```bash
169
+ python main.py --keyword "QA Automation Engineer" --location "Hyderabad" --max-jobs 3 --dry-run
170
+ ```
171
+
172
+ ### 2. Live Apply Mode
173
+ Executes the live workflow with non-headless browser:
174
+ ```bash
175
+ python main.py --keyword "SDET" --location "Hyderabad" --min-score 70 --max-jobs 5
176
+ ```
177
+
178
+ ### 3. CLI Command Options
179
+ ```
180
+ --keyword Job title or search keyword (default: "QA Automation Engineer")
181
+ --location Search location (default: "Hyderabad")
182
+ --max-jobs Maximum applications to process (default: 10)
183
+ --min-score Minimum fit score required to proceed (default: 70.0)
184
+ --headless Run Chromium in headless mode (default: False)
185
+ --dry-run Fill forms to review step without clicking final submit
186
+ --auto-approve Bypass interactive HITL prompt at review step
187
+ --profile Custom path to candidate_profile.json
188
+ --log-level Logging level [DEBUG, INFO, WARNING, ERROR] (default: INFO)
189
+ ```
190
+
191
+ ---
192
+
193
+ ## Running the Automated Test Suite
194
+
195
+ Execute pytest across all test modules:
196
+ ```bash
197
+ pytest tests/ -v
198
+ ```
@@ -0,0 +1,160 @@
1
+ # Hybrid Browser AI Agent for LinkedIn Easy Apply
2
+
3
+ A Python-based browser automation AI agent built with **Playwright**, a **Finite State Machine (FSM)**, **Page Object Model (POM)**, and an **LLM-driven Semantic Matching & Form Interpretation Engine** with a strict **Human-in-the-Loop (HITL)** approval gate.
4
+
5
+ ---
6
+
7
+ ## Architecture Overview
8
+
9
+ ```
10
+ d:\Gravity\
11
+ ├── config/
12
+ │ ├── candidate_profile.json # Single source of truth for candidate data
13
+ │ └── settings.py # Pydantic BaseSettings (.env loader)
14
+ ├── models/
15
+ │ ├── profile.py # Pydantic models for Candidate Profile
16
+ │ ├── job.py # JobCardSummary and JobDetails schemas
17
+ │ ├── evaluation.py # MatchBreakdown and JobEvaluationResult schemas
18
+ │ ├── form.py # FormField, FormStep, ApplicationSummary schemas
19
+ │ └── application.py # Database ApplicationRecord and Status
20
+ ├── services/
21
+ │ ├── profile_loader.py # Profile reader & dynamic field calculation
22
+ │ ├── db_service.py # SQLite/PostgreSQL persistence & deduplication
23
+ │ ├── llm_service.py # Multi-backend LLM client & NLP heuristic engine
24
+ │ └── resume_service.py # Resume path manager & reportlab PDF generator
25
+ ├── automation/
26
+ │ └── pages/
27
+ │ ├── base_page.py # Playwright POM base with anti-detection & typing jitter
28
+ │ ├── login_page.py # Auth state verification & manual checkpoint polling
29
+ │ ├── job_search_page.py # Easy Apply search navigation & job card extraction
30
+ │ ├── job_details_page.py # Description extraction & Easy Apply launcher
31
+ │ └── easy_apply_modal.py # Modal step traversal, dynamic filling, review
32
+ ├── agents/
33
+ │ ├── job_evaluator.py # LLM semantic fit scorer & experience analysis
34
+ │ ├── form_agent.py # Dynamic form question interpreter & HITL routing
35
+ │ └── fsm_runner.py # Finite State Machine orchestrator
36
+ ├── tests/ # Pytest automated test suite
37
+ ├── main.py # Rich CLI runner & dashboard
38
+ ├── requirements.txt # Python dependencies
39
+ └── .env.example # Example environment variables
40
+ ```
41
+
42
+ ---
43
+
44
+ ## Finite State Machine (FSM) Lifecycle
45
+
46
+ ```mermaid
47
+ stateDiagram-v2
48
+ [*] --> INIT
49
+ INIT --> LAUNCH_BROWSER: Load profile & init database
50
+ LAUNCH_BROWSER --> CHECK_LOGIN: Launch persistent Chromium context
51
+ CHECK_LOGIN --> CHECK_LOGIN: Pause & wait if CAPTCHA / 2FA / Login needed
52
+ CHECK_LOGIN --> SEARCH_JOBS: Authenticated
53
+ SEARCH_JOBS --> EXTRACT_CARDS: Search with f_AL=true (Easy Apply)
54
+ EXTRACT_CARDS --> EVALUATE_FIT: Filter out applied jobs
55
+ EVALUATE_FIT --> NEXT_JOB: Score < min_score OR Experience Reject
56
+ EVALUATE_FIT --> FILL_FORM: Score >= min_score -> Launch Modal
57
+ FILL_FORM --> AWAIT_APPROVAL: Reached final review step
58
+ AWAIT_APPROVAL --> SUBMIT: User Approved [y]
59
+ AWAIT_APPROVAL --> NEXT_JOB: User Skipped [n]
60
+ SUBMIT --> TRACK: Click submit
61
+ TRACK --> NEXT_JOB: Persist to applications.db
62
+ NEXT_JOB --> EXTRACT_CARDS: Next unapplied card
63
+ NEXT_JOB --> [*]: Max jobs reached or finished
64
+ ```
65
+
66
+ ---
67
+
68
+ ## Key Features & Adherence to Requirements
69
+
70
+ 1. **Finite State Machine & Page Object Model**:
71
+ - Clean separation between Playwright UI interactions (`automation/pages/`), agent decision logic (`agents/`), data storage (`services/`), and schema contracts (`models/`).
72
+
73
+ 2. **Stealth & Persistent Browser Context**:
74
+ - Uses Chromium in non-headless mode by default (`HEADLESS=false`).
75
+ - Uses persistent profile directory (`.browser_context/`) to preserve cookies, sessions, and tokens.
76
+ - **Zero Credential Storage**: LinkedIn passwords are never stored in code, `.env`, or logs.
77
+ - **No Automated Solvers**: If LinkedIn prompts with 2FA, OTP, or CAPTCHA, the agent halts, prints an alert to the terminal, and waits for manual completion in the open browser before resuming.
78
+
79
+ 3. **Candidate Profile as Single Source of Truth**:
80
+ - Located at `config/candidate_profile.json`.
81
+ - All downstream calculations (compensation, experience years, notice period, skill lookups) dynamically read from this profile without hardcoded values.
82
+
83
+ 4. **Semantic LLM Fit Scoring**:
84
+ - Evaluates:
85
+ - **Experience Match**: Candidate has 4 years; if job asks for 5–8 years, score is downgraded proportionally; if >8 years or Director/Lead, hard rejection.
86
+ - **Skill Match**: Semantic clustering recognizing synonyms (e.g. RestAssured/Postman <-> API testing, Selenium/Playwright <-> Web automation).
87
+ - **Role Match**: Checks relevance against preferred roles (QA Automation Engineer, SDET, etc.).
88
+ - Skips postings when `overall_score < minimum_match_score` (70%).
89
+
90
+ 5. **Dynamic Form Filling**:
91
+ - Maps standard personal details, current/expected CTC, 60 days notice period, and skill-specific experience years.
92
+ - Handles dropdowns, radio groups, and file uploads.
93
+ - Flags sensitive/ambiguous declarations (clearance, disability, citizenship) for explicit HITL prompt.
94
+
95
+ 6. **Human-in-the-Loop (HITL) Gate**:
96
+ - Pauses on the final review step of the modal.
97
+ - Renders a Rich summary table (Job Title, Company, Match Score, File Uploaded).
98
+ - Requires explicit user approval (`[y] Approve & Submit / [n] Skip / [q] Quit`) before clicking the submit button.
99
+
100
+ 7. **Application Tracking & Deduplication**:
101
+ - Async SQLite database (`applications.db`) with an `applications` table.
102
+ - Queries by `job_id` or `job_url` + `company` before opening any job card to avoid duplicates.
103
+
104
+ ---
105
+
106
+ ## Installation & Setup
107
+
108
+ 1. **Install Dependencies**:
109
+ ```bash
110
+ pip install -r requirements.txt
111
+ ```
112
+
113
+ 2. **Initialize Playwright Browser**:
114
+ ```bash
115
+ playwright install chromium
116
+ ```
117
+
118
+ 3. **Configure Environment (Optional)**:
119
+ ```bash
120
+ cp .env.example .env
121
+ ```
122
+ Add your `OPENAI_API_KEY` or `GEMINI_API_KEY` if you want live cloud LLM reasoning. If left empty, the built-in deterministic NLP extraction and semantic scoring engine will run offline automatically.
123
+
124
+ ---
125
+
126
+ ## Usage Guide
127
+
128
+ ### 1. Dry Run (Recommended for testing without submitting)
129
+ Simulates the workflow, extracts cards, computes fit scores, fills forms up to the final review step, and tests the HITL prompt without submitting:
130
+ ```bash
131
+ python main.py --keyword "QA Automation Engineer" --location "Hyderabad" --max-jobs 3 --dry-run
132
+ ```
133
+
134
+ ### 2. Live Apply Mode
135
+ Executes the live workflow with non-headless browser:
136
+ ```bash
137
+ python main.py --keyword "SDET" --location "Hyderabad" --min-score 70 --max-jobs 5
138
+ ```
139
+
140
+ ### 3. CLI Command Options
141
+ ```
142
+ --keyword Job title or search keyword (default: "QA Automation Engineer")
143
+ --location Search location (default: "Hyderabad")
144
+ --max-jobs Maximum applications to process (default: 10)
145
+ --min-score Minimum fit score required to proceed (default: 70.0)
146
+ --headless Run Chromium in headless mode (default: False)
147
+ --dry-run Fill forms to review step without clicking final submit
148
+ --auto-approve Bypass interactive HITL prompt at review step
149
+ --profile Custom path to candidate_profile.json
150
+ --log-level Logging level [DEBUG, INFO, WARNING, ERROR] (default: INFO)
151
+ ```
152
+
153
+ ---
154
+
155
+ ## Running the Automated Test Suite
156
+
157
+ Execute pytest across all test modules:
158
+ ```bash
159
+ pytest tests/ -v
160
+ ```
@@ -0,0 +1,10 @@
1
+ from .job_evaluator import JobEvaluator
2
+ from .form_agent import FormAgent
3
+ from .fsm_runner import FSMRunner, WorkflowState
4
+
5
+ __all__ = [
6
+ "JobEvaluator",
7
+ "FormAgent",
8
+ "FSMRunner",
9
+ "WorkflowState",
10
+ ]