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
@@ -318,6 +318,146 @@ export function rnxCaptureRasterRegions(
318
318
  })
319
319
  }
320
320
 
321
+ /** a region request snapped to the surface pixel grid and placed in the atlas */
322
+ export interface RnxPackedCaptureRegion extends RnxCaptureRegionRequest {
323
+ /** top-left of the region on the app surface, in pixels */
324
+ sourceX: number
325
+ sourceY: number
326
+ pixelWidth: number
327
+ pixelHeight: number
328
+ /** top-left of the region inside the atlas, in pixels */
329
+ atlasX: number
330
+ atlasY: number
331
+ }
332
+
333
+ export interface RnxPackedCaptureAtlas {
334
+ /** logical atlas dimensions; pixel dimensions are these times the pixel ratio */
335
+ width: number
336
+ height: number
337
+ pixelWidth: number
338
+ pixelHeight: number
339
+ regions: RnxPackedCaptureRegion[]
340
+ /** the wire regions a producer publishes beside the encoded atlas */
341
+ atlasRegions: RnxCaptureAtlasRegion[]
342
+ }
343
+
344
+ // the bounded selective-layer atlas every producer ships: regions snapped to
345
+ // whole surface pixels, shelf-packed into the smallest of a few candidate
346
+ // widths, and mapped back to logical atlas coordinates. one packer for the
347
+ // headless renderer (which draws isolated subtrees into the slots) and the
348
+ // browser producer (which crops them out of a screen-sized screenshot), so a
349
+ // consumer never learns which one made the artifact from the layout.
350
+ export function packRnxCaptureRegions(
351
+ regions: readonly RnxCaptureRegionRequest[],
352
+ pixelRatio: number,
353
+ surface: { pixelWidth: number; pixelHeight: number },
354
+ ): RnxPackedCaptureAtlas {
355
+ const physical = regions.map((region) => {
356
+ const left = Math.floor(region.frame.x * pixelRatio)
357
+ const top = Math.floor(region.frame.y * pixelRatio)
358
+ const right = Math.ceil((region.frame.x + region.frame.width) * pixelRatio)
359
+ const bottom = Math.ceil((region.frame.y + region.frame.height) * pixelRatio)
360
+ if (
361
+ left < 0 ||
362
+ top < 0 ||
363
+ right > surface.pixelWidth ||
364
+ bottom > surface.pixelHeight ||
365
+ right <= left ||
366
+ bottom <= top
367
+ ) {
368
+ throw new Error(`capture region ${region.key} is outside the app surface`)
369
+ }
370
+ return {
371
+ key: region.key,
372
+ nodeId: region.nodeId,
373
+ frame: {
374
+ x: left / pixelRatio,
375
+ y: top / pixelRatio,
376
+ width: (right - left) / pixelRatio,
377
+ height: (bottom - top) / pixelRatio,
378
+ },
379
+ sourceX: left,
380
+ sourceY: top,
381
+ pixelWidth: right - left,
382
+ pixelHeight: bottom - top,
383
+ }
384
+ })
385
+ const largestWidth = Math.max(...physical.map((region) => region.pixelWidth))
386
+ const totalArea = physical.reduce(
387
+ (area, region) => area + region.pixelWidth * region.pixelHeight,
388
+ 0,
389
+ )
390
+ if (totalArea > 4_194_304) {
391
+ throw new Error('capture region pixels exceed the atlas budget')
392
+ }
393
+ const candidates = [
394
+ largestWidth,
395
+ Math.max(largestWidth, Math.ceil(Math.sqrt(totalArea))),
396
+ Math.max(largestWidth, surface.pixelWidth),
397
+ 4_096,
398
+ ]
399
+ const ordered = [...physical].sort(
400
+ (left, right) =>
401
+ right.pixelHeight - left.pixelHeight ||
402
+ right.pixelWidth - left.pixelWidth ||
403
+ left.key.localeCompare(right.key),
404
+ )
405
+ let best: { width: number; height: number; regions: RnxPackedCaptureRegion[] } | null =
406
+ null
407
+ for (const candidate of [...new Set(candidates)]) {
408
+ if (candidate > 4_096) continue
409
+ let x = 0
410
+ let y = 0
411
+ let rowHeight = 0
412
+ let usedWidth = 0
413
+ const packed: RnxPackedCaptureRegion[] = []
414
+ for (const region of ordered) {
415
+ if (x > 0 && x + region.pixelWidth > candidate) {
416
+ y += rowHeight
417
+ x = 0
418
+ rowHeight = 0
419
+ }
420
+ packed.push({ ...region, atlasX: x, atlasY: y })
421
+ x += region.pixelWidth
422
+ rowHeight = Math.max(rowHeight, region.pixelHeight)
423
+ usedWidth = Math.max(usedWidth, x)
424
+ }
425
+ const height = y + rowHeight
426
+ if (height > 4_096 || usedWidth * height > 4_194_304) continue
427
+ const result = { width: usedWidth, height, regions: packed }
428
+ if (!best || result.width * result.height < best.width * best.height) best = result
429
+ }
430
+ if (!best) throw new Error('capture regions cannot fit in one bounded atlas')
431
+ const width = best.width / pixelRatio
432
+ const height = best.height / pixelRatio
433
+ return {
434
+ width,
435
+ height,
436
+ pixelWidth: best.width,
437
+ pixelHeight: best.height,
438
+ regions: best.regions,
439
+ atlasRegions: best.regions.map((region) => ({
440
+ key: region.key,
441
+ nodeId: region.nodeId,
442
+ frame: region.frame,
443
+ // a region flush with the far edge is anchored to the logical edge so
444
+ // its source never runs past the atlas by a rounding hair
445
+ source: {
446
+ x:
447
+ region.atlasX + region.pixelWidth === best.width
448
+ ? width - region.frame.width
449
+ : region.atlasX / pixelRatio,
450
+ y:
451
+ region.atlasY + region.pixelHeight === best.height
452
+ ? height - region.frame.height
453
+ : region.atlasY / pixelRatio,
454
+ width: region.frame.width,
455
+ height: region.frame.height,
456
+ },
457
+ })),
458
+ }
459
+ }
460
+
321
461
  export interface RnxCaptureAtlasRegion extends RnxCaptureRegionRequest {
322
462
  /** source rectangle inside the packed atlas, in logical atlas coordinates */
323
463
  source: RnxCaptureRect
@@ -325,7 +465,7 @@ export interface RnxCaptureAtlasRegion extends RnxCaptureRegionRequest {
325
465
 
326
466
  export interface RnxCaptureRegionAtlas {
327
467
  kind: 'png-atlas'
328
- producer: 'headless-cpu-app-surface'
468
+ producer: 'headless-cpu-app-surface' | 'browser-compositor-app-surface'
329
469
  dataUri: string
330
470
  /** logical atlas dimensions; the encoded PNG uses pixelWidth × pixelHeight */
331
471
  width: number
@@ -533,7 +673,8 @@ export function isRnxCaptureRegionAtlas(value: unknown): value is RnxCaptureRegi
533
673
  if (
534
674
  !captureRecord(value) ||
535
675
  value.kind !== 'png-atlas' ||
536
- value.producer !== 'headless-cpu-app-surface' ||
676
+ (value.producer !== 'headless-cpu-app-surface' &&
677
+ value.producer !== 'browser-compositor-app-surface') ||
537
678
  typeof value.dataUri !== 'string' ||
538
679
  !value.dataUri.startsWith('data:image/png;base64,') ||
539
680
  !captureNumber(value.width) ||
package/src/index.ts CHANGED
@@ -39,6 +39,7 @@ export {
39
39
  isRnxCaptureRegionAtlas,
40
40
  isRnxScreenCapture,
41
41
  rnxCaptureRasterRegions,
42
+ packRnxCaptureRegions,
42
43
  rnxRasterFrames,
43
44
  RNX_SCREEN_CAPTURE_VERSION,
44
45
  selectRnxRasterNodeIds,
@@ -54,6 +55,8 @@ export {
54
55
  type RnxCaptureSource,
55
56
  type RnxCaptureStyleTokenBinding,
56
57
  type RnxCaptureTextLine,
58
+ type RnxPackedCaptureAtlas,
59
+ type RnxPackedCaptureRegion,
57
60
  type RnxCaptureTextSegment,
58
61
  type RnxCaptureTree,
59
62
  type RnxCaptureVisualEvidence,