effect-browserbase 0.2.0-beta.7 → 0.2.0-beta.9

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 (54) hide show
  1. package/README.md +40 -22
  2. package/dist/Account.mjs +3 -3
  3. package/dist/{Acquisition-Ca4EE-Fg.mjs → Acquisition-BOABu_qJ.mjs} +21 -12
  4. package/dist/Acquisition-BOABu_qJ.mjs.map +1 -0
  5. package/dist/Agents.mjs +25 -25
  6. package/dist/Agents.mjs.map +1 -1
  7. package/dist/Allocation.mjs +1 -1
  8. package/dist/{Browser-BPcF550A.mjs → Browser-ByrWJ0ss.mjs} +21 -17
  9. package/dist/Browser-ByrWJ0ss.mjs.map +1 -0
  10. package/dist/Browser.d.mts +11 -9
  11. package/dist/Browser.mjs +1 -1
  12. package/dist/Certificates.mjs +9 -9
  13. package/dist/Certificates.mjs.map +1 -1
  14. package/dist/{Client-4RMKIpL2.mjs → Client-BEC4Q8ZS.mjs} +154 -14
  15. package/dist/Client-BEC4Q8ZS.mjs.map +1 -0
  16. package/dist/Client.mjs +1 -1
  17. package/dist/ContextCoordination.mjs +9 -8
  18. package/dist/ContextCoordination.mjs.map +1 -1
  19. package/dist/Contexts.mjs +7 -7
  20. package/dist/Contexts.mjs.map +1 -1
  21. package/dist/Downloads.mjs +10 -10
  22. package/dist/Downloads.mjs.map +1 -1
  23. package/dist/{Extensions-Dg3jHOf0.mjs → Extensions-BTUn9zhK.mjs} +8 -8
  24. package/dist/Extensions-BTUn9zhK.mjs.map +1 -0
  25. package/dist/Extensions.mjs +1 -1
  26. package/dist/Functions.mjs +27 -27
  27. package/dist/Functions.mjs.map +1 -1
  28. package/dist/PageFetch.mjs +4 -4
  29. package/dist/PageFetch.mjs.map +1 -1
  30. package/dist/Projects.mjs +5 -5
  31. package/dist/Projects.mjs.map +1 -1
  32. package/dist/Recordings.mjs +42 -27
  33. package/dist/Recordings.mjs.map +1 -1
  34. package/dist/Replays.mjs +6 -6
  35. package/dist/Replays.mjs.map +1 -1
  36. package/dist/{Resource-DBksC4zB.mjs → Resource-J7Kkk5mu.mjs} +7 -3
  37. package/dist/Resource-J7Kkk5mu.mjs.map +1 -0
  38. package/dist/Search.mjs +4 -4
  39. package/dist/Search.mjs.map +1 -1
  40. package/dist/{Sessions-BUoyPcPJ.mjs → Sessions-D2H5m6rF.mjs} +15 -15
  41. package/dist/Sessions-D2H5m6rF.mjs.map +1 -0
  42. package/dist/Sessions.mjs +1 -1
  43. package/dist/Testing.mjs +1 -1
  44. package/dist/Uploads.mjs +4 -4
  45. package/dist/Uploads.mjs.map +1 -1
  46. package/dist/Webhooks.mjs +14 -14
  47. package/dist/Webhooks.mjs.map +1 -1
  48. package/package.json +3 -3
  49. package/dist/Acquisition-Ca4EE-Fg.mjs.map +0 -1
  50. package/dist/Browser-BPcF550A.mjs.map +0 -1
  51. package/dist/Client-4RMKIpL2.mjs.map +0 -1
  52. package/dist/Extensions-Dg3jHOf0.mjs.map +0 -1
  53. package/dist/Resource-DBksC4zB.mjs.map +0 -1
  54. package/dist/Sessions-BUoyPcPJ.mjs.map +0 -1
@@ -1,12 +1,12 @@
1
1
  import { SessionError } from "./Errors.mjs";
2
+ import { r as span, t as BrowserbaseClient } from "./Client-BEC4Q8ZS.mjs";
2
3
  import { DownloadObservation } from "./Transfers.mjs";
3
- import { t as BrowserbaseClient } from "./Client-4RMKIpL2.mjs";
4
4
  import { r as isList } from "./Launch-cAdE2rrZ.mjs";
5
5
  import { isTerminalSessionStatus } from "./SessionData.mjs";
6
- import { a as issueLiveView, o as browserRequestFailure, t as BrowserbaseSessions } from "./Sessions-BUoyPcPJ.mjs";
6
+ import { a as issueLiveView, o as browserRequestFailure, t as BrowserbaseSessions } from "./Sessions-D2H5m6rF.mjs";
7
7
  import { t as issuedUpload } from "./Issued-DejqoMYL.mjs";
8
8
  import { t as connectionAddress } from "./Connection-sxyxtwlk.mjs";
9
- import { a as reported, i as noLocalConnection, n as reportCleanup, r as makeCleanup, t as acquireRemote } from "./Acquisition-Ca4EE-Fg.mjs";
9
+ import { a as reported, i as noLocalConnection, n as reportCleanup, r as makeCleanup, t as acquireRemote } from "./Acquisition-BOABu_qJ.mjs";
10
10
  import { BrowserbaseBrowserBinding } from "./BrowserBinding.mjs";
11
11
  import { Context, Crypto, Effect, Exit, Layer, Option, Schema, Scope } from "effect";
12
12
  import { BrowserError, Reasons } from "effect-browser/errors";
@@ -48,9 +48,9 @@ const attachRemote = Effect.fnUntraced(function* (options, local = noLocalConnec
48
48
  const notify = options.onCleanup;
49
49
  if (result !== void 0) {
50
50
  yield* reported(Effect.suspend(() => reportCleanup(result)));
51
- if (notify !== void 0) yield* reported(Effect.suspend(() => notify(result)));
51
+ if (notify !== void 0) yield* reported(Effect.suspend(() => notify(result)).pipe(span("Browserbase.callback.cleanup")));
52
52
  }
53
- })));
53
+ }).pipe(span("Browserbase.terminate", { attributes: { "browser.ownership": "borrowed" } }))));
54
54
  const closeScope = yield* Effect.cached(Scope.close(resourceScope, Exit.void));
55
55
  yield* Scope.addFinalizer(resourceScope, terminate);
56
56
  yield* Scope.addFinalizer(parent, closeScope);
@@ -61,12 +61,12 @@ const attachRemote = Effect.fnUntraced(function* (options, local = noLocalConnec
61
61
  operation: "session-connect",
62
62
  reason: "expired",
63
63
  outcome: "undispatched"
64
- })) : connectionAddress(client, sessions, reference, timeoutMillis)),
65
- release: closeScope.pipe(Effect.andThen(Effect.suspend(() => cleanup === void 0 ? Effect.die(/* @__PURE__ */ new Error("Borrowed session closed without cleanup evidence")) : Effect.succeed(cleanup)))),
64
+ })) : connectionAddress(client, sessions, reference, timeoutMillis).pipe(span("Browserbase.connection", { attributes: { "browser.ownership": "borrowed" } }))),
65
+ release: closeScope.pipe(Effect.andThen(Effect.suspend(() => cleanup === void 0 ? Effect.die(/* @__PURE__ */ new Error("Borrowed session closed without cleanup evidence")) : Effect.succeed(cleanup))), span("Browserbase.release", { attributes: { "browser.ownership": "borrowed" } })),
66
66
  cleanupResult: Effect.sync(() => Option.fromNullishOr(cleanup))
