@yielded/agent-platform-cloudflare 0.1.0-beta.166 → 0.1.0-beta.168

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/dist/{Alarm-B0ODr1NE.mjs → Alarm-DxODgAZZ.mjs} +259 -159
  2. package/dist/Alarm-DxODgAZZ.mjs.map +1 -0
  3. package/dist/Alarm.d.mts +27 -36
  4. package/dist/Alarm.mjs +2 -2
  5. package/dist/BrowserCredentials-C5IWfi7f.d.mts +91 -0
  6. package/dist/BrowserCredentials.d.mts +2 -91
  7. package/dist/BrowserRestCapture.mjs +3 -3
  8. package/dist/BrowserRestCapture.mjs.map +1 -1
  9. package/dist/BrowserRestCrawl.mjs +6 -6
  10. package/dist/BrowserRestCrawl.mjs.map +1 -1
  11. package/dist/{BrowserSession-RfIzxGCH.mjs → BrowserSession-BfNmyayH.mjs} +5 -5
  12. package/dist/BrowserSession-BfNmyayH.mjs.map +1 -0
  13. package/dist/{BrowserSession-B969Xg-2.d.mts → BrowserSession-Bx0V1-6_.d.mts} +6 -3
  14. package/dist/BrowserSession.d.mts +1 -1
  15. package/dist/BrowserSession.mjs +2 -2
  16. package/dist/BrowserUse-AstK0jKX.mjs +1467 -0
  17. package/dist/BrowserUse-AstK0jKX.mjs.map +1 -0
  18. package/dist/BrowserUse.d.mts +83 -0
  19. package/dist/BrowserUse.mjs +2 -0
  20. package/dist/CloudflareBindings.d.mts +8 -1
  21. package/dist/CloudflareBindings.mjs +2 -2
  22. package/dist/CloudflareBindings.mjs.map +1 -1
  23. package/dist/{CloudflareBrowser-5an6m-Qb.mjs → CloudflareBrowser-Vt8qTdYW.mjs} +11 -13
  24. package/dist/CloudflareBrowser-Vt8qTdYW.mjs.map +1 -0
  25. package/dist/CloudflareBrowser.mjs +1 -1
  26. package/dist/CloudflareCodeMode.mjs +1 -1
  27. package/dist/CloudflareCodeMode.mjs.map +1 -1
  28. package/dist/{CloudflareConfig-qDrRLofL.d.mts → CloudflareConfig-C9MvPbX8.d.mts} +9 -11
  29. package/dist/CloudflareConfig.d.mts +1 -1
  30. package/dist/CloudflareConfig.mjs +9 -12
  31. package/dist/CloudflareConfig.mjs.map +1 -1
  32. package/dist/CloudflareMemory.d.mts +3 -25
  33. package/dist/CloudflareMemory.mjs +33 -31
  34. package/dist/CloudflareMemory.mjs.map +1 -1
  35. package/dist/CloudflareScheduling.mjs +8 -15
  36. package/dist/CloudflareScheduling.mjs.map +1 -1
  37. package/dist/CloudflareSubscriptions.mjs +9 -16
  38. package/dist/CloudflareSubscriptions.mjs.map +1 -1
  39. package/dist/CloudflareThreadClient-CZm0TvUe.mjs +588 -0
  40. package/dist/CloudflareThreadClient-CZm0TvUe.mjs.map +1 -0
  41. package/dist/CloudflareThreadClient-QsVzLGGZ.d.mts +2033 -0
  42. package/dist/CloudflareThreadClient.d.mts +2 -1796
  43. package/dist/CloudflareThreadClient.mjs +2 -382
  44. package/dist/{InteractiveBrowser-BbG3kGA9.mjs → InteractiveBrowser-LdKzQeLR.mjs} +18 -19
  45. package/dist/InteractiveBrowser-LdKzQeLR.mjs.map +1 -0
  46. package/dist/InteractiveBrowser.mjs +1 -1
  47. package/dist/{ThreadObject-BcfXbzSO.d.mts → ThreadObject-7s5XnlH-.d.mts} +103 -79
  48. package/dist/{ThreadObject-DHjrnlX4.mjs → ThreadObject-C0vrcDrw.mjs} +265 -66
  49. package/dist/ThreadObject-C0vrcDrw.mjs.map +1 -0
  50. package/dist/ThreadObject.d.mts +2 -2
  51. package/dist/ThreadObject.mjs +2 -3
  52. package/dist/WakeScheduler.d.mts +6 -5
  53. package/dist/WakeScheduler.mjs +15 -11
  54. package/dist/WakeScheduler.mjs.map +1 -1
  55. package/dist/index.d.mts +7 -6
  56. package/dist/index.mjs +7 -6
  57. package/dist/page-function-CmUCcyNP.mjs +11 -0
  58. package/dist/page-function-CmUCcyNP.mjs.map +1 -0
  59. package/dist/{prepared-admission-DMX5p9dC.mjs → prepared-admission-3UUq0zth.mjs} +3 -3
  60. package/dist/{prepared-admission-DMX5p9dC.mjs.map → prepared-admission-3UUq0zth.mjs.map} +1 -1
  61. package/package.json +1 -1
  62. package/src/Alarm.ts +510 -279
  63. package/src/BrowserRestCapture.ts +2 -2
  64. package/src/BrowserRestCrawl.ts +10 -14
  65. package/src/BrowserSession.ts +10 -2
  66. package/src/BrowserUse.ts +1541 -0
  67. package/src/CloudflareBindings.ts +13 -4
  68. package/src/CloudflareCodeMode.ts +1 -1
  69. package/src/CloudflareConfig.ts +9 -12
  70. package/src/CloudflareMemory.ts +21 -28
  71. package/src/CloudflareScheduling.ts +7 -15
  72. package/src/CloudflareSubscriptions.ts +11 -20
  73. package/src/CloudflareThreadClient.ts +289 -9
  74. package/src/InteractiveBrowser.ts +325 -323
  75. package/src/ThreadObject.ts +172 -52
  76. package/src/WakeScheduler.ts +29 -18
  77. package/src/index.ts +1 -0
  78. package/src/internal/browser-dom.ts +845 -0
  79. package/src/internal/browser-file-selection.ts +8 -1
  80. package/src/internal/browser-jev-dom.ts +344 -0
  81. package/src/internal/browser-quick-action.ts +7 -8
  82. package/src/internal/browser-session-lifecycle.ts +2 -5
  83. package/src/internal/crypto.ts +41 -0
  84. package/src/internal/due-queue.ts +5 -69
  85. package/src/internal/layers.ts +100 -17
  86. package/src/internal/live-text-protocol.ts +51 -0
  87. package/src/internal/live-text.ts +256 -0
  88. package/src/internal/page-function.ts +12 -0
  89. package/src/internal/prepared-admission.ts +1 -1
  90. package/src/internal/progress-wait.ts +19 -24
  91. package/src/internal/transport.ts +1 -1
  92. package/dist/Alarm-B0ODr1NE.mjs.map +0 -1
  93. package/dist/BrowserSession-RfIzxGCH.mjs.map +0 -1
  94. package/dist/CloudflareBrowser-5an6m-Qb.mjs.map +0 -1
  95. package/dist/CloudflareThreadClient.mjs.map +0 -1
  96. package/dist/InteractiveBrowser-BbG3kGA9.mjs.map +0 -1
  97. package/dist/ThreadObject-DHjrnlX4.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"BrowserRestCrawl.mjs","names":[],"sources":["../src/BrowserRestCrawl.ts"],"sourcesContent":["import {\n PageCrawl,\n PageCrawlLimitError,\n PageCrawlProtocolError,\n PageCrawlRateLimitedError,\n PageCrawlRecord,\n PageCrawlTerminalError,\n type PageCrawlCrawl,\n type PageCrawlError,\n type PageCrawlRequest,\n} from \"@yielded/agent/page-crawl\";\nimport { SandboxImplementation } from \"@yielded/agent/sandbox\";\nimport {\n Duration,\n Effect,\n Layer,\n Option,\n Redacted,\n Ref,\n Schedule,\n Schema,\n Scope,\n Stream,\n} from \"effect\";\nimport {\n HttpClient,\n HttpClientRequest,\n type HttpClientError,\n type HttpClientResponse,\n} from \"effect/http\";\n\n/** Node-safe REST crawl implementation. It never exposes or persists provider job identity. */\nexport const browserRestCrawlImplementation = SandboxImplementation.make({\n isolation: \"isolated\",\n identity: \"cloudflare-browser-rest-crawl\",\n});\n\nconst API_ORIGIN = \"https://api.cloudflare.com\";\nconst POLL_INTERVAL = Duration.seconds(1);\nconst CANCEL_TIMEOUT = Duration.seconds(30);\nconst MAX_CONTROL_RESPONSE_BYTES = 64 * 1024;\nconst MAX_RESULTS_RESPONSE_BYTES = 12 * 1024 * 1024;\nconst MAX_DIAGNOSTIC_LENGTH = 8_000;\nconst MAX_CURSOR_LENGTH = 1_024;\nconst MAX_RECORDS_PER_RESPONSE = 10_000;\nconst BoundedJobId = Schema.NonEmptyString.check(Schema.isMaxLength(256));\nconst BoundedCursorString = Schema.NonEmptyString.check(Schema.isMaxLength(MAX_CURSOR_LENGTH));\n// The generated API response Schema says string; the current product example returns a number.\nconst ProviderCursor = Schema.Union([BoundedCursorString, Schema.Natural]);\n\nconst ProviderJobStatus = Schema.Literals([\n \"running\",\n \"completed\",\n \"errored\",\n \"cancelled_by_user\",\n \"cancelled_due_to_timeout\",\n \"cancelled_due_to_limits\",\n]);\n\nconst ProviderResult = Schema.Struct({\n id: BoundedJobId,\n status: ProviderJobStatus,\n browserSecondsUsed: Schema.optionalKey(Schema.Finite.check(Schema.isGreaterThanOrEqualTo(0))),\n total: Schema.optionalKey(Schema.Natural),\n finished: Schema.optionalKey(Schema.Natural),\n skipped: Schema.optionalKey(Schema.Natural),\n records: Schema.Array(PageCrawlRecord).check(Schema.isMaxLength(MAX_RECORDS_PER_RESPONSE)),\n cursor: Schema.optionalKey(ProviderCursor),\n});\n\nconst CreateEnvelope = Schema.Struct({\n success: Schema.Literal(true),\n result: BoundedJobId,\n});\n\nconst ResultEnvelope = Schema.Struct({\n success: Schema.Literal(true),\n result: ProviderResult,\n});\n\nconst DeleteEnvelope = Schema.Struct({\n success: Schema.Literal(true),\n result: Schema.Struct({\n job_id: BoundedJobId,\n message: Schema.String.check(Schema.isMaxLength(MAX_DIAGNOSTIC_LENGTH)),\n }),\n});\n\n/** Explicit credentials. The token is projected only into fixed-origin Authorization headers. */\nexport interface BrowserRestCrawlOptions {\n readonly accountId: string;\n readonly apiToken: Redacted.Redacted<string>;\n}\n\nconst boundedDiagnostic = (message: string): string => message.slice(0, MAX_DIAGNOSTIC_LENGTH);\n\nconst privateCause = (value: unknown, apiToken: Redacted.Redacted<string>): Error | undefined => {\n const raw = boundedDiagnostic(String(value));\n\n if (raw.length === 0) return undefined;\n const token = Redacted.value(apiToken);\n\n return new Error(token.length === 0 ? raw : raw.replaceAll(token, \"[REDACTED]\"));\n};\n\nconst protocolError = (message: string, cause?: unknown): PageCrawlProtocolError =>\n PageCrawlProtocolError.make({\n implementation: browserRestCrawlImplementation,\n message: boundedDiagnostic(message),\n ...(cause === undefined ? {} : { cause }),\n });\n\nconst limitError = (\n request: PageCrawlRequest,\n limit: PageCrawlLimitError[\"limit\"],\n observed: number,\n): PageCrawlLimitError => {\n const maximum =\n limit === \"pages\"\n ? request.limits.maxPages\n : limit === \"page-bytes\"\n ? request.limits.maxPageBytes\n : limit === \"total-bytes\"\n ? request.limits.maxTotalBytes\n : request.limits.deadlineMillis;\n\n return PageCrawlLimitError.make({\n implementation: browserRestCrawlImplementation,\n limit,\n maximum,\n observed,\n message: `The crawl exceeded its ${limit} limit`,\n });\n};\n\nconst retryAfterMillis = (\n headers: Readonly<Record<string, string | undefined>>,\n): number | undefined => {\n const seconds = Number(headers[\"retry-after\"]);\n\n if (!Number.isSafeInteger(seconds) || seconds < 0) return undefined;\n const millis = seconds * 1_000;\n\n return Number.isSafeInteger(millis) ? millis : undefined;\n};\n\nconst isJsonResponse = (headers: Readonly<Record<string, string | undefined>>): boolean => {\n const contentType = headers[\"content-type\"];\n\n if (contentType === undefined) return false;\n const mediaType = contentType.split(\";\", 1)[0]?.trim().toLowerCase();\n\n return mediaType === \"application/json\" || mediaType?.endsWith(\"+json\") === true;\n};\n\nconst isQuotaMessage = (bodyText: string): boolean => /time limit|daily|quota/i.test(bodyText);\n\nconst endpoint = (options: BrowserRestCrawlOptions, jobId?: string): string =>\n `${API_ORIGIN}/client/v4/accounts/${encodeURIComponent(options.accountId)}/browser-rendering/crawl${\n jobId === undefined ? \"\" : `/${encodeURIComponent(jobId)}`\n }`;\n\nconst readBoundedResponse = Effect.fn(\"BrowserRestCrawl.readBoundedResponse\")(function* (\n response: HttpClientResponse.HttpClientResponse,\n maximum: number,\n): Effect.fn.Return<string, PageCrawlProtocolError> {\n const decoder = new TextDecoder(\"utf-8\", { fatal: true, ignoreBOM: false });\n\n const state = yield* Stream.runFoldEffect<\n Uint8Array,\n HttpClientError.HttpClientError,\n never,\n { readonly observed: number; readonly text: string },\n PageCrawlProtocolError,\n never\n >(\n response.stream,\n () => ({ observed: 0, text: \"\" }),\n (current, chunk) => {\n const observed = current.observed + chunk.byteLength;\n\n if (observed > maximum) {\n return Effect.fail(\n protocolError(\n `The Browser Run crawl response exceeded ${String(maximum)} transport bytes`,\n ),\n );\n }\n\n return Effect.try({\n try: () => ({ observed, text: current.text + decoder.decode(chunk, { stream: true }) }),\n catch: (cause) => protocolError(\"Decoding the Browser Run crawl response failed\", cause),\n });\n },\n ).pipe(\n Effect.mapError((cause) =>\n Schema.is(PageCrawlProtocolError)(cause)\n ? cause\n : protocolError(\"Reading the Browser Run crawl response failed\", cause),\n ),\n );\n\n return yield* Effect.try({\n try: () => state.text + decoder.decode(),\n catch: (cause) => protocolError(\"Decoding the Browser Run crawl response failed\", cause),\n });\n});\n\nconst deadlineFailure = Effect.fn(\"BrowserRestCrawl.deadlineFailure\")(function* (\n request: PageCrawlRequest,\n startedAt: number,\n) {\n const now = yield* Effect.clockWith((clock) => clock.currentTimeMillis);\n\n return yield* limitError(request, \"deadline\", Math.max(0, now - startedAt));\n});\n\nconst withinDeadline = Effect.fn(\"BrowserRestCrawl.withinDeadline\")(function* <A, E, R>(\n effect: Effect.Effect<A, E, R>,\n request: PageCrawlRequest,\n startedAt: number,\n): Effect.fn.Return<A, E | PageCrawlLimitError, R> {\n const now = yield* Effect.clockWith((clock) => clock.currentTimeMillis);\n const elapsed = Math.max(0, now - startedAt);\n const remaining = request.limits.deadlineMillis - elapsed;\n\n if (remaining <= 0) return yield* limitError(request, \"deadline\", elapsed);\n\n return yield* effect.pipe(\n Effect.timeoutOrElse({\n duration: Duration.millis(remaining),\n orElse: () => deadlineFailure(request, startedAt),\n }),\n );\n});\n\nconst checkDeadline = Effect.fn(\"BrowserRestCrawl.checkDeadline\")(function* (\n request: PageCrawlRequest,\n startedAt: number,\n) {\n const now = yield* Effect.clockWith((clock) => clock.currentTimeMillis);\n const elapsed = Math.max(0, now - startedAt);\n\n if (elapsed >= request.limits.deadlineMillis) {\n return yield* limitError(request, \"deadline\", elapsed);\n }\n});\n\nconst normalizedCursor = (cursor: typeof ProviderCursor.Type): string => String(cursor);\n\ninterface PaginationState {\n readonly cursor: Option.Option<string>;\n readonly seen: ReadonlyArray<string>;\n}\n\ninterface RecordLimitsState {\n readonly pages: number;\n readonly totalBytes: number;\n}\n\nconst sameHost = (expectedHost: string, url: string): boolean => new URL(url).host === expectedHost;\n\nconst makeCrawl =\n (client: HttpClient.HttpClient, options: BrowserRestCrawlOptions): PageCrawlCrawl =>\n (input) =>\n Stream.unwrap(\n Effect.gen(function* () {\n const startedAt = yield* Effect.clockWith((clock) => clock.currentTimeMillis);\n const startHost = new URL(input.startUrl).host;\n\n const executeJson = Effect.fn(\"BrowserRestCrawl.executeJson\")(function* <\n S extends Schema.Top,\n >(request: HttpClientRequest.HttpClientRequest, schema: S, maximum: number) {\n const authorized = HttpClientRequest.bearerToken(request, options.apiToken).pipe(\n HttpClientRequest.acceptJson,\n );\n\n const response = yield* client\n .execute(authorized)\n .pipe(\n Effect.mapError((cause) =>\n protocolError(\n \"Calling the Browser Run crawl REST API failed\",\n privateCause(cause, options.apiToken),\n ),\n ),\n );\n\n const bodyText = yield* readBoundedResponse(response, maximum);\n\n if (response.status === 429) {\n const reason = isQuotaMessage(bodyText) ? \"quota\" : \"rate\";\n\n return yield* PageCrawlRateLimitedError.make({\n implementation: browserRestCrawlImplementation,\n reason,\n ...(retryAfterMillis(response.headers) === undefined\n ? {}\n : { retryAfterMillis: retryAfterMillis(response.headers) }),\n message:\n reason === \"quota\"\n ? \"Browser Run exceeded its browser quota\"\n : \"Browser Run crawl was rate limited\",\n ...(privateCause(bodyText, options.apiToken) === undefined\n ? {}\n : { cause: privateCause(bodyText, options.apiToken) }),\n });\n }\n if (response.status < 200 || response.status >= 300) {\n return yield* protocolError(\n `Browser Run crawl answered HTTP ${String(response.status)}`,\n privateCause(bodyText, options.apiToken),\n );\n }\n if (!isJsonResponse(response.headers)) {\n return yield* protocolError(\n \"The Browser Run crawl success response was not JSON\",\n privateCause(bodyText, options.apiToken),\n );\n }\n\n return yield* Schema.decodeEffect(Schema.fromJsonString(schema))(bodyText).pipe(\n Effect.mapError((cause) =>\n protocolError(\n \"Browser Run returned a malformed crawl response\",\n privateCause(cause, options.apiToken),\n ),\n ),\n );\n });\n\n const createJob = Effect.gen(function* () {\n const requestWithBody = yield* HttpClientRequest.post(endpoint(options)).pipe(\n HttpClientRequest.bodyJson({\n url: input.startUrl,\n crawlPurposes: [...input.purposes],\n limit: input.limits.maxPages,\n depth: input.limits.maxDepth,\n formats: [\"markdown\"],\n render: true,\n options: {\n includeExternalLinks: false,\n includeSubdomains: false,\n },\n }),\n Effect.mapError((cause) =>\n protocolError(\"Encoding the Browser Run crawl request failed\", cause),\n ),\n );\n\n const created = yield* withinDeadline(\n executeJson(requestWithBody, CreateEnvelope, MAX_CONTROL_RESPONSE_BYTES),\n input,\n startedAt,\n );\n\n return created.result;\n });\n\n const job = yield* Effect.uninterruptibleMask((restore) =>\n restore(createJob).pipe(\n Effect.flatMap((id) =>\n Effect.gen(function* () {\n const state = yield* Ref.make<\"running\" | \"terminal\">(\"running\");\n const scope = yield* Effect.scope;\n\n const cancelIfRunning = Ref.modify(state, (current) =>\n current === \"running\"\n ? [true, \"terminal\" as const]\n : [false, \"terminal\" as const],\n ).pipe(\n Effect.flatMap((shouldCancel) => {\n if (!shouldCancel) return Effect.void;\n\n const cancellation = executeJson(\n HttpClientRequest.delete(endpoint(options, id)),\n DeleteEnvelope,\n MAX_CONTROL_RESPONSE_BYTES,\n ).pipe(\n Effect.flatMap((deleted) =>\n deleted.result.job_id === id\n ? Effect.void\n : protocolError(\"Browser Run cancelled a different crawl job\"),\n ),\n );\n\n return cancellation.pipe(\n Effect.timeoutOrElse({\n duration: CANCEL_TIMEOUT,\n orElse: () =>\n protocolError(\"Cancelling the Browser Run crawl exceeded 30 seconds\"),\n }),\n );\n }),\n );\n\n yield* Scope.addFinalizer(\n scope,\n cancelIfRunning.pipe(\n Effect.catchCause(() =>\n Effect.logWarning(\"Browser Run crawl cancellation failed\"),\n ),\n ),\n );\n\n return { id, state } as const;\n }),\n ),\n ),\n );\n\n const fetchResult = Effect.fn(\"BrowserRestCrawl.fetchResult\")(function* (\n cursor: Option.Option<string>,\n statusOnly: boolean,\n ) {\n let request = HttpClientRequest.get(endpoint(options, job.id));\n\n if (statusOnly) request = HttpClientRequest.setUrlParam(request, \"limit\", \"1\");\n if (Option.isSome(cursor)) {\n request = HttpClientRequest.setUrlParam(request, \"cursor\", cursor.value);\n }\n\n // `limit=1` still permits one complete record, so poll GETs use the bounded result cap.\n const envelope = yield* withinDeadline(\n executeJson(request, ResultEnvelope, MAX_RESULTS_RESPONSE_BYTES),\n input,\n startedAt,\n );\n\n if (envelope.result.id !== job.id) {\n return yield* protocolError(\"Browser Run returned a different crawl job identity\");\n }\n\n return envelope.result;\n });\n\n const terminal = yield* Effect.uninterruptibleMask((restore) =>\n restore(\n withinDeadline(\n Effect.repeat(fetchResult(Option.none(), true), {\n schedule: Schedule.spaced(POLL_INTERVAL),\n until: (result) => result.status !== \"running\",\n }),\n input,\n startedAt,\n ),\n ).pipe(Effect.tap(() => Ref.set(job.state, \"terminal\"))),\n );\n\n if (terminal.status === \"running\") {\n return yield* protocolError(\"Browser Run polling stopped before a terminal status\");\n }\n if (terminal.status !== \"completed\") {\n return yield* PageCrawlTerminalError.make({\n implementation: browserRestCrawlImplementation,\n status: terminal.status,\n message: `Browser Run crawl ended with status ${terminal.status}`,\n });\n }\n\n const pages = Stream.paginate<PaginationState, PageCrawlRecord, PageCrawlError>(\n { cursor: Option.none(), seen: [] },\n (state) =>\n Effect.gen(function* () {\n const result = yield* fetchResult(state.cursor, false);\n\n if (result.status !== \"completed\") {\n return yield* protocolError(\n \"Browser Run changed crawl status during result pagination\",\n );\n }\n if (result.cursor === undefined) {\n return [result.records, Option.none()] as const;\n }\n const cursor = normalizedCursor(result.cursor);\n\n if (state.seen.includes(cursor)) {\n return yield* protocolError(\"Browser Run repeated a crawl result cursor\");\n }\n if (state.seen.length >= input.limits.maxPages) {\n return yield* protocolError(\"Browser Run returned too many crawl result cursors\");\n }\n\n return [\n result.records,\n Option.some({ cursor: Option.some(cursor), seen: [...state.seen, cursor] }),\n ] as const;\n }),\n );\n\n return pages.pipe(\n Stream.rechunk(1),\n Stream.mapAccumEffect(\n (): RecordLimitsState => ({ pages: 0, totalBytes: 0 }),\n (state, record) =>\n Effect.gen(function* () {\n yield* checkDeadline(input, startedAt);\n const pages = state.pages + 1;\n\n if (pages > input.limits.maxPages) {\n return yield* limitError(input, \"pages\", pages);\n }\n if (!sameHost(startHost, record.url)) {\n return yield* protocolError(\"Browser Run returned an off-host crawl record\");\n }\n if (record.metadata !== undefined && !sameHost(startHost, record.metadata.url)) {\n return yield* protocolError(\"Browser Run returned off-host crawl metadata\");\n }\n\n const pageBytes =\n record.markdown === undefined\n ? 0\n : new TextEncoder().encode(record.markdown).byteLength;\n\n if (pageBytes > input.limits.maxPageBytes) {\n return yield* limitError(input, \"page-bytes\", pageBytes);\n }\n const totalBytes = state.totalBytes + pageBytes;\n\n if (totalBytes > input.limits.maxTotalBytes) {\n return yield* limitError(input, \"total-bytes\", totalBytes);\n }\n\n return [{ pages, totalBytes }, [record]] as const;\n }),\n ),\n );\n }),\n );\n\n/** Cloudflare REST PageCrawl Layer for Node and other non-Worker composition roots. */\nexport const browserRestCrawlLayer = (\n options: BrowserRestCrawlOptions,\n): Layer.Layer<PageCrawl, never, HttpClient.HttpClient> =>\n Layer.effect(\n PageCrawl,\n Effect.map(HttpClient.HttpClient, (client) =>\n PageCrawl.of({ crawl: makeCrawl(client, options) }),\n ),\n );\n"],"mappings":"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"}
1
+ {"version":3,"file":"BrowserRestCrawl.mjs","names":[],"sources":["../src/BrowserRestCrawl.ts"],"sourcesContent":["import {\n PageCrawl,\n PageCrawlLimitError,\n PageCrawlProtocolError,\n PageCrawlRateLimitedError,\n PageCrawlRecord,\n PageCrawlTerminalError,\n type PageCrawlCrawl,\n type PageCrawlError,\n type PageCrawlRequest,\n} from \"@yielded/agent/page-crawl\";\nimport { SandboxImplementation } from \"@yielded/agent/sandbox\";\nimport {\n Duration,\n Effect,\n Layer,\n Option,\n Redacted,\n Ref,\n Schedule,\n Schema,\n Scope,\n Stream,\n} from \"effect\";\nimport {\n HttpClient,\n HttpClientRequest,\n type HttpClientError,\n type HttpClientResponse,\n} from \"effect/http\";\n\n/** Node-safe REST crawl implementation. It never exposes or persists provider job identity. */\nexport const browserRestCrawlImplementation = SandboxImplementation.make({\n isolation: \"isolated\",\n identity: \"cloudflare-browser-rest-crawl\",\n});\n\nconst API_ORIGIN = \"https://api.cloudflare.com\";\nconst POLL_INTERVAL = Duration.seconds(1);\nconst CANCEL_TIMEOUT = Duration.seconds(30);\nconst MAX_CONTROL_RESPONSE_BYTES = 64 * 1024;\nconst MAX_RESULTS_RESPONSE_BYTES = 12 * 1024 * 1024;\nconst MAX_DIAGNOSTIC_LENGTH = 8_000;\nconst MAX_CURSOR_LENGTH = 1_024;\nconst MAX_RECORDS_PER_RESPONSE = 10_000;\nconst BoundedJobId = Schema.NonEmptyString.check(Schema.isMaxLength(256));\nconst BoundedCursorString = Schema.NonEmptyString.check(Schema.isMaxLength(MAX_CURSOR_LENGTH));\n// The generated API response Schema says string; the current product example returns a number.\nconst ProviderCursor = Schema.Union([BoundedCursorString, Schema.Natural]);\n\nconst ProviderJobStatus = Schema.Literals([\n \"running\",\n \"completed\",\n \"errored\",\n \"cancelled_by_user\",\n \"cancelled_due_to_timeout\",\n \"cancelled_due_to_limits\",\n]);\n\nconst ProviderResult = Schema.Struct({\n id: BoundedJobId,\n status: ProviderJobStatus,\n browserSecondsUsed: Schema.optionalKey(Schema.Finite.check(Schema.isGreaterThanOrEqualTo(0))),\n total: Schema.optionalKey(Schema.Natural),\n finished: Schema.optionalKey(Schema.Natural),\n skipped: Schema.optionalKey(Schema.Natural),\n records: Schema.Array(PageCrawlRecord).check(Schema.isMaxLength(MAX_RECORDS_PER_RESPONSE)),\n cursor: Schema.optionalKey(ProviderCursor),\n});\n\nconst CreateEnvelope = Schema.Struct({\n success: Schema.Literal(true),\n result: BoundedJobId,\n});\n\nconst ResultEnvelope = Schema.Struct({\n success: Schema.Literal(true),\n result: ProviderResult,\n});\n\nconst DeleteEnvelope = Schema.Struct({\n success: Schema.Literal(true),\n result: Schema.Struct({\n job_id: BoundedJobId,\n message: Schema.String.check(Schema.isMaxLength(MAX_DIAGNOSTIC_LENGTH)),\n }),\n});\n\n/** Explicit credentials. The token is projected only into fixed-origin Authorization headers. */\nexport interface BrowserRestCrawlOptions {\n readonly accountId: string;\n readonly apiToken: Redacted.Redacted<string>;\n}\n\nconst boundedDiagnostic = (message: string): string => message.slice(0, MAX_DIAGNOSTIC_LENGTH);\n\nconst privateCause = (value: unknown, apiToken: Redacted.Redacted<string>): Error | undefined => {\n const raw = boundedDiagnostic(String(value));\n\n if (raw.length === 0) return undefined;\n const token = Redacted.value(apiToken);\n\n return new Error(token.length === 0 ? raw : raw.replaceAll(token, \"[REDACTED]\"));\n};\n\nconst protocolError = (message: string, cause?: unknown): PageCrawlProtocolError =>\n PageCrawlProtocolError.make({\n implementation: browserRestCrawlImplementation,\n message: boundedDiagnostic(message),\n ...(cause === undefined ? {} : { cause }),\n });\n\nconst limitError = (\n request: PageCrawlRequest,\n limit: PageCrawlLimitError[\"limit\"],\n observed: number,\n): PageCrawlLimitError => {\n const maximum =\n limit === \"pages\"\n ? request.limits.maxPages\n : limit === \"page-bytes\"\n ? request.limits.maxPageBytes\n : limit === \"total-bytes\"\n ? request.limits.maxTotalBytes\n : request.limits.deadlineMillis;\n\n return PageCrawlLimitError.make({\n implementation: browserRestCrawlImplementation,\n limit,\n maximum,\n observed,\n message: `The crawl exceeded its ${limit} limit`,\n });\n};\n\nconst retryAfterMillis = (\n headers: Readonly<Record<string, string | undefined>>,\n): number | undefined => {\n const seconds = Number(headers[\"retry-after\"]);\n\n if (!Number.isSafeInteger(seconds) || seconds < 0) return undefined;\n const millis = seconds * 1_000;\n\n return Number.isSafeInteger(millis) ? millis : undefined;\n};\n\nconst isJsonResponse = (headers: Readonly<Record<string, string | undefined>>): boolean => {\n const contentType = headers[\"content-type\"];\n\n if (contentType === undefined) return false;\n const mediaType = contentType.split(\";\", 1)[0]?.trim().toLowerCase();\n\n return mediaType === \"application/json\" || mediaType?.endsWith(\"+json\") === true;\n};\n\nconst isQuotaMessage = (bodyText: string): boolean => /time limit|daily|quota/i.test(bodyText);\n\nconst endpoint = (options: BrowserRestCrawlOptions, jobId?: string): string =>\n `${API_ORIGIN}/client/v4/accounts/${encodeURIComponent(options.accountId)}/browser-rendering/crawl${\n jobId === undefined ? \"\" : `/${encodeURIComponent(jobId)}`\n }`;\n\nconst readBoundedResponse = Effect.fnUntraced(function* (\n response: HttpClientResponse.HttpClientResponse,\n maximum: number,\n): Effect.fn.Return<string, PageCrawlProtocolError> {\n const decoder = new TextDecoder(\"utf-8\", { fatal: true, ignoreBOM: false });\n\n const state = yield* Stream.runFoldEffect<\n Uint8Array,\n HttpClientError.HttpClientError,\n never,\n { readonly observed: number; readonly text: string },\n PageCrawlProtocolError,\n never\n >(\n response.stream,\n () => ({ observed: 0, text: \"\" }),\n (current, chunk) => {\n const observed = current.observed + chunk.byteLength;\n\n if (observed > maximum) {\n return Effect.fail(\n protocolError(\n `The Browser Run crawl response exceeded ${String(maximum)} transport bytes`,\n ),\n );\n }\n\n return Effect.try({\n try: () => ({ observed, text: current.text + decoder.decode(chunk, { stream: true }) }),\n catch: (cause) => protocolError(\"Decoding the Browser Run crawl response failed\", cause),\n });\n },\n ).pipe(\n Effect.mapError((cause) =>\n Schema.is(PageCrawlProtocolError)(cause)\n ? cause\n : protocolError(\"Reading the Browser Run crawl response failed\", cause),\n ),\n );\n\n return yield* Effect.try({\n try: () => state.text + decoder.decode(),\n catch: (cause) => protocolError(\"Decoding the Browser Run crawl response failed\", cause),\n });\n});\n\nconst deadlineFailure = Effect.fnUntraced(function* (request: PageCrawlRequest, startedAt: number) {\n const now = yield* Effect.clockWith((clock) => clock.currentTimeMillis);\n\n return yield* limitError(request, \"deadline\", Math.max(0, now - startedAt));\n});\n\nconst withinDeadline = Effect.fnUntraced(function* <A, E, R>(\n effect: Effect.Effect<A, E, R>,\n request: PageCrawlRequest,\n startedAt: number,\n): Effect.fn.Return<A, E | PageCrawlLimitError, R> {\n const now = yield* Effect.clockWith((clock) => clock.currentTimeMillis);\n const elapsed = Math.max(0, now - startedAt);\n const remaining = request.limits.deadlineMillis - elapsed;\n\n if (remaining <= 0) return yield* limitError(request, \"deadline\", elapsed);\n\n return yield* effect.pipe(\n Effect.timeoutOrElse({\n duration: Duration.millis(remaining),\n orElse: () => deadlineFailure(request, startedAt),\n }),\n );\n});\n\nconst checkDeadline = Effect.fnUntraced(function* (request: PageCrawlRequest, startedAt: number) {\n const now = yield* Effect.clockWith((clock) => clock.currentTimeMillis);\n const elapsed = Math.max(0, now - startedAt);\n\n if (elapsed >= request.limits.deadlineMillis) {\n return yield* limitError(request, \"deadline\", elapsed);\n }\n});\n\nconst normalizedCursor = (cursor: typeof ProviderCursor.Type): string => String(cursor);\n\ninterface PaginationState {\n readonly cursor: Option.Option<string>;\n readonly seen: ReadonlyArray<string>;\n}\n\ninterface RecordLimitsState {\n readonly pages: number;\n readonly totalBytes: number;\n}\n\nconst sameHost = (expectedHost: string, url: string): boolean => new URL(url).host === expectedHost;\n\nconst makeCrawl =\n (client: HttpClient.HttpClient, options: BrowserRestCrawlOptions): PageCrawlCrawl =>\n (input) =>\n Stream.unwrap(\n Effect.gen(function* () {\n const startedAt = yield* Effect.clockWith((clock) => clock.currentTimeMillis);\n const startHost = new URL(input.startUrl).host;\n\n const executeJson = Effect.fnUntraced(function* <S extends Schema.Top>(\n request: HttpClientRequest.HttpClientRequest,\n schema: S,\n maximum: number,\n ) {\n const authorized = HttpClientRequest.bearerToken(request, options.apiToken).pipe(\n HttpClientRequest.acceptJson,\n );\n\n const response = yield* client\n .execute(authorized)\n .pipe(\n Effect.mapError((cause) =>\n protocolError(\n \"Calling the Browser Run crawl REST API failed\",\n privateCause(cause, options.apiToken),\n ),\n ),\n );\n\n const bodyText = yield* readBoundedResponse(response, maximum);\n\n if (response.status === 429) {\n const reason = isQuotaMessage(bodyText) ? \"quota\" : \"rate\";\n\n return yield* PageCrawlRateLimitedError.make({\n implementation: browserRestCrawlImplementation,\n reason,\n ...(retryAfterMillis(response.headers) === undefined\n ? {}\n : { retryAfterMillis: retryAfterMillis(response.headers) }),\n message:\n reason === \"quota\"\n ? \"Browser Run exceeded its browser quota\"\n : \"Browser Run crawl was rate limited\",\n ...(privateCause(bodyText, options.apiToken) === undefined\n ? {}\n : { cause: privateCause(bodyText, options.apiToken) }),\n });\n }\n if (response.status < 200 || response.status >= 300) {\n return yield* protocolError(\n `Browser Run crawl answered HTTP ${String(response.status)}`,\n privateCause(bodyText, options.apiToken),\n );\n }\n if (!isJsonResponse(response.headers)) {\n return yield* protocolError(\n \"The Browser Run crawl success response was not JSON\",\n privateCause(bodyText, options.apiToken),\n );\n }\n\n return yield* Schema.decodeEffect(Schema.fromJsonString(schema))(bodyText).pipe(\n Effect.mapError((cause) =>\n protocolError(\n \"Browser Run returned a malformed crawl response\",\n privateCause(cause, options.apiToken),\n ),\n ),\n );\n });\n\n const createJob = Effect.gen(function* () {\n const requestWithBody = yield* HttpClientRequest.post(endpoint(options)).pipe(\n HttpClientRequest.bodyJson({\n url: input.startUrl,\n crawlPurposes: [...input.purposes],\n limit: input.limits.maxPages,\n depth: input.limits.maxDepth,\n formats: [\"markdown\"],\n render: true,\n options: {\n includeExternalLinks: false,\n includeSubdomains: false,\n },\n }),\n Effect.mapError((cause) =>\n protocolError(\"Encoding the Browser Run crawl request failed\", cause),\n ),\n );\n\n const created = yield* withinDeadline(\n executeJson(requestWithBody, CreateEnvelope, MAX_CONTROL_RESPONSE_BYTES),\n input,\n startedAt,\n );\n\n return created.result;\n });\n\n const job = yield* Effect.uninterruptibleMask((restore) =>\n restore(createJob).pipe(\n Effect.flatMap((id) =>\n Effect.gen(function* () {\n const state = yield* Ref.make<\"running\" | \"terminal\">(\"running\");\n const scope = yield* Effect.scope;\n\n const cancelIfRunning = Ref.modify(state, (current) =>\n current === \"running\"\n ? [true, \"terminal\" as const]\n : [false, \"terminal\" as const],\n ).pipe(\n Effect.flatMap((shouldCancel) => {\n if (!shouldCancel) return Effect.void;\n\n const cancellation = executeJson(\n HttpClientRequest.delete(endpoint(options, id)),\n DeleteEnvelope,\n MAX_CONTROL_RESPONSE_BYTES,\n ).pipe(\n Effect.flatMap((deleted) =>\n deleted.result.job_id === id\n ? Effect.void\n : protocolError(\"Browser Run cancelled a different crawl job\"),\n ),\n );\n\n return cancellation.pipe(\n Effect.timeoutOrElse({\n duration: CANCEL_TIMEOUT,\n orElse: () =>\n protocolError(\"Cancelling the Browser Run crawl exceeded 30 seconds\"),\n }),\n );\n }),\n );\n\n yield* Scope.addFinalizer(\n scope,\n cancelIfRunning.pipe(\n Effect.catchCause(() =>\n Effect.logWarning(\"Browser Run crawl cancellation failed\"),\n ),\n ),\n );\n\n return { id, state } as const;\n }),\n ),\n ),\n );\n\n const fetchResult = Effect.fnUntraced(function* (\n cursor: Option.Option<string>,\n statusOnly: boolean,\n ) {\n let request = HttpClientRequest.get(endpoint(options, job.id));\n\n if (statusOnly) request = HttpClientRequest.setUrlParam(request, \"limit\", \"1\");\n if (Option.isSome(cursor)) {\n request = HttpClientRequest.setUrlParam(request, \"cursor\", cursor.value);\n }\n\n // `limit=1` still permits one complete record, so poll GETs use the bounded result cap.\n const envelope = yield* withinDeadline(\n executeJson(request, ResultEnvelope, MAX_RESULTS_RESPONSE_BYTES),\n input,\n startedAt,\n );\n\n if (envelope.result.id !== job.id) {\n return yield* protocolError(\"Browser Run returned a different crawl job identity\");\n }\n\n return envelope.result;\n });\n\n const terminal = yield* Effect.uninterruptibleMask((restore) =>\n restore(\n withinDeadline(\n Effect.repeat(fetchResult(Option.none(), true), {\n schedule: Schedule.spaced(POLL_INTERVAL),\n until: (result) => result.status !== \"running\",\n }),\n input,\n startedAt,\n ),\n ).pipe(Effect.tap(() => Ref.set(job.state, \"terminal\"))),\n );\n\n if (terminal.status === \"running\") {\n return yield* protocolError(\"Browser Run polling stopped before a terminal status\");\n }\n if (terminal.status !== \"completed\") {\n return yield* PageCrawlTerminalError.make({\n implementation: browserRestCrawlImplementation,\n status: terminal.status,\n message: `Browser Run crawl ended with status ${terminal.status}`,\n });\n }\n\n const pages = Stream.paginate<PaginationState, PageCrawlRecord, PageCrawlError>(\n { cursor: Option.none(), seen: [] },\n (state) =>\n Effect.gen(function* () {\n const result = yield* fetchResult(state.cursor, false);\n\n if (result.status !== \"completed\") {\n return yield* protocolError(\n \"Browser Run changed crawl status during result pagination\",\n );\n }\n if (result.cursor === undefined) {\n return [result.records, Option.none()] as const;\n }\n const cursor = normalizedCursor(result.cursor);\n\n if (state.seen.includes(cursor)) {\n return yield* protocolError(\"Browser Run repeated a crawl result cursor\");\n }\n if (state.seen.length >= input.limits.maxPages) {\n return yield* protocolError(\"Browser Run returned too many crawl result cursors\");\n }\n\n return [\n result.records,\n Option.some({ cursor: Option.some(cursor), seen: [...state.seen, cursor] }),\n ] as const;\n }),\n );\n\n return pages.pipe(\n Stream.rechunk(1),\n Stream.mapAccumEffect(\n (): RecordLimitsState => ({ pages: 0, totalBytes: 0 }),\n (state, record) =>\n Effect.gen(function* () {\n yield* checkDeadline(input, startedAt);\n const pages = state.pages + 1;\n\n if (pages > input.limits.maxPages) {\n return yield* limitError(input, \"pages\", pages);\n }\n if (!sameHost(startHost, record.url)) {\n return yield* protocolError(\"Browser Run returned an off-host crawl record\");\n }\n if (record.metadata !== undefined && !sameHost(startHost, record.metadata.url)) {\n return yield* protocolError(\"Browser Run returned off-host crawl metadata\");\n }\n\n const pageBytes =\n record.markdown === undefined\n ? 0\n : new TextEncoder().encode(record.markdown).byteLength;\n\n if (pageBytes > input.limits.maxPageBytes) {\n return yield* limitError(input, \"page-bytes\", pageBytes);\n }\n const totalBytes = state.totalBytes + pageBytes;\n\n if (totalBytes > input.limits.maxTotalBytes) {\n return yield* limitError(input, \"total-bytes\", totalBytes);\n }\n\n return [{ pages, totalBytes }, [record]] as const;\n }),\n ),\n );\n }),\n );\n\n/** Cloudflare REST PageCrawl Layer for Node and other non-Worker composition roots. */\nexport const browserRestCrawlLayer = (\n options: BrowserRestCrawlOptions,\n): Layer.Layer<PageCrawl, never, HttpClient.HttpClient> =>\n Layer.effect(\n PageCrawl,\n Effect.map(HttpClient.HttpClient, (client) =>\n PageCrawl.of({ crawl: makeCrawl(client, options) }),\n ),\n );\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
2
  import { BrowserCredentialAccess, CardCredential, CredentialFillError, CredentialFillResult, CredentialOrigin, CredentialTarget, FillCredentialRequest, LoginCredential } from "./BrowserCredentials.mjs";
3
- import { C as reportedBrowserError, S as reportBrowserCause, b as BrowserRunFailure, c as BrowserRunLiveViewResult, n as BrowserRunHandoffResult, r as BrowserRunHandoffState, s as BrowserRunLiveViewRequest, t as BrowserRunHandoffRequest, v as BrowserRunSessionLifecycle, x as browserFailure, y as BrowserRunBinding } from "./InteractiveBrowser-BbG3kGA9.mjs";
3
+ import { C as reportedBrowserError, S as reportBrowserCause, b as BrowserRunFailure, c as BrowserRunLiveViewResult, n as BrowserRunHandoffResult, r as BrowserRunHandoffState, s as BrowserRunLiveViewRequest, t as BrowserRunHandoffRequest, v as BrowserRunSessionLifecycle, x as browserFailure, y as BrowserRunBinding } from "./InteractiveBrowser-LdKzQeLR.mjs";
4
4
  import { Cause, Clock, Context, Effect, Exit, Layer, Redacted, Schema, Scope, Semaphore, Stream } from "effect";
5
5
  import { FetchHttpClient, HttpClient, HttpClientRequest } from "effect/http";
6
6
  //#region src/internal/browser-credentials.ts
@@ -421,11 +421,11 @@ var BrowserSessions = class BrowserSessions extends Context.Service()("@effect-a
421
421
  if (remaining <= 0) return yield* failure("expired", "not-dispatched", yield* terminate);
422
422
  return yield* action(Math.min(remaining, reference.commandTimeoutMillis)).pipe(Effect.catchDefect((defect) => reportBrowserCause("session.command", Cause.die(defect)).pipe(Effect.andThen(terminate), Effect.flatMap((closed) => Effect.fail(failure("provider", "possibly-dispatched", closed))))), Effect.onInterrupt(() => terminate));
423
423
  })).pipe(Effect.flatMap(Effect.fromOption(() => failure("busy"))), Effect.withTracerEnabled(false));
424
- const run = (authorize, action, terminateOnError = false) => runEffect((commandTimeoutMillis) => authorize.pipe(Effect.andThen(() => native("session.command", () => action(currentPage)).pipe(Effect.catch((error) => Effect.gen(function* () {
424
+ const run = (authorize, action, terminateOnError = false, timeoutMillis) => runEffect((commandTimeoutMillis) => authorize.pipe(Effect.andThen(() => native("session.command", () => action(currentPage)).pipe(Effect.catch((error) => Effect.gen(function* () {
425
425
  const closed = terminateOnError ? yield* terminate : "not-requested";
426
426
  return yield* reportedBrowserError(failure(error.reason, "possibly-dispatched", closed));
427
427
  })))), Effect.timeoutOrElse({
428
- duration: commandTimeoutMillis,
428
+ duration: Math.min(commandTimeoutMillis, timeoutMillis ?? commandTimeoutMillis),
429
429
  orElse: () => terminate.pipe(Effect.flatMap((closed) => Effect.fail(failure("timeout", "possibly-dispatched", closed))))
430
430
  })));
431
431
  const command = (authorize, method, parameters, schema) => run(authorize, async (page) => {
@@ -439,7 +439,7 @@ var BrowserSessions = class BrowserSessions extends Context.Service()("@effect-a
439
439
  }, method === "Cloudflare.handoff");
440
440
  return {
441
441
  reference,
442
- run,
442
+ run: (authorize, action, options) => options === void 0 ? run(authorize, action) : decode(PositiveMillis, options.timeoutMillis).pipe(Effect.flatMap((timeoutMillis) => run(authorize, action, false, timeoutMillis))),
443
443
  fillCredential: (request) => runEffect((commandTimeoutMillis) => fillCredential(request).pipe(Effect.provideService(BrowserSessionPage, {
444
444
  page: currentPage,
445
445
  commandTimeoutMillis
@@ -512,4 +512,4 @@ var BrowserSessions = class BrowserSessions extends Context.Service()("@effect-a
512
512
  //#endregion
513
513
  export { BrowserSessions as a, BrowserSession_exports as i, BrowserSessionOptions as n, BrowserSessionReference as r, BrowserSessionError as t };
514
514
 
515
- //# sourceMappingURL=BrowserSession-RfIzxGCH.mjs.map
515
+ //# sourceMappingURL=BrowserSession-BfNmyayH.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BrowserSession-BfNmyayH.mjs","names":[],"sources":["../src/internal/browser-credentials.ts","../src/internal/browser-readonly-live-view.ts","../src/BrowserSession.ts"],"sourcesContent":["import { Cause, Context, Effect, Redacted, Schema } from \"effect\";\nimport type { Frame, Page } from \"puppeteer-core/lib/esm/puppeteer/puppeteer-core-browser.js\";\n\nimport {\n BrowserCredentialAccess,\n type BrowserCredentialMaterial,\n CardCredential,\n type CredentialDispatch,\n type CredentialFieldRole,\n CredentialFillError,\n CredentialFillResult,\n CredentialOrigin,\n CredentialTarget,\n FillCredentialRequest,\n LoginCredential,\n type CredentialAccessRequest,\n} from \"../BrowserCredentials.ts\";\n\n/** Supplied only under the attachment lock, with the remaining command/session budget. */\nexport class BrowserSessionPage extends Context.Service<\n BrowserSessionPage,\n {\n readonly page: Page;\n readonly commandTimeoutMillis: number;\n }\n>()(\"@effect-agent/platform-cloudflare/internal/BrowserSessionPage\") {}\n\nconst TargetReply = Schema.Union([\n Schema.Struct({ action: Schema.String.check(Schema.isMaxLength(2048)) }),\n Schema.Struct({ reason: Schema.Literals([\"stale-target\", \"unsupported\"]) }),\n]);\n\nconst WriteReply = Schema.Literals([\n \"filled\",\n \"stale-target\",\n \"unsupported-before-write\",\n \"unsupported\",\n]);\n\n// One invocation-local isolated-world handle. Actual nodes and fingerprints never leave the page.\n// This program neither discovers controls nor classifies roles nor observes page content.\nconst prepareFields = `(() => {\n const doc = document;\n let fields = [];\n let form;\n let snapshots = [];\n const describe = el => {\n if (!el || !el.isConnected || el.ownerDocument !== doc || doc !== document) return null;\n const native = el instanceof HTMLTextAreaElement ||\n (el instanceof HTMLSelectElement && !el.multiple) ||\n (el instanceof HTMLInputElement && ['text','email','password','tel','number','month','search','url','date','time','week','datetime-local'].includes(el.type));\n if (!native || el.matches(':disabled') || el.readOnly || !el.form) return null;\n const values = [el.form.action, el.form.method, el.form.enctype, el.name, el.type, el.autocomplete ?? ''];\n if (values.some(value => value.length > 2048)) return null;\n return JSON.stringify(values);\n };\n const validate = () => fields.length > 0 && fields.every((el, index) =>\n el.form === form && describe(el) !== null && describe(el) === snapshots[index]);\n return {\n prepare(selectors) {\n try {\n fields = selectors.map(selector => {\n const matches = doc.querySelectorAll(selector);\n return matches.length === 1 ? matches[0] : null;\n });\n } catch { return {reason: 'stale-target'}; }\n if (fields.some(el => !el) || new Set(fields).size !== fields.length) return {reason: 'stale-target'};\n snapshots = fields.map(describe);\n form = fields[0].form;\n if (!form || snapshots.some(value => value === null) || fields.some(el => el.form !== form)) return {reason: 'unsupported'};\n return {action: form.action};\n },\n target() { return validate() ? {action: form.action} : {reason: 'stale-target'}; },\n fill(index, value) {\n if (!validate()) return 'stale-target';\n const el = fields[index];\n if (el instanceof HTMLSelectElement) {\n const options = [...el.options].filter(option => option.value === value);\n if (options.length !== 1 || options[0].matches(':disabled')) return 'unsupported-before-write';\n }\n let prototype = Object.getPrototypeOf(el);\n let setter;\n while (prototype && !setter) { setter = Object.getOwnPropertyDescriptor(prototype, 'value')?.set; prototype = Object.getPrototypeOf(prototype); }\n if (!setter) return 'unsupported-before-write';\n setter.call(el, value);\n if (el.value !== value) return 'unsupported';\n el.dispatchEvent(new Event('input', {bubbles: true}));\n el.dispatchEvent(new Event('change', {bubbles: true}));\n return 'filled';\n }\n };\n})()`;\n\nconst secretFor = (material: BrowserCredentialMaterial, role: typeof CredentialFieldRole.Type) => {\n if (material._tag === \"LoginCredential\")\n return role === \"username\"\n ? material.username\n : role === \"password\"\n ? material.password\n : undefined;\n switch (role) {\n case \"card-name\":\n return material.name;\n case \"card-number\":\n return material.number;\n case \"card-expiry\":\n return material.expiry;\n case \"card-expiry-month\":\n return material.expiryMonth;\n case \"card-expiry-year\":\n return material.expiryYear;\n case \"card-security-code\":\n return material.securityCode;\n case \"username\":\n case \"password\":\n return undefined;\n }\n};\n\n/**\n * Fill explicit native fields on an existing page without submitting. The owning browser session\n * serializes operations and closes on timeout, interruption or uncertain dispatch; this function releases\n * only its local handles. Ordinary native observations remain available, including credential echoes.\n */\nexport const fillCredential = Effect.fnUntraced(function* (\n input: FillCredentialRequest,\n): Effect.fn.Return<\n CredentialFillResult,\n CredentialFillError,\n BrowserCredentialAccess | BrowserSessionPage\n> {\n const { page, commandTimeoutMillis } = yield* BrowserSessionPage;\n let dispatch: typeof CredentialDispatch.Type = \"not-dispatched\";\n let filled = 0;\n\n const fail = (reason: CredentialFillError[\"reason\"]) =>\n new CredentialFillError({ reason, dispatch, filled, cleanup: \"not-requested\" });\n\n const remote = <A>(run: (signal: AbortSignal) => Promise<A>) =>\n Effect.tryPromise({\n try: async (signal) => {\n try {\n return { ok: true as const, value: await run(signal) };\n } catch {\n return { ok: false as const };\n }\n },\n catch: () => fail(\"provider\"),\n }).pipe(\n Effect.flatMap((result) =>\n result.ok ? Effect.succeed(result.value) : Effect.fail(fail(\"provider\")),\n ),\n );\n\n const release = (handles: ReadonlyArray<{ dispose(): Promise<void> }>) =>\n Effect.promise(async () => {\n await Promise.all(handles.map((handle) => handle.dispose().catch(() => {})));\n }).pipe(Effect.interruptible, Effect.timeoutOption(\"1 second\"), Effect.asVoid);\n\n const acquire = <A extends { dispose(): Promise<void> }>(run: () => Promise<ReadonlyArray<A>>) =>\n Effect.acquireRelease(\n remote(async (signal) => {\n const handles = await run();\n\n if (signal.aborted) {\n await Promise.all(handles.map((handle) => handle.dispose().catch(() => {})));\n throw fail(\"provider\");\n }\n\n return handles;\n }).pipe(Effect.interruptible),\n release,\n );\n\n const origin = (value: string) =>\n Effect.try({\n try: () => {\n const url = new URL(value);\n\n if (url.username || url.password) throw fail(\"denied\");\n\n return url.origin;\n },\n catch: () => fail(\"denied\"),\n }).pipe(\n Effect.flatMap(Schema.decodeUnknownEffect(CredentialOrigin)),\n Effect.mapError(() => fail(\"denied\")),\n );\n\n return yield* Effect.gen(function* () {\n const request = yield* Schema.decodeEffect(FillCredentialRequest, {\n onExcessProperty: \"error\",\n })(input).pipe(Effect.mapError(() => fail(\"denied\")));\n\n const roles = request.fields.map((field) => field.role);\n\n if (\n new Set(roles).size !== roles.length ||\n roles.some(\n (role) => (request.kind === \"login\") !== (role === \"username\" || role === \"password\"),\n )\n )\n return yield* fail(\"denied\");\n const access = yield* BrowserCredentialAccess;\n let frame: Frame = page.mainFrame();\n\n for (const selector of request.frame ?? []) {\n const matches = yield* acquire(() => frame.$$(selector));\n const element = matches[0];\n\n if (matches.length !== 1 || element === undefined) return yield* fail(\"stale-target\");\n const child = yield* remote(() => element.contentFrame());\n\n if (child === null) return yield* fail(\"unsupported\");\n frame = child;\n }\n\n const handles = yield* acquire(async () => [\n await frame.isolatedRealm().evaluateHandle(prepareFields),\n ]);\n\n const held = handles[0];\n\n if (held === undefined) return yield* fail(\"provider\");\n\n const inspect = (raw: unknown) =>\n Schema.decodeUnknownEffect(TargetReply)(raw).pipe(\n Effect.mapError(() => fail(\"provider\")),\n Effect.flatMap((reply) =>\n \"reason\" in reply ? Effect.fail(fail(reply.reason)) : Effect.succeed(reply.action),\n ),\n );\n\n const action = yield* remote(() =>\n held.evaluate(\n (state, selectors) => {\n if (typeof state !== \"object\" || state === null) return null;\n\n return Reflect.apply(Reflect.get(state, \"prepare\"), state, [selectors]);\n },\n request.fields.map((field) => field.selector),\n ),\n ).pipe(Effect.flatMap(inspect));\n\n const target = CredentialTarget.make({\n topOrigin: yield* origin(page.url()),\n frameOrigin: yield* origin(frame.url()),\n recipientOrigin: yield* origin(action),\n });\n\n const authorization: CredentialAccessRequest = {\n credential: request.credential,\n kind: request.kind,\n target,\n roles,\n };\n\n const authorize = Effect.suspend(() => access.authorize(authorization)).pipe(\n Effect.mapError((error) => fail(error.reason)),\n );\n\n const validate = Effect.gen(function* () {\n if (\n frame.detached ||\n (yield* origin(page.url())) !== target.topOrigin ||\n (yield* origin(frame.url())) !== target.frameOrigin\n )\n return yield* fail(\"stale-target\");\n\n const current = yield* remote(() =>\n held.evaluate((state) => {\n if (typeof state !== \"object\" || state === null) return null;\n\n return Reflect.apply(Reflect.get(state, \"target\"), state, []);\n }),\n ).pipe(Effect.flatMap(inspect));\n\n if ((yield* origin(current)) !== target.recipientOrigin) return yield* fail(\"stale-target\");\n });\n\n yield* authorize;\n yield* validate;\n\n const raw = yield* access\n .resolve(authorization)\n .pipe(Effect.mapError((error) => fail(error.reason)));\n\n const material = yield* Schema.decodeEffect(\n request.kind === \"login\" ? LoginCredential : CardCredential,\n )(raw).pipe(Effect.mapError(() => fail(\"resolver\")));\n\n for (const role of roles)\n if (secretFor(material, role) === undefined) return yield* fail(\"missing-credential\");\n for (const [index, role] of roles.entries()) {\n yield* authorize;\n yield* validate;\n const value = secretFor(material, role);\n\n if (value === undefined) return yield* fail(\"missing-credential\");\n const previous = dispatch;\n\n const result = yield* remote((signal) => {\n if (signal.aborted) return Promise.reject(fail(\"provider\"));\n dispatch = \"possibly-dispatched\";\n\n return held.evaluate(\n (state, field, secret) => {\n if (typeof state !== \"object\" || state === null) return \"stale-target\";\n\n return Reflect.apply(Reflect.get(state, \"fill\"), state, [field, secret]);\n },\n index,\n Redacted.value(value),\n );\n }).pipe(\n Effect.flatMap(Schema.decodeUnknownEffect(WriteReply)),\n Effect.mapError(() => fail(\"provider\")),\n );\n\n if (result === \"stale-target\" || result === \"unsupported-before-write\") {\n dispatch = previous;\n\n return yield* fail(result === \"stale-target\" ? \"stale-target\" : \"unsupported\");\n }\n if (result === \"unsupported\") return yield* fail(\"unsupported\");\n dispatch = \"dispatched\";\n filled++;\n }\n\n return CredentialFillResult.make({ dispatch: \"dispatched\", filled });\n }).pipe(\n Effect.scoped,\n Effect.timeoutOrElse({\n duration: commandTimeoutMillis,\n orElse: () => Effect.fail(fail(\"timeout\")),\n }),\n Effect.catchCause((cause) => {\n if (Cause.hasInterrupts(cause)) return Effect.interrupt;\n if (\n cause.reasons.some(\n (reason) =>\n reason._tag === \"Die\" ||\n (reason._tag === \"Fail\" && !Schema.is(CredentialFillError)(reason.error)),\n )\n )\n return Effect.fail(fail(\"provider\"));\n\n const expected = cause.reasons.find(\n (reason) => reason._tag === \"Fail\" && Schema.is(CredentialFillError)(reason.error),\n );\n\n return Effect.fail(\n fail(\n expected?._tag === \"Fail\" && Schema.is(CredentialFillError)(expected.error)\n ? expected.error.reason\n : \"provider\",\n ),\n );\n }),\n Effect.withTracerEnabled(false),\n );\n});\n","import { Context, Effect, Layer, Redacted, Schema, Stream } from \"effect\";\nimport { FetchHttpClient, HttpClient, HttpClientRequest } from \"effect/http\";\n\nimport { BrowserRunLiveViewRequest, BrowserRunLiveViewResult } from \"../InteractiveBrowser.ts\";\nimport { browserFailure, BrowserRunFailure } from \"./browser-failure.ts\";\nimport type { BrowserRunLifecycleOptions } from \"./browser-session-lifecycle.ts\";\n\nconst Identity = Schema.Struct({\n sessionId: Schema.String.check(Schema.isUUID()),\n targetId: Schema.NonEmptyString.check(Schema.isMaxLength(256)),\n});\n\nconst Reply = Schema.fromJsonString(\n Schema.Struct({\n id: Identity.fields.targetId,\n options: Schema.Struct({\n mode: Schema.Literal(\"tab\"),\n guardrails: Schema.Struct({ mode: Schema.Literal(\"readonly\") }),\n }),\n devtoolsFrontendUrl: Schema.String,\n }),\n);\n\nconst operation = \"session.readonlyLiveView\";\n\n/** Only the REST endpoint can mint provider-enforced read-only connections. */\nexport class BrowserRunReadonlyLiveView extends Context.Service<\n BrowserRunReadonlyLiveView,\n {\n readonly mint: (\n sessionId: Redacted.Redacted<string>,\n targetId: Redacted.Redacted<string>,\n request: BrowserRunLiveViewRequest,\n ) => Effect.Effect<BrowserRunLiveViewResult, BrowserRunFailure>;\n }\n>()(\"@effect-agent/platform-cloudflare/internal/BrowserRunReadonlyLiveView\") {\n static layer(options: BrowserRunLifecycleOptions) {\n return Layer.effect(\n this,\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient;\n\n const mint = Effect.fnUntraced(\n function* (\n sessionId: Redacted.Redacted<string>,\n targetId: Redacted.Redacted<string>,\n request: BrowserRunLiveViewRequest,\n ) {\n const identity = yield* Schema.decodeEffect(Identity)({\n sessionId: Redacted.value(sessionId),\n targetId: Redacted.value(targetId),\n });\n\n const input = yield* Schema.decodeEffect(BrowserRunLiveViewRequest)(request);\n\n const response = yield* client\n .execute(\n HttpClientRequest.post(\n `https://api.cloudflare.com/client/v4/accounts/${options.accountId}/browser-rendering/devtools/browser/${identity.sessionId}/live_view`,\n ).pipe(\n HttpClientRequest.bearerToken(options.apiToken),\n HttpClientRequest.bodyJsonUnsafe({\n mode: input.mode,\n expiresInMs: input.expiresInMs,\n targetId: identity.targetId,\n guardrails: { mode: \"readonly\" },\n }),\n ),\n )\n .pipe(Effect.provideService(FetchHttpClient.RequestInit, { redirect: \"manual\" }));\n\n if (response.status !== 200)\n return yield* new BrowserRunFailure({\n operation,\n reason: \"provider\",\n status: response.status,\n });\n\n const bytes = yield* Stream.runFoldEffect(\n response.stream,\n () => new Uint8Array(),\n (body, chunk) => {\n if (body.byteLength + chunk.byteLength > 16_384)\n return Effect.fail(new BrowserRunFailure({ operation, reason: \"malformed\" }));\n const combined = new Uint8Array(body.byteLength + chunk.byteLength);\n\n combined.set(body);\n combined.set(chunk, body.byteLength);\n\n return Effect.succeed(combined);\n },\n );\n\n const reply = yield* Schema.decodeEffect(Reply)(new TextDecoder().decode(bytes));\n\n if (reply.id !== identity.targetId)\n return yield* new BrowserRunFailure({ operation, reason: \"malformed\" });\n\n return yield* Schema.decodeEffect(BrowserRunLiveViewResult)({\n devtoolsFrontendUrl: Redacted.make(reply.devtoolsFrontendUrl),\n });\n },\n Effect.mapError((cause) => browserFailure(operation, cause)),\n Effect.withTracerEnabled(false),\n );\n\n return { mint };\n }),\n );\n }\n}\n","/// <reference types=\"@cloudflare/workers-types\" />\n\nimport {\n Cause,\n Clock,\n Context,\n Effect,\n Exit,\n Layer,\n Redacted,\n Schema,\n Semaphore,\n Scope,\n} from \"effect\";\nimport type { Browser, Page } from \"puppeteer-core/lib/esm/puppeteer/puppeteer-core-browser.js\";\n\nimport {\n CredentialFillError,\n type BrowserCredentialAccess,\n type CredentialFillResult,\n type FillCredentialRequest,\n} from \"./BrowserCredentials.ts\";\nimport {\n BrowserRunHandoffRequest,\n BrowserRunHandoffResult,\n BrowserRunHandoffState,\n BrowserRunLiveViewRequest,\n BrowserRunLiveViewResult,\n} from \"./InteractiveBrowser.ts\";\nimport { BrowserRunBinding, type BrowserRunAttachment } from \"./internal/browser-binding.ts\";\nimport { BrowserSessionPage, fillCredential } from \"./internal/browser-credentials.ts\";\nimport { reportBrowserCause, reportedBrowserError } from \"./internal/browser-failure.ts\";\nimport { BrowserRunReadonlyLiveView } from \"./internal/browser-readonly-live-view.ts\";\nimport {\n BrowserRunSessionLifecycle,\n type BrowserRunLifecycleOptions,\n} from \"./internal/browser-session-lifecycle.ts\";\n\nexport {\n BrowserRunHandoffRequest,\n BrowserRunHandoffResult,\n BrowserRunHandoffState,\n BrowserRunLiveViewRequest,\n BrowserRunLiveViewResult,\n};\n\nconst PositiveMillis = Schema.Int.check(\n Schema.isGreaterThan(0),\n Schema.isLessThanOrEqualTo(Number.MAX_SAFE_INTEGER),\n);\n\nconst SessionId = Schema.Redacted(Schema.String.check(Schema.isUUID()));\nconst ProviderId = Schema.Redacted(Schema.NonEmptyString.check(Schema.isMaxLength(256)));\n\n/** Private host record, not a model capability. Persist together with the owner's controller state. */\nexport class BrowserSessionReference extends Schema.Class<BrowserSessionReference>(\n \"BrowserSessionReference\",\n)({\n version: Schema.Literal(1),\n sessionId: SessionId,\n contextId: ProviderId,\n targetId: ProviderId,\n expiresAt: PositiveMillis,\n commandTimeoutMillis: PositiveMillis,\n}) {}\n\nexport class BrowserSessionOptions extends Schema.Class<BrowserSessionOptions>(\n \"BrowserSessionOptions\",\n)({\n maxElapsedMillis: PositiveMillis,\n keepAliveMillis: Schema.optionalKey(PositiveMillis.check(Schema.isLessThanOrEqualTo(600_000))),\n commandTimeoutMillis: Schema.optionalKey(PositiveMillis),\n}) {}\n\n/** No SDK text, selectors, page data, or credential values are retained in public failures. */\nexport class BrowserSessionError extends Schema.TaggedError<BrowserSessionError>()(\n \"BrowserSessionError\",\n {\n reason: Schema.Literals([\n \"invalid\",\n \"expired\",\n \"missing-page\",\n \"busy\",\n \"closed\",\n \"provider\",\n \"timeout\",\n \"cleanup\",\n ]),\n dispatch: Schema.Literals([\"not-dispatched\", \"possibly-dispatched\"]),\n cleanup: Schema.Literals([\"not-requested\", \"confirmed\", \"unconfirmed\"]),\n },\n) {}\n\n/**\n * One local attachment to an application-owned browser. Scope release disconnects; it never\n * transfers ownership or closes a healthy remote session. The owner serializes attachments,\n * fences old attempts, authorizes human access, and calls BrowserSessions.close on expiry/stop.\n * Native callbacks are trusted host code: never retain SDK handles or start unawaited work.\n */\nexport interface BrowserSession {\n readonly reference: BrowserSessionReference;\n /**\n * Check current authority under the lock before native dispatch. A settled SDK rejection leaves\n * the session available for inspection, but may have changed the website; never retry blindly.\n * Timeout/interruption fences outstanding SDK work and terminates the exact browser.\n * An optional timeoutMillis narrows the command deadline, for example for bounded preparation.\n */\n readonly run: <A, E, R>(\n authorize: Effect.Effect<void, E, R>,\n action: (page: Page) => Promise<A>,\n options?: { readonly timeoutMillis: number },\n ) => Effect.Effect<A, E | BrowserSessionError, R>;\n /**\n * Resolves host-owned material under fresh credential grants. Never submits or retries a write.\n * Credential timeouts retain acknowledged writes and dispatch evidence alongside cleanup.\n */\n readonly fillCredential: (\n request: FillCredentialRequest,\n ) => Effect.Effect<\n CredentialFillResult,\n CredentialFillError | BrowserSessionError,\n BrowserCredentialAccess\n >;\n readonly handoff: <E, R>(\n authorize: Effect.Effect<void, E, R>,\n request: BrowserRunHandoffRequest,\n ) => Effect.Effect<BrowserRunHandoffResult, E | BrowserSessionError, R>;\n readonly getLiveView: <E, R>(\n authorize: Effect.Effect<void, E, R>,\n request: BrowserRunLiveViewRequest,\n ) => Effect.Effect<BrowserRunLiveViewResult, E | BrowserSessionError, R>;\n /**\n * Mint a provider-enforced read-only connection to this exact page. Requires REST credentials;\n * missing read-only confirmation fails closed, never falling back to an interactive URL.\n * Expiry limits new connections, not established connections or access to visible page data.\n */\n readonly getReadOnlyLiveView: <E, R>(\n authorize: Effect.Effect<void, E, R>,\n request: BrowserRunLiveViewRequest,\n ) => Effect.Effect<BrowserRunLiveViewResult, E | BrowserSessionError, R>;\n readonly getHandoffState: <E, R>(\n authorize: Effect.Effect<void, E, R>,\n ) => Effect.Effect<BrowserRunHandoffState, E | BrowserSessionError, R>;\n}\n\nconst failure = (\n reason: BrowserSessionError[\"reason\"],\n dispatch: BrowserSessionError[\"dispatch\"] = \"not-dispatched\",\n cleanup: BrowserSessionError[\"cleanup\"] = \"not-requested\",\n) => new BrowserSessionError({ reason, dispatch, cleanup });\n\nconst decode = <A>(schema: Schema.Codec<A>, input: unknown) =>\n Schema.decodeUnknownEffect(schema, { onExcessProperty: \"error\" })(input).pipe(\n Effect.mapError(() => failure(\"invalid\")),\n );\n\n// Catch inside the Promise before workerd can report an unhandled foreign diagnostic.\nconst native = Effect.fnUntraced(function* <A>(\n operation: string,\n action: (signal: AbortSignal) => Promise<A>,\n) {\n const runReport = Effect.runPromiseWith(yield* Effect.context<never>());\n\n return yield* Effect.tryPromise({\n try: async (signal) => {\n try {\n return { ok: true as const, value: await action(signal) };\n } catch (cause) {\n if (!signal.aborted || cause !== signal.reason)\n await runReport(reportBrowserCause(operation, Cause.fail(cause)));\n\n return { ok: false as const };\n }\n },\n catch: () => failure(\"provider\"),\n }).pipe(\n Effect.flatMap((result) =>\n result.ok\n ? Effect.succeed(result.value)\n : Effect.fail(reportedBrowserError(failure(\"provider\"))),\n ),\n Effect.withTracerEnabled(false),\n );\n});\n\nconst targetId = (page: Page) =>\n native(\"session.target\", async () => {\n const cdp = await page.createCDPSession();\n\n try {\n return (await cdp.send(\"Target.getTargetInfo\")).targetInfo.targetId;\n } finally {\n await cdp.detach();\n }\n });\n\nexport interface BrowserSessionsOptions extends BrowserRunLifecycleOptions {\n readonly browser: Pick<BrowserRun, \"fetch\">;\n}\n\n/** Native Cloudflare sessions; no framework browser workflow, checkpoint transfer, or observation policy. */\nexport class BrowserSessions extends Context.Service<\n BrowserSessions,\n {\n /**\n * Allocate once and commit its private reference in retain. Failed/uncommitted creation closes\n * the allocation. After retain succeeds the application owns remote cleanup, independent of\n * attempt Scopes. A lost allocation reply can remain indeterminate until provider idle expiry.\n */\n readonly create: <E, R>(\n options: BrowserSessionOptions,\n retain: (reference: BrowserSessionReference) => Effect.Effect<void, E, R>,\n ) => Effect.Effect<BrowserSessionReference, E | BrowserSessionError, R>;\n /**\n * Allocate and retain as create does, keeping the initial attachment in the caller's Scope.\n * No session is exposed before retain succeeds. Failed acquisition releases its attachment\n * immediately; after retention the application owns remote cleanup. The 30-second acquisition\n * timeout ends before use; each command retains its own timeout and the fixed session expiry.\n */\n readonly createAttached: <E, R>(\n options: BrowserSessionOptions,\n retain: (reference: BrowserSessionReference) => Effect.Effect<void, E, R>,\n ) => Effect.Effect<BrowserSession, E | BrowserSessionError, R | Scope.Scope>;\n /** Attach only the exact saved context/page. Never recreate missing/expired state. */\n readonly attach: (\n reference: BrowserSessionReference,\n ) => Effect.Effect<BrowserSession, BrowserSessionError, Scope.Scope>;\n /** Refresh provider inactivity only; the owner must still enforce its expiresAt. */\n readonly keepAlive: (\n sessionId: Redacted.Redacted<string>,\n ) => Effect.Effect<void, BrowserSessionError>;\n readonly close: (\n sessionId: Redacted.Redacted<string>,\n ) => Effect.Effect<void, BrowserSessionError>;\n }\n>()(\"@effect-agent/platform-cloudflare/BrowserSessions\") {\n static readonly layerNoDeps = Layer.effect(\n this,\n Effect.gen(function* () {\n const binding = yield* BrowserRunBinding;\n const lifecycle = yield* BrowserRunSessionLifecycle;\n const readonlyLiveView = yield* BrowserRunReadonlyLiveView;\n\n const close = (sessionId: Redacted.Redacted<string>) =>\n decode(SessionId, sessionId).pipe(\n Effect.flatMap((id) =>\n lifecycle\n .close(id)\n .pipe(Effect.mapError(() => failure(\"cleanup\", \"not-dispatched\", \"unconfirmed\"))),\n ),\n );\n\n const cleanup = (sessionId: Redacted.Redacted<string>) =>\n close(sessionId).pipe(\n Effect.as(\"confirmed\" as const),\n Effect.catchCause((cause) =>\n reportBrowserCause(\"session.close\", cause).pipe(Effect.as(\"unconfirmed\" as const)),\n ),\n );\n\n const connect = Effect.fnUntraced(function* (sessionId: Redacted.Redacted<string>) {\n let attachment: BrowserRunAttachment | undefined;\n\n const retire = Effect.suspend(() =>\n attachment === undefined\n ? Effect.void\n : attachment.retire.pipe(\n // Dispatch is already fenced; give the socket close handshake the same\n // bounded window as keepalive instead of failing a settled command after 1s.\n Effect.timeoutOrElse({\n duration: \"10 seconds\",\n orElse: () => Effect.fail(failure(\"cleanup\")),\n }),\n Effect.catchCause((cause) =>\n reportBrowserCause(\"session.disconnect\", cause).pipe(\n Effect.andThen(Effect.die(failure(\"cleanup\", \"not-dispatched\", \"unconfirmed\"))),\n ),\n ),\n ),\n );\n\n yield* Effect.addFinalizer(() => retire);\n\n const browser = yield* native(\"session.connect\", (signal) => {\n attachment = binding.connect(Redacted.value(sessionId), \"session.connect\", signal);\n\n return attachment.browser;\n });\n\n return { browser, retire };\n });\n\n const allocate = Effect.fnUntraced(function* <E, R>(\n input: BrowserSessionOptions,\n retain: (reference: BrowserSessionReference) => Effect.Effect<void, E, R>,\n ) {\n const options = yield* decode(BrowserSessionOptions, input);\n const expiresAt = (yield* Clock.currentTimeMillis) + options.maxElapsedMillis;\n\n if (!Number.isSafeInteger(expiresAt)) return yield* failure(\"invalid\");\n let sessionId: Redacted.Redacted<string> | undefined;\n let retained = false;\n const runCleanup = Effect.runPromiseWith(yield* Effect.context<never>());\n\n yield* Effect.addFinalizer(() =>\n sessionId === undefined || retained ? Effect.void : cleanup(sessionId),\n );\n sessionId = yield* native(\"session.acquire\", async (signal) => {\n const id = Redacted.make(\n await binding.acquire(options.keepAliveMillis ?? 600_000, \"session.acquire\"),\n );\n\n if (signal.aborted) {\n await runCleanup(cleanup(id));\n signal.throwIfAborted();\n }\n\n return id;\n });\n const connection = yield* connect(sessionId);\n\n const page = yield* native(\"session.page\", async () => {\n const context = await connection.browser.createBrowserContext();\n\n return await context.newPage();\n });\n\n const reference = yield* decode(BrowserSessionReference, {\n version: 1,\n sessionId,\n contextId: Redacted.make(page.browserContext().id ?? \"\"),\n targetId: Redacted.make(yield* targetId(page)),\n expiresAt,\n commandTimeoutMillis: options.commandTimeoutMillis ?? 30_000,\n });\n\n yield* Effect.uninterruptibleMask((restore) =>\n restore(retain(reference)).pipe(\n Effect.tap(() =>\n Effect.sync(() => {\n retained = true;\n }),\n ),\n ),\n );\n\n return { reference, page, ...connection };\n });\n\n const create = <E, R>(\n input: BrowserSessionOptions,\n retain: (reference: BrowserSessionReference) => Effect.Effect<void, E, R>,\n ) =>\n allocate(input, retain).pipe(\n Effect.map(({ reference }) => reference),\n Effect.scoped,\n Effect.timeoutOrElse({\n duration: \"30 seconds\",\n orElse: () => Effect.fail(failure(\"timeout\")),\n }),\n Effect.withTracerEnabled(false),\n );\n\n const makeSession = Effect.fnUntraced(function* (\n reference: BrowserSessionReference,\n browser: Browser,\n currentPage: Page,\n retire: Effect.Effect<void>,\n ) {\n const scope = yield* Effect.scope;\n const lock = yield* Semaphore.make(1);\n let invalid = false;\n\n const terminate = Effect.suspend(() => {\n invalid = true;\n\n return retire.pipe(\n Effect.catchCause((cause) => reportBrowserCause(\"session.disconnect\", cause)),\n Effect.andThen(cleanup(reference.sessionId)),\n );\n });\n\n const runEffect = <A, E, R>(\n action: (commandTimeoutMillis: number) => Effect.Effect<A, E, R>,\n ) =>\n lock\n .withPermitsIfAvailable(1)(\n Effect.gen(function* () {\n if (invalid || scope.state._tag === \"Closed\" || !browser.isConnected())\n return yield* failure(\"closed\");\n const remaining = reference.expiresAt - (yield* Clock.currentTimeMillis);\n\n if (remaining <= 0) {\n return yield* failure(\"expired\", \"not-dispatched\", yield* terminate);\n }\n\n return yield* action(Math.min(remaining, reference.commandTimeoutMillis)).pipe(\n Effect.catchDefect((defect) =>\n reportBrowserCause(\"session.command\", Cause.die(defect)).pipe(\n Effect.andThen(terminate),\n Effect.flatMap((closed) =>\n Effect.fail(failure(\"provider\", \"possibly-dispatched\", closed)),\n ),\n ),\n ),\n Effect.onInterrupt(() => terminate),\n );\n }),\n )\n .pipe(\n Effect.flatMap(Effect.fromOption(() => failure(\"busy\"))),\n Effect.withTracerEnabled(false),\n );\n\n const run = <A, E, R>(\n authorize: Effect.Effect<void, E, R>,\n action: (page: Page) => Promise<A>,\n terminateOnError = false,\n timeoutMillis?: number,\n ) =>\n runEffect((commandTimeoutMillis) =>\n authorize.pipe(\n Effect.andThen(() =>\n native(\"session.command\", () => action(currentPage)).pipe(\n Effect.catch((error) =>\n Effect.gen(function* () {\n const closed = terminateOnError ? yield* terminate : \"not-requested\";\n\n return yield* reportedBrowserError(\n failure(error.reason, \"possibly-dispatched\", closed),\n );\n }),\n ),\n ),\n ),\n Effect.timeoutOrElse({\n duration: Math.min(commandTimeoutMillis, timeoutMillis ?? commandTimeoutMillis),\n orElse: () =>\n terminate.pipe(\n Effect.flatMap((closed) =>\n Effect.fail(failure(\"timeout\", \"possibly-dispatched\", closed)),\n ),\n ),\n }),\n ),\n );\n\n const command = <A, E, R>(\n authorize: Effect.Effect<void, E, R>,\n method: string,\n parameters: Record<string, string | number>,\n schema: Schema.Codec<A>,\n ) =>\n run(\n authorize,\n async (page) => {\n const cdp = await page.createCDPSession();\n\n try {\n const result: unknown = await Reflect.apply(cdp.send, cdp, [method, parameters]);\n\n return Schema.decodeUnknownSync(schema)(result);\n } finally {\n await cdp.detach();\n }\n },\n method === \"Cloudflare.handoff\",\n );\n\n const session: BrowserSession = {\n reference,\n run: (authorize, action, options) =>\n options === undefined\n ? run(authorize, action)\n : decode(PositiveMillis, options.timeoutMillis).pipe(\n Effect.flatMap((timeoutMillis) => run(authorize, action, false, timeoutMillis)),\n ),\n fillCredential: (request) =>\n runEffect((commandTimeoutMillis) =>\n fillCredential(request).pipe(\n Effect.provideService(BrowserSessionPage, {\n page: currentPage,\n commandTimeoutMillis,\n }),\n Effect.catchIf(\n (error) => error.reason === \"timeout\" || error.dispatch === \"possibly-dispatched\",\n (error) =>\n terminate.pipe(\n Effect.flatMap((cleanup) =>\n Effect.fail(CredentialFillError.make({ ...error, cleanup })),\n ),\n ),\n ),\n ),\n ),\n handoff: (authorize, request) =>\n decode(BrowserRunHandoffRequest, request).pipe(\n Effect.flatMap((value) =>\n command(\n authorize,\n \"Cloudflare.handoff\",\n { instructions: value.instructions, timeout: value.timeout },\n Schema.Struct({\n handoffId: Schema.NonEmptyString.check(Schema.isMaxLength(1024)),\n }),\n ),\n ),\n Effect.map((value) =>\n BrowserRunHandoffResult.make({ handoffId: Redacted.make(value.handoffId) }),\n ),\n ),\n getLiveView: (authorize, request) =>\n decode(BrowserRunLiveViewRequest, request).pipe(\n Effect.flatMap((value) =>\n command(\n authorize,\n \"Cloudflare.getLiveView\",\n { mode: value.mode, expiresInMs: value.expiresInMs },\n Schema.Struct({ devtoolsFrontendUrl: Schema.String }),\n ),\n ),\n Effect.flatMap((value) =>\n decode(BrowserRunLiveViewResult, {\n devtoolsFrontendUrl: Redacted.make(value.devtoolsFrontendUrl),\n }),\n ),\n ),\n getReadOnlyLiveView: (authorize, request) =>\n decode(BrowserRunLiveViewRequest, request).pipe(\n Effect.flatMap((value) =>\n runEffect((commandTimeoutMillis) =>\n authorize.pipe(\n Effect.andThen(() =>\n readonlyLiveView.mint(reference.sessionId, reference.targetId, value).pipe(\n Effect.tapCause((cause) =>\n reportBrowserCause(\"session.readonlyLiveView\", cause),\n ),\n Effect.mapError(() => reportedBrowserError(failure(\"provider\"))),\n ),\n ),\n Effect.timeoutOrElse({\n duration: commandTimeoutMillis,\n orElse: () => Effect.fail(failure(\"timeout\")),\n }),\n ),\n ),\n ),\n ),\n getHandoffState: (authorize) =>\n command(\n authorize,\n \"Cloudflare.getHandoffState\",\n {},\n Schema.Struct({\n active: Schema.Boolean,\n handoffId: Schema.optionalKey(\n Schema.NonEmptyString.check(Schema.isMaxLength(1024)),\n ),\n durationMs: Schema.optionalKey(Schema.Natural),\n }),\n ).pipe(\n Effect.map((value) =>\n BrowserRunHandoffState.make({\n active: value.active,\n ...(value.handoffId === undefined\n ? {}\n : { handoffId: Redacted.make(value.handoffId) }),\n ...(value.durationMs === undefined ? {} : { durationMs: value.durationMs }),\n }),\n ),\n ),\n };\n\n return session;\n });\n\n const createAttached = Effect.fnUntraced(function* <E, R>(\n input: BrowserSessionOptions,\n retain: (reference: BrowserSessionReference) => Effect.Effect<void, E, R>,\n ) {\n const scope = yield* Scope.fork(yield* Effect.scope);\n\n return yield* allocate(input, retain).pipe(\n Effect.flatMap(({ reference, browser, page, retire }) =>\n makeSession(reference, browser, page, retire),\n ),\n Effect.provideService(Scope.Scope, scope),\n Effect.timeoutOrElse({\n duration: \"30 seconds\",\n orElse: () => Effect.fail(failure(\"timeout\")),\n }),\n Effect.onExit((exit) => (Exit.isFailure(exit) ? Scope.close(scope, exit) : Effect.void)),\n Effect.withTracerEnabled(false),\n );\n });\n\n const attachPage = Effect.fnUntraced(function* (input: BrowserSessionReference) {\n const reference = yield* decode(BrowserSessionReference, input);\n\n if (reference.expiresAt <= (yield* Clock.currentTimeMillis))\n return yield* failure(\"expired\");\n\n const { browser, retire } = yield* connect(reference.sessionId);\n\n const context = browser\n .browserContexts()\n .find((value) => value.id === Redacted.value(reference.contextId));\n\n if (context === undefined) return yield* failure(\"missing-page\");\n\n for (const page of yield* native(\"session.pages\", () => context.pages())) {\n if ((yield* targetId(page)) === Redacted.value(reference.targetId))\n return yield* makeSession(reference, browser, page, retire);\n }\n\n return yield* failure(\"missing-page\");\n });\n\n const attach = Effect.fnUntraced(function* (input: BrowserSessionReference) {\n const reference = yield* decode(BrowserSessionReference, input);\n const scope = yield* Scope.fork(yield* Effect.scope);\n\n return yield* attachPage(reference).pipe(\n Effect.provideService(Scope.Scope, scope),\n Effect.timeoutOrElse({\n duration: reference.commandTimeoutMillis,\n orElse: () =>\n reportBrowserCause(\"session.connect\", Cause.fail(failure(\"timeout\"))).pipe(\n Effect.andThen(Effect.fail(reportedBrowserError(failure(\"timeout\")))),\n ),\n }),\n Effect.onExit((exit) => (Exit.isFailure(exit) ? Scope.close(scope, exit) : Effect.void)),\n );\n });\n\n return BrowserSessions.of({\n create,\n createAttached,\n attach,\n close,\n keepAlive: (sessionId) =>\n decode(SessionId, sessionId).pipe(\n Effect.flatMap((id) =>\n binding.keepAlive(Redacted.value(id)).pipe(\n Effect.timeoutOrElse({\n duration: \"10 seconds\",\n orElse: () => Effect.fail(failure(\"timeout\")),\n }),\n Effect.catch((error) =>\n reportBrowserCause(\"session.keepAlive\", Cause.fail(error)).pipe(\n Effect.andThen(\n Effect.fail(\n reportedBrowserError(\n failure(error.reason === \"timeout\" ? \"timeout\" : \"provider\"),\n ),\n ),\n ),\n ),\n ),\n ),\n ),\n Effect.withTracerEnabled(false),\n ),\n });\n }),\n );\n\n static layer(options: BrowserSessionsOptions) {\n return this.layerNoDeps.pipe(\n Layer.provide(BrowserRunBinding.layer(options.browser)),\n Layer.provide(BrowserRunSessionLifecycle.layer(options)),\n Layer.provide(BrowserRunReadonlyLiveView.layer(options)),\n );\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { BrowserCredentialAccess, CredentialFillError, CredentialFillResult, FillCredentialRequest } from "./BrowserCredentials.mjs";
1
+ import { l as CredentialFillError, m as FillCredentialRequest, t as BrowserCredentialAccess, u as CredentialFillResult } from "./BrowserCredentials-C5IWfi7f.mjs";
2
2
  import { A as BrowserRunSessionLifecycle, O as BrowserRunCleanupError, _ as BrowserRunLiveViewRequest, i as BrowserRunHandoffState, k as BrowserRunLifecycleOptions, n as BrowserRunHandoffRequest, r as BrowserRunHandoffResult, v as BrowserRunLiveViewResult } from "./InteractiveBrowser-wV2Bti5e.mjs";
3
3
  import { Cause, Context, Effect, ErrorReporter, Layer, Redacted, Schema, Scope } from "effect";
4
4
  import { HttpClient } from "effect/http";
@@ -82,8 +82,11 @@ interface BrowserSession {
82
82
  * Check current authority under the lock before native dispatch. A settled SDK rejection leaves
83
83
  * the session available for inspection, but may have changed the website; never retry blindly.
84
84
  * Timeout/interruption fences outstanding SDK work and terminates the exact browser.
85
+ * An optional timeoutMillis narrows the command deadline, for example for bounded preparation.
85
86
  */
86
- readonly run: <A, E, R>(authorize: Effect.Effect<void, E, R>, action: (page: Page) => Promise<A>) => Effect.Effect<A, E | BrowserSessionError, R>;
87
+ readonly run: <A, E, R>(authorize: Effect.Effect<void, E, R>, action: (page: Page) => Promise<A>, options?: {
88
+ readonly timeoutMillis: number;
89
+ }) => Effect.Effect<A, E | BrowserSessionError, R>;
87
90
  /**
88
91
  * Resolves host-owned material under fresh credential grants. Never submits or retries a write.
89
92
  * Credential timeouts retain acknowledged writes and dispatch evidence alongside cleanup.
@@ -129,4 +132,4 @@ declare class BrowserSessions extends BrowserSessions_base {
129
132
  }
130
133
  //#endregion
131
134
  export { BrowserSession_d_exports as a, BrowserSessionReference as i, BrowserSessionError as n, BrowserSessions as o, BrowserSessionOptions as r, BrowserSessionsOptions as s, BrowserSession as t };
132
- //# sourceMappingURL=BrowserSession-B969Xg-2.d.mts.map
135
+ //# sourceMappingURL=BrowserSession-Bx0V1-6_.d.mts.map
@@ -1,3 +1,3 @@
1
1
  import { _ as BrowserRunLiveViewRequest, i as BrowserRunHandoffState, n as BrowserRunHandoffRequest, r as BrowserRunHandoffResult, v as BrowserRunLiveViewResult } from "./InteractiveBrowser-wV2Bti5e.mjs";
2
- import { i as BrowserSessionReference, n as BrowserSessionError, o as BrowserSessions, r as BrowserSessionOptions, s as BrowserSessionsOptions, t as BrowserSession } from "./BrowserSession-B969Xg-2.mjs";
2
+ import { i as BrowserSessionReference, n as BrowserSessionError, o as BrowserSessions, r as BrowserSessionOptions, s as BrowserSessionsOptions, t as BrowserSession } from "./BrowserSession-Bx0V1-6_.mjs";
3
3
  export { BrowserRunHandoffRequest, BrowserRunHandoffResult, BrowserRunHandoffState, BrowserRunLiveViewRequest, BrowserRunLiveViewResult, BrowserSession, BrowserSessionError, BrowserSessionOptions, BrowserSessionReference, BrowserSessions, BrowserSessionsOptions };
@@ -1,4 +1,4 @@
1
1
  import "./BrowserCredentials.mjs";
2
- import { c as BrowserRunLiveViewResult, n as BrowserRunHandoffResult, r as BrowserRunHandoffState, s as BrowserRunLiveViewRequest, t as BrowserRunHandoffRequest } from "./InteractiveBrowser-BbG3kGA9.mjs";
3
- import { a as BrowserSessions, n as BrowserSessionOptions, r as BrowserSessionReference, t as BrowserSessionError } from "./BrowserSession-RfIzxGCH.mjs";
2
+ import { c as BrowserRunLiveViewResult, n as BrowserRunHandoffResult, r as BrowserRunHandoffState, s as BrowserRunLiveViewRequest, t as BrowserRunHandoffRequest } from "./InteractiveBrowser-LdKzQeLR.mjs";
3
+ import { a as BrowserSessions, n as BrowserSessionOptions, r as BrowserSessionReference, t as BrowserSessionError } from "./BrowserSession-BfNmyayH.mjs";
4
4
  export { BrowserRunHandoffRequest, BrowserRunHandoffResult, BrowserRunHandoffState, BrowserRunLiveViewRequest, BrowserRunLiveViewResult, BrowserSessionError, BrowserSessionOptions, BrowserSessionReference, BrowserSessions };