This piggybacks on the HttpClient rework (1) and makes incoming WebSocket
messages get delivered in a similar fashion. Namely, WebSocket events (connect,
data, close) are queued and only delivered at safe points. The goal is to make
sure JS is never run during a libcurl callback. This has historically caused
issues and currently requires the HttpClient to have various guards (e.g.
performing flag, dirty queue, etc..).
This change removes the last cases where JS could be executed within a libcurl
callback. Consequently, HttpClient is simplified. It no longer has a perfoming
flag nor a dirty queue nor ready queue.
(1) https://github.com/lightpanda-io/browser/pull/2889
HTMLAreaElement only implemented the URL/HTMLHyperlinkElementUtils mixin
(href, origin, protocol, host, ...). The area-specific reflected IDL
attributes were missing, so alt, coords, shape, target, download, rel,
referrerPolicy and relList all read back as undefined.
Reflect them the same way HTMLAnchorElement and HTMLLinkElement do:
plain string reflection for alt/coords/shape/target/download/rel,
enumerated reflection for referrerPolicy, and the shared DOMTokenList
helper for relList (guarded to html/svg namespaces). ping is left out to
match the current HTMLAnchorElement precedent. Adds an area.html test.
The EventSource API only requires a simple line-based parser. It's pretty
straightforward. It's RC'd by v8 and itself, but also by scheduled tasks (e.g.
to reconnect).
The bigger change is to the HttpClient to support streaming requests. This
changes to things:
1 - A transfer doesn't only deliver() once
2 - A transfer can be in the multi while delivering
Neither of these are surprising, but they both add complexity.
There's 1 WPT test that returns a 8GB value content-length (testing failures)
and the u32 limit fails to parse it and makes it as though no content-length
header exists.
Adds a /metrics endpoint in serve mode. Can be disabled via --disable-metrics.
In fetch, dumps the metrics if --metrics is specified (defaults to false).
None of the metrics being collected are on a hot path, so they're just always
collected using atomic operations (i.e. no `if (!enabled) return;`). Because
the operations are cheap and infrequent enough not to matter.
The one place I want to add more metrics is in HttpClient (bytes, status,
counts, ...) but after the pending HttpClient-related PR is merged.
./lightpanda fetch --log-level fatal --metrics "https://lightpanda.io/"
```
build_info{version="1.0.0-dev.7837+70493ce35"} 1
cdp_connections_total 0
cdp_connection_limit_total 0
cdp_active_connections 0
cdp_commands_total 0
cdp_unknown_commands_total 0
js_heap_limits_total 0
script_errors_total 0
arena_hit_total{size="tiny"} 908
arena_hit_total{size="small"} 35
arena_hit_total{size="medium"} 0
arena_hit_total{size="large"} 27
arena_miss_total{size="tiny"} 193
arena_miss_total{size="small"} 31
arena_miss_total{size="medium"} 5
arena_miss_total{size="large"} 23
navigate_total{type="page"} 1
navigate_total{type="iframe"} 0
navigate_total{type="popup"} 0
js_heap_size_bytes_bucket{le="4194304"} 0
js_heap_size_bytes_bucket{le="8388608"} 0
js_heap_size_bytes_bucket{le="16777216"} 1
js_heap_size_bytes_bucket{le="33554432"} 1
js_heap_size_bytes_bucket{le="67108864"} 1
js_heap_size_bytes_bucket{le="134217728"} 1
js_heap_size_bytes_bucket{le="268435456"} 1
js_heap_size_bytes_bucket{le="536870912"} 1
js_heap_size_bytes_bucket{le="+Inf"} 1
js_heap_size_bytes_sum 11223040
js_heap_size_bytes_count 1
```
In a custom element, when this.innerHTML = '....' is called, we need to be
careful to prevent endless recursion. The html5ever callback used to determine
the context element should not invoke the custom-element constructor, else we'll
enter an endless loop.
This also fixes an ungating problem added with the new HttpClient when a
waitForImport can block forever.
Both issues were see on a WooCommerce site - though the HttpClient is only
due to an earlier HttpClient refactor.
- Links now emit OSC 8 hyperlinks (clickable where supported) with a dim
url fallback; a bare link (label == url) drops the redundant suffix.
- Blockquote lines (`> `) render with a dim bar.
- Horizontal rules (`---`/`***`/`___`) render as a dim line.
- Backslash escapes unescape only markdown-special chars, leaving e.g.
C:\\Users intact.
Style the assistant's answer in the interactive agent REPL with ANSI
escapes: headings, bullet/numbered lists, bold/italic/inline-code/strike,
and links. Rendering is gated to the REPL on a real terminal, so
`--task`/piped output stays verbatim for programmatic consumption.
Adds src/agent/md_term.zig (markdown -> ANSI renderer) and wires it into
Terminal.printAssistant.
When deciding what type of window to return, we compare the origin of the popup
to its opener. If they match, we return a full Window. For this to work properly
we need to store the origin as soon as the window is opened, and not wait until
the async response is received.
Also, expand CrossOriginWindow to expose more methods, most notably: close.
The /save script documentation lived as a hand-maintained string in
Agent.zig whose primitives table drifted whenever a tool changed. Move
it to src/script/skill.zig and render the reference (signatures, option
lists, enums, defaults, per-parameter descriptions) from Schema.all()
at first use, keeping the curated per-tool notes behind an exhaustive
switch on Tool so a new or renamed tool is a compile error until its
doc entry exists.
The rendered skill is shared by three consumers:
- the /save and revision system prompts (built lazily in Agent.zig)
- a new mcp://skill/pandascript resource
- `zig build skills`, which writes zig-out/skills/<name>/SKILL.md with
Claude Code frontmatter via a registry-based generator exe, so
future Lightpanda skills are one registry entry each
Schema.FieldEntry now retains per-parameter schema descriptions, which
previously existed only in the raw JSON.