peachsim 0.1.657 → 0.1.659

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/README.md +21 -2
  2. package/cli/app-config.ts +25 -9
  3. package/cli/bridge-flow-runner.ts +10 -23
  4. package/cli/commands/compat.ts +234 -10
  5. package/cli/commands/do-chain.ts +5 -1
  6. package/cli/commands/inspect/actions.ts +33 -76
  7. package/cli/commands/inspect/resolve-target.ts +67 -2
  8. package/cli/commands/inspect.ts +16 -1
  9. package/cli/drivers/playwright-provisioning.ts +95 -0
  10. package/cli/ws-bridge.ts +7 -7
  11. package/dist-lib/agent-daemon-client.cjs +1 -1
  12. package/dist-lib/agent-events.cjs +1 -1
  13. package/dist-lib/agent-identity.cjs +1 -1
  14. package/dist-lib/agent-sessions.cjs +1 -1
  15. package/dist-lib/attached-projects.cjs +1 -1
  16. package/dist-lib/auth/shared-session.cjs +1 -1
  17. package/dist-lib/backend-origin.cjs +1 -1
  18. package/dist-lib/beta.cjs +1 -1
  19. package/dist-lib/beta.mjs +1 -1
  20. package/dist-lib/bridge-constants.cjs +1 -1
  21. package/dist-lib/bridge-contract-input.cjs +9 -1
  22. package/dist-lib/bridge-contract-input.mjs +9 -1
  23. package/dist-lib/bridge-contract.cjs +1 -1
  24. package/dist-lib/bridge-contract.mjs +1 -1
  25. package/dist-lib/capture-contract.cjs +1 -1
  26. package/dist-lib/capture-contract.mjs +1 -1
  27. package/dist-lib/cli-constants.cjs +1 -1
  28. package/dist-lib/cloud-contract.cjs +1 -1
  29. package/dist-lib/cloud-contract.mjs +1 -1
  30. package/dist-lib/cloud-test-args.cjs +1 -1
  31. package/dist-lib/cloud-test-args.mjs +1 -1
  32. package/dist-lib/cloud.cjs +1 -1
  33. package/dist-lib/cloud.mjs +1 -1
  34. package/dist-lib/config.cjs +3 -2
  35. package/dist-lib/detox/index.cjs +2 -2
  36. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  37. package/dist-lib/home-paths.cjs +1 -1
  38. package/dist-lib/host/bridge-host.cjs +78 -35
  39. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  40. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  41. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  42. package/dist-lib/host/replacement-module-handler.cjs +51 -8
  43. package/dist-lib/host/websocket-proxy.cjs +1 -1
  44. package/dist-lib/index.cjs +317 -70
  45. package/dist-lib/jump-to-source-babel.cjs +1 -1
  46. package/dist-lib/jump-to-source-native.cjs +1 -1
  47. package/dist-lib/kotlin-host.cjs +14 -4
  48. package/dist-lib/menu.cjs +1 -1
  49. package/dist-lib/menu.mjs +1 -1
  50. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  51. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  52. package/dist-lib/metro-production-bundle.cjs +1 -1
  53. package/dist-lib/metro-production-bundle.mjs +1 -1
  54. package/dist-lib/metro.cjs +300 -29
  55. package/dist-lib/native-app-identity.cjs +58 -25
  56. package/dist-lib/native-app-identity.mjs +57 -25
  57. package/dist-lib/plist.cjs +64 -0
  58. package/dist-lib/plist.mjs +29 -0
  59. package/dist-lib/profiles.cjs +1 -1
  60. package/dist-lib/public-brand.cjs +1 -1
  61. package/dist-lib/react-native-host-modules.cjs +1 -1
  62. package/dist-lib/react-native-host-modules.mjs +1 -1
  63. package/dist-lib/render-mode.cjs +1 -1
  64. package/dist-lib/scripts/dev-server-scanner.cjs +2 -2
  65. package/dist-lib/sdk.cjs +36 -49
  66. package/dist-lib/sdk.mjs +36 -49
  67. package/dist-lib/skills.cjs +257 -138
  68. package/dist-lib/swift-compile.cjs +1 -1
  69. package/dist-lib/swift-compile.mjs +1 -1
  70. package/dist-lib/swift-package.cjs +1 -1
  71. package/dist-lib/swift-package.mjs +1 -1
  72. package/dist-lib/swift-submit.cjs +1 -1
  73. package/dist-lib/swift-submit.mjs +1 -1
  74. package/dist-lib/swift.cjs +1 -1
  75. package/dist-lib/vite-swift.cjs +1 -1
  76. package/dist-lib/vite.cjs +51 -8
  77. package/kotlin/AppSources/android/app/Activity.kt +44 -0
  78. package/kotlin/AppSources/android/app/UiModeManager.kt +9 -0
  79. package/kotlin/AppSources/android/content/Context.kt +9 -2
  80. package/kotlin/AppSources/android/content/res/Configuration.kt +16 -0
  81. package/kotlin/AppSources/android/content/res/Resources.kt +7 -0
  82. package/kotlin/AppSources/android/graphics/Color.kt +13 -0
  83. package/kotlin/AppSources/android/os/Bundle.kt +9 -3
  84. package/kotlin/AppSources/android/view/View.kt +2 -0
  85. package/kotlin/AppSources/android/view/Window.kt +99 -8
  86. package/kotlin/AppSources/android/view/WindowInsetsController.kt +12 -0
  87. package/kotlin/AppSources/android/view/WindowManager.kt +16 -0
  88. package/kotlin/AppSources/androidx/activity/BackEventCompat.kt +17 -0
  89. package/kotlin/AppSources/androidx/activity/Cancellable.kt +5 -0
  90. package/kotlin/AppSources/androidx/activity/ComponentActivity.kt +22 -3
  91. package/kotlin/AppSources/androidx/activity/EdgeToEdge.kt +71 -0
  92. package/kotlin/AppSources/androidx/activity/OnBackPressedCallback.kt +28 -0
  93. package/kotlin/AppSources/androidx/activity/OnBackPressedDispatcher.kt +144 -0
  94. package/kotlin/AppSources/androidx/activity/OnBackPressedDispatcherOwner.kt +7 -0
  95. package/kotlin/AppSources/androidx/activity/compose/BackHandler.kt +55 -0
  96. package/kotlin/AppSources/androidx/core/view/WindowCompat.kt +32 -0
  97. package/kotlin/AppSources/dev/peach/app/PeachApp.kt +67 -12
  98. package/kotlin/AppSources/dev/peach/app/PeachWindowHost.kt +2 -1
  99. package/kotlin/AppSources/java/lang/Runnable.kt +6 -0
  100. package/kotlin/ComposeSources/PeachComposeHost.kt +11 -1
  101. package/package.json +8 -1
  102. package/skills/peach-setup/SKILL.md +27 -0
  103. package/src/android-theme.ts +167 -0
  104. package/src/android-xml.ts +70 -0
  105. package/src/bridge-contract-input.ts +10 -1
  106. package/src/bridge-contract.ts +7 -1
  107. package/src/config.ts +8 -0
  108. package/src/generated/android-framework-themes.json +6303 -0
  109. package/src/host/replacement-module-handler.ts +33 -0
  110. package/src/index.ts +1 -0
  111. package/src/kotlin-app.ts +86 -61
  112. package/src/kotlin-host.ts +13 -3
  113. package/src/metro-plugin.ts +46 -3
  114. package/src/native-app-identity.ts +75 -26
  115. package/src/sim-client.ts +2 -4
