@orkestrel/browser 0.0.22 → 0.0.24

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.
@@ -107,7 +107,7 @@ export declare const BROWSER_FRAME_WORLD_NAME = "__orkestrelBrowserFrame";
107
107
  */
108
108
  export declare const BROWSER_HAR_CREATOR: Readonly<{
109
109
  name: "@orkestrel/browser";
110
- version: "0.0.22";
110
+ version: "0.0.24";
111
111
  }>;
112
112
 
113
113
  /** Names accessibility roles that receive actionable outline references. */
@@ -159,7 +159,7 @@ export declare const BROWSER_JOURNEY_STEP_KEYS: readonly string[];
159
159
 
160
160
  /**
161
161
  * Names the journey tools a toolset constructed with `journeys` registers and reserves: `record`,
162
- * `save`, `journeys`, `edit`, `replay`, and `forget`.
162
+ * `save`, `journeys`, `edit`, `replay`, `forget`, and `capture`.
163
163
  */
164
164
  export declare const BROWSER_JOURNEY_TOOL_NAMES: readonly BrowserToolName[];
165
165
 
@@ -786,6 +786,8 @@ export declare interface BrowserContextInterface {
786
786
  * - `emulation` — emulation overrides inherited by every page of the context
787
787
  */
788
788
  export declare interface BrowserContextOptions {
789
+ /** Names each element reference the context's pages issue. Default: a counter the context owns. */
790
+ readonly reference?: BrowserReferenceFunction;
789
791
  readonly on?: EmitterHooks<BrowserContextEventMap>;
790
792
  readonly error?: EmitterErrorHandler;
791
793
  readonly proxy?: BrowserProxy;
@@ -1799,7 +1801,7 @@ export declare type BrowserJourneyEditRequest = BrowserJourneyEdit | {
1799
1801
  *
1800
1802
  * @remarks
1801
1803
  * - `store` — keeps the journeys the tools record, list, edit, and replay
1802
- * - `runs` — keeps each replay's run; omitting it writes no run
1804
+ * - `runs` — keeps each replay's run and saves standalone images when it provides `snapshot`
1803
1805
  * - `limit` — positive integer listing cap in characters; Default: the owner's `limit`, including direct construction
1804
1806
  * - `readonly` — if `true`, refuses `record`, `save`, `edit`, and `forget` before any store access, and
1805
1807
  * `replay` still writes runs; if `false` or omitted, every tool runs
@@ -1928,13 +1930,13 @@ export declare interface BrowserJourneyTarget {
1928
1930
  }
1929
1931
 
1930
1932
  /**
1931
- * Registers the journey tools `record`, `save`, `journeys`, `edit`, `replay`, and `forget` over a toolset
1933
+ * Registers the journey tools `record`, `save`, `journeys`, `edit`, `replay`, `forget`, and `capture` over a toolset
1932
1934
  * and owns the recording and the active replay.
1933
1935
  *
1934
1936
  * @remarks
1935
1937
  * The journey toolset composes the toolset's public members: `perform` reads the view a receipt
1936
1938
  * carries through `look`, `hold` and `emitter` drive the recorder and the replay, `view` converts
1937
- * an edit's `ref` to a target, and `tools` receives the six tools at construction, which refuses
1939
+ * an edit's `ref` to a target, and `tools` receives the journey tools at construction, which refuses
1938
1940
  * with `BROWSER_TOOLSET_RESERVED` when the manager already holds one of the names. Every refusal
1939
1941
  * is a sentence that names the next call, and a reason inside it is a clause without a directive
1940
1942
  * or a final period.
@@ -1950,7 +1952,7 @@ export declare interface BrowserJourneyTarget {
1950
1952
  * by the view after the run.
1951
1953
  *
1952
1954
  * `destroy()` aborts the active replay and waits for it to finish, stops a recording without
1953
- * saving it, and removes the six tools the manager still holds under the instances it added.
1955
+ * saving it, and removes the journey tools the manager still holds under the instances it added.
1954
1956
  *
1955
1957
  * @example
1956
1958
  * ```ts
@@ -1970,7 +1972,7 @@ export declare class BrowserJourneyToolset implements BrowserJourneyToolsetInter
1970
1972
  }
1971
1973
 
1972
1974
  /**
1973
- * Registers the six journey tools over a toolset and owns the recording and the active replay.
1975
+ * Registers the journey tools over a toolset and owns the recording and the active replay.
1974
1976
  *
1975
1977
  * @remarks
1976
1978
  * - `recording` — the name of the journey being recorded, or `undefined` when none is
@@ -1979,7 +1981,7 @@ export declare class BrowserJourneyToolset implements BrowserJourneyToolsetInter
1979
1981
  export declare interface BrowserJourneyToolsetInterface {
1980
1982
  readonly recording: string | undefined;
1981
1983
  readonly replaying: string | undefined;
1982
- /** Aborts the active replay and removes the six journey tools from the manager. */
1984
+ /** Aborts the active replay and removes the journey tools from the manager. */
1983
1985
  destroy(): Promise<void>;
1984
1986
  }
1985
1987
 
@@ -3481,6 +3483,14 @@ export declare interface BrowserRunStep {
3481
3483
 
3482
3484
  /** Keeps runs by the journey name and run id the run carries. */
3483
3485
  export declare interface BrowserRunStoreInterface {
3486
+ /**
3487
+ * Saves a standalone PNG under the runs root without replacing an existing file.
3488
+ * @param bytes - PNG bytes to persist
3489
+ * @param options - Cancellation options
3490
+ * @returns Absolute path of the saved image
3491
+ * @remarks Stores without standalone file storage omit this capability.
3492
+ */
3493
+ snapshot?(bytes: Uint8Array, options?: BrowserStoreOptions): Promise<string>;
3484
3494
  /** Mints a run id for the journey and creates its run directory exclusively. */
3485
3495
  open(name: string, options?: BrowserStoreOptions): Promise<BrowserRunSlot>;
3486
3496
  /** Returns the run stored under the journey name and id, or `undefined` when none is stored. */
@@ -3965,9 +3975,9 @@ export declare interface BrowserRunStoreInterface {
3965
3975
  /**
3966
3976
  * Names a tool the browser toolset reserves: the generic tools, the staged `dialog`, the
3967
3977
  * opt-in `tabs` and `switch`, and the journey tools `record`, `save`, `journeys`, `edit`,
3968
- * `replay`, and `forget`, which a toolset constructed with `journeys` reserves.
3978
+ * `replay`, `forget`, and `capture`, which a toolset constructed with `journeys` reserves.
3969
3979
  */
3970
- export declare type BrowserToolName = 'look' | 'read' | 'plain' | 'click' | 'type' | 'press' | 'navigate' | 'wait' | 'dialog' | 'tabs' | 'switch' | 'record' | 'save' | 'journeys' | 'edit' | 'replay' | 'forget';
3980
+ export declare type BrowserToolName = 'look' | 'read' | 'plain' | 'click' | 'type' | 'press' | 'navigate' | 'wait' | 'dialog' | 'tabs' | 'switch' | 'record' | 'save' | 'journeys' | 'edit' | 'replay' | 'forget' | 'capture';
3971
3981
 
3972
3982
  /** Identifies a removed WebMCP tool by document and name. */
3973
3983
  export declare interface BrowserToolRemoval {
@@ -107,7 +107,7 @@ export declare const BROWSER_FRAME_WORLD_NAME = "__orkestrelBrowserFrame";
107
107
  */
108
108
  export declare const BROWSER_HAR_CREATOR: Readonly<{
109
109
  name: "@orkestrel/browser";
110
- version: "0.0.22";
110
+ version: "0.0.24";
111
111
  }>;
112
112
 
113
113
  /** Names accessibility roles that receive actionable outline references. */
@@ -159,7 +159,7 @@ export declare const BROWSER_JOURNEY_STEP_KEYS: readonly string[];
159
159
 
160
160
  /**
161
161
  * Names the journey tools a toolset constructed with `journeys` registers and reserves: `record`,
162
- * `save`, `journeys`, `edit`, `replay`, and `forget`.
162
+ * `save`, `journeys`, `edit`, `replay`, `forget`, and `capture`.
163
163
  */
164
164
  export declare const BROWSER_JOURNEY_TOOL_NAMES: readonly BrowserToolName[];
165
165
 
@@ -786,6 +786,8 @@ export declare interface BrowserContextInterface {
786
786
  * - `emulation` — emulation overrides inherited by every page of the context
787
787
  */
788
788
  export declare interface BrowserContextOptions {
789
+ /** Names each element reference the context's pages issue. Default: a counter the context owns. */
790
+ readonly reference?: BrowserReferenceFunction;
789
791
  readonly on?: EmitterHooks<BrowserContextEventMap>;
790
792
  readonly error?: EmitterErrorHandler;
791
793
  readonly proxy?: BrowserProxy;
@@ -1799,7 +1801,7 @@ export declare type BrowserJourneyEditRequest = BrowserJourneyEdit | {
1799
1801
  *
1800
1802
  * @remarks
1801
1803
  * - `store` — keeps the journeys the tools record, list, edit, and replay
1802
- * - `runs` — keeps each replay's run; omitting it writes no run
1804
+ * - `runs` — keeps each replay's run and saves standalone images when it provides `snapshot`
1803
1805
  * - `limit` — positive integer listing cap in characters; Default: the owner's `limit`, including direct construction
1804
1806
  * - `readonly` — if `true`, refuses `record`, `save`, `edit`, and `forget` before any store access, and
1805
1807
  * `replay` still writes runs; if `false` or omitted, every tool runs
@@ -1928,13 +1930,13 @@ export declare interface BrowserJourneyTarget {
1928
1930
  }
1929
1931
 
1930
1932
  /**
1931
- * Registers the journey tools `record`, `save`, `journeys`, `edit`, `replay`, and `forget` over a toolset
1933
+ * Registers the journey tools `record`, `save`, `journeys`, `edit`, `replay`, `forget`, and `capture` over a toolset
1932
1934
  * and owns the recording and the active replay.
1933
1935
  *
1934
1936
  * @remarks
1935
1937
  * The journey toolset composes the toolset's public members: `perform` reads the view a receipt
1936
1938
  * carries through `look`, `hold` and `emitter` drive the recorder and the replay, `view` converts
1937
- * an edit's `ref` to a target, and `tools` receives the six tools at construction, which refuses
1939
+ * an edit's `ref` to a target, and `tools` receives the journey tools at construction, which refuses
1938
1940
  * with `BROWSER_TOOLSET_RESERVED` when the manager already holds one of the names. Every refusal
1939
1941
  * is a sentence that names the next call, and a reason inside it is a clause without a directive
1940
1942
  * or a final period.
@@ -1950,7 +1952,7 @@ export declare interface BrowserJourneyTarget {
1950
1952
  * by the view after the run.
1951
1953
  *
1952
1954
  * `destroy()` aborts the active replay and waits for it to finish, stops a recording without
1953
- * saving it, and removes the six tools the manager still holds under the instances it added.
1955
+ * saving it, and removes the journey tools the manager still holds under the instances it added.
1954
1956
  *
1955
1957
  * @example
1956
1958
  * ```ts
@@ -1970,7 +1972,7 @@ export declare class BrowserJourneyToolset implements BrowserJourneyToolsetInter
1970
1972
  }
1971
1973
 
1972
1974
  /**
1973
- * Registers the six journey tools over a toolset and owns the recording and the active replay.
1975
+ * Registers the journey tools over a toolset and owns the recording and the active replay.
1974
1976
  *
1975
1977
  * @remarks
1976
1978
  * - `recording` — the name of the journey being recorded, or `undefined` when none is
@@ -1979,7 +1981,7 @@ export declare class BrowserJourneyToolset implements BrowserJourneyToolsetInter
1979
1981
  export declare interface BrowserJourneyToolsetInterface {
1980
1982
  readonly recording: string | undefined;
1981
1983
  readonly replaying: string | undefined;
1982
- /** Aborts the active replay and removes the six journey tools from the manager. */
1984
+ /** Aborts the active replay and removes the journey tools from the manager. */
1983
1985
  destroy(): Promise<void>;
1984
1986
  }
1985
1987
 
@@ -3481,6 +3483,14 @@ export declare interface BrowserRunStep {
3481
3483
 
3482
3484
  /** Keeps runs by the journey name and run id the run carries. */
3483
3485
  export declare interface BrowserRunStoreInterface {
3486
+ /**
3487
+ * Saves a standalone PNG under the runs root without replacing an existing file.
3488
+ * @param bytes - PNG bytes to persist
3489
+ * @param options - Cancellation options
3490
+ * @returns Absolute path of the saved image
3491
+ * @remarks Stores without standalone file storage omit this capability.
3492
+ */
3493
+ snapshot?(bytes: Uint8Array, options?: BrowserStoreOptions): Promise<string>;
3484
3494
  /** Mints a run id for the journey and creates its run directory exclusively. */
3485
3495
  open(name: string, options?: BrowserStoreOptions): Promise<BrowserRunSlot>;
3486
3496
  /** Returns the run stored under the journey name and id, or `undefined` when none is stored. */
@@ -3965,9 +3975,9 @@ export declare interface BrowserRunStoreInterface {
3965
3975
  /**
3966
3976
  * Names a tool the browser toolset reserves: the generic tools, the staged `dialog`, the
3967
3977
  * opt-in `tabs` and `switch`, and the journey tools `record`, `save`, `journeys`, `edit`,
3968
- * `replay`, and `forget`, which a toolset constructed with `journeys` reserves.
3978
+ * `replay`, `forget`, and `capture`, which a toolset constructed with `journeys` reserves.
3969
3979
  */
3970
- export declare type BrowserToolName = 'look' | 'read' | 'plain' | 'click' | 'type' | 'press' | 'navigate' | 'wait' | 'dialog' | 'tabs' | 'switch' | 'record' | 'save' | 'journeys' | 'edit' | 'replay' | 'forget';
3980
+ export declare type BrowserToolName = 'look' | 'read' | 'plain' | 'click' | 'type' | 'press' | 'navigate' | 'wait' | 'dialog' | 'tabs' | 'switch' | 'record' | 'save' | 'journeys' | 'edit' | 'replay' | 'forget' | 'capture';
3971
3981
 
3972
3982
  /** Identifies a removed WebMCP tool by document and name. */
3973
3983
  export declare interface BrowserToolRemoval {
@@ -162,7 +162,7 @@ var BROWSER_MOUSE_BUTTON_MASKS = Object.freeze({
162
162
  */
163
163
  var BROWSER_HAR_CREATOR = Object.freeze({
164
164
  name: "@orkestrel/browser",
165
- version: "0.0.22"
165
+ version: "0.0.24"
166
166
  });
167
167
  /** Names the attribute that tags temporary screenshot styles and masks. */
168
168
  var BROWSER_SCREENSHOT_ATTRIBUTE = "data-orkestrel-screenshot";
@@ -741,7 +741,7 @@ var BROWSER_TOOL_COPY = Object.freeze({
741
741
  description: "The journey name, such as add-kettle."
742
742
  }),
743
743
  edits: Object.freeze({
744
- description: "The changes, as an array or a JSON string of the array, applied in order; one invalid change refuses them all.",
744
+ description: "The changes, as an array or its JSON string, applied in order; one invalid change refuses them all.",
745
745
  anyOf: Object.freeze([Object.freeze({
746
746
  type: "array",
747
747
  items: Object.freeze({
@@ -817,6 +817,18 @@ var BROWSER_TOOL_COPY = Object.freeze({
817
817
  required: Object.freeze(["journey"])
818
818
  })
819
819
  }),
820
+ capture: Object.freeze({
821
+ name: "capture",
822
+ description: "Saves the current view as a PNG in the runs directory and returns its path.",
823
+ parameters: Object.freeze({
824
+ type: "object",
825
+ properties: Object.freeze({ full: Object.freeze({
826
+ type: "boolean",
827
+ description: "True captures the full page; false captures the viewport."
828
+ }) }),
829
+ required: Object.freeze(["full"])
830
+ })
831
+ }),
820
832
  forget: Object.freeze({
821
833
  name: "forget",
822
834
  description: "Removes a saved journey and all its runs; the name is free to record again.",
@@ -885,7 +897,7 @@ var BROWSER_ACTION_STAGES = Object.freeze([
885
897
  var BROWSER_JOURNEY_EMPTY_LISTING = "No journeys are saved; call record to start one.";
886
898
  /**
887
899
  * Names the journey tools a toolset constructed with `journeys` registers and reserves: `record`,
888
- * `save`, `journeys`, `edit`, `replay`, and `forget`.
900
+ * `save`, `journeys`, `edit`, `replay`, `forget`, and `capture`.
889
901
  */
890
902
  var BROWSER_JOURNEY_TOOL_NAMES = Object.freeze([
891
903
  "record",
@@ -893,7 +905,8 @@ var BROWSER_JOURNEY_TOOL_NAMES = Object.freeze([
893
905
  "journeys",
894
906
  "edit",
895
907
  "replay",
896
- "forget"
908
+ "forget",
909
+ "capture"
897
910
  ]);
898
911
  /** Names observation and journey tools that cannot become journey steps. */
899
912
  var BROWSER_JOURNEY_NON_STEP_TOOLS = Object.freeze([...BROWSER_OBSERVATION_TOOL_NAMES, ...BROWSER_JOURNEY_TOOL_NAMES]);
@@ -6450,9 +6463,11 @@ var BrowserPageElement = class {
6450
6463
  object: result["object"]["objectId"],
6451
6464
  context
6452
6465
  };
6453
- } catch {
6466
+ } catch (error) {
6454
6467
  options?.signal?.throwIfAborted();
6455
- throw new BrowserElementError(this.reference, "GONE");
6468
+ if (isCDPTimeoutError(error) || isCDPConnectionError(error)) throw error;
6469
+ if (isCDPError(error) && /Could not find node|No node with given id|No node found for given backend id/i.test(error.message)) throw new BrowserElementError(this.reference, "GONE");
6470
+ throw error;
6456
6471
  }
6457
6472
  }
6458
6473
  async #call(declaration, options, target) {
@@ -6481,7 +6496,7 @@ var BrowserPageElement = class {
6481
6496
  }
6482
6497
  #failure(options, error) {
6483
6498
  options?.signal?.throwIfAborted();
6484
- if (isBrowserElementError(error)) throw error;
6499
+ if (isBrowserElementError(error) || isCDPTimeoutError(error) || isCDPConnectionError(error)) throw error;
6485
6500
  const message = (isError(error) ? error.message : String(error)).split("\n", 1)[0] ?? "";
6486
6501
  const known = BROWSER_ELEMENT_REFUSALS.get(message.replace(/^Error: /, ""));
6487
6502
  if (known !== void 0) throw new BrowserElementError(this.reference, known.reason, known.detail);
@@ -6513,11 +6528,20 @@ var BrowserPageElement = class {
6513
6528
  session: this.#input.node.session,
6514
6529
  ...options
6515
6530
  }).catch(this.#failure.bind(this, options));
6516
- await this.#call(compileActionabilityFunction({
6531
+ await this.#call(`async function() {
6532
+ await (${compileActionabilityFunction({
6517
6533
  visible: true,
6518
6534
  enabled: true,
6519
6535
  stable: true
6520
- }), options);
6536
+ })}).call(this)
6537
+ let previous
6538
+ for (;;) {
6539
+ await new Promise((resolve) => requestAnimationFrame(resolve))
6540
+ const current = [window.scrollX, window.scrollY]
6541
+ if (previous && current.every((value, index) => value === previous[index])) return true
6542
+ previous = current
6543
+ }
6544
+ }`, options);
6521
6545
  const geometry = await this.#geometry(options);
6522
6546
  const point = geometry.page.center;
6523
6547
  const local = geometry.local.center;
@@ -6528,6 +6552,10 @@ var BrowserPageElement = class {
6528
6552
  }, {
6529
6553
  session: this.#input.node.session,
6530
6554
  ...options
6555
+ }).catch((error) => {
6556
+ options?.signal?.throwIfAborted();
6557
+ if (isCDPError(error) && error.context?.["message"] === "No node found at given location") throw new BrowserElementError(this.reference, "OCCLUDED", "hit-test location held no node");
6558
+ throw error;
6531
6559
  });
6532
6560
  if (!isRecord(hit) || !isInteger(hit["backendNodeId"]) || hit["frameId"] !== void 0 && hit["frameId"] !== this.#input.frame) throw new BrowserElementError(this.reference, "OCCLUDED");
6533
6561
  if (hit["backendNodeId"] !== this.#input.backend && await this.#call(compileHitFunction(), options, hit["backendNodeId"]) !== true) {
@@ -11183,6 +11211,7 @@ var BrowserContext = class {
11183
11211
  #viewport;
11184
11212
  #writer;
11185
11213
  #downloads;
11214
+ #allocator;
11186
11215
  #emitter;
11187
11216
  #cookies;
11188
11217
  #permissions;
@@ -11202,6 +11231,7 @@ var BrowserContext = class {
11202
11231
  this.#viewport = viewport;
11203
11232
  this.#writer = writer;
11204
11233
  this.#downloads = downloads;
11234
+ this.#allocator = options?.reference;
11205
11235
  this.#emitter = new Emitter({
11206
11236
  ...options?.on !== void 0 ? { on: options.on } : {},
11207
11237
  ...options?.error !== void 0 ? { error: options.error } : {}
@@ -11338,7 +11368,7 @@ var BrowserContext = class {
11338
11368
  sessionId = await this.#openSession(targetId);
11339
11369
  await this.#enableSession(sessionId);
11340
11370
  const frameId = await this.#mainFrame(sessionId);
11341
- page = new BrowserPage(this.#client, targetId, sessionId, this.#writer, url, frameId, this.#id, void 0, options, this.#nextReference.bind(this), ready);
11371
+ page = new BrowserPage(this.#client, targetId, sessionId, this.#writer, url, frameId, this.#id, void 0, options, this.#allocator ?? this.#nextReference.bind(this), ready);
11342
11372
  this.#observe(page);
11343
11373
  await this.#configurePage(page);
11344
11374
  await this.#emulation.attach(page);
@@ -11357,7 +11387,7 @@ var BrowserContext = class {
11357
11387
  sessionId = await this.#openSession(targetId);
11358
11388
  await this.#enableSession(sessionId);
11359
11389
  const frameId = await this.#mainFrame(sessionId);
11360
- page = new BrowserPage(this.#client, targetId, sessionId, this.#writer, url, frameId, this.#id, void 0, void 0, this.#nextReference.bind(this), ready);
11390
+ page = new BrowserPage(this.#client, targetId, sessionId, this.#writer, url, frameId, this.#id, void 0, void 0, this.#allocator ?? this.#nextReference.bind(this), ready);
11361
11391
  this.#observe(page);
11362
11392
  await this.#configurePage(page);
11363
11393
  await this.#emulation.attach(page);
@@ -12275,13 +12305,13 @@ function createMemoryBrowserRunStore() {
12275
12305
  //#endregion
12276
12306
  //#region src/core/BrowserJourneyToolset.ts
12277
12307
  /**
12278
- * Registers the journey tools `record`, `save`, `journeys`, `edit`, `replay`, and `forget` over a toolset
12308
+ * Registers the journey tools `record`, `save`, `journeys`, `edit`, `replay`, `forget`, and `capture` over a toolset
12279
12309
  * and owns the recording and the active replay.
12280
12310
  *
12281
12311
  * @remarks
12282
12312
  * The journey toolset composes the toolset's public members: `perform` reads the view a receipt
12283
12313
  * carries through `look`, `hold` and `emitter` drive the recorder and the replay, `view` converts
12284
- * an edit's `ref` to a target, and `tools` receives the six tools at construction, which refuses
12314
+ * an edit's `ref` to a target, and `tools` receives the journey tools at construction, which refuses
12285
12315
  * with `BROWSER_TOOLSET_RESERVED` when the manager already holds one of the names. Every refusal
12286
12316
  * is a sentence that names the next call, and a reason inside it is a clause without a directive
12287
12317
  * or a final period.
@@ -12297,7 +12327,7 @@ function createMemoryBrowserRunStore() {
12297
12327
  * by the view after the run.
12298
12328
  *
12299
12329
  * `destroy()` aborts the active replay and waits for it to finish, stops a recording without
12300
- * saving it, and removes the six tools the manager still holds under the instances it added.
12330
+ * saving it, and removes the journey tools the manager still holds under the instances it added.
12301
12331
  *
12302
12332
  * @example
12303
12333
  * ```ts
@@ -12338,7 +12368,8 @@ var BrowserJourneyToolset = class {
12338
12368
  this.#create("journeys", this.#journeys.bind(this)),
12339
12369
  this.#create("edit", this.#edit.bind(this)),
12340
12370
  this.#create("replay", this.#replayJourney.bind(this)),
12341
- this.#create("forget", this.#forget.bind(this))
12371
+ this.#create("forget", this.#forget.bind(this)),
12372
+ this.#create("capture", this.#capture.bind(this))
12342
12373
  ]);
12343
12374
  toolset.tools.add(this.#tools);
12344
12375
  }
@@ -12365,6 +12396,22 @@ var BrowserJourneyToolset = class {
12365
12396
  signal.throwIfAborted();
12366
12397
  return handler(args, signal);
12367
12398
  }
12399
+ async #capture(args, signal) {
12400
+ const full = args["full"];
12401
+ if (!isBoolean(full)) throw new BrowserError("The full parameter must be true or false.", "BROWSER_TOOLSET_ARGUMENT");
12402
+ this.#idleReplay();
12403
+ const view = this.#toolset.view;
12404
+ if (!view.trusted) throw new BrowserError("This view is untrusted; capture requires a trusted browser view.", "BROWSER_CAPTURE_UNTRUSTED");
12405
+ if (view.screenshot === void 0) throw new BrowserError("This view cannot capture an image.", "BROWSER_CAPTURE_UNAVAILABLE");
12406
+ const runs = this.#runs;
12407
+ if (runs?.snapshot === void 0) throw new BrowserError("Capture requires a runs store with standalone file storage.", "BROWSER_CAPTURE_UNAVAILABLE");
12408
+ const screenshot = await view.screenshot({
12409
+ format: "png",
12410
+ full
12411
+ });
12412
+ signal.throwIfAborted();
12413
+ return runs.snapshot(screenshot.bytes, { signal });
12414
+ }
12368
12415
  async #record(args, signal) {
12369
12416
  if (this.#readonly) throw new BrowserError(BROWSER_JOURNEY_READONLY_REFUSAL, "BROWSER_JOURNEY_READONLY");
12370
12417
  this.#idleReplay();