effect-browserbase 0.2.0-beta.8 → 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.
Files changed (155) hide show
  1. package/README.md +277 -315
  2. package/dist/Browserbase-CaPKwEY9.mjs +544 -0
  3. package/dist/Browserbase-CaPKwEY9.mjs.map +1 -0
  4. package/dist/Browserbase.d.mts +110 -0
  5. package/dist/Browserbase.mjs +3 -0
  6. package/dist/BrowserbaseClient-CtAQ2rg4.d.mts +195 -0
  7. package/dist/BrowserbaseClient.d.mts +2 -0
  8. package/dist/BrowserbaseClient.mjs +190 -0
  9. package/dist/BrowserbaseClient.mjs.map +1 -0
  10. package/dist/BrowserbaseError-D1EOrLNc.d.mts +79 -0
  11. package/dist/BrowserbaseError.d.mts +2 -0
  12. package/dist/BrowserbaseError.mjs +101 -0
  13. package/dist/BrowserbaseError.mjs.map +1 -0
  14. package/dist/ContextLease.d.mts +42 -0
  15. package/dist/ContextLease.mjs +80 -0
  16. package/dist/ContextLease.mjs.map +1 -0
  17. package/dist/index.d.mts +5 -27
  18. package/dist/index.mjs +5 -26
  19. package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
  20. package/dist/testing/index.d.mts +136 -0
  21. package/dist/testing/index.mjs +440 -0
  22. package/dist/testing/index.mjs.map +1 -0
  23. package/package.json +51 -121
  24. package/src/Browserbase.ts +729 -0
  25. package/src/BrowserbaseClient.ts +559 -0
  26. package/src/BrowserbaseError.ts +108 -0
  27. package/src/ContextLease.ts +118 -0
  28. package/src/index.ts +7 -0
  29. package/src/internal/captureConnection.ts +214 -0
  30. package/src/testing/BrowserbaseContract.ts +170 -0
  31. package/src/testing/TestBrowserbase.ts +509 -0
  32. package/src/testing/index.ts +7 -0
  33. package/dist/Account.d.mts +0 -32
  34. package/dist/Account.mjs +0 -36
  35. package/dist/Account.mjs.map +0 -1
  36. package/dist/Acquisition-BOABu_qJ.mjs +0 -244
  37. package/dist/Acquisition-BOABu_qJ.mjs.map +0 -1
  38. package/dist/Agents-CPaTOH_g.d.mts +0 -156
  39. package/dist/Agents.d.mts +0 -3
  40. package/dist/Agents.mjs +0 -292
  41. package/dist/Agents.mjs.map +0 -1
  42. package/dist/Allocation.d.mts +0 -97
  43. package/dist/Allocation.mjs +0 -27
  44. package/dist/Allocation.mjs.map +0 -1
  45. package/dist/Authorization-Ll5f_XNM.mjs +0 -12
  46. package/dist/Authorization-Ll5f_XNM.mjs.map +0 -1
  47. package/dist/Browser-ByrWJ0ss.mjs +0 -274
  48. package/dist/Browser-ByrWJ0ss.mjs.map +0 -1
  49. package/dist/Browser.d.mts +0 -83
  50. package/dist/Browser.mjs +0 -3
  51. package/dist/BrowserBinding.d.mts +0 -13
  52. package/dist/BrowserBinding.mjs +0 -31
  53. package/dist/BrowserBinding.mjs.map +0 -1
  54. package/dist/Certificates-D4NQmyeA.d.mts +0 -34
  55. package/dist/Certificates.d.mts +0 -3
  56. package/dist/Certificates.mjs +0 -85
  57. package/dist/Certificates.mjs.map +0 -1
  58. package/dist/Cleanup-DMTDBir8.d.mts +0 -23
  59. package/dist/Cleanup.d.mts +0 -3
  60. package/dist/Cleanup.mjs +0 -43
  61. package/dist/Cleanup.mjs.map +0 -1
  62. package/dist/Client-BEC4Q8ZS.mjs +0 -564
  63. package/dist/Client-BEC4Q8ZS.mjs.map +0 -1
  64. package/dist/Client-B_f6bBLT.d.mts +0 -52
  65. package/dist/Client.d.mts +0 -3
  66. package/dist/Client.mjs +0 -2
  67. package/dist/Connection-sxyxtwlk.mjs +0 -56
  68. package/dist/Connection-sxyxtwlk.mjs.map +0 -1
  69. package/dist/ContextCoordination.d.mts +0 -29
  70. package/dist/ContextCoordination.mjs +0 -94
  71. package/dist/ContextCoordination.mjs.map +0 -1
  72. package/dist/ContextWriter-CiEma24z.mjs +0 -204
  73. package/dist/ContextWriter-CiEma24z.mjs.map +0 -1
  74. package/dist/Contexts-DqdL7cyX.d.mts +0 -31
  75. package/dist/Contexts.d.mts +0 -3
  76. package/dist/Contexts.mjs +0 -97
  77. package/dist/Contexts.mjs.map +0 -1
  78. package/dist/Deadline-CrViaogr.mjs +0 -13
  79. package/dist/Deadline-CrViaogr.mjs.map +0 -1
  80. package/dist/Downloads-CX52GOFJ.d.mts +0 -43
  81. package/dist/Downloads.d.mts +0 -3
  82. package/dist/Downloads.mjs +0 -137
  83. package/dist/Downloads.mjs.map +0 -1
  84. package/dist/Errors.d.mts +0 -100
  85. package/dist/Errors.mjs +0 -194
  86. package/dist/Errors.mjs.map +0 -1
  87. package/dist/Extensions-BTUn9zhK.mjs +0 -231
  88. package/dist/Extensions-BTUn9zhK.mjs.map +0 -1
  89. package/dist/Extensions-DBXuVM1f.d.mts +0 -43
  90. package/dist/Extensions.d.mts +0 -3
  91. package/dist/Extensions.mjs +0 -2
  92. package/dist/Functions-CsKMMUuZ.d.mts +0 -226
  93. package/dist/Functions.d.mts +0 -3
  94. package/dist/Functions.mjs +0 -318
  95. package/dist/Functions.mjs.map +0 -1
  96. package/dist/Issued-DejqoMYL.mjs +0 -15
  97. package/dist/Issued-DejqoMYL.mjs.map +0 -1
  98. package/dist/Launch-cAdE2rrZ.mjs +0 -115
  99. package/dist/Launch-cAdE2rrZ.mjs.map +0 -1
  100. package/dist/Launch.d.mts +0 -127
  101. package/dist/Launch.mjs +0 -97
  102. package/dist/Launch.mjs.map +0 -1
  103. package/dist/PageFetch-CjAM_0DS.d.mts +0 -40
  104. package/dist/PageFetch.d.mts +0 -3
  105. package/dist/PageFetch.mjs +0 -59
  106. package/dist/PageFetch.mjs.map +0 -1
  107. package/dist/Projects-tm5bTDH0.d.mts +0 -38
  108. package/dist/Projects.d.mts +0 -3
  109. package/dist/Projects.mjs +0 -65
  110. package/dist/Projects.mjs.map +0 -1
  111. package/dist/Recordings-B9k5aODB.d.mts +0 -27
  112. package/dist/Recordings.d.mts +0 -3
  113. package/dist/Recordings.mjs +0 -144
  114. package/dist/Recordings.mjs.map +0 -1
  115. package/dist/References-DOH3Wu44.d.mts +0 -34
  116. package/dist/References.d.mts +0 -3
  117. package/dist/References.mjs +0 -33
  118. package/dist/References.mjs.map +0 -1
  119. package/dist/Replays-mV93WGtx.d.mts +0 -27
  120. package/dist/Replays.d.mts +0 -3
  121. package/dist/Replays.mjs +0 -107
  122. package/dist/Replays.mjs.map +0 -1
  123. package/dist/Resource-J7Kkk5mu.mjs +0 -54
  124. package/dist/Resource-J7Kkk5mu.mjs.map +0 -1
  125. package/dist/Search-B64e7g-h.d.mts +0 -37
  126. package/dist/Search.d.mts +0 -3
  127. package/dist/Search.mjs +0 -46
  128. package/dist/Search.mjs.map +0 -1
  129. package/dist/SessionData-5xYZDshJ.d.mts +0 -38
  130. package/dist/SessionData.d.mts +0 -3
  131. package/dist/SessionData.mjs +0 -48
  132. package/dist/SessionData.mjs.map +0 -1
  133. package/dist/Sessions-D2H5m6rF.mjs +0 -260
  134. package/dist/Sessions-D2H5m6rF.mjs.map +0 -1
  135. package/dist/Sessions-oJEUmZth.d.mts +0 -69
  136. package/dist/Sessions.d.mts +0 -4
  137. package/dist/Sessions.mjs +0 -3
  138. package/dist/Testing.d.mts +0 -119
  139. package/dist/Testing.mjs +0 -206
  140. package/dist/Testing.mjs.map +0 -1
  141. package/dist/TransferPolicy-DQ06i7SZ.mjs +0 -25
  142. package/dist/TransferPolicy-DQ06i7SZ.mjs.map +0 -1
  143. package/dist/Transfers-GVqzrDWl.d.mts +0 -89
  144. package/dist/Transfers.d.mts +0 -3
  145. package/dist/Transfers.mjs +0 -85
  146. package/dist/Transfers.mjs.map +0 -1
  147. package/dist/Uploads-C2_bACgv.d.mts +0 -28
  148. package/dist/Uploads.d.mts +0 -3
  149. package/dist/Uploads.mjs +0 -105
  150. package/dist/Uploads.mjs.map +0 -1
  151. package/dist/Webhooks-BoeRAxzG.d.mts +0 -59
  152. package/dist/Webhooks.d.mts +0 -3
  153. package/dist/Webhooks.mjs +0 -134
  154. package/dist/Webhooks.mjs.map +0 -1
  155. package/dist/WriterFacts-BBJRDZYY.d.mts +0 -54
