@divebell/agent-browser 0.33.2-divebell.4 → 0.33.2-divebell.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # agent-browser
2
2
 
3
- Browser automation CLI for AI agents. This Divebell build adds memory diagnostics and code coverage support.
3
+ Browser automation CLI for AI agents. This Divebell build adds compiled JavaScript debugging, safe logpoints, memory diagnostics, and code coverage support.
4
4
 
5
5
  [![skills.sh](https://skills.sh/b/vercel-labs/agent-browser)](https://skills.sh/vercel-labs/agent-browser)
6
6
 
@@ -345,7 +345,7 @@ agent-browser click @e3 # click uses docs's refs
345
345
  agent-browser tab close docs # close by label
346
346
  ```
347
347
 
348
- Switching to a tab discarded by Chrome's Memory Saver reactivates it, since a discarded tab has no renderer to drive. Reactivation reloads the discarded page and resets its unsaved state, and the switch result reports `"revived": true`. A tab whose page is paused by a JavaScript dialog is alive rather than discarded, so the switch leaves it untouched and reports `"dialogBlocked": true`; resolve the dialog with `dialog accept` or `dialog dismiss` before interacting. Closing the active tab onto a discarded successor revives it the same way and reports `"activeTabRevived": true`.
348
+ Switching to a tab discarded by Chrome's Memory Saver reactivates it, since a discarded tab has no renderer to drive. Reactivation reloads the discarded page and resets its unsaved state, and the switch result reports `"revived": true`. A tab whose page is paused by a JavaScript dialog or debugger is alive rather than discarded, so the switch leaves it untouched and reports `"dialogBlocked": true` or `"debuggerPaused": true`. Resolve the dialog or resume the debugger before interacting. Closing the active tab onto a discarded successor revives it the same way and reports `"activeTabRevived": true`.
349
349
 
350
350
  ### Frames
351
351
 
@@ -394,6 +394,14 @@ agent-browser memory sampling stop # Save allocation profile and top call si
394
394
  agent-browser memory snapshot # Stream a heap snapshot to a local file
395
395
  agent-browser memory status # Show the active capture
396
396
  agent-browser memory cancel # Cancel the active capture
397
+ agent-browser debug enable # Enable compiled JavaScript debugging
398
+ agent-browser debug scripts # List loaded script instances
399
+ agent-browser debug source search <text> # Search compiled sources
400
+ agent-browser debug breakpoint set <script-id> <line> # Set a breakpoint
401
+ agent-browser debug logpoint set <script-id> <line> --expression <js> # Add a logpoint
402
+ agent-browser debug stack # Inspect the current pause
403
+ agent-browser debug resume # Resume the current pause
404
+ agent-browser debug events # Read debugger and logpoint events
397
405
  agent-browser console # View console messages (log, error, warn, info)
398
406
  agent-browser console --json # JSON output with raw CDP args for programmatic access
399
407
  agent-browser console --clear # Clear console
@@ -411,6 +419,75 @@ agent-browser state clear --all # Clear all saved states
411
419
  agent-browser state clean --older-than <days> # Delete old states
412
420
  ```
413
421
 
422
+ ### Compiled JavaScript debugger
423
+
424
+ The Chrome debugger works with the JavaScript that the browser actually loaded. It does not require project source files or source maps. This makes it suitable for production bundles, Rstack output, and Module Federation containers where only compiled assets are available.
425
+
426
+ Start by enabling debugging, then locate a script and a compiled line:
427
+
428
+ ```bash
429
+ agent-browser open https://app.example.com
430
+ agent-browser debug enable
431
+ agent-browser debug scripts --filter assets --json
432
+ agent-browser debug source search "checkout" --filter assets --json
433
+ ```
434
+
435
+ `debug scripts` returns a `scriptInstanceKey` scoped by connection generation, CDP session, document generation, and script ID. It also returns a separate `sourceLineageKey` and `runtimeOwner` evidence. Parent or initiator information is evidence only and is never used as identity. The generic substrate reports runtime ownership as `unknown` until a caller supplies reliable Host or Module Federation evidence. Persistent probes do not automatically rebind when ownership is unknown or ambiguous.
436
+
437
+ Set a breakpoint using the returned script ID and one-based compiled line:
438
+
439
+ ```bash
440
+ agent-browser debug breakpoint set 42 108 --strict --json
441
+ agent-browser eval "startCheckout()"
442
+ ```
443
+
444
+ When the page pauses, use another shell, agent tool call, or MCP call:
445
+
446
+ ```bash
447
+ agent-browser debug status --json
448
+ agent-browser debug stack --json
449
+ agent-browser debug eval "order.id" --frame 0 --json
450
+ agent-browser debug step-over
451
+ agent-browser debug resume
452
+ ```
453
+
454
+ Debugger inspection and control use a lock-independent daemon path. If the first CLI is waiting inside `eval`, `click`, or another renderer command that hit a breakpoint, a second CLI can still read the pause and resume it. When multiple tabs are paused, pass `--tab <tN>`, `--session <cdp-session-id>`, or `--pause-id <id>` to `stack`, `eval`, `resume`, and step commands.
455
+
456
+ Locations use one-based lines and one-based UTF-16 columns. With only a line, `--strict` selects a breakable point on that line; an explicit `--column` must match exactly. The default `--after` mode resolves forward, while `--before` and `--nearest` use backward candidates only after Chrome proves that they reach an anchor in the requested function. `--nearest` prefers a forward point when distances tie. Resolution is bounded to three lines and 512 UTF-16 code units by default; tighten or explicitly expand those bounds with `--max-lines <n>` and `--max-utf16-distance <n>`. `--nearest-forward` remains a compatibility alias for `--after`. Breakpoint conditions and logpoint expressions are syntax checked with `Runtime.compileScript`. A valid expression can still fail when the selected runtime scope does not contain a referenced variable; the logpoint records that failure without creating an unrelated pause.
457
+
458
+ Logpoints use a private Runtime binding rather than the page console:
459
+
460
+ ```bash
461
+ agent-browser debug logpoint set 42 108 \
462
+ --when "order.ready" \
463
+ --expression "order" \
464
+ --expression "cart.total" \
465
+ --tag phase=checkout \
466
+ --json
467
+
468
+ agent-browser debug events --since 0 --wait 5000 --json
469
+ ```
470
+
471
+ Logpoints use a random per-connection Runtime binding name and nonce. Serialization is bounded by depth, property count, array length, string length, and a 64 KiB payload cap. It handles cycles, `BigInt`, non-finite numbers, functions, symbols, accessors, throwing getters, and proxies without pausing the page. A false `--when` condition emits nothing; a thrown condition is reported as `whenError`, while individual expression failures are reported as `evaluationError`. Incoming binding messages must match the active connection nonce, CDP session, execution context, logical probe, and physical binding. Script identity, location, tags, and owner metadata always come from the daemon registry rather than the page payload.
472
+
473
+ Manage probes and lifecycle explicitly:
474
+
475
+ ```bash
476
+ agent-browser debug breakpoint list --json
477
+ agent-browser debug breakpoint remove <probe-id>
478
+ agent-browser debug logpoint list --json
479
+ agent-browser debug logpoint remove <probe-id>
480
+ agent-browser debug disable --resume
481
+ ```
482
+
483
+ Use `--persist` to request same-document rebinding after a new compiled script instance appears. Automatic rebinding requires a resolved runtime owner and an exact lineage match for session, document generation, execution context, compiled URL, and owner ID. Navigation, target detach, browser reconnect, and connection reset invalidate stale physical bindings. Rebinding never crosses a connection or document generation.
484
+
485
+ `debug events` stores up to 10,000 events and 8 MiB per daemon session. Responses include `oldestSequence`, `latestSequence`, `gap`, `bufferGap`, `transportGap`, `droppedThroughSequence`, and `lastTransportGapSequence`. A `transport-gap` event reports CDP broadcast lag. Use `--since` as a cursor, `--wait` for bounded long polling, and `--clear` after consuming evidence.
486
+
487
+ Debugger inspection uses the `debug.inspect` action-policy category, while probe changes and execution control use `debug.control`. Frame evaluation, logpoints, and conditional breakpoints also require `evaluate` because they run expressions in page context. When multiple policy categories apply, denial takes precedence over confirmation.
488
+
489
+ The debugger is supported on Chrome and Chromium only. Reading one compiled source response is capped at 32 MiB; source search returns at most 100 matches by default with bounded context and accepts up to 1,000. The debugger is intentionally a generic CDP substrate. Rstack HMR cycle grouping and Module Federation shared-module consumer or runtime-instance attribution belong in the Divebell extension, which should consume script, probe, pause, and lifecycle events without changing core script identity.
490
+
414
491
  ### Memory diagnostics
415
492
 
416
493
  Memory diagnostics reuse the current agent-browser Chrome session. No separate CDP port or address is required. They are disabled on Lightpanda, Safari, and other engines that do not provide the required Chrome memory capabilities.
@@ -560,7 +637,7 @@ Profiles:
560
637
  - `core` — Default. Navigation, snapshots, interaction, waits, reads, screenshots, JavaScript eval, close, tab basics, and profile discovery
561
638
  - `network` — Network routes, request inspection, HAR, headers, credentials, offline
562
639
  - `state` — Cookies, storage, auth, saved state, sessions, profiles, skills
563
- - `debug` — Console/errors, tracing, profiling, recording, a11y audit, clipboard, plugins, doctor, dashboard, install, upgrade, chat, diff, batch, confirm/deny
640
+ - `debug` — Compiled JavaScript breakpoints, logpoints, pause recovery, console/errors, tracing, profiling, recording, a11y audit, clipboard, plugins, doctor, dashboard, install, upgrade, chat, diff, batch, confirm/deny
564
641
  - `tabs` — Back/forward/reload, tabs, windows, frames, dialogs
565
642
  - `react` — React tree/inspect/renders/suspense, vitals, pushstate
566
643
  - `mobile` — Viewport/device/geolocation/media, touch, swipe, mouse, keyboard
@@ -747,7 +824,7 @@ The profile directory stores:
747
824
 
748
825
  ## Session Persistence
749
826
 
750
- Use `--restore` with a stable `--session` to automatically save and restore cookies and localStorage across browser restarts:
827
+ Use `--restore` with a stable `--session` to automatically save and restore cookies, localStorage, and sessionStorage across browser restarts. Restore State is a portable storage snapshot, not a complete Chrome Profile. A Profile also keeps IndexedDB, service workers, cache, extensions, browser preferences, and other Chrome-owned data.
751
828
 
752
829
  ```bash
753
830
  # Generate a stable id for this worktree and auto-save/load state
@@ -761,7 +838,11 @@ agent-browser --session "$SESSION" --restore open twitter.com
761
838
  agent-browser --session "$SESSION" --restore --restore-check-text Dashboard open twitter.com
762
839
  ```
763
840
 
764
- State is saved when the browser closes (explicit `close`, idle timeout, or daemon shutdown) and also periodically while the browser is open, so a browser window you close by hand still leaves a recent save behind. Periodic autosave waits for commands to settle, then saves at most once per `AGENT_BROWSER_AUTOSAVE_INTERVAL_MS` (default 30000; set to `0` to save only on close). Idle sessions keep saving on the same interval, so changes the page makes on its own (token refreshes, background requests) are captured too. It respects the `--restore-save` policy.
841
+ The three save stages are independent. By default, agent-browser saves once after a newly launched page has been quiet for about two seconds, continues periodically while the browser is open, and saves again before explicit `close`, idle timeout, daemon shutdown, or a compatible relaunch. Disable a stage with `--restore-initial-save false`, `--restore-periodic-save false`, or `--restore-close-save false`. Periodic saves run at most once per `--restore-periodic-save-interval-ms` or `AGENT_BROWSER_AUTOSAVE_INTERVAL_MS` (default 30000); an interval of `0` disables only the periodic stage.
842
+
843
+ Collecting localStorage and sessionStorage from more than one origin requires a disposable CDP target. agent-browser asks compatible browsers to create that target in the background and falls back when the CDP implementation does not support that option. In a headed browser that uses the fallback, an initial or periodic save can briefly show the temporary target. The original page is not refreshed. Disable only the post-launch save with `--restore-initial-save false` when this visual switch is undesirable; close saving remains enabled.
844
+
845
+ `--restore-save auto|always|never` remains the higher-level safety policy. `auto` skips saving after restore or validation failure, `always` permits saving despite those failures, and `never` disables every stage. In contrast, disabling initial or periodic saving still preserves close-time saving unless `--restore-close-save false` is also set.
765
846
 
766
847
  ### State Encryption
767
848
 
@@ -779,7 +860,10 @@ agent-browser --session secure --restore open example.com
779
860
  | --------------------------------- | -------------------------------------------------- |
780
861
  | `AGENT_BROWSER_RESTORE` | Auto-save/load state persistence name |
781
862
  | `AGENT_BROWSER_RESTORE_SAVE` | Restore save policy: `auto`, `always`, or `never` |
782
- | `AGENT_BROWSER_AUTOSAVE_INTERVAL_MS` | Min ms between periodic autosaves (default: 30000, 0 disables) |
863
+ | `AGENT_BROWSER_RESTORE_INITIAL_SAVE` | Enable the one-time post-launch save (default: true) |
864
+ | `AGENT_BROWSER_RESTORE_PERIODIC_SAVE` | Enable periodic saves while open (default: true) |
865
+ | `AGENT_BROWSER_RESTORE_CLOSE_SAVE` | Enable saves before close, shutdown, and relaunch (default: true) |
866
+ | `AGENT_BROWSER_AUTOSAVE_INTERVAL_MS` | Min ms between periodic saves (default: 30000; 0 disables periodic only) |
783
867
  | `AGENT_BROWSER_NAMESPACE` | Namespace for daemon sockets and restore state |
784
868
  | `AGENT_BROWSER_SESSION_NAME` | Legacy auto-save/load state persistence name |
785
869
  | `AGENT_BROWSER_ENCRYPTION_KEY` | 64-char hex key for AES-256-GCM encryption |
@@ -948,6 +1032,10 @@ This is useful for multimodal AI models that can reason about visual layout, unl
948
1032
  | `--session <name>` | Use isolated session (or `AGENT_BROWSER_SESSION` env) |
949
1033
  | `--restore [name]` | Auto-save/restore session state. Bare `--restore` uses `--session` as the key |
950
1034
  | `--restore-save <policy>` | Restore save policy: `auto`, `always`, or `never` |
1035
+ | `--restore-initial-save <bool>` | Save once after the page is quiet for about two seconds (default: true) |
1036
+ | `--restore-periodic-save <bool>` | Continue saving periodically while open (default: true) |
1037
+ | `--restore-close-save <bool>` | Save before close, shutdown, or relaunch (default: true) |
1038
+ | `--restore-periodic-save-interval-ms <ms>` | Minimum periodic save interval (default: 30000; 0 disables periodic only) |
951
1039
  | `--restore-check-url <glob>` | Validate restored state against a URL pattern |
952
1040
  | `--restore-check-text <text>` | Validate restored state against page text |
953
1041
  | `--restore-check-fn <js>` | Validate restored state against a truthy JavaScript expression |
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@divebell/agent-browser",
3
- "version": "0.33.2-divebell.4",
3
+ "version": "0.33.2-divebell.6",
4
4
  "description": "Browser automation CLI for AI agents with Divebell memory diagnostics",
5
5
  "type": "module",
6
6
  "engines": {
@@ -235,7 +235,9 @@ SESSION="$(agent-browser session id --scope worktree --prefix my-app)"
235
235
  agent-browser --session "$SESSION" --restore open https://app.example.com
236
236
  ```
237
237
 
238
- `--restore` with no value uses the current `--session` as the persistence key. Agent skills should prefer this over hand-built state file paths. Use `--restore-save auto` by default so a failed restore does not overwrite the previous known-good state. State is saved on close and also periodically while the browser is open (at most once per `AGENT_BROWSER_AUTOSAVE_INTERVAL_MS`, default 30000), so state survives even if the user closes the browser window by hand.
238
+ `--restore` with no value uses the current `--session` as the persistence key. Agent skills should prefer this over hand-built state file paths. Restore State contains cookies, localStorage, and sessionStorage; it is not a complete Chrome Profile. Use `--restore-save auto` by default so a failed restore does not overwrite the previous known-good state.
239
+
240
+ The initial, periodic, and close save stages are independent. agent-browser enables all three by default: it saves once after the launched page is quiet for about two seconds, continues at `--restore-periodic-save-interval-ms` intervals, and saves before close, shutdown, idle timeout, or compatible relaunch. Use `--restore-initial-save false` to avoid the initial cross-origin storage target, `--restore-periodic-save false` to stop background saves, or `--restore-close-save false` to suppress lifecycle saves. `--restore-save never` is stronger and disables every stage. The stage settings are attached to every command, so they also update an already-running daemon.
239
241
 
240
242
  ```bash
241
243
  agent-browser --session "$SESSION" --restore --restore-check-text Dashboard open https://app.example.com
@@ -382,6 +384,29 @@ agent-browser memory snapshot ./after.heapsnapshot
382
384
 
383
385
  Only one capture can be active per session. Sampling remains bound to the page where it started even if another tab becomes active. Use `memory status` to inspect the current capture and `memory cancel` to stop it safely. Keep `.heapprofile` and `.heapsnapshot` files local because they can contain page text, application data, credentials, and tokens. See [references/commands.md](references/commands.md#memory-diagnostics) for every option and output field.
384
386
 
387
+ ## Debugging compiled JavaScript
388
+
389
+ Use the Chrome-only `debug` commands when a loaded bundle must be inspected without source files or source maps. Enable the debugger, search the compiled source, set a probe, then use a separate command to inspect or resume if execution pauses.
390
+
391
+ ```bash
392
+ agent-browser debug enable
393
+ agent-browser debug scripts --filter assets --json
394
+ agent-browser debug source search "checkout" --filter assets --json
395
+ agent-browser debug breakpoint set <script-id> <line> --strict --json
396
+ agent-browser debug stack --json
397
+ agent-browser debug eval "order.id" --frame 0 --json
398
+ agent-browser debug resume
399
+ ```
400
+
401
+ Debugger control bypasses the daemon's ordinary renderer-command lock, so it remains available when an earlier `eval`, click, or page action is stopped at a breakpoint. If more than one page is paused, select it with exactly one of `--tab`, `--session`, or `--pause-id`. Use logpoints when evidence is needed without pausing:
402
+
403
+ ```bash
404
+ agent-browser debug logpoint set <script-id> <line> --when "order.ready" --expression "order" --json
405
+ agent-browser debug events --since 0 --wait 5000 --json
406
+ ```
407
+
408
+ Do not infer source identity from script parents. Use the returned script instance and lineage fields. Persistent rebinding is allowed only for a resolved runtime owner within the same connection, session, document generation, execution context, and compiled URL. See [references/debugging-compiled-js.md](references/debugging-compiled-js.md) for commands, lifecycle rules, safe log serialization, and HMR or Module Federation extension guidance.
409
+
385
410
  ## Diagnosing install issues
386
411
 
387
412
  If a command fails unexpectedly (`Unknown command`, `Failed to connect`, stale daemons, version mismatches after `upgrade`, missing Chrome, etc.) run `doctor` before anything else:
@@ -450,6 +475,10 @@ EOF
450
475
  --state <path> # load saved auth state from JSON
451
476
  --restore [name] # auto-save/restore session state, defaults to --session
452
477
  --restore-save <policy> # auto, always, or never
478
+ --restore-initial-save <bool> # one save after about two quiet seconds
479
+ --restore-periodic-save <bool> # continue saving periodically
480
+ --restore-close-save <bool> # save before close, shutdown, or relaunch
481
+ --restore-periodic-save-interval-ms <ms> # periodic interval; 0 disables periodic only
453
482
  --namespace <name> # isolate daemon sockets and restore-state directories
454
483
  ```
455
484
 
@@ -512,6 +541,7 @@ That pulls in:
512
541
  - `references/trust-boundaries.md` — safety rules for driving a real browser
513
542
  - `references/session-management.md` — persistence, multi-session workflows
514
543
  - `references/profiling.md` — Chrome DevTools tracing and profiling
544
+ - `references/debugging-compiled-js.md` — compiled JavaScript breakpoints, logpoints, pause recovery, and lifecycle semantics
515
545
  - `references/video-recording.md` — video capture options
516
546
  - `references/streaming.md` covers live viewport streaming, remote input, per-client frame rate, and the encoding vars that set bandwidth cost
517
547
  - `references/proxy-support.md` — proxy configuration
@@ -229,7 +229,7 @@ agent-browser tab close docs # close by label
229
229
 
230
230
  Labels are never auto-generated, never rewritten on navigation, and must be unique within a session. To interact with another tab, switch to it first: the daemon maintains a single active tab, so refs (`@eN`) belong to the tab that was active when the snapshot ran.
231
231
 
232
- Switching to a tab that the browser discarded to save memory reactivates it, since a discarded tab has no renderer to drive. Reactivation reloads the page and resets its unsaved state, and the switch result adds `"revived": true` so the reload is not silent. A tab whose page is paused by a JavaScript dialog is alive rather than discarded: the switch leaves it untouched and adds `"dialogBlocked": true`. Resolve the dialog with `dialog accept`/`dialog dismiss` and its state is preserved. Closing the active tab onto a discarded successor revives it the same way and reports `"activeTabRevived": true`.
232
+ Switching to a tab that the browser discarded to save memory reactivates it, since a discarded tab has no renderer to drive. Reactivation reloads the page and resets its unsaved state, and the switch result adds `"revived": true` so the reload is not silent. A tab whose page is paused by a JavaScript dialog or debugger is alive rather than discarded: the switch leaves it untouched and adds `"dialogBlocked": true` or `"debuggerPaused": true`. Resolve the dialog or resume the debugger and its state is preserved. Closing the active tab onto a discarded successor revives it the same way and reports `"activeTabRevived": true`.
233
233
 
234
234
  ## Frames
235
235
 
@@ -356,7 +356,7 @@ Profiles:
356
356
  - `core` - Default. Navigation, snapshots, interaction, waits, reads, screenshots, JavaScript eval, close, tab basics, and profile discovery
357
357
  - `network` - Network routes, request inspection, HAR, headers, credentials, offline
358
358
  - `state` - Cookies, storage, auth, saved state, sessions, profiles, skills
359
- - `debug` - Console/errors, tracing, profiling, recording, a11y audit, clipboard, plugins, doctor, dashboard, install, upgrade, chat, diff, batch, confirm/deny
359
+ - `debug` - Compiled JavaScript breakpoints, logpoints, pause recovery, console/errors, tracing, profiling, recording, a11y audit, clipboard, plugins, doctor, dashboard, install, upgrade, chat, diff, batch, confirm/deny
360
360
  - `tabs` - Back/forward/reload, tabs, windows, frames, dialogs
361
361
  - `react` - React tree/inspect/renders/suspense, vitals, pushstate
362
362
  - `mobile` - Viewport/device/geolocation/media, touch, swipe, mouse, keyboard
@@ -418,6 +418,39 @@ agent-browser profiler start # Start Chrome DevTools profiling
418
418
  agent-browser profiler stop trace.json # Stop and save profile
419
419
  ```
420
420
 
421
+ ### Compiled JavaScript debugger
422
+
423
+ ```bash
424
+ agent-browser debug enable [--tab <tN> | --session <id>] [--all-tabs]
425
+ agent-browser debug disable [selectors] [--all-tabs] [--resume]
426
+ agent-browser debug status [--tab <tN> | --session <id> | --pause-id <id>]
427
+ agent-browser debug scripts [--filter <url>] [--tab <tN> | --session <id>]
428
+ agent-browser debug source <script-id> [selectors]
429
+ agent-browser debug source search <text> [--filter <url>] [--max-results <count>]
430
+ agent-browser debug breakpoint set <script-id> <line> [--column <n>] [--condition <js>] [--strict | --before | --after | --nearest] [--max-lines <n>] [--max-utf16-distance <n>] [--persist] [--tag <key=value>]
431
+ agent-browser debug breakpoint list
432
+ agent-browser debug breakpoint remove <probe-id>
433
+ agent-browser debug logpoint set <script-id> <line> --expression <js>... [--when <js>] [--column <n>] [--strict | --before | --after | --nearest] [--max-lines <n>] [--max-utf16-distance <n>] [--persist] [--tag <key=value>]
434
+ agent-browser debug logpoint list
435
+ agent-browser debug logpoint remove <probe-id>
436
+ agent-browser debug pause [selectors]
437
+ agent-browser debug resume [pause selectors]
438
+ agent-browser debug step-over|step-into|step-out [pause selectors]
439
+ agent-browser debug stack [pause selectors]
440
+ agent-browser debug eval <expression> [--frame <index> | --call-frame-id <id>] [pause selectors]
441
+ agent-browser debug events [--since <sequence>] [--wait <ms>] [--clear]
442
+ ```
443
+
444
+ All locations are one-based. Columns count UTF-16 code units. `--strict` requires the requested line and, when explicitly supplied, the exact column. `--after` is the default. `--before`, `--after`, and `--nearest` use `Debugger.getPossibleBreakpoints` with verified function boundaries, a default three-line bound, and a default 512 UTF-16 code unit distance. `--nearest-forward` remains a compatibility alias for `--after`.
445
+
446
+ Debugger pause inspection and control are lock-independent. A second CLI or MCP request can use `status`, `stack`, frame `eval`, step, or `resume` while an ordinary command is blocked at a breakpoint. With multiple paused sessions, pause selectors are mandatory.
447
+
448
+ Logpoints never use the page console as their authoritative channel. They call a random per-connection private Runtime binding with a connection nonce and physical binding ID. Values are serialized with depth, collection, string, and 64 KiB total payload limits. Cycles, accessors, getters, proxies, functions, symbols, `BigInt`, and non-finite numbers are represented safely. `--when` failures and individual expression failures are reported separately. Registry metadata is not trusted from the page payload.
449
+
450
+ `debug events` is a persistent per-daemon ring capped at 10,000 events and 8 MiB. Use `latestSequence` as the next `--since` cursor. `bufferGap` and `droppedThroughSequence` report ring eviction. `transportGap`, `lastTransportGapSequence`, and the `transport-gap` event report CDP listener lag. The aggregate `gap` field is true for either condition.
451
+
452
+ See [debugging-compiled-js.md](debugging-compiled-js.md) for the identity model, lifecycle invalidation, HMR rebinding constraints, Module Federation ownership boundaries, and MCP tool mapping.
453
+
421
454
  ## Memory diagnostics
422
455
 
423
456
  Memory commands require Chrome or Chromium. They reuse the current browser session and return `memory_unsupported_engine` on Lightpanda, Safari, or other unsupported engines.
@@ -0,0 +1,185 @@
1
+ # Compiled JavaScript debugging
2
+
3
+ Use this workflow to debug JavaScript exactly as Chrome loaded it. Project sources and source maps are optional and are not consulted by these commands.
4
+
5
+ ## Start and discover scripts
6
+
7
+ ```bash
8
+ agent-browser open https://app.example.com
9
+ agent-browser debug enable
10
+ agent-browser debug scripts --filter assets --json
11
+ agent-browser debug source search "checkout" --filter assets --json
12
+ agent-browser debug source <script-id>
13
+ ```
14
+
15
+ `debug enable` enables `Runtime`, `Debugger`, and `Page` for the active tab. Pass `--all-tabs` to enable every current top-level page, or select one with `--tab <tN>` or `--session <cdp-session-id>`.
16
+
17
+ `debug source <script-id>` returns at most 32 MiB in one response. `debug source search` returns one-based UTF-16 start and end coordinates, byte offsets, and at most 160 UTF-16 code units of context on each side. Search returns 100 matches by default and accepts an explicit maximum up to 1,000.
18
+
19
+ `debug scripts` records each `Debugger.scriptParsed` event. Script records include URL, hash, execution context, compiled extent, runtime owner evidence, and two different identities:
20
+
21
+ - `scriptInstanceKey` is `connectionGeneration + sessionId + documentGeneration + scriptId`. Use it for exact CDP operations.
22
+ - `sourceLineageKey` is `sessionId + documentGeneration + executionContextId + URL or sourceURL + resolvedRuntimeOwnerId`. Use it only when deciding whether a logical probe may rebind to a new script instance.
23
+
24
+ The initiating or parent script is evidence, never an identity component. Runtime ownership is reported with `status`, `kind`, `ownerId`, `confidence`, `evidence`, and `candidates`. A default page execution context can contain both Host and Module Federation remote code, so the generic substrate reports it as `unknown`. Reliable owner resolution belongs in the Divebell extension. `unknown` and `ambiguous` owners never auto-rebind.
25
+
26
+ ## Locations
27
+
28
+ CLI locations are one-based. Columns count UTF-16 code units so non-ASCII compiled text maps to Chrome correctly.
29
+
30
+ Before setting a probe, agent-browser calls `Debugger.getPossibleBreakpoints` with `restrictToFunction: true`.
31
+
32
+ - `--strict` accepts a breakable location on the requested line. When `--column` is supplied, the column must also match.
33
+ - `--before` selects the closest earlier location only after Chrome proves that it reaches an anchor in the requested function.
34
+ - `--after` selects the closest location at or after the request in the same function. This is the default.
35
+ - `--nearest` compares verified backward candidates with forward candidates and prefers forward when distances tie.
36
+ - `--nearest-forward` is a compatibility alias for `--after`.
37
+ - `--max-lines <n>` changes the default three-line bound, up to 500.
38
+ - `--max-utf16-distance <n>` changes the default 512 UTF-16 code unit bound, up to 1,000,000.
39
+
40
+ If no bounded location is found, the command fails without installing a breakpoint.
41
+
42
+ ## Breakpoints
43
+
44
+ ```bash
45
+ agent-browser debug breakpoint set <script-id> <line> --strict --json
46
+ agent-browser debug breakpoint set <script-id> <line> --condition "order.total > 100" --json
47
+ agent-browser debug breakpoint list --json
48
+ agent-browser debug breakpoint remove <probe-id>
49
+ ```
50
+
51
+ Conditions are syntax checked with `Runtime.compileScript` in the script's execution context before the physical breakpoint is installed. Syntax success does not prove that runtime scope variables exist. Scope failures are returned as evaluation evidence and must not be converted into an unrelated debugger pause.
52
+
53
+ A logical probe has a stable `probeId`. Each compiled script installation creates a separate physical record containing `physicalId`, CDP breakpoint ID, session, document generation, script ID, execution context, requested location, and actual location.
54
+
55
+ ## Pause recovery
56
+
57
+ A normal daemon command holds ordinary browser state while it waits for a renderer response. A renderer stopped at a breakpoint cannot finish that command. Debugger inspection and control therefore use an independent controller, event receiver, state lock, and direct CDP command path.
58
+
59
+ One shell can trigger a pause:
60
+
61
+ ```bash
62
+ agent-browser eval "startCheckout()"
63
+ ```
64
+
65
+ A second shell or MCP request can recover it:
66
+
67
+ ```bash
68
+ agent-browser debug status --json
69
+ agent-browser debug stack --json
70
+ agent-browser debug eval "order.id" --frame 0 --json
71
+ agent-browser debug step-over
72
+ agent-browser debug resume
73
+ ```
74
+
75
+ Each pause receives a generation-scoped `pauseId`. If exactly one session is paused, the selector can be omitted. If more than one session is paused, use exactly one of:
76
+
77
+ ```bash
78
+ --tab <tN>
79
+ --session <cdp-session-id>
80
+ --pause-id <pause-id>
81
+ ```
82
+
83
+ `debug eval` accepts either `--frame <zero-based-index>` or `--call-frame-id <id>`. An explicit call frame ID must belong to the selected pause.
84
+
85
+ Ordinary renderer commands fail early when the active tab is already paused. Tab management remains available. A tab switch reports `debuggerPaused: true` rather than treating the paused renderer as a discarded tab and attempting recovery that could alter state.
86
+
87
+ ## Logpoints
88
+
89
+ Logpoints collect evidence without pausing:
90
+
91
+ ```bash
92
+ agent-browser debug logpoint set <script-id> <line> \
93
+ --when "order.ready" \
94
+ --expression "order" \
95
+ --expression "cart.total" \
96
+ --tag phase=checkout \
97
+ --json
98
+
99
+ agent-browser debug events --since 0 --wait 5000 --json
100
+ ```
101
+
102
+ The physical breakpoint condition always returns false. When `--when` is false it emits nothing. Otherwise it serializes each expression independently, then calls a random per-connection private Runtime binding. The browser console is not an authoritative delivery channel.
103
+
104
+ Serialization has fixed limits for depth, properties, array items, strings, and a 64 KiB total payload. It does not invoke accessors through ordinary property reads. Cycles, `BigInt`, non-finite numbers, functions, symbols, accessors, throwing getters, proxy traps, and expression failures receive explicit representations rather than escaping the condition or pausing the page. A thrown `--when` expression is reported as `whenError`; a thrown value expression is reported as `evaluationError`.
105
+
106
+ Every binding message is validated against:
107
+
108
+ - connection nonce
109
+ - CDP session
110
+ - execution context when known
111
+ - logical probe ID
112
+ - active physical binding ID
113
+ - enabled logpoint registry state
114
+
115
+ The payload supplies only serialized expression values and the validation IDs. Script identity, compiled location, runtime owner, and tags come from the daemon registry. Rejected payloads create a `logpoint-rejected` event.
116
+
117
+ Removing the final logpoint for a session calls `Runtime.removeBinding`. Disabling the debugger removes the binding and all Debugger-domain state.
118
+
119
+ ## Events and gaps
120
+
121
+ ```bash
122
+ agent-browser debug events --since <sequence> --wait <milliseconds> --json
123
+ agent-browser debug events --clear --json
124
+ ```
125
+
126
+ The debugger keeps events independently of individual CLI connections. The ring is capped at 10,000 events and 8 MiB. Every response includes:
127
+
128
+ - `oldestSequence`
129
+ - `latestSequence`
130
+ - `gap`
131
+ - `bufferGap`
132
+ - `transportGap`
133
+ - `droppedThroughSequence`
134
+ - `lastTransportGapSequence`
135
+
136
+ `bufferGap: true` means the requested cursor is older than retained history. `transportGap: true` and a `transport-gap` event mean the controller's CDP broadcast receiver lagged after that cursor and browser events may have been lost. `gap` is true for either condition. Treat a gap as incomplete evidence and refresh debugger status, scripts, and probes before making automated conclusions.
137
+
138
+ Relevant event types include `target-attached`, `target-detached`, `script-parsed`, `probe-bound`, `probe-unbound`, `probe-rebind-failed`, `probe-removed`, `debugger-paused`, `debugger-resumed`, `logpoint-hit`, `logpoint-rejected`, `document-invalidated`, `document-committed`, `execution-context-created`, `execution-context-destroyed`, `execution-contexts-cleared`, `session-detached`, `connection-reset`, `binding-residue`, and `transport-gap`.
139
+
140
+ ## Lifecycle and rebinding
141
+
142
+ Navigation, target detach, browser close, and connection replacement invalidate physical bindings and pauses. Connection generation and document generation prevent stale IDs from being reused.
143
+
144
+ `--persist` allows same-document rebinding when HMR creates a new script instance. Rebinding requires all of the following:
145
+
146
+ - same browser connection generation
147
+ - same CDP session
148
+ - same document generation
149
+ - same execution context
150
+ - same compiled URL or sourceURL
151
+ - same resolved runtime owner ID
152
+
153
+ Unknown or ambiguous ownership changes the probe status to `awaiting-owner-evidence` and performs no automatic action. Navigation never inherits a probe into the next document generation. Browser reconnect never inherits a probe into the next connection generation.
154
+
155
+ ## Rstack HMR and Module Federation
156
+
157
+ Core agent-browser deliberately provides generic CDP facts rather than framework conclusions. The Divebell extension should consume the event stream and add framework-specific grouping.
158
+
159
+ For Rstack HMR, the extension should create a runtime-scoped cycle with a stable cycle ID, start and completion evidence, affected script instances, probe rebind attempts, and one of these outcomes: applied, failed, aborted, timed out, or incomplete because of an event gap. State preservation must be reported as `verified-preserved`, `verified-reset`, or `not-verified`; a successful HMR transport message is not proof that application state survived.
160
+
161
+ For Module Federation shared modules, aggregate by consumer, runtime instance, and share scope. Do not aggregate only by package name or resolved URL. A host and multiple remotes can load the same compiled URL under different ownership and sharing decisions. If owner resolution has multiple candidates, preserve all candidates and report `ambiguous`; do not silently select a parent or initiator.
162
+
163
+ ## MCP mapping
164
+
165
+ Start the server with the debug profile:
166
+
167
+ ```bash
168
+ agent-browser mcp --tools debug
169
+ ```
170
+
171
+ The profile includes dedicated typed tools for debugger enable, disable, status, scripts, source read and search, breakpoint set/list/remove, logpoint set/list/remove, pause, resume, step over/into/out, stack, frame evaluation, and events. Tool implementations delegate through the canonical CLI parser. Advanced global CLI fields, including session isolation and confirmation policy, remain available through the common MCP arguments.
172
+
173
+ ## Security
174
+
175
+ Debugger commands use the same action policy and confirmation sources as ordinary commands. Inspection maps to `debug.inspect`, frame evaluation maps to `evaluate`, and mutation or execution control maps to `debug.control`. Logpoints and conditional breakpoints require both `debug.control` and `evaluate` because their expressions run in page context. Policy denial takes precedence over confirmation when multiple categories apply. Confirmation for debugger recovery is itself lock-independent, so a required approval does not make a paused page impossible to resume.
176
+
177
+ Frame evaluation and logpoint expressions execute in page context and can have side effects. Treat them as code execution. Logpoint events can contain application data or credentials even with size limits. Keep event output within trusted agent and storage boundaries.
178
+
179
+ ## Limitations
180
+
181
+ - Chrome and Chromium only
182
+ - Compiled locations only; no source map remapping
183
+ - Top-level page sessions are managed directly; framework worker attribution requires extension evidence
184
+ - Persistent rebinding is conservative by design
185
+ - HMR cycle semantics and Module Federation ownership are extension responsibilities
@@ -57,7 +57,13 @@ SESSION="$(agent-browser session id --scope worktree --prefix next-dev-loop)"
57
57
  agent-browser --session "$SESSION" --restore open https://app.example.com/dashboard
58
58
  ```
59
59
 
60
- When `--restore` or another restore key is configured, state is loaded before navigation and saved on close, daemon shutdown, idle timeout, and compatible relaunch. It is also saved periodically while the browser is open (after commands settle, at most once per `AGENT_BROWSER_AUTOSAVE_INTERVAL_MS`, default 30000; set to `0` to save only on close), so a browser window the user closes by hand still leaves a recent save behind. A session ID by itself only isolates the daemon and does not enable persistence; without a restore key, shutdown discards transient browser state and open tabs. Idle sessions with configured persistence keep saving on the same interval, capturing changes the page makes on its own such as token refreshes. The daemon exits after one hour without commands or dashboard input by default; `--idle-timeout <time>` or `AGENT_BROWSER_IDLE_TIMEOUT_MS` tunes this, and `0` disables it. Headed, Safari/iOS WebDriver, and user-attached browsers are exempt from the default timeout; provider-owned cloud browsers are not. The default save policy is `--restore-save auto`, which skips auto-save if restore failed or validation failed; `never` disables periodic autosave too.
60
+ When `--restore` or another restore key is configured, state is loaded before navigation. Restore State contains cookies, localStorage, and sessionStorage; it is not a complete Chrome Profile and does not preserve IndexedDB, service workers, cache, extensions, or browser preferences.
61
+
62
+ Three independent stages control saving. agent-browser enables all three by default: it saves once after a newly launched page is quiet for about two seconds, saves periodically while the browser remains open, and saves before close, daemon shutdown, idle timeout, or compatible relaunch. Use `--restore-initial-save false`, `--restore-periodic-save false`, or `--restore-close-save false` to disable an individual stage. The periodic interval comes from `--restore-periodic-save-interval-ms` or `AGENT_BROWSER_AUTOSAVE_INTERVAL_MS` (default 30000); `0` disables periodic saving only. The settings are included with every command and therefore update an already-running daemon.
63
+
64
+ Cross-origin storage collection uses a disposable CDP target. agent-browser requests a background target and falls back for browsers that do not support the option. In a headed browser, the fallback can briefly show the temporary target; the original page is not refreshed. Disabling the initial stage avoids that post-launch switch while preserving close-time saving. The default higher-level policy is `--restore-save auto`, which skips saving after a failed restore or failed validation. `--restore-save never` disables all three stages, unlike disabling initial or periodic saving alone.
65
+
66
+ A session ID by itself only isolates the daemon and does not enable persistence; without a restore key, shutdown discards transient browser state and open tabs. Idle sessions with periodic persistence enabled keep saving on the same interval, capturing page-driven changes such as token refreshes. The daemon exits after one hour without commands or dashboard input by default; `--idle-timeout <time>` or `AGENT_BROWSER_IDLE_TIMEOUT_MS` tunes this, and `0` disables it. Headed, Safari/iOS WebDriver, and user-attached browsers are exempt from the default timeout; provider-owned cloud browsers are not.
61
67
 
62
68
  ```bash
63
69
  agent-browser --session "$SESSION" --restore --restore-check-url "**/dashboard" open https://app.example.com/dashboard