peachsim 0.1.527 → 0.1.570

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 (158) hide show
  1. package/README.md +26 -26
  2. package/cli/app-fonts.ts +1 -1
  3. package/cli/app-splash.ts +1 -1
  4. package/cli/bin.ts +1 -1
  5. package/cli/bridge-diagnostics.ts +1 -1
  6. package/cli/bridge-flow-runner.ts +57 -5
  7. package/cli/cloud-client.ts +273 -6
  8. package/cli/cloud-dispatch.ts +22 -2
  9. package/cli/cloud-session.ts +60 -4
  10. package/cli/cloud-test-tunnel.ts +354 -0
  11. package/cli/commands/box/bundle-plane.ts +2 -2
  12. package/cli/commands/box/checkout-plane.ts +1 -1
  13. package/cli/commands/box/rnx-command.ts +2 -2
  14. package/cli/commands/box/search-command.ts +2 -2
  15. package/cli/commands/box.ts +8 -8
  16. package/cli/commands/compat.ts +1 -1
  17. package/cli/commands/control.ts +22 -3
  18. package/cli/commands/detox.ts +1 -1
  19. package/cli/commands/device.ts +1 -1
  20. package/cli/commands/diagnose.ts +1 -1
  21. package/cli/commands/film.ts +1 -1
  22. package/cli/commands/flow.ts +60 -3
  23. package/cli/commands/inspect/actions.ts +1 -1
  24. package/cli/commands/inspect/core.ts +6 -7
  25. package/cli/commands/inspect/find.ts +2 -1
  26. package/cli/commands/inspect/resolve-target.ts +5 -3
  27. package/cli/commands/inspect/shared.ts +1 -1
  28. package/cli/commands/inspect/wait-event.ts +1 -1
  29. package/cli/commands/inspect/wait-selector.ts +15 -4
  30. package/cli/commands/inspect.ts +19 -14
  31. package/cli/commands/maestro.ts +464 -43
  32. package/cli/commands/permissions.ts +1 -1
  33. package/cli/commands/platform.ts +205 -8
  34. package/cli/commands/preview.ts +2 -2
  35. package/cli/commands/record.ts +2 -2
  36. package/cli/commands/report-issue.ts +2 -2
  37. package/cli/commands/screenshot-layers.ts +1 -1
  38. package/cli/commands/screenshot.ts +1 -1
  39. package/cli/commands/setup.ts +2 -2
  40. package/cli/commands/test.ts +440 -115
  41. package/cli/commands/three-mode.ts +1 -1
  42. package/cli/commands/upload.ts +5 -5
  43. package/cli/commands/what-happened.ts +1 -1
  44. package/cli/desktop-companion.ts +3 -3
  45. package/cli/drivers/playwright-sim-host.ts +2 -2
  46. package/cli/flow-file.ts +7 -0
  47. package/cli/flow-live-status.ts +65 -8
  48. package/cli/help-core.ts +3 -3
  49. package/cli/hidden-runtime-alias.ts +1 -1
  50. package/cli/maestro-report.ts +178 -0
  51. package/cli/main.ts +1 -1
  52. package/cli/outbound-endpoints.ts +185 -136
  53. package/cli/parse-args.ts +1 -1
  54. package/cli/registry.ts +1 -1
  55. package/cli/resolve-assets.ts +1 -1
  56. package/cli/run-registry.ts +8 -0
  57. package/cli/send-to-box.ts +4 -4
  58. package/cli/ws-bridge.ts +3 -5
  59. package/detox/expectations.ts +1 -1
  60. package/detox/gestures.ts +2 -2
  61. package/detox/index.ts +71 -29
  62. package/detox/jest-preset.cjs +3 -3
  63. package/detox/jest-setup-after-env.cjs +1 -1
  64. package/dist-lib/agent-daemon-client.cjs +2 -2
  65. package/dist-lib/agent-events.cjs +1 -1
  66. package/dist-lib/agent-identity.cjs +1 -1
  67. package/dist-lib/agent-sessions.cjs +2 -2
  68. package/dist-lib/attached-projects.cjs +2 -2
  69. package/dist-lib/auth/shared-session.cjs +1 -1
  70. package/dist-lib/backend-origin.cjs +1 -1
  71. package/dist-lib/beta.cjs +1 -1
  72. package/dist-lib/beta.mjs +1 -1
  73. package/dist-lib/bridge-constants.cjs +1 -1
  74. package/dist-lib/bridge-contract-input.cjs +1 -1
  75. package/dist-lib/bridge-contract-input.mjs +1 -1
  76. package/dist-lib/bridge-contract.cjs +1 -1
  77. package/dist-lib/bridge-contract.mjs +1 -1
  78. package/dist-lib/capture-contract.cjs +94 -3
  79. package/dist-lib/capture-contract.mjs +93 -3
  80. package/dist-lib/cli-constants.cjs +1 -1
  81. package/dist-lib/cloud-contract.cjs +1 -1
  82. package/dist-lib/cloud-contract.mjs +1 -1
  83. package/dist-lib/cloud.cjs +2 -2
  84. package/dist-lib/cloud.mjs +2 -2
  85. package/dist-lib/config.cjs +1 -1
  86. package/dist-lib/detox/index.cjs +106 -25
  87. package/dist-lib/detox/jest-preset.cjs +3 -3
  88. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  89. package/dist-lib/home-paths.cjs +1 -1
  90. package/dist-lib/host/bridge-host.cjs +137 -61
  91. package/dist-lib/host/fetch-proxy-handler.cjs +28 -2
  92. package/dist-lib/host/fetch-proxy-overrides.cjs +33 -3
  93. package/dist-lib/host/fetch-proxy-overrides.mjs +30 -2
  94. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  95. package/dist-lib/host/websocket-proxy.cjs +1 -1
  96. package/dist-lib/index.cjs +209 -16
  97. package/dist-lib/jump-to-source-babel.cjs +1 -1
  98. package/dist-lib/jump-to-source-native.cjs +1 -1
  99. package/dist-lib/menu.cjs +2 -2
  100. package/dist-lib/menu.mjs +2 -2
  101. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  102. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  103. package/dist-lib/metro-production-bundle.cjs +3 -3
  104. package/dist-lib/metro-production-bundle.mjs +3 -3
  105. package/dist-lib/metro.cjs +8 -8
  106. package/dist-lib/profiles.cjs +1 -1
  107. package/dist-lib/public-brand.cjs +2 -2
  108. package/dist-lib/react-native-host-modules.cjs +1 -1
  109. package/dist-lib/react-native-host-modules.mjs +1 -1
  110. package/dist-lib/render-mode.cjs +1 -1
  111. package/dist-lib/scripts/dev-server-scanner.cjs +31 -15
  112. package/dist-lib/sdk.cjs +3 -2
  113. package/dist-lib/sdk.mjs +3 -2
  114. package/dist-lib/skills.cjs +362 -163
  115. package/dist-lib/swift-submit.cjs +1 -1
  116. package/dist-lib/swift-submit.mjs +1 -1
  117. package/dist-lib/swift.cjs +583 -16
  118. package/dist-lib/vite.cjs +29 -14
  119. package/package.json +9 -9
  120. package/scripts/dev-server-scanner.ts +41 -14
  121. package/scripts/optional-demo-registry.ts +3 -3
  122. package/skills/contrast/SKILL.md +9 -9
  123. package/skills/rnx-debug/SKILL.md +14 -4
  124. package/skills/rnx-perf/SKILL.md +5 -5
  125. package/skills/rnx-setup/SKILL.md +11 -11
  126. package/skills/rnx-test/SKILL.md +11 -11
  127. package/skills/rnx-visual/SKILL.md +6 -6
  128. package/src/agent-sessions.ts +3 -3
  129. package/src/attached-projects.ts +1 -1
  130. package/src/bridge-contract-input.ts +1 -1
  131. package/src/bridge-contract.ts +23 -5
  132. package/src/capture-contract.ts +145 -3
  133. package/src/config.ts +2 -2
  134. package/src/connect.ts +2 -2
  135. package/src/home-paths.ts +3 -3
  136. package/src/host/bridge-host.ts +2 -2
  137. package/src/host/fetch-proxy-handler.ts +4 -3
  138. package/src/host/fetch-proxy-overrides.ts +41 -0
  139. package/src/host/plane-host.ts +2 -2
  140. package/src/index.ts +3 -0
  141. package/src/metro-plugin.ts +4 -4
  142. package/src/metro-production-bundle.ts +2 -2
  143. package/src/native-seam-manifest.ts +6 -6
  144. package/src/public-brand.ts +1 -1
  145. package/src/rolldown-plugin-swift.ts +8 -5
  146. package/src/runtime-assets.ts +8 -6
  147. package/src/screenshots/frame-compose.ts +24 -56
  148. package/src/screenshots/org-deck.ts +1 -1
  149. package/src/screenshots/registry.ts +4 -4
  150. package/src/screenshots/schema.ts +1 -1
  151. package/src/sdk.ts +2 -2
  152. package/src/settings-bundle.ts +1 -1
  153. package/src/sim-client.ts +2 -4
  154. package/src/skills/builtin/compat-check.ts +1 -1
  155. package/src/vite-plugin-one.ts +1 -1
  156. package/src/vite-plugin-swift.ts +11 -6
  157. package/src/vite-plugin.ts +30 -17
  158. package/src/worklets-babel.ts +2 -2
