effect-browserbase 0.1.0-beta.102 → 0.2.0-beta.0

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 (130) hide show
  1. package/README.md +61 -231
  2. package/dist/Account.d.mts +4 -6
  3. package/dist/Account.mjs +4 -9
  4. package/dist/Account.mjs.map +1 -1
  5. package/dist/{Acquisition-WBafHwXH.mjs → Acquisition-D8o4jtCg.mjs} +22 -68
  6. package/dist/Acquisition-D8o4jtCg.mjs.map +1 -0
  7. package/dist/Agents.d.mts +4 -6
  8. package/dist/Agents.mjs +3 -19
  9. package/dist/Agents.mjs.map +1 -1
  10. package/dist/Allocation.d.mts +9 -11
  11. package/dist/Allocation.mjs +2 -4
  12. package/dist/Allocation.mjs.map +1 -1
  13. package/dist/Browser.d.mts +25 -140
  14. package/dist/Browser.mjs +266 -1
  15. package/dist/Browser.mjs.map +1 -0
  16. package/dist/BrowserBinding.d.mts +7 -34
  17. package/dist/BrowserBinding.mjs +30 -1
  18. package/dist/BrowserBinding.mjs.map +1 -0
  19. package/dist/Certificates.d.mts +3 -5
  20. package/dist/Certificates.mjs +2 -7
  21. package/dist/Certificates.mjs.map +1 -1
  22. package/dist/{Cleanup-G2YpTCuU.d.mts → Cleanup-DMTDBir8.d.mts} +5 -6
  23. package/dist/Cleanup.d.mts +3 -2
  24. package/dist/Cleanup.mjs +1 -6
  25. package/dist/Cleanup.mjs.map +1 -1
  26. package/dist/{Client-D1_xYM9o.mjs → Client-BQteUePT.mjs} +2 -4
  27. package/dist/{Client-D1_xYM9o.mjs.map → Client-BQteUePT.mjs.map} +1 -1
  28. package/dist/Client.d.mts +51 -2
  29. package/dist/Client.mjs +1 -1
  30. package/dist/Connection-DcvJZEdc.mjs +65 -0
  31. package/dist/Connection-DcvJZEdc.mjs.map +1 -0
  32. package/dist/ContextCoordination.d.mts +5 -6
  33. package/dist/ContextCoordination.mjs +1 -8
  34. package/dist/ContextCoordination.mjs.map +1 -1
  35. package/dist/Contexts.d.mts +4 -6
  36. package/dist/Contexts.mjs +2 -8
  37. package/dist/Contexts.mjs.map +1 -1
  38. package/dist/Downloads.d.mts +6 -8
  39. package/dist/Downloads.mjs +3 -8
  40. package/dist/Downloads.mjs.map +1 -1
  41. package/dist/Errors.d.mts +3 -26
  42. package/dist/Errors.mjs +1 -137
  43. package/dist/Errors.mjs.map +1 -1
  44. package/dist/{Extensions-ClZbYb1H.mjs → Extensions-nMNMPGCc.mjs} +3 -9
  45. package/dist/{Extensions-ClZbYb1H.mjs.map → Extensions-nMNMPGCc.mjs.map} +1 -1
  46. package/dist/Extensions.d.mts +4 -6
  47. package/dist/Extensions.mjs +1 -1
  48. package/dist/Functions.d.mts +4 -6
  49. package/dist/Functions.mjs +3 -17
  50. package/dist/Functions.mjs.map +1 -1
  51. package/dist/{Launch-BHcAEq05.mjs → Launch-m0fxzJ49.mjs} +5 -5
  52. package/dist/Launch-m0fxzJ49.mjs.map +1 -0
  53. package/dist/Launch.d.mts +130 -2
  54. package/dist/Launch.mjs +4 -11
  55. package/dist/Launch.mjs.map +1 -1
  56. package/dist/PageFetch.d.mts +3 -5
  57. package/dist/PageFetch.mjs +2 -8
  58. package/dist/PageFetch.mjs.map +1 -1
  59. package/dist/Projects.d.mts +3 -5
  60. package/dist/Projects.mjs +2 -8
  61. package/dist/Projects.mjs.map +1 -1
  62. package/dist/Recordings.d.mts +6 -8
  63. package/dist/Recordings.mjs +3 -5
  64. package/dist/Recordings.mjs.map +1 -1
  65. package/dist/{References-URDAtapt.d.mts → References-DOH3Wu44.d.mts} +5 -6
  66. package/dist/References.d.mts +3 -2
  67. package/dist/References.mjs +10 -18
  68. package/dist/References.mjs.map +1 -1
  69. package/dist/Replays.d.mts +6 -8
  70. package/dist/Replays.mjs +3 -5
  71. package/dist/Replays.mjs.map +1 -1
  72. package/dist/Search.d.mts +3 -5
  73. package/dist/Search.mjs +2 -9
  74. package/dist/Search.mjs.map +1 -1
  75. package/dist/{SessionData-DRKcKCqw.d.mts → SessionData-5xYZDshJ.d.mts} +5 -6
  76. package/dist/SessionData.d.mts +3 -2
  77. package/dist/SessionData.mjs +1 -8
  78. package/dist/SessionData.mjs.map +1 -1
  79. package/dist/{Sessions-CtbseWEh.mjs → Sessions-DoQGg9nB.mjs} +34 -18
  80. package/dist/Sessions-DoQGg9nB.mjs.map +1 -0
  81. package/dist/{Sessions-B8E4kMxo.d.mts → Sessions-tFJYaXFq.d.mts} +8 -8
  82. package/dist/Sessions.d.mts +4 -3
  83. package/dist/Sessions.mjs +1 -1
  84. package/dist/{Transfers-Czv5IZzJ.d.mts → Transfers-GVqzrDWl.d.mts} +22 -9
  85. package/dist/Transfers.d.mts +3 -2
  86. package/dist/Transfers.mjs +12 -28
  87. package/dist/Transfers.mjs.map +1 -1
  88. package/dist/Uploads.d.mts +6 -8
  89. package/dist/Uploads.mjs +3 -5
  90. package/dist/Uploads.mjs.map +1 -1
  91. package/dist/Webhooks.d.mts +3 -5
  92. package/dist/Webhooks.mjs +2 -11
  93. package/dist/Webhooks.mjs.map +1 -1
  94. package/dist/{WriterFacts-osvYAsIx.d.mts → WriterFacts-5CPBGG1P.d.mts} +4 -3
  95. package/dist/index.d.mts +27 -30
  96. package/dist/index.mjs +26 -30
  97. package/package.json +3 -24
  98. package/dist/Acquisition-WBafHwXH.mjs.map +0 -1
  99. package/dist/Association-CEps4hYP.mjs +0 -10
  100. package/dist/Association-CEps4hYP.mjs.map +0 -1
  101. package/dist/Bootstrap-BXuzZojd.mjs +0 -194
  102. package/dist/Bootstrap-BXuzZojd.mjs.map +0 -1
  103. package/dist/Bootstrap-m7lHgj0D.d.mts +0 -177
  104. package/dist/Bootstrap.d.mts +0 -2
  105. package/dist/Bootstrap.mjs +0 -2
  106. package/dist/Browser-joE4Zgys.mjs +0 -1557
  107. package/dist/Browser-joE4Zgys.mjs.map +0 -1
  108. package/dist/BrowserBinding-qbQA6JhH.mjs +0 -2452
  109. package/dist/BrowserBinding-qbQA6JhH.mjs.map +0 -1
  110. package/dist/BrowserData-LpcAuAub.d.mts +0 -369
  111. package/dist/BrowserData.d.mts +0 -2
  112. package/dist/BrowserData.mjs +0 -442
  113. package/dist/BrowserData.mjs.map +0 -1
  114. package/dist/Capture-CZJPuD7b.mjs +0 -532
  115. package/dist/Capture-CZJPuD7b.mjs.map +0 -1
  116. package/dist/Capture-Dr5MkIJb.d.mts +0 -125
  117. package/dist/Capture.d.mts +0 -2
  118. package/dist/Capture.mjs +0 -2
  119. package/dist/Client-Ca0zSg1n.d.mts +0 -53
  120. package/dist/Images-DgscEfSf.mjs +0 -127
  121. package/dist/Images-DgscEfSf.mjs.map +0 -1
  122. package/dist/Launch-BHcAEq05.mjs.map +0 -1
  123. package/dist/Launch-C8CfaYxb.d.mts +0 -132
  124. package/dist/PageControl.d.mts +0 -16
  125. package/dist/PageControl.mjs +0 -36
  126. package/dist/PageControl.mjs.map +0 -1
  127. package/dist/PageControlAssociation-DabEg5AR.mjs +0 -10
  128. package/dist/PageControlAssociation-DabEg5AR.mjs.map +0 -1
  129. package/dist/Sessions-CtbseWEh.mjs.map +0 -1
  130. package/dist/rolldown-runtime-D7D4PA-g.mjs +0 -13
