@effect-agent/platform-cloudflare 0.1.0-beta.91 → 0.1.0-beta.93
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/dist/CloudflareThreadClient.d.mts +46 -46
- package/dist/{InteractiveBrowser-DupDtfw2.mjs → InteractiveBrowser-BCS9g0tn.mjs} +117 -106
- package/dist/InteractiveBrowser-BCS9g0tn.mjs.map +1 -0
- package/dist/{InteractiveBrowser-DUE_m12-.d.mts → InteractiveBrowser-BR16UPbF.d.mts} +12 -4
- package/dist/InteractiveBrowser.d.mts +2 -2
- package/dist/InteractiveBrowser.mjs +1 -1
- package/dist/ProtectedBrowser.d.mts +1 -1
- package/dist/ProtectedBrowser.mjs +4 -4
- package/dist/ProtectedBrowser.mjs.map +1 -1
- package/dist/{ThreadObject-CIbmXZCY.d.mts → ThreadObject-BVMSQgqx.d.mts} +28 -28
- package/dist/ThreadObject.d.mts +1 -1
- package/dist/index.d.mts +1 -1
- package/package.json +1 -1
- package/src/InteractiveBrowser.ts +341 -277
- package/src/protected-browser/host.ts +3 -3
- package/src/protected-browser/policy.ts +6 -6
- package/dist/InteractiveBrowser-DupDtfw2.mjs.map +0 -1
|
@@ -1348,41 +1348,15 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
1348
1348
|
} | {
|
|
1349
1349
|
readonly _tag: "HostFailed";
|
|
1350
1350
|
readonly failure: {
|
|
1351
|
-
readonly _tag: "
|
|
1352
|
-
readonly operation: string;
|
|
1351
|
+
readonly _tag: "HostProtocolError";
|
|
1353
1352
|
readonly message: string;
|
|
1354
|
-
readonly cause?: Schema.Json | undefined;
|
|
1355
1353
|
} | {
|
|
1356
|
-
readonly _tag: "
|
|
1357
|
-
readonly operation: string;
|
|
1354
|
+
readonly _tag: "AgentInputError";
|
|
1358
1355
|
readonly message: string;
|
|
1359
|
-
readonly cause?: Schema.Json | undefined;
|
|
1360
|
-
} | {
|
|
1361
|
-
readonly _tag: "AppendConflict";
|
|
1362
|
-
readonly threadId: string;
|
|
1363
|
-
readonly batchId: string;
|
|
1364
|
-
readonly reason: "batch-digest" | "record-identity" | "tail";
|
|
1365
|
-
readonly actualTailSequence?: number | undefined;
|
|
1366
|
-
readonly actualTailDigest?: string | undefined;
|
|
1367
|
-
} | {
|
|
1368
|
-
readonly _tag: "FenceRejected";
|
|
1369
|
-
readonly threadId: string;
|
|
1370
|
-
readonly actualEpoch: number;
|
|
1371
|
-
readonly attemptedEpoch: number;
|
|
1372
|
-
} | {
|
|
1373
|
-
readonly _tag: "ThreadNotMaterialized";
|
|
1374
|
-
readonly threadId: string;
|
|
1375
1356
|
} | {
|
|
1376
|
-
readonly _tag: "
|
|
1377
|
-
readonly operation: string;
|
|
1357
|
+
readonly _tag: "DigestError";
|
|
1378
1358
|
readonly message: string;
|
|
1379
1359
|
readonly cause?: Schema.Json | undefined;
|
|
1380
|
-
} | {
|
|
1381
|
-
readonly _tag: "OperationDenied";
|
|
1382
|
-
readonly operation: "abort" | "awaitSettlement" | "explain" | "observe" | "resolveApproval" | "resolveUnknown" | "retry" | "scanObligations" | "verify" | "wake";
|
|
1383
|
-
readonly reason: string;
|
|
1384
|
-
readonly threadId?: string | undefined;
|
|
1385
|
-
readonly submissionId?: string | undefined;
|
|
1386
1360
|
} | {
|
|
1387
1361
|
readonly _tag: "AdmissionConflict";
|
|
1388
1362
|
readonly threadId: string;
|
|
@@ -1394,27 +1368,10 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
1394
1368
|
readonly _tag: "AdmissionPolicyError";
|
|
1395
1369
|
readonly reason: "occupied" | "refused" | "unavailable";
|
|
1396
1370
|
readonly code: string;
|
|
1397
|
-
} | {
|
|
1398
|
-
readonly _tag: "AgentInputError";
|
|
1399
|
-
readonly message: string;
|
|
1400
|
-
} | {
|
|
1401
|
-
readonly _tag: "DigestError";
|
|
1402
|
-
readonly message: string;
|
|
1403
|
-
readonly cause?: Schema.Json | undefined;
|
|
1404
|
-
} | {
|
|
1405
|
-
readonly _tag: "DurableRuntimeFailpointError";
|
|
1406
|
-
readonly location: "abort:after-intent" | "approval:after-request-append" | "approval:after-suspend" | "checkpoint:after-save" | "checkpoint:before-save" | "claim:after-claim" | "compaction:after-canonical-append" | "compaction:before-canonical-append" | "input:after-canonical-append" | "join:after-canonical-append" | "join:after-claim" | "policy:after-reservation-append" | "policy:before-reservation-append" | "resolve:after-intent" | "run:after-start-append" | "run:before-start-append" | "step:after-step-append" | "subagent:after-admit" | "subagent:after-child-abort-intent" | "subagent:after-child-ready" | "subagent:after-join-append" | "subagent:after-release" | "subagent:after-release-pending" | "subagent:after-request-append" | "subagent:after-reserve" | "subagent:after-sibling-settle" | "subagent:after-start-append" | "subagent:after-suspend" | "subagent:before-join-append" | "submit:after-admit" | "submit:after-materialize" | "terminalize:after-canonical-append" | "terminalize:after-reserve" | "tools:after-prepared-append" | "tools:before-prepared-append" | "turn:after-canonical-append" | "turn:after-response-append" | "turn:after-results-append" | "update:after-canonical-append" | "update:after-delivery-insert" | "update:before-canonical-append" | "update:before-delivery-insert" | "worker:after-completion-append" | "worker:after-origin-append" | "worker:after-report-append" | "worker:after-report-delivery" | "worker:after-source-append" | "worker:after-subtree-append" | "worker:before-completion-append" | "worker:before-origin-append" | "worker:before-report-append" | "worker:before-report-delivery" | "worker:before-source-append" | "worker:before-subtree-append";
|
|
1407
1371
|
} | {
|
|
1408
1372
|
readonly _tag: "SettlementConflict";
|
|
1409
1373
|
readonly submissionId: string;
|
|
1410
1374
|
readonly existingOutcome: "aborted" | "completed" | "failed";
|
|
1411
|
-
} | {
|
|
1412
|
-
readonly _tag: "JoinedToHost";
|
|
1413
|
-
readonly submissionId: string;
|
|
1414
|
-
readonly hostSubmissionId: string;
|
|
1415
|
-
} | {
|
|
1416
|
-
readonly _tag: "HostProtocolError";
|
|
1417
|
-
readonly message: string;
|
|
1418
1375
|
} | {
|
|
1419
1376
|
readonly _tag: "ApprovalConflict";
|
|
1420
1377
|
readonly submissionId: string;
|
|
@@ -1424,11 +1381,54 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
1424
1381
|
readonly _tag: "UnknownResolutionConflict";
|
|
1425
1382
|
readonly submissionId: string;
|
|
1426
1383
|
readonly toolCallId: string;
|
|
1384
|
+
} | {
|
|
1385
|
+
readonly _tag: "JoinedToHost";
|
|
1386
|
+
readonly submissionId: string;
|
|
1387
|
+
readonly hostSubmissionId: string;
|
|
1388
|
+
} | {
|
|
1389
|
+
readonly _tag: "LedgerError";
|
|
1390
|
+
readonly operation: string;
|
|
1391
|
+
readonly message: string;
|
|
1392
|
+
readonly cause?: Schema.Json | undefined;
|
|
1393
|
+
} | {
|
|
1394
|
+
readonly _tag: "ThreadStoreError";
|
|
1395
|
+
readonly operation: string;
|
|
1396
|
+
readonly message: string;
|
|
1397
|
+
readonly cause?: Schema.Json | undefined;
|
|
1398
|
+
} | {
|
|
1399
|
+
readonly _tag: "ThreadNotMaterialized";
|
|
1400
|
+
readonly threadId: string;
|
|
1401
|
+
} | {
|
|
1402
|
+
readonly _tag: "AppendConflict";
|
|
1403
|
+
readonly threadId: string;
|
|
1404
|
+
readonly batchId: string;
|
|
1405
|
+
readonly reason: "batch-digest" | "record-identity" | "tail";
|
|
1406
|
+
readonly actualTailSequence?: number | undefined;
|
|
1407
|
+
readonly actualTailDigest?: string | undefined;
|
|
1408
|
+
} | {
|
|
1409
|
+
readonly _tag: "FenceRejected";
|
|
1410
|
+
readonly threadId: string;
|
|
1411
|
+
readonly actualEpoch: number;
|
|
1412
|
+
readonly attemptedEpoch: number;
|
|
1413
|
+
} | {
|
|
1414
|
+
readonly _tag: "DurableRuntimeFailpointError";
|
|
1415
|
+
readonly location: "abort:after-intent" | "approval:after-request-append" | "approval:after-suspend" | "checkpoint:after-save" | "checkpoint:before-save" | "claim:after-claim" | "compaction:after-canonical-append" | "compaction:before-canonical-append" | "input:after-canonical-append" | "join:after-canonical-append" | "join:after-claim" | "policy:after-reservation-append" | "policy:before-reservation-append" | "resolve:after-intent" | "run:after-start-append" | "run:before-start-append" | "step:after-step-append" | "subagent:after-admit" | "subagent:after-child-abort-intent" | "subagent:after-child-ready" | "subagent:after-join-append" | "subagent:after-release" | "subagent:after-release-pending" | "subagent:after-request-append" | "subagent:after-reserve" | "subagent:after-sibling-settle" | "subagent:after-start-append" | "subagent:after-suspend" | "subagent:before-join-append" | "submit:after-admit" | "submit:after-materialize" | "terminalize:after-canonical-append" | "terminalize:after-reserve" | "tools:after-prepared-append" | "tools:before-prepared-append" | "turn:after-canonical-append" | "turn:after-response-append" | "turn:after-results-append" | "update:after-canonical-append" | "update:after-delivery-insert" | "update:before-canonical-append" | "update:before-delivery-insert" | "worker:after-completion-append" | "worker:after-origin-append" | "worker:after-report-append" | "worker:after-report-delivery" | "worker:after-source-append" | "worker:after-subtree-append" | "worker:before-completion-append" | "worker:before-origin-append" | "worker:before-report-append" | "worker:before-report-delivery" | "worker:before-source-append" | "worker:before-subtree-append";
|
|
1427
1416
|
} | {
|
|
1428
1417
|
readonly _tag: "AdmissionLimitExceeded";
|
|
1429
1418
|
readonly limit: "database-bytes" | "input-bytes" | "queue-depth";
|
|
1430
1419
|
readonly actual: number;
|
|
1431
1420
|
readonly maximum: number;
|
|
1421
|
+
} | {
|
|
1422
|
+
readonly _tag: "DurableAlarmError";
|
|
1423
|
+
readonly operation: string;
|
|
1424
|
+
readonly message: string;
|
|
1425
|
+
readonly cause?: Schema.Json | undefined;
|
|
1426
|
+
} | {
|
|
1427
|
+
readonly _tag: "OperationDenied";
|
|
1428
|
+
readonly operation: "abort" | "awaitSettlement" | "explain" | "observe" | "resolveApproval" | "resolveUnknown" | "retry" | "scanObligations" | "verify" | "wake";
|
|
1429
|
+
readonly reason: string;
|
|
1430
|
+
readonly threadId?: string | undefined;
|
|
1431
|
+
readonly submissionId?: string | undefined;
|
|
1432
1432
|
};
|
|
1433
1433
|
}, Schema.SchemaError, never>;
|
|
1434
1434
|
declare const decodeHostResponse: (input: unknown, options?: import("effect/SchemaAST").ParseOptions) => Effect.Effect<AbortRecorded | ApprovalRecorded | HostFailed | ObservedPage | ProgressCancelled | ProgressObserved | SettlementReached | SubmissionStatusResponse | SubmitSucceeded | UnknownResolutionRecorded, Schema.SchemaError, never>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Clock, Context, Duration, Effect, Layer, Option, Redacted, Ref, Schema, Semaphore, Stream } from "effect";
|
|
1
|
+
import { Clock, Context, Duration, Effect, Layer, Option, Redacted, Ref, Schema, Scope, Semaphore, Stream } from "effect";
|
|
2
2
|
import { PageScreenshotResult } from "effect-agent/page-screenshot";
|
|
3
3
|
import { SandboxImplementation } from "effect-agent/sandbox";
|
|
4
4
|
import { FetchHttpClient, HttpClient, HttpClientRequest } from "effect/unstable/http";
|
|
@@ -226,17 +226,15 @@ var BrowserRunHandoffState = class extends Schema.Class("BrowserRunHandoffState"
|
|
|
226
226
|
handoffId: Schema.optionalKey(Schema.Redacted(BoundedHostText)),
|
|
227
227
|
durationMs: Schema.optionalKey(HandoffDuration)
|
|
228
228
|
}) {};
|
|
229
|
-
/** Host-supplied Browser Run
|
|
229
|
+
/** Host-supplied Browser Run allocation and connection transport. */
|
|
230
230
|
var BrowserRunInteractiveBinding = class BrowserRunInteractiveBinding extends Context.Service()("@effect-agent/platform-cloudflare/BrowserRunInteractiveBinding") {
|
|
231
231
|
static layer(options) {
|
|
232
232
|
return Layer.effect(BrowserRunInteractiveBinding)(Effect.gen(function* () {
|
|
233
233
|
const lifecycle = yield* BrowserRunSessionLifecycle;
|
|
234
234
|
const viewport = options.viewport === void 0 ? void 0 : yield* decodeViewport(options.viewport);
|
|
235
235
|
return {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
...viewport === void 0 ? {} : { defaultViewport: { ...viewport } }
|
|
239
|
-
})),
|
|
236
|
+
acquire: async (keepAliveMillis) => (await puppeteer.acquire(options.browser, { keep_alive: keepAliveMillis })).sessionId,
|
|
237
|
+
connect: async (sessionId) => makeProductionBrowser(await puppeteer.connect(options.browser, sessionId), viewport),
|
|
240
238
|
closeSession: (sessionId) => lifecycle.close(sessionId).pipe(Effect.mapError((cause) => actionError("close", cause)))
|
|
241
239
|
};
|
|
242
240
|
}));
|
|
@@ -631,12 +629,16 @@ const makeProductionPage = (page) => {
|
|
|
631
629
|
setViewport: (viewport) => page.setViewport(viewport)
|
|
632
630
|
};
|
|
633
631
|
};
|
|
634
|
-
const makeProductionContext = (context) => ({
|
|
635
|
-
newPage: async () =>
|
|
632
|
+
const makeProductionContext = (context, viewport) => ({
|
|
633
|
+
newPage: async () => {
|
|
634
|
+
const page = await context.newPage();
|
|
635
|
+
if (viewport !== void 0) await page.setViewport(viewport);
|
|
636
|
+
return makeProductionPage(page);
|
|
637
|
+
},
|
|
636
638
|
close: () => context.close()
|
|
637
639
|
});
|
|
638
|
-
const makeProductionBrowser = (browser) => ({
|
|
639
|
-
createContext: async () => makeProductionContext(await browser.createBrowserContext()),
|
|
640
|
+
const makeProductionBrowser = (browser, viewport) => ({
|
|
641
|
+
createContext: async () => makeProductionContext(await browser.createBrowserContext(), viewport),
|
|
640
642
|
close: () => browser.close(),
|
|
641
643
|
sessionId: () => browser.sessionId(),
|
|
642
644
|
isConnected: () => browser.isConnected(),
|
|
@@ -680,7 +682,7 @@ const causeText = (cause) => {
|
|
|
680
682
|
const isCapacityRefusal = (cause) => /(^|\D)429(\D|$)|browser time limit|capacity|too many concurrent/i.test(causeText(cause));
|
|
681
683
|
const isRemoteClosure = (cause) => /target closed|browser.*closed|session.*closed|connection.*closed|not connected|websocket.*closed/i.test(causeText(cause));
|
|
682
684
|
const snapshotPolicy = Effect.fn("BrowserRunInteractive.snapshotPolicy")(function* (input) {
|
|
683
|
-
const decoded = yield* Schema.decodeEffect(InteractiveBrowserPolicy)(input).pipe(Effect.mapError(() => policyError("The interactive browser policy is malformed")));
|
|
685
|
+
const decoded = yield* Schema.decodeEffect(InteractiveBrowserPolicy, { onExcessProperty: "error" })(input).pipe(Effect.mapError(() => policyError("The interactive browser policy is malformed")));
|
|
684
686
|
if (decoded.network._tag === "PublicWeb") return yield* InteractiveBrowserUnsupportedError.make({
|
|
685
687
|
implementation: browserRunInteractiveImplementation,
|
|
686
688
|
feature: "policy",
|
|
@@ -1019,7 +1021,8 @@ const makeHostService = (binding) => {
|
|
|
1019
1021
|
}).pipe(Effect.flatMap(Schema.decodeUnknownEffect(BrowserRunSessionId)), Effect.mapError(() => actionError("close")), Effect.onError(() => closeWithWarning(browser.close, "Closing an unidentified browser failed")));
|
|
1020
1022
|
yield* terminate(Redacted.make(sessionId), [closeEntry(browser.close, "Closing the local browser connection failed")]);
|
|
1021
1023
|
});
|
|
1022
|
-
const
|
|
1024
|
+
const acquire = Effect.fn("BrowserRunInteractiveHost.acquire")(function* (policy) {
|
|
1025
|
+
const scope = yield* Scope.Scope;
|
|
1023
1026
|
const fixedPolicy = yield* snapshotPolicy(policy);
|
|
1024
1027
|
const startedAt = yield* Effect.clockWith((clock) => clock.currentTimeMillis);
|
|
1025
1028
|
const runCleanup = Effect.runPromiseWith(Context.make(Clock.Clock, yield* Clock.Clock));
|
|
@@ -1033,110 +1036,118 @@ const makeHostService = (binding) => {
|
|
|
1033
1036
|
const lifecycle = { managedTeardownInstalled: false };
|
|
1034
1037
|
const closers = [];
|
|
1035
1038
|
const releaseBeforeManaged = (entry) => Effect.suspend(() => lifecycle.managedTeardownInstalled ? Effect.void : entry.close.pipe(Effect.catchCause(() => Effect.logWarning(entry.warning))));
|
|
1036
|
-
const
|
|
1037
|
-
try: (signal) => closeLateAcquisition(signal, () => binding.
|
|
1039
|
+
const sessionIdValue = yield* Effect.acquireRelease(withinDeadline(Effect.tryPromise({
|
|
1040
|
+
try: (signal) => closeLateAcquisition(signal, () => binding.acquire(keepAliveMillis(fixedPolicy)), (id) => runCleanup(Schema.decodeUnknownEffect(BrowserRunSessionId)(id).pipe(Effect.flatMap((value) => terminate(Redacted.make(value), []))))),
|
|
1038
1041
|
catch: (cause) => isCapacityRefusal(cause) ? InteractiveBrowserCapacityError.make({
|
|
1039
1042
|
implementation: browserRunInteractiveImplementation,
|
|
1040
1043
|
message: "Browser Run has no capacity for a new browser session"
|
|
1041
|
-
}) : protocolError("
|
|
1042
|
-
}), fixedPolicy, startedAt), (
|
|
1043
|
-
state.
|
|
1044
|
-
return lifecycle.managedTeardownInstalled ? Effect.void : closeAcquired(acquired).pipe(Effect.catch(() => Effect.logWarning("Whole-browser cleanup remains unconfirmed")));
|
|
1045
|
-
}, { interruptible: true });
|
|
1046
|
-
closers.push(closeEntry(browser.close, "Closing the interactive browser failed"));
|
|
1047
|
-
const disconnected = () => {
|
|
1048
|
-
state.disconnected.value = true;
|
|
1049
|
-
};
|
|
1050
|
-
yield* Effect.acquireRelease(Effect.try({
|
|
1051
|
-
try: () => browser.onDisconnected(disconnected),
|
|
1052
|
-
catch: (cause) => protocolError("Installing the browser disconnect listener failed", cause)
|
|
1053
|
-
}), () => releaseBeforeManaged(syncCloseEntry(() => browser.offDisconnected(disconnected), "Removing the browser disconnect listener failed")));
|
|
1054
|
-
closers.push(syncCloseEntry(() => browser.offDisconnected(disconnected), "Removing the browser disconnect listener failed"));
|
|
1055
|
-
if (!(yield* Effect.try({
|
|
1056
|
-
try: browser.isConnected,
|
|
1057
|
-
catch: (cause) => protocolError("Reading the Browser Run connection state failed", cause)
|
|
1058
|
-
}))) {
|
|
1044
|
+
}) : protocolError("Acquiring the Browser Run session failed", cause)
|
|
1045
|
+
}).pipe(Effect.flatMap(Schema.decodeUnknownEffect(BrowserRunSessionId)), Effect.catchTag("SchemaError", () => protocolError("The Browser Run session identity was malformed"))), fixedPolicy, startedAt), (id) => Effect.suspend(() => {
|
|
1046
|
+
state.closed.value = true;
|
|
1059
1047
|
state.disconnected.value = true;
|
|
1060
|
-
return
|
|
1061
|
-
}
|
|
1062
|
-
const
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1048
|
+
return lifecycle.managedTeardownInstalled ? Effect.void : terminate(Redacted.make(id), []).pipe(Effect.catch(() => Effect.logWarning("Whole-browser cleanup remains unconfirmed")));
|
|
1049
|
+
}), { interruptible: true });
|
|
1050
|
+
const connect = yield* Effect.cached(Effect.gen(function* () {
|
|
1051
|
+
const browser = yield* Effect.acquireRelease(withinDeadline(Effect.tryPromise({
|
|
1052
|
+
try: (signal) => closeLateAcquisition(signal, () => binding.connect(sessionIdValue), (acquired) => runCleanup(closeAcquired(acquired))),
|
|
1053
|
+
catch: (cause) => protocolError("Connecting to the Browser Run session failed", cause)
|
|
1054
|
+
}), fixedPolicy, startedAt), (acquired) => releaseBeforeManaged(closeEntry(acquired.close, "Closing the local browser connection failed")), { interruptible: true });
|
|
1055
|
+
closers.push(closeEntry(browser.close, "Closing the interactive browser failed"));
|
|
1056
|
+
const disconnected = () => {
|
|
1057
|
+
state.disconnected.value = true;
|
|
1058
|
+
};
|
|
1059
|
+
yield* Effect.acquireRelease(Effect.try({
|
|
1060
|
+
try: () => browser.onDisconnected(disconnected),
|
|
1061
|
+
catch: (cause) => protocolError("Installing the browser disconnect listener failed", cause)
|
|
1062
|
+
}), () => releaseBeforeManaged(syncCloseEntry(() => browser.offDisconnected(disconnected), "Removing the browser disconnect listener failed")));
|
|
1063
|
+
closers.push(syncCloseEntry(() => browser.offDisconnected(disconnected), "Removing the browser disconnect listener failed"));
|
|
1064
|
+
if (!(yield* Effect.try({
|
|
1065
|
+
try: browser.isConnected,
|
|
1066
|
+
catch: (cause) => protocolError("Reading the Browser Run connection state failed", cause)
|
|
1067
|
+
}))) {
|
|
1068
|
+
state.disconnected.value = true;
|
|
1069
|
+
return yield* expiredError();
|
|
1070
|
+
}
|
|
1071
|
+
const context = yield* Effect.acquireRelease(withinDeadline(Effect.tryPromise({
|
|
1072
|
+
try: (signal) => closeLateAcquisition(signal, browser.createContext, (acquired) => acquired.close()),
|
|
1073
|
+
catch: (cause) => state.disconnected.value || isRemoteClosure(cause) ? expiredError() : protocolError("Creating the browser context failed", cause)
|
|
1074
|
+
}), fixedPolicy, startedAt), (acquired) => releaseBeforeManaged(closeEntry(acquired.close, "Closing the interactive browser context failed")), { interruptible: true });
|
|
1075
|
+
closers.push(closeEntry(context.close, "Closing the interactive browser context failed"));
|
|
1076
|
+
const page = yield* Effect.acquireRelease(withinDeadline(Effect.tryPromise({
|
|
1077
|
+
try: (signal) => closeLateAcquisition(signal, context.newPage, (acquired) => acquired.close()),
|
|
1078
|
+
catch: (cause) => state.disconnected.value || isRemoteClosure(cause) ? expiredError() : protocolError("Creating the browser page failed", cause)
|
|
1079
|
+
}), fixedPolicy, startedAt), (acquired) => releaseBeforeManaged(closeEntry(acquired.close, "Closing the interactive browser page failed")), { interruptible: true });
|
|
1080
|
+
closers.push(closeEntry(page.close, "Closing the interactive browser page failed"));
|
|
1081
|
+
yield* withinDeadline(Effect.tryPromise({
|
|
1082
|
+
try: () => page.setBypassServiceWorker(true),
|
|
1083
|
+
catch: (cause) => protocolError("Bypassing browser service workers failed", cause)
|
|
1084
|
+
}), fixedPolicy, startedAt);
|
|
1085
|
+
const requestListener = makeRequestListener(fixedPolicy, state);
|
|
1086
|
+
yield* Effect.acquireRelease(Effect.try({
|
|
1087
|
+
try: () => page.onRequest(requestListener),
|
|
1088
|
+
catch: (cause) => protocolError("Installing the browser request listener failed", cause)
|
|
1089
|
+
}), () => releaseBeforeManaged(syncCloseEntry(() => page.offRequest(requestListener), "Removing the browser request policy failed")));
|
|
1090
|
+
closers.push(syncCloseEntry(() => page.offRequest(requestListener), "Removing the browser request policy failed"));
|
|
1091
|
+
yield* withinDeadline(Effect.tryPromise({
|
|
1092
|
+
try: () => page.setRequestInterception(true),
|
|
1093
|
+
catch: (cause) => protocolError("Installing the browser request policy failed", cause)
|
|
1094
|
+
}), fixedPolicy, startedAt);
|
|
1095
|
+
yield* withinDeadline(awaitPendingRequests(state), fixedPolicy, startedAt);
|
|
1096
|
+
const setupFailure = stateFailure(state);
|
|
1097
|
+
if (setupFailure !== void 0) return yield* setupFailure;
|
|
1098
|
+
const teardown = yield* Effect.uninterruptible(Effect.gen(function* () {
|
|
1099
|
+
const cached = yield* Effect.cached(terminate(Redacted.make(sessionIdValue), closers));
|
|
1100
|
+
lifecycle.managedTeardownInstalled = true;
|
|
1101
|
+
yield* Effect.addFinalizer(() => Effect.uninterruptible(Effect.sync(() => {
|
|
1102
|
+
state.closed.value = true;
|
|
1103
|
+
state.disconnected.value = true;
|
|
1104
|
+
}).pipe(Effect.andThen(cached), Effect.catch(() => Effect.logWarning("Whole-browser cleanup remains unconfirmed")))));
|
|
1105
|
+
return cached;
|
|
1106
|
+
}));
|
|
1107
|
+
const close = Effect.uninterruptible(Effect.sync(() => {
|
|
1097
1108
|
state.closed.value = true;
|
|
1098
1109
|
state.disconnected.value = true;
|
|
1099
|
-
}).pipe(Effect.andThen(
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1110
|
+
}).pipe(Effect.andThen(teardown)));
|
|
1111
|
+
const runtime = yield* makeHandle(page, fixedPolicy, startedAt, state, close);
|
|
1112
|
+
const currentPagePreflight = decodeActionResult(page, fixedPolicy).pipe(Effect.asVoid);
|
|
1113
|
+
const requestFitsSession = (requestedMillis) => remainingMillis(fixedPolicy, startedAt).pipe(Effect.flatMap((remaining) => remaining > 0 && requestedMillis <= remaining ? Effect.void : Effect.fail(policyError("The host browser request exceeds the remaining session time"))));
|
|
1114
|
+
return {
|
|
1115
|
+
handle: runtime.handle,
|
|
1116
|
+
sessionId: Redacted.make(sessionIdValue),
|
|
1117
|
+
resizeViewport: (viewport) => decodeViewport(viewport).pipe(Effect.flatMap((decoded) => runtime.run(Effect.tryPromise({
|
|
1118
|
+
try: () => page.setViewport(decoded),
|
|
1119
|
+
catch: (cause) => {
|
|
1120
|
+
if (state.disconnected.value || isRemoteClosure(cause)) {
|
|
1121
|
+
state.disconnected.value = true;
|
|
1122
|
+
return expiredError();
|
|
1123
|
+
}
|
|
1124
|
+
return protocolError("Resizing the browser viewport failed", cause);
|
|
1125
|
+
}
|
|
1126
|
+
}), currentPagePreflight, false))),
|
|
1127
|
+
getLiveView: (request) => Schema.decodeEffect(BrowserRunLiveViewRequest)(request).pipe(Effect.mapError(() => policyError("The Live View request is malformed")), Effect.flatMap((decoded) => runtime.run(cdpCommand(page, state, "Cloudflare.getLiveView", {
|
|
1128
|
+
mode: decoded.mode,
|
|
1129
|
+
expiresInMs: decoded.expiresInMs
|
|
1130
|
+
}, LiveViewObservation, "Cloudflare returned a malformed Live View response").pipe(Effect.flatMap((observation) => Schema.decodeEffect(BrowserRunLiveViewResult)({ devtoolsFrontendUrl: Redacted.make(observation.devtoolsFrontendUrl) }).pipe(Effect.mapError(() => protocolError("Cloudflare returned a malformed Live View response"))))), currentPagePreflight.pipe(Effect.andThen(requestFitsSession(decoded.expiresInMs)))))),
|
|
1131
|
+
handoff: (request) => Schema.decodeEffect(BrowserRunHandoffRequest)(request).pipe(Effect.mapError(() => policyError("The browser handoff request is malformed")), Effect.flatMap((decoded) => runtime.run(cdpCommand(page, state, "Cloudflare.handoff", {
|
|
1132
|
+
instructions: decoded.instructions,
|
|
1133
|
+
timeout: decoded.timeout
|
|
1134
|
+
}, HandoffObservation, "Cloudflare returned a malformed browser handoff response").pipe(Effect.flatMap((observation) => Schema.decodeEffect(BrowserRunHandoffResult)({ handoffId: Redacted.make(observation.handoffId) }).pipe(Effect.mapError(() => protocolError("Cloudflare returned a malformed browser handoff response"))))), currentPagePreflight.pipe(Effect.andThen(requestFitsSession(decoded.timeout)))))),
|
|
1135
|
+
getHandoffState: runtime.run(cdpCommand(page, state, "Cloudflare.getHandoffState", {}, HandoffStateObservation, "Cloudflare returned a malformed browser handoff state").pipe(Effect.flatMap((observation) => Schema.decodeEffect(BrowserRunHandoffState)({
|
|
1136
|
+
active: observation.active,
|
|
1137
|
+
...observation.handoffId === void 0 ? {} : { handoffId: Redacted.make(observation.handoffId) },
|
|
1138
|
+
...observation.durationMs === void 0 ? {} : { durationMs: observation.durationMs }
|
|
1139
|
+
}).pipe(Effect.mapError(() => protocolError("Cloudflare returned a malformed browser handoff state"))))), currentPagePreflight),
|
|
1140
|
+
close
|
|
1141
|
+
};
|
|
1142
|
+
}).pipe(Effect.provideService(Scope.Scope, scope)));
|
|
1109
1143
|
return {
|
|
1110
|
-
handle: runtime.handle,
|
|
1111
1144
|
sessionId: Redacted.make(sessionIdValue),
|
|
1112
|
-
|
|
1113
|
-
try: () => page.setViewport(decoded),
|
|
1114
|
-
catch: (cause) => {
|
|
1115
|
-
if (state.disconnected.value || isRemoteClosure(cause)) {
|
|
1116
|
-
state.disconnected.value = true;
|
|
1117
|
-
return expiredError();
|
|
1118
|
-
}
|
|
1119
|
-
return protocolError("Resizing the browser viewport failed", cause);
|
|
1120
|
-
}
|
|
1121
|
-
}), currentPagePreflight, false))),
|
|
1122
|
-
getLiveView: (request) => Schema.decodeEffect(BrowserRunLiveViewRequest)(request).pipe(Effect.mapError(() => policyError("The Live View request is malformed")), Effect.flatMap((decoded) => runtime.run(cdpCommand(page, state, "Cloudflare.getLiveView", {
|
|
1123
|
-
mode: decoded.mode,
|
|
1124
|
-
expiresInMs: decoded.expiresInMs
|
|
1125
|
-
}, LiveViewObservation, "Cloudflare returned a malformed Live View response").pipe(Effect.flatMap((observation) => Schema.decodeEffect(BrowserRunLiveViewResult)({ devtoolsFrontendUrl: Redacted.make(observation.devtoolsFrontendUrl) }).pipe(Effect.mapError(() => protocolError("Cloudflare returned a malformed Live View response"))))), currentPagePreflight.pipe(Effect.andThen(requestFitsSession(decoded.expiresInMs)))))),
|
|
1126
|
-
handoff: (request) => Schema.decodeEffect(BrowserRunHandoffRequest)(request).pipe(Effect.mapError(() => policyError("The browser handoff request is malformed")), Effect.flatMap((decoded) => runtime.run(cdpCommand(page, state, "Cloudflare.handoff", {
|
|
1127
|
-
instructions: decoded.instructions,
|
|
1128
|
-
timeout: decoded.timeout
|
|
1129
|
-
}, HandoffObservation, "Cloudflare returned a malformed browser handoff response").pipe(Effect.flatMap((observation) => Schema.decodeEffect(BrowserRunHandoffResult)({ handoffId: Redacted.make(observation.handoffId) }).pipe(Effect.mapError(() => protocolError("Cloudflare returned a malformed browser handoff response"))))), currentPagePreflight.pipe(Effect.andThen(requestFitsSession(decoded.timeout)))))),
|
|
1130
|
-
getHandoffState: runtime.run(cdpCommand(page, state, "Cloudflare.getHandoffState", {}, HandoffStateObservation, "Cloudflare returned a malformed browser handoff state").pipe(Effect.flatMap((observation) => Schema.decodeEffect(BrowserRunHandoffState)({
|
|
1131
|
-
active: observation.active,
|
|
1132
|
-
...observation.handoffId === void 0 ? {} : { handoffId: Redacted.make(observation.handoffId) },
|
|
1133
|
-
...observation.durationMs === void 0 ? {} : { durationMs: observation.durationMs }
|
|
1134
|
-
}).pipe(Effect.mapError(() => protocolError("Cloudflare returned a malformed browser handoff state"))))), currentPagePreflight),
|
|
1135
|
-
close
|
|
1145
|
+
connect: Effect.suspend(() => state.closed.value ? expiredError() : connect)
|
|
1136
1146
|
};
|
|
1137
1147
|
});
|
|
1138
1148
|
return BrowserRunInteractiveHost.of({
|
|
1139
|
-
|
|
1149
|
+
acquire,
|
|
1150
|
+
open: (policy) => acquire(policy).pipe(Effect.flatMap((acquired) => acquired.connect)),
|
|
1140
1151
|
closeSession,
|
|
1141
1152
|
cleanupSemantics: "confirmed-terminal"
|
|
1142
1153
|
});
|
|
@@ -1166,4 +1177,4 @@ const CloudflareInteractiveBrowser = {
|
|
|
1166
1177
|
//#endregion
|
|
1167
1178
|
export { BrowserRunInteractiveHost as a, BrowserRunViewport as c, browserRunInteractiveImplementation as d, browserRunInteractiveLayer as f, BrowserRunSessionLifecycle as h, BrowserRunInteractiveBinding as i, CloudflareInteractiveBrowser as l, BrowserRunCleanupError as m, BrowserRunHandoffResult as n, BrowserRunLiveViewRequest as o, isBrowserRunUndispatchedActionError as p, BrowserRunHandoffState as r, BrowserRunLiveViewResult as s, BrowserRunHandoffRequest as t, browserRunInteractiveHostLayer as u };
|
|
1168
1179
|
|
|
1169
|
-
//# sourceMappingURL=InteractiveBrowser-
|
|
1180
|
+
//# sourceMappingURL=InteractiveBrowser-BCS9g0tn.mjs.map
|