peachsim 0.1.633 → 0.1.635

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/dist-lib/agent-daemon-client.cjs +3 -3
  2. package/dist-lib/agent-events.cjs +1 -1
  3. package/dist-lib/agent-identity.cjs +1 -1
  4. package/dist-lib/agent-sessions.cjs +1 -1
  5. package/dist-lib/attached-projects.cjs +1 -1
  6. package/dist-lib/auth/shared-session.cjs +1 -1
  7. package/dist-lib/backend-origin.cjs +1 -1
  8. package/dist-lib/beta.cjs +1 -1
  9. package/dist-lib/beta.mjs +1 -1
  10. package/dist-lib/bridge-constants.cjs +4 -4
  11. package/dist-lib/bridge-contract-input.cjs +1 -1
  12. package/dist-lib/bridge-contract-input.mjs +1 -1
  13. package/dist-lib/bridge-contract.cjs +1 -1
  14. package/dist-lib/bridge-contract.mjs +1 -1
  15. package/dist-lib/capture-contract.cjs +1 -1
  16. package/dist-lib/capture-contract.mjs +1 -1
  17. package/dist-lib/cli-constants.cjs +1 -1
  18. package/dist-lib/cloud-contract.cjs +1 -1
  19. package/dist-lib/cloud-contract.mjs +1 -1
  20. package/dist-lib/cloud-test-args.cjs +1 -1
  21. package/dist-lib/cloud-test-args.mjs +1 -1
  22. package/dist-lib/cloud.cjs +1 -1
  23. package/dist-lib/cloud.mjs +1 -1
  24. package/dist-lib/config.cjs +1 -1
  25. package/dist-lib/detox/index.cjs +1 -1
  26. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  27. package/dist-lib/home-paths.cjs +3 -3
  28. package/dist-lib/host/bridge-host.cjs +7 -7
  29. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  30. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  31. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  32. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  33. package/dist-lib/host/websocket-proxy.cjs +1 -1
  34. package/dist-lib/index.cjs +2 -2
  35. package/dist-lib/jump-to-source-babel.cjs +1 -1
  36. package/dist-lib/jump-to-source-native.cjs +1 -1
  37. package/dist-lib/kotlin-host.cjs +1 -1
  38. package/dist-lib/menu.cjs +1 -1
  39. package/dist-lib/menu.mjs +1 -1
  40. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  41. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  42. package/dist-lib/metro-production-bundle.cjs +1 -1
  43. package/dist-lib/metro-production-bundle.mjs +1 -1
  44. package/dist-lib/metro.cjs +1 -1
  45. package/dist-lib/native-app-identity.cjs +1 -1
  46. package/dist-lib/native-app-identity.mjs +1 -1
  47. package/dist-lib/profiles.cjs +1 -1
  48. package/dist-lib/public-brand.cjs +1 -1
  49. package/dist-lib/react-native-host-modules.cjs +1 -1
  50. package/dist-lib/react-native-host-modules.mjs +1 -1
  51. package/dist-lib/render-mode.cjs +1 -1
  52. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  53. package/dist-lib/sdk.cjs +1 -1
  54. package/dist-lib/sdk.mjs +1 -1
  55. package/dist-lib/skills.cjs +43 -41
  56. package/dist-lib/swift-compile.cjs +15 -4
  57. package/dist-lib/swift-compile.mjs +14 -4
  58. package/dist-lib/swift-package.cjs +1 -1
  59. package/dist-lib/swift-package.mjs +1 -1
  60. package/dist-lib/swift-submit.cjs +1 -1
  61. package/dist-lib/swift-submit.mjs +1 -1
  62. package/dist-lib/swift.cjs +2 -2
  63. package/dist-lib/vite-swift.cjs +13 -4
  64. package/dist-lib/vite.cjs +1 -1
  65. package/package.json +1 -1
  66. package/src/agent-daemon-client.ts +2 -2
  67. package/src/bridge-constants.ts +3 -3
  68. package/src/connect.ts +1 -1
  69. package/src/disk-cleanup.ts +1 -1
  70. package/src/home-paths.ts +2 -2
  71. package/src/host/bridge-host.ts +2 -2
  72. package/src/runtime-assets.ts +2 -2
  73. package/src/skills/builtin/compat-check.ts +2 -2
  74. package/src/swift-compile.ts +22 -3
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.633 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.635 | (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). peach runs those against a synthetic native app record."
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. peach backs both with a real getUserMedia preview and canvas photo capture."
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 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.",
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 peach RNTPortalView/RNTPortalHostView custom elements",
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; peach supplies the ScreenChoreographyView host and ScreenChoreographyPreparation TurboModule used by version 0.5's presentation and two-frame layout handshakes",
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; peach keeps the live overlay subtree visible for those two frames because the canvas host has no synchronous subtree snapshot API"
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 with evented simulator speech completion.",
6474
- working: 'upstream speak/getAvailableVoicesAsync/isSpeakingAsync/stop/pause/resume/maxSpeechInputLength exports run unchanged; requireNativeModule("ExpoSpeech") provides speak, getVoices, stop, pause, resume, isSpeaking, and started/done/stopped event callbacks',
6475
- missing: "no audible AVSpeechSynthesizer or browser speechSynthesis from the tenant worker; voices list is empty and boundary/error events do not fire"
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 peach ContextMenu",
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 package surface backed by browser speechSynthesis when available, with native-shaped events and validation",
6884
- working: "default Tts instance, getInitStatus, requestInstallEngine/Data, setDucking, setDefaultVoice/Rate/Pitch/Language, setIgnoreSilentSwitch, voices, engines, speak, stop, pause, resume, add/remove event listeners",
6885
- missing: "AVAudioSession silent-switch behavior, exact AVSpeechSynthesizer voice catalog, and guaranteed audible speech in runtimes without browser speechSynthesis"
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: "observable sensor streams with browser DeviceMotion/DeviceOrientation wiring and deterministic fallback samples",
6923
- working: "SensorTypes, accelerometer/gyroscope/magnetometer/barometer/orientation/gravity observables, subscribe/unsubscribe, pipe pass-through, setUpdateIntervalForType, setLogLevelForType",
6924
- missing: "real native CoreMotion pressure/magnetometer availability, RxJS Observable internals beyond subscribe/pipe, permission prompts, high-frequency continuous native sampling in worker-only runtimes"
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). audio: the ExponentAV native module keeps the web-ported element-keyed sound and recorder 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.",
7675
- working: "Audio.Sound (createAsync/loadAsync/unloadAsync/play/pause/stop/seek/setRate/setVolume/setMuted/setLooping/setProgressUpdateInterval/setOnPlaybackStatusUpdate via element-keyed seam), 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 via DeviceEventEmitter, RecordingOptionsPresets, PitchCorrectionQuality enum (Low/Medium/High), ResizeMode",
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, sound keys are elements where iOS uses numbers, shouldDuckAndroid / playThroughEarpieceAndroid ignored"
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 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.'
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 (its JS stub was dropped in 0a4ce9faf0 for omitting EventPlugin). the AnalyticsReactNative native module is absent and the SDK degrades without it, so createClient and track complete normally. UNLIKE the analytics SDKs sootsim does intercept, delivery is NOT suppressed here: a configured writeKey reaches the network from the preview.",
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 AnalyticsReactNative native module \u2014 device/app context fields it would supply fall back to defaults"
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 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.",
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 provides constants, configuration state, control methods, and codegen event emitters",
13340
- working: "configure, reset, speak, stop, pause, resume, getSpeechStatus, speechStarted/speechRangeDetected/speechFinished/speechStopped/speechPaused/speechResumed/speechError emitters",
13341
- missing: "real AVSpeechSynthesizer audio and platform voice availability when browser speechSynthesis is unavailable in the worker"
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 peach's generic native seam",
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 peach websocket proxy page URL: ${input.href}`);
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 peach websocket proxy target URL: ${input.targetUrl}`);
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 peach websocket proxy target URL: ${input.targetUrl}`);
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 peach daemon claimed the lockfile before this write");
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 peach daemon lockfile");
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 peach runtime version: ${version}`);
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 peach runtime version: ${version}`);
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 peach daemon wrote the lockfile during startup \u2014 aborting"
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 peach",
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 peach compatibility",
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.633 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.635 | (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/v1
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.633 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.635 | (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/v1
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.633 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.635 | (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.633 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.635 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/swift-package.ts
4
4
  function isSwiftManifestFile(file) {
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.633 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.635 | (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.633 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.635 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/swift-submit.ts
4
4
  var SWIFT_COMPILE_PATH = "/api/swift-compile";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.633 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.635 | (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 peach renders per iphone point (high = device native, medium = 2, low = on-screen pixels capped at native)",
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
  },
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.633 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.635 | (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/v1
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.633 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.635 | (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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "peachsim",
3
- "version": "0.1.633",
3
+ "version": "0.1.635",
4
4
  "description": "Vite and Metro plugins, testing drivers, and SDK exports for peach.",
5
5
  "author": "Tamagui LLC",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -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 peach daemon on port ${this.port}: ${err.message}`,
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 peach daemon on port ${port} but it did not come up in time. ` +
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
  )
@@ -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 peach websocket proxy page URL: ${input.href}`)
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 peach websocket proxy target URL: ${input.targetUrl}`)
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 peach websocket proxy target URL: ${input.targetUrl}`)
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 peach daemon or dev shell running?`)
88
+ throw new SimConnectError(`${message} — is the Peach daemon or dev shell running?`)
89
89
  }
90
90
  discovery.close()
91
91
 
@@ -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 peach data home: ${target}`)
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 peach daemon claimed the lockfile before this write')
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 peach daemon lockfile')
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')
@@ -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 peach daemon wrote the lockfile during startup — aborting',
1119
+ 'another Peach daemon wrote the lockfile during startup — aborting',
1120
1120
  )
1121
1121
  }
1122
1122
  } catch (err) {
@@ -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 peach runtime version: ${version}`)
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 peach runtime version: ${version}`)
145
+ if (!labels) throw new Error(`invalid Peach runtime version: ${version}`)
146
146
  return `${labels.join('.')}${RUNTIME_VERSION_HOSTNAME_SUFFIX}`
147
147
  }
148
148