peachsim 0.1.634 → 0.1.636
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/dist-lib/agent-daemon-client.cjs +3 -3
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +1 -1
- package/dist-lib/agent-sessions.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 +4 -4
- package/dist-lib/bridge-contract-input.cjs +1 -1
- package/dist-lib/bridge-contract-input.mjs +1 -1
- package/dist-lib/bridge-contract.cjs +1 -1
- package/dist-lib/bridge-contract.mjs +1 -1
- package/dist-lib/capture-contract.cjs +1 -1
- package/dist-lib/capture-contract.mjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/cloud-contract.cjs +1 -1
- package/dist-lib/cloud-contract.mjs +1 -1
- package/dist-lib/cloud-test-args.cjs +1 -1
- package/dist-lib/cloud-test-args.mjs +1 -1
- package/dist-lib/cloud.cjs +1 -1
- package/dist-lib/cloud.mjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +1 -1
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +3 -3
- package/dist-lib/host/bridge-host.cjs +7 -7
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/replacement-module-handler.cjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +2 -2
- 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 +1 -1
- 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 +1 -1
- package/dist-lib/metro-production-bundle.mjs +1 -1
- package/dist-lib/metro.cjs +1 -1
- package/dist-lib/native-app-identity.cjs +1 -1
- package/dist-lib/native-app-identity.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 +1 -1
- package/dist-lib/react-native-host-modules.mjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +43 -41
- package/dist-lib/swift-compile.cjs +15 -4
- package/dist-lib/swift-compile.mjs +14 -4
- package/dist-lib/swift-package.cjs +1 -1
- package/dist-lib/swift-package.mjs +1 -1
- package/dist-lib/swift-submit.cjs +1 -1
- package/dist-lib/swift-submit.mjs +1 -1
- package/dist-lib/swift.cjs +2 -2
- package/dist-lib/vite-swift.cjs +13 -4
- package/dist-lib/vite.cjs +1 -1
- package/package.json +1 -1
- package/src/agent-daemon-client.ts +2 -2
- package/src/bridge-constants.ts +3 -3
- package/src/connect.ts +1 -1
- package/src/disk-cleanup.ts +1 -1
- package/src/home-paths.ts +2 -2
- package/src/host/bridge-host.ts +2 -2
- package/src/runtime-assets.ts +2 -2
- package/src/skills/builtin/compat-check.ts +2 -2
- package/src/swift-compile.ts +22 -3
package/dist-lib/skills.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.636 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -4550,7 +4550,7 @@ var init_supported_native_packages = __esm({
|
|
|
4550
4550
|
"@sdcx/pull-to-refresh",
|
|
4551
4551
|
// seam
|
|
4552
4552
|
"@segment/analytics-react-native",
|
|
4553
|
-
// coverage
|
|
4553
|
+
// seam+coverage
|
|
4554
4554
|
"@segment/sovran-react-native",
|
|
4555
4555
|
// seam
|
|
4556
4556
|
"@sentry/react-native",
|
|
@@ -5101,6 +5101,8 @@ var init_supported_native_packages = __esm({
|
|
|
5101
5101
|
// seam
|
|
5102
5102
|
"react-native-securerandom",
|
|
5103
5103
|
// seam+coverage
|
|
5104
|
+
"react-native-sensors",
|
|
5105
|
+
// seam
|
|
5104
5106
|
"react-native-settings",
|
|
5105
5107
|
// seam+coverage
|
|
5106
5108
|
"react-native-sfsymbols",
|
|
@@ -5274,12 +5276,12 @@ var init_unsupported_packages = __esm({
|
|
|
5274
5276
|
// '@react-native-firebase/app' is tracked at 0.95 measured coverage.
|
|
5275
5277
|
"react-native-firebase": {
|
|
5276
5278
|
note: "it is the pre-v6 umbrella package, which bundles native Firebase SDKs with no JavaScript path",
|
|
5277
|
-
recovery: "Use the scoped packages instead \u2014 install @react-native-firebase/app plus the features you need (@react-native-firebase/auth, /firestore).
|
|
5279
|
+
recovery: "Use the scoped packages instead \u2014 install @react-native-firebase/app plus the features you need (@react-native-firebase/auth, /firestore). Peach runs those against a synthetic native app record."
|
|
5278
5280
|
},
|
|
5279
5281
|
// deprecated upstream since 2021. both replacements are tracked at 0.93.
|
|
5280
5282
|
"react-native-camera": {
|
|
5281
5283
|
note: "it is deprecated upstream and its capture path is entirely native",
|
|
5282
|
-
recovery: "Use react-native-vision-camera or expo-camera.
|
|
5284
|
+
recovery: "Use react-native-vision-camera or expo-camera. Peach backs both with a real getUserMedia preview and canvas photo capture."
|
|
5283
5285
|
},
|
|
5284
5286
|
// no maintained upstream package under this name; store billing is native.
|
|
5285
5287
|
"react-native-in-app-purchase": {
|
|
@@ -6206,7 +6208,7 @@ var init_registry = __esm({
|
|
|
6206
6208
|
{
|
|
6207
6209
|
range: ">=0.17.0",
|
|
6208
6210
|
coverage: 1,
|
|
6209
|
-
note: "full splash wired to the
|
|
6211
|
+
note: "full splash wired to the Peach canvas boot splash, including the app's REAL configured artwork. the config plugin's image + backgroundColor (+ imageWidth, resizeMode, dark variant) and the legacy expo.splash / expo.ios.splash blocks are parsed and painted on boot exactly like the native splash window. setOptions({fade,duration}) is honored: hideAsync()/hide() cross-dissolve the splash over the configured duration (default 400ms, fade default off \u2014 mirroring ios/SplashScreenManager.swift hide()); preventAutoHideAsync holds the splash until the app hides it. matches upstream index.native.ts semantics.",
|
|
6210
6212
|
working: "preventAutoHideAsync (holds splash), hideAsync, hide (sync), setOptions (fade + duration drive the real canvas fade), configured splash image + backgroundColor + imageWidth + resizeMode + dark variant painted on boot (config plugin + legacy expo.splash), SplashScreenOptions type"
|
|
6211
6213
|
}
|
|
6212
6214
|
]
|
|
@@ -6323,7 +6325,7 @@ var init_registry = __esm({
|
|
|
6323
6325
|
{
|
|
6324
6326
|
range: ">=1.0.0",
|
|
6325
6327
|
coverage: 1,
|
|
6326
|
-
note: "full portal API via
|
|
6328
|
+
note: "full portal API via Peach RNTPortalView/RNTPortalHostView custom elements",
|
|
6327
6329
|
working: "Portal (hostName/name/style/children), PortalHost (name/style/children), PortalProvider, usePortal (removePortal), NativePortal, NativePortalHost"
|
|
6328
6330
|
}
|
|
6329
6331
|
]
|
|
@@ -6335,9 +6337,9 @@ var init_registry = __esm({
|
|
|
6335
6337
|
{
|
|
6336
6338
|
range: ">=0.5.0 <0.6.0",
|
|
6337
6339
|
coverage: 0.95,
|
|
6338
|
-
note: "native-seam only: the published provider, navigation adapters, shared-element registry, transition recipes, measurement, Reanimated worklets, and react-native-teleport ownership all run unchanged;
|
|
6340
|
+
note: "native-seam only: the published provider, navigation adapters, shared-element registry, transition recipes, measurement, Reanimated worklets, and react-native-teleport ownership all run unchanged; Peach supplies the ScreenChoreographyView host and ScreenChoreographyPreparation TurboModule used by version 0.5's presentation and two-frame layout handshakes",
|
|
6339
6341
|
working: "ChoreographyProvider, ChoreographyScreen, SharedElement and SharedElement.Target, React Navigation and Expo Router adapters, forward and interactive transitions, native preparation with mounted-descendant checks, tag-recycling rejection, positive finite geometry validation, 0.5-point stability tolerance, two stable frame samples, cancellation, and the 500ms native deadline; overlay presentation acknowledgement after a rendered frame and a two-frame dismissal grace period",
|
|
6340
|
-
missing: "native teardown freezes the final overlay into a bitmap for two frames;
|
|
6342
|
+
missing: "native teardown freezes the final overlay into a bitmap for two frames; Peach keeps the live overlay subtree visible for those two frames because the canvas host has no synchronous subtree snapshot API"
|
|
6341
6343
|
}
|
|
6342
6344
|
]
|
|
6343
6345
|
},
|
|
@@ -6470,9 +6472,9 @@ var init_registry = __esm({
|
|
|
6470
6472
|
{
|
|
6471
6473
|
range: ">=13.0.0",
|
|
6472
6474
|
coverage: 0.82,
|
|
6473
|
-
note: "package-local wrapper registers only the ExpoSpeech native module; upstream expo-speech JS runs unchanged
|
|
6474
|
-
working:
|
|
6475
|
-
missing: "
|
|
6475
|
+
note: "package-local wrapper registers only the ExpoSpeech native module (SpeechModule.swift) over the shared iOS AVSpeechSynthesizer model; upstream expo-speech JS runs unchanged and speech is voiced by the host page.",
|
|
6476
|
+
working: "speak with language, voice, pitch, rate and volume; the iOS 27 simulator voice list and language-to-voice resolution; started, word-boundary, done and stopped events in AVSpeechSynthesizer order; stop cancelling the queue; pause, resume, isSpeaking; ERR_INVALID_VOICE for an unknown voice",
|
|
6477
|
+
missing: "the host voice speaks, not the iOS voice; the host needs a user activation on the page before it voices anything (until then utterances finish silently with a console warning)"
|
|
6476
6478
|
}
|
|
6477
6479
|
]
|
|
6478
6480
|
},
|
|
@@ -6667,7 +6669,7 @@ var init_registry = __esm({
|
|
|
6667
6669
|
{
|
|
6668
6670
|
range: ">=0.7.0",
|
|
6669
6671
|
coverage: 0.9,
|
|
6670
|
-
note: "MenuView renders real iOS-style canvas menu via
|
|
6672
|
+
note: "MenuView renders real iOS-style canvas menu via Peach ContextMenu",
|
|
6671
6673
|
working: "MenuView, actions (title, subtitle, id, state, attributes: disabled/destructive/hidden), subactions (nested menus), onPressAction, onOpenMenu, onCloseMenu, shouldOpenOnLongPress, themeVariant, isAnchoredToRight, NativeActionEvent",
|
|
6672
6674
|
missing: "keepsMenuPresented attribute (iOS 16+), image/imageColor rendering in menu items, inline element actions"
|
|
6673
6675
|
}
|
|
@@ -6880,9 +6882,9 @@ var init_registry = __esm({
|
|
|
6880
6882
|
{
|
|
6881
6883
|
range: ">=4.1.0",
|
|
6882
6884
|
coverage: 0.8,
|
|
6883
|
-
note: "TextToSpeech
|
|
6884
|
-
working: "
|
|
6885
|
-
missing: "
|
|
6885
|
+
note: "native seam: the TextToSpeech module (TextToSpeech.m) over the shared iOS AVSpeechSynthesizer model; the package JS runs unchanged and speech is voiced by the host page",
|
|
6886
|
+
working: "speak, stop, pause, resume, setDucking, setDefaultVoice/Rate/Pitch/Language with their iOS rejections, setIgnoreSilentSwitch, the iOS 27 simulator voices, tts-start/progress/finish/pause/resume/cancel events keyed by utterance hash",
|
|
6887
|
+
missing: "the host voice speaks, not the iOS voice; audio session categories and word-boundary stops have no host effect; the host needs a user activation before it voices anything"
|
|
6886
6888
|
}
|
|
6887
6889
|
]
|
|
6888
6890
|
},
|
|
@@ -6919,9 +6921,9 @@ var init_registry = __esm({
|
|
|
6919
6921
|
{
|
|
6920
6922
|
range: ">=7.0.0",
|
|
6921
6923
|
coverage: 0.7,
|
|
6922
|
-
note: "
|
|
6923
|
-
working: "
|
|
6924
|
-
missing: "
|
|
6924
|
+
note: "native seam: the six RNSensors modules from ios/RNSensors*.m; the package JS (rxjs observables, rnsensors.js) runs unchanged",
|
|
6925
|
+
working: 'every sensor observable errors "Sensor <type> is not available" as on the iOS Simulator, where CoreMotion and CMAltimeter report no hardware; setUpdateIntervalForType and getUpdateInterval keep CMMotionManager intervals from the simulator defaults; getData reads an empty sample',
|
|
6926
|
+
missing: "motion data: the simulator has none to send"
|
|
6925
6927
|
}
|
|
6926
6928
|
]
|
|
6927
6929
|
},
|
|
@@ -7671,9 +7673,9 @@ var init_registry = __esm({
|
|
|
7671
7673
|
{
|
|
7672
7674
|
range: ">=13.0.0",
|
|
7673
7675
|
coverage: 0.93,
|
|
7674
|
-
note: "native-seam only. real expo-av package runs from the bundle (Audio.Sound + Audio.Recording classes, AVPlaybackStatus shape, PitchCorrectionQuality enum, RecordingOptionsPresets, Video component).
|
|
7675
|
-
working: "Audio.Sound (createAsync/loadAsync/unloadAsync/play/pause/stop/seek/setRate/setVolume/setMuted/setLooping/setProgressUpdateInterval/setOnPlaybackStatusUpdate
|
|
7676
|
-
missing: "setAudioModeAsync is noop (no browser equivalent for AVAudioSession), audio metering/analyzer data absent (would need AnalyserNode), Video fullscreen rejects (no system AVPlayerViewController) and useNativeControls draws no controls,
|
|
7676
|
+
note: "native-seam only. real expo-av package runs from the bundle (Audio.Sound + Audio.Recording classes, AVPlaybackStatus shape, PitchCorrectionQuality enum, RecordingOptionsPresets, Video component). sounds: EXAV.m numeric keys over the shared EXAVPlayerData model; recording keeps the web-ported MediaRecorder methods. video: the ExpoVideoView module and view follow ios/EXAV/Video (tag-addressed loadForVideo/setStatusForVideo/replayVideo/getStatusForVideo, the EXAVPlayerData status dictionary, onLoadStart/onLoad/onReadyForDisplay/onStatusUpdate/onError) over the shared video channel.",
|
|
7677
|
+
working: "Audio.Sound (createAsync/loadAsync/unloadAsync/play/pause/stop/seek/setRate/setVolume/setMuted/setLooping/setProgressUpdateInterval/setOnPlaybackStatusUpdate with numeric keys and the iOS status dictionary), Audio.Recording (prepareToRecordAsync/startAsync/pauseAsync/stopAndUnloadAsync/getStatusAsync/getURI via singleton MediaRecorder), Video component playback of bundled and remote sources with the ref API (loadAsync/unloadAsync/playAsync/pauseAsync/setPositionAsync/setStatusAsync/replayAsync/setRate/setVolume/setIsMuted/setIsLooping) and its events, real getUserMedia permission probe with PermissionStatus reflection, didUpdatePlaybackStatus + ExponentAV.onError events through the module emitter, Qualities as AVAudioTimePitchAlgorithm names, RecordingOptionsPresets, PitchCorrectionQuality enum (Low/Medium/High), ResizeMode",
|
|
7678
|
+
missing: "setAudioModeAsync is noop (no browser equivalent for AVAudioSession), audio metering/analyzer data absent (would need AnalyserNode), Video fullscreen rejects (no system AVPlayerViewController) and useNativeControls draws no controls, recording follows the web module (MediaRecorder, blob URI), shouldDuckAndroid / playThroughEarpieceAndroid ignored"
|
|
7677
7679
|
}
|
|
7678
7680
|
]
|
|
7679
7681
|
},
|
|
@@ -7911,7 +7913,7 @@ var init_registry = __esm({
|
|
|
7911
7913
|
coverage: 0.93,
|
|
7912
7914
|
note: "real Stripe.js delegation \u2014 initStripe() lazy-loads https://js.stripe.com/v3/ on first call (no upfront network cost), then every payment op (createPaymentMethod, confirmPayment, confirmSetupIntent, createToken, retrievePaymentIntent / SetupIntent, handleNextAction, verifyMicrodepositsForPayment / Setup) delegates to the real Stripe instance and talks to api.stripe.com over HTTPS. tokenization, payment intents, setup intents, and 3DS are the real implementation; errors are mapped into upstream StripeError shape. <CardField> / <CardForm> / <AuBECSDebitForm> / <PaymentMethodMessagingElement> mount real Stripe Elements iframes (PCI-compliant card collection). Apple Pay / Google Pay route through stripe.paymentRequest (the cross-platform abstraction). native PaymentSheet, CustomerSheet, AddressSheet, AddToWalletButton, and openApplePaySetup remain documented-unavailable (no web equivalents for the native bottom sheets / PassKit setup).",
|
|
7913
7915
|
working: "real Stripe.js tokenization + intent flow \u2014 initStripe (loads js.stripe.com/v3 lazily, caches Stripe instance per publishableKey), createPaymentMethod (real), confirmPayment (real, via stripe.confirmCardPayment), confirmSetupIntent (real, via stripe.confirmCardSetup), createToken (real, via stripe.createToken \u2014 bank_account / pii / account; Card requires a mounted CardField), retrievePaymentIntent / retrieveSetupIntent (real), handleNextAction (real, via stripe.handleCardAction), handleNextActionForSetup (real, via stripe.handleNextAction), verifyMicrodepositsForPayment / Setup (real). real Stripe Elements: CardField / CardForm / AuBECSDebitForm / PaymentMethodMessagingElement mount stripe.elements().create(...) DOM iframes when wrapped in a StripeProvider. platform pay paths (confirmPlatformPayPayment / confirmPlatformPaySetupIntent / createPlatformPayPaymentMethod) route through stripe.paymentRequest \u2014 Apple Pay + Google Pay flow through the same browser PaymentRequest sheet Stripe.js abstracts. feature detection: isPlatformPaySupported via window.ApplePaySession.canMakePayments() + window.PaymentRequest. all upstream React surface: StripeProvider, useStripe / usePaymentSheet / usePlatformPay / useConfirmPayment / useConfirmSetupIntent / useApplePay / useGooglePay / useFinancialConnectionsSheet / useOnramp / useCustomerSheet hooks; StripeContainer / AddToWalletButton / AddressSheet / PlatformPayButton / CustomerSheet / ConnectComponentsProvider components; loadConnectAndInitialize, Constants (ApplePayContactFieldsType, ApplePayMerchantCapability, ApplePayShippingType, AndroidGooglePayButtonStyle / Type, IosGooglePayButtonType), all upstream error enums (Confirm/CardAction/Setup/CreatePayment/CreateToken/RetrievePayment/RetrieveSetup/ApplePay/PaymentSheet/Onramp/GooglePay/VerifyMicrodeposits/CollectBankAccount/AddressSheet/CustomerSheet/PlatformPay/Radar), CardBrand enum, PaymentMethodLayout, StripeError + ErrorType + MissingRoutingNumber",
|
|
7914
|
-
missing: 'native PaymentSheet UI (the iOS-styled bottom drawer; web has stripe.elements().create("payment") as a primitive but the styled chrome differs). CustomerSheet / AddressSheet UI (no clean web equivalent). AddToWalletButton + openApplePaySetup (PassKit-only operations). createTokenForCVCUpdate (requires a mounted CardCvcElement). collectBankAccount* APIs (require a Financial Connections session token from the merchant server). raw Stripe Connect embedded components (would need @stripe/connect-js dep). when running inside the
|
|
7916
|
+
missing: 'native PaymentSheet UI (the iOS-styled bottom drawer; web has stripe.elements().create("payment") as a primitive but the styled chrome differs). CustomerSheet / AddressSheet UI (no clean web equivalent). AddToWalletButton + openApplePaySetup (PassKit-only operations). createTokenForCVCUpdate (requires a mounted CardCvcElement). collectBankAccount* APIs (require a Financial Connections session token from the merchant server). raw Stripe Connect embedded components (would need @stripe/connect-js dep). when running inside the Peach tenant worker (no `document`), Stripe.js cannot load \u2014 a future SootSim.bridges.stripe host helper would proxy DOM ops; the stub surfaces a typed error in that case so consumer code branches through error UI.'
|
|
7915
7917
|
}
|
|
7916
7918
|
]
|
|
7917
7919
|
},
|
|
@@ -7948,9 +7950,9 @@ var init_registry = __esm({
|
|
|
7948
7950
|
{
|
|
7949
7951
|
range: ">=2.0.0",
|
|
7950
7952
|
coverage: 0.95,
|
|
7951
|
-
note: "real upstream package \u2014 not intercepted
|
|
7952
|
-
working: "the whole published API runs unmodified: createClient, AnalyticsProvider, useAnalytics, Plugin/DestinationPlugin/EventPlugin base classes, EventType/PluginType/UpdateType enums, track/identify/screen/group/alias/flush, and the sovran store peer",
|
|
7953
|
-
missing: "the
|
|
7953
|
+
note: "real upstream package \u2014 not intercepted. native side via the AnalyticsReactNative module (native-seams/segment-analytics-react-native.ts), mirroring ios/AnalyticsReactNative.swift as the iOS simulator answers it. UNLIKE the analytics SDKs sootsim does intercept, delivery is NOT suppressed here: a configured writeKey reaches the network from the preview.",
|
|
7954
|
+
working: "the whole published API runs unmodified: createClient, AnalyticsProvider, useAnalytics, Plugin/DestinationPlugin/EventPlugin base classes, EventType/PluginType/UpdateType enums, track/identify/screen/group/alias/flush, and the sovran store peer; getContextInfo supplies the app identity, identifierForVendor device id, uname model, locale, timezone, reachability network type, os and screen points",
|
|
7955
|
+
missing: "the static native entry points trackDeepLink and setAnonymousId, which only native AppDelegate code calls"
|
|
7954
7956
|
}
|
|
7955
7957
|
]
|
|
7956
7958
|
},
|
|
@@ -8459,7 +8461,7 @@ var init_registry = __esm({
|
|
|
8459
8461
|
{
|
|
8460
8462
|
range: ">=3.0.0",
|
|
8461
8463
|
coverage: 1,
|
|
8462
|
-
note: "package JS is just `export default NativeModules.SplashScreen`; the real package runs from the bundle against the SplashScreen native seam. hide() snap-hides the
|
|
8464
|
+
note: "package JS is just `export default NativeModules.SplashScreen`; the real package runs from the bundle against the SplashScreen native seam. hide() snap-hides the Peach canvas boot splash (mirrors ios/RNSplashScreen.m removeFromSuperview, no fade); show() returns immediately without re-showing, exactly as the booted-app native path where `waiting` is already false.",
|
|
8463
8465
|
working: "hide() (snap-hides the canvas splash), show() (no-op in a booted app, faithful)"
|
|
8464
8466
|
}
|
|
8465
8467
|
]
|
|
@@ -13336,9 +13338,9 @@ var init_registry = __esm({
|
|
|
13336
13338
|
{
|
|
13337
13339
|
range: ">=1.4.0",
|
|
13338
13340
|
coverage: 0.72,
|
|
13339
|
-
note: "native-seam only - upstream Speech and HighlightedText JS stay in the bundle; RNSpeech
|
|
13340
|
-
working: "configure, reset, speak, stop, pause, resume,
|
|
13341
|
-
missing: "
|
|
13341
|
+
note: "native-seam only - upstream Speech and HighlightedText JS stay in the bundle; RNSpeech follows RNSpeech.mm over the shared iOS AVSpeechSynthesizer model and speech is voiced by the host page",
|
|
13342
|
+
working: "configure, reset, speak, speakWithOptions, stop, pause, resume, isSpeaking, getAvailableVoices over the iOS 27 simulator voices, onStart/onProgress/onFinish/onPause/onResume/onStopped emitters",
|
|
13343
|
+
missing: "the host voice speaks, not the iOS voice; ducking and silent mode have no host effect; the host needs a user activation before it voices anything"
|
|
13342
13344
|
}
|
|
13343
13345
|
]
|
|
13344
13346
|
},
|
|
@@ -18655,7 +18657,7 @@ function scanDepsWithData(pkg, data) {
|
|
|
18655
18657
|
version,
|
|
18656
18658
|
coverage: null,
|
|
18657
18659
|
status: "auto-stub",
|
|
18658
|
-
note: "not yet verified; it may work through
|
|
18660
|
+
note: "not yet verified; it may work through Peach's generic native seam",
|
|
18659
18661
|
rnx
|
|
18660
18662
|
});
|
|
18661
18663
|
continue;
|
|
@@ -18959,16 +18961,16 @@ function resolveSootsimBridgePortForRuntimeLocation(input = {}) {
|
|
|
18959
18961
|
function resolveSootsimWebSocketProxyUrl(input) {
|
|
18960
18962
|
const pageUrl = parseHrefUrl(input.href);
|
|
18961
18963
|
if (!pageUrl || pageUrl.protocol !== "http:" && pageUrl.protocol !== "https:") {
|
|
18962
|
-
throw new Error(`invalid
|
|
18964
|
+
throw new Error(`invalid Peach websocket proxy page URL: ${input.href}`);
|
|
18963
18965
|
}
|
|
18964
18966
|
let targetUrl;
|
|
18965
18967
|
try {
|
|
18966
18968
|
targetUrl = new URL(input.targetUrl);
|
|
18967
18969
|
} catch {
|
|
18968
|
-
throw new Error(`invalid
|
|
18970
|
+
throw new Error(`invalid Peach websocket proxy target URL: ${input.targetUrl}`);
|
|
18969
18971
|
}
|
|
18970
18972
|
if (targetUrl.protocol !== "ws:" && targetUrl.protocol !== "wss:") {
|
|
18971
|
-
throw new Error(`invalid
|
|
18973
|
+
throw new Error(`invalid Peach websocket proxy target URL: ${input.targetUrl}`);
|
|
18972
18974
|
}
|
|
18973
18975
|
const proxyUrl = new URL("/__websocket-proxy", pageUrl);
|
|
18974
18976
|
proxyUrl.protocol = pageUrl.protocol === "https:" ? "wss:" : "ws:";
|
|
@@ -20832,10 +20834,10 @@ function writeDaemonLockfile(data) {
|
|
|
20832
20834
|
const existing = readDaemonLockfile();
|
|
20833
20835
|
if (!existing) {
|
|
20834
20836
|
if (createDaemonLockfileExclusive(data)) return;
|
|
20835
|
-
throw new Error("another
|
|
20837
|
+
throw new Error("another Peach daemon claimed the lockfile before this write");
|
|
20836
20838
|
}
|
|
20837
20839
|
if (!sameDaemonOwner(existing, data)) {
|
|
20838
|
-
throw new Error("refusing to overwrite another
|
|
20840
|
+
throw new Error("refusing to overwrite another Peach daemon lockfile");
|
|
20839
20841
|
}
|
|
20840
20842
|
const tmp = `${lockfilePath}.${data.pid}.${(0, import_node_crypto.randomUUID)()}.tmp`;
|
|
20841
20843
|
import_node_fs3.default.writeFileSync(tmp, `${JSON.stringify(data, null, 2)}
|
|
@@ -21549,11 +21551,11 @@ function resolveActiveRuntimeRoot() {
|
|
|
21549
21551
|
function runtimeVersionHostname(version) {
|
|
21550
21552
|
const trimmed = version.trim();
|
|
21551
21553
|
if (!isValidRuntimeVersion(trimmed)) {
|
|
21552
|
-
throw new Error(`invalid
|
|
21554
|
+
throw new Error(`invalid Peach runtime version: ${version}`);
|
|
21553
21555
|
}
|
|
21554
21556
|
const encoded = Buffer.from(trimmed, "utf8").toString("hex");
|
|
21555
21557
|
const labels = encoded.match(/.{1,60}/g);
|
|
21556
|
-
if (!labels) throw new Error(`invalid
|
|
21558
|
+
if (!labels) throw new Error(`invalid Peach runtime version: ${version}`);
|
|
21557
21559
|
return `${labels.join(".")}${RUNTIME_VERSION_HOSTNAME_SUFFIX}`;
|
|
21558
21560
|
}
|
|
21559
21561
|
function isRuntimeVersionHostname(hostname) {
|
|
@@ -29132,8 +29134,8 @@ var init_bridge_host = __esm({
|
|
|
29132
29134
|
import_path2 = __toESM(require("path"), 1);
|
|
29133
29135
|
import_ws = require("ws");
|
|
29134
29136
|
init_dev_server_scanner();
|
|
29135
|
-
init_backend_origin();
|
|
29136
29137
|
init_automatic_update_policy();
|
|
29138
|
+
init_backend_origin();
|
|
29137
29139
|
init_bridge_constants();
|
|
29138
29140
|
init_cli_version();
|
|
29139
29141
|
init_home_paths();
|
|
@@ -29803,7 +29805,7 @@ var init_bridge_host = __esm({
|
|
|
29803
29805
|
const claimed = claimDaemonLockfile(this.buildLockfileSnapshot());
|
|
29804
29806
|
if (!claimed) {
|
|
29805
29807
|
throw new Error(
|
|
29806
|
-
"another
|
|
29808
|
+
"another Peach daemon wrote the lockfile during startup \u2014 aborting"
|
|
29807
29809
|
);
|
|
29808
29810
|
}
|
|
29809
29811
|
} catch (err) {
|
|
@@ -40173,14 +40175,14 @@ var skill = {
|
|
|
40173
40175
|
// src/skills/builtin/compat-check.ts
|
|
40174
40176
|
var skill2 = {
|
|
40175
40177
|
name: "compat-check",
|
|
40176
|
-
description: "Check package compatibility with
|
|
40178
|
+
description: "Check package compatibility with Peach",
|
|
40177
40179
|
type: "review",
|
|
40178
40180
|
version: "1.0.0",
|
|
40179
40181
|
triggers: ["compatibility", "compat", "check package", "supported packages"],
|
|
40180
40182
|
tools: [
|
|
40181
40183
|
{
|
|
40182
40184
|
name: "check_compatibility",
|
|
40183
|
-
description: "Scan project dependencies for
|
|
40185
|
+
description: "Scan project dependencies for Peach compatibility",
|
|
40184
40186
|
parameters: {
|
|
40185
40187
|
packageName: {
|
|
40186
40188
|
type: "string",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.636 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -40,6 +40,7 @@ __export(swift_compile_exports, {
|
|
|
40
40
|
swiftArtifactHash: () => swiftArtifactHash,
|
|
41
41
|
swiftIcuAsset: () => swiftIcuAsset,
|
|
42
42
|
swiftModuleInputFiles: () => swiftModuleInputFiles,
|
|
43
|
+
swiftSourceAsIOS: () => swiftSourceAsIOS,
|
|
43
44
|
withNativeSourceGlue: () => withNativeSourceGlue,
|
|
44
45
|
writeSwiftProject: () => writeSwiftProject
|
|
45
46
|
});
|
|
@@ -320,7 +321,7 @@ var ONE_IMPLICIT_FLAGS = ', "-Xfrontend", "-import-module", "-Xfrontend", "One"'
|
|
|
320
321
|
var MULTI_MANIFEST_VERSION = 5;
|
|
321
322
|
function swiftArtifactHash(input, release, moduleRoot) {
|
|
322
323
|
const hash = (0, import_node_crypto2.createHash)("sha256");
|
|
323
|
-
hash.update(`swift-compile/
|
|
324
|
+
hash.update(`swift-compile/v2
|
|
324
325
|
${release}
|
|
325
326
|
`);
|
|
326
327
|
if (input.oneModule) hash.update("one-module\n");
|
|
@@ -420,13 +421,22 @@ function syncSwiftTree(base, files) {
|
|
|
420
421
|
(0, import_node_fs2.writeFileSync)(full, contents, "utf8");
|
|
421
422
|
}
|
|
422
423
|
}
|
|
424
|
+
var CONDITION_LINE = /^([ \t]*#(?:if|elseif)\b)(.*)$/gm;
|
|
425
|
+
var OS_IOS = /\bos\(\s*iOS\s*\)/g;
|
|
426
|
+
function swiftSourceAsIOS(source) {
|
|
427
|
+
return source.replace(
|
|
428
|
+
CONDITION_LINE,
|
|
429
|
+
(_, directive, condition) => directive + condition.replace(OS_IOS, (match) => "true".padEnd(match.length))
|
|
430
|
+
);
|
|
431
|
+
}
|
|
432
|
+
var compiledSource = (file, contents) => file.endsWith(".swift") ? swiftSourceAsIOS(contents) : contents;
|
|
423
433
|
function writeSwiftProject(layout, input, moduleRoot) {
|
|
424
434
|
const targets = compileTargets(input);
|
|
425
435
|
const files = /* @__PURE__ */ new Map();
|
|
426
436
|
if (targets.length === 0) {
|
|
427
437
|
for (const [file, contents] of Object.entries(input.files)) {
|
|
428
438
|
if (file === "Package.swift") continue;
|
|
429
|
-
files.set(import_node_path2.default.join(layout.sources, file), contents);
|
|
439
|
+
files.set(import_node_path2.default.join(layout.sources, file), compiledSource(file, contents));
|
|
430
440
|
}
|
|
431
441
|
let manifest = (0, import_node_fs2.readFileSync)(
|
|
432
442
|
import_node_path2.default.join(moduleRoot, "scripts/contrast-app-Package.swift"),
|
|
@@ -447,7 +457,7 @@ function writeSwiftProject(layout, input, moduleRoot) {
|
|
|
447
457
|
} else {
|
|
448
458
|
for (const [file, contents] of Object.entries(input.files)) {
|
|
449
459
|
if (file === "Package.swift") continue;
|
|
450
|
-
files.set(import_node_path2.default.join(layout.root, file), contents);
|
|
460
|
+
files.set(import_node_path2.default.join(layout.root, file), compiledSource(file, contents));
|
|
451
461
|
}
|
|
452
462
|
files.set(
|
|
453
463
|
import_node_path2.default.join(layout.root, "Package.swift"),
|
|
@@ -574,6 +584,7 @@ function compileSwiftProjectUnit(input, options) {
|
|
|
574
584
|
swiftArtifactHash,
|
|
575
585
|
swiftIcuAsset,
|
|
576
586
|
swiftModuleInputFiles,
|
|
587
|
+
swiftSourceAsIOS,
|
|
577
588
|
withNativeSourceGlue,
|
|
578
589
|
writeSwiftProject
|
|
579
590
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.636 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
|
|
3
3
|
// src/swift-compile.ts
|
|
4
4
|
import { execFile as execFile2 } from "node:child_process";
|
|
@@ -286,7 +286,7 @@ var ONE_IMPLICIT_FLAGS = ', "-Xfrontend", "-import-module", "-Xfrontend", "One"'
|
|
|
286
286
|
var MULTI_MANIFEST_VERSION = 5;
|
|
287
287
|
function swiftArtifactHash(input, release, moduleRoot) {
|
|
288
288
|
const hash = createHash2("sha256");
|
|
289
|
-
hash.update(`swift-compile/
|
|
289
|
+
hash.update(`swift-compile/v2
|
|
290
290
|
${release}
|
|
291
291
|
`);
|
|
292
292
|
if (input.oneModule) hash.update("one-module\n");
|
|
@@ -386,13 +386,22 @@ function syncSwiftTree(base, files) {
|
|
|
386
386
|
writeFileSync(full, contents, "utf8");
|
|
387
387
|
}
|
|
388
388
|
}
|
|
389
|
+
var CONDITION_LINE = /^([ \t]*#(?:if|elseif)\b)(.*)$/gm;
|
|
390
|
+
var OS_IOS = /\bos\(\s*iOS\s*\)/g;
|
|
391
|
+
function swiftSourceAsIOS(source) {
|
|
392
|
+
return source.replace(
|
|
393
|
+
CONDITION_LINE,
|
|
394
|
+
(_, directive, condition) => directive + condition.replace(OS_IOS, (match) => "true".padEnd(match.length))
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
var compiledSource = (file, contents) => file.endsWith(".swift") ? swiftSourceAsIOS(contents) : contents;
|
|
389
398
|
function writeSwiftProject(layout, input, moduleRoot) {
|
|
390
399
|
const targets = compileTargets(input);
|
|
391
400
|
const files = /* @__PURE__ */ new Map();
|
|
392
401
|
if (targets.length === 0) {
|
|
393
402
|
for (const [file, contents] of Object.entries(input.files)) {
|
|
394
403
|
if (file === "Package.swift") continue;
|
|
395
|
-
files.set(path2.join(layout.sources, file), contents);
|
|
404
|
+
files.set(path2.join(layout.sources, file), compiledSource(file, contents));
|
|
396
405
|
}
|
|
397
406
|
let manifest = readFileSync2(
|
|
398
407
|
path2.join(moduleRoot, "scripts/contrast-app-Package.swift"),
|
|
@@ -413,7 +422,7 @@ function writeSwiftProject(layout, input, moduleRoot) {
|
|
|
413
422
|
} else {
|
|
414
423
|
for (const [file, contents] of Object.entries(input.files)) {
|
|
415
424
|
if (file === "Package.swift") continue;
|
|
416
|
-
files.set(path2.join(layout.root, file), contents);
|
|
425
|
+
files.set(path2.join(layout.root, file), compiledSource(file, contents));
|
|
417
426
|
}
|
|
418
427
|
files.set(
|
|
419
428
|
path2.join(layout.root, "Package.swift"),
|
|
@@ -539,6 +548,7 @@ export {
|
|
|
539
548
|
swiftArtifactHash,
|
|
540
549
|
swiftIcuAsset,
|
|
541
550
|
swiftModuleInputFiles,
|
|
551
|
+
swiftSourceAsIOS,
|
|
542
552
|
withNativeSourceGlue,
|
|
543
553
|
writeSwiftProject
|
|
544
554
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.636 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.636 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
package/dist-lib/swift.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.636 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -2831,7 +2831,7 @@ var settingsSchema = {
|
|
|
2831
2831
|
renderResolution: {
|
|
2832
2832
|
type: "enum",
|
|
2833
2833
|
default: "high",
|
|
2834
|
-
description: "how many pixels
|
|
2834
|
+
description: "how many pixels Peach renders per iphone point (high = device native, medium = 2, low = on-screen pixels capped at native)",
|
|
2835
2835
|
options: import_menu.SOOTSIM_RENDER_RESOLUTION_LEVELS,
|
|
2836
2836
|
group: "simulator"
|
|
2837
2837
|
},
|
package/dist-lib/vite-swift.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.636 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -817,7 +817,7 @@ var ONE_IMPLICIT_FLAGS = ', "-Xfrontend", "-import-module", "-Xfrontend", "One"'
|
|
|
817
817
|
var MULTI_MANIFEST_VERSION = 5;
|
|
818
818
|
function swiftArtifactHash(input, release, moduleRoot) {
|
|
819
819
|
const hash = (0, import_node_crypto2.createHash)("sha256");
|
|
820
|
-
hash.update(`swift-compile/
|
|
820
|
+
hash.update(`swift-compile/v2
|
|
821
821
|
${release}
|
|
822
822
|
`);
|
|
823
823
|
if (input.oneModule) hash.update("one-module\n");
|
|
@@ -917,13 +917,22 @@ function syncSwiftTree(base, files) {
|
|
|
917
917
|
(0, import_node_fs3.writeFileSync)(full, contents, "utf8");
|
|
918
918
|
}
|
|
919
919
|
}
|
|
920
|
+
var CONDITION_LINE = /^([ \t]*#(?:if|elseif)\b)(.*)$/gm;
|
|
921
|
+
var OS_IOS = /\bos\(\s*iOS\s*\)/g;
|
|
922
|
+
function swiftSourceAsIOS(source) {
|
|
923
|
+
return source.replace(
|
|
924
|
+
CONDITION_LINE,
|
|
925
|
+
(_, directive, condition) => directive + condition.replace(OS_IOS, (match) => "true".padEnd(match.length))
|
|
926
|
+
);
|
|
927
|
+
}
|
|
928
|
+
var compiledSource = (file, contents) => file.endsWith(".swift") ? swiftSourceAsIOS(contents) : contents;
|
|
920
929
|
function writeSwiftProject(layout, input, moduleRoot) {
|
|
921
930
|
const targets = compileTargets(input);
|
|
922
931
|
const files = /* @__PURE__ */ new Map();
|
|
923
932
|
if (targets.length === 0) {
|
|
924
933
|
for (const [file, contents] of Object.entries(input.files)) {
|
|
925
934
|
if (file === "Package.swift") continue;
|
|
926
|
-
files.set(import_node_path4.default.join(layout.sources, file), contents);
|
|
935
|
+
files.set(import_node_path4.default.join(layout.sources, file), compiledSource(file, contents));
|
|
927
936
|
}
|
|
928
937
|
let manifest = (0, import_node_fs3.readFileSync)(
|
|
929
938
|
import_node_path4.default.join(moduleRoot, "scripts/contrast-app-Package.swift"),
|
|
@@ -944,7 +953,7 @@ function writeSwiftProject(layout, input, moduleRoot) {
|
|
|
944
953
|
} else {
|
|
945
954
|
for (const [file, contents] of Object.entries(input.files)) {
|
|
946
955
|
if (file === "Package.swift") continue;
|
|
947
|
-
files.set(import_node_path4.default.join(layout.root, file), contents);
|
|
956
|
+
files.set(import_node_path4.default.join(layout.root, file), compiledSource(file, contents));
|
|
948
957
|
}
|
|
949
958
|
files.set(
|
|
950
959
|
import_node_path4.default.join(layout.root, "Package.swift"),
|
package/dist-lib/vite.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.636 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
package/package.json
CHANGED
|
@@ -109,7 +109,7 @@ export class AgentDaemonClient {
|
|
|
109
109
|
this.ws.off('open', onOpen)
|
|
110
110
|
reject(
|
|
111
111
|
new AgentDaemonError(
|
|
112
|
-
`could not connect to
|
|
112
|
+
`could not connect to Peach daemon on port ${this.port}: ${err.message}`,
|
|
113
113
|
'NO_DAEMON',
|
|
114
114
|
),
|
|
115
115
|
)
|
|
@@ -399,7 +399,7 @@ export async function ensureDaemonRunning(
|
|
|
399
399
|
await new Promise((r) => setTimeout(r, 100))
|
|
400
400
|
}
|
|
401
401
|
throw new AgentDaemonError(
|
|
402
|
-
`spawned
|
|
402
|
+
`spawned Peach daemon on port ${port} but it did not come up in time. ` +
|
|
403
403
|
`run \`peach serve\` manually to diagnose.`,
|
|
404
404
|
'SPAWN_TIMEOUT',
|
|
405
405
|
)
|
package/src/bridge-constants.ts
CHANGED
|
@@ -127,16 +127,16 @@ export function resolveSootsimWebSocketProxyUrl(input: {
|
|
|
127
127
|
}): string {
|
|
128
128
|
const pageUrl = parseHrefUrl(input.href)
|
|
129
129
|
if (!pageUrl || (pageUrl.protocol !== 'http:' && pageUrl.protocol !== 'https:')) {
|
|
130
|
-
throw new Error(`invalid
|
|
130
|
+
throw new Error(`invalid Peach websocket proxy page URL: ${input.href}`)
|
|
131
131
|
}
|
|
132
132
|
let targetUrl: URL
|
|
133
133
|
try {
|
|
134
134
|
targetUrl = new URL(input.targetUrl)
|
|
135
135
|
} catch {
|
|
136
|
-
throw new Error(`invalid
|
|
136
|
+
throw new Error(`invalid Peach websocket proxy target URL: ${input.targetUrl}`)
|
|
137
137
|
}
|
|
138
138
|
if (targetUrl.protocol !== 'ws:' && targetUrl.protocol !== 'wss:') {
|
|
139
|
-
throw new Error(`invalid
|
|
139
|
+
throw new Error(`invalid Peach websocket proxy target URL: ${input.targetUrl}`)
|
|
140
140
|
}
|
|
141
141
|
const proxyUrl = new URL('/__websocket-proxy', pageUrl)
|
|
142
142
|
proxyUrl.protocol = pageUrl.protocol === 'https:' ? 'wss:' : 'ws:'
|
package/src/connect.ts
CHANGED
|
@@ -85,7 +85,7 @@ export async function connect(options: ConnectOptions = {}): Promise<SimClient>
|
|
|
85
85
|
discovery.close()
|
|
86
86
|
if (error instanceof SimConnectError) throw error
|
|
87
87
|
const message = error instanceof Error ? error.message : String(error)
|
|
88
|
-
throw new SimConnectError(`${message} — is the
|
|
88
|
+
throw new SimConnectError(`${message} — is the Peach daemon or dev shell running?`)
|
|
89
89
|
}
|
|
90
90
|
discovery.close()
|
|
91
91
|
|
package/src/disk-cleanup.ts
CHANGED
|
@@ -336,7 +336,7 @@ export function planSootsimCleanup(
|
|
|
336
336
|
function assertInsideHome(home: string, target: string): void {
|
|
337
337
|
const relative = path.relative(home, target)
|
|
338
338
|
if (!relative || relative.startsWith('..') || path.isAbsolute(relative)) {
|
|
339
|
-
throw new Error(`refusing cleanup target outside the
|
|
339
|
+
throw new Error(`refusing cleanup target outside the Peach data home: ${target}`)
|
|
340
340
|
}
|
|
341
341
|
}
|
|
342
342
|
|
package/src/home-paths.ts
CHANGED
|
@@ -627,10 +627,10 @@ export function writeDaemonLockfile(data: DaemonLockfile): void {
|
|
|
627
627
|
const existing = readDaemonLockfile()
|
|
628
628
|
if (!existing) {
|
|
629
629
|
if (createDaemonLockfileExclusive(data)) return
|
|
630
|
-
throw new Error('another
|
|
630
|
+
throw new Error('another Peach daemon claimed the lockfile before this write')
|
|
631
631
|
}
|
|
632
632
|
if (!sameDaemonOwner(existing, data)) {
|
|
633
|
-
throw new Error('refusing to overwrite another
|
|
633
|
+
throw new Error('refusing to overwrite another Peach daemon lockfile')
|
|
634
634
|
}
|
|
635
635
|
const tmp = `${lockfilePath}.${data.pid}.${randomUUID()}.tmp`
|
|
636
636
|
fs.writeFileSync(tmp, `${JSON.stringify(data, null, 2)}\n`, 'utf8')
|
package/src/host/bridge-host.ts
CHANGED
|
@@ -7,8 +7,8 @@ import {
|
|
|
7
7
|
scanDevServers,
|
|
8
8
|
type DiscoveredServer,
|
|
9
9
|
} from '../../scripts/dev-server-scanner.ts'
|
|
10
|
-
import { buildBrowserAssetProxyUrl } from '../backend-origin.ts'
|
|
11
10
|
import { automaticPeachUpdatesEnabled } from '../automatic-update-policy.ts'
|
|
11
|
+
import { buildBrowserAssetProxyUrl } from '../backend-origin.ts'
|
|
12
12
|
import {
|
|
13
13
|
AUTOMATION_SIM_IDLE_REAP_TTL_MS,
|
|
14
14
|
DEFAULT_SOOTSIM_BRIDGE_PORT,
|
|
@@ -1116,7 +1116,7 @@ export class SootSimBridgeHost {
|
|
|
1116
1116
|
const claimed = claimDaemonLockfile(this.buildLockfileSnapshot())
|
|
1117
1117
|
if (!claimed) {
|
|
1118
1118
|
throw new Error(
|
|
1119
|
-
'another
|
|
1119
|
+
'another Peach daemon wrote the lockfile during startup — aborting',
|
|
1120
1120
|
)
|
|
1121
1121
|
}
|
|
1122
1122
|
} catch (err) {
|
package/src/runtime-assets.ts
CHANGED
|
@@ -138,11 +138,11 @@ const RUNTIME_VERSION_HOSTNAME_SUFFIX = '.runtime.localhost'
|
|
|
138
138
|
export function runtimeVersionHostname(version: string): string {
|
|
139
139
|
const trimmed = version.trim()
|
|
140
140
|
if (!isValidRuntimeVersion(trimmed)) {
|
|
141
|
-
throw new Error(`invalid
|
|
141
|
+
throw new Error(`invalid Peach runtime version: ${version}`)
|
|
142
142
|
}
|
|
143
143
|
const encoded = Buffer.from(trimmed, 'utf8').toString('hex')
|
|
144
144
|
const labels = encoded.match(/.{1,60}/g)
|
|
145
|
-
if (!labels) throw new Error(`invalid
|
|
145
|
+
if (!labels) throw new Error(`invalid Peach runtime version: ${version}`)
|
|
146
146
|
return `${labels.join('.')}${RUNTIME_VERSION_HOSTNAME_SUFFIX}`
|
|
147
147
|
}
|
|
148
148
|
|