stim 1.9.0 → 1.10.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/{android-_y4Ohi5z.mjs → android-787HhP5w.mjs} +119 -29
- package/dist/{android-BPGizezh.mjs → android-DBkeHwpm.mjs} +168 -95
- package/dist/{android-DEgo4oCo.mjs → android-DPov-fv2.mjs} +2 -2
- package/dist/{android-cas-eiExNLf7.mjs → android-cas-CITmIeWY.mjs} +9 -8
- package/dist/android-cas-compiler.mjs +1 -1
- package/dist/{app-install-Uf3a83Tv.mjs → app-install-CrJ6t_bv.mjs} +2 -2
- package/dist/budget-BP4jZZL4.mjs +620 -0
- package/dist/build-progress-BXx-ZBe4.mjs +512 -0
- package/dist/{cache-manifest-Dg7OnMrp.mjs → cache-manifest-Pubfp8wV.mjs} +1 -1
- package/dist/cache-manifest.mjs +1 -1
- package/dist/cli.mjs +16 -16
- package/dist/collector-run.d.mts +5 -1
- package/dist/collector-run.mjs +7 -7
- package/dist/{command-output-gByVmIjy.mjs → command-output-D5z2_bcF.mjs} +1 -1
- package/dist/{config-Cp9lM3wX.mjs → config-BEq0Qw_a.mjs} +14 -131
- package/dist/{dependency-state-Bq5DcLGn.mjs → dependency-state-r9UesA9a.mjs} +2 -2
- package/dist/{deps-Cip5vUm1.mjs → deps-DP4eWqea.mjs} +3 -3
- package/dist/{detached-entry-KEu0_AXL.mjs → detached-entry-DJHoca49.mjs} +1 -1
- package/dist/{dev-client-HyqISM0h.mjs → dev-client-92U593KT.mjs} +137 -250
- package/dist/{device-D4U-xLty.mjs → device-DhTZe7L4.mjs} +7 -7
- package/dist/{build-lock-DPXPLgTc.mjs → device-lease-CbEaIk7b.mjs} +370 -12
- package/dist/{device-pool-CnTAz8X1.mjs → device-pool-Di8Q-9Ro.mjs} +4 -4
- package/dist/{device-remote-AQ5rQPqr.mjs → device-remote-Dy1jGj3U.mjs} +547 -468
- package/dist/{doctor-B_Ei3bZu.mjs → doctor-B-inAJmt.mjs} +58 -22
- package/dist/{error-diagnostics-Vfz83GCF.mjs → error-diagnostics-xxWKNO3-.mjs} +11 -12
- package/dist/{exec-jIAlgilk.mjs → exec-DK8KaVHK.mjs} +3 -2
- package/dist/{gc-Ckw8RQHi.mjs → gc-ChPFZMRC.mjs} +500 -1114
- package/dist/{guide-BiAbhs1J.mjs → guide-DwmaD_Wa.mjs} +882 -528
- package/dist/guide-status-CWvti2Lg.mjs +125 -0
- package/dist/idle-DpRLp5lj.mjs +157 -0
- package/dist/in-use-CjUluqIX.mjs +245 -0
- package/dist/{ios-BL2NFckr.mjs → ios-B2Fpqvlb.mjs} +25 -59
- package/dist/{ios-BzUJWk1K.mjs → ios-Dd-hYJBh.mjs} +130 -89
- package/dist/{ios-device-DPsSm0v_.mjs → ios-device-BiOsSVzd.mjs} +1 -1
- package/dist/{ios-device-D972i9wf.mjs → ios-device-CtRdEVjx.mjs} +3 -3
- package/dist/{launch-verify-Q_OtW1Rf.mjs → launch-verify-CQS_Kg-C.mjs} +5 -5
- package/dist/{logs-CI9NQSK7.mjs → logs-MARIy6m9.mjs} +9 -9
- package/dist/{metro-DrLHaMn2.mjs → metro-BWLOJ_Wr.mjs} +116 -10
- package/dist/{named-ports-CmLQSIRj.mjs → named-ports-DiTfSz6p.mjs} +4 -4
- package/dist/{ndjson-9uFNRwfe.mjs → ndjson-CDY9IkVC.mjs} +3 -56
- package/dist/{ndjson-DvHSsNU9.d.mts → ndjson-Du3j0AQ9.d.mts} +1 -0
- package/dist/{ownership-D15Op8vN.mjs → ownership-D2xbLVoz.mjs} +2 -3
- package/dist/ownership-DZjdx8Gq.mjs +1180 -0
- package/dist/{ports-BNKoWVWZ.mjs → ports-CLSSFOuz.mjs} +3 -3
- package/dist/{project-DS112DYB.mjs → project-BXZzOABt.mjs} +2 -2
- package/dist/{reload-ZNJUo1pl.mjs → reload-DoETJ3rl.mjs} +9 -10
- package/dist/{server-bare-DWkkcIxV.mjs → server-bare-DVbb7kXH.mjs} +1 -1
- package/dist/{server-expo-B_lctBR3.mjs → server-expo-BvOCeakp.mjs} +4 -4
- package/dist/server-expo-DBVTdult.mjs +2 -0
- package/dist/{settings-D030k0t4.mjs → settings-DOugPlPz.mjs} +16 -428
- package/dist/{settings-BKNh5rl4.mjs → settings-EWYNwe72.mjs} +16 -14
- package/dist/settings.schema.json +75 -0
- package/dist/{simslim-B_LsGLuJ.mjs → simslim-Ca3487H6.mjs} +182 -5
- package/dist/{slot-launch-DU9A-gYw.mjs → slot-launch-C5cg0fmk.mjs} +4 -4
- package/dist/{spawn-claims-Dn3C_N6w.mjs → spawn-claims-CUleC2cM.mjs} +1 -1
- package/dist/{start-DYkkKF0s.mjs → start-F9gv5dcC.mjs} +147 -98
- package/dist/start-VoFsPSes.mjs +2 -0
- package/dist/{state-NcJzMEBF.mjs → state-WGdIbi_d.mjs} +2 -2
- package/dist/{stats-DG9e66Rz.mjs → stats-BAgJaLA4.mjs} +1 -1
- package/dist/{stats-B63-JVAY.mjs → stats-DBYJ5bxL.mjs} +4 -4
- package/dist/{status-S6ehL4Ui.mjs → status-DLCD-o3s.mjs} +63 -231
- package/dist/status-Dr4fRkym.mjs +216 -0
- package/dist/{guide-status-BAMVU0ZA.mjs → stim-installations-CINXy_su.mjs} +3 -124
- package/dist/{stop-BO28HGqF.mjs → stop-Dj4pfmyv.mjs} +22 -18
- package/dist/{stop-T1R-cZRz.mjs → stop-ZvOeTmKb.mjs} +2 -2
- package/dist/supervisor-run.d.mts +11 -2
- package/dist/supervisor-run.mjs +185 -17
- package/dist/{workspace-process-lock-DWaiRD0e.mjs → workspace-process-lock-BXA96myD.mjs} +2 -2
- package/dist/workspaces-BTUyFfkv.mjs +1003 -0
- package/dist/{worktree-DKhSF0UX.mjs → worktree-4aZg2NnI.mjs} +1 -1
- package/dist/{worktree-LGB-UwgG.mjs → worktree-BMS7GeqB.mjs} +40 -122
- package/dist/{worktree-R_cUlE7s.mjs → worktree-BlizKDpZ.mjs} +143 -18
- package/dist/{xcode-BZqyxh3e.mjs → xcode-B2tBkf0m.mjs} +9 -158
- package/package.json +6 -5
- package/dist/build-progress-CVqkfPC6.mjs +0 -188
- package/dist/device-lease-Crs-HkJY.mjs +0 -366
- package/dist/logs-query-Cqma3WIu.mjs +0 -298
- package/dist/ownership-DCQPuWEc.mjs +0 -489
- package/dist/public-http-probe-CyMDrQ3c.mjs +0 -61
- package/dist/server-expo-CeILEu86.mjs +0 -2
- package/dist/sim-pool-KaIsp2Ft.mjs +0 -723
- package/dist/spawn-entry-nCE6m770.mjs +0 -14
- package/dist/workspace-state-DF2gCFhx.mjs +0 -169
|
@@ -1,26 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as getExecutor } from "./exec-
|
|
3
|
-
import { a as parseNdjsonLine } from "./ndjson-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { l as projectShortcut, o as findProjectRoot } from "./project-
|
|
7
|
-
import { l as readRemoteSession } from "./state-
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { i as
|
|
15
|
-
import { a as statsProjectKey, r as readStats } from "./stats-
|
|
16
|
-
import {
|
|
17
|
-
import { d as recordMatches, l as queryLogs, s as logFiles, t as ERROR_SOURCES } from "./logs-query-Cqma3WIu.mjs";
|
|
18
|
-
import { t as resolveSupervisorTarget } from "./ownership-DCQPuWEc.mjs";
|
|
19
|
-
import { i as readSupervisorState } from "./stop-BO28HGqF.mjs";
|
|
1
|
+
import { F as volumeRootFor, H as projectDeviceSlots, g as loadConfig$1, u as getConfigDir } from "./config-BEq0Qw_a.mjs";
|
|
2
|
+
import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
|
|
3
|
+
import { a as parseNdjsonLine } from "./ndjson-CDY9IkVC.mjs";
|
|
4
|
+
import { A as workspaceLogErrorIndex, a as processCwd, j as workspaceLogsDir, l as isMetroRunning, m as readWorkspaceState$1, n as listeningPids, o as processCwds, r as listeningPidsByPort, s as resolveProjectMetro } from "./metro-BWLOJ_Wr.mjs";
|
|
5
|
+
import { c as gitCommonDirOnDisk, p as linkedWorktreesOnDisk, s as gitCommonDir, y as repoRoot } from "./worktree-BlizKDpZ.mjs";
|
|
6
|
+
import { l as projectShortcut, o as findProjectRoot } from "./project-BXZzOABt.mjs";
|
|
7
|
+
import { l as readRemoteSession } from "./state-WGdIbi_d.mjs";
|
|
8
|
+
import { i as listLeaseFiles } from "./device-lease-CbEaIk7b.mjs";
|
|
9
|
+
import { a as buildStatusLine, c as createActivityReader, i as buildReport, o as parseActiveBuild, r as activeBuildState, t as ACTIVE_BUILD_KEY } from "./build-progress-BXx-ZBe4.mjs";
|
|
10
|
+
import { N as ownedAvdSerialResolver, c as androidToolPath } from "./android-787HhP5w.mjs";
|
|
11
|
+
import { b as readParked, h as POOL_SETTING_REMEDY, t as resolveSupervisorTarget, y as parkedMaxSetting } from "./ownership-DZjdx8Gq.mjs";
|
|
12
|
+
import { _ as parseSimctlList, u as listAllIosSimsAsync } from "./ios-B2Fpqvlb.mjs";
|
|
13
|
+
import { m as readEasSessionLedger$1, p as easMachineStateRoot$1 } from "./device-remote-Dy1jGj3U.mjs";
|
|
14
|
+
import { a as diskLine, c as parseDfFree, d as remoteDeviceState, f as tightVolumes, i as deviceLeaseStates, l as poolLine, n as capacity, o as environmentState, p as unprovisionedWorktrees, r as deviceLeaseLines, t as activityLabel, u as remoteDeviceLine } from "./status-Dr4fRkym.mjs";
|
|
15
|
+
import { a as statsProjectKey, r as readStats } from "./stats-BAgJaLA4.mjs";
|
|
16
|
+
import { i as readSupervisorState } from "./stop-Dj4pfmyv.mjs";
|
|
20
17
|
import { readdirSync, watch } from "node:fs";
|
|
21
|
-
import { closeSync as closeSync$1, existsSync as existsSync$1, fstatSync, openSync as openSync$1, readFileSync as readFileSync$1, readSync as readSync$1, renameSync as renameSync$1, rmSync as rmSync$1, writeFileSync as writeFileSync$1 } from "fs";
|
|
22
|
-
import { join } from "path";
|
|
18
|
+
import { closeSync as closeSync$1, existsSync as existsSync$1, fstatSync as fstatSync$1, openSync as openSync$1, readFileSync as readFileSync$1, readSync as readSync$1, renameSync as renameSync$1, rmSync as rmSync$1, writeFileSync as writeFileSync$1 } from "fs";
|
|
19
|
+
import { basename, dirname, join } from "path";
|
|
23
20
|
import { rotatedLogPath } from "@stim-cli/core";
|
|
21
|
+
import { ERROR_SOURCES, logFiles, queryLogs, readIdleStop, recordMatches } from "@stim-cli/core/state";
|
|
24
22
|
import { join as join$1 } from "node:path";
|
|
25
23
|
import { totalmem } from "os";
|
|
26
24
|
import chalk from "chalk";
|
|
@@ -106,7 +104,7 @@ function watchStatusSources({ home, onChange, platform = process.platform, simct
|
|
|
106
104
|
[home, "home"],
|
|
107
105
|
[join$1(home, "workspaces"), "workspaces"],
|
|
108
106
|
[join$1(home, "device-locks"), "leases"],
|
|
109
|
-
[easMachineStateRoot(), "eas"]
|
|
107
|
+
[easMachineStateRoot$1(), "eas"]
|
|
110
108
|
]);
|
|
111
109
|
let names = [];
|
|
112
110
|
try {
|
|
@@ -289,7 +287,7 @@ function summarize(path, known) {
|
|
|
289
287
|
return null;
|
|
290
288
|
}
|
|
291
289
|
try {
|
|
292
|
-
const { dev, ino, size } = fstatSync(fd);
|
|
290
|
+
const { dev, ino, size } = fstatSync$1(fd);
|
|
293
291
|
const key = `${dev}:${ino}`;
|
|
294
292
|
const cached = known[key];
|
|
295
293
|
const base = cached && stillExtends(fd, cached, size) ? cached : null;
|
|
@@ -408,203 +406,6 @@ function writeIndex(file, index) {
|
|
|
408
406
|
}
|
|
409
407
|
}
|
|
410
408
|
//#endregion
|
|
411
|
-
//#region src/status.ts
|
|
412
|
-
const IOS_SIM_MB = 1500;
|
|
413
|
-
const ANDROID_EMULATOR_MB = 2500;
|
|
414
|
-
const METRO_MB = 700;
|
|
415
|
-
function remoteDeviceState(record, ledger, root) {
|
|
416
|
-
if (!record) return null;
|
|
417
|
-
const claim = ledger.claims.get(record.sessionId);
|
|
418
|
-
return {
|
|
419
|
-
platform: record.platform,
|
|
420
|
-
backend: "eas",
|
|
421
|
-
sessionId: record.sessionId,
|
|
422
|
-
state: !ledger.safe ? "unknown" : claim?.workspaceRoot === root ? "claimed" : "unclaimed",
|
|
423
|
-
startedAt: record.startedAt,
|
|
424
|
-
webPreviewUrl: record.webPreviewUrl
|
|
425
|
-
};
|
|
426
|
-
}
|
|
427
|
-
function poolLine({ platform, parked, max }) {
|
|
428
|
-
if (parked <= 0) return null;
|
|
429
|
-
const what = plural(parked, `parked ${platform === "ios" ? "iOS simulator" : "Android emulator"}`);
|
|
430
|
-
return max > 0 ? `pool: ${what} (max ${max})` : `pool: ${what} (parking off; gc --delete removes them)`;
|
|
431
|
-
}
|
|
432
|
-
function environmentState(project, { simsByUdid = {}, metro = null, worktrees = [], simsAvailable = true, androidRuntime = null, androidRuntimes = {}, supervisor = null, logs = null, remote = null } = {}) {
|
|
433
|
-
const ios = project.platforms?.ios;
|
|
434
|
-
const android = project.platforms?.android;
|
|
435
|
-
const sim = ios ? simsByUdid[ios.deviceUdid] : null;
|
|
436
|
-
const simBooted = Boolean(sim && sim.state === "Booted");
|
|
437
|
-
const metroRunning = Boolean(metro?.metro);
|
|
438
|
-
const androidDetected = androidRuntime ? Boolean(androidRuntime.serial) : Boolean(android?.serial);
|
|
439
|
-
let live = simBooted || metroRunning || androidDetected || Boolean(remote);
|
|
440
|
-
let memoryMb = 0;
|
|
441
|
-
if (simBooted) memoryMb += IOS_SIM_MB;
|
|
442
|
-
if (androidDetected) memoryMb += ANDROID_EMULATOR_MB;
|
|
443
|
-
if (metroRunning) memoryMb += METRO_MB;
|
|
444
|
-
const warnings = [];
|
|
445
|
-
if (metro?.notOurs) warnings.push(`port ${project.metroPort}: ${metro.notOurs}`);
|
|
446
|
-
if (ios && !sim && simsAvailable) warnings.push(`recorded sim ${ios.deviceUdid} no longer exists`);
|
|
447
|
-
if (simBooted && project.metroPort && !metroRunning) warnings.push("simulator is booted with no Metro serving it");
|
|
448
|
-
if (androidRuntime && android?.avdName) {
|
|
449
|
-
const recordedSerial = android.consolePort ? `emulator-${android.consolePort}` : android.serial;
|
|
450
|
-
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}`);
|
|
451
|
-
if (androidRuntime.state === "missing") warnings.push(`recorded AVD ${android.avdName} no longer exists`);
|
|
452
|
-
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`);
|
|
453
|
-
if (androidRuntime.error) warnings.push(`could not check owned AVD ${android.avdName}: ${androidRuntime.error}`);
|
|
454
|
-
}
|
|
455
|
-
if (supervisor && supervisor.alive === false) warnings.push(`stale supervisor record for ${project.__path}`);
|
|
456
|
-
const slots = [];
|
|
457
|
-
for (const { slot, platforms } of projectDeviceSlots(project).slice(1)) {
|
|
458
|
-
const deviceState = environmentState({
|
|
459
|
-
...project,
|
|
460
|
-
platforms,
|
|
461
|
-
deviceSlots: void 0
|
|
462
|
-
}, {
|
|
463
|
-
simsByUdid,
|
|
464
|
-
simsAvailable,
|
|
465
|
-
metro,
|
|
466
|
-
androidRuntime: androidRuntimes[slot]
|
|
467
|
-
});
|
|
468
|
-
slots.push({
|
|
469
|
-
slot,
|
|
470
|
-
ios: deviceState.ios,
|
|
471
|
-
android: deviceState.android
|
|
472
|
-
});
|
|
473
|
-
memoryMb += deviceState.memoryMb - (metroRunning ? METRO_MB : 0);
|
|
474
|
-
live ||= deviceState.live;
|
|
475
|
-
warnings.push(...deviceState.warnings.map((warning) => `${slot}: ${warning}`));
|
|
476
|
-
}
|
|
477
|
-
return {
|
|
478
|
-
path: project.__path,
|
|
479
|
-
...slots.length ? { slots } : {},
|
|
480
|
-
live,
|
|
481
|
-
memoryMb,
|
|
482
|
-
warnings,
|
|
483
|
-
ios: ios ? {
|
|
484
|
-
name: sim?.name ?? null,
|
|
485
|
-
udid: ios.deviceUdid,
|
|
486
|
-
owned: Boolean(ios.owned),
|
|
487
|
-
state: sim?.state ?? (simsAvailable ? "missing" : "unknown")
|
|
488
|
-
} : null,
|
|
489
|
-
android: android ? {
|
|
490
|
-
name: android.avdName ?? android.serial,
|
|
491
|
-
owned: Boolean(android.owned),
|
|
492
|
-
physical: Boolean(android.serial && !android.avdName),
|
|
493
|
-
...androidRuntime ? {
|
|
494
|
-
serial: androidRuntime.serial,
|
|
495
|
-
state: androidRuntime.state
|
|
496
|
-
} : {}
|
|
497
|
-
} : null,
|
|
498
|
-
metro: project.metroPort ? {
|
|
499
|
-
port: project.metroPort,
|
|
500
|
-
running: metroRunning,
|
|
501
|
-
pid: metro?.metro?.pid ?? null
|
|
502
|
-
} : null,
|
|
503
|
-
supervisor: supervisor ? {
|
|
504
|
-
pid: supervisor.pid ?? null,
|
|
505
|
-
mode: supervisor.mode ?? null,
|
|
506
|
-
startedAt: supervisor.startedAt ?? null,
|
|
507
|
-
healthy: Boolean(supervisor.healthy)
|
|
508
|
-
} : null,
|
|
509
|
-
logs: logs ? {
|
|
510
|
-
dir: logs.dir,
|
|
511
|
-
errorsSinceMarker: logs.errorsSinceMarker ?? 0
|
|
512
|
-
} : null,
|
|
513
|
-
worktree: worktrees.find((w) => w.path === project.__path) ?? null,
|
|
514
|
-
remoteDevices: remote ? [remote] : []
|
|
515
|
-
};
|
|
516
|
-
}
|
|
517
|
-
function remoteDeviceLine(remote) {
|
|
518
|
-
const claim = remote.state === "claimed" ? "" : ` (${remote.state})`;
|
|
519
|
-
const watch = remote.webPreviewUrl ? ` -- watch: ${remote.webPreviewUrl}` : "";
|
|
520
|
-
return `remote ${remote.platform ?? "?"}: EAS session ${remote.sessionId} billable${claim}${watch}`;
|
|
521
|
-
}
|
|
522
|
-
function capacity(states, totalMemoryMb) {
|
|
523
|
-
const committedMb = states.reduce((n, s) => n + s.memoryMb, 0);
|
|
524
|
-
return {
|
|
525
|
-
liveCount: states.filter((s) => s.live).length,
|
|
526
|
-
committedMb,
|
|
527
|
-
totalMemoryMb,
|
|
528
|
-
overCapacity: Boolean(totalMemoryMb && committedMb > totalMemoryMb * .6)
|
|
529
|
-
};
|
|
530
|
-
}
|
|
531
|
-
function parseDfFree(output) {
|
|
532
|
-
const lines = String(output || "").trim().split("\n");
|
|
533
|
-
if (lines.length < 2) return null;
|
|
534
|
-
const lastLine = lines[lines.length - 1];
|
|
535
|
-
if (lastLine === void 0) return null;
|
|
536
|
-
const m = /\s(\d+)\s+(\d+)\s+(\d+)\s+(\d+)%/.exec(lastLine);
|
|
537
|
-
if (!m) return null;
|
|
538
|
-
const totalKb = Number(m[1]);
|
|
539
|
-
const availableKb = Number(m[3]);
|
|
540
|
-
if (!Number.isFinite(totalKb) || !Number.isFinite(availableKb) || totalKb <= 0) return null;
|
|
541
|
-
return {
|
|
542
|
-
availableMb: Math.round(availableKb / 1024),
|
|
543
|
-
totalMb: Math.round(totalKb / 1024)
|
|
544
|
-
};
|
|
545
|
-
}
|
|
546
|
-
function diskIsTight(disk) {
|
|
547
|
-
return Boolean(disk && disk.availableMb < 25600);
|
|
548
|
-
}
|
|
549
|
-
function formatSpace(mb) {
|
|
550
|
-
if (!Number.isFinite(mb)) return "?";
|
|
551
|
-
if (mb >= 1048576) return `${(mb / 1048576).toFixed(1)} TB`;
|
|
552
|
-
if (mb >= 1024) return `${Math.round(mb / 1024)} GB`;
|
|
553
|
-
return `${Math.round(mb)} MB`;
|
|
554
|
-
}
|
|
555
|
-
function diskLine(volumes) {
|
|
556
|
-
const usable = (volumes || []).filter((v) => Boolean(v && v.disk));
|
|
557
|
-
if (usable.length === 0) return null;
|
|
558
|
-
if (usable.length === 1) {
|
|
559
|
-
const first = usable[0];
|
|
560
|
-
if (!first) return null;
|
|
561
|
-
const { disk } = first;
|
|
562
|
-
return `${formatSpace(disk.availableMb)} free of ${formatSpace(disk.totalMb)} on disk.`;
|
|
563
|
-
}
|
|
564
|
-
return `${usable.map((v) => `${formatSpace(v.disk.availableMb)} free on ${v.volume}`).join(", ")}.`;
|
|
565
|
-
}
|
|
566
|
-
function tightVolumes(volumes) {
|
|
567
|
-
return (volumes || []).filter((v) => v && diskIsTight(v.disk));
|
|
568
|
-
}
|
|
569
|
-
function unprovisionedWorktrees(worktrees, projectPaths) {
|
|
570
|
-
const known = new Set(projectPaths);
|
|
571
|
-
return worktrees.filter((w) => !known.has(w.path));
|
|
572
|
-
}
|
|
573
|
-
function deviceLeaseStates(entries, { root, now }) {
|
|
574
|
-
return entries.map((entry) => {
|
|
575
|
-
const lease = entry.lease;
|
|
576
|
-
return {
|
|
577
|
-
path: entry.path,
|
|
578
|
-
platform: entry.platform,
|
|
579
|
-
...lease?.slot ? { slot: lease.slot } : {},
|
|
580
|
-
id: entry.id,
|
|
581
|
-
deviceName: lease?.deviceName ?? null,
|
|
582
|
-
holder: lease?.holder ?? null,
|
|
583
|
-
grantedAt: lease?.grantedAt ?? null,
|
|
584
|
-
expiresAt: lease?.expiresAt ?? null,
|
|
585
|
-
mine: Boolean(lease && root && lease.holder === root),
|
|
586
|
-
expired: Boolean(lease && Date.parse(lease.expiresAt) <= now),
|
|
587
|
-
parsed: Boolean(lease)
|
|
588
|
-
};
|
|
589
|
-
});
|
|
590
|
-
}
|
|
591
|
-
function deviceLeaseLines(states, now) {
|
|
592
|
-
if (states.length === 0) return [];
|
|
593
|
-
const lines = [`Device leases (${states.length}):`];
|
|
594
|
-
for (const state of states) {
|
|
595
|
-
const device = `${state.platform}${state.slot ? ` [${state.slot}]` : ""} ${state.id ?? state.path}${state.deviceName ? ` (${state.deviceName})` : ""}`;
|
|
596
|
-
if (!state.parsed || state.expiresAt === null) {
|
|
597
|
-
lines.push(` ${device} -- unreadable lease file, so nothing may take the device: ${state.path}`);
|
|
598
|
-
continue;
|
|
599
|
-
}
|
|
600
|
-
const when = clockTime(state.expiresAt);
|
|
601
|
-
const remaining = Date.parse(state.expiresAt) - now;
|
|
602
|
-
const expiry = state.expired ? `expired at ${when}` : `until ${when} (${formatElapsed(remaining)} left)`;
|
|
603
|
-
lines.push(` ${device} -- ${state.holder} ${expiry}${state.mine ? " [this workspace]" : ""}`);
|
|
604
|
-
}
|
|
605
|
-
return lines;
|
|
606
|
-
}
|
|
607
|
-
//#endregion
|
|
608
409
|
//#region src/commands/status.ts
|
|
609
410
|
function formatGb(mb) {
|
|
610
411
|
return `${(mb / 1024).toFixed(1)} GB`;
|
|
@@ -617,7 +418,7 @@ function statusCommand(program) {
|
|
|
617
418
|
}
|
|
618
419
|
async function statusLines(json) {
|
|
619
420
|
const out = [];
|
|
620
|
-
const cfg = loadConfig();
|
|
421
|
+
const cfg = loadConfig$1();
|
|
621
422
|
const projects = Object.entries(cfg?.projects || {});
|
|
622
423
|
const cwdRoot = findProjectRoot(process.cwd());
|
|
623
424
|
const simsRead = listAllIosSimsAsync();
|
|
@@ -631,9 +432,6 @@ async function statusLines(json) {
|
|
|
631
432
|
};
|
|
632
433
|
}));
|
|
633
434
|
processes.catch(() => {});
|
|
634
|
-
const source = resolveSourceCheckout(process.cwd());
|
|
635
|
-
const sourcePath = "path" in source ? source.path : null;
|
|
636
|
-
const worktrees = source.entries.filter((entry) => !entry.bare && entry.path !== sourcePath);
|
|
637
435
|
const androidRuntimeOf = androidRuntimeReader();
|
|
638
436
|
const devices = projects.map(([, proj]) => ({
|
|
639
437
|
androidRuntimes: Object.fromEntries(projectDeviceSlots(proj).slice(1).map(({ slot, platforms }) => [slot, platforms.android?.owned && platforms.android.avdName ? androidRuntimeOf(platforms.android.avdName) : null])),
|
|
@@ -650,10 +448,11 @@ async function statusLines(json) {
|
|
|
650
448
|
simctlError = String(e?.message || e).split("\n")[0] ?? "";
|
|
651
449
|
}
|
|
652
450
|
const running = await processes;
|
|
451
|
+
const worktrees = linkedWorktrees([process.cwd(), ...projects.map(([path]) => path)]);
|
|
653
452
|
const history = readStats().record?.history;
|
|
654
453
|
const states = [];
|
|
655
454
|
const labelOnlyRoots = [];
|
|
656
|
-
const easLedger = readEasSessionLedger();
|
|
455
|
+
const easLedger = readEasSessionLedger$1();
|
|
657
456
|
for (const [i, [path, proj]] of projects.entries()) {
|
|
658
457
|
const { metro, supervisor } = running[i];
|
|
659
458
|
states.push(environmentState({
|
|
@@ -667,18 +466,41 @@ async function statusLines(json) {
|
|
|
667
466
|
...devices[i],
|
|
668
467
|
supervisor,
|
|
669
468
|
logs: logs[i],
|
|
670
|
-
remote: remoteDeviceState(readRemoteSession(path), easLedger, path)
|
|
469
|
+
remote: remoteDeviceState(readRemoteSession(path), easLedger, path),
|
|
470
|
+
idleStop: readIdleStop(readWorkspaceState$1(path))
|
|
671
471
|
}));
|
|
672
472
|
const state = states[states.length - 1];
|
|
673
473
|
if (state) state.build = workspaceBuild(path, history);
|
|
674
474
|
labelOnlyRoots.push(Boolean(proj.worktreeRoot && !proj.bundleId && !state?.metro && !state?.ios && !state?.android));
|
|
675
475
|
}
|
|
476
|
+
const readActivity = createActivityReader();
|
|
477
|
+
for (const state of states) for (const device of [{
|
|
478
|
+
slot: "default",
|
|
479
|
+
ios: state.ios,
|
|
480
|
+
android: state.android
|
|
481
|
+
}, ...state.slots ?? []]) {
|
|
482
|
+
const base = {
|
|
483
|
+
slot: device.slot,
|
|
484
|
+
workspace: state.path
|
|
485
|
+
};
|
|
486
|
+
if (device.ios?.state === "Booted") device.ios.activity = readActivity({
|
|
487
|
+
...base,
|
|
488
|
+
platform: "ios",
|
|
489
|
+
id: device.ios.udid
|
|
490
|
+
});
|
|
491
|
+
if (device.android && !device.android.physical && device.android.serial) device.android.activity = readActivity({
|
|
492
|
+
...base,
|
|
493
|
+
platform: "android",
|
|
494
|
+
id: device.android.serial
|
|
495
|
+
});
|
|
496
|
+
}
|
|
676
497
|
const leaseNow = Date.now();
|
|
677
498
|
const leases = deviceLeaseStates(listLeaseFiles(), {
|
|
678
499
|
root: cwdRoot,
|
|
679
500
|
now: leaseNow
|
|
680
501
|
});
|
|
681
|
-
const
|
|
502
|
+
const totalMemoryMb = Math.round(totalmem() / 1048576);
|
|
503
|
+
const cap = capacity(states, totalMemoryMb);
|
|
682
504
|
const orphanWorktrees = unprovisionedWorktrees(worktrees, projects.map(([p]) => p));
|
|
683
505
|
const pools = ["ios", "android"].map((platform) => {
|
|
684
506
|
const { max, error } = parkedMaxSetting(platform);
|
|
@@ -723,7 +545,7 @@ async function statusLines(json) {
|
|
|
723
545
|
out.push(`\n${marker}${idle} ${chalk.dim(`(${path})`)}`);
|
|
724
546
|
out.push(labelOnlyRoots[i] ? chalk.dim(" worktree root (holds the label; the app registers its own entry)") : chalk.dim(` app: ${proj.bundleId ?? "?"} (${proj.isExpo ? "expo" : "bare"})`));
|
|
725
547
|
if (state.metro) {
|
|
726
|
-
const label = state.metro.running ? chalk.green(`running (pid ${state.metro.pid})`) : chalk.dim("not running");
|
|
548
|
+
const label = state.metro.running ? chalk.green(`running (pid ${state.metro.pid})`) : state.metro.idleStop ? chalk.dim(`stopped (idle) after ${state.metro.idleStop.idleMinutes}m; \`stim start\`, \`ios\` or \`android\` restarts it`) : chalk.dim("not running");
|
|
727
549
|
out.push(` metro: port ${state.metro.port} ${label}`);
|
|
728
550
|
}
|
|
729
551
|
if (state.supervisor) {
|
|
@@ -749,12 +571,12 @@ async function statusLines(json) {
|
|
|
749
571
|
if (deviceState.ios) {
|
|
750
572
|
const booted = deviceState.ios.state === "Booted" ? chalk.green("booted") : chalk.dim(deviceState.ios.state.toLowerCase());
|
|
751
573
|
const owned = deviceState.ios.owned ? chalk.dim(" (owned)") : "";
|
|
752
|
-
out.push(` ios${slotLabel}: ${chalk.cyan(deviceState.ios.name ?? deviceState.ios.udid)} ${booted}${owned}`);
|
|
574
|
+
out.push(` ios${slotLabel}: ${chalk.cyan(deviceState.ios.name ?? deviceState.ios.udid)} ${booted}${owned}${activitySuffix(deviceState.ios.activity)}`);
|
|
753
575
|
}
|
|
754
576
|
if (deviceState.android) {
|
|
755
577
|
const kind = deviceState.android.physical ? chalk.dim("(physical)") : chalk.dim("(emulator)");
|
|
756
578
|
const observed = deviceState.android.state ? ` ${deviceState.android.state}${deviceState.android.serial ? ` (${deviceState.android.serial})` : ""}` : "";
|
|
757
|
-
out.push(` android${slotLabel}: ${chalk.cyan(deviceState.android.name)} ${kind}${observed}${deviceState.android.owned ? chalk.dim(" (owned)") : ""}`);
|
|
579
|
+
out.push(` android${slotLabel}: ${chalk.cyan(deviceState.android.name)} ${kind}${observed}${deviceState.android.owned ? chalk.dim(" (owned)") : ""}${activitySuffix(deviceState.android.activity)}`);
|
|
758
580
|
}
|
|
759
581
|
}
|
|
760
582
|
for (const remote of state.remoteDevices ?? []) out.push(` ${remoteDeviceLine(remote)}`);
|
|
@@ -823,8 +645,18 @@ async function watchStatus(json) {
|
|
|
823
645
|
scheduler.trigger(0);
|
|
824
646
|
await new Promise(() => {});
|
|
825
647
|
}
|
|
648
|
+
function activitySuffix(activity) {
|
|
649
|
+
const label = activityLabel(activity, Date.now());
|
|
650
|
+
return label ? ` -- ${activity?.state === "driven" ? chalk.magenta(label) : chalk.dim(label)}` : "";
|
|
651
|
+
}
|
|
652
|
+
function linkedWorktrees(paths) {
|
|
653
|
+
return [...new Set(paths.flatMap((path) => gitCommonDirOnDisk(path) ?? []))].flatMap((common) => {
|
|
654
|
+
const repository = basename(common) === ".git" ? dirname(common) : common;
|
|
655
|
+
return linkedWorktreesOnDisk(common).map((entry) => Object.assign(entry, { repository }));
|
|
656
|
+
});
|
|
657
|
+
}
|
|
826
658
|
function workspaceBuild(path, history) {
|
|
827
|
-
const record = parseActiveBuild(readWorkspaceState(path)?.[ACTIVE_BUILD_KEY]);
|
|
659
|
+
const record = parseActiveBuild(readWorkspaceState$1(path)?.[ACTIVE_BUILD_KEY]);
|
|
828
660
|
if (!record) return null;
|
|
829
661
|
const projectKey = statsProjectKey({
|
|
830
662
|
root: path,
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { H as projectDeviceSlots } from "./config-BEq0Qw_a.mjs";
|
|
2
|
+
import { a as formatElapsed, o as formatLongDuration, r as clockTime, u as plural } from "./command-output-D5z2_bcF.mjs";
|
|
3
|
+
import { sep } from "path";
|
|
4
|
+
//#region src/status.ts
|
|
5
|
+
const IOS_SIM_MB = 1500;
|
|
6
|
+
const ANDROID_EMULATOR_MB = 2500;
|
|
7
|
+
const METRO_MB = 700;
|
|
8
|
+
function remoteDeviceState(record, ledger, root) {
|
|
9
|
+
if (!record) return null;
|
|
10
|
+
const claim = ledger.claims.get(record.sessionId);
|
|
11
|
+
return {
|
|
12
|
+
platform: record.platform,
|
|
13
|
+
backend: "eas",
|
|
14
|
+
sessionId: record.sessionId,
|
|
15
|
+
state: !ledger.safe ? "unknown" : claim?.workspaceRoot === root ? "claimed" : "unclaimed",
|
|
16
|
+
startedAt: record.startedAt,
|
|
17
|
+
webPreviewUrl: record.webPreviewUrl
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function poolLine({ platform, parked, max }) {
|
|
21
|
+
if (parked <= 0) return null;
|
|
22
|
+
const what = plural(parked, `parked ${platform === "ios" ? "iOS simulator" : "Android emulator"}`);
|
|
23
|
+
return max > 0 ? `pool: ${what} (max ${max})` : `pool: ${what} (parking off; gc --delete removes them)`;
|
|
24
|
+
}
|
|
25
|
+
function environmentState(project, { simsByUdid = {}, metro = null, worktrees = [], simsAvailable = true, androidRuntime = null, androidRuntimes = {}, supervisor = null, logs = null, remote = null, idleStop = null } = {}) {
|
|
26
|
+
const ios = project.platforms?.ios;
|
|
27
|
+
const android = project.platforms?.android;
|
|
28
|
+
const sim = ios ? simsByUdid[ios.deviceUdid] : null;
|
|
29
|
+
const simBooted = Boolean(sim && sim.state === "Booted");
|
|
30
|
+
const metroRunning = Boolean(metro?.metro);
|
|
31
|
+
const androidDetected = androidRuntime ? Boolean(androidRuntime.serial) : Boolean(android?.serial);
|
|
32
|
+
let live = simBooted || metroRunning || androidDetected || Boolean(remote);
|
|
33
|
+
let memoryMb = 0;
|
|
34
|
+
if (simBooted) memoryMb += IOS_SIM_MB;
|
|
35
|
+
if (androidDetected) memoryMb += ANDROID_EMULATOR_MB;
|
|
36
|
+
if (metroRunning) memoryMb += METRO_MB;
|
|
37
|
+
const warnings = [];
|
|
38
|
+
if (metro?.notOurs) warnings.push(`port ${project.metroPort}: ${metro.notOurs}`);
|
|
39
|
+
if (ios && !sim && simsAvailable) warnings.push(`recorded sim ${ios.deviceUdid} no longer exists`);
|
|
40
|
+
if (simBooted && project.metroPort && !metroRunning) warnings.push("simulator is booted with no Metro serving it");
|
|
41
|
+
if (androidRuntime && android?.avdName) {
|
|
42
|
+
const recordedSerial = android.consolePort ? `emulator-${android.consolePort}` : android.serial;
|
|
43
|
+
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}`);
|
|
44
|
+
if (androidRuntime.state === "missing") warnings.push(`recorded AVD ${android.avdName} no longer exists`);
|
|
45
|
+
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`);
|
|
46
|
+
if (androidRuntime.error) warnings.push(`could not check owned AVD ${android.avdName}: ${androidRuntime.error}`);
|
|
47
|
+
}
|
|
48
|
+
if (supervisor && supervisor.alive === false) warnings.push(`stale supervisor record for ${project.__path}`);
|
|
49
|
+
const slots = [];
|
|
50
|
+
for (const { slot, platforms } of projectDeviceSlots(project).slice(1)) {
|
|
51
|
+
const deviceState = environmentState({
|
|
52
|
+
...project,
|
|
53
|
+
platforms,
|
|
54
|
+
deviceSlots: void 0
|
|
55
|
+
}, {
|
|
56
|
+
simsByUdid,
|
|
57
|
+
simsAvailable,
|
|
58
|
+
metro,
|
|
59
|
+
androidRuntime: androidRuntimes[slot]
|
|
60
|
+
});
|
|
61
|
+
slots.push({
|
|
62
|
+
slot,
|
|
63
|
+
ios: deviceState.ios,
|
|
64
|
+
android: deviceState.android
|
|
65
|
+
});
|
|
66
|
+
memoryMb += deviceState.memoryMb - (metroRunning ? METRO_MB : 0);
|
|
67
|
+
live ||= deviceState.live;
|
|
68
|
+
warnings.push(...deviceState.warnings.map((warning) => `${slot}: ${warning}`));
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
path: project.__path,
|
|
72
|
+
...slots.length ? { slots } : {},
|
|
73
|
+
live,
|
|
74
|
+
memoryMb,
|
|
75
|
+
warnings,
|
|
76
|
+
ios: ios ? {
|
|
77
|
+
name: sim?.name ?? null,
|
|
78
|
+
udid: ios.deviceUdid,
|
|
79
|
+
owned: Boolean(ios.owned),
|
|
80
|
+
state: sim?.state ?? (simsAvailable ? "missing" : "unknown")
|
|
81
|
+
} : null,
|
|
82
|
+
android: android ? {
|
|
83
|
+
name: android.avdName ?? android.serial,
|
|
84
|
+
owned: Boolean(android.owned),
|
|
85
|
+
physical: Boolean(android.serial && !android.avdName),
|
|
86
|
+
...androidRuntime ? {
|
|
87
|
+
serial: androidRuntime.serial,
|
|
88
|
+
state: androidRuntime.state
|
|
89
|
+
} : {}
|
|
90
|
+
} : null,
|
|
91
|
+
metro: project.metroPort ? {
|
|
92
|
+
port: project.metroPort,
|
|
93
|
+
running: metroRunning,
|
|
94
|
+
pid: metro?.metro?.pid ?? null,
|
|
95
|
+
...idleStop && !metroRunning ? { idleStop } : {}
|
|
96
|
+
} : null,
|
|
97
|
+
supervisor: supervisor ? {
|
|
98
|
+
pid: supervisor.pid ?? null,
|
|
99
|
+
mode: supervisor.mode ?? null,
|
|
100
|
+
startedAt: supervisor.startedAt ?? null,
|
|
101
|
+
healthy: Boolean(supervisor.healthy)
|
|
102
|
+
} : null,
|
|
103
|
+
logs: logs ? {
|
|
104
|
+
dir: logs.dir,
|
|
105
|
+
errorsSinceMarker: logs.errorsSinceMarker ?? 0
|
|
106
|
+
} : null,
|
|
107
|
+
worktree: worktrees.find((w) => w.path === project.__path) ?? null,
|
|
108
|
+
remoteDevices: remote ? [remote] : []
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function activityLabel(activity, now) {
|
|
112
|
+
if (!activity) return null;
|
|
113
|
+
if (activity.state === "driven") {
|
|
114
|
+
const since = Date.parse(activity.driver?.since ?? "");
|
|
115
|
+
const duration = Number.isFinite(since) ? ` for ${formatLongDuration(Math.max(0, now - since))}` : "";
|
|
116
|
+
return `driven by ${activity.driver?.tool ?? "an unknown tool"}${duration}`;
|
|
117
|
+
}
|
|
118
|
+
if (activity.state === "unknown") return `activity unknown (${activity.basis.join(", ")})`;
|
|
119
|
+
if (activity.state === "active") return "active";
|
|
120
|
+
const last = Date.parse(activity.lastActivityAt ?? "");
|
|
121
|
+
return Number.isFinite(last) ? `idle ${formatLongDuration(Math.max(0, now - last))}` : "idle (no recorded activity)";
|
|
122
|
+
}
|
|
123
|
+
function remoteDeviceLine(remote) {
|
|
124
|
+
const claim = remote.state === "claimed" ? "" : ` (${remote.state})`;
|
|
125
|
+
const watch = remote.webPreviewUrl ? ` -- watch: ${remote.webPreviewUrl}` : "";
|
|
126
|
+
return `remote ${remote.platform ?? "?"}: EAS session ${remote.sessionId} billable${claim}${watch}`;
|
|
127
|
+
}
|
|
128
|
+
function capacity(states, totalMemoryMb) {
|
|
129
|
+
const committedMb = states.reduce((n, s) => n + s.memoryMb, 0);
|
|
130
|
+
return {
|
|
131
|
+
liveCount: states.filter((s) => s.live).length,
|
|
132
|
+
committedMb,
|
|
133
|
+
totalMemoryMb,
|
|
134
|
+
overCapacity: Boolean(totalMemoryMb && committedMb > totalMemoryMb * .6)
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function parseDfFree(output) {
|
|
138
|
+
const lines = String(output || "").trim().split("\n");
|
|
139
|
+
if (lines.length < 2) return null;
|
|
140
|
+
const lastLine = lines[lines.length - 1];
|
|
141
|
+
if (lastLine === void 0) return null;
|
|
142
|
+
const m = /\s(\d+)\s+(\d+)\s+(\d+)\s+(\d+)%/.exec(lastLine);
|
|
143
|
+
if (!m) return null;
|
|
144
|
+
const totalKb = Number(m[1]);
|
|
145
|
+
const availableKb = Number(m[3]);
|
|
146
|
+
if (!Number.isFinite(totalKb) || !Number.isFinite(availableKb) || totalKb <= 0) return null;
|
|
147
|
+
return {
|
|
148
|
+
availableMb: Math.round(availableKb / 1024),
|
|
149
|
+
totalMb: Math.round(totalKb / 1024)
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function diskIsTight(disk) {
|
|
153
|
+
return Boolean(disk && disk.availableMb < 25600);
|
|
154
|
+
}
|
|
155
|
+
function formatSpace(mb) {
|
|
156
|
+
if (!Number.isFinite(mb)) return "?";
|
|
157
|
+
if (mb >= 1048576) return `${(mb / 1048576).toFixed(1)} TB`;
|
|
158
|
+
if (mb >= 1024) return `${Math.round(mb / 1024)} GB`;
|
|
159
|
+
return `${Math.round(mb)} MB`;
|
|
160
|
+
}
|
|
161
|
+
function diskLine(volumes) {
|
|
162
|
+
const usable = (volumes || []).filter((v) => Boolean(v && v.disk));
|
|
163
|
+
if (usable.length === 0) return null;
|
|
164
|
+
if (usable.length === 1) {
|
|
165
|
+
const first = usable[0];
|
|
166
|
+
if (!first) return null;
|
|
167
|
+
const { disk } = first;
|
|
168
|
+
return `${formatSpace(disk.availableMb)} free of ${formatSpace(disk.totalMb)} on disk.`;
|
|
169
|
+
}
|
|
170
|
+
return `${usable.map((v) => `${formatSpace(v.disk.availableMb)} free on ${v.volume}`).join(", ")}.`;
|
|
171
|
+
}
|
|
172
|
+
function tightVolumes(volumes) {
|
|
173
|
+
return (volumes || []).filter((v) => v && diskIsTight(v.disk));
|
|
174
|
+
}
|
|
175
|
+
function unprovisionedWorktrees(worktrees, projectPaths) {
|
|
176
|
+
return worktrees.filter((w) => {
|
|
177
|
+
const inside = w.path.endsWith(sep) ? w.path : w.path + sep;
|
|
178
|
+
return !projectPaths.some((p) => p === w.path || p.startsWith(inside));
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
function deviceLeaseStates(entries, { root, now }) {
|
|
182
|
+
return entries.map((entry) => {
|
|
183
|
+
const lease = entry.lease;
|
|
184
|
+
return {
|
|
185
|
+
path: entry.path,
|
|
186
|
+
platform: entry.platform,
|
|
187
|
+
...lease?.slot ? { slot: lease.slot } : {},
|
|
188
|
+
id: entry.id,
|
|
189
|
+
deviceName: lease?.deviceName ?? null,
|
|
190
|
+
holder: lease?.holder ?? null,
|
|
191
|
+
grantedAt: lease?.grantedAt ?? null,
|
|
192
|
+
expiresAt: lease?.expiresAt ?? null,
|
|
193
|
+
mine: Boolean(lease && root && lease.holder === root),
|
|
194
|
+
expired: Boolean(lease && Date.parse(lease.expiresAt) <= now),
|
|
195
|
+
parsed: Boolean(lease)
|
|
196
|
+
};
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
function deviceLeaseLines(states, now) {
|
|
200
|
+
if (states.length === 0) return [];
|
|
201
|
+
const lines = [`Device leases (${states.length}):`];
|
|
202
|
+
for (const state of states) {
|
|
203
|
+
const device = `${state.platform}${state.slot ? ` [${state.slot}]` : ""} ${state.id ?? state.path}${state.deviceName ? ` (${state.deviceName})` : ""}`;
|
|
204
|
+
if (!state.parsed || state.expiresAt === null) {
|
|
205
|
+
lines.push(` ${device} -- unreadable lease file, so nothing may take the device: ${state.path}`);
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
const when = clockTime(state.expiresAt);
|
|
209
|
+
const remaining = Date.parse(state.expiresAt) - now;
|
|
210
|
+
const expiry = state.expired ? `expired at ${when}` : `until ${when} (${formatElapsed(remaining)} left)`;
|
|
211
|
+
lines.push(` ${device} -- ${state.holder} ${expiry}${state.mine ? " [this workspace]" : ""}`);
|
|
212
|
+
}
|
|
213
|
+
return lines;
|
|
214
|
+
}
|
|
215
|
+
//#endregion
|
|
216
|
+
export { diskLine as a, parseDfFree as c, remoteDeviceState as d, tightVolumes as f, deviceLeaseStates as i, poolLine as l, capacity as n, environmentState as o, unprovisionedWorktrees as p, deviceLeaseLines as r, formatSpace as s, activityLabel as t, remoteDeviceLine as u };
|