Skip to content

v1.2.0

Choose a tag to compare

@github-actions github-actions released this 09 Sep 19:07
· 13 commits to main since this release
98880e2

Added

  • Page.selectors() — extraction without having read the markup. Writing an
    extract() call means knowing the classes on the page, and an agent connected
    over MCP could not: fetch_markdown strips exactly the classes and attributes
    a selector is built from, and no tool returns HTML on purpose, since raw markup
    costs more tokens than the data it is meant to locate. So this reports the
    structure instead of the source — the blocks that repeat, the inner selectors
    that resolve across most instances, and a sample record for each, which is a
    runnable item + fields rather than something to interpret.

    Two heuristics do the work. A repeated wrapper and the card inside it appear
    equally often, so the one that offers nothing its own child does not is
    dropped: article.product_pod survives, li.col-xs-6.col-sm-4.col-md-3 does
    not. And a column whose element contains another column's is thrown away,
    because its text is every child's text run together — div.product_price
    otherwise comes back as "£51.77In stockAdd to basket".

Fixed

  • markdown() was throwing the page away on listings. Main-content
    extraction is built to discard repetition — which on a listing page is the
    content. On books.toscrape.com, the first URL the README tells you to curl,
    it returned the price column and dropped all twenty book titles: 358
    characters out of 1,851 of visible text. It now checks what came back against
    the page's own text and falls back to full-page conversion when the
    extractor kept under a quarter of it. Measured, that floor sits far below
    every good case (1.14x of visible text on quotes.toscrape.com, 1.4-1.6x on
    Wikipedia) and just above the one that broke (0.19x), so an article buried in
    navigation still gets the boilerplate stripped.

    With the content back, the saving is 4.8x on books.toscrape.com, 5.8x on
    quotes and 6.6x on a Wikipedia article — the 5-10x the README claims. The
    broken version scored 144x, which was not a saving.

Fixed

  • "Setup for agents" set nothing up. The button copies Read and follow <url>, which makes an agent read the skill for exactly one turn — next
    message it has none of it, and /bytecrawl never appears. The skill showed
    the install command but never told the agent to run it, so the button promised
    setup and delivered a single answer. Installing itself is now the first
    instruction in the file — and it branches on what the agent is, because a
    skills directory is Claude Code's convention and telling Codex or Cursor to
    write ~/.claude/skills/ produces a file nobody reads. Claude Code installs
    the file and gets /bytecrawl; an MCP client with no skills directory adds
    the hosted server, which is the one path that persists everywhere and hands
    over the tools rather than instructions about them; an agent with an
    AGENTS.md adds one line pointing back; a sandbox with nothing to write to
    skips it silently. If a task came with the URL, the task comes first.

  • /docs advertised v1.0.0 through three releases. The version was written
    into the template, so nothing tied it to the package and it simply stopped
    being true. It renders from bytecrawl.__version__ now, and a test fails if
    a literal version reappears there.

Changed

  • fetch_markdown returns tokens_html next to tokens_estimate, the pair the
    playground already showed. On its own the token count has nothing to compare
    against; beside the raw HTML it is the reason to have called the tool, and an
    agent can state the saving instead of asserting it.
  • extract called with only a url now discovers instead of failing. It used
    to raise "extract needs 'item' and 'fields', or 'select'" — refusing the one
    question an agent can ask about a page it has not seen. The same call works on
    every surface: the MCP tool, /api?method=extract without select, and the
    playground's Extract chip with the field left empty, which lists the blocks it
    found and turns each into a button that fills the selector and runs it.
  • The demo API no longer sorts JSON keys. The discovered fields come back ranked
    with the most useful selector first and the playground offers that one as the
    button; sorted alphabetically, books.toscrape.com led with a::attr(href).