Dialogs auto-dismiss in headless mode, so there is no pending dialog
by the time the CDP client sends Page.handleJavaScriptDialog. Return
an explicit error so the client knows the action had no effect.
parseDomain() rejects bare TLDs (e.g. Domain=.io) but accepts
multi-level public suffixes like .co.uk, .com.au, .co.jp.
Per RFC 6265bis §5.7.3.10, user agents should reject cookies whose
domain attribute is a public suffix. Chrome, Firefox, and Safari all
enforce this using the Public Suffix List.
The PSL data is already imported (Cookie.zig:26) and used in
findSecondLevelDomain(), but parseDomain() does not consult it.
This causes behavior differences vs Chrome when automating .co.uk /
.com.au / .co.jp sites via CDP — cookies that Chrome silently drops
are accepted by Lightpanda, polluting the cookie jar across unrelated
sites in the same session.
- Add Recorder for recording REPL sessions to .panda files, with
--no-record flag and positional file arg support. Skips read-only
commands (WAIT, TREE, MARKDOWN) per spec.
- Record resolved LLM tool calls as Pandascript commands so the
generated artifact is deterministic.
- Add self-healing in --run mode: on command failure, prompt the LLM
with the # INTENT context to resolve an alternative.
- Add LOGIN and ACCEPT_COOKIES high-level commands (LLM-resolved).
- Add multi-line EVAL """...""" support via ScriptIterator.
- Add $VAR_NAME environment variable substitution in command arguments.
- Escape JS strings in execType/execExtract to prevent injection.
- Sanitize output file paths in EXTRACT to prevent path traversal.
Introduces `lightpanda agent` command that provides a REPL where users
can chat with an AI that uses the browser's tools (goto, markdown, click,
fill, etc.) to browse the web. Uses zenai for multi-provider LLM support
(Anthropic, OpenAI, Gemini) and linenoise v2 for terminal line editing.
dispatchKeyEvent only handled keyDown, returning early for keyUp,
rawKeyDown, and char types. This meant JS keyup and keypress
listeners never fired via CDP.
Now keyUp dispatches as "keyup" and char dispatches as "keypress".
rawKeyDown remains a no-op (Chrome-internal, not used for JS dispatch).
Fixes#2080
Ref #2043
window.alert(), confirm(), and prompt() now dispatch a
javascript_dialog_opening notification that the CDP layer
forwards as a Page.javascriptDialogOpening event. This enables
Puppeteer's page.on('dialog') to fire when JS dialogs open.
Also adds Page.handleJavaScriptDialog as a CDP method. Dialogs
still auto-dismiss in headless mode (alert is void, confirm
returns false, prompt returns null), so handleJavaScriptDialog
is an acknowledgement rather than a blocking gate.
Changes:
- Notification.zig: add JavascriptDialogOpening event type
- CDP.zig: register listener, forward to page domain
- page.zig: handleJavaScriptDialog handler + event emitter
- Window.zig: alert/confirm/prompt dispatch the notification
Fixes#2082
Ref #2043
Uses libcurl's websocket capabilities to add support for WebSocket.
Depends on https://github.com/lightpanda-io/zig-v8-fork/pull/167
Issue: https://github.com/lightpanda-io/browser/issues/1952
This is a WIP because it currently uses the same connection pool used for all
HTTP requests. It would be pretty easy for a page to starve the pool and block
any progress.
We previously stored the *Transfer inside of the easy's private data. We now
store the *Connection, and a Connection now has a `transport` field which is
a union for `http: *Transfer` or `websocket: *Websocket`.