{
  "version": "0.1.9-beta",
  "commit": "e9c46b4b651852d4bac877968f33fcf90ed7c0cd",
  "build_date": "2026-09-20T01:23:54Z",
  "tool_schema": [
    {
      "name": "chrome.console_messages",
      "description": "Return buffered browser console messages (level, text, timestamp). Includes explicit console.*() calls, uncaught JS exceptions (level \"error\", text prefixed \"Uncaught \"), and failed network requests on document/xhr/fetch resources only (level \"clickprobe-network\", never a static sub-resource 404 -- that is not a bug). Buffer holds up to 1000 most recent messages. Each message carries is_new: true only if it arrived since YOUR last call to this tool (the buffer itself is never cleared unless you pass clear_after_read) -- check is_new, not just presence, to tell whether an error just happened or is an old one you already saw (e.g. a page-load error that will otherwise appear in every read for the rest of the session). new_since_previous_read gives the same answer as a count, for a quick check without scanning every entry.",
      "params": [
        "clear_after_read"
      ],
      "required": null
    },
    {
      "name": "chrome.go_back",
      "description": "Navigate the browser back one step in history.",
      "params": [
        "wait_until"
      ],
      "required": null
    },
    {
      "name": "explorer.get_unexplored_elements",
      "description": "List unexplored elements on a page — including elements the proxy registered for you from chrome.snapshot, not only ones you registered yourself. Ranked: enabled before disabled (a disabled control usually needs a prerequisite step first — e.g. selecting a row before a bulk-action button enables), then by how often you've been shown it. Capped at 25 — total_unexplored tells you if there are more. Returns {page_id, elements, count, total_unexplored}.",
      "params": [
        "page_id"
      ],
      "required": [
        "page_id"
      ]
    },
    {
      "name": "chrome.navigate",
      "description": "Navigate the persistent browser page to `url`. Subsequent chrome.* calls (click, type, screenshot without url, etc.) operate on this page.",
      "params": [
        "url",
        "wait_until"
      ],
      "required": [
        "url"
      ]
    },
    {
      "name": "chrome.click",
      "description": "Click an element on the current page. selector accepts either a CSS selector or an \"aria-ref=\u003cref\u003e\" handle taken from a chrome.snapshot result -- prefer the handle whenever chrome.snapshot showed you the element, since it names exactly one node and never guesses. Never targets an \u003coption\u003e element directly (not possible in this tool -- use chrome.select_option).",
      "params": [
        "selector",
        "button",
        "click_count",
        "timeout_ms"
      ],
      "required": [
        "selector"
      ]
    },
    {
      "name": "explorer.get_exploration_queue",
      "description": "List queued exploration items ordered by priority. By default only pending (not yet completed) items are returned. Pass the strategy named in your task prompt (\"Strategy: ...\") to get results ordered accordingly. Returns {items, count}.",
      "params": [
        "include_completed",
        "strategy",
        "limit"
      ],
      "required": null
    },
    {
      "name": "explorer.get_known_bugs",
      "description": "List known bugs. Returns {bugs, count}.",
      "params": [
        "page_url",
        "confirmed_only"
      ],
      "required": null
    },
    {
      "name": "chrome.hover",
      "description": "Hover over an element on the current page. selector accepts either a CSS selector or an \"aria-ref=\u003cref\u003e\" handle taken from a chrome.snapshot result.",
      "params": [
        "selector",
        "timeout_ms"
      ],
      "required": [
        "selector"
      ]
    },
    {
      "name": "explorer.register_elements",
      "description": "Bulk-register elements found on a page. Returns {element_ids, count}.",
      "params": [
        "page_id",
        "elements"
      ],
      "required": [
        "page_id",
        "elements"
      ]
    },
    {
      "name": "explorer.queue_exploration",
      "description": "Add a page or element to the exploration queue. Repeating the same target (same element_id, or same target_url) while it is still pending updates that item instead of creating a duplicate. Returns {queue_id} — the same id every time for a repeated target. Always pass target_url when the item refers to a specific route/tab/modal, even if the discovery page is different — this is what keeps the backlog from filling up with restated copies of the same thing.",
      "params": [
        "element_id",
        "priority",
        "target_url",
        "page_id",
        "reason"
      ],
      "required": [
        "page_id",
        "reason"
      ]
    },
    {
      "name": "chrome.type",
      "description": "Type text into an element. Uses Fill (instant) by default; set delay_ms for keystroke simulation. selector accepts either a CSS selector or an \"aria-ref=\u003cref\u003e\" handle taken from a chrome.snapshot result.",
      "params": [
        "selector",
        "text",
        "delay_ms",
        "clear_first",
        "timeout_ms"
      ],
      "required": [
        "selector",
        "text"
      ]
    },
    {
      "name": "chrome.network_requests",
      "description": "Return the page's most recent network requests -- success AND failure, unlike chrome.console_messages' clickprobe-network notices which only ever show a \u003e=400 response. Same document/xhr/fetch-only scope, same favicon exclusion. Each entry's origin is \"page\" (the application itself made this request) or \"injected\" (made by YOUR OWN chrome.evaluate call, not the application -- never treat an injected request as evidence of app behaviour). caused_by names the chrome.* call that was running when the request started (click/type/hover/select_option/press_key/navigate/go_back/evaluate), so you can tell which of your actions caused it without guessing from timing. Do NOT call chrome.evaluate to fire your own fetch()/XHR probes to find out what endpoints exist -- that manufactures traffic the application never sent and would show up here as origin: \"injected\", not as evidence of anything real; use this tool to observe, never chrome.evaluate to probe. Newest first, capped at limit (default 30, max 100); total_count/truncated tell you if anything was left out.",
      "params": [
        "limit"
      ],
      "required": null
    },
    {
      "name": "chrome.dialog",
      "description": "Arm how the NEXT browser dialog (alert/confirm/prompt) should be resolved. Call this BEFORE the action you expect to trigger a dialog (e.g. right before chrome.click on a button with a confirmation prompt) -- it applies to exactly one dialog and is then cleared. If a dialog opens with nothing armed, it is auto-dismissed and recorded in chrome.console_messages.",
      "params": [
        "action",
        "prompt_text"
      ],
      "required": [
        "action"
      ]
    },
    {
      "name": "explorer.complete_queue_item",
      "description": "Mark a queued exploration item as done. Never deletes the row -- a completed item still exists and can be seen again via get_exploration_queue(include_completed=true). Returns {completed, queue_id}.",
      "params": [
        "note",
        "queue_id"
      ],
      "required": [
        "queue_id"
      ]
    },
    {
      "name": "explorer.get_visibility_changes",
      "description": "Get every real state transition this proxy has observed (an element becoming enabled/disabled/hidden/etc. between sightings), newest first, capped at 100. Returns {changes, count} — each change has element_id, page_id, label, previous_state, new_state, changed_at.",
      "params": [
        "page_id"
      ],
      "required": null
    },
    {
      "name": "chrome.press_key",
      "description": "Press a keyboard key. If selector is given, focuses the element first.",
      "params": [
        "key",
        "selector"
      ],
      "required": [
        "key"
      ]
    },
    {
      "name": "chrome.evaluate",
      "description": "Evaluate a JavaScript expression in the current page context and return the result. Hard cap: 5 s.",
      "params": [
        "expression"
      ],
      "required": [
        "expression"
      ]
    },
    {
      "name": "chrome.snapshot",
      "description": "Return the accessibility tree of the current page as JSON. Hard cap: 5 MB (returns snapshot_too_large error if exceeded). If the result includes an untried_refs list, those are refs from THIS same result that you have not yet tried on this page — untried_count/tried_count cover the whole page (untried_refs itself may be truncated to the first 25). Treat it as your own catalogue telling you what is left, not an instruction to click in that order. If untried_refs is absent, no such catalogue is available for this snapshot — rely on your own judgment as before.",
      "params": [
        "interesting_only"
      ],
      "required": null
    },
    {
      "name": "explorer.get_page_info",
      "description": "Get info about a page by URL or ID. Returns page row + element_count.",
      "params": [
        "page_url",
        "page_id"
      ],
      "required": null
    },
    {
      "name": "chrome.take_screenshot",
      "description": "Take a PNG screenshot. If `url` is provided, navigates to that URL first (opens a fresh page). If `url` is omitted, screenshots the current persistent page (requires chrome.navigate first).",
      "params": [
        "full_page",
        "url"
      ],
      "required": null
    },
    {
      "name": "explorer.report_bug",
      "description": "File a bug. Returns {bug_id}. If this defect was already filed earlier in this project, the response also carries {duplicate_of, occurrence, note} — the report is still recorded, never dropped, as another occurrence of the earlier bug.",
      "params": [
        "bug_type",
        "severity",
        "description",
        "reproduction_steps",
        "action_id"
      ],
      "required": [
        "action_id",
        "bug_type",
        "severity",
        "description"
      ]
    },
    {
      "name": "explorer.get_app_context",
      "description": "Get the app context loaded from --app-context-path. Returns the context map or empty object.",
      "params": null,
      "required": null
    },
    {
      "name": "chrome.wait_for",
      "description": "Wait for an element to reach the given state on the current page.",
      "params": [
        "selector",
        "state",
        "timeout_ms"
      ],
      "required": [
        "selector"
      ]
    },
    {
      "name": "explorer.register_page",
      "description": "Record a newly discovered page. Returns {page_id, is_new}.",
      "params": [
        "data_persistence",
        "url",
        "title",
        "ai_description",
        "confidence",
        "url_type",
        "url_pattern"
      ],
      "required": [
        "url"
      ]
    },
    {
      "name": "chrome.select_option",
      "description": "Select one or more options in a \u003cselect\u003e element by VALUE (never by clicking the \u003coption\u003e itself -- that is not possible in any browser-automation tool). selector accepts either a CSS selector or an \"aria-ref=\u003cref\u003e\" handle taken from a chrome.snapshot result.",
      "params": [
        "selector",
        "values",
        "timeout_ms"
      ],
      "required": [
        "selector",
        "values"
      ]
    },
    {
      "name": "explorer.record_action",
      "description": "Log an action taken on an element. Returns {action_id}.",
      "params": [
        "action_type",
        "expected_result",
        "actual_result",
        "page_before_id",
        "console_errors",
        "bug_detected",
        "element_id",
        "input_value",
        "page_after_id"
      ],
      "required": [
        "element_id",
        "action_type"
      ]
    },
    {
      "name": "explorer.get_session_info",
      "description": "Get session info. Returns the active session row or a specific session by ID.",
      "params": [
        "session_id"
      ],
      "required": null
    },
    {
      "name": "chrome.resize",
      "description": "Change the browser viewport's width and height. The default is 1280x720 -- use this to test how the current page behaves at other sizes (e.g. 375x812 for a typical mobile width). Persists across chrome.navigate; call chrome.resize(1280, 720) again when you are done testing other sizes, to return to the default before continuing normal exploration. Returns the viewport size actually observed after the resize.",
      "params": [
        "width",
        "height"
      ],
      "required": [
        "width",
        "height"
      ]
    }
  ]
}
