effect-browser 0.3.0-beta.6 → 0.3.0-beta.8

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.
Files changed (53) hide show
  1. package/README.md +124 -21
  2. package/dist/{Browser-B5AV7zPS.mjs → Browser-CNwK0r0q.mjs} +2 -2
  3. package/dist/{Browser-B5AV7zPS.mjs.map → Browser-CNwK0r0q.mjs.map} +1 -1
  4. package/dist/Browser.d.mts +2 -2
  5. package/dist/Browser.mjs +1 -1
  6. package/dist/{BrowserEvent-DzdNdvoh.d.mts → BrowserEvent-BRu2juEz.d.mts} +3 -1
  7. package/dist/BrowserEvent.d.mts +1 -1
  8. package/dist/BrowserEvent.mjs +2 -0
  9. package/dist/BrowserEvent.mjs.map +1 -1
  10. package/dist/Cdp.mjs +1 -1
  11. package/dist/{Change-DVP2IJWm.d.mts → Change-iMlcuzVD.d.mts} +2 -2
  12. package/dist/Change.d.mts +1 -1
  13. package/dist/Chromium.mjs +1 -1
  14. package/dist/Expect.d.mts +1 -1
  15. package/dist/Expect.mjs +1 -1
  16. package/dist/Moment.d.mts +1 -1
  17. package/dist/{Page-DYTdVhYa.d.mts → Page-C30aG2RQ.d.mts} +6 -4
  18. package/dist/Page-D4281dIi.mjs.map +1 -1
  19. package/dist/Page.d.mts +1 -1
  20. package/dist/Plan-BvCS9qAf.d.mts +209 -0
  21. package/dist/{Plan-5MdsRzE5.mjs → Plan-CyQNv49C.mjs} +232 -38
  22. package/dist/Plan-CyQNv49C.mjs.map +1 -0
  23. package/dist/Plan.d.mts +2 -2
  24. package/dist/Plan.mjs +2 -2
  25. package/dist/Policy.d.mts +1 -1
  26. package/dist/Presentation.d.mts +1 -1
  27. package/dist/Presentation.mjs +1 -1
  28. package/dist/Stage.d.mts +1 -1
  29. package/dist/Stage.mjs +1 -1
  30. package/dist/{Supervisor-Im6-wbg5.d.mts → Supervisor-CYWFK3vM.d.mts} +106 -56
  31. package/dist/Supervisor-TNKNOVzu.mjs +599 -0
  32. package/dist/Supervisor-TNKNOVzu.mjs.map +1 -0
  33. package/dist/Supervisor.d.mts +2 -2
  34. package/dist/Supervisor.mjs +2 -2
  35. package/dist/index.d.mts +5 -5
  36. package/dist/index.mjs +3 -3
  37. package/dist/{page-BkRcLCWZ.mjs → page-DHeYWEs-.mjs} +27 -14
  38. package/dist/page-DHeYWEs-.mjs.map +1 -0
  39. package/package.json +1 -1
  40. package/src/BrowserEvent.ts +2 -0
  41. package/src/Page.ts +3 -1
  42. package/src/Plan.ts +365 -56
  43. package/src/Supervisor.ts +384 -138
  44. package/src/internal/input/perform.ts +2 -0
  45. package/src/internal/page/bridge.ts +3 -3
  46. package/src/internal/reading/ready.inpage.ts +17 -7
  47. package/src/internal/reading/ready.ts +9 -3
  48. package/src/internal/supervisor/lifecycle.ts +291 -140
  49. package/dist/Plan-5MdsRzE5.mjs.map +0 -1
  50. package/dist/Plan-CNNOU1Tx.d.mts +0 -112
  51. package/dist/Supervisor-BtEG93gR.mjs +0 -420
  52. package/dist/Supervisor-BtEG93gR.mjs.map +0 -1
  53. package/dist/page-BkRcLCWZ.mjs.map +0 -1
package/README.md CHANGED
@@ -122,6 +122,12 @@ longer than `quietMillis` between phases reads as still. On the slot machine fix
122
122
  connection stalled for 450 to 900 ms toward either end while the reels spun, none of 132 waits
123
123
  ended early, where all 36 did before.
124
124
 
125
+ `Page.ready({ still: "content", quietMillis })` instead observes a full interval without visible
126
+ recorded DOM changes. It starts the recorder itself and starts the interval again in each new
127
+ document; navigation retries share the original timeout. Canvas animation can continue while DOM
128
+ content is ready. This does not prove pixel or screencast stillness and inherits the change
129
+ recorder's limits for canvas, SVG, frames, shadow content and values changed only by scripts.
130
+
125
131
  `Page.changes({ since, until })` says what visibly changed on a page over a window, in one call to
126
132
  the page, element by element, as a `Change`: text that changed, appeared, disappeared or came and
127
133
  went (`brief`), a field's value, or the title. Each says what it showed at the window's start and
@@ -225,8 +231,37 @@ A step recorded at a point presses the same place within the element found, brou
225
231
  first, and only when a press there reaches that element, not something over it. Replay stops at
226
232
  the first step it cannot take, with a `ReplayError` naming the step and why: `Missing`,
227
233
  `Ambiguous`, `Drifted` (nothing with the subject's role and name repeats its context, or the walk
228
- ended on another site), or the step's `BrowserError`. Nothing is replayed automatically, and a plan
229
- of another version does not decode.
234
+ did not arrive at the recorded site), the step's `BrowserError`, or `Uncertain`. Arrival waits
235
+ are bounded by `arrival` (five seconds by default), including redirects after an action. A zero
236
+ wait makes one read without polling; that read retains the page operation's own timeout.
237
+ Each `Action` now records its ending address, so a bounded event history can still record the site
238
+ of later actions after its earlier navigation has expired.
239
+
240
+ `Plan.take(page, plan, index)` takes one step and returns a `Receipt`: the step index, host-clock
241
+ `startedAt` and `at`, and `taken`, `verified` or `skipped`. `Plan.replay` returns those receipts;
242
+ a `ReplayError` includes completed receipts and a serializable `stopped` value with the next step
243
+ and whether its input is `unsent` or `unknown`. Resume with `{ from: error.stopped }`. A numeric
244
+ index means fresh input, so never convert an unresolved stopping point into a number to retry it.
245
+ An interrupted call remains interrupted. Persist that a step has begun **before** calling it;
246
+ a missing receipt, including after a process restart, is `Stopped({ step, input: "unknown" })`.
247
+ The consumer owns that durable journal and the decision to reconcile a consequential operation.
248
+
249
+ An optional `Step.expect` checks `Checked`, `Appeared`, `Gone` or `Navigated` before input and
250
+ waits for it afterward. `verified` means the specified observation held; it is not a transaction
251
+ receipt from the target service. Keep the receipt with its plan to interpret that evidence.
252
+ `Checked` can converge a checkbox click to a desired boolean.
253
+ Unknown non-repeatable input is never automatically sent again: only a positive check explicitly
254
+ marked `durable: true` permits continuation. This is the author's assertion of a lasting,
255
+ uniquely scoped read-back, such as a saved order receipt. A toast or an intermediate URL cannot
256
+ justify it. A negative or failed durable check still leaves the operation uncertain.
257
+ Navigation, hover, scroll, selection and replacement typing without submission can be repeated;
258
+ back, reload, insertion, presses, drags and ordinary clicks cannot. `Plan.repeatable(step)` says
259
+ which applies. `Plan.restore(page, plan, { upTo, inputs })` reconstructs earlier steps on a fresh
260
+ page using those same rules and refuses unresolved commitments. `upTo` is exclusive.
261
+
262
+ `Plan.Plan.new(steps)` selects the stored version: recordings without expected checks remain
263
+ version 1; checks require version 2. Both decode, with version and contents validated together.
264
+ Old 0.2 plans and unknown versions do not decode.
230
265
 
231
266
  `Browser.Options.guard` is the input policy. Its `InputRequest` schema contains the action, the
232
267
  resolved element, the page's URL and title, and the `facts` the page's structure establishes:
@@ -667,25 +702,93 @@ its first glide starts mid-viewport, and each later one where the one before end
667
702
  input on another tab does meanwhile. Every sent move updates the position, including a partially
668
703
  cancelled glide. A later viewport clamps the starting point to its bounds if necessary.
669
704
 
670
- `Supervisor.make` keeps a browser open across losses and session ends, as generations, each a new
671
- browser from the provider's `open`. Opens run in the supervisor's own scope, so a caller that stops
672
- waiting never interrupts a half-open browser. `browser` gives the current generation, waiting up to
673
- `waitTimeout` while one opens. A lost browser is published at once, `Lost` with its browser's
674
- `disconnected` cause, and the next one opens on the `reopen` schedule, which also retries a failed
675
- open until it gives up, unless the provider deems the failure `definite`, such as a refused key:
676
- then the generation is `Down` at once, with its cause, which `Unavailable` also gives anyone
677
- waiting, because a schedule would only hide a configuration error. `rotate`, or the time
678
- `rotateBefore` ahead of a generation's browser's `expiresAt`, opens the next generation before it
679
- releases the current one, unless generations are `exclusive`: then the current one is released
680
- first.
681
- `retire` stops reopening at once and releases what is open, asking the provider's `release` before
682
- it closes a generation's scope; closing the scope retires too, unless the supervisor `keep`s: then
683
- the generation serving is left running, `Kept`, its scope closed but its provider never asked to
684
- release it, for a provider whose scope only disconnects. `states` streams each generation's
685
- `Opening`, `Reopening`, `Open`, `Lost`, `Down`, `Closed`, the last with the provider's release
686
- outcome, `Settled` or `Unconfirmed`, and `Kept`, so time open is a subtraction of their stamps.
687
- Pages don't carry over from one generation to the next. `effect-browserbase`'s
688
- `Browserbase.supervise` supervises hosted sessions, and with `keep` adopts the one it kept.
705
+ ## Supervising browser generations
706
+
707
+ `Supervisor.make` keeps a browser open across losses and session ends. Its `open` builds each
708
+ generation in a scope of its own and can return `{ browser, value }`: the application's pages,
709
+ tools or other resources belong to that generation. A caller that stops waiting never interrupts
710
+ the shared acquisition. Browser-only providers can continue returning `{ browser }`, with a
711
+ `void` value. Pages and values do not carry over when a new generation opens.
712
+
713
+ ```ts
714
+ import { Effect } from "effect";
715
+ import * as Chromium from "effect-browser/Chromium";
716
+ import * as Supervisor from "effect-browser/Supervisor";
717
+
718
+ const program = Effect.gen(function* () {
719
+ const browsers = yield* Supervisor.make({
720
+ open: Effect.gen(function* () {
721
+ const browser = yield* Chromium.open();
722
+ const page = yield* browser.firstPage;
723
+
724
+ return { browser, value: page };
725
+ }),
726
+ });
727
+ return yield* browsers.use(({ value: page }) => page.snapshot());
728
+ });
729
+ ```
730
+
731
+ `use(work, { wait })` atomically borrows the serving generation and runs `work` in a scope of its
732
+ own. The lease gives its `generation`, `browser`, `value`, an `ending` notice and `retain`.
733
+ `wait` defaults to `waitTimeout` (two minutes); zero either borrows immediately or fails
734
+ `Unavailable`. Cancelling the caller closes its work scope and lets its hold go. Ordinary work
735
+ errors stay ordinary work errors. `browser` still returns an unheld browser: use it only when the
736
+ caller can tolerate that generation being released underneath it.
737
+
738
+ A retained scope transfers a hold beyond the `use` call. Acquire anything that must travel with
739
+ that hold in its scope, and close it when the receiver is finished. Within a scoped program with
740
+ `browsers` as above and `Exit` and `Scope` imported from `effect`:
741
+
742
+ ```ts
743
+ const prepared =
744
+ yield *
745
+ browsers.use((lease) =>
746
+ Effect.gen(function* () {
747
+ const hold = yield* lease.retain;
748
+ const page = yield* Effect.acquireRelease(lease.browser.newPage(), (page) =>
749
+ page.close.pipe(Effect.ignore),
750
+ ).pipe(Scope.provide(hold));
751
+
752
+ return { page, hold, ending: lease.ending };
753
+ }),
754
+ );
755
+ // Hand `prepared` to its next owner; that owner eventually lets it go.
756
+ yield * Scope.close(prepared.hold, Exit.void);
757
+ ```
758
+
759
+ Rotation publishes `Draining` for the outgoing generation. It stays alive until its last hold
760
+ closes or `handover` expires, 30 seconds by default. `ending` is the first notice that it stopped
761
+ serving, with a `Superseded` reason and monotonic `revokeAt`; loss or retirement can revoke sooner.
762
+ At revocation, `use` interrupts work still running, waits for its finalizers and fails
763
+ `Superseded`. New `retain` calls refuse a revoked or releasing generation, and a retained scope
764
+ cannot extend the deadline. Retained scopes and work scopes close before the provider's
765
+ `release`; the generation's own scope closes last. Cleanup can therefore extend the time taken to
766
+ finish revocation. `Superseded` does not say whether an input reached the site: use the action's
767
+ receipt and plan stopping point to resolve that uncertainty.
768
+
769
+ Nonexclusive `rotate`, including `rotateBefore` timed rotation, opens the next generation while
770
+ old holds drain. Handover does not delay later rotations; multiple old generations can remain
771
+ owned, so the consumer chooses its rotation and overlap budget. Calls share one acquisition in
772
+ progress. Under `exclusive`, the current generation drains and finishes its provider release
773
+ before acquisition starts. Call `rotate` outside `use` for a clean cut: an exclusive rotation
774
+ inside `use` waits for its own hold to end or be revoked.
775
+
776
+ A loss publishes `Lost` with the browser's `disconnected` cause and revokes its holds immediately.
777
+ It reopens on `reopen`, which also retries an open failure until the schedule ends. A provider's
778
+ `definite` failure goes `Down` at once, with the cause also available through `Unavailable`.
779
+ `retire` revokes immediately, stops acquisition and waits for every generation to release.
780
+ Closing the supervisor's scope does the same unless `keep` is set: then only the serving
781
+ generation skips provider release, `Kept`; its application scopes still close. Other generations
782
+ are released normally.
783
+
784
+ `states` streams `Opening`, `Reopening`, `Open`, `Draining`, `Lost`, `Down`, `Closed` and `Kept`.
785
+ `Closed.released` preserves `Settled` or `Unconfirmed`; the latter does not establish that a
786
+ provider stopped the browser or its billing. `Generation.at` is wall-clock epoch milliseconds;
787
+ `hostTime` and `revokeAt` are host monotonic milliseconds from the supervisor's Effect `Clock`.
788
+ They can be compared with browser event and frame times when those use that same clock and host,
789
+ not across processes or against a provider's wall-clock timestamps. A generation event is
790
+ lifetime evidence, not proof that a frame was shown. `Browserbase.supervise` supplies hosted
791
+ generations and, with `keep`, can adopt one it previously kept.
689
792
 
