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
@@ -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;
@@ -835,6 +835,87 @@ function readBrowserCompositeCaptureRequest(value) {
835
835
  return request;
836
836
  }
837
837
 
838
+ // ../peach-engine/src/open-external.ts
839
+ var AUTH_BROWSER_EXTERNAL_NAVIGATION_EVENT = "peach:auth-browser-external-navigation";
840
+ var AUTH_BROWSER_SESSION_FRAGMENT_KEY = "peach-auth-session";
841
+ async function forwardPopupSchemeNavigations(context, eventName, sessionFragmentKey) {
842
+ const readiness = /* @__PURE__ */ new Map();
843
+ const pendingOwner = (identity) => {
844
+ const existing = readiness.get(identity);
845
+ if (existing) return existing;
846
+ let resolve;
847
+ const owner = new Promise((done) => {
848
+ resolve = done;
849
+ });
850
+ const pending = { owner, resolve };
851
+ readiness.set(identity, pending);
852
+ return pending;
853
+ };
854
+ await context.exposeBinding("__peachAuthBrowserReady", async (source, identity) => {
855
+ if (typeof identity !== "string") throw new Error("invalid auth browser session");
856
+ const owner = await pendingOwner(identity).owner;
857
+ readiness.delete(identity);
858
+ if (owner !== source.page) throw new Error("auth browser popup ownership mismatch");
859
+ });
860
+ const browserSchemes = /* @__PURE__ */ new Set([
861
+ "http:",
862
+ "https:",
863
+ "about:",
864
+ "blob:",
865
+ "data:",
866
+ "file:",
867
+ "javascript:"
868
+ ]);
869
+ context.on("page", (popup) => {
870
+ let owner = null;
871
+ const opener = popup.opener();
872
+ void opener.catch(() => {
873
+ });
874
+ const recordSession = () => {
875
+ if (owner) return;
876
+ try {
877
+ owner = new URLSearchParams(new URL(popup.url()).hash.slice(1)).get(
878
+ sessionFragmentKey
879
+ );
880
+ if (owner) {
881
+ const identity = owner;
882
+ const pending = pendingOwner(identity);
883
+ void opener.then(pending.resolve, () => pending.resolve(null));
884
+ }
885
+ } catch {
886
+ }
887
+ };
888
+ recordSession();
889
+ popup.on("framenavigated", recordSession);
890
+ const forward = (detail) => opener.then(
891
+ (page) => page?.evaluate(
892
+ ([name2, detail2]) => !window.dispatchEvent(new CustomEvent(name2, { detail: detail2, cancelable: true })),
893
+ [eventName, detail]
894
+ )
895
+ );
896
+ popup.on("close", () => {
897
+ if (!owner) return;
898
+ readiness.get(owner)?.resolve(null);
899
+ readiness.delete(owner);
900
+ void forward({ session: owner, closed: true }).catch(() => {
901
+ });
902
+ });
903
+ popup.on("request", (request) => {
904
+ if (!owner) return;
905
+ if (!request.isNavigationRequest() || request.frame() !== popup.mainFrame()) return;
906
+ let protocol;
907
+ try {
908
+ protocol = new URL(request.url()).protocol;
909
+ } catch {
910
+ return;
911
+ }
912
+ if (browserSchemes.has(protocol)) return;
913
+ void forward({ session: owner, url: request.url() }).then((accepted) => accepted ? popup.close() : void 0).catch(() => {
914
+ });
915
+ });
916
+ });
917
+ }
918
+
838
919
  // ../peach-engine/src/remote-stream/remoteEngineParam.ts
839
920
  function readRemoteEngineParam(search, hash) {
840
921
  const fromQuery = new URLSearchParams(search).get("remoteEngine");
@@ -1979,7 +2060,6 @@ var _reapBrowserNow = null;
1979
2060
  var _context = null;
1980
2061
  var _page = null;
1981
2062
  var _synchronizationEnabled = false;
1982
- var _suspendedAppId = null;
1983
2063
  var _browserCompromised = null;
1984
2064
  var browserIdentity = 0;
1985
2065
  var contextIdentity = 0;
@@ -2629,7 +2709,15 @@ async function dispatchDeviceOrientation(orientation) {
2629
2709
  landscapeSide: DETOX_PLATFORM === "ios" ? "right" : "left"
2630
2710
  }
2631
2711
  );
2632
- await page.waitForTimeout(50);
2712
+ await page.waitForFunction(
2713
+ (next) => {
2714
+ const settings = window.SootSim?.bridges?.settings?.get?.();
2715
+ const rotation = Reflect.get(window, "__sootsimDeviceRotation");
2716
+ return typeof settings === "object" && settings !== null && "orientation" in settings && settings.orientation === next && rotation?.active !== true;
2717
+ },
2718
+ orientation,
2719
+ { timeout: 15e3 }
2720
+ );
2633
2721
  }
2634
2722
  var MAX_SETTLED_SPEED_PT_PER_SEC = 2;
