Commit Graph
101 Commits
Author SHA1 Message Date
Muki Kiboigo ee2b97d9f8 fix ordering of store help entries 2026-09-24 12:24:54 -07:00
Muki Kiboigo 4afdc412ee add cors-store-entry-limit option 2026-09-23 07:33:14 -07:00
Karl Seguin 4a7590691d Merge pull request #3546 from lightpanda-io/robots-limit-entries
Robot Limit Entries
2026-09-23 07:31:30 +08:00
Muki Kiboigo d16091a403 0 for robot entry limit means no limit 2026-09-22 12:55:26 -07:00
Karl Seguin 6b28f986e6 Merge pull request #3586 from lightpanda-io/webdriver-http-limit
webdriver: increase http default / max limit
2026-09-21 18:55:53 +08:00
Karl Seguin ee4d54928d webdriver: increase http default / max limit
The http max default was 4K with a 16KB hard limit. The default limit is now 1MB
with an initial default of 4K. This is to accommodate larger WebDriver payloads.
2026-09-21 17:52:41 +08:00
Halil Durak e67301a0fb cookies: accept Netscape cookie format when loading from CLI 2026-09-18 17:19:21 +03:00
Muki Kiboigo 9fa9e5ae0d add robot store entry limit option 2026-09-17 20:00:09 -07:00
Adrià Arrufat fc13928672 agent: document the OpenRouter and OrcaRouter providers
zenai now ships openrouter and orcarouter presets (OPENROUTER_API_KEY /
ORCAROUTER_API_KEY, provider-prefixed model ids). The provider enum is
derived from zenai, so only the help text, key hint, and README need
to name them.
2026-09-16 12:21:34 +02:00
Karl Seguin 7571d6e7a0 Merge pull request #3527 from lightpanda-io/nikneym/stdin-js-exec
`Agent`: add `lightpanda run -`
2026-09-16 06:40:41 +08:00
Pierre Tachoire 9bf65fac5a add missing LLM providers in help 2026-09-15 18:34:24 +02:00
Pierre Tachoire c1ddf920ec document --dump pdf in help 2026-09-15 18:13:33 +02:00
Pierre Tachoire 580658676e remove the removed --storage-* from help 2026-09-15 18:11:30 +02:00
Halil Durak 901e5eaf4d Agent: add lightpanda run -
Arbitrary JS code can be passed directly through stdin thanks to this.
2026-09-15 16:21:01 +03:00
Karl Seguin e8f6591411 address feedback
remove --strip-mode full   (and all `full` support from cli, because it makes
backwards-compatibility a pain)
2026-09-11 06:36:49 +08:00
Karl Seguin 5bc4f7482c render: add "clutter" option to --strip-mode
Adds a `clutter` option to --strip-mode. This is based on readability.js. It
isn't a direct port (e.g. it doesn't strop bylines). It fallsback to `shell` if
it strips too much (and shell itself can fallback to not stripping anything).
But clutter rarely fallback to shell, only when a page is very small or when
it strips out _a lot_.

Also expanded shell to look at class names and ids.
2026-09-11 06:36:48 +08:00
Karl Seguin cdceca37c3 render: add "shell" option to --strip-mode
Some additional API changes:
- Add strip-mode support to pdf/png generation.
- Add LP.dump which provides greater content gathering capability to CDP,
  exposing most `fetch` dump-related parameters (e.g. format, strip, selector,
  ...)

The new "--strip-mode shell" is designed to try to remove non-content elements
such as the header and footer. The end goal is to use readibility.js test cases
as a baseline, but this isn't a port of readibility.js.

This is just the basic implementation of this, e.g removing a few key tags, e.g.
<header>, <footer> and considering some specific roles.

Even if --strip-mode shell is used, we might decide to stick with a whole dump:
it's better to strip not enough than to strip too much. This currently works by
measuring the ratio of non-link text of the stripped vs unstripped page.
2026-09-11 06:35:26 +08:00
Karl Seguin bcf69ced9c address feedback
tighten socket ownership (on error paths)

