stim 1.1.0 → 1.3.0

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 (64) hide show
  1. package/README.md +37 -0
  2. package/dist/{android-CC5bUer7.mjs → android-BW8i_YxU.mjs} +1 -1
  3. package/dist/android-BqVIJoG7.mjs +1368 -0
  4. package/dist/{android-DnZlT3aU.mjs → android-CqcW1hrP.mjs} +205 -58
  5. package/dist/{android-cas-DGlTStWu.mjs → android-cas-BR5YJBYv.mjs} +6 -6
  6. package/dist/android-cas-compiler.mjs +1 -1
  7. package/dist/{app-install-oZIQRbdD.mjs → app-install-DIp9riNx.mjs} +29 -21
  8. package/dist/{build-slots-CgacA9zQ.mjs → build-slots-C3-R4XQr.mjs} +3 -3
  9. package/dist/{cache-manifest-oeH18ERr.mjs → cache-manifest-CXR-Y8pH.mjs} +1 -1
  10. package/dist/cache-manifest.mjs +1 -1
  11. package/dist/cli.mjs +13 -13
  12. package/dist/collector-run.d.mts +4 -1
  13. package/dist/collector-run.mjs +36 -11
  14. package/dist/{config-D7uu8Gbq.mjs → config-CcefMY2Q.mjs} +94 -13
  15. package/dist/{deps-64wVnpZc.mjs → deps-Spz8ozgo.mjs} +2 -2
  16. package/dist/{dev-client-Bvky1hya.mjs → dev-client-BjisHDB5.mjs} +250 -10
  17. package/dist/{device-DJKv5Qej.mjs → device-BkiW-gkk.mjs} +19 -11
  18. package/dist/{device-lease-D-G3SgVe.mjs → device-lease-BJYybF-2.mjs} +107 -83
  19. package/dist/{device-pool-BlHXnYYs.mjs → device-pool-CPbLGfrB.mjs} +19 -13
  20. package/dist/{device-remote-CCgkG82J.mjs → device-remote-AkYCKS8U.mjs} +8 -8
  21. package/dist/{doctor-DlVxTtMq.mjs → doctor-Bmv86UUW.mjs} +18 -26
  22. package/dist/{doctor-BRF9aAJ3.mjs → doctor-fAMXC4vl.mjs} +10 -10
  23. package/dist/{error-diagnostics-B5IJwv3-.mjs → error-diagnostics-DHC31rXA.mjs} +65 -55
  24. package/dist/{exec-bsN9MJXb.mjs → exec-CyylIdq9.mjs} +4 -2
  25. package/dist/{gc-DhXdgSdt.mjs → gc-GGu-8ULN.mjs} +90 -67
  26. package/dist/{guide-DrhrDBo5.mjs → guide-92CPA21s.mjs} +414 -47
  27. package/dist/{ios-CK1Vrk6Q.mjs → ios-BSXFeO5H.mjs} +200 -59
  28. package/dist/{ios-BZxKPuqP.mjs → ios-Deh5js5V.mjs} +147 -40
  29. package/dist/{ios-device-CdSm0GDw.mjs → ios-device-CWOM_S44.mjs} +2 -2
  30. package/dist/{ios-device-CYbuRNXR.mjs → ios-device-D3pzTKQE.mjs} +1 -1
  31. package/dist/{logs-Dxoy16Qv.mjs → logs-DPNF4C9s.mjs} +9 -6
  32. package/dist/{logs-query-oqn47Ffx.mjs → logs-query-R-Cqc6Qv.mjs} +22 -5
  33. package/dist/{metro-B01H3EuD.mjs → metro-CORqXyTL.mjs} +3 -3
  34. package/dist/{ndjson-DcAtEx_K.mjs → ndjson-BZwI1NBv.mjs} +5 -2
  35. package/dist/{ownership-D8HmSv2E.mjs → ownership-8O073GIC.mjs} +3 -3
  36. package/dist/{ownership-B9QIdQOw.mjs → ownership-BpCKiRlQ.mjs} +4 -4
  37. package/dist/{ownership-claim-CeJLEpjD.mjs → ownership-claim-Bf2CAfw3.mjs} +4 -3
  38. package/dist/{project-COj6nzzh.mjs → project-fKmuIaMI.mjs} +2 -2
  39. package/dist/{reclaim-BPvN2HlP.mjs → reclaim-iW9Cad7k.mjs} +80 -73
  40. package/dist/{reload-DYZEBbZy.mjs → reload-DazHDSFA.mjs} +32 -24
  41. package/dist/{server-bare-BYHqEeyw.mjs → server-bare-DEzPZLvf.mjs} +7 -2
  42. package/dist/server-expo-44em5Pmg.mjs +2 -0
  43. package/dist/{server-expo-BEMr_m6p.mjs → server-expo-DizT4OMk.mjs} +5 -5
  44. package/dist/{settings-BSwrY4FZ.mjs → settings-DEJf6_kJ.mjs} +26 -5
  45. package/dist/slot-launch-cci0xvmC.mjs +19 -0
  46. package/dist/{start-ByCylYtB.mjs → start-mObjQH2W.mjs} +12 -12
  47. package/dist/{state-IYEY-zi8.mjs → state-B3XA2wp2.mjs} +9 -9
  48. package/dist/{stats-wqxPm7Tv.mjs → stats-BR-kwj0B.mjs} +1 -1
  49. package/dist/{stats-DZ4Q5J-7.mjs → stats-CaaQr4yN.mjs} +3 -3
  50. package/dist/{status-Dia0XTqG.mjs → status-BxQNqu9t.mjs} +86 -25
  51. package/dist/{stop-D6o5zAdm.mjs → stop-CrHGcjrV.mjs} +2 -2
  52. package/dist/{stop-BApyaF21.mjs → stop-DimGXEKY.mjs} +93 -42
  53. package/dist/supervisor-run.d.mts +1 -2
  54. package/dist/supervisor-run.mjs +5 -5
  55. package/dist/{remote-cache-DOi5-zLj.mjs → teardown-ClFp1Aax.mjs} +889 -830
  56. package/dist/{workspace-process-lock-CxOO9-pf.mjs → workspace-process-lock-3NcQnZ0X.mjs} +1 -1
  57. package/dist/{worktree-DxEmUI_n.mjs → worktree-DxTgN1CJ.mjs} +16 -16
  58. package/dist/{worktree-Dx3ZC5lS.mjs → worktree-Eq6TLH8N.mjs} +7 -3
  59. package/dist/{xcode-CDB6fytw.mjs → xcode-D7sAp-Zy.mjs} +256 -103
  60. package/package.json +5 -5
  61. package/shim/bundle-response.cjs +5 -0
  62. package/dist/android-xmyGBNy5.mjs +0 -665
  63. package/dist/build-lock-vE45ZzJZ.mjs +0 -645
  64. package/dist/server-expo-rb0k-0w7.mjs +0 -2
