peachsim 0.1.662 → 0.1.664

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 (78) hide show
  1. package/cli/commands/control.ts +9 -17
  2. package/cli/commands/inspect/core.ts +44 -23
  3. package/cli/commands/inspect/settling.ts +54 -1
  4. package/cli/commands/inspect/wait-ready.ts +40 -70
  5. package/dist-lib/agent-daemon-client.cjs +1 -1
  6. package/dist-lib/agent-events.cjs +1 -1
  7. package/dist-lib/agent-identity.cjs +1 -1
  8. package/dist-lib/agent-sessions.cjs +1 -1
  9. package/dist-lib/attached-projects.cjs +1 -1
  10. package/dist-lib/auth/shared-session.cjs +1 -1
  11. package/dist-lib/backend-origin.cjs +1 -1
  12. package/dist-lib/beta.cjs +1 -1
  13. package/dist-lib/beta.mjs +1 -1
  14. package/dist-lib/bridge-constants.cjs +1 -1
  15. package/dist-lib/bridge-contract-input.cjs +1 -1
  16. package/dist-lib/bridge-contract-input.mjs +1 -1
  17. package/dist-lib/bridge-contract.cjs +6 -1
  18. package/dist-lib/bridge-contract.mjs +5 -1
  19. package/dist-lib/capture-contract.cjs +1 -1
  20. package/dist-lib/capture-contract.mjs +1 -1
  21. package/dist-lib/cli-constants.cjs +1 -1
  22. package/dist-lib/cloud-contract.cjs +1 -1
  23. package/dist-lib/cloud-contract.mjs +1 -1
  24. package/dist-lib/cloud-test-args.cjs +1 -1
  25. package/dist-lib/cloud-test-args.mjs +1 -1
  26. package/dist-lib/cloud.cjs +1 -1
  27. package/dist-lib/cloud.mjs +1 -1
  28. package/dist-lib/config.cjs +1 -1
  29. package/dist-lib/detox/index.cjs +1 -1
  30. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  31. package/dist-lib/home-paths.cjs +1 -1
  32. package/dist-lib/host/bridge-host.cjs +1 -1
  33. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  34. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  35. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  36. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  37. package/dist-lib/host/websocket-proxy.cjs +1 -1
  38. package/dist-lib/index.cjs +16 -17
  39. package/dist-lib/jump-to-source-babel.cjs +1 -1
  40. package/dist-lib/jump-to-source-native.cjs +1 -1
  41. package/dist-lib/kotlin-host.cjs +13 -7
  42. package/dist-lib/menu.cjs +1 -1
  43. package/dist-lib/menu.mjs +1 -1
  44. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  45. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  46. package/dist-lib/metro-production-bundle.cjs +1 -1
  47. package/dist-lib/metro-production-bundle.mjs +1 -1
  48. package/dist-lib/metro.cjs +1 -1
  49. package/dist-lib/native-app-identity.cjs +1 -1
  50. package/dist-lib/native-app-identity.mjs +1 -1
  51. package/dist-lib/plist.cjs +1 -1
  52. package/dist-lib/plist.mjs +1 -1
  53. package/dist-lib/profiles.cjs +1 -1
  54. package/dist-lib/public-brand.cjs +1 -1
  55. package/dist-lib/react-native-host-modules.cjs +1 -1
  56. package/dist-lib/react-native-host-modules.mjs +1 -1
  57. package/dist-lib/render-mode.cjs +1 -1
  58. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  59. package/dist-lib/sdk.cjs +57 -17
  60. package/dist-lib/sdk.mjs +54 -17
  61. package/dist-lib/skills.cjs +38 -27
  62. package/dist-lib/swift-compile.cjs +1 -1
  63. package/dist-lib/swift-compile.mjs +1 -1
  64. package/dist-lib/swift-package.cjs +1 -1
  65. package/dist-lib/swift-package.mjs +1 -1
  66. package/dist-lib/swift-submit.cjs +1 -1
  67. package/dist-lib/swift-submit.mjs +1 -1
  68. package/dist-lib/swift.cjs +1 -1
  69. package/dist-lib/vite-swift.cjs +1 -1
  70. package/dist-lib/vite.cjs +1 -1
  71. package/kotlin/AppSources/dev/peach/app/PeachApp.kt +8 -2
  72. package/kotlin/fixtures/kotlin-app-variants/Widgets.kt +56 -0
  73. package/package.json +1 -1
  74. package/src/bridge-contract.ts +15 -0
  75. package/src/generated/android-framework-themes.json +341 -0
  76. package/src/kotlin-app.ts +47 -26
  77. package/src/kotlin-host.ts +14 -7
  78. package/src/sdk.ts +2 -1
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.662 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.664 | (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;
@@ -33273,10 +33273,20 @@ var init_app_splash = __esm({
33273
33273
  });
33274
33274
 
33275
33275
  // src/bridge-contract.ts
33276
- var PUBLIC_NO_NETWORK_MARKER, HEADLESS_TENANT_FETCH_HUNG_MARKER;
33276
+ function readyProbeHasContent(probe3) {
33277
+ return probe3.liveFrameActive || probe3.targets > 0 || probe3.nodes >= SEMANTIC_READY_CONTENT_NODE_FLOOR;
33278
+ }
33279
+ function readyProbeHasTargetContent(probe3) {
33280
+ return probe3.liveFrameActive || probe3.targets > 0;
33281
+ }
33282
+ function readyProbeIsReady(probe3) {
33283
+ return (probe3.flag === true ? readyProbeHasContent(probe3) : readyProbeHasTargetContent(probe3)) && probe3.externalReady !== false && !probe3.externalError && !probe3.loadingText;
33284
+ }
33285
+ var SEMANTIC_READY_CONTENT_NODE_FLOOR, PUBLIC_NO_NETWORK_MARKER, HEADLESS_TENANT_FETCH_HUNG_MARKER;
33277
33286
  var init_bridge_contract = __esm({
33278
33287
  "src/bridge-contract.ts"() {
33279
33288
  "use strict";
33289
+ SEMANTIC_READY_CONTENT_NODE_FLOOR = 100;
33280
33290
  PUBLIC_NO_NETWORK_MARKER = "public Peach Cloud simulators have no network";
33281
33291
  HEADLESS_TENANT_FETCH_HUNG_MARKER = "headless tenant fetch hung";
33282
33292
  }
@@ -33762,33 +33772,38 @@ function waitReadyReason(status) {
33762
33772
  return !status.externalError && status.suppressedEntryError ? `${base} (suppressed entry error: ${status.suppressedEntryError})` : base;
33763
33773
  }
33764
33774
  async function inspectWaitReady(bridge, timeoutMs = 2e4, options = {}) {
33775
+ const result = await sendReadyWait(bridge, timeoutMs, timeoutMs + 1e3, options.simId);
33776
+ const status = waitReadyStatus(result, result.matched && !result.probe?.externalError);
33777
+ if (!status.ready && options.onProgress) options.onProgress(status);
33778
+ return status;
33779
+ }
33780
+ async function inspectReadySnapshot(bridge, sendTimeoutMs, simId) {
33781
+ const result = await sendReadyWait(bridge, 1, sendTimeoutMs, simId);
33782
+ return waitReadyStatus(result, result.probe ? readyProbeIsReady(result.probe) : false);
33783
+ }
33784
+ async function sendReadyWait(bridge, timeoutMs, sendTimeoutMs, simId) {
33765
33785
  const start = Date.now();
33766
- let result;
33767
33786
  try {
33768
- result = await bridge.send(
33787
+ return await bridge.send(
33769
33788
  {
33770
33789
  type: "waitFor",
33771
- ...options.simId ? { simId: options.simId } : {},
33790
+ ...simId ? { simId } : {},
33772
33791
  waitForOptions: { condition: { type: "ready" }, timeoutMs }
33773
33792
  },
33774
- { timeoutMs: timeoutMs + 1e3 }
33793
+ { timeoutMs: sendTimeoutMs }
33775
33794
  );
33776
33795
  } catch (error) {
33777
33796
  const bridgeError = error instanceof Error ? error.message : String(error);
33778
33797
  if (bridgeError.startsWith("multiple sims are connected:") || bridgeError.startsWith("saved sim ")) {
33779
33798
  throw error;
33780
33799
  }
33781
- result = {
33782
- matched: false,
33783
- elapsedMs: Date.now() - start,
33784
- polls: 0,
33785
- error: bridgeError
33786
- };
33800
+ return { matched: false, elapsedMs: Date.now() - start, polls: 0, error: bridgeError };
33787
33801
  }
33802
+ }
33803
+ function waitReadyStatus(result, ready) {
33788
33804
  const probe3 = result.probe;
33789
- const externalError = probe3?.externalError ?? "";
33790
- const status = {
33791
- ready: result.matched && !externalError,
33805
+ return {
33806
+ ready,
33792
33807
  elapsedMs: result.elapsedMs,
33793
33808
  nodes: probe3?.nodes ?? 0,
33794
33809
  targets: probe3?.targets ?? 0,
@@ -33799,13 +33814,11 @@ async function inspectWaitReady(bridge, timeoutMs = 2e4, options = {}) {
33799
33814
  loadingText: probe3?.loadingText ?? "",
33800
33815
  externalReady: probe3?.externalReady ?? null,
33801
33816
  externalStatus: probe3?.externalStatus ?? "",
33802
- externalError,
33817
+ externalError: probe3?.externalError ?? "",
33803
33818
  suppressedEntryError: probe3?.suppressedEntryError ?? "",
33804
33819
  errors: probe3?.errors ?? 0,
33805
33820
  bridgeError: result.error ?? ""
33806
33821
  };
33807
- if (!status.ready && options.onProgress) options.onProgress(status);
33808
- return status;
33809
33822
  }
33810
33823
  function consoleEntriesEval(level, limit) {
33811
33824
  const getter = level === "error" ? "getErrors" : "getWarnings";
@@ -37434,17 +37447,14 @@ async function maybeDescribeAfterOpen(wsPort, simId, args) {
37434
37447
  if (noDescribe) return;
37435
37448
  let readyProbe = null;
37436
37449
  try {
37437
- readyProbe = await inspectWaitReady(bridge, 1);
37450
+ readyProbe = await inspectReadySnapshot(bridge, 3e3);
37438
37451
  } catch {
37439
37452
  }
37440
- if (readyProbe) {
37441
- if (!readyProbe.ready) {
37442
- const reason = readyProbe.loadingText ? `still showing "${readyProbe.loadingText}"` : readyProbe.flag !== true ? "guest ready event has not fired" : readyProbe.targets <= 0 ? "no visible app content is inspectable yet" : "app tree is still stabilizing";
37443
- console.log(
37444
- ` app still loading: ${reason} (nodes: ${readyProbe.nodes}, targets: ${readyProbe.targets})`
37445
- );
37446
- console.log(" before interacting, run: peach wait ready --max-ms 120000");
37447
- }
37453
+ if (readyProbe && !readyProbe.ready) {
37454
+ console.log(
37455
+ ` app still loading: ${waitReadyReason(readyProbe)} (nodes: ${readyProbe.nodes}, targets: ${readyProbe.targets})`
37456
+ );
37457
+ console.log(" before interacting, run: peach wait ready --max-ms 120000");
37448
37458
  }
37449
37459
  const result = await inspectDescribe(bridge, {
37450
37460
  describe: true,
@@ -38965,6 +38975,7 @@ async function waitForSootsimIdle({
38965
38975
  var init_settling = __esm({
38966
38976
  "cli/commands/inspect/settling.ts"() {
38967
38977
  "use strict";
38978
+ init_core();
38968
38979
  }
38969
38980
  });
38970
38981
 
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.662 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.664 | (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.662 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.664 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/swift-compile.ts
4
4
  import { execFile as execFile2 } from "node:child_process";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.662 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.664 | (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.662 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.664 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/swift-package.ts
4
4
  function isSwiftManifestFile(file) {
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.662 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.664 | (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.662 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.664 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/swift-submit.ts
4
4
  var SWIFT_COMPILE_PATH = "/api/swift-compile";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.662 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.664 | (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.662 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.664 | (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;
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.662 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.664 | (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;
@@ -46,7 +46,10 @@ import org.json.JSONObject
46
46
  internal class PeachAppSpec(
47
47
  val launcher: ComponentName,
48
48
  val component: ComponentName,
49
- val window: WindowTheme,
49
+ // the launcher activity's window theme in a day and a night configuration,
50
+ // values-night over values
51
+ val dayWindow: WindowTheme,
52
+ val nightWindow: WindowTheme,
50
53
  val createApplication: () -> Application,
51
54
  val createActivity: () -> Activity,
52
55
  // the activity's configChanges includes uiMode: it takes a night mode
@@ -200,7 +203,10 @@ private fun launchActivity(app: AppProcess, lastNonConfigurationInstance: Any?):
200
203
  mount.emitAtFrame("window") { window.describe().toString() }
201
204
  }
202
205
  }
203
- window = Window(activity, spec.window, host)
206
+ // the theme the activity is created under: a relaunch after a night
207
+ // change takes the other one
208
+ val theme = if (isNight(processResources.configuration)) spec.nightWindow else spec.dayWindow
209
+ window = Window(activity, theme, host)
204
210
  activity.attach(
205
211
  app.application,
206
212
  spec.component,
@@ -0,0 +1,56 @@
1
+ package dev.contrast.kotlinapp
2
+
3
+ import androidx.compose.foundation.background
4
+ import androidx.compose.foundation.layout.Arrangement
5
+ import androidx.compose.foundation.layout.Column
6
+ import androidx.compose.foundation.layout.Row
7
+ import androidx.compose.foundation.layout.fillMaxSize
8
+ import androidx.compose.foundation.layout.fillMaxWidth
9
+ import androidx.compose.foundation.layout.padding
10
+ import androidx.compose.foundation.layout.safeDrawingPadding
11
+ import androidx.compose.material3.Button
12
+ import androidx.compose.material3.Card
13
+ import androidx.compose.material3.Checkbox
14
+ import androidx.compose.material3.FilterChip
15
+ import androidx.compose.material3.HorizontalDivider
16
+ import androidx.compose.material3.LinearProgressIndicator
17
+ import androidx.compose.material3.OutlinedButton
18
+ import androidx.compose.material3.RadioButton
19
+ import androidx.compose.material3.Slider
20
+ import androidx.compose.material3.Switch
21
+ import androidx.compose.material3.Text
22
+ import androidx.compose.runtime.Composable
23
+ import androidx.compose.runtime.getValue
24
+ import androidx.compose.runtime.mutableStateOf
25
+ import androidx.compose.runtime.remember
26
+ import androidx.compose.runtime.setValue
27
+ import androidx.compose.ui.Alignment
28
+ import androidx.compose.ui.Modifier
29
+ import androidx.compose.ui.graphics.Color
30
+ import androidx.compose.ui.unit.dp
31
+
32
+ // material controls in both states: the toggle flips every one at once
33
+ @Composable
34
+ fun Widgets() {
35
+ var on by remember { mutableStateOf(false) }
36
+ Column(
37
+ Modifier.fillMaxSize().background(Color(0xFFE8EEF8)).safeDrawingPadding().padding(16.dp),
38
+ verticalArrangement = Arrangement.spacedBy(8.dp),
39
+ ) {
40
+ Text("Selection: $on")
41
+ Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
42
+ Switch(checked = on, onCheckedChange = { on = it })
43
+ Checkbox(checked = on, onCheckedChange = { on = it })
44
+ RadioButton(selected = on, onClick = { on = !on })
45
+ FilterChip(selected = on, onClick = { on = !on }, label = { Text("Chip") })
46
+ }
47
+ Slider(value = if (on) 0.8f else 0.3f, onValueChange = {})
48
+ LinearProgressIndicator(progress = { if (on) 0.9f else 0.4f }, Modifier.fillMaxWidth())
49
+ Card(Modifier.fillMaxWidth()) { Text("Card body", Modifier.padding(16.dp)) }
50
+ HorizontalDivider()
51
+ Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
52
+ Button(onClick = { on = !on }) { Text("Toggle") }
53
+ OutlinedButton(onClick = {}, enabled = on) { Text("Outlined") }
54
+ }
55
+ }
56
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "peachsim",
3
- "version": "0.1.662",
3
+ "version": "0.1.664",
4
4
  "description": "Vite and Metro plugins, testing drivers, and SDK exports for peach.",
5
5
  "author": "Tamagui LLC",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -389,6 +389,21 @@ export function readyProbeHasTargetContent(
389
389
  return probe.liveFrameActive || probe.targets > 0
390
390
  }
391
391
 
392
+ // one probe shows a ready app: it has said so with content behind it, or it
393
+ // paints targets without saying so, and it is neither loading nor errored.
394
+ // `wait ready` also requires the node count to hold still; a caller that has
395
+ // already let the app settle judges a single probe with this alone.
396
+ export function readyProbeIsReady(probe: SemanticReadyProbe): boolean {
397
+ return (
398
+ (probe.flag === true
399
+ ? readyProbeHasContent(probe)
400
+ : readyProbeHasTargetContent(probe)) &&
401
+ probe.externalReady !== false &&
402
+ !probe.externalError &&
403
+ !probe.loadingText
404
+ )
405
+ }
406
+
392
407
  export interface SemanticWaitResult {
393
408
  matched: boolean
394
409
  elapsedMs: number