Add controls inventory and truncate long data: URIs in dumps.
CI / automation-js (vitest + real Chromium) (pull_request) Successful in 1m13s
CI / Lint + tests (pull_request) Successful in 10m24s

Agents hitting Outline-style SPAs need visible vs hidden control lists,
and inlined base64 images were blowing up AI prompts and network copy.
This commit is contained in:
2026-08-09 19:13:54 -04:00
parent f45833ff07
commit ee520fc391
12 changed files with 297 additions and 12 deletions
+4
View File
@@ -12,6 +12,10 @@
<main id="main-content">
<h2>Section</h2>
<p>Hello <strong>world</strong>, visit <a href="/docs">docs</a>.</p>
<p>Big inline art: <a href="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxISEhUQEhIWFhUVFRUVFRUVFRUVFRUWFxUXFhUYHSggGBolGxUVITEhJSkrLi4uFx8zODMtNygtLisBCgoKDg0OGxAQGy0lHyUtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLf/AABEIAAEAAQMBIgACEQEDEQH/xAAbAAACAwEBAQAAAAAAAAAAAAADBAECBQYAB//EABQBAQAAAAAAAAAAAAAAAAAAAAD/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAGfAP/EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEAAQUCf//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQMBAT8Bf//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQIBAT8Bf//Z">tiny-jpeg</a>.</p>
<button type="button" aria-label="Document options" id="doc-opts-visible"></button>
<button type="button" aria-label="Document options" id="doc-opts-hidden" style="display:none"></button>
<button type="button" aria-label="Upload file" id="upload-btn">Upload file</button>
<ul>
<li>Alpha</li>
<li>Beta</li>
+55
View File
@@ -14,7 +14,62 @@ def test_shared_js_files_exist_and_match_package():
assert (CORE / "prompt.js").is_file()
# package-side copies/symlinks must resolve to the same source
assert "function extractMarkdown" in _read_js("dom.js")
assert "function truncateDataUri" in _read_js("dom.js")
assert "function inventoryInterestingControls" in _read_js("dom.js")
assert "function buildAIPrompt" in _read_js("prompt.js")
assert "function truncateDataUri" in _read_js("prompt.js")
def test_build_ai_prompt_truncates_data_uris_in_network(page):
page.goto("about:blank")
meta = {
"url": "https://example.test/page",
"title": "T",
"ts": 1_700_000_000_000,
"selector": "body",
}
long_data = "data:image/jpeg;base64," + ("A" * 500)
store = {
"console": [],
"errors": [],
"network": [{
"type": "fetch", "method": "GET", "url": long_data,
"status": 200, "ts": 3, "duration": 12, "error": None,
}],
}
out = page.evaluate(_build_prompt_script(meta, "# Hello", store))
assert "bytes truncated" in out
assert ("A" * 100) not in out
def test_build_ai_prompt_includes_interesting_controls(page):
page.goto("about:blank")
meta = {"url": "https://example.test/page", "title": "T", "ts": 1, "selector": "body"}
controls = [
{
"tag": "button",
"role": "",
"ariaLabel": "Document options",
"text": "",
"visible": True,
"selector": "#vis",
},
{
"tag": "button",
"role": "",
"ariaLabel": "Document options",
"text": "",
"visible": False,
"selector": "#hid",
},
]
out = page.evaluate(
_build_prompt_script(meta, "# Hello", {"console": [], "errors": [], "network": []}, None, controls)
)
assert "## Interesting Controls" in out
assert "[visible]" in out
assert "### Hidden" in out
assert "Document options" in out
def test_build_ai_prompt_script_formats_errors_and_failures(page):
+15
View File
@@ -31,6 +31,8 @@ def test_extract_markdown_body_and_selector(page, fixture_url):
assert "**world**" in full["markdown"]
assert "[docs](/docs)" in full["markdown"]
assert "- Alpha" in full["markdown"]
assert "bytes truncated" in full["markdown"]
assert "4AAQSkZJRgABAQAAAQABAAD" not in full["markdown"]
scoped = session.extract_markdown("#main-content")
assert scoped["selector"] == "#main-content"
@@ -64,10 +66,23 @@ def test_build_ai_prompt_has_sections(page, fixture_url):
assert prompt.startswith("# Page Context")
assert "## Page Content" in prompt
assert "Hello **world**" in prompt
assert "## Interesting Controls" in prompt
assert "[visible]" in prompt
assert "Document options" in prompt
assert "JavaScript Errors" in prompt or "Console Errors" in prompt
assert "_Extracted by Context Extractor_" in prompt
def test_inventory_controls_visible_and_hidden(page, fixture_url):
session = ExtractorSession(page)
page.goto(fixture_url, wait_until="domcontentloaded")
controls = session.inventory_controls("#main-content")
docs = [c for c in controls if c.get("ariaLabel") == "Document options"]
assert len(docs) == 2
assert any(c.get("visible") for c in docs)
assert any(not c.get("visible") for c in docs)
def test_clear_store(page, fixture_url):
session = ExtractorSession(page)
page.goto(fixture_url, wait_until="domcontentloaded")