stim 1.9.0 → 1.10.1

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 (83) hide show
  1. package/dist/{android-_y4Ohi5z.mjs → android-787HhP5w.mjs} +119 -29
  2. package/dist/{android-BPGizezh.mjs → android-Bu4mbDzc.mjs} +168 -95
  3. package/dist/{android-DEgo4oCo.mjs → android-DPov-fv2.mjs} +2 -2
  4. package/dist/{android-cas-eiExNLf7.mjs → android-cas-CITmIeWY.mjs} +9 -8
  5. package/dist/android-cas-compiler.mjs +1 -1
  6. package/dist/{app-install-Uf3a83Tv.mjs → app-install-Cfmqr3TQ.mjs} +2 -2
  7. package/dist/budget-nDCEwtJv.mjs +620 -0
  8. package/dist/build-progress-BXx-ZBe4.mjs +512 -0
  9. package/dist/{cache-manifest-Dg7OnMrp.mjs → cache-manifest-Pubfp8wV.mjs} +1 -1
  10. package/dist/cache-manifest.mjs +1 -1
  11. package/dist/cli.mjs +16 -16
  12. package/dist/collector-run.d.mts +5 -1
  13. package/dist/collector-run.mjs +7 -7
  14. package/dist/{command-output-gByVmIjy.mjs → command-output-D5z2_bcF.mjs} +1 -1
  15. package/dist/{config-Cp9lM3wX.mjs → config-BEq0Qw_a.mjs} +14 -131
  16. package/dist/{dependency-state-Bq5DcLGn.mjs → dependency-state-r9UesA9a.mjs} +2 -2
  17. package/dist/{deps-Cip5vUm1.mjs → deps-DP4eWqea.mjs} +3 -3
  18. package/dist/{detached-entry-KEu0_AXL.mjs → detached-entry-DJHoca49.mjs} +1 -1
  19. package/dist/{dev-client-HyqISM0h.mjs → dev-client-DExzPiOa.mjs} +137 -250
  20. package/dist/{device-D4U-xLty.mjs → device-Czh5kO8A.mjs} +7 -7
  21. package/dist/{build-lock-DPXPLgTc.mjs → device-lease-CbEaIk7b.mjs} +370 -12
  22. package/dist/{device-pool-CnTAz8X1.mjs → device-pool-BBWLAr55.mjs} +4 -4
  23. package/dist/{device-remote-AQ5rQPqr.mjs → device-remote-powUHdbK.mjs} +547 -468
  24. package/dist/{doctor-B_Ei3bZu.mjs → doctor-CmqK1LcQ.mjs} +58 -22
  25. package/dist/{error-diagnostics-Vfz83GCF.mjs → error-diagnostics-xxWKNO3-.mjs} +11 -12
  26. package/dist/{exec-jIAlgilk.mjs → exec-DK8KaVHK.mjs} +3 -2
  27. package/dist/{gc-Ckw8RQHi.mjs → gc-zCDpmdHU.mjs} +500 -1114
  28. package/dist/{guide-BiAbhs1J.mjs → guide-DwmaD_Wa.mjs} +882 -528
  29. package/dist/guide-status-CWvti2Lg.mjs +125 -0
  30. package/dist/idle--jn7pBNe.mjs +157 -0
  31. package/dist/in-use-CNIWU-r-.mjs +245 -0
  32. package/dist/{ios-BL2NFckr.mjs → ios-COGcGEcN.mjs} +39 -65
  33. package/dist/{ios-BzUJWk1K.mjs → ios-CbdqTqOc.mjs} +130 -89
  34. package/dist/{ios-device-DPsSm0v_.mjs → ios-device-BiOsSVzd.mjs} +1 -1
  35. package/dist/{ios-device-D972i9wf.mjs → ios-device-DNjPXBnb.mjs} +3 -3
  36. package/dist/{launch-verify-Q_OtW1Rf.mjs → launch-verify-BhgkYAws.mjs} +5 -5
  37. package/dist/{logs-CI9NQSK7.mjs → logs-MARIy6m9.mjs} +9 -9
  38. package/dist/{metro-DrLHaMn2.mjs → metro-BWLOJ_Wr.mjs} +116 -10
  39. package/dist/{named-ports-CmLQSIRj.mjs → named-ports-DiTfSz6p.mjs} +4 -4
  40. package/dist/{ndjson-9uFNRwfe.mjs → ndjson-CDY9IkVC.mjs} +3 -56
  41. package/dist/{ndjson-DvHSsNU9.d.mts → ndjson-Du3j0AQ9.d.mts} +1 -0
  42. package/dist/ownership-BfPNRf3-.mjs +1180 -0
  43. package/dist/{ownership-D15Op8vN.mjs → ownership-D2xbLVoz.mjs} +2 -3
  44. package/dist/{ports-BNKoWVWZ.mjs → ports-CLSSFOuz.mjs} +3 -3
  45. package/dist/{project-DS112DYB.mjs → project-BXZzOABt.mjs} +2 -2
  46. package/dist/{reload-ZNJUo1pl.mjs → reload-CymyF6Kk.mjs} +9 -10
  47. package/dist/{server-bare-DWkkcIxV.mjs → server-bare-DVbb7kXH.mjs} +1 -1
  48. package/dist/{server-expo-B_lctBR3.mjs → server-expo-BvOCeakp.mjs} +4 -4
  49. package/dist/server-expo-DBVTdult.mjs +2 -0
  50. package/dist/{settings-D030k0t4.mjs → settings-DOugPlPz.mjs} +16 -428
  51. package/dist/{settings-BKNh5rl4.mjs → settings-EWYNwe72.mjs} +16 -14
  52. package/dist/settings.schema.json +75 -0
  53. package/dist/{simslim-B_LsGLuJ.mjs → simslim-DZUxzsjq.mjs} +182 -5
  54. package/dist/{slot-launch-DU9A-gYw.mjs → slot-launch-Dk4oTREM.mjs} +4 -4
  55. package/dist/{spawn-claims-Dn3C_N6w.mjs → spawn-claims-CUleC2cM.mjs} +1 -1
  56. package/dist/{start-DYkkKF0s.mjs → start-RbmFPeZ7.mjs} +147 -98
  57. package/dist/start-qWapeB4W.mjs +2 -0
  58. package/dist/{state-NcJzMEBF.mjs → state-WGdIbi_d.mjs} +2 -2
  59. package/dist/{stats-DG9e66Rz.mjs → stats-BAgJaLA4.mjs} +1 -1
  60. package/dist/{stats-B63-JVAY.mjs → stats-DBYJ5bxL.mjs} +4 -4
  61. package/dist/status-Dr4fRkym.mjs +216 -0
  62. package/dist/{status-S6ehL4Ui.mjs → status-Zp8kvexe.mjs} +63 -231
  63. package/dist/{guide-status-BAMVU0ZA.mjs → stim-installations-CINXy_su.mjs} +3 -124
  64. package/dist/{stop-T1R-cZRz.mjs → stop-DI4BG4Os.mjs} +2 -2
  65. package/dist/{stop-BO28HGqF.mjs → stop-DcEv5sk-.mjs} +22 -18
  66. package/dist/supervisor-run.d.mts +11 -2
  67. package/dist/supervisor-run.mjs +185 -17
  68. package/dist/{workspace-process-lock-DWaiRD0e.mjs → workspace-process-lock-BXA96myD.mjs} +2 -2
  69. package/dist/workspaces-wrH6dXfu.mjs +1003 -0
  70. package/dist/{worktree-LGB-UwgG.mjs → worktree-Bd4dRvx7.mjs} +40 -122
  71. package/dist/{worktree-R_cUlE7s.mjs → worktree-BlizKDpZ.mjs} +143 -18
  72. package/dist/{worktree-DKhSF0UX.mjs → worktree-DEG2o9F8.mjs} +1 -1
  73. package/dist/{xcode-BZqyxh3e.mjs → xcode-B2tBkf0m.mjs} +9 -158
  74. package/package.json +6 -5
  75. package/dist/build-progress-CVqkfPC6.mjs +0 -188
  76. package/dist/device-lease-Crs-HkJY.mjs +0 -366
  77. package/dist/logs-query-Cqma3WIu.mjs +0 -298
  78. package/dist/ownership-DCQPuWEc.mjs +0 -489
  79. package/dist/public-http-probe-CyMDrQ3c.mjs +0 -61
  80. package/dist/server-expo-CeILEu86.mjs +0 -2
  81. package/dist/sim-pool-KaIsp2Ft.mjs +0 -723
  82. package/dist/spawn-entry-nCE6m770.mjs +0 -14
  83. package/dist/workspace-state-DF2gCFhx.mjs +0 -169
