peachsim 0.1.939 → 0.1.1399
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.
- package/README.md +28 -22
- package/cli/app-catalog.ts +29 -14
- package/cli/app-fonts.ts +5 -3
- package/cli/bridge-flow-runner.ts +40 -29
- package/cli/cloud-client.ts +57 -21
- package/cli/cloud-test-tunnel.ts +12 -18
- package/cli/commands/agent.ts +1 -1
- package/cli/commands/app-fonts.ts +3 -3
- package/cli/commands/assert.ts +8 -8
- package/cli/commands/auth.ts +8 -3
- package/cli/commands/box/bundle-plane.ts +13 -1
- package/cli/commands/box.ts +16 -5
- package/cli/commands/compat.ts +1 -1
- package/cli/commands/config.ts +2 -2
- package/cli/commands/control.ts +125 -71
- package/cli/commands/cpu-profile.ts +45 -1
- package/cli/commands/daemon.ts +131 -33
- package/cli/commands/debug.ts +24 -17
- package/cli/commands/desktop.ts +7 -1
- package/cli/commands/detect.ts +101 -0
- package/cli/commands/detox.ts +6 -6
- package/cli/commands/device.ts +12 -12
- package/cli/commands/electron.ts +32 -14
- package/cli/commands/flow.ts +49 -41
- package/cli/commands/guest-host.ts +39 -1
- package/cli/commands/inspect/core.ts +14 -8
- package/cli/commands/inspect/list.ts +1 -1
- package/cli/commands/inspect/settle.ts +5 -3
- package/cli/commands/inspect/settling.ts +229 -44
- package/cli/commands/inspect/wait-idle.ts +3 -2
- package/cli/commands/inspect.ts +105 -93
- package/cli/commands/install-cli.ts +36 -15
- package/cli/commands/install-desktop.ts +68 -195
- package/cli/commands/kotlin.ts +6 -5
- package/cli/commands/login.ts +5 -5
- package/cli/commands/maestro-compare.ts +554 -0
- package/cli/commands/maestro-generate.ts +6 -3
- package/cli/commands/maestro.ts +22 -0
- package/cli/commands/mode.ts +2 -2
- package/cli/commands/no-bridge-hint.ts +6 -2
- package/cli/commands/platform.ts +35 -6
- package/cli/commands/preview.ts +6 -0
- package/cli/commands/project-report.ts +10 -12
- package/cli/commands/record.ts +37 -37
- package/cli/commands/runtime.ts +9 -9
- package/cli/commands/screenshot-layers.ts +4 -4
- package/cli/commands/screenshot-mode.ts +2 -2
- package/cli/commands/screenshot.ts +8 -8
- package/cli/commands/screenshots-capture.ts +2 -2
- package/cli/commands/serve.ts +9 -12
- package/cli/commands/setup.ts +29 -14
- package/cli/commands/shell-boolean-mode.ts +2 -2
- package/cli/commands/show-touches-mode.ts +2 -2
- package/cli/commands/skills.ts +11 -11
- package/cli/commands/swift.ts +29 -11
- package/cli/commands/telemetry.ts +2 -2
- package/cli/commands/test.ts +5 -0
- package/cli/commands/three-mode.ts +3 -3
- package/cli/commands/timeline.ts +4 -4
- package/cli/commands/upgrade.ts +2 -2
- package/cli/commands/upload.ts +15 -15
- package/cli/commands/what-happened.ts +2 -2
- package/cli/current-sim.ts +6 -3
- package/cli/desktop-companion.ts +55 -149
- package/cli/dev-build-freshness.ts +2 -2
- package/cli/drivers/desktop.ts +17 -9
- package/cli/drivers/electron.ts +1 -2
- package/cli/drivers/playwright-sim-host.ts +11 -2
- package/cli/drivers/playwright.ts +35 -2
- package/cli/drivers/types.ts +8 -0
- package/cli/maestro-compare.ts +670 -0
- package/cli/outbound-endpoints.ts +46 -8
- package/cli/recording-access.ts +6 -6
- package/cli/run-registry.ts +1 -1
- package/cli/runtime-compat.ts +5 -1
- package/cli/send-to-box.ts +3 -3
- package/cli/shell-init.ts +2 -1
- package/cli/ws-bridge.ts +9 -5
- package/detox/element-types.ts +1 -0
- package/detox/gestures.ts +3 -3
- package/detox/index.ts +67 -38
- package/detox/navigation-lifecycle.ts +9 -6
- package/detox/proof-frame.cjs +6 -4
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/bridge-contract-input.cjs +42 -17
- package/dist-lib/bridge-contract-input.mjs +41 -16
- package/dist-lib/bridge-contract.cjs +1 -4
- package/dist-lib/bridge-contract.mjs +1 -3
- package/dist-lib/bundle-channel.cjs +2918 -550
- package/dist-lib/capture-contract.cjs +65 -24
- package/dist-lib/capture-contract.mjs +63 -24
- package/dist-lib/cloud-contract.cjs +2 -2
- package/dist-lib/cloud-contract.mjs +2 -2
- package/dist-lib/cloud-test-args.cjs +1 -1
- package/dist-lib/cloud-test-args.mjs +1 -1
- package/dist-lib/cloud.cjs +3 -3
- package/dist-lib/cloud.mjs +3 -3
- package/dist-lib/config.cjs +15 -5
- package/dist-lib/config.mjs +154 -0
- package/dist-lib/detox/index.cjs +495 -139
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/expo-swift-bundle.cjs +1168 -238
- package/dist-lib/expo-swift-metadata.cjs +34 -23
- package/dist-lib/expo-swift-metadata.mjs +32 -23
- package/dist-lib/home-paths.cjs +2 -2
- package/dist-lib/host/bridge-host.cjs +2938 -654
- package/dist-lib/host/fetch-proxy-handler.cjs +14 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +7 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +5 -1
- package/dist-lib/host/replacement-module-handler.cjs +2 -2
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +999 -353
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.cjs +1 -1
- package/dist-lib/kotlin-host.cjs +332 -19
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro-fingerprint-registry.cjs +1 -1
- package/dist-lib/metro-fingerprint-registry.mjs +1 -1
- package/dist-lib/metro-production-bundle.cjs +7 -7
- package/dist-lib/metro-production-bundle.mjs +5 -5
- package/dist-lib/metro.cjs +688 -250
- package/dist-lib/native-app-identity-project.cjs +2647 -0
- package/dist-lib/native-app-identity-project.mjs +1257 -0
- package/dist-lib/native-app-identity.cjs +325 -25
- package/dist-lib/native-app-identity.mjs +323 -25
- package/dist-lib/native-firebase-metadata.cjs +1 -1
- package/dist-lib/native-firebase-metadata.mjs +1 -1
- package/dist-lib/plist.cjs +1 -1
- package/dist-lib/plist.mjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +1 -1
- package/dist-lib/react-native-host-modules.cjs +5 -1
- package/dist-lib/react-native-host-modules.mjs +5 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +57 -32
- package/dist-lib/sdk.cjs +231 -51
- package/dist-lib/sdk.mjs +231 -51
- package/dist-lib/skills.cjs +4107 -1374
- package/dist-lib/swift-compile.cjs +290 -30
- package/dist-lib/swift-compile.mjs +290 -30
- package/dist-lib/swift-package.cjs +143 -12
- package/dist-lib/swift-package.mjs +137 -11
- package/dist-lib/swift-submit.cjs +47 -5
- package/dist-lib/swift-submit.mjs +42 -5
- package/dist-lib/swift-toolchain.cjs +7 -2
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite-swift.cjs +1392 -458
- package/dist-lib/vite.cjs +13 -17
- package/dist-lib/worklet-executable.cjs +248 -33
- package/dist-lib/worklet-executable.mjs +248 -33
- package/install.sh +10 -1
- package/kotlin/{AppSources → AndroidViewSources}/android/content/res/Resources.kt +9 -9
- package/kotlin/AndroidViewSources/android/graphics/Canvas.kt +20 -0
- package/kotlin/AndroidViewSources/android/view/View.kt +211 -0
- package/kotlin/AndroidViewSources/android/widget/FrameLayout.kt +61 -0
- package/kotlin/AndroidViewSources/android/widget/LinearLayout.kt +49 -0
- package/kotlin/AppSources/android/view/Window.kt +36 -0
- package/kotlin/AppSources/android/view/WindowInsets.kt +9 -0
- package/kotlin/AppSources/android/view/WindowInsetsController.kt +5 -0
- package/kotlin/AppSources/android/window/OnBackInvokedDispatcher.kt +48 -0
- package/kotlin/AppSources/androidx/activity/OnBackPressedDispatcher.kt +20 -5
- package/kotlin/AppSources/androidx/compose/foundation/layout/WindowInsets.kt +15 -0
- package/kotlin/AppSources/androidx/compose/ui/platform/ComposeView.kt +2 -1
- package/kotlin/AppSources/dev/peach/app/PeachApp.kt +42 -50
- package/kotlin/ComposeSources/PeachComposeHost.kt +200 -84
- package/kotlin/ExpoComposeSources/PeachAndroidView.kt +87 -0
- package/kotlin/ExpoComposeSources/PeachExpoViewMount.kt +24 -0
- package/kotlin/ExpoComposeSources/dev/peach/expo/PeachExpoCompose.kt +28 -0
- package/kotlin/ExpoComposeSources/expo/modules/kotlin/views/ExpoComposeView.kt +70 -0
- package/kotlin/ExpoSources/dev/peach/expo/PeachExpoRuntime.kt +513 -0
- package/kotlin/ExpoSources/dev/peach/expo/PeachExpoTypes.kt +173 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/AppContext.kt +20 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/Promise.kt +19 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/classcomponent/ClassComponentBuilder.kt +198 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/exception/CodedException.kt +126 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/functions/Functions.kt +132 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/jni/JavaScriptTypedArray.kt +81 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/modules/Module.kt +98 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/objects/ObjectDefinitionBuilder.kt +236 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/records/Record.kt +12 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/runtime/Runtime.kt +9 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/sharedobjects/SharedObject.kt +50 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/sharedobjects/SharedObjectRegistry.kt +57 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/sharedobjects/SharedRef.kt +19 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/ConcreteTypedArrays.kt +158 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/GenericTypedArray.kt +8 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/TypedArray.kt +29 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/TypedArrayIterator.kt +9 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/types/AnyType.kt +155 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/types/Either.kt +91 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/types/Enumerable.kt +6 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/viewevent/ViewEvent.kt +54 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/views/ExpoView.kt +23 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/views/ViewDefinitionBuilder.kt +71 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/views/ViewProps.kt +35 -0
- package/kotlin/README.md +13 -3
- package/kotlin/Sources/android/os/Build.kt +17 -0
- package/kotlin/Sources/android/os/Handler.kt +35 -0
- package/kotlin/Sources/android/os/Looper.kt +17 -0
- package/kotlin/Sources/android/os/MessageQueue.kt +56 -0
- package/kotlin/Sources/android/os/SystemClock.kt +14 -0
- package/kotlin/Sources/android/util/Log.kt +64 -0
- package/kotlin/Sources/java/security/MessageDigest.kt +114 -0
- package/kotlin/Sources/kotlin/text/StringFormat.kt +9 -0
- package/kotlin/Sources/org/json/JSON.kt +44 -0
- package/kotlin/fixtures/counter/Counter.d.kt.ts +1 -0
- package/kotlin/fixtures/counter/Counter.kt +10 -3
- package/kotlin/fixtures/counter/CounterApp.native.tsx +1 -1
- package/kotlin/fixtures/counter/vite.config.ts +2 -2
- package/kotlin/fixtures/headless-counter/Headless.kt +7 -6
- package/kotlin/fixtures/import-animation/Animation.d.kt.ts +7 -0
- package/kotlin/fixtures/import-animation/Animation.kt +80 -0
- package/kotlin/fixtures/import-animation/ImportAnimation.native.tsx +13 -0
- package/kotlin/fixtures/import-animation/README.md +24 -0
- package/kotlin/fixtures/import-animation/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-animation/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-animation/app/routes.d.ts +18 -0
- package/kotlin/fixtures/import-animation/package.json +23 -0
- package/kotlin/fixtures/import-animation/tsconfig.json +20 -0
- package/kotlin/fixtures/import-animation/vite.config.ts +20 -0
- package/kotlin/fixtures/import-editor/Editor.d.kt.ts +7 -0
- package/kotlin/fixtures/import-editor/Editor.kt +59 -0
- package/kotlin/fixtures/import-editor/ImportEditor.native.tsx +23 -0
- package/kotlin/fixtures/import-editor/README.md +27 -0
- package/kotlin/fixtures/import-editor/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-editor/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-editor/package.json +23 -0
- package/kotlin/fixtures/import-editor/tsconfig.json +20 -0
- package/kotlin/fixtures/import-editor/vite.config.ts +20 -0
- package/kotlin/fixtures/import-effects/Effects.d.kt.ts +7 -0
- package/kotlin/fixtures/import-effects/Effects.kt +87 -0
- package/kotlin/fixtures/import-effects/ImportEffects.native.tsx +13 -0
- package/kotlin/fixtures/import-effects/README.md +19 -0
- package/kotlin/fixtures/import-effects/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-effects/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-effects/package.json +23 -0
- package/kotlin/fixtures/import-effects/tsconfig.json +20 -0
- package/kotlin/fixtures/import-effects/vite.config.ts +20 -0
- package/kotlin/fixtures/import-layout/ImportLayout.native.tsx +13 -0
- package/kotlin/fixtures/import-layout/Layout.d.kt.ts +7 -0
- package/kotlin/fixtures/import-layout/Layout.kt +72 -0
- package/kotlin/fixtures/import-layout/README.md +24 -0
- package/kotlin/fixtures/import-layout/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-layout/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-layout/package.json +23 -0
- package/kotlin/fixtures/import-layout/tsconfig.json +20 -0
- package/kotlin/fixtures/import-layout/vite.config.ts +20 -0
- package/kotlin/fixtures/import-navigation/ImportNavigation.native.tsx +18 -0
- package/kotlin/fixtures/import-navigation/Navigation.d.kt.ts +7 -0
- package/kotlin/fixtures/import-navigation/Navigation.kt +104 -0
- package/kotlin/fixtures/import-navigation/README.md +31 -0
- package/kotlin/fixtures/import-navigation/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-navigation/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-navigation/package.json +23 -0
- package/kotlin/fixtures/import-navigation/tsconfig.json +20 -0
- package/kotlin/fixtures/import-navigation/vite.config.ts +20 -0
- package/kotlin/fixtures/import-overlays/ImportOverlays.native.tsx +29 -0
- package/kotlin/fixtures/import-overlays/Overlays.d.kt.ts +7 -0
- package/kotlin/fixtures/import-overlays/Overlays.kt +93 -0
- package/kotlin/fixtures/import-overlays/README.md +34 -0
- package/kotlin/fixtures/import-overlays/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-overlays/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-overlays/package.json +23 -0
- package/kotlin/fixtures/import-overlays/tsconfig.json +20 -0
- package/kotlin/fixtures/import-overlays/vite.config.ts +20 -0
- package/kotlin/fixtures/import-scroll/ImportScroll.native.tsx +13 -0
- package/kotlin/fixtures/import-scroll/README.md +23 -0
- package/kotlin/fixtures/import-scroll/Scroll.d.kt.ts +7 -0
- package/kotlin/fixtures/import-scroll/Scroll.kt +91 -0
- package/kotlin/fixtures/import-scroll/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-scroll/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-scroll/package.json +23 -0
- package/kotlin/fixtures/import-scroll/tsconfig.json +20 -0
- package/kotlin/fixtures/import-scroll/vite.config.ts +20 -0
- package/kotlin/fixtures/import-selection/ImportSelection.native.tsx +44 -0
- package/kotlin/fixtures/import-selection/README.md +32 -0
- package/kotlin/fixtures/import-selection/Selection.d.kt.ts +8 -0
- package/kotlin/fixtures/import-selection/Selection.kt +78 -0
- package/kotlin/fixtures/import-selection/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-selection/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-selection/package.json +23 -0
- package/kotlin/fixtures/import-selection/tsconfig.json +20 -0
- package/kotlin/fixtures/import-selection/vite.config.ts +20 -0
- package/kotlin/fixtures/import-surfaces/ImportSurfaces.native.tsx +13 -0
- package/kotlin/fixtures/import-surfaces/README.md +22 -0
- package/kotlin/fixtures/import-surfaces/Surfaces.d.kt.ts +7 -0
- package/kotlin/fixtures/import-surfaces/Surfaces.kt +64 -0
- package/kotlin/fixtures/import-surfaces/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-surfaces/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-surfaces/package.json +23 -0
- package/kotlin/fixtures/import-surfaces/tsconfig.json +20 -0
- package/kotlin/fixtures/import-surfaces/vite.config.ts +20 -0
- package/kotlin/fixtures/import-values/ImportValues.native.tsx +35 -0
- package/kotlin/fixtures/import-values/README.md +23 -0
- package/kotlin/fixtures/import-values/Values.d.kt.ts +11 -0
- package/kotlin/fixtures/import-values/Values.kt +66 -0
- package/kotlin/fixtures/import-values/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-values/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-values/package.json +23 -0
- package/kotlin/fixtures/import-values/tsconfig.json +20 -0
- package/kotlin/fixtures/import-values/vite.config.ts +20 -0
- package/kotlin/fixtures/kotlin-app-variants/BarBehavior.kt +38 -0
- package/kotlin/fixtures/kotlin-app-variants/BarVisibility.kt +36 -0
- package/kotlin/fixtures/kotlin-app-variants/Ime.kt +3 -1
- package/kotlin/fixtures/kotlin-app-variants/TransientInsets.kt +50 -0
- package/kotlin/fork/NOTICE +6 -1
- package/kotlin/fork/README.md +15 -7
- package/kotlin/fork/build.sh +2 -0
- package/kotlin/fork/compose-worker-globals.patch +186 -4
- package/kotlin/fork/fork.json +2 -2
- package/kotlin/fork/skiko-worker-clock.patch +12 -0
- package/kotlin/toolchain.json +12 -12
- package/kotlin/tools/expo-types.main.kts +115 -0
- package/package.json +17 -23
- package/scripts/dev-server-scanner.ts +92 -66
- package/skills/contrast/SKILL.md +2 -2
- package/skills/peach-debug/SKILL.md +1 -1
- package/skills/peach-perf/SKILL.md +1 -1
- package/skills/peach-setup/SKILL.md +2 -1
- package/skills/peach-test/SKILL.md +8 -0
- package/src/assetCatalogContract.ts +43 -1
- package/src/bridge-contract-input.ts +46 -19
- package/src/bridge-contract.ts +0 -1
- package/src/bundle-channel.mjs +197 -84
- package/src/bundleGlobalFooter.ts +38 -0
- package/src/capture-contract.ts +107 -33
- package/src/cloud-contract.ts +5 -1
- package/src/cloud.ts +5 -2
- package/src/config.ts +22 -3
- package/src/configured-bundle-producer.ts +1 -1
- package/src/desktop-host-delivery.ts +95 -1
- package/src/expo-kotlin-bundle.ts +29 -0
- package/src/expo-kotlin-host.ts +201 -0
- package/src/expo-swift-host.ts +96 -76
- package/src/expoKotlinContract.ts +70 -0
- package/src/expoSwiftContract.ts +4 -25
- package/src/home-paths.ts +7 -4
- package/src/host/bridge-host.ts +23 -3
- package/src/host/fetch-proxy-handler.ts +13 -0
- package/src/host/fetch-proxy-overrides.ts +11 -0
- package/src/host/replacement-module-handler.ts +5 -2
- package/src/index.ts +3 -1
- package/src/kotlin-host.ts +463 -19
- package/src/metro-plugin.ts +56 -28
- package/src/metro-production-bundle.ts +2 -2
- package/src/native-app-identity-project.ts +190 -0
- package/src/native-app-identity.ts +398 -34
- package/src/native-firebase-config.ts +69 -15
- package/src/native-seam-manifest.ts +6 -0
- package/src/one-widget-discovery.ts +2 -1
- package/src/openstep-plist.ts +107 -0
- package/src/react-native-host-modules.ts +4 -0
- package/src/runtime-assets.ts +2 -2
- package/src/sim-client.ts +2 -2
- package/src/swift-binary-modules.ts +3 -1
- package/src/swift-compile.ts +286 -38
- package/src/swift-distribution-contract.ts +4 -0
- package/src/swift-distribution.lock.json +123 -12
- package/src/swift-distribution.ts +7 -3
- package/src/swift-host.ts +298 -83
- package/src/swift-package-manifest.ts +29 -2
- package/src/swift-package.ts +180 -10
- package/src/swift-packages.ts +4 -0
- package/src/swift-standin-emit.ts +4 -1
- package/src/swift-standins.ts +274 -15
- package/src/swift-submit.ts +62 -7
- package/src/swift-toolchain.ts +6 -1
- package/src/swiftContract.ts +126 -3
- package/src/vite-plugin-one.ts +13 -16
- package/src/vite-plugin-swift.ts +4 -5
- package/src/vite-plugin.ts +360 -144
- package/src/vite.d.ts +1 -1
- package/src/worker-system-chunks.ts +221 -0
- package/src/worklet-executable.ts +348 -38
- package/src/worklets-babel.ts +1 -1
- package/src/xcode-project.ts +243 -127
- package/dist-lib/agent-identity.cjs +0 -39
- package/dist-lib/agent-sessions.cjs +0 -760
- package/dist-lib/cli-constants.cjs +0 -32
- package/dist-lib/render-mode.cjs +0 -44
- package/kotlin/AppSources/android/view/View.kt +0 -74
- package/kotlin/AppSources/android/widget/FrameLayout.kt +0 -6
- package/src/render-mode.ts +0 -15
- /package/kotlin/{AppSources → AndroidViewSources}/android/content/Context.kt +0 -0
- /package/kotlin/{AppSources → AndroidViewSources}/android/content/res/Configuration.kt +0 -0
- /package/kotlin/{AppSources → AndroidViewSources}/android/graphics/Color.kt +0 -0
- /package/kotlin/{AppSources → AndroidViewSources}/android/util/DisplayMetrics.kt +0 -0
- /package/kotlin/{AppSources → AndroidViewSources}/dev/peach/app/JavaFormat.kt +0 -0
- /package/kotlin/{AppSources → Sources}/java/lang/Runnable.kt +0 -0
package/cli/commands/platform.ts
CHANGED
|
@@ -30,6 +30,7 @@ function isDeviceModel(value: string): value is DeviceModel {
|
|
|
30
30
|
|
|
31
31
|
// flags this command reads for itself rather than treating as the bundle.
|
|
32
32
|
const REMOTE_VALUE_FLAGS = new Set([
|
|
33
|
+
'--assets',
|
|
33
34
|
'--device',
|
|
34
35
|
'--name',
|
|
35
36
|
'--endpoint',
|
|
@@ -41,12 +42,14 @@ function remoteInputFromArgs(
|
|
|
41
42
|
platform: RuntimePlatform,
|
|
42
43
|
): {
|
|
43
44
|
bundlePath: string
|
|
45
|
+
assetsDirectory: string | undefined
|
|
44
46
|
name: string | null
|
|
45
47
|
nativeProjectDir: string | undefined
|
|
46
48
|
reuse: boolean
|
|
47
49
|
fresh: boolean
|
|
48
50
|
} {
|
|
49
51
|
const positional: string[] = []
|
|
52
|
+
let assetsDirectory: string | undefined
|
|
50
53
|
let name: string | null = null
|
|
51
54
|
let nativeProjectDir: string | undefined
|
|
52
55
|
for (let index = 0; index < args.length; index++) {
|
|
@@ -57,6 +60,7 @@ function remoteInputFromArgs(
|
|
|
57
60
|
if (REMOTE_VALUE_FLAGS.has(arg)) {
|
|
58
61
|
const value = args[++index] ?? null
|
|
59
62
|
if (!value) throw new Error(`peach remote ${platform} ${arg} requires a value`)
|
|
63
|
+
if (arg === '--assets') assetsDirectory = value
|
|
60
64
|
if (arg === '--name') name = value
|
|
61
65
|
if (arg === '--native-project') nativeProjectDir = value
|
|
62
66
|
continue
|
|
@@ -66,6 +70,7 @@ function remoteInputFromArgs(
|
|
|
66
70
|
const value = assigned[2] ?? ''
|
|
67
71
|
if (!value)
|
|
68
72
|
throw new Error(`peach remote ${platform} ${assigned[1]} requires a value`)
|
|
73
|
+
if (assigned[1] === '--assets') assetsDirectory = value
|
|
69
74
|
if (assigned[1] === '--name') name = value
|
|
70
75
|
if (assigned[1] === '--native-project') nativeProjectDir = value
|
|
71
76
|
continue
|
|
@@ -97,7 +102,14 @@ function remoteInputFromArgs(
|
|
|
97
102
|
if (reuse && fresh) {
|
|
98
103
|
throw new Error(`peach remote ${platform} cannot combine --reuse and --new`)
|
|
99
104
|
}
|
|
100
|
-
return {
|
|
105
|
+
return {
|
|
106
|
+
bundlePath: positional[0],
|
|
107
|
+
assetsDirectory,
|
|
108
|
+
name,
|
|
109
|
+
nativeProjectDir,
|
|
110
|
+
reuse,
|
|
111
|
+
fresh,
|
|
112
|
+
}
|
|
101
113
|
}
|
|
102
114
|
|
|
103
115
|
/**
|
|
@@ -163,7 +175,7 @@ export async function runPlatformCommand(
|
|
|
163
175
|
}
|
|
164
176
|
}
|
|
165
177
|
|
|
166
|
-
if (args.includes('--remote')) {
|
|
178
|
+
if (args.includes('--remote') || args.includes('--nano')) {
|
|
167
179
|
if (platform === 'android' && args.includes('--nano')) {
|
|
168
180
|
const error = new UnsupportedRemoteHostError('android', 'nano')
|
|
169
181
|
console.error(` ${error.message}`)
|
|
@@ -176,8 +188,9 @@ export async function runPlatformCommand(
|
|
|
176
188
|
return await runRemoteCreate(platform, args, selectedDevice)
|
|
177
189
|
} catch (error) {
|
|
178
190
|
rethrowIfExit(error)
|
|
191
|
+
const mode = args.includes('--nano') ? '--nano' : '--remote'
|
|
179
192
|
console.error(
|
|
180
|
-
` ${rnxPublicBrand.commandName} ${platform}
|
|
193
|
+
` ${rnxPublicBrand.commandName} ${platform} ${mode} failed: ${
|
|
181
194
|
error instanceof Error ? error.message : String(error)
|
|
182
195
|
}`,
|
|
183
196
|
)
|
|
@@ -276,9 +289,15 @@ async function runRemoteCreate(
|
|
|
276
289
|
import('../cloud-session'),
|
|
277
290
|
import('./box'),
|
|
278
291
|
])
|
|
279
|
-
const artifact = await produceCloudArtifact(
|
|
292
|
+
const artifact = await produceCloudArtifact(
|
|
293
|
+
input.bundlePath,
|
|
294
|
+
undefined,
|
|
295
|
+
input.assetsDirectory,
|
|
296
|
+
)
|
|
280
297
|
const descriptor = requireCloudSessionShellUpdate()
|
|
281
|
-
const { auth, header } = authHeaderOrExit(
|
|
298
|
+
const { auth, header } = authHeaderOrExit(
|
|
299
|
+
`${platform} ${args.includes('--nano') ? '--nano' : '--remote'}`,
|
|
300
|
+
)
|
|
282
301
|
const accountId = cloudAccountIdOrExit(auth)
|
|
283
302
|
|
|
284
303
|
const existingSession = readCloudSession()
|
|
@@ -325,6 +344,7 @@ async function runRemoteCreate(
|
|
|
325
344
|
accountId,
|
|
326
345
|
platform,
|
|
327
346
|
reuse: input.reuse,
|
|
347
|
+
assetsDirectory: input.assetsDirectory,
|
|
328
348
|
})
|
|
329
349
|
try {
|
|
330
350
|
publishCloudSessionToShell(created.session, descriptor)
|
|
@@ -405,7 +425,7 @@ async function runRemoteBox(
|
|
|
405
425
|
import('../cloud-session'),
|
|
406
426
|
])
|
|
407
427
|
const { openInBrowser } = box
|
|
408
|
-
const artifact = await produceCloudBoxArtifact(input.bundlePath)
|
|
428
|
+
const artifact = await produceCloudBoxArtifact(input.bundlePath, input.assetsDirectory)
|
|
409
429
|
// the session records which bundle a box already holds, so reattaching can
|
|
410
430
|
// tell the same app from a rebuilt one. the box producer returns no digest
|
|
411
431
|
// of its own, so take it here over the bytes that actually crossed.
|
|
@@ -498,10 +518,12 @@ async function runRemoteBox(
|
|
|
498
518
|
await closeCloudBox(session)
|
|
499
519
|
throw error
|
|
500
520
|
}
|
|
521
|
+
let attachedToShell = true
|
|
501
522
|
try {
|
|
502
523
|
publishCloudSessionToShell(session)
|
|
503
524
|
} catch {
|
|
504
525
|
// shell update fd not configured
|
|
526
|
+
attachedToShell = false
|
|
505
527
|
}
|
|
506
528
|
process.env[PEACH_CLOUD_SESSION_ENV] = serializeCloudSession(session)
|
|
507
529
|
|
|
@@ -514,6 +536,13 @@ async function runRemoteBox(
|
|
|
514
536
|
if (artifact.assetsDirectory) console.log(` asset dest: ${artifact.assetsDirectory}`)
|
|
515
537
|
for (const warning of artifact.warnings) console.warn(` warning: ${warning}`)
|
|
516
538
|
console.log(REMOTE_COMMANDS_HELP)
|
|
539
|
+
// without the shell integration no later command reaches this box, so
|
|
540
|
+
// `peach remote close` cannot end it; name the command that does.
|
|
541
|
+
if (!attachedToShell) {
|
|
542
|
+
console.log(
|
|
543
|
+
` this shell has no Peach integration; the Box bills until: ${rnxPublicBrand.commandName} box stop ${created.id}`,
|
|
544
|
+
)
|
|
545
|
+
}
|
|
517
546
|
// the session is published before the grant is minted, so a grant that never
|
|
518
547
|
// arrives still leaves the box addressable: re-running this command mints it.
|
|
519
548
|
const watchUrl = await requestBoxWatchUrl({
|
package/cli/commands/preview.ts
CHANGED
|
@@ -118,12 +118,18 @@ export async function runPreview(args: string[]): Promise<number> {
|
|
|
118
118
|
JSON.stringify({
|
|
119
119
|
previewId: finalize.id,
|
|
120
120
|
previewUrl: url,
|
|
121
|
+
visibility: finalize.visibility,
|
|
121
122
|
platform,
|
|
122
123
|
artifact: artifact.receipt,
|
|
123
124
|
}),
|
|
124
125
|
)
|
|
125
126
|
else {
|
|
126
127
|
console.log(` preview: ${url}`)
|
|
128
|
+
if (finalize.visibility === 'private') {
|
|
129
|
+
console.log(
|
|
130
|
+
" private: only signed-in members of your account can open it; turn on Public link in the page's share menu to share it",
|
|
131
|
+
)
|
|
132
|
+
}
|
|
127
133
|
console.log(
|
|
128
134
|
` artifact: sha256:${artifact.sha256} (${artifact.bytes.byteLength} bytes)`,
|
|
129
135
|
)
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
readProjectJson,
|
|
16
16
|
readProjectManifest,
|
|
17
17
|
readProjectMetadata,
|
|
18
|
+
readNativeProjectRenderer,
|
|
18
19
|
resolveManifestVersions,
|
|
19
20
|
scanRepository,
|
|
20
21
|
} from './detect'
|
|
@@ -113,7 +114,7 @@ export function createProjectReport(
|
|
|
113
114
|
const lockCache = new Map<string, Map<string, string>>()
|
|
114
115
|
const notes = [
|
|
115
116
|
'Only project paths, dependency versions and toolchain settings are included. No source, environment values, URLs or credentials.',
|
|
116
|
-
'Config is inspected without execution. Unspecified
|
|
117
|
+
'Config is inspected without execution. Unspecified settings are reported as unknown; malformed, dynamic or contradictory explicit native architecture assignments are rejected.',
|
|
117
118
|
'Directories named node_modules, Pods, Carthage, vendor, build, dist, dist-lib, DerivedData, coverage, target, tmp, cache, artifacts, test-results, playwright-report, and hidden directories are excluded. Directory symlinks are not followed.',
|
|
118
119
|
'Limits: 12 directory levels, 10,000 directories, 200,000 entries, 4 MiB per metadata file. Paths are relative to the scanned root.',
|
|
119
120
|
]
|
|
@@ -151,26 +152,23 @@ export function createProjectReport(
|
|
|
151
152
|
const gradle = readProjectMetadata(join(dir, 'android/gradle.properties')) ?? ''
|
|
152
153
|
const engine =
|
|
153
154
|
metadataValue(expo, 'jsEngine') ?? metadataValue(podProperties, 'expo.jsEngine')
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
metadataValue(podProperties, 'newArchEnabled')
|
|
155
|
+
const iosRenderer = readNativeProjectRenderer(dir, 'ios')
|
|
156
|
+
const androidRenderer = readNativeProjectRenderer(dir, 'android')
|
|
157
157
|
const settings: Record<string, string> = {
|
|
158
158
|
jsEngine:
|
|
159
159
|
engine === 'hermes' || engine === 'jsc'
|
|
160
160
|
? `${engine} (configured)`
|
|
161
161
|
: 'unknown (not configured in static metadata)',
|
|
162
|
-
newArchitecture:
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
162
|
+
newArchitecture: iosRenderer
|
|
163
|
+
? `${iosRenderer === 'fabric'} (configured; iOS)`
|
|
164
|
+
: 'unknown (not configured in static metadata)',
|
|
165
|
+
androidNewArchitecture: androidRenderer
|
|
166
|
+
? `${androidRenderer === 'fabric'} (configured; Android)`
|
|
167
|
+
: 'unknown (not configured in static metadata)',
|
|
168
168
|
}
|
|
169
169
|
const hermes = /^hermesEnabled\s*=\s*(true|false)\s*$/m.exec(gradle)
|
|
170
|
-
const newArch = /^newArchEnabled\s*=\s*(true|false)\s*$/m.exec(gradle)
|
|
171
170
|
if (hermes)
|
|
172
171
|
settings.androidJsEngine = `${hermes[1] === 'true' ? 'hermes' : 'jsc'} (gradle.properties)`
|
|
173
|
-
if (newArch) settings.androidNewArchitecture = `${newArch[1]} (gradle.properties)`
|
|
174
172
|
if (resolved.expo)
|
|
175
173
|
settings.expoSdk = `${sanitizeProjectReportVersion(resolved.expo.version)} (${resolved.expo.source}; expo package version)`
|
|
176
174
|
projects.push({
|
package/cli/commands/record.ts
CHANGED
|
@@ -18,7 +18,7 @@ import { getCliIdentityKey } from '../current-sim'
|
|
|
18
18
|
import { openUrl } from '../open-url'
|
|
19
19
|
import { ensureCliRecordingEntitlement } from '../recording-access'
|
|
20
20
|
import { resolveRunProvenance } from '../run-registry'
|
|
21
|
-
import {
|
|
21
|
+
import { peachExit } from '../run-rnx'
|
|
22
22
|
import {
|
|
23
23
|
checkSimHealth,
|
|
24
24
|
createBridgeFromParsed,
|
|
@@ -88,7 +88,7 @@ async function evalCaptureStep<T>(
|
|
|
88
88
|
` the capture lock auto-releases, so simply retry the recording.\n` +
|
|
89
89
|
` if it persists, recover the sim with \`peach close --sim <id>\`.`,
|
|
90
90
|
)
|
|
91
|
-
|
|
91
|
+
peachExit(1)
|
|
92
92
|
}
|
|
93
93
|
// a leaked/contended render-host streaming session surfaces as an
|
|
94
94
|
// engine-side error delivered over the WS bridge. on the gif/video
|
|
@@ -109,12 +109,12 @@ async function evalCaptureStep<T>(
|
|
|
109
109
|
)}s — retry then, or recover now with\n` +
|
|
110
110
|
` \`peach close --sim <id>\` and reopen the sim.`,
|
|
111
111
|
)
|
|
112
|
-
|
|
112
|
+
peachExit(1)
|
|
113
113
|
}
|
|
114
114
|
// never let any other capture-eval rejection escape as an unhandled
|
|
115
115
|
// promise (raw stack + false exit 0). surface it and exit non-zero.
|
|
116
116
|
console.error(` ${step} failed: ${msg}`)
|
|
117
|
-
|
|
117
|
+
peachExit(1)
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
|
|
@@ -174,7 +174,7 @@ function readRepoScope(args: string[]): RepoScope {
|
|
|
174
174
|
const repo = valueOf(args, '--repo')?.trim()
|
|
175
175
|
if ((owner && !repo) || (!owner && repo)) {
|
|
176
176
|
console.error(' --owner and --repo must be provided together')
|
|
177
|
-
|
|
177
|
+
peachExit(1)
|
|
178
178
|
}
|
|
179
179
|
return owner && repo ? { owner, repo } : null
|
|
180
180
|
}
|
|
@@ -238,7 +238,7 @@ export async function runRecord(args: string[], opts: RecordOptions) {
|
|
|
238
238
|
const formatArg = valueOf(args, '--format') as OutputFormat | undefined
|
|
239
239
|
if (formatArg && !['webm', 'mp4', 'gif', 'png'].includes(formatArg)) {
|
|
240
240
|
console.error(` invalid --format "${formatArg}" — expected webm | mp4 | gif | png`)
|
|
241
|
-
|
|
241
|
+
peachExit(1)
|
|
242
242
|
}
|
|
243
243
|
const outputArg = valueOf(args, '--output')
|
|
244
244
|
const durationSec = Number(valueOf(args, '--duration') ?? '10')
|
|
@@ -246,7 +246,7 @@ export async function runRecord(args: string[], opts: RecordOptions) {
|
|
|
246
246
|
console.error(
|
|
247
247
|
` invalid --duration "${valueOf(args, '--duration')}" — expected a positive number of seconds`,
|
|
248
248
|
)
|
|
249
|
-
|
|
249
|
+
peachExit(1)
|
|
250
250
|
}
|
|
251
251
|
// upper bound: a fat-fingered `--duration 99999` (≈27.7h) otherwise
|
|
252
252
|
// started a runaway recording with no warning (QA F23-3). 600s mirrors
|
|
@@ -260,7 +260,7 @@ export async function runRecord(args: string[], opts: RecordOptions) {
|
|
|
260
260
|
console.error(
|
|
261
261
|
` invalid --duration "${valueOf(args, '--duration')}" — exceeds the ${MAX_DURATION_SEC}s (10m) maximum`,
|
|
262
262
|
)
|
|
263
|
-
|
|
263
|
+
peachExit(1)
|
|
264
264
|
}
|
|
265
265
|
const fps = Number(valueOf(args, '--fps') ?? '30')
|
|
266
266
|
const framesArg = valueOf(args, '--frames')
|
|
@@ -273,7 +273,7 @@ export async function runRecord(args: string[], opts: RecordOptions) {
|
|
|
273
273
|
console.error(
|
|
274
274
|
` invalid --frames "${framesArg}" — expected a positive integer count`,
|
|
275
275
|
)
|
|
276
|
-
|
|
276
|
+
peachExit(1)
|
|
277
277
|
}
|
|
278
278
|
}
|
|
279
279
|
const openAfter = args.includes('--open')
|
|
@@ -287,7 +287,7 @@ export async function runRecord(args: string[], opts: RecordOptions) {
|
|
|
287
287
|
console.error(
|
|
288
288
|
' --lockstep works with `record start` / `record stop` (stateful mode) — atomic --duration is wall-clock and cannot bound a virtual-time capture',
|
|
289
289
|
)
|
|
290
|
-
|
|
290
|
+
peachExit(1)
|
|
291
291
|
}
|
|
292
292
|
|
|
293
293
|
const durationMs = Math.max(100, Math.round(durationSec * 1000))
|
|
@@ -344,7 +344,7 @@ export async function runRecord(args: string[], opts: RecordOptions) {
|
|
|
344
344
|
` start failed: recording store refused to start (${mode})` +
|
|
345
345
|
(started.error ? `: ${started.error}` : ''),
|
|
346
346
|
)
|
|
347
|
-
|
|
347
|
+
peachExit(1)
|
|
348
348
|
}
|
|
349
349
|
console.log(` recording ${mode} for ${durationSec}s`)
|
|
350
350
|
await new Promise((r) => setTimeout(r, durationMs))
|
|
@@ -403,7 +403,7 @@ export async function runRecord(args: string[], opts: RecordOptions) {
|
|
|
403
403
|
})
|
|
404
404
|
if (!start.ok || !start.requestId) {
|
|
405
405
|
console.error(` frame capture start failed: ${start.error ?? 'unknown error'}`)
|
|
406
|
-
|
|
406
|
+
peachExit(1)
|
|
407
407
|
}
|
|
408
408
|
await new Promise((r) => setTimeout(r, durationMs))
|
|
409
409
|
const deadline = Date.now() + Math.max(5_000, durationMs)
|
|
@@ -420,19 +420,19 @@ export async function runRecord(args: string[], opts: RecordOptions) {
|
|
|
420
420
|
})
|
|
421
421
|
if (!result) {
|
|
422
422
|
console.error(' frame capture result missing')
|
|
423
|
-
|
|
423
|
+
peachExit(1)
|
|
424
424
|
}
|
|
425
425
|
if (result.done) {
|
|
426
426
|
if (!result.ok) {
|
|
427
427
|
console.error(` frame capture failed: ${result.error ?? 'unknown error'}`)
|
|
428
|
-
|
|
428
|
+
peachExit(1)
|
|
429
429
|
}
|
|
430
430
|
frames = result.frames ?? []
|
|
431
431
|
break
|
|
432
432
|
}
|
|
433
433
|
if (Date.now() >= deadline) {
|
|
434
434
|
console.error(' frame capture timed out')
|
|
435
|
-
|
|
435
|
+
peachExit(1)
|
|
436
436
|
}
|
|
437
437
|
await new Promise((r) => setTimeout(r, 100))
|
|
438
438
|
}
|
|
@@ -459,7 +459,7 @@ export async function runRecord(args: string[], opts: RecordOptions) {
|
|
|
459
459
|
)
|
|
460
460
|
if (!result) {
|
|
461
461
|
console.error(' gif capture returned no frames')
|
|
462
|
-
|
|
462
|
+
peachExit(1)
|
|
463
463
|
}
|
|
464
464
|
writeFileSync(out, Buffer.from(result.data, 'base64'))
|
|
465
465
|
console.log(` saved: ${out} (${formatBytes(result.size)})`)
|
|
@@ -505,7 +505,7 @@ export async function runRecord(args: string[], opts: RecordOptions) {
|
|
|
505
505
|
' `peach close --sim <id>` then reopen the sim.',
|
|
506
506
|
)
|
|
507
507
|
}
|
|
508
|
-
|
|
508
|
+
peachExit(1)
|
|
509
509
|
}
|
|
510
510
|
|
|
511
511
|
console.log(` recording ${format} for ${durationSec}s → ${out}`)
|
|
@@ -526,12 +526,12 @@ export async function runRecord(args: string[], opts: RecordOptions) {
|
|
|
526
526
|
)
|
|
527
527
|
if (!stopResult.ok) {
|
|
528
528
|
console.error(` stop failed: ${stopResult.error ?? 'unknown error'}`)
|
|
529
|
-
|
|
529
|
+
peachExit(1)
|
|
530
530
|
}
|
|
531
531
|
|
|
532
532
|
if (!stopResult.size) {
|
|
533
533
|
console.error(' recorder returned an empty blob — nothing written')
|
|
534
|
-
|
|
534
|
+
peachExit(1)
|
|
535
535
|
}
|
|
536
536
|
|
|
537
537
|
await downloadBlob(bridge, out)
|
|
@@ -566,7 +566,7 @@ async function probeSim(bridge: WsBridge, code: string): Promise<boolean> {
|
|
|
566
566
|
' loaded an app (or its page is unresponsive). run `peach list`\n' +
|
|
567
567
|
' and target a sim with a loaded app via --sim <id>.',
|
|
568
568
|
)
|
|
569
|
-
|
|
569
|
+
peachExit(1)
|
|
570
570
|
}
|
|
571
571
|
throw err
|
|
572
572
|
}
|
|
@@ -578,7 +578,7 @@ async function assertRecorderAvailable(bridge: WsBridge) {
|
|
|
578
578
|
console.error(
|
|
579
579
|
' window.__sootsimRecorder missing — is peach engine running in this sim?',
|
|
580
580
|
)
|
|
581
|
-
|
|
581
|
+
peachExit(1)
|
|
582
582
|
}
|
|
583
583
|
}
|
|
584
584
|
|
|
@@ -600,7 +600,7 @@ async function assertTabVisibleForCapture(bridge: WsBridge) {
|
|
|
600
600
|
' bring the chrome window to the foreground (un-minimize / switch to\n' +
|
|
601
601
|
' its tab) or run the recording in headless playwright, then retry.',
|
|
602
602
|
)
|
|
603
|
-
|
|
603
|
+
peachExit(1)
|
|
604
604
|
}
|
|
605
605
|
}
|
|
606
606
|
|
|
@@ -695,7 +695,7 @@ function parseMode(raw: string | undefined): RecordMode {
|
|
|
695
695
|
if (!raw) return 'video'
|
|
696
696
|
if (raw === 'video' || raw === 'live' || raw === 'combined') return raw
|
|
697
697
|
console.error(` invalid --mode "${raw}" — expected video | live | combined`)
|
|
698
|
-
|
|
698
|
+
peachExit(1)
|
|
699
699
|
}
|
|
700
700
|
|
|
701
701
|
function recordingStatePath(): string {
|
|
@@ -770,7 +770,7 @@ async function refuseLiveRecording(parsed: ParsedBridgeCliArgs) {
|
|
|
770
770
|
console.error(
|
|
771
771
|
` recording already in progress (started ${existing.startedAt}, sim ${existing.simId ?? '?'}). run \`peach record stop\` first, or \`peach record cancel\` to discard.`,
|
|
772
772
|
)
|
|
773
|
-
|
|
773
|
+
peachExit(1)
|
|
774
774
|
}
|
|
775
775
|
|
|
776
776
|
async function recordStart(args: string[], opts: RecordOptions) {
|
|
@@ -800,7 +800,7 @@ async function recordStart(args: string[], opts: RecordOptions) {
|
|
|
800
800
|
console.error(
|
|
801
801
|
` record start only supports webm or mp4 (got: ${formatArg}). for gif/png use atomic mode: peach record --format ${formatArg} --duration <s>`,
|
|
802
802
|
)
|
|
803
|
-
|
|
803
|
+
peachExit(1)
|
|
804
804
|
}
|
|
805
805
|
const fps = Number(valueOf(args, '--fps') ?? '30')
|
|
806
806
|
const repoScope = readRepoScope(args)
|
|
@@ -844,7 +844,7 @@ async function recordStart(args: string[], opts: RecordOptions) {
|
|
|
844
844
|
` start failed: recording store refused to start (${mode})` +
|
|
845
845
|
(started.error ? `: ${started.error}` : ''),
|
|
846
846
|
)
|
|
847
|
-
|
|
847
|
+
peachExit(1)
|
|
848
848
|
}
|
|
849
849
|
} else {
|
|
850
850
|
await assertRecorderAvailable(bridge)
|
|
@@ -852,7 +852,7 @@ async function recordStart(args: string[], opts: RecordOptions) {
|
|
|
852
852
|
const lockstep = args.includes('--lockstep')
|
|
853
853
|
if (lockstep && format !== 'mp4') {
|
|
854
854
|
console.error(' --lockstep requires --format mp4 (webm is realtime-clocked)')
|
|
855
|
-
|
|
855
|
+
peachExit(1)
|
|
856
856
|
}
|
|
857
857
|
const startOpts: {
|
|
858
858
|
format: string
|
|
@@ -868,7 +868,7 @@ async function recordStart(args: string[], opts: RecordOptions) {
|
|
|
868
868
|
})
|
|
869
869
|
if (!result.ok) {
|
|
870
870
|
console.error(` start failed: ${result.error ?? 'unknown error'}`)
|
|
871
|
-
|
|
871
|
+
peachExit(1)
|
|
872
872
|
}
|
|
873
873
|
}
|
|
874
874
|
writeRecordingState({
|
|
@@ -927,7 +927,7 @@ async function recordPreludeStart(args: string[], opts: RecordOptions) {
|
|
|
927
927
|
typeof reason === 'string' && reason ? ` (${reason})` : ''
|
|
928
928
|
}`,
|
|
929
929
|
)
|
|
930
|
-
|
|
930
|
+
peachExit(1)
|
|
931
931
|
}
|
|
932
932
|
console.log(
|
|
933
933
|
' recording preview prelude — run `peach record start --mode combined` when the visible proof segment is ready',
|
|
@@ -1153,7 +1153,7 @@ async function recordStop(args: string[], opts: RecordOptions) {
|
|
|
1153
1153
|
const state = readRecordingState()
|
|
1154
1154
|
if (!state) {
|
|
1155
1155
|
console.error(' no recording in progress. start one with `peach record start`.')
|
|
1156
|
-
|
|
1156
|
+
peachExit(1)
|
|
1157
1157
|
}
|
|
1158
1158
|
|
|
1159
1159
|
const parsed = parseBridgeCliArgs(args, {
|
|
@@ -1200,12 +1200,12 @@ async function recordStop(args: string[], opts: RecordOptions) {
|
|
|
1200
1200
|
if (!stopResult.ok) {
|
|
1201
1201
|
console.error(` stop failed: ${stopResult.error ?? 'unknown error'}`)
|
|
1202
1202
|
clearRecordingState()
|
|
1203
|
-
|
|
1203
|
+
peachExit(1)
|
|
1204
1204
|
}
|
|
1205
1205
|
if (!stopResult.size) {
|
|
1206
1206
|
console.error(' recorder returned an empty blob — nothing written')
|
|
1207
1207
|
clearRecordingState()
|
|
1208
|
-
|
|
1208
|
+
peachExit(1)
|
|
1209
1209
|
}
|
|
1210
1210
|
await downloadBlob(bridge, out)
|
|
1211
1211
|
clearRecordingState()
|
|
@@ -1232,7 +1232,7 @@ async function assertStoreBridgesAvailable(bridge: WsBridge) {
|
|
|
1232
1232
|
console.error(
|
|
1233
1233
|
' SootSim.bridges.startRecording missing — is peach engine running in this sim?',
|
|
1234
1234
|
)
|
|
1235
|
-
|
|
1235
|
+
peachExit(1)
|
|
1236
1236
|
}
|
|
1237
1237
|
}
|
|
1238
1238
|
|
|
@@ -1266,7 +1266,7 @@ async function assertGuestBundleLoaded(bridge: WsBridge, mode: RecordMode) {
|
|
|
1266
1266
|
` photos/settings/home has none). open a metro/guest app first, or\n` +
|
|
1267
1267
|
` use \`--mode video\` for a local screen recording with no upload.`,
|
|
1268
1268
|
)
|
|
1269
|
-
|
|
1269
|
+
peachExit(1)
|
|
1270
1270
|
}
|
|
1271
1271
|
}
|
|
1272
1272
|
|
|
@@ -1329,7 +1329,7 @@ async function injectPreviewSessionAuth(
|
|
|
1329
1329
|
' build without CLI-injected preview auth. reload the sim or open a\n' +
|
|
1330
1330
|
' fresh one (`peach open --new`); if it persists, update peach.',
|
|
1331
1331
|
)
|
|
1332
|
-
|
|
1332
|
+
peachExit(1)
|
|
1333
1333
|
}
|
|
1334
1334
|
}
|
|
1335
1335
|
|
|
@@ -1404,11 +1404,11 @@ function handleStoreUploadResult(
|
|
|
1404
1404
|
) {
|
|
1405
1405
|
if (result.uploadError) {
|
|
1406
1406
|
console.error(` upload failed: ${result.uploadError}`)
|
|
1407
|
-
|
|
1407
|
+
peachExit(1)
|
|
1408
1408
|
}
|
|
1409
1409
|
if (!result.previewUrl) {
|
|
1410
1410
|
console.error(' upload returned no preview URL')
|
|
1411
|
-
|
|
1411
|
+
peachExit(1)
|
|
1412
1412
|
}
|
|
1413
1413
|
console.log(` preview: ${result.previewUrl}`)
|
|
1414
1414
|
// the preview id is content-addressed (shareId = hash of the bundle), so
|
package/cli/commands/runtime.ts
CHANGED
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
rnxRuntime,
|
|
28
28
|
} from '../../src/runtime-delivery'
|
|
29
29
|
import { resolveRNXAppConfig } from '../app-config'
|
|
30
|
-
import {
|
|
30
|
+
import { peachExit } from '../run-rnx'
|
|
31
31
|
import { fetchRuntimeReleaseNotes, formatRuntimeReleaseNotes } from '../runtime-notes'
|
|
32
32
|
import { resolveDefaultBridgePort } from '../ws-bridge'
|
|
33
33
|
|
|
@@ -57,7 +57,7 @@ export async function runRuntime(args: string[], opts: RuntimeOptions = {}) {
|
|
|
57
57
|
default:
|
|
58
58
|
console.error(` unknown runtime subcommand: ${sub}`)
|
|
59
59
|
printHelp()
|
|
60
|
-
|
|
60
|
+
peachExit(1)
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
|
|
@@ -121,7 +121,7 @@ async function runtimeInstall(args: string[], opts: RuntimeOptions) {
|
|
|
121
121
|
return result
|
|
122
122
|
} catch (err) {
|
|
123
123
|
console.error(` ${describeError(err)}`)
|
|
124
|
-
|
|
124
|
+
peachExit(1)
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
127
|
|
|
@@ -235,14 +235,14 @@ async function runtimeUse(args: string[]) {
|
|
|
235
235
|
const version = args[0]
|
|
236
236
|
if (!version) {
|
|
237
237
|
console.error(` usage: peach runtime use <version>`)
|
|
238
|
-
|
|
238
|
+
peachExit(1)
|
|
239
239
|
}
|
|
240
240
|
const installed = rnxRuntime.listInstalled()
|
|
241
241
|
if (!installed.includes(version)) {
|
|
242
242
|
console.error(` version ${version} is not installed`)
|
|
243
243
|
console.error(` installed: ${installed.join(', ') || '(none)'}`)
|
|
244
244
|
console.error(` run \`peach runtime install ${version}\` first`)
|
|
245
|
-
|
|
245
|
+
peachExit(1)
|
|
246
246
|
}
|
|
247
247
|
await activateVersion(version)
|
|
248
248
|
}
|
|
@@ -253,7 +253,7 @@ async function runtimeRemove(args: string[]) {
|
|
|
253
253
|
const version = args[0]
|
|
254
254
|
if (!version) {
|
|
255
255
|
console.error(` usage: peach runtime remove <version>`)
|
|
256
|
-
|
|
256
|
+
peachExit(1)
|
|
257
257
|
}
|
|
258
258
|
const active = readActiveRuntime()
|
|
259
259
|
if (active === version) {
|
|
@@ -261,11 +261,11 @@ async function runtimeRemove(args: string[]) {
|
|
|
261
261
|
console.error(
|
|
262
262
|
` switch with \`peach runtime use <other>\` first, or install another version`,
|
|
263
263
|
)
|
|
264
|
-
|
|
264
|
+
peachExit(1)
|
|
265
265
|
}
|
|
266
266
|
if (readLiveRuntimeVersions().includes(version)) {
|
|
267
267
|
console.error(` cannot remove runtime ${version} while a project is using it`)
|
|
268
|
-
|
|
268
|
+
peachExit(1)
|
|
269
269
|
}
|
|
270
270
|
const dir = runtimeDir(version)
|
|
271
271
|
if (!fs.existsSync(dir)) {
|
|
@@ -292,7 +292,7 @@ async function runtimeWhich() {
|
|
|
292
292
|
async function runtimeNotes(args: string[]) {
|
|
293
293
|
if (args.length > 0) {
|
|
294
294
|
console.error(` usage: peach runtime notes`)
|
|
295
|
-
|
|
295
|
+
peachExit(1)
|
|
296
296
|
}
|
|
297
297
|
const { config } = await resolveRNXAppConfig()
|
|
298
298
|
const version = config?.runtimeVersion ?? readActiveRuntime()
|
|
@@ -11,7 +11,7 @@ import { mkdirSync, writeFileSync } from 'fs'
|
|
|
11
11
|
import { resolve } from 'path'
|
|
12
12
|
import { devices } from 'peach-engine/settings/devices'
|
|
13
13
|
import { buildResolveRectEval, type SampleRect } from '../browser-evals'
|
|
14
|
-
import {
|
|
14
|
+
import { peachExit } from '../run-rnx'
|
|
15
15
|
import { callInBridge, createBridgeFromParsed, parseBridgeCliArgs } from '../ws-bridge'
|
|
16
16
|
import { inspectCaptureReady, waitReadyReason } from './inspect/core'
|
|
17
17
|
|
|
@@ -41,13 +41,13 @@ output:
|
|
|
41
41
|
layer-<id>.png each subtree rendered alone on a transparent frame
|
|
42
42
|
manifest.json device metrics + logical rect per layer
|
|
43
43
|
`)
|
|
44
|
-
|
|
44
|
+
peachExit(0)
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
const idsArg = args.find((_, i) => args[i - 1] === '--ids')
|
|
48
48
|
if (!idsArg) {
|
|
49
49
|
console.error(' --ids is required (comma-separated testIDs)')
|
|
50
|
-
|
|
50
|
+
peachExit(1)
|
|
51
51
|
}
|
|
52
52
|
const testIds = idsArg
|
|
53
53
|
.split(',')
|
|
@@ -55,7 +55,7 @@ output:
|
|
|
55
55
|
.filter(Boolean)
|
|
56
56
|
if (testIds.length === 0) {
|
|
57
57
|
console.error(' --ids resolved to an empty list')
|
|
58
|
-
|
|
58
|
+
peachExit(1)
|
|
59
59
|
}
|
|
60
60
|
const outDirArg = args.find((_, i) => args[i - 1] === '--out-dir')
|
|
61
61
|
const outDir = resolve(process.cwd(), outDirArg ?? '/tmp/peach-layers')
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// wraps the existing `toggle-screenshot-mode` shell action so the CLI
|
|
7
7
|
// stays behavior-compatible with the menu item / keyboard shortcut.
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import { peachExit } from '../run-rnx'
|
|
10
10
|
import { runShellBooleanMode, type ShellBooleanModeOptions } from './shell-boolean-mode'
|
|
11
11
|
|
|
12
12
|
export async function runScreenshotMode(args: string[], opts: ShellBooleanModeOptions) {
|
|
@@ -27,7 +27,7 @@ examples:
|
|
|
27
27
|
peach mode screenshot on
|
|
28
28
|
peach mode screenshot off
|
|
29
29
|
`)
|
|
30
|
-
|
|
30
|
+
peachExit(0)
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
await runShellBooleanMode(args, opts, {
|