rnxsim 0.1.543 → 0.1.545

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 (61) hide show
  1. package/cli/commands/control.ts +8 -2
  2. package/cli/commands/inspect/wait-selector.ts +12 -2
  3. package/cli/outbound-endpoints.ts +5 -0
  4. package/dist-lib/agent-daemon-client.cjs +1 -1
  5. package/dist-lib/agent-events.cjs +1 -1
  6. package/dist-lib/agent-identity.cjs +1 -1
  7. package/dist-lib/agent-sessions.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/capture-contract.cjs +93 -2
  19. package/dist-lib/capture-contract.mjs +92 -2
  20. package/dist-lib/cli-constants.cjs +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.cjs +1 -1
  24. package/dist-lib/cloud.mjs +1 -1
  25. package/dist-lib/config.cjs +1 -1
  26. package/dist-lib/detox/index.cjs +1 -1
  27. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  28. package/dist-lib/home-paths.cjs +1 -1
  29. package/dist-lib/host/bridge-host.cjs +29 -14
  30. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  31. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  32. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  33. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  34. package/dist-lib/host/websocket-proxy.cjs +1 -1
  35. package/dist-lib/index.cjs +93 -2
  36. package/dist-lib/jump-to-source-babel.cjs +1 -1
  37. package/dist-lib/jump-to-source-native.cjs +1 -1
  38. package/dist-lib/menu.cjs +1 -1
  39. package/dist-lib/menu.mjs +1 -1
  40. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  41. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  42. package/dist-lib/metro-production-bundle.cjs +1 -1
  43. package/dist-lib/metro-production-bundle.mjs +1 -1
  44. package/dist-lib/metro.cjs +1 -1
  45. package/dist-lib/profiles.cjs +1 -1
  46. package/dist-lib/public-brand.cjs +1 -1
  47. package/dist-lib/react-native-host-modules.cjs +1 -1
  48. package/dist-lib/react-native-host-modules.mjs +1 -1
  49. package/dist-lib/render-mode.cjs +1 -1
  50. package/dist-lib/scripts/dev-server-scanner.cjs +30 -14
  51. package/dist-lib/sdk.cjs +1 -1
  52. package/dist-lib/sdk.mjs +1 -1
  53. package/dist-lib/skills.cjs +30 -15
  54. package/dist-lib/swift-submit.cjs +1 -1
  55. package/dist-lib/swift-submit.mjs +1 -1
  56. package/dist-lib/swift.cjs +1 -1
  57. package/dist-lib/vite.cjs +1 -1
  58. package/package.json +1 -1
  59. package/scripts/dev-server-scanner.ts +40 -13
  60. package/src/capture-contract.ts +143 -2
  61. package/src/index.ts +3 -0
@@ -425,14 +425,20 @@ async function resolveConnectionInputForCli(target: string): Promise<ResolvedDev
425
425
  try {
426
426
  return await resolveConnectionInput(normalized)
427
427
  } catch (error) {
428
- if (!(error instanceof Error) || !error.message.startsWith("could not resolve a native bundle")) {
428
+ if (
429
+ !(error instanceof Error) ||
430
+ !error.message.startsWith('could not resolve a native bundle')
431
+ ) {
429
432
  throw error
430
433
  }
431
434
  lastError = error
432
435
  }
433
436
  await sleep(DEV_BUNDLE_RESOLVE_INTERVAL_MS)
434
437
  }
435
- throw lastError ?? new Error("could not resolve a native bundle for " + normalized + " after retrying.")
438
+ throw (
439
+ lastError ??
440
+ new Error('could not resolve a native bundle for ' + normalized + ' after retrying.')
441
+ )
436
442
  }
437
443
 
