peachsim 0.1.628 → 0.1.630

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 (111) hide show
  1. package/README.md +8 -4
  2. package/cli/bridge-flow-runner.ts +10 -3
  3. package/cli/cli-update.ts +2 -7
  4. package/cli/cloud-test-tunnel.ts +16 -3
  5. package/cli/commands/config.ts +1 -1
  6. package/cli/commands/control.ts +28 -3
  7. package/cli/commands/daemon-mac-app.ts +4 -2
  8. package/cli/commands/daemon.ts +4 -4
  9. package/cli/commands/device.ts +2 -3
  10. package/cli/commands/inspect/actions.ts +125 -90
  11. package/cli/commands/inspect/core.ts +5 -0
  12. package/cli/commands/inspect.ts +27 -13
  13. package/cli/commands/platform.ts +1 -1
  14. package/cli/commands/screenshot-layers.ts +1 -1
  15. package/cli/commands/screenshot.ts +1 -1
  16. package/cli/commands/skills.ts +0 -31
  17. package/cli/drivers/playwright-provisioning.ts +3 -2
  18. package/cli/drivers/playwright-sim-host.ts +25 -9
  19. package/cli/main.ts +8 -2
  20. package/cli/outbound-endpoints.ts +0 -4
  21. package/detox/index.ts +74 -43
  22. package/dist-lib/agent-daemon-client.cjs +1 -1
  23. package/dist-lib/agent-events.cjs +1 -1
  24. package/dist-lib/agent-identity.cjs +1 -1
  25. package/dist-lib/agent-sessions.cjs +1 -1
  26. package/dist-lib/attached-projects.cjs +1 -1
  27. package/dist-lib/auth/shared-session.cjs +1 -1
  28. package/dist-lib/backend-origin.cjs +1 -1
  29. package/dist-lib/beta.cjs +1 -1
  30. package/dist-lib/beta.mjs +1 -1
  31. package/dist-lib/bridge-constants.cjs +1 -1
  32. package/dist-lib/bridge-contract-input.cjs +1 -1
  33. package/dist-lib/bridge-contract-input.mjs +1 -1
  34. package/dist-lib/bridge-contract.cjs +1 -1
  35. package/dist-lib/bridge-contract.mjs +1 -1
  36. package/dist-lib/capture-contract.cjs +1 -1
  37. package/dist-lib/capture-contract.mjs +1 -1
  38. package/dist-lib/cli-constants.cjs +1 -1
  39. package/dist-lib/cloud-contract.cjs +1 -1
  40. package/dist-lib/cloud-contract.mjs +1 -1
  41. package/dist-lib/cloud-test-args.cjs +1 -1
  42. package/dist-lib/cloud-test-args.mjs +1 -1
  43. package/dist-lib/cloud.cjs +1 -1
  44. package/dist-lib/cloud.mjs +1 -1
  45. package/dist-lib/config.cjs +1 -1
  46. package/dist-lib/detox/index.cjs +129 -27
  47. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  48. package/dist-lib/home-paths.cjs +1 -1
  49. package/dist-lib/host/bridge-host.cjs +290 -315
  50. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  51. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  52. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  53. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  54. package/dist-lib/host/websocket-proxy.cjs +1 -1
  55. package/dist-lib/index.cjs +253 -121
  56. package/dist-lib/jump-to-source-babel.cjs +1 -1
  57. package/dist-lib/jump-to-source-native.cjs +1 -1
  58. package/dist-lib/{vite-kotlin.cjs → kotlin-host.cjs} +130 -19
  59. package/dist-lib/menu.cjs +1 -1
  60. package/dist-lib/menu.mjs +1 -1
  61. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  62. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  63. package/dist-lib/metro-production-bundle.cjs +1 -1
  64. package/dist-lib/metro-production-bundle.mjs +1 -1
  65. package/dist-lib/metro.cjs +132 -9
  66. package/dist-lib/native-app-identity.cjs +278 -0
  67. package/dist-lib/native-app-identity.mjs +245 -0
  68. package/dist-lib/profiles.cjs +1 -1
  69. package/dist-lib/public-brand.cjs +1 -1
  70. package/dist-lib/react-native-host-modules.cjs +1 -1
  71. package/dist-lib/react-native-host-modules.mjs +1 -1
  72. package/dist-lib/render-mode.cjs +1 -1
  73. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  74. package/dist-lib/sdk.cjs +110 -87
  75. package/dist-lib/sdk.mjs +110 -87
  76. package/dist-lib/skills.cjs +841 -643
  77. package/dist-lib/swift-compile.cjs +1 -1
  78. package/dist-lib/swift-compile.mjs +1 -1
  79. package/dist-lib/swift-package.cjs +1 -1
  80. package/dist-lib/swift-package.mjs +1 -1
  81. package/dist-lib/swift-submit.cjs +1 -1
  82. package/dist-lib/swift-submit.mjs +1 -1
  83. package/dist-lib/swift.cjs +282 -177
  84. package/dist-lib/vite-swift.cjs +1 -1
  85. package/dist-lib/vite.cjs +11 -28
  86. package/kotlin/README.md +32 -4
  87. package/kotlin/fixtures/counter/Counter.kt +26 -0
  88. package/kotlin/fixtures/counter/CounterScreen.kt +40 -0
  89. package/kotlin/fixtures/headless-counter/Headless.kt +228 -0
  90. package/kotlin/fixtures/runtime-state/RuntimeState.kt +200 -0
  91. package/kotlin/fork/LICENSE +178 -0
  92. package/kotlin/fork/NOTICE +25 -0
  93. package/kotlin/fork/README.md +59 -0
  94. package/kotlin/fork/build.sh +128 -0
  95. package/kotlin/fork/compose-worker-globals.patch +96 -0
  96. package/kotlin/fork/fork.json +33 -0
  97. package/kotlin/fork/publish.ts +77 -0
  98. package/kotlin/fork/skiko-worker-clock.patch +33 -0
  99. package/kotlin/toolchain.json +288 -0
  100. package/package.json +12 -5
  101. package/src/automatic-update-policy.ts +17 -0
  102. package/src/host/bridge-host.ts +3 -1
  103. package/src/{vite-plugin-kotlin.ts → kotlin-host.ts} +155 -12
  104. package/src/metro-plugin.ts +18 -0
  105. package/src/native-app-identity.ts +376 -0
  106. package/src/native-firebase-config.ts +90 -0
  107. package/src/screenshots/frame-compose.ts +5 -2
  108. package/src/screenshots/registry.ts +1 -1
  109. package/src/screenshots/schema.ts +2 -2
  110. package/src/vite-plugin-one.ts +11 -28
  111. package/src/vite-plugin.ts +6 -1
