Spaces:
Paused
Paused
| import { parseRoleRef } from "./pw-role-snapshot.js"; | |
| let nextUploadArmId = 0; | |
| let nextDialogArmId = 0; | |
| let nextDownloadArmId = 0; | |
| export function bumpUploadArmId(): number { | |
| nextUploadArmId += 1; | |
| return nextUploadArmId; | |
| } | |
| export function bumpDialogArmId(): number { | |
| nextDialogArmId += 1; | |
| return nextDialogArmId; | |
| } | |
| export function bumpDownloadArmId(): number { | |
| nextDownloadArmId += 1; | |
| return nextDownloadArmId; | |
| } | |
| export function requireRef(value: unknown): string { | |
| const raw = typeof value === "string" ? value.trim() : ""; | |
| const roleRef = raw ? parseRoleRef(raw) : null; | |
| const ref = roleRef ?? (raw.startsWith("@") ? raw.slice(1) : raw); | |
| if (!ref) { | |
| throw new Error("ref is required"); | |
| } | |
| return ref; | |
| } | |
| export function normalizeTimeoutMs(timeoutMs: number | undefined, fallback: number) { | |
| return Math.max(500, Math.min(120_000, timeoutMs ?? fallback)); | |
| } | |
| export function toAIFriendlyError(error: unknown, selector: string): Error { | |
| const message = error instanceof Error ? error.message : String(error); | |
| if (message.includes("strict mode violation")) { | |
| const countMatch = message.match(/resolved to (\d+) elements/); | |
| const count = countMatch ? countMatch[1] : "multiple"; | |
| return new Error( | |
| `Selector "${selector}" matched ${count} elements. ` + | |
| `Run a new snapshot to get updated refs, or use a different ref.`, | |
| ); | |
| } | |
| if ( | |
| (message.includes("Timeout") || message.includes("waiting for")) && | |
| (message.includes("to be visible") || message.includes("not visible")) | |
| ) { | |
| return new Error( | |
| `Element "${selector}" not found or not visible. ` + | |
| `Run a new snapshot to see current page elements.`, | |
| ); | |
| } | |
| if ( | |
| message.includes("intercepts pointer events") || | |
| message.includes("not visible") || | |
| message.includes("not receive pointer events") | |
| ) { | |
| return new Error( | |
| `Element "${selector}" is not interactable (hidden or covered). ` + | |
| `Try scrolling it into view, closing overlays, or re-snapshotting.`, | |
| ); | |
| } | |
| return error instanceof Error ? error : new Error(message); | |
| } | |