@@ -1,23 +1,24 @@
1
- import { t as getExecutor } from "./exec-bsN9MJXb.mjs";
2
- import { C as withConfigLock, _ as releaseAndroidConsolePort, b as setDevice, g as loadConfig, i as clearDevice, t as allConsolePortsAndSerials, u as getConfigDir, y as saveConfig } from "./config-D7uu8Gbq.mjs";
3
- import { r as register } from "./cache-manifest-oeH18ERr.mjs";
4
- import { E as workspaceId, S as sharedCompilationCache, w as workspaceDerivedData } from "./state-IYEY-zi8.mjs";
5
- import { s as ownedDeviceLabel } from "./project-COj6nzzh.mjs";
1
+ import { t as getExecutor } from "./exec-CyylIdq9.mjs";
2
+ import { C as withConfigLock, E as inspectProcessIdentity, L as deviceSlotPlatforms, _ as releaseAndroidConsolePort, b as setDevice, g as loadConfig, i as clearDevice, t as allConsolePortsAndSerials, u as getConfigDir, w as captureProcessIdentity, y as saveConfig, z as projectDeviceSlots } from "./config-CcefMY2Q.mjs";
3
+ import { r as register } from "./cache-manifest-CXR-Y8pH.mjs";
4
+ import { E as workspaceId, S as sharedCompilationCache, w as workspaceDerivedData } from "./state-B3XA2wp2.mjs";
5
+ import { s as ownedDeviceLabel } from "./project-fKmuIaMI.mjs";
6
6
  import { n as stripAnsi, r as waitForChild, t as createLineReader } from "./process-output-C7IlIzd7.mjs";
7
- import { r as pidExists } from "./metro-B01H3EuD.mjs";
8
- import { C as selectParked, S as readParked, _ as teardownParkedIosSim, b as dropParked, g as teardownParkedAvd, m as teardownOwnedAvd, x as parkedMaxSetting, y as adoptParked } from "./remote-cache-DOi5-zLj.mjs";
9
- import { H as resolveOptimizations, l as androidDataPartitionSizeGbSetting, o as androidAvdConfigSetting, v as iosSimSlimProfileSetting } from "./settings-BSwrY4FZ.mjs";
7
+ import { r as pidExists } from "./metro-CORqXyTL.mjs";
10
8
  import { a as formatElapsed, l as phaseLine } from "./command-output-8wHMEde0.mjs";
11
- import { _ as resetIosKeychain, b as resolveOwnedIosSim, c as iosRuntimeMatches, g as renameIosSim, h as parseRuntimeVersion, i as createOwnedIosSim, l as listAllIosSims, n as bootIosSim, p as ownedSimName, u as listIosDeviceTypes, v as resetIosPrivacy, y as resolveIosCreation } from "./ios-BZxKPuqP.mjs";
12
- import { A as resolveOwnedAvdSerial, C as ownedAvdMatchesConfiguration, D as pickDefaultSystemImage, P as waitForBoot, T as ownedAvdSystemImage, _ as listAdbDevices, c as bootAndroidEmulator, g as getAvdNameForSerial, l as configureNewOwnedAvd, o as assertOwnedAvdStopped, s as avdPoolConfiguration, u as createOwnedAvd, v as listAvds, w as ownedAvdName, x as nextConsolePort, y as listInstalledSystemImages } from "./android-xmyGBNy5.mjs";
13
- import { t as withWorkspaceProcessLock } from "./workspace-process-lock-CxOO9-pf.mjs";
14
- import { t as cleanLine } from "./server-expo-BEMr_m6p.mjs";
9
+ import { f as releaseClaim, h as tryAcquireClaim, i as claimRemoveCommand, l as markClaimChildPending, n as ClaimRefusedError, p as setClaimChild, u as processGroupAlive } from "./ownership-claim-Bf2CAfw3.mjs";
10
+ import { A as pickDefaultSystemImage, D as ownedAvdName, E as ownedAvdMatchesConfiguration, L as waitForBoot, N as resolveOwnedAvdSerial, O as ownedAvdSystemImage, b as listAvds, c as avdPoolConfiguration, d as configureNewOwnedAvd, f as createOwnedAvd, o as assertOwnedAvdStopped, u as bootAndroidEmulator, v as getAvdNameForSerial, w as nextConsolePort, x as listInstalledSystemImages, y as listAdbDevices } from "./android-BqVIJoG7.mjs";
11
+ import { U as resolveOptimizations, l as androidDataPartitionSizeGbSetting, o as androidAvdConfigSetting, v as iosSimSlimProfileSetting } from "./settings-DEJf6_kJ.mjs";
12
+ import { t as cleanLine } from "./server-expo-DizT4OMk.mjs";
13
+ import { c as parkedMaxSetting, i as teardownParkedIosSim, l as readParked, o as adoptParked, r as teardownParkedAvd, s as dropParked, t as teardownOwnedAvd, u as selectParked } from "./teardown-ClFp1Aax.mjs";
14
+ import { t as withWorkspaceProcessLock } from "./workspace-process-lock-3NcQnZ0X.mjs";
15
+ import { E as readHostMemoryPressure, T as hostMemoryPressureAdvice, _ as renameIosSim, b as resolveIosCreation, c as iosRuntimeMatches, d as listIosDeviceTypes, g as parseRuntimeVersion, i as createOwnedIosSim, l as iosSimulatorFailureAdvice, m as ownedSimName, n as bootIosSim, u as listAllIosSims, v as resetIosKeychain, x as resolveOwnedIosSim, y as resetIosPrivacy } from "./ios-Deh5js5V.mjs";
15
16
  import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
16
17
  import { createHash, randomUUID } from "node:crypto";
17
18
  import { basename, isAbsolute, join, relative, resolve, sep } from "node:path";
18
19
  import chalk from "chalk";
19
20
  //#region src/engine/simslim.ts
