stim 1.15.0 → 1.17.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/dist/{activity-B2-kb7k0.mjs → activity-IRvJY_ru.mjs} +49 -16
- package/dist/agent-device-usage-output-BK41vnzN.mjs +411 -0
- package/dist/{android-Cu_L4RpL.mjs → android--GorydsK.mjs} +692 -321
- package/dist/{android-Db2eEMaf.mjs → android-B_YNZy61.mjs} +25 -60
- package/dist/{android-CYmq0jNi.mjs → android-DE4v59Mb.mjs} +12 -3
- package/dist/{android-cas-PnKfAdB2.mjs → android-cas-ZFpjJBL_.mjs} +6 -5
- package/dist/{app-install-CAAplXAt.mjs → app-install-VPkI5WEg.mjs} +52 -8
- package/dist/attempt-Bk2ouQVL.mjs +39 -0
- package/dist/{budget-CMiqghig.mjs → budget-DM984mnd.mjs} +372 -366
- package/dist/{build-plan-aeGMFX7e.mjs → build-plan-CmQCoyT-.mjs} +346 -88
- package/dist/{build-slots-Df1ApSuH.mjs → build-slots-41v_d2x9.mjs} +36 -21
- package/dist/{cli-0cX5s4NM.mjs → cli-Daxug5-K.mjs} +23 -17
- package/dist/cli.mjs +1 -1
- package/dist/collector-run.mjs +5 -192
- package/dist/{command-output-CliHHn7a.mjs → command-output-CDAIFD-8.mjs} +3 -3
- package/dist/{created-devices-BwVb3liH.mjs → created-devices-CpvzBL25.mjs} +1 -1
- package/dist/{dependency-state-BmsjKZ2H.mjs → dependency-state-CLcBHH2M.mjs} +1 -1
- package/dist/{deps-BFlKbOIp.mjs → deps-DNWaQs4V.mjs} +2 -2
- package/dist/{dev-client-CjzLoNs0.mjs → dev-client-B-XC4uRH.mjs} +3 -40
- package/dist/{device-BZ1IyS5A.mjs → device-C8IOoJPv.mjs} +7 -6
- package/dist/device-capacity-D0GWHnTM.mjs +580 -0
- package/dist/device-host-worker.mjs +587 -110
- package/dist/{device-ios-DMQBUPus.mjs → device-ios-Bc7vbGwl.mjs} +75 -44
- package/dist/{device-lease-W5Pi1q38.mjs → device-lease-DpoS36_u.mjs} +2 -2
- package/dist/{device-pool-B2r38YjS.mjs → device-lease-run-B8YltIH_.mjs} +5 -125
- package/dist/device-pool-3o7s5lo4.mjs +125 -0
- package/dist/{device-remote-9ulPsdhY.mjs → device-remote-hFSkpfQu.mjs} +13 -13
- package/dist/{doctor-BcE5xsBn.mjs → doctor-Cnk9d7Hm.mjs} +86 -59
- package/dist/{error-diagnostics-Cb0P1WLS.mjs → error-diagnostics-C-NMnhrk.mjs} +11 -15
- package/dist/{gc-BuL1Genr.mjs → gc-DxCL2A46.mjs} +478 -33
- package/dist/{gradle-CmdOBq1d.mjs → gradle-D7-L2Th3.mjs} +4 -4
- package/dist/{guide-cCSGRFd3.mjs → guide-DjrTQGik.mjs} +2198 -566
- package/dist/{guide-status-CIoWK6mG.mjs → guide-status-Du-ZQ3FD.mjs} +1 -1
- package/dist/hosted-android-DwLS4Mse.mjs +32 -0
- package/dist/hosted-client-wk1W_CNW.mjs +196 -0
- package/dist/hosted-ios-aMo7Cljf.mjs +15 -0
- package/dist/hosted-logs-DqYmWtXc.mjs +187 -0
- package/dist/hosted-macos-dlHXEeF5.mjs +135 -0
- package/dist/hosted-native-C9xJ9rpA.mjs +255 -0
- package/dist/{build-progress-C2Jv1AtA.mjs → idle-B2m-Ovod.mjs} +300 -9
- package/dist/{idle-shutdown-B5LPaNyY.mjs → idle-shutdown-_3oOV1V_.mjs} +25 -17
- package/dist/{in-use-CndPMilN.mjs → in-use-CvGOUn-x.mjs} +30 -10
- package/dist/ios-Cr1h5gnO.mjs +189 -0
- package/dist/{ios-Chob8ny7.mjs → ios-DE6duQoz.mjs} +819 -460
- package/dist/{ios-3CtCRhwr.mjs → ios-DSfnPfse.mjs} +4 -4
- package/dist/{ios-device-DERmMmk-.mjs → ios-device-pAN4t54-.mjs} +1 -1
- package/dist/ios-state-8L3lgum6.mjs +89 -0
- package/dist/{launch-verify-CLlofxRt.mjs → launch-verify-lTnWZikR.mjs} +3 -3
- package/dist/logs-DUoKlDoS.mjs +384 -0
- package/dist/{client-C2IS36Qf.mjs → machines-C2XiNwh9.mjs} +330 -37
- package/dist/{macos-BwtbUtTN.mjs → macos-32po3kUq.mjs} +23 -18
- package/dist/macos-run.mjs +1 -1
- package/dist/maintenance-run.d.mts +4 -0
- package/dist/maintenance-run.mjs +254 -0
- package/dist/{metro-Di8EN2Tb.mjs → metro-g8NqiJp-.mjs} +1 -1
- package/dist/metro-gateway-DmslUM30.mjs +103 -0
- package/dist/{named-ports-Dj_XBNaL.mjs → named-ports-C8m8EQs2.mjs} +2 -2
- package/dist/{native-run-DFDoIRbY.mjs → native-run-D1Q56rAD.mjs} +17 -6
- package/dist/{native-runtime-i6OkVg-w.mjs → native-runtime-DhJI3IVQ.mjs} +6 -6
- package/dist/{ndjson-CDY9IkVC.mjs → ndjson-PclOIwVY.mjs} +2 -2
- package/dist/offload-worker.d.mts +1 -0
- package/dist/offload-worker.mjs +13 -8
- package/dist/{teardown-BYuQafiA.mjs → ownership-BMLqyBgJ.mjs} +639 -53
- package/dist/{ownership-BkYxUtuj.mjs → ownership-DyRQru0q.mjs} +2 -2
- package/dist/{ports-DddwttKM.mjs → ports-4nYqxPWC.mjs} +2 -2
- package/dist/{prebuild-BvxDlD6C.mjs → prebuild-D7RUMkwN.mjs} +4 -4
- package/dist/preview-CxPRIEht.mjs +318 -0
- package/dist/{project-CV3tDFHl.mjs → project-D47Rh0ly.mjs} +72 -3
- package/dist/{recordings-GEXp4iBT.mjs → recordings-BNgsD1Tr.mjs} +1 -1
- package/dist/{reload-ChPiwvot.mjs → reload-qZei6iWn.mjs} +77 -13
- package/dist/{remote-cache-CO2elm_b.mjs → remote-cache-Ci4DQYYj.mjs} +4 -4
- package/dist/{run-B-xqRrsg.mjs → run-CkE9y0nc.mjs} +2 -2
- package/dist/{server-bare-X7PUgizL.mjs → server-bare-BkrSxSsZ.mjs} +1 -1
- package/dist/{server-expo-DhtX6bom.mjs → server-expo-CHTyXD0G.mjs} +4 -4
- package/dist/server-expo-CeakhI8P.mjs +2 -0
- package/dist/settings-BBpMcDbD.mjs +25 -0
- package/dist/settings-Cfd-0r2d.mjs +1440 -0
- package/dist/{settings-DbL6uhH8.mjs → settings-SR9OmW9h.mjs} +10 -4
- package/dist/settings.schema.json +472 -50
- package/dist/{simslim-Ciluxlq4.mjs → simslim-BWNrc3M3.mjs} +3 -3
- package/dist/{slot-launch-BY0BrOLh.mjs → slot-launch-DmjBmpQV.mjs} +10 -7
- package/dist/{spawn-entry-DncpJvWL.mjs → spawn-entry-jw19m8Nl.mjs} +1 -0
- package/dist/{start-CPO4wRg7.mjs → start-BopZcr4n.mjs} +1 -1
- package/dist/{start-CUD9nasA.mjs → start-uee1wWjY.mjs} +21 -17
- package/dist/{state-CaeaHbDA.mjs → state-BKa8wNN5.mjs} +1 -1
- package/dist/{state-BxCgeTQu.mjs → state-DyaNTgfR.mjs} +2 -2
- package/dist/{state-DFm77wRn.mjs → state-PeQiJuIu.mjs} +5 -5
- package/dist/{stats-DBLLFmKd.mjs → stats-Bq4fJOdB.mjs} +19 -5
- package/dist/{status-l84Gbvp2.mjs → status-CzS4bPO9.mjs} +5 -3
- package/dist/status-DlKvVJBE.mjs +49 -0
- package/dist/{status-DYXxNOT0.mjs → status-dXX2JX1C.mjs} +244 -50
- package/dist/{stop-CceYh1yG.mjs → stop-BCwvvs7F.mjs} +2 -2
- package/dist/{stop-Bad61z_2.mjs → stop-BjizrQwv.mjs} +83 -21
- package/dist/{stop-Bvf1MflS.mjs → stop-Cr1d8DSE.mjs} +4 -4
- package/dist/stop-cause-rhmGfwvt.mjs +97 -0
- package/dist/supervisor-run.d.mts +7 -4
- package/dist/supervisor-run.mjs +156 -27
- package/dist/{support-WLOzVKUv.mjs → support-BJPgYCu-.mjs} +61 -11
- package/dist/{support-CDQbDkL5.mjs → support-F9-sr0Oi.mjs} +6 -5
- package/dist/{toolchain-DmeYjXD9.mjs → toolchain-CNIBTIOv.mjs} +11 -11
- package/dist/trigger-Bemu8ytw.mjs +65 -0
- package/dist/trigger-CXts6qt1.mjs +2 -0
- package/dist/{warm-progress-DVHLN4uC.mjs → warm-progress-DF4JRvYI.mjs} +274 -5
- package/dist/watchman-APYjXSQa.mjs +48 -0
- package/dist/{web-k6w8-HnE.mjs → web-exQtGkoc.mjs} +14 -16
- package/dist/web-run.mjs +5 -5
- package/dist/{workspace-process-lock-BL7Q0HCO.mjs → workspace-process-lock-2mNzOlaB.mjs} +3 -2
- package/dist/{workspace-state-CL2V2Ons.mjs → workspace-state-DqcCbpE7.mjs} +34 -34
- package/dist/workspaces-Bcib97-6.mjs +306 -0
- package/dist/{worktree-BT_uULFx.mjs → worktree-Dc98cE6_.mjs} +1 -1
- package/dist/{worktree-qXKzADSC.mjs → worktree-ZpZR3S1k.mjs} +601 -33
- package/package.json +5 -5
- package/dist/device-capacity-DMuKC7nx.mjs +0 -136
- package/dist/hosted-macos-DwowNU7W.mjs +0 -447
- package/dist/logs-h9h6MUvE.mjs +0 -568
- package/dist/machine-usage-D_YYMzfR.mjs +0 -283
- package/dist/machines-CYtOCqcj.mjs +0 -259
- package/dist/merge-state-BnxLNQiM.mjs +0 -272
- package/dist/server-expo-KJeD109I.mjs +0 -2
- package/dist/settings-CduVcoxj.mjs +0 -680
- package/dist/stop-cause-CZ_Mr-v9.mjs +0 -665
- package/dist/watchman-Bx0wceoF.mjs +0 -238
- package/dist/worktree-C0c5Udwa.mjs +0 -753
|
@@ -1,29 +1,34 @@
|
|
|
1
1
|
import { t as getExecutor } from "./exec-CaErVv7t.mjs";
|
|
2
|
-
import { D as withConfigLock$1, H as projectDeviceSlots, _ as loadConfig$1, a as clearDevice, b as releaseAndroidConsolePort, i as clearAndroidBootPending, k as acquireAvdClaim, t as allConsolePortsAndSerials, w as setDevice, z as deviceSlotPlatforms } from "./config-D0DbpZtM.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import { D as makeTemporaryDirectory, O as removeTemporaryEntry, c as gitCommonDirOnDisk } from "./worktree-C0c5Udwa.mjs";
|
|
5
|
-
import { c as ownedDeviceLabel } from "./project-CV3tDFHl.mjs";
|
|
2
|
+
import { D as withConfigLock$1, H as projectDeviceSlots, _ as loadConfig$1, a as clearDevice, b as releaseAndroidConsolePort, i as clearAndroidBootPending, k as acquireAvdClaim, p as getProject, t as allConsolePortsAndSerials, w as setDevice, z as deviceSlotPlatforms } from "./config-D0DbpZtM.mjs";
|
|
3
|
+
import { n as ownership_claim_exports } from "./process-identity-BmRm1qV0.mjs";
|
|
6
4
|
import { r as waitForChild, t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
|
|
7
|
-
import { i as formatDuration, l as phaseLine, m as shortHash, u as plural } from "./command-output-
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { o as pidExists } from "./metro-
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import { b as
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import { a as
|
|
22
|
-
import { t as
|
|
5
|
+
import { i as formatDuration, l as phaseLine, m as shortHash, u as plural } from "./command-output-CDAIFD-8.mjs";
|
|
6
|
+
import { Tt as removeTemporaryEntry, a as androidAvdConfigSetting, at as gitCommonDirOnDisk, c as androidDataPartitionSizeGbSetting, wt as makeTemporaryDirectory } from "./settings-Cfd-0r2d.mjs";
|
|
7
|
+
import { u as ownedDeviceLabel } from "./project-D47Rh0ly.mjs";
|
|
8
|
+
import { o as pidExists } from "./metro-g8NqiJp-.mjs";
|
|
9
|
+
import { d as sharedBuildCache } from "./workspace-state-DqcCbpE7.mjs";
|
|
10
|
+
import { o as peekBudget } from "./budget-DM984mnd.mjs";
|
|
11
|
+
import { C as diffFingerprintSources, I as storedSources, w as entryDir, y as artifactIn } from "./device-lease-DpoS36_u.mjs";
|
|
12
|
+
import { A as listAvds, B as ownedAvdSystemImage, E as getAvdNameForSerial, F as ownedAvdDeviceProfile, J as resolveOwnedAvdSerial, L as ownedAvdMatchesConfiguration, O as listAdbDevices, P as nextConsolePort, R as ownedAvdName, W as pickDefaultSystemImage, b as createOwnedAvd, f as assertOwnedAvdStopped, ft as parkedMaxSetting, g as avdPoolConfiguration, j as listInstalledSystemImages, n as OWNED_AVD_CONFIG_DEFAULTS, pt as readParked, st as adoptParked, t as DEFAULT_AVD_DEVICE_PROFILE, tt as waitForBoot, ut as isLegacyDeletionClaim, v as bootAndroidEmulator, y as configureNewOwnedAvd } from "./android-B_YNZy61.mjs";
|
|
13
|
+
import { j as readHostMemoryPressure, u as listAllIosSims } from "./ios-DSfnPfse.mjs";
|
|
14
|
+
import { _ as teardownParkedAvd, m as teardownOwnedAvd } from "./ownership-BMLqyBgJ.mjs";
|
|
15
|
+
import { b as readStats$1, p as estimateBuild } from "./idle-B2m-Ovod.mjs";
|
|
16
|
+
import { b as tailLines, u as HEARTBEAT_INTERVAL_MS, y as startBuildHeartbeat } from "./toolchain-CNIBTIOv.mjs";
|
|
17
|
+
import { t as cleanLine } from "./server-expo-CHTyXD0G.mjs";
|
|
18
|
+
import { g as resolveBuildMachine, m as namedBuildMachine, t as configuredMachines } from "./machines-C2XiNwh9.mjs";
|
|
19
|
+
import { a as call, o as connectHost } from "./hosted-client-wk1W_CNW.mjs";
|
|
20
|
+
import { t as clearDeviceIdleShutdown } from "./idle-shutdown-_3oOV1V_.mjs";
|
|
21
|
+
import { i as countLiveOwnedDevices, n as DeviceAdmissionRefusal, p as withDeviceBootAdmission, s as peekDeviceSlots } from "./device-capacity-D0GWHnTM.mjs";
|
|
22
|
+
import { i as staleNativeDirRefusal } from "./prebuild-D7RUMkwN.mjs";
|
|
23
|
+
import { i as ensureOwnedIosDevice, r as ensureIosBooted } from "./device-ios-Bc7vbGwl.mjs";
|
|
24
|
+
import { r as readHostedNative, s as writeHostedNative } from "./ios-state-8L3lgum6.mjs";
|
|
25
|
+
import { n as prepareHostedNative } from "./hosted-native-C9xJ9rpA.mjs";
|
|
26
|
+
import { a as easAuthNote } from "./remote-cache-Ci4DQYYj.mjs";
|
|
27
|
+
import { t as reconcileSimSlim } from "./simslim-BWNrc3M3.mjs";
|
|
23
28
|
import { randomUUID } from "node:crypto";
|
|
24
29
|
import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
25
30
|
import { basename, dirname, join, relative } from "node:path";
|
|
26
|
-
import { LAST_BUILD_KEYS, loadConfig, readWorkspaceState } from "@stim-cli/core/state";
|
|
31
|
+
import { LAST_BUILD_KEYS, isJsonObject, loadConfig, machineCapacity, parseHostedChoice, parseHostedNativeOffer, readWorkspaceState } from "@stim-cli/core/state";
|
|
27
32
|
import { claimRemoveCommand, clearClaimChild, markClaimChildPending, processGroupAlive, releaseClaim, setClaimChild } from "@stim-cli/core/ownership-claim";
|
|
28
33
|
import { captureProcessIdentity } from "@stim-cli/core/process-identity";
|
|
29
34
|
import chalk from "chalk";
|
|
@@ -31,6 +36,219 @@ import { isDeepStrictEqual } from "node:util";
|
|
|
31
36
|
import * as expoFingerprint from "@expo/fingerprint";
|
|
32
37
|
import { resolveTieredBuild } from "@stim-cli/cache";
|
|
33
38
|
import { request } from "node:http";
|
|
39
|
+
//#region src/device-host/placement.ts
|
|
40
|
+
function local$1(reason, skipped = []) {
|
|
41
|
+
return {
|
|
42
|
+
kind: "local",
|
|
43
|
+
reason,
|
|
44
|
+
skipped
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function decideDevicePlacement(inputs) {
|
|
48
|
+
if ("sticky" in inputs) {
|
|
49
|
+
if ("machine" in inputs.sticky) {
|
|
50
|
+
const reason = `recorded session on ${inputs.sticky.machine}`;
|
|
51
|
+
return {
|
|
52
|
+
kind: "host",
|
|
53
|
+
reason,
|
|
54
|
+
machines: [{
|
|
55
|
+
machine: inputs.sticky.machine,
|
|
56
|
+
reason
|
|
57
|
+
}],
|
|
58
|
+
skipped: []
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
kind: "local",
|
|
63
|
+
reason: "this workspace's device runs here",
|
|
64
|
+
skipped: []
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
const { platform, here, offers, buildMachine, noWait } = inputs;
|
|
68
|
+
const { count, max, queued } = here.devices;
|
|
69
|
+
const cannotTake = !(max === 0 || count !== null && count < max) || queued > 0;
|
|
70
|
+
const usage = max > 0 ? `${count} of ${max} devices in use` : `${count} devices in use, no device cap`;
|
|
71
|
+
const localReason = count === null ? "cannot tell how many devices run here; local boot admission decides" : cannotTake ? `${usage}${queued ? `, ${queued} runs queued ahead` : ""}` : here.budgetRefusal ?? (here.memoryPressure !== "normal" ? `host memory pressure ${here.memoryPressure ?? "unknown"} here` : `load ${here.loadPerCore.toFixed(1)}/core here, ${usage}`);
|
|
72
|
+
if (!offers.length) return local$1("no hosting machines configured; " + localReason);
|
|
73
|
+
if (count === null) return local$1(localReason);
|
|
74
|
+
if (!cannotTake && here.memoryPressure === "normal" && !here.budgetRefusal && here.loadPerCore < here.maxLoadPerCore) return local$1(localReason);
|
|
75
|
+
const skipped = [];
|
|
76
|
+
const admitted = [];
|
|
77
|
+
offers.forEach((probe, index) => {
|
|
78
|
+
let reason = null;
|
|
79
|
+
if ("failure" in probe) reason = probe.failure;
|
|
80
|
+
else {
|
|
81
|
+
const { offer } = probe;
|
|
82
|
+
if (offer.declined !== null) reason = `declined: ${offer.declined}`;
|
|
83
|
+
else if (offer.platform !== platform || !offer.choice) reason = `no matching ${platform} device choice`;
|
|
84
|
+
else if (offer.resources.memoryPressure !== "normal") reason = "host memory pressure unknown or elevated";
|
|
85
|
+
else if (offer.capacity.available === 0) reason = "no hosted device capacity available";
|
|
86
|
+
else if (!cannotTake && (offer.resources.loadPerCore === null || offer.resources.loadPerCore >= here.loadPerCore)) reason = offer.resources.loadPerCore === null ? "host load unknown while this Mac has room" : "host is not less loaded than this Mac";
|
|
87
|
+
else admitted.push({
|
|
88
|
+
machine: probe.machine,
|
|
89
|
+
offer,
|
|
90
|
+
index
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
if (reason) skipped.push({
|
|
94
|
+
machine: probe.machine,
|
|
95
|
+
reason
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
admitted.sort((a, b) => Number(b.machine === buildMachine) - Number(a.machine === buildMachine) || (a.offer.resources.loadPerCore ?? Infinity) - (b.offer.resources.loadPerCore ?? Infinity) || b.offer.resources.memoryFreeBytes - a.offer.resources.memoryFreeBytes || a.index - b.index);
|
|
99
|
+
if (!admitted.length) return local$1(`${localReason}; no host admits${cannotTake && !noWait ? "; waiting locally if needed" : ""}`, skipped);
|
|
100
|
+
const machines = admitted.map(({ machine, offer }) => ({
|
|
101
|
+
machine,
|
|
102
|
+
reason: `${localReason}; ${machine}${machine === buildMachine ? " is the explicit build machine," : ""} load ${offer.resources.loadPerCore === null ? "unknown" : offer.resources.loadPerCore.toFixed(1) + "/core"}`
|
|
103
|
+
}));
|
|
104
|
+
return {
|
|
105
|
+
kind: "host",
|
|
106
|
+
machines,
|
|
107
|
+
reason: machines[0].reason,
|
|
108
|
+
skipped
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
//#endregion
|
|
112
|
+
//#region src/device-host/auto-placement.ts
|
|
113
|
+
async function probeHost(machine, platform, selectors) {
|
|
114
|
+
let host;
|
|
115
|
+
const deadline = Date.now() + 3e3;
|
|
116
|
+
try {
|
|
117
|
+
host = await connectHost(machine, 3e3, true);
|
|
118
|
+
const offer = await call(host, "device-host.offer", {
|
|
119
|
+
platform,
|
|
120
|
+
...selectors
|
|
121
|
+
}, Math.max(1, deadline - Date.now()));
|
|
122
|
+
const resources = isJsonObject(offer.resources) ? offer.resources : {};
|
|
123
|
+
const parsed = parseHostedNativeOffer({
|
|
124
|
+
...offer,
|
|
125
|
+
resources: {
|
|
126
|
+
...resources,
|
|
127
|
+
loadPerCore: resources.loadPerCore ?? 0
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
let choice = platform === "ios" ? offer.platform === "ios" ? parseHostedChoice(offer.choice) : null : parsed?.platform === "android" ? parsed.choice : null;
|
|
131
|
+
if (choice && ("runtime" in choice ? selectors.deviceType && selectors.deviceType !== choice.deviceType || selectors.runtime && selectors.runtime.replace(/^iOS /, "") !== choice.runtime.replace(/^iOS /, "") : selectors.systemImage && selectors.systemImage !== choice.systemImage || selectors.deviceProfile && selectors.deviceProfile !== choice.deviceProfile)) choice = null;
|
|
132
|
+
if (!isJsonObject(offer.capacity) || offer.declined !== null && typeof offer.declined !== "string") throw new Error("unreadable device offer");
|
|
133
|
+
return {
|
|
134
|
+
probe: {
|
|
135
|
+
machine,
|
|
136
|
+
offer: {
|
|
137
|
+
platform,
|
|
138
|
+
choice,
|
|
139
|
+
declined: offer.declined,
|
|
140
|
+
capacity: { available: typeof offer.capacity.available === "number" ? offer.capacity.available : null },
|
|
141
|
+
resources: {
|
|
142
|
+
loadPerCore: typeof resources.loadPerCore === "number" && Number.isFinite(resources.loadPerCore) && resources.loadPerCore >= 0 ? resources.loadPerCore : null,
|
|
143
|
+
memoryFreeBytes: typeof resources.memoryFreeBytes === "number" ? resources.memoryFreeBytes : 0,
|
|
144
|
+
memoryPressure: typeof resources.memoryPressure === "string" ? resources.memoryPressure : null
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
...choice ? { target: {
|
|
149
|
+
host,
|
|
150
|
+
choice,
|
|
151
|
+
session: null
|
|
152
|
+
} } : {}
|
|
153
|
+
};
|
|
154
|
+
} catch (error) {
|
|
155
|
+
return { probe: {
|
|
156
|
+
machine,
|
|
157
|
+
failure: error instanceof Error ? error.message : String(error)
|
|
158
|
+
} };
|
|
159
|
+
} finally {
|
|
160
|
+
host?.connection.close();
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function hosted(target, reason, skipped = []) {
|
|
164
|
+
target.selection = {
|
|
165
|
+
selected: "auto",
|
|
166
|
+
reason
|
|
167
|
+
};
|
|
168
|
+
return {
|
|
169
|
+
target,
|
|
170
|
+
placement: {
|
|
171
|
+
decision: "hosted",
|
|
172
|
+
machine: target.host.machine,
|
|
173
|
+
reason
|
|
174
|
+
},
|
|
175
|
+
skipped
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function local(reason, skipped = []) {
|
|
179
|
+
return {
|
|
180
|
+
target: null,
|
|
181
|
+
placement: {
|
|
182
|
+
decision: "local",
|
|
183
|
+
reason
|
|
184
|
+
},
|
|
185
|
+
skipped
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
async function automaticDevicePlacement({ root, slot, platform, selectors, buildMachine, noWait }, { machines = configuredMachines, read = readHostedNative, write = writeHostedNative, resume = prepareHostedNative, peek = () => peekDeviceSlots({
|
|
189
|
+
platform,
|
|
190
|
+
project: getProject(root),
|
|
191
|
+
slot
|
|
192
|
+
}), capacity = machineCapacity, memory = readHostMemoryPressure, probe = probeHost, budget = peekBudget } = {}) {
|
|
193
|
+
const recorded = read(root, platform, slot)[slot];
|
|
194
|
+
if (recorded) {
|
|
195
|
+
const target = await resume(recorded.machine, selectors, recorded, platform, true);
|
|
196
|
+
if (target) return {
|
|
197
|
+
target,
|
|
198
|
+
placement: {
|
|
199
|
+
decision: "hosted",
|
|
200
|
+
machine: recorded.machine,
|
|
201
|
+
reason: recorded.reason ?? decideDevicePlacement({ sticky: { machine: recorded.machine } }).reason
|
|
202
|
+
},
|
|
203
|
+
skipped: [],
|
|
204
|
+
sticky: true
|
|
205
|
+
};
|
|
206
|
+
write(root, slot, null, platform);
|
|
207
|
+
}
|
|
208
|
+
const devices = peek();
|
|
209
|
+
if (devices.localLive) return {
|
|
210
|
+
...local(decideDevicePlacement({ sticky: { local: true } }).reason),
|
|
211
|
+
sticky: true
|
|
212
|
+
};
|
|
213
|
+
const entries = machines();
|
|
214
|
+
if (entries === null) throw Object.assign(/* @__PURE__ */ new Error("hosting.machines is invalid. Run stim guide settings and correct it."), { code: "STIM_HOSTING_REFUSED" });
|
|
215
|
+
const preference = resolveBuildMachine(buildMachine, process.env.STIM_OFFLOAD_MACHINE, loadConfig$1()?.offload?.machine);
|
|
216
|
+
buildMachine = namedBuildMachine(preference) ? preference : void 0;
|
|
217
|
+
const load = capacity();
|
|
218
|
+
const here = {
|
|
219
|
+
loadPerCore: load.loadPerCore,
|
|
220
|
+
maxLoadPerCore: load.maxLoadPerCore,
|
|
221
|
+
memoryPressure: memory(),
|
|
222
|
+
devices,
|
|
223
|
+
budgetRefusal: await budget(root)
|
|
224
|
+
};
|
|
225
|
+
const early = decideDevicePlacement({
|
|
226
|
+
platform,
|
|
227
|
+
here,
|
|
228
|
+
offers: entries.map((machine) => ({
|
|
229
|
+
machine,
|
|
230
|
+
failure: "not probed"
|
|
231
|
+
})),
|
|
232
|
+
buildMachine,
|
|
233
|
+
noWait
|
|
234
|
+
});
|
|
235
|
+
if (early.kind === "local" && early.skipped.length === 0) return local(early.reason);
|
|
236
|
+
const probes = await Promise.all(entries.map((machine) => probe(machine, platform, selectors)));
|
|
237
|
+
const decision = decideDevicePlacement({
|
|
238
|
+
platform,
|
|
239
|
+
here,
|
|
240
|
+
offers: probes.map((each) => each.probe),
|
|
241
|
+
buildMachine,
|
|
242
|
+
noWait
|
|
243
|
+
});
|
|
244
|
+
if (decision.kind === "local") return local(decision.reason, decision.skipped);
|
|
245
|
+
const target = probes.find((each) => each.probe.machine === decision.machines[0].machine).target;
|
|
246
|
+
return hosted(target, decision.reason, decision.skipped);
|
|
247
|
+
}
|
|
248
|
+
function devicePlacementLine(placement, skipped) {
|
|
249
|
+
return `${placement.machine ?? "local"}, ${placement.reason}${placement.decision !== "hosted" && skipped.length ? "; " + skipped.map((each) => `${each.machine}: ${each.reason}`).join("; ") : ""}`;
|
|
250
|
+
}
|
|
251
|
+
//#endregion
|
|
34
252
|
//#region src/engine/metro-warmup.ts
|
|
35
253
|
const WARMUP_TIMEOUT_MS = 6e4;
|
|
36
254
|
async function requestLocal(url, platform, prefetch) {
|
|
@@ -326,6 +544,7 @@ async function ensureOwnedAndroidDevice({ record, projectPath, slot, settingsRoo
|
|
|
326
544
|
out(chalk.dim(`Recorded port for owned AVD ${record.avdName} is not currently ours; booting it on a freshly allocated port...`));
|
|
327
545
|
return {
|
|
328
546
|
...await bootOwnedAvdOnFreshPort({
|
|
547
|
+
deviceSlotWait: flags.deviceSlotWait,
|
|
329
548
|
avdName: record.avdName,
|
|
330
549
|
metadata: record,
|
|
331
550
|
projectPath,
|
|
@@ -398,6 +617,7 @@ async function ensureOwnedAndroidDevice({ record, projectPath, slot, settingsRoo
|
|
|
398
617
|
}
|
|
399
618
|
return {
|
|
400
619
|
...await bootOwnedAvdOnFreshPort({
|
|
620
|
+
deviceSlotWait: flags.deviceSlotWait,
|
|
401
621
|
avdName: parked.name,
|
|
402
622
|
projectPath,
|
|
403
623
|
slot,
|
|
@@ -436,6 +656,7 @@ async function ensureOwnedAndroidDevice({ record, projectPath, slot, settingsRoo
|
|
|
436
656
|
}
|
|
437
657
|
return {
|
|
438
658
|
...await bootOwnedAvdOnFreshPort({
|
|
659
|
+
deviceSlotWait: flags.deviceSlotWait,
|
|
439
660
|
avdName: created.avdName,
|
|
440
661
|
metadata: created.created ? {
|
|
441
662
|
poolConfiguration: configuration,
|
|
@@ -473,41 +694,50 @@ function liveAndroidConsolePorts() {
|
|
|
473
694
|
const adbLive = listAdbDevices();
|
|
474
695
|
return [...adbLive.emulators.map((e) => e.consolePort), ...adbLive.unhealthy.map((u) => u.consolePort).filter((p) => p != null)];
|
|
475
696
|
}
|
|
476
|
-
async function bootOwnedAvdOnFreshPort({ avdName, metadata, projectPath, slot, deviceName, out, logFile = null, alive = pidExists }) {
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
const pid = bootAndroidEmulator(avdName, claim.consolePort, { logFile });
|
|
489
|
-
out(chalk.dim(phaseLine("device", `waiting for ${serial} to finish booting`)));
|
|
490
|
-
const result = await waitForAndroidBoot({
|
|
491
|
-
serial,
|
|
492
|
-
timeoutMs: ANDROID_FRESH_BOOT_TIMEOUT_MS,
|
|
493
|
-
pid,
|
|
494
|
-
alive,
|
|
495
|
-
out
|
|
697
|
+
async function bootOwnedAvdOnFreshPort({ avdName, deviceSlotWait, metadata, projectPath, slot, deviceName, out, logFile = null, alive = pidExists }) {
|
|
698
|
+
return withDeviceBootAdmission({
|
|
699
|
+
platform: "android",
|
|
700
|
+
key: avdName
|
|
701
|
+
}, async () => {
|
|
702
|
+
const claim = claimAndroidConsolePort({
|
|
703
|
+
projectPath,
|
|
704
|
+
slot,
|
|
705
|
+
avdName,
|
|
706
|
+
deviceName,
|
|
707
|
+
livePorts: liveAndroidConsolePorts(),
|
|
708
|
+
metadata
|
|
496
709
|
});
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
710
|
+
const serial = `emulator-${claim.consolePort}`;
|
|
711
|
+
try {
|
|
712
|
+
reportAndroidMemoryPressure(out);
|
|
713
|
+
const pid = bootAndroidEmulator(avdName, claim.consolePort, { logFile });
|
|
714
|
+
out(chalk.dim(phaseLine("device", `waiting for ${serial} to finish booting`)));
|
|
715
|
+
const result = await waitForAndroidBoot({
|
|
716
|
+
serial,
|
|
717
|
+
timeoutMs: ANDROID_FRESH_BOOT_TIMEOUT_MS,
|
|
718
|
+
pid,
|
|
719
|
+
alive,
|
|
720
|
+
out
|
|
721
|
+
});
|
|
722
|
+
if (result.failed) throw new AvdBootError(result.reason, result.remedy);
|
|
723
|
+
const running = getAvdNameForSerial(serial);
|
|
724
|
+
if (running && running !== avdName) throw new Error(`${serial} is running AVD ${running}, not this workspace's owned AVD ${avdName}; refusing to use it.`);
|
|
725
|
+
clearAndroidBootPending(projectPath, avdName, slot);
|
|
726
|
+
const { bootPending: _booted, ...booted } = claim;
|
|
727
|
+
return {
|
|
728
|
+
...booted,
|
|
729
|
+
serial,
|
|
730
|
+
setup: true
|
|
731
|
+
};
|
|
732
|
+
} catch (error) {
|
|
733
|
+
releaseAndroidConsolePort(projectPath, claim.consolePort, slot);
|
|
734
|
+
throw error;
|
|
735
|
+
}
|
|
736
|
+
}, {
|
|
737
|
+
...deviceSlotWait,
|
|
738
|
+
root: projectPath,
|
|
739
|
+
out
|
|
740
|
+
});
|
|
511
741
|
}
|
|
512
742
|
function reportAndroidMemoryPressure(out) {
|
|
513
743
|
const pressure = readHostMemoryPressure();
|
|
@@ -516,11 +746,15 @@ function reportAndroidMemoryPressure(out) {
|
|
|
516
746
|
function androidBootRemedy(pressure) {
|
|
517
747
|
let count = null;
|
|
518
748
|
try {
|
|
519
|
-
|
|
520
|
-
sims: process.platform === "darwin" ? listAllIosSims({ timeoutMs: 2e3 }) : [],
|
|
521
|
-
|
|
522
|
-
|
|
749
|
+
const live = countLiveOwnedDevices({
|
|
750
|
+
sims: () => process.platform === "darwin" ? listAllIosSims({ timeoutMs: 2e3 }) : [],
|
|
751
|
+
adb: () => ({
|
|
752
|
+
...listAdbDevices({ timeoutMs: 2e3 }),
|
|
753
|
+
unhealthy: []
|
|
754
|
+
}),
|
|
755
|
+
booting: []
|
|
523
756
|
});
|
|
757
|
+
count = typeof live === "number" ? live : null;
|
|
524
758
|
} catch {}
|
|
525
759
|
const observation = pressure === "warning" || pressure === "critical" ? `macOS reports ${pressure} host memory pressure. ` : "";
|
|
526
760
|
const devices = count ? `${count} Stim-owned ${count === 1 ? "device is" : "devices are"} running. ` : "";
|
|
@@ -558,7 +792,7 @@ async function waitForAndroidBoot({ serial, timeoutMs, pid = null, alive = pidEx
|
|
|
558
792
|
remedy: exited ? "Inspect the emulator log for the process exit, fix what it reports, then run `stim android` again." : androidBootRemedy(pressure)
|
|
559
793
|
};
|
|
560
794
|
}
|
|
561
|
-
async function ensureAndroidBooted({ device, projectPath, slot, timeoutMs, out, logFile = null, alive = pidExists }) {
|
|
795
|
+
async function ensureAndroidBooted({ device, deviceSlotWait, projectPath, slot, timeoutMs, out, logFile = null, alive = pidExists }) {
|
|
562
796
|
if (!device?.avdName || !projectPath) return {
|
|
563
797
|
failed: true,
|
|
564
798
|
reason: "No owned Android emulator is recorded for this project."
|
|
@@ -596,36 +830,57 @@ async function ensureAndroidBooted({ device, projectPath, slot, timeoutMs, out,
|
|
|
596
830
|
timeoutMs,
|
|
597
831
|
out
|
|
598
832
|
}));
|
|
599
|
-
const
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
833
|
+
const boot = async () => {
|
|
834
|
+
const claim = claimAndroidConsolePort({
|
|
835
|
+
projectPath,
|
|
836
|
+
slot,
|
|
837
|
+
avdName,
|
|
838
|
+
deviceName: device.deviceName,
|
|
839
|
+
livePorts: liveAndroidConsolePorts(),
|
|
840
|
+
metadata: device
|
|
841
|
+
});
|
|
842
|
+
const serial = `emulator-${claim.consolePort}`;
|
|
843
|
+
reportAndroidMemoryPressure(out);
|
|
844
|
+
out(chalk.dim(phaseLine("device", `booting ${avdName} as ${serial}`)));
|
|
845
|
+
let pid = null;
|
|
846
|
+
try {
|
|
847
|
+
pid = bootAndroidEmulator(avdName, claim.consolePort, { logFile });
|
|
848
|
+
} catch (e) {
|
|
849
|
+
releaseAndroidConsolePort(projectPath, claim.consolePort, slot);
|
|
850
|
+
return {
|
|
851
|
+
failed: true,
|
|
852
|
+
reason: `Could not start emulator for AVD ${avdName}: ${e?.message || e}`
|
|
853
|
+
};
|
|
854
|
+
}
|
|
855
|
+
const result = await waitForAndroidBoot({
|
|
856
|
+
serial,
|
|
857
|
+
timeoutMs,
|
|
858
|
+
pid,
|
|
859
|
+
alive,
|
|
860
|
+
out
|
|
861
|
+
});
|
|
862
|
+
if (result.failed) releaseAndroidConsolePort(projectPath, claim.consolePort, slot);
|
|
863
|
+
return booted(result);
|
|
864
|
+
};
|
|
611
865
|
try {
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
866
|
+
return await withDeviceBootAdmission({
|
|
867
|
+
platform: "android",
|
|
868
|
+
key: avdName
|
|
869
|
+
}, boot, {
|
|
870
|
+
...deviceSlotWait,
|
|
871
|
+
root: projectPath,
|
|
872
|
+
out
|
|
873
|
+
});
|
|
874
|
+
} catch (error) {
|
|
875
|
+
const refusal = error instanceof DeviceAdmissionRefusal ? error : (0, ownership_claim_exports.claimFailure)(error, "stim android");
|
|
876
|
+
if (!refusal) throw error;
|
|
615
877
|
return {
|
|
616
878
|
failed: true,
|
|
617
|
-
|
|
879
|
+
code: refusal.code,
|
|
880
|
+
reason: refusal.message,
|
|
881
|
+
remedy: refusal.remedy
|
|
618
882
|
};
|
|
619
883
|
}
|
|
620
|
-
const result = await waitForAndroidBoot({
|
|
621
|
-
serial,
|
|
622
|
-
timeoutMs,
|
|
623
|
-
pid,
|
|
624
|
-
alive,
|
|
625
|
-
out
|
|
626
|
-
});
|
|
627
|
-
if (result.failed) releaseAndroidConsolePort(projectPath, claim.consolePort, slot);
|
|
628
|
-
return booted(result);
|
|
629
884
|
}
|
|
630
885
|
//#endregion
|
|
631
886
|
//#region src/engine/device.ts
|
|
@@ -669,9 +924,11 @@ async function ensureOwnedDevice({ platform, project, projectPath, slot, setting
|
|
|
669
924
|
});
|
|
670
925
|
}
|
|
671
926
|
const BOOT_POLL_MS = 500;
|
|
672
|
-
async function ensureBooted({ platform, device, simulatorApp, timeoutMs, pollMs = BOOT_POLL_MS, out = () => {}, logFile = null, alive = pidExists, projectPath, slot
|
|
927
|
+
async function ensureBooted({ platform, device, simulatorApp, timeoutMs, pollMs = BOOT_POLL_MS, out = () => {}, logFile = null, alive = pidExists, projectPath, slot, deviceSlotWait }) {
|
|
673
928
|
if (platform === "ios") return ensureIosBooted({
|
|
674
929
|
device,
|
|
930
|
+
projectPath,
|
|
931
|
+
deviceSlotWait,
|
|
675
932
|
simulatorApp,
|
|
676
933
|
timeoutMs: timeoutMs ?? 6e5,
|
|
677
934
|
pollMs,
|
|
@@ -679,6 +936,7 @@ async function ensureBooted({ platform, device, simulatorApp, timeoutMs, pollMs
|
|
|
679
936
|
});
|
|
680
937
|
if (platform === "android") return ensureAndroidBooted({
|
|
681
938
|
device,
|
|
939
|
+
deviceSlotWait,
|
|
682
940
|
projectPath,
|
|
683
941
|
slot,
|
|
684
942
|
timeoutMs: timeoutMs ?? ANDROID_BOOT_TIMEOUT_MS,
|
|
@@ -1467,7 +1725,7 @@ async function planCachedBuild(lookup, deps) {
|
|
|
1467
1725
|
function planPayload({ platform, slot, projectKey }, found) {
|
|
1468
1726
|
const { refusal, missReason, ...rest } = found;
|
|
1469
1727
|
const outcome = refusal ? null : found.cacheHit ? "hit" : "cold";
|
|
1470
|
-
const estimate = outcome ? estimateBuild(readStats().record?.history?.[projectKey], platform, outcome) : {
|
|
1728
|
+
const estimate = outcome ? estimateBuild(readStats$1().record?.history?.[projectKey], platform, outcome) : {
|
|
1471
1729
|
expectedMs: null,
|
|
1472
1730
|
basis: 0
|
|
1473
1731
|
};
|
|
@@ -1524,4 +1782,4 @@ function planFlagRefusal(flag) {
|
|
|
1524
1782
|
};
|
|
1525
1783
|
}
|
|
1526
1784
|
//#endregion
|
|
1527
|
-
export { AvdRecoveryError as _, refusePlan as a, skippedMissReason as c, refreshUpdatesManifestFile as d, swapJsBundle as f, AvdBootError as g, ensureOwnedDevice as h, printPlan as i, UPDATES_MANIFEST_NAME as l, ensureBooted as m, planFlagRefusal as n, explainBuildMiss as o, didSetUpDevice as p, planPayload as r, fingerprintErrorMissReason as s, planCachedBuild as t, detectEntryFile as u, warmMetro as v };
|
|
1785
|
+
export { AvdRecoveryError as _, refusePlan as a, devicePlacementLine as b, skippedMissReason as c, refreshUpdatesManifestFile as d, swapJsBundle as f, AvdBootError as g, ensureOwnedDevice as h, printPlan as i, UPDATES_MANIFEST_NAME as l, ensureBooted as m, planFlagRefusal as n, explainBuildMiss as o, didSetUpDevice as p, planPayload as r, fingerprintErrorMissReason as s, planCachedBuild as t, detectEntryFile as u, warmMetro as v, automaticDevicePlacement as y };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as ownership_claim_exports } from "./process-identity-BmRm1qV0.mjs";
|
|
2
|
+
import { a as formatElapsed } from "./command-output-CDAIFD-8.mjs";
|
|
2
3
|
import { n as declareSpawnsOn, o as stopDeclaringSpawnsOn } from "./spawn-claims-D0XfSe8u.mjs";
|
|
3
|
-
import { a as formatElapsed } from "./command-output-CliHHn7a.mjs";
|
|
4
4
|
import { readdirSync, statSync } from "node:fs";
|
|
5
5
|
import { join } from "node:path";
|
|
6
6
|
import { buildSlotsDir, tryAcquireBuildSlotClaim } from "@stim-cli/core/state";
|
|
@@ -53,34 +53,49 @@ function tryAcquireBuildSlot({ max, root = null, logFile = null }) {
|
|
|
53
53
|
function slotWaitingLine({ max, elapsedMs }) {
|
|
54
54
|
return `${"build".padEnd(11)} waiting for a build slot (all ${max} in use, ${formatElapsed(elapsedMs)} elapsed) -- stim guide lifecycle concurrency`;
|
|
55
55
|
}
|
|
56
|
-
async function acquireBuildSlot({ max, root = null, logFile = null, now = Date.now, out = () => {}, sleep = sleepAsync, intervalMs = SLOT_POLL_MS, progressMs = SLOT_PROGRESS_MS, ceilingMs = SLOT_CEILING_MS }) {
|
|
56
|
+
async function acquireBuildSlot({ max, root = null, logFile = null, now = Date.now, out = () => {}, waitingFor = () => {}, sleep = sleepAsync, intervalMs = SLOT_POLL_MS, progressMs = SLOT_PROGRESS_MS, ceilingMs = SLOT_CEILING_MS }) {
|
|
57
57
|
if (!max || max <= 0) return {
|
|
58
58
|
acquired: true,
|
|
59
59
|
unlimited: true
|
|
60
60
|
};
|
|
61
61
|
const started = now();
|
|
62
62
|
let lastProgress = started;
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
63
|
+
let waited = false;
|
|
64
|
+
try {
|
|
65
|
+
for (;;) {
|
|
66
|
+
const got = tryAcquireBuildSlot({
|
|
67
|
+
max,
|
|
68
|
+
root,
|
|
69
|
+
logFile
|
|
70
|
+
});
|
|
71
|
+
if (got) return {
|
|
72
|
+
...got,
|
|
73
|
+
slotWaitMs: waited ? Math.max(0, Math.round(now() - started)) : 0
|
|
74
|
+
};
|
|
75
|
+
waited = true;
|
|
76
|
+
waitingFor({
|
|
77
|
+
kind: "build-slot",
|
|
78
|
+
inUse: max,
|
|
79
79
|
max,
|
|
80
|
-
|
|
81
|
-
})
|
|
80
|
+
since: new Date(started).toISOString()
|
|
81
|
+
});
|
|
82
|
+
const elapsed = now() - started;
|
|
83
|
+
if (elapsed >= ceilingMs) {
|
|
84
|
+
const err = /* @__PURE__ */ new Error(`Waited ${formatElapsed(elapsed)} for one of ${max} build slots, and every slot is held by a process that is still running, or by a holder Stim cannot identify. Slots live under ` + buildSlotsDir() + "; remove a slot directory whose builder is not really building, or raise concurrency.maxBuilds.");
|
|
85
|
+
err.code = "STIM_BUILD_SLOT_TIMEOUT";
|
|
86
|
+
throw err;
|
|
87
|
+
}
|
|
88
|
+
if (now() - lastProgress >= progressMs) {
|
|
89
|
+
lastProgress = now();
|
|
90
|
+
out(slotWaitingLine({
|
|
91
|
+
max,
|
|
92
|
+
elapsedMs: elapsed
|
|
93
|
+
}));
|
|
94
|
+
}
|
|
95
|
+
await sleep(intervalMs);
|
|
82
96
|
}
|
|
83
|
-
|
|
97
|
+
} finally {
|
|
98
|
+
waitingFor(null);
|
|
84
99
|
}
|
|
85
100
|
}
|
|
86
101
|
function releaseBuildSlot(handle) {
|
|
@@ -3,23 +3,23 @@ import { readFileSync } from "node:fs";
|
|
|
3
3
|
import { Command } from "commander";
|
|
4
4
|
//#region bin/cli.ts
|
|
5
5
|
const commands = /* @__PURE__ */ new Map([
|
|
6
|
-
["doctor", () => import("./doctor-
|
|
7
|
-
["worktree", () => import("./worktree-
|
|
8
|
-
["start", () => import("./start-
|
|
9
|
-
["ports", () => import("./ports-
|
|
10
|
-
["stop", () => import("./stop-
|
|
11
|
-
["ios", () => import("./ios-
|
|
12
|
-
["android", () => import("./android
|
|
13
|
-
["web", () => import("./web-
|
|
14
|
-
["macos", () => import("./macos-
|
|
15
|
-
["reload", () => import("./reload-
|
|
16
|
-
["device", () => import("./device-
|
|
17
|
-
["logs", () => import("./logs-
|
|
18
|
-
["settings", () => import("./settings-
|
|
19
|
-
["status", () => import("./status-
|
|
20
|
-
["stats", () => import("./stats-
|
|
21
|
-
["gc", () => import("./gc-
|
|
22
|
-
["guide", () => import("./guide-
|
|
6
|
+
["doctor", () => import("./doctor-Cnk9d7Hm.mjs")],
|
|
7
|
+
["worktree", () => import("./worktree-Dc98cE6_.mjs")],
|
|
8
|
+
["start", () => import("./start-BopZcr4n.mjs")],
|
|
9
|
+
["ports", () => import("./ports-4nYqxPWC.mjs")],
|
|
10
|
+
["stop", () => import("./stop-BCwvvs7F.mjs")],
|
|
11
|
+
["ios", () => import("./ios-DE6duQoz.mjs")],
|
|
12
|
+
["android", () => import("./android--GorydsK.mjs")],
|
|
13
|
+
["web", () => import("./web-exQtGkoc.mjs")],
|
|
14
|
+
["macos", () => import("./macos-32po3kUq.mjs")],
|
|
15
|
+
["reload", () => import("./reload-qZei6iWn.mjs")],
|
|
16
|
+
["device", () => import("./device-C8IOoJPv.mjs")],
|
|
17
|
+
["logs", () => import("./logs-DUoKlDoS.mjs")],
|
|
18
|
+
["settings", () => import("./settings-SR9OmW9h.mjs")],
|
|
19
|
+
["status", () => import("./status-dXX2JX1C.mjs")],
|
|
20
|
+
["stats", () => import("./stats-Bq4fJOdB.mjs")],
|
|
21
|
+
["gc", () => import("./gc-DxCL2A46.mjs")],
|
|
22
|
+
["guide", () => import("./guide-DjrTQGik.mjs")]
|
|
23
23
|
]);
|
|
24
24
|
const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
|
|
25
25
|
const program = new Command();
|
|
@@ -33,6 +33,12 @@ try {
|
|
|
33
33
|
const modules = await Promise.all([...commands.values()].map((load) => load()));
|
|
34
34
|
for (const module of modules) module.default(program, pkg.version);
|
|
35
35
|
}
|
|
36
|
+
program.hook("preAction", async (_command, action) => {
|
|
37
|
+
try {
|
|
38
|
+
const { triggerMaintenance } = await import("./trigger-CXts6qt1.mjs");
|
|
39
|
+
triggerMaintenance(action.name());
|
|
40
|
+
} catch {}
|
|
41
|
+
});
|
|
36
42
|
await program.parseAsync();
|
|
37
43
|
} catch (err) {
|
|
38
44
|
const code = err?.code;
|