@effect-agent/platform-cloudflare 0.1.0-beta.13 → 0.1.0-beta.131
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Alarm.d.mts +244 -0
- package/dist/Alarm.mjs +947 -0
- package/dist/Alarm.mjs.map +1 -0
- package/dist/BrowserCredentials.d.mts +91 -0
- package/dist/BrowserCredentials.mjs +120 -0
- package/dist/BrowserCredentials.mjs.map +1 -0
- package/dist/BrowserRestCapture.d.mts +34 -0
- package/dist/BrowserRestCapture.mjs +238 -0
- package/dist/BrowserRestCapture.mjs.map +1 -0
- package/dist/BrowserRestCrawl.d.mts +16 -0
- package/dist/BrowserRestCrawl.mjs +244 -0
- package/dist/BrowserRestCrawl.mjs.map +1 -0
- package/dist/BrowserSession-DP6b-cpL.d.mts +125 -0
- package/dist/BrowserSession-DWoRC_iM.mjs +505 -0
- package/dist/BrowserSession-DWoRC_iM.mjs.map +1 -0
- package/dist/BrowserSession.d.mts +3 -0
- package/dist/BrowserSession.mjs +4 -0
- package/dist/CloudflareAiGateway.d.mts +64 -0
- package/dist/CloudflareAiGateway.mjs +70 -0
- package/dist/CloudflareAiGateway.mjs.map +1 -0
- package/dist/CloudflareBindings.d.mts +115 -0
- package/dist/CloudflareBindings.mjs +113 -0
- package/dist/CloudflareBindings.mjs.map +1 -0
- package/dist/CloudflareBrowser-DV6kya1H.mjs +495 -0
- package/dist/CloudflareBrowser-DV6kya1H.mjs.map +1 -0
- package/dist/CloudflareBrowser-Doe1M7R5.d.mts +80 -0
- package/dist/CloudflareBrowser.d.mts +2 -0
- package/dist/CloudflareBrowser.mjs +2 -0
- package/dist/CloudflareCodeMode.d.mts +44 -0
- package/dist/CloudflareCodeMode.mjs +616 -0
- package/dist/CloudflareCodeMode.mjs.map +1 -0
- package/dist/CloudflareConfig-DKXGo8L3.d.mts +106 -0
- package/dist/CloudflareConfig.d.mts +2 -0
- package/dist/CloudflareConfig.mjs +128 -0
- package/dist/CloudflareConfig.mjs.map +1 -0
- package/dist/CloudflareMemory.d.mts +142 -0
- package/dist/CloudflareMemory.mjs +202 -0
- package/dist/CloudflareMemory.mjs.map +1 -0
- package/dist/CloudflareScheduling.d.mts +52 -0
- package/dist/CloudflareScheduling.mjs +396 -0
- package/dist/CloudflareScheduling.mjs.map +1 -0
- package/dist/CloudflareSubscriptions.d.mts +87 -0
- package/dist/CloudflareSubscriptions.mjs +530 -0
- package/dist/CloudflareSubscriptions.mjs.map +1 -0
- package/dist/CloudflareThreadClient.d.mts +1752 -0
- package/dist/CloudflareThreadClient.mjs +382 -0
- package/dist/CloudflareThreadClient.mjs.map +1 -0
- package/dist/InteractiveBrowser-BnqY_Y-F.d.mts +228 -0
- package/dist/InteractiveBrowser-CxFT-Nwm.mjs +1923 -0
- package/dist/InteractiveBrowser-CxFT-Nwm.mjs.map +1 -0
- package/dist/InteractiveBrowser.d.mts +2 -0
- package/dist/InteractiveBrowser.mjs +2 -0
- package/dist/ThreadObject-CVhZC-7l.mjs +849 -0
- package/dist/ThreadObject-CVhZC-7l.mjs.map +1 -0
- package/dist/ThreadObject-D8GzJxJB.d.mts +839 -0
- package/dist/ThreadObject.d.mts +2 -0
- package/dist/ThreadObject.mjs +3 -0
- package/dist/WakeScheduler.d.mts +23 -0
- package/dist/WakeScheduler.mjs +57 -0
- package/dist/WakeScheduler.mjs.map +1 -0
- package/dist/boundary-BguazVkh.mjs +42 -0
- package/dist/boundary-BguazVkh.mjs.map +1 -0
- package/dist/index.d.mts +15 -1550
- package/dist/index.mjs +15 -1716
- package/dist/prepared-admission-DU0_T-ev.mjs +73 -0
- package/dist/prepared-admission-DU0_T-ev.mjs.map +1 -0
- package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
- package/package.json +1 -56
- package/src/Alarm.ts +1979 -0
- package/src/BrowserCredentials.ts +146 -0
- package/src/BrowserRestCapture.ts +477 -0
- package/src/BrowserRestCrawl.ts +540 -0
- package/src/BrowserSession.ts +624 -0
- package/src/CloudflareAiGateway.ts +170 -0
- package/src/CloudflareBindings.ts +199 -0
- package/src/CloudflareBrowser.ts +15 -0
- package/src/{code-mode-executor.ts → CloudflareCodeMode.ts} +308 -283
- package/src/{config.ts → CloudflareConfig.ts} +19 -12
- package/src/CloudflareMemory.ts +420 -0
- package/src/CloudflareScheduling.ts +747 -0
- package/src/CloudflareSubscriptions.ts +1041 -0
- package/src/CloudflareThreadClient.ts +809 -0
- package/src/InteractiveBrowser.ts +3246 -0
- package/src/ThreadObject.ts +1190 -0
- package/src/{wake-scheduler.ts → WakeScheduler.ts} +32 -26
- package/src/index.ts +14 -23
- package/src/internal/boundary.ts +55 -0
- package/src/internal/browser-binding.ts +322 -0
- package/src/internal/browser-credentials.ts +362 -0
- package/src/internal/browser-failure.ts +92 -0
- package/src/internal/browser-file-selection.ts +126 -0
- package/src/internal/browser-quick-action.ts +857 -0
- package/src/internal/browser-readonly-live-view.ts +111 -0
- package/src/internal/browser-session-lifecycle.ts +193 -0
- package/src/internal/layers.ts +773 -0
- package/src/internal/message-delivery.ts +131 -0
- package/src/internal/prepared-admission.ts +116 -0
- package/src/internal/progress-wait.ts +121 -0
- package/src/internal/transport.ts +44 -0
- package/dist/index.mjs.map +0 -1
- package/src/alarm.ts +0 -334
- package/src/bindings.ts +0 -145
- package/src/client.ts +0 -646
- package/src/conversation-object.ts +0 -768
- package/src/layers.ts +0 -376
- package/src/transport.ts +0 -38
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BrowserSession-DWoRC_iM.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/unstable/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 { 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 */\n readonly run: <A, E, R>(\n authorize: Effect.Effect<void, E, R>,\n action: (page: Page) => Promise<A>,\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 /** 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 create = <E, R>(\n input: BrowserSessionOptions,\n retain: (reference: BrowserSessionReference) => Effect.Effect<void, E, R>,\n ) =>\n Effect.gen(function* () {\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 { browser } = yield* connect(sessionId);\n\n const page = yield* native(\"session.page\", async () => {\n const context = await 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;\n }).pipe(\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 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 const scope = yield* Effect.scope;\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 let page: Page | undefined;\n\n for (const candidate of yield* native(\"session.pages\", () => context.pages())) {\n if ((yield* targetId(candidate)) === Redacted.value(reference.targetId)) {\n page = candidate;\n break;\n }\n }\n if (page === undefined) return yield* failure(\"missing-page\");\n const currentPage = page;\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 ) =>\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: 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,\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 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 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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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { _ as BrowserRunLiveViewRequest, i as BrowserRunHandoffState, n as BrowserRunHandoffRequest, r as BrowserRunHandoffResult, v as BrowserRunLiveViewResult } from "./InteractiveBrowser-BnqY_Y-F.mjs";
|
|
2
|
+
import { i as BrowserSessionReference, n as BrowserSessionError, o as BrowserSessions, r as BrowserSessionOptions, s as BrowserSessionsOptions, t as BrowserSession } from "./BrowserSession-DP6b-cpL.mjs";
|
|
3
|
+
export { BrowserRunHandoffRequest, BrowserRunHandoffResult, BrowserRunHandoffState, BrowserRunLiveViewRequest, BrowserRunLiveViewResult, BrowserSession, BrowserSessionError, BrowserSessionOptions, BrowserSessionReference, BrowserSessions, BrowserSessionsOptions };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import "./BrowserCredentials.mjs";
|
|
2
|
+
import { c as BrowserRunLiveViewResult, n as BrowserRunHandoffResult, r as BrowserRunHandoffState, s as BrowserRunLiveViewRequest, t as BrowserRunHandoffRequest } from "./InteractiveBrowser-CxFT-Nwm.mjs";
|
|
3
|
+
import { a as BrowserSessions, n as BrowserSessionOptions, r as BrowserSessionReference, t as BrowserSessionError } from "./BrowserSession-DWoRC_iM.mjs";
|
|
4
|
+
export { BrowserRunHandoffRequest, BrowserRunHandoffResult, BrowserRunHandoffState, BrowserRunLiveViewRequest, BrowserRunLiveViewResult, BrowserSessionError, BrowserSessionOptions, BrowserSessionReference, BrowserSessions };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Layer, Redacted } from "effect";
|
|
2
|
+
import { HttpClient } from "effect/unstable/http";
|
|
3
|
+
declare namespace CloudflareAiGateway_d_exports {
|
|
4
|
+
export { ClientOptions, ProviderOptions, RestOptions, RouteOptions, provide, provider, rest };
|
|
5
|
+
}
|
|
6
|
+
/** Options understood by upstream Effect AI clients; no model or provider wrapper is created. */
|
|
7
|
+
export interface ClientOptions {
|
|
8
|
+
readonly apiUrl: string;
|
|
9
|
+
readonly transformClient: (client: HttpClient.HttpClient) => HttpClient.HttpClient;
|
|
10
|
+
}
|
|
11
|
+
export interface ProviderOptions {
|
|
12
|
+
readonly accountId: string;
|
|
13
|
+
readonly gatewayId: string;
|
|
14
|
+
/** Cloudflare's provider path, such as openai, anthropic, google-ai-studio, or perplexity-ai. */
|
|
15
|
+
readonly provider: string;
|
|
16
|
+
/** Omit only for an unauthenticated gateway with a separately supplied provider key. */
|
|
17
|
+
readonly apiToken?: Redacted.Redacted<string>;
|
|
18
|
+
}
|
|
19
|
+
export interface RestOptions {
|
|
20
|
+
readonly accountId: string;
|
|
21
|
+
readonly gatewayId: string;
|
|
22
|
+
/** Cloudflare API token with Workers AI Read permission. */
|
|
23
|
+
readonly apiToken: Redacted.Redacted<string>;
|
|
24
|
+
/** Matches the paths appended by the upstream Effect client. */
|
|
25
|
+
readonly protocol: "responses" | "chat-completions" | "messages";
|
|
26
|
+
}
|
|
27
|
+
/** Choose exactly one route: a native provider path or an account REST protocol. */
|
|
28
|
+
export type RouteOptions = (ProviderOptions & {
|
|
29
|
+
readonly protocol?: never;
|
|
30
|
+
}) | (RestOptions & {
|
|
31
|
+
readonly provider?: never;
|
|
32
|
+
});
|
|
33
|
+
/**
|
|
34
|
+
* Provider-native proxy for model calls, streaming, embeddings, and hosted tools supported
|
|
35
|
+
* by that provider. Pass the result to the upstream client's layer along with its apiKey
|
|
36
|
+
* for BYOK-in-request, or omit apiKey for Gateway stored keys / Unified Billing.
|
|
37
|
+
* Provider model names and request bodies pass through unchanged. This module is Node-safe.
|
|
38
|
+
* Custom transforms and redirect policies must retain this endpoint and credential boundary.
|
|
39
|
+
*/
|
|
40
|
+
export declare const provider: (options: ProviderOptions) => ClientOptions;
|
|
41
|
+
/**
|
|
42
|
+
* Cloudflare's account REST API (not the deprecated /compat API). Use provider-qualified
|
|
43
|
+
* model names, e.g. openai/gpt-4.1 or anthropic/claude-haiku-4.5, and omit provider apiKey.
|
|
44
|
+
* OpenAI clients append /responses or /chat/completions; Anthropic appends /v1/messages.
|
|
45
|
+
* Compatibility remains the responsibility of the selected upstream client and model.
|
|
46
|
+
*/
|
|
47
|
+
export declare const rest: (options: RestOptions) => ClientOptions;
|
|
48
|
+
/**
|
|
49
|
+
* Provide a Gateway-configured upstream client directly in a Layer pipeline.
|
|
50
|
+
* Pass the client's `layer` factory, or a callback adding client-specific options.
|
|
51
|
+
* The factory's errors and remaining services (such as HttpClient) stay visible.
|
|
52
|
+
* Model selection and resource ownership remain with the supplied upstream Layers.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* AnthropicLanguageModel.model("claude-haiku-4-5").pipe(
|
|
57
|
+
* Gateway.provide(AnthropicClient.layer, { ...options, provider: "anthropic" }),
|
|
58
|
+
* )
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export declare const provide: <Client, E, R>(clientLayer: (options: ClientOptions) => Layer.Layer<Client, E, R>, options: RouteOptions) => <RIn2, E2, ROut2>(self: Layer.Layer<ROut2, E2, RIn2>) => Layer.Layer<ROut2, E | E2, R | Exclude<RIn2, Client>>;
|
|
62
|
+
//#endregion
|
|
63
|
+
export { CloudflareAiGateway_d_exports as t };
|
|
64
|
+
//# sourceMappingURL=CloudflareAiGateway.d.mts.map
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
|
+
import { Context, Effect, Layer, Option, Redactable, Redacted, Schema } from "effect";
|
|
3
|
+
import { FetchHttpClient, Headers, HttpClient, HttpClientError, HttpClientRequest } from "effect/unstable/http";
|
|
4
|
+
//#region src/CloudflareAiGateway.ts
|
|
5
|
+
var CloudflareAiGateway_exports = /* @__PURE__ */ __exportAll({
|
|
6
|
+
provide: () => provide,
|
|
7
|
+
provider: () => provider,
|
|
8
|
+
rest: () => rest
|
|
9
|
+
});
|
|
10
|
+
const Segment = Schema.NonEmptyString.check(Schema.isMaxLength(256), Schema.isPattern(/^[a-zA-Z0-9_-]+$/));
|
|
11
|
+
const decodeSegment = Schema.decodeUnknownSync(Segment);
|
|
12
|
+
const redactGatewayToken = (headers, tokenHeader) => {
|
|
13
|
+
Object.defineProperty(headers, Redactable.symbolRedactable, {
|
|
14
|
+
configurable: true,
|
|
15
|
+
value: (context) => Headers.redact(headers, [...Context.get(context, Headers.CurrentRedactedNames), tokenHeader])
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
const clientOptions = (apiUrl, tokenHeader, apiToken, gatewayId) => Object.freeze({
|
|
19
|
+
apiUrl,
|
|
20
|
+
transformClient: (client) => client.pipe(HttpClient.mapRequestEffect((request) => {
|
|
21
|
+
const url = URL.parse(request.url);
|
|
22
|
+
if (url === null || url.username !== "" || url.password !== "" || !(url.href === apiUrl || url.href.startsWith(`${apiUrl}/`))) return Effect.fail(new HttpClientError.HttpClientError({ reason: new HttpClientError.InvalidUrlError({
|
|
23
|
+
request,
|
|
24
|
+
description: "Request is outside the configured Cloudflare AI Gateway endpoint"
|
|
25
|
+
}) }));
|
|
26
|
+
let prepared = request;
|
|
27
|
+
if (apiToken !== void 0) prepared = HttpClientRequest.setHeader(prepared, tokenHeader, `Bearer ${Redacted.value(apiToken)}`);
|
|
28
|
+
if (gatewayId !== void 0) prepared = HttpClientRequest.setHeader(prepared, "cf-aig-gateway-id", gatewayId);
|
|
29
|
+
return Effect.succeed(prepared);
|
|
30
|
+
}), HttpClient.transformResponse((effect) => Effect.gen(function* () {
|
|
31
|
+
const defaults = yield* Effect.serviceOption(FetchHttpClient.RequestInit);
|
|
32
|
+
return yield* effect.pipe(Effect.provideService(FetchHttpClient.RequestInit, {
|
|
33
|
+
...Option.getOrElse(defaults, () => ({})),
|
|
34
|
+
redirect: "error"
|
|
35
|
+
}));
|
|
36
|
+
})), HttpClient.transformResponse((effect) => effect.pipe(Effect.tap((response) => Effect.sync(() => redactGatewayToken(response.request.headers, tokenHeader))), Effect.tapError((error) => Effect.sync(() => redactGatewayToken(error.reason.request.headers, tokenHeader))), Effect.updateService(Headers.CurrentRedactedNames, (names) => [...names, tokenHeader]))))
|
|
37
|
+
});
|
|
38
|
+
/**
|
|
39
|
+
* Provider-native proxy for model calls, streaming, embeddings, and hosted tools supported
|
|
40
|
+
* by that provider. Pass the result to the upstream client's layer along with its apiKey
|
|
41
|
+
* for BYOK-in-request, or omit apiKey for Gateway stored keys / Unified Billing.
|
|
42
|
+
* Provider model names and request bodies pass through unchanged. This module is Node-safe.
|
|
43
|
+
* Custom transforms and redirect policies must retain this endpoint and credential boundary.
|
|
44
|
+
*/
|
|
45
|
+
const provider = (options) => clientOptions(`https://gateway.ai.cloudflare.com/v1/${decodeSegment(options.accountId)}/${decodeSegment(options.gatewayId)}/${decodeSegment(options.provider)}`, "cf-aig-authorization", options.apiToken);
|
|
46
|
+
/**
|
|
47
|
+
* Cloudflare's account REST API (not the deprecated /compat API). Use provider-qualified
|
|
48
|
+
* model names, e.g. openai/gpt-4.1 or anthropic/claude-haiku-4.5, and omit provider apiKey.
|
|
49
|
+
* OpenAI clients append /responses or /chat/completions; Anthropic appends /v1/messages.
|
|
50
|
+
* Compatibility remains the responsibility of the selected upstream client and model.
|
|
51
|
+
*/
|
|
52
|
+
const rest = (options) => clientOptions(`https://api.cloudflare.com/client/v4/accounts/${decodeSegment(options.accountId)}/ai${options.protocol === "messages" ? "" : "/v1"}`, "authorization", options.apiToken, decodeSegment(options.gatewayId));
|
|
53
|
+
/**
|
|
54
|
+
* Provide a Gateway-configured upstream client directly in a Layer pipeline.
|
|
55
|
+
* Pass the client's `layer` factory, or a callback adding client-specific options.
|
|
56
|
+
* The factory's errors and remaining services (such as HttpClient) stay visible.
|
|
57
|
+
* Model selection and resource ownership remain with the supplied upstream Layers.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* AnthropicLanguageModel.model("claude-haiku-4-5").pipe(
|
|
62
|
+
* Gateway.provide(AnthropicClient.layer, { ...options, provider: "anthropic" }),
|
|
63
|
+
* )
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
const provide = (clientLayer, options) => Layer.provide(clientLayer(options.provider !== void 0 ? provider(options) : rest(options)));
|
|
67
|
+
//#endregion
|
|
68
|
+
export { provide, provider, rest, CloudflareAiGateway_exports as t };
|
|
69
|
+
|
|
70
|
+
//# sourceMappingURL=CloudflareAiGateway.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CloudflareAiGateway.mjs","names":[],"sources":["../src/CloudflareAiGateway.ts"],"sourcesContent":["import { Context, Effect, Layer, Option, Redactable, Redacted, Schema } from \"effect\";\nimport {\n FetchHttpClient,\n Headers,\n HttpClient,\n HttpClientError,\n HttpClientRequest,\n} from \"effect/unstable/http\";\n\nconst Segment = Schema.NonEmptyString.check(\n Schema.isMaxLength(256),\n Schema.isPattern(/^[a-zA-Z0-9_-]+$/),\n);\n\nconst decodeSegment = Schema.decodeUnknownSync(Segment);\n\n/** Options understood by upstream Effect AI clients; no model or provider wrapper is created. */\nexport interface ClientOptions {\n readonly apiUrl: string;\n readonly transformClient: (client: HttpClient.HttpClient) => HttpClient.HttpClient;\n}\n\nexport interface ProviderOptions {\n readonly accountId: string;\n readonly gatewayId: string;\n /** Cloudflare's provider path, such as openai, anthropic, google-ai-studio, or perplexity-ai. */\n readonly provider: string;\n /** Omit only for an unauthenticated gateway with a separately supplied provider key. */\n readonly apiToken?: Redacted.Redacted<string>;\n}\n\nexport interface RestOptions {\n readonly accountId: string;\n readonly gatewayId: string;\n /** Cloudflare API token with Workers AI Read permission. */\n readonly apiToken: Redacted.Redacted<string>;\n /** Matches the paths appended by the upstream Effect client. */\n readonly protocol: \"responses\" | \"chat-completions\" | \"messages\";\n}\n\n/** Choose exactly one route: a native provider path or an account REST protocol. */\nexport type RouteOptions =\n | (ProviderOptions & { readonly protocol?: never })\n | (RestOptions & { readonly provider?: never });\n\nconst redactGatewayToken = (headers: Headers.Headers, tokenHeader: string): void => {\n // HTTP tracing can copy headers after preprocessing. Attach the public redaction\n // protocol to the final request as well, before a provider builds error details.\n Object.defineProperty(headers, Redactable.symbolRedactable, {\n configurable: true,\n value: (context: Context.Context<never>) =>\n Headers.redact(headers, [...Context.get(context, Headers.CurrentRedactedNames), tokenHeader]),\n });\n};\n\nconst clientOptions = (\n apiUrl: string,\n tokenHeader: \"authorization\" | \"cf-aig-authorization\",\n apiToken: Redacted.Redacted<string> | undefined,\n gatewayId?: string,\n): ClientOptions =>\n Object.freeze({\n apiUrl,\n transformClient: (client: HttpClient.HttpClient) =>\n client.pipe(\n HttpClient.mapRequestEffect((request) => {\n const url = URL.parse(request.url);\n\n // Check the normalized URL too: dot segments must not escape this account or gateway.\n if (\n url === null ||\n url.username !== \"\" ||\n url.password !== \"\" ||\n !(url.href === apiUrl || url.href.startsWith(`${apiUrl}/`))\n ) {\n return Effect.fail(\n new HttpClientError.HttpClientError({\n reason: new HttpClientError.InvalidUrlError({\n request,\n description: \"Request is outside the configured Cloudflare AI Gateway endpoint\",\n }),\n }),\n );\n }\n let prepared = request;\n\n if (apiToken !== undefined) {\n prepared = HttpClientRequest.setHeader(\n prepared,\n tokenHeader,\n `Bearer ${Redacted.value(apiToken)}`,\n );\n }\n if (gatewayId !== undefined) {\n prepared = HttpClientRequest.setHeader(prepared, \"cf-aig-gateway-id\", gatewayId);\n }\n\n return Effect.succeed(prepared);\n }),\n HttpClient.transformResponse((effect) =>\n Effect.gen(function* () {\n const defaults = yield* Effect.serviceOption(FetchHttpClient.RequestInit);\n\n return yield* effect.pipe(\n Effect.provideService(FetchHttpClient.RequestInit, {\n ...Option.getOrElse(defaults, () => ({})),\n redirect: \"error\",\n }),\n );\n }),\n ),\n HttpClient.transformResponse((effect) =>\n effect.pipe(\n Effect.tap((response) =>\n Effect.sync(() => redactGatewayToken(response.request.headers, tokenHeader)),\n ),\n Effect.tapError((error) =>\n Effect.sync(() => redactGatewayToken(error.reason.request.headers, tokenHeader)),\n ),\n Effect.updateService(Headers.CurrentRedactedNames, (names) => [...names, tokenHeader]),\n ),\n ),\n ),\n });\n\n/**\n * Provider-native proxy for model calls, streaming, embeddings, and hosted tools supported\n * by that provider. Pass the result to the upstream client's layer along with its apiKey\n * for BYOK-in-request, or omit apiKey for Gateway stored keys / Unified Billing.\n * Provider model names and request bodies pass through unchanged. This module is Node-safe.\n * Custom transforms and redirect policies must retain this endpoint and credential boundary.\n */\nexport const provider = (options: ProviderOptions): ClientOptions =>\n clientOptions(\n `https://gateway.ai.cloudflare.com/v1/${decodeSegment(options.accountId)}/${decodeSegment(options.gatewayId)}/${decodeSegment(options.provider)}`,\n \"cf-aig-authorization\",\n options.apiToken,\n );\n\n/**\n * Cloudflare's account REST API (not the deprecated /compat API). Use provider-qualified\n * model names, e.g. openai/gpt-4.1 or anthropic/claude-haiku-4.5, and omit provider apiKey.\n * OpenAI clients append /responses or /chat/completions; Anthropic appends /v1/messages.\n * Compatibility remains the responsibility of the selected upstream client and model.\n */\nexport const rest = (options: RestOptions): ClientOptions =>\n clientOptions(\n `https://api.cloudflare.com/client/v4/accounts/${decodeSegment(options.accountId)}/ai${options.protocol === \"messages\" ? \"\" : \"/v1\"}`,\n \"authorization\",\n options.apiToken,\n decodeSegment(options.gatewayId),\n );\n\n/**\n * Provide a Gateway-configured upstream client directly in a Layer pipeline.\n * Pass the client's `layer` factory, or a callback adding client-specific options.\n * The factory's errors and remaining services (such as HttpClient) stay visible.\n * Model selection and resource ownership remain with the supplied upstream Layers.\n *\n * @example\n * ```ts\n * AnthropicLanguageModel.model(\"claude-haiku-4-5\").pipe(\n * Gateway.provide(AnthropicClient.layer, { ...options, provider: \"anthropic\" }),\n * )\n * ```\n */\nexport const provide = <Client, E, R>(\n clientLayer: (options: ClientOptions) => Layer.Layer<Client, E, R>,\n options: RouteOptions,\n) => Layer.provide(clientLayer(options.provider !== undefined ? provider(options) : rest(options)));\n"],"mappings":";;;;;;;;;AASA,MAAM,UAAU,OAAO,eAAe,MACpC,OAAO,YAAY,GAAG,GACtB,OAAO,UAAU,kBAAkB,CACrC;AAEA,MAAM,gBAAgB,OAAO,kBAAkB,OAAO;AA+BtD,MAAM,sBAAsB,SAA0B,gBAA8B;CAGlF,OAAO,eAAe,SAAS,WAAW,kBAAkB;EAC1D,cAAc;EACd,QAAQ,YACN,QAAQ,OAAO,SAAS,CAAC,GAAG,QAAQ,IAAI,SAAS,QAAQ,oBAAoB,GAAG,WAAW,CAAC;CAChG,CAAC;AACH;AAEA,MAAM,iBACJ,QACA,aACA,UACA,cAEA,OAAO,OAAO;CACZ;CACA,kBAAkB,WAChB,OAAO,KACL,WAAW,kBAAkB,YAAY;EACvC,MAAM,MAAM,IAAI,MAAM,QAAQ,GAAG;EAGjC,IACE,QAAQ,QACR,IAAI,aAAa,MACjB,IAAI,aAAa,MACjB,EAAE,IAAI,SAAS,UAAU,IAAI,KAAK,WAAW,GAAG,OAAO,EAAE,IAEzD,OAAO,OAAO,KACZ,IAAI,gBAAgB,gBAAgB,EAClC,QAAQ,IAAI,gBAAgB,gBAAgB;GAC1C;GACA,aAAa;EACf,CAAC,EACH,CAAC,CACH;EAEF,IAAI,WAAW;EAEf,IAAI,aAAa,KAAA,GACf,WAAW,kBAAkB,UAC3B,UACA,aACA,UAAU,SAAS,MAAM,QAAQ,GACnC;EAEF,IAAI,cAAc,KAAA,GAChB,WAAW,kBAAkB,UAAU,UAAU,qBAAqB,SAAS;EAGjF,OAAO,OAAO,QAAQ,QAAQ;CAChC,CAAC,GACD,WAAW,mBAAmB,WAC5B,OAAO,IAAI,aAAa;EACtB,MAAM,WAAW,OAAO,OAAO,cAAc,gBAAgB,WAAW;EAExE,OAAO,OAAO,OAAO,KACnB,OAAO,eAAe,gBAAgB,aAAa;GACjD,GAAG,OAAO,UAAU,iBAAiB,CAAC,EAAE;GACxC,UAAU;EACZ,CAAC,CACH;CACF,CAAC,CACH,GACA,WAAW,mBAAmB,WAC5B,OAAO,KACL,OAAO,KAAK,aACV,OAAO,WAAW,mBAAmB,SAAS,QAAQ,SAAS,WAAW,CAAC,CAC7E,GACA,OAAO,UAAU,UACf,OAAO,WAAW,mBAAmB,MAAM,OAAO,QAAQ,SAAS,WAAW,CAAC,CACjF,GACA,OAAO,cAAc,QAAQ,uBAAuB,UAAU,CAAC,GAAG,OAAO,WAAW,CAAC,CACvF,CACF,CACF;AACJ,CAAC;;;;;;;;AASH,MAAa,YAAY,YACvB,cACE,wCAAwC,cAAc,QAAQ,SAAS,EAAE,GAAG,cAAc,QAAQ,SAAS,EAAE,GAAG,cAAc,QAAQ,QAAQ,KAC9I,wBACA,QAAQ,QACV;;;;;;;AAQF,MAAa,QAAQ,YACnB,cACE,iDAAiD,cAAc,QAAQ,SAAS,EAAE,KAAK,QAAQ,aAAa,aAAa,KAAK,SAC9H,iBACA,QAAQ,UACR,cAAc,QAAQ,SAAS,CACjC;;;;;;;;;;;;;;AAeF,MAAa,WACX,aACA,YACG,MAAM,QAAQ,YAAY,QAAQ,aAAa,KAAA,IAAY,SAAS,OAAO,IAAI,KAAK,OAAO,CAAC,CAAC"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Context, Effect, Layer, Schema } from "effect";
|
|
2
|
+
import { ThreadId } from "effect-agent/identifiers";
|
|
3
|
+
import { ProducerId } from "effect-agent/records";
|
|
4
|
+
declare namespace CloudflareBindings_d_exports {
|
|
5
|
+
export { CloudflareBindingError, DurableObjectContext, ThreadObjectClient, ThreadObjectIdentity, ThreadObjectNamespace, ThreadObjectPlacement, ThreadObjectRpc, callThreadObject, threadNamespaceFromEnv, threadNamespaceLayer };
|
|
6
|
+
}
|
|
7
|
+
declare const CloudflareBindingError_base: Schema.Class<CloudflareBindingError, Schema.TaggedStruct<"CloudflareBindingError", {
|
|
8
|
+
readonly binding: Schema.String;
|
|
9
|
+
readonly message: Schema.String;
|
|
10
|
+
}>, import("effect/Cause").YieldableError>;
|
|
11
|
+
/**
|
|
12
|
+
* Cloudflare platform bindings as Effect services (DEPLOY-010: "Cloudflare platform bindings
|
|
13
|
+
* are supplied as Effect services/Layers"). Application code never reads `env` or touches a
|
|
14
|
+
* `DurableObjectState` directly — the Thread Object class constructs these Layers once
|
|
15
|
+
* per incarnation and everything downstream consumes the services.
|
|
16
|
+
*/
|
|
17
|
+
/** A Cloudflare platform binding was missing or carried the wrong shape (DEPLOY-003/010). */
|
|
18
|
+
export declare class CloudflareBindingError extends CloudflareBindingError_base {}
|
|
19
|
+
/**
|
|
20
|
+
* The RPC surface one Thread Durable Object exposes to Workers and to sibling
|
|
21
|
+
* Thread Objects. `ThreadObject.make` implements it; the Worker-side client
|
|
22
|
+
* and the cross-Object transport call it through `DurableObjectNamespace` stubs. Every
|
|
23
|
+
* `encoded` value is a Schema-encoded envelope (`client.ts` wire schemas for host entry
|
|
24
|
+
* points, `@effect-agent/storage-cloudflare` port envelopes for `portCall`), so the RPC
|
|
25
|
+
* boundary carries only structured-cloneable JSON. The optional trailing trace context is
|
|
26
|
+
* transient native RPC metadata, stripped by an opted-in effect-cf receiver before decoding
|
|
27
|
+
* the host envelope. It never enters durable state.
|
|
28
|
+
*/
|
|
29
|
+
export interface ThreadObjectRpc extends Rpc.DurableObjectBranded {
|
|
30
|
+
/** Admission-limits gate + `DurableAgentRuntime.submit`; answers a `SubmitResponse`. */
|
|
31
|
+
submitEncoded(encoded: unknown, traceContext?: unknown): Promise<unknown>;
|
|
32
|
+
/** Wake-hinted, poll-guaranteed settlement wait; answers an `AwaitSettlementResponse`. */
|
|
33
|
+
submissionStatusEncoded(encoded: unknown, traceContext?: unknown): Promise<unknown>;
|
|
34
|
+
awaitSettlementEncoded(encoded: unknown, traceContext?: unknown): Promise<unknown>;
|
|
35
|
+
/** Event-driven durable progress wait; answers a `ProgressObserved` host response. */
|
|
36
|
+
awaitProgressEncoded(encoded: unknown, traceContext?: unknown): Promise<unknown>;
|
|
37
|
+
/** Best-effort cancellation for one in-flight progress wait. */
|
|
38
|
+
cancelProgressEncoded(encoded: unknown, traceContext?: unknown): Promise<unknown>;
|
|
39
|
+
/** One bounded page of canonical records; answers an `ObservePageResponse`. */
|
|
40
|
+
observePage(encoded: unknown, traceContext?: unknown): Promise<unknown>;
|
|
41
|
+
/** Durable abort intent; answers an `AbortResponse`. */
|
|
42
|
+
abortEncoded(encoded: unknown, traceContext?: unknown): Promise<unknown>;
|
|
43
|
+
/** Durable approval decision (plan §2.6); answers a `ResolveApprovalResponse`. */
|
|
44
|
+
resolveApprovalEncoded(encoded: unknown, traceContext?: unknown): Promise<unknown>;
|
|
45
|
+
/** Authorized DUR-017 Unknown-Outcome resolution; answers a `ResolveUnknownResponse`. */
|
|
46
|
+
resolveUnknownEncoded(encoded: unknown, traceContext?: unknown): Promise<unknown>;
|
|
47
|
+
/** Owner-side cross-Object port endpoint (WP2 envelopes, executed on LOCAL facets). */
|
|
48
|
+
portCall(encoded: unknown): Promise<unknown>;
|
|
49
|
+
/** Droppable liveness hint from another Object: arms an immediate alarm. */
|
|
50
|
+
wake(): Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
/** A logical Thread endpoint may be bound to an application Object without forging its brand. */
|
|
53
|
+
export type ThreadObjectClient = Omit<ThreadObjectRpc, keyof Rpc.DurableObjectBranded>;
|
|
54
|
+
declare const ThreadObjectNamespace_base: Context.ServiceClass<ThreadObjectNamespace, "@effect-agent/platform-cloudflare/ThreadObjectNamespace", {
|
|
55
|
+
readonly get: (threadId: ThreadId) => ThreadObjectClient;
|
|
56
|
+
/** Stable binding name for opted-in native RPC tracing; absent by default. */
|
|
57
|
+
readonly rpcTracing?: string;
|
|
58
|
+
}>;
|
|
59
|
+
/**
|
|
60
|
+
* Deterministic logical Thread placement. The native adapter uses `idFromName(threadId)`;
|
|
61
|
+
* a shared application owner can bind that logical identity into its RPC adapter instead.
|
|
62
|
+
* Lookup performs no I/O and grants no authority. Calls reuse a native target within
|
|
63
|
+
* one invocation; incoming requests and durable retries acquire their own targets.
|
|
64
|
+
*/
|
|
65
|
+
export declare class ThreadObjectNamespace extends ThreadObjectNamespace_base {
|
|
66
|
+
static layer(namespace: DurableObjectNamespace<ThreadObjectRpc>, options?: {
|
|
67
|
+
readonly rpcTracing?: string;
|
|
68
|
+
}): Layer.Layer<ThreadObjectNamespace>;
|
|
69
|
+
}
|
|
70
|
+
/** Invoke a placed Thread using the current invocation's native RPC channel. */
|
|
71
|
+
export declare const callThreadObject: <A, E>(threadId: string & import("effect/Brand").Brand<"@effect-agent/core/ThreadId">, invoke: (target: ThreadObjectClient) => Promise<A>, onError: (cause: unknown) => E) => Effect.Effect<A, E, ThreadObjectNamespace>;
|
|
72
|
+
/**
|
|
73
|
+
* Narrow one `env` member to a `DurableObjectNamespace`. `env` is an untyped platform value,
|
|
74
|
+
* and a namespace binding is a host object no Schema can decode, so this is the documented
|
|
75
|
+
* narrowest-boundary check (structural probe for the namespace surface the transport uses);
|
|
76
|
+
* a missing or misshaped binding fails typed before any Layer is built.
|
|
77
|
+
*/
|
|
78
|
+
export declare const threadNamespaceFromEnv: (env: unknown, binding: string) => Effect.Effect<DurableObjectNamespace<ThreadObjectRpc>, CloudflareBindingError, never>;
|
|
79
|
+
/**
|
|
80
|
+
* Build the namespace from Worker `env` (fails typed). Enable `rpcTracing` only when the
|
|
81
|
+
* receiver also opts into the effect-cf native RPC trace-context contract.
|
|
82
|
+
*/
|
|
83
|
+
export declare const threadNamespaceLayer: (env: unknown, binding: string, options?: {
|
|
84
|
+
readonly rpcTracing?: boolean;
|
|
85
|
+
}) => Layer.Layer<ThreadObjectNamespace, CloudflareBindingError>;
|
|
86
|
+
declare const DurableObjectContext_base: Context.ServiceClass<DurableObjectContext, "@effect-agent/platform-cloudflare/DurableObjectContext", {
|
|
87
|
+
readonly ctx: DurableObjectState;
|
|
88
|
+
readonly env: unknown;
|
|
89
|
+
}>;
|
|
90
|
+
/**
|
|
91
|
+
* The live Durable Object execution context of THIS incarnation. Only Layer construction and
|
|
92
|
+
* the alarm service consume it; important state never lives on it (`ctx.storage` is truth,
|
|
93
|
+
* everything in memory is a cache — deployment spec §11).
|
|
94
|
+
*/
|
|
95
|
+
export declare class DurableObjectContext extends DurableObjectContext_base {
|
|
96
|
+
static layer(ctx: DurableObjectState, env: unknown): Layer.Layer<DurableObjectContext>;
|
|
97
|
+
}
|
|
98
|
+
declare const ThreadObjectIdentity_base: Context.ServiceClass<ThreadObjectIdentity, "@effect-agent/platform-cloudflare/ThreadObjectIdentity", {
|
|
99
|
+
readonly threadId: ThreadId;
|
|
100
|
+
readonly producerId: ProducerId;
|
|
101
|
+
}>;
|
|
102
|
+
/**
|
|
103
|
+
* The Thread identity this Object serializes and the producer identity its Attempts
|
|
104
|
+
* write with (`{producerPrefix}:{threadId}`, plan §1.4). Derived once per incarnation
|
|
105
|
+
* from `ctx.id.name` — the Object identity rule guarantees the name IS the Thread ID.
|
|
106
|
+
*/
|
|
107
|
+
export declare class ThreadObjectIdentity extends ThreadObjectIdentity_base {}
|
|
108
|
+
declare const ThreadObjectPlacement_base: Context.ServiceClass<ThreadObjectPlacement, "@effect-agent/platform-cloudflare/ThreadObjectPlacement", {
|
|
109
|
+
readonly ownsThread: (threadId: ThreadId) => boolean;
|
|
110
|
+
}>;
|
|
111
|
+
/** Logical Threads whose canonical stores and admission ledger live in this physical Object. */
|
|
112
|
+
export declare class ThreadObjectPlacement extends ThreadObjectPlacement_base {}
|
|
113
|
+
//#endregion
|
|
114
|
+
export { CloudflareBindings_d_exports as t };
|
|
115
|
+
//# sourceMappingURL=CloudflareBindings.d.mts.map
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
|
+
import { Context, Effect, Layer, Predicate, Schema } from "effect";
|
|
3
|
+
import "effect-agent/identifiers";
|
|
4
|
+
import { RpcTargets } from "effect-cf";
|
|
5
|
+
import "effect-agent/records";
|
|
6
|
+
//#region src/CloudflareBindings.ts
|
|
7
|
+
var CloudflareBindings_exports = /* @__PURE__ */ __exportAll({
|
|
8
|
+
CloudflareBindingError: () => CloudflareBindingError,
|
|
9
|
+
DurableObjectContext: () => DurableObjectContext,
|
|
10
|
+
ThreadObjectIdentity: () => ThreadObjectIdentity,
|
|
11
|
+
ThreadObjectNamespace: () => ThreadObjectNamespace,
|
|
12
|
+
ThreadObjectPlacement: () => ThreadObjectPlacement,
|
|
13
|
+
callThreadObject: () => callThreadObject,
|
|
14
|
+
threadNamespaceFromEnv: () => threadNamespaceFromEnv,
|
|
15
|
+
threadNamespaceLayer: () => threadNamespaceLayer
|
|
16
|
+
});
|
|
17
|
+
/**
|
|
18
|
+
* Cloudflare platform bindings as Effect services (DEPLOY-010: "Cloudflare platform bindings
|
|
19
|
+
* are supplied as Effect services/Layers"). Application code never reads `env` or touches a
|
|
20
|
+
* `DurableObjectState` directly — the Thread Object class constructs these Layers once
|
|
21
|
+
* per incarnation and everything downstream consumes the services.
|
|
22
|
+
*/
|
|
23
|
+
/** A Cloudflare platform binding was missing or carried the wrong shape (DEPLOY-003/010). */
|
|
24
|
+
var CloudflareBindingError = class extends Schema.TaggedError()("CloudflareBindingError", {
|
|
25
|
+
binding: Schema.String,
|
|
26
|
+
message: Schema.String
|
|
27
|
+
}) {};
|
|
28
|
+
/**
|
|
29
|
+
* Deterministic logical Thread placement. The native adapter uses `idFromName(threadId)`;
|
|
30
|
+
* a shared application owner can bind that logical identity into its RPC adapter instead.
|
|
31
|
+
* Lookup performs no I/O and grants no authority. Calls reuse a native target within
|
|
32
|
+
* one invocation; incoming requests and durable retries acquire their own targets.
|
|
33
|
+
*/
|
|
34
|
+
var ThreadObjectNamespace = class ThreadObjectNamespace extends Context.Service()("@effect-agent/platform-cloudflare/ThreadObjectNamespace") {
|
|
35
|
+
static layer(namespace, options = {}) {
|
|
36
|
+
return Layer.succeed(ThreadObjectNamespace)({
|
|
37
|
+
get: (threadId) => namespace.get(namespace.idFromName(threadId)),
|
|
38
|
+
...options.rpcTracing === void 0 ? {} : { rpcTracing: options.rpcTracing }
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
/** Invoke a placed Thread using the current invocation's native RPC channel. */
|
|
43
|
+
const callThreadObject = Effect.fn("callThreadObject")(function* (threadId, invoke, onError) {
|
|
44
|
+
const namespace = yield* ThreadObjectNamespace;
|
|
45
|
+
const target = yield* RpcTargets.get(namespace, threadId, () => namespace.get(threadId)).pipe(Effect.mapError(onError));
|
|
46
|
+
return yield* Effect.tryPromise({
|
|
47
|
+
try: () => invoke(target),
|
|
48
|
+
catch: onError
|
|
49
|
+
}).pipe(Effect.tapCause(() => RpcTargets.invalidate(target)));
|
|
50
|
+
});
|
|
51
|
+
/**
|
|
52
|
+
* Narrow one `env` member to a `DurableObjectNamespace`. `env` is an untyped platform value,
|
|
53
|
+
* and a namespace binding is a host object no Schema can decode, so this is the documented
|
|
54
|
+
* narrowest-boundary check (structural probe for the namespace surface the transport uses);
|
|
55
|
+
* a missing or misshaped binding fails typed before any Layer is built.
|
|
56
|
+
*/
|
|
57
|
+
const threadNamespaceFromEnv = Effect.fn("threadNamespaceFromEnv")(function* (env, binding) {
|
|
58
|
+
if (!Predicate.isObjectKeyword(env)) return yield* CloudflareBindingError.make({
|
|
59
|
+
binding,
|
|
60
|
+
message: "The Worker environment is not an object; no bindings are available."
|
|
61
|
+
});
|
|
62
|
+
const candidate = yield* Effect.try({
|
|
63
|
+
try: () => {
|
|
64
|
+
const value = Reflect.get(env, binding);
|
|
65
|
+
if (!Predicate.isObjectKeyword(value)) return void 0;
|
|
66
|
+
const idFromName = Reflect.get(value, "idFromName");
|
|
67
|
+
const get = Reflect.get(value, "get");
|
|
68
|
+
return typeof idFromName === "function" && typeof get === "function" ? value : void 0;
|
|
69
|
+
},
|
|
70
|
+
catch: () => CloudflareBindingError.make({
|
|
71
|
+
binding,
|
|
72
|
+
message: `env.${binding} could not be inspected as a DurableObjectNamespace binding.`
|
|
73
|
+
})
|
|
74
|
+
});
|
|
75
|
+
if (candidate !== void 0) return candidate;
|
|
76
|
+
return yield* CloudflareBindingError.make({
|
|
77
|
+
binding,
|
|
78
|
+
message: `env.${binding} is not a DurableObjectNamespace binding; declare the Thread Object class under this binding in the Worker configuration.`
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
/**
|
|
82
|
+
* Build the namespace from Worker `env` (fails typed). Enable `rpcTracing` only when the
|
|
83
|
+
* receiver also opts into the effect-cf native RPC trace-context contract.
|
|
84
|
+
*/
|
|
85
|
+
const threadNamespaceLayer = (env, binding, options = {}) => Layer.effect(ThreadObjectNamespace)(Effect.map(threadNamespaceFromEnv(env, binding), (namespace) => ({
|
|
86
|
+
get: (threadId) => namespace.get(namespace.idFromName(threadId)),
|
|
87
|
+
...options.rpcTracing === true ? { rpcTracing: binding } : {}
|
|
88
|
+
})));
|
|
89
|
+
/**
|
|
90
|
+
* The live Durable Object execution context of THIS incarnation. Only Layer construction and
|
|
91
|
+
* the alarm service consume it; important state never lives on it (`ctx.storage` is truth,
|
|
92
|
+
* everything in memory is a cache — deployment spec §11).
|
|
93
|
+
*/
|
|
94
|
+
var DurableObjectContext = class DurableObjectContext extends Context.Service()("@effect-agent/platform-cloudflare/DurableObjectContext") {
|
|
95
|
+
static layer(ctx, env) {
|
|
96
|
+
return Layer.succeed(DurableObjectContext)({
|
|
97
|
+
ctx,
|
|
98
|
+
env
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* The Thread identity this Object serializes and the producer identity its Attempts
|
|
104
|
+
* write with (`{producerPrefix}:{threadId}`, plan §1.4). Derived once per incarnation
|
|
105
|
+
* from `ctx.id.name` — the Object identity rule guarantees the name IS the Thread ID.
|
|
106
|
+
*/
|
|
107
|
+
var ThreadObjectIdentity = class extends Context.Service()("@effect-agent/platform-cloudflare/ThreadObjectIdentity") {};
|
|
108
|
+
/** Logical Threads whose canonical stores and admission ledger live in this physical Object. */
|
|
109
|
+
var ThreadObjectPlacement = class extends Context.Service()("@effect-agent/platform-cloudflare/ThreadObjectPlacement") {};
|
|
110
|
+
//#endregion
|
|
111
|
+
export { CloudflareBindingError, DurableObjectContext, ThreadObjectIdentity, ThreadObjectNamespace, ThreadObjectPlacement, callThreadObject, CloudflareBindings_exports as t, threadNamespaceFromEnv, threadNamespaceLayer };
|
|
112
|
+
|
|
113
|
+
//# sourceMappingURL=CloudflareBindings.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CloudflareBindings.mjs","names":[],"sources":["../src/CloudflareBindings.ts"],"sourcesContent":["import { Context, Effect, Layer, Predicate, Schema } from \"effect\";\nimport { type ThreadId } from \"effect-agent/identifiers\";\nimport { type ProducerId } from \"effect-agent/records\";\nimport { RpcTargets } from \"effect-cf\";\n\n/**\n * Cloudflare platform bindings as Effect services (DEPLOY-010: \"Cloudflare platform bindings\n * are supplied as Effect services/Layers\"). Application code never reads `env` or touches a\n * `DurableObjectState` directly — the Thread Object class constructs these Layers once\n * per incarnation and everything downstream consumes the services.\n */\n\n/** A Cloudflare platform binding was missing or carried the wrong shape (DEPLOY-003/010). */\nexport class CloudflareBindingError extends Schema.TaggedError<CloudflareBindingError>()(\n \"CloudflareBindingError\",\n {\n binding: Schema.String,\n message: Schema.String,\n },\n) {}\n\n/**\n * The RPC surface one Thread Durable Object exposes to Workers and to sibling\n * Thread Objects. `ThreadObject.make` implements it; the Worker-side client\n * and the cross-Object transport call it through `DurableObjectNamespace` stubs. Every\n * `encoded` value is a Schema-encoded envelope (`client.ts` wire schemas for host entry\n * points, `@effect-agent/storage-cloudflare` port envelopes for `portCall`), so the RPC\n * boundary carries only structured-cloneable JSON. The optional trailing trace context is\n * transient native RPC metadata, stripped by an opted-in effect-cf receiver before decoding\n * the host envelope. It never enters durable state.\n */\nexport interface ThreadObjectRpc extends Rpc.DurableObjectBranded {\n /** Admission-limits gate + `DurableAgentRuntime.submit`; answers a `SubmitResponse`. */\n submitEncoded(encoded: unknown, traceContext?: unknown): Promise<unknown>;\n /** Wake-hinted, poll-guaranteed settlement wait; answers an `AwaitSettlementResponse`. */\n submissionStatusEncoded(encoded: unknown, traceContext?: unknown): Promise<unknown>;\n awaitSettlementEncoded(encoded: unknown, traceContext?: unknown): Promise<unknown>;\n /** Event-driven durable progress wait; answers a `ProgressObserved` host response. */\n awaitProgressEncoded(encoded: unknown, traceContext?: unknown): Promise<unknown>;\n /** Best-effort cancellation for one in-flight progress wait. */\n cancelProgressEncoded(encoded: unknown, traceContext?: unknown): Promise<unknown>;\n /** One bounded page of canonical records; answers an `ObservePageResponse`. */\n observePage(encoded: unknown, traceContext?: unknown): Promise<unknown>;\n /** Durable abort intent; answers an `AbortResponse`. */\n abortEncoded(encoded: unknown, traceContext?: unknown): Promise<unknown>;\n /** Durable approval decision (plan §2.6); answers a `ResolveApprovalResponse`. */\n resolveApprovalEncoded(encoded: unknown, traceContext?: unknown): Promise<unknown>;\n /** Authorized DUR-017 Unknown-Outcome resolution; answers a `ResolveUnknownResponse`. */\n resolveUnknownEncoded(encoded: unknown, traceContext?: unknown): Promise<unknown>;\n /** Owner-side cross-Object port endpoint (WP2 envelopes, executed on LOCAL facets). */\n portCall(encoded: unknown): Promise<unknown>;\n /** Droppable liveness hint from another Object: arms an immediate alarm. */\n wake(): Promise<void>;\n}\n\n/** A logical Thread endpoint may be bound to an application Object without forging its brand. */\nexport type ThreadObjectClient = Omit<ThreadObjectRpc, keyof Rpc.DurableObjectBranded>;\n\n/**\n * Deterministic logical Thread placement. The native adapter uses `idFromName(threadId)`;\n * a shared application owner can bind that logical identity into its RPC adapter instead.\n * Lookup performs no I/O and grants no authority. Calls reuse a native target within\n * one invocation; incoming requests and durable retries acquire their own targets.\n */\nexport class ThreadObjectNamespace extends Context.Service<\n ThreadObjectNamespace,\n {\n readonly get: (threadId: ThreadId) => ThreadObjectClient;\n /** Stable binding name for opted-in native RPC tracing; absent by default. */\n readonly rpcTracing?: string;\n }\n>()(\"@effect-agent/platform-cloudflare/ThreadObjectNamespace\") {\n static layer(\n namespace: DurableObjectNamespace<ThreadObjectRpc>,\n options: { readonly rpcTracing?: string } = {},\n ): Layer.Layer<ThreadObjectNamespace> {\n return Layer.succeed(ThreadObjectNamespace)({\n get: (threadId) => namespace.get(namespace.idFromName(threadId)),\n ...(options.rpcTracing === undefined ? {} : { rpcTracing: options.rpcTracing }),\n });\n }\n}\n\n/** Invoke a placed Thread using the current invocation's native RPC channel. */\nexport const callThreadObject = Effect.fn(\"callThreadObject\")(function* <A, E>(\n threadId: ThreadId,\n invoke: (target: ThreadObjectClient) => Promise<A>,\n onError: (cause: unknown) => E,\n): Effect.fn.Return<A, E, ThreadObjectNamespace> {\n const namespace = yield* ThreadObjectNamespace;\n\n const target = yield* RpcTargets.get(namespace, threadId, () => namespace.get(threadId)).pipe(\n Effect.mapError(onError),\n );\n\n return yield* Effect.tryPromise({ try: () => invoke(target), catch: onError }).pipe(\n Effect.tapCause(() => RpcTargets.invalidate(target)),\n );\n});\n\n/**\n * Narrow one `env` member to a `DurableObjectNamespace`. `env` is an untyped platform value,\n * and a namespace binding is a host object no Schema can decode, so this is the documented\n * narrowest-boundary check (structural probe for the namespace surface the transport uses);\n * a missing or misshaped binding fails typed before any Layer is built.\n */\nexport const threadNamespaceFromEnv = Effect.fn(\"threadNamespaceFromEnv\")(function* (\n env: unknown,\n binding: string,\n): Effect.fn.Return<DurableObjectNamespace<ThreadObjectRpc>, CloudflareBindingError> {\n if (!Predicate.isObjectKeyword(env)) {\n return yield* CloudflareBindingError.make({\n binding,\n message: \"The Worker environment is not an object; no bindings are available.\",\n });\n }\n\n const candidate = yield* Effect.try({\n try: () => {\n const value: unknown = Reflect.get(env, binding);\n\n if (!Predicate.isObjectKeyword(value)) return undefined;\n const idFromName: unknown = Reflect.get(value, \"idFromName\");\n const get: unknown = Reflect.get(value, \"get\");\n\n return typeof idFromName === \"function\" && typeof get === \"function\" ? value : undefined;\n },\n catch: () =>\n CloudflareBindingError.make({\n binding,\n message: `env.${binding} could not be inspected as a DurableObjectNamespace binding.`,\n }),\n });\n\n if (candidate !== undefined) {\n // The structural probe above is the entire runtime contract this package relies on;\n // the assertion records that `idFromName`/`get` name a DurableObjectNamespace.\n return candidate as unknown as DurableObjectNamespace<ThreadObjectRpc>;\n }\n\n return yield* CloudflareBindingError.make({\n binding,\n message:\n `env.${binding} is not a DurableObjectNamespace binding; declare the Thread ` +\n \"Object class under this binding in the Worker configuration.\",\n });\n});\n\n/**\n * Build the namespace from Worker `env` (fails typed). Enable `rpcTracing` only when the\n * receiver also opts into the effect-cf native RPC trace-context contract.\n */\nexport const threadNamespaceLayer = (\n env: unknown,\n binding: string,\n options: { readonly rpcTracing?: boolean } = {},\n): Layer.Layer<ThreadObjectNamespace, CloudflareBindingError> =>\n Layer.effect(ThreadObjectNamespace)(\n Effect.map(threadNamespaceFromEnv(env, binding), (namespace) => ({\n get: (threadId) => namespace.get(namespace.idFromName(threadId)),\n ...(options.rpcTracing === true ? { rpcTracing: binding } : {}),\n })),\n );\n\n/**\n * The live Durable Object execution context of THIS incarnation. Only Layer construction and\n * the alarm service consume it; important state never lives on it (`ctx.storage` is truth,\n * everything in memory is a cache — deployment spec §11).\n */\nexport class DurableObjectContext extends Context.Service<\n DurableObjectContext,\n {\n readonly ctx: DurableObjectState;\n readonly env: unknown;\n }\n>()(\"@effect-agent/platform-cloudflare/DurableObjectContext\") {\n static layer(ctx: DurableObjectState, env: unknown): Layer.Layer<DurableObjectContext> {\n return Layer.succeed(DurableObjectContext)({ ctx, env });\n }\n}\n\n/**\n * The Thread identity this Object serializes and the producer identity its Attempts\n * write with (`{producerPrefix}:{threadId}`, plan §1.4). Derived once per incarnation\n * from `ctx.id.name` — the Object identity rule guarantees the name IS the Thread ID.\n */\nexport class ThreadObjectIdentity extends Context.Service<\n ThreadObjectIdentity,\n {\n readonly threadId: ThreadId;\n readonly producerId: ProducerId;\n }\n>()(\"@effect-agent/platform-cloudflare/ThreadObjectIdentity\") {}\n\n/** Logical Threads whose canonical stores and admission ledger live in this physical Object. */\nexport class ThreadObjectPlacement extends Context.Service<\n ThreadObjectPlacement,\n { readonly ownsThread: (threadId: ThreadId) => boolean }\n>()(\"@effect-agent/platform-cloudflare/ThreadObjectPlacement\") {}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAaA,IAAa,yBAAb,cAA4C,OAAO,YAAoC,CAAC,CACtF,0BACA;CACE,SAAS,OAAO;CAChB,SAAS,OAAO;AAClB,CACF,CAAC,CAAC,CAAC;;;;;;;AA6CH,IAAa,wBAAb,MAAa,8BAA8B,QAAQ,QAOjD,CAAC,CAAC,yDAAyD,CAAC,CAAC;CAC7D,OAAO,MACL,WACA,UAA4C,CAAC,GACT;EACpC,OAAO,MAAM,QAAQ,qBAAqB,CAAC,CAAC;GAC1C,MAAM,aAAa,UAAU,IAAI,UAAU,WAAW,QAAQ,CAAC;GAC/D,GAAI,QAAQ,eAAe,KAAA,IAAY,CAAC,IAAI,EAAE,YAAY,QAAQ,WAAW;EAC/E,CAAC;CACH;AACF;;AAGA,MAAa,mBAAmB,OAAO,GAAG,kBAAkB,CAAC,CAAC,WAC5D,UACA,QACA,SAC+C;CAC/C,MAAM,YAAY,OAAO;CAEzB,MAAM,SAAS,OAAO,WAAW,IAAI,WAAW,gBAAgB,UAAU,IAAI,QAAQ,CAAC,CAAC,CAAC,KACvF,OAAO,SAAS,OAAO,CACzB;CAEA,OAAO,OAAO,OAAO,WAAW;EAAE,WAAW,OAAO,MAAM;EAAG,OAAO;CAAQ,CAAC,CAAC,CAAC,KAC7E,OAAO,eAAe,WAAW,WAAW,MAAM,CAAC,CACrD;AACF,CAAC;;;;;;;AAQD,MAAa,yBAAyB,OAAO,GAAG,wBAAwB,CAAC,CAAC,WACxE,KACA,SACmF;CACnF,IAAI,CAAC,UAAU,gBAAgB,GAAG,GAChC,OAAO,OAAO,uBAAuB,KAAK;EACxC;EACA,SAAS;CACX,CAAC;CAGH,MAAM,YAAY,OAAO,OAAO,IAAI;EAClC,WAAW;GACT,MAAM,QAAiB,QAAQ,IAAI,KAAK,OAAO;GAE/C,IAAI,CAAC,UAAU,gBAAgB,KAAK,GAAG,OAAO,KAAA;GAC9C,MAAM,aAAsB,QAAQ,IAAI,OAAO,YAAY;GAC3D,MAAM,MAAe,QAAQ,IAAI,OAAO,KAAK;GAE7C,OAAO,OAAO,eAAe,cAAc,OAAO,QAAQ,aAAa,QAAQ,KAAA;EACjF;EACA,aACE,uBAAuB,KAAK;GAC1B;GACA,SAAS,OAAO,QAAQ;EAC1B,CAAC;CACL,CAAC;CAED,IAAI,cAAc,KAAA,GAGhB,OAAO;CAGT,OAAO,OAAO,uBAAuB,KAAK;EACxC;EACA,SACE,OAAO,QAAQ;CAEnB,CAAC;AACH,CAAC;;;;;AAMD,MAAa,wBACX,KACA,SACA,UAA6C,CAAC,MAE9C,MAAM,OAAO,qBAAqB,CAAC,CACjC,OAAO,IAAI,uBAAuB,KAAK,OAAO,IAAI,eAAe;CAC/D,MAAM,aAAa,UAAU,IAAI,UAAU,WAAW,QAAQ,CAAC;CAC/D,GAAI,QAAQ,eAAe,OAAO,EAAE,YAAY,QAAQ,IAAI,CAAC;AAC/D,EAAE,CACJ;;;;;;AAOF,IAAa,uBAAb,MAAa,6BAA6B,QAAQ,QAMhD,CAAC,CAAC,wDAAwD,CAAC,CAAC;CAC5D,OAAO,MAAM,KAAyB,KAAiD;EACrF,OAAO,MAAM,QAAQ,oBAAoB,CAAC,CAAC;GAAE;GAAK;EAAI,CAAC;CACzD;AACF;;;;;;AAOA,IAAa,uBAAb,cAA0C,QAAQ,QAMhD,CAAC,CAAC,wDAAwD,CAAC,CAAC,CAAC;;AAG/D,IAAa,wBAAb,cAA2C,QAAQ,QAGjD,CAAC,CAAC,yDAAyD,CAAC,CAAC,CAAC"}
|