@@ -1,17 +1,16 @@
1
- import { o as SessionReference, t as AllocationAttempt } from "./References-URDAtapt.mjs";
2
- import { AllocationError, BrowserError, ContextError, InitializationError, SessionError } from "./Errors.mjs";
3
- import { t as BrowserbaseClient } from "./Client-Ca0zSg1n.mjs";
4
- import { s as LiveView, t as BrowserbaseSessions } from "./Sessions-B8E4kMxo.mjs";
5
- import { r as DownloadObservation } from "./Transfers-Czv5IZzJ.mjs";
6
- import { n as CleanupResult } from "./Cleanup-G2YpTCuU.mjs";
7
- import { n as ContextWriterPermit } from "./WriterFacts-osvYAsIx.mjs";
8
- import { f as Plan, g as ReadinessOutcome, s as Bootstrap_d_exports, t as BindingDiagnostics } from "./Bootstrap-m7lHgj0D.mjs";
9
- import { A as ReadTextRequest, B as TypeRequest, E as PageInfo, G as WheelRequest, I as StartNavigationRequest, L as Target, M as ScreenshotResult, N as ScrollRequest, O as PointerMoveRequest, P as SelectFilesRequest, S as ObservationOptions, V as Viewport, _ as KeyStroke, a as Checkpoint, b as NavigationResult, c as ControlFacts, d as FrameInfo, f as HoverRequest, h as InputReceipt, i as BrowserPolicy, j as ScreenshotRequest, k as PressRequest, n as AutomationOptions, o as CheckpointOptions, s as ClickRequest, t as ActionResult, u as FillRequest, w as ObservedElement, x as Observation, y as NavigateRequest, z as TextResult } from "./BrowserData-LpcAuAub.mjs";
10
- import { t as LaunchRecipe } from "./Launch-C8CfaYxb.mjs";
1
+ import { a as SessionReference, t as AllocationAttempt } from "./References-DOH3Wu44.mjs";
2
+ import { AllocationError, ContextError, SessionError } from "./Errors.mjs";
3
+ import { BrowserbaseClient } from "./Client.mjs";
4
+ import { o as LiveView, t as BrowserbaseSessions } from "./Sessions-tFJYaXFq.mjs";
5
+ import { f as SelectFilesRequest, i as FileSelection, r as DownloadObservation } from "./Transfers-GVqzrDWl.mjs";
6
+ import { n as CleanupResult } from "./Cleanup-DMTDBir8.mjs";
7
+ import { n as ContextWriterPermit } from "./WriterFacts-5CPBGG1P.mjs";
8
+ import { LaunchRecipe } from "./Launch.mjs";
11
9
  import { Context, Effect, Layer, Option, Redacted, Scope } from "effect";
12
- declare namespace Browser_d_exports {
13
- export { AttachRequest, BoundTarget, BrowserAcquisition, BrowserOptions, BrowserbaseBrowser, BrowserbaseSession, ElementAdmission, Handoff, LiveView, NavigationOperation, OpenOptions };
14
- }
10
+ import { ActionResult, AutomationOptions, BrowserPolicy, ClickRequest, Observation } from "effect-browser/browser-data";
11
+ import { BrowserError, InitializationError } from "effect-browser/errors";
12
+ import { BrowserSession, OpenOptions } from "effect-browser/browser";
13
+ //#region src/Browser.d.ts
15
14
  /** Host configuration. Credentials live in the Client; a model never selects these values. */
