Commit Graph
7323 Commits
Author SHA1 Message Date
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
Adrià Arrufat 7d554846c1 build: update isocline dependency 2026-06-11 11:01:19 +02:00
Francis Bouvier 7e9acec50f agent: Improve save prompt (#2691) 2026-06-11 10:09:59 +02:00
Francis BouvierandAdrià Arrufat bdf8bd1031 agent: Improve agent script doc (#2692)
* ci: raise cdp bench MAX_VmHWM to 29000

The agent branch grew .text by ~2.8MB (mostly std monomorphization from
the new script/agent modules); none of it executes in serve mode and
anonymous/heap memory is byte-identical to main (716-724KB Private_Dirty
across main, agent-dev, and a build with the agent code compiled out).

The VmHWM delta is file-backed pages of the binary: the kernel maps them
in large readahead/THP chunks around each touched page, so peak RSS
shifts with link layout on every relink. The agent-less test build
measured 4.2MB *below* main while running the identical serve path,
purely from folio/window boundaries moving. At 28000 the gate was
failing on layout noise (28028-28064), not a regression.

* agent: improve docs agent_script

* Revert "ci: raise cdp bench MAX_VmHWM to 29000"

This reverts commit b6b704d43e.

---------

Co-authored-by: Adrià Arrufat <adria.arrufat@gmail.com>
2026-06-11 09:51:50 +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
katie-lpd b23c6c27bc Update agent.md 2026-06-09 16:21:56 +02:00
Adrià Arrufat 1a6ee90da7 Merge pull request #2681 from lightpanda-io/katie-lpd-patch-1
Update agent-tutorial.md
2026-06-09 15:55:07 +02:00
katie-lpd 1186e43f06 Update agent.md
Moving tutorial after quickstart for fluidity
2026-06-09 15:53:30 +02:00
katie-lpd a48dd45163 Update agent.md 2026-06-09 15:49:34 +02:00
Adrià Arrufat 43495dcf50 docs(agent): drop trailing whitespace in tutorial intro 2026-06-09 15:49:29 +02:00
katie-lpd 07727186da Update agent-tutorial.md
Rewrite:

- Section headings now describe tasks ("Log in to Hacker News" vs "Driving the browser by hand").
- Section 3 leads with the five login commands; selector-hunting  workflow moved to optional subsection at the end.
- Trimmed prereqs (dropped fish variant, $-escape edge cases, long LP_ prefix explanation).

Every working command preserved. Load-bearing callouts in section 3 kept (/waitForSelector doing two jobs, CSS-only selectors).
2026-06-09 15:21:23 +02:00
Adrià Arrufat 7bc35257f3 Merge pull request #2678 from lightpanda-io/katie-lpd-patch-1
Update agent.md
2026-06-09 14:32:09 +02:00
Adrià Arrufat 2601ba5d9c docs(agent): restore dropped features and fix markdown nits
The agent.md rewrite dropped documentation for several features that still
exist in the code. Restore them and clean up the markdown:

- Re-add /clear and /reset to the meta-commands table
- Re-add waitForState to the browser-tools list and the /save
  state-mutating command list
- Re-add --system-prompt and --verbosity (with the --task stderr-pipe
  escalation) to the providers section
- Strip trailing whitespace on blank lines; add blank lines before
  headings and between lists and following paragraphs
2026-06-09 14:31:05 +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
katie-lpd cd6e875707 Update agent.md
- **New opening.** Direct framing: "lets you drive a headless browser by talking to it."
- **New "How to think about it" section.** Explains the three-layer stack and the one-sentence pitch ("pay for the LLM once, then replay deterministically").
- **New "The REPL is where you build scripts" section.** Positions the REPL as a sandbox with a full sandbox-to-saved-script example.
- **New tips section.** Practical guidance for prompts that produce useful saved scripts (be specific about extracted data, name the page, check the file).
- **Updated Quick start.**
2026-06-09 13:29:32 +02: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
Pierre Tachoire 02d6c45dad Merge pull request #2677 from lightpanda-io/agent-build-cache-invalidation
ci: fix cache invalidation for agent-build
2026-06-09 11:42:13 +02: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
Pierre Tachoire a899fbaec0 ci: fix cache invalidation for agent-build 2026-06-09 11:18:23 +02: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
Pierre Tachoire a06967d54a Merge pull request #2674 from lightpanda-io/test_performance_fix
test,perf: Fix leaky thread in test runner
2026-06-09 08:47:21 +02: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