2635
2723
  async function waitForFrameClock(page, minMs = 25) {
@@ -3121,11 +3209,13 @@ function createSootSimElement(matcher) {
3121
3209
  visible: node.layout.width > 0 && node.layout.height > 0,
3122
3210
  enabled: !node.accessibilityState?.disabled,
3123
3211
  ...node,
3124
- frame: node.absolutePosition ? {
3212
+ // the transformed rect when the node reports one; a node resolved
3213
+ // without a size (x and y only) keeps its own frame
3214
+ frame: node.absolutePosition?.width !== void 0 && node.absolutePosition.height !== void 0 ? {
3125
3215
  x: node.absolutePosition.x,
3126
3216
  y: node.absolutePosition.y,
3127
- width: node.absolutePosition.width ?? node.frame?.width ?? 0,
3128
- height: node.absolutePosition.height ?? node.frame?.height ?? 0
3217
+ width: node.absolutePosition.width,
3218
+ height: node.absolutePosition.height
3129
3219
  } : node.frame
3130
3220
  };
3131
3221
  },
@@ -3211,25 +3301,34 @@ var device = {
3211
3301
  if (_browserCompromised) {
3212
3302
  throw new Error(`sootsim browser is compromised: ${_browserCompromised}`);
3213
3303
  }
3214
- if (_page && opts?.newInstance === false && !opts.delete && !opts.recordVideoDir && _suspendedAppId) {
3304
+ if (_page && opts?.newInstance === false && !opts.delete && !opts.recordVideoDir) {
3305
+ if (opts.url) {
3306
+ throw new Error(`SootSim cannot deliver a url to a running app: ${opts.url}`);
3307
+ }
3215
3308
  const page = _page;
3216
- const appId = _suspendedAppId;
3217
- await page.evaluate(
3218
- (id) => window.SootSim?.bridges?.mainShell?.launchApp?.(id),
3219
- appId
3220
- );
3221
- await pollUntil(
3222
- () => page.evaluate(async (id) => {
3223
- const state = await window.SootSim?.bridges?.mainShell?.getState?.();
3224
- return state?.state === "app" && state.activeApp === id && state.switcherPhase === "idle";
3225
- }, appId),
3226
- Boolean,
3227
- {
3228
- timeoutMs: 1e4,
3229
- label: `SootSim app ${appId} to resume`
3309
+ const appId = await page.evaluate(async () => {
3310
+ const state = await window.SootSim?.bridges?.mainShell?.getState?.();
3311
+ const guestApp = state?.guestApp;
3312
+ if (typeof guestApp !== "string") {
3313
+ throw new Error("SootSim main shell reports no guest app");
3230
3314
  }
3231
- );
3232
- _suspendedAppId = null;
3315
+ if (state?.state === "app" && state.activeApp === guestApp) return null;
3316
+ window.SootSim?.bridges?.mainShell?.launchApp?.(guestApp);
3317
+ return guestApp;
3318
+ });
3319
+ if (appId !== null) {
3320
+ await pollUntil(
3321
+ () => page.evaluate(async (id) => {
3322
+ const state = await window.SootSim?.bridges?.mainShell?.getState?.();
3323
+ return state?.state === "app" && state.activeApp === id && state.switcherPhase === "idle";
3324
+ }, appId),
3325
+ Boolean,
3326
+ {
3327
+ timeoutMs: 1e4,
3328
+ label: `SootSim app ${appId} to resume`
3329
+ }
3330
+ );
3331
+ }
3233
3332
  await waitForSootsimTree(page, 1e4);
3234
3333
  if (opts?.userNotification) {
3235
3334
  await postRemotePushToSimulator(opts.userNotification, true);
@@ -3270,6 +3369,11 @@ var device = {
3270
3369
  reapOwnedBrowser();
3271
3370
  throw error;
3272
3371
  }
3372
+ await forwardPopupSchemeNavigations(
3373
+ _context,
3374
+ AUTH_BROWSER_EXTERNAL_NAVIGATION_EVENT,
3375
+ AUTH_BROWSER_SESSION_FRAGMENT_KEY
3376
+ );
3273
3377
  await _context.exposeBinding("__sootsimHostCapture", async (source, value) => {
3274
3378
  const request = readBrowserCompositeCaptureRequest(value);
3275
3379
  const session = await source.page.context().newCDPSession(source.page);
@@ -4182,14 +4286,12 @@ var device = {
4182
4286
  },
4183
4287
  async sendToHome() {
4184
4288
  const page = getPage();
4185
- _suspendedAppId = await page.evaluate(async () => {
4289
+ await page.evaluate(async () => {
4186
4290
  const state = await window.SootSim?.bridges?.mainShell?.getState?.();
4187
- const appId = state?.activeApp;
4188
- if (typeof appId !== "string") {
4291
+ if (typeof state?.activeApp !== "string") {
4189
4292
  throw new Error(`cannot send an inactive SootSim app home`);
4190
4293
  }
4191
4294
  window.SootSim?.bridges?.mainShell?.goHome?.();
4192
- return appId;
4193
4295
  });
4194
4296
  await pollUntil(
4195
4297
  () => page.evaluate(async () => {
@@ -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;