@@ -1 +0,0 @@
1
- {"version":3,"file":"Certificates.mjs","names":["Trace.span"],"sources":["../src/Certificates.ts"],"sourcesContent":["import { Context, Effect, Layer, Schema } from \"effect\";\n\nimport { BrowserbaseClient } from \"./Client.ts\";\nimport { CertificateError } from \"./Errors.ts\";\nimport { resource } from \"./internal/http/Resource.ts\";\nimport * as Trace from \"./internal/Trace.ts\";\nimport { Identifier } from \"./References.ts\";\nimport { SafeFilename } from \"./Transfers.ts\";\n\nconst Timestamp = Schema.String.check(Schema.isMaxLength(64));\nconst MAX_CERTIFICATE_BYTES = 1024 * 1024;\n\n/** Select a certificate at launch with `provider.proxySettings.caCertificates: [certificateId]`. */\nexport class CertificateMetadata extends Schema.Class<CertificateMetadata>(\n \"BrowserbaseCertificateMetadata\",\n)({\n certificateId: Identifier,\n projectId: Identifier,\n createdAt: Timestamp,\n updatedAt: Timestamp,\n}) {}\n\nexport interface CertificateUpload {\n /** PEM or DER bytes of one CA certificate. */\n readonly bytes: Uint8Array;\n /** Portable basename sent with the part; defaults to `certificate.pem`. */\n readonly filename?: string;\n readonly maxBytes?: number;\n readonly timeoutMillis?: number;\n}\n\nconst Upload = Schema.Struct({\n filename: Schema.optionalKey(SafeFilename),\n maxBytes: Schema.optionalKey(\n Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: MAX_CERTIFICATE_BYTES })),\n ),\n timeoutMillis: Schema.optionalKey(\n Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 600_000 })),\n ),\n});\n\nconst ProviderCertificate = Schema.Struct({\n id: Identifier,\n projectId: Identifier,\n createdAt: Timestamp,\n updatedAt: Timestamp,\n});\n\n/** Proxy CA certificates. Registration is one bounded multipart mutation, never retried. */\nexport class BrowserbaseCertificates extends Context.Service<\n BrowserbaseCertificates,\n {\n readonly create: (\n upload: CertificateUpload,\n ) => Effect.Effect<CertificateMetadata, CertificateError>;\n readonly list: Effect.Effect<ReadonlyArray<CertificateMetadata>, CertificateError>;\n readonly retrieve: (\n certificateId: string,\n ) => Effect.Effect<CertificateMetadata, CertificateError>;\n readonly delete: (certificateId: string) => Effect.Effect<void, CertificateError>;\n }\n>()(\"effect-browserbase/Certificates\") {\n static readonly layer: Layer.Layer<BrowserbaseCertificates, never, BrowserbaseClient> =\n Layer.effect(\n BrowserbaseCertificates,\n Effect.gen(function* () {\n const client = yield* BrowserbaseClient;\n const api = resource<CertificateError>(client, (failure) => CertificateError.make(failure));\n\n const own = (operation: CertificateError[\"operation\"], mutation: boolean) =>\n Effect.fnUntraced(function* (value: typeof ProviderCertificate.Type) {\n if (value.projectId !== client.projectId)\n return yield* api.malformed(operation, mutation);\n\n const { id, ...rest } = value;\n\n return CertificateMetadata.make({ certificateId: id, ...rest });\n });\n\n const create = Effect.fnUntraced(function* (upload: CertificateUpload) {\n const { bytes, ...options } = upload;\n const value = yield* api.input(Upload, options, \"certificate-create\");\n const owned = new Uint8Array(bytes);\n\n const raw = yield* client\n .upload(\n \"/v1/certificates\",\n {\n field: \"file\",\n filename: value.filename ?? \"certificate.pem\",\n mediaType: \"application/x-pem-file\",\n bytes: owned,\n },\n {\n maxBytes: value.maxBytes ?? 64 * 1024,\n ...(value.timeoutMillis === undefined\n ? {}\n : { timeoutMillis: value.timeoutMillis }),\n },\n )\n .pipe(Effect.mapError(api.fromClient(\"certificate-create\")));\n\n const created = yield* Schema.decodeUnknownEffect(ProviderCertificate)(raw).pipe(\n Effect.mapError(() => api.malformed(\"certificate-create\", true)),\n );\n\n return yield* own(\"certificate-create\", true)(created);\n }, Trace.span(\"BrowserbaseCertificates.create\"));\n\n const list = api\n .request(\n \"GET\",\n \"/v1/certificates\",\n Schema.Array(ProviderCertificate).check(Schema.isMaxLength(1024)),\n \"certificate-list\",\n )\n .pipe(\n Effect.flatMap(Effect.forEach(own(\"certificate-list\", false))),\n Trace.span(\"BrowserbaseCertificates.list\"),\n );\n\n const retrieve = Effect.fnUntraced(function* (certificateId: string) {\n const id = yield* api.input(Identifier, certificateId, \"certificate-retrieve\");\n\n const value = yield* api.request(\n \"GET\",\n `/v1/certificates/${api.segment(id)}`,\n ProviderCertificate,\n \"certificate-retrieve\",\n );\n\n if (value.id !== id) return yield* api.malformed(\"certificate-retrieve\", false);\n\n return yield* own(\"certificate-retrieve\", false)(value);\n }, Trace.span(\"BrowserbaseCertificates.retrieve\"));\n\n const remove = Effect.fnUntraced(function* (certificateId: string) {\n const id = yield* api.input(Identifier, certificateId, \"certificate-delete\");\n\n yield* api.remove(`/v1/certificates/${api.segment(id)}`, \"certificate-delete\");\n }, Trace.span(\"BrowserbaseCertificates.delete\"));\n\n return BrowserbaseCertificates.of({ create, list, retrieve, delete: remove });\n }),\n );\n}\n"],"mappings":"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"}
@@ -1,23 +0,0 @@
1
- import { a as SessionReference } from "./References-DOH3Wu44.mjs";
2
- import { Schema } from "effect";
3
- //#region src/Cleanup.d.ts
4
- declare const CleanupIssue_base: Schema.Class<CleanupIssue, Schema.Struct<{
5
- readonly step: Schema.Literals<readonly ["fence", "capture", "initialization", "disconnect", "release", "status"]>;
6
- readonly reason: Schema.Literals<readonly ["timeout", "failed", "interrupted"]>;
7
- }>, {}>;
8
- declare class CleanupIssue extends CleanupIssue_base {}
9
- declare const CleanupResult_base: Schema.Class<CleanupResult, Schema.Struct<{
10
- readonly reference: typeof SessionReference;
11
- readonly ownership: Schema.Literals<readonly ["owned", "borrowed"]>;
12
- readonly releaseRequested: Schema.Boolean;
13
- readonly remote: Schema.Literals<readonly ["confirmed", "pending", "unknown", "not-owned"]>;
14
- readonly local: Schema.Literals<readonly ["closed", "failed", "not-connected", "pending"]>;
15
- readonly observedStatus: Schema.optionalKey<Schema.Literals<readonly ["PENDING", "RUNNING", "ERROR", "TIMED_OUT", "COMPLETED"]>>;
16
- readonly issues: Schema.$Array<typeof CleanupIssue>;
17
- }>, {}>;
18
- /** Local disconnection, release acknowledgement, and terminal observation are separate facts. */
19
- declare class CleanupResult extends CleanupResult_base {}
20
- //#endregion
21
- export { CleanupResult as n, CleanupIssue as t };
22
- export {};
23
- //# sourceMappingURL=Cleanup-DMTDBir8.d.mts.map
@@ -1,3 +0,0 @@
1
- import { n as CleanupResult, t as CleanupIssue } from "./Cleanup-DMTDBir8.mjs";
2
- export { CleanupIssue, CleanupResult };
3
- export {};
package/dist/Cleanup.mjs DELETED
@@ -1,43 +0,0 @@
1
- import { SessionReference } from "./References.mjs";
2
- import { SessionStatus } from "./SessionData.mjs";
3
- import { Schema } from "effect";
4
- //#region src/Cleanup.ts
5
- var CleanupIssue = class extends Schema.Class("BrowserbaseCleanupIssue")({
6
- step: Schema.Literals([
7
- "fence",
8
- "capture",
9
- "initialization",
10
- "disconnect",
11
- "release",
12
- "status"
13
- ]),
14
- reason: Schema.Literals([
15
- "timeout",
16
- "failed",
17
- "interrupted"
18
- ])
19
- }) {};
20
- /** Local disconnection, release acknowledgement, and terminal observation are separate facts. */
21
- var CleanupResult = class extends Schema.Class("BrowserbaseCleanupResult")({
22
- reference: SessionReference,
23
- ownership: Schema.Literals(["owned", "borrowed"]),
24
- releaseRequested: Schema.Boolean,
25
- remote: Schema.Literals([
26
- "confirmed",
27
- "pending",
28
- "unknown",
29
- "not-owned"
30
- ]),
31
- local: Schema.Literals([
32
- "closed",
33
- "failed",
34
- "not-connected",
35
- "pending"
36
- ]),
37
- observedStatus: Schema.optionalKey(SessionStatus),
38
- issues: Schema.Array(CleanupIssue).check(Schema.isMaxLength(64))
39
- }) {};
40
- //#endregion
41
- export { CleanupIssue, CleanupResult };
42
-
43
- //# sourceMappingURL=Cleanup.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Cleanup.mjs","names":[],"sources":["../src/Cleanup.ts"],"sourcesContent":["import { Schema } from \"effect\";\n\nimport { SessionReference } from \"./References.ts\";\nimport { SessionStatus } from \"./SessionData.ts\";\n\nexport class CleanupIssue extends Schema.Class<CleanupIssue>(\"BrowserbaseCleanupIssue\")({\n step: Schema.Literals([\"fence\", \"capture\", \"initialization\", \"disconnect\", \"release\", \"status\"]),\n reason: Schema.Literals([\"timeout\", \"failed\", \"interrupted\"]),\n}) {}\n\n/** Local disconnection, release acknowledgement, and terminal observation are separate facts. */\nexport class CleanupResult extends Schema.Class<CleanupResult>(\"BrowserbaseCleanupResult\")({\n reference: SessionReference,\n ownership: Schema.Literals([\"owned\", \"borrowed\"]),\n releaseRequested: Schema.Boolean,\n remote: Schema.Literals([\"confirmed\", \"pending\", \"unknown\", \"not-owned\"]),\n local: Schema.Literals([\"closed\", \"failed\", \"not-connected\", \"pending\"]),\n observedStatus: Schema.optionalKey(SessionStatus),\n issues: Schema.Array(CleanupIssue).check(Schema.isMaxLength(64)),\n}) {}\n"],"mappings":";;;;AAKA,IAAa,eAAb,cAAkC,OAAO,MAAoB,yBAAyB,CAAC,CAAC;CACtF,MAAM,OAAO,SAAS;EAAC;EAAS;EAAW;EAAkB;EAAc;EAAW;CAAQ,CAAC;CAC/F,QAAQ,OAAO,SAAS;EAAC;EAAW;EAAU;CAAa,CAAC;AAC9D,CAAC,CAAC,CAAC,CAAC;;AAGJ,IAAa,gBAAb,cAAmC,OAAO,MAAqB,0BAA0B,CAAC,CAAC;CACzF,WAAW;CACX,WAAW,OAAO,SAAS,CAAC,SAAS,UAAU,CAAC;CAChD,kBAAkB,OAAO;CACzB,QAAQ,OAAO,SAAS;EAAC;EAAa;EAAW;EAAW;CAAW,CAAC;CACxE,OAAO,OAAO,SAAS;EAAC;EAAU;EAAU;EAAiB;CAAS,CAAC;CACvE,gBAAgB,OAAO,YAAY,aAAa;CAChD,QAAQ,OAAO,MAAM,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,EAAE,CAAC;AACjE,CAAC,CAAC,CAAC,CAAC"}
@@ -1,564 +0,0 @@
1
- import { Identifier } from "./References.mjs";
2
- import { AllocationError, ArtifactError, CertificateError, ClientError, ContextError, ExtensionError, FileError, PlatformError, ProjectError, SessionError } from "./Errors.mjs";
3
- import { SafeFilename } from "./Transfers.mjs";
4
- import { Cause, Clock, Config, Context, Duration, Effect, Exit, Layer, Option, Random, Redacted, References, Schema, Stream, Tracer } from "effect";
5
- import { FetchHttpClient, HttpClient, HttpClientRequest } from "effect/unstable/http";
6
- //#region src/internal/Trace.ts
7
- const Failure = Schema.Union([
8
- AllocationError,
9
- ArtifactError,
10
- CertificateError,
11
- ClientError,
12
- ContextError,
13
- ExtensionError,
14
- FileError,
15
- PlatformError,
16
- ProjectError,
17
- SessionError
18
- ]);
19
- /** Causality crosses ownership boundaries as ids and sampling, never a live caller context. */
20
- const capture = Effect.gen(function* () {
21
- const current = yield* Effect.serviceOption(Tracer.ParentSpan);
22
- const enabled = yield* References.TracerEnabled;
23
- return yield* Effect.sync(() => {
24
- try {
25
- let parent = Option.getOrUndefined(current);
26
- while (parent !== void 0 && Context.get(parent.annotations, Tracer.DisablePropagation)) parent = parent._tag === "Span" ? Option.getOrUndefined(parent.parent) : void 0;
27
- return {
28
- enabled,
29
- parent: parent === void 0 ? void 0 : Object.freeze(Tracer.externalSpan({
30
- traceId: parent.traceId,
31
- spanId: parent.spanId,
32
- sampled: parent.sampled
33
- }))
34
- };
35
- } catch {
36
- return {
37
- enabled: false,
38
- parent: void 0
39
- };
40
- }
41
- });
42
- });
43
- /** Only finite, library-owned facts are passed here; exporter pressure loses telemetry only. */
44
- const annotate = (attributes) => Effect.gen(function* () {
45
- if (!(yield* References.TracerEnabled)) return;
46
- const current = yield* Effect.serviceOption(Tracer.ParentSpan);
47
- if (Option.isNone(current) || current.value._tag !== "Span") return;
48
- const span = current.value;
49
- yield* Effect.sync(() => {
50
- try {
51
- for (const [key, value] of Object.entries(attributes)) span.attribute(key, value);
52
- } catch {}
53
- });
54
- });
55
- /**
56
- * Library spans export neither successful values nor original causes/stacks. Tracer failures
57
- * cannot suppress dispatch or alter its result. Sampling metadata is available in annotations
58
- * at creation: rc.117 applies SpanOptions.attributes only after Tracer.span has returned.
59
- */
60
- const start = Effect.fnUntraced(function* (name, options = {}) {
61
- const identity = yield* capture;
62
- if (!identity.enabled) return void 0;
63
- const clock = yield* Clock.Clock;
64
- const timing = yield* References.TracerTimingEnabled;
65
- const attributes = options.attributes ?? {};
66
- const parent = options.parent ?? (options.root === true ? void 0 : identity.parent);
67
- const created = yield* Effect.makeSpan(name, {
68
- ...options,
69
- attributes: void 0,
70
- parent,
71
- root: options.root ?? parent === void 0,
72
- annotations: Context.make(References.TracerSpanAnnotations, attributes)
73
- }).pipe(Effect.provideService(References.TracerSpanAnnotations, {}), Effect.provideService(References.TracerSpanLinks, []), Effect.exit);
74
- if (Exit.isFailure(created)) return void 0;
75
- return yield* Effect.sync(() => {
76
- const span = created.value;
77
- let ended = false;
78
- try {
79
- for (const [key, value] of Object.entries(attributes)) span.attribute(key, value);
80
- } catch {}
81
- return {
82
- span,
83
- end: (exit, extra = {}) => {
84
- if (ended) return;
85
- ended = true;
86
- const interrupted = Exit.isFailure(exit) && Cause.hasInterruptsOnly(exit.cause);
87
- try {
88
- const failure = Exit.isFailure(exit) ? Option.getOrUndefined(Cause.findErrorOption(exit.cause)) : void 0;
89
- const known = Schema.is(Failure)(failure) ? failure : void 0;
90
- for (const [key, value] of Object.entries(extra)) span.attribute(key, value);
91
- span.attribute("browser.status", Exit.isSuccess(exit) ? "success" : interrupted ? "interrupted" : "failure");
92
- if (known !== void 0) {
93
- span.attribute("browser.reason", known.reason);
94
- if ("outcome" in known && known.outcome !== void 0) span.attribute("browser.outcome", known.outcome);
95
- }
96
- } catch {}
97
- try {
98
- span.end(timing ? clock.currentTimeNanosUnsafe() : 0n, Exit.isSuccess(exit) ? Exit.void : Exit.fail(interrupted ? "Operation interrupted" : "Operation failed"));
99
- } catch {}
100
- }
101
- };
102
- });
103
- });
104
- const span = (name, options = {}) => (effect) => Effect.uninterruptibleMask((restore) => start(name, options).pipe(Effect.flatMap((started) => started === void 0 ? restore(effect) : restore(effect).pipe(Effect.provideService(Tracer.ParentSpan, started.span), Effect.onExit((exit) => Effect.sync(() => started.end(exit)))))));
105
- /** One span per consumption; end after setup, pulls and the original channel scope's finalizers. */
106
- const stream = (name, options = {}) => (source) => Stream.suspend(() => {
107
- let terminal;
108
- return Stream.unwrap(Effect.uninterruptible(start(name, options).pipe(Effect.flatMap((value) => {
109
- return value === void 0 ? Effect.succeed(source) : Effect.addFinalizer((exit) => Effect.sync(() => value.end(terminal ?? exit))).pipe(Effect.as(source.pipe(Stream.provideService(Tracer.ParentSpan, value.span))));
110
- })))).pipe(Stream.onExit((exit) => Effect.sync(() => {
111
- terminal = exit;
112
- })));
113
- });
114
- //#endregion
115
- //#region src/internal/http/Multipart.ts
116
- const FIELD = /^[a-z][a-z0-9_]{0,31}$/;
117
- const MEDIA_TYPE = /^[a-z0-9][a-z0-9!#$&^_+.-]{0,63}\/[a-z0-9][a-z0-9!#$&^_+.-]{0,63}$/;
118
- const PRINTABLE_ASCII = /^[\x20-\x7e]+$/;
119
- const isSafeFilename = Schema.is(SafeFilename);
120
- /** Quoting is only safe for a portable, printable, quote-free basename. */
121
- const quotable = (value) => isSafeFilename(value) && PRINTABLE_ASCII.test(value) && !value.includes("\"");
122
- /**
123
- * Sixteen bytes from the fiber's `Random`. A boundary needs no secrecy: the encoder checks that
124
- * the content does not contain it, and draws another if it does.
125
- */
126
- const randomBoundary = Effect.map(Effect.all(Array.from({ length: 16 }, () => Random.nextIntBetween(0, 255))), (bytes) => `effect-agent-browserbase-${bytes.map((byte) => byte.toString(16).padStart(2, "0")).join("")}`);
127
- const contains = (haystack, needle) => {
128
- const first = needle[0];
129
- if (first === void 0 || needle.length > haystack.length) return false;
130
- outer: for (let i = 0; i <= haystack.length - needle.length; i++) {
131
- if (haystack[i] !== first) continue;
132
- for (let j = 1; j < needle.length; j++) {
133
- const expected = needle[j];
134
- if (expected === void 0 || haystack[i + j] !== expected) continue outer;
135
- }
136
- return true;
137
- }
138
- return false;
139
- };
140
- /**
141
- * A deliberately small RFC 7578 encoder: one file part, an ASCII-quotable name and a
142
- * delimiter proven absent from the content. It performs no filesystem or stream work.
143
- */
144
- const encodeFilePart = Effect.fnUntraced(function* (part, maxBytes, boundaries = randomBoundary) {
145
- if (!FIELD.test(part.field) || !quotable(part.filename) || !MEDIA_TYPE.test(part.mediaType) || !Number.isSafeInteger(maxBytes) || maxBytes < 1 || maxBytes > 2 ** 31 - 1) return {
146
- _tag: "Rejected",
147
- reason: "configuration"
148
- };
149
- if (part.bytes.byteLength > maxBytes) return {
150
- _tag: "Rejected",
151
- reason: "limit"
152
- };
153
- const encoder = new TextEncoder();
154
- for (let attempt = 0; attempt < 4; attempt++) {
155
- const boundary = yield* boundaries;
156
- if (!/^[A-Za-z0-9-]{1,70}$/.test(boundary)) continue;
157
- const delimiter = encoder.encode(boundary);
158
- if (contains(part.bytes, delimiter)) continue;
159
- const head = encoder.encode(`--${boundary}\r\nContent-Disposition: form-data; name="${part.field}"; filename="${part.filename}"\r\nContent-Type: ${part.mediaType}\r\n\r\n`);
160
- const tail = encoder.encode(`\r\n--${boundary}--\r\n`);
161
- const body = new Uint8Array(head.byteLength + part.bytes.byteLength + tail.byteLength);
162
- body.set(head, 0);
163
- body.set(part.bytes, head.byteLength);
164
- body.set(tail, head.byteLength + part.bytes.byteLength);
165
- return {
166
- _tag: "Encoded",
167
- contentType: `multipart/form-data; boundary=${boundary}`,
168
- body
169
- };
170
- }
171
- return {
172
- _tag: "Rejected",
173
- reason: "configuration"
174
- };
175
- });
176
- //#endregion
177
- //#region src/internal/http/Transport.ts
178
- const API_ORIGIN = "https://api.browserbase.com";
179
- const MAX_JSON_BYTES = 1048576;
180
- const MAX_JSON_DEPTH = 64;
181
- const traceMethod = (method) => [
182
- "GET",
183
- "POST",
184
- "PUT",
185
- "PATCH",
186
- "DELETE"
187
- ].includes(method) ? method : "invalid";
188
- const Options = Schema.Struct({
189
- projectId: Identifier,
190
- apiKey: Schema.Redacted(Schema.NonEmptyString.check(Schema.isMaxLength(8192), Schema.isPattern(/^[\x21-\x7e]+$/))),
191
- artifactOrigins: Schema.optionalKey(Schema.Array(Schema.String.check(Schema.isMaxLength(8192))).check(Schema.isMaxLength(32), Schema.isUnique())),
192
- requestTimeoutMillis: Schema.optionalKey(Schema.Int.check(Schema.isBetween({
193
- minimum: 1,
194
- maximum: 6e4
195
- })))
196
- });
197
- const nowMillis = Clock.monotonicTimeNanos.pipe(Effect.map((value) => Number(value) / 1e6));
198
- const deadlineAfter = (millis) => nowMillis.pipe(Effect.map((now) => now + millis));
199
- const within = (effect, deadline, operation, outcome) => Effect.suspend(() => nowMillis.pipe(Effect.flatMap((now) => {
200
- const remaining = deadline - now;
201
- const timeout = () => Effect.fail(ClientError.make({
202
- operation,
203
- reason: "timeout",
204
- ...outcome === void 0 ? {} : { outcome }
205
- }));
206
- return remaining <= 0 ? timeout() : effect.pipe(Effect.timeoutOrElse({
207
- duration: Duration.millis(remaining),
208
- orElse: timeout
209
- }));
210
- })));
211
- const withinJsonDepth = (text) => {
212
- let depth = 0;
213
- let quoted = false;
214
- let escaped = false;
215
- for (const character of text) if (quoted) {
216
- if (escaped) escaped = false;
217
- else if (character === "\\") escaped = true;
218
- else if (character === "\"") quoted = false;
219
- } else if (character === "\"") quoted = true;
220
- else if (character === "{" || character === "[") {
221
- if (++depth > MAX_JSON_DEPTH) return false;
222
- } else if (character === "}" || character === "]") depth--;
223
- return true;
224
- };
225
- const mediaType = (value) => value?.split(";", 1)[0]?.trim().toLowerCase() ?? "";
226
- const retryAfter = (value, now) => {
227
- if (value === void 0 || value.length > 128) return void 0;
228
- const seconds = Number(value);
229
- if (Number.isFinite(seconds) && seconds >= 0) return Math.min(6e4, seconds * 1e3);
230
- const date = Date.parse(value);
231
- return Number.isFinite(date) ? Math.min(6e4, Math.max(0, date - now)) : void 0;
232
- };
233
- const mutationOutcome = (method, status) => {
234
- if (method === "GET") return void 0;
235
- if (status !== void 0 && [
236
- 400,
237
- 401,
238
- 403,
239
- 404,
240
- 409,
241
- 410,
242
- 422,
243
- 429
244
- ].includes(status)) return "rejected";
245
- return "unknown";
246
- };
247
- const statusError = (method, status, operation, after) => ClientError.make({
248
- operation,
249
- reason: status === 401 || status === 403 ? "authorization" : status === 429 ? "rate-limited" : status === 409 ? "active" : status === 410 ? "expired" : status === 422 ? "disabled" : status === 404 ? "not-found" : "provider",
250
- status,
251
- ...mutationOutcome(method, status) === void 0 ? {} : { outcome: mutationOutcome(method, status) },
252
- ...after === void 0 ? {} : { retryAfterMillis: after }
253
- });
254
- const collect = (stream, maximum, operation) => Effect.gen(function* () {
255
- const chunks = [];
256
- let total = 0;
257
- yield* Stream.runForEach(stream, (chunk) => Effect.suspend(() => {
258
- if (chunk.byteLength > maximum - total) return Effect.fail(ClientError.make({
259
- operation,
260
- reason: "limit"
261
- }));
262
- total += chunk.byteLength;
263
- chunks.push(chunk);
264
- return Effect.void;
265
- }));
266
- const body = new Uint8Array(total);
267
- let offset = 0;
268
- for (const chunk of chunks) {
269
- body.set(chunk, offset);
270
- offset += chunk.byteLength;
271
- }
272
- return body;
273
- });
274
- const validApiPath = (path) => path.startsWith("/v1/") && !path.includes("\\") && !path.includes("#") && path.length <= 16384;
275
- const makeTransport = Effect.fnUntraced(function* (options) {
276
- const configured = yield* Schema.decodeEffect(Options)(options, { onExcessProperty: "error" }).pipe(Effect.mapError(() => ClientError.make({
277
- operation: "configure",
278
- reason: "configuration",
279
- outcome: "undispatched"
280
- })));
281
- const apiKey = Redacted.value(configured.apiKey);
282
- const requestTimeoutMillis = configured.requestTimeoutMillis ?? 1e4;
283
- const artifactOrigins = /* @__PURE__ */ new Set();
284
- for (const origin of configured.artifactOrigins ?? []) {
285
- const url = yield* Effect.try({
286
- try: () => new URL(origin),
287
- catch: () => ClientError.make({
288
- operation: "configure",
289
- reason: "configuration",
290
- outcome: "undispatched"
291
- })
292
- });
293
- if (url.protocol !== "https:" || url.origin !== origin || url.username || url.password) return yield* ClientError.make({
294
- operation: "configure",
295
- reason: "configuration",
296
- outcome: "undispatched"
297
- });
298
- artifactOrigins.add(origin);
299
- }
300
- const fetch = yield* FetchHttpClient.Fetch;
301
- const client = yield* HttpClient.HttpClient.pipe(Effect.provide(FetchHttpClient.layer));
302
- const scoped = HttpClient.withScope(client);
303
- const execute = (request, operation, outcome) => scoped.execute(request).pipe(Effect.provideService(FetchHttpClient.Fetch, fetch), Effect.provideService(FetchHttpClient.RequestInit, {
304
- redirect: "manual",
305
- credentials: "omit",
306
- cache: "no-store",
307
- referrerPolicy: "no-referrer"
308
- }), Effect.provideService(HttpClient.TracerDisabledWhen, () => true), Effect.provideService(HttpClient.TracerPropagationEnabled, false), Effect.withTracerEnabled(false), Effect.mapError(() => ClientError.make({
309
- operation,
310
- reason: "transport",
311
- ...outcome === void 0 ? {} : { outcome }
312
- })), span("BrowserbaseClient.execute", { attributes: {
313
- "browser.operation": operation,
314
- "http.request.method": traceMethod(request.method)
315
- } }));
316
- /** A rejected path is a typed, undispatched configuration failure, never a defect. */
317
- const apiRequest = (method, path, accept, operation) => validApiPath(path) ? Effect.succeed(HttpClientRequest.make(method)(`${API_ORIGIN}${path}`).pipe(HttpClientRequest.setHeader("x-bb-api-key", apiKey), HttpClientRequest.setHeader("accept", accept))) : Effect.fail(ClientError.make({
318
- operation,
319
- reason: "configuration",
320
- outcome: "undispatched"
321
- }));
322
- const inspectJson = Effect.fnUntraced(function* (method, response, operation) {
323
- if (response.status !== 200 && response.status !== 201 && response.status !== 202) return yield* statusError(method, response.status, operation, retryAfter(response.headers["retry-after"], yield* Clock.currentTimeMillis));
324
- if (mediaType(response.headers["content-type"]) !== "application/json") return yield* ClientError.make({
325
- operation,
326
- reason: "content-type",
327
- ...mutationOutcome(method) === void 0 ? {} : { outcome: mutationOutcome(method) }
328
- });
329
- const length = response.headers["content-length"];
330
- if (length !== void 0 && (!/^\d+$/.test(length) || Number(length) > MAX_JSON_BYTES)) return yield* ClientError.make({
331
- operation,
332
- reason: "limit",
333
- ...mutationOutcome(method) === void 0 ? {} : { outcome: mutationOutcome(method) }
334
- });
335
- let received = 0;
336
- return response.stream.pipe(Stream.mapError(() => ClientError.make({
337
- operation,
338
- reason: "transport",
339
- ...mutationOutcome(method) === void 0 ? {} : { outcome: mutationOutcome(method) }
340
- })), Stream.mapEffect((chunk) => Effect.suspend(() => {
341
- if (chunk.byteLength > MAX_JSON_BYTES - received) return Effect.fail(ClientError.make({
342
- operation,
343
- reason: "limit",
344
- ...mutationOutcome(method) === void 0 ? {} : { outcome: mutationOutcome(method) }
345
- }));
346
- received += chunk.byteLength;
347
- return Effect.succeed(new Uint8Array(chunk));
348
- })));
349
- });
350
- const readJson = Effect.fnUntraced(function* (method, response, operation) {
351
- const stream = yield* inspectJson(method, response, operation);
352
- const bytes = yield* collect(stream, MAX_JSON_BYTES, operation);
353
- const text = yield* Effect.try({
354
- try: () => new TextDecoder("utf-8", { fatal: true }).decode(bytes),
355
- catch: () => ClientError.make({
356
- operation,
357
- reason: "malformed",
358
- ...mutationOutcome(method) === void 0 ? {} : { outcome: mutationOutcome(method) }
359
- })
360
- });
361
- if (!withinJsonDepth(text)) return yield* ClientError.make({
362
- operation,
363
- reason: "limit",
364
- ...mutationOutcome(method) === void 0 ? {} : { outcome: mutationOutcome(method) }
365
- });
366
- return yield* Schema.decodeEffect(Schema.fromJsonString(Schema.Json))(text).pipe(Effect.mapError(() => ClientError.make({
367
- operation,
368
- reason: "malformed",
369
- ...mutationOutcome(method) === void 0 ? {} : { outcome: mutationOutcome(method) }
370
- })));
371
- }, span("BrowserbaseClient.decodeJson"));
372
- const jsonOnce = Effect.fnUntraced(function* (method, path, body) {
373
- const operation = method === "GET" ? "provider-read" : "provider-mutation";
374
- let request = yield* apiRequest(method, path, "application/json", operation);
375
- if (body !== void 0) request = yield* HttpClientRequest.bodyJson(request, body).pipe(Effect.mapError(() => ClientError.make({
376
- operation,
377
- reason: "configuration",
378
- outcome: "undispatched"
379
- })));
380
- const response = yield* execute(request, operation, method === "GET" ? void 0 : "unknown");
381
- return yield* readJson(method, response, operation);
382
- });
383
- /**
384
- * One bounded in-memory file part. The encoder proves its delimiter absent from the
385
- * content, and an accepted multipart mutation is never retried: a lost reply is unknown.
386
- */
387
- const upload = Effect.fnUntraced(function* (path, part, limits, outerDeadline) {
388
- const operation = "provider-upload";
389
- const timeoutMillis = limits.timeoutMillis ?? 6e4;
390
- if (!Number.isSafeInteger(timeoutMillis) || timeoutMillis < 1 || timeoutMillis > 6e5) return yield* ClientError.make({
391
- operation,
392
- reason: "configuration",
393
- outcome: "undispatched"
394
- });
395
- const encoded = yield* encodeFilePart(part, limits.maxBytes);
396
- if (encoded._tag === "Rejected") return yield* ClientError.make({
397
- operation,
398
- reason: encoded.reason,
399
- outcome: "undispatched"
400
- });
401
- const request = HttpClientRequest.bodyUint8Array(yield* apiRequest("POST", path, "application/json", operation), encoded.body, encoded.contentType);
402
- const deadline = Math.min(yield* deadlineAfter(timeoutMillis), outerDeadline ?? Infinity);
403
- return yield* within(Effect.scoped(execute(request, operation, "unknown").pipe(Effect.flatMap((response) => readJson("POST", response, operation)))), deadline, operation, "unknown");
404
- }, span("BrowserbaseClient.upload", { attributes: {
405
- "browser.operation": "provider-upload",
406
- "http.request.method": "POST"
407
- } }));
408
- const json = Effect.fnUntraced(function* (method, path, body, outerDeadline) {
409
- const deadline = Math.min(yield* deadlineAfter(requestTimeoutMillis), outerDeadline ?? Infinity);
410
- for (let attempt = 0;; attempt++) {
411
- const result = yield* within(Effect.scoped(jsonOnce(method, path, body)), deadline, method === "GET" ? "provider-read" : "provider-mutation", method === "GET" ? void 0 : "unknown").pipe(span("BrowserbaseClient.request", { attributes: {
412
- "browser.operation": method === "GET" ? "provider-read" : "provider-mutation",
413
- "http.request.method": traceMethod(method)
414
- } }), Effect.result);
415
- if (result._tag === "Success") return result.success;
416
- const error = result.failure;
417
- const retryable = error.reason === "transport" || error.reason === "rate-limited" || error.reason === "provider" && (error.status ?? 0) >= 500;
418
- if (method !== "GET" || !retryable || attempt >= 2) return yield* error;
419
- const delay = error.retryAfterMillis ?? (attempt + 1) * 150;
420
- if ((yield* nowMillis) + delay >= deadline) return yield* error;
421
- yield* Effect.sleep(delay);
422
- }
423
- }, (effect, method) => effect.pipe(span("BrowserbaseClient.json", { attributes: {
424
- "browser.operation": method === "GET" ? "provider-read" : "provider-mutation",
425
- "http.request.method": traceMethod(method)
426
- } })));
427
- const noContent = Effect.fnUntraced(function* (method, path, body, outerDeadline) {
428
- const operation = "provider-mutation";
429
- let request = yield* apiRequest(method, path, "*/*", operation);
430
- if (body !== void 0) request = yield* HttpClientRequest.bodyJson(request, body).pipe(Effect.mapError(() => ClientError.make({
431
- operation,
432
- reason: "configuration",
433
- outcome: "undispatched"
434
- })));
435
- const deadline = Math.min(yield* deadlineAfter(requestTimeoutMillis), outerDeadline ?? Infinity);
436
- const response = yield* within(Effect.scoped(execute(request, operation, "unknown")), deadline, operation, "unknown");
437
- if (![
438
- 200,
439
- 202,
440
- 204
441
- ].includes(response.status)) return yield* statusError(method, response.status, operation, retryAfter(response.headers["retry-after"], yield* Clock.currentTimeMillis));
442
- }, (effect, method) => effect.pipe(span("BrowserbaseClient.noContent", { attributes: {
443
- "browser.operation": "provider-mutation",
444
- "http.request.method": traceMethod(method)
445
- } })));
446
- const inspectBytes = Effect.fnUntraced(function* (response, operation, types, maximum) {
447
- if (response.status !== 200 && response.status !== 206) return yield* statusError("GET", response.status, operation, retryAfter(response.headers["retry-after"], yield* Clock.currentTimeMillis));
448
- if (!types.includes(mediaType(response.headers["content-type"]))) return yield* ClientError.make({
449
- operation,
450
- reason: "content-type"
451
- });
452
- const length = response.headers["content-length"];
453
- if (length !== void 0 && (!/^\d+$/.test(length) || Number(length) > maximum)) return yield* ClientError.make({
454
- operation,
455
- reason: "limit"
456
- });
457
- let received = 0;
458
- return response.stream.pipe(Stream.mapError(() => ClientError.make({
459
- operation,
460
- reason: "transport"
461
- })), Stream.mapEffect((chunk) => Effect.suspend(() => {
462
- if (chunk.byteLength > maximum - received) return Effect.fail(ClientError.make({
463
- operation,
464
- reason: "limit"
465
- }));
466
- received += chunk.byteLength;
467
- return Effect.succeed(new Uint8Array(chunk));
468
- })));
469
- });
470
- const bytes = (path, maximum, types, timeoutMillis = requestTimeoutMillis, outerDeadline) => Stream.unwrap(Effect.gen(function* () {
471
- const operation = "provider-read";
472
- if (!Number.isSafeInteger(maximum) || maximum < 1 || maximum > 2 ** 31 - 1 || !Number.isSafeInteger(timeoutMillis) || timeoutMillis < 1 || timeoutMillis > 6e5) return yield* ClientError.make({
473
- operation,
474
- reason: "configuration"
475
- });
476
- const deadline = Math.min(yield* deadlineAfter(timeoutMillis), outerDeadline ?? Infinity);
477
- const request = yield* apiRequest("GET", path, types[0] ?? "application/octet-stream", operation);
478
- const response = yield* within(execute(request, operation), deadline, operation);
479
- const stream = yield* inspectBytes(response, operation, types, maximum);
480
- return Stream.transformPull(stream, (pull) => Effect.succeed(within(pull, deadline, operation)));
481
- })).pipe(Stream.scoped, stream("BrowserbaseClient.bytes", { attributes: {
482
- "browser.operation": "provider-read",
483
- "http.request.method": "GET"
484
- } }));
485
- const text = (path, maximum, types) => collect(bytes(path, maximum, types), maximum, "provider-read").pipe(Effect.flatMap((body) => Effect.try({
486
- try: () => new TextDecoder("utf-8", { fatal: true }).decode(body),
487
- catch: () => ClientError.make({
488
- operation: "provider-read",
489
- reason: "malformed"
490
- })
491
- })), Effect.timeoutOrElse({
492
- duration: Duration.millis(requestTimeoutMillis),
493
- orElse: () => Effect.fail(ClientError.make({
494
- operation: "provider-read",
495
- reason: "timeout"
496
- }))
497
- }), span("BrowserbaseClient.text", { attributes: {
498
- "browser.operation": "provider-read",
499
- "http.request.method": "GET"
500
- } }));
501
- const validateMediaUrl = (value) => {
502
- try {
503
- const url = new URL(value);
504
- return url.protocol === "https:" && !url.username && !url.password && !url.hash && artifactOrigins.has(url.origin) && value.length <= 16384;
505
- } catch {
506
- return false;
507
- }
508
- };
509
- const media = (url, maximum, types, timeoutMillis = 6e4, outerDeadline) => Stream.unwrap(Effect.gen(function* () {
510
- const value = Redacted.value(url);
511
- if (!validateMediaUrl(value) || !Number.isSafeInteger(maximum) || maximum < 1 || maximum > 2 ** 31 - 1 || !Number.isSafeInteger(timeoutMillis) || timeoutMillis < 1 || timeoutMillis > 6e5) return yield* ClientError.make({
512
- operation: "media-download",
513
- reason: "unsafe-url"
514
- });
515
- const deadline = Math.min(yield* deadlineAfter(timeoutMillis), outerDeadline ?? Infinity);
516
- const response = yield* within(execute(HttpClientRequest.get(value), "media-download"), deadline, "media-download");
517
- const stream = yield* inspectBytes(response, "media-download", types, maximum);
518
- return Stream.transformPull(stream, (pull) => Effect.succeed(within(pull, deadline, "media-download")));
519
- })).pipe(Stream.scoped, stream("BrowserbaseClient.media", { attributes: {
520
- "browser.operation": "media-download",
521
- "http.request.method": "GET"
522
- } }));
523
- return {
524
- projectId: configured.projectId,
525
- json,
526
- noContent,
527
- upload,
528
- text,
529
- bytes,
530
- media,
531
- validateMediaUrl
532
- };
533
- }, span("BrowserbaseClient.configure"));
534
- //#endregion
535
- //#region src/Client.ts
536
- /**
537
- * One immutable Browserbase account and approved transport, shared by every resource Layer.
538
- * Constructing the Layer performs no request and never loads the native browser peer.
539
- */
540
- var BrowserbaseClient = class BrowserbaseClient extends Context.Service()("effect-browserbase/Client") {
541
- static layer(options) {
542
- return Layer.effect(BrowserbaseClient, makeTransport(options).pipe(Effect.map((client) => BrowserbaseClient.of(Object.freeze(client)))));
543
- }
544
- /**
545
- * Account authority from the application's `ConfigProvider` (the environment by default):
546
- * `BROWSERBASE_PROJECT_ID` and a redacted `BROWSERBASE_API_KEY`. Transport options stay
547
- * explicit. Configuration is read when the Layer is built, never at import.
548
- */
549
- static layerConfig(options = {}) {
550
- return Layer.unwrap(Effect.gen(function* () {
551
- const projectId = yield* Config.String("BROWSERBASE_PROJECT_ID");
552
- const apiKey = yield* Config.Redacted("BROWSERBASE_API_KEY");
553
- return BrowserbaseClient.layer({
554
- ...options,
555
- projectId,
556
- apiKey
557
- });
558
- }));
559
- }
560
- };
561
- //#endregion
562
- export { stream as i, annotate as n, span as r, BrowserbaseClient as t };
563
-
564
- //# sourceMappingURL=Client-BEC4Q8ZS.mjs.map