effect-browserbase 0.1.0-beta.102 → 0.1.0-beta.104
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 +75 -1
- package/dist/Browser.d.mts +11 -8
- package/dist/Browser.mjs +223 -2
- package/dist/Browser.mjs.map +1 -0
- package/dist/{BrowserBinding-qbQA6JhH.mjs → BrowserBinding-DlJTGYZL.mjs} +86 -30
- package/dist/{BrowserBinding-qbQA6JhH.mjs.map → BrowserBinding-DlJTGYZL.mjs.map} +1 -1
- package/dist/BrowserBinding.mjs +1 -1
- package/dist/{Capture-CZJPuD7b.mjs → Capture-Bc0z9IAi.mjs} +43 -4
- package/dist/Capture-Bc0z9IAi.mjs.map +1 -0
- package/dist/{Capture-Dr5MkIJb.d.mts → Capture-BvWI-l1A.d.mts} +48 -5
- package/dist/Capture.d.mts +2 -2
- package/dist/Capture.mjs +2 -2
- package/dist/LocalBrowser-BLancJ3R.d.mts +79 -0
- package/dist/LocalBrowser-DsQLWNL1.mjs +439 -0
- package/dist/LocalBrowser-DsQLWNL1.mjs.map +1 -0
- package/dist/LocalBrowser.d.mts +2 -0
- package/dist/LocalBrowser.mjs +2 -0
- package/dist/PageControl.d.mts +4 -4
- package/dist/PageControl.mjs.map +1 -1
- package/dist/{Browser-joE4Zgys.mjs → Session-D4nT9hOO.mjs} +185 -363
- package/dist/Session-D4nT9hOO.mjs.map +1 -0
- package/dist/index.d.mts +3 -2
- package/dist/index.mjs +4 -3
- package/package.json +5 -1
- package/dist/Browser-joE4Zgys.mjs.map +0 -1
- package/dist/Capture-CZJPuD7b.mjs.map +0 -1
|
@@ -1,20 +1,17 @@
|
|
|
1
|
-
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
1
|
import { Identifier } from "./References.mjs";
|
|
3
2
|
import { BrowserError, InitializationError, SessionError } from "./Errors.mjs";
|
|
4
|
-
import { DownloadObservation } from "./Transfers.mjs";
|
|
5
3
|
import { t as BrowserbaseClient } from "./Client-D1_xYM9o.mjs";
|
|
6
|
-
import { ActionResult,
|
|
4
|
+
import { ActionResult, Checkpoint, CheckpointOptions, ClickRequest, FillRequest, HoverRequest, InputReceipt, KeyStroke, NavigateRequest, NavigationResult, Observation, ObservationOptions, ObservedElement, PointerMoveRequest, PressRequest, ReadTextRequest, ScreenshotRequest, ScreenshotResult, ScrollRequest, StartNavigationRequest, Target, TextResult, TypeRequest, Viewport, WheelRequest } from "./BrowserData.mjs";
|
|
7
5
|
import { isTerminalSessionStatus } from "./SessionData.mjs";
|
|
8
6
|
import { n as nowMillis, r as until, t as deadlineAfter } from "./Deadline-CrViaogr.mjs";
|
|
9
7
|
import { o as issueLiveView, t as BrowserbaseSessions } from "./Sessions-CtbseWEh.mjs";
|
|
10
|
-
import { t as issuedUpload } from "./Issued-DejqoMYL.mjs";
|
|
11
8
|
import { a as reported, i as noLocalConnection, n as reportCleanup, o as connectionAddress, r as makeCleanup, t as acquireRemote } from "./Acquisition-WBafHwXH.mjs";
|
|
12
|
-
import {
|
|
9
|
+
import { h as snapshot, m as invoke, s as Plan } from "./Bootstrap-BXuzZojd.mjs";
|
|
13
10
|
import { o as publicError } from "./Images-DgscEfSf.mjs";
|
|
14
|
-
import {
|
|
11
|
+
import { o as bindingImplementation, t as BrowserbaseBrowserBinding } from "./BrowserBinding-DlJTGYZL.mjs";
|
|
15
12
|
import { t as associate } from "./Association-CEps4hYP.mjs";
|
|
16
13
|
import { t as associatePageControl } from "./PageControlAssociation-DabEg5AR.mjs";
|
|
17
|
-
import { Cause, Clock,
|
|
14
|
+
import { Cause, Clock, Deferred, Effect, Exit, FiberSet, Option, Redacted, Schema, Scope, Semaphore } from "effect";
|
|
18
15
|
//#region src/internal/browser/BindingRunner.ts
|
|
19
16
|
const makeBindingRunner = (capacity, handle, onFault) => {
|
|
20
17
|
if (!Number.isSafeInteger(capacity) || capacity < 1) throw new RangeError("Invalid binding callback capacity");
|
|
@@ -333,6 +330,136 @@ const makeBindings = Effect.fnUntraced(function* (plan) {
|
|
|
333
330
|
};
|
|
334
331
|
});
|
|
335
332
|
//#endregion
|
|
333
|
+
//#region src/internal/browser/PublicSession.ts
|
|
334
|
+
const checked = (schema, value, operation) => Schema.decodeUnknownEffect(schema)(value, { onExcessProperty: "error" }).pipe(Effect.mapError(() => BrowserError.make({
|
|
335
|
+
operation,
|
|
336
|
+
reason: "configuration",
|
|
337
|
+
outcome: "undispatched"
|
|
338
|
+
})));
|
|
339
|
+
const decoded = (schema, operation) => (value) => Schema.decodeUnknownEffect(schema)(value).pipe(Effect.mapError(() => BrowserError.make({
|
|
340
|
+
operation,
|
|
341
|
+
reason: "malformed"
|
|
342
|
+
})));
|
|
343
|
+
const action = decoded(ActionResult, "action-result");
|
|
344
|
+
const pointerMoved = decoded(InputReceipt, "pointer-move");
|
|
345
|
+
const hovered = decoded(InputReceipt, "hover");
|
|
346
|
+
const wheeled = decoded(InputReceipt, "wheel");
|
|
347
|
+
const pressed = decoded(InputReceipt, "press");
|
|
348
|
+
const typed = decoded(InputReceipt, "type");
|
|
349
|
+
const makeTarget = (bound) => ({
|
|
350
|
+
navigate: (request) => checked(NavigateRequest, request, "navigate").pipe(Effect.flatMap((value) => bound.navigate(value.url)), Effect.flatMap((url) => decoded(NavigationResult, "navigate")({ url }))),
|
|
351
|
+
startNavigation: (request) => checked(StartNavigationRequest, request, "navigate").pipe(Effect.flatMap((value) => bound.startNavigation(value.url, value.timeoutMillis)), Effect.map((operation) => ({
|
|
352
|
+
target: operation.target,
|
|
353
|
+
completed: operation.completed.pipe(Effect.flatMap((url) => decoded(NavigationResult, "navigate")({ url }))),
|
|
354
|
+
stop: operation.stop
|
|
355
|
+
}))),
|
|
356
|
+
readText: (request) => checked(ReadTextRequest, request, "read-text").pipe(Effect.flatMap((value) => bound.readText(value.selector)), Effect.flatMap((text) => decoded(TextResult, "read-text")({ text }))),
|
|
357
|
+
click: (request) => checked(ClickRequest, request, "click").pipe(Effect.flatMap((value) => bound.click(value.selector)), Effect.flatMap((url) => action({ url }))),
|
|
358
|
+
fill: (request) => checked(FillRequest, request, "fill").pipe(Effect.flatMap((value) => bound.fill(value.selector, value.value)), Effect.flatMap((url) => action({ url }))),
|
|
359
|
+
scroll: (request) => checked(ScrollRequest, request, "scroll").pipe(Effect.flatMap((value) => bound.scroll(value.deltaX, value.deltaY)), Effect.flatMap((url) => action({ url }))),
|
|
360
|
+
pointerMove: (request) => checked(PointerMoveRequest, request, "pointer-move").pipe(Effect.flatMap((value) => bound.pointerMove(value.to)), Effect.flatMap((input) => pointerMoved({
|
|
361
|
+
...input,
|
|
362
|
+
kind: "pointer-move"
|
|
363
|
+
}))),
|
|
364
|
+
hover: (request) => checked(HoverRequest, request, "hover").pipe(Effect.flatMap((value) => bound.hover(value.selector)), Effect.flatMap((input) => hovered({
|
|
365
|
+
...input,
|
|
366
|
+
kind: "hover"
|
|
367
|
+
}))),
|
|
368
|
+
wheel: (request) => checked(WheelRequest, request, "wheel").pipe(Effect.flatMap((value) => bound.wheel(value.deltaX, value.deltaY, value.at).pipe(Effect.flatMap((input) => wheeled({
|
|
369
|
+
...input,
|
|
370
|
+
kind: "wheel",
|
|
371
|
+
delta: {
|
|
372
|
+
x: value.deltaX,
|
|
373
|
+
y: value.deltaY
|
|
374
|
+
}
|
|
375
|
+
}))))),
|
|
376
|
+
press: (request) => checked(PressRequest, request, "press").pipe(Effect.flatMap((value) => bound.press(value.key, value.modifiers ?? [], value.into)), Effect.flatMap((input) => pressed({
|
|
377
|
+
...input,
|
|
378
|
+
kind: "press"
|
|
379
|
+
}))),
|
|
380
|
+
type: (request) => checked(TypeRequest, request, "type").pipe(Effect.flatMap((value) => bound.type(value.text, value.into)), Effect.flatMap((input) => typed({
|
|
381
|
+
...input,
|
|
382
|
+
kind: "type"
|
|
383
|
+
}))),
|
|
384
|
+
screenshot: (request) => checked(ScreenshotRequest, request, "screenshot").pipe(Effect.flatMap((value) => bound.screenshot(value.fullPage)), Effect.flatMap((bytes) => decoded(ScreenshotResult, "screenshot")({
|
|
385
|
+
mediaType: "image/png",
|
|
386
|
+
bytes: new Uint8Array(bytes)
|
|
387
|
+
})))
|
|
388
|
+
});
|
|
389
|
+
/** A browser-operation failure keeps its meaning when it is reported as an initialization one. */
|
|
390
|
+
const initialization = (reason) => reason === "busy" ? "busy" : reason === "closed" || reason === "disconnected" ? "closed" : reason === "timeout" ? "timeout" : reason === "stale" ? "stale" : reason === "unsupported" ? "unsupported" : reason === "configuration" ? "configuration" : "native";
|
|
391
|
+
const makeSession = (controls, bindings) => {
|
|
392
|
+
const currentTarget = controls.currentTarget.pipe(Effect.map(() => makeTarget(controls.bind())));
|
|
393
|
+
const Wait = Schema.Struct({
|
|
394
|
+
selector: ClickRequest.fields.selector,
|
|
395
|
+
state: Schema.Literals([
|
|
396
|
+
"visible",
|
|
397
|
+
"hidden",
|
|
398
|
+
"attached",
|
|
399
|
+
"detached"
|
|
400
|
+
])
|
|
401
|
+
});
|
|
402
|
+
const navigate = (url) => action({ url });
|
|
403
|
+
const session = {
|
|
404
|
+
failure: bindings.failure,
|
|
405
|
+
bindingDiagnostics: bindings.diagnostics,
|
|
406
|
+
bind: () => makeTarget(controls.bind()),
|
|
407
|
+
currentTarget,
|
|
408
|
+
target: controls.currentTarget,
|
|
409
|
+
observe: (options = {}) => checked(ObservationOptions, options, "observe").pipe(Effect.flatMap((value) => controls.observe({
|
|
410
|
+
...value,
|
|
411
|
+
scope: value.scope ?? "document"
|
|
412
|
+
}))),
|
|
413
|
+
checkpoint: (options = {}) => checked(CheckpointOptions, options, "checkpoint").pipe(Effect.flatMap((value) => controls.checkpoint({
|
|
414
|
+
...value,
|
|
415
|
+
picture: value.picture ?? false
|
|
416
|
+
})), Effect.flatMap(({ picture, ...sampled }) => decoded(Checkpoint, "checkpoint")({
|
|
417
|
+
...sampled,
|
|
418
|
+
...picture === void 0 ? {} : { picture: {
|
|
419
|
+
mediaType: "image/png",
|
|
420
|
+
bytes: new Uint8Array(picture)
|
|
421
|
+
} }
|
|
422
|
+
}))),
|
|
423
|
+
controlFacts: (reference) => checked(ObservedElement, reference, "control-facts").pipe(Effect.flatMap(controls.controlFacts)),
|
|
424
|
+
revalidateElement: (reference) => checked(ObservedElement, reference, "revalidate").pipe(Effect.flatMap((value) => controls.revalidate(value).pipe(Effect.as(value)))),
|
|
425
|
+
clickElement: (reference, admission) => checked(ObservedElement, reference, "click").pipe(Effect.flatMap((value) => controls.bind().click(value, admission?.admit)), Effect.flatMap(navigate)),
|
|
426
|
+
fillElement: (reference, value, admission) => checked(ObservedElement, reference, "fill").pipe(Effect.flatMap((element) => checked(FillRequest.fields.value, value, "fill").pipe(Effect.flatMap((text) => controls.bind().fill(element, text, admission?.admit)))), Effect.flatMap(navigate)),
|
|
427
|
+
hoverElement: (reference, admission) => checked(ObservedElement, reference, "hover").pipe(Effect.flatMap((value) => controls.bind().hover(value, admission?.admit)), Effect.flatMap((input) => hovered({
|
|
428
|
+
...input,
|
|
429
|
+
kind: "hover"
|
|
430
|
+
}))),
|
|
431
|
+
pressElement: (reference, stroke, admission) => checked(ObservedElement, reference, "press").pipe(Effect.flatMap((element) => checked(KeyStroke, stroke, "press").pipe(Effect.flatMap((value) => controls.bind().press(value.key, value.modifiers ?? [], element, admission?.admit)))), Effect.flatMap((input) => pressed({
|
|
432
|
+
...input,
|
|
433
|
+
kind: "press"
|
|
434
|
+
}))),
|
|
435
|
+
typeElement: (reference, text, admission) => checked(ObservedElement, reference, "type").pipe(Effect.flatMap((element) => checked(TypeRequest.fields.text, text, "type").pipe(Effect.flatMap((value) => controls.bind().type(value, element, admission?.admit)))), Effect.flatMap((input) => typed({
|
|
436
|
+
...input,
|
|
437
|
+
kind: "type"
|
|
438
|
+
}))),
|
|
439
|
+
pages: controls.pages,
|
|
440
|
+
frames: controls.frames,
|
|
441
|
+
selectPage: (id) => checked(Identifier, id, "select-page").pipe(Effect.flatMap(controls.selectPage), Effect.andThen(currentTarget)),
|
|
442
|
+
selectFrame: (id) => checked(Identifier, id, "select-frame").pipe(Effect.flatMap(controls.selectFrame), Effect.andThen(currentTarget)),
|
|
443
|
+
createPage: controls.createPage(),
|
|
444
|
+
closePage: (id) => checked(Identifier, id, "close-page").pipe(Effect.flatMap(controls.closePage)),
|
|
445
|
+
resizeViewport: (viewport) => checked(Viewport, viewport, "resize").pipe(Effect.flatMap(controls.resize)),
|
|
446
|
+
waitFor: (request) => checked(Wait, request, "wait").pipe(Effect.flatMap((value) => controls.waitFor(value.selector, value.state))),
|
|
447
|
+
clickAndWait: (request) => checked(ClickRequest, request, "click-and-wait").pipe(Effect.flatMap((value) => controls.clickAndWait(value.selector)), Effect.flatMap((url) => action({ url }))),
|
|
448
|
+
ready: controls.readiness.pipe(Effect.mapError((error) => InitializationError.make({
|
|
449
|
+
operation: "ready",
|
|
450
|
+
step: "session",
|
|
451
|
+
reason: initialization(error.reason)
|
|
452
|
+
})), Effect.flatMap((state) => state._tag === "NotReady" ? Effect.fail(InitializationError.make({
|
|
453
|
+
operation: "ready",
|
|
454
|
+
step: state.step,
|
|
455
|
+
reason: state.reason === "failed" ? "output" : state.reason
|
|
456
|
+
})) : Effect.succeed({ _tag: state._tag })))
|
|
457
|
+
};
|
|
458
|
+
associate(session, controls.capture);
|
|
459
|
+
associatePageControl(session, controls.pageControl);
|
|
460
|
+
return session;
|
|
461
|
+
};
|
|
462
|
+
//#endregion
|
|
336
463
|
//#region src/internal/session/Attachment.ts
|
|
337
464
|
const failure = (reason) => SessionError.make({
|
|
338
465
|
operation: "session-attach",
|
|
@@ -580,28 +707,52 @@ const native = (operation, ticket, body) => Effect.callback((resume) => {
|
|
|
580
707
|
//#endregion
|
|
581
708
|
//#region src/internal/browser/Session.ts
|
|
582
709
|
/** Allocates the session, and therefore owns releasing it. */
|
|
583
|
-
const
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
710
|
+
const providerControls = (client, sessions, reference) => ({
|
|
711
|
+
liveView: (ttl) => issueLiveView(client, reference, ttl),
|
|
712
|
+
verifyReconnect: sessions.retrieve(reference).pipe(Effect.mapError((error) => BrowserError.make({
|
|
713
|
+
operation: "reconnect",
|
|
714
|
+
reason: error.reason
|
|
715
|
+
})), Effect.flatMap((status) => status.status === "RUNNING" ? Effect.void : Effect.fail(BrowserError.make({
|
|
716
|
+
operation: "reconnect",
|
|
717
|
+
reason: "expired"
|
|
718
|
+
}))))
|
|
719
|
+
});
|
|
720
|
+
const ownedRemote = (options) => (local, lifetimeDeadline) => Effect.gen(function* () {
|
|
721
|
+
const client = yield* BrowserbaseClient;
|
|
722
|
+
const sessions = yield* BrowserbaseSessions;
|
|
723
|
+
const acquired = yield* acquireRemote({
|
|
724
|
+
launch: options.launch,
|
|
725
|
+
...options.contextWriter === void 0 ? {} : { contextWriter: options.contextWriter },
|
|
726
|
+
allocationDeadline: lifetimeDeadline,
|
|
727
|
+
...options.onCleanup === void 0 ? {} : { onCleanup: options.onCleanup },
|
|
728
|
+
...options.onAllocationUncertain === void 0 ? {} : { onAllocationUncertain: options.onAllocationUncertain }
|
|
729
|
+
}, local);
|
|
730
|
+
return {
|
|
731
|
+
...acquired,
|
|
732
|
+
...providerControls(client, sessions, acquired.reference)
|
|
733
|
+
};
|
|
734
|
+
});
|
|
590
735
|
/** Borrows a running session: local connection only, and never a release request. */
|
|
591
|
-
const borrowedRemote = (options) => (local) =>
|
|
736
|
+
const borrowedRemote = (options) => (local) => Effect.gen(function* () {
|
|
737
|
+
const client = yield* BrowserbaseClient;
|
|
738
|
+
const sessions = yield* BrowserbaseSessions;
|
|
739
|
+
const acquired = yield* attachRemote(options, local);
|
|
740
|
+
return {
|
|
741
|
+
...acquired,
|
|
742
|
+
...providerControls(client, sessions, acquired.reference)
|
|
743
|
+
};
|
|
744
|
+
});
|
|
592
745
|
/**
|
|
593
746
|
* The one owned browser. Remote allocation, release and terminal observation belong to the
|
|
594
747
|
* canonical control plane; this owner supplies only the local connection's cleanup evidence.
|
|
595
748
|
*/
|
|
596
749
|
const acquireSession = Effect.fnUntraced(function* (limits, options) {
|
|
597
|
-
const engine = bindingImplementation(yield* BrowserbaseBrowserBinding);
|
|
750
|
+
const engine = options.engine ?? bindingImplementation(yield* BrowserbaseBrowserBinding);
|
|
598
751
|
if (engine === void 0) return yield* BrowserError.make({
|
|
599
752
|
operation: "connect",
|
|
600
753
|
reason: "configuration",
|
|
601
754
|
outcome: "undispatched"
|
|
602
755
|
});
|
|
603
|
-
const client = yield* BrowserbaseClient;
|
|
604
|
-
const sessions = yield* BrowserbaseSessions;
|
|
605
756
|
const parentScope = yield* Scope.Scope;
|
|
606
757
|
const bindingLifetime = yield* Scope.fork(parentScope, "sequential");
|
|
607
758
|
const ended = yield* Deferred.make();
|
|
@@ -685,6 +836,7 @@ const acquireSession = Effect.fnUntraced(function* (limits, options) {
|
|
|
685
836
|
owner.fence("closing", "closed");
|
|
686
837
|
handoffToken = void 0;
|
|
687
838
|
activeConnection = void 0;
|
|
839
|
+
Deferred.doneUnsafe(ended, Effect.void);
|
|
688
840
|
}),
|
|
689
841
|
capture: Effect.suspend(() => Effect.forEach([...capture.captureLeases.values()], (lease) => lease.stop, { discard: true })),
|
|
690
842
|
initialization: disposeBindings,
|
|
@@ -705,6 +857,8 @@ const acquireSession = Effect.fnUntraced(function* (limits, options) {
|
|
|
705
857
|
};
|
|
706
858
|
const acquired = yield* options.remote(local, owner.lifetimeDeadline);
|
|
707
859
|
const ref = acquired.reference;
|
|
860
|
+
const release = acquired.release;
|
|
861
|
+
const cleanupResult = acquired.cleanupResult;
|
|
708
862
|
const closeScope = acquired.release.pipe(Effect.ensuring(Deferred.succeed(ended, void 0)), Effect.asVoid);
|
|
709
863
|
const connectionEvents = (connectionLease) => ({
|
|
710
864
|
invalidate: (reason) => {
|
|
@@ -1058,8 +1212,8 @@ const acquireSession = Effect.fnUntraced(function* (limits, options) {
|
|
|
1058
1212
|
capture,
|
|
1059
1213
|
bind,
|
|
1060
1214
|
currentTarget: readSelected,
|
|
1061
|
-
cleanupResult
|
|
1062
|
-
close:
|
|
1215
|
+
cleanupResult,
|
|
1216
|
+
close: release,
|
|
1063
1217
|
observe: (reading = { scope: "document" }) => textBudget("observe", reading.maxTextBytes).pipe(Effect.flatMap((bytes) => owner.guard("observe", (ticket) => observeInside(ticket, bytes, reading.maxControls ?? 32, true, reading.scope)))),
|
|
1064
1218
|
/**
|
|
1065
1219
|
* Passive: not a mutation, so the action observation and the selection are left exactly as
|
|
@@ -1110,19 +1264,23 @@ const acquireSession = Effect.fnUntraced(function* (limits, options) {
|
|
|
1110
1264
|
clickForDownload: (target) => nativeOperation("download-action", (driver, ticket) => driver.clickForDownload(target, ticket), { mutation: true }),
|
|
1111
1265
|
selectFiles: (target, files) => nativeOperation("select-files", (driver, ticket) => driver.selectFiles(target, files, ticket), { mutation: true }),
|
|
1112
1266
|
clickForFileSelection: (target, files) => nativeOperation("file-chooser", (driver, ticket) => driver.clickForFileSelection(target, files, ticket), { mutation: true }),
|
|
1113
|
-
liveView: (ttl) => owner.guard("live-view", () =>
|
|
1267
|
+
liveView: (ttl) => owner.guard("live-view", () => acquired.liveView === void 0 ? Effect.fail(BrowserError.make({
|
|
1268
|
+
operation: "live-view",
|
|
1269
|
+
reason: "unsupported",
|
|
1270
|
+
outcome: "undispatched"
|
|
1271
|
+
})) : acquired.liveView(ttl), {
|
|
1114
1272
|
charge: false,
|
|
1115
1273
|
phases: ["open", "paused"]
|
|
1116
1274
|
}),
|
|
1117
1275
|
beginHandoff: (ttl) => owner.guard("handoff", () => Effect.gen(function* () {
|
|
1118
|
-
if (options.driver.pageControl) return yield* BrowserError.make({
|
|
1276
|
+
if (options.driver.pageControl || acquired.liveView === void 0) return yield* BrowserError.make({
|
|
1119
1277
|
operation: "handoff",
|
|
1120
1278
|
reason: "unsupported",
|
|
1121
1279
|
outcome: "undispatched"
|
|
1122
1280
|
});
|
|
1123
1281
|
if (owner.state.phase === "open") owner.fence("paused", "paused");
|
|
1124
1282
|
handoffToken ??= globalThis.crypto.randomUUID();
|
|
1125
|
-
const view = yield*
|
|
1283
|
+
const view = yield* acquired.liveView(ttl);
|
|
1126
1284
|
return {
|
|
1127
1285
|
token: Redacted.make(handoffToken),
|
|
1128
1286
|
view
|
|
@@ -1178,18 +1336,12 @@ const acquireSession = Effect.fnUntraced(function* (limits, options) {
|
|
|
1178
1336
|
verifyAfter: false
|
|
1179
1337
|
}).pipe(Effect.onError(() => Effect.sync(() => owner.fence("uncertain", "uncertain")))),
|
|
1180
1338
|
reconnect: (operatorReleasedControl) => owner.guard("reconnect", (ticket) => Effect.gen(function* () {
|
|
1181
|
-
if (!options.keepAlive || reconnectTarget === void 0 || !operatorReleasedControl) return yield* BrowserError.make({
|
|
1339
|
+
if (!options.keepAlive || reconnectTarget === void 0 || !operatorReleasedControl || acquired.verifyReconnect === void 0) return yield* BrowserError.make({
|
|
1182
1340
|
operation: "reconnect",
|
|
1183
1341
|
reason: "unsupported",
|
|
1184
1342
|
outcome: "undispatched"
|
|
1185
1343
|
});
|
|
1186
|
-
|
|
1187
|
-
operation: "reconnect",
|
|
1188
|
-
reason: error.reason
|
|
1189
|
-
})))).status !== "RUNNING") return yield* BrowserError.make({
|
|
1190
|
-
operation: "reconnect",
|
|
1191
|
-
reason: "expired"
|
|
1192
|
-
});
|
|
1344
|
+
yield* acquired.verifyReconnect;
|
|
1193
1345
|
owner.state.phase = "acquiring";
|
|
1194
1346
|
const endpoint = yield* connectionUrl("reconnect");
|
|
1195
1347
|
yield* connectNative(endpoint, {
|
|
@@ -1222,336 +1374,6 @@ const acquireSession = Effect.fnUntraced(function* (limits, options) {
|
|
|
1222
1374
|
};
|
|
1223
1375
|
});
|
|
1224
1376
|
//#endregion
|
|
1225
|
-
|
|
1226
|
-
var Browser_exports = /* @__PURE__ */ __exportAll({ BrowserbaseBrowser: () => BrowserbaseBrowser });
|
|
1227
|
-
const checked = (schema, value, operation) => Schema.decodeUnknownEffect(schema)(value, { onExcessProperty: "error" }).pipe(Effect.mapError(() => BrowserError.make({
|
|
1228
|
-
operation,
|
|
1229
|
-
reason: "configuration",
|
|
1230
|
-
outcome: "undispatched"
|
|
1231
|
-
})));
|
|
1232
|
-
const decoded = (schema, operation) => (value) => Schema.decodeUnknownEffect(schema)(value).pipe(Effect.mapError(() => BrowserError.make({
|
|
1233
|
-
operation,
|
|
1234
|
-
reason: "malformed"
|
|
1235
|
-
})));
|
|
1236
|
-
const action = decoded(ActionResult, "action-result");
|
|
1237
|
-
const pointerMoved = decoded(InputReceipt, "pointer-move");
|
|
1238
|
-
const hovered = decoded(InputReceipt, "hover");
|
|
1239
|
-
const wheeled = decoded(InputReceipt, "wheel");
|
|
1240
|
-
const pressed = decoded(InputReceipt, "press");
|
|
1241
|
-
const typed = decoded(InputReceipt, "type");
|
|
1242
|
-
const makeTarget = (bound) => ({
|
|
1243
|
-
navigate: (request) => checked(NavigateRequest, request, "navigate").pipe(Effect.flatMap((value) => bound.navigate(value.url)), Effect.flatMap((url) => decoded(NavigationResult, "navigate")({ url }))),
|
|
1244
|
-
startNavigation: (request) => checked(StartNavigationRequest, request, "navigate").pipe(Effect.flatMap((value) => bound.startNavigation(value.url, value.timeoutMillis)), Effect.map((operation) => ({
|
|
1245
|
-
target: operation.target,
|
|
1246
|
-
completed: operation.completed.pipe(Effect.flatMap((url) => decoded(NavigationResult, "navigate")({ url }))),
|
|
1247
|
-
stop: operation.stop
|
|
1248
|
-
}))),
|
|
1249
|
-
readText: (request) => checked(ReadTextRequest, request, "read-text").pipe(Effect.flatMap((value) => bound.readText(value.selector)), Effect.flatMap((text) => decoded(TextResult, "read-text")({ text }))),
|
|
1250
|
-
click: (request) => checked(ClickRequest, request, "click").pipe(Effect.flatMap((value) => bound.click(value.selector)), Effect.flatMap((url) => action({ url }))),
|
|
1251
|
-
fill: (request) => checked(FillRequest, request, "fill").pipe(Effect.flatMap((value) => bound.fill(value.selector, value.value)), Effect.flatMap((url) => action({ url }))),
|
|
1252
|
-
scroll: (request) => checked(ScrollRequest, request, "scroll").pipe(Effect.flatMap((value) => bound.scroll(value.deltaX, value.deltaY)), Effect.flatMap((url) => action({ url }))),
|
|
1253
|
-
pointerMove: (request) => checked(PointerMoveRequest, request, "pointer-move").pipe(Effect.flatMap((value) => bound.pointerMove(value.to)), Effect.flatMap((input) => pointerMoved({
|
|
1254
|
-
...input,
|
|
1255
|
-
kind: "pointer-move"
|
|
1256
|
-
}))),
|
|
1257
|
-
hover: (request) => checked(HoverRequest, request, "hover").pipe(Effect.flatMap((value) => bound.hover(value.selector)), Effect.flatMap((input) => hovered({
|
|
1258
|
-
...input,
|
|
1259
|
-
kind: "hover"
|
|
1260
|
-
}))),
|
|
1261
|
-
wheel: (request) => checked(WheelRequest, request, "wheel").pipe(Effect.flatMap((value) => bound.wheel(value.deltaX, value.deltaY, value.at).pipe(Effect.flatMap((input) => wheeled({
|
|
1262
|
-
...input,
|
|
1263
|
-
kind: "wheel",
|
|
1264
|
-
delta: {
|
|
1265
|
-
x: value.deltaX,
|
|
1266
|
-
y: value.deltaY
|
|
1267
|
-
}
|
|
1268
|
-
}))))),
|
|
1269
|
-
press: (request) => checked(PressRequest, request, "press").pipe(Effect.flatMap((value) => bound.press(value.key, value.modifiers ?? [], value.into)), Effect.flatMap((input) => pressed({
|
|
1270
|
-
...input,
|
|
1271
|
-
kind: "press"
|
|
1272
|
-
}))),
|
|
1273
|
-
type: (request) => checked(TypeRequest, request, "type").pipe(Effect.flatMap((value) => bound.type(value.text, value.into)), Effect.flatMap((input) => typed({
|
|
1274
|
-
...input,
|
|
1275
|
-
kind: "type"
|
|
1276
|
-
}))),
|
|
1277
|
-
screenshot: (request) => checked(ScreenshotRequest, request, "screenshot").pipe(Effect.flatMap((value) => bound.screenshot(value.fullPage)), Effect.flatMap((bytes) => decoded(ScreenshotResult, "screenshot")({
|
|
1278
|
-
mediaType: "image/png",
|
|
1279
|
-
bytes: new Uint8Array(bytes)
|
|
1280
|
-
})))
|
|
1281
|
-
});
|
|
1282
|
-
/**
|
|
1283
|
-
* Uploaded selection is admitted by the identity of a receipt this package issued for this
|
|
1284
|
-
* exact session, never by a path read off the caller's value. A fabricated receipt has no
|
|
1285
|
-
* issuance record, so an arbitrary server pathname can never become an attached file.
|
|
1286
|
-
*/
|
|
1287
|
-
const selection = (request, reference, operation) => Effect.suspend(() => {
|
|
1288
|
-
const invalid = BrowserError.make({
|
|
1289
|
-
operation,
|
|
1290
|
-
reason: "configuration",
|
|
1291
|
-
outcome: "undispatched"
|
|
1292
|
-
});
|
|
1293
|
-
if (request.selection._tag === "Inline") return checked(InlineFiles, request.selection.files, operation).pipe(Effect.map((files) => files.map((file) => ({
|
|
1294
|
-
_tag: "Inline",
|
|
1295
|
-
name: file.name,
|
|
1296
|
-
mediaType: file.mediaType,
|
|
1297
|
-
bytes: new Uint8Array(file.bytes)
|
|
1298
|
-
}))));
|
|
1299
|
-
const uploads = request.selection.uploads;
|
|
1300
|
-
if (!Array.isArray(uploads) || uploads.length < 1 || uploads.length > 8) return Effect.fail(invalid);
|
|
1301
|
-
const files = [];
|
|
1302
|
-
for (const receipt of uploads) {
|
|
1303
|
-
const issued = issuedUpload(receipt);
|
|
1304
|
-
if (issued === void 0) return Effect.fail(BrowserError.make({
|
|
1305
|
-
operation,
|
|
1306
|
-
reason: "authorization",
|
|
1307
|
-
outcome: "undispatched"
|
|
1308
|
-
}));
|
|
1309
|
-
if (issued.reference.projectId !== reference.projectId || issued.reference.sessionId !== reference.sessionId) return Effect.fail(BrowserError.make({
|
|
1310
|
-
operation,
|
|
1311
|
-
reason: "authorization",
|
|
1312
|
-
outcome: "undispatched"
|
|
1313
|
-
}));
|
|
1314
|
-
files.push({
|
|
1315
|
-
_tag: "Remote",
|
|
1316
|
-
path: issued.remotePath
|
|
1317
|
-
});
|
|
1318
|
-
}
|
|
1319
|
-
return Effect.succeed(files);
|
|
1320
|
-
});
|
|
1321
|
-
/** A browser-operation failure keeps its meaning when it is reported as an initialization one. */
|
|
1322
|
-
const initialization = (reason) => reason === "busy" ? "busy" : reason === "closed" || reason === "disconnected" ? "closed" : reason === "timeout" ? "timeout" : reason === "stale" ? "stale" : reason === "unsupported" ? "unsupported" : reason === "configuration" ? "configuration" : "native";
|
|
1323
|
-
const makeSession = (controls, bindings) => {
|
|
1324
|
-
const currentTarget = controls.currentTarget.pipe(Effect.map(() => makeTarget(controls.bind())));
|
|
1325
|
-
const Wait = Schema.Struct({
|
|
1326
|
-
selector: ClickRequest.fields.selector,
|
|
1327
|
-
state: Schema.Literals([
|
|
1328
|
-
"visible",
|
|
1329
|
-
"hidden",
|
|
1330
|
-
"attached",
|
|
1331
|
-
"detached"
|
|
1332
|
-
])
|
|
1333
|
-
});
|
|
1334
|
-
const navigate = (url) => action({ url });
|
|
1335
|
-
const session = {
|
|
1336
|
-
reference: controls.reference,
|
|
1337
|
-
failure: bindings.failure,
|
|
1338
|
-
bindingDiagnostics: bindings.diagnostics,
|
|
1339
|
-
bind: () => makeTarget(controls.bind()),
|
|
1340
|
-
currentTarget,
|
|
1341
|
-
target: controls.currentTarget,
|
|
1342
|
-
observe: (options = {}) => checked(ObservationOptions, options, "observe").pipe(Effect.flatMap((value) => controls.observe({
|
|
1343
|
-
...value,
|
|
1344
|
-
scope: value.scope ?? "document"
|
|
1345
|
-
}))),
|
|
1346
|
-
checkpoint: (options = {}) => checked(CheckpointOptions, options, "checkpoint").pipe(Effect.flatMap((value) => controls.checkpoint({
|
|
1347
|
-
...value,
|
|
1348
|
-
picture: value.picture ?? false
|
|
1349
|
-
})), Effect.flatMap(({ picture, ...sampled }) => decoded(Checkpoint, "checkpoint")({
|
|
1350
|
-
...sampled,
|
|
1351
|
-
...picture === void 0 ? {} : { picture: {
|
|
1352
|
-
mediaType: "image/png",
|
|
1353
|
-
bytes: new Uint8Array(picture)
|
|
1354
|
-
} }
|
|
1355
|
-
}))),
|
|
1356
|
-
controlFacts: (reference) => checked(ObservedElement, reference, "control-facts").pipe(Effect.flatMap(controls.controlFacts)),
|
|
1357
|
-
revalidateElement: (reference) => checked(ObservedElement, reference, "revalidate").pipe(Effect.flatMap((value) => controls.revalidate(value).pipe(Effect.as(value)))),
|
|
1358
|
-
clickElement: (reference, admission) => checked(ObservedElement, reference, "click").pipe(Effect.flatMap((value) => controls.bind().click(value, admission?.admit)), Effect.flatMap(navigate)),
|
|
1359
|
-
fillElement: (reference, value, admission) => checked(ObservedElement, reference, "fill").pipe(Effect.flatMap((element) => checked(FillRequest.fields.value, value, "fill").pipe(Effect.flatMap((text) => controls.bind().fill(element, text, admission?.admit)))), Effect.flatMap(navigate)),
|
|
1360
|
-
hoverElement: (reference, admission) => checked(ObservedElement, reference, "hover").pipe(Effect.flatMap((value) => controls.bind().hover(value, admission?.admit)), Effect.flatMap((input) => hovered({
|
|
1361
|
-
...input,
|
|
1362
|
-
kind: "hover"
|
|
1363
|
-
}))),
|
|
1364
|
-
pressElement: (reference, stroke, admission) => checked(ObservedElement, reference, "press").pipe(Effect.flatMap((element) => checked(KeyStroke, stroke, "press").pipe(Effect.flatMap((value) => controls.bind().press(value.key, value.modifiers ?? [], element, admission?.admit)))), Effect.flatMap((input) => pressed({
|
|
1365
|
-
...input,
|
|
1366
|
-
kind: "press"
|
|
1367
|
-
}))),
|
|
1368
|
-
typeElement: (reference, text, admission) => checked(ObservedElement, reference, "type").pipe(Effect.flatMap((element) => checked(TypeRequest.fields.text, text, "type").pipe(Effect.flatMap((value) => controls.bind().type(value, element, admission?.admit)))), Effect.flatMap((input) => typed({
|
|
1369
|
-
...input,
|
|
1370
|
-
kind: "type"
|
|
1371
|
-
}))),
|
|
1372
|
-
pages: controls.pages,
|
|
1373
|
-
frames: controls.frames,
|
|
1374
|
-
selectPage: (id) => checked(Identifier, id, "select-page").pipe(Effect.flatMap(controls.selectPage), Effect.andThen(currentTarget)),
|
|
1375
|
-
selectFrame: (id) => checked(Identifier, id, "select-frame").pipe(Effect.flatMap(controls.selectFrame), Effect.andThen(currentTarget)),
|
|
1376
|
-
createPage: controls.createPage(),
|
|
1377
|
-
closePage: (id) => checked(Identifier, id, "close-page").pipe(Effect.flatMap(controls.closePage)),
|
|
1378
|
-
resizeViewport: (viewport) => checked(Viewport, viewport, "resize").pipe(Effect.flatMap(controls.resize)),
|
|
1379
|
-
waitFor: (request) => checked(Wait, request, "wait").pipe(Effect.flatMap((value) => controls.waitFor(value.selector, value.state))),
|
|
1380
|
-
clickAndWait: (request) => checked(ClickRequest, request, "click-and-wait").pipe(Effect.flatMap((value) => controls.clickAndWait(value.selector)), Effect.flatMap((url) => action({ url }))),
|
|
1381
|
-
clickForDownload: (request) => checked(ClickRequest, request, "download-action").pipe(Effect.flatMap((value) => controls.clickForDownload(value.selector)), Effect.flatMap((raw) => decoded(DownloadObservation, "download-action")({
|
|
1382
|
-
...raw,
|
|
1383
|
-
reference: controls.reference
|
|
1384
|
-
}))),
|
|
1385
|
-
selectFiles: (request) => checked(Selector, request.selector, "select-files").pipe(Effect.flatMap((selector) => selection(request, controls.reference, "select-files").pipe(Effect.flatMap((files) => controls.selectFiles(selector, files)))), Effect.flatMap(navigate)),
|
|
1386
|
-
clickForFileSelection: (request) => checked(Selector, request.selector, "file-chooser").pipe(Effect.flatMap((selector) => selection(request, controls.reference, "file-chooser").pipe(Effect.flatMap((files) => controls.clickForFileSelection(selector, files)))), Effect.flatMap(navigate)),
|
|
1387
|
-
ready: controls.readiness.pipe(Effect.mapError((error) => InitializationError.make({
|
|
1388
|
-
operation: "ready",
|
|
1389
|
-
step: "session",
|
|
1390
|
-
reason: initialization(error.reason)
|
|
1391
|
-
})), Effect.flatMap((state) => state._tag === "NotReady" ? Effect.fail(InitializationError.make({
|
|
1392
|
-
operation: "ready",
|
|
1393
|
-
step: state.step,
|
|
1394
|
-
reason: state.reason === "failed" ? "output" : state.reason
|
|
1395
|
-
})) : Effect.succeed({ _tag: state._tag }))),
|
|
1396
|
-
liveView: (ttl = 60) => controls.liveView(ttl),
|
|
1397
|
-
beginHandoff: (ttl = 60) => controls.beginHandoff(ttl),
|
|
1398
|
-
resume: (token, released) => controls.resume(token, released),
|
|
1399
|
-
detach: controls.detach,
|
|
1400
|
-
reconnect: (released) => controls.reconnect(released),
|
|
1401
|
-
close: controls.close,
|
|
1402
|
-
cleanupResult: controls.cleanupResult
|
|
1403
|
-
};
|
|
1404
|
-
associate(session, controls.capture);
|
|
1405
|
-
associatePageControl(session, controls.pageControl);
|
|
1406
|
-
return session;
|
|
1407
|
-
};
|
|
1408
|
-
/**
|
|
1409
|
-
* Credentials, budgets and connection lifetime are fixed when this Layer is built. Building it
|
|
1410
|
-
* allocates nothing and loads no native peer; every acquisition is scoped by its caller.
|
|
1411
|
-
*/
|
|
1412
|
-
var BrowserbaseBrowser = class BrowserbaseBrowser extends Context.Service()("effect-browserbase/Browser") {
|
|
1413
|
-
static layer(options) {
|
|
1414
|
-
return Layer.effect(BrowserbaseBrowser, Effect.gen(function* () {
|
|
1415
|
-
const client = yield* BrowserbaseClient;
|
|
1416
|
-
const sessions = yield* BrowserbaseSessions;
|
|
1417
|
-
const binding = yield* BrowserbaseBrowserBinding;
|
|
1418
|
-
const automation = yield* checked(AutomationOptions, projected(options), "configure");
|
|
1419
|
-
const viewport = yield* checked(Viewport, options.launch.viewport._tag === "Fixed" ? {
|
|
1420
|
-
width: options.launch.viewport.width,
|
|
1421
|
-
height: options.launch.viewport.height
|
|
1422
|
-
} : {
|
|
1423
|
-
width: 1280,
|
|
1424
|
-
height: 720
|
|
1425
|
-
}, "configure");
|
|
1426
|
-
const actionTimeoutMillis = automation.actionTimeoutMillis ?? 1e4;
|
|
1427
|
-
const maxPages = automation.maxPages ?? 10;
|
|
1428
|
-
const pageControl = automation.pageControl ?? false;
|
|
1429
|
-
const popupPolicy = automation.popupPolicy ?? "retain";
|
|
1430
|
-
const dialogPolicy = automation.dialogPolicy ?? "dismiss";
|
|
1431
|
-
if (pageControl && (options.launch.keepAlive === true || popupPolicy === "pause" || dialogPolicy === "pause")) return yield* BrowserError.make({
|
|
1432
|
-
operation: "configure",
|
|
1433
|
-
reason: "unsupported",
|
|
1434
|
-
outcome: "undispatched"
|
|
1435
|
-
});
|
|
1436
|
-
if (options.launch.context?.persist === true && options.contextWriter === void 0) return yield* BrowserError.make({
|
|
1437
|
-
operation: "configure",
|
|
1438
|
-
reason: "context-lease"
|
|
1439
|
-
});
|
|
1440
|
-
if (Object.prototype.hasOwnProperty.call(options, "bootstrap")) return yield* BrowserError.make({
|
|
1441
|
-
operation: "configure",
|
|
1442
|
-
reason: "configuration",
|
|
1443
|
-
outcome: "undispatched"
|
|
1444
|
-
});
|
|
1445
|
-
const driver = {
|
|
1446
|
-
pageControl,
|
|
1447
|
-
viewport,
|
|
1448
|
-
maxPages,
|
|
1449
|
-
popupPolicy,
|
|
1450
|
-
dialogPolicy,
|
|
1451
|
-
preserveViewport: options.launch.viewport._tag !== "Fixed",
|
|
1452
|
-
...automation.initialPage === void 0 ? {} : "targetId" in automation.initialPage ? { initialTargetId: automation.initialPage.targetId } : { newPage: true }
|
|
1453
|
-
};
|
|
1454
|
-
const acquire = Effect.fnUntraced(function* (policy, request = {}) {
|
|
1455
|
-
const fixed = yield* checked(BrowserPolicy, policy, "configure");
|
|
1456
|
-
const plan = yield* preparePlan(request.bootstrap ?? empty);
|
|
1457
|
-
const scope = yield* Scope.fork(yield* Scope.Scope, "sequential");
|
|
1458
|
-
const bindings = yield* makeBindings(plan).pipe(Scope.provide(scope));
|
|
1459
|
-
const bootstrap = compileBootstrap(plan);
|
|
1460
|
-
const acquired = yield* acquireSession({
|
|
1461
|
-
maxActions: fixed.maxActions,
|
|
1462
|
-
maxElapsedMillis: fixed.maxElapsedMillis,
|
|
1463
|
-
actionTimeoutMillis
|
|
1464
|
-
}, {
|
|
1465
|
-
remote: ownedRemote({
|
|
1466
|
-
launch: options.launch,
|
|
1467
|
-
...options.contextWriter === void 0 ? {} : { contextWriter: options.contextWriter },
|
|
1468
|
-
...options.onCleanup === void 0 ? {} : { onCleanup: options.onCleanup },
|
|
1469
|
-
...options.onAllocationUncertain === void 0 ? {} : { onAllocationUncertain: options.onAllocationUncertain }
|
|
1470
|
-
}),
|
|
1471
|
-
keepAlive: options.launch.keepAlive === true,
|
|
1472
|
-
driver: {
|
|
1473
|
-
...driver,
|
|
1474
|
-
...bootstrap === void 0 ? {} : { bootstrap }
|
|
1475
|
-
},
|
|
1476
|
-
connectBindings: bindings.connect,
|
|
1477
|
-
maxReturnedBytes: fixed.maxReturnedBytes
|
|
1478
|
-
}).pipe(Effect.provideService(BrowserbaseClient, client), Effect.provideService(BrowserbaseSessions, sessions), Effect.provideService(BrowserbaseBrowserBinding, binding), Scope.provide(scope));
|
|
1479
|
-
const connected = yield* Effect.cached(acquired.connect.pipe(Effect.map((controls) => makeSession(controls, bindings))));
|
|
1480
|
-
return {
|
|
1481
|
-
reference: acquired.reference,
|
|
1482
|
-
attempt: acquired.lease.attempt,
|
|
1483
|
-
failure: bindings.failure,
|
|
1484
|
-
close: acquired.close,
|
|
1485
|
-
connect: Effect.raceFirst(bindings.failure, acquired.connect.pipe(Effect.andThen(connected))).pipe(Effect.onError(() => acquired.close.pipe(Effect.asVoid)))
|
|
1486
|
-
};
|
|
1487
|
-
});
|
|
1488
|
-
/**
|
|
1489
|
-
* Borrowing a session another process allocated. The launch recipe is not replayed and
|
|
1490
|
-
* no allocation is attempted: the requested target is resolved explicitly, credentials
|
|
1491
|
-
* are fetched fresh because expiry races the caller's own status read, and this scope
|
|
1492
|
-
* disconnects locally without ever requesting release. Detaching and reattaching inside
|
|
1493
|
-
* a borrowed scope is deliberately absent; attaching again is the cross-process path,
|
|
1494
|
-
* and it revalidates the session instead of assuming it is still there.
|
|
1495
|
-
*/
|
|
1496
|
-
const attach = Effect.fnUntraced(function* (reference, request) {
|
|
1497
|
-
const fixed = yield* checked(BrowserPolicy, request.policy, "configure");
|
|
1498
|
-
const plan = yield* preparePlan(request.bootstrap ?? empty);
|
|
1499
|
-
const scope = yield* Scope.fork(yield* Scope.Scope, "sequential");
|
|
1500
|
-
const bindings = yield* makeBindings(plan).pipe(Scope.provide(scope));
|
|
1501
|
-
const bootstrap = compileBootstrap(plan);
|
|
1502
|
-
const targetId = request.target === void 0 ? void 0 : yield* checked(Identifier, request.target.targetId, "configure");
|
|
1503
|
-
const acquired = yield* acquireSession({
|
|
1504
|
-
maxActions: fixed.maxActions,
|
|
1505
|
-
maxElapsedMillis: fixed.maxElapsedMillis,
|
|
1506
|
-
actionTimeoutMillis
|
|
1507
|
-
}, {
|
|
1508
|
-
remote: borrowedRemote({
|
|
1509
|
-
reference,
|
|
1510
|
-
...request.pendingWaitMillis === void 0 ? {} : { pendingWaitMillis: request.pendingWaitMillis },
|
|
1511
|
-
...options.onCleanup === void 0 ? {} : { onCleanup: options.onCleanup }
|
|
1512
|
-
}),
|
|
1513
|
-
keepAlive: false,
|
|
1514
|
-
driver: {
|
|
1515
|
-
...driver,
|
|
1516
|
-
...bootstrap === void 0 ? {} : { bootstrap },
|
|
1517
|
-
newPage: false,
|
|
1518
|
-
preserveViewport: true,
|
|
1519
|
-
...targetId === void 0 ? {} : { initialTargetId: targetId }
|
|
1520
|
-
},
|
|
1521
|
-
maxReturnedBytes: fixed.maxReturnedBytes,
|
|
1522
|
-
connectBindings: bindings.connect
|
|
1523
|
-
}).pipe(Effect.provideService(BrowserbaseClient, client), Effect.provideService(BrowserbaseSessions, sessions), Effect.provideService(BrowserbaseBrowserBinding, binding), Scope.provide(scope));
|
|
1524
|
-
return yield* Effect.raceFirst(bindings.failure, acquired.connect.pipe(Effect.map((controls) => makeSession(controls, bindings)))).pipe(Effect.onError(() => acquired.close.pipe(Effect.asVoid)));
|
|
1525
|
-
});
|
|
1526
|
-
return BrowserbaseBrowser.of({
|
|
1527
|
-
acquire,
|
|
1528
|
-
attach,
|
|
1529
|
-
open: (policy, request) => acquire(policy, request).pipe(Effect.flatMap((acquired) => acquired.connect)),
|
|
1530
|
-
withBrowser: (policy, request, use) => Effect.scoped(Effect.gen(function* () {
|
|
1531
|
-
const session = yield* (yield* acquire(policy, request)).connect;
|
|
1532
|
-
const result = yield* Effect.raceFirst(session.failure, Effect.suspend(() => use(session)));
|
|
1533
|
-
const cleanup = yield* session.close;
|
|
1534
|
-
if (cleanup.remote !== "confirmed" || cleanup.local !== "closed" || cleanup.issues.length > 0) return yield* BrowserError.make({
|
|
1535
|
-
operation: "close",
|
|
1536
|
-
reason: "provider",
|
|
1537
|
-
outcome: "unknown"
|
|
1538
|
-
});
|
|
1539
|
-
return result;
|
|
1540
|
-
}))
|
|
1541
|
-
});
|
|
1542
|
-
}));
|
|
1543
|
-
}
|
|
1544
|
-
};
|
|
1545
|
-
/** Only the automation fields cross the schema boundary; launch and callbacks are separate. */
|
|
1546
|
-
const projected = (options) => ({
|
|
1547
|
-
...options.actionTimeoutMillis === void 0 ? {} : { actionTimeoutMillis: options.actionTimeoutMillis },
|
|
1548
|
-
...options.maxPages === void 0 ? {} : { maxPages: options.maxPages },
|
|
1549
|
-
...options.initialPage === void 0 ? {} : { initialPage: options.initialPage },
|
|
1550
|
-
...options.popupPolicy === void 0 ? {} : { popupPolicy: options.popupPolicy },
|
|
1551
|
-
...options.dialogPolicy === void 0 ? {} : { dialogPolicy: options.dialogPolicy },
|
|
1552
|
-
...options.pageControl === void 0 ? {} : { pageControl: options.pageControl }
|
|
1553
|
-
});
|
|
1554
|
-
//#endregion
|
|
1555
|
-
export { BrowserbaseBrowser as n, Browser_exports as t };
|
|
1377
|
+
export { decoded as a, preparePlan as c, checked as i, compileBootstrap as l, borrowedRemote as n, makeSession as o, ownedRemote as r, makeBindings as s, acquireSession as t };
|
|
1556
1378
|
|
|
1557
|
-
//# sourceMappingURL=
|
|
1379
|
+
//# sourceMappingURL=Session-D4nT9hOO.mjs.map
|