Commit Graph

7220 Commits

Author SHA1 Message Date
Adrià Arrufat
2a7bda3608 string: add string.isOneOf and deduplicate helpers 2026-06-08 09:04:36 +02:00
Adrià Arrufat
7bcab1d840 terminal: separate normal and JS REPL history
Store normal and JS history in separate files and swap them
dynamically when toggling modes.
2026-06-06 12:44:59 +02:00
Adrià Arrufat
adec4d45f5 Merge branch 'main' into agent 2026-06-06 11:42:53 +02:00
Adrià Arrufat
c2e2717170 deps: update isocline dependency
Updates the isocline dependency to a newer commit and cleans up
redundant comments in Terminal.zig.
2026-06-06 11:07:05 +02:00
Adrià Arrufat
eb118bb1de terminal: highlight $LP_* vars inside strings
Extracts `highlightDollarVarsIn` to support highlighting within a
specific range, then applies it to JavaScript string literals.
2026-06-06 11:02:54 +02:00
Adrià Arrufat
2d574a92b1 terminal: add javascript syntax highlighting in JS mode 2026-06-06 10:53:53 +02:00
Adrià Arrufat
b009e416a6 terminal: add Ctrl-D exit confirmation
Updates the isocline dependency and implements a confirmation prompt
when pressing Ctrl-D to exit the terminal.
2026-06-06 10:42:36 +02:00
Adrià Arrufat
828abda838 terminal: support double Esc clear confirmation
Updates isocline and adds a status bar indicator when a clear
is pending after the first Esc press.
2026-06-06 09:47:00 +02:00
Pierre Tachoire
29b407bc30 Merge pull request #2653 from lightpanda-io/element_set_style
add Element.style setter
2026-06-06 09:24:13 +02:00
Adrià Arrufat
a771597caa terminal: support Backspace to exit JS mode
Updates the isocline dependency and the status bar exit hint.
2026-06-06 09:18:20 +02:00
Karl Seguin
a68598fa5d Merge pull request #2650 from lightpanda-io/fix_arena_leaks
Fix two arena leaks
2026-06-06 07:21:39 +08:00
Karl Seguin
0406451750 Merge pull request #2596 from lightpanda-io/robots-next-tick-on-sync-deny
Robots Deny on Next Tick
2026-06-06 07:21:10 +08:00
Karl Seguin
b82af40453 Merge pull request #2655 from lightpanda-io/improve_import_fail_error
Better import error return
2026-06-06 07:20:23 +08:00
Karl Seguin
50e1003be5 Merge pull request #2651 from lightpanda-io/extend_cdp_test_timeout
Extend the TCP read/write timeout from 2 second to 10.
2026-06-06 07:20:09 +08:00
Karl Seguin
c7d8cb4bb9 Merge pull request #2656 from lightpanda-io/atob_btoa
Fix atob/btoa
2026-06-06 07:19:50 +08:00
Adrià Arrufat
3342813012 build: update isocline dependency 2026-06-05 19:21:22 +02:00
Adrià Arrufat
e024c1b83b config: share enum tag helpers and add tagJsonArray
Moves `tagNames` and `tagHint` from `SlashCommand` to `Config` for reuse.
Adds `tagJsonArray` to dynamically generate JSON enum schemas, and
uses it in `tools.zig` for the `WaitUntil` enum.
2026-06-05 18:06:50 +02:00
Adrià Arrufat
30725175c1 agent: derive slash command values from enums
Use comptime reflection to generate hints and allowed values for
`/verbosity` and `/effort` commands directly from their config enums.
2026-06-05 17:36:00 +02:00
Adrià Arrufat
3f0c6f6c09 terminal: autocomplete and hint enum values
Parses `enum` constraints from the schema and uses them to provide
tab-completions and ghost hints for enum fields in the REPL.
2026-06-05 16:58:19 +02:00
Adrià Arrufat
200cbe623f agent: skip network requests during initialization
Avoids network round trips during agent startup to keep it snappy.
Skips model reconciliation in REPL mode and loads the model-list
cache lazily instead of pre-warming it.
2026-06-05 16:34:29 +02:00
Muki Kiboigo
22410510db Synthetic runNextTick takes null as ctx 2026-06-05 07:26:40 -07:00
Adrià Arrufat
9d4f284c73 browser: add waitForState and default goto to load
Removes the `waitUntil` option from `goto` and other navigation tools,
making them default to the fast `load` event. Introduces a dedicated
`waitForState` tool to wait for specific load states on demand.
2026-06-05 16:26:19 +02:00
Muki Kiboigo
572267802d fire RobotsBlocked in nextTickRun 2026-06-05 07:25:32 -07:00
Muki Kiboigo
ffcdcc6e09 add optional ctx to runNextTick 2026-06-05 07:25:29 -07:00
Karl Seguin
c4e859d735 fix tests 2026-06-05 21:19:46 +08:00
Adrià Arrufat
97dc807810 repl: improve startup help messages 2026-06-05 15:16:41 +02:00
Adrià Arrufat
5ad664a63a agent: allow disabling LLM via /provider null
Adds support for `/provider null` to disable the LLM and persist this
preference in `.lp-agent.zon`. Subsequent REPL launches will start
in basic mode without prompting for API keys. Transient `--no-llm`
runs do not clobber the saved provider.
2026-06-05 15:12:04 +02:00
Karl Seguin
b0ebbf7b35 zig fmt 2026-06-05 20:46:48 +08:00
Karl Seguin
14aec37652 Fix atob/btoa
Passes WPT /html/webappapis/atob/base64.html

