peachsim 0.1.578 → 0.1.579

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 (178) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +11 -9
  3. package/cli/app-catalog.ts +77 -0
  4. package/cli/app-fonts.ts +4 -20
  5. package/cli/app-splash.ts +2 -18
  6. package/cli/bridge-flow-runner.ts +505 -139
  7. package/cli/cloud-client.ts +1 -4
  8. package/cli/cloud-session.ts +1 -4
  9. package/cli/cloud-test-result-files.ts +3 -0
  10. package/cli/cloud-test-tunnel.ts +2 -5
  11. package/cli/command-registry.ts +2 -0
  12. package/cli/commands/agent.ts +149 -23
  13. package/cli/commands/assert.ts +1 -4
  14. package/cli/commands/box/peach-command.ts +62 -0
  15. package/cli/commands/box/plane-share.ts +0 -70
  16. package/cli/commands/box/rnx-command.ts +1 -60
  17. package/cli/commands/box/search-command.ts +14 -0
  18. package/cli/commands/box.ts +2 -2
  19. package/cli/commands/control.ts +121 -27
  20. package/cli/commands/cpu-profile.ts +23 -10
  21. package/cli/commands/daemon.ts +1 -9
  22. package/cli/commands/detox.ts +26 -18
  23. package/cli/commands/device.ts +129 -1
  24. package/cli/commands/film.ts +25 -16
  25. package/cli/commands/flow.ts +9 -2
  26. package/cli/commands/inspect/actions.ts +75 -1
  27. package/cli/commands/inspect/core.ts +81 -2
  28. package/cli/commands/inspect/describe.ts +2 -6
  29. package/cli/commands/inspect/env.ts +1 -1
  30. package/cli/commands/inspect/settling.ts +20 -3
  31. package/cli/commands/inspect/shared.ts +1 -4
  32. package/cli/commands/inspect/sleep.ts +1 -1
  33. package/cli/commands/inspect.ts +16 -49
  34. package/cli/commands/install-desktop.ts +8 -6
  35. package/cli/commands/login.ts +3 -5
  36. package/cli/commands/maestro-generate.ts +1 -4
  37. package/cli/commands/maestro.ts +38 -21
  38. package/cli/commands/no-bridge-hint.ts +0 -14
  39. package/cli/commands/permissions.ts +2 -2
  40. package/cli/commands/platform.ts +13 -6
  41. package/cli/commands/screenshot.ts +6 -1
  42. package/cli/commands/skills.ts +1 -1
  43. package/cli/commands/test.ts +6 -2
  44. package/cli/commands/three-mode.ts +162 -19
  45. package/cli/commands/upload.ts +3 -18
  46. package/cli/current-sim.ts +0 -1
  47. package/cli/desktop-companion.ts +40 -8
  48. package/cli/drivers/playwright-provisioning.ts +1 -4
  49. package/cli/flow-export.ts +1 -8
  50. package/cli/flow-session.ts +0 -4
  51. package/cli/hints.ts +1 -16
  52. package/cli/inspect-notice-state.ts +0 -4
  53. package/cli/main.ts +2 -4
  54. package/cli/outbound-endpoints.ts +1 -24
  55. package/cli/parse-args.ts +1 -2
  56. package/cli/rnx-in-process.ts +3 -1
  57. package/cli/run-rnx-core.ts +4 -2
  58. package/cli/run-rnx.ts +18 -10
  59. package/cli/send-to-box.ts +1 -4
  60. package/cli/telemetry.ts +1 -1
  61. package/cli/ws-bridge.ts +1 -5
  62. package/detox/gestures.ts +20 -6
  63. package/detox/index.ts +379 -123
  64. package/detox/navigation-lifecycle.ts +22 -13
  65. package/dist-lib/agent-daemon-client.cjs +21 -15
  66. package/dist-lib/agent-events.cjs +1 -1
  67. package/dist-lib/agent-identity.cjs +3 -17
  68. package/dist-lib/agent-sessions.cjs +5 -4
  69. package/dist-lib/attached-projects.cjs +1 -77
  70. package/dist-lib/auth/shared-session.cjs +1 -1
  71. package/dist-lib/backend-origin.cjs +11 -1
  72. package/dist-lib/beta.cjs +1 -1
  73. package/dist-lib/beta.mjs +1 -1
  74. package/dist-lib/bridge-constants.cjs +1 -1
  75. package/dist-lib/bridge-contract-input.cjs +7 -5
  76. package/dist-lib/bridge-contract-input.mjs +7 -5
  77. package/dist-lib/bridge-contract.cjs +1 -1
  78. package/dist-lib/bridge-contract.mjs +1 -1
  79. package/dist-lib/capture-contract.cjs +30 -7
  80. package/dist-lib/capture-contract.mjs +30 -7
  81. package/dist-lib/cli-constants.cjs +1 -1
  82. package/dist-lib/cloud-contract.cjs +1 -1
  83. package/dist-lib/cloud-contract.mjs +1 -1
  84. package/dist-lib/cloud-test-args.cjs +1 -1
  85. package/dist-lib/cloud-test-args.mjs +1 -1
  86. package/dist-lib/cloud.cjs +17 -11
  87. package/dist-lib/cloud.mjs +17 -11
  88. package/dist-lib/config.cjs +1 -1
  89. package/dist-lib/detox/index.cjs +321 -122
  90. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  91. package/dist-lib/home-paths.cjs +1 -1
  92. package/dist-lib/host/bridge-host.cjs +427 -212
  93. package/dist-lib/host/fetch-proxy-handler.cjs +5 -28
  94. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  95. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  96. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  97. package/dist-lib/host/websocket-proxy.cjs +1 -1
  98. package/dist-lib/index.cjs +315 -58
  99. package/dist-lib/jump-to-source-babel.cjs +1 -1
  100. package/dist-lib/jump-to-source-native.cjs +1 -1
  101. package/dist-lib/menu.cjs +67 -31
  102. package/dist-lib/menu.mjs +64 -28
  103. package/dist-lib/metro-fingerprint-registry.cjs +8 -4
  104. package/dist-lib/metro-fingerprint-registry.mjs +6 -4
  105. package/dist-lib/metro-production-bundle.cjs +2 -2
  106. package/dist-lib/metro-production-bundle.mjs +2 -2
  107. package/dist-lib/metro.cjs +8 -4
  108. package/dist-lib/profiles.cjs +1 -1
  109. package/dist-lib/public-brand.cjs +7 -4
  110. package/dist-lib/react-native-host-modules.cjs +1 -1
  111. package/dist-lib/react-native-host-modules.mjs +1 -1
  112. package/dist-lib/render-mode.cjs +3 -13
  113. package/dist-lib/scripts/dev-server-scanner.cjs +5 -17
  114. package/dist-lib/sdk.cjs +129 -10
  115. package/dist-lib/sdk.mjs +127 -10
  116. package/dist-lib/skills.cjs +1635 -1121
  117. package/dist-lib/swift-compile.cjs +277 -70
  118. package/dist-lib/swift-compile.mjs +275 -70
  119. package/dist-lib/swift-package.cjs +17 -5
  120. package/dist-lib/swift-package.mjs +15 -4
  121. package/dist-lib/swift-submit.cjs +32 -8
  122. package/dist-lib/swift-submit.mjs +29 -7
  123. package/dist-lib/swift.cjs +30912 -577
  124. package/dist-lib/vite-kotlin.cjs +356 -0
  125. package/dist-lib/vite-swift.cjs +1743 -0
  126. package/dist-lib/vite.cjs +208 -1039
  127. package/kotlin/README.md +18 -0
  128. package/kotlin/Sources/androidx/annotation/Keep.kt +4 -0
  129. package/kotlin/Sources/dev/onejs/one/OneNativeSourceDispatch.kt +7 -0
  130. package/kotlin/Sources/dev/onejs/one/source/OneModule.kt +4 -0
  131. package/kotlin/Sources/org/json/JSON.kt +244 -0
  132. package/kotlin/toolchain.json +19 -0
  133. package/package.json +14 -2
  134. package/scripts/dev-server-scanner.ts +0 -18
  135. package/scripts/optional-demo-registry.ts +0 -17
  136. package/skills/contrast/SKILL.md +2 -2
  137. package/skills/peach-setup/SKILL.md +16 -0
  138. package/src/agent-daemon-client.ts +36 -22
  139. package/src/agent-identity.ts +0 -15
  140. package/src/agent-prompt.ts +12 -0
  141. package/src/attached-projects.ts +0 -72
  142. package/src/backend-origin.ts +10 -0
  143. package/src/bridge-contract-input.ts +2 -5
  144. package/src/bridge-contract.ts +2 -0
  145. package/src/capture-contract.ts +53 -11
  146. package/src/cloud.ts +4 -9
  147. package/src/dev-server-open.ts +0 -99
  148. package/src/home-paths.ts +2 -3
  149. package/src/host/agent-host.ts +82 -36
  150. package/src/host/bridge-host.ts +5 -11
  151. package/src/host/fetch-proxy-handler.ts +19 -43
  152. package/src/is-record.ts +4 -0
  153. package/src/menu.ts +82 -37
  154. package/src/metro-fingerprint-registry.ts +1 -4
  155. package/src/metro-production-bundle.ts +1 -1
  156. package/src/plist.ts +1 -4
  157. package/src/public-brand.ts +5 -3
  158. package/src/render-mode.ts +0 -12
  159. package/src/runtime-assets.ts +9 -2
  160. package/src/screenshots/compose.ts +7 -1
  161. package/src/screenshots/frame-compose.ts +21 -10
  162. package/src/screenshots/schema.ts +1 -4
  163. package/src/sim-client.ts +2 -4
  164. package/src/skills/builtin/maestro-test.ts +1 -4
  165. package/src/sleep.ts +4 -0
  166. package/src/swift-compile.ts +209 -47
  167. package/src/swift-icu.ts +140 -0
  168. package/src/swift-package.ts +26 -2
  169. package/src/swift-submit.ts +84 -4
  170. package/src/swift.ts +2 -0
  171. package/src/vite-plugin-kotlin.ts +376 -0
  172. package/src/vite-plugin-one.ts +224 -36
  173. package/src/vite-plugin-swift.ts +382 -96
  174. package/src/vite-plugin.ts +121 -134
  175. package/src/vite.d.ts +10 -0
  176. package/cli/resolve-assets.ts +0 -63
  177. package/src/rolldown-plugin-swift.ts +0 -244
  178. package/src/team-machine-prompt.ts +0 -73
