Add dedicated documentation pages for each cloud browser provider:
Browser Use, Browserbase, Browserless, and Kernel (sorted
alphabetically). Uses providers/ path per maintainer feedback.
- Fix Kernel defaults to match source code (KERNEL_HEADLESS=true,
KERNEL_STEALTH=false) — README had these inverted
- Add Providers section to sidebar navigation
- Simplify cdp-mode cloud providers section to link to new pages
Fixes part of #774
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The codebase only has CDP launchers for Chrome and Lightpanda
(cdp/chrome.rs, cdp/lightpanda.rs). Firefox and WebKit have no
launcher and are not supported.
Fixes part of #774
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Move JS metadata exports out of page.mdx files into per-directory
layout.tsx files. MDX files now contain pure markdown content, making
them render cleanly on GitHub without visible JS import/export lines.
No content changes — only the metadata mechanism is relocated.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The test was reading AGENT_BROWSER_HEADED without holding ENV_MUTEX,
causing a race with test_launch_options_from_env_headed_flag when
tests run in parallel.
Root cause: package.json `main` pointed at `dist/daemon.js` (the
internal daemon process), so programmatic consumers of the package
received the daemon module instead of a usable API. Additionally,
`BrowserManager.launch()` required IPC-only fields (`id`, `action`),
and `navigate()` existed only as a private function inside actions.ts.
Changes:
- Add src/index.ts as the public package entry point
- Add BrowserLaunchOptions type (Pick<LaunchCommand> minus id/action/engine)
to decouple the programmatic API from the IPC wire protocol
- Change launch() signature from LaunchCommand to BrowserLaunchOptions
- Add BrowserManager.navigate(url, options?) — consolidates domain check,
scoped-header setup, and page.goto() into one reusable method; auto-
recovers a new page when all pages have been closed (stale session)
- Add BrowserManager.getUrl() and getTitle() convenience methods
- Update package.json: main → ./dist/index.js, add types and exports["."]
- Add tests: navigate() with headers, waitUntil, allowedDomains blocking,
allowedDomains allow, non-http(s) scheme blocking, getUrl/getTitle, and
compile-time type assertions verifying the public entry exports the right
API surface (direct repro of #307)
Fixes#307
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
The client (connection.rs) and native daemon (native/daemon.rs) used
different get_port_for_session() implementations on Windows:
- Client: i32, .chars(), djb2 — (hash << 5) - hash + c
- Daemon: i64, .bytes(), Java hashCode — hash * 31 + b
For session name "default", client computes port 50838 while the
daemon binds on 51174, causing a 5-second timeout and startup failure.
Fix: align native/daemon.rs to use the identical djb2 algorithm from
connection.rs (i32, chars, djb2), so both sides agree on the port.
Unix is unaffected (uses Unix domain sockets, no port hashing).
Tests: add port hash regression tests to all three implementations
(native/daemon.rs, connection.rs, daemon.ts) to prevent future drift.
Fixes#705
When launched with --extension or --profile, launchPersistentContext()
is used which sets isPersistentContext=true but leaves this.browser as
null. The guard in newTab() checked !this.browser, causing a false
"Browser not launched" error even though the browser was running.
Replace !this.browser with !this.isLaunched(), which already accounts
for both launch paths (browser !== null || isPersistentContext).
Also improve the error message in newWindow() to clarify that it is
not supported in persistent context mode, since it requires a Browser
object to create a new context.
Fixes#411