Skip to content

Releases: slabbdev/navette

v1.9.0 — native input on all three engines (macOS verified)

Choose a tag to compare

@slabbdev slabbdev released this 08 Oct 19:04

macOS closes the native-input loop — all three engines now ship attempt-first OS-level key events.

  • macOS (new): show_window is the focus gate — the ghost's window becomes a titled key window, the Window Server must confirm isKeyWindow, and only then are CGEvents posted (a keystroke can never land in someone else's app). Single characters carry CGEventKeyboardSetUnicodeString: the delivered e.key is what the agent asked for on any layout — on AZERTY, keycode 0x00 produces 'q' natively; navette's events arrive as the requested character ('Z' uppercase with no shift). Delivery is verified in-page (isTrusted: true) before mode: native is reported; anything less falls back to synthetic, mode always reported. Live-tested: a, Enter, Z, Tab, ArrowLeft — all native, zero fallbacks. (#3)
  • Windows: SendInput (unchanged, verified end-to-end).
  • Linux: XTEST via x11rb (unchanged; X11/XWayland).
  • NAVETTE_EVAL_TIMEOUT_SECS (default 20, clamped 5–300) — slow or contended environments choose slow-success over false-timeout. (#7)

Carried from the v1.8.x train: cross-engine session isolation as a CI assertion, per-session WebView2 profiles + InPrivate, constant-time token compare, DNS-rebinding guard, credential-redacted proxy logs, docs/SECURITY.md, the CC BY 4.0 tollbooth dataset, and the signed-webhook demo.

Binaries for macOS arm64, Windows x64, Linux x64 + arm64.

v1.8.1 — session isolation on every engine, hardened loopback API

Choose a tag to compare

@slabbdev slabbdev released this 08 Oct 18:05

Cross-session cookie isolation is now a build-breaking CI assertion on macOS, Windows AND Linux.

  • Windows: every session gets its own WebView2 profile (with_profile_name) + InPrivate. InPrivate alone was not enough — all InPrivate controllers of one environment share a single profile (Edge InPrivate semantics, measured in CI); named profiles give each session an isolated cookies/storage/cache domain while sharing the runtime. (#6, closed)
  • macOS: non-persistent WKWebsiteDataStore per session (unchanged, now asserted).
  • Linux: isolated WebContexts per session, cookies never touch disk (now asserted). Known residual: WebKitGTK still writes HTTP cache/HSTS to ~/.cache/~/.local/share — needs the wry ephemeral-context lifetime fixed upstream.
  • Security hardening: constant-time token comparison; DNS-rebinding guard (non-local Host header → 403, /health exempt); --proxy URLs credential-redacted before logging.
  • Demo: demo/signed-webhook — a 150-line HMAC-chained mock counterparty; fraud analysis as a diff, not a log read (#5).

Also in this train: the tollbooth dataset is CC BY 4.0 with x402/paywall signals (v1.8.0's bench round 2), and the walled-web post is live at https://dev.to/slabb/my-agent-met-the-real-web-403s-challenges-and-the-coming-tollbooth-1h2g

Binaries for macOS arm64, Windows x64, Linux x64 + arm64.

v1.8.0 — visible session windows & real pointer events

Choose a tag to compare

@slabbdev slabbdev released this 08 Oct 12:47

The human-login loop is closed: visible session windows + real pointer events.

  • session_show / session_hide — a ghost session can come on-screen with its page state intact (setReleasedWhenClosed:false — a user-closed window is recoverable too), for the one thing automation can't do alone: the first human login (OAuth, 2FA, a captcha, a password manager). Park it off-screen again and the agent keeps driving. This is the loop the new demo/dailydev recipe runs in production.
  • /click now dispatches PointerEvents (pointerover/pointerdown/pointerup) before the mouse events — Radix and headless-UI components open like they do for a human. Found in the wild: the kebab menu on daily.dev would not open without them.
  • macOS /wait fix — the bridge stringifies JS booleans as 1 (NSNumber description), the probe compared against true, so every present selector "timed out". The probe now accepts both spellings.
  • webviewkit — the backend contract is now a single kit trait, compile-enforced per backend instead of trusted by convention.
  • Tollbooth round 2 — the walled-web bench now measures x402/paywall signals (HTTP 402, X-Payment*/X402* headers, schema.org isAccessibleForFree:false) alongside robots.txt AI clauses and llms.txt adoption: 200 URLs × 5 categories, dataset committed under CC BY 4.0 (bench/tollbooth-results.{json,csv} + bench/DATASET.md).

Binaries for macOS arm64, Windows x64, Linux x64 + arm64.

v1.7.0 — native keyboard input, honest modes

Choose a tag to compare

@slabbdev slabbdev released this 07 Oct 20:16

POST /key now attempts REAL OS-level keyboard events before the synthetic dispatch — and the response says which mode ran.

  • Windows: SendInput to the focused WebView2 render widget (child-window focus, VK mapping, proper keyup pairs). The platform where native input is verified end-to-end.
  • Linux: XTEST fake-input with a keysym→keycode scan of the live server keymap; the ghost window is brought on-screen and focused first.
  • macOS: wired but reports native unavailable for now — CGEvents post, but routing into a headless WKWebView needs an app-bundle activation story the Window Server only grants real foreground apps (the experimental on-screen approach is preserved in git history).

Every response carries a mode field: native or synthetic. No lies in the protocol — when the native path refuses (headless CI, missing permissions), the synthetic fallback fires automatically and the caller knows exactly what happened.

Also fixed: the Linux key path no longer pumps GTK from the HTTP thread (a worker-thread gtk::main_iteration deadlocks the main loop — CI exit 52).

Binaries for macOS arm64, Windows x64, Linux x64 + arm64.

v1.6.0 — the operator release

Choose a tag to compare

@slabbdev slabbdev released this 07 Oct 13:32

Deploy navette on machines that are not yours.

  • --token SECRET: Bearer auth on every HTTP route (except /health) — Authorization: Bearer or X-Navette-Token. An MCP host attaches to a protected serve with the NAVETTE_TOKEN env var. Loopback-only was never enough for shared machines and lab LANs.
  • --proxy URL: HTTP CONNECT or SOCKS5, applied at webview creation on the wry backends (soup / WebView2 options / Network framework). Proxy credentials in the URL are refused loudly — the engine layer doesn't carry them; use IP allowlisting. macOS follows the system proxy.
  • --user-agent UA: per-serve override at webview creation, WKWebView included.
  • linux-arm64 joins the release assets (aarch64 Linux is where agents actually run).

All three flags validated live: 401 without/with wrong token, 200 with Bearer and X-Navette-Token; navigator.userAgent override confirmed; a bogus --proxy blocks navigation while the API stays reachable.

Binaries: macOS arm64, Windows x64, Linux x64 + arm64.

v1.5.0 — the idle watchdog

Choose a tag to compare

@slabbdev slabbdev released this 06 Oct 08:59

The daemon keeps its reflexes and gives back its memory.

  • serve --idle-release <minutes>: sessions untouched for that long are dropped whole — window, webview, WebKit helper processes — while the daemon itself stays resident. The next request re-creates and re-warms on demand (the pre-warm path, 83 ms on the CI VM). 0 = off, the original always-warm promise. Idea credit: reid's point that local MCP helpers either hold VRAM forever or pay full startup every call — this is the middle path. Validated live on macOS (drop via the main thread) and Linux (drop via the event loop).
  • bench/tollbooth.py: ~200 real URLs across five categories (docs, news, e-commerce, dev-tools, social), measuring three independent walls per site — robots.txt AI clauses (10 agent user-agents), llms.txt adoption, and the agent path itself: real WebKit over a residential IP, classified ok / challenge / empty-js-gate / timeout. The dataset lands in the repo.
  • README FAQ: the native-vs-ML extraction trade documented with both orders of magnitude (~10 ms/page DOM walk vs ~600 ms/page trained models) — two trades, not a ranking.

Binaries attached for macOS arm64, Windows x64, Linux x64.

v1.4.1 — --help / --version

Choose a tag to compare

@slabbdev slabbdev released this 04 Oct 18:46

A distributed CLI without --help is a broken first impression: unknown arguments used to silently start a serve. Now:

  • navette --help — usage, modes, routes
  • navette --version / -V / version

Binaries attached for macOS arm64, Windows x64, Linux x64.

v1.4.0 — upload, scroll, 16 tools

Choose a tag to compare

@slabbdev slabbdev released this 04 Oct 15:39

The agent loop is complete: upload, scroll, and every previous primitive, on all three OSes.

  • POST /upload: fills a file input with in-memory content through a page-side DataTransfer — no OS dialog, identical JS on WKWebView, WebView2 and WebKitGTK. The CI smoke now proves a full round-trip: upload a 5-byte file, let the page's own JS read it, assert name:size.
  • POST /scroll: absolute Y offset or scrollIntoView (centered).
  • 16 MCP tools: hover, key, scroll, upload, viewport joined the original set.
  • eval_js fix worth the release on its own: the evaluation wrapper discarded its value on Windows/Linux — every /evaluate and /read call silently returned undefined. CI now tests evaluate explicitly. (navigate → read through the fold path was never affected.)
  • bench workflow (workflow_dispatch): 30-page corpus, median/p95 for navigate+read, /read and /screenshot per engine, results in the step summary.

Known gaps, stated plainly: OS-level keyboard/mouse input (synthetic events today), request/response network interception, OS file-dialog automation.

Binaries attached for macOS arm64, Windows x64, Linux x64.

v1.3.0 — full platform parity

Choose a tag to compare

@slabbdev slabbdev released this 04 Oct 15:11

navette now does everything on every OS it runs on.

  • Screenshots everywhere: WKWebView snapshot (macOS), PrintWindow PW_RENDERFULLCONTENT on the WebView2 render widget (Windows), X11 capture of the on-screened ghost window under a GTK pump (Linux). CI verifies a valid PNG on all three OSes.
  • Cookie state everywhere: export/import with one JSON schema across OSes — an authenticated session saved on macOS restores on Linux. The Playwright storageState equivalent, no Chromium attached.
  • Viewport control per session (screenshot dimensions follow it).
  • Resident daemon on every platform: LaunchAgent (macOS), schtasks ONLOGON (Windows), systemd user unit (Linux).
  • JS dialogs auto-handled in-page — alert no-ops, confirm accepts, prompt returns its default. Agents can no longer deadlock on a hidden modal.
  • hover and key events join the API. 14 MCP tools now.
  • Fixed a macOS cookie-import deadlock along the way (raw multi-argument msg_send replaced with typed Foundation APIs).

Binaries for macOS arm64, Windows x64 and Linux x64 are attached. One binary, ~630 KB, no Chromium download. Install: drop the file anywhere, run navette serve, or point your MCP host at it. CI green on all three OSes with the full smoke (navigate, read, screenshot, cookie round-trip).

v1.2.1 — cross-platform smoke green

Choose a tag to compare

@slabbdev slabbdev released this 04 Oct 13:28

The hardening release: navette now passes the same runtime smoke on all three OSes.

  • CI green on macOS (WKWebView), Windows (WebView2) and Linux (WebKitGTK) — health, navigate, fold, read on every push.
  • Five root-cause fixes behind the wry smoke failures:
    1. the fold result had no route back to the HTTP caller (pending consumed twice)
    2. page-load completion was not URL-matched — the initial about:blank load swallowed a cold-start navigate
    3. the fold wrapper discarded the extraction expression's return value
    4. gtk_init blocked on the missing D-Bus session bus in headless CI (gdb-proven)
    5. WebView2 stalls ~45 s on file:// URLs on GPU-less CI VMs — loopback http it is
  • Boot-time session pre-warm (parity with the macOS backend): first navigate on the CI VM went 38 s → 83 ms.
  • macOS remains the fully-featured platform: screenshots, cookie state export/import, resident daemon. wry parity lands next.

One binary, 626 KB, no Chromium attached.