peachsim 0.1.1619 → 0.1.1620

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 (85) hide show
  1. package/cli/bridge-flow-runner.ts +39 -63
  2. package/cli/cloud-client.ts +26 -4
  3. package/cli/commands/platform.ts +29 -7
  4. package/cli/commands/record.ts +20 -15
  5. package/cli/drivers/playwright-sim-host.ts +12 -1
  6. package/cli/outbound-endpoints.ts +5 -3
  7. package/dist-lib/agent-daemon-client.cjs +1 -1
  8. package/dist-lib/agent-events.cjs +1 -1
  9. package/dist-lib/attached-projects.cjs +1 -1
  10. package/dist-lib/auth/shared-session.cjs +1 -1
  11. package/dist-lib/backend-origin.cjs +1 -1
  12. package/dist-lib/beta.cjs +1 -1
  13. package/dist-lib/beta.mjs +1 -1
  14. package/dist-lib/bridge-constants.cjs +1 -1
  15. package/dist-lib/bridge-contract-input.cjs +1 -1
  16. package/dist-lib/bridge-contract-input.mjs +1 -1
  17. package/dist-lib/bridge-contract.cjs +1 -1
  18. package/dist-lib/bridge-contract.mjs +1 -1
  19. package/dist-lib/bundle-channel.cjs +10 -5
  20. package/dist-lib/capture-contract.cjs +1 -1
  21. package/dist-lib/capture-contract.mjs +1 -1
  22. package/dist-lib/cloud-contract.cjs +1 -1
  23. package/dist-lib/cloud-contract.mjs +1 -1
  24. package/dist-lib/cloud-test-args.cjs +1 -1
  25. package/dist-lib/cloud-test-args.mjs +1 -1
  26. package/dist-lib/cloud.cjs +2 -2
  27. package/dist-lib/cloud.mjs +2 -2
  28. package/dist-lib/config.cjs +1 -1
  29. package/dist-lib/config.mjs +1 -1
  30. package/dist-lib/detox/index.cjs +1 -1
  31. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  32. package/dist-lib/expo-swift-bundle.cjs +10 -5
  33. package/dist-lib/expo-swift-metadata.cjs +1 -1
  34. package/dist-lib/expo-swift-metadata.mjs +1 -1
  35. package/dist-lib/home-paths.cjs +1 -1
  36. package/dist-lib/host/bridge-host.cjs +10 -5
  37. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  38. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  39. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  40. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  41. package/dist-lib/host/websocket-proxy.cjs +1 -1
  42. package/dist-lib/index.cjs +8 -1
  43. package/dist-lib/jump-to-source-babel.cjs +1 -1
  44. package/dist-lib/jump-to-source-native.cjs +1 -1
  45. package/dist-lib/kotlin-host.cjs +1 -1
  46. package/dist-lib/menu.cjs +1 -1
  47. package/dist-lib/menu.mjs +1 -1
  48. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  49. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  50. package/dist-lib/metro-production-bundle.cjs +1 -1
  51. package/dist-lib/metro-production-bundle.mjs +1 -1
  52. package/dist-lib/metro.cjs +8 -1
  53. package/dist-lib/native-app-identity-project.cjs +3 -1
  54. package/dist-lib/native-app-identity-project.mjs +3 -1
  55. package/dist-lib/native-app-identity.cjs +9 -1
  56. package/dist-lib/native-app-identity.mjs +9 -1
  57. package/dist-lib/native-firebase-metadata.cjs +1 -1
  58. package/dist-lib/native-firebase-metadata.mjs +1 -1
  59. package/dist-lib/plist.cjs +1 -1
  60. package/dist-lib/plist.mjs +1 -1
  61. package/dist-lib/profiles.cjs +1 -1
  62. package/dist-lib/public-brand.cjs +1 -1
  63. package/dist-lib/react-native-host-modules.cjs +1 -1
  64. package/dist-lib/react-native-host-modules.mjs +1 -1
  65. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  66. package/dist-lib/sdk.cjs +1 -1
  67. package/dist-lib/sdk.mjs +1 -1
  68. package/dist-lib/skills.cjs +85 -49
  69. package/dist-lib/swift-compile.cjs +10 -5
  70. package/dist-lib/swift-compile.mjs +10 -5
  71. package/dist-lib/swift-package.cjs +1 -1
  72. package/dist-lib/swift-package.mjs +1 -1
  73. package/dist-lib/swift-submit.cjs +1 -1
  74. package/dist-lib/swift-submit.mjs +1 -1
  75. package/dist-lib/swift-toolchain.cjs +1 -1
  76. package/dist-lib/swift.cjs +1 -1
  77. package/dist-lib/vite-swift.cjs +10 -5
  78. package/dist-lib/vite.cjs +1 -1
  79. package/dist-lib/worklet-executable.cjs +1 -1
  80. package/dist-lib/worklet-executable.mjs +1 -1
  81. package/package.json +1 -1
  82. package/src/cloud.ts +2 -2
  83. package/src/native-app-identity-project.ts +2 -0
  84. package/src/native-app-identity.ts +17 -0
  85. package/src/swift-compile.ts +10 -4
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1619 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1620 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -4585,6 +4585,8 @@ var init_supported_native_packages = __esm({
4585
4585
  // coverage
4586
4586
  "@fingerprintjs/fingerprintjs-pro-react-native",
4587
4587
  // seam
4588
+ "@fishjam-cloud/react-native-client",
4589
+ // seam
4588
4590
  "@fishjam-cloud/react-native-webrtc",
4589
4591
  // seam
4590
4592
  "@fugood/react-native-audio-pcm-stream",
@@ -4877,6 +4879,8 @@ var init_supported_native_packages = __esm({
4877
4879
  // seam+coverage
4878
4880
  "expo-hardware-buttons",
4879
4881
  // seam
4882
+ "expo-hinge",
4883
+ // seam
4880
4884
  "expo-iap",
4881
4885
  // seam
4882
4886
  "expo-ignore-battery-optimizations",
@@ -5079,6 +5083,8 @@ var init_supported_native_packages = __esm({
5079
5083
  // coverage
5080
5084
  "react-native-calendar-events",
5081
5085
  // seam
5086
+ "react-native-callkeep",
5087
+ // seam
5082
5088
  "react-native-cashfree-pg-sdk",
5083
5089
  // seam
5084
5090
  "react-native-cloud-storage",
@@ -6788,6 +6794,19 @@ var init_registry = __esm({
6788
6794
  }
6789
6795
  ]
6790
6796
  },
6797
+ "expo-hinge": {
6798
+ category: "Device & Platform",
6799
+ stubType: "native",
6800
+ versions: [
6801
+ {
6802
+ range: ">=58.0.0",
6803
+ coverage: 0.6,
6804
+ note: "real upstream package \u2014 not intercepted. the JS (isAvailable, getHinge, addHingeListener, useHinge) runs from the bundle against the ExpoHinge native module (native-seams/expo-hinge.ts, ported from the 58.0.1 Swift and Kotlin observers). iOS reports the iPhone Duo fold bus as UIHingeInteraction does (angle in degrees, closed, partiallyOpen or fullyOpen) on iOS 27.1 and later; every other iOS device has no hinge. Android has no device spec with a hinge angle sensor, so isAvailable follows API level 30 and getHinge stays null",
6805
+ working: "isAvailable from the spec OS version (iOS 27.1, Android API 30); getHinge answering synchronously from the cached fold state; hingeChange sent to observed listeners on every angle or status change and with null when the spec loses its hinge; useHinge first render already holding the current value",
6806
+ missing: "Android hinge angle sensor and Jetpack WindowManager FoldingFeature states (no foldable Android device spec exists); iOS status unknown"
6807
+ }
6808
+ ]
6809
+ },
6791
6810
  "expo-cellular": {
6792
6811
  category: "Device & Platform",
6793
6812
  stubType: "native",
@@ -10015,10 +10034,10 @@ var init_registry = __esm({
10015
10034
  versions: [
10016
10035
  {
10017
10036
  range: ">=4.0.0",
10018
- coverage: 0.85,
10019
- note: 'full RNCallKeep surface as load-safe noop \u2014 CallKit / ConnectionService is unavailable in the iOS simulator too, so consumer code that branches on getCalls=[] takes the no-call path identically. matches docs/compat-scoring.md "score it high only when the full public API surface is present and returns the same unavailable/clean state an app should expect in development."',
10020
- working: "RNCallKeep.setup, setAvailable, displayIncomingCall, startCall, endCall, endAllCalls, answerIncomingCall, rejectCall, setMutedCall, setOnHold, sendDTMF, updateDisplay, getCalls (empty), registerPhoneAccount, setReachable, hasPhoneAccount, checkIfBusy, checkSpeaker, isCallActive, END_CALL_REASONS / AUDIO_ROUTE / HANDLE_TYPE constants, all addEventListener handlers",
10021
- missing: "no system call screen \u2014 same constraint as the iOS simulator. recommended on web: integrate WebRTC + a custom call UI surface"
10037
+ coverage: 0.5,
10038
+ note: "published JS runs over the RNCallKeep iOS module ported from RNCallKeep.m onto the iOS 27 simulator CallKit model: the simulator has no call screen, so incoming and outgoing calls end right after they start",
10039
+ working: "iOS setup and stored settings, displayIncomingCall with its reachability timeout, startCall, answer, end, end all, hold, mute and DTMF transactions with their provider events, start failure events, report end, connecting and connected reports, getCalls, isCallActive, checkIfBusy, checkSpeaker, audio routes, delayed events with didLoadWithEvents and getInitialEvents; Android settings, initial events and connection lookups",
10040
+ missing: "device call screen, audio session activation events, VoIP push and Siri start call intents on iOS; on Android every Telecom path (phone account registration and checks, showing, placing and ending calls, permissions, managed call state, audio routes) raises unsupported"
10022
10041
  }
10023
10042
  ]
10024
10043
  },
@@ -10316,9 +10335,33 @@ var init_registry = __esm({
10316
10335
  {
10317
10336
  range: ">=0.31.0",
10318
10337
  coverage: 0.6,
10319
- note: "published JS runs over the shared WebRTCModule seam, plus the fork's CallKit, PushKit and audio output methods ported from ios/RCTWebRTC over the iOS 27 simulator CallKit model: incoming calls end because the simulator has no call screen, outgoing calls run with no system UI",
10338
+ note: "published JS runs over the shared WebRTCModule seam, plus the fork's CallKit, PushKit and audio output methods ported from ios/RCTWebRTC over the iOS 27 simulator CallKit model: calls end right after they start because the simulator has no call screen",
10320
10339
  working: "peer connections, capture, data channels, stats and RTCView frames as react-native-webrtc; CallKit start, end, hold, mute, outgoing connect, ring timeout and callKitActionPerformed events; VoIP token and pending call getters; audio outputs and speaker override",
10321
- missing: "device call screen and in-call pill, PushKit pushes, audio route picker, custom audio and video tracks, camera frame processor, audio sink, broadcast pickers, livestream status, video effects and Android Telecom"
10340
+ missing: "device call screen and in-call pill, PushKit pushes, audio route picker, custom audio and video tracks, camera frame processor, audio sink, video effects and Android Telecom"
10341
+ }
10342
+ ]
10343
+ },
10344
+ "@fishjam-cloud/react-native-client": {
10345
+ category: "Networking",
10346
+ stubType: "native",
10347
+ versions: [
10348
+ {
10349
+ range: ">=0.31.0",
10350
+ coverage: 0.6,
10351
+ note: "the package ships no native code; its JavaScript runs unchanged over the @fishjam-cloud/react-native-webrtc seam. as on the iOS simulator, presentBroadcastPicker and presentLivestreamBroadcastPicker reject unsupported_platform, and livestream status stays idle because no broadcast extension runs",
10352
+ working: "FishjamProvider polyfills, peer connections, camera and microphone capture, permissions queries, data channels, RTCView frames, CallKit and VoIP hooks as the webrtc seam",
10353
+ missing: "getDisplayMedia, which the iOS simulator aborts but the shared seam serves, custom audio sources, PiP, the broadcast extension and Android foreground service and Telecom"
10354
+ }
10355
+ ]
10356
+ },
10357
+ "@fishjam-cloud/ios-expo-voip": {
10358
+ category: "Networking",
10359
+ stubType: "build-only",
10360
+ versions: [
10361
+ {
10362
+ range: ">=0.31.0",
10363
+ coverage: 1,
10364
+ note: "build-only: the package ships no JavaScript, only an ExpoAppDelegateSubscriber that calls VoIPManager.registerForVoIPPushes at launch and VoIPManager.handleContinueUserActivity for INStart call intents. The simulator issues no PushKit token and Peach delivers no call intents, so the WebRTCModule seam's null VoIP token and empty pending call getters are exactly what VoIPManager reports"
10322
10365
  }
10323
10366
  ]
10324
10367
  },
@@ -17557,7 +17600,7 @@ var init_registry = __esm({
17557
17600
  {
17558
17601
  range: ">=0.4.0",
17559
17602
  coverage: 0.6,
17560
- note: "iOS CallKit as the iOS 27 simulator runs it: no call screen, and incoming calls end as the simulator ends them",
17603
+ note: "iOS CallKit as the iOS 27 simulator runs it: no call screen, so incoming and outgoing calls end as the simulator ends them",
17561
17604
  working: "outgoing and incoming call sessions, answer fulfill requests, end, report ended, mute, hold, DTMF and video actions, call timeouts, session events with JS-ready queueing, audio session configuration and state, capture session state, and the VoIP push token",
17562
17605
  missing: "device call screen and status bar pill, VoIP push delivery, Siri and recents call intents, audio session activation and the dialtone, and the Android Core-Telecom module"
17563
17606
  }
@@ -29833,7 +29876,7 @@ function swiftTargetDependencies(files2, targets) {
29833
29876
  }
29834
29877
  function swiftArtifactHash(input, release, moduleRoot) {
29835
29878
  const hash = (0, import_node_crypto5.createHash)("sha256");
29836
- hash.update(`swift-compile/v46
29879
+ hash.update(`swift-compile/v47
29837
29880
  ${release}
29838
29881
  `);
29839
29882
  if (input.oneModule) hash.update("one-module\n");
@@ -30358,9 +30401,14 @@ function compiledSwiftSources(files2, targets) {
30358
30401
  const orderedTargets = [...targets].sort((a, b) => b.path.length - a.path.length);
30359
30402
  for (const [file, contents] of Object.entries(files2)) {
30360
30403
  if (!file.endsWith(".swift")) continue;
30361
- const owner = orderedTargets.find(
30362
- (candidate) => candidate.path === "." || file.startsWith(`${candidate.path}/`)
30363
- );
30404
+ const owner = orderedTargets.find((candidate) => {
30405
+ const prefix = candidate.path === "." ? "" : `${candidate.path}/`;
30406
+ if (!file.startsWith(prefix)) return false;
30407
+ const relative4 = file.slice(prefix.length);
30408
+ return !candidate.exclude?.some(
30409
+ (excluded) => relative4 === excluded || relative4.startsWith(`${excluded}/`)
30410
+ );
30411
+ });
30364
30412
  if (/(?:^|\/)Package(?:@swift-[\d.]+)?\.swift$/.test(file) && (!owner || /^Package(?:@swift-[\d.]+)?\.swift$/.test(file))) {
30365
30413
  compiled.set(file, contents);
30366
30414
  continue;
@@ -58217,6 +58265,8 @@ function isNativeAppIdentity(value) {
58217
58265
  return false;
58218
58266
  if (value.shareIntoAppGroupId !== void 0 && typeof value.shareIntoAppGroupId !== "string")
58219
58267
  return false;
58268
+ if (value.rtcAppGroupIdentifier !== void 0 && typeof value.rtcAppGroupIdentifier !== "string")
58269
+ return false;
58220
58270
  if (value.applicationDisplayName !== void 0 && typeof value.applicationDisplayName !== "string")
58221
58271
  return false;
58222
58272
  if (value.rootModuleName !== void 0 && typeof value.rootModuleName !== "string")
@@ -58287,6 +58337,7 @@ function readNativeAppIdentity(value) {
58287
58337
  ...value.defaultScreenOrientationMask === void 0 ? {} : { defaultScreenOrientationMask: value.defaultScreenOrientationMask },
58288
58338
  ...value.backgroundModes === void 0 ? {} : { backgroundModes: [...value.backgroundModes] },
58289
58339
  ...value.shareIntoAppGroupId === void 0 ? {} : { shareIntoAppGroupId: value.shareIntoAppGroupId },
58340
+ ...value.rtcAppGroupIdentifier === void 0 ? {} : { rtcAppGroupIdentifier: value.rtcAppGroupIdentifier },
58290
58341
  ...value.urlQuerySchemes === void 0 ? {} : { urlQuerySchemes: [...value.urlQuerySchemes] },
58291
58342
  ...value.oneUpdates === void 0 ? {} : {
58292
58343
  oneUpdates: {
@@ -58383,6 +58434,7 @@ function readNativeAppIdentityFromXcodeTarget(app, parseInfoPlist = parsePlistSo
58383
58434
  dictionary.EXDefaultScreenOrientationMask
58384
58435
  );
58385
58436
  const shareIntoAppGroupId = nonEmptyString2(dictionary.ExpoShareIntoAppGroupId);
58437
+ const rtcAppGroupIdentifier = nonEmptyString2(dictionary.RTCAppGroupIdentifier);
58386
58438
  const rootModuleName = readRootModuleName(
58387
58439
  app.allSources.filter((file) => /\.(?:swift|mm|m)$/.test(file) && import_node_fs43.default.existsSync(file)).map((file) => import_node_fs43.default.readFileSync(file, "utf8"))
58388
58440
  );
@@ -58418,6 +58470,7 @@ function readNativeAppIdentityFromXcodeTarget(app, parseInfoPlist = parsePlistSo
58418
58470
  permissionUsageDescriptions,
58419
58471
  urlQuerySchemes,
58420
58472
  ...shareIntoAppGroupId ? { shareIntoAppGroupId } : {},
58473
+ ...rtcAppGroupIdentifier ? { rtcAppGroupIdentifier } : {},
58421
58474
  backgroundTaskIdentifiers,
58422
58475
  backgroundModes,
58423
58476
  appIntentIdentifiers
@@ -67192,6 +67245,15 @@ __export(bridge_flow_runner_exports, {
67192
67245
  parseFlowSteps: () => parseFlowSteps,
67193
67246
  resolveFlowScreenshotPathWithMode: () => resolveFlowScreenshotPathWithMode
67194
67247
  });
67248
+ function stepCeilingMs(step) {
67249
+ const waitForTimeout = typeof step.waitFor?.timeout === "number" ? step.waitFor.timeout : 0;
67250
+ const extendedWaitTimeout = typeof step.extendedWaitUntil?.timeout === "number" ? step.extendedWaitUntil.timeout : 0;
67251
+ return Math.max(
67252
+ 6e4,
67253
+ scaledTimeout(waitForTimeout) + 15e3,
67254
+ scaledTimeout(extendedWaitTimeout) + 15e3
67255
+ );
67256
+ }
67195
67257
  function assertSupportedSelector(selector) {
67196
67258
  if (!selector || typeof selector !== "object") return;
67197
67259
  const keys = Object.keys(selector);
@@ -69440,8 +69502,9 @@ var init_bridge_flow_runner = __esm({
69440
69502
  return;
69441
69503
  }
69442
69504
  }
69505
+ const isContainer = !!(step.runFlow || step.repeat || step.retry);
69443
69506
  try {
69444
- if (this.recordingEnabled && this.recordingStartedAtMs == null && !step.launchApp && !step.runFlow && !step.repeat && !step.retry) {
69507
+ if (this.recordingEnabled && this.recordingStartedAtMs == null && !step.launchApp && !isContainer) {
69445
69508
  await this.ensureRecordingStarted();
69446
69509
  }
69447
69510
  await onStepStart?.();
@@ -69449,11 +69512,8 @@ var init_bridge_flow_runner = __esm({
69449
69512
  const hasBoundedWait = !!// taps combine bounded lookup, settling and delivery. a wall-clock
69450
69513
  // watchdog can finish the step while that action is still running.
69451
69514
  // let these operations finish before starting the next command.
69452
- (step.tapOn || step.doubleTapOn || step.longPressOn || step.extendedWaitUntil || step.waitFor || step.scrollUntilVisible || step.launchApp || // deep links own the same bounded guest launch and tree waits.
69453
- step.openLink || step.runFlow || // retry reruns its body on failure, so its wall time is the body's
69454
- // times the retry count — the 10s no-progress watchdog is the wrong
69455
- // budget and would report "bridge probably hung" for a slow retry.
69456
- step.retry || // runScript http calls are synchronous with a 5-minute upstream
69515
+ (step.tapOn || step.doubleTapOn || step.longPressOn || step.extendedWaitUntil || step.waitFor || step.scrollUntilVisible || // deep links own the same bounded guest launch and tree waits.
69516
+ step.openLink || // runScript http calls are synchronous with a 5-minute upstream
69457
69517
  // timeout — the 10s watchdog would kill legitimate setup scripts.
69458
69518
  step.runScript || // takeScreenshot self-governs: it retries a bounded visual settle that
69459
69519
  // already fails with its own reason. sharing the watchdog's 10s budget
@@ -69468,22 +69528,23 @@ var init_bridge_flow_runner = __esm({
69468
69528
  const STEP_WATCHDOG_MS = 1e4;
69469
69529
  const body = this.runStepInner(step);
69470
69530
  let screenshotPath;
69471
- if (hasBoundedWait) {
69531
+ if (isContainer || step.launchApp) {
69472
69532
  const result = await body;
69473
69533
  if (typeof result === "string") screenshotPath = result;
69474
69534
  } else {
69535
+ const deadlineMs = hasBoundedWait ? stepCeilingMs(step) : STEP_WATCHDOG_MS;
69475
69536
  let timer = null;
69476
- const watchdog = new Promise((_, reject) => {
69537
+ const deadline = new Promise((_, reject) => {
69477
69538
  timer = setTimeout(() => {
69478
69539
  reject(
69479
69540
  new Error(
69480
- `step watchdog: ${stepName} made no progress in ${STEP_WATCHDOG_MS}ms \u2014 bridge or bundle probably hung`
69541
+ hasBoundedWait ? `step ${stepIndex + 1} (${stepName}) exceeded ${deadlineMs}ms deadline` : `step watchdog: ${stepName} made no progress in ${STEP_WATCHDOG_MS}ms \u2014 bridge or bundle probably hung`
69481
69542
  )
69482
69543
  );
69483
- }, STEP_WATCHDOG_MS);
69544
+ }, deadlineMs);
69484
69545
  });
69485
69546
  try {
69486
- const result = await Promise.race([body, watchdog]);
69547
+ const result = await Promise.race([body, deadline]);
69487
69548
  if (typeof result === "string") screenshotPath = result;
69488
69549
  } finally {
69489
69550
  if (timer) clearTimeout(timer);
@@ -69799,15 +69860,6 @@ var init_bridge_flow_runner = __esm({
69799
69860
  async runFlowBody(steps) {
69800
69861
  for (let i = 0; i < steps.length; i++) {
69801
69862
  const step = steps[i];
69802
- const explicitWait = typeof step.wait === "number" ? step.wait : 0;
69803
- const waitForTimeout = typeof step.waitFor?.timeout === "number" ? step.waitFor.timeout : 0;
69804
- const extendedWaitTimeout = typeof step.extendedWaitUntil?.timeout === "number" ? step.extendedWaitUntil.timeout : 0;
69805
- const stepCeiling = Math.max(
69806
- 6e4,
69807
- explicitWait + 15e3,
69808
- scaledTimeout(waitForTimeout) + 15e3,
69809
- scaledTimeout(extendedWaitTimeout) + 15e3
69810
- );
69811
69863
  if (this.liveStatus) {
69812
69864
  await this.liveStatus.waitWhilePaused();
69813
69865
  }
@@ -69830,23 +69882,7 @@ var init_bridge_flow_runner = __esm({
69830
69882
  );
69831
69883
  };
69832
69884
  try {
69833
- if (step.runFlow || step.launchApp) {
69834
- await this.runStep(step, i, onStepStart);
69835
- } else {
69836
- await Promise.race([
69837
- this.runStep(step, i, onStepStart),
69838
- new Promise(
69839
- (_, reject) => setTimeout(
69840
- () => reject(
69841
- new Error(
69842
- `step ${i + 1} (${Object.keys(step)[0]}) exceeded ${stepCeiling}ms deadline`
69843
- )
69844
- ),
69845
- stepCeiling
69846
- )
69847
- )
69848
- ]);
69849
- }
69885
+ await this.runStep(step, i, onStepStart);
69850
69886
  } catch (error) {
69851
69887
  const last = this.flowTraceSteps[this.flowTraceSteps.length - 1];
69852
69888
  if (!(last && last.stepIndex === i && last.startedAtMs >= liveStartedAtMs)) {
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1619 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1620 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1490,7 +1490,7 @@ var REACTOR_FLAG = '"-Xclang-linker", "-mexec-model=reactor",\n';
1490
1490
  var MULTI_MANIFEST_VERSION = 38;
1491
1491
  function swiftArtifactHash(input, release, moduleRoot) {
1492
1492
  const hash = (0, import_node_crypto2.createHash)("sha256");
1493
- hash.update(`swift-compile/v46
1493
+ hash.update(`swift-compile/v47
1494
1494
  ${release}
1495
1495
  `);
1496
1496
  if (input.oneModule) hash.update("one-module\n");
@@ -2037,9 +2037,14 @@ function compiledSwiftSources(files, targets) {
2037
2037
  const orderedTargets = [...targets].sort((a, b) => b.path.length - a.path.length);
2038
2038
  for (const [file, contents] of Object.entries(files)) {
2039
2039
  if (!file.endsWith(".swift")) continue;
2040
- const owner = orderedTargets.find(
2041
- (candidate) => candidate.path === "." || file.startsWith(`${candidate.path}/`)
2042
- );
2040
+ const owner = orderedTargets.find((candidate) => {
2041
+ const prefix = candidate.path === "." ? "" : `${candidate.path}/`;
2042
+ if (!file.startsWith(prefix)) return false;
2043
+ const relative = file.slice(prefix.length);
2044
+ return !candidate.exclude?.some(
2045
+ (excluded) => relative === excluded || relative.startsWith(`${excluded}/`)
2046
+ );
2047
+ });
2043
2048
  if (/(?:^|\/)Package(?:@swift-[\d.]+)?\.swift$/.test(file) && (!owner || /^Package(?:@swift-[\d.]+)?\.swift$/.test(file))) {
2044
2049
  compiled.set(file, contents);
2045
2050
  continue;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1619 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1620 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/swift-compile.ts
4
4
  import { spawn as spawn2, execFileSync } from "node:child_process";
@@ -1438,7 +1438,7 @@ var REACTOR_FLAG = '"-Xclang-linker", "-mexec-model=reactor",\n';
1438
1438
  var MULTI_MANIFEST_VERSION = 38;
1439
1439
  function swiftArtifactHash(input, release, moduleRoot) {
1440
1440
  const hash = createHash2("sha256");
1441
- hash.update(`swift-compile/v46
1441
+ hash.update(`swift-compile/v47
1442
1442
  ${release}
1443
1443
  `);
1444
1444
  if (input.oneModule) hash.update("one-module\n");
@@ -1985,9 +1985,14 @@ function compiledSwiftSources(files, targets) {
1985
1985
  const orderedTargets = [...targets].sort((a, b) => b.path.length - a.path.length);
1986
1986
  for (const [file, contents] of Object.entries(files)) {
1987
1987
  if (!file.endsWith(".swift")) continue;
1988
- const owner = orderedTargets.find(
1989
- (candidate) => candidate.path === "." || file.startsWith(`${candidate.path}/`)
1990
- );
1988
+ const owner = orderedTargets.find((candidate) => {
1989
+ const prefix = candidate.path === "." ? "" : `${candidate.path}/`;
1990
+ if (!file.startsWith(prefix)) return false;
1991
+ const relative = file.slice(prefix.length);
1992
+ return !candidate.exclude?.some(
1993
+ (excluded) => relative === excluded || relative.startsWith(`${excluded}/`)
1994
+ );
1995
+ });
1991
1996
  if (/(?:^|\/)Package(?:@swift-[\d.]+)?\.swift$/.test(file) && (!owner || /^Package(?:@swift-[\d.]+)?\.swift$/.test(file))) {
1992
1997
  compiled.set(file, contents);
1993
1998
  continue;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1619 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1620 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1619 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1620 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/swift-package.ts
4
4
  function isSwiftManifestFile(file) {
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1619 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1620 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1619 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1620 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/swiftContract.ts
4
4
  function isSwiftResourcePath(value) {
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1619 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1620 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1619 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1620 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1619 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1620 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -3319,7 +3319,7 @@ var REACTOR_FLAG = '"-Xclang-linker", "-mexec-model=reactor",\n';
3319
3319
  var MULTI_MANIFEST_VERSION = 38;
3320
3320
  function swiftArtifactHash(input, release, moduleRoot) {
3321
3321
  const hash = (0, import_node_crypto2.createHash)("sha256");
3322
- hash.update(`swift-compile/v46
3322
+ hash.update(`swift-compile/v47
3323
3323
  ${release}
3324
3324
  `);
3325
3325
  if (input.oneModule) hash.update("one-module\n");
@@ -3866,9 +3866,14 @@ function compiledSwiftSources(files2, targets) {
3866
3866
  const orderedTargets = [...targets].sort((a, b) => b.path.length - a.path.length);
3867
3867
  for (const [file, contents] of Object.entries(files2)) {
3868
3868
  if (!file.endsWith(".swift")) continue;
3869
- const owner = orderedTargets.find(
3870
- (candidate) => candidate.path === "." || file.startsWith(`${candidate.path}/`)
3871
- );
3869
+ const owner = orderedTargets.find((candidate) => {
3870
+ const prefix = candidate.path === "." ? "" : `${candidate.path}/`;
3871
+ if (!file.startsWith(prefix)) return false;
3872
+ const relative = file.slice(prefix.length);
3873
+ return !candidate.exclude?.some(
3874
+ (excluded) => relative === excluded || relative.startsWith(`${excluded}/`)
3875
+ );
3876
+ });
3872
3877
  if (/(?:^|\/)Package(?:@swift-[\d.]+)?\.swift$/.test(file) && (!owner || /^Package(?:@swift-[\d.]+)?\.swift$/.test(file))) {
3873
3878
  compiled.set(file, contents);
3874
3879
  continue;
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1619 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1620 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1619 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1620 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1619 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1620 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/worklet-executable.ts
4
4
  import { parse } from "acorn";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "peachsim",
3
- "version": "0.1.1619",
3
+ "version": "0.1.1620",
4
4
  "description": "Vite and Metro plugins, testing drivers, and SDK exports for peach.",
5
5
  "author": "Tamagui LLC",
6
6
  "license": "SEE LICENSE IN LICENSE",
package/src/cloud.ts CHANGED
@@ -53,9 +53,9 @@ const DEFAULT_WAIT_READY_MS = 20_000
53
53
  // code on the body is what decides: `rate_limited` carries a `retry-after`
54
54
  // and is worth waiting for, while `concurrency_limit` refuses until the
55
55
  // customer stops something and retrying only hammers a closed door.
56
- // `early_access` and 402 never change on retry either.
56
+ // 402 never changes on retry either.
57
57
  const CLOUD_MAX_RETRIES = 2
58
- const CLOUD_NEVER_RETRY_CODES = new Set(['concurrency_limit', 'early_access'])
58
+ const CLOUD_NEVER_RETRY_CODES = new Set(['concurrency_limit'])
59
59
 
60
60
  export type RemoteCommand = {
61
61
  type: (typeof RNX_CLOUD_COMMAND_TYPES)[number]
@@ -128,6 +128,7 @@ export function readNativeAppIdentityFromXcodeTarget(
128
128
  dictionary.EXDefaultScreenOrientationMask,
129
129
  )
130
130
  const shareIntoAppGroupId = nonEmptyString(dictionary.ExpoShareIntoAppGroupId)
131
+ const rtcAppGroupIdentifier = nonEmptyString(dictionary.RTCAppGroupIdentifier)
131
132
  const rootModuleName = readRootModuleName(
132
133
  app.allSources
133
134
  .filter((file) => /\.(?:swift|mm|m)$/.test(file) && fs.existsSync(file))
@@ -173,6 +174,7 @@ export function readNativeAppIdentityFromXcodeTarget(
173
174
  permissionUsageDescriptions,
174
175
  urlQuerySchemes,
175
176
  ...(shareIntoAppGroupId ? { shareIntoAppGroupId } : {}),
177
+ ...(rtcAppGroupIdentifier ? { rtcAppGroupIdentifier } : {}),
176
178
  backgroundTaskIdentifiers,
177
179
  backgroundModes,
178
180
  appIntentIdentifiers,
@@ -60,6 +60,7 @@ export interface NativeAppIdentity {
60
60
  ipadSupportedInterfaceOrientations?: readonly string[]
61
61
  defaultScreenOrientationMask?: string
62
62
  shareIntoAppGroupId?: string
63
+ rtcAppGroupIdentifier?: string
63
64
  alternateIconNames?: readonly string[]
64
65
  appIconArtwork?: NativeAppIconArtwork
65
66
  // resolved Reanimated compile flags from the native build inputs.
@@ -150,6 +151,11 @@ export function isNativeAppIdentity(value: unknown): value is NativeAppIdentity
150
151
  typeof value.shareIntoAppGroupId !== 'string'
151
152
  )
152
153
  return false
154
+ if (
155
+ value.rtcAppGroupIdentifier !== undefined &&
156
+ typeof value.rtcAppGroupIdentifier !== 'string'
157
+ )
158
+ return false
153
159
  if (
154
160
  value.applicationDisplayName !== undefined &&
155
161
  typeof value.applicationDisplayName !== 'string'
@@ -276,6 +282,9 @@ export function readNativeAppIdentity(value: unknown): NativeAppIdentity | null
276
282
  ...(value.shareIntoAppGroupId === undefined
277
283
  ? {}
278
284
  : { shareIntoAppGroupId: value.shareIntoAppGroupId }),
285
+ ...(value.rtcAppGroupIdentifier === undefined
286
+ ? {}
287
+ : { rtcAppGroupIdentifier: value.rtcAppGroupIdentifier }),
279
288
  ...(value.urlQuerySchemes === undefined
280
289
  ? {}
281
290
  : { urlQuerySchemes: [...value.urlQuerySchemes] }),
@@ -857,6 +866,13 @@ function nativeAppIdentityFromIos(
857
866
  : undefined
858
867
  if (shareIntoAppGroupId === null)
859
868
  throw new Error('native app Info.plist ExpoShareIntoAppGroupId is unresolved')
869
+ const declaredRtcGroup = dictionary.RTCAppGroupIdentifier
870
+ const rtcAppGroupIdentifier =
871
+ typeof declaredRtcGroup === 'string'
872
+ ? resolveBuildSetting(declaredRtcGroup, settings)
873
+ : undefined
874
+ if (rtcAppGroupIdentifier === null)
875
+ throw new Error('native app Info.plist RTCAppGroupIdentifier is unresolved')
860
876
  const querySchemes = dictionary.LSApplicationQueriesSchemes
861
877
  if (querySchemes !== undefined && !Array.isArray(querySchemes)) {
862
878
  throw new Error('native app Info.plist LSApplicationQueriesSchemes is not an array')
@@ -991,6 +1007,7 @@ function nativeAppIdentityFromIos(
991
1007
  permissionUsageDescriptions,
992
1008
  urlQuerySchemes,
993
1009
  ...(shareIntoAppGroupId === undefined ? {} : { shareIntoAppGroupId }),
1010
+ ...(rtcAppGroupIdentifier === undefined ? {} : { rtcAppGroupIdentifier }),
994
1011
  backgroundTaskIdentifiers: backgroundTaskIdentifiers.every((value) => value !== null)
995
1012
  ? backgroundTaskIdentifiers
996
1013
  : [],
@@ -719,6 +719,7 @@ export function swiftArtifactHash(
719
719
  moduleRoot: string,
720
720
  ): string {
721
721
  const hash = createHash('sha256')
722
+ // v47: target ownership honors exclusions before lowering manifest-named files
722
723
  // v46: view builder literals compile as design-time lookups
723
724
  // v45: the link runs no wasm-opt pass, whatever the compiling machine has
724
725
  // v44: fixed-signature optional type methods retain metatype dispatch
@@ -765,7 +766,7 @@ export function swiftArtifactHash(
765
766
  // v6: app and scene delegate classes compile final
766
767
  // (v5: a target declaring resources gets SwiftPM's Bundle.module accessor;
767
768
  // v4: sources compile through swiftSourceAsIOS)
768
- hash.update(`swift-compile/v46\n${release}\n`)
769
+ hash.update(`swift-compile/v47\n${release}\n`)
769
770
  if (input.oneModule) hash.update('one-module\n')
770
771
  hash.update(swiftModuleDigest(moduleRoot))
771
772
  for (const file of Object.keys(input.files).sort()) {
@@ -1565,9 +1566,14 @@ function compiledSwiftSources(
1565
1566
  const orderedTargets = [...targets].sort((a, b) => b.path.length - a.path.length)
1566
1567
  for (const [file, contents] of Object.entries(files)) {
1567
1568
  if (!file.endsWith('.swift')) continue
1568
- const owner = orderedTargets.find(
1569
- (candidate) => candidate.path === '.' || file.startsWith(`${candidate.path}/`),
1570
- )
1569
+ const owner = orderedTargets.find((candidate) => {
1570
+ const prefix = candidate.path === '.' ? '' : `${candidate.path}/`
1571
+ if (!file.startsWith(prefix)) return false
1572
+ const relative = file.slice(prefix.length)
1573
+ return !candidate.exclude?.some(
1574
+ (excluded) => relative === excluded || relative.startsWith(`${excluded}/`),
1575
+ )
1576
+ })
1571
1577
  if (
1572
1578
  /(?:^|\/)Package(?:@swift-[\d.]+)?\.swift$/.test(file) &&
1573
1579
  (!owner || /^Package(?:@swift-[\d.]+)?\.swift$/.test(file))