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.
- package/README.md +61 -231
- package/dist/Account.d.mts +4 -6
- package/dist/Account.mjs +4 -9
- package/dist/Account.mjs.map +1 -1
- package/dist/{Acquisition-WBafHwXH.mjs → Acquisition-D8o4jtCg.mjs} +22 -68
- package/dist/Acquisition-D8o4jtCg.mjs.map +1 -0
- package/dist/Agents.d.mts +4 -6
- package/dist/Agents.mjs +3 -19
- package/dist/Agents.mjs.map +1 -1
- package/dist/Allocation.d.mts +9 -11
- package/dist/Allocation.mjs +2 -4
- package/dist/Allocation.mjs.map +1 -1
- package/dist/Browser.d.mts +25 -140
- package/dist/Browser.mjs +266 -1
- package/dist/Browser.mjs.map +1 -0
- package/dist/BrowserBinding.d.mts +7 -34
- package/dist/BrowserBinding.mjs +30 -1
- package/dist/BrowserBinding.mjs.map +1 -0
- package/dist/Certificates.d.mts +3 -5
- package/dist/Certificates.mjs +2 -7
- package/dist/Certificates.mjs.map +1 -1
- package/dist/{Cleanup-G2YpTCuU.d.mts → Cleanup-DMTDBir8.d.mts} +5 -6
- package/dist/Cleanup.d.mts +3 -2
- package/dist/Cleanup.mjs +1 -6
- package/dist/Cleanup.mjs.map +1 -1
- package/dist/{Client-D1_xYM9o.mjs → Client-BQteUePT.mjs} +2 -4
- package/dist/{Client-D1_xYM9o.mjs.map → Client-BQteUePT.mjs.map} +1 -1
- package/dist/Client.d.mts +51 -2
- package/dist/Client.mjs +1 -1
- package/dist/Connection-DcvJZEdc.mjs +65 -0
- package/dist/Connection-DcvJZEdc.mjs.map +1 -0
- package/dist/ContextCoordination.d.mts +5 -6
- package/dist/ContextCoordination.mjs +1 -8
- package/dist/ContextCoordination.mjs.map +1 -1
- package/dist/Contexts.d.mts +4 -6
- package/dist/Contexts.mjs +2 -8
- package/dist/Contexts.mjs.map +1 -1
- package/dist/Downloads.d.mts +6 -8
- package/dist/Downloads.mjs +3 -8
- package/dist/Downloads.mjs.map +1 -1
- package/dist/Errors.d.mts +3 -26
- package/dist/Errors.mjs +1 -137
- package/dist/Errors.mjs.map +1 -1
- package/dist/{Extensions-ClZbYb1H.mjs → Extensions-nMNMPGCc.mjs} +3 -9
- package/dist/{Extensions-ClZbYb1H.mjs.map → Extensions-nMNMPGCc.mjs.map} +1 -1
- package/dist/Extensions.d.mts +4 -6
- package/dist/Extensions.mjs +1 -1
- package/dist/Functions.d.mts +4 -6
- package/dist/Functions.mjs +3 -17
- package/dist/Functions.mjs.map +1 -1
- package/dist/{Launch-BHcAEq05.mjs → Launch-m0fxzJ49.mjs} +5 -5
- package/dist/Launch-m0fxzJ49.mjs.map +1 -0
- package/dist/Launch.d.mts +130 -2
- package/dist/Launch.mjs +4 -11
- package/dist/Launch.mjs.map +1 -1
- package/dist/PageFetch.d.mts +3 -5
- package/dist/PageFetch.mjs +2 -8
- package/dist/PageFetch.mjs.map +1 -1
- package/dist/Projects.d.mts +3 -5
- package/dist/Projects.mjs +2 -8
- package/dist/Projects.mjs.map +1 -1
- package/dist/Recordings.d.mts +6 -8
- package/dist/Recordings.mjs +3 -5
- package/dist/Recordings.mjs.map +1 -1
- package/dist/{References-URDAtapt.d.mts → References-DOH3Wu44.d.mts} +5 -6
- package/dist/References.d.mts +3 -2
- package/dist/References.mjs +10 -18
- package/dist/References.mjs.map +1 -1
- package/dist/Replays.d.mts +6 -8
- package/dist/Replays.mjs +3 -5
- package/dist/Replays.mjs.map +1 -1
- package/dist/Search.d.mts +3 -5
- package/dist/Search.mjs +2 -9
- package/dist/Search.mjs.map +1 -1
- package/dist/{SessionData-DRKcKCqw.d.mts → SessionData-5xYZDshJ.d.mts} +5 -6
- package/dist/SessionData.d.mts +3 -2
- package/dist/SessionData.mjs +1 -8
- package/dist/SessionData.mjs.map +1 -1
- package/dist/{Sessions-CtbseWEh.mjs → Sessions-DoQGg9nB.mjs} +34 -18
- package/dist/Sessions-DoQGg9nB.mjs.map +1 -0
- package/dist/{Sessions-B8E4kMxo.d.mts → Sessions-tFJYaXFq.d.mts} +8 -8
- package/dist/Sessions.d.mts +4 -3
- package/dist/Sessions.mjs +1 -1
- package/dist/{Transfers-Czv5IZzJ.d.mts → Transfers-GVqzrDWl.d.mts} +22 -9
- package/dist/Transfers.d.mts +3 -2
- package/dist/Transfers.mjs +12 -28
- package/dist/Transfers.mjs.map +1 -1
- package/dist/Uploads.d.mts +6 -8
- package/dist/Uploads.mjs +3 -5
- package/dist/Uploads.mjs.map +1 -1
- package/dist/Webhooks.d.mts +3 -5
- package/dist/Webhooks.mjs +2 -11
- package/dist/Webhooks.mjs.map +1 -1
- package/dist/{WriterFacts-osvYAsIx.d.mts → WriterFacts-5CPBGG1P.d.mts} +4 -3
- package/dist/index.d.mts +27 -30
- package/dist/index.mjs +26 -30
- package/package.json +3 -24
- package/dist/Acquisition-WBafHwXH.mjs.map +0 -1
- package/dist/Association-CEps4hYP.mjs +0 -10
- package/dist/Association-CEps4hYP.mjs.map +0 -1
- package/dist/Bootstrap-BXuzZojd.mjs +0 -194
- package/dist/Bootstrap-BXuzZojd.mjs.map +0 -1
- package/dist/Bootstrap-m7lHgj0D.d.mts +0 -177
- package/dist/Bootstrap.d.mts +0 -2
- package/dist/Bootstrap.mjs +0 -2
- package/dist/Browser-joE4Zgys.mjs +0 -1557
- package/dist/Browser-joE4Zgys.mjs.map +0 -1
- package/dist/BrowserBinding-qbQA6JhH.mjs +0 -2452
- package/dist/BrowserBinding-qbQA6JhH.mjs.map +0 -1
- package/dist/BrowserData-LpcAuAub.d.mts +0 -369
- package/dist/BrowserData.d.mts +0 -2
- package/dist/BrowserData.mjs +0 -442
- package/dist/BrowserData.mjs.map +0 -1
- package/dist/Capture-CZJPuD7b.mjs +0 -532
- package/dist/Capture-CZJPuD7b.mjs.map +0 -1
- package/dist/Capture-Dr5MkIJb.d.mts +0 -125
- package/dist/Capture.d.mts +0 -2
- package/dist/Capture.mjs +0 -2
- package/dist/Client-Ca0zSg1n.d.mts +0 -53
- package/dist/Images-DgscEfSf.mjs +0 -127
- package/dist/Images-DgscEfSf.mjs.map +0 -1
- package/dist/Launch-BHcAEq05.mjs.map +0 -1
- package/dist/Launch-C8CfaYxb.d.mts +0 -132
- package/dist/PageControl.d.mts +0 -16
- package/dist/PageControl.mjs +0 -36
- package/dist/PageControl.mjs.map +0 -1
- package/dist/PageControlAssociation-DabEg5AR.mjs +0 -10
- package/dist/PageControlAssociation-DabEg5AR.mjs.map +0 -1
- package/dist/Sessions-CtbseWEh.mjs.map +0 -1
- package/dist/rolldown-runtime-D7D4PA-g.mjs +0 -13
package/dist/Browser.d.mts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { AllocationError,
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { r as DownloadObservation } from "./Transfers-
|
|
6
|
-
import { n as CleanupResult } from "./Cleanup-
|
|
7
|
-
import { n as ContextWriterPermit } from "./WriterFacts-
|
|
8
|
-
import {
|
|
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
|
-
|
|
13
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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 {
|
|
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 {
|
|
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 {
|
|
2
|
-
import
|
|
1
|
+
import { Context, Layer } from "effect";
|
|
2
|
+
import * as BrowserRuntime from "effect-browser/browser-runtime";
|
|
3
3
|
//#region src/BrowserBinding.d.ts
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
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
|
package/dist/BrowserBinding.mjs
CHANGED
|
@@ -1,2 +1,31 @@
|
|
|
1
|
-
import {
|
|
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
|