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/upload.ts
CHANGED
|
@@ -30,7 +30,7 @@ import { authHeaderValue, githubUploadIdentity, resolveCliAuth } from '../auth'
|
|
|
30
30
|
import { openUrl } from '../open-url'
|
|
31
31
|
import { extractStringFlag } from '../parse-args'
|
|
32
32
|
import { resolveRunProvenance } from '../run-registry'
|
|
33
|
-
import {
|
|
33
|
+
import { peachExit } from '../run-rnx'
|
|
34
34
|
import {
|
|
35
35
|
callInBridge,
|
|
36
36
|
createBridgeFromParsed,
|
|
@@ -227,7 +227,7 @@ function parsePositiveMs(raw: string | undefined, name: string): number | undefi
|
|
|
227
227
|
const value = Number(raw)
|
|
228
228
|
if (!Number.isFinite(value) || value <= 0) {
|
|
229
229
|
console.error(` invalid ${name}: ${raw}`)
|
|
230
|
-
|
|
230
|
+
peachExit(1)
|
|
231
231
|
}
|
|
232
232
|
return Math.round(value)
|
|
233
233
|
}
|
|
@@ -433,7 +433,7 @@ export async function runUpload(
|
|
|
433
433
|
): Promise<UploadResult> {
|
|
434
434
|
if (args.includes('--help') || args.includes('-h')) {
|
|
435
435
|
printHelp()
|
|
436
|
-
|
|
436
|
+
peachExit(0)
|
|
437
437
|
}
|
|
438
438
|
|
|
439
439
|
const mutableArgs = [...args]
|
|
@@ -472,17 +472,17 @@ export async function runUpload(
|
|
|
472
472
|
const openResult = extractBoolFlag(mutableArgs, '--open')
|
|
473
473
|
if ((owner && !repo) || (!owner && repo)) {
|
|
474
474
|
console.error(' --owner and --repo must be provided together')
|
|
475
|
-
|
|
475
|
+
peachExit(1)
|
|
476
476
|
}
|
|
477
477
|
if (billingKind && billingKind !== 'test_run') {
|
|
478
478
|
console.error(` invalid --billing-kind: ${billingKind}`)
|
|
479
|
-
|
|
479
|
+
peachExit(1)
|
|
480
480
|
}
|
|
481
481
|
// the hosted recorder names the job whose minutes cover this recording
|
|
482
482
|
const runnerJobId = process.env.CONTRAST_RUNNER_JOB_ID
|
|
483
483
|
if (billingKind === 'test_run' && !runnerJobId) {
|
|
484
484
|
console.error(' --billing-kind test_run is only for hosted test jobs')
|
|
485
|
-
|
|
485
|
+
peachExit(1)
|
|
486
486
|
}
|
|
487
487
|
if (!eventsPath && !videoPath) {
|
|
488
488
|
console.error(
|
|
@@ -490,7 +490,7 @@ export async function runUpload(
|
|
|
490
490
|
' for a normal local preview, use `peach record --mode combined --open`\n' +
|
|
491
491
|
' or `peach maestro test --preview` instead of uploading a bundle-only snapshot.',
|
|
492
492
|
)
|
|
493
|
-
|
|
493
|
+
peachExit(1)
|
|
494
494
|
}
|
|
495
495
|
// assets-only filters captured cross-origin responses to just image/font/
|
|
496
496
|
// css/js/binary records before upload — API responses (JSON, HTML) hit the
|
|
@@ -715,14 +715,14 @@ export async function runUpload(
|
|
|
715
715
|
console.error(
|
|
716
716
|
' could not read bundle snapshot — is peach running and is the bundle loaded?',
|
|
717
717
|
)
|
|
718
|
-
|
|
718
|
+
peachExit(2)
|
|
719
719
|
}
|
|
720
720
|
if (!snapshot.bundleUrl) {
|
|
721
721
|
console.error(
|
|
722
722
|
' no ?bundle= URL on the current peach tab.\n' +
|
|
723
723
|
' open the app you want to share first (e.g. peach open 8082), then run upload.',
|
|
724
724
|
)
|
|
725
|
-
|
|
725
|
+
peachExit(2)
|
|
726
726
|
}
|
|
727
727
|
|
|
728
728
|
// prefer the post-transform bundle captured from the running tab. this
|
|
@@ -867,13 +867,13 @@ export async function runUpload(
|
|
|
867
867
|
: undefined
|
|
868
868
|
if (!videoContentType) {
|
|
869
869
|
console.error(' preview flow videos must be mp4 or gif')
|
|
870
|
-
|
|
870
|
+
peachExit(1)
|
|
871
871
|
}
|
|
872
872
|
if (videoDurationMsRaw) {
|
|
873
873
|
const parsed = Number(videoDurationMsRaw)
|
|
874
874
|
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
875
875
|
console.error(` invalid --video-duration-ms: ${videoDurationMsRaw}`)
|
|
876
|
-
|
|
876
|
+
peachExit(1)
|
|
877
877
|
}
|
|
878
878
|
videoDurationMs = Math.round(parsed)
|
|
879
879
|
}
|
|
@@ -893,7 +893,7 @@ export async function runUpload(
|
|
|
893
893
|
console.error(
|
|
894
894
|
' set PEACH_API_KEY=sk_rnx_..., run `peach login`, or use the Contrast github runner.',
|
|
895
895
|
)
|
|
896
|
-
|
|
896
|
+
peachExit(1)
|
|
897
897
|
}
|
|
898
898
|
const resolvedAuthHeader = authHeaderValue(cliAuth)
|
|
899
899
|
|
|
@@ -1193,7 +1193,7 @@ export async function runUpload(
|
|
|
1193
1193
|
if (e.phase === 'init' && e.status === 401) {
|
|
1194
1194
|
console.error(' preview upload requires a valid login.')
|
|
1195
1195
|
console.error(' run `peach login` and retry.')
|
|
1196
|
-
|
|
1196
|
+
peachExit(1, 'preview upload requires a valid login')
|
|
1197
1197
|
}
|
|
1198
1198
|
if (e.status === 402) {
|
|
1199
1199
|
// billing gate — surface the server's own `message`, not raw JSON.
|
|
@@ -1201,13 +1201,13 @@ export async function runUpload(
|
|
|
1201
1201
|
parseServerMessage(e.responseText) ??
|
|
1202
1202
|
'preview uploads require Personal, Team, or an active trial — upgrade from the billing dialog.'
|
|
1203
1203
|
console.error(` ${message}`)
|
|
1204
|
-
|
|
1204
|
+
peachExit(1, message)
|
|
1205
1205
|
}
|
|
1206
1206
|
// PresignedUploadError.message already carries the "<phase> failed:"
|
|
1207
1207
|
// prefix — don't re-prefix it (that produced "init failed: init failed:").
|
|
1208
1208
|
const message = e.message ?? `${e.phase ?? 'upload'} failed: ${String(err)}`
|
|
1209
1209
|
console.error(` ${message}`)
|
|
1210
|
-
|
|
1210
|
+
peachExit(1, message)
|
|
1211
1211
|
}
|
|
1212
1212
|
|
|
1213
1213
|
const previewUrl = `${canonicalPublicPreviewOrigin(publicOrigin)}${finalize.url}`
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
// peach what-happened --limit 50 # cap (default 200)
|
|
16
16
|
|
|
17
17
|
import { getCliIdentityKey } from '../current-sim'
|
|
18
|
-
import {
|
|
18
|
+
import { peachExit } from '../run-rnx'
|
|
19
19
|
import { createBridgeFromParsed, parseBridgeCliArgs } from '../ws-bridge'
|
|
20
20
|
import {
|
|
21
21
|
formatTimelineEvent,
|
|
@@ -184,7 +184,7 @@ note: react-commit, layout, and scroll are opt-in/noisy events. enable them
|
|
|
184
184
|
with "peach timeline start <kind>", then pass --noisy or include them in
|
|
185
185
|
--kinds to see them.
|
|
186
186
|
`)
|
|
187
|
-
|
|
187
|
+
peachExit(0)
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
const summaryMode = args.includes('--summary')
|
package/cli/current-sim.ts
CHANGED
|
@@ -5,7 +5,8 @@ import { getParentPid, getProcessComm, getProcessPgid } from './parent-pid'
|
|
|
5
5
|
import { writeSecureJsonAtomic } from './secure-file'
|
|
6
6
|
|
|
7
7
|
const CURRENT_SIM_VERSION = 2 as const
|
|
8
|
-
const CURRENT_SIM_PATH_ENV = '
|
|
8
|
+
const CURRENT_SIM_PATH_ENV = 'PEACH_CLI_CURRENT_SIM_PATH'
|
|
9
|
+
const LEGACY_CURRENT_SIM_PATH_ENV = 'SOOTSIM_CLI_CURRENT_SIM_PATH'
|
|
9
10
|
|
|
10
11
|
export interface LocalCurrentTarget {
|
|
11
12
|
version: 2
|
|
@@ -167,8 +168,10 @@ export function getOwnerProcessGroupId(): number | null {
|
|
|
167
168
|
}
|
|
168
169
|
|
|
169
170
|
export function getCurrentSimPath() {
|
|
170
|
-
|
|
171
|
-
|
|
171
|
+
const envPath =
|
|
172
|
+
process.env[CURRENT_SIM_PATH_ENV] || process.env[LEGACY_CURRENT_SIM_PATH_ENV]
|
|
173
|
+
if (envPath) {
|
|
174
|
+
return resolve(envPath)
|
|
172
175
|
}
|
|
173
176
|
const key = getCliIdentityKey()
|
|
174
177
|
return join(tmpdir(), `peach-current-sim-${key}.json`)
|
package/cli/desktop-companion.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { execFileSync, spawn } from 'child_process'
|
|
2
|
-
import { existsSync,
|
|
2
|
+
import { existsSync, mkdirSync, writeFileSync } from 'fs'
|
|
3
3
|
import { dirname, join, resolve } from 'path'
|
|
4
4
|
import { fileURLToPath } from 'url'
|
|
5
5
|
import { activeDesktopHostApp, isNativeHostBundle } from '../src/desktop-host-delivery'
|
|
6
|
+
import { rnxHomeDir } from '../src/home-paths'
|
|
6
7
|
|
|
7
|
-
// resolved lazily
|
|
8
|
+
// resolved lazily: peach-engine is a workspace package in dev, but absent
|
|
8
9
|
// from the published npm tarball. don't crash module load just because the
|
|
9
10
|
// engine package isn't installed; commands that don't need the dev-electron
|
|
10
11
|
// path (most of them) shouldn't care.
|
|
@@ -20,19 +21,11 @@ function getSootsimRoot(): string | null {
|
|
|
20
21
|
}
|
|
21
22
|
return _sootsimRoot
|
|
22
23
|
}
|
|
23
|
-
const PEACH_BUNDLE_ID = 'dev.peachsim.simulator'
|
|
24
24
|
|
|
25
25
|
export interface DesktopCompanionInstall {
|
|
26
26
|
path: string
|
|
27
27
|
platform: NodeJS.Platform
|
|
28
|
-
kind:
|
|
29
|
-
| 'native-mac-app'
|
|
30
|
-
| 'native-linux-app'
|
|
31
|
-
| 'mac-app'
|
|
32
|
-
| 'linux-appimage'
|
|
33
|
-
| 'linux-binary'
|
|
34
|
-
| 'win-exe'
|
|
35
|
-
| 'dev-electron'
|
|
28
|
+
kind: 'native-mac-app' | 'native-linux-app' | 'win-exe' | 'dev-electron'
|
|
36
29
|
// present for dev-electron: the sootsim-engine dir that electron treats
|
|
37
30
|
// as the app root (its package.json "main" points at dist-electron/main.cjs).
|
|
38
31
|
engineDir?: string
|
|
@@ -40,14 +33,7 @@ export interface DesktopCompanionInstall {
|
|
|
40
33
|
|
|
41
34
|
export interface DesktopCompanionLaunchResult {
|
|
42
35
|
launched: boolean
|
|
43
|
-
via?:
|
|
44
|
-
| 'native-mac-app'
|
|
45
|
-
| 'native-linux-app'
|
|
46
|
-
| 'mac-app'
|
|
47
|
-
| 'linux-appimage'
|
|
48
|
-
| 'linux-binary'
|
|
49
|
-
| 'win-exe'
|
|
50
|
-
| 'dev-electron'
|
|
36
|
+
via?: 'native-mac-app' | 'native-linux-app' | 'win-exe' | 'dev-electron'
|
|
51
37
|
target?: string
|
|
52
38
|
}
|
|
53
39
|
|
|
@@ -84,8 +70,7 @@ function findDevElectron(): DesktopCompanionInstall | null {
|
|
|
84
70
|
|
|
85
71
|
// detect whether the sootsim-engine we resolved is the in-repo workspace
|
|
86
72
|
// checkout (has src-electron/main.ts) vs something pulled in as a dep.
|
|
87
|
-
//
|
|
88
|
-
// against the live :5173 renderer.
|
|
73
|
+
// Windows development uses Electron against the live renderer.
|
|
89
74
|
function isInRepoCheckout(): boolean {
|
|
90
75
|
const root = getSootsimRoot()
|
|
91
76
|
if (!root) return false
|
|
@@ -95,7 +80,7 @@ function isInRepoCheckout(): boolean {
|
|
|
95
80
|
function findElectronBin(startDir: string): string | null {
|
|
96
81
|
let dir = startDir
|
|
97
82
|
for (let i = 0; i < 6; i++) {
|
|
98
|
-
const candidate = join(dir, 'node_modules
|
|
83
|
+
const candidate = join(dir, 'node_modules/electron/dist/electron.exe')
|
|
99
84
|
if (existsSync(candidate)) return candidate
|
|
100
85
|
const parent = dirname(dir)
|
|
101
86
|
if (parent === dir) break
|
|
@@ -104,120 +89,38 @@ function findElectronBin(startDir: string): string | null {
|
|
|
104
89
|
return null
|
|
105
90
|
}
|
|
106
91
|
|
|
107
|
-
function findInstalledMacApp(): DesktopCompanionInstall | null {
|
|
108
|
-
const candidates = [
|
|
109
|
-
'/Applications/peach.app',
|
|
110
|
-
resolve(process.env.HOME || '', 'Applications/peach.app'),
|
|
111
|
-
]
|
|
112
|
-
|
|
113
|
-
// the native host's /Applications/Peach.app is the same path on a
|
|
114
|
-
// case-insensitive disk
|
|
115
|
-
const found = candidates.find(
|
|
116
|
-
(candidate) => existsSync(candidate) && !isNativeHostBundle(candidate),
|
|
117
|
-
)
|
|
118
|
-
if (found) {
|
|
119
|
-
return {
|
|
120
|
-
path: found,
|
|
121
|
-
platform: 'darwin',
|
|
122
|
-
kind: 'mac-app',
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return null
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function findMacApp(): DesktopCompanionInstall | null {
|
|
130
|
-
const installed = findInstalledMacApp()
|
|
131
|
-
if (installed) return installed
|
|
132
|
-
const root = getSootsimRoot()
|
|
133
|
-
const builtApp = root ? resolve(root, 'app/peach.app') : null
|
|
134
|
-
if (builtApp && existsSync(builtApp)) {
|
|
135
|
-
return { path: builtApp, platform: 'darwin', kind: 'mac-app' }
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
try {
|
|
139
|
-
// runner-toolchain-platform: darwin
|
|
140
|
-
const result = execFileSync(
|
|
141
|
-
'mdfind',
|
|
142
|
-
[`kMDItemCFBundleIdentifier == "${PEACH_BUNDLE_ID}"`],
|
|
143
|
-
{ encoding: 'utf8', timeout: 3000 },
|
|
144
|
-
).trim()
|
|
145
|
-
if (result) {
|
|
146
|
-
return {
|
|
147
|
-
path: result.split('\n')[0],
|
|
148
|
-
platform: 'darwin',
|
|
149
|
-
kind: 'mac-app',
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
} catch {}
|
|
153
|
-
|
|
154
|
-
return null
|
|
155
|
-
}
|
|
156
|
-
|
|
157
92
|
export function findInstalledDesktopCompanion(): DesktopCompanionInstall | null {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
return null
|
|
93
|
+
return process.platform === 'win32'
|
|
94
|
+
? findWindowsInstall()
|
|
95
|
+
: findNativeDesktopCompanion()
|
|
162
96
|
}
|
|
163
97
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
.
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
kind: directMatch.endsWith('.AppImage') ? 'linux-appimage' : 'linux-binary',
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return null
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
function findLinuxInstall(): DesktopCompanionInstall | null {
|
|
194
|
-
const installed = findInstalledLinuxApp()
|
|
195
|
-
if (installed) return installed
|
|
196
|
-
const root = getSootsimRoot()
|
|
197
|
-
const directCandidates = root
|
|
198
|
-
? [resolve(root, 'app/peach.AppImage'), resolve(root, 'release/linux-unpacked/peach')]
|
|
199
|
-
: []
|
|
200
|
-
const directMatch = directCandidates.find((candidate) => existsSync(candidate))
|
|
201
|
-
if (directMatch) {
|
|
202
|
-
return {
|
|
203
|
-
path: directMatch,
|
|
204
|
-
platform: 'linux',
|
|
205
|
-
kind: directMatch.endsWith('.AppImage') ? 'linux-appimage' : 'linux-binary',
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
const scannedMatch = root
|
|
210
|
-
? findFirstAppImage(resolve(root, 'app')) ||
|
|
211
|
-
findFirstAppImage(resolve(root, 'release'))
|
|
212
|
-
: null
|
|
213
|
-
|
|
214
|
-
if (!scannedMatch) return null
|
|
215
|
-
|
|
216
|
-
return {
|
|
217
|
-
path: scannedMatch,
|
|
218
|
-
platform: 'linux',
|
|
219
|
-
kind: 'linux-appimage',
|
|
98
|
+
// existing Electron apps stay on disk; CLI users receive the migration once.
|
|
99
|
+
export function notifyDesktopMigration(): void {
|
|
100
|
+
if (process.platform !== 'darwin' && process.platform !== 'linux') return
|
|
101
|
+
const legacy =
|
|
102
|
+
process.platform === 'darwin'
|
|
103
|
+
? [
|
|
104
|
+
'/Applications/peach.app',
|
|
105
|
+
resolve(process.env.HOME || '', 'Applications/peach.app'),
|
|
106
|
+
].some((candidate) => existsSync(candidate) && !isNativeHostBundle(candidate))
|
|
107
|
+
: ['Applications/peach.AppImage', '.local/bin/peach.AppImage'].some((candidate) =>
|
|
108
|
+
existsSync(resolve(process.env.HOME || '', candidate)),
|
|
109
|
+
) ||
|
|
110
|
+
existsSync('/opt/peach/peach.AppImage') ||
|
|
111
|
+
existsSync('/opt/peach/peach')
|
|
112
|
+
const marker = join(rnxHomeDir(), 'electron-native-migration')
|
|
113
|
+
if (!legacy || existsSync(marker)) return
|
|
114
|
+
mkdirSync(rnxHomeDir(), { recursive: true })
|
|
115
|
+
try {
|
|
116
|
+
writeFileSync(marker, '', { flag: 'wx' })
|
|
117
|
+
} catch (error) {
|
|
118
|
+
if (error instanceof Error && 'code' in error && error.code === 'EEXIST') return
|
|
119
|
+
throw error
|
|
220
120
|
}
|
|
121
|
+
console.error(
|
|
122
|
+
' Electron has retired on Mac and Linux. Install the native app: peach install-desktop',
|
|
123
|
+
)
|
|
221
124
|
}
|
|
222
125
|
|
|
223
126
|
function findWindowsInstall(): DesktopCompanionInstall | null {
|
|
@@ -244,14 +147,21 @@ export interface DesktopCompanionOptions {
|
|
|
244
147
|
native?: boolean
|
|
245
148
|
}
|
|
246
149
|
|
|
247
|
-
//
|
|
150
|
+
// Electron is supported only on Windows; Mac and Linux always use native.
|
|
248
151
|
export function wantsNativeDesktop(opts: DesktopCompanionOptions = {}): boolean {
|
|
249
|
-
return
|
|
152
|
+
return (
|
|
153
|
+
process.platform === 'darwin' || process.platform === 'linux' || opts.native === true
|
|
154
|
+
)
|
|
250
155
|
}
|
|
251
156
|
|
|
252
157
|
export function getNativeDesktopAppPath(): string | null {
|
|
253
158
|
const explicitApp = process.env.PEACH_DESKTOP_APP
|
|
254
|
-
if (!explicitApp)
|
|
159
|
+
if (!explicitApp)
|
|
160
|
+
return process.platform === 'linux'
|
|
161
|
+
? existsSync('/usr/bin/peach-desktop')
|
|
162
|
+
? '/usr/bin/peach-desktop'
|
|
163
|
+
: null
|
|
164
|
+
: activeDesktopHostApp()
|
|
255
165
|
if (process.platform === 'darwin' && !explicitApp.endsWith('.app'))
|
|
256
166
|
throw new Error('PEACH_DESKTOP_APP must name a Mac .app bundle')
|
|
257
167
|
if (process.platform !== 'darwin' && process.platform !== 'linux')
|
|
@@ -279,6 +189,7 @@ export function findDesktopCompanion(
|
|
|
279
189
|
opts: DesktopCompanionOptions = {},
|
|
280
190
|
): DesktopCompanionInstall | null {
|
|
281
191
|
if (wantsNativeDesktop(opts)) return findNativeDesktopCompanion()
|
|
192
|
+
if (process.platform !== 'win32') return null
|
|
282
193
|
const dev = findDevElectron()
|
|
283
194
|
if (dev) return dev
|
|
284
195
|
if (isInRepoCheckout()) {
|
|
@@ -288,7 +199,7 @@ export function findDesktopCompanion(
|
|
|
288
199
|
console.error(
|
|
289
200
|
` dist-electron/main.cjs missing in ${engineDir}.\n` +
|
|
290
201
|
` run: bun run --cwd packages/peach-engine build:electron-main\n` +
|
|
291
|
-
` (or keep it fresh with: bun run watch:
|
|
202
|
+
` (or keep it fresh with: bun run watch:peach:electron-main)`,
|
|
292
203
|
)
|
|
293
204
|
} else {
|
|
294
205
|
console.error(
|
|
@@ -297,8 +208,6 @@ export function findDesktopCompanion(
|
|
|
297
208
|
}
|
|
298
209
|
return null
|
|
299
210
|
}
|
|
300
|
-
if (process.platform === 'darwin') return findMacApp()
|
|
301
|
-
if (process.platform === 'linux') return findLinuxInstall()
|
|
302
211
|
if (process.platform === 'win32') return findWindowsInstall()
|
|
303
212
|
return null
|
|
304
213
|
}
|
|
@@ -343,6 +252,7 @@ export async function launchDesktopCompanion(
|
|
|
343
252
|
install = findDesktopCompanion(),
|
|
344
253
|
opts: LaunchCompanionOptions = {},
|
|
345
254
|
): Promise<DesktopCompanionLaunchResult> {
|
|
255
|
+
notifyDesktopMigration()
|
|
346
256
|
if (!install) return { launched: false }
|
|
347
257
|
|
|
348
258
|
// electron argv extra: main.ts reads --device <model> from process.argv
|
|
@@ -361,22 +271,18 @@ export async function launchDesktopCompanion(
|
|
|
361
271
|
if (opts.ephemeralProfile) extraArgs.push('--ephemeral-profile')
|
|
362
272
|
if (opts.ownerPid && opts.ownerPid > 1) extraArgs.push(`--owner-pid=${opts.ownerPid}`)
|
|
363
273
|
|
|
364
|
-
if (install.kind === '
|
|
274
|
+
if (install.kind === 'native-mac-app') {
|
|
365
275
|
// `open -a` splits app args before and after `--args`. anything after
|
|
366
276
|
// --args is forwarded to electron's process.argv.
|
|
367
|
-
const nativeApp = install.kind === 'native-mac-app'
|
|
368
277
|
// the personal home screen belongs to launches from Spotlight or the Dock;
|
|
369
278
|
// every CLI launch gets the plain one
|
|
370
|
-
|
|
279
|
+
extraArgs.push('--no-personal-home')
|
|
371
280
|
// a CLI launch builds its windows from its own args: skip appkit's restore of a prior
|
|
372
281
|
// crashed session, whose reopen alert blocks boot, without clearing the saved state
|
|
373
|
-
|
|
282
|
+
extraArgs.push('-ApplePersistenceIgnoreState', 'YES')
|
|
374
283
|
const openArgs: string[] = ['-g', '-a', install.path]
|
|
375
|
-
if (url) openArgs.push(buildMacLaunchUrl(url, opts,
|
|
376
|
-
else if (
|
|
377
|
-
nativeApp &&
|
|
378
|
-
(opts.profileId || opts.ephemeralProfile || opts.ownerPid || opts.device)
|
|
379
|
-
)
|
|
284
|
+
if (url) openArgs.push(buildMacLaunchUrl(url, opts, true))
|
|
285
|
+
else if (opts.profileId || opts.ephemeralProfile || opts.ownerPid || opts.device)
|
|
380
286
|
openArgs.push(buildMacLaunchUrl(undefined, opts, true))
|
|
381
287
|
if (extraArgs.length > 0) openArgs.push('--args', ...extraArgs)
|
|
382
288
|
await spawnDetached('open', openArgs)
|
|
@@ -419,8 +325,8 @@ function buildMacLaunchUrl(
|
|
|
419
325
|
(!nativeApp || !opts.device)
|
|
420
326
|
)
|
|
421
327
|
return url || ''
|
|
422
|
-
const deepLink = new URL('peach://dev')
|
|
423
|
-
if (url) deepLink.searchParams.set('url', url)
|
|
328
|
+
const deepLink = new URL(url?.startsWith('peach://') ? url : 'peach://dev')
|
|
329
|
+
if (url && !url.startsWith('peach://')) deepLink.searchParams.set('url', url)
|
|
424
330
|
if (nativeApp && opts.device) deepLink.searchParams.set('device', opts.device)
|
|
425
331
|
if (opts.profileId) deepLink.searchParams.set('profile', opts.profileId)
|
|
426
332
|
if (opts.ephemeralProfile) deepLink.searchParams.set('ephemeral', '1')
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
//
|
|
3
3
|
// inside the Contrast monorepo checkout serve() serves public/sootsim — the
|
|
4
4
|
// dev-stack engine build — directly (see resolveDevCheckoutRuntimeRoot).
|
|
5
|
-
// without the dev watch running (bun dev's watch:
|
|
5
|
+
// without the dev watch running (bun dev's watch:peach) that build goes
|
|
6
6
|
// stale the moment an engine/shell source is edited, and serve() would hand
|
|
7
7
|
// sims the old bundle with no complaint. this module compares source and
|
|
8
8
|
// artifact mtimes per build route and reports which routes are stale, so
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
import { readdirSync, statSync, type Dirent } from 'node:fs'
|
|
21
21
|
import { join, relative, sep } from 'node:path'
|
|
22
22
|
|
|
23
|
-
export const DEV_BUILD_REBUILD_COMMAND = 'bun run build:
|
|
23
|
+
export const DEV_BUILD_REBUILD_COMMAND = 'bun run build:peach'
|
|
24
24
|
|
|
25
25
|
export type DevBuildRouteId = 'shell' | 'engine' | 'tenant'
|
|
26
26
|
|
package/cli/drivers/desktop.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
// desktop
|
|
2
|
-
// Electron companion. both wrap the desktop-companion helpers, which already
|
|
3
|
-
// handle mac `open -a`, linux AppImage and the --device seed.
|
|
1
|
+
// desktop driver selection is shared with companion discovery.
|
|
4
2
|
|
|
5
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
findDesktopCompanion,
|
|
5
|
+
launchDesktopCompanion,
|
|
6
|
+
wantsNativeDesktop,
|
|
7
|
+
notifyDesktopMigration,
|
|
8
|
+
} from '../desktop-companion'
|
|
6
9
|
import type {
|
|
7
10
|
Driver,
|
|
8
11
|
DriverAvailability,
|
|
@@ -11,8 +14,8 @@ import type {
|
|
|
11
14
|
} from './types'
|
|
12
15
|
|
|
13
16
|
export function createDesktopDriver(id: 'desktop' | 'electron'): Driver {
|
|
14
|
-
const native = id === 'desktop'
|
|
15
|
-
const missing = `peach ${id} app not installed (run \`peach desktop install${native ? '
|
|
17
|
+
const native = wantsNativeDesktop({ native: id === 'desktop' })
|
|
18
|
+
const missing = `peach ${id} app not installed (run \`peach desktop install${native ? '' : ' --electron'}\`)`
|
|
16
19
|
function probe(): DriverAvailability {
|
|
17
20
|
const install = findDesktopCompanion({ native })
|
|
18
21
|
if (!install) return { available: false, reason: missing }
|
|
@@ -25,6 +28,11 @@ export function createDesktopDriver(id: 'desktop' | 'electron'): Driver {
|
|
|
25
28
|
|
|
26
29
|
async function launch(opts: DriverLaunchOptions): Promise<DriverLaunchResult> {
|
|
27
30
|
try {
|
|
31
|
+
notifyDesktopMigration()
|
|
32
|
+
if (id === 'electron' && native)
|
|
33
|
+
console.error(
|
|
34
|
+
' Electron is Windows-only; using the native desktop app (peach install-desktop).',
|
|
35
|
+
)
|
|
28
36
|
const install = findDesktopCompanion({ native })
|
|
29
37
|
if (!install) return { launched: false, message: missing }
|
|
30
38
|
const result = await launchDesktopCompanion(opts.url, install, {
|
|
@@ -38,7 +46,7 @@ export function createDesktopDriver(id: 'desktop' | 'electron'): Driver {
|
|
|
38
46
|
}
|
|
39
47
|
return {
|
|
40
48
|
launched: true,
|
|
41
|
-
message: `${
|
|
49
|
+
message: `${native ? 'native desktop' : 'electron'} launched via ${result.via}${opts.url ? ` → ${opts.url}` : ''}`,
|
|
42
50
|
target: result.target,
|
|
43
51
|
attachUrl: opts.url,
|
|
44
52
|
}
|
|
@@ -54,8 +62,8 @@ export function createDesktopDriver(id: 'desktop' | 'electron'): Driver {
|
|
|
54
62
|
id,
|
|
55
63
|
name: id,
|
|
56
64
|
description: native
|
|
57
|
-
? 'native desktop host (macOS arm64
|
|
58
|
-
: 'peach desktop companion app (Electron;
|
|
65
|
+
? 'native desktop host (macOS arm64 and Linux x64)'
|
|
66
|
+
: 'peach desktop companion app (Electron; Windows only)',
|
|
59
67
|
kind: 'native',
|
|
60
68
|
availability: probe,
|
|
61
69
|
launch,
|
package/cli/drivers/electron.ts
CHANGED
|
@@ -104,10 +104,11 @@ const viewport = viewportSpec
|
|
|
104
104
|
const deviceScaleFactor = Number(process.env.SOOTSIM_PW_DSF || 2);
|
|
105
105
|
const closeTimeoutMs = Number(process.env.SOOTSIM_PW_CLOSE_TIMEOUT_MS || 2500);
|
|
106
106
|
const connectAckFile = process.env.SOOTSIM_PW_CONNECTED_ACK_FILE || '';
|
|
107
|
+
const completionFile = process.env.PEACH_PW_COMPLETION_FILE || '';
|
|
107
108
|
const disposableBrowserCacheDirs = new Set(${JSON.stringify(
|
|
108
109
|
DISPOSABLE_BROWSER_CACHE_DIR_NAMES,
|
|
109
110
|
)});
|
|
110
|
-
const { existsSync, mkdtempSync, readdirSync, rmSync, unlinkSync } = require('fs');
|
|
111
|
+
const { existsSync, mkdtempSync, readdirSync, rmSync, unlinkSync, writeFileSync } = require('fs');
|
|
111
112
|
const { execSync, spawn } = require('child_process');
|
|
112
113
|
const { tmpdir } = require('os');
|
|
113
114
|
const { join } = require('path');
|
|
@@ -363,10 +364,17 @@ const cleanupProfile = () => {
|
|
|
363
364
|
process.once('SIGINT', () => { void shutdown(0); });
|
|
364
365
|
// the launch-failure path at the bottom of this script exits without going
|
|
365
366
|
// through shutdown(); the exit hook (sync sweep) still reaps the tree.
|
|
366
|
-
process.on('exit', () => {
|
|
367
|
+
process.on('exit', (code) => {
|
|
367
368
|
if (desktopHost && desktopHost.exitCode === null) desktopHost.kill('SIGKILL');
|
|
368
369
|
reapChrome();
|
|
369
370
|
cleanupProfile();
|
|
371
|
+
if (completionFile) {
|
|
372
|
+
try {
|
|
373
|
+
writeFileSync(completionFile, JSON.stringify({ code, pid: process.pid, completedAt: Date.now() }) + '\\n');
|
|
374
|
+
} catch (error) {
|
|
375
|
+
process.stderr.write('[completion-error] ' + String(error) + '\\n');
|
|
376
|
+
}
|
|
377
|
+
}
|
|
370
378
|
});
|
|
371
379
|
// owner-liveness watchdog — the load-bearing fix for leaked Chrome hosts.
|
|
372
380
|
// we are spawned detached + unref'd so \`peach open\` returns immediately,
|
|
@@ -651,6 +659,7 @@ const cleanupProfile = () => {
|
|
|
651
659
|
page.on('console', (m) => {
|
|
652
660
|
if (m.type() === 'error') {
|
|
653
661
|
process.stderr.write('[console.error] ' + m.text() + '\\n');
|
|
662
|
+
if (hostCommand && m.text().includes('[compositor] worker lost:')) void shutdown(1);
|
|
654
663
|
}
|
|
655
664
|
});
|
|
656
665
|
// a crashed renderer never runs the page's bridge close path, so nothing
|