allow reaper to be disabled

Handle window where link is being destroyed, worker is still alive, and client
attempts to re-link.
2026-09-11 05:11:36 +08:00
Karl Seguin 8ad9eaf48d webdriver: HTTP WebDriver session management
This is a small step towards WebDriver supports (non-bidi). It allows creating
and deleting a BiDi "Session" (e.g. a worker). It also allows attaching a BiDi
driver to an HTTP-created BiDi session (the typical selenium startup flow).

This change unblocks the most basic setup/teardown of Selenium, so it still
isn't enough to actually use a Selenium script as-is. But it's significant
because it models a worker (thread) that isn't tied to a WebSocket, something we
haven't had before.

A consequence of a pure HTTP Session is that we don't have a clear cleanup
signal. There is no "the socket is disconnected". There's a new HTTP reaper
which kills HTTP Sessions after --http-session-timeout. It's expected that
drivers properly DELETE /session/:id. I imagine we're going to run into
--cdp-max-connections limits and need to tweak this code. BUT, this entire flow
is only enabled with --protocol webdriver, so it won't impact exiting CDP users.
2026-09-11 05:11:26 +08:00
Karl Seguin 58e1a547d8 fix help ordering, remove unnecessary pub 2026-09-10 07:41:34 +08:00
Adrià Arrufat c55afc1df9 cli: add --locale and --timezone, derive language signals from one value
navigator.language was hard-coded to en-US and Accept-Language was a
constant, while Intl, toLocaleString and Date followed the host process
environment. On a de_DE host a page saw navigator.language === "en-US"
next to German number formatting, a mismatch fingerprinting scripts look
for, and the same page rendered differently across machines.

Follow Chrome's --lang rule: one configured tag drives navigator.language(s),
the Accept-Language header and ICU's default locale. --locale defaults to
en-US, so Intl is now en-US on every host instead of whatever LANG says.
--timezone sets the IANA zone Date and Intl use; absent, the host zone stays.

Both are applied by writing LC_ALL and TZ before V8 initializes ICU, which
reads them lazily. Platform.init is the first call in App.init, before any
thread exists, so setenv is safe there.

CDP Emulation.setUserAgentOverride.acceptLanguage, which Playwright sends
for its locale option, now overrides the header and navigator.languages
for the browser context's lifetime, mirroring the user agent override, and
applies even when the Mozilla user agent is refused.

