agent-fallback

This commit is contained in:
ldy
2026-06-17 23:32:14 -04:00
parent 41037fb2f5
commit ed3ec1d2c6
5 changed files with 735 additions and 13 deletions

View File

@@ -7,10 +7,11 @@ Cascade order (return early on first success):
3. Homepage scan → heuristics.scan_homepage_links() confidence 0.60
4. Sitemap → heuristics.parse_sitemap() confidence 0.50
5. Cheap-LLM → classify_llm.classify_careers_link() confidence 0.55
6. Browser agent → agent_fallback (not implemented in this phase)
6. Browser agent → agent_fallback.find_and_extract() confidence 0.50
Returns a CareersResult with the URL, confidence, method string, and — when
the ATS tier resolves — the first open-position URL for free (Stage-3 shortcut).
the ATS tier or browser-agent tier resolves — the first open-position URL for
free (Stage-3 shortcut).
The optional *client* parameter follows the managed-client pattern from
resolve.py: supply an existing httpx.Client to reuse connections; otherwise a
@@ -23,7 +24,9 @@ import logging
import httpx
from pydantic import BaseModel
from ..config import get_settings
from ..http import build_client, request_with_retries
from .. import agent_fallback as _agent_fallback
from . import ats as _ats
from . import classify_llm as _classify_llm
from . import heuristics as _heuristics
@@ -41,7 +44,7 @@ class CareersResult(BaseModel):
careers_url: str | None = None
confidence: float = 0.0
# method values: "ats:{name}" | "url_pattern" | "homepage_scan" | "sitemap" | "llm_classify" | "none"
# method values: "ats:{name}" | "url_pattern" | "homepage_scan" | "sitemap" | "llm_classify" | "browser_agent" | "none"
method: str = "none"
ats_name: str | None = None
# Free Stage-3 shortcut: populated when ATS tier resolves (first open job URL).
@@ -163,6 +166,26 @@ def find_careers_page(
except Exception as exc:
logger.warning("cascade(%s): llm_classify tier error: %s", website, exc)
# ------------------------------------------------------------------
# Tier 6 — Browser agent (fused Stage-2 + Stage-3 fallback)
# ------------------------------------------------------------------
if get_settings().enable_browser_agent:
try:
ag = _agent_fallback.find_and_extract(website)
if ag and ag.careers_url:
logger.info(
"cascade(%s): resolved via browser_agent careers_url=%s",
website, ag.careers_url,
)
return CareersResult(
careers_url=ag.careers_url,
confidence=0.50,
method="browser_agent",
position_url=ag.position_url,
)
except Exception as exc:
logger.warning("cascade(%s): browser_agent tier error: %s", website, exc)
logger.info("cascade(%s): all tiers missed", website)
return CareersResult()