stim 1.1.0 → 1.2.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 +7 -0
- package/dist/{android-CC5bUer7.mjs → android-BW8i_YxU.mjs} +1 -1
- package/dist/{android-DnZlT3aU.mjs → android-Bcmev2s2.mjs} +86 -31
- package/dist/{android-xmyGBNy5.mjs → android-K63_0UfF.mjs} +77 -15
- package/dist/{android-cas-DGlTStWu.mjs → android-cas-D6HPZ6UQ.mjs} +6 -6
- package/dist/android-cas-compiler.mjs +1 -1
- package/dist/{app-install-oZIQRbdD.mjs → app-install-NFxUahnH.mjs} +25 -17
- package/dist/{build-lock-vE45ZzJZ.mjs → build-lock-BsVoLDaq.mjs} +6 -6
- package/dist/{build-slots-CgacA9zQ.mjs → build-slots-D0b6sJyo.mjs} +3 -3
- package/dist/{cache-manifest-oeH18ERr.mjs → cache-manifest-Cu4_Znw9.mjs} +1 -1
- package/dist/cache-manifest.mjs +1 -1
- package/dist/cli.mjs +13 -13
- package/dist/collector-run.d.mts +1 -0
- package/dist/collector-run.mjs +6 -6
- package/dist/{config-D7uu8Gbq.mjs → config-CMtIaTk9.mjs} +1 -1
- package/dist/{deps-64wVnpZc.mjs → deps-BLBsTNDS.mjs} +2 -2
- package/dist/{dev-client-Bvky1hya.mjs → dev-client-RpvXxCXV.mjs} +72 -9
- package/dist/{device-DJKv5Qej.mjs → device-CoCPmazS.mjs} +5 -5
- package/dist/{device-lease-D-G3SgVe.mjs → device-lease-Dpik41RY.mjs} +3 -3
- package/dist/{device-pool-BlHXnYYs.mjs → device-pool-B5pEVa3t.mjs} +3 -3
- package/dist/{device-remote-CCgkG82J.mjs → device-remote-E81KAdXf.mjs} +8 -8
- package/dist/{doctor-DlVxTtMq.mjs → doctor-CqPeMsSm.mjs} +19 -26
- package/dist/{doctor-BRF9aAJ3.mjs → doctor-D_CX7ib5.mjs} +10 -10
- package/dist/{error-diagnostics-B5IJwv3-.mjs → error-diagnostics-Dw8Gn3yw.mjs} +8 -8
- package/dist/{exec-bsN9MJXb.mjs → exec-CyylIdq9.mjs} +4 -2
- package/dist/{gc-DhXdgSdt.mjs → gc-B7KkDinF.mjs} +39 -25
- package/dist/{guide-DrhrDBo5.mjs → guide-BS2Xc24o.mjs} +220 -36
- package/dist/{ios-CK1Vrk6Q.mjs → ios-B7KLgIp5.mjs} +38 -26
- package/dist/{ios-BZxKPuqP.mjs → ios-D1h1Di39.mjs} +79 -10
- package/dist/{ios-device-CYbuRNXR.mjs → ios-device-D3pzTKQE.mjs} +1 -1
- package/dist/{ios-device-CdSm0GDw.mjs → ios-device-xNt0Lg6v.mjs} +2 -2
- package/dist/{logs-Dxoy16Qv.mjs → logs-DcX9AvRF.mjs} +3 -3
- package/dist/{metro-B01H3EuD.mjs → metro-COslRK_F.mjs} +3 -3
- package/dist/{ownership-D8HmSv2E.mjs → ownership-CGPart6T.mjs} +3 -3
- package/dist/{ownership-B9QIdQOw.mjs → ownership-CYOyqxUo.mjs} +4 -4
- package/dist/{ownership-claim-CeJLEpjD.mjs → ownership-claim-7zRxxTfZ.mjs} +1 -1
- package/dist/{project-COj6nzzh.mjs → project-BBTVABUz.mjs} +2 -2
- package/dist/{reclaim-BPvN2HlP.mjs → reclaim-C5Jmuahx.mjs} +9 -8
- package/dist/{reload-DYZEBbZy.mjs → reload-Z8nKifAk.mjs} +7 -7
- package/dist/{remote-cache-DOi5-zLj.mjs → remote-cache-DDmJ1Roq.mjs} +73 -13
- package/dist/{server-bare-BYHqEeyw.mjs → server-bare-DEk37Mz2.mjs} +7 -2
- package/dist/{server-expo-BEMr_m6p.mjs → server-expo-C3ktAwUG.mjs} +4 -4
- package/dist/server-expo-Drd7ksHu.mjs +2 -0
- package/dist/{settings-BSwrY4FZ.mjs → settings-DwU1_U_q.mjs} +26 -5
- package/dist/{start-ByCylYtB.mjs → start-BrY4EuIg.mjs} +10 -10
- package/dist/{state-IYEY-zi8.mjs → state-CZ-ER-8d.mjs} +1 -1
- package/dist/{stats-wqxPm7Tv.mjs → stats-BCWEVLrM.mjs} +1 -1
- package/dist/{stats-DZ4Q5J-7.mjs → stats-BsF15Bti.mjs} +3 -3
- package/dist/{status-Dia0XTqG.mjs → status-DFI1Hfpg.mjs} +46 -16
- package/dist/{stop-D6o5zAdm.mjs → stop-B7DR4awK.mjs} +2 -2
- package/dist/{stop-BApyaF21.mjs → stop-Btg770vV.mjs} +9 -9
- package/dist/supervisor-run.mjs +4 -4
- package/dist/{workspace-process-lock-CxOO9-pf.mjs → workspace-process-lock-BKfdys1q.mjs} +1 -1
- package/dist/{worktree-DxEmUI_n.mjs → worktree-BPTbI-LN.mjs} +16 -16
- package/dist/{worktree-Dx3ZC5lS.mjs → worktree-C79xx_kM.mjs} +7 -3
- package/dist/{xcode-CDB6fytw.mjs → xcode-DeKCribl.mjs} +190 -63
- package/package.json +5 -5
- package/shim/bundle-response.cjs +5 -0
- package/dist/server-expo-rb0k-0w7.mjs +0 -2
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
2
|
-
import { P as volumeRootFor, g as loadConfig, u as getConfigDir } from "./config-
|
|
3
|
-
import { D as workspaceLogsDir } from "./state-
|
|
4
|
-
import { f as listWorktrees } from "./worktree-
|
|
5
|
-
import { a as findProjectRoot, c as projectShortcut } from "./project-
|
|
6
|
-
import { a as isMetroRunning, i as resolveProjectMetro } from "./metro-
|
|
7
|
-
import { S as readParked, v as POOL_SETTING_REMEDY, x as parkedMaxSetting } from "./remote-cache-
|
|
1
|
+
import { t as getExecutor } from "./exec-CyylIdq9.mjs";
|
|
2
|
+
import { P as volumeRootFor, g as loadConfig, u as getConfigDir } from "./config-CMtIaTk9.mjs";
|
|
3
|
+
import { D as workspaceLogsDir } from "./state-CZ-ER-8d.mjs";
|
|
4
|
+
import { f as listWorktrees } from "./worktree-C79xx_kM.mjs";
|
|
5
|
+
import { a as findProjectRoot, c as projectShortcut } from "./project-BBTVABUz.mjs";
|
|
6
|
+
import { a as isMetroRunning, i as resolveProjectMetro } from "./metro-COslRK_F.mjs";
|
|
7
|
+
import { S as readParked, v as POOL_SETTING_REMEDY, x as parkedMaxSetting } from "./remote-cache-DDmJ1Roq.mjs";
|
|
8
8
|
import { a as formatElapsed, r as clockTime, u as plural } from "./command-output-8wHMEde0.mjs";
|
|
9
|
-
import {
|
|
10
|
-
import { i as listLeaseFiles } from "./device-lease-
|
|
9
|
+
import { u as listAllIosSims } from "./ios-D1h1Di39.mjs";
|
|
10
|
+
import { i as listLeaseFiles } from "./device-lease-Dpik41RY.mjs";
|
|
11
|
+
import { N as resolveOwnedAvdSerial } from "./android-K63_0UfF.mjs";
|
|
11
12
|
import { s as queryLogs } from "./logs-query-oqn47Ffx.mjs";
|
|
12
|
-
import { t as resolveSupervisorTarget } from "./ownership-
|
|
13
|
-
import { i as readSupervisorState } from "./stop-
|
|
13
|
+
import { t as resolveSupervisorTarget } from "./ownership-CYOyqxUo.mjs";
|
|
14
|
+
import { i as readSupervisorState } from "./stop-Btg770vV.mjs";
|
|
14
15
|
import { existsSync } from "fs";
|
|
15
16
|
import { totalmem } from "os";
|
|
16
17
|
import chalk from "chalk";
|
|
@@ -23,21 +24,29 @@ function poolLine({ platform, parked, max }) {
|
|
|
23
24
|
const what = plural(parked, `parked ${platform === "ios" ? "iOS simulator" : "Android emulator"}`);
|
|
24
25
|
return max > 0 ? `pool: ${what} (max ${max})` : `pool: ${what} (parking off; gc --delete removes them)`;
|
|
25
26
|
}
|
|
26
|
-
function environmentState(project, { simsByUdid = {}, metro = null, worktrees = [], simsAvailable = true, supervisor = null, logs = null } = {}) {
|
|
27
|
+
function environmentState(project, { simsByUdid = {}, metro = null, worktrees = [], simsAvailable = true, androidRuntime = null, supervisor = null, logs = null } = {}) {
|
|
27
28
|
const ios = project.platforms?.ios;
|
|
28
29
|
const android = project.platforms?.android;
|
|
29
30
|
const sim = ios ? simsByUdid[ios.deviceUdid] : null;
|
|
30
31
|
const simBooted = Boolean(sim && sim.state === "Booted");
|
|
31
32
|
const metroRunning = Boolean(metro?.metro);
|
|
32
|
-
const
|
|
33
|
+
const androidDetected = androidRuntime ? Boolean(androidRuntime.serial) : Boolean(android?.serial);
|
|
34
|
+
const live = simBooted || metroRunning || androidDetected;
|
|
33
35
|
let memoryMb = 0;
|
|
34
36
|
if (simBooted) memoryMb += IOS_SIM_MB;
|
|
35
|
-
if (
|
|
37
|
+
if (androidDetected) memoryMb += ANDROID_EMULATOR_MB;
|
|
36
38
|
if (metroRunning) memoryMb += METRO_MB;
|
|
37
39
|
const warnings = [];
|
|
38
40
|
if (metro?.notOurs) warnings.push(`port ${project.metroPort}: ${metro.notOurs}`);
|
|
39
41
|
if (ios && !sim && simsAvailable) warnings.push(`recorded sim ${ios.deviceUdid} no longer exists`);
|
|
40
42
|
if (simBooted && project.metroPort && !metroRunning) warnings.push("simulator is booted with no Metro serving it");
|
|
43
|
+
if (androidRuntime && android?.avdName) {
|
|
44
|
+
const recordedSerial = android.consolePort ? `emulator-${android.consolePort}` : android.serial;
|
|
45
|
+
if (androidRuntime.serial && recordedSerial && androidRuntime.serial !== recordedSerial) warnings.push(`owned AVD ${android.avdName} changed serial (${recordedSerial} -> ${androidRuntime.serial}); rerun your \`stim android\` command in this workspace to restore Metro forwarding, then reopen agent-device on ${androidRuntime.serial}`);
|
|
46
|
+
if (androidRuntime.state === "missing") warnings.push(`recorded AVD ${android.avdName} no longer exists`);
|
|
47
|
+
if (androidRuntime.state === "not-detected") warnings.push(`owned AVD ${android.avdName} is not detected by adb; rerun your \`stim android\` command in this workspace to reconnect`);
|
|
48
|
+
if (androidRuntime.error) warnings.push(`could not check owned AVD ${android.avdName}: ${androidRuntime.error}`);
|
|
49
|
+
}
|
|
41
50
|
if (supervisor && supervisor.alive === false) warnings.push(`stale supervisor record for ${project.__path}`);
|
|
42
51
|
return {
|
|
43
52
|
path: project.__path,
|
|
@@ -53,7 +62,11 @@ function environmentState(project, { simsByUdid = {}, metro = null, worktrees =
|
|
|
53
62
|
android: android ? {
|
|
54
63
|
name: android.avdName ?? android.serial,
|
|
55
64
|
owned: Boolean(android.owned),
|
|
56
|
-
physical: Boolean(android.serial && !android.avdName)
|
|
65
|
+
physical: Boolean(android.serial && !android.avdName),
|
|
66
|
+
...androidRuntime ? {
|
|
67
|
+
serial: androidRuntime.serial,
|
|
68
|
+
state: androidRuntime.state
|
|
69
|
+
} : {}
|
|
57
70
|
} : null,
|
|
58
71
|
metro: project.metroPort ? {
|
|
59
72
|
port: project.metroPort,
|
|
@@ -191,6 +204,7 @@ function statusCommand(program) {
|
|
|
191
204
|
metro,
|
|
192
205
|
worktrees,
|
|
193
206
|
simsAvailable,
|
|
207
|
+
androidRuntime: proj.platforms?.android?.owned && proj.platforms.android.avdName ? readAndroidRuntime(proj.platforms.android.avdName) : null,
|
|
194
208
|
supervisor,
|
|
195
209
|
logs: logFacts(path)
|
|
196
210
|
}));
|
|
@@ -267,7 +281,8 @@ function statusCommand(program) {
|
|
|
267
281
|
}
|
|
268
282
|
if (state.android) {
|
|
269
283
|
const kind = state.android.physical ? chalk.dim("(physical)") : chalk.dim("(emulator)");
|
|
270
|
-
|
|
284
|
+
const observed = state.android.state ? ` ${state.android.state}${state.android.serial ? ` (${state.android.serial})` : ""}` : "";
|
|
285
|
+
console.log(` android: ${chalk.cyan(state.android.name)} ${kind}${observed}${state.android.owned ? chalk.dim(" (owned)") : ""}`);
|
|
271
286
|
}
|
|
272
287
|
for (const w of state.warnings) console.log(chalk.yellow(` ! ${w}`));
|
|
273
288
|
}
|
|
@@ -297,6 +312,21 @@ function statusCommand(program) {
|
|
|
297
312
|
if (cap.overCapacity) console.log(chalk.yellow("Over comfortable capacity. A machine that swaps is slower than one working in sequence -- release one before starting another."));
|
|
298
313
|
});
|
|
299
314
|
}
|
|
315
|
+
function readAndroidRuntime(avdName) {
|
|
316
|
+
try {
|
|
317
|
+
const resolved = resolveOwnedAvdSerial(avdName, { timeoutMs: 5e3 });
|
|
318
|
+
return {
|
|
319
|
+
serial: resolved.serial ?? null,
|
|
320
|
+
state: resolved.serial ? "detected" : resolved.missing ? "missing" : resolved.notRunning ? "not-detected" : "unknown"
|
|
321
|
+
};
|
|
322
|
+
} catch (error) {
|
|
323
|
+
return {
|
|
324
|
+
serial: null,
|
|
325
|
+
state: "unknown",
|
|
326
|
+
error: String(error?.message || error).split("\n")[0]
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
}
|
|
300
330
|
function readVolumes(projectPath) {
|
|
301
331
|
const roots = [.../* @__PURE__ */ new Set([
|
|
302
332
|
"/",
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as resolveSupervisorTarget } from "./ownership-
|
|
2
|
-
import { a as resolveCollectorTargets, i as readSupervisorState, n as clearSupervisorState, o as runStop, r as readCollectorState, s as stopCommand, t as clearCollectorState } from "./stop-
|
|
1
|
+
import { t as resolveSupervisorTarget } from "./ownership-CYOyqxUo.mjs";
|
|
2
|
+
import { a as resolveCollectorTargets, i as readSupervisorState, n as clearSupervisorState, o as runStop, r as readCollectorState, s as stopCommand, t as clearCollectorState } from "./stop-Btg770vV.mjs";
|
|
3
3
|
export { clearCollectorState, clearSupervisorState, stopCommand as default, readCollectorState, readSupervisorState, resolveCollectorTargets, resolveSupervisorTarget, runStop };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { C as withConfigLock, D as sameProcessRecord, E as inspectProcessIdentity, O as waitForProcessExit, S as upsertProject, a as clearSupervisor, f as getProject } from "./config-
|
|
2
|
-
import { _ as writeWorkspaceState, a as clearRemoteSession, c as readMetroTunnel, i as clearManagedMetroTunnel, m as withWorkspaceStateLock, o as clearWorkspaceStateKeys, p as readWorkspaceState, s as clearWorkspaceSupervisor, u as readRemoteSession } from "./state-
|
|
3
|
-
import { a as findProjectRoot } from "./project-
|
|
4
|
-
import { i as resolveProjectMetro, n as killMetroTree, r as pidExists } from "./metro-
|
|
5
|
-
import { n as verifyCollectorOwnership } from "./ownership-
|
|
6
|
-
import { d as resolveEasCliBin, h as teardownOwnedIosSim, m as teardownOwnedAvd } from "./remote-cache-
|
|
1
|
+
import { C as withConfigLock, D as sameProcessRecord, E as inspectProcessIdentity, O as waitForProcessExit, S as upsertProject, a as clearSupervisor, f as getProject } from "./config-CMtIaTk9.mjs";
|
|
2
|
+
import { _ as writeWorkspaceState, a as clearRemoteSession, c as readMetroTunnel, i as clearManagedMetroTunnel, m as withWorkspaceStateLock, o as clearWorkspaceStateKeys, p as readWorkspaceState, s as clearWorkspaceSupervisor, u as readRemoteSession } from "./state-CZ-ER-8d.mjs";
|
|
3
|
+
import { a as findProjectRoot } from "./project-BBTVABUz.mjs";
|
|
4
|
+
import { i as resolveProjectMetro, n as killMetroTree, r as pidExists } from "./metro-COslRK_F.mjs";
|
|
5
|
+
import { n as verifyCollectorOwnership } from "./ownership-CGPart6T.mjs";
|
|
6
|
+
import { d as resolveEasCliBin, h as teardownOwnedIosSim, m as teardownOwnedAvd } from "./remote-cache-DDmJ1Roq.mjs";
|
|
7
7
|
import { f as releasedLeaseFact, l as phaseLine, u as plural } from "./command-output-8wHMEde0.mjs";
|
|
8
|
-
import { l as releaseWorkspaceLeases } from "./device-lease-
|
|
9
|
-
import { i as endRecordedSession } from "./device-remote-
|
|
10
|
-
import { r as stopTunnel, t as resolveSupervisorTarget } from "./ownership-
|
|
8
|
+
import { l as releaseWorkspaceLeases } from "./device-lease-Dpik41RY.mjs";
|
|
9
|
+
import { i as endRecordedSession } from "./device-remote-E81KAdXf.mjs";
|
|
10
|
+
import { r as stopTunnel, t as resolveSupervisorTarget } from "./ownership-CYOyqxUo.mjs";
|
|
11
11
|
import chalk from "chalk";
|
|
12
12
|
//#region src/commands/stop.ts
|
|
13
13
|
const DEFAULT_WAIT_MS = 1e4;
|
package/dist/supervisor-run.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { T as captureProcessToken, a as clearSupervisor, x as setSupervisor } from "./config-
|
|
1
|
+
import { T as captureProcessToken, a as clearSupervisor, x as setSupervisor } from "./config-CMtIaTk9.mjs";
|
|
2
2
|
import { r as createNdjsonWriter } from "./ndjson-DcAtEx_K.mjs";
|
|
3
|
-
import { D as workspaceLogsDir, _ as writeWorkspaceState, h as writePidFile, l as readPidFile, m as withWorkspaceStateLock, n as MODE_EXPO, p as readWorkspaceState, r as clearExpoMetroTunnel, s as clearWorkspaceSupervisor, t as MODE_BARE } from "./state-
|
|
4
|
-
import { i as detectIsExpo } from "./project-
|
|
3
|
+
import { D as workspaceLogsDir, _ as writeWorkspaceState, h as writePidFile, l as readPidFile, m as withWorkspaceStateLock, n as MODE_EXPO, p as readWorkspaceState, r as clearExpoMetroTunnel, s as clearWorkspaceSupervisor, t as MODE_BARE } from "./state-CZ-ER-8d.mjs";
|
|
4
|
+
import { i as detectIsExpo } from "./project-BBTVABUz.mjs";
|
|
5
5
|
import { t as describeError } from "./errors-B6W7FkxQ.mjs";
|
|
6
6
|
import { existsSync, realpathSync } from "node:fs";
|
|
7
7
|
import { isAbsolute, join, resolve } from "node:path";
|
|
@@ -97,7 +97,7 @@ async function runSupervisor({ root, port, tunnel = false, isExpo = detectIsExpo
|
|
|
97
97
|
};
|
|
98
98
|
let server;
|
|
99
99
|
try {
|
|
100
|
-
server = await (mode === "expo-child" ? startExpo || (await import("./server-expo-
|
|
100
|
+
server = await (mode === "expo-child" ? startExpo || (await import("./server-expo-Drd7ksHu.mjs")).startExpoServer : startBare || (await import("./server-bare-DEk37Mz2.mjs")).startBareServer)({
|
|
101
101
|
root,
|
|
102
102
|
port,
|
|
103
103
|
logsDir,
|
|
@@ -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-7zRxxTfZ.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
|
-
import { t as getExecutor } from "./exec-
|
|
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-
|
|
7
|
-
import {
|
|
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-CMtIaTk9.mjs";
|
|
3
|
+
import { c as readMetroTunnel, u as readRemoteSession } from "./state-CZ-ER-8d.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-C79xx_kM.mjs";
|
|
5
|
+
import { a as findProjectRoot } from "./project-BBTVABUz.mjs";
|
|
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";
|
|
8
8
|
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 { g as podInstallCommand, r as HEARTBEAT_INTERVAL_MS } from "./xcode-
|
|
11
|
-
import { a as installedNpmTreeIsValid, i as hasInstalledDependencies, o as locallyKnownUpstream, t as dependencyState } from "./doctor-
|
|
12
|
-
import { c as withManagedTunnelRemovalLock, o as withManagedRemoteWorktreeRemovalLock } from "./ownership-
|
|
13
|
-
import { n as reclaimProject } from "./reclaim-
|
|
14
|
-
import { a as runPodInstall, i as runCaptured, n as podsAreStale, r as readPodState, t as DEPS_ERROR } from "./deps-
|
|
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-7zRxxTfZ.mjs";
|
|
10
|
+
import { g as podInstallCommand, r as HEARTBEAT_INTERVAL_MS } from "./xcode-DeKCribl.mjs";
|
|
11
|
+
import { a as installedNpmTreeIsValid, i as hasInstalledDependencies, o as locallyKnownUpstream, t as dependencyState } from "./doctor-CqPeMsSm.mjs";
|
|
12
|
+
import { c as withManagedTunnelRemovalLock, o as withManagedRemoteWorktreeRemovalLock } from "./ownership-CYOyqxUo.mjs";
|
|
13
|
+
import { n as reclaimProject } from "./reclaim-C5Jmuahx.mjs";
|
|
14
|
+
import { a as runPodInstall, i as runCaptured, n as podsAreStale, r as readPodState, t as DEPS_ERROR } from "./deps-BLBsTNDS.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";
|
|
@@ -54,11 +54,11 @@ function asHolder(holder) {
|
|
|
54
54
|
};
|
|
55
55
|
}
|
|
56
56
|
function waitingLine(holder, elapsedMs) {
|
|
57
|
-
return phaseLine("lock", `waiting ${formatElapsed(elapsedMs)} for ${warmCommand(holder.phase)} (pid ${holder.pid})`);
|
|
57
|
+
return phaseLine("lock", `waiting ${formatElapsed(elapsedMs)} for ${warmCommand(holder.phase)} (pid ${holder.pid}) -- stim guide lifecycle options`);
|
|
58
58
|
}
|
|
59
59
|
function warmClaimAcquiredLine(wait) {
|
|
60
60
|
if (!wait.holder || wait.waitedMs <= 0) return phaseLine("lock", "acquired");
|
|
61
|
-
return phaseLine("lock", `acquired (waited ${formatElapsed(wait.waitedMs)} for ${warmCommand(wait.holder.phase)} pid ${wait.holder.pid})`);
|
|
61
|
+
return phaseLine("lock", `acquired (waited ${formatElapsed(wait.waitedMs)} for ${warmCommand(wait.holder.phase)} pid ${wait.holder.pid}) -- stim guide lifecycle options`);
|
|
62
62
|
}
|
|
63
63
|
function warmClaimUnavailableLine(reason) {
|
|
64
64
|
return phaseLine("lock", `unavailable (${reason}); copying without it`);
|
|
@@ -109,7 +109,7 @@ function warmClaimBlockedRefusal(blocker) {
|
|
|
109
109
|
return `Refusing to copy past a claim Stim cannot resolve. If nothing is warming, remove it and run warm again:\n ${claimRemoveCommand(blocker.path)}`;
|
|
110
110
|
}
|
|
111
111
|
function installerWaitingLine(pid, elapsedMs) {
|
|
112
|
-
return phaseLine("lock", `waiting on the install this refresh spawned (pid ${pid}, ${formatElapsed(elapsedMs)} elapsed)`);
|
|
112
|
+
return phaseLine("lock", `waiting on the install this refresh spawned (pid ${pid}, ${formatElapsed(elapsedMs)} elapsed) -- stim guide lifecycle options`);
|
|
113
113
|
}
|
|
114
114
|
function installerUnrecordedLine(reason) {
|
|
115
115
|
return phaseLine("lock", `could not record the install this refresh spawned (${reason}); holding the claim here until it exits`);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
2
|
-
import { g as loadConfig, u as getConfigDir } from "./config-
|
|
1
|
+
import { t as getExecutor } from "./exec-CyylIdq9.mjs";
|
|
2
|
+
import { g as loadConfig, u as getConfigDir } from "./config-CMtIaTk9.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";
|
|
@@ -85,7 +85,11 @@ function removeTemporaryEntry(path) {
|
|
|
85
85
|
}
|
|
86
86
|
//#endregion
|
|
87
87
|
//#region src/worktree.ts
|
|
88
|
-
const CARRY_SKIP_BASENAMES = /* @__PURE__ */ new Set([
|
|
88
|
+
const CARRY_SKIP_BASENAMES = /* @__PURE__ */ new Set([
|
|
89
|
+
".DerivedData",
|
|
90
|
+
".DS_Store",
|
|
91
|
+
".idea"
|
|
92
|
+
]);
|
|
89
93
|
function isCarrySkipped(rel) {
|
|
90
94
|
return /(^|\/)android\/build\/generated\/autolinking(\/|$)/.test(rel) || String(rel).split("/").some((seg) => CARRY_SKIP_BASENAMES.has(seg));
|
|
91
95
|
}
|
|
@@ -1,23 +1,24 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
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-
|
|
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-
|
|
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-CMtIaTk9.mjs";
|
|
3
|
+
import { r as register } from "./cache-manifest-Cu4_Znw9.mjs";
|
|
4
|
+
import { E as workspaceId, S as sharedCompilationCache, w as workspaceDerivedData } from "./state-CZ-ER-8d.mjs";
|
|
5
|
+
import { s as ownedDeviceLabel } from "./project-BBTVABUz.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-
|
|
9
|
-
import {
|
|
7
|
+
import { r as pidExists } from "./metro-COslRK_F.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-DDmJ1Roq.mjs";
|
|
9
|
+
import { U as resolveOptimizations, l as androidDataPartitionSizeGbSetting, o as androidAvdConfigSetting, v as iosSimSlimProfileSetting } from "./settings-DwU1_U_q.mjs";
|
|
10
10
|
import { a as formatElapsed, l as phaseLine } from "./command-output-8wHMEde0.mjs";
|
|
11
|
-
import { _ as
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { t as
|
|
11
|
+
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-D1h1Di39.mjs";
|
|
12
|
+
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-7zRxxTfZ.mjs";
|
|
13
|
+
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-K63_0UfF.mjs";
|
|
14
|
+
import { t as withWorkspaceProcessLock } from "./workspace-process-lock-BKfdys1q.mjs";
|
|
15
|
+
import { t as cleanLine } from "./server-expo-C3ktAwUG.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
|
-
|
|
45
|
-
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
|
58
|
-
if (result
|
|
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
|
|
143
|
+
throw new Error(`SimSlim ${action} failed with exit code ${result?.code ?? "unknown"}.${detail}`);
|
|
61
144
|
}
|
|
62
145
|
return {
|
|
63
146
|
managed: Boolean(profile),
|
|
@@ -118,6 +201,8 @@ async function ensureOwnedDevice({ platform, project, projectPath, settingsRoot
|
|
|
118
201
|
});
|
|
119
202
|
}
|
|
120
203
|
async function ensureOwnedIosDevice({ record, projectPath, settingsRoot, label, settings, flags, note, out, reconcileIosSimulator }) {
|
|
204
|
+
const memoryAdvice = hostMemoryPressureAdvice(readHostMemoryPressure());
|
|
205
|
+
if (memoryAdvice) out(chalk.yellow(phaseLine("memory", memoryAdvice)));
|
|
121
206
|
const simslimProfile = iosSimSlimProfileSetting(settings, settingsRoot);
|
|
122
207
|
if (record?.deviceUdid) {
|
|
123
208
|
if (record.owned) {
|
|
@@ -361,11 +446,21 @@ function findOtherProjectOwningAvd(avdName, projectPath) {
|
|
|
361
446
|
}
|
|
362
447
|
return null;
|
|
363
448
|
}
|
|
449
|
+
var AvdRecoveryError = class extends Error {
|
|
450
|
+
remedy;
|
|
451
|
+
constructor(message, remedy, cause) {
|
|
452
|
+
super(message, { cause });
|
|
453
|
+
this.remedy = remedy;
|
|
454
|
+
}
|
|
455
|
+
};
|
|
364
456
|
async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, label, settings, flags, note, out, logFile, alive, configureAvd, teardownAvd }) {
|
|
365
457
|
const avdConfig = androidAvdConfigSetting(settings, settingsRoot);
|
|
366
458
|
const configuration = avdPoolConfiguration(androidDataPartitionSizeGbSetting(settings), avdConfig);
|
|
367
459
|
if (record?.setupIncomplete && record.avdName) {
|
|
368
|
-
const cleanup = teardownAvd(record.avdName, {
|
|
460
|
+
const cleanup = teardownAvd(record.avdName, {
|
|
461
|
+
del: true,
|
|
462
|
+
owner: { projectPath }
|
|
463
|
+
});
|
|
369
464
|
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
465
|
clearDevice(projectPath, "android");
|
|
371
466
|
record = null;
|
|
@@ -376,6 +471,7 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
|
|
|
376
471
|
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
472
|
else if (resolved.serial) {
|
|
378
473
|
const consolePort = Number(resolved.serial.replace(/^emulator-/, ""));
|
|
474
|
+
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
475
|
const updated = {
|
|
380
476
|
...record,
|
|
381
477
|
avdName: record.avdName,
|
|
@@ -421,7 +517,8 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
|
|
|
421
517
|
if (parked.deletionClaim !== void 0) continue;
|
|
422
518
|
const resolved = resolveOwnedAvdSerial(parked.name);
|
|
423
519
|
if (resolved.missing) {
|
|
424
|
-
|
|
520
|
+
const result = teardownParkedAvd(parked.name);
|
|
521
|
+
if (result.status === "failed") out(phaseLine("device", `kept ${parked.name}: ${result.reason}`));
|
|
425
522
|
continue;
|
|
426
523
|
}
|
|
427
524
|
if (resolved.notOwned || resolved.serial) continue;
|
|
@@ -484,28 +581,45 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
|
|
|
484
581
|
} catch (e) {
|
|
485
582
|
const message = String(e?.message || e);
|
|
486
583
|
const avdName = ownedAvdName(label);
|
|
487
|
-
if (message.includes("already exists")
|
|
488
|
-
|
|
489
|
-
if (
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
const
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
584
|
+
if (message.includes("already exists")) {
|
|
585
|
+
try {
|
|
586
|
+
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
|
+
created = withConfigLock(() => {
|
|
588
|
+
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);
|
|
590
|
+
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]?.platforms?.android;
|
|
592
|
+
if (current?.avdName) {
|
|
593
|
+
const state = current.setupIncomplete ? "has incomplete setup" : "was registered";
|
|
594
|
+
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 });
|
|
595
|
+
}
|
|
596
|
+
const resolved = resolveOwnedAvdSerial(avdName);
|
|
597
|
+
if (resolved.missing || resolved.notOwned) throw new Error(`AVD ${avdName} could not be verified for recovery. Retry after checking its registration.`, { cause: e });
|
|
598
|
+
if (!resolved.serial) assertOwnedAvdStopped(avdName);
|
|
599
|
+
const recovered = {
|
|
600
|
+
avdName,
|
|
601
|
+
owned: true,
|
|
602
|
+
deviceName: avdName,
|
|
603
|
+
...resolved.serial ? { consolePort: Number(resolved.serial.replace(/^emulator-/, "")) } : {}
|
|
604
|
+
};
|
|
605
|
+
setDevice(projectPath, "android", recovered);
|
|
606
|
+
return {
|
|
607
|
+
...recovered,
|
|
608
|
+
systemImage: ownedAvdSystemImage(avdName),
|
|
609
|
+
serial: resolved.serial
|
|
610
|
+
};
|
|
505
611
|
});
|
|
506
|
-
|
|
507
|
-
|
|
612
|
+
} catch (error) {
|
|
613
|
+
if (error instanceof AvdRecoveryError) throw error;
|
|
614
|
+
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);
|
|
615
|
+
}
|
|
508
616
|
out(chalk.dim(phaseLine("device", `recovered ${avdName} (unrecorded from a prior run)`)));
|
|
617
|
+
if (created.serial) return {
|
|
618
|
+
...created,
|
|
619
|
+
owned: true,
|
|
620
|
+
deviceName: avdName,
|
|
621
|
+
created: false
|
|
622
|
+
};
|
|
509
623
|
} else throw e;
|
|
510
624
|
}
|
|
511
625
|
if (fresh) try {
|
|
@@ -514,7 +628,10 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
|
|
|
514
628
|
avdConfig
|
|
515
629
|
});
|
|
516
630
|
} catch (error) {
|
|
517
|
-
const cleanup = teardownAvd(created.avdName, {
|
|
631
|
+
const cleanup = teardownAvd(created.avdName, {
|
|
632
|
+
del: true,
|
|
633
|
+
owner: { projectPath }
|
|
634
|
+
});
|
|
518
635
|
const kept = cleanup.status === "failed" || cleanup.status === "skipped";
|
|
519
636
|
if (!kept) clearDevice(projectPath, "android");
|
|
520
637
|
const orphan = kept ? ` The owned AVD remains tracked for cleanup (${cleanup.reason || cleanup.status}); fix the cause, then retry or run \`stim gc --delete\`.` : "";
|
|
@@ -530,7 +647,7 @@ async function ensureOwnedAndroidDevice({ record, projectPath, settingsRoot, lab
|
|
|
530
647
|
logFile,
|
|
531
648
|
alive
|
|
532
649
|
}),
|
|
533
|
-
created:
|
|
650
|
+
created: fresh,
|
|
534
651
|
systemImage: created.systemImage
|
|
535
652
|
};
|
|
536
653
|
}
|
|
@@ -716,6 +833,25 @@ async function ensureIosBooted({ device, timeoutMs, pollMs, out }) {
|
|
|
716
833
|
failed: true,
|
|
717
834
|
reason: "No iOS simulator is recorded for this project."
|
|
718
835
|
};
|
|
836
|
+
const ready = () => {
|
|
837
|
+
try {
|
|
838
|
+
getExecutor().runFile("xcrun", [
|
|
839
|
+
"simctl",
|
|
840
|
+
"spawn",
|
|
841
|
+
udid,
|
|
842
|
+
"/usr/bin/true"
|
|
843
|
+
], { timeoutMs: 3e4 });
|
|
844
|
+
return {
|
|
845
|
+
ok: true,
|
|
846
|
+
udid
|
|
847
|
+
};
|
|
848
|
+
} catch (error) {
|
|
849
|
+
return {
|
|
850
|
+
failed: true,
|
|
851
|
+
reason: `Simulator ${udid} failed its process-spawn readiness check: ${error?.message || error}. ${iosSimulatorFailureAdvice()}`
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
};
|
|
719
855
|
const booting = device?.booting;
|
|
720
856
|
if (booting?.udid === udid) {
|
|
721
857
|
try {
|
|
@@ -726,10 +862,7 @@ async function ensureIosBooted({ device, timeoutMs, pollMs, out }) {
|
|
|
726
862
|
reason: `Could not boot simulator ${udid}: ${e?.message || e}`
|
|
727
863
|
};
|
|
728
864
|
}
|
|
729
|
-
return
|
|
730
|
-
ok: true,
|
|
731
|
-
udid
|
|
732
|
-
};
|
|
865
|
+
return ready();
|
|
733
866
|
}
|
|
734
867
|
let resolved;
|
|
735
868
|
try {
|
|
@@ -749,10 +882,7 @@ async function ensureIosBooted({ device, timeoutMs, pollMs, out }) {
|
|
|
749
882
|
reason: `Simulator ${udid} is now named "${resolved.notOwned}" and is not Stim-owned; refusing to boot it.`
|
|
750
883
|
};
|
|
751
884
|
const sim = resolved.sim;
|
|
752
|
-
if (sim.state === "Booted") return
|
|
753
|
-
ok: true,
|
|
754
|
-
udid
|
|
755
|
-
};
|
|
885
|
+
if (sim.state === "Booted") return ready();
|
|
756
886
|
out(chalk.dim(phaseLine("device", `booting ${sim.name} (${udid})`)));
|
|
757
887
|
const bootDeadline = Date.now() + timeoutMs;
|
|
758
888
|
try {
|
|
@@ -770,10 +900,7 @@ async function ensureIosBooted({ device, timeoutMs, pollMs, out }) {
|
|
|
770
900
|
try {
|
|
771
901
|
state = listAllIosSims({ timeoutMs: 3e4 }).find((s) => s.udid === udid)?.state ?? null;
|
|
772
902
|
} catch {}
|
|
773
|
-
if (state === "Booted") return
|
|
774
|
-
ok: true,
|
|
775
|
-
udid
|
|
776
|
-
};
|
|
903
|
+
if (state === "Booted") return ready();
|
|
777
904
|
}
|
|
778
905
|
return {
|
|
779
906
|
failed: true,
|
|
@@ -1702,4 +1829,4 @@ async function buildIos({ root, udid = null, logWriter, project = null, scheme =
|
|
|
1702
1829
|
};
|
|
1703
1830
|
}
|
|
1704
1831
|
//#endregion
|
|
1705
|
-
export {
|
|
1832
|
+
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 };
|