20
- async function reconcileSimSlim({ udid, profile, previouslyManaged = false, out = () => {}, spawn }) {
21
+ async function reconcileSimSlim({ udid, profile, previouslyManaged = false, out = () => {}, spawn, timeoutMs = 72e4, cleanupMs = 1e4 }) {
21
22
  if (!profile && !previouslyManaged) return {
22
23
  managed: false,
23
24
  profile: null
@@ -39,25 +40,107 @@ async function reconcileSimSlim({ udid, profile, previouslyManaged = false, out
39
40
  };
40
41
  const stdout = createLineReader(onLine);
41
42
  const stderr = createLineReader(onLine);
43
+ const root = join(getConfigDir(), "simslim-locks", `${encodeURIComponent(udid.toLowerCase())}.lock`);
44
+ const label = `SimSlim for ${udid}`;
45
+ const attempt = tryAcquireClaim({
46
+ root,
47
+ mode: "exclusive",
48
+ label
49
+ });
50
+ if (attempt.pending) releaseClaim(attempt.pending);
51
+ const claim = attempt.acquired;
52
+ if (!claim) throw new ClaimRefusedError({
53
+ root,
54
+ claimPath: attempt.held?.path ?? root,
55
+ label,
56
+ reason: "another SimSlim operation is still using this simulator"
57
+ });
42
58
  let child;
59
+ let result;
60
+ let identity;
61
+ let cancellation;
62
+ const stopGroup = () => {
63
+ if (child?.pid !== void 0 && identity && inspectProcessIdentity(identity) === "same") try {
64
+ process.kill(-child.pid, "SIGKILL");
65
+ } catch {}
66
+ };
67
+ const cancel = (signal) => {
68
+ cancellation ??= signal;
69
+ stopGroup();
70
+ };
71
+ const onInterrupt = () => cancel("SIGINT");
72
+ const onTerminate = () => cancel("SIGTERM");
73
+ const groupAlive = () => child?.pid !== void 0 && processGroupAlive(child.pid);
74
+ const settled = () => result !== void 0 && !groupAlive();
75
+ const waitUntil = async (deadline, cancellable = false) => {
76
+ while (!settled() && Date.now() < deadline) {
77
+ if (cancellable && cancellation) break;
78
+ await new Promise((resolve) => setTimeout(resolve, Math.min(50, deadline - Date.now())));
79
+ }
80
+ return settled();
81
+ };
82
+ process.on("SIGINT", onInterrupt);
83
+ process.on("SIGTERM", onTerminate);
84
+ process.on("exit", stopGroup);
43
85
  try {
44
- child = (spawn ?? ((cmd, childArgs, opts) => getExecutor().spawn(cmd, childArgs, opts)))("simslim", args, { stdio: [
45
- "ignore",
46
- "pipe",
47
- "pipe"
48
- ] });
49
- } catch (error) {
50
- throw simslimLaunchError(error);
86
+ markClaimChildPending(claim);
87
+ try {
88
+ child = (spawn ?? ((cmd, childArgs, opts) => getExecutor().spawn(cmd, childArgs, opts)))("simslim", args, {
89
+ stdio: [
90
+ "ignore",
91
+ "pipe",
92
+ "pipe"
93
+ ],
94
+ detached: true
95
+ });
96
+ } catch (error) {
97
+ throw simslimLaunchError(error);
98
+ }
99
+ child.stdout?.on("data", (chunk) => stdout.push(chunk));
100
+ child.stderr?.on("data", (chunk) => stderr.push(chunk));
101
+ waitForChild(child).then((value) => {
102
+ result = value;
103
+ });
104
+ if (child.pid !== void 0) {
105
+ const captured = captureProcessIdentity(child.pid);
106
+ if (captured.ok) {
107
+ identity = {
108
+ pid: child.pid,
109
+ processToken: captured.token
110
+ };
111
+ try {
112
+ setClaimChild(claim, identity);
113
+ } catch {}
114
+ }
115
+ }
116
+ const completed = await waitUntil(Date.now() + timeoutMs, true);
117
+ if (cancellation || !completed) {
118
+ stopGroup();
119
+ const stopped = await waitUntil(Date.now() + cleanupMs);
120
+ const detail = lines.length ? ` ${lines.join(" | ")}` : "";
121
+ const recovery = stopped ? "Its process group has stopped. Retry stim ios to reconcile the retained simulator settings." : `Its process group could not be confirmed stopped. The claim remains at ${claim.path}. Inspect the SimSlim process group ${child.pid ?? "unknown"} before retrying. Only when nothing is using it, remove the claim: ${claimRemoveCommand(claim.path)}`;
122
+ const message = `SimSlim ${action} ${cancellation ? `interrupted by ${cancellation}` : `exceeded ${Math.round(timeoutMs / 1e3)}s`}. ${recovery}${detail}`;
123
+ if (cancellation) out(message);
124
+ throw Object.assign(new Error(message), { code: cancellation ? "EINTR" : "ETIMEDOUT" });
125
+ }
126
+ } finally {
127
+ if (!child || settled()) releaseClaim(claim);
128
+ else {
129
+ child.stdout?.destroy?.();
130
+ child.stderr?.destroy?.();
131
+ child.unref();
132
+ }
133
+ process.off("SIGINT", onInterrupt);
134
+ process.off("SIGTERM", onTerminate);
135
+ process.off("exit", stopGroup);
136
+ if (cancellation) process.exit(cancellation === "SIGINT" ? 130 : 143);
51
137
  }
52
- child.stdout?.on("data", (chunk) => stdout.push(chunk));
53
- child.stderr?.on("data", (chunk) => stderr.push(chunk));
54
- const result = await waitForChild(child);
55
138
  stdout.flush();
56
139
  stderr.flush();
57
- if (result.error) throw simslimLaunchError(result.error);
58
- if (result.code !== 0) {
140
+ if (result?.error) throw simslimLaunchError(result.error);
141
+ if (result?.code !== 0) {
59
142
  const detail = lines.length ? ` ${lines.join(" | ")}` : "";
60
- throw new Error(`SimSlim ${action} failed with exit code ${result.code ?? "unknown"}.${detail}`);
143
+ throw new Error(`SimSlim ${action} failed with exit code ${result?.code ?? "unknown"}.${detail}`);
61
144
  }
62
145
  return {
63
146
  managed: Boolean(profile),
@@ -78,9 +161,12 @@ function simslimIsOnPath() {
78
161
  }
79
162
  //#endregion
80
163
  //#region src/engine/device.ts
81
- function startIosBoot(udid, configure) {
164
+ function startIosBoot(udid, configure, label, out) {
82
165
  const done = (async () => {
83
- await bootIosSim(udid);
166
+ await bootIosSim(udid, {
167
+ label,
168
+ out
169
+ });
84
170
  await configure();
85
171
  })();
86
172
  done.catch(() => {});
@@ -89,11 +175,13 @@ function startIosBoot(udid, configure) {
89
175
  done
90
176
  };
91
177
  }
92
- async function ensureOwnedDevice({ platform, project, projectPath, settingsRoot = projectPath, label = ownedDeviceLabel(projectPath), settings, flags = {}, note = () => {}, out = () => {}, logFile = null, alive = pidExists, configureAvd = configureNewOwnedAvd, teardownAvd = teardownOwnedAvd, reconcileIosSimulator = reconcileSimSlim }) {
93
- const record = project?.platforms?.[platform] ?? null;
178
+ async function ensureOwnedDevice({ platform, project, projectPath, slot, settingsRoot = projectPath, label = ownedDeviceLabel(projectPath), settings, flags = {}, note = () => {}, out = () => {}, logFile = null, alive = pidExists, configureAvd = configureNewOwnedAvd, teardownAvd = teardownOwnedAvd, reconcileIosSimulator = reconcileSimSlim }) {
179
+ if (slot && slot !== "default") label = `${label}-${slot}`;
180
+ const record = deviceSlotPlatforms(project, slot)?.[platform] ?? null;
94
181
  if (platform === "ios") return ensureOwnedIosDevice({
95
182
  record,
96
183
  projectPath,
184
+ slot,
97
185
  settingsRoot,
98
186
  label,
99
187
  settings,
@@ -105,6 +193,7 @@ async function ensureOwnedDevice({ platform, project, projectPath, settingsRoot
105
193
  return ensureOwnedAndroidDevice({
106
194
  record,
107
195
  projectPath,
196
+ slot,
108
197
  settingsRoot,
109
198
  label,
110
199
  settings,
@@ -117,7 +206,9 @@ async function ensureOwnedDevice({ platform, project, projectPath, settingsRoot
117
206
  teardownAvd
118
207
  });
119
208
  }
120
- async function ensureOwnedIosDevice({ record, projectPath, settingsRoot, label, settings, flags, note, out, reconcileIosSimulator }) {
209
+ async function ensureOwnedIosDevice({ record, projectPath, slot, settingsRoot, label, settings, flags, note, out, reconcileIosSimulator }) {
210
+ const memoryAdvice = hostMemoryPressureAdvice(readHostMemoryPressure());
211
+ if (memoryAdvice) out(chalk.yellow(phaseLine("memory", memoryAdvice)));
121
212
  const simslimProfile = iosSimSlimProfileSetting(settings, settingsRoot);
122
213
  if (record?.deviceUdid) {
123
214
  if (record.owned) {
@@ -148,6 +239,7 @@ async function ensureOwnedIosDevice({ record, projectPath, settingsRoot, label,
148
239
  return configureOwnedIosSim({
149
240
  record: updated,
150
241
  projectPath,
242
+ slot,
151
243
  profile: simslimProfile,
152
244
  out,
153
245
  reconcileIosSimulator
@@ -161,7 +253,7 @@ async function ensureOwnedIosDevice({ record, projectPath, settingsRoot, label,
161
253
  out(chalk.dim(phaseLine("device", `booting ${name} (${sim.udid})`)));
162
254
  return {
163
255
  ...updated,
164
- booting: startIosBoot(sim.udid, configure),
256
+ booting: startIosBoot(sim.udid, configure, name, out),
165
257
  ...facts
166
258
  };
167
259
  }
@@ -180,6 +272,12 @@ async function ensureOwnedIosDevice({ record, projectPath, settingsRoot, label,
180
272
  return record;
181
273
  }
182
274
  }
275
+ withConfigLock(() => {
276
+ const current = deviceSlotPlatforms(loadConfig()?.projects?.[projectPath], slot)?.ios;
277
+ if (!current) return;
278
+ if (current.deviceUdid !== record.deviceUdid || current.owned !== record.owned) throw new Error("The simulator assignment changed during recovery. Run `stim ios` again.");
279
+ clearDevice(projectPath, "ios", slot);
280
+ });
183
281
  }
184
282
  const choice = resolveIosCreation({
185
283
  deviceType: flags.deviceType || settings.ios?.deviceType,
@@ -187,6 +285,7 @@ async function ensureOwnedIosDevice({ record, projectPath, settingsRoot, label,
187
285
  });
188
286
  const adopted = parkedMaxSetting("ios").max > 0 ? await withIosDeviceNameLock(() => takeParkedIosSim({
189
287
  projectPath,
288
+ slot,
190
289
  label,
191
290
  choice,
192
291
  out
@@ -198,11 +297,12 @@ async function ensureOwnedIosDevice({ record, projectPath, settingsRoot, label,
198
297
  await configureOwnedIosSim({
199
298
  record: adopted,
200
299
  projectPath,
300
+ slot,
201
301
  profile: simslimProfile,
202
302
  out,
203
303
  reconcileIosSimulator
204
304
  });
205
- });
305
+ }, adopted.deviceName, out);
206
306
  return {
207
307
  ...adopted,
208
308
  booting,
@@ -220,7 +320,7 @@ async function ensureOwnedIosDevice({ record, projectPath, settingsRoot, label,
220
320
  deviceUdid: result.udid,
221
321
  owned: true,
222
322
  deviceName: result.name
223
- });
323
+ }, slot);
224
324
  return result;
225
325
  });
226
326
  const newRecord = {
@@ -231,10 +331,11 @@ async function ensureOwnedIosDevice({ record, projectPath, settingsRoot, label,
231
331
  const booting = startIosBoot(created.udid, () => configureOwnedIosSim({
232
332
  record: newRecord,
233
333
  projectPath,
334
+ slot,
234
335
  profile: simslimProfile,
235
336
  out,
236
337
  reconcileIosSimulator
237
- }));
338
+ }), created.name, out);
238
339
  return {
239
340
  ...newRecord,
240
341
  created: true,
@@ -248,8 +349,8 @@ function withIosDeviceNameLock(fn) {
248
349
  }
249
350
  function ownedIosNameSuffix(label, model, projectPath, udid) {
250
351
  const names = new Set(listAllIosSims({ includeUnavailable: true }).filter((sim) => sim.udid !== udid).map((sim) => sim.name));
251
- for (const project of Object.values(loadConfig()?.projects ?? {})) {
252
- const record = project.platforms?.ios;
352
+ for (const project of Object.values(loadConfig()?.projects ?? {})) for (const { platforms } of projectDeviceSlots(project)) {
353
+ const record = platforms.ios;
253
354
  if (record?.deviceUdid !== udid && record?.deviceName) names.add(record.deviceName);
254
355
  }
255
356
  for (const parked of readParked("ios")) if (parked.udid !== udid) names.add(parked.name);
@@ -272,7 +373,7 @@ function resetAdoptedSim(udid, out) {
272
373
  resetIosPrivacy(udid);
273
374
  resetIosKeychain(udid);
274
375
  }
275
- function takeParkedIosSim({ projectPath, label, choice, out }) {
376
+ function takeParkedIosSim({ projectPath, slot, label, choice, out }) {
276
377
  const candidates = selectParked(readParked("ios"), {
277
378
  deviceTypeIdentifier: choice.deviceTypeId,
278
379
  runtimeIdentifier: choice.runtimeId
@@ -308,6 +409,7 @@ function takeParkedIosSim({ projectPath, label, choice, out }) {
308
409
  if (!adoptParked({
309
410
  platform: "ios",
310
411
  projectPath,
412
+ slot,
311
413
  udid: parked.udid,
312
414
  device
313
415
  })) continue;
@@ -318,10 +420,10 @@ function takeParkedIosSim({ projectPath, label, choice, out }) {
318
420
  }
319
421
  return null;
320
422
  }
321
- function clearIosAdoptionPending(projectPath) {
423
+ function clearIosAdoptionPending(projectPath, slot = "default") {
322
424
  withConfigLock(() => {
323
425
  const cfg = loadConfig();
324
- const ios = cfg?.projects?.[projectPath]?.platforms?.ios;
426
+ const ios = deviceSlotPlatforms(cfg?.projects?.[projectPath], slot)?.ios;
325
427
  if (!cfg || !ios?.adoptionPending) return;
326
428
  delete ios.adopted;
327
429
  delete ios.adoptionPending;
@@ -329,7 +431,7 @@ function clearIosAdoptionPending(projectPath) {
329
431
  saveConfig(cfg);
330
432
  });
331
433
  }
332
- async function configureOwnedIosSim({ record, projectPath, profile, out, reconcileIosSimulator }) {
434
+ async function configureOwnedIosSim({ record, projectPath, slot, profile, out, reconcileIosSimulator }) {
333
435
  if (profile) out(chalk.dim(phaseLine("device", `applying the SimSlim profile to ${record.deviceUdid}`)));
334
436
  else if (record.simslimManaged) out(chalk.dim(phaseLine("device", `restoring stock simulator services on ${record.deviceUdid}`)));
335
437
  const previouslyManaged = Boolean(record.simslimManaged);
@@ -338,7 +440,7 @@ async function configureOwnedIosSim({ record, projectPath, profile, out, reconci
338
440
  ...record,
339
441
  simslimManaged: true
340
442
  };
341
- setDevice(projectPath, "ios", pending);
443
+ setDevice(projectPath, "ios", pending, slot);
342
444
  record = pending;
343
445
  }
344
446
  const result = await reconcileIosSimulator({
@@ -350,24 +452,31 @@ async function configureOwnedIosSim({ record, projectPath, profile, out, reconci
350
452
  const updated = { ...record };
351
453
  if (result.managed) updated.simslimManaged = true;
352
454
  else delete updated.simslimManaged;
353
- setDevice(projectPath, "ios", updated);
455
+ setDevice(projectPath, "ios", updated, slot);
354
456
  return updated;
355
457
  }
356
- function findOtherProjectOwningAvd(avdName, projectPath) {
458
+ function findOtherProjectOwningAvd(avdName, projectPath, selectedSlot = "default") {
357
459
  const cfg = loadConfig();
358
- for (const [path, proj] of Object.entries(cfg?.projects || {})) {
359
- if (path === projectPath) continue;
360
- if (proj?.platforms?.android?.avdName === avdName) return path;
361
- }
460
+ for (const [path, proj] of Object.entries(cfg?.projects || {})) if (projectDeviceSlots(proj).some(({ slot, platforms }) => (path !== projectPath || slot !== selectedSlot) && platforms.android?.avdName?.toLowerCase() === avdName.toLowerCase())) return path;
362
461
  return null;
363
462
  }
364
- async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, label, settings, flags, note, out, logFile, alive, configureAvd, teardownAvd }) {
463
+ var AvdRecoveryError = class extends Error {
464
+ remedy;
465
+ constructor(message, remedy, cause) {
466
+ super(message, { cause });
467
+ this.remedy = remedy;
468
+ }
469
+ };
470
+ async function ensureOwnedAndroidDevice({ record, projectPath, slot, settingsRoot, label, settings, flags, note, out, logFile, alive, configureAvd, teardownAvd }) {
365
471
  const avdConfig = androidAvdConfigSetting(settings, settingsRoot);
366
472
  const configuration = avdPoolConfiguration(androidDataPartitionSizeGbSetting(settings), avdConfig);
367
473
  if (record?.setupIncomplete && record.avdName) {
368
- const cleanup = teardownAvd(record.avdName, { del: true });
474
+ const cleanup = teardownAvd(record.avdName, {
475
+ del: true,
476
+ owner: { projectPath }
477
+ });
369
478
  if (cleanup.status === "failed" || cleanup.status === "skipped") throw new Error(`Owned AVD ${record.avdName} has incomplete setup and could not be deleted (${cleanup.reason || cleanup.status}). Fix the cause, then retry; Stim kept the device record for cleanup.`);
370
- clearDevice(projectPath, "android");
479
+ clearDevice(projectPath, "android", slot);
371
480
  record = null;
372
481
  }
373
482
  if (record?.avdName) {
@@ -376,6 +485,7 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
376
485
  if (resolved.notOwned) note(chalk.yellow(`Note: recorded AVD ${record.avdName} is not Stim-owned by name -- creating a fresh owned AVD instead of reusing it.`));
377
486
  else if (resolved.serial) {
378
487
  const consolePort = Number(resolved.serial.replace(/^emulator-/, ""));
488
+ if (record.consolePort && record.consolePort !== consolePort) out(phaseLine("device", `${record.avdName} changed serial (emulator-${record.consolePort} -> ${resolved.serial}); reconnecting this run, reopen agent-device on ${resolved.serial}`));
379
489
  const updated = {
380
490
  ...record,
381
491
  avdName: record.avdName,
@@ -383,7 +493,7 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
383
493
  owned: true,
384
494
  deviceName: record.deviceName ?? record.avdName
385
495
  };
386
- setDevice(projectPath, "android", updated);
496
+ setDevice(projectPath, "android", updated, slot);
387
497
  return {
388
498
  ...updated,
389
499
  systemImage: ownedAvdSystemImage(record.avdName)
@@ -395,6 +505,7 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
395
505
  avdName: record.avdName,
396
506
  metadata: record,
397
507
  projectPath,
508
+ slot,
398
509
  deviceName: record.deviceName,
399
510
  out,
400
511
  logFile,
@@ -421,7 +532,8 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
421
532
  if (parked.deletionClaim !== void 0) continue;
422
533
  const resolved = resolveOwnedAvdSerial(parked.name);
423
534
  if (resolved.missing) {
424
- dropParked("android", parked.udid);
535
+ const result = teardownParkedAvd(parked.name);
536
+ if (result.status === "failed") out(phaseLine("device", `kept ${parked.name}: ${result.reason}`));
425
537
  continue;
426
538
  }
427
539
  if (resolved.notOwned || resolved.serial) continue;
@@ -446,6 +558,7 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
446
558
  if (!adoptParked({
447
559
  platform: "android",
448
560
  projectPath,
561
+ slot,
449
562
  udid: parked.udid,
450
563
  device: adopted
451
564
  })) continue;
@@ -453,6 +566,7 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
453
566
  ...await bootOwnedAvdOnFreshPort({
454
567
  avdName: parked.name,
455
568
  projectPath,
569
+ slot,
456
570
  metadata: adopted,
457
571
  out,
458
572
  logFile,
@@ -467,9 +581,9 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
467
581
  let fresh = false;
468
582
  try {
469
583
  created = withConfigLock(() => {
470
- const current = loadConfig()?.projects?.[projectPath]?.platforms?.android;
584
+ const current = deviceSlotPlatforms(loadConfig()?.projects?.[projectPath], slot)?.android;
471
585
  if (current?.avdName && current.avdName !== record?.avdName) throw new Error(`Another Stim run assigned AVD ${current.avdName} to this workspace. Retry to use it.`);
472
- if (readParked("android").some((entry) => entry.name === ownedAvdName(label)) || findOtherProjectOwningAvd(ownedAvdName(label), projectPath)) label = `${label}-${randomUUID().slice(0, 8)}`;
586
+ if (readParked("android").some((entry) => entry.name === ownedAvdName(label)) || findOtherProjectOwningAvd(ownedAvdName(label), projectPath, slot)) label = `${label}-${randomUUID().slice(0, 8)}`;
473
587
  const result = createOwnedAvd(label, { systemImage: flags.systemImage || settings.android?.systemImage });
474
588
  setDevice(projectPath, "android", {
475
589
  avdName: result.avdName,
@@ -477,35 +591,52 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
477
591
  deviceName: result.avdName,
478
592
  setupIncomplete: true,
479
593
  poolConfiguration: configuration
480
- });
594
+ }, slot);
481
595
  return result;
482
596
  });
483
597
  fresh = true;
484
598
  } catch (e) {
485
599
  const message = String(e?.message || e);
486
600
  const avdName = ownedAvdName(label);
487
- if (message.includes("already exists") && listAvds().includes(avdName)) {
488
- created = withConfigLock(() => {
489
- if (readParked("android").some((entry) => entry.name === avdName)) throw new Error(`AVD ${avdName} was parked by another Stim run. Retry to adopt it safely.`, { cause: e });
490
- const owner = findOtherProjectOwningAvd(avdName, projectPath);
491
- if (owner) throw new Error(`AVD ${avdName} already exists and is owned by another project (${owner}). Retry to allocate a distinct owned emulator.`, { cause: e });
492
- const current = loadConfig()?.projects?.[projectPath]?.platforms?.android;
493
- if (current?.avdName) {
494
- const state = current.setupIncomplete ? "has incomplete setup" : "was registered";
495
- throw new Error(`AVD ${current.avdName} ${state} by another concurrent Stim run. Retry after that run finishes so the recorded device is resolved safely.`, { cause: e });
496
- }
497
- const result = {
498
- avdName,
499
- systemImage: ownedAvdSystemImage(avdName)
500
- };
501
- setDevice(projectPath, "android", {
502
- avdName,
503
- owned: true,
504
- deviceName: avdName
601
+ if (message.includes("already exists")) {
602
+ try {
603
+ if (!listAvds().includes(avdName)) throw new AvdRecoveryError(`AVD ${avdName} already exists on disk but is not listed by the emulator. ${message}`, "Run `npx stim gc` to inspect orphaned owned AVDs, then `npx stim gc --delete` to reclaim those safe to delete. Retry `stim android` after cleanup; keep any AVD that GC cannot verify.", e);
604
+ created = withConfigLock(() => {
605
+ if (readParked("android").some((entry) => entry.name === avdName)) throw new Error(`AVD ${avdName} was parked by another Stim run. Retry to adopt it safely.`, { cause: e });
606
+ const owner = findOtherProjectOwningAvd(avdName, projectPath, slot);
607
+ if (owner) throw new Error(`AVD ${avdName} already exists and is owned by another project (${owner}). Retry to allocate a distinct owned emulator.`, { cause: e });
608
+ const current = deviceSlotPlatforms(loadConfig()?.projects?.[projectPath], slot)?.android;
609
+ if (current?.avdName) {
610
+ const state = current.setupIncomplete ? "has incomplete setup" : "was registered";
611
+ throw new Error(`AVD ${current.avdName} ${state} by another concurrent Stim run. Retry after that run finishes so the recorded device is resolved safely.`, { cause: e });
612
+ }
613
+ const resolved = resolveOwnedAvdSerial(avdName);
614
+ if (resolved.missing || resolved.notOwned) throw new Error(`AVD ${avdName} could not be verified for recovery. Retry after checking its registration.`, { cause: e });
615
+ if (!resolved.serial) assertOwnedAvdStopped(avdName);
616
+ const recovered = {
617
+ avdName,
618
+ owned: true,
619
+ deviceName: avdName,
620
+ ...resolved.serial ? { consolePort: Number(resolved.serial.replace(/^emulator-/, "")) } : {}
621
+ };
622
+ setDevice(projectPath, "android", recovered, slot);
623
+ return {
624
+ ...recovered,
625
+ systemImage: ownedAvdSystemImage(avdName),
626
+ serial: resolved.serial
627
+ };
505
628
  });
506
- return result;
507
- });
629
+ } catch (error) {
630
+ if (error instanceof AvdRecoveryError) throw error;
631
+ throw new AvdRecoveryError(`Could not recover owned AVD ${avdName}: ${String(error?.message || error)}`, "Inspect `npx stim status` and `adb devices`. Wait for any other Stim run using this AVD to finish, then retry `stim android`. Keep the AVD and its process locks while its state is unverified.", error);
632
+ }
508
633
  out(chalk.dim(phaseLine("device", `recovered ${avdName} (unrecorded from a prior run)`)));
634
+ if (created.serial) return {
635
+ ...created,
636
+ owned: true,
637
+ deviceName: avdName,
638
+ created: false
639
+ };
509
640
  } else throw e;
510
641
  }
511
642
  if (fresh) try {
@@ -514,9 +645,12 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
514
645
  avdConfig
515
646
  });
516
647
  } catch (error) {
517
- const cleanup = teardownAvd(created.avdName, { del: true });
648
+ const cleanup = teardownAvd(created.avdName, {
649
+ del: true,
650
+ owner: { projectPath }
651
+ });
518
652
  const kept = cleanup.status === "failed" || cleanup.status === "skipped";
519
- if (!kept) clearDevice(projectPath, "android");
653
+ if (!kept) clearDevice(projectPath, "android", slot);
520
654
  const orphan = kept ? ` The owned AVD remains tracked for cleanup (${cleanup.reason || cleanup.status}); fix the cause, then retry or run \`stim gc --delete\`.` : "";
521
655
  throw new Error(`Created owned AVD ${created.avdName}, but could not configure its AVD settings: ${String(error?.message || error)}${orphan}`, { cause: error });
522
656
  }
@@ -525,16 +659,17 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
525
659
  avdName: created.avdName,
526
660
  metadata: fresh ? { poolConfiguration: configuration } : void 0,
527
661
  projectPath,
662
+ slot,
528
663
  deviceName: created.avdName,
529
664
  out,
530
665
  logFile,
531
666
  alive
532
667
  }),
533
- created: true,
668
+ created: fresh,
534
669
  systemImage: created.systemImage
535
670
  };
536
671
  }
537
- function claimAndroidConsolePort({ projectPath, avdName, deviceName, livePorts = [], metadata }, { lock = withConfigLock, recordedPorts = () => allConsolePortsAndSerials().androidConsolePorts, record = setDevice } = {}) {
672
+ function claimAndroidConsolePort({ projectPath, slot, avdName, deviceName, livePorts = [], metadata }, { lock = withConfigLock, recordedPorts = () => allConsolePortsAndSerials().androidConsolePorts, record = setDevice } = {}) {
538
673
  return lock(() => {
539
674
  const consolePort = nextConsolePort([...recordedPorts(), ...livePorts]);
540
675
  const claim = {
@@ -545,7 +680,7 @@ function claimAndroidConsolePort({ projectPath, avdName, deviceName, livePorts =
545
680
  owned: true,
546
681
  deviceName: deviceName ?? avdName
547
682
  };
548
- record(projectPath, "android", claim);
683
+ record(projectPath, "android", claim, slot);
549
684
  return claim;
550
685
  });
551
686
  }
@@ -553,9 +688,10 @@ function liveAndroidConsolePorts() {
553
688
  const adbLive = listAdbDevices();
554
689
  return [...adbLive.emulators.map((e) => e.consolePort), ...adbLive.unhealthy.map((u) => u.consolePort).filter((p) => p != null)];
555
690
  }
556
- async function bootOwnedAvdOnFreshPort({ avdName, metadata, projectPath, deviceName, out, logFile = null, alive = pidExists }) {
691
+ async function bootOwnedAvdOnFreshPort({ avdName, metadata, projectPath, slot, deviceName, out, logFile = null, alive = pidExists }) {
557
692
  const claim = claimAndroidConsolePort({
558
693
  projectPath,
694
+ slot,
559
695
  avdName,
560
696
  deviceName,
561
697
  livePorts: liveAndroidConsolePorts(),
@@ -574,7 +710,7 @@ async function bootOwnedAvdOnFreshPort({ avdName, metadata, projectPath, deviceN
574
710
  serial
575
711
  };
576
712
  } catch (error) {
577
- releaseAndroidConsolePort(projectPath, claim.consolePort);
713
+ releaseAndroidConsolePort(projectPath, claim.consolePort, slot);
578
714
  throw error;
579
715
  }
580
716
  }
@@ -589,25 +725,26 @@ function liveOwnedDeviceCount({ sims = [], adbEmulators = [], config = null } =
589
725
  let count = 0;
590
726
  for (const sim of sims) if (sim?.state === "Booted" && sim.name?.startsWith("stim-")) count++;
591
727
  const livePorts = new Set(adbEmulators.map((e) => e.consolePort));
592
- for (const proj of Object.values(config?.projects || {})) {
593
- const android = proj?.platforms?.android;
728
+ for (const proj of Object.values(config?.projects || {})) for (const { platforms } of projectDeviceSlots(proj)) {
729
+ const android = platforms.android;
594
730
  if (android?.owned && android.avdName && typeof android.consolePort === "number" && livePorts.has(android.consolePort)) count++;
595
731
  }
596
732
  return count;
597
733
  }
598
- function workspaceHasLiveDevice({ platform, project, sims = [], adbEmulators = [] } = {}) {
734
+ function workspaceHasLiveDevice({ platform, project, slot = "default", sims = [], adbEmulators = [] } = {}) {
599
735
  if (!platform) return false;
600
- const record = project?.platforms?.[platform];
736
+ const record = deviceSlotPlatforms(project, slot)?.[platform];
601
737
  if (!record) return false;
602
738
  if (platform === "ios") return sims.some((s) => s.udid === record.deviceUdid && s.state === "Booted");
603
739
  return typeof record.consolePort === "number" && adbEmulators.some((e) => e.consolePort === record.consolePort);
604
740
  }
605
- function deviceCapacityRefusal({ platform, project, max, sims = [], adb = null, config = null } = {}) {
741
+ function deviceCapacityRefusal({ platform, project, slot = "default", max, sims = [], adb = null, config = null } = {}) {
606
742
  if (!max || max <= 0) return null;
607
743
  const adbEmulators = adb?.emulators || [];
608
744
  if (workspaceHasLiveDevice({
609
745
  platform,
610
746
  project,
747
+ slot,
611
748
  sims,
612
749
  adbEmulators
613
750
  })) return null;
@@ -623,7 +760,7 @@ function deviceCapacityRefusal({ platform, project, max, sims = [], adb = null,
623
760
  remedy: "stop an environment (stim stop) or raise concurrency.maxDevices"
624
761
  };
625
762
  }
626
- function checkDeviceCapacity({ platform, project, max, sims = listAllIosSims, adb = listAdbDevices, config = loadConfig } = {}) {
763
+ function checkDeviceCapacity({ platform, project, slot = "default", max, sims = listAllIosSims, adb = listAdbDevices, config = loadConfig } = {}) {
627
764
  if (!max || max <= 0) return null;
628
765
  let simList = [];
629
766
  let adbRes = {
@@ -644,6 +781,7 @@ function checkDeviceCapacity({ platform, project, max, sims = listAllIosSims, ad
644
781
  return deviceCapacityRefusal({
645
782
  platform,
646
783
  project,
784
+ slot,
647
785
  max,
648
786
  sims: simList,
649
787
  adb: adbRes,
@@ -716,6 +854,26 @@ async function ensureIosBooted({ device, timeoutMs, pollMs, out }) {
716
854
  failed: true,
717
855
  reason: "No iOS simulator is recorded for this project."
718
856
  };
857
+ const ready = () => {
858
+ try {
859
+ getExecutor().runFile("xcrun", [
860
+ "simctl",
861
+ "spawn",
862
+ udid,
863
+ "launchctl",
864
+ "list"
865
+ ], { timeoutMs: 3e4 });
866
+ return {
867
+ ok: true,
868
+ udid
869
+ };
870
+ } catch (error) {
871
+ return {
872
+ failed: true,
873
+ reason: `Simulator ${udid} failed its process-spawn readiness check: ${error?.message || error}. ${iosSimulatorFailureAdvice()}`
874
+ };
875
+ }
876
+ };
719
877
  const booting = device?.booting;
720
878
  if (booting?.udid === udid) {
721
879
  try {
@@ -726,10 +884,7 @@ async function ensureIosBooted({ device, timeoutMs, pollMs, out }) {
726
884
  reason: `Could not boot simulator ${udid}: ${e?.message || e}`
727
885
  };
728
886
  }
729
- return {
730
- ok: true,
731
- udid
732
- };
887
+ return ready();
733
888
  }
734
889
  let resolved;
735
890
  try {
@@ -749,14 +904,15 @@ async function ensureIosBooted({ device, timeoutMs, pollMs, out }) {
749
904
  reason: `Simulator ${udid} is now named "${resolved.notOwned}" and is not Stim-owned; refusing to boot it.`
750
905
  };
751
906
  const sim = resolved.sim;
752
- if (sim.state === "Booted") return {
753
- ok: true,
754
- udid
755
- };
907
+ if (sim.state === "Booted") return ready();
756
908
  out(chalk.dim(phaseLine("device", `booting ${sim.name} (${udid})`)));
757
909
  const bootDeadline = Date.now() + timeoutMs;
758
910
  try {
759
- await bootIosSim(udid, { timeoutMs });
911
+ await bootIosSim(udid, {
912
+ timeoutMs,
913
+ label: sim.name,
914
+ out
915
+ });
760
916
  } catch (e) {
761
917
  return {
762
918
  failed: true,
@@ -770,10 +926,7 @@ async function ensureIosBooted({ device, timeoutMs, pollMs, out }) {
770
926
  try {
771
927
  state = listAllIosSims({ timeoutMs: 3e4 }).find((s) => s.udid === udid)?.state ?? null;
772
928
  } catch {}
773
- if (state === "Booted") return {
774
- ok: true,
775
- udid
776
- };
929
+ if (state === "Booted") return ready();
777
930
  }
778
931
  return {
779
932
  failed: true,
@@ -1702,4 +1855,4 @@ async function buildIos({ root, udid = null, logWriter, project = null, scheme =
1702
1855
  };
1703
1856
  }
1704
1857
  //#endregion
1705
- export { unknownIosDeviceTypeRefusal as C, unknownAndroidSystemImageRefusal as S, simslimIsOnPath as T, checkDeviceCapacity as _, ccacheEnabled as a, ensureOwnedDevice as b, discoverXcodeProject as c, resolveScheme as d, startBuildHeartbeat as f, podInstallCommand as g, bundlerPin as h, buildIos as i, readBundleExecutable as l, describeDiagnostic as m, COMPILATION_CACHE_UNAVAILABLE as n, compilationCacheActivityLine as o, tailLines as p, HEARTBEAT_INTERVAL_MS as r, detectXcodeMajor as s, COMPILATION_CACHE_NOT_RUN as t, readBundleId as u, clearIosAdoptionPending as v, unknownIosRuntimeRefusal as w, liveOwnedDeviceCount as x, ensureBooted as y };
1858
+ export { unknownAndroidSystemImageRefusal as C, simslimIsOnPath as E, liveOwnedDeviceCount as S, unknownIosRuntimeRefusal as T, AvdRecoveryError as _, ccacheEnabled as a, ensureBooted as b, discoverXcodeProject as c, resolveScheme as d, startBuildHeartbeat as f, podInstallCommand as g, bundlerPin as h, buildIos as i, readBundleExecutable as l, describeDiagnostic as m, COMPILATION_CACHE_UNAVAILABLE as n, compilationCacheActivityLine as o, tailLines as p, HEARTBEAT_INTERVAL_MS as r, detectXcodeMajor as s, COMPILATION_CACHE_NOT_RUN as t, readBundleId as u, checkDeviceCapacity as v, unknownIosDeviceTypeRefusal as w, ensureOwnedDevice as x, clearIosAdoptionPending as y };