browser39 1.7.0

Headless web browser for AI agents
# Changelog

## [1.7.0] - 2026-04-29

### Added

- **Decision-grade MCP tool descriptions** — every `browser39_*` tool now ships a structured description (purpose / USE WHEN / NOT WHEN / Effect class / Common failures with repair moves) so agents can pick the right tool before inspecting parameters and self-correct on errors. Effect classes follow a `read | local-mutate | external-mutate | irreversible` taxonomy.
- **Selector reference doc** (`docs/selectors.md`) — canonical CSS3-only cheat sheet, stable-vs-fragile guidance, and pitfalls (no XPath, no `:contains()`); every selector field doc-comment now points to it.
- **MCP tool schema snapshot test** (`src/mcp/snapshots/tool_schema.snap`) — locks the rendered tool list so unintended description or schema changes surface as a reviewable diff. Update intentionally with `UPDATE_SNAPSHOTS=1 cargo test tool_schema_snapshot`.

### Changed

- Param-level doc comments rewritten across `FetchParams`, `ClickParams`, `DomQueryParams`, `FillParams`, `FillFieldParam`, `SubmitParams`: secret-handle hints on credential values, `index`/`text` disambiguation on `click`, `value`/`outerHTML`/`textContent` added to documented `attr` options, `AUTH_PROFILE_DOMAIN_MISMATCH` wired into `auth_profile` docs.
- `docs/jsonl-protocol.md` and `docs/install-cli.md`: replaced stale `boa_engine` references with `deno_core` (V8) and added a top-level pointer to the selectors doc.

### Fixed

- Documentation drift: JSONL protocol doc previously described a pure-Rust JS engine surface; now reflects the actual `deno_core` sandbox capabilities (full DOM API, events, console capture).

## [1.6.3] - 2026-04-25

### Added

- **RSS / Atom / RDF feed rendering** — XML feeds (RSS 2.0, RSS 1.0/RDF, Atom 1.0) are now detected by `Content-Type` (with body sniff fallback for mislabeled servers) and converted to clean, token-optimized markdown instead of the previous run-on-text result. Each item renders as `## [title](link)` followed by a `date · category` meta line and the description; the channel/feed title becomes the H1.
- New `src/core/feed_to_md.rs` module with 12 unit tests covering all three feed formats, namespace prefixes (`dc:`, `rdf:`), CDATA-wrapped HTML descriptions, Atom `rel="alternate"` link routing, and graceful partial-parse on malformed XML.
- New dependency: `quick-xml = "0.37"`.

### Changed

- Feed dispatch runs **before** the meta-refresh redirect loop — XML feeds skip the wasted scan since they never carry HTML meta-refresh.
- `estimate_tokens`, `truncate_markdown`, and `collapse_inline_whitespace` in `html_to_md` are now `pub(crate)` so the feed module can reuse them.

### Fixed

- `core::config::tests::test_load_full_config` no longer hardcodes a stale user-agent version that broke on every release bump — the test now exercises the default-user-agent path it was always meant to cover.

## [1.6.2] - 2026-04-16

### Changed

- Crate metadata cleanup: shorter `description`, explicit `authors`, and `exclude` list to keep `cargo package` lean. No code changes.

## [1.6.1] - 2026-04-12

### Added

- **npm distribution**`npm install @aquintanar/browser39` installs the correct platform binary automatically. Supports macOS (arm64, x64), Linux (x64, arm64), and Windows (x64).

### Fixed

- Removed unused `SEL_HEAD` static (dead code warning)
- Updated yanked `fastrand` v2.4.0 to v2.4.1

## [1.6.0] - 2026-04-05

### Changed

- **JavaScript engine migrated from boa_engine to deno_core (V8)** — full ECMAScript compliance, JIT compilation, and the foundation for SPA support (React/Vue/Angular)
- DOM shim architecture redesigned: Rust `#[op2]` ops for data access + JS bootstrap for object wrappers (replaced 3,650 lines of boa closures with ~970 lines of ops + ~300 lines of JS)
- Event handler and setTimeout errors are now logged to `console_output` instead of silently swallowed
- `serde_v8` used for V8-to-JSON conversion (replaces hand-rolled converter)

## [1.5.0] - 2026-04-04

### Added