16
15
  export interface BrowserOptions extends AutomationOptions {
17
16
  readonly launch: LaunchRecipe;
@@ -24,126 +23,15 @@ export interface Handoff {
24
23
  readonly token: Redacted.Redacted<string>;
25
24
  readonly view: LiveView;
26
25
  }
27
- /**
28
- * A host's decision about one control, made on facts read from the exact node immediately
29
- * before input. Returning anything but `true`, or throwing, sends nothing and fails `denied`.
30
- * It is a plain synchronous function on purpose: it runs while the owner's permit is held, where
31
- * waiting on a model or a network call would stall every other operation. It is not an atomic
32
- * check-and-input transaction, because page script can still run before the native input lands.
33
- */
34
- export interface ElementAdmission {
35
- readonly admit: (facts: ControlFacts) => boolean;
36
- }
37
- /**
38
- * A navigation the browser is still performing. The owner's permit was released when it was
39
- * dispatched, so while it loads a host may read, `checkpoint`, hold and resume this page, and
40
- * use any other page. Anything that would change this page fails `busy` until it settles.
41
- *
42
- * Leaving its scope unsettled fences the session, exactly as an interrupted mutation does,
43
- * because nothing then knows what the browser did. It is never replayed.
44
- */
45
- export interface NavigationOperation {
46
- /** What was navigated, read before dispatch. */
47
- readonly target: Target;
48
- /**
49
- * The document reached DOMContentLoaded. It belongs to this one navigation: a successor that
50
- * reaches the same URL fails it instead. Interrupting a waiter stops nothing in the browser.
51
- */
52
- readonly completed: Effect.Effect<NavigationResult, BrowserError>;
53
- /**
54
- * Asks the browser to stop loading and waits for this navigation to settle, after which
55
- * `completed` fails `interrupted`. Success is a known outcome and the session stays usable:
56
- * the page holds whatever had loaded. It does not undo anything the page already did.
57
- */
58
- readonly stop: Effect.Effect<void, BrowserError>;
59
- }
60
- /** One selected page and frame at one connection generation, never the current DOM. */
61
- export interface BoundTarget {
62
- readonly navigate: (request: NavigateRequest) => Effect.Effect<NavigationResult, BrowserError>;
63
- /** `navigate`, left in flight: the same single dispatch, completed by the caller. */
64
- readonly startNavigation: (request: StartNavigationRequest) => Effect.Effect<NavigationOperation, BrowserError, Scope.Scope>;
65
- readonly readText: (request: ReadTextRequest) => Effect.Effect<TextResult, BrowserError>;
66
- readonly click: (request: ClickRequest) => Effect.Effect<ActionResult, BrowserError>;
67
- readonly fill: (request: FillRequest) => Effect.Effect<ActionResult, BrowserError>;
68
- /** Script in the page: instantaneous, and it raises no wheel event. */
69
- readonly scroll: (request: ScrollRequest) => Effect.Effect<ActionResult, BrowserError>;
70
- /** One real pointer move, in main-frame viewport pixels. */
71
- readonly pointerMove: (request: PointerMoveRequest) => Effect.Effect<InputReceipt, BrowserError>;
72
- /** Places the pointer on one exact element where it is, or fails `not-visible` unsent. */
73
- readonly hover: (request: HoverRequest) => Effect.Effect<InputReceipt, BrowserError>;
74
- /** One real wheel event; the browser decides what under the pointer scrolls. */
75
- readonly wheel: (request: WheelRequest) => Effect.Effect<InputReceipt, BrowserError>;
76
- /** One real key stroke to whatever has focus, or fails `not-focused` unsent if `into` lacks it. */
77
- readonly press: (request: PressRequest) => Effect.Effect<InputReceipt, BrowserError>;
78
- /** Text as the real key strokes that produce it, under the same focus rule as `press`. */
79
- readonly type: (request: TypeRequest) => Effect.Effect<InputReceipt, BrowserError>;
80
- readonly screenshot: (request: ScreenshotRequest) => Effect.Effect<ScreenshotResult, BrowserError>;
81
- }
82
- /**
83
- * Host control over one owned browser. This is not a serializable model value: copying a
84
- * session object cannot copy its capture, page-control or connection authority.
85
- */
86
- export interface BrowserbaseSession<E = never> {
26
+ /** Browserbase identity, remote artifacts and provider cleanup remain hosted capabilities. */
27
+ export interface BrowserbaseSession<E = never> extends BrowserSession<E> {
87
28
  readonly reference: SessionReference;
88
- /** First fail-session callback cause, preserving the consumer's error type on the host. */
89
- readonly failure: Effect.Effect<never, E | InitializationError>;
90
- /** Bounded host-only evidence; consumer causes are never projected into a page reply. */
91
- readonly bindingDiagnostics: Effect.Effect<BindingDiagnostics<E>>;
92
- readonly bind: () => BoundTarget;
93
- /** Re-reads the live selection first, so a stale generation fails before any dispatch. */
94
- readonly currentTarget: Effect.Effect<BoundTarget, BrowserError>;
95
- readonly target: Effect.Effect<Target, BrowserError>;
96
- /**
97
- * The one observation whose nodes later actions may name. `scope: "viewport"` keeps only text
98
- * and controls that are on screen and reachable; the default reads the whole document. It is
99
- * safe to show a model: it carries no destination, form or field value.
100
- */
101
- readonly observe: (options?: ObservationOptions) => Effect.Effect<Observation, BrowserError>;
102
- /**
103
- * Passive evidence for a recorder, with a picture when asked. It issues no references and
104
- * leaves the observation above exactly as it was. Host-only: it carries control facts.
105
- */
106
- readonly checkpoint: (options?: CheckpointOptions) => Effect.Effect<Checkpoint, BrowserError>;
107
- /** Host-only facts about one observed control, read from that exact node just now. */
108
- readonly controlFacts: (reference: ObservedElement) => Effect.Effect<ControlFacts, BrowserError>;
109
- /**
110
- * After a page hold, nothing observed on that page may be acted on unchecked. This checks one
111
- * reference: still attached, and still the control that was inspected. It never searches by
112
- * selector or label for a substitute, and it sends nothing.
113
- */
114
- readonly revalidateElement: (reference: ObservedElement) => Effect.Effect<ObservedElement, BrowserError>;
115
- readonly clickElement: (reference: ObservedElement, admission?: ElementAdmission) => Effect.Effect<ActionResult, BrowserError>;
116
- readonly fillElement: (reference: ObservedElement, value: string, admission?: ElementAdmission) => Effect.Effect<ActionResult, BrowserError>;
117
- readonly hoverElement: (reference: ObservedElement, admission?: ElementAdmission) => Effect.Effect<InputReceipt, BrowserError>;
118
- /** A key stroke sent only if the exact node an observation named already has focus. */
119
- readonly pressElement: (reference: ObservedElement, stroke: KeyStroke, admission?: ElementAdmission) => Effect.Effect<InputReceipt, BrowserError>;
120
- /** Real typing with `fillElement`'s exactness: that node must already have focus. */
121
- readonly typeElement: (reference: ObservedElement, text: string, admission?: ElementAdmission) => Effect.Effect<InputReceipt, BrowserError>;
122
- readonly pages: Effect.Effect<ReadonlyArray<PageInfo>, BrowserError>;
123
- readonly frames: Effect.Effect<ReadonlyArray<FrameInfo>, BrowserError>;
124
- readonly selectPage: (pageId: string) => Effect.Effect<BoundTarget, BrowserError>;
125
- readonly selectFrame: (frameId: string) => Effect.Effect<BoundTarget, BrowserError>;
126
- /** Create a tab without selecting it. */
127
- readonly createPage: Effect.Effect<string, BrowserError>;
128
- readonly closePage: (pageId: string) => Effect.Effect<void, BrowserError>;
129
- readonly resizeViewport: (viewport: Viewport) => Effect.Effect<void, BrowserError>;
130
- readonly waitFor: (request: {
131
- readonly selector: string;
132
- readonly state: "visible" | "hidden" | "attached" | "detached";
133
- }) => Effect.Effect<void, BrowserError>;
134
- /** Navigation observation is registered before the single click dispatch. */
135
- readonly clickAndWait: (request: ClickRequest) => Effect.Effect<ActionResult, BrowserError>;
29
+ readonly closeChecked: Effect.Effect<CleanupResult, BrowserError>;
136
30
  readonly clickForDownload: (request: ClickRequest) => Effect.Effect<DownloadObservation, BrowserError>;
137
31
  /** Attaches to an existing file input; an uploaded branch needs a receipt for this session. */
138
32
  readonly selectFiles: (request: SelectFilesRequest) => Effect.Effect<ActionResult, BrowserError>;
139
33
  /** Registers the chooser observation before the single click that opens it. */
140
34
  readonly clickForFileSelection: (request: SelectFilesRequest) => Effect.Effect<ActionResult, BrowserError>;
141
- /**
142
- * Readiness of the current document only. Dependent operations wait for it themselves;
143
- * this reports it without charging an action, so a caller can decide what to do about a
144
- * document that predates the registrations.
145
- */
146
- readonly ready: Effect.Effect<ReadinessOutcome, InitializationError>;
147
35
  readonly liveView: (expiresInSeconds?: number) => Effect.Effect<LiveView, BrowserError>;
148
36
  readonly beginHandoff: (expiresInSeconds?: number) => Effect.Effect<Handoff, BrowserError>;
149
37
  readonly resume: (token: Redacted.Redacted<string>, operatorReleasedControl: boolean) => Effect.Effect<Observation, BrowserError>;
@@ -152,13 +40,9 @@ export interface BrowserbaseSession<E = never> {
152
40
  readonly targetId: string;
153
41
  }, BrowserError>;
154
42
  readonly reconnect: (operatorReleasedControl: boolean) => Effect.Effect<Observation, BrowserError | InitializationError>;
155
- readonly close: Effect.Effect<CleanupResult, BrowserError>;
43
+ readonly close: Effect.Effect<CleanupResult>;
156
44
  readonly cleanupResult: Effect.Effect<Option.Option<CleanupResult>>;
157
45
  }
158
- /** Dependencies are captured at acquisition, not erased into an environment-free service Layer. */
159
- export interface OpenOptions<E = never, R = never> {
160
- readonly bootstrap?: Plan<E, R>;
161
- }
162
46
  export interface AttachRequest<E = never, R = never> extends OpenOptions<E, R> {
163
47
  readonly policy: BrowserPolicy;
164
48
  /** The exact page to resume; without it the session must have exactly one page. */
@@ -173,23 +57,24 @@ export interface BrowserAcquisition<E = never> {
173
57
  readonly attempt: AllocationAttempt;
174
58
  readonly failure: Effect.Effect<never, E | InitializationError>;
175
59
  readonly connect: Effect.Effect<BrowserbaseSession<E>, BrowserError | E | InitializationError>;
176
- readonly close: Effect.Effect<CleanupResult, BrowserError>;
60
+ readonly close: Effect.Effect<CleanupResult>;
177
61
  }
178
62
  declare const BrowserbaseBrowser_base: Context.ServiceClass<BrowserbaseBrowser, "effect-browserbase/Browser", {
179
63
  readonly acquire: <E = never, R = never>(policy: BrowserPolicy, request?: OpenOptions<E, R>) => Effect.Effect<BrowserAcquisition<E>, AllocationError | BrowserError | ContextError, Scope.Scope | Exclude<R, Scope.Scope>>;
180
64
  /** Borrowed control of a session this process did not allocate and will not release. */
181
65
  readonly attach: <E = never, R = never>(reference: SessionReference, request: AttachRequest<E, R>) => Effect.Effect<BrowserbaseSession<E>, BrowserError | SessionError | E | InitializationError, Scope.Scope | Exclude<R, Scope.Scope>>;
182
66
  readonly open: <E = never, R = never>(policy: BrowserPolicy, request?: OpenOptions<E, R>) => Effect.Effect<BrowserbaseSession<E>, AllocationError | BrowserError | ContextError | E | InitializationError, Scope.Scope | Exclude<R, Scope.Scope>>;
183
- /** Race the consumer with typed callback failure and confirm cleanup before normal success. */
184
- readonly withBrowser: <E, R, A, E2, R2>(policy: BrowserPolicy, request: OpenOptions<E, R>, use: (session: BrowserbaseSession<E>) => Effect.Effect<A, E2, R2>) => Effect.Effect<A, AllocationError | BrowserError | ContextError | InitializationError | E | E2, Exclude<R | R2, Scope.Scope>>;
185
67
  }>;
186
- /**
187
- * Credentials, budgets and connection lifetime are fixed when this Layer is built. Building it
188
- * allocates nothing and loads no native peer; every acquisition is scoped by its caller.
189
- */
190
68
  export declare class BrowserbaseBrowser extends BrowserbaseBrowser_base {
69
+ /** Open through the configured account and browser service, in the caller's scope. */
70
+ static open<E = never, R = never>(policy: BrowserPolicy, request?: OpenOptions<E, R>): Effect.Effect<BrowserbaseSession<E>, E | AllocationError | BrowserError | ContextError | InitializationError, BrowserbaseBrowser | Scope.Scope | Exclude<R, Scope.Scope>>;
71
+ /** Allocate the provider lifetime before connecting, preserving its attempt and cleanup. */
72
+ static acquire<E = never, R = never>(policy: BrowserPolicy, request?: OpenOptions<E, R>): Effect.Effect<BrowserAcquisition<E>, AllocationError | BrowserError | ContextError, BrowserbaseBrowser | Scope.Scope | Exclude<R, Scope.Scope>>;
73
+ /** Borrow a provider session without acquiring release authority over it. */
74
+ static attach<E = never, R = never>(reference: SessionReference, request: AttachRequest<E, R>): Effect.Effect<BrowserbaseSession<E>, E | BrowserError | InitializationError | SessionError, BrowserbaseBrowser | Scope.Scope | Exclude<R, Scope.Scope>>;
191
75
  static layer(options: BrowserOptions): Layer.Layer<BrowserbaseBrowser, BrowserError, BrowserbaseClient | BrowserbaseSessions>;
192
76
  }
193
77
  //#endregion
194
- export { type LiveView, Browser_d_exports as t };
78
+ export type { FileSelection, LiveView, SelectFilesRequest };
79
+ export {};
195
80
  //# sourceMappingURL=Browser.d.mts.map
package/dist/Browser.mjs CHANGED
@@ -1,2 +1,267 @@
1
- import { n as BrowserbaseBrowser } from "./Browser-joE4Zgys.mjs";
1
+ import { SessionError } from "./Errors.mjs";
2
+ import { DownloadObservation } from "./Transfers.mjs";
3
+ import { t as BrowserbaseClient } from "./Client-BQteUePT.mjs";
4
+ import { isTerminalSessionStatus } from "./SessionData.mjs";
5
+ import { a as issueLiveView, o as browserRequestFailure, t as BrowserbaseSessions } from "./Sessions-DoQGg9nB.mjs";
6
+ import { t as issuedUpload } from "./Issued-DejqoMYL.mjs";
7
+ import { t as connectionAddress } from "./Connection-DcvJZEdc.mjs";
8
+ import { a as reported, i as noLocalConnection, n as reportCleanup, r as makeCleanup, t as acquireRemote } from "./Acquisition-D8o4jtCg.mjs";
9
+ import { BrowserbaseBrowserBinding } from "./BrowserBinding.mjs";
10
+ import { Context, Effect, Exit, Layer, Option, Schema, Scope } from "effect";
11
+ import { BrowserError, Reasons } from "effect-browser/errors";
12
+ import * as BrowserRuntime from "effect-browser/browser-runtime";
13
+ //#region src/internal/session/Attachment.ts
14
+ const failure = (reason) => SessionError.make({
15
+ operation: "session-attach",
16
+ reason,
17
+ outcome: "undispatched"
18
+ });
19
+ /**
20
+ * Borrowing an already running session. This scope owns its local connection and nothing
21
+ * else: no allocation attempt is made, no release is requested, and no Context-writer
22
+ * authority is claimed. Whoever allocated the session keeps all three.
23
+ */
24
+ const attachRemote = Effect.fnUntraced(function* (options, local = noLocalConnection, limits) {
25
+ const client = yield* BrowserbaseClient;
26
+ const sessions = yield* BrowserbaseSessions;
27
+ const parent = yield* Scope.Scope;
28
+ const pendingWaitMillis = options.pendingWaitMillis ?? 0;
29
+ if (!Number.isSafeInteger(pendingWaitMillis) || pendingWaitMillis < 0 || pendingWaitMillis > 6e5) return yield* failure("configuration");
30
+ const observed = yield* sessions.retrieve(options.reference);
31
+ if (isTerminalSessionStatus(observed.status)) return yield* failure("expired");
32
+ if (observed.status !== "RUNNING") {
33
+ if (pendingWaitMillis === 0) return yield* failure("active");
34
+ yield* sessions.waitUntilRunning(observed.reference, { timeoutMillis: pendingWaitMillis });
35
+ }
36
+ const reference = observed.reference;
37
+ return yield* Effect.uninterruptible(Effect.gen(function* () {
38
+ const resourceScope = yield* Scope.make();
39
+ let closing = false;
40
+ let cleanup;
41
+ const terminate = yield* Effect.cached(Effect.uninterruptible(Effect.gen(function* () {
42
+ closing = true;
43
+ yield* (yield* makeCleanup(reference, "borrowed", sessions, local, (result) => {
44
+ cleanup = result;
45
+ }, limits)).close;
46
+ const result = cleanup;
47
+ const notify = options.onCleanup;
48
+ if (result !== void 0) {
49
+ yield* reported(Effect.suspend(() => reportCleanup(result)));
50
+ if (notify !== void 0) yield* reported(Effect.suspend(() => notify(result)));
51
+ }
52
+ })));
53
+ const closeScope = yield* Effect.cached(Scope.close(resourceScope, Exit.void));
54
+ yield* Scope.addFinalizer(resourceScope, terminate);
55
+ yield* Scope.addFinalizer(parent, closeScope);
56
+ return {
57
+ reference,
58
+ status: observed,
59
+ connection: (timeoutMillis) => Effect.suspend(() => closing ? Effect.fail(SessionError.make({
60
+ operation: "session-connect",
61
+ reason: "expired",
62
+ outcome: "undispatched"
63
+ })) : connectionAddress(client, sessions, reference, timeoutMillis)),
64
+ release: closeScope.pipe(Effect.andThen(Effect.suspend(() => cleanup === void 0 ? Effect.die(/* @__PURE__ */ new Error("Borrowed session closed without cleanup evidence")) : Effect.succeed(cleanup)))),
65
+ cleanupResult: Effect.sync(() => Option.fromNullishOr(cleanup))
66
+ };
67
+ }));
68
+ });
69
+ //#endregion
70
+ //#region src/internal/session/Browser.ts
71
+ /** A borrowed connection closes without requiring or requesting remote termination. */
72
+ const checkedCleanup = (close) => close.pipe(Effect.filterOrFail((result) => result.local === "closed" && result.issues.length === 0 && (result.ownership === "borrowed" ? result.remote === "not-owned" : result.remote === "confirmed"), () => BrowserError.make({
73
+ operation: "close",
74
+ reason: Reasons.Provider.make({}),
75
+ outcome: "unknown"
76
+ })));
77
+ const withConnection = (acquired) => ({
78
+ ...acquired,
79
+ connection: (timeoutMillis) => acquired.connection(timeoutMillis).pipe(Effect.mapError((error) => browserRequestFailure("connect", error))),
80
+ closeChecked: checkedCleanup(acquired.release),
81
+ controlRetired: acquired.cleanupResult.pipe(Effect.map((result) => Option.isSome(result) && result.value.ownership === "owned" && result.value.remote === "confirmed"))
82
+ });
83
+ /** Allocates the session, and therefore owns releasing it. */
84
+ const providerControls = (client, sessions, reference) => ({
85
+ liveView: (ttl) => issueLiveView(client, reference, ttl),
86
+ verifyReconnect: sessions.retrieve(reference).pipe(Effect.mapError((error) => browserRequestFailure("reconnect", error)), Effect.flatMap((status) => status.status === "RUNNING" ? Effect.void : Effect.fail(BrowserError.make({
87
+ operation: "reconnect",
88
+ reason: Reasons.Expired.make({}),
89
+ outcome: "undispatched"
90
+ }))))
91
+ });
92
+ const ownedRemote = (options) => (local, lifetimeDeadline) => Effect.gen(function* () {
93
+ const client = yield* BrowserbaseClient;
94
+ const sessions = yield* BrowserbaseSessions;
95
+ const acquired = yield* acquireRemote({
96
+ launch: options.launch,
97
+ ...options.contextWriter === void 0 ? {} : { contextWriter: options.contextWriter },
98
+ allocationDeadline: lifetimeDeadline,
99
+ ...options.onCleanup === void 0 ? {} : { onCleanup: options.onCleanup },
100
+ ...options.onAllocationUncertain === void 0 ? {} : { onAllocationUncertain: options.onAllocationUncertain }
101
+ }, local);
102
+ return {
103
+ ...withConnection(acquired),
104
+ ...providerControls(client, sessions, acquired.reference)
105
+ };
106
+ });
107
+ /** Borrows a running session: local connection only, and never a release request. */
108
+ const borrowedRemote = (options) => (local) => Effect.gen(function* () {
109
+ const client = yield* BrowserbaseClient;
110
+ const sessions = yield* BrowserbaseSessions;
111
+ const acquired = yield* attachRemote(options, local);
112
+ return {
113
+ ...withConnection(acquired),
114
+ ...providerControls(client, sessions, acquired.reference)
115
+ };
116
+ });
117
+ //#endregion
118
+ //#region src/Browser.ts
119
+ /** Only receipts issued for this exact provider session may resolve to stored paths. */
120
+ const selection = (request, reference, operation) => Effect.suspend(() => {
121
+ if (request.selection._tag === "Inline") return Effect.succeed({
122
+ _tag: "Inline",
123
+ files: request.selection.files
124
+ });
125
+ const uploads = request.selection.uploads;
126
+ if (!Array.isArray(uploads) || uploads.length < 1 || uploads.length > 8) return Effect.fail(BrowserError.make({
127
+ operation,
128
+ reason: Reasons.Configuration.make({}),
129
+ outcome: "undispatched"
130
+ }));
131
+ const paths = [];
132
+ for (const receipt of uploads) {
133
+ const issued = issuedUpload(receipt);
134
+ if (issued === void 0 || issued.reference.projectId !== reference.projectId || issued.reference.sessionId !== reference.sessionId) return Effect.fail(BrowserError.make({
135
+ operation,
136
+ reason: Reasons.Authorization.make({}),
137
+ outcome: "undispatched"
138
+ }));
139
+ paths.push(issued.remotePath);
140
+ }
141
+ return Effect.succeed({
142
+ _tag: "Stored",
143
+ paths
144
+ });
145
+ });
146
+ const makeSession = (connection, lifetime) => {
147
+ const { session, operations } = connection;
148
+ return Object.assign(session, {
149
+ reference: lifetime.reference,
150
+ closeChecked: session.closeChecked.pipe(Effect.andThen(lifetime.closeChecked)),
151
+ clickForDownload: (request) => operations.clickForDownload(request).pipe(Effect.flatMap((event) => Schema.decodeEffect(DownloadObservation)({
152
+ ...event,
153
+ reference: lifetime.reference
154
+ }).pipe(Effect.mapError(() => BrowserError.make({
155
+ operation: "download-action",
156
+ reason: Reasons.Malformed.make({}),
157
+ outcome: "unknown"
158
+ }))))),
159
+ selectFiles: (request) => selection(request, lifetime.reference, "select-files").pipe(Effect.flatMap((files) => operations.selectFiles({
160
+ selector: request.selector,
161
+ selection: files
162
+ }))),
163
+ clickForFileSelection: (request) => selection(request, lifetime.reference, "file-chooser").pipe(Effect.flatMap((files) => operations.clickForFileSelection({
164
+ selector: request.selector,
165
+ selection: files
166
+ }))),
167
+ liveView: (ttl = 60) => operations.liveView(lifetime.liveView(ttl)),
168
+ beginHandoff: (ttl = 60) => operations.beginHandoff(lifetime.liveView(ttl)),
169
+ resume: operations.resume,
170
+ detach: operations.detach,
171
+ reconnect: operations.reconnect,
172
+ close: lifetime.release,
173
+ cleanupResult: lifetime.cleanupResult
174
+ });
175
+ };
176
+ var BrowserbaseBrowser = class BrowserbaseBrowser extends Context.Service()("effect-browserbase/Browser") {
177
+ /** Open through the configured account and browser service, in the caller's scope. */
178
+ static open(policy, request) {
179
+ return Effect.flatMap(BrowserbaseBrowser, (browser) => browser.open(policy, request));
180
+ }
181
+ /** Allocate the provider lifetime before connecting, preserving its attempt and cleanup. */
182
+ static acquire(policy, request) {
183
+ return Effect.flatMap(BrowserbaseBrowser, (browser) => browser.acquire(policy, request));
184
+ }
185
+ /** Borrow a provider session without acquiring release authority over it. */
186
+ static attach(reference, request) {
187
+ return Effect.flatMap(BrowserbaseBrowser, (browser) => browser.attach(reference, request));
188
+ }
189
+ static layer(options) {
190
+ return Layer.effect(BrowserbaseBrowser, Effect.gen(function* () {
191
+ const client = yield* BrowserbaseClient;
192
+ const sessions = yield* BrowserbaseSessions;
193
+ const binding = yield* BrowserbaseBrowserBinding;
194
+ if (options.launch.context?.persist === true && options.contextWriter === void 0) return yield* BrowserError.make({
195
+ operation: "configure",
196
+ reason: Reasons.ContextLease.make({}),
197
+ outcome: "undispatched"
198
+ });
199
+ if (Object.prototype.hasOwnProperty.call(options, "bootstrap")) return yield* BrowserError.make({
200
+ operation: "configure",
201
+ reason: Reasons.Configuration.make({}),
202
+ outcome: "undispatched"
203
+ });
204
+ const runtime = yield* BrowserRuntime.make({
205
+ implementation: "browserbase-playwright-cdp",
206
+ binding,
207
+ automation: projected(options),
208
+ viewport: options.launch.viewport._tag === "Fixed" ? {
209
+ width: options.launch.viewport.width,
210
+ height: options.launch.viewport.height
211
+ } : {
212
+ width: 1280,
213
+ height: 720
214
+ },
215
+ preserveViewport: options.launch.viewport._tag !== "Fixed",
216
+ keepAlive: options.launch.keepAlive === true
217
+ });
218
+ const source = (remote) => (cleanup, deadline) => remote(cleanup, deadline).pipe(Effect.provideService(BrowserbaseClient, client), Effect.provideService(BrowserbaseSessions, sessions));
219
+ const acquire = Effect.fnUntraced(function* (policy, request = {}) {
220
+ const acquired = yield* runtime.acquire(policy, source(ownedRemote({
221
+ launch: options.launch,
222
+ ...options.contextWriter === void 0 ? {} : { contextWriter: options.contextWriter },
223
+ ...options.onCleanup === void 0 ? {} : { onCleanup: options.onCleanup },
224
+ ...options.onAllocationUncertain === void 0 ? {} : { onAllocationUncertain: options.onAllocationUncertain }
225
+ })), request);
226
+ const connected = yield* Effect.cached(acquired.connect.pipe(Effect.map((connection) => makeSession(connection, acquired.lifetime))));
227
+ return {
228
+ reference: acquired.reference,
229
+ attempt: acquired.lifetime.attempt,
230
+ failure: acquired.failure,
231
+ close: acquired.close,
232
+ connect: acquired.connect.pipe(Effect.andThen(connected))
233
+ };
234
+ });
235
+ const attach = Effect.fnUntraced(function* (reference, request) {
236
+ const acquired = yield* runtime.acquire(request.policy, source(borrowedRemote({
237
+ reference,
238
+ ...request.pendingWaitMillis === void 0 ? {} : { pendingWaitMillis: request.pendingWaitMillis },
239
+ ...options.onCleanup === void 0 ? {} : { onCleanup: options.onCleanup }
240
+ })), {
241
+ ...request.bootstrap === void 0 ? {} : { bootstrap: request.bootstrap },
242
+ existingTarget: request.target ?? {}
243
+ });
244
+ return yield* acquired.connect.pipe(Effect.map((connection) => makeSession(connection, acquired.lifetime)));
245
+ });
246
+ return BrowserbaseBrowser.of({
247
+ acquire,
248
+ attach,
249
+ open: (policy, request) => acquire(policy, request).pipe(Effect.flatMap((acquired) => acquired.connect))
250
+ });
251
+ }));
252
+ }
253
+ };
254
+ /** Only the automation fields cross the schema boundary; launch and callbacks are separate. */
255
+ const projected = (options) => ({
256
+ ...options.maxHostReads === void 0 ? {} : { maxHostReads: options.maxHostReads },
257
+ ...options.actionTimeoutMillis === void 0 ? {} : { actionTimeoutMillis: options.actionTimeoutMillis },
258
+ ...options.maxPages === void 0 ? {} : { maxPages: options.maxPages },
259
+ ...options.initialPage === void 0 ? {} : { initialPage: options.initialPage },
260
+ ...options.popupPolicy === void 0 ? {} : { popupPolicy: options.popupPolicy },
261
+ ...options.dialogPolicy === void 0 ? {} : { dialogPolicy: options.dialogPolicy },
262
+ ...options.pageControl === void 0 ? {} : { pageControl: options.pageControl }
263
+ });
264
+ //#endregion
2
265
  export { BrowserbaseBrowser };
266
+
267
+ //# sourceMappingURL=Browser.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Browser.mjs","names":[],"sources":["../src/internal/session/Attachment.ts","../src/internal/session/Browser.ts","../src/Browser.ts"],"sourcesContent":["import { Effect, Exit, Option, Scope } from \"effect\";\n\nimport type { CleanupResult } from \"../../Cleanup.ts\";\nimport { BrowserbaseClient } from \"../../Client.ts\";\nimport { SessionError } from \"../../Errors.ts\";\nimport type { SessionReference } from \"../../References.ts\";\nimport { isTerminalSessionStatus } from \"../../SessionData.ts\";\nimport { BrowserbaseSessions } from \"../../Sessions.ts\";\nimport { connectionAddress } from \"../provider/Connection.ts\";\nimport {\n makeCleanup,\n noLocalConnection,\n reported,\n type CleanupLimits,\n type LocalCleanup,\n} from \"./Cleanup.ts\";\nimport { reportCleanup } from \"./Diagnostics.ts\";\n\nexport interface AttachmentOptions {\n readonly reference: SessionReference;\n /** Bounded admission of a session the provider has not finished starting. */\n readonly pendingWaitMillis?: number;\n readonly onCleanup?: (result: CleanupResult) => Effect.Effect<void>;\n}\n\nconst failure = (reason: SessionError[\"reason\"]) =>\n SessionError.make({ operation: \"session-attach\", reason, outcome: \"undispatched\" });\n\n/**\n * Borrowing an already running session. This scope owns its local connection and nothing\n * else: no allocation attempt is made, no release is requested, and no Context-writer\n * authority is claimed. Whoever allocated the session keeps all three.\n */\nexport const attachRemote = Effect.fnUntraced(function* (\n options: AttachmentOptions,\n local: LocalCleanup = noLocalConnection,\n limits?: CleanupLimits,\n) {\n const client = yield* BrowserbaseClient;\n const sessions = yield* BrowserbaseSessions;\n const parent = yield* Scope.Scope;\n const pendingWaitMillis = options.pendingWaitMillis ?? 0;\n\n if (\n !Number.isSafeInteger(pendingWaitMillis) ||\n pendingWaitMillis < 0 ||\n pendingWaitMillis > 600_000\n )\n return yield* failure(\"configuration\");\n\n // The status read validates project authority before anything is borrowed. A terminal\n // session needs a fresh allocation from durable state, never a reattachment.\n const observed = yield* sessions.retrieve(options.reference);\n\n if (isTerminalSessionStatus(observed.status)) return yield* failure(\"expired\");\n if (observed.status !== \"RUNNING\") {\n if (pendingWaitMillis === 0) return yield* failure(\"active\");\n yield* sessions.waitUntilRunning(observed.reference, { timeoutMillis: pendingWaitMillis });\n }\n const reference = observed.reference;\n\n return yield* Effect.uninterruptible(\n Effect.gen(function* () {\n const resourceScope = yield* Scope.make();\n let closing = false;\n let cleanup: CleanupResult | undefined;\n\n const terminate = yield* Effect.cached(\n Effect.uninterruptible(\n Effect.gen(function* () {\n closing = true;\n\n const coordinator = yield* makeCleanup(\n reference,\n \"borrowed\",\n sessions,\n local,\n (result) => {\n cleanup = result;\n },\n limits,\n );\n\n yield* coordinator.close;\n const result = cleanup;\n const notify = options.onCleanup;\n\n if (result !== undefined) {\n yield* reported(Effect.suspend(() => reportCleanup(result)));\n if (notify !== undefined) yield* reported(Effect.suspend(() => notify(result)));\n }\n }),\n ),\n );\n\n const closeScope = yield* Effect.cached(Scope.close(resourceScope, Exit.void));\n\n // Teardown is registered before the first connection, exactly as an owned scope does.\n yield* Scope.addFinalizer(resourceScope, terminate);\n yield* Scope.addFinalizer(parent, closeScope);\n\n return {\n reference,\n status: observed,\n connection: (timeoutMillis: number) =>\n Effect.suspend(() =>\n closing\n ? Effect.fail(\n SessionError.make({\n operation: \"session-connect\",\n reason: \"expired\",\n outcome: \"undispatched\",\n }),\n )\n : // Credentials are fetched fresh: an expiry can race the caller's own read.\n connectionAddress(client, sessions, reference, timeoutMillis),\n ),\n release: closeScope.pipe(\n Effect.andThen(\n Effect.suspend(() =>\n cleanup === undefined\n ? Effect.die(new Error(\"Borrowed session closed without cleanup evidence\"))\n : Effect.succeed(cleanup),\n ),\n ),\n ),\n cleanupResult: Effect.sync(() => Option.fromNullishOr(cleanup)),\n };\n }),\n );\n});\n","import { Effect, Option, type Redacted } from \"effect\";\nimport type { Lifetime, Source } from \"effect-browser/browser-runtime\";\nimport { BrowserError, Reasons } from \"effect-browser/errors\";\n\nimport type { CleanupResult } from \"../../Cleanup.ts\";\nimport { BrowserbaseClient } from \"../../Client.ts\";\nimport type { AllocationError, ContextError, SessionError } from \"../../Errors.ts\";\nimport type { LaunchRecipe } from \"../../Launch.ts\";\nimport type { AllocationAttempt, SessionReference } from \"../../References.ts\";\nimport { BrowserbaseSessions } from \"../../Sessions.ts\";\nimport { issueLiveView, type LiveView } from \"../browser/LiveView.ts\";\nimport { browserRequestFailure } from \"../browser/RequestFailure.ts\";\nimport { acquireRemote } from \"./Acquisition.ts\";\nimport { attachRemote } from \"./Attachment.ts\";\nimport type { ContextWriterPermit } from \"./WriterFacts.ts\";\n\nexport interface RemoteLease extends Lifetime {\n readonly reference: SessionReference;\n readonly closeChecked: Effect.Effect<CleanupResult, BrowserError>;\n readonly attempt?: AllocationAttempt;\n readonly release: Effect.Effect<CleanupResult>;\n readonly cleanupResult: Effect.Effect<Option.Option<CleanupResult>>;\n readonly liveView: (ttl: number) => Effect.Effect<LiveView, BrowserError>;\n}\n\ntype RemoteSource<L extends Lifetime, E> = Source<L, E, BrowserbaseClient | BrowserbaseSessions>;\n\n/** A borrowed connection closes without requiring or requesting remote termination. */\nconst checkedCleanup = (\n close: Effect.Effect<CleanupResult>,\n): Effect.Effect<CleanupResult, BrowserError> =>\n close.pipe(\n Effect.filterOrFail(\n (result) =>\n result.local === \"closed\" &&\n result.issues.length === 0 &&\n (result.ownership === \"borrowed\"\n ? result.remote === \"not-owned\"\n : result.remote === \"confirmed\"),\n () =>\n BrowserError.make({\n operation: \"close\",\n reason: Reasons.Provider.make({}),\n outcome: \"unknown\",\n }),\n ),\n );\n\nconst withConnection = <\n A extends {\n readonly reference: SessionReference;\n readonly connection: (\n timeoutMillis: number,\n ) => Effect.Effect<Redacted.Redacted<string>, SessionError>;\n readonly release: Effect.Effect<CleanupResult>;\n readonly cleanupResult: Effect.Effect<Option.Option<CleanupResult>>;\n },\n>(\n acquired: A,\n) => ({\n ...acquired,\n connection: (timeoutMillis: number) =>\n acquired\n .connection(timeoutMillis)\n .pipe(Effect.mapError((error) => browserRequestFailure(\"connect\", error))),\n closeChecked: checkedCleanup(acquired.release),\n controlRetired: acquired.cleanupResult.pipe(\n Effect.map(\n (result) =>\n Option.isSome(result) &&\n result.value.ownership === \"owned\" &&\n result.value.remote === \"confirmed\",\n ),\n ),\n});\n\nexport interface OwnedLease extends RemoteLease {\n readonly attempt: AllocationAttempt;\n}\n\nexport interface OwnedOptions {\n /** The single provider-faithful launch description; the owner adds no second default body. */\n readonly launch: LaunchRecipe;\n /** Required for a persistent context; the writer permit, not this owner, holds that authority. */\n readonly contextWriter?: ContextWriterPermit;\n readonly onCleanup?: (result: CleanupResult) => Effect.Effect<void>;\n readonly onAllocationUncertain?: (attempt: AllocationAttempt) => Effect.Effect<void>;\n}\n\n/** Allocates the session, and therefore owns releasing it. */\nconst providerControls = (\n client: BrowserbaseClient[\"Service\"],\n sessions: BrowserbaseSessions[\"Service\"],\n reference: SessionReference,\n) => ({\n liveView: (ttl: number) => issueLiveView(client, reference, ttl),\n verifyReconnect: sessions.retrieve(reference).pipe(\n Effect.mapError((error) => browserRequestFailure(\"reconnect\", error)),\n Effect.flatMap((status) =>\n status.status === \"RUNNING\"\n ? Effect.void\n : Effect.fail(\n BrowserError.make({\n operation: \"reconnect\",\n reason: Reasons.Expired.make({}),\n outcome: \"undispatched\",\n }),\n ),\n ),\n ),\n});\n\nexport const ownedRemote =\n (\n options: OwnedOptions,\n ): RemoteSource<OwnedLease, AllocationError | BrowserError | ContextError> =>\n (local, lifetimeDeadline) =>\n Effect.gen(function* () {\n const client = yield* BrowserbaseClient;\n const sessions = yield* BrowserbaseSessions;\n\n const acquired = yield* acquireRemote(\n {\n launch: options.launch,\n ...(options.contextWriter === undefined ? {} : { contextWriter: options.contextWriter }),\n allocationDeadline: lifetimeDeadline,\n ...(options.onCleanup === undefined ? {} : { onCleanup: options.onCleanup }),\n ...(options.onAllocationUncertain === undefined\n ? {}\n : { onAllocationUncertain: options.onAllocationUncertain }),\n },\n local,\n );\n\n return {\n ...withConnection(acquired),\n ...providerControls(client, sessions, acquired.reference),\n };\n });\n\n/** Borrows a running session: local connection only, and never a release request. */\nexport const borrowedRemote =\n (options: {\n readonly reference: SessionReference;\n readonly pendingWaitMillis?: number;\n readonly onCleanup?: (result: CleanupResult) => Effect.Effect<void>;\n }): RemoteSource<RemoteLease, SessionError> =>\n (local) =>\n Effect.gen(function* () {\n const client = yield* BrowserbaseClient;\n const sessions = yield* BrowserbaseSessions;\n const acquired = yield* attachRemote(options, local);\n\n return {\n ...withConnection(acquired),\n ...providerControls(client, sessions, acquired.reference),\n };\n });\n","import { Context, Effect, Layer, type Option, type Redacted, Schema, type Scope } from \"effect\";\nimport type { BrowserSession, OpenOptions } from \"effect-browser/browser\";\nimport type {\n ActionResult,\n AutomationOptions,\n BrowserPolicy,\n ClickRequest,\n Observation,\n} from \"effect-browser/browser-data\";\nimport * as BrowserRuntime from \"effect-browser/browser-runtime\";\nimport {\n BrowserError,\n Reasons,\n type BrowserOperation,\n type InitializationError,\n} from \"effect-browser/errors\";\n\nimport { BrowserbaseBrowserBinding } from \"./BrowserBinding.ts\";\nimport type { CleanupResult } from \"./Cleanup.ts\";\nimport { BrowserbaseClient } from \"./Client.ts\";\nimport type { AllocationError, ContextError, SessionError } from \"./Errors.ts\";\nimport type { LiveView } from \"./internal/browser/LiveView.ts\";\nimport { borrowedRemote, ownedRemote, type RemoteLease } from \"./internal/session/Browser.ts\";\nimport type { ContextWriterPermit } from \"./internal/session/WriterFacts.ts\";\nimport { issuedUpload } from \"./internal/upload/Issued.ts\";\nimport type { LaunchRecipe } from \"./Launch.ts\";\nimport type { AllocationAttempt, SessionReference } from \"./References.ts\";\nimport { BrowserbaseSessions } from \"./Sessions.ts\";\nimport { DownloadObservation, type SelectFilesRequest } from \"./Transfers.ts\";\n\nexport type { LiveView } from \"./internal/browser/LiveView.ts\";\nexport type { FileSelection, SelectFilesRequest } from \"./Transfers.ts\";\n\n/** Host configuration. Credentials live in the Client; a model never selects these values. */\nexport interface BrowserOptions extends AutomationOptions {\n readonly launch: LaunchRecipe;\n /** Required whenever the launch recipe persists a context. */\n readonly contextWriter?: ContextWriterPermit;\n readonly onCleanup?: (result: CleanupResult) => Effect.Effect<void>;\n readonly onAllocationUncertain?: (attempt: AllocationAttempt) => Effect.Effect<void>;\n}\n\nexport interface Handoff {\n readonly token: Redacted.Redacted<string>;\n readonly view: LiveView;\n}\n\n/** Browserbase identity, remote artifacts and provider cleanup remain hosted capabilities. */\nexport interface BrowserbaseSession<E = never> extends BrowserSession<E> {\n readonly reference: SessionReference;\n readonly closeChecked: Effect.Effect<CleanupResult, BrowserError>;\n readonly clickForDownload: (\n request: ClickRequest,\n ) => Effect.Effect<DownloadObservation, BrowserError>;\n /** Attaches to an existing file input; an uploaded branch needs a receipt for this session. */\n readonly selectFiles: (request: SelectFilesRequest) => Effect.Effect<ActionResult, BrowserError>;\n /** Registers the chooser observation before the single click that opens it. */\n readonly clickForFileSelection: (\n request: SelectFilesRequest,\n ) => Effect.Effect<ActionResult, BrowserError>;\n readonly liveView: (expiresInSeconds?: number) => Effect.Effect<LiveView, BrowserError>;\n readonly beginHandoff: (expiresInSeconds?: number) => Effect.Effect<Handoff, BrowserError>;\n readonly resume: (\n token: Redacted.Redacted<string>,\n operatorReleasedControl: boolean,\n ) => Effect.Effect<Observation, BrowserError>;\n readonly detach: Effect.Effect<\n { readonly reference: SessionReference; readonly targetId: string },\n BrowserError\n >;\n readonly reconnect: (\n operatorReleasedControl: boolean,\n ) => Effect.Effect<Observation, BrowserError | InitializationError>;\n readonly close: Effect.Effect<CleanupResult>;\n readonly cleanupResult: Effect.Effect<Option.Option<CleanupResult>>;\n}\n\nexport interface AttachRequest<E = never, R = never> extends OpenOptions<E, R> {\n readonly policy: BrowserPolicy;\n /** The exact page to resume; without it the session must have exactly one page. */\n readonly target?: { readonly targetId: string };\n /** Bounded admission of a session the provider has not finished starting. */\n readonly pendingWaitMillis?: number;\n}\n\nexport interface BrowserAcquisition<E = never> {\n readonly reference: SessionReference;\n readonly attempt: AllocationAttempt;\n readonly failure: Effect.Effect<never, E | InitializationError>;\n readonly connect: Effect.Effect<BrowserbaseSession<E>, BrowserError | E | InitializationError>;\n readonly close: Effect.Effect<CleanupResult>;\n}\n\n/** Only receipts issued for this exact provider session may resolve to stored paths. */\nconst selection = (\n request: SelectFilesRequest,\n reference: SessionReference,\n operation: BrowserOperation,\n): Effect.Effect<BrowserRuntime.ResolvedFileSelection, BrowserError> =>\n Effect.suspend(() => {\n if (request.selection._tag === \"Inline\")\n return Effect.succeed<BrowserRuntime.ResolvedFileSelection>({\n _tag: \"Inline\",\n files: request.selection.files,\n });\n\n const uploads = request.selection.uploads;\n\n if (!Array.isArray(uploads) || uploads.length < 1 || uploads.length > 8)\n return Effect.fail(\n BrowserError.make({\n operation,\n reason: Reasons.Configuration.make({}),\n outcome: \"undispatched\",\n }),\n );\n const paths: string[] = [];\n\n for (const receipt of uploads) {\n const issued = issuedUpload(receipt);\n\n if (\n issued === undefined ||\n issued.reference.projectId !== reference.projectId ||\n issued.reference.sessionId !== reference.sessionId\n )\n return Effect.fail(\n BrowserError.make({\n operation,\n reason: Reasons.Authorization.make({}),\n outcome: \"undispatched\",\n }),\n );\n paths.push(issued.remotePath);\n }\n\n return Effect.succeed<BrowserRuntime.ResolvedFileSelection>({ _tag: \"Stored\", paths });\n });\n\nconst makeSession = <E>(\n connection: BrowserRuntime.Connection<SessionReference, E>,\n lifetime: RemoteLease,\n): BrowserbaseSession<E> => {\n const { session, operations } = connection;\n\n // Decorating the same object preserves its private capture and page-control associations.\n return Object.assign(session, {\n reference: lifetime.reference,\n closeChecked: session.closeChecked.pipe(Effect.andThen(lifetime.closeChecked)),\n clickForDownload: (request) =>\n operations.clickForDownload(request).pipe(\n Effect.flatMap((event) =>\n Schema.decodeEffect(DownloadObservation)({\n ...event,\n reference: lifetime.reference,\n }).pipe(\n Effect.mapError(() =>\n BrowserError.make({\n operation: \"download-action\",\n reason: Reasons.Malformed.make({}),\n outcome: \"unknown\",\n }),\n ),\n ),\n ),\n ),\n selectFiles: (request) =>\n selection(request, lifetime.reference, \"select-files\").pipe(\n Effect.flatMap((files) =>\n operations.selectFiles({ selector: request.selector, selection: files }),\n ),\n ),\n clickForFileSelection: (request) =>\n selection(request, lifetime.reference, \"file-chooser\").pipe(\n Effect.flatMap((files) =>\n operations.clickForFileSelection({ selector: request.selector, selection: files }),\n ),\n ),\n liveView: (ttl = 60) => operations.liveView(lifetime.liveView(ttl)),\n beginHandoff: (ttl = 60) => operations.beginHandoff(lifetime.liveView(ttl)),\n resume: operations.resume,\n detach: operations.detach,\n reconnect: operations.reconnect,\n close: lifetime.release,\n cleanupResult: lifetime.cleanupResult,\n } satisfies Omit<BrowserbaseSession<E>, Exclude<keyof BrowserSession<E>, \"closeChecked\">>);\n};\n\nexport class BrowserbaseBrowser extends Context.Service<\n BrowserbaseBrowser,\n {\n readonly acquire: <E = never, R = never>(\n policy: BrowserPolicy,\n request?: OpenOptions<E, R>,\n ) => Effect.Effect<\n BrowserAcquisition<E>,\n AllocationError | BrowserError | ContextError,\n Scope.Scope | Exclude<R, Scope.Scope>\n >;\n /** Borrowed control of a session this process did not allocate and will not release. */\n readonly attach: <E = never, R = never>(\n reference: SessionReference,\n request: AttachRequest<E, R>,\n ) => Effect.Effect<\n BrowserbaseSession<E>,\n BrowserError | SessionError | E | InitializationError,\n Scope.Scope | Exclude<R, Scope.Scope>\n >;\n readonly open: <E = never, R = never>(\n policy: BrowserPolicy,\n request?: OpenOptions<E, R>,\n ) => Effect.Effect<\n BrowserbaseSession<E>,\n AllocationError | BrowserError | ContextError | E | InitializationError,\n Scope.Scope | Exclude<R, Scope.Scope>\n >;\n }\n>()(\"effect-browserbase/Browser\") {\n /** Open through the configured account and browser service, in the caller's scope. */\n static open<E = never, R = never>(policy: BrowserPolicy, request?: OpenOptions<E, R>) {\n return Effect.flatMap(BrowserbaseBrowser, (browser) => browser.open(policy, request));\n }\n\n /** Allocate the provider lifetime before connecting, preserving its attempt and cleanup. */\n static acquire<E = never, R = never>(policy: BrowserPolicy, request?: OpenOptions<E, R>) {\n return Effect.flatMap(BrowserbaseBrowser, (browser) => browser.acquire(policy, request));\n }\n\n /** Borrow a provider session without acquiring release authority over it. */\n static attach<E = never, R = never>(reference: SessionReference, request: AttachRequest<E, R>) {\n return Effect.flatMap(BrowserbaseBrowser, (browser) => browser.attach(reference, request));\n }\n\n static layer(\n options: BrowserOptions,\n ): Layer.Layer<BrowserbaseBrowser, BrowserError, BrowserbaseClient | BrowserbaseSessions> {\n return Layer.effect(\n BrowserbaseBrowser,\n Effect.gen(function* () {\n const client = yield* BrowserbaseClient;\n const sessions = yield* BrowserbaseSessions;\n const binding = yield* BrowserbaseBrowserBinding;\n\n if (options.launch.context?.persist === true && options.contextWriter === undefined)\n return yield* BrowserError.make({\n operation: \"configure\",\n reason: Reasons.ContextLease.make({}),\n outcome: \"undispatched\",\n });\n if (Object.prototype.hasOwnProperty.call(options, \"bootstrap\"))\n return yield* BrowserError.make({\n operation: \"configure\",\n reason: Reasons.Configuration.make({}),\n outcome: \"undispatched\",\n });\n\n const runtime = yield* BrowserRuntime.make({\n implementation: \"browserbase-playwright-cdp\",\n binding,\n automation: projected(options),\n viewport:\n options.launch.viewport._tag === \"Fixed\"\n ? { width: options.launch.viewport.width, height: options.launch.viewport.height }\n : { width: 1280, height: 720 },\n preserveViewport: options.launch.viewport._tag !== \"Fixed\",\n keepAlive: options.launch.keepAlive === true,\n });\n\n const source =\n <L extends BrowserRuntime.Lifetime, E>(\n remote: BrowserRuntime.Source<L, E, BrowserbaseClient | BrowserbaseSessions>,\n ): BrowserRuntime.Source<L, E> =>\n (cleanup, deadline) =>\n remote(cleanup, deadline).pipe(\n Effect.provideService(BrowserbaseClient, client),\n Effect.provideService(BrowserbaseSessions, sessions),\n );\n\n const acquire = Effect.fnUntraced(function* <E = never, R = never>(\n policy: BrowserPolicy,\n request: OpenOptions<E, R> = {},\n ) {\n const acquired = yield* runtime.acquire(\n policy,\n source(\n ownedRemote({\n launch: options.launch,\n ...(options.contextWriter === undefined\n ? {}\n : { contextWriter: options.contextWriter }),\n ...(options.onCleanup === undefined ? {} : { onCleanup: options.onCleanup }),\n ...(options.onAllocationUncertain === undefined\n ? {}\n : { onAllocationUncertain: options.onAllocationUncertain }),\n }),\n ),\n request,\n );\n\n const connected = yield* Effect.cached(\n acquired.connect.pipe(\n Effect.map((connection) => makeSession(connection, acquired.lifetime)),\n ),\n );\n\n return {\n reference: acquired.reference,\n attempt: acquired.lifetime.attempt,\n failure: acquired.failure,\n close: acquired.close,\n connect: acquired.connect.pipe(Effect.andThen(connected)),\n } satisfies BrowserAcquisition<E>;\n });\n\n const attach = Effect.fnUntraced(function* <E = never, R = never>(\n reference: SessionReference,\n request: AttachRequest<E, R>,\n ) {\n const acquired = yield* runtime.acquire(\n request.policy,\n source(\n borrowedRemote({\n reference,\n ...(request.pendingWaitMillis === undefined\n ? {}\n : { pendingWaitMillis: request.pendingWaitMillis }),\n ...(options.onCleanup === undefined ? {} : { onCleanup: options.onCleanup }),\n }),\n ),\n {\n ...(request.bootstrap === undefined ? {} : { bootstrap: request.bootstrap }),\n existingTarget: request.target ?? {},\n },\n );\n\n return yield* acquired.connect.pipe(\n Effect.map((connection) => makeSession(connection, acquired.lifetime)),\n );\n });\n\n return BrowserbaseBrowser.of({\n acquire,\n attach,\n open: (policy, request) =>\n acquire(policy, request).pipe(Effect.flatMap((acquired) => acquired.connect)),\n });\n }),\n );\n }\n}\n\n/** Only the automation fields cross the schema boundary; launch and callbacks are separate. */\nconst projected = (options: BrowserOptions) => ({\n ...(options.maxHostReads === undefined ? {} : { maxHostReads: options.maxHostReads }),\n ...(options.actionTimeoutMillis === undefined\n ? {}\n : { actionTimeoutMillis: options.actionTimeoutMillis }),\n ...(options.maxPages === undefined ? {} : { maxPages: options.maxPages }),\n ...(options.initialPage === undefined ? {} : { initialPage: options.initialPage }),\n ...(options.popupPolicy === undefined ? {} : { popupPolicy: options.popupPolicy }),\n ...(options.dialogPolicy === undefined ? {} : { dialogPolicy: options.dialogPolicy }),\n ...(options.pageControl === undefined ? {} : { pageControl: options.pageControl }),\n});\n"],"mappings":"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"}
@@ -1,40 +1,13 @@
1
- import { BrowserError } from "./Errors.mjs";
2
- import { Context, Effect, Layer, Redacted } from "effect";
1
+ import { Context, Layer } from "effect";
2
+ import * as BrowserRuntime from "effect-browser/browser-runtime";
3
3
  //#region src/BrowserBinding.d.ts
4
- /**
5
- * The trusted native engine an owned or borrowed browser connects through. It is opaque: only
6
- * this module issues one, so a value that merely has this shape is refused before allocation
7
- * rather than trusted with a connection.
8
- */
9
- export interface BrowserBinding {
10
- readonly _tag: "BrowserbaseBrowserBinding";
11
- }
12
- export interface PlaywrightOptions {
13
- /**
14
- * Trusted host routing. It runs only after the provider-issued address passed the same strict
15
- * checks as the default, and returns the CDP endpoint to connect to instead. A local engine
16
- * reached this way says nothing about how a hosted connection behaves.
17
- */
18
- readonly resolveEndpoint?: (provider: {
19
- readonly url: Redacted.Redacted<string>;
20
- }) => Effect.Effect<string, BrowserError>;
21
- /**
22
- * Trusted instrumentation of the engine's own browser object, called once per connection with
23
- * the endpoint it reached, before the owner drives it. The object is typed `unknown` so that
24
- * no declaration of this package names the optional native peer; it is host configuration,
25
- * never model-facing.
26
- */
27
- readonly onConnected?: (connection: {
28
- readonly native: unknown;
29
- readonly endpoint: string;
30
- }) => void;
31
- }
32
- /** Playwright over CDP, lazily loaded at connection time and never at Layer construction. */
4
+ export type BrowserBinding = BrowserRuntime.BrowserBinding;
5
+ export type PlaywrightOptions = BrowserRuntime.PlaywrightOptions;
6
+ /** Validate provider authority before invoking any trusted host routing. */
33
7
  export declare const playwright: (options?: PlaywrightOptions) => BrowserBinding;
34
- /** Defaults to Playwright with the provider's own address, so no consumer has to provide it. */
35
- export declare const BrowserbaseBrowserBinding: Context.Reference<BrowserBinding>;
36
- /** Supply a binding to every browser Layer built beneath it. */
8
+ export declare const BrowserbaseBrowserBinding: Context.Reference<BrowserRuntime.BrowserBinding>;
37
9
  export declare const layer: (binding: BrowserBinding) => Layer.Layer<never>;
38
10
  export declare const layerPlaywright: Layer.Layer<never>;
39
11
  //#endregion
12
+ export {};
40
13
  //# sourceMappingURL=BrowserBinding.d.mts.map
@@ -1,2 +1,31 @@
1
- import { i as playwright, n as layer, r as layerPlaywright, t as BrowserbaseBrowserBinding } from "./BrowserBinding-qbQA6JhH.mjs";
1
+ import { n as validateConnection } from "./Connection-DcvJZEdc.mjs";
2
+ import { Context, Effect, Layer, Redacted } from "effect";
3
+ import { BrowserError, Reasons } from "effect-browser/errors";
4
+ import * as BrowserRuntime from "effect-browser/browser-runtime";
5
+ //#region src/BrowserBinding.ts
6
+ /** Validate provider authority before invoking any trusted host routing. */
7
+ const playwright = (options = {}) => {
8
+ const { resolveEndpoint, onConnected } = options;
9
+ return BrowserRuntime.playwright({
10
+ resolveEndpoint: ({ url }) => Effect.gen(function* () {
11
+ const validated = yield* Effect.try({
12
+ try: () => validateConnection(Redacted.value(url)),
13
+ catch: (error) => error instanceof BrowserError ? error : BrowserError.make({
14
+ operation: "connect",
15
+ reason: Reasons.Malformed.make({}),
16
+ outcome: "undispatched"
17
+ })
18
+ });
19
+ return yield* resolveEndpoint === void 0 ? Effect.succeed(validated) : resolveEndpoint({ url: Redacted.make(validated) });
20
+ }),
21
+ ...onConnected === void 0 ? {} : { onConnected }
22
+ });
23
+ };
24
+ const defaultBinding = playwright();
25
+ const BrowserbaseBrowserBinding = Context.Reference("effect-browserbase/BrowserBinding", { defaultValue: () => defaultBinding });
26
+ const layer = (binding) => Layer.succeed(BrowserbaseBrowserBinding, binding);
27
+ const layerPlaywright = layer(defaultBinding);
28
+ //#endregion
2
29
  export { BrowserbaseBrowserBinding, layer, layerPlaywright, playwright };
30
+
31
+ //# sourceMappingURL=BrowserBinding.mjs.map