Emulation.setLocaleOverride and setTimezoneOverride stay no-ops: changing
ICU's defaults at runtime needs new zig-v8-fork bindings.
2026-09-09 17:49:02 +02:00
Karl Seguin 82344c609f Merge pull request #3432 from lightpanda-io/tweak-http-timeouts
http: tweak http timeouts
2026-09-07 17:41:46 +08:00
Halil Durak 814a2ab549 update Config + help.zon 2026-09-07 10:57:35 +03:00
Karl Seguin ec61861b20 http: tweak http timeouts
change --http-timeout default to 15000 (up from 5000)
change --http-connect-timeout default to 8000 (down from 300000, curl's default)

5 second _total_ transfer time can be a little tight. I generally don't see a
good reason to overly limit this value.

Worth noting that help.zon said the default for --http-timeout was 10000, but
it was, in fact, 5000.

Hopefully this improve situations like https://github.com/lightpanda-io/browser/issues/3395
which I believe are due to slow proxies.
2026-09-07 13:19:52 +08:00
Muki Kiboigo 15d27902ba use experimental features flag instead of obey cors 2026-09-04 07:00:01 -07:00
Muki Kiboigo ec45dccacf add obey_cors option 2026-09-04 06:59:38 -07:00
Karl Seguin 731774ab67 ops: Allow serving both cdp and bidi on the same port
--protocol can now be specified multiple times. This just makes ops/dev easier
by only requiring 1 instance.
2026-08-31 22:45:15 +08:00
Karl Seguin 7dd4496b0f cli: add --http-version 1.1 / auto flag
https://github.com/lightpanda-io/browser/issues/3348

When set to 1.1, libcurl is configured to only offer HTTP 1.1. By default, or
when set to "auto", it's up to libcurl to decide how to connect. This maps to
libcurl's CURL_HTTP_VERSION_1_1 and CURL_HTTP_VERSION_NONE.

LP.configureCDP now takes an `httpVersion` field which can be "1.1" or "auto"
to control that specific browser session. Ideally this is called prior to any
navigation.
2026-08-31 16:16:47 +08:00
Karl Seguin db258bfec4 breaking: disable worker and iframe loading by default
By default, iframes and workers no longer loaded. Use `--load-resources iframe`
and `--load-resources worker` to restore the previous behavior. The disabling
makes resource loading more consistent.

To further make things more consistent, Config seems the following changes:

1. remove  `--timeout` from `serve` which does nothing but has printed a
   deprecation warning for a long time

2. added .deprecated field to CLI config flags which now logs the specified
   deprecated warning when used

3. `--log-filter-scopes` is deprecated in favor of `--log-scopes`

4. `--disable_subframes` is deprecated. Iframe loading is disabled by default,
    use `--load-resources iframe` to enable iframe loading

5. `--disable_workers` is deprecated. Worker loading is disabled by default,
    use `--load-resources worker` to enable worker loading

6. `--enable_external_stylesheets`  is deprecated. Stylesheets remain disabled
    by default. Use `--load-resources stylesheet` to enable loading external
    stylesheets

CLI log parameters now alter the logger behavior on parse. This helps minimze
the window where default log settings are in-play. It also means things like
this work:

```
./lightpanda --log-level fatal --disable_subframes --log-level warn
```

More seriously, there's now an optional `beforeParse` fired once the mode is
known. This is used by mcp to set the default log level to logfmt. Previously
this was done much later and could easily result in a mix of pretty and logfmt
logs.
2026-08-27 17:25:42 +08:00
Adrià Arrufat 6811cc8226 fetch: per-page errors, an "error" field in --json, --fail-on-http-error
A wait failure on one URL aborted the whole multi-URL fetch with no
output, the wait_ms budget was computed once before the loop so N pages
could take N times the budget, navigation failures exited 0 with an empty
dump, and HTTP 4xx/5xx were indistinguishable from success by exit code.

Each page now has its own error slot: wait, navigation and dump failures
are recorded there instead of returned, every page is still written (the
JSON envelope carries the name under "error"), then the first failure is
returned so the process exits 1. The remaining budget is recomputed per
page. --fail-on-http-error turns a status >= 400 into exit 22, curl's
code for the same condition; the dump is written first either way.
2026-08-26 15:35:15 +02:00
Adrià Arrufat 1fb7a1b983 fetch: namespace the dump options in Config too 2026-08-26 15:34:15 +02:00
Adrià Arrufat e46964e261 markdown: reuse dump's shouldStripElement 2026-08-26 15:32:25 +02:00
Adrià ArrufatandKarl Seguin c78c1d3823 fetch: namespace dump flags
Co-authored-by: Karl Seguin <karlseguin@users.noreply.github.com>
2026-08-26 15:28:18 +02:00
Adrià Arrufat d3bad960c3 fetch: add --selector and --max-bytes, honor --strip-mode for markdown
--strip-mode was silently ignored for --dump markdown, and fetch had no
way to scope a dump to one element or cap its size although the markdown
and html tools have both.

--selector dumps the first matching element in any dump mode, --max-bytes
caps html and markdown with the tools' truncation marker, and markdown
now honors strip ui (images; scripts, styles and hidden elements are
never rendered, so the other groups don't apply).
2026-08-26 13:23:18 +02:00
Halil Durak 3265d66052 change how --load-resources are provided from CLI 2026-08-25 14:18:47 +03:00
Halil Durak 6f7aa67c21 update help.zon 2026-08-25 14:18:45 +03:00
Karl Seguin 289502e19a Merge pull request #3231 from lightpanda-io/screenshot
Screenshot
2026-08-25 18:12:00 +08:00
Karl Seguin 09edfd3ce5 http: Add optional rate limit
Add an optional per-host rate limit. This currently only applies to the top-
level navigation. This makes it simpler to implement and simpler to reason
about. The full load of a page is only ever delayed at its head, not
sporadically through the page loading.

The use-case where a RateLimiter is most useful is when the browser is crawling
multiple pages of the same site, and in that case, the top-level rate limit
still applies some degree of limit to any linked resources (e.g. a JS on a
different host).

`--http-nav-delay` is the delay, in milliseconds, to apply to top level
navigates per host. Currently defaults to 0 (disabled).

`--http-nav-burst` is the burst allowed per host. Defaults to 1 (has no impact
when `--http-nav-delay` is disabled).
2026-08-20 16:03:42 +08:00
Karl Seguin ff5b791b7e wip: screenshot 2026-08-19 21:49:02 +08:00
Karl Seguin 34ca271b33 Merge pull request #3221 from lightpanda-io/option-multiple
undocument comma separated list option
2026-08-18 17:03:29 +08:00
Pierre Tachoire 25c85d9de4 undocument comma separated list option 2026-08-18 09:50:30 +02:00
Karl Seguin 5c0aa90ea4 Merge pull request #3187 from lightpanda-io/http-header-option
add --http-header option to send headers on every HTTP requests
2026-08-18 15:24:10 +08:00
Pierre Tachoire 53f939be92 adjust --http-header help 2026-08-18 08:59:11 +02:00
Pierre Tachoire 33867c7275 Merge pull request #3116 from lightpanda-io/nikneym/adblocker-init
Initial implementation for easy list parsing and AdBlocker
2026-08-18 08:50:42 +02:00
Pierre Tachoire a6afdce444 add --http-header option to send headers on every HTTP requests 2026-08-17 17:18:13 +02:00
Karl Seguin a3034105aa chore: Move cache maintenance to startup and browser.deinit
--http-cache-entry-limit is currently implemented as a hard-limit via a check
on every put. For a large --http-cache-entry-limit, this can result in a non-
trivial delay on every http get.

This commit calls cache.maintenance() on Browser.deinit and on startup.
maintenance:
1 - purges stale entries
2 - enforces the limit

With concurrent requests, the number of entries can easily exceed the limit by
hundreds of entries (but this is temporary).
2026-08-14 15:55:37 +08:00
Halil Durak cab06bdf8a add an help.zon entry for --adblock-lists 2026-08-13 16:39:13 +03:00
Karl Seguin 9eba476615 Merge pull request #3157 from lightpanda-io/http-cache-limit
Entry Limit for HTTP Cache
2026-08-10 13:14:30 +08:00
Muki Kiboigo e26a200146 add http cache entry limit options 2026-08-06 13:29:05 -07:00
Adrià Arrufat d79fb2fa6c fetch: default --wait-until to load
The implicit default was done (full quiescence), capped at --wait-ms.
Pages with constant background activity (ad timers, live sockets) never
go quiescent, so every default fetch of such a page silently rode the
full 5s cap; the timeout is non-fatal (Runner.waitForAll discards
WaitResult.timeout), so the default was effectively "wait 5s, then dump
whatever is there". load matches the agent/MCP default_nav_wait and its
rationale.

Measured on an ad-heavy news hub (ReleaseFast, interleaved runs):
default now ~3.2s vs 5.8-5.9s with done, with the load-time dump
containing slightly more of the extracted content, not less (the extra
seconds of ad-script execution mutate the page, they do not add to it).
A quiet page dumps byte-identical output under both.

Explicit --wait-until done|networkidle and --wait-selector/--wait-script
are unchanged; the fetch() doc comment now describes when error.Timeout
can actually be raised (selector/script phases only).
2026-08-06 13:22:48 +02:00