@effect-agent/platform-cloudflare 0.1.0-beta.30 → 0.1.0-beta.32
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/browser-quick-action.d.mts +2 -1
- package/dist/browser-quick-action.mjs +15 -1
- package/dist/browser-quick-action.mjs.map +1 -1
- package/dist/browser-rest-capture.mjs +13 -1
- package/dist/browser-rest-capture.mjs.map +1 -1
- package/dist/index.d.mts +10 -10
- package/dist/index.mjs +2 -2
- package/dist/interactive-browser.d.mts +57 -4
- package/dist/interactive-browser.mjs +277 -57
- package/dist/interactive-browser.mjs.map +1 -1
- package/package.json +8 -8
- package/src/browser-quick-action.ts +25 -2
- package/src/browser-rest-capture.ts +20 -1
- package/src/interactive-browser.ts +741 -152
|
@@ -24,10 +24,11 @@ interface BrowserQuickActionClient {
|
|
|
24
24
|
readonly content: (options: BrowserRunContentOptions) => Effect.Effect<Response, BrowserQuickActionRpcError>;
|
|
25
25
|
readonly markdown: (options: BrowserRunMarkdownOptions) => Effect.Effect<Response, BrowserQuickActionRpcError>;
|
|
26
26
|
readonly links: (options: BrowserRunLinksOptions) => Effect.Effect<Response, BrowserQuickActionRpcError>;
|
|
27
|
+
readonly scrape: (options: BrowserRunScrapeOptions) => Effect.Effect<Response, BrowserQuickActionRpcError>;
|
|
27
28
|
readonly json: (options: BrowserRunJsonOptions) => Effect.Effect<Response, BrowserQuickActionRpcError>;
|
|
28
29
|
}
|
|
29
30
|
declare const BrowserQuickActionRpcError_base: Schema.Class<BrowserQuickActionRpcError, Schema.TaggedStruct<"BrowserQuickActionRpcError", {
|
|
30
|
-
readonly action: Schema.Literals<readonly ["screenshot", "content", "markdown", "links", "json"]>;
|
|
31
|
+
readonly action: Schema.Literals<readonly ["screenshot", "content", "markdown", "links", "scrape", "json"]>;
|
|
31
32
|
readonly cause: Schema.Defect;
|
|
32
33
|
}>, import("effect/Cause").YieldableError>;
|
|
33
34
|
/** A native binding RPC rejected before it returned an HTTP response. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Context, Effect, Layer, Option, Schema } from "effect";
|
|
2
|
-
import { PageCapture, PageCaptureInferencePolicyError, PageCaptureInferenceUse, PageCaptureNavigationError, PageCaptureOutputLimitError, PageCaptureProtocolError, PageCaptureRateLimitedError, PageCaptureResourceUse, PageCaptureResult, PageCaptureUnsupportedError, PageContentCaptured, PageLinksCaptured, PageMarkdownCaptured, PageScreenshot, PageScreenshotOutputLimitError, PageScreenshotResult, PageStructuredCaptured, SandboxImplementation } from "@effect-agent/sandbox";
|
|
2
|
+
import { PageCapture, PageCaptureInferencePolicyError, PageCaptureInferenceUse, PageCaptureNavigationError, PageCaptureOutputLimitError, PageCaptureProtocolError, PageCaptureRateLimitedError, PageCaptureResourceUse, PageCaptureResult, PageCaptureUnsupportedError, PageContentCaptured, PageLinksCaptured, PageMarkdownCaptured, PageScrapeCaptured, PageScreenshot, PageScreenshotOutputLimitError, PageScreenshotResult, PageStructuredCaptured, SandboxImplementation } from "@effect-agent/sandbox";
|
|
3
3
|
//#region src/browser-quick-action.ts
|
|
4
4
|
/**
|
|
5
5
|
* The Cloudflare Browser Run Quick Action `PageCapture` adapter (capability
|
|
@@ -25,6 +25,7 @@ var BrowserQuickActionRpcError = class extends Schema.TaggedError()("BrowserQuic
|
|
|
25
25
|
"content",
|
|
26
26
|
"markdown",
|
|
27
27
|
"links",
|
|
28
|
+
"scrape",
|
|
28
29
|
"json"
|
|
29
30
|
]),
|
|
30
31
|
cause: Schema.Defect()
|
|
@@ -47,6 +48,7 @@ var BrowserQuickActionBrowserBinding = class BrowserQuickActionBrowserBinding ex
|
|
|
47
48
|
content: (request) => invoke("content", () => browser.quickAction("content", request)),
|
|
48
49
|
markdown: (request) => invoke("markdown", () => browser.quickAction("markdown", request)),
|
|
49
50
|
links: (request) => invoke("links", () => browser.quickAction("links", request)),
|
|
51
|
+
scrape: (request) => invoke("scrape", () => browser.quickAction("scrape", request)),
|
|
50
52
|
json: (request) => invoke("json", () => browser.quickAction("json", request))
|
|
51
53
|
});
|
|
52
54
|
}
|
|
@@ -121,6 +123,10 @@ const executeQuickAction = (browser, request) => {
|
|
|
121
123
|
...options,
|
|
122
124
|
...request.action.visibleLinksOnly === void 0 ? {} : { visibleLinksOnly: request.action.visibleLinksOnly }
|
|
123
125
|
});
|
|
126
|
+
case "CapturePageScrape": return browser.scrape({
|
|
127
|
+
...options,
|
|
128
|
+
elements: request.action.selectors.map((selector) => ({ selector }))
|
|
129
|
+
});
|
|
124
130
|
case "CapturePageStructured": return browser.json({
|
|
125
131
|
...options,
|
|
126
132
|
response_format: {
|
|
@@ -228,6 +234,14 @@ const parseOutput = (action, bodyText, response) => {
|
|
|
228
234
|
if (Option.isNone(decoded)) return protocolError("The links Quick Action did not return a bounded array of valid URLs");
|
|
229
235
|
return decoded.value;
|
|
230
236
|
}
|
|
237
|
+
case "CapturePageScrape": {
|
|
238
|
+
const decoded = Schema.decodeUnknownOption(PageScrapeCaptured)({
|
|
239
|
+
_tag: "PageScrapeCaptured",
|
|
240
|
+
groups: envelope.value.result
|
|
241
|
+
});
|
|
242
|
+
if (Option.isNone(decoded)) return protocolError("The scrape Quick Action did not return bounded grouped element records");
|
|
243
|
+
return decoded.value;
|
|
244
|
+
}
|
|
231
245
|
case "CapturePageStructured": return PageStructuredCaptured.make({ value: envelope.value.result });
|
|
232
246
|
}
|
|
233
247
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-quick-action.mjs","names":[],"sources":["../src/browser-quick-action.ts"],"sourcesContent":["/// <reference types=\"@cloudflare/workers-types\" />\n\nimport {\n PageCapture,\n PageCaptureInferenceUse,\n PageCaptureInferencePolicyError,\n PageCaptureNavigationError,\n PageCaptureOutputLimitError,\n PageCaptureProtocolError,\n PageCaptureRateLimitedError,\n PageCaptureResourceUse,\n PageCaptureResult,\n PageCaptureUnsupportedError,\n PageScreenshot,\n PageScreenshotOutputLimitError,\n PageScreenshotResult,\n type PageScreenshotCapture,\n type PageScreenshotError,\n type PageScreenshotRequest,\n PageContentCaptured,\n PageLinksCaptured,\n PageMarkdownCaptured,\n PageStructuredCaptured,\n SandboxImplementation,\n type PageCaptureAction,\n type PageCaptureCapture,\n type PageCaptureError,\n type PageCaptureOutput,\n type PageCaptureRequest,\n} from \"@effect-agent/sandbox\";\nimport { Context, Effect, Layer, Option, Schema } from \"effect\";\n\n/**\n * The Cloudflare Browser Run Quick Action `PageCapture` adapter (capability\n * spec §9.2). Each capture is one stateless `quickAction()` RPC on the\n * Wrangler `browser` binding: the platform renders the target in a managed\n * headless browser and returns one bounded output; the adapter holds no\n * session and no state between passes. The binding requires a Worker\n * compatibility date of `2026-03-24` or later, and local `wrangler dev` needs\n * remote mode (`\"remote\": true` on the binding) because `quickAction` has no\n * local implementation.\n *\n * Rendered output is untrusted, attacker-influenced content; this adapter\n * only bounds and types it. Deployment class `E` only: no durability claim.\n */\nexport const browserQuickActionImplementation = SandboxImplementation.make({\n isolation: \"isolated\",\n identity: \"cloudflare-browser-quick-action\",\n});\n\n/**\n * Effect-native client captured by the binding service. Its option types come\n * directly from the pinned Workers declarations rather than a local copy.\n */\nexport interface BrowserQuickActionClient {\n readonly screenshot: (\n options: BrowserRunScreenshotOptions,\n ) => Effect.Effect<Response, BrowserQuickActionRpcError>;\n readonly content: (\n options: BrowserRunContentOptions,\n ) => Effect.Effect<Response, BrowserQuickActionRpcError>;\n readonly markdown: (\n options: BrowserRunMarkdownOptions,\n ) => Effect.Effect<Response, BrowserQuickActionRpcError>;\n readonly links: (\n options: BrowserRunLinksOptions,\n ) => Effect.Effect<Response, BrowserQuickActionRpcError>;\n readonly json: (\n options: BrowserRunJsonOptions,\n ) => Effect.Effect<Response, BrowserQuickActionRpcError>;\n}\n\n/** A native binding RPC rejected before it returned an HTTP response. */\nexport class BrowserQuickActionRpcError extends Schema.TaggedError<BrowserQuickActionRpcError>()(\n \"BrowserQuickActionRpcError\",\n {\n action: Schema.Literals([\"screenshot\", \"content\", \"markdown\", \"links\", \"json\"]),\n cause: Schema.Defect(),\n },\n) {}\n\nexport interface BrowserQuickActionCaptureOptions {\n /** The resolved Wrangler `browser` binding (DEPLOY-014: supplied, never ambient). */\n readonly browser: BrowserRun;\n}\n\n/** Host-owned browser binding authority, supplied explicitly at the composition root. */\nexport class BrowserQuickActionBrowserBinding extends Context.Service<\n BrowserQuickActionBrowserBinding,\n BrowserQuickActionClient\n>()(\"@effect-agent/platform-cloudflare/BrowserQuickActionBrowserBinding\") {\n static layer(\n options: BrowserQuickActionCaptureOptions,\n ): Layer.Layer<BrowserQuickActionBrowserBinding> {\n const browser = options.browser;\n const invoke = Effect.fn(\"BrowserQuickActionBrowserBinding.invoke\")(function* (\n action: \"screenshot\" | \"content\" | \"markdown\" | \"links\" | \"json\",\n evaluate: () => Promise<Response>,\n ): Effect.fn.Return<Response, BrowserQuickActionRpcError> {\n return yield* Effect.tryPromise({\n try: evaluate,\n catch: (cause) => BrowserQuickActionRpcError.make({ action, cause }),\n });\n });\n return Layer.succeed(BrowserQuickActionBrowserBinding)({\n screenshot: (request) =>\n invoke(\"screenshot\", () => browser.quickAction(\"screenshot\", request)),\n content: (request) => invoke(\"content\", () => browser.quickAction(\"content\", request)),\n markdown: (request) => invoke(\"markdown\", () => browser.quickAction(\"markdown\", request)),\n links: (request) => invoke(\"links\", () => browser.quickAction(\"links\", request)),\n json: (request) => invoke(\"json\", () => browser.quickAction(\"json\", request)),\n });\n }\n}\n\n/** Host-owned authorization and accounting for one Workers AI extraction. */\nexport interface BrowserQuickActionWorkersAiPolicy {\n readonly authorizeAndAccount: (\n request: PageCaptureRequest,\n ) => Effect.Effect<void, BrowserQuickActionWorkersAiPolicyError>;\n}\n\n/** Host-only diagnostic for a denied or unaccounted Workers AI extraction. */\nexport class BrowserQuickActionWorkersAiPolicyError extends Schema.TaggedError<BrowserQuickActionWorkersAiPolicyError>()(\n \"BrowserQuickActionWorkersAiPolicyError\",\n {\n reason: Schema.Literals([\"authorization\", \"accounting\"]),\n message: Schema.String.check(Schema.isMaxLength(8_000)),\n cause: Schema.optionalKey(Schema.Defect()),\n },\n) {}\n\n/** Explicit host-owned authority and accounting for separately billed Workers AI extraction. */\nexport class BrowserQuickActionWorkersAi extends Context.Service<\n BrowserQuickActionWorkersAi,\n BrowserQuickActionWorkersAiPolicy\n>()(\"@effect-agent/platform-cloudflare/BrowserQuickActionWorkersAi\") {\n static layer(\n policy: BrowserQuickActionWorkersAiPolicy,\n ): Layer.Layer<BrowserQuickActionWorkersAi> {\n return Layer.succeed(BrowserQuickActionWorkersAi)(policy);\n }\n}\n\nconst MAX_DIAGNOSTIC_LENGTH = 8_000;\nconst boundedDiagnostic = (message: string): string => message.slice(0, MAX_DIAGNOSTIC_LENGTH);\n\nconst QuickActionSuccessEnvelope = Schema.Struct({\n success: Schema.Literal(true),\n result: Schema.Json,\n});\n\nconst QuickActionErrorEnvelope = 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 detail: Schema.optionalKey(Schema.String),\n path: Schema.optionalKey(Schema.String),\n }),\n ),\n rawAiResponse: Schema.optionalKey(Schema.String),\n});\n\nconst QuickActionEnvelope = Schema.Union([QuickActionSuccessEnvelope, QuickActionErrorEnvelope]);\nconst decodeEnvelope = Schema.decodeUnknownOption(Schema.fromJsonString(QuickActionEnvelope));\n\n/** Project the schema-validated request onto Cloudflare's native common options. */\nconst quickActionCommonOptions = (request: PageCaptureRequest): BrowserRunCommonOptions => {\n const options: BrowserRunBaseOptions = {};\n const navigation = request.navigation;\n if (navigation !== undefined) {\n const goto: NonNullable<BrowserRunBaseOptions[\"gotoOptions\"]> = {};\n if (navigation.waitUntil !== undefined) goto.waitUntil = navigation.waitUntil;\n if (navigation.timeoutMillis !== undefined) goto.timeout = navigation.timeoutMillis;\n if (Object.keys(goto).length > 0) options.gotoOptions = goto;\n if (navigation.waitForSelector !== undefined) {\n options.waitForSelector = {\n selector: navigation.waitForSelector.selector,\n ...(navigation.waitForSelector.timeoutMillis === undefined\n ? {}\n : { timeout: navigation.waitForSelector.timeoutMillis }),\n };\n }\n }\n if (request.viewport !== undefined) {\n options.viewport = { width: request.viewport.width, height: request.viewport.height };\n }\n if (request.resourcePolicy !== undefined) {\n if (request.resourcePolicy.rejectResourceTypes !== undefined) {\n options.rejectResourceTypes = [...request.resourcePolicy.rejectResourceTypes];\n }\n if (request.resourcePolicy.allowRequestPatterns !== undefined) {\n options.allowRequestPattern = [...request.resourcePolicy.allowRequestPatterns];\n }\n }\n return request.target._tag === \"PageUrlTarget\"\n ? { ...options, url: request.target.url }\n : { ...options, html: request.target.html };\n};\n\n/** Dispatch through Cloudflare's native action-specific overloads. */\nconst executeQuickAction = (\n browser: BrowserQuickActionClient,\n request: PageCaptureRequest,\n): Effect.Effect<Response, BrowserQuickActionRpcError> => {\n const options = quickActionCommonOptions(request);\n switch (request.action._tag) {\n case \"CapturePageContent\": {\n return browser.content(options);\n }\n case \"CapturePageMarkdown\": {\n return browser.markdown(options);\n }\n case \"CapturePageLinks\": {\n return browser.links({\n ...options,\n ...(request.action.visibleLinksOnly === undefined\n ? {}\n : { visibleLinksOnly: request.action.visibleLinksOnly }),\n });\n }\n case \"CapturePageStructured\": {\n return browser.json({\n ...options,\n response_format: {\n type: \"json_schema\",\n json_schema: request.action.responseFormat,\n },\n ...(request.action.prompt === undefined ? {} : { prompt: request.action.prompt }),\n });\n }\n }\n};\n\nconst protocolError = (message: string, cause?: unknown): PageCaptureProtocolError =>\n PageCaptureProtocolError.make({\n implementation: browserQuickActionImplementation,\n message: boundedDiagnostic(message),\n ...(cause === undefined ? {} : { cause }),\n });\n\nconst navigationError = (message: string, cause?: unknown): PageCaptureNavigationError =>\n PageCaptureNavigationError.make({\n implementation: browserQuickActionImplementation,\n message: boundedDiagnostic(message),\n ...(cause === undefined ? {} : { cause }),\n });\n\n/** Preserve bounded remote diagnostics for the host without exposing their text to a model. */\nconst privateResponseCause = (bodyText: string): Error | undefined =>\n bodyText.length === 0 ? undefined : new Error(boundedDiagnostic(bodyText));\n\nconst releaseResponseReader = (\n reader: ReadableStreamDefaultReader<Uint8Array>,\n): Effect.Effect<void> =>\n Effect.tryPromise({\n try: () => reader.cancel(),\n catch: (cause) => protocolError(\"Canceling the Quick Action response failed\", cause),\n }).pipe(\n Effect.catch((error) => Effect.logWarning(error.message)),\n Effect.ensuring(\n Effect.try({\n try: () => reader.releaseLock(),\n catch: (cause) => protocolError(\"Releasing the Quick Action response failed\", cause),\n }).pipe(Effect.catch((error) => Effect.logWarning(error.message))),\n ),\n );\n\nconst readBoundedResponse = Effect.fn(\"BrowserQuickActionCapture.readResponse\")(function* (\n response: Response,\n request: PageCaptureRequest,\n) {\n const body = response.body;\n if (body === null) return \"\";\n\n const reader = yield* Effect.acquireRelease(\n Effect.try({\n try: () => body.getReader(),\n catch: (cause) => protocolError(\"Opening the Quick Action response failed\", cause),\n }),\n releaseResponseReader,\n );\n const decoder = new TextDecoder(\"utf-8\", { fatal: true, ignoreBOM: false });\n let observedBytes = 0;\n let bodyText = \"\";\n\n while (true) {\n const chunk = yield* Effect.tryPromise({\n try: () => reader.read(),\n catch: (cause) => protocolError(\"Reading the Quick Action response failed\", cause),\n });\n if (chunk.done) break;\n\n observedBytes += chunk.value.byteLength;\n if (observedBytes > request.limits.maxOutputBytes) {\n return yield* PageCaptureOutputLimitError.make({\n implementation: browserQuickActionImplementation,\n limit: request.limits.maxOutputBytes,\n observed: observedBytes,\n });\n }\n\n bodyText += yield* Effect.try({\n try: () => decoder.decode(chunk.value, { stream: true }),\n catch: (cause) => protocolError(\"Decoding the Quick Action response failed\", cause),\n });\n }\n\n return (\n bodyText +\n (yield* Effect.try({\n try: () => decoder.decode(),\n catch: (cause) => protocolError(\"Decoding the Quick Action response failed\", cause),\n }))\n );\n}, Effect.scoped);\n\n/**\n * Retry-After arrives in whole seconds; a non-integer form (an HTTP date) is\n * dropped rather than guessed at.\n */\nconst retryAfterMillis = (response: Response): number | undefined => {\n const header = response.headers.get(\"Retry-After\");\n if (header === null) return undefined;\n const seconds = Number(header);\n if (!Number.isSafeInteger(seconds) || seconds < 0) return undefined;\n const millis = seconds * 1_000;\n return Number.isSafeInteger(millis) ? millis : undefined;\n};\n\nconst browserMillis = (response: Response): number | undefined => {\n const header = response.headers.get(\"X-Browser-Ms-Used\");\n if (header === null) return undefined;\n const millis = Number(header);\n return Number.isSafeInteger(millis) && millis >= 0 ? millis : undefined;\n};\n\n/** Only trusted response metadata chooses transport framing; page text never does. */\nconst isJsonResponse = (response: Response): boolean => {\n const contentType = response.headers.get(\"Content-Type\");\n if (contentType === null) return false;\n const mediaType = contentType.split(\";\", 1)[0]?.trim().toLowerCase();\n return mediaType === \"application/json\" || mediaType?.endsWith(\"+json\") === true;\n};\n\nconst parseOutput = (\n action: PageCaptureAction,\n bodyText: string,\n response: Response,\n): PageCaptureOutput | PageCaptureNavigationError | PageCaptureProtocolError => {\n if (!isJsonResponse(response)) {\n return protocolError(\n \"The Quick Action success response was not a JSON response envelope\",\n privateResponseCause(bodyText),\n );\n }\n const envelope = decodeEnvelope(bodyText);\n if (Option.isNone(envelope)) {\n return protocolError(\n \"The JSON Quick Action response did not carry a valid response envelope\",\n privateResponseCause(bodyText),\n );\n }\n if (!envelope.value.success) {\n return navigationError(\n \"The Quick Action reported a navigation failure\",\n privateResponseCause(bodyText),\n );\n }\n switch (action._tag) {\n case \"CapturePageContent\":\n case \"CapturePageMarkdown\": {\n if (typeof envelope.value.result !== \"string\") {\n return protocolError(\"The Quick Action envelope carried a non-text result\");\n }\n return action._tag === \"CapturePageContent\"\n ? PageContentCaptured.make({ html: envelope.value.result })\n : PageMarkdownCaptured.make({ markdown: envelope.value.result });\n }\n case \"CapturePageLinks\": {\n const decoded = Schema.decodeUnknownOption(PageLinksCaptured)({\n _tag: \"PageLinksCaptured\",\n links: envelope.value.result,\n });\n if (Option.isNone(decoded)) {\n return protocolError(\"The links Quick Action did not return a bounded array of valid URLs\");\n }\n return decoded.value;\n }\n case \"CapturePageStructured\": {\n return PageStructuredCaptured.make({ value: envelope.value.result });\n }\n }\n};\n\nconst isQuotaMessage = (text: string): boolean => /time limit|daily|quota/i.test(text);\n\nconst makeCapture = (\n browser: BrowserQuickActionClient,\n workersAi?: BrowserQuickActionWorkersAiPolicy,\n): PageCaptureCapture =>\n Effect.fn(\"BrowserQuickActionCapture.capture\")(function* (\n request: PageCaptureRequest,\n ): Effect.fn.Return<PageCaptureResult, PageCaptureError> {\n if (request.engine !== \"chromium\") {\n return yield* PageCaptureUnsupportedError.make({\n implementation: browserQuickActionImplementation,\n feature: \"engine\",\n message:\n \"The browser binding's quickAction() exposes no engine selector; kitesurf requires the REST or CDP surface\",\n });\n }\n\n const usesWorkersAi = request.action._tag === \"CapturePageStructured\";\n if (usesWorkersAi) {\n if (workersAi === undefined) {\n return yield* PageCaptureUnsupportedError.make({\n implementation: browserQuickActionImplementation,\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: browserQuickActionImplementation,\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\n const response = yield* executeQuickAction(browser, request).pipe(\n Effect.mapError((error) =>\n protocolError(\"The browser binding rejected the Quick Action\", error.cause),\n ),\n );\n const bodyText = yield* readBoundedResponse(response, request);\n if (response.status === 429) {\n const retryAfter = retryAfterMillis(response);\n const reason = isQuotaMessage(bodyText) ? \"quota\" : \"rate\";\n const cause = privateResponseCause(bodyText);\n return yield* PageCaptureRateLimitedError.make({\n implementation: browserQuickActionImplementation,\n reason,\n ...(retryAfter === undefined ? {} : { retryAfterMillis: retryAfter }),\n ...(cause === undefined ? {} : { cause }),\n message:\n reason === \"quota\"\n ? \"The Quick Action exceeded its browser quota\"\n : \"The Quick Action was rate limited\",\n });\n }\n if (!response.ok) {\n const message = `The Quick Action answered HTTP ${response.status}`;\n const cause = privateResponseCause(bodyText);\n if (response.status >= 500) {\n return yield* protocolError(message, cause);\n }\n return yield* navigationError(message, cause);\n }\n const output = parseOutput(request.action, bodyText, response);\n if (\n output._tag === \"PageCaptureNavigationError\" ||\n output._tag === \"PageCaptureProtocolError\"\n ) {\n return yield* output;\n }\n const millis = browserMillis(response);\n return PageCaptureResult.make({\n implementation: browserQuickActionImplementation,\n output,\n resourceUse: PageCaptureResourceUse.make({\n ...(millis === undefined ? {} : { browserMillis: millis }),\n ...(usesWorkersAi\n ? {\n inference: PageCaptureInferenceUse.make({\n provider: \"cloudflare-workers-ai\",\n modelCalls: 1,\n }),\n }\n : {}),\n }),\n });\n });\n\n/**\n * Ordinary Quick Actions require host-owned browser binding authority. Workers\n * AI stays unavailable unless the host deliberately selects its separate Layer.\n */\nexport const browserQuickActionCaptureLayer = (): Layer.Layer<\n PageCapture,\n never,\n BrowserQuickActionBrowserBinding\n> =>\n Layer.effect(\n PageCapture,\n Effect.map(BrowserQuickActionBrowserBinding, (browser) =>\n PageCapture.of({ capture: makeCapture(browser) }),\n ),\n );\n\n/** Structured Quick Actions require host-owned browser and Workers AI authority. */\nexport const browserQuickActionWorkersAiCaptureLayer = (): Layer.Layer<\n PageCapture,\n never,\n BrowserQuickActionBrowserBinding | BrowserQuickActionWorkersAi\n> =>\n Layer.effect(\n PageCapture,\n Effect.gen(function* () {\n const browser = yield* BrowserQuickActionBrowserBinding;\n const workersAi = yield* BrowserQuickActionWorkersAi;\n return PageCapture.of({ capture: makeCapture(browser, workersAi) });\n }),\n );\n\nconst screenshotOptions = (request: PageScreenshotRequest): BrowserRunScreenshotOptions => {\n const options: BrowserRunBaseOptions = {};\n if (\n request.navigation?.waitUntil !== undefined ||\n request.navigation?.timeoutMillis !== undefined\n ) {\n options.gotoOptions = {\n ...(request.navigation.waitUntil === undefined\n ? {}\n : { waitUntil: request.navigation.waitUntil }),\n ...(request.navigation.timeoutMillis === undefined\n ? {}\n : { timeout: request.navigation.timeoutMillis }),\n };\n }\n if (request.navigation?.waitForSelector !== undefined) {\n options.waitForSelector = {\n selector: request.navigation.waitForSelector.selector,\n ...(request.navigation.waitForSelector.timeoutMillis === undefined\n ? {}\n : { timeout: request.navigation.waitForSelector.timeoutMillis }),\n };\n }\n if (request.viewport !== undefined) {\n options.viewport = { width: request.viewport.width, height: request.viewport.height };\n }\n if (request.resourcePolicy?.rejectResourceTypes !== undefined) {\n options.rejectResourceTypes = [...request.resourcePolicy.rejectResourceTypes];\n }\n if (request.resourcePolicy?.allowRequestPatterns !== undefined) {\n options.allowRequestPattern = [...request.resourcePolicy.allowRequestPatterns];\n }\n return {\n ...options,\n ...(request.target._tag === \"PageUrlTarget\"\n ? { url: request.target.url }\n : { html: request.target.html }),\n screenshotOptions: { type: \"png\", encoding: \"binary\", fullPage: request.fullPage },\n };\n};\n\nconst cancelBody = (body: ReadableStream<Uint8Array>): Effect.Effect<void> =>\n Effect.tryPromise({\n try: () => body.cancel(),\n catch: () => undefined,\n }).pipe(Effect.catch(() => Effect.void));\n\nconst releaseScreenshotReader = (\n reader: ReadableStreamDefaultReader<Uint8Array>,\n): Effect.Effect<void> =>\n Effect.tryPromise({ try: () => reader.cancel(), catch: () => undefined }).pipe(\n Effect.catch(() => Effect.logWarning(\"Canceling the screenshot response failed\")),\n Effect.ensuring(\n Effect.try({\n try: () => reader.releaseLock(),\n catch: () => undefined,\n }).pipe(Effect.catch(() => Effect.logWarning(\"Releasing the screenshot response failed\"))),\n ),\n );\n\nconst pngResponse = (response: Response): boolean =>\n response.headers.get(\"Content-Type\")?.split(\";\", 1)[0]?.trim().toLowerCase() === \"image/png\";\n\nconst declaredLength = (response: Response): number | undefined => {\n const raw = response.headers.get(\"Content-Length\");\n if (raw === null || !/^(0|[1-9][0-9]*)$/.test(raw)) return undefined;\n const length = Number(raw);\n return Number.isSafeInteger(length) ? length : undefined;\n};\n\nconst readScreenshot = Effect.fn(\"BrowserQuickActionScreenshot.read\")(function* (\n response: Response,\n request: PageScreenshotRequest,\n) {\n const body = response.body;\n if (body === null) {\n return yield* protocolError(\"The screenshot response had no body\");\n }\n if (!pngResponse(response)) {\n yield* cancelBody(body);\n return yield* protocolError(\"The screenshot response was not image/png\");\n }\n const length = declaredLength(response);\n if (length !== undefined && length > request.limits.maxOutputBytes) {\n yield* cancelBody(body);\n return yield* PageScreenshotOutputLimitError.make({\n implementation: browserQuickActionImplementation,\n limit: request.limits.maxOutputBytes,\n observed: length,\n });\n }\n const reader = yield* Effect.acquireRelease(\n Effect.try({\n try: () => body.getReader(),\n catch: (cause) => protocolError(\"Opening the screenshot response failed\", cause),\n }),\n releaseScreenshotReader,\n );\n const chunks: Array<Uint8Array> = [];\n let observed = 0;\n while (true) {\n const next = yield* Effect.tryPromise({\n try: () => reader.read(),\n catch: (cause) => protocolError(\"Reading the screenshot response failed\", cause),\n });\n if (next.done) break;\n observed += next.value.byteLength;\n if (observed > request.limits.maxOutputBytes) {\n return yield* PageScreenshotOutputLimitError.make({\n implementation: browserQuickActionImplementation,\n limit: request.limits.maxOutputBytes,\n observed,\n });\n }\n chunks.push(next.value);\n }\n const bytes = new Uint8Array(observed);\n let offset = 0;\n for (const chunk of chunks) {\n bytes.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return bytes;\n}, Effect.scoped);\n\nconst makeScreenshot = (browser: BrowserQuickActionClient): PageScreenshotCapture =>\n Effect.fn(\"BrowserQuickActionScreenshot.capture\")(function* (\n request: PageScreenshotRequest,\n ): Effect.fn.Return<PageScreenshotResult, PageScreenshotError> {\n if (request.engine !== \"chromium\") {\n return yield* PageCaptureUnsupportedError.make({\n implementation: browserQuickActionImplementation,\n feature: \"engine\",\n message: \"The browser binding's screenshot action exposes no engine selector\",\n });\n }\n const response = yield* browser\n .screenshot(screenshotOptions(request))\n .pipe(\n Effect.mapError((error) =>\n protocolError(\"The browser binding rejected the screenshot\", error.cause),\n ),\n );\n if (response.status === 429) {\n const body = response.body;\n if (body !== null) yield* cancelBody(body);\n return yield* PageCaptureRateLimitedError.make({\n implementation: browserQuickActionImplementation,\n reason: \"rate\",\n ...(retryAfterMillis(response) === undefined\n ? {}\n : { retryAfterMillis: retryAfterMillis(response) }),\n message: \"The screenshot Quick Action was rate limited\",\n });\n }\n if (!response.ok) {\n const body = response.body;\n if (body !== null) yield* cancelBody(body);\n const message = `The screenshot Quick Action answered HTTP ${response.status}`;\n return yield* response.status >= 500 ? protocolError(message) : navigationError(message);\n }\n const bytes = yield* readScreenshot(response, request);\n return PageScreenshotResult.make({\n implementation: browserQuickActionImplementation,\n mediaType: \"image/png\",\n bytes,\n });\n });\n\n/** Native Browser Run screenshot adapter. It retains PNG bytes only for the caller's result. */\nexport const browserQuickActionScreenshotLayer = (): Layer.Layer<\n PageScreenshot,\n never,\n BrowserQuickActionBrowserBinding\n> =>\n Layer.effect(\n PageScreenshot,\n Effect.map(BrowserQuickActionBrowserBinding, (browser) =>\n PageScreenshot.of({ capture: makeScreenshot(browser) }),\n ),\n );\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"browser-quick-action.mjs","names":[],"sources":["../src/browser-quick-action.ts"],"sourcesContent":["/// <reference types=\"@cloudflare/workers-types\" />\n\nimport {\n PageCapture,\n PageCaptureInferenceUse,\n PageCaptureInferencePolicyError,\n PageCaptureNavigationError,\n PageCaptureOutputLimitError,\n PageCaptureProtocolError,\n PageCaptureRateLimitedError,\n PageCaptureResourceUse,\n PageCaptureResult,\n PageCaptureUnsupportedError,\n PageScreenshot,\n PageScreenshotOutputLimitError,\n PageScreenshotResult,\n type PageScreenshotCapture,\n type PageScreenshotError,\n type PageScreenshotRequest,\n PageContentCaptured,\n PageLinksCaptured,\n PageMarkdownCaptured,\n PageScrapeCaptured,\n PageStructuredCaptured,\n SandboxImplementation,\n type PageCaptureAction,\n type PageCaptureCapture,\n type PageCaptureError,\n type PageCaptureOutput,\n type PageCaptureRequest,\n} from \"@effect-agent/sandbox\";\nimport { Context, Effect, Layer, Option, Schema } from \"effect\";\n\n/**\n * The Cloudflare Browser Run Quick Action `PageCapture` adapter (capability\n * spec §9.2). Each capture is one stateless `quickAction()` RPC on the\n * Wrangler `browser` binding: the platform renders the target in a managed\n * headless browser and returns one bounded output; the adapter holds no\n * session and no state between passes. The binding requires a Worker\n * compatibility date of `2026-03-24` or later, and local `wrangler dev` needs\n * remote mode (`\"remote\": true` on the binding) because `quickAction` has no\n * local implementation.\n *\n * Rendered output is untrusted, attacker-influenced content; this adapter\n * only bounds and types it. Deployment class `E` only: no durability claim.\n */\nexport const browserQuickActionImplementation = SandboxImplementation.make({\n isolation: \"isolated\",\n identity: \"cloudflare-browser-quick-action\",\n});\n\n/**\n * Effect-native client captured by the binding service. Its option types come\n * directly from the pinned Workers declarations rather than a local copy.\n */\nexport interface BrowserQuickActionClient {\n readonly screenshot: (\n options: BrowserRunScreenshotOptions,\n ) => Effect.Effect<Response, BrowserQuickActionRpcError>;\n readonly content: (\n options: BrowserRunContentOptions,\n ) => Effect.Effect<Response, BrowserQuickActionRpcError>;\n readonly markdown: (\n options: BrowserRunMarkdownOptions,\n ) => Effect.Effect<Response, BrowserQuickActionRpcError>;\n readonly links: (\n options: BrowserRunLinksOptions,\n ) => Effect.Effect<Response, BrowserQuickActionRpcError>;\n readonly scrape: (\n options: BrowserRunScrapeOptions,\n ) => Effect.Effect<Response, BrowserQuickActionRpcError>;\n readonly json: (\n options: BrowserRunJsonOptions,\n ) => Effect.Effect<Response, BrowserQuickActionRpcError>;\n}\n\n/** A native binding RPC rejected before it returned an HTTP response. */\nexport class BrowserQuickActionRpcError extends Schema.TaggedError<BrowserQuickActionRpcError>()(\n \"BrowserQuickActionRpcError\",\n {\n action: Schema.Literals([\"screenshot\", \"content\", \"markdown\", \"links\", \"scrape\", \"json\"]),\n cause: Schema.Defect(),\n },\n) {}\n\nexport interface BrowserQuickActionCaptureOptions {\n /** The resolved Wrangler `browser` binding (DEPLOY-014: supplied, never ambient). */\n readonly browser: BrowserRun;\n}\n\n/** Host-owned browser binding authority, supplied explicitly at the composition root. */\nexport class BrowserQuickActionBrowserBinding extends Context.Service<\n BrowserQuickActionBrowserBinding,\n BrowserQuickActionClient\n>()(\"@effect-agent/platform-cloudflare/BrowserQuickActionBrowserBinding\") {\n static layer(\n options: BrowserQuickActionCaptureOptions,\n ): Layer.Layer<BrowserQuickActionBrowserBinding> {\n const browser = options.browser;\n const invoke = Effect.fn(\"BrowserQuickActionBrowserBinding.invoke\")(function* (\n action: \"screenshot\" | \"content\" | \"markdown\" | \"links\" | \"scrape\" | \"json\",\n evaluate: () => Promise<Response>,\n ): Effect.fn.Return<Response, BrowserQuickActionRpcError> {\n return yield* Effect.tryPromise({\n try: evaluate,\n catch: (cause) => BrowserQuickActionRpcError.make({ action, cause }),\n });\n });\n return Layer.succeed(BrowserQuickActionBrowserBinding)({\n screenshot: (request) =>\n invoke(\"screenshot\", () => browser.quickAction(\"screenshot\", request)),\n content: (request) => invoke(\"content\", () => browser.quickAction(\"content\", request)),\n markdown: (request) => invoke(\"markdown\", () => browser.quickAction(\"markdown\", request)),\n links: (request) => invoke(\"links\", () => browser.quickAction(\"links\", request)),\n scrape: (request) => invoke(\"scrape\", () => browser.quickAction(\"scrape\", request)),\n json: (request) => invoke(\"json\", () => browser.quickAction(\"json\", request)),\n });\n }\n}\n\n/** Host-owned authorization and accounting for one Workers AI extraction. */\nexport interface BrowserQuickActionWorkersAiPolicy {\n readonly authorizeAndAccount: (\n request: PageCaptureRequest,\n ) => Effect.Effect<void, BrowserQuickActionWorkersAiPolicyError>;\n}\n\n/** Host-only diagnostic for a denied or unaccounted Workers AI extraction. */\nexport class BrowserQuickActionWorkersAiPolicyError extends Schema.TaggedError<BrowserQuickActionWorkersAiPolicyError>()(\n \"BrowserQuickActionWorkersAiPolicyError\",\n {\n reason: Schema.Literals([\"authorization\", \"accounting\"]),\n message: Schema.String.check(Schema.isMaxLength(8_000)),\n cause: Schema.optionalKey(Schema.Defect()),\n },\n) {}\n\n/** Explicit host-owned authority and accounting for separately billed Workers AI extraction. */\nexport class BrowserQuickActionWorkersAi extends Context.Service<\n BrowserQuickActionWorkersAi,\n BrowserQuickActionWorkersAiPolicy\n>()(\"@effect-agent/platform-cloudflare/BrowserQuickActionWorkersAi\") {\n static layer(\n policy: BrowserQuickActionWorkersAiPolicy,\n ): Layer.Layer<BrowserQuickActionWorkersAi> {\n return Layer.succeed(BrowserQuickActionWorkersAi)(policy);\n }\n}\n\nconst MAX_DIAGNOSTIC_LENGTH = 8_000;\nconst boundedDiagnostic = (message: string): string => message.slice(0, MAX_DIAGNOSTIC_LENGTH);\n\nconst QuickActionSuccessEnvelope = Schema.Struct({\n success: Schema.Literal(true),\n result: Schema.Json,\n});\n\nconst QuickActionErrorEnvelope = 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 detail: Schema.optionalKey(Schema.String),\n path: Schema.optionalKey(Schema.String),\n }),\n ),\n rawAiResponse: Schema.optionalKey(Schema.String),\n});\n\nconst QuickActionEnvelope = Schema.Union([QuickActionSuccessEnvelope, QuickActionErrorEnvelope]);\nconst decodeEnvelope = Schema.decodeUnknownOption(Schema.fromJsonString(QuickActionEnvelope));\n\n/** Project the schema-validated request onto Cloudflare's native common options. */\nconst quickActionCommonOptions = (request: PageCaptureRequest): BrowserRunCommonOptions => {\n const options: BrowserRunBaseOptions = {};\n const navigation = request.navigation;\n if (navigation !== undefined) {\n const goto: NonNullable<BrowserRunBaseOptions[\"gotoOptions\"]> = {};\n if (navigation.waitUntil !== undefined) goto.waitUntil = navigation.waitUntil;\n if (navigation.timeoutMillis !== undefined) goto.timeout = navigation.timeoutMillis;\n if (Object.keys(goto).length > 0) options.gotoOptions = goto;\n if (navigation.waitForSelector !== undefined) {\n options.waitForSelector = {\n selector: navigation.waitForSelector.selector,\n ...(navigation.waitForSelector.timeoutMillis === undefined\n ? {}\n : { timeout: navigation.waitForSelector.timeoutMillis }),\n };\n }\n }\n if (request.viewport !== undefined) {\n options.viewport = { width: request.viewport.width, height: request.viewport.height };\n }\n if (request.resourcePolicy !== undefined) {\n if (request.resourcePolicy.rejectResourceTypes !== undefined) {\n options.rejectResourceTypes = [...request.resourcePolicy.rejectResourceTypes];\n }\n if (request.resourcePolicy.allowRequestPatterns !== undefined) {\n options.allowRequestPattern = [...request.resourcePolicy.allowRequestPatterns];\n }\n }\n return request.target._tag === \"PageUrlTarget\"\n ? { ...options, url: request.target.url }\n : { ...options, html: request.target.html };\n};\n\n/** Dispatch through Cloudflare's native action-specific overloads. */\nconst executeQuickAction = (\n browser: BrowserQuickActionClient,\n request: PageCaptureRequest,\n): Effect.Effect<Response, BrowserQuickActionRpcError> => {\n const options = quickActionCommonOptions(request);\n switch (request.action._tag) {\n case \"CapturePageContent\": {\n return browser.content(options);\n }\n case \"CapturePageMarkdown\": {\n return browser.markdown(options);\n }\n case \"CapturePageLinks\": {\n return browser.links({\n ...options,\n ...(request.action.visibleLinksOnly === undefined\n ? {}\n : { visibleLinksOnly: request.action.visibleLinksOnly }),\n });\n }\n case \"CapturePageScrape\": {\n return browser.scrape({\n ...options,\n elements: request.action.selectors.map((selector) => ({ selector })),\n });\n }\n case \"CapturePageStructured\": {\n return browser.json({\n ...options,\n response_format: {\n type: \"json_schema\",\n json_schema: request.action.responseFormat,\n },\n ...(request.action.prompt === undefined ? {} : { prompt: request.action.prompt }),\n });\n }\n }\n};\n\nconst protocolError = (message: string, cause?: unknown): PageCaptureProtocolError =>\n PageCaptureProtocolError.make({\n implementation: browserQuickActionImplementation,\n message: boundedDiagnostic(message),\n ...(cause === undefined ? {} : { cause }),\n });\n\nconst navigationError = (message: string, cause?: unknown): PageCaptureNavigationError =>\n PageCaptureNavigationError.make({\n implementation: browserQuickActionImplementation,\n message: boundedDiagnostic(message),\n ...(cause === undefined ? {} : { cause }),\n });\n\n/** Preserve bounded remote diagnostics for the host without exposing their text to a model. */\nconst privateResponseCause = (bodyText: string): Error | undefined =>\n bodyText.length === 0 ? undefined : new Error(boundedDiagnostic(bodyText));\n\nconst releaseResponseReader = (\n reader: ReadableStreamDefaultReader<Uint8Array>,\n): Effect.Effect<void> =>\n Effect.tryPromise({\n try: () => reader.cancel(),\n catch: (cause) => protocolError(\"Canceling the Quick Action response failed\", cause),\n }).pipe(\n Effect.catch((error) => Effect.logWarning(error.message)),\n Effect.ensuring(\n Effect.try({\n try: () => reader.releaseLock(),\n catch: (cause) => protocolError(\"Releasing the Quick Action response failed\", cause),\n }).pipe(Effect.catch((error) => Effect.logWarning(error.message))),\n ),\n );\n\nconst readBoundedResponse = Effect.fn(\"BrowserQuickActionCapture.readResponse\")(function* (\n response: Response,\n request: PageCaptureRequest,\n) {\n const body = response.body;\n if (body === null) return \"\";\n\n const reader = yield* Effect.acquireRelease(\n Effect.try({\n try: () => body.getReader(),\n catch: (cause) => protocolError(\"Opening the Quick Action response failed\", cause),\n }),\n releaseResponseReader,\n );\n const decoder = new TextDecoder(\"utf-8\", { fatal: true, ignoreBOM: false });\n let observedBytes = 0;\n let bodyText = \"\";\n\n while (true) {\n const chunk = yield* Effect.tryPromise({\n try: () => reader.read(),\n catch: (cause) => protocolError(\"Reading the Quick Action response failed\", cause),\n });\n if (chunk.done) break;\n\n observedBytes += chunk.value.byteLength;\n if (observedBytes > request.limits.maxOutputBytes) {\n return yield* PageCaptureOutputLimitError.make({\n implementation: browserQuickActionImplementation,\n limit: request.limits.maxOutputBytes,\n observed: observedBytes,\n });\n }\n\n bodyText += yield* Effect.try({\n try: () => decoder.decode(chunk.value, { stream: true }),\n catch: (cause) => protocolError(\"Decoding the Quick Action response failed\", cause),\n });\n }\n\n return (\n bodyText +\n (yield* Effect.try({\n try: () => decoder.decode(),\n catch: (cause) => protocolError(\"Decoding the Quick Action response failed\", cause),\n }))\n );\n}, Effect.scoped);\n\n/**\n * Retry-After arrives in whole seconds; a non-integer form (an HTTP date) is\n * dropped rather than guessed at.\n */\nconst retryAfterMillis = (response: Response): number | undefined => {\n const header = response.headers.get(\"Retry-After\");\n if (header === null) return undefined;\n const seconds = Number(header);\n if (!Number.isSafeInteger(seconds) || seconds < 0) return undefined;\n const millis = seconds * 1_000;\n return Number.isSafeInteger(millis) ? millis : undefined;\n};\n\nconst browserMillis = (response: Response): number | undefined => {\n const header = response.headers.get(\"X-Browser-Ms-Used\");\n if (header === null) return undefined;\n const millis = Number(header);\n return Number.isSafeInteger(millis) && millis >= 0 ? millis : undefined;\n};\n\n/** Only trusted response metadata chooses transport framing; page text never does. */\nconst isJsonResponse = (response: Response): boolean => {\n const contentType = response.headers.get(\"Content-Type\");\n if (contentType === null) return false;\n const mediaType = contentType.split(\";\", 1)[0]?.trim().toLowerCase();\n return mediaType === \"application/json\" || mediaType?.endsWith(\"+json\") === true;\n};\n\nconst parseOutput = (\n action: PageCaptureAction,\n bodyText: string,\n response: Response,\n): PageCaptureOutput | PageCaptureNavigationError | PageCaptureProtocolError => {\n if (!isJsonResponse(response)) {\n return protocolError(\n \"The Quick Action success response was not a JSON response envelope\",\n privateResponseCause(bodyText),\n );\n }\n const envelope = decodeEnvelope(bodyText);\n if (Option.isNone(envelope)) {\n return protocolError(\n \"The JSON Quick Action response did not carry a valid response envelope\",\n privateResponseCause(bodyText),\n );\n }\n if (!envelope.value.success) {\n return navigationError(\n \"The Quick Action reported a navigation failure\",\n privateResponseCause(bodyText),\n );\n }\n switch (action._tag) {\n case \"CapturePageContent\":\n case \"CapturePageMarkdown\": {\n if (typeof envelope.value.result !== \"string\") {\n return protocolError(\"The Quick Action envelope carried a non-text result\");\n }\n return action._tag === \"CapturePageContent\"\n ? PageContentCaptured.make({ html: envelope.value.result })\n : PageMarkdownCaptured.make({ markdown: envelope.value.result });\n }\n case \"CapturePageLinks\": {\n const decoded = Schema.decodeUnknownOption(PageLinksCaptured)({\n _tag: \"PageLinksCaptured\",\n links: envelope.value.result,\n });\n if (Option.isNone(decoded)) {\n return protocolError(\"The links Quick Action did not return a bounded array of valid URLs\");\n }\n return decoded.value;\n }\n case \"CapturePageScrape\": {\n const decoded = Schema.decodeUnknownOption(PageScrapeCaptured)({\n _tag: \"PageScrapeCaptured\",\n groups: envelope.value.result,\n });\n if (Option.isNone(decoded)) {\n return protocolError(\n \"The scrape Quick Action did not return bounded grouped element records\",\n );\n }\n return decoded.value;\n }\n case \"CapturePageStructured\": {\n return PageStructuredCaptured.make({ value: envelope.value.result });\n }\n }\n};\n\nconst isQuotaMessage = (text: string): boolean => /time limit|daily|quota/i.test(text);\n\nconst makeCapture = (\n browser: BrowserQuickActionClient,\n workersAi?: BrowserQuickActionWorkersAiPolicy,\n): PageCaptureCapture =>\n Effect.fn(\"BrowserQuickActionCapture.capture\")(function* (\n request: PageCaptureRequest,\n ): Effect.fn.Return<PageCaptureResult, PageCaptureError> {\n if (request.engine !== \"chromium\") {\n return yield* PageCaptureUnsupportedError.make({\n implementation: browserQuickActionImplementation,\n feature: \"engine\",\n message:\n \"The browser binding's quickAction() exposes no engine selector; kitesurf requires the REST or CDP surface\",\n });\n }\n\n const usesWorkersAi = request.action._tag === \"CapturePageStructured\";\n if (usesWorkersAi) {\n if (workersAi === undefined) {\n return yield* PageCaptureUnsupportedError.make({\n implementation: browserQuickActionImplementation,\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: browserQuickActionImplementation,\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\n const response = yield* executeQuickAction(browser, request).pipe(\n Effect.mapError((error) =>\n protocolError(\"The browser binding rejected the Quick Action\", error.cause),\n ),\n );\n const bodyText = yield* readBoundedResponse(response, request);\n if (response.status === 429) {\n const retryAfter = retryAfterMillis(response);\n const reason = isQuotaMessage(bodyText) ? \"quota\" : \"rate\";\n const cause = privateResponseCause(bodyText);\n return yield* PageCaptureRateLimitedError.make({\n implementation: browserQuickActionImplementation,\n reason,\n ...(retryAfter === undefined ? {} : { retryAfterMillis: retryAfter }),\n ...(cause === undefined ? {} : { cause }),\n message:\n reason === \"quota\"\n ? \"The Quick Action exceeded its browser quota\"\n : \"The Quick Action was rate limited\",\n });\n }\n if (!response.ok) {\n const message = `The Quick Action answered HTTP ${response.status}`;\n const cause = privateResponseCause(bodyText);\n if (response.status >= 500) {\n return yield* protocolError(message, cause);\n }\n return yield* navigationError(message, cause);\n }\n const output = parseOutput(request.action, bodyText, response);\n if (\n output._tag === \"PageCaptureNavigationError\" ||\n output._tag === \"PageCaptureProtocolError\"\n ) {\n return yield* output;\n }\n const millis = browserMillis(response);\n return PageCaptureResult.make({\n implementation: browserQuickActionImplementation,\n output,\n resourceUse: PageCaptureResourceUse.make({\n ...(millis === undefined ? {} : { browserMillis: millis }),\n ...(usesWorkersAi\n ? {\n inference: PageCaptureInferenceUse.make({\n provider: \"cloudflare-workers-ai\",\n modelCalls: 1,\n }),\n }\n : {}),\n }),\n });\n });\n\n/**\n * Ordinary Quick Actions require host-owned browser binding authority. Workers\n * AI stays unavailable unless the host deliberately selects its separate Layer.\n */\nexport const browserQuickActionCaptureLayer = (): Layer.Layer<\n PageCapture,\n never,\n BrowserQuickActionBrowserBinding\n> =>\n Layer.effect(\n PageCapture,\n Effect.map(BrowserQuickActionBrowserBinding, (browser) =>\n PageCapture.of({ capture: makeCapture(browser) }),\n ),\n );\n\n/** Structured Quick Actions require host-owned browser and Workers AI authority. */\nexport const browserQuickActionWorkersAiCaptureLayer = (): Layer.Layer<\n PageCapture,\n never,\n BrowserQuickActionBrowserBinding | BrowserQuickActionWorkersAi\n> =>\n Layer.effect(\n PageCapture,\n Effect.gen(function* () {\n const browser = yield* BrowserQuickActionBrowserBinding;\n const workersAi = yield* BrowserQuickActionWorkersAi;\n return PageCapture.of({ capture: makeCapture(browser, workersAi) });\n }),\n );\n\nconst screenshotOptions = (request: PageScreenshotRequest): BrowserRunScreenshotOptions => {\n const options: BrowserRunBaseOptions = {};\n if (\n request.navigation?.waitUntil !== undefined ||\n request.navigation?.timeoutMillis !== undefined\n ) {\n options.gotoOptions = {\n ...(request.navigation.waitUntil === undefined\n ? {}\n : { waitUntil: request.navigation.waitUntil }),\n ...(request.navigation.timeoutMillis === undefined\n ? {}\n : { timeout: request.navigation.timeoutMillis }),\n };\n }\n if (request.navigation?.waitForSelector !== undefined) {\n options.waitForSelector = {\n selector: request.navigation.waitForSelector.selector,\n ...(request.navigation.waitForSelector.timeoutMillis === undefined\n ? {}\n : { timeout: request.navigation.waitForSelector.timeoutMillis }),\n };\n }\n if (request.viewport !== undefined) {\n options.viewport = { width: request.viewport.width, height: request.viewport.height };\n }\n if (request.resourcePolicy?.rejectResourceTypes !== undefined) {\n options.rejectResourceTypes = [...request.resourcePolicy.rejectResourceTypes];\n }\n if (request.resourcePolicy?.allowRequestPatterns !== undefined) {\n options.allowRequestPattern = [...request.resourcePolicy.allowRequestPatterns];\n }\n return {\n ...options,\n ...(request.target._tag === \"PageUrlTarget\"\n ? { url: request.target.url }\n : { html: request.target.html }),\n screenshotOptions: { type: \"png\", encoding: \"binary\", fullPage: request.fullPage },\n };\n};\n\nconst cancelBody = (body: ReadableStream<Uint8Array>): Effect.Effect<void> =>\n Effect.tryPromise({\n try: () => body.cancel(),\n catch: () => undefined,\n }).pipe(Effect.catch(() => Effect.void));\n\nconst releaseScreenshotReader = (\n reader: ReadableStreamDefaultReader<Uint8Array>,\n): Effect.Effect<void> =>\n Effect.tryPromise({ try: () => reader.cancel(), catch: () => undefined }).pipe(\n Effect.catch(() => Effect.logWarning(\"Canceling the screenshot response failed\")),\n Effect.ensuring(\n Effect.try({\n try: () => reader.releaseLock(),\n catch: () => undefined,\n }).pipe(Effect.catch(() => Effect.logWarning(\"Releasing the screenshot response failed\"))),\n ),\n );\n\nconst pngResponse = (response: Response): boolean =>\n response.headers.get(\"Content-Type\")?.split(\";\", 1)[0]?.trim().toLowerCase() === \"image/png\";\n\nconst declaredLength = (response: Response): number | undefined => {\n const raw = response.headers.get(\"Content-Length\");\n if (raw === null || !/^(0|[1-9][0-9]*)$/.test(raw)) return undefined;\n const length = Number(raw);\n return Number.isSafeInteger(length) ? length : undefined;\n};\n\nconst readScreenshot = Effect.fn(\"BrowserQuickActionScreenshot.read\")(function* (\n response: Response,\n request: PageScreenshotRequest,\n) {\n const body = response.body;\n if (body === null) {\n return yield* protocolError(\"The screenshot response had no body\");\n }\n if (!pngResponse(response)) {\n yield* cancelBody(body);\n return yield* protocolError(\"The screenshot response was not image/png\");\n }\n const length = declaredLength(response);\n if (length !== undefined && length > request.limits.maxOutputBytes) {\n yield* cancelBody(body);\n return yield* PageScreenshotOutputLimitError.make({\n implementation: browserQuickActionImplementation,\n limit: request.limits.maxOutputBytes,\n observed: length,\n });\n }\n const reader = yield* Effect.acquireRelease(\n Effect.try({\n try: () => body.getReader(),\n catch: (cause) => protocolError(\"Opening the screenshot response failed\", cause),\n }),\n releaseScreenshotReader,\n );\n const chunks: Array<Uint8Array> = [];\n let observed = 0;\n while (true) {\n const next = yield* Effect.tryPromise({\n try: () => reader.read(),\n catch: (cause) => protocolError(\"Reading the screenshot response failed\", cause),\n });\n if (next.done) break;\n observed += next.value.byteLength;\n if (observed > request.limits.maxOutputBytes) {\n return yield* PageScreenshotOutputLimitError.make({\n implementation: browserQuickActionImplementation,\n limit: request.limits.maxOutputBytes,\n observed,\n });\n }\n chunks.push(next.value);\n }\n const bytes = new Uint8Array(observed);\n let offset = 0;\n for (const chunk of chunks) {\n bytes.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return bytes;\n}, Effect.scoped);\n\nconst makeScreenshot = (browser: BrowserQuickActionClient): PageScreenshotCapture =>\n Effect.fn(\"BrowserQuickActionScreenshot.capture\")(function* (\n request: PageScreenshotRequest,\n ): Effect.fn.Return<PageScreenshotResult, PageScreenshotError> {\n if (request.engine !== \"chromium\") {\n return yield* PageCaptureUnsupportedError.make({\n implementation: browserQuickActionImplementation,\n feature: \"engine\",\n message: \"The browser binding's screenshot action exposes no engine selector\",\n });\n }\n const response = yield* browser\n .screenshot(screenshotOptions(request))\n .pipe(\n Effect.mapError((error) =>\n protocolError(\"The browser binding rejected the screenshot\", error.cause),\n ),\n );\n if (response.status === 429) {\n const body = response.body;\n if (body !== null) yield* cancelBody(body);\n return yield* PageCaptureRateLimitedError.make({\n implementation: browserQuickActionImplementation,\n reason: \"rate\",\n ...(retryAfterMillis(response) === undefined\n ? {}\n : { retryAfterMillis: retryAfterMillis(response) }),\n message: \"The screenshot Quick Action was rate limited\",\n });\n }\n if (!response.ok) {\n const body = response.body;\n if (body !== null) yield* cancelBody(body);\n const message = `The screenshot Quick Action answered HTTP ${response.status}`;\n return yield* response.status >= 500 ? protocolError(message) : navigationError(message);\n }\n const bytes = yield* readScreenshot(response, request);\n return PageScreenshotResult.make({\n implementation: browserQuickActionImplementation,\n mediaType: \"image/png\",\n bytes,\n });\n });\n\n/** Native Browser Run screenshot adapter. It retains PNG bytes only for the caller's result. */\nexport const browserQuickActionScreenshotLayer = (): Layer.Layer<\n PageScreenshot,\n never,\n BrowserQuickActionBrowserBinding\n> =>\n Layer.effect(\n PageScreenshot,\n Effect.map(BrowserQuickActionBrowserBinding, (browser) =>\n PageScreenshot.of({ capture: makeScreenshot(browser) }),\n ),\n );\n"],"mappings":";;;;;;;;;;;;;;;;AA8CA,MAAa,mCAAmC,sBAAsB,KAAK;CACzE,WAAW;CACX,UAAU;AACZ,CAAC;;AA4BD,IAAa,6BAAb,cAAgD,OAAO,YAAwC,CAAC,CAC9F,8BACA;CACE,QAAQ,OAAO,SAAS;EAAC;EAAc;EAAW;EAAY;EAAS;EAAU;CAAM,CAAC;CACxF,OAAO,OAAO,OAAO;AACvB,CACF,CAAC,CAAC,CAAC;;AAQH,IAAa,mCAAb,MAAa,yCAAyC,QAAQ,QAG5D,CAAC,CAAC,oEAAoE,CAAC,CAAC;CACxE,OAAO,MACL,SAC+C;EAC/C,MAAM,UAAU,QAAQ;EACxB,MAAM,SAAS,OAAO,GAAG,yCAAyC,CAAC,CAAC,WAClE,QACA,UACwD;GACxD,OAAO,OAAO,OAAO,WAAW;IAC9B,KAAK;IACL,QAAQ,UAAU,2BAA2B,KAAK;KAAE;KAAQ;IAAM,CAAC;GACrE,CAAC;EACH,CAAC;EACD,OAAO,MAAM,QAAQ,gCAAgC,CAAC,CAAC;GACrD,aAAa,YACX,OAAO,oBAAoB,QAAQ,YAAY,cAAc,OAAO,CAAC;GACvE,UAAU,YAAY,OAAO,iBAAiB,QAAQ,YAAY,WAAW,OAAO,CAAC;GACrF,WAAW,YAAY,OAAO,kBAAkB,QAAQ,YAAY,YAAY,OAAO,CAAC;GACxF,QAAQ,YAAY,OAAO,eAAe,QAAQ,YAAY,SAAS,OAAO,CAAC;GAC/E,SAAS,YAAY,OAAO,gBAAgB,QAAQ,YAAY,UAAU,OAAO,CAAC;GAClF,OAAO,YAAY,OAAO,cAAc,QAAQ,YAAY,QAAQ,OAAO,CAAC;EAC9E,CAAC;CACH;AACF;;AAUA,IAAa,yCAAb,cAA4D,OAAO,YAAoD,CAAC,CACtH,0CACA;CACE,QAAQ,OAAO,SAAS,CAAC,iBAAiB,YAAY,CAAC;CACvD,SAAS,OAAO,OAAO,MAAM,OAAO,YAAY,GAAK,CAAC;CACtD,OAAO,OAAO,YAAY,OAAO,OAAO,CAAC;AAC3C,CACF,CAAC,CAAC,CAAC;;AAGH,IAAa,8BAAb,MAAa,oCAAoC,QAAQ,QAGvD,CAAC,CAAC,+DAA+D,CAAC,CAAC;CACnE,OAAO,MACL,QAC0C;EAC1C,OAAO,MAAM,QAAQ,2BAA2B,CAAC,CAAC,MAAM;CAC1D;AACF;AAEA,MAAM,wBAAwB;AAC9B,MAAM,qBAAqB,YAA4B,QAAQ,MAAM,GAAG,qBAAqB;AAE7F,MAAM,6BAA6B,OAAO,OAAO;CAC/C,SAAS,OAAO,QAAQ,IAAI;CAC5B,QAAQ,OAAO;AACjB,CAAC;AAED,MAAM,2BAA2B,OAAO,OAAO;CAC7C,SAAS,OAAO,QAAQ,KAAK;CAC7B,QAAQ,OAAO,MACb,OAAO,OAAO;EACZ,SAAS,OAAO;EAChB,MAAM,OAAO,YAAY,OAAO,MAAM;EACtC,QAAQ,OAAO,YAAY,OAAO,MAAM;EACxC,MAAM,OAAO,YAAY,OAAO,MAAM;CACxC,CAAC,CACH;CACA,eAAe,OAAO,YAAY,OAAO,MAAM;AACjD,CAAC;AAED,MAAM,sBAAsB,OAAO,MAAM,CAAC,4BAA4B,wBAAwB,CAAC;AAC/F,MAAM,iBAAiB,OAAO,oBAAoB,OAAO,eAAe,mBAAmB,CAAC;;AAG5F,MAAM,4BAA4B,YAAyD;CACzF,MAAM,UAAiC,CAAC;CACxC,MAAM,aAAa,QAAQ;CAC3B,IAAI,eAAe,KAAA,GAAW;EAC5B,MAAM,OAA0D,CAAC;EACjE,IAAI,WAAW,cAAc,KAAA,GAAW,KAAK,YAAY,WAAW;EACpE,IAAI,WAAW,kBAAkB,KAAA,GAAW,KAAK,UAAU,WAAW;EACtE,IAAI,OAAO,KAAK,IAAI,CAAC,CAAC,SAAS,GAAG,QAAQ,cAAc;EACxD,IAAI,WAAW,oBAAoB,KAAA,GACjC,QAAQ,kBAAkB;GACxB,UAAU,WAAW,gBAAgB;GACrC,GAAI,WAAW,gBAAgB,kBAAkB,KAAA,IAC7C,CAAC,IACD,EAAE,SAAS,WAAW,gBAAgB,cAAc;EAC1D;CAEJ;CACA,IAAI,QAAQ,aAAa,KAAA,GACvB,QAAQ,WAAW;EAAE,OAAO,QAAQ,SAAS;EAAO,QAAQ,QAAQ,SAAS;CAAO;CAEtF,IAAI,QAAQ,mBAAmB,KAAA,GAAW;EACxC,IAAI,QAAQ,eAAe,wBAAwB,KAAA,GACjD,QAAQ,sBAAsB,CAAC,GAAG,QAAQ,eAAe,mBAAmB;EAE9E,IAAI,QAAQ,eAAe,yBAAyB,KAAA,GAClD,QAAQ,sBAAsB,CAAC,GAAG,QAAQ,eAAe,oBAAoB;CAEjF;CACA,OAAO,QAAQ,OAAO,SAAS,kBAC3B;EAAE,GAAG;EAAS,KAAK,QAAQ,OAAO;CAAI,IACtC;EAAE,GAAG;EAAS,MAAM,QAAQ,OAAO;CAAK;AAC9C;;AAGA,MAAM,sBACJ,SACA,YACwD;CACxD,MAAM,UAAU,yBAAyB,OAAO;CAChD,QAAQ,QAAQ,OAAO,MAAvB;EACE,KAAK,sBACH,OAAO,QAAQ,QAAQ,OAAO;EAEhC,KAAK,uBACH,OAAO,QAAQ,SAAS,OAAO;EAEjC,KAAK,oBACH,OAAO,QAAQ,MAAM;GACnB,GAAG;GACH,GAAI,QAAQ,OAAO,qBAAqB,KAAA,IACpC,CAAC,IACD,EAAE,kBAAkB,QAAQ,OAAO,iBAAiB;EAC1D,CAAC;EAEH,KAAK,qBACH,OAAO,QAAQ,OAAO;GACpB,GAAG;GACH,UAAU,QAAQ,OAAO,UAAU,KAAK,cAAc,EAAE,SAAS,EAAE;EACrE,CAAC;EAEH,KAAK,yBACH,OAAO,QAAQ,KAAK;GAClB,GAAG;GACH,iBAAiB;IACf,MAAM;IACN,aAAa,QAAQ,OAAO;GAC9B;GACA,GAAI,QAAQ,OAAO,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ,QAAQ,OAAO,OAAO;EACjF,CAAC;CAEL;AACF;AAEA,MAAM,iBAAiB,SAAiB,UACtC,yBAAyB,KAAK;CAC5B,gBAAgB;CAChB,SAAS,kBAAkB,OAAO;CAClC,GAAI,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM;AACzC,CAAC;AAEH,MAAM,mBAAmB,SAAiB,UACxC,2BAA2B,KAAK;CAC9B,gBAAgB;CAChB,SAAS,kBAAkB,OAAO;CAClC,GAAI,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM;AACzC,CAAC;;AAGH,MAAM,wBAAwB,aAC5B,SAAS,WAAW,IAAI,KAAA,IAAY,IAAI,MAAM,kBAAkB,QAAQ,CAAC;AAE3E,MAAM,yBACJ,WAEA,OAAO,WAAW;CAChB,WAAW,OAAO,OAAO;CACzB,QAAQ,UAAU,cAAc,8CAA8C,KAAK;AACrF,CAAC,CAAC,CAAC,KACD,OAAO,OAAO,UAAU,OAAO,WAAW,MAAM,OAAO,CAAC,GACxD,OAAO,SACL,OAAO,IAAI;CACT,WAAW,OAAO,YAAY;CAC9B,QAAQ,UAAU,cAAc,8CAA8C,KAAK;AACrF,CAAC,CAAC,CAAC,KAAK,OAAO,OAAO,UAAU,OAAO,WAAW,MAAM,OAAO,CAAC,CAAC,CACnE,CACF;AAEF,MAAM,sBAAsB,OAAO,GAAG,wCAAwC,CAAC,CAAC,WAC9E,UACA,SACA;CACA,MAAM,OAAO,SAAS;CACtB,IAAI,SAAS,MAAM,OAAO;CAE1B,MAAM,SAAS,OAAO,OAAO,eAC3B,OAAO,IAAI;EACT,WAAW,KAAK,UAAU;EAC1B,QAAQ,UAAU,cAAc,4CAA4C,KAAK;CACnF,CAAC,GACD,qBACF;CACA,MAAM,UAAU,IAAI,YAAY,SAAS;EAAE,OAAO;EAAM,WAAW;CAAM,CAAC;CAC1E,IAAI,gBAAgB;CACpB,IAAI,WAAW;CAEf,OAAO,MAAM;EACX,MAAM,QAAQ,OAAO,OAAO,WAAW;GACrC,WAAW,OAAO,KAAK;GACvB,QAAQ,UAAU,cAAc,4CAA4C,KAAK;EACnF,CAAC;EACD,IAAI,MAAM,MAAM;EAEhB,iBAAiB,MAAM,MAAM;EAC7B,IAAI,gBAAgB,QAAQ,OAAO,gBACjC,OAAO,OAAO,4BAA4B,KAAK;GAC7C,gBAAgB;GAChB,OAAO,QAAQ,OAAO;GACtB,UAAU;EACZ,CAAC;EAGH,YAAY,OAAO,OAAO,IAAI;GAC5B,WAAW,QAAQ,OAAO,MAAM,OAAO,EAAE,QAAQ,KAAK,CAAC;GACvD,QAAQ,UAAU,cAAc,6CAA6C,KAAK;EACpF,CAAC;CACH;CAEA,OACE,YACC,OAAO,OAAO,IAAI;EACjB,WAAW,QAAQ,OAAO;EAC1B,QAAQ,UAAU,cAAc,6CAA6C,KAAK;CACpF,CAAC;AAEL,GAAG,OAAO,MAAM;;;;;AAMhB,MAAM,oBAAoB,aAA2C;CACnE,MAAM,SAAS,SAAS,QAAQ,IAAI,aAAa;CACjD,IAAI,WAAW,MAAM,OAAO,KAAA;CAC5B,MAAM,UAAU,OAAO,MAAM;CAC7B,IAAI,CAAC,OAAO,cAAc,OAAO,KAAK,UAAU,GAAG,OAAO,KAAA;CAC1D,MAAM,SAAS,UAAU;CACzB,OAAO,OAAO,cAAc,MAAM,IAAI,SAAS,KAAA;AACjD;AAEA,MAAM,iBAAiB,aAA2C;CAChE,MAAM,SAAS,SAAS,QAAQ,IAAI,mBAAmB;CACvD,IAAI,WAAW,MAAM,OAAO,KAAA;CAC5B,MAAM,SAAS,OAAO,MAAM;CAC5B,OAAO,OAAO,cAAc,MAAM,KAAK,UAAU,IAAI,SAAS,KAAA;AAChE;;AAGA,MAAM,kBAAkB,aAAgC;CACtD,MAAM,cAAc,SAAS,QAAQ,IAAI,cAAc;CACvD,IAAI,gBAAgB,MAAM,OAAO;CACjC,MAAM,YAAY,YAAY,MAAM,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,YAAY;CACnE,OAAO,cAAc,sBAAsB,WAAW,SAAS,OAAO,MAAM;AAC9E;AAEA,MAAM,eACJ,QACA,UACA,aAC8E;CAC9E,IAAI,CAAC,eAAe,QAAQ,GAC1B,OAAO,cACL,sEACA,qBAAqB,QAAQ,CAC/B;CAEF,MAAM,WAAW,eAAe,QAAQ;CACxC,IAAI,OAAO,OAAO,QAAQ,GACxB,OAAO,cACL,0EACA,qBAAqB,QAAQ,CAC/B;CAEF,IAAI,CAAC,SAAS,MAAM,SAClB,OAAO,gBACL,kDACA,qBAAqB,QAAQ,CAC/B;CAEF,QAAQ,OAAO,MAAf;EACE,KAAK;EACL,KAAK;GACH,IAAI,OAAO,SAAS,MAAM,WAAW,UACnC,OAAO,cAAc,qDAAqD;GAE5E,OAAO,OAAO,SAAS,uBACnB,oBAAoB,KAAK,EAAE,MAAM,SAAS,MAAM,OAAO,CAAC,IACxD,qBAAqB,KAAK,EAAE,UAAU,SAAS,MAAM,OAAO,CAAC;EAEnE,KAAK,oBAAoB;GACvB,MAAM,UAAU,OAAO,oBAAoB,iBAAiB,CAAC,CAAC;IAC5D,MAAM;IACN,OAAO,SAAS,MAAM;GACxB,CAAC;GACD,IAAI,OAAO,OAAO,OAAO,GACvB,OAAO,cAAc,qEAAqE;GAE5F,OAAO,QAAQ;EACjB;EACA,KAAK,qBAAqB;GACxB,MAAM,UAAU,OAAO,oBAAoB,kBAAkB,CAAC,CAAC;IAC7D,MAAM;IACN,QAAQ,SAAS,MAAM;GACzB,CAAC;GACD,IAAI,OAAO,OAAO,OAAO,GACvB,OAAO,cACL,wEACF;GAEF,OAAO,QAAQ;EACjB;EACA,KAAK,yBACH,OAAO,uBAAuB,KAAK,EAAE,OAAO,SAAS,MAAM,OAAO,CAAC;CAEvE;AACF;AAEA,MAAM,kBAAkB,SAA0B,0BAA0B,KAAK,IAAI;AAErF,MAAM,eACJ,SACA,cAEA,OAAO,GAAG,mCAAmC,CAAC,CAAC,WAC7C,SACuD;CACvD,IAAI,QAAQ,WAAW,YACrB,OAAO,OAAO,4BAA4B,KAAK;EAC7C,gBAAgB;EAChB,SAAS;EACT,SACE;CACJ,CAAC;CAGH,MAAM,gBAAgB,QAAQ,OAAO,SAAS;CAC9C,IAAI,eAAe;EACjB,IAAI,cAAc,KAAA,GAChB,OAAO,OAAO,4BAA4B,KAAK;GAC7C,gBAAgB;GAChB,SAAS;GACT,SACE;EACJ,CAAC;EAEH,OAAO,UAAU,oBAAoB,OAAO,CAAC,CAAC,KAC5C,OAAO,UAAU,UACf,gCAAgC,KAAK;GACnC,gBAAgB;GAChB,UAAU;GACV,QAAQ,MAAM;GACd,SACE,MAAM,WAAW,kBACb,6CACA;GACN;EACF,CAAC,CACH,CACF;CACF;CAEA,MAAM,WAAW,OAAO,mBAAmB,SAAS,OAAO,CAAC,CAAC,KAC3D,OAAO,UAAU,UACf,cAAc,iDAAiD,MAAM,KAAK,CAC5E,CACF;CACA,MAAM,WAAW,OAAO,oBAAoB,UAAU,OAAO;CAC7D,IAAI,SAAS,WAAW,KAAK;EAC3B,MAAM,aAAa,iBAAiB,QAAQ;EAC5C,MAAM,SAAS,eAAe,QAAQ,IAAI,UAAU;EACpD,MAAM,QAAQ,qBAAqB,QAAQ;EAC3C,OAAO,OAAO,4BAA4B,KAAK;GAC7C,gBAAgB;GAChB;GACA,GAAI,eAAe,KAAA,IAAY,CAAC,IAAI,EAAE,kBAAkB,WAAW;GACnE,GAAI,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM;GACvC,SACE,WAAW,UACP,gDACA;EACR,CAAC;CACH;CACA,IAAI,CAAC,SAAS,IAAI;EAChB,MAAM,UAAU,kCAAkC,SAAS;EAC3D,MAAM,QAAQ,qBAAqB,QAAQ;EAC3C,IAAI,SAAS,UAAU,KACrB,OAAO,OAAO,cAAc,SAAS,KAAK;EAE5C,OAAO,OAAO,gBAAgB,SAAS,KAAK;CAC9C;CACA,MAAM,SAAS,YAAY,QAAQ,QAAQ,UAAU,QAAQ;CAC7D,IACE,OAAO,SAAS,gCAChB,OAAO,SAAS,4BAEhB,OAAO,OAAO;CAEhB,MAAM,SAAS,cAAc,QAAQ;CACrC,OAAO,kBAAkB,KAAK;EAC5B,gBAAgB;EAChB;EACA,aAAa,uBAAuB,KAAK;GACvC,GAAI,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,eAAe,OAAO;GACxD,GAAI,gBACA,EACE,WAAW,wBAAwB,KAAK;IACtC,UAAU;IACV,YAAY;GACd,CAAC,EACH,IACA,CAAC;EACP,CAAC;CACH,CAAC;AACH,CAAC;;;;;AAMH,MAAa,uCAKX,MAAM,OACJ,aACA,OAAO,IAAI,mCAAmC,YAC5C,YAAY,GAAG,EAAE,SAAS,YAAY,OAAO,EAAE,CAAC,CAClD,CACF;;AAGF,MAAa,gDAKX,MAAM,OACJ,aACA,OAAO,IAAI,aAAa;CACtB,MAAM,UAAU,OAAO;CACvB,MAAM,YAAY,OAAO;CACzB,OAAO,YAAY,GAAG,EAAE,SAAS,YAAY,SAAS,SAAS,EAAE,CAAC;AACpE,CAAC,CACH;AAEF,MAAM,qBAAqB,YAAgE;CACzF,MAAM,UAAiC,CAAC;CACxC,IACE,QAAQ,YAAY,cAAc,KAAA,KAClC,QAAQ,YAAY,kBAAkB,KAAA,GAEtC,QAAQ,cAAc;EACpB,GAAI,QAAQ,WAAW,cAAc,KAAA,IACjC,CAAC,IACD,EAAE,WAAW,QAAQ,WAAW,UAAU;EAC9C,GAAI,QAAQ,WAAW,kBAAkB,KAAA,IACrC,CAAC,IACD,EAAE,SAAS,QAAQ,WAAW,cAAc;CAClD;CAEF,IAAI,QAAQ,YAAY,oBAAoB,KAAA,GAC1C,QAAQ,kBAAkB;EACxB,UAAU,QAAQ,WAAW,gBAAgB;EAC7C,GAAI,QAAQ,WAAW,gBAAgB,kBAAkB,KAAA,IACrD,CAAC,IACD,EAAE,SAAS,QAAQ,WAAW,gBAAgB,cAAc;CAClE;CAEF,IAAI,QAAQ,aAAa,KAAA,GACvB,QAAQ,WAAW;EAAE,OAAO,QAAQ,SAAS;EAAO,QAAQ,QAAQ,SAAS;CAAO;CAEtF,IAAI,QAAQ,gBAAgB,wBAAwB,KAAA,GAClD,QAAQ,sBAAsB,CAAC,GAAG,QAAQ,eAAe,mBAAmB;CAE9E,IAAI,QAAQ,gBAAgB,yBAAyB,KAAA,GACnD,QAAQ,sBAAsB,CAAC,GAAG,QAAQ,eAAe,oBAAoB;CAE/E,OAAO;EACL,GAAG;EACH,GAAI,QAAQ,OAAO,SAAS,kBACxB,EAAE,KAAK,QAAQ,OAAO,IAAI,IAC1B,EAAE,MAAM,QAAQ,OAAO,KAAK;EAChC,mBAAmB;GAAE,MAAM;GAAO,UAAU;GAAU,UAAU,QAAQ;EAAS;CACnF;AACF;AAEA,MAAM,cAAc,SAClB,OAAO,WAAW;CAChB,WAAW,KAAK,OAAO;CACvB,aAAa,KAAA;AACf,CAAC,CAAC,CAAC,KAAK,OAAO,YAAY,OAAO,IAAI,CAAC;AAEzC,MAAM,2BACJ,WAEA,OAAO,WAAW;CAAE,WAAW,OAAO,OAAO;CAAG,aAAa,KAAA;AAAU,CAAC,CAAC,CAAC,KACxE,OAAO,YAAY,OAAO,WAAW,0CAA0C,CAAC,GAChF,OAAO,SACL,OAAO,IAAI;CACT,WAAW,OAAO,YAAY;CAC9B,aAAa,KAAA;AACf,CAAC,CAAC,CAAC,KAAK,OAAO,YAAY,OAAO,WAAW,0CAA0C,CAAC,CAAC,CAC3F,CACF;AAEF,MAAM,eAAe,aACnB,SAAS,QAAQ,IAAI,cAAc,CAAC,EAAE,MAAM,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,YAAY,MAAM;AAEnF,MAAM,kBAAkB,aAA2C;CACjE,MAAM,MAAM,SAAS,QAAQ,IAAI,gBAAgB;CACjD,IAAI,QAAQ,QAAQ,CAAC,oBAAoB,KAAK,GAAG,GAAG,OAAO,KAAA;CAC3D,MAAM,SAAS,OAAO,GAAG;CACzB,OAAO,OAAO,cAAc,MAAM,IAAI,SAAS,KAAA;AACjD;AAEA,MAAM,iBAAiB,OAAO,GAAG,mCAAmC,CAAC,CAAC,WACpE,UACA,SACA;CACA,MAAM,OAAO,SAAS;CACtB,IAAI,SAAS,MACX,OAAO,OAAO,cAAc,qCAAqC;CAEnE,IAAI,CAAC,YAAY,QAAQ,GAAG;EAC1B,OAAO,WAAW,IAAI;EACtB,OAAO,OAAO,cAAc,2CAA2C;CACzE;CACA,MAAM,SAAS,eAAe,QAAQ;CACtC,IAAI,WAAW,KAAA,KAAa,SAAS,QAAQ,OAAO,gBAAgB;EAClE,OAAO,WAAW,IAAI;EACtB,OAAO,OAAO,+BAA+B,KAAK;GAChD,gBAAgB;GAChB,OAAO,QAAQ,OAAO;GACtB,UAAU;EACZ,CAAC;CACH;CACA,MAAM,SAAS,OAAO,OAAO,eAC3B,OAAO,IAAI;EACT,WAAW,KAAK,UAAU;EAC1B,QAAQ,UAAU,cAAc,0CAA0C,KAAK;CACjF,CAAC,GACD,uBACF;CACA,MAAM,SAA4B,CAAC;CACnC,IAAI,WAAW;CACf,OAAO,MAAM;EACX,MAAM,OAAO,OAAO,OAAO,WAAW;GACpC,WAAW,OAAO,KAAK;GACvB,QAAQ,UAAU,cAAc,0CAA0C,KAAK;EACjF,CAAC;EACD,IAAI,KAAK,MAAM;EACf,YAAY,KAAK,MAAM;EACvB,IAAI,WAAW,QAAQ,OAAO,gBAC5B,OAAO,OAAO,+BAA+B,KAAK;GAChD,gBAAgB;GAChB,OAAO,QAAQ,OAAO;GACtB;EACF,CAAC;EAEH,OAAO,KAAK,KAAK,KAAK;CACxB;CACA,MAAM,QAAQ,IAAI,WAAW,QAAQ;CACrC,IAAI,SAAS;CACb,KAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,IAAI,OAAO,MAAM;EACvB,UAAU,MAAM;CAClB;CACA,OAAO;AACT,GAAG,OAAO,MAAM;AAEhB,MAAM,kBAAkB,YACtB,OAAO,GAAG,sCAAsC,CAAC,CAAC,WAChD,SAC6D;CAC7D,IAAI,QAAQ,WAAW,YACrB,OAAO,OAAO,4BAA4B,KAAK;EAC7C,gBAAgB;EAChB,SAAS;EACT,SAAS;CACX,CAAC;CAEH,MAAM,WAAW,OAAO,QACrB,WAAW,kBAAkB,OAAO,CAAC,CAAC,CACtC,KACC,OAAO,UAAU,UACf,cAAc,+CAA+C,MAAM,KAAK,CAC1E,CACF;CACF,IAAI,SAAS,WAAW,KAAK;EAC3B,MAAM,OAAO,SAAS;EACtB,IAAI,SAAS,MAAM,OAAO,WAAW,IAAI;EACzC,OAAO,OAAO,4BAA4B,KAAK;GAC7C,gBAAgB;GAChB,QAAQ;GACR,GAAI,iBAAiB,QAAQ,MAAM,KAAA,IAC/B,CAAC,IACD,EAAE,kBAAkB,iBAAiB,QAAQ,EAAE;GACnD,SAAS;EACX,CAAC;CACH;CACA,IAAI,CAAC,SAAS,IAAI;EAChB,MAAM,OAAO,SAAS;EACtB,IAAI,SAAS,MAAM,OAAO,WAAW,IAAI;EACzC,MAAM,UAAU,6CAA6C,SAAS;EACtE,OAAO,OAAO,SAAS,UAAU,MAAM,cAAc,OAAO,IAAI,gBAAgB,OAAO;CACzF;CACA,MAAM,QAAQ,OAAO,eAAe,UAAU,OAAO;CACrD,OAAO,qBAAqB,KAAK;EAC/B,gBAAgB;EAChB,WAAW;EACX;CACF,CAAC;AACH,CAAC;;AAGH,MAAa,0CAKX,MAAM,OACJ,gBACA,OAAO,IAAI,mCAAmC,YAC5C,eAAe,GAAG,EAAE,SAAS,eAAe,OAAO,EAAE,CAAC,CACxD,CACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BrowserQuickActionWorkersAi } from "./browser-quick-action.mjs";
|
|
2
2
|
import { Effect, Layer, Option, Redacted, Schema, Stream } from "effect";
|
|
3
|
-
import { PageCapture, PageCaptureInferencePolicyError, PageCaptureInferenceUse, PageCaptureNavigationError, PageCaptureOutputLimitError, PageCaptureProtocolError, PageCaptureRateLimitedError, PageCaptureResourceUse, PageCaptureResult, PageCaptureUnsupportedError, PageContentCaptured, PageLinksCaptured, PageMarkdownCaptured, PageStructuredCaptured, SandboxImplementation } from "@effect-agent/sandbox";
|
|
3
|
+
import { PageCapture, PageCaptureInferencePolicyError, PageCaptureInferenceUse, PageCaptureNavigationError, PageCaptureOutputLimitError, PageCaptureProtocolError, PageCaptureRateLimitedError, PageCaptureResourceUse, PageCaptureResult, PageCaptureUnsupportedError, PageContentCaptured, PageLinksCaptured, PageMarkdownCaptured, PageScrapeCaptured, PageStructuredCaptured, SandboxImplementation } from "@effect-agent/sandbox";
|
|
4
4
|
import { HttpClient, HttpClientRequest } from "effect/unstable/http";
|
|
5
5
|
//#region src/browser-rest-capture.ts
|
|
6
6
|
/** Node-safe REST PageCapture implementation; it never imports Worker runtime modules. */
|
|
@@ -66,6 +66,7 @@ const actionName = (action) => {
|
|
|
66
66
|
case "CapturePageContent": return "content";
|
|
67
67
|
case "CapturePageMarkdown": return "markdown";
|
|
68
68
|
case "CapturePageLinks": return "links";
|
|
69
|
+
case "CapturePageScrape": return "scrape";
|
|
69
70
|
case "CapturePageStructured": return "json";
|
|
70
71
|
}
|
|
71
72
|
};
|
|
@@ -78,6 +79,10 @@ const actionBody = (request) => {
|
|
|
78
79
|
...body,
|
|
79
80
|
...request.action.visibleLinksOnly === void 0 ? {} : { visibleLinksOnly: request.action.visibleLinksOnly }
|
|
80
81
|
};
|
|
82
|
+
case "CapturePageScrape": return {
|
|
83
|
+
...body,
|
|
84
|
+
elements: request.action.selectors.map((selector) => ({ selector }))
|
|
85
|
+
};
|
|
81
86
|
case "CapturePageStructured": return {
|
|
82
87
|
...body,
|
|
83
88
|
response_format: {
|
|
@@ -149,6 +154,13 @@ const parseOutput = (action, bodyText, apiToken) => {
|
|
|
149
154
|
});
|
|
150
155
|
return Option.isSome(decoded) ? decoded.value : protocolError("Browser Run links did not return a bounded array of valid URLs");
|
|
151
156
|
}
|
|
157
|
+
case "CapturePageScrape": {
|
|
158
|
+
const decoded = Schema.decodeUnknownOption(PageScrapeCaptured)({
|
|
159
|
+
_tag: "PageScrapeCaptured",
|
|
160
|
+
groups: envelope.value.result
|
|
161
|
+
});
|
|
162
|
+
return Option.isSome(decoded) ? decoded.value : protocolError("Browser Run scrape did not return bounded grouped element records");
|
|
163
|
+
}
|
|
152
164
|
case "CapturePageStructured": return PageStructuredCaptured.make({ value: envelope.value.result });
|
|
153
165
|
}
|
|
154
166
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-rest-capture.mjs","names":[],"sources":["../src/browser-rest-capture.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 PageStructuredCaptured,\n PageCaptureUnsupportedError,\n SandboxImplementation,\n type PageCaptureAction,\n type PageCaptureCapture,\n type PageCaptureError,\n type PageCaptureOutput,\n type PageCaptureRequest,\n} from \"@effect-agent/sandbox\";\nimport { Effect, Layer, Option, Redacted, Schema, Stream } from \"effect\";\nimport { HttpClient, HttpClientRequest, type HttpClientError } from \"effect/unstable/http\";\n\nimport {\n BrowserQuickActionWorkersAi,\n type BrowserQuickActionWorkersAiPolicy,\n} from \"./browser-quick-action.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});\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});\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 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 if (request.navigation !== undefined) {\n const goto: Record<string, unknown> = {};\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 return body;\n};\n\nconst actionName = (action: PageCaptureAction): \"content\" | \"markdown\" | \"links\" | \"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 \"CapturePageStructured\":\n return \"json\";\n }\n};\n\nconst actionBody = (request: PageCaptureRequest): Record<string, unknown> => {\n const body = requestBody(request);\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 \"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 if (!Number.isSafeInteger(seconds) || seconds < 0) return undefined;\n const millis = seconds * 1_000;\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 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 if (contentType === undefined) return false;\n const mediaType = contentType.split(\";\", 1)[0]?.trim().toLowerCase();\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 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 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 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 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 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 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 return Option.isSome(decoded)\n ? decoded.value\n : protocolError(\"Browser Run links did not return a bounded array of valid URLs\");\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 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 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 const response = yield* client\n .execute(requestWithBody)\n .pipe(\n Effect.mapError((cause) => protocolError(\"Calling the Browser Run REST API failed\", cause)),\n );\n const bodyText = yield* readBoundedResponse(response, request);\n if (response.status === 429) {\n const reason = isQuotaMessage(bodyText) ? \"quota\" : \"rate\";\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 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 if (\n output._tag === \"PageCaptureNavigationError\" ||\n output._tag === \"PageCaptureProtocolError\"\n ) {\n return yield* output;\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 return PageCapture.of({ capture: makeCapture(client, options, workersAi) });\n }),\n );\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"browser-rest-capture.mjs","names":[],"sources":["../src/browser-rest-capture.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 SandboxImplementation,\n type PageCaptureAction,\n type PageCaptureCapture,\n type PageCaptureError,\n type PageCaptureOutput,\n type PageCaptureRequest,\n} from \"@effect-agent/sandbox\";\nimport { Effect, Layer, Option, Redacted, Schema, Stream } from \"effect\";\nimport { HttpClient, HttpClientRequest, type HttpClientError } from \"effect/unstable/http\";\n\nimport {\n BrowserQuickActionWorkersAi,\n type BrowserQuickActionWorkersAiPolicy,\n} from \"./browser-quick-action.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});\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});\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 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 if (request.navigation !== undefined) {\n const goto: Record<string, unknown> = {};\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 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 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 if (!Number.isSafeInteger(seconds) || seconds < 0) return undefined;\n const millis = seconds * 1_000;\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 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 if (contentType === undefined) return false;\n const mediaType = contentType.split(\";\", 1)[0]?.trim().toLowerCase();\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 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 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 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 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 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 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 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 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 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 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 const response = yield* client\n .execute(requestWithBody)\n .pipe(\n Effect.mapError((cause) => protocolError(\"Calling the Browser Run REST API failed\", cause)),\n );\n const bodyText = yield* readBoundedResponse(response, request);\n if (response.status === 429) {\n const reason = isQuotaMessage(bodyText) ? \"quota\" : \"rate\";\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 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 if (\n output._tag === \"PageCaptureNavigationError\" ||\n output._tag === \"PageCaptureProtocolError\"\n ) {\n return yield* output;\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 return PageCapture.of({ capture: makeCapture(client, options, workersAi) });\n }),\n );\n"],"mappings":"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"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BrowserQuickActionBrowserBinding, BrowserQuickActionCaptureOptions, BrowserQuickActionClient, BrowserQuickActionRpcError, BrowserQuickActionWorkersAi, BrowserQuickActionWorkersAiPolicy, BrowserQuickActionWorkersAiPolicyError, browserQuickActionCaptureLayer, browserQuickActionImplementation, browserQuickActionScreenshotLayer, browserQuickActionWorkersAiCaptureLayer } from "./browser-quick-action.mjs";
|
|
2
2
|
import { BrowserRestCaptureOptions, browserRestCaptureImplementation, browserRestCaptureLayer, browserRestWorkersAiCaptureLayer } from "./browser-rest-capture.mjs";
|
|
3
3
|
import { BrowserRestCrawlOptions, browserRestCrawlImplementation, browserRestCrawlLayer } from "./browser-rest-crawl.mjs";
|
|
4
|
-
import { BrowserRunInteractiveBinding, BrowserRunInteractiveBrowser, BrowserRunInteractiveContext, BrowserRunInteractivePage, BrowserRunInteractiveRequest, BrowserRunInteractiveRequestListener, browserRunInteractiveImplementation, browserRunInteractiveLayer } from "./interactive-browser.mjs";
|
|
4
|
+
import { BrowserRunCloudflareCommand, BrowserRunHandoffRequest, BrowserRunHandoffResult, BrowserRunHandoffState, BrowserRunInteractiveBinding, BrowserRunInteractiveBrowser, BrowserRunInteractiveCdpSession, BrowserRunInteractiveContext, BrowserRunInteractiveHost, BrowserRunInteractivePage, BrowserRunInteractiveRequest, BrowserRunInteractiveRequestListener, BrowserRunInteractiveSession, BrowserRunLiveViewRequest, BrowserRunLiveViewResult, browserRunInteractiveHostLayer, browserRunInteractiveImplementation, browserRunInteractiveLayer } from "./interactive-browser.mjs";
|
|
5
5
|
import { Context, Crypto, Effect, Layer, Option, Schema, Scope } from "effect";
|
|
6
6
|
import { AbortCommand, AbortIntent, AdmissionConflict, AgentBindingResolver, AppendConflict, ApprovalConflict, ApprovalDecisionCommand, ApprovalDecisionIntent, CanonicalRecordEnvelope, CanonicalSequence, ConversationNotMaterialized, ConversationStore, ConversationStoreError, DefinitionDigests, DigestError, DurableAgentRuntime, DurableBindingFailure, DurableRuntimeConfig, DurableRuntimeFailpointError, DurableRuntimeFailpointHandler, DurableSubmitAgent, DurableSubmitOptions, DurableWorkerFailure, FenceRejected, IntegrityReport, JoinedToHost, LedgerError, ObligationReport, ObligationThresholds, OperationAuthorizerService, OperationDenied, OwnershipLost, ProducerId, Receipt, RecoveryExplanation, RecoveryReport, ResolvedBinding, RetryCommand, RetryRefused, RunJournalError, Settlement, SettlementConflict, SubmissionLedger, ToolReconciler, UnknownResolutionCommand, UnknownResolutionConflict, UnknownResolutionIntent, WakeScheduler } from "@effect-agent/session";
|
|
7
7
|
import { ConversationPortTransport, DoStorageFailpointHandler, DoStorageInitializationError, PortRequest, PortResponse } from "@effect-agent/storage-cloudflare";
|
|
@@ -704,6 +704,14 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
704
704
|
readonly createdAt: string;
|
|
705
705
|
readonly deploymentId: string;
|
|
706
706
|
readonly payload: {
|
|
707
|
+
readonly _tag: "SubagentStarted";
|
|
708
|
+
readonly runId: string;
|
|
709
|
+
readonly toolCallId: string;
|
|
710
|
+
readonly childConversationId: string;
|
|
711
|
+
readonly childSubmissionId: string;
|
|
712
|
+
readonly childReceiptId: string;
|
|
713
|
+
readonly childRunId: string;
|
|
714
|
+
} | {
|
|
707
715
|
readonly _tag: "ConversationCreated";
|
|
708
716
|
readonly agentId: string;
|
|
709
717
|
readonly definitions: {
|
|
@@ -899,14 +907,6 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
899
907
|
readonly childConversationId: string;
|
|
900
908
|
readonly childPrincipal: string;
|
|
901
909
|
readonly childIdempotencyKey: string;
|
|
902
|
-
} | {
|
|
903
|
-
readonly _tag: "SubagentStarted";
|
|
904
|
-
readonly runId: string;
|
|
905
|
-
readonly toolCallId: string;
|
|
906
|
-
readonly childConversationId: string;
|
|
907
|
-
readonly childSubmissionId: string;
|
|
908
|
-
readonly childReceiptId: string;
|
|
909
|
-
readonly childRunId: string;
|
|
910
910
|
} | {
|
|
911
911
|
readonly _tag: "SubagentJoined";
|
|
912
912
|
readonly runId: string;
|
|
@@ -1718,5 +1718,5 @@ interface DynamicWorkerCodeExecutorOptions {
|
|
|
1718
1718
|
/** Layer building the Dynamic Worker `CodeExecutor` from resolved bindings. */
|
|
1719
1719
|
declare const dynamicWorkerCodeExecutorLayer: (options: DynamicWorkerCodeExecutorOptions) => Layer.Layer<CodeExecutor>;
|
|
1720
1720
|
//#endregion
|
|
1721
|
-
export { AbortRecorded, AdminExplainRequest, AdminFailed, AdminFailure, AdminResponse, AdminVerifyRequest, AdmissionLimitExceeded, ApprovalRecorded, AwaitProgressRequest, BrowserQuickActionBrowserBinding, BrowserQuickActionCaptureOptions, BrowserQuickActionClient, BrowserQuickActionRpcError, BrowserQuickActionWorkersAi, BrowserQuickActionWorkersAiPolicy, BrowserQuickActionWorkersAiPolicyError, BrowserRestCaptureOptions, BrowserRestCrawlOptions, BrowserRunInteractiveBinding, BrowserRunInteractiveBrowser, BrowserRunInteractiveContext, BrowserRunInteractivePage, BrowserRunInteractiveRequest, BrowserRunInteractiveRequestListener, CLOUDFLARE_DATABASE_CAP_BYTES, CLOUDFLARE_RUNTIME_DEFAULTS, CancelProgressRequest, ClientAbortFailure, ClientApprovalFailure, ClientAwaitFailure, ClientObserveFailure, ClientProgressFailure, ClientSubmitFailure, ClientUnknownFailure, CloudflareAdmissionLimitsValue, CloudflareBindingError, CloudflareBindingSource, CloudflareBindingSourceContext, CloudflareConversationClient, CloudflareDurableRuntime, CloudflareDurableRuntimeConfig, CloudflareDurableRuntimeConfigValue, CloudflareDurableRuntimeInitializationError, CloudflareDurableRuntimeOptions, CloudflareDurableRuntimeServices, CloudflarePlatformConfigError, CloudflareRunContextLayer, CloudflareRunContextSource, CloudflareRuntimeSourceContext, ConversationClientError, ConversationMaintenance, ConversationMaintenanceFailpoint, ConversationMaintenanceFailpointHandler, ConversationMaintenanceFailpointLocation, ConversationObjectClass, ConversationObjectIdentity, ConversationObjectInstance, ConversationObjectNamespace, ConversationObjectOptions, ConversationObjectPorts, ConversationObjectRpc, DEFAULT_MAX_DATABASE_BYTES, DurableAlarmError, DurableAlarmService, DurableObjectContext, DynamicWorkerCodeExecutorOptions, ExplainedRecovery, HostFailed, HostFailure, HostProtocolError, HostResponse, MaintenancePassFailure, MaintenancePassReport, ObligationsScanned, ObservePageRequest, ObservedPage, ProgressCancelled, ProgressObserved, ProgressWaitRegistry, RetryExecuted, SettlementReached, SubmitRequest, SubmitSucceeded, UnknownResolutionRecorded, VerifiedIntegrity, boundHostDiagnostic, browserQuickActionCaptureLayer, browserQuickActionImplementation, browserQuickActionScreenshotLayer, browserQuickActionWorkersAiCaptureLayer, browserRestCaptureImplementation, browserRestCaptureLayer, browserRestCrawlImplementation, browserRestCrawlLayer, browserRestWorkersAiCaptureLayer, browserRunInteractiveImplementation, browserRunInteractiveLayer, cloudflareWakeSchedulerLayer, conversationNamespaceFromEnv, conversationNamespaceLayer, conversationPortTransportLayer, decodeAbortCommand, decodeAdminExplainRequest, decodeAdminResponse, decodeAdminVerifyRequest, decodeApprovalDecisionCommand, decodeAwaitProgressRequest, decodeCancelProgressRequest, decodeHostResponse, decodeObligationThresholds, decodeObservePageRequest, decodeReceipt, decodeRetryCommand, decodeSubmitRequest, decodeUnknownResolutionCommand, disposeRpcHandle, dynamicWorkerCodeExecutorLayer, dynamicWorkerImplementation, encodeAbortCommand, encodeAdminResponse, encodeApprovalDecisionCommand, encodeAwaitProgressRequest, encodeCancelProgressRequest, encodeHostResponse, encodeObservePageRequest, encodeReceipt, encodeSubmitRequest, encodeUnknownResolutionCommand, makeConversationObjectClass };
|
|
1721
|
+
export { AbortRecorded, AdminExplainRequest, AdminFailed, AdminFailure, AdminResponse, AdminVerifyRequest, AdmissionLimitExceeded, ApprovalRecorded, AwaitProgressRequest, BrowserQuickActionBrowserBinding, BrowserQuickActionCaptureOptions, BrowserQuickActionClient, BrowserQuickActionRpcError, BrowserQuickActionWorkersAi, BrowserQuickActionWorkersAiPolicy, BrowserQuickActionWorkersAiPolicyError, BrowserRestCaptureOptions, BrowserRestCrawlOptions, BrowserRunCloudflareCommand, BrowserRunHandoffRequest, BrowserRunHandoffResult, BrowserRunHandoffState, BrowserRunInteractiveBinding, BrowserRunInteractiveBrowser, BrowserRunInteractiveCdpSession, BrowserRunInteractiveContext, BrowserRunInteractiveHost, BrowserRunInteractivePage, BrowserRunInteractiveRequest, BrowserRunInteractiveRequestListener, BrowserRunInteractiveSession, BrowserRunLiveViewRequest, BrowserRunLiveViewResult, CLOUDFLARE_DATABASE_CAP_BYTES, CLOUDFLARE_RUNTIME_DEFAULTS, CancelProgressRequest, ClientAbortFailure, ClientApprovalFailure, ClientAwaitFailure, ClientObserveFailure, ClientProgressFailure, ClientSubmitFailure, ClientUnknownFailure, CloudflareAdmissionLimitsValue, CloudflareBindingError, CloudflareBindingSource, CloudflareBindingSourceContext, CloudflareConversationClient, CloudflareDurableRuntime, CloudflareDurableRuntimeConfig, CloudflareDurableRuntimeConfigValue, CloudflareDurableRuntimeInitializationError, CloudflareDurableRuntimeOptions, CloudflareDurableRuntimeServices, CloudflarePlatformConfigError, CloudflareRunContextLayer, CloudflareRunContextSource, CloudflareRuntimeSourceContext, ConversationClientError, ConversationMaintenance, ConversationMaintenanceFailpoint, ConversationMaintenanceFailpointHandler, ConversationMaintenanceFailpointLocation, ConversationObjectClass, ConversationObjectIdentity, ConversationObjectInstance, ConversationObjectNamespace, ConversationObjectOptions, ConversationObjectPorts, ConversationObjectRpc, DEFAULT_MAX_DATABASE_BYTES, DurableAlarmError, DurableAlarmService, DurableObjectContext, DynamicWorkerCodeExecutorOptions, ExplainedRecovery, HostFailed, HostFailure, HostProtocolError, HostResponse, MaintenancePassFailure, MaintenancePassReport, ObligationsScanned, ObservePageRequest, ObservedPage, ProgressCancelled, ProgressObserved, ProgressWaitRegistry, RetryExecuted, SettlementReached, SubmitRequest, SubmitSucceeded, UnknownResolutionRecorded, VerifiedIntegrity, boundHostDiagnostic, browserQuickActionCaptureLayer, browserQuickActionImplementation, browserQuickActionScreenshotLayer, browserQuickActionWorkersAiCaptureLayer, browserRestCaptureImplementation, browserRestCaptureLayer, browserRestCrawlImplementation, browserRestCrawlLayer, browserRestWorkersAiCaptureLayer, browserRunInteractiveHostLayer, browserRunInteractiveImplementation, browserRunInteractiveLayer, cloudflareWakeSchedulerLayer, conversationNamespaceFromEnv, conversationNamespaceLayer, conversationPortTransportLayer, decodeAbortCommand, decodeAdminExplainRequest, decodeAdminResponse, decodeAdminVerifyRequest, decodeApprovalDecisionCommand, decodeAwaitProgressRequest, decodeCancelProgressRequest, decodeHostResponse, decodeObligationThresholds, decodeObservePageRequest, decodeReceipt, decodeRetryCommand, decodeSubmitRequest, decodeUnknownResolutionCommand, disposeRpcHandle, dynamicWorkerCodeExecutorLayer, dynamicWorkerImplementation, encodeAbortCommand, encodeAdminResponse, encodeApprovalDecisionCommand, encodeAwaitProgressRequest, encodeCancelProgressRequest, encodeHostResponse, encodeObservePageRequest, encodeReceipt, encodeSubmitRequest, encodeUnknownResolutionCommand, makeConversationObjectClass };
|
|
1722
1722
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BrowserQuickActionBrowserBinding, BrowserQuickActionRpcError, BrowserQuickActionWorkersAi, BrowserQuickActionWorkersAiPolicyError, browserQuickActionCaptureLayer, browserQuickActionImplementation, browserQuickActionScreenshotLayer, browserQuickActionWorkersAiCaptureLayer } from "./browser-quick-action.mjs";
|
|
2
2
|
import { browserRestCaptureImplementation, browserRestCaptureLayer, browserRestWorkersAiCaptureLayer } from "./browser-rest-capture.mjs";
|
|
3
|
-
import { BrowserRunInteractiveBinding, browserRunInteractiveImplementation, browserRunInteractiveLayer } from "./interactive-browser.mjs";
|
|
3
|
+
import { BrowserRunHandoffRequest, BrowserRunHandoffResult, BrowserRunHandoffState, BrowserRunInteractiveBinding, BrowserRunInteractiveHost, BrowserRunLiveViewRequest, BrowserRunLiveViewResult, browserRunInteractiveHostLayer, browserRunInteractiveImplementation, browserRunInteractiveLayer } from "./interactive-browser.mjs";
|
|
4
4
|
import { browserRestCrawlImplementation, browserRestCrawlLayer } from "./browser-rest-crawl.mjs";
|
|
5
5
|
import { Clock, Context, Crypto, Deferred, Duration, Effect, Exit, Fiber, Layer, Option, Predicate, PubSub, Queue, Random, Ref, Schema, Semaphore, Stream } from "effect";
|
|
6
6
|
import { AbortCommand, AbortIntent, AdmissionConflict, AgentBindingResolver, AppendConflict, ApprovalConflict, ApprovalDecisionCommand, ApprovalDecisionIntent, CanonicalRecordEnvelope, CanonicalSequence, ConversationNotMaterialized, ConversationRead, ConversationStore, ConversationStoreError, DEFAULT_OWNERSHIP_LEASE_DURATION, DefinitionDigests, DeploymentId, DigestError, DurableAgentRuntime, DurableRuntimeConfig, DurableRuntimeFailpoint, DurableRuntimeFailpointError, FenceRejected, IdempotencyKey, IntegrityReport, JoinedToHost, LedgerError, ObligationReport, ObligationThresholds, OperationAuthorizationRequest, OperationAuthorizer, OperationDenied, OwnershipLost, PersistedJson, Principal, ProducerId, Receipt, RecoveryExplanation, RecoveryReport, RetryCommand, RetryRefused, RunJournalError, Settlement, SettlementConflict, SubmissionLedger, SubmissionLookupByKey, ToolReconciler, UnknownResolutionCommand, UnknownResolutionConflict, UnknownResolutionIntent, WakeScheduler, makeWakeSubscriptionHub, operationAuthorizerLayer } from "@effect-agent/session";
|
|
@@ -1981,6 +1981,6 @@ const dynamicWorkerCodeExecutorLayer = (options) => Layer.effect(CodeExecutor, E
|
|
|
1981
1981
|
return CodeExecutor.of({ execute: makeExecute(options, clock) });
|
|
1982
1982
|
}));
|
|
1983
1983
|
//#endregion
|
|
1984
|
-
export { AbortRecorded, AdminExplainRequest, AdminFailed, AdminFailure, AdminResponse, AdminVerifyRequest, AdmissionLimitExceeded, ApprovalRecorded, AwaitProgressRequest, BrowserQuickActionBrowserBinding, BrowserQuickActionRpcError, BrowserQuickActionWorkersAi, BrowserQuickActionWorkersAiPolicyError, BrowserRunInteractiveBinding, CLOUDFLARE_DATABASE_CAP_BYTES, CLOUDFLARE_RUNTIME_DEFAULTS, CancelProgressRequest, CloudflareAdmissionLimitsValue, CloudflareBindingError, CloudflareConversationClient, CloudflareDurableRuntime, CloudflareDurableRuntimeConfig, CloudflareDurableRuntimeConfigValue, CloudflarePlatformConfigError, ConversationClientError, ConversationMaintenance, ConversationMaintenanceFailpoint, ConversationObjectIdentity, ConversationObjectNamespace, ConversationObjectPorts, DEFAULT_MAX_DATABASE_BYTES, DurableAlarmError, DurableAlarmService, DurableObjectContext, ExplainedRecovery, HostFailed, HostFailure, HostProtocolError, HostResponse, MaintenancePassReport, ObligationsScanned, ObservePageRequest, ObservedPage, ProgressCancelled, ProgressObserved, ProgressWaitRegistry, RetryExecuted, SettlementReached, SubmitRequest, SubmitSucceeded, UnknownResolutionRecorded, VerifiedIntegrity, boundHostDiagnostic, browserQuickActionCaptureLayer, browserQuickActionImplementation, browserQuickActionScreenshotLayer, browserQuickActionWorkersAiCaptureLayer, browserRestCaptureImplementation, browserRestCaptureLayer, browserRestCrawlImplementation, browserRestCrawlLayer, browserRestWorkersAiCaptureLayer, browserRunInteractiveImplementation, browserRunInteractiveLayer, cloudflareWakeSchedulerLayer, conversationNamespaceFromEnv, conversationNamespaceLayer, conversationPortTransportLayer, decodeAbortCommand, decodeAdminExplainRequest, decodeAdminResponse, decodeAdminVerifyRequest, decodeApprovalDecisionCommand, decodeAwaitProgressRequest, decodeCancelProgressRequest, decodeHostResponse, decodeObligationThresholds, decodeObservePageRequest, decodeReceipt, decodeRetryCommand, decodeSubmitRequest, decodeUnknownResolutionCommand, disposeRpcHandle, dynamicWorkerCodeExecutorLayer, dynamicWorkerImplementation, encodeAbortCommand, encodeAdminResponse, encodeApprovalDecisionCommand, encodeAwaitProgressRequest, encodeCancelProgressRequest, encodeHostResponse, encodeObservePageRequest, encodeReceipt, encodeSubmitRequest, encodeUnknownResolutionCommand, makeConversationObjectClass };
|
|
1984
|
+
export { AbortRecorded, AdminExplainRequest, AdminFailed, AdminFailure, AdminResponse, AdminVerifyRequest, AdmissionLimitExceeded, ApprovalRecorded, AwaitProgressRequest, BrowserQuickActionBrowserBinding, BrowserQuickActionRpcError, BrowserQuickActionWorkersAi, BrowserQuickActionWorkersAiPolicyError, BrowserRunHandoffRequest, BrowserRunHandoffResult, BrowserRunHandoffState, BrowserRunInteractiveBinding, BrowserRunInteractiveHost, BrowserRunLiveViewRequest, BrowserRunLiveViewResult, CLOUDFLARE_DATABASE_CAP_BYTES, CLOUDFLARE_RUNTIME_DEFAULTS, CancelProgressRequest, CloudflareAdmissionLimitsValue, CloudflareBindingError, CloudflareConversationClient, CloudflareDurableRuntime, CloudflareDurableRuntimeConfig, CloudflareDurableRuntimeConfigValue, CloudflarePlatformConfigError, ConversationClientError, ConversationMaintenance, ConversationMaintenanceFailpoint, ConversationObjectIdentity, ConversationObjectNamespace, ConversationObjectPorts, DEFAULT_MAX_DATABASE_BYTES, DurableAlarmError, DurableAlarmService, DurableObjectContext, ExplainedRecovery, HostFailed, HostFailure, HostProtocolError, HostResponse, MaintenancePassReport, ObligationsScanned, ObservePageRequest, ObservedPage, ProgressCancelled, ProgressObserved, ProgressWaitRegistry, RetryExecuted, SettlementReached, SubmitRequest, SubmitSucceeded, UnknownResolutionRecorded, VerifiedIntegrity, boundHostDiagnostic, browserQuickActionCaptureLayer, browserQuickActionImplementation, browserQuickActionScreenshotLayer, browserQuickActionWorkersAiCaptureLayer, browserRestCaptureImplementation, browserRestCaptureLayer, browserRestCrawlImplementation, browserRestCrawlLayer, browserRestWorkersAiCaptureLayer, browserRunInteractiveHostLayer, browserRunInteractiveImplementation, browserRunInteractiveLayer, cloudflareWakeSchedulerLayer, conversationNamespaceFromEnv, conversationNamespaceLayer, conversationPortTransportLayer, decodeAbortCommand, decodeAdminExplainRequest, decodeAdminResponse, decodeAdminVerifyRequest, decodeApprovalDecisionCommand, decodeAwaitProgressRequest, decodeCancelProgressRequest, decodeHostResponse, decodeObligationThresholds, decodeObservePageRequest, decodeReceipt, decodeRetryCommand, decodeSubmitRequest, decodeUnknownResolutionCommand, disposeRpcHandle, dynamicWorkerCodeExecutorLayer, dynamicWorkerImplementation, encodeAbortCommand, encodeAdminResponse, encodeApprovalDecisionCommand, encodeAwaitProgressRequest, encodeCancelProgressRequest, encodeHostResponse, encodeObservePageRequest, encodeReceipt, encodeSubmitRequest, encodeUnknownResolutionCommand, makeConversationObjectClass };
|
|
1985
1985
|
|
|
1986
1986
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1,7 +1,33 @@
|
|
|
1
|
-
import { Context, Layer } from "effect";
|
|
2
|
-
import { InteractiveBrowser, SandboxImplementation } from "@effect-agent/sandbox";
|
|
1
|
+
import { Context, Effect, Layer, Redacted, Schema, Scope } from "effect";
|
|
2
|
+
import { BrowserHandle, InteractiveBrowser, InteractiveBrowserError, InteractiveBrowserPolicy, SandboxImplementation } from "@effect-agent/sandbox";
|
|
3
3
|
//#region src/interactive-browser.d.ts
|
|
4
4
|
declare const browserRunInteractiveImplementation: SandboxImplementation;
|
|
5
|
+
declare const BrowserRunLiveViewRequest_base: Schema.Class<BrowserRunLiveViewRequest, Schema.Struct<{
|
|
6
|
+
readonly mode: Schema.Literal<"tab">;
|
|
7
|
+
readonly expiresInMs: Schema.Int;
|
|
8
|
+
}>, {}>;
|
|
9
|
+
/** Host-only request for a redacted Cloudflare Live View URL. */
|
|
10
|
+
declare class BrowserRunLiveViewRequest extends BrowserRunLiveViewRequest_base {}
|
|
11
|
+
declare const BrowserRunLiveViewResult_base: Schema.Class<BrowserRunLiveViewResult, Schema.Struct<{
|
|
12
|
+
readonly devtoolsFrontendUrl: Schema.Redacted<Schema.String>;
|
|
13
|
+
}>, {}>;
|
|
14
|
+
declare class BrowserRunLiveViewResult extends BrowserRunLiveViewResult_base {}
|
|
15
|
+
declare const BrowserRunHandoffRequest_base: Schema.Class<BrowserRunHandoffRequest, Schema.Struct<{
|
|
16
|
+
readonly instructions: Schema.String;
|
|
17
|
+
readonly timeout: Schema.Int;
|
|
18
|
+
}>, {}>;
|
|
19
|
+
/** Start one bounded handoff; controller ownership remains a consumer concern. */
|
|
20
|
+
declare class BrowserRunHandoffRequest extends BrowserRunHandoffRequest_base {}
|
|
21
|
+
declare const BrowserRunHandoffResult_base: Schema.Class<BrowserRunHandoffResult, Schema.Struct<{
|
|
22
|
+
readonly handoffId: Schema.Redacted<Schema.String>;
|
|
23
|
+
}>, {}>;
|
|
24
|
+
declare class BrowserRunHandoffResult extends BrowserRunHandoffResult_base {}
|
|
25
|
+
declare const BrowserRunHandoffState_base: Schema.Class<BrowserRunHandoffState, Schema.Struct<{
|
|
26
|
+
readonly active: Schema.Boolean;
|
|
27
|
+
readonly handoffId: Schema.optionalKey<Schema.Redacted<Schema.String>>;
|
|
28
|
+
readonly durationMs: Schema.optionalKey<Schema.Natural>;
|
|
29
|
+
}>, {}>;
|
|
30
|
+
declare class BrowserRunHandoffState extends BrowserRunHandoffState_base {}
|
|
5
31
|
/** One intercepted Puppeteer request, narrowed to the policy-relevant surface. */
|
|
6
32
|
interface BrowserRunInteractiveRequest {
|
|
7
33
|
readonly url: () => string;
|
|
@@ -9,6 +35,12 @@ interface BrowserRunInteractiveRequest {
|
|
|
9
35
|
readonly continue: () => Promise<void>;
|
|
10
36
|
}
|
|
11
37
|
type BrowserRunInteractiveRequestListener = (request: BrowserRunInteractiveRequest) => void;
|
|
38
|
+
type BrowserRunCloudflareCommand = "Cloudflare.getLiveView" | "Cloudflare.handoff" | "Cloudflare.getHandoffState";
|
|
39
|
+
/** Narrow CDP boundary for Cloudflare commands absent from the pinned protocol types. */
|
|
40
|
+
interface BrowserRunInteractiveCdpSession {
|
|
41
|
+
readonly send: (command: BrowserRunCloudflareCommand, parameters: unknown) => Promise<unknown>;
|
|
42
|
+
readonly detach: () => Promise<void>;
|
|
43
|
+
}
|
|
12
44
|
/** Narrow page boundary used by deterministic tests; SDK values remain in this package. */
|
|
13
45
|
interface BrowserRunInteractivePage {
|
|
14
46
|
readonly close: () => Promise<void>;
|
|
@@ -21,6 +53,9 @@ interface BrowserRunInteractivePage {
|
|
|
21
53
|
readonly readText: (selector: string | undefined, maximumBytes: number) => Promise<unknown>;
|
|
22
54
|
readonly fill: (selector: string, value: string) => Promise<void>;
|
|
23
55
|
readonly click: (selector: string) => Promise<void>;
|
|
56
|
+
readonly screenshot: (fullPage: boolean) => Promise<unknown>;
|
|
57
|
+
readonly scroll: (deltaX: number, deltaY: number) => Promise<void>;
|
|
58
|
+
readonly createCdpSession: () => Promise<BrowserRunInteractiveCdpSession>;
|
|
24
59
|
}
|
|
25
60
|
interface BrowserRunInteractiveContext {
|
|
26
61
|
readonly newPage: () => Promise<BrowserRunInteractivePage>;
|
|
@@ -29,12 +64,14 @@ interface BrowserRunInteractiveContext {
|
|
|
29
64
|
interface BrowserRunInteractiveBrowser {
|
|
30
65
|
readonly createContext: () => Promise<BrowserRunInteractiveContext>;
|
|
31
66
|
readonly close: () => Promise<void>;
|
|
67
|
+
readonly sessionId: () => unknown;
|
|
32
68
|
readonly isConnected: () => boolean;
|
|
33
69
|
readonly onDisconnected: (listener: () => void) => void;
|
|
34
70
|
readonly offDisconnected: (listener: () => void) => void;
|
|
35
71
|
}
|
|
36
72
|
declare const BrowserRunInteractiveBinding_base: Context.ServiceClass<BrowserRunInteractiveBinding, "@effect-agent/platform-cloudflare/BrowserRunInteractiveBinding", {
|
|
37
73
|
readonly launch: (keepAliveMillis: number) => Promise<BrowserRunInteractiveBrowser>;
|
|
74
|
+
readonly connect: (sessionId: string) => Promise<BrowserRunInteractiveBrowser>;
|
|
38
75
|
}>;
|
|
39
76
|
/** Host-supplied Browser Run binding projected into one fakeable launch operation. */
|
|
40
77
|
declare class BrowserRunInteractiveBinding extends BrowserRunInteractiveBinding_base {
|
|
@@ -42,8 +79,24 @@ declare class BrowserRunInteractiveBinding extends BrowserRunInteractiveBinding_
|
|
|
42
79
|
readonly browser: BrowserRun;
|
|
43
80
|
}): Layer.Layer<BrowserRunInteractiveBinding>;
|
|
44
81
|
}
|
|
45
|
-
|
|
82
|
+
interface BrowserRunInteractiveSession {
|
|
83
|
+
readonly handle: BrowserHandle;
|
|
84
|
+
readonly sessionId: Redacted.Redacted<string>;
|
|
85
|
+
readonly getLiveView: (request: BrowserRunLiveViewRequest) => Effect.Effect<BrowserRunLiveViewResult, InteractiveBrowserError>;
|
|
86
|
+
readonly handoff: (request: BrowserRunHandoffRequest) => Effect.Effect<BrowserRunHandoffResult, InteractiveBrowserError>;
|
|
87
|
+
readonly getHandoffState: Effect.Effect<BrowserRunHandoffState, InteractiveBrowserError>;
|
|
88
|
+
readonly close: Effect.Effect<void, InteractiveBrowserError>;
|
|
89
|
+
}
|
|
90
|
+
declare const BrowserRunInteractiveHost_base: Context.ServiceClass<BrowserRunInteractiveHost, "@effect-agent/platform-cloudflare/BrowserRunInteractiveHost", {
|
|
91
|
+
readonly open: (policy: InteractiveBrowserPolicy) => Effect.Effect<BrowserRunInteractiveSession, InteractiveBrowserError, Scope.Scope>;
|
|
92
|
+
readonly closeSession: (sessionId: Redacted.Redacted<string>) => Effect.Effect<void, InteractiveBrowserError>;
|
|
93
|
+
}>;
|
|
94
|
+
/** Cloudflare host authority kept separate from the provider-neutral browser handle. */
|
|
95
|
+
declare class BrowserRunInteractiveHost extends BrowserRunInteractiveHost_base {}
|
|
96
|
+
/** Cloudflare host controls and private session identity for one scoped Browser Run pass. */
|
|
97
|
+
declare const browserRunInteractiveHostLayer: () => Layer.Layer<BrowserRunInteractiveHost, never, BrowserRunInteractiveBinding>;
|
|
98
|
+
/** Worker-only generic adapter; Cloudflare identity and controls remain host-only. */
|
|
46
99
|
declare const browserRunInteractiveLayer: () => Layer.Layer<InteractiveBrowser, never, BrowserRunInteractiveBinding>;
|
|
47
100
|
//#endregion
|
|
48
|
-
export { BrowserRunInteractiveBinding, BrowserRunInteractiveBrowser, BrowserRunInteractiveContext, BrowserRunInteractivePage, BrowserRunInteractiveRequest, BrowserRunInteractiveRequestListener, browserRunInteractiveImplementation, browserRunInteractiveLayer };
|
|
101
|
+
export { BrowserRunCloudflareCommand, BrowserRunHandoffRequest, BrowserRunHandoffResult, BrowserRunHandoffState, BrowserRunInteractiveBinding, BrowserRunInteractiveBrowser, BrowserRunInteractiveCdpSession, BrowserRunInteractiveContext, BrowserRunInteractiveHost, BrowserRunInteractivePage, BrowserRunInteractiveRequest, BrowserRunInteractiveRequestListener, BrowserRunInteractiveSession, BrowserRunLiveViewRequest, BrowserRunLiveViewResult, browserRunInteractiveHostLayer, browserRunInteractiveImplementation, browserRunInteractiveLayer };
|
|
49
102
|
//# sourceMappingURL=interactive-browser.d.mts.map
|