Initial Context Extractor: extension + Playwright/Camoufox package
CI / Lint + tests (push) Has been cancelled

Ship a shared markdown/prompt core used by a Brave/Chrome MV3 extension and a Python automation API, with pytest coverage, CI, and packaging smoke.
This commit is contained in:
2026-07-15 14:52:22 -04:00
commit c91cd221d1
30 changed files with 2611 additions and 0 deletions
+40
View File
@@ -0,0 +1,40 @@
"""Minimal example: capture context from a page using Camoufox (anti-detect Firefox).
Camoufox hands you a normal Playwright Page, so ExtractorSession works
unmodified. No `main_world_eval` or init-script workarounds are needed here:
capture uses Playwright's native page.on(...) hooks (not JS injection), and
markdown extraction only *reads* the DOM, which works fine in Camoufox's
default isolated world.
Run:
pip install -e ./automation[camoufox]
python automation/examples/scrape_camoufox.py https://example.com
"""
import sys
from camoufox import Camoufox
from context_extractor import ExtractorSession
def main() -> None:
url = sys.argv[1] if len(sys.argv) > 1 else "https://example.com"
with Camoufox(headless=True, geoip=True) as browser:
page = browser.new_page()
session = ExtractorSession(page)
page.goto(url, wait_until="domcontentloaded")
page.wait_for_timeout(1000) # let SPA fetches settle
print(session.build_ai_prompt())
# Or grab pieces individually:
# extracted = session.extract_markdown("#main-content")
# store = session.get_store() # {"console": [...], "errors": [...], "network": [...]}
if __name__ == "__main__":
main()
@@ -0,0 +1,31 @@
"""Async variant, using AsyncCamoufox + AsyncExtractorSession.
Run:
pip install -e ./automation[camoufox]
python automation/examples/scrape_camoufox_async.py https://example.com
"""
import asyncio
import sys
from camoufox.async_api import AsyncCamoufox
from context_extractor import AsyncExtractorSession
async def main() -> None:
url = sys.argv[1] if len(sys.argv) > 1 else "https://example.com"
async with AsyncCamoufox(headless=True, geoip=True) as browser:
page = await browser.new_page()
session = AsyncExtractorSession(page)
await page.goto(url, wait_until="domcontentloaded")
await page.wait_for_timeout(1000)
print(await session.build_ai_prompt())
if __name__ == "__main__":
asyncio.run(main())
+35
View File
@@ -0,0 +1,35 @@
"""Minimal example: capture context from a page using plain Playwright + Chromium.
Run:
pip install -e ./automation
playwright install chromium
python automation/examples/scrape_chromium.py https://example.com
"""
import sys
from playwright.sync_api import sync_playwright
from context_extractor import ExtractorSession
def main() -> None:
url = sys.argv[1] if len(sys.argv) > 1 else "https://example.com"
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
# Attach capture *before* navigating so console/network from the very
# first load are seen.
session = ExtractorSession(page)
page.goto(url, wait_until="networkidle")
print(session.build_ai_prompt()) # selector=None -> whole <body>
browser.close()
if __name__ == "__main__":
main()