@@ -1,33 +1,34 @@
1
- import { G as parseDeviceSlotOption, H as deviceSlotKey, J as validateDeviceSlot, S as setDevice, T as withConfigLock, U as deviceSlotPlatforms, V as deviceSlotFileKey, f as getProject, g as loadConfig, k as ownership_claim_exports, l as getConcurrencyLimits, w as upsertProject, x as saveConfig } from "./config-Cp9lM3wX.mjs";
2
- import { t as getExecutor } from "./exec-jIAlgilk.mjs";
3
- import { r as createNdjsonWriter } from "./ndjson-9uFNRwfe.mjs";
4
- import { _ as workspaceDir, b as workspaceLogsDir, c as writeWorkspaceState, i as recordWorkspaceUse, l as emulatorLogFile, r as readWorkspaceState } from "./workspace-state-DF2gCFhx.mjs";
5
- import { E as removeTemporaryEntry, T as makeTemporaryDirectory, _ as repoRoot, s as gitCommonDir } from "./worktree-R_cUlE7s.mjs";
6
- import { a as detectIsExpo, i as detectBundleId, l as projectShortcut, n as appProjectProblem, o as findProjectRoot, r as detectAndroidPackage } from "./project-DS112DYB.mjs";
7
- import { n as MODE_EXPO, p as writeWorkspaceLaunch, t as MODE_BARE } from "./state-NcJzMEBF.mjs";
1
+ import { L as deviceSlotFileKey, R as deviceSlotKey, S as setDevice, T as withConfigLock, V as parseDeviceSlotOption, W as validateDeviceSlot, f as getProject, g as loadConfig, k as ownership_claim_exports, l as getConcurrencyLimits, w as upsertProject, x as saveConfig, z as deviceSlotPlatforms } from "./config-BEq0Qw_a.mjs";
2
+ import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
3
+ import { r as createNdjsonWriter } from "./ndjson-CDY9IkVC.mjs";
4
+ import { O as workspaceDir, b as emulatorLogFile, c as signalProcessTree, h as recordWorkspaceUse, i as pidExists, j as workspaceLogsDir, m as readWorkspaceState, s as resolveProjectMetro, y as writeWorkspaceState } from "./metro-BWLOJ_Wr.mjs";
5
+ import { D as makeTemporaryDirectory, O as removeTemporaryEntry, s as gitCommonDir, y as repoRoot } from "./worktree-BlizKDpZ.mjs";
6
+ import { a as detectIsExpo, i as detectBundleId, l as projectShortcut, n as appProjectProblem, o as findProjectRoot, r as detectAndroidPackage } from "./project-BXZzOABt.mjs";
7
+ import { n as MODE_EXPO, p as writeWorkspaceLaunch, t as MODE_BARE } from "./state-WGdIbi_d.mjs";
8
+ import { t as withWorkspaceProcessLock } from "./workspace-process-lock-BXA96myD.mjs";
8
9
  import { r as waitForChild, t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
9
- import { a as pidExists, c as resolveProjectMetro, l as signalProcessTree } from "./metro-DrLHaMn2.mjs";
10
- import { n as verifyCollectorOwnership, r as readCollectors } from "./ownership-D15Op8vN.mjs";
11
- import { A as settingFile, E as remoteAndroidSetting, F as unknownSettingKeys, J as optimizationBuildProfile, K as artifactCachePolicy, L as REMOTE_DEVICE_BACKENDS, M as settingShapeErrors, O as resolveCacheProviderConfig, P as tunnelModeSetting, W as detectProviders, Y as resolveOptimizations, b as metroWarmupUrlSetting, i as SETTING_SHAPE_REMEDY, k as resolveSettings, l as androidDataPartitionSizeGbSettingError, o as androidAvdConfigSettingError, q as compilerCacheFallbackMessage, u as cacheProviderSettingError, w as publicUrlSetting } from "./settings-D030k0t4.mjs";
12
- import { C as listAdbDevices, D as memoizeEmulatorProbe, H as waitForBoot, I as probeEmulatorSerial, L as resetAdoptedAvd, P as physicalDeviceModel, R as resolveOwnedAvdSerial, T as listInstalledSystemImages, _ as emulatorDiskSpaceRemedy, a as androidPoolNoCandidatesRefusal, b as findBuildTool, i as androidPoolCandidates, n as androidDeviceAbi, o as androidSystemImageAbi, r as androidHome, s as androidToolCwd, t as androidBuildToolName, v as emulatorFailureRemedy, y as extractEmulatorFailure, z as resolvePhysicalDevice } from "./android-_y4Ohi5z.mjs";
13
- import { _ as stepTimer, c as launchErrorReport, f as refuseNoProject, g as stepClock, i as formatDuration, l as phaseLine, m as shortHash, n as appReadinessMessage, v as launchErrorPreview } from "./command-output-gByVmIjy.mjs";
14
- import { C as assetDiffReason, E as readAssetManifest, S as untrackedNativeFiles, T as compareAssetManifests, _ as refingerprintAfterMutation, a as waitForBuild, b as storedAssetManifest, c as describeFingerprintMiss, d as fingerprintDiffRecord, f as fingerprintDiffSuffix, g as providerUploadOutcome, h as providerDownloadPath, m as prepareProviderDownloadDir, o as waitForSharedBuild, p as fingerprintProject, r as releaseBuildLock, s as buildCacheKey, t as acquireBuildLock, u as filesystemBuildCapability, v as resolveBuild, w as captureAssetManifest, x as untrackedMissLine, y as storeBuild } from "./build-lock-DPXPLgTc.mjs";
15
- import { t as cleanLine } from "./server-expo-B_lctBR3.mjs";
16
- import { S as uploadRemote, _ as loadProjectProvider, b as resolveEasCliBin, d as UPLOAD_TIMEOUT_MS, f as cacheLevel, g as isEasAuthFailureText, h as exitAfterFlush, m as easAuthNote, o as parkedMaxSetting, p as checkEasAuth, u as RESOLVE_TIMEOUT_MS, x as resolveRemote } from "./sim-pool-KaIsp2Ft.mjs";
17
- import { C as isEasBuildFailure, _ as noMetroMessage, c as ensureBooted, d as AvdRecoveryError, g as launchOutcomeRecord, h as isPhysicalDeviceRequest, i as detectEntryFile, l as ensureOwnedDevice, n as pickDevClientScheme, o as needsPrebuild, p as ensureWorkspaceStorageSafely, s as runPrebuild, t as devClientScheme, u as AvdBootError, v as noMetroRemedy, w as resolveEasDevelopmentBuild, x as warmMetro, y as resolveMetroWithRetry } from "./dev-client-HyqISM0h.mjs";
18
- import { t as withWorkspaceProcessLock } from "./workspace-process-lock-DWaiRD0e.mjs";
19
- import { n as NO_BUILD_PROGRESS, s as startBuildProgress } from "./build-progress-CVqkfPC6.mjs";
20
- import { a as VERIFY_TIMEOUT_MS, d as verifyLaunch, i as RELEASE_VERIFY_WAIT_MS, l as unverifiedLaunchLines, n as LAUNCH_FATAL, r as LAUNCH_UNVERIFIED, t as LAUNCH_BUNDLING, u as verifyAndroidReleaseLaunch } from "./launch-verify-Q_OtW1Rf.mjs";
21
- import { _ as launchAndroidReleaseApp, d as deviceShellArg, f as installAndroidApp, g as launchAndroidApp, o as androidAppProcess, p as installConflictKind, r as DEFAULT_METRO_PORT, s as androidDevClientUrl, t as ADB_INSTALL_TIMEOUT_MS } from "./app-install-Uf3a83Tv.mjs";
22
- import { a as lostLine, c as releaseLeaseOnSignal, i as leaseExpiryText, l as runLease, n as DEBUG_VERIFY_STEP_MS, o as lostRefusal, r as acquireRunLease, s as parseDeviceWait, t as selectFromPool, u as waitFlagConflict } from "./device-pool-CnTAz8X1.mjs";
23
- import { d as startBuildHeartbeat, f as tailLines, g as acquireBuildSlot, n as HEARTBEAT_INTERVAL_MS, v as releaseBuildSlot } from "./xcode-BZqyxh3e.mjs";
24
- import { a as statsProjectKey, i as recordRunStats, n as readRunEstimates, t as createRunRecorder } from "./stats-DG9e66Rz.mjs";
25
- import { o as unknownAndroidSystemImageRefusal, r as checkDeviceCapacity } from "./simslim-B_LsGLuJ.mjs";
26
- import { a as ensureMetroReachable, b as ownedSessionName, l as resolveRemoteContext, n as binOnPath, o as ensureRemoteBootOwned, s as remoteAndroidDeps } from "./device-remote-AQ5rQPqr.mjs";
27
- import { a as buildAndroid, c as CCACHE_NOT_RUN, f as resolveCcache, l as CCACHE_UNAVAILABLE, n as resolveAndroidCas, o as productFlavorRefusal, p as formatDiagnostic, r as resolveAndroidCompilerCache, s as readProductFlavors, u as ccacheActivityLine } from "./android-cas-eiExNLf7.mjs";
28
- import { n as nativeRunCommand, t as launchSlotScope } from "./slot-launch-DU9A-gYw.mjs";
29
- import { t as spawnEntry } from "./spawn-entry-nCE6m770.mjs";
30
- import { a as printNativeCrashReport, r as captureNativeCrashes, t as errorDiagnostics } from "./error-diagnostics-Vfz83GCF.mjs";
10
+ import { _ as stepTimer, c as launchErrorReport, f as refuseNoProject, g as stepClock, i as formatDuration, l as phaseLine, m as shortHash, n as appReadinessMessage, v as launchErrorPreview } from "./command-output-D5z2_bcF.mjs";
11
+ import { A as resolveBuild, C as fingerprintDiffRecord, D as providerDownloadPath, E as prepareProviderDownloadDir, F as assetDiffReason, I as captureAssetManifest, L as compareAssetManifests, M as storedAssetManifest, N as untrackedMissLine, O as providerUploadOutcome, P as untrackedNativeFiles, R as readAssetManifest, S as filesystemBuildCapability, T as fingerprintProject, _ as waitForBuild, b as describeFingerprintMiss, g as releaseBuildLock, j as storeBuild, k as refingerprintAfterMutation, m as acquireBuildLock, v as waitForSharedBuild, w as fingerprintDiffSuffix, y as buildCacheKey } from "./device-lease-CbEaIk7b.mjs";
12
+ import { n as NO_BUILD_PROGRESS, s as startBuildProgress } from "./build-progress-BXx-ZBe4.mjs";
13
+ import { B as resolvePhysicalDevice, E as listInstalledSystemImages, F as physicalDeviceModel, L as probeEmulatorSerial, O as memoizeEmulatorProbe, R as resetAdoptedAvd, W as waitForBoot, _ as emulatorDiskSpaceRemedy, a as androidPoolNoCandidatesRefusal, b as findBuildTool, i as androidPoolCandidates, n as androidDeviceAbi, o as androidSystemImageAbi, r as androidHome, s as androidToolCwd, t as androidBuildToolName, v as emulatorFailureRemedy, w as listAdbDevices, y as extractEmulatorFailure, z as resolveOwnedAvdSerial } from "./android-787HhP5w.mjs";
14
+ import { A as resolveCacheProviderConfig, E as publicUrlSetting, H as compilerCacheFallbackMessage, I as tunnelModeSetting, L as unknownSettingKeys, M as settingFile, O as remoteAndroidSetting, P as settingShapeErrors, S as metroWarmupUrlSetting, U as optimizationBuildProfile, V as artifactCachePolicy, W as resolveOptimizations, a as SETTING_SHAPE_REMEDY, d as cacheProviderSettingError, j as resolveSettings, r as REMOTE_DEVICE_BACKENDS, s as androidAvdConfigSettingError, u as androidDataPartitionSizeGbSettingError, z as detectProviders } from "./settings-DOugPlPz.mjs";
15
+ import { y as parkedMaxSetting } from "./ownership-BfPNRf3-.mjs";
16
+ import { a as acquireBuildSlot, s as releaseBuildSlot } from "./in-use-CNIWU-r-.mjs";
17
+ import { n as verifyCollectorOwnership, r as readCollectors } from "./ownership-D2xbLVoz.mjs";
18
+ import { t as cleanLine } from "./server-expo-BvOCeakp.mjs";
19
+ import { A as UPLOAD_TIMEOUT_MS, B as resolveRemote, F as isEasAuthFailureText, I as loadProjectProvider, M as checkEasAuth, N as easAuthNote, P as exitAfterFlush, V as uploadRemote, a as ensureMetroReachable, c as remoteAndroidDeps, j as cacheLevel, k as RESOLVE_TIMEOUT_MS, n as binOnPath, o as ensureRemoteBootOwned, u as resolveRemoteContext, w as ownedSessionName, z as resolveEasCliBin } from "./device-remote-powUHdbK.mjs";
20
+ import { _ as launchAndroidReleaseApp, d as deviceShellArg, f as installAndroidApp, g as launchAndroidApp, o as androidAppProcess, p as installConflictKind, r as DEFAULT_METRO_PORT, s as androidDevClientUrl, t as ADB_INSTALL_TIMEOUT_MS } from "./app-install-Cfmqr3TQ.mjs";
21
+ import { a as VERIFY_TIMEOUT_MS, d as verifyLaunch, i as RELEASE_VERIFY_WAIT_MS, l as unverifiedLaunchLines, n as LAUNCH_FATAL, r as LAUNCH_UNVERIFIED, t as LAUNCH_BUNDLING, u as verifyAndroidReleaseLaunch } from "./launch-verify-BhgkYAws.mjs";
22
+ import { d as isEasBuildFailure, f as resolveEasDevelopmentBuild, o as unknownAndroidSystemImageRefusal, r as checkDeviceCapacity } from "./simslim-DZUxzsjq.mjs";
23
+ import { a as lostLine, c as releaseLeaseOnSignal, i as leaseExpiryText, l as runLease, n as DEBUG_VERIFY_STEP_MS, o as lostRefusal, r as acquireRunLease, s as parseDeviceWait, t as selectFromPool, u as waitFlagConflict } from "./device-pool-BBWLAr55.mjs";
24
+ import { _ as isPhysicalDeviceRequest, b as warmMetro, c as runPrebuild, d as ensureOwnedDevice, f as AvdBootError, g as ensureWorkspaceStorageSafely, h as ensureDevServer, i as detectEntryFile, l as staleNativeDirRefusal, n as pickDevClientScheme, o as planPrebuild, p as AvdRecoveryError, s as recordPrebuild, t as devClientScheme, u as ensureBooted, v as launchOutcomeRecord } from "./dev-client-DExzPiOa.mjs";
25
+ import { t as budgetGate } from "./budget-nDCEwtJv.mjs";
26
+ import { f as spawnEntry, s as startDevServer } from "./start-RbmFPeZ7.mjs";
27
+ import { a as statsProjectKey, i as recordRunStats, n as readRunEstimates, t as createRunRecorder } from "./stats-BAgJaLA4.mjs";
28
+ import { a as buildAndroid, c as CCACHE_NOT_RUN, f as resolveCcache, l as CCACHE_UNAVAILABLE, n as resolveAndroidCas, o as productFlavorRefusal, p as formatDiagnostic, r as resolveAndroidCompilerCache, s as readProductFlavors, u as ccacheActivityLine } from "./android-cas-CITmIeWY.mjs";
29
+ import { d as startBuildHeartbeat, f as tailLines, n as HEARTBEAT_INTERVAL_MS } from "./xcode-B2tBkf0m.mjs";
30
+ import { n as nativeRunCommand, t as launchSlotScope } from "./slot-launch-Dk4oTREM.mjs";
31
+ import { a as printNativeCrashReport, r as captureNativeCrashes, t as errorDiagnostics } from "./error-diagnostics-xxWKNO3-.mjs";
31
32
  import { constants, copyFileSync, existsSync, mkdirSync, openSync, readFileSync, readdirSync, renameSync, rmSync } from "node:fs";
32
33
  import { InvalidArgumentError } from "commander";
33
34
  import { basename, dirname, isAbsolute, join, relative } from "node:path";
@@ -438,7 +439,6 @@ function systemImageRefusal({ slot, flag, resolved, physical, remoteBackend, lis
438
439
  function isReleaseVariant(variant) {
439
440
  return typeof variant === "string" && /release$/i.test(variant.trim());
440
441
  }
441
- const NO_METRO = "STIM_NO_METRO";
442
442
  const NO_FINGERPRINT = "STIM_NO_FINGERPRINT";
443
443
  const NO_DEVICE = "STIM_NO_DEVICE";
444
444
  const LAUNCH_FAILED = "STIM_LAUNCH_FAILED";
@@ -644,7 +644,7 @@ function fail$1(code, message, remedy, extra = {}) {
644
644
  extra
645
645
  };
646
646
  }
647
- async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo, device, physical, buildPlan, cacheProviderConfig, requestedBuildCache, easBuild, androidPackage: initialPackage, record, maxBuilds, progress }, { deviceAbi, fingerprint, untracked, resolveCached, storeCached, storedAssets, captureAssets, acquireLock, releaseLock, waitForBuild, loadProvider, easAuth, resolveRemoteBuild, uploadRemoteBuild, loadCacheProviderModule, acquireSlot, releaseSlot, needsPrebuildFor, prebuild, build, ccacheFor, swapApk, readState, now }) {
647
+ async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo, device, physical, buildPlan, cacheProviderConfig, requestedBuildCache, easBuild, androidPackage: initialPackage, record, maxBuilds, progress }, { deviceAbi, fingerprint, untracked, resolveCached, storeCached, storedAssets, captureAssets, acquireLock, releaseLock, waitForBuild, loadProvider, easAuth, resolveRemoteBuild, uploadRemoteBuild, loadCacheProviderModule, acquireSlot, releaseSlot, planPrebuildFor, prebuild, build, ccacheFor, swapApk, readState, now }) {
648
648
  const { phase, out, estimates, stats, step } = progress;
649
649
  const { variant, release, profile: buildProfile, cas, cache: cachePolicy } = buildPlan;
650
650
  const useBuildCache = cachePolicy.read;
@@ -926,9 +926,23 @@ async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo
926
926
  }
