peachsim 0.1.1465 → 0.1.1477

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 (86) hide show
  1. package/cli/bridge-flow-runner.ts +25 -17
  2. package/cli/cloud-client.ts +12 -19
  3. package/cli/commands/inspect/settling.ts +4 -1
  4. package/cli/drivers/playwright-sim-host.ts +7 -2
  5. package/cli/drivers/playwright.ts +6 -6
  6. package/dist-lib/agent-daemon-client.cjs +1 -1
  7. package/dist-lib/agent-events.cjs +1 -1
  8. package/dist-lib/attached-projects.cjs +1 -1
  9. package/dist-lib/auth/shared-session.cjs +1 -1
  10. package/dist-lib/backend-origin.cjs +1 -1
  11. package/dist-lib/beta.cjs +1 -1
  12. package/dist-lib/beta.mjs +1 -1
  13. package/dist-lib/bridge-constants.cjs +1 -1
  14. package/dist-lib/bridge-contract-input.cjs +1 -1
  15. package/dist-lib/bridge-contract-input.mjs +1 -1
  16. package/dist-lib/bridge-contract.cjs +1 -1
  17. package/dist-lib/bridge-contract.mjs +1 -1
  18. package/dist-lib/bundle-channel.cjs +13 -2
  19. package/dist-lib/capture-contract.cjs +1 -1
  20. package/dist-lib/capture-contract.mjs +1 -1
  21. package/dist-lib/cloud-contract.cjs +1 -1
  22. package/dist-lib/cloud-contract.mjs +1 -1
  23. package/dist-lib/cloud-test-args.cjs +1 -1
  24. package/dist-lib/cloud-test-args.mjs +1 -1
  25. package/dist-lib/cloud.cjs +1 -1
  26. package/dist-lib/cloud.mjs +1 -1
  27. package/dist-lib/config.cjs +1 -1
  28. package/dist-lib/config.mjs +1 -1
  29. package/dist-lib/detox/index.cjs +46 -40
  30. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  31. package/dist-lib/expo-swift-bundle.cjs +7 -2
  32. package/dist-lib/expo-swift-metadata.cjs +1 -1
  33. package/dist-lib/expo-swift-metadata.mjs +1 -1
  34. package/dist-lib/home-paths.cjs +1 -1
  35. package/dist-lib/host/bridge-host.cjs +170 -16
  36. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  37. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  38. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  39. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  40. package/dist-lib/host/websocket-proxy.cjs +1 -1
  41. package/dist-lib/index.cjs +5 -2
  42. package/dist-lib/jump-to-source-babel.cjs +1 -1
  43. package/dist-lib/jump-to-source-native.cjs +1 -1
  44. package/dist-lib/kotlin-host.cjs +1 -1
  45. package/dist-lib/menu.cjs +1 -1
  46. package/dist-lib/menu.mjs +1 -1
  47. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  48. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  49. package/dist-lib/metro-production-bundle.cjs +1 -1
  50. package/dist-lib/metro-production-bundle.mjs +1 -1
  51. package/dist-lib/metro.cjs +1 -1
  52. package/dist-lib/native-app-identity-project.cjs +1 -1
  53. package/dist-lib/native-app-identity-project.mjs +1 -1
  54. package/dist-lib/native-app-identity.cjs +1 -1
  55. package/dist-lib/native-app-identity.mjs +1 -1
  56. package/dist-lib/native-firebase-metadata.cjs +1 -1
  57. package/dist-lib/native-firebase-metadata.mjs +1 -1
  58. package/dist-lib/plist.cjs +1 -1
  59. package/dist-lib/plist.mjs +1 -1
  60. package/dist-lib/profiles.cjs +1 -1
  61. package/dist-lib/public-brand.cjs +1 -1
  62. package/dist-lib/react-native-host-modules.cjs +1 -1
  63. package/dist-lib/react-native-host-modules.mjs +1 -1
  64. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  65. package/dist-lib/sdk.cjs +5 -2
  66. package/dist-lib/sdk.mjs +5 -2
  67. package/dist-lib/skills.cjs +198 -83
  68. package/dist-lib/swift-compile.cjs +7 -2
  69. package/dist-lib/swift-compile.mjs +7 -2
  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-toolchain.cjs +1 -1
  75. package/dist-lib/swift.cjs +1 -1
  76. package/dist-lib/vite-swift.cjs +7 -2
  77. package/dist-lib/vite.cjs +1 -1
  78. package/dist-lib/worklet-executable.cjs +1 -1
  79. package/dist-lib/worklet-executable.mjs +1 -1
  80. package/package.json +1 -1
  81. package/src/admitted-mac-build.ts +12 -0
  82. package/src/bridge-constants.ts +5 -3
  83. package/src/bundle-asset-resource.ts +8 -0
  84. package/src/host/bridge-host.ts +34 -6
  85. package/src/swift-compile.ts +5 -0
  86. package/src/worker-system-chunks.ts +10 -9
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1465 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1477 | (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;
@@ -36,30 +36,14 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
36
36
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
37
37
 
38
38
  // ../../scripts/lib/chromium-admission.ts
39
- async function acquireChromiumAdmission(deps) {
40
- const { fs: fs38, os: os14, path: path42, childProcess: childProcess2, label } = deps;
39
+ function readChromiumQueue(deps, verified3, own) {
40
+ const { fs: fs38, os: os15, path: path42, childProcess: childProcess3 } = deps;
41
41
  const dir = path42.join(
42
- process.platform === "win32" ? os14.tmpdir() : "/tmp",
42
+ process.platform === "win32" ? os15.tmpdir() : "/tmp",
43
43
  "chromium-admission"
44
44
  );
45
45
  fs38.mkdirSync(dir, { recursive: true });
46
- const limit = Math.max(2, Math.floor(os14.availableParallelism() / 3));
47
- const startedAt = Math.round(Date.now() / 1e3 - process.uptime());
48
- const name2 = `${process.pid}-${startedAt}-${Math.random().toString(36).slice(2, 10)}`;
49
- const ticket = path42.join(dir, name2);
50
- fs38.closeSync(fs38.openSync(ticket, "wx"));
51
- let released = false;
52
- const release = () => {
53
- if (released) return;
54
- released = true;
55
- process.removeListener("exit", release);
56
- try {
57
- fs38.unlinkSync(ticket);
58
- } catch {
59
- }
60
- };
61
- process.on("exit", release);
62
- const verified3 = /* @__PURE__ */ new Map();
46
+ const limit = Math.max(2, Math.floor(os15.availableParallelism() / 3));
63
47
  const live = (entry) => {
64
48
  const match = /^(\d+)-(\d+)-/.exec(entry);
65
49
  if (!match) return false;
@@ -74,7 +58,7 @@ async function acquireChromiumAdmission(deps) {
74
58
  let same = pid === process.pid;
75
59
  if (!same) {
76
60
  try {
77
- const started = childProcess2.execFileSync("ps", ["-p", String(pid), "-o", "lstart="], { encoding: "utf8" }).trim();
61
+ const started = childProcess3.execFileSync("ps", ["-p", String(pid), "-o", "lstart="], { encoding: "utf8" }).trim();
78
62
  same = Math.abs(Date.parse(started) / 1e3 - Number(match[2])) <= 2;
79
63
  } catch {
80
64
  same = false;
@@ -83,29 +67,50 @@ async function acquireChromiumAdmission(deps) {
83
67
  verified3.set(entry, same);
84
68
  return same;
85
69
  };
86
- let waited = false;
87
- while (true) {
88
- const tickets = [];
89
- for (const entry of fs38.readdirSync(dir)) {
90
- if (entry !== name2 && !live(entry)) {
91
- try {
92
- fs38.unlinkSync(path42.join(dir, entry));
93
- } catch {
94
- }
95
- continue;
96
- }
70
+ const tickets = [];
71
+ for (const entry of fs38.readdirSync(dir)) {
72
+ if (entry !== own && !live(entry)) {
97
73
  try {
98
- tickets.push({
99
- entry,
100
- created: fs38.statSync(path42.join(dir, entry), { bigint: true }).ctimeNs
101
- });
74
+ fs38.unlinkSync(path42.join(dir, entry));
102
75
  } catch {
103
76
  }
77
+ continue;
104
78
  }
105
- tickets.sort(
106
- (a, b) => a.created === b.created ? a.entry < b.entry ? -1 : 1 : a.created < b.created ? -1 : 1
107
- );
108
- const rank = tickets.findIndex((t) => t.entry === name2);
79
+ try {
80
+ tickets.push({
81
+ entry,
82
+ created: fs38.statSync(path42.join(dir, entry), { bigint: true }).ctimeNs
83
+ });
84
+ } catch {
85
+ }
86
+ }
87
+ tickets.sort(
88
+ (a, b) => a.created === b.created ? a.entry < b.entry ? -1 : 1 : a.created < b.created ? -1 : 1
89
+ );
90
+ return { dir, limit, tickets: tickets.map((t) => t.entry) };
91
+ }
92
+ async function acquireChromiumAdmission(deps) {
93
+ const { fs: fs38, path: path42, label, readQueue } = deps;
94
+ const verified3 = /* @__PURE__ */ new Map();
95
+ const startedAt = Math.round(Date.now() / 1e3 - process.uptime());
96
+ const name2 = `${process.pid}-${startedAt}-${Math.random().toString(36).slice(2, 10)}`;
97
+ const ticket = path42.join(readQueue(deps, verified3, name2).dir, name2);
98
+ fs38.closeSync(fs38.openSync(ticket, "wx"));
99
+ let released = false;
100
+ const release = () => {
101
+ if (released) return;
102
+ released = true;
103
+ process.removeListener("exit", release);
104
+ try {
105
+ fs38.unlinkSync(ticket);
106
+ } catch {
107
+ }
108
+ };
109
+ process.on("exit", release);
110
+ let waited = false;
111
+ while (true) {
112
+ const { limit, tickets } = readQueue(deps, verified3, name2);
113
+ const rank = tickets.indexOf(name2);
109
114
  if (rank < 0) {
110
115
  fs38.closeSync(fs38.openSync(ticket, "wx"));
111
116
  continue;
@@ -116,7 +121,7 @@ async function acquireChromiumAdmission(deps) {
116
121
  return release;
117
122
  }
118
123
  if (!waited) {
119
- const holders = tickets.slice(0, limit).map((t) => t.entry.split("-")[0]);
124
+ const holders = tickets.slice(0, limit).map((t) => t.split("-")[0]);
120
125
  process.stderr.write(
121
126
  `[chromium-admission] ${label}: ${limit} chromium launches already run on this machine (pids ${holders.join(" ")}), queued ${rank - limit + 1}
122
127
  `
@@ -420,7 +425,8 @@ async function launchReapedScoped(launch2, readIdentity2 = processIdentity) {
420
425
  os,
421
426
  path,
422
427
  childProcess,
423
- label: process.argv.slice(1, 3).join(" ")
428
+ label: process.argv.slice(1, 3).join(" "),
429
+ readQueue: readChromiumQueue
424
430
  });
425
431
  let browser;
426
432
  try {
@@ -1067,7 +1073,6 @@ var init_light_native_package_names = __esm({
1067
1073
  "@react-native-karte/in-app-messaging",
1068
1074
  "@react-native-karte/notification",
1069
1075
  "@react-native-seoul/kakao-login",
1070
- "@react-native-vector-icons/get-image",
1071
1076
  "@react-native-zohosalesiq/mobilisten",
1072
1077
  "@react-native-zohosalesiq/mobilisten-core",
1073
1078
  "@reclaimprotocol/inapp-rn-sdk",
@@ -29861,6 +29866,16 @@ var init_internal_child = __esm({
29861
29866
  }
29862
29867
  });
29863
29868
 
29869
+ // src/admitted-mac-build.ts
29870
+ function admittedMacBuilderSlot(env = process.env) {
29871
+ return env.CONTRAST_REMOTE_BUILD === "mac" && env.REMOTE_MAC_SLOT_HELD === "1" && env.CONTRAST_HEAVY_ADMITTED === "1";
29872
+ }
29873
+ var init_admitted_mac_build = __esm({
29874
+ "src/admitted-mac-build.ts"() {
29875
+ "use strict";
29876
+ }
29877
+ });
29878
+
29864
29879
  // src/swift-distribution-contract.ts
29865
29880
  function swiftDistributionHost(platform, arch) {
29866
29881
  const host2 = `${platform}-${arch}`;
@@ -32104,7 +32119,7 @@ function compileSwiftProjectUnit(input, options) {
32104
32119
  };
32105
32120
  const hash = swiftArtifactHash(input, options.release, moduleRoot);
32106
32121
  return serialize(root, async () => {
32107
- if (process.platform === "darwin" && process.env.TM_SESSION && process.env.CI !== "true" && moduleRoot === import_node_path10.default.resolve(__sootsim_import_meta_dirname, "../../sootsim-swift") && !swiftDistributionAt(moduleRoot)) {
32122
+ if (process.platform === "darwin" && process.env.TM_SESSION && !admittedMacBuilderSlot() && process.env.CI !== "true" && moduleRoot === import_node_path10.default.resolve(__sootsim_import_meta_dirname, "../../sootsim-swift") && !swiftDistributionAt(moduleRoot)) {
32108
32123
  const requestRoot = (0, import_node_fs10.mkdtempSync)(import_node_path10.default.join(root, ".builder-request-"));
32109
32124
  const output = import_node_path10.default.join(requestRoot, "output");
32110
32125
  const request = import_node_path10.default.join(requestRoot, "request.json");
@@ -32234,6 +32249,7 @@ var init_swift_compile = __esm({
32234
32249
  import_node_os4 = __toESM(require("node:os"), 1);
32235
32250
  import_node_path10 = __toESM(require("node:path"), 1);
32236
32251
  import_node_util2 = require("node:util");
32252
+ init_admitted_mac_build();
32237
32253
  init_swift_distribution_contract();
32238
32254
  init_swift_icu();
32239
32255
  init_swift_package();
@@ -45217,6 +45233,15 @@ var init_metro_production_bundle = __esm({
45217
45233
  }
45218
45234
  });
45219
45235
 
45236
+ // src/bundle-asset-resource.ts
45237
+ var PEACH_BUNDLE_ASSET_PREFIX;
45238
+ var init_bundle_asset_resource = __esm({
45239
+ "src/bundle-asset-resource.ts"() {
45240
+ "use strict";
45241
+ PEACH_BUNDLE_ASSET_PREFIX = "peach-asset://";
45242
+ }
45243
+ });
45244
+
45220
45245
  // ../contrast-bundler/src/metroAssetArtifact.ts
45221
45246
  function isEmbeddedAssetDescriptor(descriptor) {
45222
45247
  return descriptor.fileUris?.length === descriptor.scales.length && descriptor.fileHashes?.length === descriptor.scales.length;
@@ -45269,6 +45294,7 @@ function quotedEnd(text3, start, end) {
45269
45294
  return end;
45270
45295
  }
45271
45296
  function decodeSingleQuoted(contents) {
45297
+ if (!contents.includes("\\")) return contents;
45272
45298
  let value = "";
45273
45299
  for (let cursor = 0; cursor < contents.length; cursor++) {
45274
45300
  const character = contents[cursor];
@@ -45688,6 +45714,15 @@ async function sha256HexBytes(bytes) {
45688
45714
  return hex;
45689
45715
  }
45690
45716
  async function assertSelfContainedMetroArtifactAssets(bundle) {
45717
+ return visitVerifiedMetroArtifactAssets(
45718
+ bundle,
45719
+ () => {
45720
+ },
45721
+ () => {
45722
+ }
45723
+ );
45724
+ }
45725
+ async function visitVerifiedMetroArtifactAssets(bundle, acceptVariant, acceptSite) {
45691
45726
  const seen = /* @__PURE__ */ new Set();
45692
45727
  const manifestLines = [];
45693
45728
  let descriptorsCount = 0;
@@ -45698,7 +45733,10 @@ async function assertSelfContainedMetroArtifactAssets(bundle) {
45698
45733
  for (const site of iterateAssetDescriptorSites(bundle)) {
45699
45734
  const descriptor = site.descriptor;
45700
45735
  const key2 = assetDescriptorKey(descriptor);
45701
- if (seen.has(key2)) continue;
45736
+ if (seen.has(key2)) {
45737
+ acceptSite(site);
45738
+ continue;
45739
+ }
45702
45740
  seen.add(key2);
45703
45741
  descriptorsCount++;
45704
45742
  const label = `${descriptor.httpServerLocation}/${descriptor.name}.${descriptor.type}`;
@@ -45733,11 +45771,13 @@ async function assertSelfContainedMetroArtifactAssets(bundle) {
45733
45771
  `peach ios --remote bundle is not self-contained: ${label} scale ${descriptor.scales[index]} bytes do not match their content hash`
45734
45772
  );
45735
45773
  }
45774
+ acceptVariant(descriptor, index, decoded);
45736
45775
  variants++;
45737
45776
  bytes += decoded.byteLength;
45738
45777
  descriptorBytes += decoded.byteLength;
45739
45778
  }
45740
45779
  sizes.push({ asset: label, bytes: descriptorBytes });
45780
+ acceptSite(site);
45741
45781
  }
45742
45782
  } catch (error) {
45743
45783
  if (error instanceof Error && error.message.startsWith("peach ios --remote bundle is not self-contained:")) {
@@ -45758,6 +45798,52 @@ async function assertSelfContainedMetroArtifactAssets(bundle) {
45758
45798
  sizes: sortedAssetSizes(sizes)
45759
45799
  };
45760
45800
  }
45801
+ async function separateMetroArtifactAssets(bundle) {
45802
+ const resources = /* @__PURE__ */ new Map();
45803
+ const entries = /* @__PURE__ */ new Map();
45804
+ const pieces = [];
45805
+ let cursor = 0;
45806
+ const assets2 = await visitVerifiedMetroArtifactAssets(
45807
+ bundle,
45808
+ (descriptor, index, bytes) => {
45809
+ const key2 = assetDescriptorKey(descriptor);
45810
+ let entry = entries.get(key2);
45811
+ if (!entry) {
45812
+ entry = { fileUris: [], fileHashes: [], scales: descriptor.scales };
45813
+ entries.set(key2, entry);
45814
+ }
45815
+ const sha256 = descriptor.fileHashes?.[index];
45816
+ const scale = descriptor.scales[index];
45817
+ if (!sha256 || scale === void 0) {
45818
+ throw new Error("verified Metro asset variant is incomplete");
45819
+ }
45820
+ const filename = metroAssetScaleFilename(descriptor.name, descriptor.type, scale);
45821
+ const uri = `${PEACH_BUNDLE_ASSET_PREFIX}${sha256}/${encodeURIComponent(filename)}`;
45822
+ if (!resources.has(uri)) {
45823
+ resources.set(uri, {
45824
+ uri,
45825
+ sha256,
45826
+ contentType: metroAssetContentType(descriptor.type),
45827
+ bytes,
45828
+ byteLength: bytes.byteLength
45829
+ });
45830
+ }
45831
+ entry.fileUris.push(uri);
45832
+ entry.fileHashes.push(sha256);
45833
+ },
45834
+ (site) => {
45835
+ const entry = entries.get(assetDescriptorKey(site.descriptor));
45836
+ if (!entry) throw new Error("verified Metro asset descriptor is missing");
45837
+ pieces.push(
45838
+ bundle.slice(cursor, site.start),
45839
+ rewriteDescriptorObject(bundle, site, entry)
45840
+ );
45841
+ cursor = site.end;
45842
+ }
45843
+ );
45844
+ pieces.push(bundle.slice(cursor));
45845
+ return { code: pieces.join(""), assets: assets2, resources: [...resources.values()] };
45846
+ }
45761
45847
  function metroAssetScaleFilename(name2, type, scale) {
45762
45848
  const suffix = scale === 1 ? "" : `@${scale}x`;
45763
45849
  return `${name2}${suffix}.${type}`;
@@ -45952,6 +46038,7 @@ var EXPRESSION_KEYWORDS, PLACEHOLDER_JPEG, METRO_ASSET_PLACEHOLDERS;
45952
46038
  var init_metroAssetArtifact = __esm({
45953
46039
  "../contrast-bundler/src/metroAssetArtifact.ts"() {
45954
46040
  "use strict";
46041
+ init_bundle_asset_resource();
45955
46042
  EXPRESSION_KEYWORDS = /* @__PURE__ */ new Set([
45956
46043
  "await",
45957
46044
  "case",
@@ -48020,11 +48107,6 @@ function searchMetroAssetDest(bundlePath, descriptors, assetsDirectory) {
48020
48107
  }
48021
48108
  return { dest: winner.dest, searched, truncated, unconfirmed: best === 0 };
48022
48109
  }
48023
- function largestEmbeddedAssets(sizes, count) {
48024
- if (sizes.length === 0) return "";
48025
- const largest = sizes.slice(0, count).map((entry) => `${entry.asset} ${entry.bytes} bytes`).join(", ");
48026
- return ` Largest embedded assets: ${largest}.`;
48027
- }
48028
48110
  async function inferCloudModuleIdentity(source) {
48029
48111
  let receipt;
48030
48112
  try {
@@ -48144,9 +48226,10 @@ async function produceArtifact(bundlePath, maxBytes, command, assetPolicy, asset
48144
48226
  });
48145
48227
  const bytes = Buffer.from(artifact.code, "utf8");
48146
48228
  const assets2 = artifact.receipt.assets;
48147
- if (bytes.length > maxBytes) {
48229
+ const executableBytes = command === PREVIEW_COMMAND ? bytes.length : Buffer.byteLength((await separateMetroArtifactAssets(artifact.code)).code, "utf8");
48230
+ if (executableBytes > maxBytes) {
48148
48231
  throw new Error(
48149
- `${REMOTE_COMMAND} artifact is ${bytes.length} bytes and exceeds the ${maxBytes}-byte limit. Embedded assets weigh ${assets2.bytes} bytes on disk, and base64 embedding costs about a third on top of that, so the practical asset budget is roughly ${Math.round(maxBytes * 0.75 / 1e6)} MB.${largestEmbeddedAssets(assets2.sizes, 10)}`
48232
+ `${command} executable is ${executableBytes} bytes and exceeds the ${maxBytes}-byte limit. The ${assets2.bytes} asset bytes are stored outside guest code.`
48150
48233
  );
48151
48234
  }
48152
48235
  const warnings = [];
@@ -48160,9 +48243,9 @@ async function produceArtifact(bundlePath, maxBytes, command, assetPolicy, asset
48160
48243
  `${command} embedded a placeholder image for ${prepared.substituted.length} asset(s) no scale of which is in ${prepared.search.searched.join(", ") || "any asset dest directory"}: ${prepared.substituted.join(", ")}. Rebuild with \`react-native bundle --assets-dest\` to ship the real images.`
48161
48244
  );
48162
48245
  }
48163
- if (bytes.length >= Math.floor(maxBytes * 0.8)) {
48246
+ if (executableBytes >= Math.floor(maxBytes * 0.8)) {
48164
48247
  warnings.push(
48165
- `${command} artifact is ${bytes.length} bytes, ${Math.round(bytes.length / maxBytes * 100)}% of the ${maxBytes}-byte limit.${largestEmbeddedAssets(assets2.sizes, 5)}`
48248
+ `${command} executable is ${executableBytes} bytes, ${Math.round(executableBytes / maxBytes * 100)}% of the ${maxBytes}-byte limit.`
48166
48249
  );
48167
48250
  }
48168
48251
  return {
@@ -48312,7 +48395,7 @@ function createCloudBridgeForParsed(parsed) {
48312
48395
  if (!session) return null;
48313
48396
  return session.service === "box" ? new CloudBoxBridge(session) : new CloudBridge(session);
48314
48397
  }
48315
- var import_node_crypto16, import_node_fs33, import_node_path34, import_node_vm, DEFAULT_RNX_CLOUD_ORIGIN, MAX_RNX_CLOUD_BUNDLE_BYTES, REMOTE_COMMAND, MAX_ASSET_DEST_FILES, ACCOUNT_CHOICE_REFUSALS, PROJECT_ONLY_DIRECTORIES, MAX_PLACEMENT_COMBINATIONS, CloudBridge, CloudBoxBridge;
48398
+ var import_node_crypto16, import_node_fs33, import_node_path34, import_node_vm, DEFAULT_RNX_CLOUD_ORIGIN, MAX_RNX_CLOUD_BUNDLE_BYTES, REMOTE_COMMAND, PREVIEW_COMMAND, MAX_ASSET_DEST_FILES, ACCOUNT_CHOICE_REFUSALS, PROJECT_ONLY_DIRECTORIES, MAX_PLACEMENT_COMBINATIONS, CloudBridge, CloudBoxBridge;
48316
48399
  var init_cloud_client = __esm({
48317
48400
  "cli/cloud-client.ts"() {
48318
48401
  "use strict";
@@ -48337,6 +48420,7 @@ var init_cloud_client = __esm({
48337
48420
  DEFAULT_RNX_CLOUD_ORIGIN = rnxPublicBrand.origin;
48338
48421
  MAX_RNX_CLOUD_BUNDLE_BYTES = RNX_CLOUD_MAX_ARTIFACT_BYTES;
48339
48422
  REMOTE_COMMAND = "peach remote";
48423
+ PREVIEW_COMMAND = "peach preview";
48340
48424
  MAX_ASSET_DEST_FILES = 25e3;
48341
48425
  ACCOUNT_CHOICE_REFUSALS = /* @__PURE__ */ new Set([
48342
48426
  "accountId is required",
@@ -48592,15 +48676,17 @@ function unrefTimer(timer) {
48592
48676
  timer.unref();
48593
48677
  }
48594
48678
  }
48595
- var import_child_process3, import_fs2, import_http4, import_path2, import_ws, SOOTSIM_CROSS_ORIGIN_EMBEDDER_POLICY, WRITE_COMMAND_TYPES, FORCE_CLOSE_GRACE_MS, FORCE_CLOSE_TERMINATE_MS, DAEMON_HEARTBEAT_INTERVAL_MS, DEFAULT_RUNTIME_UPDATE_INTERVAL_MS, RUNTIME_UPDATE_INTERVAL_ENV, HTTP_MIME_TYPES, CAMERA_FIXTURE_ROUTE, CAMERA_FIXTURE_NAME_RE, SootSimBridgeHost;
48679
+ var import_child_process3, import_fs2, import_http4, import_os, import_path2, import_ws, SOOTSIM_CROSS_ORIGIN_EMBEDDER_POLICY, WRITE_COMMAND_TYPES, FORCE_CLOSE_GRACE_MS, FORCE_CLOSE_TERMINATE_MS, DAEMON_HEARTBEAT_INTERVAL_MS, DEFAULT_RUNTIME_UPDATE_INTERVAL_MS, RUNTIME_UPDATE_INTERVAL_ENV, HTTP_MIME_TYPES, CAMERA_FIXTURE_ROUTE, CAMERA_FIXTURE_NAME_RE, SootSimBridgeHost;
48596
48680
  var init_bridge_host = __esm({
48597
48681
  "src/host/bridge-host.ts"() {
48598
48682
  "use strict";
48599
- import_child_process3 = require("child_process");
48683
+ import_child_process3 = __toESM(require("child_process"), 1);
48600
48684
  import_fs2 = __toESM(require("fs"), 1);
48601
48685
  import_http4 = require("http");
48686
+ import_os = __toESM(require("os"), 1);
48602
48687
  import_path2 = __toESM(require("path"), 1);
48603
48688
  import_ws = require("ws");
48689
+ init_chromium_admission();
48604
48690
  init_dev_server_scanner();
48605
48691
  init_automatic_update_policy();
48606
48692
  init_backend_origin();
@@ -50017,6 +50103,7 @@ var init_bridge_host = __esm({
50017
50103
  }
50018
50104
  reapIdleSims(now = Date.now()) {
50019
50105
  const attachedSimIds = new Set(this.cliSimBySocket.values());
50106
+ let reclaimable = null;
50020
50107
  for (const sim of this.sims.values()) {
50021
50108
  if (attachedSimIds.has(sim.id)) continue;
50022
50109
  const automation = this.isAutomationSim(sim);
@@ -50025,9 +50112,27 @@ var init_bridge_host = __esm({
50025
50112
  continue;
50026
50113
  }
50027
50114
  const idleMs = now - Math.max(sim.lastActiveAt, sim.connectedAt);
50028
- const ttl = automation ? AUTOMATION_SIM_IDLE_REAP_TTL_MS : _SootSimBridgeHost.SIM_IDLE_REAP_TTL_MS;
50029
- if (idleMs >= ttl) this.closeSimSocketFromHost(sim.ws);
50115
+ if (automation) {
50116
+ if (idleMs >= AUTOMATION_SIM_IDLE_REAP_TTL_MS && idleMs > (reclaimable?.idleMs ?? 0))
50117
+ reclaimable = { ws: sim.ws, idleMs };
50118
+ continue;
50119
+ }
50120
+ if (idleMs >= _SootSimBridgeHost.SIM_IDLE_REAP_TTL_MS)
50121
+ this.closeSimSocketFromHost(sim.ws);
50030
50122
  }
50123
+ if (reclaimable && this.chromiumLaunchWaiting())
50124
+ this.closeSimSocketFromHost(reclaimable.ws);
50125
+ }
50126
+ chromiumQueueVerified = /* @__PURE__ */ new Map();
50127
+ chromiumLaunchWaiting() {
50128
+ const queue2 = readChromiumQueue(
50129
+ { fs: import_fs2.default, os: import_os.default, path: import_path2.default, childProcess: import_child_process3.default },
50130
+ this.chromiumQueueVerified
50131
+ );
50132
+ const live = new Set(queue2.tickets);
50133
+ for (const entry of this.chromiumQueueVerified.keys())
50134
+ if (!live.has(entry)) this.chromiumQueueVerified.delete(entry);
50135
+ return queue2.tickets.length > queue2.limit;
50031
50136
  }
50032
50137
  // ping every connected ws; if the previous round's ping went unanswered,
50033
50138
  // terminate the socket so 'close' fires and the sim cleanup path
@@ -50923,7 +51028,7 @@ function getCurrentSimPath() {
50923
51028
  return (0, import_path3.resolve)(envPath);
50924
51029
  }
50925
51030
  const key2 = getCliIdentityKey();
50926
- return (0, import_path3.join)((0, import_os.tmpdir)(), `peach-current-sim-${key2}.json`);
51031
+ return (0, import_path3.join)((0, import_os2.tmpdir)(), `peach-current-sim-${key2}.json`);
50927
51032
  }
50928
51033
  function legacyCloudCredentialDirectory(filepath) {
50929
51034
  return (0, import_path3.join)((0, import_path3.dirname)(filepath), `${(0, import_path3.basename)(filepath)}.credentials`);
@@ -50975,12 +51080,12 @@ function saveCurrentSimId(simId) {
50975
51080
  function clearCurrentSimId() {
50976
51081
  (0, import_fs4.rmSync)(getCurrentSimPath(), { force: true });
50977
51082
  }
50978
- var import_fs4, import_os, import_path3, CURRENT_SIM_VERSION, CURRENT_SIM_PATH_ENV, LEGACY_CURRENT_SIM_PATH_ENV, IDENTITY_ENV_VARS, IMMORTAL_HOST_COMM_RE, INIT_COMM_RE, readCurrentSim;
51083
+ var import_fs4, import_os2, import_path3, CURRENT_SIM_VERSION, CURRENT_SIM_PATH_ENV, LEGACY_CURRENT_SIM_PATH_ENV, IDENTITY_ENV_VARS, IMMORTAL_HOST_COMM_RE, INIT_COMM_RE, readCurrentSim;
50979
51084
  var init_current_sim = __esm({
50980
51085
  "cli/current-sim.ts"() {
50981
51086
  "use strict";
50982
51087
  import_fs4 = require("fs");
50983
- import_os = require("os");
51088
+ import_os2 = require("os");
50984
51089
  import_path3 = require("path");
50985
51090
  init_parent_pid();
50986
51091
  init_secure_file();
@@ -55558,7 +55663,7 @@ function resolveUserDataDir(opts) {
55558
55663
  return playwrightProfileUserDataDir(ensureProfile(opts.profileId).id);
55559
55664
  }
55560
55665
  if (opts.ephemeralProfile) {
55561
- return (0, import_fs7.mkdtempSync)((0, import_path6.join)((0, import_os2.tmpdir)(), "peach-playwright-profile-"));
55666
+ return (0, import_fs7.mkdtempSync)((0, import_path6.join)((0, import_os3.tmpdir)(), "peach-playwright-profile-"));
55562
55667
  }
55563
55668
  return "";
55564
55669
  }
@@ -55649,7 +55754,7 @@ async function launch(opts) {
55649
55754
  }
55650
55755
  }
55651
55756
  const cdpPort = opts.cdpPort ?? (hostCommand ? await freePort() : void 0);
55652
- const errLog = (0, import_path6.join)((0, import_os2.tmpdir)(), playwrightHostLogName(Date.now(), process.pid));
55757
+ const errLog = (0, import_path6.join)((0, import_os3.tmpdir)(), playwrightHostLogName(Date.now(), process.pid));
55653
55758
  const connectAckFile = `${errLog}.connected`;
55654
55759
  const completionFile = `${errLog}.completed`;
55655
55760
  const errFd = (0, import_fs7.openSync)(errLog, "a");
@@ -55691,7 +55796,7 @@ async function launch(opts) {
55691
55796
  child.unref();
55692
55797
  const ownerComm = getProcessComm(ownerPid);
55693
55798
  const idleMinutes = AUTOMATION_SIM_IDLE_REAP_TTL_MS / 6e4;
55694
- const ownerNote = ` \u2014 browser closes after ${idleMinutes} min with no peach command or input, or when pid ${ownerPid}${ownerComm ? ` (${ownerComm})` : ""} exits`;
55799
+ const ownerNote = ` \u2014 browser closes when pid ${ownerPid}${ownerComm ? ` (${ownerComm})` : ""} exits, or after ${idleMinutes} min with no peach command or input if another browser launch is waiting for its slot`;
55695
55800
  return {
55696
55801
  launched: true,
55697
55802
  message: `playwright chrome launched \u2192 ${targetUrl.href}${ownerNote}`,
@@ -55712,14 +55817,14 @@ async function launch(opts) {
55712
55817
  (0, import_fs7.closeSync)(errFd);
55713
55818
  }
55714
55819
  }
55715
- var import_child_process6, import_fs7, import_net2, import_os2, import_path6, playwrightDriver;
55820
+ var import_child_process6, import_fs7, import_net2, import_os3, import_path6, playwrightDriver;
55716
55821
  var init_playwright = __esm({
55717
55822
  "cli/drivers/playwright.ts"() {
55718
55823
  "use strict";
55719
55824
  import_child_process6 = require("child_process");
55720
55825
  import_fs7 = require("fs");
55721
55826
  import_net2 = require("net");
55722
- import_os2 = require("os");
55827
+ import_os3 = require("os");
55723
55828
  import_path6 = require("path");
55724
55829
  init_bridge_constants();
55725
55830
  init_desktop_host_delivery();
@@ -56097,12 +56202,12 @@ function skillsDir() {
56097
56202
  return skillsDirPath;
56098
56203
  }
56099
56204
  function targetFromHome(envName, fallbackDir) {
56100
- const home = process.env[envName] || path38.join(os12.homedir(), fallbackDir);
56205
+ const home = process.env[envName] || path38.join(os13.homedir(), fallbackDir);
56101
56206
  return path38.join(home, "skills");
56102
56207
  }
56103
56208
  function codexTargets() {
56104
56209
  const homes = /* @__PURE__ */ new Map();
56105
- const userHome = process.env.HOME || os12.homedir();
56210
+ const userHome = process.env.HOME || os13.homedir();
56106
56211
  const primaryCodexHome = process.env.CODEX_HOME || path38.join(userHome, ".codex");
56107
56212
  homes.set(path38.resolve(primaryCodexHome), "codex");
56108
56213
  const tmCodexHomes = process.env.TM_CODEX_HOMES;
@@ -56255,13 +56360,13 @@ function listSkills() {
56255
56360
  }
56256
56361
  return skills.sort((a, b) => a.name.localeCompare(b.name));
56257
56362
  }
56258
- var import_child_process7, fs33, os12, path38, import_url3, import_meta3, skillsDirPath;
56363
+ var import_child_process7, fs33, os13, path38, import_url3, import_meta3, skillsDirPath;
56259
56364
  var init_skills = __esm({
56260
56365
  "cli/commands/skills.ts"() {
56261
56366
  "use strict";
56262
56367
  import_child_process7 = require("child_process");
56263
56368
  fs33 = __toESM(require("fs"), 1);
56264
- os12 = __toESM(require("os"), 1);
56369
+ os13 = __toESM(require("os"), 1);
56265
56370
  path38 = __toESM(require("path"), 1);
56266
56371
  import_url3 = require("url");
56267
56372
  init_cli_version();
@@ -59257,6 +59362,7 @@ async function waitForSootsimIdle({
59257
59362
  return true
59258
59363
  }
59259
59364
  while (Date.now() < deadline) {
59365
+ const pollStarted = Date.now()
59260
59366
  const snapshot = await readSnapshot()
59261
59367
  if (snapshot.runtimeUnsupported) return snapshot.runtimeUnsupported
59262
59368
  polls++
@@ -59329,7 +59435,9 @@ async function waitForSootsimIdle({
59329
59435
  lastRequestTotal = snapshot.requestTotal
59330
59436
  lastAppCommits = snapshot.appCommits
59331
59437
  lastNodeCount = snapshot.nodeCount
59332
- await sleep(pollMs)
59438
+ // reply latency belongs inside the poll interval; the stillness window
59439
+ // above remains measured from completed observations.
59440
+ await sleep(Math.max(0, pollMs - (Date.now() - pollStarted)))
59333
59441
  }
59334
59442
  const last = await readSnapshot()
59335
59443
  if (last.runtimeUnsupported) return last.runtimeUnsupported
@@ -60560,7 +60668,7 @@ var init_bridge_flow_runner = __esm({
60560
60668
  // engine's XCTest accessibility projection — one bridge evaluate, then the
60561
60669
  // same Orchestra.buildFilter semantics the render resolver implements, over
60562
60670
  // PeachAccessibilityNode instead of the visible semantic tree.
60563
- async findElementAccessibilityTree(opts) {
60671
+ async resolveAccessibilityElement(opts, command) {
60564
60672
  const tree = await this.evaluate(`(async () => {
60565
60673
  const test = window.__sootsimTest
60566
60674
  if (!test || typeof test.captureAccessibilityTree !== 'function') throw new Error('engine accessibility snapshot is unavailable')
@@ -60569,11 +60677,15 @@ var init_bridge_flow_runner = __esm({
60569
60677
  if (!isPeachAccessibilityTree(tree))
60570
60678
  throw new Error("engine returned an invalid accessibility snapshot");
60571
60679
  if (tree.length === 0) return null;
60572
- if (tree.some((node2) => node2.platform !== "ios"))
60573
- throw new Error(
60574
- "containsChild, containsDescendants and focused require the iOS accessibility hierarchy"
60575
- );
60576
- const node = resolveAccessibilitySelector(tree, opts);
60680
+ if (tree.some((node) => node.platform !== "ios"))
60681
+ throw new Error(`${command} requires the iOS accessibility hierarchy`);
60682
+ return resolveAccessibilitySelector(tree, opts);
60683
+ }
60684
+ async findElementAccessibilityTree(opts) {
60685
+ const node = await this.resolveAccessibilityElement(
60686
+ opts,
60687
+ "containsChild, containsDescendants and focused"
60688
+ );
60577
60689
  if (!node) return null;
60578
60690
  const frame = node.frame;
60579
60691
  return {
@@ -61793,14 +61905,17 @@ var init_bridge_flow_runner = __esm({
61793
61905
  }
61794
61906
  // maestro copyTextFrom: find an element and capture its text for use in
61795
61907
  // later steps via ${maestro.copiedText} (upstream form) or the legacy
61796
- // ${maestroCopiedText}. the matcher shape matches tapOn.
61908
+ // ${maestroCopiedText}. the string form is a text selector, as in tapOn.
61909
+ // the copied text is Orchestra.resolveText over the XCTest attributes:
61910
+ // text (the value), then hintText (the placeholder), then the label.
61797
61911
  async copyTextFrom(target) {
61798
- const opts = typeof target === "string" ? { id: target } : target;
61799
- const node = await this.findElement(opts);
61912
+ const opts = typeof target === "string" ? { text: target } : target;
61913
+ assertSupportedSelector(opts);
61914
+ const node = await this.resolveAccessibilityElement(opts, "copyTextFrom");
61800
61915
  if (!node) {
61801
61916
  throw new Error(`copyTextFrom: element not found: ${JSON.stringify(opts)}`);
61802
61917
  }
61803
- const captured = node.text ?? node.testID ?? "";
61918
+ const captured = node.value || node.placeholder || node.label || "";
61804
61919
  this.js.setCopiedText(captured);
61805
61920
  this.js.putEnv("maestroCopiedText", captured);
61806
61921
  console.log(`[flow] copied text: ${JSON.stringify(captured)}`);
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1465 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1477 | (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;
@@ -73,6 +73,11 @@ var import_node_os = __toESM(require("node:os"), 1);
73
73
  var import_node_path2 = __toESM(require("node:path"), 1);
74
74
  var import_node_util2 = require("node:util");
75
75
 
76
+ // src/admitted-mac-build.ts
77
+ function admittedMacBuilderSlot(env = process.env) {
78
+ return env.CONTRAST_REMOTE_BUILD === "mac" && env.REMOTE_MAC_SLOT_HELD === "1" && env.CONTRAST_HEAVY_ADMITTED === "1";
79
+ }
80
+
76
81
  // src/is-record.ts
77
82
  function isRecord(value) {
78
83
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -2343,7 +2348,7 @@ function compileSwiftProjectUnit(input, options) {
2343
2348
  };
2344
2349
  const hash = swiftArtifactHash(input, options.release, moduleRoot);
2345
2350
  return serialize(root, async () => {
2346
- if (process.platform === "darwin" && process.env.TM_SESSION && process.env.CI !== "true" && moduleRoot === import_node_path2.default.resolve(__sootsim_import_meta_dirname, "../../sootsim-swift") && !swiftDistributionAt(moduleRoot)) {
2351
+ if (process.platform === "darwin" && process.env.TM_SESSION && !admittedMacBuilderSlot() && process.env.CI !== "true" && moduleRoot === import_node_path2.default.resolve(__sootsim_import_meta_dirname, "../../sootsim-swift") && !swiftDistributionAt(moduleRoot)) {
2347
2352
  const requestRoot = (0, import_node_fs2.mkdtempSync)(import_node_path2.default.join(root, ".builder-request-"));
2348
2353
  const output = import_node_path2.default.join(requestRoot, "output");
2349
2354
  const request = import_node_path2.default.join(requestRoot, "request.json");
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1465 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1477 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/swift-compile.ts
4
4
  import { execFile as execFile2, execFileSync } from "node:child_process";
@@ -19,6 +19,11 @@ import os from "node:os";
19
19
  import path2 from "node:path";
20
20
  import { promisify as promisify2 } from "node:util";
21
21
 
22
+ // src/admitted-mac-build.ts
23
+ function admittedMacBuilderSlot(env = process.env) {
24
+ return env.CONTRAST_REMOTE_BUILD === "mac" && env.REMOTE_MAC_SLOT_HELD === "1" && env.CONTRAST_HEAVY_ADMITTED === "1";
25
+ }
26
+
22
27
  // src/is-record.ts
23
28
  function isRecord(value) {
24
29
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -2289,7 +2294,7 @@ function compileSwiftProjectUnit(input, options) {
2289
2294
  };
2290
2295
  const hash = swiftArtifactHash(input, options.release, moduleRoot);
2291
2296
  return serialize(root, async () => {
2292
- if (process.platform === "darwin" && process.env.TM_SESSION && process.env.CI !== "true" && moduleRoot === path2.resolve(import.meta.dirname, "../../sootsim-swift") && !swiftDistributionAt(moduleRoot)) {
2297
+ if (process.platform === "darwin" && process.env.TM_SESSION && !admittedMacBuilderSlot() && process.env.CI !== "true" && moduleRoot === path2.resolve(import.meta.dirname, "../../sootsim-swift") && !swiftDistributionAt(moduleRoot)) {
2293
2298
  const requestRoot = mkdtempSync(path2.join(root, ".builder-request-"));
2294
2299
  const output = path2.join(requestRoot, "output");
2295
2300
  const request = path2.join(requestRoot, "request.json");
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1465 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1477 | (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.1465 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1477 | (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.1465 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1477 | (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.1465 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1477 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/swiftContract.ts
4
4
  function isSwiftResourcePath(value) {