effect-browserbase 0.1.0-beta.102 → 0.1.0-beta.104

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.
@@ -1,2 +1,2 @@
1
- import { i as playwright, n as layer, r as layerPlaywright, t as BrowserbaseBrowserBinding } from "./BrowserBinding-qbQA6JhH.mjs";
1
+ import { i as playwright, n as layer, r as layerPlaywright, t as BrowserbaseBrowserBinding } from "./BrowserBinding-DlJTGYZL.mjs";
2
2
  export { BrowserbaseBrowserBinding, layer, layerPlaywright, playwright };
@@ -131,6 +131,27 @@ var CaptureSummary = class extends Schema.Class("BrowserbaseCaptureSummary")({
131
131
  upstreamDrops: Schema.Literal("unknown"),
132
132
  error: Schema.optionalKey(BrowserError)
133
133
  }) {};
134
+ const { reason: StopReason, nativeStop: NativeStop, ...SnapshotFields } = CaptureSummary.fields;
135
+ /**
136
+ * Host-side metadata at one instant, without reading or waking the page. The boundary prefix
137
+ * and loss counters are the same facts as the final summary, independent of frame consumption.
138
+ * `stopped` means native cleanup settled; buffered frames may still be drained afterwards.
139
+ */
140
+ var CaptureSnapshot = class extends Schema.Class("BrowserbaseCaptureSnapshot")({
141
+ ...SnapshotFields,
142
+ phase: Schema.Literals([
143
+ "capturing",
144
+ "stopping",
145
+ "stopped"
146
+ ]),
147
+ observedMonotonicNanos: Schema.BigInt,
148
+ /** Keeps counting when the bounded boundary prefix is truncated. */
149
+ currentDocument: Schema.Natural,
150
+ /** No reason is reported while the capture still accepts frames. */
151
+ reason: Schema.NullOr(StopReason),
152
+ /** Null until the native cleanup attempt settles; unconfirmed never means stopped remotely. */
153
+ nativeStop: Schema.NullOr(NativeStop)
154
+ }) {};
134
155
  //#endregion
135
156
  //#region src/internal/capture/FrameBuffer.ts
136
157
  /** Callback-side bounded retention. No Promise, Effect, blocked producer, or per-frame fiber. */
@@ -297,11 +318,17 @@ const startCapture = Effect.fnUntraced(function* (parent, options = {}) {
297
318
  sourceFirstMillis: first ?? null,
298
319
  sourceLastMillis: last ?? null,
299
320
  initialUrl,
300
- documentBoundaries: [...documentBoundaries],
321
+ documentBoundaries: documentBoundaries.map((boundary) => ({ ...boundary })),
301
322
  documentBoundariesTruncated,
302
323
  nativeStop,
303
324
  upstreamDrops: "unknown",
304
- ...error === void 0 ? {} : { error }
325
+ ...error === void 0 ? {} : { error: BrowserError.make({
326
+ operation: error.operation,
327
+ reason: error.reason,
328
+ ...error.outcome === void 0 ? {} : { outcome: error.outcome },
329
+ ...error.status === void 0 ? {} : { status: error.status },
330
+ ...error.retryAfterMillis === void 0 ? {} : { retryAfterMillis: error.retryAfterMillis }
331
+ }) }
305
332
  });
306
333
  };
