stim 1.2.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.
- package/README.md +30 -0
- package/dist/android-BqVIJoG7.mjs +1368 -0
- package/dist/{android-Bcmev2s2.mjs → android-CqcW1hrP.mjs} +148 -56
- package/dist/{android-cas-D6HPZ6UQ.mjs → android-cas-BR5YJBYv.mjs} +5 -5
- package/dist/{app-install-NFxUahnH.mjs → app-install-DIp9riNx.mjs} +6 -6
- package/dist/{build-slots-D0b6sJyo.mjs → build-slots-C3-R4XQr.mjs} +2 -2
- package/dist/{cache-manifest-Cu4_Znw9.mjs → cache-manifest-CXR-Y8pH.mjs} +1 -1
- package/dist/cache-manifest.mjs +1 -1
- package/dist/cli.mjs +13 -13
- package/dist/collector-run.d.mts +3 -1
- package/dist/collector-run.mjs +33 -8
- package/dist/{config-CMtIaTk9.mjs → config-CcefMY2Q.mjs} +93 -12
- package/dist/{deps-BLBsTNDS.mjs → deps-Spz8ozgo.mjs} +1 -1
- package/dist/{dev-client-RpvXxCXV.mjs → dev-client-BjisHDB5.mjs} +186 -9
- package/dist/{device-CoCPmazS.mjs → device-BkiW-gkk.mjs} +19 -11
- package/dist/{device-lease-Dpik41RY.mjs → device-lease-BJYybF-2.mjs} +107 -83
- package/dist/{device-pool-B5pEVa3t.mjs → device-pool-CPbLGfrB.mjs} +18 -12
- package/dist/{device-remote-E81KAdXf.mjs → device-remote-AkYCKS8U.mjs} +7 -7
- package/dist/{doctor-CqPeMsSm.mjs → doctor-Bmv86UUW.mjs} +11 -12
- package/dist/{doctor-D_CX7ib5.mjs → doctor-fAMXC4vl.mjs} +4 -4
- package/dist/{error-diagnostics-Dw8Gn3yw.mjs → error-diagnostics-DHC31rXA.mjs} +62 -52
- package/dist/{gc-B7KkDinF.mjs → gc-GGu-8ULN.mjs} +66 -57
- package/dist/{guide-BS2Xc24o.mjs → guide-92CPA21s.mjs} +196 -13
- package/dist/{ios-B7KLgIp5.mjs → ios-BSXFeO5H.mjs} +183 -54
- package/dist/{ios-D1h1Di39.mjs → ios-Deh5js5V.mjs} +78 -40
- package/dist/{ios-device-xNt0Lg6v.mjs → ios-device-CWOM_S44.mjs} +1 -1
- package/dist/{logs-DcX9AvRF.mjs → logs-DPNF4C9s.mjs} +9 -6
- package/dist/{logs-query-oqn47Ffx.mjs → logs-query-R-Cqc6Qv.mjs} +22 -5
- package/dist/{metro-COslRK_F.mjs → metro-CORqXyTL.mjs} +2 -2
- package/dist/{ndjson-DcAtEx_K.mjs → ndjson-BZwI1NBv.mjs} +5 -2
- package/dist/{ownership-CGPart6T.mjs → ownership-8O073GIC.mjs} +3 -3
- package/dist/{ownership-CYOyqxUo.mjs → ownership-BpCKiRlQ.mjs} +3 -3
- package/dist/{ownership-claim-7zRxxTfZ.mjs → ownership-claim-Bf2CAfw3.mjs} +4 -3
- package/dist/{project-BBTVABUz.mjs → project-fKmuIaMI.mjs} +2 -2
- package/dist/{reclaim-C5Jmuahx.mjs → reclaim-iW9Cad7k.mjs} +80 -74
- package/dist/{reload-Z8nKifAk.mjs → reload-DazHDSFA.mjs} +32 -24
- package/dist/{server-bare-DEk37Mz2.mjs → server-bare-DEzPZLvf.mjs} +2 -2
- package/dist/server-expo-44em5Pmg.mjs +2 -0
- package/dist/{server-expo-C3ktAwUG.mjs → server-expo-DizT4OMk.mjs} +4 -4
- package/dist/{settings-DwU1_U_q.mjs → settings-DEJf6_kJ.mjs} +2 -2
- package/dist/slot-launch-cci0xvmC.mjs +19 -0
- package/dist/{start-BrY4EuIg.mjs → start-mObjQH2W.mjs} +11 -11
- package/dist/{state-CZ-ER-8d.mjs → state-B3XA2wp2.mjs} +9 -9
- package/dist/{stats-BCWEVLrM.mjs → stats-BR-kwj0B.mjs} +1 -1
- package/dist/{stats-BsF15Bti.mjs → stats-CaaQr4yN.mjs} +3 -3
- package/dist/{status-DFI1Hfpg.mjs → status-BxQNqu9t.mjs} +55 -24
- package/dist/{stop-B7DR4awK.mjs → stop-CrHGcjrV.mjs} +2 -2
- package/dist/{stop-Btg770vV.mjs → stop-DimGXEKY.mjs} +93 -42
- package/dist/supervisor-run.d.mts +1 -2
- package/dist/supervisor-run.mjs +5 -5
- package/dist/{remote-cache-DDmJ1Roq.mjs → teardown-ClFp1Aax.mjs} +887 -888
- package/dist/{workspace-process-lock-BKfdys1q.mjs → workspace-process-lock-3NcQnZ0X.mjs} +1 -1
- package/dist/{worktree-BPTbI-LN.mjs → worktree-DxTgN1CJ.mjs} +12 -12
- package/dist/{worktree-C79xx_kM.mjs → worktree-Eq6TLH8N.mjs} +1 -1
- package/dist/{xcode-DeKCribl.mjs → xcode-D7sAp-Zy.mjs} +82 -56
- package/package.json +5 -5
- package/dist/android-K63_0UfF.mjs +0 -727
- package/dist/build-lock-BsVoLDaq.mjs +0 -645
- package/dist/server-expo-Drd7ksHu.mjs +0 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { f as releaseClaim, h as tryAcquireClaim } from "./ownership-claim-
|
|
1
|
+
import { f as releaseClaim, h as tryAcquireClaim } from "./ownership-claim-Bf2CAfw3.mjs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
//#region src/engine/workspace-process-lock.ts
|
|
4
4
|
const DEFAULT_WAIT_MS = 6e4;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { t as getExecutor } from "./exec-CyylIdq9.mjs";
|
|
2
|
-
import { S as upsertProject, f as getProject, g as loadConfig, h as isPathPrefix, u as getConfigDir, v as removeProject, w as captureProcessIdentity } from "./config-
|
|
3
|
-
import { c as readMetroTunnel, u as readRemoteSession } from "./state-
|
|
4
|
-
import { _ as resolveFullRef, b as warmWorktreePaths, c as hasRemote, d as isPodInstallChurn, f as listWorktrees, h as removeWorktree, i as depsOutOfSync, l as hasUncommittedWork, m as readWorktreeExclude, n as cloneIgnoredEntries, o as dirtyPaths, p as podsOutOfSync, r as deleteBranch, s as gitCommonDir, t as branchExists, u as isMainWorkingTree, v as restoreFile, y as unpushedCommits } from "./worktree-
|
|
5
|
-
import { a as findProjectRoot } from "./project-
|
|
6
|
-
import { v as POOL_SETTING_REMEDY, x as parkedMaxSetting } from "./remote-cache-DDmJ1Roq.mjs";
|
|
7
|
-
import { A as resolveSettings, I as unknownSettingKeys, N as settingShapeErrors, a as SETTING_SHAPE_REMEDY } from "./settings-DwU1_U_q.mjs";
|
|
2
|
+
import { S as upsertProject, f as getProject, g as loadConfig, h as isPathPrefix, u as getConfigDir, v as removeProject, w as captureProcessIdentity } from "./config-CcefMY2Q.mjs";
|
|
3
|
+
import { c as readMetroTunnel, u as readRemoteSession } from "./state-B3XA2wp2.mjs";
|
|
4
|
+
import { _ as resolveFullRef, b as warmWorktreePaths, c as hasRemote, d as isPodInstallChurn, f as listWorktrees, h as removeWorktree, i as depsOutOfSync, l as hasUncommittedWork, m as readWorktreeExclude, n as cloneIgnoredEntries, o as dirtyPaths, p as podsOutOfSync, r as deleteBranch, s as gitCommonDir, t as branchExists, u as isMainWorkingTree, v as restoreFile, y as unpushedCommits } from "./worktree-Eq6TLH8N.mjs";
|
|
5
|
+
import { a as findProjectRoot } from "./project-fKmuIaMI.mjs";
|
|
8
6
|
import { a as formatElapsed, f as releasedLeaseFact, i as formatDuration, l as phaseLine, m as shortUdid, u as plural } from "./command-output-8wHMEde0.mjs";
|
|
9
|
-
import { a as clearClaimChild, c as isClaimUnavailable, d as readClaimSet, f as releaseClaim, h as tryAcquireClaim, i as claimRemoveCommand, l as markClaimChildPending, m as settleClaim, p as setClaimChild, r as claimFailure, s as isClaimRefusal, u as processGroupAlive } from "./ownership-claim-
|
|
10
|
-
import {
|
|
11
|
-
import { a as
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
7
|
+
import { a as clearClaimChild, c as isClaimUnavailable, d as readClaimSet, f as releaseClaim, h as tryAcquireClaim, i as claimRemoveCommand, l as markClaimChildPending, m as settleClaim, p as setClaimChild, r as claimFailure, s as isClaimRefusal, u as processGroupAlive } from "./ownership-claim-Bf2CAfw3.mjs";
|
|
8
|
+
import { A as resolveSettings, I as unknownSettingKeys, N as settingShapeErrors, a as SETTING_SHAPE_REMEDY } from "./settings-DEJf6_kJ.mjs";
|
|
9
|
+
import { a as POOL_SETTING_REMEDY, c as parkedMaxSetting } from "./teardown-ClFp1Aax.mjs";
|
|
10
|
+
import { g as podInstallCommand, r as HEARTBEAT_INTERVAL_MS } from "./xcode-D7sAp-Zy.mjs";
|
|
11
|
+
import { a as installedNpmTreeIsValid, i as hasInstalledDependencies, o as locallyKnownUpstream, t as dependencyState } from "./doctor-Bmv86UUW.mjs";
|
|
12
|
+
import { c as withManagedTunnelRemovalLock, o as withManagedRemoteWorktreeRemovalLock } from "./ownership-BpCKiRlQ.mjs";
|
|
13
|
+
import { n as reclaimProject } from "./reclaim-iW9Cad7k.mjs";
|
|
14
|
+
import { a as runPodInstall, i as runCaptured, n as podsAreStale, r as readPodState, t as DEPS_ERROR } from "./deps-Spz8ozgo.mjs";
|
|
15
15
|
import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
16
16
|
import { createHash, randomUUID } from "node:crypto";
|
|
17
17
|
import { join, relative } from "node:path";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as getExecutor } from "./exec-CyylIdq9.mjs";
|
|
2
|
-
import { g as loadConfig, u as getConfigDir } from "./config-
|
|
2
|
+
import { g as loadConfig, u as getConfigDir } from "./config-CcefMY2Q.mjs";
|
|
3
3
|
import { accessSync, chmodSync, constants, lstatSync, mkdirSync, mkdtempSync, readdirSync, realpathSync, rmSync, statSync } from "node:fs";
|
|
4
4
|
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
5
5
|
import { chmodSync as chmodSync$1, existsSync as existsSync$1, lstatSync as lstatSync$1, mkdirSync as mkdirSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, realpathSync as realpathSync$1, utimesSync } from "fs";
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { t as getExecutor } from "./exec-CyylIdq9.mjs";
|
|
2
|
-
import { C as withConfigLock, E as inspectProcessIdentity, _ as releaseAndroidConsolePort, b as setDevice, g as loadConfig, i as clearDevice, t as allConsolePortsAndSerials, u as getConfigDir, w as captureProcessIdentity, y as saveConfig } from "./config-
|
|
3
|
-
import { r as register } from "./cache-manifest-
|
|
4
|
-
import { E as workspaceId, S as sharedCompilationCache, w as workspaceDerivedData } from "./state-
|
|
5
|
-
import { s as ownedDeviceLabel } from "./project-
|
|
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-
|
|
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-DDmJ1Roq.mjs";
|
|
9
|
-
import { U as resolveOptimizations, l as androidDataPartitionSizeGbSetting, o as androidAvdConfigSetting, v as iosSimSlimProfileSetting } from "./settings-DwU1_U_q.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 {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { t as
|
|
15
|
-
import { t as
|
|
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";
|
|
16
16
|
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
17
17
|
import { createHash, randomUUID } from "node:crypto";
|
|
18
18
|
import { basename, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
@@ -161,9 +161,12 @@ function simslimIsOnPath() {
|
|
|
161
161
|
}
|
|
162
162
|
//#endregion
|
|
163
163
|
//#region src/engine/device.ts
|
|
164
|
-
function startIosBoot(udid, configure) {
|
|
164
|
+
function startIosBoot(udid, configure, label, out) {
|
|
165
165
|
const done = (async () => {
|
|
166
|
-
await bootIosSim(udid
|
|
166
|
+
await bootIosSim(udid, {
|
|
167
|
+
label,
|
|
168
|
+
out
|
|
169
|
+
});
|
|
167
170
|
await configure();
|
|
168
171
|
})();
|
|
169
172
|
done.catch(() => {});
|
|
@@ -172,11 +175,13 @@ function startIosBoot(udid, configure) {
|
|
|
172
175
|
done
|
|
173
176
|
};
|
|
174
177
|
}
|
|
175
|
-
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 }) {
|
|
176
|
-
|
|
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;
|
|
177
181
|
if (platform === "ios") return ensureOwnedIosDevice({
|
|
178
182
|
record,
|
|
179
183
|
projectPath,
|
|
184
|
+
slot,
|
|
180
185
|
settingsRoot,
|
|
181
186
|
label,
|
|
182
187
|
settings,
|
|
@@ -188,6 +193,7 @@ async function ensureOwnedDevice({ platform, project, projectPath, settingsRoot
|
|
|
188
193
|
return ensureOwnedAndroidDevice({
|
|
189
194
|
record,
|
|
190
195
|
projectPath,
|
|
196
|
+
slot,
|
|
191
197
|
settingsRoot,
|
|
192
198
|
label,
|
|
193
199
|
settings,
|
|
@@ -200,7 +206,7 @@ async function ensureOwnedDevice({ platform, project, projectPath, settingsRoot
|
|
|
200
206
|
teardownAvd
|
|
201
207
|
});
|
|
202
208
|
}
|
|
203
|
-
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 }) {
|
|
204
210
|
const memoryAdvice = hostMemoryPressureAdvice(readHostMemoryPressure());
|
|
205
211
|
if (memoryAdvice) out(chalk.yellow(phaseLine("memory", memoryAdvice)));
|
|
206
212
|
const simslimProfile = iosSimSlimProfileSetting(settings, settingsRoot);
|
|
@@ -233,6 +239,7 @@ async function ensureOwnedIosDevice({ record, projectPath, settingsRoot, label,
|
|
|
233
239
|
return configureOwnedIosSim({
|
|
234
240
|
record: updated,
|
|
235
241
|
projectPath,
|
|
242
|
+
slot,
|
|
236
243
|
profile: simslimProfile,
|
|
237
244
|
out,
|
|
238
245
|
reconcileIosSimulator
|
|
@@ -246,7 +253,7 @@ async function ensureOwnedIosDevice({ record, projectPath, settingsRoot, label,
|
|
|
246
253
|
out(chalk.dim(phaseLine("device", `booting ${name} (${sim.udid})`)));
|
|
247
254
|
return {
|
|
248
255
|
...updated,
|
|
249
|
-
booting: startIosBoot(sim.udid, configure),
|
|
256
|
+
booting: startIosBoot(sim.udid, configure, name, out),
|
|
250
257
|
...facts
|
|
251
258
|
};
|
|
252
259
|
}
|
|
@@ -265,6 +272,12 @@ async function ensureOwnedIosDevice({ record, projectPath, settingsRoot, label,
|
|
|
265
272
|
return record;
|
|
266
273
|
}
|
|
267
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
|
+
});
|
|
268
281
|
}
|
|
269
282
|
const choice = resolveIosCreation({
|
|
270
283
|
deviceType: flags.deviceType || settings.ios?.deviceType,
|
|
@@ -272,6 +285,7 @@ async function ensureOwnedIosDevice({ record, projectPath, settingsRoot, label,
|
|
|
272
285
|
});
|
|
273
286
|
const adopted = parkedMaxSetting("ios").max > 0 ? await withIosDeviceNameLock(() => takeParkedIosSim({
|
|
274
287
|
projectPath,
|
|
288
|
+
slot,
|
|
275
289
|
label,
|
|
276
290
|
choice,
|
|
277
291
|
out
|
|
@@ -283,11 +297,12 @@ async function ensureOwnedIosDevice({ record, projectPath, settingsRoot, label,
|
|
|
283
297
|
await configureOwnedIosSim({
|
|
284
298
|
record: adopted,
|
|
285
299
|
projectPath,
|
|
300
|
+
slot,
|
|
286
301
|
profile: simslimProfile,
|
|
287
302
|
out,
|
|
288
303
|
reconcileIosSimulator
|
|
289
304
|
});
|
|
290
|
-
});
|
|
305
|
+
}, adopted.deviceName, out);
|
|
291
306
|
return {
|
|
292
307
|
...adopted,
|
|
293
308
|
booting,
|
|
@@ -305,7 +320,7 @@ async function ensureOwnedIosDevice({ record, projectPath, settingsRoot, label,
|
|
|
305
320
|
deviceUdid: result.udid,
|
|
306
321
|
owned: true,
|
|
307
322
|
deviceName: result.name
|
|
308
|
-
});
|
|
323
|
+
}, slot);
|
|
309
324
|
return result;
|
|
310
325
|
});
|
|
311
326
|
const newRecord = {
|
|
@@ -316,10 +331,11 @@ async function ensureOwnedIosDevice({ record, projectPath, settingsRoot, label,
|
|
|
316
331
|
const booting = startIosBoot(created.udid, () => configureOwnedIosSim({
|
|
317
332
|
record: newRecord,
|
|
318
333
|
projectPath,
|
|
334
|
+
slot,
|
|
319
335
|
profile: simslimProfile,
|
|
320
336
|
out,
|
|
321
337
|
reconcileIosSimulator
|
|
322
|
-
}));
|
|
338
|
+
}), created.name, out);
|
|
323
339
|
return {
|
|
324
340
|
...newRecord,
|
|
325
341
|
created: true,
|
|
@@ -333,8 +349,8 @@ function withIosDeviceNameLock(fn) {
|
|
|
333
349
|
}
|
|
334
350
|
function ownedIosNameSuffix(label, model, projectPath, udid) {
|
|
335
351
|
const names = new Set(listAllIosSims({ includeUnavailable: true }).filter((sim) => sim.udid !== udid).map((sim) => sim.name));
|
|
336
|
-
for (const project of Object.values(loadConfig()?.projects ?? {})) {
|
|
337
|
-
const record =
|
|
352
|
+
for (const project of Object.values(loadConfig()?.projects ?? {})) for (const { platforms } of projectDeviceSlots(project)) {
|
|
353
|
+
const record = platforms.ios;
|
|
338
354
|
if (record?.deviceUdid !== udid && record?.deviceName) names.add(record.deviceName);
|
|
339
355
|
}
|
|
340
356
|
for (const parked of readParked("ios")) if (parked.udid !== udid) names.add(parked.name);
|
|
@@ -357,7 +373,7 @@ function resetAdoptedSim(udid, out) {
|
|
|
357
373
|
resetIosPrivacy(udid);
|
|
358
374
|
resetIosKeychain(udid);
|
|
359
375
|
}
|
|
360
|
-
function takeParkedIosSim({ projectPath, label, choice, out }) {
|
|
376
|
+
function takeParkedIosSim({ projectPath, slot, label, choice, out }) {
|
|
361
377
|
const candidates = selectParked(readParked("ios"), {
|
|
362
378
|
deviceTypeIdentifier: choice.deviceTypeId,
|
|
363
379
|
runtimeIdentifier: choice.runtimeId
|
|
@@ -393,6 +409,7 @@ function takeParkedIosSim({ projectPath, label, choice, out }) {
|
|
|
393
409
|
if (!adoptParked({
|
|
394
410
|
platform: "ios",
|
|
395
411
|
projectPath,
|
|
412
|
+
slot,
|
|
396
413
|
udid: parked.udid,
|
|
397
414
|
device
|
|
398
415
|
})) continue;
|
|
@@ -403,10 +420,10 @@ function takeParkedIosSim({ projectPath, label, choice, out }) {
|
|
|
403
420
|
}
|
|
404
421
|
return null;
|
|
405
422
|
}
|
|
406
|
-
function clearIosAdoptionPending(projectPath) {
|
|
423
|
+
function clearIosAdoptionPending(projectPath, slot = "default") {
|
|
407
424
|
withConfigLock(() => {
|
|
408
425
|
const cfg = loadConfig();
|
|
409
|
-
const ios = cfg?.projects?.[projectPath]?.
|
|
426
|
+
const ios = deviceSlotPlatforms(cfg?.projects?.[projectPath], slot)?.ios;
|
|
410
427
|
if (!cfg || !ios?.adoptionPending) return;
|
|
411
428
|
delete ios.adopted;
|
|
412
429
|
delete ios.adoptionPending;
|
|
@@ -414,7 +431,7 @@ function clearIosAdoptionPending(projectPath) {
|
|
|
414
431
|
saveConfig(cfg);
|
|
415
432
|
});
|
|
416
433
|
}
|
|
417
|
-
async function configureOwnedIosSim({ record, projectPath, profile, out, reconcileIosSimulator }) {
|
|
434
|
+
async function configureOwnedIosSim({ record, projectPath, slot, profile, out, reconcileIosSimulator }) {
|
|
418
435
|
if (profile) out(chalk.dim(phaseLine("device", `applying the SimSlim profile to ${record.deviceUdid}`)));
|
|
419
436
|
else if (record.simslimManaged) out(chalk.dim(phaseLine("device", `restoring stock simulator services on ${record.deviceUdid}`)));
|
|
420
437
|
const previouslyManaged = Boolean(record.simslimManaged);
|
|
@@ -423,7 +440,7 @@ async function configureOwnedIosSim({ record, projectPath, profile, out, reconci
|
|
|
423
440
|
...record,
|
|
424
441
|
simslimManaged: true
|
|
425
442
|
};
|
|
426
|
-
setDevice(projectPath, "ios", pending);
|
|
443
|
+
setDevice(projectPath, "ios", pending, slot);
|
|
427
444
|
record = pending;
|
|
428
445
|
}
|
|
429
446
|
const result = await reconcileIosSimulator({
|
|
@@ -435,15 +452,12 @@ async function configureOwnedIosSim({ record, projectPath, profile, out, reconci
|
|
|
435
452
|
const updated = { ...record };
|
|
436
453
|
if (result.managed) updated.simslimManaged = true;
|
|
437
454
|
else delete updated.simslimManaged;
|
|
438
|
-
setDevice(projectPath, "ios", updated);
|
|
455
|
+
setDevice(projectPath, "ios", updated, slot);
|
|
439
456
|
return updated;
|
|
440
457
|
}
|
|
441
|
-
function findOtherProjectOwningAvd(avdName, projectPath) {
|
|
458
|
+
function findOtherProjectOwningAvd(avdName, projectPath, selectedSlot = "default") {
|
|
442
459
|
const cfg = loadConfig();
|
|
443
|
-
for (const [path, proj] of Object.entries(cfg?.projects || {})) {
|
|
444
|
-
if (path === projectPath) continue;
|
|
445
|
-
if (proj?.platforms?.android?.avdName === avdName) return path;
|
|
446
|
-
}
|
|
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;
|
|
447
461
|
return null;
|
|
448
462
|
}
|
|
449
463
|
var AvdRecoveryError = class extends Error {
|
|
@@ -453,7 +467,7 @@ var AvdRecoveryError = class extends Error {
|
|
|
453
467
|
this.remedy = remedy;
|
|
454
468
|
}
|
|
455
469
|
};
|
|
456
|
-
async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, label, settings, flags, note, out, logFile, alive, configureAvd, teardownAvd }) {
|
|
470
|
+
async function ensureOwnedAndroidDevice({ record, projectPath, slot, settingsRoot, label, settings, flags, note, out, logFile, alive, configureAvd, teardownAvd }) {
|
|
457
471
|
const avdConfig = androidAvdConfigSetting(settings, settingsRoot);
|
|
458
472
|
const configuration = avdPoolConfiguration(androidDataPartitionSizeGbSetting(settings), avdConfig);
|
|
459
473
|
if (record?.setupIncomplete && record.avdName) {
|
|
@@ -462,7 +476,7 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
|
|
|
462
476
|
owner: { projectPath }
|
|
463
477
|
});
|
|
464
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.`);
|
|
465
|
-
clearDevice(projectPath, "android");
|
|
479
|
+
clearDevice(projectPath, "android", slot);
|
|
466
480
|
record = null;
|
|
467
481
|
}
|
|
468
482
|
if (record?.avdName) {
|
|
@@ -479,7 +493,7 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
|
|
|
479
493
|
owned: true,
|
|
480
494
|
deviceName: record.deviceName ?? record.avdName
|
|
481
495
|
};
|
|
482
|
-
setDevice(projectPath, "android", updated);
|
|
496
|
+
setDevice(projectPath, "android", updated, slot);
|
|
483
497
|
return {
|
|
484
498
|
...updated,
|
|
485
499
|
systemImage: ownedAvdSystemImage(record.avdName)
|
|
@@ -491,6 +505,7 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
|
|
|
491
505
|
avdName: record.avdName,
|
|
492
506
|
metadata: record,
|
|
493
507
|
projectPath,
|
|
508
|
+
slot,
|
|
494
509
|
deviceName: record.deviceName,
|
|
495
510
|
out,
|
|
496
511
|
logFile,
|
|
@@ -543,6 +558,7 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
|
|
|
543
558
|
if (!adoptParked({
|
|
544
559
|
platform: "android",
|
|
545
560
|
projectPath,
|
|
561
|
+
slot,
|
|
546
562
|
udid: parked.udid,
|
|
547
563
|
device: adopted
|
|
548
564
|
})) continue;
|
|
@@ -550,6 +566,7 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
|
|
|
550
566
|
...await bootOwnedAvdOnFreshPort({
|
|
551
567
|
avdName: parked.name,
|
|
552
568
|
projectPath,
|
|
569
|
+
slot,
|
|
553
570
|
metadata: adopted,
|
|
554
571
|
out,
|
|
555
572
|
logFile,
|
|
@@ -564,9 +581,9 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
|
|
|
564
581
|
let fresh = false;
|
|
565
582
|
try {
|
|
566
583
|
created = withConfigLock(() => {
|
|
567
|
-
const current = loadConfig()?.projects?.[projectPath]?.
|
|
584
|
+
const current = deviceSlotPlatforms(loadConfig()?.projects?.[projectPath], slot)?.android;
|
|
568
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.`);
|
|
569
|
-
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)}`;
|
|
570
587
|
const result = createOwnedAvd(label, { systemImage: flags.systemImage || settings.android?.systemImage });
|
|
571
588
|
setDevice(projectPath, "android", {
|
|
572
589
|
avdName: result.avdName,
|
|
@@ -574,7 +591,7 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
|
|
|
574
591
|
deviceName: result.avdName,
|
|
575
592
|
setupIncomplete: true,
|
|
576
593
|
poolConfiguration: configuration
|
|
577
|
-
});
|
|
594
|
+
}, slot);
|
|
578
595
|
return result;
|
|
579
596
|
});
|
|
580
597
|
fresh = true;
|
|
@@ -586,9 +603,9 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
|
|
|
586
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);
|
|
587
604
|
created = withConfigLock(() => {
|
|
588
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 });
|
|
589
|
-
const owner = findOtherProjectOwningAvd(avdName, projectPath);
|
|
606
|
+
const owner = findOtherProjectOwningAvd(avdName, projectPath, slot);
|
|
590
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 });
|
|
591
|
-
const current = loadConfig()?.projects?.[projectPath]?.
|
|
608
|
+
const current = deviceSlotPlatforms(loadConfig()?.projects?.[projectPath], slot)?.android;
|
|
592
609
|
if (current?.avdName) {
|
|
593
610
|
const state = current.setupIncomplete ? "has incomplete setup" : "was registered";
|
|
594
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 });
|
|
@@ -602,7 +619,7 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
|
|
|
602
619
|
deviceName: avdName,
|
|
603
620
|
...resolved.serial ? { consolePort: Number(resolved.serial.replace(/^emulator-/, "")) } : {}
|
|
604
621
|
};
|
|
605
|
-
setDevice(projectPath, "android", recovered);
|
|
622
|
+
setDevice(projectPath, "android", recovered, slot);
|
|
606
623
|
return {
|
|
607
624
|
...recovered,
|
|
608
625
|
systemImage: ownedAvdSystemImage(avdName),
|
|
@@ -633,7 +650,7 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
|
|
|
633
650
|
owner: { projectPath }
|
|
634
651
|
});
|
|
635
652
|
const kept = cleanup.status === "failed" || cleanup.status === "skipped";
|
|
636
|
-
if (!kept) clearDevice(projectPath, "android");
|
|
653
|
+
if (!kept) clearDevice(projectPath, "android", slot);
|
|
637
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\`.` : "";
|
|
638
655
|
throw new Error(`Created owned AVD ${created.avdName}, but could not configure its AVD settings: ${String(error?.message || error)}${orphan}`, { cause: error });
|
|
639
656
|
}
|
|
@@ -642,6 +659,7 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
|
|
|
642
659
|
avdName: created.avdName,
|
|
643
660
|
metadata: fresh ? { poolConfiguration: configuration } : void 0,
|
|
644
661
|
projectPath,
|
|
662
|
+
slot,
|
|
645
663
|
deviceName: created.avdName,
|
|
646
664
|
out,
|
|
647
665
|
logFile,
|
|
@@ -651,7 +669,7 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
|
|
|
651
669
|
systemImage: created.systemImage
|
|
652
670
|
};
|
|
653
671
|
}
|
|
654
|
-
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 } = {}) {
|
|
655
673
|
return lock(() => {
|
|
656
674
|
const consolePort = nextConsolePort([...recordedPorts(), ...livePorts]);
|
|
657
675
|
const claim = {
|
|
@@ -662,7 +680,7 @@ function claimAndroidConsolePort({ projectPath, avdName, deviceName, livePorts =
|
|
|
662
680
|
owned: true,
|
|
663
681
|
deviceName: deviceName ?? avdName
|
|
664
682
|
};
|
|
665
|
-
record(projectPath, "android", claim);
|
|
683
|
+
record(projectPath, "android", claim, slot);
|
|
666
684
|
return claim;
|
|
667
685
|
});
|
|
668
686
|
}
|
|
@@ -670,9 +688,10 @@ function liveAndroidConsolePorts() {
|
|
|
670
688
|
const adbLive = listAdbDevices();
|
|
671
689
|
return [...adbLive.emulators.map((e) => e.consolePort), ...adbLive.unhealthy.map((u) => u.consolePort).filter((p) => p != null)];
|
|
672
690
|
}
|
|
673
|
-
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 }) {
|
|
674
692
|
const claim = claimAndroidConsolePort({
|
|
675
693
|
projectPath,
|
|
694
|
+
slot,
|
|
676
695
|
avdName,
|
|
677
696
|
deviceName,
|
|
678
697
|
livePorts: liveAndroidConsolePorts(),
|
|
@@ -691,7 +710,7 @@ async function bootOwnedAvdOnFreshPort({ avdName, metadata, projectPath, deviceN
|
|
|
691
710
|
serial
|
|
692
711
|
};
|
|
693
712
|
} catch (error) {
|
|
694
|
-
releaseAndroidConsolePort(projectPath, claim.consolePort);
|
|
713
|
+
releaseAndroidConsolePort(projectPath, claim.consolePort, slot);
|
|
695
714
|
throw error;
|
|
696
715
|
}
|
|
697
716
|
}
|
|
@@ -706,25 +725,26 @@ function liveOwnedDeviceCount({ sims = [], adbEmulators = [], config = null } =
|
|
|
706
725
|
let count = 0;
|
|
707
726
|
for (const sim of sims) if (sim?.state === "Booted" && sim.name?.startsWith("stim-")) count++;
|
|
708
727
|
const livePorts = new Set(adbEmulators.map((e) => e.consolePort));
|
|
709
|
-
for (const proj of Object.values(config?.projects || {})) {
|
|
710
|
-
const android =
|
|
728
|
+
for (const proj of Object.values(config?.projects || {})) for (const { platforms } of projectDeviceSlots(proj)) {
|
|
729
|
+
const android = platforms.android;
|
|
711
730
|
if (android?.owned && android.avdName && typeof android.consolePort === "number" && livePorts.has(android.consolePort)) count++;
|
|
712
731
|
}
|
|
713
732
|
return count;
|
|
714
733
|
}
|
|
715
|
-
function workspaceHasLiveDevice({ platform, project, sims = [], adbEmulators = [] } = {}) {
|
|
734
|
+
function workspaceHasLiveDevice({ platform, project, slot = "default", sims = [], adbEmulators = [] } = {}) {
|
|
716
735
|
if (!platform) return false;
|
|
717
|
-
const record = project?.
|
|
736
|
+
const record = deviceSlotPlatforms(project, slot)?.[platform];
|
|
718
737
|
if (!record) return false;
|
|
719
738
|
if (platform === "ios") return sims.some((s) => s.udid === record.deviceUdid && s.state === "Booted");
|
|
720
739
|
return typeof record.consolePort === "number" && adbEmulators.some((e) => e.consolePort === record.consolePort);
|
|
721
740
|
}
|
|
722
|
-
function deviceCapacityRefusal({ platform, project, max, sims = [], adb = null, config = null } = {}) {
|
|
741
|
+
function deviceCapacityRefusal({ platform, project, slot = "default", max, sims = [], adb = null, config = null } = {}) {
|
|
723
742
|
if (!max || max <= 0) return null;
|
|
724
743
|
const adbEmulators = adb?.emulators || [];
|
|
725
744
|
if (workspaceHasLiveDevice({
|
|
726
745
|
platform,
|
|
727
746
|
project,
|
|
747
|
+
slot,
|
|
728
748
|
sims,
|
|
729
749
|
adbEmulators
|
|
730
750
|
})) return null;
|
|
@@ -740,7 +760,7 @@ function deviceCapacityRefusal({ platform, project, max, sims = [], adb = null,
|
|
|
740
760
|
remedy: "stop an environment (stim stop) or raise concurrency.maxDevices"
|
|
741
761
|
};
|
|
742
762
|
}
|
|
743
|
-
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 } = {}) {
|
|
744
764
|
if (!max || max <= 0) return null;
|
|
745
765
|
let simList = [];
|
|
746
766
|
let adbRes = {
|
|
@@ -761,6 +781,7 @@ function checkDeviceCapacity({ platform, project, max, sims = listAllIosSims, ad
|
|
|
761
781
|
return deviceCapacityRefusal({
|
|
762
782
|
platform,
|
|
763
783
|
project,
|
|
784
|
+
slot,
|
|
764
785
|
max,
|
|
765
786
|
sims: simList,
|
|
766
787
|
adb: adbRes,
|
|
@@ -839,7 +860,8 @@ async function ensureIosBooted({ device, timeoutMs, pollMs, out }) {
|
|
|
839
860
|
"simctl",
|
|
840
861
|
"spawn",
|
|
841
862
|
udid,
|
|
842
|
-
"
|
|
863
|
+
"launchctl",
|
|
864
|
+
"list"
|
|
843
865
|
], { timeoutMs: 3e4 });
|
|
844
866
|
return {
|
|
845
867
|
ok: true,
|
|
@@ -886,7 +908,11 @@ async function ensureIosBooted({ device, timeoutMs, pollMs, out }) {
|
|
|
886
908
|
out(chalk.dim(phaseLine("device", `booting ${sim.name} (${udid})`)));
|
|
887
909
|
const bootDeadline = Date.now() + timeoutMs;
|
|
888
910
|
try {
|
|
889
|
-
await bootIosSim(udid, {
|
|
911
|
+
await bootIosSim(udid, {
|
|
912
|
+
timeoutMs,
|
|
913
|
+
label: sim.name,
|
|
914
|
+
out
|
|
915
|
+
});
|
|
890
916
|
} catch (e) {
|
|
891
917
|
return {
|
|
892
918
|
failed: true,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stim",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Stim: fast, isolated React Native environments for coding agents",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -42,16 +42,16 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@expo/fingerprint": "^0.20.10",
|
|
45
|
-
"@stim-cli/cache": "^1.
|
|
46
|
-
"@stim-cli/core": "^1.
|
|
47
|
-
"@stim-cli/metro": "^1.
|
|
45
|
+
"@stim-cli/cache": "^1.3.0",
|
|
46
|
+
"@stim-cli/core": "^1.3.0",
|
|
47
|
+
"@stim-cli/metro": "^1.3.0",
|
|
48
48
|
"chalk": "^5.4.1",
|
|
49
49
|
"commander": "^13.1.0",
|
|
50
50
|
"unique-pid": "0.1.1",
|
|
51
51
|
"ws": "^8.21.3"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@stim-cli/expo-build-cache": "1.
|
|
54
|
+
"@stim-cli/expo-build-cache": "1.3.0",
|
|
55
55
|
"@types/ws": "^8.18.1"
|
|
56
56
|
},
|
|
57
57
|
"engines": {
|