Skip to content

feat: add Claude Vision form filler + browser reliability improvements#1157

Open
Sangsiva wants to merge 4 commits intofeder-cr:mainfrom
Sangsiva:pr/claude-vision-filler
Open

feat: add Claude Vision form filler + browser reliability improvements#1157
Sangsiva wants to merge 4 commits intofeder-cr:mainfrom
Sangsiva:pr/claude-vision-filler

Conversation

@Sangsiva
Copy link
Copy Markdown

@Sangsiva Sangsiva commented Apr 4, 2026

⏺ ## Summary

This PR adds three new capabilities to AIHawk's automation and resume generation layer.


1. src/libs/jd_resume_matcher/ (new module)

A Claude-based alternative to the existing resume tailoring flow. Instead of
regenerating sections from YAML, it works from pre-written HTML resume variants
and selects + tailors the best one per job description.

Two-step approach:

  • Haiku reads stripped text of all variants + the JD, picks the best base
    and does a gap analysis (~1k tokens, very cheap)
  • Sonnet receives the full HTML of the selected resume and rewrites it to
    match the JD — reordering bullets, pulling stronger ones from other variants,
    adding missing keywords

5x fewer input tokens vs sending full HTML to the selection step.

All configuration (paths, candidate name, resume variants and their descriptions)
lives in data_folder/jd_matcher_config.yaml (gitignored).
Template at data_folder_example/jd_matcher_config.yaml.

Full setup and usage docs in src/libs/jd_resume_matcher/README.md.

Exposes two entry points:

  • run_jd_match(api_key) — interactive CLI, prompts for a job URL
  • tailor_resume_for_jd(api_key, jd_text, company_name) — programmatic, no prompts
  • generate_cover_letter_for_jd(...) — role-specific cover letter via Haiku

2. src/utils/visual_form_filler.py (new)

Claude Vision-powered utility that fills any web-based job application form
using screenshots + Selenium — useful for non-standard forms that DOM inspection
can't handle.

Flow:

  1. Takes a screenshot of the current page
  2. Sends it to Claude Sonnet with the candidate profile
  3. Claude identifies visible fields and values to fill
  4. Selenium fills each field using label / placeholder / aria strategies
  5. Handles Next/Submit navigation, cookie banners, and CAPTCHA pauses
  6. Pauses before final submit for human review

All candidate data (name, contact, salary, notice period, education, skills,
work authorization) is read from plain_text_resume.yaml — nothing hardcoded.


3. src/utils/chrome_utils.py (improved)

  • User-agent rotation across 5 real Chrome UA strings per session
  • undetected-chromedriver support with graceful fallback to standard Selenium
  • navigator.webdriver patching via CDP to reduce automation fingerprinting
  • Suppress automation extension flags (excludeSwitches, useAutomationExtension)
  • _clear_profile_locks() — kills orphaned Chrome processes and removes stale
    SingletonLock files before init, fixing crashes on restart after unclean shutdown
  • Persistent profile directory configurable via BROWSER_PROFILE_DIR env var
  • Removed --incognito flag (incompatible with persistent profiles)

Also included

  • src/utils/resume_reviewer.py — scans generated resume PDFs for formatting
    issues (overflow, blank pages, font rendering) and returns structured notes
  • data_folder_example/jd_matcher_config.yaml — setup template for the JD matcher

Siva and others added 4 commits April 4, 2026 18:55
Adds two improvements to the AIHawk browser automation layer:

1. src/utils/visual_form_filler.py (new)
   A Claude Vision-powered utility that fills any web-based job
   application form using screenshots + Selenium. Useful for
   non-standard forms that can't be handled by DOM inspection alone.

   Flow:
   - Takes a screenshot of the current page
   - Sends it to Claude Sonnet with the candidate profile
   - Claude identifies visible fields and values to fill
   - Selenium fills each field using label/placeholder/aria strategies
   - Handles Next/Submit navigation, cookie banners, and CAPTCHA pauses
   - Pauses before final submit for human review

   Profile data (name, contact, salary, notice period, education,
   skills, work authorization) is read entirely from plain_text_resume.yaml
   — nothing is hardcoded.

2. src/utils/chrome_utils.py (improved)
   - Add user-agent rotation across 5 real Chrome UA strings
   - Add undetected-chromedriver support with graceful fallback to
     standard Selenium when the package is not installed
   - Patch navigator.webdriver via CDP to reduce automation detection
   - Suppress automation extension flags (excludeSwitches, useAutomationExtension)
   - Add _clear_profile_locks() to kill orphaned Chrome processes and
     remove stale SingletonLock files before init — fixes crashes on
     restart after unclean shutdown
   - Make persistent profile directory configurable via BROWSER_PROFILE_DIR
     env var (defaults to ~/.aihawk_browser_profile)
   - Remove --incognito flag (incompatible with persistent profiles)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds two new modules to the AIHawk library layer:

### src/libs/jd_resume_matcher/jd_matcher.py

A Claude-based alternative to the existing OpenAI resume tailoring flow.
Instead of regenerating sections from YAML, it works from pre-written
HTML resume variants and selects + tailors the best one for each JD.

Flow:
1. Haiku reads stripped text of all resume variants + JD, picks the
   best base and does a gap analysis (cheap — ~1k tokens)
2. Sonnet receives full HTML of the selected resume + stripped text of
   others as bullet reference, outputs a complete tailored HTML resume
3. HTML is converted to PDF via headless Chrome
4. review_resume_pdf() auto-checks formatting before saving

Key design choices vs the existing approach:
- 5x fewer input tokens (stripped HTML vs full HTML for selection step)
- Multi-resume selection — picks best positioning from a pool of variants
- Config-driven: all paths and candidate name in jd_matcher_config.yaml
  (gitignored), example at data_folder_example/jd_matcher_config.yaml
- Exposes tailor_resume_for_jd() for programmatic use and run_jd_match()
  for interactive CLI use

### src/utils/resume_reviewer.py

Scans a generated resume PDF for common formatting issues:
- Text overflow / clipping
- Blank pages
- Font rendering problems
Returns structured review notes and optionally triggers auto-fix.

### data_folder_example/jd_matcher_config.yaml

Setup template for jd_matcher — paths, candidate name, and resume
filename map. Copy to data_folder/jd_matcher_config.yaml to use.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
RESUME_DESCRIPTIONS was hardcoded in jd_matcher.py with role names
specific to one user's career. Moved to jd_matcher_config.yaml under
resume_descriptions so any user can define their own variant labels
and descriptions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers setup, config file structure, CLI and programmatic usage,
cover letter generation, output structure, and tips.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant