effect-browserbase 0.2.0-beta.9 → 0.3.0-beta.10
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/README.md +277 -319
- package/dist/Browserbase-CaPKwEY9.mjs +544 -0
- package/dist/Browserbase-CaPKwEY9.mjs.map +1 -0
- package/dist/Browserbase.d.mts +110 -0
- package/dist/Browserbase.mjs +3 -0
- package/dist/BrowserbaseClient-CtAQ2rg4.d.mts +195 -0
- package/dist/BrowserbaseClient.d.mts +2 -0
- package/dist/BrowserbaseClient.mjs +190 -0
- package/dist/BrowserbaseClient.mjs.map +1 -0
- package/dist/BrowserbaseError-D1EOrLNc.d.mts +79 -0
- package/dist/BrowserbaseError.d.mts +2 -0
- package/dist/BrowserbaseError.mjs +101 -0
- package/dist/BrowserbaseError.mjs.map +1 -0
- package/dist/ContextLease.d.mts +42 -0
- package/dist/ContextLease.mjs +80 -0
- package/dist/ContextLease.mjs.map +1 -0
- package/dist/index.d.mts +5 -27
- package/dist/index.mjs +5 -26
- package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
- package/dist/testing/index.d.mts +136 -0
- package/dist/testing/index.mjs +440 -0
- package/dist/testing/index.mjs.map +1 -0
- package/package.json +51 -121
- package/src/Browserbase.ts +729 -0
- package/src/BrowserbaseClient.ts +559 -0
- package/src/BrowserbaseError.ts +108 -0
- package/src/ContextLease.ts +118 -0
- package/src/index.ts +7 -0
- package/src/internal/captureConnection.ts +214 -0
- package/src/testing/BrowserbaseContract.ts +170 -0
- package/src/testing/TestBrowserbase.ts +509 -0
- package/src/testing/index.ts +7 -0
- package/dist/Account.d.mts +0 -32
- package/dist/Account.mjs +0 -36
- package/dist/Account.mjs.map +0 -1
- package/dist/Acquisition-BOABu_qJ.mjs +0 -244
- package/dist/Acquisition-BOABu_qJ.mjs.map +0 -1
- package/dist/Agents-CPaTOH_g.d.mts +0 -156
- package/dist/Agents.d.mts +0 -3
- package/dist/Agents.mjs +0 -292
- package/dist/Agents.mjs.map +0 -1
- package/dist/Allocation.d.mts +0 -97
- package/dist/Allocation.mjs +0 -27
- package/dist/Allocation.mjs.map +0 -1
- package/dist/Authorization-Ll5f_XNM.mjs +0 -12
- package/dist/Authorization-Ll5f_XNM.mjs.map +0 -1
- package/dist/Browser-ByrWJ0ss.mjs +0 -274
- package/dist/Browser-ByrWJ0ss.mjs.map +0 -1
- package/dist/Browser.d.mts +0 -83
- package/dist/Browser.mjs +0 -3
- package/dist/BrowserBinding.d.mts +0 -13
- package/dist/BrowserBinding.mjs +0 -31
- package/dist/BrowserBinding.mjs.map +0 -1
- package/dist/Certificates-D4NQmyeA.d.mts +0 -34
- package/dist/Certificates.d.mts +0 -3
- package/dist/Certificates.mjs +0 -85
- package/dist/Certificates.mjs.map +0 -1
- package/dist/Cleanup-DMTDBir8.d.mts +0 -23
- package/dist/Cleanup.d.mts +0 -3
- package/dist/Cleanup.mjs +0 -43
- package/dist/Cleanup.mjs.map +0 -1
- package/dist/Client-BEC4Q8ZS.mjs +0 -564
- package/dist/Client-BEC4Q8ZS.mjs.map +0 -1
- package/dist/Client-B_f6bBLT.d.mts +0 -52
- package/dist/Client.d.mts +0 -3
- package/dist/Client.mjs +0 -2
- package/dist/Connection-sxyxtwlk.mjs +0 -56
- package/dist/Connection-sxyxtwlk.mjs.map +0 -1
- package/dist/ContextCoordination.d.mts +0 -29
- package/dist/ContextCoordination.mjs +0 -94
- package/dist/ContextCoordination.mjs.map +0 -1
- package/dist/ContextWriter-CiEma24z.mjs +0 -204
- package/dist/ContextWriter-CiEma24z.mjs.map +0 -1
- package/dist/Contexts-DqdL7cyX.d.mts +0 -31
- package/dist/Contexts.d.mts +0 -3
- package/dist/Contexts.mjs +0 -97
- package/dist/Contexts.mjs.map +0 -1
- package/dist/Deadline-CrViaogr.mjs +0 -13
- package/dist/Deadline-CrViaogr.mjs.map +0 -1
- package/dist/Downloads-CX52GOFJ.d.mts +0 -43
- package/dist/Downloads.d.mts +0 -3
- package/dist/Downloads.mjs +0 -137
- package/dist/Downloads.mjs.map +0 -1
- package/dist/Errors.d.mts +0 -100
- package/dist/Errors.mjs +0 -194
- package/dist/Errors.mjs.map +0 -1
- package/dist/Extensions-BTUn9zhK.mjs +0 -231
- package/dist/Extensions-BTUn9zhK.mjs.map +0 -1
- package/dist/Extensions-DBXuVM1f.d.mts +0 -43
- package/dist/Extensions.d.mts +0 -3
- package/dist/Extensions.mjs +0 -2
- package/dist/Functions-CsKMMUuZ.d.mts +0 -226
- package/dist/Functions.d.mts +0 -3
- package/dist/Functions.mjs +0 -318
- package/dist/Functions.mjs.map +0 -1
- package/dist/Issued-DejqoMYL.mjs +0 -15
- package/dist/Issued-DejqoMYL.mjs.map +0 -1
- package/dist/Launch-cAdE2rrZ.mjs +0 -115
- package/dist/Launch-cAdE2rrZ.mjs.map +0 -1
- package/dist/Launch.d.mts +0 -127
- package/dist/Launch.mjs +0 -97
- package/dist/Launch.mjs.map +0 -1
- package/dist/PageFetch-CjAM_0DS.d.mts +0 -40
- package/dist/PageFetch.d.mts +0 -3
- package/dist/PageFetch.mjs +0 -59
- package/dist/PageFetch.mjs.map +0 -1
- package/dist/Projects-tm5bTDH0.d.mts +0 -38
- package/dist/Projects.d.mts +0 -3
- package/dist/Projects.mjs +0 -65
- package/dist/Projects.mjs.map +0 -1
- package/dist/Recordings-B9k5aODB.d.mts +0 -27
- package/dist/Recordings.d.mts +0 -3
- package/dist/Recordings.mjs +0 -144
- package/dist/Recordings.mjs.map +0 -1
- package/dist/References-DOH3Wu44.d.mts +0 -34
- package/dist/References.d.mts +0 -3
- package/dist/References.mjs +0 -33
- package/dist/References.mjs.map +0 -1
- package/dist/Replays-mV93WGtx.d.mts +0 -27
- package/dist/Replays.d.mts +0 -3
- package/dist/Replays.mjs +0 -107
- package/dist/Replays.mjs.map +0 -1
- package/dist/Resource-J7Kkk5mu.mjs +0 -54
- package/dist/Resource-J7Kkk5mu.mjs.map +0 -1
- package/dist/Search-B64e7g-h.d.mts +0 -37
- package/dist/Search.d.mts +0 -3
- package/dist/Search.mjs +0 -46
- package/dist/Search.mjs.map +0 -1
- package/dist/SessionData-5xYZDshJ.d.mts +0 -38
- package/dist/SessionData.d.mts +0 -3
- package/dist/SessionData.mjs +0 -48
- package/dist/SessionData.mjs.map +0 -1
- package/dist/Sessions-D2H5m6rF.mjs +0 -260
- package/dist/Sessions-D2H5m6rF.mjs.map +0 -1
- package/dist/Sessions-oJEUmZth.d.mts +0 -69
- package/dist/Sessions.d.mts +0 -4
- package/dist/Sessions.mjs +0 -3
- package/dist/Testing.d.mts +0 -119
- package/dist/Testing.mjs +0 -206
- package/dist/Testing.mjs.map +0 -1
- package/dist/TransferPolicy-DQ06i7SZ.mjs +0 -25
- package/dist/TransferPolicy-DQ06i7SZ.mjs.map +0 -1
- package/dist/Transfers-GVqzrDWl.d.mts +0 -89
- package/dist/Transfers.d.mts +0 -3
- package/dist/Transfers.mjs +0 -85
- package/dist/Transfers.mjs.map +0 -1
- package/dist/Uploads-C2_bACgv.d.mts +0 -28
- package/dist/Uploads.d.mts +0 -3
- package/dist/Uploads.mjs +0 -105
- package/dist/Uploads.mjs.map +0 -1
- package/dist/Webhooks-BoeRAxzG.d.mts +0 -59
- package/dist/Webhooks.d.mts +0 -3
- package/dist/Webhooks.mjs +0 -134
- package/dist/Webhooks.mjs.map +0 -1
- package/dist/WriterFacts-BBJRDZYY.d.mts +0 -54
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Client-BEC4Q8ZS.mjs","names":["Trace.span","Trace.stream"],"sources":["../src/internal/Trace.ts","../src/internal/http/Multipart.ts","../src/internal/http/Transport.ts","../src/Client.ts"],"sourcesContent":["import {\n Cause,\n Clock,\n Context,\n Effect,\n Exit,\n Option,\n References,\n Schema,\n Stream,\n Tracer,\n} from \"effect\";\n\nimport {\n AllocationError,\n ArtifactError,\n CertificateError,\n ClientError,\n ContextError,\n ExtensionError,\n FileError,\n PlatformError,\n ProjectError,\n SessionError,\n} from \"../Errors.ts\";\n\nconst Failure = Schema.Union([\n AllocationError,\n ArtifactError,\n CertificateError,\n ClientError,\n ContextError,\n ExtensionError,\n FileError,\n PlatformError,\n ProjectError,\n SessionError,\n]);\n\n/** Causality crosses ownership boundaries as ids and sampling, never a live caller context. */\nexport const capture = Effect.gen(function* () {\n const current = yield* Effect.serviceOption(Tracer.ParentSpan);\n const enabled = yield* References.TracerEnabled;\n\n return yield* Effect.sync(() => {\n try {\n let parent = Option.getOrUndefined(current);\n\n while (parent !== undefined && Context.get(parent.annotations, Tracer.DisablePropagation))\n parent = parent._tag === \"Span\" ? Option.getOrUndefined(parent.parent) : undefined;\n\n return {\n enabled,\n parent:\n parent === undefined\n ? undefined\n : Object.freeze(\n Tracer.externalSpan({\n traceId: parent.traceId,\n spanId: parent.spanId,\n sampled: parent.sampled,\n }),\n ),\n };\n } catch {\n // A broken tracer identity cannot turn causal capture into an operation defect.\n return { enabled: false, parent: undefined };\n }\n });\n});\n\nexport type Identity = Effect.Success<typeof capture>;\n\n/** A native page callback has no observable Tool caller. It starts a linked, sampling-aware root. */\nexport const autonomous = (identity: Identity): Tracer.SpanOptionsNoTrace => ({\n root: true,\n links: identity.parent === undefined ? [] : [{ span: identity.parent, attributes: {} }],\n ...(identity.parent?.sampled === false ? { sampled: false } : {}),\n});\n\nexport interface Started {\n readonly span: Tracer.Span;\n readonly end: (exit: Exit.Exit<unknown, unknown>, attributes?: Record<string, unknown>) => void;\n}\n\n/** Only finite, library-owned facts are passed here; exporter pressure loses telemetry only. */\nexport const annotate = (attributes: Record<string, unknown>) =>\n Effect.gen(function* () {\n if (!(yield* References.TracerEnabled)) return;\n const current = yield* Effect.serviceOption(Tracer.ParentSpan);\n\n if (Option.isNone(current) || current.value._tag !== \"Span\") return;\n const span = current.value;\n\n yield* Effect.sync(() => {\n try {\n for (const [key, value] of Object.entries(attributes)) span.attribute(key, value);\n } catch {\n // Result construction and cleanup must not depend on exporter health.\n }\n });\n });\n\n/**\n * Library spans export neither successful values nor original causes/stacks. Tracer failures\n * cannot suppress dispatch or alter its result. Sampling metadata is available in annotations\n * at creation: rc.117 applies SpanOptions.attributes only after Tracer.span has returned.\n */\nexport const start = Effect.fnUntraced(function* (\n name: string,\n options: Tracer.SpanOptionsNoTrace = {},\n): Effect.fn.Return<Started | undefined> {\n const identity = yield* capture;\n\n if (!identity.enabled) return undefined;\n const clock = yield* Clock.Clock;\n const timing = yield* References.TracerTimingEnabled;\n const attributes = options.attributes ?? {};\n\n const parent = options.parent ?? (options.root === true ? undefined : identity.parent);\n\n const created = yield* Effect.makeSpan(name, {\n ...options,\n attributes: undefined,\n parent,\n root: options.root ?? parent === undefined,\n annotations: Context.make(References.TracerSpanAnnotations, attributes),\n }).pipe(\n Effect.provideService(References.TracerSpanAnnotations, {}),\n Effect.provideService(References.TracerSpanLinks, []),\n Effect.exit,\n );\n\n if (Exit.isFailure(created)) return undefined;\n\n return yield* Effect.sync((): Started => {\n const span = created.value;\n let ended = false;\n\n try {\n for (const [key, value] of Object.entries(attributes)) span.attribute(key, value);\n } catch {\n // Retain the allocated span for one termination even if its attributes were refused.\n }\n\n return {\n span,\n end: (exit, extra = {}) => {\n if (ended) return;\n ended = true;\n const interrupted = Exit.isFailure(exit) && Cause.hasInterruptsOnly(exit.cause);\n\n try {\n const failure = Exit.isFailure(exit)\n ? Option.getOrUndefined(Cause.findErrorOption(exit.cause))\n : undefined;\n\n const known = Schema.is(Failure)(failure) ? failure : undefined;\n\n for (const [key, value] of Object.entries(extra)) span.attribute(key, value);\n span.attribute(\n \"browser.status\",\n Exit.isSuccess(exit) ? \"success\" : interrupted ? \"interrupted\" : \"failure\",\n );\n if (known !== undefined) {\n span.attribute(\"browser.reason\", known.reason);\n if (\"outcome\" in known && known.outcome !== undefined)\n span.attribute(\"browser.outcome\", known.outcome);\n }\n } catch {\n // Exporter pressure and shutdown are telemetry loss, never an operation failure.\n }\n try {\n span.end(\n timing ? clock.currentTimeNanosUnsafe() : 0n,\n Exit.isSuccess(exit)\n ? Exit.void\n : Exit.fail(interrupted ? \"Operation interrupted\" : \"Operation failed\"),\n );\n } catch {\n // An exporter is allowed to fail after accepting a span; never retry its termination.\n }\n },\n };\n });\n});\n\nexport const span =\n (name: string, options: Tracer.SpanOptionsNoTrace = {}) =>\n <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>\n Effect.uninterruptibleMask((restore) =>\n start(name, options).pipe(\n Effect.flatMap((started) =>\n started === undefined\n ? restore(effect)\n : restore(effect).pipe(\n Effect.provideService(Tracer.ParentSpan, started.span),\n Effect.onExit((exit) => Effect.sync(() => started.end(exit))),\n ),\n ),\n ),\n );\n\n/** One span per consumption; end after setup, pulls and the original channel scope's finalizers. */\nexport const stream =\n (name: string, options: Tracer.SpanOptionsNoTrace = {}) =>\n <A, E, R>(source: Stream.Stream<A, E, R>): Stream.Stream<A, E, R> =>\n Stream.suspend(() => {\n let terminal: Exit.Exit<unknown, unknown> | undefined;\n\n return Stream.unwrap(\n Effect.uninterruptible(\n start(name, options).pipe(\n Effect.flatMap((value) => {\n return value === undefined\n ? Effect.succeed(source)\n : Effect.addFinalizer((exit) =>\n Effect.sync(() => value.end(terminal ?? exit)),\n ).pipe(\n Effect.as(source.pipe(Stream.provideService(Tracer.ParentSpan, value.span))),\n );\n }),\n ),\n ),\n ).pipe(\n Stream.onExit((exit) =>\n Effect.sync(() => {\n terminal = exit;\n }),\n ),\n );\n });\n","import { Effect, Random, Schema } from \"effect\";\n\nimport type { MultipartFile } from \"../../Client.ts\";\nimport { SafeFilename } from \"../../Transfers.ts\";\n\n/** One file part is the only multipart shape this transport produces. */\nexport type MultipartResult =\n | {\n readonly _tag: \"Encoded\";\n readonly contentType: string;\n readonly body: Uint8Array;\n }\n | { readonly _tag: \"Rejected\"; readonly reason: \"configuration\" | \"limit\" };\n\nconst FIELD = /^[a-z][a-z0-9_]{0,31}$/;\nconst MEDIA_TYPE = /^[a-z0-9][a-z0-9!#$&^_+.-]{0,63}\\/[a-z0-9][a-z0-9!#$&^_+.-]{0,63}$/;\nconst PRINTABLE_ASCII = /^[\\x20-\\x7e]+$/;\n\nconst isSafeFilename = Schema.is(SafeFilename);\n\n/** Quoting is only safe for a portable, printable, quote-free basename. */\nconst quotable = (value: string): boolean =>\n isSafeFilename(value) && PRINTABLE_ASCII.test(value) && !value.includes('\"');\n\n/**\n * Sixteen bytes from the fiber's `Random`. A boundary needs no secrecy: the encoder checks that\n * the content does not contain it, and draws another if it does.\n */\nconst randomBoundary: Effect.Effect<string> = Effect.map(\n Effect.all(Array.from({ length: 16 }, () => Random.nextIntBetween(0, 255))),\n (bytes) =>\n `effect-agent-browserbase-${bytes.map((byte) => byte.toString(16).padStart(2, \"0\")).join(\"\")}`,\n);\n\nconst contains = (haystack: Uint8Array, needle: Uint8Array): boolean => {\n const first = needle[0];\n\n if (first === undefined || needle.length > haystack.length) return false;\n\n outer: for (let i = 0; i <= haystack.length - needle.length; i++) {\n if (haystack[i] !== first) continue;\n for (let j = 1; j < needle.length; j++) {\n const expected = needle[j];\n\n if (expected === undefined || haystack[i + j] !== expected) continue outer;\n }\n\n return true;\n }\n\n return false;\n};\n\n/**\n * A deliberately small RFC 7578 encoder: one file part, an ASCII-quotable name and a\n * delimiter proven absent from the content. It performs no filesystem or stream work.\n */\nexport const encodeFilePart = Effect.fnUntraced(function* (\n part: MultipartFile,\n maxBytes: number,\n boundaries: Effect.Effect<string> = randomBoundary,\n): Effect.fn.Return<MultipartResult> {\n if (\n !FIELD.test(part.field) ||\n !quotable(part.filename) ||\n !MEDIA_TYPE.test(part.mediaType) ||\n !Number.isSafeInteger(maxBytes) ||\n maxBytes < 1 ||\n maxBytes > 2 ** 31 - 1\n ) {\n return { _tag: \"Rejected\", reason: \"configuration\" };\n }\n if (part.bytes.byteLength > maxBytes) return { _tag: \"Rejected\", reason: \"limit\" };\n const encoder = new TextEncoder();\n\n for (let attempt = 0; attempt < 4; attempt++) {\n const boundary = yield* boundaries;\n\n if (!/^[A-Za-z0-9-]{1,70}$/.test(boundary)) continue;\n const delimiter = encoder.encode(boundary);\n\n if (contains(part.bytes, delimiter)) continue;\n\n const head = encoder.encode(\n `--${boundary}\\r\\nContent-Disposition: form-data; name=\"${part.field}\"; filename=\"${part.filename}\"\\r\\nContent-Type: ${part.mediaType}\\r\\n\\r\\n`,\n );\n\n const tail = encoder.encode(`\\r\\n--${boundary}--\\r\\n`);\n const body = new Uint8Array(head.byteLength + part.bytes.byteLength + tail.byteLength);\n\n body.set(head, 0);\n body.set(part.bytes, head.byteLength);\n body.set(tail, head.byteLength + part.bytes.byteLength);\n\n return {\n _tag: \"Encoded\",\n contentType: `multipart/form-data; boundary=${boundary}`,\n body,\n };\n }\n\n return { _tag: \"Rejected\", reason: \"configuration\" };\n});\n","import { Clock, Duration, Effect, Redacted, Schema, Stream } from \"effect\";\nimport {\n FetchHttpClient,\n HttpClient,\n HttpClientRequest,\n type HttpClientResponse,\n} from \"effect/unstable/http\";\n\nimport type { ClientMethod, ClientOptions, MultipartFile, UploadLimits } from \"../../Client.ts\";\nimport { ClientError } from \"../../Errors.ts\";\nimport { Identifier } from \"../../References.ts\";\nimport * as Trace from \"../Trace.ts\";\nimport { encodeFilePart } from \"./Multipart.ts\";\n\nconst API_ORIGIN = \"https://api.browserbase.com\";\nconst MAX_JSON_BYTES = 1024 * 1024;\nconst MAX_JSON_DEPTH = 64;\n\nconst traceMethod = (method: string) =>\n [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\"].includes(method) ? method : \"invalid\";\n\nconst Options = Schema.Struct({\n projectId: Identifier,\n apiKey: Schema.Redacted(\n Schema.NonEmptyString.check(Schema.isMaxLength(8192), Schema.isPattern(/^[\\x21-\\x7e]+$/)),\n ),\n artifactOrigins: Schema.optionalKey(\n Schema.Array(Schema.String.check(Schema.isMaxLength(8192))).check(\n Schema.isMaxLength(32),\n Schema.isUnique(),\n ),\n ),\n requestTimeoutMillis: Schema.optionalKey(\n Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 60_000 })),\n ),\n});\n\nconst nowMillis = Clock.monotonicTimeNanos.pipe(Effect.map((value) => Number(value) / 1_000_000));\n\nconst deadlineAfter = (millis: number) => nowMillis.pipe(Effect.map((now) => now + millis));\n\nconst within = <A, E, R>(\n effect: Effect.Effect<A, E, R>,\n deadline: number,\n operation: ClientError[\"operation\"],\n outcome?: \"undispatched\" | \"unknown\",\n): Effect.Effect<A, E | ClientError, R> =>\n Effect.suspend(() =>\n nowMillis.pipe(\n Effect.flatMap((now) => {\n const remaining = deadline - now;\n\n const timeout = () =>\n Effect.fail(\n ClientError.make({\n operation,\n reason: \"timeout\",\n ...(outcome === undefined ? {} : { outcome }),\n }),\n );\n\n return remaining <= 0\n ? timeout()\n : effect.pipe(\n Effect.timeoutOrElse({\n duration: Duration.millis(remaining),\n orElse: timeout,\n }),\n );\n }),\n ),\n );\n\nconst withinJsonDepth = (text: string): boolean => {\n let depth = 0;\n let quoted = false;\n let escaped = false;\n\n for (const character of text) {\n if (quoted) {\n if (escaped) escaped = false;\n else if (character === \"\\\\\") escaped = true;\n else if (character === '\"') quoted = false;\n } else if (character === '\"') quoted = true;\n else if (character === \"{\" || character === \"[\") {\n if (++depth > MAX_JSON_DEPTH) return false;\n } else if (character === \"}\" || character === \"]\") depth--;\n }\n\n return true;\n};\n\nconst mediaType = (value: string | undefined): string =>\n value?.split(\";\", 1)[0]?.trim().toLowerCase() ?? \"\";\n\nconst retryAfter = (value: string | undefined, now: number): number | undefined => {\n if (value === undefined || value.length > 128) return undefined;\n const seconds = Number(value);\n\n if (Number.isFinite(seconds) && seconds >= 0) return Math.min(60_000, seconds * 1000);\n const date = Date.parse(value);\n\n return Number.isFinite(date) ? Math.min(60_000, Math.max(0, date - now)) : undefined;\n};\n\nconst mutationOutcome = (\n method: ClientMethod,\n status?: number,\n): \"rejected\" | \"unknown\" | undefined => {\n if (method === \"GET\") return undefined;\n if (status !== undefined && [400, 401, 403, 404, 409, 410, 422, 429].includes(status)) {\n return \"rejected\";\n }\n\n return \"unknown\";\n};\n\nconst statusError = (\n method: ClientMethod,\n status: number,\n operation: ClientError[\"operation\"],\n after?: number,\n) =>\n ClientError.make({\n operation,\n reason:\n status === 401 || status === 403\n ? \"authorization\"\n : status === 429\n ? \"rate-limited\"\n : status === 409\n ? \"active\"\n : status === 410\n ? \"expired\"\n : status === 422\n ? \"disabled\"\n : status === 404\n ? \"not-found\"\n : \"provider\",\n status,\n ...(mutationOutcome(method, status) === undefined\n ? {}\n : { outcome: mutationOutcome(method, status) }),\n ...(after === undefined ? {} : { retryAfterMillis: after }),\n });\n\nconst collect = (\n stream: Stream.Stream<Uint8Array, ClientError>,\n maximum: number,\n operation: ClientError[\"operation\"],\n) =>\n Effect.gen(function* () {\n const chunks: Uint8Array[] = [];\n let total = 0;\n\n yield* Stream.runForEach(stream, (chunk) =>\n Effect.suspend(() => {\n if (chunk.byteLength > maximum - total) {\n return Effect.fail(ClientError.make({ operation, reason: \"limit\" }));\n }\n total += chunk.byteLength;\n chunks.push(chunk);\n\n return Effect.void;\n }),\n );\n\n const body = new Uint8Array(total);\n let offset = 0;\n\n for (const chunk of chunks) {\n body.set(chunk, offset);\n offset += chunk.byteLength;\n }\n\n return body;\n });\n\nconst validApiPath = (path: string): boolean =>\n path.startsWith(\"/v1/\") && !path.includes(\"\\\\\") && !path.includes(\"#\") && path.length <= 16_384;\n\nexport const makeTransport = Effect.fnUntraced(function* (options: ClientOptions) {\n const configured = yield* Schema.decodeEffect(Options)(options, {\n onExcessProperty: \"error\",\n }).pipe(\n Effect.mapError(() =>\n ClientError.make({\n operation: \"configure\",\n reason: \"configuration\",\n outcome: \"undispatched\",\n }),\n ),\n );\n\n const apiKey = Redacted.value(configured.apiKey);\n const requestTimeoutMillis = configured.requestTimeoutMillis ?? 10_000;\n const artifactOrigins = new Set<string>();\n\n for (const origin of configured.artifactOrigins ?? []) {\n const url = yield* Effect.try({\n try: () => new URL(origin),\n catch: () =>\n ClientError.make({\n operation: \"configure\",\n reason: \"configuration\",\n outcome: \"undispatched\",\n }),\n });\n\n if (url.protocol !== \"https:\" || url.origin !== origin || url.username || url.password) {\n return yield* ClientError.make({\n operation: \"configure\",\n reason: \"configuration\",\n outcome: \"undispatched\",\n });\n }\n artifactOrigins.add(origin);\n }\n\n const fetch = yield* FetchHttpClient.Fetch;\n const client = yield* HttpClient.HttpClient.pipe(Effect.provide(FetchHttpClient.layer));\n const scoped = HttpClient.withScope(client);\n\n const execute = (\n request: HttpClientRequest.HttpClientRequest,\n operation: ClientError[\"operation\"],\n outcome?: \"undispatched\" | \"unknown\",\n ) =>\n scoped.execute(request).pipe(\n Effect.provideService(FetchHttpClient.Fetch, fetch),\n Effect.provideService(FetchHttpClient.RequestInit, {\n redirect: \"manual\",\n credentials: \"omit\",\n cache: \"no-store\",\n referrerPolicy: \"no-referrer\",\n }),\n Effect.provideService(HttpClient.TracerDisabledWhen, () => true),\n Effect.provideService(HttpClient.TracerPropagationEnabled, false),\n Effect.withTracerEnabled(false),\n Effect.mapError(() =>\n ClientError.make({\n operation,\n reason: \"transport\",\n ...(outcome === undefined ? {} : { outcome }),\n }),\n ),\n Trace.span(\"BrowserbaseClient.execute\", {\n attributes: {\n \"browser.operation\": operation,\n \"http.request.method\": traceMethod(request.method),\n },\n }),\n );\n\n /** A rejected path is a typed, undispatched configuration failure, never a defect. */\n const apiRequest = (\n method: ClientMethod,\n path: string,\n accept: string,\n operation: ClientError[\"operation\"],\n ) =>\n validApiPath(path)\n ? Effect.succeed(\n HttpClientRequest.make(method)(`${API_ORIGIN}${path}`).pipe(\n HttpClientRequest.setHeader(\"x-bb-api-key\", apiKey),\n HttpClientRequest.setHeader(\"accept\", accept),\n ),\n )\n : Effect.fail(\n ClientError.make({ operation, reason: \"configuration\", outcome: \"undispatched\" }),\n );\n\n const inspectJson = Effect.fnUntraced(function* (\n method: ClientMethod,\n response: HttpClientResponse.HttpClientResponse,\n operation: ClientError[\"operation\"],\n ) {\n if (response.status !== 200 && response.status !== 201 && response.status !== 202) {\n return yield* statusError(\n method,\n response.status,\n operation,\n retryAfter(response.headers[\"retry-after\"], yield* Clock.currentTimeMillis),\n );\n }\n if (mediaType(response.headers[\"content-type\"]) !== \"application/json\") {\n return yield* ClientError.make({\n operation,\n reason: \"content-type\",\n ...(mutationOutcome(method) === undefined ? {} : { outcome: mutationOutcome(method) }),\n });\n }\n const length = response.headers[\"content-length\"];\n\n if (length !== undefined && (!/^\\d+$/.test(length) || Number(length) > MAX_JSON_BYTES)) {\n return yield* ClientError.make({\n operation,\n reason: \"limit\",\n ...(mutationOutcome(method) === undefined ? {} : { outcome: mutationOutcome(method) }),\n });\n }\n let received = 0;\n\n return response.stream.pipe(\n Stream.mapError(() =>\n ClientError.make({\n operation,\n reason: \"transport\",\n ...(mutationOutcome(method) === undefined ? {} : { outcome: mutationOutcome(method) }),\n }),\n ),\n Stream.mapEffect((chunk) =>\n Effect.suspend(() => {\n if (chunk.byteLength > MAX_JSON_BYTES - received) {\n return Effect.fail(\n ClientError.make({\n operation,\n reason: \"limit\",\n ...(mutationOutcome(method) === undefined\n ? {}\n : { outcome: mutationOutcome(method) }),\n }),\n );\n }\n received += chunk.byteLength;\n\n return Effect.succeed(new Uint8Array(chunk));\n }),\n ),\n );\n });\n\n const readJson = Effect.fnUntraced(function* (\n method: ClientMethod,\n response: HttpClientResponse.HttpClientResponse,\n operation: ClientError[\"operation\"],\n ) {\n const stream = yield* inspectJson(method, response, operation);\n const bytes = yield* collect(stream, MAX_JSON_BYTES, operation);\n\n const text = yield* Effect.try({\n try: () => new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes),\n catch: () =>\n ClientError.make({\n operation,\n reason: \"malformed\",\n ...(mutationOutcome(method) === undefined ? {} : { outcome: mutationOutcome(method) }),\n }),\n });\n\n if (!withinJsonDepth(text)) {\n return yield* ClientError.make({\n operation,\n reason: \"limit\",\n ...(mutationOutcome(method) === undefined ? {} : { outcome: mutationOutcome(method) }),\n });\n }\n\n return yield* Schema.decodeEffect(Schema.fromJsonString(Schema.Json))(text).pipe(\n Effect.mapError(() =>\n ClientError.make({\n operation,\n reason: \"malformed\",\n ...(mutationOutcome(method) === undefined ? {} : { outcome: mutationOutcome(method) }),\n }),\n ),\n );\n }, Trace.span(\"BrowserbaseClient.decodeJson\"));\n\n const jsonOnce = Effect.fnUntraced(function* (\n method: ClientMethod,\n path: string,\n body?: Schema.Json,\n ) {\n const operation = method === \"GET\" ? \"provider-read\" : \"provider-mutation\";\n let request = yield* apiRequest(method, path, \"application/json\", operation);\n\n if (body !== undefined) {\n request = yield* HttpClientRequest.bodyJson(request, body).pipe(\n Effect.mapError(() =>\n ClientError.make({\n operation,\n reason: \"configuration\",\n outcome: \"undispatched\",\n }),\n ),\n );\n }\n const response = yield* execute(request, operation, method === \"GET\" ? undefined : \"unknown\");\n\n return yield* readJson(method, response, operation);\n });\n\n /**\n * One bounded in-memory file part. The encoder proves its delimiter absent from the\n * content, and an accepted multipart mutation is never retried: a lost reply is unknown.\n */\n const upload = Effect.fnUntraced(\n function* (path: string, part: MultipartFile, limits: UploadLimits, outerDeadline?: number) {\n const operation = \"provider-upload\";\n const timeoutMillis = limits.timeoutMillis ?? 60_000;\n\n if (!Number.isSafeInteger(timeoutMillis) || timeoutMillis < 1 || timeoutMillis > 600_000) {\n return yield* ClientError.make({\n operation,\n reason: \"configuration\",\n outcome: \"undispatched\",\n });\n }\n\n const encoded = yield* encodeFilePart(part, limits.maxBytes);\n\n if (encoded._tag === \"Rejected\") {\n return yield* ClientError.make({\n operation,\n reason: encoded.reason,\n outcome: \"undispatched\",\n });\n }\n\n const request = HttpClientRequest.bodyUint8Array(\n yield* apiRequest(\"POST\", path, \"application/json\", operation),\n encoded.body,\n encoded.contentType,\n );\n\n const deadline = Math.min(yield* deadlineAfter(timeoutMillis), outerDeadline ?? Infinity);\n\n return yield* within(\n Effect.scoped(\n execute(request, operation, \"unknown\").pipe(\n Effect.flatMap((response) => readJson(\"POST\", response, operation)),\n ),\n ),\n deadline,\n operation,\n \"unknown\",\n );\n },\n Trace.span(\"BrowserbaseClient.upload\", {\n attributes: { \"browser.operation\": \"provider-upload\", \"http.request.method\": \"POST\" },\n }),\n );\n\n const json = Effect.fnUntraced(\n function* (method: ClientMethod, path: string, body?: Schema.Json, outerDeadline?: number) {\n const deadline = Math.min(\n yield* deadlineAfter(requestTimeoutMillis),\n outerDeadline ?? Infinity,\n );\n\n for (let attempt = 0; ; attempt++) {\n const result = yield* within(\n Effect.scoped(jsonOnce(method, path, body)),\n deadline,\n // A request that times out is labelled like the same request failing any other way.\n method === \"GET\" ? \"provider-read\" : \"provider-mutation\",\n method === \"GET\" ? undefined : \"unknown\",\n ).pipe(\n Trace.span(\"BrowserbaseClient.request\", {\n attributes: {\n \"browser.operation\": method === \"GET\" ? \"provider-read\" : \"provider-mutation\",\n \"http.request.method\": traceMethod(method),\n },\n }),\n Effect.result,\n );\n\n if (result._tag === \"Success\") return result.success;\n const error = result.failure;\n\n const retryable =\n error.reason === \"transport\" ||\n error.reason === \"rate-limited\" ||\n (error.reason === \"provider\" && (error.status ?? 0) >= 500);\n\n if (method !== \"GET\" || !retryable || attempt >= 2) return yield* error;\n const delay = error.retryAfterMillis ?? (attempt + 1) * 150;\n\n if ((yield* nowMillis) + delay >= deadline) return yield* error;\n yield* Effect.sleep(delay);\n }\n },\n (effect, method) =>\n effect.pipe(\n Trace.span(\"BrowserbaseClient.json\", {\n attributes: {\n \"browser.operation\": method === \"GET\" ? \"provider-read\" : \"provider-mutation\",\n \"http.request.method\": traceMethod(method),\n },\n }),\n ),\n );\n\n const noContent = Effect.fnUntraced(\n function* (\n method: Exclude<ClientMethod, \"GET\">,\n path: string,\n body?: Schema.Json,\n outerDeadline?: number,\n ) {\n const operation = \"provider-mutation\";\n let request = yield* apiRequest(method, path, \"*/*\", operation);\n\n if (body !== undefined) {\n request = yield* HttpClientRequest.bodyJson(request, body).pipe(\n Effect.mapError(() =>\n ClientError.make({\n operation,\n reason: \"configuration\",\n outcome: \"undispatched\",\n }),\n ),\n );\n }\n\n const deadline = Math.min(\n yield* deadlineAfter(requestTimeoutMillis),\n outerDeadline ?? Infinity,\n );\n\n const response = yield* within(\n Effect.scoped(execute(request, operation, \"unknown\")),\n deadline,\n operation,\n \"unknown\",\n );\n\n if (![200, 202, 204].includes(response.status)) {\n return yield* statusError(\n method,\n response.status,\n operation,\n retryAfter(response.headers[\"retry-after\"], yield* Clock.currentTimeMillis),\n );\n }\n },\n (effect, method) =>\n effect.pipe(\n Trace.span(\"BrowserbaseClient.noContent\", {\n attributes: {\n \"browser.operation\": \"provider-mutation\",\n \"http.request.method\": traceMethod(method),\n },\n }),\n ),\n );\n\n const inspectBytes = Effect.fnUntraced(function* (\n response: HttpClientResponse.HttpClientResponse,\n operation: ClientError[\"operation\"],\n types: ReadonlyArray<string>,\n maximum: number,\n ) {\n if (response.status !== 200 && response.status !== 206) {\n return yield* statusError(\n \"GET\",\n response.status,\n operation,\n retryAfter(response.headers[\"retry-after\"], yield* Clock.currentTimeMillis),\n );\n }\n if (!types.includes(mediaType(response.headers[\"content-type\"]))) {\n return yield* ClientError.make({ operation, reason: \"content-type\" });\n }\n const length = response.headers[\"content-length\"];\n\n if (length !== undefined && (!/^\\d+$/.test(length) || Number(length) > maximum)) {\n return yield* ClientError.make({ operation, reason: \"limit\" });\n }\n let received = 0;\n\n return response.stream.pipe(\n Stream.mapError(() => ClientError.make({ operation, reason: \"transport\" })),\n Stream.mapEffect((chunk) =>\n Effect.suspend(() => {\n if (chunk.byteLength > maximum - received) {\n return Effect.fail(ClientError.make({ operation, reason: \"limit\" }));\n }\n received += chunk.byteLength;\n\n return Effect.succeed(new Uint8Array(chunk));\n }),\n ),\n );\n });\n\n const bytes = (\n path: string,\n maximum: number,\n types: ReadonlyArray<string>,\n timeoutMillis = requestTimeoutMillis,\n outerDeadline?: number,\n ) =>\n Stream.unwrap(\n Effect.gen(function* () {\n // A bounded authenticated read. Resource services relabel it with their own operation.\n const operation = \"provider-read\";\n\n if (\n !Number.isSafeInteger(maximum) ||\n maximum < 1 ||\n maximum > 2 ** 31 - 1 ||\n !Number.isSafeInteger(timeoutMillis) ||\n timeoutMillis < 1 ||\n timeoutMillis > 600_000\n ) {\n return yield* ClientError.make({ operation, reason: \"configuration\" });\n }\n const deadline = Math.min(yield* deadlineAfter(timeoutMillis), outerDeadline ?? Infinity);\n\n const request = yield* apiRequest(\n \"GET\",\n path,\n types[0] ?? \"application/octet-stream\",\n operation,\n );\n\n const response = yield* within(execute(request, operation), deadline, operation);\n\n const stream = yield* inspectBytes(response, operation, types, maximum);\n\n return Stream.transformPull(stream, (pull) =>\n Effect.succeed(within(pull, deadline, operation)),\n );\n }),\n ).pipe(\n Stream.scoped,\n Trace.stream(\"BrowserbaseClient.bytes\", {\n attributes: { \"browser.operation\": \"provider-read\", \"http.request.method\": \"GET\" },\n }),\n );\n\n const text = (path: string, maximum: number, types: ReadonlyArray<string>) =>\n collect(bytes(path, maximum, types), maximum, \"provider-read\").pipe(\n Effect.flatMap((body) =>\n Effect.try({\n try: () => new TextDecoder(\"utf-8\", { fatal: true }).decode(body),\n catch: () => ClientError.make({ operation: \"provider-read\", reason: \"malformed\" }),\n }),\n ),\n Effect.timeoutOrElse({\n duration: Duration.millis(requestTimeoutMillis),\n orElse: () =>\n Effect.fail(ClientError.make({ operation: \"provider-read\", reason: \"timeout\" })),\n }),\n Trace.span(\"BrowserbaseClient.text\", {\n attributes: { \"browser.operation\": \"provider-read\", \"http.request.method\": \"GET\" },\n }),\n );\n\n const validateMediaUrl = (value: string): boolean => {\n try {\n const url = new URL(value);\n\n return (\n url.protocol === \"https:\" &&\n !url.username &&\n !url.password &&\n !url.hash &&\n artifactOrigins.has(url.origin) &&\n value.length <= 16_384\n );\n } catch {\n return false;\n }\n };\n\n const media = (\n url: Redacted.Redacted<string>,\n maximum: number,\n types: ReadonlyArray<string>,\n timeoutMillis = 60_000,\n outerDeadline?: number,\n ) =>\n Stream.unwrap(\n Effect.gen(function* () {\n const value = Redacted.value(url);\n\n if (\n !validateMediaUrl(value) ||\n !Number.isSafeInteger(maximum) ||\n maximum < 1 ||\n maximum > 2 ** 31 - 1 ||\n !Number.isSafeInteger(timeoutMillis) ||\n timeoutMillis < 1 ||\n timeoutMillis > 600_000\n ) {\n return yield* ClientError.make({ operation: \"media-download\", reason: \"unsafe-url\" });\n }\n const deadline = Math.min(yield* deadlineAfter(timeoutMillis), outerDeadline ?? Infinity);\n\n const response = yield* within(\n execute(HttpClientRequest.get(value), \"media-download\"),\n deadline,\n \"media-download\",\n );\n\n const stream = yield* inspectBytes(response, \"media-download\", types, maximum);\n\n return Stream.transformPull(stream, (pull) =>\n Effect.succeed(within(pull, deadline, \"media-download\")),\n );\n }),\n ).pipe(\n Stream.scoped,\n Trace.stream(\"BrowserbaseClient.media\", {\n attributes: { \"browser.operation\": \"media-download\", \"http.request.method\": \"GET\" },\n }),\n );\n\n return {\n projectId: configured.projectId,\n json,\n noContent,\n upload,\n text,\n bytes,\n media,\n validateMediaUrl,\n };\n}, Trace.span(\"BrowserbaseClient.configure\"));\n","import { Config, Context, Effect, Layer, type Redacted, type Schema, type Stream } from \"effect\";\n\nimport type { ClientError } from \"./Errors.ts\";\nimport { makeTransport } from \"./internal/http/Transport.ts\";\n\n/** Account authority only. Launch recipes and browser-operation policy do not belong here. */\nexport interface ClientOptions {\n readonly projectId: string;\n readonly apiKey: Redacted.Redacted<string>;\n /** Exact HTTPS origins approved for credential-free media/artifact transfers. */\n readonly artifactOrigins?: ReadonlyArray<string>;\n readonly requestTimeoutMillis?: number;\n}\n\nexport type ClientMethod = \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n\n/** One bounded in-memory file part. A filesystem path is never a transport input. */\nexport interface MultipartFile {\n readonly field: string;\n readonly filename: string;\n readonly mediaType: string;\n readonly bytes: Uint8Array;\n}\n\n/** Upload bounds are caller-owned; an omitted timeout keeps the 60-second default. */\nexport interface UploadLimits {\n readonly maxBytes: number;\n readonly timeoutMillis?: number;\n}\n\n/**\n * One immutable Browserbase account and approved transport, shared by every resource Layer.\n * Constructing the Layer performs no request and never loads the native browser peer.\n */\nexport class BrowserbaseClient extends Context.Service<\n BrowserbaseClient,\n {\n readonly projectId: string;\n readonly json: (\n method: ClientMethod,\n path: string,\n body?: Schema.Json,\n outerDeadline?: number,\n ) => Effect.Effect<Schema.Json, ClientError>;\n readonly noContent: (\n method: Exclude<ClientMethod, \"GET\">,\n path: string,\n body?: Schema.Json,\n outerDeadline?: number,\n ) => Effect.Effect<void, ClientError>;\n /** One bounded multipart mutation. A lost reply stays unknown and is never retried. */\n readonly upload: (\n path: string,\n part: MultipartFile,\n limits: UploadLimits,\n outerDeadline?: number,\n ) => Effect.Effect<Schema.Json, ClientError>;\n readonly text: (\n path: string,\n maximum: number,\n types: ReadonlyArray<string>,\n ) => Effect.Effect<string, ClientError>;\n readonly bytes: (\n path: string,\n maximum: number,\n types: ReadonlyArray<string>,\n timeoutMillis?: number,\n outerDeadline?: number,\n ) => Stream.Stream<Uint8Array, ClientError>;\n readonly media: (\n url: Redacted.Redacted<string>,\n maximum: number,\n types: ReadonlyArray<string>,\n timeoutMillis?: number,\n outerDeadline?: number,\n ) => Stream.Stream<Uint8Array, ClientError>;\n readonly validateMediaUrl: (value: string) => boolean;\n }\n>()(\"effect-browserbase/Client\") {\n static layer(options: ClientOptions): Layer.Layer<BrowserbaseClient, ClientError> {\n return Layer.effect(\n BrowserbaseClient,\n makeTransport(options).pipe(\n Effect.map((client) => BrowserbaseClient.of(Object.freeze(client))),\n ),\n );\n }\n\n /**\n * Account authority from the application's `ConfigProvider` (the environment by default):\n * `BROWSERBASE_PROJECT_ID` and a redacted `BROWSERBASE_API_KEY`. Transport options stay\n * explicit. Configuration is read when the Layer is built, never at import.\n */\n static layerConfig(\n options: Omit<ClientOptions, \"projectId\" | \"apiKey\"> = {},\n ): Layer.Layer<BrowserbaseClient, ClientError | Config.ConfigError> {\n return Layer.unwrap(\n Effect.gen(function* () {\n const projectId = yield* Config.String(\"BROWSERBASE_PROJECT_ID\");\n const apiKey = yield* Config.Redacted(\"BROWSERBASE_API_KEY\");\n\n return BrowserbaseClient.layer({ ...options, projectId, apiKey });\n }),\n );\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { ClientError } from "./Errors.mjs";
|
|
2
|
-
import { Config, Context, Effect, Layer, Redacted, Schema, Stream } from "effect";
|
|
3
|
-
//#region src/Client.d.ts
|
|
4
|
-
/** Account authority only. Launch recipes and browser-operation policy do not belong here. */
|
|
5
|
-
interface ClientOptions {
|
|
6
|
-
readonly projectId: string;
|
|
7
|
-
readonly apiKey: Redacted.Redacted<string>;
|
|
8
|
-
/** Exact HTTPS origins approved for credential-free media/artifact transfers. */
|
|
9
|
-
readonly artifactOrigins?: ReadonlyArray<string>;
|
|
10
|
-
readonly requestTimeoutMillis?: number;
|
|
11
|
-
}
|
|
12
|
-
type ClientMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
13
|
-
/** One bounded in-memory file part. A filesystem path is never a transport input. */
|
|
14
|
-
interface MultipartFile {
|
|
15
|
-
readonly field: string;
|
|
16
|
-
readonly filename: string;
|
|
17
|
-
readonly mediaType: string;
|
|
18
|
-
readonly bytes: Uint8Array;
|
|
19
|
-
}
|
|
20
|
-
/** Upload bounds are caller-owned; an omitted timeout keeps the 60-second default. */
|
|
21
|
-
interface UploadLimits {
|
|
22
|
-
readonly maxBytes: number;
|
|
23
|
-
readonly timeoutMillis?: number;
|
|
24
|
-
}
|
|
25
|
-
declare const BrowserbaseClient_base: Context.ServiceClass<BrowserbaseClient, "effect-browserbase/Client", {
|
|
26
|
-
readonly projectId: string;
|
|
27
|
-
readonly json: (method: ClientMethod, path: string, body?: Schema.Json, outerDeadline?: number) => Effect.Effect<Schema.Json, ClientError>;
|
|
28
|
-
readonly noContent: (method: Exclude<ClientMethod, "GET">, path: string, body?: Schema.Json, outerDeadline?: number) => Effect.Effect<void, ClientError>;
|
|
29
|
-
/** One bounded multipart mutation. A lost reply stays unknown and is never retried. */
|
|
30
|
-
readonly upload: (path: string, part: MultipartFile, limits: UploadLimits, outerDeadline?: number) => Effect.Effect<Schema.Json, ClientError>;
|
|
31
|
-
readonly text: (path: string, maximum: number, types: ReadonlyArray<string>) => Effect.Effect<string, ClientError>;
|
|
32
|
-
readonly bytes: (path: string, maximum: number, types: ReadonlyArray<string>, timeoutMillis?: number, outerDeadline?: number) => Stream.Stream<Uint8Array, ClientError>;
|
|
33
|
-
readonly media: (url: Redacted.Redacted<string>, maximum: number, types: ReadonlyArray<string>, timeoutMillis?: number, outerDeadline?: number) => Stream.Stream<Uint8Array, ClientError>;
|
|
34
|
-
readonly validateMediaUrl: (value: string) => boolean;
|
|
35
|
-
}>;
|
|
36
|
-
/**
|
|
37
|
-
* One immutable Browserbase account and approved transport, shared by every resource Layer.
|
|
38
|
-
* Constructing the Layer performs no request and never loads the native browser peer.
|
|
39
|
-
*/
|
|
40
|
-
declare class BrowserbaseClient extends BrowserbaseClient_base {
|
|
41
|
-
static layer(options: ClientOptions): Layer.Layer<BrowserbaseClient, ClientError>;
|
|
42
|
-
/**
|
|
43
|
-
* Account authority from the application's `ConfigProvider` (the environment by default):
|
|
44
|
-
* `BROWSERBASE_PROJECT_ID` and a redacted `BROWSERBASE_API_KEY`. Transport options stay
|
|
45
|
-
* explicit. Configuration is read when the Layer is built, never at import.
|
|
46
|
-
*/
|
|
47
|
-
static layerConfig(options?: Omit<ClientOptions, "projectId" | "apiKey">): Layer.Layer<BrowserbaseClient, ClientError | Config.ConfigError>;
|
|
48
|
-
}
|
|
49
|
-
//#endregion
|
|
50
|
-
export { UploadLimits as a, MultipartFile as i, ClientMethod as n, ClientOptions as r, BrowserbaseClient as t };
|
|
51
|
-
export {};
|
|
52
|
-
//# sourceMappingURL=Client-B_f6bBLT.d.mts.map
|
package/dist/Client.d.mts
DELETED
package/dist/Client.mjs
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { SessionReference } from "./References.mjs";
|
|
2
|
-
import { SessionError } from "./Errors.mjs";
|
|
3
|
-
import { ProviderSession } from "./SessionData.mjs";
|
|
4
|
-
import { n as nowMillis, r as until, t as deadlineAfter } from "./Deadline-CrViaogr.mjs";
|
|
5
|
-
import { Effect, Redacted, Schema } from "effect";
|
|
6
|
-
import { BrowserError, Reasons } from "effect-browser/errors";
|
|
7
|
-
//#region src/internal/provider/Connection.ts
|
|
8
|
-
const Connection = Schema.Struct({
|
|
9
|
-
...ProviderSession.fields,
|
|
10
|
-
connectUrl: Schema.String.check(Schema.isMaxLength(16384))
|
|
11
|
-
});
|
|
12
|
-
/** A provider-issued endpoint is authority, not a persisted session identifier. */
|
|
13
|
-
const connectionUrl = Schema.String.check(Schema.isMaxLength(16384), Schema.makeFilter((value) => {
|
|
14
|
-
try {
|
|
15
|
-
const url = new URL(value);
|
|
16
|
-
return url.protocol === "wss:" && !url.username && !url.password && !url.port && !url.hash && url.hostname.endsWith(".browserbase.com");
|
|
17
|
-
} catch {
|
|
18
|
-
return false;
|
|
19
|
-
}
|
|
20
|
-
}));
|
|
21
|
-
/** The provider endpoint is validated before any custom routing gets to observe it. */
|
|
22
|
-
const validateConnection = (connection) => {
|
|
23
|
-
if (typeof connection !== "string" || connection.length > 16384 || !URL.canParse(connection)) throw BrowserError.make({
|
|
24
|
-
operation: "connect",
|
|
25
|
-
reason: Reasons.Malformed.make({}),
|
|
26
|
-
outcome: "undispatched"
|
|
27
|
-
});
|
|
28
|
-
if (!Schema.is(connectionUrl)(connection)) throw BrowserError.make({
|
|
29
|
-
operation: "connect",
|
|
30
|
-
reason: Reasons.UnsafeUrl.make({}),
|
|
31
|
-
outcome: "undispatched"
|
|
32
|
-
});
|
|
33
|
-
return connection;
|
|
34
|
-
};
|
|
35
|
-
const connectionAddress = Effect.fnUntraced(function* (client, sessions, reference, remainingMillis) {
|
|
36
|
-
const timeoutMillis = Math.min(6e5, remainingMillis);
|
|
37
|
-
const fail = (reason) => SessionError.make({
|
|
38
|
-
operation: "session-connect",
|
|
39
|
-
reason
|
|
40
|
-
});
|
|
41
|
-
const ref = yield* Schema.decodeEffect(SessionReference)(reference).pipe(Effect.mapError(() => fail("configuration")));
|
|
42
|
-
if (ref.projectId !== client.projectId) return yield* fail("authorization");
|
|
43
|
-
const deadline = yield* deadlineAfter(timeoutMillis);
|
|
44
|
-
yield* sessions.waitUntilRunning(ref, { timeoutMillis });
|
|
45
|
-
if ((yield* nowMillis) >= deadline) return yield* fail("timeout");
|
|
46
|
-
const raw = yield* until(client.json("GET", `/v1/sessions/${encodeURIComponent(ref.sessionId)}`, void 0, deadline), deadline, () => fail("timeout")).pipe(Effect.mapError((error) => fail(error.reason)));
|
|
47
|
-
const value = yield* Schema.decodeUnknownEffect(Connection)(raw).pipe(Effect.mapError(() => fail("malformed")));
|
|
48
|
-
if (value.id !== ref.sessionId || value.projectId !== ref.projectId) return yield* fail("malformed");
|
|
49
|
-
if (value.status !== "RUNNING") return yield* fail("expired");
|
|
50
|
-
const url = yield* Schema.decodeEffect(connectionUrl)(value.connectUrl).pipe(Effect.mapError(() => fail("unsafe-url")));
|
|
51
|
-
return Redacted.make(url);
|
|
52
|
-
});
|
|
53
|
-
//#endregion
|
|
54
|
-
export { validateConnection as n, connectionAddress as t };
|
|
55
|
-
|
|
56
|
-
//# sourceMappingURL=Connection-sxyxtwlk.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Connection-sxyxtwlk.mjs","names":[],"sources":["../src/internal/provider/Connection.ts"],"sourcesContent":["import { Effect, Redacted, Schema } from \"effect\";\nimport { BrowserError, Reasons } from \"effect-browser/errors\";\n\nimport type { BrowserbaseClient } from \"../../Client.ts\";\nimport { SessionError } from \"../../Errors.ts\";\nimport { SessionReference } from \"../../References.ts\";\nimport { ProviderSession } from \"../../SessionData.ts\";\nimport type { BrowserbaseSessions } from \"../../Sessions.ts\";\nimport { deadlineAfter, nowMillis, until } from \"../Deadline.ts\";\n\nconst Connection = Schema.Struct({\n ...ProviderSession.fields,\n connectUrl: Schema.String.check(Schema.isMaxLength(16384)),\n});\n\n/** A provider-issued endpoint is authority, not a persisted session identifier. */\nexport const connectionUrl = Schema.String.check(\n Schema.isMaxLength(16384),\n Schema.makeFilter((value) => {\n try {\n const url = new URL(value);\n\n return (\n url.protocol === \"wss:\" &&\n !url.username &&\n !url.password &&\n !url.port &&\n !url.hash &&\n url.hostname.endsWith(\".browserbase.com\")\n );\n } catch {\n return false;\n }\n }),\n);\n\n/** The provider endpoint is validated before any custom routing gets to observe it. */\nexport const validateConnection = (connection: unknown): string => {\n if (typeof connection !== \"string\" || connection.length > 16384 || !URL.canParse(connection))\n throw BrowserError.make({\n operation: \"connect\",\n reason: Reasons.Malformed.make({}),\n outcome: \"undispatched\",\n });\n if (!Schema.is(connectionUrl)(connection))\n throw BrowserError.make({\n operation: \"connect\",\n reason: Reasons.UnsafeUrl.make({}),\n outcome: \"undispatched\",\n });\n\n return connection;\n};\n\nexport const connectionAddress = Effect.fnUntraced(function* (\n client: BrowserbaseClient[\"Service\"],\n sessions: BrowserbaseSessions[\"Service\"],\n reference: SessionReference,\n remainingMillis: number,\n) {\n const timeoutMillis = Math.min(600_000, remainingMillis);\n\n const fail = (reason: SessionError[\"reason\"]) =>\n SessionError.make({ operation: \"session-connect\", reason });\n\n const ref = yield* Schema.decodeEffect(SessionReference)(reference).pipe(\n Effect.mapError(() => fail(\"configuration\")),\n );\n\n if (ref.projectId !== client.projectId) return yield* fail(\"authorization\");\n const deadline = yield* deadlineAfter(timeoutMillis);\n\n yield* sessions.waitUntilRunning(ref, { timeoutMillis });\n if ((yield* nowMillis) >= deadline) return yield* fail(\"timeout\");\n\n const raw = yield* until(\n client.json(\"GET\", `/v1/sessions/${encodeURIComponent(ref.sessionId)}`, undefined, deadline),\n deadline,\n () => fail(\"timeout\"),\n ).pipe(Effect.mapError((error) => fail(error.reason)));\n\n const value = yield* Schema.decodeUnknownEffect(Connection)(raw).pipe(\n Effect.mapError(() => fail(\"malformed\")),\n );\n\n if (value.id !== ref.sessionId || value.projectId !== ref.projectId)\n return yield* fail(\"malformed\");\n if (value.status !== \"RUNNING\") return yield* fail(\"expired\");\n\n const url = yield* Schema.decodeEffect(connectionUrl)(value.connectUrl).pipe(\n Effect.mapError(() => fail(\"unsafe-url\")),\n );\n\n return Redacted.make(url);\n});\n"],"mappings":";;;;;;;AAUA,MAAM,aAAa,OAAO,OAAO;CAC/B,GAAG,gBAAgB;CACnB,YAAY,OAAO,OAAO,MAAM,OAAO,YAAY,KAAK,CAAC;AAC3D,CAAC;;AAGD,MAAa,gBAAgB,OAAO,OAAO,MACzC,OAAO,YAAY,KAAK,GACxB,OAAO,YAAY,UAAU;CAC3B,IAAI;EACF,MAAM,MAAM,IAAI,IAAI,KAAK;EAEzB,OACE,IAAI,aAAa,UACjB,CAAC,IAAI,YACL,CAAC,IAAI,YACL,CAAC,IAAI,QACL,CAAC,IAAI,QACL,IAAI,SAAS,SAAS,kBAAkB;CAE5C,QAAQ;EACN,OAAO;CACT;AACF,CAAC,CACH;;AAGA,MAAa,sBAAsB,eAAgC;CACjE,IAAI,OAAO,eAAe,YAAY,WAAW,SAAS,SAAS,CAAC,IAAI,SAAS,UAAU,GACzF,MAAM,aAAa,KAAK;EACtB,WAAW;EACX,QAAQ,QAAQ,UAAU,KAAK,CAAC,CAAC;EACjC,SAAS;CACX,CAAC;CACH,IAAI,CAAC,OAAO,GAAG,aAAa,CAAC,CAAC,UAAU,GACtC,MAAM,aAAa,KAAK;EACtB,WAAW;EACX,QAAQ,QAAQ,UAAU,KAAK,CAAC,CAAC;EACjC,SAAS;CACX,CAAC;CAEH,OAAO;AACT;AAEA,MAAa,oBAAoB,OAAO,WAAW,WACjD,QACA,UACA,WACA,iBACA;CACA,MAAM,gBAAgB,KAAK,IAAI,KAAS,eAAe;CAEvD,MAAM,QAAQ,WACZ,aAAa,KAAK;EAAE,WAAW;EAAmB;CAAO,CAAC;CAE5D,MAAM,MAAM,OAAO,OAAO,aAAa,gBAAgB,CAAC,CAAC,SAAS,CAAC,CAAC,KAClE,OAAO,eAAe,KAAK,eAAe,CAAC,CAC7C;CAEA,IAAI,IAAI,cAAc,OAAO,WAAW,OAAO,OAAO,KAAK,eAAe;CAC1E,MAAM,WAAW,OAAO,cAAc,aAAa;CAEnD,OAAO,SAAS,iBAAiB,KAAK,EAAE,cAAc,CAAC;CACvD,KAAK,OAAO,cAAc,UAAU,OAAO,OAAO,KAAK,SAAS;CAEhE,MAAM,MAAM,OAAO,MACjB,OAAO,KAAK,OAAO,gBAAgB,mBAAmB,IAAI,SAAS,KAAK,KAAA,GAAW,QAAQ,GAC3F,gBACM,KAAK,SAAS,CACtB,CAAC,CAAC,KAAK,OAAO,UAAU,UAAU,KAAK,MAAM,MAAM,CAAC,CAAC;CAErD,MAAM,QAAQ,OAAO,OAAO,oBAAoB,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,KAC/D,OAAO,eAAe,KAAK,WAAW,CAAC,CACzC;CAEA,IAAI,MAAM,OAAO,IAAI,aAAa,MAAM,cAAc,IAAI,WACxD,OAAO,OAAO,KAAK,WAAW;CAChC,IAAI,MAAM,WAAW,WAAW,OAAO,OAAO,KAAK,SAAS;CAE5D,MAAM,MAAM,OAAO,OAAO,aAAa,aAAa,CAAC,CAAC,MAAM,UAAU,CAAC,CAAC,KACtE,OAAO,eAAe,KAAK,YAAY,CAAC,CAC1C;CAEA,OAAO,SAAS,KAAK,GAAG;AAC1B,CAAC"}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { n as ContextReference } from "./References-DOH3Wu44.mjs";
|
|
2
|
-
import { ContextError, SessionError } from "./Errors.mjs";
|
|
3
|
-
import { t as BrowserbaseSessions } from "./Sessions-oJEUmZth.mjs";
|
|
4
|
-
import { a as WriterLease, i as WriterAttemptFacts, n as ContextWriterPermit, o as WriterOptions, r as PersistenceEvidence, s as WriterSettlementFacts, t as ContextWriterBackend } from "./WriterFacts-BBJRDZYY.mjs";
|
|
5
|
-
import { Effect, Scope } from "effect";
|
|
6
|
-
//#region src/ContextCoordination.d.ts
|
|
7
|
-
/**
|
|
8
|
-
* Owns the backend lease, child browser scopes, and exact attempt evidence. The backend must
|
|
9
|
-
* handle uncertain distributed lease acquisition itself. It must persist quarantine facts;
|
|
10
|
-
* a local Scope closing is never permission to admit another remote writer. A writer that
|
|
11
|
-
* settles as anything but a release leaves its Context refused in this process until
|
|
12
|
-
* `reconcile` succeeds.
|
|
13
|
-
*/
|
|
14
|
-
export declare const withWriter: <A, E, R, LeaseE, LeaseR, VerifyE = never, VerifyR = never>(backend: ContextWriterBackend<LeaseE, LeaseR>, reference: ContextReference, use: (permit: ContextWriterPermit) => Effect.Effect<A, E, R>, options?: WriterOptions<A, VerifyE, VerifyR>) => Effect.Effect<A, E | LeaseE | VerifyE | ContextError, Exclude<R | LeaseR | VerifyR, Scope.Scope>>;
|
|
15
|
-
/**
|
|
16
|
-
* Lifts this process's quarantine on a Context once no writer it admitted can still write:
|
|
17
|
-
* the provider reports every session the quarantined writer recorded as terminal, and then
|
|
18
|
-
* the consumer's readback of the Context passes. The Context stays held throughout, so no
|
|
19
|
-
* writer is admitted against evidence still being gathered; a live writer is refused rather
|
|
20
|
-
* than waited for. An allocation whose outcome stayed unknown names no session to check, so
|
|
21
|
-
* its Context stays refused. Ending a session is the caller's explicit request; this only
|
|
22
|
-
* reads status. With no quarantine held here, only the readback runs. The backend keeps its
|
|
23
|
-
* own quarantine until the consumer reports this reconciliation to it.
|
|
24
|
-
*/
|
|
25
|
-
export declare const reconcile: <E, R>(reference: ContextReference, readback: Effect.Effect<void, E, R>) => Effect.Effect<void, E | ContextError | SessionError, BrowserbaseSessions | Exclude<R, Scope.Scope>>;
|
|
26
|
-
//#endregion
|
|
27
|
-
export { type ContextWriterBackend, type ContextWriterPermit, PersistenceEvidence, WriterAttemptFacts, type WriterLease, type WriterOptions, WriterSettlementFacts };
|
|
28
|
-
export {};
|
|
29
|
-
//# sourceMappingURL=ContextCoordination.d.mts.map
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { ContextReference } from "./References.mjs";
|
|
2
|
-
import { ContextError } from "./Errors.mjs";
|
|
3
|
-
import { r as span } from "./Client-BEC4Q8ZS.mjs";
|
|
4
|
-
import { isTerminalSessionStatus } from "./SessionData.mjs";
|
|
5
|
-
import { c as WriterSettlementFacts, i as makeContextWriterPermit, n as closeContextWriterPermit, o as PersistenceEvidence, r as isContextWriterBusy, s as WriterAttemptFacts, t as claimReconciliation } from "./ContextWriter-CiEma24z.mjs";
|
|
6
|
-
import { t as BrowserbaseSessions } from "./Sessions-D2H5m6rF.mjs";
|
|
7
|
-
import { Clock, Effect, Exit, Schema } from "effect";
|
|
8
|
-
//#region src/ContextCoordination.ts
|
|
9
|
-
const decodeReference = (reference, operation) => Schema.decodeEffect(ContextReference)(reference, { onExcessProperty: "error" }).pipe(Effect.mapError(() => ContextError.make({
|
|
10
|
-
operation,
|
|
11
|
-
reason: "configuration",
|
|
12
|
-
outcome: "undispatched"
|
|
13
|
-
})));
|
|
14
|
-
/**
|
|
15
|
-
* Owns the backend lease, child browser scopes, and exact attempt evidence. The backend must
|
|
16
|
-
* handle uncertain distributed lease acquisition itself. It must persist quarantine facts;
|
|
17
|
-
* a local Scope closing is never permission to admit another remote writer. A writer that
|
|
18
|
-
* settles as anything but a release leaves its Context refused in this process until
|
|
19
|
-
* `reconcile` succeeds.
|
|
20
|
-
*/
|
|
21
|
-
const withWriter = (backend, reference, use, options = {}) => Effect.scoped(Effect.uninterruptibleMask((restore) => Effect.gen(function* () {
|
|
22
|
-
const ref = yield* decodeReference(reference, "writer");
|
|
23
|
-
const timeout = options.settlementTimeoutMillis ?? 5e3;
|
|
24
|
-
if (!Number.isSafeInteger(timeout) || timeout < 1 || timeout > 6e4 || isContextWriterBusy(ref)) return yield* ContextError.make({
|
|
25
|
-
operation: "writer",
|
|
26
|
-
reason: isContextWriterBusy(ref) ? "active" : "configuration",
|
|
27
|
-
outcome: "undispatched"
|
|
28
|
-
});
|
|
29
|
-
const permit = yield* makeContextWriterPermit(ref);
|
|
30
|
-
const acquired = yield* restore(backend.acquire(ref)).pipe(span("BrowserbaseWriter.acquire"), Effect.exit);
|
|
31
|
-
if (Exit.isFailure(acquired)) {
|
|
32
|
-
closeContextWriterPermit(permit, true);
|
|
33
|
-
return yield* Effect.failCause(acquired.cause);
|
|
34
|
-
}
|
|
35
|
-
const lease = acquired.value;
|
|
36
|
-
const body = yield* restore(Effect.scoped(Effect.suspend(() => use(permit)))).pipe(span("BrowserbaseWriter.use"), Effect.exit);
|
|
37
|
-
if (Exit.isFailure(body)) yield* permit.quarantine;
|
|
38
|
-
let verification = Exit.void;
|
|
39
|
-
if (Exit.isSuccess(body) && options.verify !== void 0) {
|
|
40
|
-
verification = yield* restore(Effect.scoped(options.verify(body.value))).pipe(span("BrowserbaseWriter.readback"), Effect.exit);
|
|
41
|
-
if (Exit.isSuccess(verification)) verification = yield* permit.confirmReadback(yield* Clock.currentTimeMillis).pipe(Effect.exit);
|
|
42
|
-
else yield* permit.quarantine;
|
|
43
|
-
}
|
|
44
|
-
const facts = yield* permit.snapshot;
|
|
45
|
-
const settlement = yield* restore(lease.settle(facts)).pipe(Effect.timeoutOrElse({
|
|
46
|
-
duration: timeout,
|
|
47
|
-
orElse: () => Effect.fail(ContextError.make({
|
|
48
|
-
operation: "writer-settle",
|
|
49
|
-
reason: "timeout",
|
|
50
|
-
outcome: "unknown"
|
|
51
|
-
}))
|
|
52
|
-
}), span("BrowserbaseWriter.settle", { attributes: { "browser.writer.disposition": facts.disposition } }), Effect.exit);
|
|
53
|
-
if (Exit.isFailure(settlement)) yield* permit.quarantine;
|
|
54
|
-
closeContextWriterPermit(permit, Exit.isSuccess(settlement) && facts.disposition === "release");
|
|
55
|
-
if (Exit.isFailure(body)) {
|
|
56
|
-
if (Exit.isFailure(settlement)) yield* Effect.logError("Browserbase writer settlement remained unconfirmed");
|
|
57
|
-
return yield* Effect.failCause(body.cause);
|
|
58
|
-
}
|
|
59
|
-
if (Exit.isFailure(verification)) return yield* Effect.failCause(verification.cause);
|
|
60
|
-
if (Exit.isFailure(settlement)) return yield* Effect.failCause(settlement.cause);
|
|
61
|
-
return body.value;
|
|
62
|
-
}))).pipe(span("BrowserbaseWriter.withWriter"));
|
|
63
|
-
/**
|
|
64
|
-
* Lifts this process's quarantine on a Context once no writer it admitted can still write:
|
|
65
|
-
* the provider reports every session the quarantined writer recorded as terminal, and then
|
|
66
|
-
* the consumer's readback of the Context passes. The Context stays held throughout, so no
|
|
67
|
-
* writer is admitted against evidence still being gathered; a live writer is refused rather
|
|
68
|
-
* than waited for. An allocation whose outcome stayed unknown names no session to check, so
|
|
69
|
-
* its Context stays refused. Ending a session is the caller's explicit request; this only
|
|
70
|
-
* reads status. With no quarantine held here, only the readback runs. The backend keeps its
|
|
71
|
-
* own quarantine until the consumer reports this reconciliation to it.
|
|
72
|
-
*/
|
|
73
|
-
const reconcile = (reference, readback) => Effect.uninterruptibleMask((restore) => Effect.gen(function* () {
|
|
74
|
-
const ref = yield* decodeReference(reference, "writer-reconcile");
|
|
75
|
-
const sessions = yield* BrowserbaseSessions;
|
|
76
|
-
const claim = yield* claimReconciliation(ref);
|
|
77
|
-
const checked = yield* restore(Effect.gen(function* () {
|
|
78
|
-
for (const entry of yield* claim.attempts) {
|
|
79
|
-
if (entry.state === "rejected") continue;
|
|
80
|
-
if (!(entry.session !== void 0 && isTerminalSessionStatus((yield* sessions.retrieve(entry.session)).status))) return yield* ContextError.make({
|
|
81
|
-
operation: "writer-reconcile",
|
|
82
|
-
reason: "active",
|
|
83
|
-
outcome: "undispatched"
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
yield* Effect.scoped(readback).pipe(span("BrowserbaseWriter.readback"));
|
|
87
|
-
})).pipe(Effect.exit);
|
|
88
|
-
claim.finish(Exit.isSuccess(checked));
|
|
89
|
-
return yield* checked;
|
|
90
|
-
})).pipe(span("BrowserbaseWriter.reconcile"));
|
|
91
|
-
//#endregion
|
|
92
|
-
export { PersistenceEvidence, WriterAttemptFacts, WriterSettlementFacts, reconcile, withWriter };
|
|
93
|
-
|
|
94
|
-
//# sourceMappingURL=ContextCoordination.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ContextCoordination.mjs","names":["Trace.span"],"sources":["../src/ContextCoordination.ts"],"sourcesContent":["import { Clock, Effect, Exit, Schema, type Scope } from \"effect\";\n\nimport { ContextError, type SessionError } from \"./Errors.ts\";\nimport {\n claimReconciliation,\n makeContextWriterPermit,\n closeContextWriterPermit,\n isContextWriterBusy,\n} from \"./internal/session/ContextWriter.ts\";\nimport type {\n ContextWriterBackend,\n ContextWriterPermit,\n WriterOptions,\n} from \"./internal/session/WriterFacts.ts\";\nimport * as Trace from \"./internal/Trace.ts\";\nimport { ContextReference } from \"./References.ts\";\nimport { isTerminalSessionStatus } from \"./SessionData.ts\";\nimport { BrowserbaseSessions } from \"./Sessions.ts\";\n\nexport {\n PersistenceEvidence,\n WriterAttemptFacts,\n WriterSettlementFacts,\n type ContextWriterBackend,\n type ContextWriterPermit,\n type WriterLease,\n type WriterOptions,\n} from \"./internal/session/WriterFacts.ts\";\n\nconst decodeReference = (reference: ContextReference, operation: \"writer\" | \"writer-reconcile\") =>\n Schema.decodeEffect(ContextReference)(reference, { onExcessProperty: \"error\" }).pipe(\n Effect.mapError(() =>\n ContextError.make({ operation, reason: \"configuration\", outcome: \"undispatched\" }),\n ),\n );\n\n/**\n * Owns the backend lease, child browser scopes, and exact attempt evidence. The backend must\n * handle uncertain distributed lease acquisition itself. It must persist quarantine facts;\n * a local Scope closing is never permission to admit another remote writer. A writer that\n * settles as anything but a release leaves its Context refused in this process until\n * `reconcile` succeeds.\n */\nexport const withWriter = <A, E, R, LeaseE, LeaseR, VerifyE = never, VerifyR = never>(\n backend: ContextWriterBackend<LeaseE, LeaseR>,\n reference: ContextReference,\n use: (permit: ContextWriterPermit) => Effect.Effect<A, E, R>,\n options: WriterOptions<A, VerifyE, VerifyR> = {},\n): Effect.Effect<\n A,\n E | LeaseE | VerifyE | ContextError,\n Exclude<R | LeaseR | VerifyR, Scope.Scope>\n> =>\n Effect.scoped(\n Effect.uninterruptibleMask((restore) =>\n Effect.gen(function* () {\n const ref = yield* decodeReference(reference, \"writer\");\n\n const timeout = options.settlementTimeoutMillis ?? 5000;\n\n if (\n !Number.isSafeInteger(timeout) ||\n timeout < 1 ||\n timeout > 60000 ||\n isContextWriterBusy(ref)\n ) {\n return yield* ContextError.make({\n operation: \"writer\",\n reason: isContextWriterBusy(ref) ? \"active\" : \"configuration\",\n outcome: \"undispatched\",\n });\n }\n const permit = yield* makeContextWriterPermit(ref);\n\n const acquired = yield* restore(backend.acquire(ref)).pipe(\n Trace.span(\"BrowserbaseWriter.acquire\"),\n Effect.exit,\n );\n\n if (Exit.isFailure(acquired)) {\n // `use` never received the permit, so no allocation was attempted under it and this\n // process admitted no remote writer. What the failed acquisition left uncertain\n // remotely is the backend's to resolve.\n closeContextWriterPermit(permit, true);\n\n return yield* Effect.failCause(acquired.cause);\n }\n const lease = acquired.value;\n\n const body = yield* restore(Effect.scoped(Effect.suspend(() => use(permit)))).pipe(\n Trace.span(\"BrowserbaseWriter.use\"),\n Effect.exit,\n );\n\n // Every remote-resource finalizer in use() has run before any settlement/readback below.\n if (Exit.isFailure(body)) yield* permit.quarantine;\n let verification: Exit.Exit<void, VerifyE | ContextError> = Exit.void;\n\n if (Exit.isSuccess(body) && options.verify !== undefined) {\n verification = yield* restore(Effect.scoped(options.verify(body.value))).pipe(\n Trace.span(\"BrowserbaseWriter.readback\"),\n Effect.exit,\n );\n if (Exit.isSuccess(verification)) {\n verification = yield* permit\n .confirmReadback(yield* Clock.currentTimeMillis)\n .pipe(Effect.exit);\n } else yield* permit.quarantine;\n }\n const facts = yield* permit.snapshot;\n\n const settlement = yield* restore(lease.settle(facts)).pipe(\n Effect.timeoutOrElse({\n duration: timeout,\n orElse: () =>\n Effect.fail(\n ContextError.make({\n operation: \"writer-settle\",\n reason: \"timeout\",\n outcome: \"unknown\",\n }),\n ),\n }),\n Trace.span(\"BrowserbaseWriter.settle\", {\n attributes: { \"browser.writer.disposition\": facts.disposition },\n }),\n Effect.exit,\n );\n\n if (Exit.isFailure(settlement)) yield* permit.quarantine;\n closeContextWriterPermit(\n permit,\n Exit.isSuccess(settlement) && facts.disposition === \"release\",\n );\n // Preserve the primary cause; secondary failure is visible in the retained quarantine and\n // a content-free diagnostic. Never serialize arbitrary consumer/database error values.\n if (Exit.isFailure(body)) {\n if (Exit.isFailure(settlement))\n yield* Effect.logError(\"Browserbase writer settlement remained unconfirmed\");\n\n return yield* Effect.failCause(body.cause);\n }\n if (Exit.isFailure(verification)) return yield* Effect.failCause(verification.cause);\n if (Exit.isFailure(settlement)) return yield* Effect.failCause(settlement.cause);\n\n return body.value;\n }),\n ),\n ).pipe(Trace.span(\"BrowserbaseWriter.withWriter\"));\n\n/**\n * Lifts this process's quarantine on a Context once no writer it admitted can still write:\n * the provider reports every session the quarantined writer recorded as terminal, and then\n * the consumer's readback of the Context passes. The Context stays held throughout, so no\n * writer is admitted against evidence still being gathered; a live writer is refused rather\n * than waited for. An allocation whose outcome stayed unknown names no session to check, so\n * its Context stays refused. Ending a session is the caller's explicit request; this only\n * reads status. With no quarantine held here, only the readback runs. The backend keeps its\n * own quarantine until the consumer reports this reconciliation to it.\n */\nexport const reconcile = <E, R>(\n reference: ContextReference,\n readback: Effect.Effect<void, E, R>,\n): Effect.Effect<\n void,\n E | ContextError | SessionError,\n BrowserbaseSessions | Exclude<R, Scope.Scope>\n> =>\n Effect.uninterruptibleMask((restore) =>\n Effect.gen(function* () {\n const ref = yield* decodeReference(reference, \"writer-reconcile\");\n const sessions = yield* BrowserbaseSessions;\n const claim = yield* claimReconciliation(ref);\n\n const checked = yield* restore(\n Effect.gen(function* () {\n for (const entry of yield* claim.attempts) {\n // A rejected creation made no session. Any other attempt must name a session the\n // provider has ended, and the readback must come after every one of them.\n if (entry.state === \"rejected\") continue;\n\n const ended =\n entry.session !== undefined &&\n isTerminalSessionStatus((yield* sessions.retrieve(entry.session)).status);\n\n if (!ended) {\n return yield* ContextError.make({\n operation: \"writer-reconcile\",\n reason: \"active\",\n outcome: \"undispatched\",\n });\n }\n }\n yield* Effect.scoped(readback).pipe(Trace.span(\"BrowserbaseWriter.readback\"));\n }),\n ).pipe(Effect.exit);\n\n claim.finish(Exit.isSuccess(checked));\n\n return yield* checked;\n }),\n ).pipe(Trace.span(\"BrowserbaseWriter.reconcile\"));\n"],"mappings":"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"}
|
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
import { AllocationAttempt, ContextReference, SessionReference } from "./References.mjs";
|
|
2
|
-
import { ContextError } from "./Errors.mjs";
|
|
3
|
-
import { CleanupResult } from "./Cleanup.mjs";
|
|
4
|
-
import { Effect, Schema } from "effect";
|
|
5
|
-
//#region src/internal/session/WriterFacts.ts
|
|
6
|
-
/**
|
|
7
|
-
* The writer vocabulary both the public coordination entry point and the permit
|
|
8
|
-
* implementation need. Keeping it here leaves one direction of dependency:
|
|
9
|
-
* `ContextCoordination` and `ContextWriter` both read this module, never each other.
|
|
10
|
-
*/
|
|
11
|
-
const PersistenceEvidence = Schema.Union([
|
|
12
|
-
Schema.TaggedStruct("NotRequested", {}),
|
|
13
|
-
Schema.TaggedStruct("Unconfirmed", { reason: Schema.Literals([
|
|
14
|
-
"writer-active",
|
|
15
|
-
"writer-unknown",
|
|
16
|
-
"flush-unacknowledged"
|
|
17
|
-
]) }),
|
|
18
|
-
Schema.TaggedStruct("Observed", {
|
|
19
|
-
method: Schema.Literal("consumer-readback"),
|
|
20
|
-
observedAtMillis: Schema.Finite
|
|
21
|
-
})
|
|
22
|
-
]);
|
|
23
|
-
var WriterAttemptFacts = class extends Schema.Class("BrowserbaseWriterAttemptFacts")({
|
|
24
|
-
attempt: AllocationAttempt,
|
|
25
|
-
session: Schema.optionalKey(SessionReference),
|
|
26
|
-
state: Schema.Literals([
|
|
27
|
-
"admitted",
|
|
28
|
-
"rejected",
|
|
29
|
-
"unknown",
|
|
30
|
-
"terminal"
|
|
31
|
-
]),
|
|
32
|
-
cleanup: Schema.optionalKey(CleanupResult)
|
|
33
|
-
}) {};
|
|
34
|
-
var WriterSettlementFacts = class extends Schema.Class("BrowserbaseWriterSettlementFacts")({
|
|
35
|
-
reference: ContextReference,
|
|
36
|
-
attempts: Schema.Array(WriterAttemptFacts).check(Schema.isMaxLength(64)),
|
|
37
|
-
persistence: PersistenceEvidence,
|
|
38
|
-
disposition: Schema.Literals(["release", "quarantine"])
|
|
39
|
-
}) {};
|
|
40
|
-
//#endregion
|
|
41
|
-
//#region src/internal/session/ContextWriter.ts
|
|
42
|
-
const authentic = /* @__PURE__ */ new WeakMap();
|
|
43
|
-
const active = /* @__PURE__ */ new Map();
|
|
44
|
-
const key = (ref) => `${ref.projectId}/${ref.contextId}`;
|
|
45
|
-
const isContextWriterBusy = (ref) => active.has(key(ref));
|
|
46
|
-
const makeContextWriterPermit = (reference) => Effect.suspend(() => {
|
|
47
|
-
if (active.has(key(reference)) || active.size >= 2048) return Effect.fail(ContextError.make({
|
|
48
|
-
operation: "writer",
|
|
49
|
-
reason: "active",
|
|
50
|
-
outcome: "undispatched"
|
|
51
|
-
}));
|
|
52
|
-
const owned = Object.freeze(reference);
|
|
53
|
-
const attempts = /* @__PURE__ */ new Map();
|
|
54
|
-
let closed = false, quarantined = false;
|
|
55
|
-
let persistence = { _tag: "NotRequested" };
|
|
56
|
-
const unknown = () => {
|
|
57
|
-
quarantined = true;
|
|
58
|
-
persistence = {
|
|
59
|
-
_tag: "Unconfirmed",
|
|
60
|
-
reason: "writer-unknown"
|
|
61
|
-
};
|
|
62
|
-
};
|
|
63
|
-
const noActive = () => [...attempts.values()].every((entry) => entry.state === "rejected" || entry.state === "terminal");
|
|
64
|
-
const permit = {
|
|
65
|
-
_tag: "ContextWriterPermit",
|
|
66
|
-
reference: owned,
|
|
67
|
-
recordAttempt: (attempt) => Effect.suspend(() => {
|
|
68
|
-
if (closed || quarantined || !noActive() || attempt.projectId !== owned.projectId || attempts.size > 0 && persistence._tag === "Unconfirmed") return Effect.fail(ContextError.make({
|
|
69
|
-
operation: "writer-admit",
|
|
70
|
-
reason: "active",
|
|
71
|
-
outcome: "undispatched"
|
|
72
|
-
}));
|
|
73
|
-
if (attempts.has(attempt.attemptId) || attempts.size >= 64) return Effect.fail(ContextError.make({
|
|
74
|
-
operation: "writer-admit",
|
|
75
|
-
reason: "limit",
|
|
76
|
-
outcome: "undispatched"
|
|
77
|
-
}));
|
|
78
|
-
const copy = Object.freeze(attempt);
|
|
79
|
-
attempts.set(copy.attemptId, {
|
|
80
|
-
attempt: copy,
|
|
81
|
-
state: "admitted"
|
|
82
|
-
});
|
|
83
|
-
persistence = {
|
|
84
|
-
_tag: "Unconfirmed",
|
|
85
|
-
reason: "writer-active"
|
|
86
|
-
};
|
|
87
|
-
return Effect.void;
|
|
88
|
-
}),
|
|
89
|
-
recordSession: (attempt, session) => {
|
|
90
|
-
const record = attempts.get(attempt.attemptId);
|
|
91
|
-
if (record === void 0 || record.attempt !== attempt || session.projectId !== owned.projectId || record.session !== void 0 && record.session.sessionId !== session.sessionId) {
|
|
92
|
-
unknown();
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
record.session = Object.freeze(session);
|
|
96
|
-
},
|
|
97
|
-
rejected: (attempt) => {
|
|
98
|
-
const record = attempts.get(attempt.attemptId);
|
|
99
|
-
if (record === void 0 || record.attempt !== attempt || record.session !== void 0) {
|
|
100
|
-
unknown();
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
record.state = "rejected";
|
|
104
|
-
if ([...attempts.values()].every((item) => item.state === "rejected")) persistence = { _tag: "NotRequested" };
|
|
105
|
-
},
|
|
106
|
-
uncertain: (attempt) => {
|
|
107
|
-
const record = attempts.get(attempt.attemptId);
|
|
108
|
-
if (record !== void 0 && record.attempt === attempt) record.state = "unknown";
|
|
109
|
-
unknown();
|
|
110
|
-
},
|
|
111
|
-
completed: (attempt, cleanup) => {
|
|
112
|
-
const record = attempts.get(attempt.attemptId);
|
|
113
|
-
if (record === void 0 || record.attempt !== attempt || cleanup.ownership !== "owned" || record.session === void 0 || record.session.sessionId !== cleanup.reference.sessionId || cleanup.reference.projectId !== owned.projectId) {
|
|
114
|
-
unknown();
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
record.cleanup = cleanup;
|
|
118
|
-
if (cleanup.remote !== "confirmed") {
|
|
119
|
-
record.state = "unknown";
|
|
120
|
-
unknown();
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
record.state = "terminal";
|
|
124
|
-
if (cleanup.observedStatus !== "COMPLETED") {
|
|
125
|
-
unknown();
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
if (!quarantined) persistence = {
|
|
129
|
-
_tag: "Unconfirmed",
|
|
130
|
-
reason: "flush-unacknowledged"
|
|
131
|
-
};
|
|
132
|
-
},
|
|
133
|
-
confirmReadback: (atMillis) => Effect.suspend(() => {
|
|
134
|
-
if (closed || quarantined || !noActive() || !Number.isFinite(atMillis) || attempts.size === 0 || [...attempts.values()].some((entry) => entry.state === "terminal" && entry.cleanup?.observedStatus !== "COMPLETED")) return Effect.fail(ContextError.make({
|
|
135
|
-
operation: "writer-readback",
|
|
136
|
-
reason: "active",
|
|
137
|
-
outcome: "undispatched"
|
|
138
|
-
}));
|
|
139
|
-
persistence = {
|
|
140
|
-
_tag: "Observed",
|
|
141
|
-
method: "consumer-readback",
|
|
142
|
-
observedAtMillis: atMillis
|
|
143
|
-
};
|
|
144
|
-
return Effect.void;
|
|
145
|
-
}),
|
|
146
|
-
quarantine: Effect.sync(unknown),
|
|
147
|
-
snapshot: Effect.sync(() => WriterSettlementFacts.make({
|
|
148
|
-
reference: owned,
|
|
149
|
-
attempts: [...attempts.values()].map((entry) => WriterAttemptFacts.make({
|
|
150
|
-
attempt: entry.attempt,
|
|
151
|
-
state: entry.state,
|
|
152
|
-
...entry.session === void 0 ? {} : { session: entry.session },
|
|
153
|
-
...entry.cleanup === void 0 ? {} : { cleanup: entry.cleanup }
|
|
154
|
-
})),
|
|
155
|
-
persistence,
|
|
156
|
-
disposition: quarantined || !noActive() || persistence._tag === "Unconfirmed" ? "quarantine" : "release"
|
|
157
|
-
}))
|
|
158
|
-
};
|
|
159
|
-
Object.freeze(permit);
|
|
160
|
-
authentic.set(permit, permit);
|
|
161
|
-
active.set(key(owned), permit);
|
|
162
|
-
retirement.set(permit, (released) => {
|
|
163
|
-
closed = true;
|
|
164
|
-
if (active.get(key(owned)) !== permit) return;
|
|
165
|
-
if (released) active.delete(key(owned));
|
|
166
|
-
else active.set(key(owned), {
|
|
167
|
-
_tag: "Quarantined",
|
|
168
|
-
permit
|
|
169
|
-
});
|
|
170
|
-
});
|
|
171
|
-
return Effect.succeed(permit);
|
|
172
|
-
});
|
|
173
|
-
const retirement = /* @__PURE__ */ new WeakMap();
|
|
174
|
-
const closeContextWriterPermit = (permit, released) => retirement.get(permit)?.(released);
|
|
175
|
-
const claimReconciliation = (reference) => Effect.suspend(() => {
|
|
176
|
-
const held = active.get(key(reference));
|
|
177
|
-
if (held?._tag === "ContextWriterPermit" || held?._tag === "Reconciling" || held === void 0 && active.size >= 2048) return Effect.fail(ContextError.make({
|
|
178
|
-
operation: "writer-reconcile",
|
|
179
|
-
reason: "active",
|
|
180
|
-
outcome: "undispatched"
|
|
181
|
-
}));
|
|
182
|
-
const claim = { _tag: "Reconciling" };
|
|
183
|
-
active.set(key(reference), claim);
|
|
184
|
-
return Effect.succeed({
|
|
185
|
-
attempts: held === void 0 ? Effect.succeed([]) : held.permit.snapshot.pipe(Effect.map((facts) => facts.attempts)),
|
|
186
|
-
finish: (reconciled) => {
|
|
187
|
-
if (active.get(key(reference)) !== claim) return;
|
|
188
|
-
if (reconciled || held === void 0) active.delete(key(reference));
|
|
189
|
-
else active.set(key(reference), held);
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
});
|
|
193
|
-
const requireContextWriterPermit = (permit, reference) => Effect.suspend(() => {
|
|
194
|
-
const actual = authentic.get(permit);
|
|
195
|
-
return actual !== void 0 && active.get(key(reference)) === actual && actual.reference.contextId === reference.contextId && actual.reference.projectId === reference.projectId ? Effect.succeed(actual) : Effect.fail(ContextError.make({
|
|
196
|
-
operation: "writer-authority",
|
|
197
|
-
reason: "authorization",
|
|
198
|
-
outcome: "undispatched"
|
|
199
|
-
}));
|
|
200
|
-
});
|
|
201
|
-
//#endregion
|
|
202
|
-
export { requireContextWriterPermit as a, WriterSettlementFacts as c, makeContextWriterPermit as i, closeContextWriterPermit as n, PersistenceEvidence as o, isContextWriterBusy as r, WriterAttemptFacts as s, claimReconciliation as t };
|
|
203
|
-
|
|
204
|
-
//# sourceMappingURL=ContextWriter-CiEma24z.mjs.map
|