927
927
  phase("build", chalk.yellow(`could not take a build slot: ${err?.message || err}; building anyway`));
928
928
  }
929
- if (needsPrebuildFor(root, "android", isExpo)) {
929
+ const prebuildPlan = planPrebuildFor(root, PLATFORM, {
930
+ isExpo,
931
+ fingerprint: hash,
932
+ sources: fingerprintSources
933
+ });
934
+ if (prebuildPlan === "refuse") {
935
+ const refusal = staleNativeDirRefusal(PLATFORM);
936
+ phaseFailure = fail$1(refusal.code, refusal.message, refusal.remedy, { lastBuildStatus: true });
937
+ return false;
938
+ }
939
+ if (prebuildPlan === "generate" || prebuildPlan === "regenerate") {
930
940
  step("prebuild");
931
- const pre = await prebuild(root, PLATFORM, writer, { isExpo });
941
+ recordPrebuild(root, PLATFORM, null);
942
+ const pre = await prebuild(root, PLATFORM, writer, {
943
+ isExpo,
944
+ clean: prebuildPlan === "regenerate"
945
+ });
932
946
  if (pre.failed) {
933
947
  phaseFailure = fail$1(pre.code, pre.reason, pre.remedy, {
934
948
  lastBuildStatus: true,
@@ -937,8 +951,8 @@ async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo
937
951
  });
938
952
  return false;
939
953
  }
940
- phase("prebuild", `android/ generated (${formatDuration(pre.durationMs)})`);
941
- androidPackage = androidPackage || detectAndroidPackage(root);
954
+ phase("prebuild", `${prebuildPlan === "generate" ? "android/ generated" : "android/ not generated from this fingerprint -> regenerated with --clean"} (${formatDuration(pre.durationMs)})`);
955
+ androidPackage = detectAndroidPackage(root) || androidPackage;
942
956
  record.bundleId = androidPackage;
943
957
  const after = await refingerprintAfterMutation({
944
958
  projectRoot: root,
@@ -946,6 +960,7 @@ async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo
946
960
  previousHash: hash,
947
961
  fingerprint
948
962
  });
963
+ if (after) recordPrebuild(root, PLATFORM, after.hash);
949
964
  if (after?.moved) {
950
965
  storeHash = after.hash;
951
966
  storeSources = after.sources;
@@ -1100,7 +1115,7 @@ function tail(lines, n = FALLBACK_LINES) {
1100
1115
  }
1101
1116
  //#endregion
1102
1117
  //#region src/commands/android/result.ts
1103
- function androidFacts({ slot, serial, avdName = null, deviceName = null, systemImage = null, fingerprint, cacheKey = null, variant = null, metroPort = null, cacheHit, cacheSkipped = false, waitedForBuild = null, appPath, bundleId, installSkipped = false, launched, ccache = CCACHE_UNAVAILABLE, logs, debugHttpHost = null, debugHttpHostNote = null, devClientUrl = null, durationMs, lease }) {
1118
+ function androidFacts({ slot, serial, avdName = null, deviceName = null, systemImage = null, fingerprint, cacheKey = null, variant = null, metroPort = null, cacheHit, cacheSkipped = false, waitedForBuild = null, appPath, bundleId, installSkipped = false, launched, ccache = CCACHE_UNAVAILABLE, logs, debugHttpHost = null, debugHttpHostNote = null, devClientUrl = null, durationMs, lease, devServer = null }) {
1104
1119
  return {
1105
1120
  platform: PLATFORM,
1106
1121
  ...slot && slot !== "default" ? { slot } : {},
@@ -1128,7 +1143,8 @@ function androidFacts({ slot, serial, avdName = null, deviceName = null, systemI
1128
1143
  devClientUrl: devClientUrl ?? null,
1129
1144
  logs: logs ?? null,
1130
1145
  durationMs: typeof durationMs === "number" && Number.isFinite(durationMs) ? durationMs : null,
1131
- ...lease === void 0 ? {} : { lease }
1146
+ ...lease === void 0 ? {} : { lease },
1147
+ ...devServer ? { devServer } : {}
1132
1148
  };
1133
1149
  }
1134
1150
  function lastBuildRecord({ fingerprint, cacheKey, cacheHit, cacheSkipped = false, durationMs, appPath, bundleId, startedAt, status, errorCode = null, avdName = null, deviceName = null }) {
@@ -1166,7 +1182,7 @@ async function finishAndroidUpload(uploadPending, remote, phase) {
1166
1182
  }
1167
1183
  return false;
1168
1184
  }
1169
- function reportAndroidResult({ slot, json, useBuildCache, variant, release, metroCheck, metroPort, logsDir, serial, apkPath, androidPackage, installSkipped, record, waitedForBuild, remote, providerName, launchState, launchWarning, launched, ccache, durationMs, writer, emit, lease, recordRun }) {
1185
+ function reportAndroidResult({ slot, json, useBuildCache, variant, release, metroCheck, metroPort, logsDir, serial, apkPath, androidPackage, installSkipped, record, waitedForBuild, remote, providerName, launchState, launchWarning, launched, ccache, durationMs, writer, emit, lease, recordRun, reclaimed = [], devServer = null }) {
1170
1186
  recordRun({
1171
1187
  failed: false,
1172
1188
  cacheHit: cacheLevel(record.cacheHit),
@@ -1196,16 +1212,20 @@ function reportAndroidResult({ slot, json, useBuildCache, variant, release, metr
1196
1212
  ccache,
1197
1213
  logs: logsDir,
1198
1214
  durationMs,
1199
- lease
1215
+ lease,
1216
+ devServer
1200
1217
  });
1201
1218
  writer.close();
1202
- if (json) emit(JSON.stringify(facts));
1219
+ if (json) emit(JSON.stringify(reclaimed.length ? {
1220
+ ...facts,
1221
+ reclaimed
1222
+ } : facts));
1203
1223
  else {
1204
1224
  const summary = `${launchWarning ? "WARNING" : "OK"}: ${androidPackage} launched on ${serial}, ${release ? `${variant} (embedded JS, no Metro)` : `Metro port ${metroPort}`} (${cacheOutcome(record.cacheHit, remote?.name ?? providerName)})`;
1205
1225
  const outcome = launchWarning ? chalk.yellow(`${summary} -- ${launchWarning}`) : launchState === "unverified" ? chalk.yellow(`${summary} -- launch UNVERIFIED`) : launchState === "bundling" ? chalk.green(`${summary} -- bundle requested, still building`) : chalk.green(summary);
1206
1226
  const deviceName = record.avdName || record.deviceName || serial;
1207
1227
  const cacheResult = useBuildCache ? cacheOutcome(record.cacheHit, remote?.name ?? providerName) : "bypassed; built";
1208
- const metroResult = release ? `embedded (${variant})` : !metroCheck ? `check skipped on port ${metroPort}` : launchState === "unverified" ? `state unverified on port ${metroPort}` : `running on port ${metroPort}`;
1228
+ const metroResult = release ? `embedded (${variant})` : !metroCheck ? `check skipped on port ${metroPort}` : launchState === "unverified" ? `state unverified on port ${metroPort}` : `running on port ${metroPort}${devServer ? ` (started: ${devServer.reason})` : ""}`;
1209
1229
  emit([
1210
1230
  outcome,
1211
1231
  phaseLine("device", `${deviceName} (${serial})`),
@@ -1461,7 +1481,7 @@ async function resolveInstallSerial({ root, slot, device, physical, remoteDevice
1461
1481
  });
1462
1482
  return resolved.serial;
1463
1483
  }
1464
- async function finishAndroidRun({ lease, releaseLease, root, slot, json, metroCheck, useBuildCache, variant, release, isExpo, metroPort, logsDir, emuLog, device, physical, remoteDevice, bootPromise, resolveAvdSerial, waitForDeviceBoot, bootDuration, apkPath, androidPackage: initialPackage, swapDir, record, waitedForBuild, ccache, uploadPending, providerUpload, providerName, remote, abandonedRemote: remoteWasAbandoned, started, startedAt, writer, phase, fail, readApkPackage, install, launch, launchRelease, resolveDevClientScheme, verifyLaunched, verifyReleaseLaunched, spawn, kill, pidAlive, verifyCollector, writeLaunch, writeState, now, out, emit, recordRun, enterPhase }) {
1484
+ async function finishAndroidRun({ lease, releaseLease, root, slot, json, metroCheck, useBuildCache, variant, release, isExpo, metroPort, logsDir, emuLog, device, physical, remoteDevice, bootPromise, resolveAvdSerial, waitForDeviceBoot, bootDuration, apkPath, androidPackage: initialPackage, swapDir, record, waitedForBuild, ccache, uploadPending, providerUpload, providerName, remote, abandonedRemote: remoteWasAbandoned, started, startedAt, writer, phase, fail, readApkPackage, install, launch, launchRelease, resolveDevClientScheme, verifyLaunched, verifyReleaseLaunched, spawn, kill, pidAlive, verifyCollector, writeLaunch, writeState, now, out, emit, recordRun, reclaimed, devServer, enterPhase }) {
1465
1485
  let androidPackage = initialPackage;
1466
1486
  let leaseWarned = false;
1467
1487
  const raiseLeaseFor = (boundMs, beforeInstall) => {
@@ -1529,9 +1549,12 @@ async function finishAndroidRun({ lease, releaseLease, root, slot, json, metroCh
1529
1549
  allowUninstall: release || adopting
1530
1550
  });
1531
1551
  if (installed.failed) {
1532
- const conflict = installConflictKind(installed.reason);
1533
- const rerun = useBuildCache ? " Then run this command again; it installs the APK from cache without building it again." : " Then run this command again.";
1534
- const installRemedy = conflict ? `${androidPackage} is already installed on ${serial} ` + (conflict === "signature" ? "with a different signer" : "at a higher versionCode") + `. Uninstall it first (\`adb -s ${serial} uninstall ${androidPackage}\`); its data goes with it.` + rerun : `Check that ${serial} is still connected (\`adb devices\`) and has room for the APK.`;
1552
+ const installRemedy = remoteDevice?.failureRemedy() ?? localInstallRemedy({
1553
+ reason: installed.reason,
1554
+ packageName: androidPackage,
1555
+ serial,
1556
+ useBuildCache
1557
+ });
1535
1558
  return fail(installed.code || "STIM_INSTALL_FAILED", installed.reason, installRemedy, { lastBuildStatus: true });
1536
1559
  }
1537
1560
  if (adopting) try {
@@ -1606,7 +1629,7 @@ async function finishAndroidRun({ lease, releaseLease, root, slot, json, metroCh
1606
1629
  appId: androidPackage,
1607
1630
  since: launchedAt
1608
1631
  }, logsDir, (line) => phase("launch", chalk.red(line)), Boolean(remoteDevice));
1609
- return fail(launched.code || "STIM_LAUNCH_FAILED", launched.reason, `Check the app installed correctly (\`adb -s ${serial} shell pm list packages ${androidPackage}\`).`, { lastBuildStatus: true });
1632
+ return fail(launched.code || "STIM_LAUNCH_FAILED", launched.reason, launchRemedy(remoteDevice, serial, androidPackage), { lastBuildStatus: true });
1610
1633
  }
1611
1634
  writer.write({
1612
1635
  src: "build",
@@ -1626,17 +1649,15 @@ async function finishAndroidRun({ lease, releaseLease, root, slot, json, metroCh
1626
1649
  } catch (error) {
1627
1650
  out(phaseLine("state", chalk.yellow(`could not record Android launch: ${error?.message || error}`)));
1628
1651
  }
1629
- const reversedSummary = (launched.reversed ?? []).join(", ") || `tcp:${metroPort}->tcp:${metroPort}`;
1630
- if (!release && launched.debugHttpHost) phase("metro", `debug_http_host ${launched.debugHttpHost} + adb reverse ${reversedSummary}`);
1631
- else if (!release) {
1632
- phase("metro", chalk.yellow(`adb reverse ${reversedSummary}; ${launched.debugHttpHostNote || "debug_http_host not written"}`));
1633
- writer.write({
1634
- src: "build",
1635
- level: "warn",
1636
- event: "debug_http_host_failed",
1637
- msg: `debug_http_host was not written for ${androidPackage} on ${serial}: ${launched.debugHttpHostNote || "unknown reason"}`
1638
- });
1639
- }
1652
+ if (!release) reportMetroRoute({
1653
+ launched,
1654
+ remote: Boolean(remoteDevice),
1655
+ metroPort,
1656
+ androidPackage,
1657
+ serial,
1658
+ phase,
1659
+ writer
1660
+ });
1640
1661
  if (launched.devClientNote) {
1641
1662
  phase("metro", chalk.yellow(launched.devClientNote));
1642
1663
  writer.write({
@@ -1659,7 +1680,21 @@ async function finishAndroidRun({ lease, releaseLease, root, slot, json, metroCh
1659
1680
  out
1660
1681
  });
1661
1682
  const remoteRelease = Boolean(remoteDevice && release);
1662
- if (!remoteRelease) {
1683
+ if (remoteDevice) {
1684
+ killPreviousCollector(root, {
1685
+ slot,
1686
+ kill,
1687
+ isAlive: pidAlive,
1688
+ verify: verifyCollector,
1689
+ note: (line) => out(phaseLine("logs", line))
1690
+ });
1691
+ writer.write({
1692
+ src: "build",
1693
+ level: "info",
1694
+ event: "collector_skipped",
1695
+ msg: `remote session ${serial}: device logs come from agent-device/EAS, so no adb logcat collector is attached`
1696
+ });
1697
+ } else {
1663
1698
  if (physical) raiseLeaseFor(0, false);
1664
1699
  const collectorPid = await startCollector({
1665
1700
  root,
@@ -1735,7 +1770,9 @@ async function finishAndroidRun({ lease, releaseLease, root, slot, json, metroCh
1735
1770
  writer,
1736
1771
  emit,
1737
1772
  lease: physical ? leaseFacts : void 0,
1738
- recordRun
1773
+ recordRun,
1774
+ reclaimed,
1775
+ devServer
1739
1776
  });
1740
1777
  if (remoteWasAbandoned || uploadWasAbandoned) exitAfterFlush(0);
1741
1778
  return {
@@ -1743,6 +1780,33 @@ async function finishAndroidRun({ lease, releaseLease, root, slot, json, metroCh
1743
1780
  facts
1744
1781
  };
1745
1782
  }
1783
+ function localInstallRemedy({ reason, packageName, serial, useBuildCache }) {
1784
+ const conflict = installConflictKind(reason);
1785
+ if (!conflict) return `Check that ${serial} is still connected (\`adb devices\`) and has room for the APK.`;
1786
+ const rerun = useBuildCache ? " Then run this command again; it installs the APK from cache without building it again." : " Then run this command again.";
1787
+ return `${packageName} is already installed on ${serial} ` + (conflict === "signature" ? "with a different signer" : "at a higher versionCode") + `. Uninstall it first (\`adb -s ${serial} uninstall ${packageName}\`); its data goes with it.` + rerun;
1788
+ }
1789
+ function launchRemedy(remoteDevice, serial, packageName) {
1790
+ return remoteDevice?.failureRemedy() ?? `Check the app installed correctly (\`adb -s ${serial} shell pm list packages ${packageName}\`).`;
1791
+ }
1792
+ function reportMetroRoute({ launched, remote, metroPort, androidPackage, serial, phase, writer }) {
1793
+ if (remote) {
1794
+ phase("metro", `public origin ${launched.jsLocation}`);
1795
+ return;
1796
+ }
1797
+ const reversedSummary = (launched.reversed ?? []).join(", ") || `tcp:${metroPort}->tcp:${metroPort}`;
1798
+ if (launched.debugHttpHost) {
1799
+ phase("metro", `debug_http_host ${launched.debugHttpHost} + adb reverse ${reversedSummary}`);
1800
+ return;
1801
+ }
1802
+ phase("metro", chalk.yellow(`adb reverse ${reversedSummary}; ${launched.debugHttpHostNote || "debug_http_host not written"}`));
1803
+ writer.write({
1804
+ src: "build",
1805
+ level: "warn",
1806
+ event: "debug_http_host_failed",
1807
+ msg: `debug_http_host was not written for ${androidPackage} on ${serial}: ${launched.debugHttpHostNote || "unknown reason"}`
1808
+ });
1809
+ }
1746
1810
  function diagnoseBootFailure(booted, logFile, runCommand, physical) {
1747
1811
  return noDeviceDiagnostic({
1748
1812
  reason: booted.reason ?? "The emulator did not boot.",
@@ -1885,7 +1949,7 @@ function androidCommand(program) {
1885
1949
  registerAndroid(program);
1886
1950
  }
1887
1951
  function registerAndroid(program) {
1888
- program.command("android").description("Build (or install from the shared cache), install and launch this workspace's Android app on its owned emulator, wired to the reserved Metro port. Never starts the bundler -- run `stim start` first.").option("--eas-profile <name>", "Download a matching EAS development build; on a miss, print the build command without running it").option("--slot <name>", "Reusable device slot within this workspace (default: default)", parseDeviceSlotOption).option("--json", "Emit the facts as a single JSON line on stdout; every other line goes to stderr").option("--no-metro-check", "Skip the reserved-port Metro health check (the app will load no bundle unless something else serves it)").option("--no-build-cache", "Build fresh, ignoring cached artifacts (local and the project's build-cache provider); the fresh build still replaces the cache entry").option("--variant <name>", "Gradle variant to assemble and install (e.g. productionDebug on a flavored project); overrides the android.variant setting. A variant ending in Release embeds the JS bundle and skips Metro entirely. Default: debug").option("--system-image <id>", "Android system image to create this workspace's owned AVD from, as the sdkmanager package id (e.g. \"system-images;android-36;google_apis;arm64-v8a\"). Overrides the android.systemImage setting for this invocation. An unknown id refuses with STIM_BAD_ARG and prints the installed images.").option("--device [serial]", "Install and launch on a connected physical device instead of this workspace's owned emulator. With no serial, the first connected device this workspace can lease is used. Stim never creates, boots, or deletes a physical device.").option("--remote <backend>", "Install and launch on a remote device with proxy or EAS. Builds are local unless --eas-profile selects an existing EAS build.", (value) => {
1952
+ program.command("android").description("Build (or install from the shared cache), install and launch this workspace's Android app on its owned emulator, wired to the reserved Metro port. A Debug run starts the dev server when it is not running.").option("--eas-profile <name>", "Download a matching EAS development build; on a miss, print the build command without running it").option("--slot <name>", "Reusable device slot within this workspace (default: default)", parseDeviceSlotOption).option("--json", "Emit the facts as a single JSON line on stdout; every other line goes to stderr").option("--no-metro-check", "Skip the reserved-port Metro health check and do not start it (the app will load no bundle unless something else serves it)").option("--no-build-cache", "Build fresh, ignoring cached artifacts (local and the project's build-cache provider); the fresh build still replaces the cache entry").option("--variant <name>", "Gradle variant to assemble and install (e.g. productionDebug on a flavored project); overrides the android.variant setting. A variant ending in Release embeds the JS bundle and skips Metro entirely. Default: debug").option("--system-image <id>", "Android system image to create this workspace's owned AVD from, as the sdkmanager package id (e.g. \"system-images;android-36;google_apis;arm64-v8a\"). Overrides the android.systemImage setting for this invocation. An unknown id refuses with STIM_BAD_ARG and prints the installed images.").option("--device [serial]", "Install and launch on a connected physical device instead of this workspace's owned emulator. With no serial, the first connected device this workspace can lease is used. Stim never creates, boots, or deletes a physical device.").option("--remote <backend>", "Install and launch on a remote device with proxy or EAS. Builds are local unless --eas-profile selects an existing EAS build.", (value) => {
1889
1953
  if (REMOTE_DEVICE_BACKENDS.includes(value)) return value;
1890
1954
  throw new InvalidArgumentError(`expected one of: ${REMOTE_DEVICE_BACKENDS.join(", ")}`);
1891
1955
  }).option("--wait <seconds>", "How long to wait for another workspace to release the device it leases, before refusing with STIM_DEVICE_BUSY (default 60, 0 refuses at once). Only with --device.").option("--no-wait", "Install on a device another workspace leases instead of waiting: this run takes no lease and, when both workspaces build the same app id, the install terminates the holder's running app. Only with --device.").action(async (opts) => {
@@ -1929,7 +1993,7 @@ function registerAndroid(program) {
1929
1993
  })).ok) process.exit(1);
1930
1994
  });
1931
1995
  }
1932
- function resolveRunAndroidOptions({ root, json = false, remoteDevice: commandRemoteBackend = null, resolveSettingsFor = resolveSettings, resolveRemoteDeviceContext = resolveRemoteContext, remoteDeviceDeps: makeRemoteDeviceDeps = remoteAndroidDeps, resolveEasBin = resolveEasCliBin, ensureMetroReachable: ensureRemoteMetro = ensureMetroReachable, ensureRemoteBootOwned: ensureRemoteOwned = ensureRemoteBootOwned, detectRemoteProviders = detectProviders, metroCheck = true, useBuildCache = true, easProfile, resolveEasDevelopmentBuild: resolveEasBuild = resolveEasDevelopmentBuild, variant: variantFlag = null, systemImage: systemImageFlag = null, device: deviceFlag = null, wait: waitFlag = void 0, waitConflict = false, acquireLease = acquireRunLease, makeRunLease = runLease, selectPool = selectFromPool, onLeaseSignal = releaseLeaseOnSignal, listDevices = listAdbDevices, deviceModel = physicalDeviceModel, deviceAbi = androidDeviceAbi, isEmulatorDevice = probeEmulatorSerial, readApkPackage = (apkPath) => apkPackage(dumpApkManifest(apkPath)), getLimits = getConcurrencyLimits, checkCapacity = checkDeviceCapacity, acquireSlot = acquireBuildSlot, releaseSlot = releaseBuildSlot, ensureDevice = ensureOwnedDevice, listSystemImages = listInstalledSystemImages, ensureDeviceBooted = ensureBooted, resolveAvdSerial = resolveOwnedAvdSerial, waitForDeviceBoot = waitForBoot, resolveMetro = resolveProjectMetro, warmMetro: prewarmMetro = warmMetro, resolveMetroRetrying = resolveMetroWithRetry, readState = readWorkspaceState, pidAlive = pidExists, verifyCollector = verifyCollectorOwnership, verifyLaunched = verifyLaunch, ensureStorage = ensureWorkspaceStorageSafely, fingerprint = fingerprintProject, untracked = untrackedNativeFiles, resolveCached = resolveBuild, storeCached = storeBuild, storedAssets = storedAssetManifest, captureAssets = captureAssetManifest, acquireLock = acquireBuildLock, releaseLock = releaseBuildLock, waitForBuild: waitForBuild$1 = waitForBuild, loadProvider = loadProjectProvider, easAuth = checkEasAuth, resolveRemoteBuild = resolveRemote, uploadRemoteBuild = uploadRemote, resolveCacheProvider = resolveCacheProviderConfig, loadCacheProviderModule = loadCacheProvider, needsPrebuildFor = needsPrebuild, prebuild = runPrebuild, build = buildAndroid, ccacheFor = resolveCcache, install = installAndroidApp, launch = launchAndroidApp, launchRelease = launchAndroidReleaseApp, verifyReleaseLaunched = verifyAndroidReleaseLaunch, swapApk = swapApkBundle, resolveDevClientScheme = androidDevClientScheme, spawn = (cmd, args, opts) => getExecutor().spawn(cmd, args, opts), kill = (pid, signal) => process.kill(pid, signal), createWriter = createNdjsonWriter, writeLaunch = writeWorkspaceLaunch, writeState = writeWorkspaceState, recordStats = recordRunStats, readEstimates = readRunEstimates, now = Date.now, out = (line) => console.error(line), emit = (line) => console.log(line) } = {}) {
1996
+ function resolveRunAndroidOptions({ root, json = false, remoteDevice: commandRemoteBackend = null, resolveSettingsFor = resolveSettings, resolveRemoteDeviceContext = resolveRemoteContext, remoteDeviceDeps: makeRemoteDeviceDeps = remoteAndroidDeps, resolveEasBin = resolveEasCliBin, ensureMetroReachable: ensureRemoteMetro = ensureMetroReachable, ensureRemoteBootOwned: ensureRemoteOwned = ensureRemoteBootOwned, detectRemoteProviders = detectProviders, metroCheck = true, useBuildCache = true, easProfile, resolveEasDevelopmentBuild: resolveEasBuild = resolveEasDevelopmentBuild, variant: variantFlag = null, systemImage: systemImageFlag = null, device: deviceFlag = null, wait: waitFlag = void 0, waitConflict = false, acquireLease = acquireRunLease, makeRunLease = runLease, selectPool = selectFromPool, onLeaseSignal = releaseLeaseOnSignal, listDevices = listAdbDevices, deviceModel = physicalDeviceModel, deviceAbi = androidDeviceAbi, isEmulatorDevice = probeEmulatorSerial, readApkPackage = (apkPath) => apkPackage(dumpApkManifest(apkPath)), getLimits = getConcurrencyLimits, checkCapacity = checkDeviceCapacity, acquireSlot = acquireBuildSlot, releaseSlot = releaseBuildSlot, ensureDevice = ensureOwnedDevice, listSystemImages = listInstalledSystemImages, ensureDeviceBooted = ensureBooted, resolveAvdSerial = resolveOwnedAvdSerial, waitForDeviceBoot = waitForBoot, resolveMetro = resolveProjectMetro, warmMetro: prewarmMetro = warmMetro, startServer = startDevServer, readState = readWorkspaceState, pidAlive = pidExists, verifyCollector = verifyCollectorOwnership, verifyLaunched = verifyLaunch, ensureStorage = ensureWorkspaceStorageSafely, fingerprint = fingerprintProject, untracked = untrackedNativeFiles, resolveCached = resolveBuild, storeCached = storeBuild, storedAssets = storedAssetManifest, captureAssets = captureAssetManifest, acquireLock = acquireBuildLock, releaseLock = releaseBuildLock, waitForBuild: waitForBuild$1 = waitForBuild, loadProvider = loadProjectProvider, easAuth = checkEasAuth, resolveRemoteBuild = resolveRemote, uploadRemoteBuild = uploadRemote, resolveCacheProvider = resolveCacheProviderConfig, loadCacheProviderModule = loadCacheProvider, planPrebuildFor = planPrebuild, prebuild = runPrebuild, build = buildAndroid, ccacheFor = resolveCcache, install = installAndroidApp, launch = launchAndroidApp, launchRelease = launchAndroidReleaseApp, verifyReleaseLaunched = verifyAndroidReleaseLaunch, swapApk = swapApkBundle, resolveDevClientScheme = androidDevClientScheme, spawn = (cmd, args, opts) => getExecutor().spawn(cmd, args, opts), kill = (pid, signal) => process.kill(pid, signal), createWriter = createNdjsonWriter, writeLaunch = writeWorkspaceLaunch, writeState = writeWorkspaceState, recordStats = recordRunStats, readEstimates = readRunEstimates, now = Date.now, out = (line) => console.error(line), emit = (line) => console.log(line) } = {}) {
1933
1997
  return {
1934
1998
  root,
1935
1999
  json,
@@ -1970,7 +2034,7 @@ function resolveRunAndroidOptions({ root, json = false, remoteDevice: commandRem
1970
2034
  waitForDeviceBoot,
1971
2035
  resolveMetro,
1972
2036
  prewarmMetro,
1973
- resolveMetroRetrying,
2037
+ startServer,
1974
2038
  readState,
1975
2039
  pidAlive,
1976
2040
  verifyCollector,
@@ -1991,7 +2055,7 @@ function resolveRunAndroidOptions({ root, json = false, remoteDevice: commandRem
1991
2055
  uploadRemoteBuild,
1992
2056
  resolveCacheProvider,
1993
2057
  loadCacheProviderModule,
1994
- needsPrebuildFor,
2058
+ planPrebuildFor,
1995
2059
  prebuild,
1996
2060
  build,
1997
2061
  ccacheFor,
@@ -2066,7 +2130,7 @@ function avdSetupFailure(error, root, logFile) {
2066
2130
  };
2067
2131
  }
2068
2132
  async function runAndroid(options = {}) {
2069
- let { root, json, commandRemoteBackend, resolveSettingsFor, resolveRemoteDeviceContext, makeRemoteDeviceDeps, resolveEasBin, ensureRemoteMetro, ensureRemoteOwned, detectRemoteProviders, metroCheck, useBuildCache: requestedBuildCache, easProfile, resolveEasBuild, variantFlag, systemImageFlag, deviceFlag, waitFlag, waitConflict, acquireLease, makeRunLease, selectPool, onLeaseSignal, listDevices, deviceModel, deviceAbi, isEmulatorDevice, readApkPackage, getLimits, checkCapacity, acquireSlot, releaseSlot, ensureDevice, listSystemImages, ensureDeviceBooted, resolveAvdSerial, waitForDeviceBoot, resolveMetro, prewarmMetro, resolveMetroRetrying, readState, pidAlive, verifyCollector, verifyLaunched, ensureStorage, fingerprint, untracked, resolveCached, storeCached, storedAssets, captureAssets, acquireLock, releaseLock, waitForBuild, loadProvider, easAuth, resolveRemoteBuild, uploadRemoteBuild, resolveCacheProvider, loadCacheProviderModule, needsPrebuildFor, prebuild, build, ccacheFor, install, launch, launchRelease, verifyReleaseLaunched, swapApk, resolveDevClientScheme, spawn, kill, createWriter, writeLaunch, writeState, recordStats, readEstimates, now, out, emit } = androidSlotOptions(options);
2133
+ let { root, json, commandRemoteBackend, resolveSettingsFor, resolveRemoteDeviceContext, makeRemoteDeviceDeps, resolveEasBin, ensureRemoteMetro, ensureRemoteOwned, detectRemoteProviders, metroCheck, useBuildCache: requestedBuildCache, easProfile, resolveEasBuild, variantFlag, systemImageFlag, deviceFlag, waitFlag, waitConflict, acquireLease, makeRunLease, selectPool, onLeaseSignal, listDevices, deviceModel, deviceAbi, isEmulatorDevice, readApkPackage, getLimits, checkCapacity, acquireSlot, releaseSlot, ensureDevice, listSystemImages, ensureDeviceBooted, resolveAvdSerial, waitForDeviceBoot, resolveMetro, prewarmMetro, startServer, readState, pidAlive, verifyCollector, verifyLaunched, ensureStorage, fingerprint, untracked, resolveCached, storeCached, storedAssets, captureAssets, acquireLock, releaseLock, waitForBuild, loadProvider, easAuth, resolveRemoteBuild, uploadRemoteBuild, resolveCacheProvider, loadCacheProviderModule, planPrebuildFor, prebuild, build, ccacheFor, install, launch, launchRelease, verifyReleaseLaunched, swapApk, resolveDevClientScheme, spawn, kill, createWriter, writeLaunch, writeState, recordStats, readEstimates, now, out, emit } = androidSlotOptions(options);
2070
2134
  const progress = options.progress ?? NO_BUILD_PROGRESS;
2071
2135
  const slot = validateDeviceSlot(options.slot);
2072
2136
  const started = now();
@@ -2137,6 +2201,7 @@ async function runAndroid(options = {}) {
2137
2201
  });
2138
2202
  const recordRun = stats.record;
2139
2203
  let ccacheActivity = CCACHE_NOT_RUN;
2204
+ let reclaimed = [];
2140
2205
  const fail = (code, message, remedy, { lastBuildStatus = false, diagnostics = [], lines = [], logPath = null, lease } = {}) => {
2141
2206
  if (lastBuildStatus) persistLastBuild({
2142
2207
  writeState,
@@ -2162,7 +2227,8 @@ async function runAndroid(options = {}) {
2162
2227
  message,
2163
2228
  remedy: remedy ?? null,
2164
2229
  ...ccacheActivity.status === "not-run" ? {} : { ccache: ccacheActivity },
2165
- ...lease === void 0 ? {} : { lease }
2230
+ ...lease === void 0 ? {} : { lease },
2231
+ ...reclaimed.length ? { reclaimed } : {}
2166
2232
  }));
2167
2233
  writer.close();
2168
2234
  return {
@@ -2217,6 +2283,19 @@ async function runAndroid(options = {}) {
2217
2283
  const useBuildCache = cachePolicy.read;
2218
2284
  const physical = target.kind === "physical";
2219
2285
  const remoteBackend = target.kind === "remote" ? target.backend : null;
2286
+ const budget = await (options.checkBudget ?? budgetGate)({
2287
+ root,
2288
+ note: out
2289
+ });
2290
+ reclaimed = budget.reclaimed;
2291
+ if (budget.refusal) return fail(budget.refusal.code, budget.refusal.message, budget.refusal.remedy);
2292
+ const remoteContext = remoteBackend ? await resolveRemoteDeviceContext({
2293
+ root,
2294
+ platform: PLATFORM,
2295
+ backend: remoteBackend,
2296
+ easBin: resolveEasBin(root)?.file ?? null
2297
+ }) : null;
2298
+ if (remoteContext && "failed" in remoteContext) return fail(remoteContext.code ?? "STIM_NO_REMOTE_SESSION", remoteContext.failed, remoteContext.remedy);
2220
2299
  const easBuild = await resolveEasBuild({
2221
2300
  root,
2222
2301
  platform: PLATFORM,
@@ -2241,45 +2320,37 @@ async function runAndroid(options = {}) {
2241
2320
  let remoteDevice = null;
2242
2321
  const reservedPort = project?.metroPort ?? null;
2243
2322
  let metroPort = null;
2323
+ let devServer = null;
2244
2324
  let phaseFailure = null;
2245
2325
  async function resolveMetroPort() {
2246
2326
  if (release) phase("metro", `skipped (${variant}: the JS bundle is embedded, no dev server is used)`);
2247
2327
  else if (metroCheck) {
2248
- if (!reservedPort) {
2249
- phaseFailure = fail(NO_METRO, "No Metro port is reserved for this workspace.", "Run `stim start` first, or pass --no-metro-check.");
2250
- return false;
2251
- }
2252
- const held = await resolveMetroRetrying(resolveMetro, reservedPort, root, { onRetry: ({ delayMs }) => phase("metro", `port ${reservedPort} did not verify yet; retrying in ${Math.round(delayMs / 1e3)}s (Metro may still be indexing)`) });
2253
- if (!held.metro) {
2254
- const supervisor = readState(root)?.supervisor ?? null;
2255
- const supervisorAlive = Boolean(supervisor?.pid && pidAlive(supervisor.pid));
2256
- phaseFailure = fail(NO_METRO, noMetroMessage({
2257
- port: reservedPort,
2258
- resolution: held,
2259
- supervisor,
2260
- supervisorAlive
2261
- }), noMetroRemedy({
2262
- port: reservedPort,
2263
- supervisor,
2264
- supervisorAlive
2265
- }));
2328
+ const gate = await ensureDevServer({
2329
+ root,
2330
+ port: reservedPort,
2331
+ settings,
2332
+ remote: remoteContext !== null,
2333
+ note: out,
2334
+ resolve: resolveMetro,
2335
+ start: startServer,
2336
+ readState
2337
+ });
2338
+ reclaimed = [...reclaimed, ...gate.reclaimed];
2339
+ if (!gate.ok) {
2340
+ phaseFailure = fail(gate.code, gate.message, gate.remedy, { lines: gate.lines });
2266
2341
  return false;
2267
2342
  }
2268
- phase("metro", `port ${reservedPort} (pid ${held.metro?.pid})`);
2343
+ metroPort = gate.port;
2344
+ devServer = gate.devServer;
2345
+ phase("metro", `port ${metroPort} (${devServer ? `started: ${devServer.reason}` : `pid ${gate.pid ?? "unknown, started outside Stim"}`})`);
2346
+ return true;
2269
2347
  } else phase("metro", reservedPort ? `port ${reservedPort} (not checked)` : `no reservation; using ${DEFAULT_METRO_PORT} (not checked)`);
2270
2348
  metroPort = release ? null : reservedPort ?? 8081;
2271
2349
  return true;
2272
2350
  }
2273
2351
  if (!await resolveMetroPort()) return phaseFailure;
2274
- if (remoteBackend) {
2275
- const resolved = await resolveRemoteDeviceContext({
2276
- root,
2277
- platform: PLATFORM,
2278
- backend: remoteBackend,
2279
- easBin: resolveEasBin(root)?.file ?? null
2280
- });
2281
- if ("failed" in resolved) return fail(resolved.code ?? "STIM_NO_REMOTE_SESSION", resolved.failed, resolved.remedy);
2282
- remoteDevice = makeRemoteDeviceDeps(resolved.ctx);
2352
+ if (remoteContext) {
2353
+ remoteDevice = makeRemoteDeviceDeps(remoteContext.ctx);
2283
2354
  if (metroPort !== null) {
2284
2355
  const reachable = await ensureRemoteMetro({
2285
2356
  ctx: remoteDevice.ctx,
@@ -2453,7 +2524,7 @@ async function runAndroid(options = {}) {
2453
2524
  loadCacheProviderModule,
2454
2525
  acquireSlot,
2455
2526
  releaseSlot,
2456
- needsPrebuildFor,
2527
+ planPrebuildFor,
2457
2528
  prebuild,
2458
2529
  build,
2459
2530
  ccacheFor,
@@ -2567,6 +2638,8 @@ async function runAndroid(options = {}) {
2567
2638
  out,
2568
2639
  emit,
2569
2640
  recordRun,
2641
+ reclaimed,
2642
+ devServer,
2570
2643
  enterPhase: progress.step
2571
2644
  });
2572
2645
  } finally {
@@ -2584,4 +2657,4 @@ async function runAndroid(options = {}) {
2584
2657
  }
2585
2658
  }
2586
2659
  //#endregion
2587
- export { NO_DEVICE, NO_FINGERPRINT, NO_METRO, androidDevClientScheme, androidFacts, androidSystemImageSetting, androidVariantSetting, apkDevClientFacts, apkPackage, collectorLogFile, androidCommand as default, displayPath, dumpApkManifest, findAapt, formatDuration, isReleaseVariant, killPreviousCollector, lastBuildRecord, noDeviceDiagnostic, parseXmltree, phaseLine, registerAndroid, resolveSystemImage, resolveVariant, runAndroid, shortHash, startCollector };
2660
+ export { NO_DEVICE, NO_FINGERPRINT, androidDevClientScheme, androidFacts, androidSystemImageSetting, androidVariantSetting, apkDevClientFacts, apkPackage, collectorLogFile, androidCommand as default, displayPath, dumpApkManifest, findAapt, formatDuration, isReleaseVariant, killPreviousCollector, lastBuildRecord, noDeviceDiagnostic, parseXmltree, phaseLine, registerAndroid, resolveSystemImage, resolveVariant, runAndroid, shortHash, startCollector };
@@ -1,5 +1,5 @@
1
- import { t as getExecutor } from "./exec-jIAlgilk.mjs";
2
- import { s as androidToolCwd } from "./android-_y4Ohi5z.mjs";
1
+ import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
2
+ import { s as androidToolCwd } from "./android-787HhP5w.mjs";
3
3
  //#region src/collector/android.ts
4
4
  const LEVEL_BY_LETTER = {
5
5
  V: "debug",
@@ -1,13 +1,14 @@
1
- import { A as withDirLock, M as readJsonFile, j as isJsonObject, u as getConfigDir } from "./config-Cp9lM3wX.mjs";
2
- import { t as getExecutor } from "./exec-jIAlgilk.mjs";
3
- import { r as register } from "./cache-manifest-Dg7OnMrp.mjs";
4
- import { b as workspaceLogsDir, f as sharedCcache, u as ensureWorkspaceStorage } from "./workspace-state-DF2gCFhx.mjs";
1
+ import { u as getConfigDir } from "./config-BEq0Qw_a.mjs";
2
+ import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
3
+ import { r as register } from "./cache-manifest-Pubfp8wV.mjs";
4
+ import { C as sharedCcache, P as withDirLock, j as workspaceLogsDir, x as ensureWorkspaceStorage } from "./metro-BWLOJ_Wr.mjs";
5
+ import { n as spawnDeclared } from "./spawn-claims-CUleC2cM.mjs";
5
6
  import { n as stripAnsi, r as waitForChild, t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
6
- import { r as androidHome } from "./android-_y4Ohi5z.mjs";
7
- import { l as phaseLine } from "./command-output-gByVmIjy.mjs";
8
- import { n as spawnDeclared } from "./spawn-claims-Dn3C_N6w.mjs";
9
- import { d as startBuildHeartbeat, n as HEARTBEAT_INTERVAL_MS } from "./xcode-BZqyxh3e.mjs";
7
+ import { l as phaseLine } from "./command-output-D5z2_bcF.mjs";
8
+ import { r as androidHome } from "./android-787HhP5w.mjs";
9
+ import { d as startBuildHeartbeat, n as HEARTBEAT_INTERVAL_MS } from "./xcode-B2tBkf0m.mjs";
10
10
  import { accessSync, constants, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, symlinkSync, writeFileSync } from "node:fs";
11
+ import { isJsonObject, readJsonFile } from "@stim-cli/core/state";
11
12
  import { dirname, isAbsolute, join, relative, sep } from "node:path";
12
13
  import { createHash, randomUUID } from "node:crypto";
13
14
  import { fileURLToPath } from "node:url";
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as getExecutor } from "./exec-jIAlgilk.mjs";
2
+ import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
3
3
  import { appendFileSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
4
4
  import { join } from "node:path";
5
5
  import { createHash, randomUUID } from "node:crypto";
@@ -1,5 +1,5 @@
1
- import { t as getExecutor } from "./exec-jIAlgilk.mjs";
2
- import { E as uninstallIosApp, l as iosSimulatorFailureAdvice, m as listUserApps } from "./ios-BL2NFckr.mjs";
1
+ import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
2
+ import { T as uninstallIosApp, c as iosSimulatorFailureAdvice, p as listUserApps } from "./ios-COGcGEcN.mjs";
3
3
  import { closeSync, lstatSync, openSync, readSync, readdirSync } from "node:fs";
4
4
  import { isAbsolute, join } from "node:path";
5
5
  import { createHash } from "node:crypto";