diff options
| author | Joel Kronqvist <joel.kronqvist@iki.fi> | 2026-10-11 23:26:03 +0300 |
|---|---|---|
| committer | Joel Kronqvist <joel.kronqvist@iki.fi> | 2026-10-11 23:26:03 +0300 |
| commit | 24309a822aa56e624f280a095b9d92d32f8c18bb (patch) | |
| tree | f4bb653c36980ff42da57edc3c041ae7d9715837 /web_utils.py | |
| parent | 085133e1b87d56edc9f0542ea830ca0a385204c0 (diff) | |
| download | agent-24309a822aa56e624f280a095b9d92d32f8c18bb.tar.gz agent-24309a822aa56e624f280a095b9d92d32f8c18bb.zip | |
feat: webgrep
Diffstat (limited to 'web_utils.py')
| -rw-r--r-- | web_utils.py | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/web_utils.py b/web_utils.py new file mode 100644 index 0000000..91561b5 --- /dev/null +++ b/web_utils.py @@ -0,0 +1,61 @@ +import urllib.request +import subprocess +import re +from typing import Dict, Union +from dataclasses import dataclass + + +@dataclass +class FetchSuccess: + """Successful fetch result containing the markdown content.""" + + content: str + + +@dataclass +class FetchError: + """Failed fetch result containing the error message.""" + + error: str + + +FetchResult = Union[FetchSuccess, FetchError] + +# Memoization cache for web pages +_cache: Dict[str, FetchResult] = {} + + +def html_to_markdown(html: str) -> str: + """Converts HTML to markdown using pandoc with GFM format.""" + try: + # Use gfm (GitHub Flavored Markdown) for better compatibility and robust conversion + process = subprocess.run( + ["pandoc", "-f", "html", "-t", "gfm", "-o", "-"], + input=html, + capture_output=True, + text=True, + check=True, + encoding="utf-8", + ) + return process.stdout.strip() + except subprocess.CalledProcessError as e: + raise RuntimeError(f"Pandoc error: {e}") + except Exception as e: + raise RuntimeError(f"Unexpected error during markdown conversion: {e}") + + +def fetch_and_markdownify(url: str) -> FetchResult: + """Fetches a web page and transforms it to markdown, with memoization.""" + if url in _cache: + return _cache[url] + + try: + req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"}) + with urllib.request.urlopen(req, timeout=10) as response: + html = response.read().decode("utf-8") + markdown = html_to_markdown(html) + res = FetchSuccess(content=markdown) + _cache[url] = res + return res + except Exception as e: + return FetchError(error=str(e)) |
