stim 1.1.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -0
- package/dist/{android-CC5bUer7.mjs → android-BW8i_YxU.mjs} +1 -1
- package/dist/android-BqVIJoG7.mjs +1368 -0
- package/dist/{android-DnZlT3aU.mjs → android-CqcW1hrP.mjs} +205 -58
- package/dist/{android-cas-DGlTStWu.mjs → android-cas-BR5YJBYv.mjs} +6 -6
- package/dist/android-cas-compiler.mjs +1 -1
- package/dist/{app-install-oZIQRbdD.mjs → app-install-DIp9riNx.mjs} +29 -21
- package/dist/{build-slots-CgacA9zQ.mjs → build-slots-C3-R4XQr.mjs} +3 -3
- package/dist/{cache-manifest-oeH18ERr.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 +4 -1
- package/dist/collector-run.mjs +36 -11
- package/dist/{config-D7uu8Gbq.mjs → config-CcefMY2Q.mjs} +94 -13
- package/dist/{deps-64wVnpZc.mjs → deps-Spz8ozgo.mjs} +2 -2
- package/dist/{dev-client-Bvky1hya.mjs → dev-client-BjisHDB5.mjs} +250 -10
- package/dist/{device-DJKv5Qej.mjs → device-BkiW-gkk.mjs} +19 -11
- package/dist/{device-lease-D-G3SgVe.mjs → device-lease-BJYybF-2.mjs} +107 -83
- package/dist/{device-pool-BlHXnYYs.mjs → device-pool-CPbLGfrB.mjs} +19 -13
- package/dist/{device-remote-CCgkG82J.mjs → device-remote-AkYCKS8U.mjs} +8 -8
- package/dist/{doctor-DlVxTtMq.mjs → doctor-Bmv86UUW.mjs} +18 -26
- package/dist/{doctor-BRF9aAJ3.mjs → doctor-fAMXC4vl.mjs} +10 -10
- package/dist/{error-diagnostics-B5IJwv3-.mjs → error-diagnostics-DHC31rXA.mjs} +65 -55
- package/dist/{exec-bsN9MJXb.mjs → exec-CyylIdq9.mjs} +4 -2
- package/dist/{gc-DhXdgSdt.mjs → gc-GGu-8ULN.mjs} +90 -67
- package/dist/{guide-DrhrDBo5.mjs → guide-92CPA21s.mjs} +414 -47
- package/dist/{ios-CK1Vrk6Q.mjs → ios-BSXFeO5H.mjs} +200 -59
- package/dist/{ios-BZxKPuqP.mjs → ios-Deh5js5V.mjs} +147 -40
- package/dist/{ios-device-CdSm0GDw.mjs → ios-device-CWOM_S44.mjs} +2 -2
- package/dist/{ios-device-CYbuRNXR.mjs → ios-device-D3pzTKQE.mjs} +1 -1
- package/dist/{logs-Dxoy16Qv.mjs → logs-DPNF4C9s.mjs} +9 -6
- package/dist/{logs-query-oqn47Ffx.mjs → logs-query-R-Cqc6Qv.mjs} +22 -5
- package/dist/{metro-B01H3EuD.mjs → metro-CORqXyTL.mjs} +3 -3
- package/dist/{ndjson-DcAtEx_K.mjs → ndjson-BZwI1NBv.mjs} +5 -2
- package/dist/{ownership-D8HmSv2E.mjs → ownership-8O073GIC.mjs} +3 -3
- package/dist/{ownership-B9QIdQOw.mjs → ownership-BpCKiRlQ.mjs} +4 -4
- package/dist/{ownership-claim-CeJLEpjD.mjs → ownership-claim-Bf2CAfw3.mjs} +4 -3
- package/dist/{project-COj6nzzh.mjs → project-fKmuIaMI.mjs} +2 -2
- package/dist/{reclaim-BPvN2HlP.mjs → reclaim-iW9Cad7k.mjs} +80 -73
- package/dist/{reload-DYZEBbZy.mjs → reload-DazHDSFA.mjs} +32 -24
- package/dist/{server-bare-BYHqEeyw.mjs → server-bare-DEzPZLvf.mjs} +7 -2
- package/dist/server-expo-44em5Pmg.mjs +2 -0
- package/dist/{server-expo-BEMr_m6p.mjs → server-expo-DizT4OMk.mjs} +5 -5
- package/dist/{settings-BSwrY4FZ.mjs → settings-DEJf6_kJ.mjs} +26 -5
- package/dist/slot-launch-cci0xvmC.mjs +19 -0
- package/dist/{start-ByCylYtB.mjs → start-mObjQH2W.mjs} +12 -12
- package/dist/{state-IYEY-zi8.mjs → state-B3XA2wp2.mjs} +9 -9
- package/dist/{stats-wqxPm7Tv.mjs → stats-BR-kwj0B.mjs} +1 -1
- package/dist/{stats-DZ4Q5J-7.mjs → stats-CaaQr4yN.mjs} +3 -3
- package/dist/{status-Dia0XTqG.mjs → status-BxQNqu9t.mjs} +86 -25
- package/dist/{stop-D6o5zAdm.mjs → stop-CrHGcjrV.mjs} +2 -2
- package/dist/{stop-BApyaF21.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-DOi5-zLj.mjs → teardown-ClFp1Aax.mjs} +889 -830
- package/dist/{workspace-process-lock-CxOO9-pf.mjs → workspace-process-lock-3NcQnZ0X.mjs} +1 -1
- package/dist/{worktree-DxEmUI_n.mjs → worktree-DxTgN1CJ.mjs} +16 -16
- package/dist/{worktree-Dx3ZC5lS.mjs → worktree-Eq6TLH8N.mjs} +7 -3
- package/dist/{xcode-CDB6fytw.mjs → xcode-D7sAp-Zy.mjs} +256 -103
- package/package.json +5 -5
- package/shim/bundle-response.cjs +5 -0
- package/dist/android-xmyGBNy5.mjs +0 -665
- package/dist/build-lock-vE45ZzJZ.mjs +0 -645
- package/dist/server-expo-rb0k-0w7.mjs +0 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { I as deviceSlotKey } from "./config-CcefMY2Q.mjs";
|
|
1
2
|
import { a as formatElapsed, r as clockTime } from "./command-output-8wHMEde0.mjs";
|
|
2
|
-
import { A as APP_READINESS_TIMEOUT_MS, l as VERIFY_TIMEOUT_MS } from "./app-install-
|
|
3
|
-
import { a as parseLease, c as releaseRunLease, d as selectPoolDevice, f as takeLease, n as fileLeaseIo, r as leaseIsExpired, s as raiseLease, t as deviceLeasePath } from "./device-lease-
|
|
3
|
+
import { A as APP_READINESS_TIMEOUT_MS, l as VERIFY_TIMEOUT_MS } from "./app-install-DIp9riNx.mjs";
|
|
4
|
+
import { a as parseLease, c as releaseRunLease, d as selectPoolDevice, f as takeLease, n as fileLeaseIo, r as leaseIsExpired, s as raiseLease, t as deviceLeasePath } from "./device-lease-BJYybF-2.mjs";
|
|
4
5
|
//#region src/engine/device-lease-run.ts
|
|
5
6
|
const LEASE_STEP_FLOOR_MS = 6e4;
|
|
6
7
|
const DEBUG_VERIFY_STEP_MS = VERIFY_TIMEOUT_MS + APP_READINESS_TIMEOUT_MS;
|
|
@@ -36,7 +37,7 @@ function facts(lease) {
|
|
|
36
37
|
};
|
|
37
38
|
}
|
|
38
39
|
function waitingLine(lease, now) {
|
|
39
|
-
return `waiting for ${lease.holder} to release ${describeDevice(lease)}; its lease runs until ${leaseExpiryText(lease.expiresAt, now)}`;
|
|
40
|
+
return `waiting for ${lease.holder} to release ${describeDevice(lease)}; its lease runs until ${leaseExpiryText(lease.expiresAt, now)} -- stim guide lifecycle lease`;
|
|
40
41
|
}
|
|
41
42
|
function appIdMatch(ours, theirs) {
|
|
42
43
|
if (!ours || !theirs) return "unknown";
|
|
@@ -101,7 +102,7 @@ function lostRefusal(holder, expiresAt, now) {
|
|
|
101
102
|
lease: null
|
|
102
103
|
};
|
|
103
104
|
}
|
|
104
|
-
function runLease({ root, platform, kind, expiresAt, io = fileLeaseIo }) {
|
|
105
|
+
function runLease({ root, platform, slot = "default", kind, expiresAt, io = fileLeaseIo }) {
|
|
105
106
|
const handle = {
|
|
106
107
|
kind,
|
|
107
108
|
expiresAt,
|
|
@@ -115,6 +116,7 @@ function runLease({ root, platform, kind, expiresAt, io = fileLeaseIo }) {
|
|
|
115
116
|
const result = raiseLease({
|
|
116
117
|
root,
|
|
117
118
|
platform,
|
|
119
|
+
slot,
|
|
118
120
|
minMs: leaseStepMs(boundMs)
|
|
119
121
|
}, io);
|
|
120
122
|
if (result.status === "raised") {
|
|
@@ -137,7 +139,8 @@ function runLease({ root, platform, kind, expiresAt, io = fileLeaseIo }) {
|
|
|
137
139
|
if (handle.kind === null) return;
|
|
138
140
|
releaseRunLease({
|
|
139
141
|
root,
|
|
140
|
-
platform
|
|
142
|
+
platform,
|
|
143
|
+
slot
|
|
141
144
|
}, io);
|
|
142
145
|
},
|
|
143
146
|
facts() {
|
|
@@ -173,7 +176,7 @@ function releaseLeaseOnSignal(release, { on = (signal, handler) => {
|
|
|
173
176
|
installed.length = 0;
|
|
174
177
|
};
|
|
175
178
|
}
|
|
176
|
-
async function waitForDevice({ root, platform, id, idLabel, waitSeconds, noWait = false, appId = null, holderAppId = () => null, now = Date.now, sleep = (ms) => new Promise((r) => setTimeout(r, ms)), warn = () => {}, io = fileLeaseIo, deadline, lastLine }) {
|
|
179
|
+
async function waitForDevice({ root, platform, slot = "default", id, idLabel, waitSeconds, noWait = false, appId = null, holderAppId = () => null, now = Date.now, sleep = (ms) => new Promise((r) => setTimeout(r, ms)), warn = () => {}, io = fileLeaseIo, deadline, lastLine }) {
|
|
177
180
|
const path = deviceLeasePath(platform, id);
|
|
178
181
|
for (;;) {
|
|
179
182
|
const raw = io.readLease(path);
|
|
@@ -183,7 +186,7 @@ async function waitForDevice({ root, platform, id, idLabel, waitSeconds, noWait
|
|
|
183
186
|
refusal: unreadableRefusal(path)
|
|
184
187
|
};
|
|
185
188
|
if (!current || leaseIsExpired(current, now())) return { status: "free" };
|
|
186
|
-
if (current.holder === root) return {
|
|
189
|
+
if (current.holder === root && (current.slot ?? "default") === slot) return {
|
|
187
190
|
status: "ours",
|
|
188
191
|
lease: current
|
|
189
192
|
};
|
|
@@ -210,8 +213,8 @@ async function waitForDevice({ root, platform, id, idLabel, waitSeconds, noWait
|
|
|
210
213
|
await sleep(DEVICE_WAIT_POLL_MS);
|
|
211
214
|
}
|
|
212
215
|
}
|
|
213
|
-
async function acquireRunLease({ root, platform, id, deviceName = null, idLabel, waitSeconds, noWait, installBoundMs, appId = null, holderAppId = () => null, now = Date.now, sleep = (ms) => new Promise((r) => setTimeout(r, ms)), warn = () => {}, io = fileLeaseIo }) {
|
|
214
|
-
const recorded = io.readHolder(root)[platform];
|
|
216
|
+
async function acquireRunLease({ root, platform, slot = "default", id, deviceName = null, idLabel, waitSeconds, noWait, installBoundMs, appId = null, holderAppId = () => null, now = Date.now, sleep = (ms) => new Promise((r) => setTimeout(r, ms)), warn = () => {}, io = fileLeaseIo }) {
|
|
217
|
+
const recorded = io.readHolder(root)[deviceSlotKey(platform, slot)];
|
|
215
218
|
let held = recorded;
|
|
216
219
|
if (recorded && recorded.id !== id) {
|
|
217
220
|
const other = parseLease(io.readLease(deviceLeasePath(platform, recorded.id)));
|
|
@@ -234,6 +237,7 @@ async function acquireRunLease({ root, platform, id, deviceName = null, idLabel,
|
|
|
234
237
|
const raised = raiseLease({
|
|
235
238
|
root,
|
|
236
239
|
platform,
|
|
240
|
+
slot,
|
|
237
241
|
minMs: leaseStepMs(installBoundMs)
|
|
238
242
|
}, io);
|
|
239
243
|
if (raised.status === "raised") return {
|
|
@@ -245,6 +249,7 @@ async function acquireRunLease({ root, platform, id, deviceName = null, idLabel,
|
|
|
245
249
|
const outcome = await waitForDevice({
|
|
246
250
|
root,
|
|
247
251
|
platform,
|
|
252
|
+
slot,
|
|
248
253
|
id,
|
|
249
254
|
idLabel,
|
|
250
255
|
waitSeconds,
|
|
@@ -267,6 +272,7 @@ async function acquireRunLease({ root, platform, id, deviceName = null, idLabel,
|
|
|
267
272
|
const taken = takeLease({
|
|
268
273
|
root,
|
|
269
274
|
platform,
|
|
275
|
+
slot,
|
|
270
276
|
id,
|
|
271
277
|
deviceName,
|
|
272
278
|
kind: "run",
|
|
@@ -285,8 +291,8 @@ async function acquireRunLease({ root, platform, id, deviceName = null, idLabel,
|
|
|
285
291
|
}
|
|
286
292
|
//#endregion
|
|
287
293
|
//#region src/engine/device-pool.ts
|
|
288
|
-
function heldPoolId(root, platform, now, io = fileLeaseIo) {
|
|
289
|
-
const record = io.readHolder(root)[platform];
|
|
294
|
+
function heldPoolId(root, platform, now, io = fileLeaseIo, slot = "default") {
|
|
295
|
+
const record = io.readHolder(root)[deviceSlotKey(platform, slot)];
|
|
290
296
|
if (!record) return null;
|
|
291
297
|
const lease = parseLease(io.readLease(deviceLeasePath(platform, record.id)));
|
|
292
298
|
if (!lease || lease.token !== record.token || leaseIsExpired(lease, now)) return null;
|
|
@@ -352,8 +358,8 @@ function poolBusyRefusal(holders, leases, unreadable, now, waitSeconds) {
|
|
|
352
358
|
}
|
|
353
359
|
};
|
|
354
360
|
}
|
|
355
|
-
async function selectFromPool({ root, platform, idLabel, list, noCandidates, waitSeconds, deadline, noWait = false, now = Date.now, sleep = (ms) => new Promise((r) => setTimeout(r, ms)), warn = () => {}, io = fileLeaseIo }) {
|
|
356
|
-
const held = heldPoolId(root, platform, now(), io);
|
|
361
|
+
async function selectFromPool({ root, platform, slot = "default", idLabel, list, noCandidates, waitSeconds, deadline, noWait = false, now = Date.now, sleep = (ms) => new Promise((r) => setTimeout(r, ms)), warn = () => {}, io = fileLeaseIo }) {
|
|
362
|
+
const held = heldPoolId(root, platform, now(), io, slot);
|
|
357
363
|
const until = deadline ?? now() + waitSeconds * 1e3;
|
|
358
364
|
let lastLine = null;
|
|
359
365
|
for (;;) {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
2
|
-
import { k as withDirLock, u as getConfigDir } from "./config-
|
|
3
|
-
import { D as workspaceLogsDir, O as workspaceName, T as workspaceDir, a as clearRemoteSession, c as readMetroTunnel, k as workspaceStateFile, u as readRemoteSession } from "./state-
|
|
4
|
-
import { r as pidExists } from "./metro-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
1
|
+
import { t as getExecutor } from "./exec-CyylIdq9.mjs";
|
|
2
|
+
import { k as withDirLock, u as getConfigDir } from "./config-CcefMY2Q.mjs";
|
|
3
|
+
import { D as workspaceLogsDir, O as workspaceName, T as workspaceDir, a as clearRemoteSession, c as readMetroTunnel, k as workspaceStateFile, u as readRemoteSession } from "./state-B3XA2wp2.mjs";
|
|
4
|
+
import { r as pidExists } from "./metro-CORqXyTL.mjs";
|
|
5
|
+
import { z as planMetroReach } from "./settings-DEJf6_kJ.mjs";
|
|
6
|
+
import { t as withWorkspaceProcessLock } from "./workspace-process-lock-3NcQnZ0X.mjs";
|
|
7
|
+
import { T as readMetroRecords, a as LAUNCH_ERROR, b as isBundleProof, p as devClientDeepLink, r as INSTALL_ERROR } from "./app-install-DIp9riNx.mjs";
|
|
8
|
+
import { S as sanitizeDeviceLabel } from "./ios-Deh5js5V.mjs";
|
|
9
9
|
import { existsSync, mkdirSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
10
10
|
import { dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
11
11
|
import { homedir } from "node:os";
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
2
|
-
import { g as loadConfig, l as getConcurrencyLimits, o as configCorruptRepair } from "./config-
|
|
3
|
-
import { b as sharedBuildCache, w as workspaceDerivedData } from "./state-
|
|
4
|
-
import { S as makeTemporaryDirectory, a as dirtyFingerprintFiles, f as listWorktrees, g as repoRoot, s as gitCommonDir, w as temporaryRoot, x as filesystemDevice } from "./worktree-
|
|
5
|
-
import { i as detectIsExpo, t as appProjectProblem } from "./project-
|
|
6
|
-
import { d as resolveEasCliBin, i as checkEasAuth$1, l as ownerFromConfig, u as providerFromConfig, v as POOL_SETTING_REMEDY, x as parkedMaxSetting } from "./remote-cache-DOi5-zLj.mjs";
|
|
7
|
-
import { B as compilerCacheFallbackMessage, C as projectOptimizations, D as remoteIosSetting, F as unknownSettingKeys, H as resolveOptimizations, M as settingShapeErrors, N as settingsLayers, T as remoteAndroidSetting, a as SETTING_SHAPE_REMEDY, i as SETTINGS_WITH_RESOLVE_TIME_FALLBACK, j as settingOrigin, k as resolveSettings, n as PATH_SETTINGS, v as iosSimSlimProfileSetting, y as mergeSettingsLayers } from "./settings-BSwrY4FZ.mjs";
|
|
1
|
+
import { t as getExecutor } from "./exec-CyylIdq9.mjs";
|
|
2
|
+
import { g as loadConfig, l as getConcurrencyLimits, o as configCorruptRepair } from "./config-CcefMY2Q.mjs";
|
|
3
|
+
import { b as sharedBuildCache, w as workspaceDerivedData } from "./state-B3XA2wp2.mjs";
|
|
4
|
+
import { S as makeTemporaryDirectory, a as dirtyFingerprintFiles, f as listWorktrees, g as repoRoot, s as gitCommonDir, w as temporaryRoot, x as filesystemDevice } from "./worktree-Eq6TLH8N.mjs";
|
|
5
|
+
import { i as detectIsExpo, t as appProjectProblem } from "./project-fKmuIaMI.mjs";
|
|
8
6
|
import { d as quotedPath, u as plural } from "./command-output-8wHMEde0.mjs";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
7
|
+
import { B as listBuildLocks, Z as fingerprintProject, q as diffFingerprintSources, y as listAdbDevices } from "./android-BqVIJoG7.mjs";
|
|
8
|
+
import { A as resolveSettings, E as remoteAndroidSetting, I as unknownSettingKeys, M as settingOrigin, N as settingShapeErrors, O as remoteIosSetting, P as settingsLayers, U as resolveOptimizations, V as compilerCacheFallbackMessage, a as SETTING_SHAPE_REMEDY, i as SETTINGS_WITH_RESOLVE_TIME_FALLBACK, n as PATH_SETTINGS, v as iosSimSlimProfileSetting, w as projectOptimizations, y as mergeSettingsLayers } from "./settings-DEJf6_kJ.mjs";
|
|
9
|
+
import { a as POOL_SETTING_REMEDY, b as providerFromConfig, c as parkedMaxSetting, m as checkEasAuth$1, x as resolveEasCliBin, y as ownerFromConfig } from "./teardown-ClFp1Aax.mjs";
|
|
10
|
+
import { E as readHostMemoryPressure, T as hostMemoryPressureAdvice, u as listAllIosSims } from "./ios-Deh5js5V.mjs";
|
|
11
|
+
import { n as listBuildSlots } from "./build-slots-C3-R4XQr.mjs";
|
|
12
|
+
import { E as simslimIsOnPath, S as liveOwnedDeviceCount, a as ccacheEnabled, g as podInstallCommand } from "./xcode-D7sAp-Zy.mjs";
|
|
13
|
+
import { d as projectCmakeLauncher, i as apkOutputsDir, r as resolveAndroidCompilerCache, t as readAndroidCasToolchain } from "./android-cas-BR5YJBYv.mjs";
|
|
15
14
|
import { existsSync, lstatSync, readFileSync, readdirSync, realpathSync, rmSync } from "node:fs";
|
|
16
15
|
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
17
16
|
import { existsSync as existsSync$1, lstatSync as lstatSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, realpathSync as realpathSync$1, rmSync as rmSync$1 } from "fs";
|
|
@@ -699,15 +698,6 @@ function checkMainCheckout(projectRoot, { npmTreeValid, brokenPods = void 0, ups
|
|
|
699
698
|
if (linkedWorktrees === void 0 ? hasLinkedWorktree(projectRoot) : linkedWorktrees) findings.push(...seedFindings(mainRoot, upstream === void 0 ? locallyKnownUpstream(mainRoot) : upstream));
|
|
700
699
|
return findings;
|
|
701
700
|
}
|
|
702
|
-
function checkDevClient(pkg, isExpo = true) {
|
|
703
|
-
const deps = {
|
|
704
|
-
...pkg?.dependencies,
|
|
705
|
-
...pkg?.devDependencies
|
|
706
|
-
};
|
|
707
|
-
if (deps["expo-dev-client"]) return null;
|
|
708
|
-
if (!isExpo || !deps.expo) return null;
|
|
709
|
-
return finding("cost", "expo-dev-client is not installed", "A Metro port reserved by Stim cannot reach the app without it: the port travels in the dev-client deep link `stim ios` opens, and without the dev client nothing handles that URL. The app falls back to port 8081 and shows \"No script URL provided\".", "npx expo install expo-dev-client, then rebuild with `stim ios` / `stim android`. It is a NATIVE dependency: an app already on the device will not pick it up, and the first build after installing it is a cache miss by design because the native fingerprint moved. Do not solve this by compiling the port in (RCT_METRO_PORT, or the dev client defaultLaunchURL) -- the build cache does not key on the port, so a binary built for one workspace would silently talk to another workspace bundler.");
|
|
710
|
-
}
|
|
711
701
|
function checkMetroCache(metroConfigSource) {
|
|
712
702
|
if (metroConfigSource == null) return null;
|
|
713
703
|
const lines = String(metroConfigSource).split("\n");
|
|
@@ -811,10 +801,11 @@ function checkRemoteDevice({ configured = null, daemonInEnv = false, agentDevice
|
|
|
811
801
|
}
|
|
812
802
|
function checkSimSlim({ configured = false, profileError = null, onPath = false } = {}) {
|
|
813
803
|
if (profileError) return finding("cost", "The SimSlim profile is invalid", profileError, "Set ios.simslimProfile to a readable JSON profile inside the repository.");
|
|
814
|
-
if (!configured
|
|
804
|
+
if (!configured) return finding("note", "SimSlim is recommended for parallel iOS simulator work", "A reviewed profile can reduce background simulator services and memory use. It is optional: disabling services can affect tests that depend on them, and installing the binary alone does not apply a profile.", "Run `stim guide lifecycle simslim` to install SimSlim and configure ios.simslimProfile. Stim does not enable a profile through doctor --fix.");
|
|
805
|
+
if (onPath) return null;
|
|
815
806
|
return finding("cost", "A SimSlim profile is configured, but SimSlim is not installed", "`stim ios` needs the `simslim` command to apply the profile to its owned simulator.", "brew install mobai-app/tap/simslim");
|
|
816
807
|
}
|
|
817
|
-
function runDoctor(projectRoot, { readFile = readFileSync$1, xcodeMajor = null, easAuth = checkEasAuth$1, concurrency = getConcurrencyLimits, liveDevices = null, activeBuilds = null, remoteEnv = process.env, lookupAgentDevice = null, lookupEasCli = null, lookupSimSlim = null, lookupCcache = null, platform } = {}) {
|
|
808
|
+
function runDoctor(projectRoot, { readFile = readFileSync$1, xcodeMajor = null, easAuth = checkEasAuth$1, concurrency = getConcurrencyLimits, liveDevices = null, activeBuilds = null, remoteEnv = process.env, lookupAgentDevice = null, lookupEasCli = null, lookupSimSlim = null, memoryPressure = readHostMemoryPressure, lookupCcache = null, platform } = {}) {
|
|
818
809
|
const read = (rel) => {
|
|
819
810
|
const p = join$1(projectRoot, rel);
|
|
820
811
|
if (!existsSync$1(p)) return null;
|
|
@@ -886,7 +877,7 @@ function runDoctor(projectRoot, { readFile = readFileSync$1, xcodeMajor = null,
|
|
|
886
877
|
} catch (error) {
|
|
887
878
|
simslimProfileError = String(error?.message || error);
|
|
888
879
|
}
|
|
889
|
-
const simslimFinding = platform === "android" ? null : checkSimSlim({
|
|
880
|
+
const simslimFinding = platform === "android" || !simslimProfile && !simslimProfileError && remoteIosSetting(projectSettings) ? null : checkSimSlim({
|
|
890
881
|
configured: Boolean(simslimProfile),
|
|
891
882
|
profileError: simslimProfileError,
|
|
892
883
|
onPath: simslimProfile ? lookupSimSlim ? lookupSimSlim() : simslimIsOnPath() : false
|
|
@@ -901,12 +892,12 @@ function runDoctor(projectRoot, { readFile = readFileSync$1, xcodeMajor = null,
|
|
|
901
892
|
agentDeviceOnPath,
|
|
902
893
|
easCliResolvable
|
|
903
894
|
})).filter((remoteFinding) => remoteFinding !== null);
|
|
895
|
+
const memoryAdvice = platform !== "android" && !remoteIosSetting(projectSettings) ? hostMemoryPressureAdvice(memoryPressure()) : null;
|
|
904
896
|
return [
|
|
905
897
|
checkAppProject(projectRoot),
|
|
906
898
|
...checkMainCheckout(projectRoot, { platform }),
|
|
907
899
|
...platform === "android" ? [] : inspectIosDebugArchitectures(mainCheckoutProjectRoot(projectRoot)),
|
|
908
900
|
...checkStorageLayout(projectRoot, { platform }),
|
|
909
|
-
checkDevClient(pkg, isExpo),
|
|
910
901
|
optimizations?.metroSharedCache ? checkMetroCache(metroConfig) : null,
|
|
911
902
|
platform === "android" || !optimizations?.ios.compilationCache ? null : checkCompilationCache(podfile, xcodeMajor),
|
|
912
903
|
platform === "android" || !optimizations?.ios.compilationCache ? null : checkCcacheConflict(podfile, podfileProperties),
|
|
@@ -914,6 +905,7 @@ function runDoctor(projectRoot, { readFile = readFileSync$1, xcodeMajor = null,
|
|
|
914
905
|
remoteBuildCache ? checkBuildCacheProvider(appConfig, sdkMajor, isExpo, dynamicConfig) : null,
|
|
915
906
|
easFinding,
|
|
916
907
|
concurrencyFinding,
|
|
908
|
+
memoryAdvice ? finding("cost", "Host memory pressure can stall the iOS simulator", memoryAdvice, "Free host memory, then retry. Run `stim guide lifecycle simslim` for the optional memory reduction setup.") : null,
|
|
917
909
|
simslimFinding,
|
|
918
910
|
...remoteFindings,
|
|
919
911
|
...settingShapeFindings,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
2
|
-
import { g as repoRoot } from "./worktree-
|
|
3
|
-
import { a as findProjectRoot } from "./project-
|
|
1
|
+
import { t as getExecutor } from "./exec-CyylIdq9.mjs";
|
|
2
|
+
import { g as repoRoot } from "./worktree-Eq6TLH8N.mjs";
|
|
3
|
+
import { a as findProjectRoot } from "./project-fKmuIaMI.mjs";
|
|
4
4
|
import { l as phaseLine } from "./command-output-8wHMEde0.mjs";
|
|
5
|
-
import { s as detectXcodeMajor } from "./xcode-
|
|
6
|
-
import { c as repairCxxLauncherState, n as detectFingerprintParity, r as detectLinkedLibraryGitMetadata, s as runDoctor } from "./doctor-
|
|
5
|
+
import { s as detectXcodeMajor } from "./xcode-D7sAp-Zy.mjs";
|
|
6
|
+
import { c as repairCxxLauncherState, n as detectFingerprintParity, r as detectLinkedLibraryGitMetadata, s as runDoctor } from "./doctor-Bmv86UUW.mjs";
|
|
7
7
|
import { accessSync, constants, realpathSync, statSync } from "node:fs";
|
|
8
8
|
import { InvalidArgumentError } from "commander";
|
|
9
9
|
import { delimiter, join, resolve } from "node:path";
|
|
@@ -209,7 +209,7 @@ function sandboxFinding(settingsRoot, { env = process.env, home = homedir(), sti
|
|
|
209
209
|
level: "cost",
|
|
210
210
|
title,
|
|
211
211
|
detail: `${symptoms} Missing: ${missing.join(", ")}.`,
|
|
212
|
-
fix: `Run \`stim doctor --fix\` to
|
|
212
|
+
fix: `Run \`stim doctor --fix\` to write sandbox.filesystem.allowWrite, sandbox.network.allowMachLookup, and sandbox.network.allowLocalBinding into ${paths[0]}, merged with what is there, or add the missing keys by hand. See \`stim guide errors sandbox\`.`
|
|
213
213
|
};
|
|
214
214
|
}
|
|
215
215
|
//#endregion
|
|
@@ -395,13 +395,13 @@ function doctorSuccessLines(platform, stim) {
|
|
|
395
395
|
];
|
|
396
396
|
if (platform !== "android") {
|
|
397
397
|
lines.push("", "iOS");
|
|
398
|
-
lines.push(phaseLine("setup", "CocoaPods, warm state,
|
|
398
|
+
lines.push(phaseLine("setup", "CocoaPods, warm state, effective Debug simulator architectures"));
|
|
399
399
|
lines.push(phaseLine("caches", "Metro, Xcode compilation, ccache, build provider"));
|
|
400
400
|
lines.push(phaseLine("devices", "remote device, SimSlim profile"));
|
|
401
401
|
}
|
|
402
402
|
if (platform !== "ios") {
|
|
403
403
|
lines.push("", "Android");
|
|
404
|
-
lines.push(phaseLine("setup", "warm state
|
|
404
|
+
lines.push(phaseLine("setup", "warm state"));
|
|
405
405
|
lines.push(phaseLine("caches", "Metro, Gradle, ccache, build provider"));
|
|
406
406
|
lines.push(phaseLine("devices", "remote device"));
|
|
407
407
|
}
|
|
@@ -464,7 +464,7 @@ function applySandboxFix(root, env = process.env) {
|
|
|
464
464
|
console.error(chalk.dim("Added writes to Stim's state directory, the simulator XPC service, and local port binding. Claude Code reads project settings from the directory a session starts in, so this file only counts for sessions rooted there. Restart the session for it to take effect."));
|
|
465
465
|
}
|
|
466
466
|
function doctorCommand(program, version, inspectVersions = inspectStimVersions) {
|
|
467
|
-
program.command("doctor").description("Inspect the source checkout and report project state that can make native worktrees slow or invalid. Read-only unless --fix is passed; --platform filters native findings.").option("--json", "print the findings as JSON").option("--platform <platform>", "report shared findings plus only this native platform: ios or android", parseDoctorPlatform).option("--fix", "repair the sandbox allowance and stale Android .cxx configurations in this checkout. Stop native builds first. Generated CMake output must be ignored and untracked; custom launcher settings and source files are preserved.").action(async (opts) => {
|
|
467
|
+
program.command("doctor").description("Inspect the source checkout and report project state that can make native worktrees slow or invalid. Read-only unless --fix is passed; --platform filters native findings.").option("--json", "print the findings as JSON").option("--platform <platform>", "report shared findings plus only this native platform: ios or android", parseDoctorPlatform).option("--fix", "repair the sandbox allowance when the report names it, and stale Android .cxx configurations in this checkout. Stop native builds first. Generated CMake output must be ignored and untracked; custom launcher settings and source files are preserved.").action(async (opts) => {
|
|
468
468
|
const root = findProjectRoot(process.cwd());
|
|
469
469
|
if (!root) {
|
|
470
470
|
console.error(chalk.red("Not in a React Native project (no package.json found)."));
|
|
@@ -472,7 +472,7 @@ function doctorCommand(program, version, inspectVersions = inspectStimVersions)
|
|
|
472
472
|
return;
|
|
473
473
|
}
|
|
474
474
|
if (opts.fix) {
|
|
475
|
-
if (
|
|
475
|
+
if (sandboxFinding(repoRoot(root) ?? root)) applySandboxFix(root);
|
|
476
476
|
if (opts.platform !== "ios") try {
|
|
477
477
|
const repair = repairCxxLauncherState(root);
|
|
478
478
|
for (const path of repair.removed) console.error(phaseLine("cache", `removed ${path}; next build reconfigures`));
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
2
|
-
import { f as getProject, k as withDirLock } from "./config-
|
|
3
|
-
import { f as readWorkspaceLaunches, p as readWorkspaceState } from "./state-
|
|
4
|
-
import { n as deviceConsoleLevel } from "./ios-device-
|
|
5
|
-
import { i as resolveProjectMetro } from "./metro-
|
|
6
|
-
import { n as parseLogcatLine, t as androidClockOffset } from "./android-
|
|
1
|
+
import { t as getExecutor } from "./exec-CyylIdq9.mjs";
|
|
2
|
+
import { I as deviceSlotKey, L as deviceSlotPlatforms, f as getProject, k as withDirLock } from "./config-CcefMY2Q.mjs";
|
|
3
|
+
import { f as readWorkspaceLaunches, p as readWorkspaceState } from "./state-B3XA2wp2.mjs";
|
|
4
|
+
import { n as deviceConsoleLevel } from "./ios-device-D3pzTKQE.mjs";
|
|
5
|
+
import { i as resolveProjectMetro } from "./metro-CORqXyTL.mjs";
|
|
6
|
+
import { n as parseLogcatLine, t as androidClockOffset } from "./android-BW8i_YxU.mjs";
|
|
7
7
|
import { _ as launchErrorPreview } from "./command-output-8wHMEde0.mjs";
|
|
8
|
-
import {
|
|
9
|
-
import { n as
|
|
10
|
-
import { c as readLogRecords, t as attachExpoErrorContext } from "./logs-query-
|
|
8
|
+
import { n as androidHome } from "./android-BqVIJoG7.mjs";
|
|
9
|
+
import { a as parseLease, n as fileLeaseIo, t as deviceLeasePath } from "./device-lease-BJYybF-2.mjs";
|
|
10
|
+
import { c as readLogRecords, t as attachExpoErrorContext } from "./logs-query-R-Cqc6Qv.mjs";
|
|
11
11
|
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
12
12
|
import { createHash, randomUUID } from "node:crypto";
|
|
13
13
|
import { basename, dirname, join, resolve, sep } from "node:path";
|
|
@@ -333,14 +333,18 @@ function captureNativeCrashes(target, logsDir) {
|
|
|
333
333
|
if (text) records = parseAndroidCrashes(text, target, offset).map((record) => symbolicateAndroid(record, target.root, deadline));
|
|
334
334
|
}
|
|
335
335
|
} catch {}
|
|
336
|
-
for (const record of records)
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
336
|
+
for (const record of records) {
|
|
337
|
+
if (target.slot && target.slot !== "default") record.slot = target.slot;
|
|
338
|
+
try {
|
|
339
|
+
const key = createHash("sha256").update(JSON.stringify([
|
|
340
|
+
record.slot,
|
|
341
|
+
record.deviceId,
|
|
342
|
+
record.incident ?? record.deviceTs,
|
|
343
|
+
record.rawReport
|
|
344
|
+
])).digest("hex");
|
|
345
|
+
writeDiagnosticOnce(join(logsDir, `native-crash-${key}.ndjson`), `${JSON.stringify(record)}\n`);
|
|
346
|
+
} catch {}
|
|
347
|
+
}
|
|
344
348
|
return records;
|
|
345
349
|
}
|
|
346
350
|
function printNativeCrashReport(target, logsDir, emit, remote) {
|
|
@@ -350,45 +354,51 @@ function printNativeCrashReport(target, logsDir, emit, remote) {
|
|
|
350
354
|
function captureWorkspaceCrashes(root, logsDir) {
|
|
351
355
|
const attempts = readLogRecords(logsDir).filter((record) => record.event === "launch_attempt");
|
|
352
356
|
const launches = readWorkspaceLaunches(root);
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
const
|
|
357
|
-
const
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
const
|
|
362
|
-
const
|
|
363
|
-
if (
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
if (
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
"
|
|
377
|
-
|
|
378
|
-
|
|
357
|
+
const latest = /* @__PURE__ */ new Map();
|
|
358
|
+
for (const attempt of attempts) if (attempt.platform === "ios" || attempt.platform === "android") latest.set(deviceSlotKey(attempt.platform, String(attempt.slot ?? "default")), attempt);
|
|
359
|
+
for (const [key, attempt] of latest) {
|
|
360
|
+
const platform = attempt.platform;
|
|
361
|
+
const slot = String(attempt.slot ?? "default");
|
|
362
|
+
try {
|
|
363
|
+
if (!attempt || attempt.remote) continue;
|
|
364
|
+
const { deviceId, appId } = attempt;
|
|
365
|
+
const since = attempt.ts;
|
|
366
|
+
const until = Date.now();
|
|
367
|
+
if (typeof deviceId !== "string" || typeof appId !== "string" || typeof since !== "number" || !Number.isFinite(since)) continue;
|
|
368
|
+
if (attempt.physical) {
|
|
369
|
+
const holder = fileLeaseIo.readHolder(root)[key];
|
|
370
|
+
const lease = parseLease(fileLeaseIo.readLease(deviceLeasePath(platform, deviceId)));
|
|
371
|
+
if (holder?.id !== deviceId || !lease || lease.platform !== platform || lease.id !== deviceId || lease.holder !== root || lease.token !== holder.token || Date.parse(lease.expiresAt) <= until || !lease.grantedAt || !Number.isFinite(Date.parse(lease.grantedAt)) || Date.parse(lease.grantedAt) > since) continue;
|
|
372
|
+
} else {
|
|
373
|
+
const launch = launches[key];
|
|
374
|
+
if (!launch || launch.deviceId !== deviceId || launch.appId !== appId || Date.parse(launch.launchedAt) !== since) continue;
|
|
375
|
+
const configured = deviceSlotPlatforms(getProject(root), slot)?.[platform];
|
|
376
|
+
if (!configured?.owned) continue;
|
|
377
|
+
if (platform === "ios" && configured.deviceUdid !== deviceId) continue;
|
|
378
|
+
if (platform === "android") {
|
|
379
|
+
if (!configured.avdName) continue;
|
|
380
|
+
if (getExecutor().runFileQuiet("adb", [
|
|
381
|
+
"-s",
|
|
382
|
+
deviceId,
|
|
383
|
+
"emu",
|
|
384
|
+
"avd",
|
|
385
|
+
"name"
|
|
386
|
+
], { timeoutMs: 2e3 })?.split("\n")[0]?.trim() !== configured.avdName) continue;
|
|
387
|
+
}
|
|
379
388
|
}
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
389
|
+
captureNativeCrashes({
|
|
390
|
+
root,
|
|
391
|
+
slot,
|
|
392
|
+
platform,
|
|
393
|
+
deviceId,
|
|
394
|
+
appId,
|
|
395
|
+
since: Number(since),
|
|
396
|
+
until,
|
|
397
|
+
physical: attempt?.physical === true,
|
|
398
|
+
appPath: attempt?.appPath ?? readWorkspaceState(root)?.lastBuild?.appPath
|
|
399
|
+
}, logsDir);
|
|
400
|
+
} catch {}
|
|
401
|
+
}
|
|
392
402
|
}
|
|
393
403
|
//#endregion
|
|
394
404
|
//#region src/error-symbolication.ts
|
|
@@ -2,7 +2,7 @@ import { execFileSync, execSync, spawn } from "child_process";
|
|
|
2
2
|
//#region src/exec.ts
|
|
3
3
|
const MAX_BUFFER = 67108864;
|
|
4
4
|
let active = {
|
|
5
|
-
run(cmd, { timeoutMs, cwd } = {}) {
|
|
5
|
+
run(cmd, { timeoutMs, killSignal, cwd } = {}) {
|
|
6
6
|
const opts = {
|
|
7
7
|
encoding: "utf-8",
|
|
8
8
|
stdio: [
|
|
@@ -13,10 +13,11 @@ let active = {
|
|
|
13
13
|
maxBuffer: MAX_BUFFER
|
|
14
14
|
};
|
|
15
15
|
if (timeoutMs) opts.timeout = timeoutMs;
|
|
16
|
+
if (killSignal) opts.killSignal = killSignal;
|
|
16
17
|
if (cwd) opts.cwd = cwd;
|
|
17
18
|
return String(execSync(cmd, opts)).trim();
|
|
18
19
|
},
|
|
19
|
-
runFile(file, args = [], { timeoutMs, cwd, env, omitEnv } = {}) {
|
|
20
|
+
runFile(file, args = [], { timeoutMs, killSignal, cwd, env, omitEnv } = {}) {
|
|
20
21
|
const opts = {
|
|
21
22
|
encoding: "utf-8",
|
|
22
23
|
stdio: [
|
|
@@ -27,6 +28,7 @@ let active = {
|
|
|
27
28
|
maxBuffer: MAX_BUFFER
|
|
28
29
|
};
|
|
29
30
|
if (timeoutMs) opts.timeout = timeoutMs;
|
|
31
|
+
if (killSignal) opts.killSignal = killSignal;
|
|
30
32
|
if (cwd) opts.cwd = cwd;
|
|
31
33
|
if (env || omitEnv?.length) {
|
|
32
34
|
const childEnv = {
|