- Implement `verifySelect` to check element values in `Verifier`.
- Add `.select` to retryable commands in `Agent`.
- Increase retries to 3 with incremental backoff.
- Simplify click verification by removing navigation intent logic.
Consolidates verification and failure reason generation into a single
call. Optimizes state capture to be command-aware and fixes EVAL block
parsing logic in `Command.zig`.
Introduces a Verifier to ensure commands like click or type actually
achieve their intended effects. Adds retry logic for flaky actions
and includes verification context in self-healing prompts.
This introduces two slightly related changes.
My understanding is:
- frameId represents the page. Even if the page navigates, it's the same
frameId. We capture this in Page._frame_id. Nothing here changes.
- loaderId is essentially for a specific document of the page. If the page
navigates, it should be a different loaderId. We were using a distinct
loaderId per request. Not sure what problems that caused. But it was wrong.
This was achieved by exposing Page.id to CDP.
- requestId was mostly correct: unique per request. HOWEVER, for the original
document, apparently, requestId == loaderId. This change is particularly
important for various puppeteer and playwrightb behavior. This is a bit
hacked. CDP will look at the resource_type, if it's .document, it'll return
the loaderId, else it returns the requestId it always id.
Tracks command spans and automatically updates script files with
LLM-generated fixes when self-healing succeeds. Includes atomic file
writes and automatic .bak file creation.
When we stop streaming, we need to use any previously streamed data as part of
the last "unstreamed" chunk. Or, put differently, when stream is false, that
merely stops any subsequent streams, it doesn't discard any previously streamed
data.
Websockets client can send a Protocol which the server can agree to. This isn't
as fancy as it sounds. We just send a specific header on websocket handshake
and then read the response header.
Since group depth is not used for indentation in headless mode,
simplify by removing the field. group/groupCollapsed just log,
groupEnd is a no-op.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add missing console grouping APIs per the WHATWG Console spec:
- console.group(...data): logs label and increments group depth
- console.groupCollapsed(...data): same as group (headless mode has no
visual collapsing, so behavior is identical to group)
- console.groupEnd(): decrements group depth, clamped at 0
Depth is tracked via _group_depth (u32) on the Console struct.
Saturation arithmetic (+|=) prevents overflow on runaway group() calls.
Fixes TypeError crashes on sites that use console.group* APIs (e.g.
React/Vite dev builds).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Extract `getJsonString` helper in Agent.zig.
- Match specific triple quote types in EVAL blocks to allow nested quotes.
- Use `cmd.format` and larger buffers in Recorder.zig.
- Use `std.json.Stringify` for safer JS escaping in `execExtract`.
- Streamline `CommandExecutor` and remove redundant helpers.
- Add "QUIT" as an alias for the "EXIT" command.
- Clean up REPL loop control flow and error reporting in `Agent`.
- Simplify `Recorder` file operations and logging.
Allows starting the agent without a provider to use Pandascript
commands without an API key. Commands requiring an LLM and
--self-heal now explicitly require a provider.
https://github.com/lightpanda-io/browser/pull/1987 added support for a
connection that was close with a valid response. This commit goes a step further
and removes the requirement for a "connection: close" header.
We see a lot of these in WPT tests, e.g.
/referrer-policy/gen/iframe.http-rp/unset/iframe-tag.http.html
Also, switch MO and IO to use a "small" arena, as they probably don't require
too many allocations in most normal cases (just observing 1 or 2 things).