@@ -9,6 +9,9 @@ export type SootsimNavigationIdentity = {
9
9
 
10
10
  type SootsimPageState = {
11
11
  bodyText: string
12
+ bootStage: string | null
13
+ bootMarks: unknown[]
14
+ capturedAtEpochMs: number
12
15
  bridges: {
13
16
  sootsim: boolean
14
17
  test: boolean
@@ -205,19 +208,25 @@ async function readSootsimPageState(
205
208
  page: Page,
206
209
  ): Promise<SootsimPageState | { evaluateError: string }> {
207
210
  try {
208
- return await page.evaluate(() => ({
209
- bodyText: document.body?.innerText?.slice(0, 500) ?? '',
210
- bridges: {
211
- sootsim: Boolean(window.SootSim),
212
- test: Boolean(window.__sootsimTest),
213
- },
214
- globals: Object.keys(window)
215
- .filter((key) => key.startsWith('__sootsim') || key === 'SootSim')
216
- .sort(),
217
- readyState: document.readyState,
218
- title: document.title,
219
- url: window.location.href,
220
- }))
211
+ return await page.evaluate(() => {
212
+ const bootMarks = Reflect.get(window, '__sootsimBootMarks')
213
+ return {
214
+ bodyText: document.body?.innerText?.slice(0, 500) ?? '',
215
+ bootStage: document.documentElement.dataset.sootsimBootStage ?? null,
216
+ bootMarks: Array.isArray(bootMarks) ? bootMarks.slice(-16) : [],
217
+ capturedAtEpochMs: Date.now(),
218
+ bridges: {
219
+ sootsim: Boolean(window.SootSim),
220
+ test: Boolean(window.__sootsimTest),
221
+ },
222
+ globals: Object.keys(window)
223
+ .filter((key) => key.startsWith('__sootsim') || key === 'SootSim')
224
+ .sort(),
225
+ readyState: document.readyState,
226
+ title: document.title,
227
+ url: window.location.href,
228
+ }
229
+ })
221
230
  } catch (error) {
222
231
  return {
223
232
  evaluateError: error instanceof Error ? error.message : String(error),
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.578 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.579 | (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;
@@ -54,13 +54,14 @@ var import_node_url = require("node:url");
54
54
 
55
55
  // src/public-brand.ts
56
56
  var name = "Peach";
57
- var rnxPublicBrand = Object.freeze({
57
+ var peachPublicBrand = Object.freeze({
58
58
  name,
59
59
  packageName: "peachsim",
60
60
  commandName: "peach",
61
- domain: "rnxsim.com",
62
- origin: "https://rnxsim.com"
61
+ domain: "peachsim.com",
62
+ origin: "https://peachsim.com"
63
63
  });
64
+ var rnxPublicBrand = peachPublicBrand;
64
65
 
65
66
  // cli/standalone.ts
66
67
  var IS_STANDALONE = typeof __SOOTSIM_STANDALONE__ !== "undefined" && __SOOTSIM_STANDALONE__;
@@ -294,13 +295,18 @@ var AgentDaemonClient = class {
294
295
  prompt
295
296
  });
296
297
  }
297
- async sendClaimedPrompt(simId, prompt) {
298
+ async listenForInspect(simId) {
299
+ return this.send("agent:listen-inspect", { simId });
300
+ }
301
+ async getInspectListenerStatus(simId) {
302
+ return this.send("agent:get-inspect-listener-status", {
303
+ simId
304
+ });
305
+ }
306
+ async sendInspectMessage(simId, prompt) {
298
307
  return this.send(
299
- "agent:send-claimed-prompt",
300
- {
301
- simId,
302
- prompt
303
- }
308
+ "agent:send-inspect-message",
309
+ { simId, prompt }
304
310
  );
305
311
  }
306
312
  async endSession(sessionId) {
@@ -352,7 +358,7 @@ var AgentDaemonClient = class {
352
358
  }
353
359
  const id = this.nextId++;
354
360
  return new Promise((resolve, reject) => {
355
- const timer = setTimeout(() => {
361
+ const timer = this.commandTimeoutMs > 0 ? setTimeout(() => {
356
362
  this.pending.delete(id);
357
363
  reject(
358
364
  new AgentDaemonError(
@@ -360,7 +366,7 @@ var AgentDaemonClient = class {
360
366
  "TIMEOUT"
361
367
  )
362
368
  );
363
- }, this.commandTimeoutMs);
369
+ }, this.commandTimeoutMs) : null;
364
370
  this.pending.set(id, {
365
371
  resolve,
366
372
  reject,
@@ -369,7 +375,7 @@ var AgentDaemonClient = class {
369
375
  try {
370
376
  this.ws.send(JSON.stringify({ id, type, ...payload }));
371
377
  } catch (err) {
372
- clearTimeout(timer);
378
+ if (timer) clearTimeout(timer);
373
379
  this.pending.delete(id);
374
380
  reject(err instanceof Error ? err : new Error(String(err)));
375
381
  }
@@ -405,7 +411,7 @@ var AgentDaemonClient = class {
405
411
  const entry = this.pending.get(msg.id);
406
412
  if (!entry) return;
407
413
  this.pending.delete(msg.id);
408
- clearTimeout(entry.timer);
414
+ if (entry.timer) clearTimeout(entry.timer);
409
415
  if (msg.error) {
410
416
  entry.reject(new AgentDaemonError(msg.error, msg.code));
411
417
  } else {
@@ -416,7 +422,7 @@ var AgentDaemonClient = class {
416
422
  if (this.closed) return;
417
423
  this.closed = true;
418
424
  for (const [, entry] of this.pending) {
419
- clearTimeout(entry.timer);
425
+ if (entry.timer) clearTimeout(entry.timer);
420
426
  entry.reject(new AgentDaemonError("daemon disconnected", "DISCONNECT"));
421
427
  }
422
428
  this.pending.clear();
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.578 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.579 | (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.578 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.579 | (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;
@@ -22,12 +22,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
22
22
  // src/agent-identity.ts
23
23
  var agent_identity_exports = {};
24
24
  __export(agent_identity_exports, {
25
- agentSessionIdFromCliIdentity: () => agentSessionIdFromCliIdentity,
26
- isValidTeamMachineSessionId: () => isValidTeamMachineSessionId,
27
- teamMachineSessionIdFromCliIdentity: () => teamMachineSessionIdFromCliIdentity
25
+ agentSessionIdFromCliIdentity: () => agentSessionIdFromCliIdentity
28
26
  });
29
27
  module.exports = __toCommonJS(agent_identity_exports);
30
- var TEAM_MACHINE_SESSION_RE = /^[A-Za-z0-9._:-]{1,160}$/;
31
28
  function agentSessionIdFromCliIdentity(identity) {
32
29
  if (!identity) return null;
33
30
  const colon = identity.indexOf(":");
@@ -36,18 +33,7 @@ function agentSessionIdFromCliIdentity(identity) {
36
33
  const value = identity.slice(colon + 1).trim();
37
34
  return source === "PEACH_CLI_IDENTITY" && value ? value : null;
38
35
  }
39
- function teamMachineSessionIdFromCliIdentity(identity) {
40
- if (!identity?.startsWith("TM_SESSION:")) return null;
41
- const sessionId = identity.slice("TM_SESSION:".length).trim();
42
- if (!TEAM_MACHINE_SESSION_RE.test(sessionId)) return null;
43
- return sessionId;
44
- }
45
- function isValidTeamMachineSessionId(sessionId) {
46
- return TEAM_MACHINE_SESSION_RE.test(sessionId);
47
- }
48
36
  // Annotate the CommonJS export names for ESM import in node:
49
37
  0 && (module.exports = {
50
- agentSessionIdFromCliIdentity,
51
- isValidTeamMachineSessionId,
52
- teamMachineSessionIdFromCliIdentity
38
+ agentSessionIdFromCliIdentity
53
39
  });
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.578 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.579 | (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;
@@ -59,13 +59,14 @@ var import_node_url = require("node:url");
59
59
 
60
60
  // src/public-brand.ts
61
61
  var name = "Peach";
62
- var rnxPublicBrand = Object.freeze({
62
+ var peachPublicBrand = Object.freeze({
63
63
  name,
64
64
  packageName: "peachsim",
65
65
  commandName: "peach",
66
- domain: "rnxsim.com",
67
- origin: "https://rnxsim.com"
66
+ domain: "peachsim.com",
67
+ origin: "https://peachsim.com"
68
68
  });
69
+ var rnxPublicBrand = peachPublicBrand;
69
70
 
70
71
  // cli/standalone.ts
71
72
  var IS_STANDALONE = typeof __SOOTSIM_STANDALONE__ !== "undefined" && __SOOTSIM_STANDALONE__;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.578 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.579 | (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;
@@ -35,7 +35,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
35
35
  // scripts/optional-demo-registry.ts
36
36
  var optional_demo_registry_exports = {};
37
37
  __export(optional_demo_registry_exports, {
38
- __withOptionalDemoAppsForTests: () => __withOptionalDemoAppsForTests,
39
38
  findInternalDemoRegistry: () => findInternalDemoRegistry,
40
39
  loadOptionalDemoApps: () => loadOptionalDemoApps,
41
40
  optionalDemoAppsSync: () => optionalDemoAppsSync
@@ -73,15 +72,6 @@ async function loadOptionalDemoApps() {
73
72
  function optionalDemoAppsSync() {
74
73
  return cached ?? [];
75
74
  }
76
- function __withOptionalDemoAppsForTests(apps) {
77
- const previous = cached;
78
- cached = apps;
79
- return {
80
- restore: () => {
81
- cached = previous;
82
- }
83
- };
84
- }
85
75
  var import_node_fs, import_node_path2, import_node_url, REGISTRY_REPO_PATH, MAX_ANCESTOR_STEPS, cached;
86
76
  var init_optional_demo_registry = __esm({
87
77
  "scripts/optional-demo-registry.ts"() {
@@ -98,18 +88,14 @@ var init_optional_demo_registry = __esm({
98
88
  // src/attached-projects.ts
99
89
  var attached_projects_exports = {};
100
90
  __export(attached_projects_exports, {
101
- __setUserDataDirForTests: () => __setUserDataDirForTests,
102
91
  applySessionStatusPatch: () => applySessionStatusPatch,
103
92
  costThisWeek: () => costThisWeek,
104
93
  deletePreviewAttachment: () => deletePreviewAttachment,
105
94
  deleteProject: () => deleteProject,
106
95
  deleteSession: () => deleteSession,
107
- findProjectByBundleUrl: () => findProjectByBundleUrl,
108
- findProjectByCwd: () => findProjectByCwd,
109
96
  findProjectById: () => findProjectById,
110
97
  findSessionById: () => findSessionById,
111
98
  getUserDataDir: () => getUserDataDir,
112
- listPreviewAttachments: () => listPreviewAttachments,
113
99
  listProjects: () => listProjects,
114
100
  listSessions: () => listSessions,
115
101
  loadStore: () => loadStore,
@@ -120,7 +106,6 @@ __export(attached_projects_exports, {
120
106
  setUserDataDir: () => setUserDataDir,
121
107
  updateSessionStatus: () => updateSessionStatus,
122
108
  updateSessionStatuses: () => updateSessionStatuses,
123
- upsertPreviewAttachment: () => upsertPreviewAttachment,
124
109
  upsertProject: () => upsertProject,
125
110
  upsertSession: () => upsertSession
126
111
  });
@@ -151,7 +136,6 @@ var overrideDir = null;
151
136
  function setUserDataDir(dir) {
152
137
  overrideDir = dir;
153
138
  }
154
- var __setUserDataDirForTests = setUserDataDir;
155
139
  function userDataDir() {
156
140
  if (overrideDir) return overrideDir;
157
141
  const fromEnv = process.env.SOOTSIM_USER_DATA_DIR;
@@ -227,9 +211,6 @@ function projectIdForCwd(cwd) {
227
211
  function newSessionId() {
228
212
  return `s_${(0, import_node_crypto.randomBytes)(10).toString("hex")}`;
229
213
  }
230
- function newPreviewId() {
231
- return `pa_${(0, import_node_crypto.randomBytes)(10).toString("hex")}`;
232
- }
233
214
  function upsertProject(input) {
234
215
  const cwd = import_node_path3.default.resolve(input.cwd);
235
216
  const id = projectIdForCwd(cwd);
@@ -283,23 +264,6 @@ function upsertProject(input) {
283
264
  function findProjectById(id) {
284
265
  return loadStore().attachedProjects.find((p) => p.id === id) ?? null;
285
266
  }
286
- function findProjectByCwd(cwd) {
287
- const resolved = import_node_path3.default.resolve(cwd);
288
- return loadStore().attachedProjects.find((p) => p.cwd === resolved) ?? null;
289
- }
290
- function findProjectByBundleUrl(bundleUrl) {
291
- const store = loadStore();
292
- const exact = store.attachedProjects.find((p) => p.knownBundleUrls.includes(bundleUrl));
293
- if (exact) return exact;
294
- const base = stripQuery(bundleUrl);
295
- return store.attachedProjects.find(
296
- (p) => p.knownBundleUrls.some((u) => stripQuery(u) === base)
297
- ) ?? null;
298
- }
299
- function stripQuery(url) {
300
- const q = url.indexOf("?");
301
- return q >= 0 ? url.slice(0, q) : url;
302
- }
303
267
  function listProjects() {
304
268
  return loadStore().attachedProjects;
305
269
  }
@@ -426,41 +390,6 @@ function deleteSession(id) {
426
390
  store.agentSessions = store.agentSessions.filter((s) => s.id !== id);
427
391
  });
428
392
  }
429
- function upsertPreviewAttachment(input) {
430
- let result;
431
- mutateStore((store) => {
432
- const existing = store.previewAttachments.find(
433
- (pa) => pa.bundleUrl === input.bundleUrl && pa.simId === input.simId
434
- );
435
- if (existing) {
436
- const merged = {
437
- ...existing,
438
- ...input,
439
- lastSeenAt: Date.now()
440
- };
441
- const idx = store.previewAttachments.indexOf(existing);
442
- store.previewAttachments[idx] = merged;
443
- result = merged;
444
- return;
445
- }
446
- const created = {
447
- id: input.id ?? newPreviewId(),
448
- projectId: input.projectId ?? null,
449
- bundleUrl: input.bundleUrl,
450
- simId: input.simId,
451
- deviceModel: input.deviceModel ?? "unknown",
452
- status: input.status ?? "connecting",
453
- lastSeenAt: Date.now()
454
- };
455
- store.previewAttachments.push(created);
456
- result = created;
457
- });
458
- return result;
459
- }
460
- function listPreviewAttachments(projectId) {
461
- const all = loadStore().previewAttachments;
462
- return projectId ? all.filter((pa) => pa.projectId === projectId) : all;
463
- }
464
393
  function deletePreviewAttachment(id) {
465
394
  mutateStore((store) => {
466
395
  store.previewAttachments = store.previewAttachments.filter((pa) => pa.id !== id);
@@ -498,18 +427,14 @@ async function seedFromDemoAppRegistry() {
498
427
  }
499
428
  // Annotate the CommonJS export names for ESM import in node:
500
429
  0 && (module.exports = {
501
- __setUserDataDirForTests,
502
430
  applySessionStatusPatch,
503
431
  costThisWeek,
504
432
  deletePreviewAttachment,
505
433
  deleteProject,
506
434
  deleteSession,
507
- findProjectByBundleUrl,
508
- findProjectByCwd,
509
435
  findProjectById,
510
436
  findSessionById,
511
437
  getUserDataDir,
512
- listPreviewAttachments,
513
438
  listProjects,
514
439
  listSessions,
515
440
  loadStore,
@@ -520,7 +445,6 @@ async function seedFromDemoAppRegistry() {
520
445
  setUserDataDir,
521
446
  updateSessionStatus,
522
447
  updateSessionStatuses,
523
- upsertPreviewAttachment,
524
448
  upsertProject,
525
449
  upsertSession
526
450
  });
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.578 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.579 | (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.578 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.579 | (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;
@@ -29,6 +29,7 @@ __export(backend_origin_exports, {
29
29
  isContrastBackendHost: () => isContrastBackendHost,
30
30
  isContrastBackendOrigin: () => isContrastBackendOrigin,
31
31
  isLoopbackHost: () => isLoopbackHost,
32
+ loopbackOriginOf: () => loopbackOriginOf,
32
33
  normalizeHostname: () => normalizeHostname,
33
34
  resolveContrastBackendOrigin: () => resolveContrastBackendOrigin
34
35
  });
@@ -47,6 +48,14 @@ function isLoopbackHost(hostname) {
47
48
  const normalized = normalizeHostname(hostname);
48
49
  return normalized === "localhost" || normalized.endsWith(".localhost") || normalized === "0.0.0.0" || normalized === "::1" || /^127(?:\.\d{1,3}){3}$/.test(normalized);
49
50
  }
51
+ function loopbackOriginOf(value) {
52
+ try {
53
+ const url = new URL(value);
54
+ return isLoopbackHost(url.hostname) ? url.origin : null;
55
+ } catch {
56
+ return null;
57
+ }
58
+ }
50
59
  function buildBrowserAssetProxyUrl(targetUrl) {
51
60
  const proxyPath = isLoopbackHost(new URL(targetUrl).hostname) ? "/__bundle-proxy" : "/__fetch-proxy";
52
61
  return `${proxyPath}?url=${encodeURIComponent(targetUrl)}`;
@@ -83,6 +92,7 @@ function resolveContrastBackendOrigin(currentOrigin) {
83
92
  isContrastBackendHost,
84
93
  isContrastBackendOrigin,
85
94
  isLoopbackHost,
95
+ loopbackOriginOf,
86
96
  normalizeHostname,
87
97
  resolveContrastBackendOrigin
88
98
  });
package/dist-lib/beta.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.578 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.579 | (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.578 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.579 | (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.578 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.579 | (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.578 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.579 | (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;
@@ -39,6 +39,11 @@ module.exports = __toCommonJS(bridge_contract_input_exports);
39
39
  // src/bridge-contract.ts
40
40
  var SIM_LONG_PRESS_MAX_MS = 5e3;
41
41
 
42
+ // src/is-record.ts
43
+ function isRecord(value) {
44
+ return typeof value === "object" && value !== null && !Array.isArray(value);
45
+ }
46
+
42
47
  // src/bridge-contract-input.ts
43
48
  var BridgeInputError = class extends Error {
44
49
  constructor(message) {
@@ -50,11 +55,8 @@ var SEMANTIC_WAIT_MAX_TIMEOUT_MS = 3e4;
50
55
  function validationFailure(path, expectation) {
51
56
  throw new BridgeInputError(`${path} ${expectation}`);
52
57
  }
53
- function isRecordValue(value) {
54
- return value !== null && typeof value === "object" && !Array.isArray(value);
55
- }
56
58
  function recordValue(value, path) {
57
- if (!isRecordValue(value)) {
59
+ if (!isRecord(value)) {
58
60
  validationFailure(path, "must be an object");
59
61
  }
60
62
  return value;
@@ -1,8 +1,13 @@
1
- /*! rnx v0.1.578 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.579 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var SIM_LONG_PRESS_MAX_MS = 5e3;
5
5
 
6
+ // src/is-record.ts
7
+ function isRecord(value) {
8
+ return typeof value === "object" && value !== null && !Array.isArray(value);
9
+ }
10
+
6
11
  // src/bridge-contract-input.ts
7
12
  var BridgeInputError = class extends Error {
8
13
  constructor(message) {
@@ -14,11 +19,8 @@ var SEMANTIC_WAIT_MAX_TIMEOUT_MS = 3e4;
14
19
  function validationFailure(path, expectation) {
15
20
  throw new BridgeInputError(`${path} ${expectation}`);
16
21
  }
17
- function isRecordValue(value) {
18
- return value !== null && typeof value === "object" && !Array.isArray(value);
19
- }
20
22
  function recordValue(value, path) {
21
- if (!isRecordValue(value)) {
23
+ if (!isRecord(value)) {
22
24
  validationFailure(path, "must be an object");
23
25
  }
24
26
  return value;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.578 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.579 | (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.578 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.579 | (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.578 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.579 | (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;
@@ -83,27 +83,26 @@ function rnxRasterFrames(tree, nodeIds) {
83
83
  width: node.layout.width,
84
84
  height: node.layout.height
85
85
  };
86
- const liquidGlass = node.style._liquidGlass;
87
- const capturePadding = liquidGlass && typeof liquidGlass === "object" && typeof Reflect.get(liquidGlass, "capturePadding") === "number" ? Reflect.get(liquidGlass, "capturePadding") : 0;
86
+ const glassOutset = liquidGlassPaintOutset(node.style._liquidGlass, frame);
88
87
  const shadowRadius = typeof node.style.shadowRadius === "number" ? node.style.shadowRadius : 0;
89
88
  const shadowOffset = node.style.shadowOffset;
90
89
  const shadowOffsetX = shadowOffset && typeof shadowOffset === "object" && typeof Reflect.get(shadowOffset, "width") === "number" ? Reflect.get(shadowOffset, "width") : 0;
91
90
  const shadowOffsetY = shadowOffset && typeof shadowOffset === "object" && typeof Reflect.get(shadowOffset, "height") === "number" ? Reflect.get(shadowOffset, "height") : 0;
92
91
  const left = Math.max(
93
92
  0,
94
- frame.x - Math.max(capturePadding, shadowRadius - shadowOffsetX)
93
+ frame.x - Math.max(glassOutset.x, shadowRadius - shadowOffsetX, 0)
95
94
  );
96
95
  const top = Math.max(
97
96
  0,
98
- frame.y - Math.max(capturePadding, shadowRadius - shadowOffsetY)
97
+ frame.y - Math.max(glassOutset.top, shadowRadius - shadowOffsetY, 0)
99
98
  );
100
99
  const right = Math.min(
101
100
  tree.width,
102
- frame.x + frame.width + Math.max(capturePadding, shadowRadius + shadowOffsetX)
101
+ frame.x + frame.width + Math.max(glassOutset.x, shadowRadius + shadowOffsetX, 0)
103
102
  );
104
103
  const bottom = Math.min(
105
104
  tree.height,
106
- frame.y + frame.height + Math.max(capturePadding, shadowRadius + shadowOffsetY)
105
+ frame.y + frame.height + Math.max(glassOutset.bottom, shadowRadius + shadowOffsetY, 0)
107
106
  );
108
107
  if (right > left && bottom > top) {
109
108
  frames.set(node.nodeId, {
@@ -116,6 +115,30 @@ function rnxRasterFrames(tree, nodeIds) {
116
115
  }
117
116
  return frames;
118
117
  }
118
+ function liquidGlassPaintOutset(glass, frame) {
119
+ const outset = { x: 0, top: 0, bottom: 0 };
120
+ if (!glass || typeof glass !== "object") return outset;
121
+ const contour = Reflect.get(glass, "contour");
122
+ const shadows = [
123
+ Reflect.get(glass, "shadow"),
124
+ Math.min(frame.width, frame.height) > 62 ? Reflect.get(glass, "tallShadow") : null,
125
+ ...Array.isArray(contour) ? contour : []
126
+ ];
127
+ for (const shadow of shadows) {
128
+ if (!shadow || typeof shadow !== "object") continue;
129
+ const sigma = Reflect.get(shadow, "sigma");
130
+ if (typeof sigma !== "number") continue;
131
+ const offsetY = Reflect.get(shadow, "offsetY");
132
+ const spread = Reflect.get(shadow, "spread");
133
+ const [spreadX, spreadY] = typeof spread === "number" ? [spread, spread] : Array.isArray(spread) && typeof spread[0] === "number" && typeof spread[1] === "number" ? [spread[0], spread[1]] : [0, 0];
134
+ const dy = typeof offsetY === "number" ? offsetY : 0;
135
+ const blur = sigma * 3;
136
+ outset.x = Math.max(outset.x, spreadX + blur);
137
+ outset.top = Math.max(outset.top, spreadY + blur - dy);
138
+ outset.bottom = Math.max(outset.bottom, spreadY + blur + dy);
139
+ }
140
+ return outset;
141
+ }
119
142
  function rnxCaptureRasterRegions(capture) {
120
143
  const tree = {
121
144
  width: capture.tree.viewport.width,
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.578 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.579 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/capture-contract.ts
4
4
  var RNX_SCREEN_CAPTURE_VERSION = 1;
@@ -53,27 +53,26 @@ function rnxRasterFrames(tree, nodeIds) {
53
53
  width: node.layout.width,
54
54
  height: node.layout.height
55
55
  };
56
- const liquidGlass = node.style._liquidGlass;
57
- const capturePadding = liquidGlass && typeof liquidGlass === "object" && typeof Reflect.get(liquidGlass, "capturePadding") === "number" ? Reflect.get(liquidGlass, "capturePadding") : 0;
56
+ const glassOutset = liquidGlassPaintOutset(node.style._liquidGlass, frame);
58
57
  const shadowRadius = typeof node.style.shadowRadius === "number" ? node.style.shadowRadius : 0;
59
58
  const shadowOffset = node.style.shadowOffset;
60
59
  const shadowOffsetX = shadowOffset && typeof shadowOffset === "object" && typeof Reflect.get(shadowOffset, "width") === "number" ? Reflect.get(shadowOffset, "width") : 0;
61
60
  const shadowOffsetY = shadowOffset && typeof shadowOffset === "object" && typeof Reflect.get(shadowOffset, "height") === "number" ? Reflect.get(shadowOffset, "height") : 0;
62
61
  const left = Math.max(
63
62
  0,
64
- frame.x - Math.max(capturePadding, shadowRadius - shadowOffsetX)
63
+ frame.x - Math.max(glassOutset.x, shadowRadius - shadowOffsetX, 0)
65
64
  );
66
65
  const top = Math.max(
67
66
  0,
68
- frame.y - Math.max(capturePadding, shadowRadius - shadowOffsetY)
67
+ frame.y - Math.max(glassOutset.top, shadowRadius - shadowOffsetY, 0)
69
68
  );
70
69
  const right = Math.min(
71
70
  tree.width,
72
- frame.x + frame.width + Math.max(capturePadding, shadowRadius + shadowOffsetX)
71
+ frame.x + frame.width + Math.max(glassOutset.x, shadowRadius + shadowOffsetX, 0)
73
72
  );
74
73
  const bottom = Math.min(
75
74
  tree.height,
76
- frame.y + frame.height + Math.max(capturePadding, shadowRadius + shadowOffsetY)
75
+ frame.y + frame.height + Math.max(glassOutset.bottom, shadowRadius + shadowOffsetY, 0)
77
76
  );
78
77
  if (right > left && bottom > top) {
79
78
  frames.set(node.nodeId, {
@@ -86,6 +85,30 @@ function rnxRasterFrames(tree, nodeIds) {
86
85
  }
87
86
  return frames;
88
87
  }
88
+ function liquidGlassPaintOutset(glass, frame) {
89
+ const outset = { x: 0, top: 0, bottom: 0 };
90
+ if (!glass || typeof glass !== "object") return outset;
91
+ const contour = Reflect.get(glass, "contour");
92
+ const shadows = [
93
+ Reflect.get(glass, "shadow"),
94
+ Math.min(frame.width, frame.height) > 62 ? Reflect.get(glass, "tallShadow") : null,
95
+ ...Array.isArray(contour) ? contour : []
96
+ ];
97
+ for (const shadow of shadows) {
98
+ if (!shadow || typeof shadow !== "object") continue;
99
+ const sigma = Reflect.get(shadow, "sigma");
100
+ if (typeof sigma !== "number") continue;
101
+ const offsetY = Reflect.get(shadow, "offsetY");
102
+ const spread = Reflect.get(shadow, "spread");
103
+ const [spreadX, spreadY] = typeof spread === "number" ? [spread, spread] : Array.isArray(spread) && typeof spread[0] === "number" && typeof spread[1] === "number" ? [spread[0], spread[1]] : [0, 0];
104
+ const dy = typeof offsetY === "number" ? offsetY : 0;
105
+ const blur = sigma * 3;
106
+ outset.x = Math.max(outset.x, spreadX + blur);
107
+ outset.top = Math.max(outset.top, spreadY + blur - dy);
108
+ outset.bottom = Math.max(outset.bottom, spreadY + blur + dy);
109
+ }
110
+ return outset;
111
+ }
89
112
  function rnxCaptureRasterRegions(capture) {
90
113
  const tree = {
91
114
  width: capture.tree.viewport.width,
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.578 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.579 | (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;