@yielded/agent-platform-cloudflare 0.1.0-beta.166 → 0.1.0-beta.168
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/{Alarm-B0ODr1NE.mjs → Alarm-DxODgAZZ.mjs} +259 -159
- package/dist/Alarm-DxODgAZZ.mjs.map +1 -0
- package/dist/Alarm.d.mts +27 -36
- package/dist/Alarm.mjs +2 -2
- package/dist/BrowserCredentials-C5IWfi7f.d.mts +91 -0
- package/dist/BrowserCredentials.d.mts +2 -91
- package/dist/BrowserRestCapture.mjs +3 -3
- package/dist/BrowserRestCapture.mjs.map +1 -1
- package/dist/BrowserRestCrawl.mjs +6 -6
- package/dist/BrowserRestCrawl.mjs.map +1 -1
- package/dist/{BrowserSession-RfIzxGCH.mjs → BrowserSession-BfNmyayH.mjs} +5 -5
- package/dist/BrowserSession-BfNmyayH.mjs.map +1 -0
- package/dist/{BrowserSession-B969Xg-2.d.mts → BrowserSession-Bx0V1-6_.d.mts} +6 -3
- package/dist/BrowserSession.d.mts +1 -1
- package/dist/BrowserSession.mjs +2 -2
- package/dist/BrowserUse-AstK0jKX.mjs +1467 -0
- package/dist/BrowserUse-AstK0jKX.mjs.map +1 -0
- package/dist/BrowserUse.d.mts +83 -0
- package/dist/BrowserUse.mjs +2 -0
- package/dist/CloudflareBindings.d.mts +8 -1
- package/dist/CloudflareBindings.mjs +2 -2
- package/dist/CloudflareBindings.mjs.map +1 -1
- package/dist/{CloudflareBrowser-5an6m-Qb.mjs → CloudflareBrowser-Vt8qTdYW.mjs} +11 -13
- package/dist/CloudflareBrowser-Vt8qTdYW.mjs.map +1 -0
- package/dist/CloudflareBrowser.mjs +1 -1
- package/dist/CloudflareCodeMode.mjs +1 -1
- package/dist/CloudflareCodeMode.mjs.map +1 -1
- package/dist/{CloudflareConfig-qDrRLofL.d.mts → CloudflareConfig-C9MvPbX8.d.mts} +9 -11
- package/dist/CloudflareConfig.d.mts +1 -1
- package/dist/CloudflareConfig.mjs +9 -12
- package/dist/CloudflareConfig.mjs.map +1 -1
- package/dist/CloudflareMemory.d.mts +3 -25
- package/dist/CloudflareMemory.mjs +33 -31
- package/dist/CloudflareMemory.mjs.map +1 -1
- package/dist/CloudflareScheduling.mjs +8 -15
- package/dist/CloudflareScheduling.mjs.map +1 -1
- package/dist/CloudflareSubscriptions.mjs +9 -16
- package/dist/CloudflareSubscriptions.mjs.map +1 -1
- package/dist/CloudflareThreadClient-CZm0TvUe.mjs +588 -0
- package/dist/CloudflareThreadClient-CZm0TvUe.mjs.map +1 -0
- package/dist/CloudflareThreadClient-QsVzLGGZ.d.mts +2033 -0
- package/dist/CloudflareThreadClient.d.mts +2 -1796
- package/dist/CloudflareThreadClient.mjs +2 -382
- package/dist/{InteractiveBrowser-BbG3kGA9.mjs → InteractiveBrowser-LdKzQeLR.mjs} +18 -19
- package/dist/InteractiveBrowser-LdKzQeLR.mjs.map +1 -0
- package/dist/InteractiveBrowser.mjs +1 -1
- package/dist/{ThreadObject-BcfXbzSO.d.mts → ThreadObject-7s5XnlH-.d.mts} +103 -79
- package/dist/{ThreadObject-DHjrnlX4.mjs → ThreadObject-C0vrcDrw.mjs} +265 -66
- package/dist/ThreadObject-C0vrcDrw.mjs.map +1 -0
- package/dist/ThreadObject.d.mts +2 -2
- package/dist/ThreadObject.mjs +2 -3
- package/dist/WakeScheduler.d.mts +6 -5
- package/dist/WakeScheduler.mjs +15 -11
- package/dist/WakeScheduler.mjs.map +1 -1
- package/dist/index.d.mts +7 -6
- package/dist/index.mjs +7 -6
- package/dist/page-function-CmUCcyNP.mjs +11 -0
- package/dist/page-function-CmUCcyNP.mjs.map +1 -0
- package/dist/{prepared-admission-DMX5p9dC.mjs → prepared-admission-3UUq0zth.mjs} +3 -3
- package/dist/{prepared-admission-DMX5p9dC.mjs.map → prepared-admission-3UUq0zth.mjs.map} +1 -1
- package/package.json +1 -1
- package/src/Alarm.ts +510 -279
- package/src/BrowserRestCapture.ts +2 -2
- package/src/BrowserRestCrawl.ts +10 -14
- package/src/BrowserSession.ts +10 -2
- package/src/BrowserUse.ts +1541 -0
- package/src/CloudflareBindings.ts +13 -4
- package/src/CloudflareCodeMode.ts +1 -1
- package/src/CloudflareConfig.ts +9 -12
- package/src/CloudflareMemory.ts +21 -28
- package/src/CloudflareScheduling.ts +7 -15
- package/src/CloudflareSubscriptions.ts +11 -20
- package/src/CloudflareThreadClient.ts +289 -9
- package/src/InteractiveBrowser.ts +325 -323
- package/src/ThreadObject.ts +172 -52
- package/src/WakeScheduler.ts +29 -18
- package/src/index.ts +1 -0
- package/src/internal/browser-dom.ts +845 -0
- package/src/internal/browser-file-selection.ts +8 -1
- package/src/internal/browser-jev-dom.ts +344 -0
- package/src/internal/browser-quick-action.ts +7 -8
- package/src/internal/browser-session-lifecycle.ts +2 -5
- package/src/internal/crypto.ts +41 -0
- package/src/internal/due-queue.ts +5 -69
- package/src/internal/layers.ts +100 -17
- package/src/internal/live-text-protocol.ts +51 -0
- package/src/internal/live-text.ts +256 -0
- package/src/internal/page-function.ts +12 -0
- package/src/internal/prepared-admission.ts +1 -1
- package/src/internal/progress-wait.ts +19 -24
- package/src/internal/transport.ts +1 -1
- package/dist/Alarm-B0ODr1NE.mjs.map +0 -1
- package/dist/BrowserSession-RfIzxGCH.mjs.map +0 -1
- package/dist/CloudflareBrowser-5an6m-Qb.mjs.map +0 -1
- package/dist/CloudflareThreadClient.mjs.map +0 -1
- package/dist/InteractiveBrowser-BbG3kGA9.mjs.map +0 -1
- package/dist/ThreadObject-DHjrnlX4.mjs.map +0 -1
package/dist/Alarm.d.mts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { DurableObjectContext } from "./CloudflareBindings.mjs";
|
|
2
|
-
import { s as CloudflareDurableRuntimeConfig } from "./CloudflareConfig-
|
|
2
|
+
import { s as CloudflareDurableRuntimeConfig } from "./CloudflareConfig-C9MvPbX8.mjs";
|
|
3
3
|
import { DurableBindingFailure } from "@yielded/agent/agent-registration";
|
|
4
4
|
import { DurableAgentRuntime, DurableRuntimeConfig, DurableWorkerFailure, RecoveryFailure } from "@yielded/agent/durable-agent-runtime";
|
|
5
5
|
import { SubmissionLedger } from "@yielded/agent/submission-ledger";
|
|
6
6
|
import { ThreadProjectionError, ThreadProjectionMaintenance } from "@yielded/agent/thread-projection-maintenance";
|
|
7
7
|
import { WakeScheduler } from "@yielded/agent/wake-scheduler";
|
|
8
8
|
import { Cause, Context, Effect, Layer, Option, Schema, Scope } from "effect";
|
|
9
|
+
import { DurableObjectAlarm } from "effect-cf";
|
|
9
10
|
import { SqlClient } from "effect/sql/SqlClient";
|
|
10
11
|
import { SqlError } from "effect/sql/SqlError";
|
|
11
12
|
declare namespace Alarm_d_exports {
|
|
12
|
-
export { DurableAlarmError, DurableAlarmService, MaintenancePassFailure, MaintenancePassReport, ThreadHostMaintenance, ThreadHostMaintenanceLane, ThreadMaintenance, ThreadMaintenanceFailpoint, ThreadMaintenanceFailpointHandler, ThreadMaintenanceFailpointLocation, ThreadMessageDelivery, ThreadMutationGate, ThreadNativeMaintenance, ThreadPublication, ThreadPublicationService, ThreadRecoveryEvents, ThreadRecoveryFaultEvent, publishCommitted };
|
|
13
|
+
export { DurableAlarmError, DurableAlarmService, MaintenancePassFailure, MaintenancePassReport, ThreadHostMaintenance, ThreadHostMaintenanceLane, ThreadMaintenance, ThreadMaintenanceAlarm, ThreadMaintenanceFailpoint, ThreadMaintenanceFailpointHandler, ThreadMaintenanceFailpointLocation, ThreadMessageDelivery, ThreadMutationGate, ThreadNativeMaintenance, ThreadPublication, ThreadPublicationService, ThreadRecoveryEvents, ThreadRecoveryFaultEvent, publishCommitted };
|
|
13
14
|
}
|
|
14
15
|
declare const DurableAlarmError_base: Schema.Class<DurableAlarmError, Schema.TaggedStruct<"DurableAlarmError", {
|
|
15
16
|
readonly operation: Schema.String;
|
|
@@ -17,10 +18,8 @@ declare const DurableAlarmError_base: Schema.Class<DurableAlarmError, Schema.Tag
|
|
|
17
18
|
readonly cause: Schema.optionalKey<Schema.Defect>;
|
|
18
19
|
}>, Cause.YieldableError>;
|
|
19
20
|
/**
|
|
20
|
-
* The
|
|
21
|
-
* alarm slot
|
|
22
|
-
* and abort re-checks, retry backoff) multiplexes into one idempotent maintenance pass, and
|
|
23
|
-
* the slot always holds the EARLIEST deadline any caller asked for.
|
|
21
|
+
* The maintenance queue owns lease expiry, settlement, retries and dirty generations.
|
|
22
|
+
* Its manual effect-cf alarm shares the native slot with other registered alarms.
|
|
24
23
|
*
|
|
25
24
|
* The alarm invariant (plan §1.4): every committed actionable mutation carries a newer durable
|
|
26
25
|
* maintenance generation and a committed alarm. Stable externally-driven waits may be
|
|
@@ -29,38 +28,27 @@ declare const DurableAlarmError_base: Schema.Class<DurableAlarmError, Schema.Tag
|
|
|
29
28
|
*/
|
|
30
29
|
/** The Durable Object alarm API failed; surfaces on host entry points as a typed refusal. */
|
|
31
30
|
export declare class DurableAlarmError extends DurableAlarmError_base {}
|
|
31
|
+
declare const ThreadMaintenanceAlarm_base: DurableObjectAlarm.AlarmTagClass<ThreadMaintenanceAlarm, "@yielded/agent/thread-maintenance", {
|
|
32
|
+
readonly "@yielded/agent/thread-maintenance": {
|
|
33
|
+
readonly payload: Schema.Null;
|
|
34
|
+
readonly lifecycle: "manual";
|
|
35
|
+
};
|
|
36
|
+
}>;
|
|
37
|
+
/** One manual alarm for the entire consumer-owned maintenance queue. */
|
|
38
|
+
export declare class ThreadMaintenanceAlarm extends ThreadMaintenanceAlarm_base {}
|
|
32
39
|
declare const DurableAlarmService_base: Context.ServiceClass<DurableAlarmService, "@effect-agent/platform-cloudflare/DurableAlarmService", {
|
|
33
|
-
/** The scheduled deadline in epoch milliseconds, if any. */
|
|
34
40
|
readonly scheduled: Effect.Effect<Option.Option<number>, DurableAlarmError>;
|
|
35
|
-
/** Replace the slot with this deadline. */
|
|
36
41
|
readonly scheduleAt: (epochMillis: number) => Effect.Effect<void, DurableAlarmError>;
|
|
37
|
-
/** Keep the EARLIER of the existing deadline and this one (the multiplexing rule). */
|
|
38
42
|
readonly ensureScheduledBy: (epochMillis: number) => Effect.Effect<void, DurableAlarmError>;
|
|
39
|
-
/**
|
|
40
|
-
* Arm an immediate alarm (the durable, coalescing local wake) — DEFERRED while a
|
|
41
|
-
* maintenance pass is executing. Workerd cancels an in-flight alarm handler when a new
|
|
42
|
-
* EARLIER deadline is written during its execution (`requestScheduledAlarm`), and the
|
|
43
|
-
* maintenance pass runs INSIDE the alarm handler: an immediate wake landing mid-pass
|
|
44
|
-
* (a routed port mutation, a sibling's `wake()`, the coordinator's own local notify)
|
|
45
|
-
* would kill the running Attempt — manufacturing an ownership loss no real eviction
|
|
46
|
-
* caused, and routing open uncertain-class Tool Calls into spurious Unknown Outcomes.
|
|
47
|
-
* Deferral is contract-safe: wakes are droppable hints, every mutating entry point
|
|
48
|
-
* pre-arms BEFORE its first durable mutation (the alarm invariant never rests on this
|
|
49
|
-
* call). The pass's durable generation check observes any racing mutation, so the
|
|
50
|
-
* in-memory hint does not need to be flushed after a stable wait is acknowledged.
|
|
51
|
-
*/
|
|
43
|
+
/** Queue-aware promptness hint; idle queues stay idle and retry floors survive. */
|
|
52
44
|
readonly scheduleNow: Effect.Effect<void, DurableAlarmError>;
|
|
53
|
-
/**
|
|
54
|
-
|
|
55
|
-
* executes are droppable promptness hints; correctness rests on the durable generation.
|
|
56
|
-
*/
|
|
57
|
-
readonly withWakesDeferred: <A, E, R>(body: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
|
|
58
|
-
/** Clear the slot; correctness-sensitive clears live in maintenance generation transactions. */
|
|
45
|
+
/** Coalesce droppable inline hints without delaying committed deadlines or their delivery. */
|
|
46
|
+
readonly withHintsDeferred: <A, E, R>(body: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
|
|
59
47
|
readonly cancel: Effect.Effect<void, DurableAlarmError>;
|
|
60
48
|
}>;
|
|
61
|
-
/**
|
|
49
|
+
/** Named maintenance checkpoint; the library owns the shared native alarm slot. */
|
|
62
50
|
export declare class DurableAlarmService extends DurableAlarmService_base {
|
|
63
|
-
static readonly layer: Layer.Layer<DurableAlarmService, never, DurableObjectContext | SqlClient>;
|
|
51
|
+
static readonly layer: Layer.Layer<DurableAlarmService, never, DurableObjectContext | SqlClient | ThreadMaintenanceAlarm>;
|
|
64
52
|
}
|
|
65
53
|
declare const MaintenancePassReport_base: Schema.Class<MaintenancePassReport, Schema.Struct<{
|
|
66
54
|
/** `caught-up` ran no runtime work (publication may be pending); `actionable` ran recovery. */
|
|
@@ -74,7 +62,6 @@ declare const MaintenancePassReport_base: Schema.Class<MaintenancePassReport, Sc
|
|
|
74
62
|
/** `rearmed` for dirty/autonomous work, `cleared` for stable waits or settlement. */
|
|
75
63
|
readonly alarm: Schema.Literals<readonly ["rearmed", "cleared"]>;
|
|
76
64
|
}>, {}>;
|
|
77
|
-
/** What one maintenance pass did — auditable evidence mirroring `NodeDurableHost`'s report. */
|
|
78
65
|
export declare class MaintenancePassReport extends MaintenancePassReport_base {}
|
|
79
66
|
/** Fault boundaries around every maintenance-owned durable mutation. */
|
|
80
67
|
export type ThreadMaintenanceFailpointLocation = "maintenance:dirty:before" | "maintenance:dirty:after" | "maintenance:mutation:armed" | "maintenance:mutation:finished" | "maintenance:ensure:before" | "maintenance:ensure:after" | "maintenance:begin:before" | "maintenance:begin:after" | "maintenance:select:before" | "maintenance:select:after" | "maintenance:binding-retry:before" | "maintenance:binding-retry:after" | "maintenance:recovery-status:before" | "maintenance:recovery-status:after" | "maintenance:retry:before" | "maintenance:retry:after" | "maintenance:checkpoint:before" | "maintenance:checkpoint:after" | "maintenance:finish:before" | "maintenance:finish:after";
|
|
@@ -157,6 +144,8 @@ export declare const ThreadHostMaintenance: Context.Reference<{
|
|
|
157
144
|
/** @internal Framework handlers are separate from host registrations and their namespace. */
|
|
158
145
|
export declare const ThreadNativeMaintenance: Context.Reference<{
|
|
159
146
|
readonly lanes: ReadonlyArray<ThreadHostMaintenanceLane>;
|
|
147
|
+
/** Exact runtime built over a single-Thread placement; never apply to a replacement. */
|
|
148
|
+
readonly singleThreadRuntime?: DurableAgentRuntime["Service"];
|
|
160
149
|
}>;
|
|
161
150
|
/** @internal Required host publication only; native lifecycle facts use a maintenance lane. */
|
|
162
151
|
export declare const publishCommitted: Effect.Effect<void, never, ThreadPublication>;
|
|
@@ -186,8 +175,9 @@ declare const ThreadRecoveryEvents_base: Context.ServiceClass<ThreadRecoveryEven
|
|
|
186
175
|
*/
|
|
187
176
|
export declare class ThreadRecoveryEvents extends ThreadRecoveryEvents_base {}
|
|
188
177
|
declare const ThreadMutationGate_base: Context.ServiceClass<ThreadMutationGate, "@effect-agent/platform-cloudflare/internal/ThreadMutationGate", {
|
|
189
|
-
/** Commit source facts and their scheduling intent together.
|
|
190
|
-
*
|
|
178
|
+
/** Commit source facts and their scheduling intent together. Mutate from this callback's
|
|
179
|
+
* fiber, or use an explicit child transaction. The flush runs before native commit;
|
|
180
|
+
* failed or interrupted transactions discard their queue view. */
|
|
191
181
|
readonly withTransaction: <A, E, R>(body: Effect.Effect<A, E, R>) => Effect.Effect<A, E | SqlError, R>;
|
|
192
182
|
readonly withMutation: <A, E, R>(body: Effect.Effect<A, E, R>,
|
|
193
183
|
/**
|
|
@@ -221,7 +211,7 @@ declare const ThreadMutationGate_base: Context.ServiceClass<ThreadMutationGate,
|
|
|
221
211
|
readonly withSnapshot: <A, E, R>(body: (active: number) => Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
|
|
222
212
|
}>;
|
|
223
213
|
export declare class ThreadMutationGate extends ThreadMutationGate_base {
|
|
224
|
-
static readonly layer: Layer.Layer<ThreadMutationGate, DurableAlarmError, CloudflareDurableRuntimeConfig | DurableObjectContext | SqlClient | ThreadMaintenanceFailpoint>;
|
|
214
|
+
static readonly layer: Layer.Layer<ThreadMutationGate, DurableAlarmError, CloudflareDurableRuntimeConfig | DurableObjectContext | SqlClient | ThreadMaintenanceAlarm | ThreadMaintenanceFailpoint>;
|
|
225
215
|
}
|
|
226
216
|
export type MaintenancePassFailure = DurableWorkerFailure | DurableBindingFailure | DurableAlarmError | ThreadProjectionError;
|
|
227
217
|
declare const ThreadMaintenance_base: Context.ServiceClass<ThreadMaintenance, "@effect-agent/platform-cloudflare/ThreadMaintenance", {
|
|
@@ -249,7 +239,8 @@ declare const ThreadMaintenance_base: Context.ServiceClass<ThreadMaintenance, "@
|
|
|
249
239
|
* 2. Reconcile before each head Attempt, then checkpoint only the observed generation. A racing
|
|
250
240
|
* producer keeps its generation dirty and immediately eligible. Quiescent native retries
|
|
251
241
|
* retain their durable backoff.
|
|
252
|
-
* 3. Admit
|
|
242
|
+
* 3. Admit one Attempt for a single-Thread runtime, or at most two independent Thread
|
|
243
|
+
* Attempts for a shared host, with one active head per Thread.
|
|
253
244
|
* Keep native and delivery admission open together while finite waves remain active, so
|
|
254
245
|
* fresh replies and abort controls can progress during unrelated cleanup. Close atomically
|
|
255
246
|
* at quiescence, or at the original ten-minute yield deadline, then join admitted waves.
|
|
@@ -260,7 +251,7 @@ declare const ThreadMaintenance_base: Context.ServiceClass<ThreadMaintenance, "@
|
|
|
260
251
|
* The whole event retains one fourteen-minute cooperative timeout.
|
|
261
252
|
*/
|
|
262
253
|
export declare class ThreadMaintenance extends ThreadMaintenance_base {
|
|
263
|
-
static readonly layer: Layer.Layer<ThreadMaintenance, DurableAlarmError, ThreadMutationGate | ThreadPublication | ThreadProjectionMaintenance | DurableAgentRuntime | DurableRuntimeConfig | SubmissionLedger | WakeScheduler | DurableAlarmService | ThreadMaintenanceFailpoint | CloudflareDurableRuntimeConfig | DurableObjectContext | SqlClient>;
|
|
254
|
+
static readonly layer: Layer.Layer<ThreadMaintenance, DurableAlarmError, ThreadMutationGate | ThreadPublication | ThreadProjectionMaintenance | DurableAgentRuntime | DurableRuntimeConfig | SubmissionLedger | WakeScheduler | DurableAlarmService | ThreadMaintenanceAlarm | ThreadMaintenanceFailpoint | CloudflareDurableRuntimeConfig | DurableObjectContext | SqlClient>;
|
|
264
255
|
}
|
|
265
256
|
//#endregion
|
|
266
257
|
export { Alarm_d_exports as t };
|
package/dist/Alarm.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as ThreadHostMaintenance, c as
|
|
2
|
-
export { DurableAlarmError, DurableAlarmService, MaintenancePassReport, ThreadHostMaintenance, ThreadMaintenance, ThreadMaintenanceFailpoint, ThreadMessageDelivery, ThreadMutationGate, ThreadNativeMaintenance, ThreadPublication, ThreadRecoveryEvents, ThreadRecoveryFaultEvent, publishCommitted };
|
|
1
|
+
import { a as ThreadHostMaintenance, c as ThreadMaintenanceFailpoint, d as ThreadNativeMaintenance, f as ThreadPublication, h as publishCommitted, i as MaintenancePassReport, l as ThreadMessageDelivery, m as ThreadRecoveryFaultEvent, n as DurableAlarmError, o as ThreadMaintenance, p as ThreadRecoveryEvents, r as DurableAlarmService, s as ThreadMaintenanceAlarm, u as ThreadMutationGate } from "./Alarm-DxODgAZZ.mjs";
|
|
2
|
+
export { DurableAlarmError, DurableAlarmService, MaintenancePassReport, ThreadHostMaintenance, ThreadMaintenance, ThreadMaintenanceAlarm, ThreadMaintenanceFailpoint, ThreadMessageDelivery, ThreadMutationGate, ThreadNativeMaintenance, ThreadPublication, ThreadRecoveryEvents, ThreadRecoveryFaultEvent, publishCommitted };
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { Context, Effect, Schema } from "effect";
|
|
2
|
+
declare namespace BrowserCredentials_d_exports {
|
|
3
|
+
export { BrowserCredentialAccess, BrowserCredentialMaterial, CardCredential, CredentialAccessError, CredentialAccessRequest, CredentialDispatch, CredentialFieldRole, CredentialFillError, CredentialFillResult, CredentialKind, CredentialOrigin, CredentialTarget, FillCredentialRequest, LoginCredential };
|
|
4
|
+
}
|
|
5
|
+
declare const CredentialKind: Schema.Literals<readonly ["login", "card"]>;
|
|
6
|
+
declare const CredentialFieldRole: Schema.Literals<readonly ["username", "password", "card-name", "card-number", "card-expiry", "card-expiry-month", "card-expiry-year", "card-security-code"]>;
|
|
7
|
+
/** Canonical HTTPS origins, including non-default ports. Grants must match exactly. */
|
|
8
|
+
declare const CredentialOrigin: Schema.String;
|
|
9
|
+
declare const CredentialTarget_base: Schema.Class<CredentialTarget, Schema.Struct<{
|
|
10
|
+
readonly topOrigin: Schema.String;
|
|
11
|
+
readonly frameOrigin: Schema.String;
|
|
12
|
+
readonly recipientOrigin: Schema.String;
|
|
13
|
+
}>, {}>;
|
|
14
|
+
declare class CredentialTarget extends CredentialTarget_base {}
|
|
15
|
+
declare const FillCredentialRequest_base: Schema.Class<FillCredentialRequest, Schema.Struct<{
|
|
16
|
+
readonly credential: Schema.NonEmptyString;
|
|
17
|
+
readonly kind: Schema.Literals<readonly ["login", "card"]>;
|
|
18
|
+
readonly frame: Schema.optionalKey<Schema.$Array<Schema.NonEmptyString>>;
|
|
19
|
+
readonly fields: Schema.$Array<Schema.Struct<{
|
|
20
|
+
readonly selector: Schema.NonEmptyString;
|
|
21
|
+
readonly role: Schema.Literals<readonly ["username", "password", "card-name", "card-number", "card-expiry", "card-expiry-month", "card-expiry-year", "card-security-code"]>;
|
|
22
|
+
}>>;
|
|
23
|
+
}>, {}>;
|
|
24
|
+
/** Selectors identify one native form. Roles explicitly select material; no field inference occurs. */
|
|
25
|
+
declare class FillCredentialRequest extends FillCredentialRequest_base {}
|
|
26
|
+
/** Host-only material. Never return or encode it through a Tool, log, trace, or checkpoint. */
|
|
27
|
+
declare const LoginCredential: Schema.TaggedStruct<"LoginCredential", {
|
|
28
|
+
readonly username: Schema.Redacted<Schema.NonEmptyString>;
|
|
29
|
+
readonly password: Schema.Redacted<Schema.NonEmptyString>;
|
|
30
|
+
}>;
|
|
31
|
+
/** Security codes are transient; the host must not persist them. */
|
|
32
|
+
declare const CardCredential: Schema.TaggedStruct<"CardCredential", {
|
|
33
|
+
readonly name: Schema.Redacted<Schema.NonEmptyString>;
|
|
34
|
+
readonly number: Schema.Redacted<Schema.String>;
|
|
35
|
+
readonly expiry: Schema.Redacted<Schema.NonEmptyString>;
|
|
36
|
+
readonly expiryMonth: Schema.Redacted<Schema.String>;
|
|
37
|
+
readonly expiryYear: Schema.Redacted<Schema.String>;
|
|
38
|
+
readonly securityCode: Schema.optionalKey<Schema.Redacted<Schema.String>>;
|
|
39
|
+
}>;
|
|
40
|
+
declare const BrowserCredentialMaterial: Schema.Union<readonly [Schema.TaggedStruct<"LoginCredential", {
|
|
41
|
+
readonly username: Schema.Redacted<Schema.NonEmptyString>;
|
|
42
|
+
readonly password: Schema.Redacted<Schema.NonEmptyString>;
|
|
43
|
+
}>, Schema.TaggedStruct<"CardCredential", {
|
|
44
|
+
readonly name: Schema.Redacted<Schema.NonEmptyString>;
|
|
45
|
+
readonly number: Schema.Redacted<Schema.String>;
|
|
46
|
+
readonly expiry: Schema.Redacted<Schema.NonEmptyString>;
|
|
47
|
+
readonly expiryMonth: Schema.Redacted<Schema.String>;
|
|
48
|
+
readonly expiryYear: Schema.Redacted<Schema.String>;
|
|
49
|
+
readonly securityCode: Schema.optionalKey<Schema.Redacted<Schema.String>>;
|
|
50
|
+
}>]>;
|
|
51
|
+
type BrowserCredentialMaterial = typeof BrowserCredentialMaterial.Type;
|
|
52
|
+
declare const CredentialAccessError_base: Schema.Class<CredentialAccessError, Schema.TaggedStruct<"CredentialAccessError", {
|
|
53
|
+
readonly reason: Schema.Literals<readonly ["denied", "missing-credential", "needs-attention", "busy", "resolver"]>;
|
|
54
|
+
}>, import("effect/Cause").YieldableError>;
|
|
55
|
+
declare class CredentialAccessError extends CredentialAccessError_base {}
|
|
56
|
+
interface CredentialAccessRequest {
|
|
57
|
+
readonly credential: string;
|
|
58
|
+
readonly kind: typeof CredentialKind.Type;
|
|
59
|
+
readonly target: CredentialTarget;
|
|
60
|
+
readonly roles: ReadonlyArray<typeof CredentialFieldRole.Type>;
|
|
61
|
+
}
|
|
62
|
+
declare const BrowserCredentialAccess_base: Context.ServiceClass<BrowserCredentialAccess, "@effect-agent/platform-cloudflare/BrowserCredentialAccess", {
|
|
63
|
+
readonly authorize: (request: CredentialAccessRequest) => Effect.Effect<void, CredentialAccessError>;
|
|
64
|
+
readonly resolve: (request: CredentialAccessRequest) => Effect.Effect<BrowserCredentialMaterial, CredentialAccessError>;
|
|
65
|
+
}>;
|
|
66
|
+
/**
|
|
67
|
+
* Invocation-owned authority. Derive caller/ownership from the host, not the public credential
|
|
68
|
+
* identifier. Authorize the actual merchant, frame, recipient, roles, and side effects of filling.
|
|
69
|
+
* Repeated checks must consult current grants. Never log or trace resolved material.
|
|
70
|
+
* Bind caller identity and identifier-to-vault-item selection for the whole invocation; an alias
|
|
71
|
+
* changing between resolve and authorize must never authorize different material.
|
|
72
|
+
*/
|
|
73
|
+
declare class BrowserCredentialAccess extends BrowserCredentialAccess_base {}
|
|
74
|
+
declare const CredentialDispatch: Schema.Literals<readonly ["not-dispatched", "possibly-dispatched", "dispatched"]>;
|
|
75
|
+
declare const CredentialFillResult_base: Schema.Class<CredentialFillResult, Schema.Struct<{
|
|
76
|
+
readonly dispatch: Schema.Literal<"dispatched">;
|
|
77
|
+
readonly filled: Schema.Natural;
|
|
78
|
+
}>, {}>;
|
|
79
|
+
/** Filled counts acknowledged assignments, not authentication, submission, or website acceptance. */
|
|
80
|
+
declare class CredentialFillResult extends CredentialFillResult_base {}
|
|
81
|
+
declare const CredentialFillError_base: Schema.Class<CredentialFillError, Schema.TaggedStruct<"CredentialFillError", {
|
|
82
|
+
readonly reason: Schema.Literals<readonly ["denied", "missing-credential", "stale-target", "unsupported", "needs-attention", "busy", "provider", "resolver", "timeout"]>;
|
|
83
|
+
readonly dispatch: Schema.Literals<readonly ["not-dispatched", "possibly-dispatched", "dispatched"]>;
|
|
84
|
+
readonly filled: Schema.Natural;
|
|
85
|
+
readonly cleanup: Schema.Literals<readonly ["not-requested", "confirmed", "unconfirmed"]>;
|
|
86
|
+
}>, import("effect/Cause").YieldableError>;
|
|
87
|
+
/** Content-free evidence. A lost reply never authorizes a retry or proves that no write occurred. */
|
|
88
|
+
declare class CredentialFillError extends CredentialFillError_base {}
|
|
89
|
+
//#endregion
|
|
90
|
+
export { CredentialAccessError as a, CredentialFieldRole as c, CredentialKind as d, CredentialOrigin as f, LoginCredential as h, CardCredential as i, CredentialFillError as l, FillCredentialRequest as m, BrowserCredentialMaterial as n, CredentialAccessRequest as o, CredentialTarget as p, BrowserCredentials_d_exports as r, CredentialDispatch as s, BrowserCredentialAccess as t, CredentialFillResult as u };
|
|
91
|
+
//# sourceMappingURL=BrowserCredentials-C5IWfi7f.d.mts.map
|
|
@@ -1,91 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export { BrowserCredentialAccess, BrowserCredentialMaterial, CardCredential, CredentialAccessError, CredentialAccessRequest, CredentialDispatch, CredentialFieldRole, CredentialFillError, CredentialFillResult, CredentialKind, CredentialOrigin, CredentialTarget, FillCredentialRequest, LoginCredential };
|
|
4
|
-
}
|
|
5
|
-
export declare const CredentialKind: Schema.Literals<readonly ["login", "card"]>;
|
|
6
|
-
export declare const CredentialFieldRole: Schema.Literals<readonly ["username", "password", "card-name", "card-number", "card-expiry", "card-expiry-month", "card-expiry-year", "card-security-code"]>;
|
|
7
|
-
/** Canonical HTTPS origins, including non-default ports. Grants must match exactly. */
|
|
8
|
-
export declare const CredentialOrigin: Schema.String;
|
|
9
|
-
declare const CredentialTarget_base: Schema.Class<CredentialTarget, Schema.Struct<{
|
|
10
|
-
readonly topOrigin: Schema.String;
|
|
11
|
-
readonly frameOrigin: Schema.String;
|
|
12
|
-
readonly recipientOrigin: Schema.String;
|
|
13
|
-
}>, {}>;
|
|
14
|
-
export declare class CredentialTarget extends CredentialTarget_base {}
|
|
15
|
-
declare const FillCredentialRequest_base: Schema.Class<FillCredentialRequest, Schema.Struct<{
|
|
16
|
-
readonly credential: Schema.NonEmptyString;
|
|
17
|
-
readonly kind: Schema.Literals<readonly ["login", "card"]>;
|
|
18
|
-
readonly frame: Schema.optionalKey<Schema.$Array<Schema.NonEmptyString>>;
|
|
19
|
-
readonly fields: Schema.$Array<Schema.Struct<{
|
|
20
|
-
readonly selector: Schema.NonEmptyString;
|
|
21
|
-
readonly role: Schema.Literals<readonly ["username", "password", "card-name", "card-number", "card-expiry", "card-expiry-month", "card-expiry-year", "card-security-code"]>;
|
|
22
|
-
}>>;
|
|
23
|
-
}>, {}>;
|
|
24
|
-
/** Selectors identify one native form. Roles explicitly select material; no field inference occurs. */
|
|
25
|
-
export declare class FillCredentialRequest extends FillCredentialRequest_base {}
|
|
26
|
-
/** Host-only material. Never return or encode it through a Tool, log, trace, or checkpoint. */
|
|
27
|
-
export declare const LoginCredential: Schema.TaggedStruct<"LoginCredential", {
|
|
28
|
-
readonly username: Schema.Redacted<Schema.NonEmptyString>;
|
|
29
|
-
readonly password: Schema.Redacted<Schema.NonEmptyString>;
|
|
30
|
-
}>;
|
|
31
|
-
/** Security codes are transient; the host must not persist them. */
|
|
32
|
-
export declare const CardCredential: Schema.TaggedStruct<"CardCredential", {
|
|
33
|
-
readonly name: Schema.Redacted<Schema.NonEmptyString>;
|
|
34
|
-
readonly number: Schema.Redacted<Schema.String>;
|
|
35
|
-
readonly expiry: Schema.Redacted<Schema.NonEmptyString>;
|
|
36
|
-
readonly expiryMonth: Schema.Redacted<Schema.String>;
|
|
37
|
-
readonly expiryYear: Schema.Redacted<Schema.String>;
|
|
38
|
-
readonly securityCode: Schema.optionalKey<Schema.Redacted<Schema.String>>;
|
|
39
|
-
}>;
|
|
40
|
-
export declare const BrowserCredentialMaterial: Schema.Union<readonly [Schema.TaggedStruct<"LoginCredential", {
|
|
41
|
-
readonly username: Schema.Redacted<Schema.NonEmptyString>;
|
|
42
|
-
readonly password: Schema.Redacted<Schema.NonEmptyString>;
|
|
43
|
-
}>, Schema.TaggedStruct<"CardCredential", {
|
|
44
|
-
readonly name: Schema.Redacted<Schema.NonEmptyString>;
|
|
45
|
-
readonly number: Schema.Redacted<Schema.String>;
|
|
46
|
-
readonly expiry: Schema.Redacted<Schema.NonEmptyString>;
|
|
47
|
-
readonly expiryMonth: Schema.Redacted<Schema.String>;
|
|
48
|
-
readonly expiryYear: Schema.Redacted<Schema.String>;
|
|
49
|
-
readonly securityCode: Schema.optionalKey<Schema.Redacted<Schema.String>>;
|
|
50
|
-
}>]>;
|
|
51
|
-
export type BrowserCredentialMaterial = typeof BrowserCredentialMaterial.Type;
|
|
52
|
-
declare const CredentialAccessError_base: Schema.Class<CredentialAccessError, Schema.TaggedStruct<"CredentialAccessError", {
|
|
53
|
-
readonly reason: Schema.Literals<readonly ["denied", "missing-credential", "needs-attention", "busy", "resolver"]>;
|
|
54
|
-
}>, import("effect/Cause").YieldableError>;
|
|
55
|
-
export declare class CredentialAccessError extends CredentialAccessError_base {}
|
|
56
|
-
export interface CredentialAccessRequest {
|
|
57
|
-
readonly credential: string;
|
|
58
|
-
readonly kind: typeof CredentialKind.Type;
|
|
59
|
-
readonly target: CredentialTarget;
|
|
60
|
-
readonly roles: ReadonlyArray<typeof CredentialFieldRole.Type>;
|
|
61
|
-
}
|
|
62
|
-
declare const BrowserCredentialAccess_base: Context.ServiceClass<BrowserCredentialAccess, "@effect-agent/platform-cloudflare/BrowserCredentialAccess", {
|
|
63
|
-
readonly authorize: (request: CredentialAccessRequest) => Effect.Effect<void, CredentialAccessError>;
|
|
64
|
-
readonly resolve: (request: CredentialAccessRequest) => Effect.Effect<BrowserCredentialMaterial, CredentialAccessError>;
|
|
65
|
-
}>;
|
|
66
|
-
/**
|
|
67
|
-
* Invocation-owned authority. Derive caller/ownership from the host, not the public credential
|
|
68
|
-
* identifier. Authorize the actual merchant, frame, recipient, roles, and side effects of filling.
|
|
69
|
-
* Repeated checks must consult current grants. Never log or trace resolved material.
|
|
70
|
-
* Bind caller identity and identifier-to-vault-item selection for the whole invocation; an alias
|
|
71
|
-
* changing between resolve and authorize must never authorize different material.
|
|
72
|
-
*/
|
|
73
|
-
export declare class BrowserCredentialAccess extends BrowserCredentialAccess_base {}
|
|
74
|
-
export declare const CredentialDispatch: Schema.Literals<readonly ["not-dispatched", "possibly-dispatched", "dispatched"]>;
|
|
75
|
-
declare const CredentialFillResult_base: Schema.Class<CredentialFillResult, Schema.Struct<{
|
|
76
|
-
readonly dispatch: Schema.Literal<"dispatched">;
|
|
77
|
-
readonly filled: Schema.Natural;
|
|
78
|
-
}>, {}>;
|
|
79
|
-
/** Filled counts acknowledged assignments, not authentication, submission, or website acceptance. */
|
|
80
|
-
export declare class CredentialFillResult extends CredentialFillResult_base {}
|
|
81
|
-
declare const CredentialFillError_base: Schema.Class<CredentialFillError, Schema.TaggedStruct<"CredentialFillError", {
|
|
82
|
-
readonly reason: Schema.Literals<readonly ["denied", "missing-credential", "stale-target", "unsupported", "needs-attention", "busy", "provider", "resolver", "timeout"]>;
|
|
83
|
-
readonly dispatch: Schema.Literals<readonly ["not-dispatched", "possibly-dispatched", "dispatched"]>;
|
|
84
|
-
readonly filled: Schema.Natural;
|
|
85
|
-
readonly cleanup: Schema.Literals<readonly ["not-requested", "confirmed", "unconfirmed"]>;
|
|
86
|
-
}>, import("effect/Cause").YieldableError>;
|
|
87
|
-
/** Content-free evidence. A lost reply never authorizes a retry or proves that no write occurred. */
|
|
88
|
-
export declare class CredentialFillError extends CredentialFillError_base {}
|
|
89
|
-
//#endregion
|
|
90
|
-
export { BrowserCredentials_d_exports as t };
|
|
91
|
-
//# sourceMappingURL=BrowserCredentials.d.mts.map
|
|
1
|
+
import { a as CredentialAccessError, c as CredentialFieldRole, d as CredentialKind, f as CredentialOrigin, h as LoginCredential, i as CardCredential, l as CredentialFillError, m as FillCredentialRequest, n as BrowserCredentialMaterial, o as CredentialAccessRequest, p as CredentialTarget, s as CredentialDispatch, t as BrowserCredentialAccess, u as CredentialFillResult } from "./BrowserCredentials-C5IWfi7f.mjs";
|
|
2
|
+
export { BrowserCredentialAccess, BrowserCredentialMaterial, CardCredential, CredentialAccessError, CredentialAccessRequest, CredentialDispatch, CredentialFieldRole, CredentialFillError, CredentialFillResult, CredentialKind, CredentialOrigin, CredentialTarget, FillCredentialRequest, LoginCredential };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as BrowserQuickActionWorkersAi } from "./CloudflareBrowser-
|
|
1
|
+
import { i as BrowserQuickActionWorkersAi } from "./CloudflareBrowser-Vt8qTdYW.mjs";
|
|
2
2
|
import { Effect, Layer, Option, Redacted, Schema, Stream } from "effect";
|
|
3
3
|
import { PageCapture, PageCaptureInferencePolicyError, PageCaptureInferenceUse, PageCaptureNavigationError, PageCaptureOutputLimitError, PageCaptureProtocolError, PageCaptureRateLimitedError, PageCaptureResourceUse, PageCaptureResult, PageCaptureUnsupportedError, PageContentCaptured, PageLinksCaptured, PageMarkdownCaptured, PageScrapeCaptured, PageStructuredCaptured } from "@yielded/agent/page-capture";
|
|
4
4
|
import { SandboxImplementation } from "@yielded/agent/sandbox";
|
|
@@ -111,7 +111,7 @@ const isJsonResponse = (headers) => {
|
|
|
111
111
|
const mediaType = contentType.split(";", 1)[0]?.trim().toLowerCase();
|
|
112
112
|
return mediaType === "application/json" || mediaType?.endsWith("+json") === true;
|
|
113
113
|
};
|
|
114
|
-
const readBoundedResponse = Effect.
|
|
114
|
+
const readBoundedResponse = Effect.fnUntraced(function* (response, request) {
|
|
115
115
|
const decoder = new TextDecoder("utf-8", {
|
|
116
116
|
fatal: true,
|
|
117
117
|
ignoreBOM: false
|
|
@@ -166,7 +166,7 @@ const parseOutput = (action, bodyText, apiToken) => {
|
|
|
166
166
|
}
|
|
167
167
|
};
|
|
168
168
|
const isQuotaMessage = (text) => /time limit|daily|quota/i.test(text);
|
|
169
|
-
const makeCapture = (client, options, workersAi) => Effect.
|
|
169
|
+
const makeCapture = (client, options, workersAi) => Effect.fnUntraced(function* (request) {
|
|
170
170
|
const usesWorkersAi = request.action._tag === "CapturePageStructured";
|
|
171
171
|
if (usesWorkersAi) {
|
|
172
172
|
if (workersAi === void 0) return yield* PageCaptureUnsupportedError.make({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BrowserRestCapture.mjs","names":[],"sources":["../src/BrowserRestCapture.ts"],"sourcesContent":["import {\n PageCapture,\n PageCaptureInferencePolicyError,\n PageCaptureInferenceUse,\n PageCaptureNavigationError,\n PageCaptureOutputLimitError,\n PageCaptureProtocolError,\n PageCaptureRateLimitedError,\n PageCaptureResourceUse,\n PageCaptureResult,\n PageContentCaptured,\n PageLinksCaptured,\n PageMarkdownCaptured,\n PageScrapeCaptured,\n PageStructuredCaptured,\n PageCaptureUnsupportedError,\n type PageCaptureAction,\n type PageCaptureCapture,\n type PageCaptureError,\n type PageCaptureOutput,\n type PageCaptureRequest,\n} from \"@yielded/agent/page-capture\";\nimport { SandboxImplementation } from \"@yielded/agent/sandbox\";\nimport { Effect, Layer, Option, Redacted, Schema, Stream } from \"effect\";\nimport { HttpClient, HttpClientRequest, type HttpClientError } from \"effect/http\";\n\nimport {\n BrowserQuickActionWorkersAi,\n type BrowserQuickActionWorkersAiPolicy,\n} from \"./CloudflareBrowser.ts\";\n\n/** Node-safe REST PageCapture implementation; it never imports Worker runtime modules. */\nexport const browserRestCaptureImplementation = SandboxImplementation.make({\n isolation: \"isolated\",\n identity: \"cloudflare-browser-rest\",\n});\n\nconst API_ORIGIN = \"https://api.cloudflare.com\";\nconst MAX_DIAGNOSTIC_LENGTH = 8_000;\nconst boundedDiagnostic = (message: string): string => message.slice(0, MAX_DIAGNOSTIC_LENGTH);\n\n/** Explicit construction inputs; credentials are only projected into the fixed-origin Authorization header. */\nexport interface BrowserRestCaptureOptions {\n readonly accountId: string;\n readonly apiToken: Redacted.Redacted<string>;\n}\n\nconst RestSuccessEnvelope = Schema.Struct({\n success: Schema.Literal(true),\n result: Schema.Json,\n errors: Schema.optionalKey(Schema.Array(Schema.Unknown)),\n meta: Schema.optionalKey(Schema.Unknown),\n});\n\nconst RestErrorEnvelope = Schema.Struct({\n success: Schema.Literal(false),\n errors: Schema.Array(\n Schema.Struct({\n message: Schema.String,\n code: Schema.optionalKey(Schema.Number),\n }),\n ),\n result: Schema.optionalKey(Schema.Json),\n meta: Schema.optionalKey(Schema.Unknown),\n});\n\nconst RestEnvelope = Schema.Union([RestSuccessEnvelope, RestErrorEnvelope]);\nconst decodeEnvelope = Schema.decodeUnknownOption(Schema.fromJsonString(RestEnvelope));\n\nconst protocolError = (message: string, cause?: unknown): PageCaptureProtocolError =>\n PageCaptureProtocolError.make({\n implementation: browserRestCaptureImplementation,\n message: boundedDiagnostic(message),\n ...(cause === undefined ? {} : { cause }),\n });\n\nconst navigationError = (message: string, cause?: unknown): PageCaptureNavigationError =>\n PageCaptureNavigationError.make({\n implementation: browserRestCaptureImplementation,\n message: boundedDiagnostic(message),\n ...(cause === undefined ? {} : { cause }),\n });\n\nconst privateResponseCause = (\n bodyText: string,\n apiToken: Redacted.Redacted<string>,\n): Error | undefined => {\n if (bodyText.length === 0) return undefined;\n const token = Redacted.value(apiToken);\n const diagnostic = boundedDiagnostic(bodyText);\n\n return new Error(token.length === 0 ? diagnostic : diagnostic.replaceAll(token, \"[REDACTED]\"));\n};\n\nconst requestBody = (request: PageCaptureRequest): Record<string, unknown> => {\n const body: Record<string, unknown> =\n request.target._tag === \"PageUrlTarget\"\n ? { url: request.target.url }\n : { html: request.target.html };\n\n if (request.navigation !== undefined) {\n const goto: Record<string, unknown> = {};\n\n if (request.navigation.waitUntil !== undefined) goto.waitUntil = request.navigation.waitUntil;\n if (request.navigation.timeoutMillis !== undefined)\n goto.timeout = request.navigation.timeoutMillis;\n if (Object.keys(goto).length > 0) body.gotoOptions = goto;\n if (request.navigation.waitForSelector !== undefined) {\n body.waitForSelector = {\n selector: request.navigation.waitForSelector.selector,\n ...(request.navigation.waitForSelector.timeoutMillis === undefined\n ? {}\n : { timeout: request.navigation.waitForSelector.timeoutMillis }),\n };\n }\n }\n if (request.viewport !== undefined) body.viewport = request.viewport;\n if (request.resourcePolicy?.rejectResourceTypes !== undefined) {\n body.rejectResourceTypes = [...request.resourcePolicy.rejectResourceTypes];\n }\n if (request.resourcePolicy?.allowRequestPatterns !== undefined) {\n body.allowRequestPattern = [...request.resourcePolicy.allowRequestPatterns];\n }\n\n return body;\n};\n\nconst actionName = (\n action: PageCaptureAction,\n): \"content\" | \"markdown\" | \"links\" | \"scrape\" | \"json\" => {\n switch (action._tag) {\n case \"CapturePageContent\":\n return \"content\";\n case \"CapturePageMarkdown\":\n return \"markdown\";\n case \"CapturePageLinks\":\n return \"links\";\n case \"CapturePageScrape\":\n return \"scrape\";\n case \"CapturePageStructured\":\n return \"json\";\n }\n};\n\nconst actionBody = (request: PageCaptureRequest): Record<string, unknown> => {\n const body = requestBody(request);\n\n switch (request.action._tag) {\n case \"CapturePageContent\":\n case \"CapturePageMarkdown\":\n return body;\n case \"CapturePageLinks\":\n return {\n ...body,\n ...(request.action.visibleLinksOnly === undefined\n ? {}\n : { visibleLinksOnly: request.action.visibleLinksOnly }),\n };\n case \"CapturePageScrape\":\n return {\n ...body,\n elements: request.action.selectors.map((selector) => ({ selector })),\n };\n case \"CapturePageStructured\":\n return {\n ...body,\n response_format: { type: \"json_schema\", json_schema: request.action.responseFormat },\n ...(request.action.prompt === undefined ? {} : { prompt: request.action.prompt }),\n };\n }\n};\n\nconst retryAfterMillis = (\n headers: Readonly<Record<string, string | undefined>>,\n): number | undefined => {\n const seconds = Number(headers[\"retry-after\"]);\n\n if (!Number.isSafeInteger(seconds) || seconds < 0) return undefined;\n const millis = seconds * 1_000;\n\n return Number.isSafeInteger(millis) ? millis : undefined;\n};\n\nconst browserMillis = (\n headers: Readonly<Record<string, string | undefined>>,\n): number | undefined => {\n const millis = Number(headers[\"x-browser-ms-used\"]);\n\n return Number.isSafeInteger(millis) && millis >= 0 ? millis : undefined;\n};\n\n/** Response framing is provider metadata, never content controlled by the rendered page. */\nconst isJsonResponse = (headers: Readonly<Record<string, string | undefined>>): boolean => {\n const contentType = headers[\"content-type\"];\n\n if (contentType === undefined) return false;\n const mediaType = contentType.split(\";\", 1)[0]?.trim().toLowerCase();\n\n return mediaType === \"application/json\" || mediaType?.endsWith(\"+json\") === true;\n};\n\nconst readBoundedResponse = Effect.fn(\"BrowserRestCapture.readResponse\")(function* (\n response: { readonly stream: Stream.Stream<Uint8Array, HttpClientError.HttpClientError> },\n request: PageCaptureRequest,\n): Effect.fn.Return<string, PageCaptureError> {\n const decoder = new TextDecoder(\"utf-8\", { fatal: true, ignoreBOM: false });\n\n const chunks = yield* Stream.runFoldEffect<\n Uint8Array,\n HttpClientError.HttpClientError,\n never,\n { readonly observed: number; readonly text: string },\n PageCaptureOutputLimitError | PageCaptureProtocolError,\n never\n >(\n response.stream,\n () => ({ observed: 0, text: \"\" }),\n (state, chunk) => {\n const observed = state.observed + chunk.byteLength;\n\n if (observed > request.limits.maxOutputBytes) {\n return Effect.fail(\n PageCaptureOutputLimitError.make({\n implementation: browserRestCaptureImplementation,\n limit: request.limits.maxOutputBytes,\n observed,\n }),\n );\n }\n\n return Effect.try({\n try: () => ({ observed, text: state.text + decoder.decode(chunk, { stream: true }) }),\n catch: (cause) => protocolError(\"Decoding the Browser Run response failed\", cause),\n });\n },\n ).pipe(\n Effect.mapError((error) =>\n Schema.is(PageCaptureOutputLimitError)(error) || Schema.is(PageCaptureProtocolError)(error)\n ? error\n : protocolError(\"Reading the Browser Run response failed\", error),\n ),\n );\n\n return yield* Effect.try({\n try: () => chunks.text + decoder.decode(),\n catch: (cause) => protocolError(\"Decoding the Browser Run response failed\", cause),\n });\n});\n\nconst parseOutput = (\n action: PageCaptureAction,\n bodyText: string,\n apiToken: Redacted.Redacted<string>,\n): PageCaptureOutput | PageCaptureNavigationError | PageCaptureProtocolError => {\n const envelope = decodeEnvelope(bodyText);\n\n if (Option.isNone(envelope)) {\n return protocolError(\n \"The Browser Run response did not carry a valid response envelope\",\n privateResponseCause(bodyText, apiToken),\n );\n }\n if (!envelope.value.success) {\n return navigationError(\n \"Browser Run reported a navigation failure\",\n privateResponseCause(bodyText, apiToken),\n );\n }\n switch (action._tag) {\n case \"CapturePageContent\":\n case \"CapturePageMarkdown\":\n if (typeof envelope.value.result !== \"string\") {\n return protocolError(\"The Browser Run response envelope carried a non-text result\");\n }\n\n return action._tag === \"CapturePageContent\"\n ? PageContentCaptured.make({ html: envelope.value.result })\n : PageMarkdownCaptured.make({ markdown: envelope.value.result });\n case \"CapturePageLinks\": {\n const decoded = Schema.decodeUnknownOption(PageLinksCaptured)({\n _tag: \"PageLinksCaptured\",\n links: envelope.value.result,\n });\n\n return Option.isSome(decoded)\n ? decoded.value\n : protocolError(\"Browser Run links did not return a bounded array of valid URLs\");\n }\n case \"CapturePageScrape\": {\n const decoded = Schema.decodeUnknownOption(PageScrapeCaptured)({\n _tag: \"PageScrapeCaptured\",\n groups: envelope.value.result,\n });\n\n return Option.isSome(decoded)\n ? decoded.value\n : protocolError(\"Browser Run scrape did not return bounded grouped element records\");\n }\n case \"CapturePageStructured\":\n return PageStructuredCaptured.make({ value: envelope.value.result });\n }\n};\n\nconst isQuotaMessage = (text: string): boolean => /time limit|daily|quota/i.test(text);\n\nconst makeCapture = (\n client: HttpClient.HttpClient,\n options: BrowserRestCaptureOptions,\n workersAi?: BrowserQuickActionWorkersAiPolicy,\n): PageCaptureCapture =>\n Effect.fn(\"BrowserRestCapture.capture\")(function* (\n request: PageCaptureRequest,\n ): Effect.fn.Return<PageCaptureResult, PageCaptureError> {\n const usesWorkersAi = request.action._tag === \"CapturePageStructured\";\n\n if (usesWorkersAi) {\n if (workersAi === undefined) {\n return yield* PageCaptureUnsupportedError.make({\n implementation: browserRestCaptureImplementation,\n feature: \"action\",\n message:\n \"Structured capture invokes separately billed Workers AI and requires an explicit authorization and accounting policy\",\n });\n }\n yield* workersAi.authorizeAndAccount(request).pipe(\n Effect.mapError((cause) =>\n PageCaptureInferencePolicyError.make({\n implementation: browserRestCaptureImplementation,\n provider: \"cloudflare-workers-ai\",\n reason: cause.reason,\n message:\n cause.reason === \"authorization\"\n ? \"Workers AI extraction was not authorized\"\n : \"Workers AI extraction could not be accounted for\",\n cause,\n }),\n ),\n );\n }\n const action = actionName(request.action);\n const path = `${API_ORIGIN}/client/v4/accounts/${encodeURIComponent(options.accountId)}/browser-rendering/${action}`;\n\n const requestWithBody = yield* HttpClientRequest.post(path).pipe(\n request.engine === \"kitesurf\"\n ? HttpClientRequest.setUrlParam(\"browser\", \"kitesurf\")\n : (value) => value,\n HttpClientRequest.bearerToken(options.apiToken),\n HttpClientRequest.acceptJson,\n HttpClientRequest.bodyJson(actionBody(request)),\n Effect.mapError((cause) => protocolError(\"Encoding the Browser Run request failed\", cause)),\n );\n\n const response = yield* client\n .execute(requestWithBody)\n .pipe(\n Effect.mapError((cause) => protocolError(\"Calling the Browser Run REST API failed\", cause)),\n );\n\n const bodyText = yield* readBoundedResponse(response, request);\n\n if (response.status === 429) {\n const reason = isQuotaMessage(bodyText) ? \"quota\" : \"rate\";\n\n return yield* PageCaptureRateLimitedError.make({\n implementation: browserRestCaptureImplementation,\n reason,\n ...(retryAfterMillis(response.headers) === undefined\n ? {}\n : { retryAfterMillis: retryAfterMillis(response.headers) }),\n ...(privateResponseCause(bodyText, options.apiToken) === undefined\n ? {}\n : { cause: privateResponseCause(bodyText, options.apiToken) }),\n message:\n reason === \"quota\"\n ? \"Browser Run exceeded its browser quota\"\n : \"Browser Run was rate limited\",\n });\n }\n if (response.status < 200 || response.status >= 300) {\n const error =\n response.status >= 500\n ? protocolError(\n `Browser Run answered HTTP ${String(response.status)}`,\n privateResponseCause(bodyText, options.apiToken),\n )\n : navigationError(\n `Browser Run answered HTTP ${String(response.status)}`,\n privateResponseCause(bodyText, options.apiToken),\n );\n\n return yield* error;\n }\n if (!isJsonResponse(response.headers)) {\n return yield* protocolError(\n \"The Browser Run success response was not a JSON response envelope\",\n privateResponseCause(bodyText, options.apiToken),\n );\n }\n const output = parseOutput(request.action, bodyText, options.apiToken);\n\n if (\n output._tag === \"PageCaptureNavigationError\" ||\n output._tag === \"PageCaptureProtocolError\"\n ) {\n return yield* output;\n }\n\n return PageCaptureResult.make({\n implementation: browserRestCaptureImplementation,\n output,\n resourceUse: PageCaptureResourceUse.make({\n ...(browserMillis(response.headers) === undefined\n ? {}\n : { browserMillis: browserMillis(response.headers) }),\n ...(usesWorkersAi\n ? {\n inference: PageCaptureInferenceUse.make({\n provider: \"cloudflare-workers-ai\",\n modelCalls: 1,\n }),\n }\n : {}),\n }),\n });\n });\n\n/** REST PageCapture layer for Node and other non-Worker composition roots. */\nexport const browserRestCaptureLayer = (\n options: BrowserRestCaptureOptions,\n): Layer.Layer<PageCapture, never, HttpClient.HttpClient> =>\n Layer.effect(\n PageCapture,\n Effect.map(HttpClient.HttpClient, (client) =>\n PageCapture.of({ capture: makeCapture(client, options) }),\n ),\n );\n\n/** REST structured extraction additionally requires explicit Workers AI authorization/accounting. */\nexport const browserRestWorkersAiCaptureLayer = (\n options: BrowserRestCaptureOptions,\n): Layer.Layer<PageCapture, never, HttpClient.HttpClient | BrowserQuickActionWorkersAi> =>\n Layer.effect(\n PageCapture,\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient;\n const workersAi = yield* BrowserQuickActionWorkersAi;\n\n return PageCapture.of({ capture: makeCapture(client, options, workersAi) });\n }),\n );\n\n/** Explicit REST credentials and optional authorization for separately billed extraction. */\nexport interface CloudflareBrowserRestOptions extends BrowserRestCaptureOptions {\n readonly workersAi?: BrowserQuickActionWorkersAiPolicy;\n}\n\n/** Node-safe WebCapture handler assembly; the application supplies its HttpClient. */\nexport const CloudflareBrowserRest = {\n /**\n * Supports capture, scrape, and extraction definitions. Only PageCapture is supplied;\n * handler errors and other services remain visible. Extraction fails closed without\n * workersAi. Existing host policies, response limits, and scoped cleanup are unchanged.\n */\n layer: <A, E, R>(\n definition: { readonly handlers: Layer.Layer<A, E, R> },\n options: CloudflareBrowserRestOptions,\n ): Layer.Layer<A, E, Exclude<R, PageCapture> | HttpClient.HttpClient> => {\n const capture =\n options.workersAi === undefined\n ? browserRestCaptureLayer(options)\n : browserRestWorkersAiCaptureLayer(options).pipe(\n Layer.provide(BrowserQuickActionWorkersAi.layer(options.workersAi)),\n );\n\n return definition.handlers.pipe(Layer.provide(capture));\n },\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BrowserRestCapture.mjs","names":[],"sources":["../src/BrowserRestCapture.ts"],"sourcesContent":["import {\n PageCapture,\n PageCaptureInferencePolicyError,\n PageCaptureInferenceUse,\n PageCaptureNavigationError,\n PageCaptureOutputLimitError,\n PageCaptureProtocolError,\n PageCaptureRateLimitedError,\n PageCaptureResourceUse,\n PageCaptureResult,\n PageContentCaptured,\n PageLinksCaptured,\n PageMarkdownCaptured,\n PageScrapeCaptured,\n PageStructuredCaptured,\n PageCaptureUnsupportedError,\n type PageCaptureAction,\n type PageCaptureCapture,\n type PageCaptureError,\n type PageCaptureOutput,\n type PageCaptureRequest,\n} from \"@yielded/agent/page-capture\";\nimport { SandboxImplementation } from \"@yielded/agent/sandbox\";\nimport { Effect, Layer, Option, Redacted, Schema, Stream } from \"effect\";\nimport { HttpClient, HttpClientRequest, type HttpClientError } from \"effect/http\";\n\nimport {\n BrowserQuickActionWorkersAi,\n type BrowserQuickActionWorkersAiPolicy,\n} from \"./CloudflareBrowser.ts\";\n\n/** Node-safe REST PageCapture implementation; it never imports Worker runtime modules. */\nexport const browserRestCaptureImplementation = SandboxImplementation.make({\n isolation: \"isolated\",\n identity: \"cloudflare-browser-rest\",\n});\n\nconst API_ORIGIN = \"https://api.cloudflare.com\";\nconst MAX_DIAGNOSTIC_LENGTH = 8_000;\nconst boundedDiagnostic = (message: string): string => message.slice(0, MAX_DIAGNOSTIC_LENGTH);\n\n/** Explicit construction inputs; credentials are only projected into the fixed-origin Authorization header. */\nexport interface BrowserRestCaptureOptions {\n readonly accountId: string;\n readonly apiToken: Redacted.Redacted<string>;\n}\n\nconst RestSuccessEnvelope = Schema.Struct({\n success: Schema.Literal(true),\n result: Schema.Json,\n errors: Schema.optionalKey(Schema.Array(Schema.Unknown)),\n meta: Schema.optionalKey(Schema.Unknown),\n});\n\nconst RestErrorEnvelope = Schema.Struct({\n success: Schema.Literal(false),\n errors: Schema.Array(\n Schema.Struct({\n message: Schema.String,\n code: Schema.optionalKey(Schema.Number),\n }),\n ),\n result: Schema.optionalKey(Schema.Json),\n meta: Schema.optionalKey(Schema.Unknown),\n});\n\nconst RestEnvelope = Schema.Union([RestSuccessEnvelope, RestErrorEnvelope]);\nconst decodeEnvelope = Schema.decodeUnknownOption(Schema.fromJsonString(RestEnvelope));\n\nconst protocolError = (message: string, cause?: unknown): PageCaptureProtocolError =>\n PageCaptureProtocolError.make({\n implementation: browserRestCaptureImplementation,\n message: boundedDiagnostic(message),\n ...(cause === undefined ? {} : { cause }),\n });\n\nconst navigationError = (message: string, cause?: unknown): PageCaptureNavigationError =>\n PageCaptureNavigationError.make({\n implementation: browserRestCaptureImplementation,\n message: boundedDiagnostic(message),\n ...(cause === undefined ? {} : { cause }),\n });\n\nconst privateResponseCause = (\n bodyText: string,\n apiToken: Redacted.Redacted<string>,\n): Error | undefined => {\n if (bodyText.length === 0) return undefined;\n const token = Redacted.value(apiToken);\n const diagnostic = boundedDiagnostic(bodyText);\n\n return new Error(token.length === 0 ? diagnostic : diagnostic.replaceAll(token, \"[REDACTED]\"));\n};\n\nconst requestBody = (request: PageCaptureRequest): Record<string, unknown> => {\n const body: Record<string, unknown> =\n request.target._tag === \"PageUrlTarget\"\n ? { url: request.target.url }\n : { html: request.target.html };\n\n if (request.navigation !== undefined) {\n const goto: Record<string, unknown> = {};\n\n if (request.navigation.waitUntil !== undefined) goto.waitUntil = request.navigation.waitUntil;\n if (request.navigation.timeoutMillis !== undefined)\n goto.timeout = request.navigation.timeoutMillis;\n if (Object.keys(goto).length > 0) body.gotoOptions = goto;\n if (request.navigation.waitForSelector !== undefined) {\n body.waitForSelector = {\n selector: request.navigation.waitForSelector.selector,\n ...(request.navigation.waitForSelector.timeoutMillis === undefined\n ? {}\n : { timeout: request.navigation.waitForSelector.timeoutMillis }),\n };\n }\n }\n if (request.viewport !== undefined) body.viewport = request.viewport;\n if (request.resourcePolicy?.rejectResourceTypes !== undefined) {\n body.rejectResourceTypes = [...request.resourcePolicy.rejectResourceTypes];\n }\n if (request.resourcePolicy?.allowRequestPatterns !== undefined) {\n body.allowRequestPattern = [...request.resourcePolicy.allowRequestPatterns];\n }\n\n return body;\n};\n\nconst actionName = (\n action: PageCaptureAction,\n): \"content\" | \"markdown\" | \"links\" | \"scrape\" | \"json\" => {\n switch (action._tag) {\n case \"CapturePageContent\":\n return \"content\";\n case \"CapturePageMarkdown\":\n return \"markdown\";\n case \"CapturePageLinks\":\n return \"links\";\n case \"CapturePageScrape\":\n return \"scrape\";\n case \"CapturePageStructured\":\n return \"json\";\n }\n};\n\nconst actionBody = (request: PageCaptureRequest): Record<string, unknown> => {\n const body = requestBody(request);\n\n switch (request.action._tag) {\n case \"CapturePageContent\":\n case \"CapturePageMarkdown\":\n return body;\n case \"CapturePageLinks\":\n return {\n ...body,\n ...(request.action.visibleLinksOnly === undefined\n ? {}\n : { visibleLinksOnly: request.action.visibleLinksOnly }),\n };\n case \"CapturePageScrape\":\n return {\n ...body,\n elements: request.action.selectors.map((selector) => ({ selector })),\n };\n case \"CapturePageStructured\":\n return {\n ...body,\n response_format: { type: \"json_schema\", json_schema: request.action.responseFormat },\n ...(request.action.prompt === undefined ? {} : { prompt: request.action.prompt }),\n };\n }\n};\n\nconst retryAfterMillis = (\n headers: Readonly<Record<string, string | undefined>>,\n): number | undefined => {\n const seconds = Number(headers[\"retry-after\"]);\n\n if (!Number.isSafeInteger(seconds) || seconds < 0) return undefined;\n const millis = seconds * 1_000;\n\n return Number.isSafeInteger(millis) ? millis : undefined;\n};\n\nconst browserMillis = (\n headers: Readonly<Record<string, string | undefined>>,\n): number | undefined => {\n const millis = Number(headers[\"x-browser-ms-used\"]);\n\n return Number.isSafeInteger(millis) && millis >= 0 ? millis : undefined;\n};\n\n/** Response framing is provider metadata, never content controlled by the rendered page. */\nconst isJsonResponse = (headers: Readonly<Record<string, string | undefined>>): boolean => {\n const contentType = headers[\"content-type\"];\n\n if (contentType === undefined) return false;\n const mediaType = contentType.split(\";\", 1)[0]?.trim().toLowerCase();\n\n return mediaType === \"application/json\" || mediaType?.endsWith(\"+json\") === true;\n};\n\nconst readBoundedResponse = Effect.fnUntraced(function* (\n response: { readonly stream: Stream.Stream<Uint8Array, HttpClientError.HttpClientError> },\n request: PageCaptureRequest,\n): Effect.fn.Return<string, PageCaptureError> {\n const decoder = new TextDecoder(\"utf-8\", { fatal: true, ignoreBOM: false });\n\n const chunks = yield* Stream.runFoldEffect<\n Uint8Array,\n HttpClientError.HttpClientError,\n never,\n { readonly observed: number; readonly text: string },\n PageCaptureOutputLimitError | PageCaptureProtocolError,\n never\n >(\n response.stream,\n () => ({ observed: 0, text: \"\" }),\n (state, chunk) => {\n const observed = state.observed + chunk.byteLength;\n\n if (observed > request.limits.maxOutputBytes) {\n return Effect.fail(\n PageCaptureOutputLimitError.make({\n implementation: browserRestCaptureImplementation,\n limit: request.limits.maxOutputBytes,\n observed,\n }),\n );\n }\n\n return Effect.try({\n try: () => ({ observed, text: state.text + decoder.decode(chunk, { stream: true }) }),\n catch: (cause) => protocolError(\"Decoding the Browser Run response failed\", cause),\n });\n },\n ).pipe(\n Effect.mapError((error) =>\n Schema.is(PageCaptureOutputLimitError)(error) || Schema.is(PageCaptureProtocolError)(error)\n ? error\n : protocolError(\"Reading the Browser Run response failed\", error),\n ),\n );\n\n return yield* Effect.try({\n try: () => chunks.text + decoder.decode(),\n catch: (cause) => protocolError(\"Decoding the Browser Run response failed\", cause),\n });\n});\n\nconst parseOutput = (\n action: PageCaptureAction,\n bodyText: string,\n apiToken: Redacted.Redacted<string>,\n): PageCaptureOutput | PageCaptureNavigationError | PageCaptureProtocolError => {\n const envelope = decodeEnvelope(bodyText);\n\n if (Option.isNone(envelope)) {\n return protocolError(\n \"The Browser Run response did not carry a valid response envelope\",\n privateResponseCause(bodyText, apiToken),\n );\n }\n if (!envelope.value.success) {\n return navigationError(\n \"Browser Run reported a navigation failure\",\n privateResponseCause(bodyText, apiToken),\n );\n }\n switch (action._tag) {\n case \"CapturePageContent\":\n case \"CapturePageMarkdown\":\n if (typeof envelope.value.result !== \"string\") {\n return protocolError(\"The Browser Run response envelope carried a non-text result\");\n }\n\n return action._tag === \"CapturePageContent\"\n ? PageContentCaptured.make({ html: envelope.value.result })\n : PageMarkdownCaptured.make({ markdown: envelope.value.result });\n case \"CapturePageLinks\": {\n const decoded = Schema.decodeUnknownOption(PageLinksCaptured)({\n _tag: \"PageLinksCaptured\",\n links: envelope.value.result,\n });\n\n return Option.isSome(decoded)\n ? decoded.value\n : protocolError(\"Browser Run links did not return a bounded array of valid URLs\");\n }\n case \"CapturePageScrape\": {\n const decoded = Schema.decodeUnknownOption(PageScrapeCaptured)({\n _tag: \"PageScrapeCaptured\",\n groups: envelope.value.result,\n });\n\n return Option.isSome(decoded)\n ? decoded.value\n : protocolError(\"Browser Run scrape did not return bounded grouped element records\");\n }\n case \"CapturePageStructured\":\n return PageStructuredCaptured.make({ value: envelope.value.result });\n }\n};\n\nconst isQuotaMessage = (text: string): boolean => /time limit|daily|quota/i.test(text);\n\nconst makeCapture = (\n client: HttpClient.HttpClient,\n options: BrowserRestCaptureOptions,\n workersAi?: BrowserQuickActionWorkersAiPolicy,\n): PageCaptureCapture =>\n Effect.fnUntraced(function* (\n request: PageCaptureRequest,\n ): Effect.fn.Return<PageCaptureResult, PageCaptureError> {\n const usesWorkersAi = request.action._tag === \"CapturePageStructured\";\n\n if (usesWorkersAi) {\n if (workersAi === undefined) {\n return yield* PageCaptureUnsupportedError.make({\n implementation: browserRestCaptureImplementation,\n feature: \"action\",\n message:\n \"Structured capture invokes separately billed Workers AI and requires an explicit authorization and accounting policy\",\n });\n }\n yield* workersAi.authorizeAndAccount(request).pipe(\n Effect.mapError((cause) =>\n PageCaptureInferencePolicyError.make({\n implementation: browserRestCaptureImplementation,\n provider: \"cloudflare-workers-ai\",\n reason: cause.reason,\n message:\n cause.reason === \"authorization\"\n ? \"Workers AI extraction was not authorized\"\n : \"Workers AI extraction could not be accounted for\",\n cause,\n }),\n ),\n );\n }\n const action = actionName(request.action);\n const path = `${API_ORIGIN}/client/v4/accounts/${encodeURIComponent(options.accountId)}/browser-rendering/${action}`;\n\n const requestWithBody = yield* HttpClientRequest.post(path).pipe(\n request.engine === \"kitesurf\"\n ? HttpClientRequest.setUrlParam(\"browser\", \"kitesurf\")\n : (value) => value,\n HttpClientRequest.bearerToken(options.apiToken),\n HttpClientRequest.acceptJson,\n HttpClientRequest.bodyJson(actionBody(request)),\n Effect.mapError((cause) => protocolError(\"Encoding the Browser Run request failed\", cause)),\n );\n\n const response = yield* client\n .execute(requestWithBody)\n .pipe(\n Effect.mapError((cause) => protocolError(\"Calling the Browser Run REST API failed\", cause)),\n );\n\n const bodyText = yield* readBoundedResponse(response, request);\n\n if (response.status === 429) {\n const reason = isQuotaMessage(bodyText) ? \"quota\" : \"rate\";\n\n return yield* PageCaptureRateLimitedError.make({\n implementation: browserRestCaptureImplementation,\n reason,\n ...(retryAfterMillis(response.headers) === undefined\n ? {}\n : { retryAfterMillis: retryAfterMillis(response.headers) }),\n ...(privateResponseCause(bodyText, options.apiToken) === undefined\n ? {}\n : { cause: privateResponseCause(bodyText, options.apiToken) }),\n message:\n reason === \"quota\"\n ? \"Browser Run exceeded its browser quota\"\n : \"Browser Run was rate limited\",\n });\n }\n if (response.status < 200 || response.status >= 300) {\n const error =\n response.status >= 500\n ? protocolError(\n `Browser Run answered HTTP ${String(response.status)}`,\n privateResponseCause(bodyText, options.apiToken),\n )\n : navigationError(\n `Browser Run answered HTTP ${String(response.status)}`,\n privateResponseCause(bodyText, options.apiToken),\n );\n\n return yield* error;\n }\n if (!isJsonResponse(response.headers)) {\n return yield* protocolError(\n \"The Browser Run success response was not a JSON response envelope\",\n privateResponseCause(bodyText, options.apiToken),\n );\n }\n const output = parseOutput(request.action, bodyText, options.apiToken);\n\n if (\n output._tag === \"PageCaptureNavigationError\" ||\n output._tag === \"PageCaptureProtocolError\"\n ) {\n return yield* output;\n }\n\n return PageCaptureResult.make({\n implementation: browserRestCaptureImplementation,\n output,\n resourceUse: PageCaptureResourceUse.make({\n ...(browserMillis(response.headers) === undefined\n ? {}\n : { browserMillis: browserMillis(response.headers) }),\n ...(usesWorkersAi\n ? {\n inference: PageCaptureInferenceUse.make({\n provider: \"cloudflare-workers-ai\",\n modelCalls: 1,\n }),\n }\n : {}),\n }),\n });\n });\n\n/** REST PageCapture layer for Node and other non-Worker composition roots. */\nexport const browserRestCaptureLayer = (\n options: BrowserRestCaptureOptions,\n): Layer.Layer<PageCapture, never, HttpClient.HttpClient> =>\n Layer.effect(\n PageCapture,\n Effect.map(HttpClient.HttpClient, (client) =>\n PageCapture.of({ capture: makeCapture(client, options) }),\n ),\n );\n\n/** REST structured extraction additionally requires explicit Workers AI authorization/accounting. */\nexport const browserRestWorkersAiCaptureLayer = (\n options: BrowserRestCaptureOptions,\n): Layer.Layer<PageCapture, never, HttpClient.HttpClient | BrowserQuickActionWorkersAi> =>\n Layer.effect(\n PageCapture,\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient;\n const workersAi = yield* BrowserQuickActionWorkersAi;\n\n return PageCapture.of({ capture: makeCapture(client, options, workersAi) });\n }),\n );\n\n/** Explicit REST credentials and optional authorization for separately billed extraction. */\nexport interface CloudflareBrowserRestOptions extends BrowserRestCaptureOptions {\n readonly workersAi?: BrowserQuickActionWorkersAiPolicy;\n}\n\n/** Node-safe WebCapture handler assembly; the application supplies its HttpClient. */\nexport const CloudflareBrowserRest = {\n /**\n * Supports capture, scrape, and extraction definitions. Only PageCapture is supplied;\n * handler errors and other services remain visible. Extraction fails closed without\n * workersAi. Existing host policies, response limits, and scoped cleanup are unchanged.\n */\n layer: <A, E, R>(\n definition: { readonly handlers: Layer.Layer<A, E, R> },\n options: CloudflareBrowserRestOptions,\n ): Layer.Layer<A, E, Exclude<R, PageCapture> | HttpClient.HttpClient> => {\n const capture =\n options.workersAi === undefined\n ? browserRestCaptureLayer(options)\n : browserRestWorkersAiCaptureLayer(options).pipe(\n Layer.provide(BrowserQuickActionWorkersAi.layer(options.workersAi)),\n );\n\n return definition.handlers.pipe(Layer.provide(capture));\n },\n};\n"],"mappings":"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"}
|
|
@@ -88,7 +88,7 @@ const isJsonResponse = (headers) => {
|
|
|
88
88
|
};
|
|
89
89
|
const isQuotaMessage = (bodyText) => /time limit|daily|quota/i.test(bodyText);
|
|
90
90
|
const endpoint = (options, jobId) => `${API_ORIGIN}/client/v4/accounts/${encodeURIComponent(options.accountId)}/browser-rendering/crawl${jobId === void 0 ? "" : `/${encodeURIComponent(jobId)}`}`;
|
|
91
|
-
const readBoundedResponse = Effect.
|
|
91
|
+
const readBoundedResponse = Effect.fnUntraced(function* (response, maximum) {
|
|
92
92
|
const decoder = new TextDecoder("utf-8", {
|
|
93
93
|
fatal: true,
|
|
94
94
|
ignoreBOM: false
|
|
@@ -112,11 +112,11 @@ const readBoundedResponse = Effect.fn("BrowserRestCrawl.readBoundedResponse")(fu
|
|
|
112
112
|
catch: (cause) => protocolError("Decoding the Browser Run crawl response failed", cause)
|
|
113
113
|
});
|
|
114
114
|
});
|
|
115
|
-
const deadlineFailure = Effect.
|
|
115
|
+
const deadlineFailure = Effect.fnUntraced(function* (request, startedAt) {
|
|
116
116
|
const now = yield* Effect.clockWith((clock) => clock.currentTimeMillis);
|
|
117
117
|
return yield* limitError(request, "deadline", Math.max(0, now - startedAt));
|
|
118
118
|
});
|
|
119
|
-
const withinDeadline = Effect.
|
|
119
|
+
const withinDeadline = Effect.fnUntraced(function* (effect, request, startedAt) {
|
|
120
120
|
const now = yield* Effect.clockWith((clock) => clock.currentTimeMillis);
|
|
121
121
|
const elapsed = Math.max(0, now - startedAt);
|
|
122
122
|
const remaining = request.limits.deadlineMillis - elapsed;
|
|
@@ -126,7 +126,7 @@ const withinDeadline = Effect.fn("BrowserRestCrawl.withinDeadline")(function* (e
|
|
|
126
126
|
orElse: () => deadlineFailure(request, startedAt)
|
|
127
127
|
}));
|
|
128
128
|
});
|
|
129
|
-
const checkDeadline = Effect.
|
|
129
|
+
const checkDeadline = Effect.fnUntraced(function* (request, startedAt) {
|
|
130
130
|
const now = yield* Effect.clockWith((clock) => clock.currentTimeMillis);
|
|
131
131
|
const elapsed = Math.max(0, now - startedAt);
|
|
132
132
|
if (elapsed >= request.limits.deadlineMillis) return yield* limitError(request, "deadline", elapsed);
|
|
@@ -136,7 +136,7 @@ const sameHost = (expectedHost, url) => new URL(url).host === expectedHost;
|
|
|
136
136
|
const makeCrawl = (client, options) => (input) => Stream.unwrap(Effect.gen(function* () {
|
|
137
137
|
const startedAt = yield* Effect.clockWith((clock) => clock.currentTimeMillis);
|
|
138
138
|
const startHost = new URL(input.startUrl).host;
|
|
139
|
-
const executeJson = Effect.
|
|
139
|
+
const executeJson = Effect.fnUntraced(function* (request, schema, maximum) {
|
|
140
140
|
const authorized = HttpClientRequest.bearerToken(request, options.apiToken).pipe(HttpClientRequest.acceptJson);
|
|
141
141
|
const response = yield* client.execute(authorized).pipe(Effect.mapError((cause) => protocolError("Calling the Browser Run crawl REST API failed", privateCause(cause, options.apiToken))));
|
|
142
142
|
const bodyText = yield* readBoundedResponse(response, maximum);
|
|
@@ -185,7 +185,7 @@ const makeCrawl = (client, options) => (input) => Stream.unwrap(Effect.gen(funct
|
|
|
185
185
|
state
|
|
186
186
|
};
|
|
187
187
|
}))));
|
|
188
|
-
const fetchResult = Effect.
|
|
188
|
+
const fetchResult = Effect.fnUntraced(function* (cursor, statusOnly) {
|
|
189
189
|
let request = HttpClientRequest.get(endpoint(options, job.id));
|
|
190
190
|
if (statusOnly) request = HttpClientRequest.setUrlParam(request, "limit", "1");
|
|
191
191
|
if (Option.isSome(cursor)) request = HttpClientRequest.setUrlParam(request, "cursor", cursor.value);
|