@@ -4,6 +4,7 @@
4
4
  // (this machine, a local box, or the `rnx remote` namespace). this file resolves
5
5
  // the device and hands the rest to the normal open path.
6
6
 
7
+ import { createHash } from 'node:crypto'
7
8
  import {
8
9
  DEFAULT_DEVICE_BY_PLATFORM,
9
10
  devices,
@@ -11,9 +12,10 @@ import {
11
12
  listSelectableDeviceModels,
12
13
  type DeviceModel,
13
14
  type RuntimePlatform,
14
- } from 'sootsim-engine/settings'
15
- import { settingsStore } from 'sootsim-engine/settings/store'
15
+ } from 'peach-engine/settings'
16
+ import { settingsStore } from 'peach-engine/settings/store'
16
17
  import { rnxPublicBrand } from '../../src/public-brand'
18
+ import { UnsupportedRemoteHostError } from '../cloud-client'
17
19
  import { rethrowIfExit } from '../run-rnx'
18
20
  import type { CloudSession } from '../cloud-session'
19
21
 
@@ -27,23 +29,28 @@ function isDeviceModel(value: string): value is DeviceModel {
27
29
  }
28
30
 
29
31
  // flags this command reads for itself rather than treating as the bundle.
30
- const REMOTE_VALUE_FLAGS = new Set(['--device'])
32
+ const REMOTE_VALUE_FLAGS = new Set(['--device', '--name', '--endpoint'])
31
33
 
