refactor(tools): compact web backend ladder/client slots, cache path guards, policy path resolution

This commit is contained in:
Teknium
2026-09-02 23:58:28 -07:00
parent 61f834bfec
commit 8e2c8b18d5
3 changed files with 8 additions and 17 deletions

View File

@@ -265,10 +265,10 @@ def extract_cache_get(url: str, format: Optional[str] = None, provider: str = ""
try:
file_path, cache_root = Path(entry["file"]), _cache_dir()
# The index is plain JSON on disk; never let a tampered entry read outside cache/web.
if cache_root is None or cache_root.resolve() not in file_path.resolve().parents:
if cache_root.resolve() not in file_path.resolve().parents:
return None
content = file_path.read_text(encoding="utf-8")
except Exception: # noqa: BLE001 — evicted/pruned file == miss
except Exception: # noqa: BLE001 — evicted/pruned file == miss (or no cache dir)
return None
logger.info("web_extract cache hit: %s", url)
return {"url": url, "title": entry.get("title", ""), "content": content, "error": None, "cached": True}

View File

@@ -27,11 +27,7 @@ from plugins.web.parallel.provider import _get_async_parallel_client, _get_paral
from plugins.web.exa.provider import _get_exa_client # noqa: F401
# Per-vendor client cache slots; plugins read/write these via tools.web_tools (tests reset them to None).
_firecrawl_client: Optional[Any] = None
_firecrawl_client_config: Optional[Any] = None
_parallel_client: Optional[Any] = None
_async_parallel_client: Optional[Any] = None
_exa_client: Optional[Any] = None
_firecrawl_client = _firecrawl_client_config = _parallel_client = _async_parallel_client = _exa_client = None
from tools.debug_helpers import DebugSession
from tools.managed_tool_gateway import ( # noqa: F401 — backward-compat names for tests
@@ -137,15 +133,11 @@ def _get_backend() -> str:
# token's tier may not grant web access; the gateway then fails at runtime with no fallback).
# Free tiers trail paid.
backend_candidates = (
("tavily", _has_env("TAVILY_API_KEY")),
("exa", _has_env("EXA_API_KEY")),
("parallel", _has_env("PARALLEL_API_KEY")),
("keenable", _has_env("KEENABLE_API_KEY")),
("tavily", _has_env("TAVILY_API_KEY")), ("exa", _has_env("EXA_API_KEY")),
("parallel", _has_env("PARALLEL_API_KEY")), ("keenable", _has_env("KEENABLE_API_KEY")),
("firecrawl", _has_env("FIRECRAWL_API_KEY") or _has_env("FIRECRAWL_API_URL")),
("firecrawl", _is_tool_gateway_ready()),
("searxng", _has_env("SEARXNG_URL")),
("brave-free", _has_env("BRAVE_SEARCH_API_KEY")),
("ddgs", _ddgs_package_importable()),
("firecrawl", _is_tool_gateway_ready()), ("searxng", _has_env("SEARXNG_URL")),
("brave-free", _has_env("BRAVE_SEARCH_API_KEY")), ("ddgs", _ddgs_package_importable()),
)
for backend, available in backend_candidates:
if available:

View File

@@ -119,8 +119,7 @@ def load_website_blocklist(config_path: Optional[Path] = None) -> Dict[str, Any]
if not isinstance(shared_file, str) or not shared_file.strip():
continue
path = Path(shared_file).expanduser()
if not path.is_absolute():
path = (get_hermes_home() / path).resolve()
path = path if path.is_absolute() else (get_hermes_home() / path).resolve()
pairs += [(normalized, str(path)) for normalized in _iter_blocklist_file_rules(path)]
# dict.fromkeys dedupes (pattern, source) while keeping first-seen order.
result = {"enabled": enabled, "rules": [{"pattern": p, "source": s} for p, s in dict.fromkeys(pairs)]}