@@ -35,16 +35,69 @@ export interface ResolvedTargetCoords {
35
35
  testID?: string | null
36
36
  text?: string | null
37
37
  type?: string | null
38
+ // absent from runtimes older than the field; coordinate-only callers do not
39
+ // need it, and the tap boundary refuses to guess without it.
40
+ viewport?: { width: number; height: number }
41
+ }
42
+
43
+ export type ScreenSize = { width: number; height: number }
44
+
45
+ // a reported screen with a zero or non-finite side has not been laid out yet.
46
+ export function isScreenSize(value: unknown): value is ScreenSize {
47
+ if (value === null || typeof value !== 'object') return false
48
+ const width = Reflect.get(value, 'width')
49
+ const height = Reflect.get(value, 'height')
50
+ return (
51
+ typeof width === 'number' &&
52
+ Number.isFinite(width) &&
53
+ width > 0 &&
54
+ typeof height === 'number' &&
55
+ Number.isFinite(height) &&
56
+ height > 0
57
+ )
58
+ }
59
+
60
+ export function isOffscreen(
61
+ x: number,
62
+ y: number,
63
+ screen: { width: number; height: number },
64
+ ): boolean {
65
+ return !(x >= 0 && y >= 0 && x <= screen.width && y <= screen.height)
66
+ }
67
+
68
+ export const UNREPORTED_SCREEN_ERROR =
69
+ 'this runtime does not report the screen size a targeted gesture needs; ' +
70
+ 'update it with `peach runtime install`, or use coordinates'
71
+
72
+ // a gesture at a resolved point outside the device screen presses whatever the
73
+ // hit test finds where no finger can reach. a cloud sim refuses such a point
74
+ // itself; every other plane checks here. returns the refusal, or null to send.
75
+ export function offscreenTargetRefusal(
76
+ plane: InspectBridge['plane'],
77
+ target: ResolvedTargetCoords,
78
+ ): string | null {
79
+ if (plane === 'cloud') return null
80
+ const screen = target.viewport
81
+ if (!screen) return UNREPORTED_SCREEN_ERROR
82
+ if (!isScreenSize(screen)) {
83
+ return 'the screen is not laid out yet, so the target cannot be checked; run the command again'
84
+ }
85
+ if (!isOffscreen(target.x, target.y, screen)) return null
86
+ return `the target at (${Math.round(target.x)},${Math.round(target.y)}) is outside the ${screen.width}x${screen.height} screen; scroll it into view first`
38
87
  }
