@stablyai/playwright-base 0.1.0 → 0.1.1

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 (37) hide show
  1. package/dist/ai/extract.d.ts +2 -2
  2. package/dist/ai/extract.js +23 -56
  3. package/dist/ai/verify-prompt.js +15 -18
  4. package/dist/expect.d.ts +2 -2
  5. package/dist/expect.js +13 -58
  6. package/dist/image-compare.d.ts +5 -0
  7. package/dist/image-compare.js +41 -0
  8. package/dist/index.d.ts +53 -11
  9. package/dist/index.js +5 -15
  10. package/dist/playwright-augment/augment.d.ts +1 -1
  11. package/dist/playwright-augment/augment.js +22 -31
  12. package/dist/playwright-augment/methods/agent.d.ts +1 -1
  13. package/dist/playwright-augment/methods/agent.js +3 -6
  14. package/dist/playwright-augment/methods/auto-heal.d.ts +16 -0
  15. package/dist/playwright-augment/methods/auto-heal.js +7 -0
  16. package/dist/playwright-augment/methods/extract.d.ts +2 -2
  17. package/dist/playwright-augment/methods/extract.js +6 -11
  18. package/dist/playwright-augment/methods/test-info.d.ts +16 -0
  19. package/dist/playwright-augment/methods/test-info.js +96 -0
  20. package/dist/playwright-type-predicates.d.ts +1 -1
  21. package/dist/playwright-type-predicates.js +8 -12
  22. package/dist/runtime.js +4 -9
  23. package/dist/screenshot.d.ts +3 -0
  24. package/dist/screenshot.js +38 -0
  25. package/package.json +12 -6
  26. package/src/ai/extract.ts +19 -19
  27. package/src/ai/verify-prompt.ts +8 -8
  28. package/src/expect.ts +15 -72
  29. package/src/image-compare.ts +69 -0
  30. package/src/index.ts +53 -11
  31. package/src/playwright-augment/augment.ts +33 -33
  32. package/src/playwright-augment/methods/agent.ts +2 -2
  33. package/src/playwright-augment/methods/extract.ts +2 -2
  34. package/src/playwright-type-predicates.ts +7 -7
  35. package/src/runtime.ts +1 -1
  36. package/src/screenshot.ts +52 -0
  37. package/tsconfig.json +15 -5
@@ -1,5 +1,5 @@
1
- import type { Locator, Page } from 'playwright';
2
- import * as z4 from 'zod/v4/core';
1
+ import type { Locator, Page } from "@stablyai/internal-playwright-test";
2
+ import * as z4 from "zod/v4/core";
3
3
  export type ExtractSchema = z4.$ZodType;
4
4
  export type SchemaOutput<T extends ExtractSchema> = z4.output<T>;
5
5
  type ExtractSubject = Page | Locator;
@@ -1,73 +1,38 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.extract = extract;
37
- const z4 = __importStar(require("zod/v4/core"));
38
- const zod_1 = require("zod");
39
- const runtime_1 = require("../runtime");
40
- const EXTRACT_ENDPOINT = 'https://api.stably.ai/internal/v1/extract';
41
- const zSuccess = zod_1.z.object({ value: zod_1.z.unknown() });
42
- const zError = zod_1.z.object({ error: zod_1.z.string() });
1
+ import * as z4 from "zod/v4/core";
2
+ import { z } from "zod";
3
+ import { requireApiKey } from "../runtime";
4
+ const EXTRACT_ENDPOINT = "https://api.stably.ai/internal/v1/extract";
5
+ const zSuccess = z.object({ value: z.unknown() });
6
+ const zError = z.object({ error: z.string() });
43
7
  class ExtractValidationError extends Error {
8
+ issues;
44
9
  constructor(message, issues) {
45
10
  super(message);
46
11
  this.issues = issues;
47
- this.name = 'ExtractValidationError';
12
+ this.name = "ExtractValidationError";
48
13
  }
49
14
  }
50
15
  async function validateWithSchema(schema, value) {
51
16
  const result = await z4.safeParseAsync(schema, value);
52
17
  if (!result.success) {
53
- throw new ExtractValidationError('Validation failed', result.error.issues);
18
+ throw new ExtractValidationError("Validation failed", result.error.issues);
54
19
  }
55
20
  return result.data;
56
21
  }
