/** * TestDriver SDK - TypeScript Definitions */ // Type Definitions export type ClickAction = | "click" | "right-click" | "double-click" | "hover" | "mouseDown" | "mouseUp"; export type ScrollDirection = "up" | "down" | "left" | "right"; export type ScrollMethod = "keyboard" | "mouse"; export type TextMatchMethod = "ai" | "turbo"; export type ExecLanguage = "sh" | "pwsh"; /** * Preview mode for live test visualization * - "browser": Opens debugger in default browser (default) * - "ide": Opens preview in IDE panel (VSCode, Cursor, etc.) * - "none": Headless mode, no visual preview */ export type PreviewMode = "browser" | "ide" | "none"; export type KeyboardKey = | "\t" | "\n" | "\r" | " " | "!" | '"' | "#" | "$" | "%" | "&" | "'" | "(" | ")" | "*" | "+" | "," | "-" | "." | "/" | "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | ":" | ";" | "<" | "=" | ">" | "?" | "@" | "[" | "\\" | "]" | "^" | "_" | "`" | "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" | "{" | "|" | "}" | "~" | "accept" | "add" | "alt" | "altleft" | "altright" | "apps" | "backspace" | "browserback" | "browserfavorites" | "browserforward" | "browserhome" | "browserrefresh" | "browsersearch" | "browserstop" | "capslock" | "clear" | "convert" | "ctrl" | "ctrlleft" | "ctrlright" | "decimal" | "del" | "delete" | "divide" | "down" | "end" | "enter" | "esc" | "escape" | "execute" | "f1" | "f2" | "f3" | "f4" | "f5" | "f6" | "f7" | "f8" | "f9" | "f10" | "f11" | "f12" | "f13" | "f14" | "f15" | "f16" | "f17" | "f18" | "f19" | "f20" | "f21" | "f22" | "f23" | "f24" | "final" | "fn" | "hanguel" | "hangul" | "hanja" | "help" | "home" | "insert" | "junja" | "kana" | "kanji" | "launchapp1" | "launchapp2" | "launchmail" | "launchmediaselect" | "left" | "modechange" | "multiply" | "nexttrack" | "nonconvert" | "num0" | "num1" | "num2" | "num3" | "num4" | "num5" | "num6" | "num7" | "num8" | "num9" | "numlock" | "pagedown" | "pageup" | "pause" | "pgdn" | "pgup" | "playpause" | "prevtrack" | "print" | "printscreen" | "prntscrn" | "prtsc" | "prtscr" | "return" | "right" | "scrolllock" | "select" | "separator" | "shift" | "shiftleft" | "shiftright" | "sleep" | "space" | "stop" | "subtract" | "tab" | "up" | "volumedown" | "volumemute" | "volumeup" | "win" | "winleft" | "winright" | "yen" | "command" | "option" | "optionleft" | "optionright"; export interface TestDriverOptions { /** API endpoint URL (default depends on release channel: latest → 'https://api.testdriver.ai') */ apiRoot?: string; /** Sandbox resolution (default: '1366x768') */ resolution?: string; /** Operating system for the sandbox (default: 'linux') */ os?: "windows" | "linux"; /** Enable analytics tracking (default: true) */ analytics?: boolean; /** Enable console logging output (default: true) */ logging?: boolean; /** Enable/disable cache, or configure with thresholds * @example { cache: { enabled: true, thresholds: { find: { screen: 0.05, element: 0.8 }, assert: 0.05 } } } */ cache?: boolean | { enabled?: boolean; thresholds?: { /** Thresholds for find operations */ find?: { /** Pixel diff threshold for screen comparison (0-1, default 0.05 = 5% diff allowed) */ screen?: number; /** OpenCV template match threshold for element matching (0-1, default 0.8 = 80% correlation) */ element?: number; }; /** Pixel diff threshold for assert operations (0-1, default 0.05 = 5% diff allowed) */ assert?: number; }; }; ai?: AIConfig; /** @deprecated Use cache.thresholds instead */ cacheThreshold?: { /** Threshold for find operations (default: 0.05 = 5% difference, 95% similarity) */ find?: number; /** Threshold for findAll operations (default: 0.05 = 5% difference, 95% similarity) */ findAll?: number; }; /** Force creation of a new sandbox (default: true) */ newSandbox?: boolean; /** * Preview mode for live test visualization (default: "browser") * - "browser": Opens debugger in default browser * - "ide": Opens preview in IDE panel (VSCode, Cursor, etc.) * - "none": Headless mode, no visual preview */ preview?: PreviewMode; /** * @deprecated Use `preview: "none"` instead. Run in headless mode (default: false) * For backward compatibility: headless: true maps to preview: "none" */ headless?: boolean; /** Direct IP address to connect to a running sandbox instance */ ip?: string; /** Custom AMI ID for sandbox instance (e.g., 'ami-1234') */ sandboxAmi?: string; /** EC2 instance type for sandbox (e.g., 'i3.metal') */ sandboxInstance?: string; /** E2B template ID to use when creating the sandbox (e.g., 'my-template-id') */ e2bTemplateId?: string; /** Cache key for element finding operations. If provided, enables caching tied to this key */ cacheKey?: string; /** Reconnect to the last used sandbox instead of creating a new one. When true, provision methods (chrome, vscode, installer, etc.) will be skipped since the application is already running. Throws error if no previous sandbox exists. */ reconnect?: boolean; /** Enable/disable Dashcam video recording (default: true) */ dashcam?: boolean; /** * Enable automatic screenshots before and after each command (default: true) * Screenshots are saved to .testdriver/screenshots// with descriptive filenames * Format: ---L-.png * Example: 001-click-before-L42-submit-button.png */ autoScreenshots?: boolean; /** Redraw configuration for screen change detection * @example { redraw: { enabled: true, thresholds: { screen: 0.05, network: true } } } */ redraw?: | boolean | { /** Enable redraw detection (default: true) */ enabled?: boolean; /** Threshold configuration */ thresholds?: { /** Screen diff threshold (0-1). Set to false to disable screen redraw detection. Default: 0.05 */ screen?: number | false; /** Enable/disable network activity monitoring (default: false) */ network?: boolean; }; /** @deprecated Use thresholds.screen instead */ diffThreshold?: number; /** @deprecated Use thresholds.screen !== false instead */ screenRedraw?: boolean; /** @deprecated Use thresholds.network instead */ networkMonitor?: boolean; }; /** @deprecated Use redraw option instead */ redrawThreshold?: number | object; /** Additional environment variables */ environment?: Record; } export interface ConnectOptions { /** Existing sandbox ID to reconnect to */ sandboxId?: string; /** Force creation of a new sandbox */ newSandbox?: boolean; /** Reconnect to the last used sandbox instead of creating a new one. When true, provision methods (chrome, vscode, installer, etc.) will be skipped since the application is already running. Throws error if no previous sandbox exists. */ reconnect?: boolean; /** Direct IP address to connect to a running sandbox instance */ ip?: string; /** Custom AMI ID for sandbox instance (e.g., 'ami-1234') */ sandboxAmi?: string; /** EC2 instance type for sandbox (e.g., 'i3.metal') */ sandboxInstance?: string; /** E2B template ID to use when creating the sandbox (e.g., 'my-template-id') */ e2bTemplateId?: string; /** Operating system for the sandbox (default: 'linux') */ os?: "windows" | "linux"; /** * Preview mode for live test visualization (default: "browser") * - "browser": Opens debugger in default browser * - "ide": Opens preview in IDE panel (VSCode, Cursor, etc.) * - "none": Headless mode, no visual preview */ preview?: PreviewMode; /** * @deprecated Use `preview: "none"` instead. Run in headless mode (default: false) * For backward compatibility: headless: true maps to preview: "none" */ headless?: boolean; /** Reuse recent connection if available (default: true) */ reuseConnection?: boolean; /** Keep sandbox alive for specified milliseconds after disconnect (default: 60000). Set to 0 to terminate immediately on disconnect. */ keepAlive?: number; } export interface SandboxInstance { instanceId: string; ip: string; vncPort: number; [key: string]: any; } export interface ElementCoordinates { x: number; y: number; centerX: number; centerY: number; } export interface ElementBoundingBox { top: number; left: number; bottom: number; right: number; [key: string]: any; } export interface ElementResponse { coordinates: ElementCoordinates; confidence?: number; screenshot?: string; width?: number; height?: number; boundingBox?: ElementBoundingBox; text?: string; label?: string; [key: string]: any; } export interface HoverResult { x: number; y: number; centerX: number; centerY: number; [key: string]: any; } /** Bounding box for a parsed element (pixel coordinates) */ export interface ParsedElementBBox { /** Left edge X coordinate */ x0: number; /** Top edge Y coordinate */ y0: number; /** Right edge X coordinate */ x1: number; /** Bottom edge Y coordinate */ y1: number; } /** Bounding box as {left, top, width, height} */ export interface ParsedElementBoundingBox { left: number; top: number; width: number; height: number; } /** Individual element detected by OmniParser */ export interface ParsedElement { /** Element index */ index: number; /** Element type (e.g. "text", "icon", "button") */ type: string; /** Text content or description */ content: string; /** Interactivity level (e.g. "clickable", "non-interactive") */ interactivity: string; /** Bounding box in pixel coordinates */ bbox: ParsedElementBBox; /** Bounding box as {left, top, width, height} */ boundingBox: ParsedElementBoundingBox; } /** Result from OmniParser screen analysis */ export interface ParseResult { /** Array of detected UI elements */ elements: ParsedElement[]; /** URL of the annotated screenshot */ annotatedImageUrl: string; /** Width of the analyzed screenshot */ imageWidth: number; /** Height of the analyzed screenshot */ imageHeight: number; } // ==================================== // Command Options Interfaces // ==================================== /** Options for scroll command */ export interface ScrollOptions { /** Direction to scroll */ direction?: ScrollDirection; /** Amount to scroll in pixels */ amount?: number; } /** Options for click command */ export interface ClickOptions { /** X coordinate */ x: number; /** Y coordinate */ y: number; /** Type of click action */ action?: ClickAction; /** Prompt for tracking */ prompt?: string; /** Whether cache was hit */ cacheHit?: boolean; /** Selector used */ selector?: string; /** Whether selector was used */ selectorUsed?: boolean; } /** Options for hover command */ export interface HoverOptions { /** X coordinate */ x: number; /** Y coordinate */ y: number; /** Prompt for tracking */ prompt?: string; /** Whether cache was hit */ cacheHit?: boolean; /** Selector used */ selector?: string; /** Whether selector was used */ selectorUsed?: boolean; } /** Options for hoverText command */ export interface HoverTextOptions { /** Text to find and hover over */ text: string; /** Optional description of the element */ description?: string | null; /** Action to perform */ action?: ClickAction; /** Timeout in milliseconds */ timeout?: number; } /** Options for hoverImage command */ export interface HoverImageOptions { /** Description of the image to find */ description: string; /** Action to perform */ action?: ClickAction; } /** Options for matchImage command */ export interface MatchImageOptions { /** Path to the image template */ path: string; /** Action to perform */ action?: ClickAction; /** Invert the match */ invert?: boolean; } /** Options for type command */ export interface TypeOptions { /** Text to type */ text: string | number; /** Delay between keystrokes in milliseconds */ delay?: number; } /** Options for pressKeys command */ export interface PressKeysOptions { /** Array of keys to press */ keys: KeyboardKey[]; } /** Options for wait command */ export interface WaitOptions { /** Time to wait in milliseconds */ timeout?: number; } /** Options for waitForText command */ export interface WaitForTextOptions { /** Text to wait for */ text: string; /** Timeout in milliseconds */ timeout?: number; } /** Options for waitForImage command */ export interface WaitForImageOptions { /** Description of the image */ description: string; /** Timeout in milliseconds */ timeout?: number; } /** Options for scrollUntilText command */ export interface ScrollUntilTextOptions { /** Text to find */ text: string; /** Scroll direction */ direction?: ScrollDirection; /** Maximum distance to scroll in pixels */ maxDistance?: number; /** Invert the match */ invert?: boolean; } /** Options for scrollUntilImage command */ export interface ScrollUntilImageOptions { /** Description of the image */ description?: string; /** Scroll direction */ direction?: ScrollDirection; /** Maximum distance to scroll in pixels */ maxDistance?: number; /** Scroll method */ method?: ScrollMethod; /** Path to image template */ path?: string; /** Invert the match */ invert?: boolean; } /** Options for focusApplication command */ export interface FocusApplicationOptions { /** Application name */ name: string; } /** AI sampling configuration for controlling model behavior */ export interface AIConfig { /** Temperature for AI sampling (0 = deterministic, higher = more creative). Default: 0 for find verification, model default for assert. */ temperature?: number; /** Top-P and Top-K sampling parameters */ top?: { /** Top-P (nucleus sampling). Controls diversity by limiting to top P probability mass. Range: 0-1. */ p?: number; /** Top-K sampling. Limits choices to top K tokens. 1 = always pick most likely. 0 = disabled. */ k?: number; }; } /** Options for extract command */ export interface ExtractOptions { /** What to extract */ description: string; } /** Options for assert command */ export interface AssertOptions { /** Assertion to check */ assertion: string; /** Cache threshold (0-1). Lower values require closer matches. Set to -1 to disable cache. */ threshold?: number; /** Cache key for grouping cached assertions (enables caching when provided) */ cacheKey?: string; /** Operating system identifier for cache partitioning */ os?: string; /** Screen resolution for cache partitioning */ resolution?: string; /** AI sampling configuration (overrides global ai config) */ ai?: AIConfig; } /** Options for exec command */ export interface ExecOptions { /** Language ('js', 'pwsh', or 'sh') */ language?: ExecLanguage; /** Code to execute */ code: string; /** Timeout in milliseconds */ timeout?: number; /** Suppress output */ silent?: boolean; } /** Options for captcha command */ export interface CaptchaOptions { /** 2captcha API key (required) */ apiKey: string; /** Override auto-detected sitekey */ sitekey?: string; /** Captcha type: 'recaptcha_v2', 'recaptcha_v3', 'hcaptcha', 'turnstile' */ type?: string; /** reCAPTCHA v3 action (default: 'verify') */ action?: string; /** Whether to auto-submit the form (default: true) */ autoSubmit?: boolean; /** Polling interval in ms for 2captcha (default: 5000) */ pollInterval?: number; /** Max time in ms to wait for solution (default: 120000) */ timeout?: number; } /** Result of captcha solving */ export interface CaptchaResult { /** Whether the captcha was solved successfully */ success: boolean; /** Success/error message */ message: string; /** The solved captcha token */ token: string | null; /** Raw output from the solver script */ output: string; } /** * A Promise that resolves to an Element but also has chainable element methods. * This enables syntax like: await testdriver.find("button").click() */ export interface ChainableElementPromise extends Promise { /** * Click on the element (chainable) * @param action - Type of click action (default: 'click') */ click(action?: ClickAction): Promise; /** * Hover over the element (chainable) */ hover(): Promise; /** * Double-click on the element (chainable) */ doubleClick(): Promise; /** * Right-click on the element (chainable) */ rightClick(): Promise; /** * Press mouse button down on this element (chainable) */ mouseDown(): Promise; /** * Release mouse button on this element (chainable) */ mouseUp(): Promise; /** * Check if element was found (chainable) */ found(): Promise; /** * Get the coordinates of the element (chainable) */ getCoordinates(): Promise; /** * Get the full API response data (chainable) */ getResponse(): Promise; /** * Get the x coordinate (chainable) */ readonly x: Promise; /** * Get the y coordinate (chainable) */ readonly y: Promise; /** * Get the center x coordinate (chainable) */ readonly centerX: Promise; /** * Get the center y coordinate (chainable) */ readonly centerY: Promise; } /** * Element class representing a located or to-be-located element on screen */ export class Element { constructor(description: string); /** * Check if element was found */ found(): boolean; /** * Find the element on screen * @param newDescription - Optional new description to search for * @param options - Cache options: number for threshold, or object with cache.thresholds */ find(newDescription?: string, cacheThreshold?: number): Promise; /** * Click on the element * @param action - Type of click action (default: 'click') */ click(action?: ClickAction): Promise; /** * Hover over the element */ hover(): Promise; /** * Double-click on the element */ doubleClick(): Promise; /** * Right-click on the element */ rightClick(): Promise; /** * Press mouse button down on this element */ mouseDown(): Promise; /** * Release mouse button on this element */ mouseUp(): Promise; /** * Get the coordinates of the element */ getCoordinates(): ElementCoordinates | null; /** * Get the x coordinate (top-left) */ readonly x: number | null; /** * Get the y coordinate (top-left) */ readonly y: number | null; /** * Get the center x coordinate */ readonly centerX: number | null; /** * Get the center y coordinate */ readonly centerY: number | null; /** * Get the full API response data */ getResponse(): ElementResponse | null; /** * Get element screenshot if available (base64 encoded) */ readonly screenshot: string | null; /** * Get element confidence score if available */ readonly confidence: number | null; /** * Get element width if available */ readonly width: number | null; /** * Get element height if available */ readonly height: number | null; /** * Get element bounding box if available */ readonly boundingBox: ElementBoundingBox | null; /** * Get element text content if available */ readonly text: string | null; /** * Get element label if available */ readonly label: string | null; } // ==================================== // Provision API Interfaces // ==================================== /** Options for provision.chrome */ export interface ProvisionChromeOptions { /** URL to navigate to (default: 'http://testdriver-sandbox.vercel.app/') */ url?: string; /** Start maximized (default: true) */ maximized?: boolean; /** Use guest mode (default: false) */ guest?: boolean; } /** Options for provision.chromeExtension */ export interface ProvisionChromeExtensionOptions { /** Local filesystem path to the unpacked extension directory */ extensionPath?: string; /** Chrome Web Store extension ID */ extensionId?: string; /** Start maximized (default: true) */ maximized?: boolean; } /** Options for provision.vscode */ export interface ProvisionVSCodeOptions { /** Path to workspace or folder to open */ workspace?: string; /** Array of extension IDs to install */ extensions?: string[]; } /** Options for provision.installer */ export interface ProvisionInstallerOptions { /** URL to download the installer from */ url: string; /** Filename to save as (auto-detected from URL if not provided) */ filename?: string; /** Application name to focus after install */ appName?: string; /** Whether to launch the app after installation (default: true) */ launch?: boolean; } /** Options for provision.electron */ export interface ProvisionElectronOptions { /** Path to Electron app (required) */ appPath: string; /** Additional electron args */ args?: string[]; } /** Options for provision.dashcam */ export interface ProvisionDashcamOptions { /** Path to log file (auto-generated if not provided) */ logPath?: string; /** Display name for the log (default: 'TestDriver Log') */ logName?: string; /** Enable web log tracking (default: true) */ webLogs?: boolean; /** Custom title for the recording */ title?: string; } /** Provision API for launching applications */ export interface ProvisionAPI { /** * Launch Chrome browser * @param options - Chrome launch options */ chrome(options?: ProvisionChromeOptions): Promise; /** * Launch Chrome browser with a custom extension loaded * @param options - Chrome extension launch options */ chromeExtension(options?: ProvisionChromeExtensionOptions): Promise; /** * Launch VS Code * @param options - VS Code launch options */ vscode(options?: ProvisionVSCodeOptions): Promise; /** * Download and install an application * @param options - Installer options * @returns Path to the downloaded file */ installer(options: ProvisionInstallerOptions): Promise; /** * Launch Electron app * @param options - Electron launch options */ electron(options: ProvisionElectronOptions): Promise; /** * Initialize Dashcam recording with logging * @param options - Dashcam options */ dashcam(options?: ProvisionDashcamOptions): Promise; } /** Dashcam API for screen recording */ export interface DashcamAPI { /** * Start recording */ start(): Promise; /** * Stop recording and get replay URL */ stop(): Promise; /** * Check if currently recording */ isRecording(): boolean; } export default class TestDriverSDK { /** * Create a new TestDriverSDK instance * Automatically loads environment variables from .env file via dotenv. * * @param apiKey - API key (optional, defaults to TD_API_KEY environment variable) * @param options - SDK configuration options * * @example * // API key loaded automatically from TD_API_KEY in .env * const client = new TestDriver(); * * @example * // Pass options only (API key from .env) * const client = new TestDriver({ os: 'windows' }); * * @example * // Or pass API key explicitly * const client = new TestDriver('your-api-key'); */ constructor(apiKey?: string | TestDriverOptions, options?: TestDriverOptions); /** * Whether the SDK is currently connected to a sandbox */ readonly connected: boolean; /** * The operating system of the sandbox */ readonly os: "windows" | "linux"; /** * Provision API for launching applications */ readonly provision: ProvisionAPI; /** * Dashcam API for screen recording */ readonly dashcam: DashcamAPI; /** * Whether Dashcam recording is enabled (default: true) */ readonly dashcamEnabled: boolean; /** * Wait for the sandbox to be ready * Called automatically by provision methods */ ready(): Promise; /** * Authenticate with TestDriver API */ auth(): Promise; /** * Connect to a sandbox environment */ connect(options?: ConnectOptions): Promise; /** * Disconnect from the sandbox */ disconnect(): Promise; /** * Get the last sandbox info from the stored file * @returns Last sandbox info or null if not found */ getLastSandboxId(): { sandboxId: string | null; os: "windows" | "linux"; ami: string | null; instanceType: string | null; timestamp: string | null; } | null; // Element Finding API /** * Find an element by description * Automatically locates the element and returns it * * @param description - Description of the element to find * @param options - Cache threshold (number) or options object with cache.thresholds * @returns Chainable promise that resolves to Element instance * * @example * // Find and click immediately (chainable) * await client.find('the sign in button').click(); * * @example * // Find and click (traditional) * const element = await client.find('the sign in button'); * await element.click(); * * @example * // Find with custom cache thresholds * const element = await client.find('login button', { * cache: { thresholds: { screen: 0.05, element: 0.9 } } * }); * * @example * // Poll for element with timeout (retries every 5 seconds) * const element = await client.find('loading complete indicator', { timeout: 30000 }); * await element.click(); */ find(description: string, cacheThreshold?: number): ChainableElementPromise; find( description: string, options?: { cacheThreshold?: number; cacheKey?: string; timeout?: number; confidence?: number; type?: "text" | "image" | "ui" | "any"; ai?: AIConfig; cache?: { thresholds?: { screen?: number; element?: number } } }, ): ChainableElementPromise; /** * Find all elements matching a description * @param description - Description of the elements to find * @param cacheThreshold - Cache threshold for this specific findAll (overrides global setting) * @returns Array of Element instances * * @example * // Find all buttons * const buttons = await client.findAll('button'); * * @example * // Find with custom cache threshold * const items = await client.findAll('list item', 0.05); */ findAll(description: string, cacheThreshold?: number): Promise; findAll( description: string, options?: { cacheThreshold?: number; cacheKey?: string; cache?: { thresholds?: { screen?: number } } }, ): Promise; // Text Interaction Methods /** * Hover over text on screen * @deprecated Use find() and element.click() instead * @param options - Options object with text, description, action, and timeout */ hoverText(options: HoverTextOptions): Promise; /** * Hover over text on screen (positional arguments - legacy) * @deprecated Use find() and element.click() instead * @param text - Text to find and hover over * @param description - Optional description of the element * @param action - Action to perform (default: 'click') * @param timeout - Timeout in milliseconds (default: 5000) */ hoverText( text: string, description?: string | null, action?: ClickAction, timeout?: number, ): Promise; /** * Type text * @param text - Text to type * @param options - Options object with delay and secret * * @example * // Type regular text * await client.type('hello world'); * * @example * // Type a password securely (not logged or stored) * await client.type(process.env.TD_PASSWORD, { secret: true }); * * @example * // Type with custom delay * await client.type('slow typing', { delay: 100 }); */ type( text: string | number, options?: { delay?: number; secret?: boolean }, ): Promise; /** * Wait for text to appear on screen * @deprecated Use find() in a polling loop instead * @param options - Options object with text and timeout */ waitForText(options: WaitForTextOptions): Promise; /** * Wait for text to appear on screen (positional arguments - legacy) * @deprecated Use find() in a polling loop instead * @param text - Text to wait for * @param timeout - Timeout in milliseconds (default: 5000) */ waitForText(text: string, timeout?: number): Promise; /** * Scroll until text is found * @param options - Options object with text, direction, maxDistance, and invert */ scrollUntilText(options: ScrollUntilTextOptions): Promise; /** * Scroll until text is found (positional arguments - legacy) * @param text - Text to find * @param direction - Scroll direction (default: 'down') * @param maxDistance - Maximum distance to scroll in pixels (default: 10000) * @param invert - Invert the match (default: false) */ scrollUntilText( text: string, direction?: ScrollDirection, maxDistance?: number, invert?: boolean, ): Promise; // Image Interaction Methods /** * Hover over an image on screen * @deprecated Use find() and element.click() instead * @param options - Options object with description and action */ hoverImage(options: HoverImageOptions): Promise; /** * Hover over an image on screen (positional arguments - legacy) * @deprecated Use find() and element.click() instead * @param description - Description of the image to find * @param action - Action to perform (default: 'click') */ hoverImage(description: string, action?: ClickAction): Promise; /** * Match and interact with an image template * @param options - Options object with path, action, and invert */ matchImage(options: MatchImageOptions): Promise; /** * Match and interact with an image template (positional arguments - legacy) * @param imagePath - Path to the image template * @param action - Action to perform (default: 'click') * @param invert - Invert the match (default: false) */ matchImage( imagePath: string, action?: ClickAction, invert?: boolean, ): Promise; /** * Wait for image to appear on screen * @deprecated Use find() in a polling loop instead * @param options - Options object with description and timeout */ waitForImage(options: WaitForImageOptions): Promise; /** * Wait for image to appear on screen (positional arguments - legacy) * @deprecated Use find() in a polling loop instead * @param description - Description of the image * @param timeout - Timeout in milliseconds (default: 10000) */ waitForImage(description: string, timeout?: number): Promise; /** * Scroll until image is found * @param options - Options object with description, direction, maxDistance, method, path, and invert */ scrollUntilImage(options: ScrollUntilImageOptions): Promise; /** * Scroll until image is found (positional arguments - legacy) * @param description - Description of the image (or use path parameter) * @param direction - Scroll direction (default: 'down') * @param maxDistance - Maximum distance to scroll in pixels (default: 10000) * @param method - Scroll method (default: 'keyboard') * @param path - Path to image template (default: null) * @param invert - Invert the match (default: false) */ scrollUntilImage( description: string, direction?: ScrollDirection, maxDistance?: number, method?: ScrollMethod, path?: string | null, invert?: boolean, ): Promise; // Mouse & Keyboard Methods /** * Click at coordinates * @param options - Options object with x, y, and action */ click(options: ClickOptions): Promise; /** * Click at coordinates (positional arguments - legacy) * @param x - X coordinate * @param y - Y coordinate * @param action - Type of click action (default: 'click') */ click(x: number, y: number, action?: ClickAction): Promise; /** * Hover at coordinates * @param options - Options object with x and y */ hover(options: HoverOptions): Promise; /** * Hover at coordinates (positional arguments - legacy) * @param x - X coordinate * @param y - Y coordinate */ hover(x: number, y: number): Promise; /** * Press keyboard keys * @param keys - Array of keys to press * @param options - Additional options (reserved for future use) */ pressKeys(keys: KeyboardKey[], options?: object): Promise; /** * Scroll the page * @param direction - Direction to scroll (default: 'down') * @param options - Options object with amount */ scroll( direction?: ScrollDirection, options?: { amount?: number }, ): Promise; // Application Control /** * Focus an application by name * @param name - Application name * @param options - Additional options (reserved for future use) */ focusApplication(name: string, options?: object): Promise; // AI-Powered Methods /** * Make an AI-powered assertion * @param assertion - Assertion to check * @param options - Cache options for the assertion * * @example * // Simple assertion * await client.assert('the login form is visible'); * * @example * // With caching enabled via cacheKey * await client.assert('the submit button is enabled', { cacheKey: 'my-test-run' }); * * @example * // With custom threshold * await client.assert('the page loaded', { threshold: 0.05, cacheKey: 'login-test' }); */ assert(assertion: string, options?: { threshold?: number; cacheKey?: string; os?: string; resolution?: string; ai?: AIConfig }): Promise; /** * Extract information from the screen using AI * @param options - Options object with description */ extract(options: { description: string }): Promise; /** * Extract information from the screen using AI (positional arguments - legacy) * @param description - What to extract */ extract(description: string): Promise; /** * Solve a captcha on the current page using 2captcha service * @param options - Captcha solving options */ captcha(options: CaptchaOptions): Promise; // Code Execution /** * Execute code in the sandbox * @param options - Options object with language, code, timeout, and silent */ exec(options: ExecOptions): Promise; /** * Execute code in the sandbox (positional arguments - legacy) * @param language - Language ('js' or 'pwsh') * @param code - Code to execute * @param timeout - Timeout in milliseconds * @param silent - Suppress output (default: false) */ exec( language: ExecLanguage, code: string, timeout: number, silent?: boolean, ): Promise; // Utility Methods /** * Capture a screenshot of the current screen and save it to .testdriver/screenshots * @param filename - Custom filename (without .png extension) * @returns The file path where the screenshot was saved * * @example * // Capture a screenshot with auto-generated filename * const screenshotPath = await testdriver.screenshot(); * * @example * // Capture with custom filename * const screenshotPath = await testdriver.screenshot("login-page"); * // Saves to: .testdriver/screenshots//login-page.png */ screenshot(filename?: string): Promise; /** * Parse the current screen using OmniParser v2 to detect all UI elements * Returns structured data with element types, bounding boxes, and content * Requires enterprise or self-hosted plan. * * @returns Parsed screen elements with positions and types * * @example * // Get all elements on screen * const result = await testdriver.parse(); * console.log(`Found ${result.elements.length} elements`); * * @example * // Find clickable elements * const result = await testdriver.parse(); * const clickable = result.elements.filter(e => e.interactivity === 'clickable'); * * @example * // Find text content * const result = await testdriver.parse(); * const textElements = result.elements.filter(e => e.type === 'text'); */ parse(): Promise; /** * Wait for specified time. Useful for adding delays between actions, waiting for * animations to complete, or pausing for state changes to settle. * * For waiting for specific elements to appear, prefer `find()` with a `timeout` option instead. * * @param timeout - Time to wait in milliseconds (default: 3000) * @param options - Additional options (reserved for future use) * * @example * // Wait 2 seconds for an animation to complete * await testdriver.wait(2000); * * @example * // Wait after a click for state to settle * await testdriver.find('submit button').click(); * await testdriver.wait(1000); */ wait(timeout?: number, options?: object): Promise; /** * Get the current sandbox instance details */ getInstance(): SandboxInstance | null; /** * Get the session ID */ getSessionId(): string | null; /** * Enable or disable logging output */ setLogging(enabled: boolean): void; /** * Get the event emitter for custom event handling */ getEmitter(): any; // EventEmitter2 type // AI Methods (Exploratory Loop) /** * @deprecated Use ai() instead * Execute a natural language task using AI * This is the SDK equivalent of the CLI's exploratory loop * * @param task - Natural language description of what to do * @param options - Execution options * @returns Final AI response if validateAndLoop is true * * @example * // Simple execution * await client.ai('Click the submit button'); * * @example * // With validation loop * const result = await client.ai('Fill out the contact form', { validateAndLoop: true }); * console.log(result); // AI's final assessment */ act( task: string, options?: { validateAndLoop?: boolean }, ): Promise; /** * Execute a natural language task using AI * * @param task - Natural language description of what to do * @param options - Execution options * @returns Final AI response if validateAndLoop is true */ ai( task: string, options?: { validateAndLoop?: boolean }, ): Promise; }