32
34
  function remoteInputFromArgs(
33
35
  args: string[],
34
36
  platform: RuntimePlatform,
35
37
  ): {
36
38
  bundlePath: string
39
+ name: string | null
37
40
  reuse: boolean
38
41
  fresh: boolean
39
42
  } {
40
43
  const positional: string[] = []
44
+ let name: string | null = null
41
45
  for (let index = 0; index < args.length; index++) {
42
46
  const arg = args[index]
43
- if (arg === '--remote' || arg === '--reuse' || arg === '--new') continue
47
+ if (arg === '--remote' || arg === '--nano' || arg === '--reuse' || arg === '--new') {
48
+ continue
49
+ }
44
50
  if (REMOTE_VALUE_FLAGS.has(arg)) {
45
51
  const value = args[++index] ?? null
46
52
  if (!value) throw new Error(`rnx remote ${platform} ${arg} requires a value`)
53
+ if (arg === '--name') name = value
47
54
  continue
48
55
  }
49
56
  const assigned = arg.match(/^(--[a-z-]+)=(.*)$/)
@@ -51,6 +58,7 @@ function remoteInputFromArgs(
51
58
  const value = assigned[2] ?? ''
52
59
  if (!value)
53
60
  throw new Error(`rnx remote ${platform} ${assigned[1]} requires a value`)
61
+ if (assigned[1] === '--name') name = value
54
62
  continue
55
63
  }
56
64
  if (
@@ -80,7 +88,25 @@ function remoteInputFromArgs(
80
88
  if (reuse && fresh) {
81
89
  throw new Error(`rnx remote ${platform} cannot combine --reuse and --new`)
82
90
  }
83
- return { bundlePath: positional[0], reuse, fresh }
91
+ return { bundlePath: positional[0], name, reuse, fresh }
92
+ }
93
+
94
+ /**
95
+ * the box's name, taken from what was built.
96
+ *
97
+ * a bundle arrives as a file or a URL and neither carries a name, so the last
98
+ * path segment without its extension is the one thing both have. box names are
99
+ * lowercase words joined by dashes, so anything else in it becomes a dash.
100
+ */
101
+ function boxNameForBundle(bundlePath: string): string {
102
+ const segment = bundlePath.split(/[?#]/)[0]?.split('/').filter(Boolean).at(-1) ?? ''
103
+ const stem = segment.replace(/\.[^.]+$/, '')
104
+ const name = stem
105
+ .toLowerCase()
106
+ .replace(/[^a-z0-9]+/g, '-')
107
+ .replace(/^-+|-+$/g, '')
108
+ if (!name) throw new Error(`rnx remote could not name a box after ${bundlePath}`)
109
+ return name
84
110
  }
85
111
 
86
112
  export async function runPlatformCommand(
@@ -129,7 +155,15 @@ export async function runPlatformCommand(
129
155
  }
130
156
 
131
157
  if (args.includes('--remote')) {
158
+ if (platform === 'android' && args.includes('--nano')) {
159
+ const error = new UnsupportedRemoteHostError('android', 'nano')
160
+ console.error(` ${error.message}`)
161
+ return 1
162
+ }
132
163
  try {
164
+ if (!args.includes('--nano')) {
165
+ return await runRemoteBox(platform, args, selectedDevice)
166
+ }
133
167
  return await runRemoteCreate(platform, args, selectedDevice)
134
168
  } catch (error) {
135
169
  rethrowIfExit(error)
@@ -185,6 +219,11 @@ export function runRemotePlatformCommand(
185
219
  args: string[],
186
220
  opts: { port?: number } = {},
187
221
  ): Promise<number | undefined> {
222
+ if (platform === 'android' && args.includes('--nano')) {
223
+ const error = new UnsupportedRemoteHostError('android', 'nano')
224
+ console.error(` ${error.message}`)
225
+ return Promise.resolve(1)
226
+ }
188
227
  return runPlatformCommand(platform, ['--remote', ...args], opts)
189
228
  }
190
229
 
@@ -207,6 +246,7 @@ async function runRemoteCreate(
207
246
  { authHeaderOrExit, cloudAccountIdOrExit },
208
247
  {
209
248
  claimCloudSimulator,
249
+ closeCloudBox,
210
250
  closeCloudSession,
211
251
  createRemoteSim,
212
252
  getRemoteSim,
@@ -232,7 +272,7 @@ async function runRemoteCreate(
232
272
 
233
273
  const existingSession = readCloudSession()
234
274
  if (
235
- existingSession &&
275
+ existingSession?.service === 'sim' &&
236
276
  !input.fresh &&
237
277
  existingSession.platform === platform &&
238
278
  existingSession.artifact?.sha256 === artifact.sha256
@@ -265,7 +305,8 @@ async function runRemoteCreate(
265
305
 
266
306
  // the new session supersedes the old one, so the shell update channel
267
307
  // carries exactly one update: the shell accepts nothing else.
268
- if (existingSession) await closeCloudSession(existingSession)
308
+ if (existingSession?.service === 'box') await closeCloudBox(existingSession)
309
+ else if (existingSession) await closeCloudSession(existingSession)
269
310
  const created = await createRemoteSim({
270
311
  bundlePath: input.bundlePath,
271
312
  device: selectedDevice,
@@ -310,6 +351,159 @@ async function runRemoteCreate(
310
351
  return openInBrowser(created.session.streamUrl)
311
352
  }
312
353
 
354
+ /**
355
+ * `rnx ios --remote` and `rnx android --remote` — the app runs in a micro box.
356
+ *
357
+ * the bundle is prepared by the box plane's own producer, the one `rnx box
358
+ * create --bundle` uses: assets embedded, nothing minified and no module
359
+ * identity rewritten. the nano producer's artifact is built for the nano
360
+ * runner, which imports it as a module; a box page evaluates the bytes with
361
+ * `(0, eval)` as Script in global scope, and a minified artifact reaches it
362
+ * with no react instance for the reconciler to bind to. there is no size cap
363
+ * either way: the box holds the bundle in parts, so the single-message ceiling
364
+ * a nano upload answers to does not apply.
365
+ *
366
+ * a box created from the already-built app boots it in its own page, and this
367
+ * opens the bare shell watch url minted from the box's display grant — the same
368
+ * /sootsim/#remoteEngine fragment the nano service mints, pointed at the box.
369
+ */
370
+ async function runRemoteBox(
371
+ platform: RuntimePlatform,
372
+ args: string[],
373
+ selectedDevice: string,
374
+ ): Promise<number> {
375
+ const command = `${platform} --remote`
376
+ const input = remoteInputFromArgs(args, platform)
377
+ const [
378
+ { closeCloudBox, closeCloudSession, produceCloudBoxArtifact, requestBoxWatchUrl },
379
+ box,
380
+ { cloudBoxConnectUrl, ensureCloudBoxBrowser, readCloudBoxSession },
381
+ { authHeaderOrExit, cloudAccountIdOrExit },
382
+ {
383
+ createCloudBoxSession,
384
+ publishCloudSessionToShell,
385
+ readCloudSession,
386
+ serializeCloudSession,
387
+ RNX_CLOUD_SESSION_ENV,
388
+ },
389
+ ] = await Promise.all([
390
+ import('../cloud-client'),
391
+ import('./box'),
392
+ import('peach-cloud-box/client'),
393
+ import('../auth'),
394
+ import('../cloud-session'),
395
+ ])
396
+ const { openInBrowser } = box
397
+ const artifact = await produceCloudBoxArtifact(input.bundlePath)
398
+ // the session records which bundle a box already holds, so reattaching can
399
+ // tell the same app from a rebuilt one. the box producer returns no digest
400
+ // of its own, so take it here over the bytes that actually crossed.
401
+ const artifactSha256 = createHash('sha256').update(artifact.bytes).digest('hex')
402
+ const endpoint = box.cloudBoxEndpoint(args, command)
403
+ if (!endpoint) return 1
404
+
405
+ const existingSession = readCloudSession()
406
+ if (
407
+ existingSession?.service === 'box' &&
408
+ !input.fresh &&
409
+ existingSession.apiOrigin === endpoint &&
410
+ existingSession.platform === platform &&
411
+ existingSession.device === selectedDevice &&
412
+ existingSession.artifact?.sha256 === artifactSha256
413
+ ) {
414
+ const live = await readCloudBoxSession({
415
+ endpoint: existingSession.apiOrigin,
416
+ boxId: existingSession.boxId,
417
+ accessToken: existingSession.boxToken,
418
+ })
419
+ if (live.sessionId) {
420
+ // the simulator lives in the box's Browser Run tab, which lapses on its
421
+ // own, so a reconnect restores it before promising commands will answer.
422
+ await ensureCloudBoxBrowser({
423
+ connectUrl: cloudBoxConnectUrl(existingSession.apiOrigin, existingSession.boxId),
424
+ accessToken: existingSession.boxToken,
425
+ })
426
+ // grants are short-lived, so a reconnect mints a fresh one rather than
427
+ // reopening whatever url the create printed.
428
+ const watchUrl = await requestBoxWatchUrl({
429
+ apiOrigin: existingSession.apiOrigin,
430
+ boxId: existingSession.boxId,
431
+ boxToken: existingSession.boxToken,
432
+ })
433
+ console.log(
434
+ ` reconnected to remote simulator: ${existingSession.boxId} (${platform})`,
435
+ )
436
+ console.log(` open ${watchUrl}`)
437
+ console.log(REMOTE_COMMANDS_HELP)
438
+ return openInBrowser(watchUrl)
439
+ }
440
+ }
441
+
442
+ const { auth, header } = authHeaderOrExit(command)
443
+ const accountId = cloudAccountIdOrExit(auth)
444
+
445
+ if (existingSession?.service === 'box') {
446
+ await closeCloudBox(existingSession)
447
+ try {
448
+ publishCloudSessionToShell(null)
449
+ } catch {
450
+ // no shell update channel is required outside an interactive rnx shell
451
+ }
452
+ } else if (existingSession) {
453
+ await closeCloudSession(existingSession)
454
+ }
455
+ const created = await box.createPrebuiltBundleBox({
456
+ bundle: new Uint8Array(artifact.bytes),
457
+ name: input.name ?? boxNameForBundle(input.bundlePath),
458
+ endpoint,
459
+ apiOrigin: box.cloudBoxApiOrigin(args, auth),
460
+ apiKey: header.replace(/^Bearer /, ''),
461
+ accountId,
462
+ })
463
+ // creating a box starts no browser, and only its Browser Run tab hosts the
464
+ // simulator, so without this the viewer opens onto a box nobody is running.
465
+ await ensureCloudBoxBrowser({
466
+ connectUrl: cloudBoxConnectUrl(endpoint, created.id),
467
+ accessToken: created.accessToken ?? '',
468
+ })
469
+ const session = createCloudBoxSession({
470
+ boxId: created.id,
471
+ boxToken: created.accessToken ?? '',
472
+ apiOrigin: endpoint,
473
+ platform,
474
+ device: selectedDevice,
475
+ artifact: {
476
+ sha256: artifactSha256,
477
+ bytes: artifact.bytes.length,
478
+ },
479
+ })
480
+ try {
481
+ publishCloudSessionToShell(session)
482
+ } catch {
483
+ // shell update fd not configured
484
+ }
485
+ process.env[RNX_CLOUD_SESSION_ENV] = serializeCloudSession(session)
486
+
487
+ console.log(` box: ${created.id} (${artifact.bytes.length} bytes)`)
488
+ console.log(` platform: ${platform}`)
489
+ if (selectedDevice) console.log(` device: ${selectedDevice}`)
490
+ console.log(` artifact: sha256:${artifactSha256}`)
491
+ // the dest directory was chosen by resolving this bundle's descriptors
492
+ // against it, so say which one won rather than leaving it invisible.
493
+ if (artifact.assetsDirectory) console.log(` asset dest: ${artifact.assetsDirectory}`)
494
+ for (const warning of artifact.warnings) console.warn(` warning: ${warning}`)
495
+ console.log(REMOTE_COMMANDS_HELP)
496
+ // the session is published before the grant is minted, so a grant that never
497
+ // arrives still leaves the box addressable: re-running this command mints it.
498
+ const watchUrl = await requestBoxWatchUrl({
499
+ apiOrigin: endpoint,
500
+ boxId: created.id,
501
+ boxToken: created.accessToken ?? '',
502
+ })
503
+ console.log(` open ${watchUrl}`)
504
+ return openInBrowser(watchUrl)
505
+ }
506
+
313
507
  /** `rnx remote list`: the simulators this account runs that `rnx remote` made. */
314
508
  export async function runRemoteList(args: string[]): Promise<number> {
315
509
  try {
@@ -381,7 +575,10 @@ export async function runRemoteStop(args: string[]): Promise<number> {
381
575
  }
382
576
  // stopping the shell's own simulator clears the shell with it, so the
383
577
  // update channel is required before anything is deleted.
384
- const descriptor = current?.simId === simId ? requireCloudSessionShellUpdate() : null
578
+ const descriptor =
579
+ current?.service === 'sim' && current.simId === simId
580
+ ? requireCloudSessionShellUpdate()
581
+ : null
385
582
  const { auth, header } = authHeaderOrExit('remote stop')
386
583
  const accountId = cloudAccountIdOrExit(auth)
387
584
  const deleted = await deleteRemoteSim({
@@ -1,9 +1,9 @@
1
1
  import { createHash } from 'node:crypto'
2
- import { brotliBundle } from 'sootsim-engine/preview/compress-node'
2
+ import { brotliBundle } from 'peach-engine/preview/compress-node'
3
3
  import {
4
4
  runPresignedUpload,
5
5
  type InitRequestBody,
6
- } from 'sootsim-engine/preview/presigned-upload'
6
+ } from 'peach-engine/preview/presigned-upload'
7
7
  import { authHeaderValue, cloudAccountIdOrExit, resolveCliAuth } from '../auth'
8
8
  import { producePreviewArtifact } from '../cloud-client'
9
9
  import { openUrl } from '../open-url'
@@ -37,7 +37,7 @@ type OutputFormat = 'webm' | 'mp4' | 'gif' | 'png'
37
37
  // recorder bridge (current CLI default). 'live' and 'combined' route
38
38
  // through the recording store so they capture pointer events (and, for
39
39
  // combined, video) and upload to /preview/<id>. mirrors RecordingMode in
40
- // packages/sootsim-engine/src/recording/recordingStore.ts.
40
+ // packages/peach-engine/src/recording/recordingStore.ts.
41
41
  type RecordMode = 'video' | 'live' | 'combined'
42
42
 
43
43
  // how long to wait for the live/combined upload to settle after stop. dev
@@ -180,7 +180,7 @@ function readRepoScope(args: string[]): RepoScope {
180
180
 
181
181
  export async function runRecord(args: string[], opts: RecordOptions) {
182
182
  // note: `--help` / `-h` never reach here — bin.ts intercepts them and
183
- // renders the registry-driven help page (packages/rnx-skills meta.ts).
183
+ // renders the registry-driven help page (packages/peach-skills meta.ts).
184
184
 
185
185
  const sub = findRecordSubcommand(args)
186
186
  if (sub) {
@@ -6,7 +6,7 @@ import { getCliVersion } from '../../src/cli-version'
6
6
  import { readActiveRuntime } from '../../src/home-paths'
7
7
  import { authHeaderValue, resolveCliAuth } from '../auth'
8
8
  import { confirm } from '../prompt'
9
- import type { ScanResult } from '@sootsim/compat/web'
9
+ import type { ScanResult } from '@peach/compat/web'
10
10
 
11
11
  const DEFAULT_REPORT_ORIGIN = 'https://contrast.dev'
12
12
  const MAX_DESCRIPTION_LENGTH = 8_000
@@ -154,7 +154,7 @@ export async function createReportIssuePayload(
154
154
  ): Promise<ReportIssuePayload> {
155
155
  const manifest = readManifest(options.appDir)
156
156
  const compatibility = manifest
157
- ? (await import('@sootsim/compat/web')).scanDeps(manifest)
157
+ ? (await import('@peach/compat/web')).scanDeps(manifest)
158
158
  : null
159
159
  const cliVersion = getCliVersion()
160
160
  const runtimeVersion = readActiveRuntime()
@@ -9,7 +9,7 @@
9
9
 
10
10
  import { mkdirSync, writeFileSync } from 'fs'
11
11
  import { resolve } from 'path'
12
- import { devices } from 'sootsim-engine/settings'
12
+ import { devices } from 'peach-engine/settings'
13
13
  import { buildResolveRectEval, type SampleRect } from '../browser-evals'
14
14
  import { rnxExit } from '../run-rnx'
15
15
  import { callInBridge, createBridgeFromParsed, parseBridgeCliArgs } from '../ws-bridge'
@@ -8,7 +8,7 @@
8
8
 
9
9
  import { mkdirSync, writeFileSync } from 'fs'
10
10
  import { dirname, resolve } from 'path'
11
- import { devices, type DeviceModel } from 'sootsim-engine/settings'
11
+ import { devices, type DeviceModel } from 'peach-engine/settings'
12
12
  import { launchReapedChrome } from '../../../../scripts/lib/reap-browser'
13
13
  import { DEFAULT_SOOTSIM_BRIDGE_PORT } from '../../src/bridge-constants'
14
14
  import { composeFramedScreenshot } from '../../src/screenshots/frame-compose'
@@ -361,7 +361,7 @@ async function decideRepository(
361
361
  if (options.yes || options.ci || !process.stdin.isTTY) return false
362
362
  printPromptBlock('Share rnx with your team', [
363
363
  'rnx already works here with no project setup.',
364
- 'This only adds an exact rnxsim dev dependency and an rnx script for teammates.',
364
+ 'This only adds an exact peachsim dev dependency and an rnx script for teammates.',
365
365
  ])
366
366
  return confirm(`Add rnx to ${path.basename(plan.appDir)}?`, false)
367
367
  }
@@ -392,7 +392,7 @@ rnx setup - configure optional local conveniences
392
392
 
393
393
  rnx works without project setup. This command can enable the faster background
394
394
  service, choose Browser or Desktop, configure private diagnostics, and optionally
395
- add an exact rnxsim dependency plus an rnx script for teammates.
395
+ add an exact peachsim dependency plus an rnx script for teammates.
396
396
 
397
397
  usage:
398
398
  rnx setup