@@ -286,37 +286,6 @@ function linkSkill(skill: SkillInfo, targetDir: string, force: boolean): LinkRes
286
286
  return 'conflict'
287
287
  }
288
288
 
289
- // quiet, conflict-safe (re)install of all bundled skills into the agent stores
290
- // that already exist on this machine. wired into the CLI build so building or
291
- // updating the CLI re-establishes the symlinks idempotently — never forces, so
292
- // it can't clobber a skill the user customized, and never creates a store for
293
- // an agent that isn't set up here. silent on success.
294
- export function refreshInstalledSkills() {
295
- const skills = listSkills()
296
- if (skills.length === 0) return
297
- for (const target of defaultAgentTargets()) {
298
- const skillsDir = path.resolve(target.dir)
299
- // only touch agents already present (~/.claude, ~/.codex) — don't seed a
300
- // store on a CI runner or a machine that doesn't use that agent.
301
- if (!fs.existsSync(path.dirname(skillsDir))) continue
302
- try {
303
- fs.mkdirSync(skillsDir, { recursive: true })
304
- } catch {
305
- continue
306
- }
307
- try {
308
- removeLegacyBundledSkills(skillsDir)
309
- } catch {}
310
- for (const skill of skills) {
311
- try {
312
- linkSkill(skill, skillsDir, false)
313
- } catch {
314
- // best-effort: a single bad store must not fail the build
315
- }
316
- }
317
- }
318
- }
319
-
320
289
  const LEGACY_BUNDLED_SKILL_DIRS = [
321
290
  'sootsim-setup',
322
291
  'sootsim-debug',
@@ -2,9 +2,9 @@ import { spawnSync } from 'node:child_process'
2
2
  import { existsSync, readFileSync } from 'node:fs'
3
3
  import { createRequire } from 'node:module'
4
4
  import { dirname, join } from 'node:path'
5
+ import { isRecord } from '../../src/is-record'
5
6
  import { RNX_INTERNAL_CHILDREN, RNX_INTERNAL_COMMAND } from '../internal-child'
6
7
  import { rnxSelfInvocation } from '../self-invocation'
7
- import { isRecord } from '../../src/is-record'
8
8
 
9
9
  export interface ResolvedPlaywright {
10
10
  // package name that resolved (for human-facing messaging)
@@ -32,7 +32,8 @@ export function resolvePlaywright(): ResolvedPlaywright | null {
32
32
  // resolve from several roots, not just cwd. a user can invoke a global CLI
33
33
  // from an arbitrary directory while Playwright is installed beside the CLI.
34
34
  const roots = [`${process.cwd()}/`]
35
- if (process.argv[1]) roots.push(process.argv[1])
35
+ const self = rnxSelfInvocation()
36
+ roots.push(self.prefixArgs[0] ?? self.executable)
36
37
  for (const root of roots) {
37
38
  try {
38
39
  const requireFromRoot = createRequire(root)
@@ -2,6 +2,11 @@ import {
2
2
  readBrowserCompositeCaptureRequest,
3
3
  resolveBrowserCompositeCdpClip,
4
4
  } from '../../../peach-engine/src/capture/browser-composite'
5
+ import {
6
+ AUTH_BROWSER_EXTERNAL_NAVIGATION_EVENT,
7
+ AUTH_BROWSER_SESSION_FRAGMENT_KEY,
8
+ forwardPopupSchemeNavigations,
9
+ } from '../../../peach-engine/src/open-external'
5
10
  import { createBrowserPointerDispatcher } from '../../../peach-engine/src/render-worker/browser-pointer'
6
11
  // the detached browser host, as CJS source.
7
12
  //
@@ -46,11 +51,13 @@ const cdpPort = process.env.SOOTSIM_PW_CDP_PORT || '';
46
51
  const extraChromeArgs = (process.env.SOOTSIM_PW_CHROME_ARGS || '')
47
52
  .split(' ')
48
53
  .filter(Boolean);
49
- // Local CanvasKit work must never fall back to Playwright's software
50
- // renderer. CI may use the bundled browser for non-interactive coverage, but
51
- // local test drives fail closed unless the hardware-backed test browser is
52
- // proven after launch.
53
- const hardwareGpuRequired = process.env.CI !== '1' && process.env.CI !== 'true';
54
+ // A Mac always has a GPU, so a local macOS drive that lands on Playwright's
55
+ // software renderer is a misconfiguration that pegs every core: it fails
56
+ // closed unless the hardware-backed test browser is proven after launch. CI
57
+ // and Linux or Windows hosts, which are often GPU-less servers, use the
58
+ // bundled browser and render in software when no GPU is present.
59
+ const hardwareGpuRequired =
60
+ process.platform === 'darwin' && process.env.CI !== '1' && process.env.CI !== 'true';
54
61
  const softwareRendererPattern = /swiftshader|software(?: rasterizer)?|llvmpipe|lavapipe|softpipe/i;
55
62
  // page viewport as '<w>x<h>'. the caller sizes it from the device profile;
56
63
  // the fallback is phone-shaped because the page hosts a phone sim — the
@@ -74,6 +81,7 @@ const { execSync } = require('child_process');
74
81
  const { tmpdir } = require('os');
75
82
  const { join } = require('path');
76
83
  const createBrowserPointerDispatcher = ${createBrowserPointerDispatcher.toString()};
84
+ const forwardPopupSchemeNavigations = ${forwardPopupSchemeNavigations.toString()};
77
85
  const readBrowserCompositeCaptureRequest = ${readBrowserCompositeCaptureRequest.toString()};
78
86
  const resolveBrowserCompositeCdpClip = ${resolveBrowserCompositeCdpClip.toString()};
79
87
  // chrome tree reaper — playwright's browser.close() and even SIGKILLing the
@@ -300,9 +308,9 @@ const cleanupProfile = () => {
300
308
  startOwnerWatch();
301
309
  // Local rendering uses Playwright's full Chrome for Testing app. On macOS its
302
310
  // com.google.chrome.for.testing identity cannot intercept open/quit events for
303
- // the user's com.google.Chrome browser. CI may use chromium_headless_shell;
304
- // local rendering fails closed because that shell has no GPU and silently
305
- // chooses SwiftShader. NOTE: this is NOT enough to make \`peach perf cpu\`
311
+ // the user's com.google.Chrome browser. CI and non-Mac hosts use
312
+ // chromium_headless_shell; local Mac rendering fails closed because that
313
+ // shell has no GPU and silently chooses SwiftShader. NOTE: this is NOT enough to make \`peach perf cpu\`
306
314
  // work — that profiles the tenant *worker*, and the JS Self-Profiler API
307
315
  // cannot be constructed in a dedicated worker (see
308
316
  // worker-handlers/cpu-profile.ts). cpu-profile needs a CDP-based profiler
@@ -317,7 +325,8 @@ const cleanupProfile = () => {
317
325
  throw new Error('[playwright-driver] refused SwiftShader launch arguments');
318
326
  }
319
327
  // one browser path per environment: the full, separately identified test app
320
- // locally; chromium_headless_shell on CI. never launch a branded user browser.
328
+ // on a local Mac; the bundled chromium everywhere else. never launch a
329
+ // branded user browser.
321
330
  const channelsToTry = hardwareGpuRequired ? ['chromium'] : [null];
322
331
  const launchWith = async (channel) => {
323
332
  const opts = channel
@@ -429,6 +438,13 @@ const cleanupProfile = () => {
429
438
  await context.addInitScript({
430
439
  content: 'Object.defineProperty(window, "__sootsimHostMeta", { value: ' + JSON.stringify(hostMeta) + ', configurable: true });' + bridgePortInject,
431
440
  });
441
+ // ASWebAuthenticationSession completes on a navigation to its callback
442
+ // scheme, which a browser popup cannot follow.
443
+ await forwardPopupSchemeNavigations(
444
+ context,
445
+ ${JSON.stringify(AUTH_BROWSER_EXTERNAL_NAVIGATION_EVENT)},
446
+ ${JSON.stringify(AUTH_BROWSER_SESSION_FRAGMENT_KEY)},
447
+ );
432
448
  await context.exposeBinding('__sootsimHostClose', async () => {
433
449
  await shutdown(0);
434
450
  });
package/cli/main.ts CHANGED
@@ -2,6 +2,7 @@
2
2
  // single lazy-imported command a run dispatches to. `./bin` imports this only
3
3
  // when none of its hidden entry points claimed the process.
4
4
 
5
+ import { automaticPeachUpdatesEnabled } from '../src/automatic-update-policy'
5
6
  import { rnxPublicBrand } from '../src/public-brand'
6
7
  import { levenshtein } from './levenshtein'
7
8
  import { COMMANDS, parseArgs, TOP_LEVEL_RUNTIME_COMMANDS } from './parse-args'
@@ -92,7 +93,7 @@ const isReadOnlyInvocation =
92
93
  parsed.commandArgs.includes('--dry-run')
93
94
 
94
95
  if (isCliUpdateWorker) {
95
- if (IS_STANDALONE) {
96
+ if (IS_STANDALONE && automaticPeachUpdatesEnabled()) {
96
97
  try {
97
98
  const { refreshCliUpdateCache } = await import('./cli-update')
98
99
  await refreshCliUpdateCache()
@@ -119,7 +120,12 @@ if (
119
120
  // interactive command runs next prints it once (stderr, so --json stdout
120
121
  // stays parseable) and deletes it. the daemon/serve processes skip it so a
121
122
  // background process can't eat the notice before a human sees it.
122
- if (!isReadOnlyInvocation && parsed.command !== 'serve' && parsed.command !== 'daemon') {
123
+ if (
124
+ automaticPeachUpdatesEnabled() &&
125
+ !isReadOnlyInvocation &&
126
+ parsed.command !== 'serve' &&
127
+ parsed.command !== 'daemon'
128
+ ) {
123
129
  const { consumeRuntimeUpgradeNotice } = await import('../src/home-paths')
124
130
  const notice = consumeRuntimeUpgradeNotice()
125
131
  if (notice) {
@@ -349,12 +349,8 @@ export const DECLARED_OUTBOUND_CALLS: Record<string, OutboundCallDeclaration> =
349
349
  category: 'guest_app_network',
350
350
  count: 1,
351
351
  },
352
- 'packages/peach-engine/src/engine/config-plugin-splash-loader.ts :: fetch :: manifestFetchUrl(origin)':
353
- { category: 'local_development', count: 1 },
354
352
  'packages/peach-engine/src/engine/emoji-metrics-font-loader.ts :: fetch :: attemptedBundledUrl':
355
353
  { category: 'same_origin_runtime', count: 1 },
356
- 'packages/peach-engine/src/engine/expo-app-config.ts :: fetch :: manifestFetchUrl(origin)':
357
- { category: 'local_development', count: 1 },
358
354
  'packages/peach-engine/src/engine/image-loader.ts :: fetch :: resolveImageFetchUri(uri)':
359
355
  { category: 'guest_app_network', count: 1 },
360
356
  'packages/peach-engine/src/engine/language-font-loader.ts :: fetch :: url': {
package/detox/index.ts CHANGED
@@ -10,6 +10,11 @@ import {
10
10
  readBrowserCompositeCaptureRequest,
11
11
  resolveBrowserCompositeCdpClip,
12
12
  } from '../../peach-engine/src/capture/browser-composite'
13
+ import {
14
+ AUTH_BROWSER_EXTERNAL_NAVIGATION_EVENT,
15
+ AUTH_BROWSER_SESSION_FRAGMENT_KEY,
16
+ forwardPopupSchemeNavigations,
17
+ } from '../../peach-engine/src/open-external'
13
18
  import { isAppBootTargetUrl } from '../../peach-engine/src/render-worker/app-load'
14
19
  import { SOOTSIM_SHELL_COMMAND_NAME } from '../src/menu'
15
20
  import { pollUntil } from '../src/poll-until'
@@ -55,7 +60,6 @@ let _reapBrowserNow: (() => void) | null = null
55
60
  let _context: BrowserContext | null = null
56
61
  let _page: Page | null = null
57
62
  let _synchronizationEnabled = false
58
- let _suspendedAppId: string | null = null
59
63
  let _browserCompromised: string | null = null
60
64
  let browserIdentity = 0
61
65
  let contextIdentity = 0
@@ -933,7 +937,22 @@ async function dispatchDeviceOrientation(orientation: 'portrait' | 'landscape')
933
937
  landscapeSide: DETOX_PLATFORM === 'ios' ? 'right' : 'left',
934
938
  },
935
939
  )
936
- await page.waitForTimeout(50)
940
+ // destination dimensions publish before the interface finishes turning.
941
+ await page.waitForFunction(
942
+ (next) => {
943
+ const settings = window.SootSim?.bridges?.settings?.get?.()
944
+ const rotation = Reflect.get(window, '__sootsimDeviceRotation')
945
+ return (
946
+ typeof settings === 'object' &&
947
+ settings !== null &&
948
+ 'orientation' in settings &&
949
+ settings.orientation === next &&
950
+ rotation?.active !== true
951
+ )
952
+ },
953
+ orientation,
954
+ { timeout: 15000 },
955
+ )
937
956
  }
938
957
 
939
958
  const MAX_SETTLED_SPEED_PT_PER_SEC = 2.0
@@ -1584,14 +1603,18 @@ function createSootSimElement(matcher: Matcher): SootSimElement {
1584
1603
  visible: node.layout.width > 0 && node.layout.height > 0,
1585
1604
  enabled: !node.accessibilityState?.disabled,
1586
1605
  ...node,
1587
- frame: node.absolutePosition
1588
- ? {
1589
- x: node.absolutePosition.x,
1590
- y: node.absolutePosition.y,
1591
- width: node.absolutePosition.width ?? node.frame?.width ?? 0,
1592
- height: node.absolutePosition.height ?? node.frame?.height ?? 0,
1593
- }
1594
- : node.frame,
1606
+ // the transformed rect when the node reports one; a node resolved
1607
+ // without a size (x and y only) keeps its own frame
1608
+ frame:
1609
+ node.absolutePosition?.width !== undefined &&
1610
+ node.absolutePosition.height !== undefined
1611
+ ? {
1612
+ x: node.absolutePosition.x,
1613
+ y: node.absolutePosition.y,
1614
+ width: node.absolutePosition.width,
1615
+ height: node.absolutePosition.height,
1616
+ }
1617
+ : node.frame,
1595
1618
  }
1596
1619
  },
1597
1620
 
@@ -1755,36 +1778,41 @@ export const device = {
1755
1778
  if (_browserCompromised) {
1756
1779
  throw new Error(`sootsim browser is compromised: ${_browserCompromised}`)
1757
1780
  }
1758
- if (
1759
- _page &&
1760
- opts?.newInstance === false &&
1761
- !opts.delete &&
1762
- !opts.recordVideoDir &&
1763
- _suspendedAppId
1764
- ) {
1781
+ if (_page && opts?.newInstance === false && !opts.delete && !opts.recordVideoDir) {
1782
+ // detox activates the running app without relaunching it; a url would
1783
+ // need a delivery path into the running guest that the adapter lacks.
1784
+ if (opts.url) {
1785
+ throw new Error(`SootSim cannot deliver a url to a running app: ${opts.url}`)
1786
+ }
1765
1787
  const page = _page
1766
- const appId = _suspendedAppId
1767
- await page.evaluate(
1768
- (id) => window.SootSim?.bridges?.mainShell?.launchApp?.(id),
1769
- appId,
1770
- )
1771
- await pollUntil(
1772
- () =>
1773
- page.evaluate(async (id) => {
1774
- const state = await window.SootSim?.bridges?.mainShell?.getState?.()
1775
- return (
1776
- state?.state === 'app' &&
1777
- state.activeApp === id &&
1778
- state.switcherPhase === 'idle'
1779
- )
1780
- }, appId),
1781
- Boolean,
1782
- {
1783
- timeoutMs: 10000,
1784
- label: `SootSim app ${appId} to resume`,
1785
- },
1786
- )
1787
- _suspendedAppId = null
1788
+ const appId = await page.evaluate(async () => {
1789
+ const state = await window.SootSim?.bridges?.mainShell?.getState?.()
1790
+ const guestApp = state?.guestApp
1791
+ if (typeof guestApp !== 'string') {
1792
+ throw new Error('SootSim main shell reports no guest app')
1793
+ }
1794
+ if (state?.state === 'app' && state.activeApp === guestApp) return null
1795
+ window.SootSim?.bridges?.mainShell?.launchApp?.(guestApp)
1796
+ return guestApp
1797
+ })
1798
+ if (appId !== null) {
1799
+ await pollUntil(
1800
+ () =>
1801
+ page.evaluate(async (id) => {
1802
+ const state = await window.SootSim?.bridges?.mainShell?.getState?.()
1803
+ return (
1804
+ state?.state === 'app' &&
1805
+ state.activeApp === id &&
1806
+ state.switcherPhase === 'idle'
1807
+ )
1808
+ }, appId),
1809
+ Boolean,
1810
+ {
1811
+ timeoutMs: 10000,
1812
+ label: `SootSim app ${appId} to resume`,
1813
+ },
1814
+ )
1815
+ }
1788
1816
  await waitForSootsimTree(page, 10000)
1789
1817
  if (opts?.userNotification) {
1790
1818
  await postRemotePushToSimulator(opts.userNotification, true)
@@ -1833,6 +1861,11 @@ export const device = {
1833
1861
  reapOwnedBrowser()
1834
1862
  throw error
1835
1863
  }
1864
+ await forwardPopupSchemeNavigations(
1865
+ _context,
1866
+ AUTH_BROWSER_EXTERNAL_NAVIGATION_EVENT,
1867
+ AUTH_BROWSER_SESSION_FRAGMENT_KEY,
1868
+ )
1836
1869
  await _context.exposeBinding('__sootsimHostCapture', async (source, value) => {
1837
1870
  const request = readBrowserCompositeCaptureRequest(value)
1838
1871
  const session = await source.page.context().newCDPSession(source.page)
@@ -3178,14 +3211,12 @@ export const device = {
3178
3211
 
3179
3212
  async sendToHome() {
3180
3213
  const page = getPage()
3181
- _suspendedAppId = await page.evaluate(async () => {
3214
+ await page.evaluate(async () => {
3182
3215
  const state = await window.SootSim?.bridges?.mainShell?.getState?.()
3183
- const appId = state?.activeApp
3184
- if (typeof appId !== 'string') {
3216
+ if (typeof state?.activeApp !== 'string') {
3185
3217
  throw new Error(`cannot send an inactive SootSim app home`)
3186
3218
  }
3187
3219
  window.SootSim?.bridges?.mainShell?.goHome?.()
3188
- return appId
3189
3220
  })
3190
3221
  await pollUntil(
3191
3222
  () =>
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var SIM_LONG_PRESS_MAX_MS = 5e3;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (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.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.630 | (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;