@vostride/agent-qa-android 0.2.3 → 0.2.4

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.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/adapter.ts","../src/session.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto'\nimport { mkdir, rm, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type {\n ActionsFor,\n ActionResult,\n AppRegistryEntry,\n ConsoleLogEntry,\n Direction,\n FillRefusalMeta,\n FillSubmitMeta,\n FillVerdictMeta,\n InterimNode,\n ObserveOptions,\n PlatformAdapter,\n LiveStreamCapability,\n PlatformConfig,\n RecordingCapability,\n ScrollPrimitives,\n ShellActionMeta,\n SwipeSignal,\n} from '@vostride/agent-qa-runner'\nimport {\n assertNever,\n buildScreenState,\n compareFillReread,\n createSnapshotLiveStream,\n resolveAppName,\n runDirectionScroll,\n runToEndScroll,\n runUntilVisibleLoop,\n} from '@vostride/agent-qa-runner'\nimport type { ElementLabels, ElementState, Ref, ScreenState } from '@vostride/agent-qa-schema'\nimport {\n KEY_MAP,\n MobileElementResolver,\n MobileSetupError,\n WEBVIEW_SCROLLERS_SCRIPT,\n buildRefEntries,\n computeFingerPositions,\n computePinch,\n computeSwipe,\n deriveMobileScroll,\n parseMobileSource,\n parseWebViewScrollers,\n warnIfOutOfBounds,\n webViewSwipeSignal,\n} from '@vostride/agent-qa-core'\nimport type { IdentifiedScrollOffsets, MobileRefMap } from '@vostride/agent-qa-core'\nimport { createAndroidSession } from './session.js'\nimport type { AndroidAdapterConfig } from './types.js'\n\nconst ANDROID_FILLABLE_ROLES = new Set(['textbox', 'searchbox', 'edittext', 'combobox'])\n\n// UiAutomator2 refuses getAttribute for showing-hint and multiline although it lists them, so they\n// are read through XPath over the focused node's page-source attributes (437 Pitfall 5).\nconst FOCUSED_XPATH = '//*[@focused=\"true\"]'\nconst FOCUSED_HINT_XPATH = '//*[@focused=\"true\" and @showing-hint=\"true\"]'\nconst FOCUSED_MULTILINE_XPATH = '//*[@focused=\"true\" and @multiline=\"true\"]'\nconst FOCUSED_SINGLE_LINE_XPATH = '//*[@focused=\"true\" and @multiline=\"false\"]'\n// 437 D-11 (WR-02): the focused node's `bounds` must lie within the ref's, within iOS's RECT_TOLERANCE.\nconst FOCUS_BOUNDS_TOLERANCE = 1\nconst ANDROID_BOUNDS_RE = /^\\[(-?\\d+),(-?\\d+)\\]\\[(-?\\d+),(-?\\d+)\\]$/\nconst ENTER_KEYCODE = 66\nconst CTRL_A = { keycode: 29, metastate: 0x1000 }\nconst DEL_KEYCODE = 67\nconst MULTI_LINE_SUBMIT_NOTICE =\n 'submit not sent: Return would add a new line in this multi-line field; tap its send or submit control'\nconst LINE_BREAK_RE = /[\\r\\n]/\n// The fixed @appium/base-driver text for a refused insecure feature (437 D-18).\nconst ADB_SHELL_REFUSAL = \"Potentially insecure feature 'adb_shell' has not been enabled\"\n\n// 437 D-11: the WebView fill and clear use page scripts only to probe focus and read the value.\n// The probe runs after a trusted tap at the ref's centre and never writes to the page.\nconst WEB_FOCUS_PROBE_SCRIPT =\n 'var a = document.activeElement;'\n + 'var hit = document.elementFromPoint(arguments[0], arguments[1]);'\n + 'if (!a) {'\n + ' return { editable: false, matches: false, multiline: false, secure: false, value: null };'\n + '}'\n + 'var tag = a.tagName;'\n + 'var type = tag === \"INPUT\" ? String(a.type || \"text\").toLowerCase() : \"\";'\n + 'var textual = [\"text\", \"search\", \"email\", \"url\", \"tel\", \"password\", \"number\"]'\n + '.indexOf(type) >= 0;'\n + 'var field = (tag === \"INPUT\" && textual) || tag === \"TEXTAREA\";'\n + 'var rich = !field && a.isContentEditable === true;'\n + 'var v = field ? a.value : (rich ? a.innerText : null);'\n + 'return {'\n + ' editable: (field && !a.readOnly && !a.disabled) || rich,'\n + ' matches: !!hit && (a === hit || a.contains(hit)),'\n + ' multiline: tag === \"TEXTAREA\" || rich,'\n + ' secure: type === \"password\",'\n + ' value: typeof v === \"string\" ? v : null'\n + '};'\n// 437 D-11 (WR-01): Chromium moves focus a moment after the tap, so the probe is polled the way\n// iOS polls its focus (FOCUS_POLLS, FOCUS_POLL_PAUSE_MS) before the WebView path refuses.\nconst WEB_FOCUS_POLLS = 3\nconst WEB_FOCUS_POLL_MS = 300\nconst WEB_FIELD_VALUE_SCRIPT =\n 'var a = document.activeElement;'\n + 'if (!a) { return null; }'\n + 'var v = (a.tagName === \"INPUT\" || a.tagName === \"TEXTAREA\") ? a.value'\n + ' : (a.isContentEditable ? a.innerText : null);'\n + 'return typeof v === \"string\" ? v : null;'\nconst ANDROID_NATIVE_SELECT_ROLES = new Set(['combobox', 'spinbutton', 'listbox', 'list'])\nconst ANDROID_NATIVE_SELECT_TYPES = new Set([\n 'android.widget.Spinner',\n 'android.widget.NumberPicker',\n 'android.widget.DatePicker',\n 'android.widget.TimePicker',\n 'android.widget.ListView',\n 'androidx.recyclerview.widget.RecyclerView',\n])\n\nasync function safePerform(chain: { perform: () => Promise<void> }): Promise<void> {\n try {\n await chain.perform()\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err)\n if (msg.includes('actions') && msg.includes('DELETE')) return\n throw err\n }\n}\n\nconst LOGCAT_REGEX = /^(\\d{2}-\\d{2})\\s+(\\d{2}:\\d{2}:\\d{2}\\.\\d{3})\\s+(\\d+)\\s+(\\d+)\\s+([VDIWEF])\\s+(.+?)\\s*:\\s+(.*)/\n\nconst ANDROID_LEVEL_MAP: Record<string, string> = {\n V: 'debug',\n D: 'debug',\n I: 'info',\n W: 'warn',\n E: 'error',\n F: 'error',\n}\n\nfunction firstNonEmpty(...values: Array<string | null | undefined>): string | undefined {\n for (const value of values) {\n const trimmed = typeof value === 'string' ? value.trim() : ''\n if (trimmed) return trimmed\n }\n return undefined\n}\n\ntype TextBox = {\n coordinates: { x: number; y: number }\n boundingBox: { x: number; y: number; width: number; height: number }\n}\n\ntype FocusedField = {\n getText: () => Promise<string>\n getAttribute: (name: string) => Promise<string | null>\n setValue: (value: string) => Promise<void>\n addValue: (value: string) => Promise<void>\n clearValue: () => Promise<void>\n}\n\ntype WebFocus = {\n editable: boolean\n matches: boolean\n multiline: boolean\n secure: boolean\n value?: string\n}\n\ntype InputPath = NonNullable<FillVerdictMeta['path']>\n\nconst INPUT_FAILED: FillSubmitMeta = { sent: false, outcome: 'not-sent', reason: 'input-failed' }\n\ntype FieldKind = 'single-line' | 'multi-line' | 'unknown'\n\n// Android InputType: the low nibble is the class (1 = text); 0x20000 is TYPE_TEXT_FLAG_MULTI_LINE.\nfunction fieldKindOf(refData: MobileRefMap[string] | undefined): FieldKind {\n const inputType = refData?.inputType\n if (inputType === undefined || (inputType & 0xf) === 0) return 'unknown'\n if ((inputType & 0xf) === 1 && (inputType & 0x20000) !== 0) return 'multi-line'\n return 'single-line'\n}\n\ntype Rect = { x: number; y: number; width: number; height: number }\n\ntype FocusVerdict = 'target' | 'elsewhere' | 'moved'\n\nfunction webFocusEvidence(focus: WebFocus): 'no-keyboard-focus' | 'focus-elsewhere' {\n return focus.editable ? 'focus-elsewhere' : 'no-keyboard-focus'\n}\n\nfunction parseBoundsAttr(value: unknown): Rect | undefined {\n if (typeof value !== 'string') return undefined\n const match = ANDROID_BOUNDS_RE.exec(value.trim())\n if (!match) return undefined\n const [left, top, right, bottom] = match.slice(1).map(Number) as [number, number, number, number]\n return { x: left, y: top, width: right - left, height: bottom - top }\n}\n\nfunction rectWithin(inner: Rect, outer: Rect): boolean {\n return inner.x >= outer.x - FOCUS_BOUNDS_TOLERANCE\n && inner.y >= outer.y - FOCUS_BOUNDS_TOLERANCE\n && inner.x + inner.width <= outer.x + outer.width + FOCUS_BOUNDS_TOLERANCE\n && inner.y + inner.height <= outer.y + outer.height + FOCUS_BOUNDS_TOLERANCE\n}\n\nfunction firstErrorLine(err: unknown): string {\n const message = err instanceof Error ? err.message : String(err)\n return message.split('\\n')[0]!.trim()\n}\n\nfunction isShellRefusal(err: unknown): boolean {\n return (err instanceof Error ? err.message : String(err)).includes(ADB_SHELL_REFUSAL)\n}\n\nfunction isAndroidWebContextName(context: string): boolean {\n const normalized = context.toUpperCase()\n return normalized.includes('CHROMIUM') || normalized.includes('WEBVIEW')\n}\n\nfunction isTargetWebContext(context: string, appPackage: string | null, explicitBrowserMode: boolean): boolean {\n if (explicitBrowserMode) return isAndroidWebContextName(context)\n if (!appPackage) return false\n return context.toLowerCase().includes(appPackage.toLowerCase())\n}\n\nfunction isAndroidNativeSelectTarget(refData: MobileRefMap[string] | undefined): boolean {\n const role = refData?.role?.toLowerCase()\n return Boolean(\n (role && ANDROID_NATIVE_SELECT_ROLES.has(role))\n || (refData?.nativeType && ANDROID_NATIVE_SELECT_TYPES.has(refData.nativeType))\n )\n}\n\n/**\n * Escape untrusted target text for interpolation into a UiAutomator `UiSelector` source string\n * (T-359-01 · Pitfall 9). Backslash-escape backslashes FIRST, then double quotes, so the raw\n * text can never break out of the `textContains(\"…\")` literal. Control characters cannot be\n * represented safely in the selector language, so a target carrying any is rejected with a\n * structured error rather than being interpolated verbatim (T-352-11 posture).\n */\nconst CONTROL_CHAR_RE = /[\\u0000-\\u001F\\u007F]/\nfunction escapeUiSelectorText(value: string): string {\n if (CONTROL_CHAR_RE.test(value)) {\n throw new Error(\n `scroll target contains a control character and cannot be used as a UiAutomator selector — provide a plain-text target for untilVisible.`,\n )\n }\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')\n}\n\n/** Scroll intent (reveal content toward `direction`) maps to the OPPOSITE finger swipe. */\nfunction fingerDirectionFor(scroll: Direction): 'up' | 'down' | 'left' | 'right' {\n switch (scroll) {\n case 'up':\n return 'down'\n case 'down':\n return 'up'\n case 'left':\n return 'right'\n case 'right':\n return 'left'\n }\n}\n\nfunction androidUiSelectorText(value: string): string {\n return `android=new UiSelector().text(${JSON.stringify(value)})`\n}\n\nfunction androidUiSelectorDescription(value: string): string {\n return `android=new UiSelector().description(${JSON.stringify(value)})`\n}\n\nasync function findAndroidNativeOption(\n driver: WebdriverIO.Browser,\n value: string,\n): Promise<{ element: any; matchedValue: string; matchStrategy: 'text' | 'description' } | null> {\n for (const [selector, matchStrategy] of [\n [androidUiSelectorText(value), 'text'],\n [androidUiSelectorDescription(value), 'description'],\n ] as const) {\n try {\n const element = await driver.$(selector)\n if (await element.isExisting()) {\n return { element, matchedValue: value, matchStrategy }\n }\n } catch {\n // Try the next exact selector.\n }\n }\n return null\n}\n\nfunction parseLogcatLine(message: string, timestamp: number, appPid: string | null): ConsoleLogEntry | null {\n const match = message.match(LOGCAT_REGEX)\n if (!match) return null\n const [, , , pid, , levelChar, tag, text] = match\n if (appPid && pid !== appPid) return null\n return {\n level: ANDROID_LEVEL_MAP[levelChar] ?? 'debug',\n text: `[${tag.trim()}] ${text.trim()}`,\n timestamp,\n }\n}\n\n// Injected into the WebView/browser to emit a JSON-serializable array of interim-node\n// records from the live DOM (RESEARCH Pitfall #5). It walks the DOM as before but NO\n// longer mints refs or renders tree text in-page — the shared runner builder owns ref\n// minting, name normalization, and tree rendering (D-01/D-02/D-03). Every record carries\n// only real DOM signals (D-08); the builder derives all defaults. Defined as a string\n// because this runs in browser context — the Node tsconfig has no DOM lib so a typed\n// function would fail compilation.\nconst WEB_OBSERVER_SCRIPT = `\nreturn (function() {\n var TAG_ROLES = {\n A: 'link', BUTTON: 'button', INPUT: 'textbox', TEXTAREA: 'textbox',\n SELECT: 'combobox', H1: 'heading', H2: 'heading', H3: 'heading',\n H4: 'heading', H5: 'heading', H6: 'heading', IMG: 'image'\n };\n\n var doc = document;\n var vw = window.innerWidth;\n var vh = window.innerHeight;\n var active = doc.activeElement;\n\n var all = doc.querySelectorAll(\n 'a, button, input, textarea, select, h1, h2, h3, h4, h5, h6, img[alt], [role], [contenteditable]:not([contenteditable=\"false\"])'\n );\n\n var nodes = [];\n var includedEls = [];\n var seen = {};\n var CAPTION_TYPES = { submit: true, button: true, reset: true };\n var VALUELESS_TYPES = {\n password: true, checkbox: true, radio: true, submit: true, button: true, reset: true,\n image: true, file: true, hidden: true, range: true, color: true\n };\n\n function textOf(node) {\n return node ? (node.textContent || '').trim() : '';\n }\n\n // 437 D-11 (CR-02): a field is named by its label, never by its value, so typed text never\n // becomes a name. A wrapping label's text drops the field's own text (a select's options).\n function labelText(el, label) {\n var text = label.textContent || '';\n var own = el.textContent || '';\n if (own && label.contains(el)) text = text.replace(own, '');\n return text.trim();\n }\n\n function fieldName(el, tag) {\n var ids = (el.getAttribute('aria-labelledby') || '').split(' ');\n var parts = [];\n for (var j = 0; j < ids.length; j++) {\n var part = ids[j] ? textOf(doc.getElementById(ids[j])) : '';\n if (part) parts.push(part);\n }\n if (parts.length > 0) return parts.join(' ');\n var label = el.labels && el.labels.length > 0 ? labelText(el, el.labels[0]) : '';\n if (label) return label;\n var hint = el.getAttribute('placeholder') || el.getAttribute('title');\n if (hint) return hint;\n if (tag === 'INPUT' && CAPTION_TYPES[String(el.type).toLowerCase()]) return el.value || '';\n return '';\n }\n\n // parentIndex is the nearest INCLUDED ancestor (structural/skipped nodes collapse\n // away, matching the mobile/web walkers' Pitfall #7 handling).\n function nearestAncestorIndex(el) {\n var p = el.parentElement;\n while (p) {\n var idx = includedEls.indexOf(p);\n if (idx !== -1) return idx;\n p = p.parentElement;\n }\n return undefined;\n }\n\n for (var i = 0; i < all.length; i++) {\n var el = all[i];\n var rect = el.getBoundingClientRect();\n if (rect.width === 0 && rect.height === 0) continue;\n\n var style = window.getComputedStyle(el);\n if (style.display === 'none' || style.visibility === 'hidden') continue;\n\n var tag = el.tagName;\n // 2026-10-19 (444.1-05, D-09): only the outermost content-editable element is an editor;\n // its descendants are ordinary nodes.\n var host = el.isContentEditable === true\n && !(el.parentElement && el.parentElement.isContentEditable === true);\n var ariaRole = el.getAttribute('role');\n var role = (ariaRole || TAG_ROLES[tag] || (host ? 'textbox' : '')).toLowerCase();\n if (!role) continue;\n\n var field = tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT';\n var editable = field || host;\n var textual = role === 'textbox' || role === 'searchbox' || role === 'combobox';\n var name = '';\n var ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) {\n name = ariaLabel;\n } else if (tag === 'IMG') {\n name = el.alt || '';\n } else if (editable || textual) {\n name = fieldName(el, tag) || el.getAttribute('aria-placeholder') || '';\n } else {\n name = (el.textContent || '').trim();\n }\n\n name = name.slice(0, 100).replace(/[\\\\n\\\\r]+/g, ' ').trim();\n if (!name && !editable && !textual) continue;\n\n if (!editable && !textual) {\n var key = role + ':' + name;\n if (seen[key]) continue;\n seen[key] = true;\n }\n\n var bounds = {\n x: Math.round(rect.left),\n y: Math.round(rect.top),\n width: Math.round(rect.width),\n height: Math.round(rect.height)\n };\n\n // Real DOM state signals only — the builder derives every default (D-08).\n var state = {};\n var disabled = el.disabled === true\n || el.hasAttribute('disabled')\n || el.getAttribute('aria-disabled') === 'true';\n state.enabled = !disabled;\n state.focused = el === active;\n if (bounds.y + bounds.height < 0 || bounds.y > vh) state.visible = false;\n if (tag === 'INPUT' && (el.type === 'checkbox' || el.type === 'radio')) {\n state.checked = el.checked === true;\n }\n\n var labels = {};\n var testId = el.getAttribute('data-testid');\n if (testId) labels.testId = testId;\n if (ariaLabel) labels.ariaLabel = ariaLabel;\n var placeholder = el.getAttribute('placeholder');\n if (placeholder) labels.placeholder = placeholder;\n var title = el.getAttribute('title');\n if (title) labels.title = title;\n\n var attributes = {};\n if (el.type) attributes.type = String(el.type);\n\n var parentIndex = nearestAncestorIndex(el);\n\n // 2026-10-19 (444.1-05 D-08, 444.1-22 D-33): what a field or an editor holds is its value, never its name; a password's never.\n var observedValue = undefined;\n var textEntry = tag === 'TEXTAREA' || (tag === 'INPUT' && !VALUELESS_TYPES[String(el.type).toLowerCase()]);\n if (textEntry && el.value) {\n observedValue = String(el.value).slice(0, 200);\n } else if (tag === 'SELECT') {\n var option = el.options && el.selectedIndex >= 0 ? el.options[el.selectedIndex] : null;\n var optionText = option ? String(option.text || '').trim().slice(0, 200) : '';\n if (optionText) observedValue = optionText;\n } else if (host || (textual && !field)) {\n var held = textOf(el).replace(/[\\\\n\\\\r]+/g, ' ').slice(0, 200).trim();\n if (held) observedValue = held;\n }\n\n var record = {\n role: role,\n name: name,\n value: observedValue,\n bounds: bounds,\n state: state,\n labels: labels,\n attributes: attributes\n };\n if (parentIndex !== undefined) record.parentIndex = parentIndex;\n\n nodes.push(record);\n includedEls.push(el);\n }\n\n var docEl = doc.documentElement;\n return {\n nodes: nodes,\n viewport: { width: vw, height: vh },\n scroll: {\n offsetX: window.scrollX,\n offsetY: window.scrollY,\n contentWidth: docEl.scrollWidth,\n contentHeight: docEl.scrollHeight\n },\n url: location.href\n };\n})();\n`\n\n/**\n * Coerce one attacker-shaped in-page record into a trusted InterimNode (T-352-11).\n * `driver.execute` results are untrusted; a record without a usable string role is\n * dropped to typed-absence, never thrown into the builder loop.\n */\nfunction coerceWebInterimNode(value: unknown): InterimNode | null {\n if (!value || typeof value !== 'object') return null\n const v = value as Record<string, unknown>\n const role = coerceString(v.role)\n if (!role) return null\n\n const node: InterimNode = { role: role.toLowerCase(), attributes: coerceStringBag(v.attributes) }\n const name = coerceString(v.name)\n if (name) node.name = name\n const fieldValue = coerceString(v.value)\n if (fieldValue) node.value = fieldValue\n if (typeof v.parentIndex === 'number' && Number.isInteger(v.parentIndex) && v.parentIndex >= 0) {\n node.parentIndex = v.parentIndex\n }\n const bounds = coerceWebBounds(v.bounds)\n if (bounds) node.bounds = bounds\n const state = coerceWebState(v.state)\n if (state) node.state = state\n const labels = coerceWebLabels(v.labels)\n if (labels) node.labels = labels\n return node\n}\n\nfunction coerceString(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined\n}\n\nfunction coerceStringBag(value: unknown): Record<string, string> {\n const bag: Record<string, string> = {}\n if (!value || typeof value !== 'object') return bag\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n if (typeof v === 'string') bag[k] = v\n else if (typeof v === 'number' || typeof v === 'boolean') bag[k] = String(v)\n }\n return bag\n}\n\nfunction coerceWebBounds(value: unknown): { x: number; y: number; width: number; height: number } | undefined {\n if (!value || typeof value !== 'object') return undefined\n const v = value as Record<string, unknown>\n const { x, y, width, height } = v\n if (\n typeof x === 'number' && Number.isFinite(x) &&\n typeof y === 'number' && Number.isFinite(y) &&\n typeof width === 'number' && Number.isFinite(width) &&\n typeof height === 'number' && Number.isFinite(height)\n ) {\n return { x, y, width, height }\n }\n return undefined\n}\n\nfunction coerceWebState(value: unknown): Partial<ElementState> | undefined {\n if (!value || typeof value !== 'object') return undefined\n const v = value as Record<string, unknown>\n const state: Partial<ElementState> = {}\n if (typeof v.enabled === 'boolean') state.enabled = v.enabled\n if (typeof v.focused === 'boolean') state.focused = v.focused\n if (typeof v.visible === 'boolean') state.visible = v.visible\n if (typeof v.checked === 'boolean') state.checked = v.checked\n if (typeof v.selected === 'boolean') state.selected = v.selected\n return Object.keys(state).length > 0 ? state : undefined\n}\n\nfunction coerceWebLabels(value: unknown): ElementLabels | undefined {\n if (!value || typeof value !== 'object') return undefined\n const v = value as Record<string, unknown>\n const labels: ElementLabels = {}\n const testId = coerceString(v.testId)\n if (testId) labels.testId = testId\n const ariaLabel = coerceString(v.ariaLabel)\n if (ariaLabel) labels.ariaLabel = ariaLabel\n const placeholder = coerceString(v.placeholder)\n if (placeholder) labels.placeholder = placeholder\n const title = coerceString(v.title)\n if (title) labels.title = title\n return Object.keys(labels).length > 0 ? labels : undefined\n}\n\nfunction coerceViewport(\n value: unknown,\n fallback: { width: number; height: number },\n): { width: number; height: number } {\n if (value && typeof value === 'object') {\n const v = value as Record<string, unknown>\n const width = typeof v.width === 'number' && Number.isFinite(v.width) ? v.width : fallback.width\n const height = typeof v.height === 'number' && Number.isFinite(v.height) ? v.height : fallback.height\n return { width, height }\n }\n return fallback\n}\n\nfunction coerceWebScroll(\n value: unknown,\n viewport: { width: number; height: number },\n): { offsetX: number; offsetY: number; contentWidth: number; contentHeight: number } {\n const num = (x: unknown, fb: number): number => (typeof x === 'number' && Number.isFinite(x) ? x : fb)\n if (value && typeof value === 'object') {\n const v = value as Record<string, unknown>\n return {\n offsetX: num(v.offsetX, 0),\n offsetY: num(v.offsetY, 0),\n contentWidth: num(v.contentWidth, viewport.width),\n contentHeight: num(v.contentHeight, viewport.height),\n }\n }\n return { offsetX: 0, offsetY: 0, contentWidth: viewport.width, contentHeight: viewport.height }\n}\n\n/**\n * 2026-10-08 (436-12, live A1): a gesture that starts in a system gesture zone (the home and\n * recents bar at the bottom, the shade at the top, the back edges at the sides) is taken by\n * Android, not the app: the list does not move and scrollGesture answers false, which would read\n * as a boundary. The area is kept to the middle 60% of the screen on the swipe axis, where the\n * swipe ran before 436-02; an area wholly outside that band is used as it is.\n */\nfunction gestureArea(\n bounds: { x: number; y: number; width: number; height: number },\n direction: Direction,\n viewport: { width: number; height: number },\n): { x: number; y: number; width: number; height: number } {\n const vertical = direction === 'up' || direction === 'down'\n const length = vertical ? viewport.height : viewport.width\n const start = vertical ? bounds.y : bounds.x\n const end = start + (vertical ? bounds.height : bounds.width)\n const from = Math.max(start, Math.round(length * 0.2))\n const to = Math.min(end, Math.round(length * 0.8))\n if (to - from < 1) return bounds\n return vertical\n ? { ...bounds, y: from, height: to - from }\n : { ...bounds, x: from, width: to - from }\n}\n\nexport class AndroidPlatformAdapter implements PlatformAdapter<'android'> {\n readonly platform = 'android' as const\n\n private driver: WebdriverIO.Browser | null = null\n private lastRefs: MobileRefMap = {}\n private config: AndroidAdapterConfig | null = null\n // Tracks the active web context name (e.g. 'CHROMIUM', 'WEBVIEW_...').\n // null means last observation was native-only.\n private activeWebContext: string | null = null\n // Cached so we skip redundant switchContext round-trips.\n private currentContext: string | null = null\n private recordingCapability: RecordingCapability | undefined\n private liveStreamCapability: LiveStreamCapability | undefined\n private consoleLogs: ConsoleLogEntry[] = []\n private consoleDrainIndex = 0\n private captureConsole = true\n private appPackage: string | null = null\n private appPid: string | null = null\n // EXEC-03 session-cached app registry (D-10/D-12): enumerated once per session; null = not yet\n // enumerated (or enumeration failed and may be retried). Reset in cleanup().\n private appRegistry: AppRegistryEntry[] | null = null\n\n async setup(config: PlatformConfig): Promise<void> {\n this.config = config as AndroidAdapterConfig\n this.captureConsole = config.logCapture?.console !== false\n this.appPackage = this.config.appPackage ?? (config.device?.match?.appPackage as string | undefined) ?? null\n\n this.driver = await createAndroidSession(this.config, config.farmSession)\n\n const appPackage = this.appPackage\n if (appPackage && !this.config.browserName && !this.config.device?.match?.browserName) {\n let state: number | undefined\n try {\n state = await this.driver.queryAppState(appPackage)\n } catch {\n // The typed call's route is deprecated in Appium 3; the mobile command outlives it.\n try {\n const answer = await this.driver.execute('mobile: queryAppState', { appId: appPackage })\n if (typeof answer === 'number') state = answer\n } catch {\n state = undefined\n }\n }\n // D-11 (#566): activating a foreground app clears a deep link above a singleTask launcher.\n if (state !== 4) {\n try {\n await this.driver.activateApp(appPackage)\n } catch (err) {\n throw new MobileSetupError({\n category: 'app-launch',\n message: `Failed to launch Android app \"${appPackage}\": ${err instanceof Error ? err.message : String(err)}`,\n platform: 'android',\n deviceName: config.device?.name,\n appId: appPackage,\n cause: err,\n })\n }\n }\n }\n\n // Resolve app PID for logcat filtering only when explicitly enabled. Appium\n // 3 blocks mobile: shell unless the server is started with adb_shell enabled.\n if (process.env.AGENT_QA_ANDROID_USE_MOBILE_SHELL === '1' && this.appPackage && this.driver) {\n try {\n const result = String(await this.driver.execute('mobile: shell', { command: 'pidof', args: [this.appPackage] }))\n const pid = result?.trim()\n if (pid && /^\\d+$/.test(pid)) this.appPid = pid\n } catch {\n // mobile shell may be disabled — logs will be unfiltered\n }\n }\n\n }\n\n async cleanup(): Promise<void> {\n try { await this.recordingCapability?.stop() } catch { /* best-effort */ }\n this.recordingCapability = undefined\n try { await this.liveStreamCapability?.stop() } catch { /* best-effort */ }\n this.liveStreamCapability = undefined\n\n try {\n if (this.driver) {\n await this.driver.deleteSession()\n }\n } catch {\n // session may already be closed\n }\n this.driver = null\n this.lastRefs = {}\n this.config = null\n this.consoleLogs = []\n this.appPackage = null\n this.appPid = null\n this.appRegistry = null\n this.activeWebContext = null\n this.currentContext = null\n }\n\n // Whether we've ever successfully observed via a web context.\n // Once true, we know a WebView/browser exists and should retry rather than\n // falling back to native (which returns an opaque WebView and can crash UiAutomator2).\n private hasSeenWebContext = false\n\n async observe(_options?: ObserveOptions): Promise<ScreenState> {\n if (!this.driver) {\n throw new Error('AndroidPlatformAdapter not initialized — call setup() first')\n }\n\n // Dynamically detect web contexts (handles browserName sessions, native browser\n // apps like Chrome opened via appPackage, and hybrid apps with WebViews).\n const webState = await this.tryObserveWeb()\n if (webState) {\n this.hasSeenWebContext = true\n return webState\n }\n\n // If we previously had web content, the page is likely transitioning (navigation,\n // new tab, etc.). Wait for the web context to come back before giving up.\n if (this.hasSeenWebContext) {\n for (const delay of [2000, 3000]) {\n await this.driver.pause(delay)\n const retry = await this.tryObserveWeb()\n if (retry) return retry\n }\n }\n\n // No web context available — fall back to native XML observation.\n // Wrapped in try-catch because calling getPageSource() on Chrome's native\n // view hierarchy can crash UiAutomator2's instrumentation process.\n this.activeWebContext = null\n try {\n return await this.observeNative()\n } catch {\n this.lastRefs = {}\n // Schema-valid empty state (D-11 honest observe-time modality: textOnly) carrying\n // the diagnostic tree — no elements resolved, so refMap is empty (geometry rule).\n return {\n platform: 'android',\n tree: '(native observation unavailable — WebView content not accessible)',\n elements: [],\n refMap: {},\n timestamp: Date.now(),\n metadata: {\n captureMode: 'textOnly',\n coordSpace: 'viewport',\n viewportWidth: 0,\n viewportHeight: 0,\n scroll: { offsetX: 0, offsetY: 0, contentWidth: 0, contentHeight: 0 },\n },\n }\n }\n }\n\n async execute(action: ActionsFor<'android'>): Promise<ActionResult> {\n if (!this.driver) {\n throw new Error('AndroidPlatformAdapter not initialized — call setup() first')\n }\n\n try {\n // Ensure we're in the right context before acting\n if (this.activeWebContext) {\n await this.ensureContext(this.activeWebContext)\n }\n return await this.executeAction(action)\n } catch (err) {\n let screenshot: Buffer | undefined\n try {\n screenshot = await this.captureScreenshot()\n } catch {\n // ignore screenshot failure\n }\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n screenshot,\n }\n }\n }\n\n async screenshot(): Promise<Buffer | undefined> {\n if (this.activeWebContext) {\n await this.ensureContext(this.activeWebContext)\n } else {\n try { await this.ensureContext('NATIVE_APP') } catch { /* best-effort */ }\n }\n const buf = await this.captureScreenshot()\n if (buf && this.driver) {\n // D-19 / D-20 (Phase 138.1.1): Android screenshot dims differ from getWindowSize() on WebView\n // (1080x2274 image vs 411x810 viewport — ~6% vertical AR drift from URL bar, per D-13/D-14).\n // On native, dims match (1080x2400 == 1080x2400 getWindowSize). Phase 142 removed all\n // scaling code — coords are viewport-space identity. Log kept for diagnostics.\n try {\n // 363 D-08/Q10: sharp image utilities moved to runner-local (sharp left core).\n const { getImageDimensions } = await import('@vostride/agent-qa-runner-local')\n const dims = await getImageDimensions(buf)\n const { width } = await this.driver.getWindowSize()\n if (dims && Math.abs(dims.width - width) > 1) {\n // eslint-disable-next-line no-console\n console.warn(`[android-adapter] screenshot width ${dims.width} != window width ${width} (coord-space divergence, handled by scaleFactor per D-19/D-20)`)\n }\n } catch { /* best-effort assertion */ }\n }\n return buf\n }\n\n // ---------------------------------------------------------------------------\n // Device log capture\n // ---------------------------------------------------------------------------\n\n async pollDeviceLogs(): Promise<void> {\n if (!this.captureConsole) return\n if (!this.driver) return\n try {\n const logs = await this.driver.getLogs('logcat') as { message: string; timestamp?: number }[]\n for (const entry of logs) {\n const parsed = parseLogcatLine(entry.message, entry.timestamp ?? Date.now(), this.appPid)\n if (!parsed) continue\n this.consoleLogs.push(parsed)\n }\n if (this.consoleLogs.length > 1000) {\n this.consoleLogs = this.consoleLogs.slice(-500)\n }\n } catch {\n // getLogs may fail in some Appium configurations\n }\n }\n\n drainConsoleLogs(level?: string): ConsoleLogEntry[] {\n const newLogs = this.consoleLogs.slice(this.consoleDrainIndex)\n this.consoleDrainIndex = this.consoleLogs.length\n if (!level) return newLogs\n return newLogs.filter(e => e.level === level)\n }\n\n /**\n * 428 D-11: the labelled 1s snapshot preview, over `captureScreenshot()` — `takeScreenshot()`\n * and nothing else. Never `screenshot()`: that one switches the Appium context, and a tick\n * landing between a step's context switch and its command would run the command in the wrong\n * context. Declared before the driver exists (a capture then answers `undefined`), so the\n * composition's selection never falls through to `screenshot()`.\n */\n get liveStream(): LiveStreamCapability {\n this.liveStreamCapability ??= createSnapshotLiveStream({ capture: () => this.captureScreenshot() })\n return this.liveStreamCapability\n }\n\n get recording(): RecordingCapability | undefined {\n const driver = this.driver\n const config = this.config?.recording\n if (!driver || !config) return undefined\n if (this.recordingCapability) return this.recordingCapability\n let running = false\n let busy = false\n let needsCleanup = false\n async function recover() {\n if (!needsCleanup) return\n await driver!.stopRecordingScreen()\n needsCleanup = false\n }\n this.recordingCapability = {\n async start() {\n if (busy || running) throw new Error('Recording already started')\n busy = true\n try {\n await recover()\n const videoSize = config.videoSize\n ? `${config.videoSize.width}x${config.videoSize.height}`\n : undefined\n needsCleanup = true\n try {\n await driver.startRecordingScreen({ videoSize, timeLimit: 1800, forceRestart: true })\n } catch (error) {\n try { await recover() } catch { /* Retry driver cleanup before reuse. */ }\n throw error\n }\n needsCleanup = false\n running = true\n return {}\n } finally { busy = false }\n },\n async stop() {\n if (busy) throw new Error('Recording operation already in progress')\n busy = true\n try {\n if (!running) { await recover(); return undefined }\n running = false\n let base64Video: string\n try {\n base64Video = await driver.stopRecordingScreen()\n } catch (error) {\n needsCleanup = true\n try { await recover() } catch { /* Retry driver cleanup before reuse. */ }\n throw error\n }\n if (!base64Video) return undefined\n await mkdir(config.videoDir, { recursive: true })\n const stagingPath = join(config.videoDir, `${randomUUID()}.mp4`)\n try {\n await writeFile(stagingPath, Buffer.from(base64Video, 'base64'))\n } catch (error) {\n await rm(stagingPath, { force: true }).catch(() => undefined)\n throw error\n }\n return { stagingPath, contentType: 'video/mp4' }\n } finally { busy = false }\n },\n }\n return this.recordingCapability\n }\n\n // ---------------------------------------------------------------------------\n // Observation\n // ---------------------------------------------------------------------------\n\n private async tryObserveWeb(): Promise<ScreenState | null> {\n const driver = this.driver!\n try {\n const contexts = await driver.getContexts() as string[]\n const explicitBrowserMode = Boolean(this.config?.browserName || this.config?.device?.match?.browserName)\n const webCtx = contexts.find(c =>\n typeof c === 'string' && isTargetWebContext(c, this.appPackage, explicitBrowserMode)\n )\n if (!webCtx) return null\n\n await this.ensureContext(webCtx)\n\n // The in-page script returns a JSON-serializable interim-node payload — attacker-\n // shaped (T-352-11), so it is Array-guarded and every record/field is primitive-\n // coerced before entering the builder. No refs, no tree text cross the boundary.\n const raw = await driver.execute(WEB_OBSERVER_SCRIPT) as unknown\n if (!raw || typeof raw !== 'object') return null\n const payload = raw as Record<string, unknown>\n\n const rawNodes = payload.nodes\n if (!Array.isArray(rawNodes) || rawNodes.length === 0) return null\n\n const nodes: InterimNode[] = []\n for (const candidate of rawNodes) {\n const node = coerceWebInterimNode(candidate)\n if (node) nodes.push(node)\n }\n if (nodes.length === 0) return null\n\n const windowSize = await driver.getWindowSize()\n const viewport = coerceViewport(payload.viewport, { width: windowSize.width, height: windowSize.height })\n const scroll = coerceWebScroll(payload.scroll, viewport)\n const url = typeof payload.url === 'string' ? payload.url : undefined\n\n // Same builder pipeline as the native path — hybrid-app WebView runs share the one\n // schema type world. WebView contexts expose exact scroll (window/document reads).\n const { state, binding } = buildScreenState({\n platform: 'android',\n nodes,\n viewport,\n scroll,\n coordSpace: 'viewport',\n timestamp: Date.now(),\n ...(url !== undefined ? { url } : {}),\n })\n this.lastRefs = buildRefEntries(nodes, binding)\n this.activeWebContext = webCtx\n\n return state\n } catch {\n // Web observation failed — caller will fall back to native\n return null\n }\n }\n\n private async observeNative(): Promise<ScreenState> {\n const driver = this.driver!\n\n await this.ensureContext('NATIVE_APP')\n\n const [xml, viewport] = await Promise.all([\n driver.getPageSource(),\n driver.getWindowSize(),\n ])\n\n // The shared mobile walk emits platform-neutral interim nodes (352-04); the runner\n // builder mints refs, normalizes names, and renders the tree (D-01/D-02/D-03). Mobile\n // scroll is a documented best-effort approximation (D-10). Execute-time resolution\n // survives via buildRefEntries feeding the adapter-private lastRefs record.\n const { nodes } = parseMobileSource(xml, 'android', viewport)\n const scroll = deriveMobileScroll(nodes, viewport)\n const { state, binding } = buildScreenState({\n platform: 'android',\n nodes,\n viewport,\n scroll,\n coordSpace: 'viewport',\n timestamp: Date.now(),\n })\n this.lastRefs = buildRefEntries(nodes, binding)\n\n return state\n }\n\n // ---------------------------------------------------------------------------\n // Context management\n // ---------------------------------------------------------------------------\n\n private async ensureContext(target: string): Promise<void> {\n if (this.currentContext === target) return\n try {\n await this.driver!.switchContext(target)\n this.currentContext = target\n } catch {\n // If switch fails, clear cache so next call retries\n this.currentContext = null\n }\n }\n\n // ---------------------------------------------------------------------------\n // Screenshots\n // ---------------------------------------------------------------------------\n\n private async captureScreenshot(): Promise<Buffer | undefined> {\n try {\n if (this.driver) {\n const base64 = await this.driver.takeScreenshot()\n const buf = Buffer.from(base64, 'base64')\n if (!this.activeWebContext) return buf\n // 2026-10-19 (444.1-22, D-34): every capture in a WebView context, so the failure screenshot and the live preview are not black either.\n try {\n const { flattenOntoWhite } = await import('@vostride/agent-qa-runner-local')\n return await flattenOntoWhite(buf)\n } catch {\n return buf\n }\n }\n return undefined\n } catch {\n return undefined\n }\n }\n\n // ---------------------------------------------------------------------------\n // Compound behaviors (EXEC-01/02/03)\n // ---------------------------------------------------------------------------\n\n /** Read the live text of a focused element handle; undefined when nothing is readable. */\n private async readElementText(el: { getText: () => Promise<string> }): Promise<string | undefined> {\n try {\n const value = await el.getText()\n return typeof value === 'string' ? value : undefined\n } catch {\n return undefined\n }\n }\n\n private async focusedMatches(xpath: string): Promise<boolean> {\n try {\n return await (await this.driver!.$(xpath)).isExisting()\n } catch {\n return false\n }\n }\n\n /** An empty field's getText() returns its hint (437 Pitfall 4), so a showing hint reads ''. */\n private async readFocusedValue(el: { getText: () => Promise<string> }): Promise<string | undefined> {\n if (await this.focusedMatches(FOCUSED_HINT_XPATH)) return ''\n return await this.readElementText(el)\n }\n\n /**\n * The `mobile: shell` route of keyevent and openQuickSettings (437 D-18). A refusal by secure\n * Appium is recorded as unavailable and any other driver error as failed; neither is a pass.\n */\n private async runShell(\n verb: ShellActionMeta['verb'],\n args: { command: string; args: string[] },\n ): Promise<ActionResult> {\n try {\n await this.driver!.execute('mobile: shell', args)\n return { success: true }\n } catch (err) {\n if (isShellRefusal(err)) {\n const shellAction: ShellActionMeta = {\n verb,\n outcome: 'unavailable',\n reason: 'adb-shell-disabled',\n }\n return {\n success: false,\n error:\n `${verb} unavailable: Appium does not allow mobile: shell here (adb_shell is not `\n + 'enabled), so nothing was sent. Use pressBack, pressHome or keypress where they fit.',\n metadata: { shellAction },\n }\n }\n const detail = firstErrorLine(err)\n const shellAction: ShellActionMeta = { verb, outcome: 'failed', detail }\n return { success: false, error: `${verb} failed: ${detail}`, metadata: { shellAction } }\n }\n }\n\n /** The one submit mechanism on every Android path (437 D-13); pressed once, never retried. */\n private async pressEnter(): Promise<FillSubmitMeta> {\n try {\n await this.driver!.execute('mobile: pressKey', { keycode: ENTER_KEYCODE })\n return { sent: true, outcome: 'sent' }\n } catch (err) {\n return { sent: false, outcome: 'failed', detail: firstErrorLine(err) }\n }\n }\n\n /** 437 FA-2 (owner, 2026-10-08): line breaks into a single-line field are refused before typing. */\n private refuseLineBreaks(action: { submit: boolean }, box: TextBox): ActionResult {\n const fillRefusal: FillRefusalMeta = {\n verb: 'fill',\n cause: 'single-line-field',\n evidence: 'text-has-line-breaks',\n }\n return {\n success: false,\n error:\n 'fill: this field is single-line and the text has line breaks; nothing was typed. '\n + 'Send the text without line breaks, or use a multi-line field.',\n ...box,\n metadata: { fillRefusal, ...(action.submit ? { fillSubmit: { ...INPUT_FAILED } } : {}) },\n }\n }\n\n /**\n * Native fill from the focused handle (437 D-08..D-10, D-12, D-13, D-15, D-17). Delivers once\n * (addValue for append, setValue for replace), reads back from the same handle and records the\n * shared verdict. An unknown append prior or an unreadable read-back is unverified, which never\n * stops a requested Enter; a mismatch or a multi-line field holds it. A driver error during\n * delivery ends the fill: nothing is typed again and no Enter follows. A secure field yields\n * length sentinels only.\n */\n private async fillNativeCompound(\n el: FocusedField,\n action: { text: string; clearMode: 'replace' | 'append'; submit: boolean },\n box: TextBox,\n ): Promise<ActionResult> {\n const isAppend = action.clearMode === 'append'\n if (LINE_BREAK_RE.test(action.text) && await this.focusedMatches(FOCUSED_SINGLE_LINE_XPATH)) {\n return this.refuseLineBreaks(action, box)\n }\n const multiline = action.submit && await this.focusedMatches(FOCUSED_MULTILINE_XPATH)\n const secure = (await el.getAttribute('password').catch(() => null)) === 'true'\n const prior = isAppend ? await this.readFocusedValue(el) : ''\n\n try {\n if (isAppend) {\n await el.addValue(action.text)\n } else {\n await el.setValue(action.text)\n }\n } catch {\n return this.interruptedFill('native', secure, action, box)\n }\n\n const actual = prior === undefined ? undefined : await this.readFocusedValue(el)\n const verdict = compareFillReread({ expected: (prior ?? '') + action.text, actual, secure })\n return await this.settleFill(action, box, {\n path: 'native',\n verdict,\n multiline,\n enter: () => this.pressEnter(),\n })\n }\n\n /** The focused element handle, or undefined when UiAutomator2 reports none or the lookup fails. */\n private async focusedField(): Promise<FocusedField | undefined> {\n try {\n const el = await this.driver!.$(FOCUSED_XPATH)\n return (await el.isExisting()) ? el : undefined\n } catch {\n return undefined\n }\n }\n\n /**\n * 437 D-11 (WR-02): where the focused node is relative to the ref, judged by its read bounds.\n * An unreadable or unparseable value is no evidence, so the native path stays (D-04, D-15).\n * 444.1 D-07: 'elsewhere' needs positive evidence, the bounds of another observed field.\n */\n private async focusIsElsewhere(\n handle: FocusedField,\n ref: string,\n bounds: { x: number; y: number; width: number; height: number },\n ): Promise<FocusVerdict> {\n let raw: string | null\n try {\n raw = await handle.getAttribute('bounds')\n } catch {\n return 'target'\n }\n const focused = parseBoundsAttr(raw)\n if (focused === undefined || rectWithin(focused, bounds)) return 'target'\n for (const [other, entry] of Object.entries(this.lastRefs)) {\n if (other === ref || !entry.bounds) continue\n const field = entry.editable === true || ANDROID_FILLABLE_ROLES.has(entry.role.toLowerCase())\n if (field && rectWithin(focused, entry.bounds)) return 'elsewhere'\n }\n return 'moved'\n }\n\n /** Ctrl+A then DEL as key input; clears only the view holding input focus (437 D-14). */\n private async clearByKeys(): Promise<void> {\n await this.driver!.execute('mobile: pressKey', CTRL_A)\n await this.driver!.execute('mobile: pressKey', { keycode: DEL_KEYCODE })\n }\n\n /**\n * The last-resort keyboard path (437 D-14): the tap left no focused handle. Replace clears by\n * keys, the text goes through one `mobile: type` (Appium's Unicode IME, exact for every D-08\n * text), and the value is read back only when a focused handle can be found afterwards. An\n * append's prior value is unknown, so it is never better than unverified. The field's kind comes\n * from the observed input-type (D-15): only positive evidence refuses line breaks or holds Enter.\n */\n private async fillKeyboardPath(\n action: { text: string; clearMode: 'replace' | 'append'; submit: boolean },\n box: TextBox,\n refData: MobileRefMap[string] | undefined,\n ): Promise<ActionResult> {\n const isAppend = action.clearMode === 'append'\n const kind = fieldKindOf(refData)\n if (kind === 'single-line' && LINE_BREAK_RE.test(action.text)) {\n return this.refuseLineBreaks(action, box)\n }\n try {\n if (!isAppend) await this.clearByKeys()\n await this.driver!.execute('mobile: type', { text: action.text })\n } catch {\n return this.interruptedFill('keyboard', false, action, box)\n }\n\n const handle = await this.focusedField()\n let secure = false\n let actual: string | undefined\n if (handle) {\n secure = await this.isSecure(handle)\n if (!isAppend) actual = await this.readFocusedValue(handle)\n }\n const verdict = compareFillReread({ expected: action.text, actual, secure })\n return await this.settleFill(action, box, {\n path: 'keyboard',\n verdict,\n multiline: kind === 'multi-line',\n enter: () => this.pressEnter(),\n })\n }\n\n /**\n * Native and keyboard clearText (437 D-16): clearValue on the focused handle, or Ctrl+A then DEL\n * when the tap left none, then the hint-aware read-back judged against the empty string. The\n * caller has already checked that a focused handle is the referenced field (WR-02).\n */\n private async clearNativeOrKeyboard(\n box: TextBox,\n handle: FocusedField | undefined,\n ): Promise<ActionResult> {\n const path: InputPath = handle ? 'native' : 'keyboard'\n const before = handle ? await this.isSecure(handle) : false\n try {\n if (handle) await handle.clearValue()\n else await this.clearByKeys()\n } catch {\n return this.interruptedClear(path, before, box)\n }\n const readable = handle ?? (await this.focusedField())\n if (!readable) return this.settleClear(path, undefined, false, box)\n const secure = handle ? before : await this.isSecure(readable)\n return this.settleClear(path, await this.readFocusedValue(readable), secure, box)\n }\n\n private async isSecure(el: FocusedField): Promise<boolean> {\n return (await el.getAttribute('password').catch(() => null)) === 'true'\n }\n\n private settleClear(\n path: InputPath,\n actual: string | undefined,\n secure: boolean,\n box: TextBox,\n ): ActionResult {\n const verdict = compareFillReread({ expected: '', actual, secure, verb: 'clearText' })\n const fillVerdict: FillVerdictMeta = {\n verb: 'clearText',\n verdict: verdict.verdict,\n path,\n ...(verdict.secure ? { secure: true as const } : {}),\n }\n const metadata = { ...(verdict.meta ? { fillReread: verdict.meta } : {}), fillVerdict }\n return verdict.ok\n ? { success: true, ...box, metadata }\n : { success: false, error: verdict.selfCorrectingError, ...box, metadata }\n }\n\n /** A driver error while clearing ends the clear; it is never repeated. */\n private interruptedClear(path: InputPath, secure: boolean, box: TextBox): ActionResult {\n return {\n success: false,\n error:\n 'clearText was interrupted by a driver error; the field may be partly cleared, and it '\n + 'was not cleared again. Re-observe the field before clearing it again.',\n ...box,\n metadata: {\n fillVerdict: {\n verb: 'clearText',\n verdict: 'unverified',\n path,\n ...(secure ? { secure: true as const } : {}),\n },\n },\n }\n }\n\n /** A driver error during delivery ends the fill: nothing is typed again and no Enter follows. */\n private interruptedFill(\n path: InputPath,\n secure: boolean,\n action: { submit: boolean },\n box: TextBox,\n ): ActionResult {\n const fillVerdict: FillVerdictMeta = {\n verb: 'fill',\n verdict: 'unverified',\n path,\n ...(secure ? { secure: true as const } : {}),\n }\n return {\n success: false,\n error:\n 'fill: typing was interrupted by a driver error; the field may hold part of the text, '\n + 'and it was not typed again. Re-observe the field before filling it again.',\n ...box,\n metadata: { fillVerdict, ...(action.submit ? { fillSubmit: { ...INPUT_FAILED } } : {}) },\n }\n }\n\n /**\n * The shared end of every Android fill (437 D-09, D-10, D-13, D-15, D-17): records the verdict\n * and, when a submit was requested, holds Enter on a mismatch or a multi-line field and otherwise\n * presses it once through `enter`.\n */\n private async settleFill(\n action: { submit: boolean },\n box: TextBox,\n settle: {\n path: InputPath\n verdict: ReturnType<typeof compareFillReread>\n multiline: boolean\n enter: () => Promise<FillSubmitMeta>\n },\n ): Promise<ActionResult> {\n const { path, verdict, multiline, enter } = settle\n const fillVerdict: FillVerdictMeta = {\n verb: 'fill',\n verdict: verdict.verdict,\n path,\n ...(verdict.secure ? { secure: true as const } : {}),\n }\n\n let fillSubmit: FillSubmitMeta | undefined\n if (action.submit) {\n if (verdict.verdict === 'mismatch') {\n fillSubmit = { sent: false, outcome: 'not-sent', reason: 'mismatch' }\n } else if (multiline) {\n fillSubmit = { sent: false, outcome: 'not-sent', reason: 'multi-line-field' }\n } else {\n fillSubmit = await enter()\n }\n }\n const notice = fillSubmit?.reason === 'multi-line-field' ? { data: MULTI_LINE_SUBMIT_NOTICE } : {}\n const metadata = {\n ...(verdict.meta ? { fillReread: verdict.meta } : {}),\n fillVerdict,\n ...(fillSubmit ? { fillSubmit } : {}),\n }\n if (!verdict.ok) return { success: false, error: verdict.selfCorrectingError, ...box, metadata }\n if (fillSubmit?.outcome === 'failed') {\n return {\n success: false,\n error:\n 'fill typed the text, but Enter failed and was not sent again. Re-observe the screen; '\n + 'if the field still holds the text, submit it without typing it again.',\n ...box,\n metadata,\n }\n }\n return { success: true, ...box, ...notice, metadata }\n }\n\n /** A real W3C touch tap in the WebView context at the ref's CSS-pixel centre (437 D-11). */\n private async trustedWebTap(center: { x: number; y: number }): Promise<void> {\n await safePerform(this.driver!.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(center.x), y: Math.round(center.y), origin: 'viewport' })\n .down({ button: 0 })\n .up({ button: 0 })\n )\n }\n\n /** Whether the tap left an editable field focused at the ref's point; read-only. */\n private async probeWebFocus(center: { x: number; y: number }): Promise<WebFocus> {\n const none: WebFocus = { editable: false, matches: false, multiline: false, secure: false }\n try {\n const raw = await this.driver!.execute(\n WEB_FOCUS_PROBE_SCRIPT, Math.round(center.x), Math.round(center.y),\n ) as unknown as Record<string, unknown> | null\n if (!raw || typeof raw !== 'object') return none\n return {\n editable: raw.editable === true,\n matches: raw.matches === true,\n multiline: raw.multiline === true,\n secure: raw.secure === true,\n ...(typeof raw.value === 'string' ? { value: raw.value } : {}),\n }\n } catch {\n return none\n }\n }\n\n /** Polls the read-only probe until the tap's field holds focus; returns the last answer. */\n private async awaitWebFocus(center: { x: number; y: number }): Promise<WebFocus> {\n let focus = await this.probeWebFocus(center)\n for (let poll = 1; poll < WEB_FOCUS_POLLS && !(focus.editable && focus.matches); poll++) {\n await this.driver!.pause(WEB_FOCUS_POLL_MS)\n focus = await this.probeWebFocus(center)\n }\n return focus\n }\n\n private async readWebFieldValue(): Promise<string | undefined> {\n try {\n const value = await this.driver!.execute(WEB_FIELD_VALUE_SCRIPT) as unknown\n return typeof value === 'string' ? value : undefined\n } catch {\n return undefined\n }\n }\n\n /** Runs a driver call from NATIVE_APP and always returns to the active WebView context. */\n private async withNativeContext<T>(fn: () => Promise<T>): Promise<T> {\n await this.ensureContext('NATIVE_APP')\n try {\n return await fn()\n } finally {\n if (this.activeWebContext) await this.ensureContext(this.activeWebContext)\n }\n }\n\n /** 437 D-11: a tap that left no editable field, or another field, focused writes nothing. */\n private refuseFocus(\n verb: 'fill' | 'clearText',\n ref: string,\n focus: 'no-keyboard-focus' | 'focus-elsewhere' | Exclude<FocusVerdict, 'target'>,\n submit: boolean,\n box: TextBox,\n ): ActionResult {\n const nothing = verb === 'fill' ? 'nothing was typed' : 'nothing was cleared'\n let fillRefusal: FillRefusalMeta\n let error: string\n if (focus === 'moved') {\n fillRefusal = { verb, cause: 'target-not-found', evidence: 'stale-target' }\n error = `${verb}: after tapping ${ref}, the focused field is no longer where it was observed; `\n + `${nothing}. Re-observe and target the field where it is now.`\n } else if (focus === 'elsewhere') {\n fillRefusal = { verb, cause: 'not-editable', evidence: 'focus-elsewhere' }\n error = `${verb}: after tapping ${ref}, input focus is on another field; ${nothing}. `\n + 'Input is never sent to a field other than the target. Re-observe and target the field itself.'\n } else {\n fillRefusal = { verb, cause: 'not-editable', evidence: focus }\n error = `${verb}: the tap on ${ref} did not focus an editable field; ${nothing}. `\n + 'Target the input itself and try again.'\n }\n return {\n success: false,\n error,\n ...box,\n metadata: { fillRefusal, ...(submit ? { fillSubmit: { ...INPUT_FAILED } } : {}) },\n }\n }\n\n /**\n * WebView clearText (437 D-11, D-16): the same tap and focus probe as the fill, W3C Ctrl+A and\n * Backspace, then a read-back judged against the empty string. Never success without that check.\n */\n private async clearWebViewField(\n ref: string,\n center: { x: number; y: number },\n box: TextBox,\n ): Promise<ActionResult> {\n const driver = this.driver!\n await this.trustedWebTap(center)\n const focus = await this.awaitWebFocus(center)\n if (!focus.editable || !focus.matches) {\n return this.refuseFocus('clearText', ref, webFocusEvidence(focus), false, box)\n }\n try {\n await driver.keys(['Control', 'a'])\n await driver.keys(['Backspace'])\n } catch {\n return this.interruptedClear('webview', focus.secure, box)\n }\n return this.settleClear('webview', await this.readWebFieldValue(), focus.secure, box)\n }\n\n /**\n * WebView fill as trusted input (437 D-11): a W3C tap on the ref, a read-only focus probe,\n * W3C Ctrl+A and Backspace for replace, `mobile: type` from NATIVE_APP, a read-only read-back,\n * and one `mobile: pressKey 66` from NATIVE_APP. No script writes the field or fires an event.\n */\n private async fillWebViewCompound(\n action: { ref: string; text: string; clearMode: 'replace' | 'append'; submit: boolean },\n box: TextBox,\n center: { x: number; y: number },\n ): Promise<ActionResult> {\n const driver = this.driver!\n const isAppend = action.clearMode === 'append'\n await this.trustedWebTap(center)\n const focus = await this.awaitWebFocus(center)\n if (!focus.editable || !focus.matches) {\n return this.refuseFocus('fill', action.ref, webFocusEvidence(focus), action.submit, box)\n }\n if (!focus.multiline && LINE_BREAK_RE.test(action.text)) {\n return this.refuseLineBreaks(action, box)\n }\n const prior = isAppend ? focus.value : ''\n try {\n if (isAppend) {\n await driver.keys(focus.multiline ? ['Control', 'End'] : ['End'])\n } else {\n await driver.keys(['Control', 'a'])\n await driver.keys(['Backspace'])\n }\n await this.withNativeContext(() => driver.execute('mobile: type', { text: action.text }))\n } catch {\n return this.interruptedFill('webview', focus.secure, action, box)\n }\n const actual = prior === undefined ? undefined : await this.readWebFieldValue()\n const verdict = compareFillReread({\n expected: (prior ?? '') + action.text,\n actual,\n secure: focus.secure,\n })\n return await this.settleFill(action, box, {\n path: 'webview',\n verdict,\n multiline: focus.multiline,\n enter: () => this.withNativeContext(() => this.pressEnter()),\n })\n }\n\n /**\n * EXEC-02 platform primitives injected into the shared runner scroll loops (D-02/D-03; 436-02\n * D-25). A native swipe is `mobile: scrollGesture` over the container (the ref's bounds, else the\n * screen), whose boolean is the driver's own boundary signal; in a WebView the touch swipe is\n * measured over every WebView scroller before and after (436-18), paired by identity (436-23).\n * nativeSearchScroll drives the UiAutomator\n * `UiScrollable.scrollIntoView` rung over an injection-escaped selector; readInterimTree is a\n * light page-source parse — NO refMap mint, NO screenshot, lastRefs untouched.\n */\n private async buildAndroidScrollPrimitives(\n scrollDirection: Direction,\n maxSwipes: number,\n factor = 1,\n ): Promise<ScrollPrimitives> {\n const driver = this.driver!\n const viewport = await driver.getWindowSize()\n const axisLength = scrollDirection === 'left' || scrollDirection === 'right' ? viewport.width : viewport.height\n const distance = Math.max(1, Math.round(axisLength * 0.6 * factor))\n\n const webViewSwipe = async (direction: Direction, ref?: Ref): Promise<SwipeSignal> => {\n let sx = Math.round(viewport.width / 2)\n let sy = Math.round(viewport.height / 2)\n if (ref) {\n const { center } = new MobileElementResolver(this.lastRefs).resolve(ref)\n sx = Math.round(center.x)\n sy = Math.round(center.y)\n }\n const before = await this.readWebViewScrollers()\n const pts = computeSwipe(sx, sy, fingerDirectionFor(direction), distance)\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: pts.startX, y: pts.startY })\n .down({ button: 0 })\n .move({ x: pts.endX, y: pts.endY, duration: 300 })\n .up({ button: 0 })\n )\n const after = await this.readWebViewScrollers()\n return webViewSwipeSignal(direction, before, after)\n }\n\n return {\n swipeOnce: async (direction: Direction, ref?: Ref): Promise<SwipeSignal> => {\n if (this.activeWebContext) return webViewSwipe(direction, ref)\n const area = gestureArea(\n ref\n ? new MobileElementResolver(this.lastRefs).resolve(ref).bounds\n : { x: 0, y: 0, width: viewport.width, height: viewport.height },\n direction,\n viewport,\n )\n // A1 (436-RESEARCH), confirmed live by 436-12 on an emulator: true = moved and more remains,\n // false = the scrollable cannot go further.\n const canScrollMore = await driver.execute('mobile: scrollGesture', {\n left: Math.round(area.x),\n top: Math.round(area.y),\n width: Math.max(1, Math.round(area.width)),\n height: Math.max(1, Math.round(area.height)),\n direction,\n percent: 0.75 * factor,\n }) as unknown\n if (canScrollMore === true) return 'moved'\n if (canScrollMore === false) return 'at-boundary'\n return 'unknown'\n },\n nativeSearchScroll: async (target: string): Promise<boolean> => {\n // escapeUiSelectorText re-validates + escapes; a control char here throws and the loop\n // surfaces it (the case already rejected control chars up front, so this is escaping only).\n const escaped = escapeUiSelectorText(target)\n const selector =\n `new UiScrollable(new UiSelector().scrollable(true))`\n + `.scrollIntoView(new UiSelector().textContains(\"${escaped}\"))`\n try {\n await driver.execute('mobile: scroll', { strategy: '-android uiautomator', selector, maxSwipes })\n return true\n } catch {\n return false\n }\n },\n readInterimTree: async (): Promise<InterimNode[]> => {\n const xml = await driver.getPageSource()\n const { nodes } = parseMobileSource(xml, 'android', viewport)\n return nodes\n },\n }\n }\n\n /**\n * The WebView scrollers a touch swipe may have acted on (436-18 · D-25), read by the shared\n * WEBVIEW_SCROLLERS_SCRIPT. The touch point cannot be mapped into the WebView's CSS coordinates,\n * so the swipe is judged over all of them.\n * 2026-10-08 (436-23): a frame in view reads unknown; members carry an identity and are paired\n * by it; open shadow roots are walked; only on-screen element scrollers are members.\n */\n private async readWebViewScrollers(): Promise<IdentifiedScrollOffsets[] | undefined> {\n try {\n return parseWebViewScrollers(await this.driver!.execute(WEBVIEW_SCROLLERS_SCRIPT) as unknown)\n } catch {\n return undefined\n }\n }\n\n /**\n * EXEC-03 openApp (D-10/D-11/D-12). Resolve a human name to a package id (or validate an\n * explicit bundleId) over the session-cached registry, then launch via activateApp. On a\n * resolution MISS the registry is re-enumerated exactly once (catches mid-run installs) before\n * erroring with the resolver's candidate ids. Never a best-guess launch (T-359-04).\n */\n private async openApp(\n action: { appName: string } | { bundleId: string },\n ): Promise<ActionResult> {\n const driver = this.driver!\n let registry = await this.ensureAppRegistry()\n if (registry === null) {\n return {\n success: false,\n error:\n 'openApp could not enumerate installed apps: \"mobile: listApps\" failed and the '\n + 'shell fallback is disabled. Retry with an explicit openApp {bundleId}, or set '\n + 'AGENT_QA_ANDROID_USE_MOBILE_SHELL=1 to allow the pm-list fallback.',\n }\n }\n\n if ('bundleId' in action) {\n // Explicit variant: skip matching, validate membership against the cached registry.\n if (!registry.some((entry) => entry.id === action.bundleId)) {\n return {\n success: false,\n error: `openApp: bundleId \"${action.bundleId}\" is not installed (not in the app registry). Verify the package id or use openApp {appName}.`,\n }\n }\n await driver.activateApp(action.bundleId)\n return { success: true, metadata: { openApp: { resolvedId: action.bundleId, matchKind: 'explicit' } } }\n }\n\n let resolution = resolveAppName(action.appName, registry)\n if (resolution.kind === 'unknown' || resolution.kind === 'ambiguous') {\n // Re-enumerate exactly once on a MISS before erroring (D-12).\n const fresh = await this.enumerateApps()\n if (fresh !== null) {\n this.appRegistry = fresh\n registry = fresh\n resolution = resolveAppName(action.appName, registry)\n }\n }\n\n switch (resolution.kind) {\n case 'exact':\n case 'fuzzy':\n await driver.activateApp(resolution.id)\n return { success: true, metadata: { openApp: { resolvedId: resolution.id, matchKind: resolution.kind } } }\n case 'ambiguous':\n case 'unknown': {\n const ids = resolution.candidates.map((c) => c.id).join(', ')\n const lead =\n resolution.kind === 'ambiguous' ? 'is ambiguous between installed apps' : 'did not match an installed app'\n return {\n success: false,\n error: `openApp: \"${action.appName}\" ${lead}. Closest candidates: ${ids || '(none)'}. Retry openApp {bundleId} with the exact package id.`,\n }\n }\n }\n }\n\n /** Return the cached registry, enumerating once on first use. Failed enumeration returns null (uncached). */\n private async ensureAppRegistry(): Promise<AppRegistryEntry[] | null> {\n if (this.appRegistry !== null) return this.appRegistry\n const enumerated = await this.enumerateApps()\n if (enumerated !== null) this.appRegistry = enumerated\n return enumerated\n }\n\n /**\n * Enumerate installed apps through the driver only (ownership contract — no adb/child_process).\n * `mobile: listApps` maps package ids → AppRegistryEntry (labels only when the same call carries\n * them, D-10 — no per-package round-trips). On failure, fall back to `mobile: shell` pm-list ONLY\n * when the AGENT_QA_ANDROID_USE_MOBILE_SHELL gate is '1' (Pitfall 4). Null = enumeration unavailable.\n */\n private async enumerateApps(): Promise<AppRegistryEntry[] | null> {\n const driver = this.driver!\n try {\n const raw = await driver.execute('mobile: listApps')\n return this.mapListApps(raw)\n } catch {\n if (process.env.AGENT_QA_ANDROID_USE_MOBILE_SHELL === '1') {\n try {\n const out = String(await driver.execute('mobile: shell', { command: 'pm', args: ['list', 'packages'] }))\n return this.parsePmListPackages(out)\n } catch {\n return null\n }\n }\n return null\n }\n }\n\n /** Coerce a `mobile: listApps` result (package-id-keyed map, or an array of entries) into the registry. */\n private mapListApps(raw: unknown): AppRegistryEntry[] {\n const labelOf = (value: unknown): string | undefined => {\n if (!value || typeof value !== 'object') return undefined\n const v = value as Record<string, unknown>\n for (const key of ['label', 'name', 'appName']) {\n const candidate = v[key]\n if (typeof candidate === 'string' && candidate.length > 0) return candidate\n }\n return undefined\n }\n const entries: AppRegistryEntry[] = []\n if (Array.isArray(raw)) {\n for (const item of raw) {\n if (!item || typeof item !== 'object') continue\n const v = item as Record<string, unknown>\n const id = v.packageName ?? v.bundleId ?? v.id\n if (typeof id !== 'string' || id.length === 0) continue\n const label = labelOf(item)\n entries.push(label !== undefined ? { id, label } : { id })\n }\n } else if (raw && typeof raw === 'object') {\n for (const [id, value] of Object.entries(raw as Record<string, unknown>)) {\n if (!id) continue\n const label = labelOf(value)\n entries.push(label !== undefined ? { id, label } : { id })\n }\n }\n return entries\n }\n\n /** Parse `pm list packages` output (\"package:com.foo\\n…\") into id-only registry entries. */\n private parsePmListPackages(output: string): AppRegistryEntry[] {\n const entries: AppRegistryEntry[] = []\n for (const line of output.split('\\n')) {\n const id = line.trim().replace(/^package:/, '')\n if (id) entries.push({ id })\n }\n return entries\n }\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n\n private async executeAction(action: ActionsFor<'android'>): Promise<ActionResult> {\n const driver = this.driver!\n const resolver = new MobileElementResolver(this.lastRefs)\n const inWeb = !!this.activeWebContext\n\n switch (action.type) {\n case 'tap': {\n const { center, bounds } = resolver.resolve(action.ref)\n if (inWeb) {\n await driver.execute(\n 'var el = document.elementFromPoint(arguments[0], arguments[1]); if (el) el.click();',\n center.x, center.y,\n )\n } else {\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(center.x), y: Math.round(center.y) })\n .down({ button: 0 })\n .up({ button: 0 })\n )\n }\n return { success: true, coordinates: center, boundingBox: bounds }\n }\n\n case 'fill': {\n // EXEC-01 fill compound (D-05..D-08): tap-focus → clear/append → type → RE-READ the SAME\n // handle → (Enter keycode 66 if submit). ONE ActionResult carrying fillReread metadata;\n // a mismatch is an honest single-shot failure (no internal retry — the 358 ladder mediates).\n const { center, bounds } = resolver.resolve(action.ref)\n const refData = this.lastRefs[action.ref]\n const role = refData?.role?.toLowerCase()\n if (role && !ANDROID_FILLABLE_ROLES.has(role)) {\n return {\n success: false,\n error: `Element ${action.ref} is not fillable (role: ${role}). Use a textbox or input element instead.`,\n }\n }\n const box = { coordinates: center, boundingBox: bounds }\n if (inWeb) {\n return await this.fillWebViewCompound(action, box, center)\n }\n // Native fill — tap to focus, then run the compound from the focused-element handle.\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(center.x), y: Math.round(center.y) })\n .down({ button: 0 })\n .up({ button: 0 })\n )\n // 437-05 (2026-10-08, D-12): the path is chosen here, before any text is delivered.\n const focusedEl = await this.focusedField()\n const verdict = focusedEl ? await this.focusIsElsewhere(focusedEl, action.ref, bounds) : 'target'\n if (verdict !== 'target') {\n return this.refuseFocus('fill', action.ref, verdict, action.submit, box)\n }\n if (focusedEl) return await this.fillNativeCompound(focusedEl, action, box)\n return await this.fillKeyboardPath(action, box, refData)\n }\n\n case 'nativeSelect': {\n const { center, bounds } = resolver.resolve(action.ref)\n const refData = this.lastRefs[action.ref]\n if (!isAndroidNativeSelectTarget(refData)) {\n return {\n success: false,\n error: 'nativeSelect only supports native Android picker/dropdown/list controls. Use tap, swipe, or tapCoordinate for custom controls.',\n coordinates: center,\n boundingBox: bounds,\n }\n }\n\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(center.x), y: Math.round(center.y) })\n .down({ button: 0 })\n .up({ button: 0 })\n )\n\n const option = await findAndroidNativeOption(driver, action.value)\n if (!option) {\n return {\n success: false,\n error: `Could not find native Android option \"${action.value}\". Open the control with tap, then use swipe/tap/tapCoordinate for custom controls.`,\n coordinates: center,\n boundingBox: bounds,\n }\n }\n\n if (typeof option.element.click === 'function') {\n await option.element.click()\n } else {\n return {\n success: false,\n error: `Could not click native Android option \"${action.value}\". Use tap, swipe, or tapCoordinate for custom controls.`,\n coordinates: center,\n boundingBox: bounds,\n }\n }\n\n return {\n success: true,\n coordinates: center,\n boundingBox: bounds,\n data: {\n requestedValue: action.value,\n matchedValue: option.matchedValue,\n matchStrategy: option.matchStrategy,\n },\n }\n }\n\n case 'scroll': {\n // EXEC-02 scroll (D-02/D-03; 436-02 D-24/D-25): ONE ActionResult carrying scrollUntilVisible\n // metadata. untilVisible prefers the native UiScrollable rung (injection-escaped), then\n // bounded swipes with light page-source probes for target visibility; direction mode is one\n // gesture. Movement and boundaries come only from scrollGesture's result or WebView\n // offsets, never from interim-tree comparisons, and lastRefs is untouched (D-03).\n if (action.mode === 'untilVisible') {\n // Reject a hostile/control-char target up front — never interpolate it (Pitfall 9).\n try {\n escapeUiSelectorText(action.text)\n } catch (err) {\n return { success: false, error: err instanceof Error ? err.message : String(err) }\n }\n const primitives = await this.buildAndroidScrollPrimitives(action.direction, action.maxSwipes)\n const { meta } = await runUntilVisibleLoop(primitives, {\n target: action.text,\n direction: action.direction,\n maxSwipes: action.maxSwipes,\n retryOpposite: action.retryOpposite,\n ...(action.ref ? { ref: action.ref } : {}),\n })\n return { success: true, metadata: { scrollUntilVisible: meta } }\n }\n\n // direction mode: page / halfPage / toEnd.\n const factor = action.amount === 'halfPage' ? 0.5 : 1\n const primitives = await this.buildAndroidScrollPrimitives(action.direction, 0, factor)\n if (action.amount === 'toEnd') {\n const { meta } = await runToEndScroll(primitives, action.direction, action.ref)\n return { success: true, metadata: { scrollUntilVisible: meta } }\n }\n const { meta } = await runDirectionScroll(primitives, {\n direction: action.direction,\n ...(action.ref ? { ref: action.ref } : {}),\n })\n return { success: true, metadata: { scrollUntilVisible: meta } }\n }\n\n case 'swipe': {\n if (inWeb) {\n await this.ensureContext('NATIVE_APP')\n }\n const { width, height } = await driver.getWindowSize()\n\n // Schema shapes: SwipeByPath drives explicit from/to points; SwipeByDirection computes a\n // page-sized gesture from the (optional ref) center (legacy startX..endY reads retired).\n let pts: { startX: number; startY: number; endX: number; endY: number }\n if (action.mode === 'path') {\n pts = {\n startX: Math.round(action.from.x),\n startY: Math.round(action.from.y),\n endX: Math.round(action.to.x),\n endY: Math.round(action.to.y),\n }\n } else {\n let sx = Math.round(width / 2)\n let sy = Math.round(height / 2)\n if (action.ref) {\n const { center } = resolver.resolve(action.ref)\n sx = Math.round(center.x)\n sy = Math.round(center.y)\n }\n const distance = Math.round(height * 0.6)\n pts = computeSwipe(sx, sy, action.direction, distance)\n }\n warnIfOutOfBounds({ x: pts.startX, y: pts.startY }, { width, height }, 'swipe')\n warnIfOutOfBounds({ x: pts.endX, y: pts.endY }, { width, height }, 'swipe')\n const swipeDuration = action.durationMs\n\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: pts.startX, y: pts.startY })\n .down({ button: 0 })\n .move({ x: pts.endX, y: pts.endY, duration: swipeDuration })\n .up({ button: 0 })\n )\n if (inWeb) {\n await this.ensureContext(this.activeWebContext!)\n }\n return {\n success: true,\n startCoordinates: { x: pts.startX, y: pts.startY },\n endCoordinates: { x: pts.endX, y: pts.endY },\n }\n }\n\n case 'pinch': {\n const { width: pinchW, height: pinchH } = await driver.getWindowSize()\n let pcx = Math.round(pinchW / 2)\n let pcy = Math.round(pinchH / 2)\n\n if ('ref' in action) {\n const { center } = resolver.resolve(action.ref)\n pcx = Math.round(center.x)\n pcy = Math.round(center.y)\n } else {\n pcx = action.x\n pcy = action.y\n }\n warnIfOutOfBounds({ x: pcx, y: pcy }, { width: pinchW, height: pinchH }, 'pinch')\n\n const { finger1Start, finger1End, finger2Start, finger2End } = computePinch(pcx, pcy, action.scale)\n const pinchDuration = 500\n\n await driver.actions([\n driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(finger1Start.x), y: Math.round(finger1Start.y) })\n .down({ button: 0 })\n .move({ x: Math.round(finger1End.x), y: Math.round(finger1End.y), duration: pinchDuration })\n .up({ button: 0 }),\n driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(finger2Start.x), y: Math.round(finger2Start.y) })\n .down({ button: 0 })\n .move({ x: Math.round(finger2End.x), y: Math.round(finger2End.y), duration: pinchDuration })\n .up({ button: 0 }),\n ])\n return { success: true, coordinates: { x: pcx, y: pcy } }\n }\n\n case 'multiTap': {\n const { width: mtW, height: mtH } = await driver.getWindowSize()\n let mtcx = Math.round(mtW / 2)\n let mtcy = Math.round(mtH / 2)\n\n if ('ref' in action) {\n const { center } = resolver.resolve(action.ref)\n mtcx = Math.round(center.x)\n mtcy = Math.round(center.y)\n } else {\n mtcx = action.x\n mtcy = action.y\n }\n warnIfOutOfBounds({ x: mtcx, y: mtcy }, { width: mtW, height: mtH }, 'multiTap')\n\n const positions = computeFingerPositions(mtcx, mtcy, action.fingers)\n await driver.actions(\n positions.map(pos =>\n driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(pos.x), y: Math.round(pos.y) })\n .down({ button: 0 })\n .pause(100)\n .up({ button: 0 })\n )\n )\n return { success: true }\n }\n\n case 'longpress': {\n const { center } = resolver.resolve(action.ref)\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(center.x), y: Math.round(center.y) })\n .down({ button: 0 })\n .pause(action.duration ?? 1000)\n .up({ button: 0 })\n )\n return { success: true }\n }\n\n case 'waitFor': {\n // Schema on-modes replace the legacy {condition,timeout} blind pause. text/gone poll the\n // native accessibility tree; selector-mode is a web-only capability (§7.1, catalog pin).\n if (action.on === 'selector') {\n return {\n success: false,\n error: 'waitFor {on:\"selector\"} (CSS/XPath) is a web-only mode. On native Android, wait on visible text with waitFor {on:\"text\"} or {on:\"gone\"}.',\n }\n }\n const wantPresent = action.on === 'text'\n const needle = action.text\n const deadline = Date.now() + action.timeoutMs\n for (;;) {\n let source = ''\n try {\n source = await driver.getPageSource()\n } catch {\n source = ''\n }\n if (source.includes(needle) === wantPresent) return { success: true }\n if (Date.now() >= deadline) break\n await driver.pause(Math.min(250, Math.max(1, deadline - Date.now())))\n }\n return {\n success: false,\n error: wantPresent\n ? `waitFor: text \"${needle}\" did not appear within ${action.timeoutMs}ms.`\n : `waitFor: text \"${needle}\" was still present after ${action.timeoutMs}ms.`,\n }\n }\n\n case 'delay': {\n await driver.pause(action.ms)\n return { success: true }\n }\n\n case 'keypress': {\n // Schema adds mode:'press'|'down'|'up'. Only 'press' is meaningful on mobile — key\n // hold/release is a web-only lane (§7.1, catalog pin). convertPlatformKeys is a no-op on\n // mobile (no Meta/Control distinction in Appium key codes per D-13).\n if (action.mode !== 'press') {\n return {\n success: false,\n error: `keypress {mode:\"${action.mode}\"} (key hold/release) is web-only. On mobile, emit keypress {mode:\"press\"} to send the key.`,\n }\n }\n for (const rawKey of action.keys) {\n const mapped = KEY_MAP[rawKey] ?? rawKey\n await driver.keys([mapped])\n }\n return { success: true }\n }\n\n // --- New actions ---\n\n case 'hideKeyboard': {\n try {\n await driver.hideKeyboard()\n } catch {\n try { await driver.execute('mobile: pressKey', { keycode: 4 }) } catch { /* best-effort */ }\n }\n return { success: true }\n }\n\n case 'clearText': {\n const { center, bounds } = resolver.resolve(action.ref)\n const clearRefData = this.lastRefs[action.ref]\n const clearRole = clearRefData?.role?.toLowerCase()\n if (clearRole && !ANDROID_FILLABLE_ROLES.has(clearRole)) {\n return {\n success: false,\n error: `Element ${action.ref} is not fillable (role: ${clearRole}). clearText only works on text inputs. Use a textbox or input element instead.`,\n }\n }\n if (inWeb) {\n return await this.clearWebViewField(action.ref, center, {\n coordinates: center,\n boundingBox: bounds,\n })\n }\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(center.x), y: Math.round(center.y) })\n .down({ button: 0 })\n .up({ button: 0 })\n )\n const clearBox = { coordinates: center, boundingBox: bounds }\n const clearHandle = await this.focusedField()\n const clearVerdict = clearHandle\n ? await this.focusIsElsewhere(clearHandle, action.ref, bounds)\n : 'target'\n if (clearVerdict !== 'target') {\n return this.refuseFocus('clearText', action.ref, clearVerdict, false, clearBox)\n }\n return await this.clearNativeOrKeyboard(clearBox, clearHandle)\n }\n\n // --- Android hardware / system verbs (numeric keycodes / typed driver args only) ---\n\n case 'pressBack':\n await driver.execute('mobile: pressKey', { keycode: 4 })\n return { success: true }\n\n case 'pressHome':\n await driver.execute('mobile: pressKey', { keycode: 3 })\n return { success: true }\n\n case 'pressRecent':\n await driver.execute('mobile: pressKey', { keycode: 187 })\n return { success: true }\n\n case 'openNotifications':\n await driver.execute('mobile: openNotifications')\n return { success: true }\n\n case 'openQuickSettings':\n // args-array shell (A1) — never a concatenated command string (Pitfall 6).\n return await this.runShell('openQuickSettings', {\n command: 'cmd',\n args: ['statusbar', 'expand-settings'],\n })\n\n case 'intent': {\n // T-360-02 / Pitfall 6: map the schema fields onto TYPED mobile: startActivity args. Extras\n // become [[typeTag, key, value]] triples (string→s / int→i / long→l / float→f / bool→z);\n // planner-supplied values pass through byte-identical as typed args — NEVER interpolated\n // into an am-start shell string.\n const TYPE_TAG: Record<'string' | 'int' | 'long' | 'float' | 'bool', string> = {\n string: 's', int: 'i', long: 'l', float: 'f', bool: 'z',\n }\n const intentArgs: Record<string, unknown> = { action: action.action }\n if (action.data !== undefined) intentArgs.uri = action.data\n if (action.packageName !== undefined) intentArgs.package = action.packageName\n if (action.extras && action.extras.length > 0) {\n intentArgs.extras = action.extras.map(\n (e): [string, string, string] => [TYPE_TAG[e.type], e.key, e.value],\n )\n }\n await driver.execute('mobile: startActivity', intentArgs)\n return { success: true }\n }\n\n case 'keyevent': {\n // T-360-02: allow-list the symbolic code BEFORE any driver call (the 359 escapeUiSelectorText\n // posture). A non-matching (hostile) string is rejected with a §7.1 error — never reaches a\n // driver.execute. A matching code runs through an args-array shell lane (no interpolation).\n if (!/^KEYCODE_[A-Z0-9_]+$/.test(action.keycode)) {\n return {\n success: false,\n error: `keyevent: \"${action.keycode}\" is not a valid Android key code. Provide a symbolic code matching ^KEYCODE_[A-Z0-9_]+$ (e.g. KEYCODE_ENTER, KEYCODE_TAB).`,\n }\n }\n return await this.runShell('keyevent', {\n command: 'input',\n args: ['keyevent', action.keycode],\n })\n }\n\n case 'assertValue': {\n // D-10: the adapter RESOLVES the requested source to a raw value on ActionResult.data; the\n // runner-side comparator applies the op and judges. The adapter never compares. url/storage/\n // expr read the live WebView (web-context) machinery; sources with no native lane return a\n // §7.1 error naming the platform limitation.\n if ('expr' in action) {\n if (!inWeb) {\n return {\n success: false,\n error: 'assertValue {expr} evaluates JavaScript and is only available in an Android WebView/browser context. Assert on a native signal, or run against a web target.',\n }\n }\n const value = await driver.execute(`return (${action.expr});`)\n return { success: true, data: value }\n }\n switch (action.source) {\n case 'url': {\n if (!inWeb) {\n return {\n success: false,\n error: 'assertValue {source:\"url\"} reads the browser URL and is only available in an Android WebView/browser context; native screens have no URL.',\n }\n }\n const value = await driver.execute('return window.location.href;')\n return { success: true, data: value }\n }\n case 'storage': {\n if (!inWeb) {\n return {\n success: false,\n error: 'assertValue {source:\"storage\"} reads Web Storage and is only available in an Android WebView/browser context.',\n }\n }\n const value = await driver.execute(\n 'return Object.fromEntries(Object.keys(localStorage).map(function(k){return [k, localStorage.getItem(k)];}));',\n )\n return { success: true, data: value }\n }\n case 'network':\n return {\n success: false,\n error: 'assertValue {source:\"network\"} (HTTP log inspection) is not available on the Android adapter. Use a web target for network assertions, or assert on visible UI text.',\n }\n case 'expr-result':\n return { success: true, data: undefined }\n }\n }\n\n case 'drag': {\n const from = resolver.resolve(action.fromRef)\n const to = resolver.resolve(action.toRef)\n if (inWeb) await this.ensureContext('NATIVE_APP')\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(from.center.x), y: Math.round(from.center.y) })\n .down({ button: 0 })\n .pause(300)\n .move({ x: Math.round(to.center.x), y: Math.round(to.center.y), duration: 500 })\n .up({ button: 0 })\n )\n if (inWeb) await this.ensureContext(this.activeWebContext!)\n return { success: true }\n }\n\n case 'doubleTap': {\n const { center, bounds } = resolver.resolve(action.ref)\n const x = Math.round(center.x)\n const y = Math.round(center.y)\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x, y })\n .down({ button: 0 })\n .up({ button: 0 })\n .pause(50)\n .down({ button: 0 })\n .up({ button: 0 })\n )\n return { success: true, coordinates: center, boundingBox: bounds }\n }\n\n case 'openApp':\n // EXEC-03 (D-10/D-12): resolve a human app name (or validate an explicit bundleId) over a\n // session-cached registry, then launch via activateApp. Never a best-guess launch.\n return await this.openApp(action)\n\n case 'stopApp': {\n await driver.terminateApp(action.bundleId)\n return { success: true }\n }\n\n case 'setOrientation': {\n await driver.setOrientation(action.orientation === 'landscape' ? 'LANDSCAPE' : 'PORTRAIT')\n return { success: true }\n }\n\n case 'executeScript': {\n const result = await driver.execute(action.command, action.args ?? {})\n return { success: true, data: result }\n }\n\n case 'tapCoordinate': {\n const x = action.x\n const y = action.y\n const tcVp = await driver.getWindowSize()\n warnIfOutOfBounds({ x, y }, { width: tcVp.width, height: tcVp.height }, 'tapCoordinate')\n if (inWeb) {\n await driver.execute(\n 'var el = document.elementFromPoint(arguments[0], arguments[1]); if (el) el.click();',\n x, y,\n )\n } else {\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x, y })\n .down({ button: 0 })\n .up({ button: 0 })\n )\n }\n return { success: true, coordinates: { x, y } }\n }\n\n // Runner-minted / author-channel verbs (D-01/D-15): reportValue, assertAI, extractAI, and\n // setVariable are intercepted at the runner dispatch seam and never reach the adapter. A\n // grouped §7.1 defensive case surfaces a dispatch-routing error if one arrives here;\n // assertNever remains the backstop for a genuinely unknown schema verb. (uniqueValue is\n // web-only and is not part of ActionsFor<'android'>.)\n case 'reportValue':\n case 'assertAI':\n case 'extractAI':\n case 'setVariable':\n return {\n success: false,\n error: `Action \"${action.type}\" is handled by the runner dispatch seam and must not reach the Android adapter (runner-minted/author-channel verb). This indicates a dispatch routing error.`,\n }\n\n default:\n return assertNever(action)\n }\n }\n}\n","import { remote } from 'webdriverio'\nimport { MobileSetupError } from '@vostride/agent-qa-core'\nimport type { AndroidAdapterConfig } from './types.js'\n\nexport async function createAndroidSession(\n config: AndroidAdapterConfig,\n farmSession?: { hostname: string; port: number; path: string; capabilities: Record<string, unknown> },\n) {\n const match = config.device?.match ?? {}\n const appiumUrl = process.env.AGENT_QA_APPIUM_URL ?? config.appiumUrl ?? 'http://localhost:4723'\n const url = new URL(appiumUrl)\n\n const browserName = config.browserName ?? (match.browserName as string | undefined)\n const appPath = config.appPath\n if (browserName && appPath) {\n throw new MobileSetupError({\n category: 'app-install',\n message: 'Mobile browser mode cannot be combined with app.path',\n platform: 'android',\n deviceName: config.device?.name,\n appId: appPath,\n })\n }\n\n const appStateNoReset =\n config.appState === 'preserve' ? true :\n config.appState === 'reset' ? false :\n undefined\n\n const capabilities: Record<string, unknown> = {\n platformName: 'Android',\n 'appium:automationName': (match.automationName as string) ?? 'UiAutomator2',\n 'appium:deviceName': config.device?.name ?? 'Android Emulator',\n 'appium:newCommandTimeout': config.timeouts?.test ? Math.ceil(config.timeouts.test / 1000) : 300,\n 'appium:chromedriverAutodownload': true,\n }\n\n if (match.platformVersion) capabilities['appium:platformVersion'] = match.platformVersion\n if (match.serial) capabilities['appium:udid'] = match.serial\n if (match.avd) capabilities['appium:avd'] = match.avd\n if (config.avd) capabilities['appium:avd'] = config.avd\n if (appPath) capabilities['appium:app'] = appPath\n\n if (browserName) {\n capabilities.browserName = browserName\n capabilities['appium:autoWebview'] = true\n } else {\n if (appStateNoReset !== undefined) capabilities['appium:noReset'] = appStateNoReset\n if (match.appPackage) capabilities['appium:appPackage'] = match.appPackage\n if (config.appPackage) capabilities['appium:appPackage'] = config.appPackage\n if (match.appActivity) capabilities['appium:appActivity'] = match.appActivity\n if (config.appActivity) capabilities['appium:appActivity'] = config.appActivity\n }\n\n // Strip undefined values\n for (const key of Object.keys(capabilities)) {\n if (capabilities[key] === undefined) {\n delete capabilities[key]\n }\n }\n\n if (farmSession) {\n Object.assign(capabilities, farmSession.capabilities)\n return remote({\n protocol: 'https',\n hostname: farmSession.hostname,\n port: farmSession.port,\n path: farmSession.path,\n logLevel: config.verbose ? 'info' : 'silent',\n capabilities: capabilities as WebdriverIO.Capabilities,\n })\n }\n\n return remote({\n hostname: url.hostname,\n port: parseInt(url.port || '4723', 10),\n path: url.pathname === '/' ? '/' : url.pathname,\n logLevel: config.verbose ? 'info' : 'silent',\n capabilities: capabilities as WebdriverIO.Capabilities,\n })\n}\n"],"mappings":"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","names":["MobileSetupError","MobileSetupError","shellAction","primitives","meta"]}
1
+ {"version":3,"sources":["../src/adapter.ts","../src/session.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto'\nimport { mkdir, rm, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type {\n ActionsFor,\n ActionResult,\n AppRegistryEntry,\n ConsoleLogEntry,\n Direction,\n FillRefusalMeta,\n FillSubmitMeta,\n FillVerdictMeta,\n InterimNode,\n PlatformAdapter,\n LiveStreamCapability,\n PlatformConfig,\n RecordingCapability,\n ScrollPrimitives,\n ShellActionMeta,\n SwipeSignal,\n} from '@vostride/agent-qa-runner'\nimport {\n assertNever,\n buildScreenState,\n compareFillReread,\n createSnapshotLiveStream,\n resolveAppName,\n runDirectionScroll,\n runToEndScroll,\n runUntilVisibleLoop,\n} from '@vostride/agent-qa-runner'\nimport type { ElementLabels, ElementState, Ref, ScreenState } from '@vostride/agent-qa-schema'\nimport {\n KEY_MAP,\n MobileElementResolver,\n MobileSetupError,\n WEBVIEW_SCROLLERS_SCRIPT,\n buildRefEntries,\n computeFingerPositions,\n computePinch,\n computeSwipe,\n deriveMobileScroll,\n parseMobileSource,\n parseWebViewScrollers,\n warnIfOutOfBounds,\n webViewSwipeSignal,\n} from '@vostride/agent-qa-core'\nimport type { IdentifiedScrollOffsets, MobileRefMap } from '@vostride/agent-qa-core'\nimport { createAndroidSession } from './session.js'\nimport type { AndroidAdapterConfig } from './types.js'\n\nconst ANDROID_FILLABLE_ROLES = new Set(['textbox', 'searchbox', 'edittext', 'combobox'])\n\n// UiAutomator2 refuses getAttribute for showing-hint and multiline, so XPath reads them.\nconst FOCUSED_XPATH = '//*[@focused=\"true\"]'\nconst FOCUSED_HINT_XPATH = '//*[@focused=\"true\" and @showing-hint=\"true\"]'\nconst FOCUSED_MULTILINE_XPATH = '//*[@focused=\"true\" and @multiline=\"true\"]'\nconst FOCUSED_SINGLE_LINE_XPATH = '//*[@focused=\"true\" and @multiline=\"false\"]'\n// The focused node's `bounds` must lie within the ref's, within iOS's `RECT_TOLERANCE`.\nconst FOCUS_BOUNDS_TOLERANCE = 1\nconst ANDROID_BOUNDS_RE = /^\\[(-?\\d+),(-?\\d+)\\]\\[(-?\\d+),(-?\\d+)\\]$/\nconst ENTER_KEYCODE = 66\nconst CTRL_A = { keycode: 29, metastate: 0x1000 }\nconst DEL_KEYCODE = 67\nconst MULTI_LINE_SUBMIT_NOTICE =\n 'submit not sent: Return would add a new line in this multi-line field; tap its send or submit control'\nconst LINE_BREAK_RE = /[\\r\\n]/\n// The fixed @appium/base-driver text for a refused insecure feature.\nconst ADB_SHELL_REFUSAL = \"Potentially insecure feature 'adb_shell' has not been enabled\"\n\n// WebView page scripts only probe focus and read the value; they never write to the page.\nconst WEB_FOCUS_PROBE_SCRIPT =\n 'var a = document.activeElement;'\n + 'var hit = document.elementFromPoint(arguments[0], arguments[1]);'\n + 'if (!a) {'\n + ' return { editable: false, matches: false, multiline: false, secure: false, value: null };'\n + '}'\n + 'var tag = a.tagName;'\n + 'var type = tag === \"INPUT\" ? String(a.type || \"text\").toLowerCase() : \"\";'\n + 'var textual = [\"text\", \"search\", \"email\", \"url\", \"tel\", \"password\", \"number\"]'\n + '.indexOf(type) >= 0;'\n + 'var field = (tag === \"INPUT\" && textual) || tag === \"TEXTAREA\";'\n + 'var rich = !field && a.isContentEditable === true;'\n + 'var v = field ? a.value : (rich ? a.innerText : null);'\n + 'return {'\n + ' editable: (field && !a.readOnly && !a.disabled) || rich,'\n + ' matches: !!hit && (a === hit || a.contains(hit)),'\n + ' multiline: tag === \"TEXTAREA\" || rich,'\n + ' secure: type === \"password\",'\n + ' value: typeof v === \"string\" ? v : null'\n + '};'\n// Chromium moves focus a moment after the tap, so the probe is polled before the path refuses.\nconst WEB_FOCUS_POLLS = 3\nconst WEB_FOCUS_POLL_MS = 300\nconst WEB_FIELD_VALUE_SCRIPT =\n 'var a = document.activeElement;'\n + 'if (!a) { return null; }'\n + 'var v = (a.tagName === \"INPUT\" || a.tagName === \"TEXTAREA\") ? a.value'\n + ' : (a.isContentEditable ? a.innerText : null);'\n + 'return typeof v === \"string\" ? v : null;'\nconst ANDROID_NATIVE_SELECT_ROLES = new Set(['combobox', 'spinbutton', 'listbox', 'list'])\nconst ANDROID_NATIVE_SELECT_TYPES = new Set([\n 'android.widget.Spinner',\n 'android.widget.NumberPicker',\n 'android.widget.DatePicker',\n 'android.widget.TimePicker',\n 'android.widget.ListView',\n 'androidx.recyclerview.widget.RecyclerView',\n])\n\nasync function safePerform(chain: { perform: () => Promise<void> }): Promise<void> {\n try {\n await chain.perform()\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err)\n if (msg.includes('actions') && msg.includes('DELETE')) return\n throw err\n }\n}\n\nconst LOGCAT_REGEX = /^(\\d{2}-\\d{2})\\s+(\\d{2}:\\d{2}:\\d{2}\\.\\d{3})\\s+(\\d+)\\s+(\\d+)\\s+([VDIWEF])\\s+(.+?)\\s*:\\s+(.*)/\n\nconst ANDROID_LEVEL_MAP: Record<string, string> = {\n V: 'debug',\n D: 'debug',\n I: 'info',\n W: 'warn',\n E: 'error',\n F: 'error',\n}\n\nfunction firstNonEmpty(...values: Array<string | null | undefined>): string | undefined {\n for (const value of values) {\n const trimmed = typeof value === 'string' ? value.trim() : ''\n if (trimmed) return trimmed\n }\n return undefined\n}\n\ntype TextBox = {\n coordinates: { x: number; y: number }\n boundingBox: { x: number; y: number; width: number; height: number }\n}\n\ntype FocusedField = {\n getText: () => Promise<string>\n getAttribute: (name: string) => Promise<string | null>\n setValue: (value: string) => Promise<void>\n addValue: (value: string) => Promise<void>\n clearValue: () => Promise<void>\n}\n\ntype WebFocus = {\n editable: boolean\n matches: boolean\n multiline: boolean\n secure: boolean\n value?: string\n}\n\ntype InputPath = NonNullable<FillVerdictMeta['path']>\n\nconst INPUT_FAILED: FillSubmitMeta = { sent: false, outcome: 'not-sent', reason: 'input-failed' }\n\ntype FieldKind = 'single-line' | 'multi-line' | 'unknown'\n\n// Android InputType: the low nibble is the class (1 = text); 0x20000 is TYPE_TEXT_FLAG_MULTI_LINE.\nfunction fieldKindOf(refData: MobileRefMap[string] | undefined): FieldKind {\n const inputType = refData?.inputType\n if (inputType === undefined || (inputType & 0xf) === 0) return 'unknown'\n if ((inputType & 0xf) === 1 && (inputType & 0x20000) !== 0) return 'multi-line'\n return 'single-line'\n}\n\ntype Rect = { x: number; y: number; width: number; height: number }\n\ntype FocusVerdict = 'target' | 'elsewhere' | 'moved'\n\nfunction webFocusEvidence(focus: WebFocus): 'no-keyboard-focus' | 'focus-elsewhere' {\n return focus.editable ? 'focus-elsewhere' : 'no-keyboard-focus'\n}\n\nfunction parseBoundsAttr(value: unknown): Rect | undefined {\n if (typeof value !== 'string') return undefined\n const match = ANDROID_BOUNDS_RE.exec(value.trim())\n if (!match) return undefined\n const [left, top, right, bottom] = match.slice(1).map(Number) as [number, number, number, number]\n return { x: left, y: top, width: right - left, height: bottom - top }\n}\n\nfunction rectWithin(inner: Rect, outer: Rect): boolean {\n return inner.x >= outer.x - FOCUS_BOUNDS_TOLERANCE\n && inner.y >= outer.y - FOCUS_BOUNDS_TOLERANCE\n && inner.x + inner.width <= outer.x + outer.width + FOCUS_BOUNDS_TOLERANCE\n && inner.y + inner.height <= outer.y + outer.height + FOCUS_BOUNDS_TOLERANCE\n}\n\nfunction firstErrorLine(err: unknown): string {\n const message = err instanceof Error ? err.message : String(err)\n return message.split('\\n')[0]!.trim()\n}\n\nfunction isShellRefusal(err: unknown): boolean {\n return (err instanceof Error ? err.message : String(err)).includes(ADB_SHELL_REFUSAL)\n}\n\nfunction isAndroidWebContextName(context: string): boolean {\n const normalized = context.toUpperCase()\n return normalized.includes('CHROMIUM') || normalized.includes('WEBVIEW')\n}\n\nfunction isTargetWebContext(context: string, appPackage: string | null, explicitBrowserMode: boolean): boolean {\n if (explicitBrowserMode) return isAndroidWebContextName(context)\n if (!appPackage) return false\n return context.toLowerCase().includes(appPackage.toLowerCase())\n}\n\nfunction isAndroidNativeSelectTarget(refData: MobileRefMap[string] | undefined): boolean {\n const role = refData?.role?.toLowerCase()\n return Boolean(\n (role && ANDROID_NATIVE_SELECT_ROLES.has(role))\n || (refData?.nativeType && ANDROID_NATIVE_SELECT_TYPES.has(refData.nativeType))\n )\n}\n\n// Backslashes escape first, then quotes, so text never leaves the `textContains` literal.\nconst CONTROL_CHAR_RE = /[\\u0000-\\u001F\\u007F]/\nfunction escapeUiSelectorText(value: string): string {\n if (CONTROL_CHAR_RE.test(value)) {\n throw new Error(\n `scroll target contains a control character and cannot be used as a UiAutomator selector — provide a plain-text target for untilVisible.`,\n )\n }\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')\n}\n\n/** Scroll intent (reveal content toward `direction`) maps to the OPPOSITE finger swipe. */\nfunction fingerDirectionFor(scroll: Direction): 'up' | 'down' | 'left' | 'right' {\n switch (scroll) {\n case 'up':\n return 'down'\n case 'down':\n return 'up'\n case 'left':\n return 'right'\n case 'right':\n return 'left'\n }\n}\n\nfunction androidUiSelectorText(value: string): string {\n return `android=new UiSelector().text(${JSON.stringify(value)})`\n}\n\nfunction androidUiSelectorDescription(value: string): string {\n return `android=new UiSelector().description(${JSON.stringify(value)})`\n}\n\nasync function findAndroidNativeOption(\n driver: WebdriverIO.Browser,\n value: string,\n): Promise<{ element: any; matchedValue: string; matchStrategy: 'text' | 'description' } | null> {\n for (const [selector, matchStrategy] of [\n [androidUiSelectorText(value), 'text'],\n [androidUiSelectorDescription(value), 'description'],\n ] as const) {\n try {\n const element = await driver.$(selector)\n if (await element.isExisting()) {\n return { element, matchedValue: value, matchStrategy }\n }\n } catch {\n // Try the next exact selector.\n }\n }\n return null\n}\n\nfunction parseLogcatLine(message: string, timestamp: number, appPid: string | null): ConsoleLogEntry | null {\n const match = message.match(LOGCAT_REGEX)\n if (!match) return null\n const [, , , pid, , levelChar, tag, text] = match\n if (appPid && pid !== appPid) return null\n return {\n level: ANDROID_LEVEL_MAP[levelChar] ?? 'debug',\n text: `[${tag.trim()}] ${text.trim()}`,\n timestamp,\n }\n}\n\n// A string, because it runs in the page and the Node tsconfig has no DOM lib.\nconst WEB_OBSERVER_SCRIPT = `\nreturn (function() {\n var TAG_ROLES = {\n A: 'link', BUTTON: 'button', INPUT: 'textbox', TEXTAREA: 'textbox',\n SELECT: 'combobox', H1: 'heading', H2: 'heading', H3: 'heading',\n H4: 'heading', H5: 'heading', H6: 'heading', IMG: 'image'\n };\n\n var doc = document;\n var vw = window.innerWidth;\n var vh = window.innerHeight;\n var active = doc.activeElement;\n\n var all = doc.querySelectorAll(\n 'a, button, input, textarea, select, h1, h2, h3, h4, h5, h6, img[alt], [role], [contenteditable]:not([contenteditable=\"false\"])'\n );\n\n var nodes = [];\n var includedEls = [];\n var seen = {};\n var CAPTION_TYPES = { submit: true, button: true, reset: true };\n var VALUELESS_TYPES = {\n password: true, checkbox: true, radio: true, submit: true, button: true, reset: true,\n image: true, file: true, hidden: true, range: true, color: true\n };\n\n function textOf(node) {\n return node ? (node.textContent || '').trim() : '';\n }\n\n // A field is named by its label, not its value; a wrapping label drops the field's own text.\n function labelText(el, label) {\n var text = label.textContent || '';\n var own = el.textContent || '';\n if (own && label.contains(el)) text = text.replace(own, '');\n return text.trim();\n }\n\n function fieldName(el, tag) {\n var ids = (el.getAttribute('aria-labelledby') || '').split(' ');\n var parts = [];\n for (var j = 0; j < ids.length; j++) {\n var part = ids[j] ? textOf(doc.getElementById(ids[j])) : '';\n if (part) parts.push(part);\n }\n if (parts.length > 0) return parts.join(' ');\n var label = el.labels && el.labels.length > 0 ? labelText(el, el.labels[0]) : '';\n if (label) return label;\n var hint = el.getAttribute('placeholder') || el.getAttribute('title');\n if (hint) return hint;\n if (tag === 'INPUT' && CAPTION_TYPES[String(el.type).toLowerCase()]) return el.value || '';\n return '';\n }\n\n // The nearest included ancestor: structural and skipped nodes collapse, as on mobile and web.\n function nearestAncestorIndex(el) {\n var p = el.parentElement;\n while (p) {\n var idx = includedEls.indexOf(p);\n if (idx !== -1) return idx;\n p = p.parentElement;\n }\n return undefined;\n }\n\n for (var i = 0; i < all.length; i++) {\n var el = all[i];\n var rect = el.getBoundingClientRect();\n if (rect.width === 0 && rect.height === 0) continue;\n\n var style = window.getComputedStyle(el);\n if (style.display === 'none' || style.visibility === 'hidden') continue;\n\n var tag = el.tagName;\n // Only the outermost content-editable element is an editor; its descendants are ordinary nodes.\n var host = el.isContentEditable === true\n && !(el.parentElement && el.parentElement.isContentEditable === true);\n var ariaRole = el.getAttribute('role');\n var role = (ariaRole || TAG_ROLES[tag] || (host ? 'textbox' : '')).toLowerCase();\n if (!role) continue;\n\n var field = tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT';\n var editable = field || host;\n var textual = role === 'textbox' || role === 'searchbox' || role === 'combobox';\n var name = '';\n var ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) {\n name = ariaLabel;\n } else if (tag === 'IMG') {\n name = el.alt || '';\n } else if (editable || textual) {\n name = fieldName(el, tag) || el.getAttribute('aria-placeholder') || '';\n } else {\n name = (el.textContent || '').trim();\n }\n\n name = name.slice(0, 100).replace(/[\\\\n\\\\r]+/g, ' ').trim();\n if (!name && !editable && !textual) continue;\n\n if (!editable && !textual) {\n var key = role + ':' + name;\n if (seen[key]) continue;\n seen[key] = true;\n }\n\n var bounds = {\n x: Math.round(rect.left),\n y: Math.round(rect.top),\n width: Math.round(rect.width),\n height: Math.round(rect.height)\n };\n\n // Real DOM state signals only; the builder derives every default.\n var state = {};\n var disabled = el.disabled === true\n || el.hasAttribute('disabled')\n || el.getAttribute('aria-disabled') === 'true';\n state.enabled = !disabled;\n state.focused = el === active;\n if (bounds.y + bounds.height < 0 || bounds.y > vh) state.visible = false;\n if (tag === 'INPUT' && (el.type === 'checkbox' || el.type === 'radio')) {\n state.checked = el.checked === true;\n }\n\n var labels = {};\n var testId = el.getAttribute('data-testid');\n if (testId) labels.testId = testId;\n if (ariaLabel) labels.ariaLabel = ariaLabel;\n var placeholder = el.getAttribute('placeholder');\n if (placeholder) labels.placeholder = placeholder;\n var title = el.getAttribute('title');\n if (title) labels.title = title;\n\n var attributes = {};\n if (el.type) attributes.type = String(el.type);\n\n var parentIndex = nearestAncestorIndex(el);\n\n // What a field or an editor holds is its value, never its name; a password has no value here.\n var observedValue = undefined;\n var textEntry = tag === 'TEXTAREA' || (tag === 'INPUT' && !VALUELESS_TYPES[String(el.type).toLowerCase()]);\n if (textEntry && el.value) {\n observedValue = String(el.value).slice(0, 200);\n } else if (tag === 'SELECT') {\n var option = el.options && el.selectedIndex >= 0 ? el.options[el.selectedIndex] : null;\n var optionText = option ? String(option.text || '').trim().slice(0, 200) : '';\n if (optionText) observedValue = optionText;\n } else if (host || (textual && !field)) {\n var held = textOf(el).replace(/[\\\\n\\\\r]+/g, ' ').slice(0, 200).trim();\n if (held) observedValue = held;\n }\n\n var record = {\n role: role,\n name: name,\n value: observedValue,\n bounds: bounds,\n state: state,\n labels: labels,\n attributes: attributes\n };\n if (parentIndex !== undefined) record.parentIndex = parentIndex;\n\n nodes.push(record);\n includedEls.push(el);\n }\n\n var docEl = doc.documentElement;\n return {\n nodes: nodes,\n viewport: { width: vw, height: vh },\n scroll: {\n offsetX: window.scrollX,\n offsetY: window.scrollY,\n contentWidth: docEl.scrollWidth,\n contentHeight: docEl.scrollHeight\n },\n url: location.href\n };\n})();\n`\n\n// `driver.execute` results are untrusted; a record without a string role is dropped, not thrown.\nfunction coerceWebInterimNode(value: unknown): InterimNode | null {\n if (!value || typeof value !== 'object') return null\n const v = value as Record<string, unknown>\n const role = coerceString(v.role)\n if (!role) return null\n\n const node: InterimNode = { role: role.toLowerCase(), attributes: coerceStringBag(v.attributes) }\n const name = coerceString(v.name)\n if (name) node.name = name\n const fieldValue = coerceString(v.value)\n if (fieldValue) node.value = fieldValue\n if (typeof v.parentIndex === 'number' && Number.isInteger(v.parentIndex) && v.parentIndex >= 0) {\n node.parentIndex = v.parentIndex\n }\n const bounds = coerceWebBounds(v.bounds)\n if (bounds) node.bounds = bounds\n const state = coerceWebState(v.state)\n if (state) node.state = state\n const labels = coerceWebLabels(v.labels)\n if (labels) node.labels = labels\n return node\n}\n\nfunction coerceString(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined\n}\n\nfunction coerceStringBag(value: unknown): Record<string, string> {\n const bag: Record<string, string> = {}\n if (!value || typeof value !== 'object') return bag\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n if (typeof v === 'string') bag[k] = v\n else if (typeof v === 'number' || typeof v === 'boolean') bag[k] = String(v)\n }\n return bag\n}\n\nfunction coerceWebBounds(value: unknown): { x: number; y: number; width: number; height: number } | undefined {\n if (!value || typeof value !== 'object') return undefined\n const v = value as Record<string, unknown>\n const { x, y, width, height } = v\n if (\n typeof x === 'number' && Number.isFinite(x) &&\n typeof y === 'number' && Number.isFinite(y) &&\n typeof width === 'number' && Number.isFinite(width) &&\n typeof height === 'number' && Number.isFinite(height)\n ) {\n return { x, y, width, height }\n }\n return undefined\n}\n\nfunction coerceWebState(value: unknown): Partial<ElementState> | undefined {\n if (!value || typeof value !== 'object') return undefined\n const v = value as Record<string, unknown>\n const state: Partial<ElementState> = {}\n if (typeof v.enabled === 'boolean') state.enabled = v.enabled\n if (typeof v.focused === 'boolean') state.focused = v.focused\n if (typeof v.visible === 'boolean') state.visible = v.visible\n if (typeof v.checked === 'boolean') state.checked = v.checked\n if (typeof v.selected === 'boolean') state.selected = v.selected\n return Object.keys(state).length > 0 ? state : undefined\n}\n\nfunction coerceWebLabels(value: unknown): ElementLabels | undefined {\n if (!value || typeof value !== 'object') return undefined\n const v = value as Record<string, unknown>\n const labels: ElementLabels = {}\n const testId = coerceString(v.testId)\n if (testId) labels.testId = testId\n const ariaLabel = coerceString(v.ariaLabel)\n if (ariaLabel) labels.ariaLabel = ariaLabel\n const placeholder = coerceString(v.placeholder)\n if (placeholder) labels.placeholder = placeholder\n const title = coerceString(v.title)\n if (title) labels.title = title\n return Object.keys(labels).length > 0 ? labels : undefined\n}\n\nfunction coerceViewport(\n value: unknown,\n fallback: { width: number; height: number },\n): { width: number; height: number } {\n if (value && typeof value === 'object') {\n const v = value as Record<string, unknown>\n const width = typeof v.width === 'number' && Number.isFinite(v.width) ? v.width : fallback.width\n const height = typeof v.height === 'number' && Number.isFinite(v.height) ? v.height : fallback.height\n return { width, height }\n }\n return fallback\n}\n\nfunction coerceWebScroll(\n value: unknown,\n viewport: { width: number; height: number },\n): { offsetX: number; offsetY: number; contentWidth: number; contentHeight: number } {\n const num = (x: unknown, fb: number): number => (typeof x === 'number' && Number.isFinite(x) ? x : fb)\n if (value && typeof value === 'object') {\n const v = value as Record<string, unknown>\n return {\n offsetX: num(v.offsetX, 0),\n offsetY: num(v.offsetY, 0),\n contentWidth: num(v.contentWidth, viewport.width),\n contentHeight: num(v.contentHeight, viewport.height),\n }\n }\n return { offsetX: 0, offsetY: 0, contentWidth: viewport.width, contentHeight: viewport.height }\n}\n\n// A gesture starting in a system gesture zone moves nothing, so keep to the middle 60% of the axis.\nfunction gestureArea(\n bounds: { x: number; y: number; width: number; height: number },\n direction: Direction,\n viewport: { width: number; height: number },\n): { x: number; y: number; width: number; height: number } {\n const vertical = direction === 'up' || direction === 'down'\n const length = vertical ? viewport.height : viewport.width\n const start = vertical ? bounds.y : bounds.x\n const end = start + (vertical ? bounds.height : bounds.width)\n const from = Math.max(start, Math.round(length * 0.2))\n const to = Math.min(end, Math.round(length * 0.8))\n if (to - from < 1) return bounds\n return vertical\n ? { ...bounds, y: from, height: to - from }\n : { ...bounds, x: from, width: to - from }\n}\n\nexport class AndroidPlatformAdapter implements PlatformAdapter<'android'> {\n readonly platform = 'android' as const\n\n private driver: WebdriverIO.Browser | null = null\n private lastRefs: MobileRefMap = {}\n private config: AndroidAdapterConfig | null = null\n // Tracks the active web context name (e.g. 'CHROMIUM', 'WEBVIEW_...').\n // null means last observation was native-only.\n private activeWebContext: string | null = null\n // Cached so we skip redundant switchContext round-trips.\n private currentContext: string | null = null\n private recordingCapability: RecordingCapability | undefined\n private liveStreamCapability: LiveStreamCapability | undefined\n private consoleLogs: ConsoleLogEntry[] = []\n private consoleDrainIndex = 0\n private captureConsole = true\n private appPackage: string | null = null\n private appPid: string | null = null\n // Enumerated once per session; `null` is not yet enumerated or retryable; reset in `cleanup()`.\n private appRegistry: AppRegistryEntry[] | null = null\n\n async setup(config: PlatformConfig): Promise<void> {\n this.config = config as AndroidAdapterConfig\n this.captureConsole = config.logCapture?.console !== false\n this.appPackage = this.config.appPackage ?? (config.device?.match?.appPackage as string | undefined) ?? null\n\n this.driver = await createAndroidSession(this.config)\n\n const appPackage = this.appPackage\n if (appPackage && !this.config.browserName && !this.config.device?.match?.browserName) {\n let state: number | undefined\n try {\n state = await this.driver.queryAppState(appPackage)\n } catch {\n // The typed call's route is deprecated in Appium 3; the mobile command outlives it.\n try {\n const answer = await this.driver.execute('mobile: queryAppState', { appId: appPackage })\n if (typeof answer === 'number') state = answer\n } catch {\n state = undefined\n }\n }\n // Activating a foreground app clears a deep link above a singleTask launcher.\n if (state !== 4) {\n try {\n await this.driver.activateApp(appPackage)\n } catch (err) {\n throw new MobileSetupError({\n category: 'app-launch',\n message: `Failed to launch Android app \"${appPackage}\": ${err instanceof Error ? err.message : String(err)}`,\n platform: 'android',\n deviceName: config.device?.name,\n appId: appPackage,\n cause: err,\n })\n }\n }\n }\n\n // Resolve app PID for logcat filtering only when explicitly enabled. Appium\n // 3 blocks mobile: shell unless the server is started with adb_shell enabled.\n if (process.env.AGENT_QA_ANDROID_USE_MOBILE_SHELL === '1' && this.appPackage && this.driver) {\n try {\n const result = String(await this.driver.execute('mobile: shell', { command: 'pidof', args: [this.appPackage] }))\n const pid = result?.trim()\n if (pid && /^\\d+$/.test(pid)) this.appPid = pid\n } catch {\n // mobile shell may be disabled — logs will be unfiltered\n }\n }\n\n }\n\n async cleanup(): Promise<void> {\n try { await this.recordingCapability?.stop() } catch { /* best-effort */ }\n this.recordingCapability = undefined\n try { await this.liveStreamCapability?.stop() } catch { /* best-effort */ }\n this.liveStreamCapability = undefined\n\n try {\n if (this.driver) {\n await this.driver.deleteSession()\n }\n } catch {\n // session may already be closed\n }\n this.driver = null\n this.lastRefs = {}\n this.config = null\n this.consoleLogs = []\n this.appPackage = null\n this.appPid = null\n this.appRegistry = null\n this.activeWebContext = null\n this.currentContext = null\n }\n\n // Whether we've ever successfully observed via a web context.\n // Once true, we know a WebView/browser exists and should retry rather than\n // falling back to native (which returns an opaque WebView and can crash UiAutomator2).\n private hasSeenWebContext = false\n\n async observe(): Promise<ScreenState> {\n if (!this.driver) {\n throw new Error('AndroidPlatformAdapter not initialized — call setup() first')\n }\n\n // Dynamically detect web contexts (handles browserName sessions, native browser\n // apps like Chrome opened via appPackage, and hybrid apps with WebViews).\n const webState = await this.tryObserveWeb()\n if (webState) {\n this.hasSeenWebContext = true\n return webState\n }\n\n // If we previously had web content, the page is likely transitioning (navigation,\n // new tab, etc.). Wait for the web context to come back before giving up.\n if (this.hasSeenWebContext) {\n for (const delay of [2000, 3000]) {\n await this.driver.pause(delay)\n const retry = await this.tryObserveWeb()\n if (retry) return retry\n }\n }\n\n // No web context available — fall back to native XML observation.\n // Wrapped in try-catch because calling getPageSource() on Chrome's native\n // view hierarchy can crash UiAutomator2's instrumentation process.\n this.activeWebContext = null\n try {\n return await this.observeNative()\n } catch {\n this.lastRefs = {}\n // Schema-valid empty text-only state with the diagnostic tree; no elements, so no `refMap`.\n return {\n platform: 'android',\n tree: '(native observation unavailable — WebView content not accessible)',\n elements: [],\n refMap: {},\n timestamp: Date.now(),\n metadata: {\n captureMode: 'textOnly',\n coordSpace: 'viewport',\n viewportWidth: 0,\n viewportHeight: 0,\n scroll: { offsetX: 0, offsetY: 0, contentWidth: 0, contentHeight: 0 },\n },\n }\n }\n }\n\n async execute(action: ActionsFor<'android'>): Promise<ActionResult> {\n if (!this.driver) {\n throw new Error('AndroidPlatformAdapter not initialized — call setup() first')\n }\n\n try {\n // Ensure we're in the right context before acting\n if (this.activeWebContext) {\n await this.ensureContext(this.activeWebContext)\n }\n return await this.executeAction(action)\n } catch (err) {\n let screenshot: Buffer | undefined\n try {\n screenshot = await this.captureScreenshot()\n } catch {\n // ignore screenshot failure\n }\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n screenshot,\n }\n }\n }\n\n async screenshot(): Promise<Buffer | undefined> {\n if (this.activeWebContext) {\n await this.ensureContext(this.activeWebContext)\n } else {\n try { await this.ensureContext('NATIVE_APP') } catch { /* best-effort */ }\n }\n const buf = await this.captureScreenshot()\n if (buf && this.driver) {\n // Screenshot and window dims can differ on WebView; coords stay viewport-space, logged here.\n try {\n const { getImageDimensions } = await import('@vostride/agent-qa-runner-local')\n const dims = await getImageDimensions(buf)\n const { width } = await this.driver.getWindowSize()\n if (dims && Math.abs(dims.width - width) > 1) {\n // eslint-disable-next-line no-console\n console.warn(`[android-adapter] screenshot width ${dims.width} != window width ${width} (coord-space divergence, handled by scaleFactor)`)\n }\n } catch { /* best-effort assertion */ }\n }\n return buf\n }\n\n // ---------------------------------------------------------------------------\n // Device log capture\n // ---------------------------------------------------------------------------\n\n async pollDeviceLogs(): Promise<void> {\n if (!this.captureConsole) return\n if (!this.driver) return\n try {\n const logs = await this.driver.getLogs('logcat') as { message: string; timestamp?: number }[]\n for (const entry of logs) {\n const parsed = parseLogcatLine(entry.message, entry.timestamp ?? Date.now(), this.appPid)\n if (!parsed) continue\n this.consoleLogs.push(parsed)\n }\n if (this.consoleLogs.length > 1000) {\n this.consoleLogs = this.consoleLogs.slice(-500)\n }\n } catch {\n // getLogs may fail in some Appium configurations\n }\n }\n\n drainConsoleLogs(level?: string): ConsoleLogEntry[] {\n const newLogs = this.consoleLogs.slice(this.consoleDrainIndex)\n this.consoleDrainIndex = this.consoleLogs.length\n if (!level) return newLogs\n return newLogs.filter(e => e.level === level)\n }\n\n // `takeScreenshot()` only: `screenshot()` switches the Appium context mid-step.\n get liveStream(): LiveStreamCapability {\n this.liveStreamCapability ??= createSnapshotLiveStream({ capture: () => this.captureScreenshot() })\n return this.liveStreamCapability\n }\n\n get recording(): RecordingCapability | undefined {\n const driver = this.driver\n const config = this.config?.recording\n if (!driver || !config) return undefined\n if (this.recordingCapability) return this.recordingCapability\n let running = false\n let busy = false\n let needsCleanup = false\n async function recover() {\n if (!needsCleanup) return\n await driver!.stopRecordingScreen()\n needsCleanup = false\n }\n this.recordingCapability = {\n async start() {\n if (busy || running) throw new Error('Recording already started')\n busy = true\n try {\n await recover()\n const videoSize = config.videoSize\n ? `${config.videoSize.width}x${config.videoSize.height}`\n : undefined\n needsCleanup = true\n try {\n await driver.startRecordingScreen({ videoSize, timeLimit: 1800, forceRestart: true })\n } catch (error) {\n try { await recover() } catch { /* Retry driver cleanup before reuse. */ }\n throw error\n }\n needsCleanup = false\n running = true\n return {}\n } finally { busy = false }\n },\n async stop() {\n if (busy) throw new Error('Recording operation already in progress')\n busy = true\n try {\n if (!running) { await recover(); return undefined }\n running = false\n let base64Video: string\n try {\n base64Video = await driver.stopRecordingScreen()\n } catch (error) {\n needsCleanup = true\n try { await recover() } catch { /* Retry driver cleanup before reuse. */ }\n throw error\n }\n if (!base64Video) return undefined\n await mkdir(config.videoDir, { recursive: true })\n const stagingPath = join(config.videoDir, `${randomUUID()}.mp4`)\n try {\n await writeFile(stagingPath, Buffer.from(base64Video, 'base64'))\n } catch (error) {\n await rm(stagingPath, { force: true }).catch(() => undefined)\n throw error\n }\n return { stagingPath, contentType: 'video/mp4' }\n } finally { busy = false }\n },\n }\n return this.recordingCapability\n }\n\n // ---------------------------------------------------------------------------\n // Observation\n // ---------------------------------------------------------------------------\n\n private async tryObserveWeb(): Promise<ScreenState | null> {\n const driver = this.driver!\n try {\n const contexts = await driver.getContexts() as string[]\n const explicitBrowserMode = Boolean(this.config?.browserName || this.config?.device?.match?.browserName)\n const webCtx = contexts.find(c =>\n typeof c === 'string' && isTargetWebContext(c, this.appPackage, explicitBrowserMode)\n )\n if (!webCtx) return null\n\n await this.ensureContext(webCtx)\n\n // The in-page payload is attacker-shaped, so it is array-guarded and every field coerced.\n const raw = await driver.execute(WEB_OBSERVER_SCRIPT) as unknown\n if (!raw || typeof raw !== 'object') return null\n const payload = raw as Record<string, unknown>\n\n const rawNodes = payload.nodes\n if (!Array.isArray(rawNodes) || rawNodes.length === 0) return null\n\n const nodes: InterimNode[] = []\n for (const candidate of rawNodes) {\n const node = coerceWebInterimNode(candidate)\n if (node) nodes.push(node)\n }\n if (nodes.length === 0) return null\n\n const windowSize = await driver.getWindowSize()\n const viewport = coerceViewport(payload.viewport, { width: windowSize.width, height: windowSize.height })\n const scroll = coerceWebScroll(payload.scroll, viewport)\n const url = typeof payload.url === 'string' ? payload.url : undefined\n\n // Same builder pipeline as the native path — hybrid-app WebView runs share the one\n // schema type world. WebView contexts expose exact scroll (window/document reads).\n const { state, binding } = buildScreenState({\n platform: 'android',\n nodes,\n viewport,\n scroll,\n coordSpace: 'viewport',\n timestamp: Date.now(),\n ...(url !== undefined ? { url } : {}),\n })\n this.lastRefs = buildRefEntries(nodes, binding)\n this.activeWebContext = webCtx\n\n return state\n } catch {\n // Web observation failed — caller will fall back to native\n return null\n }\n }\n\n private async observeNative(): Promise<ScreenState> {\n const driver = this.driver!\n\n await this.ensureContext('NATIVE_APP')\n\n const [xml, viewport] = await Promise.all([\n driver.getPageSource(),\n driver.getWindowSize(),\n ])\n\n // The runner builder mints refs and the tree; `buildRefEntries` keeps execute-time lookup.\n const { nodes } = parseMobileSource(xml, 'android', viewport)\n const scroll = deriveMobileScroll(nodes, viewport)\n const { state, binding } = buildScreenState({\n platform: 'android',\n nodes,\n viewport,\n scroll,\n coordSpace: 'viewport',\n timestamp: Date.now(),\n })\n this.lastRefs = buildRefEntries(nodes, binding)\n\n return state\n }\n\n // ---------------------------------------------------------------------------\n // Context management\n // ---------------------------------------------------------------------------\n\n private async ensureContext(target: string): Promise<void> {\n if (this.currentContext === target) return\n try {\n await this.driver!.switchContext(target)\n this.currentContext = target\n } catch {\n // If switch fails, clear cache so next call retries\n this.currentContext = null\n }\n }\n\n // ---------------------------------------------------------------------------\n // Screenshots\n // ---------------------------------------------------------------------------\n\n private async captureScreenshot(): Promise<Buffer | undefined> {\n try {\n if (this.driver) {\n const base64 = await this.driver.takeScreenshot()\n const buf = Buffer.from(base64, 'base64')\n if (!this.activeWebContext) return buf\n // Flattened onto white in a WebView, so failure screenshots and previews are not black.\n try {\n const { flattenOntoWhite } = await import('@vostride/agent-qa-runner-local')\n return await flattenOntoWhite(buf)\n } catch {\n return buf\n }\n }\n return undefined\n } catch {\n return undefined\n }\n }\n\n /** Read the live text of a focused element handle; undefined when nothing is readable. */\n private async readElementText(el: { getText: () => Promise<string> }): Promise<string | undefined> {\n try {\n const value = await el.getText()\n return typeof value === 'string' ? value : undefined\n } catch {\n return undefined\n }\n }\n\n private async focusedMatches(xpath: string): Promise<boolean> {\n try {\n return await (await this.driver!.$(xpath)).isExisting()\n } catch {\n return false\n }\n }\n\n /** An empty field's getText() returns its hint, so a showing hint reads ''. */\n private async readFocusedValue(el: { getText: () => Promise<string> }): Promise<string | undefined> {\n if (await this.focusedMatches(FOCUSED_HINT_XPATH)) return ''\n return await this.readElementText(el)\n }\n\n // A secure-Appium refusal is recorded as unavailable and any other driver error as failed.\n private async runShell(\n verb: ShellActionMeta['verb'],\n args: { command: string; args: string[] },\n ): Promise<ActionResult> {\n try {\n await this.driver!.execute('mobile: shell', args)\n return { success: true }\n } catch (err) {\n if (isShellRefusal(err)) {\n const shellAction: ShellActionMeta = {\n verb,\n outcome: 'unavailable',\n reason: 'adb-shell-disabled',\n }\n return {\n success: false,\n error:\n `${verb} unavailable: Appium does not allow mobile: shell here (adb_shell is not `\n + 'enabled), so nothing was sent. Use pressBack, pressHome or keypress where they fit.',\n metadata: { shellAction },\n }\n }\n const detail = firstErrorLine(err)\n const shellAction: ShellActionMeta = { verb, outcome: 'failed', detail }\n return { success: false, error: `${verb} failed: ${detail}`, metadata: { shellAction } }\n }\n }\n\n /** The one submit mechanism on every Android path; pressed once, never retried. */\n private async pressEnter(): Promise<FillSubmitMeta> {\n try {\n await this.driver!.execute('mobile: pressKey', { keycode: ENTER_KEYCODE })\n return { sent: true, outcome: 'sent' }\n } catch (err) {\n return { sent: false, outcome: 'failed', detail: firstErrorLine(err) }\n }\n }\n\n // Line breaks into a single-line field are refused before typing.\n private refuseLineBreaks(action: { submit: boolean }, box: TextBox): ActionResult {\n const fillRefusal: FillRefusalMeta = {\n verb: 'fill',\n cause: 'single-line-field',\n evidence: 'text-has-line-breaks',\n }\n return {\n success: false,\n error:\n 'fill: this field is single-line and the text has line breaks; nothing was typed. '\n + 'Send the text without line breaks, or use a multi-line field.',\n ...box,\n metadata: { fillRefusal, ...(action.submit ? { fillSubmit: { ...INPUT_FAILED } } : {}) },\n }\n }\n\n // Delivers once and reads back; an unverified result still presses Enter, a mismatch holds it.\n private async fillNativeCompound(\n el: FocusedField,\n action: { text: string; clearMode: 'replace' | 'append'; submit: boolean },\n box: TextBox,\n ): Promise<ActionResult> {\n const isAppend = action.clearMode === 'append'\n if (LINE_BREAK_RE.test(action.text) && await this.focusedMatches(FOCUSED_SINGLE_LINE_XPATH)) {\n return this.refuseLineBreaks(action, box)\n }\n const multiline = action.submit && await this.focusedMatches(FOCUSED_MULTILINE_XPATH)\n const secure = (await el.getAttribute('password').catch(() => null)) === 'true'\n const prior = isAppend ? await this.readFocusedValue(el) : ''\n\n try {\n if (isAppend) {\n await el.addValue(action.text)\n } else {\n await el.setValue(action.text)\n }\n } catch {\n return this.interruptedFill('native', secure, action, box)\n }\n\n const actual = prior === undefined ? undefined : await this.readFocusedValue(el)\n const verdict = compareFillReread({ expected: (prior ?? '') + action.text, actual, secure })\n return await this.settleFill(action, box, {\n path: 'native',\n verdict,\n multiline,\n enter: () => this.pressEnter(),\n })\n }\n\n /** The focused element handle, or undefined when UiAutomator2 reports none or the lookup fails. */\n private async focusedField(): Promise<FocusedField | undefined> {\n try {\n const el = await this.driver!.$(FOCUSED_XPATH)\n return (await el.isExisting()) ? el : undefined\n } catch {\n return undefined\n }\n }\n\n // `elsewhere` needs positive evidence: the read bounds of another observed field.\n private async focusIsElsewhere(\n handle: FocusedField,\n ref: string,\n bounds: { x: number; y: number; width: number; height: number },\n ): Promise<FocusVerdict> {\n let raw: string | null\n try {\n raw = await handle.getAttribute('bounds')\n } catch {\n return 'target'\n }\n const focused = parseBoundsAttr(raw)\n if (focused === undefined || rectWithin(focused, bounds)) return 'target'\n for (const [other, entry] of Object.entries(this.lastRefs)) {\n if (other === ref || !entry.bounds) continue\n const field = entry.editable === true || ANDROID_FILLABLE_ROLES.has(entry.role.toLowerCase())\n if (field && rectWithin(focused, entry.bounds)) return 'elsewhere'\n }\n return 'moved'\n }\n\n /** Ctrl+A then DEL as key input; clears only the view holding input focus. */\n private async clearByKeys(): Promise<void> {\n await this.driver!.execute('mobile: pressKey', CTRL_A)\n await this.driver!.execute('mobile: pressKey', { keycode: DEL_KEYCODE })\n }\n\n // Last resort when the tap left no handle; an append's prior is unknown, so at best unverified.\n private async fillKeyboardPath(\n action: { text: string; clearMode: 'replace' | 'append'; submit: boolean },\n box: TextBox,\n refData: MobileRefMap[string] | undefined,\n ): Promise<ActionResult> {\n const isAppend = action.clearMode === 'append'\n const kind = fieldKindOf(refData)\n if (kind === 'single-line' && LINE_BREAK_RE.test(action.text)) {\n return this.refuseLineBreaks(action, box)\n }\n try {\n if (!isAppend) await this.clearByKeys()\n await this.driver!.execute('mobile: type', { text: action.text })\n } catch {\n return this.interruptedFill('keyboard', false, action, box)\n }\n\n const handle = await this.focusedField()\n let secure = false\n let actual: string | undefined\n if (handle) {\n secure = await this.isSecure(handle)\n if (!isAppend) actual = await this.readFocusedValue(handle)\n }\n const verdict = compareFillReread({ expected: action.text, actual, secure })\n return await this.settleFill(action, box, {\n path: 'keyboard',\n verdict,\n multiline: kind === 'multi-line',\n enter: () => this.pressEnter(),\n })\n }\n\n // The caller has already checked that a focused handle is the referenced field.\n private async clearNativeOrKeyboard(\n box: TextBox,\n handle: FocusedField | undefined,\n ): Promise<ActionResult> {\n const path: InputPath = handle ? 'native' : 'keyboard'\n const before = handle ? await this.isSecure(handle) : false\n try {\n if (handle) await handle.clearValue()\n else await this.clearByKeys()\n } catch {\n return this.interruptedClear(path, before, box)\n }\n const readable = handle ?? (await this.focusedField())\n if (!readable) return this.settleClear(path, undefined, false, box)\n const secure = handle ? before : await this.isSecure(readable)\n return this.settleClear(path, await this.readFocusedValue(readable), secure, box)\n }\n\n private async isSecure(el: FocusedField): Promise<boolean> {\n return (await el.getAttribute('password').catch(() => null)) === 'true'\n }\n\n private settleClear(\n path: InputPath,\n actual: string | undefined,\n secure: boolean,\n box: TextBox,\n ): ActionResult {\n const verdict = compareFillReread({ expected: '', actual, secure, verb: 'clearText' })\n const fillVerdict: FillVerdictMeta = {\n verb: 'clearText',\n verdict: verdict.verdict,\n path,\n ...(verdict.secure ? { secure: true as const } : {}),\n }\n const metadata = { ...(verdict.meta ? { fillReread: verdict.meta } : {}), fillVerdict }\n return verdict.ok\n ? { success: true, ...box, metadata }\n : { success: false, error: verdict.selfCorrectingError, ...box, metadata }\n }\n\n /** A driver error while clearing ends the clear; it is never repeated. */\n private interruptedClear(path: InputPath, secure: boolean, box: TextBox): ActionResult {\n return {\n success: false,\n error:\n 'clearText was interrupted by a driver error; the field may be partly cleared, and it '\n + 'was not cleared again. Re-observe the field before clearing it again.',\n ...box,\n metadata: {\n fillVerdict: {\n verb: 'clearText',\n verdict: 'unverified',\n path,\n ...(secure ? { secure: true as const } : {}),\n },\n },\n }\n }\n\n /** A driver error during delivery ends the fill: nothing is typed again and no Enter follows. */\n private interruptedFill(\n path: InputPath,\n secure: boolean,\n action: { submit: boolean },\n box: TextBox,\n ): ActionResult {\n const fillVerdict: FillVerdictMeta = {\n verb: 'fill',\n verdict: 'unverified',\n path,\n ...(secure ? { secure: true as const } : {}),\n }\n return {\n success: false,\n error:\n 'fill: typing was interrupted by a driver error; the field may hold part of the text, '\n + 'and it was not typed again. Re-observe the field before filling it again.',\n ...box,\n metadata: { fillVerdict, ...(action.submit ? { fillSubmit: { ...INPUT_FAILED } } : {}) },\n }\n }\n\n // Holds Enter on a mismatch or a multi-line field; otherwise presses it once.\n private async settleFill(\n action: { submit: boolean },\n box: TextBox,\n settle: {\n path: InputPath\n verdict: ReturnType<typeof compareFillReread>\n multiline: boolean\n enter: () => Promise<FillSubmitMeta>\n },\n ): Promise<ActionResult> {\n const { path, verdict, multiline, enter } = settle\n const fillVerdict: FillVerdictMeta = {\n verb: 'fill',\n verdict: verdict.verdict,\n path,\n ...(verdict.secure ? { secure: true as const } : {}),\n }\n\n let fillSubmit: FillSubmitMeta | undefined\n if (action.submit) {\n if (verdict.verdict === 'mismatch') {\n fillSubmit = { sent: false, outcome: 'not-sent', reason: 'mismatch' }\n } else if (multiline) {\n fillSubmit = { sent: false, outcome: 'not-sent', reason: 'multi-line-field' }\n } else {\n fillSubmit = await enter()\n }\n }\n const notice = fillSubmit?.reason === 'multi-line-field' ? { data: MULTI_LINE_SUBMIT_NOTICE } : {}\n const metadata = {\n ...(verdict.meta ? { fillReread: verdict.meta } : {}),\n fillVerdict,\n ...(fillSubmit ? { fillSubmit } : {}),\n }\n if (!verdict.ok) return { success: false, error: verdict.selfCorrectingError, ...box, metadata }\n if (fillSubmit?.outcome === 'failed') {\n return {\n success: false,\n error:\n 'fill typed the text, but Enter failed and was not sent again. Re-observe the screen; '\n + 'if the field still holds the text, submit it without typing it again.',\n ...box,\n metadata,\n }\n }\n return { success: true, ...box, ...notice, metadata }\n }\n\n /** A real W3C touch tap in the WebView context at the ref's CSS-pixel centre. */\n private async trustedWebTap(center: { x: number; y: number }): Promise<void> {\n await safePerform(this.driver!.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(center.x), y: Math.round(center.y), origin: 'viewport' })\n .down({ button: 0 })\n .up({ button: 0 })\n )\n }\n\n /** Whether the tap left an editable field focused at the ref's point; read-only. */\n private async probeWebFocus(center: { x: number; y: number }): Promise<WebFocus> {\n const none: WebFocus = { editable: false, matches: false, multiline: false, secure: false }\n try {\n const raw = await this.driver!.execute(\n WEB_FOCUS_PROBE_SCRIPT, Math.round(center.x), Math.round(center.y),\n ) as unknown as Record<string, unknown> | null\n if (!raw || typeof raw !== 'object') return none\n return {\n editable: raw.editable === true,\n matches: raw.matches === true,\n multiline: raw.multiline === true,\n secure: raw.secure === true,\n ...(typeof raw.value === 'string' ? { value: raw.value } : {}),\n }\n } catch {\n return none\n }\n }\n\n /** Polls the read-only probe until the tap's field holds focus; returns the last answer. */\n private async awaitWebFocus(center: { x: number; y: number }): Promise<WebFocus> {\n let focus = await this.probeWebFocus(center)\n for (let poll = 1; poll < WEB_FOCUS_POLLS && !(focus.editable && focus.matches); poll++) {\n await this.driver!.pause(WEB_FOCUS_POLL_MS)\n focus = await this.probeWebFocus(center)\n }\n return focus\n }\n\n private async readWebFieldValue(): Promise<string | undefined> {\n try {\n const value = await this.driver!.execute(WEB_FIELD_VALUE_SCRIPT) as unknown\n return typeof value === 'string' ? value : undefined\n } catch {\n return undefined\n }\n }\n\n /** Runs a driver call from NATIVE_APP and always returns to the active WebView context. */\n private async withNativeContext<T>(fn: () => Promise<T>): Promise<T> {\n await this.ensureContext('NATIVE_APP')\n try {\n return await fn()\n } finally {\n if (this.activeWebContext) await this.ensureContext(this.activeWebContext)\n }\n }\n\n // A tap that leaves no editable field, or another field, focused writes nothing.\n private refuseFocus(\n verb: 'fill' | 'clearText',\n ref: string,\n focus: 'no-keyboard-focus' | 'focus-elsewhere' | Exclude<FocusVerdict, 'target'>,\n submit: boolean,\n box: TextBox,\n ): ActionResult {\n const nothing = verb === 'fill' ? 'nothing was typed' : 'nothing was cleared'\n let fillRefusal: FillRefusalMeta\n let error: string\n if (focus === 'moved') {\n fillRefusal = { verb, cause: 'target-not-found', evidence: 'stale-target' }\n error = `${verb}: after tapping ${ref}, the focused field is no longer where it was observed; `\n + `${nothing}. Re-observe and target the field where it is now.`\n } else if (focus === 'elsewhere') {\n fillRefusal = { verb, cause: 'not-editable', evidence: 'focus-elsewhere' }\n error = `${verb}: after tapping ${ref}, input focus is on another field; ${nothing}. `\n + 'Input is never sent to a field other than the target. Re-observe and target the field itself.'\n } else {\n fillRefusal = { verb, cause: 'not-editable', evidence: focus }\n error = `${verb}: the tap on ${ref} did not focus an editable field; ${nothing}. `\n + 'Target the input itself and try again.'\n }\n return {\n success: false,\n error,\n ...box,\n metadata: { fillRefusal, ...(submit ? { fillSubmit: { ...INPUT_FAILED } } : {}) },\n }\n }\n\n // Never success without the read-back judged against the empty string.\n private async clearWebViewField(\n ref: string,\n center: { x: number; y: number },\n box: TextBox,\n ): Promise<ActionResult> {\n const driver = this.driver!\n await this.trustedWebTap(center)\n const focus = await this.awaitWebFocus(center)\n if (!focus.editable || !focus.matches) {\n return this.refuseFocus('clearText', ref, webFocusEvidence(focus), false, box)\n }\n try {\n await driver.keys(['Control', 'a'])\n await driver.keys(['Backspace'])\n } catch {\n return this.interruptedClear('webview', focus.secure, box)\n }\n return this.settleClear('webview', await this.readWebFieldValue(), focus.secure, box)\n }\n\n // Trusted input only: no page script writes the field or fires an event.\n private async fillWebViewCompound(\n action: { ref: string; text: string; clearMode: 'replace' | 'append'; submit: boolean },\n box: TextBox,\n center: { x: number; y: number },\n ): Promise<ActionResult> {\n const driver = this.driver!\n const isAppend = action.clearMode === 'append'\n await this.trustedWebTap(center)\n const focus = await this.awaitWebFocus(center)\n if (!focus.editable || !focus.matches) {\n return this.refuseFocus('fill', action.ref, webFocusEvidence(focus), action.submit, box)\n }\n if (!focus.multiline && LINE_BREAK_RE.test(action.text)) {\n return this.refuseLineBreaks(action, box)\n }\n const prior = isAppend ? focus.value : ''\n try {\n if (isAppend) {\n await driver.keys(focus.multiline ? ['Control', 'End'] : ['End'])\n } else {\n await driver.keys(['Control', 'a'])\n await driver.keys(['Backspace'])\n }\n await this.withNativeContext(() => driver.execute('mobile: type', { text: action.text }))\n } catch {\n return this.interruptedFill('webview', focus.secure, action, box)\n }\n const actual = prior === undefined ? undefined : await this.readWebFieldValue()\n const verdict = compareFillReread({\n expected: (prior ?? '') + action.text,\n actual,\n secure: focus.secure,\n })\n return await this.settleFill(action, box, {\n path: 'webview',\n verdict,\n multiline: focus.multiline,\n enter: () => this.withNativeContext(() => this.pressEnter()),\n })\n }\n\n // Native swipes trust `scrollGesture`'s boolean; WebView swipes compare every scroller by id.\n private async buildAndroidScrollPrimitives(\n scrollDirection: Direction,\n maxSwipes: number,\n factor = 1,\n ): Promise<ScrollPrimitives> {\n const driver = this.driver!\n const viewport = await driver.getWindowSize()\n const axisLength = scrollDirection === 'left' || scrollDirection === 'right' ? viewport.width : viewport.height\n const distance = Math.max(1, Math.round(axisLength * 0.6 * factor))\n\n const webViewSwipe = async (direction: Direction, ref?: Ref): Promise<SwipeSignal> => {\n let sx = Math.round(viewport.width / 2)\n let sy = Math.round(viewport.height / 2)\n if (ref) {\n const { center } = new MobileElementResolver(this.lastRefs).resolve(ref)\n sx = Math.round(center.x)\n sy = Math.round(center.y)\n }\n const before = await this.readWebViewScrollers()\n const pts = computeSwipe(sx, sy, fingerDirectionFor(direction), distance)\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: pts.startX, y: pts.startY })\n .down({ button: 0 })\n .move({ x: pts.endX, y: pts.endY, duration: 300 })\n .up({ button: 0 })\n )\n const after = await this.readWebViewScrollers()\n return webViewSwipeSignal(direction, before, after)\n }\n\n return {\n swipeOnce: async (direction: Direction, ref?: Ref): Promise<SwipeSignal> => {\n if (this.activeWebContext) return webViewSwipe(direction, ref)\n const area = gestureArea(\n ref\n ? new MobileElementResolver(this.lastRefs).resolve(ref).bounds\n : { x: 0, y: 0, width: viewport.width, height: viewport.height },\n direction,\n viewport,\n )\n // `scrollGesture` answers true when the list moved and more remains, false at its end.\n const canScrollMore = await driver.execute('mobile: scrollGesture', {\n left: Math.round(area.x),\n top: Math.round(area.y),\n width: Math.max(1, Math.round(area.width)),\n height: Math.max(1, Math.round(area.height)),\n direction,\n percent: 0.75 * factor,\n }) as unknown\n if (canScrollMore === true) return 'moved'\n if (canScrollMore === false) return 'at-boundary'\n return 'unknown'\n },\n nativeSearchScroll: async (target: string): Promise<boolean> => {\n // escapeUiSelectorText re-validates + escapes; a control char here throws and the loop\n // surfaces it (the case already rejected control chars up front, so this is escaping only).\n const escaped = escapeUiSelectorText(target)\n const selector =\n `new UiScrollable(new UiSelector().scrollable(true))`\n + `.scrollIntoView(new UiSelector().textContains(\"${escaped}\"))`\n try {\n await driver.execute('mobile: scroll', { strategy: '-android uiautomator', selector, maxSwipes })\n return true\n } catch {\n return false\n }\n },\n readInterimTree: async (): Promise<InterimNode[]> => {\n const xml = await driver.getPageSource()\n const { nodes } = parseMobileSource(xml, 'android', viewport)\n return nodes\n },\n }\n }\n\n // The touch point cannot map into CSS coordinates, so the swipe is judged over every scroller.\n private async readWebViewScrollers(): Promise<IdentifiedScrollOffsets[] | undefined> {\n try {\n return parseWebViewScrollers(await this.driver!.execute(WEBVIEW_SCROLLERS_SCRIPT) as unknown)\n } catch {\n return undefined\n }\n }\n\n // On a resolution miss the registry is re-enumerated once before erroring; never a best guess.\n private async openApp(\n action: { appName: string } | { bundleId: string },\n ): Promise<ActionResult> {\n const driver = this.driver!\n let registry = await this.ensureAppRegistry()\n if (registry === null) {\n return {\n success: false,\n error:\n 'openApp could not enumerate installed apps: \"mobile: listApps\" failed and the '\n + 'shell fallback is disabled. Retry with an explicit openApp {bundleId}, or set '\n + 'AGENT_QA_ANDROID_USE_MOBILE_SHELL=1 to allow the pm-list fallback.',\n }\n }\n\n if ('bundleId' in action) {\n // Explicit variant: skip matching, validate membership against the cached registry.\n if (!registry.some((entry) => entry.id === action.bundleId)) {\n return {\n success: false,\n error: `openApp: bundleId \"${action.bundleId}\" is not installed (not in the app registry). Verify the package id or use openApp {appName}.`,\n }\n }\n await driver.activateApp(action.bundleId)\n return { success: true, metadata: { openApp: { resolvedId: action.bundleId, matchKind: 'explicit' } } }\n }\n\n let resolution = resolveAppName(action.appName, registry)\n if (resolution.kind === 'unknown' || resolution.kind === 'ambiguous') {\n const fresh = await this.enumerateApps()\n if (fresh !== null) {\n this.appRegistry = fresh\n registry = fresh\n resolution = resolveAppName(action.appName, registry)\n }\n }\n\n switch (resolution.kind) {\n case 'exact':\n case 'fuzzy':\n await driver.activateApp(resolution.id)\n return { success: true, metadata: { openApp: { resolvedId: resolution.id, matchKind: resolution.kind } } }\n case 'ambiguous':\n case 'unknown': {\n const ids = resolution.candidates.map((c) => c.id).join(', ')\n const lead =\n resolution.kind === 'ambiguous' ? 'is ambiguous between installed apps' : 'did not match an installed app'\n return {\n success: false,\n error: `openApp: \"${action.appName}\" ${lead}. Closest candidates: ${ids || '(none)'}. Retry openApp {bundleId} with the exact package id.`,\n }\n }\n }\n }\n\n /** Return the cached registry, enumerating once on first use. Failed enumeration returns null (uncached). */\n private async ensureAppRegistry(): Promise<AppRegistryEntry[] | null> {\n if (this.appRegistry !== null) return this.appRegistry\n const enumerated = await this.enumerateApps()\n if (enumerated !== null) this.appRegistry = enumerated\n return enumerated\n }\n\n // Driver only, no adb; the `mobile: shell` fallback needs `AGENT_QA_ANDROID_USE_MOBILE_SHELL=1`.\n private async enumerateApps(): Promise<AppRegistryEntry[] | null> {\n const driver = this.driver!\n try {\n const raw = await driver.execute('mobile: listApps')\n return this.mapListApps(raw)\n } catch {\n if (process.env.AGENT_QA_ANDROID_USE_MOBILE_SHELL === '1') {\n try {\n const out = String(await driver.execute('mobile: shell', { command: 'pm', args: ['list', 'packages'] }))\n return this.parsePmListPackages(out)\n } catch {\n return null\n }\n }\n return null\n }\n }\n\n /** Coerce a `mobile: listApps` result (package-id-keyed map, or an array of entries) into the registry. */\n private mapListApps(raw: unknown): AppRegistryEntry[] {\n const labelOf = (value: unknown): string | undefined => {\n if (!value || typeof value !== 'object') return undefined\n const v = value as Record<string, unknown>\n for (const key of ['label', 'name', 'appName']) {\n const candidate = v[key]\n if (typeof candidate === 'string' && candidate.length > 0) return candidate\n }\n return undefined\n }\n const entries: AppRegistryEntry[] = []\n if (Array.isArray(raw)) {\n for (const item of raw) {\n if (!item || typeof item !== 'object') continue\n const v = item as Record<string, unknown>\n const id = v.packageName ?? v.bundleId ?? v.id\n if (typeof id !== 'string' || id.length === 0) continue\n const label = labelOf(item)\n entries.push(label !== undefined ? { id, label } : { id })\n }\n } else if (raw && typeof raw === 'object') {\n for (const [id, value] of Object.entries(raw as Record<string, unknown>)) {\n if (!id) continue\n const label = labelOf(value)\n entries.push(label !== undefined ? { id, label } : { id })\n }\n }\n return entries\n }\n\n /** Parse `pm list packages` output (\"package:com.foo\\n…\") into id-only registry entries. */\n private parsePmListPackages(output: string): AppRegistryEntry[] {\n const entries: AppRegistryEntry[] = []\n for (const line of output.split('\\n')) {\n const id = line.trim().replace(/^package:/, '')\n if (id) entries.push({ id })\n }\n return entries\n }\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n\n private async executeAction(action: ActionsFor<'android'>): Promise<ActionResult> {\n const driver = this.driver!\n const resolver = new MobileElementResolver(this.lastRefs)\n const inWeb = !!this.activeWebContext\n\n switch (action.type) {\n case 'tap': {\n const { center, bounds } = resolver.resolve(action.ref)\n if (inWeb) {\n await driver.execute(\n 'var el = document.elementFromPoint(arguments[0], arguments[1]); if (el) el.click();',\n center.x, center.y,\n )\n } else {\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(center.x), y: Math.round(center.y) })\n .down({ button: 0 })\n .up({ button: 0 })\n )\n }\n return { success: true, coordinates: center, boundingBox: bounds }\n }\n\n case 'fill': {\n // One `ActionResult` with re-read metadata; a mismatch fails once, with no internal retry.\n const { center, bounds } = resolver.resolve(action.ref)\n const refData = this.lastRefs[action.ref]\n const role = refData?.role?.toLowerCase()\n if (role && !ANDROID_FILLABLE_ROLES.has(role)) {\n return {\n success: false,\n error: `Element ${action.ref} is not fillable (role: ${role}). Use a textbox or input element instead.`,\n }\n }\n const box = { coordinates: center, boundingBox: bounds }\n if (inWeb) {\n return await this.fillWebViewCompound(action, box, center)\n }\n // Native fill — tap to focus, then run the compound from the focused-element handle.\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(center.x), y: Math.round(center.y) })\n .down({ button: 0 })\n .up({ button: 0 })\n )\n // The path is chosen here, before any text is delivered.\n const focusedEl = await this.focusedField()\n const verdict = focusedEl ? await this.focusIsElsewhere(focusedEl, action.ref, bounds) : 'target'\n if (verdict !== 'target') {\n return this.refuseFocus('fill', action.ref, verdict, action.submit, box)\n }\n if (focusedEl) return await this.fillNativeCompound(focusedEl, action, box)\n return await this.fillKeyboardPath(action, box, refData)\n }\n\n case 'nativeSelect': {\n const { center, bounds } = resolver.resolve(action.ref)\n const refData = this.lastRefs[action.ref]\n if (!isAndroidNativeSelectTarget(refData)) {\n return {\n success: false,\n error: 'nativeSelect only supports native Android picker/dropdown/list controls. Use tap, swipe, or tapCoordinate for custom controls.',\n coordinates: center,\n boundingBox: bounds,\n }\n }\n\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(center.x), y: Math.round(center.y) })\n .down({ button: 0 })\n .up({ button: 0 })\n )\n\n const option = await findAndroidNativeOption(driver, action.value)\n if (!option) {\n return {\n success: false,\n error: `Could not find native Android option \"${action.value}\". Open the control with tap, then use swipe/tap/tapCoordinate for custom controls.`,\n coordinates: center,\n boundingBox: bounds,\n }\n }\n\n if (typeof option.element.click === 'function') {\n await option.element.click()\n } else {\n return {\n success: false,\n error: `Could not click native Android option \"${action.value}\". Use tap, swipe, or tapCoordinate for custom controls.`,\n coordinates: center,\n boundingBox: bounds,\n }\n }\n\n return {\n success: true,\n coordinates: center,\n boundingBox: bounds,\n data: {\n requestedValue: action.value,\n matchedValue: option.matchedValue,\n matchStrategy: option.matchStrategy,\n },\n }\n }\n\n case 'scroll': {\n // Movement and boundaries come from `scrollGesture` or WebView offsets, never tree diffs.\n if (action.mode === 'untilVisible') {\n // Reject a hostile or control-char target up front, never interpolating it.\n try {\n escapeUiSelectorText(action.text)\n } catch (err) {\n return { success: false, error: err instanceof Error ? err.message : String(err) }\n }\n const primitives = await this.buildAndroidScrollPrimitives(action.direction, action.maxSwipes)\n const { meta } = await runUntilVisibleLoop(primitives, {\n target: action.text,\n direction: action.direction,\n maxSwipes: action.maxSwipes,\n retryOpposite: action.retryOpposite,\n ...(action.ref ? { ref: action.ref } : {}),\n })\n return { success: true, metadata: { scrollUntilVisible: meta } }\n }\n\n // direction mode: page / halfPage / toEnd.\n const factor = action.amount === 'halfPage' ? 0.5 : 1\n const primitives = await this.buildAndroidScrollPrimitives(action.direction, 0, factor)\n if (action.amount === 'toEnd') {\n const { meta } = await runToEndScroll(primitives, action.direction, action.ref)\n return { success: true, metadata: { scrollUntilVisible: meta } }\n }\n const { meta } = await runDirectionScroll(primitives, {\n direction: action.direction,\n ...(action.ref ? { ref: action.ref } : {}),\n })\n return { success: true, metadata: { scrollUntilVisible: meta } }\n }\n\n case 'swipe': {\n if (inWeb) {\n await this.ensureContext('NATIVE_APP')\n }\n const { width, height } = await driver.getWindowSize()\n\n // `path` drives explicit points; a direction swipes a page from the ref or screen center.\n let pts: { startX: number; startY: number; endX: number; endY: number }\n if (action.mode === 'path') {\n pts = {\n startX: Math.round(action.from.x),\n startY: Math.round(action.from.y),\n endX: Math.round(action.to.x),\n endY: Math.round(action.to.y),\n }\n } else {\n let sx = Math.round(width / 2)\n let sy = Math.round(height / 2)\n if (action.ref) {\n const { center } = resolver.resolve(action.ref)\n sx = Math.round(center.x)\n sy = Math.round(center.y)\n }\n const distance = Math.round(height * 0.6)\n pts = computeSwipe(sx, sy, action.direction, distance)\n }\n warnIfOutOfBounds({ x: pts.startX, y: pts.startY }, { width, height }, 'swipe')\n warnIfOutOfBounds({ x: pts.endX, y: pts.endY }, { width, height }, 'swipe')\n const swipeDuration = action.durationMs\n\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: pts.startX, y: pts.startY })\n .down({ button: 0 })\n .move({ x: pts.endX, y: pts.endY, duration: swipeDuration })\n .up({ button: 0 })\n )\n if (inWeb) {\n await this.ensureContext(this.activeWebContext!)\n }\n return {\n success: true,\n startCoordinates: { x: pts.startX, y: pts.startY },\n endCoordinates: { x: pts.endX, y: pts.endY },\n }\n }\n\n case 'pinch': {\n const { width: pinchW, height: pinchH } = await driver.getWindowSize()\n let pcx = Math.round(pinchW / 2)\n let pcy = Math.round(pinchH / 2)\n\n if ('ref' in action) {\n const { center } = resolver.resolve(action.ref)\n pcx = Math.round(center.x)\n pcy = Math.round(center.y)\n } else {\n pcx = action.x\n pcy = action.y\n }\n warnIfOutOfBounds({ x: pcx, y: pcy }, { width: pinchW, height: pinchH }, 'pinch')\n\n const { finger1Start, finger1End, finger2Start, finger2End } = computePinch(pcx, pcy, action.scale)\n const pinchDuration = 500\n\n await driver.actions([\n driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(finger1Start.x), y: Math.round(finger1Start.y) })\n .down({ button: 0 })\n .move({ x: Math.round(finger1End.x), y: Math.round(finger1End.y), duration: pinchDuration })\n .up({ button: 0 }),\n driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(finger2Start.x), y: Math.round(finger2Start.y) })\n .down({ button: 0 })\n .move({ x: Math.round(finger2End.x), y: Math.round(finger2End.y), duration: pinchDuration })\n .up({ button: 0 }),\n ])\n return { success: true, coordinates: { x: pcx, y: pcy } }\n }\n\n case 'multiTap': {\n const { width: mtW, height: mtH } = await driver.getWindowSize()\n let mtcx = Math.round(mtW / 2)\n let mtcy = Math.round(mtH / 2)\n\n if ('ref' in action) {\n const { center } = resolver.resolve(action.ref)\n mtcx = Math.round(center.x)\n mtcy = Math.round(center.y)\n } else {\n mtcx = action.x\n mtcy = action.y\n }\n warnIfOutOfBounds({ x: mtcx, y: mtcy }, { width: mtW, height: mtH }, 'multiTap')\n\n const positions = computeFingerPositions(mtcx, mtcy, action.fingers)\n await driver.actions(\n positions.map(pos =>\n driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(pos.x), y: Math.round(pos.y) })\n .down({ button: 0 })\n .pause(100)\n .up({ button: 0 })\n )\n )\n return { success: true }\n }\n\n case 'longpress': {\n const { center } = resolver.resolve(action.ref)\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(center.x), y: Math.round(center.y) })\n .down({ button: 0 })\n .pause(action.duration ?? 1000)\n .up({ button: 0 })\n )\n return { success: true }\n }\n\n case 'waitFor': {\n // `text` and `gone` poll the native accessibility tree; `selector` is a web-only mode.\n if (action.on === 'selector') {\n return {\n success: false,\n error: 'waitFor {on:\"selector\"} (CSS/XPath) is a web-only mode. On native Android, wait on visible text with waitFor {on:\"text\"} or {on:\"gone\"}.',\n }\n }\n const wantPresent = action.on === 'text'\n const needle = action.text\n const deadline = Date.now() + action.timeoutMs\n for (;;) {\n let source = ''\n try {\n source = await driver.getPageSource()\n } catch {\n source = ''\n }\n if (source.includes(needle) === wantPresent) return { success: true }\n if (Date.now() >= deadline) break\n await driver.pause(Math.min(250, Math.max(1, deadline - Date.now())))\n }\n return {\n success: false,\n error: wantPresent\n ? `waitFor: text \"${needle}\" did not appear within ${action.timeoutMs}ms.`\n : `waitFor: text \"${needle}\" was still present after ${action.timeoutMs}ms.`,\n }\n }\n\n case 'delay': {\n await driver.pause(action.ms)\n return { success: true }\n }\n\n case 'keypress': {\n // Only `press` is meaningful on mobile; key hold and release are web-only.\n if (action.mode !== 'press') {\n return {\n success: false,\n error: `keypress {mode:\"${action.mode}\"} (key hold/release) is web-only. On mobile, emit keypress {mode:\"press\"} to send the key.`,\n }\n }\n for (const rawKey of action.keys) {\n const mapped = KEY_MAP[rawKey] ?? rawKey\n await driver.keys([mapped])\n }\n return { success: true }\n }\n\n // --- New actions ---\n\n case 'hideKeyboard': {\n try {\n await driver.hideKeyboard()\n } catch {\n try { await driver.execute('mobile: pressKey', { keycode: 4 }) } catch { /* best-effort */ }\n }\n return { success: true }\n }\n\n case 'clearText': {\n const { center, bounds } = resolver.resolve(action.ref)\n const clearRefData = this.lastRefs[action.ref]\n const clearRole = clearRefData?.role?.toLowerCase()\n if (clearRole && !ANDROID_FILLABLE_ROLES.has(clearRole)) {\n return {\n success: false,\n error: `Element ${action.ref} is not fillable (role: ${clearRole}). clearText only works on text inputs. Use a textbox or input element instead.`,\n }\n }\n if (inWeb) {\n return await this.clearWebViewField(action.ref, center, {\n coordinates: center,\n boundingBox: bounds,\n })\n }\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(center.x), y: Math.round(center.y) })\n .down({ button: 0 })\n .up({ button: 0 })\n )\n const clearBox = { coordinates: center, boundingBox: bounds }\n const clearHandle = await this.focusedField()\n const clearVerdict = clearHandle\n ? await this.focusIsElsewhere(clearHandle, action.ref, bounds)\n : 'target'\n if (clearVerdict !== 'target') {\n return this.refuseFocus('clearText', action.ref, clearVerdict, false, clearBox)\n }\n return await this.clearNativeOrKeyboard(clearBox, clearHandle)\n }\n\n // --- Android hardware / system verbs (numeric keycodes / typed driver args only) ---\n\n case 'pressBack':\n await driver.execute('mobile: pressKey', { keycode: 4 })\n return { success: true }\n\n case 'pressHome':\n await driver.execute('mobile: pressKey', { keycode: 3 })\n return { success: true }\n\n case 'pressRecent':\n await driver.execute('mobile: pressKey', { keycode: 187 })\n return { success: true }\n\n case 'openNotifications':\n await driver.execute('mobile: openNotifications')\n return { success: true }\n\n case 'openQuickSettings':\n // An args-array shell, never a concatenated command string.\n return await this.runShell('openQuickSettings', {\n command: 'cmd',\n args: ['statusbar', 'expand-settings'],\n })\n\n case 'intent': {\n // Extras pass as typed `startActivity` args, never interpolated into a shell string.\n const TYPE_TAG: Record<'string' | 'int' | 'long' | 'float' | 'bool', string> = {\n string: 's', int: 'i', long: 'l', float: 'f', bool: 'z',\n }\n const intentArgs: Record<string, unknown> = { action: action.action }\n if (action.data !== undefined) intentArgs.uri = action.data\n if (action.packageName !== undefined) intentArgs.package = action.packageName\n if (action.extras && action.extras.length > 0) {\n intentArgs.extras = action.extras.map(\n (e): [string, string, string] => [TYPE_TAG[e.type], e.key, e.value],\n )\n }\n await driver.execute('mobile: startActivity', intentArgs)\n return { success: true }\n }\n\n case 'keyevent': {\n // The keycode is allow-listed before any driver call, so a hostile string never reaches it.\n if (!/^KEYCODE_[A-Z0-9_]+$/.test(action.keycode)) {\n return {\n success: false,\n error: `keyevent: \"${action.keycode}\" is not a valid Android key code. Provide a symbolic code matching ^KEYCODE_[A-Z0-9_]+$ (e.g. KEYCODE_ENTER, KEYCODE_TAB).`,\n }\n }\n return await this.runShell('keyevent', {\n command: 'input',\n args: ['keyevent', action.keycode],\n })\n }\n\n case 'assertValue': {\n // The adapter resolves the source to a raw value; the runner-side comparator judges.\n if ('expr' in action) {\n if (!inWeb) {\n return {\n success: false,\n error: 'assertValue {expr} evaluates JavaScript and is only available in an Android WebView/browser context. Assert on a native signal, or run against a web target.',\n }\n }\n const value = await driver.execute(`return (${action.expr});`)\n return { success: true, data: value }\n }\n switch (action.source) {\n case 'url': {\n if (!inWeb) {\n return {\n success: false,\n error: 'assertValue {source:\"url\"} reads the browser URL and is only available in an Android WebView/browser context; native screens have no URL.',\n }\n }\n const value = await driver.execute('return window.location.href;')\n return { success: true, data: value }\n }\n case 'storage': {\n if (!inWeb) {\n return {\n success: false,\n error: 'assertValue {source:\"storage\"} reads Web Storage and is only available in an Android WebView/browser context.',\n }\n }\n const value = await driver.execute(\n 'return Object.fromEntries(Object.keys(localStorage).map(function(k){return [k, localStorage.getItem(k)];}));',\n )\n return { success: true, data: value }\n }\n case 'network':\n return {\n success: false,\n error: 'assertValue {source:\"network\"} (HTTP log inspection) is not available on the Android adapter. Use a web target for network assertions, or assert on visible UI text.',\n }\n }\n }\n\n case 'drag': {\n const from = resolver.resolve(action.fromRef)\n const to = resolver.resolve(action.toRef)\n if (inWeb) await this.ensureContext('NATIVE_APP')\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(from.center.x), y: Math.round(from.center.y) })\n .down({ button: 0 })\n .pause(300)\n .move({ x: Math.round(to.center.x), y: Math.round(to.center.y), duration: 500 })\n .up({ button: 0 })\n )\n if (inWeb) await this.ensureContext(this.activeWebContext!)\n return { success: true }\n }\n\n case 'doubleTap': {\n const { center, bounds } = resolver.resolve(action.ref)\n const x = Math.round(center.x)\n const y = Math.round(center.y)\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x, y })\n .down({ button: 0 })\n .up({ button: 0 })\n .pause(50)\n .down({ button: 0 })\n .up({ button: 0 })\n )\n return { success: true, coordinates: center, boundingBox: bounds }\n }\n\n case 'openApp':\n return await this.openApp(action)\n\n case 'stopApp': {\n await driver.terminateApp(action.bundleId)\n return { success: true }\n }\n\n case 'setOrientation': {\n await driver.setOrientation(action.orientation === 'landscape' ? 'LANDSCAPE' : 'PORTRAIT')\n return { success: true }\n }\n\n case 'executeScript': {\n const result = await driver.execute(action.command, action.args ?? {})\n return { success: true, data: result }\n }\n\n case 'tapCoordinate': {\n const x = action.x\n const y = action.y\n const tcVp = await driver.getWindowSize()\n warnIfOutOfBounds({ x, y }, { width: tcVp.width, height: tcVp.height }, 'tapCoordinate')\n if (inWeb) {\n await driver.execute(\n 'var el = document.elementFromPoint(arguments[0], arguments[1]); if (el) el.click();',\n x, y,\n )\n } else {\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x, y })\n .down({ button: 0 })\n .up({ button: 0 })\n )\n }\n return { success: true, coordinates: { x, y } }\n }\n\n // Runner-channel verbs never reach the adapter; one arriving here is a routing error.\n case 'reportValue':\n case 'assertAI':\n case 'extractAI':\n case 'setVariable':\n return {\n success: false,\n error: `Action \"${action.type}\" is handled by the runner dispatch seam and must not reach the Android adapter (runner-minted/author-channel verb). This indicates a dispatch routing error.`,\n }\n\n default:\n return assertNever(action)\n }\n }\n}\n","import { remote } from 'webdriverio'\nimport { MobileSetupError } from '@vostride/agent-qa-core'\nimport type { AndroidAdapterConfig } from './types.js'\n\nexport async function createAndroidSession(config: AndroidAdapterConfig) {\n const match = config.device?.match ?? {}\n const appiumUrl = process.env.AGENT_QA_APPIUM_URL ?? config.appiumUrl ?? 'http://localhost:4723'\n const url = new URL(appiumUrl)\n\n const browserName = config.browserName ?? (match.browserName as string | undefined)\n const appPath = config.appPath\n if (browserName && appPath) {\n throw new MobileSetupError({\n category: 'app-install',\n message: 'Mobile browser mode cannot be combined with app.path',\n platform: 'android',\n deviceName: config.device?.name,\n appId: appPath,\n })\n }\n\n const appStateNoReset =\n config.appState === 'preserve' ? true :\n config.appState === 'reset' ? false :\n undefined\n\n const capabilities: Record<string, unknown> = {\n platformName: 'Android',\n 'appium:automationName': (match.automationName as string) ?? 'UiAutomator2',\n 'appium:deviceName': config.device?.name ?? 'Android Emulator',\n 'appium:newCommandTimeout': config.timeouts?.test ? Math.ceil(config.timeouts.test / 1000) : 300,\n 'appium:chromedriverAutodownload': true,\n }\n\n if (match.platformVersion) capabilities['appium:platformVersion'] = match.platformVersion\n if (match.serial) capabilities['appium:udid'] = match.serial\n if (match.avd) capabilities['appium:avd'] = match.avd\n if (config.avd) capabilities['appium:avd'] = config.avd\n if (appPath) capabilities['appium:app'] = appPath\n\n if (browserName) {\n capabilities.browserName = browserName\n capabilities['appium:autoWebview'] = true\n } else {\n if (appStateNoReset !== undefined) capabilities['appium:noReset'] = appStateNoReset\n if (match.appPackage) capabilities['appium:appPackage'] = match.appPackage\n if (config.appPackage) capabilities['appium:appPackage'] = config.appPackage\n if (match.appActivity) capabilities['appium:appActivity'] = match.appActivity\n if (config.appActivity) capabilities['appium:appActivity'] = config.appActivity\n }\n\n // Strip undefined values\n for (const key of Object.keys(capabilities)) {\n if (capabilities[key] === undefined) {\n delete capabilities[key]\n }\n }\n\n return remote({\n hostname: url.hostname,\n port: parseInt(url.port || '4723', 10),\n path: url.pathname === '/' ? '/' : url.pathname,\n logLevel: config.verbose ? 'info' : 'silent',\n capabilities: capabilities as WebdriverIO.Capabilities,\n })\n}\n"],"mappings":"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","names":["MobileSetupError","MobileSetupError","shellAction","primitives","meta"]}