690
793
  Every module is also an entry point, such as `effect-browser/Page`. The
691
794
  [repository README](https://github.com/mannyc2/effect-agent-browserbase#readme) has examples.
@@ -3,7 +3,7 @@ import { DialogShown, Disconnected, PageClosed, PageOpened, PageUntracked, Recor
3
3
  import { BrowserError, Closed, EventHistoryExpired, Failed, InvalidRequest, Limit } from "./BrowserError.mjs";
4
4
  import { c as FailFast, i as redact } from "./url-CcL0K7S0.mjs";
5
5
  import { i as failWith, s as undispatched, t as call } from "./context-DAYjATgC.mjs";
6
- import { n as make$3, o as mapping } from "./page-BkRcLCWZ.mjs";
6
+ import { n as make$3, o as mapping } from "./page-DHeYWEs-.mjs";
7
7
  import { Cause, Clock, Context, DateTime, Deferred, Duration, Effect, Exit, Option, Queue, Scope, Semaphore, Stream } from "effect";
8
8
  //#region src/internal/page/openings.ts
9
9
  /** A page's input waits for the actual tabs it opened to finish the browser's registration. */
@@ -434,4 +434,4 @@ const make = Effect.fn("Browser.make")(function* (context, info, options = {}) {
434
434
  //#endregion
435
435
  export { Browser_exports as n, make as r, Browser as t };
436
436
 
437
- //# sourceMappingURL=Browser-B5AV7zPS.mjs.map
437
+ //# sourceMappingURL=Browser-CNwK0r0q.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Browser-B5AV7zPS.mjs","names":["make","make","Url.redact","mapping","BrowserClock.mapping","Timeline.make","PageImpl.make","Openings.make"],"sources":["../src/internal/page/openings.ts","../src/internal/timeline/events.ts","../src/Browser.ts"],"sourcesContent":["/** A page's input waits for the actual tabs it opened to finish the browser's registration. */\nimport { Deferred, Effect, Exit } from \"effect\";\nimport type { CDPSession, Page as PlaywrightPage } from \"playwright-core\";\n\nimport { BrowserError, Closed, Failed, type Reason } from \"../../BrowserError.ts\";\n\n/** How the browser's registration of each tab it was told of ended, once it has. */\nexport type Registrations = WeakMap<PlaywrightPage, Deferred.Deferred<void, BrowserError>>;\n\nexport interface Mark {\n windows: number;\n readonly registrations: Array<Effect.Effect<void, BrowserError>>;\n changed: Deferred.Deferred<void>;\n}\n\nexport const make = Effect.fnUntraced(function* (\n playwright: PlaywrightPage,\n cdp: CDPSession,\n registrations: Registrations,\n closedBy: () => Closed[\"cause\"],\n) {\n const failed = (reason: Reason) =>\n Exit.fail(new BrowserError({ operation: \"newPage\", reason, dispatched: false }));\n\n let active: Mark | undefined;\n const gone = Deferred.makeUnsafe<never, BrowserError>();\n\n const windowOpened = () => {\n if (active !== undefined) active.windows += 1;\n };\n\n const popup = (opened: PlaywrightPage) => {\n if (active === undefined) return;\n // Playwright emits the context's page event first, so its owner already has this exact\n // popup's registration. A window notification alone has no target id and cannot name it.\n const registered = registrations.get(opened);\n\n active.registrations.push(\n registered === undefined\n ? failed(new Failed({ detail: \"the popup has no registration\" }))\n : Deferred.await(registered),\n );\n Deferred.doneUnsafe(active.changed, Exit.void);\n active.changed = Deferred.makeUnsafe<void>();\n };\n\n const clear = Effect.sync(() => {\n active = undefined;\n });\n\n yield* Effect.acquireRelease(\n Effect.sync(() => {\n cdp.on(\"Page.windowOpen\", windowOpened);\n playwright.on(\"popup\", popup);\n }),\n () =>\n Effect.sync(() => {\n active = undefined;\n cdp.off(\"Page.windowOpen\", windowOpened);\n playwright.off(\"popup\", popup);\n Deferred.doneUnsafe(gone, failed(new Closed({ cause: closedBy() })));\n }),\n );\n\n return {\n mark: () => {\n const mark: Mark = { windows: 0, registrations: [], changed: Deferred.makeUnsafe<void>() };\n\n active = mark;\n\n return mark;\n },\n clear,\n settle: (mark: Mark) =>\n Effect.gen(function* () {\n // A blocked window or a tab that closes as it opens may never become a Playwright popup.\n // Discovery and registration both share the input's deadline, so an unresolved opening\n // fails with potentially dispatched input rather than claiming the tab has been tracked.\n while (mark.registrations.length < mark.windows) yield* Deferred.await(mark.changed);\n // A real popup has a known registration; its failure stays a failure, and its wait shares\n // the input's deadline rather than quietly returning before the browser tracks it.\n yield* Effect.forEach(mark.registrations, (registration) => registration);\n }).pipe(Effect.raceFirst(Deferred.await(gone)), Effect.ensuring(clear)),\n };\n});\n\nexport type Openings = Effect.Success<ReturnType<typeof make>>;\n","/**\n * The browser's bounded event history and replay cursors. Readers share the same records and\n * wakeup generation, so a delayed reader cannot block input or retain an unbounded private queue.\n */\nimport { Cause, Deferred, Effect, Stream } from \"effect\";\n\nimport { type BrowserError, EventHistoryExpired, InvalidRequest } from \"../../BrowserError.ts\";\nimport { type BrowserEvent, RecordedEvent } from \"../../BrowserEvent.ts\";\nimport { undispatched } from \"../page/context.ts\";\n\n/** The owning Browser validates capacity and closes this timeline with its scope. */\nexport const make = (capacity: number) => {\n let records: ReadonlyArray<RecordedEvent> = [];\n let sequence = 0;\n let closed = false;\n let changed = Deferred.makeUnsafe<void>();\n\n const wake = () => {\n const previous = changed;\n\n changed = Deferred.makeUnsafe<void>();\n Deferred.doneUnsafe(previous, Effect.void);\n };\n\n const publish = (event: BrowserEvent): number => {\n // Native callbacks may finish after their owning scope. They must not revive closed readers.\n if (closed) return sequence;\n sequence += 1;\n const recorded = new RecordedEvent({ sequence, event });\n\n records = records.length < capacity ? [...records, recorded] : [...records.slice(1), recorded];\n wake();\n\n return sequence;\n };\n\n const stream = (after?: number): Stream.Stream<RecordedEvent, BrowserError> =>\n Stream.unwrap(\n Effect.sync(() => {\n // This runs for each subscription, rather than when the reusable stream is constructed.\n let cursor = after ?? sequence;\n\n if (!Number.isSafeInteger(cursor) || cursor < 0 || cursor > sequence)\n return Stream.fail(\n undispatched(\n \"events\",\n new InvalidRequest({\n detail:\n \"the event cursor must be a nonnegative integer no greater than the latest sequence\",\n }),\n ),\n );\n\n return Stream.fromEffectRepeat(\n Effect.gen(function* () {\n while (true) {\n const oldest = records[0]?.sequence ?? sequence + 1;\n\n if (cursor < oldest - 1)\n return yield* undispatched(\n \"events\",\n new EventHistoryExpired({ after: cursor, oldest, latest: sequence }),\n );\n const next = records[cursor - oldest + 1];\n\n if (next !== undefined) {\n cursor = next.sequence;\n\n return next;\n }\n if (closed) return yield* Cause.done();\n // Capture the generation in the same synchronous read as the empty history check.\n // A publish before await completes this exact Deferred, so no wakeup can be missed.\n const waiting = changed;\n\n yield* Deferred.await(waiting);\n }\n }),\n );\n }),\n );\n\n return {\n publish,\n recent: Effect.sync(() => records),\n stream,\n close: Effect.sync(() => {\n if (closed) return;\n closed = true;\n wake();\n }),\n };\n};\n","/**\n * A live browser: its pages and what happens in it.\n *\n * `Browser` is a service with one implementation, built by a provider over a Playwright browser\n * context: `Chromium` launches one locally, `Cdp` connects to any DevTools endpoint and\n * `effect-browserbase` allocates a hosted one. Code written against `Browser` runs on all three.\n * A page is named by its CDP target id, so a new connection to the same browser finds it again.\n *\n * @since 0.3.0\n */\nimport {\n Clock,\n Context,\n DateTime,\n Deferred,\n Duration,\n Effect,\n Exit,\n Option,\n Queue,\n Scope,\n Semaphore,\n type Stream,\n} from \"effect\";\nimport type { BrowserContext, Dialog, Page as PlaywrightPage } from \"playwright-core\";\n\nimport { type BrowserError, Failed, InvalidRequest, Limit } from \"./BrowserError.ts\";\nimport {\n type BrowserEvent,\n DialogShown,\n Disconnected,\n type DisconnectCause,\n PageClosed,\n PageOpened,\n PageUntracked,\n type RecordedEvent,\n SessionEnding,\n} from \"./BrowserEvent.ts\";\nimport { call, failWith, type Settings, undispatched } from \"./internal/page/context.ts\";\nimport { FailFast } from \"./internal/page/lane.ts\";\nimport * as Openings from \"./internal/page/openings.ts\";\nimport * as PageImpl from \"./internal/page/page.ts\";\nimport * as Url from \"./internal/page/url.ts\";\nimport * as BrowserClock from \"./internal/pictures/clock.ts\";\nimport * as Timeline from \"./internal/timeline/events.ts\";\nimport type * as Page from \"./Page.ts\";\n\n/** A script that documents run before their own, such as a consent-banner remover. */\nexport interface InitScript {\n /**\n * The documents that run it, by a pattern their address (`location.href`) matches; every\n * document and frame when left out. Under a `match`, the source runs as a block, so its own\n * top-level `let`, `const` and classes stay its own.\n */\n readonly match?: RegExp | undefined;\n readonly source: string;\n}\n\nexport interface Options {\n /**\n * Bound on each action; finite and positive. Defaults to 10 seconds. What a presenter's view\n * takes to show an action, such as its glides and typing at a person's pace, does not count\n * against it.\n */\n readonly actionTimeout?: Duration.Input | undefined;\n /** Bound on each navigation; finite and positive. Defaults to 30 seconds. */\n readonly navigationTimeout?: Duration.Input | undefined;\n /**\n * How long each page keeps screencast frames for `recentFrames`, measured back from the newest;\n * finite and positive. Defaults to 5 seconds, a moment's default window.\n */\n readonly frameHistory?: Duration.Input | undefined;\n /** Events retained for replay and `recentEvents`. A positive safe integer, defaulting to 4,096. */\n readonly eventHistory?: number | undefined;\n /** Allow, deny or hold each input or navigation before it reaches the page. Defaults to allow. */\n readonly guard?: Page.InputGuard | undefined;\n /** A separate bound for policy holds, outside action timeouts. Defaults to 5 minutes. */\n readonly policyTimeout?: Duration.Input | undefined;\n /** Scripts that new documents run before their own, each where its `match` allows. */\n readonly initScripts?: ReadonlyArray<InitScript> | undefined;\n /**\n * The most pages the browser keeps open, those a site opens included, which are never refused. At\n * it, `newPage` waits for one to close, within the action timeout, then fails `Limit`; under\n * `Page.failFast` it fails at once. A positive safe integer; no limit when left out.\n */\n readonly maxPages?: number | undefined;\n}\n\nexport interface EventOptions {\n /** Resume after this sequence; 0 replays from the beginning if it is still retained. */\n readonly after?: number | undefined;\n}\n\n/**\n * A connection to the browser apart from the one that drives its pages, for their screencasts,\n * as a provider that reaches the browser over a network supplies it: a frame and its\n * acknowledgement then never wait behind a large message, such as an upload or a read's answer,\n * on the connection that drives the page. It is read-only. A page's session on it sends the\n * capture's commands alone, and the page's own session keeps its focus emulation, which keeps a\n * tab behind painting.\n */\nexport interface CaptureSource {\n /**\n * A session on the page's target, for the scope. `event` gets the session's events in the order\n * the browser sent them, its target's detach among them, until the scope closes; `lost` gets\n * the connection's failure, once, if it fails first. Its calls never throw: a failure rejects.\n */\n readonly attach: (\n target: string,\n listener: {\n readonly event: (method: string, params: unknown) => void;\n readonly lost: (error: BrowserError) => void;\n },\n ) => Effect.Effect<\n (\n method:\n | \"Page.enable\"\n | \"Page.getFrameTree\"\n | \"Page.startScreencast\"\n | \"Page.screencastFrameAck\"\n | \"Page.stopScreencast\",\n params?: Record<string, unknown>,\n ) => Promise<unknown>,\n BrowserError,\n Scope.Scope\n >;\n}\n\nexport interface Service {\n /** The provider's session id, or a local id. */\n readonly id: string;\n readonly provider: string;\n /** When the provider ends the session on its own, as a hosted session's timeout does. */\n readonly expiresAt: DateTime.Utc | undefined;\n /** Host monotonic milliseconds on the clock shared by this browser’s events and frames. */\n readonly now: Effect.Effect<number>;\n /** The Playwright context, for anything this API does not cover. Never give it to a model. */\n readonly context: BrowserContext;\n /** Open pages in the order this browser began tracking them. */\n readonly pages: Effect.Effect<ReadonlyArray<Page.Page>>;\n /** The open page with this id, its CDP target id, as stored before a reconnect. */\n readonly page: (id: string) => Effect.Effect<Option.Option<Page.Page>>;\n /** The first open page, opening one when there is none. */\n readonly firstPage: Effect.Effect<Page.Page, BrowserError>;\n readonly newPage: (url?: string) => Effect.Effect<Page.Page, BrowserError>;\n /**\n * Completes once the browser is lost to its owner, with why: its connection dropped, its\n * provider ended its session, or its owner's scope released it.\n */\n readonly disconnected: Effect.Effect<DisconnectCause>;\n /** Live events, or replay after a cursor. A reader that falls behind fails with EventHistoryExpired. */\n readonly events: (options?: EventOptions) => Stream.Stream<RecordedEvent, BrowserError>;\n /** The latest `eventHistory` events, oldest first. */\n readonly recentEvents: Effect.Effect<ReadonlyArray<BrowserEvent>>;\n}\n\nexport class Browser extends Context.Service<Browser, Service>()(\"effect-browser/Browser\") {}\n\n/** The settings every page shares, and how many events the browser keeps, from its options. */\nconst settingsOf = Effect.fnUntraced(function* (options: Options) {\n const invalid = (detail: string) => undispatched(\"make\", new InvalidRequest({ detail }));\n\n // Every bound guards a lock or a held key, so each must be a real, finite deadline.\n const bound = (name: string, input: Duration.Input | undefined, fallback: Duration.Duration) => {\n const decoded = Duration.fromInput(input ?? fallback);\n\n return Option.isSome(decoded) &&\n Number.isFinite(Duration.toMillis(decoded.value)) &&\n Duration.isPositive(decoded.value)\n ? Effect.succeed(decoded.value)\n : Effect.fail(invalid(`${name} must be finite and greater than zero`));\n };\n\n const settings: Settings = {\n actionTimeout: yield* bound(\"actionTimeout\", options.actionTimeout, Duration.seconds(10)),\n navigationTimeout: yield* bound(\n \"navigationTimeout\",\n options.navigationTimeout,\n Duration.seconds(30),\n ),\n frameHistory: yield* bound(\"frameHistory\", options.frameHistory, Duration.seconds(5)),\n guard: options.guard,\n policyTimeout: yield* bound(\"policyTimeout\", options.policyTimeout, Duration.minutes(5)),\n };\n\n const eventHistory = options.eventHistory ?? 4096;\n const { maxPages } = options;\n\n if (!Number.isSafeInteger(eventHistory) || eventHistory < 1)\n return yield* invalid(\"eventHistory must be a positive safe integer\");\n if (maxPages !== undefined && (!Number.isSafeInteger(maxPages) || maxPages < 1))\n return yield* invalid(\"maxPages must be a positive safe integer\");\n\n return { settings, eventHistory, maxPages };\n});\n\n/**\n * A provider that ends a session at `expiresAt` by its own clock can cut the connection a little\n * before this host's clock gets there.\n */\nconst endMargin = Duration.seconds(5);\n\n/**\n * The browser's loss, once: its context closing from the other side, at or after the session's\n * end or before it, or `lose`, as the owner's scope releases it. Playwright leaves the calls in\n * flight on the library's own sessions unanswered when the connection drops, so `untilLost` fails\n * each with the browser, as a closed page's call fails.\n */\nconst watchLoss = Effect.fnUntraced(function* (\n context: BrowserContext,\n expiresAt: DateTime.Utc | undefined,\n clock: Clock.Clock,\n disconnected: (cause: DisconnectCause) => void,\n) {\n let lostBy: DisconnectCause | undefined;\n const lost = yield* Deferred.make<DisconnectCause>();\n const inFlight = new Set<(cause: Error) => void>();\n const gone = () => new Error(\"Target page, context or browser has been closed\");\n\n const lose = (cause: DisconnectCause) => {\n if (lostBy !== undefined) return;\n lostBy = cause;\n for (const reject of inFlight) reject(gone());\n disconnected(cause);\n Deferred.doneUnsafe(lost, Exit.succeed(cause));\n };\n\n const untilLost = <A>(reply: Promise<A>): Promise<A> => {\n if (lostBy !== undefined) {\n void reply.catch(() => undefined);\n\n return Promise.reject(gone());\n }\n\n return new Promise<A>((resolve, reject) => {\n inFlight.add(reject);\n void reply.then(resolve, reject).finally(() => inFlight.delete(reject));\n });\n };\n\n const ended = () =>\n expiresAt !== undefined &&\n clock.currentTimeMillisUnsafe() >=\n DateTime.toEpochMillis(expiresAt) - Duration.toMillis(endMargin);\n\n const onClose = () => lose(ended() ? \"session\" : \"connection\");\n\n context.on(\"close\", onClose);\n yield* Effect.addFinalizer(() => Effect.sync(() => context.off(\"close\", onClose)));\n if (context.browser()?.isConnected() === false) onClose();\n\n const native = <A>(operation: string, run: () => Promise<A>) =>\n call(operation, run, () => lostBy ?? \"page\");\n\n return { lostBy: () => lostBy, lost: Deferred.await(lost), lose, untilLost, native };\n});\n\n/**\n * What a page's own Playwright events publish, its close and crash aside, while its scope is\n * open. Dialogs are answered: alerts accepted, others dismissed. The page's own session tells its\n * documents' commits and loads.\n */\nconst listen = (\n playwright: PlaywrightPage,\n page: string,\n publish: (event: BrowserEvent) => number,\n now: () => number,\n on: { readonly close: () => void; readonly crash: () => void },\n) => {\n const dialog = (shown: Dialog) => {\n const kind = shown.type();\n const answer = kind === \"alert\" || kind === \"beforeunload\" ? \"accepted\" : \"dismissed\";\n const message = shown.message().slice(0, 500);\n\n publish(new DialogShown({ at: now(), page, kind, message, answer }));\n (answer === \"accepted\" ? shown.accept() : shown.dismiss()).catch(() => undefined);\n };\n\n return Effect.acquireRelease(\n Effect.sync(() => {\n playwright.on(\"close\", on.close);\n playwright.on(\"crash\", on.crash);\n playwright.on(\"dialog\", dialog);\n }),\n () =>\n Effect.sync(() => {\n playwright.off(\"close\", on.close);\n playwright.off(\"crash\", on.crash);\n playwright.off(\"dialog\", dialog);\n }),\n );\n};\n\n/**\n * Register each page the site opens, such as a popup, as Playwright reports it, for as long as the\n * scope is open. One that could not be tracked is published, unless it closed as it opened.\n */\nconst followOpened = Effect.fnUntraced(function* (\n context: BrowserContext,\n register: (playwright: PlaywrightPage) => Effect.Effect<Page.Page, BrowserError>,\n publish: (event: BrowserEvent) => number,\n now: () => number,\n registrations: Openings.Registrations,\n) {\n const opened = yield* Queue.unbounded<PlaywrightPage>();\n\n const onPage = (playwright: PlaywrightPage) => {\n registrations.set(playwright, Deferred.makeUnsafe<void, BrowserError>());\n Queue.offerUnsafe(opened, playwright);\n };\n\n const untracked = (playwright: PlaywrightPage) => (error: BrowserError) =>\n Effect.sync(() => {\n const url = Url.redact(playwright.url());\n\n if (!playwright.isClosed())\n publish(new PageUntracked({ at: now(), url, detail: error.message }));\n });\n\n context.on(\"page\", onPage);\n yield* Effect.addFinalizer(() => Effect.sync(() => context.off(\"page\", onPage)));\n yield* Queue.take(opened).pipe(\n Effect.flatMap((playwright) =>\n register(playwright).pipe(\n Effect.asVoid,\n Effect.onExit((exit) =>\n Effect.sync(() => {\n const done = registrations.get(playwright);\n\n if (done !== undefined) Deferred.doneUnsafe(done, exit);\n }),\n ),\n Effect.catch(untracked(playwright)),\n ),\n ),\n Effect.forever,\n Effect.forkScoped,\n );\n});\n\n/** Release something native, on the owner's clock, giving up after a second: cleanup only. */\nconst releaseNative = (clock: Clock.Clock) => (run: () => Promise<unknown>) =>\n Effect.tryPromise(run).pipe(\n Effect.interruptible,\n Effect.timeoutOrElse({ duration: Duration.seconds(1), orElse: () => Effect.void }),\n Effect.provideService(Clock.Clock, clock),\n Effect.ignore,\n );\n\n/** A page's own events among the browser's retained ones, and the openings of tabs it opened. */\nconst eventsOf = (recent: Effect.Effect<ReadonlyArray<RecordedEvent>>, page: string) =>\n Effect.map(recent, (records) =>\n records.flatMap(({ event }) =>\n (\"page\" in event && event.page === page) ||\n (event._tag === \"PageOpened\" && event.opener === page)\n ? [event]\n : [],\n ),\n );\n\n/** A script as its documents run it: everywhere, or as a block where its `match` allows. */\nconst scoped = ({ match, source }: InitScript) =>\n match === undefined ? source : `if (${String(match)}.test(location.href)) {\\n${source}\\n}`;\n\n/**\n * At most `maxPages` open pages, those a site opened included, which are never refused: an open\n * past it waits for one to close, within `wait` on the owner's clock, then fails `Limit`, or fails\n * at once under `FailFast`. An open counts until its page is tracked.\n */\nconst pageBudget = (\n maxPages: number | undefined,\n tracked: () => number,\n wait: Duration.Duration,\n clock: Clock.Clock,\n) => {\n let opening = 0;\n // Completed as a page closes or an open ends, so the opens waiting look again.\n let roomMade = Deferred.makeUnsafe<void>();\n\n const makeRoom = () => {\n Deferred.doneUnsafe(roomMade, Exit.void);\n roomMade = Deferred.makeUnsafe<void>();\n };\n\n const full = (limit: number) => tracked() + opening >= limit;\n\n const room = (limit: number) =>\n Effect.gen(function* () {\n const refused = undispatched(\"newPage\", new Limit({ maxPages: limit }));\n\n if ((yield* FailFast) && full(limit)) return yield* refused;\n yield* Effect.gen(function* () {\n while (full(limit)) yield* Deferred.await(roomMade);\n opening += 1;\n }).pipe(\n Effect.timeoutOrElse({ duration: wait, orElse: () => Effect.fail(refused) }),\n Effect.provideService(Clock.Clock, clock),\n );\n });\n\n const open = <A, E, R>(opened: Effect.Effect<A, E, R>) =>\n maxPages === undefined\n ? opened\n : Effect.uninterruptibleMask((restore) =>\n restore(room(maxPages)).pipe(\n Effect.andThen(\n restore(opened).pipe(\n Effect.ensuring(\n Effect.sync(() => {\n opening -= 1;\n makeRoom();\n }),\n ),\n ),\n ),\n ),\n );\n\n return { makeRoom, open };\n};\n\n/** A call sent now and awaited later, by whatever needs its answer. */\nconst sentNow = <A>(sent: Promise<A>) => {\n void sent.catch(() => undefined);\n\n return sent;\n};\n\n/**\n * Build the service over a context the provider owns. The provider closes the context; this only\n * tracks its pages and events, for as long as the surrounding scope is open. Each page's protocol\n * session, capture and listeners end when that page closes or when the scope does, so a closed\n * tab retains nothing and the context keeps none of them afterwards.\n */\nexport const make = Effect.fn(\"Browser.make\")(function* (\n context: BrowserContext,\n info: {\n readonly id: string;\n readonly provider: string;\n readonly expiresAt?: DateTime.Utc | undefined;\n /** Where pages' screencasts run, if not on each page's own session. */\n readonly capture?: CaptureSource | undefined;\n },\n options: Options = {},\n) {\n const clock = yield* Clock.Clock;\n const now = () => Number(clock.monotonicTimeNanosUnsafe()) / 1e6;\n const { settings, eventHistory, maxPages } = yield* settingsOf(options);\n // Measured on first need: the first capture of any page measures it, and input never waits.\n const mapping = BrowserClock.mapping(now);\n\n const timeline = Timeline.make(eventHistory);\n\n yield* Effect.addFinalizer(() => timeline.close);\n const publish = timeline.publish;\n\n if (info.expiresAt !== undefined)\n publish(new SessionEnding({ at: now(), expiresAt: info.expiresAt }));\n\n const { lostBy, lost, lose, untilLost, native } = yield* watchLoss(\n context,\n info.expiresAt,\n clock,\n (cause) => publish(new Disconnected({ at: now(), cause })),\n );\n\n const registry = new Map<PlaywrightPage, Page.Page>();\n const registrations: Openings.Registrations = new WeakMap();\n const registering = yield* Semaphore.make(1);\n // The pages' scopes close after the browser is marked released, so what fails as they close\n // says why.\n const pagesScope = yield* Scope.fork(yield* Scope.Scope);\n\n const release = releaseNative(clock);\n const budget = pageBudget(maxPages, () => registry.size, settings.actionTimeout, clock);\n\n // Each tab's scope closes with the tab or the browser. A dropped connection closes every page,\n // then the context, and `Disconnected` stands for all of them: the queue hands a close to its\n // fiber in a later turn, once Playwright has reported the context's.\n const closing = yield* Queue.unbounded<{\n readonly scope: Scope.Closeable;\n readonly page: string;\n readonly cause: PageClosed[\"cause\"];\n }>();\n\n yield* Queue.take(closing).pipe(\n Effect.tap(({ page, cause }) =>\n Effect.sync(() => {\n if (lostBy() === undefined) publish(new PageClosed({ at: now(), page, cause }));\n }),\n ),\n Effect.flatMap(({ scope }) => Scope.close(scope, Exit.void)),\n Effect.forever,\n Effect.forkScoped,\n );\n\n const register = (playwright: PlaywrightPage) =>\n registering.withPermits(1)(\n Effect.gen(function* () {\n const known = registry.get(playwright);\n\n if (known !== undefined) return known;\n if (playwright.isClosed())\n return yield* failWith(\"newPage\", new Failed({ detail: \"the page closed as it opened\" }));\n const scope = yield* Scope.fork(pagesScope);\n\n return yield* Effect.gen(function* () {\n let crashed = false;\n const closedBy = () => lostBy() ?? (crashed ? \"crashed\" : \"page\");\n const cdp = yield* native(\"newPage\", () => context.newCDPSession(playwright));\n\n yield* Effect.addFinalizer(() => release(() => cdp.detach()));\n // The page's name, its target id, costs one round trip, which the calls that keep it\n // painting behind other tabs and report its documents share. A renderer busy with its\n // first script answers those two late, so what needs them waits, and registering does not.\n const send: typeof cdp.send = (method, params) => untilLost(cdp.send(method, params));\n const focusing = sentNow(send(\"Emulation.setFocusEmulationEnabled\", { enabled: true }));\n const paging = sentNow(send(\"Page.enable\"));\n const { targetInfo } = yield* native(\"newPage\", () => send(\"Target.getTargetInfo\"));\n const id = targetInfo.targetId;\n\n const page = yield* PageImpl.make({\n id,\n session: info.id,\n url: targetInfo.url,\n playwright,\n cdp,\n untilLost,\n settings,\n clock,\n mapping,\n publish,\n recentEvents: eventsOf(timeline.recent, id),\n openings: yield* Openings.make(playwright, cdp, registrations, closedBy),\n focused: call(\"focus\", () => focusing, closedBy).pipe(Effect.asVoid),\n paging: (operation) => call(operation, () => paging, closedBy).pipe(Effect.asVoid),\n closedBy,\n capture: info.capture,\n });\n\n const close = () => {\n if (registry.get(playwright) !== page) return;\n registry.delete(playwright);\n budget.makeRoom();\n Queue.offerUnsafe(closing, { scope, page: id, cause: crashed ? \"crashed\" : \"page\" });\n };\n\n // Playwright drives a crashed page no more and its calls never return, so it is closed:\n // they fail at once, `Closed` because it crashed.\n const crash = () => {\n crashed = true;\n void playwright.close().catch(() => undefined);\n };\n\n registry.set(playwright, page);\n publish(\n new PageOpened({\n at: now(),\n page: id,\n url: Url.redact(targetInfo.url),\n opener: targetInfo.openerId,\n }),\n );\n yield* listen(playwright, id, publish, now, { close, crash });\n if (playwright.isClosed()) close();\n\n return page;\n }).pipe(\n Scope.provide(scope),\n Effect.onError(() => Scope.close(scope, Exit.void)),\n );\n }),\n );\n\n // Playwright registers its init scripts as it sets up each page, before a popup's first document\n // runs, and they cost no call per document.\n for (const script of options.initScripts ?? [])\n yield* native(\"initScripts\", () => context.addInitScript({ content: scoped(script) }));\n yield* followOpened(context, register, publish, now, registrations);\n for (const existing of context.pages()) yield* register(existing);\n\n const pages = Effect.sync(() => [...registry.values()]);\n\n const newPage = Effect.fn(\"Browser.newPage\")(function* (url?: string) {\n const page = yield* budget.open(\n native(\"newPage\", () => context.newPage()).pipe(\n Effect.flatMap((playwright) =>\n register(playwright).pipe(Effect.onError(() => release(() => playwright.close()))),\n ),\n ),\n );\n\n // A rejected or interrupted navigation must not leave the newly allocated blank tab behind.\n if (url !== undefined)\n yield* page.goto(url).pipe(Effect.onError(() => page.close.pipe(Effect.ignore)));\n\n return page;\n });\n\n // Added last, so it runs first as the owner's scope closes.\n yield* Effect.addFinalizer(() => Effect.sync(() => lose(\"released\")));\n\n const service: Service = {\n id: info.id,\n provider: info.provider,\n expiresAt: info.expiresAt,\n now: Effect.sync(now),\n context,\n pages,\n page: (id) =>\n Effect.map(pages, (open) => Option.fromNullishOr(open.find((page) => page.id === id))),\n firstPage: pages.pipe(\n Effect.map((open) => Option.fromNullishOr(open[0])),\n Effect.flatMap(Option.match({ onNone: () => newPage(), onSome: Effect.succeed })),\n ),\n newPage,\n disconnected: lost,\n events: (eventOptions = {}) => timeline.stream(eventOptions.after),\n recentEvents: timeline.recent.pipe(\n Effect.map((records) => records.map((record) => record.event)),\n ),\n };\n\n return Browser.of(service);\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"Browser-CNwK0r0q.mjs","names":["make","make","Url.redact","mapping","BrowserClock.mapping","Timeline.make","PageImpl.make","Openings.make"],"sources":["../src/internal/page/openings.ts","../src/internal/timeline/events.ts","../src/Browser.ts"],"sourcesContent":["/** A page's input waits for the actual tabs it opened to finish the browser's registration. */\nimport { Deferred, Effect, Exit } from \"effect\";\nimport type { CDPSession, Page as PlaywrightPage } from \"playwright-core\";\n\nimport { BrowserError, Closed, Failed, type Reason } from \"../../BrowserError.ts\";\n\n/** How the browser's registration of each tab it was told of ended, once it has. */\nexport type Registrations = WeakMap<PlaywrightPage, Deferred.Deferred<void, BrowserError>>;\n\nexport interface Mark {\n windows: number;\n readonly registrations: Array<Effect.Effect<void, BrowserError>>;\n changed: Deferred.Deferred<void>;\n}\n\nexport const make = Effect.fnUntraced(function* (\n playwright: PlaywrightPage,\n cdp: CDPSession,\n registrations: Registrations,\n closedBy: () => Closed[\"cause\"],\n) {\n const failed = (reason: Reason) =>\n Exit.fail(new BrowserError({ operation: \"newPage\", reason, dispatched: false }));\n\n let active: Mark | undefined;\n const gone = Deferred.makeUnsafe<never, BrowserError>();\n\n const windowOpened = () => {\n if (active !== undefined) active.windows += 1;\n };\n\n const popup = (opened: PlaywrightPage) => {\n if (active === undefined) return;\n // Playwright emits the context's page event first, so its owner already has this exact\n // popup's registration. A window notification alone has no target id and cannot name it.\n const registered = registrations.get(opened);\n\n active.registrations.push(\n registered === undefined\n ? failed(new Failed({ detail: \"the popup has no registration\" }))\n : Deferred.await(registered),\n );\n Deferred.doneUnsafe(active.changed, Exit.void);\n active.changed = Deferred.makeUnsafe<void>();\n };\n\n const clear = Effect.sync(() => {\n active = undefined;\n });\n\n yield* Effect.acquireRelease(\n Effect.sync(() => {\n cdp.on(\"Page.windowOpen\", windowOpened);\n playwright.on(\"popup\", popup);\n }),\n () =>\n Effect.sync(() => {\n active = undefined;\n cdp.off(\"Page.windowOpen\", windowOpened);\n playwright.off(\"popup\", popup);\n Deferred.doneUnsafe(gone, failed(new Closed({ cause: closedBy() })));\n }),\n );\n\n return {\n mark: () => {\n const mark: Mark = { windows: 0, registrations: [], changed: Deferred.makeUnsafe<void>() };\n\n active = mark;\n\n return mark;\n },\n clear,\n settle: (mark: Mark) =>\n Effect.gen(function* () {\n // A blocked window or a tab that closes as it opens may never become a Playwright popup.\n // Discovery and registration both share the input's deadline, so an unresolved opening\n // fails with potentially dispatched input rather than claiming the tab has been tracked.\n while (mark.registrations.length < mark.windows) yield* Deferred.await(mark.changed);\n // A real popup has a known registration; its failure stays a failure, and its wait shares\n // the input's deadline rather than quietly returning before the browser tracks it.\n yield* Effect.forEach(mark.registrations, (registration) => registration);\n }).pipe(Effect.raceFirst(Deferred.await(gone)), Effect.ensuring(clear)),\n };\n});\n\nexport type Openings = Effect.Success<ReturnType<typeof make>>;\n","/**\n * The browser's bounded event history and replay cursors. Readers share the same records and\n * wakeup generation, so a delayed reader cannot block input or retain an unbounded private queue.\n */\nimport { Cause, Deferred, Effect, Stream } from \"effect\";\n\nimport { type BrowserError, EventHistoryExpired, InvalidRequest } from \"../../BrowserError.ts\";\nimport { type BrowserEvent, RecordedEvent } from \"../../BrowserEvent.ts\";\nimport { undispatched } from \"../page/context.ts\";\n\n/** The owning Browser validates capacity and closes this timeline with its scope. */\nexport const make = (capacity: number) => {\n let records: ReadonlyArray<RecordedEvent> = [];\n let sequence = 0;\n let closed = false;\n let changed = Deferred.makeUnsafe<void>();\n\n const wake = () => {\n const previous = changed;\n\n changed = Deferred.makeUnsafe<void>();\n Deferred.doneUnsafe(previous, Effect.void);\n };\n\n const publish = (event: BrowserEvent): number => {\n // Native callbacks may finish after their owning scope. They must not revive closed readers.\n if (closed) return sequence;\n sequence += 1;\n const recorded = new RecordedEvent({ sequence, event });\n\n records = records.length < capacity ? [...records, recorded] : [...records.slice(1), recorded];\n wake();\n\n return sequence;\n };\n\n const stream = (after?: number): Stream.Stream<RecordedEvent, BrowserError> =>\n Stream.unwrap(\n Effect.sync(() => {\n // This runs for each subscription, rather than when the reusable stream is constructed.\n let cursor = after ?? sequence;\n\n if (!Number.isSafeInteger(cursor) || cursor < 0 || cursor > sequence)\n return Stream.fail(\n undispatched(\n \"events\",\n new InvalidRequest({\n detail:\n \"the event cursor must be a nonnegative integer no greater than the latest sequence\",\n }),\n ),\n );\n\n return Stream.fromEffectRepeat(\n Effect.gen(function* () {\n while (true) {\n const oldest = records[0]?.sequence ?? sequence + 1;\n\n if (cursor < oldest - 1)\n return yield* undispatched(\n \"events\",\n new EventHistoryExpired({ after: cursor, oldest, latest: sequence }),\n );\n const next = records[cursor - oldest + 1];\n\n if (next !== undefined) {\n cursor = next.sequence;\n\n return next;\n }\n if (closed) return yield* Cause.done();\n // Capture the generation in the same synchronous read as the empty history check.\n // A publish before await completes this exact Deferred, so no wakeup can be missed.\n const waiting = changed;\n\n yield* Deferred.await(waiting);\n }\n }),\n );\n }),\n );\n\n return {\n publish,\n recent: Effect.sync(() => records),\n stream,\n close: Effect.sync(() => {\n if (closed) return;\n closed = true;\n wake();\n }),\n };\n};\n","/**\n * A live browser: its pages and what happens in it.\n *\n * `Browser` is a service with one implementation, built by a provider over a Playwright browser\n * context: `Chromium` launches one locally, `Cdp` connects to any DevTools endpoint and\n * `effect-browserbase` allocates a hosted one. Code written against `Browser` runs on all three.\n * A page is named by its CDP target id, so a new connection to the same browser finds it again.\n *\n * @since 0.3.0\n */\nimport {\n Clock,\n Context,\n DateTime,\n Deferred,\n Duration,\n Effect,\n Exit,\n Option,\n Queue,\n Scope,\n Semaphore,\n type Stream,\n} from \"effect\";\nimport type { BrowserContext, Dialog, Page as PlaywrightPage } from \"playwright-core\";\n\nimport { type BrowserError, Failed, InvalidRequest, Limit } from \"./BrowserError.ts\";\nimport {\n type BrowserEvent,\n DialogShown,\n Disconnected,\n type DisconnectCause,\n PageClosed,\n PageOpened,\n PageUntracked,\n type RecordedEvent,\n SessionEnding,\n} from \"./BrowserEvent.ts\";\nimport { call, failWith, type Settings, undispatched } from \"./internal/page/context.ts\";\nimport { FailFast } from \"./internal/page/lane.ts\";\nimport * as Openings from \"./internal/page/openings.ts\";\nimport * as PageImpl from \"./internal/page/page.ts\";\nimport * as Url from \"./internal/page/url.ts\";\nimport * as BrowserClock from \"./internal/pictures/clock.ts\";\nimport * as Timeline from \"./internal/timeline/events.ts\";\nimport type * as Page from \"./Page.ts\";\n\n/** A script that documents run before their own, such as a consent-banner remover. */\nexport interface InitScript {\n /**\n * The documents that run it, by a pattern their address (`location.href`) matches; every\n * document and frame when left out. Under a `match`, the source runs as a block, so its own\n * top-level `let`, `const` and classes stay its own.\n */\n readonly match?: RegExp | undefined;\n readonly source: string;\n}\n\nexport interface Options {\n /**\n * Bound on each action; finite and positive. Defaults to 10 seconds. What a presenter's view\n * takes to show an action, such as its glides and typing at a person's pace, does not count\n * against it.\n */\n readonly actionTimeout?: Duration.Input | undefined;\n /** Bound on each navigation; finite and positive. Defaults to 30 seconds. */\n readonly navigationTimeout?: Duration.Input | undefined;\n /**\n * How long each page keeps screencast frames for `recentFrames`, measured back from the newest;\n * finite and positive. Defaults to 5 seconds, a moment's default window.\n */\n readonly frameHistory?: Duration.Input | undefined;\n /** Events retained for replay and `recentEvents`. A positive safe integer, defaulting to 4,096. */\n readonly eventHistory?: number | undefined;\n /** Allow, deny or hold each input or navigation before it reaches the page. Defaults to allow. */\n readonly guard?: Page.InputGuard | undefined;\n /** A separate bound for policy holds, outside action timeouts. Defaults to 5 minutes. */\n readonly policyTimeout?: Duration.Input | undefined;\n /** Scripts that new documents run before their own, each where its `match` allows. */\n readonly initScripts?: ReadonlyArray<InitScript> | undefined;\n /**\n * The most pages the browser keeps open, those a site opens included, which are never refused. At\n * it, `newPage` waits for one to close, within the action timeout, then fails `Limit`; under\n * `Page.failFast` it fails at once. A positive safe integer; no limit when left out.\n */\n readonly maxPages?: number | undefined;\n}\n\nexport interface EventOptions {\n /** Resume after this sequence; 0 replays from the beginning if it is still retained. */\n readonly after?: number | undefined;\n}\n\n/**\n * A connection to the browser apart from the one that drives its pages, for their screencasts,\n * as a provider that reaches the browser over a network supplies it: a frame and its\n * acknowledgement then never wait behind a large message, such as an upload or a read's answer,\n * on the connection that drives the page. It is read-only. A page's session on it sends the\n * capture's commands alone, and the page's own session keeps its focus emulation, which keeps a\n * tab behind painting.\n */\nexport interface CaptureSource {\n /**\n * A session on the page's target, for the scope. `event` gets the session's events in the order\n * the browser sent them, its target's detach among them, until the scope closes; `lost` gets\n * the connection's failure, once, if it fails first. Its calls never throw: a failure rejects.\n */\n readonly attach: (\n target: string,\n listener: {\n readonly event: (method: string, params: unknown) => void;\n readonly lost: (error: BrowserError) => void;\n },\n ) => Effect.Effect<\n (\n method:\n | \"Page.enable\"\n | \"Page.getFrameTree\"\n | \"Page.startScreencast\"\n | \"Page.screencastFrameAck\"\n | \"Page.stopScreencast\",\n params?: Record<string, unknown>,\n ) => Promise<unknown>,\n BrowserError,\n Scope.Scope\n >;\n}\n\nexport interface Service {\n /** The provider's session id, or a local id. */\n readonly id: string;\n readonly provider: string;\n /** When the provider ends the session on its own, as a hosted session's timeout does. */\n readonly expiresAt: DateTime.Utc | undefined;\n /** Host monotonic milliseconds on the clock shared by this browser’s events and frames. */\n readonly now: Effect.Effect<number>;\n /** The Playwright context, for anything this API does not cover. Never give it to a model. */\n readonly context: BrowserContext;\n /** Open pages in the order this browser began tracking them. */\n readonly pages: Effect.Effect<ReadonlyArray<Page.Page>>;\n /** The open page with this id, its CDP target id, as stored before a reconnect. */\n readonly page: (id: string) => Effect.Effect<Option.Option<Page.Page>>;\n /** The first open page, opening one when there is none. */\n readonly firstPage: Effect.Effect<Page.Page, BrowserError>;\n readonly newPage: (url?: string) => Effect.Effect<Page.Page, BrowserError>;\n /**\n * Completes once the browser is lost to its owner, with why: its connection dropped, its\n * provider ended its session, or its owner's scope released it.\n */\n readonly disconnected: Effect.Effect<DisconnectCause>;\n /** Live events, or replay after a cursor. A reader that falls behind fails with EventHistoryExpired. */\n readonly events: (options?: EventOptions) => Stream.Stream<RecordedEvent, BrowserError>;\n /** The latest `eventHistory` events, oldest first. */\n readonly recentEvents: Effect.Effect<ReadonlyArray<BrowserEvent>>;\n}\n\nexport class Browser extends Context.Service<Browser, Service>()(\"effect-browser/Browser\") {}\n\n/** The settings every page shares, and how many events the browser keeps, from its options. */\nconst settingsOf = Effect.fnUntraced(function* (options: Options) {\n const invalid = (detail: string) => undispatched(\"make\", new InvalidRequest({ detail }));\n\n // Every bound guards a lock or a held key, so each must be a real, finite deadline.\n const bound = (name: string, input: Duration.Input | undefined, fallback: Duration.Duration) => {\n const decoded = Duration.fromInput(input ?? fallback);\n\n return Option.isSome(decoded) &&\n Number.isFinite(Duration.toMillis(decoded.value)) &&\n Duration.isPositive(decoded.value)\n ? Effect.succeed(decoded.value)\n : Effect.fail(invalid(`${name} must be finite and greater than zero`));\n };\n\n const settings: Settings = {\n actionTimeout: yield* bound(\"actionTimeout\", options.actionTimeout, Duration.seconds(10)),\n navigationTimeout: yield* bound(\n \"navigationTimeout\",\n options.navigationTimeout,\n Duration.seconds(30),\n ),\n frameHistory: yield* bound(\"frameHistory\", options.frameHistory, Duration.seconds(5)),\n guard: options.guard,\n policyTimeout: yield* bound(\"policyTimeout\", options.policyTimeout, Duration.minutes(5)),\n };\n\n const eventHistory = options.eventHistory ?? 4096;\n const { maxPages } = options;\n\n if (!Number.isSafeInteger(eventHistory) || eventHistory < 1)\n return yield* invalid(\"eventHistory must be a positive safe integer\");\n if (maxPages !== undefined && (!Number.isSafeInteger(maxPages) || maxPages < 1))\n return yield* invalid(\"maxPages must be a positive safe integer\");\n\n return { settings, eventHistory, maxPages };\n});\n\n/**\n * A provider that ends a session at `expiresAt` by its own clock can cut the connection a little\n * before this host's clock gets there.\n */\nconst endMargin = Duration.seconds(5);\n\n/**\n * The browser's loss, once: its context closing from the other side, at or after the session's\n * end or before it, or `lose`, as the owner's scope releases it. Playwright leaves the calls in\n * flight on the library's own sessions unanswered when the connection drops, so `untilLost` fails\n * each with the browser, as a closed page's call fails.\n */\nconst watchLoss = Effect.fnUntraced(function* (\n context: BrowserContext,\n expiresAt: DateTime.Utc | undefined,\n clock: Clock.Clock,\n disconnected: (cause: DisconnectCause) => void,\n) {\n let lostBy: DisconnectCause | undefined;\n const lost = yield* Deferred.make<DisconnectCause>();\n const inFlight = new Set<(cause: Error) => void>();\n const gone = () => new Error(\"Target page, context or browser has been closed\");\n\n const lose = (cause: DisconnectCause) => {\n if (lostBy !== undefined) return;\n lostBy = cause;\n for (const reject of inFlight) reject(gone());\n disconnected(cause);\n Deferred.doneUnsafe(lost, Exit.succeed(cause));\n };\n\n const untilLost = <A>(reply: Promise<A>): Promise<A> => {\n if (lostBy !== undefined) {\n void reply.catch(() => undefined);\n\n return Promise.reject(gone());\n }\n\n return new Promise<A>((resolve, reject) => {\n inFlight.add(reject);\n void reply.then(resolve, reject).finally(() => inFlight.delete(reject));\n });\n };\n\n const ended = () =>\n expiresAt !== undefined &&\n clock.currentTimeMillisUnsafe() >=\n DateTime.toEpochMillis(expiresAt) - Duration.toMillis(endMargin);\n\n const onClose = () => lose(ended() ? \"session\" : \"connection\");\n\n context.on(\"close\", onClose);\n yield* Effect.addFinalizer(() => Effect.sync(() => context.off(\"close\", onClose)));\n if (context.browser()?.isConnected() === false) onClose();\n\n const native = <A>(operation: string, run: () => Promise<A>) =>\n call(operation, run, () => lostBy ?? \"page\");\n\n return { lostBy: () => lostBy, lost: Deferred.await(lost), lose, untilLost, native };\n});\n\n/**\n * What a page's own Playwright events publish, its close and crash aside, while its scope is\n * open. Dialogs are answered: alerts accepted, others dismissed. The page's own session tells its\n * documents' commits and loads.\n */\nconst listen = (\n playwright: PlaywrightPage,\n page: string,\n publish: (event: BrowserEvent) => number,\n now: () => number,\n on: { readonly close: () => void; readonly crash: () => void },\n) => {\n const dialog = (shown: Dialog) => {\n const kind = shown.type();\n const answer = kind === \"alert\" || kind === \"beforeunload\" ? \"accepted\" : \"dismissed\";\n const message = shown.message().slice(0, 500);\n\n publish(new DialogShown({ at: now(), page, kind, message, answer }));\n (answer === \"accepted\" ? shown.accept() : shown.dismiss()).catch(() => undefined);\n };\n\n return Effect.acquireRelease(\n Effect.sync(() => {\n playwright.on(\"close\", on.close);\n playwright.on(\"crash\", on.crash);\n playwright.on(\"dialog\", dialog);\n }),\n () =>\n Effect.sync(() => {\n playwright.off(\"close\", on.close);\n playwright.off(\"crash\", on.crash);\n playwright.off(\"dialog\", dialog);\n }),\n );\n};\n\n/**\n * Register each page the site opens, such as a popup, as Playwright reports it, for as long as the\n * scope is open. One that could not be tracked is published, unless it closed as it opened.\n */\nconst followOpened = Effect.fnUntraced(function* (\n context: BrowserContext,\n register: (playwright: PlaywrightPage) => Effect.Effect<Page.Page, BrowserError>,\n publish: (event: BrowserEvent) => number,\n now: () => number,\n registrations: Openings.Registrations,\n) {\n const opened = yield* Queue.unbounded<PlaywrightPage>();\n\n const onPage = (playwright: PlaywrightPage) => {\n registrations.set(playwright, Deferred.makeUnsafe<void, BrowserError>());\n Queue.offerUnsafe(opened, playwright);\n };\n\n const untracked = (playwright: PlaywrightPage) => (error: BrowserError) =>\n Effect.sync(() => {\n const url = Url.redact(playwright.url());\n\n if (!playwright.isClosed())\n publish(new PageUntracked({ at: now(), url, detail: error.message }));\n });\n\n context.on(\"page\", onPage);\n yield* Effect.addFinalizer(() => Effect.sync(() => context.off(\"page\", onPage)));\n yield* Queue.take(opened).pipe(\n Effect.flatMap((playwright) =>\n register(playwright).pipe(\n Effect.asVoid,\n Effect.onExit((exit) =>\n Effect.sync(() => {\n const done = registrations.get(playwright);\n\n if (done !== undefined) Deferred.doneUnsafe(done, exit);\n }),\n ),\n Effect.catch(untracked(playwright)),\n ),\n ),\n Effect.forever,\n Effect.forkScoped,\n );\n});\n\n/** Release something native, on the owner's clock, giving up after a second: cleanup only. */\nconst releaseNative = (clock: Clock.Clock) => (run: () => Promise<unknown>) =>\n Effect.tryPromise(run).pipe(\n Effect.interruptible,\n Effect.timeoutOrElse({ duration: Duration.seconds(1), orElse: () => Effect.void }),\n Effect.provideService(Clock.Clock, clock),\n Effect.ignore,\n );\n\n/** A page's own events among the browser's retained ones, and the openings of tabs it opened. */\nconst eventsOf = (recent: Effect.Effect<ReadonlyArray<RecordedEvent>>, page: string) =>\n Effect.map(recent, (records) =>\n records.flatMap(({ event }) =>\n (\"page\" in event && event.page === page) ||\n (event._tag === \"PageOpened\" && event.opener === page)\n ? [event]\n : [],\n ),\n );\n\n/** A script as its documents run it: everywhere, or as a block where its `match` allows. */\nconst scoped = ({ match, source }: InitScript) =>\n match === undefined ? source : `if (${String(match)}.test(location.href)) {\\n${source}\\n}`;\n\n/**\n * At most `maxPages` open pages, those a site opened included, which are never refused: an open\n * past it waits for one to close, within `wait` on the owner's clock, then fails `Limit`, or fails\n * at once under `FailFast`. An open counts until its page is tracked.\n */\nconst pageBudget = (\n maxPages: number | undefined,\n tracked: () => number,\n wait: Duration.Duration,\n clock: Clock.Clock,\n) => {\n let opening = 0;\n // Completed as a page closes or an open ends, so the opens waiting look again.\n let roomMade = Deferred.makeUnsafe<void>();\n\n const makeRoom = () => {\n Deferred.doneUnsafe(roomMade, Exit.void);\n roomMade = Deferred.makeUnsafe<void>();\n };\n\n const full = (limit: number) => tracked() + opening >= limit;\n\n const room = (limit: number) =>\n Effect.gen(function* () {\n const refused = undispatched(\"newPage\", new Limit({ maxPages: limit }));\n\n if ((yield* FailFast) && full(limit)) return yield* refused;\n yield* Effect.gen(function* () {\n while (full(limit)) yield* Deferred.await(roomMade);\n opening += 1;\n }).pipe(\n Effect.timeoutOrElse({ duration: wait, orElse: () => Effect.fail(refused) }),\n Effect.provideService(Clock.Clock, clock),\n );\n });\n\n const open = <A, E, R>(opened: Effect.Effect<A, E, R>) =>\n maxPages === undefined\n ? opened\n : Effect.uninterruptibleMask((restore) =>\n restore(room(maxPages)).pipe(\n Effect.andThen(\n restore(opened).pipe(\n Effect.ensuring(\n Effect.sync(() => {\n opening -= 1;\n makeRoom();\n }),\n ),\n ),\n ),\n ),\n );\n\n return { makeRoom, open };\n};\n\n/** A call sent now and awaited later, by whatever needs its answer. */\nconst sentNow = <A>(sent: Promise<A>) => {\n void sent.catch(() => undefined);\n\n return sent;\n};\n\n/**\n * Build the service over a context the provider owns. The provider closes the context; this only\n * tracks its pages and events, for as long as the surrounding scope is open. Each page's protocol\n * session, capture and listeners end when that page closes or when the scope does, so a closed\n * tab retains nothing and the context keeps none of them afterwards.\n */\nexport const make = Effect.fn(\"Browser.make\")(function* (\n context: BrowserContext,\n info: {\n readonly id: string;\n readonly provider: string;\n readonly expiresAt?: DateTime.Utc | undefined;\n /** Where pages' screencasts run, if not on each page's own session. */\n readonly capture?: CaptureSource | undefined;\n },\n options: Options = {},\n) {\n const clock = yield* Clock.Clock;\n const now = () => Number(clock.monotonicTimeNanosUnsafe()) / 1e6;\n const { settings, eventHistory, maxPages } = yield* settingsOf(options);\n // Measured on first need: the first capture of any page measures it, and input never waits.\n const mapping = BrowserClock.mapping(now);\n\n const timeline = Timeline.make(eventHistory);\n\n yield* Effect.addFinalizer(() => timeline.close);\n const publish = timeline.publish;\n\n if (info.expiresAt !== undefined)\n publish(new SessionEnding({ at: now(), expiresAt: info.expiresAt }));\n\n const { lostBy, lost, lose, untilLost, native } = yield* watchLoss(\n context,\n info.expiresAt,\n clock,\n (cause) => publish(new Disconnected({ at: now(), cause })),\n );\n\n const registry = new Map<PlaywrightPage, Page.Page>();\n const registrations: Openings.Registrations = new WeakMap();\n const registering = yield* Semaphore.make(1);\n // The pages' scopes close after the browser is marked released, so what fails as they close\n // says why.\n const pagesScope = yield* Scope.fork(yield* Scope.Scope);\n\n const release = releaseNative(clock);\n const budget = pageBudget(maxPages, () => registry.size, settings.actionTimeout, clock);\n\n // Each tab's scope closes with the tab or the browser. A dropped connection closes every page,\n // then the context, and `Disconnected` stands for all of them: the queue hands a close to its\n // fiber in a later turn, once Playwright has reported the context's.\n const closing = yield* Queue.unbounded<{\n readonly scope: Scope.Closeable;\n readonly page: string;\n readonly cause: PageClosed[\"cause\"];\n }>();\n\n yield* Queue.take(closing).pipe(\n Effect.tap(({ page, cause }) =>\n Effect.sync(() => {\n if (lostBy() === undefined) publish(new PageClosed({ at: now(), page, cause }));\n }),\n ),\n Effect.flatMap(({ scope }) => Scope.close(scope, Exit.void)),\n Effect.forever,\n Effect.forkScoped,\n );\n\n const register = (playwright: PlaywrightPage) =>\n registering.withPermits(1)(\n Effect.gen(function* () {\n const known = registry.get(playwright);\n\n if (known !== undefined) return known;\n if (playwright.isClosed())\n return yield* failWith(\"newPage\", new Failed({ detail: \"the page closed as it opened\" }));\n const scope = yield* Scope.fork(pagesScope);\n\n return yield* Effect.gen(function* () {\n let crashed = false;\n const closedBy = () => lostBy() ?? (crashed ? \"crashed\" : \"page\");\n const cdp = yield* native(\"newPage\", () => context.newCDPSession(playwright));\n\n yield* Effect.addFinalizer(() => release(() => cdp.detach()));\n // The page's name, its target id, costs one round trip, which the calls that keep it\n // painting behind other tabs and report its documents share. A renderer busy with its\n // first script answers those two late, so what needs them waits, and registering does not.\n const send: typeof cdp.send = (method, params) => untilLost(cdp.send(method, params));\n const focusing = sentNow(send(\"Emulation.setFocusEmulationEnabled\", { enabled: true }));\n const paging = sentNow(send(\"Page.enable\"));\n const { targetInfo } = yield* native(\"newPage\", () => send(\"Target.getTargetInfo\"));\n const id = targetInfo.targetId;\n\n const page = yield* PageImpl.make({\n id,\n session: info.id,\n url: targetInfo.url,\n playwright,\n cdp,\n untilLost,\n settings,\n clock,\n mapping,\n publish,\n recentEvents: eventsOf(timeline.recent, id),\n openings: yield* Openings.make(playwright, cdp, registrations, closedBy),\n focused: call(\"focus\", () => focusing, closedBy).pipe(Effect.asVoid),\n paging: (operation) => call(operation, () => paging, closedBy).pipe(Effect.asVoid),\n closedBy,\n capture: info.capture,\n });\n\n const close = () => {\n if (registry.get(playwright) !== page) return;\n registry.delete(playwright);\n budget.makeRoom();\n Queue.offerUnsafe(closing, { scope, page: id, cause: crashed ? \"crashed\" : \"page\" });\n };\n\n // Playwright drives a crashed page no more and its calls never return, so it is closed:\n // they fail at once, `Closed` because it crashed.\n const crash = () => {\n crashed = true;\n void playwright.close().catch(() => undefined);\n };\n\n registry.set(playwright, page);\n publish(\n new PageOpened({\n at: now(),\n page: id,\n url: Url.redact(targetInfo.url),\n opener: targetInfo.openerId,\n }),\n );\n yield* listen(playwright, id, publish, now, { close, crash });\n if (playwright.isClosed()) close();\n\n return page;\n }).pipe(\n Scope.provide(scope),\n Effect.onError(() => Scope.close(scope, Exit.void)),\n );\n }),\n );\n\n // Playwright registers its init scripts as it sets up each page, before a popup's first document\n // runs, and they cost no call per document.\n for (const script of options.initScripts ?? [])\n yield* native(\"initScripts\", () => context.addInitScript({ content: scoped(script) }));\n yield* followOpened(context, register, publish, now, registrations);\n for (const existing of context.pages()) yield* register(existing);\n\n const pages = Effect.sync(() => [...registry.values()]);\n\n const newPage = Effect.fn(\"Browser.newPage\")(function* (url?: string) {\n const page = yield* budget.open(\n native(\"newPage\", () => context.newPage()).pipe(\n Effect.flatMap((playwright) =>\n register(playwright).pipe(Effect.onError(() => release(() => playwright.close()))),\n ),\n ),\n );\n\n // A rejected or interrupted navigation must not leave the newly allocated blank tab behind.\n if (url !== undefined)\n yield* page.goto(url).pipe(Effect.onError(() => page.close.pipe(Effect.ignore)));\n\n return page;\n });\n\n // Added last, so it runs first as the owner's scope closes.\n yield* Effect.addFinalizer(() => Effect.sync(() => lose(\"released\")));\n\n const service: Service = {\n id: info.id,\n provider: info.provider,\n expiresAt: info.expiresAt,\n now: Effect.sync(now),\n context,\n pages,\n page: (id) =>\n Effect.map(pages, (open) => Option.fromNullishOr(open.find((page) => page.id === id))),\n firstPage: pages.pipe(\n Effect.map((open) => Option.fromNullishOr(open[0])),\n Effect.flatMap(Option.match({ onNone: () => newPage(), onSome: Effect.succeed })),\n ),\n newPage,\n disconnected: lost,\n events: (eventOptions = {}) => timeline.stream(eventOptions.after),\n recentEvents: timeline.recent.pipe(\n Effect.map((records) => records.map((record) => record.event)),\n ),\n };\n\n return Browser.of(service);\n});\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { t as BrowserError } from "./BrowserError-DXXIA6Rk.mjs";
2
- import { c as DisconnectCause, i as BrowserEvent, v as RecordedEvent } from "./BrowserEvent-DzdNdvoh.mjs";
3
- import { c as InputGuard, d as Page_d_exports, u as Page$1 } from "./Page-DYTdVhYa.mjs";
2
+ import { c as DisconnectCause, i as BrowserEvent, v as RecordedEvent } from "./BrowserEvent-BRu2juEz.mjs";
3
+ import { c as InputGuard, d as Page_d_exports, u as Page$1 } from "./Page-C30aG2RQ.mjs";
4
4
  import { Context, DateTime, Duration, Effect, Option, Scope, Stream } from "effect";
5
5
  import { BrowserContext } from "playwright-core";
6
6
  declare namespace Browser_d_exports {
package/dist/Browser.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { r as make, t as Browser } from "./Browser-B5AV7zPS.mjs";
1
+ import { r as make, t as Browser } from "./Browser-CNwK0r0q.mjs";
2
2
  export { Browser, make };
@@ -134,6 +134,8 @@ declare const Action_base: Schema.Class<Action, Schema.TaggedStruct<"Action", {
134
134
  readonly startedAt: Schema.Finite;
135
135
  readonly page: Schema.String;
136
136
  readonly name: Schema.String;
137
+ /** The address when the action ended; absent in events recorded by older releases. */
138
+ readonly url: Schema.optional<Schema.String>;
137
139
  readonly correlation: Schema.optional<Schema.String>;
138
140
  readonly target: Schema.optional<Schema.String>;
139
141
  readonly options: Schema.optional<Schema.Struct<{
@@ -274,4 +276,4 @@ declare const RecordedEvent_base: Schema.Class<RecordedEvent, Schema.Struct<{
274
276
  declare class RecordedEvent extends RecordedEvent_base {}
275
277
  //#endregion
276
278
  export { TrackEvent as C, WheelScrolled as E, TextInserted as S, TrackPlanned as T, PointerReleased as _, BrowserEvent_d_exports as a, Subject as b, DisconnectCause as c, Navigated as d, PageClosed as f, PointerPressed as g, PageUntracked as h, BrowserEvent as i, Disconnected as l, PageOpened as m, ActionOptions as n, CursorChanged as o, PageLoaded as p, Box as r, DialogShown as s, Action as t, KeyChanged as u, RecordedEvent as v, TrackPerformed as w, SubjectContext as x, SessionEnding as y };
277
- //# sourceMappingURL=BrowserEvent-DzdNdvoh.d.mts.map
279
+ //# sourceMappingURL=BrowserEvent-BRu2juEz.d.mts.map
@@ -1,2 +1,2 @@
1
- import { C as TrackEvent, E as WheelScrolled, S as TextInserted, T as TrackPlanned, _ as PointerReleased, b as Subject, c as DisconnectCause, d as Navigated, f as PageClosed, g as PointerPressed, h as PageUntracked, i as BrowserEvent, l as Disconnected, m as PageOpened, n as ActionOptions, o as CursorChanged, p as PageLoaded, r as Box, s as DialogShown, t as Action, u as KeyChanged, v as RecordedEvent, w as TrackPerformed, x as SubjectContext, y as SessionEnding } from "./BrowserEvent-DzdNdvoh.mjs";
1
+ import { C as TrackEvent, E as WheelScrolled, S as TextInserted, T as TrackPlanned, _ as PointerReleased, b as Subject, c as DisconnectCause, d as Navigated, f as PageClosed, g as PointerPressed, h as PageUntracked, i as BrowserEvent, l as Disconnected, m as PageOpened, n as ActionOptions, o as CursorChanged, p as PageLoaded, r as Box, s as DialogShown, t as Action, u as KeyChanged, v as RecordedEvent, w as TrackPerformed, x as SubjectContext, y as SessionEnding } from "./BrowserEvent-BRu2juEz.mjs";
2
2
  export { Action, ActionOptions, Box, BrowserEvent, CursorChanged, DialogShown, DisconnectCause, Disconnected, KeyChanged, Navigated, PageClosed, PageLoaded, PageOpened, PageUntracked, PointerPressed, PointerReleased, RecordedEvent, SessionEnding, Subject, SubjectContext, TextInserted, TrackEvent, TrackPerformed, TrackPlanned, WheelScrolled };
@@ -173,6 +173,8 @@ var Action = class extends Schema.TaggedClass()("Action", {
173
173
  startedAt: Schema.Finite,
174
174
  page: Schema.String,
175
175
  name: Schema.String,
176
+ /** The address when the action ended; absent in events recorded by older releases. */
177
+ url: Schema.optional(Schema.String),
176
178
  correlation: Schema.optional(Schema.String),
177
179
  target: Schema.optional(Schema.String),
178
180
  options: Schema.optional(ActionOptions),
@@ -1 +1 @@
1
- {"version":3,"file":"BrowserEvent.mjs","names":["Motion.Point","Motion.Plan"],"sources":["../src/BrowserEvent.ts"],"sourcesContent":["/**\n * What happened in a browser, in order: pages and their documents, actions, pointer motion, and\n * the browser's own end.\n *\n * Every event carries `at`, host monotonic milliseconds from the owning browser’s Effect `Clock`.\n * This clock also stamps screencast frames’ `receivedAt` and moments, so wall-clock corrections\n * cannot disturb their order. Compare stamps only within the same browser clock, not across hosts.\n * A page is named by its CDP target id, which stays the same across reconnects, and every URL is\n * reported without its userinfo or known secret parameters.\n *\n * @since 0.3.0\n */\nimport { Schema } from \"effect\";\n\nimport * as Motion from \"./Motion.ts\";\n\n/** A page opened, and the page that opened it, as a link or `window.open` does, if one did. */\nexport class PageOpened extends Schema.TaggedClass<PageOpened>()(\"PageOpened\", {\n at: Schema.Finite,\n page: Schema.String,\n url: Schema.String,\n opener: Schema.optional(Schema.String),\n}) {}\n\n/**\n * The page closed (`page`), or crashed and was closed (`crashed`). A page lost with its browser\n * has no event of its own: `Disconnected` stands for all of them.\n */\nexport class PageClosed extends Schema.TaggedClass<PageClosed>()(\"PageClosed\", {\n at: Schema.Finite,\n page: Schema.String,\n cause: Schema.Literals([\"page\", \"crashed\"]),\n}) {}\n\n/**\n * A tab the site opened that the library could not track, as its registration failed with\n * `detail`. A tab that closed as it opened has no event.\n */\nexport class PageUntracked extends Schema.TaggedClass<PageUntracked>()(\"PageUntracked\", {\n at: Schema.Finite,\n url: Schema.String,\n detail: Schema.String,\n}) {}\n\n/**\n * The page's main frame moved to `url`: into a new document, or within the current one\n * (`sameDocument`), as `pushState` and fragment links do. Frames carry the document they followed.\n */\nexport class Navigated extends Schema.TaggedClass<Navigated>()(\"Navigated\", {\n at: Schema.Finite,\n page: Schema.String,\n url: Schema.String,\n /**\n * The page's documents counted from 0, the one it had when this browser began tracking it, one\n * more for each new document. The count belongs to the page within one `Browser` and starts at\n * 0 again on a new connection, so compare it only with the same page's in the same browser.\n */\n document: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n sameDocument: Schema.Boolean,\n}) {}\n\n/** The page's document finished parsing (`domcontentloaded`) or loading (`load`). */\nexport class PageLoaded extends Schema.TaggedClass<PageLoaded>()(\"PageLoaded\", {\n at: Schema.Finite,\n page: Schema.String,\n state: Schema.Literals([\"domcontentloaded\", \"load\"]),\n}) {}\n\n/**\n * Why a browser was lost to its owner: its connection dropped (`connection`), its provider ended\n * its session, at or after the session's `expiresAt` (`session`), or its owner released it.\n */\nexport const DisconnectCause = Schema.Literals([\"connection\", \"session\", \"released\"]);\n\nexport type DisconnectCause = typeof DisconnectCause.Type;\n\n/** The browser was lost to its owner, with every page in it. It happens once. */\nexport class Disconnected extends Schema.TaggedClass<Disconnected>()(\"Disconnected\", {\n at: Schema.Finite,\n cause: DisconnectCause,\n}) {}\n\n/** The provider ends this browser's session at `expiresAt`, a wall-clock instant. */\nexport class SessionEnding extends Schema.TaggedClass<SessionEnding>()(\"SessionEnding\", {\n at: Schema.Finite,\n expiresAt: Schema.DateTimeUtc,\n}) {}\n\n/**\n * The words around a subject that say which one it is, each bound to it in the page rather than\n * read off nearby text later. In a table, `row` is the row's header or first cell with text and\n * `column` the header over it; elsewhere, `label` is the words just before it in its row, item,\n * group or block, at most 40 characters. `heading` is the nearest heading above it, left out for\n * what is pinned to the viewport. Row, column and heading are at most 60 characters.\n */\nexport const SubjectContext = Schema.Struct({\n row: Schema.optional(Schema.String),\n column: Schema.optional(Schema.String),\n label: Schema.optional(Schema.String),\n heading: Schema.optional(Schema.String),\n});\n\nexport type SubjectContext = typeof SubjectContext.Type;\n\n/**\n * What an input acted on, or what `Page.find` found, as the page named it then: its role (null\n * when it has none), its accessible name (empty when it has none), its lowercase tag and its\n * context. For a point, it is the control under the point, or else the element painted there.\n * Unlike a ref, it keeps its meaning after the page changes.\n */\nexport class Subject extends Schema.Class<Subject>(\"effect-browser/Subject\")({\n role: Schema.NullOr(Schema.String),\n name: Schema.String,\n tag: Schema.String,\n context: SubjectContext,\n}) {}\n\nconst Button = Schema.Literals([\"left\", \"right\", \"middle\"]);\n\n/** An element's box in viewport CSS pixels; it may lie partly or wholly outside the viewport. */\nexport const Box = Schema.Struct({\n x: Schema.Finite,\n y: Schema.Finite,\n width: Schema.Finite,\n height: Schema.Finite,\n});\n\nexport type Box = typeof Box.Type;\n\n/**\n * What else an action was asked, where it changes what the action does: a click's button, count\n * and hold, how `type` enters its text, how often and how long `press` holds its keys, how far\n * `scroll` moves, and the options `select` chose. Only a completed action records them.\n */\nexport const ActionOptions = Schema.Struct({\n button: Schema.optional(Button),\n clickCount: Schema.optional(Schema.Finite),\n holdMillis: Schema.optional(Schema.Finite),\n replace: Schema.optional(Schema.Boolean),\n submit: Schema.optional(Schema.Boolean),\n times: Schema.optional(Schema.Finite),\n dx: Schema.optional(Schema.Finite),\n dy: Schema.optional(Schema.Finite),\n values: Schema.optional(Schema.Array(Schema.String)),\n});\n\nexport type ActionOptions = typeof ActionOptions.Type;\n\n/**\n * One page operation ended, including one its caller interrupted (`error: \"interrupted\"`).\n * `target` is what the caller asked for: a ref, a point, a URL or keys, and `options` the rest.\n * `subject` is what an element or point action found there, and `to` where a drag ended; an\n * action that failed before finding its target has neither. Point actions carry the viewport\n * point they used. `correlation` is the id its caller gave it with `Page.correlate`, such as a\n * model's tool call id.\n */\nexport class Action extends Schema.TaggedClass<Action>()(\"Action\", {\n at: Schema.Finite,\n startedAt: Schema.Finite,\n page: Schema.String,\n name: Schema.String,\n correlation: Schema.optional(Schema.String),\n target: Schema.optional(Schema.String),\n options: Schema.optional(ActionOptions),\n subject: Schema.optional(Subject),\n to: Schema.optional(Subject),\n /** For an action at a point, the box of what it found there. */\n box: Schema.optional(Box),\n text: Schema.optional(Schema.String),\n x: Schema.optional(Schema.Finite),\n y: Schema.optional(Schema.Finite),\n ok: Schema.Boolean,\n dispatched: Schema.Boolean,\n error: Schema.optional(Schema.String),\n}) {}\n\nconst Sequence = Schema.Int.check(Schema.isGreaterThan(0));\n\n/** One whole glide, published before its first input. Offsets use the host monotonic clock. */\nexport class TrackPlanned extends Schema.TaggedClass<TrackPlanned>()(\"TrackPlanned\", {\n at: Schema.Finite,\n page: Schema.String,\n from: Motion.Point,\n samples: Motion.Plan,\n}) {}\n\n/**\n * The submitted prefix of a glide. `plan` is its TrackPlanned envelope sequence; `dispatched`\n * counts samples. `complete` means every sample was submitted, not acknowledged by the browser.\n * The terminal point clips a canceled plan so a compositor never draws its unrealized future.\n */\nexport class TrackPerformed extends Schema.TaggedClass<TrackPerformed>()(\"TrackPerformed\", {\n at: Schema.Finite,\n page: Schema.String,\n plan: Sequence,\n dispatched: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n x: Schema.Finite,\n y: Schema.Finite,\n complete: Schema.Boolean,\n}) {}\n\nexport class PointerPressed extends Schema.TaggedClass<PointerPressed>()(\"PointerPressed\", {\n at: Schema.Finite,\n page: Schema.String,\n x: Schema.Finite,\n y: Schema.Finite,\n button: Button,\n clickCount: Schema.Int.check(Schema.isGreaterThan(0)),\n}) {}\n\nexport class PointerReleased extends Schema.TaggedClass<PointerReleased>()(\"PointerReleased\", {\n at: Schema.Finite,\n page: Schema.String,\n x: Schema.Finite,\n y: Schema.Finite,\n button: Button,\n clickCount: Schema.Int.check(Schema.isGreaterThan(0)),\n}) {}\n\nexport class WheelScrolled extends Schema.TaggedClass<WheelScrolled>()(\"WheelScrolled\", {\n at: Schema.Finite,\n page: Schema.String,\n x: Schema.Finite,\n y: Schema.Finite,\n dx: Schema.Finite,\n dy: Schema.Finite,\n}) {}\n\nexport class KeyChanged extends Schema.TaggedClass<KeyChanged>()(\"KeyChanged\", {\n at: Schema.Finite,\n page: Schema.String,\n key: Schema.String,\n phase: Schema.Literals([\"down\", \"up\"]),\n}) {}\n\n/** Literal text insertion has no corresponding key events, including Unicode and newlines. */\nexport class TextInserted extends Schema.TaggedClass<TextInserted>()(\"TextInserted\", {\n at: Schema.Finite,\n page: Schema.String,\n text: Schema.String,\n}) {}\n\n/** The target's CSS cursor, obtained during target resolution without another browser call. */\nexport class CursorChanged extends Schema.TaggedClass<CursorChanged>()(\"CursorChanged\", {\n at: Schema.Finite,\n page: Schema.String,\n cursor: Schema.String,\n}) {}\n\nexport const TrackEvent = Schema.Union([\n TrackPlanned,\n TrackPerformed,\n PointerPressed,\n PointerReleased,\n WheelScrolled,\n KeyChanged,\n TextInserted,\n CursorChanged,\n]);\n\nexport type TrackEvent = typeof TrackEvent.Type;\n\n/**\n * A JavaScript dialog appeared and was answered: an alert or a leave-page prompt accepted, a\n * confirm or a prompt dismissed, as if its Cancel were pressed.\n */\nexport class DialogShown extends Schema.TaggedClass<DialogShown>()(\"DialogShown\", {\n at: Schema.Finite,\n page: Schema.String,\n kind: Schema.String,\n message: Schema.String,\n answer: Schema.Literals([\"accepted\", \"dismissed\"]),\n}) {}\n\nexport const BrowserEvent = Schema.Union([\n PageOpened,\n PageClosed,\n PageUntracked,\n Navigated,\n PageLoaded,\n Action,\n ...TrackEvent.members,\n DialogShown,\n Disconnected,\n SessionEnding,\n]);\n\nexport type BrowserEvent = typeof BrowserEvent.Type;\n\n/** A position in the browser's one replayable event history. Sequences begin at one. */\nexport class RecordedEvent extends Schema.Class<RecordedEvent>(\"effect-browser/RecordedEvent\")({\n sequence: Sequence,\n event: BrowserEvent,\n}) {}\n"],"mappings":"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"}
1
+ {"version":3,"file":"BrowserEvent.mjs","names":["Motion.Point","Motion.Plan"],"sources":["../src/BrowserEvent.ts"],"sourcesContent":["/**\n * What happened in a browser, in order: pages and their documents, actions, pointer motion, and\n * the browser's own end.\n *\n * Every event carries `at`, host monotonic milliseconds from the owning browser’s Effect `Clock`.\n * This clock also stamps screencast frames’ `receivedAt` and moments, so wall-clock corrections\n * cannot disturb their order. Compare stamps only within the same browser clock, not across hosts.\n * A page is named by its CDP target id, which stays the same across reconnects, and every URL is\n * reported without its userinfo or known secret parameters.\n *\n * @since 0.3.0\n */\nimport { Schema } from \"effect\";\n\nimport * as Motion from \"./Motion.ts\";\n\n/** A page opened, and the page that opened it, as a link or `window.open` does, if one did. */\nexport class PageOpened extends Schema.TaggedClass<PageOpened>()(\"PageOpened\", {\n at: Schema.Finite,\n page: Schema.String,\n url: Schema.String,\n opener: Schema.optional(Schema.String),\n}) {}\n\n/**\n * The page closed (`page`), or crashed and was closed (`crashed`). A page lost with its browser\n * has no event of its own: `Disconnected` stands for all of them.\n */\nexport class PageClosed extends Schema.TaggedClass<PageClosed>()(\"PageClosed\", {\n at: Schema.Finite,\n page: Schema.String,\n cause: Schema.Literals([\"page\", \"crashed\"]),\n}) {}\n\n/**\n * A tab the site opened that the library could not track, as its registration failed with\n * `detail`. A tab that closed as it opened has no event.\n */\nexport class PageUntracked extends Schema.TaggedClass<PageUntracked>()(\"PageUntracked\", {\n at: Schema.Finite,\n url: Schema.String,\n detail: Schema.String,\n}) {}\n\n/**\n * The page's main frame moved to `url`: into a new document, or within the current one\n * (`sameDocument`), as `pushState` and fragment links do. Frames carry the document they followed.\n */\nexport class Navigated extends Schema.TaggedClass<Navigated>()(\"Navigated\", {\n at: Schema.Finite,\n page: Schema.String,\n url: Schema.String,\n /**\n * The page's documents counted from 0, the one it had when this browser began tracking it, one\n * more for each new document. The count belongs to the page within one `Browser` and starts at\n * 0 again on a new connection, so compare it only with the same page's in the same browser.\n */\n document: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n sameDocument: Schema.Boolean,\n}) {}\n\n/** The page's document finished parsing (`domcontentloaded`) or loading (`load`). */\nexport class PageLoaded extends Schema.TaggedClass<PageLoaded>()(\"PageLoaded\", {\n at: Schema.Finite,\n page: Schema.String,\n state: Schema.Literals([\"domcontentloaded\", \"load\"]),\n}) {}\n\n/**\n * Why a browser was lost to its owner: its connection dropped (`connection`), its provider ended\n * its session, at or after the session's `expiresAt` (`session`), or its owner released it.\n */\nexport const DisconnectCause = Schema.Literals([\"connection\", \"session\", \"released\"]);\n\nexport type DisconnectCause = typeof DisconnectCause.Type;\n\n/** The browser was lost to its owner, with every page in it. It happens once. */\nexport class Disconnected extends Schema.TaggedClass<Disconnected>()(\"Disconnected\", {\n at: Schema.Finite,\n cause: DisconnectCause,\n}) {}\n\n/** The provider ends this browser's session at `expiresAt`, a wall-clock instant. */\nexport class SessionEnding extends Schema.TaggedClass<SessionEnding>()(\"SessionEnding\", {\n at: Schema.Finite,\n expiresAt: Schema.DateTimeUtc,\n}) {}\n\n/**\n * The words around a subject that say which one it is, each bound to it in the page rather than\n * read off nearby text later. In a table, `row` is the row's header or first cell with text and\n * `column` the header over it; elsewhere, `label` is the words just before it in its row, item,\n * group or block, at most 40 characters. `heading` is the nearest heading above it, left out for\n * what is pinned to the viewport. Row, column and heading are at most 60 characters.\n */\nexport const SubjectContext = Schema.Struct({\n row: Schema.optional(Schema.String),\n column: Schema.optional(Schema.String),\n label: Schema.optional(Schema.String),\n heading: Schema.optional(Schema.String),\n});\n\nexport type SubjectContext = typeof SubjectContext.Type;\n\n/**\n * What an input acted on, or what `Page.find` found, as the page named it then: its role (null\n * when it has none), its accessible name (empty when it has none), its lowercase tag and its\n * context. For a point, it is the control under the point, or else the element painted there.\n * Unlike a ref, it keeps its meaning after the page changes.\n */\nexport class Subject extends Schema.Class<Subject>(\"effect-browser/Subject\")({\n role: Schema.NullOr(Schema.String),\n name: Schema.String,\n tag: Schema.String,\n context: SubjectContext,\n}) {}\n\nconst Button = Schema.Literals([\"left\", \"right\", \"middle\"]);\n\n/** An element's box in viewport CSS pixels; it may lie partly or wholly outside the viewport. */\nexport const Box = Schema.Struct({\n x: Schema.Finite,\n y: Schema.Finite,\n width: Schema.Finite,\n height: Schema.Finite,\n});\n\nexport type Box = typeof Box.Type;\n\n/**\n * What else an action was asked, where it changes what the action does: a click's button, count\n * and hold, how `type` enters its text, how often and how long `press` holds its keys, how far\n * `scroll` moves, and the options `select` chose. Only a completed action records them.\n */\nexport const ActionOptions = Schema.Struct({\n button: Schema.optional(Button),\n clickCount: Schema.optional(Schema.Finite),\n holdMillis: Schema.optional(Schema.Finite),\n replace: Schema.optional(Schema.Boolean),\n submit: Schema.optional(Schema.Boolean),\n times: Schema.optional(Schema.Finite),\n dx: Schema.optional(Schema.Finite),\n dy: Schema.optional(Schema.Finite),\n values: Schema.optional(Schema.Array(Schema.String)),\n});\n\nexport type ActionOptions = typeof ActionOptions.Type;\n\n/**\n * One page operation ended, including one its caller interrupted (`error: \"interrupted\"`).\n * `target` is what the caller asked for: a ref, a point, a URL or keys, and `options` the rest.\n * `subject` is what an element or point action found there, and `to` where a drag ended; an\n * action that failed before finding its target has neither. Point actions carry the viewport\n * point they used. `correlation` is the id its caller gave it with `Page.correlate`, such as a\n * model's tool call id.\n */\nexport class Action extends Schema.TaggedClass<Action>()(\"Action\", {\n at: Schema.Finite,\n startedAt: Schema.Finite,\n page: Schema.String,\n name: Schema.String,\n /** The address when the action ended; absent in events recorded by older releases. */\n url: Schema.optional(Schema.String),\n correlation: Schema.optional(Schema.String),\n target: Schema.optional(Schema.String),\n options: Schema.optional(ActionOptions),\n subject: Schema.optional(Subject),\n to: Schema.optional(Subject),\n /** For an action at a point, the box of what it found there. */\n box: Schema.optional(Box),\n text: Schema.optional(Schema.String),\n x: Schema.optional(Schema.Finite),\n y: Schema.optional(Schema.Finite),\n ok: Schema.Boolean,\n dispatched: Schema.Boolean,\n error: Schema.optional(Schema.String),\n}) {}\n\nconst Sequence = Schema.Int.check(Schema.isGreaterThan(0));\n\n/** One whole glide, published before its first input. Offsets use the host monotonic clock. */\nexport class TrackPlanned extends Schema.TaggedClass<TrackPlanned>()(\"TrackPlanned\", {\n at: Schema.Finite,\n page: Schema.String,\n from: Motion.Point,\n samples: Motion.Plan,\n}) {}\n\n/**\n * The submitted prefix of a glide. `plan` is its TrackPlanned envelope sequence; `dispatched`\n * counts samples. `complete` means every sample was submitted, not acknowledged by the browser.\n * The terminal point clips a canceled plan so a compositor never draws its unrealized future.\n */\nexport class TrackPerformed extends Schema.TaggedClass<TrackPerformed>()(\"TrackPerformed\", {\n at: Schema.Finite,\n page: Schema.String,\n plan: Sequence,\n dispatched: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n x: Schema.Finite,\n y: Schema.Finite,\n complete: Schema.Boolean,\n}) {}\n\nexport class PointerPressed extends Schema.TaggedClass<PointerPressed>()(\"PointerPressed\", {\n at: Schema.Finite,\n page: Schema.String,\n x: Schema.Finite,\n y: Schema.Finite,\n button: Button,\n clickCount: Schema.Int.check(Schema.isGreaterThan(0)),\n}) {}\n\nexport class PointerReleased extends Schema.TaggedClass<PointerReleased>()(\"PointerReleased\", {\n at: Schema.Finite,\n page: Schema.String,\n x: Schema.Finite,\n y: Schema.Finite,\n button: Button,\n clickCount: Schema.Int.check(Schema.isGreaterThan(0)),\n}) {}\n\nexport class WheelScrolled extends Schema.TaggedClass<WheelScrolled>()(\"WheelScrolled\", {\n at: Schema.Finite,\n page: Schema.String,\n x: Schema.Finite,\n y: Schema.Finite,\n dx: Schema.Finite,\n dy: Schema.Finite,\n}) {}\n\nexport class KeyChanged extends Schema.TaggedClass<KeyChanged>()(\"KeyChanged\", {\n at: Schema.Finite,\n page: Schema.String,\n key: Schema.String,\n phase: Schema.Literals([\"down\", \"up\"]),\n}) {}\n\n/** Literal text insertion has no corresponding key events, including Unicode and newlines. */\nexport class TextInserted extends Schema.TaggedClass<TextInserted>()(\"TextInserted\", {\n at: Schema.Finite,\n page: Schema.String,\n text: Schema.String,\n}) {}\n\n/** The target's CSS cursor, obtained during target resolution without another browser call. */\nexport class CursorChanged extends Schema.TaggedClass<CursorChanged>()(\"CursorChanged\", {\n at: Schema.Finite,\n page: Schema.String,\n cursor: Schema.String,\n}) {}\n\nexport const TrackEvent = Schema.Union([\n TrackPlanned,\n TrackPerformed,\n PointerPressed,\n PointerReleased,\n WheelScrolled,\n KeyChanged,\n TextInserted,\n CursorChanged,\n]);\n\nexport type TrackEvent = typeof TrackEvent.Type;\n\n/**\n * A JavaScript dialog appeared and was answered: an alert or a leave-page prompt accepted, a\n * confirm or a prompt dismissed, as if its Cancel were pressed.\n */\nexport class DialogShown extends Schema.TaggedClass<DialogShown>()(\"DialogShown\", {\n at: Schema.Finite,\n page: Schema.String,\n kind: Schema.String,\n message: Schema.String,\n answer: Schema.Literals([\"accepted\", \"dismissed\"]),\n}) {}\n\nexport const BrowserEvent = Schema.Union([\n PageOpened,\n PageClosed,\n PageUntracked,\n Navigated,\n PageLoaded,\n Action,\n ...TrackEvent.members,\n DialogShown,\n Disconnected,\n SessionEnding,\n]);\n\nexport type BrowserEvent = typeof BrowserEvent.Type;\n\n/** A position in the browser's one replayable event history. Sequences begin at one. */\nexport class RecordedEvent extends Schema.Class<RecordedEvent>(\"effect-browser/RecordedEvent\")({\n sequence: Sequence,\n event: BrowserEvent,\n}) {}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiBA,IAAa,aAAb,cAAgC,OAAO,YAAwB,CAAC,CAAC,cAAc;CAC7E,IAAI,OAAO;CACX,MAAM,OAAO;CACb,KAAK,OAAO;CACZ,QAAQ,OAAO,SAAS,OAAO,MAAM;AACvC,CAAC,CAAC,CAAC,CAAC;;;;;AAMJ,IAAa,aAAb,cAAgC,OAAO,YAAwB,CAAC,CAAC,cAAc;CAC7E,IAAI,OAAO;CACX,MAAM,OAAO;CACb,OAAO,OAAO,SAAS,CAAC,QAAQ,SAAS,CAAC;AAC5C,CAAC,CAAC,CAAC,CAAC;;;;;AAMJ,IAAa,gBAAb,cAAmC,OAAO,YAA2B,CAAC,CAAC,iBAAiB;CACtF,IAAI,OAAO;CACX,KAAK,OAAO;CACZ,QAAQ,OAAO;AACjB,CAAC,CAAC,CAAC,CAAC;;;;;AAMJ,IAAa,YAAb,cAA+B,OAAO,YAAuB,CAAC,CAAC,aAAa;CAC1E,IAAI,OAAO;CACX,MAAM,OAAO;CACb,KAAK,OAAO;;;;;;CAMZ,UAAU,OAAO,IAAI,MAAM,OAAO,uBAAuB,CAAC,CAAC;CAC3D,cAAc,OAAO;AACvB,CAAC,CAAC,CAAC,CAAC;;AAGJ,IAAa,aAAb,cAAgC,OAAO,YAAwB,CAAC,CAAC,cAAc;CAC7E,IAAI,OAAO;CACX,MAAM,OAAO;CACb,OAAO,OAAO,SAAS,CAAC,oBAAoB,MAAM,CAAC;AACrD,CAAC,CAAC,CAAC,CAAC;;;;;AAMJ,MAAa,kBAAkB,OAAO,SAAS;CAAC;CAAc;CAAW;AAAU,CAAC;;AAKpF,IAAa,eAAb,cAAkC,OAAO,YAA0B,CAAC,CAAC,gBAAgB;CACnF,IAAI,OAAO;CACX,OAAO;AACT,CAAC,CAAC,CAAC,CAAC;;AAGJ,IAAa,gBAAb,cAAmC,OAAO,YAA2B,CAAC,CAAC,iBAAiB;CACtF,IAAI,OAAO;CACX,WAAW,OAAO;AACpB,CAAC,CAAC,CAAC,CAAC;;;;;;;;AASJ,MAAa,iBAAiB,OAAO,OAAO;CAC1C,KAAK,OAAO,SAAS,OAAO,MAAM;CAClC,QAAQ,OAAO,SAAS,OAAO,MAAM;CACrC,OAAO,OAAO,SAAS,OAAO,MAAM;CACpC,SAAS,OAAO,SAAS,OAAO,MAAM;AACxC,CAAC;;;;;;;AAUD,IAAa,UAAb,cAA6B,OAAO,MAAe,wBAAwB,CAAC,CAAC;CAC3E,MAAM,OAAO,OAAO,OAAO,MAAM;CACjC,MAAM,OAAO;CACb,KAAK,OAAO;CACZ,SAAS;AACX,CAAC,CAAC,CAAC,CAAC;AAEJ,MAAM,SAAS,OAAO,SAAS;CAAC;CAAQ;CAAS;AAAQ,CAAC;;AAG1D,MAAa,MAAM,OAAO,OAAO;CAC/B,GAAG,OAAO;CACV,GAAG,OAAO;CACV,OAAO,OAAO;CACd,QAAQ,OAAO;AACjB,CAAC;;;;;;AASD,MAAa,gBAAgB,OAAO,OAAO;CACzC,QAAQ,OAAO,SAAS,MAAM;CAC9B,YAAY,OAAO,SAAS,OAAO,MAAM;CACzC,YAAY,OAAO,SAAS,OAAO,MAAM;CACzC,SAAS,OAAO,SAAS,OAAO,OAAO;CACvC,QAAQ,OAAO,SAAS,OAAO,OAAO;CACtC,OAAO,OAAO,SAAS,OAAO,MAAM;CACpC,IAAI,OAAO,SAAS,OAAO,MAAM;CACjC,IAAI,OAAO,SAAS,OAAO,MAAM;CACjC,QAAQ,OAAO,SAAS,OAAO,MAAM,OAAO,MAAM,CAAC;AACrD,CAAC;;;;;;;;;AAYD,IAAa,SAAb,cAA4B,OAAO,YAAoB,CAAC,CAAC,UAAU;CACjE,IAAI,OAAO;CACX,WAAW,OAAO;CAClB,MAAM,OAAO;CACb,MAAM,OAAO;;CAEb,KAAK,OAAO,SAAS,OAAO,MAAM;CAClC,aAAa,OAAO,SAAS,OAAO,MAAM;CAC1C,QAAQ,OAAO,SAAS,OAAO,MAAM;CACrC,SAAS,OAAO,SAAS,aAAa;CACtC,SAAS,OAAO,SAAS,OAAO;CAChC,IAAI,OAAO,SAAS,OAAO;;CAE3B,KAAK,OAAO,SAAS,GAAG;CACxB,MAAM,OAAO,SAAS,OAAO,MAAM;CACnC,GAAG,OAAO,SAAS,OAAO,MAAM;CAChC,GAAG,OAAO,SAAS,OAAO,MAAM;CAChC,IAAI,OAAO;CACX,YAAY,OAAO;CACnB,OAAO,OAAO,SAAS,OAAO,MAAM;AACtC,CAAC,CAAC,CAAC,CAAC;AAEJ,MAAM,WAAW,OAAO,IAAI,MAAM,OAAO,cAAc,CAAC,CAAC;;AAGzD,IAAa,eAAb,cAAkC,OAAO,YAA0B,CAAC,CAAC,gBAAgB;CACnF,IAAI,OAAO;CACX,MAAM,OAAO;CACb,MAAMA;CACN,SAASC;AACX,CAAC,CAAC,CAAC,CAAC;;;;;;AAOJ,IAAa,iBAAb,cAAoC,OAAO,YAA4B,CAAC,CAAC,kBAAkB;CACzF,IAAI,OAAO;CACX,MAAM,OAAO;CACb,MAAM;CACN,YAAY,OAAO,IAAI,MAAM,OAAO,uBAAuB,CAAC,CAAC;CAC7D,GAAG,OAAO;CACV,GAAG,OAAO;CACV,UAAU,OAAO;AACnB,CAAC,CAAC,CAAC,CAAC;AAEJ,IAAa,iBAAb,cAAoC,OAAO,YAA4B,CAAC,CAAC,kBAAkB;CACzF,IAAI,OAAO;CACX,MAAM,OAAO;CACb,GAAG,OAAO;CACV,GAAG,OAAO;CACV,QAAQ;CACR,YAAY,OAAO,IAAI,MAAM,OAAO,cAAc,CAAC,CAAC;AACtD,CAAC,CAAC,CAAC,CAAC;AAEJ,IAAa,kBAAb,cAAqC,OAAO,YAA6B,CAAC,CAAC,mBAAmB;CAC5F,IAAI,OAAO;CACX,MAAM,OAAO;CACb,GAAG,OAAO;CACV,GAAG,OAAO;CACV,QAAQ;CACR,YAAY,OAAO,IAAI,MAAM,OAAO,cAAc,CAAC,CAAC;AACtD,CAAC,CAAC,CAAC,CAAC;AAEJ,IAAa,gBAAb,cAAmC,OAAO,YAA2B,CAAC,CAAC,iBAAiB;CACtF,IAAI,OAAO;CACX,MAAM,OAAO;CACb,GAAG,OAAO;CACV,GAAG,OAAO;CACV,IAAI,OAAO;CACX,IAAI,OAAO;AACb,CAAC,CAAC,CAAC,CAAC;AAEJ,IAAa,aAAb,cAAgC,OAAO,YAAwB,CAAC,CAAC,cAAc;CAC7E,IAAI,OAAO;CACX,MAAM,OAAO;CACb,KAAK,OAAO;CACZ,OAAO,OAAO,SAAS,CAAC,QAAQ,IAAI,CAAC;AACvC,CAAC,CAAC,CAAC,CAAC;;AAGJ,IAAa,eAAb,cAAkC,OAAO,YAA0B,CAAC,CAAC,gBAAgB;CACnF,IAAI,OAAO;CACX,MAAM,OAAO;CACb,MAAM,OAAO;AACf,CAAC,CAAC,CAAC,CAAC;;AAGJ,IAAa,gBAAb,cAAmC,OAAO,YAA2B,CAAC,CAAC,iBAAiB;CACtF,IAAI,OAAO;CACX,MAAM,OAAO;CACb,QAAQ,OAAO;AACjB,CAAC,CAAC,CAAC,CAAC;AAEJ,MAAa,aAAa,OAAO,MAAM;CACrC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;;;;;AAQD,IAAa,cAAb,cAAiC,OAAO,YAAyB,CAAC,CAAC,eAAe;CAChF,IAAI,OAAO;CACX,MAAM,OAAO;CACb,MAAM,OAAO;CACb,SAAS,OAAO;CAChB,QAAQ,OAAO,SAAS,CAAC,YAAY,WAAW,CAAC;AACnD,CAAC,CAAC,CAAC,CAAC;AAEJ,MAAa,eAAe,OAAO,MAAM;CACvC;CACA;CACA;CACA;CACA;CACA;CACA,GAAG,WAAW;CACd;CACA;CACA;AACF,CAAC;;AAKD,IAAa,gBAAb,cAAmC,OAAO,MAAqB,8BAA8B,CAAC,CAAC;CAC7F,UAAU;CACV,OAAO;AACT,CAAC,CAAC,CAAC,CAAC"}
package/dist/Cdp.mjs CHANGED
@@ -2,7 +2,7 @@ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
2
  import { Failed } from "./BrowserError.mjs";
3
3
  import { r as quoted } from "./url-CcL0K7S0.mjs";
4
4
  import { o as reasonOf, s as undispatched } from "./context-DAYjATgC.mjs";
5
- import { r as make, t as Browser } from "./Browser-B5AV7zPS.mjs";
5
+ import { r as make, t as Browser } from "./Browser-CNwK0r0q.mjs";
6
6
  import { Effect, Layer, Redacted } from "effect";
7
7
  import { chromium } from "playwright-core";
8
8
  //#region src/Cdp.ts
@@ -1,4 +1,4 @@
1
- import { b as Subject } from "./BrowserEvent-DzdNdvoh.mjs";
1
+ import { b as Subject } from "./BrowserEvent-BRu2juEz.mjs";
2
2
  import { Schema } from "effect";
3
3
  declare namespace Change_d_exports {
4
4
  export { Change, Changes, Kind, describe };
@@ -68,4 +68,4 @@ declare class Changes extends Changes_base {}
68
68
  declare const describe: (change: Change) => string;
69
69
  //#endregion
70
70
  export { describe as a, Kind as i, Change_d_exports as n, Changes as r, Change as t };
71
- //# sourceMappingURL=Change-DVP2IJWm.d.mts.map
71
+ //# sourceMappingURL=Change-iMlcuzVD.d.mts.map
package/dist/Change.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as describe, i as Kind, r as Changes, t as Change } from "./Change-DVP2IJWm.mjs";
1
+ import { a as describe, i as Kind, r as Changes, t as Change } from "./Change-iMlcuzVD.mjs";
2
2
  export { Change, Changes, Kind, describe };
package/dist/Chromium.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
2
  import { Failed } from "./BrowserError.mjs";
3
3
  import { o as reasonOf, s as undispatched } from "./context-DAYjATgC.mjs";
4
- import { r as make, t as Browser } from "./Browser-B5AV7zPS.mjs";
4
+ import { r as make, t as Browser } from "./Browser-CNwK0r0q.mjs";
5
5
  import { Effect, Layer } from "effect";
6
6
  import { chromium } from "playwright-core";
7
7
  //#region src/Chromium.ts
package/dist/Expect.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as BrowserError } from "./BrowserError-DXXIA6Rk.mjs";
2
- import { a as FindQuery, u as Page } from "./Page-DYTdVhYa.mjs";
2
+ import { a as FindQuery, u as Page } from "./Page-C30aG2RQ.mjs";
3
3
  import { Duration, Effect } from "effect";
4
4
  declare namespace Expect_d_exports {
5
5
  export { Attempt, Expectation, Options, Outcome, appeared, attempt, changed, gone, navigated };
package/dist/Expect.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
2
  import { InvalidRequest } from "./BrowserError.mjs";
3
3
  import { s as undispatched } from "./context-DAYjATgC.mjs";
4
- import { t as internalsOf } from "./page-BkRcLCWZ.mjs";
4
+ import { t as internalsOf } from "./page-DHeYWEs-.mjs";
5
5
  import { Cause, Duration, Effect, Exit, Option, Schedule } from "effect";
6
6
  //#region src/Expect.ts
7
7
  /**
package/dist/Moment.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { A as Account, F as account, I as capture, L as toPrompt, M as Moment, P as Window, j as CaptureOptions } from "./Page-DYTdVhYa.mjs";
1
+ import { A as Account, F as account, I as capture, L as toPrompt, M as Moment, P as Window, j as CaptureOptions } from "./Page-C30aG2RQ.mjs";
2
2
  export { Account, CaptureOptions, Moment, Window, account, capture, toPrompt };