Merge pull request #1480 from feder-cr/forms-not-stuck

A form does not run out of steps repeating what changed nothing
This commit is contained in:
Federico Elia authored and GitHub committed 2026-11-05 19:38:35 +01:00
commit 0a88535eba
6 files changed
+9 -4

No files matched your search

+1
View File
@@ -18,6 +18,7 @@
- A form no longer stops to ask. The model fills every required field from what the CV says and implies, and a written field it has nothing for says to see the attached CV.
- The checks on the model's calls are gone, for far less code: it is told not to send, and nothing holds it to that. See SECURITY.md.
- Less to carry: your own CV goes with every form, in place of one written for each job, and there is one gateway, one key variable and one folder.
- A form no longer runs out of steps pressing a key that scrolls nothing: the model is told not to repeat what changed nothing.
- What goes wrong in the browser now reaches the screen as itself, a refused key included, in place of "unhandled errors in a TaskGroup". A page that says nothing yet after the send is read again when it changes, and a click that breaks is never called failed, because it may have gone.
- Every posting is tried. A plugin helps the model where there is one, and there is no list of sites AIHawk will not touch.
- A setting of the wrong type in `aihawk.yaml` is one plain line instead of a traceback.
+1 -1
View File
@@ -10,7 +10,7 @@ Loading a resume rewrites this file, and the rewrite drops the comments you put
| `goals` | empty | What you are looking for, in your own words. The decision model and the judge read it. |
| `database` | `https://github.com/feder-cr/Jobs_Applier_AI_Agent/releases/download/jobs-latest/manifest.json` | Where the job database is: the URL of its `manifest.json`, or the path of a local one. The files it names sit beside it, unless its `base_url` says otherwise. |
| `max_age_days` | `60` | Postings posted more than this many days ago are left out. A posting with no date is kept. |
| `model` | `deepseek/deepseek-v4.1-flash` | Writes the tailored CV and fills the application forms. |
| `model` | `deepseek/deepseek-v4.1-flash` | Fills the application forms. |
| `quick_model` | `google/gemini-3.5-flash` | Writes the search plan from your CV, and the other short calls of a search. |
| `judge_model` | `deepseek/deepseek-v4.1-flash` | Writes the score and the report of each shortlisted posting. |
| `decision_model` | `typesafe/jev-1.14` | Jev, which answers the six questions that shortlist the postings. |
+2 -2
View File
@@ -10,11 +10,11 @@ What AIHawk can do on each site, from the real forms it has been run on. Posting
| JazzHR (applytojob.com) | ~154k | stops at a captcha most of the time | reCAPTCHA did not pass with a click on 5 postings; it often turned into an image puzzle. |
| BambooHR (bamboohr.com) | ~87k | stops at a captcha most of the time | reCAPTCHA did not pass with a click on 5 postings; it often turned into an image puzzle. |
| Personio (jobs.personio.de, jobs.personio.com) | ~64k | stops at a captcha about half the time | Turnstile passed on 2 of 4 postings. A real form ended blocked. |
| SmartRecruiters (jobs.smartrecruiters.com) | ~519k | reaches the send button, not always | One real form filled through every step in about 11 minutes, and the send button named. Later runs on the same form did not get there: one failed on an error, one stopped at 150 steps. No send has gone. |
| SmartRecruiters (jobs.smartrecruiters.com) | ~519k | reaches the send button, not always | One real form filled through every step in about 11 minutes, and the send button named. A later run stopped at 150 steps, pressing keys that scrolled nothing; with a rule against that, the next run reached the button in about 10 minutes. No send has gone. |
| Recruitee (recruitee.com) | ~26k | sent and confirmed on a real form | One real send (one send only). Other forms stopped at required questions that test answers do not fit. |
| Teamtailor (teamtailor.com) | ~30k | sent and confirmed on a real form | One real send (one send only). An earlier click was refused for its test phone number, so nothing went then. Other forms stopped at required questions. |
| Workable (apply.workable.com) | ~35k | send clicked, not confirmed | One real form filled and sent: the button stayed on "Submitting…" beside an unticked Cloudflare box, and the browser was closed with no answer from the page. |
| Paylocity (recruiting.paylocity.com) | ~228k | reaches the send button, not always | One real form of 5 steps filled in about 27 minutes, and the send button named. A later run stopped at 150 steps. No send has gone. |
| Paylocity (recruiting.paylocity.com) | ~228k | reaches the send button, not always | One real form of 5 steps filled in about 27 minutes, and the send button named. A later run stopped at 150 steps, and the next one reached the button in about 10 minutes. No send has gone. |
| Breezy (breezy.hr) | ~50k | sent and confirmed on a real form | One real send (one send only). |
| Workday (myworkdayjobs.com, myworkdaysite.com) | ~1,481k | tried, no plugin | Needs an account on each company's site: a form stops at the sign-in unless you are signed in. Not tried on a real form. |
| iCIMS (icims.com) | ~622k | tried, no plugin | Needs an account: a form stops at the sign-in unless you are signed in. Not tried on a real form. |
+2
View File
@@ -73,6 +73,8 @@ You fill in one job application form in a browser, for the candidate, from the C
on it.
- Do not send the application yourself. When every required field is filled, call finish_form with status ready and the
CSS selector of the submit control.
- An action that leaves the page as it was will not work the second time: never repeat it, do something else. A key that
scrolls nothing means the form scrolls inside its own container: read and reach its fields with browser_evaluate.
- A captcha shown as a box to tick: click it. A puzzle or image challenge, a login wall or a closed posting: call
finish_form with status blocked.
- A code or confirmation link sent by email may be fetched as the instructions for that site say.
+2
View File
@@ -18,6 +18,8 @@ Menus (the country list, City suggestions, a dropdown's answers) open a list und
The footer "Next" button has no selector in browser_snapshot: read its centre the same way (browser_evaluate reads, then browser_click_at). Leave "Add" under Experience and Education alone unless the page requires an entry: "Please provide at least one work experience entry" under Experience means it does. Then add one from the CV: Title, Company and Office location suggest as you type, and From and To take MM/YYYY.
The form scrolls inside its own container, so PageUp and PageDown move nothing: seen on a real form, 40 steps lost pressing them. To reach a field, call its `scrollIntoView()` with browser_evaluate, walking the shadow roots.
The "Preliminary questions" step often asks for the right to work, sponsorship, and a block of required boxes with the person's name and today's date, stating that the answers are true.
The last step's footer control sends the application: `[data-test='footer-submit']`, labelled "Submit". Its label is what the page says, for example "Submit application". Never click it. If a plain CSS selector matches only that control, name it as the submit control; if none does, call finish_form with status blocked and say that the send control could not be named.
+1 -1
View File
@@ -508,7 +508,7 @@ class AIHawk(App[None]):
("places", "Where", ", ".join(config.filters.locations)),
("exclude", "Leave out", ", ".join(config.filters.exclude)),
("max_age_days", "Posted within (days)", str(config.max_age_days)),
("model", "Forms and CVs model", config.model),
("model", "Forms model", config.model),
("judge_model", "Scoring model", config.judge_model),
("quick_model", "Search plan model", config.quick_model),
("decision_model", "Shortlist model", config.decision_model),