Two changes
1 - Use the forgiving decoder already in data_url
2 - Coerce input (3 => "3")

The 2nd change was more interesting. These take a js.String.OneByte as an
optimization, which doesn't coerce. To preserve this optimization a union was
used with a `raw: []const u8` fallback (and our bridge always coerces to
a `[]const u8`)
2026-06-05 20:44:19 +08:00
Adrià Arrufat
ce34ea6625 agent: persist and restore verbosity setting
Saves the agent's verbosity setting to `.lp-agent.zon` and
restores it on initialization, similar to the effort setting.
2026-06-05 14:40:55 +02:00
Adrià Arrufat
d7be4ebade browser: update driver guidance for efficient browsing
Adds instructions on using `url` parameters with `markdown`, `tree`,
and `html` to avoid redundant `goto` calls. Also adds a section on
browsing efficiently to minimize page loads and triage search results.
2026-06-05 14:26:31 +02:00
Adrià Arrufat
c355b0bda8 agent: add /clear and /reset REPL commands
- `/clear` forgets conversation history, usage, and node IDs while
  keeping the loaded page and cookies.
- `/reset` does a full reset, starting a fresh browser session.
2026-06-05 14:13:10 +02:00
Adrià Arrufat
2d2914e878 agent: add /usage slash command to REPL
Adds a new `/usage` meta command to print cumulative token usage and
cache hit rate for the current session. Also updates zenai.
2026-06-05 13:35:34 +02:00
Karl Seguin
c21c683474 Better import error return
Just a random test I happen to see in WPT, 0/99 -> 99/99:

/html/semantics/scripting-1/the-script-element/json-module/invalid-content-type.any.worker.html
2026-06-05 19:21:43 +08:00
Karl Seguin
f0060dd677 add Element.style setter 2026-06-05 18:46:05 +08:00
Adrià Arrufat
88c8828224 Merge branch 'main' into agent 2026-06-05 12:43:46 +02:00
Adrià Arrufat
5f2330bb2f agent: add reasoning effort configuration
Adds the `--effort` CLI flag and `/effort` REPL command to control
the reasoning budget, persisting the setting in `.lp-agent.zon`.
2026-06-05 12:40:34 +02:00
Karl Seguin
37f5a8c819 Merge pull request #2648 from lightpanda-io/worker_isolate_terminate
Make worker more robust in the face of a disconnected CDP client
2026-06-05 18:27:01 +08:00
Karl Seguin
6ecf54fc32 Merge pull request #2649 from lightpanda-io/fix/deferred-context-uaf-on-teardown
fix: drop orphaned deferred contexts on frame teardown
2026-06-05 18:22:58 +08:00
Adrià Arrufat
76504604ba docs: update recorder details and add /logout 2026-06-05 12:14:42 +02:00
Karl Seguin
c3233867c8 Extend the TCP read/write timeout from 2 second to 10.
This limit isn't about correctness,it's just about making sure a test doesn't
block forever. 2 seconds does seem like plenty of time, but I'm thinking it's a
slow/busy CI. If it still happens after this bump, could mean there's an actual
issue.
2026-06-05 18:13:24 +08:00
Karl Seguin
5db5969c92 Merge pull request #2647 from staylor/fix/synwait-teardown-interrupt
fix(http): abort blocking-script sync wait when a teardown command is queued (#2646)
2026-06-05 17:55:51 +08:00
Karl Seguin
995efd57e6 Fix two arena leaks
The first is with WGS not flushing the deferring layer after its synchronous
importScripts call, see: https://github.com/lightpanda-io/browser/pull/2329#discussion_r3271068955

The second is from the ability of an XHR request to be re-used. This was gated
on a boolean, but the ordering means that the 1st requests' released gets
blocked by the gate, and thus we're always 1 release short. The solution is to
use a counter instead of a boolean.
2026-06-05 17:32:21 +08:00
Adrià Arrufat
157aa30bdc agent: clarify script primitives and save behavior
Updates documentation to clarify that script primitives use CSS
selectors instead of backendNodeIds. Explains how to use `/nodeDetails`
to get selectors. Clarifies the difference in `/save` behavior
between `--no-llm` and LLM modes.
2026-06-05 11:26:24 +02:00
Adrià Arrufat
d18297f204 agent: update docs for recent features and fixes
Updates documentation to reflect the new REPL status bar, JS mode,
corrected `press` syntax, and updated error messages.
2026-06-05 10:43:41 +02:00
Adrià Arrufat
3044f620b9 docs(agent): update docs for recent features and CLI flags
Updates agent-related documentation to reflect recent changes:
- Removes obsolete `follow` option from `extract` schema.
- Documents automatic printing of the script's final expression.
- Adds details on Ollama auto-detection and new CLI flags.
- Documents the `/logout` command and updated tool list.
2026-06-05 10:23:50 +02:00
Adrià Arrufat
ee21138bde fix: drop orphaned deferred contexts on frame teardown
A fetch() deferred behind a parser-blocking script keeps a DeferredContext
in the DeferringLayer whose forward.ctx points at the Fetch struct, which
lives in a page/session arena. If the transfer completes while deferred,
it is deinited and unlinked from the frame owner, so abortTransfers ->
abortOwner can't reach the now-orphaned context. It lingers in the active
list, and when the page is torn down its Fetch arena is freed; a later
flushFrame (e.g. the next page's parser-blocking script popping) replays
the buffered header callback into the freed Fetch -> use-after-free.

Add DeferringLayer.cancelFrame to drop these orphaned (terminal) contexts
during Frame.abortTransfers. Non-terminal contexts still have a live
transfer that cleans them up through its own callback path, so they are
left alone.
2026-06-05 09:47:15 +02:00
Adrià Arrufat
6c9c6df3af build: update isocline dependency 2026-06-05 09:11:24 +02:00
Karl Seguin
86b9e8675e Make worker more robust in the face of a disconnected CDP client
When a CDP client disconnects, through a series of step, we call `Isolate::
TerminateExecution`. The problem is that this only terminates the currently
executing script. If scripts are nested, or another script runs immediately
after the terminated one, the worker keeps running.

I was specifically trying to fix some 100% endless loop in a few WPT tests, e.g
Worker-terminate-forever-during-evaluation.html

The first is the issue described above. We potentially need to guard every entry
into script executing with `if (!env.is_terminated)`. AND/OR we need to bubble
an error when a script _is_ terminated (right now, most JS errors map to
error.JsException which makes this hard). For the specific WPT failures, I opted
for a more targeted fix directly in the Worker. But I think we need to keep an
eye out on other cases where this can happen.

I also discovered another issue, which is not addressed is this commit:

var worker = new Worker("endlessloop.js");
worker.terminate(); <-- never gets called

Given our current architecture, the only solution I can think of is a watcher
thread (or re-using the main/network thread).
2026-06-05 13:00:35 +08:00
Scott Taylor
0bfd0222f2 fix(http): abort blocking-script sync wait when a teardown command is queued
A blocking <script src> loads via HttpClient.syncRequest, which spins on
tick(200, .sync_wait). That drain mode only dispatches Fetch-interception
methods (it can't free Page/Frame state mid-parse), so Target.closeTarget /
Target.disposeBrowserContext / Page.close sit undispatched until the blocking
fetch completes — i.e. up to the per-request timeout, per blocking script.

For storefronts with slow/never-completing third-party subresources this
stalls page.close()/context dispose for tens of seconds and collapses CDP
throughput under concurrency (the process stays up; other connections are
unaffected).

Fix: while waiting, peek the inbox; if a teardown/close command (or a
client close/disconnect) is queued, abort the in-flight blocking transfer.
syncRequest then returns the same way it already does on a fetch failure,
the parser unwinds to the next safe .all drain, and the queued command
runs there. No command is dispatched mid-parse, so no UAF.

Repro: 8 workers looping newContext->goto(commit)->page.close against a page
with 15 never-answered subresources went from 0.1 ctx/s (page.close stalling
~30-60s) to ~25 ctx/s; a no-hanging-subresource baseline is unchanged.

Fixes #2646
2026-06-04 23:17:24 -04:00