67
67
  };
68
68
  }));
69
- });
69
+ }, span("Browserbase.attachRemote", { attributes: { "browser.ownership": "borrowed" } }));
70
70
  //#endregion
71
71
  //#region src/internal/session/Browser.ts
72
72
  /** A borrowed connection closes without requiring or requesting remote termination. */
@@ -146,27 +146,28 @@ const selection = (request, reference, operation) => Effect.suspend(() => {
146
146
  });
147
147
  const makeSession = (connection, lifetime) => {
148
148
  const { session, operations } = connection;
149
+ const transfers = (page) => operations.forPage(page);
149
150
  return Object.assign(session, {
150
151
  reference: lifetime.reference,
151
152
  closeChecked: session.closeChecked.pipe(Effect.andThen(lifetime.closeChecked)),
152
- clickForDownload: (request) => operations.clickForDownload(request).pipe(Effect.flatMap((event) => Schema.decodeEffect(DownloadObservation)({
153
+ clickForDownload: (page, request, options) => transfers(page).pipe(Effect.flatMap((operations) => operations.clickForDownload(request, options)), Effect.flatMap((event) => Schema.decodeEffect(DownloadObservation)({
153
154
  ...event,
154
155
  reference: lifetime.reference
155
156
  }).pipe(Effect.mapError(() => BrowserError.make({
156
157
  operation: "download-action",
157
158
  reason: Reasons.Malformed.make({}),
158
- outcome: "unknown"
159
+ outcome: "performed"
159
160
  }))))),
160
- selectFiles: (request) => selection(request, lifetime.reference, "select-files").pipe(Effect.flatMap((files) => operations.selectFiles({
161
+ selectFiles: (page, request, options) => transfers(page).pipe(Effect.flatMap((operations) => selection(request, lifetime.reference, "select-files").pipe(Effect.flatMap((files) => operations.selectFiles({
161
162
  selector: request.selector,
162
163
  selection: files
163
- }))),
164
- clickForFileSelection: (request) => selection(request, lifetime.reference, "file-chooser").pipe(Effect.flatMap((files) => operations.clickForFileSelection({
164
+ }, options))))),
165
+ clickForFileSelection: (page, request, options) => transfers(page).pipe(Effect.flatMap((operations) => selection(request, lifetime.reference, "file-chooser").pipe(Effect.flatMap((files) => operations.clickForFileSelection({
165
166
  selector: request.selector,
166
167
  selection: files
167
- }))),
168
- liveView: (ttl = 60) => operations.liveView(lifetime.liveView(ttl)),
169
- beginHandoff: (ttl = 60) => operations.beginHandoff(lifetime.liveView(ttl)),
168
+ }, options))))),
169
+ liveView: (ttl = 60, options) => operations.liveView(lifetime.liveView(ttl), options),
170
+ beginHandoff: (ttl = 60, options) => operations.beginHandoff(lifetime.liveView(ttl), options),
170
171
  resume: operations.resume,
171
172
  detach: operations.detach,
172
173
  reconnect: operations.reconnect,
@@ -256,6 +257,9 @@ var BrowserbaseBrowser = class BrowserbaseBrowser extends Context.Service()("eff
256
257
  };
257
258
  /** Only the automation fields cross the schema boundary; launch and callbacks are separate. */
258
259
  const projected = (options) => ({
260
+ ...options.timelineLimits === void 0 ? {} : { timelineLimits: options.timelineLimits },
261
+ ...options.admissionLimits === void 0 ? {} : { admissionLimits: options.admissionLimits },
262
+ ...options.observationLimits === void 0 ? {} : { observationLimits: options.observationLimits },
259
263
  ...options.maxHostReads === void 0 ? {} : { maxHostReads: options.maxHostReads },
260
264
  ...options.actionTimeoutMillis === void 0 ? {} : { actionTimeoutMillis: options.actionTimeoutMillis },
261
265
  ...options.maxPages === void 0 ? {} : { maxPages: options.maxPages },
@@ -267,4 +271,4 @@ const projected = (options) => ({
267
271
  //#endregion
268
272
  export { BrowserbaseBrowser as t };
269
273
 
270
- //# sourceMappingURL=Browser-BPcF550A.mjs.map
274
+ //# sourceMappingURL=Browser-ByrWJ0ss.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Browser-ByrWJ0ss.mjs","names":["Trace.span"],"sources":["../src/internal/session/Attachment.ts","../src/internal/session/Browser.ts","../src/Browser.ts"],"sourcesContent":["import { Effect, Exit, Option, Scope } from \"effect\";\n\nimport type { CleanupResult } from \"../../Cleanup.ts\";\nimport { BrowserbaseClient } from \"../../Client.ts\";\nimport { SessionError } from \"../../Errors.ts\";\nimport type { SessionReference } from \"../../References.ts\";\nimport { isTerminalSessionStatus } from \"../../SessionData.ts\";\nimport { BrowserbaseSessions } from \"../../Sessions.ts\";\nimport { connectionAddress } from \"../provider/Connection.ts\";\nimport * as Trace from \"../Trace.ts\";\nimport {\n makeCleanup,\n noLocalConnection,\n reported,\n type CleanupLimits,\n type LocalCleanup,\n} from \"./Cleanup.ts\";\nimport { reportCleanup } from \"./Diagnostics.ts\";\n\nexport interface AttachmentOptions {\n readonly reference: SessionReference;\n /** Bounded admission of a session the provider has not finished starting. */\n readonly pendingWaitMillis?: number;\n readonly onCleanup?: (result: CleanupResult) => Effect.Effect<void>;\n}\n\nconst failure = (reason: SessionError[\"reason\"]) =>\n SessionError.make({ operation: \"session-attach\", reason, outcome: \"undispatched\" });\n\n/**\n * Borrowing an already running session. This scope owns its local connection and nothing\n * else: no allocation attempt is made, no release is requested, and no Context-writer\n * authority is claimed. Whoever allocated the session keeps all three.\n */\nexport const attachRemote = Effect.fnUntraced(\n function* (\n options: AttachmentOptions,\n local: LocalCleanup = noLocalConnection,\n limits?: CleanupLimits,\n ) {\n const client = yield* BrowserbaseClient;\n const sessions = yield* BrowserbaseSessions;\n const parent = yield* Scope.Scope;\n const pendingWaitMillis = options.pendingWaitMillis ?? 0;\n\n if (\n !Number.isSafeInteger(pendingWaitMillis) ||\n pendingWaitMillis < 0 ||\n pendingWaitMillis > 600_000\n )\n return yield* failure(\"configuration\");\n\n // The status read validates project authority before anything is borrowed. A terminal\n // session needs a fresh allocation from durable state, never a reattachment.\n const observed = yield* sessions.retrieve(options.reference);\n\n if (isTerminalSessionStatus(observed.status)) return yield* failure(\"expired\");\n if (observed.status !== \"RUNNING\") {\n if (pendingWaitMillis === 0) return yield* failure(\"active\");\n yield* sessions.waitUntilRunning(observed.reference, { timeoutMillis: pendingWaitMillis });\n }\n const reference = observed.reference;\n\n return yield* Effect.uninterruptible(\n Effect.gen(function* () {\n const resourceScope = yield* Scope.make();\n let closing = false;\n let cleanup: CleanupResult | undefined;\n\n const terminate = yield* Effect.cached(\n Effect.uninterruptible(\n Effect.gen(function* () {\n closing = true;\n\n const coordinator = yield* makeCleanup(\n reference,\n \"borrowed\",\n sessions,\n local,\n (result) => {\n cleanup = result;\n },\n limits,\n );\n\n yield* coordinator.close;\n const result = cleanup;\n const notify = options.onCleanup;\n\n if (result !== undefined) {\n yield* reported(Effect.suspend(() => reportCleanup(result)));\n if (notify !== undefined)\n yield* reported(\n Effect.suspend(() => notify(result)).pipe(\n Trace.span(\"Browserbase.callback.cleanup\"),\n ),\n );\n }\n }).pipe(\n Trace.span(\"Browserbase.terminate\", {\n attributes: { \"browser.ownership\": \"borrowed\" },\n }),\n ),\n ),\n );\n\n const closeScope = yield* Effect.cached(Scope.close(resourceScope, Exit.void));\n\n // Teardown is registered before the first connection, exactly as an owned scope does.\n yield* Scope.addFinalizer(resourceScope, terminate);\n yield* Scope.addFinalizer(parent, closeScope);\n\n return {\n reference,\n status: observed,\n connection: (timeoutMillis: number) =>\n Effect.suspend(() =>\n closing\n ? Effect.fail(\n SessionError.make({\n operation: \"session-connect\",\n reason: \"expired\",\n outcome: \"undispatched\",\n }),\n )\n : // Credentials are fetched fresh: an expiry can race the caller's own read.\n connectionAddress(client, sessions, reference, timeoutMillis).pipe(\n Trace.span(\"Browserbase.connection\", {\n attributes: { \"browser.ownership\": \"borrowed\" },\n }),\n ),\n ),\n release: closeScope.pipe(\n Effect.andThen(\n Effect.suspend(() =>\n cleanup === undefined\n ? Effect.die(new Error(\"Borrowed session closed without cleanup evidence\"))\n : Effect.succeed(cleanup),\n ),\n ),\n Trace.span(\"Browserbase.release\", { attributes: { \"browser.ownership\": \"borrowed\" } }),\n ),\n cleanupResult: Effect.sync(() => Option.fromNullishOr(cleanup)),\n };\n }),\n );\n },\n Trace.span(\"Browserbase.attachRemote\", { attributes: { \"browser.ownership\": \"borrowed\" } }),\n);\n","import { type Crypto, Effect, Option, type Redacted } from \"effect\";\nimport type { Lifetime, Source } from \"effect-browser/browser-runtime\";\nimport { BrowserError, Reasons } from \"effect-browser/errors\";\n\nimport type { CleanupResult } from \"../../Cleanup.ts\";\nimport { BrowserbaseClient } from \"../../Client.ts\";\nimport type { AllocationError, ContextError, SessionError } from \"../../Errors.ts\";\nimport type { LaunchRecipe } from \"../../Launch.ts\";\nimport type { AllocationAttempt, SessionReference } from \"../../References.ts\";\nimport { BrowserbaseSessions } from \"../../Sessions.ts\";\nimport { issueLiveView, type LiveView } from \"../browser/LiveView.ts\";\nimport { browserRequestFailure } from \"../browser/RequestFailure.ts\";\nimport { acquireRemote } from \"./Acquisition.ts\";\nimport { attachRemote } from \"./Attachment.ts\";\nimport type { ContextWriterPermit } from \"./WriterFacts.ts\";\n\nexport interface RemoteLease extends Lifetime {\n readonly reference: SessionReference;\n readonly closeChecked: Effect.Effect<CleanupResult, BrowserError>;\n readonly attempt?: AllocationAttempt;\n readonly release: Effect.Effect<CleanupResult>;\n readonly cleanupResult: Effect.Effect<Option.Option<CleanupResult>>;\n readonly liveView: (ttl: number) => Effect.Effect<LiveView, BrowserError>;\n}\n\ntype RemoteSource<L extends Lifetime, E> = Source<\n L,\n E,\n BrowserbaseClient | BrowserbaseSessions | Crypto.Crypto\n>;\n\n/** A borrowed connection closes without requiring or requesting remote termination. */\nconst checkedCleanup = (\n close: Effect.Effect<CleanupResult>,\n): Effect.Effect<CleanupResult, BrowserError> =>\n close.pipe(\n Effect.filterOrFail(\n (result) =>\n result.local === \"closed\" &&\n result.issues.length === 0 &&\n (result.ownership === \"borrowed\"\n ? result.remote === \"not-owned\"\n : result.remote === \"confirmed\"),\n () =>\n BrowserError.make({\n operation: \"close\",\n reason: Reasons.Provider.make({}),\n outcome: \"unknown\",\n }),\n ),\n );\n\nconst withConnection = <\n A extends {\n readonly reference: SessionReference;\n readonly connection: (\n timeoutMillis: number,\n ) => Effect.Effect<Redacted.Redacted<string>, SessionError>;\n readonly release: Effect.Effect<CleanupResult>;\n readonly cleanupResult: Effect.Effect<Option.Option<CleanupResult>>;\n },\n>(\n acquired: A,\n) => ({\n ...acquired,\n connection: (timeoutMillis: number) =>\n acquired\n .connection(timeoutMillis)\n .pipe(Effect.mapError((error) => browserRequestFailure(\"connect\", error))),\n closeChecked: checkedCleanup(acquired.release),\n controlRetired: acquired.cleanupResult.pipe(\n Effect.map(\n (result) =>\n Option.isSome(result) &&\n result.value.ownership === \"owned\" &&\n result.value.remote === \"confirmed\",\n ),\n ),\n});\n\nexport interface OwnedLease extends RemoteLease {\n readonly attempt: AllocationAttempt;\n}\n\nexport interface OwnedOptions {\n /** The single provider-faithful launch description; the owner adds no second default body. */\n readonly launch: LaunchRecipe;\n /** Required for a persistent context; the writer permit, not this owner, holds that authority. */\n readonly contextWriter?: ContextWriterPermit;\n readonly onCleanup?: (result: CleanupResult) => Effect.Effect<void>;\n readonly onAllocationUncertain?: (attempt: AllocationAttempt) => Effect.Effect<void>;\n}\n\n/** Allocates the session, and therefore owns releasing it. */\nconst providerControls = (\n client: BrowserbaseClient[\"Service\"],\n sessions: BrowserbaseSessions[\"Service\"],\n reference: SessionReference,\n) => ({\n liveView: (ttl: number) => issueLiveView(client, reference, ttl),\n verifyReconnect: sessions.retrieve(reference).pipe(\n Effect.mapError((error) => browserRequestFailure(\"reconnect\", error)),\n Effect.flatMap((status) =>\n status.status === \"RUNNING\"\n ? Effect.void\n : Effect.fail(\n BrowserError.make({\n operation: \"reconnect\",\n reason: Reasons.Expired.make({}),\n outcome: \"undispatched\",\n }),\n ),\n ),\n ),\n});\n\nexport const ownedRemote =\n (\n options: OwnedOptions,\n ): RemoteSource<OwnedLease, AllocationError | BrowserError | ContextError> =>\n (local, lifetimeDeadline) =>\n Effect.gen(function* () {\n const client = yield* BrowserbaseClient;\n const sessions = yield* BrowserbaseSessions;\n\n const acquired = yield* acquireRemote(\n {\n launch: options.launch,\n ...(options.contextWriter === undefined ? {} : { contextWriter: options.contextWriter }),\n allocationDeadline: lifetimeDeadline,\n ...(options.onCleanup === undefined ? {} : { onCleanup: options.onCleanup }),\n ...(options.onAllocationUncertain === undefined\n ? {}\n : { onAllocationUncertain: options.onAllocationUncertain }),\n },\n local,\n );\n\n return {\n ...withConnection(acquired),\n ...providerControls(client, sessions, acquired.reference),\n };\n });\n\n/** Borrows a running session: local connection only, and never a release request. */\nexport const borrowedRemote =\n (options: {\n readonly reference: SessionReference;\n readonly pendingWaitMillis?: number;\n readonly onCleanup?: (result: CleanupResult) => Effect.Effect<void>;\n }): RemoteSource<RemoteLease, SessionError> =>\n (local) =>\n Effect.gen(function* () {\n const client = yield* BrowserbaseClient;\n const sessions = yield* BrowserbaseSessions;\n const acquired = yield* attachRemote(options, local);\n\n return {\n ...withConnection(acquired),\n ...providerControls(client, sessions, acquired.reference),\n };\n });\n","import {\n Context,\n Crypto,\n Effect,\n Layer,\n type Option,\n type Redacted,\n Schema,\n type Scope,\n} from \"effect\";\nimport type { BrowserSession, OpenOptions, OperationOptions, Page } from \"effect-browser/browser\";\nimport type {\n ActionResult,\n AutomationOptions,\n BrowserPolicy,\n ClickRequest,\n Inventory,\n} from \"effect-browser/browser-data\";\nimport * as BrowserRuntime from \"effect-browser/browser-runtime\";\nimport {\n BrowserError,\n Reasons,\n type BrowserOperation,\n type InitializationError,\n} from \"effect-browser/errors\";\n\nimport { BrowserbaseBrowserBinding } from \"./BrowserBinding.ts\";\nimport type { CleanupResult } from \"./Cleanup.ts\";\nimport { BrowserbaseClient } from \"./Client.ts\";\nimport type { AllocationError, ContextError, SessionError } from \"./Errors.ts\";\nimport type { LiveView } from \"./internal/browser/LiveView.ts\";\nimport { isList } from \"./internal/List.ts\";\nimport { borrowedRemote, ownedRemote, type RemoteLease } from \"./internal/session/Browser.ts\";\nimport type { ContextWriterPermit } from \"./internal/session/WriterFacts.ts\";\nimport { issuedUpload } from \"./internal/upload/Issued.ts\";\nimport type { LaunchRecipe } from \"./Launch.ts\";\nimport type { AllocationAttempt, SessionReference } from \"./References.ts\";\nimport { BrowserbaseSessions } from \"./Sessions.ts\";\nimport { DownloadObservation, type SelectFilesRequest } from \"./Transfers.ts\";\n\nexport type { LiveView } from \"./internal/browser/LiveView.ts\";\nexport type { FileSelection, SelectFilesRequest } from \"./Transfers.ts\";\n\n/** Host configuration. Credentials live in the Client; a model never selects these values. */\nexport interface BrowserOptions extends AutomationOptions {\n readonly launch: LaunchRecipe;\n /** Required whenever the launch recipe persists a context. */\n readonly contextWriter?: ContextWriterPermit;\n readonly onCleanup?: (result: CleanupResult) => Effect.Effect<void>;\n readonly onAllocationUncertain?: (attempt: AllocationAttempt) => Effect.Effect<void>;\n}\n\nexport interface Handoff {\n readonly token: Redacted.Redacted<string>;\n readonly view: LiveView;\n}\n\n/** Browserbase identity, remote artifacts and provider cleanup remain hosted capabilities. */\nexport interface BrowserbaseSession<E = never> extends BrowserSession<E> {\n readonly reference: SessionReference;\n readonly closeChecked: Effect.Effect<CleanupResult, BrowserError>;\n /** Transfers take the issued Page first, like `Capture.start(page)` and `PageControl`. */\n readonly clickForDownload: (\n page: Page,\n request: ClickRequest,\n options?: OperationOptions,\n ) => Effect.Effect<DownloadObservation, BrowserError>;\n /** Attaches to an existing file input; an uploaded branch needs a receipt for this session. */\n readonly selectFiles: (\n page: Page,\n request: SelectFilesRequest,\n options?: OperationOptions,\n ) => Effect.Effect<ActionResult, BrowserError>;\n /** Registers the chooser observation before the single click that opens it. */\n readonly clickForFileSelection: (\n page: Page,\n request: SelectFilesRequest,\n options?: OperationOptions,\n ) => Effect.Effect<ActionResult, BrowserError>;\n readonly liveView: (\n expiresInSeconds?: number,\n options?: OperationOptions,\n ) => Effect.Effect<LiveView, BrowserError>;\n readonly beginHandoff: (\n expiresInSeconds?: number,\n options?: OperationOptions,\n ) => Effect.Effect<Handoff, BrowserError>;\n readonly resume: (\n token: Redacted.Redacted<string>,\n operatorReleasedControl: boolean,\n options?: OperationOptions,\n ) => Effect.Effect<Inventory, BrowserError>;\n readonly detach: Effect.Effect<\n {\n readonly reference: SessionReference;\n readonly targetId: string;\n readonly inventory: Inventory;\n },\n BrowserError\n >;\n readonly reconnect: (\n operatorReleasedControl: boolean,\n options?: OperationOptions,\n ) => Effect.Effect<Inventory, BrowserError | InitializationError>;\n readonly close: Effect.Effect<CleanupResult>;\n readonly cleanupResult: Effect.Effect<Option.Option<CleanupResult>>;\n}\n\nexport interface AttachRequest<E = never, R = never> extends OpenOptions<E, R> {\n readonly policy: BrowserPolicy;\n /** The exact page to resume; without it the session must have exactly one page. */\n readonly target?: { readonly targetId: string };\n /** Bounded admission of a session the provider has not finished starting. */\n readonly pendingWaitMillis?: number;\n}\n\nexport interface BrowserAcquisition<E = never> {\n readonly reference: SessionReference;\n readonly attempt: AllocationAttempt;\n readonly failure: Effect.Effect<never, E | InitializationError>;\n readonly connect: Effect.Effect<BrowserbaseSession<E>, BrowserError | E | InitializationError>;\n readonly close: Effect.Effect<CleanupResult>;\n}\n\n/** Only receipts issued for this exact provider session may resolve to stored paths. */\nconst selection = (\n request: SelectFilesRequest,\n reference: SessionReference,\n operation: BrowserOperation,\n): Effect.Effect<BrowserRuntime.ResolvedFileSelection, BrowserError> =>\n Effect.suspend(() => {\n if (request.selection._tag === \"Inline\")\n return Effect.succeed<BrowserRuntime.ResolvedFileSelection>({\n _tag: \"Inline\",\n files: request.selection.files,\n });\n\n const uploads = request.selection.uploads;\n\n if (!isList(uploads) || uploads.length < 1 || uploads.length > 8)\n return Effect.fail(\n BrowserError.make({\n operation,\n reason: Reasons.Configuration.make({}),\n outcome: \"undispatched\",\n }),\n );\n const paths: string[] = [];\n\n for (const receipt of uploads) {\n const issued = issuedUpload(receipt);\n\n if (\n issued === undefined ||\n issued.reference.projectId !== reference.projectId ||\n issued.reference.sessionId !== reference.sessionId\n )\n return Effect.fail(\n BrowserError.make({\n operation,\n reason: Reasons.Authorization.make({}),\n outcome: \"undispatched\",\n }),\n );\n paths.push(issued.remotePath);\n }\n\n return Effect.succeed<BrowserRuntime.ResolvedFileSelection>({ _tag: \"Stored\", paths });\n });\n\nconst makeSession = <E>(\n connection: BrowserRuntime.Connection<SessionReference, E>,\n lifetime: RemoteLease,\n): BrowserbaseSession<E> => {\n const { session, operations } = connection;\n\n const transfers = (page: Page): Effect.Effect<BrowserRuntime.TransferOperations, BrowserError> =>\n operations.forPage(page);\n\n // Decorating the same object preserves its private capture and page-control associations.\n return Object.assign(session, {\n reference: lifetime.reference,\n closeChecked: session.closeChecked.pipe(Effect.andThen(lifetime.closeChecked)),\n clickForDownload: (page, request, options) =>\n transfers(page).pipe(\n Effect.flatMap((operations) => operations.clickForDownload(request, options)),\n Effect.flatMap((event) =>\n Schema.decodeEffect(DownloadObservation)({\n ...event,\n reference: lifetime.reference,\n }).pipe(\n Effect.mapError(() =>\n BrowserError.make({\n operation: \"download-action\",\n reason: Reasons.Malformed.make({}),\n outcome: \"performed\",\n }),\n ),\n ),\n ),\n ),\n selectFiles: (page, request, options) =>\n transfers(page).pipe(\n Effect.flatMap((operations) =>\n selection(request, lifetime.reference, \"select-files\").pipe(\n Effect.flatMap((files) =>\n operations.selectFiles({ selector: request.selector, selection: files }, options),\n ),\n ),\n ),\n ),\n clickForFileSelection: (page, request, options) =>\n transfers(page).pipe(\n Effect.flatMap((operations) =>\n selection(request, lifetime.reference, \"file-chooser\").pipe(\n Effect.flatMap((files) =>\n operations.clickForFileSelection(\n { selector: request.selector, selection: files },\n options,\n ),\n ),\n ),\n ),\n ),\n liveView: (ttl = 60, options) => operations.liveView(lifetime.liveView(ttl), options),\n beginHandoff: (ttl = 60, options) => operations.beginHandoff(lifetime.liveView(ttl), options),\n resume: operations.resume,\n detach: operations.detach,\n reconnect: operations.reconnect,\n close: lifetime.release,\n cleanupResult: lifetime.cleanupResult,\n } satisfies Omit<BrowserbaseSession<E>, Exclude<keyof BrowserSession<E>, \"closeChecked\">>);\n};\n\nexport class BrowserbaseBrowser extends Context.Service<\n BrowserbaseBrowser,\n {\n readonly acquire: <E = never, R = never>(\n policy: BrowserPolicy,\n request?: OpenOptions<E, R>,\n ) => Effect.Effect<\n BrowserAcquisition<E>,\n AllocationError | BrowserError | ContextError,\n Scope.Scope | Exclude<R, Scope.Scope>\n >;\n /** Borrowed control of a session this process did not allocate and will not release. */\n readonly attach: <E = never, R = never>(\n reference: SessionReference,\n request: AttachRequest<E, R>,\n ) => Effect.Effect<\n BrowserbaseSession<E>,\n BrowserError | SessionError | E | InitializationError,\n Scope.Scope | Exclude<R, Scope.Scope>\n >;\n readonly open: <E = never, R = never>(\n policy: BrowserPolicy,\n request?: OpenOptions<E, R>,\n ) => Effect.Effect<\n BrowserbaseSession<E>,\n AllocationError | BrowserError | ContextError | E | InitializationError,\n Scope.Scope | Exclude<R, Scope.Scope>\n >;\n }\n>()(\"effect-browserbase/Browser\") {\n /** Open through the configured account and browser service, in the caller's scope. */\n static open<E = never, R = never>(policy: BrowserPolicy, request?: OpenOptions<E, R>) {\n return Effect.flatMap(BrowserbaseBrowser, (browser) => browser.open(policy, request));\n }\n\n /** Allocate the provider lifetime before connecting, preserving its attempt and cleanup. */\n static acquire<E = never, R = never>(policy: BrowserPolicy, request?: OpenOptions<E, R>) {\n return Effect.flatMap(BrowserbaseBrowser, (browser) => browser.acquire(policy, request));\n }\n\n /** Borrow a provider session without acquiring release authority over it. */\n static attach<E = never, R = never>(reference: SessionReference, request: AttachRequest<E, R>) {\n return Effect.flatMap(BrowserbaseBrowser, (browser) => browser.attach(reference, request));\n }\n\n /** Allocation attempts, connection ids and handoff tokens come from the required `Crypto`. */\n static layer(\n options: BrowserOptions,\n ): Layer.Layer<\n BrowserbaseBrowser,\n BrowserError,\n BrowserbaseClient | BrowserbaseSessions | Crypto.Crypto\n > {\n return Layer.effect(\n BrowserbaseBrowser,\n Effect.gen(function* () {\n const client = yield* BrowserbaseClient;\n const sessions = yield* BrowserbaseSessions;\n const crypto = yield* Crypto.Crypto;\n const binding = yield* BrowserbaseBrowserBinding;\n\n if (options.launch.context?.persist === true && options.contextWriter === undefined)\n return yield* BrowserError.make({\n operation: \"configure\",\n reason: Reasons.ContextLease.make({}),\n outcome: \"undispatched\",\n });\n if (Object.prototype.hasOwnProperty.call(options, \"bootstrap\"))\n return yield* BrowserError.make({\n operation: \"configure\",\n reason: Reasons.Configuration.make({}),\n outcome: \"undispatched\",\n });\n\n const runtime = yield* BrowserRuntime.make({\n implementation: \"browserbase-playwright-cdp\",\n binding,\n automation: projected(options),\n viewport:\n options.launch.viewport._tag === \"Fixed\"\n ? { width: options.launch.viewport.width, height: options.launch.viewport.height }\n : { width: 1280, height: 720 },\n preserveViewport: options.launch.viewport._tag !== \"Fixed\",\n keepAlive: options.launch.keepAlive === true,\n });\n\n const source =\n <L extends BrowserRuntime.Lifetime, E>(\n remote: BrowserRuntime.Source<\n L,\n E,\n BrowserbaseClient | BrowserbaseSessions | Crypto.Crypto\n >,\n ): BrowserRuntime.Source<L, E> =>\n (cleanup, deadline) =>\n remote(cleanup, deadline).pipe(\n Effect.provideService(BrowserbaseClient, client),\n Effect.provideService(BrowserbaseSessions, sessions),\n Effect.provideService(Crypto.Crypto, crypto),\n );\n\n const acquire = Effect.fnUntraced(function* <E = never, R = never>(\n policy: BrowserPolicy,\n request: OpenOptions<E, R> = {},\n ) {\n const acquired = yield* runtime.acquire(\n policy,\n source(\n ownedRemote({\n launch: options.launch,\n ...(options.contextWriter === undefined\n ? {}\n : { contextWriter: options.contextWriter }),\n ...(options.onCleanup === undefined ? {} : { onCleanup: options.onCleanup }),\n ...(options.onAllocationUncertain === undefined\n ? {}\n : { onAllocationUncertain: options.onAllocationUncertain }),\n }),\n ),\n request,\n );\n\n const connected = yield* Effect.cached(\n acquired.connect.pipe(\n Effect.map((connection) => makeSession(connection, acquired.lifetime)),\n ),\n );\n\n return {\n reference: acquired.reference,\n attempt: acquired.lifetime.attempt,\n failure: acquired.failure,\n close: acquired.close,\n connect: acquired.connect.pipe(Effect.andThen(connected)),\n } satisfies BrowserAcquisition<E>;\n });\n\n const attach = Effect.fnUntraced(function* <E = never, R = never>(\n reference: SessionReference,\n request: AttachRequest<E, R>,\n ) {\n const acquired = yield* runtime.acquire(\n request.policy,\n source(\n borrowedRemote({\n reference,\n ...(request.pendingWaitMillis === undefined\n ? {}\n : { pendingWaitMillis: request.pendingWaitMillis }),\n ...(options.onCleanup === undefined ? {} : { onCleanup: options.onCleanup }),\n }),\n ),\n {\n ...(request.bootstrap === undefined ? {} : { bootstrap: request.bootstrap }),\n existingTarget: request.target ?? {},\n },\n );\n\n return yield* acquired.connect.pipe(\n Effect.map((connection) => makeSession(connection, acquired.lifetime)),\n );\n });\n\n return BrowserbaseBrowser.of({\n acquire,\n attach,\n open: (policy, request) =>\n acquire(policy, request).pipe(Effect.flatMap((acquired) => acquired.connect)),\n });\n }),\n );\n }\n}\n\n/** Only the automation fields cross the schema boundary; launch and callbacks are separate. */\nconst projected = (options: BrowserOptions) => ({\n ...(options.timelineLimits === undefined ? {} : { timelineLimits: options.timelineLimits }),\n ...(options.admissionLimits === undefined ? {} : { admissionLimits: options.admissionLimits }),\n ...(options.observationLimits === undefined\n ? {}\n : { observationLimits: options.observationLimits }),\n ...(options.maxHostReads === undefined ? {} : { maxHostReads: options.maxHostReads }),\n ...(options.actionTimeoutMillis === undefined\n ? {}\n : { actionTimeoutMillis: options.actionTimeoutMillis }),\n ...(options.maxPages === undefined ? {} : { maxPages: options.maxPages }),\n ...(options.initialPage === undefined ? {} : { initialPage: options.initialPage }),\n ...(options.popupPolicy === undefined ? {} : { popupPolicy: options.popupPolicy }),\n ...(options.dialogPolicy === undefined ? {} : { dialogPolicy: options.dialogPolicy }),\n ...(options.pageControl === undefined ? {} : { pageControl: options.pageControl }),\n});\n"],"mappings":"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"}
@@ -7,9 +7,9 @@ import { n as CleanupResult } from "./Cleanup-DMTDBir8.mjs";
7
7
  import { n as ContextWriterPermit } from "./WriterFacts-BBJRDZYY.mjs";
8
8
  import { LaunchRecipe } from "./Launch.mjs";
9
9
  import { Context, Crypto, Effect, Layer, Option, Redacted, Scope } from "effect";
10
- import { ActionResult, AutomationOptions, BrowserPolicy, ClickRequest, Observation } from "effect-browser/browser-data";
10
+ import { ActionResult, AutomationOptions, BrowserPolicy, ClickRequest, Inventory } from "effect-browser/browser-data";
11
11
  import { BrowserError, InitializationError } from "effect-browser/errors";
12
- import { BrowserSession, OpenOptions } from "effect-browser/browser";
12
+ import { BrowserSession, OpenOptions, OperationOptions, Page } from "effect-browser/browser";
13
13
  //#region src/Browser.d.ts
14
14
  /** Host configuration. Credentials live in the Client; a model never selects these values. */
15
15
  export interface BrowserOptions extends AutomationOptions {
@@ -27,19 +27,21 @@ export interface Handoff {
27
27
  export interface BrowserbaseSession<E = never> extends BrowserSession<E> {
28
28
  readonly reference: SessionReference;
29
29
  readonly closeChecked: Effect.Effect<CleanupResult, BrowserError>;
30
- readonly clickForDownload: (request: ClickRequest) => Effect.Effect<DownloadObservation, BrowserError>;
30
+ /** Transfers take the issued Page first, like `Capture.start(page)` and `PageControl`. */
31
+ readonly clickForDownload: (page: Page, request: ClickRequest, options?: OperationOptions) => Effect.Effect<DownloadObservation, BrowserError>;
31
32
  /** Attaches to an existing file input; an uploaded branch needs a receipt for this session. */
32
- readonly selectFiles: (request: SelectFilesRequest) => Effect.Effect<ActionResult, BrowserError>;
33
+ readonly selectFiles: (page: Page, request: SelectFilesRequest, options?: OperationOptions) => Effect.Effect<ActionResult, BrowserError>;
33
34
  /** Registers the chooser observation before the single click that opens it. */
34
- readonly clickForFileSelection: (request: SelectFilesRequest) => Effect.Effect<ActionResult, BrowserError>;
35
- readonly liveView: (expiresInSeconds?: number) => Effect.Effect<LiveView, BrowserError>;
36
- readonly beginHandoff: (expiresInSeconds?: number) => Effect.Effect<Handoff, BrowserError>;
37
- readonly resume: (token: Redacted.Redacted<string>, operatorReleasedControl: boolean) => Effect.Effect<Observation, BrowserError>;
35
+ readonly clickForFileSelection: (page: Page, request: SelectFilesRequest, options?: OperationOptions) => Effect.Effect<ActionResult, BrowserError>;
36
+ readonly liveView: (expiresInSeconds?: number, options?: OperationOptions) => Effect.Effect<LiveView, BrowserError>;
37
+ readonly beginHandoff: (expiresInSeconds?: number, options?: OperationOptions) => Effect.Effect<Handoff, BrowserError>;
38
+ readonly resume: (token: Redacted.Redacted<string>, operatorReleasedControl: boolean, options?: OperationOptions) => Effect.Effect<Inventory, BrowserError>;
38
39
  readonly detach: Effect.Effect<{
39
40
  readonly reference: SessionReference;
40
41
  readonly targetId: string;
42
+ readonly inventory: Inventory;
41
43
  }, BrowserError>;
42
- readonly reconnect: (operatorReleasedControl: boolean) => Effect.Effect<Observation, BrowserError | InitializationError>;
44
+ readonly reconnect: (operatorReleasedControl: boolean, options?: OperationOptions) => Effect.Effect<Inventory, BrowserError | InitializationError>;
43
45
  readonly close: Effect.Effect<CleanupResult>;
44
46
  readonly cleanupResult: Effect.Effect<Option.Option<CleanupResult>>;
45
47
  }
package/dist/Browser.mjs CHANGED
@@ -1,3 +1,3 @@
1
1
  import "./BrowserBinding.mjs";
2
- import { t as BrowserbaseBrowser } from "./Browser-BPcF550A.mjs";
2
+ import { t as BrowserbaseBrowser } from "./Browser-ByrWJ0ss.mjs";
3
3
  export { BrowserbaseBrowser };
@@ -1,8 +1,8 @@
1
1
  import { Identifier } from "./References.mjs";
2
2
  import { CertificateError } from "./Errors.mjs";
3
+ import { r as span, t as BrowserbaseClient } from "./Client-BEC4Q8ZS.mjs";
3
4
  import { SafeFilename } from "./Transfers.mjs";
4
- import { t as BrowserbaseClient } from "./Client-4RMKIpL2.mjs";
5
- import { t as resource } from "./Resource-DBksC4zB.mjs";
5
+ import { t as resource } from "./Resource-J7Kkk5mu.mjs";
6
6
  import { Context, Effect, Layer, Schema } from "effect";
7
7
  //#region src/Certificates.ts
8
8
  const Timestamp = Schema.String.check(Schema.isMaxLength(64));
@@ -44,7 +44,7 @@ var BrowserbaseCertificates = class BrowserbaseCertificates extends Context.Serv
44
44
  ...rest
45
45
  });
46
46
  });
47
- const create = Effect.fn("BrowserbaseCertificates.create")(function* (upload) {
47
+ const create = Effect.fnUntraced(function* (upload) {
48
48
  const { bytes, ...options } = upload;
49
49
  const value = yield* api.input(Upload, options, "certificate-create");
50
50
  const owned = new Uint8Array(bytes);
@@ -59,18 +59,18 @@ var BrowserbaseCertificates = class BrowserbaseCertificates extends Context.Serv
59
59
  }).pipe(Effect.mapError(api.fromClient("certificate-create")));
60
60
  const created = yield* Schema.decodeUnknownEffect(ProviderCertificate)(raw).pipe(Effect.mapError(() => api.malformed("certificate-create", true)));
61
61
  return yield* own("certificate-create", true)(created);
62
- });
63
- const list = api.request("GET", "/v1/certificates", Schema.Array(ProviderCertificate).check(Schema.isMaxLength(1024)), "certificate-list").pipe(Effect.flatMap(Effect.forEach(own("certificate-list", false))), Effect.withSpan("BrowserbaseCertificates.list"));
64
- const retrieve = Effect.fn("BrowserbaseCertificates.retrieve")(function* (certificateId) {
62
+ }, span("BrowserbaseCertificates.create"));
63
+ const list = api.request("GET", "/v1/certificates", Schema.Array(ProviderCertificate).check(Schema.isMaxLength(1024)), "certificate-list").pipe(Effect.flatMap(Effect.forEach(own("certificate-list", false))), span("BrowserbaseCertificates.list"));
64
+ const retrieve = Effect.fnUntraced(function* (certificateId) {
65
65
  const id = yield* api.input(Identifier, certificateId, "certificate-retrieve");
66
66
  const value = yield* api.request("GET", `/v1/certificates/${api.segment(id)}`, ProviderCertificate, "certificate-retrieve");
67
67
  if (value.id !== id) return yield* api.malformed("certificate-retrieve", false);
68
68
  return yield* own("certificate-retrieve", false)(value);
69
- });
70
- const remove = Effect.fn("BrowserbaseCertificates.delete")(function* (certificateId) {
69
+ }, span("BrowserbaseCertificates.retrieve"));
70
+ const remove = Effect.fnUntraced(function* (certificateId) {
71
71
  const id = yield* api.input(Identifier, certificateId, "certificate-delete");
72
72
  yield* api.remove(`/v1/certificates/${api.segment(id)}`, "certificate-delete");
73
- });
73
+ }, span("BrowserbaseCertificates.delete"));
74
74
  return BrowserbaseCertificates.of({
75
75
  create,
76
76
  list,
@@ -1 +1 @@
1
- {"version":3,"file":"Certificates.mjs","names":[],"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 { 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.fn(\"BrowserbaseCertificates.create\")(function* (\n upload: CertificateUpload,\n ) {\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 });\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 Effect.withSpan(\"BrowserbaseCertificates.list\"),\n );\n\n const retrieve = Effect.fn(\"BrowserbaseCertificates.retrieve\")(function* (\n certificateId: string,\n ) {\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 });\n\n const remove = Effect.fn(\"BrowserbaseCertificates.delete\")(function* (\n certificateId: string,\n ) {\n const id = yield* api.input(Identifier, certificateId, \"certificate-delete\");\n\n yield* api.remove(`/v1/certificates/${api.segment(id)}`, \"certificate-delete\");\n });\n\n return BrowserbaseCertificates.of({ create, list, retrieve, delete: remove });\n }),\n );\n}\n"],"mappings":"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"}
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,8 +1,117 @@
1
1
  import { Identifier } from "./References.mjs";
2
- import { ClientError } from "./Errors.mjs";
2
+ import { AllocationError, ArtifactError, CertificateError, ClientError, ContextError, ExtensionError, FileError, PlatformError, ProjectError, SessionError } from "./Errors.mjs";
3
3
  import { SafeFilename } from "./Transfers.mjs";
4
- import { Clock, Config, Context, Duration, Effect, Layer, Random, Redacted, Schema, Stream } from "effect";
4
+ import { Cause, Clock, Config, Context, Duration, Effect, Exit, Layer, Option, Random, Redacted, References, Schema, Stream, Tracer } from "effect";
5
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
6
115
  //#region src/internal/http/Multipart.ts
7
116
  const FIELD = /^[a-z][a-z0-9_]{0,31}$/;
8
117
  const MEDIA_TYPE = /^[a-z0-9][a-z0-9!#$&^_+.-]{0,63}\/[a-z0-9][a-z0-9!#$&^_+.-]{0,63}$/;
@@ -69,6 +178,13 @@ const encodeFilePart = Effect.fnUntraced(function* (part, maxBytes, boundaries =
69
178
  const API_ORIGIN = "https://api.browserbase.com";
70
179
  const MAX_JSON_BYTES = 1048576;
71
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";
72
188
  const Options = Schema.Struct({
73
189
  projectId: Identifier,
74
190
  apiKey: Schema.Redacted(Schema.NonEmptyString.check(Schema.isMaxLength(8192), Schema.isPattern(/^[\x21-\x7e]+$/))),
@@ -193,7 +309,10 @@ const makeTransport = Effect.fnUntraced(function* (options) {
193
309
  operation,
194
310
  reason: "transport",
195
311
  ...outcome === void 0 ? {} : { outcome }
196
- })));
312
+ })), span("BrowserbaseClient.execute", { attributes: {
313
+ "browser.operation": operation,
314
+ "http.request.method": traceMethod(request.method)
315
+ } }));
197
316
  /** A rejected path is a typed, undispatched configuration failure, never a defect. */
198
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({
199
318
  operation,
@@ -249,7 +368,7 @@ const makeTransport = Effect.fnUntraced(function* (options) {
249
368
  reason: "malformed",
250
369
  ...mutationOutcome(method) === void 0 ? {} : { outcome: mutationOutcome(method) }
251
370
  })));
252
- });
371
+ }, span("BrowserbaseClient.decodeJson"));
253
372
  const jsonOnce = Effect.fnUntraced(function* (method, path, body) {
254
373
  const operation = method === "GET" ? "provider-read" : "provider-mutation";
255
374
  let request = yield* apiRequest(method, path, "application/json", operation);
@@ -282,11 +401,17 @@ const makeTransport = Effect.fnUntraced(function* (options) {
282
401
  const request = HttpClientRequest.bodyUint8Array(yield* apiRequest("POST", path, "application/json", operation), encoded.body, encoded.contentType);
283
402
  const deadline = Math.min(yield* deadlineAfter(timeoutMillis), outerDeadline ?? Infinity);
284
403
  return yield* within(Effect.scoped(execute(request, operation, "unknown").pipe(Effect.flatMap((response) => readJson("POST", response, operation)))), deadline, operation, "unknown");
285
- });
404
+ }, span("BrowserbaseClient.upload", { attributes: {
405
+ "browser.operation": "provider-upload",
406
+ "http.request.method": "POST"
407
+ } }));
286
408
  const json = Effect.fnUntraced(function* (method, path, body, outerDeadline) {
287
409
  const deadline = Math.min(yield* deadlineAfter(requestTimeoutMillis), outerDeadline ?? Infinity);
288
410
  for (let attempt = 0;; attempt++) {
289
- const result = yield* within(Effect.scoped(jsonOnce(method, path, body)), deadline, method === "GET" ? "provider-read" : "provider-mutation", method === "GET" ? void 0 : "unknown").pipe(Effect.result);
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);
290
415
  if (result._tag === "Success") return result.success;
291
416
  const error = result.failure;
292
417
  const retryable = error.reason === "transport" || error.reason === "rate-limited" || error.reason === "provider" && (error.status ?? 0) >= 500;
@@ -295,7 +420,10 @@ const makeTransport = Effect.fnUntraced(function* (options) {
295
420
  if ((yield* nowMillis) + delay >= deadline) return yield* error;
296
421
  yield* Effect.sleep(delay);
297
422
  }
298
- });
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
+ } })));
299
427
  const noContent = Effect.fnUntraced(function* (method, path, body, outerDeadline) {
300
428
  const operation = "provider-mutation";
301
429
  let request = yield* apiRequest(method, path, "*/*", operation);
@@ -311,7 +439,10 @@ const makeTransport = Effect.fnUntraced(function* (options) {
311
439
  202,
312
440
  204
313
441
  ].includes(response.status)) return yield* statusError(method, response.status, operation, retryAfter(response.headers["retry-after"], yield* Clock.currentTimeMillis));
314
- });
442
+ }, (effect, method) => effect.pipe(span("BrowserbaseClient.noContent", { attributes: {
443
+ "browser.operation": "provider-mutation",
444
+ "http.request.method": traceMethod(method)
445
+ } })));
315
446
  const inspectBytes = Effect.fnUntraced(function* (response, operation, types, maximum) {
316
447
  if (response.status !== 200 && response.status !== 206) return yield* statusError("GET", response.status, operation, retryAfter(response.headers["retry-after"], yield* Clock.currentTimeMillis));
317
448
  if (!types.includes(mediaType(response.headers["content-type"]))) return yield* ClientError.make({
@@ -347,7 +478,10 @@ const makeTransport = Effect.fnUntraced(function* (options) {
347
478
  const response = yield* within(execute(request, operation), deadline, operation);
348
479
  const stream = yield* inspectBytes(response, operation, types, maximum);
349
480
  return Stream.transformPull(stream, (pull) => Effect.succeed(within(pull, deadline, operation)));
350
- })).pipe(Stream.scoped);
481
+ })).pipe(Stream.scoped, stream("BrowserbaseClient.bytes", { attributes: {
482
+ "browser.operation": "provider-read",
483
+ "http.request.method": "GET"
484
+ } }));
351
485
  const text = (path, maximum, types) => collect(bytes(path, maximum, types), maximum, "provider-read").pipe(Effect.flatMap((body) => Effect.try({
352
486
  try: () => new TextDecoder("utf-8", { fatal: true }).decode(body),
353
487
  catch: () => ClientError.make({
@@ -360,7 +494,10 @@ const makeTransport = Effect.fnUntraced(function* (options) {
360
494
  operation: "provider-read",
361
495
  reason: "timeout"
362
496
  }))
363
- }));
497
+ }), span("BrowserbaseClient.text", { attributes: {
498
+ "browser.operation": "provider-read",
499
+ "http.request.method": "GET"
500
+ } }));
364
501
  const validateMediaUrl = (value) => {
365
502
  try {
366
503
  const url = new URL(value);
@@ -379,7 +516,10 @@ const makeTransport = Effect.fnUntraced(function* (options) {
379
516
  const response = yield* within(execute(HttpClientRequest.get(value), "media-download"), deadline, "media-download");
380
517
  const stream = yield* inspectBytes(response, "media-download", types, maximum);
381
518
  return Stream.transformPull(stream, (pull) => Effect.succeed(within(pull, deadline, "media-download")));
382
- })).pipe(Stream.scoped);
519
+ })).pipe(Stream.scoped, stream("BrowserbaseClient.media", { attributes: {
520
+ "browser.operation": "media-download",
521
+ "http.request.method": "GET"
522
+ } }));
383
523
  return {
384
524
  projectId: configured.projectId,
385
525
  json,
@@ -390,7 +530,7 @@ const makeTransport = Effect.fnUntraced(function* (options) {
390
530
  media,
391
531
  validateMediaUrl
392
532
  };
393
- });
533
+ }, span("BrowserbaseClient.configure"));
394
534
  //#endregion
395
535
  //#region src/Client.ts
396
536
  /**
@@ -419,6 +559,6 @@ var BrowserbaseClient = class BrowserbaseClient extends Context.Service()("effec
419
559
  }
420
560
  };
421
561
  //#endregion
422
- export { BrowserbaseClient as t };
562
+ export { stream as i, annotate as n, span as r, BrowserbaseClient as t };
423
563
 
424
- //# sourceMappingURL=Client-4RMKIpL2.mjs.map
564
+ //# sourceMappingURL=Client-BEC4Q8ZS.mjs.map