Commit Graph
5857 Commits
Author SHA1 Message Date
Adrià Arrufat aeba63427e script: enforce positional arguments come first
Returns a specific `PositionalMustComeFirst` error when a positional
argument is placed after key-value pairs.
2026-06-11 18:24:44 +02:00
Adrià Arrufat d292f2b342 agent: pump session during terminal idle
Updates isocline to support idle callbacks and registers a hook to
pump the session's curl multi while waiting for user input. This
prevents connection timeouts. Also refactors the idle pumping logic
into `Session.idleSlice` to share it with the MCP server.
2026-06-11 18:19:51 +02:00
Adrià Arrufat 30c8bcbdd9 mcp: pump browser session during idle periods
Pumps the browser session while waiting for MCP requests to prevent
curl timeouts. Adds an idle polling loop to the request router.
2026-06-11 17:48:24 +02:00
Adrià Arrufat de7ad43bb9 agent: treat first arg of /save as filename and append .js
Updates `/save` to always treat the first token as the filename,
appending `.js` if missing. Remaining tokens are used as the prompt.
2026-06-11 17:35:15 +02:00
Adrià Arrufat 19581f34ce agent: simplify model and provider output 2026-06-11 11:04:30 +02:00
Francis Bouvier 7e9acec50f agent: Improve save prompt (#2691) 2026-06-11 10:09:59 +02:00
Adrià ArrufatandFrancis Bouvier b0cf88b6a8 agent: improve extract tool description (#2696)
Co-authored-by: Francis Bouvier <francis@lightpanda.io>
2026-06-11 09:42:47 +02:00
Adrià Arrufat 314e3c58ea Merge branch 'main' into agent
# Conflicts:
#	src/mcp/Server.zig
2026-06-11 09:00:44 +02:00
Karl Seguin d695ce10c3 Merge pull request #2690 from lightpanda-io/log_shrink
log, mem: Reduce generated code size of logger
2026-06-11 13:52:38 +08:00
Karl Seguin b145519fc3 Merge pull request #2688 from lightpanda-io/script_reentrency_too_strict
script: Force pending script evaluation after evalutate finishes
2026-06-11 12:32:13 +08:00
Karl Seguin 93346ef5a6 mem: reduce generic use in log
Experiment to see if this shrinks the build by any significant amount. Some
investigation did surface this as some of the code we control directly which
did stand out.
2026-06-11 10:21:57 +08:00
Karl Seguin 96becbd296 log, mem: Make scope and msg runtime values to shrink generated code size 2026-06-11 08:41:57 +08:00
Karl Seguin def62ebfa0 Apply endEvaluationWindow in more places 2026-06-11 07:18:14 +08:00
Karl Seguin b0426bab9b Merge pull request #2685 from lightpanda-io/shadow-dom
wpt, shadowdom: Improve shadowdom
2026-06-11 06:45:24 +08:00
Karl Seguin e8e9b0356a script: Force pending script evaluation after evalutate finishes
This commit is in the same vein as 0d9482ccbf. A
dynamic async script which completes during an evalute() does not evaluate if
`is_evaluating == true`. That's good, but we need to make sure that it _does_
eventually get evaluated. As-is, we rely on a done callback to call evaluate()
again which works for all but the last script.

This commit creates a more robust reentrancy flow. is_evaluating still guards
against reentrancy, but a new flag, `evaluate_pending` is set to true. Whenever
`is_evaluating` is set to false if `evaluate_pending` is true, we evaluate().

Similalry, during evaluate(), we better handle completed scripts during
evaluate() and process them immediately (via an outer loop).
2026-06-10 20:14:05 +08:00
Pierre Tachoire e2fc3918a0 Merge pull request #2683 from lightpanda-io/mcp-ping-object 2026-06-10 13:56:29 +02:00
Karl Seguin d1f4c40920 Merge pull request #2671 from navidemad/datatransfer-api
webapi: DataTransfer / DataTransferItem / DataTransferItemList + DragEvent (drag-and-drop file upload)
2026-06-10 19:08:07 +08:00
Navid EMAD fefc1931b9 webapi: address DataTransfer review feedback
- DataTransferItem/DataTransferItemList/Iterator forward acquireRef/releaseRef
  to the owning DataTransfer, so its pooled arena outlives any JS-held wrapper
  (fixes a potential use-after-free when JS keeps an item/list/iterator alive
  past the DataTransfer).
- addItem reads strings straight into the persistent arena via
  toStringSliceWithAlloc, removing the intermediate call_arena copy.
- normalizeFormat uses std.ascii.allocLowerString instead of dupe + lowerString.
- setData: rename dup -> owned_data for clarity.
2026-06-10 12:33:22 +02:00
Adrià Arrufat a1d427e518 browser: make console capture opt-in (#2686)
Move console message listener registration out of Session initialization
into an explicit `enableConsoleCapture` method. This avoids buffering
console logs when they are not needed.
2026-06-10 11:12:59 +02:00
Karl Seguin caeb359f75 wpt, shadowdom: Improve shadowdom
This was driven by various WPT tests in the /shadow-dom/ category. There are
4 distinct changes.

1. Template hooks into "cloned" to include the _content. This change required
   passing `deep: bool` which is why TextArea and Input are also changed (they
   ignore that new parameter)

2. Node.getRootNode and Node.ownerDocument will now traverse through the
   ShadowRoot to find the root/document

3. DOM events won't gain the Window when triggered from within a ShadowRoot

4. attachShadow now takes a full option, not just a string mode. This also
   touched a few different places since it's called internally too.
2026-06-10 15:28:11 +08:00
Karl Seguin 6bead7becd Merge pull request #2676 from lightpanda-io/intersection_observer_perf
perf; Optimize IntersectionObserver
2026-06-10 07:43:59 +08:00
Karl Seguin 843de5cd0e Merge pull request #2675 from lightpanda-io/script_preload
perf,http: Support for script preloading
2026-06-10 07:43:42 +08:00
Adrià Arrufat 668c5d1628 Merge branch 'main' into agent 2026-06-09 19:07:31 +02:00
Adrià Arrufat 4b3e18fda2 agent: extract save helpers to save.zig (#2684)
* Revert "agent: enhance /save progress and verification feedback"

This reverts commit 54f467d1fa.

* Revert "agent: verify synthesized scripts during /save"

This reverts commit b141da30ca.

* agent: extract save helpers to save.zig

Moves pure helper functions related to the `/save` command (parsing,
validation, file writing, prompt shaping) from `Agent.zig` to a
dedicated `save.zig` module.
2026-06-09 19:06:09 +02:00
Pierre Tachoire a52c45f309 mcp: ping's response must be an object not an array
The array returned breaks the mcp keep alive feature implemented by the
official mcp client in Go.
2026-06-09 17:40:08 +02:00
Adrià Arrufat 54f467d1fa agent: enhance /save progress and verification feedback
- Add step-by-step progress reporting during script synthesis.
- Introduce yellow warning bullets for superseded verification runs.
- Refactor bullet emission in Terminal to support multiple statuses.
- Fix spinner formatting when tool arguments are empty.
2026-06-09 17:35:31 +02:00
Adrià Arrufat b141da30ca agent: verify synthesized scripts during /save
Introduces a multi-step synthesis process for `/save` that derives a
logical JSON output schema and uses a dry-run runtime to verify
candidate scripts. The LLM can now run and self-correct its scripts
using a new `run_script` tool before finalizing the save.
2026-06-09 16:53:39 +02:00
Karl Seguin d24832ee08 Move preloads out of async_scripts
async_scripts is used to block the "load" event, and preload scripts (a)
shouldn't block this and (b) might never be used.  The `preloaded_scripts` map
itself can be cleaned up on shutdown/reset.
2026-06-09 20:13:41 +08:00
Karl Seguin aa32dbeb1b clean: Map -> Set since value isn't needed
Swap `_previous_states: Map(*Element, Bool)` to `_tracked: Set(*Element)` since
we only care about membership (the value was previous always bool). This better
captures the intent.
2026-06-09 19:02:10 +08:00
Karl Seguin fa4a60680e Merge pull request #2672 from lightpanda-io/element_scroll
Add Element.scroll (and scrollTo and scrollBy)
2026-06-09 17:35:58 +08:00
Karl Seguin c77f57d476 perf; Optimize IntersectionObserver
`checkIntersection` can be called a lot...on every domChanged. And it can call
a known expensive API: `getBoundingClientRect`.

This commit reworks the code to be able to exit from checkIntersection early.
`_previous_states` is now seeded with the target so that, once reported, the
lack of entry can be used to quickly exit.

When profiling airbnb, `checkIntersection` was reported 841 times. With this
change, it was reported twice.
2026-06-09 16:57:19 +08:00
Adrià Arrufat 59fb13892e terminal: hint first slash command on single slash
Triggers a ghost hint with the first matching slash command when the
user inputs a single `/` character.
2026-06-09 10:29:57 +02:00
Adrià Arrufat cd8192656b agent: update panda logo and alignment 2026-06-09 10:17:02 +02:00
Adrià Arrufat 3baa2726e9 agent: streamline and shorten comments 2026-06-09 09:34:26 +02:00
Karl Seguin c81b4d13d9 perf,http: Support for script preloading
Implement <link rel=preload as=script href=...>. The implementation is similar
to preloadImport / waitForImport. Consider a website that does something like:

```
// pseudo html
<head>
<link preload script1.js>
<link preload script2.js>
<link preload script3.js>
<link preload script4.js>

<script script1.js></script>
<script script2.js></script>
<script script3.js></script>
<script script4.js></script>
```

Then, without preloading, we hit <script script1.js></script> and block while we
load it + execute it. Repeat for 2, 3, 4 ...

With preloading, by the time we block on <script script1.js></script> all the
scripts are already being downloaded in the background.

I opted to remove the script on first use. If a script happens to be used twice
(we have seen this happen for imports, but I guess it's more rare on blocking
scripts), then it'll get re-downloaded the 2nd time, just like before (and just
like before, the http cache is a better mechanism to rely on here).

airbnb preloads 41 scripts.
2026-06-09 15:16:34 +08:00
Adrià Arrufat 6f54c78042 agent: simplify and clean up code comments 2026-06-09 08:43:40 +02:00
Adrià Arrufat 3615e58700 agent: deduplicate option setting and tool handling
- Consolidate `/verbosity` and `/effort` into `setEnumOption`.
- Add `abortSave` helper to clean up `synthesizeSave` error paths.
- Simplify `handleToolCall` by extracting the tool execution outcome.
- Update outdated comments referencing `message_arena`.
2026-06-09 08:16:07 +02:00
Adrià Arrufat f2b5f05479 agent: extract conversation, welcome, and settings
Extracts chat history and arena management into `Conversation.zig`,
the startup banner into `welcome.zig`, and model/config resolution
helpers into `settings.zig` to simplify `Agent.zig`.
2026-06-09 07:54:32 +02:00
Adrià Arrufat ceff290ff9 Merge branch 'main' into agent 2026-06-09 07:24:10 +02:00
Karl Seguin db260fe029 test,perf: Fix leaky thread in test runner
The TestHTTPServer leaks a thread for every connection that shuts down. This
commit correctly releases it. It also closes a leaking CDP socket.

Full test went from 20s -> 10s for me
2026-06-09 11:42:31 +08:00
Karl Seguin 72770cf438 webapi, gc: Give FormData its own arena
Rather than relying on the frame_arena, use a distinct arena for FormData. This
generally results in tighter memory usage, but more importantly it ensures that
if FormData outlives the frame, we don't get a UAF. This can happen if the
FormData is refernced in v8 and finalized late (e.g. after the frame would
appear to still be needed).

Also, in Frame.submitForm use the explicit acquireRef and releaseRef. This
FormData can [in theory] be passed to JS, via the `formdata` event that we fire.
2026-06-09 10:45:55 +08:00
Karl Seguin 1e68d7693b Add Element.scroll (and scrollTo and scrollBy)
Needed by bluesky to render
2026-06-09 08:57:23 +08:00
Karl Seguin f4774f1ac2 Merge pull request #2668 from lightpanda-io/fix-newsession-init-failure
browser: clear session slot when Session.init fails
2026-06-09 07:09:04 +08:00
Karl Seguin 4784c29287 Merge pull request #2666 from lightpanda-io/crypto
WPT /WebCryptoAPI/
2026-06-09 07:07:12 +08:00
Navid EMAD ff1fb2dc0d webapi: add DragEvent carrying dataTransfer; wire InputEvent.dataTransfer
DragEvent extends MouseEvent (new drag_event arm in the MouseEvent type union)
and exposes a nullable dataTransfer, so JS can build a DataTransfer and dispatch
a drop/dragover event whose .dataTransfer.files is readable. Also resolves the
InputEvent dataTransfer TODO with a real field + accessor.

Both events hold a refcount on the DataTransfer for their lifetime and release
it in deinit (via the leaf acquireRef/releaseRef/deinit trio, like MessageEvent
holds a Blob), so the store's arena can't be freed out from under an event whose
JS wrapper is collected first.

Refs #2043
2026-06-08 23:05:49 +02:00
Navid EMAD 42ecdf4d02 webapi: add DataTransfer, DataTransferItem, DataTransferItemList
Implements the constructible DataTransfer interface and its item views over a
single drag-data-store: string- and file-kind items, with .files (FileList) and
.types derived from the file items so items.add(file) is visible immediately.
File refs are acquired on add and released on remove/clear; the backing FileList
is frame-tracked and the DataTransfer arena is refcounted so the GC finalizer
reclaims it, leaving no leaks.

Refs #2043
2026-06-08 22:46:59 +02:00
Adrià Arrufat 8e12f6cdf9 agent: exclude version from comptime banner check 2026-06-08 20:08:32 +02:00
Adrià Arrufat e6ae13717d agent: move up text 2026-06-08 19:52:42 +02:00
Adrià Arrufat 02cf1c582b agent: add colored braille panda logo
Replace the monochrome braille logo with a truecolor ANSI-colored
version. Update logo dimensions and row counting logic, and simplify
the welcome banner printing to stream logo lines directly.
2026-06-08 19:48:05 +02:00
Adrià Arrufat 826fa34cb5 agent: remove schema from slash help
Stop printing the verbose JSON schema for tool parameters when
displaying slash command help.
2026-06-08 19:11:02 +02:00