307
334
  const stopNative = (yield* Effect.cached(Effect.uninterruptibleMask((restore) => Effect.gen(function* () {
@@ -487,6 +514,17 @@ const startCapture = Effect.fnUntraced(function* (parent, options = {}) {
487
514
  subscribed = true;
488
515
  return Effect.succeed(Stream.fromEffectRepeat(next).pipe(Stream.ensuring(stopNative.pipe(Effect.asVoid))));
489
516
  })),
517
+ snapshot: Effect.sync(() => {
518
+ const { reason, nativeStop, ...metadata } = snapshot();
519
+ return CaptureSnapshot.make({
520
+ ...metadata,
521
+ phase: cleanupFinished ? "stopped" : ended ? "stopping" : "capturing",
522
+ observedMonotonicNanos: clock.monotonicTimeNanosUnsafe(),
523
+ currentDocument: document,
524
+ reason: ended ? reason : null,
525
+ nativeStop: cleanupFinished ? nativeStop : null
526
+ });
527
+ }),
490
528
  stop: stopNative,
491
529
  completed: Deferred.await(completed).pipe(Effect.map(snapshot))
492
530
  };
@@ -496,6 +534,7 @@ const startCapture = Effect.fnUntraced(function* (parent, options = {}) {
496
534
  var Capture_exports = /* @__PURE__ */ __exportAll({
497
535
  CaptureOptions: () => CaptureOptions,
498
536
  CaptureSize: () => CaptureSize,
537
+ CaptureSnapshot: () => CaptureSnapshot,
499
538
  CaptureSummary: () => CaptureSummary,
500
539
  CapturedFrame: () => CapturedFrame,
501
540
  start: () => start
@@ -527,6 +566,6 @@ const start = (session, options = {}) => Effect.suspend(() => {
527
566
  })));
528
567
  });
529
568
  //#endregion
530
- export { CaptureSummary as a, CaptureSize as i, start as n, CapturedFrame as o, CaptureOptions as r, Capture_exports as t };
569
+ export { CaptureSnapshot as a, CaptureSize as i, start as n, CaptureSummary as o, CaptureOptions as r, CapturedFrame as s, Capture_exports as t };
531
570
 
532
- //# sourceMappingURL=Capture-CZJPuD7b.mjs.map
571
+ //# sourceMappingURL=Capture-Bc0z9IAi.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Capture-Bc0z9IAi.mjs","names":[],"sources":["../src/internal/capture/CaptureTypes.ts","../src/internal/capture/FrameBuffer.ts","../src/internal/capture/Capture.ts","../src/Capture.ts"],"sourcesContent":["import { Schema, type Effect, type Stream } from \"effect\";\n\nimport { PageInfo, Target } from \"../../BrowserData.ts\";\nimport { BrowserError } from \"../../Errors.ts\";\nconst Dimension = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 16384 }));\nconst BufferedBytes = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 64 * 1024 * 1024 }));\n\n/** Defaults shared by admission and the optional public data schema. */\nexport const CaptureDefaults = Object.freeze({\n maxFrames: 4,\n maxBufferedBytes: 16 * 1024 * 1024,\n maxFrameBytes: 4 * 1024 * 1024,\n maxDurationMillis: 60000,\n quality: 80,\n});\n\nconst LimitFields = {\n maxFrames: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 64 })),\n maxBufferedBytes: BufferedBytes,\n maxFrameBytes: BufferedBytes,\n maxDurationMillis: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 600000 })),\n quality: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 100 })),\n};\n\nconst FrameBudget = Schema.makeFilter(\n (value: { readonly maxFrameBytes?: number; readonly maxBufferedBytes?: number }) =>\n (value.maxFrameBytes ?? CaptureDefaults.maxFrameBytes) <=\n (value.maxBufferedBytes ?? CaptureDefaults.maxBufferedBytes),\n { message: \"A frame must fit within the resolved buffer budget\" },\n);\n\n/** Private resolved admission schema. It is not an additional public options API. */\nexport const CaptureLimits = Schema.Struct(LimitFields).check(FrameBudget);\n\n/**\n * Binary frame data, not a live capability or a JSON/thread/Tool value. Decoding validates\n * fields; it does not copy bytes, decode JPEG pixels, prove target authority, or repair clocks.\n * Capture itself owns the byte copy, freezes its shared target identity, and verifies JPEG framing.\n */\nexport const CapturedFrame = Schema.Struct({\n bytes: Schema.Uint8Array.check(Schema.isMinLength(4), Schema.isMaxLength(64 * 1024 * 1024)),\n mediaType: Schema.Literal(\"image/jpeg\"),\n target: Target,\n sequence: Schema.Natural,\n /**\n * Which document of its page this frame was received during: 0 at the start, one more for each\n * main-frame navigation the interval observed. It is attribution by receipt order, not proof\n * of whose pixels these are: a frame received just after a navigation can still show the\n * document before it. Always 0 for an interval that lasts one document.\n */\n document: Schema.Natural,\n sourceTimeMillis: Schema.Finite.check(Schema.isGreaterThan(0)),\n sourceClock: Schema.Literal(\"presentation-unix-millis\"),\n receivedMonotonicNanos: Schema.BigInt,\n width: Dimension,\n height: Dimension,\n viewportWidth: Dimension,\n viewportHeight: Dimension,\n}).check(\n Schema.makeFilter((frame) => frame.width * frame.height <= 33_554_432, {\n message: \"Frame geometry exceeds the capture pixel bound\",\n }),\n);\n\nexport type CapturedFrame = typeof CapturedFrame.Type;\n\n/** Source-fit request in pixels. Actual JPEG bounds are checked before any frame is delivered. */\nexport const CaptureSize = Schema.Struct({ width: Dimension, height: Dimension });\n\nexport type CaptureSize = typeof CaptureSize.Type;\n\n/** Optional capture data. Defaults are applied at admission, not during schema decoding. */\nexport const CaptureOptions = Schema.Struct({\n /** Pin to a page from `session.pages`; omission preserves selected-page behavior. */\n target: Schema.optionalKey(PageInfo),\n maxFrames: Schema.optionalKey(LimitFields.maxFrames),\n maxBufferedBytes: Schema.optionalKey(LimitFields.maxBufferedBytes),\n maxFrameBytes: Schema.optionalKey(LimitFields.maxFrameBytes),\n maxDurationMillis: Schema.optionalKey(LimitFields.maxDurationMillis),\n quality: Schema.optionalKey(LimitFields.quality),\n /** Source fit only. Does not resize the viewport or impose an FPS cap. */\n size: Schema.optionalKey(CaptureSize),\n /**\n * `document`, the default, ends the interval when its page navigates. `page` follows the page\n * across documents, so a capture started before a navigation covers the loading in between.\n * It applies to a page's main frame; a capture bound to a child frame still ends with it.\n */\n lifetime: Schema.optionalKey(Schema.Literals([\"document\", \"page\"])),\n}).check(FrameBudget);\n\nexport type CaptureOptions = typeof CaptureOptions.Type;\n\n/** An address as the browser reported it. One longer than this is recorded as null, not cut. */\nconst DocumentUrl = Schema.NullOr(Schema.String.check(Schema.isMaxLength(8192)));\n\nexport class CaptureSummary extends Schema.Class<CaptureSummary>(\"BrowserbaseCaptureSummary\")({\n target: Target,\n reason: Schema.String.check(Schema.isMaxLength(64)),\n received: Schema.Natural,\n delivered: Schema.Natural,\n dropped: Schema.Natural,\n duplicates: Schema.Natural,\n /** Arrived after a newer frame was accepted; counted within `dropped`, never reordered in. */\n late: Schema.Natural,\n peakBufferedFrames: Schema.Natural,\n peakBufferedBytes: Schema.Natural,\n bufferedFrames: Schema.Natural,\n bufferedBytes: Schema.Natural,\n sourceFirstMillis: Schema.NullOr(Schema.Finite),\n sourceLastMillis: Schema.NullOr(Schema.Finite),\n /**\n * The captured frame's address when this interval began watching it: the URL of document 0.\n * It is read in the same turn the watch is installed, so no navigation can fall between them.\n */\n initialUrl: DocumentUrl,\n /**\n * Each main-frame navigation a `page` interval observed, in order, with the last frame\n * received before it and the address the new document committed. The native screencast is\n * never restarted for one, so a boundary is not a gap this package introduced; what Chromium\n * omitted while loading stays `upstreamDrops`. A boundary is the commit. When that navigation\n * started and when its document finished loading are the caller's to stamp, on this same\n * clock, around the operation that caused it. A title is page state, not part of a transition.\n */\n documentBoundaries: Schema.Array(\n Schema.Struct({\n document: Schema.Natural,\n observedMonotonicNanos: Schema.BigInt,\n afterSequence: Schema.NullOr(Schema.Natural),\n url: DocumentUrl,\n }),\n ).check(Schema.isMaxLength(64)),\n /** More navigations were observed than are recorded above. Frames still count them all. */\n documentBoundariesTruncated: Schema.Boolean,\n nativeStop: Schema.Literals([\"confirmed\", \"unconfirmed\"]),\n /** Package accounting cannot measure frames omitted by Chromium, transport, or the provider. */\n upstreamDrops: Schema.Literal(\"unknown\"),\n error: Schema.optionalKey(BrowserError),\n}) {}\n\nconst { reason: StopReason, nativeStop: NativeStop, ...SnapshotFields } = CaptureSummary.fields;\n\n/**\n * Host-side metadata at one instant, without reading or waking the page. The boundary prefix\n * and loss counters are the same facts as the final summary, independent of frame consumption.\n * `stopped` means native cleanup settled; buffered frames may still be drained afterwards.\n */\nexport class CaptureSnapshot extends Schema.Class<CaptureSnapshot>(\"BrowserbaseCaptureSnapshot\")({\n ...SnapshotFields,\n phase: Schema.Literals([\"capturing\", \"stopping\", \"stopped\"]),\n observedMonotonicNanos: Schema.BigInt,\n /** Keeps counting when the bounded boundary prefix is truncated. */\n currentDocument: Schema.Natural,\n /** No reason is reported while the capture still accepts frames. */\n reason: Schema.NullOr(StopReason),\n /** Null until the native cleanup attempt settles; unconfirmed never means stopped remotely. */\n nativeStop: Schema.NullOr(NativeStop),\n}) {}\n\n/** Live stream/Effect capabilities intentionally have no data schema or serialization contract. */\nexport interface CaptureInterval {\n /** Single subscription. Ending or interrupting it stops this interval, not its browser. */\n readonly frames: Stream.Stream<CapturedFrame, BrowserError>;\n /**\n * A bounded copy of recorded metadata, available during capture and after cleanup. No native\n * work, budget charge or subscription. Drain frames, then read `completed` for final accounting.\n */\n readonly snapshot: Effect.Effect<CaptureSnapshot>;\n readonly stop: Effect.Effect<CaptureSummary>;\n readonly completed: Effect.Effect<CaptureSummary>;\n}\n","/** Callback-side bounded retention. No Promise, Effect, blocked producer, or per-frame fiber. */\nexport class FrameBuffer<A extends { readonly bytes: Uint8Array }> {\n readonly maximumFrames: number;\n readonly maximumBytes: number;\n private readonly items: A[] = [];\n private retained = 0;\n dropped = 0;\n received = 0;\n highWaterBytes = 0;\n highWaterFrames = 0;\n\n constructor(maximumFrames: number, maximumBytes: number) {\n if (\n !Number.isSafeInteger(maximumFrames) ||\n maximumFrames < 1 ||\n maximumFrames > 64 ||\n !Number.isSafeInteger(maximumBytes) ||\n maximumBytes < 1 ||\n maximumBytes > 64 * 1024 * 1024\n ) {\n throw new RangeError(\"Invalid capture retention limits\");\n }\n this.maximumFrames = maximumFrames;\n this.maximumBytes = maximumBytes;\n }\n\n offer(frame: A): boolean {\n this.received++;\n if (frame.bytes.byteLength > this.maximumBytes) {\n this.dropped++;\n\n return false;\n }\n while (\n this.items.length >= this.maximumFrames ||\n this.retained + frame.bytes.byteLength > this.maximumBytes\n ) {\n const removed = this.items.shift();\n\n if (removed === undefined) break;\n this.retained -= removed.bytes.byteLength;\n this.dropped++;\n }\n this.items.push(frame);\n this.retained += frame.bytes.byteLength;\n this.highWaterBytes = Math.max(this.highWaterBytes, this.retained);\n this.highWaterFrames = Math.max(this.highWaterFrames, this.items.length);\n\n return true;\n }\n\n take(): A | undefined {\n const frame = this.items.shift();\n\n if (frame !== undefined) this.retained -= frame.bytes.byteLength;\n\n return frame;\n }\n\n clear(): void {\n this.items.length = 0;\n this.retained = 0;\n }\n\n get size(): number {\n return this.items.length;\n }\n get bytes(): number {\n return this.retained;\n }\n}\n","import { Cause, Clock, Deferred, Effect, Exit, Queue, Schema, Stream } from \"effect\";\n\nimport type { Target } from \"../../BrowserData.ts\";\nimport { BrowserError } from \"../../Errors.ts\";\nimport { type CaptureLease, type CaptureParent } from \"../browser/Association.ts\";\nimport type { CaptureSource, NativeFrame } from \"../browser/Driver.ts\";\nimport {\n CaptureDefaults,\n CaptureLimits,\n CaptureSize,\n CaptureSnapshot,\n CaptureSummary,\n type CaptureInterval,\n type CaptureOptions,\n type CapturedFrame,\n} from \"./CaptureTypes.ts\";\nimport { FrameBuffer } from \"./FrameBuffer.ts\";\nimport { jpegGeometry } from \"./Images.ts\";\n\nconst MaxParentCaptures = 4;\nconst MaxParentBufferedBytes = 64 * 1024 * 1024;\nconst MaxDocumentBoundaries = 64;\nconst MaxDocumentUrlLength = 8192;\n\n/** An over-long address is recorded as null rather than cut into one that was never shown. */\nconst documentUrl = (url: unknown): string | null =>\n typeof url === \"string\" && url.length <= MaxDocumentUrlLength ? url : null;\n\n/**\n * Chromium stamps a screencast frame on its UI thread, encodes it on an unsequenced thread\n * pool, and emits it when that encode completes. It admits a new frame while at most two are\n * unacknowledged (`kMaxScreencastFramesInFlight`), so up to three encode at once and two\n * frames stamped close together can complete in either order. Every frame stamped before an\n * accepted one was already in flight when that one was stamped, so at most two late frames\n * can arrive in a row. A longer run is source time that really went backwards.\n */\nconst MaxConsecutiveLateFrames = 2;\n\n// Synchronous Schema decoding at the callback boundary; no Effect/Fiber is allocated for each frame.\nconst Metadata = Schema.Struct({\n timestamp: Schema.Finite.check(Schema.isGreaterThan(0)),\n viewportWidth: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 16384 })),\n viewportHeight: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 16384 })),\n});\n\nconst parseMetadata = Schema.decodeUnknownSync(Metadata);\n\n/** Private seam for deterministic callback/lifetime tests. The public start accepts a real live session. */\nexport const startCapture = Effect.fnUntraced(function* (\n parent: CaptureParent,\n options: CaptureOptions = {},\n) {\n const maxFrames = options.maxFrames ?? CaptureDefaults.maxFrames;\n const maxBytes = options.maxBufferedBytes ?? CaptureDefaults.maxBufferedBytes;\n const maxFrameBytes = options.maxFrameBytes ?? CaptureDefaults.maxFrameBytes;\n const duration = options.maxDurationMillis ?? CaptureDefaults.maxDurationMillis;\n const quality = options.quality ?? CaptureDefaults.quality;\n\n const size =\n options.size === undefined\n ? undefined\n : yield* Schema.decodeEffect(CaptureSize)(options.size, { onExcessProperty: \"error\" }).pipe(\n Effect.map(({ width, height }) => Object.freeze({ width, height })),\n Effect.mapError(() =>\n BrowserError.make({\n operation: \"capture\",\n reason: \"configuration\",\n outcome: \"undispatched\",\n }),\n ),\n );\n\n yield* Schema.decodeEffect(CaptureLimits)({\n maxFrames,\n maxBufferedBytes: maxBytes,\n maxFrameBytes,\n maxDurationMillis: duration,\n quality,\n }).pipe(\n Effect.mapError(() =>\n BrowserError.make({\n operation: \"capture\",\n reason: \"configuration\",\n outcome: \"undispatched\",\n }),\n ),\n );\n const clock = yield* Clock.Clock;\n const wake = yield* Queue.dropping<void>(1);\n const finished = yield* Queue.dropping<void>(1);\n const completed = yield* Deferred.make<void>();\n\n yield* Effect.addFinalizer(() =>\n Queue.shutdown(wake).pipe(Effect.andThen(Queue.shutdown(finished)), Effect.asVoid),\n );\n const buffer = new FrameBuffer<CapturedFrame>(maxFrames, maxBytes);\n let source: CaptureSource | undefined;\n let startPromise: Promise<void> | undefined;\n let startSettled = true;\n let target: Target | undefined;\n let leaseKey: string | undefined;\n\n let ended = false,\n subscribed = false,\n cleanupFinished = false;\n\n let reason = \"stopped\";\n let error: BrowserError | undefined;\n\n let received = 0,\n delivered = 0,\n rejected = 0,\n duplicates = 0,\n late = 0,\n lateRun = 0;\n\n let first: number | undefined, last: number | undefined;\n let document = 0;\n let initialUrl: string | null = null;\n let documentBoundariesTruncated = false;\n const documentBoundaries: Array<CaptureSummary[\"documentBoundaries\"][number]> = [];\n\n /** The page navigated and its screencast kept running: later frames belong to a new document. */\n const nextDocument = (url: string): void => {\n if (ended) return;\n document++;\n if (documentBoundaries.length >= MaxDocumentBoundaries) documentBoundariesTruncated = true;\n else\n documentBoundaries.push({\n document,\n observedMonotonicNanos: clock.monotonicTimeNanosUnsafe(),\n afterSequence: received === 0 ? null : received - 1,\n url: documentUrl(url),\n });\n };\n\n let geometry:\n | { width: number; height: number; viewportWidth: number; viewportHeight: number }\n | undefined;\n\n let nativeStop: CaptureSummary[\"nativeStop\"] = \"unconfirmed\";\n let lease: CaptureLease | undefined;\n\n const finish = (why: string, failure?: BrowserError) => {\n if (ended) return;\n ended = true;\n reason = why;\n error = failure;\n Queue.offerUnsafe(wake, undefined);\n Queue.offerUnsafe(finished, undefined);\n };\n\n const snapshot = (): CaptureSummary => {\n if (target === undefined) throw new Error(\"Capture target was not admitted\");\n\n return CaptureSummary.make({\n target,\n reason,\n received,\n delivered,\n dropped: buffer.dropped + rejected,\n duplicates,\n late,\n peakBufferedFrames: buffer.highWaterFrames,\n peakBufferedBytes: buffer.highWaterBytes,\n bufferedFrames: buffer.size,\n bufferedBytes: buffer.bytes,\n sourceFirstMillis: first ?? null,\n sourceLastMillis: last ?? null,\n initialUrl,\n documentBoundaries: documentBoundaries.map((boundary) => ({ ...boundary })),\n documentBoundariesTruncated,\n nativeStop,\n upstreamDrops: \"unknown\",\n ...(error === undefined\n ? {}\n : {\n error: BrowserError.make({\n operation: error.operation,\n reason: error.reason,\n ...(error.outcome === undefined ? {} : { outcome: error.outcome }),\n ...(error.status === undefined ? {} : { status: error.status }),\n ...(error.retryAfterMillis === undefined\n ? {}\n : { retryAfterMillis: error.retryAfterMillis }),\n }),\n }),\n });\n };\n\n const performStop = yield* Effect.cached(\n Effect.uninterruptibleMask((restore) =>\n Effect.gen(function* () {\n finish(\"stopped\");\n // Wait for an in-flight start before stop. If it will not settle, quarantine this page lease.\n if (startPromise !== undefined && !startSettled) {\n yield* restore(\n Effect.tryPromise({\n try: () => startPromise!,\n catch: () => BrowserError.make({ operation: \"capture-start\", reason: \"provider\" }),\n }).pipe(Effect.timeout(2000), Effect.exit),\n );\n }\n if (source !== undefined) {\n const stopped = yield* restore(\n Effect.tryPromise({\n try: () => source!.stop(),\n catch: () => BrowserError.make({ operation: \"capture-stop\", reason: \"provider\" }),\n }).pipe(Effect.timeout(3000)),\n ).pipe(Effect.exit);\n\n if (Exit.isSuccess(stopped) && startSettled) nativeStop = \"confirmed\";\n } else nativeStop = \"confirmed\";\n // No older attachment may clear a replacement. Unconfirmed native cleanup quarantines only this page.\n if (\n nativeStop === \"confirmed\" &&\n leaseKey !== undefined &&\n lease !== undefined &&\n parent.captureLeases.get(leaseKey) === lease\n ) {\n parent.captureLeases.delete(leaseKey);\n parent.captureReservedBytes = Math.max(\n 0,\n parent.captureReservedBytes - lease.reservedBytes,\n );\n }\n cleanupFinished = true;\n\n return snapshot();\n }),\n ),\n );\n\n // Publish completion only after the cached cleanup Exit has settled. Publishing\n // inside it lets the caller close Scope and interrupt the caching fiber first.\n const stopNative = performStop.pipe(Effect.tap(() => Deferred.succeed(completed, undefined)));\n\n const receive = (frame: NativeFrame): void => {\n if (ended) return;\n if (\n target === undefined ||\n parent.owner.state.generation !== target.generation ||\n parent.owner.state.phase !== \"open\"\n ) {\n finish(\"parent-unavailable\", BrowserError.make({ operation: \"capture\", reason: \"closed\" }));\n\n return;\n }\n const sequence = received++;\n\n try {\n const meta = parseMetadata(frame);\n\n if (!(frame.data instanceof Uint8Array) || frame.data.length > maxFrameBytes) {\n rejected++;\n finish(\"frame-limit\", BrowserError.make({ operation: \"capture\", reason: \"limit\" }));\n\n return;\n }\n if (last !== undefined && meta.timestamp < last) {\n // A newer frame is already accepted, so this one can no longer be presented in order.\n // It is discarded and counted rather than sorted in or given an invented time.\n rejected++;\n late++;\n if (++lateRun > MaxConsecutiveLateFrames) {\n finish(\n \"timestamp-discontinuity\",\n BrowserError.make({ operation: \"capture\", reason: \"timestamp\" }),\n );\n }\n\n return;\n }\n if (last === meta.timestamp) {\n duplicates++;\n rejected++;\n\n return;\n }\n const dimensions = jpegGeometry(frame.data);\n\n if (\n dimensions.width > 16384 ||\n dimensions.height > 16384 ||\n (size !== undefined &&\n (dimensions.width > size.width || dimensions.height > size.height)) ||\n dimensions.width * dimensions.height > 33_554_432 ||\n frame.data[frame.data.length - 2] !== 255 ||\n frame.data[frame.data.length - 1] !== 217\n ) {\n rejected++;\n finish(\"frame-limit\", BrowserError.make({ operation: \"capture\", reason: \"limit\" }));\n\n return;\n }\n if (\n geometry !== undefined &&\n (geometry.width !== dimensions.width ||\n geometry.height !== dimensions.height ||\n geometry.viewportWidth !== meta.viewportWidth ||\n geometry.viewportHeight !== meta.viewportHeight)\n ) {\n rejected++;\n finish(\"resized\", BrowserError.make({ operation: \"capture\", reason: \"resized\" }));\n\n return;\n }\n geometry ??= {\n ...dimensions,\n viewportWidth: meta.viewportWidth,\n viewportHeight: meta.viewportHeight,\n };\n first ??= meta.timestamp;\n last = meta.timestamp;\n lateRun = 0;\n buffer.offer({\n bytes: new Uint8Array(frame.data),\n mediaType: \"image/jpeg\",\n target,\n sequence,\n document,\n sourceTimeMillis: meta.timestamp,\n sourceClock: \"presentation-unix-millis\",\n receivedMonotonicNanos: clock.monotonicTimeNanosUnsafe(),\n ...dimensions,\n viewportWidth: meta.viewportWidth,\n viewportHeight: meta.viewportHeight,\n });\n Queue.offerUnsafe(wake, undefined);\n } catch {\n rejected++;\n finish(\"malformed-frame\", BrowserError.make({ operation: \"capture\", reason: \"malformed\" }));\n }\n };\n\n yield* parent.owner\n .guard(\n \"capture-start\",\n (ticket) =>\n Effect.gen(function* () {\n const resolved = yield* parent.resolve(ticket, options.target);\n\n // Frames and summaries share this identity with the generation guard. It must not\n // become writable through consumer-owned frame data.\n target = Object.freeze(resolved.target);\n source = resolved.source;\n leaseKey = resolved.key;\n if (parent.captureLeases.has(leaseKey)) {\n return yield* BrowserError.make({\n operation: \"capture\",\n reason: \"busy\",\n outcome: \"undispatched\",\n });\n }\n if (\n parent.captureLeases.size >= MaxParentCaptures ||\n parent.captureReservedBytes + maxBytes > MaxParentBufferedBytes\n ) {\n return yield* BrowserError.make({\n operation: \"capture\",\n reason: \"limit\",\n outcome: \"undispatched\",\n });\n }\n lease = {\n reservedBytes: maxBytes,\n stop: stopNative.pipe(Effect.asVoid),\n invalidate: (why) =>\n finish(\n why,\n BrowserError.make({\n operation: \"capture\",\n reason: why === \"resized\" ? \"resized\" : \"target-changed\",\n }),\n ),\n };\n parent.captureLeases.set(leaseKey, lease);\n parent.captureReservedBytes += maxBytes;\n // Installed before native acquisition. A cancelled capture cannot escape its caller's scope.\n yield* Effect.addFinalizer(() =>\n stopNative.pipe(\n Effect.andThen(\n Effect.sync(() => {\n rejected += buffer.size;\n buffer.clear();\n }),\n ),\n ),\n );\n startSettled = false;\n yield* Effect.tryPromise({\n try: () => {\n startPromise = source!.start({\n receive,\n quality,\n invalidate: (why) => lease?.invalidate(why),\n opened: (url) => {\n initialUrl = documentUrl(url);\n },\n ...(size === undefined ? {} : { size }),\n ...(options.lifetime === \"page\" ? { document: nextDocument } : {}),\n });\n void startPromise.then(\n () => {\n startSettled = true;\n if (\n cleanupFinished &&\n nativeStop === \"unconfirmed\" &&\n leaseKey !== undefined &&\n parent.captureLeases.get(leaseKey) === lease\n ) {\n // One late acquisition cleanup, not a callback-side worker. Keep the page quarantined.\n void source!.stop().catch(() => {});\n }\n },\n () => {\n startSettled = true;\n },\n );\n\n return startPromise;\n },\n catch: () => BrowserError.make({ operation: \"capture-start\", reason: \"provider\" }),\n });\n ticket.check();\n }),\n { charge: false },\n )\n .pipe(\n Effect.onError(() => (lease === undefined ? Effect.void : stopNative.pipe(Effect.asVoid))),\n Effect.onInterrupt(() =>\n lease === undefined ? Effect.void : stopNative.pipe(Effect.asVoid),\n ),\n );\n // One monitor, not a fiber per frame. The finalizer also calls stop directly if this monitor is interrupted.\n // The timeout and explicit-finish branches intentionally carry different\n // values before shared cleanup; preserve the proven first-completion semantics.\n // @effect-diagnostics-next-line raceFirstWithSleepToTimeout:off\n yield* Effect.raceFirst(\n Queue.take(finished).pipe(Effect.as(false)),\n Effect.sleep(duration).pipe(Effect.as(true)),\n ).pipe(\n Effect.tap((expired) => (expired ? Effect.sync(() => finish(\"duration-limit\")) : Effect.void)),\n Effect.andThen(stopNative),\n Effect.forkScoped,\n );\n\n const next: Effect.Effect<CapturedFrame, BrowserError | Cause.Done> = Effect.suspend(() => {\n const frame = buffer.take();\n\n if (frame !== undefined) {\n delivered++;\n\n return Effect.succeed(frame);\n }\n if (ended) return error === undefined ? Cause.done() : Effect.fail(error);\n\n return Queue.take(wake).pipe(Effect.andThen(next));\n });\n\n const frames = Stream.unwrap(\n Effect.suspend(() => {\n if (subscribed)\n return Effect.fail(BrowserError.make({ operation: \"capture-consume\", reason: \"busy\" }));\n subscribed = true;\n\n return Effect.succeed(\n Stream.fromEffectRepeat(next).pipe(Stream.ensuring(stopNative.pipe(Effect.asVoid))),\n );\n }),\n );\n\n return {\n frames,\n snapshot: Effect.sync(() => {\n const { reason, nativeStop, ...metadata } = snapshot();\n\n return CaptureSnapshot.make({\n ...metadata,\n phase: cleanupFinished ? \"stopped\" : ended ? \"stopping\" : \"capturing\",\n observedMonotonicNanos: clock.monotonicTimeNanosUnsafe(),\n currentDocument: document,\n reason: ended ? reason : null,\n nativeStop: cleanupFinished ? nativeStop : null,\n });\n }),\n stop: stopNative,\n completed: Deferred.await(completed).pipe(Effect.map(snapshot)),\n } satisfies CaptureInterval;\n});\n","import { Effect, Schema, type Scope } from \"effect\";\n\nimport type { BrowserSession } from \"./Browser.ts\";\nimport { PageInfo } from \"./BrowserData.ts\";\nimport { BrowserError } from \"./Errors.ts\";\nimport { captureParent } from \"./internal/browser/Association.ts\";\nimport { startCapture } from \"./internal/capture/Capture.ts\";\nimport type { CaptureInterval, CaptureOptions } from \"./internal/capture/CaptureTypes.ts\";\n\nexport {\n CapturedFrame,\n CaptureOptions,\n CaptureSize,\n CaptureSnapshot,\n CaptureSummary,\n} from \"./internal/capture/CaptureTypes.ts\";\n\nexport type { CaptureInterval } from \"./internal/capture/CaptureTypes.ts\";\n\n/**\n * Capture one remote page independently of the session's selected page.\n *\n * Requires the exact live session returned by the host; copying a session object or decoding\n * a durable reference cannot copy its capture authority. The private owner is not frame data.\n * `CapturedFrame` and `CaptureOptions` are Schema values as well as structural types. Frame\n * decoding checks binary/metadata fields, not the complete JPEG bitstream or target authority,\n * and does not copy bytes. Options decoding preserves omissions; admission applies defaults.\n * `CaptureInterval` remains a live scoped capability, not a schema or JSON/Tool value.\n */\nexport const start = <E>(\n session: BrowserSession<E>,\n options: CaptureOptions = {},\n): Effect.Effect<CaptureInterval, BrowserError, Scope.Scope> =>\n Effect.suspend(() => {\n const parent = captureParent(session);\n\n if (parent === undefined)\n return Effect.fail(BrowserError.make({ operation: \"capture\", reason: \"closed\" }));\n if (options.target === undefined) return startCapture(parent, options);\n\n return Schema.decodeEffect(PageInfo)(options.target, { onExcessProperty: \"error\" }).pipe(\n Effect.mapError(() =>\n BrowserError.make({\n operation: \"capture\",\n reason: \"configuration\",\n outcome: \"undispatched\",\n }),\n ),\n Effect.flatMap((target) => startCapture(parent, { ...options, target })),\n );\n });\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { BrowserError } from "./Errors.mjs";
2
2
  import { E as PageInfo, L as Target } from "./BrowserData-LpcAuAub.mjs";
3
- import { BrowserbaseSession } from "./Browser.mjs";
3
+ import { BrowserSession } from "./Browser.mjs";
4
4
  import { Effect, Schema, Scope, Stream } from "effect";
5
5
  //#region src/internal/capture/CaptureTypes.d.ts
6
6
  /**
@@ -99,15 +99,58 @@ declare const CaptureSummary_base: Schema.Class<CaptureSummary, Schema.Struct<{
99
99
  readonly error: Schema.optionalKey<typeof BrowserError>;
100
100
  }>, {}>;
101
101
  declare class CaptureSummary extends CaptureSummary_base {}
102
+ declare const CaptureSnapshot_base: Schema.Class<CaptureSnapshot, Schema.Struct<{
103
+ readonly target: typeof Target;
104
+ readonly received: Schema.Natural;
105
+ readonly delivered: Schema.Natural;
106
+ readonly dropped: Schema.Natural;
107
+ readonly duplicates: Schema.Natural;
108
+ readonly late: Schema.Natural;
109
+ readonly peakBufferedFrames: Schema.Natural;
110
+ readonly peakBufferedBytes: Schema.Natural;
111
+ readonly bufferedFrames: Schema.Natural;
112
+ readonly bufferedBytes: Schema.Natural;
113
+ readonly sourceFirstMillis: Schema.NullOr<Schema.Finite>;
114
+ readonly sourceLastMillis: Schema.NullOr<Schema.Finite>;
115
+ readonly initialUrl: Schema.NullOr<Schema.String>;
116
+ readonly documentBoundaries: Schema.$Array<Schema.Struct<{
117
+ readonly document: Schema.Natural;
118
+ readonly observedMonotonicNanos: Schema.BigInt;
119
+ readonly afterSequence: Schema.NullOr<Schema.Natural>;
120
+ readonly url: Schema.NullOr<Schema.String>;
121
+ }>>;
122
+ readonly documentBoundariesTruncated: Schema.Boolean;
123
+ readonly upstreamDrops: Schema.Literal<"unknown">;
124
+ readonly error: Schema.optionalKey<typeof BrowserError>;
125
+ readonly phase: Schema.Literals<readonly ["capturing", "stopping", "stopped"]>;
126
+ readonly observedMonotonicNanos: Schema.BigInt;
127
+ /** Keeps counting when the bounded boundary prefix is truncated. */
128
+ readonly currentDocument: Schema.Natural;
129
+ /** No reason is reported while the capture still accepts frames. */
130
+ readonly reason: Schema.NullOr<Schema.String>;
131
+ /** Null until the native cleanup attempt settles; unconfirmed never means stopped remotely. */
132
+ readonly nativeStop: Schema.NullOr<Schema.Literals<readonly ["confirmed", "unconfirmed"]>>;
133
+ }>, {}>;
134
+ /**
135
+ * Host-side metadata at one instant, without reading or waking the page. The boundary prefix
136
+ * and loss counters are the same facts as the final summary, independent of frame consumption.
137
+ * `stopped` means native cleanup settled; buffered frames may still be drained afterwards.
138
+ */
139
+ declare class CaptureSnapshot extends CaptureSnapshot_base {}
102
140
  /** Live stream/Effect capabilities intentionally have no data schema or serialization contract. */
103
141
  interface CaptureInterval {
104
142
  /** Single subscription. Ending or interrupting it stops this interval, not its browser. */
105
143
  readonly frames: Stream.Stream<CapturedFrame, BrowserError>;
144
+ /**
145
+ * A bounded copy of recorded metadata, available during capture and after cleanup. No native
146
+ * work, budget charge or subscription. Drain frames, then read `completed` for final accounting.
147
+ */
148
+ readonly snapshot: Effect.Effect<CaptureSnapshot>;
106
149
  readonly stop: Effect.Effect<CaptureSummary>;
107
150
  readonly completed: Effect.Effect<CaptureSummary>;
108
151
  }
109
152
  declare namespace Capture_d_exports {
110
- export { CaptureInterval, CaptureOptions, CaptureSize, CaptureSummary, CapturedFrame, start };
153
+ export { CaptureInterval, CaptureOptions, CaptureSize, CaptureSnapshot, CaptureSummary, CapturedFrame, start };
111
154
  }
112
155
  /**
113
156
  * Capture one remote page independently of the session's selected page.
@@ -119,7 +162,7 @@ declare namespace Capture_d_exports {
119
162
  * and does not copy bytes. Options decoding preserves omissions; admission applies defaults.
120
163
  * `CaptureInterval` remains a live scoped capability, not a schema or JSON/Tool value.
121
164
  */
122
- declare const start: <E>(session: BrowserbaseSession<E>, options?: CaptureOptions) => Effect.Effect<CaptureInterval, BrowserError, Scope.Scope>;
165
+ declare const start: <E>(session: BrowserSession<E>, options?: CaptureOptions) => Effect.Effect<CaptureInterval, BrowserError, Scope.Scope>;
123
166
  //#endregion
124
- export { CaptureSize as a, CaptureOptions as i, start as n, CaptureSummary as o, CaptureInterval as r, CapturedFrame as s, Capture_d_exports as t };
125
- //# sourceMappingURL=Capture-Dr5MkIJb.d.mts.map
167
+ export { CaptureSize as a, CapturedFrame as c, CaptureOptions as i, start as n, CaptureSnapshot as o, CaptureInterval as r, CaptureSummary as s, Capture_d_exports as t };
168
+ //# sourceMappingURL=Capture-BvWI-l1A.d.mts.map
@@ -1,2 +1,2 @@
1
- import { a as CaptureSize, i as CaptureOptions, n as start, o as CaptureSummary, r as CaptureInterval, s as CapturedFrame } from "./Capture-Dr5MkIJb.mjs";
2
- export { type CaptureInterval, CaptureOptions, CaptureSize, CaptureSummary, CapturedFrame, start };
1
+ import { a as CaptureSize, c as CapturedFrame, i as CaptureOptions, n as start, o as CaptureSnapshot, r as CaptureInterval, s as CaptureSummary } from "./Capture-BvWI-l1A.mjs";
2
+ export { type CaptureInterval, CaptureOptions, CaptureSize, CaptureSnapshot, CaptureSummary, CapturedFrame, start };
package/dist/Capture.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { a as CaptureSummary, i as CaptureSize, n as start, o as CapturedFrame, r as CaptureOptions } from "./Capture-CZJPuD7b.mjs";
2
- export { CaptureOptions, CaptureSize, CaptureSummary, CapturedFrame, start };
1
+ import { a as CaptureSnapshot, i as CaptureSize, n as start, o as CaptureSummary, r as CaptureOptions, s as CapturedFrame } from "./Capture-Bc0z9IAi.mjs";
2
+ export { CaptureOptions, CaptureSize, CaptureSnapshot, CaptureSummary, CapturedFrame, start };
@@ -0,0 +1,79 @@
1
+ import { BrowserError, InitializationError } from "./Errors.mjs";
2
+ import { V as Viewport, i as BrowserPolicy, n as AutomationOptions } from "./BrowserData-LpcAuAub.mjs";
3
+ import { BrowserSession, OpenOptions } from "./Browser.mjs";
4
+ import { Context, Effect, Layer, Option, Redacted, Schema, Scope } from "effect";
5
+ //#region src/internal/browser/LocalData.d.ts
6
+ declare const LocalReference_base: Schema.Class<LocalReference, Schema.Struct<{
7
+ readonly provider: Schema.Literal<"local">;
8
+ readonly id: Schema.NonEmptyString;
9
+ }>, {}>;
10
+ /** Identifies this local ownership lifetime, not a Browserbase resource or a reusable endpoint. */
11
+ declare class LocalReference extends LocalReference_base {}
12
+ declare const LocalCleanupIssue_base: Schema.Class<LocalCleanupIssue, Schema.Struct<{
13
+ readonly step: Schema.Literals<readonly ["fence", "capture", "initialization", "disconnect", "terminate", "profile"]>;
14
+ readonly reason: Schema.Literals<readonly ["timeout", "failed", "interrupted"]>;
15
+ }>, {}>;
16
+ declare class LocalCleanupIssue extends LocalCleanupIssue_base {}
17
+ declare const LocalCleanupResult_base: Schema.Class<LocalCleanupResult, Schema.Struct<{
18
+ readonly reference: typeof LocalReference;
19
+ readonly ownership: Schema.Literals<readonly ["owned", "borrowed"]>;
20
+ readonly connection: Schema.Literals<readonly ["closed", "failed", "not-connected", "pending"]>;
21
+ readonly process: Schema.Literals<readonly ["terminated", "unknown", "not-owned"]>;
22
+ readonly issues: Schema.$Array<typeof LocalCleanupIssue>;
23
+ }>, {}>;
24
+ /** Connection teardown and observed process exit are separate facts; no provider status exists. */
25
+ declare class LocalCleanupResult extends LocalCleanupResult_base {}
26
+ declare const LocalLaunch: Schema.Struct<{
27
+ readonly executablePath: Schema.optionalKey<Schema.NonEmptyString>;
28
+ readonly headless: Schema.optionalKey<Schema.Boolean>;
29
+ /** Enabled by default; a trusted host must explicitly choose a sandbox exception. */
30
+ readonly chromiumSandbox: Schema.optionalKey<Schema.Boolean>;
31
+ readonly args: Schema.optionalKey<Schema.$Array<Schema.NonEmptyString>>;
32
+ readonly proxy: Schema.optionalKey<Schema.Struct<{
33
+ readonly server: Schema.NonEmptyString;
34
+ readonly bypass: Schema.optionalKey<Schema.NonEmptyString>;
35
+ }>>;
36
+ readonly startupTimeoutMillis: Schema.optionalKey<Schema.Int>;
37
+ }>;
38
+ type LocalLaunch = typeof LocalLaunch.Type;
39
+ declare namespace LocalBrowser_d_exports {
40
+ export { LocalAcquisition, LocalAttachRequest, LocalBrowser, LocalBrowserOptions, LocalCleanupIssue, LocalCleanupResult, LocalLaunch, LocalReference, LocalSession };
41
+ }
42
+ /** Host-only process configuration. Building this layer neither loads Playwright nor starts Chromium. */
43
+ interface LocalBrowserOptions extends AutomationOptions {
44
+ readonly launch?: LocalLaunch;
45
+ readonly viewport?: Viewport;
46
+ readonly onCleanup?: (result: LocalCleanupResult) => Effect.Effect<void>;
47
+ }
48
+ /** A local lifetime has modeled browser authority, never Browserbase resource or release authority. */
49
+ interface LocalSession<E = never> extends BrowserSession<E> {
50
+ readonly reference: LocalReference;
51
+ readonly close: Effect.Effect<LocalCleanupResult>;
52
+ readonly cleanupResult: Effect.Effect<Option.Option<LocalCleanupResult>>;
53
+ }
54
+ interface LocalAcquisition<E = never> {
55
+ readonly reference: LocalReference;
56
+ readonly failure: Effect.Effect<never, E | InitializationError>;
57
+ readonly connect: Effect.Effect<LocalSession<E>, BrowserError | InitializationError | E>;
58
+ readonly close: Effect.Effect<LocalCleanupResult>;
59
+ }
60
+ interface LocalAttachRequest<E = never, R = never> extends OpenOptions<E, R> {
61
+ readonly policy: BrowserPolicy;
62
+ /** Resolve this exact target; without it, multiple open pages are an ambiguity error. */
63
+ readonly target?: {
64
+ readonly targetId: string;
65
+ };
66
+ }
67
+ declare const LocalBrowser_base: Context.ServiceClass<LocalBrowser, "effect-browserbase/LocalBrowser", {
68
+ readonly acquire: <E = never, R = never>(policy: BrowserPolicy, request?: OpenOptions<E, R>) => Effect.Effect<LocalAcquisition<E>, BrowserError, Scope.Scope | Exclude<R, Scope.Scope>>;
69
+ readonly open: <E = never, R = never>(policy: BrowserPolicy, request?: OpenOptions<E, R>) => Effect.Effect<LocalSession<E>, BrowserError | InitializationError | E, Scope.Scope | Exclude<R, Scope.Scope>>;
70
+ /** A concrete loopback ws://.../devtools/browser/... endpoint; this scope owns only its connection. */
71
+ readonly attach: <E = never, R = never>(endpoint: Redacted.Redacted<string>, request: LocalAttachRequest<E, R>) => Effect.Effect<LocalSession<E>, BrowserError | InitializationError | E, Scope.Scope | Exclude<R, Scope.Scope>>;
72
+ readonly withBrowser: <E, R, A, E2, R2>(policy: BrowserPolicy, request: OpenOptions<E, R>, use: (session: LocalSession<E>) => Effect.Effect<A, E2, R2>) => Effect.Effect<A, BrowserError | InitializationError | E | E2, Exclude<R | R2, Scope.Scope>>;
73
+ }>;
74
+ declare class LocalBrowser extends LocalBrowser_base {
75
+ static layer(options?: LocalBrowserOptions): Layer.Layer<LocalBrowser, BrowserError>;
76
+ }
77
+ //#endregion
78
+ export { LocalBrowser_d_exports as a, LocalCleanupResult as c, LocalBrowserOptions as i, LocalLaunch as l, LocalAttachRequest as n, LocalSession as o, LocalBrowser as r, LocalCleanupIssue as s, LocalAcquisition as t, LocalReference as u };
79
+ //# sourceMappingURL=LocalBrowser-BLancJ3R.d.mts.map