57
- async function extract({ prompt, pageOrLocator, schema, }) {
22
+ export async function extract({ prompt, pageOrLocator, schema, }) {
58
23
  const jsonSchema = schema ? z4.toJSONSchema(schema) : undefined;
59
- const apiKey = (0, runtime_1.requireApiKey)();
24
+ const apiKey = requireApiKey();
60
25
  const form = new FormData();
61
- form.append('prompt', prompt);
26
+ form.append("prompt", prompt);
62
27
  if (jsonSchema) {
63
- form.append('jsonSchema', JSON.stringify(jsonSchema));
28
+ form.append("jsonSchema", JSON.stringify(jsonSchema));
64
29
  }
65
- const pngBuffer = await pageOrLocator.screenshot({ type: 'png' }); // Buffer
30
+ const pngBuffer = await pageOrLocator.screenshot({ type: "png" }); // Buffer
66
31
  const u8 = Uint8Array.from(pngBuffer); // strips Buffer type → plain Uint8Array
67
- const blob = new Blob([u8], { type: 'image/png' });
68
- form.append('image', blob, 'screenshot.png');
32
+ const blob = new Blob([u8], { type: "image/png" });
33
+ form.append("image", blob, "screenshot.png");
69
34
  const response = await fetch(EXTRACT_ENDPOINT, {
70
- method: 'POST',
35
+ method: "POST",
71
36
  headers: {
72
37
  Authorization: `Bearer ${apiKey}`,
73
38
  },
@@ -76,10 +41,12 @@ async function extract({ prompt, pageOrLocator, schema, }) {
76
41
  const parsed = await response.json().catch(() => undefined);
77
42
  if (response.ok) {
78
43
  const { value } = zSuccess.parse(parsed);
79
- return (schema ? await validateWithSchema(schema, value)
80
- : typeof value === 'string' ? value
81
- : JSON.stringify(value));
44
+ return schema
45
+ ? await validateWithSchema(schema, value)
46
+ : typeof value === "string"
47
+ ? value
48
+ : JSON.stringify(value);
82
49
  }
83
50
  const err = zError.safeParse(parsed);
84
- throw new Error(`Extract failed (${response.status})${err.success ? `: ${err.data.error}` : ''}`);
51
+ throw new Error(`Extract failed (${response.status})${err.success ? `: ${err.data.error}` : ""}`);
85
52
  }
@@ -1,25 +1,22 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.verifyPrompt = verifyPrompt;
4
- const PROMPT_ASSERTION_ENDPOINT = 'https://api.stably.ai/internal/v1/assert';
5
- const zod_1 = require("zod");
6
- const runtime_1 = require("../runtime");
7
- const zSuccess = zod_1.z.object({
8
- success: zod_1.z.boolean(),
9
- reason: zod_1.z.string().optional(),
1
+ const PROMPT_ASSERTION_ENDPOINT = "https://api.stably.ai/internal/v1/assert";
2
+ import { z } from "zod";
3
+ import { requireApiKey } from "../runtime";
4
+ const zSuccess = z.object({
5
+ success: z.boolean(),
6
+ reason: z.string().optional(),
10
7
  });
11
- const zError = zod_1.z.object({
12
- error: zod_1.z.string(),
8
+ const zError = z.object({
9
+ error: z.string(),
13
10
  });
14
- async function verifyPrompt({ prompt, screenshot, }) {
15
- const apiKey = (0, runtime_1.requireApiKey)();
11
+ export async function verifyPrompt({ prompt, screenshot, }) {
12
+ const apiKey = requireApiKey();
16
13
  const form = new FormData();
17
- form.append('prompt', prompt);
14
+ form.append("prompt", prompt);
18
15
  const u8 = Uint8Array.from(screenshot);
19
- const blob = new Blob([u8], { type: 'image/png' });
20
- form.append('image', blob, 'screenshot.png');
16
+ const blob = new Blob([u8], { type: "image/png" });
17
+ form.append("image", blob, "screenshot.png");
21
18
  const response = await fetch(PROMPT_ASSERTION_ENDPOINT, {
22
- method: 'POST',
19
+ method: "POST",
23
20
  headers: {
24
21
  Authorization: `Bearer ${apiKey}`,
25
22
  },
@@ -34,5 +31,5 @@ async function verifyPrompt({ prompt, screenshot, }) {
34
31
  };
35
32
  }
36
33
  const err = zError.safeParse(parsed);
37
- throw new Error(`Verify prompt failed (${response.status})${err.success ? `: ${err.data.error}` : ''}`);
34
+ throw new Error(`Verify prompt failed (${response.status})${err.success ? `: ${err.data.error}` : ""}`);
38
35
  }
package/dist/expect.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { Locator, Page } from 'playwright';
2
- import type { ScreenshotPromptOptions } from './index';
1
+ import type { Locator, Page } from "@stablyai/internal-playwright-test";
2
+ import type { ScreenshotPromptOptions } from "./index";
3
3
  type MatcherContext = {
4
4
  isNot: boolean;
5
5
  message?: () => string;
package/dist/expect.js CHANGED
@@ -1,75 +1,30 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.stablyPlaywrightMatchers = void 0;
4
- const playwright_type_predicates_1 = require("./playwright-type-predicates");
5
- const verify_prompt_1 = require("./ai/verify-prompt");
1
+ import { isLocator, isPage } from "./playwright-type-predicates";
2
+ import { verifyPrompt } from "./ai/verify-prompt";
3
+ import { takeStableScreenshot } from "./screenshot";
6
4
  function createFailureMessage({ targetType, condition, didPass, isNot, reason, }) {
7
- const expectation = isNot ? 'not to satisfy' : 'to satisfy';
8
- const result = didPass ? 'it did' : 'it did not';
5
+ const expectation = isNot ? "not to satisfy" : "to satisfy";
6
+ const result = didPass ? "it did" : "it did not";
9
7
  let message = `Expected ${targetType} ${expectation} ${JSON.stringify(condition)}, but ${result}.`;
10
8
  if (reason) {
11
9
  message += `\n\nReason: ${reason}`;
12
10
  }
13
11
  return message;
14
12
  }
15
- function areScreenshotsEqual(a, b) {
16
- if (a.byteLength !== b.byteLength) {
17
- return false;
18
- }
19
- for (let index = 0; index < a.byteLength; index += 1) {
20
- if (a[index] !== b[index]) {
21
- return false;
22
- }
23
- }
24
- return true;
25
- }
26
- async function takeStableScreenshot(target, options) {
27
- var _a;
28
- const page = (0, playwright_type_predicates_1.isPage)(target) ? target : target.page();
29
- // Use a small budget for stabilization within the overall assertion timeout.
30
- // We allocate up to 25% of the total timeout (bounded between 300ms and 2000ms).
31
- const totalTimeout = (_a = options === null || options === void 0 ? void 0 : options.timeout) !== null && _a !== void 0 ? _a : 5000;
32
- // Budget is 25% of the total timeout
33
- const stabilizationBudgetMs = Math.floor(totalTimeout * 0.25);
34
- const stabilityBudgetMs = Math.min(2000, Math.max(300, stabilizationBudgetMs));
35
- const deadline = Date.now() + stabilityBudgetMs;
36
- let actual;
37
- let previous;
38
- const pollIntervals = [0, 100, 250, 500];
39
- let isFirstIteration = true;
40
- while (true) {
41
- if (Date.now() >= deadline)
42
- break;
43
- const delay = pollIntervals.length ? pollIntervals.shift() : 1000;
44
- if (delay) {
45
- await page.waitForTimeout(delay);
46
- }
47
- previous = actual;
48
- const rawScreenshot = await target.screenshot(options);
49
- actual = Uint8Array.from(rawScreenshot);
50
- if (!isFirstIteration &&
51
- actual &&
52
- previous &&
53
- areScreenshotsEqual(actual, previous)) {
54
- return actual;
55
- }
56
- isFirstIteration = false;
57
- }
58
- return actual !== null && actual !== void 0 ? actual : Uint8Array.from(await target.screenshot(options));
59
- }
60
- exports.stablyPlaywrightMatchers = {
13
+ export const stablyPlaywrightMatchers = {
61
14
  async toMatchScreenshotPrompt(received, condition, options) {
62
- const target = (0, playwright_type_predicates_1.isPage)(received) ? received
63
- : (0, playwright_type_predicates_1.isLocator)(received) ? received
15
+ const target = isPage(received)
16
+ ? received
17
+ : isLocator(received)
18
+ ? received
64
19
  : undefined;
65
20
  if (!target) {
66
21
  // Should never happen
67
- throw new Error('toMatchScreenshotPrompt only supports Playwright Page and Locator instances.');
22
+ throw new Error("toMatchScreenshotPrompt only supports Playwright Page and Locator instances.");
68
23
  }
69
- const targetType = (0, playwright_type_predicates_1.isPage)(target) ? 'page' : 'locator';
24
+ const targetType = isPage(target) ? "page" : "locator";
70
25
  // Wait for two consecutive identical screenshots before sending to AI
71
26
  const screenshot = await takeStableScreenshot(target, options);
72
- const verifyResult = await (0, verify_prompt_1.verifyPrompt)({ prompt: condition, screenshot });
27
+ const verifyResult = await verifyPrompt({ prompt: condition, screenshot });
73
28
  return {
74
29
  pass: verifyResult.pass,
75
30
  message: () => createFailureMessage({
@@ -0,0 +1,5 @@
1
+ export declare const imagesAreSimilar: ({ image1, image2, threshold, }: {
2
+ image1: Buffer;
3
+ image2: Buffer;
4
+ threshold: number;
5
+ }) => boolean;
@@ -0,0 +1,41 @@
1
+ import pixelmatch from "pixelmatch";
2
+ import { PNG } from "pngjs";
3
+ import * as jpeg from "jpeg-js";
4
+ const isPng = (buffer) => {
5
+ return (buffer.length >= 8 &&
6
+ buffer[0] === 0x89 &&
7
+ buffer[1] === 0x50 &&
8
+ buffer[2] === 0x4e &&
9
+ buffer[3] === 0x47 &&
10
+ buffer[4] === 0x0d &&
11
+ buffer[5] === 0x0a &&
12
+ buffer[6] === 0x1a &&
13
+ buffer[7] === 0x0a);
14
+ };
15
+ const isJpeg = (buffer) => {
16
+ return buffer.length >= 2 && buffer[0] === 0xff && buffer[1] === 0xd8;
17
+ };
18
+ const decodeImage = (buffer) => {
19
+ if (isPng(buffer)) {
20
+ const png = PNG.sync.read(buffer);
21
+ return { data: png.data, width: png.width, height: png.height };
22
+ }
23
+ if (isJpeg(buffer)) {
24
+ const img = jpeg.decode(buffer, { maxMemoryUsageInMB: 1024 });
25
+ return { data: img.data, width: img.width, height: img.height };
26
+ }
27
+ // Default to PNG decode; if it fails upstream, treat as different sizes
28
+ const png = PNG.sync.read(buffer);
29
+ return { data: png.data, width: png.width, height: png.height };
30
+ };
31
+ export const imagesAreSimilar = ({ image1, image2, threshold, }) => {
32
+ const decodedImage1 = decodeImage(image1);
33
+ const decodedImage2 = decodeImage(image2);
34
+ if (decodedImage1.width !== decodedImage2.width ||
35
+ decodedImage1.height !== decodedImage2.height) {
36
+ return false;
37
+ }
38
+ const diffRgbaData = new Uint8Array(decodedImage1.width * decodedImage1.height * 4);
39
+ const numDiffPixels = pixelmatch(decodedImage1.data, decodedImage2.data, diffRgbaData, decodedImage1.width, decodedImage1.height, { threshold });
40
+ return numDiffPixels === 0;
41
+ };
package/dist/index.d.ts CHANGED
@@ -1,27 +1,69 @@
1
- import type { Page } from 'playwright';
2
- import type { LocatorDescribeOptions } from './playwright-augment/augment';
3
- import type { ExtractSchema, SchemaOutput } from './ai/extract';
4
- import { augmentBrowser, augmentBrowserContext, augmentBrowserType, augmentLocator, augmentPage } from './playwright-augment/augment';
5
- import { stablyPlaywrightMatchers } from './expect';
6
- import { requireApiKey } from './runtime';
7
- export { setApiKey } from './runtime';
8
- export type { LocatorDescribeOptions } from './playwright-augment/augment';
9
- export type { ExtractSchema, SchemaOutput } from './ai/extract';
10
- export type ScreenshotPromptOptions = import('@playwright/test').PageAssertionsToHaveScreenshotOptions;
1
+ import type { Page } from "@stablyai/internal-playwright-test";
2
+ import type { LocatorDescribeOptions } from "./playwright-augment/augment";
3
+ import type { ExtractSchema, SchemaOutput } from "./ai/extract";
4
+ import { augmentBrowser, augmentBrowserContext, augmentBrowserType, augmentLocator, augmentPage } from "./playwright-augment/augment";
5
+ import { stablyPlaywrightMatchers } from "./expect";
6
+ import { requireApiKey } from "./runtime";
7
+ export { setApiKey } from "./runtime";
8
+ export type { LocatorDescribeOptions } from "./playwright-augment/augment";
9
+ export type { ExtractSchema, SchemaOutput } from "./ai/extract";
10
+ export type ScreenshotPromptOptions = import("@stablyai/internal-playwright-test").PageAssertionsToHaveScreenshotOptions;
11
11
  export { augmentBrowser, augmentBrowserContext, augmentBrowserType, augmentLocator, augmentPage, stablyPlaywrightMatchers, requireApiKey, };
12
12
  export interface Expect<T = Page> {
13
13
  toMatchScreenshotPrompt(condition: string, options?: ScreenshotPromptOptions): Promise<void>;
14
14
  }
15
- declare module 'playwright' {
15
+ declare module "@stablyai/internal-playwright-test" {
16
16
  interface Locator {
17
+ /**
18
+ * Extracts information from this locator using Stably AI.
19
+ *
20
+ * Takes a screenshot of the locator and uses AI to extract information based on the
21
+ * provided prompt. When a schema is provided, the extracted data is validated and
22
+ * typed according to the schema.
23
+ *
24
+ * @param prompt - A natural language description of what information to extract
25
+ * @returns A string containing the extracted information
26
+ */
17
27
  extract(prompt: string): Promise<string>;
28
+ /**
29
+ * Extracts information from this locator using Stably AI.
30
+ *
31
+ * Takes a screenshot of the locator and uses AI to extract information based on the
32
+ * provided prompt. The extracted data is validated and typed according to the schema.
33
+ *
34
+ * @param prompt - A natural language description of what information to extract
35
+ * @param options - Configuration object containing the Zod schema for validation
36
+ * @param options.schema - Zod schema to validate and type the extracted data
37
+ * @returns Typed data matching the provided schema
38
+ */
18
39
  extract<T extends ExtractSchema>(prompt: string, options: {
19
40
  schema: T;
20
41
  }): Promise<SchemaOutput<T>>;
21
42
  describe(description: string, options?: LocatorDescribeOptions): Locator;
22
43
  }
23
44
  interface Page {
45
+ /**
46
+ * Extracts information from this page using Stably AI.
47
+ *
48
+ * Takes a screenshot of the page and uses AI to extract information based on the
49
+ * provided prompt. When a schema is provided, the extracted data is validated and
50
+ * typed according to the schema.
51
+ *
52
+ * @param prompt - A natural language description of what information to extract
53
+ * @returns A string containing the extracted information
54
+ */
24
55
  extract(prompt: string): Promise<string>;
56
+ /**
57
+ * Extracts information from this page using Stably AI.
58
+ *
59
+ * Takes a screenshot of the page and uses AI to extract information based on the
60
+ * provided prompt. The extracted data is validated and typed according to the schema.
61
+ *
62
+ * @param prompt - A natural language description of what information to extract
63
+ * @param options - Configuration object containing the Zod schema for validation
64
+ * @param options.schema - Zod schema to validate and type the extracted data
65
+ * @returns Typed data matching the provided schema
66
+ */
25
67
  extract<T extends ExtractSchema>(prompt: string, options: {
26
68
  schema: T;
27
69
  }): Promise<SchemaOutput<T>>;
package/dist/index.js CHANGED
@@ -1,15 +1,5 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.requireApiKey = exports.stablyPlaywrightMatchers = exports.augmentPage = exports.augmentLocator = exports.augmentBrowserType = exports.augmentBrowserContext = exports.augmentBrowser = exports.setApiKey = void 0;
4
- const augment_1 = require("./playwright-augment/augment");
5
- Object.defineProperty(exports, "augmentBrowser", { enumerable: true, get: function () { return augment_1.augmentBrowser; } });
6
- Object.defineProperty(exports, "augmentBrowserContext", { enumerable: true, get: function () { return augment_1.augmentBrowserContext; } });
7
- Object.defineProperty(exports, "augmentBrowserType", { enumerable: true, get: function () { return augment_1.augmentBrowserType; } });
8
- Object.defineProperty(exports, "augmentLocator", { enumerable: true, get: function () { return augment_1.augmentLocator; } });
9
- Object.defineProperty(exports, "augmentPage", { enumerable: true, get: function () { return augment_1.augmentPage; } });
10
- const expect_1 = require("./expect");
11
- Object.defineProperty(exports, "stablyPlaywrightMatchers", { enumerable: true, get: function () { return expect_1.stablyPlaywrightMatchers; } });
12
- const runtime_1 = require("./runtime");
13
- Object.defineProperty(exports, "requireApiKey", { enumerable: true, get: function () { return runtime_1.requireApiKey; } });
14
- var runtime_2 = require("./runtime");
15
- Object.defineProperty(exports, "setApiKey", { enumerable: true, get: function () { return runtime_2.setApiKey; } });
1
+ import { augmentBrowser, augmentBrowserContext, augmentBrowserType, augmentLocator, augmentPage, } from "./playwright-augment/augment";
2
+ import { stablyPlaywrightMatchers } from "./expect";
3
+ import { requireApiKey } from "./runtime";
4
+ export { setApiKey } from "./runtime";
5
+ export { augmentBrowser, augmentBrowserContext, augmentBrowserType, augmentLocator, augmentPage, stablyPlaywrightMatchers, requireApiKey, };
@@ -1,4 +1,4 @@
1
- import type { Browser, BrowserContext, BrowserType, Locator, Page } from 'playwright';
1
+ import type { Browser, BrowserContext, BrowserType, Locator, Page } from "@stablyai/internal-playwright-test";
2
2
  export interface LocatorDescribeOptions {
3
3
  autoHeal?: boolean;
4
4
  }
@@ -1,18 +1,11 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.augmentLocator = augmentLocator;
4
- exports.augmentPage = augmentPage;
5
- exports.augmentBrowserContext = augmentBrowserContext;
6
- exports.augmentBrowser = augmentBrowser;
7
- exports.augmentBrowserType = augmentBrowserType;
8
- const extract_1 = require("./methods/extract");
9
- const agent_1 = require("./methods/agent");
10
- const LOCATOR_PATCHED = Symbol.for('stably.playwright.locatorPatched');
11
- const LOCATOR_DESCRIBE_WRAPPED = Symbol.for('stably.playwright.locatorDescribeWrapped');
12
- const PAGE_PATCHED = Symbol.for('stably.playwright.pagePatched');
13
- const CONTEXT_PATCHED = Symbol.for('stably.playwright.contextPatched');
14
- const BROWSER_PATCHED = Symbol.for('stably.playwright.browserPatched');
15
- const BROWSER_TYPE_PATCHED = Symbol.for('stably.playwright.browserTypePatched');
1
+ import { createLocatorExtract, createPageExtract } from "./methods/extract";
2
+ import { createAgentStub } from "./methods/agent";
3
+ const LOCATOR_PATCHED = Symbol.for("stably.playwright.locatorPatched");
4
+ const LOCATOR_DESCRIBE_WRAPPED = Symbol.for("stably.playwright.locatorDescribeWrapped");
5
+ const PAGE_PATCHED = Symbol.for("stably.playwright.pagePatched");
6
+ const CONTEXT_PATCHED = Symbol.for("stably.playwright.contextPatched");
7
+ const BROWSER_PATCHED = Symbol.for("stably.playwright.browserPatched");
8
+ const BROWSER_TYPE_PATCHED = Symbol.for("stably.playwright.browserTypePatched");
16
9
  function defineHiddenProperty(target, key, value) {
17
10
  Object.defineProperty(target, key, {
18
11
  value,
@@ -21,13 +14,13 @@ function defineHiddenProperty(target, key, value) {
21
14
  writable: true,
22
15
  });
23
16
  }
24
- function augmentLocator(locator) {
17
+ export function augmentLocator(locator) {
25
18
  if (locator[LOCATOR_PATCHED]) {
26
19
  return locator;
27
20
  }
28
- defineHiddenProperty(locator, 'extract', (0, extract_1.createLocatorExtract)(locator));
21
+ defineHiddenProperty(locator, "extract", createLocatorExtract(locator));
29
22
  const markerTarget = locator;
30
- if (typeof locator.describe === 'function' &&
23
+ if (typeof locator.describe === "function" &&
31
24
  !markerTarget[LOCATOR_DESCRIBE_WRAPPED]) {
32
25
  const originalDescribe = locator.describe.bind(locator);
33
26
  locator.describe = ((description, options) => {
@@ -40,7 +33,7 @@ function augmentLocator(locator) {
40
33
  defineHiddenProperty(locator, LOCATOR_PATCHED, true);
41
34
  return locator;
42
35
  }
43
- function augmentPage(page) {
36
+ export function augmentPage(page) {
44
37
  if (page[PAGE_PATCHED]) {
45
38
  return page;
46
39
  }
@@ -49,12 +42,11 @@ function augmentPage(page) {
49
42
  const locator = originalLocator(...args);
50
43
  return augmentLocator(locator);
51
44
  });
52
- defineHiddenProperty(page, 'extract', (0, extract_1.createPageExtract)(page));
45
+ defineHiddenProperty(page, "extract", createPageExtract(page));
53
46
  defineHiddenProperty(page, PAGE_PATCHED, true);
54
47
  return page;
55
48
  }
56
- function augmentBrowserContext(context) {
57
- var _a;
49
+ export function augmentBrowserContext(context) {
58
50
  if (context[CONTEXT_PATCHED]) {
59
51
  return context;
60
52
  }
@@ -63,17 +55,17 @@ function augmentBrowserContext(context) {
63
55
  const page = await originalNewPage(...args);
64
56
  return augmentPage(page);
65
57
  });
66
- const originalPages = (_a = context.pages) === null || _a === void 0 ? void 0 : _a.bind(context);
58
+ const originalPages = context.pages?.bind(context);
67
59
  if (originalPages) {
68
60
  context.pages = (() => originalPages().map((page) => augmentPage(page)));
69
61
  }
70
62
  if (!context.agent) {
71
- defineHiddenProperty(context, 'agent', (0, agent_1.createAgentStub)());
63
+ defineHiddenProperty(context, "agent", createAgentStub());
72
64
  }
73
65
  defineHiddenProperty(context, CONTEXT_PATCHED, true);
74
66
  return context;
75
67
  }
76
- function augmentBrowser(browser) {
68
+ export function augmentBrowser(browser) {
77
69
  if (browser[BROWSER_PATCHED]) {
78
70
  return browser;
79
71
  }
@@ -90,13 +82,12 @@ function augmentBrowser(browser) {
90
82
  const originalContexts = browser.contexts.bind(browser);
91
83
  browser.contexts = (() => originalContexts().map((context) => augmentBrowserContext(context)));
92
84
  if (!browser.agent) {
93
- defineHiddenProperty(browser, 'agent', (0, agent_1.createAgentStub)());
85
+ defineHiddenProperty(browser, "agent", createAgentStub());
94
86
  }
95
87
  defineHiddenProperty(browser, BROWSER_PATCHED, true);
96
88
  return browser;
97
89
  }
98
- function augmentBrowserType(browserType) {
99
- var _a, _b, _c;
90
+ export function augmentBrowserType(browserType) {
100
91
  if (browserType[BROWSER_TYPE_PATCHED]) {
101
92
  return browserType;
102
93
  }
@@ -105,21 +96,21 @@ function augmentBrowserType(browserType) {
105
96
  const browser = await originalLaunch(...args);
106
97
  return augmentBrowser(browser);
107
98
  });
108
- const originalConnect = (_a = browserType.connect) === null || _a === void 0 ? void 0 : _a.bind(browserType);
99
+ const originalConnect = browserType.connect?.bind(browserType);
109
100
  if (originalConnect) {
110
101
  browserType.connect = (async (...args) => {
111
102
  const browser = await originalConnect(...args);
112
103
  return augmentBrowser(browser);
113
104
  });
114
105
  }
115
- const originalConnectOverCDP = (_b = browserType.connectOverCDP) === null || _b === void 0 ? void 0 : _b.bind(browserType);
106
+ const originalConnectOverCDP = browserType.connectOverCDP?.bind(browserType);
116
107
  if (originalConnectOverCDP) {
117
108
  browserType.connectOverCDP = (async (...args) => {
118
109
  const browser = await originalConnectOverCDP(...args);
119
110
  return augmentBrowser(browser);
120
111
  });
121
112
  }
122
- const originalLaunchPersistentContext = (_c = browserType.launchPersistentContext) === null || _c === void 0 ? void 0 : _c.bind(browserType);
113
+ const originalLaunchPersistentContext = browserType.launchPersistentContext?.bind(browserType);
123
114
  if (originalLaunchPersistentContext) {
124
115
  browserType.launchPersistentContext = (async (...args) => {
125
116
  const context = await originalLaunchPersistentContext(...args);
@@ -1,4 +1,4 @@
1
- import type { Page } from 'playwright';
1
+ import type { Page } from "@stablyai/internal-playwright-test";
2
2
  type AgentOptions = {
3
3
  page: Page;
4
4
  maxCycles?: number;
@@ -1,10 +1,7 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createAgentStub = createAgentStub;
4
- const runtime_1 = require("../../runtime");
5
- function createAgentStub() {
1
+ import { requireApiKey } from "../../runtime";
2
+ export function createAgentStub() {
6
3
  return async (prompt, options) => {
7
- (0, runtime_1.requireApiKey)();
4
+ requireApiKey();
8
5
  void prompt;
9
6
  void options;
10
7
  return { success: true };
@@ -0,0 +1,16 @@
1
+ import type { Locator, Page } from "playwright";
2
+ export type LocatorAutoHealContext = {
3
+ description: string;
4
+ error: unknown;
5
+ locator: Locator;
6
+ method: string;
7
+ args: unknown[];
8
+ page: Page;
9
+ };
10
+ export type LocatorAutoHealResult = {
11
+ locator?: Locator;
12
+ retry?: boolean;
13
+ } | void;
14
+ export type LocatorAutoHealHandler = (context: LocatorAutoHealContext) => LocatorAutoHealResult | Promise<LocatorAutoHealResult>;
15
+ export declare function setLocatorAutoHealHandler(handler: LocatorAutoHealHandler | undefined): void;
16
+ export declare function getLocatorAutoHealHandler(): LocatorAutoHealHandler | undefined;
@@ -0,0 +1,7 @@
1
+ let locatorAutoHealHandler;
2
+ export function setLocatorAutoHealHandler(handler) {
3
+ locatorAutoHealHandler = handler;
4
+ }
5
+ export function getLocatorAutoHealHandler() {
6
+ return locatorAutoHealHandler;
7
+ }
@@ -1,5 +1,5 @@
1
- import type { Locator, Page } from 'playwright';
2
- import { type ExtractSchema, type SchemaOutput } from '../../ai/extract';
1
+ import type { Locator, Page } from "@stablyai/internal-playwright-test";
2
+ import { type ExtractSchema, type SchemaOutput } from "../../ai/extract";
3
3
  type ExtractOptions<T extends ExtractSchema> = {
4
4
  schema: T;
5
5
  };
@@ -1,21 +1,16 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createPageExtract = exports.createLocatorExtract = void 0;
4
- const extract_1 = require("../../ai/extract");
1
+ import { extract, } from "../../ai/extract";
5
2
  function createExtract(pageOrLocator) {
6
3
  const impl = (async (prompt, options) => {
7
- if (options === null || options === void 0 ? void 0 : options.schema) {
8
- return (0, extract_1.extract)({
4
+ if (options?.schema) {
5
+ return extract({
9
6
  prompt,
10
7
  schema: options.schema,
11
8
  pageOrLocator,
12
9
  });
13
10
  }
14
- return (0, extract_1.extract)({ prompt, pageOrLocator });
11
+ return extract({ prompt, pageOrLocator });
15
12
  });
16
13
  return impl;
17
14
  }
18
- const createLocatorExtract = (locator) => createExtract(locator);
19
- exports.createLocatorExtract = createLocatorExtract;
20
- const createPageExtract = (page) => createExtract(page);
21
- exports.createPageExtract = createPageExtract;
15
+ export const createLocatorExtract = (locator) => createExtract(locator);
16
+ export const createPageExtract = (page) => createExtract(page);