438
444
  function getShellRoutePrefix(pathname: string): string {
@@ -19,13 +19,23 @@ export async function runWaitSelectorSubcommand(opts: {
19
19
  const testId = positional[1]
20
20
  if (!testId) {
21
21
  console.error(
22
- inspectUsage('selector', '<testid> [--max-ms 5000] [--gone] [--structural]'),
22
+ inspectUsage(
23
+ 'selector',
24
+ '<testid> [--max-ms 5000 | --timeout 5000] [--gone] [--structural]',
25
+ ),
23
26
  )
24
27
  rnxExit(1)
25
28
  }
29
+ // the wait budget. `--max-ms` names it, and `--timeout` (the global
30
+ // per-command budget) means the same thing for a command whose whole job is
31
+ // to wait — without this it parsed away and the wait silently stayed at 5s,
32
+ // reporting a false timeout.
26
33
  const maxMsIdx = args.indexOf('--max-ms')
34
+ const budgetIdx = maxMsIdx >= 0 ? maxMsIdx : args.indexOf('--timeout')
27
35
  const timeoutMs =
28
- maxMsIdx >= 0 && args[maxMsIdx + 1] ? Math.max(100, Number(args[maxMsIdx + 1])) : 5000
36
+ budgetIdx >= 0 && args[budgetIdx + 1]
37
+ ? Math.max(100, Number(args[budgetIdx + 1]))
38
+ : 5000
29
39
  const gone = args.includes('--gone')
30
40
  const structural = args.includes('--structural')
31
41
 
@@ -277,6 +277,11 @@ export const DECLARED_OUTBOUND_CALLS: Record<string, OutboundCallDeclaration> =
277
277
  { category: 'contrast_user_action', count: 1 },
278
278
  'packages/rnx-cloud-box/src/box-do.ts :: fetch :: `${origin}/api/v1/rnx/sessions/internal/${encodeURIComponent()}`':
279
279
  { category: 'contrast_user_action', count: 1 },
280
+ // stop and delete authorize the caller against the account before any
281
+ // teardown. the account service owns the verdict on a key, its scope and the
282
+ // account it names; no project content is sent.
283
+ 'packages/rnx-cloud-box/src/box-do.ts :: fetch :: `${origin}/api/v1/rnx/sessions?accountId=${encodeURIComponent()}&kind=box&status=running`':
284
+ { category: 'contrast_user_action', count: 1 },
280
285
  // the Cloudflare Worker forwards the already-authenticated request to the
281
286
  // selected Durable Object in the same service.
282
287
  'packages/rnx-cloud-box/src/worker.ts :: fetch :: request': {
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (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.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (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.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
package/dist-lib/beta.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
package/dist-lib/beta.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/beta.ts
4
4
  var IS_BETA = true;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (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.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (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.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var SIM_LONG_PRESS_MAX_MS = 5e3;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (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.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var REFUSED_PERFORM_STEP_TYPES = [
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (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;
@@ -25,6 +25,7 @@ __export(capture_contract_exports, {
25
25
  RNX_SCREEN_CAPTURE_VERSION: () => RNX_SCREEN_CAPTURE_VERSION,
26
26
  isRnxCaptureRegionAtlas: () => isRnxCaptureRegionAtlas,
27
27
  isRnxScreenCapture: () => isRnxScreenCapture,
28
+ packRnxCaptureRegions: () => packRnxCaptureRegions,
28
29
  rnxCaptureRasterRegions: () => rnxCaptureRasterRegions,
29
30
  rnxRasterFrames: () => rnxRasterFrames,
30
31
  selectRnxRasterNodeIds: () => selectRnxRasterNodeIds
@@ -138,6 +139,95 @@ function rnxCaptureRasterRegions(capture) {
138
139
  return frame ? [{ key: String(nodeId), nodeId, frame }] : [];
139
140
  });
140
141
  }
142
+ function packRnxCaptureRegions(regions, pixelRatio, surface) {
143
+ const physical = regions.map((region) => {
144
+ const left = Math.floor(region.frame.x * pixelRatio);
145
+ const top = Math.floor(region.frame.y * pixelRatio);
146
+ const right = Math.ceil((region.frame.x + region.frame.width) * pixelRatio);
147
+ const bottom = Math.ceil((region.frame.y + region.frame.height) * pixelRatio);
148
+ if (left < 0 || top < 0 || right > surface.pixelWidth || bottom > surface.pixelHeight || right <= left || bottom <= top) {
149
+ throw new Error(`capture region ${region.key} is outside the app surface`);
150
+ }
151
+ return {
152
+ key: region.key,
153
+ nodeId: region.nodeId,
154
+ frame: {
155
+ x: left / pixelRatio,
156
+ y: top / pixelRatio,
157
+ width: (right - left) / pixelRatio,
158
+ height: (bottom - top) / pixelRatio
159
+ },
160
+ sourceX: left,
161
+ sourceY: top,
162
+ pixelWidth: right - left,
163
+ pixelHeight: bottom - top
164
+ };
165
+ });
166
+ const largestWidth = Math.max(...physical.map((region) => region.pixelWidth));
167
+ const totalArea = physical.reduce(
168
+ (area, region) => area + region.pixelWidth * region.pixelHeight,
169
+ 0
170
+ );
171
+ if (totalArea > 4194304) {
172
+ throw new Error("capture region pixels exceed the atlas budget");
173
+ }
174
+ const candidates = [
175
+ largestWidth,
176
+ Math.max(largestWidth, Math.ceil(Math.sqrt(totalArea))),
177
+ Math.max(largestWidth, surface.pixelWidth),
178
+ 4096
179
+ ];
180
+ const ordered = [...physical].sort(
181
+ (left, right) => right.pixelHeight - left.pixelHeight || right.pixelWidth - left.pixelWidth || left.key.localeCompare(right.key)
182
+ );
183
+ let best = null;
184
+ for (const candidate of [...new Set(candidates)]) {
185
+ if (candidate > 4096) continue;
186
+ let x = 0;
187
+ let y = 0;
188
+ let rowHeight = 0;
189
+ let usedWidth = 0;
190
+ const packed = [];
191
+ for (const region of ordered) {
192
+ if (x > 0 && x + region.pixelWidth > candidate) {
193
+ y += rowHeight;
194
+ x = 0;
195
+ rowHeight = 0;
196
+ }
197
+ packed.push({ ...region, atlasX: x, atlasY: y });
198
+ x += region.pixelWidth;
199
+ rowHeight = Math.max(rowHeight, region.pixelHeight);
200
+ usedWidth = Math.max(usedWidth, x);
201
+ }
202
+ const height2 = y + rowHeight;
203
+ if (height2 > 4096 || usedWidth * height2 > 4194304) continue;
204
+ const result = { width: usedWidth, height: height2, regions: packed };
205
+ if (!best || result.width * result.height < best.width * best.height) best = result;
206
+ }
207
+ if (!best) throw new Error("capture regions cannot fit in one bounded atlas");
208
+ const width = best.width / pixelRatio;
209
+ const height = best.height / pixelRatio;
210
+ return {
211
+ width,
212
+ height,
213
+ pixelWidth: best.width,
214
+ pixelHeight: best.height,
215
+ regions: best.regions,
216
+ atlasRegions: best.regions.map((region) => ({
217
+ key: region.key,
218
+ nodeId: region.nodeId,
219
+ frame: region.frame,
220
+ // a region flush with the far edge is anchored to the logical edge so
221
+ // its source never runs past the atlas by a rounding hair
222
+ source: {
223
+ x: region.atlasX + region.pixelWidth === best.width ? width - region.frame.width : region.atlasX / pixelRatio,
224
+ y: region.atlasY + region.pixelHeight === best.height ? height - region.frame.height : region.atlasY / pixelRatio,
225
+ width: region.frame.width,
226
+ height: region.frame.height
227
+ }
228
+ }))
229
+ };
230
+ }
141
231
  function captureRecord(value) {
142
232
  return value !== null && typeof value === "object" && !Array.isArray(value);
143
233
  }
@@ -193,7 +283,7 @@ function isRnxScreenCapture(value) {
193
283
  return captureRecord(tree.viewport) && captureInteger(tree.viewport.width) && tree.viewport.width > 0 && captureInteger(tree.viewport.height) && tree.viewport.height > 0 && captureInteger(tree.rootNodeId) && (tree.commitRevision === void 0 || captureInteger(tree.commitRevision)) && Array.isArray(tree.nodes) && tree.nodes.every(captureNode) && (visual === void 0 || visual.kind === "png" && (visual.producer === "headless-cpu-app-surface" || visual.producer === "browser-compositor-app-surface") && typeof visual.dataUri === "string" && visual.dataUri.startsWith("data:image/png;base64,") && captureInteger(visual.pixelWidth) && visual.pixelWidth > 0 && captureInteger(visual.pixelHeight) && visual.pixelHeight > 0);
194
284
  }
195
285
  function isRnxCaptureRegionAtlas(value) {
196
- if (!captureRecord(value) || value.kind !== "png-atlas" || value.producer !== "headless-cpu-app-surface" || typeof value.dataUri !== "string" || !value.dataUri.startsWith("data:image/png;base64,") || !captureNumber(value.width) || value.width <= 0 || !captureNumber(value.height) || value.height <= 0 || !captureInteger(value.pixelWidth) || value.pixelWidth <= 0 || !captureInteger(value.pixelHeight) || value.pixelHeight <= 0 || !Array.isArray(value.regions) || value.regions.length === 0 || value.regions.length > 256) {
286
+ if (!captureRecord(value) || value.kind !== "png-atlas" || value.producer !== "headless-cpu-app-surface" && value.producer !== "browser-compositor-app-surface" || typeof value.dataUri !== "string" || !value.dataUri.startsWith("data:image/png;base64,") || !captureNumber(value.width) || value.width <= 0 || !captureNumber(value.height) || value.height <= 0 || !captureInteger(value.pixelWidth) || value.pixelWidth <= 0 || !captureInteger(value.pixelHeight) || value.pixelHeight <= 0 || !Array.isArray(value.regions) || value.regions.length === 0 || value.regions.length > 256) {
197
287
  return false;
198
288
  }
199
289
  const scale = value.pixelWidth / value.width;
@@ -214,6 +304,7 @@ function isRnxCaptureRegionAtlas(value) {
214
304
  RNX_SCREEN_CAPTURE_VERSION,
215
305
  isRnxCaptureRegionAtlas,
216
306
  isRnxScreenCapture,
307
+ packRnxCaptureRegions,
217
308
  rnxCaptureRasterRegions,
218
309
  rnxRasterFrames,
219
310
  selectRnxRasterNodeIds
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/capture-contract.ts
4
4
  var RNX_SCREEN_CAPTURE_VERSION = 1;
@@ -109,6 +109,95 @@ function rnxCaptureRasterRegions(capture) {
109
109
  return frame ? [{ key: String(nodeId), nodeId, frame }] : [];
110
110
  });
111
111
  }
112
+ function packRnxCaptureRegions(regions, pixelRatio, surface) {
113
+ const physical = regions.map((region) => {
114
+ const left = Math.floor(region.frame.x * pixelRatio);
115
+ const top = Math.floor(region.frame.y * pixelRatio);
116
+ const right = Math.ceil((region.frame.x + region.frame.width) * pixelRatio);
117
+ const bottom = Math.ceil((region.frame.y + region.frame.height) * pixelRatio);
118
+ if (left < 0 || top < 0 || right > surface.pixelWidth || bottom > surface.pixelHeight || right <= left || bottom <= top) {
119
+ throw new Error(`capture region ${region.key} is outside the app surface`);
120
+ }
121
+ return {
122
+ key: region.key,
123
+ nodeId: region.nodeId,
124
+ frame: {
125
+ x: left / pixelRatio,
126
+ y: top / pixelRatio,
127
+ width: (right - left) / pixelRatio,
128
+ height: (bottom - top) / pixelRatio
129
+ },
130
+ sourceX: left,
131
+ sourceY: top,
132
+ pixelWidth: right - left,
133
+ pixelHeight: bottom - top
134
+ };
135
+ });
136
+ const largestWidth = Math.max(...physical.map((region) => region.pixelWidth));
137
+ const totalArea = physical.reduce(
138
+ (area, region) => area + region.pixelWidth * region.pixelHeight,
139
+ 0
140
+ );
141
+ if (totalArea > 4194304) {
142
+ throw new Error("capture region pixels exceed the atlas budget");
143
+ }
144
+ const candidates = [
145
+ largestWidth,
146
+ Math.max(largestWidth, Math.ceil(Math.sqrt(totalArea))),
147
+ Math.max(largestWidth, surface.pixelWidth),
148
+ 4096
149
+ ];
150
+ const ordered = [...physical].sort(
151
+ (left, right) => right.pixelHeight - left.pixelHeight || right.pixelWidth - left.pixelWidth || left.key.localeCompare(right.key)
152
+ );
153
+ let best = null;
154
+ for (const candidate of [...new Set(candidates)]) {
155
+ if (candidate > 4096) continue;
156
+ let x = 0;
157
+ let y = 0;
158
+ let rowHeight = 0;
159
+ let usedWidth = 0;
160
+ const packed = [];
161
+ for (const region of ordered) {
162
+ if (x > 0 && x + region.pixelWidth > candidate) {
163
+ y += rowHeight;
164
+ x = 0;
165
+ rowHeight = 0;
166
+ }
167
+ packed.push({ ...region, atlasX: x, atlasY: y });
168
+ x += region.pixelWidth;
169
+ rowHeight = Math.max(rowHeight, region.pixelHeight);
170
+ usedWidth = Math.max(usedWidth, x);
171
+ }
172
+ const height2 = y + rowHeight;
173
+ if (height2 > 4096 || usedWidth * height2 > 4194304) continue;
174
+ const result = { width: usedWidth, height: height2, regions: packed };
175
+ if (!best || result.width * result.height < best.width * best.height) best = result;
176
+ }
177
+ if (!best) throw new Error("capture regions cannot fit in one bounded atlas");
178
+ const width = best.width / pixelRatio;
179
+ const height = best.height / pixelRatio;
180
+ return {
181
+ width,
182
+ height,
183
+ pixelWidth: best.width,
184
+ pixelHeight: best.height,
185
+ regions: best.regions,
186
+ atlasRegions: best.regions.map((region) => ({
187
+ key: region.key,
188
+ nodeId: region.nodeId,
189
+ frame: region.frame,
190
+ // a region flush with the far edge is anchored to the logical edge so
191
+ // its source never runs past the atlas by a rounding hair
192
+ source: {
193
+ x: region.atlasX + region.pixelWidth === best.width ? width - region.frame.width : region.atlasX / pixelRatio,
194
+ y: region.atlasY + region.pixelHeight === best.height ? height - region.frame.height : region.atlasY / pixelRatio,
195
+ width: region.frame.width,
196
+ height: region.frame.height
197
+ }
198
+ }))
199
+ };
200
+ }
112
201
  function captureRecord(value) {
113
202
  return value !== null && typeof value === "object" && !Array.isArray(value);
114
203
  }
@@ -164,7 +253,7 @@ function isRnxScreenCapture(value) {
164
253
  return captureRecord(tree.viewport) && captureInteger(tree.viewport.width) && tree.viewport.width > 0 && captureInteger(tree.viewport.height) && tree.viewport.height > 0 && captureInteger(tree.rootNodeId) && (tree.commitRevision === void 0 || captureInteger(tree.commitRevision)) && Array.isArray(tree.nodes) && tree.nodes.every(captureNode) && (visual === void 0 || visual.kind === "png" && (visual.producer === "headless-cpu-app-surface" || visual.producer === "browser-compositor-app-surface") && typeof visual.dataUri === "string" && visual.dataUri.startsWith("data:image/png;base64,") && captureInteger(visual.pixelWidth) && visual.pixelWidth > 0 && captureInteger(visual.pixelHeight) && visual.pixelHeight > 0);
165
254
  }
166
255
  function isRnxCaptureRegionAtlas(value) {
167
- if (!captureRecord(value) || value.kind !== "png-atlas" || value.producer !== "headless-cpu-app-surface" || typeof value.dataUri !== "string" || !value.dataUri.startsWith("data:image/png;base64,") || !captureNumber(value.width) || value.width <= 0 || !captureNumber(value.height) || value.height <= 0 || !captureInteger(value.pixelWidth) || value.pixelWidth <= 0 || !captureInteger(value.pixelHeight) || value.pixelHeight <= 0 || !Array.isArray(value.regions) || value.regions.length === 0 || value.regions.length > 256) {
256
+ if (!captureRecord(value) || value.kind !== "png-atlas" || value.producer !== "headless-cpu-app-surface" && value.producer !== "browser-compositor-app-surface" || typeof value.dataUri !== "string" || !value.dataUri.startsWith("data:image/png;base64,") || !captureNumber(value.width) || value.width <= 0 || !captureNumber(value.height) || value.height <= 0 || !captureInteger(value.pixelWidth) || value.pixelWidth <= 0 || !captureInteger(value.pixelHeight) || value.pixelHeight <= 0 || !Array.isArray(value.regions) || value.regions.length === 0 || value.regions.length > 256) {
168
257
  return false;
169
258
  }
170
259
  const scale = value.pixelWidth / value.width;
@@ -184,6 +273,7 @@ export {
184
273
  RNX_SCREEN_CAPTURE_VERSION,
185
274
  isRnxCaptureRegionAtlas,
186
275
  isRnxScreenCapture,
276
+ packRnxCaptureRegions,
187
277
  rnxCaptureRasterRegions,
188
278
  rnxRasterFrames,
189
279
  selectRnxRasterNodeIds
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (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.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (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.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/cloud-contract.ts
4
4
  var RNX_CLOUD_MAX_ARTIFACT_BYTES = 20 * 1024 * 1024;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (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.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  var __defProp = Object.defineProperty;
3
3
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
4
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (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.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (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.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (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;
@@ -5098,7 +5098,7 @@ async function resolveLocalIconPath(hostname, port, rawIcon) {
5098
5098
  const res = await httpGet(hostname, port, candidate, "HEAD", ENRICH_TIMEOUT_MS);
5099
5099
  if (res?.statusCode === 200) {
5100
5100
  localIconPathCache.set(port, candidate);
5101
- portCache.delete(port);
5101
+ invalidatePortCache(port);
5102
5102
  return;
5103
5103
  }
5104
5104
  }
@@ -5220,7 +5220,7 @@ async function fetchManifestEnrichment(result, buildIconProxyUrl) {
5220
5220
  iconPath: parsed.iconPath,
5221
5221
  bundleId: parsed.bundleId
5222
5222
  });
5223
- portCache.delete(result.port);
5223
+ invalidatePortCache(result.port);
5224
5224
  }
5225
5225
  var knownNonPatched = /* @__PURE__ */ new Set();
5226
5226
  var knownNonExpo = /* @__PURE__ */ new Set();
@@ -5260,16 +5260,19 @@ async function probePort(port, buildIconProxyUrl, listeningProcess) {
5260
5260
  const framework = launchUrl2.includes(
5261
5261
  "/one/metro-entry.bundle"
5262
5262
  ) ? "one" : "expo";
5263
- return applyManifest(
5264
- {
5265
- port,
5266
- framework,
5267
- bundleUrl: withRuntimeConfig(port, launchUrl2, owner.cwd),
5268
- hmrUrl: `${buildLoopbackProbeBaseUrl("ws:", probeHostname, port)}/hot`,
5269
- lastSeen: Date.now(),
5270
- ...owner
5271
- },
5272
- manifestRes,
5263
+ return enrichWithManifest(
5264
+ applyManifest(
5265
+ {
5266
+ port,
5267
+ framework,
5268
+ bundleUrl: withRuntimeConfig(port, launchUrl2, owner.cwd),
5269
+ hmrUrl: `${buildLoopbackProbeBaseUrl("ws:", probeHostname, port)}/hot`,
5270
+ lastSeen: Date.now(),
5271
+ ...owner
5272
+ },
5273
+ manifestRes,
5274
+ buildIconProxyUrl
5275
+ ),
5273
5276
  buildIconProxyUrl
5274
5277
  );
5275
5278
  }
@@ -5347,6 +5350,11 @@ function isSootSimSelfServer(server) {
5347
5350
  return false;
5348
5351
  }
5349
5352
  var portCache = /* @__PURE__ */ new Map();
5353
+ var portCacheInvalidatedAt = /* @__PURE__ */ new Map();
5354
+ function invalidatePortCache(port) {
5355
+ portCache.delete(port);
5356
+ portCacheInvalidatedAt.set(port, Date.now());
5357
+ }
5350
5358
  var NEGATIVE_CACHE_TTL_MS = 3e4;
5351
5359
  var WEAK_RESULT_CACHE_TTL_MS = 1500;
5352
5360
  function isWeakCachedResult(result) {
@@ -5401,6 +5409,9 @@ async function scanDevServers(opts = {}) {
5401
5409
  for (const p of [...localIconPathCache.keys()]) {
5402
5410
  if (!currentPorts.has(p)) localIconPathCache.delete(p);
5403
5411
  }
5412
+ for (const p of [...portCacheInvalidatedAt.keys()]) {
5413
+ if (!currentPorts.has(p)) portCacheInvalidatedAt.delete(p);
5414
+ }
5404
5415
  const results = [];
5405
5416
  const toProbe = [];
5406
5417
  for (const { port, pid } of processes) {
@@ -5419,12 +5430,16 @@ async function scanDevServers(opts = {}) {
5419
5430
  toProbe.push({ port, pid });
5420
5431
  }
5421
5432
  if (toProbe.length > 0) {
5433
+ const scanStartedAt = Date.now();
5422
5434
  const probed = await Promise.all(
5423
5435
  toProbe.map((p) => probePort(p.port, opts.buildIconProxyUrl, p))
5424
5436
  );
5425
5437
  probed.forEach((result, i) => {
5426
5438
  const { port, pid } = toProbe[i];
5427
- if (pid !== 0) portCache.set(port, { pid, result, cachedAt: Date.now() });
5439
+ const invalidatedAt = portCacheInvalidatedAt.get(port) ?? 0;
5440
+ if (pid !== 0 && invalidatedAt < scanStartedAt) {
5441
+ portCache.set(port, { pid, result, cachedAt: Date.now() });
5442
+ }
5428
5443
  if (result) results.push(result);
5429
5444
  });
5430
5445
  }
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (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.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/host/fetch-proxy-overrides.ts
4
4
  var FETCH_PROXY_BROWSER_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.543 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.545 | (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;