@humanjs/playwright 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/internal/timing.ts","../src/internal/mouse-walk.ts","../src/scroll/index.ts","../src/mouse/index.ts","../src/forms/index.ts","../src/keyboard/index.ts","../src/reading/index.ts","../src/recording/codegen.ts","../src/recording/index.ts","../src/recording/capture.ts","../src/mouse-helper/index.ts","../src/index.ts"],"names":["box","clamp","isPoint","writeFile","sleep","options"],"mappings":"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","file":"chunk-CCZEDNOF.js","sourcesContent":["import type { Personality, Rng } from '@humanjs/core';\nimport type { Speed } from '..';\n\n/**\n * Sleeps for `ms` milliseconds. Resolves immediately if `ms <= 0` so callers\n * can hand the result of `computeDwellTime` straight through without guards.\n */\nexport function sleep(ms: number): Promise<void> {\n return ms > 0 ? new Promise((resolve) => setTimeout(resolve, ms)) : Promise.resolve();\n}\n\n/**\n * Per-mode timing multiplier applied on top of personality.speed.\n * - `'human'`: 1 — full humanization\n * - `'fast'`: 0.5 — accelerated humanization (still humanized, just brisk)\n * - `'instant'`: 0 — no delays (CI / snapshot mode)\n */\nexport function speedModeFactor(speed: Speed): number {\n switch (speed) {\n case 'fast':\n return 0.5;\n case 'instant':\n return 0;\n default:\n return 1;\n }\n}\n\n/**\n * Computes a dwell time in ms with deterministic jitter and personality scaling.\n *\n * base = meanMs\n * jitter = base × jitterFraction × rand[-1, 1]\n * total = (base + jitter) × personality.speed × speedModeFactor(speed)\n *\n * Returns 0 for non-positive inputs so callers can skip the sleep entirely.\n */\nexport function computeDwellTime(\n meanMs: number,\n jitter: number,\n personality: Personality,\n speed: Speed,\n rng: Rng,\n): number {\n if (meanMs <= 0) return 0;\n const jitterMag = meanMs * jitter;\n const offset = rng.nextFloat(-jitterMag, jitterMag);\n return Math.max(0, (meanMs + offset) * personality.speed * speedModeFactor(speed));\n}\n","import type { Point } from '@humanjs/core';\nimport type { Page } from 'playwright';\nimport { sleep } from './timing';\n\n/**\n * Walks the mouse along `path` over `durationMs`, evenly spacing the steps.\n * Generic helper used by both the click executor (which derives `durationMs`\n * from `personality.mouse.travelTimeMs`) and the read executor (which uses\n * the reading dwell duration so the cursor finishes its scan exactly as the\n * dwell elapses).\n *\n * - Empty path is a no-op.\n * - `durationMs <= 0` jumps through the path without inter-step delays\n * (matches `speed: 'instant'` behavior).\n */\nexport async function walkMouseAlongPath(\n page: Page,\n path: readonly Point[],\n durationMs: number,\n): Promise<void> {\n if (path.length === 0) return;\n const stepDelayMs = path.length > 1 && durationMs > 0 ? durationMs / (path.length - 1) : 0;\n\n for (let i = 0; i < path.length; i++) {\n const point = path[i];\n if (!point) continue;\n await page.mouse.move(point.x, point.y);\n if (i < path.length - 1 && stepDelayMs > 0) {\n await sleep(stepDelayMs);\n }\n }\n}\n","import { type Personality, planScroll, type Rng, type ScrollSegment } from '@humanjs/core';\nimport type { Locator, Page } from 'playwright';\nimport type { Speed } from '../index';\nimport { sleep, speedModeFactor } from '../internal/timing';\n\n/** Runtime dependencies for a humanized scroll. */\nexport interface ScrollContext {\n readonly page: Page;\n readonly personality: Personality;\n readonly rng: Rng;\n readonly speed: Speed;\n}\n\n/**\n * What / where to scroll. The chosen axis (`'y'` by default, `'x'` via\n * `options.axis`) decides whether targets resolve along the vertical or\n * horizontal axis.\n *\n * - `'natural'`: scroll one viewport along the chosen axis (default).\n * - `'end'`: scroll to the far edge (bottom for `'y'`, right for `'x'`).\n * - `'top'`: scroll to the origin (top for `'y'`, left for `'x'`).\n * - `string`: a Playwright-compatible selector — scroll until in view.\n * - `Locator`: same, but you already have a Locator handle.\n * - `{ by: number }`: relative pixel delta (negative = up / left).\n * - `{ to: number }`: absolute scroll position on the chosen axis.\n */\nexport type ScrollTarget =\n | 'natural'\n | 'end'\n | 'top'\n | string\n | Locator\n | { readonly by: number }\n | { readonly to: number };\n\nexport interface ScrollOptions {\n /**\n * Force an overshoot + correction even if the personality wouldn't choose\n * one. Useful when you want the humanization signal regardless of\n * personality (e.g. demos).\n */\n readonly overshoot?: boolean;\n /**\n * Disable mid-scroll micro-pauses. Defaults to `true` (pauses enabled).\n * Set `false` for the smoothest possible motion.\n */\n readonly withPauses?: boolean;\n /**\n * For element targets only: where to align the element along the chosen\n * axis when the scroll ends. Mirrors `scrollIntoView({ block })`.\n * Defaults to `'start'`.\n *\n * - `'start'`: element's leading edge aligns with the viewport's leading\n * edge (top for `axis: 'y'`, left for `axis: 'x'`)\n * - `'center'`: element centers in the viewport\n * - `'end'`: element's trailing edge aligns with the viewport's trailing\n * edge (bottom for `'y'`, right for `'x'`)\n * - `'nearest'`: do the minimum scroll — stay put if the element is\n * already fully visible, otherwise scroll to the closest edge\n */\n readonly block?: 'start' | 'center' | 'end' | 'nearest';\n /**\n * Scroll inside a scrollable container instead of the page. Accepts a\n * Playwright-compatible selector or a built `Locator`. Every scroll\n * semantic (`'natural'`, `'top'`, `'end'`, `{ by }`, `{ to }`, element\n * targets, `block` alignment) applies relative to the container.\n *\n * In humanized speed modes, the cursor parks over the container's\n * center so the visible cursor reads as \"human hand on the wheel\"\n * (when paired with `installMouseHelper`), and each planned segment\n * advances the container's `scrollLeft` / `scrollTop` directly. Direct\n * property assignment is more reliable than dispatching wheel events\n * into nested overflow containers — Playwright's synthetic wheel\n * events don't always route past the cursor element. In `'instant'`\n * mode, the container's scroll position is set with a single\n * `scrollTo` call.\n *\n * Common use: chat threads, modal bodies, infinite-scroll feeds, any\n * `<div style=\"overflow-y: auto\">` that owns its own scrollbar.\n */\n readonly within?: string | Locator;\n /**\n * Which axis to scroll along. Defaults to `'y'` (vertical).\n *\n * Set `'x'` for horizontal scrolling — carousels, kanban boards,\n * sideways galleries. Every target shape still works: `'natural'`\n * scrolls one viewport-width right, `'top'` jumps to scrollLeft 0,\n * `'end'` to (scrollWidth - clientWidth), `{ by }` / `{ to }` apply to\n * the X-axis, and element targets scroll until the element is visible\n * horizontally.\n */\n readonly axis?: 'x' | 'y';\n}\n\n/** Outcome of a scroll, returned to the caller for observability. */\nexport interface ScrollResult {\n /** Starting scroll position along the chosen axis (scrollY or scrollX). */\n readonly from: number;\n /** Final scroll position the scroll aimed for, along the chosen axis. */\n readonly to: number;\n /** Signed pixel distance (`to - from`). */\n readonly distance: number;\n /** Total elapsed dwell + motion time in ms. Zero in `speed: 'instant'`. */\n readonly durationMs: number;\n}\n\n/** Reserved string targets that select a behavior rather than an element. */\nconst RESERVED_TARGETS = new Set(['natural', 'end', 'top']);\n\n/**\n * Generic axis description — the planner doesn't care whether it's driving\n * `window.scrollY` or an element's `scrollTop`. Both look like the same\n * 1-D problem: a current position, a viewport length, and a max scrollable\n * extent.\n */\ninterface ScrollGeometry {\n /** Current scroll position. */\n readonly current: number;\n /** Visible length (viewport height for window, clientHeight for container). */\n readonly viewport: number;\n /** Total scrollable extent (docHeight for window, scrollHeight for container). */\n readonly total: number;\n /**\n * For container scrolls: viewport-relative center coordinates the cursor\n * should park at so an `installMouseHelper` overlay reads as \"human hand\n * on the wheel\" during the scroll. Undefined for window scrolls (no\n * cursor parking — the page scrolls without a per-target hover).\n */\n readonly hover?: { x: number; y: number };\n}\n\n/**\n * Executes a humanized scroll on either the page or a scrollable container,\n * along the chosen axis.\n *\n * Flow:\n * 1. Resolve the scope: page (default) or a container if `within` is set.\n * 2. Read current position + viewport + total geometry for the chosen axis.\n * 3. Resolve target → final position on that axis.\n * 4. Plan segments via `planScroll`.\n * 5. Walk the segments — for page scrolls, dispatch `page.mouse.wheel`\n * events on the chosen axis. For containers, advance the element's\n * `scrollLeft` / `scrollTop` directly (wheel events don't always\n * route into nested overflow containers). Containers also park the\n * cursor at their center so an `installMouseHelper` overlay reads\n * as \"hand on the wheel.\"\n *\n * In `speed: 'instant'`, all humanization is bypassed:\n * - Page scrolls call `window.scrollTo(...)` with the new position on the\n * chosen axis and the existing position on the other.\n * - Container scrolls evaluate `el.scrollTo(...)` with the same shape.\n */\nexport async function executeScroll(\n target: ScrollTarget | undefined,\n ctx: ScrollContext,\n options: ScrollOptions = {},\n): Promise<ScrollResult> {\n const { page, personality, rng, speed } = ctx;\n const speedFactor = speedModeFactor(speed);\n const axis: 'x' | 'y' = options.axis ?? 'y';\n\n const container = resolveWithin(options.within, ctx);\n const geom = container\n ? await readContainerGeometry(container, axis)\n : await readWindowGeometry(page, axis);\n if (!geom) {\n // Container not found / not scrollable — nothing to do.\n return { from: 0, to: 0, distance: 0, durationMs: 0 };\n }\n\n const from = geom.current;\n const targetPos = await resolveTarget(target, ctx, geom, container, axis, options.block);\n const to = clamp(targetPos, 0, Math.max(0, geom.total - geom.viewport));\n const distance = to - from;\n\n if (distance === 0) {\n return { from, to, distance: 0, durationMs: 0 };\n }\n\n if (speed === 'instant') {\n if (container) {\n await container.evaluate(\n (el, args) => {\n const a = args as { axis: 'x' | 'y'; pos: number };\n if (a.axis === 'x') el.scrollTo(a.pos, el.scrollTop);\n else el.scrollTo(el.scrollLeft, a.pos);\n },\n { axis, pos: to },\n );\n } else {\n await page.evaluate(\n (args) => {\n if (args.axis === 'x') window.scrollTo(args.pos, window.scrollY);\n else window.scrollTo(window.scrollX, args.pos);\n },\n { axis, pos: to },\n );\n }\n return { from, to, distance, durationMs: 0 };\n }\n\n const segments = planScroll(from, to, personality.scroll, rng, {\n forceOvershoot: options.overshoot,\n withPauses: options.withPauses,\n personalitySpeed: personality.speed,\n speedFactor,\n });\n\n // For container scrolls, park the cursor over the container so the\n // visible cursor (when `installMouseHelper` is in use) reads as \"human\n // hand on the wheel.\" Actual scrolling goes through direct\n // `scrollLeft` / `scrollTop` assignment in `walkSegments` — Playwright's\n // synthetic wheel events don't reliably route into nested overflow\n // containers.\n if (container && geom.hover) {\n await page.mouse.move(geom.hover.x, geom.hover.y);\n }\n\n const startedAt = Date.now();\n await walkSegments(page, segments, axis, container);\n const durationMs = Date.now() - startedAt;\n\n return { from, to, distance, durationMs };\n}\n\n/** Coerces the `within` option into a Locator (or null when unset). */\nfunction resolveWithin(within: ScrollOptions['within'], ctx: ScrollContext): Locator | null {\n if (!within) return null;\n return typeof within === 'string' ? ctx.page.locator(within) : within;\n}\n\n/** Reads the page's current scroll geometry for the chosen axis. */\nasync function readWindowGeometry(page: Page, axis: 'x' | 'y'): Promise<ScrollGeometry> {\n const g = await page.evaluate((a: 'x' | 'y') => {\n if (a === 'x') {\n return {\n current: window.scrollX,\n viewport: window.innerWidth,\n total: Math.max(document.documentElement.scrollWidth, document.body?.scrollWidth ?? 0),\n };\n }\n return {\n current: window.scrollY,\n viewport: window.innerHeight,\n total: Math.max(document.documentElement.scrollHeight, document.body?.scrollHeight ?? 0),\n };\n }, axis);\n return { current: g.current, viewport: g.viewport, total: g.total };\n}\n\n/**\n * Reads container scroll geometry for the chosen axis plus the center of\n * its viewport-relative bounding box (for cursor parking). Returns `null`\n * if the element resolves to nothing.\n */\nasync function readContainerGeometry(\n container: Locator,\n axis: 'x' | 'y',\n): Promise<ScrollGeometry | null> {\n return container\n .evaluate((el, a: 'x' | 'y') => {\n const rect = el.getBoundingClientRect();\n const isX = a === 'x';\n return {\n current: isX ? el.scrollLeft : el.scrollTop,\n viewport: isX ? el.clientWidth : el.clientHeight,\n total: isX ? el.scrollWidth : el.scrollHeight,\n hover: {\n x: rect.left + rect.width / 2,\n y: rect.top + rect.height / 2,\n },\n } as const;\n }, axis)\n .catch(() => null);\n}\n\n/**\n * Resolves a `ScrollTarget` to an absolute scroll position on the active\n * axis (window scroll or container scroll, vertical or horizontal).\n */\nasync function resolveTarget(\n target: ScrollTarget | undefined,\n ctx: ScrollContext,\n geom: ScrollGeometry,\n container: Locator | null,\n axis: 'x' | 'y',\n block: 'start' | 'center' | 'end' | 'nearest' = 'start',\n): Promise<number> {\n if (target === undefined || target === 'natural') return geom.current + geom.viewport;\n if (target === 'end') return geom.total;\n if (target === 'top') return 0;\n if (typeof target === 'object' && 'by' in target) return geom.current + target.by;\n if (typeof target === 'object' && 'to' in target) return target.to;\n\n // Element target — selector string or Locator.\n const elementLocator =\n typeof target === 'string' && !RESERVED_TARGETS.has(target)\n ? ctx.page.locator(target)\n : typeof target === 'string'\n ? null\n : target;\n if (!elementLocator) return geom.current + geom.viewport;\n\n return container\n ? resolveElementWithinContainer(elementLocator, container, geom, axis, block)\n : resolveElementInWindow(elementLocator, geom, axis, block);\n}\n\n/**\n * Computes the scroll position needed to align a window-level element per\n * `block` along the chosen axis. `rect.x` / `rect.y` are viewport-relative;\n * absolute position is `geom.current + rect.{axis}`.\n */\nasync function resolveElementInWindow(\n elementLocator: Locator,\n geom: ScrollGeometry,\n axis: 'x' | 'y',\n block: 'start' | 'center' | 'end' | 'nearest',\n): Promise<number> {\n const rect = await elementLocator.boundingBox().catch(() => null);\n if (!rect) return geom.current;\n const relStart = axis === 'x' ? rect.x : rect.y;\n const length = axis === 'x' ? rect.width : rect.height;\n const absoluteStart = geom.current + relStart;\n const absoluteEnd = absoluteStart + length;\n if (block === 'start') return absoluteStart;\n if (block === 'end') return absoluteEnd - geom.viewport;\n if (block === 'nearest') {\n if (relStart >= 0 && relStart + length <= geom.viewport) return geom.current;\n if (relStart < 0) return absoluteStart;\n return absoluteEnd - geom.viewport;\n }\n return absoluteStart - (geom.viewport - length) / 2;\n}\n\n/**\n * Computes the container's `scrollTop` / `scrollLeft` needed to align an\n * element per `block` along the chosen axis. Element offset from the\n * container's content origin =\n * `(element.rect.{axis} - container.rect.{axis}) + container.scroll{axis}`\n * regardless of whether the container is the element's positioning ancestor.\n */\nasync function resolveElementWithinContainer(\n elementLocator: Locator,\n container: Locator,\n geom: ScrollGeometry,\n axis: 'x' | 'y',\n block: 'start' | 'center' | 'end' | 'nearest',\n): Promise<number> {\n const rects = await container\n .evaluate(\n (containerEl, args: { sel: string | null; axis: 'x' | 'y' }) => {\n const elementEl = args.sel ? document.querySelector(args.sel) : null;\n // The element may not be a child of the container — handle that too.\n const targetEl = elementEl ?? (containerEl.querySelector(':scope > *') as Element | null);\n if (!targetEl) return null;\n const cRect = containerEl.getBoundingClientRect();\n const eRect = targetEl.getBoundingClientRect();\n return args.axis === 'x'\n ? { relStart: eRect.left - cRect.left, length: eRect.width }\n : { relStart: eRect.top - cRect.top, length: eRect.height };\n },\n { sel: await locatorSelector(elementLocator), axis },\n )\n .catch(() => null);\n if (!rects) return geom.current;\n // Offset from container's content origin = (visual delta) + scroll position.\n const offsetStart = rects.relStart + geom.current;\n const offsetEnd = offsetStart + rects.length;\n if (block === 'start') return offsetStart;\n if (block === 'end') return offsetEnd - geom.viewport;\n if (block === 'nearest') {\n if (rects.relStart >= 0 && rects.relStart + rects.length <= geom.viewport) {\n return geom.current;\n }\n if (rects.relStart < 0) return offsetStart;\n return offsetEnd - geom.viewport;\n }\n return offsetStart - (geom.viewport - rects.length) / 2;\n}\n\n/**\n * Best-effort recovery of the selector string a Locator wraps. Playwright's\n * `Locator.toString()` returns something like `locator('css=#foo')` — we\n * strip the wrapper to get the inner selector. Falls back to `null` when\n * the format isn't recognized; the caller treats that as \"no element.\"\n *\n * Fragile by design: depends on Playwright's internal `toString()` shape,\n * which isn't a stable public API. Used only when resolving element\n * targets *inside* a `within` container, since the executor needs to\n * `querySelector` from the container's perspective rather than the\n * document's. For chained Locators (e.g. `page.locator('foo').first()`)\n * the regex grabs the first quoted selector and ignores chained\n * refinements — good enough for the common case, but worth a richer\n * approach if Playwright ever changes the shape.\n */\nasync function locatorSelector(locator: Locator): Promise<string | null> {\n const s = locator.toString?.();\n if (typeof s !== 'string') return null;\n const match = /locator\\(['\"](.+?)['\"]/.exec(s);\n if (!match) return null;\n const raw = match[1] ?? '';\n // Strip an \"engine=\" prefix when present (Playwright sometimes prepends one).\n const eq = raw.indexOf('=');\n return eq > 0 && /^[a-z]+$/.test(raw.slice(0, eq)) ? raw.slice(eq + 1) : raw;\n}\n\n/**\n * Walks the planned segments. For page scrolls, dispatches wheel events\n * on the chosen axis — real wheel events trigger every page-level wheel\n * handler, which is part of HumanJS's \"dispatch what a human dispatches\"\n * promise.\n *\n * For container scrolls, advances `scrollLeft` / `scrollTop` directly via\n * `container.evaluate`. Playwright's `page.mouse.wheel` doesn't reliably\n * route into nested overflow containers (the event hits the element under\n * the cursor but may scroll a parent or no element instead). Direct\n * property assignment is deterministic — it always scrolls the target —\n * and the brand promise stays intact because the planner still owns the\n * bell-curve cadence, mid-scroll pauses, and overshoot.\n */\nasync function walkSegments(\n page: Page,\n segments: readonly ScrollSegment[],\n axis: 'x' | 'y',\n container: Locator | null,\n): Promise<void> {\n for (const segment of segments) {\n if (segment.delayBeforeMs > 0) await sleep(segment.delayBeforeMs);\n if (segment.delta === 0) continue;\n if (container) {\n await container.evaluate(\n (el, args) => {\n const a = args as { axis: 'x' | 'y'; delta: number };\n // Direct property assignment is more reliable than `scrollBy()`\n // — some flex/grid layouts have edge cases where scrollBy\n // becomes a no-op despite the element being scrollable.\n if (a.axis === 'x') el.scrollLeft += a.delta;\n else el.scrollTop += a.delta;\n },\n { axis, delta: segment.delta },\n );\n } else if (axis === 'x') {\n await page.mouse.wheel(segment.delta, 0);\n } else {\n await page.mouse.wheel(0, segment.delta);\n }\n }\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return value < min ? min : value > max ? max : value;\n}\n","import { bezierPath, humanizePath, type Personality, type Point, type Rng } from '@humanjs/core';\nimport type { Locator, Page } from 'playwright';\nimport type { Speed } from '../index';\nimport { walkMouseAlongPath } from '../internal/mouse-walk';\nimport { computeDwellTime, sleep, speedModeFactor } from '../internal/timing';\nimport { executeScroll } from '../scroll';\n\n/** Runtime dependencies for a humanized mouse action. */\nexport interface MouseContext {\n readonly page: Page;\n readonly personality: Personality;\n readonly rng: Rng;\n readonly speed: Speed;\n /** Last known mouse position — used as the path start. */\n readonly getMousePosition: () => Point;\n /** Updates the last known mouse position after a move/click. */\n readonly setMousePosition: (point: Point) => void;\n}\n\n/** Anything that can resolve to a click/move point. */\nexport type MouseTarget = Locator | string | Point;\n\n/** Result of a click action, returned to the caller for observability. */\nexport interface ClickResult {\n /** Coordinates the click landed at. */\n readonly target: Point;\n}\n\n/** Result of a hover action. */\nexport interface HoverResult {\n /** Coordinates the cursor settled at. */\n readonly target: Point;\n}\n\n/** Result of a drag action. */\nexport interface DragResult {\n /** Coordinates the drag started from. */\n readonly from: Point;\n /** Coordinates the drag ended at. */\n readonly to: Point;\n}\n\n/** Result of a move action. */\nexport interface MoveResult {\n /** Coordinates the cursor settled at. */\n readonly target: Point;\n}\n\n/** Options for {@link executeClick}. */\nexport interface ClickOptions {\n /**\n * Mouse button to press. Defaults to `'left'`. `'right'` produces a\n * context-menu click; `'middle'` is the wheel-button click (rarely used).\n */\n readonly button?: 'left' | 'right' | 'middle';\n /**\n * Number of clicks at the target. `2` dispatches a double-click (the two\n * presses fire back-to-back within the OS double-click window). Defaults\n * to `1`. The humanized approach motion (path + hover dwell) is identical\n * regardless of count — only the final dispatch differs.\n */\n readonly clickCount?: 1 | 2;\n}\n\n/**\n * Executes a humanized click on a target.\n *\n * `target` accepts a selector, a `Locator`, or a raw `Point`. The `Point`\n * form is the Computer-Use-style fallback: when an AI agent can *see* a\n * control in a screenshot but has no clean selector for it (icon-only\n * buttons, canvas, SVG), it can click the visible coordinates directly.\n * Coordinate clicks skip auto-scroll and box-relative aim — the caller\n * owns the exact point.\n *\n * Steps:\n * 1. Resolve the target's bounding box (or accept a raw `Point`).\n * 2. Pick a click point inside it — Gaussian-centered so we never click\n * dead-center, which is itself a bot signal. (Raw `Point` is used as-is.)\n * 3. Generate a Bezier path from the current mouse position to the target.\n * 4. Apply velocity profile + micro-jitter via `humanizePath`.\n * 5. Walk the mouse along the path with timing scaled by personality + speed.\n * 6. Hover dwell — a real user briefly settles on the target before clicking.\n * 7. Click at the target coordinates with the configured button.\n *\n * In `speed: 'instant'`, all humanization is bypassed: element targets use\n * Playwright's native `locator.click()`; raw `Point` targets dispatch a\n * single `mouse.click()` at the coordinates.\n */\nexport async function executeClick(\n target: MouseTarget,\n ctx: MouseContext,\n options: ClickOptions = {},\n): Promise<ClickResult> {\n const button = options.button ?? 'left';\n const clickCount = options.clickCount ?? 1;\n // Only surface `clickCount` when it's a double-click — keeps the common\n // single-click dispatch as `{ button }` (no behavioral change for clicks).\n const clickOpts = clickCount > 1 ? { button, clickCount } : { button };\n\n if (ctx.speed === 'instant') {\n if (isPoint(target)) {\n await ctx.page.mouse.click(target.x, target.y, clickOpts);\n ctx.setMousePosition(target);\n return { target };\n }\n // Playwright's `locator.click()` auto-scrolls the element into view as\n // part of its actionability checks, so we don't need a manual scroll\n // here. Read the box BEFORE the click — the click may navigate away or\n // remove the element, after which `boundingBox()` returns null.\n const locator = typeof target === 'string' ? ctx.page.locator(target) : target;\n const box = await locator.boundingBox();\n await locator.click(clickOpts);\n const center = box\n ? { x: box.x + box.width / 2, y: box.y + box.height / 2 }\n : ctx.getMousePosition();\n ctx.setMousePosition(center);\n return { target: center };\n }\n\n // Resolve to a point (+ box for element targets, null for raw Points).\n // Same path drag's grab endpoint uses, so the misclick beat picks a\n // \"near-miss outside the box\" for elements and \"around the point\" for\n // raw coordinates.\n const { point: targetPoint, box } = await resolveTargetPointAndBox(target, ctx, 'click');\n await maybeMisclickBeat(ctx, box, targetPoint);\n await walkBezierTo(targetPoint, ctx);\n\n // Hover dwell — a real user briefly settles on the target before clicking.\n const preClickMs = computeDwellTime(\n ctx.personality.dwell.preClickMs,\n ctx.personality.dwell.preClickJitter,\n ctx.personality,\n ctx.speed,\n ctx.rng,\n );\n if (preClickMs > 0) await sleep(preClickMs);\n\n // Commit the new position BEFORE the click side-effect. If the click throws\n // (page closed, target removed mid-flight), the next action still starts\n // from the correct mouse position.\n ctx.setMousePosition(targetPoint);\n await ctx.page.mouse.click(targetPoint.x, targetPoint.y, clickOpts);\n\n // Post-action dwell — a beat after the click before the next action.\n const postActionMs = computeDwellTime(\n ctx.personality.dwell.postActionMs,\n ctx.personality.dwell.postActionJitter,\n ctx.personality,\n ctx.speed,\n ctx.rng,\n );\n if (postActionMs > 0) await sleep(postActionMs);\n\n return { target: targetPoint };\n}\n\n/**\n * Executes a humanized hover. Moves the cursor to the target along a Bezier\n * path, settles on it briefly (the same pre-click dwell `click` uses), and\n * leaves the cursor parked there. No click is dispatched.\n *\n * Useful for hover-triggered UI (tooltips, dropdowns) and for explicitly\n * positioning the cursor when subsequent actions should originate from a\n * specific element.\n *\n * In `speed: 'instant'`, dispatches a single `page.mouse.move()` to the\n * element's center — same bypass semantic as click's instant mode.\n */\nexport async function executeHover(\n target: Locator | string,\n ctx: MouseContext,\n): Promise<HoverResult> {\n if (ctx.speed === 'instant') {\n // Snap the element into view only if its center isn't already inside\n // the viewport — same shape as the humanized path's viewport check.\n // Skipping the no-op `scrollIntoViewIfNeeded()` call saves a protocol\n // round-trip on every hover, and keeps all four instant-mode paths\n // (click via locator.click, hover, move, drag) consistent: scroll only\n // when required, never unconditionally.\n const box = await readBoxWithAutoScroll(target, ctx, 'hover');\n const center = { x: box.x + box.width / 2, y: box.y + box.height / 2 };\n await ctx.page.mouse.move(center.x, center.y);\n ctx.setMousePosition(center);\n return { target: center };\n }\n\n const targetPoint = await moveToTarget(target, ctx);\n\n // Use the pre-click dwell as the \"settle on the hover target\" beat —\n // same shape as click's hover-before-click motion.\n const dwellMs = computeDwellTime(\n ctx.personality.dwell.preClickMs,\n ctx.personality.dwell.preClickJitter,\n ctx.personality,\n ctx.speed,\n ctx.rng,\n );\n if (dwellMs > 0) await sleep(dwellMs);\n\n ctx.setMousePosition(targetPoint);\n return { target: targetPoint };\n}\n\n/**\n * Executes a humanized drag from one location to another.\n *\n * 0. **Curve-aware viewport check** (element×element drags only): the\n * drag's main walk uses a Bezier curve whose perpendicular extent\n * can reach `distance × curvature`. If that worst-case path would\n * extrude past a viewport edge with the mouse button held, Chrome\n * engages native edge-scroll-during-drag and walks the page wildly.\n * We pre-scroll just enough plus a small margin so the worst-case\n * curve fits. Skipped for raw-`Point` endpoints because scrolling\n * would shift the element relative to the caller's explicit point.\n * 1. Optionally near-miss the grab — with probability\n * `personality.mouse.misclickProbability`, the cursor first walks to a\n * point just outside the `from` target (or near it, for raw-Point\n * `from`), dwells briefly, then approaches the real grab point. No\n * mousedown fires at the off-target coordinates.\n * 2. Move the cursor to the `from` target along a Bezier path.\n * 3. Press the left mouse button down.\n * 4. Optionally near-miss the drop — independent probability roll, same\n * visual-only shape: cursor walks to a near-miss point with the\n * button still held, dwells, then continues to the real drop point.\n * No mouseup fires at the off-target coordinates. The marginal cost\n * is a small extra detour through `dragover` events on neighbors,\n * which is already part of normal drag motion.\n * 5. Walk a fresh Bezier path to `to`, with the button still held. This\n * is the actual drag motion the page sees.\n * 6. Release the button at `to`.\n *\n * Both endpoints accept a CSS selector, a Locator, or a literal `Point` —\n * the last form is essential for canvas/SVG drags where the destination\n * isn't a DOM element. The grab and drop endpoints roll for misclick\n * independently, so a single drag may near-miss either, both, or neither.\n *\n * In `speed: 'instant'`, dispatches a single `mouse.down → move → up`\n * sequence at the resolved endpoints without humanized motion.\n */\nexport async function executeDrag(\n from: MouseTarget,\n to: MouseTarget,\n ctx: MouseContext,\n): Promise<DragResult> {\n // Resolve `from` first, scrolling if needed. Then resolve `to` — if the\n // destination is also off-viewport, this triggers a second scroll. That's\n // the right shape for cross-viewport drags: a real user scrolls to grab,\n // then scrolls again to drop, rather than dragging through invisible space.\n //\n // We bracket the resolves with `scrollY` reads to detect any auto-scroll\n // that happened for an element-bound endpoint, then shift raw `Point`\n // endpoints by the same delta. That preserves the *visual relationship*\n // a raw Point has to the view at the time of call — callers typically\n // compute raw Points from element positions they see right now, so when\n // the page scrolls during resolution, the Point should follow. Otherwise\n // a horizontal slider drag ('#thumb' → { x, y }) silently becomes\n // diagonal as soon as the thumb auto-scrolls and the raw Point stays put.\n //\n // `let` because both endpoints may shift during the curve-aware check\n // below.\n const scrollYBeforeResolve = await readScrollY(ctx.page);\n let { point: fromPoint, box: fromBox } = await resolveTargetPointAndBox(from, ctx, 'drag');\n let { point: toPoint, box: toBox } = await resolveTargetPointAndBox(to, ctx, 'drag');\n const resolveScrollDelta = (await readScrollY(ctx.page)) - scrollYBeforeResolve;\n if (resolveScrollDelta !== 0) {\n if (isPoint(from)) fromPoint = { x: fromPoint.x, y: fromPoint.y - resolveScrollDelta };\n if (isPoint(to)) toPoint = { x: toPoint.x, y: toPoint.y - resolveScrollDelta };\n }\n\n if (ctx.speed === 'instant') {\n await ctx.page.mouse.move(fromPoint.x, fromPoint.y);\n await ctx.page.mouse.down();\n await ctx.page.mouse.move(toPoint.x, toPoint.y);\n await ctx.page.mouse.up();\n ctx.setMousePosition(toPoint);\n return { from: fromPoint, to: toPoint };\n }\n\n // 0. Curve-aware viewport headroom. Both endpoints might be individually\n // in-viewport (so per-endpoint auto-scroll didn't fire), yet the Bezier\n // curve between them — control points perpendicular-offset by up to\n // `distance × curvature` — can extrude outside the viewport while the\n // mouse button is held. When that happens Chrome engages its native\n // edge-scroll-during-drag behavior and walks the page wildly.\n //\n // Pre-scroll just enough plus a small margin so the worst-case curve\n // fits. Only applies when both endpoints are element-bound: a page\n // scroll moves both together and preserves their relative geometry.\n // For mixed endpoints, the resolve-time scroll above already shifted\n // any raw Point by the auto-scroll delta — if a curve still wouldn't\n // fit after that, scrolling more would chase its own tail (each scroll\n // shifts the raw Point but lengthens the drag), so we don't.\n if (fromBox && toBox) {\n const scrollDelta = computeCurveScrollDelta(\n fromPoint,\n toPoint,\n ctx.page.viewportSize(),\n ctx.personality.mouse.curvature,\n );\n if (scrollDelta !== 0) {\n await executeScroll({ by: scrollDelta }, ctx, {});\n const refreshedFrom = await resolveTargetPointAndBox(from, ctx, 'drag');\n fromPoint = refreshedFrom.point;\n fromBox = refreshedFrom.box;\n const refreshedTo = await resolveTargetPointAndBox(to, ctx, 'drag');\n toPoint = refreshedTo.point;\n toBox = refreshedTo.box;\n }\n }\n\n // 1. Maybe near-miss the grab. Same shape as click's misclick beat;\n // `from` commits an action (mousedown), so the misclick principle applies.\n await maybeMisclickBeat(ctx, fromBox, fromPoint);\n\n // 2. Move to the start of the drag.\n await walkBezierTo(fromPoint, ctx);\n ctx.setMousePosition(fromPoint);\n\n // 3. Press down. Beat between settling on the source and starting to drag\n // — real users don't grab the same frame they arrive.\n const preDragMs = computeDwellTime(\n ctx.personality.dwell.preClickMs,\n ctx.personality.dwell.preClickJitter,\n ctx.personality,\n ctx.speed,\n ctx.rng,\n );\n if (preDragMs > 0) await sleep(preDragMs);\n await ctx.page.mouse.down();\n\n // 4. Maybe near-miss the drop. Independent roll from the grab — a drag\n // may near-miss the grab, the drop, both, or neither. Same visual-only\n // safety: the cursor wanders near `to` and dwells, but mouseup only\n // fires once the cursor has walked to the real drop point in step 5.\n // Dragover events fire on neighbors during the detour, but they were\n // already firing along the natural drag path — the misclick adds a\n // small extra loop, which is exactly what an exploratory drop attempt\n // looks like in real human use.\n await maybeMisclickBeat(ctx, toBox, toPoint);\n\n // 5. Walk to the destination with the button still held. `walkBezierTo`\n // generates a fresh humanized path from the cursor's current position\n // (which may be the misclick point from step 4, or `fromPoint` if no\n // misclick fired) to `toPoint`.\n await walkBezierTo(toPoint, ctx);\n\n // 6. Release. Post-action dwell so the next action doesn't fire in the\n // same frame as the drop.\n await ctx.page.mouse.up();\n ctx.setMousePosition(toPoint);\n\n const postActionMs = computeDwellTime(\n ctx.personality.dwell.postActionMs,\n ctx.personality.dwell.postActionJitter,\n ctx.personality,\n ctx.speed,\n ctx.rng,\n );\n if (postActionMs > 0) await sleep(postActionMs);\n\n return { from: fromPoint, to: toPoint };\n}\n\n/**\n * Moves the cursor to `target` along a humanized Bezier path. Pure\n * positioning — no settle dwell, no element interaction, no event beyond\n * the standard mousemove sequence from walking the path. Accepts the same\n * `MouseTarget` shape as `drag`'s endpoints (Locator | string | Point).\n *\n * Distinct from `executeHover`:\n *\n * - `move` is positional. Pass coordinates or an element; the cursor\n * arrives and stops. Use this for canvas painting, slider drags\n * composed with separate up/down, placement before a keyboard press, or cinematic\n * beats where the cursor should pause somewhere with no element under it.\n * - `hover` is element-bound and includes the post-arrival dwell that\n * lets hover-state UI fire (tooltips, dropdown reveals).\n *\n * In `speed: 'instant'`, dispatches a single `page.mouse.move()` to the\n * resolved coordinates — same bypass semantic as the rest of the mouse\n * primitives in instant mode.\n */\nexport async function executeMove(target: MouseTarget, ctx: MouseContext): Promise<MoveResult> {\n const point = await resolveTargetPoint(target, ctx, 'move');\n\n if (ctx.speed === 'instant') {\n await ctx.page.mouse.move(point.x, point.y);\n ctx.setMousePosition(point);\n return { target: point };\n }\n\n await walkBezierTo(point, ctx);\n ctx.setMousePosition(point);\n return { target: point };\n}\n\n/**\n * Resolves an element-bound hover target, picks a Gaussian point inside its\n * box, walks the Bezier path to it, and returns the chosen point. Hover\n * never misclicks — hovers are about settling on an element, not committing\n * an action — so unlike click there's no near-miss beat here.\n *\n * `executeClick` resolves through `resolveTargetPointAndBox` instead (so it\n * can also accept raw `Point` targets); `executeDrag` and `executeMove`\n * reach the Bezier walk through `resolveTargetPoint` directly.\n */\nasync function moveToTarget(target: Locator | string, ctx: MouseContext): Promise<Point> {\n const box = await readBoxWithAutoScroll(target, ctx, 'hover');\n const targetPoint = pickClickPoint(box, ctx.rng, ctx.personality.mouse.clickSpread);\n await walkBezierTo(targetPoint, ctx);\n return targetPoint;\n}\n\n/** Walks a humanized Bezier path from the current mouse position to `to`. */\nasync function walkBezierTo(to: Point, ctx: MouseContext): Promise<void> {\n const startPoint = ctx.getMousePosition();\n const rawPath = bezierPath(startPoint, to, ctx.rng, {\n curvature: ctx.personality.mouse.curvature,\n });\n const path = humanizePath(rawPath, ctx.rng);\n const travelMs = computeTravelTime(path, ctx.personality, ctx.speed, ctx.rng);\n await walkMouseAlongPath(ctx.page, path, travelMs);\n}\n\n/**\n * Resolves a mouse target (selector, Locator, or raw Point) to absolute\n * coordinates. Shared by `executeDrag` (both endpoints) and `executeMove`.\n *\n * `action` is just used to make the error message meaningful when an element\n * lookup fails — \"Cannot drag: …\" vs \"Cannot move: …\" reads better than a\n * generic \"cannot resolve\" complaint.\n *\n * Raw `Point` targets pass through untouched — the caller chose explicit\n * coordinates, so we don't auto-scroll (which has no element to track).\n * Element targets go through the auto-scroll-aware path.\n */\nasync function resolveTargetPoint(\n target: MouseTarget,\n ctx: MouseContext,\n action: 'drag' | 'move',\n): Promise<Point> {\n if (isPoint(target)) return target;\n return resolveLocatorPoint(target, ctx, action);\n}\n\n/**\n * Same as {@link resolveTargetPoint} but also returns the bounding box\n * when the target is element-bound. Raw `Point` targets get `box: null` —\n * there's no element, just a coordinate. Used by `executeDrag` so the\n * misclick beat can pick a \"near-miss outside the box\" for element-bound\n * grabs and a \"near-miss around the point\" for raw-coordinate grabs.\n */\nasync function resolveTargetPointAndBox(\n target: MouseTarget,\n ctx: MouseContext,\n action: 'drag' | 'click',\n): Promise<{ point: Point; box: BoundingBox | null }> {\n if (isPoint(target)) return { point: target, box: null };\n const box = await readBoxWithAutoScroll(target, ctx, action);\n const point = pickClickPoint(box, ctx.rng, ctx.personality.mouse.clickSpread);\n return { point, box };\n}\n\n/**\n * Picks a click point inside the target's bounding box, auto-scrolling\n * first when the box isn't in the viewport. See {@link readBoxWithAutoScroll}\n * for the viewport / scroll rules. The picked point uses personality-driven\n * Gaussian spread inside the box; raw-box callers (like {@link executeHover}'s\n * instant mode) bypass this and center on the box directly.\n */\nasync function resolveLocatorPoint(\n target: Locator | string,\n ctx: MouseContext,\n action: 'click' | 'hover' | 'drag' | 'move',\n): Promise<Point> {\n const box = await readBoxWithAutoScroll(target, ctx, action);\n return pickClickPoint(box, ctx.rng, ctx.personality.mouse.clickSpread);\n}\n\n/**\n * Reads the target's bounding box, auto-scrolling first when the box is\n * outside the viewport. Returns the (post-scroll, if applicable) box —\n * never null. Throws with the action name baked into the message when the\n * element doesn't exist or vanishes mid-scroll.\n *\n * Why this exists: Playwright's `page.mouse.move/click` use viewport\n * coordinates, not document coordinates. For an element below the fold,\n * `locator.boundingBox()` returns a y > viewport height — dispatching a\n * mouse move to that point lands off-screen and the click silently misses.\n * Real users scroll to bring the element into view before clicking, so we\n * do the same: humanized scroll (`block: 'center'`) in regular speed modes,\n * `scrollIntoViewIfNeeded` snap in `'instant'`.\n *\n * The viewport check uses the box's geometric center: if the center sits\n * inside the visible viewport, the click will land somewhere visible even\n * with personality-driven Gaussian spread, so no scroll fires. This also\n * gracefully handles elements larger than the viewport — the center-in-view\n * rule prevents an impossible \"scroll until fully visible\" loop.\n *\n * Shared between {@link resolveLocatorPoint} (humanized paths, which then\n * Gaussian-pick a point inside the box) and {@link executeHover}'s\n * instant-mode path (which centers on the box without humanization).\n */\nasync function readBoxWithAutoScroll(\n target: Locator | string,\n ctx: MouseContext,\n action: 'click' | 'hover' | 'drag' | 'move',\n): Promise<BoundingBox> {\n const locator = typeof target === 'string' ? ctx.page.locator(target) : target;\n let box = await locator.boundingBox();\n if (!box) {\n throw new Error(\n `Cannot ${action}: element not found or has no bounding box (target: ${describeTarget(target)})`,\n );\n }\n\n // Playwright returns null from `viewportSize()` when no explicit viewport\n // is set (rare — requires omitting `viewport` from newContext options).\n // In that case we fall back to the pre-fix behavior; nothing better to do\n // without a known viewport size to compare against.\n const viewport = ctx.page.viewportSize();\n if (viewport && !isBoxCenterInViewport(box, viewport)) {\n if (ctx.speed === 'instant') {\n await locator.scrollIntoViewIfNeeded();\n } else {\n // Humanized scroll. `block: 'center'` lands the target in the middle\n // of the viewport, which is what real users do when they're about to\n // interact with something — they scroll until they can comfortably\n // see it, not until it just barely peeks past the edge. `'nearest'`\n // would feel robotic: minimum-scroll places the element right at the\n // viewport boundary, which no human reaches for.\n await executeScroll(locator, ctx, { block: 'center' });\n }\n box = await locator.boundingBox();\n if (!box) {\n throw new Error(\n `Cannot ${action}: element disappeared after scrolling into view (target: ${describeTarget(target)})`,\n );\n }\n }\n\n return box;\n}\n\n/**\n * True when the box's center sits inside the viewport. Center-based rather\n * than corner-based so elements that straddle a viewport edge but have\n * their click target visible don't trigger an unnecessary scroll.\n *\n * Trade-off: for elements larger than the viewport, the Gaussian click\n * point could land outside the visible area in the extreme tail of the\n * distribution. Acceptable because typical `clickSpread` values keep ±3σ\n * well inside any element bigger than the viewport.\n */\nfunction isBoxCenterInViewport(\n box: BoundingBox,\n viewport: { readonly width: number; readonly height: number },\n): boolean {\n const cx = box.x + box.width / 2;\n const cy = box.y + box.height / 2;\n return cx >= 0 && cx <= viewport.width && cy >= 0 && cy <= viewport.height;\n}\n\n/**\n * Reads the page's current vertical scroll position. Used in `executeDrag`\n * to detect auto-scroll that happened during endpoint resolution and\n * mirror it onto raw `Point` endpoints (preserving the drag's geometry).\n *\n * Defensive against test mocks that don't implement `page.evaluate`\n * (returns `0`, matching \"no scroll happened\"). Real Playwright `Page`\n * always has `evaluate`.\n */\nasync function readScrollY(page: Page): Promise<number> {\n if (typeof page.evaluate !== 'function') return 0;\n return page.evaluate(() => window.scrollY);\n}\n\n/**\n * Safety margin (in CSS pixels) between the predicted drag-curve bounds\n * and the viewport edge. Small enough that the pre-scroll stays close to\n * \"the minimum needed,\" large enough that micro-jitter or rounding doesn't\n * still push the curve past the edge.\n */\nconst CURVE_VIEWPORT_MARGIN = 20;\n\n/**\n * Computes how far to scroll the page (positive = down, negative = up) so\n * the Bezier curve a drag would walk from `from` to `to` fits entirely\n * inside the viewport. Returns `0` if no scroll is needed.\n *\n * The Bezier path (see {@link import('@humanjs/core').bezierPath}) places\n * two control points perpendicular-offset by up to `distance × curvature`\n * in either direction. The curve itself stays within that perpendicular\n * band, so a conservative worst-case bounding box is the from→to line\n * inflated by `distance × curvature` on each side.\n *\n * Scroll just enough to bring whichever side overflows the most into the\n * viewport, plus a small {@link CURVE_VIEWPORT_MARGIN} so the curve\n * doesn't graze the edge. We only handle vertical overflow — pages\n * almost always scroll vertically and the horizontal axis rarely has\n * room to gain headroom from.\n *\n * If both top and bottom overflow (the drag's worst-case bounding box is\n * taller than the viewport), pick the larger overflow and live with the\n * partial fix — there's no scroll position that fully contains a curve\n * bigger than the viewport.\n */\nfunction computeCurveScrollDelta(\n from: Point,\n to: Point,\n viewport: { readonly width: number; readonly height: number } | null,\n curvature: number,\n): number {\n if (!viewport) return 0;\n\n const distance = Math.hypot(to.x - from.x, to.y - from.y);\n const perpendicularExtent = distance * curvature;\n\n const minY = Math.min(from.y, to.y) - perpendicularExtent;\n const maxY = Math.max(from.y, to.y) + perpendicularExtent;\n\n const topOverflow = -minY + CURVE_VIEWPORT_MARGIN;\n const bottomOverflow = maxY + CURVE_VIEWPORT_MARGIN - viewport.height;\n\n // Positive return → scroll page DOWN (elements move UP in viewport).\n // Negative return → scroll page UP (elements move DOWN in viewport).\n if (bottomOverflow > 0 && bottomOverflow >= topOverflow) return bottomOverflow;\n if (topOverflow > 0) return -topOverflow;\n return 0;\n}\n\n/** Type guard for raw `Point` targets — distinguishes them from Locator/string. */\nfunction isPoint(target: MouseTarget): target is Point {\n return (\n typeof target === 'object' &&\n target !== null &&\n !('boundingBox' in target) &&\n typeof (target as Point).x === 'number' &&\n typeof (target as Point).y === 'number'\n );\n}\n\n/** Bounding box returned by Playwright's `Locator.boundingBox()`. */\ninterface BoundingBox {\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n}\n\n/** Range, in CSS pixels, that a misclick lands outside the target's bounding box. */\nconst MISCLICK_OFFSET_MIN = 5;\nconst MISCLICK_OFFSET_MAX = 15;\n\n/**\n * Performs the \"near-miss\" beat shared by `click` and both endpoints of\n * `drag`: with probability `personality.mouse.misclickProbability`, walks\n * the cursor to a point just outside (or near, for raw-Point targets) the\n * commit point, dwells briefly, then returns. The caller continues from\n * wherever the cursor lands — usually with its own walk to the real point.\n *\n * No click / mousedown / mouseup is dispatched at the off-target\n * coordinates. The misclick is visible cursor motion only.\n *\n * Two flavors:\n * - `box` non-null: pick a point just outside one of the four edges.\n * Used for element-bound targets where \"outside the box\" has obvious\n * geometry.\n * - `box` null: pick a point 5–15 px from the target Point in a random\n * direction. Used for raw-Point targets (canvas/SVG drags), where there\n * is no box but the action still commits at a specific coordinate.\n *\n * Skipped (no beat) in three cases:\n * 1. The probability roll comes up under the threshold.\n * 2. The cursor is already on the target — there's no approach to miss\n * when you're already hovering the element. A real user doesn't aim\n * away from a button they're already on. The probability roll still\n * consumes one RNG value in this case (kept *before* the cursor-on-\n * target check) so seeded runs stay deterministic regardless of\n * where the cursor happened to start.\n * 3. The candidate near-miss would have to be clamped back onto the\n * target (target pinned at the viewport edge). Better to commit\n * cleanly than fake a degenerate \"miss\" that lands on the target.\n */\nasync function maybeMisclickBeat(\n ctx: MouseContext,\n box: BoundingBox | null,\n targetPoint: Point,\n): Promise<void> {\n if (!ctx.rng.chance(ctx.personality.mouse.misclickProbability)) return;\n\n // Skip when cursor is already on/near the target — no approach to miss.\n // Important: this check runs AFTER the chance() roll above so the RNG\n // sequence stays identical regardless of where the cursor happened to\n // start, preserving seed-level determinism across runs.\n if (cursorAlreadyOnTarget(ctx.getMousePosition(), box, targetPoint)) return;\n\n const viewport = ctx.page.viewportSize();\n const misclickPoint = box\n ? pickMisclickOutsideBox(box, ctx.rng, viewport)\n : pickMisclickAroundPoint(targetPoint, ctx.rng, viewport);\n\n if (misclickPoint === null) return;\n\n await walkBezierTo(misclickPoint, ctx);\n ctx.setMousePosition(misclickPoint);\n\n const realizeMs = computeDwellTime(\n ctx.personality.dwell.preClickMs,\n ctx.personality.dwell.preClickJitter,\n ctx.personality,\n ctx.speed,\n ctx.rng,\n );\n if (realizeMs > 0) await sleep(realizeMs);\n}\n\n/**\n * True when the cursor is already on (or close enough to) the target.\n * Used by {@link maybeMisclickBeat} to skip the near-miss beat when\n * there's no approach to overshoot.\n *\n * For element-bound targets (`box` non-null): inside the bounding box.\n * For raw-Point targets (`box` null): within `MISCLICK_OFFSET_MIN` px\n * of the target coordinate — at that distance any \"outside\" near-miss\n * would be barely-outside, defeating the visual signal anyway.\n */\nfunction cursorAlreadyOnTarget(\n current: Point,\n box: BoundingBox | null,\n targetPoint: Point,\n): boolean {\n if (box) {\n return (\n current.x >= box.x &&\n current.x <= box.x + box.width &&\n current.y >= box.y &&\n current.y <= box.y + box.height\n );\n }\n const dx = current.x - targetPoint.x;\n const dy = current.y - targetPoint.y;\n return Math.hypot(dx, dy) < MISCLICK_OFFSET_MIN;\n}\n\n/**\n * Picks a point just outside the target's bounding box — the \"near-miss\"\n * coordinates the cursor visits before correcting to the real click point.\n *\n * Process:\n *\n * 1. Pick one of the four edges to miss toward (top/right/bottom/left).\n * 2. Pick an outward offset (5–15 px) — far enough to read as a miss,\n * close enough to read as a correctable wobble.\n * 3. Pick a position along that edge (biased toward the middle 60%, so we\n * don't miss past a corner where the wobble reads as wild).\n * 4. Clamp to the viewport, since the cursor can't legally land off-screen.\n * 5. If clamping pulled the point back inside the target's box (target sits\n * at the viewport edge), return `null` — the caller skips the misclick\n * this round rather than produce a \"near-miss\" that lands on the target.\n */\nfunction pickMisclickOutsideBox(\n box: BoundingBox,\n rng: Rng,\n viewport: { readonly width: number; readonly height: number } | null,\n): Point | null {\n const edge = rng.nextInt(0, 4); // 0=top, 1=right, 2=bottom, 3=left\n const offset = rng.nextFloat(MISCLICK_OFFSET_MIN, MISCLICK_OFFSET_MAX);\n const along = rng.nextFloat(0.2, 0.8);\n\n let x: number;\n let y: number;\n if (edge === 0) {\n x = box.x + box.width * along;\n y = box.y - offset;\n } else if (edge === 1) {\n x = box.x + box.width + offset;\n y = box.y + box.height * along;\n } else if (edge === 2) {\n x = box.x + box.width * along;\n y = box.y + box.height + offset;\n } else {\n x = box.x - offset;\n y = box.y + box.height * along;\n }\n\n if (viewport) {\n x = clamp(x, 0, viewport.width - 1);\n y = clamp(y, 0, viewport.height - 1);\n }\n\n // Clamping pulled the point back inside the box → the misclick is\n // impossible at the viewport edge; skip it rather than fake one.\n const insideBox = x >= box.x && x <= box.x + box.width && y >= box.y && y <= box.y + box.height;\n if (insideBox) return null;\n\n return { x, y };\n}\n\n/**\n * Picks a point near (but not on) a raw target coordinate — the no-box\n * analog of {@link pickMisclickOutsideBox}, used for `drag`'s raw-`Point`\n * `from` endpoint (canvas / SVG / pixel-precise targets).\n *\n * Process:\n * 1. Pick a random direction (angle in radians).\n * 2. Pick a distance (5–15 px), same range as the box case.\n * 3. Clamp to the viewport.\n * 4. If clamping pulled the candidate exactly onto the target (target\n * pinned to the viewport corner with no usable direction), return\n * `null` so the caller skips the misclick rather than fake one.\n *\n * The target is treated as a zero-sized box: any non-zero offset puts the\n * misclick \"outside,\" which is the right semantic for a pixel-precise\n * action committing at the exact coordinate.\n */\nfunction pickMisclickAroundPoint(\n target: Point,\n rng: Rng,\n viewport: { readonly width: number; readonly height: number } | null,\n): Point | null {\n const angle = rng.nextFloat(0, Math.PI * 2);\n const distance = rng.nextFloat(MISCLICK_OFFSET_MIN, MISCLICK_OFFSET_MAX);\n\n let x = target.x + Math.cos(angle) * distance;\n let y = target.y + Math.sin(angle) * distance;\n\n if (viewport) {\n x = clamp(x, 0, viewport.width - 1);\n y = clamp(y, 0, viewport.height - 1);\n }\n\n if (x === target.x && y === target.y) return null;\n\n return { x, y };\n}\n\n/**\n * Picks a click point inside the bounding box. Gaussian-centered so the\n * majority of clicks land near the visual center but with natural spread.\n * Clamped to never fall outside the element.\n */\nfunction pickClickPoint(box: BoundingBox, rng: Rng, clickSpread: number): Point {\n const cx = box.x + box.width / 2;\n const cy = box.y + box.height / 2;\n // Standard deviation scales with each dimension separately, so wide\n // elements scatter horizontally and tall elements scatter vertically.\n // The clickSpread fraction comes from the personality — precise users\n // cluster near center, distracted users scatter across the target.\n const sigmaX = box.width * clickSpread;\n const sigmaY = box.height * clickSpread;\n const x = clamp(cx + rng.nextGaussian(0, sigmaX), box.x, box.x + box.width);\n const y = clamp(cy + rng.nextGaussian(0, sigmaY), box.y, box.y + box.height);\n return { x, y };\n}\n\n/**\n * Travel time in ms for the given path.\n *\n * base = (totalDistance / 1000) * Personality.mouse.travelTimeMs\n * jitter = base * Personality.mouse.travelTimeJitter * rand[-1, 1]\n * total = (base + jitter) * Personality.speed * speedModeFactor\n */\nfunction computeTravelTime(\n path: readonly Point[],\n personality: Personality,\n speed: Speed,\n rng: Rng,\n): number {\n let distance = 0;\n for (let i = 1; i < path.length; i++) {\n const prev = path[i - 1];\n const curr = path[i];\n if (!prev || !curr) continue;\n distance += Math.hypot(curr.x - prev.x, curr.y - prev.y);\n }\n\n const baseTime = (distance / 1000) * personality.mouse.travelTimeMs;\n const jitterMag = baseTime * personality.mouse.travelTimeJitter;\n const jitter = rng.nextFloat(-jitterMag, jitterMag);\n const total = (baseTime + jitter) * personality.speed * speedModeFactor(speed);\n return Math.max(0, total);\n}\n\nfunction describeTarget(target: MouseTarget): string {\n if (isPoint(target)) return `point(${target.x}, ${target.y})`;\n return typeof target === 'string' ? target : (target.toString?.() ?? 'locator');\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return value < min ? min : value > max ? max : value;\n}\n","import type { Locator } from 'playwright';\nimport { executeClick, executeHover, type MouseContext } from '../mouse';\n\n/** Values accepted by {@link executeSelectOption} — the Playwright `selectOption` shape. */\nexport type SelectOptionValues = Parameters<Locator['selectOption']>[0];\n/** Files accepted by {@link executeUpload} — the Playwright `setInputFiles` shape. */\nexport type UploadFiles = Parameters<Locator['setInputFiles']>[0];\n\n/** Form targets are element-bound: a selector or a pre-built `Locator`. */\nexport type FormTarget = Locator | string;\n\nfunction toLocator(target: FormTarget, ctx: MouseContext): Locator {\n return typeof target === 'string' ? ctx.page.locator(target) : target;\n}\n\nfunction describe(target: FormTarget): string {\n return typeof target === 'string' ? target : (target.toString?.() ?? 'locator');\n}\n\n/**\n * Reads a checkable element's state, returning `null` when the element isn't\n * directly checkable (e.g. the target is a wrapping `<label>` or a styled\n * control). Used by {@link executeSetChecked} to guard idempotency and verify\n * the toggle only when the element actually reports a checked state.\n */\nasync function readChecked(locator: Locator): Promise<boolean | null> {\n try {\n return await locator.isChecked();\n } catch {\n return null;\n }\n}\n\n/**\n * Humanized checkbox/radio toggle. Moves the cursor to the control along a\n * Bezier path and clicks it (with the same hover dwell and occasional\n * near-miss as {@link executeClick}) — but only when a click is actually\n * needed:\n *\n * - If the element already reports the desired state, no click fires. A\n * real user doesn't re-click a box that's already in the state they want.\n * - After toggling, the new state is verified. If it didn't change (e.g.\n * trying to `uncheck` a radio, which can't be unchecked by clicking), a\n * clear error is thrown rather than silently passing.\n *\n * The idempotency guard and verification are skipped when the element isn't\n * directly checkable (a `<label>` or `role`-based control where `isChecked()`\n * doesn't apply) — there the humanized click still toggles the associated\n * input, we just can't read/verify the state from this node.\n *\n * In `speed: 'instant'`, delegates to Playwright's native\n * `locator.check()` / `locator.uncheck()` (idempotent + actionability-checked).\n */\nexport async function executeSetChecked(\n target: FormTarget,\n ctx: MouseContext,\n checked: boolean,\n): Promise<void> {\n const locator = toLocator(target, ctx);\n\n if (ctx.speed === 'instant') {\n if (checked) await locator.check();\n else await locator.uncheck();\n return;\n }\n\n const before = await readChecked(locator);\n // Already in the desired state — nothing to do (only short-circuit when the\n // state is actually readable; `null` means \"not directly checkable\", fall\n // through to a humanized click and let it toggle the associated control).\n if (before === checked) return;\n\n await executeClick(locator, ctx);\n\n const after = await readChecked(locator);\n if (after !== null && after !== checked) {\n throw new Error(\n `Cannot ${checked ? 'check' : 'uncheck'}: element did not reach the ${\n checked ? 'checked' : 'unchecked'\n } state after clicking (target: ${describe(target)}). Radios can't be unchecked by clicking — select a different option instead.`,\n );\n }\n}\n\n/**\n * Humanized native `<select>` choice. Moves the cursor to the dropdown along a\n * Bezier path and settles on it (the {@link executeHover} dwell), then sets the\n * value via Playwright's `selectOption`.\n *\n * Native selects open an OS-level menu Playwright can't drive visually, so the\n * humanized part is the *approach* — the value itself is set programmatically\n * (firing `input`/`change` events) the same way Playwright does. For custom,\n * DOM-rendered dropdowns, drive them with `click` + `click` on the rendered\n * options instead.\n *\n * In `speed: 'instant'`, sets the value with no cursor motion.\n *\n * Returns the list of option values that ended up selected.\n */\nexport async function executeSelectOption(\n target: FormTarget,\n values: SelectOptionValues,\n ctx: MouseContext,\n): Promise<string[]> {\n const locator = toLocator(target, ctx);\n if (ctx.speed !== 'instant') {\n try {\n await executeHover(locator, ctx);\n } catch {\n // No visible control to approach (zero-box / not yet rendered). Don't\n // surface a \"Cannot hover\" error for a selectOption call — fall through\n // and let `selectOption` raise the authoritative error (or succeed via\n // its own actionability) so the failure is attributed correctly.\n }\n }\n return locator.selectOption(values);\n}\n\n/**\n * Humanized file upload. Moves the cursor to the upload control along a Bezier\n * path (so the motion is visible in recordings / to the overlay), then sets the\n * files via Playwright's `setInputFiles`.\n *\n * The OS file picker can't be driven by automation, so — unlike a real click —\n * this never *clicks* the control (a click on `<input type=\"file\">` would open\n * the native dialog and hang). Files are attached directly, which is how\n * Playwright models uploads. `target` should be the `<input type=\"file\">`\n * itself; for the common \"hidden input behind a styled button\" pattern there's\n * no visible control to approach, so the cursor motion is skipped and the files\n * are attached directly.\n *\n * In `speed: 'instant'`, attaches the files with no cursor motion.\n */\nexport async function executeUpload(\n target: FormTarget,\n files: UploadFiles,\n ctx: MouseContext,\n): Promise<void> {\n const locator = toLocator(target, ctx);\n if (ctx.speed !== 'instant') {\n try {\n await executeHover(locator, ctx);\n } catch {\n // Hidden file input (no bounding box) — common when a styled button\n // proxies a `display:none` input. No visible control to approach;\n // attach the files directly.\n }\n }\n await locator.setInputFiles(files);\n}\n","import { type Personality, planTypeKeystrokes, type Rng } from '@humanjs/core';\nimport type { Locator, Page } from 'playwright';\nimport type { Speed } from '../index';\nimport { computeDwellTime, sleep, speedModeFactor } from '../internal/timing';\n\n/** Runtime dependencies for a humanized keyboard action. */\nexport interface KeyboardContext {\n readonly page: Page;\n readonly personality: Personality;\n readonly rng: Rng;\n readonly speed: Speed;\n}\n\n/** Result of a typing action, returned to the caller for observability. */\nexport interface TypeResult {\n /** Number of characters in the input string. */\n readonly characters: number;\n /** Number of typos injected (with or without correction). */\n readonly typos: number;\n /** Number of typo corrections via Backspace. */\n readonly corrections: number;\n}\n\n/**\n * Executes a humanized typing pass over `value` on `target`.\n *\n * Planning (which keys to press, with what delays, in what order) is delegated\n * to `@humanjs/core`'s `planTypeKeystrokes`. This module is the thin Playwright\n * dispatcher: it focuses the target, walks the plan, and chooses the best\n * Playwright API per key:\n *\n * - Named keys (`Enter`, `Backspace`, `Tab`) and ASCII chars: `keyboard.press`\n * — fires keydown/press/up, so handlers (autocomplete, validation) run.\n * - Non-ASCII characters: `keyboard.insertText` — fires `input` events but\n * not keyboard events, since `keyboard.press` is keyboard-layout-aware\n * and can't reliably synthesize characters like `é` or `🎉` on every layout.\n *\n * In `speed: 'instant'`, the whole humanized loop is bypassed in favor of\n * `locator.pressSequentially(value, { delay: 0 })` — events still fire,\n * humanization is skipped.\n */\nexport async function executeType(\n target: Locator | string,\n value: string,\n ctx: KeyboardContext,\n): Promise<TypeResult> {\n const locator = typeof target === 'string' ? ctx.page.locator(target) : target;\n\n if (value.length === 0) {\n return { characters: 0, typos: 0, corrections: 0 };\n }\n\n if (ctx.speed === 'instant') {\n await locator.pressSequentially(value, { delay: 0 });\n return { characters: value.length, typos: 0, corrections: 0 };\n }\n\n await locator.focus();\n\n const plan = planTypeKeystrokes(value, ctx.personality.typing, ctx.rng, {\n personalitySpeed: ctx.personality.speed,\n speedFactor: speedModeFactor(ctx.speed),\n });\n\n let typos = 0;\n let corrections = 0;\n\n for (const step of plan) {\n if (step.delayBeforeMs > 0) await sleep(step.delayBeforeMs);\n await dispatchKey(ctx.page, step.key);\n if (step.isTypo) typos++;\n if (step.isCorrection) corrections++;\n }\n\n return { characters: value.length, typos, corrections };\n}\n\n/**\n * Dispatches a single planned key. Multi-char strings are treated as named\n * keys (`Enter`, `Backspace`). Single ASCII chars use the layout-aware\n * `keyboard.press`. Single non-ASCII chars fall back to `insertText` so the\n * adapter works on any keyboard layout, at the cost of skipping per-key events.\n */\nasync function dispatchKey(page: Page, key: string): Promise<void> {\n if (key.length > 1 || key.charCodeAt(0) < 128) {\n await page.keyboard.press(key);\n } else {\n await page.keyboard.insertText(key);\n }\n}\n\n/** Result of a paste action. */\nexport interface PasteResult {\n /** Length of the pasted value. */\n readonly characters: number;\n}\n\n/**\n * Inserts `value` into the target without per-character timing — the Cmd-V\n * semantic. The implicit click before insertion follows the same pattern as\n * `executeType`: a real user clicks the field, then pastes; they don't\n * teleport-focus a field. The click is driven by the caller (`human.paste`\n * in the factory) so this executor is keyboard-only.\n *\n * Uses `page.keyboard.insertText` rather than synthesizing a paste event —\n * the goal is \"the value lands in the field instantly,\" not \"fire the page's\n * paste handler.\" If a user needs paste-event semantics, they can call\n * `human.press('Mod+V')` after setting clipboard contents themselves.\n *\n * In `speed: 'instant'`, behaves identically — paste is already instant by\n * nature; there's nothing to humanize about the timing.\n */\nexport async function executePaste(\n target: Locator | string,\n value: string,\n ctx: KeyboardContext,\n): Promise<PasteResult> {\n if (value.length === 0) return { characters: 0 };\n const locator = typeof target === 'string' ? ctx.page.locator(target) : target;\n await locator.focus();\n await ctx.page.keyboard.insertText(value);\n return { characters: value.length };\n}\n\n/**\n * Clears a text field the way a person does: select-all, a beat, then delete —\n * a real keyboard gesture, not a programmatic value reset. The implicit click\n * that focuses the field is driven by the caller (`human.clear` in the\n * factory), same pattern as `executeType` / `executePaste`, so this executor\n * is keyboard-only.\n *\n * The select-all chord is platform-aware (`Meta+A` on macOS, `Control+A`\n * elsewhere) via the same resolver `human.press` uses, then `Delete` clears the\n * selection. Works for inputs, textareas, and contenteditable.\n *\n * In `speed: 'instant'`, delegates to Playwright's native `locator.clear()`\n * (focus + actionability + value reset) — no visible gesture, same as the rest\n * of instant mode.\n */\nexport async function executeClear(target: Locator | string, ctx: KeyboardContext): Promise<void> {\n const locator = typeof target === 'string' ? ctx.page.locator(target) : target;\n\n if (ctx.speed === 'instant') {\n await locator.clear();\n return;\n }\n\n await locator.focus();\n // Select all, then delete the selection — the human \"wipe the field\" gesture.\n await ctx.page.keyboard.press(resolveChord('Mod+A'));\n // A short beat so the selection visibly registers before it's deleted,\n // scaled by personality + speed like the other humanized dwells.\n const beatMs = computeDwellTime(\n ctx.personality.dwell.preClickMs,\n ctx.personality.dwell.preClickJitter,\n ctx.personality,\n ctx.speed,\n ctx.rng,\n );\n if (beatMs > 0) await sleep(beatMs);\n await ctx.page.keyboard.press('Delete');\n}\n\n/**\n * Modifier tokens accepted in a `human.press()` chord. `Mod` and `CmdOrCtrl` /\n * `CommandOrControl` are the magic auto-mapping tokens (Meta on Mac,\n * Control elsewhere). The rest are literal — they always resolve to the\n * keycode they name, on every platform.\n *\n * Canonical-case names are listed here for IntelliSense; the runtime\n * parser is case-insensitive, so `'cmd+s'` and `'CMD+S'` work too — they\n * just won't autocomplete.\n */\nexport type KeyModifier =\n | 'Mod'\n | 'CmdOrCtrl'\n | 'CommandOrControl'\n | 'Cmd'\n | 'Command'\n | 'Meta'\n | 'Win'\n | 'Super'\n | 'Ctrl'\n | 'Control'\n | 'Alt'\n | 'Option'\n | 'Opt'\n | 'Shift';\n\n/**\n * The canonical key names that autocomplete in a `KeyOrChord`. Mirrors\n * Playwright's accepted key vocabulary, plus a few common synonyms.\n * CamelCase names (`ArrowDown`, `PageUp`) are listed in their canonical\n * form — `normalizeKey` preserves case from the input, so what you type is\n * what gets dispatched.\n *\n * Not exhaustive: every other Playwright key (less-common Numpad keys,\n * `BracketLeft`, locale-specific keys, etc.) is outside the typed union\n * and needs a cast at the call site (`'BracketLeft' as KeyOrChord`). The\n * runtime parser handles them — the type just doesn't enumerate them,\n * because adding a `(string & {})` escape hatch would collapse TypeScript's\n * template-literal IntelliSense for the chord autocompletes.\n */\nexport type KeyName =\n // Letters\n | 'A'\n | 'B'\n | 'C'\n | 'D'\n | 'E'\n | 'F'\n | 'G'\n | 'H'\n | 'I'\n | 'J'\n | 'K'\n | 'L'\n | 'M'\n | 'N'\n | 'O'\n | 'P'\n | 'Q'\n | 'R'\n | 'S'\n | 'T'\n | 'U'\n | 'V'\n | 'W'\n | 'X'\n | 'Y'\n | 'Z'\n // Digits\n | '0'\n | '1'\n | '2'\n | '3'\n | '4'\n | '5'\n | '6'\n | '7'\n | '8'\n | '9'\n // Function keys\n | 'F1'\n | 'F2'\n | 'F3'\n | 'F4'\n | 'F5'\n | 'F6'\n | 'F7'\n | 'F8'\n | 'F9'\n | 'F10'\n | 'F11'\n | 'F12'\n // Navigation\n | 'ArrowUp'\n | 'ArrowDown'\n | 'ArrowLeft'\n | 'ArrowRight'\n | 'PageUp'\n | 'PageDown'\n | 'Home'\n | 'End'\n // Editing & control\n | 'Enter'\n | 'Tab'\n | 'Escape'\n | 'Space'\n | 'Backspace'\n | 'Delete'\n | 'Insert'\n // Lock & system keys\n | 'CapsLock'\n | 'NumLock'\n | 'ScrollLock'\n | 'PrintScreen'\n | 'Pause';\n\n/**\n * Strings accepted by `human.press(key)`:\n *\n * - A bare known key: `'Enter'`, `'F4'`, `'ArrowDown'`, `'S'`, …\n * - One known modifier + a known key: `'Mod+S'`, `'Shift+ArrowDown'`, …\n * - Two known modifiers + a known key: `'Mod+Shift+P'`, `'Ctrl+Alt+Tab'`, …\n *\n * Every member of the union is a fully-enumerated literal, which is what\n * makes IDE autocomplete work — type `'Shift+'` and you get every\n * `Shift+<key>` combination as a completion. Adding a `(string & {})`\n * escape hatch anywhere would collapse that down to a single wide\n * template member, killing the completion list.\n *\n * Modifier typos (`'Mosd+S'`) and uncommon-key typos (`'Mod+BraketLeft'`)\n * are both TS errors at the call site — the closed sets on both sides\n * give you compile-time protection that Playwright's plain `string` key\n * type can't.\n *\n * **Escape hatch for uncommon keys.** Less-common Playwright keys\n * (`'BracketLeft'`, `'NumpadAdd'`, locale-specific keys, …) and 3+\n * modifier chords (`'Ctrl+Shift+Alt+K'`) aren't in the union and need a\n * cast at the call site:\n *\n * ```ts\n * await human.press('Mod+BracketLeft' as KeyOrChord);\n * await human.press('Ctrl+Shift+Alt+K' as KeyOrChord);\n * ```\n *\n * The runtime parser handles these fine — the cast just acknowledges\n * \"I'm using a key outside the autocomplete vocabulary.\" If you find\n * yourself casting often for a specific key, propose adding it to\n * `KeyName` in a PR.\n *\n * Lowercase modifiers (`'mod+s'`) also don't typecheck even though the\n * runtime accepts them — TS-strict steers users toward the canonical\n * casing, which keeps key strings consistent across a codebase.\n */\nexport type KeyOrChord =\n | KeyName\n | `${KeyModifier}+${KeyName}`\n | `${KeyModifier}+${KeyModifier}+${KeyName}`;\n\n/** Result of a `press` action. */\nexport interface PressResult {\n /** The exact chord that was dispatched (after Mod-resolution). */\n readonly dispatched: string;\n}\n\n/**\n * Dispatches a single key or keyboard chord — `'Tab'`, `'Enter'`, `'Mod+S'`,\n * `'Cmd+Shift+P'`, `'Ctrl+C'`, …\n *\n * Parses the input into zero-or-more modifiers + a final key, normalizes\n * aliases, then dispatches via `page.keyboard.press()` which uses\n * Playwright's standard `Modifier+Key` syntax (or just `Key` for bare keys).\n *\n * Modifier rules:\n *\n * - `Mod` / `CmdOrCtrl` / `CommandOrControl` → magic: becomes `Meta` on\n * macOS, `Control` elsewhere. The right token for cross-platform app\n * shortcuts. All three are aliases; `Mod` is shortest, the others come\n * from the Electron / Mousetrap convention.\n * - `Cmd` / `Command` / `Meta` / `Win` / `Super` → literal `Meta` keycode.\n * Same physical key on every OS (Command on Mac, Windows key on Windows,\n * Super on Linux). Note: this does NOT auto-translate to Control.\n * - `Ctrl` / `Control` → literal Control. Stays Control on every OS, so\n * Mac-specific things like terminal Ctrl+C still work.\n * - `Alt` / `Option` / `Opt` → literal Alt.\n * - `Shift` → literal Shift.\n *\n * Modifier names and key names are case-insensitive.\n *\n * @example\n * ```ts\n * await human.press('Tab'); // bare key\n * await human.press('Enter'); // bare key\n * await human.press('Mod+S'); // cross-platform save\n * await human.press('Cmd+Shift+P'); // literal Meta+Shift+P\n * await human.press('Control+C'); // literal Ctrl+C\n * ```\n */\nexport async function executePress(key: KeyOrChord, ctx: KeyboardContext): Promise<PressResult> {\n const dispatched = resolveChord(key);\n await ctx.page.keyboard.press(dispatched);\n return { dispatched };\n}\n\n/**\n * Parses the user-facing key string and resolves it to Playwright's\n * canonical `Modifier+...+Key` form (or just `Key` for bare keys), with\n * `Mod` mapped per platform and aliases normalized.\n *\n * Exported for the test suite — not part of the public API.\n */\nexport function resolveChord(key: KeyOrChord): string {\n // Narrow to plain string for the parser — `KeyOrChord` is a wide template\n // literal union and TS can't always infer the callbacks' parameter type\n // from `.split()` when the input is the full union shape.\n const parts = (key as string)\n .split('+')\n .map((p) => p.trim())\n .filter((p) => p.length > 0);\n if (parts.length === 0) {\n throw new Error(`Invalid key: ${JSON.stringify(key)} — empty or only separators`);\n }\n\n const keyToken = parts[parts.length - 1];\n if (keyToken === undefined) {\n throw new Error(`Invalid key: ${JSON.stringify(key)} — missing key`);\n }\n const modifierTokens = parts.slice(0, -1);\n\n const modifiers: string[] = [];\n for (const token of modifierTokens) {\n const resolved = resolveModifier(token);\n if (resolved === null) {\n throw new Error(\n `Invalid key modifier: ${JSON.stringify(token)} in ${JSON.stringify(key)}. ` +\n `Use one of: Mod/CmdOrCtrl/CommandOrControl, Cmd/Command/Meta/Win/Super, Ctrl/Control, Alt/Option/Opt, Shift.`,\n );\n }\n modifiers.push(resolved);\n }\n\n return [...modifiers, normalizeKey(keyToken)].join('+');\n}\n\n/**\n * Normalizes a modifier alias to Playwright's canonical name. Returns `null`\n * if the input isn't a known modifier — the caller then throws with a useful\n * message instead of letting Playwright fail with a cryptic error downstream.\n */\nfunction resolveModifier(token: string): string | null {\n const lower = token.toLowerCase();\n switch (lower) {\n case 'mod':\n case 'cmdorctrl':\n case 'commandorcontrol':\n return isMac() ? 'Meta' : 'Control';\n case 'cmd':\n case 'command':\n case 'meta':\n case 'win':\n case 'super':\n return 'Meta';\n case 'ctrl':\n case 'control':\n return 'Control';\n case 'alt':\n case 'option':\n case 'opt':\n return 'Alt';\n case 'shift':\n return 'Shift';\n default:\n return null;\n }\n}\n\n/**\n * Normalizes the final key in a chord. Single-letter keys are upper-cased\n * (Playwright expects `'S'`, not `'s'`, for the `S` key in chord form).\n * Multi-character keys get their first letter upper-cased but **keep the\n * rest of their case** — Playwright's canonical key names are CamelCase\n * (`ArrowDown`, `PageUp`, `KeyA`, `BracketLeft`, `NumpadAdd`), and\n * lowercasing the tail would mangle them into `Arrowdown` / `Pageup` /\n * etc., which Playwright doesn't recognize.\n *\n * Single-word keys (`Tab`, `Enter`, `Escape`) still title-case correctly\n * with this rule: their tail is already lowercase, so preserving it is\n * the same as lowercasing it.\n */\nfunction normalizeKey(key: string): string {\n if (key.length === 1) return key.toUpperCase();\n return key.charAt(0).toUpperCase() + key.slice(1);\n}\n\n/**\n * Platform detection for the `Mod` token. Node-only check; runs at chord-\n * resolution time (not at module load) so tests that need to simulate a\n * different platform can stub `process.platform` first.\n */\nfunction isMac(): boolean {\n return process.platform === 'darwin';\n}\n","import {\n computeReadingDwellMs,\n countWords,\n type Personality,\n type Point,\n planReadingScan,\n type ReadKind,\n type Rng,\n} from '@humanjs/core';\nimport type { Locator, Page } from 'playwright';\nimport type { Speed } from '../index';\nimport { walkMouseAlongPath } from '../internal/mouse-walk';\nimport { sleep, speedModeFactor } from '../internal/timing';\n\n/** Runtime dependencies for a humanized reading dwell. */\nexport interface ReadingContext {\n readonly page: Page;\n readonly personality: Personality;\n readonly rng: Rng;\n readonly speed: Speed;\n /**\n * Last known cursor position. Used as the starting point for an eye-scan\n * when `withMotion: true`. Required even when motion is off — the read\n * adapter needs to know where the cursor *would* start if motion is later\n * enabled mid-session.\n */\n readonly getMousePosition: () => Point;\n /** Updates the tracked cursor position after a scan completes. */\n readonly setMousePosition: (point: Point) => void;\n}\n\n/**\n * What to read:\n * - `string`: a Playwright-compatible selector (matches `click()` / `type()`).\n * The element's `innerText` is resolved and word-counted.\n * - `Locator`: same, but you already have a Locator handle.\n * - `{ text }`: literal text (you have the string in hand, no selector).\n * - `{ words }`: pre-counted (bypass extraction entirely).\n */\nexport type ReadTarget = string | Locator | { readonly text: string } | { readonly words: number };\n\nexport interface ReadOptions {\n /**\n * Reading mode. Built-in multipliers on top of `personality.reading.wpm`:\n * - `'prose'`: 1.0× (default for non-code targets)\n * - `'code'`: 0.4× (default when target is a `<pre>` or `<code>` element)\n * - `'scan'`: 1.8× (skim mode, must be explicit)\n *\n * **Smart defaults:** when `kind` is omitted AND the target is a Locator/\n * selector, the adapter inspects the resolved element's tag — `<pre>` and\n * `<code>` auto-detect as `'code'`; everything else as `'prose'`. An\n * explicit `kind` always wins over auto-detection.\n */\n readonly kind?: ReadKind;\n /** Override the effective WPM multiplier directly. Wins over `kind`. */\n readonly wpmMultiplier?: number;\n /**\n * For selector/Locator targets: scroll the element into the viewport\n * before the dwell. A user can't read what isn't on screen. Defaults to\n * `false` — in most flows the caller has already scrolled there.\n */\n readonly scrollIntoView?: boolean;\n /**\n * For selector/Locator targets: trace a humanized cursor path through the\n * target's bounding box while the dwell elapses, like an eye tracking\n * lines of text. **Defaults to `true`** — \"reading\" implies looking, and\n * looking implies motion. Pass `false` to skip motion when you only\n * care about the temporal pattern (typical AI-agent use case where\n * the cursor position is irrelevant).\n *\n * The scan path is generated by `planReadingScan` from `@humanjs/core`\n * (same deterministic-by-seed contract as the rest of the library) and\n * walked over the computed dwell duration, so motion finishes exactly as\n * the read does. The cursor's tracked position is updated to the scan's\n * endpoint so the next click starts from where the eye landed.\n *\n * Ignored when the target is `{ text }` or `{ words }` (no bounding box).\n */\n readonly withMotion?: boolean;\n}\n\n/** Outcome of a read, returned to the caller for observability. */\nexport interface ReadResult {\n /** Number of words counted (after whitespace splitting / from caller's `{ words }`). */\n readonly words: number;\n /** Sleep duration in ms. Zero in `speed: 'instant'` or for zero-word inputs. */\n readonly durationMs: number;\n /** Final reading kind used (after auto-detection + explicit-override resolution). */\n readonly kind: ReadKind;\n}\n\n/**\n * Executes a humanized reading dwell.\n *\n * Flow:\n * 1. Resolve target → words + (optional) Locator\n * 2. Optionally scroll into view\n * 3. Resolve `kind` (explicit → auto-detected from tag → `'prose'`)\n * 4. Compute dwell via `computeReadingDwellMs` (jittered + scaled)\n * 5. Walk a humanized eye-scan path across the bounding box (default on),\n * pacing the steps so motion ends exactly as the dwell does\n */\nexport async function executeRead(\n target: ReadTarget,\n ctx: ReadingContext,\n options: ReadOptions = {},\n): Promise<ReadResult> {\n // ── Resolve target → words (+ optional Locator for tag detection / scroll) ─\n let words = 0;\n let locator: Locator | undefined;\n\n if (typeof target === 'string') {\n locator = ctx.page.locator(target);\n } else if ('words' in target) {\n words = target.words;\n } else if ('text' in target) {\n words = countWords(target.text);\n } else {\n // Only Locator remains in the union after the discriminator checks above.\n locator = target;\n }\n\n let autoDetectedKind: ReadKind | undefined;\n\n if (locator) {\n if (options.scrollIntoView) {\n await locator.scrollIntoViewIfNeeded();\n }\n const text = await locator.innerText().catch(() => '');\n words = countWords(text);\n\n // Auto-detect kind from tag only when caller didn't specify one.\n if (options.kind === undefined) {\n autoDetectedKind = await detectKindFromTag(locator);\n }\n }\n\n const kind = options.kind ?? autoDetectedKind ?? 'prose';\n\n const durationMs = computeReadingDwellMs(words, ctx.personality.reading, ctx.rng, {\n kind,\n wpmMultiplier: options.wpmMultiplier,\n personalitySpeed: ctx.personality.speed,\n speedFactor: speedModeFactor(ctx.speed),\n });\n\n const withMotion = options.withMotion ?? true;\n if (withMotion && locator && durationMs > 0) {\n // Walk a humanized scan path across the rendered text over the dwell\n // duration. `walkMouseAlongPath` paces the steps so motion ends exactly\n // as the read does — no extra sleep needed.\n const box = await locator.boundingBox().catch(() => null);\n if (box) {\n // Per-line rects make sweeps land on actual text edges, not the\n // element's full width — important for `<pre>` / `<code>` blocks\n // where individual lines are far narrower than the container.\n const lineRects = await getLineRects(locator).catch(() => []);\n const path = planReadingScan(box, ctx.rng, {\n start: ctx.getMousePosition(),\n lineRects: lineRects.length > 0 ? lineRects : undefined,\n });\n await walkMouseAlongPath(ctx.page, path, durationMs);\n const final = path[path.length - 1];\n if (final) ctx.setMousePosition(final);\n return { words, durationMs, kind };\n }\n // No box → fall through to a plain sleep (rare but possible if the\n // element disappeared between innerText() and boundingBox()).\n }\n\n if (durationMs > 0) await sleep(durationMs);\n\n return { words, durationMs, kind };\n}\n\n// ────────── helpers ──────────\n\n/**\n * Returns one rect per visible line of *text* inside the element, in\n * viewport coordinates (same space as `locator.boundingBox()`).\n *\n * Walks text-node descendants and collects each text node's line rects via\n * `Range.getClientRects()`. This is the only way to get tight per-line\n * geometry when the target contains block-level descendants — calling\n * `selectNodeContents` over a `<ul>` or `<div>` would return the block's\n * content box (full container width), not the rendered text edges.\n *\n * Rects on the same visual line (e.g. text broken by `<strong>` / `<em>`)\n * are merged so the planner sweeps each line as a single L→R stroke\n * rather than zigzagging through inline siblings.\n */\nasync function getLineRects(\n locator: Locator,\n): Promise<Array<{ x: number; y: number; width: number; height: number }>> {\n const result = await locator.evaluate((el) => {\n type Rect = { x: number; y: number; width: number; height: number };\n // `4` === `NodeFilter.SHOW_TEXT`. Hardcoded so we don't depend on the\n // global `NodeFilter` being in the Node-side TS lib.\n const walker = el.ownerDocument.createTreeWalker(el, 4);\n const rects: Rect[] = [];\n let node = walker.nextNode();\n while (node) {\n const text = node.textContent ?? '';\n if (text.trim().length > 0) {\n const range = el.ownerDocument.createRange();\n range.selectNodeContents(node);\n for (const r of Array.from(range.getClientRects())) {\n if (r.width > 0 && r.height > 0) {\n rects.push({ x: r.x, y: r.y, width: r.width, height: r.height });\n }\n }\n }\n node = walker.nextNode();\n }\n\n // Merge rects that sit on the same visual line — text broken by inline\n // siblings (\"hello <strong>bold</strong> world\") produces three rects\n // with the same y. Merged, that becomes a single L→R stroke across the\n // full line of text.\n rects.sort((a, b) => a.y - b.y || a.x - b.x);\n const merged: Rect[] = [];\n for (const r of rects) {\n const last = merged[merged.length - 1];\n if (last && Math.abs(last.y - r.y) < 1 && r.x - (last.x + last.width) < 6) {\n const right = Math.max(last.x + last.width, r.x + r.width);\n const bottom = Math.max(last.y + last.height, r.y + r.height);\n last.width = right - last.x;\n last.height = bottom - last.y;\n } else {\n merged.push({ ...r });\n }\n }\n return merged;\n });\n // Defensive: validate the evaluate result is an array of rect-shaped\n // objects before handing it to the planner. Cheap, and keeps the planner\n // from ever seeing junk from a mocked evaluate or an exotic test harness.\n if (!Array.isArray(result)) return [];\n return result.filter(\n (r): r is { x: number; y: number; width: number; height: number } =>\n r != null &&\n typeof r === 'object' &&\n typeof (r as { x?: unknown }).x === 'number' &&\n typeof (r as { y?: unknown }).y === 'number' &&\n typeof (r as { width?: unknown }).width === 'number' &&\n typeof (r as { height?: unknown }).height === 'number',\n );\n}\n\n/**\n * Inspects the element's tag for the smart default. Only the narrowest\n * heuristic (literal `<pre>` / `<code>` tagName) — CSS class sniffing would\n * be too magical. Returns undefined for anything else, so the caller's\n * resolution chain falls back to `'prose'`.\n */\nasync function detectKindFromTag(locator: Locator): Promise<ReadKind | undefined> {\n // `evaluate` runs the function in the browser context; Playwright's types\n // give the callback a DOM Element here without needing the lib.dom ref\n // on the Node-side tsconfig.\n const tag = await locator.evaluate((el) => el.tagName?.toLowerCase() ?? '').catch(() => '');\n if (tag === 'pre' || tag === 'code') return 'code';\n return undefined;\n}\n","import type { Timeline, TimelineEvent } from './index';\n\n// A raw-coordinate target (`point(x, y)`) has no selector, so generated code\n// keeps the coordinate verbatim and flags it — converting it to a guessed\n// locator would silently change behavior (canvas/map/pixel-precise clicks).\nconst POINT_RE = /^point\\((-?\\d+(?:\\.\\d+)?),\\s*(-?\\d+(?:\\.\\d+)?)\\)$/;\nconst POINT_COMMENT = ' // raw coordinate — replace with a locator for a stable selector';\nconst UNCAPTURED_COMMENT =\n ' // input not captured (masked or captureInputs disabled) — fill in (e.g. process.env.X)';\n\n/** Single-quoted JS string literal, escaped. */\nfunction q(value: unknown): string {\n return `'${String(value ?? '')\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/'/g, \"\\\\'\")\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')}'`;\n}\n\n/** Render a mouse-target description as a call argument. */\nfunction targetArg(desc: unknown): { code: string; isPoint: boolean } {\n const s = String(desc ?? '');\n const m = s.match(POINT_RE);\n if (m) return { code: `{ x: ${m[1]}, y: ${m[2]} }`, isPoint: true };\n return { code: q(s), isPoint: false };\n}\n\n/**\n * `createHuman` options block, reconstructed from the timeline metadata.\n * With `ciSpeed`, emits the documented test pattern — instant in CI, the\n * recorded speed locally — so generated tests stay fast in pipelines.\n */\nfunction createHumanOptions(timeline: Timeline, ciSpeed = false): string {\n const parts = [` personality: ${q(timeline.personality)},`];\n if (timeline.seed !== null) parts.push(` seed: ${q(timeline.seed)},`);\n parts.push(\n ciSpeed\n ? ` speed: process.env.CI ? 'instant' : ${q(timeline.speed)},`\n : ` speed: ${q(timeline.speed)},`,\n );\n return `{\\n${parts.join('\\n')}\\n }`;\n}\n\n/** Render `selectOption` values (string / string[] / `{value|label|index}`) as a call arg. */\nfunction serializeSelectValues(values: unknown): string {\n if (typeof values === 'string') return q(values);\n if (Array.isArray(values)) {\n return `[${values.map((v) => (typeof v === 'string' ? q(v) : JSON.stringify(v))).join(', ')}]`;\n }\n // Object form ({ value } / { label } / { index }) — JSON is valid JS here.\n return JSON.stringify(values ?? '');\n}\n\n/** Render `upload` files (recorded as a path string or array of paths) as a call arg. */\nfunction serializeFiles(files: unknown): string {\n if (Array.isArray(files)) return `[${files.map((f) => q(String(f))).join(', ')}]`;\n return q(String(files ?? ''));\n}\n\nfunction emitScroll(target: unknown): string {\n const s = String(target ?? 'natural');\n if (s === 'natural') return \" await human.scroll('natural');\";\n const by = s.match(/^by:(-?\\d+(?:\\.\\d+)?)$/);\n if (by) return ` await human.scroll({ by: ${by[1]} });`;\n const to = s.match(/^to:(-?\\d+(?:\\.\\d+)?)$/);\n if (to) return ` await human.scroll({ to: ${to[1]} });`;\n return ` await human.scroll(${q(s)});`;\n}\n\ninterface EmitOptions {\n /** Append safely-derivable assertions (test export). */\n readonly asserts?: boolean;\n /** When set, `goto` URLs under this origin are emitted as relative paths. */\n readonly baseOrigin?: string;\n}\n\n/**\n * Map one timeline event to generated code. With `asserts` on (test export),\n * append the assertions we can safely derive from recorded state: a read\n * implies the target was visible; a captured input implies its value.\n */\nfunction emitAction(e: TimelineEvent, opts: EmitOptions = {}): string {\n const p = e.params;\n switch (e.type) {\n case 'goto': {\n const url = String(p.url ?? '');\n if (opts.baseOrigin && url.startsWith(opts.baseOrigin)) {\n return ` await human.goto(${q(url.slice(opts.baseOrigin.length) || '/')});`;\n }\n return ` await human.goto(${q(url)});`;\n }\n case 'click':\n case 'rightClick':\n case 'doubleClick':\n case 'hover':\n case 'move': {\n const { code, isPoint } = targetArg(p.target);\n return ` await human.${e.type}(${code});${isPoint ? POINT_COMMENT : ''}`;\n }\n case 'check':\n case 'uncheck':\n case 'clear': {\n const { code } = targetArg(p.target);\n return ` await human.${e.type}(${code});`;\n }\n case 'selectOption': {\n const { code } = targetArg(p.target);\n return ` await human.selectOption(${code}, ${serializeSelectValues(p.values)});`;\n }\n case 'upload': {\n const { code } = targetArg(p.target);\n return ` await human.upload(${code}, ${serializeFiles(p.files)});`;\n }\n case 'drag': {\n const from = targetArg(p.from);\n const to = targetArg(p.to);\n const comment = from.isPoint || to.isPoint ? POINT_COMMENT : '';\n return ` await human.drag(${from.code}, ${to.code});${comment}`;\n }\n case 'type':\n case 'paste': {\n const { code, isPoint } = targetArg(p.target);\n if (e.inputValue === undefined) {\n return ` await human.${e.type}(${code}, '');${UNCAPTURED_COMMENT}`;\n }\n const call = ` await human.${e.type}(${code}, ${q(e.inputValue)});`;\n if (opts.asserts && !isPoint) {\n return `${call}\\n await expect(page.locator(${code})).toHaveValue(${q(e.inputValue)});`;\n }\n return call;\n }\n case 'press':\n return ` await human.press(${q(p.key)});`;\n case 'scroll':\n return emitScroll(p.target);\n case 'read': {\n // Reads driven by word-count or raw text don't carry a selector, and\n // the text itself is never recorded — emit a note instead of broken code.\n const desc = String(p.target ?? '');\n if (/^\\d+ words$/.test(desc) || /^text:\\d+ chars$/.test(desc)) {\n return ` // human.read(...) — ${desc}; original target not captured`;\n }\n const call = ` await human.read(${q(desc)});`;\n if (opts.asserts) return `${call}\\n await expect(page.locator(${q(desc)})).toBeVisible();`;\n return call;\n }\n case 'sleep':\n return ` await sleep(${Number(p.ms) || 0});`;\n case 'reload':\n return ' await human.reload();';\n case 'goBack':\n return ' await human.goBack();';\n case 'goForward':\n return ' await human.goForward();';\n default:\n return ` // unsupported action: ${e.type}`;\n }\n}\n\nfunction needsSleepImport(timeline: Timeline): boolean {\n return timeline.events.some((e) => e.type === 'sleep');\n}\n\n/**\n * Generates a standalone, runnable HumanJS script that replays the recorded\n * session. String selectors round-trip verbatim; raw coordinates and\n * un-captured inputs are emitted with a flag so they're easy to fix up.\n */\nexport function generateHumanJS(timeline: Timeline): string {\n const imports = needsSleepImport(timeline)\n ? \"import { chromium, createHuman, sleep } from '@humanjs/playwright';\"\n : \"import { chromium, createHuman } from '@humanjs/playwright';\";\n const body = timeline.events.map((e) => emitAction(e)).join('\\n');\n return `${imports}\n\nasync function main() {\n const browser = await chromium.launch({ headless: false });\n const page = await browser.newPage();\n const human = await createHuman(page, ${createHumanOptions(timeline)});\n\n${body}\n\n await browser.close();\n}\n\nmain();\n`;\n}\n\n/** Options for {@link generatePlaywrightTest} / `Recording.toPlaywright`. */\nexport interface PlaywrightTestOptions {\n /**\n * Keep recorded `sleep()` pauses. Default `false` — a test shouldn't carry\n * human-timing waits (slow + flaky in CI; Playwright auto-waits instead).\n */\n readonly keepSleeps?: boolean;\n /** Test title. Defaults to the recording's name, else `'recorded session'`. */\n readonly title?: string;\n /**\n * Wrap actions in `test.step(...)` groups — a new step per navigation — so\n * they show as collapsible sections in the HTML report / trace. Default false.\n */\n readonly steps?: boolean;\n /**\n * When all `goto`s share one origin, emit them as relative paths and add a\n * note to set `use.baseURL` in the Playwright config (portable across\n * environments). Default false — absolute URLs that run without any config.\n */\n readonly baseUrl?: boolean;\n}\n\nconst NAV_TYPES = new Set(['goto', 'reload', 'goBack', 'goForward']);\n\n/** The common origin of all `goto`s, or undefined if absent / mixed / relative. */\nfunction sharedGotoOrigin(events: readonly TimelineEvent[]): string | undefined {\n let origin: string | undefined;\n for (const e of events) {\n if (e.type !== 'goto') continue;\n try {\n const o = new URL(String(e.params.url ?? '')).origin;\n if (origin === undefined) origin = o;\n else if (origin !== o) return undefined;\n } catch {\n return undefined;\n }\n }\n return origin;\n}\n\n/** Prefix every non-empty line of `block` with `pad`. */\nfunction indentLines(block: string, pad: string): string {\n return block\n .split('\\n')\n .map((line) => (line.length > 0 ? pad + line : line))\n .join('\\n');\n}\n\n/** A human-ish label for a `test.step` that begins with `event`. */\nfunction stepLabel(event: TimelineEvent, index: number, baseOrigin?: string): string {\n switch (event.type) {\n case 'goto': {\n const url = String(event.params.url ?? '');\n const path =\n baseOrigin && url.startsWith(baseOrigin) ? url.slice(baseOrigin.length) || '/' : url;\n return `go to ${path}`;\n }\n case 'reload':\n return 'reload';\n case 'goBack':\n return 'go back';\n case 'goForward':\n return 'go forward';\n default:\n return `step ${index + 1}`;\n }\n}\n\n/** Group events into `test.step` blocks — a new step begins at each navigation. */\nfunction emitSteps(events: readonly TimelineEvent[], opts: EmitOptions): string {\n const groups: TimelineEvent[][] = [];\n for (const e of events) {\n const last = groups[groups.length - 1];\n if (last === undefined || NAV_TYPES.has(e.type)) groups.push([e]);\n else last.push(e);\n }\n return groups\n .map((group, i) => {\n const [first] = group;\n const label = first ? stepLabel(first, i, opts.baseOrigin) : `step ${i + 1}`;\n const inner = group.map((e) => indentLines(emitAction(e, opts), ' ')).join('\\n');\n return ` await test.step(${q(label)}, async () => {\\n${inner}\\n });`;\n })\n .join('\\n\\n');\n}\n\n/**\n * Generates a `@playwright/test` spec that replays the session through\n * HumanJS — a humanized test, not raw Playwright, since the humanization is\n * the point. Uses the `@humanjs/playwright/test` fixture for the `human`\n * (recorded personality / seed / speed applied via `test.use({ humanOptions })`),\n * runs instant in CI / recorded speed locally, drops timing `sleep()`s by\n * default, and derives the assertions it safely can.\n */\nexport function generatePlaywrightTest(\n timeline: Timeline,\n options: PlaywrightTestOptions = {},\n): string {\n // A test shouldn't replay human-timing pauses — drop them unless asked.\n const events = options.keepSleeps\n ? timeline.events\n : timeline.events.filter((e) => e.type !== 'sleep');\n const baseOrigin = options.baseUrl ? sharedGotoOrigin(events) : undefined;\n const emitOpts: EmitOptions = { asserts: true, baseOrigin };\n const body = options.steps\n ? emitSteps(events, emitOpts)\n : events.map((e) => emitAction(e, emitOpts)).join('\\n');\n const needsSleep = events.some((e) => e.type === 'sleep');\n // Only import `expect` if we actually emitted assertions (body has no\n // comments yet, so this won't match the TODO placeholder below).\n const hasAsserts = body.includes('await expect(');\n // `test` + `expect` come from the `@humanjs/playwright/test` fixture (which\n // supplies the `human`); only `sleep` (when kept) stays on the package root.\n const fixtureImport = hasAsserts\n ? \"import { expect, test } from '@humanjs/playwright/test';\"\n : \"import { test } from '@humanjs/playwright/test';\";\n const sleepImport = needsSleep ? \"\\nimport { sleep } from '@humanjs/playwright';\" : '';\n const title = options.title ?? timeline.name ?? 'recorded session';\n // `page` is only referenced by the derived assertions — omit it from the\n // test args when there are none, so the generated test has no unused fixture.\n const args = hasAsserts ? '{ human, page }' : '{ human }';\n const baseUrlNote = baseOrigin\n ? ` // Set use.baseURL = ${q(baseOrigin)} in playwright.config.ts for these relative paths.\\n\\n`\n : '';\n // Outcome assertions (URL, text appeared, …) can't be derived from recorded\n // actions, so leave a guided placeholder instead of guessing them.\n const todo = [\n hasAsserts\n ? ' // TODO: add assertions for the outcome of this flow, e.g.:'\n : \" // TODO: assert the outcome — add `page` to the test args and import { expect } from '@humanjs/playwright/test', e.g.:\",\n ' // await expect(page).toHaveURL(/dashboard/);',\n \" // await expect(page.getByText('Welcome back')).toBeVisible();\",\n ].join('\\n');\n // Recorded personality / seed / speed are applied via the fixture's\n // `humanOptions` option, so the test still replays with its exact settings\n // (instant in CI) while skipping the per-test createHuman boilerplate.\n return `${fixtureImport}${sleepImport}\n\ntest.use({ humanOptions: ${createHumanOptions(timeline, true)} });\n\ntest(${q(title)}, async (${args}) => {\n${baseUrlNote}${body}\n\n${todo}\n});\n`;\n}\n","import { spawn } from 'node:child_process';\nimport { rmSync } from 'node:fs';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, extname } from 'node:path';\nimport ffmpegStatic from 'ffmpeg-static';\nimport type { CaptureResult } from './capture';\nimport { generateHumanJS, generatePlaywrightTest, type PlaywrightTestOptions } from './codegen';\n\nexport type { PlaywrightTestOptions } from './codegen';\n\n// Safety net for captured-frame temp dirs: every live Recording registers\n// its dir here, and a single lazy `process.on('exit')` handler sweeps\n// whatever's left when the process ends. The OS would eventually reap\n// `os.tmpdir()` anyway, but cleaning on exit avoids the \"100 demo runs and\n// now /tmp has 20GB of frames\" failure mode. Explicit `dispose()` removes\n// from this set so we don't double-clean.\nconst pendingFrameCleanups = new Set<string>();\nlet exitHandlerInstalled = false;\n\nfunction ensureExitHandler(): void {\n if (exitHandlerInstalled) return;\n exitHandlerInstalled = true;\n process.on('exit', () => {\n for (const dir of pendingFrameCleanups) {\n try {\n // Sync rm — `process.on('exit')` can't await Promises. The dirs are\n // small (frames already encoded into the user's output by now in\n // most cases), so the blocking shutdown cost is negligible.\n rmSync(dir, { recursive: true, force: true });\n } catch {\n // Swallow — exit-phase cleanup can race the OS or hit a perms\n // issue we can't recover from anyway. Worst case: the OS reaps\n // tmpdir on its own schedule.\n }\n }\n pendingFrameCleanups.clear();\n });\n}\n\n// `ffmpeg-static` returns the absolute path of a bundled ffmpeg binary at\n// require time, or `null` on platforms it can't support. We resolve once.\nconst FFMPEG_PATH = ffmpegStatic as unknown as string | null;\n\n/**\n * Encoding quality preset. Picks the per-frame capture quality + the\n * ffmpeg encode settings used to assemble them into a video.\n *\n * - `'fast'` — JPEG q=85, CRF 23, preset fast (iteration)\n * - `'standard'` — JPEG q=90, CRF 20, preset fast (balanced)\n * - `'high'` (default) — JPEG q=95, CRF 18, preset slow, tune animation (marketing-grade)\n * - `'lossless'` — PNG capture, CRF 12, preset veryslow (archival; huge temp files)\n */\nexport type RecordingQuality = 'fast' | 'high' | 'lossless' | 'standard';\n\n/** ffmpeg `-preset` values, ordered from fastest to slowest. */\nexport type FfmpegPreset =\n | 'fast'\n | 'faster'\n | 'medium'\n | 'slow'\n | 'slower'\n | 'superfast'\n | 'ultrafast'\n | 'veryfast'\n | 'veryslow';\n\n/** ffmpeg `-tune` values for libx264. */\nexport type FfmpegTune =\n | 'animation'\n | 'fastdecode'\n | 'film'\n | 'grain'\n | 'stillimage'\n | 'zerolatency';\n\ninterface QualityPreset {\n readonly crf: number;\n readonly preset: FfmpegPreset;\n readonly tune?: FfmpegTune;\n /** Per-frame capture format used to source the frames. */\n readonly captureFormat: 'jpeg' | 'png';\n readonly captureJpegQuality: number;\n /** Target capture FPS — the polling rate for `page.screenshot()`. */\n readonly captureFps: number;\n}\n\nconst QUALITY_PRESETS: Record<RecordingQuality, QualityPreset> = {\n fast: {\n captureFormat: 'jpeg',\n captureJpegQuality: 85,\n captureFps: 24,\n crf: 23,\n preset: 'fast',\n },\n standard: {\n captureFormat: 'jpeg',\n captureJpegQuality: 90,\n captureFps: 30,\n crf: 20,\n preset: 'fast',\n },\n high: {\n captureFormat: 'jpeg',\n captureJpegQuality: 95,\n captureFps: 30,\n crf: 18,\n preset: 'slow',\n // 'animation' suits screen content (large solid regions, sharp edges)\n // better than 'film' which is tuned for live-action grain.\n tune: 'animation',\n },\n lossless: {\n // PNG capture for perceptually lossless source frames. Temp files are\n // 10-20× larger than JPEG; output mp4 still benefits from the extra\n // headroom (no JPEG artifacts to preserve).\n captureFormat: 'png',\n captureJpegQuality: 100,\n captureFps: 30,\n crf: 12,\n preset: 'veryslow',\n tune: 'animation',\n },\n};\n\n/** Returns the capture-side settings for a quality preset. */\nexport function getCaptureSettingsForQuality(quality: RecordingQuality): {\n readonly format: 'jpeg' | 'png';\n readonly quality: number;\n readonly fps: number;\n} {\n const preset = QUALITY_PRESETS[quality];\n return {\n format: preset.captureFormat,\n quality: preset.captureJpegQuality,\n fps: preset.captureFps,\n };\n}\n\n/** Options for {@link Recording.toVideo}. */\nexport interface ToVideoOptions {\n /** Encoding quality preset. Defaults to `'high'`. */\n readonly quality?: RecordingQuality;\n /** Override CRF (0–51, lower = better). Defaults to the quality preset's CRF. */\n readonly crf?: number;\n /** Override ffmpeg `-preset`. Defaults to the quality preset's preset. */\n readonly preset?: FfmpegPreset;\n /** Override ffmpeg `-tune`. Defaults to the quality preset's tune (if any). */\n readonly tune?: FfmpegTune;\n}\n\n/** Options for {@link Recording.toGif}. */\nexport interface ToGifOptions {\n /**\n * Frames per second of the output GIF. Defaults to `15` — high enough for\n * smooth motion in most renderers, low enough to keep file size sane.\n * Renderers cap GIF playback around 50fps anyway.\n */\n readonly fps?: number;\n /**\n * Scale the GIF to this width (pixels). Height is computed to preserve\n * aspect ratio. Omit to keep the source viewport size — but most embedded\n * GIFs (README, PR, Slack) look fine at 640–960px and weigh a fraction.\n */\n readonly width?: number;\n}\n\n/** One action captured during a recording, as emitted in {@link Timeline.events}. */\nexport interface TimelineEvent {\n readonly type: string;\n readonly params: Readonly<Record<string, unknown>>;\n /** Offset (ms) from the recording start when the action began. */\n readonly tMs: number;\n readonly durationMs: number;\n /** Error message, present only if the action threw. */\n readonly error?: string;\n /**\n * For `type` / `paste`: the actual text written, captured when\n * `captureInputs` is on (the default). Omitted when capture is off or the\n * target is a password field (always masked). Flows into exported code.\n */\n readonly inputValue?: string;\n}\n\n/** Structured action timeline of a recording. */\nexport interface Timeline {\n readonly version: 1;\n /** Optional label for the recording (used as the generated test's title). */\n readonly name?: string;\n readonly personality: string;\n readonly seed: string | null;\n readonly speed: string;\n readonly durationMs: number;\n readonly events: readonly TimelineEvent[];\n}\n\n/** Metadata passed from `human.record()` into the Recording constructor. */\nexport interface RecordingTimelineSource {\n readonly name?: string;\n readonly personality: string;\n readonly seed: string | null;\n readonly speed: string;\n readonly events: readonly TimelineEvent[];\n}\n\n/**\n * A recorded window of a humanized session. Returned by `human.record(cb)`.\n *\n * A Recording can hold a frame capture (`hasVideo === true`) OR be\n * timeline-only (`hasVideo === false`). `toVideo()` / `toGif()` require a\n * capture; `toTimeline()` and `.timeline` work either way.\n *\n * The video exporters are repeatable and interleavable — they read the\n * captured frames without consuming them. Calling `dispose()` is OPTIONAL:\n * the captured-frames temp dir is also swept by a `process.on('exit')`\n * handler installed on first use, so casual scripts can skip it entirely.\n * Call `dispose()` (or use `await using`) when you want to release the\n * frames proactively — long-running services, batch jobs, etc.\n */\nexport class Recording {\n readonly #capture: CaptureResult | null;\n readonly #windowStartMs: number;\n readonly #windowEndMs: number;\n readonly #timelineSource: RecordingTimelineSource;\n // Frames live on disk until `dispose()` is called. Exporters\n // (`toVideo`, `toGif`) are repeatable and interleavable — they read the\n // same frame source, they don't consume it.\n #disposed = false;\n\n constructor(\n capture: CaptureResult | null,\n windowStartMs: number,\n windowEndMs: number,\n timelineSource: RecordingTimelineSource,\n ) {\n this.#capture = capture;\n this.#windowStartMs = windowStartMs;\n this.#windowEndMs = windowEndMs;\n this.#timelineSource = timelineSource;\n\n // Register the captured-frames dir for sweep-on-exit. If the user\n // forgets to call `dispose()`, the process-exit handler still cleans\n // it up — so casual scripts don't have to think about lifecycle.\n if (capture !== null) {\n pendingFrameCleanups.add(capture.dir);\n ensureExitHandler();\n }\n }\n\n /** Wall-clock duration of the recorded window. */\n get durationMs(): number {\n return this.#windowEndMs - this.#windowStartMs;\n }\n\n /** True if frames were captured during this recording. */\n get hasVideo(): boolean {\n return this.#capture !== null;\n }\n\n /**\n * The structured action timeline of this recording — same data that\n * `toTimeline()` writes to disk.\n */\n get timeline(): Timeline {\n return {\n version: 1,\n ...(this.#timelineSource.name !== undefined ? { name: this.#timelineSource.name } : {}),\n personality: this.#timelineSource.personality,\n seed: this.#timelineSource.seed,\n speed: this.#timelineSource.speed,\n durationMs: this.durationMs,\n events: this.#timelineSource.events,\n };\n }\n\n /**\n * Assembles the captured frames into a video at `outputPath`. The output\n * format is inferred from the extension — `.mp4` (H.264, re-encoded\n * with the configured quality) or `.webm` (VP9).\n *\n * Repeatable and interleavable with `toGif()` — the frame source is read,\n * not consumed. Frames live until you call `dispose()` (or `await using`\n * goes out of scope, or the process exits and the OS reaps `tmpdir`).\n *\n * @returns the resolved output path.\n */\n async toVideo(outputPath: string, options: ToVideoOptions = {}): Promise<string> {\n if (this.#disposed) {\n throw new Error('Recording.toVideo() called after dispose() — the source frames are gone.');\n }\n if (this.#capture === null) {\n throw new Error(\n 'Recording.toVideo() requires video capture, which was disabled for this recording. ' +\n 'Call `human.record(cb)` (default captures video) or pass `output` to ' +\n \"@humanjs/recorder's `record()`. `toTimeline()` and `.timeline` work without capture.\",\n );\n }\n\n const preset = QUALITY_PRESETS[options.quality ?? 'high'];\n const crf = options.crf ?? preset.crf;\n const ffmpegPreset = options.preset ?? preset.preset;\n const tune = options.tune ?? preset.tune;\n\n const { dir, frames, startedAtMs, stoppedAtMs } = this.#capture;\n if (frames.length === 0) {\n throw new Error(\n 'No frames were captured. The recording window may have been too short, ' +\n 'or the page may not have rendered any frames before the callback completed.',\n );\n }\n\n await mkdir(dirname(outputPath), { recursive: true });\n\n const ext = extname(outputPath).toLowerCase();\n if (ext !== '.mp4' && ext !== '.webm') {\n throw new Error(`Unsupported output extension: ${ext || '(none)'}. Use .mp4 or .webm.`);\n }\n\n // Use a concat-demuxer file with per-frame duration so the assembled\n // video matches the real-world capture timing. Handles uneven frame\n // intervals from the polling loop.\n const concatPath = `${dir}/concat.txt`;\n const concatBody = buildConcatFile(frames, stoppedAtMs - startedAtMs);\n await writeFile(concatPath, concatBody, 'utf8');\n\n const args: string[] = ['-y', '-f', 'concat', '-safe', '0', '-i', concatPath, '-vsync', 'vfr'];\n\n if (ext === '.mp4') {\n args.push(\n '-c:v',\n 'libx264',\n '-pix_fmt',\n 'yuv420p',\n '-crf',\n String(crf),\n '-preset',\n ffmpegPreset,\n );\n if (tune) args.push('-tune', tune);\n args.push('-movflags', '+faststart');\n } else {\n // .webm via libvpx-vp9 — lossless friendly, good gradient handling.\n args.push(\n '-c:v',\n 'libvpx-vp9',\n '-pix_fmt',\n 'yuv420p',\n '-crf',\n String(crf),\n '-b:v',\n '0',\n '-deadline',\n ffmpegPreset === 'fast' || ffmpegPreset === 'veryfast' ? 'realtime' : 'good',\n );\n }\n\n args.push(outputPath);\n await runFfmpeg(args);\n\n return outputPath;\n }\n\n /**\n * Assembles the captured frames into an animated GIF at `outputPath`.\n * Optimized for embedding in READMEs, PRs, Slack, and docs — uses a\n * per-recording palette (`palettegen` + `paletteuse`) with Bayer dithering\n * so gradients stay smooth without exploding the file size.\n *\n * Repeatable and interleavable with `toVideo()` — call them in any order,\n * any number of times. Frames live until you call `dispose()`.\n *\n * @returns the resolved output path.\n */\n async toGif(outputPath: string, options: ToGifOptions = {}): Promise<string> {\n if (this.#disposed) {\n throw new Error('Recording.toGif() called after dispose() — the source frames are gone.');\n }\n if (this.#capture === null) {\n throw new Error(\n 'Recording.toGif() requires video capture, which was disabled for this recording. ' +\n 'Call `human.record(cb)` (default captures video) or pass `output` to ' +\n \"@humanjs/recorder's `record()`. `toTimeline()` and `.timeline` work without capture.\",\n );\n }\n\n const fps = options.fps ?? 15;\n const width = options.width;\n\n const { dir, frames, startedAtMs, stoppedAtMs } = this.#capture;\n if (frames.length === 0) {\n throw new Error(\n 'No frames were captured. The recording window may have been too short, ' +\n 'or the page may not have rendered any frames before the callback completed.',\n );\n }\n\n await mkdir(dirname(outputPath), { recursive: true });\n\n const ext = extname(outputPath).toLowerCase();\n if (ext !== '.gif') {\n throw new Error(`Unsupported output extension: ${ext || '(none)'}. Use .gif.`);\n }\n\n const concatPath = `${dir}/concat.txt`;\n const concatBody = buildConcatFile(frames, stoppedAtMs - startedAtMs);\n await writeFile(concatPath, concatBody, 'utf8');\n\n // Filter graph: drop to the target fps, optionally scale, then run the\n // standard split → palettegen → paletteuse pattern. `stats_mode=diff`\n // weights changing pixels more heavily so the palette favors regions\n // that actually move; Bayer dither at scale 5 is the usual sweet spot\n // for screen content (sharp edges, large flat regions).\n const filterSteps: string[] = [`fps=${fps}`];\n if (width !== undefined) {\n filterSteps.push(`scale=${width}:-1:flags=lanczos`);\n }\n const preFilter = filterSteps.join(',');\n const filterComplex =\n `${preFilter},split [a][b]; ` +\n `[a] palettegen=stats_mode=diff [p]; ` +\n `[b][p] paletteuse=dither=bayer:bayer_scale=5`;\n\n const args: string[] = [\n '-y',\n '-f',\n 'concat',\n '-safe',\n '0',\n '-i',\n concatPath,\n '-filter_complex',\n filterComplex,\n '-loop',\n '0',\n outputPath,\n ];\n await runFfmpeg(args);\n\n return outputPath;\n }\n\n /**\n * Writes the structured action timeline to `outputPath` as JSON.\n * Independent of `toVideo()` / `toGif()` — call before, after, in between,\n * or instead. Safe to call multiple times. Unaffected by `dispose()`\n * (the timeline lives in memory, not in the captured-frames temp dir).\n *\n * @returns the resolved output path.\n */\n async toTimeline(outputPath: string): Promise<string> {\n await mkdir(dirname(outputPath), { recursive: true });\n await writeFile(outputPath, `${JSON.stringify(this.timeline, null, 2)}\\n`, 'utf8');\n return outputPath;\n }\n\n /**\n * Generates a standalone, runnable HumanJS script from the timeline and\n * writes it to `outputPath`. String selectors round-trip verbatim; typed\n * values are included when `captureInputs` was on (passwords masked).\n *\n * Independent of frame capture — works on timeline-only recordings and is\n * unaffected by `dispose()`.\n *\n * @returns the resolved output path.\n */\n async toHumanJS(outputPath: string): Promise<string> {\n await mkdir(dirname(outputPath), { recursive: true });\n await writeFile(outputPath, generateHumanJS(this.timeline), 'utf8');\n return outputPath;\n }\n\n /**\n * Generates a `@playwright/test` spec from the timeline — a humanized test\n * (uses `createHuman` + `human.*`), not raw Playwright — and writes it to\n * `outputPath`. Runs instant in CI / recorded speed locally, drops timing\n * `sleep()`s (pass `{ keepSleeps: true }` to keep them), and derives the\n * assertions it safely can.\n *\n * Independent of frame capture — works on timeline-only recordings and is\n * unaffected by `dispose()`.\n *\n * @returns the resolved output path.\n */\n async toPlaywright(outputPath: string, options?: PlaywrightTestOptions): Promise<string> {\n await mkdir(dirname(outputPath), { recursive: true });\n await writeFile(outputPath, generatePlaywrightTest(this.timeline, options), 'utf8');\n return outputPath;\n }\n\n /**\n * Releases the captured-frames temp directory. After this call, `toVideo()`\n * and `toGif()` throw — but `toTimeline()` and the in-memory `timeline`\n * still work because those don't depend on the frames.\n *\n * **Optional.** A process-exit handler also sweeps any un-disposed frame\n * dirs, so casual scripts can skip this entirely. Call it explicitly when\n * you want to release frames proactively (long-running services, batch\n * jobs, or anywhere you want predictable disk usage).\n *\n * Idempotent. Safe to call on a Recording that never had a capture\n * (timeline-only mode) — no-op there.\n *\n * Also wired to `Symbol.asyncDispose`, so the explicit-resource-management\n * `await using` syntax (TypeScript ≥ 5.2 / Node ≥ 20.4) works:\n *\n * ```ts\n * await using rec = await human.record(fn);\n * await rec.toVideo('demo.mp4');\n * await rec.toGif('demo.gif');\n * // frames cleaned up automatically when `rec` goes out of scope\n * ```\n */\n async dispose(): Promise<void> {\n if (this.#disposed) return;\n if (this.#capture !== null) {\n await this.#capture.cleanup();\n // Only unregister from the exit-sweep AFTER cleanup succeeds — if\n // cleanup throws, the sweep stays armed as a last-resort fallback.\n pendingFrameCleanups.delete(this.#capture.dir);\n }\n this.#disposed = true;\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n await this.dispose();\n }\n}\n\n/**\n * Builds an ffmpeg concat-demuxer file describing each captured frame and\n * its duration in seconds. The last frame's duration is the gap to the\n * stop timestamp.\n */\nfunction buildConcatFile(\n frames: readonly { readonly path: string; readonly tMs: number }[],\n totalMs: number,\n): string {\n const lines: string[] = [];\n for (let i = 0; i < frames.length; i++) {\n const frame = frames[i] as { readonly path: string; readonly tMs: number };\n const next = frames[i + 1];\n const nextTMs = next ? next.tMs : totalMs;\n const durationS = Math.max(0.001, (nextTMs - frame.tMs) / 1000);\n lines.push(`file '${frame.path.replaceAll(\"'\", \"'\\\\''\")}'`);\n lines.push(`duration ${durationS.toFixed(6)}`);\n }\n // ffmpeg's concat demuxer requires the final entry repeated without\n // duration so the encoder doesn't drop the last frame.\n const last = frames[frames.length - 1];\n if (last) {\n lines.push(`file '${last.path.replaceAll(\"'\", \"'\\\\''\")}'`);\n }\n return `${lines.join('\\n')}\\n`;\n}\n\nfunction runFfmpeg(args: readonly string[]): Promise<void> {\n if (!FFMPEG_PATH) {\n return Promise.reject(\n new Error(\n 'ffmpeg-static did not bundle a binary for this platform. ' +\n 'Install system ffmpeg and set FFMPEG_PATH, or run on a supported platform.',\n ),\n );\n }\n return new Promise<void>((resolve, reject) => {\n const proc = spawn(FFMPEG_PATH, [...args]);\n let stderr = '';\n proc.stderr?.on('data', (chunk: Buffer) => {\n stderr += chunk.toString();\n });\n proc.on('error', reject);\n proc.on('close', (code) => {\n if (code === 0) resolve();\n else reject(new Error(`ffmpeg exited with code ${code}\\n${stderr.trim()}`));\n });\n });\n}\n","import { mkdtemp, rm, writeFile } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { sleep } from '@humanjs/core';\nimport type { Page } from 'playwright';\n\n/**\n * A captured frame in the timer-based capture session. `tMs` is the\n * wall-clock offset (ms) from the capture start.\n */\nexport interface CapturedFrame {\n readonly path: string;\n readonly tMs: number;\n}\n\n/** Outcome of a finalized capture session. */\nexport interface CaptureResult {\n readonly dir: string;\n readonly frames: readonly CapturedFrame[];\n readonly startedAtMs: number;\n readonly stoppedAtMs: number;\n readonly format: 'jpeg' | 'png';\n readonly fps: number;\n /**\n * Removes the temp directory + all frames. Called by `Recording.dispose()`\n * and by the sweep-on-exit handler — not by the exporters, which are\n * repeatable and read the frames without consuming them. Also called\n * directly by the error path in `human.record()` when the callback throws.\n */\n cleanup(): Promise<void>;\n}\n\n/** Options for {@link startCapture}. */\nexport interface StartCaptureOptions {\n /**\n * Per-frame compression. `'png'` is lossless but produces large temp files\n * (~5-15 MB/frame at 1080p). `'jpeg'` with `quality` is the sweet spot —\n * quality 95+ is near-imperceptible.\n *\n * Defaults to `'jpeg'`.\n */\n readonly format?: 'jpeg' | 'png';\n /** JPEG quality (0-100). Ignored for PNG. Defaults to 95. */\n readonly quality?: number;\n /**\n * Target capture rate in frames per second. The actual rate may be lower\n * if individual screenshots take longer than the per-frame budget — we\n * never pile up captures, so a slow disk just lowers effective FPS.\n * Defaults to 30.\n */\n readonly fps?: number;\n}\n\n/** Live handle returned by {@link startCapture}. */\nexport interface CaptureSession {\n /** Stops the capture loop and returns the assembled frame list. */\n stop(): Promise<CaptureResult>;\n /**\n * Aborts the capture loop without producing a CaptureResult. Used by the\n * error path so the temp dir doesn't linger.\n */\n abort(): Promise<void>;\n}\n\n/**\n * Starts a timer-based capture loop that polls `page.screenshot()` at the\n * configured FPS and writes each frame to a temp directory.\n *\n * Timer-based polling is more reliable than CDP `Page.startScreencast` for\n * the HumanJS use case: the browser only fires screencast events when it\n * re-renders, which means long `sleep()` gaps between actions show up as\n * captured-frame gaps too. Polling gives consistent FPS regardless of\n * what the page is doing.\n *\n * Caller is responsible for invoking either `stop()` (happy path) or\n * `abort()` (error path) to release resources.\n */\nexport async function startCapture(\n page: Page,\n options: StartCaptureOptions = {},\n): Promise<CaptureSession> {\n const format = options.format ?? 'jpeg';\n const quality = options.quality ?? 95;\n const fps = Math.max(1, Math.min(60, options.fps ?? 30));\n const intervalMs = 1000 / fps;\n\n const dir = await mkdtemp(join(tmpdir(), 'humanjs-capture-'));\n const frames: CapturedFrame[] = [];\n const ext = format === 'png' ? 'png' : 'jpg';\n\n let stopped = false;\n let frameIndex = 0;\n // Collects every in-flight write so stop()/abort() can wait for them to\n // settle. Using `allSettled` (in `finish`) means an individual writeFile\n // failure drops one frame but never blocks the rest of the queue or the\n // abort() cleanup path — important when disk pressure shows up mid-capture.\n const writes: Promise<unknown>[] = [];\n\n const startedAtMs = Date.now();\n\n const captureLoop = async (): Promise<void> => {\n while (!stopped) {\n const loopStart = Date.now();\n try {\n const buf = await page.screenshot({\n type: format,\n quality: format === 'jpeg' ? quality : undefined,\n });\n if (stopped) return;\n const idx = frameIndex++;\n const path = join(dir, `frame_${String(idx).padStart(6, '0')}.${ext}`);\n const tMs = loopStart - startedAtMs;\n writes.push(\n writeFile(path, buf).then(\n () => {\n frames.push({ path, tMs });\n },\n (err) => {\n // A single failed write drops one frame but doesn't poison the\n // queue — finish()'s `allSettled` keeps the rest moving and lets\n // abort() reach its `rm()` cleanup.\n console.warn(`humanjs capture: write failed for frame ${idx}:`, err);\n },\n ),\n );\n } catch (err) {\n // Page closed mid-capture, or screenshot otherwise failed. Bail\n // cleanly rather than crashing the loop.\n if (stopped) return;\n console.warn('humanjs capture: screenshot failed, stopping loop:', err);\n stopped = true;\n return;\n }\n const elapsed = Date.now() - loopStart;\n const wait = intervalMs - elapsed;\n if (wait > 0) await sleep(wait);\n }\n };\n\n // Kick off the loop but don't await — it runs until stop()/abort().\n const loopPromise = captureLoop();\n\n const finish = async (): Promise<void> => {\n stopped = true;\n await loopPromise;\n // `allSettled` over `writes` makes individual failures non-blocking; the\n // per-write `.then` above already logs them, so callers see one warning\n // per failed frame and a complete (possibly shorter) frames array.\n await Promise.allSettled(writes);\n };\n\n return {\n async stop(): Promise<CaptureResult> {\n await finish();\n const stoppedAtMs = Date.now();\n return {\n dir,\n frames: [...frames].sort((a, b) => a.tMs - b.tMs),\n startedAtMs,\n stoppedAtMs,\n format,\n fps,\n cleanup: () => rm(dir, { recursive: true, force: true }).then(() => undefined),\n };\n },\n async abort(): Promise<void> {\n await finish();\n await rm(dir, { recursive: true, force: true }).catch(() => undefined);\n },\n };\n}\n","/// <reference lib=\"dom\" />\n\nimport type { BrowserContext, Page } from 'playwright';\n\n/**\n * Canonical HumanJS cursor path — kept in lockstep with the SVG used by the\n * web app's `HumanCursorIcon`. Inlined here so the playwright package has no\n * dependency on `@humanjs/web` or DOM assets.\n */\nconst CURSOR_PATH = 'M 0 0 L 16 6 L 8 9.5 L 5 19 Z';\n\n/** Options for {@link installMouseHelper}. */\nexport interface InstallMouseHelperOptions {\n /** Cursor fill color. Defaults to the HumanJS amber `#f5a55c`. */\n readonly color?: string;\n /** Cursor visual size in pixels. Defaults to 22. */\n readonly size?: number;\n /**\n * Render a ripple at each `mousedown` position so clicks read on video.\n * Defaults to `true`.\n */\n readonly showClicks?: boolean;\n /** Halo opacity behind the cursor. Defaults to `0.18`. */\n readonly haloOpacity?: number;\n}\n\n/**\n * Installs a visual cursor overlay that follows every `mousemove` on each\n * page in the target. Real synthetic motion from Playwright (e.g.\n * `human.click()`, `human.read(..., { withMotion: true })`) is *already*\n * happening — the page just doesn't render a system cursor for it. This\n * helper injects a HumanJS-styled SVG cursor that listens to mousemove\n * events and follows them, making the motion visible in headed demos and\n * screen recordings.\n *\n * Re-runs on every navigation via `addInitScript`, so the overlay survives\n * page reloads. Idempotent — guard flag on `window` prevents double-install.\n *\n * Accepts either a `Page` (overlay applies to that page) or a\n * `BrowserContext` (overlay applies to every page in the context, including\n * pages opened later).\n *\n * @example\n * ```ts\n * const browser = await chromium.launch({ headless: false });\n * const context = await browser.newContext();\n * await installMouseHelper(context);\n * const page = await context.newPage();\n * // human-driven actions are now visible in the page\n * ```\n */\n// Cross-realm idempotency flag. We stash this on the target so a second\n// `installMouseHelper(samePageOrContext)` call is a no-op instead of\n// quietly stacking duplicate listeners. `Symbol.for` keeps the key stable\n// across bundle boundaries if @humanjs/playwright ever ends up duplicated\n// in node_modules (e.g. peer-dep resolution quirks).\nconst INSTALLED_FLAG = Symbol.for('@humanjs/playwright:mouse-helper:installed');\n\nexport async function installMouseHelper(\n target: BrowserContext | Page,\n options: InstallMouseHelperOptions = {},\n): Promise<void> {\n // Guard against re-install on the same target. Without this, every extra\n // call adds another 'domcontentloaded' and 'page' listener, multiplying\n // the per-navigation evaluate() round-trips (the DOM guard in\n // `installScript` makes them no-ops, but the round-trips still cost).\n const tagged = target as unknown as { [k: symbol]: true | undefined };\n if (tagged[INSTALLED_FLAG]) return;\n tagged[INSTALLED_FLAG] = true;\n\n const config: HelperConfig = {\n color: options.color ?? '#f5a55c',\n stroke: '#020203',\n size: options.size ?? 22,\n showClicks: options.showClicks ?? true,\n haloOpacity: options.haloOpacity ?? 0.18,\n path: CURSOR_PATH,\n };\n\n // Register for every future navigation. Fires on goto, reload, frame\n // attachment — but, critically, NOT on `page.setContent()` (Playwright\n // doesn't treat setContent as a navigation, so its new document never\n // sees the init script). The `domcontentloaded` listener below catches\n // that case.\n await target.addInitScript(installScript, config);\n\n // Per-page re-injection on every DOMContentLoaded. `setContent` fires\n // this event but doesn't trigger addInitScript; this is the bridge.\n // The DOM-element guard inside `installScript` makes duplicate installs\n // into a no-op, so it's safe to run on top of addInitScript.\n const attachPageHooks = (page: Page): void => {\n page.on('domcontentloaded', () => {\n page.evaluate(installScript, config).catch(() => undefined);\n });\n };\n\n // Existing pages + future ones (when the target is a context).\n const pages: Page[] = 'pages' in target ? target.pages() : [target];\n for (const page of pages) attachPageHooks(page);\n if ('on' in target && 'newPage' in target) {\n // BrowserContext branch — pages opened after `installMouseHelper`\n // returns still get the same lifecycle hooks.\n target.on('page', attachPageHooks);\n }\n\n // Initial injection for already-loaded pages: if the page is already on a\n // document (via goto/setContent before we attached), the DOMContentLoaded\n // event already fired and our listener won't see it. Evaluate once now.\n await Promise.all(\n pages.map((page) => page.evaluate(installScript, config).catch(() => undefined)),\n );\n}\n\ninterface HelperConfig {\n color: string;\n stroke: string;\n size: number;\n showClicks: boolean;\n haloOpacity: number;\n path: string;\n}\n\n/**\n * Serialized into the page and re-run on every navigation. No closures —\n * everything threads through `config`. `window` and `document` are the\n * page's globals at runtime, not the Node-side types.\n */\nfunction installScript(config: HelperConfig) {\n // Guard on the *document*'s cursor element, not the window. `page.setContent()`\n // replaces the document (and our cursor element inside it) but keeps the\n // same `window`, so a window-level flag would falsely report \"already\n // installed\" while the cursor is actually gone. Querying the DOM is the\n // reliable check.\n if (document.querySelector('[data-humanjs-cursor]')) return;\n\n const attach = () => {\n const cursor = document.createElement('div');\n cursor.setAttribute('aria-hidden', 'true');\n cursor.setAttribute('data-humanjs-cursor', 'true');\n cursor.style.cssText = [\n 'position: fixed',\n 'left: 0',\n 'top: 0',\n `width: ${config.size}px`,\n `height: ${config.size + 4}px`,\n 'pointer-events: none',\n 'z-index: 2147483647',\n // Start visible at (0, 0) so the cursor is on screen from the moment\n // the page loads — without this the helper looks like nothing happened\n // until the first mousemove arrives.\n 'opacity: 1',\n 'transform: translate(0px, 0px)',\n // CSS interpolates between successive `mousemove` updates so the\n // cursor reads as continuous motion instead of discrete hops. Slightly\n // longer than the path-walker's typical step interval (~30–80ms) so\n // each tween is still settling when the next move lands → no pauses.\n 'transition: transform 110ms ease-out, opacity 0.18s ease-out',\n 'will-change: transform',\n ].join('; ');\n const haloRadius = Math.round(config.size * 0.6);\n cursor.innerHTML = `\n <svg width=\"${config.size}\" height=\"${config.size + 4}\" viewBox=\"0 0 22 24\" style=\"overflow: visible;\">\n <circle cx=\"0\" cy=\"0\" r=\"${haloRadius}\" fill=\"${config.color}\" opacity=\"${config.haloOpacity}\" />\n <path d=\"${config.path}\" fill=\"${config.color}\" stroke=\"${config.stroke}\" stroke-width=\"0.7\" stroke-linejoin=\"round\" />\n </svg>\n `;\n document.body.appendChild(cursor);\n\n let lastX = 0;\n let lastY = 0;\n const onMove = (e: MouseEvent) => {\n lastX = e.clientX;\n lastY = e.clientY;\n cursor.style.transform = `translate(${lastX}px, ${lastY}px)`;\n cursor.style.opacity = '1';\n };\n // Listen on both window and document so we catch synthetic mouse events\n // dispatched at either level (Playwright sends them via CDP, and the\n // target frame can vary by event source).\n window.addEventListener('mousemove', onMove, { capture: true, passive: true });\n document.addEventListener('mousemove', onMove, { capture: true, passive: true });\n document.addEventListener(\n 'mouseleave',\n () => {\n cursor.style.opacity = '0';\n },\n { capture: true, passive: true },\n );\n\n if (config.showClicks) {\n const styleEl = document.createElement('style');\n styleEl.textContent =\n '@keyframes humanjs-ripple { 0% { transform: translate(-50%, -50%) scale(0.4); opacity: 0.9; } 100% { transform: translate(-50%, -50%) scale(2); opacity: 0; } }';\n document.head.appendChild(styleEl);\n\n window.addEventListener(\n 'mousedown',\n () => {\n const ripple = document.createElement('div');\n ripple.style.cssText = [\n 'position: fixed',\n `left: ${lastX}px`,\n `top: ${lastY}px`,\n 'width: 28px',\n 'height: 28px',\n 'border-radius: 50%',\n `border: 1.5px solid ${config.color}`,\n 'pointer-events: none',\n 'z-index: 2147483646',\n 'animation: humanjs-ripple 0.45s ease-out forwards',\n ].join('; ');\n document.body.appendChild(ripple);\n window.setTimeout(() => ripple.remove(), 500);\n },\n { capture: true, passive: true },\n );\n }\n };\n\n if (document.body) attach();\n else document.addEventListener('DOMContentLoaded', attach, { once: true });\n}\n","import {\n type ActionResult,\n createRng,\n type HumanAction,\n type HumanPlugin,\n type Personality,\n type PersonalityConfig,\n type PluginContext,\n type Point,\n resolvePersonality,\n sleep,\n} from '@humanjs/core';\nimport type { Locator, Page } from 'playwright';\nimport {\n executeSelectOption,\n executeSetChecked,\n executeUpload,\n type SelectOptionValues,\n type UploadFiles,\n} from './forms';\nimport { executeClear, executePaste, executePress, executeType, type KeyOrChord } from './keyboard';\nimport { executeClick, executeDrag, executeHover, executeMove, type MouseTarget } from './mouse';\nimport { executeRead, type ReadOptions, type ReadResult, type ReadTarget } from './reading';\nimport {\n getCaptureSettingsForQuality,\n Recording,\n type RecordingQuality,\n type TimelineEvent,\n} from './recording';\nimport { startCapture } from './recording/capture';\nimport { executeScroll, type ScrollOptions, type ScrollResult, type ScrollTarget } from './scroll';\n\nexport type {\n ActionResult,\n ActionType,\n BezierPathOptions,\n ComputeReadingDwellOptions,\n DwellProfile,\n HumanAction,\n HumanizePathOptions,\n HumanPlugin,\n Keystroke,\n KnownActionType,\n MouseProfile,\n Personality,\n PersonalityConfig,\n PersonalityExtension,\n PlanTypingOptions,\n PluginContext,\n Point,\n PresetName,\n ReadingProfile,\n ReadKind,\n Rng,\n ScrollProfile,\n ScrollSegment,\n TypingProfile,\n} from '@humanjs/core';\n// Re-exports of the public core API so consumers have one import surface.\nexport {\n applyMicroJitter,\n applyVelocityProfile,\n bezierPath,\n blend,\n careful,\n computeReadingDwellMs,\n countWords,\n createRng,\n distracted,\n fast,\n humanizePath,\n planScroll,\n planTypeKeystrokes,\n precise,\n resolvePersonality,\n sleep,\n} from '@humanjs/core';\n// Playwright primitives re-exported for one-import convenience. These are\n// the unmodified upstream values/types — `@humanjs/playwright` is a\n// Playwright integration, so users shouldn't have to dual-import for the\n// common case. Add more re-exports here only when a real user need shows\n// up; the goal is \"covers 95% of demo/test code,\" not \"mirrors all of\n// playwright.\"\nexport {\n type Browser,\n type BrowserContext,\n type BrowserContextOptions,\n chromium,\n type ElementHandle,\n firefox,\n type LaunchOptions,\n type Locator,\n type Page,\n webkit,\n} from 'playwright';\nexport type { SelectOptionValues, UploadFiles } from './forms';\nexport type { KeyModifier, KeyName, KeyOrChord, PressResult } from './keyboard';\nexport type { MouseTarget } from './mouse';\nexport type { InstallMouseHelperOptions } from './mouse-helper';\nexport { installMouseHelper } from './mouse-helper';\nexport type { ReadOptions, ReadResult, ReadTarget } from './reading';\nexport {\n type FfmpegPreset,\n type FfmpegTune,\n type PlaywrightTestOptions,\n Recording,\n type RecordingQuality,\n type Timeline,\n type TimelineEvent,\n type ToGifOptions,\n type ToVideoOptions,\n} from './recording';\nexport type { ScrollOptions, ScrollResult, ScrollTarget } from './scroll';\n\n/**\n * How fast the humanized session runs.\n * - `'human'` — full humanization (default)\n * - `'fast'` — humanized but accelerated\n * - `'instant'` — bypass all humanization, straight Playwright\n */\nexport type Speed = 'fast' | 'human' | 'instant';\n\n/** Options for {@link createHuman}. */\nexport interface CreateHumanOptions {\n /** Personality preset, extension, or fully built personality. Defaults to `'careful'`. */\n readonly personality?: PersonalityConfig;\n /** Seed for the session's PRNG. Same seed produces identical trajectories. */\n readonly seed?: number | string;\n /** Speed mode. Defaults to `'human'`. */\n readonly speed?: Speed;\n /** Plugins installed on this session, invoked in registration order. */\n readonly plugins?: readonly HumanPlugin[];\n /**\n * Starting cursor position used as the origin of the first humanized path.\n * Defaults to `{ x: 0, y: 0 }`. Set this if you've already moved the cursor\n * (e.g. via `page.mouse.move`) before creating the session, so the first\n * click's path starts from the correct location.\n */\n readonly initialMousePosition?: Point;\n}\n\n/** A humanized Playwright session bound to a single `Page`. */\nexport interface Human {\n /** The resolved personality this session is using. */\n readonly personality: Personality;\n /** The speed mode this session was created with. */\n readonly speed: Speed;\n /**\n * Navigate to `url`. Plugins observe the action via `'goto'`; the underlying\n * `page.goto(url)` is awaited unchanged.\n */\n goto(url: string): Promise<void>;\n /**\n * Move the mouse along a humanized Bezier path to `target` and click.\n *\n * `target` accepts a Playwright-compatible selector string (e.g.\n * `'button:has-text(\"Buy now\")'`), a built `Locator`, or a raw `Point`.\n * For element targets the click point is Gaussian-distributed around the\n * center; for a raw `Point` the exact coordinates are clicked. The\n * `Point` form is the fallback for things with no clean selector —\n * icon-only buttons, canvas, SVG — where you can see the pixel position\n * but can't address the element.\n *\n * In `speed: 'instant'`, all humanization is skipped: element targets use\n * Playwright's native `locator.click()`; a `Point` dispatches one\n * `mouse.click()` at the coordinates.\n */\n click(target: MouseTarget): Promise<void>;\n /**\n * Right-click `target` — opens a native context menu. Same Bezier-path\n * motion and hover dwell as `click()`; only the dispatched button differs.\n * Accepts the same selector / `Locator` / `Point` targets as `click()`.\n *\n * In `speed: 'instant'`, element targets fall back to\n * `locator.click({ button: 'right' })`; a `Point` dispatches one\n * `mouse.click({ button: 'right' })` at the coordinates.\n */\n rightClick(target: MouseTarget): Promise<void>;\n /**\n * Double-click `target`. Identical humanized approach to `click()` — same\n * Bezier path, hover dwell, and occasional near-miss — but the final\n * dispatch is a double-click (two presses within the OS double-click\n * window). Accepts the same selector / `Locator` / `Point` targets.\n *\n * In `speed: 'instant'`, element targets fall back to\n * `locator.click({ clickCount: 2 })`; a `Point` dispatches\n * `mouse.click(x, y, { clickCount: 2 })`.\n */\n doubleClick(target: MouseTarget): Promise<void>;\n /**\n * Move the cursor to `target` along a humanized Bezier path and settle\n * on it — no click is dispatched. Useful for hover-triggered UI\n * (tooltips, dropdowns), for positioning the cursor before a non-target\n * action, or for visible demos where the cursor should pause on\n * something noteworthy.\n *\n * In `speed: 'instant'`, dispatches one `mouse.move()` to the element's\n * center.\n */\n hover(target: Locator | string): Promise<void>;\n /**\n * Move the cursor to `target` along a humanized Bezier path. Pure\n * positioning — no settle dwell, no element interaction. `target` accepts\n * a CSS selector, a `Locator`, or a literal `Point`; the `Point` form\n * lets you position the cursor anywhere (canvas, SVG, dead space) without\n * a DOM element to anchor on.\n *\n * Distinct from `hover()`: `hover` is element-bound and includes a settle\n * dwell to let hover-state UI fire (tooltips, dropdowns). `move` is\n * positional only — use it when you want the cursor placed somewhere\n * without implying interaction with what's under it (pre-press\n * placement, canvas painting, cinematic beats).\n *\n * In `speed: 'instant'`, dispatches one `mouse.move()` at the resolved\n * coordinates.\n */\n move(target: MouseTarget): Promise<void>;\n /**\n * Drag from `from` to `to`. Each endpoint accepts a CSS selector, a\n * `Locator`, or a literal `Point` — the last form matters for canvas /\n * SVG / slider drags where the destination isn't a DOM element.\n *\n * The motion is two humanized paths back-to-back: cursor → source,\n * then source → destination with the left button held throughout.\n *\n * In `speed: 'instant'`, dispatches `mouse.down → move → up` at the\n * resolved coordinates without humanized motion.\n */\n drag(from: MouseTarget, to: MouseTarget): Promise<void>;\n /**\n * Type `value` into `target` with humanized per-key timing, optional typo\n * injection (with backspace recovery), and occasional think-pauses.\n *\n * Per-key `keydown`/`press`/`up` events fire for each character, so\n * handlers like autocomplete dropdowns still receive every keystroke.\n *\n * In `speed: 'instant'`, falls back to `locator.pressSequentially` with\n * zero inter-key delay — events still fire, but humanization is skipped.\n */\n type(target: Locator | string, value: string): Promise<void>;\n /**\n * Insert `value` into `target` in one shot — the Cmd-V semantic. No\n * per-character timing. Like `type()`, drives an implicit click to focus\n * the field first; unlike `type()`, dispatches the whole value via\n * `keyboard.insertText` rather than per-key presses.\n *\n * Use this for long strings (code blocks, multi-line content, secrets)\n * where the typing simulation would be slow and unnecessary. If you need\n * the page's `paste` event handler to fire, call `human.press('Mod+V')`\n * after setting clipboard contents yourself.\n *\n * In `speed: 'instant'`, behaves identically — paste is already instant\n * by nature.\n */\n paste(target: Locator | string, value: string): Promise<void>;\n /**\n * Clear a text field `target` (input, textarea, or contenteditable) with a\n * humanized gesture: click to focus, **select-all**, a beat, then **delete**\n * — the real keyboard motion a person uses to wipe a field before retyping,\n * not a silent value reset. Fires the keydown/up + `input` events the page\n * expects.\n *\n * Pair with `type()` to edit an existing value:\n * `await human.clear('#name'); await human.type('#name', 'New');`\n *\n * In `speed: 'instant'`, delegates to Playwright's native `locator.clear()`.\n */\n clear(target: Locator | string): Promise<void>;\n /**\n * Tick a checkbox or radio `target`. Moves the cursor to the control and\n * clicks it with the same humanized motion as `click()` — but only when\n * needed: if it already reports checked, no click fires (a real user\n * doesn't re-click a box that's already ticked). The resulting state is\n * verified; trying to `check` something that won't toggle throws.\n *\n * `target` is element-bound (selector or `Locator`). In `speed: 'instant'`,\n * delegates to Playwright's native `locator.check()`.\n */\n check(target: Locator | string): Promise<void>;\n /**\n * Untick a checkbox `target`. Mirror of `check()` — humanized click only if\n * currently checked, with state verification afterward. Radios can't be\n * unchecked by clicking (select a different option instead); attempting it\n * throws a clear error.\n *\n * In `speed: 'instant'`, delegates to `locator.uncheck()`.\n */\n uncheck(target: Locator | string): Promise<void>;\n /**\n * Choose option(s) in a native `<select>` `target`. The cursor moves to the\n * dropdown and settles on it (humanized), then the value is set — native\n * selects open an OS menu automation can't drive visually, so the *approach*\n * is humanized while the choice itself is set programmatically (firing\n * `input`/`change`), exactly as Playwright does. For custom DOM dropdowns,\n * drive the rendered options with `click` instead.\n *\n * `values` takes the Playwright `selectOption` shape — a value string, an\n * array of values, or `{ value | label | index }`. Returns the option\n * values that ended up selected.\n *\n * In `speed: 'instant'`, sets the value with no cursor motion.\n */\n selectOption(target: Locator | string, values: SelectOptionValues): Promise<string[]>;\n /**\n * Attach file(s) to a file-input `target`. The cursor moves to the control\n * (visible in recordings / the overlay), then the files are attached via\n * `setInputFiles`. Unlike a real click this never opens the OS file dialog\n * (which would hang) — files are set directly, the way Playwright models\n * uploads.\n *\n * `target` should be the `<input type=\"file\">`. For the common hidden-input-\n * behind-a-styled-button pattern there's no visible control to approach, so\n * the motion is skipped and the files are attached directly. `files` takes\n * the Playwright `setInputFiles` shape (a path, an array of paths, or\n * in-memory `{ name, mimeType, buffer }` payloads).\n *\n * In `speed: 'instant'`, attaches the files with no cursor motion.\n */\n upload(target: Locator | string, files: UploadFiles): Promise<void>;\n /**\n * Press a single key (`'Tab'`, `'Enter'`, `'Escape'`, `'ArrowDown'`, …)\n * or a keyboard chord (`'Mod+S'`, `'Cmd+Shift+P'`, `'Ctrl+C'`, …).\n *\n * Modifier rules:\n *\n * - `Mod` / `CmdOrCtrl` / `CommandOrControl` — magic: `Meta` on Mac,\n * `Control` elsewhere. Use for cross-platform app shortcuts. The three\n * are aliases; `Mod` is shortest.\n * - `Cmd`, `Command`, `Meta`, `Win`, `Super` — literal `Meta` keycode\n * (Command on Mac, Windows key on Windows, Super on Linux).\n * - `Ctrl`, `Control` — literal Control. Stays Control on every OS.\n * - `Alt`, `Option`, `Opt` — literal Alt.\n * - `Shift` — literal Shift.\n *\n * Case-insensitive. Throws on unknown modifiers. The `KeyOrChord` type\n * is a template-literal union of every modifier × key combination (up to\n * two literal modifiers + a key), so IDEs autocomplete common bare keys\n * and chords as you type. Less common keys (`BracketLeft`, `NumpadAdd`,\n * locale-specific keys) still typecheck through the union's string\n * escape hatch — they just don't autocomplete.\n *\n * Does **not** move the cursor — keyboard input dispatches against\n * focus, not cursor position. Compose with `click` / `hover` / `move`\n * when you need both.\n */\n press(key: KeyOrChord): Promise<void>;\n /**\n * Dwell as if reading `target` — the third pillar of humanization after\n * the cursor and the keyboard. Real users pause to read; HumanJS models\n * that pause from word count + the personality's reading WPM (+ jitter).\n *\n * **Targets:**\n * - `string`: a Playwright-compatible selector (matches `click()`/`type()`).\n * - `Locator`: a pre-built Locator.\n * - `{ text }`: literal text in hand (no DOM lookup).\n * - `{ words }`: pre-counted — skip text extraction entirely.\n *\n * **Smart defaults** (only when the caller doesn't override):\n * - `kind` auto-detects as `'code'` for `<pre>` and `<code>` tags;\n * everything else falls back to `'prose'`. Explicit `kind` always wins.\n * - `scrollIntoView: false` — most flows already scrolled to the content.\n *\n * Plugins observe `'read'` actions with `{ target, words, kind }` in params.\n * The text content itself is never echoed — passwords, tokens, and other\n * sensitive strings stay out of telemetry by default.\n *\n * In `speed: 'instant'`, dwell collapses to 0 ms but the action still fires\n * so observability stays consistent.\n *\n * Returns a {@link ReadResult} with the word count, final kind (after\n * auto-detection), and total dwell duration — useful for assertions in\n * tests or for surfacing reading metadata to a UI.\n */\n read(target: ReadTarget, options?: ReadOptions): Promise<ReadResult>;\n /**\n * Scroll the page (or a scrollable container) humanly. Multi-segment\n * motion with a bell-curve velocity profile, optional mid-scroll\n * micro-pauses, and (for the `distracted` personality) the occasional\n * overshoot + correction.\n *\n * **Targets:**\n * - `'natural'` (default): scroll one viewport in the chosen axis\n * - `'end'` / `'top'`: jump to the document/container edges, humanized\n * - `string`: a Playwright-compatible selector — scroll until in view\n * - `Locator`: same, but with a pre-built handle\n * - `{ by: n }`: relative pixel delta (negative = up / left)\n * - `{ to: n }`: absolute scroll position on the chosen axis\n *\n * **Options:** `axis: 'x' | 'y'` (default `'y'`) picks the direction;\n * `within: selector | Locator` scopes the scroll to a scrollable\n * container; `block: 'start' | 'center' | 'end' | 'nearest'` aligns\n * element targets; `overshoot` / `withPauses` toggle individual\n * humanization signals.\n *\n * Plugins observe `'scroll'` actions with `{ target }` in\n * `beforeAction`'s params (a human-readable description of the target).\n * The full {@link ScrollResult} (`from` / `to` / `distance` /\n * `durationMs`) is available via `afterAction`'s `result` argument.\n *\n * In `speed: 'instant'`, the page (or container) is moved with a single\n * `scrollTo` call. No wheel events, no segments — but the action still\n * fires for observability.\n *\n * Returns a {@link ScrollResult} for assertions in tests.\n */\n scroll(target?: ScrollTarget, options?: ScrollOptions): Promise<ScrollResult>;\n /**\n * Pause for `ms` milliseconds. Equivalent to importing `sleep` from\n * `@humanjs/playwright` and calling it — exposed on the Human instance\n * so users who already have `human` in scope don't need an extra import.\n *\n * Not a humanized action: this is a raw `setTimeout` wait, not scaled\n * by personality or speed mode, and no plugin events fire. Use it for\n * generic pacing between humanized actions.\n */\n sleep(ms: number): Promise<void>;\n /**\n * Records `fn`'s actions. Returns a {@link Recording} you can export\n * to mp4/webm video (`toVideo`), JSON timeline (`toTimeline`), or both.\n *\n * By default, frames are captured from the browser via timer-polled\n * `page.screenshot()` — fully controllable quality, not limited by\n * Playwright's recordVideo bitrate ceiling. Pass `{ video: false }` to\n * skip capture entirely (timeline-only mode, zero video overhead).\n *\n * Plugins observe `'record'` in `beforeAction` / `afterAction` so\n * recording shows up alongside the other primitives in observability\n * pipelines.\n *\n * Single-use per session: `Recording.toVideo()` finalizes the captured\n * frames, so calling `human.record()` twice on the same human throws.\n *\n * @example\n * ```ts\n * // Default: video + timeline\n * const rec = await human.record(async () => {\n * await human.click('#login');\n * });\n * await rec.toVideo('demo.mp4');\n * await rec.toTimeline('demo.json');\n *\n * // Timeline-only, no video overhead\n * const rec = await human.record({ video: false }, async () => {\n * await human.click('#login');\n * });\n * await rec.toTimeline('demo.json');\n * ```\n */\n record(fn: () => Promise<void>): Promise<Recording>;\n record(options: HumanRecordOptions, fn: () => Promise<void>): Promise<Recording>;\n\n // ────────────────────────────────────────────────────────────────────\n // Thin re-exports of common Playwright `Page` methods, for ergonomic\n // coherence (`human.*` is the single surface a user thinks about). No\n // humanization happens here — these are pure forwards. Navigation\n // actions fire plugin events; read-only state queries and waits do not.\n // ────────────────────────────────────────────────────────────────────\n\n /**\n * Take a screenshot of the page. Forwards to `page.screenshot(options)`\n * unchanged — see Playwright docs for the full options shape.\n *\n * Not a humanized action: no plugin events fire. Pure ergonomic\n * re-export so `human.*` stays a single surface.\n */\n screenshot(options?: Parameters<Page['screenshot']>[0]): Promise<Buffer>;\n /**\n * Visible text content of the page (`document.body.innerText`). Forwards\n * to `page.innerText('body')`. Useful for AI agents that need to\n * understand what's on screen without parsing HTML.\n *\n * For a region instead of the whole page, use `page.innerText(selector)`.\n *\n * Not a humanized action: no plugin events fire.\n */\n pageText(): Promise<string>;\n /**\n * Full HTML of the page. Forwards to `page.content()`. Often large\n * (50–500 KB on typical sites) — prefer {@link Human.pageText} when\n * passing to an LLM unless structure matters.\n *\n * Not a humanized action: no plugin events fire.\n */\n content(): Promise<string>;\n /**\n * Accessibility-tree **outline** of the page (or a region) — every\n * interactive element and landmark by its ARIA role + accessible name,\n * rendered as compact YAML (Playwright's `ariaSnapshot`). The most\n * token-efficient way for an AI agent to see what's actionable and pick a\n * selector: the names map directly to `getByRole` / accessible-name\n * selectors, which HumanJS already favors.\n *\n * Prefer this over {@link Human.content} when the question is \"what can I\n * click / fill\"; reach for {@link Human.screenshot} when you need the\n * visual layout. Pass `target` to scope the outline to a region.\n *\n * Not a humanized action: no plugin events fire. Requires Playwright ≥ 1.49\n * (when `ariaSnapshot` landed).\n */\n outline(target?: Locator | string): Promise<string>;\n /**\n * Current URL of the page. Forwards to `page.url()`. Synchronous return\n * because Playwright's underlying API is sync.\n *\n * Not a humanized action: no plugin events fire.\n */\n url(): string;\n /**\n * Current document title. Forwards to `page.title()`.\n *\n * Not a humanized action: no plugin events fire.\n */\n title(): Promise<string>;\n /**\n * Reload the current page. Forwards to `page.reload(options)`. Real-user\n * analog of hitting the refresh button — the click motion is *not*\n * humanized (we treat reload as navigation, not a cursor action).\n *\n * Plugins observe a `'reload'` action.\n */\n reload(options?: Parameters<Page['reload']>[0]): Promise<void>;\n /**\n * Navigate back in the browser history. Forwards to `page.goBack(options)`.\n *\n * Plugins observe a `'goBack'` action.\n */\n goBack(options?: Parameters<Page['goBack']>[0]): Promise<void>;\n /**\n * Navigate forward in the browser history. Forwards to\n * `page.goForward(options)`.\n *\n * Plugins observe a `'goForward'` action.\n */\n goForward(options?: Parameters<Page['goForward']>[0]): Promise<void>;\n /**\n * Wait until the page reaches the specified load state. Forwards to\n * `page.waitForLoadState(state, options)`. Common after a humanized\n * click that triggers navigation — gives the page time to settle before\n * the next action.\n *\n * Not a humanized action: no plugin events fire.\n */\n waitForLoadState(\n state?: Parameters<Page['waitForLoadState']>[0],\n options?: Parameters<Page['waitForLoadState']>[1],\n ): Promise<void>;\n /**\n * Wait until the page's URL matches `url` (string, RegExp, or predicate).\n * Forwards to `page.waitForURL(url, options)`. Common post-action wait\n * (e.g. after `human.click('#login')`, wait for `/dashboard`).\n *\n * Not a humanized action: no plugin events fire.\n */\n waitForURL(\n url: Parameters<Page['waitForURL']>[0],\n options?: Parameters<Page['waitForURL']>[1],\n ): Promise<void>;\n /**\n * Resize the viewport. Forwards to `page.setViewportSize(size)`. Useful\n * for testing responsive layouts or switching between breakpoints\n * mid-session.\n *\n * Not a humanized action: no plugin events fire.\n */\n setViewportSize(size: { width: number; height: number }): Promise<void>;\n /**\n * Render the page as a PDF. Forwards to `page.pdf(options)`. Chromium\n * only; works most reliably in headless mode (in headed mode, Playwright\n * silently switches to a print-style render).\n *\n * Not a humanized action: no plugin events fire.\n */\n pdf(options?: Parameters<Page['pdf']>[0]): Promise<Buffer>;\n}\n\n/** Options for {@link Human.record}. */\nexport interface HumanRecordOptions {\n /**\n * Optional label for the recording. Stored on the timeline and used as the\n * title of a generated `toPlaywright()` test.\n */\n readonly name?: string;\n /**\n * Whether to capture frames for video output. Defaults to `true`.\n * Set to `false` for timeline-only recordings (no capture loop, no\n * temp files, no encoding overhead — `toTimeline()` still works).\n */\n readonly video?: boolean;\n /**\n * Capture quality preset. Controls per-frame JPEG quality (or PNG for\n * lossless) AND the ffmpeg encode settings used by `toVideo()`.\n * Defaults to `'high'`. Ignored when `video: false`.\n */\n readonly quality?: RecordingQuality;\n /**\n * Capture the actual typed/pasted text into the timeline (and therefore\n * into code generated by `toHumanJS()` / `toPlaywright()`). Defaults to\n * `true`.\n *\n * Values typed/pasted into `input[type=\"password\"]` are always masked\n * (omitted) regardless of this flag — the video already renders them as\n * dots, and freezing a cleartext secret into an artifact would leak more\n * than the recording itself. Set `false` to record no input values at all;\n * exporters then emit empty-string placeholders.\n *\n * Captured values land in the timeline JSON and any exported test, so treat\n * those artifacts with the same care as the values themselves.\n */\n readonly captureInputs?: boolean;\n}\n\n/**\n * Creates a humanized session bound to a Playwright `Page`.\n *\n * @example\n * ```ts\n * import { chromium } from 'playwright';\n * import { createHuman } from '@humanjs/playwright';\n *\n * const browser = await chromium.launch();\n * const page = await browser.newPage();\n *\n * const human = await createHuman(page, {\n * personality: 'careful',\n * seed: 'session-42',\n * });\n *\n * await human.goto('https://example.com');\n * ```\n */\nexport async function createHuman(page: Page, options: CreateHumanOptions = {}): Promise<Human> {\n const personality = resolvePersonality(options.personality ?? 'careful');\n const rng = createRng(options.seed);\n const speed = options.speed ?? 'human';\n const plugins = options.plugins ?? [];\n\n const context: PluginContext = { personality, rng };\n for (const plugin of plugins) {\n await plugin.install?.(context);\n }\n\n // Each session can only produce one Recording — we can't run two\n // concurrent capture loops on the same page without their screenshots\n // interfering. Reject loudly rather than letting both quietly drop frames.\n let hasRecorded = false;\n\n // Timeline capture is \"armed\" only while `human.record(cb)` is running:\n // a non-null `activeRecordingEvents` means performAction should push each\n // child action into the buffer. The wrapper `record` action itself is\n // skipped — consumers care about what happened inside, not the wrapper.\n let activeRecordingEvents: TimelineEvent[] | null = null;\n let activeRecordingStartMs = 0;\n // Whether `type`/`paste` should record their actual value into the timeline.\n // Armed alongside `activeRecordingEvents` from `record()`'s options.\n let activeRecordingCaptureInputs = false;\n\n // `recordMeta` is recording-only: it reaches the timeline event but is never\n // passed to plugin hooks, so captured input values don't leak through\n // `params` to every installed plugin.\n async function performAction<T>(\n action: HumanAction,\n actionFn: () => Promise<T>,\n recordMeta?: { readonly inputValue?: string },\n ): Promise<T> {\n for (const plugin of plugins) {\n await plugin.beforeAction?.(action);\n }\n const startedAt = Date.now();\n try {\n const value = await actionFn();\n const durationMs = Date.now() - startedAt;\n const result: ActionResult = { type: action.type, durationMs };\n if (activeRecordingEvents !== null && action.type !== 'record') {\n activeRecordingEvents.push({\n type: action.type,\n params: action.params ?? {},\n tMs: startedAt - activeRecordingStartMs,\n durationMs,\n ...(recordMeta?.inputValue !== undefined ? { inputValue: recordMeta.inputValue } : {}),\n });\n }\n for (const plugin of plugins) {\n await plugin.afterAction?.(action, result);\n }\n return value;\n } catch (error) {\n if (activeRecordingEvents !== null && action.type !== 'record') {\n activeRecordingEvents.push({\n type: action.type,\n params: action.params ?? {},\n tMs: startedAt - activeRecordingStartMs,\n durationMs: Date.now() - startedAt,\n error: error instanceof Error ? error.message : String(error),\n ...(recordMeta?.inputValue !== undefined ? { inputValue: recordMeta.inputValue } : {}),\n });\n }\n for (const plugin of plugins) {\n await plugin.onError?.(action, error);\n }\n throw error;\n }\n }\n\n let lastMousePosition: Point = options.initialMousePosition ?? { x: 0, y: 0 };\n\n // Mouse context factory — every mouse primitive (click, rightClick, hover,\n // drag, plus type's implicit click) reads from the same lastMousePosition\n // closure so successive actions chain off where the cursor actually was.\n const mouseCtx = () => ({\n page,\n personality,\n rng,\n speed,\n getMousePosition: () => lastMousePosition,\n setMousePosition: (point: Point) => {\n lastMousePosition = point;\n },\n });\n\n // Mouse-target description for timeline/plugin params. Selectors and\n // Locators stringify as-is; raw Points show as `point(x, y)` so the\n // timeline still reads usefully when a drag targets free coordinates.\n const describeMouseTarget = (target: MouseTarget): string => {\n if (typeof target === 'string') return target;\n if ('x' in target && 'y' in target && typeof target.x === 'number') {\n return `point(${target.x}, ${target.y})`;\n }\n return target.toString?.() ?? 'locator';\n };\n\n const isPointTarget = (target: MouseTarget): target is Point =>\n typeof target !== 'string' && 'x' in target && 'y' in target && typeof target.x === 'number';\n\n // The value a `type`/`paste` should record into the timeline: the real text\n // when capture is on, `undefined` when it's off OR the target is a password\n // field (masked by omission). Runs only while recording, so the extra\n // attribute read costs nothing in normal use.\n const captureInputValue = async (\n target: MouseTarget,\n value: string,\n ): Promise<string | undefined> => {\n if (activeRecordingEvents === null || !activeRecordingCaptureInputs) return undefined;\n const locator =\n typeof target === 'string' ? page.locator(target) : isPointTarget(target) ? null : target;\n if (locator !== null) {\n try {\n // `type` is case-insensitive in the DOM, so normalize before matching\n // (don't leak a value typed into `<input type=\"Password\">`).\n const fieldType = await locator.first().getAttribute('type', { timeout: 1000 });\n if (fieldType?.toLowerCase() === 'password') {\n return undefined;\n }\n } catch {\n // Element type couldn't be read in time — capture the value anyway.\n }\n }\n return value;\n };\n\n return {\n personality,\n speed,\n async goto(url) {\n await performAction({ type: 'goto', params: { url } }, async () => {\n await page.goto(url);\n });\n },\n async click(target) {\n const description = describeMouseTarget(target);\n await performAction({ type: 'click', params: { target: description } }, async () => {\n await executeClick(target, mouseCtx());\n });\n },\n async rightClick(target) {\n const description = describeMouseTarget(target);\n await performAction({ type: 'rightClick', params: { target: description } }, async () => {\n await executeClick(target, mouseCtx(), { button: 'right' });\n });\n },\n async doubleClick(target) {\n const description = describeMouseTarget(target);\n await performAction({ type: 'doubleClick', params: { target: description } }, async () => {\n await executeClick(target, mouseCtx(), { clickCount: 2 });\n });\n },\n async hover(target) {\n const description = describeMouseTarget(target);\n await performAction({ type: 'hover', params: { target: description } }, async () => {\n await executeHover(target, mouseCtx());\n });\n },\n async move(target) {\n const description = describeMouseTarget(target);\n await performAction({ type: 'move', params: { target: description } }, async () => {\n await executeMove(target, mouseCtx());\n });\n },\n async drag(from, to) {\n const fromDesc = describeMouseTarget(from);\n const toDesc = describeMouseTarget(to);\n await performAction({ type: 'drag', params: { from: fromDesc, to: toDesc } }, async () => {\n await executeDrag(from, to, mouseCtx());\n });\n },\n async type(target, value) {\n const description = describeMouseTarget(target);\n // `value` itself is intentionally not echoed into params — typed input may\n // be sensitive (passwords, tokens). Expose length only for observability.\n // The actual value reaches the timeline only via `recordMeta` (when\n // captureInputs is on and the field isn't a password) — never params.\n const inputValue = await captureInputValue(target, value);\n await performAction(\n { type: 'type', params: { target: description, length: value.length } },\n async () => {\n // Implicit click before typing: a real user moves the cursor to\n // the input and clicks it; they don't teleport-focus a field. The\n // click is a sub-step of the type action — not its own timeline\n // event (executeClick called directly, bypassing performAction),\n // same pattern as click's built-in hover-before-click motion.\n //\n // Skipped in instant mode (the whole point of which is to bypass\n // humanization) and for empty values (no typing to set up).\n if (speed !== 'instant' && value.length > 0) {\n await executeClick(target, mouseCtx());\n }\n await executeType(target, value, { page, personality, rng, speed });\n },\n inputValue !== undefined ? { inputValue } : undefined,\n );\n },\n async paste(target, value) {\n const description = describeMouseTarget(target);\n // Same privacy posture as `type`: pasted values may be sensitive\n // (passwords, tokens, secrets being pasted from a manager). Expose\n // length only; the real value reaches the timeline via `recordMeta`.\n const inputValue = await captureInputValue(target, value);\n await performAction(\n { type: 'paste', params: { target: description, length: value.length } },\n async () => {\n // Implicit click before pasting — same reasoning as `type`. A real\n // user clicks the field before pasting; they don't teleport-focus.\n // Skipped in instant mode and for empty values.\n if (speed !== 'instant' && value.length > 0) {\n await executeClick(target, mouseCtx());\n }\n await executePaste(target, value, { page, personality, rng, speed });\n },\n inputValue !== undefined ? { inputValue } : undefined,\n );\n },\n async clear(target) {\n await performAction(\n { type: 'clear', params: { target: describeMouseTarget(target) } },\n async () => {\n // Implicit click to focus the field first — same pattern as type/paste\n // (a real user clicks into a field before wiping it). Skipped in\n // instant mode, where executeClear uses native locator.clear().\n if (speed !== 'instant') {\n await executeClick(target, mouseCtx());\n }\n await executeClear(target, { page, personality, rng, speed });\n },\n );\n },\n async check(target) {\n await performAction(\n { type: 'check', params: { target: describeMouseTarget(target) } },\n async () => {\n await executeSetChecked(target, mouseCtx(), true);\n },\n );\n },\n async uncheck(target) {\n await performAction(\n { type: 'uncheck', params: { target: describeMouseTarget(target) } },\n async () => {\n await executeSetChecked(target, mouseCtx(), false);\n },\n );\n },\n async selectOption(target, values) {\n return performAction(\n { type: 'selectOption', params: { target: describeMouseTarget(target), values } },\n () => executeSelectOption(target, values, mouseCtx()),\n );\n },\n async upload(target, files) {\n await performAction(\n {\n type: 'upload',\n params: { target: describeMouseTarget(target), files: sanitizeUploadFiles(files) },\n },\n async () => {\n await executeUpload(target, files, mouseCtx());\n },\n );\n },\n async press(key) {\n await performAction({ type: 'press', params: { key } }, async () => {\n await executePress(key, { page, personality, rng, speed });\n });\n },\n async read(target, options) {\n const description = describeReadTarget(target);\n // Same privacy posture as `type`: never echo arbitrary content into\n // action params. `target` description, words (when known up front), and\n // kind are inert metadata; the text itself never lands here.\n return performAction(\n {\n type: 'read',\n params: {\n target: description,\n kind: options?.kind,\n },\n },\n () =>\n executeRead(\n target,\n {\n page,\n personality,\n rng,\n speed,\n // Read shares the session's tracked cursor position so an eye\n // scan starts from where the last click left off, and the next\n // click starts from where the scan ended.\n getMousePosition: () => lastMousePosition,\n setMousePosition: (point) => {\n lastMousePosition = point;\n },\n },\n options,\n ),\n );\n },\n async scroll(target, options) {\n const description = describeScrollTarget(target);\n return performAction(\n {\n type: 'scroll',\n params: { target: description },\n },\n () => executeScroll(target, { page, personality, rng, speed }, options),\n );\n },\n async sleep(ms) {\n // Wrap the core `sleep` in performAction so each pause shows up as a\n // 'sleep' event in the recorded timeline. Without this, `human.record()`\n // exporters (toPlaywright, toHumanJS, ...) would emit replay code that\n // skips the user's intentional pauses entirely.\n await performAction({ type: 'sleep', params: { ms } }, () => sleep(ms));\n },\n async record(\n optionsOrFn: HumanRecordOptions | (() => Promise<void>),\n maybeFn?: () => Promise<void>,\n ): Promise<Recording> {\n const [recordOptions, fn] =\n typeof optionsOrFn === 'function'\n ? [{}, optionsOrFn]\n : [optionsOrFn, maybeFn as () => Promise<void>];\n\n if (hasRecorded) {\n throw new Error(\n 'human.record() can only be called once per session. Create a ' +\n 'new browser context (and a new human session) to record a ' +\n 'separate clip.',\n );\n }\n hasRecorded = true;\n\n const captureEnabled = recordOptions.video !== false;\n const captureQuality = recordOptions.quality ?? 'high';\n\n // Start frame capture before any action runs so the first action's\n // motion is in the recording.\n let captureSession: Awaited<ReturnType<typeof startCapture>> | null = null;\n if (captureEnabled) {\n const { format, quality, fps } = getCaptureSettingsForQuality(captureQuality);\n captureSession = await startCapture(page, { format, quality, fps });\n }\n\n // Arm the timeline buffer. `performAction` pushes a TimelineEvent for\n // every child action while this is non-null; the wrapper `record` action\n // is filtered out there.\n const events: TimelineEvent[] = [];\n const windowStartMs = Date.now();\n activeRecordingEvents = events;\n activeRecordingStartMs = windowStartMs;\n activeRecordingCaptureInputs = recordOptions.captureInputs !== false;\n let windowEndMs = windowStartMs;\n\n try {\n await performAction({ type: 'record', params: {} }, async () => {\n try {\n await fn();\n } finally {\n windowEndMs = Date.now();\n }\n });\n } catch (error) {\n // If the callback threw, abort the capture so the temp dir doesn't\n // linger. Then re-throw.\n if (captureSession) await captureSession.abort();\n throw error;\n } finally {\n activeRecordingEvents = null;\n activeRecordingCaptureInputs = false;\n }\n\n const captureResult = captureSession ? await captureSession.stop() : null;\n\n return new Recording(captureResult, windowStartMs, windowEndMs, {\n name: recordOptions.name,\n personality: personality.name,\n seed: options.seed === undefined ? null : String(options.seed),\n speed,\n events,\n });\n },\n\n // ────────────────────────────────────────────────────────────────────\n // Thin re-exports of common Playwright `Page` methods. See the `Human`\n // interface for the rationale; implementations forward unchanged.\n // ────────────────────────────────────────────────────────────────────\n\n screenshot(opts) {\n return page.screenshot(opts);\n },\n pageText() {\n return page.innerText('body');\n },\n content() {\n return page.content();\n },\n outline(target) {\n const locator =\n target === undefined\n ? page.locator('body')\n : typeof target === 'string'\n ? page.locator(target)\n : target;\n return locator.ariaSnapshot();\n },\n url() {\n return page.url();\n },\n title() {\n return page.title();\n },\n async reload(opts) {\n await performAction({ type: 'reload', params: {} }, async () => {\n await page.reload(opts);\n });\n },\n async goBack(opts) {\n await performAction({ type: 'goBack', params: {} }, async () => {\n await page.goBack(opts);\n });\n },\n async goForward(opts) {\n await performAction({ type: 'goForward', params: {} }, async () => {\n await page.goForward(opts);\n });\n },\n waitForLoadState(state, opts) {\n return page.waitForLoadState(state, opts);\n },\n waitForURL(url, opts) {\n return page.waitForURL(url, opts);\n },\n setViewportSize(size) {\n return page.setViewportSize(size);\n },\n pdf(opts) {\n return page.pdf(opts);\n },\n };\n}\n\n/**\n * JSON-safe projection of upload files for the timeline / plugin params.\n * Paths pass through; in-memory `{ name, mimeType, buffer }` payloads collapse\n * to their `name` so a Buffer never bloats (or breaks) the serialized timeline.\n */\nfunction sanitizeUploadFiles(files: UploadFiles): string | string[] {\n const one = (f: unknown): string =>\n typeof f === 'string'\n ? f\n : f && typeof f === 'object' && 'name' in f\n ? String((f as { name: unknown }).name)\n : 'file';\n return Array.isArray(files) ? files.map(one) : one(files);\n}\n\n/**\n * Human-readable description of a scroll target for action params. Strings\n * (presets + selectors) pass through; objects describe their shape; the\n * Locator branch falls back to `toString()`.\n */\nfunction describeScrollTarget(target: ScrollTarget | undefined): string {\n if (target === undefined) return 'natural';\n if (typeof target === 'string') return target;\n if ('by' in target) return `by:${target.by}`;\n if ('to' in target) return `to:${target.to}`;\n return target.toString?.() ?? 'locator';\n}\n\n/**\n * Human-readable description of a read target for action params. Echoes\n * selectors and `{ words }` (both inert); abbreviates literal text to its\n * length so we never expose content even via accidental logging.\n */\nfunction describeReadTarget(target: ReadTarget): string {\n if (typeof target === 'string') return target;\n if ('words' in target && typeof target.words === 'number') return `${target.words} words`;\n if ('text' in target && typeof target.text === 'string') {\n return `text:${target.text.length} chars`;\n }\n return target.toString?.() ?? 'locator';\n}\n"]}