- **Full JavaScript DOM API** — massively expanded the JS sandbox beyond basic `querySelector`:
  - **DOM traversal**: `parentElement`, `parentNode`, `children`, `childNodes`, `childElementCount`, `firstChild`, `lastChild`, `firstElementChild`, `lastElementChild`, `nextSibling`, `previousSibling`, `nextElementSibling`, `previousElementSibling`
  - **DOM lookup**: `getElementById`, `getElementsByClassName`, `getElementsByTagName`, `getElementsByName`, `document.forms`, `document.links`
  - **DOM mutation**: `createElement`, `createTextNode`, `appendChild`, `removeChild`, `insertBefore`, `element.remove()`, `setAttribute`, `removeAttribute`, `textContent` setter, `innerHTML` setter
  - **Element properties**: `matches(selector)`, `closest(selector)`, `contains(node)`, `hasAttribute`, `classList` (contains/length/item), `dataset` (data-* to camelCase), `nodeType`, `nodeName`, `disabled`, `checked`, `hidden`, `type`, `name`, `src`, `alt`, `placeholder`
  - **Event system**: `addEventListener`, `removeEventListener`, `dispatchEvent` with listener storage; `new Event`, `new CustomEvent`, `new MouseEvent`, `new KeyboardEvent`, `new InputEvent`, `new FocusEvent` constructors
  - **Console**: `console.log/warn/error/info/debug` — output captured and returned in `console_output` field
  - **Timers**: `setTimeout` (synchronous execution), `setInterval`/`clearInterval` (no-op), `requestAnimationFrame` (synchronous)
  - **Utilities**: `atob`/`btoa` (base64), `getComputedStyle` (stub), `MutationObserver` (no-op stub)
- **`--version` CLI flag**`browser39 --version` prints the version
- **Config version tracking** — config.toml now includes a `version` field; auto-updated on load when the binary version changes

### Changed

- JS sandbox internals refactored from single file (`dom_script.rs`) into `dom_script/` submodule (mod, element, document, window, events, convert) for maintainability
- DOM backing migrated from `Rc<Html>` to `Rc<RefCell<Html>>` to support mutation
- Mutated DOM is serialized back and stored in session state after script execution
- Default user-agent now matches binary version (`browser39/1.5.0` instead of `browser39/0.1`)
- MCP tool descriptions expanded to document JS capabilities for LLMs
- `DomQueryParams.script` field doc now lists every available DOM API
- Plugin manifests updated to 1.5.0

## [1.1.0] - 2026-04-04

### Added

- **10 MCP config management tools** — agents can now manage browser39's configuration directly via MCP:
  - `browser39_config_show` — view config with sensitive values masked (never exposes raw file)
  - `browser39_config_set` — set scalar settings (search engine, timeouts, session defaults)
  - `browser39_config_auth_set` / `browser39_config_auth_delete` — manage auth profiles (credentials stored securely, never returned via MCP)
  - `browser39_config_cookie_set` / `browser39_config_cookie_delete` — manage preloaded cookies
  - `browser39_config_storage_set` / `browser39_config_storage_delete` — manage preloaded storage entries
  - `browser39_config_header_set` / `browser39_config_header_delete` — manage default header rules
- Config changes are saved to disk atomically and take effect immediately (live reload)
- Security config changes (redaction patterns, sensitive cookie names) are applied to the running redaction engine without restart

### Changed

- Release binaries now use versionless names (`browser39-macos-arm64` instead of `browser39-v1.0.0-macos-arm64`) for stable download URLs
- Install prompts simplified — direct binary download from GitHub releases, no Rust toolchain required
- Config structs now implement `Serialize` for TOML round-tripping
- `Config::resolve()` is now public for use after config mutations

### Fixed

- `build.sh` restored (accidentally deleted in v1.0.0)

## [1.0.0] - 2026-03-28

Initial release.

- Headless web browser for AI agents with HTML-to-Markdown conversion
- 19 MCP tools: fetch, click, links, DOM query, forms, cookies, storage, search, history, navigation
- 4 MCP resources: page markdown, links, metadata, cookies
- JavaScript execution via boa_engine
- Session persistence with AES-256-GCM encryption
- Auth profiles with domain enforcement and secret redaction
- Content preselection with section-level token estimates
- MCP (stdio + HTTP), JSONL (watch + batch), and CLI transports
- Pre-authenticated startup via config (cookies, storage, headers)