39
88
 
40
89
  export async function resolveTargetCoords(
41
90
  bridge: InspectBridge,
42
- target: { mode: 'testid' | 'text'; value: string },
91
+ target: { mode: 'testid' | 'text'; value: string } | { mode: 'node'; nodeId: number },
43
92
  ): Promise<ResolvedTargetCoords | null> {
44
93
  const result: unknown = await bridge.send({
45
94
  type: 'resolve',
46
95
  selector:
47
- target.mode === 'testid' ? { testID: target.value } : { text: target.value },
96
+ target.mode === 'node'
97
+ ? { nodeId: target.nodeId }
98
+ : target.mode === 'testid'
99
+ ? { testID: target.value }
100
+ : { text: target.value },
48
101
  })
49
102
  if (result === null) return null
50
103
  if (typeof result !== 'object') throw new Error('resolve returned an invalid result')
@@ -52,6 +105,15 @@ export async function resolveTargetCoords(
52
105
  const resolvedTarget = Reflect.get(result, 'target')
53
106
  const semanticNodes = [match, resolvedTarget]
54
107
  const point = Reflect.get(result, 'point')
108
+ const viewport = Reflect.get(result, 'viewport')
109
+ const width =
110
+ viewport !== null && typeof viewport === 'object'
111
+ ? Reflect.get(viewport, 'width')
112
+ : undefined
113
+ const height =
114
+ viewport !== null && typeof viewport === 'object'
115
+ ? Reflect.get(viewport, 'height')
116
+ : undefined
55
117
  const x =
56
118
  point !== null && typeof point === 'object' ? Reflect.get(point, 'x') : undefined
57
119
  const y =
@@ -75,5 +137,8 @@ export async function resolveTargetCoords(
75
137
  text:
76
138
  semanticMatch.text ?? (target.mode === 'text' ? target.value : semanticMatch.label),
77
139
  type: semanticMatch.type,
140
+ ...(typeof width === 'number' && typeof height === 'number'
141
+ ? { viewport: { width, height } }
142
+ : {}),
78
143
  }
79
144
  }
@@ -75,7 +75,11 @@ import {
75
75
  redactKeyboardStateForOutput,
76
76
  redactTextForKeyboardState,
77
77
  } from './inspect/redaction'
78
- import { readTargetFlag, resolveTargetCoords } from './inspect/resolve-target'
78
+ import {
79
+ offscreenTargetRefusal,
80
+ readTargetFlag,
81
+ resolveTargetCoords,
82
+ } from './inspect/resolve-target'
79
83
  import { runScreensSubcommand } from './inspect/screens'
80
84
  import { runSettleSubcommand } from './inspect/settle'
81
85
  import { waitForSootsimIdle } from './inspect/settling'
@@ -2006,6 +2010,7 @@ export async function runInspect(args: string[], opts: InspectOptions) {
2006
2010
  return {
2007
2011
  cx: resolved.x,
2008
2012
  cy: resolved.y,
2013
+ screen: resolved.viewport,
2009
2014
  match: {
2010
2015
  nodeId: resolved.nodeId,
2011
2016
  testID:
@@ -2798,6 +2803,11 @@ export async function runInspect(args: string[], opts: InspectOptions) {
2798
2803
  await reportMissingTarget(bridge, 'double-tap', target)
2799
2804
  rnxExit(1)
2800
2805
  }
2806
+ const refusal = offscreenTargetRefusal(bridge.plane, resolved)
2807
+ if (refusal) {
2808
+ console.error(` double-tap: ${refusal}`)
2809
+ rnxExit(1)
2810
+ }
2801
2811
  x = resolved.x
2802
2812
  y = resolved.y
2803
2813
  }
@@ -2838,6 +2848,11 @@ export async function runInspect(args: string[], opts: InspectOptions) {
2838
2848
  await reportMissingTarget(bridge, 'long-press', target)
2839
2849
  rnxExit(1)
2840
2850
  }
2851
+ const refusal = offscreenTargetRefusal(bridge.plane, resolved)
2852
+ if (refusal) {
2853
+ console.error(` long-press: ${refusal}`)
2854
+ rnxExit(1)
2855
+ }
2841
2856
  x = resolved.x
2842
2857
  y = resolved.y
2843
2858
  resolvedTarget = {
@@ -161,6 +161,8 @@ export function ensurePlaywrightBrowser(
161
161
  const before = probeBrowser(resolved, probeEnv)
162
162
  if (!before.ok) return before
163
163
  if (before.exists) {
164
+ const missing = missingLibrariesMessage(before.executablePath, browser)
165
+ if (missing) return { ok: false, message: missing }
164
166
  return { ok: true, executablePath: before.executablePath, installed: false }
165
167
  }
166
168
 
@@ -209,5 +211,98 @@ export function ensurePlaywrightBrowser(
209
211
  `${browser} executable is still missing at ${after.executablePath}`,
210
212
  }
211
213
  }
214
+ const missing = missingLibrariesMessage(after.executablePath, browser)
215
+ if (missing) return { ok: false, message: missing }
212
216
  return { ok: true, executablePath: after.executablePath, installed: true }
213
217
  }
218
+
219
+ // the debian package providing each shared library chromium and its headless
220
+ // shell link (readelf NEEDED, linux x64 and arm64), apart from glibc's own.
221
+ const LIBRARY_PACKAGES: Record<string, string> = {
222
+ 'libasound.so.2': 'libasound2',
223
+ 'libatk-1.0.so.0': 'libatk1.0-0',
224
+ 'libatk-bridge-2.0.so.0': 'libatk-bridge2.0-0',
225
+ 'libatspi.so.0': 'libatspi2.0-0',
226
+ 'libcairo.so.2': 'libcairo2',
227
+ 'libcups.so.2': 'libcups2',
228
+ 'libdbus-1.so.3': 'libdbus-1-3',
229
+ 'libexpat.so.1': 'libexpat1',
230
+ 'libgbm.so.1': 'libgbm1',
231
+ 'libgio-2.0.so.0': 'libglib2.0-0',
232
+ 'libglib-2.0.so.0': 'libglib2.0-0',
233
+ 'libgobject-2.0.so.0': 'libglib2.0-0',
234
+ 'libnspr4.so': 'libnspr4',
235
+ 'libnss3.so': 'libnss3',
236
+ 'libnssutil3.so': 'libnss3',
237
+ 'libpango-1.0.so.0': 'libpango-1.0-0',
238
+ 'libsmime3.so': 'libnss3',
239
+ 'libudev.so.1': 'libudev1',
240
+ 'libX11.so.6': 'libx11-6',
241
+ 'libxcb.so.1': 'libxcb1',
242
+ 'libXcomposite.so.1': 'libxcomposite1',
243
+ 'libXdamage.so.1': 'libxdamage1',
244
+ 'libXext.so.6': 'libxext6',
245
+ 'libXfixes.so.3': 'libxfixes3',
246
+ 'libxkbcommon.so.0': 'libxkbcommon0',
247
+ 'libXrandr.so.2': 'libxrandr2',
248
+ }
249
+
250
+ // packages renamed by the 64-bit time_t transition in ubuntu 24.04 and debian 13.
251
+ const TIME64_PACKAGES = new Set([
252
+ 'libasound2',
253
+ 'libatk1.0-0',
254
+ 'libatk-bridge2.0-0',
255
+ 'libatspi2.0-0',
256
+ 'libcups2',
257
+ 'libglib2.0-0',
258
+ ])
259
+
260
+ function isTime64Distro(): boolean {
261
+ if (!existsSync('/etc/os-release')) return false
262
+ const fields = Object.fromEntries(
263
+ readFileSync('/etc/os-release', 'utf8')
264
+ .split('\n')
265
+ .map((line) => line.match(/^(\w+)="?([^"]*)"?$/))
266
+ .filter((match) => match !== null)
267
+ .map((match) => [match[1], match[2]]),
268
+ )
269
+ const version = Number.parseFloat(fields.VERSION_ID ?? '')
270
+ return (
271
+ (fields.ID === 'ubuntu' && version >= 24.04) ||
272
+ (fields.ID === 'debian' && version >= 13)
273
+ )
274
+ }
275
+
276
+ /** a linux browser whose shared libraries are missing exits 127 before
277
+ * playwright can say why, so name them and their packages up front, as
278
+ * playwright's own host validation does. */
279
+ function missingLibrariesMessage(executablePath: string, browser: string): string | null {
280
+ if (process.platform !== 'linux') return null
281
+ const ldd = spawnSync('ldd', [executablePath], { encoding: 'utf8', timeout: 30_000 })
282
+ const libraries = [...(ldd.stdout ?? '').matchAll(/^\s*(\S+) => not found$/gm)].map(
283
+ (match) => match[1]!,
284
+ )
285
+ if (!libraries.length) return null
286
+ const time64 = isTime64Distro()
287
+ const packages = new Set<string>()
288
+ const unknown: string[] = []
289
+ for (const library of libraries) {
290
+ const name = LIBRARY_PACKAGES[library]
291
+ if (!name) unknown.push(library)
292
+ else packages.add(time64 && TIME64_PACKAGES.has(name) ? `${name}t64` : name)
293
+ }
294
+ const sudo = process.getuid?.() === 0 ? '' : 'sudo '
295
+ return [
296
+ `${browser} at ${executablePath} cannot start: this system is missing shared libraries it links (${libraries.join(', ')}).`,
297
+ ...(packages.size
298
+ ? [
299
+ 'On Debian or Ubuntu, install them and run the command again:',
300
+ '',
301
+ ` ${sudo}apt-get update && ${sudo}apt-get install -y --no-install-recommends ${[...packages].join(' ')}`,
302
+ ]
303
+ : []),
304
+ ...(unknown.length
305
+ ? ['', `No known Debian package provides: ${unknown.join(', ')}`]
306
+ : []),
307
+ ].join('\n')
308
+ }
package/cli/ws-bridge.ts CHANGED
@@ -24,7 +24,6 @@ import {
24
24
  } from '../src/home-paths'
25
25
  import { createCloudBridgeForParsed } from './cloud-client'
26
26
  import {
27
- clearCurrentSimId,
28
27
  getCliIdentity,
29
28
  readCurrentSim,
30
29
  readCurrentSimId,
@@ -825,13 +824,14 @@ export function createBridge(wsPort: number, opts: WsBridgeOptions = {}): WsBrid
825
824
  )
826
825
  return sendOnce(successor)
827
826
  }
828
- clearCurrentSimId()
829
- // the saved sim is gone and nothing proves what replaced it. fail
830
- // closed instead of driving whichever sim is primary; that is how
831
- // agents end up recording the wrong app.
827
+ // the saved sim is not connected and nothing proves what replaced
828
+ // it. fail closed instead of driving whichever sim is primary; that
829
+ // is how agents end up recording the wrong app. the pin stays: a
830
+ // page whose socket dropped reconnects under the same id, and
831
+ // clearing the pin then would hand every later command to primary.
832
832
  throw new Error(
833
- `saved sim ${sentSimId} is gone${message.slice(missingSimMessage.length)}; ` +
834
- 'run `peach list` and ' +
833
+ `saved sim ${sentSimId} is not connected${message.slice(missingSimMessage.length)}; ` +
834
+ 'commands resume when it reconnects, or run `peach list` and ' +
835
835
  `\`peach use <sim>\`, or open a fresh sim`,
836
836
  )
837
837
  }
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
package/dist-lib/beta.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
package/dist-lib/beta.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/beta.ts
4
4
  var IS_BETA = true;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -358,6 +358,14 @@ function semanticResolveSelector(value, path) {
358
358
  return validationFailure(path, "must select testID or text");
359
359
  }
360
360
  function parseSemanticResolveSelector(value) {
361
+ const selector = recordValue(value, "selector");
362
+ if (selector.nodeId !== void 0) {
363
+ const nodeId = numberValue(selector.nodeId, "selector.nodeId");
364
+ if (!Number.isSafeInteger(nodeId)) {
365
+ return validationFailure("selector.nodeId", "must be an integer");
366
+ }
367
+ return { nodeId };
368
+ }
361
369
  return semanticResolveSelector(value, "selector");
362
370
  }
363
371
  function parseSemanticWaitOptions(value) {
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var SIM_LONG_PRESS_MAX_MS = 5e3;
@@ -322,6 +322,14 @@ function semanticResolveSelector(value, path) {
322
322
  return validationFailure(path, "must select testID or text");
323
323
  }
324
324
  function parseSemanticResolveSelector(value) {
325
+ const selector = recordValue(value, "selector");
326
+ if (selector.nodeId !== void 0) {
327
+ const nodeId = numberValue(selector.nodeId, "selector.nodeId");
328
+ if (!Number.isSafeInteger(nodeId)) {
329
+ return validationFailure("selector.nodeId", "must be an integer");
330
+ }
331
+ return { nodeId };
332
+ }
325
333
  return semanticResolveSelector(value, "selector");
326
334
  }
327
335
  function parseSemanticWaitOptions(value) {
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var REFUSED_PERFORM_STEP_TYPES = [
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/capture-contract.ts
4
4
  var RNX_SCREEN_CAPTURE_VERSION = 1;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/cloud-contract.ts
4
4
  var RNX_CLOUD_MAX_ARTIFACT_BYTES = 20 * 1024 * 1024;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/cloud-test-args.ts
4
4
  var CLOUD_TEST_ARGS_MAX_COUNT = 32;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  var __defProp = Object.defineProperty;
3
3
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
4
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -39,7 +39,7 @@ function hasOwnKeys(value) {
39
39
  }
40
40
  function hasPeachConfig(config) {
41
41
  if (!config) return false;
42
- return typeof config.runtimeVersion === "string" && config.runtimeVersion.length > 0 || hasOwnKeys(config.modules) || hasOwnKeys(config.turboModules) || hasOwnKeys(config.nativeModules) || hasOwnKeys(config.env) || hasOwnKeys(config.network?.remap) || hasOwnKeys(config.settings) || hasOwnKeys(config.initialState);
42
+ return typeof config.runtimeVersion === "string" && config.runtimeVersion.length > 0 || hasOwnKeys(config.modules) || hasOwnKeys(config.turboModules) || hasOwnKeys(config.nativeModules) || hasOwnKeys(config.nativeViews) || hasOwnKeys(config.env) || hasOwnKeys(config.network?.remap) || hasOwnKeys(config.settings) || hasOwnKeys(config.initialState);
43
43
  }
44
44
  function mergePeachConfig(base, override) {
45
45
  if (!hasPeachConfig(base) && !hasPeachConfig(override)) return void 0;
@@ -53,6 +53,7 @@ function mergePeachConfig(base, override) {
53
53
  ...base.nativeModules || {},
54
54
  ...override.nativeModules || {}
55
55
  },
56
+ nativeViews: { ...base.nativeViews || {}, ...override.nativeViews || {} },
56
57
  env: { ...base.env || {}, ...override.env || {} },
57
58
  network: {
58
59
  remap: { ...base.network?.remap || {}, ...override.network?.remap || {} }
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -269,7 +269,7 @@ function processIdentity(pid) {
269
269
  }
270
270
  function softwareChromeAllowed(runtime = currentRuntime()) {
271
271
  if (runtime.platform !== "linux") return false;
272
- return runtime.env.GITHUB_ACTIONS === "true" && runtime.env.RUNNER_OS === "Linux" || runtime.env.CONTRAST_CF_FACTORY_CONTAINER === "1";
272
+ return runtime.env.GITHUB_ACTIONS === "true" && runtime.env.RUNNER_OS === "Linux" || runtime.env.CONTRAST_CF_FACTORY_CONTAINER === "1" || runtime.env.PEACH_NATIVE_COMPOSITOR === "1";
273
273
  }
274
274
  function isSoftwareRendererArgument(value) {
275
275
  const arg = String(value);
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.657 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.659 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;